@fluid-app/portal-sdk 0.1.241 → 0.1.243
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/dist/{EmbedWidget-Q45pAeCI.cjs → EmbedWidget-DgbCzBA4.cjs} +5 -4
- package/dist/EmbedWidget-DgbCzBA4.cjs.map +1 -0
- package/dist/{EmbedWidget-Cj6VgQJC.mjs → EmbedWidget-LYnd3TZD.mjs} +5 -4
- package/dist/EmbedWidget-LYnd3TZD.mjs.map +1 -0
- package/dist/{FluidProvider-BwMwMCxW.mjs → FluidProvider-CNk1Y2k1.mjs} +3 -3
- package/dist/{FluidProvider-BwMwMCxW.mjs.map → FluidProvider-CNk1Y2k1.mjs.map} +1 -1
- package/dist/{FluidProvider-eT4gA6Io.cjs → FluidProvider-o1Gu53TN.cjs} +3 -3
- package/dist/{FluidProvider-eT4gA6Io.cjs.map → FluidProvider-o1Gu53TN.cjs.map} +1 -1
- package/dist/{MessagingScreen-D3S230Ba.cjs → MessagingScreen-CCbgNRp1.cjs} +2 -2
- package/dist/{MessagingScreen-D3S230Ba.cjs.map → MessagingScreen-CCbgNRp1.cjs.map} +1 -1
- package/dist/{MessagingScreen-BHYX1Kc6.cjs → MessagingScreen-KYx6DSMx.cjs} +3 -3
- package/dist/{MessagingScreen-CZddjqma.mjs → MessagingScreen-vb5P-7jP.mjs} +2 -2
- package/dist/{MessagingScreen-CZddjqma.mjs.map → MessagingScreen-vb5P-7jP.mjs.map} +1 -1
- package/dist/{ProfileScreen-DAujb81k.cjs → ProfileScreen-BT0iys-q.cjs} +2 -2
- package/dist/{ProfileScreen-DAujb81k.cjs.map → ProfileScreen-BT0iys-q.cjs.map} +1 -1
- package/dist/{ProfileScreen-BYJj4D1W.cjs → ProfileScreen-CKcdtroU.cjs} +3 -3
- package/dist/{ProfileScreen-DlMEqXXg.mjs → ProfileScreen-CZAIUM2a.mjs} +2 -2
- package/dist/{ProfileScreen-DlMEqXXg.mjs.map → ProfileScreen-CZAIUM2a.mjs.map} +1 -1
- package/dist/{ShopScreen-6nEKrNjK.cjs → ShopScreen-DVpCo-OV.cjs} +3 -3
- package/dist/{ShopScreen-1yvcCk7l.cjs → ShopScreen-Dm85_rMp.cjs} +2 -2
- package/dist/{ShopScreen-1yvcCk7l.cjs.map → ShopScreen-Dm85_rMp.cjs.map} +1 -1
- package/dist/{ShopScreen-U7G6Jf67.mjs → ShopScreen-sLUTgIcQ.mjs} +2 -2
- package/dist/{ShopScreen-U7G6Jf67.mjs.map → ShopScreen-sLUTgIcQ.mjs.map} +1 -1
- package/dist/index.cjs +13 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +13 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +14 -14
- package/dist/EmbedWidget-Cj6VgQJC.mjs.map +0 -1
- package/dist/EmbedWidget-Q45pAeCI.cjs.map +0 -1
|
@@ -211,9 +211,9 @@ function EmbedWidget({ url = "", title = "Embedded Content", height = "400px", f
|
|
|
211
211
|
useModalBodyScrollLock(modalOpen);
|
|
212
212
|
useModalEscapeClose(modalOpen, closeModal);
|
|
213
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 ${
|
|
215
|
-
style: isFullScreen ? void 0 : { height: displayMode === "cover" ? coverHeight : height },
|
|
214
|
+
className: `flex items-center justify-center rounded-${borderRadius} border-border bg-muted text-muted-foreground border-2 border-dashed ${className ?? ""}`,
|
|
216
215
|
...props,
|
|
216
|
+
style: isFullScreen ? { height: "var(--portal-fullscreen-embed-height, calc(100dvh - 4rem))" } : { height: displayMode === "cover" ? coverHeight : height },
|
|
217
217
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
218
218
|
className: "flex flex-col items-center gap-2 p-6 text-center",
|
|
219
219
|
children: [
|
|
@@ -341,8 +341,9 @@ function EmbedWidget({ url = "", title = "Embedded Content", height = "400px", f
|
|
|
341
341
|
}, `modal-${iframeReloadKey}`)] });
|
|
342
342
|
}
|
|
343
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] : ""} ${
|
|
344
|
+
className: `relative w-full rounded-${borderRadius} ${require_registries.borderWidthClasses[borderWidth]} ${borderWidth !== "none" ? require_registries.borderColorClasses[borderColor] : ""} ${className ?? ""}`,
|
|
345
345
|
...props,
|
|
346
|
+
style: isFullScreen ? { height: "var(--portal-fullscreen-embed-height, calc(100dvh - 4rem))" } : void 0,
|
|
346
347
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("iframe", {
|
|
347
348
|
ref: iframeRef,
|
|
348
349
|
src: iframeSrc,
|
|
@@ -681,4 +682,4 @@ Object.defineProperty(exports, "useRepUser", {
|
|
|
681
682
|
}
|
|
682
683
|
});
|
|
683
684
|
|
|
684
|
-
//# sourceMappingURL=EmbedWidget-
|
|
685
|
+
//# sourceMappingURL=EmbedWidget-DgbCzBA4.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmbedWidget-DgbCzBA4.cjs","names":["BookmarkIcon","GraduationCap","Globe","borderWidthClasses","borderColorClasses","RotateCw","Maximize2","ExternalLink","X","getHeightField","getColorField","getBorderRadiusField","getBorderWidthField","getBorderColorField"],"sources":["../../widgets/src/contexts/RepUserContext.tsx","../../widgets/src/widgets/EmbedWidget.tsx"],"sourcesContent":["import React, {\n createContext,\n useContext,\n useMemo,\n type ReactNode,\n} from \"react\";\n\nexport interface RepUser {\n name: string | null;\n email: string | null;\n imageUrl: string | null;\n publicId?: string;\n}\n\nconst RepUserContext = createContext<RepUser | null>(null);\n\nexport interface RepUserProviderProps {\n user: RepUser;\n children: ReactNode;\n}\n\nexport function RepUserProvider({\n user,\n children,\n}: RepUserProviderProps): React.JSX.Element {\n const value = useMemo(() => user, [user]);\n return (\n <RepUserContext.Provider value={value}>{children}</RepUserContext.Provider>\n );\n}\n\nexport function useRepUser(): RepUser | null {\n return useContext(RepUserContext);\n}\n","import {\n Bell,\n BookmarkIcon,\n BookOpen,\n Calendar,\n ExternalLink,\n Gift,\n Globe,\n GraduationCap,\n Heart,\n Maximize2,\n RotateCw,\n ShoppingBag,\n Sparkles,\n Star,\n Trophy,\n User,\n Video,\n X,\n Zap,\n type LucideIcon,\n} from \"lucide-react\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ComponentProps,\n type RefObject,\n} from \"react\";\nimport type React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport {\n getBorderRadiusField,\n getHeightField,\n type WidgetPropertySchema,\n} from \"@fluid-app/portal-core/registries\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n ShareableItem,\n} from \"@fluid-app/portal-core/types\";\nimport {\n getBorderWidthField,\n getBorderColorField,\n getColorField,\n borderWidthClasses,\n borderColorClasses,\n} from \"../core/fields\";\nimport { useRepUser } from \"../contexts/RepUserContext\";\n\ntype EmbedWidgetMessage = {\n type: \"OPEN_FULL_SCREEN_WEBVIEW\";\n url: string;\n};\n\ntype DisplayMode = \"inline\" | \"cover\";\n\ntype EmbedUrlState = {\n normalizedUrl: string;\n isValidUrl: boolean;\n iframeSrc: string;\n};\n\nfunction isValidHttpUrl(urlString: string): boolean {\n try {\n const parsed = new URL(urlString);\n return parsed.protocol === \"https:\" || parsed.protocol === \"http:\";\n } catch {\n return false;\n }\n}\n\nfunction useEmbedUrl(url: string, publicId: string | undefined): EmbedUrlState {\n return useMemo(() => {\n const normalizedUrl =\n url && (url.startsWith(\"http://\") || url.startsWith(\"https://\"))\n ? url\n : url\n ? `https://${url}`\n : \"\";\n\n let isValidUrl = false;\n if (normalizedUrl) {\n try {\n const parsed = new URL(normalizedUrl);\n isValidUrl =\n (parsed.protocol === \"http:\" || parsed.protocol === \"https:\") &&\n (parsed.hostname.includes(\".\") || parsed.hostname === \"localhost\");\n } catch {\n // invalid URL\n }\n }\n\n if (!isValidUrl || !publicId) {\n return { normalizedUrl, isValidUrl, iframeSrc: normalizedUrl };\n }\n\n const urlObj = new URL(normalizedUrl);\n urlObj.searchParams.set(\"public_id\", publicId);\n return { normalizedUrl, isValidUrl, iframeSrc: urlObj.toString() };\n }, [url, publicId]);\n}\n\ntype UseEmbedPostMessageBridgeProps = {\n iframeRef: RefObject<HTMLIFrameElement | null>;\n normalizedUrl: string;\n isValidUrl: boolean;\n editMode: boolean;\n};\n\nfunction useEmbedPostMessageBridge({\n iframeRef,\n normalizedUrl,\n isValidUrl,\n editMode,\n}: UseEmbedPostMessageBridgeProps): void {\n useEffect(() => {\n if (!isValidUrl || editMode) return;\n\n const expectedOrigin = new URL(normalizedUrl).origin;\n\n function handleMessage(event: MessageEvent) {\n if (event.origin !== expectedOrigin) return;\n if (event.source !== iframeRef.current?.contentWindow) return;\n\n let data: unknown;\n if (typeof event.data === \"string\") {\n try {\n data = JSON.parse(event.data);\n } catch {\n return;\n }\n } else {\n data = event.data;\n }\n\n if (\n typeof data === \"object\" &&\n data !== null &&\n \"type\" in data &&\n (data as EmbedWidgetMessage).type === \"OPEN_FULL_SCREEN_WEBVIEW\"\n ) {\n const messageUrl = (data as EmbedWidgetMessage).url;\n if (messageUrl && isValidHttpUrl(messageUrl)) {\n window.open(messageUrl, \"_blank\", \"noopener,noreferrer\");\n }\n }\n }\n\n window.addEventListener(\"message\", handleMessage);\n return () => window.removeEventListener(\"message\", handleMessage);\n }, [iframeRef, normalizedUrl, isValidUrl, editMode]);\n}\n\nfunction useModalBodyScrollLock(isOpen: boolean): void {\n useEffect(() => {\n if (!isOpen) return;\n const previousOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = previousOverflow;\n };\n }, [isOpen]);\n}\n\nfunction useModalEscapeClose(isOpen: boolean, onClose: () => void): void {\n useEffect(() => {\n if (!isOpen) return;\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") onClose();\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => window.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, onClose]);\n}\n\nfunction useDialogFocusRestore(dialogRef: RefObject<HTMLElement | null>): void {\n useEffect(() => {\n const previouslyFocused =\n document.activeElement instanceof HTMLElement\n ? document.activeElement\n : null;\n dialogRef.current?.focus();\n return () => {\n previouslyFocused?.focus();\n };\n }, [dialogRef]);\n}\n\n// ---------- header icon registry ----------\n\nconst HEADER_ICON_MAP: Record<string, LucideIcon> = {\n GraduationCap,\n Video,\n BookOpen,\n Globe,\n User,\n Star,\n Heart,\n Trophy,\n Sparkles,\n Zap,\n Gift,\n ShoppingBag,\n Bell,\n Calendar,\n Bookmark: BookmarkIcon,\n};\n\nconst HEADER_ICON_OPTIONS: Array<{ label: string; value: string }> = [\n { label: \"Graduation Cap\", value: \"GraduationCap\" },\n { label: \"Video\", value: \"Video\" },\n { label: \"Book\", value: \"BookOpen\" },\n { label: \"Globe\", value: \"Globe\" },\n { label: \"User\", value: \"User\" },\n { label: \"Star\", value: \"Star\" },\n { label: \"Heart\", value: \"Heart\" },\n { label: \"Trophy\", value: \"Trophy\" },\n { label: \"Sparkles\", value: \"Sparkles\" },\n { label: \"Zap / Lightning\", value: \"Zap\" },\n { label: \"Gift\", value: \"Gift\" },\n { label: \"Shopping Bag\", value: \"ShoppingBag\" },\n { label: \"Bell\", value: \"Bell\" },\n { label: \"Calendar\", value: \"Calendar\" },\n { label: \"Bookmark\", value: \"Bookmark\" },\n];\n\nconst getHeaderIcon = (name: string | undefined): LucideIcon => {\n if (!name) return GraduationCap;\n return HEADER_ICON_MAP[name] ?? GraduationCap;\n};\n\ntype EmbedWidgetProps = ComponentProps<\"div\"> & {\n url?: string;\n title?: string;\n height?: string;\n fullScreen?: boolean;\n allowFullscreen?: boolean;\n loading?: \"eager\" | \"lazy\";\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n editMode?: boolean;\n isSelected?: boolean;\n\n // Cover-mode additions (all optional — inline mode ignores these)\n displayMode?: DisplayMode;\n coverResource?: ShareableItem;\n coverUseCustomUrl?: boolean;\n coverImageUrl?: string;\n coverTitle?: string;\n coverMeta?: string;\n coverShowHeader?: boolean;\n coverHeaderIcon?: string;\n coverHeaderIconColor?: ColorOptions;\n coverHeight?: string;\n};\n\nexport function EmbedWidget({\n url = \"\",\n title = \"Embedded Content\",\n height = \"400px\",\n fullScreen = false,\n allowFullscreen = true,\n loading = \"lazy\",\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n editMode = false,\n isSelected = false,\n\n displayMode = \"inline\",\n coverResource,\n coverUseCustomUrl = false,\n coverImageUrl = \"\",\n coverTitle = \"\",\n coverMeta = \"\",\n coverShowHeader = true,\n coverHeaderIcon = \"GraduationCap\",\n coverHeaderIconColor = \"primary\",\n coverHeight = \"320px\",\n\n className,\n ...props\n}: EmbedWidgetProps): React.JSX.Element {\n const isFullScreen = fullScreen;\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const repUser = useRepUser();\n const publicId = repUser?.publicId;\n\n const [modalOpen, setModalOpen] = useState(false);\n const [coverReloadKey, setCoverReloadKey] = useState(0);\n const [iframeReloadKey, setIframeReloadKey] = useState(0);\n\n const closeModal = useCallback(() => setModalOpen(false), []);\n\n const { normalizedUrl, isValidUrl, iframeSrc } = useEmbedUrl(url, publicId);\n useEmbedPostMessageBridge({\n iframeRef,\n normalizedUrl,\n isValidUrl,\n editMode,\n });\n useModalBodyScrollLock(modalOpen);\n useModalEscapeClose(modalOpen, closeModal);\n\n // ----- Empty/invalid URL states -----\n\n if (!url || !isValidUrl) {\n return (\n <div\n className={`flex items-center justify-center rounded-${borderRadius} border-border bg-muted text-muted-foreground border-2 border-dashed ${className ?? \"\"}`}\n {...props}\n style={\n isFullScreen\n ? {\n height:\n \"var(--portal-fullscreen-embed-height, calc(100dvh - 4rem))\",\n }\n : { height: displayMode === \"cover\" ? coverHeight : height }\n }\n >\n <div className=\"flex flex-col items-center gap-2 p-6 text-center\">\n <Globe className=\"h-12 w-12 opacity-50\" />\n <p className=\"text-sm font-medium\">\n Enter a URL to embed external content\n </p>\n <p className=\"text-xs opacity-75\">\n Configure the URL in the properties panel\n </p>\n </div>\n </div>\n );\n }\n\n // ----- Cover mode -----\n\n if (displayMode === \"cover\") {\n const resolvedCoverImage = coverUseCustomUrl\n ? coverImageUrl\n : coverResource?.imageUrl || coverResource?.image_url || coverImageUrl;\n\n const effectiveTitle = coverTitle || title;\n const HeaderIcon = getHeaderIcon(coverHeaderIcon);\n\n const handleOpenModal = () => {\n if (editMode) return;\n setModalOpen(true);\n };\n\n const handleReload = () => {\n if (editMode) return;\n setCoverReloadKey((key) => key + 1);\n };\n\n const handleOpenNewTab = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (editMode) return;\n window.open(iframeSrc, \"_blank\", \"noopener,noreferrer\");\n };\n\n return (\n <>\n <div\n className={`relative w-full overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-background ${className ?? \"\"}`}\n style={{\n boxShadow:\n \"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)\",\n }}\n {...props}\n >\n {/* Inset hairline ring */}\n <div\n aria-hidden=\"true\"\n className={`pointer-events-none absolute inset-0 z-[1] rounded-${borderRadius}`}\n style={{\n boxShadow:\n \"inset 0 0 0 1px color-mix(in oklch, var(--color-foreground) 8%, transparent)\",\n }}\n />\n {coverShowHeader && (\n <div className=\"relative z-[2] flex items-center gap-3 px-5 py-3\">\n <span\n aria-hidden=\"true\"\n className={`text-${coverHeaderIconColor}-foreground flex size-7 shrink-0 items-center justify-center rounded-${borderRadius}`}\n style={{\n background: `linear-gradient(135deg, color-mix(in oklch, var(--color-${coverHeaderIconColor}) 75%, white 25%) 0%, var(--color-${coverHeaderIconColor}) 100%)`,\n boxShadow: `\n inset 0 1px 0 rgba(255,255,255,0.25),\n inset 0 -1px 0 rgba(0,0,0,0.08),\n 0 1px 2px color-mix(in oklch, var(--color-${coverHeaderIconColor}) 25%, transparent)\n `,\n }}\n >\n <HeaderIcon className=\"size-3.5\" strokeWidth={2.25} />\n </span>\n\n <div className=\"min-w-0 flex-1\">\n {effectiveTitle && (\n <h3 className=\"text-foreground truncate text-[15px] leading-tight font-semibold tracking-tight\">\n {effectiveTitle}\n </h3>\n )}\n {coverMeta && (\n <p className=\"text-foreground/40 mt-0.5 truncate text-[11px] font-medium tracking-[0.08em] uppercase\">\n {coverMeta}\n </p>\n )}\n </div>\n\n <div className=\"bg-foreground/5 flex shrink-0 items-center rounded-lg p-0.5\">\n <HeaderIconButton\n Icon={RotateCw}\n label=\"Reload\"\n onClick={(e) => {\n e.stopPropagation();\n handleReload();\n }}\n />\n <HeaderIconButton\n Icon={Maximize2}\n label=\"Open\"\n onClick={(e) => {\n e.stopPropagation();\n handleOpenModal();\n }}\n />\n <HeaderIconButton\n Icon={ExternalLink}\n label=\"Open in new tab\"\n onClick={handleOpenNewTab}\n />\n </div>\n </div>\n )}\n\n <button\n type=\"button\"\n onClick={handleOpenModal}\n disabled={editMode}\n className={`relative block w-full overflow-hidden ${editMode ? \"cursor-default\" : \"cursor-pointer\"}`}\n style={{ height: coverHeight }}\n aria-label={`Open ${effectiveTitle || title}`}\n >\n {resolvedCoverImage ? (\n <img\n key={`cover-${coverReloadKey}`}\n src={resolvedCoverImage}\n alt={effectiveTitle || title}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <div className=\"bg-muted flex h-full w-full items-center justify-center\">\n <Globe className=\"text-muted-foreground/40 size-16\" />\n </div>\n )}\n </button>\n {editMode && !isSelected && <div className=\"absolute inset-0 z-10\" />}\n </div>\n\n {modalOpen && (\n <EmbedModal\n key={`modal-${iframeReloadKey}`}\n src={iframeSrc}\n title={effectiveTitle || title}\n allowFullscreen={allowFullscreen}\n iframeRef={iframeRef}\n onClose={closeModal}\n onReload={() => setIframeReloadKey((key) => key + 1)}\n />\n )}\n </>\n );\n }\n\n // ----- Inline mode (original behavior) -----\n\n return (\n <div\n className={`relative w-full rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${className ?? \"\"}`}\n {...props}\n style={\n isFullScreen\n ? {\n height:\n \"var(--portal-fullscreen-embed-height, calc(100dvh - 4rem))\",\n }\n : undefined\n }\n >\n <iframe\n ref={iframeRef}\n src={iframeSrc}\n title={title}\n width=\"100%\"\n style={isFullScreen ? { height: \"100%\" } : { height }}\n loading={loading}\n allowFullScreen={allowFullscreen}\n className={`rounded-${borderRadius} border-border border`}\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox\"\n />\n {editMode && !isSelected && <div className=\"absolute inset-0 z-10\" />}\n </div>\n );\n}\n\n// ----- Header icon button -----\n\ntype HeaderIconButtonProps = {\n Icon: LucideIcon;\n label: string;\n onClick: (e: React.MouseEvent) => void;\n};\n\nfunction HeaderIconButton({\n Icon,\n label,\n onClick,\n}: HeaderIconButtonProps): React.JSX.Element {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={label}\n className=\"text-foreground/45 hover:text-foreground hover:bg-background flex size-7 items-center justify-center rounded-md transition-colors\"\n >\n <Icon className=\"size-3.5\" strokeWidth={2.25} />\n </button>\n );\n}\n\n// ----- Modal -----\n\ntype EmbedModalProps = {\n src: string;\n title: string;\n allowFullscreen: boolean;\n iframeRef: RefObject<HTMLIFrameElement | null>;\n onClose: () => void;\n onReload: () => void;\n};\n\nfunction EmbedModal({\n src,\n title,\n allowFullscreen,\n iframeRef,\n onClose,\n onReload,\n}: EmbedModalProps): React.JSX.Element {\n const dialogRef = useRef<HTMLDivElement>(null);\n\n useDialogFocusRestore(dialogRef);\n\n // Portal to document.body so the fixed-position dialog isn't clipped by\n // a transformed widget container on the live canvas (CSS transforms make\n // descendants the containing block for `position: fixed`).\n return createPortal(\n <div\n ref={dialogRef}\n tabIndex={-1}\n className=\"fixed inset-0 z-[100] flex items-center justify-center p-4 focus:outline-none sm:p-8\"\n style={{\n background: \"color-mix(in oklch, var(--color-foreground) 80%, black)\",\n }}\n onClick={onClose}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title}\n >\n <div\n className=\"bg-background relative flex h-full max-h-[95vh] w-full max-w-[1400px] flex-col overflow-hidden rounded-2xl shadow-2xl\"\n onClick={(e) => e.stopPropagation()}\n >\n <div\n className=\"flex items-center justify-between gap-4 px-5 py-3\"\n style={{\n borderBottom:\n \"1px solid color-mix(in oklch, var(--color-foreground) 8%, transparent)\",\n }}\n >\n <h3 className=\"text-foreground truncate text-sm font-semibold tracking-tight\">\n {title}\n </h3>\n <div className=\"flex shrink-0 items-center gap-1\">\n <HeaderIconButton\n Icon={RotateCw}\n label=\"Reload\"\n onClick={(e) => {\n e.stopPropagation();\n onReload();\n }}\n />\n <button\n type=\"button\"\n onClick={onClose}\n aria-label=\"Close\"\n className=\"text-foreground/60 hover:text-foreground hover:bg-foreground/5 flex size-9 shrink-0 items-center justify-center rounded-full transition-colors\"\n >\n <X className=\"size-5\" />\n </button>\n </div>\n </div>\n <iframe\n ref={iframeRef}\n src={src}\n title={title}\n className=\"flex-1 border-0\"\n allowFullScreen={allowFullscreen}\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox\"\n />\n </div>\n </div>,\n document.body,\n );\n}\n\n// ----- Schema -----\n\nexport const embedWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"EmbedWidget\",\n displayName: \"Embed\",\n fields: [\n // Content\n {\n key: \"url\",\n label: \"URL\",\n type: \"text\",\n description: \"The URL of the external site to embed\",\n placeholder: \"https://example.com\",\n defaultValue: \"\",\n group: \"Content\",\n },\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"Accessibility title for the embedded content\",\n defaultValue: \"Embedded Content\",\n group: \"Content\",\n },\n\n // Display Mode\n {\n key: \"displayMode\",\n label: \"Display Mode\",\n type: \"buttonGroup\",\n description:\n \"Inline: iframe renders directly. Cover: shows a card that opens the embed in a full-screen modal.\",\n defaultValue: \"inline\",\n options: [\n { label: \"Inline\", value: \"inline\" },\n { label: \"Cover + Modal\", value: \"cover\" },\n ],\n group: \"Display Mode\",\n },\n\n // Cover fields — all gated behind displayMode=cover\n {\n key: \"coverResource\",\n label: \"Cover Image\",\n type: \"resource\",\n description: \"Select the image shown before the embed opens\",\n allowedTypes: [\"Medium\"],\n group: \"Cover\",\n requiresKeyValue: { key: \"displayMode\", value: \"cover\" },\n },\n {\n key: \"coverUseCustomUrl\",\n label: \"Use Custom URL\",\n type: \"boolean\",\n description: \"Enter a custom image URL instead of selecting media\",\n defaultValue: false,\n group: \"Cover\",\n requiresKeyValue: { key: \"displayMode\", value: \"cover\" },\n },\n {\n key: \"coverImageUrl\",\n label: \"Cover Image URL\",\n type: \"text\",\n description: \"Direct URL to the cover image\",\n placeholder: \"https://example.com/cover.jpg\",\n defaultValue: \"\",\n group: \"Cover\",\n requiresKeyValue: [\n { key: \"displayMode\", value: \"cover\" },\n { key: \"coverUseCustomUrl\", value: true },\n ],\n },\n getHeightField({\n key: \"coverHeight\",\n label: \"Cover Height\",\n description: \"Height of the cover image area\",\n defaultValue: \"320px\",\n group: \"Cover\",\n requiresKeyValue: { key: \"displayMode\", value: \"cover\" },\n }),\n\n // Cover header (optional)\n {\n key: \"coverShowHeader\",\n label: \"Show Card Header\",\n type: \"boolean\",\n description: \"Show the header with icon, title, and action buttons\",\n defaultValue: true,\n group: \"Cover Header\",\n requiresKeyValue: { key: \"displayMode\", value: \"cover\" },\n },\n {\n key: \"coverHeaderIcon\",\n label: \"Header Icon\",\n type: \"select\",\n description: \"Icon displayed in the colored badge on the left\",\n options: HEADER_ICON_OPTIONS,\n defaultValue: \"GraduationCap\",\n group: \"Cover Header\",\n requiresKeyValue: [\n { key: \"displayMode\", value: \"cover\" },\n { key: \"coverShowHeader\", value: true },\n ],\n },\n getColorField({\n key: \"coverHeaderIconColor\",\n label: \"Icon Badge Color\",\n description: \"Background color of the icon badge\",\n defaultValue: \"primary\",\n group: \"Cover Header\",\n requiresKeyValue: [\n { key: \"displayMode\", value: \"cover\" },\n { key: \"coverShowHeader\", value: true },\n ],\n }),\n {\n key: \"coverTitle\",\n label: \"Header Title\",\n type: \"text\",\n description:\n \"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.\",\n defaultValue: \"\",\n group: \"Cover Header\",\n requiresKeyValue: { key: \"displayMode\", value: \"cover\" },\n },\n {\n key: \"coverMeta\",\n label: \"Meta Text\",\n type: \"text\",\n description:\n \"Small uppercase meta line below the title (e.g. 'APR 16 · COACHING THE HOSTESS')\",\n defaultValue: \"\",\n group: \"Cover Header\",\n requiresKeyValue: [\n { key: \"displayMode\", value: \"cover\" },\n { key: \"coverShowHeader\", value: true },\n ],\n },\n\n // Design\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the embed container\",\n defaultValue: \"md\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the widget\",\n defaultValue: \"none\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Border color for the widget\",\n defaultValue: \"muted\",\n group: \"Design\",\n }),\n {\n key: \"fullScreen\",\n label: \"Full Screen\",\n type: \"boolean\",\n description:\n \"Inline mode: fill the available space instead of a fixed height\",\n defaultValue: false,\n group: \"Design\",\n requiresKeyValue: { key: \"displayMode\", value: \"inline\" },\n },\n getHeightField({\n key: \"height\",\n label: \"Height\",\n description: \"Height of the inline embed iframe\",\n defaultValue: \"400px\",\n group: \"Design\",\n requiresKeyValue: [\n { key: \"displayMode\", value: \"inline\" },\n { key: \"fullScreen\", value: false },\n ],\n }),\n\n // Settings\n {\n key: \"allowFullscreen\",\n label: \"Allow Fullscreen\",\n type: \"boolean\",\n description: \"Allow the embedded content to use fullscreen mode\",\n defaultValue: true,\n group: \"Settings\",\n },\n {\n key: \"loading\",\n label: \"Loading\",\n type: \"select\",\n description: \"When to load the embedded content (inline mode only)\",\n options: [\n { label: \"Lazy (on scroll)\", value: \"lazy\" },\n { label: \"Eager (immediately)\", value: \"eager\" },\n ],\n defaultValue: \"lazy\",\n group: \"Settings\",\n requiresKeyValue: { key: \"displayMode\", value: \"inline\" },\n },\n ],\n};\n"],"mappings":"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"}
|
|
@@ -210,9 +210,9 @@ function EmbedWidget({ url = "", title = "Embedded Content", height = "400px", f
|
|
|
210
210
|
useModalBodyScrollLock(modalOpen);
|
|
211
211
|
useModalEscapeClose(modalOpen, closeModal);
|
|
212
212
|
if (!url || !isValidUrl) return /* @__PURE__ */ jsx("div", {
|
|
213
|
-
className: `flex items-center justify-center rounded-${borderRadius} border-border bg-muted text-muted-foreground border-2 border-dashed ${
|
|
214
|
-
style: isFullScreen ? void 0 : { height: displayMode === "cover" ? coverHeight : height },
|
|
213
|
+
className: `flex items-center justify-center rounded-${borderRadius} border-border bg-muted text-muted-foreground border-2 border-dashed ${className ?? ""}`,
|
|
215
214
|
...props,
|
|
215
|
+
style: isFullScreen ? { height: "var(--portal-fullscreen-embed-height, calc(100dvh - 4rem))" } : { height: displayMode === "cover" ? coverHeight : height },
|
|
216
216
|
children: /* @__PURE__ */ jsxs("div", {
|
|
217
217
|
className: "flex flex-col items-center gap-2 p-6 text-center",
|
|
218
218
|
children: [
|
|
@@ -340,8 +340,9 @@ function EmbedWidget({ url = "", title = "Embedded Content", height = "400px", f
|
|
|
340
340
|
}, `modal-${iframeReloadKey}`)] });
|
|
341
341
|
}
|
|
342
342
|
return /* @__PURE__ */ jsxs("div", {
|
|
343
|
-
className: `relative w-full rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== "none" ? borderColorClasses[borderColor] : ""} ${
|
|
343
|
+
className: `relative w-full rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== "none" ? borderColorClasses[borderColor] : ""} ${className ?? ""}`,
|
|
344
344
|
...props,
|
|
345
|
+
style: isFullScreen ? { height: "var(--portal-fullscreen-embed-height, calc(100dvh - 4rem))" } : void 0,
|
|
345
346
|
children: [/* @__PURE__ */ jsx("iframe", {
|
|
346
347
|
ref: iframeRef,
|
|
347
348
|
src: iframeSrc,
|
|
@@ -651,4 +652,4 @@ const embedWidgetPropertySchema = {
|
|
|
651
652
|
//#endregion
|
|
652
653
|
export { useRepUser as a, RepUserProvider as i, EmbedWidget_exports as n, embedWidgetPropertySchema as r, EmbedWidget as t };
|
|
653
654
|
|
|
654
|
-
//# sourceMappingURL=EmbedWidget-
|
|
655
|
+
//# sourceMappingURL=EmbedWidget-LYnd3TZD.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmbedWidget-LYnd3TZD.mjs","names":[],"sources":["../../widgets/src/contexts/RepUserContext.tsx","../../widgets/src/widgets/EmbedWidget.tsx"],"sourcesContent":["import React, {\n createContext,\n useContext,\n useMemo,\n type ReactNode,\n} from \"react\";\n\nexport interface RepUser {\n name: string | null;\n email: string | null;\n imageUrl: string | null;\n publicId?: string;\n}\n\nconst RepUserContext = createContext<RepUser | null>(null);\n\nexport interface RepUserProviderProps {\n user: RepUser;\n children: ReactNode;\n}\n\nexport function RepUserProvider({\n user,\n children,\n}: RepUserProviderProps): React.JSX.Element {\n const value = useMemo(() => user, [user]);\n return (\n <RepUserContext.Provider value={value}>{children}</RepUserContext.Provider>\n );\n}\n\nexport function useRepUser(): RepUser | null {\n return useContext(RepUserContext);\n}\n","import {\n Bell,\n BookmarkIcon,\n BookOpen,\n Calendar,\n ExternalLink,\n Gift,\n Globe,\n GraduationCap,\n Heart,\n Maximize2,\n RotateCw,\n ShoppingBag,\n Sparkles,\n Star,\n Trophy,\n User,\n Video,\n X,\n Zap,\n type LucideIcon,\n} from \"lucide-react\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ComponentProps,\n type RefObject,\n} from \"react\";\nimport type React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport {\n getBorderRadiusField,\n getHeightField,\n type WidgetPropertySchema,\n} from \"@fluid-app/portal-core/registries\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n ShareableItem,\n} from \"@fluid-app/portal-core/types\";\nimport {\n getBorderWidthField,\n getBorderColorField,\n getColorField,\n borderWidthClasses,\n borderColorClasses,\n} from \"../core/fields\";\nimport { useRepUser } from \"../contexts/RepUserContext\";\n\ntype EmbedWidgetMessage = {\n type: \"OPEN_FULL_SCREEN_WEBVIEW\";\n url: string;\n};\n\ntype DisplayMode = \"inline\" | \"cover\";\n\ntype EmbedUrlState = {\n normalizedUrl: string;\n isValidUrl: boolean;\n iframeSrc: string;\n};\n\nfunction isValidHttpUrl(urlString: string): boolean {\n try {\n const parsed = new URL(urlString);\n return parsed.protocol === \"https:\" || parsed.protocol === \"http:\";\n } catch {\n return false;\n }\n}\n\nfunction useEmbedUrl(url: string, publicId: string | undefined): EmbedUrlState {\n return useMemo(() => {\n const normalizedUrl =\n url && (url.startsWith(\"http://\") || url.startsWith(\"https://\"))\n ? url\n : url\n ? `https://${url}`\n : \"\";\n\n let isValidUrl = false;\n if (normalizedUrl) {\n try {\n const parsed = new URL(normalizedUrl);\n isValidUrl =\n (parsed.protocol === \"http:\" || parsed.protocol === \"https:\") &&\n (parsed.hostname.includes(\".\") || parsed.hostname === \"localhost\");\n } catch {\n // invalid URL\n }\n }\n\n if (!isValidUrl || !publicId) {\n return { normalizedUrl, isValidUrl, iframeSrc: normalizedUrl };\n }\n\n const urlObj = new URL(normalizedUrl);\n urlObj.searchParams.set(\"public_id\", publicId);\n return { normalizedUrl, isValidUrl, iframeSrc: urlObj.toString() };\n }, [url, publicId]);\n}\n\ntype UseEmbedPostMessageBridgeProps = {\n iframeRef: RefObject<HTMLIFrameElement | null>;\n normalizedUrl: string;\n isValidUrl: boolean;\n editMode: boolean;\n};\n\nfunction useEmbedPostMessageBridge({\n iframeRef,\n normalizedUrl,\n isValidUrl,\n editMode,\n}: UseEmbedPostMessageBridgeProps): void {\n useEffect(() => {\n if (!isValidUrl || editMode) return;\n\n const expectedOrigin = new URL(normalizedUrl).origin;\n\n function handleMessage(event: MessageEvent) {\n if (event.origin !== expectedOrigin) return;\n if (event.source !== iframeRef.current?.contentWindow) return;\n\n let data: unknown;\n if (typeof event.data === \"string\") {\n try {\n data = JSON.parse(event.data);\n } catch {\n return;\n }\n } else {\n data = event.data;\n }\n\n if (\n typeof data === \"object\" &&\n data !== null &&\n \"type\" in data &&\n (data as EmbedWidgetMessage).type === \"OPEN_FULL_SCREEN_WEBVIEW\"\n ) {\n const messageUrl = (data as EmbedWidgetMessage).url;\n if (messageUrl && isValidHttpUrl(messageUrl)) {\n window.open(messageUrl, \"_blank\", \"noopener,noreferrer\");\n }\n }\n }\n\n window.addEventListener(\"message\", handleMessage);\n return () => window.removeEventListener(\"message\", handleMessage);\n }, [iframeRef, normalizedUrl, isValidUrl, editMode]);\n}\n\nfunction useModalBodyScrollLock(isOpen: boolean): void {\n useEffect(() => {\n if (!isOpen) return;\n const previousOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = previousOverflow;\n };\n }, [isOpen]);\n}\n\nfunction useModalEscapeClose(isOpen: boolean, onClose: () => void): void {\n useEffect(() => {\n if (!isOpen) return;\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") onClose();\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => window.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, onClose]);\n}\n\nfunction useDialogFocusRestore(dialogRef: RefObject<HTMLElement | null>): void {\n useEffect(() => {\n const previouslyFocused =\n document.activeElement instanceof HTMLElement\n ? document.activeElement\n : null;\n dialogRef.current?.focus();\n return () => {\n previouslyFocused?.focus();\n };\n }, [dialogRef]);\n}\n\n// ---------- header icon registry ----------\n\nconst HEADER_ICON_MAP: Record<string, LucideIcon> = {\n GraduationCap,\n Video,\n BookOpen,\n Globe,\n User,\n Star,\n Heart,\n Trophy,\n Sparkles,\n Zap,\n Gift,\n ShoppingBag,\n Bell,\n Calendar,\n Bookmark: BookmarkIcon,\n};\n\nconst HEADER_ICON_OPTIONS: Array<{ label: string; value: string }> = [\n { label: \"Graduation Cap\", value: \"GraduationCap\" },\n { label: \"Video\", value: \"Video\" },\n { label: \"Book\", value: \"BookOpen\" },\n { label: \"Globe\", value: \"Globe\" },\n { label: \"User\", value: \"User\" },\n { label: \"Star\", value: \"Star\" },\n { label: \"Heart\", value: \"Heart\" },\n { label: \"Trophy\", value: \"Trophy\" },\n { label: \"Sparkles\", value: \"Sparkles\" },\n { label: \"Zap / Lightning\", value: \"Zap\" },\n { label: \"Gift\", value: \"Gift\" },\n { label: \"Shopping Bag\", value: \"ShoppingBag\" },\n { label: \"Bell\", value: \"Bell\" },\n { label: \"Calendar\", value: \"Calendar\" },\n { label: \"Bookmark\", value: \"Bookmark\" },\n];\n\nconst getHeaderIcon = (name: string | undefined): LucideIcon => {\n if (!name) return GraduationCap;\n return HEADER_ICON_MAP[name] ?? GraduationCap;\n};\n\ntype EmbedWidgetProps = ComponentProps<\"div\"> & {\n url?: string;\n title?: string;\n height?: string;\n fullScreen?: boolean;\n allowFullscreen?: boolean;\n loading?: \"eager\" | \"lazy\";\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n editMode?: boolean;\n isSelected?: boolean;\n\n // Cover-mode additions (all optional — inline mode ignores these)\n displayMode?: DisplayMode;\n coverResource?: ShareableItem;\n coverUseCustomUrl?: boolean;\n coverImageUrl?: string;\n coverTitle?: string;\n coverMeta?: string;\n coverShowHeader?: boolean;\n coverHeaderIcon?: string;\n coverHeaderIconColor?: ColorOptions;\n coverHeight?: string;\n};\n\nexport function EmbedWidget({\n url = \"\",\n title = \"Embedded Content\",\n height = \"400px\",\n fullScreen = false,\n allowFullscreen = true,\n loading = \"lazy\",\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n editMode = false,\n isSelected = false,\n\n displayMode = \"inline\",\n coverResource,\n coverUseCustomUrl = false,\n coverImageUrl = \"\",\n coverTitle = \"\",\n coverMeta = \"\",\n coverShowHeader = true,\n coverHeaderIcon = \"GraduationCap\",\n coverHeaderIconColor = \"primary\",\n coverHeight = \"320px\",\n\n className,\n ...props\n}: EmbedWidgetProps): React.JSX.Element {\n const isFullScreen = fullScreen;\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const repUser = useRepUser();\n const publicId = repUser?.publicId;\n\n const [modalOpen, setModalOpen] = useState(false);\n const [coverReloadKey, setCoverReloadKey] = useState(0);\n const [iframeReloadKey, setIframeReloadKey] = useState(0);\n\n const closeModal = useCallback(() => setModalOpen(false), []);\n\n const { normalizedUrl, isValidUrl, iframeSrc } = useEmbedUrl(url, publicId);\n useEmbedPostMessageBridge({\n iframeRef,\n normalizedUrl,\n isValidUrl,\n editMode,\n });\n useModalBodyScrollLock(modalOpen);\n useModalEscapeClose(modalOpen, closeModal);\n\n // ----- Empty/invalid URL states -----\n\n if (!url || !isValidUrl) {\n return (\n <div\n className={`flex items-center justify-center rounded-${borderRadius} border-border bg-muted text-muted-foreground border-2 border-dashed ${className ?? \"\"}`}\n {...props}\n style={\n isFullScreen\n ? {\n height:\n \"var(--portal-fullscreen-embed-height, calc(100dvh - 4rem))\",\n }\n : { height: displayMode === \"cover\" ? coverHeight : height }\n }\n >\n <div className=\"flex flex-col items-center gap-2 p-6 text-center\">\n <Globe className=\"h-12 w-12 opacity-50\" />\n <p className=\"text-sm font-medium\">\n Enter a URL to embed external content\n </p>\n <p className=\"text-xs opacity-75\">\n Configure the URL in the properties panel\n </p>\n </div>\n </div>\n );\n }\n\n // ----- Cover mode -----\n\n if (displayMode === \"cover\") {\n const resolvedCoverImage = coverUseCustomUrl\n ? coverImageUrl\n : coverResource?.imageUrl || coverResource?.image_url || coverImageUrl;\n\n const effectiveTitle = coverTitle || title;\n const HeaderIcon = getHeaderIcon(coverHeaderIcon);\n\n const handleOpenModal = () => {\n if (editMode) return;\n setModalOpen(true);\n };\n\n const handleReload = () => {\n if (editMode) return;\n setCoverReloadKey((key) => key + 1);\n };\n\n const handleOpenNewTab = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (editMode) return;\n window.open(iframeSrc, \"_blank\", \"noopener,noreferrer\");\n };\n\n return (\n <>\n <div\n className={`relative w-full overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-background ${className ?? \"\"}`}\n style={{\n boxShadow:\n \"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)\",\n }}\n {...props}\n >\n {/* Inset hairline ring */}\n <div\n aria-hidden=\"true\"\n className={`pointer-events-none absolute inset-0 z-[1] rounded-${borderRadius}`}\n style={{\n boxShadow:\n \"inset 0 0 0 1px color-mix(in oklch, var(--color-foreground) 8%, transparent)\",\n }}\n />\n {coverShowHeader && (\n <div className=\"relative z-[2] flex items-center gap-3 px-5 py-3\">\n <span\n aria-hidden=\"true\"\n className={`text-${coverHeaderIconColor}-foreground flex size-7 shrink-0 items-center justify-center rounded-${borderRadius}`}\n style={{\n background: `linear-gradient(135deg, color-mix(in oklch, var(--color-${coverHeaderIconColor}) 75%, white 25%) 0%, var(--color-${coverHeaderIconColor}) 100%)`,\n boxShadow: `\n inset 0 1px 0 rgba(255,255,255,0.25),\n inset 0 -1px 0 rgba(0,0,0,0.08),\n 0 1px 2px color-mix(in oklch, var(--color-${coverHeaderIconColor}) 25%, transparent)\n `,\n }}\n >\n <HeaderIcon className=\"size-3.5\" strokeWidth={2.25} />\n </span>\n\n <div className=\"min-w-0 flex-1\">\n {effectiveTitle && (\n <h3 className=\"text-foreground truncate text-[15px] leading-tight font-semibold tracking-tight\">\n {effectiveTitle}\n </h3>\n )}\n {coverMeta && (\n <p className=\"text-foreground/40 mt-0.5 truncate text-[11px] font-medium tracking-[0.08em] uppercase\">\n {coverMeta}\n </p>\n )}\n </div>\n\n <div className=\"bg-foreground/5 flex shrink-0 items-center rounded-lg p-0.5\">\n <HeaderIconButton\n Icon={RotateCw}\n label=\"Reload\"\n onClick={(e) => {\n e.stopPropagation();\n handleReload();\n }}\n />\n <HeaderIconButton\n Icon={Maximize2}\n label=\"Open\"\n onClick={(e) => {\n e.stopPropagation();\n handleOpenModal();\n }}\n />\n <HeaderIconButton\n Icon={ExternalLink}\n label=\"Open in new tab\"\n onClick={handleOpenNewTab}\n />\n </div>\n </div>\n )}\n\n <button\n type=\"button\"\n onClick={handleOpenModal}\n disabled={editMode}\n className={`relative block w-full overflow-hidden ${editMode ? \"cursor-default\" : \"cursor-pointer\"}`}\n style={{ height: coverHeight }}\n aria-label={`Open ${effectiveTitle || title}`}\n >\n {resolvedCoverImage ? (\n <img\n key={`cover-${coverReloadKey}`}\n src={resolvedCoverImage}\n alt={effectiveTitle || title}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <div className=\"bg-muted flex h-full w-full items-center justify-center\">\n <Globe className=\"text-muted-foreground/40 size-16\" />\n </div>\n )}\n </button>\n {editMode && !isSelected && <div className=\"absolute inset-0 z-10\" />}\n </div>\n\n {modalOpen && (\n <EmbedModal\n key={`modal-${iframeReloadKey}`}\n src={iframeSrc}\n title={effectiveTitle || title}\n allowFullscreen={allowFullscreen}\n iframeRef={iframeRef}\n onClose={closeModal}\n onReload={() => setIframeReloadKey((key) => key + 1)}\n />\n )}\n </>\n );\n }\n\n // ----- Inline mode (original behavior) -----\n\n return (\n <div\n className={`relative w-full rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${className ?? \"\"}`}\n {...props}\n style={\n isFullScreen\n ? {\n height:\n \"var(--portal-fullscreen-embed-height, calc(100dvh - 4rem))\",\n }\n : undefined\n }\n >\n <iframe\n ref={iframeRef}\n src={iframeSrc}\n title={title}\n width=\"100%\"\n style={isFullScreen ? { height: \"100%\" } : { height }}\n loading={loading}\n allowFullScreen={allowFullscreen}\n className={`rounded-${borderRadius} border-border border`}\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox\"\n />\n {editMode && !isSelected && <div className=\"absolute inset-0 z-10\" />}\n </div>\n );\n}\n\n// ----- Header icon button -----\n\ntype HeaderIconButtonProps = {\n Icon: LucideIcon;\n label: string;\n onClick: (e: React.MouseEvent) => void;\n};\n\nfunction HeaderIconButton({\n Icon,\n label,\n onClick,\n}: HeaderIconButtonProps): React.JSX.Element {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={label}\n className=\"text-foreground/45 hover:text-foreground hover:bg-background flex size-7 items-center justify-center rounded-md transition-colors\"\n >\n <Icon className=\"size-3.5\" strokeWidth={2.25} />\n </button>\n );\n}\n\n// ----- Modal -----\n\ntype EmbedModalProps = {\n src: string;\n title: string;\n allowFullscreen: boolean;\n iframeRef: RefObject<HTMLIFrameElement | null>;\n onClose: () => void;\n onReload: () => void;\n};\n\nfunction EmbedModal({\n src,\n title,\n allowFullscreen,\n iframeRef,\n onClose,\n onReload,\n}: EmbedModalProps): React.JSX.Element {\n const dialogRef = useRef<HTMLDivElement>(null);\n\n useDialogFocusRestore(dialogRef);\n\n // Portal to document.body so the fixed-position dialog isn't clipped by\n // a transformed widget container on the live canvas (CSS transforms make\n // descendants the containing block for `position: fixed`).\n return createPortal(\n <div\n ref={dialogRef}\n tabIndex={-1}\n className=\"fixed inset-0 z-[100] flex items-center justify-center p-4 focus:outline-none sm:p-8\"\n style={{\n background: \"color-mix(in oklch, var(--color-foreground) 80%, black)\",\n }}\n onClick={onClose}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title}\n >\n <div\n className=\"bg-background relative flex h-full max-h-[95vh] w-full max-w-[1400px] flex-col overflow-hidden rounded-2xl shadow-2xl\"\n onClick={(e) => e.stopPropagation()}\n >\n <div\n className=\"flex items-center justify-between gap-4 px-5 py-3\"\n style={{\n borderBottom:\n \"1px solid color-mix(in oklch, var(--color-foreground) 8%, transparent)\",\n }}\n >\n <h3 className=\"text-foreground truncate text-sm font-semibold tracking-tight\">\n {title}\n </h3>\n <div className=\"flex shrink-0 items-center gap-1\">\n <HeaderIconButton\n Icon={RotateCw}\n label=\"Reload\"\n onClick={(e) => {\n e.stopPropagation();\n onReload();\n }}\n />\n <button\n type=\"button\"\n onClick={onClose}\n aria-label=\"Close\"\n className=\"text-foreground/60 hover:text-foreground hover:bg-foreground/5 flex size-9 shrink-0 items-center justify-center rounded-full transition-colors\"\n >\n <X className=\"size-5\" />\n </button>\n </div>\n </div>\n <iframe\n ref={iframeRef}\n src={src}\n title={title}\n className=\"flex-1 border-0\"\n allowFullScreen={allowFullscreen}\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox\"\n />\n </div>\n </div>,\n document.body,\n );\n}\n\n// ----- Schema -----\n\nexport const embedWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"EmbedWidget\",\n displayName: \"Embed\",\n fields: [\n // Content\n {\n key: \"url\",\n label: \"URL\",\n type: \"text\",\n description: \"The URL of the external site to embed\",\n placeholder: \"https://example.com\",\n defaultValue: \"\",\n group: \"Content\",\n },\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"Accessibility title for the embedded content\",\n defaultValue: \"Embedded Content\",\n group: \"Content\",\n },\n\n // Display Mode\n {\n key: \"displayMode\",\n label: \"Display Mode\",\n type: \"buttonGroup\",\n description:\n \"Inline: iframe renders directly. Cover: shows a card that opens the embed in a full-screen modal.\",\n defaultValue: \"inline\",\n options: [\n { label: \"Inline\", value: \"inline\" },\n { label: \"Cover + Modal\", value: \"cover\" },\n ],\n group: \"Display Mode\",\n },\n\n // Cover fields — all gated behind displayMode=cover\n {\n key: \"coverResource\",\n label: \"Cover Image\",\n type: \"resource\",\n description: \"Select the image shown before the embed opens\",\n allowedTypes: [\"Medium\"],\n group: \"Cover\",\n requiresKeyValue: { key: \"displayMode\", value: \"cover\" },\n },\n {\n key: \"coverUseCustomUrl\",\n label: \"Use Custom URL\",\n type: \"boolean\",\n description: \"Enter a custom image URL instead of selecting media\",\n defaultValue: false,\n group: \"Cover\",\n requiresKeyValue: { key: \"displayMode\", value: \"cover\" },\n },\n {\n key: \"coverImageUrl\",\n label: \"Cover Image URL\",\n type: \"text\",\n description: \"Direct URL to the cover image\",\n placeholder: \"https://example.com/cover.jpg\",\n defaultValue: \"\",\n group: \"Cover\",\n requiresKeyValue: [\n { key: \"displayMode\", value: \"cover\" },\n { key: \"coverUseCustomUrl\", value: true },\n ],\n },\n getHeightField({\n key: \"coverHeight\",\n label: \"Cover Height\",\n description: \"Height of the cover image area\",\n defaultValue: \"320px\",\n group: \"Cover\",\n requiresKeyValue: { key: \"displayMode\", value: \"cover\" },\n }),\n\n // Cover header (optional)\n {\n key: \"coverShowHeader\",\n label: \"Show Card Header\",\n type: \"boolean\",\n description: \"Show the header with icon, title, and action buttons\",\n defaultValue: true,\n group: \"Cover Header\",\n requiresKeyValue: { key: \"displayMode\", value: \"cover\" },\n },\n {\n key: \"coverHeaderIcon\",\n label: \"Header Icon\",\n type: \"select\",\n description: \"Icon displayed in the colored badge on the left\",\n options: HEADER_ICON_OPTIONS,\n defaultValue: \"GraduationCap\",\n group: \"Cover Header\",\n requiresKeyValue: [\n { key: \"displayMode\", value: \"cover\" },\n { key: \"coverShowHeader\", value: true },\n ],\n },\n getColorField({\n key: \"coverHeaderIconColor\",\n label: \"Icon Badge Color\",\n description: \"Background color of the icon badge\",\n defaultValue: \"primary\",\n group: \"Cover Header\",\n requiresKeyValue: [\n { key: \"displayMode\", value: \"cover\" },\n { key: \"coverShowHeader\", value: true },\n ],\n }),\n {\n key: \"coverTitle\",\n label: \"Header Title\",\n type: \"text\",\n description:\n \"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.\",\n defaultValue: \"\",\n group: \"Cover Header\",\n requiresKeyValue: { key: \"displayMode\", value: \"cover\" },\n },\n {\n key: \"coverMeta\",\n label: \"Meta Text\",\n type: \"text\",\n description:\n \"Small uppercase meta line below the title (e.g. 'APR 16 · COACHING THE HOSTESS')\",\n defaultValue: \"\",\n group: \"Cover Header\",\n requiresKeyValue: [\n { key: \"displayMode\", value: \"cover\" },\n { key: \"coverShowHeader\", value: true },\n ],\n },\n\n // Design\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the embed container\",\n defaultValue: \"md\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the widget\",\n defaultValue: \"none\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Border color for the widget\",\n defaultValue: \"muted\",\n group: \"Design\",\n }),\n {\n key: \"fullScreen\",\n label: \"Full Screen\",\n type: \"boolean\",\n description:\n \"Inline mode: fill the available space instead of a fixed height\",\n defaultValue: false,\n group: \"Design\",\n requiresKeyValue: { key: \"displayMode\", value: \"inline\" },\n },\n getHeightField({\n key: \"height\",\n label: \"Height\",\n description: \"Height of the inline embed iframe\",\n defaultValue: \"400px\",\n group: \"Design\",\n requiresKeyValue: [\n { key: \"displayMode\", value: \"inline\" },\n { key: \"fullScreen\", value: false },\n ],\n }),\n\n // Settings\n {\n key: \"allowFullscreen\",\n label: \"Allow Fullscreen\",\n type: \"boolean\",\n description: \"Allow the embedded content to use fullscreen mode\",\n defaultValue: true,\n group: \"Settings\",\n },\n {\n key: \"loading\",\n label: \"Loading\",\n type: \"select\",\n description: \"When to load the embedded content (inline mode only)\",\n options: [\n { label: \"Lazy (on scroll)\", value: \"lazy\" },\n { label: \"Eager (immediately)\", value: \"eager\" },\n ],\n defaultValue: \"lazy\",\n group: \"Settings\",\n requiresKeyValue: { key: \"displayMode\", value: \"inline\" },\n },\n ],\n};\n"],"mappings":"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"}
|
|
@@ -9,7 +9,7 @@ import { C as pages_show, a as content_playlists_by_shares, b as media_show, i a
|
|
|
9
9
|
import { C as resolveTheme, r as removeTheme, t as applyTheme } from "./src-C9vtVoJs.mjs";
|
|
10
10
|
import { n as usePortalTenantClient, t as PortalTenantClientProvider } from "./PortalTenantClientProvider-CjJzBCTL.mjs";
|
|
11
11
|
import { t as DataSourceRegistryProvider } from "./registry-context-CTHUCfEc.mjs";
|
|
12
|
-
import { t as EmbedWidget } from "./EmbedWidget-
|
|
12
|
+
import { t as EmbedWidget } from "./EmbedWidget-LYnd3TZD.mjs";
|
|
13
13
|
import { r as WidgetsApiProvider } from "./error-state-DYzHx8tt.mjs";
|
|
14
14
|
import { t as LayoutWidget } from "./LayoutWidget-UI5fbsx4.mjs";
|
|
15
15
|
import { t as TextWidget } from "./TextWidget-BteaMIsX.mjs";
|
|
@@ -2041,7 +2041,7 @@ const widgetPropertySchemas = {
|
|
|
2041
2041
|
CatchUpWidget: () => import("./CatchUpWidget-B9CI7lq0.mjs").then((n) => n.n).then((m) => m.catchUpWidgetPropertySchema),
|
|
2042
2042
|
ChartWidget: () => import("./ChartWidget-obje-Xj9.mjs").then((n) => n.n).then((m) => m.chartWidgetPropertySchema),
|
|
2043
2043
|
ContainerWidget: () => import("./ContainerWidget-DNenbORS.mjs").then((n) => n.n).then((m) => m.containerWidgetPropertySchema),
|
|
2044
|
-
EmbedWidget: () => import("./EmbedWidget-
|
|
2044
|
+
EmbedWidget: () => import("./EmbedWidget-LYnd3TZD.mjs").then((n) => n.n).then((m) => m.embedWidgetPropertySchema),
|
|
2045
2045
|
ImageWidget: () => import("./ImageWidget-vNWT_O1E.mjs").then((n) => n.n).then((m) => m.imageWidgetPropertySchema),
|
|
2046
2046
|
LayoutWidget: () => import("./LayoutWidget-UI5fbsx4.mjs").then((n) => n.n).then((m) => m.layoutWidgetPropertySchema),
|
|
2047
2047
|
LinkWidget: () => import("./LinkWidget-CO-Cxf7Z.mjs").then((n) => n.n).then((m) => m.linkWidgetPropertySchema),
|
|
@@ -2234,4 +2234,4 @@ function useFluidContext() {
|
|
|
2234
2234
|
//#endregion
|
|
2235
2235
|
export { createScreen as a, FluidThemeProvider as c, useLanguagesApi as d, useAppDefinitionApi as f, widgetPropertySchemas as i, useThemeContext as l, deleteDatabase as m, useFluidContext as n, createWidgetFromShareable as o, createPersister as p, DEFAULT_SDK_WIDGET_REGISTRY as r, createWidgetRegistry as s, FluidProvider as t, ApiError as u };
|
|
2236
2236
|
|
|
2237
|
-
//# sourceMappingURL=FluidProvider-
|
|
2237
|
+
//# sourceMappingURL=FluidProvider-CNk1Y2k1.mjs.map
|