@nuxt/scripts 0.13.2 → 1.0.0-beta.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 (98) hide show
  1. package/README.md +15 -0
  2. package/dist/client/200.html +1 -1
  3. package/dist/client/404.html +1 -1
  4. package/dist/client/_nuxt/B66N9HCo.js +1 -0
  5. package/dist/client/_nuxt/B8XOar-X.js +162 -0
  6. package/dist/client/_nuxt/{Bje-0OHL.js → DfLgoB--.js} +1 -1
  7. package/dist/client/_nuxt/DvH517bE.js +1 -0
  8. package/dist/client/_nuxt/builds/latest.json +1 -1
  9. package/dist/client/_nuxt/builds/meta/133a46c5-a5c1-4a63-87d1-037947a5bcdb.json +1 -0
  10. package/dist/client/_nuxt/entry.D45OuV0w.css +1 -0
  11. package/dist/client/_nuxt/error-404.B57D-jUQ.css +1 -0
  12. package/dist/client/_nuxt/error-500.DTHUW7BI.css +1 -0
  13. package/dist/client/index.html +1 -1
  14. package/dist/module.d.mts +106 -4
  15. package/dist/module.json +1 -1
  16. package/dist/module.mjs +705 -173
  17. package/dist/registry.mjs +63 -0
  18. package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.d.vue.ts +29 -1
  19. package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue +35 -10
  20. package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue.d.ts +29 -1
  21. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.d.vue.ts +20 -8
  22. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue +2 -2
  23. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue.d.ts +20 -8
  24. package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPinElement.vue +7 -1
  25. package/dist/runtime/components/ScriptCrisp.d.vue.ts +1 -1
  26. package/dist/runtime/components/ScriptCrisp.vue.d.ts +1 -1
  27. package/dist/runtime/components/ScriptInstagramEmbed.d.vue.ts +53 -0
  28. package/dist/runtime/components/ScriptInstagramEmbed.vue +38 -0
  29. package/dist/runtime/components/ScriptInstagramEmbed.vue.d.ts +53 -0
  30. package/dist/runtime/components/ScriptIntercom.d.vue.ts +1 -1
  31. package/dist/runtime/components/ScriptIntercom.vue.d.ts +1 -1
  32. package/dist/runtime/components/ScriptVimeoPlayer.d.vue.ts +2 -2
  33. package/dist/runtime/components/ScriptVimeoPlayer.vue.d.ts +2 -2
  34. package/dist/runtime/components/ScriptXEmbed.d.vue.ts +82 -0
  35. package/dist/runtime/components/ScriptXEmbed.vue +76 -0
  36. package/dist/runtime/components/ScriptXEmbed.vue.d.ts +82 -0
  37. package/dist/runtime/components/ScriptYouTubePlayer.d.vue.ts +12 -1
  38. package/dist/runtime/components/ScriptYouTubePlayer.vue +41 -16
  39. package/dist/runtime/components/ScriptYouTubePlayer.vue.d.ts +12 -1
  40. package/dist/runtime/composables/useScript.js +34 -3
  41. package/dist/runtime/composables/useScriptTriggerServiceWorker.d.ts +7 -0
  42. package/dist/runtime/composables/useScriptTriggerServiceWorker.js +39 -0
  43. package/dist/runtime/npm-script-stub.d.ts +20 -0
  44. package/dist/runtime/npm-script-stub.js +73 -0
  45. package/dist/runtime/plugins/sw-register.client.d.ts +2 -0
  46. package/dist/runtime/plugins/sw-register.client.js +12 -0
  47. package/dist/runtime/registry/google-recaptcha.d.ts +27 -0
  48. package/dist/runtime/registry/google-recaptcha.js +45 -0
  49. package/dist/runtime/registry/google-sign-in.d.ts +84 -0
  50. package/dist/runtime/registry/google-sign-in.js +50 -0
  51. package/dist/runtime/registry/google-tag-manager.d.ts +3 -1
  52. package/dist/runtime/registry/google-tag-manager.js +15 -5
  53. package/dist/runtime/registry/instagram-embed.d.ts +23 -0
  54. package/dist/runtime/registry/instagram-embed.js +22 -0
  55. package/dist/runtime/registry/lemon-squeezy.d.ts +0 -1
  56. package/dist/runtime/registry/matomo-analytics.js +1 -1
  57. package/dist/runtime/registry/plausible-analytics.js +8 -6
  58. package/dist/runtime/registry/posthog.d.ts +26 -0
  59. package/dist/runtime/registry/posthog.js +92 -0
  60. package/dist/runtime/registry/rybbit-analytics.js +38 -8
  61. package/dist/runtime/registry/tiktok-pixel.d.ts +44 -0
  62. package/dist/runtime/registry/tiktok-pixel.js +44 -0
  63. package/dist/runtime/registry/x-embed.d.ts +77 -0
  64. package/dist/runtime/registry/x-embed.js +41 -0
  65. package/dist/runtime/server/google-static-maps-proxy.d.ts +2 -0
  66. package/dist/runtime/server/google-static-maps-proxy.js +54 -0
  67. package/dist/runtime/server/instagram-embed-asset.d.ts +2 -0
  68. package/dist/runtime/server/instagram-embed-asset.js +42 -0
  69. package/dist/runtime/server/instagram-embed-image.d.ts +2 -0
  70. package/dist/runtime/server/instagram-embed-image.js +54 -0
  71. package/dist/runtime/server/instagram-embed.d.ts +2 -0
  72. package/dist/runtime/server/instagram-embed.js +91 -0
  73. package/dist/runtime/server/proxy-handler.d.ts +6 -0
  74. package/dist/runtime/server/proxy-handler.js +230 -0
  75. package/dist/runtime/server/sw-handler.d.ts +2 -0
  76. package/dist/runtime/server/sw-handler.js +25 -0
  77. package/dist/runtime/server/utils/privacy.d.ts +97 -0
  78. package/dist/runtime/server/utils/privacy.js +268 -0
  79. package/dist/runtime/server/x-embed-image.d.ts +2 -0
  80. package/dist/runtime/server/x-embed-image.js +53 -0
  81. package/dist/runtime/server/x-embed.d.ts +49 -0
  82. package/dist/runtime/server/x-embed.js +31 -0
  83. package/dist/runtime/sw/proxy-sw.template.d.ts +1 -0
  84. package/dist/runtime/sw/proxy-sw.template.js +54 -0
  85. package/dist/runtime/types.d.ts +42 -1
  86. package/dist/runtime/utils/pure.d.ts +13 -0
  87. package/dist/runtime/utils/pure.js +67 -0
  88. package/dist/runtime/utils.d.ts +3 -2
  89. package/dist/runtime/utils.js +11 -1
  90. package/dist/types.d.mts +1 -1
  91. package/package.json +39 -32
  92. package/dist/client/_nuxt/DMut0W-e.js +0 -162
  93. package/dist/client/_nuxt/builds/meta/5e0206fe-a683-423c-8d59-2596d0b16fee.json +0 -1
  94. package/dist/client/_nuxt/entry.BjfcJo5q.css +0 -1
  95. package/dist/client/_nuxt/error-404.B0ZhSNwd.css +0 -1
  96. package/dist/client/_nuxt/error-500.D4MdgPaC.css +0 -1
  97. package/dist/client/_nuxt/iNmKC7TZ.js +0 -1
  98. package/dist/client/_nuxt/rttsH3SL.js +0 -1
