@fluid-app/portal-sdk 0.1.239 → 0.1.241

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 (83) hide show
  1. package/dist/{CalendarWidget-BXxNxHDV.mjs → CalendarWidget-C03VcDLQ.mjs} +2 -2
  2. package/dist/{CalendarWidget-BXxNxHDV.mjs.map → CalendarWidget-C03VcDLQ.mjs.map} +1 -1
  3. package/dist/{CalendarWidget-VjQXZW8B.cjs → CalendarWidget-C4Dv_TUk.cjs} +2 -2
  4. package/dist/{CalendarWidget-VjQXZW8B.cjs.map → CalendarWidget-C4Dv_TUk.cjs.map} +1 -1
  5. package/dist/{CardWidget-BNkMlxQ3.mjs → CardWidget-2wcjCf2M.mjs} +2 -2
  6. package/dist/{CardWidget-BNkMlxQ3.mjs.map → CardWidget-2wcjCf2M.mjs.map} +1 -1
  7. package/dist/{CardWidget-CraWMttj.cjs → CardWidget-BQl-8Xrt.cjs} +3 -3
  8. package/dist/{CardWidget-C3I9OwgS.cjs → CardWidget-D-KEikO_.cjs} +2 -2
  9. package/dist/{CardWidget-C3I9OwgS.cjs.map → CardWidget-D-KEikO_.cjs.map} +1 -1
  10. package/dist/{CarouselWidget-p8Z6L-G5.mjs → CarouselWidget-Cn5P4FVN.mjs} +92 -83
  11. package/dist/CarouselWidget-Cn5P4FVN.mjs.map +1 -0
  12. package/dist/{CarouselWidget-CiKlooUF.cjs → CarouselWidget-Cu1b3ERq.cjs} +92 -83
  13. package/dist/CarouselWidget-Cu1b3ERq.cjs.map +1 -0
  14. package/dist/{CatchUpWidget-B9DQlzd_.mjs → CatchUpWidget-B9CI7lq0.mjs} +2 -2
  15. package/dist/{CatchUpWidget-B9DQlzd_.mjs.map → CatchUpWidget-B9CI7lq0.mjs.map} +1 -1
  16. package/dist/{CatchUpWidget-SY7hOHk6.cjs → CatchUpWidget-BzgybvuC.cjs} +2 -2
  17. package/dist/{CatchUpWidget-SY7hOHk6.cjs.map → CatchUpWidget-BzgybvuC.cjs.map} +1 -1
  18. package/dist/ContainerWidget-CDbB8c0E.cjs +8 -0
  19. package/dist/{ContainerWidget-CpwvcxFm.mjs → ContainerWidget-DNenbORS.mjs} +2 -2
  20. package/dist/{ContainerWidget-CpwvcxFm.mjs.map → ContainerWidget-DNenbORS.mjs.map} +1 -1
  21. package/dist/{ContainerWidget-BXpdj06u.cjs → ContainerWidget-DbAhQKbY.cjs} +2 -2
  22. package/dist/{ContainerWidget-BXpdj06u.cjs.map → ContainerWidget-DbAhQKbY.cjs.map} +1 -1
  23. package/dist/{FluidProvider-DL5rChtj.mjs → FluidProvider-BwMwMCxW.mjs} +23 -23
  24. package/dist/{FluidProvider-DL5rChtj.mjs.map → FluidProvider-BwMwMCxW.mjs.map} +1 -1
  25. package/dist/{FluidProvider-D_PHVlUU.cjs → FluidProvider-eT4gA6Io.cjs} +23 -23
  26. package/dist/{FluidProvider-D_PHVlUU.cjs.map → FluidProvider-eT4gA6Io.cjs.map} +1 -1
  27. package/dist/{LayoutWidget-BIfNHlVE.cjs → LayoutWidget-Bt2I2XMy.cjs} +2 -2
  28. package/dist/{LayoutWidget-BIfNHlVE.cjs.map → LayoutWidget-Bt2I2XMy.cjs.map} +1 -1
  29. package/dist/{LayoutWidget-LdF_cKrB.cjs → LayoutWidget-DKqZgCMu.cjs} +3 -3
  30. package/dist/{LayoutWidget-CC3oK78H.mjs → LayoutWidget-UI5fbsx4.mjs} +2 -2
  31. package/dist/{LayoutWidget-CC3oK78H.mjs.map → LayoutWidget-UI5fbsx4.mjs.map} +1 -1
  32. package/dist/{MessagingScreen-Dxy2VQbO.cjs → MessagingScreen-BHYX1Kc6.cjs} +14 -14
  33. package/dist/{MessagingScreen-mt1u3Bs1.mjs → MessagingScreen-CZddjqma.mjs} +2 -2
  34. package/dist/{MessagingScreen-mt1u3Bs1.mjs.map → MessagingScreen-CZddjqma.mjs.map} +1 -1
  35. package/dist/{MessagingScreen-Dkh3Dsp7.cjs → MessagingScreen-D3S230Ba.cjs} +2 -2
  36. package/dist/{MessagingScreen-Dkh3Dsp7.cjs.map → MessagingScreen-D3S230Ba.cjs.map} +1 -1
  37. package/dist/{MySiteWidget-BnjPrQxE.mjs → MySiteWidget-CQNASVaF.mjs} +2 -2
  38. package/dist/{MySiteWidget-BnjPrQxE.mjs.map → MySiteWidget-CQNASVaF.mjs.map} +1 -1
  39. package/dist/{MySiteWidget-C8eFWHOT.cjs → MySiteWidget-CYiH2lmX.cjs} +2 -2
  40. package/dist/{MySiteWidget-C8eFWHOT.cjs.map → MySiteWidget-CYiH2lmX.cjs.map} +1 -1
  41. package/dist/{PointsWidget-C2KB4k48.mjs → PointsWidget-BwA6aGVZ.mjs} +5 -8
  42. package/dist/PointsWidget-BwA6aGVZ.mjs.map +1 -0
  43. package/dist/{PointsWidget-DLp-PYus.cjs → PointsWidget-D1FV8l1h.cjs} +5 -8
  44. package/dist/PointsWidget-D1FV8l1h.cjs.map +1 -0
  45. package/dist/{ProfileScreen-ChCZZ91o.cjs → ProfileScreen-BYJj4D1W.cjs} +14 -14
  46. package/dist/{ProfileScreen-BMe-dQi7.cjs → ProfileScreen-DAujb81k.cjs} +2 -2
  47. package/dist/{ProfileScreen-BMe-dQi7.cjs.map → ProfileScreen-DAujb81k.cjs.map} +1 -1
  48. package/dist/{ProfileScreen-_1GlBr7z.mjs → ProfileScreen-DlMEqXXg.mjs} +2 -2
  49. package/dist/{ProfileScreen-_1GlBr7z.mjs.map → ProfileScreen-DlMEqXXg.mjs.map} +1 -1
  50. package/dist/{RecentActivityWidget-DelPdiwR.mjs → RecentActivityWidget-D1AlZgfV.mjs} +2 -2
  51. package/dist/{RecentActivityWidget-DelPdiwR.mjs.map → RecentActivityWidget-D1AlZgfV.mjs.map} +1 -1
  52. package/dist/{RecentActivityWidget-BNW9aFT4.cjs → RecentActivityWidget-DNyhUZNs.cjs} +2 -2
  53. package/dist/{RecentActivityWidget-BNW9aFT4.cjs.map → RecentActivityWidget-DNyhUZNs.cjs.map} +1 -1
  54. package/dist/{ScreenRenderer-ClYgfQf_.mjs → ScreenRenderer-Cl2aAJ7D.mjs} +2 -2
  55. package/dist/{ScreenRenderer-ClYgfQf_.mjs.map → ScreenRenderer-Cl2aAJ7D.mjs.map} +1 -1
  56. package/dist/{ScreenRenderer-Ct1w4PNu.cjs → ScreenRenderer-xH01YkEQ.cjs} +2 -2
  57. package/dist/{ScreenRenderer-Ct1w4PNu.cjs.map → ScreenRenderer-xH01YkEQ.cjs.map} +1 -1
  58. package/dist/{ShopScreen-DWLGH2gt.cjs → ShopScreen-1yvcCk7l.cjs} +6 -2
  59. package/dist/ShopScreen-1yvcCk7l.cjs.map +1 -0
  60. package/dist/{ShopScreen-CZ_290EP.cjs → ShopScreen-6nEKrNjK.cjs} +14 -14
  61. package/dist/{ShopScreen-BBfOte5o.mjs → ShopScreen-U7G6Jf67.mjs} +6 -2
  62. package/dist/ShopScreen-U7G6Jf67.mjs.map +1 -0
  63. package/dist/{ToDoWidget-CYDsZA0Z.mjs → ToDoWidget-BciI_D70.mjs} +2 -2
  64. package/dist/{ToDoWidget-CYDsZA0Z.mjs.map → ToDoWidget-BciI_D70.mjs.map} +1 -1
  65. package/dist/{ToDoWidget-Bjoan2Rm.cjs → ToDoWidget-OxT9z59F.cjs} +2 -2
  66. package/dist/{ToDoWidget-Bjoan2Rm.cjs.map → ToDoWidget-OxT9z59F.cjs.map} +1 -1
  67. package/dist/{ToDoWidget-C_CvWdLi.cjs → ToDoWidget-mSGQgnu3.cjs} +2 -2
  68. package/dist/index.cjs +22 -22
  69. package/dist/index.d.cts.map +1 -1
  70. package/dist/index.d.mts.map +1 -1
  71. package/dist/index.mjs +22 -22
  72. package/dist/{registry-context-BahYMRqn.mjs → registry-context-CTHUCfEc.mjs} +6 -5
  73. package/dist/{registry-context-bf52ZIJX.cjs.map → registry-context-CTHUCfEc.mjs.map} +1 -1
  74. package/dist/{registry-context-bf52ZIJX.cjs → registry-context-CcZYS15Q.cjs} +6 -5
  75. package/dist/{registry-context-BahYMRqn.mjs.map → registry-context-CcZYS15Q.cjs.map} +1 -1
  76. package/package.json +10 -10
  77. package/dist/CarouselWidget-CiKlooUF.cjs.map +0 -1
  78. package/dist/CarouselWidget-p8Z6L-G5.mjs.map +0 -1
  79. package/dist/ContainerWidget-CyfPYEAv.cjs +0 -8
  80. package/dist/PointsWidget-C2KB4k48.mjs.map +0 -1
  81. package/dist/PointsWidget-DLp-PYus.cjs.map +0 -1
  82. package/dist/ShopScreen-BBfOte5o.mjs.map +0 -1
  83. package/dist/ShopScreen-DWLGH2gt.cjs.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluid-app/portal-sdk",
