@fluid-app/portal-sdk 0.1.216 → 0.1.218

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 (55) hide show
  1. package/dist/{ContactsScreen-D-g7XEB-.cjs → ContactsScreen-DYVR-UvO.cjs} +1 -1
  2. package/dist/EmbedWidget-BysWpVIC.cjs +684 -0
  3. package/dist/EmbedWidget-BysWpVIC.cjs.map +1 -0
  4. package/dist/EmbedWidget-tU8njf5H.mjs +654 -0
  5. package/dist/EmbedWidget-tU8njf5H.mjs.map +1 -0
  6. package/dist/{FluidProvider-D0ZapBR-.mjs → FluidProvider-22PONJDa.mjs} +9 -9
  7. package/dist/{FluidProvider-D0ZapBR-.mjs.map → FluidProvider-22PONJDa.mjs.map} +1 -1
  8. package/dist/{FluidProvider-ZbTGc_uY.cjs → FluidProvider-DTdi38VO.cjs} +9 -9
  9. package/dist/{FluidProvider-ZbTGc_uY.cjs.map → FluidProvider-DTdi38VO.cjs.map} +1 -1
  10. package/dist/{ListWidget-C0ltFhxE.cjs → ListWidget-BE7uA4W4.cjs} +1 -2
  11. package/dist/{ListWidget-Ct8IDkio.mjs → ListWidget-D7y8bfvT.mjs} +252 -120
  12. package/dist/ListWidget-D7y8bfvT.mjs.map +1 -0
  13. package/dist/{ListWidget-C7ouNpEo.cjs → ListWidget-DJ-_dMOK.cjs} +251 -119
  14. package/dist/ListWidget-DJ-_dMOK.cjs.map +1 -0
  15. package/dist/{MessagingScreen-C5QOgB1w.cjs → MessagingScreen-BDlC9VWJ.cjs} +7 -7
  16. package/dist/{MessagingScreen-B8azvEc0.mjs → MessagingScreen-BM21ZxGL.mjs} +2 -2
  17. package/dist/{MessagingScreen-B8azvEc0.mjs.map → MessagingScreen-BM21ZxGL.mjs.map} +1 -1
  18. package/dist/{MessagingScreen-CkwCSMou.cjs → MessagingScreen-ehHW4LwI.cjs} +2 -2
  19. package/dist/{MessagingScreen-CkwCSMou.cjs.map → MessagingScreen-ehHW4LwI.cjs.map} +1 -1
  20. package/dist/{MySiteWidget-CDQjyrRA.cjs → MySiteWidget-8UsfEK-w.cjs} +1 -1
  21. package/dist/{MySiteWidget-CDQjyrRA.cjs.map → MySiteWidget-8UsfEK-w.cjs.map} +1 -1
  22. package/dist/{MySiteWidget-BlUbduit.mjs → MySiteWidget-D46TVWnf.mjs} +1 -1
  23. package/dist/{MySiteWidget-BlUbduit.mjs.map → MySiteWidget-D46TVWnf.mjs.map} +1 -1
  24. package/dist/{NestedWidget-ChAWwsRP.cjs → NestedWidget-BjT-UrSi.cjs} +2 -2
  25. package/dist/{NestedWidget-ChAWwsRP.cjs.map → NestedWidget-BjT-UrSi.cjs.map} +1 -1
  26. package/dist/{NestedWidget-Dw0QHoqw.mjs → NestedWidget-CEeQeCq0.mjs} +2 -2
  27. package/dist/{NestedWidget-Dw0QHoqw.mjs.map → NestedWidget-CEeQeCq0.mjs.map} +1 -1
  28. package/dist/{NestedWidget--suTLM6l.cjs → NestedWidget-D4amXykk.cjs} +2 -2
  29. package/dist/{ProfileScreen-DMmfRQp8.cjs → ProfileScreen-CN1DDd-Q.cjs} +7 -7
  30. package/dist/{ProfileScreen-DsEH0aZU.cjs → ProfileScreen-DNRpWpex.cjs} +2 -2
  31. package/dist/{ProfileScreen-DsEH0aZU.cjs.map → ProfileScreen-DNRpWpex.cjs.map} +1 -1
  32. package/dist/{ProfileScreen-BhmbCKGd.mjs → ProfileScreen-VonnJyFa.mjs} +2 -2
  33. package/dist/{ProfileScreen-BhmbCKGd.mjs.map → ProfileScreen-VonnJyFa.mjs.map} +1 -1
  34. package/dist/{ShopScreen-BBPH0l23.cjs → ShopScreen-BAbAc2ah.cjs} +7 -7
  35. package/dist/{ShopScreen-CWCPGEbn.mjs → ShopScreen-DQ1-68kV.mjs} +2 -2
  36. package/dist/{ShopScreen-CWCPGEbn.mjs.map → ShopScreen-DQ1-68kV.mjs.map} +1 -1
  37. package/dist/{ShopScreen-C6UUeGA9.cjs → ShopScreen-DcJ0DLvB.cjs} +2 -2
  38. package/dist/{ShopScreen-C6UUeGA9.cjs.map → ShopScreen-DcJ0DLvB.cjs.map} +1 -1
  39. package/dist/index.cjs +17 -17
  40. package/dist/index.d.cts +21 -0
  41. package/dist/index.d.cts.map +1 -1
  42. package/dist/index.d.mts +21 -0
  43. package/dist/index.d.mts.map +1 -1
  44. package/dist/index.mjs +15 -15
  45. package/dist/{scroll-arrows-fK_MFlSX.mjs → scroll-arrows-COrfvJk9.mjs} +1 -1
  46. package/dist/{scroll-arrows-fK_MFlSX.mjs.map → scroll-arrows-COrfvJk9.mjs.map} +1 -1
  47. package/dist/{scroll-arrows-DVwMDTt3.cjs → scroll-arrows-i0E2N-ct.cjs} +1 -1
  48. package/dist/{scroll-arrows-DVwMDTt3.cjs.map → scroll-arrows-i0E2N-ct.cjs.map} +1 -1
  49. package/package.json +12 -12
  50. package/dist/EmbedWidget-C3mGurOv.mjs +0 -221
  51. package/dist/EmbedWidget-C3mGurOv.mjs.map +0 -1
  52. package/dist/EmbedWidget-PIWoA9sU.cjs +0 -251
  53. package/dist/EmbedWidget-PIWoA9sU.cjs.map +0 -1
  54. package/dist/ListWidget-C7ouNpEo.cjs.map +0 -1
  55. package/dist/ListWidget-Ct8IDkio.mjs.map +0 -1
