@nuxt/scripts 0.7.1 → 0.7.2

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.
Files changed (36) hide show
  1. package/README.md +73 -73
  2. package/dist/client/200.html +9 -9
  3. package/dist/client/404.html +9 -9
  4. package/dist/client/_nuxt/{C1IUq70_.js → B7a7KwY0.js} +1 -1
  5. package/dist/client/_nuxt/{DOi3Eb0n.js → BYm2jJpo.js} +11 -11
  6. package/dist/client/_nuxt/{iQqcKxZm.js → CEoS15Fi.js} +1 -1
  7. package/dist/client/_nuxt/{CnUvXFHd.js → Nd9uLa0s.js} +1 -1
  8. package/dist/client/_nuxt/builds/latest.json +1 -1
  9. package/dist/client/_nuxt/builds/meta/0bada317-9aed-4ca5-ae27-fa6f72950e87.json +1 -0
  10. package/dist/client/_nuxt/{entry.FVeyw1Qn.css → entry.BAZUAl3s.css} +1 -1
  11. package/dist/client/_nuxt/error-404.ChzstOPh.css +1 -0
  12. package/dist/client/_nuxt/error-500.BaOmLlKq.css +1 -0
  13. package/dist/client/index.html +9 -9
  14. package/dist/module.d.mts +2 -2
  15. package/dist/module.d.ts +2 -2
  16. package/dist/module.json +1 -1
  17. package/dist/module.mjs +2 -0
  18. package/dist/runtime/components/ScriptCarbonAds.vue +78 -71
  19. package/dist/runtime/components/ScriptCrisp.vue +94 -87
  20. package/dist/runtime/components/ScriptGoogleAdsense.vue +75 -69
  21. package/dist/runtime/components/ScriptGoogleMaps.vue +457 -435
  22. package/dist/runtime/components/ScriptIntercom.vue +103 -96
  23. package/dist/runtime/components/ScriptLemonSqueezy.vue +52 -45
  24. package/dist/runtime/components/ScriptLoadingIndicator.vue +22 -22
  25. package/dist/runtime/components/ScriptStripePricingTable.vue +75 -68
  26. package/dist/runtime/components/ScriptVimeoPlayer.vue +281 -280
  27. package/dist/runtime/components/ScriptYouTubePlayer.vue +174 -171
  28. package/dist/runtime/composables/useScript.js +25 -7
  29. package/dist/runtime/composables/useScriptTriggerElement.d.ts +3 -1
  30. package/dist/runtime/composables/useScriptTriggerElement.js +46 -19
  31. package/dist/runtime/registry/google-adsense.js +11 -14
  32. package/dist/runtime/types.js +1 -1
  33. package/package.json +29 -28
  34. package/dist/client/_nuxt/builds/meta/e4092e18-9a58-41ab-947e-35e1f2082b75.json +0 -1
  35. package/dist/client/_nuxt/error-404.CHrXIISA.css +0 -1
  36. package/dist/client/_nuxt/error-500.CrsjMPPf.css +0 -1
