@fluid-app/portal-sdk 0.1.259 → 0.1.261

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 (144) hide show
  1. package/dist/{AlertWidget-CcIBGBik.mjs → AlertWidget-Bua0I46v.mjs} +2 -2
  2. package/dist/{AlertWidget-CcIBGBik.mjs.map → AlertWidget-Bua0I46v.mjs.map} +1 -1
  3. package/dist/{AlertWidget-BZ67Uqfh.cjs → AlertWidget-ByokSA3K.cjs} +2 -2
  4. package/dist/{AlertWidget-BZ67Uqfh.cjs.map → AlertWidget-ByokSA3K.cjs.map} +1 -1
  5. package/dist/{BulletListWidget-iGJI33Ed.cjs → BulletListWidget-BwrMNPZ-.cjs} +2 -2
  6. package/dist/{BulletListWidget-iGJI33Ed.cjs.map → BulletListWidget-BwrMNPZ-.cjs.map} +1 -1
  7. package/dist/{BulletListWidget-mRwUgtzN.mjs → BulletListWidget-DvT2x5wg.mjs} +2 -2
  8. package/dist/{BulletListWidget-mRwUgtzN.mjs.map → BulletListWidget-DvT2x5wg.mjs.map} +1 -1
  9. package/dist/{CalendarWidget-ByY49yYX.mjs → CalendarWidget-BB1C5K_j.mjs} +2 -2
  10. package/dist/{CalendarWidget-ByY49yYX.mjs.map → CalendarWidget-BB1C5K_j.mjs.map} +1 -1
  11. package/dist/{CalendarWidget-CSipLdwg.cjs → CalendarWidget-MVJmxwFQ.cjs} +2 -2
  12. package/dist/{CalendarWidget-CSipLdwg.cjs.map → CalendarWidget-MVJmxwFQ.cjs.map} +1 -1
  13. package/dist/{CardWidget-CXsjl-Is.cjs → CardWidget-5hGl1bt9.cjs} +2 -2
  14. package/dist/{CardWidget-DK4VQau1.mjs → CardWidget-CEERBKUN.mjs} +2 -2
  15. package/dist/{CardWidget-DK4VQau1.mjs.map → CardWidget-CEERBKUN.mjs.map} +1 -1
  16. package/dist/{CardWidget-DovkTkKg.cjs → CardWidget-Cf4-dF-v.cjs} +2 -2
  17. package/dist/{CardWidget-DovkTkKg.cjs.map → CardWidget-Cf4-dF-v.cjs.map} +1 -1
  18. package/dist/{CarouselWidget-Cu1b3ERq.cjs → CarouselWidget-BJSO17JY.cjs} +2 -2
  19. package/dist/{CarouselWidget-Cu1b3ERq.cjs.map → CarouselWidget-BJSO17JY.cjs.map} +1 -1
  20. package/dist/{CarouselWidget-C0X-nFyW.mjs → CarouselWidget-Dhjf60LS.mjs} +2 -2
  21. package/dist/{CarouselWidget-C0X-nFyW.mjs.map → CarouselWidget-Dhjf60LS.mjs.map} +1 -1
  22. package/dist/{CatchUpWidget-C17xpj3Z.cjs → CatchUpWidget-CFF-Fgdo.cjs} +2 -2
  23. package/dist/{CatchUpWidget-C17xpj3Z.cjs.map → CatchUpWidget-CFF-Fgdo.cjs.map} +1 -1
  24. package/dist/{CatchUpWidget-Bj30ZbUk.mjs → CatchUpWidget-CM-iCMhK.mjs} +2 -2
  25. package/dist/{CatchUpWidget-Bj30ZbUk.mjs.map → CatchUpWidget-CM-iCMhK.mjs.map} +1 -1
  26. package/dist/{ChartWidget-Brxz8j4Q.cjs → ChartWidget-6nZLzlQM.cjs} +2 -2
  27. package/dist/{ChartWidget-Brxz8j4Q.cjs.map → ChartWidget-6nZLzlQM.cjs.map} +1 -1
  28. package/dist/{ChartWidget-CIscUHUD.mjs → ChartWidget-CJXZ9qf7.mjs} +2 -2
  29. package/dist/{ChartWidget-CIscUHUD.mjs.map → ChartWidget-CJXZ9qf7.mjs.map} +1 -1
  30. package/dist/{ChartWidget-CNhmJePK.cjs → ChartWidget-WXGJeXdl.cjs} +2 -2
  31. package/dist/{ContainerWidget-YMePQ1FG.mjs → ContainerWidget-2Rep2gGz.mjs} +3 -3
  32. package/dist/{ContainerWidget-YMePQ1FG.mjs.map → ContainerWidget-2Rep2gGz.mjs.map} +1 -1
  33. package/dist/{ContainerWidget-D5rr47AN.cjs → ContainerWidget-CpIynF1n.cjs} +3 -3
  34. package/dist/{ContainerWidget-wtuUrr1c.cjs → ContainerWidget-DX9qO1T-.cjs} +3 -3
  35. package/dist/{ContainerWidget-wtuUrr1c.cjs.map → ContainerWidget-DX9qO1T-.cjs.map} +1 -1
  36. package/dist/{EmbedWidget-DE1yhLR1.mjs → EmbedWidget-Czn_RJbm.mjs} +2 -2
  37. package/dist/{EmbedWidget-DE1yhLR1.mjs.map → EmbedWidget-Czn_RJbm.mjs.map} +1 -1
  38. package/dist/{EmbedWidget-BO0TonyK.cjs → EmbedWidget-DFlg5AI7.cjs} +2 -2
  39. package/dist/{EmbedWidget-BO0TonyK.cjs.map → EmbedWidget-DFlg5AI7.cjs.map} +1 -1
  40. package/dist/{FluidProvider-CDNk3Ssn.mjs → FluidProvider-C0YKxODs.mjs} +49 -49
  41. package/dist/{FluidProvider-CDNk3Ssn.mjs.map → FluidProvider-C0YKxODs.mjs.map} +1 -1
  42. package/dist/{FluidProvider-P_MBgI-c.cjs → FluidProvider-CoSgK0jL.cjs} +49 -49
  43. package/dist/{FluidProvider-P_MBgI-c.cjs.map → FluidProvider-CoSgK0jL.cjs.map} +1 -1
  44. package/dist/{ImageWidget-DmaAQZBK.mjs → ImageWidget--WJppfij.mjs} +2 -2
  45. package/dist/{ImageWidget-DmaAQZBK.mjs.map → ImageWidget--WJppfij.mjs.map} +1 -1
  46. package/dist/{ImageWidget-CbQVxMe3.cjs → ImageWidget-CU2cet5p.cjs} +2 -2
  47. package/dist/{ImageWidget-CbQVxMe3.cjs.map → ImageWidget-CU2cet5p.cjs.map} +1 -1
  48. package/dist/{LayoutWidget-BK8AxE60.cjs → LayoutWidget-8DwDBW24.cjs} +2 -2
  49. package/dist/{LayoutWidget-BK8AxE60.cjs.map → LayoutWidget-8DwDBW24.cjs.map} +1 -1
  50. package/dist/{LayoutWidget-K2iF13-C.cjs → LayoutWidget-CUjv-pB1.cjs} +2 -2
  51. package/dist/{LayoutWidget-8KxCmJcd.mjs → LayoutWidget-iKNNIRPq.mjs} +2 -2
  52. package/dist/{LayoutWidget-8KxCmJcd.mjs.map → LayoutWidget-iKNNIRPq.mjs.map} +1 -1
  53. package/dist/{LinkWidget-Dvb6WlaR.mjs → LinkWidget-BoVmB_zf.mjs} +2 -2
  54. package/dist/{LinkWidget-Dvb6WlaR.mjs.map → LinkWidget-BoVmB_zf.mjs.map} +1 -1
  55. package/dist/{LinkWidget-DnAGzdnF.cjs → LinkWidget-BzgMcUuV.cjs} +2 -2
  56. package/dist/{LinkWidget-88wWH7-i.cjs → LinkWidget-DpylGthu.cjs} +2 -2
  57. package/dist/{LinkWidget-88wWH7-i.cjs.map → LinkWidget-DpylGthu.cjs.map} +1 -1
  58. package/dist/{ListWidget-xetptWnX.cjs → ListWidget-CQgei8SF.cjs} +2 -2
  59. package/dist/{ListWidget-xetptWnX.cjs.map → ListWidget-CQgei8SF.cjs.map} +1 -1
  60. package/dist/{ListWidget-Bsi4jdcz.mjs → ListWidget-CuwsaMQ9.mjs} +2 -2
  61. package/dist/{ListWidget-Bsi4jdcz.mjs.map → ListWidget-CuwsaMQ9.mjs.map} +1 -1
  62. package/dist/{ListWidget-BzuYuJkf.cjs → ListWidget-TXPwy2v6.cjs} +2 -2
  63. package/dist/MessagingScreen-CKIs5m0_.cjs +48 -0
  64. package/dist/{MessagingScreen-SQXX6kkC.mjs → MessagingScreen-Ck6c7BK3.mjs} +2 -2
  65. package/dist/{MessagingScreen-SQXX6kkC.mjs.map → MessagingScreen-Ck6c7BK3.mjs.map} +1 -1
  66. package/dist/MessagingScreen-DgS_ZEzO.mjs +46 -0
  67. package/dist/{MessagingScreen-CsZsCnnX.cjs → MessagingScreen-ga_zEAeB.cjs} +2 -2
  68. package/dist/{MessagingScreen-CsZsCnnX.cjs.map → MessagingScreen-ga_zEAeB.cjs.map} +1 -1
  69. package/dist/{MySiteWidget-DXY59o3T.cjs → MySiteWidget-BziY8ylH.cjs} +2 -2
  70. package/dist/{MySiteWidget-DXY59o3T.cjs.map → MySiteWidget-BziY8ylH.cjs.map} +1 -1
  71. package/dist/{MySiteWidget-8XrZA0Un.mjs → MySiteWidget-CsJzjc7o.mjs} +2 -2
  72. package/dist/{MySiteWidget-8XrZA0Un.mjs.map → MySiteWidget-CsJzjc7o.mjs.map} +1 -1
  73. package/dist/{NestedWidget-CSA2gUPx.cjs → NestedWidget-B1Rwz6nb.cjs} +2 -2
  74. package/dist/{NestedWidget-B8lW9Fzv.mjs → NestedWidget-DrZ62oaO.mjs} +2 -2
  75. package/dist/{NestedWidget-B8lW9Fzv.mjs.map → NestedWidget-DrZ62oaO.mjs.map} +1 -1
  76. package/dist/{NestedWidget-C2D4eWqb.cjs → NestedWidget-vrohV65N.cjs} +2 -2
  77. package/dist/{NestedWidget-C2D4eWqb.cjs.map → NestedWidget-vrohV65N.cjs.map} +1 -1
  78. package/dist/{PointsWidget-ComTSNQZ.cjs → PointsWidget-DI3N8-6W.cjs} +2 -2
  79. package/dist/{PointsWidget-ComTSNQZ.cjs.map → PointsWidget-DI3N8-6W.cjs.map} +1 -1
  80. package/dist/{PointsWidget-CRvG5LOV.mjs → PointsWidget-ubAn0b-m.mjs} +2 -2
  81. package/dist/{PointsWidget-CRvG5LOV.mjs.map → PointsWidget-ubAn0b-m.mjs.map} +1 -1
  82. package/dist/ProfileScreen-90-Jf8IH.mjs +46 -0
  83. package/dist/ProfileScreen-B7sbMdbH.cjs +48 -0
  84. package/dist/{ProfileScreen-C6Z8g6-L.cjs → ProfileScreen-DYO-1rw4.cjs} +2 -2
  85. package/dist/{ProfileScreen-C6Z8g6-L.cjs.map → ProfileScreen-DYO-1rw4.cjs.map} +1 -1
  86. package/dist/{ProfileScreen-C45yTIj-.mjs → ProfileScreen-FG1DZum3.mjs} +2 -2
  87. package/dist/{ProfileScreen-C45yTIj-.mjs.map → ProfileScreen-FG1DZum3.mjs.map} +1 -1
  88. package/dist/{QuickLinksWidget-Bcl4CxfW.cjs → QuickLinksWidget-Cpq1V-uX.cjs} +2 -2
  89. package/dist/{QuickLinksWidget-Bcl4CxfW.cjs.map → QuickLinksWidget-Cpq1V-uX.cjs.map} +1 -1
  90. package/dist/{QuickLinksWidget-roBJQ1Ge.mjs → QuickLinksWidget-J5axodVF.mjs} +2 -2
  91. package/dist/{QuickLinksWidget-roBJQ1Ge.mjs.map → QuickLinksWidget-J5axodVF.mjs.map} +1 -1
  92. package/dist/{QuickShareWidget-D_Ghjgwz.cjs → QuickShareWidget-CYPOXs8X.cjs} +2 -2
  93. package/dist/{QuickShareWidget-D_Ghjgwz.cjs.map → QuickShareWidget-CYPOXs8X.cjs.map} +1 -1
  94. package/dist/{QuickShareWidget-D-NVbmfw.mjs → QuickShareWidget-CyYW9nS6.mjs} +2 -2
  95. package/dist/{QuickShareWidget-D-NVbmfw.mjs.map → QuickShareWidget-CyYW9nS6.mjs.map} +1 -1
  96. package/dist/{RecentActivityWidget-Bz54YXQN.mjs → RecentActivityWidget-CndO-Ac0.mjs} +2 -2
  97. package/dist/{RecentActivityWidget-Bz54YXQN.mjs.map → RecentActivityWidget-CndO-Ac0.mjs.map} +1 -1
  98. package/dist/{RecentActivityWidget-sv_3ewZa.cjs → RecentActivityWidget-Cp3fYBM2.cjs} +2 -2
  99. package/dist/{RecentActivityWidget-sv_3ewZa.cjs.map → RecentActivityWidget-Cp3fYBM2.cjs.map} +1 -1
  100. package/dist/{SeparatorWidget-CY6uMLHP.cjs → SeparatorWidget-DW_9_L9_.cjs} +2 -2
  101. package/dist/{SeparatorWidget-CY6uMLHP.cjs.map → SeparatorWidget-DW_9_L9_.cjs.map} +1 -1
  102. package/dist/{SeparatorWidget-DR75Yj_C.mjs → SeparatorWidget-eI7b2n6u.mjs} +2 -2
  103. package/dist/{SeparatorWidget-DR75Yj_C.mjs.map → SeparatorWidget-eI7b2n6u.mjs.map} +1 -1
  104. package/dist/{ShopScreen-C3PYT1v_.cjs → ShopScreen-BDhf2CmC.cjs} +2 -2
  105. package/dist/{ShopScreen-C3PYT1v_.cjs.map → ShopScreen-BDhf2CmC.cjs.map} +1 -1
  106. package/dist/ShopScreen-BgTi5eCl.cjs +49 -0
  107. package/dist/ShopScreen-BhYkCXLT.mjs +47 -0
  108. package/dist/{ShopScreen-BFKwuM2U.mjs → ShopScreen-D0p5rQD8.mjs} +2 -2
  109. package/dist/{ShopScreen-BFKwuM2U.mjs.map → ShopScreen-D0p5rQD8.mjs.map} +1 -1
  110. package/dist/{TableWidget-yky-XAA1.cjs → TableWidget-BORWeyOR.cjs} +2 -2
  111. package/dist/{TableWidget-CiI5pArP.cjs → TableWidget-CT6T3IgY.cjs} +2 -2
  112. package/dist/{TableWidget-CiI5pArP.cjs.map → TableWidget-CT6T3IgY.cjs.map} +1 -1
  113. package/dist/{TableWidget-C87Czlh6.mjs → TableWidget-D8HBHejy.mjs} +2 -2
  114. package/dist/{TableWidget-C87Czlh6.mjs.map → TableWidget-D8HBHejy.mjs.map} +1 -1
  115. package/dist/{TextWidget-C7oY0X3r.cjs → TextWidget-CMOofhaH.cjs} +2 -2
  116. package/dist/{TextWidget-C7oY0X3r.cjs.map → TextWidget-CMOofhaH.cjs.map} +1 -1
  117. package/dist/{TextWidget-CfLUQr6V.mjs → TextWidget-DSGevTKM.mjs} +2 -2
  118. package/dist/{TextWidget-CfLUQr6V.mjs.map → TextWidget-DSGevTKM.mjs.map} +1 -1
  119. package/dist/{ToDoWidget-BY-6VIxD.mjs → ToDoWidget-5IiWutYI.mjs} +2 -2
  120. package/dist/{ToDoWidget-BY-6VIxD.mjs.map → ToDoWidget-5IiWutYI.mjs.map} +1 -1
  121. package/dist/{ToDoWidget-CpO7jdw0.cjs → ToDoWidget-B97blWRO.cjs} +2 -2
  122. package/dist/{ToDoWidget-CpO7jdw0.cjs.map → ToDoWidget-B97blWRO.cjs.map} +1 -1
  123. package/dist/{ToDoWidget-CjY1i0lz.cjs → ToDoWidget-kn1dtlKi.cjs} +2 -2
  124. package/dist/{VideoWidget-DSPDdiYr.mjs → VideoWidget-BiaPF0-w.mjs} +2 -2
  125. package/dist/{VideoWidget-DSPDdiYr.mjs.map → VideoWidget-BiaPF0-w.mjs.map} +1 -1
  126. package/dist/{VideoWidget-BpEF3gRZ.cjs → VideoWidget-zdT_mVo9.cjs} +2 -2
  127. package/dist/{VideoWidget-BpEF3gRZ.cjs.map → VideoWidget-zdT_mVo9.cjs.map} +1 -1
  128. package/dist/index.cjs +42 -42
  129. package/dist/index.cjs.map +1 -1
  130. package/dist/index.mjs +42 -42
  131. package/dist/index.mjs.map +1 -1
  132. package/dist/{registries-kvRRUHcO.mjs → registries-6F90ZS1m.mjs} +10 -1
  133. package/dist/registries-6F90ZS1m.mjs.map +1 -0
  134. package/dist/{registries-DBb6VjAX.cjs → registries-CVsthTnW.cjs} +10 -1
  135. package/dist/registries-CVsthTnW.cjs.map +1 -0
  136. package/package.json +18 -18
  137. package/dist/MessagingScreen-J59IMCoQ.mjs +0 -46
  138. package/dist/MessagingScreen-Sur4umLF.cjs +0 -48
  139. package/dist/ProfileScreen-B1J74rK1.cjs +0 -48
  140. package/dist/ProfileScreen-BdmW4weg.mjs +0 -46
  141. package/dist/ShopScreen-C_8yLQjA.mjs +0 -47
  142. package/dist/ShopScreen-Cg_DoIMi.cjs +0 -49
  143. package/dist/registries-DBb6VjAX.cjs.map +0 -1
  144. package/dist/registries-kvRRUHcO.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"NestedWidget-B8lW9Fzv.mjs","names":[],"sources":["../../widgets/src/ui/scroll-arrows.tsx","../../widgets/src/widgets/NestedWidget.tsx"],"sourcesContent":["import type React from \"react\";\nimport { ChevronLeft, ChevronRight } from \"lucide-react\";\n\ntype ScrollArrowsProps = {\n onPrevious: () => void;\n onNext: () => void;\n};\n\nexport function ScrollArrows({\n onPrevious,\n onNext,\n}: ScrollArrowsProps): React.JSX.Element {\n return (\n <>\n <button\n type=\"button\"\n className=\"bg-foreground text-background flex h-6 w-6 items-center justify-center rounded-2xl opacity-70 transition-colors hover:opacity-50 disabled:opacity-30\"\n onClick={onPrevious}\n aria-label=\"Previous slide\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n </button>\n <button\n type=\"button\"\n className=\"bg-foreground text-background flex h-6 w-6 items-center justify-center rounded-2xl opacity-70 transition-colors hover:opacity-50 disabled:opacity-30\"\n onClick={onNext}\n aria-label=\"Next slide\"\n >\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </>\n );\n}\n","import { useRef, type ComponentProps } from \"react\";\nimport type React from \"react\";\nimport {\n MediaRenderer,\n getMediaPropsFromShareable,\n} from \"../components/MediaRenderer\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n AlignOptions,\n GapOptions,\n BackgroundValue,\n} from \"@fluid-app/portal-core/types\";\nimport {\n getHeightField,\n type WidgetPropertySchema,\n} from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n borderWidthClasses,\n borderColorClasses,\n getColorField,\n getFontSizeField,\n getGapField,\n getPaddingField,\n gapValues,\n} from \"../core/fields\";\nimport { ScrollArrows } from \"../ui/scroll-arrows\";\nimport { type ShareableItem } from \"@fluid-app/portal-core/types\";\nimport { useWidgetInteraction } from \"../contexts/WidgetInteractionContext\";\n\nconst DEFAULT_SHAREABLES: ShareableItem[] = [];\n\ntype NestedWidgetProps = ComponentProps<\"div\"> & {\n // Content\n resource?: ShareableItem;\n titleEnabled?: boolean;\n titleText?: string;\n shareables?: ShareableItem[];\n\n // Layout\n gap?: GapOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n primaryMediaHeight?: string;\n\n // Title styling\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n titleAlignment?: AlignOptions;\n\n // Nested media styling\n nestedTextColor?: ColorOptions;\n background?: BackgroundValue;\n\n // Overlay\n overlayEnabled?: boolean;\n overlayType?: \"solid\" | \"gradient\";\n overlayIntensity?: number;\n};\n\nexport function NestedWidget({\n resource,\n titleEnabled = true,\n titleText = \"Featured Collection\",\n shareables = DEFAULT_SHAREABLES,\n gap = \"md\",\n padding = 4,\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n primaryMediaHeight = \"400px\",\n titleFontSize = \"xl\",\n titleColor = \"background\",\n titleAlignment = { horizontal: \"left\", vertical: \"bottom\" },\n nestedTextColor = \"foreground\",\n background = {\n type: \"solid\",\n color: \"background\",\n },\n overlayEnabled = true,\n overlayType = \"gradient\",\n overlayIntensity = 50,\n className,\n ...props\n}: NestedWidgetProps): React.JSX.Element {\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n\n const scrollByAmount = (direction: \"prev\" | \"next\") => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const computedGap = parseFloat(getComputedStyle(container).gap) || 0;\n const firstItem = container.firstElementChild as HTMLElement | null;\n const itemWidth = firstItem?.offsetWidth ?? 0;\n const scrollAmount = itemWidth + computedGap;\n\n container.scrollTo({\n left:\n container.scrollLeft +\n (direction === \"next\" ? scrollAmount : -scrollAmount),\n behavior: \"smooth\",\n });\n };\n\n // Cap border radius for the primary media container: \"full\" creates a circle that clips\n // the absolutely-positioned title overlay to the narrow bottom of the circle.\n const primaryMediaRadius = borderRadius === \"full\" ? \"2xl\" : borderRadius;\n\n const { onItemClick } = useWidgetInteraction();\n\n const hasNestedMedia = shareables.length > 0;\n\n const titleAlignmentClasses = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n };\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 return (\n <div\n className={`@container flex w-full overflow-hidden p-${padding} rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-${backgroundColor} ${className}`}\n {...props}\n style={{\n maxHeight: primaryMediaHeight,\n backgroundImage: backgroundImage,\n }}\n >\n {/* Primary Media Container - Full width on mobile, fixed on desktop */}\n <div\n className={`relative @md:flex-none`}\n style={{\n width: primaryMediaHeight,\n }}\n >\n {/* Media + overlay clipped to rounded shape — title is a sibling so it isn't clipped */}\n <div\n className={`overflow-hidden rounded-${primaryMediaRadius} absolute inset-0`}\n >\n <MediaRenderer\n {...(resource ? getMediaPropsFromShareable(resource) : {})}\n autoplay\n loop\n muted\n />\n\n {/* Overlay */}\n {overlayEnabled && (\n <div\n className={`pointer-events-none absolute inset-0 z-10 ${\n overlayType === \"gradient\"\n ? \"bg-gradient-to-t from-black to-transparent\"\n : \"bg-black\"\n }`}\n style={{\n opacity:\n (Number(String(overlayIntensity).replace(\"%\", \"\")) || 50) /\n 100,\n }}\n />\n )}\n </div>\n\n {/* Title and Mobile Nested Media — outside the overflow-hidden clip */}\n {((titleEnabled && titleText) || hasNestedMedia) && (\n <div\n className={`absolute z-20 w-full ${titleAlignmentClasses[titleAlignment?.horizontal ?? \"left\"]} p-${padding} ${\n titleAlignment.vertical === \"top\"\n ? `top-0 pt-${padding}`\n : titleAlignment.vertical === \"center\"\n ? \"top-1/2 -translate-y-1/2\"\n : `bottom-0 pb-${padding}`\n }`}\n >\n {titleEnabled && titleText && (\n <h2\n className={`font-header leading-tight font-bold text-${titleColor} text-${titleFontSize === \"md\" ? \"base\" : titleFontSize}`}\n >\n {titleText}\n </h2>\n )}\n\n {/* Mobile: Products overlay inside primary media */}\n {hasNestedMedia && (\n <div className={`pt-${padding} @md:hidden`}>\n <div\n className={`flex overflow-x-auto gap-${gapValues[gap]} bg-transparent`}\n >\n {shareables.map((shareable) => (\n <div\n key={shareable.id}\n className={`flex shrink-0 flex-col items-center ${onItemClick ? \"cursor-pointer\" : \"\"}`}\n {...(onItemClick\n ? {\n role: \"button\",\n tabIndex: 0,\n onClick: () => onItemClick(shareable),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onItemClick(shareable);\n }\n },\n }\n : {})}\n >\n <div\n className={`aspect-3/4 h-40 overflow-hidden rounded-${borderRadius}`}\n >\n <MediaRenderer\n {...getMediaPropsFromShareable(shareable)}\n />\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n\n {/* Desktop: Products Container - Single row beside primary media */}\n {hasNestedMedia && (\n <div\n className={`relative hidden min-w-0 self-stretch @md:flex @md:flex-1 px-${padding}`}\n >\n <div\n ref={scrollContainerRef}\n className={`flex h-full flex-row overflow-x-auto gap-${gapValues[gap]}`}\n style={{ scrollSnapType: \"x mandatory\" }}\n >\n {shareables.map((shareable) => (\n <div\n key={shareable.id}\n className={`flex shrink-0 flex-col gap-1 ${onItemClick ? \"cursor-pointer\" : \"\"}`}\n style={{\n width: `calc(${primaryMediaHeight} * 0.75)`,\n scrollSnapAlign: \"start\",\n }}\n {...(onItemClick\n ? {\n role: \"button\",\n tabIndex: 0,\n onClick: () => onItemClick(shareable),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onItemClick(shareable);\n }\n },\n }\n : {})}\n >\n <div\n className={`aspect-3/4 h-full rounded-${borderRadius} overflow-hidden`}\n >\n <MediaRenderer {...getMediaPropsFromShareable(shareable)} />\n </div>\n <span className={`flex-none text-sm text-${nestedTextColor}`}>\n <p className=\"truncate\">{shareable.title || \"\"}</p>\n <p className=\"truncate\">\n {((shareable.display_price as string) ?? shareable.price) ||\n \"\"}\n </p>\n </span>\n </div>\n ))}\n </div>\n\n {/* Navigation arrows */}\n <div\n className={`absolute inset-x-0 top-1/2 flex w-full -translate-y-1/2 items-center justify-between px-8`}\n >\n <ScrollArrows\n onPrevious={() => scrollByAmount(\"prev\")}\n onNext={() => scrollByAmount(\"next\")}\n />\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport const nestedWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"NestedWidget\",\n displayName: \"Nested Widget\",\n tabsConfig: [\n { id: \"styling\", label: \"Styling\" },\n { id: \"data\", label: \"Data\" },\n ],\n dataSourceTargetProps: [\"shareables\"],\n fields: [\n // Content tab - Resource group\n {\n key: \"resource\",\n label: \"Primary Media\",\n type: \"resource\",\n description: \"Select the primary media displayed in the large panel\",\n allowedTypes: [\"Medium\"],\n tab: \"styling\",\n group: \"Content\",\n },\n // Content tab - Title group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed over the primary media\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Main title displayed over the primary media\",\n defaultValue: \"Featured Collection\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n label: \"Title Font Size\",\n defaultValue: \"xl\",\n key: \"titleFontSize\",\n description: \"Font size for the widget title\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n defaultValue: \"background\",\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n // Styling tab - Design group\n getHeightField({\n key: \"primaryMediaHeight\",\n label: \"Primary Media Height\",\n description: \"Height of the primary media container\",\n defaultValue: \"400px\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"titleAlignment\",\n label: \"Content Alignment\",\n type: \"alignment\",\n description: \"Alignment of the content inside the primary media\",\n defaultValue: { horizontal: \"left\", vertical: \"bottom\" },\n options: {\n horizontalEnabled: true,\n verticalEnabled: true,\n },\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 getPaddingField({\n defaultValue: 4,\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding used throughout the widget\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n defaultValue: \"md\",\n label: \"Border Radius\",\n key: \"borderRadius\",\n description: \"Rounded corners for the widget\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the widget\",\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 widget\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"overlayEnabled\",\n label: \"Enable Overlay\",\n type: \"boolean\",\n description:\n \"Add a dark overlay to the primary media for better text readability\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"overlayType\",\n label: \"Overlay Type\",\n type: \"buttonGroup\",\n description: \"Type of overlay effect\",\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: 50,\n unit: \"%\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n // Styling tab - Nested Media Styling group\n getGapField({\n label: \"Gap\",\n defaultValue: \"md\",\n key: \"gap\",\n description: \"Gap between nested media items\",\n tab: \"styling\",\n group: \"Nested Design\",\n }),\n getColorField({\n defaultValue: \"foreground\",\n key: \"nestedTextColor\",\n label: \"Nested Text Color\",\n description: \"Color for nested media labels\",\n tab: \"styling\",\n group: \"Nested Design\",\n }),\n {\n type: \"background\",\n defaultValue: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background color for nested media container\",\n tab: \"styling\",\n group: \"Nested Design\",\n },\n // Data tab\n {\n key: \"dataSource\",\n label: \"Data Source\",\n type: \"dataSource\",\n description: \"Configure dynamic data fetching from an API\",\n tab: \"data\",\n group: \"Data Configuration\",\n },\n ],\n // Per-item configuration schema for custom data sources\n itemConfigSchema: {\n description: \"Configure settings for this item\",\n fields: [\n {\n key: \"title\",\n label: \"Custom Title\",\n type: \"text\",\n description: \"Override the item's title for this widget\",\n },\n ],\n },\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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CtB;EACD,iBAAiB;GACf,OAAO;GACP,cAAc;GACd,KAAK;GACL,aAAa;GACb,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EACF,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EAEF,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;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;IAAE,YAAY;IAAQ,UAAU;IAAU;GACxD,SAAS;IACP,mBAAmB;IACnB,iBAAiB;IAClB;GACD,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;EACD,gBAAgB;GACd,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF,qBAAqB;GACnB,cAAc;GACd,OAAO;GACP,KAAK;GACL,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;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,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;EAED,YAAY;GACV,OAAO;GACP,cAAc;GACd,KAAK;GACL,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,MAAM;GACN,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR;EAED;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,OAAO;GACR;EACF;CAED,kBAAkB;EAChB,aAAa;EACb,QAAQ,CACN;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACd,CACF;EACF;CACF"}
