@nuxt/scripts 0.6.6 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/200.html +8 -8
- package/dist/client/404.html +8 -8
- package/dist/client/_nuxt/{aQeyjCqJ.js → C1IUq70_.js} +1 -1
- package/dist/client/_nuxt/{BKIFFtfV.js → CnUvXFHd.js} +1 -1
- package/dist/client/_nuxt/DOi3Eb0n.js +31 -0
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/e4092e18-9a58-41ab-947e-35e1f2082b75.json +1 -0
- package/dist/client/_nuxt/error-404.CHrXIISA.css +1 -0
- package/dist/client/_nuxt/error-500.CrsjMPPf.css +1 -0
- package/dist/client/_nuxt/{BKJqCZ0j.js → iQqcKxZm.js} +1 -1
- package/dist/client/index.html +8 -8
- package/dist/module.json +2 -2
- package/dist/module.mjs +10 -4
- package/dist/runtime/components/ScriptCrisp.vue +10 -7
- package/dist/runtime/components/ScriptGoogleAdsense.vue +7 -7
- package/dist/runtime/components/ScriptGoogleMaps.vue +236 -68
- package/dist/runtime/components/ScriptIntercom.vue +10 -7
- package/dist/runtime/components/ScriptLemonSqueezy.vue +1 -1
- package/dist/runtime/components/ScriptStripePricingTable.vue +6 -6
- package/dist/runtime/components/ScriptVimeoPlayer.vue +62 -40
- package/dist/runtime/components/ScriptYouTubePlayer.vue +9 -9
- package/dist/runtime/composables/useScript.d.ts +6 -1
- package/dist/runtime/composables/useScript.js +8 -8
- package/dist/runtime/composables/useScriptEventPage.d.ts +0 -3
- package/dist/runtime/registry/clarity.d.ts +1 -12
- package/dist/runtime/registry/cloudflare-web-analytics.d.ts +1 -3
- package/dist/runtime/registry/crisp.d.ts +1 -3
- package/dist/runtime/registry/fathom-analytics.d.ts +1 -3
- package/dist/runtime/registry/google-adsense.d.ts +1 -3
- package/dist/runtime/registry/google-analytics.d.ts +2 -10
- package/dist/runtime/registry/google-maps.d.ts +2 -4
- package/dist/runtime/registry/google-maps.js +1 -3
- package/dist/runtime/registry/google-tag-manager.d.ts +2 -10
- package/dist/runtime/registry/hotjar.d.ts +1 -3
- package/dist/runtime/registry/intercom.d.ts +1 -3
- package/dist/runtime/registry/lemon-squeezy.d.ts +1 -3
- package/dist/runtime/registry/matomo-analytics.d.ts +1 -3
- package/dist/runtime/registry/meta-pixel.d.ts +1 -3
- package/dist/runtime/registry/npm.d.ts +1 -3
- package/dist/runtime/registry/plausible-analytics.d.ts +1 -3
- package/dist/runtime/registry/segment.d.ts +1 -3
- package/dist/runtime/registry/stripe.d.ts +1 -3
- package/dist/runtime/registry/vimeo-player.d.ts +1 -3
- package/dist/runtime/registry/vimeo-player.js +1 -1
- package/dist/runtime/registry/x-pixel.d.ts +1 -3
- package/dist/runtime/registry/youtube-player.d.ts +1 -3
- package/dist/runtime/registry/youtube-player.js +1 -1
- package/dist/runtime/types.d.ts +3 -3
- package/dist/runtime/utils.d.ts +2 -4
- package/package.json +29 -23
- package/dist/client/_nuxt/DcF05ETD.js +0 -31
- package/dist/client/_nuxt/builds/meta/3dcaf2bf-82f1-460f-80a6-1412196a7a77.json +0 -1
- package/dist/client/_nuxt/error-404.B7Lh29wY.css +0 -1
- package/dist/client/_nuxt/error-500.B_VIyt60.css +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"id":"
|
|
1
|
+
{"id":"e4092e18-9a58-41ab-947e-35e1f2082b75","timestamp":1724318010522}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"id":"e4092e18-9a58-41ab-947e-35e1f2082b75","timestamp":1724318010522,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.spotlight[data-v-379fced0]{background:linear-gradient(45deg,#00dc82,#36e4da 50%,#0047e1);bottom:-30vh;filter:blur(20vh);height:40vh}.gradient-border[data-v-379fced0]{-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-radius:.5rem;position:relative}@media (prefers-color-scheme:light){.gradient-border[data-v-379fced0]{background-color:#ffffff4d}.gradient-border[data-v-379fced0]:before{background:linear-gradient(90deg,#e2e2e2,#e2e2e2 25%,#00dc82,#36e4da 75%,#0047e1)}}@media (prefers-color-scheme:dark){.gradient-border[data-v-379fced0]{background-color:#1414144d}.gradient-border[data-v-379fced0]:before{background:linear-gradient(90deg,#303030,#303030 25%,#00dc82,#36e4da 75%,#0047e1)}}.gradient-border[data-v-379fced0]:before{background-size:400% auto;border-radius:.5rem;bottom:0;content:"";left:0;-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask-composite:exclude;opacity:.5;padding:2px;position:absolute;right:0;top:0;transition:background-position .3s ease-in-out,opacity .2s ease-in-out;width:100%}.gradient-border[data-v-379fced0]:hover:before{background-position:-50% 0;opacity:1}.fixed[data-v-379fced0]{position:fixed}.left-0[data-v-379fced0]{left:0}.right-0[data-v-379fced0]{right:0}.z-10[data-v-379fced0]{z-index:10}.z-20[data-v-379fced0]{z-index:20}.grid[data-v-379fced0]{display:grid}.mb-16[data-v-379fced0]{margin-bottom:4rem}.mb-8[data-v-379fced0]{margin-bottom:2rem}.max-w-520px[data-v-379fced0]{max-width:520px}.min-h-screen[data-v-379fced0]{min-height:100vh}.w-full[data-v-379fced0]{width:100%}.flex[data-v-379fced0]{display:flex}.cursor-pointer[data-v-379fced0]{cursor:pointer}.place-content-center[data-v-379fced0]{place-content:center}.items-center[data-v-379fced0]{align-items:center}.justify-center[data-v-379fced0]{justify-content:center}.overflow-hidden[data-v-379fced0]{overflow:hidden}.bg-white[data-v-379fced0]{--un-bg-opacity:1;background-color:rgb(255 255 255/var(--un-bg-opacity))}.px-4[data-v-379fced0]{padding-left:1rem;padding-right:1rem}.px-8[data-v-379fced0]{padding-left:2rem;padding-right:2rem}.py-2[data-v-379fced0]{padding-bottom:.5rem;padding-top:.5rem}.text-center[data-v-379fced0]{text-align:center}.text-8xl[data-v-379fced0]{font-size:6rem;line-height:1}.text-xl[data-v-379fced0]{font-size:1.25rem;line-height:1.75rem}.text-black[data-v-379fced0]{--un-text-opacity:1;color:rgb(0 0 0/var(--un-text-opacity))}.font-light[data-v-379fced0]{font-weight:300}.font-medium[data-v-379fced0]{font-weight:500}.leading-tight[data-v-379fced0]{line-height:1.25}.font-sans[data-v-379fced0]{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.antialiased[data-v-379fced0]{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media (prefers-color-scheme:dark){.dark\:bg-black[data-v-379fced0]{--un-bg-opacity:1;background-color:rgb(0 0 0/var(--un-bg-opacity))}.dark\:text-white[data-v-379fced0]{--un-text-opacity:1;color:rgb(255 255 255/var(--un-text-opacity))}}@media (min-width:640px){.sm\:px-0[data-v-379fced0]{padding-left:0;padding-right:0}.sm\:px-6[data-v-379fced0]{padding-left:1.5rem;padding-right:1.5rem}.sm\:py-3[data-v-379fced0]{padding-bottom:.75rem;padding-top:.75rem}.sm\:text-4xl[data-v-379fced0]{font-size:2.25rem;line-height:2.5rem}.sm\:text-xl[data-v-379fced0]{font-size:1.25rem;line-height:1.75rem}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.spotlight[data-v-8b7b3844]{background:linear-gradient(45deg,#00dc82,#36e4da 50%,#0047e1);filter:blur(20vh)}.fixed[data-v-8b7b3844]{position:fixed}.-bottom-1\/2[data-v-8b7b3844]{bottom:-50%}.left-0[data-v-8b7b3844]{left:0}.right-0[data-v-8b7b3844]{right:0}.grid[data-v-8b7b3844]{display:grid}.mb-16[data-v-8b7b3844]{margin-bottom:4rem}.mb-8[data-v-8b7b3844]{margin-bottom:2rem}.h-1\/2[data-v-8b7b3844]{height:50%}.max-w-520px[data-v-8b7b3844]{max-width:520px}.min-h-screen[data-v-8b7b3844]{min-height:100vh}.place-content-center[data-v-8b7b3844]{place-content:center}.overflow-hidden[data-v-8b7b3844]{overflow:hidden}.bg-white[data-v-8b7b3844]{--un-bg-opacity:1;background-color:rgb(255 255 255/var(--un-bg-opacity))}.px-8[data-v-8b7b3844]{padding-left:2rem;padding-right:2rem}.text-center[data-v-8b7b3844]{text-align:center}.text-8xl[data-v-8b7b3844]{font-size:6rem;line-height:1}.text-xl[data-v-8b7b3844]{font-size:1.25rem;line-height:1.75rem}.text-black[data-v-8b7b3844]{--un-text-opacity:1;color:rgb(0 0 0/var(--un-text-opacity))}.font-light[data-v-8b7b3844]{font-weight:300}.font-medium[data-v-8b7b3844]{font-weight:500}.leading-tight[data-v-8b7b3844]{line-height:1.25}.font-sans[data-v-8b7b3844]{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.antialiased[data-v-8b7b3844]{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media (prefers-color-scheme:dark){.dark\:bg-black[data-v-8b7b3844]{--un-bg-opacity:1;background-color:rgb(0 0 0/var(--un-bg-opacity))}.dark\:text-white[data-v-8b7b3844]{--un-text-opacity:1;color:rgb(255 255 255/var(--un-text-opacity))}}@media (min-width:640px){.sm\:px-0[data-v-8b7b3844]{padding-left:0;padding-right:0}.sm\:text-4xl[data-v-8b7b3844]{font-size:2.25rem;line-height:2.5rem}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{i as o,r as u,g as f,h as d,j as v,k as l,l as i,m as h,n as m}from"./
|
|
1
|
+
import{i as o,r as u,g as f,h as d,j as v,k as l,l as i,m as h,n as m}from"./DOi3Eb0n.js";function U(t,a={}){const e=a.head||o();if(e)return e.ssr?e.push(t,a):p(e,t,a)}function p(t,a,e={}){const s=u(!1),n=u({});f(()=>{n.value=s.value?{}:h(a)});const r=t.push(n.value,e);return d(n,c=>{r.patch(c)}),m()&&(v(()=>{r.dispose()}),l(()=>{s.value=!0}),i(()=>{s.value=!1})),r}export{U as u};
|
package/dist/client/index.html
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!DOCTYPE html><html data-capo=""><head><meta charset="utf-8">
|
|
2
2
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
3
3
|
<link rel="stylesheet" href="/__nuxt-scripts/_nuxt/entry.FVeyw1Qn.css">
|
|
4
|
-
<link rel="modulepreload" as="script" crossorigin href="/__nuxt-scripts/_nuxt/
|
|
4
|
+
<link rel="modulepreload" as="script" crossorigin href="/__nuxt-scripts/_nuxt/DOi3Eb0n.js">
|
|
5
5
|
<link rel="prefetch" as="script" crossorigin href="/__nuxt-scripts/_nuxt/DXFkqnOI.js">
|
|
6
6
|
<link rel="prefetch" as="script" crossorigin href="/__nuxt-scripts/_nuxt/BigF1UXR.js">
|
|
7
7
|
<link rel="prefetch" as="script" crossorigin href="/__nuxt-scripts/_nuxt/CowR2XfX.js">
|
|
@@ -257,10 +257,10 @@
|
|
|
257
257
|
<link rel="prefetch" as="script" crossorigin href="/__nuxt-scripts/_nuxt/B3g-KkBK.js">
|
|
258
258
|
<link rel="prefetch" as="script" crossorigin href="/__nuxt-scripts/_nuxt/Bxkoe-BC.js">
|
|
259
259
|
<link rel="prefetch" as="script" crossorigin href="/__nuxt-scripts/_nuxt/Br6ll-O0.js">
|
|
260
|
-
<link rel="prefetch" as="style" href="/__nuxt-scripts/_nuxt/error-404.
|
|
261
|
-
<link rel="prefetch" as="script" crossorigin href="/__nuxt-scripts/_nuxt/
|
|
262
|
-
<link rel="prefetch" as="script" crossorigin href="/__nuxt-scripts/_nuxt/
|
|
263
|
-
<link rel="prefetch" as="style" href="/__nuxt-scripts/_nuxt/error-500.
|
|
264
|
-
<link rel="prefetch" as="script" crossorigin href="/__nuxt-scripts/_nuxt/
|
|
265
|
-
<script type="module" src="/__nuxt-scripts/_nuxt/
|
|
266
|
-
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-scripts",buildId:"
|
|
260
|
+
<link rel="prefetch" as="style" href="/__nuxt-scripts/_nuxt/error-404.CHrXIISA.css">
|
|
261
|
+
<link rel="prefetch" as="script" crossorigin href="/__nuxt-scripts/_nuxt/C1IUq70_.js">
|
|
262
|
+
<link rel="prefetch" as="script" crossorigin href="/__nuxt-scripts/_nuxt/iQqcKxZm.js">
|
|
263
|
+
<link rel="prefetch" as="style" href="/__nuxt-scripts/_nuxt/error-500.CrsjMPPf.css">
|
|
264
|
+
<link rel="prefetch" as="script" crossorigin href="/__nuxt-scripts/_nuxt/CnUvXFHd.js">
|
|
265
|
+
<script type="module" src="/__nuxt-scripts/_nuxt/DOi3Eb0n.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" id="__NUXT_DATA__" data-ssr="false">[{"serverRendered":1},false]</script>
|
|
266
|
+
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-scripts",buildId:"e4092e18-9a58-41ab-947e-35e1f2082b75",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -152,7 +152,7 @@ function NuxtScriptBundleTransformer(options) {
|
|
|
152
152
|
if (scriptSrcNode || src) {
|
|
153
153
|
src = src || (typeof scriptSrcNode?.value === "string" ? scriptSrcNode?.value : false);
|
|
154
154
|
if (src) {
|
|
155
|
-
let canBundle = options.defaultBundle;
|
|
155
|
+
let canBundle = !!options.defaultBundle;
|
|
156
156
|
if (node.arguments[1]?.type === "ObjectExpression") {
|
|
157
157
|
const scriptOptionsArg = node.arguments[1];
|
|
158
158
|
const bundleProperty = scriptOptionsArg.properties.find(
|
|
@@ -175,6 +175,13 @@ function NuxtScriptBundleTransformer(options) {
|
|
|
175
175
|
canBundle = true;
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
|
+
const scriptOptions = node.arguments[0].properties?.find(
|
|
179
|
+
(p) => p.key?.name === "scriptOptions"
|
|
180
|
+
);
|
|
181
|
+
const bundleOption = scriptOptions?.value.properties?.find((prop) => {
|
|
182
|
+
return prop.type === "Property" && prop.key?.name === "bundle" && prop.value.type === "Literal";
|
|
183
|
+
});
|
|
184
|
+
canBundle = bundleOption ? bundleOption.value.value : canBundle;
|
|
178
185
|
if (canBundle) {
|
|
179
186
|
const newSrc = options.resolveScript(src);
|
|
180
187
|
if (src === newSrc) {
|
|
@@ -502,9 +509,8 @@ const module = defineNuxtModule({
|
|
|
502
509
|
const unheadPath = await resolvePath("@unhead/vue").catch(() => void 0);
|
|
503
510
|
if (unheadPath) {
|
|
504
511
|
const { version: unheadVersion } = await readPackageJSON(join(unheadPath, "package.json"));
|
|
505
|
-
if (!unheadVersion || lt(unheadVersion, "1.
|
|
506
|
-
logger.
|
|
507
|
-
return;
|
|
512
|
+
if (!unheadVersion || lt(unheadVersion, "1.10.0")) {
|
|
513
|
+
logger.error(`Nuxt Scripts requires Unhead >= 1.10.0, you are using v${unheadVersion}. Please run \`nuxi upgrade --clean\` to upgrade...`);
|
|
508
514
|
}
|
|
509
515
|
}
|
|
510
516
|
nuxt.options.alias["#nuxt-scripts-validator"] = resolve(`./runtime/validation/${nuxt.options.dev || nuxt.options._prepare ? "valibot" : "mock"}`);
|
|
@@ -40,9 +40,12 @@ const crisp = useScriptCrisp({
|
|
|
40
40
|
trigger,
|
|
41
41
|
},
|
|
42
42
|
})
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
const { onLoaded, status } = crisp
|
|
44
|
+
if (props.trigger === 'click') {
|
|
45
|
+
onLoaded((instance) => {
|
|
46
|
+
instance.do('chat:open')
|
|
47
|
+
})
|
|
48
|
+
}
|
|
46
49
|
|
|
47
50
|
defineExpose({
|
|
48
51
|
crisp,
|
|
@@ -50,7 +53,7 @@ defineExpose({
|
|
|
50
53
|
|
|
51
54
|
let observer: MutationObserver
|
|
52
55
|
onMounted(() => {
|
|
53
|
-
watch(
|
|
56
|
+
watch(status, (status) => {
|
|
54
57
|
if (status === 'loaded') {
|
|
55
58
|
observer = new MutationObserver(() => {
|
|
56
59
|
if (document.getElementById('crisp-chatbox')) {
|
|
@@ -77,8 +80,8 @@ onBeforeUnmount(() => {
|
|
|
77
80
|
:style="{ display: isReady ? 'none' : 'block' }"
|
|
78
81
|
>
|
|
79
82
|
<slot :ready="isReady" />
|
|
80
|
-
<slot v-if="
|
|
81
|
-
<slot v-else-if="
|
|
82
|
-
<slot v-else-if="
|
|
83
|
+
<slot v-if="status === 'awaitingLoad'" name="awaitingLoad" />
|
|
84
|
+
<slot v-else-if="status === 'loading' || !isReady" name="loading" />
|
|
85
|
+
<slot v-else-if="status === 'error'" name="error" />
|
|
83
86
|
</div>
|
|
84
87
|
</template>
|
|
@@ -34,17 +34,17 @@ const instance = useScriptGoogleAdsense({
|
|
|
34
34
|
},
|
|
35
35
|
})
|
|
36
36
|
|
|
37
|
-
const {
|
|
37
|
+
const { status } = instance
|
|
38
38
|
|
|
39
39
|
onMounted(() => {
|
|
40
40
|
callOnce(() => {
|
|
41
41
|
(window.adsbygoogle = window.adsbygoogle || []).push({})
|
|
42
42
|
})
|
|
43
|
-
watch(
|
|
44
|
-
if (
|
|
43
|
+
watch(status, (val) => {
|
|
44
|
+
if (val === 'loaded') {
|
|
45
45
|
emits('ready', instance)
|
|
46
46
|
}
|
|
47
|
-
else if (
|
|
47
|
+
else if (val === 'error') {
|
|
48
48
|
emits('error')
|
|
49
49
|
}
|
|
50
50
|
})
|
|
@@ -62,8 +62,8 @@ onMounted(() => {
|
|
|
62
62
|
:data-full-width-responsive="dataFullWidthResponsive"
|
|
63
63
|
v-bind="{ ...$attrs }"
|
|
64
64
|
>
|
|
65
|
-
<slot v-if="
|
|
66
|
-
<slot v-else-if="
|
|
67
|
-
<slot v-else-if="
|
|
65
|
+
<slot v-if="status === 'awaitingLoad'" name="awaitingLoad" />
|
|
66
|
+
<slot v-else-if="status === 'loading'" name="loading" />
|
|
67
|
+
<slot v-else-if="status === 'error'" name="error" />
|
|
68
68
|
</ins>
|
|
69
69
|
</template>
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
/// <reference types="google.maps" />
|
|
3
|
-
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
|
3
|
+
import { computed, onBeforeUnmount, onMounted, ref, watch, toRaw } from 'vue'
|
|
4
4
|
import type { HTMLAttributes, ImgHTMLAttributes, Ref, ReservedProps } from 'vue'
|
|
5
5
|
import { withQuery } from 'ufo'
|
|
6
6
|
import type { QueryObject } from 'ufo'
|
|
7
7
|
import { defu } from 'defu'
|
|
8
|
+
import { hash } from 'ohash'
|
|
8
9
|
import type { ElementScriptTrigger } from '../types'
|
|
9
10
|
import { scriptRuntimeConfig } from '../utils'
|
|
10
11
|
import { useScriptTriggerElement } from '../composables/useScriptTriggerElement'
|
|
@@ -44,15 +45,19 @@ const props = withDefaults(defineProps<{
|
|
|
44
45
|
/**
|
|
45
46
|
* Defines the Google Maps API key. Must have access to the Static Maps API as well.
|
|
46
47
|
*/
|
|
47
|
-
apiKey
|
|
48
|
+
apiKey?: string
|
|
48
49
|
/**
|
|
49
|
-
*
|
|
50
|
+
* A latitude / longitude of where to focus the map.
|
|
50
51
|
*/
|
|
51
|
-
|
|
52
|
+
center?: google.maps.LatLng | google.maps.LatLngLiteral | `${string},${string}`
|
|
53
|
+
/**
|
|
54
|
+
* Should a marker be displayed on the map where the centre is.
|
|
55
|
+
*/
|
|
56
|
+
centerMarker?: boolean
|
|
52
57
|
/**
|
|
53
58
|
* Options for the map.
|
|
54
59
|
*/
|
|
55
|
-
|
|
60
|
+
mapOptions?: google.maps.MapOptions
|
|
56
61
|
/**
|
|
57
62
|
* Defines the width of the map.
|
|
58
63
|
*/
|
|
@@ -75,30 +80,39 @@ const props = withDefaults(defineProps<{
|
|
|
75
80
|
* Customize the root element attributes.
|
|
76
81
|
*/
|
|
77
82
|
rootAttrs?: HTMLAttributes & ReservedProps & Record<string, unknown>
|
|
83
|
+
/**
|
|
84
|
+
* Extra Markers to add to the map.
|
|
85
|
+
*/
|
|
86
|
+
markers?: (`${string},${string}` | google.maps.marker.AdvancedMarkerElementOptions)[]
|
|
78
87
|
}>(), {
|
|
79
88
|
// @ts-expect-error untyped
|
|
80
89
|
trigger: ['mouseenter', 'mouseover', 'mousedown'],
|
|
81
|
-
width:
|
|
90
|
+
width: 640,
|
|
82
91
|
height: 400,
|
|
92
|
+
centerMarker: true,
|
|
83
93
|
})
|
|
84
94
|
|
|
85
95
|
const emits = defineEmits<{
|
|
86
96
|
// our emit
|
|
87
|
-
ready: [e:
|
|
97
|
+
ready: [e: typeof googleMaps]
|
|
88
98
|
error: []
|
|
89
99
|
}>()
|
|
90
100
|
|
|
91
101
|
const apiKey = props.apiKey || scriptRuntimeConfig('googleMaps')?.apiKey
|
|
92
102
|
|
|
93
|
-
|
|
103
|
+
const mapsApi = ref<typeof google.maps | undefined>()
|
|
104
|
+
|
|
105
|
+
if (import.meta.dev && !apiKey)
|
|
94
106
|
throw new Error('GoogleMaps requires an API key. Please provide `apiKey` on the <ScriptGoogleMaps> or globally via `runtimeConfig.public.scripts.googleMaps.apiKey`.')
|
|
95
|
-
|
|
96
|
-
|
|
107
|
+
|
|
108
|
+
// TODO allow a null center may need to be resolved via an API function
|
|
97
109
|
|
|
98
110
|
const rootEl = ref<HTMLElement>()
|
|
99
111
|
const mapEl = ref<HTMLElement>()
|
|
100
112
|
|
|
101
|
-
const
|
|
113
|
+
const centerOverride = ref()
|
|
114
|
+
|
|
115
|
+
const { load, status, onLoaded } = useScriptGoogleMaps({
|
|
102
116
|
apiKey: props.apiKey,
|
|
103
117
|
scriptOptions: {
|
|
104
118
|
trigger: useScriptTriggerElement({ trigger: props.trigger, el: rootEl }),
|
|
@@ -106,16 +120,70 @@ const { $script } = useScriptGoogleMaps({
|
|
|
106
120
|
})
|
|
107
121
|
|
|
108
122
|
const options = computed(() => {
|
|
109
|
-
return defu(props.
|
|
123
|
+
return defu({ center: centerOverride.value }, props.mapOptions, {
|
|
124
|
+
center: props.center,
|
|
110
125
|
zoom: 15,
|
|
111
126
|
mapId: 'map',
|
|
112
127
|
})
|
|
113
128
|
})
|
|
114
129
|
const ready = ref(false)
|
|
115
130
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
131
|
+
const map: Ref<google.maps.Map | undefined> = ref()
|
|
132
|
+
const mapMarkers: Ref<Map<string, Promise<google.maps.marker.AdvancedMarkerElement>>> = ref(new Map())
|
|
133
|
+
|
|
134
|
+
function isLocationQuery(s: string | any) {
|
|
135
|
+
return typeof s === 'string' && (s.split(',').length > 2 || s.includes('+'))
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async function createAdvancedMapMarker(_options: google.maps.marker.AdvancedMarkerElementOptions | `${string},${string}`) {
|
|
139
|
+
const key = hash(_options)
|
|
140
|
+
if (mapMarkers.value.has(key))
|
|
141
|
+
return mapMarkers.value.get(key)
|
|
142
|
+
// eslint-disable-next-line no-async-promise-executor
|
|
143
|
+
const p = new Promise<google.maps.marker.AdvancedMarkerElement>(async (resolve) => {
|
|
144
|
+
const lib = await importLibrary('marker')
|
|
145
|
+
const options = typeof _options === 'string'
|
|
146
|
+
? {
|
|
147
|
+
position: {
|
|
148
|
+
lat: Number.parseFloat(_options.split(',')[0] || '0'),
|
|
149
|
+
lng: Number.parseFloat(_options.split(',')[1] || '0'),
|
|
150
|
+
},
|
|
151
|
+
}
|
|
152
|
+
: _options
|
|
153
|
+
const mapMarkerOptions = defu(toRaw(options), {
|
|
154
|
+
map: toRaw(map.value!),
|
|
155
|
+
// @ts-expect-error unified API for maps and markers
|
|
156
|
+
position: options.location,
|
|
157
|
+
})
|
|
158
|
+
resolve(new lib.AdvancedMarkerElement(mapMarkerOptions))
|
|
159
|
+
})
|
|
160
|
+
mapMarkers.value.set(key, p)
|
|
161
|
+
return p
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const queryToLatLngCache = new Map<string, google.maps.LatLng>()
|
|
165
|
+
|
|
166
|
+
async function resolveQueryToLatLang(query: string) {
|
|
167
|
+
if (query && typeof query === 'object')
|
|
168
|
+
return Promise.resolve(query)
|
|
169
|
+
if (queryToLatLngCache.has(query)) {
|
|
170
|
+
return Promise.resolve(queryToLatLngCache.get(query))
|
|
171
|
+
}
|
|
172
|
+
// only if the query is a string we need to do a lookup
|
|
173
|
+
// eslint-disable-next-line no-async-promise-executor
|
|
174
|
+
return new Promise<google.maps.LatLng>(async (resolve, reject) => {
|
|
175
|
+
if (!mapsApi.value) {
|
|
176
|
+
await load()
|
|
177
|
+
// await new promise, watch until mapsApi is set
|
|
178
|
+
await new Promise<void>((resolve) => {
|
|
179
|
+
const _ = watch(mapsApi, () => {
|
|
180
|
+
_()
|
|
181
|
+
resolve()
|
|
182
|
+
})
|
|
183
|
+
})
|
|
184
|
+
}
|
|
185
|
+
const placesService = new mapsApi.value!.places.PlacesService(map.value!)
|
|
186
|
+
placesService.findPlaceFromQuery({
|
|
119
187
|
query,
|
|
120
188
|
fields: ['name', 'geometry'],
|
|
121
189
|
}, (results, status) => {
|
|
@@ -123,60 +191,135 @@ function queryToLocation(service: google.maps.places.PlacesService, query: strin
|
|
|
123
191
|
return resolve(results[0].geometry.location)
|
|
124
192
|
return reject(new Error(`No location found for ${query}`))
|
|
125
193
|
})
|
|
194
|
+
}).then((res) => {
|
|
195
|
+
queryToLatLngCache.set(query, res)
|
|
196
|
+
return res
|
|
126
197
|
})
|
|
127
198
|
}
|
|
128
199
|
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
200
|
+
const libraries = new Map<string, any>()
|
|
201
|
+
|
|
202
|
+
function importLibrary(key: 'marker'): Promise<google.maps.MarkerLibrary>
|
|
203
|
+
function importLibrary(key: 'places'): Promise<google.maps.PlacesLibrary>
|
|
204
|
+
function importLibrary(key: 'geometry'): Promise<google.maps.GeometryLibrary>
|
|
205
|
+
function importLibrary(key: 'drawing'): Promise<google.maps.DrawingLibrary>
|
|
206
|
+
function importLibrary(key: 'visualization'): Promise<google.maps.VisualizationLibrary>
|
|
207
|
+
function importLibrary(key: string): Promise<any>
|
|
208
|
+
function importLibrary<T>(key: string): Promise<T> {
|
|
209
|
+
if (libraries.has(key))
|
|
210
|
+
return libraries.get(key)
|
|
211
|
+
const p = mapsApi.value?.importLibrary(key) || new Promise((resolve) => {
|
|
212
|
+
const stop = watch(mapsApi, (api) => {
|
|
213
|
+
if (api) {
|
|
214
|
+
const p = api.importLibrary(key)
|
|
215
|
+
resolve(p)
|
|
216
|
+
stop()
|
|
217
|
+
}
|
|
218
|
+
}, { immediate: true })
|
|
219
|
+
})
|
|
220
|
+
libraries.set(key, p)
|
|
221
|
+
return p as any as Promise<T>
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const googleMaps = {
|
|
225
|
+
googleMaps: mapsApi,
|
|
132
226
|
map,
|
|
133
|
-
|
|
134
|
-
|
|
227
|
+
createAdvancedMapMarker,
|
|
228
|
+
resolveQueryToLatLang,
|
|
229
|
+
importLibrary,
|
|
230
|
+
} as const
|
|
231
|
+
|
|
232
|
+
defineExpose(googleMaps)
|
|
135
233
|
|
|
136
234
|
onMounted(() => {
|
|
137
235
|
watch(ready, (v) => {
|
|
138
236
|
if (v) {
|
|
139
|
-
emits('ready',
|
|
237
|
+
emits('ready', googleMaps)
|
|
140
238
|
}
|
|
141
239
|
})
|
|
142
|
-
watch(
|
|
143
|
-
if (
|
|
240
|
+
watch(status, (v) => {
|
|
241
|
+
if (v === 'error') {
|
|
144
242
|
emits('error')
|
|
145
243
|
}
|
|
146
244
|
})
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
markers.value.push(new marker.AdvancedMarkerElement({
|
|
169
|
-
map: _map,
|
|
170
|
-
position: location,
|
|
171
|
-
}))
|
|
172
|
-
ready.value = true
|
|
245
|
+
watch(options, () => {
|
|
246
|
+
map.value?.setOptions(options.value)
|
|
247
|
+
})
|
|
248
|
+
watch([() => props.markers, map], async () => {
|
|
249
|
+
if (!map.value) {
|
|
250
|
+
return
|
|
251
|
+
}
|
|
252
|
+
// mapMarkers is a map where we hash the next array entry as the map key
|
|
253
|
+
// we need to do a diff to see what we remove or add
|
|
254
|
+
const nextMap = new Map((props.markers || []).map(m => [hash(m), m]))
|
|
255
|
+
// compare idsToMatch in nextMap, if we're missing an id, we need to remove it
|
|
256
|
+
const toRemove = new Set([
|
|
257
|
+
...mapMarkers.value.keys(),
|
|
258
|
+
].filter(k => !nextMap.has(k)))
|
|
259
|
+
// compare to existing
|
|
260
|
+
const toAdd = new Set([...nextMap.keys()].filter(k => !mapMarkers.value.has(k)))
|
|
261
|
+
// do a diff of next and prev
|
|
262
|
+
const centerHash = hash({ position: options.value.center })
|
|
263
|
+
for (const key of toRemove) {
|
|
264
|
+
if (key === centerHash) {
|
|
265
|
+
continue
|
|
173
266
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
267
|
+
const marker = await mapMarkers.value.get(key)
|
|
268
|
+
if (marker) {
|
|
269
|
+
// @ts-expect-error broken type
|
|
270
|
+
marker.setMap(null)
|
|
271
|
+
// make sure it gets removed from map
|
|
272
|
+
mapMarkers.value.delete(key)
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
for (const k of toAdd) {
|
|
276
|
+
// @ts-expect-error broken
|
|
277
|
+
createAdvancedMapMarker(nextMap.get(k))
|
|
278
|
+
}
|
|
279
|
+
}, {
|
|
280
|
+
immediate: true,
|
|
281
|
+
deep: true,
|
|
282
|
+
})
|
|
283
|
+
watch([() => options.value.center, ready, map], async (next, prev) => {
|
|
284
|
+
if (!map.value) {
|
|
285
|
+
return
|
|
286
|
+
}
|
|
287
|
+
let center = toRaw(next[0])
|
|
288
|
+
if (center) {
|
|
289
|
+
if (isLocationQuery(center) && ready.value) {
|
|
290
|
+
// need to resolve center from query
|
|
291
|
+
center = await resolveQueryToLatLang(center as string)
|
|
292
|
+
}
|
|
293
|
+
map.value!.setCenter(center as google.maps.LatLng)
|
|
294
|
+
if (props.centerMarker) {
|
|
295
|
+
if (prev[0]) {
|
|
296
|
+
const prevCenterHash = hash({ position: prev[0] })
|
|
297
|
+
// @ts-expect-error broken upstream type
|
|
298
|
+
mapMarkers.value.get(prevCenterHash)?.setMap(null)
|
|
299
|
+
mapMarkers.value.delete(prevCenterHash)
|
|
300
|
+
}
|
|
301
|
+
createAdvancedMapMarker({ position: center })
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}, {
|
|
305
|
+
immediate: true,
|
|
306
|
+
})
|
|
307
|
+
onLoaded(async (instance) => {
|
|
308
|
+
mapsApi.value = await instance.maps as any as typeof google.maps // some weird type issue here
|
|
309
|
+
// may need to transform the center before we can init the map
|
|
310
|
+
const center = options.value.center as string
|
|
311
|
+
const _options: google.maps.MapOptions = {
|
|
312
|
+
...options.value,
|
|
313
|
+
// @ts-expect-error broken
|
|
314
|
+
center: !center || isLocationQuery(center) ? undefined : center,
|
|
315
|
+
}
|
|
316
|
+
map.value = new mapsApi.value!.Map(mapEl.value!, _options)
|
|
317
|
+
if (center && isLocationQuery(center)) {
|
|
318
|
+
// need to resolve center
|
|
319
|
+
centerOverride.value = await resolveQueryToLatLang(center)
|
|
320
|
+
map.value?.setCenter(centerOverride.value)
|
|
321
|
+
}
|
|
322
|
+
ready.value = true
|
|
180
323
|
})
|
|
181
324
|
})
|
|
182
325
|
|
|
@@ -192,15 +335,34 @@ if (import.meta.server) {
|
|
|
192
335
|
}
|
|
193
336
|
|
|
194
337
|
const placeholder = computed(() => {
|
|
338
|
+
let center = options.value.center
|
|
339
|
+
if (center && typeof center === 'object') {
|
|
340
|
+
center = `${center.lat},${center.lng}`
|
|
341
|
+
}
|
|
342
|
+
// @ts-expect-error lazy type
|
|
195
343
|
const placeholderOptions: PlaceholderOptions = defu(props.placeholderOptions, {
|
|
196
344
|
// only map option values
|
|
197
345
|
zoom: options.value.zoom,
|
|
198
|
-
center
|
|
346
|
+
center,
|
|
199
347
|
}, {
|
|
200
348
|
size: `${props.width}x${props.height}`,
|
|
201
349
|
key: apiKey,
|
|
202
350
|
scale: 2, // we assume a high DPI to avoid hydration issues
|
|
203
|
-
markers:
|
|
351
|
+
markers: [
|
|
352
|
+
...(props.markers || []),
|
|
353
|
+
center,
|
|
354
|
+
]
|
|
355
|
+
.filter(Boolean)
|
|
356
|
+
.map((m) => {
|
|
357
|
+
if (typeof m === 'object' && m.location) {
|
|
358
|
+
m = m.location
|
|
359
|
+
}
|
|
360
|
+
if (typeof m === 'object' && m.lat) {
|
|
361
|
+
return `${m.lat},${m.lng}`
|
|
362
|
+
}
|
|
363
|
+
return m
|
|
364
|
+
})
|
|
365
|
+
.join('|'),
|
|
204
366
|
})
|
|
205
367
|
return withQuery('https://maps.googleapis.com/maps/api/staticmap', placeholderOptions as QueryObject)
|
|
206
368
|
})
|
|
@@ -208,7 +370,7 @@ const placeholder = computed(() => {
|
|
|
208
370
|
const placeholderAttrs = computed(() => {
|
|
209
371
|
return defu(props.placeholderAttrs, {
|
|
210
372
|
src: placeholder.value,
|
|
211
|
-
alt:
|
|
373
|
+
alt: 'Google Maps Static Map',
|
|
212
374
|
loading: props.aboveTheFold ? 'eager' : 'lazy',
|
|
213
375
|
style: {
|
|
214
376
|
cursor: 'pointer',
|
|
@@ -221,10 +383,10 @@ const placeholderAttrs = computed(() => {
|
|
|
221
383
|
|
|
222
384
|
const rootAttrs = computed(() => {
|
|
223
385
|
return defu(props.rootAttrs, {
|
|
224
|
-
'aria-busy':
|
|
225
|
-
'aria-label':
|
|
386
|
+
'aria-busy': status.value === 'loading',
|
|
387
|
+
'aria-label': status.value === 'awaitingLoad'
|
|
226
388
|
? 'Google Maps Static Map'
|
|
227
|
-
:
|
|
389
|
+
: status.value === 'loading'
|
|
228
390
|
? 'Google Maps Map Embed Loading'
|
|
229
391
|
: 'Google Maps Embed',
|
|
230
392
|
'aria-live': 'polite',
|
|
@@ -242,9 +404,15 @@ const rootAttrs = computed(() => {
|
|
|
242
404
|
|
|
243
405
|
const ScriptLoadingIndicator = resolveComponent('ScriptLoadingIndicator')
|
|
244
406
|
|
|
245
|
-
onBeforeUnmount(() => {
|
|
246
|
-
|
|
247
|
-
|
|
407
|
+
onBeforeUnmount(async () => {
|
|
408
|
+
await Promise.all([...mapMarkers.value.entries()].map(async (_marker) => {
|
|
409
|
+
const marker = await _marker
|
|
410
|
+
if (marker) {
|
|
411
|
+
// @ts-expect-error broken type
|
|
412
|
+
marker.setMap(null)
|
|
413
|
+
}
|
|
414
|
+
}))
|
|
415
|
+
mapMarkers.value.clear()
|
|
248
416
|
map.value?.unbindAll()
|
|
249
417
|
map.value = undefined
|
|
250
418
|
mapEl.value?.firstChild?.remove()
|
|
@@ -253,15 +421,15 @@ onBeforeUnmount(() => {
|
|
|
253
421
|
|
|
254
422
|
<template>
|
|
255
423
|
<div ref="rootEl" v-bind="rootAttrs">
|
|
256
|
-
<div v-show="ready" ref="mapEl"
|
|
424
|
+
<div v-show="ready" ref="mapEl" :style="{ width: '100%', height: '100%', maxWidth: '100%' }" />
|
|
257
425
|
<slot v-if="!ready" :placeholder="placeholder" name="placeholder">
|
|
258
426
|
<img v-bind="placeholderAttrs">
|
|
259
427
|
</slot>
|
|
260
|
-
<slot v-if="
|
|
428
|
+
<slot v-if="status !== 'awaitingLoad' && !ready" name="loading">
|
|
261
429
|
<ScriptLoadingIndicator color="black" />
|
|
262
430
|
</slot>
|
|
263
|
-
<slot v-if="
|
|
264
|
-
<slot v-else-if="
|
|
431
|
+
<slot v-if="status === 'awaitingLoad'" name="awaitingLoad" />
|
|
432
|
+
<slot v-else-if="status === 'error'" name="error" />
|
|
265
433
|
<slot />
|
|
266
434
|
</div>
|
|
267
435
|
</template>
|
|
@@ -46,9 +46,12 @@ const intercom = useScriptIntercom({
|
|
|
46
46
|
trigger,
|
|
47
47
|
},
|
|
48
48
|
})
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
const { status, onLoaded } = intercom
|
|
50
|
+
if (props.trigger === 'click') {
|
|
51
|
+
onLoaded((instance) => {
|
|
52
|
+
instance.Intercom('show')
|
|
53
|
+
})
|
|
54
|
+
}
|
|
52
55
|
|
|
53
56
|
defineExpose({
|
|
54
57
|
intercom,
|
|
@@ -56,7 +59,7 @@ defineExpose({
|
|
|
56
59
|
|
|
57
60
|
let observer: MutationObserver
|
|
58
61
|
onMounted(() => {
|
|
59
|
-
watch(
|
|
62
|
+
watch(status, (status) => {
|
|
60
63
|
if (status === 'loading') {
|
|
61
64
|
observer = new MutationObserver(() => {
|
|
62
65
|
if (document.getElementById('intercom-frame')) {
|
|
@@ -86,8 +89,8 @@ onBeforeUnmount(() => {
|
|
|
86
89
|
}"
|
|
87
90
|
>
|
|
88
91
|
<slot :ready="isReady" />
|
|
89
|
-
<slot v-if="
|
|
90
|
-
<slot v-else-if="
|
|
91
|
-
<slot v-else-if="
|
|
92
|
+
<slot v-if="status === 'awaitingLoad'" name="awaitingLoad" />
|
|
93
|
+
<slot v-else-if="status === 'loading' || !isReady" name="loading" />
|
|
94
|
+
<slot v-else-if="status === 'error'" name="error" />
|
|
92
95
|
</div>
|
|
93
96
|
</template>
|
|
@@ -26,7 +26,7 @@ onMounted(() => {
|
|
|
26
26
|
rootEl.value?.querySelectorAll('a[href]').forEach((a) => {
|
|
27
27
|
a.classList.add('lemonsqueezy-button')
|
|
28
28
|
})
|
|
29
|
-
instance
|
|
29
|
+
instance.onLoaded(({ Setup, Refresh }) => {
|
|
30
30
|
Setup({
|
|
31
31
|
eventHandler(event) {
|
|
32
32
|
emits('lemonSqueezyEvent', event)
|