diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 000000000..e69de29bb diff --git a/404.html b/404.html new file mode 100644 index 000000000..f2d94a5ba --- /dev/null +++ b/404.html @@ -0,0 +1,14 @@ + + + + + +Page Not Found | GmapVue Docs + + + + + +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

+ + \ No newline at end of file diff --git a/assets/css/styles.5d8c82f1.css b/assets/css/styles.5d8c82f1.css new file mode 100644 index 000000000..105aac827 --- /dev/null +++ b/assets/css/styles.5d8c82f1.css @@ -0,0 +1 @@ +.col,.container{padding:0 var(--ifm-spacing-horizontal);width:100%}.markdown>h2,.markdown>h3,.markdown>h4,.markdown>h5,.markdown>h6{margin-bottom:calc(var(--ifm-heading-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown li,body{word-wrap:break-word}body,ol ol,ol ul,ul ol,ul ul{margin:0}pre,table{overflow:auto}blockquote,pre{margin:0 0 var(--ifm-spacing-vertical)}.breadcrumbs__link,.button{transition-timing-function:var(--ifm-transition-timing-default)}.button,code{vertical-align:middle}.button--outline.button--active,.button--outline:active,.button--outline:hover,:root{--ifm-button-color:var(--ifm-font-color-base-inverse)}.menu__link:hover,a{transition:color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.navbar--dark,:root{--ifm-navbar-link-hover-color:var(--ifm-color-primary)}.menu,.navbar-sidebar{overflow-x:hidden}:root,html[data-theme=dark]{--ifm-color-emphasis-500:var(--ifm-color-gray-500)}.toggleButton_hN0O,html{-webkit-tap-highlight-color:transparent}.authorSocials_Ne1J,.authorTitle_ZCyR{-webkit-box-orient:vertical;overflow:hidden}.clean-list,.containsTaskList_rtSP,.details_clFM>summary,.dropdown__menu,.menu__list{list-style:none}:root{--ifm-color-scheme:light;--ifm-dark-value:10%;--ifm-darker-value:15%;--ifm-darkest-value:30%;--ifm-light-value:15%;--ifm-lighter-value:30%;--ifm-lightest-value:50%;--ifm-contrast-background-value:90%;--ifm-contrast-foreground-value:70%;--ifm-contrast-background-dark-value:70%;--ifm-contrast-foreground-dark-value:90%;--ifm-color-primary:#3578e5;--ifm-color-secondary:#ebedf0;--ifm-color-success:#00a400;--ifm-color-info:#54c7ec;--ifm-color-warning:#ffba00;--ifm-color-danger:#fa383e;--ifm-color-primary-dark:#306cce;--ifm-color-primary-darker:#2d66c3;--ifm-color-primary-darkest:#2554a0;--ifm-color-primary-light:#538ce9;--ifm-color-primary-lighter:#72a1ed;--ifm-color-primary-lightest:#9abcf2;--ifm-color-primary-contrast-background:#ebf2fc;--ifm-color-primary-contrast-foreground:#102445;--ifm-color-secondary-dark:#d4d5d8;--ifm-color-secondary-darker:#c8c9cc;--ifm-color-secondary-darkest:#a4a6a8;--ifm-color-secondary-light:#eef0f2;--ifm-color-secondary-lighter:#f1f2f5;--ifm-color-secondary-lightest:#f5f6f8;--ifm-color-secondary-contrast-background:#fdfdfe;--ifm-color-secondary-contrast-foreground:#474748;--ifm-color-success-dark:#009400;--ifm-color-success-darker:#008b00;--ifm-color-success-darkest:#007300;--ifm-color-success-light:#26b226;--ifm-color-success-lighter:#4dbf4d;--ifm-color-success-lightest:#80d280;--ifm-color-success-contrast-background:#e6f6e6;--ifm-color-success-contrast-foreground:#003100;--ifm-color-info-dark:#4cb3d4;--ifm-color-info-darker:#47a9c9;--ifm-color-info-darkest:#3b8ba5;--ifm-color-info-light:#6ecfef;--ifm-color-info-lighter:#87d8f2;--ifm-color-info-lightest:#aae3f6;--ifm-color-info-contrast-background:#eef9fd;--ifm-color-info-contrast-foreground:#193c47;--ifm-color-warning-dark:#e6a700;--ifm-color-warning-darker:#d99e00;--ifm-color-warning-darkest:#b38200;--ifm-color-warning-light:#ffc426;--ifm-color-warning-lighter:#ffcf4d;--ifm-color-warning-lightest:#ffdd80;--ifm-color-warning-contrast-background:#fff8e6;--ifm-color-warning-contrast-foreground:#4d3800;--ifm-color-danger-dark:#e13238;--ifm-color-danger-darker:#d53035;--ifm-color-danger-darkest:#af272b;--ifm-color-danger-light:#fb565b;--ifm-color-danger-lighter:#fb7478;--ifm-color-danger-lightest:#fd9c9f;--ifm-color-danger-contrast-background:#ffebec;--ifm-color-danger-contrast-foreground:#4b1113;--ifm-color-white:#fff;--ifm-color-black:#000;--ifm-color-gray-0:var(--ifm-color-white);--ifm-color-gray-100:#f5f6f7;--ifm-color-gray-200:#ebedf0;--ifm-color-gray-300:#dadde1;--ifm-color-gray-400:#ccd0d5;--ifm-color-gray-500:#bec3c9;--ifm-color-gray-600:#8d949e;--ifm-color-gray-700:#606770;--ifm-color-gray-800:#444950;--ifm-color-gray-900:#1c1e21;--ifm-color-gray-1000:var(--ifm-color-black);--ifm-color-emphasis-0:var(--ifm-color-gray-0);--ifm-color-emphasis-100:var(--ifm-color-gray-100);--ifm-color-emphasis-200:var(--ifm-color-gray-200);--ifm-color-emphasis-300:var(--ifm-color-gray-300);--ifm-color-emphasis-400:var(--ifm-color-gray-400);--ifm-color-emphasis-600:var(--ifm-color-gray-600);--ifm-color-emphasis-700:var(--ifm-color-gray-700);--ifm-color-emphasis-800:var(--ifm-color-gray-800);--ifm-color-emphasis-900:var(--ifm-color-gray-900);--ifm-color-emphasis-1000:var(--ifm-color-gray-1000);--ifm-color-content:var(--ifm-color-emphasis-900);--ifm-color-content-inverse:var(--ifm-color-emphasis-0);--ifm-color-content-secondary:#525860;--ifm-background-color:#0000;--ifm-background-surface-color:var(--ifm-color-content-inverse);--ifm-global-border-width:1px;--ifm-global-radius:0.4rem;--ifm-hover-overlay:#0000000d;--ifm-font-color-base:var(--ifm-color-content);--ifm-font-color-base-inverse:var(--ifm-color-content-inverse);--ifm-font-color-secondary:var(--ifm-color-content-secondary);--ifm-font-family-base:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--ifm-font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--ifm-font-size-base:100%;--ifm-font-weight-light:300;--ifm-font-weight-normal:400;--ifm-font-weight-semibold:500;--ifm-font-weight-bold:700;--ifm-font-weight-base:var(--ifm-font-weight-normal);--ifm-line-height-base:1.65;--ifm-global-spacing:1rem;--ifm-spacing-vertical:var(--ifm-global-spacing);--ifm-spacing-horizontal:var(--ifm-global-spacing);--ifm-transition-fast:200ms;--ifm-transition-slow:400ms;--ifm-transition-timing-default:cubic-bezier(0.08,0.52,0.52,1);--ifm-global-shadow-lw:0 1px 2px 0 #0000001a;--ifm-global-shadow-md:0 5px 40px #0003;--ifm-global-shadow-tl:0 12px 28px 0 #0003,0 2px 4px 0 #0000001a;--ifm-z-index-dropdown:100;--ifm-z-index-fixed:200;--ifm-z-index-overlay:400;--ifm-container-width:1140px;--ifm-container-width-xl:1320px;--ifm-code-background:#f6f7f8;--ifm-code-border-radius:var(--ifm-global-radius);--ifm-code-font-size:90%;--ifm-code-padding-horizontal:0.1rem;--ifm-code-padding-vertical:0.1rem;--ifm-pre-background:var(--ifm-code-background);--ifm-pre-border-radius:var(--ifm-code-border-radius);--ifm-pre-color:inherit;--ifm-pre-line-height:1.45;--ifm-pre-padding:1rem;--ifm-heading-color:inherit;--ifm-heading-margin-top:0;--ifm-heading-margin-bottom:var(--ifm-spacing-vertical);--ifm-heading-font-family:var(--ifm-font-family-base);--ifm-heading-font-weight:var(--ifm-font-weight-bold);--ifm-heading-line-height:1.25;--ifm-h1-font-size:2rem;--ifm-h2-font-size:1.5rem;--ifm-h3-font-size:1.25rem;--ifm-h4-font-size:1rem;--ifm-h5-font-size:0.875rem;--ifm-h6-font-size:0.85rem;--ifm-image-alignment-padding:1.25rem;--ifm-leading-desktop:1.25;--ifm-leading:calc(var(--ifm-leading-desktop)*1rem);--ifm-list-left-padding:2rem;--ifm-list-margin:1rem;--ifm-list-item-margin:0.25rem;--ifm-list-paragraph-margin:1rem;--ifm-table-cell-padding:0.75rem;--ifm-table-background:#0000;--ifm-table-stripe-background:#00000008;--ifm-table-border-width:1px;--ifm-table-border-color:var(--ifm-color-emphasis-300);--ifm-table-head-background:inherit;--ifm-table-head-color:inherit;--ifm-table-head-font-weight:var(--ifm-font-weight-bold);--ifm-table-cell-color:inherit;--ifm-link-color:var(--ifm-color-primary);--ifm-link-decoration:none;--ifm-link-hover-color:var(--ifm-link-color);--ifm-link-hover-decoration:underline;--ifm-paragraph-margin-bottom:var(--ifm-leading);--ifm-blockquote-font-size:var(--ifm-font-size-base);--ifm-blockquote-border-left-width:2px;--ifm-blockquote-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-blockquote-padding-vertical:0;--ifm-blockquote-shadow:none;--ifm-blockquote-color:var(--ifm-color-emphasis-800);--ifm-blockquote-border-color:var(--ifm-color-emphasis-300);--ifm-hr-background-color:var(--ifm-color-emphasis-500);--ifm-hr-height:1px;--ifm-hr-margin-vertical:1.5rem;--ifm-scrollbar-size:7px;--ifm-scrollbar-track-background-color:#f1f1f1;--ifm-scrollbar-thumb-background-color:silver;--ifm-scrollbar-thumb-hover-background-color:#a7a7a7;--ifm-alert-background-color:inherit;--ifm-alert-border-color:inherit;--ifm-alert-border-radius:var(--ifm-global-radius);--ifm-alert-border-width:0px;--ifm-alert-border-left-width:5px;--ifm-alert-color:var(--ifm-font-color-base);--ifm-alert-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-alert-padding-vertical:var(--ifm-spacing-vertical);--ifm-alert-shadow:var(--ifm-global-shadow-lw);--ifm-avatar-intro-margin:1rem;--ifm-avatar-intro-alignment:inherit;--ifm-avatar-photo-size:3rem;--ifm-badge-background-color:inherit;--ifm-badge-border-color:inherit;--ifm-badge-border-radius:var(--ifm-global-radius);--ifm-badge-border-width:var(--ifm-global-border-width);--ifm-badge-color:var(--ifm-color-white);--ifm-badge-padding-horizontal:calc(var(--ifm-spacing-horizontal)*0.5);--ifm-badge-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-breadcrumb-border-radius:1.5rem;--ifm-breadcrumb-spacing:0.5rem;--ifm-breadcrumb-color-active:var(--ifm-color-primary);--ifm-breadcrumb-item-background-active:var(--ifm-hover-overlay);--ifm-breadcrumb-padding-horizontal:0.8rem;--ifm-breadcrumb-padding-vertical:0.4rem;--ifm-breadcrumb-size-multiplier:1;--ifm-breadcrumb-separator:url('data:image/svg+xml;utf8,');--ifm-breadcrumb-separator-filter:none;--ifm-breadcrumb-separator-size:0.5rem;--ifm-breadcrumb-separator-size-multiplier:1.25;--ifm-button-background-color:inherit;--ifm-button-border-color:var(--ifm-button-background-color);--ifm-button-border-width:var(--ifm-global-border-width);--ifm-button-font-weight:var(--ifm-font-weight-bold);--ifm-button-padding-horizontal:1.5rem;--ifm-button-padding-vertical:0.375rem;--ifm-button-size-multiplier:1;--ifm-button-transition-duration:var(--ifm-transition-fast);--ifm-button-border-radius:calc(var(--ifm-global-radius)*var(--ifm-button-size-multiplier));--ifm-button-group-spacing:2px;--ifm-card-background-color:var(--ifm-background-surface-color);--ifm-card-border-radius:calc(var(--ifm-global-radius)*2);--ifm-card-horizontal-spacing:var(--ifm-global-spacing);--ifm-card-vertical-spacing:var(--ifm-global-spacing);--ifm-toc-border-color:var(--ifm-color-emphasis-300);--ifm-toc-link-color:var(--ifm-color-content-secondary);--ifm-toc-padding-vertical:0.5rem;--ifm-toc-padding-horizontal:0.5rem;--ifm-dropdown-background-color:var(--ifm-background-surface-color);--ifm-dropdown-font-weight:var(--ifm-font-weight-semibold);--ifm-dropdown-link-color:var(--ifm-font-color-base);--ifm-dropdown-hover-background-color:var(--ifm-hover-overlay);--ifm-footer-background-color:var(--ifm-color-emphasis-100);--ifm-footer-color:inherit;--ifm-footer-link-color:var(--ifm-color-emphasis-700);--ifm-footer-link-hover-color:var(--ifm-color-primary);--ifm-footer-link-horizontal-spacing:0.5rem;--ifm-footer-padding-horizontal:calc(var(--ifm-spacing-horizontal)*2);--ifm-footer-padding-vertical:calc(var(--ifm-spacing-vertical)*2);--ifm-footer-title-color:inherit;--ifm-footer-logo-max-width:min(30rem,90vw);--ifm-hero-background-color:var(--ifm-background-surface-color);--ifm-hero-text-color:var(--ifm-color-emphasis-800);--ifm-menu-color:var(--ifm-color-emphasis-700);--ifm-menu-color-active:var(--ifm-color-primary);--ifm-menu-color-background-active:var(--ifm-hover-overlay);--ifm-menu-color-background-hover:var(--ifm-hover-overlay);--ifm-menu-link-padding-horizontal:0.75rem;--ifm-menu-link-padding-vertical:0.375rem;--ifm-menu-link-sublist-icon:url('data:image/svg+xml;utf8,');--ifm-menu-link-sublist-icon-filter:none;--ifm-navbar-background-color:var(--ifm-background-surface-color);--ifm-navbar-height:3.75rem;--ifm-navbar-item-padding-horizontal:0.75rem;--ifm-navbar-item-padding-vertical:0.25rem;--ifm-navbar-link-color:var(--ifm-font-color-base);--ifm-navbar-link-active-color:var(--ifm-link-color);--ifm-navbar-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-navbar-padding-vertical:calc(var(--ifm-spacing-vertical)*0.5);--ifm-navbar-shadow:var(--ifm-global-shadow-lw);--ifm-navbar-search-input-background-color:var(--ifm-color-emphasis-200);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-800);--ifm-navbar-search-input-placeholder-color:var(--ifm-color-emphasis-500);--ifm-navbar-search-input-icon:url('data:image/svg+xml;utf8,');--ifm-navbar-sidebar-width:83vw;--ifm-pagination-border-radius:var(--ifm-global-radius);--ifm-pagination-color-active:var(--ifm-color-primary);--ifm-pagination-font-size:1rem;--ifm-pagination-item-active-background:var(--ifm-hover-overlay);--ifm-pagination-page-spacing:0.2em;--ifm-pagination-padding-horizontal:calc(var(--ifm-spacing-horizontal)*1);--ifm-pagination-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-pagination-nav-border-radius:var(--ifm-global-radius);--ifm-pagination-nav-color-hover:var(--ifm-color-primary);--ifm-pills-color-active:var(--ifm-color-primary);--ifm-pills-color-background-active:var(--ifm-hover-overlay);--ifm-pills-spacing:0.125rem;--ifm-tabs-color:var(--ifm-font-color-secondary);--ifm-tabs-color-active:var(--ifm-color-primary);--ifm-tabs-color-active-border:var(--ifm-tabs-color-active);--ifm-tabs-padding-horizontal:1rem;--ifm-tabs-padding-vertical:1rem;--docusaurus-progress-bar-color:var(--ifm-color-primary);--ifm-color-primary:#2e8555;--ifm-color-primary-dark:#29784c;--ifm-color-primary-darker:#277148;--ifm-color-primary-darkest:#205d3b;--ifm-color-primary-light:#33925d;--ifm-color-primary-lighter:#359962;--ifm-color-primary-lightest:#3cad6e;--ifm-code-font-size:95%;--docusaurus-highlighted-code-line-bg:#0000001a;--docusaurus-announcement-bar-height:auto;--docusaurus-collapse-button-bg:#0000;--docusaurus-collapse-button-bg-hover:#0000001a;--doc-sidebar-width:300px;--doc-sidebar-hidden-width:30px;--docusaurus-blog-social-icon-size:1rem;--docusaurus-tag-list-border:var(--ifm-color-emphasis-300)}.badge--danger,.badge--info,.badge--primary,.badge--secondary,.badge--success,.badge--warning{--ifm-badge-border-color:var(--ifm-badge-background-color)}.button--link,.button--outline{--ifm-button-background-color:#0000}*{box-sizing:border-box}html{background-color:var(--ifm-background-color);color:var(--ifm-font-color-base);color-scheme:var(--ifm-color-scheme);font:var(--ifm-font-size-base)/var(--ifm-line-height-base) var(--ifm-font-family-base);-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility;-webkit-text-size-adjust:100%;text-size-adjust:100%}iframe{border:0;color-scheme:auto}.container{margin:0 auto;max-width:var(--ifm-container-width)}.container--fluid{max-width:inherit}.row{display:flex;flex-wrap:wrap;margin:0 calc(var(--ifm-spacing-horizontal)*-1)}.list_ybXY article:last-child,.margin-bottom--none,.margin-vert--none,.markdown>:last-child{margin-bottom:0!important}.margin-top--none,.margin-vert--none,.tabItem_NxBH{margin-top:0!important}.row--no-gutters{margin-left:0;margin-right:0}.margin-horiz--none,.margin-right--none{margin-right:0!important}.row--no-gutters>.col{padding-left:0;padding-right:0}.row--align-top{align-items:flex-start}.row--align-bottom{align-items:flex-end}.menuExternalLink_TZOs,.row--align-center{align-items:center}.row--align-stretch{align-items:stretch}.row--align-baseline{align-items:baseline}.col{--ifm-col-width:100%;flex:1 0;margin-left:0;max-width:var(--ifm-col-width)}.padding-bottom--none,.padding-vert--none{padding-bottom:0!important}.padding-top--none,.padding-vert--none{padding-top:0!important}.padding-horiz--none,.padding-left--none{padding-left:0!important}.padding-horiz--none,.padding-right--none{padding-right:0!important}.col[class*=col--]{flex:0 0 var(--ifm-col-width)}.col--1{--ifm-col-width:8.33333%}.col--offset-1{margin-left:8.33333%}.col--2{--ifm-col-width:16.66667%}.col--offset-2{margin-left:16.66667%}.col--3{--ifm-col-width:25%}.col--offset-3{margin-left:25%}.col--4{--ifm-col-width:33.33333%}.col--offset-4{margin-left:33.33333%}.col--5{--ifm-col-width:41.66667%}.col--offset-5{margin-left:41.66667%}.col--6{--ifm-col-width:50%}.col--offset-6{margin-left:50%}.col--7{--ifm-col-width:58.33333%}.col--offset-7{margin-left:58.33333%}.col--8{--ifm-col-width:66.66667%}.col--offset-8{margin-left:66.66667%}.col--9{--ifm-col-width:75%}.col--offset-9{margin-left:75%}.col--10{--ifm-col-width:83.33333%}.col--offset-10{margin-left:83.33333%}.col--11{--ifm-col-width:91.66667%}.col--offset-11{margin-left:91.66667%}.col--12{--ifm-col-width:100%}.col--offset-12{margin-left:100%}.margin-horiz--none,.margin-left--none{margin-left:0!important}.margin--none{margin:0!important}.margin-bottom--xs,.margin-vert--xs{margin-bottom:.25rem!important}.margin-top--xs,.margin-vert--xs{margin-top:.25rem!important}.margin-horiz--xs,.margin-left--xs{margin-left:.25rem!important}.margin-horiz--xs,.margin-right--xs{margin-right:.25rem!important}.margin--xs{margin:.25rem!important}.margin-bottom--sm,.margin-vert--sm{margin-bottom:.5rem!important}.margin-top--sm,.margin-vert--sm{margin-top:.5rem!important}.margin-horiz--sm,.margin-left--sm{margin-left:.5rem!important}.margin-horiz--sm,.margin-right--sm{margin-right:.5rem!important}.margin--sm{margin:.5rem!important}.margin-bottom--md,.margin-vert--md{margin-bottom:1rem!important}.margin-top--md,.margin-vert--md{margin-top:1rem!important}.margin-horiz--md,.margin-left--md{margin-left:1rem!important}.margin-horiz--md,.margin-right--md{margin-right:1rem!important}.margin--md{margin:1rem!important}.margin-bottom--lg,.margin-vert--lg{margin-bottom:2rem!important}.margin-top--lg,.margin-vert--lg{margin-top:2rem!important}.margin-horiz--lg,.margin-left--lg{margin-left:2rem!important}.margin-horiz--lg,.margin-right--lg{margin-right:2rem!important}.margin--lg{margin:2rem!important}.margin-bottom--xl,.margin-vert--xl{margin-bottom:5rem!important}.margin-top--xl,.margin-vert--xl{margin-top:5rem!important}.margin-horiz--xl,.margin-left--xl{margin-left:5rem!important}.margin-horiz--xl,.margin-right--xl{margin-right:5rem!important}.margin--xl{margin:5rem!important}.padding--none{padding:0!important}.padding-bottom--xs,.padding-vert--xs{padding-bottom:.25rem!important}.padding-top--xs,.padding-vert--xs{padding-top:.25rem!important}.padding-horiz--xs,.padding-left--xs{padding-left:.25rem!important}.padding-horiz--xs,.padding-right--xs{padding-right:.25rem!important}.padding--xs{padding:.25rem!important}.padding-bottom--sm,.padding-vert--sm{padding-bottom:.5rem!important}.padding-top--sm,.padding-vert--sm{padding-top:.5rem!important}.padding-horiz--sm,.padding-left--sm{padding-left:.5rem!important}.padding-horiz--sm,.padding-right--sm{padding-right:.5rem!important}.padding--sm{padding:.5rem!important}.padding-bottom--md,.padding-vert--md{padding-bottom:1rem!important}.padding-top--md,.padding-vert--md{padding-top:1rem!important}.padding-horiz--md,.padding-left--md{padding-left:1rem!important}.padding-horiz--md,.padding-right--md{padding-right:1rem!important}.padding--md{padding:1rem!important}.padding-bottom--lg,.padding-vert--lg{padding-bottom:2rem!important}.padding-top--lg,.padding-vert--lg{padding-top:2rem!important}.padding-horiz--lg,.padding-left--lg{padding-left:2rem!important}.padding-horiz--lg,.padding-right--lg{padding-right:2rem!important}.padding--lg{padding:2rem!important}.padding-bottom--xl,.padding-vert--xl{padding-bottom:5rem!important}.padding-top--xl,.padding-vert--xl{padding-top:5rem!important}.padding-horiz--xl,.padding-left--xl{padding-left:5rem!important}.padding-horiz--xl,.padding-right--xl{padding-right:5rem!important}.padding--xl{padding:5rem!important}code{background-color:var(--ifm-code-background);border:.1rem solid #0000001a;border-radius:var(--ifm-code-border-radius);font-family:var(--ifm-font-family-monospace);font-size:var(--ifm-code-font-size);padding:var(--ifm-code-padding-vertical) var(--ifm-code-padding-horizontal)}a code{color:inherit}pre{background-color:var(--ifm-pre-background);border-radius:var(--ifm-pre-border-radius);color:var(--ifm-pre-color);font:var(--ifm-code-font-size)/var(--ifm-pre-line-height) var(--ifm-font-family-monospace);padding:var(--ifm-pre-padding)}pre code{background-color:initial;border:none;font-size:100%;line-height:inherit;padding:0}kbd{background-color:var(--ifm-color-emphasis-0);border:1px solid var(--ifm-color-emphasis-400);border-radius:.2rem;box-shadow:inset 0 -1px 0 var(--ifm-color-emphasis-400);color:var(--ifm-color-emphasis-800);font:80% var(--ifm-font-family-monospace);padding:.15rem .3rem}h1,h2,h3,h4,h5,h6{color:var(--ifm-heading-color);font-family:var(--ifm-heading-font-family);font-weight:var(--ifm-heading-font-weight);line-height:var(--ifm-heading-line-height);margin:var(--ifm-heading-margin-top) 0 var(--ifm-heading-margin-bottom) 0}h1{font-size:var(--ifm-h1-font-size)}h2{font-size:var(--ifm-h2-font-size)}h3{font-size:var(--ifm-h3-font-size)}h4{font-size:var(--ifm-h4-font-size)}h5{font-size:var(--ifm-h5-font-size)}h6{font-size:var(--ifm-h6-font-size)}img{max-width:100%}img[align=right]{padding-left:var(--image-alignment-padding)}img[align=left]{padding-right:var(--image-alignment-padding)}.markdown{--ifm-h1-vertical-rhythm-top:3;--ifm-h2-vertical-rhythm-top:2;--ifm-h3-vertical-rhythm-top:1.5;--ifm-heading-vertical-rhythm-top:1.25;--ifm-h1-vertical-rhythm-bottom:1.25;--ifm-heading-vertical-rhythm-bottom:1}.markdown:after,.markdown:before{content:"";display:table}.markdown:after{clear:both}.markdown h1:first-child{--ifm-h1-font-size:3rem;margin-bottom:calc(var(--ifm-h1-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown>h2{--ifm-h2-font-size:2rem;margin-top:calc(var(--ifm-h2-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h3{--ifm-h3-font-size:1.5rem;margin-top:calc(var(--ifm-h3-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h4,.markdown>h5,.markdown>h6{margin-top:calc(var(--ifm-heading-vertical-rhythm-top)*var(--ifm-leading))}.markdown>p,.markdown>pre,.markdown>ul,.tabList_vBCw{margin-bottom:var(--ifm-leading)}.markdown li>p{margin-top:var(--ifm-list-paragraph-margin)}.markdown li+li{margin-top:var(--ifm-list-item-margin)}ol,ul{margin:0 0 var(--ifm-list-margin);padding-left:var(--ifm-list-left-padding)}ol ol,ul ol{list-style-type:lower-roman}ol ol ol,ol ul ol,ul ol ol,ul ul ol{list-style-type:lower-alpha}table{border-collapse:collapse;display:block;margin-bottom:var(--ifm-spacing-vertical)}table thead tr{border-bottom:2px solid var(--ifm-table-border-color)}table thead,table tr:nth-child(2n){background-color:var(--ifm-table-stripe-background)}table tr{background-color:var(--ifm-table-background);border-top:var(--ifm-table-border-width) solid var(--ifm-table-border-color)}table td,table th{border:var(--ifm-table-border-width) solid var(--ifm-table-border-color);padding:var(--ifm-table-cell-padding)}table th{background-color:var(--ifm-table-head-background);color:var(--ifm-table-head-color);font-weight:var(--ifm-table-head-font-weight)}table td{color:var(--ifm-table-cell-color)}strong{font-weight:var(--ifm-font-weight-bold)}a{color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}a:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button:hover,.text--no-decoration,.text--no-decoration:hover,a:not([href]){text-decoration:none}p{margin:0 0 var(--ifm-paragraph-margin-bottom)}blockquote{border-left:var(--ifm-blockquote-border-left-width) solid var(--ifm-blockquote-border-color);box-shadow:var(--ifm-blockquote-shadow);color:var(--ifm-blockquote-color);font-size:var(--ifm-blockquote-font-size);padding:var(--ifm-blockquote-padding-vertical) var(--ifm-blockquote-padding-horizontal)}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}hr{background-color:var(--ifm-hr-background-color);border:0;height:var(--ifm-hr-height);margin:var(--ifm-hr-margin-vertical) 0}.shadow--lw{box-shadow:var(--ifm-global-shadow-lw)!important}.shadow--md{box-shadow:var(--ifm-global-shadow-md)!important}.shadow--tl{box-shadow:var(--ifm-global-shadow-tl)!important}.text--primary,.wordWrapButtonEnabled_NBsA .wordWrapButtonIcon_Zz6W{color:var(--ifm-color-primary)}.text--secondary{color:var(--ifm-color-secondary)}.text--success{color:var(--ifm-color-success)}.text--info{color:var(--ifm-color-info)}.text--warning{color:var(--ifm-color-warning)}.text--danger{color:var(--ifm-color-danger)}.text--center{text-align:center}.text--left{text-align:left}.text--justify{text-align:justify}.text--right{text-align:right}.text--capitalize{text-transform:capitalize}.text--lowercase{text-transform:lowercase}.admonitionHeading_yWJJ,.alert__heading,.text--uppercase{text-transform:uppercase}.text--light{font-weight:var(--ifm-font-weight-light)}.text--normal{font-weight:var(--ifm-font-weight-normal)}.text--semibold{font-weight:var(--ifm-font-weight-semibold)}.text--bold{font-weight:var(--ifm-font-weight-bold)}.text--italic{font-style:italic}.text--truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text--break{word-wrap:break-word!important;word-break:break-word!important}.clean-btn{background:none;border:none;color:inherit;cursor:pointer;font-family:inherit;padding:0}.alert,.alert .close{color:var(--ifm-alert-foreground-color)}.clean-list{padding-left:0}.alert--primary{--ifm-alert-background-color:var(--ifm-color-primary-contrast-background);--ifm-alert-background-color-highlight:#3578e526;--ifm-alert-foreground-color:var(--ifm-color-primary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-primary-dark)}.alert--secondary{--ifm-alert-background-color:var(--ifm-color-secondary-contrast-background);--ifm-alert-background-color-highlight:#ebedf026;--ifm-alert-foreground-color:var(--ifm-color-secondary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-secondary-dark)}.alert--success{--ifm-alert-background-color:var(--ifm-color-success-contrast-background);--ifm-alert-background-color-highlight:#00a40026;--ifm-alert-foreground-color:var(--ifm-color-success-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-success-dark)}.alert--info{--ifm-alert-background-color:var(--ifm-color-info-contrast-background);--ifm-alert-background-color-highlight:#54c7ec26;--ifm-alert-foreground-color:var(--ifm-color-info-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-info-dark)}.alert--warning{--ifm-alert-background-color:var(--ifm-color-warning-contrast-background);--ifm-alert-background-color-highlight:#ffba0026;--ifm-alert-foreground-color:var(--ifm-color-warning-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-warning-dark)}.alert--danger{--ifm-alert-background-color:var(--ifm-color-danger-contrast-background);--ifm-alert-background-color-highlight:#fa383e26;--ifm-alert-foreground-color:var(--ifm-color-danger-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-danger-dark)}.alert{--ifm-code-background:var(--ifm-alert-background-color-highlight);--ifm-link-color:var(--ifm-alert-foreground-color);--ifm-link-hover-color:var(--ifm-alert-foreground-color);--ifm-link-decoration:underline;--ifm-tabs-color:var(--ifm-alert-foreground-color);--ifm-tabs-color-active:var(--ifm-alert-foreground-color);--ifm-tabs-color-active-border:var(--ifm-alert-border-color);background-color:var(--ifm-alert-background-color);border:var(--ifm-alert-border-width) solid var(--ifm-alert-border-color);border-left-width:var(--ifm-alert-border-left-width);border-radius:var(--ifm-alert-border-radius);box-shadow:var(--ifm-alert-shadow);padding:var(--ifm-alert-padding-vertical) var(--ifm-alert-padding-horizontal)}.alert__heading{align-items:center;display:flex;font:700 var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family);margin-bottom:.5rem}.alert__icon{display:inline-flex;margin-right:.4em}.alert__icon svg{fill:var(--ifm-alert-foreground-color);stroke:var(--ifm-alert-foreground-color);stroke-width:0}.alert .close{margin:calc(var(--ifm-alert-padding-vertical)*-1) calc(var(--ifm-alert-padding-horizontal)*-1) 0 0;opacity:.75}.alert .close:focus,.alert .close:hover{opacity:1}.alert a{text-decoration-color:var(--ifm-alert-border-color)}.alert a:hover{text-decoration-thickness:2px}.avatar{column-gap:var(--ifm-avatar-intro-margin);display:flex}.avatar__photo{border-radius:50%;display:block;height:var(--ifm-avatar-photo-size);overflow:hidden;width:var(--ifm-avatar-photo-size)}.card--full-height,.navbar__logo img,body,html{height:100%}.avatar__photo--sm{--ifm-avatar-photo-size:2rem}.avatar__photo--lg{--ifm-avatar-photo-size:4rem}.avatar__photo--xl{--ifm-avatar-photo-size:6rem}.avatar__intro{display:flex;flex:1 1;flex-direction:column;justify-content:center;text-align:var(--ifm-avatar-intro-alignment)}.badge,.breadcrumbs__item,.breadcrumbs__link,.button,.dropdown>.navbar__link:after{display:inline-block}.avatar__name{font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base)}.avatar__subtitle{margin-top:.25rem}.avatar--vertical{--ifm-avatar-intro-alignment:center;--ifm-avatar-intro-margin:0.5rem;align-items:center;flex-direction:column}.badge{background-color:var(--ifm-badge-background-color);border:var(--ifm-badge-border-width) solid var(--ifm-badge-border-color);border-radius:var(--ifm-badge-border-radius);color:var(--ifm-badge-color);font-size:75%;font-weight:var(--ifm-font-weight-bold);line-height:1;padding:var(--ifm-badge-padding-vertical) var(--ifm-badge-padding-horizontal)}.badge--primary{--ifm-badge-background-color:var(--ifm-color-primary)}.badge--secondary{--ifm-badge-background-color:var(--ifm-color-secondary);color:var(--ifm-color-black)}.breadcrumbs__link,.button.button--secondary.button--outline:not(.button--active):not(:hover){color:var(--ifm-font-color-base)}.badge--success{--ifm-badge-background-color:var(--ifm-color-success)}.badge--info{--ifm-badge-background-color:var(--ifm-color-info)}.badge--warning{--ifm-badge-background-color:var(--ifm-color-warning)}.badge--danger{--ifm-badge-background-color:var(--ifm-color-danger)}.breadcrumbs{margin-bottom:0;padding-left:0}.breadcrumbs__item:not(:last-child):after{background:var(--ifm-breadcrumb-separator) center;content:" ";display:inline-block;filter:var(--ifm-breadcrumb-separator-filter);height:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier));margin:0 var(--ifm-breadcrumb-spacing);opacity:.5;width:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier))}.breadcrumbs__item--active .breadcrumbs__link{background:var(--ifm-breadcrumb-item-background-active);color:var(--ifm-breadcrumb-color-active)}.breadcrumbs__link{border-radius:var(--ifm-breadcrumb-border-radius);font-size:calc(1rem*var(--ifm-breadcrumb-size-multiplier));padding:calc(var(--ifm-breadcrumb-padding-vertical)*var(--ifm-breadcrumb-size-multiplier)) calc(var(--ifm-breadcrumb-padding-horizontal)*var(--ifm-breadcrumb-size-multiplier));transition-duration:var(--ifm-transition-fast);transition-property:background,color}.breadcrumbs__link:any-link:hover,.breadcrumbs__link:link:hover,.breadcrumbs__link:visited:hover,area[href].breadcrumbs__link:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs--sm{--ifm-breadcrumb-size-multiplier:0.8}.breadcrumbs--lg{--ifm-breadcrumb-size-multiplier:1.2}.button{background-color:var(--ifm-button-background-color);border:var(--ifm-button-border-width) solid var(--ifm-button-border-color);border-radius:var(--ifm-button-border-radius);cursor:pointer;font-size:calc(.875rem*var(--ifm-button-size-multiplier));font-weight:var(--ifm-button-font-weight);line-height:1.5;padding:calc(var(--ifm-button-padding-vertical)*var(--ifm-button-size-multiplier)) calc(var(--ifm-button-padding-horizontal)*var(--ifm-button-size-multiplier));text-align:center;transition-duration:var(--ifm-button-transition-duration);transition-property:color,background,border-color;-webkit-user-select:none;user-select:none;white-space:nowrap}.button,.button:hover{color:var(--ifm-button-color)}.button--outline{--ifm-button-color:var(--ifm-button-border-color)}.button--outline:hover{--ifm-button-background-color:var(--ifm-button-border-color)}.button--link{--ifm-button-border-color:#0000;color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}.button--link.button--active,.button--link:active,.button--link:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button.disabled,.button:disabled,.button[disabled]{opacity:.65;pointer-events:none}.button--sm{--ifm-button-size-multiplier:0.8}.button--lg{--ifm-button-size-multiplier:1.35}.button--block{display:block;width:100%}.button.button--secondary{color:var(--ifm-color-gray-900)}:where(.button--primary){--ifm-button-background-color:var(--ifm-color-primary);--ifm-button-border-color:var(--ifm-color-primary)}:where(.button--primary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-primary-dark);--ifm-button-border-color:var(--ifm-color-primary-dark)}.button--primary.button--active,.button--primary:active{--ifm-button-background-color:var(--ifm-color-primary-darker);--ifm-button-border-color:var(--ifm-color-primary-darker)}:where(.button--secondary){--ifm-button-background-color:var(--ifm-color-secondary);--ifm-button-border-color:var(--ifm-color-secondary)}:where(.button--secondary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-secondary-dark);--ifm-button-border-color:var(--ifm-color-secondary-dark)}.button--secondary.button--active,.button--secondary:active{--ifm-button-background-color:var(--ifm-color-secondary-darker);--ifm-button-border-color:var(--ifm-color-secondary-darker)}:where(.button--success){--ifm-button-background-color:var(--ifm-color-success);--ifm-button-border-color:var(--ifm-color-success)}:where(.button--success):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-success-dark);--ifm-button-border-color:var(--ifm-color-success-dark)}.button--success.button--active,.button--success:active{--ifm-button-background-color:var(--ifm-color-success-darker);--ifm-button-border-color:var(--ifm-color-success-darker)}:where(.button--info){--ifm-button-background-color:var(--ifm-color-info);--ifm-button-border-color:var(--ifm-color-info)}:where(.button--info):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-info-dark);--ifm-button-border-color:var(--ifm-color-info-dark)}.button--info.button--active,.button--info:active{--ifm-button-background-color:var(--ifm-color-info-darker);--ifm-button-border-color:var(--ifm-color-info-darker)}:where(.button--warning){--ifm-button-background-color:var(--ifm-color-warning);--ifm-button-border-color:var(--ifm-color-warning)}:where(.button--warning):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-warning-dark);--ifm-button-border-color:var(--ifm-color-warning-dark)}.button--warning.button--active,.button--warning:active{--ifm-button-background-color:var(--ifm-color-warning-darker);--ifm-button-border-color:var(--ifm-color-warning-darker)}:where(.button--danger){--ifm-button-background-color:var(--ifm-color-danger);--ifm-button-border-color:var(--ifm-color-danger)}:where(.button--danger):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-danger-dark);--ifm-button-border-color:var(--ifm-color-danger-dark)}.button--danger.button--active,.button--danger:active{--ifm-button-background-color:var(--ifm-color-danger-darker);--ifm-button-border-color:var(--ifm-color-danger-darker)}.button-group{display:inline-flex;gap:var(--ifm-button-group-spacing)}.button-group>.button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.button-group>.button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.button-group--block{display:flex;justify-content:stretch}.button-group--block>.button{flex-grow:1}.card{background-color:var(--ifm-card-background-color);border-radius:var(--ifm-card-border-radius);box-shadow:var(--ifm-global-shadow-lw);display:flex;flex-direction:column;overflow:hidden}.card__image{padding-top:var(--ifm-card-vertical-spacing)}.card__image:first-child{padding-top:0}.card__body,.card__footer,.card__header{padding:var(--ifm-card-vertical-spacing) var(--ifm-card-horizontal-spacing)}.card__body:not(:last-child),.card__footer:not(:last-child),.card__header:not(:last-child){padding-bottom:0}.card__body>:last-child,.card__footer>:last-child,.card__header>:last-child{margin-bottom:0}.card__footer{margin-top:auto}.table-of-contents{font-size:.8rem;margin-bottom:0;padding:var(--ifm-toc-padding-vertical) 0}.table-of-contents,.table-of-contents ul{list-style:none;padding-left:var(--ifm-toc-padding-horizontal)}.table-of-contents li{margin:var(--ifm-toc-padding-vertical) var(--ifm-toc-padding-horizontal)}.table-of-contents__left-border{border-left:1px solid var(--ifm-toc-border-color)}.table-of-contents__link{color:var(--ifm-toc-link-color);display:block}.table-of-contents__link--active,.table-of-contents__link--active code,.table-of-contents__link:hover,.table-of-contents__link:hover code{color:var(--ifm-color-primary);text-decoration:none}.close{color:var(--ifm-color-black);float:right;font-size:1.5rem;font-weight:var(--ifm-font-weight-bold);line-height:1;opacity:.5;padding:1rem;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.close:hover{opacity:.7}.close:focus{opacity:.8}.dropdown{display:inline-flex;font-weight:var(--ifm-dropdown-font-weight);position:relative;vertical-align:top}.dropdown--hoverable:hover .dropdown__menu,.dropdown--show .dropdown__menu{opacity:1;pointer-events:all;transform:translateY(-1px);visibility:visible}#nprogress,.dropdown__menu,.navbar__item.dropdown .navbar__link:not([href]){pointer-events:none}.dropdown--right .dropdown__menu{left:inherit;right:0}.dropdown--nocaret .navbar__link:after{content:none!important}.dropdown__menu{background-color:var(--ifm-dropdown-background-color);border-radius:var(--ifm-global-radius);box-shadow:var(--ifm-global-shadow-md);left:0;max-height:80vh;min-width:10rem;opacity:0;overflow-y:auto;padding:.5rem;position:absolute;top:calc(100% - var(--ifm-navbar-item-padding-vertical) + .3rem);transform:translateY(-.625rem);transition-duration:var(--ifm-transition-fast);transition-property:opacity,transform,visibility;transition-timing-function:var(--ifm-transition-timing-default);visibility:hidden;z-index:var(--ifm-z-index-dropdown)}.sidebar_ekj2,.tableOfContents_esvT{max-height:calc(100vh - var(--ifm-navbar-height) - 2rem)}.menu__caret,.menu__link,.menu__list-item-collapsible{border-radius:.25rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.dropdown__link{border-radius:.25rem;color:var(--ifm-dropdown-link-color);display:block;font-size:.875rem;margin-top:.2rem;padding:.25rem .5rem;white-space:nowrap}.dropdown__link--active,.dropdown__link:hover{background-color:var(--ifm-dropdown-hover-background-color);color:var(--ifm-dropdown-link-color);text-decoration:none}.dropdown__link--active,.dropdown__link--active:hover{--ifm-dropdown-link-color:var(--ifm-link-color)}.dropdown>.navbar__link:after{border-color:currentcolor #0000;border-style:solid;border-width:.4em .4em 0;content:"";margin-left:.3em;position:relative;top:2px;transform:translateY(-50%)}.footer{background-color:var(--ifm-footer-background-color);color:var(--ifm-footer-color);padding:var(--ifm-footer-padding-vertical) var(--ifm-footer-padding-horizontal)}.footer--dark{--ifm-footer-background-color:#303846;--ifm-footer-color:var(--ifm-footer-link-color);--ifm-footer-link-color:var(--ifm-color-secondary);--ifm-footer-title-color:var(--ifm-color-white)}.footer__links{margin-bottom:1rem}.footer__link-item{color:var(--ifm-footer-link-color);line-height:2}.footer__link-item:hover{color:var(--ifm-footer-link-hover-color)}.footer__link-separator{margin:0 var(--ifm-footer-link-horizontal-spacing)}.footer__logo{margin-top:1rem;max-width:var(--ifm-footer-logo-max-width)}.footer__title{color:var(--ifm-footer-title-color);font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base);margin-bottom:var(--ifm-heading-margin-bottom)}.menu,.navbar__link{font-weight:var(--ifm-font-weight-semibold)}.docItemContainer_YWsO article>:first-child,.docItemContainer_YWsO header+*,.footer__item{margin-top:0}.admonitionContent_zuJU>:last-child,.cardContainer_diBC :last-child,.collapsibleContent_ZlZ5 p:last-child,.details_clFM>summary>p:last-child,.footer__items,.tabItem_nvWs>:last-child{margin-bottom:0}.codeBlockStandalone_ZvFu,[type=checkbox]{padding:0}.hero{align-items:center;background-color:var(--ifm-hero-background-color);color:var(--ifm-hero-text-color);display:flex;padding:4rem 2rem}.hero--primary{--ifm-hero-background-color:var(--ifm-color-primary);--ifm-hero-text-color:var(--ifm-font-color-base-inverse)}.hero--dark{--ifm-hero-background-color:#303846;--ifm-hero-text-color:var(--ifm-color-white)}.hero__title,.title_Ikqq{font-size:3rem}.hero__subtitle{font-size:1.5rem}.menu__list{margin:0;padding-left:0}.menu__caret,.menu__link{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu__list .menu__list{flex:0 0 100%;margin-top:.25rem;padding-left:var(--ifm-menu-link-padding-horizontal)}.menu__list-item:not(:first-child){margin-top:.25rem}.menu__list-item--collapsed .menu__list{height:0;overflow:hidden}.details_clFM[data-collapsed=false].isBrowser_CPzx>summary:before,.details_clFM[open]:not(.isBrowser_CPzx)>summary:before,.menu__list-item--collapsed .menu__caret:before,.menu__list-item--collapsed .menu__link--sublist:after{transform:rotate(90deg)}.menu__list-item-collapsible{display:flex;flex-wrap:wrap;position:relative}.menu__caret:hover,.menu__link:hover,.menu__list-item-collapsible--active,.menu__list-item-collapsible:hover{background:var(--ifm-menu-color-background-hover)}.menu__list-item-collapsible .menu__link--active,.menu__list-item-collapsible .menu__link:hover{background:none!important}.menu__caret,.menu__link{align-items:center;display:flex}.menu__link{color:var(--ifm-menu-color);flex:1;line-height:1.25}.menu__link:hover{color:var(--ifm-menu-color);text-decoration:none}.menu__caret:before,.menu__link--sublist-caret:after{content:"";height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast) linear;width:1.25rem;filter:var(--ifm-menu-link-sublist-icon-filter)}.menu__link--sublist-caret:after{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem;margin-left:auto;min-width:1.25rem}.menu__link--active,.menu__link--active:hover{color:var(--ifm-menu-color-active)}.navbar__brand,.navbar__link{color:var(--ifm-navbar-link-color)}.menu__link--active:not(.menu__link--sublist){background-color:var(--ifm-menu-color-background-active)}.menu__caret:before{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem}.navbar--dark,html[data-theme=dark]{--ifm-menu-link-sublist-icon-filter:invert(100%) sepia(94%) saturate(17%) hue-rotate(223deg) brightness(104%) contrast(98%)}.navbar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-navbar-shadow);height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar,.navbar>.container,.navbar>.container-fluid{display:flex}.navbar--fixed-top{position:sticky;top:0;z-index:var(--ifm-z-index-fixed)}.navbar-sidebar,.navbar-sidebar__backdrop{bottom:0;opacity:0;position:fixed;transition-duration:var(--ifm-transition-fast);transition-timing-function:ease-in-out;left:0;top:0;visibility:hidden}.navbar__inner{display:flex;flex-wrap:wrap;justify-content:space-between;width:100%}.navbar__brand{align-items:center;display:flex;margin-right:1rem;min-width:0}.navbar__brand:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.announcementBarContent_csuS,.navbar__title{flex:1 1 auto}.navbar__toggle{display:none;margin-right:.5rem}.navbar__logo{flex:0 0 auto;height:2rem;margin-right:.5rem}.navbar__items{align-items:center;display:flex;flex:1;min-width:0}.navbar__items--center{flex:0 0 auto}.navbar__items--center .navbar__brand{margin:0}.navbar__items--center+.navbar__items--right{flex:1}.navbar__items--right{flex:0 0 auto;justify-content:flex-end}.navbar__items--right>:last-child{padding-right:0}.navbar__item{display:inline-block;padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.navbar__link--active,.navbar__link:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.navbar--dark,.navbar--primary{--ifm-menu-color:var(--ifm-color-gray-300);--ifm-navbar-link-color:var(--ifm-color-gray-100);--ifm-navbar-search-input-background-color:#ffffff1a;--ifm-navbar-search-input-placeholder-color:#ffffff80;color:var(--ifm-color-white)}.navbar--dark{--ifm-navbar-background-color:#242526;--ifm-menu-color-background-active:#ffffff0d;--ifm-navbar-search-input-color:var(--ifm-color-white)}.navbar--primary{--ifm-navbar-background-color:var(--ifm-color-primary);--ifm-navbar-link-hover-color:var(--ifm-color-white);--ifm-menu-color-active:var(--ifm-color-white);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-500)}.navbar__search-input{appearance:none;background:var(--ifm-navbar-search-input-background-color) var(--ifm-navbar-search-input-icon) no-repeat .75rem center/1rem 1rem;border:none;border-radius:2rem;color:var(--ifm-navbar-search-input-color);cursor:text;display:inline-block;font-size:1rem;height:2rem;padding:0 .5rem 0 2.25rem;width:12.5rem}.navbar__search-input::placeholder{color:var(--ifm-navbar-search-input-placeholder-color)}.navbar-sidebar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-global-shadow-md);transform:translate3d(-100%,0,0);transition-property:opacity,visibility,transform;width:var(--ifm-navbar-sidebar-width)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar__items{transform:translateZ(0)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar--show .navbar-sidebar__backdrop{opacity:1;visibility:visible}.navbar-sidebar__backdrop{background-color:#0009;right:0;transition-property:opacity,visibility}.navbar-sidebar__brand{align-items:center;box-shadow:var(--ifm-navbar-shadow);display:flex;flex:1;height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar-sidebar__items{display:flex;height:calc(100% - var(--ifm-navbar-height));transition:transform var(--ifm-transition-fast) ease-in-out}.navbar-sidebar__items--show-secondary{transform:translate3d(calc((var(--ifm-navbar-sidebar-width))*-1),0,0)}.navbar-sidebar__item{flex-shrink:0;padding:.5rem;width:calc(var(--ifm-navbar-sidebar-width))}.navbar-sidebar__back{background:var(--ifm-menu-color-background-active);font-size:15px;font-weight:var(--ifm-button-font-weight);margin:0 0 .2rem -.5rem;padding:.6rem 1.5rem;position:relative;text-align:left;top:-.5rem;width:calc(100% + 1rem)}.navbar-sidebar__close{display:flex;margin-left:auto}.pagination{column-gap:var(--ifm-pagination-page-spacing);display:flex;font-size:var(--ifm-pagination-font-size);padding-left:0}.pagination--sm{--ifm-pagination-font-size:0.8rem;--ifm-pagination-padding-horizontal:0.8rem;--ifm-pagination-padding-vertical:0.2rem}.pagination--lg{--ifm-pagination-font-size:1.2rem;--ifm-pagination-padding-horizontal:1.2rem;--ifm-pagination-padding-vertical:0.3rem}.pagination__item{display:inline-flex}.pagination__item>span{padding:var(--ifm-pagination-padding-vertical)}.pagination__item--active .pagination__link{color:var(--ifm-pagination-color-active)}.pagination__item--active .pagination__link,.pagination__item:not(.pagination__item--active):hover .pagination__link{background:var(--ifm-pagination-item-active-background)}.pagination__item--disabled,.pagination__item[disabled]{opacity:.25;pointer-events:none}.pagination__link{border-radius:var(--ifm-pagination-border-radius);color:var(--ifm-font-color-base);display:inline-block;padding:var(--ifm-pagination-padding-vertical) var(--ifm-pagination-padding-horizontal);transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination__link:hover,.sidebarItemLink_GXb_:hover{text-decoration:none}.pagination-nav{display:grid;grid-gap:var(--ifm-spacing-horizontal);gap:var(--ifm-spacing-horizontal);grid-template-columns:repeat(2,1fr)}.pagination-nav__link{border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-pagination-nav-border-radius);display:block;height:100%;line-height:var(--ifm-heading-line-height);padding:var(--ifm-global-spacing);transition:border-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination-nav__link:hover{border-color:var(--ifm-pagination-nav-color-hover);text-decoration:none}.pagination-nav__link--next{grid-column:2/3;text-align:right}.pagination-nav__label{font-size:var(--ifm-h4-font-size);font-weight:var(--ifm-heading-font-weight);word-break:break-word}.pagination-nav__link--prev .pagination-nav__label:before{content:"« "}.pagination-nav__link--next .pagination-nav__label:after{content:" »"}.pagination-nav__sublabel{color:var(--ifm-color-content-secondary);font-size:var(--ifm-h5-font-size);font-weight:var(--ifm-font-weight-semibold);margin-bottom:.25rem}.pills__item,.sidebarItemTitle_TsGU,.tabs{font-weight:var(--ifm-font-weight-bold)}.pills{display:flex;gap:var(--ifm-pills-spacing);padding-left:0}.pills__item{border-radius:.5rem;cursor:pointer;display:inline-block;padding:.25rem 1rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs,:not(.containsTaskList_rtSP>li)>.containsTaskList_rtSP{padding-left:0}.pills__item--active{color:var(--ifm-pills-color-active)}.pills__item--active,.pills__item:not(.pills__item--active):hover{background:var(--ifm-pills-color-background-active)}.pills--block{justify-content:stretch}.pills--block .pills__item{flex-grow:1;text-align:center}.tabs{color:var(--ifm-tabs-color);display:flex;margin-bottom:0;overflow-x:auto}.tabs__item{border-bottom:3px solid #0000;border-radius:var(--ifm-global-radius);cursor:pointer;display:inline-flex;padding:var(--ifm-tabs-padding-vertical) var(--ifm-tabs-padding-horizontal);transition:background-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs__item--active{border-bottom-color:var(--ifm-tabs-color-active-border);border-bottom-left-radius:0;border-bottom-right-radius:0;color:var(--ifm-tabs-color-active)}.tabs__item:hover{background-color:var(--ifm-hover-overlay)}.tabs--block{justify-content:stretch}.tabs--block .tabs__item{flex-grow:1;justify-content:center}html[data-theme=dark]{--ifm-color-scheme:dark;--ifm-color-emphasis-0:var(--ifm-color-gray-1000);--ifm-color-emphasis-100:var(--ifm-color-gray-900);--ifm-color-emphasis-200:var(--ifm-color-gray-800);--ifm-color-emphasis-300:var(--ifm-color-gray-700);--ifm-color-emphasis-400:var(--ifm-color-gray-600);--ifm-color-emphasis-600:var(--ifm-color-gray-400);--ifm-color-emphasis-700:var(--ifm-color-gray-300);--ifm-color-emphasis-800:var(--ifm-color-gray-200);--ifm-color-emphasis-900:var(--ifm-color-gray-100);--ifm-color-emphasis-1000:var(--ifm-color-gray-0);--ifm-background-color:#1b1b1d;--ifm-background-surface-color:#242526;--ifm-hover-overlay:#ffffff0d;--ifm-color-content:#e3e3e3;--ifm-color-content-secondary:#fff;--ifm-breadcrumb-separator-filter:invert(64%) sepia(11%) saturate(0%) hue-rotate(149deg) brightness(99%) contrast(95%);--ifm-code-background:#ffffff1a;--ifm-scrollbar-track-background-color:#444;--ifm-scrollbar-thumb-background-color:#686868;--ifm-scrollbar-thumb-hover-background-color:#7a7a7a;--ifm-table-stripe-background:#ffffff12;--ifm-toc-border-color:var(--ifm-color-emphasis-200);--ifm-color-primary-contrast-background:#102445;--ifm-color-primary-contrast-foreground:#ebf2fc;--ifm-color-secondary-contrast-background:#474748;--ifm-color-secondary-contrast-foreground:#fdfdfe;--ifm-color-success-contrast-background:#003100;--ifm-color-success-contrast-foreground:#e6f6e6;--ifm-color-info-contrast-background:#193c47;--ifm-color-info-contrast-foreground:#eef9fd;--ifm-color-warning-contrast-background:#4d3800;--ifm-color-warning-contrast-foreground:#fff8e6;--ifm-color-danger-contrast-background:#4b1113;--ifm-color-danger-contrast-foreground:#ffebec}#nprogress .bar{background:var(--docusaurus-progress-bar-color);height:2px;left:0;position:fixed;top:0;width:100%;z-index:1031}#nprogress .peg{box-shadow:0 0 10px var(--docusaurus-progress-bar-color),0 0 5px var(--docusaurus-progress-bar-color);height:100%;opacity:1;position:absolute;right:0;transform:rotate(3deg) translateY(-4px);width:100px}[data-theme=dark]{--ifm-color-primary:#25c2a0;--ifm-color-primary-dark:#21af90;--ifm-color-primary-darker:#1fa588;--ifm-color-primary-darkest:#1a8870;--ifm-color-primary-light:#29d5b0;--ifm-color-primary-lighter:#32d8b4;--ifm-color-primary-lightest:#4fddbf;--docusaurus-highlighted-code-line-bg:#0000004d}.backToTopButton_jzr7{background-color:var(--ifm-color-emphasis-200);border-radius:50%;bottom:1.3rem;box-shadow:var(--ifm-global-shadow-lw);height:3rem;opacity:0;position:fixed;right:1.3rem;transform:scale(0);transition:all var(--ifm-transition-fast) var(--ifm-transition-timing-default);visibility:hidden;width:3rem;z-index:calc(var(--ifm-z-index-fixed) - 1)}.backToTopButton_jzr7:after{background-color:var(--ifm-color-emphasis-1000);content:" ";display:inline-block;height:100%;-webkit-mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;width:100%}.backToTopButtonShow_LiSR{opacity:1;transform:scale(1);visibility:visible}.skipToContent_esWp{background-color:var(--ifm-background-surface-color);color:var(--ifm-color-emphasis-900);left:100%;padding:calc(var(--ifm-global-spacing)/2) var(--ifm-global-spacing);position:fixed;top:1rem;z-index:calc(var(--ifm-z-index-fixed) + 1)}.skipToContent_esWp:focus{box-shadow:var(--ifm-global-shadow-md);left:1rem}.closeButton_z67h{line-height:0;padding:0}.content_M7UF{font-size:85%;padding:5px 0;text-align:center}.content_M7UF a{color:inherit;text-decoration:underline}.announcementBar_cOTQ{align-items:center;background-color:var(--ifm-color-white);border-bottom:1px solid var(--ifm-color-emphasis-100);color:var(--ifm-color-black);display:flex;height:var(--docusaurus-announcement-bar-height)}#__docusaurus-base-url-issue-banner-container,.docSidebarContainer_XanE,.navbarSearchContainer_g7Aj:empty,.sidebarLogo_bM71,.themedComponent_CScX,[data-theme=dark] .lightToggleIcon_E1vg,[data-theme=light] .darkToggleIcon_qyYr,html[data-announcement-bar-initially-dismissed=true] .announcementBar_cOTQ{display:none}.announcementBarPlaceholder_BoKj{flex:0 0 10px}.announcementBarClose_b2Aa{align-self:stretch;flex:0 0 30px}.toggle_WMbr{height:2rem;width:2rem}.toggleButton_hN0O{align-items:center;border-radius:50%;display:flex;height:100%;justify-content:center;transition:background var(--ifm-transition-fast);width:100%}.toggleButton_hN0O:hover{background:var(--ifm-color-emphasis-200)}.toggleButtonDisabled_n4lf{cursor:not-allowed}.darkNavbarColorModeToggle_tApx:hover{background:var(--ifm-color-gray-800)}[data-theme=dark] .themedComponent--dark_Beqs,[data-theme=light] .themedComponent--light_djhj,html:not([data-theme]) .themedComponent--light_djhj{display:initial}[data-theme=dark]:root{--docusaurus-collapse-button-bg:#ffffff0d;--docusaurus-collapse-button-bg-hover:#ffffff1a}.collapseSidebarButton_Pdml{display:none;margin:0}.iconExternalLink_JpHR{margin-left:.3rem}.docMainContainer_DED4,.docRoot_pzaq{display:flex;width:100%}.docsWrapper_MMMB{display:flex;flex:1 0 auto}.dropdownNavbarItemMobile_oMgt{cursor:pointer}.iconLanguage_OAol{margin-right:5px;vertical-align:text-bottom}.navbarHideable_y_Tb{transition:transform var(--ifm-transition-fast) ease}.navbarHidden_Gnbb{transform:translate3d(0,calc(-100% - 2px),0)}.errorBoundaryError_QUF5{color:red;white-space:pre-wrap}.errorBoundaryFallback_WZZy{color:red;padding:.55rem}.footerLogoLink_Y6HT{opacity:.5;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.footerLogoLink_Y6HT:hover,.hash-link:focus,:hover>.hash-link{opacity:1}body:not(.navigation-with-keyboard) :not(input):focus{outline:0}.anchorWithStickyNavbar_SdP1{scroll-margin-top:calc(var(--ifm-navbar-height) + .5rem)}.anchorWithHideOnScrollNavbar_y77B{scroll-margin-top:.5rem}.hash-link{opacity:0;padding-left:.5rem;transition:opacity var(--ifm-transition-fast);-webkit-user-select:none;user-select:none}.hash-link:before{content:"#"}.mainWrapper_HtD6{display:flex;flex:1 0 auto;flex-direction:column}.docusaurus-mt-lg{margin-top:3rem}#__docusaurus{display:flex;flex-direction:column;min-height:100%}.sidebar_ekj2{overflow-y:auto;position:sticky;top:calc(var(--ifm-navbar-height) + 2rem)}.sidebarItemTitle_TsGU{font-size:var(--ifm-h3-font-size)}.container_jSy4,.sidebarItemList_b3mG{font-size:.9rem}.sidebarItem_dMav{margin-top:.7rem}.sidebarItemLink_GXb_{color:var(--ifm-font-color-base);display:block}.sidebarItemLinkActive_taOo{color:var(--ifm-color-primary)!important}.yearGroupHeading_Ckl1{margin-bottom:.4rem;margin-top:1.6rem}.yearGroupHeading_GSbm{margin:1rem .75rem .5rem}.cardContainer_diBC{--ifm-link-color:var(--ifm-color-emphasis-800);--ifm-link-hover-color:var(--ifm-color-emphasis-700);--ifm-link-hover-decoration:none;border:1px solid var(--ifm-color-emphasis-200);box-shadow:0 1.5px 3px 0 #00000026;transition:all var(--ifm-transition-fast) ease;transition-property:border,box-shadow}.cardContainer_diBC:hover{border-color:var(--ifm-color-primary);box-shadow:0 3px 6px 0 #0003}.cardTitle_nQYB{font-size:1.2rem}.cardDescription_Izla{font-size:.8rem}.features_t9lD{align-items:center;display:flex;padding:2rem 0;width:100%}.featureSvg_GfXr{height:200px;width:200px}.authorSocialIcon_KepY,.authorSocialLink_aXph,.authorSocials_Ne1J{height:var(--docusaurus-blog-social-icon-size)}.authorSocialIcon_KepY,.authorSocialLink_aXph{width:var(--docusaurus-blog-social-icon-size)}.heroBanner_qdFl{overflow:hidden;padding:4rem 0;position:relative;text-align:center}.buttons_AeoN{align-items:center;display:flex;justify-content:center}[data-theme=dark] .githubSvg__FCE,[data-theme=dark] .xSvg_ot0p{fill:var(--light)}[data-theme=light] .githubSvg__FCE,[data-theme=light] .xSvg_ot0p{fill:var(--dark)}.authorSocials_Ne1J{align-items:center;display:flex;flex-wrap:wrap;line-clamp:1;-webkit-line-clamp:1}.authorSocialLink_aXph,.authorSocials_Ne1J{line-height:0}.authorSocialLink_aXph{margin-right:.4rem}.authorImage_WqWv{--ifm-avatar-photo-size:3.6rem}.author-as-h1_2BiG .authorImage_WqWv{--ifm-avatar-photo-size:7rem}.author-as-h2_XK7b .authorImage_WqWv{--ifm-avatar-photo-size:5.4rem}.authorDetails_j6ts{align-items:flex-start;display:flex;flex-direction:column;justify-content:space-around}.authorName_KvIr{display:flex;flex-direction:row;font-size:1.1rem;line-height:1.1rem}.author-as-h1_2BiG .authorName_KvIr{display:inline;font-size:2.4rem;line-height:2.4rem}.author-as-h2_XK7b .authorName_KvIr{display:inline;font-size:1.4rem;line-height:1.4rem}.authorTitle_ZCyR{display:-webkit-box;font-size:.8rem;line-height:1rem;line-clamp:1;-webkit-line-clamp:1}.author-as-h1_2BiG .authorTitle_ZCyR{font-size:1.2rem;line-height:1.6rem}.author-as-h2_XK7b .authorTitle_ZCyR{font-size:1rem;line-height:1.3rem}.authorBlogPostCount_hPSD{background:var(--ifm-color-secondary);border-radius:var(--ifm-global-radius);color:var(--ifm-color-black);font-size:.8rem;line-height:1.2;margin-left:.3rem;padding:.1rem .4rem}.buttonGroup_n6Yf button,.codeBlockContainer_Ucfp{background:var(--prism-background-color);color:var(--prism-color)}.authorListItem_p5fW{list-style-type:none;margin-bottom:2rem}.authorCol_JeSG{max-width:inherit!important}.imageOnlyAuthorRow_ItSf{display:flex;flex-flow:row wrap}.imageOnlyAuthorCol_dDNt{margin-left:.3rem;margin-right:.3rem}.codeBlockContainer_Ucfp{border-radius:var(--ifm-code-border-radius);box-shadow:var(--ifm-global-shadow-lw);margin-bottom:var(--ifm-leading)}.codeBlockContent_kaYt{border-radius:inherit;direction:ltr;position:relative}.codeBlockTitle_WUXV{border-bottom:1px solid var(--ifm-color-emphasis-300);border-top-left-radius:inherit;border-top-right-radius:inherit;font-size:var(--ifm-code-font-size);font-weight:500;padding:.75rem var(--ifm-pre-padding)}.codeBlock_XDXA{--ifm-pre-background:var(--prism-background-color);margin:0;padding:0}.codeBlockTitle_WUXV+.codeBlockContent_kaYt .codeBlock_XDXA{border-top-left-radius:0;border-top-right-radius:0}.codeBlockLines_yVZ4{float:left;font:inherit;min-width:100%;padding:var(--ifm-pre-padding)}.codeBlockLinesWithNumbering_xSW1{display:table;padding:var(--ifm-pre-padding) 0}.buttonGroup_n6Yf{column-gap:.2rem;display:flex;position:absolute;right:calc(var(--ifm-pre-padding)/2);top:calc(var(--ifm-pre-padding)/2)}.buttonGroup_n6Yf button{align-items:center;border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-global-radius);display:flex;line-height:0;opacity:0;padding:.4rem;transition:opacity var(--ifm-transition-fast) ease-in-out}.buttonGroup_n6Yf button:focus-visible,.buttonGroup_n6Yf button:hover{opacity:1!important}.theme-code-block:hover .buttonGroup_n6Yf button{opacity:.4}:where(:root){--docusaurus-highlighted-code-line-bg:#484d5b}:where([data-theme=dark]){--docusaurus-highlighted-code-line-bg:#646464}.theme-code-block-highlighted-line{background-color:var(--docusaurus-highlighted-code-line-bg);display:block;margin:0 calc(var(--ifm-pre-padding)*-1);padding:0 var(--ifm-pre-padding)}.codeLine_OyOU{counter-increment:a;display:table-row}.codeLineNumber__mNJ{background:var(--ifm-pre-background);display:table-cell;left:0;overflow-wrap:normal;padding:0 var(--ifm-pre-padding);position:sticky;text-align:right;width:1%}.codeLineNumber__mNJ:before{content:counter(a);opacity:.4}.theme-code-block-highlighted-line .codeLineNumber__mNJ:before{opacity:.8}.codeLineContent_yz5a{padding-right:var(--ifm-pre-padding)}.theme-code-block:hover .copyButtonCopied_as4q{opacity:1!important}.copyButtonIcons_HshT{height:1.125rem;position:relative;width:1.125rem}.copyButtonIcon_Vfgz,.copyButtonSuccessIcon_e8w7{left:0;position:absolute;top:0;fill:currentColor;height:inherit;opacity:inherit;transition:all var(--ifm-transition-fast) ease;width:inherit}.copyButtonSuccessIcon_e8w7{color:#00d600;left:50%;opacity:0;top:50%;transform:translate(-50%,-50%) scale(.33)}.copyButtonCopied_as4q .copyButtonIcon_Vfgz{opacity:0;transform:scale(.33)}.copyButtonCopied_as4q .copyButtonSuccessIcon_e8w7{opacity:1;transform:translate(-50%,-50%) scale(1);transition-delay:75ms}.tag_KPVF{border:1px solid var(--docusaurus-tag-list-border);transition:border var(--ifm-transition-fast)}.tag_KPVF:hover{--docusaurus-tag-list-border:var(--ifm-link-color);text-decoration:none}.tagRegular_Zwf4{border-radius:var(--ifm-global-radius);font-size:90%;padding:.2rem .5rem .3rem}.tagWithCount_bxyO{align-items:center;border-left:0;display:flex;padding:0 .5rem 0 1rem;position:relative}.tagWithCount_bxyO:after,.tagWithCount_bxyO:before{border:1px solid var(--docusaurus-tag-list-border);content:"";position:absolute;top:50%;transition:inherit}.tagWithCount_bxyO:before{border-bottom:0;border-right:0;height:1.18rem;right:100%;transform:translate(50%,-50%) rotate(-45deg);width:1.18rem}.tagWithCount_bxyO:after{border-radius:50%;height:.5rem;left:0;transform:translateY(-50%);width:.5rem}.tagWithCount_bxyO span{background:var(--ifm-color-secondary);border-radius:var(--ifm-global-radius);color:var(--ifm-color-black);font-size:.7rem;line-height:1.2;margin-left:.3rem;padding:.1rem .4rem}.tag_n9Am{display:inline-block;margin:.5rem .5rem 0 1rem}.wordWrapButtonIcon_Zz6W{height:1.2rem;width:1.2rem}.tags__8i0{display:inline}.tag_AruW{display:inline-block;margin:0 .4rem .5rem 0}.iconEdit_GDTm{margin-right:.3em;vertical-align:sub}.lastUpdated_rmkS{font-size:smaller;font-style:italic;margin-top:.2rem}.tocCollapsibleButton_F1dD{align-items:center;display:flex;font-size:inherit;justify-content:space-between;padding:.4rem .8rem;width:100%}.tocCollapsibleButton_F1dD:after{background:var(--ifm-menu-link-sublist-icon) 50% 50%/2rem 2rem no-repeat;content:"";filter:var(--ifm-menu-link-sublist-icon-filter);height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast);width:1.25rem}.tocCollapsibleButtonExpanded_VwGD:after,.tocCollapsibleExpanded_QSUg{transform:none}.tocCollapsible_y71X{background-color:var(--ifm-menu-color-background-active);border-radius:var(--ifm-global-radius);margin:1rem 0}.tocCollapsibleContent_QRtb>ul{border-left:none;border-top:1px solid var(--ifm-color-emphasis-300);font-size:15px;padding:.2rem 0}.tocCollapsibleContent_QRtb ul li{margin:.4rem .8rem}.tocCollapsibleContent_QRtb a{display:block}.details_clFM{--docusaurus-details-summary-arrow-size:0.38rem;--docusaurus-details-transition:transform 200ms ease;--docusaurus-details-decoration-color:grey}.details_clFM>summary{cursor:pointer;padding-left:1rem;position:relative}.details_clFM>summary::-webkit-details-marker{display:none}.details_clFM>summary:before{border-color:#0000 #0000 #0000 var(--docusaurus-details-decoration-color);border-style:solid;border-width:var(--docusaurus-details-summary-arrow-size);content:"";left:0;position:absolute;top:.45rem;transform:rotate(0);transform-origin:calc(var(--docusaurus-details-summary-arrow-size)/2) 50%;transition:var(--docusaurus-details-transition)}.collapsibleContent_ZlZ5{border-top:1px solid var(--docusaurus-details-decoration-color);margin-top:1rem;padding-top:1rem}.details_KfSi{--docusaurus-details-decoration-color:var(--ifm-alert-border-color);--docusaurus-details-transition:transform var(--ifm-transition-fast) ease;border:1px solid var(--ifm-alert-border-color);margin:0 0 var(--ifm-spacing-vertical)}.img_kJhV{height:auto}.tableOfContents_esvT{overflow-y:auto;position:sticky;top:calc(var(--ifm-navbar-height) + 1rem)}.admonition_yUKs{margin-bottom:1em}.admonitionHeading_yWJJ{font:var(--ifm-heading-font-weight) var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family)}.admonitionHeading_yWJJ:not(:last-child){margin-bottom:.3rem}.admonitionHeading_yWJJ code{text-transform:none}.admonitionIcon_Yzup{display:inline-block;margin-right:.4em;vertical-align:middle}.admonitionIcon_Yzup svg{display:inline-block;height:1.6em;width:1.6em;fill:var(--ifm-alert-foreground-color)}.breadcrumbHomeIcon_nDSQ{height:1.1rem;position:relative;top:1px;vertical-align:top;width:1.1rem}.breadcrumbsContainer_ynrm{--ifm-breadcrumb-size-multiplier:0.8;margin-bottom:.8rem}.title_uNxe{--ifm-h1-font-size:3rem;margin-bottom:calc(var(--ifm-leading)*1.25)}@media (min-width:997px){.collapseSidebarButton_Pdml,.expandButton_LoY7{background-color:var(--docusaurus-collapse-button-bg)}:root{--docusaurus-announcement-bar-height:30px}.announcementBarClose_b2Aa,.announcementBarPlaceholder_BoKj{flex-basis:50px}.collapseSidebarButton_Pdml{border:1px solid var(--ifm-toc-border-color);border-radius:0;bottom:0;display:block!important;height:40px;position:sticky}.collapseSidebarButtonIcon_WXMU{margin-top:4px;transform:rotate(180deg)}.expandButtonIcon_dmCM,[dir=rtl] .collapseSidebarButtonIcon_WXMU{transform:rotate(0)}.collapseSidebarButton_Pdml:focus,.collapseSidebarButton_Pdml:hover,.expandButton_LoY7:focus,.expandButton_LoY7:hover{background-color:var(--docusaurus-collapse-button-bg-hover)}.menuHtmlItem_Ws5y{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu_yJEK{flex-grow:1;padding:.5rem}@supports (scrollbar-gutter:stable){.menu_yJEK{padding:.5rem 0 .5rem .5rem;scrollbar-gutter:stable}}.menuWithAnnouncementBar_Puz2{margin-bottom:var(--docusaurus-announcement-bar-height)}.sidebar_otvc{display:flex;flex-direction:column;height:100%;padding-top:var(--ifm-navbar-height);width:var(--doc-sidebar-width)}.sidebarWithHideableNavbar_WZHY{padding-top:0}.sidebarHidden_hDe8{opacity:0;visibility:hidden}.sidebarLogo_bM71{align-items:center;color:inherit!important;display:flex!important;margin:0 var(--ifm-navbar-padding-horizontal);max-height:var(--ifm-navbar-height);min-height:var(--ifm-navbar-height);text-decoration:none!important}.sidebarLogo_bM71 img{height:2rem;margin-right:.5rem}.expandButton_LoY7{align-items:center;display:flex;height:100%;justify-content:center;position:absolute;right:0;top:0;transition:background-color var(--ifm-transition-fast) ease;width:100%}[dir=rtl] .expandButtonIcon_dmCM{transform:rotate(180deg)}.docSidebarContainer_XanE{border-right:1px solid var(--ifm-toc-border-color);clip-path:inset(0);display:block;margin-top:calc(var(--ifm-navbar-height)*-1);transition:width var(--ifm-transition-fast) ease;width:var(--doc-sidebar-width);will-change:width}.docSidebarContainerHidden_EXCO{cursor:pointer;width:var(--doc-sidebar-hidden-width)}.sidebarViewport_IZ4k{height:100%;max-height:100vh;position:sticky;top:0}.docMainContainer_DED4{flex-grow:1;max-width:calc(100% - var(--doc-sidebar-width))}.docMainContainerEnhanced_RI44{max-width:calc(100% - var(--doc-sidebar-hidden-width))}.docItemWrapperEnhanced_vhJD{max-width:calc(var(--ifm-container-width) + var(--doc-sidebar-width))!important}.navbarSearchContainer_g7Aj{padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.lastUpdated_rmkS{text-align:right}.tocMobile_pk_C{display:none}.docItemCol_U9wp,.generatedIndexPage_G9J0{max-width:75%!important}.list_ybXY article:nth-last-child(-n+2){margin-bottom:0!important}}@media (min-width:1440px){.container{max-width:var(--ifm-container-width-xl)}}@media (max-width:996px){.col{--ifm-col-width:100%;flex-basis:var(--ifm-col-width);margin-left:0}.footer{--ifm-footer-padding-horizontal:0}.colorModeToggle_fJbX,.footer__link-separator,.navbar__item,.sidebar_ekj2,.tableOfContents_esvT{display:none}.footer__col{margin-bottom:calc(var(--ifm-spacing-vertical)*3)}.footer__link-item{display:block;width:max-content}.hero{padding-left:0;padding-right:0}.navbar>.container,.navbar>.container-fluid{padding:0}.navbar__toggle{display:inherit}.navbar__search-input{width:9rem}.pills--block,.tabs--block{flex-direction:column}.navbarSearchContainer_g7Aj{position:absolute;right:var(--ifm-navbar-padding-horizontal)}.docItemContainer_EOpK{padding:0 .3rem}}@media screen and (max-width:996px){.heroBanner_qdFl{padding:2rem}}@media (max-width:576px){.markdown h1:first-child{--ifm-h1-font-size:2rem}.markdown>h2{--ifm-h2-font-size:1.5rem}.markdown>h3{--ifm-h3-font-size:1.25rem}.title_Ikqq{font-size:2rem}}@media (hover:hover){.backToTopButton_jzr7:hover{background-color:var(--ifm-color-emphasis-300)}}@media (pointer:fine){.thin-scrollbar{scrollbar-width:thin}.thin-scrollbar::-webkit-scrollbar{height:var(--ifm-scrollbar-size);width:var(--ifm-scrollbar-size)}.thin-scrollbar::-webkit-scrollbar-track{background:var(--ifm-scrollbar-track-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb{background:var(--ifm-scrollbar-thumb-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb:hover{background:var(--ifm-scrollbar-thumb-hover-background-color)}}@media (prefers-reduced-motion:reduce){:root{--ifm-transition-fast:0ms;--ifm-transition-slow:0ms}}@media print{.announcementBar_cOTQ,.footer,.menu,.navbar,.pagination-nav,.table-of-contents,.tocMobile_pk_C{display:none}.tabs{page-break-inside:avoid}.codeBlockLines_yVZ4{white-space:pre-wrap}} \ No newline at end of file diff --git a/assets/images/docusaurus-plushie-banner-a60f7593abca1e3eef26a9afa244e4fb.jpeg b/assets/images/docusaurus-plushie-banner-a60f7593abca1e3eef26a9afa244e4fb.jpeg new file mode 100644 index 000000000..11bda0928 Binary files /dev/null and b/assets/images/docusaurus-plushie-banner-a60f7593abca1e3eef26a9afa244e4fb.jpeg differ diff --git a/assets/js/01a85c17.00111f7a.js b/assets/js/01a85c17.00111f7a.js new file mode 100644 index 000000000..477ac7981 --- /dev/null +++ b/assets/js/01a85c17.00111f7a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[8209],{9930:(e,t,a)=>{a.d(t,{in:()=>c,OU:()=>P,Ki:()=>y,kJ:()=>b,x:()=>l,e7:()=>m,J_:()=>f,Gx:()=>A});var s=a(758),n=a(9751),i=a(3206),r=a(6070);function l(){const e=(0,i.A)(),t=e?.data?.blogMetadata;if(!t)throw new Error("useBlogMetadata() can't be called on the current route because the blog metadata could not be found in route context");return t}const o=s.createContext(null);function c(e){let{children:t,content:a,isBlogPostPage:n=!1}=e;const i=function(e){let{content:t,isBlogPostPage:a}=e;return(0,s.useMemo)((()=>({metadata:t.metadata,frontMatter:t.frontMatter,assets:t.assets,toc:t.toc,isBlogPostPage:a})),[t,a])}({content:a,isBlogPostPage:n});return(0,r.jsx)(o.Provider,{value:i,children:t})}function m(){const e=(0,s.useContext)(o);if(null===e)throw new n.dV("BlogPostProvider");return e}var d=a(1926),u=a(3501);const g=e=>new Date(e).toISOString();function h(e){const t=e.map(x);return{author:1===t.length?t[0]:t}}function p(e,t,a){return e?{image:j({imageUrl:t(e,{absolute:!0}),caption:`title image for the blog post: ${a}`})}:{}}function b(e){const{siteConfig:t}=(0,u.A)(),{withBaseUrl:a}=(0,d.hH)(),{metadata:{blogDescription:s,blogTitle:n,permalink:i}}=e,r=`${t.url}${i}`;return{"@context":"https://schema.org","@type":"Blog","@id":r,mainEntityOfPage:r,headline:n,description:s,blogPost:e.items.map((e=>function(e,t,a){const{assets:s,frontMatter:n,metadata:i}=e,{date:r,title:l,description:o,lastUpdatedAt:c}=i,m=s.image??n.image,d=n.keywords??[],u=`${t.url}${i.permalink}`,b=c?g(c):void 0;return{"@type":"BlogPosting","@id":u,mainEntityOfPage:u,url:u,headline:l,name:l,description:o,datePublished:r,...b?{dateModified:b}:{},...h(i.authors),...p(m,a,l),...d?{keywords:d}:{}}}(e.content,t,a)))}}function f(){const e=l(),{assets:t,metadata:a}=m(),{siteConfig:s}=(0,u.A)(),{withBaseUrl:n}=(0,d.hH)(),{date:i,title:r,description:o,frontMatter:c,lastUpdatedAt:b}=a,f=t.image??c.image,x=c.keywords??[],j=b?g(b):void 0,v=`${s.url}${a.permalink}`;return{"@context":"https://schema.org","@type":"BlogPosting","@id":v,mainEntityOfPage:v,url:v,headline:r,name:r,description:o,datePublished:i,...j?{dateModified:j}:{},...h(a.authors),...p(f,n,r),...x?{keywords:x}:{},isPartOf:{"@type":"Blog","@id":`${s.url}${e.blogBasePath}`,name:e.blogTitle}}}function x(e){return{"@type":"Person",...e.name?{name:e.name}:{},...e.title?{description:e.title}:{},...e.url?{url:e.url}:{},...e.email?{email:e.email}:{},...e.imageURL?{image:e.imageURL}:{}}}function j(e){let{imageUrl:t,caption:a}=e;return{"@type":"ImageObject","@id":t,url:t,contentUrl:t,caption:a}}var v=a(5557),N=a(9857),C=a(4919),k=a(7372);function A(e){const{pathname:t}=(0,v.zy)();return(0,s.useMemo)((()=>e.filter((e=>function(e,t){return!(e.unlisted&&!(0,k.ys)(e.permalink,t))}(e,t)))),[e,t])}function y(e){const t=(0,C.$z)(e,(e=>`${new Date(e.date).getFullYear()}`)),a=Object.entries(t);return a.reverse(),a}function P(e){let{items:t,ulClassName:a,liClassName:s,linkClassName:n,linkActiveClassName:i}=e;return(0,r.jsx)("ul",{className:a,children:t.map((e=>(0,r.jsx)("li",{className:s,children:(0,r.jsx)(N.A,{isNavLink:!0,to:e.permalink,className:n,activeClassName:i,children:e.title})},e.permalink)))})}},5867:(e,t,a)=>{a.d(t,{A:()=>U});var s=a(758),n=a(3526),i=a(5574),r=a(8816),l=a(4532),o=a(9930),c=a(517),m=a(6096),d=a(6070);function u(e){let{year:t,yearGroupHeadingClassName:a,children:s}=e;return(0,d.jsxs)("div",{role:"group",children:[(0,d.jsx)(m.A,{as:"h3",className:a,children:t}),s]})}function g(e){let{items:t,yearGroupHeadingClassName:a,ListComponent:s}=e;if((0,c.p)().blog.sidebar.groupByYear){const e=(0,o.Ki)(t);return(0,d.jsx)(d.Fragment,{children:e.map((e=>{let[t,n]=e;return(0,d.jsx)(u,{year:t,yearGroupHeadingClassName:a,children:(0,d.jsx)(s,{items:n})},t)}))})}return(0,d.jsx)(s,{items:t})}const h=(0,s.memo)(g),p="sidebar_ekj2",b="sidebarItemTitle_TsGU",f="sidebarItemList_b3mG",x="sidebarItem_dMav",j="sidebarItemLink_GXb_",v="sidebarItemLinkActive_taOo",N="yearGroupHeading_Ckl1",C=e=>{let{items:t}=e;return(0,d.jsx)(o.OU,{items:t,ulClassName:(0,n.A)(f,"clean-list"),liClassName:x,linkClassName:j,linkActiveClassName:v})};function k(e){let{sidebar:t}=e;const a=(0,o.Gx)(t.items);return(0,d.jsx)("aside",{className:"col col--3",children:(0,d.jsxs)("nav",{className:(0,n.A)(p,"thin-scrollbar"),"aria-label":(0,l.T)({id:"theme.blog.sidebar.navAriaLabel",message:"Blog recent posts navigation",description:"The ARIA label for recent posts in the blog sidebar"}),children:[(0,d.jsx)("div",{className:(0,n.A)(b,"margin-bottom--md"),children:t.title}),(0,d.jsx)(h,{items:a,ListComponent:C,yearGroupHeadingClassName:N})]})})}const A=(0,s.memo)(k);var y=a(1843);const P="yearGroupHeading_GSbm",_=e=>{let{items:t}=e;return(0,d.jsx)(o.OU,{items:t,ulClassName:"menu__list",liClassName:"menu__list-item",linkClassName:"menu__link",linkActiveClassName:"menu__link--active"})};function w(e){let{sidebar:t}=e;const a=(0,o.Gx)(t.items);return(0,d.jsx)(h,{items:a,ListComponent:_,yearGroupHeadingClassName:P})}function G(e){return(0,d.jsx)(y.GX,{component:w,props:e})}const B=(0,s.memo)(G);function O(e){let{sidebar:t}=e;const a=(0,r.l)();return t?.items.length?"mobile"===a?(0,d.jsx)(B,{sidebar:t}):(0,d.jsx)(A,{sidebar:t}):null}function U(e){const{sidebar:t,toc:a,children:s,...r}=e,l=t&&t.items.length>0;return(0,d.jsx)(i.A,{...r,children:(0,d.jsx)("div",{className:"container margin-vert--lg",children:(0,d.jsxs)("div",{className:"row",children:[(0,d.jsx)(O,{sidebar:t}),(0,d.jsx)("main",{className:(0,n.A)("col",{"col--7":l,"col--9 col--offset-1":!l}),children:s}),a&&(0,d.jsx)("div",{className:"col col--2",children:a})]})})})}},5951:(e,t,a)=>{a.r(t),a.d(t,{default:()=>b});a(758);var s=a(3526),n=a(4532);const i=()=>(0,n.T)({id:"theme.tags.tagsPageTitle",message:"Tags",description:"The title of the tag list page"});var r=a(2614),l=a(8238),o=a(5867),c=a(5138),m=a(6096);const d={tag:"tag_n9Am"};var u=a(6070);function g(e){let{letterEntry:t}=e;return(0,u.jsxs)("article",{children:[(0,u.jsx)(m.A,{as:"h2",id:t.letter,children:t.letter}),(0,u.jsx)("ul",{className:"padding--none",children:t.tags.map((e=>(0,u.jsx)("li",{className:d.tag,children:(0,u.jsx)(c.A,{...e})},e.permalink)))}),(0,u.jsx)("hr",{})]})}function h(e){let{tags:t}=e;const a=function(e){const t={};return Object.values(e).forEach((e=>{const a=function(e){return e[0].toUpperCase()}(e.label);t[a]??=[],t[a].push(e)})),Object.entries(t).sort(((e,t)=>{let[a]=e,[s]=t;return a.localeCompare(s)})).map((e=>{let[t,a]=e;return{letter:t,tags:a.sort(((e,t)=>e.label.localeCompare(t.label)))}}))}(t);return(0,u.jsx)("section",{className:"margin-vert--lg",children:a.map((e=>(0,u.jsx)(g,{letterEntry:e},e.letter)))})}var p=a(714);function b(e){let{tags:t,sidebar:a}=e;const n=i();return(0,u.jsxs)(r.e3,{className:(0,s.A)(l.G.wrapper.blogPages,l.G.page.blogTagsListPage),children:[(0,u.jsx)(r.be,{title:n}),(0,u.jsx)(p.A,{tag:"blog_tags_list"}),(0,u.jsxs)(o.A,{sidebar:a,children:[(0,u.jsx)(m.A,{as:"h1",children:n}),(0,u.jsx)(h,{tags:t})]})]})}},5138:(e,t,a)=>{a.d(t,{A:()=>l});a(758);var s=a(3526),n=a(9857);const i={tag:"tag_KPVF",tagRegular:"tagRegular_Zwf4",tagWithCount:"tagWithCount_bxyO"};var r=a(6070);function l(e){let{permalink:t,label:a,count:l,description:o}=e;return(0,r.jsxs)(n.A,{href:t,title:o,className:(0,s.A)(i.tag,l?i.tagWithCount:i.tagRegular),children:[a,l&&(0,r.jsx)("span",{children:l})]})}}}]); \ No newline at end of file diff --git a/assets/js/036da81a.f941f10b.js b/assets/js/036da81a.f941f10b.js new file mode 100644 index 000000000..72baa632b --- /dev/null +++ b/assets/js/036da81a.f941f10b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[6219],{9064:e=>{e.exports=JSON.parse('{"categoryGeneratedIndex":{"title":"API","description":"API documentation","slug":"/category/api-1","permalink":"/gmap-vue/docs/category/api-1","sidebar":"vue3Version","navigation":{"previous":{"title":"Map","permalink":"/gmap-vue/docs/vue-3-version/guide/components/map"},"next":{"title":"main.ts","permalink":"/gmap-vue/docs/vue-3-version/api/"}}}}')}}]); \ No newline at end of file diff --git a/assets/js/0a3daff0.bbb9d3aa.js b/assets/js/0a3daff0.bbb9d3aa.js new file mode 100644 index 000000000..28afd38da --- /dev/null +++ b/assets/js/0a3daff0.bbb9d3aa.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[3664],{941:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>M,contentTitle:()=>A,default:()=>D,frontMatter:()=>N,metadata:()=>r,toc:()=>C});const r=JSON.parse('{"id":"vue-3-version/introduction","title":"Welcome","description":"This documentation is under development, it contains the main points and examples but we continue working on it. Please if you find a bug or something that is not correct, feel free to report it or send a PR to improve it. Thank you.","source":"@site/docs/vue-3-version/index.mdx","sourceDirName":"vue-3-version","slug":"/vue-3-version/","permalink":"/gmap-vue/docs/vue-3-version/","draft":false,"unlisted":false,"editUrl":"https://github.com/diegoazh/gmap-vue/docs/vue-3-version/index.mdx","tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"id":"introduction","title":"Welcome","type":"link","sidebar_position":1,"sidebar_label":"Introduction"},"sidebar":"vue3Version","next":{"title":"Guide","permalink":"/gmap-vue/docs/category/guide-1"}}');var i=t(6070),a=t(5658),s=t(758),l=t(3526),o=t(2973),c=t(5557),d=t(7636),u=t(2310),p=t(4919),h=t(1231);function m(e){return s.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,s.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function f(e){const{values:n,children:t}=e;return(0,s.useMemo)((()=>{const e=n??function(e){return m(e).map((e=>{let{props:{value:n,label:t,attributes:r,default:i}}=e;return{value:n,label:t,attributes:r,default:i}}))}(t);return function(e){const n=(0,p.XI)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,t])}function g(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function v(e){let{queryString:n=!1,groupId:t}=e;const r=(0,c.W6)(),i=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return t??null}({queryString:n,groupId:t});return[(0,u.aZ)(i),(0,s.useCallback)((e=>{if(!i)return;const n=new URLSearchParams(r.location.search);n.set(i,e),r.replace({...r.location,search:n.toString()})}),[i,r])]}function x(e){const{defaultValue:n,queryString:t=!1,groupId:r}=e,i=f(e),[a,l]=(0,s.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!g({value:n,tabValues:t}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=t.find((e=>e.default))??t[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:i}))),[o,c]=v({queryString:t,groupId:r}),[u,p]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[r,i]=(0,h.Dv)(t);return[r,(0,s.useCallback)((e=>{t&&i.set(e)}),[t,i])]}({groupId:r}),m=(()=>{const e=o??u;return g({value:e,tabValues:i})?e:null})();(0,d.A)((()=>{m&&l(m)}),[m]);return{selectedValue:a,selectValue:(0,s.useCallback)((e=>{if(!g({value:e,tabValues:i}))throw new Error(`Can't select invalid tab value=${e}`);l(e),c(e),p(e)}),[c,p,i]),tabValues:i}}var j=t(1760);const b={tabList:"tabList_vBCw",tabItem:"tabItem_NxBH"};function y(e){let{className:n,block:t,selectedValue:r,selectValue:a,tabValues:s}=e;const c=[],{blockElementScrollPositionUntilNextRender:d}=(0,o.a_)(),u=e=>{const n=e.currentTarget,t=c.indexOf(n),i=s[t].value;i!==r&&(d(n),a(i))},p=e=>{let n=null;switch(e.key){case"Enter":u(e);break;case"ArrowRight":{const t=c.indexOf(e.currentTarget)+1;n=c[t]??c[0];break}case"ArrowLeft":{const t=c.indexOf(e.currentTarget)-1;n=c[t]??c[c.length-1];break}}n?.focus()};return(0,i.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,l.A)("tabs",{"tabs--block":t},n),children:s.map((e=>{let{value:n,label:t,attributes:a}=e;return(0,i.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>c.push(e),onKeyDown:p,onClick:u,...a,className:(0,l.A)("tabs__item",b.tabItem,a?.className,{"tabs__item--active":r===n}),children:t??n},n)}))})}function w(e){let{lazy:n,children:t,selectedValue:r}=e;const a=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=a.find((e=>e.props.value===r));return e?(0,s.cloneElement)(e,{className:(0,l.A)("margin-top--md",e.props.className)}):null}return(0,i.jsx)("div",{className:"margin-top--md",children:a.map(((e,n)=>(0,s.cloneElement)(e,{key:n,hidden:e.props.value!==r})))})}function k(e){const n=x(e);return(0,i.jsxs)("div",{className:(0,l.A)("tabs-container",b.tabList),children:[(0,i.jsx)(y,{...n,...e}),(0,i.jsx)(w,{...n,...e})]})}function T(e){const n=(0,j.A)();return(0,i.jsx)(k,{...e,children:m(e.children)},String(n))}const I={tabItem:"tabItem_nvWs"};function V(e){let{children:n,hidden:t,className:r}=e;return(0,i.jsx)("div",{role:"tabpanel",className:(0,l.A)(I.tabItem,r),hidden:t,children:n})}const N={id:"introduction",title:"Welcome",type:"link",sidebar_position:1,sidebar_label:"Introduction"},A="GmapVue for Vue 3",M={},C=[{value:"Installation",id:"installation",level:2},{value:"Using a CDN",id:"using-a-cdn",level:3},{value:"Global styles",id:"global-styles",level:2},{value:"Dynamic Library Import",id:"dynamic-library-import",level:2},{value:"Migrating from version for Vue 2",id:"migrating-from-version-for-vue-2",level:2}];function P(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"gmapvue-for-vue-3",children:"GmapVue for Vue 3"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.a,{href:"https://www.jsdelivr.com/package/npm/@gmap-vue/v3",children:(0,i.jsx)(n.img,{src:"https://data.jsdelivr.com/v1/package/npm/@gmap-vue/v3/badge",alt:""})})}),"\n",(0,i.jsx)(n.admonition,{type:"warning",children:(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"This documentation is under development"}),", it contains the main points and examples but we continue working on it. Please if you find a bug or something that is not correct, feel free to report it or send a PR to improve it. Thank you."]})}),"\n",(0,i.jsx)(n.h2,{id:"installation",children:"Installation"}),"\n",(0,i.jsxs)(T,{children:[(0,i.jsx)(V,{value:"npm",label:"NPM",default:!0,children:(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"npm install @gmap-vue/v3 --save\n"})})}),(0,i.jsx)(V,{value:"yarn",label:"Yarn",children:(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"yarn add @gmap-vue/v3\n"})})}),(0,i.jsx)(V,{value:"pnpm",label:"PNPM",children:(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",children:"pnpm add @gmap-vue/v3\n"})})}),(0,i.jsxs)(V,{value:"manual",label:"Manually",children:[(0,i.jsxs)(n.p,{children:["Just download ",(0,i.jsx)(n.code,{children:"dist/main.umd.js"})," file and include it from your HTML."]}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-html",children:' + + + + + + \ No newline at end of file diff --git a/blog/atom.xml b/blog/atom.xml new file mode 100644 index 000000000..ee87d5830 --- /dev/null +++ b/blog/atom.xml @@ -0,0 +1,117 @@ + + + https://diegoazh.github.io/gmap-vue/blog + GmapVue Docs Blog + 2021-08-26T00:00:00.000Z + https://github.com/jpmonette/feed + + GmapVue Docs Blog + https://diegoazh.github.io/gmap-vue/img/favicon.ico + + <![CDATA[Welcome]]> + https://diegoazh.github.io/gmap-vue/blog/welcome + + 2021-08-26T00:00:00.000Z + + Docusaurus blogging features are powered by the blog plugin.

+

Simply add Markdown files (or folders) to the blog directory.

+

Regular blog authors can be added to authors.yml.

+

The blog post date can be extracted from filenames, such as:

+
    +
  • 2019-05-30-welcome.md
  • +
  • 2019-05-30-welcome/index.md
  • +
+

A blog post folder can be convenient to co-locate blog post images:

+

Docusaurus Plushie

+

The blog supports tags as well!

+

And if you don't want a blog: just delete this directory, and use blog: false in your Docusaurus config.

]]>
+ + Sébastien Lorber + https://sebastienlorber.com + + + Yangshun Tay + https://github.com/yangshun + + + + +
+ + <![CDATA[MDX Blog Post]]> + https://diegoazh.github.io/gmap-vue/blog/mdx-blog-post + + 2021-08-01T00:00:00.000Z + + Blog posts support Docusaurus Markdown features, such as MDX.

+
tip

Use the power of React to create interactive blog posts.

<button onClick={() => alert('button clicked!')}>Click me!</button>
]]>
+ + Sébastien Lorber + https://sebastienlorber.com + + +
+ + <![CDATA[Greetings!]]> + https://diegoazh.github.io/gmap-vue/blog/greetings + + 2021-02-28T00:00:00.000Z + + Congratulations, you have made your first post!

+

Feel free to play around and edit this post as much as you like.

]]>
+ + Joel Marcey + https://github.com/JoelMarcey + + + Sébastien Lorber + https://sebastienlorber.com + + +
+ + <![CDATA[Long Blog Post]]> + https://diegoazh.github.io/gmap-vue/blog/long-blog-post + + 2019-05-29T00:00:00.000Z + + This is the summary of a very long blog post,

+

Use a <!-- truncate --> comment to limit blog post size in the list view.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

]]>
+ + Endilie Yacop Sucipto + https://github.com/endiliey + + + +
+ + <![CDATA[First Blog Post]]> + https://diegoazh.github.io/gmap-vue/blog/first-blog-post + + 2019-05-28T00:00:00.000Z + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

]]>
+ + Gao Wei + https://github.com/wgao19 + + + +
+
\ No newline at end of file diff --git a/blog/authors/index.html b/blog/authors/index.html new file mode 100644 index 000000000..9efbcbdca --- /dev/null +++ b/blog/authors/index.html @@ -0,0 +1,14 @@ + + + + + +Authors | GmapVue Docs + + + + + +

Authors

+ + \ No newline at end of file diff --git a/blog/first-blog-post/index.html b/blog/first-blog-post/index.html new file mode 100644 index 000000000..ee3ee6acf --- /dev/null +++ b/blog/first-blog-post/index.html @@ -0,0 +1,14 @@ + + + + + +First Blog Post | GmapVue Docs + + + + + +

First Blog Post

· One min read
Gao Wei
Docusaurus Core Team

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+ + \ No newline at end of file diff --git a/blog/greetings/index.html b/blog/greetings/index.html new file mode 100644 index 000000000..c758fe3b5 --- /dev/null +++ b/blog/greetings/index.html @@ -0,0 +1,15 @@ + + + + + +Greetings! | GmapVue Docs + + + + + +

Greetings!

· One min read
Joel Marcey
Co-creator of Docusaurus 1
Sébastien Lorber
Docusaurus maintainer

Congratulations, you have made your first post!

+

Feel free to play around and edit this post as much as you like.

+ + \ No newline at end of file diff --git a/blog/index.html b/blog/index.html new file mode 100644 index 000000000..bc26b3841 --- /dev/null +++ b/blog/index.html @@ -0,0 +1,28 @@ + + + + + +Blog | GmapVue Docs + + + + + +

Welcome

· One min read
Sébastien Lorber
Docusaurus maintainer
Yangshun Tay
Front End Engineer @ Facebook

Docusaurus blogging features are powered by the blog plugin.

+

Simply add Markdown files (or folders) to the blog directory.

+

Regular blog authors can be added to authors.yml.

+

The blog post date can be extracted from filenames, such as:

+
    +
  • 2019-05-30-welcome.md
  • +
  • 2019-05-30-welcome/index.md
  • +
+

A blog post folder can be convenient to co-locate blog post images:

+

Docusaurus Plushie

+

The blog supports tags as well!

+

And if you don't want a blog: just delete this directory, and use blog: false in your Docusaurus config.

Greetings!

· One min read
Joel Marcey
Co-creator of Docusaurus 1
Sébastien Lorber
Docusaurus maintainer

Congratulations, you have made your first post!

+

Feel free to play around and edit this post as much as you like.

First Blog Post

· One min read
Gao Wei
Docusaurus Core Team

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+ + \ No newline at end of file diff --git a/blog/long-blog-post/index.html b/blog/long-blog-post/index.html new file mode 100644 index 000000000..89a1825ac --- /dev/null +++ b/blog/long-blog-post/index.html @@ -0,0 +1,31 @@ + + + + + +Long Blog Post | GmapVue Docs + + + + + +

Long Blog Post

· 3 min read
Endilie Yacop Sucipto
Maintainer of Docusaurus

This is the summary of a very long blog post,

+

Use a <!-- truncate --> comment to limit blog post size in the list view.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+ + \ No newline at end of file diff --git a/blog/mdx-blog-post/index.html b/blog/mdx-blog-post/index.html new file mode 100644 index 000000000..e596d7989 --- /dev/null +++ b/blog/mdx-blog-post/index.html @@ -0,0 +1,15 @@ + + + + + +MDX Blog Post | GmapVue Docs + + + + + +
+ + \ No newline at end of file diff --git a/blog/rss.xml b/blog/rss.xml new file mode 100644 index 000000000..a371293e6 --- /dev/null +++ b/blog/rss.xml @@ -0,0 +1,91 @@ + + + + GmapVue Docs Blog + https://diegoazh.github.io/gmap-vue/blog + GmapVue Docs Blog + Thu, 26 Aug 2021 00:00:00 GMT + https://validator.w3.org/feed/docs/rss2.html + https://github.com/jpmonette/feed + en + + <![CDATA[Welcome]]> + https://diegoazh.github.io/gmap-vue/blog/welcome + https://diegoazh.github.io/gmap-vue/blog/welcome + Thu, 26 Aug 2021 00:00:00 GMT + + Docusaurus blogging features are powered by the blog plugin.

+

Simply add Markdown files (or folders) to the blog directory.

+

Regular blog authors can be added to authors.yml.

+

The blog post date can be extracted from filenames, such as:

+
    +
  • 2019-05-30-welcome.md
  • +
  • 2019-05-30-welcome/index.md
  • +
+

A blog post folder can be convenient to co-locate blog post images:

+

Docusaurus Plushie

+

The blog supports tags as well!

+

And if you don't want a blog: just delete this directory, and use blog: false in your Docusaurus config.

]]>
+ facebook + hello + docusaurus +
+ + <![CDATA[MDX Blog Post]]> + https://diegoazh.github.io/gmap-vue/blog/mdx-blog-post + https://diegoazh.github.io/gmap-vue/blog/mdx-blog-post + Sun, 01 Aug 2021 00:00:00 GMT + + Blog posts support Docusaurus Markdown features, such as MDX.

+
tip

Use the power of React to create interactive blog posts.

<button onClick={() => alert('button clicked!')}>Click me!</button>
]]>
+ docusaurus +
+ + <![CDATA[Greetings!]]> + https://diegoazh.github.io/gmap-vue/blog/greetings + https://diegoazh.github.io/gmap-vue/blog/greetings + Sun, 28 Feb 2021 00:00:00 GMT + + Congratulations, you have made your first post!

+

Feel free to play around and edit this post as much as you like.

]]>
+ greetings +
+ + <![CDATA[Long Blog Post]]> + https://diegoazh.github.io/gmap-vue/blog/long-blog-post + https://diegoazh.github.io/gmap-vue/blog/long-blog-post + Wed, 29 May 2019 00:00:00 GMT + + This is the summary of a very long blog post,

+

Use a <!-- truncate --> comment to limit blog post size in the list view.

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

]]>
+ hello + docusaurus +
+ + <![CDATA[First Blog Post]]> + https://diegoazh.github.io/gmap-vue/blog/first-blog-post + https://diegoazh.github.io/gmap-vue/blog/first-blog-post + Tue, 28 May 2019 00:00:00 GMT + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

]]>
+ hola + docusaurus +
+
+
\ No newline at end of file diff --git a/blog/tags/docusaurus/index.html b/blog/tags/docusaurus/index.html new file mode 100644 index 000000000..917656e45 --- /dev/null +++ b/blog/tags/docusaurus/index.html @@ -0,0 +1,27 @@ + + + + + +4 posts tagged with "docusaurus" | GmapVue Docs + + + + + +

4 posts tagged with "docusaurus"

View All Tags

Welcome

· One min read
Sébastien Lorber
Docusaurus maintainer
Yangshun Tay
Front End Engineer @ Facebook

Docusaurus blogging features are powered by the blog plugin.

+

Simply add Markdown files (or folders) to the blog directory.

+

Regular blog authors can be added to authors.yml.

+

The blog post date can be extracted from filenames, such as:

+
    +
  • 2019-05-30-welcome.md
  • +
  • 2019-05-30-welcome/index.md
  • +
+

A blog post folder can be convenient to co-locate blog post images:

+

Docusaurus Plushie

+

The blog supports tags as well!

+

And if you don't want a blog: just delete this directory, and use blog: false in your Docusaurus config.

First Blog Post

· One min read
Gao Wei
Docusaurus Core Team

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+ + \ No newline at end of file diff --git a/blog/tags/facebook/index.html b/blog/tags/facebook/index.html new file mode 100644 index 000000000..6791a29dd --- /dev/null +++ b/blog/tags/facebook/index.html @@ -0,0 +1,25 @@ + + + + + +One post tagged with "facebook" | GmapVue Docs + + + + + +

One post tagged with "facebook"

View All Tags

Welcome

· One min read
Sébastien Lorber
Docusaurus maintainer
Yangshun Tay
Front End Engineer @ Facebook

Docusaurus blogging features are powered by the blog plugin.

+

Simply add Markdown files (or folders) to the blog directory.

+

Regular blog authors can be added to authors.yml.

+

The blog post date can be extracted from filenames, such as:

+
    +
  • 2019-05-30-welcome.md
  • +
  • 2019-05-30-welcome/index.md
  • +
+

A blog post folder can be convenient to co-locate blog post images:

+

Docusaurus Plushie

+

The blog supports tags as well!

+

And if you don't want a blog: just delete this directory, and use blog: false in your Docusaurus config.

+ + \ No newline at end of file diff --git a/blog/tags/greetings/index.html b/blog/tags/greetings/index.html new file mode 100644 index 000000000..deba1108e --- /dev/null +++ b/blog/tags/greetings/index.html @@ -0,0 +1,15 @@ + + + + + +One post tagged with "greetings" | GmapVue Docs + + + + + +

One post tagged with "greetings"

View All Tags

Greetings!

· One min read
Joel Marcey
Co-creator of Docusaurus 1
Sébastien Lorber
Docusaurus maintainer

Congratulations, you have made your first post!

+

Feel free to play around and edit this post as much as you like.

+ + \ No newline at end of file diff --git a/blog/tags/hello/index.html b/blog/tags/hello/index.html new file mode 100644 index 000000000..8c6a56f96 --- /dev/null +++ b/blog/tags/hello/index.html @@ -0,0 +1,26 @@ + + + + + +2 posts tagged with "hello" | GmapVue Docs + + + + + +

2 posts tagged with "hello"

View All Tags

Welcome

· One min read
Sébastien Lorber
Docusaurus maintainer
Yangshun Tay
Front End Engineer @ Facebook

Docusaurus blogging features are powered by the blog plugin.

+

Simply add Markdown files (or folders) to the blog directory.

+

Regular blog authors can be added to authors.yml.

+

The blog post date can be extracted from filenames, such as:

+
    +
  • 2019-05-30-welcome.md
  • +
  • 2019-05-30-welcome/index.md
  • +
+

A blog post folder can be convenient to co-locate blog post images:

+

Docusaurus Plushie

+

The blog supports tags as well!

+

And if you don't want a blog: just delete this directory, and use blog: false in your Docusaurus config.

+ + \ No newline at end of file diff --git a/blog/tags/hola/index.html b/blog/tags/hola/index.html new file mode 100644 index 000000000..31cb499d9 --- /dev/null +++ b/blog/tags/hola/index.html @@ -0,0 +1,14 @@ + + + + + +One post tagged with "hola" | GmapVue Docs + + + + + +

One post tagged with "hola"

View All Tags

First Blog Post

· One min read
Gao Wei
Docusaurus Core Team

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

+ + \ No newline at end of file diff --git a/blog/tags/index.html b/blog/tags/index.html new file mode 100644 index 000000000..2c3d7ccb7 --- /dev/null +++ b/blog/tags/index.html @@ -0,0 +1,14 @@ + + + + + +Tags | GmapVue Docs + + + + + + + + \ No newline at end of file diff --git a/blog/welcome/index.html b/blog/welcome/index.html new file mode 100644 index 000000000..e16f4d610 --- /dev/null +++ b/blog/welcome/index.html @@ -0,0 +1,25 @@ + + + + + +Welcome | GmapVue Docs + + + + + +

Welcome

· One min read
Sébastien Lorber
Docusaurus maintainer
Yangshun Tay
Front End Engineer @ Facebook

Docusaurus blogging features are powered by the blog plugin.

+

Simply add Markdown files (or folders) to the blog directory.

+

Regular blog authors can be added to authors.yml.

+

The blog post date can be extracted from filenames, such as:

+
    +
  • 2019-05-30-welcome.md
  • +
  • 2019-05-30-welcome/index.md
  • +
+

A blog post folder can be convenient to co-locate blog post images:

+

Docusaurus Plushie

+

The blog supports tags as well!

+

And if you don't want a blog: just delete this directory, and use blog: false in your Docusaurus config.

+ + \ No newline at end of file diff --git a/docs/category/api-1/index.html b/docs/category/api-1/index.html new file mode 100644 index 000000000..4f60bad21 --- /dev/null +++ b/docs/category/api-1/index.html @@ -0,0 +1,14 @@ + + + + + +API | GmapVue Docs + + + + + + + + \ No newline at end of file diff --git a/docs/category/api/index.html b/docs/category/api/index.html new file mode 100644 index 000000000..8daa11df5 --- /dev/null +++ b/docs/category/api/index.html @@ -0,0 +1,14 @@ + + + + + +API | GmapVue Docs + + + + + + + + \ No newline at end of file diff --git a/docs/category/basic-usage/index.html b/docs/category/basic-usage/index.html new file mode 100644 index 000000000..9a8c50c4d --- /dev/null +++ b/docs/category/basic-usage/index.html @@ -0,0 +1,14 @@ + + + + + +Basic usage | GmapVue Docs + + + + + +
+ + \ No newline at end of file diff --git a/docs/category/components-1/index.html b/docs/category/components-1/index.html new file mode 100644 index 000000000..0c81b05d1 --- /dev/null +++ b/docs/category/components-1/index.html @@ -0,0 +1,14 @@ + + + + + +Components | GmapVue Docs + + + + + + + + \ No newline at end of file diff --git a/docs/category/components/index.html b/docs/category/components/index.html new file mode 100644 index 000000000..44e67e89b --- /dev/null +++ b/docs/category/components/index.html @@ -0,0 +1,14 @@ + + + + + +Components | GmapVue Docs + + + + + + + + \ No newline at end of file diff --git a/docs/category/developers-1/index.html b/docs/category/developers-1/index.html new file mode 100644 index 000000000..b86144115 --- /dev/null +++ b/docs/category/developers-1/index.html @@ -0,0 +1,14 @@ + + + + + +Developers | GmapVue Docs + + + + + + + + \ No newline at end of file diff --git a/docs/category/developers/index.html b/docs/category/developers/index.html new file mode 100644 index 000000000..8dbc0057f --- /dev/null +++ b/docs/category/developers/index.html @@ -0,0 +1,14 @@ + + + + + +Developers | GmapVue Docs + + + + + + + + \ No newline at end of file diff --git a/docs/category/guide-1/index.html b/docs/category/guide-1/index.html new file mode 100644 index 000000000..addb985a0 --- /dev/null +++ b/docs/category/guide-1/index.html @@ -0,0 +1,14 @@ + + + + + +Guide | GmapVue Docs + + + + + + + + \ No newline at end of file diff --git a/docs/category/guide/index.html b/docs/category/guide/index.html new file mode 100644 index 000000000..1e8424e16 --- /dev/null +++ b/docs/category/guide/index.html @@ -0,0 +1,14 @@ + + + + + +Guide | GmapVue Docs + + + + + + + + \ No newline at end of file diff --git a/docs/vue-2-version/changelog/index.html b/docs/vue-2-version/changelog/index.html new file mode 100644 index 000000000..64337e2ca --- /dev/null +++ b/docs/vue-2-version/changelog/index.html @@ -0,0 +1,272 @@ + + + + + +Changelog | GmapVue Docs + + + + + +

Changelog

3.5.2 (2022-03-12)

+

Bug Fixes

+
    +
  • gmap-vue: fix mapped props and kml-layer component (2cc7157)
  • +
  • gmap-vue: move from webpack to rollup and make differente builds (dbafc84), closes #231
  • +
+

3.5.1 (2022-03-03)

+

Bug Fixes

+
    +
  • gmap-vue: add mapped props to cluster-icon component (f008a35)
  • +
+

3.5.0 (2022-03-03)

+

Features

+
    +
  • gmap-vue: add render, on-cluster-click and options props to cluster component (8552070)
  • +
+

3.4.5 (2022-03-03)

+

Bug Fixes

+
    +
  • gmap-vue: add missing options on marker-clusterer constructor (7b4d573), closes #255
  • +
+

3.4.4 (2022-03-02)

+

Bug Fixes

+
    +
  • gmap-vue: set default vallue of contentn prop to undefined (bee86ad), closes #254
  • +
+

3.4.3 (2022-02-21)

+

Bug Fixes

+
    +
  • gmap-vue: add prop content to info-window component (29dface)
  • +
+

3.4.2 (2022-02-19)

+

Bug Fixes

+
    +
  • gmap-vue: add missing props to all shapes for drawing over the map (c39c500), closes #138
  • +
+

3.4.1 (2022-02-18)

+

Bug Fixes

+
    +
  • gmap-vue: change repaint method by render (4d7b7c9), closes #247
  • +
  • gmap-vue: clear interval when callback was successfully called (302c6e1)
  • +
+

3.4.0 (2022-02-16)

+

Features

+
    +
  • gmap-vue: update kml-layer adding all options as props (d8cb91f), closes #148
  • +
+

3.3.0 (2022-02-16)

+

Features

+
    +
  • gmap-vue: add dynamic loading for google maps api (7825dba), closes #239
  • +
+

3.2.0 (2022-02-15)

+

Features

+
    +
  • gmap-vue: auto detect when google maps api is loaded (93a9ecc)
  • +
+

3.1.0 (2022-02-15)

+

Features

+
    +
  • gmap-vue: emit update:position event on markers (6a34bb7), closes #14
  • +
+

3.0.0 (2022-02-13)

+

Features

+
    +
  • gmap-vue: add custom callback option to config (b8409e3), closes #143
  • +
+

BREAKING CHANGES

+
    +
  • gmap-vue: reuse existing google maps api and rename functions
  • +
+

2.0.4 (2022-02-11)

+

Bug Fixes

+
    +
  • gmap-vue: fix fields error on autocomplete component (a6b8712), closes #118
  • +
+

2.0.3 (2022-02-09)

+

Bug Fixes

+
    +
  • gmap-vue: fix error loading cluster (a2cb9ba), closes #234
  • +
+

2.0.2 (2021-11-27)

+

Bug Fixes

+
    +
  • docs: fix documentation issues with webpack config and build (1dfed13)
  • +
  • docs: fix vuepress alert on main readme (ad57f64)
  • +
+

Change Log

+

2.0.1 (2021-11-27)

+

Bug Fixes

+
    +
  • docs: update documentation with the last changes (1caf43f)
  • +
  • gmap-vue: fix build errors on the plugin (dc70306), closes #226
  • +
  • gmap-vue: remove semantic-release-monorepo (854ebd2)
  • +
+

2.0.0 (2021-11-24) [DEPRECATED]

+

Bug Fixes

+
    +
  • +

    all: split build process in two steps and remove lerna (6d7f779)

    +
  • +
  • +

    all: update vuejs version to the latest one (e22b276)

    +
  • +
  • +

    docs: add exact webpack 4 to docs to avoid vuepress build errors (797d92e)

    +
  • +
  • +

    docs: add webpack 4 to documentation to solve vuepress build errors (0ade630)

    +
  • +
  • +

    docs: wip on documentation and gmap vue (eb777dc)

    +
  • +
  • +

    documentation: add to way events for circle component (774f287)

    +
  • +
  • +

    documentation: change guide menu order (6e2bbfb)

    +
  • +
  • +

    documentation: fix documentation for autocomplete and circle (a289c12)

    +
  • +
  • +

    documentation: remove unused file (d15ebd8)

    +
  • +
  • +

    documentation: update documentation for GmapCircle component (405abd6)

    +
  • +
  • +

    documentation: update documentation of GmapCluster (b06464c)

    +
  • +
  • +

    documentation: upgrade snyk from 1.370.1 to 1.372.0 (#85) (916cb2b)

    +
  • +
  • +

    documentation: upgrade vuepress from 1.5.4 to 1.6.0 (#108) (dac60ad)

    +
  • +
  • +

    gmap-vue: add core-js and regenerator-runtime to use new features (fd59848)

    +
  • +
  • +

    gmap-vue: add description for props (63e18f4)

    +
  • +
  • +

    gmap-vue: fix linter errors (640000a)

    +
  • +
  • +

    gmap-vue: fix linter errors on test and examples folder (4479404)

    +
  • +
  • +

    gmap-vue: fix ref conflict on autocomplete component (#101) (0471e32)

    +
  • +
  • +

    gmap-vue: fix some code styles and linter rules (03540f7)

    +
  • +
  • +

    gmap-vue: fix tests and styles (b06aa81)

    +
  • +
  • +

    gmap-vue: remove independen helper function files (c08cbb8)

    +
  • +
  • +

    gmap-vue: remove unnecesary async/await (1fba907)

    +
  • +
  • +

    gmap-vue: remove unnecesary style block (3b2b87a)

    +
  • +
  • +

    gmap-vue: replace deprecated uglyfy plugin for terser plugin (ac74777)

    +
  • +
  • +

    gmap-vue: update link to source code (f4c3dce)

    +
  • +
  • +

    gmap-vue: update mappedProps name (f439eab)

    +
  • +
  • +

    gmap-vue: use async instead promise (af5da48)

    +
  • +
  • +

    packages/documentation/package.json & packages/documentation/package-lock.json to reduce vulnerabilities (c2a8b0a)

    +
  • +
  • +

    root: add content for need helps and vulnerability issue templates (aed11bc)

    +
  • +
  • +

    root: moving to semantic-release instead of using lerna version (9dae26f)

    +
  • +
  • +

    tmp: add incomplete work to the branch (db4d4b0)

    +
  • +
  • +

    upgrade @google/markerclustererplus from 5.1.0 to 5.1.3 (909eca9)

    +
  • +
  • +

    upgrade snyk from 1.372.0 to 1.373.1 (#87) (0431d1b)

    +
  • +
  • +

    upgrade snyk from 1.373.1 to 1.401.0 (deb8c72)

    +
  • +
  • +

    upgrade vuepress from 1.5.3 to 1.5.4 (#91) (0125598)

    +
  • +
  • +

    fix(gmap-vue)!: change to use default slot and fallback content (d53cbbe)

    +
  • +
+

Features

+
    +
  • all: remove unnecesary files and upgrade dependcies (1efc34e)
  • +
  • all: update marker component and its documentation (4ee095c)
  • +
  • docs: add link to github repo in the header menu (d906345)
  • +
  • docs: update and improve documentation (f3f999d)
  • +
  • documentation: add documentation for circle component (01986fa)
  • +
  • documentation: add documentation for cluster component (c6b93ab)
  • +
  • documentation: update and unify docs for autocomplete component (41702bd)
  • +
  • gmap-vue: add cluster.vue component and remove cluster.js (3398d5f)
  • +
  • gmap-vue: move drawing-manager,heatmap and info-window to vue files (66d8064)
  • +
  • gmap-vue: rename all components to follow vue linter rules (c2df328)
  • +
  • gmap-vue: update kml-layer component to a vue file (ca4056a)
  • +
  • gmap-vue: upgrade map.vue (38fe7c4)
  • +
  • gmap-vue: upgrade markerclustererplus (e2aebb3)
  • +
  • gmap-vue: upgrade markerclustererplus (e64eafa)
  • +
+

BREAKING CHANGES

+
    +
  • we remove the slot input and use the default one
  • +
+

1.5.0 (2020-10-31)

+

1.4.1 (2020-10-30)

+

Note: Version bump only for package gmap-vue

+

1.4.0 (2020-08-09)

+

Bug Fixes

+
    +
  • all: update vuejs version to the latest one (e22b276)
  • +
  • gmap-vue: fix hit and drawer map components and examples (#56) (#57) (778a927), closes #44 #44
  • +
  • gmap-vue: fix tests and styles (b06aa81)
  • +
+

1.2.1 (2020-08-03)

+

1.2.0 (2020-08-03)

+

Features

+
    +
  • gmap-vue: add a drawing manager component (#19) (d7afa94)
  • +
  • gmap-vue: add a heatmap layer component (#8) (5d7d9c0)
  • +
+

1.3.0 (2020-08-08)

+

Bug Fixes

+
    +
  • all: update vuejs version to the latest one (50ffde7)
  • +
  • gmap-vue: fix hit and drawer map components and examples (#56) (#57) (778a927), closes #44 #44
  • +
  • gmap-vue: fix tests and styles (d014f18)
  • +
+

1.2.1 (2020-08-03)

+

1.2.0 (2020-08-03)

+

Features

+
    +
  • gmap-vue: add a drawing manager component (#19) (d7afa94)
  • +
  • gmap-vue: add a heatmap layer component (#8) (5d7d9c0)
  • +
+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/components/autocomplete-input/index.html b/docs/vue-2-version/code/components/autocomplete-input/index.html new file mode 100644 index 000000000..f83d1f070 --- /dev/null +++ b/docs/vue-2-version/code/components/autocomplete-input/index.html @@ -0,0 +1,25 @@ + + + + + +autocomplete-input | GmapVue Docs + + + + + +

GmapAutocomplete

+
+

Autocomplete component

+
+

[See](source code)

+

Props

+
Prop nameDescriptionTypeValuesDefault
boundsMap bounds this is an LatLngBounds
object builded with
@value new google.maps.LatLngBounds(...)
@see Map Bounds
object-undefined
componentRestrictionsRestrict the search to a specific country
@value \{[key: string]: string\}
@see componentRestrictions
object-undefined
typesMap types this is an array of strings
@value string[]
@see Map Bounds
array-undefined
selectFirstOnEnterSelect the first result in the list when press enter keyboardbooleantrue, falsefalse
slotRefNamethe unique ref set to the component passed in the slot inputstring-'input'
childRefNameThe name of the ref to obtain the html input element
if its a child of component in the slot input
very useful whe we use a component like v-text-field of vuetify
that has a 'input' ref pointing to the final html input element
string-'input'
optionsOther options that you can pass to the Google Mapas
Autocomplete API
@see Options
objectgeocode, address, regionsundefined
setFieldsToTo avoid paying for data that you don't need,
be sure to use Autocomplete.setFields() to specify
only the place data that you will use.
@see Place information
@see setFields
@see PlaceResult
array-null
+

Events

+
Event namePropertiesDescription
place_changedplace object - this.$autocomplete.getPlace()Place change event
+

Slots

+
NameDescriptionBindings
defaultUsed to set your custom component for the input, eg: v-text-field.

+
+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/components/circle-shape/index.html b/docs/vue-2-version/code/components/circle-shape/index.html new file mode 100644 index 000000000..fb37afd41 --- /dev/null +++ b/docs/vue-2-version/code/components/circle-shape/index.html @@ -0,0 +1,23 @@ + + + + + +circle-shape | GmapVue Docs + + + + + +

GmapCircle

+
+

Circle component

+
+

}

+

[See](source code) +,[See](official reference)

+

Props

+
Prop nameDescriptionTypeValuesDefault
centerThe center of the Circle.
@value { lat: 41.878, lng: -87.629 }
@see Circle simple
object-
radiusThe radius in meters on the Earth's surface.
@value 10
@see Circle simple
number-10
clickableIndicates whether this Polygon handles mouse events. Defaults to true.
@value true, false
@see Circle draggable
boolean-false
draggableIf set to true, the user can drag this circle over the map. Defaults to false.
@value true, false
@see Circle simple
boolean-false
editableIf set to true, the user can edit this circle by dragging the control points shown at the center and around the circumference of the circle. Defaults to false.
@value true, false
@see Circle simple
boolean-false
fillColorThe fill color. All CSS3 colors are supported except for extended named colors.
@value '#000'
@see Circle editable
string-''
fillOpacityThe fill opacity between 0.0 and 1.0
@value 1
@see Circle editable
number-1
strokeColorThe stroke color. All CSS3 colors are supported except for extended named colors.
@value '#000'
@see Circle editable
string-''
strokeOpacityThe stroke opacity between 0.0 and 1.0.
@value 1
@see Circle editable
number-1
strokePositionThe stroke position. Defaults to CENTER.
@value 1
@see Circle editable
@see StrokePosition constant
number-0
strokeWeightThe stroke width in pixels.
@value 1
@see Circle editable
number-1
visibleWhether this polyline is visible on the map. Defaults to true.
@value 1
@see Circle editable
boolean-true
optionsThe Google Maps circle options
@value {
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35,
map,
center: citymap[city].center,
radius: Math.sqrt(citymap[city].population) * 100,
}
@see Circle simple
object-undefined
+
+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/components/cluster-icon/index.html b/docs/vue-2-version/code/components/cluster-icon/index.html new file mode 100644 index 000000000..95347c299 --- /dev/null +++ b/docs/vue-2-version/code/components/cluster-icon/index.html @@ -0,0 +1,25 @@ + + + + + +cluster-icon | GmapVue Docs + + + + + +

GmapCluster

+
+

Cluster component

+
+

[See](source code) +,[See](Official documentation) +,[See](Marker clusterer)

+

Props

+
Prop nameDescriptionTypeValuesDefault
algorithmAn algorithm to cluster markers. Default is SuperClusterAlgorithm. Must provide a
calculate method accepting AlgorithmInput and returning an array of Cluster.
@see algorithm
objectundefinedundefined
onClusterClickFunction to run when the user clicks the cluster.
@see onClusterClick
funcundefinedundefined
rendererAn object that converts a Cluster into a google.maps.Marker. Default is DefaultRenderer.
@see renderer
objectundefinedundefined
optionsOther options that you can pass to the MarkerClustererobjectundefinedundefined
+

Slots

+
NameDescriptionBindings
defaultUsed to set your cluster
+
+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/components/drawing-manager/index.html b/docs/vue-2-version/code/components/drawing-manager/index.html new file mode 100644 index 000000000..82b32f67d --- /dev/null +++ b/docs/vue-2-version/code/components/drawing-manager/index.html @@ -0,0 +1,44 @@ + + + + + +drawing-manager | GmapVue Docs + + + + + +

GmapDrawingManager

+
+

DrawingManager component

+
+

[See](source code) +,[See](Official documentation) +,[See](Official reference)

+

Props

+
Prop nameDescriptionTypeValuesDefault
circleOptionsThe circle options
@see circleOptions interface
object-undefined
markerOptionsThe marker options
@see markerOptions interface
object-undefined
polygonOptionsThe polygon options
@see polygonOptions interface
object-undefined
polylineOptionsThe polyline options
@see polylineOptions interface
object-undefined
rectangleOptionsThe rectangle options
@see rectangleOptions interface
object-undefined
positionThe position of the toolbar
Possible values: 'TOP_CENTER', 'TOP_LEFT', 'TOP_RIGHT', 'LEFT_TOP', 'RIGHT_TOP', 'LEFT_CENTER',<br/>'RIGHT_CENTER', 'LEFT_BOTTOM', 'RIGHT_BOTTOM', 'BOTTOM_CENTER', 'BOTTOM_LEFT', 'BOTTOM_RIGHT'
string-''
shapesAn array of shapes that you can set to render in the map and saves on it the new shapes that you add.array-
+

Methods

+

setDrawingMode

+
+

The setDrawingMode method is binded into the default component slot

+
+

Params

+
Param nameTypeDescription
modestringmode - Possible values 'marker', 'circle', 'polygon', 'polyline', 'rectangle', null
+

Return

+
TypeDescription
void
+

deleteSelection

+
+

The deleteSelection method is binded into the default component slot

+
+

Params

+
Param nameTypeDescription
mixedIt doesn't requires any parameter
+

Return

+
TypeDescription
void
+

Events

+
Event namePropertiesDescription
update:shapesplace array - this.finalShapesupdate:shapes event
+

Slots

+
NameDescriptionBindings
defaultUsed to set your drawing manager
+
+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/components/heatmap-layer/index.html b/docs/vue-2-version/code/components/heatmap-layer/index.html new file mode 100644 index 000000000..dafa12a42 --- /dev/null +++ b/docs/vue-2-version/code/components/heatmap-layer/index.html @@ -0,0 +1,22 @@ + + + + + +heatmap-layer | GmapVue Docs + + + + + +

HeatmapLayer

+
+

HeatmapLayer component

+
+

[See](source code) +,[See](Official documentation)

+

Props

+
Prop nameDescriptionTypeValuesDefault
optionsExtra options that you want to pass to the componentobject-() => {}
dataThe heat map data, is an array of new google.maps.LatLng,
@see heatmap options
@example [new google.maps.LatLng(37.782, -122.447)]
array-undefined
+
+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/components/info-window/index.html b/docs/vue-2-version/code/components/info-window/index.html new file mode 100644 index 000000000..91107a3b1 --- /dev/null +++ b/docs/vue-2-version/code/components/info-window/index.html @@ -0,0 +1,25 @@ + + + + + +info-window | GmapVue Docs + + + + + +

Info-Window

+
+

InfoWindow component

+
+

[See](source code) +,[See](Official documentation) +,[See](Official reference)

+

Props

+
Prop nameDescriptionTypeValuesDefault
contentNOTE: This prop overrides the content of the default slot, use only one of them, not both at the same time
Content to display in the InfoWindow. This can be an HTML element, a plain-text string, or a string containing HTML. The InfoWindow will be sized according to the content. To set an explicit size for the content, set content to be a HTML element with that size.
@value undefined
@see InfoWindow content
string|object-undefined
openedDetermines if the info-window is open or notboolean-true
positionContains the LatLng at which this info window is anchored.
Note: An InfoWindow may be attached either to a Marker object
(in which case its position is based on the marker's location)
or on the map itself at a specified LatLng.

The LatLng at which to display this InfoWindow. If the InfoWindow is opened with an anchor, the anchor's position will be used instead.
@value undefined
@type LatLng|LatLngLiteral
@see InfoWindow position
object-undefined
zIndexAll InfoWindows are displayed on the map in order of their zIndex, with higher values displaying in front of InfoWindows with lower values. By default, InfoWindows are displayed according to their latitude, with InfoWindows of lower latitudes appearing in front of InfoWindows at higher latitudes. InfoWindows are always displayed in front of markers.
@value 0
@see InfoWindow position
number-0
optionsExtra options that you want to pass to the componentobject-undefined
+

Slots

+
NameDescriptionBindings
defaultUsed to set your info window.
+
+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/components/kml-layer/index.html b/docs/vue-2-version/code/components/kml-layer/index.html new file mode 100644 index 000000000..a60de0bff --- /dev/null +++ b/docs/vue-2-version/code/components/kml-layer/index.html @@ -0,0 +1,23 @@ + + + + + +kml-layer | GmapVue Docs + + + + + +

Kml-Layer

+
+

KmlLayer component

+
+

[See](source code) +,[See](Official documentation) +,[See](Official reference)

+

Props

+
Prop nameDescriptionTypeValuesDefault
clickableIf true, the layer receives mouse events. Default value is true.
@see KmlLayerOptions interface
boolean-true
mapSpecifies the Map on which to render the KmlLayer. You can hide a KmlLayer by setting this value to null within the setMap() method
@see KmlLayerOptions interface
object-undefined
preserveViewportBy default, the input map is centered and zoomed to the bounding box of the contents of the layer. If this option is set to true, the viewport is
left unchanged, unless the map's center and zoom were never set.
@see KmlLayerOptions interface
boolean-false
screenOverlaysWhether to render the screen overlays. Default true.
@see KmlLayerOptions interface
boolean-false
suppressInfoWindowsSuppress the rendering of info windows when layer features are clicked.
@see KmlLayerOptions interface
boolean-undefined
urlThe URL of the KML document to display.
@see KmlLayerOptions interface
string-''
zIndexThe z-index of the layer.
@see KmlLayerOptions interface
number-undefined
optionsMore options that you can pass to the component
@value boolean
object-undefined
+
+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/components/map-layer/index.html b/docs/vue-2-version/code/components/map-layer/index.html new file mode 100644 index 000000000..58885bc99 --- /dev/null +++ b/docs/vue-2-version/code/components/map-layer/index.html @@ -0,0 +1,85 @@ + + + + + +map-layer | GmapVue Docs + + + + + +

Map

+
+

Map component

+
+

[See](source code) +,[See](Official documentation) +,[See](Official reference)

+

Props

+
Prop nameDescriptionTypeValuesDefault
resizeBusundefined-
centerThe initial Map center.
@see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions
object-
zoomThe initial Map zoom level. Valid values: Integers between zero, and up to the supported maximum zoom level.
@see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions
number-undefined
headingThe heading for aerial imagery in degrees measured clockwise from cardinal direction North. Headings are snapped to the nearest available angle for which imagery is available.
@see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions
number-undefined
mapTypeIdThe initial Map mapTypeId. Defaults to ROADMAP.
@see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions
string-'roadmap'
tiltFor vector maps, sets the angle of incidence of the map. The allowed values are restricted depending on the zoom level of the map. For raster maps, controls the automatic switching behavior for the angle of incidence of the map. The only allowed values are 0 and 45. The value 0 causes the map to always use a 0° overhead view regardless of the zoom level and viewport. The value 45 causes the tilt angle to automatically switch to 45 whenever 45° imagery is available for the current zoom level and viewport, and switch back to 0 whenever 45° imagery is not available (this is the default behavior). 45° imagery is only available for satellite and hybrid map types, within some locations, and at some zoom levels. Note: getTilt returns the current tilt angle, not the value specified by this option. Because getTilt and this option refer to different things, do not bind() the tilt property; doing so may yield unpredictable effects.
@see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions
number-undefined
optionsExtra options that you want pass to the componentobject-undefined
+

Methods

+

resize

+
+

This method trigger the resize event of Google Maps

+
+

Params

+
Param nameTypeDescription
undefined
+

Return

+
TypeDescription
void
+

resizePreserveCenter

+
+

Preserve the previous center when resize the map

+
+

Params

+
Param nameTypeDescription
undefined
+

Return

+
TypeDescription
void
+

panBy

+
+

Changes the center of the map by the given distance in pixels. If the distance is less than both the width and height of the map, the transition will be smoothly animated. Note that the map coordinate system increases from west to east (for x values) and north to south (for y values).

+
+

Params

+
Param nameTypeDescription
numberx - Number of pixels to move the map in the x direction.
numbery - Number of pixels to move the map in the y direction.
+

Return

+
TypeDescription
void
+

panTo

+
+

Changes the center of the map to the given LatLng. If the change is less than both the width and height of the map, the transition will be smoothly animated.

+
+

Params

+
Param nameTypeDescription
latLngunionThe new center latitude/longitude of the map. (types LatLng|LatLngLiteral)
+

Return

+
TypeDescription
void
+

panToBounds

+
+

Pans the map by the minimum amount necessary to contain the given LatLngBounds. It makes no guarantee where on the map the bounds will be, except that the map will be panned to show as much of the bounds as possible inside {currentMapSizeInPx} - {padding}. For both raster and vector maps, the map's zoom, tilt, and heading will not be changed.

+
+

Params

+
Param nameTypeDescription
latLngBoundsunionThe bounds to pan the map to. (types: LatLngBounds|LatLngBoundsLiteral)
union[padding] - optional Padding in pixels. A number value will yield the same padding on all 4 sides. The default value is 0. (types: number|Padding)
+

Return

+
TypeDescription
void
+

fitBounds

+
+

Sets the viewport to contain the given bounds. +Note: When the map is set to display: none, the fitBounds function reads the map's size as 0x0, and therefore does not do anything. To change the viewport while the map is hidden, set the map to visibility: hidden, thereby ensuring the map div has an actual size. For vector maps, this method sets the map's tilt and heading to their default zero values.

+
+

Params

+
Param nameTypeDescription
boundsunionBounds to show. (types: LatLngBounds|LatLngBoundsLiteral)
union[padding] - optional Padding in pixels. The bounds will be fit in the part of the map that remains after padding is removed. A number value will yield the same padding on all 4 sides. Supply 0 here to make a fitBounds idempotent on the result of getBounds. (types: number|Padding)
+

Return

+
TypeDescription
void
+

getRecycleKey

+
+

Get the recycle key of the map

+
+

Params

+
Param nameTypeDescription
undefined
+

Return

+
TypeDescription
void
+

Events

+
Event namePropertiesDescription
center_changedThis event is fired when the map center property changes. It sends the position displayed at the center of the map. If the center or bounds have not been set then the result is undefined. (types: LatLng|undefined)
zoom_changedThis event is fired when the map zoom property changes. It sends the zoom of the map. If the zoom has not been set then the result is undefined. (types: number|undefined)
bounds_changedThis event is fired when the viewport bounds have changed. It sends The lat/lng bounds of the current viewport.
+

Slots

+
NameDescriptionBindings
defaultThe default slot is wrapped in a class that sets display: none; so by default any component you add to your map will be invisible. This is ok for most of the supplied components that interact directly with the Google map object, but it's not good if you want to bring up things like toolboxes, etc.
visibleThis slot must be used if you want to display content within the responsive wrapper for the map.
+
+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/components/marker-icon/index.html b/docs/vue-2-version/code/components/marker-icon/index.html new file mode 100644 index 000000000..5eecbb42d --- /dev/null +++ b/docs/vue-2-version/code/components/marker-icon/index.html @@ -0,0 +1,27 @@ + + + + + +marker-icon | GmapVue Docs + + + + + +

Marker

+
+

Marker component

+
+

[See](source code) +,[See](Official documentation) +,[See](Official reference)

+

Props

+
Prop nameDescriptionTypeValuesDefault
animationWhich animation to play when marker is added to a map.
@see https://developers.google.com/maps/documentation/javascript/reference/marker
number-undefined
attributionThis property was not found on the Googole Maps documentation, but it was defined in the previous version of this component.
Any suggestion is welcome here.
object-undefined
clickableIf true, the marker receives mouse and touch events. Default value is true.
@see https://developers.google.com/maps/documentation/javascript/reference/marker
boolean-true
cursorMouse cursor type to show on hover.
@see https://developers.google.com/maps/documentation/javascript/reference/marker
string-undefined
draggableIf true, the marker can be dragged. Default value is false.
@see https://developers.google.com/maps/documentation/javascript/reference/marker
boolean-false
iconIcon for the foreground. If a string is provided, it is treated as though it were an Icon with the string as url.
Its type can be string|Icon|Symbol optional
@see Icon type
@see Symbol type
@see https://developers.google.com/maps/documentation/javascript/reference/marker
string|object-undefined
labelAdds a label to the marker. A marker label is a letter or number that appears inside a marker. The label can either be a string, or a MarkerLabel object. If provided and MarkerOptions.title is not provided, an accessibility text (e.g. for use with screen readers) will be added to the marker with the provided label's text. Please note that the label is currently only used for accessibility text for non-optimized markers.
@see https://developers.google.com/maps/documentation/javascript/reference/marker
string|object-undefined
opacityA number between 0.0, transparent, and 1.0, opaque.
@see https://developers.google.com/maps/documentation/javascript/reference/marker
number-1
optionsExtra options passed to this component.object-undefined
placeThis property was not found on the Googole Maps documentation, but it was defined in the previous version of this component.
Any suggestion is welcome here.
object-undefined
positionMarker position. The position is required to display the marker and can be provided with Marker.setPosition if not provided at marker construction.
@see https://developers.google.com/maps/documentation/javascript/reference/marker
object-undefined
shapeImage map region definition used for drag/click.
@see MarkerShape type
@see https://developers.google.com/maps/documentation/javascript/reference/marker
object-undefined
titleRollover text. If provided, an accessibility text (e.g. for use with screen readers) will be added to the marker with the provided value. Please note that the title is currently only used for accessibility text for non-optimized markers.
@see https://developers.google.com/maps/documentation/javascript/reference/marker
string-undefined
visibleIf true, the marker is visible.
@see https://developers.google.com/maps/documentation/javascript/reference/marker
boolean-true
zIndexAll markers are displayed on the map in order of their zIndex, with higher values displaying in front of markers with lower values. By default, markers are displayed according to their vertical position on screen, with lower markers appearing in front of markers further up the screen.
@see https://developers.google.com/maps/documentation/javascript/reference/marker
number-undefined
+

Events

+
Event namePropertiesDescription
update:positionposition Object - Object with lat and lng values, eg: { lat: 10.0, lng: 10.0 }An event to detect when a position changes
+

Slots

+
NameDescriptionBindings
defaultDefault slot of the component.
+
+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/components/place-input/index.html b/docs/vue-2-version/code/components/place-input/index.html new file mode 100644 index 000000000..aea1d9aba --- /dev/null +++ b/docs/vue-2-version/code/components/place-input/index.html @@ -0,0 +1,29 @@ + + + + + +place-input | GmapVue Docs + + + + + +

place-input


+

title: PlaceInput

+

PlaceInput

+
+

Deprecated true

+
+
+

PlaceInput component

+
+

[See](source code) +,[See](Map Bounds)

+

Props

+
Prop nameDescriptionTypeValuesDefault
boundsMap bounds this is an LatLngBounds
object builded with
@value new google.maps.LatLngBounds(...)
@see Map Bounds
object-undefined
defaultPlaceA default value for the html input
@value string
string-''
componentRestrictionsRestrict the search to a specific country
@value \{[key: string]: string\}
@see componentRestrictions
object-null
typesMap types this is an array of strings
@value string[]
@see Map Bounds
array-undefined
placeholderA placeholder for the html input
@value string
string-undefined
classNameA html class name for the html input
@value string
string-undefined
labelA label for the html input
@value string
string-null
selectFirstOnEnterIf true the first element on the list will be selected
when you press enter in the html input.
@value boolean
boolean-false
+

Events

+
Event namePropertiesDescription
place_changedplace object - this.$autocomplete.getPlace()Place change event
+
+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/components/polygon-shape/index.html b/docs/vue-2-version/code/components/polygon-shape/index.html new file mode 100644 index 000000000..ffe23ff14 --- /dev/null +++ b/docs/vue-2-version/code/components/polygon-shape/index.html @@ -0,0 +1,25 @@ + + + + + +polygon-shape | GmapVue Docs + + + + + +

GmapPolygon

+
+

Polygon component

+
+

[See](source code) +,[See](official docs) +,[See](official reference)

+

Props

+
Prop nameDescriptionTypeValuesDefault
deepWatchIf set true the object will be deep watched
@value boolean
boolean-false
clickableIndicates whether this Polygon handles mouse events. Defaults to true.
@value true, false
@see Polygon draggable
boolean-false
draggableIndicates if the polygon is draggable
@value true, false
@see Polygon dragable
boolean-false
editableIndicates if the polygon is editable
@value true, false
@see Polygon editable
boolean-false
fillColorThe fill color. All CSS3 colors are supported except for extended named colors.
@value '#000'
@see Polygon editable
string-''
fillOpacityThe fill opacity between 0.0 and 1.0
@value 1
@see Polygon editable
number-1
strokeColorThe stroke color. All CSS3 colors are supported except for extended named colors.
@value '#000'
@see Polygon editable
string-''
strokeOpacityThe stroke opacity between 0.0 and 1.0.
@value 1
@see Polygon editable
number-1
strokePositionThe stroke position. Defaults to CENTER.
@value 1
@see Polygon editable
@see StrokePosition constant
number-0
strokeWeightThe stroke width in pixels.
@value 1
@see Polygon editable
number-1
visibleWhether this polyline is visible on the map. Defaults to true.
@value 1
@see Polygon editable
boolean-true
optionsMore options that you can pass to the component
@value boolean
object-undefined
pathIndicates if the polygon is editable
@value Array
@see Polygon path
array-undefined
pathsIndicates if the polygon is editable
@value Array
@see Polygon paths
array-undefined
+

Events

+
Event namePropertiesDescription
paths_changedpaths array - this.$polygonObject.getPaths() |An event to detect when a paths changes
path_changedpath array - this.$polygonObject.getPath()### path_changed (undefined)

An event to detect when a path change
+
+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/components/polyline-shape/index.html b/docs/vue-2-version/code/components/polyline-shape/index.html new file mode 100644 index 000000000..ea2b7dbe8 --- /dev/null +++ b/docs/vue-2-version/code/components/polyline-shape/index.html @@ -0,0 +1,25 @@ + + + + + +polyline-shape | GmapVue Docs + + + + + +

GmapPolyline

+
+

PolyLine component

+
+

[See](source code) +,[See](official docs) +,[See](official reference)

+

Props

+
Prop nameDescriptionTypeValuesDefault
deepWatchIf set true the object will be deep watched
@value boolean
boolean-false
clickableIndicates whether this Polygon handles mouse events. Defaults to true.
@value true, false
@see Polyline draggable
boolean-false
draggableIndicates if the polyline is draggable
@value true, false
@see Polyline draggable
boolean-
editableIndicates if the polygon is editable
@value true, false
@see Polyline editable
boolean-
strokeColorThe stroke color. All CSS3 colors are supported except for extended named colors.
@value '#000'
@see Polyline editable
string-''
strokeOpacityThe stroke opacity between 0.0 and 1.0.
@value 1
@see Polyline editable
number-1
strokeWeightThe stroke width in pixels.
@value 1
@see Polyline editable
number-1
visibleWhether this polyline is visible on the map. Defaults to true.
@value 1
@see Polyline editable
boolean-true
optionsMore options that you can pass to the component
@value boolean
object-undefined
pathIndicates if the polygon is editable
@value Array
@see Polyline path
array-undefined
+

Events

+
Event namePropertiesDescription
path_changedpath array - this.$polygonObject.getPath()An event to detect when a path change
+
+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/components/rectangle-shape/index.html b/docs/vue-2-version/code/components/rectangle-shape/index.html new file mode 100644 index 000000000..af4428efb --- /dev/null +++ b/docs/vue-2-version/code/components/rectangle-shape/index.html @@ -0,0 +1,23 @@ + + + + + +rectangle-shape | GmapVue Docs + + + + + +

GmapRectangle

+
+

Rectangle component

+
+

[See](source code) +,[See](official docs) +,[See](official reference)

+

Props

+
Prop nameDescriptionTypeValuesDefault
boundsThe bounds.
@value object
@type LatLngBounds|LatLngBoundsLiteral
@see Rectangle bounds
object-undefined
clickableIndicates whether this Polygon handles mouse events. Defaults to true.
@value true, false
@see Rectangle draggable
boolean-false
draggableIf set to true, the user can drag this rectangle over the map. Defaults to false.
@value boolean
@see Rectangle draggable
boolean-false
editableIf set to true, the user can edit this rectangle by dragging the control points shown at the corners and on each edge. Defaults to false.
@value boolean
@see Rectangle editable
boolean-false
fillColorThe fill color. All CSS3 colors are supported except for extended named colors.
@value '#000'
@see Rectangle editable
string-''
fillOpacityThe fill opacity between 0.0 and 1.0
@value 1
@see Rectangle editable
number-1
strokeColorThe stroke color. All CSS3 colors are supported except for extended named colors.
@value '#000'
@see Rectangle editable
string-''
strokeOpacityThe stroke opacity between 0.0 and 1.0.
@value 1
@see Rectangle editable
number-1
strokePositionThe stroke position. Defaults to CENTER.
@value 1
@see Rectangle editable
@see StrokePosition constant
number-0
strokeWeightThe stroke width in pixels.
@value 1
@see Rectangle editable
number-1
visibleWhether this polyline is visible on the map. Defaults to true.
@value 1
@see Rectangle editable
boolean-true
optionsMore options that you can pass to the component
@value boolean
object-undefined
+
+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/components/street-view-panorama/index.html b/docs/vue-2-version/code/components/street-view-panorama/index.html new file mode 100644 index 000000000..e6de5aea3 --- /dev/null +++ b/docs/vue-2-version/code/components/street-view-panorama/index.html @@ -0,0 +1,26 @@ + + + + + +street-view-panorama | GmapVue Docs + + + + + +

GmapStreetViewPanorama

+
+

Street View Panorama component

+
+

[See](source code) +,[See](official docs)

+

Props

+
Prop nameDescriptionTypeValuesDefault
resizeBusundefined-
zoomThe zoom of the panorama, specified as a number. A zoom of 0 gives a 180 degrees Field of View.
@value number
@see StreetViewPanorama zoom
number-undefined
povThe camera orientation, specified as heading and pitch, for the panorama.
@value object
@type StreetViewPov
@see StreetViewPanorama pov
object-undefined
positionThe LatLng position of the Street View panorama.
@value object
@type LatLng|LatLngLiteral
@see StreetViewPanorama position
object-undefined
panoThe panorama ID, which should be set when specifying a custom panorama.
@value string
@see StreetViewPanorama pano
string-undefined
motionTrackingWhether motion tracking is on or off. Enabled by default when the motion tracking control is present, so that the POV (point of view) follows the orientation of the device. This is primarily applicable to mobile devices. If motionTracking is set to false while motionTrackingControl is enabled, the motion tracking control appears but tracking is off. The user can tap the motion tracking control to toggle this option.
@value boolean
@see StreetViewPanorama motionTracking
boolean-
visibleIf true, the Street View panorama is visible on load.
@value boolean
@see StreetViewPanorama visible
boolean-true
optionsMore options that you can pass to the component
@value boolean
object-undefined
+

Events

+
Event namePropertiesDescription
position_changed
+

Slots

+
NameDescriptionBindings
defaultA default slot to render the street view panorama
+
+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/index.html b/docs/vue-2-version/code/index.html new file mode 100644 index 000000000..e2ac2cbca --- /dev/null +++ b/docs/vue-2-version/code/index.html @@ -0,0 +1,86 @@ + + + + + +GmapVue | GmapVue Docs + + + + + +

GmapVue

+

+

Documentation

+

The new documentation page is ready and it contains all examples for any component in the plugin.

+

You can use your own gmap key in order to test it in the live example section.

+

We have planed improve and grow all required documentation about the plugin.

+

Please follow next link to our documentation.

+

Vue-2 port of vue-google-maps

+

This is a fork of the popular vue2-google-maps. As the author of the library no longer commit to maintain the project, we forked it to develop and maintain the project.

+

CONTRIBUTORS NEEDED!

+

If you have time to contribute to a rather frequently used library, feel free to make a PR! +For more background, please refer to this issue.

+

What's urgently needed are:

+
    +
  1. Better automated tests
  2. +
  3. Better integration tests with the popular frameworks, especially Nuxt and Vue template
  4. +
  5. Better documentation (examples, recommendations)
  6. +
+

The above three will go a long way to keeping the project maintainable and contributable, and will address many of the open issues.

+

Breaking changes

+

v3.0.0

+
    +
  • autobindAllEvents config option was renamed to autoBindAllEvents
  • +
  • vueGoogleMapsInit name was renamed to GoogleMapsCallback
  • +
  • gmapApi function was renamed to getGoogleMapsAPI
  • +
  • MapElementMixin now is exported from components object instead of helpers object
  • +
  • customCallback config option was added to reuse existing Google Maps API that already loaded, eg from an HTML file
  • +
+

v2.0.0

+
    +
  • +

    All components were rewriting in SFC (.vue)

    +
  • +
  • +

    MarkerCluster was renamed to Cluster

    +
  • +
  • +

    @google/markerclustererplus was replace for @googlemaps/markerclusterer

    +
  • +
  • +

    The plugin exports two main objects:

    +
      +
    • components: it has all components and mountable mixin)
    • +
    • helpers: it has promise lazy factory function, gmapApi function and map element mixin
    • +
    +
  • +
  • +

    The plugin now exports by default the install function, this means that you can do the following

    +
  • +
  • +

    From v2.0.0 and above, the autocomplete component uses the default slot instead of the named input slot, from v1.5.0 the input slot on the autocomplete component still works.

    +
    import GmapVue from 'gmap-vue';
    +

    instead of

    +
    import * as GmapVue from 'gmap-vue';
    +
  • +
+

Installation

+

npm

+
npm install gmap-vue --save
+

yarn

+
yarn add gmap-vue
+

Manually

+

Just download dist/gmap-vue.js file and include it from your HTML.

+
<script src="./gmap-vue.js"></script>
+

jsdelivr

+

You can use a free CDN like jsdelivr to include this plugin in your html file

+
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>
+

unpkg

+

You can use a free CDN like unpkg to include this plugin in your html file

+
<script src="https://unpkg.com/gmap-vue@1.2.2/dist/gmap-vue.js"></script>
+
warning

Be aware that if you use this method, you cannot use TitleCase for your components and your attributes. +That is, instead of writing <GmapMap>, you need to write <gmap-map>.

+

Live example.

+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/main/index.html b/docs/vue-2-version/code/main/index.html new file mode 100644 index 000000000..83aee1b12 --- /dev/null +++ b/docs/vue-2-version/code/main/index.html @@ -0,0 +1,84 @@ + + + + + +main | GmapVue Docs + + + + + +

main

+

Members

+
GoogleMapsApi : Object | undefined

An independent Vue instance that helps us to know when the Google Maps API is loaded.

+

Constants

+
components : Object

Export all components and mixins

helpers : Object

Export all helpers

+

Functions

+
getGoogleMapsAPI()

This function helps you to get the Google Maps API +when its ready on the window object

gmapVuePluginInstallFn(Vue, options)

GmapVue install function

+ +

GoogleMapsApi : Object | undefined

+

An independent Vue instance that helps us to know when the Google Maps API is loaded.

+

Kind: global variable

+ +

components : Object

+

Export all components and mixins

+

Kind: global constant
+Properties

+
NameTypeDescription
HeatmapLayerObjectVue component HeatmapLayer
KmlLayerObjectVue component KmlLayer
MarkerObjectVue component Marker
PolylineObjectVue component Polyline
PolygonObjectVue component Polygon
CircleObjectVue component Circle
ClusterObjectVue component Cluster
RectangleObjectVue component Rectangle
DrawingManagerObjectVue component DrawingManager
InfoWindowObjectVue component InfoWindow
MapLayerObjectVue component MapLayer
PlaceInputObjectVue component PlaceInput
AutocompleteObjectVue component Autocomplete
StreetViewPanoramaObjectVue component StreetViewPanorama
MapElementMixinObjectVue component MapElementMixin
MountableMixinObjectVue component MountableMixin
+ +

helpers : Object

+

Export all helpers

+

Kind: global constant
+Properties

+
NameTypeDescription
initGoogleMapsApifunctionfunction to initialize the Google Maps API
MapElementFactoryfunctionfunction to initialize the Google Maps API
+ +

getGoogleMapsAPI()

+

This function helps you to get the Google Maps API +when its ready on the window object

+

Kind: global function

+ +

gmapVuePluginInstallFn(Vue, options)

+

GmapVue install function

+

Kind: global function

+
ParamTypeDefaultDescription
VueObjectthe vue instance
optionsObject | undefinedconfiguration object to initialize the GmapVue plugin
options.dynamicLoadbooleanfalseload the Google Maps API dynamically, if you set this to true the plugin doesn't load the Google Maps API
options.installComponentsbooleantrueinstall all components
options.autoBindAllEventsbooleanfalseauto bind all Google Maps API events
options.loadObject | undefinedoptions to configure the Google Maps API
options.load.keystringyour Google Maps API key
options.load.librariesstring"places"the Google Maps libraries that you will use eg: 'places,drawing,visualization'
options.load.vstring | undefinedthe Google Maps API version, default latest
options.load.callbackstring | undefined"GoogleMapsCallback"This must be ignored if have another callback that you need to run when Google Maps API is ready please use the customCallback option.
options.load.customCallbackstring | undefinedThis option was added on v3.0.0 but will be removed in the next major release. If you already have an script tag that loads Google Maps API and you want to use it set you callback in the customCallback option and our GoogleMapsCallback callback will execute your custom callback at the end; it must attached to the window object, is the only requirement.
+ + +

gmapVuePluginInstallFn~GoogleMapsApi

+

Update the global GoogleMapsApi. This will allow +components to use the google global reactively +via: +import { getGoogleMapsAPI } from 'gmap-vue' +export default { computed: { google: getGoogleMapsAPI } }

+

Kind: inner property of gmapVuePluginInstallFn

+ +

gmapVuePluginInstallFn~promiseLazyCreator : function

+

Use a lazy to only load the API when +a GMap component is loaded

+

Kind: inner constant of gmapVuePluginInstallFn

+ +

gmapVuePluginInstallFn~gmapApiPromiseLazy : function

+

The gmapApiPromiseLazy function to can wait until Google Maps API is ready

+

Kind: inner constant of gmapVuePluginInstallFn

+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/mixins/map-element/index.html b/docs/vue-2-version/code/mixins/map-element/index.html new file mode 100644 index 000000000..c5616b830 --- /dev/null +++ b/docs/vue-2-version/code/mixins/map-element/index.html @@ -0,0 +1,25 @@ + + + + + +map-element | GmapVue Docs + + + + + +

map-element

+ +

mapElementMixin

+

MapElementMixin

+

Add a inject object to inject $mapPromise and a provide function to the +component this function save the returned Google Maps object in the $map +property after the $mapPromise is resolved.

+

The mixin code

+
  export default {
inject: {
$mapPromise: { default: 'abcdef' },
},
provide() {
this.$mapPromise.then((map) => {
this.$map = map;
});

return {};
},
};
+

Kind: global class
+Properties

+
NameDescription
$mapPromiseThe map property that should return the $map.
Note: although this mixin is not "providing" anything, components' expect the $map property to be present on the component. In order for that to happen, this mixin must intercept the $mapPromise .then(() => ) first before its component does so. Since a provide() on a mixin is executed before a provide() on the component, putting this code in provide() ensures that the $map is already set by the time the component's provide() is called.
$mapThe Google map (valid only after the promise ($mapPromise) returns)
+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/mixins/mountable/index.html b/docs/vue-2-version/code/mixins/mountable/index.html new file mode 100644 index 000000000..374d2e229 --- /dev/null +++ b/docs/vue-2-version/code/mixins/mountable/index.html @@ -0,0 +1,25 @@ + + + + + +mountable | GmapVue Docs + + + + + +

mountable

+ +

mountableMixin

+

MountableMixin

+

Mixin for objects that are mounted by Google Maps Javascript API.

+

These are objects that are sensitive to element resize operations +so it exposes a property which accepts a bus

+

The mixin code:

+
  export default {
props: ['resizeBus'],

data() {
return {
_actualResizeBus: null,
};
},

created() {
if (typeof this.resizeBus === 'undefined') {
this.$data._actualResizeBus = this.$gmapDefaultResizeBus;
} else {
this.$data._actualResizeBus = this.resizeBus;
}
},

methods: {
_resizeCallback() {
this.resize();
},
_delayedResizeCallback() {
this.$nextTick(() => this._resizeCallback());
},
},

watch: {
resizeBus(newVal) {
this.$data._actualResizeBus = newVal;
},
'$data._actualResizeBus': function actualResizeBus(newVal, oldVal) {
if (oldVal) {
oldVal.$off('resize', this._delayedResizeCallback);
}
if (newVal) {
newVal.$on('resize', this._delayedResizeCallback);
}
},
},

destroyed() {
if (this.$data._actualResizeBus) {
this.$data._actualResizeBus.$off('resize', this._delayedResizeCallback);
}
},
};
+

Kind: global class
+Properties

+
NameTypeDescription
resizeBusfunction | undefinedVue props to set your custom resize bus function, otherwise it takes the default $gmapDefaultResizeBus
_actualResizeBusfunction | undefinedThe current default resize bus function, this should not be used outside of this mixin
+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/utils/factories/map-element/index.html b/docs/vue-2-version/code/utils/factories/map-element/index.html new file mode 100644 index 000000000..025f7e5f8 --- /dev/null +++ b/docs/vue-2-version/code/utils/factories/map-element/index.html @@ -0,0 +1,27 @@ + + + + + +map-element | GmapVue Docs + + + + + +

map-element

+

Functions

+
_assert(v, message)

Custom assert for local validation

mapElement(options)Object

A helper to build your own component for the plugin

+ +

_assert(v, message)

+

Custom assert for local validation

+

Kind: global function

+
ParamTypeDescription
vbooleanThe expression that should return a boolean value, if false the assertion fails
messagestringError message to be displayed
+ +

mapElement(options) ⇒ Object

+

A helper to build your own component for the plugin

+

Kind: global function
+Returns: Object - A component object that should be exported by default from a Vue component

+
ParamTypeDescription
optionsObject
options.mappedPropsObjectDefinitions of props
options.mappedProps.PROP.typeObjectValue type
options.mappedProps.PROP.twoWayBoolean- Whether the prop has a corresponding PROP_changed event
options.mappedProps.PROP.noBindBoolean- If true, do not apply the default bindProps / bindEvents. However it will still be added to the list of component props
options.propsObjectRegular Vue-style props. Note: must be in the Object form because it will be merged with the mappedProps
options.eventsObjectGoogle Maps API events that are not bound to a corresponding prop
options.nameStringe.g. polyline
options.ctrfunctionconstructor, e.g. google.maps.Polyline. However, since this is not generally available during library load, this becomes a function instead, e.g. () => google.maps.Polyline which will be called only after the API has been loaded default: () => String
options.ctrArgsfunctionIf the constructor in ctr needs to be called with arguments other than a single options object, e.g. for GroundOverlay, we call new GroundOverlay(url, bounds, options) then pass in a function that returns the argument list as an array default: (MappedProps, OtherVueProps) => Array Otherwise, the constructor will be called with an options object, with property and values merged from: 1. the options property, if any 2. a map property with the Google Maps 3. all the properties passed to the component in mappedProps
options.beforeCreatefunctionHook to modify the options passed to the initializer default: (Object) => Any
options.afterCreatefunctionHook called when default: (options.ctr, Object) => Any
+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/utils/factories/promise-lazy/index.html b/docs/vue-2-version/code/utils/factories/promise-lazy/index.html new file mode 100644 index 000000000..409ec71ef --- /dev/null +++ b/docs/vue-2-version/code/utils/factories/promise-lazy/index.html @@ -0,0 +1,53 @@ + + + + + +promise-lazy | GmapVue Docs + + + + + +

promise-lazy

+

Functions

+
createCallbackAndChecksIfMapIsLoaded(resolveFn, customCallback)

This function allow to auto detect an external load of the Google Maps API +or load it dynamically from our component.

getPromiseLazyCreatorFn(googleMapsApiInitializer, GoogleMapsApi)function

This function is a factory of the promise lazy creator +it helps you creating the function that will call the +Google Maps API in an async way

+ +

createCallbackAndChecksIfMapIsLoaded(resolveFn, customCallback)

+

This function allow to auto detect an external load of the Google Maps API +or load it dynamically from our component.

+

Kind: global function

+
ParamTypeDescription
resolveFnfunctionthe function that indicates to the plugin that Google Maps is loaded
customCallbackfunctionthe custom callback to execute when the plugin load. This option will be removed on the next major release
+ +

getPromiseLazyCreatorFn(googleMapsApiInitializer, GoogleMapsApi) ⇒ function

+

This function is a factory of the promise lazy creator +it helps you creating the function that will call the +Google Maps API in an async way

+

Kind: global function

+
ParamTypeDescription
googleMapsApiInitializerfunctionfunction that initialize the Google Maps API
GoogleMapsApiObjectVue instance that will help to know if the google API object is ready
+ + +

getPromiseLazyCreatorFn~promiseLazyCreator(options)

+

The creator of the lazy promise

+

Kind: inner method of getPromiseLazyCreatorFn

+
ParamTypeDefaultDescription
optionsObject | undefinedconfiguration object to initialize the GmapVue plugin
options.dynamicLoadbooleanfalseload the Google Maps API dynamically, if you set this to true the plugin doesn't load the Google Maps API
options.installComponentsbooleantrueinstall all components
options.autoBindAllEventsbooleanfalseauto bind all Google Maps API events
options.loadObject | undefinedoptions to configure the Google Maps API
options.load.keystringyour Google Maps API key
options.load.librariesstring"places"the Google Maps libraries that you will use eg: 'places,drawing,visualization'
options.load.vstring | undefinedthe Google Maps API version, default latest
options.load.callbackstring | undefined"GoogleMapsCallback"This must be ignored if have another callback that you need to run when Google Maps API is ready please use the customCallback option.
options.load.customCallbackstring | undefinedThis option was added on v3.0.0 but will be removed in the next major release. If you already have an script tag that loads Google Maps API and you want to use it set you callback in the customCallback option and our GoogleMapsCallback callback will execute your custom callback at the end; it must attached to the window object, is the only requirement.
+ +

promiseLazyCreator~onMapsReady() ⇒ Object

+

Things to do once the API is loaded

+

Kind: inner method of promiseLazyCreator
+Returns: Object - the Google Maps API object

+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/utils/helpers/index.html b/docs/vue-2-version/code/utils/helpers/index.html new file mode 100644 index 000000000..b9016403f --- /dev/null +++ b/docs/vue-2-version/code/utils/helpers/index.html @@ -0,0 +1,117 @@ + + + + + +helpers | GmapVue Docs + + + + + +

helpers

+

Functions

+
bindEvents(vueInst, googleMapsInst, events)void

This function helps you to bind events from Google Maps API to Vue events

capitalizeFirstLetter(text)string

Function that helps you to capitalize the first letter on a word

getPropsValues(vueInst, props)Object

Function that helps you to get all non nullable props from a component

getLazyValue(fn)function

This function is a helper for return to the user the internal Google Maps promise +and can wait until it is ready. +This piece of code was orignally written by sindresorhus and can be seen here

mappedPropsToVueProps(mappedProps)Object

Strips out the extraneous properties we have in our +mapped props definitions

downArrowSimulator(input)void

This function simulates a down arrow key event when user +hits return (enter) on the autocomplete component selection +the first occurrence in the list.

+

This piece of code was orignally written by amirnissim +and has been ported to Vanilla.js by GuillaumeLeclerc

twoWayBindingWrapper(fn)

When you have two-way bindings, but the actual bound value will not equal +the value you initially passed in, then to avoid an infinite loop you +need to increment a counter every time you pass in a value, decrement the +same counter every time the bound value changed, but only bubble up +the event when the counter is zero.

watchPrimitiveProperties(vueInst, propertiesToTrack, handler, immediate)void

Watch the individual properties of a PoD object, instead of the object +per se. This is different from a deep watch where both the reference +and the individual values are watched.

+

In effect, it throttles the multiple $watch to execute at most once per tick.

bindProps(vueInst, googleMapsInst, props)void

Binds the properties defined in props to the google maps instance. +If the prop is an Object type, and we wish to track the properties +of the object (e.g. the lat and lng of a LatLng), then we do a deep +watch. For deep watch, we also prevent the _changed event from being +emitted if the data source was external.

+ +

bindEvents(vueInst, googleMapsInst, events) ⇒ void

+

This function helps you to bind events from Google Maps API to Vue events

+

Kind: global function

+
ParamTypeDescription
vueInstObjectthe Vue instance
googleMapsInstObjectthe Google Maps instance
eventsArray.<string>an array of string with all events that you want to bind
+ +

capitalizeFirstLetter(text) ⇒ string

+

Function that helps you to capitalize the first letter on a word

+

Kind: global function

+
ParamTypeDescription
textstringthe text that you want to capitalize
+ +

getPropsValues(vueInst, props) ⇒ Object

+

Function that helps you to get all non nullable props from a component

+

Kind: global function

+
ParamTypeDescription
vueInstObjectthe Vue component instance
propsObjectthe props object
+ +

getLazyValue(fn) ⇒ function

+

This function is a helper for return to the user the internal Google Maps promise +and can wait until it is ready. +This piece of code was orignally written by sindresorhus and can be seen here

+

Kind: global function
+Returns: function - anonymous function that returns the value returned by the fn parameter
+See: [https://github.com/sindresorhus/lazy-value/blob/master/index.js](https://github.com/sindresorhus/lazy-value/blob/master/index.js)

+
ParamTypeDescription
fnfunctiona function that actually return the promise or async value
+ +

mappedPropsToVueProps(mappedProps) ⇒ Object

+

Strips out the extraneous properties we have in our +mapped props definitions

+

Kind: global function

+
ParamTypeDescription
mappedPropsObjectthe mapped props object
+ +

downArrowSimulator(input) ⇒ void

+

This function simulates a down arrow key event when user +hits return (enter) on the autocomplete component selection +the first occurrence in the list.

+

This piece of code was orignally written by amirnissim +and has been ported to Vanilla.js by GuillaumeLeclerc

+

Kind: global function
+See: [http://stackoverflow.com/a/11703018/2694653](http://stackoverflow.com/a/11703018/2694653)

+
ParamTypeDescription
inputObjectthe HTML input node element reference
+ +

downArrowSimulator~addEventListenerWrapper(type, listener) ⇒ void

+

Add event listener wrapper that will replace to default addEventListener or attachEvent function

+

Kind: inner method of downArrowSimulator

+
ParamTypeDescription
typestringthe event type
listenerfunctionfunction should be executed when the event is fired
+ +

twoWayBindingWrapper(fn)

+

When you have two-way bindings, but the actual bound value will not equal +the value you initially passed in, then to avoid an infinite loop you +need to increment a counter every time you pass in a value, decrement the +same counter every time the bound value changed, but only bubble up +the event when the counter is zero.

+
ParamTypeDescription
fnfunctionFunction to be executed to determine if the event was executed Example: Let's say DrawingRecognitionCanvas is a deep-learning backed canvas that, when given the name of an object (e.g. 'dog'), draws a dog. But whenever the drawing on it changes, it also sends back its interpretation of the image by way of the @newObjectRecognized event. <input type="text" placeholder="an object, e.g. Dog, Cat, Frog" v-model="identifiedObject" /> <DrawingRecognitionCanvas :object="identifiedObject"
+

Kind: global function

+

Example:

+

Let's say DrawingRecognitionCanvas is a deep-learning backed canvas +that, when given the name of an object (e.g. 'dog'), draws a dog. +But whenever the drawing on it changes, it also sends back its interpretation +of the image by way of the @newObjectRecognized event.

+
<input
type="text"
placeholder="an object, e.g. Dog, Cat, Frog"
v-model="identifiedObject" />
<DrawingRecognitionCanvas
:object="identifiedObject"
@newObjectRecognized="identifiedObject = $event"
/>
+
    new TwoWayBindingWrapper((increment, decrement, shouldUpdate) => {
this.$watch('identifiedObject', () => {
// new object passed in
increment()
})
this.$deepLearningBackend.on('drawingChanged', () => {
recognizeObject(this.$deepLearningBackend)
.then((object) => {
decrement()
if (shouldUpdate()) {
this.$emit('newObjectRecognized', object.name)
}
})
})
})
+ +

watchPrimitiveProperties(vueInst, propertiesToTrack, handler, immediate) ⇒ void

+

Watch the individual properties of a PoD object, instead of the object +per se. This is different from a deep watch where both the reference +and the individual values are watched.

+

In effect, it throttles the multiple $watch to execute at most once per tick.

+

Kind: global function

+
ParamTypeDefaultDescription
vueInstObjectthe component instance
propertiesToTrackArray.<string>string array with all properties that you want to track
handlerfunctionfunction to be fired when the prop change
immediatebooleanfalse
+ +

watchPrimitiveProperties~requestHandle() ⇒

+

Function in charge to execute the handler function if it was not fired

+

Kind: inner method of watchPrimitiveProperties
+Returns: void

+ +

bindProps(vueInst, googleMapsInst, props) ⇒ void

+

Binds the properties defined in props to the google maps instance. +If the prop is an Object type, and we wish to track the properties +of the object (e.g. the lat and lng of a LatLng), then we do a deep +watch. For deep watch, we also prevent the _changed event from being +emitted if the data source was external.

+

Kind: global function

+
ParamTypeDescription
vueInstObjectthe component instance
googleMapsInstObjectthe Google Maps instance
propsObjectobject with the component props tha should be synched with the Google Maps instances props
+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/utils/initializer/google-maps-api-initializer/index.html b/docs/vue-2-version/code/utils/initializer/google-maps-api-initializer/index.html new file mode 100644 index 000000000..d9dd0acf8 --- /dev/null +++ b/docs/vue-2-version/code/utils/initializer/google-maps-api-initializer/index.html @@ -0,0 +1,30 @@ + + + + + +google-maps-api-initializer | GmapVue Docs + + + + + +

google-maps-api-initializer

+ +

createGoogleMapsAPIInitializer() ⇒ function

+

This function returns the initializer function, it is exported +in that way because we need to generate a closure to define a +private property called isApiSetUp to detect if the Google Maps +API was initializer in a previous execution. +The function that it exports is the function that we use inside +of promise-lazy file to initialize the Google Maps API if +it is required.

+

Kind: global function
+Returns: function - The initializer function

+ +

createGoogleMapsAPIInitializer~googleMapsAPIInitializer(options, loadCn)

+

The initializer function, it adds into the head of the page the Google Maps API script tag to loads the library

+

Kind: inner method of createGoogleMapsAPIInitializer

+
ParamTypeDefaultDescription
optionsObject | undefinedThe configuration Object. (@see https://developers.google.com/maps/documentation/javascript/url-params) libraries.
options.keystringYour Google Maps API key
options.librariesstring"places"The Google Maps libraries that you will use eg: 'places,drawing,visualization', can be given as an array too (@see https://developers.google.com/maps/documentation/javascript/libraries)
options.vstring | undefinedThe Google Maps API version, default latest
options.callbackstring | undefined"GoogleMapsCallback"This must be ignored if have another callback that you need to run when Google Maps API is ready please use the customCallback option.
options.customCallbackstring | undefinedThis option was added on v3.0.0 but will be removed in the next major release. If you already have an script tag that loads Google Maps API and you want to use it set you callback in the customCallback option and our GoogleMapsCallback callback will execute your custom callback at the end; it must attached to the window object, is the only requirement.
loadCnbooleanfalseBoolean. If set to true, the map will be loaded from google maps China (@see https://developers.google.com/maps/documentation/javascript/basics#GoogleMapsChina)
+ + \ No newline at end of file diff --git a/docs/vue-2-version/code/utils/mapped-props-by-map-element/index.html b/docs/vue-2-version/code/utils/mapped-props-by-map-element/index.html new file mode 100644 index 000000000..d1d552ec4 --- /dev/null +++ b/docs/vue-2-version/code/utils/mapped-props-by-map-element/index.html @@ -0,0 +1,32 @@ + + + + + +mapped-props-by-map-element | GmapVue Docs + + + + + +

mapped-props-by-map-element

+ +

autocompleteMappedProps

+

This are GoogleMapsOptions that we want to have like +props in our Vue component. +This properties are in the way that GoogleMaps accept it +and with extraneous properties for the VueJs API. +In a previous version of this plugin, to avoid repetition, +we created a .js file component with a mappedProps key on it +and used a variety of helper functions to clean it and bind it +to Vue props and watch them, etc. +To day our primary main goal is get a more intuitive and descriptive +API and a better documentation of it, following this goals we move +this extraneous properties to an independent file in order to consume +it when is needed. +Please you need to remind that you need to create properties in the +correspondent Vue component with the same names and the same values +for those properties that are not extraneous to Vue.

+

Kind: global constant

+ + \ No newline at end of file diff --git a/docs/vue-2-version/developers/index.html b/docs/vue-2-version/developers/index.html new file mode 100644 index 000000000..bc72dbe30 --- /dev/null +++ b/docs/vue-2-version/developers/index.html @@ -0,0 +1,54 @@ + + + + + +Contributing guide | GmapVue Docs + + + + + +

Contributing guide

+

Commit convention

+

We follow the conventional commit style to write our commits and can follow a semantic version of each package.

+

The commit structure is the follow for inline commits

+
type(scope): the message
+

of the following when you want to add a body or a footer.

+
type(scope): the message

body

footer
+

We use commitlint bot to ensure that all PRs follow this pattern, all PRs that not follow these rules will not be merged until the author fix all needed commits.

+

Valid types

+

We follow the angular convention for types, some of the valid commit types are for example feat, fix, chore, etc; if you want a more detailed explanation please read the valid types on the angular contributing guide.

+

Valid scopes

+

In this project the scopes are required this is because Lerna needs it to determine when it should upgrade the version of a package in the mono repository.

+
NameDescription
rootThis is for changes that only affect the root monorepo managed by Lerna
allThis is for changes that affect all packages and the root monorepo
gmap-vueThis is for changes that affect the gmap-vue package (the plugin package)
docsThis is for changes that affect the documentation package
+

If you have changes that affect gmap-vue and documentation packages you can use the scope that contains the main changes, but this situation is very rare and you must commit the changes in different commits and each of one must have the corresponding scope.

+

Subject min and max length

+

The subject should have 15 characters as a minimum and 75 as a maximum.

+

The subject should be a concise description of the changes.

+

Body

+

The body of the commit is optional, there you can explain in a more detailed way the changes that you will commit. The maximum length of the body should be 300 characters.

+ +

The footer of the commit is optional, there you should add the related issue if it exists, or a message if the commit close o resolve an issue. Also, you can put in this section the keyword BREAKING CHANGE: message to inform that this commit inserts a breaking change on the API, another option to do that is adding the ! symbol after the type(scope) section.

+

Footer examples:

+
issue: #45
+
close: #45
+
resolve: #45
+
BREAKING CHANGE: This breaks the api that generate automatically all components.
+

Git flow and history

+

At this moment we have one main branch master when you fork the project you must work on that branch.

+

This branch have a linear history and you should use the rebase strategy instead of merge strategy to maintain the linear history of the commits.

+

After ensuring that all changes in your branch works as expected we will merge it on the master branch and all features and fixes added to the master branch will automatically be deployed to npm and the documentation site.

+

PR title (deprecated)

+

A tricky point that you need to keep in mind is because of the GitHub behaviour when you make a PR the title of the PR should be similar to an inline commit style, in this way the title validator will approve you PR and will review it and merge it.

+

The regex patter that validates the title for a PR is the following

+
/^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\()(deps|root|all|gmap-vue|documentation)(\))(:)(\s{1}[\.\/\-\_a-z0-9\s]+)$/gm
+

You can test this regex expression following this link regexr.com/59fn0.

+

Code style

+

We follow the Airbnb code style rules, if you have doubts, please read the explanation on his GitHub repository or the Eslint documentation.

+

Your changes must pass the linter before you can commit your changes, this is not optional and required to maintain the same style in the project.

+

Tests

+

We have a few tests in the project and they must pass before we can merge your PR into the project.

+

We have planned to improve our tests adding jest and cypress to the project in the middle term.

+ + \ No newline at end of file diff --git a/docs/vue-2-version/developers/license/index.html b/docs/vue-2-version/developers/license/index.html new file mode 100644 index 000000000..7a3dd8076 --- /dev/null +++ b/docs/vue-2-version/developers/license/index.html @@ -0,0 +1,18 @@ + + + + + +MIT License | GmapVue Docs + + + + + +

MIT License

+ +

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

+

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

+

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ + \ No newline at end of file diff --git a/docs/vue-2-version/guide/autocomplete/index.html b/docs/vue-2-version/guide/autocomplete/index.html new file mode 100644 index 000000000..b96727b0e --- /dev/null +++ b/docs/vue-2-version/guide/autocomplete/index.html @@ -0,0 +1,42 @@ + + + + + +autocomplete | GmapVue Docs + + + + + +

autocomplete

Description

+

This component helps you to find and select a place on Google Maps API.

+

For more information read the Google Maps documentation for autocomplete.

+

It is exported with the name GmapAutocomplete.

+
Breaking changes

From v2.x.x we change the slot used in this component until v1.5.0 and below it was named input from v2.x.x we use the default slot and its fallback content if you don't provide a slot content.

For more information please read the Vue.js documentation for slots.

+

Variables

+

This component save the original autocomplete object provided by Google Maps in a property called $autocomplete, as the example below.

+
this.$autocomplete = new google.maps.places.Autocomplete(...);
+

Source code

+
Click to se the source code of autocomplete.vue component
<template>
<div>
<slot v-bind:attrs="$attrs" v-bind:listeners="$listeners">
<input ref="input" v-bind="$attrs" v-on="$listeners" />
</slot>
</div>
</template>

<script>
import {
downArrowSimulator,
getPropsValues,
bindProps,
} from '../utils/helpers';
import { autocompleteMappedProps } from '../utils/mapped-props-by-map-element';

export default {
props: {
bounds: {
type: Object,
},
componentRestrictions: {
type: Object,
},
types: {
type: Array,
default: undefined
},
selectFirstOnEnter: {
required: false,
type: Boolean,
default: false,
},
slotRefName: {
required: false,
type: String,
default: 'input',
},
childRefName: {
required: false,
type: String,
default: 'input',
},
options: {
type: Object,
},
setFieldsTo: {
required: false,
type: Array,
default: null,
},
},
async mounted() {
await this.$gmapApiPromiseLazy();

let scopedInput = null;

if (this.$scopedSlots.default) {
if (!Object.keys(this.$scopedSlots.default()[0].context.$refs).length) {
throw new Error(
'If you use the slot input you must add a ref to the element that you will use as the input, and if you use a vue component, eg: v-text-field, etc, you need to set the childRefName indicating what is the ref name of the HTML input elemnt behind your component.'
);
}

scopedInput = this.$scopedSlots.default()[0].context.$refs[
this.slotRefName
];

if (scopedInput && scopedInput.$refs) {
scopedInput = scopedInput.$refs[this.childRefName];
}

if (scopedInput) {
this.$refs.input = scopedInput;
}
}

if (this.selectFirstOnEnter) {
downArrowSimulator(this.$refs.input);
}

if (typeof google.maps.places.Autocomplete !== 'function') {
throw new Error(
"google.maps.places.Autocomplete is undefined. Did you add 'places' to libraries when loading Google Maps?"
);
}

const autocompleteOptions = {
...getPropsValues(this, autocompleteMappedProps),
...this.options,
};

this.$autocomplete = new google.maps.places.Autocomplete(
this.$refs.input,
autocompleteOptions
);

bindProps(this, this.$autocomplete, autocompleteMappedProps);

if (this.setFieldsTo) {
this.$autocomplete.setFields(this.setFieldsTo);
}

this.$autocomplete.addListener('place_changed', () => {
this.$emit('place_changed', this.$autocomplete.getPlace());
});
},
watch: {
componentRestrictions(v) {
if (v !== undefined) {
this.$autocomplete.setComponentRestrictions(v);
}
},
},
};
</script>
+

If you need to know what are mappedProps please read the general concepts of this application here.

+
Mapped Props of GmapAutocomplete component
export const autocompleteMappedProps = {
bounds: {
type: Object,
},
componentRestrictions: {
type: Object,
noBind: true,
},
types: {
type: Array,
default() {
return [];
},
},
};
+

How to use it

+
<template>
<!-- you can use the auto close form if you don't use the slot -->
<gmap-autocomplete />

<gmap-map :center="center" :zoom="7" style="width: 100%; height: 500px">
</gmap-map>
</template>
+
<template>
<!-- or use the common form with the slot -->
<gmap-autocomplete></gmap-autocomplete>

<gmap-map :center="center" :zoom="7" style="width: 100%; height: 500px">
</gmap-map>
</template>
+

If you need to know the API of this component please read it here.

+

HTML examples

+
Complete HTML example
<body>
<div id="root">
<h1>Autocomplete Example (#164)</h1>
<label>
AutoComplete
<gmap-autocomplete
placeholder="This is a placeholder text"
@place_changed="setPlace">
</gmap-autocomplete>
<button @click="usePlace">Add</button>
</label>
<br />

<gmap-map
style="width: 600px; height: 300px;"
:zoom="1"
:center="{lat: 0, lng: 0}">
<gmap-marker
v-for="(marker, index) in markers"
:key="index"
:position="marker.position"></gmap-marker>
<gmap-marker v-if="this.place" label="&#x2605;" :position="{
lat: this.place.geometry.location.lat(),
lng: this.place.geometry.location.lng(),
}"></gmap-marker>
</gmap-map>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc',
libraries: 'places'
},
});

document.addEventListener('DOMContentLoaded', function () {
new Vue({
el: '#root',
data: {
markers: [],
place: null,
},
methods: {
setDescription(description) {
this.description = description;
},
setPlace(place) {
this.place = place
},
usePlace(place) {
if (this.place) {
this.markers.push({
position: {
lat: this.place.geometry.location.lat(),
lng: this.place.geometry.location.lng(),
}
})
this.place = null;
}
}
}
});
});
</script>
</body>
+
Basic HTML example
<body>
<div id="root">
<h3>Changing Default Place updates text box</h3>
<small>
<ol>
<li>select a place</li>
<li>click in place input</li>
<li>select one option of the list</li>
<li>press <kbd>&#9166;</kbd></li>
</ol>
</small>
<button @click="setDescription('Tokyo')">Set to Tokyo</button>&nbsp;
<button @click="setDescription('Shanghai')">Set to Shanghai</button>&nbsp;
<button @click="setDescription('Seoul')">Set to Seoul</button>
<br />
<br />
<label>
<strong>Place:</strong>
<gmap-autocomplete
:value="description"
placeholder="This is a placeholder text"
@place_changed="setPlace"
:select-first-on-enter="true"
>
</gmap-autocomplete>
</label>
<br />
<p>Use a place input to see coordinates</p>
<strong>lat:</strong> <i>{{ latLng.lat }}</i
>, <strong>lng:</strong> <i>{{ latLng.lng }}</i>

<div>
<h3>Options work</h3>
You cannot find the state of Texas in this
<label>
Only locations in Singapore:
<gmap-autocomplete
:value="description2"
@place_changed="setPlace2"
:options="{
bounds: { north: 1.4, south: 1.2, east: 104, west: 102 },
strictBounds: true,
}"
:select-first-on-enter="true"
>
</gmap-autocomplete>
</label>
<br />
<p>Use a place input to see coordinates</p>
<strong>lat:</strong> <i>{{ latLng2.lat }}</i>,
<strong>lng:</strong> <i>{{ latLng2.lng }}</i>
</div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc',
libraries: 'places'
},
});

document.addEventListener('DOMContentLoaded', function () {
new Vue({
el: '#root',
data: {
description: "Singapore",
description2: "Singapore",
latLng: {
lat: "",
lng: "",
},
latLng2: {
lat: "",
lng: "",
},
},
methods: {
setDescription(description) {
this.description = description;
},
setPlace(place) {
if (!place?.geometry) return;

this.latLng = {
lat: place.geometry.location.lat(),
lng: place.geometry.location.lng(),
};

this.description = place.name;
},
setPlace2(place) {
if (!place?.geometry) return;

this.latLng2 = {
lat: place.geometry.location.lat(),
lng: place.geometry.location.lng(),
};

this.description2 = place.name;
},
},
});
});
</script>
</body>
+
tip

The autocomplete supports cutsom text field via scoped slot

+

Important: from v1.5.0 and below you must use v-slot:input instead of v-slot:default.

+
          <gmap-autocomplete class="introInput" >
<template v-slot:default="slotProps">
<v-text-field outlined
prepend-inner-icon="place"
placeholder="Location Of Event"
ref="input"
v-on:listeners="slotProps.listeners"
v-on:attrs="slotProps.attrs">
</v-text-field>
</template>
</gmap-autocomplete>

The ref on the element must be unique. If you create more than one autocomplete, each one should have a unique ref and it must be mentioned in the slot-ref-name prop. Like this:

          <gmap-autocomplete class="introInput" >
<template v-slot:default="slotProps">
<v-text-field outlined
prepend-inner-icon="place"
placeholder="Location Of Event"
ref="input"
v-on:listeners="slotProps.listeners"
v-on:attrs="slotProps.attrs">
</v-text-field>
</template>
</gmap-autocomplete>
<gmap-autocomplete class="introInput" slot-ref-name="input2">
<template v-slot:default="slotProps">
<v-text-field outlined
prepend-inner-icon="place"
placeholder="Location Of Event"
ref="input2"
v-on:listeners="slotProps.listeners"
v-on:attrs="slotProps.attrs">
</v-text-field>
</template>
</gmap-autocomplete>

If the element in the slot is a vue component then it must have a child ref called input (like in vuetify text-field) or specify a custom name via the child-ref-name prop (only works one level deep into a component).

The v-on:listeners is rquired, v-on:attrs may or may not be required depending on your implementation.

+
warning

Cutsom text fields via scoped slot requires vue 2.6 or higher for the new slot support.

+

Test the component

+
+

This is the first HTML example

+
+ +
Click to see the simple html example
+ + \ No newline at end of file diff --git a/docs/vue-2-version/guide/cdn/index.html b/docs/vue-2-version/guide/cdn/index.html new file mode 100644 index 000000000..f550b534d --- /dev/null +++ b/docs/vue-2-version/guide/cdn/index.html @@ -0,0 +1,17 @@ + + + + + +cdn | GmapVue Docs + + + + + +

cdn

CDN example

+

If you want to use a CDN it is available on unpkg and jsdelivr, the above is an example using unpkg CDN

+
<body>
<div id="root">
<google-map :center="{lat: 1.38, lng: 103.8}" :zoom="12" style="width: 100%; height: 500px">
<ground-overlay source="./overlay.png" :bounds="{
north: 1.502,
south: 1.185,
east: 104.0262,
west: 103.5998,
}" :opacity="0.5">
</ground-overlay>
</google-map>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://unpkg.com/gmap-vue@1.2.2/dist/gmap-vue.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc', // use a valid key
v: '3.26',
},
// Demonstrating how we can customize the name of the components
installComponents: false,
});

document.addEventListener('DOMContentLoaded', function() {
Vue.component('google-map', GmapVue.Map);
Vue.component('ground-overlay', GmapVue.MapElementFactory({
mappedProps: {
'opacity': {}
},
props: {
'source': {type: String},
'bounds': {type: Object},
},
events: ['click', 'dblclick'],
name: 'groundOverlay',
ctr: () => google.maps.GroundOverlay,
ctrArgs: (options, {source, bounds}) => [source, bounds, options],
}));

new Vue({
el: '#root',
data: {
place: '',
},
});
});
</script>
</body>
+
tip

You can copy and paste this example in a html file and run it, but you shouldn't forget to provide a valid Google Map key

+ + \ No newline at end of file diff --git a/docs/vue-2-version/guide/circle/index.html b/docs/vue-2-version/guide/circle/index.html new file mode 100644 index 000000000..79ce15b51 --- /dev/null +++ b/docs/vue-2-version/guide/circle/index.html @@ -0,0 +1,38 @@ + + + + + +circle | GmapVue Docs + + + + + +

circle

Description

+

This component helps you to create a circle on Google Maps API.

+

For more information read the Google Maps documentation +for circles +.

+

It is exported with the name GmapCircle.

+

Variables

+

This component save the original circle object provided by Google Maps in a property called $circleObject, as the +example below.

+
this.$circleObject = new google.maps.Circle(...);
+

Source code

+
Click to se the source code of circle.vue component
<script>
import mapElementMixin from '../mixins/map-element';
import { circleMappedProps } from '../utils/mapped-props-by-map-element';
import { bindEvents, getPropsValues, bindProps } from '../utils/helpers';

export default {
mixins: [mapElementMixin],
props: {
center: {
type: Object,
required: true,
},
radius: {
type: Number,
default: 10,
},
clickable: {
type: Boolean,
default: false,
},
draggable: {
type: Boolean,
default: false,
},
editable: {
type: Boolean,
default: false,
},
fillColor: {
type: String,
default: '',
},
fillOpacity: {
type: Number,
default: 1,
},
strokeColor: {
type: String,
default: '',
},
strokeOpacity: {
type: Number,
default: 1,
},
strokePosition: {
type: Number,
default: 0,
},
strokeWeight: {
type: Number,
default: 1,
},
visible: {
type: Boolean,
default: true,
},
options: {
type: Object,
},
},
render() {
return '';
},
async provide() {
// events to bind with toWay
const events = [
'click',
'dblclick',
'drag',
'dragend',
'dragstart',
'mousedown',
'mousemove',
'mouseout',
'mouseover',
'mouseup',
'rightclick',
];

// Infowindow needs this to be immediately available
const promise = this.$mapPromise
.then((map) => {
this.$map = map;

// Initialize the maps with the given options
const initialOptions = {
...this.options,
map,
...getPropsValues(this, circleMappedProps),
};
const { options: extraOptions, ...finalOptions } = initialOptions;
this.$circleObject = new google.maps.Circle(finalOptions);
bindProps(this, this.$circleObject, circleMappedProps);
bindEvents(this, this.$circleObject, events);

return this.$circleObject;
})
.catch((error) => {
throw error;
});

this.$circlePromise = promise;
return { $circlePromise: promise };
},
destroyed() {
// Note: not all Google Maps components support maps
if (this.$circleObject && this.$circleObject.setMap) {
this.$circleObject.setMap(null);
}
},
};
</script>

+

If you need to know what are mappedProps please read the general concepts of this +application here.

+
Mapped Props of GmapCircle component
export const circleMappedProps = {
center: {
type: Object,
twoWay: true,
required: true,
},
radius: {
type: Number,
twoWay: true,
},
clickable: {
type: Boolean,
noBind: true,
},
draggable: {
type: Boolean,
default: false,
},
editable: {
type: Boolean,
default: false,
},
fillColor: {
type: String,
noBind: true,
},
fillOpacity: {
type: Number,
noBind: true,
},
strokeColor: {
type: String,
noBind: true,
},
strokeOpacity: {
type: Number,
noBind: true,
},
strokePosition: {
type: Number,
noBind: true,
},
strokeWeight: {
type: Number,
noBind: true,
},
visible: {
type: Boolean,
},
options: {
type: Object,
twoWay: false,
},
};
+
Events bound with to way on GmapCircle
const events = [
'click',
'dblclick',
'drag',
'dragend',
'dragstart',
'mousedown',
'mousemove',
'mouseout',
'mouseover',
'mouseup',
'rightclick',
];
+

How to use it

+
<template>
<gmap-map :center="center" :zoom="7" style="width: 100%; height: 500px">
<!-- you can use the auto close form if you want -->
<gmap-circle />
</gmap-map>
</template>
+
<template>
<gmap-map :center="center" :zoom="7" style="width: 100%; height: 500px">
<!-- or -->
<gmap-circle></gmap-circle>
</gmap-map>
</template>
+

If you need to know the API of this component please read it here.

+

HTML examples

+
Simple circle example

We use the following example +of the google documentation.

<body>
<div id="root">
<gmap-map
:center="center"
:zoom="4"
style="width: 100%; height: 500px"
ref="map"
>
<gmap-circle
v-if="radius"
:editable="editable"
:draggable="draggable"
:radius="radius"
:center="circleCenter"
:options="options"
ref="circle"
>
</gmap-circle>
</gmap-map>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc',
libraries: 'places',
},
});

document.addEventListener('DOMContentLoaded', function() {
window.rectangleExample = new Vue({
el: '#root',
data: {
center: { lat: 40.714, lng: -74.005 },
editable: true,
draggable: true,
population: 8405837,
circleCenter: { lat: 40.714, lng: -74.005 },
options: {
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35,
},
},
computed: {
radius() {
return Math.sqrt(this.population) * 100;
},
},
});
});
</script>
</body>
+

Test the component

+
+ + \ No newline at end of file diff --git a/docs/vue-2-version/guide/cluster/index.html b/docs/vue-2-version/guide/cluster/index.html new file mode 100644 index 000000000..bd7a2b1d9 --- /dev/null +++ b/docs/vue-2-version/guide/cluster/index.html @@ -0,0 +1,37 @@ + + + + + +cluster | GmapVue Docs + + + + + +

cluster

Description

+

This component helps you to create a cluster of markers on Google Maps API.

+

For more information read the Google Maps documentation +for clustering.

+
warning

To use this component you need to have installed @googlemaps/markerclusterer


npm install --save @googlemaps/markerclusterer

+
warning

This component must be manually imported

// import globally use the Vue instance
import { components } from 'gmap-vue';

Vue.component('gmap-cluster', components.Cluster);
// import locally inside your component
import { components } from "gmap-vue";

export default {
name: "MyCoolComponent",
data() {
return {
center: {
lat: 10.0,
lng: 10.0
},
markers: [
{
position: {
lat: 10.0,
lng: 10.0
}
},
{
position: {
lat: 11.0,
lng: 11.0
}
}
]
};
},
components: {
"gmap-cluster": components.Cluster
}
};
+
tip

This component is exported in the components object with the name Cluster

import { components } from "gmap-vue";

export default {
...
components: {
"gmap-cluster": components.Cluster
}
};
+

Variables

+

This component save the original cluster object provided by Google Maps in a property called $clusterObject, as the +example below.

+
this.$clusterObject = new MarkerClusterer(...);
+

Source code

+
Click to se the source code of cluster.vue component
<template>
<div>
<slot></slot>
</div>
</template>

<script>
import { MarkerClusterer } from '@googlemaps/markerclusterer';
import MapElementMixin from '../mixins/map-element';
import { clusterIconMappedProps } from '../utils/mapped-props-by-map-element';
import { bindEvents, getPropsValues, bindProps } from '../utils/helpers';

export default {
name: 'ClusterIcon',
mixins: [MapElementMixin],
provide() {
// events to bind with toWay
const events = [
'click',
'rightclick',
'dblclick',
'drag',
'dragstart',
'dragend',
'mouseup',
'mousedown',
'mouseover',
'mouseout',
];

// Infowindow needs this to be immediately available
const promise = this.$mapPromise
.then((map) => {
this.$map = map;

// Initialize the maps with the given options
const initialOptions = {
...this.options,
map,
...getPropsValues(this, clusterIconMappedProps),
};
const { options: extraOptions, ...finalOptions } = initialOptions;

if (typeof MarkerClusterer === 'undefined') {
throw new Error(
'MarkerClusterer is not installed! require() it or include it from https://cdnjs.cloudflare.com/ajax/libs/js-marker-clusterer/1.0.0/markerclusterer.js'
);
}

const {
map: mapInstance,
markers,
algorithm,
onClusterClick,
renderer,
} = finalOptions;

this.$clusterObject = new MarkerClusterer({
map: mapInstance,
markers,
algorithm,
onClusterClick,
renderer,
});

bindProps(this, this.$clusterObject, {});
bindEvents(this, this.$clusterObject, events);

Object.keys({}).forEach((prop) => {
if ({}[prop].twoWay) {
this.$on(`${prop.toLowerCase()}_changed`, this.reinsertMarkers);
}
});

return this.$clusterObject;
})
.catch((error) => {
throw error;
});

this.$clusterPromise = promise;
return { $clusterPromise: promise };
},
props: {
algorithm: {
type: Object,
default: undefined,
},
onClusterClick: {
type: Function,
default: undefined,
},
renderer: {
type: Object,
default: undefined,
},
options: {
type: Object,
default: undefined,
},
},
beforeDestroy() {
this.$children.forEach((marker) => {
if (marker.$clusterObject === this.$clusterObject) {
marker.$clusterObject = null;
}
});

if (this.$clusterObject) {
this.$clusterObject.clearMarkers();
}
},
destroyed() {
if (this.$clusterObject && this.$clusterObject.setMap) {
this.$clusterObject.setMap(null);
}
},
updated() {
if (this.$clusterObject) {
this.$clusterObject.repaint();
}
},
methods: {
reinsertMarkers() {
const oldMarkers = this.$clusterObject.getMarkers();
this.$clusterObject.clearMarkers();
this.$clusterObject.addMarkers(oldMarkers);
},
},
};
</script>

+

If you need to know what are mappedProps please read the general concepts of this +application here.

+
Mapped Props of GmapCluster component
export const clusterIconMappedProps = {
algorithm: {
type: Object,
},
onClusterClick: {
type: Function,
},
renderer: {
type: Object,
},
options: {
type: Object,
},
};
+
Events bound with to way on GmapCircle
const events = [
'click',
'rightclick',
'dblclick',
'drag',
'dragstart',
'dragend',
'mouseup',
'mousedown',
'mouseover',
'mouseout',
];
+

How to use it

+
<template>
<gmap-map
:center="center"
:zoom="7"
style="width: 100%; height: 500px"
>
<!-- use the default slot to pass markers to it -->
<gmap-cluster></gmap-cluster>
</gmap-map>
</template>
+

If you need to know the API of this component please read it here.

+

HTML examples

+
<body>
<div id="root">
<gmap-map :center="center" :zoom="7" style="width: 100%; height: 500px">
<gmap-cluster>
<gmap-marker v-for="(m, index) in markers"
:position="m.position"
:clickable="true" :draggable="true"
@click="center=m.position"
:key="index"
></gmap-marker>
</gmap-cluster>
</gmap-map>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://unpkg.com/@googlemaps/markerclusterer@1.0.13/dist/index.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc'
},
});

Vue.component('gmap-cluster', GmapVue.components.Cluster);

document.addEventListener('DOMContentLoaded', function() {
new Vue({
el: '#root',
data: {
center: {
lat: 10.0,
lng: 10.0
},
markers: [{
position: {
lat: 10.0,
lng: 10.0
}
}, {
position: {
lat: 11.0,
lng: 11.0
}
}]
},
});
});
</script>
</body>
+

Test the component

+
Click to see the html example in action
+ + \ No newline at end of file diff --git a/docs/vue-2-version/guide/drawing-manager/index.html b/docs/vue-2-version/guide/drawing-manager/index.html new file mode 100644 index 000000000..b96ea4433 --- /dev/null +++ b/docs/vue-2-version/guide/drawing-manager/index.html @@ -0,0 +1,39 @@ + + + + + +drawing-manager | GmapVue Docs + + + + + +

drawing-manager

Description

+

This component helps you to drawing shapes on over the map.

+

For more information read the Google Maps documentation +for drawing manager.

+

It is exported with the name GmapDrawingManager.

+

Variables

+

This component save the original drawing manager object provided by Google Maps in a property +called $drawingManagerObject, as the example below.

+
  this.$drawingManagerObject = new google.maps.drawing.DrawingManager(...);
+

Source code

+
Click to se the source code of drawing-manager.vue component
<template>
<div>
<slot
v-bind:setDrawingMode="setDrawingMode"
v-bind:deleteSelection="deleteSelection"
/>
</div>
</template>

<script>
import MapElementMixin from '../mixins/map-element';
import { drawingManagerMappedProps } from '../utils/mapped-props-by-map-element';
import { bindProps, getPropsValues } from '../utils/helpers';

export default {
mixins: [MapElementMixin],
props: {
circleOptions: {
type: Object,
},
markerOptions: {
type: Object,
},
polygonOptions: {
type: Object,
},
polylineOptions: {
type: Object,
},
rectangleOptions: {
type: Object,
},
position: {
type: String,
},
shapes: {
type: Array,
required: true,
},
},
data() {
return {
selectedShape: null,
drawingModes: [],
options: {
drawingMode: null,
drawingControl: true,
drawingControlOptions: {},
},
};
},
methods: {
setDrawingMode(mode) {
this.$drawingManagerObject.setDrawingMode(mode);
},
drawAll() {
const shapeType = {
circle: google.maps.Circle,
marker: google.maps.Marker,
polygon: google.maps.Polygon,
polyline: google.maps.Polyline,
rectangle: google.maps.Rectangle,
};

const self = this;
this.shapes.forEach((shape) => {
const shapeDrawing = new shapeType[shape.type](shape.overlay);
shapeDrawing.setMap(this.$map);
shape.overlay = shapeDrawing;
google.maps.event.addListener(shapeDrawing, 'click', () => {
self.setSelection(shape);
});
});
},
clearAll() {
this.clearSelection();
this.shapes.forEach((shape) => {
shape.overlay.setMap(null);
});
},
clearSelection() {
if (this.selectedShape) {
this.selectedShape.overlay.set('fillColor', '#777');
this.selectedShape.overlay.set('strokeColor', '#999');
this.selectedShape.overlay.setEditable(false);
this.selectedShape.overlay.setDraggable(false);
this.selectedShape = null;
}
},
setSelection(shape) {
this.clearSelection();
this.selectedShape = shape;
shape.overlay.setEditable(true);
shape.overlay.setDraggable(true);
this.selectedShape.overlay.set('fillColor', '#555');
this.selectedShape.overlay.set('strokeColor', '#777');
},
deleteSelection() {
if (this.selectedShape) {
this.selectedShape.overlay.setMap(null);
const index = this.shapes.indexOf(this.selectedShape);
if (index > -1) {
this.shapes.splice(index, 1);
}
}
},
addShape(shape) {
this.setDrawingMode(null);
this.shapes.push(shape);
const self = this;
google.maps.event.addListener(shape.overlay, 'click', () => {
self.setSelection(shape);
});
google.maps.event.addListener(shape.overlay, 'rightclick', () => {
self.deleteSelection();
});
this.setSelection(shape);
},
},
watch: {
position(position) {
if (this.$drawingManagerObject) {
const drawingControlOptions = {
position:
position && google.maps.ControlPosition[position]
? google.maps.ControlPosition[position]
: google.maps.ControlPosition.TOP_LEFT,
drawingModes: this.drawingModes,
};
this.$drawingManagerObject.setOptions({ drawingControlOptions });
}
},
circleOptions(circleOptions) {
if (this.$drawingManagerObject) {
this.$drawingManagerObject.setOptions({ circleOptions });
}
},
markerOptions(markerOptions) {
if (this.$drawingManagerObject) {
this.$drawingManagerObject.setOptions({ markerOptions });
}
},
polygonOptions(polygonOptions) {
if (this.$drawingManagerObject) {
this.$drawingManagerObject.setOptions({ polygonOptions });
}
},
polylineOptions(polylineOptions) {
if (this.$drawingManagerObject) {
this.$drawingManagerObject.setOptions({ polylineOptions });
}
},
rectangleOptions(rectangleOptions) {
if (this.$drawingManagerObject) {
this.$drawingManagerObject.setOptions({ rectangleOptions });
}
},
},
provide() {
// Infowindow needs this to be immediately available
const promise = await this.$mapPromise
.then((map) => {
this.$map = map;

// Initialize the maps with the given options
const initialOptions = {
...this.options,
map,
...getPropsValues(this, drawingManagerMappedProps),
};

const { options: extraOptions, ...finalOptions } = initialOptions;

this.drawingModes = Object.keys(finalOptions).reduce((modes, opt) => {
const val = opt.split('Options');

if (val.length > 1) {
modes.push(val[0]);
}

return modes;
}, []);

const position =
this.position && google.maps.ControlPosition[this.position]
? google.maps.ControlPosition[this.position]
: google.maps.ControlPosition.TOP_LEFT;

finalOptions.drawingMode = null;
finalOptions.drawingControl = !this.$scopedSlots.default;
finalOptions.drawingControlOptions = {
drawingModes: this.drawingModes,
position,
};

// https://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible
this.$drawingManagerObject = new google.maps.drawing.DrawingManager(
finalOptions
);

bindProps(this, this.$drawingManagerObject, drawingManagerMappedProps);

this.$drawingManagerObject.addListener('overlaycomplete', (e) =>
this.addShape(e)
);

this.$map.addListener('click', this.clearSelection);

if (this.shapes.length) {
this.drawAll();
}

return this.$drawingManagerObject;
})
.catch((error) => {
throw error;
});

this.$drawingManagerPromise = promise;
return { $drawingManagerPromise: promise };
},
destroyed() {
this.clearAll();

// Note: not all Google Maps components support maps
if (this.$drawingManagerObject && this.$drawingManagerObject.setMap) {
this.$drawingManagerObject.setMap(null);
}
},
};
</script>

+

If you need to know what are mappedProps please read the general concepts of this +application here.

+
Mapped Props of GmapDrawingManager component

export const drawingManagerMappedProps = {
circleOptions: {
type: Object,
twoWay: false,
noBind: true,
},
markerOptions: {
type: Object,
twoWay: false,
noBind: true,
},
polygonOptions: {
type: Object,
twoWay: false,
noBind: true,
},
polylineOptions: {
type: Object,
twoWay: false,
noBind: true,
},
rectangleOptions: {
type: Object,
twoWay: false,
noBind: true,
},
};

+

How to use it

+
<template>
<gmap-map
ref="mapRef"
:center="mapCenter"
:zoom="7"
map-type-id="roadmap"
style="width: 100%; height: 800px"
:options="{
zoomControl: true,
mapTypeControl: true,
scaleControl: false,
streetViewControl: false,
rotateControl: false,
fullscreenControl: false,
disableDefaultUi: false,
draggable: mapDraggable,
draggableCursor: mapCursor
}"
>
<!-- use the default slot to pass markers to it -->
<gmap-drawing-manager></gmap-drawing-manager>
</gmap-map>
</template>
+
<template>
<gmap-map
ref="mapRef"
:center="mapCenter"
:zoom="7"
map-type-id="roadmap"
style="width: 100%; height: 800px"
:options="{
zoomControl: true,
mapTypeControl: true,
scaleControl: false,
streetViewControl: false,
rotateControl: false,
fullscreenControl: false,
disableDefaultUi: false,
draggable: mapDraggable,
draggableCursor: mapCursor
}"
>
<!-- or with an slot -->
<gmap-drawing-manager>
<template v-slot="on">
<your-toolbar-component
@drawingmode_changed="on.setDrawingMode($event)"
@delete_selection="on.deleteSelection()"
@save="mapMode='ready'"
/>
</template>
</gmap-drawing-manager>
</gmap-map>
</template>
+

If you need to know the API of this component please read it here.

+

HTML examples

+
HTML example
<body>
<div id="root">
<h1>Drawing Manager Example</h1>
<div style="width:100%; display: flex; justify-content: center;">
<span style="width:auto" />
{{ mapMode }} - {{ toolbarPosition }}
<span style="width:auto" />
<button @click="setPos">Position</button>
<button @click="mapMode='edit'">Edit</button>
</div>
<br />
<gmap-map
ref="mapRef"
:center="mapCenter"
:zoom="7"
map-type-id="roadmap"
style="width: 100%; height: 800px"
:options="{
zoomControl: true,
mapTypeControl: true,
scaleControl: false,
streetViewControl: false,
rotateControl: false,
fullscreenControl: false,
disableDefaultUi: false,
draggable: mapDraggable,
draggableCursor: mapCursor
}"
>
<template #visible>
<gmap-drawing-manager
v-if="mapMode==='edit'"
:position="toolbarPosition"
:rectangle-options="rectangleOptions"
:circle-options="circleOptions"
:polyline-options="polylineOptions"
:shapes="shapes"
/>
</template>
</gmap-map>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc',
libraries: 'places,drawing'
}
});

document.addEventListener('DOMContentLoaded', function() {
new Vue({
el: '#root',
data: {
mapCenter: { lat: 4.5, lng: 99 },
mapMode: null,
toolbarPosition: 'TOP_CENTER',
mapDraggable: true,
mapCursor: null,
shapes: [],
rectangleOptions: {
fillColor: '#777',
fillOpacity: 0.4,
strokeWeight: 2,
strokeColor: '#999',
draggable: false,
editable: false,
clickable: true
},
circleOptions: {
fillColor: '#777',
fillOpacity: 0.4,
strokeWeight: 2,
strokeColor: '#999',
draggable: false,
editable: false,
clickable: true
},
polylineOptions: {
fillColor: '#777',
fillOpacity: 0.4,
strokeWeight: 2,
strokeColor: '#999',
draggable: false,
editable: false,
clickable: true
}
},
watch: {
mapMode(newMode, oldMode) {
if (newMode === 'ready') {
if (oldMode === 'edit') {
this.mapDraggable = true;
this.mapCursor = null;
return;
}
}

if (newMode === 'edit') {
this.mapDraggable = false;
this.mapCursor = 'default';
}
}
},
mounted() {
this.mapMode = 'ready';
},
methods: {
setPos() {
const posTypes = [
'TOP_CENTER',
'TOP_LEFT',
'TOP_RIGHT',
'LEFT_TOP',
'RIGHT_TOP',
'LEFT_CENTER',
'RIGHT_CENTER',
'LEFT_BOTTOM',
'RIGHT_BOTTOM',
'BOTTOM_CENTER',
'BOTTOM_LEFT',
'BOTTOM_RIGHT'
];

this.toolbarPosition =
posTypes[Math.floor(Math.random() * posTypes.length)];
}
}
});
});
</script>
</body>
+
HML examples with slot
<body>
<div id="root">
<h1>Drawing Manager Example</h1>
<div style="width:100%; display: flex; justify-content: center;">
<span style="width: auto;" />
{{ mapMode }}
<span style="width: auto;" />
<button @click="mapMode='edit'">Edit</button>
</div>
<br />
<gmap-map
ref="mapRef"
:center="mapCenter"
:zoom="7"
map-type-id="roadmap"
style="width: 100%; height: 800px; display:flex; justify-content: center; align-items: flex-start;"
:options="{
zoomControl: true,
mapTypeControl: true,
scaleControl: false,
streetViewControl: false,
rotateControl: false,
fullscreenControl: false,
disableDefaultUi: false,
draggable: mapDraggable,
draggableCursor: mapCursor
}"
>
<template #visible>
<gmap-drawing-manager
v-if="mapMode==='edit'"
:rectangle-options="rectangleOptions"
:circle-options="circleOptions"
:polyline-options="polylineOptions"
:polygon-options="polygonOptions"
:shapes="shapes"
>
<template v-slot="on">
<drawing-toolbar
@drawingmode_changed="on.setDrawingMode($event)"
@delete_selection="on.deleteSelection()"
@save="mapMode='ready'"
/>
</template>
</gmap-drawing-manager>
</template>
</gmap-map>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
// Only for example purposes
// In a real application you would simply create a separate component
const toolbarTemplate =
'<div style="background-color: #040404; display: flex; position: absolute; padding: 8px">' +
" <div><button @click=\"$emit('drawingmode_changed', 'rectangle')\">Rectangle</button></div>" +
" <div><button @click=\"$emit('drawingmode_changed', 'circle')\">Circle</button></div>" +
" <div><button @click=\"$emit('drawingmode_changed', 'polyline')\">Line</button></div>" +
" <div><button @click=\"$emit('drawingmode_changed', 'polygon')\">Polygon</button></div>" +
" <div><button @click=\"$emit('delete_selection')\">Delete</button></div>" +
" <div><button @click=\"$emit('save')\">Save</button></div>" +
"</div>";

Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc',
libraries: 'places,drawing'
}
});

document.addEventListener('DOMContentLoaded', function() {
new Vue({
el: '#root',
components: {
drawingToolbar: {
template: toolbarTemplate
}
},
data: {
mapCenter: { lat: 4.5, lng: 99 },
mapMode: null,
mapDraggable: true,
mapCursor: null,
shapes: [],
rectangleOptions: {
fillColor: '#777',
fillOpacity: 0.4,
strokeWeight: 2,
strokeColor: '#999',
draggable: false,
editable: false,
clickable: true
},
circleOptions: {
fillColor: '#777',
fillOpacity: 0.4,
strokeWeight: 2,
strokeColor: '#999',
draggable: false,
editable: false,
clickable: true
},
polylineOptions: {
fillColor: '#777',
fillOpacity: 0.4,
strokeWeight: 2,
strokeColor: '#999',
draggable: false,
editable: false,
clickable: true
},
polygonOptions: {
fillColor: '#777',
fillOpacity: 0.4,
strokeWeight: 2,
strokeColor: '#999',
draggable: false,
editable: false,
clickable: true
}
},
watch: {
mapMode(newMode, oldMode) {
if (newMode === 'ready') {
if (oldMode === 'edit') {
this.mapDraggable = true;
this.mapCursor = null;
return;
}
}

if (newMode === 'edit') {
this.mapDraggable = false;
this.mapCursor = 'default';
}
}
},
mounted() {
this.mapMode = 'ready';
}
});
});
</script>
</body>
+
warning

If you are using the runtime-only build the template on toolbarTemplate will not work, instead of that +you need to pre-compile the templates into render functions, or use the compiler-included build.

+

Test the component

+
Click to see the HTML example in action
+
Click to see the HTML example with slot in action
+ + \ No newline at end of file diff --git a/docs/vue-2-version/guide/extra-examples/index.html b/docs/vue-2-version/guide/extra-examples/index.html new file mode 100644 index 000000000..f74c861a7 --- /dev/null +++ b/docs/vue-2-version/guide/extra-examples/index.html @@ -0,0 +1,36 @@ + + + + + +extra-examples | GmapVue Docs + + + + + +

extra-examples

Status Bar

+

You can add a status bar with a description when the moues is over the marker.

+

HTML status bar example

+
Click to see the example
<body>
<div id="root">
You should see a blue status bar with a description of the place at the
position of the marker when you move your mouse over the markers.

<gmap-map
:center="center"
:zoom="15"
style="width: 100%; height: 500px"
>
<gmap-marker
v-for="m in markers"
:position="{lat: m.position[0], lng: m.position[1]}"
:clickable="true"
:draggable="true"
@click="center = m.position"
@mouseover="statusText = m.text"
@mouseout="statusText = null"
></gmap-marker>

<div slot="visible">
<div style="bottom: 0; left: 0; background-color: #0000FF; color: white; position: absolute; z-index: 100">
{{statusText}}
</div>
</div>
</gmap-map>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc'
},
});

document.addEventListener('DOMContentLoaded', function() {
new Vue({
el: '#root',
data: {
center: {lat: 47.376332, lng: 8.547511},
statusText: '',
markers: [{
position: [47.376332, 8.547511],
text: 'Hauptgebäude der ETH Zürich'
}, {
position: [47.374592, 8.548867],
text: 'Hauptgebäude der Universität Zürich'
}]
},
});
});
</script>
</body>
+

Test the status bar example

+ +

Overlay

+

You can add add an overlay image over the map to mark a zone.

+

HTML overlay example

+
Click to see the example
<body>
<div id="root">
<p>Please move the map in order to see the limits of the overlay image</p>
<gmap-map :center="{lat: 1.38, lng: 103.8}" :zoom="12" style="width: 100%; height: 500px">
<ground-overlay source="./overlay.png" :bounds="{
north: 1.502,
south: 1.185,
east: 104.0262,
west: 103.5998,
}" :opacity="0.5">
</ground-overlay>
</gmap-map>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc',
v: '3.26',
},
// Demonstrating how we can customize the name of the components
installComponents: false,
});

document.addEventListener('DOMContentLoaded', function() {
Vue.component('gmap-map', GmapVue.Map);
Vue.component('ground-overlay', GmapVue.MapElementFactory({
mappedProps: {
'opacity': {}
},
props: {
'source': {type: String},
'bounds': {type: Object},
},
events: ['click', 'dblclick'],
name: 'groundOverlay',
ctr: () => google.maps.GroundOverlay,
ctrArgs: (options, {source, bounds}) => [source, bounds, options],
}));

new Vue({
el: '#root',
data: {
place: '',
},
});
});
</script>
</body>
+

Test the overlay example

+ +

Resize Bus

+
danger

This functionality is no longer supported by Google Maps, please read the following answers in StackOverflow:

and also check the official documentation of the Map class and you will note that this property is no longer +supported as a property of the Map class.

+

You can modify the size of the bus if want check the above example to see it in action

+

HTML resize bus example

+
Click to see the example
<body>
<div id="root">
<h1>Resize Bus</h1>

<p>
The first map is displayed correctly after clicking
the button.

The second and third are not (not bound to default resize bus).
<button @click=updateStyle>
Click me first
</button>
</p>
<p>
However, the third map responds to the second button
(custom resize bus)

<button @click=updateBus>
Click me second
</button>
</p>

<gmap-map
:style="currentStyle"
:center="{lat: 1.38, lng: 103.8}"
:zoom=12>
</gmap-map>

<gmap-map
:style="currentStyle"
:center="{lat: 1.38, lng: 103.8}"
:zoom=12
:resize-bus="null">
</gmap-map>

<gmap-map
:style="currentStyle"
:center="{lat: 1.38, lng: 103.8}"
:zoom=12
:resize-bus="customBus">
</gmap-map>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc',
},
});

document.addEventListener('DOMContentLoaded', function() {
new Vue({
el: '#root',
data: {
currentStyle: {
display: 'none'
},
customBus: new Vue(),
},
methods: {
updateStyle() {
this.currentStyle = {
display: 'inline-block',
width: '200px',
height: '200px',
};
Vue.$gmapDefaultResizeBus.$emit('resize');
},
updateBus() {
this.customBus.$emit('resize');
}
}
});
});
</script>
</body>
+

Test the resize bus example

+
+ + \ No newline at end of file diff --git a/docs/vue-2-version/guide/heatmap-layer/index.html b/docs/vue-2-version/guide/heatmap-layer/index.html new file mode 100644 index 000000000..b9ae2cc40 --- /dev/null +++ b/docs/vue-2-version/guide/heatmap-layer/index.html @@ -0,0 +1,38 @@ + + + + + +heatmap-layer | GmapVue Docs + + + + + +

heatmap-layer

Description

+

This components helps you to set a heat zone over the map.

+

For more information read the Google Maps documentation +for heatmaplayer

+

It is exported with the name GmapHeatmapLayer.

+

Variables

+

This component save the original heat map layer object provided by Google Maps in a property +called $heatmapLayerObject, as the example below.

+
  this.$heatmapLayerObject = new google.maps.visualization.HeatmapLayer(...);
+

Source code

+
Click to se the source code of heatmap-layer.vue component
<script>
import MapElementMixin from '../mixins/map-element';
import { heatMapLayerMappedProps } from '../utils/mapped-props-by-map-element';
import { bindProps, getPropsValues, bindEvents } from '../utils/helpers';

export default {
mixins: [MapElementMixin],
props: {
options: {
type: Object,
default: () => {},
},
data: {
type: Array,
},
},
provide() {
const events = [];

// Infowindow needs this to be immediately available
const promise = await this.$mapPromise
.then((map) => {
this.$map = map;

// Initialize the maps with the given options
const initialOptions = {
...this.options,
map: this.$map,
...getPropsValues(this, heatMapLayerMappedProps),
};

const { options: extraOptions, ...finalOptions } = initialOptions;

this.$heatmapLayerObject = new google.maps.visualization.HeatmapLayer(
finalOptions
);

bindProps(this, this.$heatmapLayerObject, heatMapLayerMappedProps);
bindEvents(this, this.$heatmapLayerObject, events);

return this.$heatmapLayerObject;
})
.catch((error) => {
throw error;
});

this.$heatmapLayerPromise = promise;
return { $heatmapLayerPromise: promise };
},
destroyed() {
// Note: not all Google Maps components support maps
if (this.$heatmapLayerObject && this.$heatmapLayerObject.setMap) {
this.$heatmapLayerObject.setMap(null);
}
},
};
</script>

+

If you need to know what are mappedProps please read the general concepts of this +application here.

+
Mapped Props of GmapHeatmapLayer component

export const heatMapLayerMappedProps = {
options: {
type: Object,
twoWay: false,
default: () => {},
},
data: {
type: Array,
twoWay: true,
},
};

+

How to use it

+
<template>
<gmap-map
ref="mapRef"
:zoom="7"
:center="center"
map-type-id="roadmap"
style="width: 100%; height: 500px;"
>
<gmap-heatmap-layer
:data="[new google.maps.LatLng(37.782, -122.447)]"
:options="{maxIntensity: 120, dissipating: false}"
/>
</gmap-map>
</template>
+

You also can use a computed property like below

+
<template>
<gmap-map
ref="mapRef"
:zoom="7"
:center="center"
map-type-id="roadmap"
style="width: 100%; height: 500px;"
>
<gmap-marker
v-for="(m, index) in markers"
:key="index"
:position="m.location"
:clickable="true"
:draggable="true"
@click="center=m.location"
/>
<gmap-heatmap-layer
:data="markers"
:options="{maxIntensity: 120, dissipating: false}"
/>
</gmap-map>
</template>
<script>
import { gmapApi } from 'gmap-vue';

export default {
computed: {
google: gmapApi,
markers() {
if (this.google) {
return [
{ location: new google.maps.LatLng({ lat: 3, lng: 101 }), weight: 100 },
{ location: new google.maps.LatLng({ lat: 5, lng: 99 }), weight: 50 },
{ location: new google.maps.LatLng({ lat: 6, lng: 97 }), weight: 80 }
];
}
return [];
},
},
};
</script>
+
warning

This component is one of the few components where you must use the Google LatLng object to create the markers, you +can't use a generic object like { lat: 0, lng: 0 } to generate them.

+

If you need to know the API of this component please read it here.

+

HTML examples

+
HTML example
<body>
<div id="root">
<gmap-map
ref="mapRef"
:zoom="7"
:center="center"
map-type-id="roadmap"
style="width: 100%; height: 500px;"
>
<gmap-marker
v-for="(m, index) in markers"
:key="index"
:position="m.location"
:clickable="true"
:draggable="true"
@click="center=m.location"
/>
<gmap-heatmap-layer
:data="markers"
:options="{maxIntensity: 120, dissipating: false}"
/>
</gmap-map>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc',
libraries: 'visualization'
}
});

document.addEventListener('DOMContentLoaded', function() {
new Vue({
el: '#root',
data: {
center: { lat: 4.5, lng: 99 },
markers: [],
},
async mounted() {
await this.$gmapApiPromiseLazy();
this.markers = [
{
location: new google.maps.LatLng({ lat: 3, lng: 101 }),
weight: 100
},
{
location: new google.maps.LatLng({ lat: 5, lng: 99 }),
weight: 50
},
{
location: new google.maps.LatLng({ lat: 6, lng: 97 }),
weight: 80
}
];
}
});
});
</script>
</body>
+

Test the component

+
Click to see the HTML example in action
+ + \ No newline at end of file diff --git a/docs/vue-2-version/guide/index.html b/docs/vue-2-version/guide/index.html new file mode 100644 index 000000000..cfb7d32bc --- /dev/null +++ b/docs/vue-2-version/guide/index.html @@ -0,0 +1,20 @@ + + + + + +Introduction | GmapVue Docs + + + + + +

Introduction

Mapped props

+
warning

We are trying to remove this approach and its possible that in major releases this will disappear.

+

This are GoogleMapsOptions that we want to have like props in our Vue component.

+

This properties are in the way that GoogleMaps accept it and with extraneous properties for the VueJs API. +In a previous version of this plugin, to avoid repetition, we created a .js file component with a mappedProps key on it and used a variety of helper functions to clean it and bind it to Vue props and watch them, etc.

+

To day our main goal is write a more intuitive, readable and descriptive API with a better documentation of it, following this goals we move this extraneous properties to an independent file in order to consume it when is needed.

+
For developers

You need to remind that you need to create properties in the correspondent Vue component with the same names and the same values for those properties that are not extraneous to Vue.

+ + \ No newline at end of file diff --git a/docs/vue-2-version/guide/info-window/index.html b/docs/vue-2-version/guide/info-window/index.html new file mode 100644 index 000000000..e56832f83 --- /dev/null +++ b/docs/vue-2-version/guide/info-window/index.html @@ -0,0 +1,42 @@ + + + + + +info-window | GmapVue Docs + + + + + +

info-window

Description

+

This component helps you to create a info window in a marker.

+

For more information read the Google Maps documentation +for info window.

+

It is exported with the name GmapInfoWindow.

+

Variables

+

This component save the original Info-Window object provided by Google Maps in a property called $infoWindowObject, as +the example below.

+
  this.$infoWindowObject = new google.maps.InfoWindow(...);
+

Source code

+
Click to se the source code of info-window.vue component
<template>
<div>
<div ref="flyaway">
<!-- so named because it will fly away to another component -->
<!-- @slot Used to set your info window. -->
<slot></slot>
</div>
</div>
</template>

<script>
import MapElementMixin from '../mixins/map-element';
import { infoWindowMappedProps } from '../utils/mapped-props-by-map-element';
import { bindEvents, bindProps, getPropsValues } from '../utils/helpers';

export default {
mixins: [MapElementMixin],
props: {
content: {
type: [String, Object],
default: undefined,
},
opened: {
type: Boolean,
default: true,
},
options: {
type: Object,
required: false,
default: undefined,
},
position: {
type: Object,
},
zIndex: {
type: Number,
},
},
methods: {
_openInfoWindow() {
if (this.opened) {
if (this.$markerObject !== null) {
this.$infoWindowObject.open(this.$map, this.$markerObject);
} else {
this.$infoWindowObject.open(this.$map);
}
} else {
this.$infoWindowObject.close();
}
},
},
inject: {
$markerPromise: {
default: null,
},
},
provide() {
const events = ['domready', 'closeclick', 'content_changed'];

// Infowindow needs this to be immediately available
const promise = await this.$mapPromise
.then((map) => {
this.$map = map;

// Initialize the maps with the given options
const initialOptions = {
...this.options,
map,
...getPropsValues(this, infoWindowMappedProps),
};

const {
options: extraOptions,
position,
...finalOptions
} = initialOptions;

this.beforeCreate(finalOptions);

this.$infoWindowObject = new google.maps.InfoWindow(finalOptions);

bindProps(this, this.$infoWindowObject, infoWindowMappedProps);
bindEvents(this, this.$infoWindowObject, events);

return this.$infoWindowObject;
})
.catch((error) => {
throw error;
});

this.$infoWindowPromise = promise;
return { $infoWindowPromise: promise };
},
beforeCreate(options) {
options.content = this.$refs.flyaway;

if (this.$markerPromise) {
return this.$markerPromise.then((mo) => {
this.$markerObject = mo;
return mo;
});
}

// this return is to follow the consistent-return rule of eslint, https://eslint.org/docs/rules/consistent-return
return undefined;
},
afterCreate() {
this._openInfoWindow();
this.$watch('opened', () => {
this._openInfoWindow();
});
},
mounted() {
const el = this.$refs.flyaway;
el.parentNode.removeChild(el);
},
destroyed() {
// Note: not all Google Maps components support maps
if (this.$infoWindowObject && this.$infoWindowObject.setMap) {
this.$infoWindowObject.setMap(null);
}
},
};
</script>

+

If you need to know what are mappedProps please read the general concepts of this +application here.

+
Mapped Props of GmapInfoWindow component
export const infoWindowMappedProps = {
content: {
type: Object,
twoWay: true,
},
options: {
type: Object,
required: false,
default() {
return {};
},
},
position: {
type: Object,
twoWay: true,
},
zIndex: {
type: Number,
twoWay: true,
},
};
+
Events bound with to way on GmapInfoWindow
const events = ['domready', 'closeclick', 'content_changed'];
+

How to use it

+
warning

If you only need to display a simple text, from v3.4.3, we added a new prop called content and you can use it to +pass data to the InfoWindow component, it accepts HTML too but take care about it because it has precedence over +the slot use only one of both options.

If you need to pass an entire block of HTML is better and simplest to use the default slot for it and leave the content +prop empty. Doing that you have more flexibility and control over your HTML content.

+

From v3.4.3

+
<template>
<gmap-map :center="center" :zoom="15" style="width: 100%; height: 500px">
<gmap-info-window
content="This is my info window content"
:options="infoOptions"
:position="infoWindowPos"
:opened="infoWinOpen"
@closeclick="infoWinOpen=false"
/>

<gmap-marker
:key="i"
v-for="(m,i) in markers"
:position="m.position"
:clickable="true"
@click="toggleInfoWindow(m,i)"
>
</gmap-marker>
</gmap-map>
</template>
+

or use the default slot as below

+
<template>
<gmap-map :center="center" :zoom="15" style="width: 100%; height: 500px">
<gmap-info-window
:options="infoOptions"
:position="infoWindowPos"
:opened="infoWinOpen"
@closeclick="infoWinOpen=false"
>
</gmap-info-window>

<gmap-marker
:key="i"
v-for="(m,i) in markers"
:position="m.position"
:clickable="true"
@click="toggleInfoWindow(m,i)"
>
</gmap-marker>
</gmap-map>
</template>
+

If you need to know the API of this component please read it here.

+

HTML examples

+
HTML example
<body>
<div id="root">
A basic example of using a single infowindow for 3 markers.

<gmap-map :center="center" :zoom="15" style="width: 100%; height: 500px">
<gmap-info-window :options="infoOptions" :position="infoWindowPos" :opened="infoWinOpen" @closeclick="infoWinOpen=false">
</gmap-info-window>

<gmap-marker :key="i" v-for="(m,i) in markers" :position="m.position" :clickable="true" @click="toggleInfoWindow(m,i)"></gmap-marker>
</gmap-map>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc'
},
});

document.addEventListener('DOMContentLoaded', function() {
new Vue({
el: '#root',
data: {
center: {
lat: 47.376332,
lng: 8.547511
},
infoWindowPos: null,
infoWinOpen: false,
currentMidx: null,

infoOptions: {
content: '',
//optional: offset infowindow so it visually sits nicely on top of our marker
pixelOffset: {
width: 0,
height: -35
}
},
markers: [{
position: {
lat: 47.376332,
lng: 8.547511
},
infoText: '<strong>Marker 1</strong>'
}, {
position: {
lat: 47.374592,
lng: 8.548867
},
infoText: '<strong>Marker 2</strong>'
}, {
position: {
lat: 47.379592,
lng: 8.549867
},
infoText: '<strong>Marker 3</strong>'
}]
},
methods: {
toggleInfoWindow: function(marker, idx) {
this.infoWindowPos = marker.position;
this.infoOptions.content = marker.infoText;

//check if its the same marker that was selected if yes toggle
if (this.currentMidx == idx) {
this.infoWinOpen = !this.infoWinOpen;
}

//if different marker set infowindow to open and reset current marker index
else {
this.infoWinOpen = true;
this.currentMidx = idx;
}
}
}
});
});
</script>
</body>
+

Test the component

+
Click to see the HTML example in action
+ + \ No newline at end of file diff --git a/docs/vue-2-version/guide/kml-layer/index.html b/docs/vue-2-version/guide/kml-layer/index.html new file mode 100644 index 000000000..d0df2ba76 --- /dev/null +++ b/docs/vue-2-version/guide/kml-layer/index.html @@ -0,0 +1,35 @@ + + + + + +kml-layer | GmapVue Docs + + + + + +

kml-layer

Description

+

This component helps you to create a Kml layer.

+

For more information read the Google Maps documentation +for kml layers.

+

It is exported with the name GmapKmlLayer.

+

Variables

+

This component save the original Kml-layer object provided by Google Maps in a property called $kmlLayerObject, as the +example below.

+
  this.$kmlLayerObject = new google.maps.KmlLayer(...);
+

Source code

+
Click to se the source code of info-window.vue component
<script>
import MapElementMixin from '../mixins/map-element';
import { getPropsValues, bindEvents, bindProps } from '../utils/helpers';
import { kmlLayerMappedProps } from '../utils/mapped-props-by-map-element';

export default {
mixins: [MapElementMixin],
props: {
clickable: {
type: Boolean,
default: true,
},
map: {
type: Object,
default: undefined,
},
preserveViewport: {
type: Boolean,
default: false,
},
screenOverlays: {
type: Boolean,
default: false,
},
suppressInfoWindows: {
type: Boolean,
default: undefined,
},
url: {
type: String,
default: '',
},
zIndex: {
type: Number,
default: undefined,
},
},
provide() {
const events = [
'click',
'rightclick',
'dblclick',
'mouseup',
'mousedown',
'mouseover',
'mouseout',
];

// Infowindow needs this to be immediately available
const promise = await this.$mapPromise
.then((map) => {
this.$map = map;

// Initialize the maps with the given options
const initialOptions = {
...this.options,
map,
...getPropsValues(this, kmlLayerMappedProps),
};

const { options: extraOptions, ...finalOptions } = initialOptions;

this.$kmlLayerObject = new google.maps.KmlLayer(finalOptions);

bindProps(this, this.$kmlLayerObject, kmlLayerMappedProps);
bindEvents(this, this.$kmlLayerObject, events);

return this.$kmlLayerObject;
})
.catch((error) => {
throw error;
});

this.$kmlLayerPromise = promise;
return { $kmlLayerPromise: promise };
},
destroyed() {
// Note: not all Google Maps components support maps
if (this.$kmlLayerObject && this.$kmlLayerObject.setMap) {
this.$kmlLayerObject.setMap(null);
}
},
};
</script>

+

If you need to know what are mappedProps please read the general concepts of this +application here.

+
Mapped Props of GmapKmlLayer component
export const kmlLayerMappedProps = {
clickable: {
type: Boolean,
twoWay: true,
noBind: true,
},
map: {
type: Object,
twoWay: true,
},
preserveViewport: {
type: Boolean,
twoWay: true,
noBind: true,
},
screenOverlays: {
type: Boolean,
twoWay: true,
noBind: true,
},
suppressInfoWindows: {
type: Boolean,
twoWay: true,
noBind: true,
},
url: {
type: String,
twoWay: false,
},
zIndex: {
type: Number,
twoWay: true,
},
options: {
type: Object,
default() {
return {};
},
},
};
+
Events bound with to way on GmapKmlLayer
const events = [
'click',
'rightclick',
'dblclick',
'mouseup',
'mousedown',
'mouseover',
'mouseout',
];
+

How to use it

+
<template>
<gmap-map :center="center" :zoom="7" style="width: 100%; height: 500px">
<google-kml-layer
v-for="l in kmlLayers"
:url="l.url"
:clickable="true"
:preserveViewport="true"
>
</google-kml-layer>
</gmap-map>
</template>

<script>
export default {
data() {
return {
kmlLayers = [
{
url:
'https://developers.google.com/maps/documentation/javascript/examples/kml/westcampus.kml',
},
],
}
}
}
</script>
+

If you need to know the API of this component please read it here.

+

HTML examples

+
HTML example
<body>
<div id="root">
<gmap-map :center="center" :zoom="7" style="width: 100%; height: 500px">
<google-kml-layer v-for="l in kmlLayers" :url="l.url" :clickable="true" :preserveViewport="true"></google-kml-layer>
</gmap-map>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc'
},
// Demonstrating how we can customize the name of the components
installComponents: false,
});

document.addEventListener('DOMContentLoaded', function () {
Vue.component('google-map', GmapVue.Map);
Vue.component('google-kml-layer', GmapVue.KmlLayer);

new Vue({
el: '#root',
data: {
center: {
lat: -19.257753,
lng: 146.823688
},
kmlLayers: [{
url: 'https://developers.google.com/maps/documentation/javascript/examples/kml/westcampus.kml'
}]
},
});
});
</script>
</body>
+

Test the component

+
Click to see the HTML example in action
+ + \ No newline at end of file diff --git a/docs/vue-2-version/guide/map-element-factory/index.html b/docs/vue-2-version/guide/map-element-factory/index.html new file mode 100644 index 000000000..9c6e89439 --- /dev/null +++ b/docs/vue-2-version/guide/map-element-factory/index.html @@ -0,0 +1,17 @@ + + + + + +The mapElement factory | GmapVue Docs + + + + + +

The mapElement factory

+

The current code of the mapElement factory function.

+

You can find the API documentation here.

+
import MapElementMixin from '../../mixins/map-element';
import {
bindEvents,
bindProps,
getPropsValues,
mappedPropsToVueProps,
} from '../helpers';

function _assert(v, message) {
if (!v) throw new Error(message);
}

function mapElement(providedOptions) {
const {
mappedProps,
name,
ctr,
ctrArgs,
events,
beforeCreate,
afterCreate,
props,
...rest
} = providedOptions;

const promiseName = `$${name}Promise`;
const instanceName = `$${name}Object`;

_assert(!(props instanceof Array), '`props` should be an object, not Array');

return {
...(typeof GENERATE_DOC !== 'undefined'
? { $vgmOptions: providedOptions }
: {}),
mixins: [MapElementMixin],
props: {
...props,
...mappedPropsToVueProps(mappedProps),
},
render() {
return '';
},
provide() {
const promise = this.$mapPromise
.then((map) => {
// Infowindow needs this to be immediately available
this.$map = map;

// Initialize the maps with the given options
const initialOptions = {
...this.options,
map,
...getPropsValues(this, mappedProps),
};
// don't use delete keyword in order to create a more predictable code for the engine
const { options: extraOptions, ...finalOptions } = initialOptions; // delete the extra options
const options = finalOptions;

if (beforeCreate) {
const result = beforeCreate.bind(this)(options);

if (result instanceof Promise) {
return result.then(() => ({ options }));
}
}
return { options };
})
.then(({ options }) => {
const ConstructorObject = ctr();
// https://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible
this[instanceName] = ctrArgs
? new (Function.prototype.bind.call(
ConstructorObject,
null,
...ctrArgs(options, getPropsValues(this, props || {}))
))()
: new ConstructorObject(options);

bindProps(this, this[instanceName], mappedProps);
bindEvents(this, this[instanceName], events);

if (afterCreate) {
afterCreate.bind(this)(this[instanceName]);
}
return this[instanceName];
});

this[promiseName] = promise;
return { [promiseName]: promise };
},
destroyed() {
// Note: not all Google Maps components support maps
if (this[instanceName] && this[instanceName].setMap) {
this[instanceName].setMap(null);
}
},
...rest,
};
}

export default mapElement;
+ + \ No newline at end of file diff --git a/docs/vue-2-version/guide/map/index.html b/docs/vue-2-version/guide/map/index.html new file mode 100644 index 000000000..bdda2398d --- /dev/null +++ b/docs/vue-2-version/guide/map/index.html @@ -0,0 +1,69 @@ + + + + + +map | GmapVue Docs + + + + + +

map

Description

+

This component helps you to create a Google Map.

+

For more information read the Google Maps documentation +for map.

+

It is exported with the name GmapMap.

+

Variables

+

This component save the original map object instance provided by Google Maps in a property called $mapObject, as the +example below.

+
  this.$mapObject = new google.maps.Map(element, options);;
+

Source code

+
Click to se the source code of map.vue component
<template>
<div class="vue-map-container">
<div ref="vue-map" class="vue-map"></div>
<div class="vue-map-hidden">
<slot></slot>
</div>
<slot name="visible"></slot>
</div>
</template>

<script>
import mountableMixin from '../mixins/mountable';
import {
bindEvents,
bindProps,
getPropsValues,
twoWayBindingWrapper,
watchPrimitiveProperties,
} from '../utils/helpers';
import { mapMappedProps } from '../utils/mapped-props-by-map-element';

export default {
mixins: [mountableMixin],
props: {
center: {
type: Object,
required: true,
},
zoom: {
type: Number,
required: false,
},
heading: {
type: Number,
},
mapTypeId: {
type: String,
},
tilt: {
type: Number,
},
options: {
type: Object,
default: undefined,
},
},
data() {
return {
recyclePrefix: '__gmc__',
};
},
provide() {
this.$mapPromise = new Promise((resolve, reject) => {
this.$mapPromise = { resolve, reject };
});

return {
$mapPromise: this.$mapPromise,
};
},
computed: {
finalLat() {
return this.center && typeof this.center.lat === 'function'
? this.center.lat()
: this.center.lat;
},
finalLng() {
return this.center && typeof this.center.lng === 'function'
? this.center.lng()
: this.center.lng;
},
finalLatLng() {
return { lat: this.finalLat, lng: this.finalLng };
},
},
watch: {
zoom(zoom) {
if (this.$mapObject) {
this.$mapObject.setZoom(zoom);
}
},
},
beforeDestroy() {
const recycleKey = this.getRecycleKey();
if (window[recycleKey]) {
window[recycleKey].div = this.$mapObject.getDiv();
}
},
mounted() {
return this.$gmapApiPromiseLazy()
.then(() => {
const events = [
'bounds_changed',
'click',
'dblclick',
'drag',
'dragend',
'dragstart',
'idle',
'mousemove',
'mouseout',
'mouseover',
'resize',
'rightclick',
'tilesloaded',
];

// getting the DOM element where to create the map
const element = this.$refs['vue-map'];

// creating the map
const initialOptions = {
...this.options,
...getPropsValues(this, mapMappedProps),
};

// don't use delete keyword in order to create a more predictable code for the engine
const { options: extraOptions, ...finalOptions } = initialOptions;
const options = finalOptions;

const recycleKey = this.getRecycleKey();
if (this.options.recycle && window[recycleKey]) {
element.appendChild(window[recycleKey].div);
this.$mapObject = window[recycleKey].map;
this.$mapObject.setOptions(options);
} else {
// console.warn('[gmap-vue] New google map created')
this.$mapObject = new google.maps.Map(element, options);
window[recycleKey] = { map: this.$mapObject };
}

// binding properties (two and one way)
bindProps(this, this.$mapObject, mapMappedProps);
// binding events
bindEvents(this, this.$mapObject, events);

// manually trigger center and zoom
twoWayBindingWrapper((increment, decrement, shouldUpdate) => {
this.$mapObject.addListener('center_changed', () => {
if (shouldUpdate()) {
this.$emit('center_changed', this.$mapObject.getCenter());
}
decrement();
});

const updateCenter = () => {
increment();
this.$mapObject.setCenter(this.finalLatLng);
};

watchPrimitiveProperties(
this,
['finalLat', 'finalLng'],
updateCenter
);
});
this.$mapObject.addListener('zoom_changed', () => {
this.$emit('zoom_changed', this.$mapObject.getZoom());
});
this.$mapObject.addListener('bounds_changed', () => {
this.$emit('bounds_changed', this.$mapObject.getBounds());
});

this.$mapPromise.resolve(this.$mapObject);

return this.$mapObject;
})
.catch((error) => {
throw error;
});
},
methods: {
resize() {
if (this.$mapObject) {
google.maps.event.trigger(this.$mapObject, 'resize');
}
},
resizePreserveCenter() {
if (!this.$mapObject) {
return;
}

const oldCenter = this.$mapObject.getCenter();
google.maps.event.trigger(this.$mapObject, 'resize');
this.$mapObject.setCenter(oldCenter);
},

/// Override mountableMixin::_resizeCallback
/// because resizePreserveCenter is usually the
/// expected behaviour
// eslint-disable-next-line no-underscore-dangle -- old code
_resizeCallback() {
this.resizePreserveCenter();
},
panBy(...args) {
if (this.$mapObject) {
this.$mapObject.panBy(...args);
}
},
panTo(...args) {
if (this.$mapObject) {
this.$mapObject.panTo(...args);
}
},
panToBounds(...args) {
if (this.$mapObject) {
this.$mapObject.panToBounds(...args);
}
},
fitBounds(...args) {
if (this.$mapObject) {
this.$mapObject.fitBounds(...args);
}
},
getRecycleKey() {
return this?.options?.recycle
? this.recyclePrefix + this.options.recycle
: this.recyclePrefix;
},
},
};
</script>

<style lang="css">
.vue-map-container {
position: relative;
}

.vue-map-container .vue-map {
left: 0;
right: 0;
top: 0;
bottom: 0;
position: absolute;
}
.vue-map-hidden {
display: none;
}
</style>

+

If you need to know what are mappedProps please read the general concepts of this +application here.

+
Mapped Props of GmapMap component
export const mapMappedProps = {
center: {
required: true,
twoWay: true,
type: Object,
noBind: true,
},
zoom: {
required: false,
twoWay: true,
type: Number,
noBind: true,
},
heading: {
type: Number,
twoWay: true,
},
mapTypeId: {
twoWay: true,
type: String,
},
tilt: {
twoWay: true,
type: Number,
},
options: {
type: Object,
default() {
return {};
},
},
};
+
Events bound with to way on GmapMap
const events = [
'bounds_changed',
'click',
'dblclick',
'drag',
'dragend',
'dragstart',
'idle',
'mousemove',
'mouseout',
'mouseover',
'resize',
'rightclick',
'tilesloaded',
];
+

Some tricky parts

+

getBounds

+

If you need to use the getBounds method of the $mapObject you can do it with a reference as in the below example, +but if you use the getBounds method in the mounted hook you need to take care about three things:

+
    +
  1. the center should be defined
  2. +
  3. the zoom should be defined
  4. +
  5. the map should be visible
  6. +
+

In the official documentation +it says:

+
+

If the map is not yet initialized or center and zoom have not been set then the result is undefined.

+
+

Because of that behaviour you must listen for the tilesloaded event in the map component, this event is fired when the +maps is visible and allows you to accomplish with the three requirements mentioned above.

+
+

You can refer to the issue #67

+
+
<template>
<div>
<GmapMap
@tilesloaded="tilesloadedEvent"
:center="center"
:zoom="11"
style="width: 100%; height: 500px"
ref="gmap">
....
</GmapMap>
</div>
</template>

<script>
export default {
// ...
async mounted() {
// this is a good practice
await this.$gmapApiPromiseLazy();

// you can do the same in the following way but is more verbose
// this.$refs.gmap.$mapObject.addListener('tilesloaded', () => {
// console.log('>>>>>>>>>> getCenter', this.$refs.gmap.$mapObject.getCenter())
// console.log('>>>>>>>>>> getZoom', this.$refs.gmap.$mapObject.getZoom())
// console.log('>>>>>>>>>> getBounds', this.$refs.gmap.$mapObject.getBounds())
// });
},
methods: {
tilesloadedEvent() {
console.log('>>>>>>>>>> getCenter', this.$refs.gmap.$mapObject.getCenter())
console.log('>>>>>>>>>> getZoom', this.$refs.gmap.$mapObject.getZoom())
console.log('>>>>>>>>>> getBounds', this.$refs.gmap.$mapObject.getBounds())
}
}
};
</script>
+

PlacesService

+

If want to use the google.maps.places.PlacesService class we let you here an example about how to implement it.

+
+

You can refer to the issue #130

+
+
<template>
<div>
<GmapMap
:center="center"
:zoom="zoom"
style="width: 100%; height: 500px"
ref="googleMap"
>
</GmapMap>
</div>
</template>

<script>
import { getGoogleMapsAPI } from "gmap-vue";

export default {
data() {
return {
center: { lat: 10, lng: 10 },
zoom: 11,
};
},
async mounted() {
await this.$gmapApiPromiseLazy();

const google = getGoogleMapsAPI();
console.log(">>>>>>>>>>>> placesService", google.maps.places);
console.log(">>>>>>>>>>>> $mapObject", this.$refs.googleMap.$mapObject);

const service = new google.maps.places.PlacesService(
document.createElement("div") // if you pass the map object here it doesn't work
);

console.log("service", service);

const request = {
query: "Museum of Contemporary Art Australia",
fields: ["name", "geometry"],
};

const self = this;
service.findPlaceFromQuery(request, function (results, status) {
if (status === google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
console.log(results[i]);
}
self.$refs.googleMap.$mapObject.setCenter(results[0].geometry.location);
}
});
},
};
</script>
+

How to use it

+
<template>
<gmap-map
:center="center"
:zoom="7"
ref="mmm"
style="width: 100%; height: 500px;"
>
</gmap-map>
</template>
+

If you need to know the API of this component please read it here.

+

HTML examples

+
HTML example with center twoway
<head>
<meta charset="utf-8" />
<style>
.map-container {
width: 400px;
height: 400px;
display: inline-block;
}
.flex-container {
display: flex;
flex-direction: row;
justify-content: space-around;
}
</style>
</head>
<body>
<script>
var tests = [];

</script>

<div id="test1">
<h2>Test 1</h2>
<ol>
<li>You can pan around this map, and the center is updated.</li>
<li>When you edit the lat/lng the map center is updated</li>
</ol>

<div>
<small><strong>Lat:</strong></small>
<input type="number"
v-model.number.lazy="reportedMapCenter.lat"
@change="sync"
step="0.00001" />
&nbsp;
<small><strong>Lng:</strong></small>
<input type="number"
v-model.number.lazy="reportedMapCenter.lng"
@change="sync"
step="0.00001" />
</div>
<br>

<div class="flex-container">
<div>
<gmap-map :center="mapCenter" :zoom="12"
ref="map"
@center_changed="updateCenter"
@idle="sync"
class="map-container">
</gmap-map>
</div>
<div>
<gmap-street-view-panorama
:position="mapCenter"
ref="pano"
@position_changed="updateCenter"
:pov="pov"
class="map-container">
</gmap-street-view-panorama>
</div>
</div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc',
}
});

document.addEventListener('DOMContentLoaded', function() {
new Vue({
el: '#test1',
data: {
reportedMapCenter: {
lat: 1.32,
lng: 103.8
},
mapCenter: null,
pov: {
pitch: 0,
heading: 0,
},
},
created () {
this.sync()
},
methods: {
updateCenter(latLng) {
this.reportedMapCenter = {
lat: latLng.lat(),
lng: latLng.lng(),
}
},
sync () {
this.mapCenter = this.reportedMapCenter
}
}
});
});
</script>
</body>
+
HTML example with center
<head>
<style>
.map-container {
width: 400px;
height: 400px;
}
.flex-test3-container {
display: flex;
flex-direction: row;
justify-content: space-around;
}
.flex-test3-container > div {
display: flex;
flex-direction: row;
}
.flex-test3-container > div > small {
margin-right: .3rem;
font-size: 16px;
font-weight: bolder;
}
</style>
</head>
<body>
<script>
var tests = [];
</script>

<div id="test1">
<h2>Test 1</h2>
<small><strong>Passes if:</strong> You can pan around this map without it being snapped back to the center</small>
<br><br>
<gmap-map :center="{lat: 1.38, lng: 103.8}" :zoom="12"
class="map-container">
</gmap-map>
</div>
<script>
tests.push(() => {
new Vue({
el: '#test1',
});
});
</script>

<div id="test2">
<h2>Test 2</h2>
<small><strong>Passes if:</strong> Clicking the button changes the center</small>
<br>
<button @click="changeCenter">Change Center</button>&nbsp;
<button @click="changeZoom">Change Zoom</button>
<br><br>
<gmap-map :center="changingCenter" :zoom="changingZoom" class="map-container">
</gmap-map>
</div>
<script>
tests.push(() => {
new Vue({
el: '#test2',
data: {
changingZoom: 12,
changingCenter: {lat: 1.38, lng: 103.8},
},
methods: {
changeCenter() {
this.changingCenter = {
lat: 1.38 + Math.random() * 0.3,
lng: 103.8 + Math.random() * 0.1
};
},
changeZoom() {
this.changingZoom = Math.floor(5 + Math.random() * 10);
},
}
});
});
</script>

<div id="test3">
<h2>Test 3</h2>
<small><strong>Passes if:</strong> Resize of (1) is artefact-free.</small>
<br>
<small><strong>Passes if:</strong> Resize of (2) preserves the center</small>
<br>
<button @click="changeSize">Change Size</button>
<br><br>

<div class="flex-test3-container">
<div>
<small><strong>1</strong></small>
<gmap-map :center="changingCenter" :zoom="changingZoom" ref="resizeMap1"
:style="changingSize" class="map-container">
</gmap-map>
</div>
<div>
<small><strong>2</strong></small>
<gmap-map :center="changingCenter" :zoom="changingZoom" ref="resizeMap2"
:style="changingSize" class="map-container">
</gmap-map>
</div>
</div>
</div>
<script>
tests.push(() => new Vue({
el: '#test3',
data: {
changingZoom: 12,
changingCenter: {lat:1.38, lng:103.8},
changingWidth: 200,
changingHeight: 200,
i: 0,
},
computed: {
changingSize() {
return {
width: this.changingWidth + 'px',
height: this.changingHeight + 'px',
};
}
},
methods: {
changeCenter() {
this.changingCenter = {
lat: 1.38 + Math.random() * 0.3,
lng: 103.8 + Math.random() * 0.1
};
},
changeZoom() {
this.changingZoom = Math.floor(5 + Math.random() * 10);
},
changeSize() {
this.i = (this.i + 1) % 2;
this.changingWidth = 200 + this.i * 300;
this.changingHeight = 200 + Math.random() * 150;
this.$nextTick(() => {
this.$refs.resizeMap1.resize();
this.$refs.resizeMap2.resizePreserveCenter();
});
}
}
}));
</script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc',
}
});

document.addEventListener('DOMContentLoaded', function() {
Vue.component('gmap-map', GmapVue.Map);

for (let test of tests) {
test();
}
});
</script>
</body>
+
HTML example with destroy
<body>
<div id="root">
<h1>Resize Bus</h1>

<p>
There should be no error toggling the visibility of the maps
<button @click=updateStyle>
Toggle Visibility
</button>
</p>

<div v-if="showElements">
<gmap-map
:style="currentStyle"
:center="{lat: 1.38, lng: 103.8}"
:zoom=12>
</gmap-map>

<gmap-map
:style="currentStyle"
:center="{lat: 1.38, lng: 103.8}"
:zoom=12>
</gmap-map>

<gmap-map
:style="currentStyle"
:center="{lat: 1.38, lng: 103.8}"
:zoom=12
:resize-bus="customBus">
</gmap-map>
</div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc',
},
});

document.addEventListener('DOMContentLoaded', function() {
new Vue({
el: '#root',
data: {
currentStyle: {
display: 'inline-block',
width: '200px',
height: '200px',
},
showElements: true,
customBus: new Vue(),
},
methods: {
updateStyle() {
this.showElements = !this.showElements;
Vue.$gmapDefaultResizeBus.$emit('resize');
},
updateBus() {
this.customBus.$emit('resize');
}
}
});
});
</script>
</body>
+
HTML example of map functions
<body>
<div id="root">
<button @click="panTo">
Pan To
</button>

<button @click="panToBounds">
Pan To Bounds
</button>

<button @click="fitBounds">
Fit Bounds
</button>

<gmap-map :center="center" :zoom="7" ref="mmm" style="width: 100%; height: 500px">
<gmap-marker :key="index" v-for="(m, index) in markers" :position="m.position" :clickable="true" :draggable="true" @click="center=m.position"></gmap-marker>
</gmap-map>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc'
},
});

document.addEventListener('DOMContentLoaded', function() {
new Vue({
el: '#root',
data: {
center: {
lat: 10.0,
lng: 10.0
},
markers: [{
position: {
lat: 10.0,
lng: 10.0
}
}, {
position: {
lat: 11.0,
lng: 11.0
}
}]
},

methods: {
fitBounds() {
var b = new google.maps.LatLngBounds();

b.extend({
lat: 33.972,
lng: 35.4054
});
b.extend({
lat: 33.7606,
lng: 35.64592
});

this.$refs.mmm.fitBounds(b);
},
panToBounds() {
var b = new google.maps.LatLngBounds();

b.extend({
lat: 33.972,
lng: 35.4054
});
b.extend({
lat: 33.7606,
lng: 35.64592
});

this.$refs.mmm.panToBounds(b);
},
panTo() {
this.$refs.mmm.panTo({
lat: 47.912867,
lng: 106.910723
});
},
}
});
});
</script>
</body>
+
HTML example of map type id
<body>
<div id="root">
<p>Map type id <strong>{{mapTypeId}}</strong></p>

<gmap-map :center="center" :zoom="15" style="width: 100%; height: 500px"
@maptypeid_changed="updateMapType"
:map-type-id="mapTypeId">
</gmap-map>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc'
},
});

document.addEventListener('DOMContentLoaded', function() {
new Vue({
el: '#root',
data: {
center: {
lat: 47.376332,
lng: 8.547511
},
mapTypeId: "terrain",
},
methods: {
updateMapType: function(type) {
this.mapTypeId = type
}
}
});
});
</script>
</body>
+

Test the component

+
Click to see the HTML example with center two-way in action
+
Click to see the HTML example with center in action
+
Click to see the HTML example with destroy in action
+
Click to see the HTML example of map functions in action
+
Click to see the HTML example of map type id in action
+ + \ No newline at end of file diff --git a/docs/vue-2-version/guide/marker/index.html b/docs/vue-2-version/guide/marker/index.html new file mode 100644 index 000000000..836fe2e7a --- /dev/null +++ b/docs/vue-2-version/guide/marker/index.html @@ -0,0 +1,39 @@ + + + + + +marker | GmapVue Docs + + + + + +

marker

Description

+

This component helps you to create a marker in the map.

+

For more information read the Google Maps documentation +for markers.

+

It is exported with the name GmapMarker.

+

Variables

+

This component save the original marker object provided by Google Maps in a property called $kmlLayerObject, as the +example below.

+
  this.$markerObject = new google.maps.Marker(...);
+

Source code

+
Click to se the source code of marker-icon.vue component
<script>
import MapElementMixin from '../mixins/map-element';
import { getPropsValues, bindEvents, bindProps } from '../utils/helpers';
import { markerMappedProps } from '../utils/mapped-props-by-map-element';

export default {
name: 'MarkerIcon',
mixins: [MapElementMixin],
inject: {
$clusterPromise: {
default: null,
},
},
provide() {
const events = [
'click',
'rightclick',
'dblclick',
'drag',
'dragstart',
'dragend',
'mouseup',
'mousedown',
'mouseover',
'mouseout',
];

const promise = this.$mapPromise
.then((map) => {
this.$map = map;

// Initialize the maps with the given options
const initialOptions = {
// TODO: analyze the below line because I think it can be removed
...this.options,
map,
...getPropsValues(this, markerMappedProps),
};

const { options: extraOptions, ...finalOptions } = initialOptions;

if (this.$clusterPromise) {
finalOptions.map = null;
}

this.$markerObject = new google.maps.Marker(finalOptions);

bindProps(this, this.$markerObject, markerMappedProps);
bindEvents(this, this.$markerObject, events);

// From v3.1.0
this.$markerObject.addListener('dragend', () => {
const newPosition = this.$markerObject.getPosition();

this.$emit('update:position', {
lat: newPosition.lat(),
lng: newPosition.lng(),
});
});

if (this.$clusterPromise) {
this.$clusterPromise.then((clusterObject) => {
clusterObject.addMarker(this.$markerObject);
this.$clusterObject = clusterObject;
});
}

return this.$markerObject;
})
.catch((error) => {
throw error;
});

this.$markerPromise = promise;
return { $markerPromise: promise };
},
props: {
animation: {
type: Number,
default: undefined,
},
attribution: {
type: Object,
default: undefined,
},
clickable: {
type: Boolean,
default: true,
},
cursor: {
type: String,
default: undefined,
},
draggable: {
type: Boolean,
default: false,
},
icon: {
type: [String, Object],
default: undefined,
},
label: {
type: [String, Object],
default: undefined,
},
opacity: {
type: Number,
default: 1,
},
options: {
type: Object,
default: undefined,
},
place: {
type: Object,
default: undefined,
},
position: {
type: Object,
default: undefined,
},
shape: {
type: Object,
default: undefined,
},
title: {
type: String,
default: undefined,
},
visible: {
type: Boolean,
default: true,
},
zIndex: {
type: Number,
default: undefined,
},
},
destroyed() {
if (!this.$markerObject) {
return;
}

if (this.$clusterObject) {
// Repaint will be performed in `updated()` of cluster
this.$clusterObject.removeMarker(this.$markerObject, true);
} else if (this.$markerObject && this.$markerObject.setMap) {
this.$markerObject.setMap(null);
}
},
render(h) {
if (!this.$slots.default || this.$slots.default.length === 0) {
return '';
}
if (this.$slots.default.length === 1) {
// So that infowindows can have a marker parent
return this.$slots.default[0];
}

/**
* @slot Default slot of the component.
*/
return h('div', this.$slots.default);
},
};
</script>
+

If you need to know what are mappedProps please read the general concepts of this +application here.

+
Mapped Props of GmapMarker component
export const markerMappedProps = {
animation: {
twoWay: true,
type: Number,
},
attribution: {
type: Object,
},
clickable: {
type: Boolean,
twoWay: true,
default: true,
},
cursor: {
type: String,
twoWay: true,
},
draggable: {
type: Boolean,
twoWay: true,
default: false,
},
icon: {
twoWay: true,
},
label: {},
opacity: {
type: Number,
default: 1,
},
options: {
type: Object,
},
place: {
type: Object,
},
position: {
type: Object,
twoWay: true,
},
shape: {
type: Object,
twoWay: true,
},
title: {
type: String,
twoWay: true,
},
zIndex: {
type: Number,
twoWay: true,
},
visible: {
twoWay: true,
default: true,
},
};
+
Events bound with to way on GmapMarker
const events = [
'click',
'rightclick',
'dblclick',
'drag',
'dragstart',
'dragend',
'mouseup',
'mousedown',
'mouseover',
'mouseout',
];

update:position event (from v3.1.0)

From version 3.1.0 we emit the update:position when the Google Maps API fires the dragend event, it returns an +object in the form { lat: 10, lng: 10 }, in this way we start preparing the plugin to migrate to Vue v3 in a near +future and can use v-model on the position prop.

+

How to use it

+
<template>
<gmap-map :center="center" :zoom="7" style="width: 100%; height: 500px">
<gmap-marker
v-for="m in markers"
:position="m.position"
:clickable="true"
:draggable="true"
@click="center=m.position"
>
</gmap-marker>
</gmap-map>
</template>

<script>
export default {
data() {
return {
markers: [{
position: {
lat: 10.0,
lng: 10.0
}
}],
}
}
}
</script>
+

If you need to know the API of this component please read it here.

+

HTML examples

+
Basic marker HTML example
<body>
<div id="root">
<gmap-map :center="center" :zoom="7" style="width: 100%; height: 500px">
<gmap-marker v-for="m in markers" :position="m.position" :clickable="true" :draggable="true" @click="center=m.position"></gmap-marker>
</gmap-map>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc'
},
// Demonstrating how we can customize the name of the components
installComponents: false,
});

document.addEventListener('DOMContentLoaded', function() {
Vue.component('google-map', GmapVue.Map);
Vue.component('google-marker', GmapVue.Marker);

new Vue({
el: '#root',
data: {
center: {
lat: 10.0,
lng: 10.0
},
markers: [{
position: {
lat: 10.0,
lng: 10.0
}
}, {
position: {
lat: 11.0,
lng: 11.0
}
}]
},
});
});
</script>
</body>
+
Shape marker HTML example
<body>
<div id="root">
<p>Only the dark dots in the middle of the marker are clickable</p>

<google-map :center="center" :zoom="7" style="width: 100%; height: 500px">
<google-marker v-for="m in markers" :position="m.position" :clickable="true"
:draggable="true" @click="center=m.position" :shape="shape"></google-marker>
</google-map>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc'
},
// Demonstrating how we can customize the name of the components
installComponents: false,
});

document.addEventListener('DOMContentLoaded', function() {
Vue.component('google-map', GmapVue.Map);
Vue.component('google-marker', GmapVue.Marker);

new Vue({
el: '#root',
data: {
center: {
lat: 10.0,
lng: 10.0
},
markers: [{
position: {
lat: 10.0,
lng: 10.0
}
}, {
position: {
lat: 11.0,
lng: 11.0
}
}],
shape: {
coords: [10, 10, 10, 15, 15, 15, 15, 10],
type: 'poly'
},
},
});
});
</script>
</body>
+

Test the component

+
Click to see the basic marker HTML example in action
+
Click to see the shape marker HTML example in action
+ + \ No newline at end of file diff --git a/docs/vue-2-version/guide/place-input/index.html b/docs/vue-2-version/guide/place-input/index.html new file mode 100644 index 000000000..c845c28d0 --- /dev/null +++ b/docs/vue-2-version/guide/place-input/index.html @@ -0,0 +1,36 @@ + + + + + +place-input | GmapVue Docs + + + + + +

place-input

Description

+
danger

DEPRECATED, use autocomplete component instead.

+

This component helps you to create a place input it use the auto-complete API but was the first implementation of that API. +We encourage to use autocomplete component instead of this component, because it will be removed in the next major release.

+

For more information read the Google Maps documentation for autocomplete.

+

It is exported with the name GmapPlaceInput.

+

Variables

+

This component save the original autocomplete object provided by Google Maps in a property called autoCompleter, as the example below.

+
this.autoCompleter = new google.maps.places.Autocomplete(...);
+

Source code

+
Click to se the source code of autocomplete.vue component
<template>
<label>
<span v-text="label"></span>
<input
type="text"
:placeholder="placeholder"
:class="className"
ref="input"
/>
</label>
</template>

<script>
import MapElementMixin from '../mixins/map-element';
import {
bindProps,
downArrowSimulator,
getPropsValues,
} from '../utils/helpers';

export default {
mixins: [MapElementMixin],
props: {
bounds: {
type: Object,
},
defaultPlace: {
type: String,
default: '',
},
componentRestrictions: {
type: Object,
default: null,
},
types: {
type: Array,
default: undefined
},
placeholder: {
required: false,
type: String,
},
className: {
required: false,
type: String,
},
label: {
required: false,
type: String,
default: null,
},
selectFirstOnEnter: {
require: false,
type: Boolean,
default: false,
},
},
created() {
window.console.warn(
'The PlaceInput class is deprecated! Please consider using the Autocomplete input instead, it will be removed in the next major release of this plugin.'
);
},
mounted() {
const { input } = this.$refs;

// Allow default place to be set
input.value = this.defaultPlace;

this.$watch('defaultPlace', () => {
input.value = this.defaultPlace;
});

this.$gmapApiPromiseLazy().then(() => {
const options = getPropsValues(this, this.props);

if (this.selectFirstOnEnter) {
downArrowSimulator(this.$refs.input);
}

if (typeof google.maps.places.Autocomplete !== 'function') {
throw new Error(
"google.maps.places.Autocomplete is undefined. Did you add 'places' to libraries when loading Google Maps?"
);
}

this.autoCompleter = new google.maps.places.Autocomplete(
this.$refs.input,
options
);

const {
placeholder,
place,
defaultPlace,
className,
label,
selectFirstOnEnter,
...rest
} = this.props;

bindProps(this, this.autoCompleter, rest);

this.autoCompleter.addListener('place_changed', () => {
this.$emit('place_changed', this.autoCompleter.getPlace());
});
});
},
};
</script>
+

If you need to know what are mappedProps please read the general concepts of this application here.

+
Mapped Props of GmapAutocomplete component

This component does not has mapped props.

+

How to use it

+
<template>
<gmap-place-input :default-place="place"
@place_changed="setPlace">
</gmap-place-input>
</template>
+

If you need to know the API of this component please read it here.

+

HTML examples

+
basic HTML example
<body>
<div id="root">
<h1>Changing Default Place updates text box</h1>
<button @click="setPlaceText('Tokyo')">Set to Tokyo</button><br/>
<button @click="setPlaceText('Shanghai')">Set to Shanghai</button><br/>
<button @click="setPlaceText('Seoul')">Set to Seoul</button><br/>
<gmap-place-input :default-place="place"
@place_changed="setPlace">
</gmap-place-input>
<br/>
{{latLng.lat}},
{{latLng.lng}}
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc',
libraries: 'places'
},
});

document.addEventListener('DOMContentLoaded', function() {
new Vue({
el: '#root',
data: {
place: 'Singapore',
latLng: {}
},
methods: {
setPlaceText(place) {
this.place = place;
},
setPlace(place) {
this.latLng = {
lat: place.geometry.location.lat(),
lng: place.geometry.location.lng(),
};
}
}
});
});
</script>
</body>
+
Place input with default place HTML example
<body>
<div id="root">
<h1>Test</h1> "Singapore" should appear in the text box on page load. No errors in console.
<gmap-place-input default-place="Singapore" @place_changed="updatePlace">
</gmap-place-input>
{{place && place.lat}}, {{place && place.lng}},
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc',
libraries: 'places'
},
// Demonstrating how we can customize the name of the components
installComponents: true,
});

document.addEventListener('DOMContentLoaded', function() {
new Vue({
el: '#root',
data: {
place: null
},
methods: {
updatePlace(what) {
this.place = {
lat: what.geometry.location.lat(),
lng: what.geometry.location.lng()
};
}
}
});
});
</script>
</body>
+

Test the component

+
danger

DEPRECATED, use autocomplete component instead.

+
Basic Place Input example
+
Basic Place Input example
+ + \ No newline at end of file diff --git a/docs/vue-2-version/guide/polygon/index.html b/docs/vue-2-version/guide/polygon/index.html new file mode 100644 index 000000000..d075b2f4b --- /dev/null +++ b/docs/vue-2-version/guide/polygon/index.html @@ -0,0 +1,37 @@ + + + + + +polygon | GmapVue Docs + + + + + +

polygon

Description

+

This component helps you to create a polygon on Google Maps API.

+

For more information read the Google Maps documentation +for polygons.

+

It is exported with the name GmapPolygon.

+

Variables

+

This component save the original polygon object provided by Google Maps in a property called $polygonObject, as the +example below.

+
this.$polygonObject = new google.maps.Polygon(...);
+

Source code

+
Click to se the source code of polygon.vue component
<script>
import MapElementMixin from '../mixins/map-element';
import { getPropsValues, bindEvents, bindProps } from '../utils/helpers';
import { polygonMappedProps } from '../utils/mapped-props-by-map-element';

export default {
mixins: [MapElementMixin],
props: {
deepWatch: {
type: Boolean,
default: false,
},
clickable: {
type: Boolean,
default: false,
},
draggable: {
type: Boolean,
default: false,
},
editable: {
type: Boolean,
default: false,
},
fillColor: {
type: String,
default: '',
},
fillOpacity: {
type: Number,
default: 1,
},
strokeColor: {
type: String,
default: '',
},
strokeOpacity: {
type: Number,
default: 1,
},
strokePosition: {
type: Number,
default: 0,
},
strokeWeight: {
type: Number,
default: 1,
},
visible: {
type: Boolean,
default: true,
},
options: {
type: Object,
},
path: {
type: Array,
noBind: true,
},
paths: {
type: Array,
noBind: true,
},
},
provide() {
const events = [
'click',
'dblclick',
'drag',
'dragend',
'dragstart',
'mousedown',
'mousemove',
'mouseout',
'mouseover',
'mouseup',
'rightclick',
];

const promise = this.$mapPromise
.then((map) => {
this.$map = map;

const initialOptions = {
...this.options,
map,
...getPropsValues(this, polygonMappedProps),
};
const {
options: extraOptions,
path: optionPath,
paths: optionPaths,
...finalOptions
} = initialOptions;

this.$polygonObject = new google.maps.Polygon(finalOptions);

bindProps(this, this.$polygonObject, polygonMappedProps);
bindEvents(this, this.$polygonObject, events);

let clearEvents = () => {};

this.$watch(
'paths',
(paths) => {
if (paths) {
clearEvents();

this.$polygonObject.setPaths(paths);

const updatePaths = () => {
this.$emit('paths_changed', this.$polygonObject.getPaths());
};
const eventListeners = [];

const mvcArray = this.$polygonObject.getPaths();
for (let i = 0; i < mvcArray.getLength(); i += 1) {
const mvcPath = mvcArray.getAt(i);
eventListeners.push([
mvcPath,
mvcPath.addListener('insert_at', updatePaths),
]);
eventListeners.push([
mvcPath,
mvcPath.addListener('remove_at', updatePaths),
]);
eventListeners.push([
mvcPath,
mvcPath.addListener('set_at', updatePaths),
]);
}
eventListeners.push([
mvcArray,
mvcArray.addListener('insert_at', updatePaths),
]);
eventListeners.push([
mvcArray,
mvcArray.addListener('remove_at', updatePaths),
]);
eventListeners.push([
mvcArray,
mvcArray.addListener('set_at', updatePaths),
]);

clearEvents = () => {
eventListeners.forEach(([, listenerHandle]) => {
google.maps.event.removeListener(listenerHandle);
});
};
}
},
{
deep: this.deepWatch,
immediate: true,
}
);

this.$watch(
'path',
(path) => {
if (path) {
clearEvents();

this.$polygonObject.setPaths(path);

const mvcPath = this.$polygonObject.getPath();
const eventListeners = [];

const updatePaths = () => {
this.$emit('path_changed', this.$polygonObject.getPath());
};

eventListeners.push([
mvcPath,
mvcPath.addListener('insert_at', updatePaths),
]);
eventListeners.push([
mvcPath,
mvcPath.addListener('remove_at', updatePaths),
]);
eventListeners.push([
mvcPath,
mvcPath.addListener('set_at', updatePaths),
]);

clearEvents = () => {
eventListeners.forEach(([, listenerHandle]) => {
google.maps.event.removeListener(listenerHandle);
});
};
}
},
{
deep: this.deepWatch,
immediate: true,
}
);

return this.$polygonObject;
})
.catch((error) => {
throw error;
});

this.$polygonPromise = promise;
return { $polygonPromise: promise };
},
};
</script>
+

If you need to know what are mappedProps please read the general concepts of this +application here.

+
Mapped Props of GmapPolygon component
export const polygonMappedProps = {
clickable: {
type: Boolean,
noBind: true,
},
draggable: {
type: Boolean,
},
editable: {
type: Boolean,
},
fillColor: {
type: String,
noBind: true,
},
fillOpacity: {
type: Number,
noBind: true,
},
strokeColor: {
type: String,
noBind: true,
},
strokeOpacity: {
type: Number,
noBind: true,
},
strokePosition: {
type: Number,
noBind: true,
},
strokeWeight: {
type: Number,
noBind: true,
},
visible: {
type: Boolean,
},
options: {
type: Object,
},
path: {
type: Array,
twoWay: true,
noBind: true,
},
paths: {
type: Array,
twoWay: true,
noBind: true,
},
};
+
Events bound with to way on GmapPolygon
const events = [
'click',
'dblclick',
'drag',
'dragend',
'dragstart',
'mousedown',
'mousemove',
'mouseout',
'mouseover',
'mouseup',
'rightclick',
];
+

How to use it

+
<template>
<gmap-map
:center="{lat: 1.38, lng: 103.8}"
:zoom="12"
style="width: 100%; height: 500px">
<gmap-polygon
:paths="paths"
:editable="true"
@paths_changed="updateEdited($event)">
</gmap-polygon>
</gmap-map>
</template>
+

If you need to know the API of this component please read it here.

+

HTML examples

+
Simple polygon example
<body>
<div id="root">
<gmap-map :center="{lat: 1.38, lng: 103.8}" :zoom="12" style="width: 100%; height: 500px">
<gmap-polygon :paths="paths" :editable="true" @paths_changed="updateEdited($event)">
</gmap-polygon>
</gmap-map>

<ul v-if="edited" @click="edited = null">
<li v-for="path in edited">
<ol>
<li v-for="point in path">
{{point.lat}}, {{point.lng}}
</li>
</ol>
</li>
</ul>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc'
},
});

document.addEventListener('DOMContentLoaded', function() {
window.XXX = new Vue({
el: '#root',
data: {
edited: null,
paths: [
[ {lat: 1.380, lng: 103.800}, {lat:1.380, lng: 103.810}, {lat: 1.390, lng: 103.810}, {lat: 1.390, lng: 103.800} ],
[ {lat: 1.382, lng: 103.802}, {lat:1.382, lng: 103.808}, {lat: 1.388, lng: 103.808}, {lat: 1.388, lng: 103.802} ],
]
},
methods: {
updateEdited(mvcArray) {
let paths = [];
for (let i=0; i<mvcArray.getLength(); i++) {
let path = [];
for (let j=0; j<mvcArray.getAt(i).getLength(); j++) {
let point = mvcArray.getAt(i).getAt(j);
path.push({lat: point.lat(), lng: point.lng()});
}
paths.push(path);
}
this.edited = paths;
}
}
});
});
</script>
</body>
+
Advanced polygon example
<body>
<div id="root">
<label>
<strong>Start at:</strong>
<gmap-autocomplete @place_changed="updateCenter($event)" />
</label>

<br>
<br>

<gmap-map :center="center" :zoom="12" style="width: 100%; height: 500px" ref="map">
<gmap-polygon v-if="paths.length > 0" :paths="paths" :editable="true" @paths_changed="updateEdited($event)"
@rightclick="handleClickForDelete"
ref="polygon">
</gmap-polygon>
</gmap-map>

<div>
<button @click="addPath()">Add Path</button>
<button @click="removePath()">Remove Path</button>
</div>

<br>

<div>
<label for="geojson">
<strong>Paste your geojson here:</strong>
</label>
<textarea id="geojson" :value="polygonGeojson" style="width: 100%; height: 100px"
@input="readGeojson">
</textarea>
<div v-if="errorMessage">{{errorMessage}}</div>
</div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc',
libraries: 'places',
},
});

function closeLoop (path) {
return path.concat(path.slice(0, 1))
}

document.addEventListener('DOMContentLoaded', function() {
window.XXX = new Vue({
el: '#root',
data: {
center: {lat: 1.38, lng: 103.8},
edited: null,
paths: [
],
mvcPaths: null,
errorMessage: null,
polygonGeojson: '',
},
watch: {
polygonPaths: _.throttle(function (paths) {
if (paths) {
this.paths = paths
this.polygonGeojson = JSON.stringify({
type: 'Polygon',
coordinates: this.paths.map(path => closeLoop(path.map(({lat, lng}) => [lng, lat])))
}, null, 2)
}
}, 1000)
},
computed: {
polygonPaths: function () {
if (!this.mvcPaths) return null

let paths = [];
for (let i=0; i < this.mvcPaths.getLength(); i++) {
let path = [];
for (let j=0; j<this.mvcPaths.getAt(i).getLength(); j++) {
let point = this.mvcPaths.getAt(i).getAt(j);
path.push({lat: point.lat(), lng: point.lng()});
}
paths.push(path);
}
return paths
},
},
methods: {
updateCenter: function (place) {
this.center = {
lat: place.geometry.location.lat(),
lng: place.geometry.location.lng(),
}
},
updateEdited: function (mvcPaths) {
this.mvcPaths = mvcPaths
},
addPath: function () {
// obtain the bounds, so we can guess how big the polygon should be
var bounds = this.$refs.map.$mapObject.getBounds()
var northEast = bounds.getNorthEast()
var southWest = bounds.getSouthWest()
var center = bounds.getCenter()
var degree = this.paths.length + 1;
var f = Math.pow(0.66, degree)

// Draw a triangle. Use f to control the size of the triangle.
// i.e., every time we add a path, we reduce the size of the triangle
var path = [
{ lng: center.lng(), lat: (1-f) * center.lat() + (f) * northEast.lat() },
{ lng: (1-f) * center.lng() + (f) * southWest.lng(), lat: (1-f) * center.lat() + (f) * southWest.lat() },
{ lng: (1-f) * center.lng() + (f) * northEast.lng(), lat: (1-f) * center.lat() + (f) * southWest.lat() },
]

this.paths.push(path)
},
removePath: function () {
this.paths.splice(this.paths.length - 1, 1)
},
handleClickForDelete($event) {
if ($event.vertex) {
this.$refs.polygon.$polygonObject.getPaths()
.getAt($event.path)
.removeAt($event.vertex)
}
},
readGeojson: function ($event) {
try {
this.polygonGeojson = $event.target.value

var v = JSON.parse($event.target.value);

this.paths = v.coordinates.map(linearRing =>
linearRing.slice(0, linearRing.length - 1)
.map(([lng, lat]) => ({lat, lng}))
)

this.errorMessage = null
} catch (err) {
this.errorMessage = err.message
}
}
}
});
});
</script>
</body>
+

Test the component

+
Simple polygon
+
Advanced polygon
+ + \ No newline at end of file diff --git a/docs/vue-2-version/guide/polyline/index.html b/docs/vue-2-version/guide/polyline/index.html new file mode 100644 index 000000000..51c45d9aa --- /dev/null +++ b/docs/vue-2-version/guide/polyline/index.html @@ -0,0 +1,35 @@ + + + + + +polyline | GmapVue Docs + + + + + +

polyline

Description

+

This component helps you to create a polyline on Google Maps API.

+

For more information read the Google Maps documentation +for polyline.

+

It is exported with the name GmapPolyline.

+

Variables

+

This component save the original polygon object provided by Google Maps in a property called $polylineObject, as the +example below.

+
this.$polylineObject = new google.maps.Polyline(...);
+

Source code

+
Click to se the source code of polyline.vue component
<script>
import mapElementMixin from '../mixins/map-element';
import { getPropsValues, bindEvents, bindProps } from '../utils/helpers';
import { polylineMappedProps } from '../utils/mapped-props-by-map-element';

export default {
mixins: [mapElementMixin],
props: {
deepWatch: {
type: Boolean,
default: false,
},
clickable: {
type: Boolean,
default: false,
},
draggable: {
type: Boolean,
},
editable: {
type: Boolean,
},
strokeColor: {
type: String,
default: '',
},
strokeOpacity: {
type: Number,
default: 1,
},
strokeWeight: {
type: Number,
default: 1,
},
visible: {
type: Boolean,
default: true,
},
options: {
type: Object,
},
path: {
type: Array,
},
},
provide() {
const events = [
'click',
'dblclick',
'drag',
'dragend',
'dragstart',
'mousedown',
'mousemove',
'mouseout',
'mouseover',
'mouseup',
'rightclick',
];

const promise = this.$mapPromise
.then((map) => {
this.$map = map;

const initialOptions = {
...this.options,
map,
...getPropsValues(this, polylineMappedProps),
};
const { options: extraOptions, ...finalOptions } = initialOptions;

this.$polylineObject = new google.maps.Polyline(finalOptions);

bindProps(this, this.$polylineObject, polylineMappedProps);
bindEvents(this, this.$polylineObject, events);

let clearEvents = () => {};

this.$watch(
'path',
(path) => {
if (path) {
clearEvents();

this.$polylineObject.setPath(path);

const mvcPath = this.$polylineObject.getPath();
const eventListeners = [];

const updatePaths = () => {
this.$emit('path_changed', this.$polylineObject.getPath());
};

eventListeners.push([
mvcPath,
mvcPath.addListener('insert_at', updatePaths),
]);
eventListeners.push([
mvcPath,
mvcPath.addListener('remove_at', updatePaths),
]);
eventListeners.push([
mvcPath,
mvcPath.addListener('set_at', updatePaths),
]);

clearEvents = () => {
eventListeners.forEach(([, listenerHandle]) => {
google.maps.event.removeListener(listenerHandle);
});
};
}
},
{
deep: this.deepWatch,
immediate: true,
}
);

return this.$polylineObject;
})
.catch((error) => {
throw error;
});

this.$polylinePromise = promise;
return { $polylinePromise: promise };
},
};
</script>
+

If you need to know what are mappedProps please read the general concepts of this +application here.

+
Mapped Props of GmapPolyline component
export const polylineMappedProps = {
clickable: {
type: Boolean,
noBind: true,
},
draggable: {
type: Boolean,
},
editable: {
type: Boolean,
},
strokeColor: {
type: String,
noBind: true,
},
strokeOpacity: {
type: Number,
noBind: true,
},
strokeWeight: {
type: Number,
noBind: true,
},
visible: {
type: Boolean,
},
options: {
twoWay: false,
type: Object,
},
path: {
type: Array,
twoWay: true,
},
};
+
Events bound with to way on GmapPolyline
const events = [
'click',
'dblclick',
'drag',
'dragend',
'dragstart',
'mousedown',
'mousemove',
'mouseout',
'mouseover',
'mouseup',
'rightclick',
];
+

How to use it

+
<template>
<gmap-map
:center="center"
:zoom="12"
style="width: 100%; height: 500px"
ref="map">
<gmap-polyline
v-if="path.length > 0"
:path="path"
:editable="true"
@path_changed="updateEdited($event)"
@rightclick="handleClickForDelete"
ref="polyline">
</gmap-polyline>
</gmap-map>
</template>
+

If you need to know the API of this component please read it here.

+

HTML examples

+
Simple polyline example
<body>
<div id="root">
<label>
Start at:
<gmap-autocomplete @place_changed="updateCenter($event)" />
</label>

<gmap-map :center="center" :zoom="12" style="width: 100%; height: 500px" ref="map">
<gmap-polyline v-if="path.length > 0" :path="path" :editable="true" @path_changed="updateEdited($event)"
@rightclick="handleClickForDelete"
ref="polyline">
</gmap-polyline>
</gmap-map>

<div>
<textarea :value="polylineGeojson" style="width: 100%; height: 200px"
@input="readGeojson">
</textarea>
<div v-if="errorMessage">{{errorMessage}}</div>
</div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc',
libraries: 'places',
},
});

document.addEventListener('DOMContentLoaded', function() {
window.XXX = new Vue({
el: '#root',
data: {
center: {lat: 1.38, lng: 103.8},
edited: null,
path: [
{lat: 1.33, lng: 103.75},
{lat: 1.43, lng: 103.85},
],
mvcPath: null,
errorMessage: null,
polylineGeojson: '',
},
watch: {
polylinePath: _.throttle(function (path) {
if (path) {
this.path = path
this.polylineGeojson = JSON.stringify({
type: 'Polyline',
coordinates: this.path.map(({lat, lng}) => [lng, lat])
}, null, 2)
}
}, 1000)
},
computed: {
polylinePath: function () {
if (!this.mvcPath) return null

let path = [];
for (let j=0; j<this.mvcPath.getLength(); j++) {
let point = this.mvcPath.getAt(j);
path.push({lat: point.lat(), lng: point.lng()});
}
return path
},
},
methods: {
updateCenter: function (place) {
this.center = {
lat: place.geometry.location.lat(),
lng: place.geometry.location.lng(),
}
},
updateEdited: function (mvcPath) {
this.mvcPath = mvcPath
},
handleClickForDelete($event) {
if ($event.vertex) {
this.$refs.polyline.$polylineObject.getPaths()
.getAt($event.path)
.removeAt($event.vertex)
}
},
readGeojson: function ($event) {
try {
this.polylineGeojson = $event.target.value

var v = JSON.parse($event.target.value);

this.path = v.coordinates
.map(([lng, lat]) => ({lat, lng}))

this.errorMessage = null
} catch (err) {
this.errorMessage = err.message
}
}
}
});
});
</script>
</body>
+

Test the component

+
+ + \ No newline at end of file diff --git a/docs/vue-2-version/guide/promise-lazy-factory/index.html b/docs/vue-2-version/guide/promise-lazy-factory/index.html new file mode 100644 index 000000000..44fc789ae --- /dev/null +++ b/docs/vue-2-version/guide/promise-lazy-factory/index.html @@ -0,0 +1,17 @@ + + + + + +The promizeLazy factory | GmapVue Docs + + + + + +

The promizeLazy factory

+

The current code of the promizeLazy factory function.

+

You can find the API documentation here.

+
import { getLazyValue } from '../helpers';

function getPromiseLazyCreatorFn(googleMapsApiInitializer, GoogleMapsApi) {
const promiseLazyCreator = (options) => {
/**
* Things to do once the API is loaded
*
* @returns {Object} the Google Maps API object
*/
function onMapsReady() {
GoogleMapsApi.isReady = true;
return window.google;
}

// If library should load the API
if (options.load) {
return getLazyValue(() => {
// This will only be evaluated once
if (typeof window === 'undefined') {
// server side -- never resolve this promise
return new Promise(() => {}).then(onMapsReady);
}

return new Promise((resolve, reject) => {
try {
window.GoogleMapsCallback = resolve;
googleMapsApiInitializer(options.load, options.loadCn);
} catch (err) {
reject(err);
}
}).then(onMapsReady);
});
}

// If library should not handle API, provide
// end-users with the global `GoogleMapsCallback: () => undefined`
// when the Google Maps API has been loaded
const promise = new Promise((resolve) => {
if (typeof window === 'undefined') {
// Do nothing if run from server-side
return;
}
window.GoogleMapsCallback = resolve;
}).then(onMapsReady);

return getLazyValue(() => promise);
};

return promiseLazyCreator;
}

export default getPromiseLazyCreatorFn;
+ + \ No newline at end of file diff --git a/docs/vue-2-version/guide/rectangle/index.html b/docs/vue-2-version/guide/rectangle/index.html new file mode 100644 index 000000000..e9800a9f7 --- /dev/null +++ b/docs/vue-2-version/guide/rectangle/index.html @@ -0,0 +1,37 @@ + + + + + +rectangle | GmapVue Docs + + + + + +

rectangle

Description

+

This component helps you to create a rectangle on Google Maps API.

+

For more information read the Google Maps documentation +for rectangle.

+

It is exported with the name GmapRectangle.

+

Variables

+

This component save the original polygon object provided by Google Maps in a property called $rectangleObject, as the +example below.

+
this.$rectangleObject = new google.maps.Rectangle(...);
+

Source code

+
Click to se the source code of rectangle.vue component
<script>
import MapElementMixin from '../mixins/map-element';
import { bindProps, bindEvents, getPropsValues } from '../utils/helpers';
import { rectangleMappedProps } from '../utils/mapped-props-by-map-element';

export default {
mixins: [MapElementMixin],
props: {
bounds: {
type: Object,
default: undefined,
},
clickable: {
type: Boolean,
default: false,
},
draggable: {
type: Boolean,
default: false,
},
editable: {
type: Boolean,
default: false,
},
fillColor: {
type: String,
default: '',
},
fillOpacity: {
type: Number,
default: 1,
},
strokeColor: {
type: String,
default: '',
},
strokeOpacity: {
type: Number,
default: 1,
},
strokePosition: {
type: Number,
default: 0,
},
strokeWeight: {
type: Number,
default: 1,
},
visible: {
type: Boolean,
default: true,
},
options: {
type: Object,
},
},
provide() {
const events = [
'click',
'dblclick',
'drag',
'dragend',
'dragstart',
'mousedown',
'mousemove',
'mouseout',
'mouseover',
'mouseup',
'rightclick',
];

const promise = this.$mapPromise
.then((map) => {
this.$map = map;

const initialOptions = {
...this.options,
map,
...getPropsValues(this, rectangleMappedProps),
};
const { options: extraOptions, ...finalOptions } = initialOptions;

this.$rectangleObject = new google.maps.Rectangle(finalOptions);

bindProps(this, this.$rectangleObject, rectangleMappedProps);
bindEvents(this, this.$rectangleObject, events);

return this.$rectangleObject;
})
.catch((error) => {
throw error;
});

this.$rectanglePromise = promise;
return { $rectanglePromise: promise };
},
};
</script>
+

If you need to know what are mappedProps please read the general concepts of this +application here.

+
Mapped Props of GmapRectangle component
export const rectangleMappedProps = {
bounds: {
type: Object,
twoWay: true,
},
clickable: {
type: Boolean,
noBind: true,
},
draggable: {
type: Boolean,
default: false,
},
editable: {
type: Boolean,
default: false,
},
fillColor: {
type: String,
noBind: true,
},
fillOpacity: {
type: Number,
noBind: true,
},
strokeColor: {
type: String,
noBind: true,
},
strokeOpacity: {
type: Number,
noBind: true,
},
strokePosition: {
type: Number,
noBind: true,
},
strokeWeight: {
type: Number,
noBind: true,
},
visible: {
type: Boolean,
},
options: {
type: Object,
twoWay: false,
},
};
+
Events bound with to way on GmapRectangle
const events = [
'click',
'dblclick',
'drag',
'dragend',
'dragstart',
'mousedown',
'mousemove',
'mouseout',
'mouseover',
'mouseup',
'rightclick',
];
+

How to use it

+
<template>
<gmap-map
:center="center"
:zoom="12"
style="width: 100%; height: 500px"
ref="map">
<gmap-rectangle
:bounds="{
north: 33.685,
south: 33.671,
east: -116.234,
west: -116.251,
}"
:draggable="true"
:editable="true"
ref="rectangle">
</gmap-rectangle>
</gmap-map>
</template>
+

If you need to know the API of this component please read it here.

+

HTML examples

+
Simple rectangle example

We use the +following example of the +google documentation.

<body>
<div id="root">
<gmap-map :center="center" :zoom="11" style="width: 100%; height: 500px" ref="map">
<gmap-rectangle
:editable="editable"
:draggable="draggable"
:bounds="bounds"
:options="options"
ref="rectangle">
</gmap-rectangle>
</gmap-map>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc',
libraries: 'places',
},
});

document.addEventListener('DOMContentLoaded', function() {
window.rectangleExample = new Vue({
el: '#root',
data: {
center: { lat: 33.678, lng: -116.243 },
editable: true,
draggable: true,
bounds: {
north: 33.685,
south: 33.671,
east: -116.234,
west: -116.251,
},
options: {
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35,
},
},
});
});
</script>
</body>
+

Test the component

+
+ + \ No newline at end of file diff --git a/docs/vue-2-version/guide/street-view-panorama/index.html b/docs/vue-2-version/guide/street-view-panorama/index.html new file mode 100644 index 000000000..b3296d5e1 --- /dev/null +++ b/docs/vue-2-version/guide/street-view-panorama/index.html @@ -0,0 +1,35 @@ + + + + + +street-view-panorama | GmapVue Docs + + + + + +

street-view-panorama

Description

+

This component helps you to create a street view panorama on Google Maps API.

+

For more information read the Google Maps documentation +for street view panorama.

+

It is exported with the name GmapStreetViewPanorama.

+

Variables

+

This component save the original street view panorama object provided by Google Maps in a property called $panoObject, +as the example below.

+
this.$panoObject = new google.maps.StreetViewPanorama(element, options);
+

Source code

+
Click to se the source code of street-view-panorama.vue component
<template>
<div class="vue-street-view-pano-container">
<div ref="vue-street-view-pano" class="vue-street-view-pano"></div>
<slot></slot>
</div>
</template>

<script>
import MountableMixin from '../mixins/mountable';
import {
bindEvents,
bindProps,
getPropsValues,
twoWayBindingWrapper,
watchPrimitiveProperties,
} from '../utils/helpers';
import { streetViewPanoramaMappedProps } from '../utils/mapped-props-by-map-element';

export default {
mixins: [MountableMixin],
props: {
zoom: {
type: Number,
},
pov: {
type: Object,
},
position: {
type: Object,
},
pano: {
type: String,
},
motionTracking: {
type: Boolean,
},
visible: {
type: Boolean,
default: true,
},
options: {
type: Object,
default: undefined,
},
},
replace: false,
computed: {
finalLat() {
return this.position && typeof this.position.lat === 'function'
? this.position.lat()
: this.position.lat;
},
finalLng() {
return this.position && typeof this.position.lng === 'function'
? this.position.lng()
: this.position.lng;
},
finalLatLng() {
return {
lat: this.finalLat,
lng: this.finalLng,
};
},
},
watch: {
zoom(zoom) {
if (this.$panoObject) {
this.$panoObject.setZoom(zoom);
}
},
},
methods: {
resize() {
if (this.$panoObject) {
google.maps.event.trigger(this.$panoObject, 'resize');
}
},
},
mounted() {
const events = ['closeclick', 'status_changed'];

return this.$gmapApiPromiseLazy()
.then(() => {
const element = this.$refs['vue-street-view-pano'];

const options = {
...this.options,
...getPropsValues(this, streetViewPanoramaMappedProps),
};
delete options.options;

this.$panoObject = new google.maps.StreetViewPanorama(element, options);

bindProps(this, this.$panoObject, streetViewPanoramaMappedProps);
bindEvents(this, this.$panoObject, events);

twoWayBindingWrapper((increment, decrement, shouldUpdate) => {
increment();

this.$panoObject.addListener('position_changed', () => {
if (shouldUpdate()) {
this.$emit('position_changed', this.$panoObject.getPosition());
}
decrement();
});

const updateCenter = () => {
increment();
this.$panoObject.setPosition(this.finalLatLng);
};

watchPrimitiveProperties(
this,
['finalLat', 'finalLng'],
updateCenter
);
});

this.$panoPromiseDeferred.resolve(this.$panoObject);

return this.$panoPromise;
})
.catch((error) => {
throw error;
});
},
provide() {
const promise = new Promise((resolve, reject) => {
this.$panoPromiseDeferred = { resolve, reject };
});
return {
$panoPromise: promise,
$mapPromise: promise,
};
},
};
</script>

<style lang="css">
.vue-street-view-pano-container {
position: relative;
}

.vue-street-view-pano-container .vue-street-view-pano {
left: 0;
right: 0;
top: 0;
bottom: 0;
position: absolute;
}
</style>
+

If you need to know what are mappedProps please read the general concepts of this +application here.

+
Events bound with to way on GmapPolyline
const events = ['closeclick', 'status_changed'];
+

How to use it

+
<template>
<div class="flex-container">
<div>
<gmap-map :center="mapCenter" :zoom="12"
ref="map"
@center_changed="updateCenter"
@idle="sync"
class="map-container">
</gmap-map>
</div>
<div>
<gmap-street-view-panorama
ref="pano"
:position="mapCenter"
:pov="pov"
:zoom="1"
class="map-container"
@position_changed="updateCenter"
@pano_changed="updatePano"
@pov_changed="updatePov">
</gmap-street-view-panorama>
</div>
</div>
</template>
+

If you need to know the API of this component please read it here.

+

HTML examples

+
Street view panorama
<head>
<style>
.map-container {
width: 400px;
height: 400px;
display: inline-block;
}
.flex-container {
display: flex;
flex-direction: row;
justify-content: space-around;
}
</style>
</head>
<body>
<div id="root">
<h3>Panorama at Pembroke College, Cambridge, facing North, looking slightly upwards (10 degrees)</h3>
<p>Point-of-view updates when you pan around</p>
<ul>
<li><strong>Heading:</strong> <i>{{pov && pov.heading}}</i> <button @click="pov.heading = Math.random() * 360">Change</button></li>
<li><strong>Pitch:</strong> <i>{{pov && pov.pitch}}</i> <button @click="pov.pitch = Math.random() * 180 - 90">Change</button></li>
<li> <strong>Change booth:</strong> <button @click="pov.pitch = Math.random() * 180 - 90, pov.heading = Math.random() * 360">Change Both</button></li>
<li><strong>Pano ID:</strong> <i>{{pano}}</i></li>
</ul>
<br><br>
<div class="flex-container">
<div>
<gmap-map :center="mapCenter" :zoom="12"
ref="map"
@center_changed="updateCenter"
@idle="sync"
class="map-container">
</gmap-map>
</div>
<div>
<gmap-street-view-panorama
ref="pano"
:position="mapCenter"
:pov="pov"
:zoom="1"
class="map-container"
@position_changed="updateCenter"
@pano_changed="updatePano"
@pov_changed="updatePov">
</gmap-street-view-panorama>
</div>
</div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.min.js"></script>

<script>
Vue.use(GmapVue, {
load: {
key: 'AIzaSyDf43lPdwlF98RCBsJOFNKOkoEjkwxb5Sc',
libraries: 'places'
},
// Demonstrating how we can customize the name of the components
installComponents: true,
});

document.addEventListener('DOMContentLoaded', function() {
new Vue({
el: '#root',
data: {
reportedMapCenter: {
lat: 52.201272,
lng: 0.118720
},
mapCenter: null,
pov: {
heading: 0,
pitch: 0,
},
pano: 0,
},
methods: {
updatePov(pov) {
this.pov = pov;
},
updatePano(pano) {
this.pano = pano;
},
updateCenter(latLng) {
this.reportedMapCenter = {
lat: latLng.lat(),
lng: latLng.lng(),
}
},
sync () {
this.mapCenter = this.reportedMapCenter
}
},
created() {
this.sync()
},
});
});
</script>
</body>
+

Test the component

+
warning

Experimental

+
+ + \ No newline at end of file diff --git a/docs/vue-2-version/index.html b/docs/vue-2-version/index.html new file mode 100644 index 000000000..966bdc6e3 --- /dev/null +++ b/docs/vue-2-version/index.html @@ -0,0 +1,194 @@ + + + + + +Welcome | GmapVue Docs + + + + + +

Welcome

About GmapVue

+
danger

This version is no longer maintained because of the EOL of Vue 2.

+

GmapVue is a fork from vue2-google-maps.

+

This project has all features added to vue2-google-maps plugin up +to v0.10.8, but in the case of gmap-vue it has ** +the last features** added to vue2-google-maps repository by the community developers in many PRs, that they can't +landed in a new version of that project, for different reasons.

+

Because of that we fork the project and plain to continue working and adding new features to this great plugin.

+

Breaking changes

+
warning

We have planned to change all components names and file names to the same way that they are registered for the next +major release (v4.0.0).

+

v3.0.0

+
    +
  • autobindAllEvents config option was renamed to autoBindAllEvents
  • +
  • vueGoogleMapsInit name was renamed to GoogleMapsCallback
  • +
  • gmapApi function was renamed to getGoogleMapsAPI
  • +
  • MapElementMixin now is exported from components object instead of helpers object
  • +
  • customCallback config option was added to reuse existing Google Maps API that already loaded, eg from an HTML file
  • +
+

v2.0.0

+
    +
  • +

    All components were rewriting in SFC (.vue)

    +
  • +
  • +

    MarkerCluster was renamed to Cluster

    +
  • +
  • +

    @google/markerclustererplus was replace for @googlemaps/markerclusterer

    +
  • +
  • +

    The plugin exports two main objects:

    +
      +
    • components: it has all components and mountable mixin)
    • +
    • helpers: it has promise lazy factory function, gmapApi function and map element mixin
    • +
    +
  • +
  • +

    The plugin now exports by default the install function, this means that you can do the following

    +
  • +
  • +

    From v2.0.0 and above, the autocomplete component uses the default slot instead of the named input slot, +from v1.5.0 the input slot on the autocomplete component still works.

    +
    import GmapVue from 'gmap-vue';
    +

    instead of

    +
    import * as GmapVue from 'gmap-vue';
    +
  • +
+

Installation

+

npm

+
npm install gmap-vue --save
+

yarn

+
yarn add gmap-vue
+

Manually

+

Just download dist/gmap-vue.js file and include it from your HTML.

+
<script src="./gmap-vue.js"></script>
+

jsdelivr

+

You can use a free CDN like jsdelivr to include this plugin in your html file

+
<script src="https://cdn.jsdelivr.net/npm/gmap-vue@1.2.2/dist/gmap-vue.js"></script>
+

unpkg

+

You can use a free CDN like unpkg to include this plugin in your html file

+
<script src="https://unpkg.com/gmap-vue@1.2.2/dist/gmap-vue.js"></script>
+
warning

Be aware that if you use this method, you cannot use TitleCase for your components and your attributes. +That is, instead of writing <GmapMap>, you need to write <gmap-map>.

+

Live example.

+
warning

Vue-CLI v4 applications

For those application that use vue-cli v4 you will need to add the following dependencies and configuration to +your vue.config.js file

npm install --save-dev babel-loader @babel/preset-env @babel/plugin-proposal-optional-chaining @babel/plugin-proposal-nullish-coalescing-operator
// vue.config.js

module.exports = {
chainWebpack: (config) => {
config.module
.rule('mjs')
.test({
test: /\.mjs$/,
})
.use('babel-loader')
.loader('babel-loader')
.options({
presets: ['@babel/preset-env'],
plugins: [
'@babel/plugin-proposal-optional-chaining',
'@babel/plugin-proposal-nullish-coalescing-operator',
],
})
.end()
},
}
+

Basic usage

+

Get an API key from Google

+

Generating an Google Maps API key.

+

Quickstart (Webpack, Nuxt):

+

If you are using Webpack and Vue file components, just add the following to your code!

+

In your main.js or inside a Nuxt plugin:

+
import Vue from 'vue'
import GmapVue from 'gmap-vue'

Vue.use(GmapVue, {
load: {
// [REQUIRED] This is the unique required value by Google Maps API
key: 'YOUR_API_TOKEN',
// [OPTIONAL] This is required if you use the Autocomplete plugin
// OR: libraries: 'places,drawing'
// OR: libraries: 'places,drawing,visualization'
// (as you require)
libraries: 'places',

// [OPTIONAL] If you want to set the version, you can do so:
v: '3.26',

// This option was added on v3.0.0 but will be removed in the next major release.
// If you already have an script tag that loads Google Maps API and you want to use it set you callback
// here and our callback `GoogleMapsCallback` will execute your custom callback at the end; it must attached
// to the `window` object, is the only requirement.
customCallback: 'MyCustomCallback',
},

// [OPTIONAL] If you intend to programmatically custom event listener code
// (e.g. `this.$refs.gmap.$on('zoom_changed', someFunc)`)
// instead of going through Vue templates (e.g. `<GmapMap @zoom_changed="someFunc">`)
// you might need to turn this on.
autoBindAllEvents: false,

// [OPTIONAL] If you want to manually install components, e.g.
// import {GmapMarker} from 'gmap-vue/src/components/marker'
// Vue.component('GmapMarker', GmapMarker)
// then set installComponents to 'false'.
// If you want to automatically install all the components this property must be set to 'true':
installComponents: true,

// Load the Google Maps API dynamically, if you set this to `true` the plugin doesn't load the Google Maps API
dynamicLoad: false,
})
+
tip

v3.2.0

From v3.2.0 when you load the Google Maps API externally, from an HTML file for example, now you can load the plugin +without any load option, and you don't need to change anything from you Google Map script tag in the HTML file, in that +sort of cases if the callback is not called after 1 second from be initialized the plugin will be check every 0.5 +second if the object window.google.maps is populated and ready to use it.

v3.0.0

We encourage to use the new way introduced from v3.2.0 and explained above

If you already have an script tag that loads Google Maps API and you want to use it set you callback in +the customCallback option and our GoogleMapsCallback callback will execute your custom callback at the end.

It must attached to the window object, is the only requirement.

window.MyCustomCallback = () => { console.info('MyCustomCallback was executed') }
+
warning

The new option customCallback inside the load object in the plugin configuration will be removed in the next major +version.

+

In you components or .vue files add the following

+
<GmapMap
:center="{lat:10, lng:10}"
:zoom="7"
map-type-id="terrain"
style="width: 500px; height: 300px"
>
<GmapMarker
:key="index"
v-for="(m, index) in markers"
:position="m.position"
:clickable="true"
:draggable="true"
@click="center=m.position"
/>
</GmapMap>
+

Dynamic load

+
tip

Available from v3.3.0 and above

+

If you need to initialize the Google Maps API in a dynamic way you can use the dynamicLoad option of the plugin +configuration, this option start the plugin but it doesn't load the Google Maps API, you need to load it manually using +the googleMapsApiInitializer helper as we show below

+
<script>
import { helpers } from 'gmap-vue';
const { googleMapsApiInitializer } = helpers;

export default {
// ...
mounted() {
googleMapsApiInitializer({
key: 'ABCDEF',
}, false);
}
// ...
}
</script>
+

If you want to know the googleMapsApiInitializer API please check +it here +.

+

The three main utilities

+

The plugin exports two main useful function and one important object, they are references to the same memory places.

+

In your components you have access to the following instance properties:

+
  this.$gmapDefaultResizeBus; // this is the default resize function used if you not provide you own resize function
this.$gmapApiPromiseLazy; // this is the promise that you need to wait to be sure that the plugin is ready
this.$gmapOptions; // this is the final set of options passed to the Google Maps API
+

In the main Vue instance you have access to the following static properties:

+
  Vue.$gmapDefaultResizeBus; // this is the default resize function used if you not provide you own resize function
Vue.$gmapApiPromiseLazy; // this is the promise that you need to wait to be sure that the plugin is ready
Vue.$gmapOptions; // this is the final set of options passed to the Google Maps API
+

Getting a map reference

+

If you need to gain access to the Map instance (e.g. to call panToBounds, panTo):

+
<template>
<GmapMap ref="mapRef" ...>
</GmapMap>
</template>
<script>
export default {
mounted () {
// At this point, the child GmapMap has been mounted, but
// its map has not been initialized.
// Therefore we need to write mapRef.$mapPromise.then(() => ...)

this.$refs.mapRef.$mapPromise.then((map) => {
map.panTo({lat: 1.38, lng: 103.80})
})
}
}
</script>
+

Accessing Google Maps API

+
warning
    +
  • From v3.0.0 and above the function is exported as getGoogleMapsAPI.
  • +
  • Versions below v3.0.0 export the function as gmapApi
  • +
+

If you need to access the Google maps API directly you can use the exported getGoogleMapsAPI() function like this

+
<template>
<GmapMap ref="mapRef" ...>
<GmapMarker ref="myMarker" :position="google && new google.maps.LatLng(1.38, 103.8)" />
</GmapMap>
</template>
<script>
import { getGoogleMapsAPI } from 'gmap-vue';

export default {
name: 'your-component-name',
computed: {
// The below example is the same as writing
// google() {
// return getGoogleMapsAPI();
// },
google: getGoogleMapsAPI,
},
};
</script>
+

You will get an object with a maps property and inside of it you can find all the Google maps API.

+

Map Options

+

Control the options of the map with the options property. For more information about +google MapOptions visit the +link.

+
<GmapMap
:options="{
zoomControl: true,
mapTypeControl: false,
scaleControl: false,
streetViewControl: false,
rotateControl: false,
fullscreenControl: true,
disableDefaultUi: false
}"
>
</GmapMap>
+

Region and language localization

+

To add region and language localization. For more information about +google Localization visit the link.

+
Vue.use(GmapVue, {
load: {
region: 'VI',
language: 'vi',
},
})
+

Lazy loading

+

If you need to wait for google maps API to be ready, you can use the this.$gmapApiPromiseLazy() function to wait for +it. This function is automatically added to your components when you use GmapVue plugin, also, you can find a reference +of this function in your Vue instance if you have a reference of following common practice to assign it to vm +variable.

+

A simple example

+
export default {
name: 'your-component-name',
data() {
return {
center: { lat: 4.5, lng: 99 },
markers: [],
}
},
async mounted() {
// if you have a reference of Vue in a `vm` variable
// the following option should work too
// await vm.$gmapApiPromiseLazy();

await this.$gmapApiPromiseLazy();
this.markers = [
{
location: new google.maps.LatLng({ lat: 3, lng: 101 }),
weight: 100
},
{
location: new google.maps.LatLng({ lat: 5, lng: 99 }),
weight: 50
},
{
location: new google.maps.LatLng({ lat: 6, lng: 97 }),
weight: 80
}
];
}
};
+

GmapMap slots

+

GmapMap component has two slots with a different behavior. +The default slot is wrapped in a class that sets display: none; so by default any component you add to your map will +be invisible.

+

This is ok for most of the supplied components that interact directly with the Google map object, but it's not good if +you want to bring up things like toolboxes, etc.

+

There is a second slot named "visible" that must be used if you want to display content within the responsive +wrapper for the map, hence that's why you'll see this in +the drawing manager with slot example. It's actually +not required in the first example +because the default toolbox is part of the Google map object.

+
+

Thanks to @davydnorris to document this part of GmapVue.

+
+

Exported objects from the GmapVue plugin

+

In previous version the plugin exports all without any organization, from version 2 the plugin exports a default object +with the install function required for Vue.js to install this plugin and two objects, helpers and components.

+

This two objects exports the same functions as before but in a better way, in the main.js file. The code below is a +copy from that file.

+

/**
* Export all components and mixins
*/
export const components = {
HeatmapLayer,
KmlLayer,
Marker,
Polyline,
Polygon,
Circle,
Cluster,
Rectangle,
DrawingManager,
InfoWindow,
MapLayer,
PlaceInput,
Autocomplete,
StreetViewPanorama,
MapElementMixin,
MountableMixin,
};

/**
* Export all helpers
*/
export const helpers = {
googleMapsApiInitializer,
MapElementFactory,
};

+

Nuxt.js config

+

For Nuxt.js projects, please import GmapVue in the following way:

+
import GmapVue from '~/node_modules/gmap-vue'
+

Add the following to your nuxt.config.js's build.extend():

+
transpile: [/^gmap-vue($|\/)/]
+
note

Please take a look at this example on stackblitz

+

Officially supported components:

+

The list of officially support components are:

+
    +
  • Rectangle, Circle
  • +
  • Polygon, Polyline
  • +
  • KML Layer
  • +
  • Marker
  • +
  • InfoWindow
  • +
  • Autocomplete
  • +
  • Cluster* (via marker-clusterer-plus)
  • +
  • Heat map
  • +
  • Drawing map: rectangle, circle, polygon, line
  • +
+

Check our documentation guide to see examples of every component.

+

For Cluster, you must import the class specifically, e.g.

+
import { components } from "gmap-vue";
const { Cluster } = components;

Vue.component('GmapCluster', Cluster);
+

Inconvenient, but this means all other users don't have to bundle the marker clusterer package +in their source code.

+

Adding your own components

+

It should be relatively easy to add your own components (e.g. Heatmap, GroundOverlay). please refer to the +source code for mapElementFactory +.

+

Example +for DirectionsRenderer:

+
// DirectionsRenderer.js
import { helpers } from 'gmap-vue'
const { MapElementFactory } = helpers;

export default MapElementFactory({
name: 'directionsRenderer',
ctr: () => google.maps.DirectionsRenderer,
//// The following is optional, but necessary if the constructor takes multiple arguments
//// e.g. for GroundOverlay
// ctrArgs: (options, otherProps) => [options],
events: ['directions_changed'],

// Mapped Props will automatically set up
// this.$watch('propertyName', (v) => instance.setPropertyName(v))
//
// If you specify `twoWay`, then it also sets up:
// google.maps.event.addListener(instance, 'propertyName_changed', () => {
// this.$emit('propertyName_changed', instance.getPropertyName())
// })
//
// If you specify `noBind`, then neither will be set up. You should manually
// create your watchers in `afterCreate()`.
mappedProps: {
routeIndex: { type: Number },
options: { type: Object },
panel: { },
directions: { type: Object },
//// If you have a property that comes with a `_changed` event,
//// you can specify `twoWay` to automatically bind the event, e.g. Map's `zoom`:
// zoom: {type: Number, twoWay: true}
},
// Any other properties you want to bind. Note: Must be in Object notation
props: {},
// Actions you want to perform before creating the object instance using the
// provided constructor (for example, you can modify the `options` object).
// If you return a promise, execution will suspend until the promise resolves
beforeCreate (options) {},
// Actions to perform after creating the object instance.
afterCreate (directionsRendererInstance) {},
})
+

Thereafter, it's easy to use the newly-minted component!

+
<template>
<GmapMap :zoom="..." :center="...">
<DirectionsRenderer />
</GmapMap>
</template>
<script>
import DirectionsRenderer from './DirectionsRenderer.js'

export default {
components: {DirectionsRenderer}
}
</script>
+

Testing

+

More automated tests should be written to help new contributors.

+

Improvements to the tests are welcome :)

+ + \ No newline at end of file diff --git a/docs/vue-3-version/api/components/autocomplete/index.html b/docs/vue-3-version/api/components/autocomplete/index.html new file mode 100644 index 000000000..f4be63075 --- /dev/null +++ b/docs/vue-3-version/api/components/autocomplete/index.html @@ -0,0 +1,74 @@ + + + + + +Autocomplete | GmapVue Docs + + + + + +

Autocomplete

+
Official sources
+

This component is a wrapper of the Google Autocomplete class.

+
From the authors
+

Autocomplete is a feature of the Places library in the Maps JavaScript API. You can use autocomplete to give your applications the type-ahead-search behavior of the Google Maps search field. The autocomplete service can match on full words and substrings, resolving place names, addresses, and plus codes. Applications can therefore send queries as the user types, to provide on-the-fly place predictions. reference

+
+

Props

+
info

The highlighted lines are the official props, we strongly recommend to read the official documentation.

Here we only describe the custom props added by this plugin

+
Autocomplete props interface
/**
* Autocomplete input Google Maps properties documentation
*
* @see https://developers.google.com/maps/documentation/javascript/reference/places-widget#AutocompleteOptions.bounds
* @see https://developers.google.com/maps/documentation/javascript/reference/places-widget#AutocompleteOptions.componentRestrictions
* @see https://developers.google.com/maps/documentation/javascript/reference/places-widget#AutocompleteOptions.fields
* @see https://developers.google.com/maps/documentation/javascript/reference/places-widget#AutocompleteOptions.strictBounds
* @see https://developers.google.com/maps/documentation/javascript/reference/places-widget#AutocompleteOptions.types
*/
export interface IAutoCompleteInputVueComponentProps {
bounds?: google.maps.LatLngBounds | google.maps.LatLngBoundsLiteral;
componentRestrictions?: google.maps.places.ComponentRestrictions;
fields?: string[];
strictBounds?: boolean;
types?: string[];
/**
* Select the first result in the list when press enter keyboard
* @values true, false
*/
selectFirstOnEnter?: boolean;
/**
* the unique ref set to the component passed in the slot input
*/
slotRef?: HTMLInputElement;
/**
* To avoid paying for data that you don't need,
* be sure to use Autocomplete.setFields() to specify
* only the place data that you will use.
*
* @see [Place information](https://developers.google.com/maps/documentation/javascript/places-autocomplete#get-place-information)
* @see [setFields](https://developers.google.com/maps/documentation/javascript/reference/places-widget#Autocomplete.setFields)
* @see [PlaceResult](https://developers.google.com/maps/documentation/javascript/reference/places-service#PlaceResult)
*/
setFieldsTo?: string[];
autocompleteKey?: string;
options?: Record<string, unknown>;
}
+
    +
  • selectFirstOnEnter: +
      +
    • type: boolean
    • +
    • description: Select the first result in the list when press enter keyboard
    • +
    +
  • +
  • slotRef: +
      +
    • type: HTMLInputElement
    • +
    • description: the unique ref set to the component passed in the slot input
    • +
    +
  • +
  • setFieldsTo: To avoid paying for data that you don't need, be sure to use Autocomplete.setFields() to specify only the place data that you will use.
  • +
  • autocompleteKey: This is used to identify every instance of the Google Maps Autocomplete class. If it's not provided it always use the $autocompletePromise key as its default value, but take care about it because if you use it in many places you will use always the same instance.
  • +
  • options: +
      +
    • type: Record<string, unknown>
    • +
    • description: We use this prop as a fallback option. If the official API changes and add new props to the class you can use the options prop to use and populate these new props until we update our API to use it explicitly.
    • +
    +
  • +
+

Exposed const

+
note

We only document the exposed methods of the component

+ +

Events

+
    +
  • place_changed: +
      +
    • Event type: google.maps.places.PlaceResult
    • +
    • description: This event is fired when a PlaceResult is made available for a Place the user has selected. +If the user enters the name of a Place that was not suggested by the control and presses the Enter key, or if a Place Details request fails, the PlaceResult contains the user input in the name property, with no other properties defined.
    • +
    +
  • +
+

Slots

+
    +
  • default: It provides a fallback content if you don't provide a slot content
  • +
+
<template>
<div>
<slot :attrs="$attrs">
<input ref="gmvAutoCompleteInput" v-bind="$attrs" />
</slot>
</div>
</template>
+

Source code

+
autocomplete-input.vue source code
<template>
<div>
<!--
@slot Used to set your custom component for the input, eg: v-text-field.
It has two binding properties:
- `attrs`, it's type is `object`, it's all attributes passed to the component ([vm.$attrs](https://vuejs.org/v2/api/?#vm-attrs))<br>
-->
<slot :attrs="$attrs">
<input ref="gmvAutoCompleteInput" v-bind="$attrs" />
</slot>
</div>
</template>

<script lang="ts" setup>
import {
bindGoogleMapsEventsToVueEventsOnSetup,
bindPropsWithGoogleMapsSettersAndGettersOnSetup,
downArrowSimulator,
getComponentEventsConfig,
getComponentPropsConfig,
getPropsValuesWithoutOptionsProp,
useComponentPromiseFactory,
useDestroyPromisesOnUnmounted,
useGoogleMapsApiPromiseLazy,
usePluginOptions,
} from '@/composables';
import type { IAutoCompleteInputVueComponentProps } from '@/interfaces';
import { $autocompletePromise } from '@/keys';
import { onMounted, onUnmounted, provide, ref, watch } from 'vue';

/**
* Autocomplete component
* @displayName GmvAutocomplete
* @see [official guide](https://developers.google.com/maps/documentation/javascript/place-autocomplete)
* @see [official reference](https://developers.google.com/maps/documentation/javascript/reference/places-widget#Autocomplete)
* @see [source code](https://diegoazh.github.io/gmap-vue/docs/vue-3-version/api/components/autocomplete)
*/

/*******************************************************************************
* DEFINE COMPONENT PROPS
******************************************************************************/
const props = withDefaults(
defineProps<{
bounds?: google.maps.LatLngBounds | google.maps.LatLngBoundsLiteral;
componentRestrictions?: google.maps.places.ComponentRestrictions;
fields?: string[];
strictBounds?: boolean;
types?: string[];
/**
* Select the first result in the list when press enter keyboard
* @values true, false
*/
selectFirstOnEnter?: boolean;
/**
* the unique ref set to the component passed in the slot input
*/
slotRef?: HTMLInputElement;
/**
* To avoid paying for data that you don't need,
* be sure to use Autocomplete.setFields() to specify
* only the place data that you will use.
*
* @see [Place information](https://developers.google.com/maps/documentation/javascript/places-autocomplete#get-place-information)
* @see [setFields](https://developers.google.com/maps/documentation/javascript/reference/places-widget#Autocomplete.setFields)
* @see [PlaceResult](https://developers.google.com/maps/documentation/javascript/reference/places-service#PlaceResult)
*/
setFieldsTo?: string[];
autocompleteKey?: string;
options?: Record<string, unknown>;
}>(),
{
selectFirstOnEnter: true,
},
);

/*******************************************************************************
* TEMPLATE REF, ATTRIBUTES, EMITTERS AND SLOTS
******************************************************************************/
const gmvAutoCompleteInput = ref<HTMLInputElement | null>(null);
const emits = defineEmits<{
place_changed: [value: google.maps.places.PlaceResult];
}>();

/*******************************************************************************
* INJECT
******************************************************************************/

/*******************************************************************************
* AUTOCOMPLETE
******************************************************************************/
defineOptions({ inheritAttrs: false, name: 'autocomplete-input' });
const excludedEvents = usePluginOptions()?.excludeEventsOnAllComponents?.();

/*******************************************************************************
* PROVIDE
******************************************************************************/
const { promiseDeferred: autocompletePromiseDeferred, promise } =
useComponentPromiseFactory(props.autocompleteKey || $autocompletePromise);
provide(props.autocompleteKey || $autocompletePromise, promise);

/*******************************************************************************
* COMPUTED
******************************************************************************/

/*******************************************************************************
* METHODS
******************************************************************************/

/*******************************************************************************
* WATCHERS
******************************************************************************/
watch(
() => props.componentRestrictions,
async (newValue, oldValue) => {
const autocomplete = await promise;

if (!autocomplete) {
return console.error('the autocomplete instance is not defined');
}

if (newValue && newValue !== oldValue) {
autocomplete.setComponentRestrictions(newValue);
}
},
);

/*******************************************************************************
* HOOKS
******************************************************************************/
onMounted(() => {
useGoogleMapsApiPromiseLazy()
.then(async () => {
let scopedInput = props.slotRef
? props.slotRef
: gmvAutoCompleteInput.value;

if (!scopedInput) {
throw new Error(
`we can find the template ref: 'gmvAutoCompleteInput' or we can't use the slotRef prop`,
);
}

if (props.selectFirstOnEnter) {
downArrowSimulator(scopedInput);
}

const autocompleteOptions: IAutoCompleteInputVueComponentProps & {
[key: string]: any;
} = {
...getPropsValuesWithoutOptionsProp(props),
...props.options,
};

const { Autocomplete } = (await google.maps.importLibrary(
'places',
)) as google.maps.PlacesLibrary;

if (typeof Autocomplete !== 'function') {
throw new Error(
"google.maps.places.Autocomplete is undefined. Did you add 'places' to libraries when loading Google Maps?",
);
}

const autocomplete = new Autocomplete(scopedInput, autocompleteOptions);

const autocompletePropsConfig =
getComponentPropsConfig('GmvAutocomplete');
const autocompleteEventsConfig = getComponentEventsConfig(
'GmvAutocomplete',
'auto',
);

bindPropsWithGoogleMapsSettersAndGettersOnSetup(
autocompletePropsConfig,
autocomplete,
emits as any,
props,
);

bindGoogleMapsEventsToVueEventsOnSetup(
autocompleteEventsConfig,
autocomplete,
emits as any,
excludedEvents,
);

if (props.setFieldsTo) {
autocomplete.setFields(props.setFieldsTo);
}

/**
* Not using `bindEvents` because we also want
* to return the result of `getPlace()`
*/
autocomplete.addListener('place_changed', () => {
if (autocomplete) {
/**
* Place change event
* @event place_changed
* @property {object} place `this.$autocomplete.getPlace()`
* @see [Get place information](https://developers.google.com/maps/documentation/javascript/places-autocomplete#get-place-information)
*/
emits('place_changed', autocomplete.getPlace());
}
});

if (!autocompletePromiseDeferred.resolve) {
throw new Error('autocompletePromiseDeferred.resolve is undefined');
}

autocompletePromiseDeferred.resolve(autocomplete);
})
.catch((error) => {
throw error;
});
});

onUnmounted(() => {
useDestroyPromisesOnUnmounted(props.autocompleteKey || $autocompletePromise);
});

/*******************************************************************************
* RENDERS
******************************************************************************/

/*******************************************************************************
* EXPOSE
******************************************************************************/
defineExpose({
autocompletePromise: promise,
});
</script>
+ + \ No newline at end of file diff --git a/docs/vue-3-version/api/components/index.html b/docs/vue-3-version/api/components/index.html new file mode 100644 index 000000000..e44bc7bdb --- /dev/null +++ b/docs/vue-3-version/api/components/index.html @@ -0,0 +1,20 @@ + + + + + +The components of the plugin | GmapVue Docs + + + + + +

The components of the plugin

+

This plugin expose all components types from the following path @gmap-vue/v3/components.

+
/**
* Export all components
* @property {Object} HeatmapLayer - Vue component HeatmapLayer
* @property {Object} KmlLayer - Vue component KmlLayer
* @property {Object} Marker - Vue component Marker
* @property {Object} Polyline - Vue component Polyline
* @property {Object} Polygon - Vue component Polygon
* @property {Object} Circle - Vue component Circle
* @property {Object} Cluster - Vue component Cluster
* @property {Object} Rectangle - Vue component Rectangle
* @property {Object} DrawingManager - Vue component DrawingManager
* @property {Object} InfoWindow - Vue component InfoWindow
* @property {Object} MapLayer - Vue component MapLayer
* @property {Object} PlaceInput - Vue component PlaceInput
* @property {Object} Autocomplete - Vue component Autocomplete
* @property {Object} StreetViewPanorama - Vue component StreetViewPanorama
*/
export {
Autocomplete,
Circle,
Cluster,
DrawingManager,
HeatmapLayer,
InfoWindow,
KmlLayer,
MapLayer,
Marker,
Polyline,
Polygon,
Rectangle,
StreetViewPanorama,
};
+

How to use it

+

This object is useful to install only the components that you need, for example

+
import { ref, ComponentInstance } from 'vue';
import type { MapLayer } from '@gmap-vue/v3/components';

const mapRef = ref<ComponentInstance<typeof MapLayer> | null>(null);
+
warning

Remember this path export component types not classes. This exports are only types not the final components classes.

+ + \ No newline at end of file diff --git a/docs/vue-3-version/api/components/map/index.html b/docs/vue-3-version/api/components/map/index.html new file mode 100644 index 000000000..6a8bc1b34 --- /dev/null +++ b/docs/vue-3-version/api/components/map/index.html @@ -0,0 +1,318 @@ + + + + + +Map | GmapVue Docs + + + + + +

Map

+
Official sources
+

This component is a wrapper of the Google Map class.

+
From the authors
+

The JavaScript class that represents a map is the Map class. Objects of this class define a single map on a page. (You may create more than one instance of this class — each object will define a separate map on the page.) We create a new instance of this class using the JavaScript new operator. When you create a new map instance, you specify a <div> HTML element in the page as a container for the map. HTML nodes are children of the JavaScript document object, and we obtain a reference to this element via the document.getElementById() method. This code defines a variable (named map) and assigns that variable to a new Map object. The function Map() is known as a constructor and its definition is shown below: reference +:::

+

Props

info

The highlighted lines are the official props, we strongly recommend to read the official documentation.

Here we only describe the custom props added by this plugin

+
Map Layer props interface
/**
* MapOptions interface
*
* MapOptions object used to define the properties that can be set on a Map.
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions
*
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.backgroundColor
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.center
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.clickableIcons
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.controlSize
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.disableDefaultUI
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.disableDoubleClickZoom
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.draggableCursor
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.draggingCursor
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.fullscreenControl
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.fullscreenControlOptions
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.gestureHandling
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.heading
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.isFractionalZoomEnabled
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.keyboardShortcuts
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.mapTypeControl
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.mapTypeControlOptions
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.mapTypeId
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.maxZoom
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.minZoom
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.noClear
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.restriction
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.rotateControl
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.rotateControlOptions
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.scaleControl
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.scaleControlOptions
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.streetView
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.streetViewControl
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.styles
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.tilt
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.zoom
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.zoomControl
* @see https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.zoomControlOptions
*/
export interface IMapLayerVueComponentProps {
backgroundColor?: string;
center: google.maps.LatLng | google.maps.LatLngLiteral;
clickableIcons?: boolean;
controlSize?: number;
disableDefaultUI?: boolean;
disableDoubleClickZoom?: boolean;
draggableCursor?: string;
draggingCursor?: string;
fullscreenControl?: boolean;
fullscreenControlOptions?: google.maps.FullscreenControlOptions;
gestureHandling?: "cooperative" | "greedy" | "none" | "auto";
heading?: number;
isFractionalZoomEnabled?: boolean;
keyboardShortcuts?: boolean;
mapId?: string;
mapTypeControl?: boolean;
mapTypeControlOptions?: google.maps.MapTypeControlOptions;
mapTypeId?: google.maps.MapTypeId;
maxZoom?: number;
minZoom?: number;
noClear?: boolean;
restriction?: google.maps.MapRestriction;
rotateControl?: boolean;
rotateControlOptions?: google.maps.RotateControlOptions;
scaleControl?: boolean;
scaleControlOptions?: google.maps.ScaleControlOptions;
scrollwheel?: boolean;
streetView?: google.maps.StreetViewPanorama;
streetViewControl?: boolean;
streetViewControlOptions?: google.maps.StreetViewControlOptions;
styles?: google.maps.MapTypeStyle[];
tilt?: number;
zoom?: number;
zoomControl?: boolean;
zoomControlOptions?: google.maps.ZoomControlOptions;
mapKey?: string;
resizeBus?: Emitter<Record<EventType, unknown>>;
options?: { [key: string]: any };
}
+
    +
  • mapKey: +
      +
    • type: string
    • +
    • description: A unique key to identify different instances of the GmvMap component. This always be prefixed with __gmc__ as a recycle key to save the Google Map class instance into the global window object. For example if you set this prop with 'MyMap' this results on '__gmc__MyMap' for the recycle key, that is returned by the exposed getRecycleKey method. and you should use this key to get the correct map promise using the useMapPromise('MyMap') composable. This is the old recycle prop from v2.0.1 and below.
    • +
    +
  • +
+
warning

For legacy compatibility we decide to maintain the old way to set the map key, eg: options: { recycle: 'myMapKey' } but, we strongly recommend to use the new mapKey prop because the old way should be removed in the next major release.

+
    +
  • resizeBus: +
      +
    • type: Emitter<Record<EventType, unknown>>;
    • +
    • description: This is the resize bus, the default value is the default resize bus is an emit object. EventType is typed as string | symbol and the event is unknown because we can not know which events will you fire.
    • +
    +
  • +
  • options: +
      +
    • type: Record<string, unknown>
    • +
    • description: We use this prop as a fallback option. If the official API changes and add new props to the class you can use the options prop to use and populate these new props until we update our API to use it explicitly.
    • +
    +
  • +
+

Methods

+
note

We only document the exposed methods of the component

+
    +
  • +

    panBy:

    +
      +
    • return type: void
    • +
    • params: +
        +
      • x: number: Number of pixels to move the map in the x direction.
      • +
      • y: number: Number of pixels to move the map in the y direction.
      • +
      +
    • +
    • description: Changes the center of the map by the given distance in pixels. If the distance is less than both the width and height of the map, the transition will be smoothly animated. Note that the map coordinate system increases from west to east (for x values) and north to south (for y values).
    • +
    +
    //...
    function panBy(x: number, y: number): void {
    if (mapInstance) {
    mapInstance.panBy(x, y);
    }
    }
    //...
    +
  • +
  • +

    panTo:

    +
      +
    • return type: void
    • +
    • params: + +
    • +
    • description: Changes the center of the map to the given LatLng. If the change is less than both the width and height of the map, the transition will be smoothly animated.
    • +
    +
    //...
    function panTo(latLng: google.maps.LatLng | google.maps.LatLngLiteral): void {
    if (mapInstance) {
    mapInstance.panTo(latLng);
    }
    }
    //...
    +
  • +
  • +

    panToBounds:

    +
      +
    • return type: void
    • +
    • params: + +
    • +
    • description: Pans the map by the minimum amount necessary to contain the given LatLngBounds. It makes no guarantee where on the map the bounds will be, except that the map will be panned to show as much of the bounds as possible inside {currentMapSizeInPx} - {padding}. For both raster and vector maps, the map's zoom, tilt, and heading will not be changed.
    • +
    +
    //...
    function panToBounds(
    latLngBounds: google.maps.LatLngBounds | google.maps.LatLngBoundsLiteral,
    padding: number | google.maps.Padding,
    ): void {
    if (mapInstance) {
    mapInstance.panToBounds(latLngBounds, padding);
    }
    }
    //...
    +
  • +
  • +

    fitBounds:

    +
      +
    • return type: void
    • +
    • params: +
        +
      • bounds: google.maps.LatLngBounds | google.maps.LatLngBoundsLiteral: Bounds to show.
      • +
      • padding: number | google.maps.Padding: optional Padding in pixels. The bounds will be fit in the part of the map that remains after padding is removed. A number value will yield the same padding on all 4 sides. Supply 0 here to make a fitBounds idempotent on the result of getBounds.
      • +
      +
    • +
    • description: Sets the viewport to contain the given bounds. +Note: When the map is set to display: none, the fitBounds function reads the map's size as 0x0, and therefore does not do anything. To change the viewport while the map is hidden, set the map to visibility: hidden, thereby ensuring the map div has an actual size. For vector maps, this method sets the map's tilt and heading to their default zero values.
    • +
    +
    //...
    function fitBounds(
    bounds: google.maps.LatLngBounds | google.maps.LatLngBoundsLiteral,
    padding: number | google.maps.Padding,
    ): void {
    if (mapInstance) {
    mapInstance.fitBounds(bounds, padding);
    }
    }
    //...
    +
  • +
  • +

    _resizeCallback:

    +
      +
    • return type: void
    • +
    • description: It executes the resize function passed to the component through the resizeBus prop.
    • +
    +
    //...
    _resizeCallback = (): void => {
    resizeFn();
    //...
    };

    +
  • +
  • +

    _delayedResizeCallback:

    +
      +
    • return type: Promise<void>
    • +
    • description: It use the nextTick function to execute the _resizeCallback function.
    • +
    +
    //...
    _delayedResizeCallback = (): Promise<void> => {
    return nextTick(() => _resizeCallback());
    };
    //...
    +
  • +
  • +

    resize:

    +
      +
    • return type: void
    • +
    • description: This method trigger the resize event of Google Maps.
    • +
    +
    //...
    function resize(): void {
    if (mapInstance) {
    google.maps.event.trigger(mapInstance, 'resize');
    }
    }
    //...
    +
  • +
  • +

    resizePreserveCenter:

    +
      +
    • return type: void
    • +
    • description: Preserve the previous center when resize the map.
    • +
    +
    //...
    function resizePreserveCenter(): void {
    if (!mapInstance) {
    return;
    }

    const oldCenter = mapInstance.getCenter();
    google.maps.event.trigger(mapInstance, 'resize');

    if (oldCenter) {
    mapInstance.setCenter(oldCenter);
    }
    }
    //...
    +
  • +
  • +

    getRecycleKey:

    +
      +
    • return type: string
    • +
    • description: Get the recycle key of the map. The default recycle key is __gmc__.
    • +
    +
    //...
    function getRecycleKey(): string {
    return props?.recycle ? `${recyclePrefix}${props.recycle}` : recyclePrefix;
    }
    //...
    +
  • +
+

Exposed const

+
    +
  • mapPromise: +
      +
    • type: Promise<InstanceType<google.maps.Map> | undefined>
    • +
    • description: This promise returns the Map class constructor when the Google Maps API is ready and successfully loaded.
    • +
    +
  • +
+

Events

+
    +
  • bounds_changed: + +
  • +
  • center_changed: + +
  • +
  • click: +
      +
    • Event type: google.maps.MapMouseEvent | google.maps.IconMouseEvent
    • +
    • description: This event is fired when the user clicks on the map. A MapMouseEvent with properties for the clicked location is returned unless a place icon was clicked, in which case an IconMouseEvent with a place ID is returned. IconMouseEvent and MapMouseEvent are identical, except that IconMouseEvent has the place ID field. The event can always be treated as an MapMouseEvent when the place ID is not important. The click event is not fired if a marker or info window was clicked.
    • +
    +
  • +
  • contextmenu: +
      +
    • Event type: google.maps.MapMouseEvent
    • +
    • description: This event is fired when the DOM contextmenu event is fired on the map container.
    • +
    +
  • +
  • dblclick: +
      +
    • Event type: google.maps.MapMouseEvent
    • +
    • description: This event is fired when the user double-clicks on the map. Note that the click event will sometimes fire once and sometimes twice, right before this one.
    • +
    +
  • +
  • drag: +
      +
    • Event type: void
    • +
    • description: This event is repeatedly fired while the user drags the map.
    • +
    +
  • +
  • drag: +
      +
    • Event type: void
    • +
    • description: This event is repeatedly fired while the user drags the map.
    • +
    +
  • +
  • dragend: +
      +
    • Event type: void
    • +
    • description: This event is fired when the user stops dragging the map.
    • +
    +
  • +
  • dragstart: +
      +
    • Event type: void
    • +
    • description: This event is fired when the user starts dragging the map.
    • +
    +
  • +
  • heading_changed: +
      +
    • Event type: void
    • +
    • description: This event is fired when the map heading property changes.
    • +
    +
  • +
  • idle: +
      +
    • Event type: void
    • +
    • description: This event is fired when the map becomes idle after panning or zooming.
    • +
    +
  • +
  • isfractionalzoomenabled_changed: +
      +
    • Event type: void
    • +
    • description: This event is fired when the isFractionalZoomEnabled property has changed.
    • +
    +
  • +
  • mapcapabilities_changed: +
      +
    • Event type: void
    • +
    • description: This event is fired when the map capabilities change.
    • +
    +
  • +
  • maptypeid_changed: +
      +
    • Event type: void
    • +
    • description: This event is fired when the mapTypeId property changes.
    • +
    +
  • +
  • mousemove: +
      +
    • Event type: google.maps.MapMouseEvent
    • +
    • description: This event is fired whenever the user's mouse moves over the map container.
    • +
    +
  • +
  • mouseout: + +
  • +
  • mouseover: + +
  • +
  • projection_changed: +
      +
    • Event type: void
    • +
    • description: This event is fired when the projection has changed.
    • +
    +
  • +
  • renderingtype_changed: +
      +
    • Event type: void
    • +
    • description: This event is fired when the renderingType has changed.
    • +
    +
  • +
  • tilesloaded: +
      +
    • Event type: void
    • +
    • description: This event is fired when the visible tiles have finished loading.
    • +
    +
  • +
  • tilt_changed: +
      +
    • Event type: void
    • +
    • description: This event is fired when the map tilt property changes.
    • +
    +
  • +
  • zoom_changed: +
      +
    • Event type: void
    • +
    • description: This event is fired when the map zoom property changes.
    • +
    +
  • +
  • resize: +
      +
    • Event type: void
    • +
    • description: This event is fired when the map is resized.
    • +
    +
  • +
+

Slots

+
    +
  • default: The default slot is wrapped in a class that sets display: none; so by default any component you add to your map will be invisible. This is ok for most of the supplied components that interact directly with the Google map object, but it's not good if you want to bring up things like toolboxes, etc.
  • +
  • visible: This slot must be used if you want to display content within the responsive wrapper for the map.
  • +
+
<template>
<div class="gmv-map-container">
<div ref="gmvMap" class="gmv-map"></div>
<div class="gmv-map-hidden">
<slot></slot>
</div>
<slot name="visible"></slot>
</div>
</template>
+

Provide/Inject

+

This component provides to its descendants a mapPromise to know when the map instance is ready to use.

+

From versions above v2.0.1 every map promise si provided using the mapKey prop or using the $mapPromise key as the default value. If you have only one instance of the map you can avoid to set this prop but, take care because if you have more than one map and forget to set the mapKey, the second instance of the map will override the promise of the first map and you will be using the same instance in both places causing the issues described in the following report.

+
warning

From v2.0.1 and below it only provides one promise with the default key $mapPromise.

+
import { $mapPromise } from '@/keys';

//...
const { promiseDeferred: mapPromiseDeferred, promise } =
useComponentPromiseFactory(defineMapKey() || $mapPromise);
provide(defineMapKey() || $mapPromise, promise);
//...
+

You can get the promise using inject like de following example but, only on the descendants of the GmvMap component, that mean only on components placed between the GmvMap tags.

+
import { $mapPromise } from '@/keys';

//...
const mapPromise = inject($mapPromise); // if you are using only one map
const mapPromise = inject('mapKey'); // two or more instances needs to use the `mapKey` prop
//...
+
<GmvMap>
<YourComponentHere /> <!-- 👈🏼 Your component here can use inject to get the promise. -->
</GmvMap>
+

For other cases you can use the useMapPromise composable. Read more about it here.

+
import { useMapPromise } from "@gmap-vue/v3/composables";

const mapPromise = useMapPromise('mapKey');
+
info

This mapPromise is exposed and you can access it from the component reference using ref.

+

Ref

+

To get a component reference for the GmvMap, please follow this guide.

+

Source code

+
map-layer.vue source code
<template>
<div class="gmv-map-container">
<div ref="gmvMap" class="gmv-map"></div>
<div class="gmv-map-hidden">
<!-- @slot The default slot is wrapped in a class that sets display: none; so by default any component you add to your map will be invisible. This is ok for most of the supplied components that interact directly with the Google map object, but it's not good if you want to bring up things like toolboxes, etc. -->
<slot></slot>
</div>
<!-- @slot This slot must be used if you want to display content within the responsive wrapper for the map. -->
<slot name="visible"></slot>
</div>
</template>

<script lang="ts" setup>
import {
bindGoogleMapsEventsToVueEventsOnSetup,
bindPropsWithGoogleMapsSettersAndGettersOnSetup,
getComponentEventsConfig,
getComponentPropsConfig,
getPropsValuesWithoutOptionsProp,
onMountedResizeBusHook,
onUnmountedResizeBusHook,
twoWayBindingWrapper,
useComponentPromiseFactory,
useDestroyPromisesOnUnmounted,
useGoogleMapsApiPromiseLazy,
usePluginOptions,
useResizeBus,
watchPrimitivePropertiesOnSetup,
} from '@/composables';
import type { IMapLayerVueComponentProps } from '@/interfaces';
import { $mapPromise, $recyclePrefix } from '@/keys';
import type { Emitter, EventType } from 'mitt';
import {
computed,
onBeforeUnmount,
onMounted,
onUnmounted,
provide,
ref,
watch,
} from 'vue';

/**
* Map component
* @displayName GmvMap
* @see [source code](/guide/map.html#source-code)
* @see [Official documentation](https://developers.google.com/maps/documentation/javascript/basics)
* @see [Official reference](https://developers.google.com/maps/documentation/javascript/reference/map)
*/

/*******************************************************************************
* DEFINE COMPONENT PROPS
******************************************************************************/
const props = withDefaults(
defineProps<{
backgroundColor?: string;
center: google.maps.LatLng | google.maps.LatLngLiteral;
clickableIcons?: boolean;
controlSize?: number;
disableDefaultUI?: boolean;
disableDoubleClickZoom?: boolean;
draggableCursor?: string;
draggingCursor?: string;
fullscreenControl?: boolean;
fullscreenControlOptions?: google.maps.FullscreenControlOptions;
gestureHandling?: 'cooperative' | 'greedy' | 'none' | 'auto';
heading?: number;
isFractionalZoomEnabled?: boolean;
keyboardShortcuts?: boolean;
mapId?: string;
mapTypeControl?: boolean;
mapTypeControlOptions?: google.maps.MapTypeControlOptions;
mapTypeId?: google.maps.MapTypeId;
maxZoom?: number;
minZoom?: number;
noClear?: boolean;
restriction?: google.maps.MapRestriction;
rotateControl?: boolean;
rotateControlOptions?: google.maps.RotateControlOptions;
scaleControl?: boolean;
scaleControlOptions?: google.maps.ScaleControlOptions;
scrollwheel?: boolean;
streetView?: google.maps.StreetViewPanorama;
streetViewControl?: boolean;
streetViewControlOptions?: google.maps.StreetViewControlOptions;
styles?: google.maps.MapTypeStyle[];
tilt?: number;
zoom?: number;
zoomControl?: boolean;
zoomControlOptions?: google.maps.ZoomControlOptions;
mapKey?: string;
resizeBus?: Emitter<Record<EventType, unknown>>;
options?: { [key: string]: any };
}>(),
{
mapTypeId: globalThis?.google?.maps?.MapTypeId?.ROADMAP || 'roadmap',
clickableIcons: true,
disableDefaultUI: false,
fullscreenControl: true,
gestureHandling: 'auto',
keyboardShortcuts: true,
mapTypeControl: true,
panControl: true,
rotateControl: true,
scaleControl: true,
streetViewControl: true,
zoomControl: true,
},
);

/*******************************************************************************
* TEMPLATE REF, ATTRIBUTES AND EMITTERS
******************************************************************************/
const gmvMap = ref<HTMLElement | null>(null);
const emits = defineEmits<{
bounds_changed: [value: google.maps.LatLngBounds | undefined];
center_changed: [value: google.maps.LatLng | undefined];
click: [value: google.maps.MapMouseEvent | google.maps.IconMouseEvent];
contextmenu: [value: google.maps.MapMouseEvent];
dblclick: [value: google.maps.MapMouseEvent];
drag: [];
dragend: [];
dragstart: [];
heading_changed: [];
idle: [];
isfractionalzoomenabled_changed: [];
mapcapabilities_changed: [];
maptypeid_changed: [];
mousemove: [value: google.maps.MapMouseEvent];
mouseout: [value: google.maps.MapMouseEvent];
mouseover: [value: google.maps.MapMouseEvent];
projection_changed: [];
renderingtype_changed: [];
tilesloaded: [];
tilt_changed: [];
zoom_changed: [value: number | undefined];
resize: [];
}>();

/*******************************************************************************
* RECYCLE KEY
******************************************************************************/
/**
* Define de final mapKey.
* This method is a legacy method to maintain compatibility with the old recycle key and should be removed in the next major release.
*
* @method defineMapKey
* @returns {string}
* @internal
*/
function defineMapKey(): string {
return props?.mapKey
? props.mapKey
: props?.options && props.options?.recycle
? props.options.recycle
: '';
}

/**
* Get the recycle key of the map
* @method getRecycleKey
* @returns {void}
* @public
*/
function getRecycleKey(): string {
return `${$recyclePrefix}${defineMapKey()}`;
}

/*******************************************************************************
* MAP
******************************************************************************/
defineOptions({ name: 'map-layer' });
const excludedEvents = usePluginOptions()?.excludeEventsOnAllComponents?.();

/*******************************************************************************
* PROVIDE
******************************************************************************/
const { promiseDeferred: mapPromiseDeferred, promise } =
useComponentPromiseFactory(defineMapKey() || $mapPromise);
provide(defineMapKey() || $mapPromise, promise);

/*******************************************************************************
* RESIZE BUS
******************************************************************************/
const { currentResizeBus, _delayedResizeCallback } = useResizeBus();
let { _resizeCallback } = useResizeBus();

/**
* This method trigger the resize event of Google Maps
* @method resize
* @returns {void}
* @public
*/
async function resize(): Promise<void> {
const mapInstance = await promise;

if (mapInstance) {
google.maps.event.trigger(mapInstance, 'resize');
}
}

/**
* Preserve the previous center when resize the map
* @method resizePreserveCenter
* @returns {void}
* @public
*/
async function resizePreserveCenter(): Promise<void> {
const mapInstance = await promise;

if (!mapInstance) {
return;
}

const oldCenter = mapInstance.getCenter();
google.maps.event.trigger(mapInstance, 'resize');

if (oldCenter) {
mapInstance.setCenter(oldCenter);
}
}

/*******************************************************************************
* COMPUTED
******************************************************************************/
const finalLat = computed(() => {
if (!props.center) {
return console.warn('center is not defined');
}

return typeof props.center.lat === 'function'
? props.center.lat()
: props.center.lat;
});
const finalLng = computed(() => {
if (!props.center) {
return console.warn('center is not defined');
}

return typeof props.center.lng === 'function'
? props.center.lng()
: props.center.lng;
});
const finalLatLng = computed(
() =>
({ lat: finalLat.value, lng: finalLng.value }) as google.maps.LatLngLiteral,
);

/*******************************************************************************
* METHODS
******************************************************************************/
/**
* Changes the center of the map by the given distance in pixels. If the distance is less than both the width and height of the map, the transition will be smoothly animated. Note that the map coordinate system increases from west to east (for x values) and north to south (for y values).
* @method panBy
* @param {number} x - Number of pixels to move the map in the x direction.
* @param {number} y - Number of pixels to move the map in the y direction.
* @returns {void}
* @public
*/
async function panBy(x: number, y: number): Promise<void> {
const mapInstance = await promise;

if (mapInstance) {
mapInstance.panBy(x, y);
}
}

/**
* Changes the center of the map to the given LatLng. If the change is less than both the width and height of the map, the transition will be smoothly animated.
* @method panTo
* @param {(LatLng|LatLngLiteral)} latLng - The new center latitude/longitude of the map. (types `LatLng|LatLngLiteral`)
* @returns {void}
* @public
*/
async function panTo(
latLng: google.maps.LatLng | google.maps.LatLngLiteral,
): Promise<void> {
const mapInstance = await promise;

if (mapInstance) {
mapInstance.panTo(latLng);
}
}

/**
* Pans the map by the minimum amount necessary to contain the given LatLngBounds. It makes no guarantee where on the map the bounds will be, except that the map will be panned to show as much of the bounds as possible inside {currentMapSizeInPx} - {padding}. For both raster and vector maps, the map's zoom, tilt, and heading will not be changed.
* @method panToBounds
* @param {(LatLngBounds|LatLngBoundsLiteral)} latLngBounds - The bounds to pan the map to. (types: `LatLngBounds|LatLngBoundsLiteral`)
* @param {(number|Padding)} [padding] - optional Padding in pixels. A number value will yield the same padding on all 4 sides. The default value is 0. (types: `number|Padding`)
* @returns {void}
* @public
*/
async function panToBounds(
latLngBounds: google.maps.LatLngBounds | google.maps.LatLngBoundsLiteral,
padding: number | google.maps.Padding,
): Promise<void> {
const mapInstance = await promise;

if (mapInstance) {
mapInstance.panToBounds(latLngBounds, padding);
}
}

/**
* Sets the viewport to contain the given bounds.
Note: When the map is set to display: none, the fitBounds function reads the map's size as 0x0, and therefore does not do anything. To change the viewport while the map is hidden, set the map to visibility: hidden, thereby ensuring the map div has an actual size. For vector maps, this method sets the map's tilt and heading to their default zero values.
* @method fitBounds
* @param {(LatLngBounds|LatLngBoundsLiteral)} bounds - Bounds to show. (types: `LatLngBounds|LatLngBoundsLiteral`)
* @param {(number|Padding)} [padding] - optional Padding in pixels. The bounds will be fit in the part of the map that remains after padding is removed. A number value will yield the same padding on all 4 sides. Supply 0 here to make a fitBounds idempotent on the result of getBounds. (types: `number|Padding`)
* @returns {void}
* @public
*/
async function fitBounds(
bounds: google.maps.LatLngBounds | google.maps.LatLngBoundsLiteral,
padding: number | google.maps.Padding,
): Promise<void> {
const mapInstance = await promise;

if (mapInstance) {
mapInstance.fitBounds(bounds, padding);
}
}

/*******************************************************************************
* WATCHERS
******************************************************************************/
watch(
() => props.zoom,
async (newVal, oldValue) => {
const mapInstance = await promise;

if (mapInstance && newVal && newVal !== oldValue) {
mapInstance.setZoom(newVal);
}
},
);

/*******************************************************************************
* HOOKS
******************************************************************************/
onMounted(() => {
useGoogleMapsApiPromiseLazy()
.then(async () => {
if (!gmvMap.value) {
throw new Error(`we can find the template ref: 'gmvMap'`);
}

const mapLayerOptions: Partial<IMapLayerVueComponentProps> = {
...getPropsValuesWithoutOptionsProp(props),
...props.options,
};

const recycleKey = getRecycleKey();
let mapInstance: google.maps.Map | undefined;

if (window[recycleKey]) {
gmvMap.value.appendChild(window[recycleKey].div);
mapInstance = window[recycleKey].map as google.maps.Map;
mapInstance.setOptions(mapLayerOptions);
} else {
const { Map } = (await google.maps.importLibrary(
'maps',
)) as google.maps.MapsLibrary;
mapInstance = new Map(gmvMap.value, mapLayerOptions);
window[recycleKey] = { map: mapInstance };
}

onMountedResizeBusHook(props, resizePreserveCenter);

const mapLayerPropsConfig = getComponentPropsConfig('GmvMap');
const mapLayerEventsConfig = getComponentEventsConfig('GmvMap', 'auto');

// binding properties (two and one way)
bindPropsWithGoogleMapsSettersAndGettersOnSetup(
mapLayerPropsConfig,
mapInstance,
emits as any,
props,
);

// Auto bind all events by default
bindGoogleMapsEventsToVueEventsOnSetup(
mapLayerEventsConfig,
mapInstance,
emits as any,
excludedEvents,
);

// manually trigger center and zoom
twoWayBindingWrapper(
(
increment: () => void,
decrement: () => void,
shouldUpdate: () => boolean,
) => {
mapInstance?.addListener('center_changed', () => {
if (shouldUpdate()) {
/**
* This event is fired when the map center property changes. It sends the position displayed at the center of the map. If the center or bounds have not been set then the result is undefined. (types: `LatLng|undefined`)
*
* @event center_changed
* @type {(LatLng|undefined)}
*/
emits('center_changed', mapInstance?.getCenter());
}

decrement();
});

const updateCenter = () => {
increment();

mapInstance?.setCenter(finalLatLng.value);
};

watchPrimitivePropertiesOnSetup(
['finalLat', 'finalLng'],
updateCenter,
{ finalLat, finalLng },
);
},
);

mapInstance?.addListener('zoom_changed', () => {
/**
* This event is fired when the map zoom property changes. It sends the zoom of the map. If the zoom has not been set then the result is undefined. (types: `number|undefined`)
*
* @event zoom_changed
* @type {(number|undefined)}
*/
emits('zoom_changed', mapInstance?.getZoom());
});
mapInstance?.addListener('bounds_changed', () => {
/**
* This event is fired when the viewport bounds have changed. It sends The lat/lng bounds of the current viewport.
*
* @event bounds_changed
* @type {LatLngBounds}
*/
emits('bounds_changed', mapInstance?.getBounds());
});

if (!mapPromiseDeferred.resolve) {
throw new Error('mapPromiseDeferred.resolve is undefined');
}

mapPromiseDeferred.resolve(mapInstance);
})
.catch((error) => {
throw error;
});
});

onBeforeUnmount(async () => {
const mapInstance = await promise;

if (mapInstance) {
const recycleKey = getRecycleKey();

if (window[recycleKey]) {
window[recycleKey].div = mapInstance.getDiv();
}
}
});

onUnmounted(() => {
onUnmountedResizeBusHook();
useDestroyPromisesOnUnmounted(defineMapKey() || $mapPromise);
});

/*******************************************************************************
* RENDERS
******************************************************************************/

/*******************************************************************************
* EXPOSE
******************************************************************************/
defineExpose({
mapPromise: promise,
panBy,
panTo,
panToBounds,
fitBounds,
currentResizeBus,
_resizeCallback,
_delayedResizeCallback,
resize,
resizePreserveCenter,
getRecycleKey,
});
</script>

<style lang="stylus" scoped>
.gmv-map-container {
position: relative;

.gmv-map {
left: 0;
right: 0;
top: 0;
bottom: 0;
position: absolute;
}

.gmv-map-hidden {
display: none;
}
}
</style>
+ + \ No newline at end of file diff --git a/docs/vue-3-version/api/composables/index.html b/docs/vue-3-version/api/composables/index.html new file mode 100644 index 000000000..8430ca802 --- /dev/null +++ b/docs/vue-3-version/api/composables/index.html @@ -0,0 +1,156 @@ + + + + + +The exposed composables | GmapVue Docs + + + + + +

The exposed composables

+
info

From versions above v2.0.1 all components have its own composable to get their promises.

+

The plugin expose composables from the following path @gmap-vue/v3/composables. You can use in your application using the composition API.

+

You can use it in the following way

+
import {
useMapPromise,
useResizeBus,
useGoogleMapsApiPromiseLazy,
useStreetViewPanoramaPromise,
usePluginOptions,
} from '@gmap-vue/v3/composables';

const promise = useMapPromise('yourMapKey');
// ...
+

useGoogleMapsApiPromiseLazy

+

This composable return the a promise that when it is resolved return the global google object, this mean the window.google object added to the globalThis object bye the Google Maps API.

+

You can use it in the following way

+
import { useGoogleMapsApiPromiseLazy } from '@gmap-vue/v3/composables';

const googlePromise = useGoogleMapsApiPromiseLazy();

if (googlePromise) {
const googleObject = await googlePromise;
}
+
warning

If the Google API was not loaded yet you will see a warning message in the console like this: '$googleMapsApiPromiseLazy was not created yet...' and the composable function should return undefined.

+

useGoogleMapsApiPromiseLazy API

+
let $googleMapsApiPromiseLazy: LazyValueGetterFn<GlobalGoogleObject>;

/**
* This function helps to save the final options passed to the plugin and
* the function to get the promise useful to wait until the Google Maps API
* is loaded and ready to use it
*
* @param {IPluginOptions} finalOptions
* @param {LazyValueGetterFn} googleMapsApiPromiseLazy
* @returns void
*
* @internal
*/
export function saveLazyPromiseAndFinalOptions(
finalOptions: IPluginOptions,
googleMapsApiPromiseLazy: LazyValueGetterFn<GlobalGoogleObject>
): void {
if (!$finalOptions) {
$finalOptions = finalOptions;
}

if (!$googleMapsApiPromiseLazy) {
$googleMapsApiPromiseLazy = googleMapsApiPromiseLazy;
}
}

/**
* This function returns a promise when is resolved returns the original Google
* Maps API. With this promise you can wait until the Google Maps API is fully
* loaded.
*
* @public
* @returns {Promise<any>}
*/
export function useGoogleMapsApiPromiseLazy(): Promise<
GlobalGoogleObject | undefined
> {
if (!$googleMapsApiPromiseLazy) {
globalThis.console.warn('$googleMapsApiPromiseLazy was not created yet...');
}

return $googleMapsApiPromiseLazy?.();
}
+

Like the plugin options this lazy promise is saved when the plugin is loaded

+
main.ts
  /**
* Use a lazy to only load the API when
* a GMap component is loaded
*
* @constant
* @type {Function} the promise lazy creator function
*/
const promiseLazyCreator = usePromiseLazyBuilderFn(
googleMapsApiInitializer,
globalThis.GoogleMapsApi
);
/**
* The googleMapsApiPromiseLazy function to can wait until Google Maps API is ready
*
* @constant
* @type {Function}
*/
const googleMapsApiPromiseLazy = promiseLazyCreator(finalOptions);
saveLazyPromiseAndFinalOptions(finalOptions, googleMapsApiPromiseLazy);
+
info
    +
  • Check the LazyValueGetterFn type here
  • +
  • Check the GlobalGoogleObject type here
  • +
+

usePluginOptions

+

This composable return the final options object used by the plugin when it was initialized.

+

How to use it

+
import { usePluginOptions } from '@gmap-vue/v3/composables';

const options = usePluginOptions();

// do something with the options
+

usePluginOptions API

+
    +
  • +

    Check the Options Interface

    +
  • +
  • +

    The options are saved when the plugin is load as we show below

    +
  • +
+
main.ts
  /**
* Use a lazy to only load the API when
* a GMap component is loaded
*
* @constant
* @type {Function} the promise lazy creator function
*/
const promiseLazyCreator = usePromiseLazyBuilderFn(
googleMapsApiInitializer,
globalThis.GoogleMapsApi
);
/**
* The googleMapsApiPromiseLazy function to can wait until Google Maps API is ready
*
* @constant
* @type {Function}
*/
const googleMapsApiPromiseLazy = promiseLazyCreator(finalOptions);
saveLazyPromiseAndFinalOptions(finalOptions, googleMapsApiPromiseLazy);
+
    +
  • The core API of this composable
  • +
+
let $finalOptions: IPluginOptions;

/**
* This function helps to save the final options passed to the plugin and
* the function to get the promise useful to wait until the Google Maps API
* is loaded and ready to use it
*
* @param {IPluginOptions} finalOptions
* @param {LazyValueGetterFn} googleMapsApiPromiseLazy
* @returns void
*
* @internal
*/
export function saveLazyPromiseAndFinalOptions(
finalOptions: IPluginOptions,
googleMapsApiPromiseLazy: LazyValueGetterFn<GlobalGoogleObject>
): void {
if (!$finalOptions) {
$finalOptions = finalOptions;
}

if (!$googleMapsApiPromiseLazy) {
$googleMapsApiPromiseLazy = googleMapsApiPromiseLazy;
}
}

/**
* This function returns the configuration passed to the plugin
*
* @returns IPluginOptions
*/
export function usePluginOptions(): IPluginOptions {
if (!$finalOptions) {
globalThis.console.warn('$finalOptions was not defined yet...');
}

return $finalOptions;
}
+
warning

The saveLazyPromiseAndFinalOptions is internal and it is not exposed by the plugin

+

useResizeBus

+

This composable returns the currentResizeBus, _resizeCallback, _delayedResizeCallback. If you provide your own resize bus through the GmvMap component props, it should be assigned to the currentResizeBus otherwise the defaultResizeBus (a mitt object) should be assigned to it.

+

You can use it in the following way

+
import { useResizeBus } from '@gmap-vue/v3/composables';

const { currentResizeBus, _resizeCallback, _delayedResizeCallback } = useResizeBus();

currentResizeBus.emit('foo', { a: 'b' });
+

The _resizeCallback is a function used to preserve the map center when it is resized. The _delayedResizeCallback use the nextTick function to call the _resizeCallback in the next change.

+

useResizeBus API

+
// this code is executed when the GmvMap component is initialized

const currentResizeBus = ref<Emitter<Record<EventType, unknown>> | undefined>();
let _resizeCallback: () => void;
let _delayedResizeCallback: () => Promise<void>;

// ...

if (!props.resizeBus) {
currentResizeBus.value = defaultResizeBus; // default resize bus is mitt();
}

if (props.resizeBus) {
currentResizeBus.value = props.resizeBus; // your custom resize bus
}

_resizeCallback = (): void => {
resizeFn();
};

_delayedResizeCallback = (): Promise<void> => {
return nextTick(() => _resizeCallback());
};

// ...

/**
* @typedef ResizeBus
* @property {() => void} currentResizeBus
* @property {() => void} _resizeCallback
* @property {() => void} _delayedResizeCallback
*/
/**
* this function returns the rezise bus functions
*
* @public
* @returns {ResizeBus}
*/
export function useResizeBus() {
return {
currentResizeBus,
_resizeCallback,
_delayedResizeCallback,
};
}
+

useMapPromise

+
warning
    +
  • From v2.0.1 and below we only use one instance of map, because in the previous implementation we always use the same promise to return the same map or we overwrite that promise with a new map instance. From versions above v2.0.1 every map and component is saved in its own promise and is independent to other components.
  • +
  • We strongly recommend to set the mapKey prop on each map, the old recycle prop, we use that key to get the correct map instance and add marker, shapes, etc to the correct map instance.
  • +
+

This composable returns a promise and, when it is resolved return the GmvMap component.

+

You can use it to be sure that the GmvMap component is ready.

+
How to use it
/**
* This function returns a promise, when it is resolved returns the Google Maps component instance
*
* @param {string} key - the recycle prop of the map
* @returns {Promise}
* @public
*/
export function useMapPromise(
key: string | InjectionKey<Promise<google.maps.Map | undefined>>,
): Promise<google.maps.Map | undefined> {
return usePromise<google.maps.Map>(key);
}
+

When the GmvMap component is initialized and the map is ready this promise is resolved

+
map-layer.vue
//...

const mapPromiseDeferred = usePromiseDeferred(props.mapKey || $mapPromise);
promiseDeferred.resolve(mapInstance);

// ...
+
warning

If the Map object was not loaded yet the composable function returns undefined.

+

useStreetViewPanoramaPromise

+
warning
    +
  • From v2.0.1 and below we only use one instance of street view panorama, because in the previous implementation we always use the same promise to return the same street view panorama or we overwrite that promise with a new street view panorama instance. From versions above v2.0.1 every street view panorama and component is saved in its own promise and is independent to other components.
  • +
  • We strongly recommend to set the streetViewKey prop on each street view panorama, we use this key to get the correct street view panorama instance.
  • +
+

This composable is similar to the previous above, the only difference is that it return the street view panorama object from the Google Maps API.

+
How to use it
/**
* This function returns a promise, when it is resolved returns the Google Map StreetViewPanorama component instance
*
* @param {string} key - the streetViewKey prop of the StreetViewPanorama
* @returns {Promise}
* @public
*/
export function useStreetViewPanoramaPromise(
key:
| string
| InjectionKey<Promise<google.maps.StreetViewPanorama | undefined>>,
): Promise<google.maps.StreetViewPanorama | undefined> {
return usePromise<google.maps.StreetViewPanorama>(key);
}
+
warning

If the Street View Panorama object was not loaded yet the composable function returns undefined.

+

useMarkerPromise

+
warning
    +
  • From v2.0.1 and below we only use one instance of marker, because in the previous implementation we always use the same promise to return the same marker or we overwrite that promise with a new marker instance. From versions above v2.0.1 every marker and component is saved in its own promise and is independent to other components.
  • +
  • We strongly recommend to set the markerKey prop on each marker, we use this key to get the correct marker instance.
  • +
+

This composable is similar to the previous above, the only difference is that it return the marker object from the Google Maps API.

+
How to use it
/**
* This function returns a promise, when it is resolved returns the Google Advanced Marker Element component instance
*
* @param {string} key - the markerKey prop of the marker
* @returns {Promise}
* @public
*/
export function useMarkerPromise(
key:
| string
| InjectionKey<
Promise<google.maps.marker.AdvancedMarkerElement | undefined>
>,
): Promise<google.maps.marker.AdvancedMarkerElement | undefined> {
return usePromise<google.maps.marker.AdvancedMarkerElement>(key);
}
+
warning

If the marker object was not loaded yet the composable function returns undefined.

+

useCirclePromise

+
warning
    +
  • From v2.0.1 and below we only use one instance of circle, because in the previous implementation we always use the same promise to return the same circle or we overwrite that promise with a new circle instance. From versions above v2.0.1 every circle and component is saved in its own promise and is independent to other components.
  • +
  • We strongly recommend to set the circleKey prop on each circle, we use this key to get the correct circle instance.
  • +
+

This composable is similar to the previous above, the only difference is that it return the circle object from the Google Maps API.

+
How to use it
/**
* This function returns a promise, when it is resolved returns the Google Circle component instance
*
* @param {string} key - the circleKey prop of the CircleShape
* @returns {Promise}
* @public
*/
export function useCirclePromise(
key: string | InjectionKey<Promise<google.maps.Circle | undefined>>,
): Promise<google.maps.Circle | undefined> {
return usePromise<google.maps.Circle>(key);
}
+
warning

If the circle object was not loaded yet the composable function returns undefined.

+

useClusterPromise

+
warning
    +
  • From v2.0.1 and below we only use one instance of cluster, because in the previous implementation we always use the same promise to return the same cluster or we overwrite that promise with a new cluster instance. From versions above v2.0.1 every cluster and component is saved in its own promise and is independent to other components.
  • +
  • We strongly recommend to set the clusterKey prop on each cluster, we use this key to get the correct cluster instance.
  • +
+

This composable is similar to the previous above, the only difference is that it return the cluster object from the Google Maps API.

+
How to use it
/**
* This function returns a promise, when it is resolved returns the Cluster component instance
*
* @param {string} key - the clusterKey prop of the Cluster
* @returns {Promise}
* @public
*/
export function useClusterPromise(
key: string | InjectionKey<Promise<MarkerClusterer | undefined>>,
): Promise<MarkerClusterer | undefined> {
return usePromise<MarkerClusterer>(key);
}
+
warning

If the cluster object was not loaded yet the composable function returns undefined.

+

useDrawingPromise

+
warning
    +
  • From v2.0.1 and below we only use one instance of drawing, because in the previous implementation we always use the same promise to return the same drawing or we overwrite that promise with a new drawing instance. From versions above v2.0.1 every drawing and component is saved in its own promise and is independent to other components.
  • +
  • We strongly recommend to set the drawingKey prop on each drawing, we use this key to get the correct drawing instance.
  • +
+

This composable is similar to the previous above, the only difference is that it return the drawing object from the Google Maps API.

+
How to use it
/**
* This function returns a promise, when it is resolved returns the Google Map Drawing Manager component instance
*
* @param {string} key - the drawingKey prop of the DrawingManager
* @returns {Promise}
* @public
*/
export function useDrawingPromise(
key:
| string
| InjectionKey<Promise<google.maps.drawing.DrawingManager | undefined>>,
): Promise<google.maps.drawing.DrawingManager | undefined> {
return usePromise<google.maps.drawing.DrawingManager>(key);
}
+
warning

If the drawing object was not loaded yet the composable function returns undefined.

+

useHeatmapLayerPromise

+
warning
    +
  • From v2.0.1 and below we only use one instance of heatmap, because in the previous implementation we always use the same promise to return the same heatmap or we overwrite that promise with a new heatmap instance. From versions above v2.0.1 every heatmap and component is saved in its own promise and is independent to other components.
  • +
  • We strongly recommend to set the heatmapKey prop on each heatmap, we use this key to get the correct heatmap instance.
  • +
+

This composable is similar to the previous above, the only difference is that it return the heatmap object from the Google Maps API.

+
How to use it
/**
* This function returns a promise, when it is resolved returns the Google Map Heatmap Layer component instance
*
* @param {string} key - the heatmapKey prop of the Heatmap Layer
* @returns {Promise}
* @public
*/
export function useHeatmapLayerPromise(
key:
| string
| InjectionKey<Promise<google.maps.visualization.HeatmapLayer | undefined>>,
): Promise<google.maps.visualization.HeatmapLayer | undefined> {
return usePromise<google.maps.visualization.HeatmapLayer>(key);
}
+
warning

If the heatmap object was not loaded yet the composable function returns undefined.

+

useInfoWindowPromise

+
warning
    +
  • From v2.0.1 and below we only use one instance of Info Window, because in the previous implementation we always use the same promise to return the same Info Window or we overwrite that promise with a new Info Window instance. From versions above v2.0.1 every Info Window and component is saved in its own promise and is independent to other components.
  • +
  • We strongly recommend to set the infoWindowKey prop on each Info Window, we use this key to get the correct Info Window instance.
  • +
+

This composable is similar to the previous above, the only difference is that it return the Info Window object from the Google Maps API.

+
How to use it
/**
* This function returns a promise, when it is resolved returns the Google Map Info Window component instance
*
* @param {string} key - the infoWindowKey prop of the Info Window
* @returns {Promise}
* @public
*/
export function useInfoWindowPromise(
key: string | InjectionKey<Promise<google.maps.InfoWindow | undefined>>,
): Promise<google.maps.InfoWindow | undefined> {
return usePromise<google.maps.InfoWindow>(key);
}
+
warning

If the Info Window object was not loaded yet the composable function returns undefined.

+

useKmlPromise

+
warning
    +
  • From v2.0.1 and below we only use one instance of Kml layer, because in the previous implementation we always use the same promise to return the same Kml layer or we overwrite that promise with a new Kml layer instance. From versions above v2.0.1 every Kml layer and component is saved in its own promise and is independent to other components.
  • +
  • We strongly recommend to set the kmlKey prop on each Kml layer, we use this key to get the correct Kml layer instance.
  • +
+

This composable is similar to the previous above, the only difference is that it return the Kml layer object from the Google Maps API.

+
How to use it
/**
* This function returns a promise, when it is resolved returns the Google Map Kml Layer component instance
*
* @param {string} key - the kmlKey prop of the Kml Layer
* @returns {Promise}
* @public
*/
export function useKmlPromise(
key: string | InjectionKey<Promise<google.maps.KmlLayer | undefined>>,
): Promise<google.maps.KmlLayer | undefined> {
return usePromise<google.maps.KmlLayer>(key);
}
+
warning

If the Kml layer object was not loaded yet the composable function returns undefined.

+

usePolygonPromise

+
warning
    +
  • From v2.0.1 and below we only use one instance of polygon, because in the previous implementation we always use the same promise to return the same polygon or we overwrite that promise with a new polygon instance. From versions above v2.0.1 every polygon and component is saved in its own promise and is independent to other components.
  • +
  • We strongly recommend to set the polygonKey prop on each polygon, we use this key to get the correct polygon instance.
  • +
+

This composable is similar to the previous above, the only difference is that it return the polygon object from the Google Maps API.

+
How to use it
/**
* This function returns a promise, when it is resolved returns the Google Map Polygon component instance
*
* @param {string} key - the polygonKey prop of the Polygon
* @returns {Promise}
* @public
*/
export function usePolygonPromise(
key: string | InjectionKey<Promise<google.maps.Polygon | undefined>>,
): Promise<google.maps.Polygon | undefined> {
return usePromise<google.maps.Polygon>(key);
}
+
warning

If the polygon object was not loaded yet the composable function returns undefined.

+

usePolylinePromise

+
warning
    +
  • From v2.0.1 and below we only use one instance of polyline, because in the previous implementation we always use the same promise to return the same polyline or we overwrite that promise with a new polyline instance. From versions above v2.0.1 every polyline and component is saved in its own promise and is independent to other components.
  • +
  • We strongly recommend to set the polylineKey prop on each polyline, we use this key to get the correct polyline instance.
  • +
+

This composable is similar to the previous above, the only difference is that it return the polyline object from the Google Maps API.

+
How to use it
/**
* This function returns a promise, when it is resolved returns the Google Map Polyline component instance
*
* @param {string} key - the polylineKey prop of the Polyline
* @returns {Promise}
* @public
*/
export function usePolylinePromise(
key: string | InjectionKey<Promise<google.maps.Polyline | undefined>>,
): Promise<google.maps.Polyline | undefined> {
return usePromise<google.maps.Polyline>(key);
}
+
warning

If the polyline object was not loaded yet the composable function returns undefined.

+

useRectanglePromise

+
warning
    +
  • From v2.0.1 and below we only use one instance of rectangle, because in the previous implementation we always use the same promise to return the same rectangle or we overwrite that promise with a new rectangle instance. From versions above v2.0.1 every rectangle and component is saved in its own promise and is independent to other components.
  • +
  • We strongly recommend to set the rectangleKey prop on each rectangle, we use this key to get the correct rectangle instance.
  • +
+

This composable is similar to the previous above, the only difference is that it return the rectangle object from the Google Maps API.

+
How to use it
/**
* This function returns a promise, when it is resolved returns the Google Map Rectangle component instance
*
* @param {string} key - the rectangleKey prop of the Rectangle
* @returns {Promise}
* @public
*/
export function useRectanglePromise(
key: string | InjectionKey<Promise<google.maps.Rectangle | undefined>>,
): Promise<google.maps.Rectangle | undefined> {
return usePromise<google.maps.Rectangle>(key);
}
+
warning

If the rectangle object was not loaded yet the composable function returns undefined.

+ + \ No newline at end of file diff --git a/docs/vue-3-version/api/gmap-vue-plugin/index.html b/docs/vue-3-version/api/gmap-vue-plugin/index.html new file mode 100644 index 000000000..d40b013c1 --- /dev/null +++ b/docs/vue-3-version/api/gmap-vue-plugin/index.html @@ -0,0 +1,21 @@ + + + + + +The GmapVuePlugin object | GmapVue Docs + + + + + +

The GmapVuePlugin object

+

It implements the Plugin interface from Vue and get the plugin options.

+

Plugin options

+

The available options of the plugin are the following

+
/**
* The object which contain all event names to and params that should be used to add listener to the Google Maps instance
* @typedef {Object} LoadPluginOptions
* @property {string} key - The Google Maps key
* @property {string?} callback - The callback name that should be called when Google Maps is ready, if you set this do not forget to call `globalThis.GoogleMapsCallback` function in your callback
* @property {string?} v - The version of the Maps JavaScript API to load.
* @property {string} libraries - A comma-separated list of additional Maps JavaScript API libraries to load. Specifying a fixed set of libraries is not generally recommended, but is available for developers who wish to finely tune the caching behavior on their website.
* @property {string} language - The language to use. This affects the names of controls, copyright notices, driving directions, and control labels, and the responses to service requests. See the list of supported languages.
* @property {string} region - The region code to use. This alters the map's behavior based on a given country or territory.
* @property {string} authReferrerPolicy - Maps JS customers can configure HTTP Referrer Restrictions in the Cloud Console to limit which URLs are allowed to use a particular API Key. By default, these restrictions can be configured to allow only certain paths to use an API Key. If any URL on the same domain or origin may use the API Key, you can set authReferrerPolicy: "origin" to limit the amount of data sent when authorizing requests from the Maps JavaScript API. When this parameter is specified and HTTP Referrer Restrictions are enabled on Cloud Console, Maps JavaScript API will only be able to load if there is an HTTP Referrer Restriction that matches the current website's domain without a path specified.
* @property {string} mapIds - An array of map Ids. Causes the configuration for the specified map Ids to be preloaded.
* @property {string} channel - See Usage tracking per channel.
* @property {string} solutionChannel - Google Maps Platform provides many types of sample code to help you get up and running quickly. To track adoption of our more complex code samples and improve solution quality, Google includes the solutionChannel query parameter in API calls in our sample code.
* @see https://developers.google.com/maps/documentation/javascript/load-maps-js-api#optional_parameters
*/
export interface ILoadPluginOptions {
key?: string;
callback?: string;
v?: string;
libraries?: string;
language?: string;
region?: string;
authReferrerPolicy?: string;
mapIds?: string;
channel?: string;
solutionChannel?: string;
}

/**
* @typedef {() => string[]} ExcludeEvents
*
*
* The object which contain all event names to and params that should be used to add listener to the Google Maps instance
* @public
* @typedef {object} PluginOptions - The options required to configure the plugin
* @property {boolean} [dynamicLoad=false] - The plugin should be loaded dynamically, if you set this to `true` the plugin doesn't load the Google Maps API
* @property {LoadPluginOptions} [load] - All load plugin options
* @property {ExcludeEvents} [excludeEventsOnAllComponents] - A function that should return an array of events that should not be fired
*/
export interface IGmapVuePluginOptions {
dynamicLoad?: boolean;
load?: ILoadPluginOptions;
excludeEventsOnAllComponents?: () => string[];
}
+
DEPRECATED

The customCallback option was removed and it is no longer supported

+

The install function

+
/**
* @var
* @type {Object|undefined}
*
* An independent Vue instance that helps us to know when the Google Maps API is loaded.
*/
globalThis.GoogleMapsApi = { isReady: false };

/**
* GmapVuePlugin factory function
*
* @param {IGmapVuePluginOptions} [options] configuration object to initialize the GmapVue plugin
*/
const createGmapVuePlugin = (
options: IGmapVuePluginOptions
): FunctionPlugin => {
/**
* install function
*
* @param {Object} app the vue app instance
*/
return (app: App): void => {
// see defaults
const finalOptions: IGmapVuePluginOptions = {
dynamicLoad: false,
...options,
load: {
libraries: 'places',
...options?.load,
} as any,
};

/**
* Use a lazy to only load the API when
* a GMap component is loaded
*
* @constant
* @type {Function} the promise lazy creator function
*/
const promiseLazyCreator = usePromiseLazyBuilderFn(
googleMapsApiInitializer,
globalThis.GoogleMapsApi
);
/**
* The googleMapsApiPromiseLazy function to can wait until Google Maps API is ready
*
* @constant
* @type {Function}
*/
const googleMapsApiPromiseLazy = promiseLazyCreator(finalOptions);
saveLazyPromiseAndFinalOptions(finalOptions, googleMapsApiPromiseLazy);

/**
* Static properties
*
* These properties are the same references that you can find in the instance,
* but they are static because they are attached to the main Vue object.
* app.config.globalProperties.$googleMapsApiPromiseLazy - function that you can use to wait until Google Maps API is ready
* app.config.globalProperties.$gmapOptions - object with the final options passed to Google Maps API to configure it
*/
app.config.globalProperties.$gmapApiPromiseLazy = googleMapsApiPromiseLazy;
app.config.globalProperties.$gmapOptions = finalOptions;
app.provide($gmapOptions, finalOptions);

app
.component(
'GmvMap',
defineAsyncComponent(() => import('./components/map-layer.vue'))
)
.component(
'GmvMarker',
defineAsyncComponent(() => import('./components/marker-icon.vue'))
)
.component(
'GmvInfoWindow',
defineAsyncComponent(() => import('./components/info-window.vue'))
)
.component(
'GmvKmlLayer',
defineAsyncComponent(() => import('./components/kml-layer.vue'))
)
.component(
'GmvAutocomplete',
defineAsyncComponent(
() => import('./components/autocomplete-input.vue')
)
)
.component(
'GmvStreetViewPanorama',
defineAsyncComponent(
() => import('./components/street-view-panorama.vue')
)
)
.component(
'GmvHeatmapLayer',
defineAsyncComponent(() => import('./components/heatmap-layer.vue'))
)
.component(
'GmvCircle',
defineAsyncComponent(() => import('./components/circle-shape.vue'))
)
.component(
'GmvPolygon',
defineAsyncComponent(() => import('./components/polygon-shape.vue'))
)
.component(
'GmvPolyline',
defineAsyncComponent(() => import('./components/polyline-shape.vue'))
)
.component(
'GmvRectangle',
defineAsyncComponent(() => import('./components/rectangle-shape.vue'))
)
.component(
'GmvDrawingManager',
defineAsyncComponent(() => import('./components/drawing-manager.vue'))
)
.component(
'GmvCluster',
defineAsyncComponent(() => import('./components/cluster-icon.vue'))
);
};
};
+ + \ No newline at end of file diff --git a/docs/vue-3-version/api/index.html b/docs/vue-3-version/api/index.html new file mode 100644 index 000000000..264a96be9 --- /dev/null +++ b/docs/vue-3-version/api/index.html @@ -0,0 +1,49 @@ + + + + + +main.ts | GmapVue Docs + + + + + +

main.ts

+

The main.ts file expose four objects.

+
    +
  • createGmapVuePlugin: The main factory function, used to install the plugin. It returns the install function required by Vue.
  • +
  • utilities: An object with util functions.
  • +
+
export { createGmapVuePlugin, utilities };
+

Other exposed APIs

+

This plugin also exports:

+
    +
  • keys: keys to use with the Vue inject function +
      +
    • path: @gmap-vue/v3/keys
    • +
    +
  • +
  • types: types possible needed to type things when using TypeScript +
      +
    • path: @gmap-vue/v3/types
    • +
    +
  • +
  • interfaces: interfaces possible needed to type things when using TypeScript +
      +
    • path: @gmap-vue/v3/interfaces
    • +
    +
  • +
  • composables: useful composables to access different things of the plugin +
      +
    • path: @gmap-vue/v3/composables
    • +
    +
  • +
  • components: components types of the plugin +
      +
    • path: @gmap-vue/v3/components
    • +
    +
  • +
+ + \ No newline at end of file diff --git a/docs/vue-3-version/api/types/index.html b/docs/vue-3-version/api/types/index.html new file mode 100644 index 000000000..75c50b6fd --- /dev/null +++ b/docs/vue-3-version/api/types/index.html @@ -0,0 +1,20 @@ + + + + + +Types definitions | GmapVue Docs + + + + + +

Types definitions

+

GlobalGoogleObject

+
export type GlobalGoogleObject = typeof google;
+

LazyValueGetterFn

+
export type LazyValueGetterFn<T> = () => Promise<T>;
+

SinglePluginComponentConfig

+
/**
* @typedef {Object} SinglePluginComponentConfigWithoutEvents
* @property {string[]} noBind - Props with should not be bind to Google Maps. Has precedence over twoWay
* @property {string[]} twoWay - Props that should be bind in two-way data binding
* @property {Object} trackProperties - Object with nested properties of a prop that should be watched
* @property {string} trackProperties.key - Should be a string
* @property {string[]} trackProperties.value - Should be an array of nested properties of the prop that should be watched
*/
/**
* @typedef {Object} SinglePluginComponentConfig
* @property {string[]} noBind - Props with should not be bind to Google Maps. Has precedence over twoWay
* @property {string[]} twoWay - Props that should be bind in two-way data binding
* @property {Object} trackProperties - Object with nested properties of a prop that should be watched
* @property {string} trackProperties.key - Should be a string
* @property {string[]} trackProperties.value - Should be an array of nested properties of the prop that should be watched
* @property {Object} events - Events should be bind on the component
* @property {string[]} events.auto - Events of the Google Maps component instance that should be bind
* @property {string[]} events.manual - Manual events that should emit or bind
*/
/** @internal */
export type SinglePluginComponentConfig = {
noBind: string[];
twoWay: string[];
trackProperties: { [key: string]: string[] };
events: {
auto: string[];
manual: string[]; // TODO: try to improve this to be an object with specific keys that can be used in the code
};
};
+ + \ No newline at end of file diff --git a/docs/vue-3-version/api/utilities/index.html b/docs/vue-3-version/api/utilities/index.html new file mode 100644 index 000000000..e2f34f060 --- /dev/null +++ b/docs/vue-3-version/api/utilities/index.html @@ -0,0 +1,31 @@ + + + + + +Utilities | GmapVue Docs + + + + + +

Utilities

+

We have three main utilities googleMapsApiInitializer, pluginComponentBuilder, and getGoogleMapsAPI.

+

googleMapsApiInitializer

+

This function load the Google Maps API into your page creating the <script></script> tag in the head of your page to load the Maps script from https://maps.google.cn or https://maps.googleapis.com depending on your preference and the options you passed into the plugin.

+

googleMapsApiInitializer API

+
(options: ILoadPluginOptions): void => {
/**
* Allow options to be an object.
* This is to support more esoteric means of loading Google Maps,
* such as Google for business
* https://developers.google.com/maps/documentation/javascript/get-api-key#premium-auth
*/
if (Array.isArray(options) || typeof options !== 'object') {
throw new Error('options should be an object');
}

// Do nothing if run from server-side
if (typeof document === 'undefined') {
return;
}

const finalOptions = { ...options };
const { libraries } = finalOptions;
finalOptions.callback = 'GoogleMapsCallback';

// libraries
if (Array.isArray(libraries)) {
finalOptions.libraries = libraries.join(',');
}

if (!isApiSetUp) {
isApiSetUp = true;

const googleMapScript = document.createElement('script');
googleMapScript.setAttribute('type', 'text/javascript');
googleMapScript.innerHTML = `
((g) => {
var h,
a,
k,
p = 'The Google Maps JavaScript API',
c = 'google',
l = 'importLibrary',
q = '__ib__',
m = document,
b = window;
b = b[c] || (b[c] = {});
var d = b.maps || (b.maps = {}),
r = new Set(),
e = new URLSearchParams(),
u = () =>
h ||
(h = new Promise(async (f, n) => {
await (a = m.createElement('script'));
e.set('libraries', [...r] + '');
for (k in g)
e.set(
k.replace(/[A-Z]/g, (t) => '_' + t[0].toLowerCase()),
g[k]
);
e.set('callback', c + '.maps.' + q);
a.src = \`https://maps.\${c}apis.com/maps/api/js?\` + e;
d[q] = f;
a.onerror = () => (h = n(Error(p + ' could not load.')));
a.nonce = m.querySelector('script[nonce]')?.nonce || '';
m.head.append(a);
}));
d[l]
? console.warn(p + ' only loads once. Ignoring:', g)
: (d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)));
})(${JSON.stringify(finalOptions)});`;
document.head.appendChild(googleMapScript);
} else {
window.console.info('You already started the loading of google maps');
}
};
+

pluginComponentBuilder

+

This function helps you to build your own components if it does not exist in the plugin, you can pass a set of options and the function will return a new vue component to be used in your application.

+

pluginComponentBuilder API

+
/**
* A helper to build your own component for the plugin
*
* @param {Object} providedOptions
* @param {Object} providedOptions.mappedProps - Definitions of props
* @param {Object} providedOptions.mappedProps.PROP.type - Value type
* @param {Boolean} providedOptions.mappedProps.PROP.twoWay
* - Whether the prop has a corresponding PROP_changed
* event
* @param {Boolean} providedOptions.mappedProps.PROP.noBind
* - If true, do not apply the default bindProps / bindEvents.
* However it will still be added to the list of component props
* @param {Object} providedOptions.props - Regular Vue-style props.
* Note: must be in the Object form because it will be
* merged with the `mappedProps`
*
* @param {Object} providedOptions.events - Google Maps API events
* that are not bound to a corresponding prop
* @param {String} providedOptions.name - e.g. `polyline`
* @param {Function} providedOptions.ctr - constructor, e.g.
* `google.maps.Polyline`. However, since this is not
* generally available during library load, this becomes
* a function instead, e.g. () => google.maps.Polyline
* which will be called only after the API has been loaded
*
* default: () => String
*
* @param {Function} providedOptions.ctrArgs -
* If the constructor in `ctr` needs to be called with
* arguments other than a single `options` object, e.g. for
* GroundOverlay, we call `new GroundOverlay(url, bounds, options)`
* then pass in a function that returns the argument list as an array
*
* default: (MappedProps, OtherVueProps) => Array
*
* Otherwise, the constructor will be called with an `options` object,
* with property and values merged from:
*
* 1. the `options` property, if any
* 2. a `map` property with the Google Maps
* 3. all the properties passed to the component in `mappedProps`
* @param {Function} providedOptions.beforeCreate -
* Hook to modify the options passed to the initializer
*
* default: (Object) => Any
*
* @param {Function} providedOptions.afterCreate -
* Hook called when
*
* default: (options.ctr, Object) => Any
*
* @returns {Object} A component object that should be exported by default from a Vue component
*/
export function pluginComponentBuilder(
providedOptions: IGmapVueElementOptions
): ComponentOptions {
const {
mappedProps,
name,
ctr,
ctrArgs,
events,
beforeCreate,
afterCreate,
props,
...rest
} = providedOptions;

const promiseName = `$${name}Promise`;
const instanceName = `$${name}Object`;

_assert(!(props instanceof Array), '`props` should be an object, not Array');

return {
props: {
...props,
},
async setup() {},
render() {
return '';
},
provide() {
const promise = useMapPromise()
?.then((map) => {
if (!map) {
throw new Error('the map instance was not created');
}

// Infowindow needs this to be immediately available
this.$map = map;

// Initialize the maps with the given options
const options = {
map,
...getPropsValuesWithoutOptionsProp(props, this),
...this.options,
};
// don't use delete keyword in order to create a more predictable code for the engine

if (beforeCreate) {
const result = beforeCreate.bind(this)(options);

if (result instanceof Promise) {
return result.then(() => ({ options }));
}
}
return { options };
})
.then(({ options }: { options: { [key: string]: any } }) => {
const ConstructorObject = ctr();
// https://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible
this[instanceName] = ctrArgs
? new (Function.prototype.bind.call(
ConstructorObject,
null,
...ctrArgs(
options,
getPropsValuesWithoutOptionsProp(props || {}, this)
)
))()
: new ConstructorObject(options);

bindProps(mappedProps, this[instanceName], this);
bindEvents(events, this[instanceName], this);

if (afterCreate) {
afterCreate.bind(this)(this[instanceName]);
}
return this[instanceName];
});

this[promiseName] = promise;
return { [promiseName]: promise };
},
destroyed() {
// Note: not all Google Maps components support maps
if (this[instanceName] && this[instanceName].setMap) {
this[instanceName].setMap(null);
}
},
...rest,
};
}
+

Below you can see the interface of the options object that it receives

+
export interface IVueProp {
type?:
| StringConstructor
| NumberConstructor
| BooleanConstructor
| ArrayConstructor
| ObjectConstructor
| DateConstructor
| FunctionConstructor
| SymbolConstructor;
required?: boolean;
default?: () => undefined;
validator?: () => boolean;
}

export interface IGmapVueElementOptions {
mappedProps: Omit<SinglePluginComponentConfig, 'events'>;
props: { [key: string]: IVueProp };
events: string[];
name: string;
ctr: () => any;
ctrArgs: (
options: { [key: string]: any },
props: { [key: string]: IVueProp }
) => any[];
beforeCreate: (options: { [key: string]: any }) => any;
afterCreate: (mapElementInstance: { [key: string]: any }) => any;
}
+
info

You can check the SinglePluginComponentConfig type here

+

getGoogleMapsAPI

+

This functions helps you to get the global google object if it is available on your page.

+

getGoogleMapsAPI API

+
/**
* This function helps you to get the Google Maps API
* when its ready on the window object
* @function
*/
function getGoogleMapsAPI(): false | GlobalGoogleObject {
return globalThis.GoogleMapsApi.isReady && globalThis.google;
}
+
info

Check the GlobalGoogleObject type here

+ + \ No newline at end of file diff --git a/docs/vue-3-version/changelog/index.html b/docs/vue-3-version/changelog/index.html new file mode 100644 index 000000000..deb53d42a --- /dev/null +++ b/docs/vue-3-version/changelog/index.html @@ -0,0 +1,73 @@ + + + + + +Changelog | GmapVue Docs + + + + + +

Changelog

2.1.2 (2024-04-24)

+

Bug Fixes

+
    +
  • v3: change inject for composable to get component promise (#324) (6613c59), closes #323
  • +
+

2.1.1 (2024-04-24)

+

Bug Fixes

+
    +
  • v3: remove exposed instances because they are always undefined and cause errors with watchers and events (bdc2f86), closes #318 #319 #320
  • +
+

2.1.0 (2024-04-11)

+

Features

+
    +
  • v3: create independent instances of every component using a component key prop (#315) (0c21c60), closes #309 #309 #309
  • +
+

2.0.1 (2024-04-05)

+

Bug Fixes

+
    +
  • v3: update map props and its interface (90acc21)
  • +
+

2.0.0 (2024-03-31)

+

Bug Fixes

+
    +
  • v3: add type define-emit declarations (fb29c9c)
  • +
  • v3: improve types, interfaces and composables (072f661)
  • +
+

Features

+
    +
  • v3: implement import-library in all components (5d13adf)
  • +
  • v3: improve exports, types and remove deprecated options (9947ce6)
  • +
+

BREAKING CHANGES

+
    +
  • v3: CHANGE
  • +
+

1.0.3 (2023-07-23)

+

Bug Fixes

+
    +
  • v3: fix reactivity problems with google maps objects (#303) (0ef42e7), closes #301
  • +
+

1.0.2 (2023-07-22)

+

Bug Fixes

+
    +
  • docs: update path on import to the new structure (3a0a0ad)
  • +
  • v3: fix visibility issue excluding only null and undefined values from props (159b048)
  • +
+

1.0.1 (2023-06-04)

+

Bug Fixes

+
    +
  • v3: add all single file components to the npm package (79839af)
  • +
+

1.0.0 (2023-06-04)

+

Features

+ +

BREAKING CHANGES

+
    +
  • v3: migrate to vue v3
  • +
+ + \ No newline at end of file diff --git a/docs/vue-3-version/developers/index.html b/docs/vue-3-version/developers/index.html new file mode 100644 index 000000000..4d519f8f4 --- /dev/null +++ b/docs/vue-3-version/developers/index.html @@ -0,0 +1,63 @@ + + + + + +Contributing guide | GmapVue Docs + + + + + +

Contributing guide

+

Commit convention

+

We follow the conventional commit style to write our commits and can follow a semantic version of each package.

+

The commit structure is the follow for inline commits

+
type(scope): the message
+

of the following when you want to add a body or a footer.

+
type(scope): the message

body

footer
+

We use commitlint bot to ensure that all PRs follow this pattern, all PRs that not follow these rules will not be merged until the author fix all needed commits.

+

Valid types

+

We follow the angular convention for types, some of the valid commit types are for example feat, fix, chore, etc; if you want a more detailed explanation please read the valid types on the angular contributing guide.

+

Valid scopes

+

In this project the scopes are required this is because Lerna needs it to determine when it should upgrade the version of a package in the mono repository.

+
NameDescription
rootThis is for changes that only affect the root monorepo managed by Lerna
allThis is for changes that affect all packages and the root monorepo
gmap-vueThis is for changes that affect the gmap-vue package (the plugin package)
docsThis is for changes that affect the documentation package
+

If you have changes that affect gmap-vue and documentation packages you can use the scope that contains the main changes, but this situation is very rare and you must commit the changes in different commits and each of one must have the corresponding scope.

+

Subject min and max length

+

The subject should have 15 characters as a minimum and 75 as a maximum.

+

The subject should be a concise description of the changes.

+

Body

+

The body of the commit is optional, there you can explain in a more detailed way the changes that you will commit. The maximum length of the body should be 300 characters.

+ +

The footer of the commit is optional, there you should add the related issue if it exists, or a message if the commit close o resolve an issue. Also, you can put in this section the keyword BREAKING CHANGE: message to inform that this commit inserts a breaking change on the API, another option to do that is adding the ! symbol after the type(scope) section.

+

Footer examples:

+
issue: #45
+
close: #45
+
resolve: #45
+
BREAKING CHANGE: This breaks the api that generate automatically all components.
+

Git flow and history

+

At this moment we have one main branch master when you fork the project you must work on that branch.

+

This branch have a linear history and you should use the rebase strategy instead of merge strategy to maintain the linear history of the commits.

+

After ensuring that all changes in your branch works as expected we will merge it on the master branch and all features and fixes added to the master branch will automatically be deployed to npm and the documentation site.

+

PR title (deprecated)

+

A tricky point that you need to keep in mind is because of the GitHub behaviour when you make a PR the title of the PR should be similar to an inline commit style, in this way the title validator will approve you PR and will review it and merge it.

+

The regex patter that validates the title for a PR is the following

+
/^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\()(deps|root|all|gmap-vue|documentation)(\))(:)(\s{1}[\.\/\-\_a-z0-9\s]+)$/gm
+

You can test this regex expression following this link regexr.com/59fn0.

+

Code style

+

We follow the Airbnb code style rules, if you have doubts, please read the explanation on his GitHub repository or the Eslint documentation.

+

Your changes must pass the linter before you can commit your changes, this is not optional and required to maintain the same style in the project.

+

Tests

+

We have a few tests in the project and they must pass before we can merge your PR into the project.

+

We have planned to improve our tests adding jest and cypress to the project in the middle term.

+

CONTRIBUTORS NEEDED

+

If you have time to contribute to a rather frequently used library, feel free to make a PR! +For more background, please refer to this issue.

+

What's we needed are:

+
    +
  1. Better automated tests
  2. +
  3. Better integration tests with the popular frameworks, especially Nuxt and Vue template
  4. +
+

The above three will go a long way to keeping the project maintainable and contributable, and will address many of the open issues.

+ + \ No newline at end of file diff --git a/docs/vue-3-version/developers/license/index.html b/docs/vue-3-version/developers/license/index.html new file mode 100644 index 000000000..a6cd92c5a --- /dev/null +++ b/docs/vue-3-version/developers/license/index.html @@ -0,0 +1,18 @@ + + + + + +MIT License | GmapVue Docs + + + + + +

MIT License

+ +

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

+

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

+

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ + \ No newline at end of file diff --git a/docs/vue-3-version/developers/test-the-plugin/index.html b/docs/vue-3-version/developers/test-the-plugin/index.html new file mode 100644 index 000000000..be787a4fa --- /dev/null +++ b/docs/vue-3-version/developers/test-the-plugin/index.html @@ -0,0 +1,21 @@ + + + + + +Test the plugin | GmapVue Docs + + + + + +

Test the plugin

+

To test the plugin locally you can build a local package using the following script

+
pnpm run emulate:package
+

After that a new .pack folder will be generated at the same level than src or dist folders. When this new folder is ready you can install the plugin using that folder in any project that you are using to test it.

+

Go to the vue project that use the plugin and, in its root directory, at the same level of the package.json run the below command.

+
pnpm link ../gmap-vue/packages/v3/.pack
+
warning

Don't forget to add your own relative path there 👆🏼

+

After do that your project will be using the plugin from the .pack folder and not downloading from the NPM registry.

+ + \ No newline at end of file diff --git a/docs/vue-3-version/examples/index.html b/docs/vue-3-version/examples/index.html new file mode 100644 index 000000000..2992d6097 --- /dev/null +++ b/docs/vue-3-version/examples/index.html @@ -0,0 +1,15 @@ + + + + + +Examples | GmapVue Docs + + + + + +

Examples

+

Here you can play with a CodeSandbox project to test all the examples provided in this documentation.

+ + \ No newline at end of file diff --git a/docs/vue-3-version/guide/basic-usage/accessing-google-maps-api/index.html b/docs/vue-3-version/guide/basic-usage/accessing-google-maps-api/index.html new file mode 100644 index 000000000..1bdbf20e3 --- /dev/null +++ b/docs/vue-3-version/guide/basic-usage/accessing-google-maps-api/index.html @@ -0,0 +1,18 @@ + + + + + +Accessing Google Maps API | GmapVue Docs + + + + + +

Accessing Google Maps API

+

If you need to access the Google maps API directly you can use the getGoogleMapsAPI function utility.

+
Options API
<template>
<GmvMap ref="mapRef" class="map" :center="center" :zoom="7"></GmvMap>
</template>
<script>
import { utilities } from '@gmap-vue/v3';

const { getGoogleMapsAPI } = utilities;

export default {
name: 'your-component-name',
data() {
return {
center: {
lat: 1.32,
lng: 103.8,
},
};
},
computed: {
// The below example is the same as writing
// google() {
// return getGoogleMapsAPI();
// },
google: getGoogleMapsAPI,
},
};
</script>
<style scoped>
.map {
height: 50vh;
width: 50vw;
}
</style>
+

In composition API you can use this function as any normal function

+
Composition API
<template>
<GmvMap ref="mapRef" class="map" :center="center" :zoom="7"></GmvMap>
</template>
<script setup lang="ts">
import { utilities } from '@gmap-vue/v3';

const center = {
lat: 1.32,
lng: 103.8,
};
const { getGoogleMapsAPI } = utilities;
const googleAPI = getGoogleMapsAPI()
</script>
<style scoped>
.map {
height: 50vh;
width: 50vw;
}
</style>
+ + \ No newline at end of file diff --git a/docs/vue-3-version/guide/basic-usage/dynamic-load/index.html b/docs/vue-3-version/guide/basic-usage/dynamic-load/index.html new file mode 100644 index 000000000..26e95f539 --- /dev/null +++ b/docs/vue-3-version/guide/basic-usage/dynamic-load/index.html @@ -0,0 +1,26 @@ + + + + + +Dynamic load | GmapVue Docs + + + + + +

Dynamic load

+

If you need to initialize the Google Maps API in a dynamic way you can use the dynamicLoad option of the plugin +configuration, this option start the plugin but it doesn't load the Google Maps API, you need to load it manually using +the googleMapsApiInitializer function from the utilities object exposed by the plugin as we show below

+
main.ts
//...

createApp(App)
.use(router)
.use(createGmapVuePlugin({ dynamicLoad: true }))
.mount("#app");

//...
+

In setup script

+
[your-component].vue - Composition API
import { onMounted } from "vue";
import { utilities } from "@gmap-vue/v3";
import { usePluginOptions } from "@gmap-vue/v3/composables";

const { googleMapsApiInitializer } = utilities;
const options = usePluginOptions();

onMounted(() => {
googleMapsApiInitializer(options);
});
+

or in options API

+
[your-component].vue - Options API
import { onMounted } from "vue";
import { utilities } from "@gmap-vue/v3";

const { googleMapsApiInitializer } = utilities;

export default {
mounted() {
googleMapsApiInitializer(this.$gmapOptions);
},
};
+
info
    +
  • If you want to know the googleMapsApiInitializer API please check it here.
  • +
  • Check the plugin options interface here
  • +
+ + \ No newline at end of file diff --git a/docs/vue-3-version/guide/basic-usage/gmv-map-slots/index.html b/docs/vue-3-version/guide/basic-usage/gmv-map-slots/index.html new file mode 100644 index 000000000..079dfb7e2 --- /dev/null +++ b/docs/vue-3-version/guide/basic-usage/gmv-map-slots/index.html @@ -0,0 +1,26 @@ + + + + + +GmvMap Slots | GmapVue Docs + + + + + +

GmvMap Slots

+
note

This is the MapLayer component

+

GmvMap component has two slots with a different behavior. +The default slot is wrapped in a class that sets display: none; so by default any component you add to your map will +be invisible.

+

This is ok for most of the supplied components that interact directly with the Google map object, but it's not good if +you want to bring up things like toolboxes, etc.

+

There is a second slot named "visible" that must be used if you want to display content within the responsive +wrapper for the map, hence that's why you'll see this in the drawing manager with slot example. It's actually +not required in the first example because the default toolbox is part of the Google map object.

+
+

Thanks to @davydnorris to document this part of the plugin.

+
+ + \ No newline at end of file diff --git a/docs/vue-3-version/guide/basic-usage/lazy-loading/index.html b/docs/vue-3-version/guide/basic-usage/lazy-loading/index.html new file mode 100644 index 000000000..2b717cdb5 --- /dev/null +++ b/docs/vue-3-version/guide/basic-usage/lazy-loading/index.html @@ -0,0 +1,19 @@ + + + + + +Lazy loading | GmapVue Docs + + + + + + + + \ No newline at end of file diff --git a/docs/vue-3-version/guide/basic-usage/map-reference/index.html b/docs/vue-3-version/guide/basic-usage/map-reference/index.html new file mode 100644 index 000000000..a8fc6bee7 --- /dev/null +++ b/docs/vue-3-version/guide/basic-usage/map-reference/index.html @@ -0,0 +1,21 @@ + + + + + +Getting a map reference | GmapVue Docs + + + + + +

Getting a map reference

+

If you need to gain access to the Map instance (e.g. to call panToBounds, panTo)

+
Options API
<template>
<GmvMap ref="mapRef" class="map" :center="center" :zoom="7"></GmvMap>
</template>
<script lang="ts">
// import { type IMapLayerVueComponentExpose } from '@gmap-vue/v3/interfaces';

export default {
data() {
return {
center: {
lat: 1.32,
lng: 103.8,
},
};
},
mounted() {
// At this point, the child GmapMap has been mounted, but
// its map has not been initialized.
// Therefore we need to write mapRef.$mapPromise.then(() => ...)

// (this.$refs.mapRef as (typeof MapLayer & IMapLayerVueComponentExpose)).mapPromise // - useful to type the exposed method
this.$refs.mapRef.mapPromise?.then((map) => {
if (map) {
setTimeout(() => {
map.panTo({ lat: 1.0, lng: 100.0 });
console.log(this.$refs.mapRef);
}, 2000);
}
});
},
};
</script>
<style scoped>
.map {
height: 50vh;
width: 50vw;
}
</style>
+
Composition API
<template>
<GmvMap ref="mapRef" class="map" :center="center" :zoom="7"></GmvMap>
</template>

<script setup lang="ts">
import { useMapPromise } from "@gmap-vue/v3/composables";
import { onMounted, ref } from "vue";
import { MapLayer } from "@gmap-vue/v3/components";

const mapRef = ref<typeof MapLayer | null>(null);
const mapPromise = useMapPromise();
const center = {
lat: 1.32,
lng: 103.8,
};
onMounted(() => {
mapPromise?.then((map) => {
if (map) {
setTimeout(() => {
map.panTo({ lat: 1.0, lng: 100.0 });
console.log(mapRef.value);
}, 2000);
}
});
});
</script>

<style scoped>
.map {
height: 50vh;
width: 50vw;
}
</style>
+

Typing a component ref

+
info

To safety type a ref of one of the plugin components is to add the following to your main.ts file

main.ts
import { ComponentInstance } from "vue";
import { MapLayer } from "@gmap-vue/v3/components";
import { type IMapLayerVueComponentExpose } from "@gmap-vue/v3/interfaces";

/**
* Vue augmentations
*/
declare module "vue" {
interface ComponentCustomProperties {
$refs: {
mapRef: ComponentInstance<typeof MapLayer & IMapLayerVueComponentExpose>;
};
}
}
+

The inject issue

+
warning

In this example you can not use the inject method to get the mapPromise as we show below

Composition API
import { inject } from "vue";
import { $mapPromise } from "@gmap-vue/v3/keys";

const mapPromise = inject($mapPromise);

Why not? because you can use inject in a child component, that means in any component that you put between <GmvMap ref="mapRef" class="map" :center="center" :zoom="7"> ... </GmvMap>.

In the examples above our component is the parent of the GmvMap component and the provide function was not executed yet, and we can not inject something that is not provided yet. Simple but tricky in a simple overview.

+ + \ No newline at end of file diff --git a/docs/vue-3-version/guide/basic-usage/nuxt/index.html b/docs/vue-3-version/guide/basic-usage/nuxt/index.html new file mode 100644 index 000000000..1cdd06dae --- /dev/null +++ b/docs/vue-3-version/guide/basic-usage/nuxt/index.html @@ -0,0 +1,20 @@ + + + + + +Nuxt | GmapVue Docs + + + + + +

Nuxt

+
warning

This was taken from the documentation about the version form Vue 2. This should be checked and confirmed.

+

For Nuxt projects, please import GmapVuePlugin in the following way:

+
import { GmapVuePlugin } from '~/node_modules/@gmap-vue/v3'
+

Add the following to your nuxt.config.js's build.extend():

+
transpile: [/^@gmap-vue\/v3($|\/)/]
+
note

Please take a look at this example on stackblitz

+ + \ No newline at end of file diff --git a/docs/vue-3-version/guide/basic-usage/plugin-component-builder/index.html b/docs/vue-3-version/guide/basic-usage/plugin-component-builder/index.html new file mode 100644 index 000000000..fdd50a5dc --- /dev/null +++ b/docs/vue-3-version/guide/basic-usage/plugin-component-builder/index.html @@ -0,0 +1,23 @@ + + + + + +Plugin component builder | GmapVue Docs + + + + + +

Plugin component builder

+

To build your own component you can use the pluginComponentBuilder function. You need to provide the following options to it

+
interfaces & types
export type SinglePluginComponentConfig = {
noBind: string[];
twoWay: string[];
trackProperties: { [key: string]: string[] };
events: {
auto: string[];
manual: string[]; // TODO: try to improve this to be an object with specific keys that can be used in the code
};
};

export interface IVueProp {
type?:
| StringConstructor
| NumberConstructor
| BooleanConstructor
| ArrayConstructor
| ObjectConstructor
| DateConstructor
| FunctionConstructor
| SymbolConstructor;
required?: boolean;
default?: () => undefined;
validator?: () => boolean;
}

export interface IGmapVueElementOptions {
mappedProps: Omit<SinglePluginComponentConfig, 'events'>;
props: { [key: string]: IVueProp };
events: string[];
name: string;
ctr: () => any;
ctrArgs: (
options: { [key: string]: any },
props: { [key: string]: IVueProp },
) => any[];
beforeCreate: (options: { [key: string]: any }) => any;
afterCreate: (mapElementInstance: { [key: string]: any }) => any;
}
+

How to use it

+
DirectionsRenderer.ts
import { helpers } from 'gmap-vue'
const { MapElementFactory } = helpers;

export default MapElementFactory({
name: 'directionsRenderer',
ctr: () => google.maps.DirectionsRenderer,
//// The following is optional, but necessary if the constructor takes multiple arguments
//// e.g. for GroundOverlay
// ctrArgs: (options, otherProps) => [options],
events: ['directions_changed'],

// Mapped Props will automatically set up
// this.$watch('propertyName', (v) => instance.setPropertyName(v))
//
// If you specify `twoWay`, then it also sets up:
// google.maps.event.addListener(instance, 'propertyName_changed', () => {
// this.$emit('propertyName_changed', instance.getPropertyName())
// })
//
// If you specify `noBind`, then neither will be set up. You should manually
// create your watchers in `afterCreate()`.
mappedProps: {
routeIndex: { type: Number },
options: { type: Object },
panel: { },
directions: { type: Object },
//// If you have a property that comes with a `_changed` event,
//// you can specify `twoWay` to automatically bind the event, e.g. Map's `zoom`:
// zoom: {type: Number, twoWay: true}
},
// Any other properties you want to bind. Note: Must be in Object notation
props: {},
// Actions you want to perform before creating the object instance using the
// provided constructor (for example, you can modify the `options` object).
// If you return a promise, execution will suspend until the promise resolves
beforeCreate (options) {},
// Actions to perform after creating the object instance.
afterCreate (directionsRendererInstance) {},
})
+

Thereafter, it's easy to use the newly-minted component!

+
Options API
<template>
<GmvMap :zoom="..." :center="...">
<DirectionsRenderer />
</GmvMap>
</template>
<script>
import DirectionsRenderer from './DirectionsRenderer.js'

export default {
components: { DirectionsRenderer },
}
</script>
+
info
+ + \ No newline at end of file diff --git a/docs/vue-3-version/guide/basic-usage/region-and-language/index.html b/docs/vue-3-version/guide/basic-usage/region-and-language/index.html new file mode 100644 index 000000000..7f643e7cd --- /dev/null +++ b/docs/vue-3-version/guide/basic-usage/region-and-language/index.html @@ -0,0 +1,21 @@ + + + + + +Region and Language | GmapVue Docs + + + + + +

Region and Language

+

Use the region and language options to localize your map.

+
For more information
+
main.ts
import { createGmapVuePlugin } from '@gmap-vue/v3';
import '@gmap-vue/v3/dist/style.css';
import { createApp } from 'vue';
import App from './App.vue';
import './style.css';

createApp(App)
.use(
createGmapVuePlugin({
load: {
key: '...',
region: 'VI',
language: 'vi',
},
})
)
.mount('#app');
+ + \ No newline at end of file diff --git a/docs/vue-3-version/guide/components/autocomplete/index.html b/docs/vue-3-version/guide/components/autocomplete/index.html new file mode 100644 index 000000000..368a8985b --- /dev/null +++ b/docs/vue-3-version/guide/components/autocomplete/index.html @@ -0,0 +1,30 @@ + + + + + +Autocomplete | GmapVue Docs + + + + + +

Autocomplete

+

This component helps you to find and select a place on Google Maps API. For more information read the Google Maps documentation for autocomplete.

+

It is exported with the name Autocomplete, it is registered as GmvAutocomplete.

+

Autocomplete instance

+

This component save the original autocomplete object provided by Google Maps in a property called autoCompleteInstance, as the example below.

+
// ...
const { Autocomplete } = (await google.maps.importLibrary(
'places',
)) as google.maps.PlacesLibrary;

if (typeof Autocomplete !== 'function') {
throw new Error(
"google.maps.places.Autocomplete is undefined. Did you add 'places' to libraries when loading Google Maps?",
);
}

const autocomplete = new Autocomplete(scopedInput, autocompleteOptions);
// ...
+

Source code

+

You can see the source code on:

+ +

How to use it

+
<template>
<!-- you can use the auto close form if you don't use the slot -->
<gmv-autocomplete />
<!-- <gmv-autocomplete></gmv-autocomplete> -->

<gmv-map :center="center" :zoom="7" style="width: 100%; height: 500px">
</gmv-map>
</template>
+
<template>
<!-- or use it with a slot -->
<GmvAutocomplete></GmvAutocomplete>
<!-- <GmvAutocomplete /> -->

<gmv-map :center="center" :zoom="7" style="width: 100%; height: 500px">
</gmv-map>
</template>
+

Customizing your text field

+
tip

The autocomplete supports custom text field via scoped slot

<gmv-autocomplete class="introInput">
<template v-slot:default="slotProps">
<v-text-field
outlined
prepend-inner-icon="place"
placeholder="Location Of Event"
ref="input"
v-bind:attrs="slotProps.attrs"
>
</v-text-field>
</template>
</gmv-autocomplete>

The ref on the element must be unique. If you create more than one autocomplete, each one should have a unique ref and it must be mentioned in the slot-ref-name prop. Like this:

<gmv-autocomplete class="introInput">
<template v-slot:default="slotProps">
<v-text-field
outlined
prepend-inner-icon="place"
placeholder="Location Of Event"
ref="input"
v-bind:attrs="slotProps.attrs"
>
</v-text-field>
</template>
</gmv-autocomplete>
<gmv-autocomplete class="introInput" slot-ref-name="input2">
<template v-slot:default="slotProps">
<v-text-field
outlined
prepend-inner-icon="place"
placeholder="Location Of Event"
ref="input2"
v-bind:attrs="slotProps.attrs"
>
</v-text-field>
</template>
</gmv-autocomplete>

If the element in the slot is a vue component then it must have a child ref called input (like in vuetify text-field) or specify a custom name via the child-ref-name prop (only works one level deep into a component).

The v-bind:attrs is required.

+ + \ No newline at end of file diff --git a/docs/vue-3-version/guide/components/map/index.html b/docs/vue-3-version/guide/components/map/index.html new file mode 100644 index 000000000..5279dfeda --- /dev/null +++ b/docs/vue-3-version/guide/components/map/index.html @@ -0,0 +1,54 @@ + + + + + +Map | GmapVue Docs + + + + + +

Map

+

This component helps you to create a Map with the Google Maps API. For more information read the Google Maps documentation for the map.

+

It is exported with the name MapLayer, it is registered as GmvMap.

+

Map instance

+

This component save the original map object provided by Google Maps in a property called mapInstance, as the example below.

+
// ...
const { Map } = (await google.maps.importLibrary(
'maps',
)) as google.maps.MapsLibrary;
mapInstance = new Map(gmvMap.value, mapLayerOptions);
// ...
+

Source code

+

You can see the source code on:

+ +

How to use it

+
<template>
<!-- you can use the auto close form if you don't use the slot -->
<gmv-map :center="center" :zoom="7" style="width: 100%; height: 500px"/>

<gmv-map :center="center" :zoom="7" style="width: 100%; height: 500px">
</gmv-map>
</template>
+
<template>
<!-- you can use the auto close form if you don't use the slot -->
<GmvMap :center="center" :zoom="7" style="width: 100%; height: 500px"/>

<GmvMap :center="center" :zoom="7" style="width: 100%; height: 500px">
</GmvMap>
</template>
+

Some tricky parts

+

getBounds

+

If you need to use the getBounds method of the Map instance, you can do it with a reference, and wait for the mapPromise to resolve or using the useMapPromise('you-map-key') composable to get the map promise and wait for it to resolve.

+

If you use the getBounds method in the mounted hook you need to take care about three things:

+
    +
  1. The center should be defined
  2. +
  3. The zoom should be defined
  4. +
  5. The map should be visible
  6. +
+

In the official documentation +it says:

+
+

If the map is not yet initialized or center and zoom have not been set then the result is undefined.

+
+

Because of that behavior you must listen for the tilesloaded event in the map component, this event is fired when the +maps is visible and allows you to accomplish with the three requirements mentioned above.

+
+

You can refer to the issue #67

+
+
<template>
<div>
<GmvMap
@tilesloaded="tilesloadedEvent"
:center="center"
:zoom="11"
style="width: 100%; height: 500px"
ref="gmap">
....
</GmvMap>
</div>
</template>

<script>
export default {
// ...
data() {
return {
map: undefined,
}
},
async mounted() {
// this is a good practice
await this.$gmapApiPromiseLazy();
this.map = await this.$refs.gmap.mapPromise;

// you can do the same in the following way but is more verbose
// this.$refs.gmap.mapPromise
// .then((map) => {
// map.addListener('tilesloaded', () => {
// console.log('>>>>>>>>>> getCenter', map.getCenter())
// console.log('>>>>>>>>>> getZoom', map.getZoom())
// console.log('>>>>>>>>>> getBounds', map.getBounds())
// });
// })
// .catch((e) => console.error(e));
},
methods: {
tilesloadedEvent() {
console.log('>>>>>>>>>> getCenter', this.map.getCenter())
console.log('>>>>>>>>>> getZoom', this.map.getZoom())
console.log('>>>>>>>>>> getBounds', this.map.getBounds())
}
}
};
</script>
+

PlacesService

+

If want to use the google.maps.places.PlacesService class we let you here an example about how to implement it.

+
+

You can refer to the issue #130

+
+
<template>
<div>
<GmvMap
:center="center"
:zoom="zoom"
style="width: 100%; height: 500px"
ref="googleMap"
>
</GmvMap>
</div>
</template>

<script>
import { utilities } from "gmap-vue";

const { getGoogleMapsAPI } = utilities;

export default {
data() {
return {
center: { lat: 10, lng: 10 },
zoom: 11,
};
},
async mounted() {
await this.$gmapApiPromiseLazy();

const google = getGoogleMapsAPI();
console.log(">>>>>>>>>>>> placesService", google.maps.places);
console.log(">>>>>>>>>>>> map instance", await this.$refs.googleMap.mapPromise);

const service = new google.maps.places.PlacesService(
document.createElement("div") // if you pass the map object here it doesn't work
);

console.log("service", service);

const request = {
query: "Museum of Contemporary Art Australia",
fields: ["name", "geometry"],
};

const map = await this.$refs.googleMap.mapPromise;
service.findPlaceFromQuery(request, function (results, status) {
if (status === google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
console.log(results[i]);
}
map.setCenter(results[0].geometry.location);
}
});
},
};
</script>
+ + \ No newline at end of file diff --git a/docs/vue-3-version/guide/global-properties/index.html b/docs/vue-3-version/guide/global-properties/index.html new file mode 100644 index 000000000..f0ae15be4 --- /dev/null +++ b/docs/vue-3-version/guide/global-properties/index.html @@ -0,0 +1,31 @@ + + + + + +Global Properties | GmapVue Docs + + + + + +

Global Properties

+

We have two main global properties

+
    +
  1. $gmapApiPromiseLazy
  2. +
  3. $gmapOptions.
  4. +
+

You can access these properties as follows

+

Options API

+
[your-component].vue
export default {
mounted() {
this.$gmapApiPromiseLazy().then(...).catch(...);
this.$gmapOptions;
}
}
+

Composition API

+

You can use the following composables

+
[your-component].vue
import { usePluginOptions, useGoogleMapsApiPromiseLazy } from '@gmap-vue/v3/composables';

const options = usePluginOptions();
const googleMapsApiPromiseLazy = useGoogleMapsApiPromiseLazy();
+

Getting the plugin options with inject

+
[your-component].vue
import { $gmapOptions } from '@gmap-vue/v3/keys';
import { inject } from 'vue';

const options = inject($gmapOptions);
+
info
    +
  • Check the useGoogleMapsApiPromiseLazy object here
  • +
  • Check the usePluginOptions object here
  • +
+ + \ No newline at end of file diff --git a/docs/vue-3-version/guide/index.html b/docs/vue-3-version/guide/index.html new file mode 100644 index 000000000..396a01e59 --- /dev/null +++ b/docs/vue-3-version/guide/index.html @@ -0,0 +1,25 @@ + + + + + +Introduction | GmapVue Docs + + + + + +

Introduction

This plugin is a Vue wrapper over the Google Maps API.

+

TypeScript support

+

This plugin was re-built entirely to has a full TypeScript support. Many things on it changed from the plugin built to use with Vue 2.

+

JSDoc comments

+

All files in the source code are entirely self documented with jsdoc comments. You can refer to this comments with confidence to learn how this new version of the plugin works.

+

Get an API key from Google

+

Generating an Google Maps API key.

+

How to use it

+

The GmapVuePlugin exposed in the package is an object that contains the install function required for Vue to add plugins to your app.

+
main.ts
import { createGmapVuePlugin } from '@gmap-vue/v3';
import App from './App.vue';
import '@gmap-vue/v3/dist/style.css';

const app = createApp(App);

app.use(
createGmapVuePlugin({
load: {
key: 'DlSzZaMeStOJndmvuPsSUcPBjxUNCpqd3BNYlZ1sWdMrOT5XrxrcvMNVllLH2nwINsFo8kyXVGStqKci',
},
})
);
app.mount('#app');
+
info

To know the available options of the plugin go to the api documentation to check it.

+
info

To know more about the components object check the api documentation to check it.

+ + \ No newline at end of file diff --git a/docs/vue-3-version/guide/install-function/index.html b/docs/vue-3-version/guide/install-function/index.html new file mode 100644 index 000000000..f05e875ff --- /dev/null +++ b/docs/vue-3-version/guide/install-function/index.html @@ -0,0 +1,29 @@ + + + + + +The install function | GmapVue Docs + + + + + +

The install function

+

The install function get the options passed to the plugin and process it to initialize the plugin.

+

The install function loads the Google Maps API using a promise. This promise is returned by the googleMapsApiPromiseLazy function. This function is saved in a global property inside the app called $gmapApiPromiseLazy and you can use it to access it in the options API.

+

The install function also saved the options passed to the plugin in a global property of the app called $gmapOptions that you can use to access the plugin options in the Vue options API. The install function also use provide with a key called $gmapOptions to provide it to all child components in the application.

+

These two options also have its own composables functions that you can use to get their respective values using the Vue composition API. For more details go to the next section.

+
plugin main.ts
// ...
app.config.globalProperties.$gmapApiPromiseLazy = googleMapsApiPromiseLazy;
app.config.globalProperties.$gmapOptions = finalOptions;
app.provide($gmapOptions, finalOptions);
// ...
+

Finally, by default the install function initialize and install all components in the plugin.

+
plugin main.ts
// ...
app
.component(
'GmvMap',
defineAsyncComponent(() => import('./components/map-layer.vue'))
)
.component(
'GmvMarker',
defineAsyncComponent(() => import('./components/marker-icon.vue'))
)
.component(
'GmvInfoWindow',
defineAsyncComponent(() => import('./components/info-window.vue'))
)
.component(
'GmvKmlLayer',
defineAsyncComponent(() => import('./components/kml-layer.vue'))
)
.component(
'GmvAutocomplete',
defineAsyncComponent(() => import('./components/autocomplete-input.vue'))
)
.component(
'GmvStreetViewPanorama',
defineAsyncComponent(() => import('./components/street-view-panorama.vue'))
)
.component(
'GmvHeatmapLayer',
defineAsyncComponent(() => import('./components/heatmap-layer.vue'))
)
.component(
'GmvCircle',
defineAsyncComponent(() => import('./components/circle-shape.vue'))
)
.component(
'GmvPolygon',
defineAsyncComponent(() => import('./components/polygon-shape.vue'))
)
.component(
'GmvPolyline',
defineAsyncComponent(() => import('./components/polyline-shape.vue'))
)
.component(
'GmvRectangle',
defineAsyncComponent(() => import('./components/rectangle-shape.vue'))
)
.component(
'GmvDrawingManager',
defineAsyncComponent(() => import('./components/drawing-manager.vue'))
)
.component(
'GmvCluster',
defineAsyncComponent(() => import('./components/cluster-icon.vue'))
);

// ...
+
note
    +
  • As you can see above all components are lazy loaded
  • +
  • Now the GmvCluster component is registered by default, remember to install the "@googlemaps/markerclusterer": "^2.5.3" package
  • +
+
info
    +
  • Check the install function API here
  • +
  • Check the resize bus API here
  • +
+ + \ No newline at end of file diff --git a/docs/vue-3-version/index.html b/docs/vue-3-version/index.html new file mode 100644 index 000000000..bcc5e7923 --- /dev/null +++ b/docs/vue-3-version/index.html @@ -0,0 +1,49 @@ + + + + + +Welcome | GmapVue Docs + + + + + +

GmapVue for Vue 3

+

+
warning

This documentation is under development, it contains the main points and examples but we continue working on it. Please if you find a bug or something that is not correct, feel free to report it or send a PR to improve it. Thank you.

+

Installation

+
npm install @gmap-vue/v3 --save
+

Using a CDN

+

You can use a free CDN like jsdelivr to include this plugin in your html file

<script src="https://cdn.jsdelivr.net/npm/@gmap-vue/v3/dist/main.umd.js"></script>
+
warning

Be aware that if you use this method, you cannot use TitleCase for your components and your attributes. +That is, instead of writing <GmvMap>, you need to write <gmv-map>.

+

Global styles

+

The plugin exports a simple css file to add minimum styles to the main GmvMap component.

+
main.ts
import { createGmapVuePlugin } from '@gmap-vue/v3';
import { createApp } from 'vue';
import '@gmap-vue/v3/dist/style.css';
import App from './App.vue';
import './style.css';

const app = createApp(App);
app.use(createGmapVuePlugin({
load: { key: '...' },
}));
app.mount('#app');
+

Dynamic Library Import

+

We follow the recommendation of the Google Maps team, who encourages to tuse the dynamic load of the library. For more information please follow this link.

+

Migrating from version for Vue 2

+
    +
  • You can import the package from '@gmap-vue/v3' instead of 'gmap-vue'
  • +
  • The install fucntion of the plugin now is not exported by default, it is exported by name as we show below
  • +
+
import { createGmapVuePlugin } from '@gmap-vue/v3';
+
    +
  • All components now are lazy loaded, that means if you don't use it in your code they are not include in your final bundle. This change makes the installComponents property unuseful.
  • +
  • The config proerty installComponents was removed.
  • +
  • The $gmapDefaultResizeBus global property was removed.
  • +
  • The customCallback option is deprecated
  • +
  • We add a new global property $gmapOptions it contains the final options object received by the plugin.
  • +
  • All components now are prefixed with Gmv, eg: GmvMap in the case of the Map component.
  • +
  • The initGoogleMapsApi now is called googleMapsApiInitializer
  • +
  • The MapElementFactory now is called pluginComponentBuilder
  • +
  • The GoogleMapsApi now is only a global variable attached to the window object
  • +
  • All mixins were removed, now they are composable functions
  • +
  • Many of the old factories and helpers now are internal composable functions and they are not exposed by the plugin because, is not intended to be used.
  • +
  • The createGoogleMapsAPIInitializer now is called googleMapsAPIInitializerFactory, and it is an internal function of the plugin.
  • +
  • The mapped-props concept was removed from the plugin and now every component has its props defined on it.
  • +
+
note

If we missed some of the bracking changes, feel free to open a PR to add them to this list.

+ + \ No newline at end of file diff --git a/img/docusaurus-social-card.jpg b/img/docusaurus-social-card.jpg new file mode 100644 index 000000000..ffcb44821 Binary files /dev/null and b/img/docusaurus-social-card.jpg differ diff --git a/img/docusaurus.png b/img/docusaurus.png new file mode 100644 index 000000000..f458149e3 Binary files /dev/null and b/img/docusaurus.png differ diff --git a/img/favicon.ico b/img/favicon.ico new file mode 100644 index 000000000..c01d54bcd Binary files /dev/null and b/img/favicon.ico differ diff --git a/img/logo.svg b/img/logo.svg new file mode 100644 index 000000000..9db6d0d06 --- /dev/null +++ b/img/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/undraw_docusaurus_mountain.svg b/img/undraw_docusaurus_mountain.svg new file mode 100644 index 000000000..af961c49a --- /dev/null +++ b/img/undraw_docusaurus_mountain.svg @@ -0,0 +1,171 @@ + + Easy to Use + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/img/undraw_docusaurus_react.svg b/img/undraw_docusaurus_react.svg new file mode 100644 index 000000000..94b5cf08f --- /dev/null +++ b/img/undraw_docusaurus_react.svg @@ -0,0 +1,170 @@ + + Powered by React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/img/undraw_docusaurus_tree.svg b/img/undraw_docusaurus_tree.svg new file mode 100644 index 000000000..d9161d339 --- /dev/null +++ b/img/undraw_docusaurus_tree.svg @@ -0,0 +1,40 @@ + + Focus on What Matters + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/index.html b/index.html new file mode 100644 index 000000000..00532563c --- /dev/null +++ b/index.html @@ -0,0 +1,14 @@ + + + + + +Hello from GmapVue Docs | GmapVue Docs + + + + + +

GmapVue Docs

Documentation about GmapVue plugin

Easy to Use

New API

An improved API designed thinking on the developer experience.

Focus on What Matters

Full TypeScript support

Now with full typescript support is easy to understand what happens in the code, self documented and with good inline documentation using JSDocs comments.

Powered by React

Easy to use

In this version we tried to make the plugin simple and easy to use.

+ + \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 000000000..32698ea56 --- /dev/null +++ b/sitemap.xml @@ -0,0 +1 @@ +https://diegoazh.github.io/gmap-vue/blogweekly0.5https://diegoazh.github.io/gmap-vue/blog/archiveweekly0.5https://diegoazh.github.io/gmap-vue/blog/authorsweekly0.5https://diegoazh.github.io/gmap-vue/blog/first-blog-postweekly0.5https://diegoazh.github.io/gmap-vue/blog/greetingsweekly0.5https://diegoazh.github.io/gmap-vue/blog/long-blog-postweekly0.5https://diegoazh.github.io/gmap-vue/blog/mdx-blog-postweekly0.5https://diegoazh.github.io/gmap-vue/blog/tagsweekly0.5https://diegoazh.github.io/gmap-vue/blog/tags/docusaurusweekly0.5https://diegoazh.github.io/gmap-vue/blog/tags/facebookweekly0.5https://diegoazh.github.io/gmap-vue/blog/tags/greetingsweekly0.5https://diegoazh.github.io/gmap-vue/blog/tags/helloweekly0.5https://diegoazh.github.io/gmap-vue/blog/tags/holaweekly0.5https://diegoazh.github.io/gmap-vue/blog/welcomeweekly0.5https://diegoazh.github.io/gmap-vue/docs/category/apiweekly0.5https://diegoazh.github.io/gmap-vue/docs/category/api-1weekly0.5https://diegoazh.github.io/gmap-vue/docs/category/basic-usageweekly0.5https://diegoazh.github.io/gmap-vue/docs/category/componentsweekly0.5https://diegoazh.github.io/gmap-vue/docs/category/components-1weekly0.5https://diegoazh.github.io/gmap-vue/docs/category/developersweekly0.5https://diegoazh.github.io/gmap-vue/docs/category/developers-1weekly0.5https://diegoazh.github.io/gmap-vue/docs/category/guideweekly0.5https://diegoazh.github.io/gmap-vue/docs/category/guide-1weekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/weekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/changelog/weekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/weekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/components/autocomplete-inputweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/components/circle-shapeweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/components/cluster-iconweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/components/drawing-managerweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/components/heatmap-layerweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/components/info-windowweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/components/kml-layerweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/components/map-layerweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/components/marker-iconweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/components/place-inputweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/components/polygon-shapeweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/components/polyline-shapeweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/components/rectangle-shapeweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/components/street-view-panoramaweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/mainweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/mixins/map-elementweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/mixins/mountableweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/utils/factories/map-elementweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/utils/factories/promise-lazyweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/utils/helpersweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/utils/initializer/google-maps-api-initializerweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/code/utils/mapped-props-by-map-elementweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/developers/weekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/developers/licenseweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/guide/weekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/guide/autocompleteweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/guide/cdnweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/guide/circleweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/guide/clusterweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/guide/drawing-managerweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/guide/extra-examplesweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/guide/heatmap-layerweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/guide/info-windowweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/guide/kml-layerweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/guide/mapweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/guide/map-element-factoryweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/guide/markerweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/guide/place-inputweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/guide/polygonweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/guide/polylineweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/guide/promise-lazy-factoryweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/guide/rectangleweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-2-version/guide/street-view-panoramaweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/weekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/api/weekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/api/components/weekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/api/components/autocompleteweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/api/components/mapweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/api/composablesweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/api/gmap-vue-pluginweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/api/typesweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/api/utilitiesweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/changelog/weekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/developers/weekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/developers/licenseweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/developers/test-the-pluginweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/examples/weekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/guide/weekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/guide/basic-usage/accessing-google-maps-apiweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/guide/basic-usage/dynamic-loadweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/guide/basic-usage/gmv-map-slotsweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/guide/basic-usage/lazy-loadingweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/guide/basic-usage/map-referenceweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/guide/basic-usage/nuxtweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/guide/basic-usage/plugin-component-builderweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/guide/basic-usage/region-and-languageweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/guide/components/autocompleteweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/guide/components/mapweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/guide/global-propertiesweekly0.5https://diegoazh.github.io/gmap-vue/docs/vue-3-version/guide/install-functionweekly0.5https://diegoazh.github.io/gmap-vue/weekly0.5 \ No newline at end of file