@fluid-app/portal-sdk 0.1.238 → 0.1.239

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/dist/{CalendarWidget-BaGML5Xh.mjs → CalendarWidget-BXxNxHDV.mjs} +2 -2
  2. package/dist/{CalendarWidget-BaGML5Xh.mjs.map → CalendarWidget-BXxNxHDV.mjs.map} +1 -1
  3. package/dist/{CalendarWidget-oGK122s9.cjs → CalendarWidget-VjQXZW8B.cjs} +2 -2
  4. package/dist/{CalendarWidget-oGK122s9.cjs.map → CalendarWidget-VjQXZW8B.cjs.map} +1 -1
  5. package/dist/{CardWidget-CqYjGkq-.mjs → CardWidget-BNkMlxQ3.mjs} +2 -2
  6. package/dist/{CardWidget-CqYjGkq-.mjs.map → CardWidget-BNkMlxQ3.mjs.map} +1 -1
  7. package/dist/{CardWidget-CSLSlKM6.cjs → CardWidget-C3I9OwgS.cjs} +2 -2
  8. package/dist/{CardWidget-CSLSlKM6.cjs.map → CardWidget-C3I9OwgS.cjs.map} +1 -1
  9. package/dist/{CardWidget-DjhK0yr-.cjs → CardWidget-CraWMttj.cjs} +3 -3
  10. package/dist/{CarouselWidget-DlxYQB5j.cjs → CarouselWidget-CiKlooUF.cjs} +2 -2
  11. package/dist/{CarouselWidget-DlxYQB5j.cjs.map → CarouselWidget-CiKlooUF.cjs.map} +1 -1
  12. package/dist/{CarouselWidget-CdQhlRrW.mjs → CarouselWidget-p8Z6L-G5.mjs} +2 -2
  13. package/dist/{CarouselWidget-CdQhlRrW.mjs.map → CarouselWidget-p8Z6L-G5.mjs.map} +1 -1
  14. package/dist/{CatchUpWidget-BQjtjcGR.mjs → CatchUpWidget-B9DQlzd_.mjs} +2 -2
  15. package/dist/{CatchUpWidget-BQjtjcGR.mjs.map → CatchUpWidget-B9DQlzd_.mjs.map} +1 -1
  16. package/dist/{CatchUpWidget-B1Muaurg.cjs → CatchUpWidget-SY7hOHk6.cjs} +2 -2
  17. package/dist/{CatchUpWidget-B1Muaurg.cjs.map → CatchUpWidget-SY7hOHk6.cjs.map} +1 -1
  18. package/dist/{ContainerWidget-Cjwrq2MS.cjs → ContainerWidget-BXpdj06u.cjs} +2 -2
  19. package/dist/{ContainerWidget-Cjwrq2MS.cjs.map → ContainerWidget-BXpdj06u.cjs.map} +1 -1
  20. package/dist/{ContainerWidget-DYThUtiZ.mjs → ContainerWidget-CpwvcxFm.mjs} +2 -2
  21. package/dist/{ContainerWidget-DYThUtiZ.mjs.map → ContainerWidget-CpwvcxFm.mjs.map} +1 -1
  22. package/dist/ContainerWidget-CyfPYEAv.cjs +8 -0
  23. package/dist/{FluidProvider-B3DjYoUW.mjs → FluidProvider-DL5rChtj.mjs} +67 -84
  24. package/dist/FluidProvider-DL5rChtj.mjs.map +1 -0
  25. package/dist/{FluidProvider-DcpUKHrn.cjs → FluidProvider-D_PHVlUU.cjs} +67 -84
  26. package/dist/FluidProvider-D_PHVlUU.cjs.map +1 -0
  27. package/dist/{ImageWidget-xcE0sFf-.cjs → ImageWidget-CbQVxMe3.cjs} +2 -2
  28. package/dist/{ImageWidget-xcE0sFf-.cjs.map → ImageWidget-CbQVxMe3.cjs.map} +1 -1
  29. package/dist/{ImageWidget-CFTpbu8X.mjs → ImageWidget-vNWT_O1E.mjs} +2 -2
  30. package/dist/{ImageWidget-CFTpbu8X.mjs.map → ImageWidget-vNWT_O1E.mjs.map} +1 -1
  31. package/dist/{LayoutWidget-CK-SvFQL.cjs → LayoutWidget-BIfNHlVE.cjs} +2 -2
  32. package/dist/{LayoutWidget-CK-SvFQL.cjs.map → LayoutWidget-BIfNHlVE.cjs.map} +1 -1
  33. package/dist/{LayoutWidget-Cx5ZyXSU.mjs → LayoutWidget-CC3oK78H.mjs} +2 -2
  34. package/dist/{LayoutWidget-Cx5ZyXSU.mjs.map → LayoutWidget-CC3oK78H.mjs.map} +1 -1
  35. package/dist/{LayoutWidget-DuueFNAS.cjs → LayoutWidget-LdF_cKrB.cjs} +3 -3
  36. package/dist/{LinkWidget-B14FTQP7.cjs → LinkWidget-BoR7nVbH.cjs} +2 -2
  37. package/dist/{LinkWidget-B14FTQP7.cjs.map → LinkWidget-BoR7nVbH.cjs.map} +1 -1
  38. package/dist/{LinkWidget-CQHmKO-O.mjs → LinkWidget-CO-Cxf7Z.mjs} +2 -2
  39. package/dist/{LinkWidget-CQHmKO-O.mjs.map → LinkWidget-CO-Cxf7Z.mjs.map} +1 -1
  40. package/dist/{LinkWidget-CPmE8gpd.cjs → LinkWidget-M9YzMJT8.cjs} +2 -2
  41. package/dist/{ListWidget-YvCp7XDq.cjs → ListWidget-CuSjvwEw.cjs} +3 -3
  42. package/dist/{ListWidget-wBDnXWxa.cjs → ListWidget-CzljZ1LA.cjs} +3 -3
  43. package/dist/{ListWidget-wBDnXWxa.cjs.map → ListWidget-CzljZ1LA.cjs.map} +1 -1
  44. package/dist/{ListWidget-BnyD2Hpc.mjs → ListWidget-f88QhcGI.mjs} +3 -3
  45. package/dist/{ListWidget-BnyD2Hpc.mjs.map → ListWidget-f88QhcGI.mjs.map} +1 -1
  46. package/dist/{MediaRenderer-CfgWd0cC.cjs → MediaRenderer-CvN8Ku0i.cjs} +4 -4
  47. package/dist/MediaRenderer-CvN8Ku0i.cjs.map +1 -0
  48. package/dist/{MediaRenderer-CqUpv3St.mjs → MediaRenderer-DMdb_5xw.mjs} +4 -4
  49. package/dist/MediaRenderer-DMdb_5xw.mjs.map +1 -0
  50. package/dist/{MessagingScreen-BzWV22JZ.cjs → MessagingScreen-Dkh3Dsp7.cjs} +2 -2
  51. package/dist/{MessagingScreen-BzWV22JZ.cjs.map → MessagingScreen-Dkh3Dsp7.cjs.map} +1 -1
  52. package/dist/{MessagingScreen-CPBUg-32.cjs → MessagingScreen-Dxy2VQbO.cjs} +22 -22
  53. package/dist/{MessagingScreen-BBqwXPZB.mjs → MessagingScreen-mt1u3Bs1.mjs} +2 -2
  54. package/dist/{MessagingScreen-BBqwXPZB.mjs.map → MessagingScreen-mt1u3Bs1.mjs.map} +1 -1
  55. package/dist/{MySiteWidget-COj7yYQF.mjs → MySiteWidget-BnjPrQxE.mjs} +2 -2
  56. package/dist/{MySiteWidget-COj7yYQF.mjs.map → MySiteWidget-BnjPrQxE.mjs.map} +1 -1
  57. package/dist/{MySiteWidget-DRH4q_YV.cjs → MySiteWidget-C8eFWHOT.cjs} +2 -2
  58. package/dist/{MySiteWidget-DRH4q_YV.cjs.map → MySiteWidget-C8eFWHOT.cjs.map} +1 -1
  59. package/dist/{NestedWidget-C_2XwnW0.cjs → NestedWidget-CEoAO2sp.cjs} +3 -3
  60. package/dist/{NestedWidget-C_2XwnW0.cjs.map → NestedWidget-CEoAO2sp.cjs.map} +1 -1
  61. package/dist/{NestedWidget-CXIvsJdD.cjs → NestedWidget-CMCZjV6t.cjs} +3 -3
  62. package/dist/{NestedWidget-WJoWOFda.mjs → NestedWidget-RuyrOrFn.mjs} +3 -3
  63. package/dist/{NestedWidget-WJoWOFda.mjs.map → NestedWidget-RuyrOrFn.mjs.map} +1 -1
  64. package/dist/{PointsWidget-DoUljaNY.mjs → PointsWidget-C2KB4k48.mjs} +2 -2
  65. package/dist/{PointsWidget-DoUljaNY.mjs.map → PointsWidget-C2KB4k48.mjs.map} +1 -1
  66. package/dist/{PointsWidget-CLUWrFjZ.cjs → PointsWidget-DLp-PYus.cjs} +2 -2
  67. package/dist/{PointsWidget-CLUWrFjZ.cjs.map → PointsWidget-DLp-PYus.cjs.map} +1 -1
  68. package/dist/{ProfileScreen-C0nmvuW1.cjs → ProfileScreen-BMe-dQi7.cjs} +2 -2
  69. package/dist/{ProfileScreen-C0nmvuW1.cjs.map → ProfileScreen-BMe-dQi7.cjs.map} +1 -1
  70. package/dist/{ProfileScreen-MCfnv8eT.cjs → ProfileScreen-ChCZZ91o.cjs} +22 -22
  71. package/dist/{ProfileScreen-CwQr_Km7.mjs → ProfileScreen-_1GlBr7z.mjs} +2 -2
  72. package/dist/{ProfileScreen-CwQr_Km7.mjs.map → ProfileScreen-_1GlBr7z.mjs.map} +1 -1
  73. package/dist/{RecentActivityWidget-C6RwlUUw.cjs → RecentActivityWidget-BNW9aFT4.cjs} +2 -2
  74. package/dist/{RecentActivityWidget-C6RwlUUw.cjs.map → RecentActivityWidget-BNW9aFT4.cjs.map} +1 -1
  75. package/dist/{RecentActivityWidget-zQxtUECm.mjs → RecentActivityWidget-DelPdiwR.mjs} +2 -2
  76. package/dist/{RecentActivityWidget-zQxtUECm.mjs.map → RecentActivityWidget-DelPdiwR.mjs.map} +1 -1
  77. package/dist/{ScreenRenderer-Bk23YOtN.mjs → ScreenRenderer-ClYgfQf_.mjs} +2 -2
  78. package/dist/{ScreenRenderer-Bk23YOtN.mjs.map → ScreenRenderer-ClYgfQf_.mjs.map} +1 -1
  79. package/dist/{ScreenRenderer-aYfgv6mR.cjs → ScreenRenderer-Ct1w4PNu.cjs} +2 -2
  80. package/dist/{ScreenRenderer-aYfgv6mR.cjs.map → ScreenRenderer-Ct1w4PNu.cjs.map} +1 -1
  81. package/dist/{ShopScreen-D39WpS6j.mjs → ShopScreen-BBfOte5o.mjs} +2 -2
  82. package/dist/{ShopScreen-D39WpS6j.mjs.map → ShopScreen-BBfOte5o.mjs.map} +1 -1
  83. package/dist/{ShopScreen-Brw7gNMu.cjs → ShopScreen-CZ_290EP.cjs} +22 -22
  84. package/dist/{ShopScreen-CiGozvW4.cjs → ShopScreen-DWLGH2gt.cjs} +2 -2
  85. package/dist/{ShopScreen-CiGozvW4.cjs.map → ShopScreen-DWLGH2gt.cjs.map} +1 -1
  86. package/dist/{TableWidget-D4jQN-to.cjs → TableWidget-BIn1oRiJ.cjs} +4 -4
  87. package/dist/TableWidget-BIn1oRiJ.cjs.map +1 -0
  88. package/dist/{TableWidget-DWAYgQcl.cjs → TableWidget-C--8TSX7.cjs} +3 -3
  89. package/dist/{TableWidget-B0CRdzNf.mjs → TableWidget-dfUvhH0S.mjs} +4 -4
  90. package/dist/TableWidget-dfUvhH0S.mjs.map +1 -0
  91. package/dist/{ToDoWidget-BbeXt99H.cjs → ToDoWidget-Bjoan2Rm.cjs} +2 -2
  92. package/dist/{ToDoWidget-BbeXt99H.cjs.map → ToDoWidget-Bjoan2Rm.cjs.map} +1 -1
  93. package/dist/{ToDoWidget-VSaNmtWH.mjs → ToDoWidget-CYDsZA0Z.mjs} +2 -2
  94. package/dist/{ToDoWidget-VSaNmtWH.mjs.map → ToDoWidget-CYDsZA0Z.mjs.map} +1 -1
  95. package/dist/{ToDoWidget-YHmoDbVU.cjs → ToDoWidget-C_CvWdLi.cjs} +2 -2
  96. package/dist/{VideoWidget-Bc6ZAAaA.cjs → VideoWidget-CDcV0J5W.cjs} +2 -2
  97. package/dist/{VideoWidget-Bc6ZAAaA.cjs.map → VideoWidget-CDcV0J5W.cjs.map} +1 -1
  98. package/dist/{VideoWidget-DcWm239R.mjs → VideoWidget-Dj9wue7j.mjs} +2 -2
  99. package/dist/{VideoWidget-DcWm239R.mjs.map → VideoWidget-Dj9wue7j.mjs.map} +1 -1
  100. package/dist/WidgetInteractionContext-B1mELhQ_.mjs +28 -0
  101. package/dist/{WidgetInteractionContext-D0TJv70C.mjs.map → WidgetInteractionContext-B1mELhQ_.mjs.map} +1 -1
  102. package/dist/WidgetInteractionContext-DvPmzGqB.cjs +41 -0
  103. package/dist/{WidgetInteractionContext-Bs3LkFFH.cjs.map → WidgetInteractionContext-DvPmzGqB.cjs.map} +1 -1
  104. package/dist/index.cjs +81 -52
  105. package/dist/index.cjs.map +1 -1
  106. package/dist/index.d.cts.map +1 -1
  107. package/dist/index.d.mts.map +1 -1
  108. package/dist/index.mjs +81 -52
  109. package/dist/index.mjs.map +1 -1
  110. package/dist/{registry-context-BDH0vNHR.mjs → registry-context-BahYMRqn.mjs} +12 -20
  111. package/dist/registry-context-BahYMRqn.mjs.map +1 -0
  112. package/dist/{registry-context-C7-RLxVt.cjs → registry-context-bf52ZIJX.cjs} +12 -20
  113. package/dist/registry-context-bf52ZIJX.cjs.map +1 -0
  114. package/package.json +11 -11
  115. package/dist/ContainerWidget-NFBqSeRV.cjs +0 -8
  116. package/dist/FluidProvider-B3DjYoUW.mjs.map +0 -1
  117. package/dist/FluidProvider-DcpUKHrn.cjs.map +0 -1
  118. package/dist/MediaRenderer-CfgWd0cC.cjs.map +0 -1
  119. package/dist/MediaRenderer-CqUpv3St.mjs.map +0 -1
  120. package/dist/TableWidget-B0CRdzNf.mjs.map +0 -1
  121. package/dist/TableWidget-D4jQN-to.cjs.map +0 -1
  122. package/dist/WidgetInteractionContext-Bs3LkFFH.cjs +0 -18
  123. package/dist/WidgetInteractionContext-D0TJv70C.mjs +0 -11
  124. package/dist/registry-context-BDH0vNHR.mjs.map +0 -1
  125. package/dist/registry-context-C7-RLxVt.cjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"CardWidget-CSLSlKM6.cjs","names":["useRegistry","ScreenRenderer","useScreenRenderer","DefaultScreenRenderer","gapValues","borderWidthClasses","borderColorClasses","getFontSizeField","getColorField","getPaddingField","getBorderRadiusField","getBorderWidthField","getBorderColorField","getGapField"],"sources":["../../widgets/src/widgets/CardWidget.tsx"],"sourcesContent":["import { ScreenRenderer as DefaultScreenRenderer } from \"../core/ScreenRenderer\";\nimport { useRegistry } from \"../contexts/RegistryContext\";\nimport { useScreenRenderer } from \"../contexts/ScreenRendererContext\";\nimport type {\n WidgetSchema,\n BackgroundValue,\n BorderRadiusOptions,\n BorderWidthOptions,\n PaddingOptions,\n GapOptions,\n ColorOptions,\n FontSizeOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type React from \"react\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n getColorField,\n getFontSizeField,\n getGapField,\n getPaddingField,\n gapValues,\n borderWidthClasses,\n borderColorClasses,\n} from \"../core/fields\";\n\nconst DEFAULT_BACKGROUND: BackgroundValue = {\n type: \"solid\",\n color: \"background\",\n};\nconst DEFAULT_CHILDREN: (WidgetSchema | null)[] = [];\n\ntype CardWidgetProps = {\n // Header\n headerEnabled?: boolean;\n title?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n headerBackground?: ColorOptions;\n\n // Footer\n footerEnabled?: boolean;\n footerContent?: string;\n footerColor?: ColorOptions;\n footerBackground?: ColorOptions;\n\n // Styling\n background?: BackgroundValue;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n /** @deprecated Use borderWidth instead */\n borderEnabled?: boolean;\n gapSize?: GapOptions;\n\n // Container props (children = other widgets)\n children?: (WidgetSchema | null)[];\n\n // Styling\n className?: string;\n};\n\nexport function CardWidget({\n // Header\n headerEnabled = true,\n title = \"Card Title\",\n titleFontSize = \"lg\",\n titleColor = \"foreground\",\n headerBackground = \"transparent\",\n\n // Footer\n footerEnabled = false,\n footerContent = \"\",\n footerColor = \"muted\",\n footerBackground = \"transparent\",\n\n // Styling\n background = DEFAULT_BACKGROUND,\n padding = 6,\n borderRadius = \"xl\",\n borderWidth = \"thin\",\n borderColor = \"muted\",\n borderEnabled,\n gapSize = \"md\",\n\n // Container\n children = DEFAULT_CHILDREN,\n\n className = \"\",\n}: CardWidgetProps): React.JSX.Element {\n // Get registry from context if not provided as prop\n const contextRegistry = useRegistry();\n\n // Use ScreenRenderer from context, fall back to local\n const ContextScreenRenderer = useScreenRenderer();\n const ScreenRenderer = ContextScreenRenderer ?? DefaultScreenRenderer;\n\n // Extract background values\n const backgroundColor = background.color || \"background\";\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 const gapSizeValue = gapSize ? gapValues[gapSize] : 4;\n\n // Backwards compatibility: if legacy borderEnabled prop exists, map it\n const effectiveBorderWidth = borderEnabled === false ? \"none\" : borderWidth;\n\n const cardClasses = [\n \"flex flex-col gap-6\",\n `bg-${backgroundColor}`,\n `p-${padding}`,\n `rounded-${borderRadius}`,\n borderWidthClasses[effectiveBorderWidth],\n effectiveBorderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n const containerStyle: React.CSSProperties = {\n backgroundImage,\n };\n\n // Filter out null children\n const validChildren = children.filter(\n (child): child is WidgetSchema => child !== null,\n );\n\n return (\n <div data-slot=\"card\" className={cardClasses} style={containerStyle}>\n {headerEnabled && (title || headerBackground !== \"transparent\") && (\n <div\n data-slot=\"card-header\"\n className={\n headerBackground !== \"transparent\"\n ? `bg-${headerBackground} -mx-${padding} -mt-${padding} px-${padding} py-${padding} rounded-t-${borderRadius}`\n : undefined\n }\n >\n {title && (\n <div\n data-slot=\"card-title\"\n className={`text-${titleFontSize} text-${titleColor} font-header leading-none font-semibold`}\n >\n {title}\n </div>\n )}\n </div>\n )}\n\n <div data-slot=\"card-content\" className=\"@container flex-1\">\n {contextRegistry ? (\n <ScreenRenderer\n screen={validChildren}\n registry={contextRegistry}\n className={`flex flex-col gap-${gapSizeValue}`}\n />\n ) : (\n <div className={`flex flex-col gap-${gapSizeValue}`} />\n )}\n </div>\n\n {footerEnabled && footerContent && (\n <div\n data-slot=\"card-footer\"\n className={[\n `text-sm text-${footerColor} flex items-center`,\n footerBackground !== \"transparent\"\n ? `bg-${footerBackground} -mx-${padding} -mb-${padding} px-${padding} py-${padding} rounded-b-${borderRadius}`\n : \"\",\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n {footerContent}\n </div>\n )}\n </div>\n );\n}\n\nexport const cardWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"CardWidget\",\n displayName: \"Card\",\n fields: [\n // Header\n {\n key: \"headerEnabled\",\n label: \"Show Header\",\n type: \"boolean\",\n description: \"Toggle header visibility\",\n defaultValue: true,\n group: \"Header\",\n },\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"Card title text\",\n defaultValue: \"Card Title\",\n group: \"Header\",\n requiresKeyToBeTrue: \"headerEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the title\",\n defaultValue: \"lg\",\n group: \"Header\",\n requiresKeyToBeTrue: \"headerEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the title\",\n defaultValue: \"foreground\",\n group: \"Header\",\n requiresKeyToBeTrue: \"headerEnabled\",\n }),\n getColorField({\n key: \"headerBackground\",\n label: \"Header Background\",\n description: \"Background color for the header\",\n defaultValue: \"transparent\",\n group: \"Header\",\n requiresKeyToBeTrue: \"headerEnabled\",\n }),\n\n // Footer\n {\n key: \"footerEnabled\",\n label: \"Show Footer\",\n type: \"boolean\",\n description: \"Toggle footer visibility\",\n defaultValue: false,\n group: \"Footer\",\n },\n {\n key: \"footerContent\",\n label: \"Footer Text\",\n type: \"text\",\n description: \"Footer content text\",\n defaultValue: \"\",\n group: \"Footer\",\n requiresKeyToBeTrue: \"footerEnabled\",\n },\n getColorField({\n key: \"footerColor\",\n label: \"Footer Color\",\n description: \"Color for the footer text\",\n defaultValue: \"muted\",\n group: \"Footer\",\n requiresKeyToBeTrue: \"footerEnabled\",\n }),\n getColorField({\n key: \"footerBackground\",\n label: \"Footer Background\",\n description: \"Background color for the footer\",\n defaultValue: \"transparent\",\n group: \"Footer\",\n requiresKeyToBeTrue: \"footerEnabled\",\n }),\n\n // Design\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the card\",\n defaultValue: \"background\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Card padding\",\n defaultValue: 6,\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Card border radius\",\n defaultValue: \"xl\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Card border width\",\n defaultValue: \"thin\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Card border color\",\n defaultValue: \"muted\",\n group: \"Design\",\n }),\n getGapField({\n key: \"gapSize\",\n label: \"Gap\",\n description: \"Gap between child widgets\",\n defaultValue: \"md\",\n group: \"Design\",\n }),\n ],\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"CardWidget-C3I9OwgS.cjs","names":["useRegistry","ScreenRenderer","useScreenRenderer","DefaultScreenRenderer","gapValues","borderWidthClasses","borderColorClasses","getFontSizeField","getColorField","getPaddingField","getBorderRadiusField","getBorderWidthField","getBorderColorField","getGapField"],"sources":["../../widgets/src/widgets/CardWidget.tsx"],"sourcesContent":["import { ScreenRenderer as DefaultScreenRenderer } from \"../core/ScreenRenderer\";\nimport { useRegistry } from \"../contexts/RegistryContext\";\nimport { useScreenRenderer } from \"../contexts/ScreenRendererContext\";\nimport type {\n WidgetSchema,\n BackgroundValue,\n BorderRadiusOptions,\n BorderWidthOptions,\n PaddingOptions,\n GapOptions,\n ColorOptions,\n FontSizeOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type React from \"react\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n getColorField,\n getFontSizeField,\n getGapField,\n getPaddingField,\n gapValues,\n borderWidthClasses,\n borderColorClasses,\n} from \"../core/fields\";\n\nconst DEFAULT_BACKGROUND: BackgroundValue = {\n type: \"solid\",\n color: \"background\",\n};\nconst DEFAULT_CHILDREN: (WidgetSchema | null)[] = [];\n\ntype CardWidgetProps = {\n // Header\n headerEnabled?: boolean;\n title?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n headerBackground?: ColorOptions;\n\n // Footer\n footerEnabled?: boolean;\n footerContent?: string;\n footerColor?: ColorOptions;\n footerBackground?: ColorOptions;\n\n // Styling\n background?: BackgroundValue;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n /** @deprecated Use borderWidth instead */\n borderEnabled?: boolean;\n gapSize?: GapOptions;\n\n // Container props (children = other widgets)\n children?: (WidgetSchema | null)[];\n\n // Styling\n className?: string;\n};\n\nexport function CardWidget({\n // Header\n headerEnabled = true,\n title = \"Card Title\",\n titleFontSize = \"lg\",\n titleColor = \"foreground\",\n headerBackground = \"transparent\",\n\n // Footer\n footerEnabled = false,\n footerContent = \"\",\n footerColor = \"muted\",\n footerBackground = \"transparent\",\n\n // Styling\n background = DEFAULT_BACKGROUND,\n padding = 6,\n borderRadius = \"xl\",\n borderWidth = \"thin\",\n borderColor = \"muted\",\n borderEnabled,\n gapSize = \"md\",\n\n // Container\n children = DEFAULT_CHILDREN,\n\n className = \"\",\n}: CardWidgetProps): React.JSX.Element {\n // Get registry from context if not provided as prop\n const contextRegistry = useRegistry();\n\n // Use ScreenRenderer from context, fall back to local\n const ContextScreenRenderer = useScreenRenderer();\n const ScreenRenderer = ContextScreenRenderer ?? DefaultScreenRenderer;\n\n // Extract background values\n const backgroundColor = background.color || \"background\";\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 const gapSizeValue = gapSize ? gapValues[gapSize] : 4;\n\n // Backwards compatibility: if legacy borderEnabled prop exists, map it\n const effectiveBorderWidth = borderEnabled === false ? \"none\" : borderWidth;\n\n const cardClasses = [\n \"flex flex-col gap-6\",\n `bg-${backgroundColor}`,\n `p-${padding}`,\n `rounded-${borderRadius}`,\n borderWidthClasses[effectiveBorderWidth],\n effectiveBorderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n const containerStyle: React.CSSProperties = {\n backgroundImage,\n };\n\n // Filter out null children\n const validChildren = children.filter(\n (child): child is WidgetSchema => child !== null,\n );\n\n return (\n <div data-slot=\"card\" className={cardClasses} style={containerStyle}>\n {headerEnabled && (title || headerBackground !== \"transparent\") && (\n <div\n data-slot=\"card-header\"\n className={\n headerBackground !== \"transparent\"\n ? `bg-${headerBackground} -mx-${padding} -mt-${padding} px-${padding} py-${padding} rounded-t-${borderRadius}`\n : undefined\n }\n >\n {title && (\n <div\n data-slot=\"card-title\"\n className={`text-${titleFontSize} text-${titleColor} font-header leading-none font-semibold`}\n >\n {title}\n </div>\n )}\n </div>\n )}\n\n <div data-slot=\"card-content\" className=\"@container flex-1\">\n {contextRegistry ? (\n <ScreenRenderer\n screen={validChildren}\n registry={contextRegistry}\n className={`flex flex-col gap-${gapSizeValue}`}\n />\n ) : (\n <div className={`flex flex-col gap-${gapSizeValue}`} />\n )}\n </div>\n\n {footerEnabled && footerContent && (\n <div\n data-slot=\"card-footer\"\n className={[\n `text-sm text-${footerColor} flex items-center`,\n footerBackground !== \"transparent\"\n ? `bg-${footerBackground} -mx-${padding} -mb-${padding} px-${padding} py-${padding} rounded-b-${borderRadius}`\n : \"\",\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n {footerContent}\n </div>\n )}\n </div>\n );\n}\n\nexport const cardWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"CardWidget\",\n displayName: \"Card\",\n fields: [\n // Header\n {\n key: \"headerEnabled\",\n label: \"Show Header\",\n type: \"boolean\",\n description: \"Toggle header visibility\",\n defaultValue: true,\n group: \"Header\",\n },\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"Card title text\",\n defaultValue: \"Card Title\",\n group: \"Header\",\n requiresKeyToBeTrue: \"headerEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the title\",\n defaultValue: \"lg\",\n group: \"Header\",\n requiresKeyToBeTrue: \"headerEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the title\",\n defaultValue: \"foreground\",\n group: \"Header\",\n requiresKeyToBeTrue: \"headerEnabled\",\n }),\n getColorField({\n key: \"headerBackground\",\n label: \"Header Background\",\n description: \"Background color for the header\",\n defaultValue: \"transparent\",\n group: \"Header\",\n requiresKeyToBeTrue: \"headerEnabled\",\n }),\n\n // Footer\n {\n key: \"footerEnabled\",\n label: \"Show Footer\",\n type: \"boolean\",\n description: \"Toggle footer visibility\",\n defaultValue: false,\n group: \"Footer\",\n },\n {\n key: \"footerContent\",\n label: \"Footer Text\",\n type: \"text\",\n description: \"Footer content text\",\n defaultValue: \"\",\n group: \"Footer\",\n requiresKeyToBeTrue: \"footerEnabled\",\n },\n getColorField({\n key: \"footerColor\",\n label: \"Footer Color\",\n description: \"Color for the footer text\",\n defaultValue: \"muted\",\n group: \"Footer\",\n requiresKeyToBeTrue: \"footerEnabled\",\n }),\n getColorField({\n key: \"footerBackground\",\n label: \"Footer Background\",\n description: \"Background color for the footer\",\n defaultValue: \"transparent\",\n group: \"Footer\",\n requiresKeyToBeTrue: \"footerEnabled\",\n }),\n\n // Design\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the card\",\n defaultValue: \"background\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Card padding\",\n defaultValue: 6,\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Card border radius\",\n defaultValue: \"xl\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Card border width\",\n defaultValue: \"thin\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Card border color\",\n defaultValue: \"muted\",\n group: \"Design\",\n }),\n getGapField({\n key: \"gapSize\",\n label: \"Gap\",\n description: \"Gap between child widgets\",\n defaultValue: \"md\",\n group: \"Design\",\n }),\n ],\n};\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  require("./chunk-9hOWP6kD.cjs");
2
- require("./ScreenRenderer-aYfgv6mR.cjs");
3
- require("./registry-context-C7-RLxVt.cjs");
2
+ require("./ScreenRenderer-Ct1w4PNu.cjs");
3
+ require("./registry-context-bf52ZIJX.cjs");
4
4
  require("./registries-DBb6VjAX.cjs");
5
5
  require("./fields-COJ84ouS.cjs");
6
- const require_CardWidget = require("./CardWidget-CSLSlKM6.cjs");
6
+ const require_CardWidget = require("./CardWidget-C3I9OwgS.cjs");
7
7
  exports.cardWidgetPropertySchema = require_CardWidget.cardWidgetPropertySchema;
@@ -1,7 +1,7 @@
1
1
  const require_chunk = require("./chunk-9hOWP6kD.cjs");
2
2
  const require_registries = require("./registries-DBb6VjAX.cjs");
3
3
  const require_purify_es = require("./purify.es-CxBw_WJp.cjs");
4
- const require_MediaRenderer = require("./MediaRenderer-CfgWd0cC.cjs");
4
+ const require_MediaRenderer = require("./MediaRenderer-CvN8Ku0i.cjs");
5
5
  let react = require("react");
6
6
  let react_jsx_runtime = require("react/jsx-runtime");
7
7
  //#region ../widgets/src/widgets/CarouselWidget.tsx
@@ -717,4 +717,4 @@ Object.defineProperty(exports, "carouselWidgetPropertySchema", {
717
717
  }
718
718
  });