@@ -14,7 +14,7 @@ type __VLS_Props = {
14
14
  trigger?: ElementScriptTrigger;
15
15
  };
16
16
  declare var __VLS_1: {
17
- ready: any;
17
+ ready: boolean;
18
18
  }, __VLS_3: {}, __VLS_5: {}, __VLS_7: {};
19
19
  type __VLS_Slots = {} & {
20
20
  default?: (props: typeof __VLS_1) => any;
@@ -14,7 +14,7 @@ type __VLS_Props = {
14
14
  trigger?: ElementScriptTrigger;
15
15
  };
16
16
  declare var __VLS_1: {
17
- ready: any;
17
+ ready: boolean;
18
18
  }, __VLS_3: {}, __VLS_5: {}, __VLS_7: {};
19
19
  type __VLS_Slots = {} & {
20
20
  default?: (props: typeof __VLS_1) => any;
@@ -64,6 +64,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
64
64
  getPlaybackRate: () => Promise<number> | undefined;
65
65
  setPlaybackRate: (rate: number) => Promise<number> | undefined;
66
66
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
67
+ progress: (event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any;
67
68
  error: (event: import("@vimeo/player").Error, player: Vimeo.Player) => any;
68
69
  loaded: (event: import("@vimeo/player").LoadedEvent, player: Vimeo.Player) => any;
69
70
  cuechange: (event: import("@vimeo/player").CueChangeEvent, player: Vimeo.Player) => any;
@@ -72,7 +73,6 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
72
73
  pause: (event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any;
73
74
  play: (event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any;
74
75
  playing: (event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any;
75
- progress: (event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any;
76
76
  resize: (event: import("@vimeo/player").ResizeEvent, player: Vimeo.Player) => any;
77
77
  seeked: (event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any;
78
78
  seeking: (event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any;
@@ -90,6 +90,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
90
90
  enterpictureinpicture: (event: never, player: Vimeo.Player) => any;
91
91
  leavepictureinpicture: (event: never, player: Vimeo.Player) => any;
92
92
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
93
+ onProgress?: ((event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any) | undefined;
93
94
  onError?: ((event: import("@vimeo/player").Error, player: Vimeo.Player) => any) | undefined;
94
95
  onLoaded?: ((event: import("@vimeo/player").LoadedEvent, player: Vimeo.Player) => any) | undefined;
95
96
  onCuechange?: ((event: import("@vimeo/player").CueChangeEvent, player: Vimeo.Player) => any) | undefined;
@@ -98,7 +99,6 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
98
99
  onPause?: ((event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any) | undefined;
99
100
  onPlay?: ((event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any) | undefined;
100
101
  onPlaying?: ((event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any) | undefined;
101
- onProgress?: ((event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any) | undefined;
102
102
  onResize?: ((event: import("@vimeo/player").ResizeEvent, player: Vimeo.Player) => any) | undefined;
103
103
  onSeeked?: ((event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any) | undefined;
104
104
  onSeeking?: ((event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any) | undefined;
@@ -64,6 +64,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
64
64
  getPlaybackRate: () => Promise<number> | undefined;
65
65
  setPlaybackRate: (rate: number) => Promise<number> | undefined;
66
66
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
67
+ progress: (event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any;
67
68
  error: (event: import("@vimeo/player").Error, player: Vimeo.Player) => any;
68
69
  loaded: (event: import("@vimeo/player").LoadedEvent, player: Vimeo.Player) => any;
69
70
  cuechange: (event: import("@vimeo/player").CueChangeEvent, player: Vimeo.Player) => any;
@@ -72,7 +73,6 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
72
73
  pause: (event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any;
73
74
  play: (event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any;
74
75
  playing: (event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any;
75
- progress: (event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any;
76
76
  resize: (event: import("@vimeo/player").ResizeEvent, player: Vimeo.Player) => any;
77
77
  seeked: (event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any;
78
78
  seeking: (event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any;
@@ -90,6 +90,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
90
90
  enterpictureinpicture: (event: never, player: Vimeo.Player) => any;
91
91
  leavepictureinpicture: (event: never, player: Vimeo.Player) => any;
92
92
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
93
+ onProgress?: ((event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any) | undefined;
93
94
  onError?: ((event: import("@vimeo/player").Error, player: Vimeo.Player) => any) | undefined;
94
95
  onLoaded?: ((event: import("@vimeo/player").LoadedEvent, player: Vimeo.Player) => any) | undefined;
95
96
  onCuechange?: ((event: import("@vimeo/player").CueChangeEvent, player: Vimeo.Player) => any) | undefined;
@@ -98,7 +99,6 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
98
99
  onPause?: ((event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any) | undefined;
99
100
  onPlay?: ((event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any) | undefined;
100
101
  onPlaying?: ((event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any) | undefined;
101
- onProgress?: ((event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any) | undefined;
102
102
  onResize?: ((event: import("@vimeo/player").ResizeEvent, player: Vimeo.Player) => any) | undefined;
103
103
  onSeeked?: ((event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any) | undefined;
104
104
  onSeeking?: ((event: import("@vimeo/player").TimeEvent, player: Vimeo.Player) => any) | undefined;
@@ -0,0 +1,82 @@
1
+ import type { HTMLAttributes } from 'vue';
2
+ import type { XEmbedTweetData } from '../registry/x-embed.js';
3
+ type __VLS_Props = {
4
+ /**
5
+ * The tweet ID to embed
6
+ */
7
+ tweetId: string;
8
+ /**
9
+ * Custom API endpoint for fetching tweet data
10
+ * @default '/_scripts/x-embed'
11
+ */
12
+ apiEndpoint?: string;
13
+ /**
14
+ * Custom image proxy endpoint
15
+ * @default '/_scripts/x-embed-image'
16
+ */
17
+ imageProxyEndpoint?: string;
18
+ /**
19
+ * Root element attributes
20
+ */
21
+ rootAttrs?: HTMLAttributes;
22
+ };
23
+ declare var __VLS_1: {}, __VLS_3: {
24
+ error: import("nuxt/app").NuxtError<unknown> | undefined;
25
+ }, __VLS_5: {
26
+ tweet: XEmbedTweetData;
27
+ userName: string;
28
+ userHandle: string;
29
+ userAvatar: string;
30
+ userAvatarOriginal: string;
31
+ isVerified: boolean | undefined;
32
+ text: string;
33
+ datetime: string;
34
+ createdAt: Date;
35
+ likes: number;
36
+ likesFormatted: string;
37
+ replies: number;
38
+ repliesFormatted: string;
39
+ photos: {
40
+ proxiedUrl: string;
41
+ url: string;
42
+ width: number;
43
+ height: number;
44
+ }[] | undefined;
45
+ video: {
46
+ posterProxied: string;
47
+ poster: string;
48
+ variants: Array<{
49
+ type: string;
50
+ src: string;
51
+ }>;
52
+ } | null;
53
+ tweetUrl: string;
54
+ userUrl: string;
55
+ quotedTweet: XEmbedTweetData | undefined;
56
+ isReply: boolean;
57
+ replyToUser: string | undefined;
58
+ proxyImage: (url: string) => string;
59
+ };
60
+ type __VLS_Slots = {} & {
61
+ loading?: (props: typeof __VLS_1) => any;
62
+ } & {
63
+ error?: (props: typeof __VLS_3) => any;
64
+ } & {
65
+ default?: (props: typeof __VLS_5) => any;
66
+ };
67
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
68
+ tweet: import("vue").Ref<XEmbedTweetData | undefined, XEmbedTweetData | undefined>;
69
+ status: import("vue").Ref<import("nuxt/app").AsyncDataRequestStatus, import("nuxt/app").AsyncDataRequestStatus>;
70
+ error: import("vue").Ref<import("nuxt/app").NuxtError<unknown> | undefined, import("nuxt/app").NuxtError<unknown> | undefined>;
71
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
72
+ apiEndpoint: string;
73
+ imageProxyEndpoint: string;
74
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
75
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
76
+ declare const _default: typeof __VLS_export;
77
+ export default _default;
78
+ type __VLS_WithSlots<T, S> = T & {
79
+ new (): {
80
+ $slots: S;
81
+ };
82
+ };
@@ -0,0 +1,76 @@
1
+ <script setup>
2
+ import { computed } from "vue";
3
+ import { useAsyncData } from "nuxt/app";
4
+ import { formatCount, formatTweetDate, proxyXImageUrl } from "../registry/x-embed";
5
+ const props = defineProps({
6
+ tweetId: { type: String, required: true },
7
+ apiEndpoint: { type: String, required: false, default: "/api/_scripts/x-embed" },
8
+ imageProxyEndpoint: { type: String, required: false, default: "/api/_scripts/x-embed-image" },
9
+ rootAttrs: { type: Object, required: false }
10
+ });
11
+ const cacheKey = computed(() => `x-embed-${props.tweetId}`);
12
+ const { data: tweet, status, error } = useAsyncData(
13
+ cacheKey,
14
+ () => $fetch(`${props.apiEndpoint}?id=${props.tweetId}`)
15
+ );
16
+ const slotProps = computed(() => {
17
+ if (!tweet.value)
18
+ return null;
19
+ const t = tweet.value;
20
+ return {
21
+ // Raw data
22
+ tweet: t,
23
+ // User info
24
+ userName: t.user.name,
25
+ userHandle: t.user.screen_name,
26
+ userAvatar: proxyXImageUrl(t.user.profile_image_url_https, props.imageProxyEndpoint),
27
+ userAvatarOriginal: t.user.profile_image_url_https,
28
+ isVerified: t.user.verified || t.user.is_blue_verified,
29
+ // Tweet content
30
+ text: t.text,
31
+ // Formatted values
32
+ datetime: formatTweetDate(t.created_at),
33
+ createdAt: new Date(t.created_at),
34
+ likes: t.favorite_count,
35
+ likesFormatted: formatCount(t.favorite_count),
36
+ replies: t.conversation_count,
37
+ repliesFormatted: formatCount(t.conversation_count),
38
+ // Media
39
+ photos: t.photos?.map((p) => ({
40
+ ...p,
41
+ proxiedUrl: proxyXImageUrl(p.url, props.imageProxyEndpoint)
42
+ })),
43
+ video: t.video ? {
44
+ ...t.video,
45
+ posterProxied: proxyXImageUrl(t.video.poster, props.imageProxyEndpoint)
46
+ } : null,
47
+ // Links
48
+ tweetUrl: `https://x.com/${t.user.screen_name}/status/${t.id_str}`,
49
+ userUrl: `https://x.com/${t.user.screen_name}`,
50
+ // Quoted tweet
51
+ quotedTweet: t.quoted_tweet,
52
+ // Reply context
53
+ isReply: !!t.parent,
54
+ replyToUser: t.parent?.user.screen_name,
55
+ // Helpers
56
+ proxyImage: (url) => proxyXImageUrl(url, props.imageProxyEndpoint)
57
+ };
58
+ });
59
+ defineExpose({
60
+ tweet,
61
+ status,
62
+ error
63
+ });
64
+ </script>
65
+
66
+ <template>
67
+ <div v-bind="rootAttrs">
68
+ <slot v-if="status === 'pending'" name="loading">
69
+ <div>Loading tweet...</div>
70
+ </slot>
71
+ <slot v-else-if="status === 'error'" name="error" :error="error">
72
+ <div>Failed to load tweet</div>
73
+ </slot>
74
+ <slot v-else-if="slotProps" v-bind="slotProps" />
75
+ </div>
76
+ </template>
@@ -0,0 +1,82 @@
1
+ import type { HTMLAttributes } from 'vue';
2
+ import type { XEmbedTweetData } from '../registry/x-embed.js';
3
+ type __VLS_Props = {
4
+ /**
5
+ * The tweet ID to embed
6
+ */
7
+ tweetId: string;
8
+ /**
9
+ * Custom API endpoint for fetching tweet data
10
+ * @default '/_scripts/x-embed'
11
+ */
12
+ apiEndpoint?: string;
13
+ /**
14
+ * Custom image proxy endpoint
15
+ * @default '/_scripts/x-embed-image'
16
+ */
17
+ imageProxyEndpoint?: string;
18
+ /**
19
+ * Root element attributes
20
+ */
21
+ rootAttrs?: HTMLAttributes;
22
+ };
23
+ declare var __VLS_1: {}, __VLS_3: {
24
+ error: import("nuxt/app").NuxtError<unknown> | undefined;
25
+ }, __VLS_5: {
26
+ tweet: XEmbedTweetData;
27
+ userName: string;
28
+ userHandle: string;
29
+ userAvatar: string;
30
+ userAvatarOriginal: string;
31
+ isVerified: boolean | undefined;
32
+ text: string;
33
+ datetime: string;
34
+ createdAt: Date;
35
+ likes: number;
36
+ likesFormatted: string;
37
+ replies: number;
38
+ repliesFormatted: string;
39
+ photos: {
40
+ proxiedUrl: string;
41
+ url: string;
42
+ width: number;
43
+ height: number;
44
+ }[] | undefined;
45
+ video: {
46
+ posterProxied: string;
47
+ poster: string;
48
+ variants: Array<{
49
+ type: string;
50
+ src: string;
51
+ }>;
52
+ } | null;
53
+ tweetUrl: string;
54
+ userUrl: string;
55
+ quotedTweet: XEmbedTweetData | undefined;
56
+ isReply: boolean;
57
+ replyToUser: string | undefined;
58
+ proxyImage: (url: string) => string;
59
+ };
60
+ type __VLS_Slots = {} & {
61
+ loading?: (props: typeof __VLS_1) => any;
62
+ } & {
63
+ error?: (props: typeof __VLS_3) => any;
64
+ } & {
65
+ default?: (props: typeof __VLS_5) => any;
66
+ };
67
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
68
+ tweet: import("vue").Ref<XEmbedTweetData | undefined, XEmbedTweetData | undefined>;
69
+ status: import("vue").Ref<import("nuxt/app").AsyncDataRequestStatus, import("nuxt/app").AsyncDataRequestStatus>;
70
+ error: import("vue").Ref<import("nuxt/app").NuxtError<unknown> | undefined, import("nuxt/app").NuxtError<unknown> | undefined>;
71
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
72
+ apiEndpoint: string;
73
+ imageProxyEndpoint: string;
74
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
75
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
76
+ declare const _default: typeof __VLS_export;
77
+ export default _default;
78
+ type __VLS_WithSlots<T, S> = T & {
79
+ new (): {
80
+ $slots: S;
81
+ };
82
+ };
@@ -10,6 +10,7 @@ type __VLS_Props = {
10
10
  playerVars?: YT.PlayerVars;
11
11
  width?: number;
12
12
  height?: number;
13
+ ratio?: string;
13
14
  /**
14
15
  * Whether to use youtube-nocookie.com for embedding.
15
16
  *
@@ -19,9 +20,15 @@ type __VLS_Props = {
19
20
  playerOptions?: YT.PlayerOptions;
20
21
  thumbnailSize?: YoutubeThumbnailSize;
21
22
  webp?: boolean;
23
+ /**
24
+ * Object-fit for the placeholder image.
25
+ *
26
+ * @default 'cover'
27
+ */
28
+ placeholderObjectFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';
22
29
  };
23
30
  declare var __VLS_1: {
24
- placeholder: any;
31
+ placeholder: string;
25
32
  }, __VLS_3: {}, __VLS_10: {}, __VLS_12: {}, __VLS_14: {};
26
33
  type __VLS_Slots = {} & {
27
34
  placeholder?: (props: typeof __VLS_1) => any;
@@ -42,20 +49,24 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
42
49
  "state-change": (e: YT.OnStateChangeEvent, target: YT.Player) => any;
43
50
  "playback-quality-change": (e: YT.OnPlaybackQualityChangeEvent, target: YT.Player) => any;
44
51
  "playback-rate-change": (e: YT.OnPlaybackRateChangeEvent, target: YT.Player) => any;
52
+ "api-change": (e: YT.PlayerEvent, target: YT.Player) => any;
45
53
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
46
54
  onError?: ((e: YT.OnErrorEvent, target: YT.Player) => any) | undefined;
47
55
  onReady?: ((e: YT.PlayerEvent) => any) | undefined;
48
56
  "onState-change"?: ((e: YT.OnStateChangeEvent, target: YT.Player) => any) | undefined;
49
57
  "onPlayback-quality-change"?: ((e: YT.OnPlaybackQualityChangeEvent, target: YT.Player) => any) | undefined;
50
58
  "onPlayback-rate-change"?: ((e: YT.OnPlaybackRateChangeEvent, target: YT.Player) => any) | undefined;
59
+ "onApi-change"?: ((e: YT.PlayerEvent, target: YT.Player) => any) | undefined;
51
60
  }>, {
52
61
  trigger: ElementScriptTrigger;
53
62
  width: number;
54
63
  height: number;
55
64
  playerVars: YT.PlayerVars;
65
+ ratio: string;
56
66
  cookies: boolean;
57
67
  thumbnailSize: YoutubeThumbnailSize;
58
68
  webp: boolean;
69
+ placeholderObjectFit: "cover" | "contain" | "fill" | "none" | "scale-down";
59
70
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
60
71
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
61
72
  declare const _default: typeof __VLS_export;
@@ -1,5 +1,5 @@
1
1
  <script setup>
2
- import { computed, onMounted, ref, watch } from "vue";
2
+ import { computed, onBeforeUnmount, onMounted, ref, watch } from "vue";
3
3
  import { defu } from "defu";
4
4
  import { useHead } from "nuxt/app";
5
5
  import { useScriptTriggerElement } from "../composables/useScriptTriggerElement";
@@ -14,12 +14,14 @@ const props = defineProps({
14
14
  playerVars: { type: null, required: false, default: { autoplay: 0, playsinline: 1 } },
15
15
  width: { type: Number, required: false, default: 640 },
16
16
  height: { type: Number, required: false, default: 360 },
17
+ ratio: { type: String, required: false, default: "16/9" },
17
18
  cookies: { type: Boolean, required: false, default: false },
18
19
  playerOptions: { type: null, required: false },
19
20
  thumbnailSize: { type: String, required: false, default: "hq720" },
20
- webp: { type: Boolean, required: false, default: true }
21
+ webp: { type: Boolean, required: false, default: true },
22
+ placeholderObjectFit: { type: String, required: false, default: "cover" }
21
23
  });
22
- const emits = defineEmits(["ready", "state-change", "playback-quality-change", "playback-rate-change", "error"]);
24
+ const emits = defineEmits(["ready", "state-change", "playback-quality-change", "playback-rate-change", "error", "api-change"]);
23
25
  const events = [
24
26
  "onReady",
25
27
  "onStateChange",
@@ -31,24 +33,46 @@ const events = [
31
33
  const rootEl = ref();
32
34
  const youtubeEl = ref();
33
35
  const ready = ref(false);
36
+ const isTriggered = ref(false);
34
37
  const trigger = useScriptTriggerElement({ trigger: props.trigger, el: rootEl });
35
38
  const script = useScriptYouTubePlayer({
36
39
  scriptOptions: {
40
+ // Use immediate trigger so script loads when ANY player needs it
41
+ // Each player will wait for its own trigger before creating iframe
37
42
  trigger
38
43
  }
39
44
  });
40
45
  const { onLoaded, status } = script;
41
46
  const player = ref();
42
- let clickTriggered = false;
43
- if (props.trigger === "mousedown" && trigger instanceof Promise) {
47
+ const clickTriggered = ref(false);
48
+ if (trigger instanceof Promise) {
44
49
  trigger.then((triggered) => {
45
50
  if (triggered) {
46
- clickTriggered = true;
51
+ isTriggered.value = true;
52
+ if (props.trigger === "mousedown") {
53
+ clickTriggered.value = true;
54
+ }
47
55
  }
48
56
  });
57
+ } else {
58
+ isTriggered.value = true;
49
59
  }
60
+ const stopVideoIdWatch = watch(() => props.videoId, (newId) => {
61
+ if (ready.value && player.value) {
62
+ player.value.loadVideoById(newId);
63
+ }
64
+ });
65
+ onBeforeUnmount(() => {
66
+ stopVideoIdWatch();
67
+ player.value?.destroy();
68
+ });
50
69
  onMounted(() => {
51
70
  onLoaded(async (instance) => {
71
+ if (!isTriggered.value && trigger instanceof Promise) {
72
+ const triggered = await trigger;
73
+ if (!triggered) return;
74
+ }
75
+ if (!youtubeEl.value) return;
52
76
  const YouTube = instance.YT instanceof Promise ? await instance.YT : instance.YT;
53
77
  await new Promise((resolve) => {
54
78
  if (typeof YT.Player === "undefined")
@@ -56,22 +80,23 @@ onMounted(() => {
56
80
  else
57
81
  resolve();
58
82
  });
83
+ if (!youtubeEl.value) return;
59
84
  player.value = new YT.Player(youtubeEl.value, {
60
85
  host: !props.cookies ? "https://www.youtube-nocookie.com" : "https://www.youtube.com",
61
- ...props,
86
+ videoId: props.videoId,
87
+ width: props.width,
88
+ height: props.height,
89
+ playerVars: props.playerVars,
62
90
  ...props.playerOptions,
63
91
  events: Object.fromEntries(events.map((event) => [event, (e) => {
64
92
  const emitEventName = event.replace(/([A-Z])/g, "-$1").replace("on-", "").toLowerCase();
65
93
  emits(emitEventName, e);
66
94
  if (event === "onReady") {
67
95
  ready.value = true;
68
- if (clickTriggered) {
96
+ if (clickTriggered.value) {
69
97
  player.value?.playVideo();
70
- clickTriggered = false;
98
+ clickTriggered.value = false;
71
99
  }
72
- watch(() => props.videoId, () => {
73
- player.value?.loadVideoById(props.videoId);
74
- });
75
100
  }
76
101
  }]))
77
102
  });
@@ -96,7 +121,7 @@ const rootAttrs = computed(() => {
96
121
  position: "relative",
97
122
  backgroundColor: "black",
98
123
  width: "100%",
99
- aspectRatio: `${props.width}/${props.height}`
124
+ aspectRatio: props.ratio
100
125
  },
101
126
  ...trigger instanceof Promise ? trigger.ssrAttrs || {} : {}
102
127
  });
@@ -108,12 +133,12 @@ if (import.meta.server) {
108
133
  useHead({
109
134
  link: [
110
135
  {
111
- key: `nuxt-script-youtube-img`,
136
+ key: "nuxt-script-youtube-img-preconnect",
112
137
  rel: props.aboveTheFold ? "preconnect" : "dns-prefetch",
113
138
  href: "https://i.ytimg.com"
114
139
  },
115
140
  props.aboveTheFold ? {
116
- key: `nuxt-script-youtube-img`,
141
+ key: `nuxt-script-youtube-img-preload-${props.videoId}`,
117
142
  rel: "preload",
118
143
  as: "image",
119
144
  href: placeholder.value
@@ -128,7 +153,7 @@ const placeholderAttrs = computed(() => {
128
153
  loading: props.aboveTheFold ? "eager" : "lazy",
129
154
  style: {
130
155
  width: "100%",
131
- objectFit: "contain",
156
+ objectFit: props.placeholderObjectFit,
132
157
  height: "100%"
133
158
  },
134
159
  onLoad(payload) {
@@ -10,6 +10,7 @@ type __VLS_Props = {
10
10
  playerVars?: YT.PlayerVars;
11
11
  width?: number;
12
12
  height?: number;
13
+ ratio?: string;
13
14
  /**
14
15
  * Whether to use youtube-nocookie.com for embedding.
15
16
  *
@@ -19,9 +20,15 @@ type __VLS_Props = {
19
20
  playerOptions?: YT.PlayerOptions;
20
21
  thumbnailSize?: YoutubeThumbnailSize;
21
22
  webp?: boolean;
23
+ /**
24
+ * Object-fit for the placeholder image.
25
+ *
26
+ * @default 'cover'
27
+ */
28
+ placeholderObjectFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';
22
29
  };
23
30
  declare var __VLS_1: {
24
- placeholder: any;
31
+ placeholder: string;
25
32
  }, __VLS_3: {}, __VLS_10: {}, __VLS_12: {}, __VLS_14: {};
26
33
  type __VLS_Slots = {} & {
27
34
  placeholder?: (props: typeof __VLS_1) => any;
@@ -42,20 +49,24 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
42
49
  "state-change": (e: YT.OnStateChangeEvent, target: YT.Player) => any;
43
50
  "playback-quality-change": (e: YT.OnPlaybackQualityChangeEvent, target: YT.Player) => any;
44
51
  "playback-rate-change": (e: YT.OnPlaybackRateChangeEvent, target: YT.Player) => any;
52
+ "api-change": (e: YT.PlayerEvent, target: YT.Player) => any;
45
53
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
46
54
  onError?: ((e: YT.OnErrorEvent, target: YT.Player) => any) | undefined;
47
55
  onReady?: ((e: YT.PlayerEvent) => any) | undefined;
48
56
  "onState-change"?: ((e: YT.OnStateChangeEvent, target: YT.Player) => any) | undefined;
49
57
  "onPlayback-quality-change"?: ((e: YT.OnPlaybackQualityChangeEvent, target: YT.Player) => any) | undefined;
50
58
  "onPlayback-rate-change"?: ((e: YT.OnPlaybackRateChangeEvent, target: YT.Player) => any) | undefined;
59
+ "onApi-change"?: ((e: YT.PlayerEvent, target: YT.Player) => any) | undefined;
51
60
  }>, {
52
61
  trigger: ElementScriptTrigger;
53
62
  width: number;
54
63
  height: number;
55
64
  playerVars: YT.PlayerVars;
65
+ ratio: string;
56
66
  cookies: boolean;
57
67
  thumbnailSize: YoutubeThumbnailSize;
58
68
  webp: boolean;
69
+ placeholderObjectFit: "cover" | "contain" | "fill" | "none" | "scale-down";
59
70
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
60
71
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
61
72
  declare const _default: typeof __VLS_export;
@@ -1,7 +1,7 @@
1
1
  import { defu } from "defu";
2
2
  import { useScript as _useScript } from "@unhead/vue/scripts";
3
- import { reactive } from "vue";
4
- import { onNuxtReady, useNuxtApp, useRuntimeConfig, injectHead } from "nuxt/app";
3
+ import { reactive, ref } from "vue";
4
+ import { onNuxtReady, useNuxtApp, useRuntimeConfig, injectHead, useHead } from "nuxt/app";
5
5
  import { logger } from "../logger.js";
6
6
  import { resolveTrigger } from "#build/nuxt-scripts-trigger-resolver";
7
7
  function useNuxtScriptRuntimeConfig() {
@@ -13,6 +13,27 @@ export function resolveScriptKey(input) {
13
13
  export function useScript(input, options) {
14
14
  input = typeof input === "string" ? { src: input } : input;
15
15
  options = defu(options, useNuxtScriptRuntimeConfig()?.defaultScriptOptions);
16
+ if (options.partytown) {
17
+ const src = input.src;
18
+ if (!src) {
19
+ throw new Error("useScript with partytown requires a src");
20
+ }
21
+ useHead({
22
+ script: [{ src, type: "text/partytown" }]
23
+ });
24
+ const nuxtApp2 = useNuxtApp();
25
+ nuxtApp2.$scripts = nuxtApp2.$scripts || reactive({});
26
+ const status = ref("loaded");
27
+ const stub = {
28
+ id: src,
29
+ status,
30
+ load: () => Promise.resolve({}),
31
+ remove: () => false,
32
+ entry: void 0
33
+ };
34
+ nuxtApp2.$scripts[src] = stub;
35
+ return stub;
36
+ }
16
37
  if (import.meta.dev && options.bundle === "unsupported") {
17
38
  console.warn("[Nuxt Scripts] Bundling is not supported for dynamic script sources. Static URLs are required for bundling.");
18
39
  options.bundle = false;
@@ -23,8 +44,8 @@ export function useScript(input, options) {
23
44
  options.trigger = resolved;
24
45
  }
25
46
  }
26
- const id = String(resolveScriptKey(input));
27
47
  const nuxtApp = useNuxtApp();
48
+ const id = String(resolveScriptKey(input));
28
49
  options.head = options.head || injectHead();
29
50
  if (!options.head) {
30
51
  throw new Error("useScript() has been called without Nuxt context.");
@@ -65,6 +86,16 @@ export function useScript(input, options) {
65
86
  }
66
87
  return _load();
67
88
  };
89
+ instance.reload = async () => {
90
+ instance.remove();
91
+ const reloadInput = typeof input === "string" ? { src: input, key: `${id}-${Date.now()}` } : { ...input, key: `${id}-${Date.now()}` };
92
+ const reloaded = _useScript(reloadInput, { ...options, trigger: "client" });
93
+ Object.assign(instance, {
94
+ status: reloaded.status,
95
+ entry: reloaded.entry
96
+ });
97
+ return reloaded.load();
98
+ };
68
99
  nuxtApp.$scripts[id] = instance;
69
100
  if (import.meta.dev && import.meta.client) {
70
101
  let syncScripts = function() {
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Create a trigger that loads a script after the service worker is controlling the page.
3
+ * Falls back to immediate loading if service workers are not supported or after timeout.
4
+ */
5
+ export declare function useScriptTriggerServiceWorker(options?: {
6
+ timeout?: number;
7
+ }): Promise<boolean>;
@@ -0,0 +1,39 @@
1
+ import { tryOnScopeDispose } from "@vueuse/shared";
2
+ export function useScriptTriggerServiceWorker(options) {
3
+ if (import.meta.server)
4
+ return new Promise(() => {
5
+ });
6
+ const timeout = options?.timeout ?? 3e3;
7
+ return new Promise((resolve) => {
8
+ if (!("serviceWorker" in navigator)) {
9
+ resolve(true);
10
+ return;
11
+ }
12
+ let resolved = false;
13
+ const done = () => {
14
+ if (resolved)
15
+ return;
16
+ resolved = true;
17
+ resolve(true);
18
+ };
19
+ if (navigator.serviceWorker.controller) {
20
+ done();
21
+ return;
22
+ }
23
+ const onControllerChange = () => {
24
+ navigator.serviceWorker.removeEventListener("controllerchange", onControllerChange);
25
+ done();
26
+ };
27
+ navigator.serviceWorker.addEventListener("controllerchange", onControllerChange);
28
+ const timer = setTimeout(() => {
29
+ navigator.serviceWorker.removeEventListener("controllerchange", onControllerChange);
30
+ console.warn("[nuxt-scripts] Service worker not controlling after timeout, loading scripts anyway");
31
+ done();
32
+ }, timeout);
33
+ tryOnScopeDispose(() => {
34
+ navigator.serviceWorker.removeEventListener("controllerchange", onControllerChange);
35
+ clearTimeout(timer);
36
+ resolve(false);
37
+ });
38
+ });
39
+ }