@nuxt/scripts 0.1.12 → 0.2.0
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/README.md +10 -200
- package/dist/client/200.html +14 -14
- package/dist/client/404.html +14 -14
- package/dist/client/_nuxt/-hLHpAOl.js +1 -0
- package/dist/client/_nuxt/3Yx8WcR-.js +1 -0
- package/dist/client/_nuxt/BLO8rZtj.js +31 -0
- package/dist/client/_nuxt/{DggdVF2v.js → CQ1WWl9n.js} +1 -1
- package/dist/client/_nuxt/CudBhkk3.js +1 -0
- package/dist/client/_nuxt/{CW3w6uup.js → D6KmUh4-.js} +1 -1
- package/dist/client/_nuxt/{7fd6vGzb.js → DBeuZS66.js} +1 -1
- package/dist/client/_nuxt/DG73IEBO.js +1 -0
- package/dist/client/_nuxt/DX0ZGhB-.js +1 -0
- package/dist/client/_nuxt/{A1WiD9SJ.js → DaCkt_J7.js} +1 -1
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/69e9f83a-05c7-439f-bf82-0c2d6d83b961.json +1 -0
- package/dist/client/_nuxt/error-404.BRldFSII.css +1 -0
- package/dist/client/_nuxt/error-500.D8yw_IbC.css +1 -0
- package/dist/client/index.html +14 -14
- package/dist/module.d.mts +2 -6
- package/dist/module.d.ts +2 -6
- package/dist/module.json +6 -2
- package/dist/module.mjs +275 -131
- package/dist/runtime/components/GoogleMaps.vue +130 -0
- package/dist/runtime/components/LemonSqueezyButton.vue +28 -0
- package/dist/runtime/components/StripePricingTableEmbed.vue +33 -0
- package/dist/runtime/components/VimeoEmbed.vue +161 -0
- package/dist/runtime/components/YouTubeEmbed.vue +79 -0
- package/dist/runtime/composables/useElementScriptTrigger.d.ts +3 -0
- package/dist/runtime/composables/useElementScriptTrigger.mjs +9 -0
- package/dist/runtime/composables/useScript.d.ts +1 -1
- package/dist/runtime/composables/useScript.mjs +0 -1
- package/dist/runtime/registry/cloudflare-web-analytics.d.ts +9 -7
- package/dist/runtime/registry/cloudflare-web-analytics.mjs +16 -18
- package/dist/runtime/registry/confetti.d.ts +4 -4
- package/dist/runtime/registry/confetti.mjs +11 -8
- package/dist/runtime/registry/facebook-pixel.d.ts +4 -5
- package/dist/runtime/registry/facebook-pixel.mjs +15 -17
- package/dist/runtime/registry/fathom-analytics.d.ts +22 -14
- package/dist/runtime/registry/fathom-analytics.mjs +25 -20
- package/dist/runtime/registry/google-analytics.d.ts +19 -1
- package/dist/runtime/registry/google-analytics.mjs +30 -3
- package/dist/runtime/registry/google-maps.d.ts +21 -1
- package/dist/runtime/registry/google-maps.mjs +40 -3
- package/dist/runtime/registry/google-tag-manager.d.ts +19 -1
- package/dist/runtime/registry/google-tag-manager.mjs +29 -3
- package/dist/runtime/registry/hotjar.d.ts +3 -3
- package/dist/runtime/registry/hotjar.mjs +14 -18
- package/dist/runtime/registry/intercom.d.ts +3 -3
- package/dist/runtime/registry/intercom.mjs +19 -16
- package/dist/runtime/registry/lemon-squeezy.d.ts +66 -0
- package/dist/runtime/registry/lemon-squeezy.mjs +21 -0
- package/dist/runtime/registry/matomo-analytics.d.ts +22 -0
- package/dist/runtime/registry/matomo-analytics.mjs +33 -0
- package/dist/runtime/registry/npm.d.ts +5 -3
- package/dist/runtime/registry/npm.mjs +10 -11
- package/dist/runtime/registry/plausible-analytics.d.ts +20 -0
- package/dist/runtime/registry/plausible-analytics.mjs +35 -0
- package/dist/runtime/registry/segment.d.ts +3 -3
- package/dist/runtime/registry/segment.mjs +34 -34
- package/dist/runtime/registry/stripe.d.ts +16 -0
- package/dist/runtime/registry/stripe.mjs +27 -0
- package/dist/runtime/registry/vimeo-player.d.ts +13 -0
- package/dist/runtime/registry/vimeo-player.mjs +45 -0
- package/dist/runtime/registry/x-pixel.d.ts +39 -0
- package/dist/runtime/registry/x-pixel.mjs +28 -0
- package/dist/runtime/registry/youtube-iframe.d.ts +13 -0
- package/dist/runtime/registry/youtube-iframe.mjs +54 -0
- package/dist/runtime/types.d.ts +31 -15
- package/dist/runtime/utils.d.ts +11 -0
- package/dist/runtime/utils.mjs +30 -1
- package/package.json +34 -23
- package/dist/client/_nuxt/BG_OyJVq.js +0 -1
- package/dist/client/_nuxt/C3YqBJkQ.js +0 -1
- package/dist/client/_nuxt/CKtB_0Vj.js +0 -36
- package/dist/client/_nuxt/CrjQeCwm.js +0 -1
- package/dist/client/_nuxt/D75a3hZQ.js +0 -1
- package/dist/client/_nuxt/builds/meta/7bb27f9d-e4a9-494c-83a3-01bc2df7d17d.json +0 -1
- package/dist/client/_nuxt/error-404.ORekjfyJ.css +0 -1
- package/dist/client/_nuxt/error-500.BIuFL0tW.css +0 -1
- package/dist/client/_nuxt/yr0V4Txy.js +0 -1
- package/dist/runtime/composables/validateScriptInputSchema.d.ts +0 -2
- package/dist/runtime/composables/validateScriptInputSchema.mjs +0 -14
- package/dist/runtime/registry/cloudflare-turnstile.d.ts +0 -1
- package/dist/runtime/registry/cloudflare-turnstile.mjs +0 -4
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { type PropType, computed, ref, watch } from 'vue'
|
|
3
|
+
import { withQuery } from 'ufo'
|
|
4
|
+
import type google from 'google.maps'
|
|
5
|
+
import { defu } from 'defu'
|
|
6
|
+
import type { ElementScriptTrigger } from '../composables/useElementScriptTrigger'
|
|
7
|
+
import { useElementScriptTrigger, useRuntimeConfig, useScriptGoogleMaps } from '#imports'
|
|
8
|
+
|
|
9
|
+
const props = defineProps({
|
|
10
|
+
trigger: { type: String as PropType<ElementScriptTrigger>, required: false, default: 'mouseover' },
|
|
11
|
+
/**
|
|
12
|
+
* Defines the Google Maps API key. Must have access to the Static Maps API as well.
|
|
13
|
+
*
|
|
14
|
+
* @see https://developers.google.com/maps/documentation/javascript/get-api-key
|
|
15
|
+
*/
|
|
16
|
+
apiKey: { type: String, required: true },
|
|
17
|
+
/**
|
|
18
|
+
* Defines map marker location.
|
|
19
|
+
*
|
|
20
|
+
* @example City Hall, New York, NY
|
|
21
|
+
*/
|
|
22
|
+
query: { type: String, required: false, default: '' },
|
|
23
|
+
/**
|
|
24
|
+
* Defines center of the map view.
|
|
25
|
+
*
|
|
26
|
+
* @example 37.4218,-122.0840
|
|
27
|
+
*/
|
|
28
|
+
options: { type: Object as PropType<Omit<google.maps.MapOptions, 'center'>>, required: false, default: undefined },
|
|
29
|
+
/**
|
|
30
|
+
* Defines the width of the map.
|
|
31
|
+
*/
|
|
32
|
+
width: { type: Number, required: false, default: 500 },
|
|
33
|
+
/**
|
|
34
|
+
* Defines the height of the map
|
|
35
|
+
*/
|
|
36
|
+
height: { type: Number, required: false, default: 400 },
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
const apiKey = props.apiKey || useRuntimeConfig().public.scripts?.googleMaps?.apikey
|
|
40
|
+
|
|
41
|
+
if (!apiKey)
|
|
42
|
+
throw new Error('GoogleMaps requires an API key')
|
|
43
|
+
if (!props.query && !props.options?.center)
|
|
44
|
+
throw new Error('GoogleMaps requires either a query or center option')
|
|
45
|
+
|
|
46
|
+
const elMap = ref<HTMLElement>()
|
|
47
|
+
|
|
48
|
+
const { $script } = useScriptGoogleMaps({
|
|
49
|
+
apiKey: props.apiKey,
|
|
50
|
+
scriptOptions: {
|
|
51
|
+
trigger: useElementScriptTrigger(props.trigger, elMap),
|
|
52
|
+
},
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const options = computed(() => {
|
|
56
|
+
return defu(props.options, {
|
|
57
|
+
zoom: 15,
|
|
58
|
+
mapId: 'map',
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
const ready = ref(false)
|
|
62
|
+
|
|
63
|
+
function queryMaps(maps: google.maps, marker: google.maps.MarkerLibrary, map: google.maps.Map) {
|
|
64
|
+
const request = {
|
|
65
|
+
query: props.query,
|
|
66
|
+
fields: ['name', 'geometry'],
|
|
67
|
+
}
|
|
68
|
+
const markers: google.maps.AdvancedMarkerElement[] = []
|
|
69
|
+
const service = new maps.places.PlacesService(map)
|
|
70
|
+
service.findPlaceFromQuery(request, (results, status) => {
|
|
71
|
+
if (status === maps.places.PlacesServiceStatus.OK && results) {
|
|
72
|
+
for (let i = 0; i < results.length; i++) {
|
|
73
|
+
const location = results[i].geometry?.location
|
|
74
|
+
location && markers.push(
|
|
75
|
+
new marker.AdvancedMarkerElement({
|
|
76
|
+
map,
|
|
77
|
+
position: location,
|
|
78
|
+
}),
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (results[0].geometry?.location)
|
|
83
|
+
markers[0] && map.setCenter(results[0].geometry.location)
|
|
84
|
+
ready.value = true
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// create the map
|
|
90
|
+
$script.then(async (instance) => {
|
|
91
|
+
const maps = await instance.maps
|
|
92
|
+
const marker = await maps.importLibrary('marker') as google.maps.MarkerLibrary
|
|
93
|
+
|
|
94
|
+
const mapDiv = document.createElement('div')
|
|
95
|
+
mapDiv.style.width = '100%'
|
|
96
|
+
mapDiv.style.height = '100%'
|
|
97
|
+
const _ = watch(ready, (v) => {
|
|
98
|
+
v && elMap.value?.appendChild(mapDiv)
|
|
99
|
+
_()
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
const map = new maps.Map(mapDiv, options.value)
|
|
103
|
+
watch(options, () => map.setOptions(options.value))
|
|
104
|
+
watch(() => props.query, () => {
|
|
105
|
+
queryMaps(maps, marker, map)
|
|
106
|
+
}, {
|
|
107
|
+
immediate: !!props.query,
|
|
108
|
+
})
|
|
109
|
+
if (!props.query)
|
|
110
|
+
ready.value = true
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
const poster = computed(() => {
|
|
114
|
+
return withQuery('https://maps.googleapis.com/maps/api/staticmap', {
|
|
115
|
+
center: props.query, // will be overriden by options if they were set
|
|
116
|
+
size: `${props.width}x${props.height}`,
|
|
117
|
+
key: apiKey,
|
|
118
|
+
scale: 2, // we assume a high DPI to avoid hydration issues
|
|
119
|
+
...options.value,
|
|
120
|
+
})
|
|
121
|
+
})
|
|
122
|
+
</script>
|
|
123
|
+
|
|
124
|
+
<template>
|
|
125
|
+
<div ref="elMap" :style="{ width: `${width}px`, height: `${height}px`, position: 'relative' }">
|
|
126
|
+
<slot>
|
|
127
|
+
<img v-if="!ready" :src="poster" title="" :width="width" :height="height">
|
|
128
|
+
</slot>
|
|
129
|
+
</div>
|
|
130
|
+
</template>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { useScriptLemonSqueezy } from '#imports'
|
|
3
|
+
|
|
4
|
+
defineProps<{
|
|
5
|
+
href: string
|
|
6
|
+
}>()
|
|
7
|
+
|
|
8
|
+
const emits = defineEmits<{
|
|
9
|
+
event: [{ event: string, data?: Record<string, any> }]
|
|
10
|
+
}>()
|
|
11
|
+
|
|
12
|
+
const instance = useScriptLemonSqueezy()
|
|
13
|
+
instance.Setup({
|
|
14
|
+
eventHandler(event) {
|
|
15
|
+
emits('event', event)
|
|
16
|
+
},
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
defineExpose({
|
|
20
|
+
instance,
|
|
21
|
+
})
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<template>
|
|
25
|
+
<a :href="href" class="lemonsqueezy-button">
|
|
26
|
+
<slot />
|
|
27
|
+
</a>
|
|
28
|
+
</template>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import type { ElementScriptTrigger } from '../composables/useElementScriptTrigger'
|
|
4
|
+
import { useElementScriptTrigger, useScript } from '#imports'
|
|
5
|
+
|
|
6
|
+
const props = defineProps<{
|
|
7
|
+
trigger?: ElementScriptTrigger
|
|
8
|
+
publishableKey: string
|
|
9
|
+
pricingTableId: string
|
|
10
|
+
clientReferenceId?: string
|
|
11
|
+
customerEmail?: string
|
|
12
|
+
customerSessionClientSecret?: string
|
|
13
|
+
}>()
|
|
14
|
+
|
|
15
|
+
const table = ref()
|
|
16
|
+
useScript(`https://js.stripe.com/v3/pricing-table.js`, {
|
|
17
|
+
trigger: useElementScriptTrigger(props.trigger, table),
|
|
18
|
+
})
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<template>
|
|
22
|
+
<ClientOnly>
|
|
23
|
+
<stripe-pricing-table
|
|
24
|
+
ref="table"
|
|
25
|
+
v-bind="$attrs"
|
|
26
|
+
:publishable-key="publishableKey"
|
|
27
|
+
:pricing-table-id="pricingTableId"
|
|
28
|
+
:client-reference-id="clientReferenceId"
|
|
29
|
+
:customer-email="customerEmail"
|
|
30
|
+
:customer-session-client-secret="customerSessionClientSecret"
|
|
31
|
+
/>
|
|
32
|
+
</ClientOnly>
|
|
33
|
+
</template>
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, onBeforeUnmount, ref, watch } from 'vue'
|
|
3
|
+
import type Player from 'vimeo__player'
|
|
4
|
+
import type { EventMap, VimeoVideoQuality } from 'vimeo__player'
|
|
5
|
+
import type { ElementScriptTrigger } from '../composables/useElementScriptTrigger'
|
|
6
|
+
import { useAsyncData, useElementScriptTrigger, useScriptVimeoPlayer } from '#imports'
|
|
7
|
+
|
|
8
|
+
const props = withDefaults(defineProps<{
|
|
9
|
+
// custom
|
|
10
|
+
trigger?: ElementScriptTrigger
|
|
11
|
+
// copied from @types/vimeo__player
|
|
12
|
+
id: number | undefined
|
|
13
|
+
url?: string | undefined
|
|
14
|
+
autopause?: boolean | undefined
|
|
15
|
+
autoplay?: boolean | undefined
|
|
16
|
+
background?: boolean | undefined
|
|
17
|
+
byline?: boolean | undefined
|
|
18
|
+
color?: string | undefined
|
|
19
|
+
controls?: boolean | undefined
|
|
20
|
+
dnt?: boolean | undefined
|
|
21
|
+
height?: number | undefined
|
|
22
|
+
// eslint-disable-next-line vue/prop-name-casing
|
|
23
|
+
interactive_params?: string | undefined
|
|
24
|
+
keyboard?: boolean | undefined
|
|
25
|
+
loop?: boolean | undefined
|
|
26
|
+
maxheight?: number | undefined
|
|
27
|
+
maxwidth?: number | undefined
|
|
28
|
+
muted?: boolean | undefined
|
|
29
|
+
pip?: boolean | undefined
|
|
30
|
+
playsinline?: boolean | undefined
|
|
31
|
+
portrait?: boolean | undefined
|
|
32
|
+
responsive?: boolean | undefined
|
|
33
|
+
speed?: boolean | undefined
|
|
34
|
+
quality?: VimeoVideoQuality | undefined
|
|
35
|
+
texttrack?: string | undefined
|
|
36
|
+
title?: boolean | undefined
|
|
37
|
+
transparent?: boolean | undefined
|
|
38
|
+
width?: number | undefined
|
|
39
|
+
}>(), {
|
|
40
|
+
trigger: 'mouseover',
|
|
41
|
+
width: 640,
|
|
42
|
+
height: 480,
|
|
43
|
+
loop: false,
|
|
44
|
+
controls: true,
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
const emits = defineEmits<{
|
|
48
|
+
play: [e: EventMap['play'], player: Player]
|
|
49
|
+
playing: [e: EventMap['playing'], player: Player]
|
|
50
|
+
pause: [e: EventMap['pause'], player: Player]
|
|
51
|
+
ended: [e: EventMap['ended'], player: Player]
|
|
52
|
+
timeupdate: [e: EventMap['timeupdate'], player: Player]
|
|
53
|
+
progress: [e: EventMap['progress'], player: Player]
|
|
54
|
+
seeking: [e: EventMap['seeking'], player: Player]
|
|
55
|
+
seeked: [e: EventMap['seeked'], player: Player]
|
|
56
|
+
texttrackchange: [e: EventMap['texttrackchange'], player: Player]
|
|
57
|
+
chapterchange: [e: EventMap['chapterchange'], player: Player]
|
|
58
|
+
cuechange: [e: EventMap['cuechange'], player: Player]
|
|
59
|
+
cuepoint: [e: EventMap['cuepoint'], player: Player]
|
|
60
|
+
volumechange: [e: EventMap['volumechange'], player: Player]
|
|
61
|
+
playbackratechange: [e: EventMap['playbackratechange'], player: Player]
|
|
62
|
+
bufferstart: [e: EventMap['bufferstart'], player: Player]
|
|
63
|
+
bufferend: [e: EventMap['bufferend'], player: Player]
|
|
64
|
+
error: [e: EventMap['error'], player: Player]
|
|
65
|
+
loaded: [e: EventMap['loaded'], player: Player]
|
|
66
|
+
durationchange: [e: EventMap['durationchange'], player: Player]
|
|
67
|
+
fullscreenchange: [e: EventMap['fullscreenchange'], player: Player]
|
|
68
|
+
qualitychange: [e: EventMap['qualitychange'], player: Player]
|
|
69
|
+
camerachange: [e: EventMap['camerachange'], player: Player]
|
|
70
|
+
resize: [e: EventMap['resize'], player: Player]
|
|
71
|
+
enterpictureinpicture: [e: EventMap['enterpictureinpicture'], player: Player]
|
|
72
|
+
leavepictureinpicture: [e: EventMap['leavepictureinpicture'], player: Player]
|
|
73
|
+
}>()
|
|
74
|
+
|
|
75
|
+
const events = [
|
|
76
|
+
'play',
|
|
77
|
+
'playing',
|
|
78
|
+
'pause',
|
|
79
|
+
'ended',
|
|
80
|
+
'timeupdate',
|
|
81
|
+
'progress',
|
|
82
|
+
'seeking',
|
|
83
|
+
'seeked',
|
|
84
|
+
'texttrackchange',
|
|
85
|
+
'chapterchange',
|
|
86
|
+
'cuechange',
|
|
87
|
+
'cuepoint',
|
|
88
|
+
'volumechange',
|
|
89
|
+
'playbackratechange',
|
|
90
|
+
'bufferstart',
|
|
91
|
+
'bufferend',
|
|
92
|
+
'error',
|
|
93
|
+
'loaded',
|
|
94
|
+
'durationchange',
|
|
95
|
+
'fullscreenchange',
|
|
96
|
+
'qualitychange',
|
|
97
|
+
'camerachange',
|
|
98
|
+
'resize',
|
|
99
|
+
]
|
|
100
|
+
|
|
101
|
+
const elVimeo = ref()
|
|
102
|
+
const root = ref()
|
|
103
|
+
|
|
104
|
+
const ready = ref(false)
|
|
105
|
+
const { $script } = useScriptVimeoPlayer({
|
|
106
|
+
scriptOptions: {
|
|
107
|
+
trigger: useElementScriptTrigger(props.trigger, root.value),
|
|
108
|
+
},
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
const { data: payload } = useAsyncData(
|
|
112
|
+
`vimeo-embed:${props.id}`,
|
|
113
|
+
// TODO ideally we cache this
|
|
114
|
+
() => $fetch(`https://vimeo.com/api/v2/video/${props.id}.json`).then(res => res[0]),
|
|
115
|
+
{
|
|
116
|
+
watch: [() => props.id],
|
|
117
|
+
},
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
const poster = computed(() => {
|
|
121
|
+
const { width, height } = props
|
|
122
|
+
// 2 dpi for retina, this is safest while SSR
|
|
123
|
+
return payload.value.thumbnail_large.replace(/-d_[\dx]+$/i, `-d_${Math.round(width * 2)}x${Math.round(height * 2)}`)
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
let player: Player
|
|
127
|
+
$script.then(({ Player }) => {
|
|
128
|
+
// filter props for false values
|
|
129
|
+
player = Player(elVimeo.value, {
|
|
130
|
+
...props,
|
|
131
|
+
url: encodeURI(`https://vimeo.com/${props.id}`),
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
events.forEach((event) => {
|
|
135
|
+
player.on(event, (e: any) => {
|
|
136
|
+
emits(event as keyof typeof emits, e, player)
|
|
137
|
+
if (event === 'loaded')
|
|
138
|
+
ready.value = true
|
|
139
|
+
})
|
|
140
|
+
})
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
onBeforeUnmount(() => player?.unload())
|
|
144
|
+
|
|
145
|
+
defineExpose({
|
|
146
|
+
player,
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
watch(() => props.id, (v) => {
|
|
150
|
+
v && player?.loadVideo(v)
|
|
151
|
+
})
|
|
152
|
+
</script>
|
|
153
|
+
|
|
154
|
+
<template>
|
|
155
|
+
<div ref="root" :style="{ width: `${width}px`, height: `${height}px`, position: 'relative' }">
|
|
156
|
+
<div v-show="ready" ref="elVimeo" style="width: 100%; height: 100%;" />
|
|
157
|
+
<slot v-bind="payload" :poster="poster">
|
|
158
|
+
<img v-if="!ready" :src="poster" v-bind="trigger ? { loading: 'lazy' } : {}" :width="width" :height="height" :style="{ aspectRatio: '4/3', cursor: $script.status.value !== 'awaitingLoad' ? 'wait' : '' }">
|
|
159
|
+
</slot>
|
|
160
|
+
</div>
|
|
161
|
+
</template>
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, ref, watch } from 'vue'
|
|
3
|
+
import type YT from 'youtube'
|
|
4
|
+
import type { ElementScriptTrigger } from '../composables/useElementScriptTrigger'
|
|
5
|
+
import { useElementScriptTrigger, useScriptYouTubeIframe } from '#imports'
|
|
6
|
+
|
|
7
|
+
const props = withDefaults(defineProps<{
|
|
8
|
+
trigger?: ElementScriptTrigger
|
|
9
|
+
videoId: string
|
|
10
|
+
playerVars?: YT.PlayerVars
|
|
11
|
+
width?: number
|
|
12
|
+
height?: number
|
|
13
|
+
}>(), {
|
|
14
|
+
playerVars: { autoplay: 1, playsinline: 1 },
|
|
15
|
+
width: 640,
|
|
16
|
+
height: 480,
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
const emits = defineEmits<{
|
|
20
|
+
onReady: [e: YT.PlayerEvent]
|
|
21
|
+
onStateChange: [e: YT.PlayerEvent]
|
|
22
|
+
onPlaybackQualityChange: [e: YT.PlayerEvent]
|
|
23
|
+
onPlaybackRateChange: [e: YT.PlayerEvent]
|
|
24
|
+
onError: [e: YT.PlayerEvent]
|
|
25
|
+
onApiChange: [e: YT.PlayerEvent]
|
|
26
|
+
}>()
|
|
27
|
+
const events: (keyof YT.Events)[] = [
|
|
28
|
+
'onReady',
|
|
29
|
+
'onStateChange',
|
|
30
|
+
'onPlaybackQualityChange',
|
|
31
|
+
'onPlaybackRateChange',
|
|
32
|
+
'onError',
|
|
33
|
+
'onApiChange',
|
|
34
|
+
]
|
|
35
|
+
const elYoutube = ref()
|
|
36
|
+
|
|
37
|
+
const ready = ref(false)
|
|
38
|
+
const { $script } = useScriptYouTubeIframe({
|
|
39
|
+
scriptOptions: {
|
|
40
|
+
trigger: useElementScriptTrigger(props.trigger, elYoutube.value),
|
|
41
|
+
},
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
let player: YT.Player
|
|
45
|
+
$script.then(async (instance) => {
|
|
46
|
+
const YT = await instance.YT
|
|
47
|
+
await new Promise<void>((resolve) => {
|
|
48
|
+
if (typeof YT.Player === 'undefined')
|
|
49
|
+
YT.ready(resolve)
|
|
50
|
+
else
|
|
51
|
+
resolve()
|
|
52
|
+
})
|
|
53
|
+
player = new YT.Player(elYoutube.value, {
|
|
54
|
+
...props,
|
|
55
|
+
events: Object.fromEntries(events.map(event => [event, (e: any) => {
|
|
56
|
+
// @ts-expect-error untyped
|
|
57
|
+
emits(event, e)
|
|
58
|
+
}])),
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
defineExpose({
|
|
63
|
+
player,
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
watch(() => props.videoId, () => {
|
|
67
|
+
player?.loadVideoById(props.videoId)
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
const poster = computed(() => `https://i.ytimg.com/vi_webp/${props.videoId}/sddefault.webp`)
|
|
71
|
+
</script>
|
|
72
|
+
|
|
73
|
+
<template>
|
|
74
|
+
<div ref="elYoutube" :style="{ width: `${width}px`, height: `${height}px`, position: 'relative' }">
|
|
75
|
+
<slot :poster="poster">
|
|
76
|
+
<img v-if="!ready" :src="poster" title="" :width="width" :height="height">
|
|
77
|
+
</slot>
|
|
78
|
+
</div>
|
|
79
|
+
</template>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { useElementHover, useElementVisibility, watchOnce } from "@vueuse/core";
|
|
2
|
+
import { ref } from "vue";
|
|
3
|
+
export function useElementScriptTrigger(trigger, el) {
|
|
4
|
+
if (import.meta.server || !el)
|
|
5
|
+
return new Promise(() => {
|
|
6
|
+
});
|
|
7
|
+
const activeRef = trigger ? trigger === "mouseover" ? useElementHover(el) : useElementVisibility(el) : ref(false);
|
|
8
|
+
return trigger ? new Promise((resolve) => watchOnce(activeRef, resolve)) : Promise.resolve();
|
|
9
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type UseScriptInput, type VueScriptInstance } from '@unhead/vue';
|
|
2
2
|
import type { NuxtUseScriptOptions } from '#nuxt-scripts';
|
|
3
3
|
export declare function useScript<T>(input: UseScriptInput, options?: NuxtUseScriptOptions): T & {
|
|
4
|
-
$script: VueScriptInstance<T>;
|
|
4
|
+
$script: VueScriptInstance<T> & Promise<T>;
|
|
5
5
|
};
|
|
@@ -10,7 +10,6 @@ export function useScript(input, options) {
|
|
|
10
10
|
const nuxtApp = useNuxtApp();
|
|
11
11
|
const id = input.key || input.src || hashCode(typeof input.innerHTML === "string" ? input.innerHTML : "");
|
|
12
12
|
if (!nuxtApp.scripts?.[id]) {
|
|
13
|
-
options.beforeInit?.();
|
|
14
13
|
if (import.meta.client) {
|
|
15
14
|
performance?.mark?.("mark_feature_usage", {
|
|
16
15
|
detail: {
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import type { RegistryScriptInput } from '#nuxt-scripts';
|
|
2
|
+
/**
|
|
3
|
+
* Sample:
|
|
4
|
+
* <!-- Cloudflare Web Analytics -->
|
|
5
|
+
* <script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "12ee46bf598b45c2868bbc07a3073f58"}'></script>
|
|
6
|
+
* <!-- End Cloudflare Web Analytics -->
|
|
7
|
+
*/
|
|
3
8
|
export interface CloudflareWebAnalyticsApi {
|
|
4
9
|
__cfBeacon: {
|
|
5
10
|
load: 'single';
|
|
6
11
|
spa: boolean;
|
|
7
12
|
token: string;
|
|
8
13
|
};
|
|
9
|
-
__cfRl?: unknown;
|
|
10
14
|
}
|
|
11
15
|
declare global {
|
|
12
16
|
interface Window extends CloudflareWebAnalyticsApi {
|
|
@@ -15,8 +19,6 @@ declare global {
|
|
|
15
19
|
export declare const CloudflareWebAnalyticsOptions: import("valibot").ObjectSchema<{
|
|
16
20
|
/**
|
|
17
21
|
* The Cloudflare Web Analytics token.
|
|
18
|
-
*
|
|
19
|
-
* Required when used for the first time.
|
|
20
22
|
*/
|
|
21
23
|
token: import("valibot").StringSchema<string>;
|
|
22
24
|
/**
|
|
@@ -30,5 +32,5 @@ export declare const CloudflareWebAnalyticsOptions: import("valibot").ObjectSche
|
|
|
30
32
|
token: string;
|
|
31
33
|
spa?: boolean | undefined;
|
|
32
34
|
}>;
|
|
33
|
-
export type CloudflareWebAnalyticsInput =
|
|
34
|
-
export declare function useScriptCloudflareWebAnalytics<T extends CloudflareWebAnalyticsApi>(
|
|
35
|
+
export type CloudflareWebAnalyticsInput = RegistryScriptInput<typeof CloudflareWebAnalyticsOptions>;
|
|
36
|
+
export declare function useScriptCloudflareWebAnalytics<T extends CloudflareWebAnalyticsApi>(_options?: CloudflareWebAnalyticsInput): any;
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { boolean, minLength, object, optional, string } from "valibot";
|
|
2
2
|
import { defu } from "defu";
|
|
3
|
-
import {
|
|
3
|
+
import { registryScript } from "../utils.mjs";
|
|
4
4
|
export const CloudflareWebAnalyticsOptions = object({
|
|
5
5
|
/**
|
|
6
6
|
* The Cloudflare Web Analytics token.
|
|
7
|
-
*
|
|
8
|
-
* Required when used for the first time.
|
|
9
7
|
*/
|
|
10
|
-
token: string([minLength(
|
|
8
|
+
token: string([minLength(32)]),
|
|
11
9
|
/**
|
|
12
10
|
* Cloudflare Web Analytics enables measuring SPAs automatically by overriding the History API’s pushState function
|
|
13
11
|
* and listening to the onpopstate. Hash-based router is not supported.
|
|
@@ -16,19 +14,19 @@ export const CloudflareWebAnalyticsOptions = object({
|
|
|
16
14
|
*/
|
|
17
15
|
spa: optional(boolean())
|
|
18
16
|
});
|
|
19
|
-
export function useScriptCloudflareWebAnalytics(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
17
|
+
export function useScriptCloudflareWebAnalytics(_options) {
|
|
18
|
+
return registryScript("cloudflareWebAnalytics", (options) => ({
|
|
19
|
+
scriptInput: {
|
|
20
|
+
"src": "https://static.cloudflareinsights.com/beacon.min.js",
|
|
21
|
+
"data-cf-beacon": JSON.stringify(defu(options, { spa: true }))
|
|
22
|
+
},
|
|
23
|
+
schema: import.meta.dev ? CloudflareWebAnalyticsOptions : void 0,
|
|
24
|
+
scriptOptions: {
|
|
25
|
+
// we want to load earlier so that the web vitals reports are correct
|
|
26
|
+
trigger: "client",
|
|
27
|
+
use() {
|
|
28
|
+
return { __cfBeacon: window.__cfBeacon };
|
|
29
|
+
}
|
|
32
30
|
}
|
|
33
|
-
});
|
|
31
|
+
}), _options);
|
|
34
32
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { NuxtUseScriptIntegrationOptions } from '#nuxt-scripts';
|
|
1
|
+
import type { RegistryScriptInput } from '#nuxt-scripts';
|
|
3
2
|
export interface ConfettiApi {
|
|
4
3
|
addConfetti: (options?: {
|
|
5
4
|
emojis: string[];
|
|
@@ -16,8 +15,9 @@ export declare const ConfettiOptions: import("valibot").ObjectSchema<Pick<{
|
|
|
16
15
|
packageName: import("valibot").StringSchema<string>;
|
|
17
16
|
file: import("valibot").OptionalSchema<import("valibot").StringSchema<string>, undefined, string | undefined>;
|
|
18
17
|
version: import("valibot").OptionalSchema<import("valibot").StringSchema<string>, undefined, string | undefined>;
|
|
18
|
+
type: import("valibot").OptionalSchema<import("valibot").StringSchema<string>, undefined, string | undefined>;
|
|
19
19
|
}, "version">, undefined, {
|
|
20
20
|
version?: string | undefined;
|
|
21
21
|
}>;
|
|
22
|
-
export type ConfettiInput =
|
|
23
|
-
export declare function useScriptConfetti(options
|
|
22
|
+
export type ConfettiInput = RegistryScriptInput<typeof ConfettiOptions>;
|
|
23
|
+
export declare function useScriptConfetti<T extends ConfettiApi>(options?: ConfettiInput): any;
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { pick } from "valibot";
|
|
2
2
|
import { NpmOptions, useScriptNpm } from "./npm.mjs";
|
|
3
3
|
export const ConfettiOptions = pick(NpmOptions, ["version"]);
|
|
4
|
-
export function useScriptConfetti(options
|
|
5
|
-
return useScriptNpm({
|
|
4
|
+
export function useScriptConfetti(options) {
|
|
5
|
+
return useScriptNpm("js-confetti", {
|
|
6
|
+
// ...options,
|
|
6
7
|
packageName: "js-confetti",
|
|
7
|
-
version: options
|
|
8
|
+
version: options?.version,
|
|
8
9
|
file: "dist/js-confetti.browser.js"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
// scriptOptions: {
|
|
11
|
+
// use() {
|
|
12
|
+
// if (typeof window.JSConfetti === 'undefined')
|
|
13
|
+
// return null
|
|
14
|
+
// return new window.JSConfetti()
|
|
15
|
+
// },
|
|
16
|
+
// },
|
|
14
17
|
});
|
|
15
18
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { NuxtUseScriptIntegrationOptions } from '#nuxt-scripts';
|
|
1
|
+
import type { RegistryScriptInput } from '#nuxt-scripts';
|
|
3
2
|
type StandardEvents = 'AddPaymentInfo' | 'AddToCart' | 'AddToWishlist' | 'CompleteRegistration' | 'Contact' | 'CustomizeProduct' | 'Donate' | 'FindLocation' | 'InitiateCheckout' | 'Lead' | 'Purchase' | 'Schedule' | 'Search' | 'StartTrial' | 'SubmitApplication' | 'Subscribe' | 'ViewContent';
|
|
4
3
|
interface EventObjectProperties {
|
|
5
4
|
content_category?: string;
|
|
@@ -34,10 +33,10 @@ declare global {
|
|
|
34
33
|
}
|
|
35
34
|
}
|
|
36
35
|
export declare const FacebookPixelOptions: import("valibot").ObjectSchema<{
|
|
37
|
-
id: import("valibot").UnionSchema<(import("valibot").
|
|
36
|
+
id: import("valibot").UnionSchema<(import("valibot").NumberSchema<number> | import("valibot").StringSchema<string>)[], string | number>;
|
|
38
37
|
}, undefined, {
|
|
39
38
|
id: string | number;
|
|
40
39
|
}>;
|
|
41
|
-
export type FacebookPixelInput =
|
|
42
|
-
export declare function useScriptFacebookPixel<T extends FacebookPixelApi>(
|
|
40
|
+
export type FacebookPixelInput = RegistryScriptInput<typeof FacebookPixelOptions>;
|
|
41
|
+
export declare function useScriptFacebookPixel<T extends FacebookPixelApi>(_options?: FacebookPixelInput): any;
|
|
43
42
|
export {};
|
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
import { number, object, string, union } from "valibot";
|
|
2
|
-
import {
|
|
2
|
+
import { registryScript } from "../utils.mjs";
|
|
3
|
+
import { FacebookPixelScriptResolver } from "../../registry";
|
|
3
4
|
export const FacebookPixelOptions = object({
|
|
4
5
|
id: union([string(), number()])
|
|
5
6
|
});
|
|
6
|
-
export function useScriptFacebookPixel(
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
export function useScriptFacebookPixel(_options) {
|
|
8
|
+
return registryScript("facebookPixel", (options) => ({
|
|
9
|
+
scriptInput: {
|
|
10
|
+
src: FacebookPixelScriptResolver()
|
|
11
|
+
},
|
|
12
|
+
schema: FacebookPixelOptions,
|
|
13
|
+
scriptOptions: {
|
|
14
|
+
use() {
|
|
15
|
+
return { fbq: window.fbq };
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
clientInit: import.meta.server ? void 0 : () => {
|
|
11
19
|
const fbq = window.fbq = function(...params) {
|
|
12
20
|
fbq.callMethod ? fbq.callMethod(...params) : fbq.queue.push(params);
|
|
13
21
|
};
|
|
@@ -20,15 +28,5 @@ export function useScriptFacebookPixel(options, _scriptOptions) {
|
|
|
20
28
|
fbq("init", options?.id);
|
|
21
29
|
fbq("track", "PageView");
|
|
22
30
|
}
|
|
23
|
-
|
|
24
|
-
};
|
|
25
|
-
return useScript({
|
|
26
|
-
key: "facebookPixel",
|
|
27
|
-
src: "https://connect.facebook.net/en_US/fbevents.js"
|
|
28
|
-
}, {
|
|
29
|
-
...scriptOptions,
|
|
30
|
-
use() {
|
|
31
|
-
return { fbq: window.fbq };
|
|
32
|
-
}
|
|
33
|
-
});
|
|
31
|
+
}), _options);
|
|
34
32
|
}
|