3
- "version": "0.1.239",
3
+ "version": "0.1.241",
4
4
  "description": "SDK for building custom Fluid portals",
5
5
  "files": [
6
6
  "dist",
@@ -72,50 +72,50 @@
72
72
  "typescript": "^5",
73
73
  "zod": "4.3.5",
74
74
  "@fluid-app/api-client-core": "0.1.0",
75
+ "@fluid-app/cart-ui": "0.1.17",
75
76
  "@fluid-app/auth": "0.1.0",
76
77
  "@fluid-app/company-switcher-core": "0.1.0",
77
- "@fluid-app/cart-ui": "0.1.17",
78
78
  "@fluid-app/company-switcher-ui": "0.1.0",
79
- "@fluid-app/contacts-core": "0.1.0",
80
79
  "@fluid-app/contacts-ui": "0.1.0",
80
+ "@fluid-app/contacts-core": "0.1.0",
81
81
  "@fluid-app/file-picker-api-client": "0.1.0",
82
82
  "@fluid-app/file-picker-core": "0.1.0",
83
+ "@fluid-app/fluid-pay-core": "0.1.0",
83
84
  "@fluid-app/fluidos-api-client": "0.1.0",
84
85
  "@fluid-app/messaging-api-client": "0.1.0",
85
86
  "@fluid-app/messaging-core": "0.1.0",
86
87
  "@fluid-app/messaging-ui": "0.1.0",
87
88
  "@fluid-app/mysite-core": "0.1.0",
88
89
  "@fluid-app/mysite-ui": "0.1.0",
89
- "@fluid-app/fluid-pay-core": "0.1.0",
90
90
  "@fluid-app/orders-core": "0.1.0",
91
91
  "@fluid-app/orders-ui": "0.1.0",
92
92
  "@fluid-app/portal-app-download-ui": "0.1.0",
93
93
  "@fluid-app/permissions": "0.1.0",
94
+ "@fluid-app/portal-pro-upgrade-ui": "0.1.0",
94
95
  "@fluid-app/portal-core": "0.1.23",
95
96
  "@fluid-app/portal-preview": "0.1.0",
96
- "@fluid-app/portal-pro-upgrade-ui": "0.1.0",
97
- "@fluid-app/portal-tenant-api-client": "0.1.0",
98
97
  "@fluid-app/portal-react": "0.1.0",
98
+ "@fluid-app/portal-tenant-api-client": "0.1.0",
99
99
  "@fluid-app/portal-tenant-contacts-api-client": "0.1.0",
100
100
  "@fluid-app/portal-tenant-content-api-client": "0.1.0",
101
101
  "@fluid-app/portal-tenant-mysite-api-client": "0.1.0",
102
- "@fluid-app/portal-tenant-store-api-client": "0.1.0",
103
102
  "@fluid-app/portal-widgets": "0.1.22",
104
103
  "@fluid-app/portal-tenant-pay-api-client": "0.1.0",
105
104
  "@fluid-app/products-api-client": "0.1.0",
105
+ "@fluid-app/portal-tenant-store-api-client": "0.1.0",
106
106
  "@fluid-app/products-core": "0.1.0",
107
107
  "@fluid-app/profile-core": "0.1.0",
108
108
  "@fluid-app/profile-ui": "0.1.0",
109
+ "@fluid-app/shareables-ui": "0.1.0",
109
110
  "@fluid-app/query-persister": "0.1.0",
110
111
  "@fluid-app/shareables-core": "0.1.0",
111
- "@fluid-app/shareables-ui": "0.1.0",
112
112
  "@fluid-app/shop-ui": "0.1.0",
113
113
  "@fluid-app/store-api-client": "0.1.0",
114
114
  "@fluid-app/subscriptions-core": "0.1.0",
115
115
  "@fluid-app/store-core": "0.1.0",
116
- "@fluid-app/subscriptions-ui": "0.1.0",
116
+ "@fluid-app/typescript-config": "0.0.0",
117
117
  "@fluid-app/ui-primitives": "0.1.13",
118
- "@fluid-app/typescript-config": "0.0.0"
118
+ "@fluid-app/subscriptions-ui": "0.1.0"
119
119
  },