@@ -1,7 +1,7 @@
1
1
  require("./chunk-9hOWP6kD.cjs");
2
2
  require("./src-BNcNh8fM.cjs");
3
3
  require("./src-aItPhUAR.cjs");
4
- require("./scroll-arrows-DVwMDTt3.cjs");
4
+ require("./scroll-arrows-i0E2N-ct.cjs");
5
5
  require("./ScreenHeaderContext-BXgWydjB.cjs");
6
6
  require("./dist-CGuUUVNt.cjs");
7
7
  const require_ContactsScreen = require("./ContactsScreen-CSY7Of6x.cjs");
@@ -0,0 +1,684 @@
1
+ const require_chunk = require("./chunk-9hOWP6kD.cjs");
2
+ const require_registries = require("./registries-CpUM406S.cjs");
3
+ let react = require("react");
4
+ react = require_chunk.__toESM(react);
5
+ let react_jsx_runtime = require("react/jsx-runtime");
6
+ let lucide_react = require("lucide-react");
7
+ let react_dom = require("react-dom");
8
+ //#region ../widgets/src/contexts/RepUserContext.tsx
9
+ const RepUserContext = (0, react.createContext)(null);
10
+ function RepUserProvider({ user, children }) {
11
+ const value = (0, react.useMemo)(() => user, [user]);
12
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RepUserContext.Provider, {
13
+ value,
14
+ children
15
+ });
16
+ }
17
+ function useRepUser() {
18
+ return (0, react.useContext)(RepUserContext);
19
+ }
20
+ //#endregion
21
+ //#region ../widgets/src/widgets/EmbedWidget.tsx
22
+ var EmbedWidget_exports = /* @__PURE__ */ require_chunk.__exportAll({
23
+ EmbedWidget: () => EmbedWidget,
24
+ embedWidgetPropertySchema: () => embedWidgetPropertySchema
25
+ });
26
+ function isValidHttpUrl(urlString) {
27
+ try {
28
+ const parsed = new URL(urlString);
29
+ return parsed.protocol === "https:" || parsed.protocol === "http:";
30
+ } catch {
31
+ return false;
32
+ }
33
+ }
34
+ function useEmbedUrl(url, publicId) {
35
+ return (0, react.useMemo)(() => {
36
+ const normalizedUrl = url && (url.startsWith("http://") || url.startsWith("https://")) ? url : url ? `https://${url}` : "";
37
+ let isValidUrl = false;
38
+ if (normalizedUrl) try {
39
+ const parsed = new URL(normalizedUrl);
40
+ isValidUrl = (parsed.protocol === "http:" || parsed.protocol === "https:") && (parsed.hostname.includes(".") || parsed.hostname === "localhost");
41
+ } catch {}
42
+ if (!isValidUrl || !publicId) return {
43
+ normalizedUrl,
44
+ isValidUrl,
45
+ iframeSrc: normalizedUrl
46
+ };
47
+ const urlObj = new URL(normalizedUrl);
48
+ urlObj.searchParams.set("public_id", publicId);
49
+ return {
50
+ normalizedUrl,
51
+ isValidUrl,
52
+ iframeSrc: urlObj.toString()
53
+ };
54
+ }, [url, publicId]);
55
+ }
56
+ function useEmbedPostMessageBridge({ iframeRef, normalizedUrl, isValidUrl, editMode }) {
57
+ (0, react.useEffect)(() => {
58
+ if (!isValidUrl || editMode) return;
59
+ const expectedOrigin = new URL(normalizedUrl).origin;
60
+ function handleMessage(event) {
61
+ if (event.origin !== expectedOrigin) return;
62
+ if (event.source !== iframeRef.current?.contentWindow) return;
63
+ let data;
64
+ if (typeof event.data === "string") try {
65
+ data = JSON.parse(event.data);
66
+ } catch {
67
+ return;
68
+ }
69
+ else data = event.data;
70
+ if (typeof data === "object" && data !== null && "type" in data && data.type === "OPEN_FULL_SCREEN_WEBVIEW") {
71
+ const messageUrl = data.url;
72
+ if (messageUrl && isValidHttpUrl(messageUrl)) window.open(messageUrl, "_blank", "noopener,noreferrer");
73
+ }
74
+ }
75
+ window.addEventListener("message", handleMessage);
76
+ return () => window.removeEventListener("message", handleMessage);
77
+ }, [
78
+ iframeRef,
79
+ normalizedUrl,
80
+ isValidUrl,
81
+ editMode
82
+ ]);
83
+ }
84
+ function useModalBodyScrollLock(isOpen) {
85
+ (0, react.useEffect)(() => {
86
+ if (!isOpen) return;
87
+ const previousOverflow = document.body.style.overflow;
88
+ document.body.style.overflow = "hidden";
89
+ return () => {
90
+ document.body.style.overflow = previousOverflow;
91
+ };
92
+ }, [isOpen]);
93
+ }
94
+ function useModalEscapeClose(isOpen, onClose) {
95
+ (0, react.useEffect)(() => {
96
+ if (!isOpen) return;
97
+ const handleKeyDown = (event) => {
98
+ if (event.key === "Escape") onClose();
99
+ };
100
+ window.addEventListener("keydown", handleKeyDown);
101
+ return () => window.removeEventListener("keydown", handleKeyDown);
102
+ }, [isOpen, onClose]);
103
+ }
104
+ function useDialogFocusRestore(dialogRef) {
105
+ (0, react.useEffect)(() => {
106
+ const previouslyFocused = document.activeElement instanceof HTMLElement ? document.activeElement : null;
107
+ dialogRef.current?.focus();
108
+ return () => {
109
+ previouslyFocused?.focus();
110
+ };
111
+ }, [dialogRef]);
112
+ }
113
+ const HEADER_ICON_MAP = {
114
+ GraduationCap: lucide_react.GraduationCap,
115
+ Video: lucide_react.Video,
116
+ BookOpen: lucide_react.BookOpen,
117
+ Globe: lucide_react.Globe,
118
+ User: lucide_react.User,
119
+ Star: lucide_react.Star,
120
+ Heart: lucide_react.Heart,
121
+ Trophy: lucide_react.Trophy,
122
+ Sparkles: lucide_react.Sparkles,
123
+ Zap: lucide_react.Zap,
124
+ Gift: lucide_react.Gift,
125
+ ShoppingBag: lucide_react.ShoppingBag,
126
+ Bell: lucide_react.Bell,
127
+ Calendar: lucide_react.Calendar,
128
+ Bookmark: lucide_react.BookmarkIcon
129
+ };
130
+ const HEADER_ICON_OPTIONS = [
131
+ {
132
+ label: "Graduation Cap",
133
+ value: "GraduationCap"
134
+ },
135
+ {
136
+ label: "Video",
137
+ value: "Video"
138
+ },
139
+ {
140
+ label: "Book",
141
+ value: "BookOpen"
142
+ },
143
+ {
144
+ label: "Globe",
145
+ value: "Globe"
146
+ },
147
+ {
148
+ label: "User",
149
+ value: "User"
150
+ },
151
+ {
152
+ label: "Star",
153
+ value: "Star"
154
+ },
155
+ {
156
+ label: "Heart",
157
+ value: "Heart"
158
+ },
159
+ {
160
+ label: "Trophy",
161
+ value: "Trophy"
162
+ },
163
+ {
164
+ label: "Sparkles",
165
+ value: "Sparkles"
166
+ },
167
+ {
168
+ label: "Zap / Lightning",
169
+ value: "Zap"
170
+ },
171
+ {
172
+ label: "Gift",
173
+ value: "Gift"
174
+ },
175
+ {
176
+ label: "Shopping Bag",
177
+ value: "ShoppingBag"
178
+ },
179
+ {
180
+ label: "Bell",
181
+ value: "Bell"
182
+ },
183
+ {
184
+ label: "Calendar",
185
+ value: "Calendar"
186
+ },
187
+ {
188
+ label: "Bookmark",
189
+ value: "Bookmark"
190
+ }
191
+ ];
192
+ const getHeaderIcon = (name) => {
193
+ if (!name) return lucide_react.GraduationCap;
194
+ return HEADER_ICON_MAP[name] ?? lucide_react.GraduationCap;
195
+ };
196
+ function EmbedWidget({ url = "", title = "Embedded Content", height = "400px", fullScreen = false, allowFullscreen = true, loading = "lazy", borderRadius = "md", borderWidth = "none", borderColor = "muted", editMode = false, isSelected = false, displayMode = "inline", coverResource, coverUseCustomUrl = false, coverImageUrl = "", coverTitle = "", coverMeta = "", coverShowHeader = true, coverHeaderIcon = "GraduationCap", coverHeaderIconColor = "primary", coverHeight = "320px", className, ...props }) {
197
+ const isFullScreen = fullScreen;
198
+ const iframeRef = (0, react.useRef)(null);
199
+ const publicId = useRepUser()?.publicId;
200
+ const [modalOpen, setModalOpen] = (0, react.useState)(false);
201
+ const [coverReloadKey, setCoverReloadKey] = (0, react.useState)(0);
202
+ const [iframeReloadKey, setIframeReloadKey] = (0, react.useState)(0);
203
+ const closeModal = (0, react.useCallback)(() => setModalOpen(false), []);
204
+ const { normalizedUrl, isValidUrl, iframeSrc } = useEmbedUrl(url, publicId);
205
+ useEmbedPostMessageBridge({
206
+ iframeRef,
207
+ normalizedUrl,
208
+ isValidUrl,
209
+ editMode
210
+ });
211
+ useModalBodyScrollLock(modalOpen);
212
+ useModalEscapeClose(modalOpen, closeModal);
213
+ if (!url || !isValidUrl) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
214
+ className: `flex items-center justify-center rounded-${borderRadius} border-border bg-muted text-muted-foreground border-2 border-dashed ${isFullScreen ? "h-full" : ""} ${className ?? ""}`,
215
+ style: isFullScreen ? void 0 : { height: displayMode === "cover" ? coverHeight : height },
216
+ ...props,
217
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
218
+ className: "flex flex-col items-center gap-2 p-6 text-center",
219
+ children: [
220
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Globe, { className: "h-12 w-12 opacity-50" }),
221
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
222
+ className: "text-sm font-medium",
223
+ children: "Enter a URL to embed external content"
224
+ }),
225
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
226
+ className: "text-xs opacity-75",
227
+ children: "Configure the URL in the properties panel"
228
+ })
229
+ ]
230
+ })
231
+ });
232
+ if (displayMode === "cover") {
233
+ const resolvedCoverImage = coverUseCustomUrl ? coverImageUrl : coverResource?.imageUrl || coverResource?.image_url || coverImageUrl;
234
+ const effectiveTitle = coverTitle || title;
235
+ const HeaderIcon = getHeaderIcon(coverHeaderIcon);
236
+ const handleOpenModal = () => {
237
+ if (editMode) return;
238
+ setModalOpen(true);
239
+ };
240
+ const handleReload = () => {
241
+ if (editMode) return;
242
+ setCoverReloadKey((key) => key + 1);
243
+ };
244
+ const handleOpenNewTab = (e) => {
245
+ e.stopPropagation();
246
+ if (editMode) return;
247
+ window.open(iframeSrc, "_blank", "noopener,noreferrer");
248
+ };
249
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
250
+ className: `relative w-full overflow-hidden rounded-${borderRadius} ${require_registries.borderWidthClasses[borderWidth]} ${borderWidth !== "none" ? require_registries.borderColorClasses[borderColor] : ""} bg-background ${className ?? ""}`,
251
+ style: { boxShadow: "0 1px 2px color-mix(in oklch, var(--color-foreground) 5%, transparent), 0 12px 32px -16px color-mix(in oklch, var(--color-foreground) 10%, transparent)" },
252
+ ...props,
253
+ children: [
254
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
255
+ "aria-hidden": "true",
256
+ className: `pointer-events-none absolute inset-0 z-[1] rounded-${borderRadius}`,
257
+ style: { boxShadow: "inset 0 0 0 1px color-mix(in oklch, var(--color-foreground) 8%, transparent)" }
258
+ }),
259
+ coverShowHeader && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
260
+ className: "relative z-[2] flex items-center gap-3 px-5 py-3",
261
+ children: [
262
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
263
+ "aria-hidden": "true",
264
+ className: `text-${coverHeaderIconColor}-foreground flex size-7 shrink-0 items-center justify-center rounded-${borderRadius}`,
265
+ style: {
266
+ background: `linear-gradient(135deg, color-mix(in oklch, var(--color-${coverHeaderIconColor}) 75%, white 25%) 0%, var(--color-${coverHeaderIconColor}) 100%)`,
267
+ boxShadow: `
268
+ inset 0 1px 0 rgba(255,255,255,0.25),
269
+ inset 0 -1px 0 rgba(0,0,0,0.08),
270
+ 0 1px 2px color-mix(in oklch, var(--color-${coverHeaderIconColor}) 25%, transparent)
271
+ `
272
+ },
273
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HeaderIcon, {
274
+ className: "size-3.5",
275
+ strokeWidth: 2.25
276
+ })
277
+ }),
278
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
279
+ className: "min-w-0 flex-1",
280
+ children: [effectiveTitle && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
281
+ className: "text-foreground truncate text-[15px] leading-tight font-semibold tracking-tight",
282
+ children: effectiveTitle
283
+ }), coverMeta && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
284
+ className: "text-foreground/40 mt-0.5 truncate text-[11px] font-medium tracking-[0.08em] uppercase",
285
+ children: coverMeta
286
+ })]
287
+ }),
288
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
289
+ className: "bg-foreground/5 flex shrink-0 items-center rounded-lg p-0.5",
290
+ children: [
291
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HeaderIconButton, {
292
+ Icon: lucide_react.RotateCw,
293
+ label: "Reload",
294
+ onClick: (e) => {
295
+ e.stopPropagation();
296
+ handleReload();
297
+ }
298
+ }),
299
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HeaderIconButton, {
300
+ Icon: lucide_react.Maximize2,
301
+ label: "Open",
302
+ onClick: (e) => {
303
+ e.stopPropagation();
304
+ handleOpenModal();
305
+ }
306
+ }),
307
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HeaderIconButton, {
308
+ Icon: lucide_react.ExternalLink,
309
+ label: "Open in new tab",
310
+ onClick: handleOpenNewTab
311
+ })
312
+ ]
313
+ })
314
+ ]
315
+ }),
316
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
317
+ type: "button",
318
+ onClick: handleOpenModal,
319
+ disabled: editMode,
320
+ className: `relative block w-full overflow-hidden ${editMode ? "cursor-default" : "cursor-pointer"}`,
321
+ style: { height: coverHeight },
322
+ "aria-label": `Open ${effectiveTitle || title}`,
323
+ children: resolvedCoverImage ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
324
+ src: resolvedCoverImage,
325
+ alt: effectiveTitle || title,
326
+ className: "h-full w-full object-cover"
327
+ }, `cover-${coverReloadKey}`) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
328
+ className: "bg-muted flex h-full w-full items-center justify-center",
329
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Globe, { className: "text-muted-foreground/40 size-16" })
330
+ })
331
+ }),
332
+ editMode && !isSelected && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "absolute inset-0 z-10" })
333
+ ]
334
+ }), modalOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EmbedModal, {
335
+ src: iframeSrc,
336
+ title: effectiveTitle || title,
337
+ allowFullscreen,
338
+ iframeRef,
339
+ onClose: closeModal,
340
+ onReload: () => setIframeReloadKey((key) => key + 1)
341
+ }, `modal-${iframeReloadKey}`)] });
342
+ }
343
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
344
+ className: `relative w-full rounded-${borderRadius} ${require_registries.borderWidthClasses[borderWidth]} ${borderWidth !== "none" ? require_registries.borderColorClasses[borderColor] : ""} ${isFullScreen ? "h-full" : ""} ${className ?? ""}`,
345
+ ...props,
346
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("iframe", {
347
+ ref: iframeRef,
348
+ src: iframeSrc,
349
+ title,
350
+ width: "100%",
351
+ style: isFullScreen ? { height: "100%" } : { height },
352
+ loading,
353
+ allowFullScreen: allowFullscreen,
354
+ className: `rounded-${borderRadius} border-border border`,
355
+ sandbox: "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox"
356
+ }), editMode && !isSelected && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "absolute inset-0 z-10" })]
357
+ });
358
+ }
359
+ function HeaderIconButton({ Icon, label, onClick }) {
360
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
361
+ type: "button",
362
+ onClick,
363
+ "aria-label": label,
364
+ className: "text-foreground/45 hover:text-foreground hover:bg-background flex size-7 items-center justify-center rounded-md transition-colors",
365
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
366
+ className: "size-3.5",
367
+ strokeWidth: 2.25
368
+ })
369
+ });
370
+ }
371
+ function EmbedModal({ src, title, allowFullscreen, iframeRef, onClose, onReload }) {
372
+ const dialogRef = (0, react.useRef)(null);
373
+ useDialogFocusRestore(dialogRef);
374
+ return (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
375
+ ref: dialogRef,
376
+ tabIndex: -1,
377
+ className: "fixed inset-0 z-[100] flex items-center justify-center p-4 focus:outline-none sm:p-8",
378
+ style: { background: "color-mix(in oklch, var(--color-foreground) 80%, black)" },
379
+ onClick: onClose,
380
+ role: "dialog",
381
+ "aria-modal": "true",
382
+ "aria-label": title,
383
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
384
+ className: "bg-background relative flex h-full max-h-[95vh] w-full max-w-[1400px] flex-col overflow-hidden rounded-2xl shadow-2xl",
385
+ onClick: (e) => e.stopPropagation(),
386
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
387
+ className: "flex items-center justify-between gap-4 px-5 py-3",
388
+ style: { borderBottom: "1px solid color-mix(in oklch, var(--color-foreground) 8%, transparent)" },
389
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
390
+ className: "text-foreground truncate text-sm font-semibold tracking-tight",
391
+ children: title
392
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
393
+ className: "flex shrink-0 items-center gap-1",
394
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(HeaderIconButton, {
395
+ Icon: lucide_react.RotateCw,
396
+ label: "Reload",
397
+ onClick: (e) => {
398
+ e.stopPropagation();
399
+ onReload();
400
+ }
401
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
402
+ type: "button",
403
+ onClick: onClose,
404
+ "aria-label": "Close",
405
+ className: "text-foreground/60 hover:text-foreground hover:bg-foreground/5 flex size-9 shrink-0 items-center justify-center rounded-full transition-colors",
406
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.X, { className: "size-5" })
407
+ })]
408
+ })]
409
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("iframe", {
410
+ ref: iframeRef,
411
+ src,
412
+ title,
413
+ className: "flex-1 border-0",
414
+ allowFullScreen: allowFullscreen,
415
+ sandbox: "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox"
416
+ })]
417
+ })
418
+ }), document.body);
419
+ }
420
+ const embedWidgetPropertySchema = {
421
+ widgetType: "EmbedWidget",
422
+ displayName: "Embed",
423
+ fields: [
424
+ {
425
+ key: "url",
426
+ label: "URL",
427
+ type: "text",
428
+ description: "The URL of the external site to embed",
429
+ placeholder: "https://example.com",
430
+ defaultValue: "",
431
+ group: "Content"
432
+ },
433
+ {
434
+ key: "title",
435
+ label: "Title",
436
+ type: "text",
437
+ description: "Accessibility title for the embedded content",
438
+ defaultValue: "Embedded Content",
439
+ group: "Content"
440
+ },
441
+ {
442
+ key: "displayMode",
443
+ label: "Display Mode",
444
+ type: "buttonGroup",
445
+ description: "Inline: iframe renders directly. Cover: shows a card that opens the embed in a full-screen modal.",
446
+ defaultValue: "inline",
447
+ options: [{
448
+ label: "Inline",
449
+ value: "inline"
450
+ }, {
451
+ label: "Cover + Modal",
452
+ value: "cover"
453
+ }],
454
+ group: "Display Mode"
455
+ },
456
+ {
457
+ key: "coverResource",
458
+ label: "Cover Image",
459
+ type: "resource",
460
+ description: "Select the image shown before the embed opens",
461
+ allowedTypes: ["Medium"],
462
+ group: "Cover",
463
+ requiresKeyValue: {
464
+ key: "displayMode",
465
+ value: "cover"
466
+ }
467
+ },
468
+ {
469
+ key: "coverUseCustomUrl",
470
+ label: "Use Custom URL",
471
+ type: "boolean",
472
+ description: "Enter a custom image URL instead of selecting media",
473
+ defaultValue: false,
474
+ group: "Cover",
475
+ requiresKeyValue: {
476
+ key: "displayMode",
477
+ value: "cover"
478
+ }
479
+ },
480
+ {
481
+ key: "coverImageUrl",
482
+ label: "Cover Image URL",
483
+ type: "text",
484
+ description: "Direct URL to the cover image",
485
+ placeholder: "https://example.com/cover.jpg",
486
+ defaultValue: "",
487
+ group: "Cover",
488
+ requiresKeyValue: [{
489
+ key: "displayMode",
490
+ value: "cover"
491
+ }, {
492
+ key: "coverUseCustomUrl",
493
+ value: true
494
+ }]
495
+ },
496
+ require_registries.getHeightField({
497
+ key: "coverHeight",
498
+ label: "Cover Height",
499
+ description: "Height of the cover image area",
500
+ defaultValue: "320px",
501
+ group: "Cover",
502
+ requiresKeyValue: {
503
+ key: "displayMode",
504
+ value: "cover"
505
+ }
506
+ }),
507
+ {
508
+ key: "coverShowHeader",
509
+ label: "Show Card Header",
510
+ type: "boolean",
511
+ description: "Show the header with icon, title, and action buttons",
512
+ defaultValue: true,
513
+ group: "Cover Header",
514
+ requiresKeyValue: {
515
+ key: "displayMode",
516
+ value: "cover"
517
+ }
518
+ },
519
+ {
520
+ key: "coverHeaderIcon",
521
+ label: "Header Icon",
522
+ type: "select",
523
+ description: "Icon displayed in the colored badge on the left",
524
+ options: HEADER_ICON_OPTIONS,
525
+ defaultValue: "GraduationCap",
526
+ group: "Cover Header",
527
+ requiresKeyValue: [{
528
+ key: "displayMode",
529
+ value: "cover"
530
+ }, {
531
+ key: "coverShowHeader",
532
+ value: true
533
+ }]
534
+ },
535
+ require_registries.getColorField({
536
+ key: "coverHeaderIconColor",
537
+ label: "Icon Badge Color",
538
+ description: "Background color of the icon badge",
539
+ defaultValue: "primary",
540
+ group: "Cover Header",
541
+ requiresKeyValue: [{
542
+ key: "displayMode",
543
+ value: "cover"
544
+ }, {
545
+ key: "coverShowHeader",
546
+ value: true
547
+ }]
548
+ }),
549
+ {
550
+ key: "coverTitle",
551
+ label: "Header Title",
552
+ type: "text",
553
+ description: "Title shown in the card header and modal (falls back to the widget Title if empty). Available even when the card header is hidden so the modal still has a meaningful title.",
554
+ defaultValue: "",
555
+ group: "Cover Header",
556
+ requiresKeyValue: {
557
+ key: "displayMode",
558
+ value: "cover"
559
+ }
560
+ },
561
+ {
562
+ key: "coverMeta",
563
+ label: "Meta Text",
564
+ type: "text",
565
+ description: "Small uppercase meta line below the title (e.g. 'APR 16 · COACHING THE HOSTESS')",
566
+ defaultValue: "",
567
+ group: "Cover Header",
568
+ requiresKeyValue: [{
569
+ key: "displayMode",
570
+ value: "cover"
571
+ }, {
572
+ key: "coverShowHeader",
573
+ value: true
574
+ }]
575
+ },
576
+ require_registries.getBorderRadiusField({
577
+ key: "borderRadius",
578
+ label: "Border Radius",
579
+ description: "Border radius for the embed container",
580
+ defaultValue: "md",
581
+ group: "Design"
582
+ }),
583
+ require_registries.getBorderWidthField({
584
+ key: "borderWidth",
585
+ label: "Border Width",
586
+ description: "Border width for the widget",
587
+ defaultValue: "none",
588
+ group: "Design"
589
+ }),
590
+ require_registries.getBorderColorField({
591
+ key: "borderColor",
592
+ label: "Border Color",
593
+ description: "Border color for the widget",
594
+ defaultValue: "muted",
595
+ group: "Design"
596
+ }),
597
+ {
598
+ key: "fullScreen",
599
+ label: "Full Screen",
600
+ type: "boolean",
601
+ description: "Inline mode: fill the available space instead of a fixed height",
602
+ defaultValue: false,
603
+ group: "Design",
604
+ requiresKeyValue: {
605
+ key: "displayMode",
606
+ value: "inline"
607
+ }
608
+ },
609
+ require_registries.getHeightField({
610
+ key: "height",
611
+ label: "Height",
612
+ description: "Height of the inline embed iframe",
613
+ defaultValue: "400px",
614
+ group: "Design",
615
+ requiresKeyValue: [{
616
+ key: "displayMode",
617
+ value: "inline"
618
+ }, {
619
+ key: "fullScreen",
620
+ value: false
621
+ }]
622
+ }),
623
+ {
624
+ key: "allowFullscreen",
625
+ label: "Allow Fullscreen",
626
+ type: "boolean",
627
+ description: "Allow the embedded content to use fullscreen mode",
628
+ defaultValue: true,
629
+ group: "Settings"
630
+ },
631
+ {
632
+ key: "loading",
633
+ label: "Loading",
634
+ type: "select",
635
+ description: "When to load the embedded content (inline mode only)",
636
+ options: [{
637
+ label: "Lazy (on scroll)",
638
+ value: "lazy"
639
+ }, {
640
+ label: "Eager (immediately)",
641
+ value: "eager"
642
+ }],
643
+ defaultValue: "lazy",
644
+ group: "Settings",
645
+ requiresKeyValue: {
646
+ key: "displayMode",
647
+ value: "inline"
648
+ }
649
+ }
650
+ ]
651
+ };
652
+ //#endregion
653
+ Object.defineProperty(exports, "EmbedWidget", {
654
+ enumerable: true,
655
+ get: function() {
656
+ return EmbedWidget;
657
+ }
658
+ });
659
+ Object.defineProperty(exports, "EmbedWidget_exports", {
660
+ enumerable: true,
661
+ get: function() {
662
+ return EmbedWidget_exports;
663
+ }
664
+ });
665
+ Object.defineProperty(exports, "RepUserProvider", {
666
+ enumerable: true,
667
+ get: function() {
668
+ return RepUserProvider;
669
+ }
670
+ });
671
+ Object.defineProperty(exports, "embedWidgetPropertySchema", {
672
+ enumerable: true,
673
+ get: function() {
674
+ return embedWidgetPropertySchema;
675
+ }
676
+ });
677
+ Object.defineProperty(exports, "useRepUser", {
678
+ enumerable: true,
679
+ get: function() {
680
+ return useRepUser;
681
+ }
682
+ });
683
+
684
+ //# sourceMappingURL=EmbedWidget-BysWpVIC.cjs.map