@fluid-app/portal-sdk 0.1.211 → 0.1.213

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 (42) hide show
  1. package/dist/CalendarWidget-CmVC7I4i.cjs +627 -0
  2. package/dist/CalendarWidget-CmVC7I4i.cjs.map +1 -0
  3. package/dist/CalendarWidget-RdPgsQLG.mjs +610 -0
  4. package/dist/CalendarWidget-RdPgsQLG.mjs.map +1 -0
  5. package/dist/{FluidProvider-DJfKbTQm.mjs → FluidProvider-D2eBYdP9.mjs} +5 -5
  6. package/dist/{FluidProvider-DJfKbTQm.mjs.map → FluidProvider-D2eBYdP9.mjs.map} +1 -1
  7. package/dist/{FluidProvider-CfBG1eFt.cjs → FluidProvider-D7-UjZFz.cjs} +5 -5
  8. package/dist/{FluidProvider-CfBG1eFt.cjs.map → FluidProvider-D7-UjZFz.cjs.map} +1 -1
  9. package/dist/{MessagingScreen-4QQbsIUy.cjs → MessagingScreen-B0WWqXj9.cjs} +4 -4
  10. package/dist/{MessagingScreen-C6rXYwlm.cjs → MessagingScreen-CrPiH9br.cjs} +2 -2
  11. package/dist/{MessagingScreen-C6rXYwlm.cjs.map → MessagingScreen-CrPiH9br.cjs.map} +1 -1
  12. package/dist/{MessagingScreen-BUSGkkQM.mjs → MessagingScreen-D54c5afj.mjs} +2 -2
  13. package/dist/{MessagingScreen-BUSGkkQM.mjs.map → MessagingScreen-D54c5afj.mjs.map} +1 -1
  14. package/dist/{ProfileScreen-aUcLKi7B.mjs → ProfileScreen-C60U8ubV.mjs} +2 -2
  15. package/dist/{ProfileScreen-aUcLKi7B.mjs.map → ProfileScreen-C60U8ubV.mjs.map} +1 -1
  16. package/dist/{ProfileScreen-DaDRVK5B.cjs → ProfileScreen-KKkt3e9c.cjs} +2 -2
  17. package/dist/{ProfileScreen-DaDRVK5B.cjs.map → ProfileScreen-KKkt3e9c.cjs.map} +1 -1
  18. package/dist/{ProfileScreen-gHoo8LGb.cjs → ProfileScreen-u9MNVGne.cjs} +4 -4
  19. package/dist/{ShopScreen-jdit46tQ.mjs → ShopScreen-BJfA62O-.mjs} +2 -2
  20. package/dist/{ShopScreen-jdit46tQ.mjs.map → ShopScreen-BJfA62O-.mjs.map} +1 -1
  21. package/dist/{ShopScreen-Bdkbl6gq.cjs → ShopScreen-Bc7jZje5.cjs} +4 -4
  22. package/dist/{ShopScreen-vC7Yk8vC.cjs → ShopScreen-Ct3RyfWT.cjs} +2 -2
  23. package/dist/{ShopScreen-vC7Yk8vC.cjs.map → ShopScreen-Ct3RyfWT.cjs.map} +1 -1
  24. package/dist/VideoWidget-CMk4QEx_.mjs +969 -0
  25. package/dist/VideoWidget-CMk4QEx_.mjs.map +1 -0
  26. package/dist/VideoWidget-DIUMQy1C.cjs +986 -0
  27. package/dist/VideoWidget-DIUMQy1C.cjs.map +1 -0
  28. package/dist/index.cjs +12 -12
  29. package/dist/index.d.cts +42 -8
  30. package/dist/index.d.cts.map +1 -1
  31. package/dist/index.d.mts +42 -8
  32. package/dist/index.d.mts.map +1 -1
  33. package/dist/index.mjs +12 -12
  34. package/package.json +16 -16
  35. package/dist/CalendarWidget-BcZNsVQo.cjs +0 -445
  36. package/dist/CalendarWidget-BcZNsVQo.cjs.map +0 -1
  37. package/dist/CalendarWidget-DTqgk0qe.mjs +0 -428
  38. package/dist/CalendarWidget-DTqgk0qe.mjs.map +0 -1
  39. package/dist/VideoWidget-B9yfmLXd.cjs +0 -222
  40. package/dist/VideoWidget-B9yfmLXd.cjs.map +0 -1
  41. package/dist/VideoWidget-FoAueFwA.mjs +0 -205
  42. package/dist/VideoWidget-FoAueFwA.mjs.map +0 -1