120
120
  "peerDependencies": {
121
121
  "@hookform/resolvers": "^5.2.2",
@@ -1 +0,0 @@
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 +0,0 @@
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,8 +0,0 @@
1
- require("./chunk-9hOWP6kD.cjs");
2
- require("./ScreenRenderer-Ct1w4PNu.cjs");
3
- require("./registry-context-bf52ZIJX.cjs");
4
- require("./LayoutWidget-BIfNHlVE.cjs");
5
- require("./registries-DBb6VjAX.cjs");
6
- require("./fields-COJ84ouS.cjs");
7
- const require_ContainerWidget = require("./ContainerWidget-BXpdj06u.cjs");
8
- exports.containerWidgetPropertySchema = require_ContainerWidget.containerWidgetPropertySchema;
@@ -1 +0,0 @@
1
- {"version":3,"file":"PointsWidget-C2KB4k48.mjs","names":[],"sources":["../../widgets/src/hooks/use-points-ledger.preview.ts","../../widgets/src/hooks/use-points-ledger.ts","../../widgets/src/widgets/PointsWidget.tsx"],"sourcesContent":["import type { PointsData } from \"@fluid-app/portal-core/widgets-api-types\";\n\nconst now = new Date();\n\nfunction daysAgo(days: number): string {\n return new Date(now.getTime() - days * 86_400_000).toISOString();\n}\n\nexport const PREVIEW_DATA: PointsData = {\n balance: 25,\n entries: [\n {\n id: 1,\n description: \"Purchase March 3rd\",\n amount: 20,\n createdAt: daysAgo(3),\n },\n {\n id: 2,\n description: \"Referral Bonus\",\n amount: 50,\n createdAt: daysAgo(14),\n },\n {\n id: 3,\n description: \"Points Redemption\",\n amount: -75,\n createdAt: daysAgo(60),\n },\n {\n id: 4,\n description: \"Welcome Reward\",\n amount: 30,\n createdAt: daysAgo(90),\n },\n ],\n};\n","import { useQuery, type UseQueryResult } from \"@tanstack/react-query\";\nimport { useWidgetsApi } from \"@fluid-app/portal-core/widgets-api-context\";\nimport { useWidgetPreviewContext } from \"@fluid-app/portal-react/data-sources/preview-context\";\nimport { useDataSourceRegistryConfig } from \"@fluid-app/portal-react/data-sources/registry-context\";\nimport { PREVIEW_DATA } from \"./use-points-ledger.preview\";\nimport type { PointsData } from \"@fluid-app/portal-core/widgets-api-types\";\n\nexport type {\n PointsData,\n PointsEntry,\n} from \"@fluid-app/portal-core/widgets-api-types\";\n\nexport const POINTS_LEDGER_QUERY_KEY = \"points-ledger\" as const;\n\nexport function usePointsLedger(): UseQueryResult<PointsData, Error> {\n const widgetsApi = useWidgetsApi();\n const { isPreview } = useWidgetPreviewContext();\n const registryConfig = useDataSourceRegistryConfig();\n const { baseUrl } = registryConfig;\n const customerId = registryConfig.variables?.customer_id;\n\n return useQuery({\n queryKey: [\n \"portal-widget-use\",\n POINTS_LEDGER_QUERY_KEY,\n isPreview ? \"preview\" : baseUrl,\n customerId,\n ] as const,\n queryFn: ({ signal }) => {\n if (!customerId) throw new Error(\"customerId is required\");\n return widgetsApi.fetchPointsLedger(customerId, signal);\n },\n enabled: !isPreview && !!customerId,\n ...(isPreview && { placeholderData: PREVIEW_DATA }),\n });\n}\n","import { useId, useState, type ComponentProps } from \"react\";\nimport type React from \"react\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n borderWidthClasses,\n borderColorClasses,\n} from \"../core/fields\";\nimport { usePointsLedger, type PointsEntry } from \"../hooks/use-points-ledger\";\nimport { ErrorState } from \"../components/error-state\";\nimport { ChevronDown, Coins } from \"lucide-react\";\n\nconst formatRelativeTime = (dateString: string): string => {\n const now = new Date();\n const date = new Date(dateString);\n const diffMs = now.getTime() - date.getTime();\n const diffDays = Math.floor(diffMs / 86_400_000);\n\n if (diffDays < 1) return \"Today\";\n if (diffDays === 1) return \"1 day ago\";\n if (diffDays < 7) return `${diffDays} days ago`;\n if (diffDays < 14) return \"1 week ago\";\n if (diffDays < 30) return `${Math.floor(diffDays / 7)} weeks ago`;\n if (diffDays < 60) return \"1 month ago\";\n return `${Math.floor(diffDays / 30)} months ago`;\n};\n\nconst formatBalance = (balance: number): string => {\n return balance.toLocaleString(\"en-US\");\n};\n\ntype PointsWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n title?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Balance\n balanceColor?: ColorOptions;\n\n // History\n historyEnabled?: boolean;\n historyTitle?: string;\n\n // Styling\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n};\n\nfunction PointsEntryRow({\n entry,\n textColor,\n accentColor,\n}: {\n entry: PointsEntry;\n textColor: ColorOptions;\n accentColor: ColorOptions;\n}) {\n const sign = entry.amount >= 0 ? \"+\" : \"-\";\n return (\n <div className=\"flex w-full items-center gap-3\">\n <div className=\"min-w-0 flex-1\">\n <p className={`text-sm text-${textColor} truncate`}>\n {entry.description}\n </p>\n <p className={`text-[10px] text-${textColor} leading-tight opacity-70`}>\n {formatRelativeTime(entry.createdAt)}\n </p>\n </div>\n <div className={`bg-${accentColor}/20 shrink-0 rounded-md px-1.5`}>\n <span className={`text-xs font-medium text-${accentColor} opacity-70`}>\n {sign}\n {Math.abs(entry.amount).toLocaleString(\"en-US\")}pts\n </span>\n </div>\n </div>\n );\n}\n\nexport function PointsWidget({\n // Title\n titleEnabled = true,\n title = \"Points\",\n titleFontSize = \"md\",\n titleColor = \"foreground\",\n\n // Balance\n balanceColor = \"primary\",\n\n // History\n historyEnabled = true,\n historyTitle = \"History\",\n\n // Styling\n background = { type: \"solid\", color: \"background\" },\n textColor = \"foreground\",\n accentColor = \"primary\",\n padding = 4,\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n\n className,\n ...props\n}: PointsWidgetProps): React.JSX.Element {\n const [historyOpen, setHistoryOpen] = useState(false);\n const historyPanelId = useId();\n\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 { data, isLoading, isError } = usePointsLedger();\n\n return (\n <div\n className={`@container overflow-hidden rounded-${borderRadius} bg-${backgroundColor} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${className ?? \"\"}`}\n style={{ backgroundImage }}\n {...props}\n >\n <div className={`p-${padding} flex flex-col gap-2.5`}>\n {/* Header: Title + Balance */}\n {titleEnabled && (\n <h2\n className={`text-${titleFontSize} font-header font-bold text-${titleColor}`}\n >\n {title}\n </h2>\n )}\n {!isLoading && data && (\n <span\n className={`text-3xl font-semibold text-${balanceColor} font-header leading-snug`}\n >\n {formatBalance(data.balance)}\n </span>\n )}\n\n {/* Loading */}\n {isLoading ? (\n <div className=\"flex min-h-[60px] items-center justify-center\">\n <div className=\"h-8 w-8 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n </div>\n ) : isError ? (\n <ErrorState />\n ) : historyEnabled && (!data || data.entries.length === 0) ? (\n /* Empty state — only shown when history is enabled but no entries */\n <div className=\"flex min-h-[60px] flex-col items-center justify-center gap-2\">\n <Coins className={`size-10 text-${textColor} opacity-30`} />\n <p className={`text-sm font-semibold text-${textColor} opacity-50`}>\n No Points Activity\n </p>\n </div>\n ) : historyEnabled && data && data.entries.length > 0 ? (\n /* History dropdown */\n <div className=\"flex flex-col gap-2\">\n {/* Dropdown toggle */}\n <button\n type=\"button\"\n aria-expanded={historyOpen}\n aria-controls={historyPanelId}\n onClick={() => setHistoryOpen((prev) => !prev)}\n className={`flex w-full items-center text-xs font-semibold text-${textColor} cursor-pointer`}\n >\n <span className=\"flex-1 text-left\">{historyTitle}</span>\n <ChevronDown\n className={`size-4 transition-transform duration-200 ${historyOpen ? \"rotate-180\" : \"\"}`}\n />\n </button>\n <div className={`bg-${textColor}/20 h-px w-full`} />\n\n {/* Collapsible entries */}\n <div\n id={historyPanelId}\n className={`flex flex-col gap-3 ${!historyOpen ? \"hidden\" : \"\"}`}\n >\n {data.entries.map((entry) => (\n <PointsEntryRow\n key={entry.id}\n entry={entry}\n textColor={textColor}\n accentColor={accentColor}\n />\n ))}\n </div>\n </div>\n ) : null}\n </div>\n </div>\n );\n}\n\nexport const pointsWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"PointsWidget\",\n displayName: \"Points\",\n fields: [\n // Title group\n {\n key: \"titleEnabled\",\n label: \"Show Title\",\n type: \"boolean\",\n description: \"Toggle title visibility\",\n defaultValue: true,\n\n group: \"Title\",\n },\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"Title text displayed above the balance\",\n defaultValue: \"Points\",\n\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the title\",\n defaultValue: \"md\",\n\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the title\",\n defaultValue: \"foreground\",\n\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Balance group\n getColorField({\n key: \"balanceColor\",\n label: \"Balance Color\",\n description: \"Color for the points balance number\",\n defaultValue: \"primary\",\n\n group: \"Balance\",\n }),\n\n // History group\n {\n key: \"historyEnabled\",\n label: \"Show History\",\n type: \"boolean\",\n description: \"Show a collapsible history dropdown below the balance\",\n defaultValue: true,\n\n group: \"History\",\n },\n {\n key: \"historyTitle\",\n label: \"History Title\",\n type: \"text\",\n description: \"Title for the history dropdown\",\n defaultValue: \"History\",\n\n group: \"History\",\n requiresKeyToBeTrue: \"historyEnabled\",\n },\n\n // Design group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the widget\",\n defaultValue: \"background\",\n\n group: \"Design\",\n },\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color\",\n defaultValue: \"foreground\",\n\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description: \"Color for points badges and highlights\",\n defaultValue: \"primary\",\n\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Widget padding\",\n defaultValue: 4,\n\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Widget border radius\",\n defaultValue: \"md\",\n\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Widget border width\",\n defaultValue: \"none\",\n\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Widget border color\",\n defaultValue: \"muted\",\n\n group: \"Design\",\n }),\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"PointsWidget-DLp-PYus.cjs","names":["useWidgetsApi","useWidgetPreviewContext","useDataSourceRegistryConfig","borderWidthClasses","borderColorClasses","ErrorState","Coins","ChevronDown","getFontSizeField","getColorField","getPaddingField","getBorderRadiusField","getBorderWidthField","getBorderColorField"],"sources":["../../widgets/src/hooks/use-points-ledger.preview.ts","../../widgets/src/hooks/use-points-ledger.ts","../../widgets/src/widgets/PointsWidget.tsx"],"sourcesContent":["import type { PointsData } from \"@fluid-app/portal-core/widgets-api-types\";\n\nconst now = new Date();\n\nfunction daysAgo(days: number): string {\n return new Date(now.getTime() - days * 86_400_000).toISOString();\n}\n\nexport const PREVIEW_DATA: PointsData = {\n balance: 25,\n entries: [\n {\n id: 1,\n description: \"Purchase March 3rd\",\n amount: 20,\n createdAt: daysAgo(3),\n },\n {\n id: 2,\n description: \"Referral Bonus\",\n amount: 50,\n createdAt: daysAgo(14),\n },\n {\n id: 3,\n description: \"Points Redemption\",\n amount: -75,\n createdAt: daysAgo(60),\n },\n {\n id: 4,\n description: \"Welcome Reward\",\n amount: 30,\n createdAt: daysAgo(90),\n },\n ],\n};\n","import { useQuery, type UseQueryResult } from \"@tanstack/react-query\";\nimport { useWidgetsApi } from \"@fluid-app/portal-core/widgets-api-context\";\nimport { useWidgetPreviewContext } from \"@fluid-app/portal-react/data-sources/preview-context\";\nimport { useDataSourceRegistryConfig } from \"@fluid-app/portal-react/data-sources/registry-context\";\nimport { PREVIEW_DATA } from \"./use-points-ledger.preview\";\nimport type { PointsData } from \"@fluid-app/portal-core/widgets-api-types\";\n\nexport type {\n PointsData,\n PointsEntry,\n} from \"@fluid-app/portal-core/widgets-api-types\";\n\nexport const POINTS_LEDGER_QUERY_KEY = \"points-ledger\" as const;\n\nexport function usePointsLedger(): UseQueryResult<PointsData, Error> {\n const widgetsApi = useWidgetsApi();\n const { isPreview } = useWidgetPreviewContext();\n const registryConfig = useDataSourceRegistryConfig();\n const { baseUrl } = registryConfig;\n const customerId = registryConfig.variables?.customer_id;\n\n return useQuery({\n queryKey: [\n \"portal-widget-use\",\n POINTS_LEDGER_QUERY_KEY,\n isPreview ? \"preview\" : baseUrl,\n customerId,\n ] as const,\n queryFn: ({ signal }) => {\n if (!customerId) throw new Error(\"customerId is required\");\n return widgetsApi.fetchPointsLedger(customerId, signal);\n },\n enabled: !isPreview && !!customerId,\n ...(isPreview && { placeholderData: PREVIEW_DATA }),\n });\n}\n","import { useId, useState, type ComponentProps } from \"react\";\nimport type React from \"react\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n borderWidthClasses,\n borderColorClasses,\n} from \"../core/fields\";\nimport { usePointsLedger, type PointsEntry } from \"../hooks/use-points-ledger\";\nimport { ErrorState } from \"../components/error-state\";\nimport { ChevronDown, Coins } from \"lucide-react\";\n\nconst formatRelativeTime = (dateString: string): string => {\n const now = new Date();\n const date = new Date(dateString);\n const diffMs = now.getTime() - date.getTime();\n const diffDays = Math.floor(diffMs / 86_400_000);\n\n if (diffDays < 1) return \"Today\";\n if (diffDays === 1) return \"1 day ago\";\n if (diffDays < 7) return `${diffDays} days ago`;\n if (diffDays < 14) return \"1 week ago\";\n if (diffDays < 30) return `${Math.floor(diffDays / 7)} weeks ago`;\n if (diffDays < 60) return \"1 month ago\";\n return `${Math.floor(diffDays / 30)} months ago`;\n};\n\nconst formatBalance = (balance: number): string => {\n return balance.toLocaleString(\"en-US\");\n};\n\ntype PointsWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n title?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Balance\n balanceColor?: ColorOptions;\n\n // History\n historyEnabled?: boolean;\n historyTitle?: string;\n\n // Styling\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n};\n\nfunction PointsEntryRow({\n entry,\n textColor,\n accentColor,\n}: {\n entry: PointsEntry;\n textColor: ColorOptions;\n accentColor: ColorOptions;\n}) {\n const sign = entry.amount >= 0 ? \"+\" : \"-\";\n return (\n <div className=\"flex w-full items-center gap-3\">\n <div className=\"min-w-0 flex-1\">\n <p className={`text-sm text-${textColor} truncate`}>\n {entry.description}\n </p>\n <p className={`text-[10px] text-${textColor} leading-tight opacity-70`}>\n {formatRelativeTime(entry.createdAt)}\n </p>\n </div>\n <div className={`bg-${accentColor}/20 shrink-0 rounded-md px-1.5`}>\n <span className={`text-xs font-medium text-${accentColor} opacity-70`}>\n {sign}\n {Math.abs(entry.amount).toLocaleString(\"en-US\")}pts\n </span>\n </div>\n </div>\n );\n}\n\nexport function PointsWidget({\n // Title\n titleEnabled = true,\n title = \"Points\",\n titleFontSize = \"md\",\n titleColor = \"foreground\",\n\n // Balance\n balanceColor = \"primary\",\n\n // History\n historyEnabled = true,\n historyTitle = \"History\",\n\n // Styling\n background = { type: \"solid\", color: \"background\" },\n textColor = \"foreground\",\n accentColor = \"primary\",\n padding = 4,\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n\n className,\n ...props\n}: PointsWidgetProps): React.JSX.Element {\n const [historyOpen, setHistoryOpen] = useState(false);\n const historyPanelId = useId();\n\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 { data, isLoading, isError } = usePointsLedger();\n\n return (\n <div\n className={`@container overflow-hidden rounded-${borderRadius} bg-${backgroundColor} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${className ?? \"\"}`}\n style={{ backgroundImage }}\n {...props}\n >\n <div className={`p-${padding} flex flex-col gap-2.5`}>\n {/* Header: Title + Balance */}\n {titleEnabled && (\n <h2\n className={`text-${titleFontSize} font-header font-bold text-${titleColor}`}\n >\n {title}\n </h2>\n )}\n {!isLoading && data && (\n <span\n className={`text-3xl font-semibold text-${balanceColor} font-header leading-snug`}\n >\n {formatBalance(data.balance)}\n </span>\n )}\n\n {/* Loading */}\n {isLoading ? (\n <div className=\"flex min-h-[60px] items-center justify-center\">\n <div className=\"h-8 w-8 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n </div>\n ) : isError ? (\n <ErrorState />\n ) : historyEnabled && (!data || data.entries.length === 0) ? (\n /* Empty state — only shown when history is enabled but no entries */\n <div className=\"flex min-h-[60px] flex-col items-center justify-center gap-2\">\n <Coins className={`size-10 text-${textColor} opacity-30`} />\n <p className={`text-sm font-semibold text-${textColor} opacity-50`}>\n No Points Activity\n </p>\n </div>\n ) : historyEnabled && data && data.entries.length > 0 ? (\n /* History dropdown */\n <div className=\"flex flex-col gap-2\">\n {/* Dropdown toggle */}\n <button\n type=\"button\"\n aria-expanded={historyOpen}\n aria-controls={historyPanelId}\n onClick={() => setHistoryOpen((prev) => !prev)}\n className={`flex w-full items-center text-xs font-semibold text-${textColor} cursor-pointer`}\n >\n <span className=\"flex-1 text-left\">{historyTitle}</span>\n <ChevronDown\n className={`size-4 transition-transform duration-200 ${historyOpen ? \"rotate-180\" : \"\"}`}\n />\n </button>\n <div className={`bg-${textColor}/20 h-px w-full`} />\n\n {/* Collapsible entries */}\n <div\n id={historyPanelId}\n className={`flex flex-col gap-3 ${!historyOpen ? \"hidden\" : \"\"}`}\n >\n {data.entries.map((entry) => (\n <PointsEntryRow\n key={entry.id}\n entry={entry}\n textColor={textColor}\n accentColor={accentColor}\n />\n ))}\n </div>\n </div>\n ) : null}\n </div>\n </div>\n );\n}\n\nexport const pointsWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"PointsWidget\",\n displayName: \"Points\",\n fields: [\n // Title group\n {\n key: \"titleEnabled\",\n label: \"Show Title\",\n type: \"boolean\",\n description: \"Toggle title visibility\",\n defaultValue: true,\n\n group: \"Title\",\n },\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"Title text displayed above the balance\",\n defaultValue: \"Points\",\n\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the title\",\n defaultValue: \"md\",\n\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the title\",\n defaultValue: \"foreground\",\n\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Balance group\n getColorField({\n key: \"balanceColor\",\n label: \"Balance Color\",\n description: \"Color for the points balance number\",\n defaultValue: \"primary\",\n\n group: \"Balance\",\n }),\n\n // History group\n {\n key: \"historyEnabled\",\n label: \"Show History\",\n type: \"boolean\",\n description: \"Show a collapsible history dropdown below the balance\",\n defaultValue: true,\n\n group: \"History\",\n },\n {\n key: \"historyTitle\",\n label: \"History Title\",\n type: \"text\",\n description: \"Title for the history dropdown\",\n defaultValue: \"History\",\n\n group: \"History\",\n requiresKeyToBeTrue: \"historyEnabled\",\n },\n\n // Design group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the widget\",\n defaultValue: \"background\",\n\n group: \"Design\",\n },\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color\",\n defaultValue: \"foreground\",\n\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description: \"Color for points badges and highlights\",\n defaultValue: \"primary\",\n\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Widget padding\",\n defaultValue: 4,\n\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Widget border radius\",\n defaultValue: \"md\",\n\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Widget border width\",\n defaultValue: \"none\",\n\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Widget border color\",\n defaultValue: \"muted\",\n\n group: \"Design\",\n }),\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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"}