@@ -1,171 +1,174 @@
1
- <script setup lang="ts">
2
- /// <reference types="youtube" />
3
- import { computed, onMounted, ref, watch } from 'vue'
4
- import type { HTMLAttributes, ImgHTMLAttributes, Ref } from 'vue'
5
- import { defu } from 'defu'
6
- import type { ElementScriptTrigger } from '../types'
7
- import { useScriptTriggerElement } from '../composables/useScriptTriggerElement'
8
- import { useScriptYouTubePlayer } from '../registry/youtube-player'
9
- import { useHead } from '#imports'
10
-
11
- const props = withDefaults(defineProps<{
12
- placeholderAttrs?: ImgHTMLAttributes
13
- rootAttrs?: HTMLAttributes
14
- aboveTheFold?: boolean
15
- trigger?: ElementScriptTrigger
16
- videoId: string
17
- playerVars?: YT.PlayerVars
18
- width?: number
19
- height?: number
20
- }>(), {
21
- trigger: 'mousedown',
22
- // @ts-expect-error untyped
23
- playerVars: { autoplay: 0, playsinline: 1 },
24
- width: 640,
25
- height: 480,
26
- })
27
-
28
- const emits = defineEmits<{
29
- 'ready': [e: YT.PlayerEvent]
30
- 'state-change': [e: YT.OnStateChangeEvent, target: YT.Player]
31
- 'playback-quality-change': [e: YT.OnPlaybackQualityChangeEvent, target: YT.Player]
32
- 'playback-rate-change': [e: YT.OnPlaybackRateChangeEvent, target: YT.Player]
33
- 'error': [e: YT.OnErrorEvent, target: YT.Player]
34
- }>()
35
- const events: (keyof YT.Events)[] = [
36
- 'onReady',
37
- 'onStateChange',
38
- 'onPlaybackQualityChange',
39
- 'onPlaybackRateChange',
40
- 'onError',
41
- 'onApiChange',
42
- ]
43
- const rootEl = ref()
44
- const youtubeEl = ref()
45
- const ready = ref(false)
46
- const trigger = useScriptTriggerElement({ trigger: props.trigger, el: rootEl })
47
- const { onLoaded, status } = useScriptYouTubePlayer({
48
- scriptOptions: {
49
- trigger,
50
- },
51
- })
52
-
53
- const player: Ref<YT.Player | undefined> = ref()
54
- let clickTriggered = false
55
- if (props.trigger === 'mousedown') {
56
- trigger.then(() => {
57
- clickTriggered = true
58
- })
59
- }
60
- onMounted(() => {
61
- onLoaded(async (instance) => {
62
- const YouTube: typeof YT & { ready: (fn: () => void) => void } = await instance.YT
63
- await new Promise<void>((resolve) => {
64
- if (typeof YT.Player === 'undefined')
65
- YouTube.ready(resolve)
66
- else
67
- resolve()
68
- })
69
- player.value = new YT.Player(youtubeEl.value, {
70
- ...props,
71
- events: Object.fromEntries(events.map(event => [event, (e: any) => {
72
- const emitEventName = event.replace(/([A-Z])/g, '-$1').replace('on-', '').toLowerCase()
73
- // @ts-expect-error untyped
74
- emits(emitEventName, e)
75
- if (event === 'onReady') {
76
- ready.value = true
77
- if (clickTriggered) {
78
- player.value?.playVideo()
79
- clickTriggered = false
80
- }
81
- watch(() => props.videoId, () => {
82
- player.value?.loadVideoById(props.videoId)
83
- })
84
- }
85
- }])),
86
- })
87
- })
88
- watch(status, (status) => {
89
- if (status === 'error') {
90
- // @ts-expect-error untyped
91
- emits('error')
92
- }
93
- })
94
- })
95
-
96
- defineExpose({
97
- player,
98
- })
99
-
100
- const rootAttrs = computed(() => {
101
- return defu(props.rootAttrs, {
102
- 'aria-busy': status.value === 'loading',
103
- 'aria-label': status.value === 'awaitingLoad'
104
- ? 'YouTube Player - Placeholder'
105
- : status.value === 'loading'
106
- ? 'YouTube Player - Loading'
107
- : 'YouTube Player - Loaded',
108
- 'aria-live': 'polite',
109
- 'role': 'application',
110
- 'style': {
111
- cursor: 'pointer',
112
- position: 'relative',
113
- backgroundColor: 'black',
114
- maxWidth: '100%',
115
- width: `${props.width}px`,
116
- height: `'auto'`,
117
- aspectRatio: `${props.width}/${props.height}`,
118
- },
119
- }) as HTMLAttributes
120
- })
121
-
122
- const placeholder = computed(() => `https://i.ytimg.com/vi_webp/${props.videoId}/sddefault.webp`)
123
-
124
- if (import.meta.server) {
125
- // dns-prefetch https://i.vimeocdn.com
126
- useHead({
127
- link: [
128
- {
129
- rel: props.aboveTheFold ? 'preconnect' : 'dns-prefetch',
130
- href: 'https://i.ytimg.com',
131
- },
132
- props.aboveTheFold
133
- // we can preload the placeholder image
134
- ? {
135
- rel: 'preload',
136
- as: 'image',
137
- href: placeholder.value,
138
- }
139
- : {},
140
- ],
141
- })
142
- }
143
-
144
- const placeholderAttrs = computed(() => {
145
- return defu(props.placeholderAttrs, {
146
- src: placeholder.value,
147
- alt: '',
148
- loading: props.aboveTheFold ? 'eager' : 'lazy',
149
- style: {
150
- width: '100%',
151
- objectFit: 'contain',
152
- height: '100%',
153
- },
154
- } satisfies ImgHTMLAttributes)
155
- })
156
- </script>
157
-
158
- <template>
159
- <div ref="rootEl" v-bind="rootAttrs">
160
- <div ref="youtubeEl" style="width: 100%; height: 100%; position: absolute; top: 0; left: 0;" />
161
- <slot v-if="!ready" :placeholder="placeholder" name="placeholder">
162
- <img v-bind="placeholderAttrs">
163
- </slot>
164
- <slot v-if="status === 'loading'" name="loading">
165
- <ScriptLoadingIndicator />
166
- </slot>
167
- <slot v-if="status === 'awaitingLoad'" name="awaitingLoad" />
168
- <slot v-else-if="status === 'error'" name="error" />
169
- <slot />
170
- </div>
171
- </template>
1
+ <script setup lang="ts">
2
+ /// <reference types="youtube" />
3
+ import { computed, onMounted, ref, watch } from 'vue'
4
+ import type { HTMLAttributes, ImgHTMLAttributes, Ref } from 'vue'
5
+ import { defu } from 'defu'
6
+ import type { ElementScriptTrigger } from '../types'
7
+ import { useScriptTriggerElement } from '../composables/useScriptTriggerElement'
8
+ import { useScriptYouTubePlayer } from '../registry/youtube-player'
9
+ import { useHead } from '#imports'
10
+
11
+ const props = withDefaults(defineProps<{
12
+ placeholderAttrs?: ImgHTMLAttributes
13
+ rootAttrs?: HTMLAttributes
14
+ aboveTheFold?: boolean
15
+ trigger?: ElementScriptTrigger
16
+ videoId: string
17
+ playerVars?: YT.PlayerVars
18
+ width?: number
19
+ height?: number
20
+ }>(), {
21
+ trigger: 'mousedown',
22
+ // @ts-expect-error untyped
23
+ playerVars: { autoplay: 0, playsinline: 1 },
24
+ width: 640,
25
+ height: 480,
26
+ })
27
+
28
+ const emits = defineEmits<{
29
+ 'ready': [e: YT.PlayerEvent]
30
+ 'state-change': [e: YT.OnStateChangeEvent, target: YT.Player]
31
+ 'playback-quality-change': [e: YT.OnPlaybackQualityChangeEvent, target: YT.Player]
32
+ 'playback-rate-change': [e: YT.OnPlaybackRateChangeEvent, target: YT.Player]
33
+ 'error': [e: YT.OnErrorEvent, target: YT.Player]
34
+ }>()
35
+ const events: (keyof YT.Events)[] = [
36
+ 'onReady',
37
+ 'onStateChange',
38
+ 'onPlaybackQualityChange',
39
+ 'onPlaybackRateChange',
40
+ 'onError',
41
+ 'onApiChange',
42
+ ]
43
+ const rootEl = ref()
44
+ const youtubeEl = ref()
45
+ const ready = ref(false)
46
+ const trigger = useScriptTriggerElement({ trigger: props.trigger, el: rootEl })
47
+ const { onLoaded, status } = useScriptYouTubePlayer({
48
+ scriptOptions: {
49
+ trigger,
50
+ },
51
+ })
52
+
53
+ const player: Ref<YT.Player | undefined> = ref()
54
+ let clickTriggered = false
55
+ if (props.trigger === 'mousedown' && trigger instanceof Promise) {
56
+ trigger.then(() => {
57
+ clickTriggered = true
58
+ })
59
+ }
60
+ onMounted(() => {
61
+ onLoaded(async (instance) => {
62
+ const YouTube: typeof YT & { ready: (fn: () => void) => void } = await instance.YT
63
+ await new Promise<void>((resolve) => {
64
+ if (typeof YT.Player === 'undefined')
65
+ YouTube.ready(resolve)
66
+ else
67
+ resolve()
68
+ })
69
+ player.value = new YT.Player(youtubeEl.value, {
70
+ ...props,
71
+ events: Object.fromEntries(events.map(event => [event, (e: any) => {
72
+ const emitEventName = event.replace(/([A-Z])/g, '-$1').replace('on-', '').toLowerCase()
73
+ // @ts-expect-error untyped
74
+ emits(emitEventName, e)
75
+ if (event === 'onReady') {
76
+ ready.value = true
77
+ if (clickTriggered) {
78
+ player.value?.playVideo()
79
+ clickTriggered = false
80
+ }
81
+ watch(() => props.videoId, () => {
82
+ player.value?.loadVideoById(props.videoId)
83
+ })
84
+ }
85
+ }])),
86
+ })
87
+ })
88
+ watch(status, (status) => {
89
+ if (status === 'error') {
90
+ // @ts-expect-error untyped
91
+ emits('error')
92
+ }
93
+ })
94
+ })
95
+
96
+ defineExpose({
97
+ player,
98
+ })
99
+
100
+ const rootAttrs = computed(() => {
101
+ return defu(props.rootAttrs, {
102
+ 'aria-busy': status.value === 'loading',
103
+ 'aria-label': status.value === 'awaitingLoad'
104
+ ? 'YouTube Player - Placeholder'
105
+ : status.value === 'loading'
106
+ ? 'YouTube Player - Loading'
107
+ : 'YouTube Player - Loaded',
108
+ 'aria-live': 'polite',
109
+ 'role': 'application',
110
+ 'style': {
111
+ cursor: 'pointer',
112
+ position: 'relative',
113
+ backgroundColor: 'black',
114
+ maxWidth: '100%',
115
+ width: `${props.width}px`,
116
+ height: `'auto'`,
117
+ aspectRatio: `${props.width}/${props.height}`,
118
+ },
119
+ ...(trigger instanceof Promise ? trigger.ssrAttrs || {} : {}),
120
+ }) as HTMLAttributes
121
+ })
122
+
123
+ const placeholder = computed(() => `https://i.ytimg.com/vi_webp/${props.videoId}/sddefault.webp`)
124
+
125
+ if (import.meta.server) {
126
+ // dns-prefetch https://i.vimeocdn.com
127
+ useHead({
128
+ link: [
129
+ {
130
+ key: `nuxt-script-youtube-img`,
131
+ rel: props.aboveTheFold ? 'preconnect' : 'dns-prefetch',
132
+ href: 'https://i.ytimg.com',
133
+ },
134
+ props.aboveTheFold
135
+ // we can preload the placeholder image
136
+ ? {
137
+ key: `nuxt-script-youtube-img`,
138
+ rel: 'preload',
139
+ as: 'image',
140
+ href: placeholder.value,
141
+ }
142
+ : {},
143
+ ],
144
+ })
145
+ }
146
+
147
+ const placeholderAttrs = computed(() => {
148
+ return defu(props.placeholderAttrs, {
149
+ src: placeholder.value,
150
+ alt: '',
151
+ loading: props.aboveTheFold ? 'eager' : 'lazy',
152
+ style: {
153
+ width: '100%',
154
+ objectFit: 'contain',
155
+ height: '100%',
156
+ },
157
+ } satisfies ImgHTMLAttributes)
158
+ })
159
+ </script>
160
+
161
+ <template>
162
+ <div ref="rootEl" v-bind="rootAttrs">
163
+ <div ref="youtubeEl" style="width: 100%; height: 100%; position: absolute; top: 0; left: 0;" />
164
+ <slot v-if="!ready" :placeholder="placeholder" name="placeholder">
165
+ <img v-bind="placeholderAttrs">
166
+ </slot>
167
+ <slot v-if="status === 'loading'" name="loading">
168
+ <ScriptLoadingIndicator />
169
+ </slot>
170
+ <slot v-if="status === 'awaitingLoad'" name="awaitingLoad" />
171
+ <slot v-else-if="status === 'error'" name="error" />
172
+ <slot />
173
+ </div>
174
+ </template>
@@ -1,23 +1,38 @@
1
1
  import { resolveScriptKey } from "unhead";