1
+ {"version":3,"file":"NestedWidget-DrZ62oaO.mjs","names":[],"sources":["../../widgets/src/ui/scroll-arrows.tsx","../../widgets/src/widgets/NestedWidget.tsx"],"sourcesContent":["import type React from \"react\";\nimport { ChevronLeft, ChevronRight } from \"lucide-react\";\n\ntype ScrollArrowsProps = {\n onPrevious: () => void;\n onNext: () => void;\n};\n\nexport function ScrollArrows({\n onPrevious,\n onNext,\n}: ScrollArrowsProps): React.JSX.Element {\n return (\n <>\n <button\n type=\"button\"\n className=\"bg-foreground text-background flex h-6 w-6 items-center justify-center rounded-2xl opacity-70 transition-colors hover:opacity-50 disabled:opacity-30\"\n onClick={onPrevious}\n aria-label=\"Previous slide\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n </button>\n <button\n type=\"button\"\n className=\"bg-foreground text-background flex h-6 w-6 items-center justify-center rounded-2xl opacity-70 transition-colors hover:opacity-50 disabled:opacity-30\"\n onClick={onNext}\n aria-label=\"Next slide\"\n >\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </>\n );\n}\n","import { useRef, type ComponentProps } from \"react\";\nimport type React from \"react\";\nimport {\n MediaRenderer,\n getMediaPropsFromShareable,\n} from \"../components/MediaRenderer\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n AlignOptions,\n GapOptions,\n BackgroundValue,\n} from \"@fluid-app/portal-core/types\";\nimport {\n getHeightField,\n type WidgetPropertySchema,\n} from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n borderWidthClasses,\n borderColorClasses,\n getColorField,\n getFontSizeField,\n getGapField,\n getPaddingField,\n gapValues,\n} from \"../core/fields\";\nimport { ScrollArrows } from \"../ui/scroll-arrows\";\nimport { type ShareableItem } from \"@fluid-app/portal-core/types\";\nimport { useWidgetInteraction } from \"../contexts/WidgetInteractionContext\";\n\nconst DEFAULT_SHAREABLES: ShareableItem[] = [];\n\ntype NestedWidgetProps = ComponentProps<\"div\"> & {\n // Content\n resource?: ShareableItem;\n titleEnabled?: boolean;\n titleText?: string;\n shareables?: ShareableItem[];\n\n // Layout\n gap?: GapOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n primaryMediaHeight?: string;\n\n // Title styling\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n titleAlignment?: AlignOptions;\n\n // Nested media styling\n nestedTextColor?: ColorOptions;\n background?: BackgroundValue;\n\n // Overlay\n overlayEnabled?: boolean;\n overlayType?: \"solid\" | \"gradient\";\n overlayIntensity?: number;\n};\n\nexport function NestedWidget({\n resource,\n titleEnabled = true,\n titleText = \"Featured Collection\",\n shareables = DEFAULT_SHAREABLES,\n gap = \"md\",\n padding = 4,\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n primaryMediaHeight = \"400px\",\n titleFontSize = \"xl\",\n titleColor = \"background\",\n titleAlignment = { horizontal: \"left\", vertical: \"bottom\" },\n nestedTextColor = \"foreground\",\n background = {\n type: \"solid\",\n color: \"background\",\n },\n overlayEnabled = true,\n overlayType = \"gradient\",\n overlayIntensity = 50,\n className,\n ...props\n}: NestedWidgetProps): React.JSX.Element {\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n\n const scrollByAmount = (direction: \"prev\" | \"next\") => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const computedGap = parseFloat(getComputedStyle(container).gap) || 0;\n const firstItem = container.firstElementChild as HTMLElement | null;\n const itemWidth = firstItem?.offsetWidth ?? 0;\n const scrollAmount = itemWidth + computedGap;\n\n container.scrollTo({\n left:\n container.scrollLeft +\n (direction === \"next\" ? scrollAmount : -scrollAmount),\n behavior: \"smooth\",\n });\n };\n\n // Cap border radius for the primary media container: \"full\" creates a circle that clips\n // the absolutely-positioned title overlay to the narrow bottom of the circle.\n const primaryMediaRadius = borderRadius === \"full\" ? \"2xl\" : borderRadius;\n\n const { onItemClick } = useWidgetInteraction();\n\n const hasNestedMedia = shareables.length > 0;\n\n const titleAlignmentClasses = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n };\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 return (\n <div\n className={`@container flex w-full overflow-hidden p-${padding} rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-${backgroundColor} ${className}`}\n {...props}\n style={{\n maxHeight: primaryMediaHeight,\n backgroundImage: backgroundImage,\n }}\n >\n {/* Primary Media Container - Full width on mobile, fixed on desktop */}\n <div\n className={`relative @md:flex-none`}\n style={{\n width: primaryMediaHeight,\n }}\n >\n {/* Media + overlay clipped to rounded shape — title is a sibling so it isn't clipped */}\n <div\n className={`overflow-hidden rounded-${primaryMediaRadius} absolute inset-0`}\n >\n <MediaRenderer\n {...(resource ? getMediaPropsFromShareable(resource) : {})}\n autoplay\n loop\n muted\n />\n\n {/* Overlay */}\n {overlayEnabled && (\n <div\n className={`pointer-events-none absolute inset-0 z-10 ${\n overlayType === \"gradient\"\n ? \"bg-gradient-to-t from-black to-transparent\"\n : \"bg-black\"\n }`}\n style={{\n opacity:\n (Number(String(overlayIntensity).replace(\"%\", \"\")) || 50) /\n 100,\n }}\n />\n )}\n </div>\n\n {/* Title and Mobile Nested Media — outside the overflow-hidden clip */}\n {((titleEnabled && titleText) || hasNestedMedia) && (\n <div\n className={`absolute z-20 w-full ${titleAlignmentClasses[titleAlignment?.horizontal ?? \"left\"]} p-${padding} ${\n titleAlignment.vertical === \"top\"\n ? `top-0 pt-${padding}`\n : titleAlignment.vertical === \"center\"\n ? \"top-1/2 -translate-y-1/2\"\n : `bottom-0 pb-${padding}`\n }`}\n >\n {titleEnabled && titleText && (\n <h2\n className={`font-header leading-tight font-bold text-${titleColor} text-${titleFontSize === \"md\" ? \"base\" : titleFontSize}`}\n >\n {titleText}\n </h2>\n )}\n\n {/* Mobile: Products overlay inside primary media */}\n {hasNestedMedia && (\n <div className={`pt-${padding} @md:hidden`}>\n <div\n className={`flex overflow-x-auto gap-${gapValues[gap]} bg-transparent`}\n >\n {shareables.map((shareable) => (\n <div\n key={shareable.id}\n className={`flex shrink-0 flex-col items-center ${onItemClick ? \"cursor-pointer\" : \"\"}`}\n {...(onItemClick\n ? {\n role: \"button\",\n tabIndex: 0,\n onClick: () => onItemClick(shareable),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onItemClick(shareable);\n }\n },\n }\n : {})}\n >\n <div\n className={`aspect-3/4 h-40 overflow-hidden rounded-${borderRadius}`}\n >\n <MediaRenderer\n {...getMediaPropsFromShareable(shareable)}\n />\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n\n {/* Desktop: Products Container - Single row beside primary media */}\n {hasNestedMedia && (\n <div\n className={`relative hidden min-w-0 self-stretch @md:flex @md:flex-1 px-${padding}`}\n >\n <div\n ref={scrollContainerRef}\n className={`flex h-full flex-row overflow-x-auto gap-${gapValues[gap]}`}\n style={{ scrollSnapType: \"x mandatory\" }}\n >\n {shareables.map((shareable) => (\n <div\n key={shareable.id}\n className={`flex shrink-0 flex-col gap-1 ${onItemClick ? \"cursor-pointer\" : \"\"}`}\n style={{\n width: `calc(${primaryMediaHeight} * 0.75)`,\n scrollSnapAlign: \"start\",\n }}\n {...(onItemClick\n ? {\n role: \"button\",\n tabIndex: 0,\n onClick: () => onItemClick(shareable),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onItemClick(shareable);\n }\n },\n }\n : {})}\n >\n <div\n className={`aspect-3/4 h-full rounded-${borderRadius} overflow-hidden`}\n >\n <MediaRenderer {...getMediaPropsFromShareable(shareable)} />\n </div>\n <span className={`flex-none text-sm text-${nestedTextColor}`}>\n <p className=\"truncate\">{shareable.title || \"\"}</p>\n <p className=\"truncate\">\n {((shareable.display_price as string) ?? shareable.price) ||\n \"\"}\n </p>\n </span>\n </div>\n ))}\n </div>\n\n {/* Navigation arrows */}\n <div\n className={`absolute inset-x-0 top-1/2 flex w-full -translate-y-1/2 items-center justify-between px-8`}\n >\n <ScrollArrows\n onPrevious={() => scrollByAmount(\"prev\")}\n onNext={() => scrollByAmount(\"next\")}\n />\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport const nestedWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"NestedWidget\",\n displayName: \"Nested Widget\",\n tabsConfig: [\n { id: \"styling\", label: \"Styling\" },\n { id: \"data\", label: \"Data\" },\n ],\n dataSourceTargetProps: [\"shareables\"],\n fields: [\n // Content tab - Resource group\n {\n key: \"resource\",\n label: \"Primary Media\",\n type: \"resource\",\n description: \"Select the primary media displayed in the large panel\",\n allowedTypes: [\"Medium\"],\n tab: \"styling\",\n group: \"Content\",\n },\n // Content tab - Title group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed over the primary media\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Main title displayed over the primary media\",\n defaultValue: \"Featured Collection\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n label: \"Title Font Size\",\n defaultValue: \"xl\",\n key: \"titleFontSize\",\n description: \"Font size for the widget title\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n defaultValue: \"background\",\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n // Styling tab - Design group\n getHeightField({\n key: \"primaryMediaHeight\",\n label: \"Primary Media Height\",\n description: \"Height of the primary media container\",\n defaultValue: \"400px\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"titleAlignment\",\n label: \"Content Alignment\",\n type: \"alignment\",\n description: \"Alignment of the content inside the primary media\",\n defaultValue: { horizontal: \"left\", vertical: \"bottom\" },\n options: {\n horizontalEnabled: true,\n verticalEnabled: true,\n },\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 getPaddingField({\n defaultValue: 4,\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding used throughout the widget\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n defaultValue: \"md\",\n label: \"Border Radius\",\n key: \"borderRadius\",\n description: \"Rounded corners for the widget\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the widget\",\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 widget\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"overlayEnabled\",\n label: \"Enable Overlay\",\n type: \"boolean\",\n description:\n \"Add a dark overlay to the primary media for better text readability\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"overlayType\",\n label: \"Overlay Type\",\n type: \"buttonGroup\",\n description: \"Type of overlay effect\",\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: 50,\n unit: \"%\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n // Styling tab - Nested Media Styling group\n getGapField({\n label: \"Gap\",\n defaultValue: \"md\",\n key: \"gap\",\n description: \"Gap between nested media items\",\n tab: \"styling\",\n group: \"Nested Design\",\n }),\n getColorField({\n defaultValue: \"foreground\",\n key: \"nestedTextColor\",\n label: \"Nested Text Color\",\n description: \"Color for nested media labels\",\n tab: \"styling\",\n group: \"Nested Design\",\n }),\n {\n type: \"background\",\n defaultValue: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background color for nested media container\",\n tab: \"styling\",\n group: \"Nested Design\",\n },\n // Data tab\n {\n key: \"dataSource\",\n label: \"Data Source\",\n type: \"dataSource\",\n description: \"Configure dynamic data fetching from an API\",\n tab: \"data\",\n group: \"Data Configuration\",\n },\n ],\n // Per-item configuration schema for custom data sources\n itemConfigSchema: {\n description: \"Configure settings for this item\",\n fields: [\n {\n key: \"title\",\n label: \"Custom Title\",\n type: \"text\",\n description: \"Override the item's title for this widget\",\n },\n ],\n },\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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CtB;EACD,iBAAiB;GACf,OAAO;GACP,cAAc;GACd,KAAK;GACL,aAAa;GACb,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EACF,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EAEF,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;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;IAAE,YAAY;IAAQ,UAAU;IAAU;GACxD,SAAS;IACP,mBAAmB;IACnB,iBAAiB;IAClB;GACD,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;EACD,gBAAgB;GACd,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF,qBAAqB;GACnB,cAAc;GACd,OAAO;GACP,KAAK;GACL,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;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,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;EAED,YAAY;GACV,OAAO;GACP,cAAc;GACd,KAAK;GACL,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,MAAM;GACN,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR;EAED;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,OAAO;GACR;EACF;CAED,kBAAkB;EAChB,aAAa;EACb,QAAQ,CACN;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACd,CACF;EACF;CACF"}
@@ -1,6 +1,6 @@
1
1
  require("./chunk-9hOWP6kD.cjs");
2
2
  const require_WidgetInteractionContext = require("./WidgetInteractionContext-DUJhDVnC.cjs");
3
- const require_registries = require("./registries-DBb6VjAX.cjs");
3
+ const require_registries = require("./registries-CVsthTnW.cjs");
4
4
  const require_MediaRenderer = require("./MediaRenderer-CvN8Ku0i.cjs");
5
5
  let react = require("react");
6
6
  let react_jsx_runtime = require("react/jsx-runtime");
@@ -376,4 +376,4 @@ Object.defineProperty(exports, "nestedWidgetPropertySchema", {
376
376
  }
377
377
  });