719
719
 
720
- //# sourceMappingURL=CarouselWidget-DlxYQB5j.cjs.map
720
+ //# sourceMappingURL=CarouselWidget-CiKlooUF.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"CarouselWidget-DlxYQB5j.cjs","names":["borderWidthClasses","borderColorClasses","MediaRenderer","getMediaPropsFromWidgetSchema","DOMPurify","getColorField","getFontSizeField","getHeightField","getBorderRadiusField","getBorderWidthField","getBorderColorField","getPaddingField","getButtonSizeField"],"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\";\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};\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 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 const handleMouseEnter = useCallback(() => setIsHovered(true), []);\n const handleMouseLeave = useCallback(() => setIsHovered(false), []);\n const handleFocus = useCallback(() => setIsFocused(true), []);\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 handleMouseEnter,\n handleMouseLeave,\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 handleMouseEnter,\n handleMouseLeave,\n handleFocus,\n handleBlur,\n } = useCarouselController({\n slideCount: totalSlides,\n enableAutoScroll,\n autoScrollInterval,\n });\n\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\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 onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\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 // 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 return (\n <div\n key={slide.id}\n className=\"absolute inset-0 transition-opacity duration-700 ease-out\"\n style={{\n opacity: isActive ? 1 : 0,\n pointerEvents: isActive ? \"auto\" : \"none\",\n }}\n aria-hidden={!isActive}\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 <div\n className={`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: padding * 4 + (totalSlides > 1 ? 24 : 0),\n }}\n >\n <div\n key={`content-${currentIndex}`}\n className={`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 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 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 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 className=\"pointer-events-auto absolute inset-x-0 bottom-0 flex items-center gap-1 px-6 pb-2 sm:px-10\">\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 === \"done\") return { width: \"100%\" };\n if (state === \"upcoming\") return { width: \"0%\" };\n if (autoScroll) {\n return {\n width: \"0%\",\n animation: `fluidCarouselProgressFill ${duration}ms linear forwards`,\n animationPlayState: paused ? \"paused\" : \"running\",\n };\n }\n return { width: \"100%\" };\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: \"Display the primary CTA in slide content\",\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: \"\",\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 ],\n },\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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CzC;GACD,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,MAAM;GACN,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,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,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;GACF;EACF;CACF"}
1
+ {"version":3,"file":"CarouselWidget-CiKlooUF.cjs","names":["borderWidthClasses","borderColorClasses","MediaRenderer","getMediaPropsFromWidgetSchema","DOMPurify","getColorField","getFontSizeField","getHeightField","getBorderRadiusField","getBorderWidthField","getBorderColorField","getPaddingField","getButtonSizeField"],"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\";\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};\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 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 const handleMouseEnter = useCallback(() => setIsHovered(true), []);\n const handleMouseLeave = useCallback(() => setIsHovered(false), []);\n const handleFocus = useCallback(() => setIsFocused(true), []);\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 handleMouseEnter,\n handleMouseLeave,\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 handleMouseEnter,\n handleMouseLeave,\n handleFocus,\n handleBlur,\n } = useCarouselController({\n slideCount: totalSlides,\n enableAutoScroll,\n autoScrollInterval,\n });\n\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\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 onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\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 // 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 return (\n <div\n key={slide.id}\n className=\"absolute inset-0 transition-opacity duration-700 ease-out\"\n style={{\n opacity: isActive ? 1 : 0,\n pointerEvents: isActive ? \"auto\" : \"none\",\n }}\n aria-hidden={!isActive}\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 <div\n className={`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: padding * 4 + (totalSlides > 1 ? 24 : 0),\n }}\n >\n <div\n key={`content-${currentIndex}`}\n className={`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 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 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 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 className=\"pointer-events-auto absolute inset-x-0 bottom-0 flex items-center gap-1 px-6 pb-2 sm:px-10\">\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 === \"done\") return { width: \"100%\" };\n if (state === \"upcoming\") return { width: \"0%\" };\n if (autoScroll) {\n return {\n width: \"0%\",\n animation: `fluidCarouselProgressFill ${duration}ms linear forwards`,\n animationPlayState: paused ? \"paused\" : \"running\",\n };\n }\n return { width: \"100%\" };\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: \"Display the primary CTA in slide content\",\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: \"\",\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 ],\n },\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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CzC;GACD,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,MAAM;GACN,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,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,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;GACF;EACF;CACF"}
@@ -1,7 +1,7 @@
1
1
  import { r as __exportAll } from "./es-BXxGlAp6.mjs";
