@fluid-app/portal-sdk 0.1.493 → 0.1.494
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/{AnnouncementWidget-CNP37JUB.cjs → AnnouncementWidget--nRHRrQH.cjs} +3 -3
- package/dist/{AnnouncementWidget-93a322Pl.mjs → AnnouncementWidget-BND76Ojg.mjs} +2 -2
- package/dist/{AnnouncementWidget-93a322Pl.mjs.map → AnnouncementWidget-BND76Ojg.mjs.map} +1 -1
- package/dist/{AnnouncementWidget-BIFJ7E6o.cjs → AnnouncementWidget-Dh6nKAqT.cjs} +2 -2
- package/dist/{AnnouncementWidget-BIFJ7E6o.cjs.map → AnnouncementWidget-Dh6nKAqT.cjs.map} +1 -1
- package/dist/{CarouselWidget-fft3Aibh.cjs → CarouselWidget-BETNqs_K.cjs} +3 -3
- package/dist/{CarouselWidget-fft3Aibh.cjs.map → CarouselWidget-BETNqs_K.cjs.map} +1 -1
- package/dist/{CarouselWidget-COavwXvx.mjs → CarouselWidget-CU1oj0q4.mjs} +3 -3
- package/dist/{CarouselWidget-COavwXvx.mjs.map → CarouselWidget-CU1oj0q4.mjs.map} +1 -1
- package/dist/{CarouselWidget-DDKKVEan.cjs → CarouselWidget-D3BODbpO.cjs} +3 -3
- package/dist/{CatchUpWidget-C3HdLA5t.mjs → CatchUpWidget-BtwG2-JD.mjs} +2 -2
- package/dist/{CatchUpWidget-BNEEQNcr.mjs → CatchUpWidget-CLwHp30X.mjs} +5 -4
- package/dist/CatchUpWidget-CLwHp30X.mjs.map +1 -0
- package/dist/{CatchUpWidget-G4txAfv3.cjs → CatchUpWidget-CqAHpCJP.cjs} +5 -4
- package/dist/CatchUpWidget-CqAHpCJP.cjs.map +1 -0
- package/dist/{CatchUpWidget-g9GtsvCy.cjs → CatchUpWidget-ak-oFdKY.cjs} +2 -2
- package/dist/{FluidProvider-DxwbLpfX.mjs → FluidProvider-BRgNyDk3.mjs} +3 -3
- package/dist/{FluidProvider-DxwbLpfX.mjs.map → FluidProvider-BRgNyDk3.mjs.map} +1 -1
- package/dist/{FluidProvider-B7bYw1AY.cjs → FluidProvider-XONLsJbE.cjs} +3 -3
- package/dist/{FluidProvider-B7bYw1AY.cjs.map → FluidProvider-XONLsJbE.cjs.map} +1 -1
- package/dist/{ImageWidget-B3IlWnKJ.cjs → ImageWidget-CksrA9rH.cjs} +2 -2
- package/dist/{ImageWidget-B3IlWnKJ.cjs.map → ImageWidget-CksrA9rH.cjs.map} +1 -1
- package/dist/{ImageWidget-DiWlWvKm.cjs → ImageWidget-DmO84AYo.cjs} +3 -3
- package/dist/{ImageWidget-CovwH8bp.mjs → ImageWidget-I8F34YlI.mjs} +2 -2
- package/dist/{ImageWidget-CovwH8bp.mjs.map → ImageWidget-I8F34YlI.mjs.map} +1 -1
- package/dist/{LinkWidget-StpP6gPq.mjs → LinkWidget-Dg0tHfgD.mjs} +2 -2
- package/dist/{LinkWidget-StpP6gPq.mjs.map → LinkWidget-Dg0tHfgD.mjs.map} +1 -1
- package/dist/{LinkWidget-BTIsGyc5.cjs → LinkWidget-Dvp6-Dow.cjs} +2 -2
- package/dist/{LinkWidget-BTIsGyc5.cjs.map → LinkWidget-Dvp6-Dow.cjs.map} +1 -1
- package/dist/{LinkWidget-ZVFlL178.cjs → LinkWidget-N6yz6w-U.cjs} +3 -3
- package/dist/{ListWidget-ddhJLwxZ.mjs → ListWidget-BAS3SGpD.mjs} +3 -3
- package/dist/{ListWidget-ddhJLwxZ.mjs.map → ListWidget-BAS3SGpD.mjs.map} +1 -1
- package/dist/{ListWidget-6TkLyp00.cjs → ListWidget-CH-zz3sb.cjs} +3 -3
- package/dist/{ListWidget-6TkLyp00.cjs.map → ListWidget-CH-zz3sb.cjs.map} +1 -1
- package/dist/{ListWidget-BNAED5xZ.cjs → ListWidget-vG31UVVS.cjs} +3 -3
- package/dist/{MessagingScreen-CZje-9-C.mjs → MessagingScreen-B8--eInM.mjs} +19 -19
- package/dist/{MessagingScreen-DDVflwCT.cjs → MessagingScreen-D2oC8zGg.cjs} +19 -19
- package/dist/{MessagingScreen-Q0BSmRuJ.mjs → MessagingScreen-DYjU5smt.mjs} +2 -2
- package/dist/{MessagingScreen-Q0BSmRuJ.mjs.map → MessagingScreen-DYjU5smt.mjs.map} +1 -1
- package/dist/{MessagingScreen-D7Yuy_Rn.cjs → MessagingScreen-gPqbIcFd.cjs} +2 -2
- package/dist/{MessagingScreen-D7Yuy_Rn.cjs.map → MessagingScreen-gPqbIcFd.cjs.map} +1 -1
- package/dist/{NestedWidget-orTqukJD.cjs → NestedWidget-B24yMkV4.cjs} +2 -2
- package/dist/{NestedWidget-orTqukJD.cjs.map → NestedWidget-B24yMkV4.cjs.map} +1 -1
- package/dist/{NestedWidget-DMhmCZT6.mjs → NestedWidget-D31rZhTR.mjs} +2 -2
- package/dist/{NestedWidget-DMhmCZT6.mjs.map → NestedWidget-D31rZhTR.mjs.map} +1 -1
- package/dist/{NestedWidget-BZZqukZw.cjs → NestedWidget-DqM5HGFl.cjs} +2 -2
- package/dist/{OrdersScreen-vAO6E8EM.cjs → OrdersScreen-BdLqCq1V.cjs} +19 -19
- package/dist/{OrdersScreen-CXxGN6RY.mjs → OrdersScreen-CHSqar4N.mjs} +3 -3
- package/dist/{OrdersScreen-CXxGN6RY.mjs.map → OrdersScreen-CHSqar4N.mjs.map} +1 -1
- package/dist/{OrdersScreen-DOBWnf_w.mjs → OrdersScreen-DRcdhc7y.mjs} +19 -19
- package/dist/{OrdersScreen-C0TzmZCl.cjs → OrdersScreen-Xs90dlpC.cjs} +3 -3
- package/dist/{OrdersScreen-C0TzmZCl.cjs.map → OrdersScreen-Xs90dlpC.cjs.map} +1 -1
- package/dist/{ProfileScreen-B9NHS4A_.cjs → ProfileScreen-BeaM28Qw.cjs} +20 -20
- package/dist/{ProfileScreen-DWFXnUUU.mjs → ProfileScreen-C-YfTr7l.mjs} +20 -20
- package/dist/{ProfileScreen-BGLpyuef.mjs → ProfileScreen-CpoLji_m.mjs} +3 -3
- package/dist/{ProfileScreen-BGLpyuef.mjs.map → ProfileScreen-CpoLji_m.mjs.map} +1 -1
- package/dist/{ProfileScreen-tq1DJ71b.cjs → ProfileScreen-DdCPrQUL.cjs} +3 -3
- package/dist/{ProfileScreen-tq1DJ71b.cjs.map → ProfileScreen-DdCPrQUL.cjs.map} +1 -1
- package/dist/{QuickLinksWidget-DIkDVuvE.mjs → QuickLinksWidget-BiEUvm_J.mjs} +2 -2
- package/dist/{QuickLinksWidget-DIkDVuvE.mjs.map → QuickLinksWidget-BiEUvm_J.mjs.map} +1 -1
- package/dist/{QuickLinksWidget-DDFtIKqs.cjs → QuickLinksWidget-CLBvaogv.cjs} +2 -2
- package/dist/{QuickLinksWidget-DDFtIKqs.cjs.map → QuickLinksWidget-CLBvaogv.cjs.map} +1 -1
- package/dist/{QuickLinksWidget-HvMQHOkz.cjs → QuickLinksWidget-DzAL_wuz.cjs} +3 -3
- package/dist/{QuickShareWidget-BNf1Un61.cjs → QuickShareWidget-B7mlqgW8.cjs} +2 -2
- package/dist/{QuickShareWidget-lysi8Dhh.mjs → QuickShareWidget-Dzpzis1d.mjs} +2 -2
- package/dist/{QuickShareWidget-lysi8Dhh.mjs.map → QuickShareWidget-Dzpzis1d.mjs.map} +1 -1
- package/dist/{QuickShareWidget-mxiy1zdd.cjs → QuickShareWidget-wxRcBUkf.cjs} +2 -2
- package/dist/{QuickShareWidget-mxiy1zdd.cjs.map → QuickShareWidget-wxRcBUkf.cjs.map} +1 -1
- package/dist/{RecentActivityWidget-DGtKC_9F.mjs → RecentActivityWidget-BzmV4G8e.mjs} +2 -2
- package/dist/{RecentActivityWidget-DGtKC_9F.mjs.map → RecentActivityWidget-BzmV4G8e.mjs.map} +1 -1
- package/dist/{RecentActivityWidget-DcgOzvHx.cjs → RecentActivityWidget-DQcy41-I.cjs} +2 -2
- package/dist/{RecentActivityWidget-Cr1G82Cd.cjs → RecentActivityWidget-zBOY0c_B.cjs} +2 -2
- package/dist/{RecentActivityWidget-Cr1G82Cd.cjs.map → RecentActivityWidget-zBOY0c_B.cjs.map} +1 -1
- package/dist/{ShopWidget-C5hjVwsY.cjs → ShopWidget-CCITGTSs.cjs} +2 -2
- package/dist/{ShopWidget-C5hjVwsY.cjs.map → ShopWidget-CCITGTSs.cjs.map} +1 -1
- package/dist/{ShopWidget-BYQKWyri.mjs → ShopWidget-D98tmUgG.mjs} +2 -2
- package/dist/{ShopWidget-B80w-Drk.mjs → ShopWidget-DHM86LM3.mjs} +2 -2
- package/dist/{ShopWidget-B80w-Drk.mjs.map → ShopWidget-DHM86LM3.mjs.map} +1 -1
- package/dist/{ShopWidget-CoOK6Ctd.cjs → ShopWidget-DXVsF1Jh.cjs} +2 -2
- package/dist/{SubscriptionsScreen-BwcpTAn5.mjs → SubscriptionsScreen-BOM_1txu.mjs} +20 -20
- package/dist/{SubscriptionsScreen-BEzmLp01.cjs → SubscriptionsScreen-DGIEnvLM.cjs} +20 -20
- package/dist/{SubscriptionsScreen-Cy7RtO5K.cjs → SubscriptionsScreen-DzBPA9H8.cjs} +4 -4
- package/dist/{SubscriptionsScreen-Cy7RtO5K.cjs.map → SubscriptionsScreen-DzBPA9H8.cjs.map} +1 -1
- package/dist/{SubscriptionsScreen-C7OOGlBt.mjs → SubscriptionsScreen-cAKZwpIu.mjs} +4 -4
- package/dist/{SubscriptionsScreen-C7OOGlBt.mjs.map → SubscriptionsScreen-cAKZwpIu.mjs.map} +1 -1
- package/dist/{TableWidget-lXrvBX6U.cjs → TableWidget-B8F_uQ92.cjs} +2 -2
- package/dist/{TableWidget-Bxwn3QYs.mjs → TableWidget-CDGdl71J.mjs} +2 -2
- package/dist/{TableWidget-Bxwn3QYs.mjs.map → TableWidget-CDGdl71J.mjs.map} +1 -1
- package/dist/{TableWidget-uoeYCPzf.cjs → TableWidget-DNjUA2Il.cjs} +2 -2
- package/dist/{TableWidget-uoeYCPzf.cjs.map → TableWidget-DNjUA2Il.cjs.map} +1 -1
- package/dist/{VideoWidget-D8FAjnvj.cjs → VideoWidget-UQQoRmwC.cjs} +3 -3
- package/dist/{VideoWidget-DQzYOcFF.mjs → VideoWidget-Wca2-So_.mjs} +2 -2
- package/dist/{VideoWidget-DQzYOcFF.mjs.map → VideoWidget-Wca2-So_.mjs.map} +1 -1
- package/dist/{VideoWidget-BhN4oTGG.cjs → VideoWidget-bf-gkCfx.cjs} +2 -2
- package/dist/{VideoWidget-BhN4oTGG.cjs.map → VideoWidget-bf-gkCfx.cjs.map} +1 -1
- package/dist/{WidgetInteractionContext-Bjy4P_YP.cjs → WidgetInteractionContext-D9dBJ-39.cjs} +5 -3
- package/dist/WidgetInteractionContext-D9dBJ-39.cjs.map +1 -0
- package/dist/{WidgetInteractionContext-Ba_G5sDP.mjs → WidgetInteractionContext-IsMo73Ka.mjs} +5 -3
- package/dist/WidgetInteractionContext-IsMo73Ka.mjs.map +1 -0
- package/dist/{build-widget-registry-DAOb4Muk.mjs → build-widget-registry-70KBtqiR.mjs} +27 -27
- package/dist/{build-widget-registry-DAOb4Muk.mjs.map → build-widget-registry-70KBtqiR.mjs.map} +1 -1
- package/dist/{build-widget-registry-BZeMOKCj.cjs → build-widget-registry-CWQ0YvEy.cjs} +27 -27
- package/dist/{build-widget-registry-BZeMOKCj.cjs.map → build-widget-registry-CWQ0YvEy.cjs.map} +1 -1
- package/dist/index.cjs +55 -34
- 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 +55 -34
- package/dist/index.mjs.map +1 -1
- package/dist/styles/remote-widget-shadow.css +2 -2
- package/dist/{use-internal-link-WJcYzKsi.mjs → use-internal-link-CKMpGvvs.mjs} +2 -2
- package/dist/{use-internal-link-WJcYzKsi.mjs.map → use-internal-link-CKMpGvvs.mjs.map} +1 -1
- package/dist/{use-internal-link-BTIkbJYg.cjs → use-internal-link-IcDHjPGp.cjs} +2 -2
- package/dist/{use-internal-link-BTIkbJYg.cjs.map → use-internal-link-IcDHjPGp.cjs.map} +1 -1
- package/dist/{use-link-action-C32zrsI0.mjs → use-link-action-CtVnC_2G.mjs} +2 -2
- package/dist/{use-link-action-C32zrsI0.mjs.map → use-link-action-CtVnC_2G.mjs.map} +1 -1
- package/dist/{use-link-action-rBy0j6go.cjs → use-link-action-DzA9AQsE.cjs} +2 -2
- package/dist/{use-link-action-rBy0j6go.cjs.map → use-link-action-DzA9AQsE.cjs.map} +1 -1
- package/dist/{use-portal-card-add-3ds-flow-DhfOxgMV.mjs → use-portal-card-add-3ds-flow-BMHRmeuB.mjs} +3 -3
- package/dist/{use-portal-card-add-3ds-flow-DhfOxgMV.mjs.map → use-portal-card-add-3ds-flow-BMHRmeuB.mjs.map} +1 -1
- package/dist/{use-portal-card-add-3ds-flow-DUBFzvAB.cjs → use-portal-card-add-3ds-flow-BsSH1Xks.cjs} +3 -3
- package/dist/{use-portal-card-add-3ds-flow-DUBFzvAB.cjs.map → use-portal-card-add-3ds-flow-BsSH1Xks.cjs.map} +1 -1
- package/dist/utils/build-remote-widget-plugin-manifests.cjs +17 -17
- package/dist/utils/build-remote-widget-plugin-manifests.mjs +17 -17
- package/dist/utils/build-widget-registry.cjs +17 -17
- package/dist/utils/build-widget-registry.mjs +17 -17
- package/package.json +19 -19
- package/dist/CatchUpWidget-BNEEQNcr.mjs.map +0 -1
- package/dist/CatchUpWidget-G4txAfv3.cjs.map +0 -1
- package/dist/WidgetInteractionContext-Ba_G5sDP.mjs.map +0 -1
- package/dist/WidgetInteractionContext-Bjy4P_YP.cjs.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require("./chunk-9hOWP6kD.cjs");
|
|
2
|
-
require("./WidgetInteractionContext-
|
|
2
|
+
require("./WidgetInteractionContext-D9dBJ-39.cjs");
|
|
3
3
|
require("./registries-MpWTUak_.cjs");
|
|
4
4
|
require("./fields-DbTpcT4E.cjs");
|
|
5
|
-
require("./use-internal-link-
|
|
6
|
-
const require_AnnouncementWidget = require("./AnnouncementWidget-
|
|
5
|
+
require("./use-internal-link-IcDHjPGp.cjs");
|
|
6
|
+
const require_AnnouncementWidget = require("./AnnouncementWidget-Dh6nKAqT.cjs");
|
|
7
7
|
exports.announcementWidgetPropertySchema = require_AnnouncementWidget.announcementWidgetPropertySchema;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Vn as __exportAll } from "./src-BfINy9nC.mjs";
|
|
2
2
|
import { i as getBorderColorField, l as getColorField, m as getPaddingField, n as borderWidthClasses, o as getBorderRadiusField, s as getBorderWidthField, t as borderColorClasses, u as getFontSizeField } from "./registries-B2aW34Dg.mjs";
|
|
3
3
|
import { n as sanitizeHref } from "./link-type-utils-DJBBqvOF.mjs";
|
|
4
|
-
import { t as useInternalLinks } from "./use-internal-link-
|
|
4
|
+
import { t as useInternalLinks } from "./use-internal-link-CKMpGvvs.mjs";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { AlertTriangle, AlignCenter, AlignLeft, AlignRight, ArrowRight, CheckCircle2, Info, Megaphone, Sparkles } from "lucide-react";
|
|
7
7
|
//#region ../widgets/src/widgets/AnnouncementWidget.tsx
|
|
@@ -293,4 +293,4 @@ const announcementWidgetPropertySchema = {
|
|
|
293
293
|
//#endregion
|
|
294
294
|
export { AnnouncementWidget_exports as n, announcementWidgetPropertySchema as r, AnnouncementWidget as t };
|
|
295
295
|
|
|
296
|
-
//# sourceMappingURL=AnnouncementWidget-
|
|
296
|
+
//# sourceMappingURL=AnnouncementWidget-BND76Ojg.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnnouncementWidget-93a322Pl.mjs","names":[],"sources":["../../widgets/src/widgets/AnnouncementWidget.tsx"],"sourcesContent":["import type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport type { ComponentProps, ComponentType } from \"react\";\nimport type React from \"react\";\nimport {\n getBorderColorField,\n getBorderRadiusField,\n getBorderWidthField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n borderWidthClasses,\n borderColorClasses,\n} from \"../core/fields\";\nimport { sanitizeHref } from \"../lib/link-type-utils\";\nimport { useInternalLinks } from \"../hooks/use-internal-link\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport {\n AlertTriangle,\n AlignCenter,\n AlignLeft,\n AlignRight,\n ArrowRight,\n CheckCircle2,\n Info,\n Megaphone,\n Sparkles,\n} from \"lucide-react\";\n\ntype TextAlignment = \"left\" | \"center\" | \"right\";\ntype Tone = \"info\" | \"success\" | \"warning\" | \"promo\" | \"neutral\";\n\nconst textAlignmentClasses: Record<TextAlignment, string> = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n} as const;\n\n// FontSizeOptions like \"md\" don't map to a real Tailwind class via\n// `text-${size}` (there is no `text-md`), so resolve through a table.\nconst fontSizeClasses: Record<FontSizeOptions, string> = {\n \"2xl\": \"text-2xl\",\n xl: \"text-xl\",\n lg: \"text-lg\",\n md: \"text-base\",\n sm: \"text-sm\",\n xs: \"text-xs\",\n};\n\n// Each tone picks a semantic icon; the color is chosen separately (accentColor)\n// so it always resolves to a theme token rather than a hard-coded hue.\nconst toneIcons: Record<Tone, ComponentType<{ className?: string }>> = {\n info: Info,\n success: CheckCircle2,\n warning: AlertTriangle,\n promo: Megaphone,\n neutral: Sparkles,\n};\n\ntype AnnouncementWidgetProps = ComponentProps<\"div\"> & {\n // Title\n title?: string;\n titleColor?: ColorOptions;\n titleFontSize?: FontSizeOptions;\n\n // Message (optional body)\n message?: string;\n messageColor?: ColorOptions;\n\n // Callout appearance\n tone?: Tone;\n showIcon?: boolean;\n showAccentBar?: boolean;\n accentColor?: ColorOptions;\n\n // Optional call to action\n ctaText?: string;\n ctaHref?: string;\n\n // Layout / styling\n alignment?: TextAlignment;\n background?: BackgroundValue;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n};\n\n// A text token that matches the surface renders invisibly. Fall back to a token\n// that actually contrasts: \"background\" when the surface itself is \"foreground\",\n// otherwise \"foreground\" (so a foreground-on-foreground pick stays legible too).\nfunction readableOn(color: ColorOptions, surface: ColorOptions): ColorOptions {\n if (color !== surface) return color;\n return surface === \"foreground\" ? \"background\" : \"foreground\";\n}\n\nexport function AnnouncementWidget({\n title = \"Announcement\",\n titleColor = \"foreground\",\n titleFontSize = \"lg\",\n message,\n messageColor = \"muted\",\n tone = \"promo\",\n showIcon = true,\n showAccentBar = true,\n accentColor = \"primary\",\n ctaText,\n ctaHref,\n alignment = \"left\",\n background = {\n type: \"solid\",\n color: \"muted\",\n },\n padding = 6,\n borderRadius = \"lg\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n className,\n ...props\n}: AnnouncementWidgetProps): React.JSX.Element {\n const resolveInternalLink = useInternalLinks();\n const backgroundColor = background.color || \"muted\";\n const backgroundImage =\n (background.resource?.image_url || background.resource?.imageUrl) &&\n background.type === \"image\"\n ? `url(${background.resource.image_url || background.resource.imageUrl})`\n : \"none\";\n\n // A text token that matches the background renders invisibly (e.g. muted body\n // text on a muted surface, or foreground text on a foreground surface). Fall\n // back to a contrasting token in that case.\n const titleTextColor = readableOn(titleColor, backgroundColor);\n const messageTextColor = readableOn(messageColor, backgroundColor);\n\n const Icon = toneIcons[tone];\n // Only render a CTA for a safe, well-formed href. sanitizeHref rejects\n // javascript:/data: and other non-navigational schemes an author could type\n // into the free-text Button Link field.\n const safeCtaHref = sanitizeHref(ctaHref?.trim() ?? \"\");\n const hasCta = !!ctaText?.trim() && !!safeCtaHref;\n // Same-portal links navigate in-app (keeping a back button) rather than doing\n // a full document load; external links fall through to the browser.\n const ctaLink = resolveInternalLink(safeCtaHref);\n\n // The icon chip + accent stripe read as a left-anchored callout. Centered\n // alignment stacks the icon above the text instead so nothing looks lopsided.\n const stacked = alignment === \"center\";\n const showStripe = showAccentBar && alignment === \"left\";\n\n return (\n <div\n className={`relative flex overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-${backgroundColor} p-${padding} ${className ?? \"\"}`}\n style={{ backgroundImage }}\n {...props}\n >\n {showStripe && (\n <span\n className={`absolute inset-y-0 left-0 w-1 bg-${accentColor}`}\n aria-hidden\n />\n )}\n\n <div\n className={`flex w-full gap-3 ${stacked ? \"flex-col items-center\" : \"flex-row items-start\"} ${showStripe ? \"pl-2\" : \"\"}`}\n >\n {showIcon && (\n <span\n className={`flex size-9 shrink-0 items-center justify-center rounded-full bg-${accentColor}/15 text-${accentColor}`}\n aria-hidden\n >\n <Icon className=\"size-5\" />\n </span>\n )}\n\n <div className={`min-w-0 flex-1 ${textAlignmentClasses[alignment]}`}>\n <p\n className={`${fontSizeClasses[titleFontSize]} font-header font-semibold tracking-tight text-pretty text-${titleTextColor}`}\n >\n {title}\n </p>\n\n {message && (\n <p\n className={`mt-1 text-sm leading-relaxed text-pretty text-${messageTextColor}`}\n >\n {message}\n </p>\n )}\n\n {hasCta && (\n <a\n href={safeCtaHref}\n onClick={ctaLink.followInternally}\n className={`mt-3 inline-flex items-center gap-1 text-sm font-semibold tracking-tight text-${accentColor} transition-opacity hover:opacity-80`}\n >\n {ctaText}\n <ArrowRight className=\"size-3.5\" aria-hidden />\n </a>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nexport const announcementWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"AnnouncementWidget\",\n displayName: \"Announcement\",\n tabsConfig: [{ id: \"content\", label: \"Content\" }],\n dataSourceTargetProps: [\"title\", \"message\", \"ctaText\", \"ctaHref\"],\n fields: [\n // Title group\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"The announcement headline\",\n defaultValue: \"Announcement\",\n tab: \"content\",\n group: \"Title\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the title\",\n defaultValue: \"lg\",\n tab: \"content\",\n group: \"Title\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"The color of the title\",\n defaultValue: \"foreground\",\n tab: \"content\",\n group: \"Title\",\n }),\n // Message group\n {\n key: \"message\",\n label: \"Message\",\n type: \"textarea\",\n description: \"Optional supporting text\",\n rows: 2,\n defaultValue: \"\",\n tab: \"content\",\n group: \"Message\",\n },\n getColorField({\n key: \"messageColor\",\n label: \"Message Color\",\n description: \"The color of the message — kept readable on the background\",\n defaultValue: \"muted\",\n tab: \"content\",\n group: \"Message\",\n }),\n // Call to action group\n {\n key: \"ctaText\",\n label: \"Button Text\",\n type: \"text\",\n description: \"Optional call-to-action link label (leave blank to hide)\",\n defaultValue: \"\",\n tab: \"content\",\n group: \"Call to Action\",\n },\n {\n key: \"ctaHref\",\n label: \"Button Link\",\n type: \"text\",\n description: \"Where the call-to-action link goes\",\n defaultValue: \"\",\n tab: \"content\",\n group: \"Call to Action\",\n },\n // Appearance group\n {\n key: \"tone\",\n label: \"Tone\",\n type: \"select\",\n description: \"Picks the leading icon that frames the message\",\n options: [\n { label: \"Promo (megaphone)\", value: \"promo\" },\n { label: \"Info\", value: \"info\" },\n { label: \"Success (check)\", value: \"success\" },\n { label: \"Warning\", value: \"warning\" },\n { label: \"Neutral (sparkle)\", value: \"neutral\" },\n ],\n defaultValue: \"promo\",\n tab: \"content\",\n group: \"Appearance\",\n },\n {\n key: \"showIcon\",\n label: \"Show Icon\",\n type: \"boolean\",\n description: \"Show the leading tone icon\",\n defaultValue: true,\n tab: \"content\",\n group: \"Appearance\",\n },\n {\n key: \"showAccentBar\",\n label: \"Show Accent Bar\",\n type: \"boolean\",\n description: \"Show the colored accent stripe (left-aligned only)\",\n defaultValue: true,\n tab: \"content\",\n group: \"Appearance\",\n },\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description: \"Icon, accent stripe and call-to-action color\",\n defaultValue: \"primary\",\n tab: \"content\",\n group: \"Appearance\",\n }),\n {\n key: \"alignment\",\n label: \"Alignment\",\n type: \"buttonGroup\",\n description: \"Text alignment\",\n options: [\n { icon: AlignLeft, ariaLabel: \"Align left\", value: \"left\" },\n { icon: AlignCenter, ariaLabel: \"Align center\", value: \"center\" },\n { icon: AlignRight, ariaLabel: \"Align right\", value: \"right\" },\n ],\n defaultValue: \"left\",\n tab: \"content\",\n group: \"Appearance\",\n },\n // Style group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the announcement banner\",\n defaultValue: { type: \"solid\", color: \"muted\" },\n tab: \"content\",\n group: \"Style\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"The padding of the banner\",\n defaultValue: 6,\n tab: \"content\",\n group: \"Style\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"The border radius of the banner\",\n defaultValue: \"lg\",\n tab: \"content\",\n group: \"Style\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Width of the banner border\",\n defaultValue: \"none\",\n tab: \"content\",\n group: \"Style\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Color of the banner border\",\n defaultValue: \"muted\",\n tab: \"content\",\n group: \"Style\",\n }),\n ],\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AnnouncementWidget-BND76Ojg.mjs","names":[],"sources":["../../widgets/src/widgets/AnnouncementWidget.tsx"],"sourcesContent":["import type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport type { ComponentProps, ComponentType } from \"react\";\nimport type React from \"react\";\nimport {\n getBorderColorField,\n getBorderRadiusField,\n getBorderWidthField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n borderWidthClasses,\n borderColorClasses,\n} from \"../core/fields\";\nimport { sanitizeHref } from \"../lib/link-type-utils\";\nimport { useInternalLinks } from \"../hooks/use-internal-link\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport {\n AlertTriangle,\n AlignCenter,\n AlignLeft,\n AlignRight,\n ArrowRight,\n CheckCircle2,\n Info,\n Megaphone,\n Sparkles,\n} from \"lucide-react\";\n\ntype TextAlignment = \"left\" | \"center\" | \"right\";\ntype Tone = \"info\" | \"success\" | \"warning\" | \"promo\" | \"neutral\";\n\nconst textAlignmentClasses: Record<TextAlignment, string> = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n} as const;\n\n// FontSizeOptions like \"md\" don't map to a real Tailwind class via\n// `text-${size}` (there is no `text-md`), so resolve through a table.\nconst fontSizeClasses: Record<FontSizeOptions, string> = {\n \"2xl\": \"text-2xl\",\n xl: \"text-xl\",\n lg: \"text-lg\",\n md: \"text-base\",\n sm: \"text-sm\",\n xs: \"text-xs\",\n};\n\n// Each tone picks a semantic icon; the color is chosen separately (accentColor)\n// so it always resolves to a theme token rather than a hard-coded hue.\nconst toneIcons: Record<Tone, ComponentType<{ className?: string }>> = {\n info: Info,\n success: CheckCircle2,\n warning: AlertTriangle,\n promo: Megaphone,\n neutral: Sparkles,\n};\n\ntype AnnouncementWidgetProps = ComponentProps<\"div\"> & {\n // Title\n title?: string;\n titleColor?: ColorOptions;\n titleFontSize?: FontSizeOptions;\n\n // Message (optional body)\n message?: string;\n messageColor?: ColorOptions;\n\n // Callout appearance\n tone?: Tone;\n showIcon?: boolean;\n showAccentBar?: boolean;\n accentColor?: ColorOptions;\n\n // Optional call to action\n ctaText?: string;\n ctaHref?: string;\n\n // Layout / styling\n alignment?: TextAlignment;\n background?: BackgroundValue;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n};\n\n// A text token that matches the surface renders invisibly. Fall back to a token\n// that actually contrasts: \"background\" when the surface itself is \"foreground\",\n// otherwise \"foreground\" (so a foreground-on-foreground pick stays legible too).\nfunction readableOn(color: ColorOptions, surface: ColorOptions): ColorOptions {\n if (color !== surface) return color;\n return surface === \"foreground\" ? \"background\" : \"foreground\";\n}\n\nexport function AnnouncementWidget({\n title = \"Announcement\",\n titleColor = \"foreground\",\n titleFontSize = \"lg\",\n message,\n messageColor = \"muted\",\n tone = \"promo\",\n showIcon = true,\n showAccentBar = true,\n accentColor = \"primary\",\n ctaText,\n ctaHref,\n alignment = \"left\",\n background = {\n type: \"solid\",\n color: \"muted\",\n },\n padding = 6,\n borderRadius = \"lg\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n className,\n ...props\n}: AnnouncementWidgetProps): React.JSX.Element {\n const resolveInternalLink = useInternalLinks();\n const backgroundColor = background.color || \"muted\";\n const backgroundImage =\n (background.resource?.image_url || background.resource?.imageUrl) &&\n background.type === \"image\"\n ? `url(${background.resource.image_url || background.resource.imageUrl})`\n : \"none\";\n\n // A text token that matches the background renders invisibly (e.g. muted body\n // text on a muted surface, or foreground text on a foreground surface). Fall\n // back to a contrasting token in that case.\n const titleTextColor = readableOn(titleColor, backgroundColor);\n const messageTextColor = readableOn(messageColor, backgroundColor);\n\n const Icon = toneIcons[tone];\n // Only render a CTA for a safe, well-formed href. sanitizeHref rejects\n // javascript:/data: and other non-navigational schemes an author could type\n // into the free-text Button Link field.\n const safeCtaHref = sanitizeHref(ctaHref?.trim() ?? \"\");\n const hasCta = !!ctaText?.trim() && !!safeCtaHref;\n // Same-portal links navigate in-app (keeping a back button) rather than doing\n // a full document load; external links fall through to the browser.\n const ctaLink = resolveInternalLink(safeCtaHref);\n\n // The icon chip + accent stripe read as a left-anchored callout. Centered\n // alignment stacks the icon above the text instead so nothing looks lopsided.\n const stacked = alignment === \"center\";\n const showStripe = showAccentBar && alignment === \"left\";\n\n return (\n <div\n className={`relative flex overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-${backgroundColor} p-${padding} ${className ?? \"\"}`}\n style={{ backgroundImage }}\n {...props}\n >\n {showStripe && (\n <span\n className={`absolute inset-y-0 left-0 w-1 bg-${accentColor}`}\n aria-hidden\n />\n )}\n\n <div\n className={`flex w-full gap-3 ${stacked ? \"flex-col items-center\" : \"flex-row items-start\"} ${showStripe ? \"pl-2\" : \"\"}`}\n >\n {showIcon && (\n <span\n className={`flex size-9 shrink-0 items-center justify-center rounded-full bg-${accentColor}/15 text-${accentColor}`}\n aria-hidden\n >\n <Icon className=\"size-5\" />\n </span>\n )}\n\n <div className={`min-w-0 flex-1 ${textAlignmentClasses[alignment]}`}>\n <p\n className={`${fontSizeClasses[titleFontSize]} font-header font-semibold tracking-tight text-pretty text-${titleTextColor}`}\n >\n {title}\n </p>\n\n {message && (\n <p\n className={`mt-1 text-sm leading-relaxed text-pretty text-${messageTextColor}`}\n >\n {message}\n </p>\n )}\n\n {hasCta && (\n <a\n href={safeCtaHref}\n onClick={ctaLink.followInternally}\n className={`mt-3 inline-flex items-center gap-1 text-sm font-semibold tracking-tight text-${accentColor} transition-opacity hover:opacity-80`}\n >\n {ctaText}\n <ArrowRight className=\"size-3.5\" aria-hidden />\n </a>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nexport const announcementWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"AnnouncementWidget\",\n displayName: \"Announcement\",\n tabsConfig: [{ id: \"content\", label: \"Content\" }],\n dataSourceTargetProps: [\"title\", \"message\", \"ctaText\", \"ctaHref\"],\n fields: [\n // Title group\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"The announcement headline\",\n defaultValue: \"Announcement\",\n tab: \"content\",\n group: \"Title\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the title\",\n defaultValue: \"lg\",\n tab: \"content\",\n group: \"Title\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"The color of the title\",\n defaultValue: \"foreground\",\n tab: \"content\",\n group: \"Title\",\n }),\n // Message group\n {\n key: \"message\",\n label: \"Message\",\n type: \"textarea\",\n description: \"Optional supporting text\",\n rows: 2,\n defaultValue: \"\",\n tab: \"content\",\n group: \"Message\",\n },\n getColorField({\n key: \"messageColor\",\n label: \"Message Color\",\n description: \"The color of the message — kept readable on the background\",\n defaultValue: \"muted\",\n tab: \"content\",\n group: \"Message\",\n }),\n // Call to action group\n {\n key: \"ctaText\",\n label: \"Button Text\",\n type: \"text\",\n description: \"Optional call-to-action link label (leave blank to hide)\",\n defaultValue: \"\",\n tab: \"content\",\n group: \"Call to Action\",\n },\n {\n key: \"ctaHref\",\n label: \"Button Link\",\n type: \"text\",\n description: \"Where the call-to-action link goes\",\n defaultValue: \"\",\n tab: \"content\",\n group: \"Call to Action\",\n },\n // Appearance group\n {\n key: \"tone\",\n label: \"Tone\",\n type: \"select\",\n description: \"Picks the leading icon that frames the message\",\n options: [\n { label: \"Promo (megaphone)\", value: \"promo\" },\n { label: \"Info\", value: \"info\" },\n { label: \"Success (check)\", value: \"success\" },\n { label: \"Warning\", value: \"warning\" },\n { label: \"Neutral (sparkle)\", value: \"neutral\" },\n ],\n defaultValue: \"promo\",\n tab: \"content\",\n group: \"Appearance\",\n },\n {\n key: \"showIcon\",\n label: \"Show Icon\",\n type: \"boolean\",\n description: \"Show the leading tone icon\",\n defaultValue: true,\n tab: \"content\",\n group: \"Appearance\",\n },\n {\n key: \"showAccentBar\",\n label: \"Show Accent Bar\",\n type: \"boolean\",\n description: \"Show the colored accent stripe (left-aligned only)\",\n defaultValue: true,\n tab: \"content\",\n group: \"Appearance\",\n },\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description: \"Icon, accent stripe and call-to-action color\",\n defaultValue: \"primary\",\n tab: \"content\",\n group: \"Appearance\",\n }),\n {\n key: \"alignment\",\n label: \"Alignment\",\n type: \"buttonGroup\",\n description: \"Text alignment\",\n options: [\n { icon: AlignLeft, ariaLabel: \"Align left\", value: \"left\" },\n { icon: AlignCenter, ariaLabel: \"Align center\", value: \"center\" },\n { icon: AlignRight, ariaLabel: \"Align right\", value: \"right\" },\n ],\n defaultValue: \"left\",\n tab: \"content\",\n group: \"Appearance\",\n },\n // Style group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the announcement banner\",\n defaultValue: { type: \"solid\", color: \"muted\" },\n tab: \"content\",\n group: \"Style\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"The padding of the banner\",\n defaultValue: 6,\n tab: \"content\",\n group: \"Style\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"The border radius of the banner\",\n defaultValue: \"lg\",\n tab: \"content\",\n group: \"Style\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Width of the banner border\",\n defaultValue: \"none\",\n tab: \"content\",\n group: \"Style\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Color of the banner border\",\n defaultValue: \"muted\",\n tab: \"content\",\n group: \"Style\",\n }),\n ],\n};\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require("./chunk-9hOWP6kD.cjs");
|
|
2
2
|
const require_registries = require("./registries-MpWTUak_.cjs");
|
|
3
3
|
const require_link_type_utils = require("./link-type-utils-BLFQIFXy.cjs");
|
|
4
|
-
const require_use_internal_link = require("./use-internal-link-
|
|
4
|
+
const require_use_internal_link = require("./use-internal-link-IcDHjPGp.cjs");
|
|
5
5
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
6
6
|
let lucide_react = require("lucide-react");
|
|
7
7
|
//#region ../widgets/src/widgets/AnnouncementWidget.tsx
|
|
@@ -300,4 +300,4 @@ Object.defineProperty(exports, "announcementWidgetPropertySchema", {
|
|
|
300
300
|
}
|
|
301
301
|
});
|
|
302
302
|
|
|
303
|
-
//# sourceMappingURL=AnnouncementWidget-
|
|
303
|
+
//# sourceMappingURL=AnnouncementWidget-Dh6nKAqT.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnnouncementWidget-BIFJ7E6o.cjs","names":["Info","CheckCircle2","AlertTriangle","Megaphone","Sparkles","useInternalLinks","sanitizeHref","borderWidthClasses","borderColorClasses","ArrowRight","getFontSizeField","getColorField","AlignLeft","AlignCenter","AlignRight","getPaddingField","getBorderRadiusField","getBorderWidthField","getBorderColorField"],"sources":["../../widgets/src/widgets/AnnouncementWidget.tsx"],"sourcesContent":["import type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport type { ComponentProps, ComponentType } from \"react\";\nimport type React from \"react\";\nimport {\n getBorderColorField,\n getBorderRadiusField,\n getBorderWidthField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n borderWidthClasses,\n borderColorClasses,\n} from \"../core/fields\";\nimport { sanitizeHref } from \"../lib/link-type-utils\";\nimport { useInternalLinks } from \"../hooks/use-internal-link\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport {\n AlertTriangle,\n AlignCenter,\n AlignLeft,\n AlignRight,\n ArrowRight,\n CheckCircle2,\n Info,\n Megaphone,\n Sparkles,\n} from \"lucide-react\";\n\ntype TextAlignment = \"left\" | \"center\" | \"right\";\ntype Tone = \"info\" | \"success\" | \"warning\" | \"promo\" | \"neutral\";\n\nconst textAlignmentClasses: Record<TextAlignment, string> = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n} as const;\n\n// FontSizeOptions like \"md\" don't map to a real Tailwind class via\n// `text-${size}` (there is no `text-md`), so resolve through a table.\nconst fontSizeClasses: Record<FontSizeOptions, string> = {\n \"2xl\": \"text-2xl\",\n xl: \"text-xl\",\n lg: \"text-lg\",\n md: \"text-base\",\n sm: \"text-sm\",\n xs: \"text-xs\",\n};\n\n// Each tone picks a semantic icon; the color is chosen separately (accentColor)\n// so it always resolves to a theme token rather than a hard-coded hue.\nconst toneIcons: Record<Tone, ComponentType<{ className?: string }>> = {\n info: Info,\n success: CheckCircle2,\n warning: AlertTriangle,\n promo: Megaphone,\n neutral: Sparkles,\n};\n\ntype AnnouncementWidgetProps = ComponentProps<\"div\"> & {\n // Title\n title?: string;\n titleColor?: ColorOptions;\n titleFontSize?: FontSizeOptions;\n\n // Message (optional body)\n message?: string;\n messageColor?: ColorOptions;\n\n // Callout appearance\n tone?: Tone;\n showIcon?: boolean;\n showAccentBar?: boolean;\n accentColor?: ColorOptions;\n\n // Optional call to action\n ctaText?: string;\n ctaHref?: string;\n\n // Layout / styling\n alignment?: TextAlignment;\n background?: BackgroundValue;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n};\n\n// A text token that matches the surface renders invisibly. Fall back to a token\n// that actually contrasts: \"background\" when the surface itself is \"foreground\",\n// otherwise \"foreground\" (so a foreground-on-foreground pick stays legible too).\nfunction readableOn(color: ColorOptions, surface: ColorOptions): ColorOptions {\n if (color !== surface) return color;\n return surface === \"foreground\" ? \"background\" : \"foreground\";\n}\n\nexport function AnnouncementWidget({\n title = \"Announcement\",\n titleColor = \"foreground\",\n titleFontSize = \"lg\",\n message,\n messageColor = \"muted\",\n tone = \"promo\",\n showIcon = true,\n showAccentBar = true,\n accentColor = \"primary\",\n ctaText,\n ctaHref,\n alignment = \"left\",\n background = {\n type: \"solid\",\n color: \"muted\",\n },\n padding = 6,\n borderRadius = \"lg\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n className,\n ...props\n}: AnnouncementWidgetProps): React.JSX.Element {\n const resolveInternalLink = useInternalLinks();\n const backgroundColor = background.color || \"muted\";\n const backgroundImage =\n (background.resource?.image_url || background.resource?.imageUrl) &&\n background.type === \"image\"\n ? `url(${background.resource.image_url || background.resource.imageUrl})`\n : \"none\";\n\n // A text token that matches the background renders invisibly (e.g. muted body\n // text on a muted surface, or foreground text on a foreground surface). Fall\n // back to a contrasting token in that case.\n const titleTextColor = readableOn(titleColor, backgroundColor);\n const messageTextColor = readableOn(messageColor, backgroundColor);\n\n const Icon = toneIcons[tone];\n // Only render a CTA for a safe, well-formed href. sanitizeHref rejects\n // javascript:/data: and other non-navigational schemes an author could type\n // into the free-text Button Link field.\n const safeCtaHref = sanitizeHref(ctaHref?.trim() ?? \"\");\n const hasCta = !!ctaText?.trim() && !!safeCtaHref;\n // Same-portal links navigate in-app (keeping a back button) rather than doing\n // a full document load; external links fall through to the browser.\n const ctaLink = resolveInternalLink(safeCtaHref);\n\n // The icon chip + accent stripe read as a left-anchored callout. Centered\n // alignment stacks the icon above the text instead so nothing looks lopsided.\n const stacked = alignment === \"center\";\n const showStripe = showAccentBar && alignment === \"left\";\n\n return (\n <div\n className={`relative flex overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-${backgroundColor} p-${padding} ${className ?? \"\"}`}\n style={{ backgroundImage }}\n {...props}\n >\n {showStripe && (\n <span\n className={`absolute inset-y-0 left-0 w-1 bg-${accentColor}`}\n aria-hidden\n />\n )}\n\n <div\n className={`flex w-full gap-3 ${stacked ? \"flex-col items-center\" : \"flex-row items-start\"} ${showStripe ? \"pl-2\" : \"\"}`}\n >\n {showIcon && (\n <span\n className={`flex size-9 shrink-0 items-center justify-center rounded-full bg-${accentColor}/15 text-${accentColor}`}\n aria-hidden\n >\n <Icon className=\"size-5\" />\n </span>\n )}\n\n <div className={`min-w-0 flex-1 ${textAlignmentClasses[alignment]}`}>\n <p\n className={`${fontSizeClasses[titleFontSize]} font-header font-semibold tracking-tight text-pretty text-${titleTextColor}`}\n >\n {title}\n </p>\n\n {message && (\n <p\n className={`mt-1 text-sm leading-relaxed text-pretty text-${messageTextColor}`}\n >\n {message}\n </p>\n )}\n\n {hasCta && (\n <a\n href={safeCtaHref}\n onClick={ctaLink.followInternally}\n className={`mt-3 inline-flex items-center gap-1 text-sm font-semibold tracking-tight text-${accentColor} transition-opacity hover:opacity-80`}\n >\n {ctaText}\n <ArrowRight className=\"size-3.5\" aria-hidden />\n </a>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nexport const announcementWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"AnnouncementWidget\",\n displayName: \"Announcement\",\n tabsConfig: [{ id: \"content\", label: \"Content\" }],\n dataSourceTargetProps: [\"title\", \"message\", \"ctaText\", \"ctaHref\"],\n fields: [\n // Title group\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"The announcement headline\",\n defaultValue: \"Announcement\",\n tab: \"content\",\n group: \"Title\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the title\",\n defaultValue: \"lg\",\n tab: \"content\",\n group: \"Title\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"The color of the title\",\n defaultValue: \"foreground\",\n tab: \"content\",\n group: \"Title\",\n }),\n // Message group\n {\n key: \"message\",\n label: \"Message\",\n type: \"textarea\",\n description: \"Optional supporting text\",\n rows: 2,\n defaultValue: \"\",\n tab: \"content\",\n group: \"Message\",\n },\n getColorField({\n key: \"messageColor\",\n label: \"Message Color\",\n description: \"The color of the message — kept readable on the background\",\n defaultValue: \"muted\",\n tab: \"content\",\n group: \"Message\",\n }),\n // Call to action group\n {\n key: \"ctaText\",\n label: \"Button Text\",\n type: \"text\",\n description: \"Optional call-to-action link label (leave blank to hide)\",\n defaultValue: \"\",\n tab: \"content\",\n group: \"Call to Action\",\n },\n {\n key: \"ctaHref\",\n label: \"Button Link\",\n type: \"text\",\n description: \"Where the call-to-action link goes\",\n defaultValue: \"\",\n tab: \"content\",\n group: \"Call to Action\",\n },\n // Appearance group\n {\n key: \"tone\",\n label: \"Tone\",\n type: \"select\",\n description: \"Picks the leading icon that frames the message\",\n options: [\n { label: \"Promo (megaphone)\", value: \"promo\" },\n { label: \"Info\", value: \"info\" },\n { label: \"Success (check)\", value: \"success\" },\n { label: \"Warning\", value: \"warning\" },\n { label: \"Neutral (sparkle)\", value: \"neutral\" },\n ],\n defaultValue: \"promo\",\n tab: \"content\",\n group: \"Appearance\",\n },\n {\n key: \"showIcon\",\n label: \"Show Icon\",\n type: \"boolean\",\n description: \"Show the leading tone icon\",\n defaultValue: true,\n tab: \"content\",\n group: \"Appearance\",\n },\n {\n key: \"showAccentBar\",\n label: \"Show Accent Bar\",\n type: \"boolean\",\n description: \"Show the colored accent stripe (left-aligned only)\",\n defaultValue: true,\n tab: \"content\",\n group: \"Appearance\",\n },\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description: \"Icon, accent stripe and call-to-action color\",\n defaultValue: \"primary\",\n tab: \"content\",\n group: \"Appearance\",\n }),\n {\n key: \"alignment\",\n label: \"Alignment\",\n type: \"buttonGroup\",\n description: \"Text alignment\",\n options: [\n { icon: AlignLeft, ariaLabel: \"Align left\", value: \"left\" },\n { icon: AlignCenter, ariaLabel: \"Align center\", value: \"center\" },\n { icon: AlignRight, ariaLabel: \"Align right\", value: \"right\" },\n ],\n defaultValue: \"left\",\n tab: \"content\",\n group: \"Appearance\",\n },\n // Style group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the announcement banner\",\n defaultValue: { type: \"solid\", color: \"muted\" },\n tab: \"content\",\n group: \"Style\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"The padding of the banner\",\n defaultValue: 6,\n tab: \"content\",\n group: \"Style\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"The border radius of the banner\",\n defaultValue: \"lg\",\n tab: \"content\",\n group: \"Style\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Width of the banner border\",\n defaultValue: \"none\",\n tab: \"content\",\n group: \"Style\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Color of the banner border\",\n defaultValue: \"muted\",\n tab: \"content\",\n group: \"Style\",\n }),\n ],\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AnnouncementWidget-Dh6nKAqT.cjs","names":["Info","CheckCircle2","AlertTriangle","Megaphone","Sparkles","useInternalLinks","sanitizeHref","borderWidthClasses","borderColorClasses","ArrowRight","getFontSizeField","getColorField","AlignLeft","AlignCenter","AlignRight","getPaddingField","getBorderRadiusField","getBorderWidthField","getBorderColorField"],"sources":["../../widgets/src/widgets/AnnouncementWidget.tsx"],"sourcesContent":["import type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport type { ComponentProps, ComponentType } from \"react\";\nimport type React from \"react\";\nimport {\n getBorderColorField,\n getBorderRadiusField,\n getBorderWidthField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n borderWidthClasses,\n borderColorClasses,\n} from \"../core/fields\";\nimport { sanitizeHref } from \"../lib/link-type-utils\";\nimport { useInternalLinks } from \"../hooks/use-internal-link\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport {\n AlertTriangle,\n AlignCenter,\n AlignLeft,\n AlignRight,\n ArrowRight,\n CheckCircle2,\n Info,\n Megaphone,\n Sparkles,\n} from \"lucide-react\";\n\ntype TextAlignment = \"left\" | \"center\" | \"right\";\ntype Tone = \"info\" | \"success\" | \"warning\" | \"promo\" | \"neutral\";\n\nconst textAlignmentClasses: Record<TextAlignment, string> = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n} as const;\n\n// FontSizeOptions like \"md\" don't map to a real Tailwind class via\n// `text-${size}` (there is no `text-md`), so resolve through a table.\nconst fontSizeClasses: Record<FontSizeOptions, string> = {\n \"2xl\": \"text-2xl\",\n xl: \"text-xl\",\n lg: \"text-lg\",\n md: \"text-base\",\n sm: \"text-sm\",\n xs: \"text-xs\",\n};\n\n// Each tone picks a semantic icon; the color is chosen separately (accentColor)\n// so it always resolves to a theme token rather than a hard-coded hue.\nconst toneIcons: Record<Tone, ComponentType<{ className?: string }>> = {\n info: Info,\n success: CheckCircle2,\n warning: AlertTriangle,\n promo: Megaphone,\n neutral: Sparkles,\n};\n\ntype AnnouncementWidgetProps = ComponentProps<\"div\"> & {\n // Title\n title?: string;\n titleColor?: ColorOptions;\n titleFontSize?: FontSizeOptions;\n\n // Message (optional body)\n message?: string;\n messageColor?: ColorOptions;\n\n // Callout appearance\n tone?: Tone;\n showIcon?: boolean;\n showAccentBar?: boolean;\n accentColor?: ColorOptions;\n\n // Optional call to action\n ctaText?: string;\n ctaHref?: string;\n\n // Layout / styling\n alignment?: TextAlignment;\n background?: BackgroundValue;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n};\n\n// A text token that matches the surface renders invisibly. Fall back to a token\n// that actually contrasts: \"background\" when the surface itself is \"foreground\",\n// otherwise \"foreground\" (so a foreground-on-foreground pick stays legible too).\nfunction readableOn(color: ColorOptions, surface: ColorOptions): ColorOptions {\n if (color !== surface) return color;\n return surface === \"foreground\" ? \"background\" : \"foreground\";\n}\n\nexport function AnnouncementWidget({\n title = \"Announcement\",\n titleColor = \"foreground\",\n titleFontSize = \"lg\",\n message,\n messageColor = \"muted\",\n tone = \"promo\",\n showIcon = true,\n showAccentBar = true,\n accentColor = \"primary\",\n ctaText,\n ctaHref,\n alignment = \"left\",\n background = {\n type: \"solid\",\n color: \"muted\",\n },\n padding = 6,\n borderRadius = \"lg\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n className,\n ...props\n}: AnnouncementWidgetProps): React.JSX.Element {\n const resolveInternalLink = useInternalLinks();\n const backgroundColor = background.color || \"muted\";\n const backgroundImage =\n (background.resource?.image_url || background.resource?.imageUrl) &&\n background.type === \"image\"\n ? `url(${background.resource.image_url || background.resource.imageUrl})`\n : \"none\";\n\n // A text token that matches the background renders invisibly (e.g. muted body\n // text on a muted surface, or foreground text on a foreground surface). Fall\n // back to a contrasting token in that case.\n const titleTextColor = readableOn(titleColor, backgroundColor);\n const messageTextColor = readableOn(messageColor, backgroundColor);\n\n const Icon = toneIcons[tone];\n // Only render a CTA for a safe, well-formed href. sanitizeHref rejects\n // javascript:/data: and other non-navigational schemes an author could type\n // into the free-text Button Link field.\n const safeCtaHref = sanitizeHref(ctaHref?.trim() ?? \"\");\n const hasCta = !!ctaText?.trim() && !!safeCtaHref;\n // Same-portal links navigate in-app (keeping a back button) rather than doing\n // a full document load; external links fall through to the browser.\n const ctaLink = resolveInternalLink(safeCtaHref);\n\n // The icon chip + accent stripe read as a left-anchored callout. Centered\n // alignment stacks the icon above the text instead so nothing looks lopsided.\n const stacked = alignment === \"center\";\n const showStripe = showAccentBar && alignment === \"left\";\n\n return (\n <div\n className={`relative flex overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-${backgroundColor} p-${padding} ${className ?? \"\"}`}\n style={{ backgroundImage }}\n {...props}\n >\n {showStripe && (\n <span\n className={`absolute inset-y-0 left-0 w-1 bg-${accentColor}`}\n aria-hidden\n />\n )}\n\n <div\n className={`flex w-full gap-3 ${stacked ? \"flex-col items-center\" : \"flex-row items-start\"} ${showStripe ? \"pl-2\" : \"\"}`}\n >\n {showIcon && (\n <span\n className={`flex size-9 shrink-0 items-center justify-center rounded-full bg-${accentColor}/15 text-${accentColor}`}\n aria-hidden\n >\n <Icon className=\"size-5\" />\n </span>\n )}\n\n <div className={`min-w-0 flex-1 ${textAlignmentClasses[alignment]}`}>\n <p\n className={`${fontSizeClasses[titleFontSize]} font-header font-semibold tracking-tight text-pretty text-${titleTextColor}`}\n >\n {title}\n </p>\n\n {message && (\n <p\n className={`mt-1 text-sm leading-relaxed text-pretty text-${messageTextColor}`}\n >\n {message}\n </p>\n )}\n\n {hasCta && (\n <a\n href={safeCtaHref}\n onClick={ctaLink.followInternally}\n className={`mt-3 inline-flex items-center gap-1 text-sm font-semibold tracking-tight text-${accentColor} transition-opacity hover:opacity-80`}\n >\n {ctaText}\n <ArrowRight className=\"size-3.5\" aria-hidden />\n </a>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nexport const announcementWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"AnnouncementWidget\",\n displayName: \"Announcement\",\n tabsConfig: [{ id: \"content\", label: \"Content\" }],\n dataSourceTargetProps: [\"title\", \"message\", \"ctaText\", \"ctaHref\"],\n fields: [\n // Title group\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"The announcement headline\",\n defaultValue: \"Announcement\",\n tab: \"content\",\n group: \"Title\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the title\",\n defaultValue: \"lg\",\n tab: \"content\",\n group: \"Title\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"The color of the title\",\n defaultValue: \"foreground\",\n tab: \"content\",\n group: \"Title\",\n }),\n // Message group\n {\n key: \"message\",\n label: \"Message\",\n type: \"textarea\",\n description: \"Optional supporting text\",\n rows: 2,\n defaultValue: \"\",\n tab: \"content\",\n group: \"Message\",\n },\n getColorField({\n key: \"messageColor\",\n label: \"Message Color\",\n description: \"The color of the message — kept readable on the background\",\n defaultValue: \"muted\",\n tab: \"content\",\n group: \"Message\",\n }),\n // Call to action group\n {\n key: \"ctaText\",\n label: \"Button Text\",\n type: \"text\",\n description: \"Optional call-to-action link label (leave blank to hide)\",\n defaultValue: \"\",\n tab: \"content\",\n group: \"Call to Action\",\n },\n {\n key: \"ctaHref\",\n label: \"Button Link\",\n type: \"text\",\n description: \"Where the call-to-action link goes\",\n defaultValue: \"\",\n tab: \"content\",\n group: \"Call to Action\",\n },\n // Appearance group\n {\n key: \"tone\",\n label: \"Tone\",\n type: \"select\",\n description: \"Picks the leading icon that frames the message\",\n options: [\n { label: \"Promo (megaphone)\", value: \"promo\" },\n { label: \"Info\", value: \"info\" },\n { label: \"Success (check)\", value: \"success\" },\n { label: \"Warning\", value: \"warning\" },\n { label: \"Neutral (sparkle)\", value: \"neutral\" },\n ],\n defaultValue: \"promo\",\n tab: \"content\",\n group: \"Appearance\",\n },\n {\n key: \"showIcon\",\n label: \"Show Icon\",\n type: \"boolean\",\n description: \"Show the leading tone icon\",\n defaultValue: true,\n tab: \"content\",\n group: \"Appearance\",\n },\n {\n key: \"showAccentBar\",\n label: \"Show Accent Bar\",\n type: \"boolean\",\n description: \"Show the colored accent stripe (left-aligned only)\",\n defaultValue: true,\n tab: \"content\",\n group: \"Appearance\",\n },\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description: \"Icon, accent stripe and call-to-action color\",\n defaultValue: \"primary\",\n tab: \"content\",\n group: \"Appearance\",\n }),\n {\n key: \"alignment\",\n label: \"Alignment\",\n type: \"buttonGroup\",\n description: \"Text alignment\",\n options: [\n { icon: AlignLeft, ariaLabel: \"Align left\", value: \"left\" },\n { icon: AlignCenter, ariaLabel: \"Align center\", value: \"center\" },\n { icon: AlignRight, ariaLabel: \"Align right\", value: \"right\" },\n ],\n defaultValue: \"left\",\n tab: \"content\",\n group: \"Appearance\",\n },\n // Style group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the announcement banner\",\n defaultValue: { type: \"solid\", color: \"muted\" },\n tab: \"content\",\n group: \"Style\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"The padding of the banner\",\n defaultValue: 6,\n tab: \"content\",\n group: \"Style\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"The border radius of the banner\",\n defaultValue: \"lg\",\n tab: \"content\",\n group: \"Style\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Width of the banner border\",\n defaultValue: \"none\",\n tab: \"content\",\n group: \"Style\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Color of the banner border\",\n defaultValue: \"muted\",\n tab: \"content\",\n group: \"Style\",\n }),\n ],\n};\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
require("./chunk-9hOWP6kD.cjs");
|
|
2
|
-
const require_WidgetInteractionContext = require("./WidgetInteractionContext-
|
|
2
|
+
const require_WidgetInteractionContext = require("./WidgetInteractionContext-D9dBJ-39.cjs");
|
|
3
3
|
const require_WidgetRenderStateContext = require("./WidgetRenderStateContext-C6wVdsJR.cjs");
|
|
4
4
|
const require_registries = require("./registries-MpWTUak_.cjs");
|
|
5
|
-
const require_use_internal_link = require("./use-internal-link-
|
|
5
|
+
const require_use_internal_link = require("./use-internal-link-IcDHjPGp.cjs");
|
|
6
6
|
const require_helpers = require("./helpers-BNPN4U1M.cjs");
|
|
7
7
|
const require_MediaRenderer = require("./MediaRenderer-m_d4GHu0.cjs");
|
|
8
8
|
const require_link_type_schema_fields = require("./link-type-schema-fields-CNbDLtZ3.cjs");
|
|
@@ -759,4 +759,4 @@ Object.defineProperty(exports, "carouselWidgetPropertySchema", {
|
|
|
759
759
|
}
|
|
760
760
|
});
|
|
761
761
|
|
|
762
|
-
//# sourceMappingURL=CarouselWidget-
|
|
762
|
+
//# sourceMappingURL=CarouselWidget-BETNqs_K.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CarouselWidget-fft3Aibh.cjs","names":["useWidgetInteraction","useInternalLinks","useRepUser","useWidgetRenderState","borderWidthClasses","borderColorClasses","buildItemInteractionProps","MediaRenderer","getMediaPropsFromWidgetSchema","DOMPurify","getColorField","getFontSizeField","getHeightField","getBorderRadiusField","getBorderWidthField","getBorderColorField","getPaddingField","getButtonSizeField","getLinkTypeFields"],"sources":["../../widgets/src/widgets/CarouselWidget.tsx"],"sourcesContent":["import type { ComponentProps, CSSProperties } from \"react\";\nimport type React from \"react\";\nimport { useEffect, useState, useCallback } from \"react\";\nimport DOMPurify from \"dompurify\";\nimport {\n MediaRenderer,\n getMediaPropsFromWidgetSchema,\n} from \"../components/MediaRenderer\";\nimport type {\n WidgetSchema,\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n AlignOptions,\n FontSizeOptions,\n PaddingOptions,\n ButtonSizeOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n borderColorClasses,\n borderWidthClasses,\n getBorderColorField,\n getBorderRadiusField,\n getBorderWidthField,\n getButtonSizeField,\n getColorField,\n getFontSizeField,\n getHeightField,\n getPaddingField,\n} from \"../core/fields\";\nimport { useWidgetInteraction } from \"../contexts/WidgetInteractionContext\";\nimport { useRepUser } from \"../contexts/RepUserContext\";\nimport { useWidgetRenderState } from \"../contexts/WidgetRenderStateContext\";\nimport { useInternalLinks } from \"../hooks/use-internal-link\";\nimport { buildItemInteractionProps } from \"./list-widget/helpers\";\nimport { getLinkTypeFields } from \"../lib/link-type-schema-fields\";\n\ntype CarouselSlide = {\n id: string;\n content: WidgetSchema;\n title?: string;\n description?: string;\n // Editorial additions (all optional — existing configs keep working)\n eyebrow?: string;\n meta?: string;\n tag?: string;\n tagColor?: ColorOptions;\n buttonEnabled?: boolean;\n buttonText?: string;\n buttonVariant?:\n | \"default\"\n | \"secondary\"\n | \"outline\"\n | \"destructive\"\n | \"ghost\"\n | \"link\";\n buttonLink?: string;\n secondaryButtonText?: string;\n secondaryButtonLink?: string;\n // Index signature lets data-source-driven slides carry extra fields\n // (e.g. shareable_type, subscription_token) through to onItemClick,\n // which routes based on them — matches ListWidget's ListItem shape.\n [key: string]: unknown;\n};\n\ntype CarouselWidgetProps = ComponentProps<\"div\"> & {\n slides?: CarouselSlide[];\n autoScrollInterval?: number;\n enableAutoScroll?: boolean;\n\n // Layout\n align?: AlignOptions;\n // CSS-unit string (\"400px\", \"30rem\", \"50%\") — kept as string so saved\n // configs from the previous schema continue to render. The schema field\n // is `cssUnit` (via getHeightField), which produces a string with the\n // unit baked in.\n carouselHeight?: string;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n padding?: PaddingOptions;\n\n // Text Styling\n headerSize?: FontSizeOptions;\n headerColor?: ColorOptions;\n textSize?: FontSizeOptions;\n textColor?: ColorOptions;\n textWidth?: string;\n\n // Button\n showButton?: boolean;\n buttonColor?: ColorOptions;\n buttonSize?: ButtonSizeOptions;\n\n // Overlay\n overlayEnabled?: boolean;\n overlayType?: \"solid\" | \"gradient\";\n overlayIntensity?: number;\n\n // Editorial frame (new — opt-out via `editorialFrame={false}`)\n editorialFrame?: boolean;\n frameColor?: ColorOptions;\n};\n\nconst VIDEO_CONTROLS_HEIGHT = 44;\n\nconst HEADER_SIZE_MAP: Record<FontSizeOptions, string> = {\n xs: \"text-base sm:text-lg\",\n sm: \"text-lg sm:text-xl\",\n md: \"text-xl sm:text-2xl\",\n lg: \"text-2xl sm:text-3xl\",\n xl: \"text-3xl sm:text-[32px]\",\n \"2xl\": \"text-[32px] sm:text-[40px]\",\n};\n\nconst BODY_SIZE_MAP: Record<FontSizeOptions, string> = {\n xs: \"text-[12px]\",\n sm: \"text-[13px]\",\n md: \"text-[14px]\",\n lg: \"text-[15px]\",\n xl: \"text-[16px]\",\n \"2xl\": \"text-[18px]\",\n};\n\nfunction useCarouselController({\n slideCount,\n enableAutoScroll,\n autoScrollInterval,\n}: {\n slideCount: number;\n enableAutoScroll: boolean;\n autoScrollInterval: number;\n}) {\n const [currentIndex, setCurrentIndex] = useState(0);\n // Track hover and keyboard focus separately — combining them in one boolean\n // would let `onMouseLeave` clear the paused state even while a child button\n // still has focus.\n const [isHovered, setIsHovered] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n const hasSlides = slideCount > 0;\n const isPaused = isHovered || isFocused;\n\n const goToNext = useCallback(() => {\n if (!hasSlides) return;\n setCurrentIndex((prev) => (prev === slideCount - 1 ? 0 : prev + 1));\n }, [hasSlides, slideCount]);\n\n const goToPrevious = useCallback(() => {\n if (!hasSlides) return;\n setCurrentIndex((prev) => (prev === 0 ? slideCount - 1 : prev - 1));\n }, [hasSlides, slideCount]);\n\n const goToSlide = useCallback(\n (index: number) => {\n if (!hasSlides) return;\n if (index >= 0 && index < slideCount) {\n setCurrentIndex(index);\n }\n },\n [hasSlides, slideCount],\n );\n\n useEffect(() => {\n if (!enableAutoScroll || !hasSlides || isPaused) return;\n const intervalId = setInterval(goToNext, autoScrollInterval);\n return () => clearInterval(intervalId);\n }, [enableAutoScroll, autoScrollInterval, hasSlides, isPaused, goToNext]);\n\n useEffect(() => {\n if (currentIndex >= slideCount && slideCount > 0) {\n setCurrentIndex(0);\n }\n }, [slideCount, currentIndex]);\n\n // Pause for a mouse or the keyboard, never for a touch. On iOS a tap fires\n // mouseenter with no mouseleave after it, and it focuses the button too, so\n // either one would leave the carousel stuck paused.\n const handlePointerEnter = useCallback((e: React.PointerEvent) => {\n if (e.pointerType === \"mouse\") setIsHovered(true);\n }, []);\n const handlePointerLeave = useCallback((e: React.PointerEvent) => {\n if (e.pointerType === \"mouse\") setIsHovered(false);\n }, []);\n const handleFocus = useCallback((e: React.FocusEvent<HTMLElement>) => {\n // Set it either way, or a click inside leaves it paused.\n setIsFocused(\n e.target instanceof Element && e.target.matches(\":focus-visible\"),\n );\n }, []);\n const handleBlur = useCallback((e: React.FocusEvent<HTMLElement>) => {\n // Only flip to unfocused when focus actually leaves the carousel.\n // When focus moves between two children (e.g. tabbing from prev to next\n // button), `relatedTarget` is the new focus target and is still contained.\n if (!e.currentTarget.contains(e.relatedTarget as Node | null)) {\n setIsFocused(false);\n }\n }, []);\n\n return {\n currentIndex,\n hasSlides,\n isPaused,\n goToNext,\n goToPrevious,\n goToSlide,\n handlePointerEnter,\n handlePointerLeave,\n handleFocus,\n handleBlur,\n };\n}\n\nexport function CarouselWidget({\n slides = [],\n autoScrollInterval = 6500,\n enableAutoScroll = false,\n carouselHeight = \"400px\",\n align = { vertical: \"bottom\", horizontal: \"left\" },\n overlayIntensity = 70,\n borderRadius = \"xl\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n padding = 8,\n textWidth = \"620px\",\n headerSize = \"xl\",\n headerColor = \"background\",\n textSize = \"md\",\n textColor = \"background\",\n showButton = true,\n buttonColor = \"background\",\n buttonSize = \"default\",\n overlayEnabled = true,\n overlayType = \"gradient\",\n editorialFrame = true,\n frameColor = \"foreground\",\n className,\n ...props\n}: CarouselWidgetProps): React.JSX.Element {\n const totalSlides = slides.length;\n const {\n currentIndex,\n hasSlides,\n isPaused,\n goToNext,\n goToPrevious,\n goToSlide,\n handlePointerEnter,\n handlePointerLeave,\n handleFocus,\n handleBlur,\n } = useCarouselController({\n slideCount: totalSlides,\n enableAutoScroll,\n autoScrollInterval,\n });\n const { onItemClick, onNavigate, buildHref, resolveInternalSlug } =\n useWidgetInteraction();\n const resolveInternalLink = useInternalLinks();\n const publicId = useRepUser()?.publicId;\n const { editMode } = useWidgetRenderState();\n const verticalClass =\n align.vertical === \"top\"\n ? \"items-start\"\n : align.vertical === \"center\"\n ? \"items-center\"\n : \"items-end\";\n\n const horizontalClass =\n align.horizontal === \"center\"\n ? \"justify-center text-center mx-auto\"\n : align.horizontal === \"right\"\n ? \"justify-end ml-auto text-right\"\n : \"justify-start text-left\";\n\n // Themed dual-shadow (crisp + soft ambient) on the editorial frame —\n // derived from the foreground token so the lift reads in both light\n // and dark themes.\n const frameShadowStyle: CSSProperties | undefined = editorialFrame\n ? {\n boxShadow: `0 1px 2px color-mix(in oklch, var(--color-foreground) 4%, transparent), 0 30px 60px -30px color-mix(in oklch, var(--color-foreground) 40%, transparent)`,\n }\n : undefined;\n\n const frameBg = editorialFrame ? `bg-${frameColor}` : \"\";\n const isActiveSlideVideo =\n slides[currentIndex]?.content.type === \"VideoWidget\";\n\n if (!hasSlides) {\n return (\n <div\n className={`relative w-full overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${frameBg} ${className ?? \"\"}`}\n style={{ minHeight: carouselHeight, ...frameShadowStyle }}\n {...props}\n >\n <div\n className=\"bg-muted/20 flex h-full w-full items-center justify-center\"\n style={{ minHeight: carouselHeight }}\n >\n <div className=\"text-muted-foreground flex flex-col items-center gap-2\">\n <div className=\"text-4xl\">🎠</div>\n <p className=\"text-sm\">No slides added</p>\n <p className=\"text-muted-foreground/70 text-xs\">\n Add slides to create a carousel\n </p>\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div\n className={`relative isolate w-full overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${frameBg} ${className ?? \"\"}`}\n style={{ minHeight: carouselHeight, ...frameShadowStyle }}\n onPointerEnter={handlePointerEnter}\n onPointerLeave={handlePointerLeave}\n onFocus={handleFocus}\n onBlur={handleBlur}\n {...props}\n >\n <div\n className=\"relative w-full\"\n style={{\n minHeight: carouselHeight,\n height: carouselHeight,\n }}\n >\n {slides.map((slide, index) => {\n const isActive = index === currentIndex;\n const isVideoSlide = slide.content.type === \"VideoWidget\";\n // Strip the optional \"%\" suffix, then parse. Use Number.isFinite +\n // clamp so an explicit 0 isn't silently replaced by the 70 fallback\n // (the previous `|| 70` treated 0 as falsy).\n const parsedOverlayIntensity = Number(\n String(overlayIntensity).replace(\"%\", \"\"),\n );\n const overlayOpacity =\n (Number.isFinite(parsedOverlayIntensity)\n ? Math.min(100, Math.max(0, parsedOverlayIntensity))\n : 70) / 100;\n\n // Slide-level tap: if the slide has an explicit linkType from\n // itemConfigSchema, use it; otherwise fall back to onItemClick\n // (which routes based on shareable_type, subscription_token, etc.).\n const slideLinkProps =\n isActive && !isVideoSlide\n ? buildItemInteractionProps(slide, {\n onItemClick,\n onNavigate,\n buildHref,\n resolveInternalSlug,\n publicId,\n editMode,\n })\n : {};\n const isInteractive = Object.keys(slideLinkProps).length > 0;\n\n return (\n <div\n key={slide.id}\n className={`absolute inset-0 transition-opacity duration-700 ease-out${isInteractive ? \" cursor-pointer focus-visible:ring-2 focus-visible:ring-white/60 focus-visible:outline-none focus-visible:ring-inset\" : \"\"}`}\n style={{\n opacity: isActive ? 1 : 0,\n pointerEvents: isActive ? \"auto\" : \"none\",\n }}\n aria-hidden={!isActive}\n {...slideLinkProps}\n >\n {isVideoSlide ? (\n <div className=\"absolute inset-0 h-full w-full\">\n {isActive && (\n <MediaRenderer\n {...getMediaPropsFromWidgetSchema(slide.content)}\n />\n )}\n </div>\n ) : (\n <>\n <div\n className=\"absolute inset-0 h-full w-full\"\n style={{\n transform: isActive ? \"scale(1)\" : \"scale(1.04)\",\n animation: isActive\n ? \"fluidCarouselKenBurns 900ms ease-out both\"\n : undefined,\n }}\n >\n <MediaRenderer\n {...getMediaPropsFromWidgetSchema(slide.content)}\n />\n </div>\n\n {overlayEnabled && editorialFrame && (\n <>\n <div\n className={`pointer-events-none absolute inset-0 bg-gradient-to-t from-${frameColor} via-${frameColor}/65 to-${frameColor}/10`}\n style={{ opacity: overlayOpacity }}\n />\n <div\n className={`pointer-events-none absolute inset-0 bg-gradient-to-r from-${frameColor}/80 via-transparent to-transparent`}\n style={{ opacity: Math.min(1, overlayOpacity + 0.1) }}\n />\n </>\n )}\n\n {overlayEnabled && !editorialFrame && (\n <div\n className={`pointer-events-none absolute inset-0 ${\n overlayType === \"gradient\"\n ? \"bg-gradient-to-t from-black to-transparent\"\n : \"bg-black\"\n }`}\n style={{ opacity: overlayOpacity }}\n />\n )}\n </>\n )}\n\n <div\n className={`pointer-events-none absolute inset-0 flex px-6 sm:px-10 ${verticalClass} ${\n align.horizontal === \"center\"\n ? \"justify-center\"\n : align.horizontal === \"right\"\n ? \"justify-end\"\n : \"justify-start\"\n }`}\n style={{\n paddingTop: padding * 4,\n paddingBottom:\n padding * 4 +\n (totalSlides > 1\n ? 24 + (isVideoSlide ? VIDEO_CONTROLS_HEIGHT : 0)\n : 0),\n }}\n >\n <div\n key={`content-${currentIndex}`}\n className={`${isActive && !isVideoSlide ? \"pointer-events-auto\" : \"pointer-events-none\"} flex w-full flex-col gap-3 ${horizontalClass}`}\n style={{\n maxWidth: textWidth,\n animation: isActive\n ? \"fluidCarouselTextRise 450ms ease-out both\"\n : undefined,\n animationDelay: isActive ? \"120ms\" : undefined,\n }}\n >\n {(slide.eyebrow || slide.tag || slide.meta) && (\n <div\n className={`flex flex-wrap items-center gap-2 ${\n align.horizontal === \"center\"\n ? \"justify-center\"\n : align.horizontal === \"right\"\n ? \"justify-end\"\n : \"justify-start\"\n }`}\n >\n {slide.tag && (\n <span\n className={`rounded-full bg-${slide.tagColor ?? \"background\"} text-${slide.tagColor ?? \"background\"}-foreground px-2.5 py-1 text-[10px] font-bold tracking-[0.14em] uppercase`}\n style={\n slide.tagColor === \"background\" ||\n slide.tagColor === \"foreground\" ||\n !slide.tagColor\n ? tagFallbackStyle(slide.tagColor, frameColor)\n : undefined\n }\n >\n {slide.tag}\n </span>\n )}\n {slide.eyebrow && (\n <span\n className={`text-${headerColor}/70 text-[10px] font-bold tracking-[0.16em] uppercase`}\n >\n {slide.eyebrow}\n </span>\n )}\n {slide.meta && (\n <span\n className={`text-${headerColor}/60 text-[10px] font-bold tracking-[0.16em] uppercase`}\n >\n {slide.meta}\n </span>\n )}\n </div>\n )}\n\n {slide.title && (\n <h2\n className={`text-${headerColor} font-bold ${HEADER_SIZE_MAP[headerSize]} leading-[1.12] tracking-[-0.018em]`}\n >\n {slide.title}\n </h2>\n )}\n\n {slide.description && (\n // Description supports inline HTML for emphasis / line\n // breaks / lists. Sanitized via DOMPurify with the same\n // allowlist as the previous implementation so saved\n // slides containing <strong>, <em>, <br>, <ul>, etc.\n // continue rendering as authored. Element is a <div>\n // (not <p>) to permit block-level allowed tags.\n <div\n className={`text-${textColor}/70 ${BODY_SIZE_MAP[textSize]} leading-[1.55]`}\n dangerouslySetInnerHTML={{\n __html: DOMPurify.sanitize(slide.description, {\n ALLOWED_TAGS: [\n \"br\",\n \"strong\",\n \"em\",\n \"b\",\n \"i\",\n \"ul\",\n \"ol\",\n \"li\",\n \"p\",\n ],\n ALLOWED_ATTR: [],\n }),\n }}\n />\n )}\n\n {(() => {\n const showPrimary =\n slide.buttonEnabled &&\n showButton &&\n Boolean(slide.buttonText) &&\n Boolean(slide.buttonLink);\n const showSecondary =\n Boolean(slide.secondaryButtonText) &&\n Boolean(slide.secondaryButtonLink);\n if (!showPrimary && !showSecondary) return null;\n\n const primaryLink = resolveInternalLink(slide.buttonLink);\n const secondaryLink = resolveInternalLink(\n slide.secondaryButtonLink,\n );\n\n return (\n <div\n className={`mt-3 flex flex-wrap items-center gap-3 ${\n align.horizontal === \"center\"\n ? \"justify-center\"\n : align.horizontal === \"right\"\n ? \"justify-end\"\n : \"justify-start\"\n }`}\n >\n {showPrimary && (\n <a\n href={slide.buttonLink}\n onClick={(e) => {\n e.stopPropagation();\n primaryLink.followInternally(e);\n }}\n className={`inline-flex items-center gap-1.5 rounded-full bg-${buttonColor} text-${buttonColor}-foreground px-5 py-2.5 text-[13px] font-bold transition-transform hover:scale-[1.02] ${buttonSizeClass(buttonSize)}`}\n style={{\n boxShadow: `0 8px 22px -8px color-mix(in oklch, var(--color-foreground) 35%, transparent)`,\n }}\n >\n {slide.buttonText}\n <span aria-hidden=\"true\" className=\"text-[14px]\">\n →\n </span>\n </a>\n )}\n {showSecondary && (\n <a\n href={slide.secondaryButtonLink}\n onClick={(e) => {\n e.stopPropagation();\n secondaryLink.followInternally(e);\n }}\n className={`inline-flex items-center gap-1 text-${headerColor}/80 hover:text-${headerColor} text-[12px] font-bold transition-colors`}\n >\n {slide.secondaryButtonText}\n <span aria-hidden=\"true\">→</span>\n </a>\n )}\n </div>\n );\n })()}\n </div>\n </div>\n </div>\n );\n })}\n\n {totalSlides > 1 && (\n <div className=\"pointer-events-none absolute inset-0 z-20\">\n <div className=\"pointer-events-auto absolute top-6 right-6 flex items-center gap-1.5\">\n <button\n type=\"button\"\n onClick={goToPrevious}\n aria-label=\"Previous slide\"\n className={`flex size-10 items-center justify-center rounded-full bg-${headerColor}/10 text-${headerColor} ring-1 ring-${headerColor}/15 backdrop-blur-sm transition-colors hover:bg-${headerColor}/20`}\n >\n <ChevronLeftIcon />\n </button>\n <button\n type=\"button\"\n onClick={goToNext}\n aria-label=\"Next slide\"\n className={`flex size-10 items-center justify-center rounded-full bg-${headerColor} text-${headerColor}-foreground transition-transform hover:scale-[1.04]`}\n style={{\n // Themed lift shadow (was hardcoded white) so the active\n // nav button reads on both light and dark frames.\n boxShadow: `0 4px 14px -4px color-mix(in oklch, var(--color-${headerColor}) 45%, transparent)`,\n ...nextButtonFallbackStyle(headerColor, frameColor),\n }}\n >\n <ChevronRightIcon />\n </button>\n </div>\n\n <div\n className={`pointer-events-auto absolute inset-x-0 flex items-center gap-1 px-6 pb-2 sm:px-10`}\n style={{\n bottom: isActiveSlideVideo ? VIDEO_CONTROLS_HEIGHT : 0,\n transition: \"bottom 200ms ease-out\",\n }}\n >\n {slides.map((_, i) => {\n const state =\n i < currentIndex\n ? \"done\"\n : i === currentIndex\n ? \"active\"\n : \"upcoming\";\n return (\n <button\n key={`progress-${i}`}\n type=\"button\"\n onClick={() => goToSlide(i)}\n aria-label={`Go to slide ${i + 1}`}\n aria-current={state === \"active\" ? \"true\" : \"false\"}\n className=\"group flex-1 py-2\"\n >\n <span\n className={`block h-[2px] w-full overflow-hidden rounded-full bg-${headerColor}/20`}\n >\n <span\n key={`fill-${i}-${currentIndex}`}\n className={`block h-full rounded-full bg-${headerColor}`}\n style={progressFillStyle(\n state,\n enableAutoScroll,\n autoScrollInterval,\n isPaused,\n )}\n />\n </span>\n </button>\n );\n })}\n </div>\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction progressFillStyle(\n state: \"done\" | \"active\" | \"upcoming\",\n autoScroll: boolean,\n duration: number,\n paused: boolean,\n): CSSProperties {\n if (state === \"upcoming\") return { width: \"0%\" };\n if (!autoScroll) {\n // Nothing is counting down, so only the current bar fills. Otherwise the\n // last slide has every bar full and you can't tell which one you're on.\n return { width: state === \"active\" ? \"100%\" : \"0%\" };\n }\n if (state === \"done\") return { width: \"100%\" };\n return {\n width: \"0%\",\n animation: `fluidCarouselProgressFill ${duration}ms linear forwards`,\n animationPlayState: paused ? \"paused\" : \"running\",\n };\n}\n\nfunction tagFallbackStyle(\n tagColor: ColorOptions | undefined,\n frameColor: ColorOptions,\n): CSSProperties | undefined {\n // bg-background/foreground don't emit -foreground utilities by default;\n // fall back to contrast-safe inline colors so tag chips always read.\n if (!tagColor || tagColor === \"background\") {\n return { color: `var(--color-${frameColor})` };\n }\n if (tagColor === \"foreground\") {\n return { color: `var(--color-background)` };\n }\n return undefined;\n}\n\nfunction nextButtonFallbackStyle(\n headerColor: ColorOptions,\n frameColor: ColorOptions,\n): CSSProperties | undefined {\n // Same contrast fix as tags — ensure icon color reads on the active button.\n if (headerColor === \"background\") {\n return { color: `var(--color-${frameColor})` };\n }\n if (headerColor === \"foreground\") {\n return { color: `var(--color-background)` };\n }\n return undefined;\n}\n\nfunction buttonSizeClass(size: ButtonSizeOptions): string {\n if (size === \"sm\") return \"px-4 py-1.5 text-[12px]\";\n if (size === \"lg\") return \"px-6 py-3 text-[14px]\";\n if (size === \"xl\") return \"px-7 py-3.5 text-[15px]\";\n return \"\";\n}\n\nfunction ChevronLeftIcon() {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M15 18l-6-6 6-6\" />\n </svg>\n );\n}\n\nfunction ChevronRightIcon() {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M9 18l6-6-6-6\" />\n </svg>\n );\n}\n\nexport const carouselWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"CarouselWidget\",\n displayName: \"Carousel\",\n tabsConfig: [\n { id: \"styling\", label: \"Styling\" },\n { id: \"behavior\", label: \"Behavior\" },\n { id: \"data\", label: \"Data\" },\n ],\n dataSourceTargetProps: [\"slides\"],\n fields: [\n // Styling tab — Frame group (new)\n {\n key: \"editorialFrame\",\n label: \"Editorial Frame\",\n type: \"boolean\",\n description:\n \"Premium dark canvas with layered shadow and gradient stack. Turn off for a classic transparent carousel.\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Frame\",\n },\n getColorField({\n defaultValue: \"foreground\",\n key: \"frameColor\",\n label: \"Frame Color\",\n description:\n \"Surface color of the carousel canvas. Drives the frame and gradient overlay.\",\n tab: \"styling\",\n group: \"Frame\",\n requiresKeyToBeTrue: \"editorialFrame\",\n }),\n\n // Text Styling group\n getFontSizeField({\n defaultValue: \"xl\",\n key: \"headerSize\",\n label: \"Header Font Size\",\n description: \"Font size for the slide header\",\n tab: \"styling\",\n group: \"Text Styling\",\n }),\n getColorField({\n defaultValue: \"background\",\n key: \"headerColor\",\n label: \"Header Color\",\n description:\n \"Headline color. Also drives eyebrow, controls and progress bar.\",\n tab: \"styling\",\n group: \"Text Styling\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Text Styling\",\n },\n getFontSizeField({\n defaultValue: \"md\",\n key: \"textSize\",\n label: \"Text Font Size\",\n description: \"Font size for the slide text\",\n tab: \"styling\",\n group: \"Text Styling\",\n }),\n getColorField({\n defaultValue: \"background\",\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Color variant for the slide text\",\n tab: \"styling\",\n group: \"Text Styling\",\n }),\n\n // Layout group\n {\n key: \"align\",\n label: \"Alignment\",\n type: \"alignment\",\n description: \"Alignment of the carousel content\",\n defaultValue: { vertical: \"bottom\", horizontal: \"left\" },\n options: {\n verticalEnabled: true,\n horizontalEnabled: true,\n },\n tab: \"styling\",\n group: \"Layout\",\n },\n {\n key: \"textWidth\",\n label: \"Content Width\",\n type: \"cssUnit\",\n description: \"Maximum width for slide content\",\n defaultValue: \"620px\",\n allowedUnits: [\"px\", \"rem\", \"%\"],\n defaultUnit: \"px\",\n minByUnit: { px: 50, rem: 3, \"%\": 10 },\n maxByUnit: { px: 1200, rem: 75, \"%\": 100 },\n stepByUnit: { px: 10, rem: 1, \"%\": 1 },\n tab: \"styling\",\n group: \"Layout\",\n },\n\n // Design group\n getHeightField({\n key: \"carouselHeight\",\n label: \"Carousel Height\",\n description: \"Height of the carousel\",\n defaultValue: \"400px\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"separator2\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n getBorderRadiusField({\n defaultValue: \"xl\",\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Rounded corners for the carousel\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the carousel container\",\n defaultValue: \"none\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Border color for the carousel container\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getPaddingField({\n defaultValue: 8,\n key: \"padding\",\n label: \"Padding\",\n description: \"Inner padding around slide content\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"overlayEnabled\",\n label: \"Enable Overlay\",\n type: \"boolean\",\n description: \"Add background overlay to slide content\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"overlayType\",\n label: \"Overlay Type\",\n type: \"buttonGroup\",\n description: \"Overlay style (only applies when editorial frame is off)\",\n defaultValue: \"gradient\",\n options: [\n { label: \"Solid\", value: \"solid\" },\n { label: \"Gradient\", value: \"gradient\" },\n ],\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"overlayIntensity\",\n label: \"Overlay Intensity\",\n type: \"slider\",\n description: \"Opacity of the overlay (0-100)\",\n min: 0,\n max: 100,\n step: 5,\n defaultValue: 70,\n unit: \"%\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"showButton\",\n label: \"Show Primary Button\",\n type: \"boolean\",\n description:\n \"Global show/hide for all slide CTAs. Per-slide button content is set on each item under the Data tab (custom sources only).\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n getColorField({\n defaultValue: \"background\",\n key: \"buttonColor\",\n label: \"Button Color\",\n description: \"Color variant for the slide button\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"showButton\",\n }),\n getButtonSizeField({\n defaultValue: \"default\",\n key: \"buttonSize\",\n label: \"Button Size\",\n description: \"Size of the slide button\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"showButton\",\n }),\n\n // Behavior tab\n {\n key: \"enableAutoScroll\",\n label: \"Enable Auto-Scroll\",\n type: \"boolean\",\n description:\n \"Automatically advance to the next slide. Progress bar fills at this rate and pauses on hover.\",\n defaultValue: false,\n tab: \"behavior\",\n group: \"Auto-Scroll\",\n },\n {\n key: \"autoScrollInterval\",\n label: \"Auto-Scroll Interval (ms)\",\n type: \"number\",\n description: \"Time between automatic slide transitions\",\n min: 1000,\n max: 15000,\n step: 500,\n defaultValue: 6500,\n tab: \"behavior\",\n group: \"Auto-Scroll\",\n requiresKeyToBeTrue: \"enableAutoScroll\",\n },\n\n // Data tab\n {\n key: \"dataSource\",\n label: \"Data Source\",\n type: \"dataSource\",\n description: \"Configure the slides rendered by the carousel.\",\n targetProps: [\n {\n key: \"slides\",\n description:\n \"Slides rendered by the carousel, usually supplied by a data source.\",\n },\n ],\n tab: \"data\",\n group: \"Data Configuration\",\n },\n ],\n itemConfigSchema: {\n description: \"Configure settings for this slide\",\n fields: [\n {\n key: \"eyebrow\",\n label: \"Eyebrow\",\n type: \"text\",\n description:\n \"Short label above the title (e.g. 'From Fluid · Newsroom')\",\n },\n {\n key: \"tag\",\n label: \"Tag / Category\",\n type: \"text\",\n description: \"Short pill label (e.g. 'Policy', 'New release')\",\n },\n {\n key: \"tagColor\",\n label: \"Tag Color\",\n type: \"colorSelect\",\n description: \"Background color of the tag pill\",\n defaultValue: \"background\",\n },\n {\n key: \"meta\",\n label: \"Meta\",\n type: \"text\",\n description: \"Meta line (e.g. 'Apr 12 · 4 min read')\",\n },\n {\n key: \"separator_slide_1\",\n type: \"separator\",\n label: \"Separator\",\n },\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"Override the item's title for this slide\",\n },\n {\n key: \"description\",\n label: \"Description\",\n type: \"textarea\",\n description: \"Override the item's description for this slide\",\n rows: 3,\n },\n {\n key: \"separator_slide_2\",\n type: \"separator\",\n label: \"Separator\",\n },\n {\n key: \"buttonEnabled\",\n label: \"Show Primary Button\",\n type: \"boolean\",\n description: \"Show the primary CTA on this slide\",\n defaultValue: false,\n },\n {\n key: \"buttonText\",\n label: \"Button Text\",\n type: \"text\",\n description: \"Text for the primary button\",\n requiresKeyToBeTrue: \"buttonEnabled\",\n },\n {\n key: \"buttonLink\",\n label: \"Button Link\",\n type: \"text\",\n description: \"URL for the primary button\",\n requiresKeyToBeTrue: \"buttonEnabled\",\n },\n {\n key: \"secondaryButtonText\",\n label: \"Secondary Link Text\",\n type: \"text\",\n description:\n \"Optional text-only secondary link (renders with an arrow)\",\n },\n {\n key: \"secondaryButtonLink\",\n label: \"Secondary Link URL\",\n type: \"text\",\n description: \"URL for the secondary link\",\n },\n { key: \"separator_link\", type: \"separator\", label: \"Separator\" },\n ...getLinkTypeFields(),\n ],\n },\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACDN,mBAAAA,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EACFO,mBAAAA,mBAAmB;GACjB,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EAGF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EAGD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,aAAa,CACX;IACE,KAAK;IACL,aACE;IACH,CACF;GACD,KAAK;GACL,OAAO;GACR;EACF;CACD,kBAAkB;EAChB,aAAa;EACb,QAAQ;GACN;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aACE;IACH;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACd;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACb,cAAc;IACf;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACd;GACD;IACE,KAAK;IACL,MAAM;IACN,OAAO;IACR;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACd;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACb,MAAM;IACP;GACD;IACE,KAAK;IACL,MAAM;IACN,OAAO;IACR;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACb,cAAc;IACf;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACb,qBAAqB;IACtB;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACb,qBAAqB;IACtB;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aACE;IACH;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACd;GACD;IAAE,KAAK;IAAkB,MAAM;IAAa,OAAO;IAAa;GAChE,GAAGC,gCAAAA,mBAAmB;GACvB;EACF;CACF"}
|
|
1
|
+
{"version":3,"file":"CarouselWidget-BETNqs_K.cjs","names":["useWidgetInteraction","useInternalLinks","useRepUser","useWidgetRenderState","borderWidthClasses","borderColorClasses","buildItemInteractionProps","MediaRenderer","getMediaPropsFromWidgetSchema","DOMPurify","getColorField","getFontSizeField","getHeightField","getBorderRadiusField","getBorderWidthField","getBorderColorField","getPaddingField","getButtonSizeField","getLinkTypeFields"],"sources":["../../widgets/src/widgets/CarouselWidget.tsx"],"sourcesContent":["import type { ComponentProps, CSSProperties } from \"react\";\nimport type React from \"react\";\nimport { useEffect, useState, useCallback } from \"react\";\nimport DOMPurify from \"dompurify\";\nimport {\n MediaRenderer,\n getMediaPropsFromWidgetSchema,\n} from \"../components/MediaRenderer\";\nimport type {\n WidgetSchema,\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n AlignOptions,\n FontSizeOptions,\n PaddingOptions,\n ButtonSizeOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n borderColorClasses,\n borderWidthClasses,\n getBorderColorField,\n getBorderRadiusField,\n getBorderWidthField,\n getButtonSizeField,\n getColorField,\n getFontSizeField,\n getHeightField,\n getPaddingField,\n} from \"../core/fields\";\nimport { useWidgetInteraction } from \"../contexts/WidgetInteractionContext\";\nimport { useRepUser } from \"../contexts/RepUserContext\";\nimport { useWidgetRenderState } from \"../contexts/WidgetRenderStateContext\";\nimport { useInternalLinks } from \"../hooks/use-internal-link\";\nimport { buildItemInteractionProps } from \"./list-widget/helpers\";\nimport { getLinkTypeFields } from \"../lib/link-type-schema-fields\";\n\ntype CarouselSlide = {\n id: string;\n content: WidgetSchema;\n title?: string;\n description?: string;\n // Editorial additions (all optional — existing configs keep working)\n eyebrow?: string;\n meta?: string;\n tag?: string;\n tagColor?: ColorOptions;\n buttonEnabled?: boolean;\n buttonText?: string;\n buttonVariant?:\n | \"default\"\n | \"secondary\"\n | \"outline\"\n | \"destructive\"\n | \"ghost\"\n | \"link\";\n buttonLink?: string;\n secondaryButtonText?: string;\n secondaryButtonLink?: string;\n // Index signature lets data-source-driven slides carry extra fields\n // (e.g. shareable_type, subscription_token) through to onItemClick,\n // which routes based on them — matches ListWidget's ListItem shape.\n [key: string]: unknown;\n};\n\ntype CarouselWidgetProps = ComponentProps<\"div\"> & {\n slides?: CarouselSlide[];\n autoScrollInterval?: number;\n enableAutoScroll?: boolean;\n\n // Layout\n align?: AlignOptions;\n // CSS-unit string (\"400px\", \"30rem\", \"50%\") — kept as string so saved\n // configs from the previous schema continue to render. The schema field\n // is `cssUnit` (via getHeightField), which produces a string with the\n // unit baked in.\n carouselHeight?: string;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n padding?: PaddingOptions;\n\n // Text Styling\n headerSize?: FontSizeOptions;\n headerColor?: ColorOptions;\n textSize?: FontSizeOptions;\n textColor?: ColorOptions;\n textWidth?: string;\n\n // Button\n showButton?: boolean;\n buttonColor?: ColorOptions;\n buttonSize?: ButtonSizeOptions;\n\n // Overlay\n overlayEnabled?: boolean;\n overlayType?: \"solid\" | \"gradient\";\n overlayIntensity?: number;\n\n // Editorial frame (new — opt-out via `editorialFrame={false}`)\n editorialFrame?: boolean;\n frameColor?: ColorOptions;\n};\n\nconst VIDEO_CONTROLS_HEIGHT = 44;\n\nconst HEADER_SIZE_MAP: Record<FontSizeOptions, string> = {\n xs: \"text-base sm:text-lg\",\n sm: \"text-lg sm:text-xl\",\n md: \"text-xl sm:text-2xl\",\n lg: \"text-2xl sm:text-3xl\",\n xl: \"text-3xl sm:text-[32px]\",\n \"2xl\": \"text-[32px] sm:text-[40px]\",\n};\n\nconst BODY_SIZE_MAP: Record<FontSizeOptions, string> = {\n xs: \"text-[12px]\",\n sm: \"text-[13px]\",\n md: \"text-[14px]\",\n lg: \"text-[15px]\",\n xl: \"text-[16px]\",\n \"2xl\": \"text-[18px]\",\n};\n\nfunction useCarouselController({\n slideCount,\n enableAutoScroll,\n autoScrollInterval,\n}: {\n slideCount: number;\n enableAutoScroll: boolean;\n autoScrollInterval: number;\n}) {\n const [currentIndex, setCurrentIndex] = useState(0);\n // Track hover and keyboard focus separately — combining them in one boolean\n // would let `onMouseLeave` clear the paused state even while a child button\n // still has focus.\n const [isHovered, setIsHovered] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n const hasSlides = slideCount > 0;\n const isPaused = isHovered || isFocused;\n\n const goToNext = useCallback(() => {\n if (!hasSlides) return;\n setCurrentIndex((prev) => (prev === slideCount - 1 ? 0 : prev + 1));\n }, [hasSlides, slideCount]);\n\n const goToPrevious = useCallback(() => {\n if (!hasSlides) return;\n setCurrentIndex((prev) => (prev === 0 ? slideCount - 1 : prev - 1));\n }, [hasSlides, slideCount]);\n\n const goToSlide = useCallback(\n (index: number) => {\n if (!hasSlides) return;\n if (index >= 0 && index < slideCount) {\n setCurrentIndex(index);\n }\n },\n [hasSlides, slideCount],\n );\n\n useEffect(() => {\n if (!enableAutoScroll || !hasSlides || isPaused) return;\n const intervalId = setInterval(goToNext, autoScrollInterval);\n return () => clearInterval(intervalId);\n }, [enableAutoScroll, autoScrollInterval, hasSlides, isPaused, goToNext]);\n\n useEffect(() => {\n if (currentIndex >= slideCount && slideCount > 0) {\n setCurrentIndex(0);\n }\n }, [slideCount, currentIndex]);\n\n // Pause for a mouse or the keyboard, never for a touch. On iOS a tap fires\n // mouseenter with no mouseleave after it, and it focuses the button too, so\n // either one would leave the carousel stuck paused.\n const handlePointerEnter = useCallback((e: React.PointerEvent) => {\n if (e.pointerType === \"mouse\") setIsHovered(true);\n }, []);\n const handlePointerLeave = useCallback((e: React.PointerEvent) => {\n if (e.pointerType === \"mouse\") setIsHovered(false);\n }, []);\n const handleFocus = useCallback((e: React.FocusEvent<HTMLElement>) => {\n // Set it either way, or a click inside leaves it paused.\n setIsFocused(\n e.target instanceof Element && e.target.matches(\":focus-visible\"),\n );\n }, []);\n const handleBlur = useCallback((e: React.FocusEvent<HTMLElement>) => {\n // Only flip to unfocused when focus actually leaves the carousel.\n // When focus moves between two children (e.g. tabbing from prev to next\n // button), `relatedTarget` is the new focus target and is still contained.\n if (!e.currentTarget.contains(e.relatedTarget as Node | null)) {\n setIsFocused(false);\n }\n }, []);\n\n return {\n currentIndex,\n hasSlides,\n isPaused,\n goToNext,\n goToPrevious,\n goToSlide,\n handlePointerEnter,\n handlePointerLeave,\n handleFocus,\n handleBlur,\n };\n}\n\nexport function CarouselWidget({\n slides = [],\n autoScrollInterval = 6500,\n enableAutoScroll = false,\n carouselHeight = \"400px\",\n align = { vertical: \"bottom\", horizontal: \"left\" },\n overlayIntensity = 70,\n borderRadius = \"xl\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n padding = 8,\n textWidth = \"620px\",\n headerSize = \"xl\",\n headerColor = \"background\",\n textSize = \"md\",\n textColor = \"background\",\n showButton = true,\n buttonColor = \"background\",\n buttonSize = \"default\",\n overlayEnabled = true,\n overlayType = \"gradient\",\n editorialFrame = true,\n frameColor = \"foreground\",\n className,\n ...props\n}: CarouselWidgetProps): React.JSX.Element {\n const totalSlides = slides.length;\n const {\n currentIndex,\n hasSlides,\n isPaused,\n goToNext,\n goToPrevious,\n goToSlide,\n handlePointerEnter,\n handlePointerLeave,\n handleFocus,\n handleBlur,\n } = useCarouselController({\n slideCount: totalSlides,\n enableAutoScroll,\n autoScrollInterval,\n });\n const { onItemClick, onNavigate, buildHref, resolveInternalSlug } =\n useWidgetInteraction();\n const resolveInternalLink = useInternalLinks();\n const publicId = useRepUser()?.publicId;\n const { editMode } = useWidgetRenderState();\n const verticalClass =\n align.vertical === \"top\"\n ? \"items-start\"\n : align.vertical === \"center\"\n ? \"items-center\"\n : \"items-end\";\n\n const horizontalClass =\n align.horizontal === \"center\"\n ? \"justify-center text-center mx-auto\"\n : align.horizontal === \"right\"\n ? \"justify-end ml-auto text-right\"\n : \"justify-start text-left\";\n\n // Themed dual-shadow (crisp + soft ambient) on the editorial frame —\n // derived from the foreground token so the lift reads in both light\n // and dark themes.\n const frameShadowStyle: CSSProperties | undefined = editorialFrame\n ? {\n boxShadow: `0 1px 2px color-mix(in oklch, var(--color-foreground) 4%, transparent), 0 30px 60px -30px color-mix(in oklch, var(--color-foreground) 40%, transparent)`,\n }\n : undefined;\n\n const frameBg = editorialFrame ? `bg-${frameColor}` : \"\";\n const isActiveSlideVideo =\n slides[currentIndex]?.content.type === \"VideoWidget\";\n\n if (!hasSlides) {\n return (\n <div\n className={`relative w-full overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${frameBg} ${className ?? \"\"}`}\n style={{ minHeight: carouselHeight, ...frameShadowStyle }}\n {...props}\n >\n <div\n className=\"bg-muted/20 flex h-full w-full items-center justify-center\"\n style={{ minHeight: carouselHeight }}\n >\n <div className=\"text-muted-foreground flex flex-col items-center gap-2\">\n <div className=\"text-4xl\">🎠</div>\n <p className=\"text-sm\">No slides added</p>\n <p className=\"text-muted-foreground/70 text-xs\">\n Add slides to create a carousel\n </p>\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div\n className={`relative isolate w-full overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${frameBg} ${className ?? \"\"}`}\n style={{ minHeight: carouselHeight, ...frameShadowStyle }}\n onPointerEnter={handlePointerEnter}\n onPointerLeave={handlePointerLeave}\n onFocus={handleFocus}\n onBlur={handleBlur}\n {...props}\n >\n <div\n className=\"relative w-full\"\n style={{\n minHeight: carouselHeight,\n height: carouselHeight,\n }}\n >\n {slides.map((slide, index) => {\n const isActive = index === currentIndex;\n const isVideoSlide = slide.content.type === \"VideoWidget\";\n // Strip the optional \"%\" suffix, then parse. Use Number.isFinite +\n // clamp so an explicit 0 isn't silently replaced by the 70 fallback\n // (the previous `|| 70` treated 0 as falsy).\n const parsedOverlayIntensity = Number(\n String(overlayIntensity).replace(\"%\", \"\"),\n );\n const overlayOpacity =\n (Number.isFinite(parsedOverlayIntensity)\n ? Math.min(100, Math.max(0, parsedOverlayIntensity))\n : 70) / 100;\n\n // Slide-level tap: if the slide has an explicit linkType from\n // itemConfigSchema, use it; otherwise fall back to onItemClick\n // (which routes based on shareable_type, subscription_token, etc.).\n const slideLinkProps =\n isActive && !isVideoSlide\n ? buildItemInteractionProps(slide, {\n onItemClick,\n onNavigate,\n buildHref,\n resolveInternalSlug,\n publicId,\n editMode,\n })\n : {};\n const isInteractive = Object.keys(slideLinkProps).length > 0;\n\n return (\n <div\n key={slide.id}\n className={`absolute inset-0 transition-opacity duration-700 ease-out${isInteractive ? \" cursor-pointer focus-visible:ring-2 focus-visible:ring-white/60 focus-visible:outline-none focus-visible:ring-inset\" : \"\"}`}\n style={{\n opacity: isActive ? 1 : 0,\n pointerEvents: isActive ? \"auto\" : \"none\",\n }}\n aria-hidden={!isActive}\n {...slideLinkProps}\n >\n {isVideoSlide ? (\n <div className=\"absolute inset-0 h-full w-full\">\n {isActive && (\n <MediaRenderer\n {...getMediaPropsFromWidgetSchema(slide.content)}\n />\n )}\n </div>\n ) : (\n <>\n <div\n className=\"absolute inset-0 h-full w-full\"\n style={{\n transform: isActive ? \"scale(1)\" : \"scale(1.04)\",\n animation: isActive\n ? \"fluidCarouselKenBurns 900ms ease-out both\"\n : undefined,\n }}\n >\n <MediaRenderer\n {...getMediaPropsFromWidgetSchema(slide.content)}\n />\n </div>\n\n {overlayEnabled && editorialFrame && (\n <>\n <div\n className={`pointer-events-none absolute inset-0 bg-gradient-to-t from-${frameColor} via-${frameColor}/65 to-${frameColor}/10`}\n style={{ opacity: overlayOpacity }}\n />\n <div\n className={`pointer-events-none absolute inset-0 bg-gradient-to-r from-${frameColor}/80 via-transparent to-transparent`}\n style={{ opacity: Math.min(1, overlayOpacity + 0.1) }}\n />\n </>\n )}\n\n {overlayEnabled && !editorialFrame && (\n <div\n className={`pointer-events-none absolute inset-0 ${\n overlayType === \"gradient\"\n ? \"bg-gradient-to-t from-black to-transparent\"\n : \"bg-black\"\n }`}\n style={{ opacity: overlayOpacity }}\n />\n )}\n </>\n )}\n\n <div\n className={`pointer-events-none absolute inset-0 flex px-6 sm:px-10 ${verticalClass} ${\n align.horizontal === \"center\"\n ? \"justify-center\"\n : align.horizontal === \"right\"\n ? \"justify-end\"\n : \"justify-start\"\n }`}\n style={{\n paddingTop: padding * 4,\n paddingBottom:\n padding * 4 +\n (totalSlides > 1\n ? 24 + (isVideoSlide ? VIDEO_CONTROLS_HEIGHT : 0)\n : 0),\n }}\n >\n <div\n key={`content-${currentIndex}`}\n className={`${isActive && !isVideoSlide ? \"pointer-events-auto\" : \"pointer-events-none\"} flex w-full flex-col gap-3 ${horizontalClass}`}\n style={{\n maxWidth: textWidth,\n animation: isActive\n ? \"fluidCarouselTextRise 450ms ease-out both\"\n : undefined,\n animationDelay: isActive ? \"120ms\" : undefined,\n }}\n >\n {(slide.eyebrow || slide.tag || slide.meta) && (\n <div\n className={`flex flex-wrap items-center gap-2 ${\n align.horizontal === \"center\"\n ? \"justify-center\"\n : align.horizontal === \"right\"\n ? \"justify-end\"\n : \"justify-start\"\n }`}\n >\n {slide.tag && (\n <span\n className={`rounded-full bg-${slide.tagColor ?? \"background\"} text-${slide.tagColor ?? \"background\"}-foreground px-2.5 py-1 text-[10px] font-bold tracking-[0.14em] uppercase`}\n style={\n slide.tagColor === \"background\" ||\n slide.tagColor === \"foreground\" ||\n !slide.tagColor\n ? tagFallbackStyle(slide.tagColor, frameColor)\n : undefined\n }\n >\n {slide.tag}\n </span>\n )}\n {slide.eyebrow && (\n <span\n className={`text-${headerColor}/70 text-[10px] font-bold tracking-[0.16em] uppercase`}\n >\n {slide.eyebrow}\n </span>\n )}\n {slide.meta && (\n <span\n className={`text-${headerColor}/60 text-[10px] font-bold tracking-[0.16em] uppercase`}\n >\n {slide.meta}\n </span>\n )}\n </div>\n )}\n\n {slide.title && (\n <h2\n className={`text-${headerColor} font-bold ${HEADER_SIZE_MAP[headerSize]} leading-[1.12] tracking-[-0.018em]`}\n >\n {slide.title}\n </h2>\n )}\n\n {slide.description && (\n // Description supports inline HTML for emphasis / line\n // breaks / lists. Sanitized via DOMPurify with the same\n // allowlist as the previous implementation so saved\n // slides containing <strong>, <em>, <br>, <ul>, etc.\n // continue rendering as authored. Element is a <div>\n // (not <p>) to permit block-level allowed tags.\n <div\n className={`text-${textColor}/70 ${BODY_SIZE_MAP[textSize]} leading-[1.55]`}\n dangerouslySetInnerHTML={{\n __html: DOMPurify.sanitize(slide.description, {\n ALLOWED_TAGS: [\n \"br\",\n \"strong\",\n \"em\",\n \"b\",\n \"i\",\n \"ul\",\n \"ol\",\n \"li\",\n \"p\",\n ],\n ALLOWED_ATTR: [],\n }),\n }}\n />\n )}\n\n {(() => {\n const showPrimary =\n slide.buttonEnabled &&\n showButton &&\n Boolean(slide.buttonText) &&\n Boolean(slide.buttonLink);\n const showSecondary =\n Boolean(slide.secondaryButtonText) &&\n Boolean(slide.secondaryButtonLink);\n if (!showPrimary && !showSecondary) return null;\n\n const primaryLink = resolveInternalLink(slide.buttonLink);\n const secondaryLink = resolveInternalLink(\n slide.secondaryButtonLink,\n );\n\n return (\n <div\n className={`mt-3 flex flex-wrap items-center gap-3 ${\n align.horizontal === \"center\"\n ? \"justify-center\"\n : align.horizontal === \"right\"\n ? \"justify-end\"\n : \"justify-start\"\n }`}\n >\n {showPrimary && (\n <a\n href={slide.buttonLink}\n onClick={(e) => {\n e.stopPropagation();\n primaryLink.followInternally(e);\n }}\n className={`inline-flex items-center gap-1.5 rounded-full bg-${buttonColor} text-${buttonColor}-foreground px-5 py-2.5 text-[13px] font-bold transition-transform hover:scale-[1.02] ${buttonSizeClass(buttonSize)}`}\n style={{\n boxShadow: `0 8px 22px -8px color-mix(in oklch, var(--color-foreground) 35%, transparent)`,\n }}\n >\n {slide.buttonText}\n <span aria-hidden=\"true\" className=\"text-[14px]\">\n →\n </span>\n </a>\n )}\n {showSecondary && (\n <a\n href={slide.secondaryButtonLink}\n onClick={(e) => {\n e.stopPropagation();\n secondaryLink.followInternally(e);\n }}\n className={`inline-flex items-center gap-1 text-${headerColor}/80 hover:text-${headerColor} text-[12px] font-bold transition-colors`}\n >\n {slide.secondaryButtonText}\n <span aria-hidden=\"true\">→</span>\n </a>\n )}\n </div>\n );\n })()}\n </div>\n </div>\n </div>\n );\n })}\n\n {totalSlides > 1 && (\n <div className=\"pointer-events-none absolute inset-0 z-20\">\n <div className=\"pointer-events-auto absolute top-6 right-6 flex items-center gap-1.5\">\n <button\n type=\"button\"\n onClick={goToPrevious}\n aria-label=\"Previous slide\"\n className={`flex size-10 items-center justify-center rounded-full bg-${headerColor}/10 text-${headerColor} ring-1 ring-${headerColor}/15 backdrop-blur-sm transition-colors hover:bg-${headerColor}/20`}\n >\n <ChevronLeftIcon />\n </button>\n <button\n type=\"button\"\n onClick={goToNext}\n aria-label=\"Next slide\"\n className={`flex size-10 items-center justify-center rounded-full bg-${headerColor} text-${headerColor}-foreground transition-transform hover:scale-[1.04]`}\n style={{\n // Themed lift shadow (was hardcoded white) so the active\n // nav button reads on both light and dark frames.\n boxShadow: `0 4px 14px -4px color-mix(in oklch, var(--color-${headerColor}) 45%, transparent)`,\n ...nextButtonFallbackStyle(headerColor, frameColor),\n }}\n >\n <ChevronRightIcon />\n </button>\n </div>\n\n <div\n className={`pointer-events-auto absolute inset-x-0 flex items-center gap-1 px-6 pb-2 sm:px-10`}\n style={{\n bottom: isActiveSlideVideo ? VIDEO_CONTROLS_HEIGHT : 0,\n transition: \"bottom 200ms ease-out\",\n }}\n >\n {slides.map((_, i) => {\n const state =\n i < currentIndex\n ? \"done\"\n : i === currentIndex\n ? \"active\"\n : \"upcoming\";\n return (\n <button\n key={`progress-${i}`}\n type=\"button\"\n onClick={() => goToSlide(i)}\n aria-label={`Go to slide ${i + 1}`}\n aria-current={state === \"active\" ? \"true\" : \"false\"}\n className=\"group flex-1 py-2\"\n >\n <span\n className={`block h-[2px] w-full overflow-hidden rounded-full bg-${headerColor}/20`}\n >\n <span\n key={`fill-${i}-${currentIndex}`}\n className={`block h-full rounded-full bg-${headerColor}`}\n style={progressFillStyle(\n state,\n enableAutoScroll,\n autoScrollInterval,\n isPaused,\n )}\n />\n </span>\n </button>\n );\n })}\n </div>\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction progressFillStyle(\n state: \"done\" | \"active\" | \"upcoming\",\n autoScroll: boolean,\n duration: number,\n paused: boolean,\n): CSSProperties {\n if (state === \"upcoming\") return { width: \"0%\" };\n if (!autoScroll) {\n // Nothing is counting down, so only the current bar fills. Otherwise the\n // last slide has every bar full and you can't tell which one you're on.\n return { width: state === \"active\" ? \"100%\" : \"0%\" };\n }\n if (state === \"done\") return { width: \"100%\" };\n return {\n width: \"0%\",\n animation: `fluidCarouselProgressFill ${duration}ms linear forwards`,\n animationPlayState: paused ? \"paused\" : \"running\",\n };\n}\n\nfunction tagFallbackStyle(\n tagColor: ColorOptions | undefined,\n frameColor: ColorOptions,\n): CSSProperties | undefined {\n // bg-background/foreground don't emit -foreground utilities by default;\n // fall back to contrast-safe inline colors so tag chips always read.\n if (!tagColor || tagColor === \"background\") {\n return { color: `var(--color-${frameColor})` };\n }\n if (tagColor === \"foreground\") {\n return { color: `var(--color-background)` };\n }\n return undefined;\n}\n\nfunction nextButtonFallbackStyle(\n headerColor: ColorOptions,\n frameColor: ColorOptions,\n): CSSProperties | undefined {\n // Same contrast fix as tags — ensure icon color reads on the active button.\n if (headerColor === \"background\") {\n return { color: `var(--color-${frameColor})` };\n }\n if (headerColor === \"foreground\") {\n return { color: `var(--color-background)` };\n }\n return undefined;\n}\n\nfunction buttonSizeClass(size: ButtonSizeOptions): string {\n if (size === \"sm\") return \"px-4 py-1.5 text-[12px]\";\n if (size === \"lg\") return \"px-6 py-3 text-[14px]\";\n if (size === \"xl\") return \"px-7 py-3.5 text-[15px]\";\n return \"\";\n}\n\nfunction ChevronLeftIcon() {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M15 18l-6-6 6-6\" />\n </svg>\n );\n}\n\nfunction ChevronRightIcon() {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M9 18l6-6-6-6\" />\n </svg>\n );\n}\n\nexport const carouselWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"CarouselWidget\",\n displayName: \"Carousel\",\n tabsConfig: [\n { id: \"styling\", label: \"Styling\" },\n { id: \"behavior\", label: \"Behavior\" },\n { id: \"data\", label: \"Data\" },\n ],\n dataSourceTargetProps: [\"slides\"],\n fields: [\n // Styling tab — Frame group (new)\n {\n key: \"editorialFrame\",\n label: \"Editorial Frame\",\n type: \"boolean\",\n description:\n \"Premium dark canvas with layered shadow and gradient stack. Turn off for a classic transparent carousel.\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Frame\",\n },\n getColorField({\n defaultValue: \"foreground\",\n key: \"frameColor\",\n label: \"Frame Color\",\n description:\n \"Surface color of the carousel canvas. Drives the frame and gradient overlay.\",\n tab: \"styling\",\n group: \"Frame\",\n requiresKeyToBeTrue: \"editorialFrame\",\n }),\n\n // Text Styling group\n getFontSizeField({\n defaultValue: \"xl\",\n key: \"headerSize\",\n label: \"Header Font Size\",\n description: \"Font size for the slide header\",\n tab: \"styling\",\n group: \"Text Styling\",\n }),\n getColorField({\n defaultValue: \"background\",\n key: \"headerColor\",\n label: \"Header Color\",\n description:\n \"Headline color. Also drives eyebrow, controls and progress bar.\",\n tab: \"styling\",\n group: \"Text Styling\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Text Styling\",\n },\n getFontSizeField({\n defaultValue: \"md\",\n key: \"textSize\",\n label: \"Text Font Size\",\n description: \"Font size for the slide text\",\n tab: \"styling\",\n group: \"Text Styling\",\n }),\n getColorField({\n defaultValue: \"background\",\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Color variant for the slide text\",\n tab: \"styling\",\n group: \"Text Styling\",\n }),\n\n // Layout group\n {\n key: \"align\",\n label: \"Alignment\",\n type: \"alignment\",\n description: \"Alignment of the carousel content\",\n defaultValue: { vertical: \"bottom\", horizontal: \"left\" },\n options: {\n verticalEnabled: true,\n horizontalEnabled: true,\n },\n tab: \"styling\",\n group: \"Layout\",\n },\n {\n key: \"textWidth\",\n label: \"Content Width\",\n type: \"cssUnit\",\n description: \"Maximum width for slide content\",\n defaultValue: \"620px\",\n allowedUnits: [\"px\", \"rem\", \"%\"],\n defaultUnit: \"px\",\n minByUnit: { px: 50, rem: 3, \"%\": 10 },\n maxByUnit: { px: 1200, rem: 75, \"%\": 100 },\n stepByUnit: { px: 10, rem: 1, \"%\": 1 },\n tab: \"styling\",\n group: \"Layout\",\n },\n\n // Design group\n getHeightField({\n key: \"carouselHeight\",\n label: \"Carousel Height\",\n description: \"Height of the carousel\",\n defaultValue: \"400px\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"separator2\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n getBorderRadiusField({\n defaultValue: \"xl\",\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Rounded corners for the carousel\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the carousel container\",\n defaultValue: \"none\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Border color for the carousel container\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getPaddingField({\n defaultValue: 8,\n key: \"padding\",\n label: \"Padding\",\n description: \"Inner padding around slide content\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"overlayEnabled\",\n label: \"Enable Overlay\",\n type: \"boolean\",\n description: \"Add background overlay to slide content\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"overlayType\",\n label: \"Overlay Type\",\n type: \"buttonGroup\",\n description: \"Overlay style (only applies when editorial frame is off)\",\n defaultValue: \"gradient\",\n options: [\n { label: \"Solid\", value: \"solid\" },\n { label: \"Gradient\", value: \"gradient\" },\n ],\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"overlayIntensity\",\n label: \"Overlay Intensity\",\n type: \"slider\",\n description: \"Opacity of the overlay (0-100)\",\n min: 0,\n max: 100,\n step: 5,\n defaultValue: 70,\n unit: \"%\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"showButton\",\n label: \"Show Primary Button\",\n type: \"boolean\",\n description:\n \"Global show/hide for all slide CTAs. Per-slide button content is set on each item under the Data tab (custom sources only).\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n getColorField({\n defaultValue: \"background\",\n key: \"buttonColor\",\n label: \"Button Color\",\n description: \"Color variant for the slide button\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"showButton\",\n }),\n getButtonSizeField({\n defaultValue: \"default\",\n key: \"buttonSize\",\n label: \"Button Size\",\n description: \"Size of the slide button\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"showButton\",\n }),\n\n // Behavior tab\n {\n key: \"enableAutoScroll\",\n label: \"Enable Auto-Scroll\",\n type: \"boolean\",\n description:\n \"Automatically advance to the next slide. Progress bar fills at this rate and pauses on hover.\",\n defaultValue: false,\n tab: \"behavior\",\n group: \"Auto-Scroll\",\n },\n {\n key: \"autoScrollInterval\",\n label: \"Auto-Scroll Interval (ms)\",\n type: \"number\",\n description: \"Time between automatic slide transitions\",\n min: 1000,\n max: 15000,\n step: 500,\n defaultValue: 6500,\n tab: \"behavior\",\n group: \"Auto-Scroll\",\n requiresKeyToBeTrue: \"enableAutoScroll\",\n },\n\n // Data tab\n {\n key: \"dataSource\",\n label: \"Data Source\",\n type: \"dataSource\",\n description: \"Configure the slides rendered by the carousel.\",\n targetProps: [\n {\n key: \"slides\",\n description:\n \"Slides rendered by the carousel, usually supplied by a data source.\",\n },\n ],\n tab: \"data\",\n group: \"Data Configuration\",\n },\n ],\n itemConfigSchema: {\n description: \"Configure settings for this slide\",\n fields: [\n {\n key: \"eyebrow\",\n label: \"Eyebrow\",\n type: \"text\",\n description:\n \"Short label above the title (e.g. 'From Fluid · Newsroom')\",\n },\n {\n key: \"tag\",\n label: \"Tag / Category\",\n type: \"text\",\n description: \"Short pill label (e.g. 'Policy', 'New release')\",\n },\n {\n key: \"tagColor\",\n label: \"Tag Color\",\n type: \"colorSelect\",\n description: \"Background color of the tag pill\",\n defaultValue: \"background\",\n },\n {\n key: \"meta\",\n label: \"Meta\",\n type: \"text\",\n description: \"Meta line (e.g. 'Apr 12 · 4 min read')\",\n },\n {\n key: \"separator_slide_1\",\n type: \"separator\",\n label: \"Separator\",\n },\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"Override the item's title for this slide\",\n },\n {\n key: \"description\",\n label: \"Description\",\n type: \"textarea\",\n description: \"Override the item's description for this slide\",\n rows: 3,\n },\n {\n key: \"separator_slide_2\",\n type: \"separator\",\n label: \"Separator\",\n },\n {\n key: \"buttonEnabled\",\n label: \"Show Primary Button\",\n type: \"boolean\",\n description: \"Show the primary CTA on this slide\",\n defaultValue: false,\n },\n {\n key: \"buttonText\",\n label: \"Button Text\",\n type: \"text\",\n description: \"Text for the primary button\",\n requiresKeyToBeTrue: \"buttonEnabled\",\n },\n {\n key: \"buttonLink\",\n label: \"Button Link\",\n type: \"text\",\n description: \"URL for the primary button\",\n requiresKeyToBeTrue: \"buttonEnabled\",\n },\n {\n key: \"secondaryButtonText\",\n label: \"Secondary Link Text\",\n type: \"text\",\n description:\n \"Optional text-only secondary link (renders with an arrow)\",\n },\n {\n key: \"secondaryButtonLink\",\n label: \"Secondary Link URL\",\n type: \"text\",\n description: \"URL for the secondary link\",\n },\n { key: \"separator_link\", type: \"separator\", label: \"Separator\" },\n ...getLinkTypeFields(),\n ],\n },\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACDN,mBAAAA,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EACFO,mBAAAA,mBAAmB;GACjB,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EAGF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EAGD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,aAAa,CACX;IACE,KAAK;IACL,aACE;IACH,CACF;GACD,KAAK;GACL,OAAO;GACR;EACF;CACD,kBAAkB;EAChB,aAAa;EACb,QAAQ;GACN;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aACE;IACH;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACd;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACb,cAAc;IACf;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACd;GACD;IACE,KAAK;IACL,MAAM;IACN,OAAO;IACR;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACd;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACb,MAAM;IACP;GACD;IACE,KAAK;IACL,MAAM;IACN,OAAO;IACR;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACb,cAAc;IACf;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACb,qBAAqB;IACtB;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACb,qBAAqB;IACtB;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aACE;IACH;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACd;GACD;IAAE,KAAK;IAAkB,MAAM;IAAa,OAAO;IAAa;GAChE,GAAGC,gCAAAA,mBAAmB;GACvB;EACF;CACF"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Vn as __exportAll } from "./src-BfINy9nC.mjs";
|
|
2
|
-
import { n as useWidgetInteraction } from "./WidgetInteractionContext-
|
|
2
|
+
import { n as useWidgetInteraction } from "./WidgetInteractionContext-IsMo73Ka.mjs";
|
|
3
3
|
import { r as useRepUser, t as useWidgetRenderState } from "./WidgetRenderStateContext-Bax78KoX.mjs";
|
|
4
4
|
import { c as getButtonSizeField, i as getBorderColorField, l as getColorField, m as getPaddingField, n as borderWidthClasses, o as getBorderRadiusField, p as getHeightField, s as getBorderWidthField, t as borderColorClasses, u as getFontSizeField } from "./registries-B2aW34Dg.mjs";
|
|
5
|
-
import { t as useInternalLinks } from "./use-internal-link-
|
|
5
|
+
import { t as useInternalLinks } from "./use-internal-link-CKMpGvvs.mjs";
|
|
6
6
|
import { r as purify, t as buildItemInteractionProps } from "./helpers-wMrhc0DH.mjs";
|
|
7
7
|
import { r as getMediaPropsFromWidgetSchema, t as MediaRenderer } from "./MediaRenderer-BgMdmkkL.mjs";
|
|
8
8
|
import { t as getLinkTypeFields } from "./link-type-schema-fields-ab4eyJar.mjs";
|
|
@@ -752,4 +752,4 @@ const carouselWidgetPropertySchema = {
|
|
|
752
752
|
//#endregion
|
|
753
753
|
export { CarouselWidget_exports as n, carouselWidgetPropertySchema as r, CarouselWidget as t };
|
|
754
754
|
|
|
755
|
-
//# sourceMappingURL=CarouselWidget-
|
|
755
|
+
//# sourceMappingURL=CarouselWidget-CU1oj0q4.mjs.map
|