2
2
  import { defu } from "defu";
3
3
  import { useScript as _useScript } from "@unhead/vue";
4
- import { injectHead, onNuxtReady, useNuxtApp, useRuntimeConfig, reactive } from "#imports";
4
+ import { injectHead, onNuxtReady, useHead, useNuxtApp, useRuntimeConfig, reactive } from "#imports";
5
5
  function useNuxtScriptRuntimeConfig() {
6
6
  return useRuntimeConfig().public["nuxt-scripts"];
7
7
  }
8
8
  export function useScript(input, options) {
9
9
  input = typeof input === "string" ? { src: input } : input;
10
10
  options = defu(options, useNuxtScriptRuntimeConfig()?.defaultScriptOptions);
11
- if (options.trigger === "onNuxtReady")
11
+ const rel = options.trigger === "onNuxtReady" ? "preload" : "preconnect";
12
+ const id = resolveScriptKey(input);
13
+ if (options.trigger !== "server" && (rel === "preload" || !input.src.startsWith("/"))) {
14
+ useHead({
15
+ link: [
16
+ {
17
+ rel,
18
+ as: rel === "preload" ? "script" : void 0,
19
+ href: input.src,
20
+ crossorigin: input.src.startsWith("/") ? void 0 : typeof input.crossorigin !== "undefined" ? input.crossorigin : "anonymous",
21
+ key: `nuxt-script-${id}`,
22
+ tagPriority: rel === "preload" ? "high" : 0,
23
+ fetchpriority: "low"
24
+ }
25
+ ]
26
+ });
27
+ }
28
+ if (options.trigger === "onNuxtReady") {
12
29
  options.trigger = onNuxtReady;
30
+ }
13
31
  const nuxtApp = useNuxtApp();
14
- const id = resolveScriptKey(input);
15
32
  nuxtApp.$scripts = nuxtApp.$scripts || reactive({});
16
- if (nuxtApp.$scripts[id]) {
17
- return nuxtApp.$scripts[id];
18
- }
33
+ const exists = !!nuxtApp.$scripts?.[id];
19
34
  if (import.meta.client) {
20
- if (!nuxtApp._scripts?.[id]) {
35
+ if (!exists) {
21
36
  performance?.mark?.("mark_feature_usage", {
22
37
  detail: {
23
38
  feature: options.performanceMarkFeature ?? `nuxt-scripts:${id}`
@@ -32,6 +47,9 @@ export function useScript(input, options) {
32
47
  nuxtApp._scripts[instance.id] = payload;
33
48
  nuxtApp.hooks.callHook("scripts:updated", { scripts: nuxtApp._scripts });
34
49
  };
50
+ if (exists) {
51
+ return instance;
52
+ }
35
53
  const payload = {
36
54
  ...options.devtools,
37
55
  src: input.src,
@@ -14,4 +14,6 @@ export interface ElementScriptTriggerOptions {
14
14
  /**
15
15
  * Create a trigger for an element to load a script based on specific element events.
16
16
  */
17
- export declare function useScriptTriggerElement(options: ElementScriptTriggerOptions): Promise<void>;
17
+ export declare function useScriptTriggerElement(options: ElementScriptTriggerOptions): Promise<void> & {
18
+ ssrAttrs?: Record<string, string>;
19
+ } | 'onNuxtReady';
@@ -2,9 +2,11 @@ import {
2
2
  useEventListener,
3
3
  useIntersectionObserver
4
4
  } from "@vueuse/core";
5
+ import { tryOnScopeDispose, tryOnMounted } from "@vueuse/shared";
6
+ import { watch } from "vue";
5
7
  function useElementVisibilityPromise(element) {
6
8
  let observer;
7
- return new Promise((resolve) => {
9
+ return new Promise((resolve, reject) => {
8
10
  observer = useIntersectionObserver(
9
11
  element,
10
12
  (intersectionObserverEntries) => {
@@ -18,32 +20,57 @@ function useElementVisibilityPromise(element) {
18
20
  threshold: 0
19
21
  }
20
22
  );
23
+ tryOnScopeDispose(reject);
24
+ }).catch(() => {
21
25
  }).finally(() => {
22
26
  observer.stop();
23
27
  });
24
28
  }
25
29
  export function useScriptTriggerElement(options) {
26
30
  const { el, trigger } = options;
27
- if (import.meta.server || !el)
28
- return new Promise(() => {
29
- });
30
31
  const triggers = (Array.isArray(options.trigger) ? options.trigger : [options.trigger]).filter(Boolean);
31
- if (el && triggers.some((t) => ["visibility", "visible"].includes(t)))
32
+ if (!trigger || triggers.includes("immediate") || triggers.includes("onNuxtReady")) {
33
+ return "onNuxtReady";
34
+ }
35
+ if (triggers.some((t) => ["visibility", "visible"].includes(t))) {
36
+ if (import.meta.server || !el)
37
+ return new Promise(() => {
38
+ });
32
39
  return useElementVisibilityPromise(el);
33
- if (!trigger)
34
- return Promise.resolve();
35
- if (!triggers.includes("immediate")) {
36
- return new Promise((resolve) => {
37
- const _ = useEventListener(
38
- typeof el !== "undefined" ? el : document.body,
39
- triggers,
40
- () => {
41
- resolve();
42
- _();
43
- },
44
- { once: true, passive: true }
45
- );
40
+ }
41
+ const ssrAttrs = {};
42
+ if (import.meta.server) {
43
+ triggers.forEach((trigger2) => {
44
+ ssrAttrs[`on${trigger2}`] = `this.dataset.script_${trigger2} = true`;
46
45
  });
47
46
  }
48
- return Promise.resolve();
47
+ const p = new Promise((resolve, reject) => {
48
+ const target = typeof el !== "undefined" ? el : document.body;
49
+ const _ = useEventListener(
50
+ target,
51
+ triggers,
52
+ () => {
53
+ _();
54
+ resolve();
55
+ },
56
+ { once: true, passive: true }
57
+ );
58
+ tryOnMounted(() => {
59
+ watch(target, ($el) => {
60
+ if ($el) {
61
+ triggers.forEach((trigger2) => {
62
+ if ($el.dataset[`script_${trigger2}`]) {
63
+ _();
64
+ resolve();
65
+ }
66
+ });
67
+ }
68
+ }, {
69
+ immediate: true
70
+ });
71
+ });
72
+ tryOnScopeDispose(reject);
73
+ }).catch(() => {
74
+ });
75
+ return Object.assign(p, { ssrAttrs });
49
76
  }
@@ -1,6 +1,5 @@
1
- import { optional } from "valibot";
2
1
  import { useRegistryScript } from "../utils.js";
3
- import { object, string } from "#nuxt-scripts-validator";
2
+ import { object, string, optional } from "#nuxt-scripts-validator";
4
3
  import { useHead } from "#imports";
5
4
  export const GoogleAdsenseOptions = object({
6
5
  /**
@@ -18,19 +17,17 @@ export function useScriptGoogleAdsense(_options) {
18
17
  use() {
19
18
  return { adsbygoogle: window.adsbygoogle };
20
19
  },
21
- // allow dataLayer to be accessed on the server
22
- stub: import.meta.client ? void 0 : ({ fn }) => {
23
- return fn === "adsbygoogle" ? [] : void 0;
24
- },
25
20
  beforeInit() {
26
- useHead({
27
- meta: [
28
- {
29
- name: "google-adsense-account",
30
- content: options?.client
31
- }
32
- ]
33
- });
21
+ if (options?.client) {
22
+ useHead({
23
+ meta: [
24
+ {
25
+ name: "google-adsense-account",
26
+ content: options?.client
27
+ }
28
+ ]
29
+ });
30
+ }
34
31
  }
35
32
  }
36
33
  }), _options);
@@ -1,2 +1,2 @@
1
- import { object } from "valibot";
1
+ import { object } from "#nuxt-scripts-validator";
2
2
  const _emptyOptions = object({});
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@nuxt/scripts",
3
3
  "type": "module",
4
- "version": "0.7.1",
5
- "packageManager": "pnpm@9.7.1",
4
+ "version": "0.7.2",
5
+ "packageManager": "pnpm@9.9.0",
6
6
  "description": "Load third-party scripts with better performance, privacy and DX in Nuxt Apps.",
7
7
  "author": {
8
8
  "website": "https://harlanzw.com",
@@ -65,15 +65,15 @@
65
65
  ]
66
66
  },
67
67
  "dependencies": {
68
- "@nuxt/devtools-kit": "^1.3.14",
69
- "@nuxt/devtools-ui-kit": "^1.3.14",
70
- "@nuxt/kit": "^3.12.4",
71
- "@types/google.maps": "^3.55.12",
68
+ "@nuxt/devtools-kit": "^1.4.1",
69
+ "@nuxt/devtools-ui-kit": "^1.4.1",
70
+ "@nuxt/kit": "^3.13.0",
71
+ "@types/google.maps": "^3.57.0",
72
72
  "@types/stripe-v3": "^3.1.33",
73
73
  "@types/vimeo__player": "^2.18.3",
74
- "@types/youtube": "^0.0.50",
75
- "@unhead/vue": "^1.10.0",
76
- "@vueuse/core": "^11.0.1",
74
+ "@types/youtube": "^0.1.0",
75
+ "@unhead/vue": "^1.10.3",
76
+ "@vueuse/core": "^11.0.3",
77
77
  "consola": "^3.2.3",
78
78
  "defu": "^6.1.4",
79
79
  "h3": "^1.12.0",
@@ -82,33 +82,33 @@
82
82
  "ofetch": "^1.3.4",
83
83
  "ohash": "^1.1.3",
84
84
  "pathe": "^1.1.2",
85
- "pkg-types": "^1.1.3",
85
+ "pkg-types": "^1.2.0",
86
86
  "semver": "^7.6.3",
87
- "shiki": "1.14.1",
87
+ "shiki": "1.16.1",
88
88
  "sirv": "^2.0.4",
89
89
  "std-env": "^3.7.0",
90
90
  "third-party-capital": "2.3.0",
91
91
  "ufo": "^1.5.4",
92
- "unimport": "^3.11.0",
93
- "unplugin": "^1.12.2",
92
+ "unimport": "^3.11.1",
93
+ "unplugin": "^1.12.3",
94
94
  "unstorage": "^1.10.2",
95
- "valibot": "^0.38.0"
95
+ "valibot": "^0.41.0"
96
96
  },
97
97
  "devDependencies": {
98
- "@nuxt/devtools-ui-kit": "^1.3.14",
99
- "@nuxt/eslint-config": "^0.5.1",
98
+ "@nuxt/devtools-ui-kit": "^1.4.1",
99
+ "@nuxt/eslint-config": "^0.5.5",
100
100
  "@nuxt/module-builder": "^0.8.3",
101
101
  "@nuxt/test-utils": "3.14.1",
102
102
  "@types/semver": "^7.5.8",
103
- "@typescript-eslint/typescript-estree": "^8.2.0",
104
- "@unhead/schema": "^1.10.0",
103
+ "@typescript-eslint/typescript-estree": "^8.4.0",
104
+ "@unhead/schema": "^1.10.3",
105
105
  "acorn-loose": "^8.4.0",
106
- "bumpp": "^9.5.1",
106
+ "bumpp": "^9.5.2",
107
107
  "changelogen": "^0.5.5",
108
- "eslint": "9.9.0",
108
+ "eslint": "9.9.1",
109
109
  "eslint-plugin-n": "^17.10.2",
110
110
  "knitwork": "^1.1.0",
111
- "nuxt": "^3.12.4",
111
+ "nuxt": "^3.13.0",
112
112
  "nuxt-scripts-devtools": "workspace:*",
113
113
  "playwright-core": "^1.46.1",
114
114
  "typescript": "^5.5.4",
@@ -117,16 +117,17 @@
117
117
  "vue-router": "^4.4.3"
118
118
  },
119
119
  "resolutions": {
120
+ "@nuxt/schema": "3.13.0",
120
121
  "@nuxt/scripts": "workspace:*",
121
- "@unhead/dom": "1.10.0",
122
- "@unhead/schema": "1.10.0",
123
- "@unhead/shared": "1.10.0",
124
- "@unhead/ssr": "1.10.0",
125
- "@unhead/vue": "1.10.0",
126
- "nuxt": "^3.12.4",
122
+ "@unhead/dom": "1.10.2",
123
+ "@unhead/schema": "1.10.4",
124
+ "@unhead/shared": "1.10.4",
125
+ "@unhead/ssr": "1.10.4",
126
+ "@unhead/vue": "1.10.4",
127
+ "nuxt": "^3.13.0",
127
128
  "nuxt-scripts-devtools": "workspace:*",
128
129
  "shiki": "1.10.3",
129
- "unhead": "1.10.0",
130
+ "unhead": "1.10.4",
130
131
  "vue": "^3.4.38",
131
132
  "vue-router": "^4.4.3"
132
133
  }
@@ -1 +0,0 @@
1
- {"id":"e4092e18-9a58-41ab-947e-35e1f2082b75","timestamp":1724318010522,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
@@ -1 +0,0 @@
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}}