2
2
  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-Ct8o2YRe.mjs";
3
3
  import { t as purify } from "./purify.es-DzInNL5X.mjs";
4
- import { r as getMediaPropsFromWidgetSchema, t as MediaRenderer } from "./MediaRenderer-CqUpv3St.mjs";
4
+ import { r as getMediaPropsFromWidgetSchema, t as MediaRenderer } from "./MediaRenderer-DMdb_5xw.mjs";
5
5
  import { useCallback, useEffect, useState } from "react";
6
6
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
7
7
  //#region ../widgets/src/widgets/CarouselWidget.tsx
@@ -700,4 +700,4 @@ const carouselWidgetPropertySchema = {
700
700
  //#endregion
701
701
  export { CarouselWidget_exports as n, carouselWidgetPropertySchema as r, CarouselWidget as t };
702
702
 
703
- //# sourceMappingURL=CarouselWidget-CdQhlRrW.mjs.map
703
+ //# sourceMappingURL=CarouselWidget-p8Z6L-G5.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"CarouselWidget-CdQhlRrW.mjs","names":["DOMPurify"],"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\";\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};\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 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 const handleMouseEnter = useCallback(() => setIsHovered(true), []);\n const handleMouseLeave = useCallback(() => setIsHovered(false), []);\n const handleFocus = useCallback(() => setIsFocused(true), []);\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 handleMouseEnter,\n handleMouseLeave,\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 handleMouseEnter,\n handleMouseLeave,\n handleFocus,\n handleBlur,\n } = useCarouselController({\n slideCount: totalSlides,\n enableAutoScroll,\n autoScrollInterval,\n });\n\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\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 onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\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 // 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 return (\n <div\n key={slide.id}\n className=\"absolute inset-0 transition-opacity duration-700 ease-out\"\n style={{\n opacity: isActive ? 1 : 0,\n pointerEvents: isActive ? \"auto\" : \"none\",\n }}\n aria-hidden={!isActive}\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 <div\n className={`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: padding * 4 + (totalSlides > 1 ? 24 : 0),\n }}\n >\n <div\n key={`content-${currentIndex}`}\n className={`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 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 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 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 className=\"pointer-events-auto absolute inset-x-0 bottom-0 flex items-center gap-1 px-6 pb-2 sm:px-10\">\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 === \"done\") return { width: \"100%\" };\n if (state === \"upcoming\") return { width: \"0%\" };\n if (autoScroll) {\n return {\n width: \"0%\",\n animation: `fluidCarouselProgressFill ${duration}ms linear forwards`,\n animationPlayState: paused ? \"paused\" : \"running\",\n };\n }\n return { width: \"100%\" };\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: \"Display the primary CTA in slide content\",\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: \"\",\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 ],\n },\n} as const satisfies WidgetPropertySchema;\n"],"mappings":";;;;;;;;;;;AA+FA,MAAM,kBAAmD;CACvD,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,OAAO;CACR;AAED,MAAM,gBAAiD;CACrD,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,OAAO;CACR;AAED,SAAS,sBAAsB,EAC7B,YACA,kBACA,sBAKC;CACD,MAAM,CAAC,cAAc,mBAAmB,SAAS,EAAE;CAInD,MAAM,CAAC,WAAW,gBAAgB,SAAS,MAAM;CACjD,MAAM,CAAC,WAAW,gBAAgB,SAAS,MAAM;CACjD,MAAM,YAAY,aAAa;CAC/B,MAAM,WAAW,aAAa;CAE9B,MAAM,WAAW,kBAAkB;AACjC,MAAI,CAAC,UAAW;AAChB,mBAAiB,SAAU,SAAS,aAAa,IAAI,IAAI,OAAO,EAAG;IAClE,CAAC,WAAW,WAAW,CAAC;CAE3B,MAAM,eAAe,kBAAkB;AACrC,MAAI,CAAC,UAAW;AAChB,mBAAiB,SAAU,SAAS,IAAI,aAAa,IAAI,OAAO,EAAG;IAClE,CAAC,WAAW,WAAW,CAAC;CAE3B,MAAM,YAAY,aACf,UAAkB;AACjB,MAAI,CAAC,UAAW;AAChB,MAAI,SAAS,KAAK,QAAQ,WACxB,iBAAgB,MAAM;IAG1B,CAAC,WAAW,WAAW,CACxB;AAED,iBAAgB;AACd,MAAI,CAAC,oBAAoB,CAAC,aAAa,SAAU;EACjD,MAAM,aAAa,YAAY,UAAU,mBAAmB;AAC5D,eAAa,cAAc,WAAW;IACrC;EAAC;EAAkB;EAAoB;EAAW;EAAU;EAAS,CAAC;AAEzE,iBAAgB;AACd,MAAI,gBAAgB,cAAc,aAAa,EAC7C,iBAAgB,EAAE;IAEnB,CAAC,YAAY,aAAa,CAAC;AAc9B,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA,kBAnBuB,kBAAkB,aAAa,KAAK,EAAE,EAAE,CAAC;EAoBhE,kBAnBuB,kBAAkB,aAAa,MAAM,EAAE,EAAE,CAAC;EAoBjE,aAnBkB,kBAAkB,aAAa,KAAK,EAAE,EAAE,CAAC;EAoB3D,YAnBiB,aAAa,MAAqC;AAInE,OAAI,CAAC,EAAE,cAAc,SAAS,EAAE,cAA6B,CAC3D,cAAa,MAAM;KAEpB,EAAE,CAAC;EAaL;;AAGH,SAAgB,eAAe,EAC7B,SAAS,EAAE,EACX,qBAAqB,MACrB,mBAAmB,OACnB,iBAAiB,SACjB,QAAQ;CAAE,UAAU;CAAU,YAAY;CAAQ,EAClD,mBAAmB,IACnB,eAAe,MACf,cAAc,QACd,cAAc,SACd,UAAU,GACV,YAAY,SACZ,aAAa,MACb,cAAc,cACd,WAAW,MACX,YAAY,cACZ,aAAa,MACb,cAAc,cACd,aAAa,WACb,iBAAiB,MACjB,cAAc,YACd,iBAAiB,MACjB,aAAa,cACb,WACA,GAAG,SACsC;CACzC,MAAM,cAAc,OAAO;CAC3B,MAAM,EACJ,cACA,WACA,UACA,UACA,cACA,WACA,kBACA,kBACA,aACA,eACE,sBAAsB;EACxB,YAAY;EACZ;EACA;EACD,CAAC;CAEF,MAAM,gBACJ,MAAM,aAAa,QACf,gBACA,MAAM,aAAa,WACjB,iBACA;CAER,MAAM,kBACJ,MAAM,eAAe,WACjB,uCACA,MAAM,eAAe,UACnB,mCACA;CAKR,MAAM,mBAA8C,iBAChD,EACE,WAAW,2JACZ,GACD,KAAA;CAEJ,MAAM,UAAU,iBAAiB,MAAM,eAAe;AAEtD,KAAI,CAAC,UACH,QACE,oBAAC,OAAD;EACE,WAAW,2CAA2C,aAAa,GAAG,mBAAmB,aAAa,GAAG,gBAAgB,SAAS,mBAAmB,eAAe,GAAG,GAAG,QAAQ,GAAG,aAAa;EAClM,OAAO;GAAE,WAAW;GAAgB,GAAG;GAAkB;EACzD,GAAI;YAEJ,oBAAC,OAAD;GACE,WAAU;GACV,OAAO,EAAE,WAAW,gBAAgB;aAEpC,qBAAC,OAAD;IAAK,WAAU;cAAf;KACE,oBAAC,OAAD;MAAK,WAAU;gBAAW;MAAQ,CAAA;KAClC,oBAAC,KAAD;MAAG,WAAU;gBAAU;MAAmB,CAAA;KAC1C,oBAAC,KAAD;MAAG,WAAU;gBAAmC;MAE5C,CAAA;KACA;;GACF,CAAA;EACF,CAAA;AAIV,QACE,oBAAC,OAAD;EACE,WAAW,mDAAmD,aAAa,GAAG,mBAAmB,aAAa,GAAG,gBAAgB,SAAS,mBAAmB,eAAe,GAAG,GAAG,QAAQ,GAAG,aAAa;EAC1M,OAAO;GAAE,WAAW;GAAgB,GAAG;GAAkB;EACzD,cAAc;EACd,cAAc;EACd,SAAS;EACT,QAAQ;EACR,GAAI;YAEJ,qBAAC,OAAD;GACE,WAAU;GACV,OAAO;IACL,WAAW;IACX,QAAQ;IACT;aALH,CAOG,OAAO,KAAK,OAAO,UAAU;IAC5B,MAAM,WAAW,UAAU;IAI3B,MAAM,yBAAyB,OAC7B,OAAO,iBAAiB,CAAC,QAAQ,KAAK,GAAG,CAC1C;IACD,MAAM,kBACH,OAAO,SAAS,uBAAuB,GACpC,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,uBAAuB,CAAC,GAClD,MAAM;AAEZ,WACE,qBAAC,OAAD;KAEE,WAAU;KACV,OAAO;MACL,SAAS,WAAW,IAAI;MACxB,eAAe,WAAW,SAAS;MACpC;KACD,eAAa,CAAC;eAPhB;MASE,oBAAC,OAAD;OACE,WAAU;OACV,OAAO;QACL,WAAW,WAAW,aAAa;QACnC,WAAW,WACP,8CACA,KAAA;QACL;iBAED,oBAAC,eAAD,EACE,GAAI,8BAA8B,MAAM,QAAQ,EAChD,CAAA;OACE,CAAA;MAEL,kBAAkB,kBACjB,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,OAAD;OACE,WAAW,8DAA8D,WAAW,OAAO,WAAW,SAAS,WAAW;OAC1H,OAAO,EAAE,SAAS,gBAAgB;OAClC,CAAA,EACF,oBAAC,OAAD;OACE,WAAW,8DAA8D,WAAW;OACpF,OAAO,EAAE,SAAS,KAAK,IAAI,GAAG,iBAAiB,GAAI,EAAE;OACrD,CAAA,CACD,EAAA,CAAA;MAGJ,kBAAkB,CAAC,kBAClB,oBAAC,OAAD;OACE,WAAW,wCACT,gBAAgB,aACZ,+CACA;OAEN,OAAO,EAAE,SAAS,gBAAgB;OAClC,CAAA;MAGJ,oBAAC,OAAD;OACE,WAAW,uCAAuC,cAAc,GAC9D,MAAM,eAAe,WACjB,mBACA,MAAM,eAAe,UACnB,gBACA;OAER,OAAO;QACL,YAAY,UAAU;QACtB,eAAe,UAAU,KAAK,cAAc,IAAI,KAAK;QACtD;iBAED,qBAAC,OAAD;QAEE,WAAW,8BAA8B;QACzC,OAAO;SACL,UAAU;SACV,WAAW,WACP,8CACA,KAAA;SACJ,gBAAgB,WAAW,UAAU,KAAA;SACtC;kBATH;UAWI,MAAM,WAAW,MAAM,OAAO,MAAM,SACpC,qBAAC,OAAD;UACE,WAAW,qCACT,MAAM,eAAe,WACjB,mBACA,MAAM,eAAe,UACnB,gBACA;oBANV;WASG,MAAM,OACL,oBAAC,QAAD;YACE,WAAW,mBAAmB,MAAM,YAAY,aAAa,QAAQ,MAAM,YAAY,aAAa;YACpG,OACE,MAAM,aAAa,gBACnB,MAAM,aAAa,gBACnB,CAAC,MAAM,WACH,iBAAiB,MAAM,UAAU,WAAW,GAC5C,KAAA;sBAGL,MAAM;YACF,CAAA;WAER,MAAM,WACL,oBAAC,QAAD;YACE,WAAW,QAAQ,YAAY;sBAE9B,MAAM;YACF,CAAA;WAER,MAAM,QACL,oBAAC,QAAD;YACE,WAAW,QAAQ,YAAY;sBAE9B,MAAM;YACF,CAAA;WAEL;;SAGP,MAAM,SACL,oBAAC,MAAD;UACE,WAAW,QAAQ,YAAY,aAAa,gBAAgB,YAAY;oBAEvE,MAAM;UACJ,CAAA;SAGN,MAAM,eAOL,oBAAC,OAAD;UACE,WAAW,QAAQ,UAAU,MAAM,cAAc,UAAU;UAC3D,yBAAyB,EACvB,QAAQA,OAAU,SAAS,MAAM,aAAa;WAC5C,cAAc;YACZ;YACA;YACA;YACA;YACA;YACA;YACA;YACA;YACA;YACD;WACD,cAAc,EAAE;WACjB,CAAC,EACH;UACD,CAAA;gBAGI;UACN,MAAM,cACJ,MAAM,iBACN,cACA,QAAQ,MAAM,WAAW,IACzB,QAAQ,MAAM,WAAW;UAC3B,MAAM,gBACJ,QAAQ,MAAM,oBAAoB,IAClC,QAAQ,MAAM,oBAAoB;AACpC,cAAI,CAAC,eAAe,CAAC,cAAe,QAAO;AAE3C,iBACE,qBAAC,OAAD;WACE,WAAW,0CACT,MAAM,eAAe,WACjB,mBACA,MAAM,eAAe,UACnB,gBACA;qBANV,CASG,eACC,qBAAC,KAAD;YACE,MAAM,MAAM;YACZ,WAAW,oDAAoD,YAAY,QAAQ,YAAY,wFAAwF,gBAAgB,WAAW;YAClN,OAAO,EACL,WAAW,iFACZ;sBALH,CAOG,MAAM,YACP,oBAAC,QAAD;aAAM,eAAY;aAAO,WAAU;uBAAc;aAE1C,CAAA,CACL;eAEL,iBACC,qBAAC,KAAD;YACE,MAAM,MAAM;YACZ,WAAW,uCAAuC,YAAY,iBAAiB,YAAY;sBAF7F,CAIG,MAAM,qBACP,oBAAC,QAAD;aAAM,eAAY;uBAAO;aAAQ,CAAA,CAC/B;cAEF;;aAEN;SACA;UAtIC,WAAW,eAsIZ;OACF,CAAA;MACF;OApMC,MAAM,GAoMP;KAER,EAED,cAAc,KACb,qBAAC,OAAD;IAAK,WAAU;cAAf,CACE,qBAAC,OAAD;KAAK,WAAU;eAAf,CACE,oBAAC,UAAD;MACE,MAAK;MACL,SAAS;MACT,cAAW;MACX,WAAW,4DAA4D,YAAY,WAAW,YAAY,eAAe,YAAY,kDAAkD,YAAY;gBAEnM,oBAAC,iBAAD,EAAmB,CAAA;MACZ,CAAA,EACT,oBAAC,UAAD;MACE,MAAK;MACL,SAAS;MACT,cAAW;MACX,WAAW,4DAA4D,YAAY,QAAQ,YAAY;MACvG,OAAO;OAGL,WAAW,mDAAmD,YAAY;OAC1E,GAAG,wBAAwB,aAAa,WAAW;OACpD;gBAED,oBAAC,kBAAD,EAAoB,CAAA;MACb,CAAA,CACL;QAEN,oBAAC,OAAD;KAAK,WAAU;eACZ,OAAO,KAAK,GAAG,MAAM;MACpB,MAAM,QACJ,IAAI,eACA,SACA,MAAM,eACJ,WACA;AACR,aACE,oBAAC,UAAD;OAEE,MAAK;OACL,eAAe,UAAU,EAAE;OAC3B,cAAY,eAAe,IAAI;OAC/B,gBAAc,UAAU,WAAW,SAAS;OAC5C,WAAU;iBAEV,oBAAC,QAAD;QACE,WAAW,wDAAwD,YAAY;kBAE/E,oBAAC,QAAD;SAEE,WAAW,gCAAgC;SAC3C,OAAO,kBACL,OACA,kBACA,oBACA,SACD;SACD,EARK,QAAQ,EAAE,GAAG,eAQlB;QACG,CAAA;OACA,EArBF,YAAY,IAqBV;OAEX;KACE,CAAA,CACF;MAEJ;;EACF,CAAA;;AAIV,SAAS,kBACP,OACA,YACA,UACA,QACe;AACf,KAAI,UAAU,OAAQ,QAAO,EAAE,OAAO,QAAQ;AAC9C,KAAI,UAAU,WAAY,QAAO,EAAE,OAAO,MAAM;AAChD,KAAI,WACF,QAAO;EACL,OAAO;EACP,WAAW,6BAA6B,SAAS;EACjD,oBAAoB,SAAS,WAAW;EACzC;AAEH,QAAO,EAAE,OAAO,QAAQ;;AAG1B,SAAS,iBACP,UACA,YAC2B;AAG3B,KAAI,CAAC,YAAY,aAAa,aAC5B,QAAO,EAAE,OAAO,eAAe,WAAW,IAAI;AAEhD,KAAI,aAAa,aACf,QAAO,EAAE,OAAO,2BAA2B;;AAK/C,SAAS,wBACP,aACA,YAC2B;AAE3B,KAAI,gBAAgB,aAClB,QAAO,EAAE,OAAO,eAAe,WAAW,IAAI;AAEhD,KAAI,gBAAgB,aAClB,QAAO,EAAE,OAAO,2BAA2B;;AAK/C,SAAS,gBAAgB,MAAiC;AACxD,KAAI,SAAS,KAAM,QAAO;AAC1B,KAAI,SAAS,KAAM,QAAO;AAC1B,KAAI,SAAS,KAAM,QAAO;AAC1B,QAAO;;AAGT,SAAS,kBAAkB;AACzB,QACE,oBAAC,OAAD;EACE,OAAM;EACN,QAAO;EACP,SAAQ;EACR,MAAK;EACL,QAAO;EACP,aAAY;EACZ,eAAc;EACd,gBAAe;EACf,eAAY;YAEZ,oBAAC,QAAD,EAAM,GAAE,mBAAoB,CAAA;EACxB,CAAA;;AAIV,SAAS,mBAAmB;AAC1B,QACE,oBAAC,OAAD;EACE,OAAM;EACN,QAAO;EACP,SAAQ;EACR,MAAK;EACL,QAAO;EACP,aAAY;EACZ,eAAc;EACd,gBAAe;EACf,eAAY;YAEZ,oBAAC,QAAD,EAAM,GAAE,iBAAkB,CAAA;EACtB,CAAA;;AAIV,MAAa,+BAAqD;CAChE,YAAY;CACZ,aAAa;CACb,YAAY;EACV;GAAE,IAAI;GAAW,OAAO;GAAW;EACnC;GAAE,IAAI;GAAY,OAAO;GAAY;EACrC;GAAE,IAAI;GAAQ,OAAO;GAAQ;EAC9B;CACD,uBAAuB,CAAC,SAAS;CACjC,QAAQ;EAEN;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aACE;GACF,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EAGF,iBAAiB;GACf,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aACE;GACF,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;EACD,iBAAiB;GACf,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EAGF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;IAAE,UAAU;IAAU,YAAY;IAAQ;GACxD,SAAS;IACP,iBAAiB;IACjB,mBAAmB;IACpB;GACD,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,cAAc;IAAC;IAAM;IAAO;IAAI;GAChC,aAAa;GACb,WAAW;IAAE,IAAI;IAAI,KAAK;IAAG,KAAK;IAAI;GACtC,WAAW;IAAE,IAAI;IAAM,KAAK;IAAI,KAAK;IAAK;GAC1C,YAAY;IAAE,IAAI;IAAI,KAAK;IAAG,KAAK;IAAG;GACtC,KAAK;GACL,OAAO;GACR;EAGD,eAAe;GACb,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;EACD,qBAAqB;GACnB,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,gBAAgB;GACd,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,SAAS,CACP;IAAE,OAAO;IAAS,OAAO;IAAS,EAClC;IAAE,OAAO;IAAY,OAAO;IAAY,CACzC;GACD,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,MAAM;GACN,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EACF,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,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;GACF;EACF;CACF"}
1
+ {"version":3,"file":"CarouselWidget-p8Z6L-G5.mjs","names":["DOMPurify"],"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\";\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};\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 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 const handleMouseEnter = useCallback(() => setIsHovered(true), []);\n const handleMouseLeave = useCallback(() => setIsHovered(false), []);\n const handleFocus = useCallback(() => setIsFocused(true), []);\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 handleMouseEnter,\n handleMouseLeave,\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 handleMouseEnter,\n handleMouseLeave,\n handleFocus,\n handleBlur,\n } = useCarouselController({\n slideCount: totalSlides,\n enableAutoScroll,\n autoScrollInterval,\n });\n\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\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 onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\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 // 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 return (\n <div\n key={slide.id}\n className=\"absolute inset-0 transition-opacity duration-700 ease-out\"\n style={{\n opacity: isActive ? 1 : 0,\n pointerEvents: isActive ? \"auto\" : \"none\",\n }}\n aria-hidden={!isActive}\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 <div\n className={`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: padding * 4 + (totalSlides > 1 ? 24 : 0),\n }}\n >\n <div\n key={`content-${currentIndex}`}\n className={`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 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 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 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 className=\"pointer-events-auto absolute inset-x-0 bottom-0 flex items-center gap-1 px-6 pb-2 sm:px-10\">\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 === \"done\") return { width: \"100%\" };\n if (state === \"upcoming\") return { width: \"0%\" };\n if (autoScroll) {\n return {\n width: \"0%\",\n animation: `fluidCarouselProgressFill ${duration}ms linear forwards`,\n animationPlayState: paused ? \"paused\" : \"running\",\n };\n }\n return { width: \"100%\" };\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: \"Display the primary CTA in slide content\",\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: \"\",\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 ],\n },\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,SAAS,CACP;IAAE,OAAO;IAAS,OAAO;IAAS,EAClC;IAAE,OAAO;IAAY,OAAO;IAAY,CACzC;GACD,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,MAAM;GACN,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EACF,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,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;GACF;EACF;CACF"}
@@ -1,5 +1,5 @@
1
1
  import { r as __exportAll } from "./es-BXxGlAp6.mjs";
2
- import { n as useDataSourceRegistryConfig } from "./registry-context-BDH0vNHR.mjs";
2
+ import { n as useDataSourceRegistryConfig } from "./registry-context-BahYMRqn.mjs";
3
3
  import { i as useWidgetsApi, n as useWidgetPreviewContext, t as ErrorState } from "./error-state-DYzHx8tt.mjs";
4
4
  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-Ct8o2YRe.mjs";
5
5
  import { useQuery } from "@tanstack/react-query";
@@ -241,4 +241,4 @@ const catchUpWidgetPropertySchema = {
241
241
  //#endregion
242
242
  export { CatchUpWidget_exports as n, catchUpWidgetPropertySchema as r, CatchUpWidget as t };
243
243
 
244
- //# sourceMappingURL=CatchUpWidget-BQjtjcGR.mjs.map
244
+ //# sourceMappingURL=CatchUpWidget-B9DQlzd_.mjs.map