@nuxt/scripts 0.6.5 → 0.7.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 +1 -1
- package/dist/client/200.html +9 -9
- package/dist/client/404.html +9 -9
- package/dist/client/_nuxt/{D3k5CjNA.js → BW5_3H_7.js} +1 -1
- package/dist/client/_nuxt/{D9Ze639F.js → CObySb1Z.js} +1 -1
- package/dist/client/_nuxt/Cdyv1BV6.js +31 -0
- package/dist/client/_nuxt/{D6UD5WyS.js → DPxoUSuY.js} +1 -1
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/b4af023e-aaec-4265-8ade-ce133bb4c4c3.json +1 -0
- package/dist/client/_nuxt/entry.FVeyw1Qn.css +1 -0
- package/dist/client/_nuxt/error-404.D8Cdd2Pl.css +1 -0
- package/dist/client/_nuxt/error-500.BENoupyF.css +1 -0
- package/dist/client/index.html +9 -9
- package/dist/module.d.mts +2 -10
- package/dist/module.d.ts +2 -10
- package/dist/module.json +2 -2
- package/dist/module.mjs +13 -4
- package/dist/runtime/components/ScriptCrisp.vue +10 -7
- package/dist/runtime/components/ScriptGoogleAdsense.vue +7 -7
- package/dist/runtime/components/ScriptGoogleMaps.vue +224 -66
- package/dist/runtime/components/ScriptIntercom.vue +10 -7
- package/dist/runtime/components/ScriptLemonSqueezy.vue +1 -1
- package/dist/runtime/components/ScriptStripePricingTable.vue +6 -6
- package/dist/runtime/components/ScriptVimeoPlayer.vue +62 -38
- package/dist/runtime/components/ScriptYouTubePlayer.vue +9 -9
- package/dist/runtime/composables/useScript.d.ts +6 -1
- package/dist/runtime/composables/useScript.js +8 -8
- package/dist/runtime/composables/useScriptEventPage.d.ts +2 -2
- package/dist/runtime/composables/useScriptEventPage.js +6 -5
- package/dist/runtime/registry/clarity.d.ts +1 -12
- package/dist/runtime/registry/cloudflare-web-analytics.d.ts +1 -3
- package/dist/runtime/registry/crisp.d.ts +1 -3
- package/dist/runtime/registry/fathom-analytics.d.ts +1 -3
- package/dist/runtime/registry/google-adsense.d.ts +1 -3
- package/dist/runtime/registry/google-analytics.d.ts +2 -10
- package/dist/runtime/registry/google-analytics.js +6 -3
- package/dist/runtime/registry/google-maps.d.ts +2 -4
- package/dist/runtime/registry/google-maps.js +1 -3
- package/dist/runtime/registry/google-tag-manager.d.ts +2 -10
- package/dist/runtime/registry/hotjar.d.ts +1 -3
- package/dist/runtime/registry/intercom.d.ts +1 -3
- package/dist/runtime/registry/lemon-squeezy.d.ts +1 -3
- package/dist/runtime/registry/matomo-analytics.d.ts +1 -3
- package/dist/runtime/registry/matomo-analytics.js +6 -2
- package/dist/runtime/registry/meta-pixel.d.ts +2 -3
- package/dist/runtime/registry/meta-pixel.js +5 -1
- package/dist/runtime/registry/npm.d.ts +1 -3
- package/dist/runtime/registry/plausible-analytics.d.ts +1 -3
- package/dist/runtime/registry/segment.d.ts +2 -5
- package/dist/runtime/registry/stripe.d.ts +1 -3
- package/dist/runtime/registry/vimeo-player.d.ts +1 -3
- package/dist/runtime/registry/vimeo-player.js +1 -1
- package/dist/runtime/registry/x-pixel.d.ts +1 -3
- package/dist/runtime/registry/x-pixel.js +6 -2
- package/dist/runtime/registry/youtube-player.d.ts +1 -3
- package/dist/runtime/registry/youtube-player.js +1 -1
- package/dist/runtime/types.d.ts +5 -5
- package/dist/runtime/types.js +1 -1
- package/dist/runtime/utils.d.ts +2 -4
- package/package.json +41 -37
- package/dist/client/_nuxt/BA8oXX6l.js +0 -31
- package/dist/client/_nuxt/builds/meta/a5c6ec68-62ae-43af-96d0-bdd9f64f38b1.json +0 -1
- package/dist/client/_nuxt/entry.Cts5wDvr.css +0 -1
- package/dist/client/_nuxt/error-404.-RjlvToe.css +0 -1
- package/dist/client/_nuxt/error-500.Bz7LXgZy.css +0 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
/// <reference types="google.maps" />
|
|
3
|
-
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
|
3
|
+
import { computed, onBeforeUnmount, onMounted, ref, watch, toRaw } from 'vue'
|
|
4
4
|
import type { HTMLAttributes, ImgHTMLAttributes, Ref, ReservedProps } from 'vue'
|
|
5
5
|
import { withQuery } from 'ufo'
|
|
6
6
|
import type { QueryObject } from 'ufo'
|
|
7
7
|
import { defu } from 'defu'
|
|
8
|
+
import { hash } from 'ohash'
|
|
8
9
|
import type { ElementScriptTrigger } from '../types'
|
|
9
10
|
import { scriptRuntimeConfig } from '../utils'
|
|
10
11
|
import { useScriptTriggerElement } from '../composables/useScriptTriggerElement'
|
|
@@ -44,15 +45,19 @@ const props = withDefaults(defineProps<{
|
|
|
44
45
|
/**
|
|
45
46
|
* Defines the Google Maps API key. Must have access to the Static Maps API as well.
|
|
46
47
|
*/
|
|
47
|
-
apiKey
|
|
48
|
+
apiKey?: string
|
|
48
49
|
/**
|
|
49
|
-
*
|
|
50
|
+
* A latitude / longitude of where to focus the map.
|
|
50
51
|
*/
|
|
51
|
-
|
|
52
|
+
center?: google.maps.LatLng | google.maps.LatLngLiteral | `${string},${string}`
|
|
53
|
+
/**
|
|
54
|
+
* Should a marker be displayed on the map where the centre is.
|
|
55
|
+
*/
|
|
56
|
+
centerMarker?: boolean
|
|
52
57
|
/**
|
|
53
58
|
* Options for the map.
|
|
54
59
|
*/
|
|
55
|
-
|
|
60
|
+
mapOptions?: google.maps.MapOptions
|
|
56
61
|
/**
|
|
57
62
|
* Defines the width of the map.
|
|
58
63
|
*/
|
|
@@ -75,30 +80,39 @@ const props = withDefaults(defineProps<{
|
|
|
75
80
|
* Customize the root element attributes.
|
|
76
81
|
*/
|
|
77
82
|
rootAttrs?: HTMLAttributes & ReservedProps & Record<string, unknown>
|
|
83
|
+
/**
|
|
84
|
+
* Extra Markers to add to the map.
|
|
85
|
+
*/
|
|
86
|
+
markers?: (`${string},${string}` | google.maps.marker.AdvancedMarkerElementOptions)[]
|
|
78
87
|
}>(), {
|
|
79
88
|
// @ts-expect-error untyped
|
|
80
89
|
trigger: ['mouseenter', 'mouseover', 'mousedown'],
|
|
81
|
-
width:
|
|
90
|
+
width: 640,
|
|
82
91
|
height: 400,
|
|
92
|
+
centerMarker: true,
|
|
83
93
|
})
|
|
84
94
|
|
|
85
95
|
const emits = defineEmits<{
|
|
86
96
|
// our emit
|
|
87
|
-
ready: [e:
|
|
97
|
+
ready: [e: typeof googleMaps]
|
|
88
98
|
error: []
|
|
89
99
|
}>()
|
|
90
100
|
|
|
91
101
|
const apiKey = props.apiKey || scriptRuntimeConfig('googleMaps')?.apiKey
|
|
92
102
|
|
|
93
|
-
|
|
103
|
+
const mapsApi = ref<typeof google.maps | undefined>()
|
|
104
|
+
|
|
105
|
+
if (import.meta.dev && !apiKey)
|
|
94
106
|
throw new Error('GoogleMaps requires an API key. Please provide `apiKey` on the <ScriptGoogleMaps> or globally via `runtimeConfig.public.scripts.googleMaps.apiKey`.')
|
|
95
|
-
|
|
96
|
-
|
|
107
|
+
|
|
108
|
+
// TODO allow a null center may need to be resolved via an API function
|
|
97
109
|
|
|
98
110
|
const rootEl = ref<HTMLElement>()
|
|
99
111
|
const mapEl = ref<HTMLElement>()
|
|
100
112
|
|
|
101
|
-
const
|
|
113
|
+
const centerOverride = ref()
|
|
114
|
+
|
|
115
|
+
const { load, status, onLoaded } = useScriptGoogleMaps({
|
|
102
116
|
apiKey: props.apiKey,
|
|
103
117
|
scriptOptions: {
|
|
104
118
|
trigger: useScriptTriggerElement({ trigger: props.trigger, el: rootEl }),
|
|
@@ -106,16 +120,65 @@ const { $script } = useScriptGoogleMaps({
|
|
|
106
120
|
})
|
|
107
121
|
|
|
108
122
|
const options = computed(() => {
|
|
109
|
-
return defu(props.
|
|
123
|
+
return defu({ center: centerOverride.value }, props.mapOptions, {
|
|
124
|
+
center: props.center,
|
|
110
125
|
zoom: 15,
|
|
111
126
|
mapId: 'map',
|
|
112
127
|
})
|
|
113
128
|
})
|
|
114
129
|
const ready = ref(false)
|
|
115
130
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
131
|
+
const map: Ref<google.maps.Map | undefined> = ref()
|
|
132
|
+
const mapMarkers: Ref<Map<string, google.maps.marker.AdvancedMarkerElement>> = ref(new Map())
|
|
133
|
+
|
|
134
|
+
function isLocationQuery(s: string | any) {
|
|
135
|
+
return typeof s === 'string' && (s.split(',').length > 2 || s.includes('+'))
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async function createAdvancedMapMarker(_options: google.maps.marker.AdvancedMarkerElementOptions | `${string},${string}`) {
|
|
139
|
+
const lib = await importLibrary('marker')
|
|
140
|
+
const options = typeof _options === 'string'
|
|
141
|
+
? {
|
|
142
|
+
position: {
|
|
143
|
+
lat: Number.parseFloat(_options.split(',')[0]),
|
|
144
|
+
lng: Number.parseFloat(_options.split(',')[1]),
|
|
145
|
+
},
|
|
146
|
+
}
|
|
147
|
+
: _options
|
|
148
|
+
const mapMarkerOptions = defu(toRaw(options), {
|
|
149
|
+
map: toRaw(map.value!),
|
|
150
|
+
// @ts-expect-error unified API for maps and markers
|
|
151
|
+
position: options.location,
|
|
152
|
+
})
|
|
153
|
+
const marker = new lib.AdvancedMarkerElement(mapMarkerOptions)
|
|
154
|
+
// create new marker
|
|
155
|
+
mapMarkers.value.set(hash(_options), marker)
|
|
156
|
+
return marker
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const queryToLatLngCache = new Map<string, google.maps.LatLng>()
|
|
160
|
+
|
|
161
|
+
async function resolveQueryToLatLang(query: string) {
|
|
162
|
+
if (query && typeof query === 'object')
|
|
163
|
+
return Promise.resolve(query)
|
|
164
|
+
if (queryToLatLngCache.has(query)) {
|
|
165
|
+
return Promise.resolve(queryToLatLngCache.get(query))
|
|
166
|
+
}
|
|
167
|
+
// only if the query is a string we need to do a lookup
|
|
168
|
+
// eslint-disable-next-line no-async-promise-executor
|
|
169
|
+
return new Promise<google.maps.LatLng>(async (resolve, reject) => {
|
|
170
|
+
if (!mapsApi.value) {
|
|
171
|
+
await load()
|
|
172
|
+
// await new promise, watch until mapsApi is set
|
|
173
|
+
await new Promise<void>((resolve) => {
|
|
174
|
+
const _ = watch(mapsApi, () => {
|
|
175
|
+
_()
|
|
176
|
+
resolve()
|
|
177
|
+
})
|
|
178
|
+
})
|
|
179
|
+
}
|
|
180
|
+
const placesService = new mapsApi.value!.places.PlacesService(map.value!)
|
|
181
|
+
placesService.findPlaceFromQuery({
|
|
119
182
|
query,
|
|
120
183
|
fields: ['name', 'geometry'],
|
|
121
184
|
}, (results, status) => {
|
|
@@ -123,58 +186,134 @@ function queryToLocation(service: google.maps.places.PlacesService, query: strin
|
|
|
123
186
|
return resolve(results[0].geometry.location)
|
|
124
187
|
return reject(new Error(`No location found for ${query}`))
|
|
125
188
|
})
|
|
189
|
+
}).then((res) => {
|
|
190
|
+
queryToLatLngCache.set(query, res)
|
|
191
|
+
return res
|
|
126
192
|
})
|
|
127
193
|
}
|
|
128
194
|
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
195
|
+
const libraries = new Map<string, any>()
|
|
196
|
+
|
|
197
|
+
function importLibrary(key: 'marker'): Promise<google.maps.MarkerLibrary>
|
|
198
|
+
function importLibrary(key: 'places'): Promise<google.maps.PlacesLibrary>
|
|
199
|
+
function importLibrary(key: 'geometry'): Promise<google.maps.GeometryLibrary>
|
|
200
|
+
function importLibrary(key: 'drawing'): Promise<google.maps.DrawingLibrary>
|
|
201
|
+
function importLibrary(key: 'visualization'): Promise<google.maps.VisualizationLibrary>
|
|
202
|
+
function importLibrary(key: string): Promise<any>
|
|
203
|
+
function importLibrary<T>(key: string): Promise<T> {
|
|
204
|
+
if (libraries.has(key))
|
|
205
|
+
return libraries.get(key)
|
|
206
|
+
const p = mapsApi.value?.importLibrary(key) || new Promise((resolve) => {
|
|
207
|
+
const stop = watch(mapsApi, (api) => {
|
|
208
|
+
if (api) {
|
|
209
|
+
const p = api.importLibrary(key)
|
|
210
|
+
resolve(p)
|
|
211
|
+
stop()
|
|
212
|
+
}
|
|
213
|
+
}, { immediate: true })
|
|
214
|
+
})
|
|
215
|
+
libraries.set(key, p)
|
|
216
|
+
return p as any as Promise<T>
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const googleMaps = {
|
|
220
|
+
googleMaps: mapsApi,
|
|
132
221
|
map,
|
|
133
|
-
|
|
134
|
-
|
|
222
|
+
createAdvancedMapMarker,
|
|
223
|
+
resolveQueryToLatLang,
|
|
224
|
+
importLibrary,
|
|
225
|
+
} as const
|
|
226
|
+
|
|
227
|
+
defineExpose(googleMaps)
|
|
135
228
|
|
|
136
229
|
onMounted(() => {
|
|
137
230
|
watch(ready, (v) => {
|
|
138
|
-
|
|
231
|
+
if (v) {
|
|
232
|
+
emits('ready', googleMaps)
|
|
233
|
+
}
|
|
139
234
|
})
|
|
140
|
-
watch(
|
|
141
|
-
if (
|
|
235
|
+
watch(status, (v) => {
|
|
236
|
+
if (v === 'error') {
|
|
142
237
|
emits('error')
|
|
143
238
|
}
|
|
144
239
|
})
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
markers.value.push(new marker.AdvancedMarkerElement({
|
|
167
|
-
map: _map,
|
|
168
|
-
position: location,
|
|
169
|
-
}))
|
|
170
|
-
ready.value = true
|
|
240
|
+
watch(options, () => {
|
|
241
|
+
map.value?.setOptions(options.value)
|
|
242
|
+
})
|
|
243
|
+
watch([() => props.markers, map], () => {
|
|
244
|
+
if (!map.value) {
|
|
245
|
+
return
|
|
246
|
+
}
|
|
247
|
+
// mapMarkers is a map where we hash the next array entry as the map key
|
|
248
|
+
// we need to do a diff to see what we remove or add
|
|
249
|
+
const nextMap = new Map((props.markers || []).map(m => [hash(m), m]))
|
|
250
|
+
// compare idsToMatch in nextMap, if we're missing an id, we need to remove it
|
|
251
|
+
const toRemove = new Set([
|
|
252
|
+
...mapMarkers.value.keys(),
|
|
253
|
+
].filter(k => !nextMap.has(k)))
|
|
254
|
+
// compare to existing
|
|
255
|
+
const toAdd = new Set([...nextMap.keys()].filter(k => !mapMarkers.value.has(k)))
|
|
256
|
+
// do a diff of next and prev
|
|
257
|
+
const centerHash = hash({ position: options.value.center })
|
|
258
|
+
toRemove.forEach((key) => {
|
|
259
|
+
if (key === centerHash) {
|
|
260
|
+
return
|
|
171
261
|
}
|
|
172
|
-
|
|
173
|
-
|
|
262
|
+
// @ts-expect-error broken type
|
|
263
|
+
mapMarkers.value.get(key)?.setMap(null)
|
|
264
|
+
mapMarkers.value.delete(key)
|
|
174
265
|
})
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
266
|
+
for (const k of toAdd) {
|
|
267
|
+
// @ts-expect-error broken
|
|
268
|
+
createAdvancedMapMarker(nextMap.get(k))
|
|
269
|
+
}
|
|
270
|
+
}, {
|
|
271
|
+
immediate: true,
|
|
272
|
+
deep: true,
|
|
273
|
+
})
|
|
274
|
+
watch([() => props.center, ready], async (next, prev) => {
|
|
275
|
+
if (!map.value) {
|
|
276
|
+
return
|
|
277
|
+
}
|
|
278
|
+
let center = toRaw(next[0])
|
|
279
|
+
if (center) {
|
|
280
|
+
if (isLocationQuery(center) && ready.value) {
|
|
281
|
+
// need to resolve center from query
|
|
282
|
+
// @ts-expect-error broken
|
|
283
|
+
center = await resolveQueryToLatLang(center as string)
|
|
284
|
+
}
|
|
285
|
+
map.value!.setCenter(center as google.maps.LatLng)
|
|
286
|
+
if (props.centerMarker) {
|
|
287
|
+
if (prev[0]) {
|
|
288
|
+
const prevCenterHash = hash({ position: prev[0] })
|
|
289
|
+
// @ts-expect-error broken upstream type
|
|
290
|
+
mapMarkers.value.get(prevCenterHash)?.setMap(null)
|
|
291
|
+
mapMarkers.value.delete(prevCenterHash)
|
|
292
|
+
}
|
|
293
|
+
// @ts-expect-error untyped
|
|
294
|
+
createAdvancedMapMarker({ position: center })
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}, {
|
|
298
|
+
immediate: true,
|
|
299
|
+
deep: true,
|
|
300
|
+
})
|
|
301
|
+
onLoaded(async (instance) => {
|
|
302
|
+
mapsApi.value = await instance.maps as any as typeof google.maps // some weird type issue here
|
|
303
|
+
// may need to transform the center before we can init the map
|
|
304
|
+
const center = options.value.center as string
|
|
305
|
+
const _options: google.maps.MapOptions = {
|
|
306
|
+
...options.value,
|
|
307
|
+
// @ts-expect-error broken
|
|
308
|
+
center: !center || isLocationQuery(center) ? undefined : center,
|
|
309
|
+
}
|
|
310
|
+
map.value = new mapsApi.value!.Map(mapEl.value!, _options)
|
|
311
|
+
if (center && isLocationQuery(center)) {
|
|
312
|
+
// need to resolve center
|
|
313
|
+
centerOverride.value = await resolveQueryToLatLang(center)
|
|
314
|
+
map.value?.setCenter(centerOverride.value)
|
|
315
|
+
}
|
|
316
|
+
ready.value = true
|
|
178
317
|
})
|
|
179
318
|
})
|
|
180
319
|
|
|
@@ -190,15 +329,34 @@ if (import.meta.server) {
|
|
|
190
329
|
}
|
|
191
330
|
|
|
192
331
|
const placeholder = computed(() => {
|
|
332
|
+
let center = options.value.center
|
|
333
|
+
if (center && typeof center === 'object') {
|
|
334
|
+
center = `${center.lat},${center.lng}`
|
|
335
|
+
}
|
|
336
|
+
// @ts-expect-error lazy type
|
|
193
337
|
const placeholderOptions: PlaceholderOptions = defu(props.placeholderOptions, {
|
|
194
338
|
// only map option values
|
|
195
339
|
zoom: options.value.zoom,
|
|
196
|
-
center
|
|
340
|
+
center,
|
|
197
341
|
}, {
|
|
198
342
|
size: `${props.width}x${props.height}`,
|
|
199
343
|
key: apiKey,
|
|
200
344
|
scale: 2, // we assume a high DPI to avoid hydration issues
|
|
201
|
-
markers:
|
|
345
|
+
markers: [
|
|
346
|
+
...(props.markers || []),
|
|
347
|
+
center,
|
|
348
|
+
]
|
|
349
|
+
.filter(Boolean)
|
|
350
|
+
.map((m) => {
|
|
351
|
+
if (typeof m === 'object' && m.location) {
|
|
352
|
+
m = m.location
|
|
353
|
+
}
|
|
354
|
+
if (typeof m === 'object' && m.lat) {
|
|
355
|
+
return `${m.lat},${m.lng}`
|
|
356
|
+
}
|
|
357
|
+
return m
|
|
358
|
+
})
|
|
359
|
+
.join('|'),
|
|
202
360
|
})
|
|
203
361
|
return withQuery('https://maps.googleapis.com/maps/api/staticmap', placeholderOptions as QueryObject)
|
|
204
362
|
})
|
|
@@ -206,7 +364,7 @@ const placeholder = computed(() => {
|
|
|
206
364
|
const placeholderAttrs = computed(() => {
|
|
207
365
|
return defu(props.placeholderAttrs, {
|
|
208
366
|
src: placeholder.value,
|
|
209
|
-
alt:
|
|
367
|
+
alt: 'Google Maps Static Map',
|
|
210
368
|
loading: props.aboveTheFold ? 'eager' : 'lazy',
|
|
211
369
|
style: {
|
|
212
370
|
cursor: 'pointer',
|
|
@@ -219,10 +377,10 @@ const placeholderAttrs = computed(() => {
|
|
|
219
377
|
|
|
220
378
|
const rootAttrs = computed(() => {
|
|
221
379
|
return defu(props.rootAttrs, {
|
|
222
|
-
'aria-busy':
|
|
223
|
-
'aria-label':
|
|
380
|
+
'aria-busy': status.value === 'loading',
|
|
381
|
+
'aria-label': status.value === 'awaitingLoad'
|
|
224
382
|
? 'Google Maps Static Map'
|
|
225
|
-
:
|
|
383
|
+
: status.value === 'loading'
|
|
226
384
|
? 'Google Maps Map Embed Loading'
|
|
227
385
|
: 'Google Maps Embed',
|
|
228
386
|
'aria-live': 'polite',
|
|
@@ -241,8 +399,8 @@ const rootAttrs = computed(() => {
|
|
|
241
399
|
const ScriptLoadingIndicator = resolveComponent('ScriptLoadingIndicator')
|
|
242
400
|
|
|
243
401
|
onBeforeUnmount(() => {
|
|
244
|
-
|
|
245
|
-
|
|
402
|
+
mapMarkers.value.forEach(marker => marker.remove())
|
|
403
|
+
mapMarkers.value.clear()
|
|
246
404
|
map.value?.unbindAll()
|
|
247
405
|
map.value = undefined
|
|
248
406
|
mapEl.value?.firstChild?.remove()
|
|
@@ -251,15 +409,15 @@ onBeforeUnmount(() => {
|
|
|
251
409
|
|
|
252
410
|
<template>
|
|
253
411
|
<div ref="rootEl" v-bind="rootAttrs">
|
|
254
|
-
<div v-show="ready" ref="mapEl"
|
|
412
|
+
<div v-show="ready" ref="mapEl" :style="{ width: '100%', height: '100%', maxWidth: '100%' }" />
|
|
255
413
|
<slot v-if="!ready" :placeholder="placeholder" name="placeholder">
|
|
256
414
|
<img v-bind="placeholderAttrs">
|
|
257
415
|
</slot>
|
|
258
|
-
<slot v-if="
|
|
416
|
+
<slot v-if="status !== 'awaitingLoad' && !ready" name="loading">
|
|
259
417
|
<ScriptLoadingIndicator color="black" />
|
|
260
418
|
</slot>
|
|
261
|
-
<slot v-if="
|
|
262
|
-
<slot v-else-if="
|
|
419
|
+
<slot v-if="status === 'awaitingLoad'" name="awaitingLoad" />
|
|
420
|
+
<slot v-else-if="status === 'error'" name="error" />
|
|
263
421
|
<slot />
|
|
264
422
|
</div>
|
|
265
423
|
</template>
|
|
@@ -46,9 +46,12 @@ const intercom = useScriptIntercom({
|
|
|
46
46
|
trigger,
|
|
47
47
|
},
|
|
48
48
|
})
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
const { status, onLoaded } = intercom
|
|
50
|
+
if (props.trigger === 'click') {
|
|
51
|
+
onLoaded((instance) => {
|
|
52
|
+
instance.Intercom('show')
|
|
53
|
+
})
|
|
54
|
+
}
|
|
52
55
|
|
|
53
56
|
defineExpose({
|
|
54
57
|
intercom,
|
|
@@ -56,7 +59,7 @@ defineExpose({
|
|
|
56
59
|
|
|
57
60
|
let observer: MutationObserver
|
|
58
61
|
onMounted(() => {
|
|
59
|
-
watch(
|
|
62
|
+
watch(status, (status) => {
|
|
60
63
|
if (status === 'loading') {
|
|
61
64
|
observer = new MutationObserver(() => {
|
|
62
65
|
if (document.getElementById('intercom-frame')) {
|
|
@@ -86,8 +89,8 @@ onBeforeUnmount(() => {
|
|
|
86
89
|
}"
|
|
87
90
|
>
|
|
88
91
|
<slot :ready="isReady" />
|
|
89
|
-
<slot v-if="
|
|
90
|
-
<slot v-else-if="
|
|
91
|
-
<slot v-else-if="
|
|
92
|
+
<slot v-if="status === 'awaitingLoad'" name="awaitingLoad" />
|
|
93
|
+
<slot v-else-if="status === 'loading' || !isReady" name="loading" />
|
|
94
|
+
<slot v-else-if="status === 'error'" name="error" />
|
|
92
95
|
</div>
|
|
93
96
|
</template>
|
|
@@ -26,7 +26,7 @@ onMounted(() => {
|
|
|
26
26
|
rootEl.value?.querySelectorAll('a[href]').forEach((a) => {
|
|
27
27
|
a.classList.add('lemonsqueezy-button')
|
|
28
28
|
})
|
|
29
|
-
instance
|
|
29
|
+
instance.onLoaded(({ Setup, Refresh }) => {
|
|
30
30
|
Setup({
|
|
31
31
|
eventHandler(event) {
|
|
32
32
|
emits('lemonSqueezyEvent', event)
|
|
@@ -26,11 +26,11 @@ const containerEl = ref<HTMLDivElement | undefined>()
|
|
|
26
26
|
const instance = useScript(`https://js.stripe.com/v3/pricing-table.js`, {
|
|
27
27
|
trigger: useScriptTriggerElement({ trigger: props.trigger, el: rootEl }),
|
|
28
28
|
})
|
|
29
|
-
const {
|
|
29
|
+
const { onLoaded, status } = instance
|
|
30
30
|
|
|
31
31
|
const pricingTable = ref<HTMLElement | undefined>()
|
|
32
32
|
onMounted(() => {
|
|
33
|
-
|
|
33
|
+
onLoaded(() => {
|
|
34
34
|
const StripePricingTable = window.customElements.get('stripe-pricing-table')!
|
|
35
35
|
const stripePricingTable = new StripePricingTable()
|
|
36
36
|
stripePricingTable.setAttribute('publishable-key', props.publishableKey)
|
|
@@ -45,7 +45,7 @@ onMounted(() => {
|
|
|
45
45
|
rootEl.value!.appendChild(stripePricingTable)
|
|
46
46
|
emit('ready', instance)
|
|
47
47
|
})
|
|
48
|
-
watch(
|
|
48
|
+
watch(status, (status) => {
|
|
49
49
|
if (status === 'error') {
|
|
50
50
|
emit('error')
|
|
51
51
|
}
|
|
@@ -60,9 +60,9 @@ onBeforeUnmount(() => {
|
|
|
60
60
|
<template>
|
|
61
61
|
<div ref="rootEl">
|
|
62
62
|
<div ref="containerEl" />
|
|
63
|
-
<slot v-if="
|
|
64
|
-
<slot v-if="
|
|
65
|
-
<slot v-else-if="
|
|
63
|
+
<slot v-if="status === 'loading'" name="loading" />
|
|
64
|
+
<slot v-if="status === 'awaitingLoad'" name="awaitingLoad" />
|
|
65
|
+
<slot v-else-if="status === 'error'" name="error" />
|
|
66
66
|
<slot />
|
|
67
67
|
</div>
|
|
68
68
|
</template>
|
|
@@ -8,12 +8,7 @@ import { useScriptTriggerElement } from '../composables/useScriptTriggerElement'
|
|
|
8
8
|
import { useScriptVimeoPlayer } from '../registry/vimeo-player'
|
|
9
9
|
import { useAsyncData, useHead } from '#imports'
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
// custom
|
|
13
|
-
trigger?: ElementScriptTrigger
|
|
14
|
-
placeholderAttrs?: ImgHTMLAttributes
|
|
15
|
-
rootAttrs?: HTMLAttributes
|
|
16
|
-
aboveTheFold?: boolean
|
|
11
|
+
interface VimeoOptions {
|
|
17
12
|
// copied from @types/vimeo__player
|
|
18
13
|
id?: number | undefined
|
|
19
14
|
url?: string | undefined
|
|
@@ -25,7 +20,7 @@ const props = withDefaults(defineProps<{
|
|
|
25
20
|
controls?: boolean | undefined
|
|
26
21
|
dnt?: boolean | undefined
|
|
27
22
|
height?: number | undefined
|
|
28
|
-
|
|
23
|
+
|
|
29
24
|
interactive_params?: string | undefined
|
|
30
25
|
keyboard?: boolean | undefined
|
|
31
26
|
loop?: boolean | undefined
|
|
@@ -42,12 +37,19 @@ const props = withDefaults(defineProps<{
|
|
|
42
37
|
title?: boolean | undefined
|
|
43
38
|
transparent?: boolean | undefined
|
|
44
39
|
width?: number | undefined
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const props = withDefaults(defineProps<{
|
|
43
|
+
// custom
|
|
44
|
+
trigger?: ElementScriptTrigger
|
|
45
|
+
placeholderAttrs?: ImgHTMLAttributes
|
|
46
|
+
rootAttrs?: HTMLAttributes
|
|
47
|
+
aboveTheFold?: boolean
|
|
48
|
+
vimeoOptions?: VimeoOptions
|
|
49
|
+
id?: number | undefined
|
|
50
|
+
url?: string | undefined
|
|
45
51
|
}>(), {
|
|
46
52
|
trigger: 'mousedown',
|
|
47
|
-
width: 640,
|
|
48
|
-
height: 480,
|
|
49
|
-
loop: false,
|
|
50
|
-
controls: true,
|
|
51
53
|
})
|
|
52
54
|
|
|
53
55
|
const emits = defineEmits<TEmits>()
|
|
@@ -122,7 +124,7 @@ if (props.trigger === 'mousedown') {
|
|
|
122
124
|
})
|
|
123
125
|
}
|
|
124
126
|
const ready = ref(false)
|
|
125
|
-
const {
|
|
127
|
+
const { onLoaded, status } = useScriptVimeoPlayer({
|
|
126
128
|
scriptOptions: {
|
|
127
129
|
trigger,
|
|
128
130
|
},
|
|
@@ -140,12 +142,16 @@ if (import.meta.server) {
|
|
|
140
142
|
})
|
|
141
143
|
}
|
|
142
144
|
|
|
145
|
+
const id = computed(() => {
|
|
146
|
+
return props.vimeoOptions?.id || props.id
|
|
147
|
+
})
|
|
148
|
+
|
|
143
149
|
const { data: payload } = useAsyncData(
|
|
144
|
-
`vimeo-embed:${
|
|
150
|
+
`vimeo-embed:${id.value}`,
|
|
145
151
|
// TODO ideally we cache this
|
|
146
|
-
() => $fetch(`https://vimeo.com/api/v2/video/${
|
|
152
|
+
() => $fetch(`https://vimeo.com/api/v2/video/${id.value}.json`).then(res => (res as any)[0]),
|
|
147
153
|
{
|
|
148
|
-
watch: [
|
|
154
|
+
watch: [id],
|
|
149
155
|
},
|
|
150
156
|
)
|
|
151
157
|
|
|
@@ -169,10 +175,26 @@ defineExpose({
|
|
|
169
175
|
setPlaybackRate: (rate: number) => player?.setPlaybackRate(rate),
|
|
170
176
|
})
|
|
171
177
|
|
|
178
|
+
const width = computed(() => {
|
|
179
|
+
return props.vimeoOptions?.width || elVimeo.value?.parentNode?.offsetWidth || 640
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
const height = computed(() => {
|
|
183
|
+
return props.vimeoOptions?.height || elVimeo.value?.parentNode?.offsetHeight || 480
|
|
184
|
+
})
|
|
185
|
+
|
|
172
186
|
onMounted(() => {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
187
|
+
onLoaded(async ({ Vimeo }) => {
|
|
188
|
+
const vimeoOptions = props.vimeoOptions || {}
|
|
189
|
+
if (!vimeoOptions.id && props.id) {
|
|
190
|
+
vimeoOptions.id = props.id
|
|
191
|
+
}
|
|
192
|
+
if (!vimeoOptions.url && props.url) {
|
|
193
|
+
vimeoOptions.url = props.url
|
|
194
|
+
}
|
|
195
|
+
vimeoOptions.width = width.value
|
|
196
|
+
vimeoOptions.height = height.value
|
|
197
|
+
player = new Vimeo.Player(elVimeo.value, vimeoOptions)
|
|
176
198
|
if (clickTriggered) {
|
|
177
199
|
player!.play()
|
|
178
200
|
clickTriggered = false
|
|
@@ -186,33 +208,35 @@ onMounted(() => {
|
|
|
186
208
|
})
|
|
187
209
|
}
|
|
188
210
|
})
|
|
211
|
+
})
|
|
189
212
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
213
|
+
watch(() => props.id, (v) => {
|
|
214
|
+
if (v) {
|
|
215
|
+
player?.loadVideo(Number(v))
|
|
216
|
+
}
|
|
217
|
+
})
|
|
218
|
+
watch(status, (status) => {
|
|
219
|
+
if (status === 'error') {
|
|
220
|
+
// @ts-expect-error untyped
|
|
221
|
+
emits('error')
|
|
222
|
+
}
|
|
199
223
|
})
|
|
200
224
|
|
|
201
225
|
const rootAttrs = computed(() => {
|
|
202
226
|
return defu(props.rootAttrs, {
|
|
203
|
-
'aria-busy':
|
|
204
|
-
'aria-label':
|
|
227
|
+
'aria-busy': status.value === 'loading',
|
|
228
|
+
'aria-label': status.value === 'awaitingLoad'
|
|
205
229
|
? 'Vimeo Player - Placeholder'
|
|
206
|
-
:
|
|
230
|
+
: status.value === 'loading'
|
|
207
231
|
? 'Vimeo Player - Loading'
|
|
208
232
|
: 'Vimeo Player - Loaded',
|
|
209
233
|
'aria-live': 'polite',
|
|
210
234
|
'role': 'application',
|
|
211
235
|
'style': {
|
|
212
236
|
maxWidth: '100%',
|
|
213
|
-
width: `${
|
|
214
|
-
height:
|
|
215
|
-
aspectRatio:
|
|
237
|
+
width: `${width.value}px`,
|
|
238
|
+
height: 'auto',
|
|
239
|
+
aspectRatio: `16/9`,
|
|
216
240
|
position: 'relative',
|
|
217
241
|
backgroundColor: 'black',
|
|
218
242
|
},
|
|
@@ -240,19 +264,19 @@ onBeforeUnmount(() => player?.unload())
|
|
|
240
264
|
|
|
241
265
|
<template>
|
|
242
266
|
<div ref="rootEl" v-bind="rootAttrs">
|
|
243
|
-
<div v-show="ready" ref="elVimeo" class="vimeo-player"
|
|
267
|
+
<div v-show="ready" ref="elVimeo" class="vimeo-player" />
|
|
244
268
|
<slot v-if="!ready" v-bind="payload" :placeholder="placeholder" name="placeholder">
|
|
245
269
|
<img v-if="placeholder" v-bind="placeholderAttrs">
|
|
246
270
|
</slot>
|
|
247
|
-
<slot v-if="
|
|
271
|
+
<slot v-if="status === 'loading'" name="loading">
|
|
248
272
|
<ScriptLoadingIndicator color="white" />
|
|
249
273
|
</slot>
|
|
250
|
-
<slot v-if="
|
|
251
|
-
<slot v-else-if="
|
|
274
|
+
<slot v-if="status === 'awaitingLoad'" name="awaitingLoad" />
|
|
275
|
+
<slot v-else-if="status === 'error'" name="error" />
|
|
252
276
|
<slot />
|
|
253
277
|
</div>
|
|
254
278
|
</template>
|
|
255
279
|
|
|
256
280
|
<style>
|
|
257
|
-
.vimeo-player iframe{max-width:100%!important}
|
|
281
|
+
.vimeo-player iframe{aspect-ratio:16/9;height:auto;max-width:100%!important;width:100%}
|
|
258
282
|
</style>
|