import { ft as __exportAll } from "./translation-adapter-RsuBioxm.mjs";
import { i as useOptionalStore } from "./use-optional-store-DpB_jK4Q.mjs";
import { n as useRepUser } from "./RepUserContext-CBe1s8qG.mjs";
import { t as useWidgetRenderState } from "./WidgetRenderStateContext-CksDoD6G.mjs";
import { r as useShellTranslation } from "./shell-translation-api-context-ghBBW7ju.mjs";
import { i as getBorderColorField, l as getColorField, n as borderWidthClasses, o as getBorderRadiusField, p as getHeightField, s as getBorderWidthField, t as borderColorClasses } from "./registries-DXVOnKV2.mjs";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
import { Bell, BookOpen, BookmarkIcon, Calendar, ExternalLink, Gift, Globe, GraduationCap, Heart, Maximize2, RotateCw, ShoppingBag, Sparkles, Star, Trophy, User, Video, X, Zap } from "lucide-react";
import { createPortal } from "react-dom";
//#region ../../platform/app-bridge/src/errors.ts
var FluidBridgeError = class extends Error {
	code;
	details;
	constructor(code, message, details) {
		super(message);
		this.name = "FluidBridgeError";
		this.code = code;
		this.details = details;
	}
};
var FluidBridgeIncompatibleVersionError = class extends FluidBridgeError {
	constructor(message = "Fluid App Bridge SDK is not compatible with the host", details) {
		super("incompatible_version", message, details);
		this.name = "FluidBridgeIncompatibleVersionError";
	}
};
var FluidBridgeTokenMintError = class extends FluidBridgeError {
	constructor(message = "Fluid App Bridge host could not mint a session token", details) {
		super("token_mint_failed", message, details);
		this.name = "FluidBridgeTokenMintError";
	}
};
var FluidBridgeUnauthorizedError = class extends FluidBridgeError {
	constructor(message = "Fluid App Bridge request is unauthorized", details) {
		super("unauthorized", message, details);
		this.name = "FluidBridgeUnauthorizedError";
	}
};
var FluidBridgeForbiddenOriginError = class extends FluidBridgeError {
	constructor(message = "Fluid App Bridge host origin is forbidden", details) {
		super("forbidden_origin", message, details);
		this.name = "FluidBridgeForbiddenOriginError";
	}
};
var FluidBridgeInvalidContextError = class extends FluidBridgeError {
	constructor(message = "Fluid App Bridge context is invalid", details) {
		super("invalid_context", message, details);
		this.name = "FluidBridgeInvalidContextError";
	}
};
var FluidBridgeFailedAuthenticationError = class extends FluidBridgeError {
	constructor(message = "Fluid App Bridge authentication failed", details) {
		super("failed_authentication", message, details);
		this.name = "FluidBridgeFailedAuthenticationError";
	}
};
//#endregion
//#region ../../platform/app-bridge/src/protocol.ts
const FLUID_BRIDGE_PROTOCOL_VERSION = "2026-07";
const APP_BRIDGE_SDK_NAME = "@fluid-commerce/app-bridge";
const APP_BRIDGE_SDK_VERSION = "0.1.0";
const FluidBridgeMessageType = {
	SessionTokenRequest: "FLUID::SESSION_TOKEN_REQUEST",
	SessionTokenRespond: "FLUID::SESSION_TOKEN_RESPOND",
	ContextRequest: "FLUID::CONTEXT_REQUEST",
	ContextRespond: "FLUID::CONTEXT_RESPOND",
	FailedAuthentication: "FLUID::ERROR::FAILED_AUTHENTICATION",
	Unauthorized: "FLUID::ERROR::UNAUTHORIZED",
	IncompatibleVersion: "FLUID::ERROR::INCOMPATIBLE_VERSION",
	TokenMintFailed: "FLUID::ERROR::TOKEN_MINT_FAILED",
	InvalidContext: "FLUID::ERROR::INVALID_CONTEXT"
};
//#endregion
//#region ../../platform/app-bridge/src/host.ts
function createFluidBridgeHost(options) {
	const targetWindow = options.targetWindow ?? window;
	const appOrigin = normalizeOrigin(options.appOrigin);
	const handleMessage = (event) => {
		if (event.origin !== appOrigin) return;
		if (event.source !== options.iframe.contentWindow) return;
		if (!isBridgeEnvelope(event.data)) return;
		respondToBridgeMessage(options, event.data, appOrigin);
	};
	targetWindow.addEventListener("message", handleMessage);
	return { destroy: () => targetWindow.removeEventListener("message", handleMessage) };
}
async function respondToBridgeMessage(options, envelope, appOrigin) {
	const childWindow = options.iframe.contentWindow;
	if (!childWindow) return;
	try {
		validateRequestPayload(envelope.payload, options.clientId);
		switch (envelope.type) {
			case FluidBridgeMessageType.ContextRequest: {
				const context = await options.getContext();
				childWindow.postMessage({
					id: envelope.id,
					type: FluidBridgeMessageType.ContextRespond,
					payload: context
				}, appOrigin);
				return;
			}
			case FluidBridgeMessageType.SessionTokenRequest: {
				const context = await options.getContext();
				const sessionToken = await options.getSessionToken(context);
				if (sessionToken.length === 0) throw new FluidBridgeTokenMintError("Fluid App Bridge host returned an empty session token");
				childWindow.postMessage({
					id: envelope.id,
					type: FluidBridgeMessageType.SessionTokenRespond,
					payload: { sessionToken }
				}, appOrigin);
				return;
			}
			default: throw new FluidBridgeForbiddenOriginError("Fluid App Bridge host received an unsupported message type", { type: envelope.type });
		}
	} catch (error) {
		childWindow.postMessage({
			id: envelope.id,
			type: errorTypeFor(error),
			payload: errorPayloadFor(error)
		}, appOrigin);
	}
}
function validateRequestPayload(value, clientId) {
	if (typeof value !== "object" || value === null) throw new FluidBridgeInvalidContextError("Fluid App Bridge request payload is invalid");
	if (!("clientId" in value) || value.clientId !== clientId) throw new FluidBridgeFailedAuthenticationError("Fluid App Bridge request client ID does not match the host context");
	if (!("protocol" in value) || value.protocol !== "2026-07") throw new FluidBridgeIncompatibleVersionError();
	return value;
}
function isBridgeEnvelope(value) {
	if (typeof value !== "object" || value === null) return false;
	return "id" in value && "type" in value && "payload" in value && typeof value.id === "string" && typeof value.type === "string";
}
function errorTypeFor(error) {
	if (error instanceof FluidBridgeFailedAuthenticationError) return FluidBridgeMessageType.FailedAuthentication;
	if (error instanceof FluidBridgeIncompatibleVersionError) return FluidBridgeMessageType.IncompatibleVersion;
	if (error instanceof FluidBridgeUnauthorizedError) return FluidBridgeMessageType.Unauthorized;
	if (error instanceof FluidBridgeTokenMintError) return FluidBridgeMessageType.TokenMintFailed;
	if (error instanceof FluidBridgeInvalidContextError) return FluidBridgeMessageType.InvalidContext;
	if (error instanceof FluidBridgeForbiddenOriginError) return FluidBridgeMessageType.InvalidContext;
	return FluidBridgeMessageType.TokenMintFailed;
}
function errorPayloadFor(error) {
	if (error instanceof Error && "code" in error && typeof error.code === "string") return {
		code: error.code,
		message: error.message,
		details: "details" in error ? error.details : void 0
	};
	return {
		code: "token_mint_failed",
		message: "Fluid App Bridge host could not complete the request",
		details: error
	};
}
function normalizeOrigin(origin) {
	return new URL(origin).origin;
}
//#endregion
//#region ../../platform/app-bridge/src/session-token-api.ts
const DEFAULT_SESSION_TOKEN_PATH = "api/v2025-06/app_bridge/session_token";
async function mintAppBridgeSessionToken({ request, apiBaseUrl, authToken, fetch: fetchImplementation = globalThis.fetch?.bind(globalThis) }) {
	if (!fetchImplementation) throw new FluidBridgeTokenMintError("Fluid App Bridge host requires a fetch implementation to mint session tokens");
	const response = await fetchImplementation(resolveSessionTokenUrl(apiBaseUrl), {
		method: "POST",
		headers: sessionTokenHeaders(authToken),
		body: JSON.stringify(sessionTokenRequestBody(request))
	});
	const body = await response.json().catch(() => null);
	if (!response.ok) throw errorForTokenResponse(response.status, body);
	if (!isSessionTokenSuccessResponse(body) || body.session_token.length === 0) throw new FluidBridgeTokenMintError("Fluid App Bridge backend returned an invalid session token response", { body });
	return body.session_token;
}
function sessionTokenRequestFromContext(context, sessionId) {
	return {
		clientId: context.app.clientId,
		entry: context.entry,
		resources: context.resources,
		allowedOrigins: context.fetch.allowedOrigins,
		...sessionId ? { sessionId } : {}
	};
}
function sessionTokenHeaders(authToken) {
	const headers = new Headers({
		"Content-Type": "application/json",
		"X-Fluid-App-Bridge-Protocol": FLUID_BRIDGE_PROTOCOL_VERSION,
		"X-Fluid-App-Bridge-Version": APP_BRIDGE_SDK_VERSION,
		"X-Fluid-App-Bridge-Sdk": APP_BRIDGE_SDK_NAME
	});
	if (authToken) headers.set("Authorization", `Bearer ${authToken}`);
	return headers;
}
function sessionTokenRequestBody(request) {
	return {
		client_id: request.clientId,
		entry: request.entry,
		resources: request.resources ?? [],
		allowed_origins: request.allowedOrigins ?? [],
		...request.sessionId ? { session_id: request.sessionId } : {}
	};
}
function resolveSessionTokenUrl(apiBaseUrl) {
	if (!apiBaseUrl) return `/${DEFAULT_SESSION_TOKEN_PATH}`;
	return new URL(DEFAULT_SESSION_TOKEN_PATH, ensureTrailingSlash(apiBaseUrl)).toString();
}
function ensureTrailingSlash(url) {
	return url.endsWith("/") ? url : `${url}/`;
}
function isSessionTokenSuccessResponse(value) {
	return typeof value === "object" && value !== null && "session_token" in value && typeof value.session_token === "string";
}
function errorForTokenResponse(status, body) {
	const errorBody = isLegacyErrorResponse(body) ? body.error : void 0;
	const message = errorBody?.message ?? "Fluid App Bridge backend rejected the session-token request";
	const details = errorBody?.details ?? body;
	if (status === 401) return new FluidBridgeUnauthorizedError(message, details);
	if (status === 403) return new FluidBridgeFailedAuthenticationError(message, details);
	if (status === 422) return new FluidBridgeIncompatibleVersionError(message, details);
	return new FluidBridgeTokenMintError(message, details);
}
function isLegacyErrorResponse(value) {
	return typeof value === "object" && value !== null && "error" in value;
}
//#endregion
//#region ../widgets/src/widgets/EmbedWidget.tsx
var EmbedWidget_exports = /* @__PURE__ */ __exportAll({
	EmbedWidget: () => EmbedWidget,
	embedWidgetPropertySchema: () => embedWidgetPropertySchema
});
function isValidHttpUrl(urlString) {
	try {
		const parsed = new URL(urlString);
		return parsed.protocol === "https:" || parsed.protocol === "http:";
	} catch {
		return false;
	}
}
function useEmbedUrl(url, publicId) {
	return useMemo(() => {
		const normalizedUrl = url && (url.startsWith("http://") || url.startsWith("https://")) ? url : url ? `https://${url}` : "";
		let isValidUrl = false;
		if (normalizedUrl) try {
			const parsed = new URL(normalizedUrl);
			isValidUrl = (parsed.protocol === "http:" || parsed.protocol === "https:") && (parsed.hostname.includes(".") || parsed.hostname === "localhost");
		} catch {}
		if (!isValidUrl || !publicId) return {
			normalizedUrl,
			isValidUrl,
			iframeSrc: normalizedUrl
		};
		const urlObj = new URL(normalizedUrl);
		urlObj.searchParams.set("public_id", publicId);
		return {
			normalizedUrl,
			isValidUrl,
			iframeSrc: urlObj.toString()
		};
	}, [url, publicId]);
}
function getEmbedOrigin(url) {
	try {
		return new URL(url).origin;
	} catch {
		return null;
	}
}
function useEmbedPostMessageBridge({ iframeRef, normalizedUrl, isValidUrl, editMode }) {
	useEffect(() => {
		if (!isValidUrl || editMode) return;
		const expectedOrigin = new URL(normalizedUrl).origin;
		function handleMessage(event) {
			if (event.origin !== expectedOrigin) return;
			if (event.source !== iframeRef.current?.contentWindow) return;
			let data;
			if (typeof event.data === "string") try {
				data = JSON.parse(event.data);
			} catch {
				return;
			}
			else data = event.data;
			if (typeof data === "object" && data !== null && "type" in data && data.type === "OPEN_FULL_SCREEN_WEBVIEW") {
				const messageUrl = data.url;
				if (messageUrl && isValidHttpUrl(messageUrl)) window.open(messageUrl, "_blank", "noopener,noreferrer");
			}
		}
		window.addEventListener("message", handleMessage);
		return () => window.removeEventListener("message", handleMessage);
	}, [
		iframeRef,
		normalizedUrl,
		isValidUrl,
		editMode
	]);
}
function useEmbedability(normalizedUrl, isValidUrl, editMode) {
	const [state, setState] = useState("idle");
	useEffect(() => {
		if (!editMode || !isValidUrl) {
			setState("idle");
			return;
		}
		setState("checking");
		const controller = new AbortController();
		const timer = setTimeout(() => {
			fetch(`/api/embed-can-frame?url=${encodeURIComponent(normalizedUrl)}`, { signal: controller.signal }).then((res) => res.ok ? res.json() : null).then((data) => {
				if (controller.signal.aborted) return;
				if (data && typeof data.canFrame === "boolean") setState(data.canFrame ? "embeddable" : "blocked");
				else setState("idle");
			}).catch(() => {
				if (!controller.signal.aborted) setState("idle");
			});
		}, 400);
		return () => {
			controller.abort();
			clearTimeout(timer);
		};
	}, [
		normalizedUrl,
		isValidUrl,
		editMode
	]);
	return state;
}
function useModalBodyScrollLock(isOpen) {
	useEffect(() => {
		if (!isOpen) return;
		const previousOverflow = document.body.style.overflow;
		document.body.style.overflow = "hidden";
		return () => {
			document.body.style.overflow = previousOverflow;
		};
	}, [isOpen]);
}
function useModalEscapeClose(isOpen, onClose) {
	useEffect(() => {
		if (!isOpen) return;
		const handleKeyDown = (event) => {
			if (event.key === "Escape") onClose();
		};
		window.addEventListener("keydown", handleKeyDown);
		return () => window.removeEventListener("keydown", handleKeyDown);
	}, [isOpen, onClose]);
}
function useDialogFocusRestore(dialogRef) {
	useEffect(() => {
		const previouslyFocused = document.activeElement instanceof HTMLElement ? document.activeElement : null;
		dialogRef.current?.focus();
		return () => {
			previouslyFocused?.focus();
		};
	}, [dialogRef]);
}
const HEADER_ICON_MAP = {
	GraduationCap,
	Video,
	BookOpen,
	Globe,
	User,
	Star,
	Heart,
	Trophy,
	Sparkles,
	Zap,
	Gift,
	ShoppingBag,
	Bell,
	Calendar,
	Bookmark: BookmarkIcon
};
const HEADER_ICON_OPTIONS = [
	{
		label: "Graduation Cap",
		value: "GraduationCap"
	},
	{
		label: "Video",
		value: "Video"
	},
	{
		label: "Book",
		value: "BookOpen"
	},
	{
		label: "Globe",
		value: "Globe"
	},
	{
		label: "User",
		value: "User"
	},
	{
		label: "Star",
		value: "Star"
	},
	{
		label: "Heart",
		value: "Heart"
	},
	{
		label: "Trophy",
		value: "Trophy"
	},
	{
		label: "Sparkles",
		value: "Sparkles"
	},
	{
		label: "Zap / Lightning",
		value: "Zap"
	},
	{
		label: "Gift",
		value: "Gift"
	},
	{
		label: "Shopping Bag",
		value: "ShoppingBag"
	},
	{
		label: "Bell",
		value: "Bell"
	},
	{
		label: "Calendar",
		value: "Calendar"
	},
	{
		label: "Bookmark",
		value: "Bookmark"
	}
];
const getHeaderIcon = (name) => {
	if (!name) return GraduationCap;
	return HEADER_ICON_MAP[name] ?? GraduationCap;
};
function EmbedWidget({ url = "", appBridge, title = "Embedded Content", height = "400px", fullScreen = false, allowFullscreen = true, loading = "lazy", borderRadius = "md", borderWidth = "none", borderColor = "muted", editMode: _editMode, isSelected: _isSelected, displayMode = "inline", coverResource, coverUseCustomUrl = false, coverImageUrl = "", coverTitle = "", coverMeta = "", coverShowHeader = true, coverHeaderIcon = "GraduationCap", coverHeaderIconColor = "primary", coverHeight = "320px", className, ...props }) {
	const renderState = useWidgetRenderState();
	const editMode = _editMode ?? renderState.editMode;
	const isSelected = _isSelected ?? renderState.isSelected;
	const isFullScreen = fullScreen;
	const iframeRef = useRef(null);
	const repUser = useRepUser();
	const publicId = repUser?.publicId;
	const { data: store } = useOptionalStore();
	const [modalOpen, setModalOpen] = useState(false);
	const [coverReloadKey, setCoverReloadKey] = useState(0);
	const [iframeReloadKey, setIframeReloadKey] = useState(0);
	const closeModal = useCallback(() => setModalOpen(false), []);
	const { t } = useShellTranslation();
	const { normalizedUrl, isValidUrl, iframeSrc } = useEmbedUrl(url, publicId);
	useEmbedPostMessageBridge({
		iframeRef,
		normalizedUrl,
		isValidUrl,
		editMode
	});
	const appBridgeClientId = appBridge?.clientId;
	const appBridgeEntryType = appBridge?.entryType;
	const appBridgeEntryName = appBridge?.entryName;
	const appBridgeResources = appBridge?.resources;
	const appBridgeAppOrigins = appBridge?.appOrigins;
	const appBridgeContext = useMemo(() => {
		if (!appBridgeClientId || !store || !isValidUrl) return null;
		return {
			protocol: FLUID_BRIDGE_PROTOCOL_VERSION,
			app: { clientId: appBridgeClientId },
			store: {
				subdomain: store.subdomain,
				url: `https://${store.subdomain}.fluid.app`,
				name: store.name
			},
			...repUser ? { actor: {
				type: "member",
				...repUser.publicId ? { uuid: repUser.publicId } : {},
				roles: [],
				permissions: []
			} } : {},
			entry: {
				type: appBridgeEntryType ?? "portal_embed",
				name: appBridgeEntryName ?? title
			},
			resources: appBridgeResources ?? [],
			fetch: { allowedOrigins: [getEmbedOrigin(normalizedUrl), ...appBridgeAppOrigins ?? []].filter((origin) => Boolean(origin)) },
			sdk: { minVersion: APP_BRIDGE_SDK_VERSION }
		};
	}, [
		appBridgeAppOrigins,
		appBridgeClientId,
		appBridgeEntryName,
		appBridgeEntryType,
		appBridgeResources,
		isValidUrl,
		normalizedUrl,
		repUser,
		store,
		title
	]);
	const appBridgeContextRef = useRef(null);
	const appBridgeContextReady = appBridgeContext !== null;
	useEffect(() => {
		appBridgeContextRef.current = appBridgeContext;
	}, [appBridgeContext]);
	const getAppBridgeContext = useCallback(() => {
		if (!appBridgeContextRef.current) throw new Error("App Bridge context is unavailable");
		return appBridgeContextRef.current;
	}, []);
	const getAppBridgeSessionToken = useCallback((bridgeContext) => mintAppBridgeSessionToken({ request: sessionTokenRequestFromContext(bridgeContext) }), []);
	useEffect(() => {
		if (!appBridgeClientId || !appBridgeContextReady || editMode) return;
		const iframe = iframeRef.current;
		const appOrigin = getEmbedOrigin(normalizedUrl);
		if (!iframe || !appOrigin) return;
		const host = createFluidBridgeHost({
			iframe,
			appOrigin,
			clientId: appBridgeClientId,
			getContext: getAppBridgeContext,
			getSessionToken: getAppBridgeSessionToken
		});
		return () => host.destroy();
	}, [
		appBridgeClientId,
		appBridgeContextReady,
		editMode,
		getAppBridgeContext,
		getAppBridgeSessionToken,
		iframeReloadKey,
		modalOpen,
		normalizedUrl
	]);
	useModalBodyScrollLock(modalOpen);
	useModalEscapeClose(modalOpen, closeModal);
	const embedability = useEmbedability(normalizedUrl, isValidUrl, editMode && displayMode !== "cover");
	if (!url || !isValidUrl) return /* @__PURE__ */ jsx("div", {
		className: `flex items-center justify-center rounded-${borderRadius} border-border bg-muted text-muted-foreground border-2 border-dashed ${className ?? ""}`,
		...props,
		style: isFullScreen ? { height: "var(--portal-fullscreen-embed-height, calc(100dvh - 4rem))" } : { height: displayMode === "cover" ? coverHeight : height },
		children: /* @__PURE__ */ jsxs("div", {
			className: "flex flex-col items-center gap-2 p-6 text-center",
			children: [
				/* @__PURE__ */ jsx(Globe, { className: "size-12 opacity-50" }),
				/* @__PURE__ */ jsx("p", {
					className: "text-sm font-medium",
					children: "Enter a URL to embed external content"
				}),
				/* @__PURE__ */ jsx("p", {
					className: "text-xs opacity-75",
					children: "Configure the URL in the properties panel"
				})
			]
		})
	});
	if (displayMode === "cover") {
		const resolvedCoverImage = coverUseCustomUrl ? coverImageUrl : coverResource?.imageUrl || coverResource?.image_url || coverImageUrl;
		const effectiveTitle = coverTitle || title;
		const HeaderIcon = getHeaderIcon(coverHeaderIcon);
		const handleOpenModal = () => {
			if (editMode) return;
			setModalOpen(true);
		};
		const handleReload = () => {
			if (editMode) return;
			setCoverReloadKey((key) => key + 1);
		};
		const handleOpenNewTab = (e) => {
			e.stopPropagation();
			if (editMode) return;
			window.open(iframeSrc, "_blank", "noopener,noreferrer");
		};
		return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
			className: `relative w-full overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== "none" ? borderColorClasses[borderColor] : ""} bg-background ${className ?? ""}`,
			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)" },
			...props,
			children: [
				/* @__PURE__ */ jsx("div", {
					"aria-hidden": "true",
					className: `pointer-events-none absolute inset-0 z-[1] rounded-${borderRadius}`,
					style: { boxShadow: "inset 0 0 0 1px color-mix(in oklch, var(--color-foreground) 8%, transparent)" }
				}),
				coverShowHeader && /* @__PURE__ */ jsxs("div", {
					className: "relative z-[2] flex items-center gap-3 px-5 py-3",
					children: [
						/* @__PURE__ */ jsx("span", {
							"aria-hidden": "true",
							className: `text-${coverHeaderIconColor}-foreground flex size-7 shrink-0 items-center justify-center rounded-${borderRadius}`,
							style: {
								background: `linear-gradient(135deg, color-mix(in oklch, var(--color-${coverHeaderIconColor}) 75%, white 25%) 0%, var(--color-${coverHeaderIconColor}) 100%)`,
								boxShadow: `
                    inset 0 1px 0 rgba(255,255,255,0.25),
                    inset 0 -1px 0 rgba(0,0,0,0.08),
                    0 1px 2px color-mix(in oklch, var(--color-${coverHeaderIconColor}) 25%, transparent)
                  `
							},
							children: /* @__PURE__ */ jsx(HeaderIcon, {
								className: "size-3.5",
								strokeWidth: 2.25
							})
						}),
						/* @__PURE__ */ jsxs("div", {
							className: "min-w-0 flex-1",
							children: [effectiveTitle && /* @__PURE__ */ jsx("h3", {
								className: "text-foreground truncate text-[15px] leading-tight font-semibold tracking-tight",
								children: effectiveTitle
							}), coverMeta && /* @__PURE__ */ jsx("p", {
								className: "text-foreground/40 mt-0.5 truncate text-[11px] font-medium tracking-[0.08em] uppercase",
								children: coverMeta
							})]
						}),
						/* @__PURE__ */ jsxs("div", {
							className: "bg-foreground/5 flex shrink-0 items-center rounded-lg p-0.5",
							children: [
								/* @__PURE__ */ jsx(HeaderIconButton, {
									Icon: RotateCw,
									label: "Reload",
									onClick: (e) => {
										e.stopPropagation();
										handleReload();
									}
								}),
								/* @__PURE__ */ jsx(HeaderIconButton, {
									Icon: Maximize2,
									label: "Open",
									onClick: (e) => {
										e.stopPropagation();
										handleOpenModal();
									}
								}),
								/* @__PURE__ */ jsx(HeaderIconButton, {
									Icon: ExternalLink,
									label: "Open in new tab",
									onClick: handleOpenNewTab
								})
							]
						})
					]
				}),
				/* @__PURE__ */ jsx("button", {
					type: "button",
					onClick: handleOpenModal,
					disabled: editMode,
					className: `relative block w-full overflow-hidden ${editMode ? "cursor-default" : "cursor-pointer"}`,
					style: { height: coverHeight },
					"aria-label": `Open ${effectiveTitle || title}`,
					children: resolvedCoverImage ? /* @__PURE__ */ jsx("img", {
						src: resolvedCoverImage,
						alt: effectiveTitle || title,
						className: "h-full w-full object-cover"
					}, `cover-${coverReloadKey}`) : /* @__PURE__ */ jsx("div", {
						className: "bg-muted flex h-full w-full items-center justify-center",
						children: /* @__PURE__ */ jsx(Globe, { className: "text-muted-foreground/40 size-16" })
					})
				}),
				editMode && !isSelected && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-10" })
			]
		}), modalOpen && /* @__PURE__ */ jsx(EmbedModal, {
			src: iframeSrc,
			title: effectiveTitle || title,
			allowFullscreen,
			iframeRef,
			onClose: closeModal,
			onReload: () => setIframeReloadKey((key) => key + 1)
		}, `modal-${iframeReloadKey}`)] });
	}
	if (editMode && embedability === "blocked") {
		let displayUrl = normalizedUrl;
		try {
			const parsed = new URL(normalizedUrl);
			displayUrl = `${parsed.host}${parsed.pathname === "/" ? "" : parsed.pathname}`;
		} catch {}
		const inlineHeight = isFullScreen ? "var(--portal-fullscreen-embed-height, calc(100dvh - 4rem))" : height;
		return /* @__PURE__ */ jsx("div", {
			className: `flex items-center justify-center rounded-${borderRadius} border-destructive/40 bg-destructive/5 text-destructive border-2 border-dashed ${className ?? ""}`,
			...props,
			style: { height: inlineHeight },
			children: /* @__PURE__ */ jsxs("div", {
				className: "flex flex-col items-center gap-2 p-6 text-center",
				children: [
					/* @__PURE__ */ jsx(Globe, { className: "h-12 w-12 opacity-50" }),
					/* @__PURE__ */ jsx("p", {
						className: "text-sm font-medium",
						children: t("embed_blocked_title")
					}),
					/* @__PURE__ */ jsx("p", {
						className: "max-w-xs truncate text-xs opacity-75",
						children: displayUrl
					}),
					/* @__PURE__ */ jsx("p", {
						className: "text-xs opacity-60",
						children: t("embed_blocked_hint")
					})
				]
			})
		});
	}
	return /* @__PURE__ */ jsxs("div", {
		className: `relative w-full rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== "none" ? borderColorClasses[borderColor] : ""} ${className ?? ""}`,
		...props,
		style: isFullScreen ? { height: "var(--portal-fullscreen-embed-height, calc(100dvh - 4rem))" } : void 0,
		children: [/* @__PURE__ */ jsx("iframe", {
			ref: iframeRef,
			src: iframeSrc,
			title,
			width: "100%",
			style: isFullScreen ? { height: "100%" } : { height },
			loading,
			allowFullScreen: allowFullscreen,
			className: `rounded-${borderRadius} border-border border`,
			sandbox: "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads"
		}), editMode && !isSelected && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-10" })]
	});
}
function HeaderIconButton({ Icon, label, onClick }) {
	return /* @__PURE__ */ jsx("button", {
		type: "button",
		onClick,
		"aria-label": label,
		className: "text-foreground/45 hover:text-foreground hover:bg-background flex size-7 items-center justify-center rounded-md transition-colors",
		children: /* @__PURE__ */ jsx(Icon, {
			className: "size-3.5",
			strokeWidth: 2.25
		})
	});
}
function EmbedModal({ src, title, allowFullscreen, iframeRef, onClose, onReload }) {
	const dialogRef = useRef(null);
	useDialogFocusRestore(dialogRef);
	return createPortal(/* @__PURE__ */ jsx("div", {
		ref: dialogRef,
		tabIndex: -1,
		className: "fixed inset-0 z-[100] flex items-center justify-center p-4 focus:outline-none sm:p-8",
		style: { background: "color-mix(in oklch, var(--color-foreground) 80%, black)" },
		onClick: onClose,
		role: "dialog",
		"aria-modal": "true",
		"aria-label": title,
		children: /* @__PURE__ */ jsxs("div", {
			className: "bg-background relative flex h-full max-h-[95vh] w-full max-w-[1400px] flex-col overflow-hidden rounded-2xl shadow-2xl",
			onClick: (e) => e.stopPropagation(),
			children: [/* @__PURE__ */ jsxs("div", {
				className: "flex items-center justify-between gap-4 px-5 py-3",
				style: { borderBottom: "1px solid color-mix(in oklch, var(--color-foreground) 8%, transparent)" },
				children: [/* @__PURE__ */ jsx("h3", {
					className: "text-foreground truncate text-sm font-semibold tracking-tight",
					children: title
				}), /* @__PURE__ */ jsxs("div", {
					className: "flex shrink-0 items-center gap-1",
					children: [/* @__PURE__ */ jsx(HeaderIconButton, {
						Icon: RotateCw,
						label: "Reload",
						onClick: (e) => {
							e.stopPropagation();
							onReload();
						}
					}), /* @__PURE__ */ jsx("button", {
						type: "button",
						onClick: onClose,
						"aria-label": "Close",
						className: "text-foreground/60 hover:text-foreground hover:bg-foreground/5 flex size-9 shrink-0 items-center justify-center rounded-full transition-colors",
						children: /* @__PURE__ */ jsx(X, { className: "size-5" })
					})]
				})]
			}), /* @__PURE__ */ jsx("iframe", {
				ref: iframeRef,
				src,
				title,
				className: "flex-1 border-0",
				allowFullScreen: allowFullscreen,
				sandbox: "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads"
			})]
		})
	}), document.body);
}
const embedWidgetPropertySchema = {
	widgetType: "EmbedWidget",
	displayName: "Embed",
	fields: [
		{
			key: "url",
			label: "URL",
			type: "text",
			description: "The URL of the external site to embed",
			placeholder: "https://example.com",
			defaultValue: "",
			group: "Content"
		},
		{
			key: "title",
			label: "Screen Reader Label",
			type: "text",
			description: "Describes the embed for screen readers and assistive tech. Not visible on the page.",
			defaultValue: "Embedded Content",
			group: "Content"
		},
		{
			key: "displayMode",
			label: "Display Mode",
			type: "buttonGroup",
			description: "Inline: iframe renders directly. Cover: shows a card that opens the embed in a full-screen modal.",
			defaultValue: "inline",
			options: [{
				label: "Inline",
				value: "inline"
			}, {
				label: "Cover + Modal",
				value: "cover"
			}],
			group: "Display Mode"
		},
		{
			key: "coverResource",
			label: "Cover Image",
			type: "image",
			description: "Select the image shown before the embed opens",
			group: "Cover",
			requiresKeyValue: {
				key: "displayMode",
				value: "cover"
			}
		},
		{
			key: "coverUseCustomUrl",
			label: "Use Custom URL",
			type: "boolean",
			description: "Enter a custom image URL instead of selecting media",
			defaultValue: false,
			group: "Cover",
			requiresKeyValue: {
				key: "displayMode",
				value: "cover"
			}
		},
		{
			key: "coverImageUrl",
			label: "Cover Image URL",
			type: "text",
			description: "Direct URL to the cover image",
			placeholder: "https://example.com/cover.jpg",
			defaultValue: "",
			group: "Cover",
			requiresKeyValue: [{
				key: "displayMode",
				value: "cover"
			}, {
				key: "coverUseCustomUrl",
				value: true
			}]
		},
		getHeightField({
			key: "coverHeight",
			label: "Cover Height",
			description: "Height of the cover image area",
			defaultValue: "320px",
			group: "Cover",
			requiresKeyValue: {
				key: "displayMode",
				value: "cover"
			}
		}),
		{
			key: "coverShowHeader",
			label: "Show Card Header",
			type: "boolean",
			description: "Show the header with icon, title, and action buttons",
			defaultValue: true,
			group: "Cover Header",
			requiresKeyValue: {
				key: "displayMode",
				value: "cover"
			}
		},
		{
			key: "coverHeaderIcon",
			label: "Header Icon",
			type: "select",
			description: "Icon displayed in the colored badge on the left",
			options: HEADER_ICON_OPTIONS,
			defaultValue: "GraduationCap",
			group: "Cover Header",
			requiresKeyValue: [{
				key: "displayMode",
				value: "cover"
			}, {
				key: "coverShowHeader",
				value: true
			}]
		},
		getColorField({
			key: "coverHeaderIconColor",
			label: "Icon Badge Color",
			description: "Background color of the icon badge",
			defaultValue: "primary",
			group: "Cover Header",
			requiresKeyValue: [{
				key: "displayMode",
				value: "cover"
			}, {
				key: "coverShowHeader",
				value: true
			}]
		}),
		{
			key: "coverTitle",
			label: "Header Title",
			type: "text",
			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.",
			defaultValue: "",
			group: "Cover Header",
			requiresKeyValue: {
				key: "displayMode",
				value: "cover"
			}
		},
		{
			key: "coverMeta",
			label: "Meta Text",
			type: "text",
			description: "Small uppercase meta line below the title (e.g. 'APR 16 · COACHING THE HOSTESS')",
			defaultValue: "",
			group: "Cover Header",
			requiresKeyValue: [{
				key: "displayMode",
				value: "cover"
			}, {
				key: "coverShowHeader",
				value: true
			}]
		},
		getBorderRadiusField({
			key: "borderRadius",
			label: "Border Radius",
			description: "Border radius for the embed container",
			defaultValue: "md",
			group: "Design"
		}),
		getBorderWidthField({
			key: "borderWidth",
			label: "Border Width",
			description: "Border width for the widget",
			defaultValue: "none",
			group: "Design"
		}),
		getBorderColorField({
			key: "borderColor",
			label: "Border Color",
			description: "Border color for the widget",
			defaultValue: "muted",
			group: "Design"
		}),
		{
			key: "fullScreen",
			label: "Full Screen",
			type: "boolean",
			description: "Inline mode: fill the available space instead of a fixed height",
			defaultValue: false,
			group: "Design",
			requiresKeyValue: {
				key: "displayMode",
				value: "inline"
			}
		},
		getHeightField({
			key: "height",
			label: "Height",
			description: "Height of the inline embed iframe",
			defaultValue: "400px",
			group: "Design",
			requiresKeyValue: [{
				key: "displayMode",
				value: "inline"
			}, {
				key: "fullScreen",
				value: false
			}]
		}),
		{
			key: "allowFullscreen",
			label: "Allow Fullscreen",
			type: "boolean",
			description: "Allow the embedded content to use fullscreen mode",
			defaultValue: true,
			group: "Settings"
		},
		{
			key: "loading",
			label: "Loading",
			type: "select",
			description: "When to load the embedded content (inline mode only)",
			options: [{
				label: "Lazy (on scroll)",
				value: "lazy"
			}, {
				label: "Eager (immediately)",
				value: "eager"
			}],
			defaultValue: "lazy",
			group: "Settings",
			requiresKeyValue: {
				key: "displayMode",
				value: "inline"
			}
		}
	]
};
//#endregion
export { EmbedWidget_exports as n, embedWidgetPropertySchema as r, EmbedWidget as t };

//# sourceMappingURL=EmbedWidget-DfhOZVCm.mjs.map