378
378
 
379
- //# sourceMappingURL=NestedWidget-C2D4eWqb.cjs.map
379
+ //# sourceMappingURL=NestedWidget-vrohV65N.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"NestedWidget-C2D4eWqb.cjs","names":["ChevronLeft","ChevronRight","useWidgetInteraction","borderWidthClasses","borderColorClasses","MediaRenderer","getMediaPropsFromShareable","gapValues","getFontSizeField","getColorField","getHeightField","getPaddingField","getBorderRadiusField","getBorderWidthField","getBorderColorField","getGapField"],"sources":["../../widgets/src/ui/scroll-arrows.tsx","../../widgets/src/widgets/NestedWidget.tsx"],"sourcesContent":["import type React from \"react\";\nimport { ChevronLeft, ChevronRight } from \"lucide-react\";\n\ntype ScrollArrowsProps = {\n onPrevious: () => void;\n onNext: () => void;\n};\n\nexport function ScrollArrows({\n onPrevious,\n onNext,\n}: ScrollArrowsProps): React.JSX.Element {\n return (\n <>\n <button\n type=\"button\"\n className=\"bg-foreground text-background flex h-6 w-6 items-center justify-center rounded-2xl opacity-70 transition-colors hover:opacity-50 disabled:opacity-30\"\n onClick={onPrevious}\n aria-label=\"Previous slide\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n </button>\n <button\n type=\"button\"\n className=\"bg-foreground text-background flex h-6 w-6 items-center justify-center rounded-2xl opacity-70 transition-colors hover:opacity-50 disabled:opacity-30\"\n onClick={onNext}\n aria-label=\"Next slide\"\n >\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </>\n );\n}\n","import { useRef, type ComponentProps } from \"react\";\nimport type React from \"react\";\nimport {\n MediaRenderer,\n getMediaPropsFromShareable,\n} from \"../components/MediaRenderer\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n AlignOptions,\n GapOptions,\n BackgroundValue,\n} from \"@fluid-app/portal-core/types\";\nimport {\n getHeightField,\n type WidgetPropertySchema,\n} from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n borderWidthClasses,\n borderColorClasses,\n getColorField,\n getFontSizeField,\n getGapField,\n getPaddingField,\n gapValues,\n} from \"../core/fields\";\nimport { ScrollArrows } from \"../ui/scroll-arrows\";\nimport { type ShareableItem } from \"@fluid-app/portal-core/types\";\nimport { useWidgetInteraction } from \"../contexts/WidgetInteractionContext\";\n\nconst DEFAULT_SHAREABLES: ShareableItem[] = [];\n\ntype NestedWidgetProps = ComponentProps<\"div\"> & {\n // Content\n resource?: ShareableItem;\n titleEnabled?: boolean;\n titleText?: string;\n shareables?: ShareableItem[];\n\n // Layout\n gap?: GapOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n primaryMediaHeight?: string;\n\n // Title styling\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n titleAlignment?: AlignOptions;\n\n // Nested media styling\n nestedTextColor?: ColorOptions;\n background?: BackgroundValue;\n\n // Overlay\n overlayEnabled?: boolean;\n overlayType?: \"solid\" | \"gradient\";\n overlayIntensity?: number;\n};\n\nexport function NestedWidget({\n resource,\n titleEnabled = true,\n titleText = \"Featured Collection\",\n shareables = DEFAULT_SHAREABLES,\n gap = \"md\",\n padding = 4,\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n primaryMediaHeight = \"400px\",\n titleFontSize = \"xl\",\n titleColor = \"background\",\n titleAlignment = { horizontal: \"left\", vertical: \"bottom\" },\n nestedTextColor = \"foreground\",\n background = {\n type: \"solid\",\n color: \"background\",\n },\n overlayEnabled = true,\n overlayType = \"gradient\",\n overlayIntensity = 50,\n className,\n ...props\n}: NestedWidgetProps): React.JSX.Element {\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n\n const scrollByAmount = (direction: \"prev\" | \"next\") => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const computedGap = parseFloat(getComputedStyle(container).gap) || 0;\n const firstItem = container.firstElementChild as HTMLElement | null;\n const itemWidth = firstItem?.offsetWidth ?? 0;\n const scrollAmount = itemWidth + computedGap;\n\n container.scrollTo({\n left:\n container.scrollLeft +\n (direction === \"next\" ? scrollAmount : -scrollAmount),\n behavior: \"smooth\",\n });\n };\n\n // Cap border radius for the primary media container: \"full\" creates a circle that clips\n // the absolutely-positioned title overlay to the narrow bottom of the circle.\n const primaryMediaRadius = borderRadius === \"full\" ? \"2xl\" : borderRadius;\n\n const { onItemClick } = useWidgetInteraction();\n\n const hasNestedMedia = shareables.length > 0;\n\n const titleAlignmentClasses = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n };\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 return (\n <div\n className={`@container flex w-full overflow-hidden p-${padding} rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-${backgroundColor} ${className}`}\n {...props}\n style={{\n maxHeight: primaryMediaHeight,\n backgroundImage: backgroundImage,\n }}\n >\n {/* Primary Media Container - Full width on mobile, fixed on desktop */}\n <div\n className={`relative @md:flex-none`}\n style={{\n width: primaryMediaHeight,\n }}\n >\n {/* Media + overlay clipped to rounded shape — title is a sibling so it isn't clipped */}\n <div\n className={`overflow-hidden rounded-${primaryMediaRadius} absolute inset-0`}\n >\n <MediaRenderer\n {...(resource ? getMediaPropsFromShareable(resource) : {})}\n autoplay\n loop\n muted\n />\n\n {/* Overlay */}\n {overlayEnabled && (\n <div\n className={`pointer-events-none absolute inset-0 z-10 ${\n overlayType === \"gradient\"\n ? \"bg-gradient-to-t from-black to-transparent\"\n : \"bg-black\"\n }`}\n style={{\n opacity:\n (Number(String(overlayIntensity).replace(\"%\", \"\")) || 50) /\n 100,\n }}\n />\n )}\n </div>\n\n {/* Title and Mobile Nested Media — outside the overflow-hidden clip */}\n {((titleEnabled && titleText) || hasNestedMedia) && (\n <div\n className={`absolute z-20 w-full ${titleAlignmentClasses[titleAlignment?.horizontal ?? \"left\"]} p-${padding} ${\n titleAlignment.vertical === \"top\"\n ? `top-0 pt-${padding}`\n : titleAlignment.vertical === \"center\"\n ? \"top-1/2 -translate-y-1/2\"\n : `bottom-0 pb-${padding}`\n }`}\n >\n {titleEnabled && titleText && (\n <h2\n className={`font-header leading-tight font-bold text-${titleColor} text-${titleFontSize === \"md\" ? \"base\" : titleFontSize}`}\n >\n {titleText}\n </h2>\n )}\n\n {/* Mobile: Products overlay inside primary media */}\n {hasNestedMedia && (\n <div className={`pt-${padding} @md:hidden`}>\n <div\n className={`flex overflow-x-auto gap-${gapValues[gap]} bg-transparent`}\n >\n {shareables.map((shareable) => (\n <div\n key={shareable.id}\n className={`flex shrink-0 flex-col items-center ${onItemClick ? \"cursor-pointer\" : \"\"}`}\n {...(onItemClick\n ? {\n role: \"button\",\n tabIndex: 0,\n onClick: () => onItemClick(shareable),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onItemClick(shareable);\n }\n },\n }\n : {})}\n >\n <div\n className={`aspect-3/4 h-40 overflow-hidden rounded-${borderRadius}`}\n >\n <MediaRenderer\n {...getMediaPropsFromShareable(shareable)}\n />\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n\n {/* Desktop: Products Container - Single row beside primary media */}\n {hasNestedMedia && (\n <div\n className={`relative hidden min-w-0 self-stretch @md:flex @md:flex-1 px-${padding}`}\n >\n <div\n ref={scrollContainerRef}\n className={`flex h-full flex-row overflow-x-auto gap-${gapValues[gap]}`}\n style={{ scrollSnapType: \"x mandatory\" }}\n >\n {shareables.map((shareable) => (\n <div\n key={shareable.id}\n className={`flex shrink-0 flex-col gap-1 ${onItemClick ? \"cursor-pointer\" : \"\"}`}\n style={{\n width: `calc(${primaryMediaHeight} * 0.75)`,\n scrollSnapAlign: \"start\",\n }}\n {...(onItemClick\n ? {\n role: \"button\",\n tabIndex: 0,\n onClick: () => onItemClick(shareable),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onItemClick(shareable);\n }\n },\n }\n : {})}\n >\n <div\n className={`aspect-3/4 h-full rounded-${borderRadius} overflow-hidden`}\n >\n <MediaRenderer {...getMediaPropsFromShareable(shareable)} />\n </div>\n <span className={`flex-none text-sm text-${nestedTextColor}`}>\n <p className=\"truncate\">{shareable.title || \"\"}</p>\n <p className=\"truncate\">\n {((shareable.display_price as string) ?? shareable.price) ||\n \"\"}\n </p>\n </span>\n </div>\n ))}\n </div>\n\n {/* Navigation arrows */}\n <div\n className={`absolute inset-x-0 top-1/2 flex w-full -translate-y-1/2 items-center justify-between px-8`}\n >\n <ScrollArrows\n onPrevious={() => scrollByAmount(\"prev\")}\n onNext={() => scrollByAmount(\"next\")}\n />\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport const nestedWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"NestedWidget\",\n displayName: \"Nested Widget\",\n tabsConfig: [\n { id: \"styling\", label: \"Styling\" },\n { id: \"data\", label: \"Data\" },\n ],\n dataSourceTargetProps: [\"shareables\"],\n fields: [\n // Content tab - Resource group\n {\n key: \"resource\",\n label: \"Primary Media\",\n type: \"resource\",\n description: \"Select the primary media displayed in the large panel\",\n allowedTypes: [\"Medium\"],\n tab: \"styling\",\n group: \"Content\",\n },\n // Content tab - Title group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed over the primary media\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Main title displayed over the primary media\",\n defaultValue: \"Featured Collection\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n label: \"Title Font Size\",\n defaultValue: \"xl\",\n key: \"titleFontSize\",\n description: \"Font size for the widget title\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n defaultValue: \"background\",\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n // Styling tab - Design group\n getHeightField({\n key: \"primaryMediaHeight\",\n label: \"Primary Media Height\",\n description: \"Height of the primary media container\",\n defaultValue: \"400px\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"titleAlignment\",\n label: \"Content Alignment\",\n type: \"alignment\",\n description: \"Alignment of the content inside the primary media\",\n defaultValue: { horizontal: \"left\", vertical: \"bottom\" },\n options: {\n horizontalEnabled: true,\n verticalEnabled: true,\n },\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 getPaddingField({\n defaultValue: 4,\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding used throughout the widget\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n defaultValue: \"md\",\n label: \"Border Radius\",\n key: \"borderRadius\",\n description: \"Rounded corners for the widget\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the widget\",\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 widget\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"overlayEnabled\",\n label: \"Enable Overlay\",\n type: \"boolean\",\n description:\n \"Add a dark overlay to the primary media for better text readability\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"overlayType\",\n label: \"Overlay Type\",\n type: \"buttonGroup\",\n description: \"Type of overlay effect\",\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: 50,\n unit: \"%\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n // Styling tab - Nested Media Styling group\n getGapField({\n label: \"Gap\",\n defaultValue: \"md\",\n key: \"gap\",\n description: \"Gap between nested media items\",\n tab: \"styling\",\n group: \"Nested Design\",\n }),\n getColorField({\n defaultValue: \"foreground\",\n key: \"nestedTextColor\",\n label: \"Nested Text Color\",\n description: \"Color for nested media labels\",\n tab: \"styling\",\n group: \"Nested Design\",\n }),\n {\n type: \"background\",\n defaultValue: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background color for nested media container\",\n tab: \"styling\",\n group: \"Nested Design\",\n },\n // Data tab\n {\n key: \"dataSource\",\n label: \"Data Source\",\n type: \"dataSource\",\n description: \"Configure dynamic data fetching from an API\",\n tab: \"data\",\n group: \"Data Configuration\",\n },\n ],\n // Per-item configuration schema for custom data sources\n itemConfigSchema: {\n description: \"Configure settings for this item\",\n fields: [\n {\n key: \"title\",\n label: \"Custom Title\",\n type: \"text\",\n description: \"Override the item's title for this widget\",\n },\n ],\n },\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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CFC,mBAAAA,qBAAqB;GACnB,cAAc;GACd,OAAO;GACP,KAAK;GACL,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACFC,mBAAAA,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFC,mBAAAA,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;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,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;EAEDC,mBAAAA,YAAY;GACV,OAAO;GACP,cAAc;GACd,KAAK;GACL,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACFN,mBAAAA,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,MAAM;GACN,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR;EAED;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,OAAO;GACR;EACF;CAED,kBAAkB;EAChB,aAAa;EACb,QAAQ,CACN;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACd,CACF;EACF;CACF"}
1
+ {"version":3,"file":"NestedWidget-vrohV65N.cjs","names":["ChevronLeft","ChevronRight","useWidgetInteraction","borderWidthClasses","borderColorClasses","MediaRenderer","getMediaPropsFromShareable","gapValues","getFontSizeField","getColorField","getHeightField","getPaddingField","getBorderRadiusField","getBorderWidthField","getBorderColorField","getGapField"],"sources":["../../widgets/src/ui/scroll-arrows.tsx","../../widgets/src/widgets/NestedWidget.tsx"],"sourcesContent":["import type React from \"react\";\nimport { ChevronLeft, ChevronRight } from \"lucide-react\";\n\ntype ScrollArrowsProps = {\n onPrevious: () => void;\n onNext: () => void;\n};\n\nexport function ScrollArrows({\n onPrevious,\n onNext,\n}: ScrollArrowsProps): React.JSX.Element {\n return (\n <>\n <button\n type=\"button\"\n className=\"bg-foreground text-background flex h-6 w-6 items-center justify-center rounded-2xl opacity-70 transition-colors hover:opacity-50 disabled:opacity-30\"\n onClick={onPrevious}\n aria-label=\"Previous slide\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n </button>\n <button\n type=\"button\"\n className=\"bg-foreground text-background flex h-6 w-6 items-center justify-center rounded-2xl opacity-70 transition-colors hover:opacity-50 disabled:opacity-30\"\n onClick={onNext}\n aria-label=\"Next slide\"\n >\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </>\n );\n}\n","import { useRef, type ComponentProps } from \"react\";\nimport type React from \"react\";\nimport {\n MediaRenderer,\n getMediaPropsFromShareable,\n} from \"../components/MediaRenderer\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n AlignOptions,\n GapOptions,\n BackgroundValue,\n} from \"@fluid-app/portal-core/types\";\nimport {\n getHeightField,\n type WidgetPropertySchema,\n} from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n borderWidthClasses,\n borderColorClasses,\n getColorField,\n getFontSizeField,\n getGapField,\n getPaddingField,\n gapValues,\n} from \"../core/fields\";\nimport { ScrollArrows } from \"../ui/scroll-arrows\";\nimport { type ShareableItem } from \"@fluid-app/portal-core/types\";\nimport { useWidgetInteraction } from \"../contexts/WidgetInteractionContext\";\n\nconst DEFAULT_SHAREABLES: ShareableItem[] = [];\n\ntype NestedWidgetProps = ComponentProps<\"div\"> & {\n // Content\n resource?: ShareableItem;\n titleEnabled?: boolean;\n titleText?: string;\n shareables?: ShareableItem[];\n\n // Layout\n gap?: GapOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n primaryMediaHeight?: string;\n\n // Title styling\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n titleAlignment?: AlignOptions;\n\n // Nested media styling\n nestedTextColor?: ColorOptions;\n background?: BackgroundValue;\n\n // Overlay\n overlayEnabled?: boolean;\n overlayType?: \"solid\" | \"gradient\";\n overlayIntensity?: number;\n};\n\nexport function NestedWidget({\n resource,\n titleEnabled = true,\n titleText = \"Featured Collection\",\n shareables = DEFAULT_SHAREABLES,\n gap = \"md\",\n padding = 4,\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n primaryMediaHeight = \"400px\",\n titleFontSize = \"xl\",\n titleColor = \"background\",\n titleAlignment = { horizontal: \"left\", vertical: \"bottom\" },\n nestedTextColor = \"foreground\",\n background = {\n type: \"solid\",\n color: \"background\",\n },\n overlayEnabled = true,\n overlayType = \"gradient\",\n overlayIntensity = 50,\n className,\n ...props\n}: NestedWidgetProps): React.JSX.Element {\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n\n const scrollByAmount = (direction: \"prev\" | \"next\") => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const computedGap = parseFloat(getComputedStyle(container).gap) || 0;\n const firstItem = container.firstElementChild as HTMLElement | null;\n const itemWidth = firstItem?.offsetWidth ?? 0;\n const scrollAmount = itemWidth + computedGap;\n\n container.scrollTo({\n left:\n container.scrollLeft +\n (direction === \"next\" ? scrollAmount : -scrollAmount),\n behavior: \"smooth\",\n });\n };\n\n // Cap border radius for the primary media container: \"full\" creates a circle that clips\n // the absolutely-positioned title overlay to the narrow bottom of the circle.\n const primaryMediaRadius = borderRadius === \"full\" ? \"2xl\" : borderRadius;\n\n const { onItemClick } = useWidgetInteraction();\n\n const hasNestedMedia = shareables.length > 0;\n\n const titleAlignmentClasses = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n };\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 return (\n <div\n className={`@container flex w-full overflow-hidden p-${padding} rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-${backgroundColor} ${className}`}\n {...props}\n style={{\n maxHeight: primaryMediaHeight,\n backgroundImage: backgroundImage,\n }}\n >\n {/* Primary Media Container - Full width on mobile, fixed on desktop */}\n <div\n className={`relative @md:flex-none`}\n style={{\n width: primaryMediaHeight,\n }}\n >\n {/* Media + overlay clipped to rounded shape — title is a sibling so it isn't clipped */}\n <div\n className={`overflow-hidden rounded-${primaryMediaRadius} absolute inset-0`}\n >\n <MediaRenderer\n {...(resource ? getMediaPropsFromShareable(resource) : {})}\n autoplay\n loop\n muted\n />\n\n {/* Overlay */}\n {overlayEnabled && (\n <div\n className={`pointer-events-none absolute inset-0 z-10 ${\n overlayType === \"gradient\"\n ? \"bg-gradient-to-t from-black to-transparent\"\n : \"bg-black\"\n }`}\n style={{\n opacity:\n (Number(String(overlayIntensity).replace(\"%\", \"\")) || 50) /\n 100,\n }}\n />\n )}\n </div>\n\n {/* Title and Mobile Nested Media — outside the overflow-hidden clip */}\n {((titleEnabled && titleText) || hasNestedMedia) && (\n <div\n className={`absolute z-20 w-full ${titleAlignmentClasses[titleAlignment?.horizontal ?? \"left\"]} p-${padding} ${\n titleAlignment.vertical === \"top\"\n ? `top-0 pt-${padding}`\n : titleAlignment.vertical === \"center\"\n ? \"top-1/2 -translate-y-1/2\"\n : `bottom-0 pb-${padding}`\n }`}\n >\n {titleEnabled && titleText && (\n <h2\n className={`font-header leading-tight font-bold text-${titleColor} text-${titleFontSize === \"md\" ? \"base\" : titleFontSize}`}\n >\n {titleText}\n </h2>\n )}\n\n {/* Mobile: Products overlay inside primary media */}\n {hasNestedMedia && (\n <div className={`pt-${padding} @md:hidden`}>\n <div\n className={`flex overflow-x-auto gap-${gapValues[gap]} bg-transparent`}\n >\n {shareables.map((shareable) => (\n <div\n key={shareable.id}\n className={`flex shrink-0 flex-col items-center ${onItemClick ? \"cursor-pointer\" : \"\"}`}\n {...(onItemClick\n ? {\n role: \"button\",\n tabIndex: 0,\n onClick: () => onItemClick(shareable),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onItemClick(shareable);\n }\n },\n }\n : {})}\n >\n <div\n className={`aspect-3/4 h-40 overflow-hidden rounded-${borderRadius}`}\n >\n <MediaRenderer\n {...getMediaPropsFromShareable(shareable)}\n />\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n\n {/* Desktop: Products Container - Single row beside primary media */}\n {hasNestedMedia && (\n <div\n className={`relative hidden min-w-0 self-stretch @md:flex @md:flex-1 px-${padding}`}\n >\n <div\n ref={scrollContainerRef}\n className={`flex h-full flex-row overflow-x-auto gap-${gapValues[gap]}`}\n style={{ scrollSnapType: \"x mandatory\" }}\n >\n {shareables.map((shareable) => (\n <div\n key={shareable.id}\n className={`flex shrink-0 flex-col gap-1 ${onItemClick ? \"cursor-pointer\" : \"\"}`}\n style={{\n width: `calc(${primaryMediaHeight} * 0.75)`,\n scrollSnapAlign: \"start\",\n }}\n {...(onItemClick\n ? {\n role: \"button\",\n tabIndex: 0,\n onClick: () => onItemClick(shareable),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onItemClick(shareable);\n }\n },\n }\n : {})}\n >\n <div\n className={`aspect-3/4 h-full rounded-${borderRadius} overflow-hidden`}\n >\n <MediaRenderer {...getMediaPropsFromShareable(shareable)} />\n </div>\n <span className={`flex-none text-sm text-${nestedTextColor}`}>\n <p className=\"truncate\">{shareable.title || \"\"}</p>\n <p className=\"truncate\">\n {((shareable.display_price as string) ?? shareable.price) ||\n \"\"}\n </p>\n </span>\n </div>\n ))}\n </div>\n\n {/* Navigation arrows */}\n <div\n className={`absolute inset-x-0 top-1/2 flex w-full -translate-y-1/2 items-center justify-between px-8`}\n >\n <ScrollArrows\n onPrevious={() => scrollByAmount(\"prev\")}\n onNext={() => scrollByAmount(\"next\")}\n />\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport const nestedWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"NestedWidget\",\n displayName: \"Nested Widget\",\n tabsConfig: [\n { id: \"styling\", label: \"Styling\" },\n { id: \"data\", label: \"Data\" },\n ],\n dataSourceTargetProps: [\"shareables\"],\n fields: [\n // Content tab - Resource group\n {\n key: \"resource\",\n label: \"Primary Media\",\n type: \"resource\",\n description: \"Select the primary media displayed in the large panel\",\n allowedTypes: [\"Medium\"],\n tab: \"styling\",\n group: \"Content\",\n },\n // Content tab - Title group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed over the primary media\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Main title displayed over the primary media\",\n defaultValue: \"Featured Collection\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n label: \"Title Font Size\",\n defaultValue: \"xl\",\n key: \"titleFontSize\",\n description: \"Font size for the widget title\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n defaultValue: \"background\",\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n // Styling tab - Design group\n getHeightField({\n key: \"primaryMediaHeight\",\n label: \"Primary Media Height\",\n description: \"Height of the primary media container\",\n defaultValue: \"400px\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"titleAlignment\",\n label: \"Content Alignment\",\n type: \"alignment\",\n description: \"Alignment of the content inside the primary media\",\n defaultValue: { horizontal: \"left\", vertical: \"bottom\" },\n options: {\n horizontalEnabled: true,\n verticalEnabled: true,\n },\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 getPaddingField({\n defaultValue: 4,\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding used throughout the widget\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n defaultValue: \"md\",\n label: \"Border Radius\",\n key: \"borderRadius\",\n description: \"Rounded corners for the widget\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the widget\",\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 widget\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"overlayEnabled\",\n label: \"Enable Overlay\",\n type: \"boolean\",\n description:\n \"Add a dark overlay to the primary media for better text readability\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"overlayType\",\n label: \"Overlay Type\",\n type: \"buttonGroup\",\n description: \"Type of overlay effect\",\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: 50,\n unit: \"%\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n // Styling tab - Nested Media Styling group\n getGapField({\n label: \"Gap\",\n defaultValue: \"md\",\n key: \"gap\",\n description: \"Gap between nested media items\",\n tab: \"styling\",\n group: \"Nested Design\",\n }),\n getColorField({\n defaultValue: \"foreground\",\n key: \"nestedTextColor\",\n label: \"Nested Text Color\",\n description: \"Color for nested media labels\",\n tab: \"styling\",\n group: \"Nested Design\",\n }),\n {\n type: \"background\",\n defaultValue: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background color for nested media container\",\n tab: \"styling\",\n group: \"Nested Design\",\n },\n // Data tab\n {\n key: \"dataSource\",\n label: \"Data Source\",\n type: \"dataSource\",\n description: \"Configure dynamic data fetching from an API\",\n tab: \"data\",\n group: \"Data Configuration\",\n },\n ],\n // Per-item configuration schema for custom data sources\n itemConfigSchema: {\n description: \"Configure settings for this item\",\n fields: [\n {\n key: \"title\",\n label: \"Custom Title\",\n type: \"text\",\n description: \"Override the item's title for this widget\",\n },\n ],\n },\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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CFC,mBAAAA,qBAAqB;GACnB,cAAc;GACd,OAAO;GACP,KAAK;GACL,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACFC,mBAAAA,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFC,mBAAAA,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;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,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;EAEDC,mBAAAA,YAAY;GACV,OAAO;GACP,cAAc;GACd,KAAK;GACL,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACFN,mBAAAA,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,MAAM;GACN,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR;EAED;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,OAAO;GACR;EACF;CAED,kBAAkB;EAChB,aAAa;EACb,QAAQ,CACN;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACd,CACF;EACF;CACF"}
@@ -1,7 +1,7 @@
1
1
  const require_chunk = require("./chunk-9hOWP6kD.cjs");
2
2
  const require_registry_context = require("./registry-context-OIsrZ2Ij.cjs");
3
3
  const require_error_state = require("./error-state-BDhSltIa.cjs");
4
- const require_registries = require("./registries-DBb6VjAX.cjs");
4
+ const require_registries = require("./registries-CVsthTnW.cjs");
5
5
  let react = require("react");
6
6
  let _tanstack_react_query = require("@tanstack/react-query");
7
7
  let react_jsx_runtime = require("react/jsx-runtime");
@@ -311,4 +311,4 @@ Object.defineProperty(exports, "pointsWidgetPropertySchema", {
311
311
  }
312
312
  });