@@ -0,0 +1,969 @@
1
+ import { r as __exportAll } from "./es-Cw_Kikmu.mjs";
2
+ import { i as getBorderColorField, l as getColorField, n as borderWidthClasses, o as getBorderRadiusField, p as getHeightField, s as getBorderWidthField, t as borderColorClasses } from "./registries-DT36l-bR.mjs";
3
+ import { t as MediaRenderer } from "./MediaRenderer-C-cxsqLq.mjs";
4
+ import { useCallback, useEffect, useRef, useState } from "react";
5
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
6
+ import { createPortal } from "react-dom";
7
+ //#region ../widgets/src/widgets/VideoWidget.tsx
8
+ var VideoWidget_exports = /* @__PURE__ */ __exportAll({
9
+ VideoWidget: () => VideoWidget,
10
+ videoWidgetPropertySchema: () => videoWidgetPropertySchema
11
+ });
12
+ function VideoWidget({ src = "", poster = "", resource, useCustomUrl, displayMode = "inline", borderRadius = "md", borderWidth = "none", borderColor = "muted", verticalSizing = "auto", fixedHeight = "200px", displayFit = "cover", focusPoint, controls = true, autoplay = false, loop = false, muted = true, editorialFrame = true, frameColor = "foreground", eyebrow, tag, title, tagline, duration, author, date, showFullscreenPill = true, primaryCtaText, primaryCtaLink, secondaryCtaText, secondaryCtaLink }) {
13
+ const effectiveSrc = useCustomUrl ? src : resource?.videoUrl ?? src;
14
+ const effectivePoster = useCustomUrl ? poster : resource?.imageUrl ?? poster ?? void 0;
15
+ if (displayMode === "card") {
16
+ const resolvedTitle = typeof title === "string" && title.trim() ? title : resource?.title ?? void 0;
17
+ const resourceDescription = typeof resource?.description === "string" ? resource.description : void 0;
18
+ const resolvedTagline = typeof tagline === "string" && tagline.trim() ? tagline : resourceDescription;
19
+ return /* @__PURE__ */ jsx(VideoCard, {
20
+ src: effectiveSrc,
21
+ poster: effectivePoster ?? void 0,
22
+ borderRadius,
23
+ editorialFrame,
24
+ frameColor,
25
+ eyebrow,
26
+ tag,
27
+ title: resolvedTitle,
28
+ tagline: resolvedTagline,
29
+ duration,
30
+ author,
31
+ date,
32
+ showFullscreenPill,
33
+ primaryCtaText,
34
+ primaryCtaLink,
35
+ secondaryCtaText,
36
+ secondaryCtaLink
37
+ });
38
+ }
39
+ const isFixed = verticalSizing === "fixed";
40
+ const borderWidthClass = borderWidthClasses[borderWidth];
41
+ return /* @__PURE__ */ jsx("div", {
42
+ className: `relative w-full overflow-hidden rounded-${borderRadius} ${borderWidthClass} ${borderWidth !== "none" ? borderColorClasses[borderColor] : ""}`,
43
+ style: isFixed ? { height: fixedHeight } : void 0,
44
+ children: /* @__PURE__ */ jsx(MediaRenderer, {
45
+ mediaType: "video",
46
+ src: effectiveSrc,
47
+ poster: effectivePoster,
48
+ objectFit: isFixed ? displayFit : void 0,
49
+ focusPoint: isFixed ? focusPoint : void 0,
50
+ controls,
51
+ autoplay,
52
+ loop,
53
+ muted
54
+ })
55
+ });
56
+ }
57
+ function VideoCard({ src, poster, borderRadius, editorialFrame, frameColor, eyebrow, tag, title, tagline, duration, author, date, showFullscreenPill, primaryCtaText, primaryCtaLink, secondaryCtaText, secondaryCtaLink }) {
58
+ const [modalOpen, setModalOpen] = useState(false);
59
+ const handleClose = useCallback(() => setModalOpen(false), []);
60
+ const embed = parseVideoSource(src);
61
+ const resolvedPoster = poster || embed.thumbnail || "";
62
+ const [posterSrc, setPosterSrc] = useState(resolvedPoster);
63
+ useEffect(() => {
64
+ setPosterSrc(resolvedPoster);
65
+ }, [resolvedPoster]);
66
+ const frameVar = `var(--color-${frameColor})`;
67
+ const frameShadow = editorialFrame ? "shadow-[0_1px_2px_rgba(15,23,42,0.04),0_30px_60px_-30px_rgba(15,23,42,0.4)]" : "";
68
+ const frameBg = editorialFrame ? `bg-${frameColor}` : "";
69
+ const gradientTop = { background: `linear-gradient(to top, ${frameVar}, color-mix(in oklch, ${frameVar} 55%, transparent), color-mix(in oklch, ${frameVar} 8%, transparent))` };
70
+ const gradientLeft = { background: `linear-gradient(to right, color-mix(in oklch, ${frameVar} 70%, transparent), transparent)` };
71
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("button", {
72
+ type: "button",
73
+ onClick: () => setModalOpen(true),
74
+ "aria-label": title ? `Play video: ${title}` : "Play video",
75
+ className: `group relative block w-full overflow-hidden rounded-${borderRadius} ${frameBg} ${frameShadow} focus-visible:ring-primary text-left focus:outline-none focus-visible:ring-2`,
76
+ children: /* @__PURE__ */ jsxs("div", {
77
+ className: "relative aspect-[16/9] w-full",
78
+ children: [
79
+ posterSrc ? /* @__PURE__ */ jsx("img", {
80
+ src: posterSrc,
81
+ alt: title ?? "Video thumbnail",
82
+ className: "absolute inset-0 h-full w-full object-cover transition-transform duration-[700ms] group-hover:scale-[1.03]",
83
+ onError: () => {
84
+ if (embed.thumbnailFallback && posterSrc !== embed.thumbnailFallback) setPosterSrc(embed.thumbnailFallback);
85
+ }
86
+ }) : /* @__PURE__ */ jsx("div", {
87
+ className: "bg-muted/30 absolute inset-0 flex items-center justify-center",
88
+ children: /* @__PURE__ */ jsx(PlayIcon, {
89
+ size: 40,
90
+ filled: true
91
+ })
92
+ }),
93
+ editorialFrame && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
94
+ className: "pointer-events-none absolute inset-0",
95
+ style: gradientTop
96
+ }), /* @__PURE__ */ jsx("div", {
97
+ className: "pointer-events-none absolute inset-0",
98
+ style: gradientLeft
99
+ })] }),
100
+ /* @__PURE__ */ jsx("div", {
101
+ className: "pointer-events-none absolute inset-0 flex items-center justify-center",
102
+ children: /* @__PURE__ */ jsx("span", {
103
+ className: `bg-${frameColor === "foreground" ? "background" : "foreground"} flex size-16 items-center justify-center rounded-full shadow-[0_12px_32px_-8px_rgba(255,255,255,0.35)] transition-transform duration-300 group-hover:scale-[1.08] group-active:scale-95`,
104
+ style: { animation: "fluidVideoPopIn 400ms ease-out 120ms both" },
105
+ children: /* @__PURE__ */ jsx(PlayIcon, {
106
+ size: 22,
107
+ filled: true,
108
+ color: frameVar
109
+ })
110
+ })
111
+ }),
112
+ showFullscreenPill && /* @__PURE__ */ jsx("div", {
113
+ className: "absolute top-1/2 right-6 -translate-y-1/2 opacity-0 transition-opacity duration-300 group-hover:opacity-100",
114
+ children: /* @__PURE__ */ jsxs("div", {
115
+ className: "flex items-center gap-1.5 rounded-full px-3 py-1.5 text-[11px] font-bold shadow-lg",
116
+ style: {
117
+ backgroundColor: "rgba(255,255,255,0.95)",
118
+ color: frameVar
119
+ },
120
+ children: [/* @__PURE__ */ jsx(MaximizeIcon, { size: 12 }), "Full screen"]
121
+ })
122
+ }),
123
+ /* @__PURE__ */ jsxs("div", {
124
+ className: "absolute inset-x-0 top-0 z-10 flex items-center justify-between p-5 sm:p-6",
125
+ children: [(eyebrow || tag) && /* @__PURE__ */ jsxs("div", {
126
+ className: "flex items-center gap-2",
127
+ children: [
128
+ /* @__PURE__ */ jsx("span", {
129
+ className: "flex size-5 items-center justify-center rounded-full backdrop-blur-sm",
130
+ style: {
131
+ backgroundColor: "rgba(255,255,255,0.15)",
132
+ boxShadow: "inset 0 0 0 1px rgba(255,255,255,0.2)"
133
+ },
134
+ children: /* @__PURE__ */ jsx(PlayIcon, {
135
+ size: 10,
136
+ filled: true,
137
+ color: "#fff",
138
+ marginLeft: 1
139
+ })
140
+ }),
141
+ tag && /* @__PURE__ */ jsx("span", {
142
+ className: "rounded-full px-2.5 py-1 text-[10px] font-bold tracking-[0.24em] text-white uppercase backdrop-blur-sm",
143
+ style: {
144
+ backgroundColor: "rgba(255,255,255,0.15)",
145
+ boxShadow: "inset 0 0 0 1px rgba(255,255,255,0.2)"
146
+ },
147
+ children: tag
148
+ }),
149
+ eyebrow && /* @__PURE__ */ jsx("span", {
150
+ className: "text-[10px] font-bold tracking-[0.24em] uppercase",
151
+ style: { color: "rgba(255,255,255,0.85)" },
152
+ children: eyebrow
153
+ })
154
+ ]
155
+ }), duration && /* @__PURE__ */ jsxs("span", {
156
+ className: "flex items-center gap-1.5 rounded-full px-2.5 py-1 font-mono text-[10px] font-bold text-white tabular-nums backdrop-blur-sm",
157
+ style: {
158
+ backgroundColor: "rgba(255,255,255,0.1)",
159
+ boxShadow: "inset 0 0 0 1px rgba(255,255,255,0.15)"
160
+ },
161
+ children: [/* @__PURE__ */ jsx(ClockIcon, { size: 10 }), duration]
162
+ })]
163
+ }),
164
+ (title || tagline || author || date) && /* @__PURE__ */ jsxs("div", {
165
+ className: "absolute inset-x-0 bottom-0 z-10 flex flex-col p-5 sm:p-6",
166
+ children: [
167
+ title && /* @__PURE__ */ jsx("h3", {
168
+ className: "text-[22px] leading-[1.18] font-bold tracking-[-0.015em] text-white sm:text-[24px]",
169
+ children: title
170
+ }),
171
+ tagline && /* @__PURE__ */ jsx("p", {
172
+ className: "mt-1.5 max-w-[520px] text-[12.5px] leading-[1.55]",
173
+ style: { color: "rgba(255,255,255,0.7)" },
174
+ children: tagline
175
+ }),
176
+ (author || date) && /* @__PURE__ */ jsxs("div", {
177
+ className: "mt-3 flex items-center gap-2 text-[10px] font-bold tracking-[0.16em] uppercase",
178
+ style: { color: "rgba(255,255,255,0.6)" },
179
+ children: [
180
+ author && /* @__PURE__ */ jsx("span", { children: author }),
181
+ author && date && /* @__PURE__ */ jsx("span", {
182
+ className: "size-0.5 rounded-full",
183
+ style: { backgroundColor: "rgba(255,255,255,0.3)" }
184
+ }),
185
+ date && /* @__PURE__ */ jsx("span", { children: date })
186
+ ]
187
+ })
188
+ ]
189
+ })
190
+ ]
191
+ })
192
+ }), modalOpen && /* @__PURE__ */ jsx(VideoModal, {
193
+ src,
194
+ embed,
195
+ title,
196
+ frameColor,
197
+ onClose: handleClose,
198
+ primaryCtaText,
199
+ primaryCtaLink,
200
+ secondaryCtaText,
201
+ secondaryCtaLink
202
+ })] });
203
+ }
204
+ function VideoModal({ src, embed, title, frameColor, onClose, primaryCtaText, primaryCtaLink, secondaryCtaText, secondaryCtaLink }) {
205
+ const directSrc = src?.trim();
206
+ const isMissingDirectVideo = embed.source === "direct" && !directSrc;
207
+ const [loading, setLoading] = useState(!isMissingDirectVideo);
208
+ const [loadFailed, setLoadFailed] = useState(isMissingDirectVideo);
209
+ const [iframeKey, setIframeKey] = useState(0);
210
+ const dialogRef = useRef(null);
211
+ useEffect(() => {
212
+ setLoading(!isMissingDirectVideo);
213
+ setLoadFailed(isMissingDirectVideo);
214
+ }, [
215
+ isMissingDirectVideo,
216
+ src,
217
+ embed.embedUrl
218
+ ]);
219
+ useEffect(() => {
220
+ const handler = (e) => {
221
+ if (e.key === "Escape") onClose();
222
+ };
223
+ window.addEventListener("keydown", handler);
224
+ return () => window.removeEventListener("keydown", handler);
225
+ }, [onClose]);
226
+ useEffect(() => {
227
+ const { overflow } = document.body.style;
228
+ document.body.style.overflow = "hidden";
229
+ return () => {
230
+ document.body.style.overflow = overflow;
231
+ };
232
+ }, []);
233
+ useEffect(() => {
234
+ const previouslyFocused = document.activeElement;
235
+ dialogRef.current?.focus();
236
+ return () => {
237
+ previouslyFocused?.focus?.();
238
+ };
239
+ }, []);
240
+ const backdropStyle = {
241
+ backgroundColor: `color-mix(in oklch, ${`var(--color-${frameColor})`} 85%, transparent)`,
242
+ backdropFilter: "blur(12px)",
243
+ WebkitBackdropFilter: "blur(12px)"
244
+ };
245
+ const brandAccent = embed.accent ?? "var(--color-primary)";
246
+ return createPortal(/* @__PURE__ */ jsxs("div", {
247
+ ref: dialogRef,
248
+ tabIndex: -1,
249
+ className: "fixed inset-0 z-[9999] flex items-center justify-center p-4 focus:outline-none sm:p-8",
250
+ role: "dialog",
251
+ "aria-modal": "true",
252
+ "aria-label": title ?? "Video player",
253
+ children: [/* @__PURE__ */ jsx("div", {
254
+ className: "absolute inset-0",
255
+ style: backdropStyle,
256
+ onClick: onClose,
257
+ "aria-hidden": "true"
258
+ }), /* @__PURE__ */ jsxs("div", {
259
+ className: `bg-${frameColor} relative z-10 flex max-h-full w-full max-w-5xl flex-col overflow-hidden rounded-2xl shadow-[0_40px_80px_-20px_rgba(0,0,0,0.6)]`,
260
+ children: [
261
+ /* @__PURE__ */ jsxs("div", {
262
+ className: "flex items-center justify-between gap-3 px-4 py-3",
263
+ style: { borderBottom: "1px solid rgba(255,255,255,0.1)" },
264
+ children: [/* @__PURE__ */ jsxs("div", {
265
+ className: "flex items-center gap-3",
266
+ children: [embed.source !== "direct" && /* @__PURE__ */ jsx("span", {
267
+ className: "flex size-9 items-center justify-center rounded-full",
268
+ style: { background: embed.iconGradient ?? "var(--color-primary)" },
269
+ children: /* @__PURE__ */ jsx(PlayIcon, {
270
+ size: 16,
271
+ filled: true,
272
+ color: "#fff",
273
+ marginLeft: 2
274
+ })
275
+ }), title && /* @__PURE__ */ jsx("span", {
276
+ className: "line-clamp-1 text-[13px] font-bold text-white",
277
+ children: title
278
+ })]
279
+ }), /* @__PURE__ */ jsxs("div", {
280
+ className: "flex items-center gap-1",
281
+ children: [
282
+ /* @__PURE__ */ jsx(ToolbarButton, {
283
+ label: "Refresh",
284
+ onClick: () => {
285
+ setIframeKey((k) => k + 1);
286
+ setLoading(!isMissingDirectVideo);
287
+ setLoadFailed(isMissingDirectVideo);
288
+ },
289
+ children: /* @__PURE__ */ jsx(RefreshIcon, { size: 14 })
290
+ }),
291
+ embed.watchUrl && /* @__PURE__ */ jsx(ToolbarButton, {
292
+ label: "Open externally",
293
+ asLink: true,
294
+ href: embed.watchUrl,
295
+ children: /* @__PURE__ */ jsx(ExternalIcon, { size: 14 })
296
+ }),
297
+ /* @__PURE__ */ jsx(ToolbarButton, {
298
+ label: "Close",
299
+ onClick: onClose,
300
+ children: /* @__PURE__ */ jsx(CloseIcon, { size: 14 })
301
+ })
302
+ ]
303
+ })]
304
+ }),
305
+ /* @__PURE__ */ jsx("div", {
306
+ className: `bg-${frameColor} relative w-full`,
307
+ children: /* @__PURE__ */ jsxs("div", {
308
+ className: "relative aspect-video w-full",
309
+ children: [loading && /* @__PURE__ */ jsx("div", {
310
+ className: "absolute inset-0 flex items-center justify-center",
311
+ children: /* @__PURE__ */ jsx("span", {
312
+ className: "size-8 animate-spin rounded-full border-2",
313
+ style: {
314
+ borderColor: "rgba(255,255,255,0.1)",
315
+ borderTopColor: brandAccent
316
+ }
317
+ })
318
+ }), loadFailed ? /* @__PURE__ */ jsx("div", {
319
+ className: "absolute inset-0 flex items-center justify-center",
320
+ children: /* @__PURE__ */ jsx("p", {
321
+ className: "text-sm",
322
+ style: { color: "rgba(255,255,255,0.7)" },
323
+ children: "Unable to load video."
324
+ })
325
+ }) : embed.source === "direct" ? /* @__PURE__ */ jsx("video", {
326
+ src: directSrc,
327
+ controls: true,
328
+ autoPlay: true,
329
+ className: "absolute inset-0 h-full w-full",
330
+ onLoadedData: () => setLoading(false),
331
+ onError: () => {
332
+ setLoading(false);
333
+ setLoadFailed(true);
334
+ },
335
+ children: "Your browser does not support the video tag."
336
+ }, iframeKey) : embed.embedUrl ? /* @__PURE__ */ jsx("iframe", {
337
+ src: embed.embedUrl,
338
+ title: title ?? "Video",
339
+ className: "absolute inset-0 h-full w-full border-0",
340
+ allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share",
341
+ allowFullScreen: true,
342
+ onLoad: () => setLoading(false)
343
+ }, iframeKey) : /* @__PURE__ */ jsx("div", {
344
+ className: "absolute inset-0 flex items-center justify-center",
345
+ children: /* @__PURE__ */ jsx("p", {
346
+ className: "text-sm",
347
+ style: { color: "rgba(255,255,255,0.7)" },
348
+ children: "Unable to load video."
349
+ })
350
+ })]
351
+ })
352
+ }),
353
+ (primaryCtaText && primaryCtaLink || secondaryCtaText && secondaryCtaLink) && /* @__PURE__ */ jsxs("div", {
354
+ className: "flex items-center justify-end gap-3 px-4 py-3",
355
+ style: { borderTop: "1px solid rgba(255,255,255,0.1)" },
356
+ children: [secondaryCtaText && secondaryCtaLink && /* @__PURE__ */ jsx("a", {
357
+ href: secondaryCtaLink,
358
+ className: "inline-flex items-center gap-1.5 rounded-full px-4 py-2 text-[12px] font-bold transition-colors",
359
+ style: { color: "rgba(255,255,255,0.75)" },
360
+ children: secondaryCtaText
361
+ }), primaryCtaText && primaryCtaLink && /* @__PURE__ */ jsxs("a", {
362
+ href: primaryCtaLink,
363
+ className: `text-${frameColor} inline-flex items-center gap-1.5 rounded-full bg-white px-5 py-2 text-[13px] font-bold shadow-[0_8px_22px_-8px_rgba(255,255,255,0.4)] transition-transform hover:scale-[1.02]`,
364
+ children: [primaryCtaText, /* @__PURE__ */ jsx("span", {
365
+ "aria-hidden": "true",
366
+ children: "→"
367
+ })]
368
+ })]
369
+ })
370
+ ]
371
+ })]
372
+ }), document.body);
373
+ }
374
+ function ToolbarButton({ label, onClick, asLink, href, children }) {
375
+ const className = "flex size-9 items-center justify-center rounded-full transition-colors hover:text-white";
376
+ const style = { color: "rgba(255,255,255,0.7)" };
377
+ if (asLink && href) return /* @__PURE__ */ jsx("a", {
378
+ href,
379
+ target: "_blank",
380
+ rel: "noopener noreferrer",
381
+ "aria-label": label,
382
+ className,
383
+ style,
384
+ children
385
+ });
386
+ return /* @__PURE__ */ jsx("button", {
387
+ type: "button",
388
+ onClick,
389
+ "aria-label": label,
390
+ className,
391
+ style,
392
+ children
393
+ });
394
+ }
395
+ function parseVideoSource(src) {
396
+ if (!src) return { source: "direct" };
397
+ const url = src.trim();
398
+ const youtubeId = extractYouTubeId(url);
399
+ if (youtubeId) return {
400
+ source: "youtube",
401
+ embedUrl: `https://www.youtube.com/embed/${youtubeId}?autoplay=1&rel=0`,
402
+ watchUrl: `https://www.youtube.com/watch?v=${youtubeId}`,
403
+ thumbnail: `https://i.ytimg.com/vi/${youtubeId}/maxresdefault.jpg`,
404
+ thumbnailFallback: `https://i.ytimg.com/vi/${youtubeId}/hqdefault.jpg`,
405
+ accent: "#FF0033",
406
+ iconGradient: "linear-gradient(135deg, #FF0033 0%, #CC0022 100%)"
407
+ };
408
+ const vimeoId = extractVimeoId(url);
409
+ if (vimeoId) return {
410
+ source: "vimeo",
411
+ embedUrl: `https://player.vimeo.com/video/${vimeoId}?autoplay=1`,
412
+ watchUrl: `https://vimeo.com/${vimeoId}`,
413
+ accent: "#1AB7EA",
414
+ iconGradient: "linear-gradient(135deg, #1AB7EA 0%, #0D8BBA 100%)"
415
+ };
416
+ return { source: "direct" };
417
+ }
418
+ function extractYouTubeId(url) {
419
+ const normalizeId = (value) => value && /^[a-zA-Z0-9_-]{11}$/.test(value) ? value : void 0;
420
+ try {
421
+ const parsed = new URL(url);
422
+ const hostname = parsed.hostname.replace(/^www\./, "").toLowerCase();
423
+ const pathParts = parsed.pathname.split("/").filter(Boolean);
424
+ if (hostname === "youtu.be") return normalizeId(pathParts[0]);
425
+ if (hostname === "youtube.com" || hostname.endsWith(".youtube.com") || hostname === "youtube-nocookie.com" || hostname.endsWith(".youtube-nocookie.com")) {
426
+ const watchId = normalizeId(parsed.searchParams.get("v"));
427
+ if (watchId) return watchId;
428
+ if ((pathParts[0] === "embed" || pathParts[0] === "shorts") && pathParts[1]) return normalizeId(pathParts[1]);
429
+ }
430
+ } catch {}
431
+ for (const pattern of [
432
+ /youtube\.com\/watch.*[?&]v=([a-zA-Z0-9_-]{11})/,
433
+ /youtu\.be\/([a-zA-Z0-9_-]{11})/,
434
+ /youtube\.com\/embed\/([a-zA-Z0-9_-]{11})/,
435
+ /youtube\.com\/shorts\/([a-zA-Z0-9_-]{11})/
436
+ ]) {
437
+ const youtubeId = normalizeId(pattern.exec(url)?.[1]);
438
+ if (youtubeId) return youtubeId;
439
+ }
440
+ }
441
+ function extractVimeoId(url) {
442
+ for (const pattern of [/vimeo\.com\/(?:video\/)?(\d{6,})/, /player\.vimeo\.com\/video\/(\d{6,})/]) {
443
+ const match = pattern.exec(url);
444
+ if (match?.[1]) return match[1];
445
+ }
446
+ }
447
+ function PlayIcon({ size, color, filled, marginLeft }) {
448
+ const style = {};
449
+ if (color) style.color = color;
450
+ if (marginLeft) style.marginLeft = `${marginLeft}px`;
451
+ return /* @__PURE__ */ jsx("svg", {
452
+ width: size,
453
+ height: size,
454
+ viewBox: "0 0 24 24",
455
+ fill: filled ? "currentColor" : "none",
456
+ stroke: "currentColor",
457
+ strokeWidth: filled ? 0 : 2.5,
458
+ strokeLinejoin: "round",
459
+ "aria-hidden": "true",
460
+ style,
461
+ children: /* @__PURE__ */ jsx("path", { d: "M8 5v14l11-7z" })
462
+ });
463
+ }
464
+ function ClockIcon({ size }) {
465
+ return /* @__PURE__ */ jsxs("svg", {
466
+ width: size,
467
+ height: size,
468
+ viewBox: "0 0 24 24",
469
+ fill: "none",
470
+ stroke: "currentColor",
471
+ strokeWidth: 2.5,
472
+ strokeLinecap: "round",
473
+ strokeLinejoin: "round",
474
+ "aria-hidden": "true",
475
+ children: [/* @__PURE__ */ jsx("circle", {
476
+ cx: "12",
477
+ cy: "12",
478
+ r: "10"
479
+ }), /* @__PURE__ */ jsx("polyline", { points: "12 6 12 12 16 14" })]
480
+ });
481
+ }
482
+ function MaximizeIcon({ size }) {
483
+ return /* @__PURE__ */ jsxs("svg", {
484
+ width: size,
485
+ height: size,
486
+ viewBox: "0 0 24 24",
487
+ fill: "none",
488
+ stroke: "currentColor",
489
+ strokeWidth: 2.5,
490
+ strokeLinecap: "round",
491
+ strokeLinejoin: "round",
492
+ "aria-hidden": "true",
493
+ children: [
494
+ /* @__PURE__ */ jsx("polyline", { points: "15 3 21 3 21 9" }),
495
+ /* @__PURE__ */ jsx("polyline", { points: "9 21 3 21 3 15" }),
496
+ /* @__PURE__ */ jsx("line", {
497
+ x1: "21",
498
+ y1: "3",
499
+ x2: "14",
500
+ y2: "10"
501
+ }),
502
+ /* @__PURE__ */ jsx("line", {
503
+ x1: "3",
504
+ y1: "21",
505
+ x2: "10",
506
+ y2: "14"
507
+ })
508
+ ]
509
+ });
510
+ }
511
+ function RefreshIcon({ size }) {
512
+ return /* @__PURE__ */ jsxs("svg", {
513
+ width: size,
514
+ height: size,
515
+ viewBox: "0 0 24 24",
516
+ fill: "none",
517
+ stroke: "currentColor",
518
+ strokeWidth: 2,
519
+ strokeLinecap: "round",
520
+ strokeLinejoin: "round",
521
+ "aria-hidden": "true",
522
+ children: [
523
+ /* @__PURE__ */ jsx("polyline", { points: "23 4 23 10 17 10" }),
524
+ /* @__PURE__ */ jsx("polyline", { points: "1 20 1 14 7 14" }),
525
+ /* @__PURE__ */ jsx("path", { d: "M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15" })
526
+ ]
527
+ });
528
+ }
529
+ function ExternalIcon({ size }) {
530
+ return /* @__PURE__ */ jsxs("svg", {
531
+ width: size,
532
+ height: size,
533
+ viewBox: "0 0 24 24",
534
+ fill: "none",
535
+ stroke: "currentColor",
536
+ strokeWidth: 2,
537
+ strokeLinecap: "round",
538
+ strokeLinejoin: "round",
539
+ "aria-hidden": "true",
540
+ children: [
541
+ /* @__PURE__ */ jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }),
542
+ /* @__PURE__ */ jsx("polyline", { points: "15 3 21 3 21 9" }),
543
+ /* @__PURE__ */ jsx("line", {
544
+ x1: "10",
545
+ y1: "14",
546
+ x2: "21",
547
+ y2: "3"
548
+ })
549
+ ]
550
+ });
551
+ }
552
+ function CloseIcon({ size }) {
553
+ return /* @__PURE__ */ jsxs("svg", {
554
+ width: size,
555
+ height: size,
556
+ viewBox: "0 0 24 24",
557
+ fill: "none",
558
+ stroke: "currentColor",
559
+ strokeWidth: 2.5,
560
+ strokeLinecap: "round",
561
+ strokeLinejoin: "round",
562
+ "aria-hidden": "true",
563
+ children: [/* @__PURE__ */ jsx("line", {
564
+ x1: "18",
565
+ y1: "6",
566
+ x2: "6",
567
+ y2: "18"
568
+ }), /* @__PURE__ */ jsx("line", {
569
+ x1: "6",
570
+ y1: "6",
571
+ x2: "18",
572
+ y2: "18"
573
+ })]
574
+ });
575
+ }
576
+ const videoWidgetPropertySchema = {
577
+ widgetType: "VideoWidget",
578
+ displayName: "Video",
579
+ tabsConfig: [{
580
+ id: "styling",
581
+ label: "Styling"
582
+ }, {
583
+ id: "behavior",
584
+ label: "Behavior"
585
+ }],
586
+ fields: [
587
+ {
588
+ key: "resource",
589
+ label: "Select Video",
590
+ type: "resource",
591
+ description: "Browse and select a video",
592
+ allowedTypes: ["Medium"],
593
+ tab: "styling",
594
+ group: "Content"
595
+ },
596
+ {
597
+ key: "useCustomUrl",
598
+ label: "Use Custom URL",
599
+ type: "boolean",
600
+ description: "Enter a custom video URL instead of selecting media.",
601
+ defaultValue: false,
602
+ tab: "styling",
603
+ group: "Content"
604
+ },
605
+ {
606
+ key: "src",
607
+ label: "Video URL",
608
+ type: "text",
609
+ description: "Direct video URL for inline mode. Card mode supports YouTube, Vimeo, and direct video URLs.",
610
+ defaultValue: "",
611
+ tab: "styling",
612
+ group: "Content",
613
+ requiresKeyToBeTrue: "useCustomUrl"
614
+ },
615
+ {
616
+ key: "poster",
617
+ label: "Poster Image URL",
618
+ type: "text",
619
+ description: "Thumbnail shown before play. Card mode can auto-derive YouTube thumbnails; add a poster for Vimeo URLs.",
620
+ defaultValue: "",
621
+ tab: "styling",
622
+ group: "Content",
623
+ requiresKeyToBeTrue: "useCustomUrl"
624
+ },
625
+ {
626
+ key: "displayMode",
627
+ label: "Display Mode",
628
+ type: "buttonGroup",
629
+ description: "Inline: native player embedded in the page. Card: premium thumbnail that opens a modal.",
630
+ options: [{
631
+ label: "Inline",
632
+ value: "inline"
633
+ }, {
634
+ label: "Card",
635
+ value: "card"
636
+ }],
637
+ defaultValue: "inline",
638
+ tab: "styling",
639
+ group: "Display Mode"
640
+ },
641
+ {
642
+ key: "title",
643
+ label: "Title",
644
+ type: "text",
645
+ description: "Headline on the card thumbnail (card mode only).",
646
+ defaultValue: "",
647
+ tab: "styling",
648
+ group: "Card Content",
649
+ requiresKeyValue: {
650
+ key: "displayMode",
651
+ value: "card"
652
+ }
653
+ },
654
+ {
655
+ key: "tagline",
656
+ label: "Tagline",
657
+ type: "textarea",
658
+ description: "Short body line under the title.",
659
+ defaultValue: "",
660
+ rows: 2,
661
+ tab: "styling",
662
+ group: "Card Content",
663
+ requiresKeyValue: {
664
+ key: "displayMode",
665
+ value: "card"
666
+ }
667
+ },
668
+ {
669
+ key: "eyebrow",
670
+ label: "Eyebrow",
671
+ type: "text",
672
+ description: "Small label above the card (e.g. 'Training · Fluid Academy').",
673
+ defaultValue: "",
674
+ tab: "styling",
675
+ group: "Card Content",
676
+ requiresKeyValue: {
677
+ key: "displayMode",
678
+ value: "card"
679
+ }
680
+ },
681
+ {
682
+ key: "tag",
683
+ label: "Tag",
684
+ type: "text",
685
+ description: "Optional pill label.",
686
+ defaultValue: "",
687
+ tab: "styling",
688
+ group: "Card Content",
689
+ requiresKeyValue: {
690
+ key: "displayMode",
691
+ value: "card"
692
+ }
693
+ },
694
+ {
695
+ key: "duration",
696
+ label: "Duration",
697
+ type: "text",
698
+ description: "Runtime (e.g. '4:52' or '1:09:30'). Shown as a chip.",
699
+ defaultValue: "",
700
+ tab: "styling",
701
+ group: "Card Content",
702
+ requiresKeyValue: {
703
+ key: "displayMode",
704
+ value: "card"
705
+ }
706
+ },
707
+ {
708
+ key: "author",
709
+ label: "Author / Instructor",
710
+ type: "text",
711
+ description: "Meta line author.",
712
+ defaultValue: "",
713
+ tab: "styling",
714
+ group: "Card Content",
715
+ requiresKeyValue: {
716
+ key: "displayMode",
717
+ value: "card"
718
+ }
719
+ },
720
+ {
721
+ key: "date",
722
+ label: "Date",
723
+ type: "text",
724
+ description: "Meta line date (e.g. 'Apr 12').",
725
+ defaultValue: "",
726
+ tab: "styling",
727
+ group: "Card Content",
728
+ requiresKeyValue: {
729
+ key: "displayMode",
730
+ value: "card"
731
+ }
732
+ },
733
+ {
734
+ key: "editorialFrame",
735
+ label: "Editorial Frame",
736
+ type: "boolean",
737
+ description: "Premium dark canvas with layered shadow and dual gradient overlays.",
738
+ defaultValue: true,
739
+ tab: "styling",
740
+ group: "Card Frame",
741
+ requiresKeyValue: {
742
+ key: "displayMode",
743
+ value: "card"
744
+ }
745
+ },
746
+ getColorField({
747
+ defaultValue: "foreground",
748
+ key: "frameColor",
749
+ label: "Frame Color",
750
+ description: "Surface color for the card and modal.",
751
+ tab: "styling",
752
+ group: "Card Frame",
753
+ requiresKeyValue: {
754
+ key: "displayMode",
755
+ value: "card"
756
+ }
757
+ }),
758
+ {
759
+ key: "showFullscreenPill",
760
+ label: "Show Fullscreen Pill",
761
+ type: "boolean",
762
+ description: "Show the 'Full screen' hover hint on the card.",
763
+ defaultValue: true,
764
+ tab: "styling",
765
+ group: "Card Frame",
766
+ requiresKeyValue: {
767
+ key: "displayMode",
768
+ value: "card"
769
+ }
770
+ },
771
+ {
772
+ key: "primaryCtaText",
773
+ label: "Primary CTA Text",
774
+ type: "text",
775
+ description: "Primary button in the modal footer (optional).",
776
+ defaultValue: "",
777
+ tab: "styling",
778
+ group: "Modal CTAs",
779
+ requiresKeyValue: {
780
+ key: "displayMode",
781
+ value: "card"
782
+ }
783
+ },
784
+ {
785
+ key: "primaryCtaLink",
786
+ label: "Primary CTA Link",
787
+ type: "text",
788
+ description: "URL for the primary CTA.",
789
+ defaultValue: "",
790
+ tab: "styling",
791
+ group: "Modal CTAs",
792
+ requiresKeyValue: {
793
+ key: "displayMode",
794
+ value: "card"
795
+ }
796
+ },
797
+ {
798
+ key: "secondaryCtaText",
799
+ label: "Secondary CTA Text",
800
+ type: "text",
801
+ description: "Secondary (ghost) button in the modal footer (optional).",
802
+ defaultValue: "",
803
+ tab: "styling",
804
+ group: "Modal CTAs",
805
+ requiresKeyValue: {
806
+ key: "displayMode",
807
+ value: "card"
808
+ }
809
+ },
810
+ {
811
+ key: "secondaryCtaLink",
812
+ label: "Secondary CTA Link",
813
+ type: "text",
814
+ description: "URL for the secondary CTA.",
815
+ defaultValue: "",
816
+ tab: "styling",
817
+ group: "Modal CTAs",
818
+ requiresKeyValue: {
819
+ key: "displayMode",
820
+ value: "card"
821
+ }
822
+ },
823
+ getBorderRadiusField({
824
+ key: "borderRadius",
825
+ label: "Border Radius",
826
+ description: "Border radius for the video container",
827
+ defaultValue: "md",
828
+ tab: "styling",
829
+ group: "Design"
830
+ }),
831
+ getBorderWidthField({
832
+ key: "borderWidth",
833
+ label: "Border Width",
834
+ description: "Border width for the widget",
835
+ defaultValue: "none",
836
+ tab: "styling",
837
+ group: "Design"
838
+ }),
839
+ getBorderColorField({
840
+ key: "borderColor",
841
+ label: "Border Color",
842
+ description: "Border color for the widget",
843
+ defaultValue: "muted",
844
+ tab: "styling",
845
+ group: "Design"
846
+ }),
847
+ {
848
+ key: "verticalSizing",
849
+ label: "Vertical Sizing",
850
+ type: "buttonGroup",
851
+ description: "How the video height is determined (inline mode only)",
852
+ options: [{
853
+ label: "Auto",
854
+ value: "auto"
855
+ }, {
856
+ label: "Fixed",
857
+ value: "fixed"
858
+ }],
859
+ defaultValue: "auto",
860
+ tab: "styling",
861
+ group: "Design",
862
+ requiresKeyValue: {
863
+ key: "displayMode",
864
+ value: "inline"
865
+ }
866
+ },
867
+ getHeightField({
868
+ key: "fixedHeight",
869
+ label: "Height",
870
+ description: "Fixed height of the video container",
871
+ defaultValue: "200px",
872
+ tab: "styling",
873
+ group: "Design",
874
+ requiresKeyValue: {
875
+ key: "verticalSizing",
876
+ value: "fixed"
877
+ }
878
+ }),
879
+ {
880
+ key: "displayFit",
881
+ label: "Display Fit",
882
+ type: "buttonGroup",
883
+ description: "How the video fills its container",
884
+ options: [{
885
+ label: "Cover",
886
+ value: "cover"
887
+ }, {
888
+ label: "Contain",
889
+ value: "contain"
890
+ }],
891
+ defaultValue: "cover",
892
+ tab: "styling",
893
+ group: "Design",
894
+ requiresKeyValue: {
895
+ key: "verticalSizing",
896
+ value: "fixed"
897
+ }
898
+ },
899
+ {
900
+ key: "focusPoint",
901
+ label: "Focus Point",
902
+ type: "contentPosition",
903
+ description: "The focal point of the video within its container",
904
+ defaultValue: "center",
905
+ tab: "styling",
906
+ group: "Design",
907
+ requiresKeyValue: {
908
+ key: "verticalSizing",
909
+ value: "fixed"
910
+ }
911
+ },
912
+ {
913
+ key: "controls",
914
+ label: "Show Controls",
915
+ type: "boolean",
916
+ description: "Display video playback controls (inline mode only — card mode always shows controls in the modal).",
917
+ defaultValue: true,
918
+ tab: "behavior",
919
+ group: "Behavior",
920
+ requiresKeyValue: {
921
+ key: "displayMode",
922
+ value: "inline"
923
+ }
924
+ },
925
+ {
926
+ key: "autoplay",
927
+ label: "Autoplay",
928
+ type: "boolean",
929
+ description: "Automatically start playing the video",
930
+ defaultValue: false,
931
+ tab: "behavior",
932
+ group: "Behavior",
933
+ requiresKeyValue: {
934
+ key: "displayMode",
935
+ value: "inline"
936
+ }
937
+ },
938
+ {
939
+ key: "loop",
940
+ label: "Loop",
941
+ type: "boolean",
942
+ description: "Repeat the video when it ends",
943
+ defaultValue: false,
944
+ tab: "behavior",
945
+ group: "Behavior",
946
+ requiresKeyValue: {
947
+ key: "displayMode",
948
+ value: "inline"
949
+ }
950
+ },
951
+ {
952
+ key: "muted",
953
+ label: "Muted",
954
+ type: "boolean",
955
+ description: "Start with audio muted",
956
+ defaultValue: true,
957
+ tab: "behavior",
958
+ group: "Behavior",
959
+ requiresKeyValue: {
960
+ key: "displayMode",
961
+ value: "inline"
962
+ }
963
+ }
964
+ ]
965
+ };
966
+ //#endregion
967
+ export { VideoWidget_exports as n, videoWidgetPropertySchema as r, VideoWidget as t };
968
+
969
+ //# sourceMappingURL=VideoWidget-CMk4QEx_.mjs.map