313
313
 
314
- //# sourceMappingURL=PointsWidget-ComTSNQZ.cjs.map
314
+ //# sourceMappingURL=PointsWidget-DI3N8-6W.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"PointsWidget-ComTSNQZ.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 // Contract: the BFF adapter (portal app, composite factory spreads BFF over\n // legacy) ignores customerId and infers the customer from the JWT, so the\n // portal renders this widget with no registry-variable plumbing. The legacy\n // adapter (fluid-admin) builds /v202506/customers/{customerId}/points_ledgers\n // and MUST receive a real id; that consumer always supplies one via registry\n // variables, so empty string never reaches the legacy URL in practice. If a\n // future caller wires this hook to a legacy-only adapter, configure\n // registry variables.customer_id at the provider — otherwise the request\n // would 404 on /customers//points_ledgers.\n return useQuery({\n queryKey: [\n \"portal-widget-use\",\n POINTS_LEDGER_QUERY_KEY,\n isPreview ? \"preview\" : baseUrl,\n customerId ?? null,\n ] as const,\n queryFn: ({ signal }) =>\n widgetsApi.fetchPointsLedger(customerId ?? \"\", signal),\n enabled: !isPreview,\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":";;;;;;;;;AAEA,MAAM,sBAAM,IAAI,MAAM;AAEtB,SAAS,QAAQ,MAAsB;AACrC,yBAAO,IAAI,KAAK,IAAI,SAAS,GAAG,OAAO,MAAW,EAAC,aAAa;;AAGlE,MAAa,eAA2B;CACtC,SAAS;CACT,SAAS;EACP;GACE,IAAI;GACJ,aAAa;GACb,QAAQ;GACR,WAAW,QAAQ,EAAE;GACtB;EACD;GACE,IAAI;GACJ,aAAa;GACb,QAAQ;GACR,WAAW,QAAQ,GAAG;GACvB;EACD;GACE,IAAI;GACJ,aAAa;GACb,QAAQ;GACR,WAAW,QAAQ,GAAG;GACvB;EACD;GACE,IAAI;GACJ,aAAa;GACb,QAAQ;GACR,WAAW,QAAQ,GAAG;GACvB;EACF;CACF;;;ACxBD,MAAa,0BAA0B;AAEvC,SAAgB,kBAAqD;CACnE,MAAM,aAAaA,oBAAAA,eAAe;CAClC,MAAM,EAAE,cAAcC,oBAAAA,yBAAyB;CAC/C,MAAM,iBAAiBC,yBAAAA,6BAA6B;CACpD,MAAM,EAAE,YAAY;CACpB,MAAM,aAAa,eAAe,WAAW;AAW7C,SAAA,GAAA,sBAAA,UAAgB;EACd,UAAU;GACR;GACA;GACA,YAAY,YAAY;GACxB,cAAc;GACf;EACD,UAAU,EAAE,aACV,WAAW,kBAAkB,cAAc,IAAI,OAAO;EACxD,SAAS,CAAC;EACV,GAAI,aAAa,EAAE,iBAAiB,cAAc;EACnD,CAAC;;;;;;;;AChBJ,MAAM,sBAAsB,eAA+B;CACzD,MAAM,sBAAM,IAAI,MAAM;CACtB,MAAM,OAAO,IAAI,KAAK,WAAW;CACjC,MAAM,SAAS,IAAI,SAAS,GAAG,KAAK,SAAS;CAC7C,MAAM,WAAW,KAAK,MAAM,SAAS,MAAW;AAEhD,KAAI,WAAW,EAAG,QAAO;AACzB,KAAI,aAAa,EAAG,QAAO;AAC3B,KAAI,WAAW,EAAG,QAAO,GAAG,SAAS;AACrC,KAAI,WAAW,GAAI,QAAO;AAC1B,KAAI,WAAW,GAAI,QAAO,GAAG,KAAK,MAAM,WAAW,EAAE,CAAC;AACtD,KAAI,WAAW,GAAI,QAAO;AAC1B,QAAO,GAAG,KAAK,MAAM,WAAW,GAAG,CAAC;;AAGtC,MAAM,iBAAiB,YAA4B;AACjD,QAAO,QAAQ,eAAe,QAAQ;;AA2BxC,SAAS,eAAe,EACtB,OACA,WACA,eAKC;CACD,MAAM,OAAO,MAAM,UAAU,IAAI,MAAM;AACvC,QACE,iBAAA,GAAA,kBAAA,MAAC,OAAD;EAAK,WAAU;YAAf,CACE,iBAAA,GAAA,kBAAA,MAAC,OAAD;GAAK,WAAU;aAAf,CACE,iBAAA,GAAA,kBAAA,KAAC,KAAD;IAAG,WAAW,gBAAgB,UAAU;cACrC,MAAM;IACL,CAAA,EACJ,iBAAA,GAAA,kBAAA,KAAC,KAAD;IAAG,WAAW,oBAAoB,UAAU;cACzC,mBAAmB,MAAM,UAAU;IAClC,CAAA,CACA;MACN,iBAAA,GAAA,kBAAA,KAAC,OAAD;GAAK,WAAW,MAAM,YAAY;aAChC,iBAAA,GAAA,kBAAA,MAAC,QAAD;IAAM,WAAW,4BAA4B,YAAY;cAAzD;KACG;KACA,KAAK,IAAI,MAAM,OAAO,CAAC,eAAe,QAAQ;KAAC;KAC3C;;GACH,CAAA,CACF;;;AAIV,SAAgB,aAAa,EAE3B,eAAe,MACf,QAAQ,UACR,gBAAgB,MAChB,aAAa,cAGb,eAAe,WAGf,iBAAiB,MACjB,eAAe,WAGf,aAAa;CAAE,MAAM;CAAS,OAAO;CAAc,EACnD,YAAY,cACZ,cAAc,WACd,UAAU,GACV,eAAe,MACf,cAAc,QACd,cAAc,SAEd,WACA,GAAG,SACoC;CACvC,MAAM,CAAC,aAAa,mBAAA,GAAA,MAAA,UAA2B,MAAM;CACrD,MAAM,kBAAA,GAAA,MAAA,QAAwB;CAE9B,MAAM,kBAAkB,WAAW,SAAS;CAC5C,MAAM,mBACH,WAAW,UAAU,aAAa,WAAW,UAAU,aACxD,WAAW,SAAS,UAChB,OAAO,WAAW,SAAS,aAAa,WAAW,SAAS,SAAS,KACrE;CAEN,MAAM,EAAE,MAAM,WAAW,YAAY,iBAAiB;AAEtD,QACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EACE,WAAW,sCAAsC,aAAa,MAAM,gBAAgB,GAAGC,mBAAAA,mBAAmB,aAAa,GAAG,gBAAgB,SAASC,mBAAAA,mBAAmB,eAAe,GAAG,GAAG,aAAa;EACxM,OAAO,EAAE,iBAAiB;EAC1B,GAAI;YAEJ,iBAAA,GAAA,kBAAA,MAAC,OAAD;GAAK,WAAW,KAAK,QAAQ;aAA7B;IAEG,gBACC,iBAAA,GAAA,kBAAA,KAAC,MAAD;KACE,WAAW,QAAQ,cAAc,8BAA8B;eAE9D;KACE,CAAA;IAEN,CAAC,aAAa,QACb,iBAAA,GAAA,kBAAA,KAAC,QAAD;KACE,WAAW,+BAA+B,aAAa;eAEtD,cAAc,KAAK,QAAQ;KACvB,CAAA;IAIR,YACC,iBAAA,GAAA,kBAAA,KAAC,OAAD;KAAK,WAAU;eACb,iBAAA,GAAA,kBAAA,KAAC,OAAD,EAAK,WAAU,kFAAmF,CAAA;KAC9F,CAAA,GACJ,UACF,iBAAA,GAAA,kBAAA,KAACC,oBAAAA,YAAD,EAAc,CAAA,GACZ,mBAAmB,CAAC,QAAQ,KAAK,QAAQ,WAAW,KAEtD,iBAAA,GAAA,kBAAA,MAAC,OAAD;KAAK,WAAU;eAAf,CACE,iBAAA,GAAA,kBAAA,KAACC,aAAAA,OAAD,EAAO,WAAW,gBAAgB,UAAU,cAAgB,CAAA,EAC5D,iBAAA,GAAA,kBAAA,KAAC,KAAD;MAAG,WAAW,8BAA8B,UAAU;gBAAc;MAEhE,CAAA,CACA;SACJ,kBAAkB,QAAQ,KAAK,QAAQ,SAAS,IAElD,iBAAA,GAAA,kBAAA,MAAC,OAAD;KAAK,WAAU;eAAf;MAEE,iBAAA,GAAA,kBAAA,MAAC,UAAD;OACE,MAAK;OACL,iBAAe;OACf,iBAAe;OACf,eAAe,gBAAgB,SAAS,CAAC,KAAK;OAC9C,WAAW,uDAAuD,UAAU;iBAL9E,CAOE,iBAAA,GAAA,kBAAA,KAAC,QAAD;QAAM,WAAU;kBAAoB;QAAoB,CAAA,EACxD,iBAAA,GAAA,kBAAA,KAACC,aAAAA,aAAD,EACE,WAAW,4CAA4C,cAAc,eAAe,MACpF,CAAA,CACK;;MACT,iBAAA,GAAA,kBAAA,KAAC,OAAD,EAAK,WAAW,MAAM,UAAU,kBAAoB,CAAA;MAGpD,iBAAA,GAAA,kBAAA,KAAC,OAAD;OACE,IAAI;OACJ,WAAW,uBAAuB,CAAC,cAAc,WAAW;iBAE3D,KAAK,QAAQ,KAAK,UACjB,iBAAA,GAAA,kBAAA,KAAC,gBAAD;QAES;QACI;QACE;QACb,EAJK,MAAM,GAIX,CACF;OACE,CAAA;MACF;SACJ;IACA;;EACF,CAAA;;AAIV,MAAa,6BAAmD;CAC9D,YAAY;CACZ,aAAa;CACb,QAAQ;EAEN;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GAEd,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GAEd,OAAO;GACP,qBAAqB;GACtB;EACDC,mBAAAA,iBAAiB;GACf,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GAEd,OAAO;GACP,qBAAqB;GACtB,CAAC;EACFC,mBAAAA,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GAEd,OAAO;GACP,qBAAqB;GACtB,CAAC;EAGFA,mBAAAA,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GAEd,OAAO;GACR,CAAC;EAGF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GAEd,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GAEd,OAAO;GACP,qBAAqB;GACtB;EAGD;GACE,MAAM;GACN,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GAEd,OAAO;GACR;EACDA,mBAAAA,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GAEd,OAAO;GACR,CAAC;EACFA,mBAAAA,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GAEd,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,MAAM;GACN,OAAO;GAEP,OAAO;GACR;EACDC,mBAAAA,gBAAgB;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GAEd,OAAO;GACR,CAAC;EACFC,mBAAAA,qBAAqB;GACnB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GAEd,OAAO;GACR,CAAC;EACFC,mBAAAA,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GAEd,OAAO;GACR,CAAC;EACFC,mBAAAA,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GAEd,OAAO;GACR,CAAC;EACH;CACF"}
1
+ {"version":3,"file":"PointsWidget-DI3N8-6W.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 // Contract: the BFF adapter (portal app, composite factory spreads BFF over\n // legacy) ignores customerId and infers the customer from the JWT, so the\n // portal renders this widget with no registry-variable plumbing. The legacy\n // adapter (fluid-admin) builds /v202506/customers/{customerId}/points_ledgers\n // and MUST receive a real id; that consumer always supplies one via registry\n // variables, so empty string never reaches the legacy URL in practice. If a\n // future caller wires this hook to a legacy-only adapter, configure\n // registry variables.customer_id at the provider — otherwise the request\n // would 404 on /customers//points_ledgers.\n return useQuery({\n queryKey: [\n \"portal-widget-use\",\n POINTS_LEDGER_QUERY_KEY,\n isPreview ? \"preview\" : baseUrl,\n customerId ?? null,\n ] as const,\n queryFn: ({ signal }) =>\n widgetsApi.fetchPointsLedger(customerId ?? \"\", signal),\n enabled: !isPreview,\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,7 +1,7 @@
1
1
  import { I as __exportAll } from "./portal_tenant_content-DPLnrtOG.mjs";
2
2
  import { n as useDataSourceRegistryConfig } from "./registry-context-BSJeDI2A.mjs";
3
3
  import { i as useWidgetsApi, n as useWidgetPreviewContext, t as ErrorState } from "./error-state--Z2OlDFr.mjs";
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-kvRRUHcO.mjs";
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-6F90ZS1m.mjs";
5
5
  import { useId, useState } from "react";
6
6
  import { useQuery } from "@tanstack/react-query";
7
7
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -294,4 +294,4 @@ const pointsWidgetPropertySchema = {
294
294
  //#endregion
295
295
  export { PointsWidget_exports as n, pointsWidgetPropertySchema as r, PointsWidget as t };
296
296
 
297
- //# sourceMappingURL=PointsWidget-CRvG5LOV.mjs.map
297
+ //# sourceMappingURL=PointsWidget-ubAn0b-m.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"PointsWidget-CRvG5LOV.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 // Contract: the BFF adapter (portal app, composite factory spreads BFF over\n // legacy) ignores customerId and infers the customer from the JWT, so the\n // portal renders this widget with no registry-variable plumbing. The legacy\n // adapter (fluid-admin) builds /v202506/customers/{customerId}/points_ledgers\n // and MUST receive a real id; that consumer always supplies one via registry\n // variables, so empty string never reaches the legacy URL in practice. If a\n // future caller wires this hook to a legacy-only adapter, configure\n // registry variables.customer_id at the provider — otherwise the request\n // would 404 on /customers//points_ledgers.\n return useQuery({\n queryKey: [\n \"portal-widget-use\",\n POINTS_LEDGER_QUERY_KEY,\n isPreview ? \"preview\" : baseUrl,\n customerId ?? null,\n ] as const,\n queryFn: ({ signal }) =>\n widgetsApi.fetchPointsLedger(customerId ?? \"\", signal),\n enabled: !isPreview,\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
+ {"version":3,"file":"PointsWidget-ubAn0b-m.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 // Contract: the BFF adapter (portal app, composite factory spreads BFF over\n // legacy) ignores customerId and infers the customer from the JWT, so the\n // portal renders this widget with no registry-variable plumbing. The legacy\n // adapter (fluid-admin) builds /v202506/customers/{customerId}/points_ledgers\n // and MUST receive a real id; that consumer always supplies one via registry\n // variables, so empty string never reaches the legacy URL in practice. If a\n // future caller wires this hook to a legacy-only adapter, configure\n // registry variables.customer_id at the provider — otherwise the request\n // would 404 on /customers//points_ledgers.\n return useQuery({\n queryKey: [\n \"portal-widget-use\",\n POINTS_LEDGER_QUERY_KEY,\n isPreview ? \"preview\" : baseUrl,\n customerId ?? null,\n ] as const,\n queryFn: ({ signal }) =>\n widgetsApi.fetchPointsLedger(customerId ?? \"\", signal),\n enabled: !isPreview,\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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"}
@@ -0,0 +1,46 @@
1
+ import "./FluidProvider-C0YKxODs.mjs";
2
+ import "./ScreenRenderer-YOmW7J80.mjs";
3
+ import "./account-api-context-BIZ_aibJ.mjs";
4
+ import "./store-api-context-C1lXT_3d.mjs";
5
+ import "./api-context-3GmfqvIB.mjs";
6
+ import "./mysite-api-context-5-qpKHWA.mjs";
7
+ import "./countries-api-context-CMh13cfX.mjs";
8
+ import "./registry-context-BSJeDI2A.mjs";
9
+ import "./WidgetInteractionContext-I716c8kj.mjs";
10
+ import "./EmbedWidget-Czn_RJbm.mjs";
11
+ import "./locale-context-B_ufX9EH.mjs";
12
+ import "./error-state--Z2OlDFr.mjs";
13
+ import "./LayoutWidget-iKNNIRPq.mjs";
14
+ import "./registries-6F90ZS1m.mjs";
15
+ import "./fields-FTgjMOdh.mjs";
16
+ import "./TextWidget-DSGevTKM.mjs";
17
+ import "./AlertWidget-Bua0I46v.mjs";
18
+ import "./BulletListWidget-DvT2x5wg.mjs";
19
+ import "./CalendarWidget-BB1C5K_j.mjs";
20
+ import "./CardWidget-CEERBKUN.mjs";
21
+ import "./purify.es-Ba5Ug4-y.mjs";
22
+ import "./MediaRenderer-13Jlf38P.mjs";
23
+ import "./CarouselWidget-Dhjf60LS.mjs";
24
+ import "./CatchUpWidget-CM-iCMhK.mjs";
25
+ import "./src-B3W228vu.mjs";
26
+ import "./ChartWidget-CJXZ9qf7.mjs";
27
+ import "./ContainerWidget-2Rep2gGz.mjs";
28
+ import "./ImageWidget--WJppfij.mjs";
29
+ import "./LinkWidget-BoVmB_zf.mjs";
30
+ import "./ListWidget-CuwsaMQ9.mjs";
31
+ import "./MySiteWidget-CsJzjc7o.mjs";
32
+ import "./NestedWidget-DrZ62oaO.mjs";
33
+ import "./PointsWidget-ubAn0b-m.mjs";
34
+ import "./QuickLinksWidget-J5axodVF.mjs";
35
+ import "./QuickShareWidget-CyYW9nS6.mjs";
36
+ import "./RecentActivityWidget-CndO-Ac0.mjs";
37
+ import "./SeparatorWidget-eI7b2n6u.mjs";
38
+ import "./SpacerWidget-s0N26_Hb.mjs";
39
+ import "./TableWidget-D8HBHejy.mjs";
40
+ import "./ToDoWidget-5IiWutYI.mjs";
41
+ import "./VideoWidget-BiaPF0-w.mjs";
42
+ import "./ScreenHeaderContext-kG_zh0zW.mjs";
43
+ import "./AddressAutocompleteInput-pqzSBpqP.mjs";
44
+ import "./use-mysite-portal-B7N48vKo.mjs";
45
+ import { n as profileScreenPropertySchema, t as ProfileScreen } from "./ProfileScreen-FG1DZum3.mjs";
46
+ export { ProfileScreen, profileScreenPropertySchema };
@@ -0,0 +1,48 @@
1
+ require("./chunk-9hOWP6kD.cjs");
2
+ require("./FluidProvider-CoSgK0jL.cjs");
3
+ require("./ScreenRenderer-j7Nz1HQx.cjs");
4
+ require("./account-api-context-DZP9IiGg.cjs");
5
+ require("./store-api-context-D1gZn22Z.cjs");
6
+ require("./api-context-BkBvyFVK.cjs");
7
+ require("./mysite-api-context-Dz4lI5Xd.cjs");
8
+ require("./countries-api-context-C0C0K9gJ.cjs");
9
+ require("./registry-context-OIsrZ2Ij.cjs");
10
+ require("./WidgetInteractionContext-DUJhDVnC.cjs");
11
+ require("./EmbedWidget-DFlg5AI7.cjs");
12
+ require("./locale-context-34b1u6At.cjs");
13
+ require("./error-state-BDhSltIa.cjs");
14
+ require("./LayoutWidget-8DwDBW24.cjs");
15
+ require("./registries-CVsthTnW.cjs");
16
+ require("./fields-COJ84ouS.cjs");
17
+ require("./TextWidget-CMOofhaH.cjs");
18
+ require("./AlertWidget-ByokSA3K.cjs");
19
+ require("./BulletListWidget-BwrMNPZ-.cjs");
20
+ require("./CalendarWidget-MVJmxwFQ.cjs");
21
+ require("./CardWidget-Cf4-dF-v.cjs");
22
+ require("./purify.es-CxBw_WJp.cjs");
23
+ require("./MediaRenderer-CvN8Ku0i.cjs");
24
+ require("./CarouselWidget-BJSO17JY.cjs");
25
+ require("./CatchUpWidget-CFF-Fgdo.cjs");
26
+ require("./src-BFJg9F_s.cjs");
27
+ require("./ChartWidget-6nZLzlQM.cjs");
28
+ require("./ContainerWidget-DX9qO1T-.cjs");
29
+ require("./ImageWidget-CU2cet5p.cjs");
30
+ require("./LinkWidget-DpylGthu.cjs");
31
+ require("./ListWidget-CQgei8SF.cjs");
32
+ require("./MySiteWidget-BziY8ylH.cjs");
33
+ require("./NestedWidget-vrohV65N.cjs");
34
+ require("./PointsWidget-DI3N8-6W.cjs");
35
+ require("./QuickLinksWidget-Cpq1V-uX.cjs");
36
+ require("./QuickShareWidget-CYPOXs8X.cjs");
37
+ require("./RecentActivityWidget-Cp3fYBM2.cjs");
38
+ require("./SeparatorWidget-DW_9_L9_.cjs");
39
+ require("./SpacerWidget-DLQU3wbc.cjs");
40
+ require("./TableWidget-CT6T3IgY.cjs");
41
+ require("./ToDoWidget-B97blWRO.cjs");
42
+ require("./VideoWidget-zdT_mVo9.cjs");
43
+ require("./ScreenHeaderContext-JDIUM84f.cjs");
44
+ require("./AddressAutocompleteInput-BrnJTpK8.cjs");
45
+ require("./use-mysite-portal-YnHKJ-Y-.cjs");
46
+ const require_ProfileScreen = require("./ProfileScreen-DYO-1rw4.cjs");
47
+ exports.ProfileScreen = require_ProfileScreen.ProfileScreen;
48
+ exports.profileScreenPropertySchema = require_ProfileScreen.profileScreenPropertySchema;