@fluid-app/portal-sdk 0.1.237 → 0.1.239

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/dist/{CalendarWidget-BaGML5Xh.mjs → CalendarWidget-BXxNxHDV.mjs} +2 -2
  2. package/dist/{CalendarWidget-BaGML5Xh.mjs.map → CalendarWidget-BXxNxHDV.mjs.map} +1 -1
  3. package/dist/{CalendarWidget-oGK122s9.cjs → CalendarWidget-VjQXZW8B.cjs} +2 -2
  4. package/dist/{CalendarWidget-oGK122s9.cjs.map → CalendarWidget-VjQXZW8B.cjs.map} +1 -1
  5. package/dist/{CardWidget-CqYjGkq-.mjs → CardWidget-BNkMlxQ3.mjs} +2 -2
  6. package/dist/{CardWidget-CqYjGkq-.mjs.map → CardWidget-BNkMlxQ3.mjs.map} +1 -1
  7. package/dist/{CardWidget-CSLSlKM6.cjs → CardWidget-C3I9OwgS.cjs} +2 -2
  8. package/dist/{CardWidget-CSLSlKM6.cjs.map → CardWidget-C3I9OwgS.cjs.map} +1 -1
  9. package/dist/{CardWidget-DjhK0yr-.cjs → CardWidget-CraWMttj.cjs} +3 -3
  10. package/dist/{CarouselWidget-DlxYQB5j.cjs → CarouselWidget-CiKlooUF.cjs} +2 -2
  11. package/dist/{CarouselWidget-DlxYQB5j.cjs.map → CarouselWidget-CiKlooUF.cjs.map} +1 -1
  12. package/dist/{CarouselWidget-CdQhlRrW.mjs → CarouselWidget-p8Z6L-G5.mjs} +2 -2
  13. package/dist/{CarouselWidget-CdQhlRrW.mjs.map → CarouselWidget-p8Z6L-G5.mjs.map} +1 -1
  14. package/dist/{CatchUpWidget-BQjtjcGR.mjs → CatchUpWidget-B9DQlzd_.mjs} +2 -2
  15. package/dist/{CatchUpWidget-BQjtjcGR.mjs.map → CatchUpWidget-B9DQlzd_.mjs.map} +1 -1
  16. package/dist/{CatchUpWidget-B1Muaurg.cjs → CatchUpWidget-SY7hOHk6.cjs} +2 -2
  17. package/dist/{CatchUpWidget-B1Muaurg.cjs.map → CatchUpWidget-SY7hOHk6.cjs.map} +1 -1
  18. package/dist/{ContainerWidget-Cjwrq2MS.cjs → ContainerWidget-BXpdj06u.cjs} +2 -2
  19. package/dist/{ContainerWidget-Cjwrq2MS.cjs.map → ContainerWidget-BXpdj06u.cjs.map} +1 -1
  20. package/dist/{ContainerWidget-DYThUtiZ.mjs → ContainerWidget-CpwvcxFm.mjs} +2 -2
  21. package/dist/{ContainerWidget-DYThUtiZ.mjs.map → ContainerWidget-CpwvcxFm.mjs.map} +1 -1
  22. package/dist/ContainerWidget-CyfPYEAv.cjs +8 -0
  23. package/dist/{FluidProvider-BazvsIwu.mjs → FluidProvider-DL5rChtj.mjs} +67 -84
  24. package/dist/FluidProvider-DL5rChtj.mjs.map +1 -0
  25. package/dist/{FluidProvider-Dxn7Ehiz.cjs → FluidProvider-D_PHVlUU.cjs} +67 -84
  26. package/dist/FluidProvider-D_PHVlUU.cjs.map +1 -0
  27. package/dist/{ImageWidget-xcE0sFf-.cjs → ImageWidget-CbQVxMe3.cjs} +2 -2
  28. package/dist/{ImageWidget-xcE0sFf-.cjs.map → ImageWidget-CbQVxMe3.cjs.map} +1 -1
  29. package/dist/{ImageWidget-CFTpbu8X.mjs → ImageWidget-vNWT_O1E.mjs} +2 -2
  30. package/dist/{ImageWidget-CFTpbu8X.mjs.map → ImageWidget-vNWT_O1E.mjs.map} +1 -1
  31. package/dist/{LayoutWidget-CK-SvFQL.cjs → LayoutWidget-BIfNHlVE.cjs} +2 -2
  32. package/dist/{LayoutWidget-CK-SvFQL.cjs.map → LayoutWidget-BIfNHlVE.cjs.map} +1 -1
  33. package/dist/{LayoutWidget-Cx5ZyXSU.mjs → LayoutWidget-CC3oK78H.mjs} +2 -2
  34. package/dist/{LayoutWidget-Cx5ZyXSU.mjs.map → LayoutWidget-CC3oK78H.mjs.map} +1 -1
  35. package/dist/{LayoutWidget-DuueFNAS.cjs → LayoutWidget-LdF_cKrB.cjs} +3 -3
  36. package/dist/{LinkWidget-B14FTQP7.cjs → LinkWidget-BoR7nVbH.cjs} +2 -2
  37. package/dist/{LinkWidget-B14FTQP7.cjs.map → LinkWidget-BoR7nVbH.cjs.map} +1 -1
  38. package/dist/{LinkWidget-CQHmKO-O.mjs → LinkWidget-CO-Cxf7Z.mjs} +2 -2
  39. package/dist/{LinkWidget-CQHmKO-O.mjs.map → LinkWidget-CO-Cxf7Z.mjs.map} +1 -1
  40. package/dist/{LinkWidget-CPmE8gpd.cjs → LinkWidget-M9YzMJT8.cjs} +2 -2
  41. package/dist/{ListWidget-YvCp7XDq.cjs → ListWidget-CuSjvwEw.cjs} +3 -3
  42. package/dist/{ListWidget-wBDnXWxa.cjs → ListWidget-CzljZ1LA.cjs} +3 -3
  43. package/dist/{ListWidget-wBDnXWxa.cjs.map → ListWidget-CzljZ1LA.cjs.map} +1 -1
  44. package/dist/{ListWidget-BnyD2Hpc.mjs → ListWidget-f88QhcGI.mjs} +3 -3
  45. package/dist/{ListWidget-BnyD2Hpc.mjs.map → ListWidget-f88QhcGI.mjs.map} +1 -1
  46. package/dist/{MediaRenderer-CfgWd0cC.cjs → MediaRenderer-CvN8Ku0i.cjs} +4 -4
  47. package/dist/MediaRenderer-CvN8Ku0i.cjs.map +1 -0
  48. package/dist/{MediaRenderer-CqUpv3St.mjs → MediaRenderer-DMdb_5xw.mjs} +4 -4
  49. package/dist/MediaRenderer-DMdb_5xw.mjs.map +1 -0
  50. package/dist/{MessagingScreen-40YCQbX9.cjs → MessagingScreen-Dkh3Dsp7.cjs} +2 -2
  51. package/dist/{MessagingScreen-40YCQbX9.cjs.map → MessagingScreen-Dkh3Dsp7.cjs.map} +1 -1
  52. package/dist/{MessagingScreen-CrdiB4M3.cjs → MessagingScreen-Dxy2VQbO.cjs} +22 -22
  53. package/dist/{MessagingScreen-RItZgONw.mjs → MessagingScreen-mt1u3Bs1.mjs} +2 -2
  54. package/dist/{MessagingScreen-RItZgONw.mjs.map → MessagingScreen-mt1u3Bs1.mjs.map} +1 -1
  55. package/dist/{MySiteWidget-B0dc_7Dc.mjs → MySiteWidget-BnjPrQxE.mjs} +23 -30
  56. package/dist/MySiteWidget-BnjPrQxE.mjs.map +1 -0
  57. package/dist/{MySiteWidget-BkqAS0aY.cjs → MySiteWidget-C8eFWHOT.cjs} +23 -30
  58. package/dist/MySiteWidget-C8eFWHOT.cjs.map +1 -0
  59. package/dist/{NestedWidget-C_2XwnW0.cjs → NestedWidget-CEoAO2sp.cjs} +3 -3
  60. package/dist/{NestedWidget-C_2XwnW0.cjs.map → NestedWidget-CEoAO2sp.cjs.map} +1 -1
  61. package/dist/{NestedWidget-CXIvsJdD.cjs → NestedWidget-CMCZjV6t.cjs} +3 -3
  62. package/dist/{NestedWidget-WJoWOFda.mjs → NestedWidget-RuyrOrFn.mjs} +3 -3
  63. package/dist/{NestedWidget-WJoWOFda.mjs.map → NestedWidget-RuyrOrFn.mjs.map} +1 -1
  64. package/dist/{PointsWidget-DoUljaNY.mjs → PointsWidget-C2KB4k48.mjs} +2 -2
  65. package/dist/{PointsWidget-DoUljaNY.mjs.map → PointsWidget-C2KB4k48.mjs.map} +1 -1
  66. package/dist/{PointsWidget-CLUWrFjZ.cjs → PointsWidget-DLp-PYus.cjs} +2 -2
  67. package/dist/{PointsWidget-CLUWrFjZ.cjs.map → PointsWidget-DLp-PYus.cjs.map} +1 -1
  68. package/dist/{ProfileScreen-CEKbhSRz.cjs → ProfileScreen-BMe-dQi7.cjs} +2 -2
  69. package/dist/{ProfileScreen-CEKbhSRz.cjs.map → ProfileScreen-BMe-dQi7.cjs.map} +1 -1
  70. package/dist/{ProfileScreen-Dex8VHSB.cjs → ProfileScreen-ChCZZ91o.cjs} +22 -22
  71. package/dist/{ProfileScreen-CeD1jq89.mjs → ProfileScreen-_1GlBr7z.mjs} +2 -2
  72. package/dist/{ProfileScreen-CeD1jq89.mjs.map → ProfileScreen-_1GlBr7z.mjs.map} +1 -1
  73. package/dist/{RecentActivityWidget-C6RwlUUw.cjs → RecentActivityWidget-BNW9aFT4.cjs} +2 -2
  74. package/dist/{RecentActivityWidget-C6RwlUUw.cjs.map → RecentActivityWidget-BNW9aFT4.cjs.map} +1 -1
  75. package/dist/{RecentActivityWidget-zQxtUECm.mjs → RecentActivityWidget-DelPdiwR.mjs} +2 -2
  76. package/dist/{RecentActivityWidget-zQxtUECm.mjs.map → RecentActivityWidget-DelPdiwR.mjs.map} +1 -1
  77. package/dist/{ScreenRenderer-Bk23YOtN.mjs → ScreenRenderer-ClYgfQf_.mjs} +2 -2
  78. package/dist/{ScreenRenderer-Bk23YOtN.mjs.map → ScreenRenderer-ClYgfQf_.mjs.map} +1 -1
  79. package/dist/{ScreenRenderer-aYfgv6mR.cjs → ScreenRenderer-Ct1w4PNu.cjs} +2 -2
  80. package/dist/{ScreenRenderer-aYfgv6mR.cjs.map → ScreenRenderer-Ct1w4PNu.cjs.map} +1 -1
  81. package/dist/{ShareablesScreen-Bt0E1aya.cjs → ShareablesScreen-A69L0Nok.cjs} +136 -108
  82. package/dist/ShareablesScreen-A69L0Nok.cjs.map +1 -0
  83. package/dist/{ShareablesScreen-LSyiDa6q.cjs → ShareablesScreen-BUYG-mjj.cjs} +1 -1
  84. package/dist/{ShareablesScreen-D3Hfqg9-.mjs → ShareablesScreen-sieWBlAl.mjs} +136 -108
  85. package/dist/ShareablesScreen-sieWBlAl.mjs.map +1 -0
  86. package/dist/{ShopScreen-dAe71cdL.mjs → ShopScreen-BBfOte5o.mjs} +2 -2
  87. package/dist/{ShopScreen-dAe71cdL.mjs.map → ShopScreen-BBfOte5o.mjs.map} +1 -1
  88. package/dist/{ShopScreen-Cgro0M1d.cjs → ShopScreen-CZ_290EP.cjs} +22 -22
  89. package/dist/{ShopScreen-BiqZPyiB.cjs → ShopScreen-DWLGH2gt.cjs} +2 -2
  90. package/dist/{ShopScreen-BiqZPyiB.cjs.map → ShopScreen-DWLGH2gt.cjs.map} +1 -1
  91. package/dist/{TableWidget-D4jQN-to.cjs → TableWidget-BIn1oRiJ.cjs} +4 -4
  92. package/dist/TableWidget-BIn1oRiJ.cjs.map +1 -0
  93. package/dist/{TableWidget-DWAYgQcl.cjs → TableWidget-C--8TSX7.cjs} +3 -3
  94. package/dist/{TableWidget-B0CRdzNf.mjs → TableWidget-dfUvhH0S.mjs} +4 -4
  95. package/dist/TableWidget-dfUvhH0S.mjs.map +1 -0
  96. package/dist/{ToDoWidget-BbeXt99H.cjs → ToDoWidget-Bjoan2Rm.cjs} +2 -2
  97. package/dist/{ToDoWidget-BbeXt99H.cjs.map → ToDoWidget-Bjoan2Rm.cjs.map} +1 -1
  98. package/dist/{ToDoWidget-VSaNmtWH.mjs → ToDoWidget-CYDsZA0Z.mjs} +2 -2
  99. package/dist/{ToDoWidget-VSaNmtWH.mjs.map → ToDoWidget-CYDsZA0Z.mjs.map} +1 -1
  100. package/dist/{ToDoWidget-YHmoDbVU.cjs → ToDoWidget-C_CvWdLi.cjs} +2 -2
  101. package/dist/{VideoWidget-Bc6ZAAaA.cjs → VideoWidget-CDcV0J5W.cjs} +2 -2
  102. package/dist/{VideoWidget-Bc6ZAAaA.cjs.map → VideoWidget-CDcV0J5W.cjs.map} +1 -1
  103. package/dist/{VideoWidget-DcWm239R.mjs → VideoWidget-Dj9wue7j.mjs} +2 -2
  104. package/dist/{VideoWidget-DcWm239R.mjs.map → VideoWidget-Dj9wue7j.mjs.map} +1 -1
  105. package/dist/WidgetInteractionContext-B1mELhQ_.mjs +28 -0
  106. package/dist/{WidgetInteractionContext-D0TJv70C.mjs.map → WidgetInteractionContext-B1mELhQ_.mjs.map} +1 -1
  107. package/dist/WidgetInteractionContext-DvPmzGqB.cjs +41 -0
  108. package/dist/{WidgetInteractionContext-Bs3LkFFH.cjs.map → WidgetInteractionContext-DvPmzGqB.cjs.map} +1 -1
  109. package/dist/index.cjs +84 -55
  110. package/dist/index.cjs.map +1 -1
  111. package/dist/index.d.cts.map +1 -1
  112. package/dist/index.d.mts.map +1 -1
  113. package/dist/index.mjs +84 -55
  114. package/dist/index.mjs.map +1 -1
  115. package/dist/{registry-context-BDH0vNHR.mjs → registry-context-BahYMRqn.mjs} +12 -20
  116. package/dist/registry-context-BahYMRqn.mjs.map +1 -0
  117. package/dist/{registry-context-C7-RLxVt.cjs → registry-context-bf52ZIJX.cjs} +12 -20
  118. package/dist/registry-context-bf52ZIJX.cjs.map +1 -0
  119. package/package.json +12 -12
  120. package/dist/ContainerWidget-NFBqSeRV.cjs +0 -8
  121. package/dist/FluidProvider-BazvsIwu.mjs.map +0 -1
  122. package/dist/FluidProvider-Dxn7Ehiz.cjs.map +0 -1
  123. package/dist/MediaRenderer-CfgWd0cC.cjs.map +0 -1
  124. package/dist/MediaRenderer-CqUpv3St.mjs.map +0 -1
  125. package/dist/MySiteWidget-B0dc_7Dc.mjs.map +0 -1
  126. package/dist/MySiteWidget-BkqAS0aY.cjs.map +0 -1
  127. package/dist/ShareablesScreen-Bt0E1aya.cjs.map +0 -1
  128. package/dist/ShareablesScreen-D3Hfqg9-.mjs.map +0 -1
  129. package/dist/TableWidget-B0CRdzNf.mjs.map +0 -1
  130. package/dist/TableWidget-D4jQN-to.cjs.map +0 -1
  131. package/dist/WidgetInteractionContext-Bs3LkFFH.cjs +0 -18
  132. package/dist/WidgetInteractionContext-D0TJv70C.mjs +0 -11
  133. package/dist/registry-context-BDH0vNHR.mjs.map +0 -1
  134. package/dist/registry-context-C7-RLxVt.cjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"TableWidget-B0CRdzNf.mjs","names":[],"sources":["../../widgets/src/widgets/TableWidget.tsx"],"sourcesContent":["import { useState, useMemo, 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 borderWidthClasses,\n borderColorClasses,\n getColorField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport { Input } from \"@fluid-app/ui-primitives\";\nimport {\n MediaRenderer,\n getMediaPropsFromShareable,\n} from \"../components/MediaRenderer\";\nimport { type ShareableItem } from \"@fluid-app/portal-core/types\";\nimport { useWidgetInteraction } from \"../contexts/WidgetInteractionContext\";\n\n/** Plain column definition provided by data sources (no render functions) */\nexport type TableColumnDef = {\n key: string;\n label: string;\n sortable: boolean;\n};\n\n// Internal column definition (includes render function)\ntype ColumnDef = TableColumnDef & {\n render?: (value: unknown, item: ShareableItem) => React.ReactNode;\n};\n\nconst DEFAULT_DATA: ShareableItem[] = [];\n\n// ---------------------------------------------------------------------------\n// Column cell renderers\n// ---------------------------------------------------------------------------\n\nfunction ImageCellRenderer(_value: unknown, item: ShareableItem) {\n return (\n <div className=\"h-10 w-10 rounded object-cover\">\n <MediaRenderer {...getMediaPropsFromShareable(item)} />\n </div>\n );\n}\n\nfunction PriceCellRenderer(_value: unknown, item: ShareableItem) {\n return ((item.display_price as string) ?? item.price) || \"-\";\n}\n\nfunction StatusCellRenderer(value: unknown) {\n const status = String(value || \"unknown\").toLowerCase();\n const statusStyles: Record<string, string> = {\n active: \"bg-primary text-primary-foreground\",\n paid: \"bg-primary text-primary-foreground\",\n inactive: \"bg-secondary text-secondary-foreground\",\n paused: \"bg-secondary text-secondary-foreground\",\n unknown: \"bg-muted text-muted-foreground\",\n unpaid: \"bg-destructive text-destructive-foreground\",\n refunded: \"bg-muted text-muted-foreground\",\n cancelled: \"bg-destructive text-destructive-foreground\",\n };\n return (\n <span\n className={`inline-flex rounded-full px-2 py-1 text-xs font-medium ${statusStyles[status] || \"bg-muted text-foreground\"}`}\n >\n {String(value || \"Unknown\")}\n </span>\n );\n}\n\n/** Map of column keys to custom cell renderers */\nconst CELL_RENDERERS: Record<\n string,\n (value: unknown, item: ShareableItem) => React.ReactNode\n> = {\n imageUrl: ImageCellRenderer,\n price: PriceCellRenderer,\n display_price: PriceCellRenderer,\n status: StatusCellRenderer,\n};\n\n/** Resolve plain column definitions from a data source into full ColumnDefs with renderers */\nfunction resolveColumns(columns: TableColumnDef[]): ColumnDef[] {\n return columns.map((col) => {\n const render = CELL_RENDERERS[col.key];\n return render ? { ...col, render } : { ...col };\n });\n}\n\n// Default columns for product data\nconst defaultColumns: ColumnDef[] = [\n {\n key: \"imageUrl\",\n label: \"Image\",\n sortable: false,\n render: ImageCellRenderer,\n },\n {\n key: \"title\",\n label: \"Title\",\n sortable: true,\n },\n {\n key: \"price\",\n label: \"Price\",\n sortable: true,\n render: PriceCellRenderer,\n },\n {\n key: \"status\",\n label: \"Status\",\n sortable: true,\n render: StatusCellRenderer,\n },\n];\n\ntype TableWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n background?: BackgroundValue;\n alternatingColorEnabled?: boolean;\n textColor?: ColorOptions;\n headerBackgroundColor?: ColorOptions;\n headerTextColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n\n // Data\n data?: ShareableItem[];\n /** Column definitions from a data source (plain data, renderers resolved internally) */\n columns?: TableColumnDef[];\n\n // Features\n filterEnabled?: boolean;\n sortingEnabled?: boolean;\n paginationEnabled?: boolean;\n maxRowsPerPage?: number;\n};\n\nexport function TableWidget({\n // Title defaults\n titleEnabled = true,\n titleText = \"Products\",\n titleFontSize = \"xl\",\n titleColor = \"foreground\",\n\n // Styling defaults\n background = {\n type: \"solid\",\n color: \"background\",\n },\n alternatingColorEnabled = true,\n textColor = \"foreground\",\n headerBackgroundColor = \"muted\",\n headerTextColor = \"foreground\",\n padding = 4,\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n\n // Data\n data = DEFAULT_DATA,\n columns: columnsProp,\n\n // Feature defaults\n filterEnabled = true,\n sortingEnabled = true,\n paginationEnabled = true,\n maxRowsPerPage = 5,\n\n className,\n ...props\n}: TableWidgetProps): React.JSX.Element {\n const backgroundColor = background.color || \"background\";\n const isImageBackground = background.type === \"image\";\n const backgroundImage =\n (background.resource?.image_url || background.resource?.imageUrl) &&\n isImageBackground\n ? `url(${background.resource.image_url || background.resource.imageUrl})`\n : \"none\";\n const pageSize = maxRowsPerPage;\n\n // When using an image or transparent background, inner elements should be\n // transparent so the image/page shows through. Otherwise use the configured colors.\n const isTransparentBg = backgroundColor === \"transparent\";\n const useTransparentInner = isImageBackground || isTransparentBg;\n const innerBg = useTransparentInner\n ? \"bg-transparent\"\n : `bg-${backgroundColor}`;\n const innerBgAlt = useTransparentInner\n ? \"bg-black/5\"\n : `bg-${backgroundColor}/40`;\n const transparentBorder = isTransparentBg\n ? \"border-black/20\"\n : \"border-white/20\";\n const innerBorder = useTransparentInner\n ? transparentBorder\n : `border-${backgroundColor}/60`;\n const headerBg = useTransparentInner\n ? \"bg-black/10\"\n : `bg-${headerBackgroundColor}/40`;\n const headerBorder = useTransparentInner\n ? transparentBorder\n : `border-${headerBackgroundColor}/60`;\n const paginationBg = useTransparentInner\n ? \"bg-black/10\"\n : `bg-${backgroundColor}/40`;\n\n // State for filtering, sorting, and pagination\n const [globalFilter, setGlobalFilter] = useState(\"\");\n const [sortConfig, setSortConfig] = useState<{\n key: string;\n direction: \"asc\" | \"desc\";\n } | null>(null);\n const [currentPage, setCurrentPage] = useState(1);\n\n // Only use columns from the data source if they look like valid column defs\n // (have a `key` string). When transformers return a plain array (e.g. toShareableProps),\n // use-widget-data maps the same array to ALL targetProps, so `columns` may\n // receive the data rows instead of column definitions.\n const firstCol = columnsProp?.[0];\n const validColumnsProp =\n firstCol && typeof firstCol.key === \"string\" && firstCol.key !== \"\"\n ? columnsProp\n : undefined;\n\n const columns = useMemo(\n () =>\n validColumnsProp ? resolveColumns(validColumnsProp) : defaultColumns,\n [validColumnsProp],\n );\n\n // Filter data\n const filteredData = useMemo(() => {\n let result = [...data];\n\n if (globalFilter) {\n const lowerFilter = globalFilter.toLowerCase();\n result = result.filter((item) =>\n columns.some((col) => {\n const value = item[col.key];\n return String(value ?? \"\")\n .toLowerCase()\n .includes(lowerFilter);\n }),\n );\n }\n\n return result;\n }, [data, globalFilter, columns]);\n\n // Sort data\n const sortedData = useMemo(() => {\n if (!sortConfig) return filteredData;\n\n return [...filteredData].sort((a, b) => {\n const aValue = a[sortConfig.key];\n const bValue = b[sortConfig.key];\n\n // Handle null/undefined\n if (aValue == null && bValue == null) return 0;\n if (aValue == null) return sortConfig.direction === \"asc\" ? 1 : -1;\n if (bValue == null) return sortConfig.direction === \"asc\" ? -1 : 1;\n\n // Compare values\n let comparison = 0;\n if (typeof aValue === \"number\" && typeof bValue === \"number\") {\n comparison = aValue - bValue;\n } else {\n comparison = String(aValue).localeCompare(String(bValue));\n }\n\n return sortConfig.direction === \"asc\" ? comparison : -comparison;\n });\n }, [filteredData, sortConfig]);\n\n // Paginate data\n const paginatedData = useMemo(() => {\n if (!paginationEnabled) return sortedData;\n\n const startIndex = (currentPage - 1) * pageSize;\n return sortedData.slice(startIndex, startIndex + pageSize);\n }, [sortedData, currentPage, pageSize, paginationEnabled]);\n\n const totalPages = Math.ceil(sortedData.length / pageSize);\n\n // Reset to page 1 when filters change\n const handleGlobalFilterChange = (value: string) => {\n setGlobalFilter(value);\n setCurrentPage(1);\n };\n\n // Handle sort\n const handleSort = (key: string) => {\n if (!sortingEnabled) return;\n\n setSortConfig((prev) => {\n if (prev?.key !== key) return { key, direction: \"asc\" };\n if (prev.direction === \"asc\") return { key, direction: \"desc\" };\n return null;\n });\n };\n\n // Get sort indicator\n const getSortIndicator = (key: string) => {\n if (sortConfig?.key !== key) return null;\n return sortConfig.direction === \"asc\" ? \" ↑\" : \" ↓\";\n };\n\n const { onItemClick } = useWidgetInteraction();\n\n return (\n <div\n className={`@container overflow-hidden ${paginationEnabled ? \"\" : \"overflow-y-auto\"} rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-${backgroundColor} bg-cover bg-center text-${textColor} ${className}`}\n style={{ backgroundImage }}\n {...props}\n >\n <div\n className={`flex items-center justify-between p-${padding} ${innerBg} space-x-2`}\n >\n {/* Title */}\n {titleEnabled && titleText && (\n <h2\n className={`text-${titleFontSize === \"md\" ? \"base\" : titleFontSize} font-header font-bold text-${titleColor} min-w-0 truncate`}\n >\n {titleText}\n </h2>\n )}\n\n {/* Global Search */}\n {filterEnabled && (\n <Input\n type=\"text\"\n placeholder=\"Search all columns...\"\n value={globalFilter}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n handleGlobalFilterChange(e.target.value)\n }\n className={`w-full rounded-md border ${headerBorder} ${headerBg} ring-offset-muted px-3 py-2 text-sm placeholder:text-${headerTextColor}/40 focus-visible:ring-primary focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none md:w-64`}\n />\n )}\n </div>\n\n {/* Table */}\n <div className=\"overflow-x-auto\">\n <table className=\"w-full border-collapse\">\n <thead>\n <tr className={`${headerBg} ${headerBorder} border-y`}>\n {columns.map((col) => (\n <th\n key={col.key}\n className={`px-4 py-3 text-left text-sm font-semibold text-${headerTextColor} ${col.sortable && sortingEnabled ? \"cursor-pointer select-none hover:opacity-80\" : \"\"}`}\n {...(col.sortable && sortingEnabled\n ? {\n role: \"button\" as const,\n tabIndex: 0,\n onClick: () => handleSort(col.key),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleSort(col.key);\n }\n },\n }\n : {})}\n >\n <div className=\"flex flex-col gap-1\">\n <span>\n {col.label}\n {col.sortable &&\n sortingEnabled &&\n getSortIndicator(col.key)}\n </span>\n </div>\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {data.length === 0 ? (\n <tr>\n <td colSpan={columns.length}>\n <div className=\"text-muted-foreground flex min-h-[200px] flex-col items-center justify-center gap-2\">\n <div className=\"text-4xl\">📋</div>\n <p className=\"text-sm\">No data available</p>\n <p className=\"text-muted-foreground/70 text-xs\">\n Connect a data source to display table data\n </p>\n </div>\n </td>\n </tr>\n ) : paginatedData.length === 0 ? (\n <tr>\n <td colSpan={columns.length}>\n <div className=\"py-8 text-center\">\n <p className=\"text-sm\">No results found</p>\n <p className=\"text-xs\">Try adjusting your search</p>\n </div>\n </td>\n </tr>\n ) : (\n <>\n {paginatedData.map((item, index) => (\n <tr\n key={item.id ?? index}\n className={`h-17 border-b ${innerBorder} last:border-none ${innerBg} ${alternatingColorEnabled ? `even:${innerBgAlt}` : \"\"} ${onItemClick ? \"cursor-pointer hover:opacity-80\" : \"\"}`}\n {...(onItemClick\n ? {\n tabIndex: 0,\n onClick: () => onItemClick(item),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onItemClick(item);\n }\n },\n }\n : {})}\n >\n {columns.map((col) => (\n <td key={col.key} className=\"px-4 py-3 text-sm\">\n {col.render\n ? col.render(item[col.key], item)\n : String(item[col.key] ?? \"-\")}\n </td>\n ))}\n </tr>\n ))}\n {/* Empty rows to fill the last page for consistent pagination position */}\n {paginationEnabled &&\n paginatedData.length < pageSize &&\n paginatedData.length > 0 &&\n Array.from({ length: pageSize - paginatedData.length }).map(\n (_, index) => (\n <tr\n key={`empty-${index}`}\n className={`h-17 border-b ${innerBorder} last:border-none ${innerBg} ${alternatingColorEnabled ? `even:${innerBgAlt}` : \"\"}`}\n >\n {columns.map((col) => (\n <td key={col.key} className=\"px-4 py-3 text-sm\">\n &nbsp;\n </td>\n ))}\n </tr>\n ),\n )}\n </>\n )}\n </tbody>\n </table>\n </div>\n\n {/* Pagination */}\n {paginationEnabled && totalPages > 1 && (\n <div\n className={`flex flex-col items-center justify-between gap-2 border-t ${innerBorder} p-${padding} @md:flex-row ${paginationBg} text-${textColor}`}\n >\n <p className=\"text-sm\">\n Showing {(currentPage - 1) * pageSize + 1}-\n {Math.min(currentPage * pageSize, sortedData.length)} of{\" \"}\n {sortedData.length} results\n </p>\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => setCurrentPage((p) => Math.max(1, p - 1))}\n disabled={currentPage === 1}\n className={`rounded-md border border-${headerBackgroundColor}/60 bg-${headerBackgroundColor} ring-offset-muted placeholder:text-muted-foreground focus-visible:ring-primary px-3 py-1 text-sm transition-opacity hover:opacity-80 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50`}\n >\n Previous\n </button>\n <span className=\"text-sm\">\n Page {currentPage} of {totalPages}\n </span>\n <button\n onClick={() => setCurrentPage((p) => Math.min(totalPages, p + 1))}\n disabled={currentPage === totalPages}\n className={`rounded-md border border-${headerBackgroundColor}/60 bg-${headerBackgroundColor} ring-offset-muted placeholder:text-muted-foreground focus-visible:ring-primary px-3 py-1 text-sm transition-opacity hover:opacity-80 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50`}\n >\n Next\n </button>\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport const tableWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"TableWidget\",\n displayName: \"Table Widget\",\n tabsConfig: [\n { id: \"styling\", label: \"Styling\" },\n { id: \"behavior\", label: \"Behavior\" },\n { id: \"data\", label: \"Data\" },\n ],\n dataSourceTargetProps: [\"data\", \"columns\"],\n fields: [\n // Content Tab - Title Group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed above the table\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Title text displayed above the table\",\n defaultValue: \"Products\",\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 key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Styling Tab - Design Group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the table container\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"alternatingColorEnabled\",\n label: \"Enable Alternating Colors\",\n type: \"boolean\",\n description: \"Enable alternating colors for table rows\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n getColorField({\n key: \"headerBackgroundColor\",\n label: \"Header Background\",\n description: \"Background color for the table header\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for table content\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"headerTextColor\",\n label: \"Header Text Color\",\n description: \"Text color for the table header\",\n defaultValue: \"foreground\",\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 getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the table container\",\n defaultValue: 4,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the table container\",\n defaultValue: \"md\",\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 // Behavior Tab - Features Group\n {\n key: \"filterEnabled\",\n label: \"Enable Filters\",\n type: \"boolean\",\n description: \"Show global search and column filters\",\n defaultValue: true,\n tab: \"behavior\",\n group: \"Features\",\n },\n {\n key: \"sortingEnabled\",\n label: \"Enable Sorting\",\n type: \"boolean\",\n description: \"Allow sorting by clicking column headers\",\n defaultValue: true,\n tab: \"behavior\",\n group: \"Features\",\n },\n {\n key: \"paginationEnabled\",\n label: \"Enable Pagination\",\n type: \"boolean\",\n description: \"Split data into pages\",\n defaultValue: true,\n tab: \"behavior\",\n group: \"Features\",\n },\n {\n key: \"maxRowsPerPage\",\n label: \"Max Rows Per Page\",\n type: \"number\",\n description: \"Maximum number of rows to display per page\",\n min: 1,\n max: 50,\n step: 1,\n defaultValue: 5,\n tab: \"behavior\",\n group: \"Features\",\n requiresKeyToBeTrue: \"paginationEnabled\",\n },\n\n // Data Tab\n {\n key: \"dataSource\",\n label: \"Data Source\",\n type: \"dataSource\",\n description: \"Configure data source for the table\",\n tab: \"data\",\n group: \"Data Configuration\",\n },\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":";;;;;;;;;;;;AAyCA,MAAM,eAAgC,EAAE;AAMxC,SAAS,kBAAkB,QAAiB,MAAqB;AAC/D,QACE,oBAAC,OAAD;EAAK,WAAU;YACb,oBAAC,eAAD,EAAe,GAAI,2BAA2B,KAAK,EAAI,CAAA;EACnD,CAAA;;AAIV,SAAS,kBAAkB,QAAiB,MAAqB;AAC/D,SAAS,KAAK,iBAA4B,KAAK,UAAU;;AAG3D,SAAS,mBAAmB,OAAgB;AAY1C,QACE,oBAAC,QAAD;EACE,WAAW,0DAZ8B;GAC3C,QAAQ;GACR,MAAM;GACN,UAAU;GACV,QAAQ;GACR,SAAS;GACT,QAAQ;GACR,UAAU;GACV,WAAW;GACZ,CAVc,OAAO,SAAS,UAAU,CAAC,aAAa,KAa0C;YAE5F,OAAO,SAAS,UAAU;EACtB,CAAA;;;AAKX,MAAM,iBAGF;CACF,UAAU;CACV,OAAO;CACP,eAAe;CACf,QAAQ;CACT;;AAGD,SAAS,eAAe,SAAwC;AAC9D,QAAO,QAAQ,KAAK,QAAQ;EAC1B,MAAM,SAAS,eAAe,IAAI;AAClC,SAAO,SAAS;GAAE,GAAG;GAAK;GAAQ,GAAG,EAAE,GAAG,KAAK;GAC/C;;AAIJ,MAAM,iBAA8B;CAClC;EACE,KAAK;EACL,OAAO;EACP,UAAU;EACV,QAAQ;EACT;CACD;EACE,KAAK;EACL,OAAO;EACP,UAAU;EACX;CACD;EACE,KAAK;EACL,OAAO;EACP,UAAU;EACV,QAAQ;EACT;CACD;EACE,KAAK;EACL,OAAO;EACP,UAAU;EACV,QAAQ;EACT;CACF;AAgCD,SAAgB,YAAY,EAE1B,eAAe,MACf,YAAY,YACZ,gBAAgB,MAChB,aAAa,cAGb,aAAa;CACX,MAAM;CACN,OAAO;CACR,EACD,0BAA0B,MAC1B,YAAY,cACZ,wBAAwB,SACxB,kBAAkB,cAClB,UAAU,GACV,eAAe,MACf,cAAc,QACd,cAAc,SAGd,OAAO,cACP,SAAS,aAGT,gBAAgB,MAChB,iBAAiB,MACjB,oBAAoB,MACpB,iBAAiB,GAEjB,WACA,GAAG,SACmC;CACtC,MAAM,kBAAkB,WAAW,SAAS;CAC5C,MAAM,oBAAoB,WAAW,SAAS;CAC9C,MAAM,mBACH,WAAW,UAAU,aAAa,WAAW,UAAU,aACxD,oBACI,OAAO,WAAW,SAAS,aAAa,WAAW,SAAS,SAAS,KACrE;CACN,MAAM,WAAW;CAIjB,MAAM,kBAAkB,oBAAoB;CAC5C,MAAM,sBAAsB,qBAAqB;CACjD,MAAM,UAAU,sBACZ,mBACA,MAAM;CACV,MAAM,aAAa,sBACf,eACA,MAAM,gBAAgB;CAC1B,MAAM,oBAAoB,kBACtB,oBACA;CACJ,MAAM,cAAc,sBAChB,oBACA,UAAU,gBAAgB;CAC9B,MAAM,WAAW,sBACb,gBACA,MAAM,sBAAsB;CAChC,MAAM,eAAe,sBACjB,oBACA,UAAU,sBAAsB;CACpC,MAAM,eAAe,sBACjB,gBACA,MAAM,gBAAgB;CAG1B,MAAM,CAAC,cAAc,mBAAmB,SAAS,GAAG;CACpD,MAAM,CAAC,YAAY,iBAAiB,SAG1B,KAAK;CACf,MAAM,CAAC,aAAa,kBAAkB,SAAS,EAAE;CAMjD,MAAM,WAAW,cAAc;CAC/B,MAAM,mBACJ,YAAY,OAAO,SAAS,QAAQ,YAAY,SAAS,QAAQ,KAC7D,cACA,KAAA;CAEN,MAAM,UAAU,cAEZ,mBAAmB,eAAe,iBAAiB,GAAG,gBACxD,CAAC,iBAAiB,CACnB;CAGD,MAAM,eAAe,cAAc;EACjC,IAAI,SAAS,CAAC,GAAG,KAAK;AAEtB,MAAI,cAAc;GAChB,MAAM,cAAc,aAAa,aAAa;AAC9C,YAAS,OAAO,QAAQ,SACtB,QAAQ,MAAM,QAAQ;IACpB,MAAM,QAAQ,KAAK,IAAI;AACvB,WAAO,OAAO,SAAS,GAAG,CACvB,aAAa,CACb,SAAS,YAAY;KACxB,CACH;;AAGH,SAAO;IACN;EAAC;EAAM;EAAc;EAAQ,CAAC;CAGjC,MAAM,aAAa,cAAc;AAC/B,MAAI,CAAC,WAAY,QAAO;AAExB,SAAO,CAAC,GAAG,aAAa,CAAC,MAAM,GAAG,MAAM;GACtC,MAAM,SAAS,EAAE,WAAW;GAC5B,MAAM,SAAS,EAAE,WAAW;AAG5B,OAAI,UAAU,QAAQ,UAAU,KAAM,QAAO;AAC7C,OAAI,UAAU,KAAM,QAAO,WAAW,cAAc,QAAQ,IAAI;AAChE,OAAI,UAAU,KAAM,QAAO,WAAW,cAAc,QAAQ,KAAK;GAGjE,IAAI,aAAa;AACjB,OAAI,OAAO,WAAW,YAAY,OAAO,WAAW,SAClD,cAAa,SAAS;OAEtB,cAAa,OAAO,OAAO,CAAC,cAAc,OAAO,OAAO,CAAC;AAG3D,UAAO,WAAW,cAAc,QAAQ,aAAa,CAAC;IACtD;IACD,CAAC,cAAc,WAAW,CAAC;CAG9B,MAAM,gBAAgB,cAAc;AAClC,MAAI,CAAC,kBAAmB,QAAO;EAE/B,MAAM,cAAc,cAAc,KAAK;AACvC,SAAO,WAAW,MAAM,YAAY,aAAa,SAAS;IACzD;EAAC;EAAY;EAAa;EAAU;EAAkB,CAAC;CAE1D,MAAM,aAAa,KAAK,KAAK,WAAW,SAAS,SAAS;CAG1D,MAAM,4BAA4B,UAAkB;AAClD,kBAAgB,MAAM;AACtB,iBAAe,EAAE;;CAInB,MAAM,cAAc,QAAgB;AAClC,MAAI,CAAC,eAAgB;AAErB,iBAAe,SAAS;AACtB,OAAI,MAAM,QAAQ,IAAK,QAAO;IAAE;IAAK,WAAW;IAAO;AACvD,OAAI,KAAK,cAAc,MAAO,QAAO;IAAE;IAAK,WAAW;IAAQ;AAC/D,UAAO;IACP;;CAIJ,MAAM,oBAAoB,QAAgB;AACxC,MAAI,YAAY,QAAQ,IAAK,QAAO;AACpC,SAAO,WAAW,cAAc,QAAQ,OAAO;;CAGjD,MAAM,EAAE,gBAAgB,sBAAsB;AAE9C,QACE,qBAAC,OAAD;EACE,WAAW,8BAA8B,oBAAoB,KAAK,kBAAkB,WAAW,aAAa,GAAG,mBAAmB,aAAa,GAAG,gBAAgB,SAAS,mBAAmB,eAAe,GAAG,MAAM,gBAAgB,2BAA2B,UAAU,GAAG;EAC9Q,OAAO,EAAE,iBAAiB;EAC1B,GAAI;YAHN;GAKE,qBAAC,OAAD;IACE,WAAW,uCAAuC,QAAQ,GAAG,QAAQ;cADvE,CAIG,gBAAgB,aACf,oBAAC,MAAD;KACE,WAAW,QAAQ,kBAAkB,OAAO,SAAS,cAAc,8BAA8B,WAAW;eAE3G;KACE,CAAA,EAIN,iBACC,oBAAC,OAAD;KACE,MAAK;KACL,aAAY;KACZ,OAAO;KACP,WAAW,MACT,yBAAyB,EAAE,OAAO,MAAM;KAE1C,WAAW,4BAA4B,aAAa,GAAG,SAAS,wDAAwD,gBAAgB;KACxI,CAAA,CAEA;;GAGN,oBAAC,OAAD;IAAK,WAAU;cACb,qBAAC,SAAD;KAAO,WAAU;eAAjB,CACE,oBAAC,SAAD,EAAA,UACE,oBAAC,MAAD;MAAI,WAAW,GAAG,SAAS,GAAG,aAAa;gBACxC,QAAQ,KAAK,QACZ,oBAAC,MAAD;OAEE,WAAW,kDAAkD,gBAAgB,GAAG,IAAI,YAAY,iBAAiB,gDAAgD;OACjK,GAAK,IAAI,YAAY,iBACjB;QACE,MAAM;QACN,UAAU;QACV,eAAe,WAAW,IAAI,IAAI;QAClC,YAAY,MAA2B;AACrC,aAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,YAAE,gBAAgB;AAClB,qBAAW,IAAI,IAAI;;;QAGxB,GACD,EAAE;iBAEN,oBAAC,OAAD;QAAK,WAAU;kBACb,qBAAC,QAAD,EAAA,UAAA,CACG,IAAI,OACJ,IAAI,YACH,kBACA,iBAAiB,IAAI,IAAI,CACtB,EAAA,CAAA;QACH,CAAA;OACH,EAxBE,IAAI,IAwBN,CACL;MACC,CAAA,EACC,CAAA,EACR,oBAAC,SAAD,EAAA,UACG,KAAK,WAAW,IACf,oBAAC,MAAD,EAAA,UACE,oBAAC,MAAD;MAAI,SAAS,QAAQ;gBACnB,qBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,oBAAC,OAAD;SAAK,WAAU;mBAAW;SAAQ,CAAA;QAClC,oBAAC,KAAD;SAAG,WAAU;mBAAU;SAAqB,CAAA;QAC5C,oBAAC,KAAD;SAAG,WAAU;mBAAmC;SAE5C,CAAA;QACA;;MACH,CAAA,EACF,CAAA,GACH,cAAc,WAAW,IAC3B,oBAAC,MAAD,EAAA,UACE,oBAAC,MAAD;MAAI,SAAS,QAAQ;gBACnB,qBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,oBAAC,KAAD;QAAG,WAAU;kBAAU;QAAoB,CAAA,EAC3C,oBAAC,KAAD;QAAG,WAAU;kBAAU;QAA6B,CAAA,CAChD;;MACH,CAAA,EACF,CAAA,GAEL,qBAAA,YAAA,EAAA,UAAA,CACG,cAAc,KAAK,MAAM,UACxB,oBAAC,MAAD;MAEE,WAAW,iBAAiB,YAAY,oBAAoB,QAAQ,GAAG,0BAA0B,QAAQ,eAAe,GAAG,GAAG,cAAc,oCAAoC;MAChL,GAAK,cACD;OACE,UAAU;OACV,eAAe,YAAY,KAAK;OAChC,YAAY,MAA2B;AACrC,YAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,WAAE,gBAAgB;AAClB,qBAAY,KAAK;;;OAGtB,GACD,EAAE;gBAEL,QAAQ,KAAK,QACZ,oBAAC,MAAD;OAAkB,WAAU;iBACzB,IAAI,SACD,IAAI,OAAO,KAAK,IAAI,MAAM,KAAK,GAC/B,OAAO,KAAK,IAAI,QAAQ,IAAI;OAC7B,EAJI,IAAI,IAIR,CACL;MACC,EAtBE,KAAK,MAAM,MAsBb,CACL,EAED,qBACC,cAAc,SAAS,YACvB,cAAc,SAAS,KACvB,MAAM,KAAK,EAAE,QAAQ,WAAW,cAAc,QAAQ,CAAC,CAAC,KACrD,GAAG,UACF,oBAAC,MAAD;MAEE,WAAW,iBAAiB,YAAY,oBAAoB,QAAQ,GAAG,0BAA0B,QAAQ,eAAe;gBAEvH,QAAQ,KAAK,QACZ,oBAAC,MAAD;OAAkB,WAAU;iBAAoB;OAE3C,EAFI,IAAI,IAER,CACL;MACC,EARE,SAAS,QAQX,CAER,CACF,EAAA,CAAA,EAEC,CAAA,CACF;;IACJ,CAAA;GAGL,qBAAqB,aAAa,KACjC,qBAAC,OAAD;IACE,WAAW,6DAA6D,YAAY,KAAK,QAAQ,gBAAgB,aAAa,QAAQ;cADxI,CAGE,qBAAC,KAAD;KAAG,WAAU;eAAb;MAAuB;OACX,cAAc,KAAK,WAAW;MAAE;MACzC,KAAK,IAAI,cAAc,UAAU,WAAW,OAAO;MAAC;MAAI;MACxD,WAAW;MAAO;MACjB;QACJ,qBAAC,OAAD;KAAK,WAAU;eAAf;MACE,oBAAC,UAAD;OACE,eAAe,gBAAgB,MAAM,KAAK,IAAI,GAAG,IAAI,EAAE,CAAC;OACxD,UAAU,gBAAgB;OAC1B,WAAW,4BAA4B,sBAAsB,SAAS,sBAAsB;iBAC7F;OAEQ,CAAA;MACT,qBAAC,QAAD;OAAM,WAAU;iBAAhB;QAA0B;QAClB;QAAY;QAAK;QAClB;;MACP,oBAAC,UAAD;OACE,eAAe,gBAAgB,MAAM,KAAK,IAAI,YAAY,IAAI,EAAE,CAAC;OACjE,UAAU,gBAAgB;OAC1B,WAAW,4BAA4B,sBAAsB,SAAS,sBAAsB;iBAC7F;OAEQ,CAAA;MACL;OACF;;GAEJ;;;AAIV,MAAa,4BAAkD;CAC7D,YAAY;CACZ,aAAa;CACb,YAAY;EACV;GAAE,IAAI;GAAW,OAAO;GAAW;EACnC;GAAE,IAAI;GAAY,OAAO;GAAY;EACrC;GAAE,IAAI;GAAQ,OAAO;GAAQ;EAC9B;CACD,uBAAuB,CAAC,QAAQ,UAAU;CAC1C,QAAQ;EAEN;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD,iBAAiB;GACf,OAAO;GACP,cAAc;GACd,KAAK;GACL,aAAa;GACb,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EACF,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EAGF;GACE,MAAM;GACN,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,cAAc;GACZ,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,gBAAgB;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,qBAAqB;GACnB,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,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EAGF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EAGD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,OAAO;GACR;EACF;CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"TableWidget-D4jQN-to.cjs","names":["MediaRenderer","getMediaPropsFromShareable","useWidgetInteraction","borderWidthClasses","borderColorClasses","Input","getFontSizeField","getColorField","getPaddingField","getBorderRadiusField","getBorderWidthField","getBorderColorField"],"sources":["../../widgets/src/widgets/TableWidget.tsx"],"sourcesContent":["import { useState, useMemo, 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 borderWidthClasses,\n borderColorClasses,\n getColorField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport { Input } from \"@fluid-app/ui-primitives\";\nimport {\n MediaRenderer,\n getMediaPropsFromShareable,\n} from \"../components/MediaRenderer\";\nimport { type ShareableItem } from \"@fluid-app/portal-core/types\";\nimport { useWidgetInteraction } from \"../contexts/WidgetInteractionContext\";\n\n/** Plain column definition provided by data sources (no render functions) */\nexport type TableColumnDef = {\n key: string;\n label: string;\n sortable: boolean;\n};\n\n// Internal column definition (includes render function)\ntype ColumnDef = TableColumnDef & {\n render?: (value: unknown, item: ShareableItem) => React.ReactNode;\n};\n\nconst DEFAULT_DATA: ShareableItem[] = [];\n\n// ---------------------------------------------------------------------------\n// Column cell renderers\n// ---------------------------------------------------------------------------\n\nfunction ImageCellRenderer(_value: unknown, item: ShareableItem) {\n return (\n <div className=\"h-10 w-10 rounded object-cover\">\n <MediaRenderer {...getMediaPropsFromShareable(item)} />\n </div>\n );\n}\n\nfunction PriceCellRenderer(_value: unknown, item: ShareableItem) {\n return ((item.display_price as string) ?? item.price) || \"-\";\n}\n\nfunction StatusCellRenderer(value: unknown) {\n const status = String(value || \"unknown\").toLowerCase();\n const statusStyles: Record<string, string> = {\n active: \"bg-primary text-primary-foreground\",\n paid: \"bg-primary text-primary-foreground\",\n inactive: \"bg-secondary text-secondary-foreground\",\n paused: \"bg-secondary text-secondary-foreground\",\n unknown: \"bg-muted text-muted-foreground\",\n unpaid: \"bg-destructive text-destructive-foreground\",\n refunded: \"bg-muted text-muted-foreground\",\n cancelled: \"bg-destructive text-destructive-foreground\",\n };\n return (\n <span\n className={`inline-flex rounded-full px-2 py-1 text-xs font-medium ${statusStyles[status] || \"bg-muted text-foreground\"}`}\n >\n {String(value || \"Unknown\")}\n </span>\n );\n}\n\n/** Map of column keys to custom cell renderers */\nconst CELL_RENDERERS: Record<\n string,\n (value: unknown, item: ShareableItem) => React.ReactNode\n> = {\n imageUrl: ImageCellRenderer,\n price: PriceCellRenderer,\n display_price: PriceCellRenderer,\n status: StatusCellRenderer,\n};\n\n/** Resolve plain column definitions from a data source into full ColumnDefs with renderers */\nfunction resolveColumns(columns: TableColumnDef[]): ColumnDef[] {\n return columns.map((col) => {\n const render = CELL_RENDERERS[col.key];\n return render ? { ...col, render } : { ...col };\n });\n}\n\n// Default columns for product data\nconst defaultColumns: ColumnDef[] = [\n {\n key: \"imageUrl\",\n label: \"Image\",\n sortable: false,\n render: ImageCellRenderer,\n },\n {\n key: \"title\",\n label: \"Title\",\n sortable: true,\n },\n {\n key: \"price\",\n label: \"Price\",\n sortable: true,\n render: PriceCellRenderer,\n },\n {\n key: \"status\",\n label: \"Status\",\n sortable: true,\n render: StatusCellRenderer,\n },\n];\n\ntype TableWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n background?: BackgroundValue;\n alternatingColorEnabled?: boolean;\n textColor?: ColorOptions;\n headerBackgroundColor?: ColorOptions;\n headerTextColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n\n // Data\n data?: ShareableItem[];\n /** Column definitions from a data source (plain data, renderers resolved internally) */\n columns?: TableColumnDef[];\n\n // Features\n filterEnabled?: boolean;\n sortingEnabled?: boolean;\n paginationEnabled?: boolean;\n maxRowsPerPage?: number;\n};\n\nexport function TableWidget({\n // Title defaults\n titleEnabled = true,\n titleText = \"Products\",\n titleFontSize = \"xl\",\n titleColor = \"foreground\",\n\n // Styling defaults\n background = {\n type: \"solid\",\n color: \"background\",\n },\n alternatingColorEnabled = true,\n textColor = \"foreground\",\n headerBackgroundColor = \"muted\",\n headerTextColor = \"foreground\",\n padding = 4,\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n\n // Data\n data = DEFAULT_DATA,\n columns: columnsProp,\n\n // Feature defaults\n filterEnabled = true,\n sortingEnabled = true,\n paginationEnabled = true,\n maxRowsPerPage = 5,\n\n className,\n ...props\n}: TableWidgetProps): React.JSX.Element {\n const backgroundColor = background.color || \"background\";\n const isImageBackground = background.type === \"image\";\n const backgroundImage =\n (background.resource?.image_url || background.resource?.imageUrl) &&\n isImageBackground\n ? `url(${background.resource.image_url || background.resource.imageUrl})`\n : \"none\";\n const pageSize = maxRowsPerPage;\n\n // When using an image or transparent background, inner elements should be\n // transparent so the image/page shows through. Otherwise use the configured colors.\n const isTransparentBg = backgroundColor === \"transparent\";\n const useTransparentInner = isImageBackground || isTransparentBg;\n const innerBg = useTransparentInner\n ? \"bg-transparent\"\n : `bg-${backgroundColor}`;\n const innerBgAlt = useTransparentInner\n ? \"bg-black/5\"\n : `bg-${backgroundColor}/40`;\n const transparentBorder = isTransparentBg\n ? \"border-black/20\"\n : \"border-white/20\";\n const innerBorder = useTransparentInner\n ? transparentBorder\n : `border-${backgroundColor}/60`;\n const headerBg = useTransparentInner\n ? \"bg-black/10\"\n : `bg-${headerBackgroundColor}/40`;\n const headerBorder = useTransparentInner\n ? transparentBorder\n : `border-${headerBackgroundColor}/60`;\n const paginationBg = useTransparentInner\n ? \"bg-black/10\"\n : `bg-${backgroundColor}/40`;\n\n // State for filtering, sorting, and pagination\n const [globalFilter, setGlobalFilter] = useState(\"\");\n const [sortConfig, setSortConfig] = useState<{\n key: string;\n direction: \"asc\" | \"desc\";\n } | null>(null);\n const [currentPage, setCurrentPage] = useState(1);\n\n // Only use columns from the data source if they look like valid column defs\n // (have a `key` string). When transformers return a plain array (e.g. toShareableProps),\n // use-widget-data maps the same array to ALL targetProps, so `columns` may\n // receive the data rows instead of column definitions.\n const firstCol = columnsProp?.[0];\n const validColumnsProp =\n firstCol && typeof firstCol.key === \"string\" && firstCol.key !== \"\"\n ? columnsProp\n : undefined;\n\n const columns = useMemo(\n () =>\n validColumnsProp ? resolveColumns(validColumnsProp) : defaultColumns,\n [validColumnsProp],\n );\n\n // Filter data\n const filteredData = useMemo(() => {\n let result = [...data];\n\n if (globalFilter) {\n const lowerFilter = globalFilter.toLowerCase();\n result = result.filter((item) =>\n columns.some((col) => {\n const value = item[col.key];\n return String(value ?? \"\")\n .toLowerCase()\n .includes(lowerFilter);\n }),\n );\n }\n\n return result;\n }, [data, globalFilter, columns]);\n\n // Sort data\n const sortedData = useMemo(() => {\n if (!sortConfig) return filteredData;\n\n return [...filteredData].sort((a, b) => {\n const aValue = a[sortConfig.key];\n const bValue = b[sortConfig.key];\n\n // Handle null/undefined\n if (aValue == null && bValue == null) return 0;\n if (aValue == null) return sortConfig.direction === \"asc\" ? 1 : -1;\n if (bValue == null) return sortConfig.direction === \"asc\" ? -1 : 1;\n\n // Compare values\n let comparison = 0;\n if (typeof aValue === \"number\" && typeof bValue === \"number\") {\n comparison = aValue - bValue;\n } else {\n comparison = String(aValue).localeCompare(String(bValue));\n }\n\n return sortConfig.direction === \"asc\" ? comparison : -comparison;\n });\n }, [filteredData, sortConfig]);\n\n // Paginate data\n const paginatedData = useMemo(() => {\n if (!paginationEnabled) return sortedData;\n\n const startIndex = (currentPage - 1) * pageSize;\n return sortedData.slice(startIndex, startIndex + pageSize);\n }, [sortedData, currentPage, pageSize, paginationEnabled]);\n\n const totalPages = Math.ceil(sortedData.length / pageSize);\n\n // Reset to page 1 when filters change\n const handleGlobalFilterChange = (value: string) => {\n setGlobalFilter(value);\n setCurrentPage(1);\n };\n\n // Handle sort\n const handleSort = (key: string) => {\n if (!sortingEnabled) return;\n\n setSortConfig((prev) => {\n if (prev?.key !== key) return { key, direction: \"asc\" };\n if (prev.direction === \"asc\") return { key, direction: \"desc\" };\n return null;\n });\n };\n\n // Get sort indicator\n const getSortIndicator = (key: string) => {\n if (sortConfig?.key !== key) return null;\n return sortConfig.direction === \"asc\" ? \" ↑\" : \" ↓\";\n };\n\n const { onItemClick } = useWidgetInteraction();\n\n return (\n <div\n className={`@container overflow-hidden ${paginationEnabled ? \"\" : \"overflow-y-auto\"} rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-${backgroundColor} bg-cover bg-center text-${textColor} ${className}`}\n style={{ backgroundImage }}\n {...props}\n >\n <div\n className={`flex items-center justify-between p-${padding} ${innerBg} space-x-2`}\n >\n {/* Title */}\n {titleEnabled && titleText && (\n <h2\n className={`text-${titleFontSize === \"md\" ? \"base\" : titleFontSize} font-header font-bold text-${titleColor} min-w-0 truncate`}\n >\n {titleText}\n </h2>\n )}\n\n {/* Global Search */}\n {filterEnabled && (\n <Input\n type=\"text\"\n placeholder=\"Search all columns...\"\n value={globalFilter}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n handleGlobalFilterChange(e.target.value)\n }\n className={`w-full rounded-md border ${headerBorder} ${headerBg} ring-offset-muted px-3 py-2 text-sm placeholder:text-${headerTextColor}/40 focus-visible:ring-primary focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none md:w-64`}\n />\n )}\n </div>\n\n {/* Table */}\n <div className=\"overflow-x-auto\">\n <table className=\"w-full border-collapse\">\n <thead>\n <tr className={`${headerBg} ${headerBorder} border-y`}>\n {columns.map((col) => (\n <th\n key={col.key}\n className={`px-4 py-3 text-left text-sm font-semibold text-${headerTextColor} ${col.sortable && sortingEnabled ? \"cursor-pointer select-none hover:opacity-80\" : \"\"}`}\n {...(col.sortable && sortingEnabled\n ? {\n role: \"button\" as const,\n tabIndex: 0,\n onClick: () => handleSort(col.key),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleSort(col.key);\n }\n },\n }\n : {})}\n >\n <div className=\"flex flex-col gap-1\">\n <span>\n {col.label}\n {col.sortable &&\n sortingEnabled &&\n getSortIndicator(col.key)}\n </span>\n </div>\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {data.length === 0 ? (\n <tr>\n <td colSpan={columns.length}>\n <div className=\"text-muted-foreground flex min-h-[200px] flex-col items-center justify-center gap-2\">\n <div className=\"text-4xl\">📋</div>\n <p className=\"text-sm\">No data available</p>\n <p className=\"text-muted-foreground/70 text-xs\">\n Connect a data source to display table data\n </p>\n </div>\n </td>\n </tr>\n ) : paginatedData.length === 0 ? (\n <tr>\n <td colSpan={columns.length}>\n <div className=\"py-8 text-center\">\n <p className=\"text-sm\">No results found</p>\n <p className=\"text-xs\">Try adjusting your search</p>\n </div>\n </td>\n </tr>\n ) : (\n <>\n {paginatedData.map((item, index) => (\n <tr\n key={item.id ?? index}\n className={`h-17 border-b ${innerBorder} last:border-none ${innerBg} ${alternatingColorEnabled ? `even:${innerBgAlt}` : \"\"} ${onItemClick ? \"cursor-pointer hover:opacity-80\" : \"\"}`}\n {...(onItemClick\n ? {\n tabIndex: 0,\n onClick: () => onItemClick(item),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onItemClick(item);\n }\n },\n }\n : {})}\n >\n {columns.map((col) => (\n <td key={col.key} className=\"px-4 py-3 text-sm\">\n {col.render\n ? col.render(item[col.key], item)\n : String(item[col.key] ?? \"-\")}\n </td>\n ))}\n </tr>\n ))}\n {/* Empty rows to fill the last page for consistent pagination position */}\n {paginationEnabled &&\n paginatedData.length < pageSize &&\n paginatedData.length > 0 &&\n Array.from({ length: pageSize - paginatedData.length }).map(\n (_, index) => (\n <tr\n key={`empty-${index}`}\n className={`h-17 border-b ${innerBorder} last:border-none ${innerBg} ${alternatingColorEnabled ? `even:${innerBgAlt}` : \"\"}`}\n >\n {columns.map((col) => (\n <td key={col.key} className=\"px-4 py-3 text-sm\">\n &nbsp;\n </td>\n ))}\n </tr>\n ),\n )}\n </>\n )}\n </tbody>\n </table>\n </div>\n\n {/* Pagination */}\n {paginationEnabled && totalPages > 1 && (\n <div\n className={`flex flex-col items-center justify-between gap-2 border-t ${innerBorder} p-${padding} @md:flex-row ${paginationBg} text-${textColor}`}\n >\n <p className=\"text-sm\">\n Showing {(currentPage - 1) * pageSize + 1}-\n {Math.min(currentPage * pageSize, sortedData.length)} of{\" \"}\n {sortedData.length} results\n </p>\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => setCurrentPage((p) => Math.max(1, p - 1))}\n disabled={currentPage === 1}\n className={`rounded-md border border-${headerBackgroundColor}/60 bg-${headerBackgroundColor} ring-offset-muted placeholder:text-muted-foreground focus-visible:ring-primary px-3 py-1 text-sm transition-opacity hover:opacity-80 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50`}\n >\n Previous\n </button>\n <span className=\"text-sm\">\n Page {currentPage} of {totalPages}\n </span>\n <button\n onClick={() => setCurrentPage((p) => Math.min(totalPages, p + 1))}\n disabled={currentPage === totalPages}\n className={`rounded-md border border-${headerBackgroundColor}/60 bg-${headerBackgroundColor} ring-offset-muted placeholder:text-muted-foreground focus-visible:ring-primary px-3 py-1 text-sm transition-opacity hover:opacity-80 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50`}\n >\n Next\n </button>\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport const tableWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"TableWidget\",\n displayName: \"Table Widget\",\n tabsConfig: [\n { id: \"styling\", label: \"Styling\" },\n { id: \"behavior\", label: \"Behavior\" },\n { id: \"data\", label: \"Data\" },\n ],\n dataSourceTargetProps: [\"data\", \"columns\"],\n fields: [\n // Content Tab - Title Group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed above the table\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Title text displayed above the table\",\n defaultValue: \"Products\",\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 key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Styling Tab - Design Group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the table container\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"alternatingColorEnabled\",\n label: \"Enable Alternating Colors\",\n type: \"boolean\",\n description: \"Enable alternating colors for table rows\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n getColorField({\n key: \"headerBackgroundColor\",\n label: \"Header Background\",\n description: \"Background color for the table header\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for table content\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"headerTextColor\",\n label: \"Header Text Color\",\n description: \"Text color for the table header\",\n defaultValue: \"foreground\",\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 getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the table container\",\n defaultValue: 4,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the table container\",\n defaultValue: \"md\",\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 // Behavior Tab - Features Group\n {\n key: \"filterEnabled\",\n label: \"Enable Filters\",\n type: \"boolean\",\n description: \"Show global search and column filters\",\n defaultValue: true,\n tab: \"behavior\",\n group: \"Features\",\n },\n {\n key: \"sortingEnabled\",\n label: \"Enable Sorting\",\n type: \"boolean\",\n description: \"Allow sorting by clicking column headers\",\n defaultValue: true,\n tab: \"behavior\",\n group: \"Features\",\n },\n {\n key: \"paginationEnabled\",\n label: \"Enable Pagination\",\n type: \"boolean\",\n description: \"Split data into pages\",\n defaultValue: true,\n tab: \"behavior\",\n group: \"Features\",\n },\n {\n key: \"maxRowsPerPage\",\n label: \"Max Rows Per Page\",\n type: \"number\",\n description: \"Maximum number of rows to display per page\",\n min: 1,\n max: 50,\n step: 1,\n defaultValue: 5,\n tab: \"behavior\",\n group: \"Features\",\n requiresKeyToBeTrue: \"paginationEnabled\",\n },\n\n // Data Tab\n {\n key: \"dataSource\",\n label: \"Data Source\",\n type: \"dataSource\",\n description: \"Configure data source for the table\",\n tab: \"data\",\n group: \"Data Configuration\",\n },\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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O;GACP,cAAc;GACd,KAAK;GACL,aAAa;GACb,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EACFC,mBAAAA,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EAGF;GACE,MAAM;GACN,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACDA,mBAAAA,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFA,mBAAAA,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFA,mBAAAA,cAAc;GACZ,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;EACDC,mBAAAA,gBAAgB;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFC,mBAAAA,qBAAqB;GACnB,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;EACFC,mBAAAA,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EAGF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EAGD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,OAAO;GACR;EACF;CACF"}
@@ -1,18 +0,0 @@
1
- const require_chunk = require("./chunk-9hOWP6kD.cjs");
2
- let react = require("react");
3
- react = require_chunk.__toESM(react);
4
- require("react/jsx-runtime");
5
- //#region ../widgets/src/contexts/WidgetInteractionContext.tsx
6
- const WidgetInteractionContext = (0, react.createContext)({});
7
- function useWidgetInteraction() {
8
- return (0, react.useContext)(WidgetInteractionContext);
9
- }
10
- //#endregion
11
- Object.defineProperty(exports, "useWidgetInteraction", {
12
- enumerable: true,
13
- get: function() {
14
- return useWidgetInteraction;
15
- }
16
- });
17
-
18
- //# sourceMappingURL=WidgetInteractionContext-Bs3LkFFH.cjs.map
@@ -1,11 +0,0 @@
1
- import { createContext, useContext } from "react";
2
- import "react/jsx-runtime";
3
- //#region ../widgets/src/contexts/WidgetInteractionContext.tsx
4
- const WidgetInteractionContext = createContext({});
5
- function useWidgetInteraction() {
6
- return useContext(WidgetInteractionContext);
7
- }
8
- //#endregion
9
- export { useWidgetInteraction as t };
10
-
11
- //# sourceMappingURL=WidgetInteractionContext-D0TJv70C.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"registry-context-BDH0vNHR.mjs","names":[],"sources":["../../core/src/data-sources/fetchers/api.ts","../../core/src/data-sources/fetchers/custom.ts","../../core/src/data-sources/fetchers/static.ts","../../core/src/data-sources/transformers.ts","../../core/src/data-sources/registry.ts","../../react/src/data-sources/context.tsx","../../react/src/data-sources/registry-context.tsx"],"sourcesContent":["import type { DataSourceShareableType } from \"../../data-source-api-types\";\nimport type { ApiDataSource, DataSourceContext } from \"../types\";\n\n/**\n * Delegates a preset API source to the injected DataSourceApi adapter.\n * Returns undefined for unknown presets (caller falls through to raw fetch).\n */\nasync function fetchViaAdapter(\n source: ApiDataSource,\n context: DataSourceContext,\n): Promise<unknown> {\n const api = context.api!;\n const vars = { ...context.variables, ...source.variables };\n\n switch (source.presetId) {\n case \"rep-most-shared\": {\n return api.fetchMostShared(vars?.rep_id ?? \"\", {\n shareableType:\n (vars?.shareable_type as DataSourceShareableType) ?? \"products\",\n limit: vars?.limit ? Number(vars.limit) : undefined,\n period: vars?.period,\n languageIso: vars?.language_iso,\n signal: context.signal,\n });\n }\n case \"rep-most-viewed\": {\n return api.fetchMostViewed(vars?.rep_id ?? \"\", {\n shareableType:\n (vars?.shareable_type as DataSourceShareableType) ?? \"products\",\n limit: vars?.limit ? Number(vars.limit) : undefined,\n period: vars?.period,\n languageIso: vars?.language_iso,\n signal: context.signal,\n });\n }\n case \"customer-orders\": {\n const customerId = vars?.customer_id;\n if (!customerId) return undefined;\n return api.fetchOrders(customerId, {\n limit: vars?.limit ? Number(vars.limit) : undefined,\n status: vars?.status,\n signal: context.signal,\n });\n }\n case \"customer-subscriptions\": {\n const customerId = vars?.customer_id;\n if (!customerId) return undefined;\n return api.fetchSubscriptions(customerId, {\n limit: vars?.limit ? Number(vars.limit) : undefined,\n status: vars?.status,\n signal: context.signal,\n });\n }\n default:\n return undefined;\n }\n}\n\n/**\n * Extracts a value from an object using dot notation path\n * e.g., getByPath({ data: { items: [1,2,3] } }, 'data.items') => [1,2,3]\n */\nfunction getByPath(obj: unknown, path: string): unknown {\n return path.split(\".\").reduce((current, key) => {\n if (current && typeof current === \"object\" && key in current) {\n return (current as Record<string, unknown>)[key];\n }\n return undefined;\n }, obj);\n}\n\n/**\n * Replaces {variable} placeholders in an endpoint path with values from the\n * variables map. E.g., \"/reps/{rep_id}/most_shared\" with { rep_id: \"42\" }\n * becomes \"/reps/42/most_shared\".\n */\nfunction interpolateVariables(\n endpoint: string,\n variables?: Record<string, string>,\n): string {\n if (!variables) return endpoint;\n const resolved = endpoint.replace(\n /\\{(\\w+)\\}/g,\n (match, key: string) => variables[key] ?? match,\n );\n const unresolved = resolved.match(/\\{(\\w+)\\}/g);\n if (unresolved) {\n console.warn(\n `[DataSource] Unresolved variable placeholders in endpoint: ${unresolved.join(\", \")}. ` +\n `Endpoint: \"${endpoint}\". Available variables: ${Object.keys(variables).join(\", \") || \"(none)\"}`,\n );\n }\n return stripAllQueryParams(resolved);\n}\n\n/**\n * Removes query parameters whose value is \"all\" from a URL.\n *\n * Convention: \"all\" is a reserved no-op value for data source preset\n * config fields. Preset authors should use \"all\" as the default option\n * for \"show everything\" filters. This function strips those params so\n * APIs that don't recognise \"all\" fall back to their default (return\n * everything) behaviour. Do not use \"all\" as a meaningful filter value\n * in preset endpoints.\n */\nfunction stripAllQueryParams(url: string): string {\n const qIndex = url.indexOf(\"?\");\n if (qIndex === -1) return url;\n\n const base = url.slice(0, qIndex);\n const query = url.slice(qIndex + 1);\n const kept = query\n .split(\"&\")\n .filter((pair) => {\n const eqIndex = pair.indexOf(\"=\");\n if (eqIndex === -1) return true;\n return pair.slice(eqIndex + 1) !== \"all\";\n })\n .join(\"&\");\n\n return kept ? `${base}?${kept}` : base;\n}\n\n/**\n * Resolves the full URL for an endpoint.\n * - Substitutes {variable} placeholders from context variables\n * - Absolute URLs (starting with http:// or https://) are used as-is\n * - Relative paths are prefixed with the context's baseUrl\n */\nfunction resolveEndpointUrl(\n endpoint: string,\n baseUrl?: string,\n variables?: Record<string, string>,\n): string {\n const resolved = interpolateVariables(endpoint, variables);\n\n // If endpoint is already absolute, use it directly\n if (resolved.startsWith(\"http://\") || resolved.startsWith(\"https://\")) {\n return resolved;\n }\n\n // If we have a baseUrl, prepend it to the relative endpoint\n if (baseUrl) {\n // Ensure proper joining (no double slashes)\n const base = baseUrl.endsWith(\"/\") ? baseUrl.slice(0, -1) : baseUrl;\n const path = resolved.startsWith(\"/\") ? resolved : `/${resolved}`;\n return `${base}${path}`;\n }\n\n // No baseUrl provided, return endpoint as-is (will likely fail for relative paths)\n return resolved;\n}\n\n/**\n * Default API fetcher implementation\n */\nexport async function apiFetcher(\n source: ApiDataSource,\n context: DataSourceContext,\n): Promise<unknown> {\n // Delegate to adapter if available for preset-backed sources\n if (context.api && source.presetId) {\n const result = await fetchViaAdapter(source, context);\n if (result !== undefined) return result;\n // Fall through to legacy fetch for unknown presets\n }\n\n const { endpoint, method = \"GET\", headers = {}, body, resultPath } = source;\n\n // Merge context variables with per-source variables (source overrides context)\n const mergedVariables = { ...context.variables, ...source.variables };\n\n // Resolve the full URL, substituting variables and using baseUrl for relative endpoints\n const url = resolveEndpointUrl(endpoint, context.baseUrl, mergedVariables);\n\n // Skip the fetch if the URL still contains unresolved {variable} placeholders\n // (e.g. customer_id not yet loaded). Returning undefined avoids a bad API request.\n if (/\\{\\w+\\}/.test(url)) {\n return undefined;\n }\n\n const fetchOptions: RequestInit = {\n method,\n headers: {\n \"content-type\": \"application/json\",\n ...context.getApiHeaders?.(),\n ...headers,\n },\n signal: context.signal,\n };\n\n if (body && (method === \"POST\" || method === \"PUT\")) {\n fetchOptions.body = JSON.stringify(body);\n }\n\n const response = await fetch(url, fetchOptions);\n\n if (!response.ok) {\n throw new Error(\n `API request failed: ${response.status} ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n\n // Extract data at resultPath if specified\n if (resultPath) {\n return getByPath(data, resultPath);\n }\n\n return data;\n}\n","import type { ResourceType } from \"../../data-source-api-types\";\nimport type {\n CustomDataSource,\n DataSourceContext,\n SelectedItem,\n} from \"../types\";\n\nconst SHAREABLE_TO_RESOURCE_TYPE: Record<string, ResourceType> = {\n Medium: \"Medium\",\n Page: \"Page\",\n Library: \"Library\",\n Product: \"Product\",\n EnrollmentPack: \"EnrollmentPack\",\n};\n\nasync function fetchItemsViaAdapter(\n items: SelectedItem[],\n context: DataSourceContext,\n): Promise<unknown[]> {\n const api = context.api!;\n\n // Use Promise.allSettled so individual failures don't blow up the whole\n // batch, but *do* surface the aggregate failure for visibility — a rep who\n // hand-picked 5 items shouldn't silently see 3 without knowing why.\n const settled = await Promise.allSettled(\n items.map(async (item) => {\n const resourceType = SHAREABLE_TO_RESOURCE_TYPE[item.shareableType];\n if (!resourceType) {\n throw new Error(\n `Unknown shareable type: ${item.shareableType} for item #${item.id}`,\n );\n }\n return api.fetchResource(resourceType, item.id, context.signal);\n }),\n );\n\n const successful: unknown[] = [];\n const failures: { item: SelectedItem; reason: unknown }[] = [];\n\n settled.forEach((result, index) => {\n const item = items[index];\n if (!item) return;\n if (result.status === \"fulfilled\") {\n successful.push(result.value);\n } else {\n failures.push({ item, reason: result.reason });\n }\n });\n\n if (failures.length > 0) {\n // Log once with aggregate context so Sentry/logs show the full picture\n // rather than N scattered warnings that are hard to correlate.\n console.error(\n `[CustomFetcher] ${failures.length}/${items.length} items failed to fetch:`,\n failures.map((f) => ({\n shareableType: f.item.shareableType,\n id: f.item.id,\n error: f.reason instanceof Error ? f.reason.message : f.reason,\n })),\n );\n }\n\n if (successful.length === 0 && items.length > 0) {\n const firstErr = failures[0]?.reason;\n throw new Error(\n `Failed to fetch all ${items.length} item(s)${firstErr instanceof Error ? `: ${firstErr.message}` : \"\"}`,\n );\n }\n\n return successful;\n}\n\n/**\n * Custom fetcher that fetches selected items via the injected DataSourceApi adapter.\n *\n * Fetches all items in parallel for performance.\n * Returns an array of successfully fetched items, preserving order.\n * Logs warnings for failed fetches but doesn't throw unless all items fail.\n */\nexport async function customFetcher(\n source: CustomDataSource,\n context: DataSourceContext,\n): Promise<unknown[]> {\n const { selectedItems } = source;\n if (!selectedItems || selectedItems.length === 0) {\n return [];\n }\n\n if (!context.api) {\n throw new Error(\n \"customFetcher requires context.api — ensure a DataSourceApiProvider wraps this tree.\",\n );\n }\n\n return fetchItemsViaAdapter(selectedItems, context);\n}\n","import type {\n StaticDataSource,\n DataSourceContext,\n StaticSourceType,\n} from \"../types\";\n\n/**\n * Static data source fetcher.\n *\n * Delegates to the injected DataSourceApi adapter to fetch products filtered\n * by collection, category, or tag.\n */\nexport async function staticFetcher(\n source: StaticDataSource,\n context: DataSourceContext,\n): Promise<unknown[]> {\n const { staticType, selectedId } = source;\n\n if (!context.api) {\n throw new Error(\n \"staticFetcher requires context.api — ensure a DataSourceApiProvider wraps this tree.\",\n );\n }\n\n // Validate filterId once at the shared delegation point so BFF and legacy\n // adapters behave identically. Tags are a known-unsupported type the\n // adapters throw for separately.\n if (staticType !== \"tags\" && Number.isNaN(Number(selectedId))) {\n throw new Error(\n `staticFetcher: selectedId must be numeric, got \"${selectedId}\"`,\n );\n }\n\n return context.api.fetchProductsByFilter(\n staticType,\n selectedId,\n context.signal,\n );\n}\n\n/**\n * Endpoints for listing static source items (collections, categories, tags).\n * Used by the portal builder UI for populating selection dropdowns.\n */\nexport const LIST_ENDPOINTS: Record<\n StaticSourceType,\n { endpoint: string; resultKey: string }\n> = {\n collections: {\n endpoint: \"/company/v1/collections\",\n resultKey: \"collections\",\n },\n categories: { endpoint: \"/company/v1/categories\", resultKey: \"categories\" },\n tags: { endpoint: \"/company/v1/tags\", resultKey: \"tags\" },\n};\n","/**\n * Widget Transformers\n *\n * Transform functions that map API response data to widget-specific prop shapes.\n * Each widget has one transformer that handles all data structure variants:\n * - Standard: Direct field name match\n * - Legacy: Different field names that need mapping\n * - Minimal: Bare minimum fields that need defaults\n *\n * Usage:\n * 1. Transformers are registered in the DataSourceRegistry\n * 2. Reference by name in ApiDataSource.transform\n * 3. Applied after resultPath extraction, before targetProps assignment\n */\n\nimport type { DataTransformer, DataSource } from \"./types\";\n\n/**\n * Helper to extract image URL from various API response structures.\n * Handles:\n * - Flat fields (Medium, Page, Product): image_url, imageUrl, thumbnail_url, src\n * - Nested images array (EnrollmentPack): images[0].image_url\n * - Nested library_items (Library): library_items[0].relateable.image_url\n */\nfunction extractImageUrl(d: Record<string, unknown>): string {\n // Try flat fields first (Medium, Page, Product)\n if (d.image_url) return d.image_url as string;\n if (d.imageUrl) return d.imageUrl as string;\n if (d.thumbnail_url) return d.thumbnail_url as string;\n if (d.src) return d.src as string;\n\n // Try nested images array (EnrollmentPack)\n const images = d.images as Array<Record<string, unknown>> | undefined;\n if (images && images.length > 0) {\n const firstImage = images[0];\n if (firstImage?.image_url) return firstImage.image_url as string;\n if (firstImage?.url) return firstImage.url as string;\n }\n\n // Try nested library_items (Library/Playlist)\n const libraryItems = d.library_items as\n | Array<Record<string, unknown>>\n | undefined;\n if (libraryItems && libraryItems.length > 0) {\n const firstItem = libraryItems[0];\n const relateable = firstItem?.relateable as\n | Record<string, unknown>\n | undefined;\n if (relateable?.image_url) return relateable.image_url as string;\n if (relateable?.imageUrl) return relateable.imageUrl as string;\n if (relateable?.thumbnail_url) return relateable.thumbnail_url as string;\n }\n\n return \"\";\n}\n\n/**\n * Helper to extract description from various API response structures.\n * Handles different field names across endpoints.\n */\nfunction extractDescription(d: Record<string, unknown>): string {\n // Try various description field names\n const desc =\n d.description ?? d.stripped ?? d.stripped_description ?? d.body ?? \"\";\n\n // Handle nested description object (some APIs return { body: \"...\" })\n if (typeof desc === \"object\" && desc !== null && \"body\" in desc) {\n return ((desc as Record<string, unknown>).body as string) ?? \"\";\n }\n\n return desc as string;\n}\n\n/**\n * Helper to extract custom widget config from a selected item.\n */\nfunction extractCustomWidgetConfig(\n d: Record<string, unknown>,\n source: DataSource | undefined,\n): Record<string, unknown> {\n if (source === undefined || source.type !== \"custom\") return {};\n\n const selectedItem = source.selectedItems.find(\n (s) => String(s.id) === String(d.id),\n );\n return selectedItem?.widgetConfig ?? {};\n}\n\n/**\n * ImageWidget transformer from shareable data\n */\nconst toImagePropsFromShareable: DataTransformer = (data) => {\n const item = Array.isArray(data) ? data[0] : data;\n if (!item || typeof item !== \"object\") {\n return { src: \"\", alt: \"Image\", objectFit: \"cover\" };\n }\n\n const d = item as Record<string, unknown>;\n return {\n src: extractImageUrl(d),\n alt: (d.title ?? d.name ?? d.alt ?? \"Image\") as string,\n objectFit: \"cover\" as const,\n };\n};\n\n/**\n * VideoWidget transformer from shareable data\n */\nconst toVideoPropsFromShareable: DataTransformer = (data) => {\n const item = Array.isArray(data) ? data[0] : data;\n if (!item || typeof item !== \"object\") {\n return { src: \"\", poster: \"\", caption: \"\" };\n }\n\n const d = item as Record<string, unknown>;\n return {\n src: ((d.video_url ?? d.videoUrl ?? d.src) as string) || \"\",\n poster: extractImageUrl(d),\n caption: (d.title ?? d.name ?? d.caption ?? \"\") as string,\n };\n};\n\n/**\n * Shareable content transformer\n * Normalizes shareable API responses to a consistent format\n */\nconst toShareableProps: DataTransformer = (data, source) => {\n if (!Array.isArray(data)) return [];\n\n // Derive a fallback shareable type from the data source configuration.\n // API presets pass shareable_type in their variables (e.g., \"products\").\n // Custom sources store it per-item (handled below).\n const sourceTypeHint =\n source?.type === \"api\" ? source.variables?.shareable_type : undefined;\n\n return data.map((item: unknown) => {\n const d = item as Record<string, unknown>;\n\n const widgetConfig = extractCustomWidgetConfig(d, source);\n\n // Resolve shareable type from the item itself, then fall back to source hint\n const shareableType = (d.type ??\n d.relateable_type ??\n d.shareable_type ??\n d.shareableType ??\n sourceTypeHint ??\n \"\") as string;\n\n return {\n ...d,\n id: d.id,\n title: (d.title ?? d.name ?? \"\") as string,\n description: extractDescription(d),\n imageUrl: extractImageUrl(d),\n videoUrl: ((d.video_url ?? d.videoUrl) as string) || null,\n shareableType,\n kind: (d.kind ?? \"image\") as string,\n status: (d.status ?? \"active\") as string,\n wholesalePrice: d.display_wholesale_price ?? d.wholesale_price ?? null,\n subscriptionPrice: d.subscription_price ?? null,\n outOfStock: d.out_of_stock ?? false,\n lowInStock: d.low_in_stock ?? false,\n ...widgetConfig,\n };\n });\n};\n\n/**\n * Carousel slides from shareables transformer\n */\nconst toCarouselSlidesFromShareables: DataTransformer = (data, source) => {\n if (!Array.isArray(data)) return [];\n\n return data.map((item: unknown, index: number) => {\n const d = item as Record<string, unknown>;\n\n const widgetConfig = extractCustomWidgetConfig(d, source);\n\n const imageUrl = extractImageUrl(d);\n const isVideo = d.kind === \"video\" || d.videoUrl || d.video_url;\n const title = (d.title ?? d.name ?? \"\") as string;\n\n const content = isVideo\n ? {\n type: \"VideoWidget\",\n props: {\n src: ((d.videoUrl ?? d.video_url) as string) || \"\",\n poster: imageUrl,\n caption: title,\n autoplay: true,\n loop: true,\n muted: true,\n controls: true,\n },\n }\n : {\n type: \"ImageWidget\",\n props: {\n src: imageUrl,\n alt: title || \"Slide image\",\n objectFit: \"cover\",\n },\n };\n\n const baseSlide = {\n id: String(d.id ?? `slide-${index}`),\n content,\n title,\n description: extractDescription(d),\n };\n\n return {\n ...baseSlide,\n ...widgetConfig,\n };\n });\n};\n\n/**\n * Orders table transformer\n * Normalizes order list data into ShareableItem rows + column definitions.\n * Returns { data, columns } so multi-targetProp mapping sends each to the widget.\n */\nconst toOrderTableProps: DataTransformer = (data) => {\n const orders = Array.isArray(data) ? data : [];\n\n const columns = [\n { key: \"imageUrl\", label: \"Image\", sortable: false },\n { key: \"order_number\", label: \"Order #\", sortable: true },\n { key: \"price\", label: \"Total\", sortable: true },\n { key: \"status\", label: \"Status\", sortable: true },\n ];\n\n const rows = orders.map((item: unknown) => {\n const d = item as Record<string, unknown>;\n const firstItem = d.first_item as Record<string, unknown> | undefined;\n const amount = parseFloat(String(d.amount ?? \"0\")) || 0;\n\n return {\n ...d,\n id: d.id ?? d.token,\n shareableType: \"Order\",\n imageUrl: (firstItem?.image_url as string) || \"\",\n title: (firstItem?.title as string) || \"\",\n order_number: d.order_number ?? \"\",\n price: amount,\n display_price: (d.total_display_amount as string) ?? d.amount ?? \"\",\n status: (d.status as string) ?? \"unknown\",\n created_at: d.created_at,\n };\n });\n\n return { data: rows, columns };\n};\n\n/**\n * Subscriptions table transformer\n * Normalizes subscription list data into ShareableItem rows + column definitions.\n */\nconst toSubscriptionTableProps: DataTransformer = (data) => {\n const subscriptions = Array.isArray(data) ? data : [];\n\n const columns = [\n { key: \"imageUrl\", label: \"Image\", sortable: false },\n { key: \"title\", label: \"Product\", sortable: true },\n { key: \"price\", label: \"Price\", sortable: true },\n { key: \"status\", label: \"Status\", sortable: true },\n ];\n\n const rows = subscriptions.map((item: unknown) => {\n const d = item as Record<string, unknown>;\n const variant = d.variant as Record<string, unknown> | undefined;\n const product = variant?.product as Record<string, unknown> | undefined;\n\n return {\n ...d,\n id: d.id ?? d.subscription_token,\n shareableType: \"Subscription\",\n imageUrl: (product?.image_url as string) || \"\",\n title: (product?.title as string) || \"\",\n price: parseFloat(String(d.price ?? \"0\")) || 0,\n display_price:\n (product?.price_in_currency as string) ?? String(d.price ?? \"\"),\n status: (d.status as string) ?? \"unknown\",\n next_bill_date: d.next_bill_date,\n };\n });\n\n return { data: rows, columns };\n};\n\n/**\n * All widget transformers bundled for registration\n */\nexport const WIDGET_TRANSFORMERS: Record<string, DataTransformer> = {\n toShareableProps,\n toCarouselSlidesFromShareables,\n toImagePropsFromShareable,\n toVideoPropsFromShareable,\n toOrderTableProps,\n toSubscriptionTableProps,\n};\n","import type {\n DataSourceRegistry,\n DataFetcher,\n DataTransformer,\n DataSourceType,\n} from \"./types\";\nimport { apiFetcher } from \"./fetchers/api\";\nimport { customFetcher } from \"./fetchers/custom\";\nimport { staticFetcher } from \"./fetchers/static\";\nimport { WIDGET_TRANSFORMERS } from \"./transformers\";\n\nexport interface CreateDataSourceRegistryOptions {\n /** Custom fetchers to add or override */\n fetchers?: Partial<Record<DataSourceType, DataFetcher>>;\n /** Custom transform functions */\n transformers?: Record<string, DataTransformer>;\n}\n\n/**\n * Creates a data source registry with default fetchers.\n * Users can extend this with custom fetchers and transformers.\n */\nexport function createDataSourceRegistry(\n options?: CreateDataSourceRegistryOptions,\n): DataSourceRegistry {\n return {\n fetchers: {\n api: apiFetcher,\n custom: customFetcher,\n static: staticFetcher,\n ...options?.fetchers,\n } as Record<DataSourceType, DataFetcher>,\n transformers: {\n ...WIDGET_TRANSFORMERS,\n ...options?.transformers,\n },\n };\n}\n\n/** Default registry instance */\nexport const DEFAULT_DATA_SOURCE_REGISTRY: DataSourceRegistry =\n createDataSourceRegistry();\n","import type React from \"react\";\nimport { createContext, useContext, useMemo, type ReactNode } from \"react\";\n\nexport interface DataSourceContextValue {\n baseUrl?: string | undefined;\n getApiHeaders?: (() => Record<string, string>) | undefined;\n}\n\nconst DataSourceContext = createContext<DataSourceContextValue>({});\n\nexport interface DataSourceProviderProps {\n baseUrl?: string | undefined;\n getApiHeaders?: (() => Record<string, string>) | undefined;\n children: ReactNode;\n}\n\nexport function DataSourceProvider({\n baseUrl,\n getApiHeaders,\n children,\n}: DataSourceProviderProps): React.JSX.Element {\n const value = useMemo(\n () => ({ baseUrl, getApiHeaders }),\n [baseUrl, getApiHeaders],\n );\n\n return (\n <DataSourceContext.Provider value={value}>\n {children}\n </DataSourceContext.Provider>\n );\n}\n\nexport function useDataSourceConfig(): DataSourceContextValue {\n return useContext(DataSourceContext);\n}\n","import type React from \"react\";\nimport { createContext, useContext, useMemo, type ReactNode } from \"react\";\nimport type { DataSourceRegistry } from \"@fluid-app/portal-core/data-sources/types\";\nimport { DEFAULT_DATA_SOURCE_REGISTRY } from \"@fluid-app/portal-core/data-sources/registry\";\nimport { DataSourceProvider } from \"./context\";\n\ninterface DataSourceRegistryContextValue {\n registry: DataSourceRegistry;\n baseUrl?: string | undefined;\n /** Get API headers function */\n getApiHeaders?: (() => Record<string, string>) | undefined;\n /** Dynamic variables for endpoint path substitution (e.g., { rep_id: \"123\" }) */\n variables?: Record<string, string> | undefined;\n}\n\nconst DataSourceRegistryContext = createContext<DataSourceRegistryContextValue>(\n {\n registry: DEFAULT_DATA_SOURCE_REGISTRY,\n },\n);\n\nexport interface DataSourceRegistryProviderProps {\n registry?: DataSourceRegistry | undefined;\n /** Base URL for API calls (e.g., \"https://api.fluid.app/api\") */\n baseUrl?: string | undefined;\n /**\n * Get API headers function\n */\n getApiHeaders?: (() => Record<string, string>) | undefined;\n /** Dynamic variables for endpoint path substitution (e.g., { rep_id: \"123\" }) */\n variables?: Record<string, string> | undefined;\n children: ReactNode;\n}\n\n/**\n * Provides data source registry and configuration to all descendants.\n * If no registry is provided, uses the default.\n * Also provides the shared DataSourceProvider from portal-core so that\n * portal-widgets hooks can access baseUrl and getApiHeaders.\n *\n * The DataSourceApi adapter is provided separately via DataSourceApiProvider.\n */\nexport function DataSourceRegistryProvider({\n registry,\n baseUrl,\n getApiHeaders,\n variables,\n children,\n}: DataSourceRegistryProviderProps): React.JSX.Element {\n const value = useMemo(\n () => ({\n registry: registry ?? DEFAULT_DATA_SOURCE_REGISTRY,\n baseUrl,\n getApiHeaders,\n variables,\n }),\n [registry, baseUrl, getApiHeaders, variables],\n );\n\n return (\n <DataSourceRegistryContext.Provider value={value}>\n <DataSourceProvider baseUrl={baseUrl} getApiHeaders={getApiHeaders}>\n {children}\n </DataSourceProvider>\n </DataSourceRegistryContext.Provider>\n );\n}\n\n/**\n * Hook to access the data source registry.\n */\nexport function useDataSourceRegistry(): DataSourceRegistry {\n return useContext(DataSourceRegistryContext).registry;\n}\n\n/**\n * Hook to access the full data source registry context (registry + config).\n */\nexport function useDataSourceRegistryConfig(): DataSourceRegistryContextValue {\n return useContext(DataSourceRegistryContext);\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"registry-context-C7-RLxVt.cjs","names":[],"sources":["../../core/src/data-sources/fetchers/api.ts","../../core/src/data-sources/fetchers/custom.ts","../../core/src/data-sources/fetchers/static.ts","../../core/src/data-sources/transformers.ts","../../core/src/data-sources/registry.ts","../../react/src/data-sources/context.tsx","../../react/src/data-sources/registry-context.tsx"],"sourcesContent":["import type { DataSourceShareableType } from \"../../data-source-api-types\";\nimport type { ApiDataSource, DataSourceContext } from \"../types\";\n\n/**\n * Delegates a preset API source to the injected DataSourceApi adapter.\n * Returns undefined for unknown presets (caller falls through to raw fetch).\n */\nasync function fetchViaAdapter(\n source: ApiDataSource,\n context: DataSourceContext,\n): Promise<unknown> {\n const api = context.api!;\n const vars = { ...context.variables, ...source.variables };\n\n switch (source.presetId) {\n case \"rep-most-shared\": {\n return api.fetchMostShared(vars?.rep_id ?? \"\", {\n shareableType:\n (vars?.shareable_type as DataSourceShareableType) ?? \"products\",\n limit: vars?.limit ? Number(vars.limit) : undefined,\n period: vars?.period,\n languageIso: vars?.language_iso,\n signal: context.signal,\n });\n }\n case \"rep-most-viewed\": {\n return api.fetchMostViewed(vars?.rep_id ?? \"\", {\n shareableType:\n (vars?.shareable_type as DataSourceShareableType) ?? \"products\",\n limit: vars?.limit ? Number(vars.limit) : undefined,\n period: vars?.period,\n languageIso: vars?.language_iso,\n signal: context.signal,\n });\n }\n case \"customer-orders\": {\n const customerId = vars?.customer_id;\n if (!customerId) return undefined;\n return api.fetchOrders(customerId, {\n limit: vars?.limit ? Number(vars.limit) : undefined,\n status: vars?.status,\n signal: context.signal,\n });\n }\n case \"customer-subscriptions\": {\n const customerId = vars?.customer_id;\n if (!customerId) return undefined;\n return api.fetchSubscriptions(customerId, {\n limit: vars?.limit ? Number(vars.limit) : undefined,\n status: vars?.status,\n signal: context.signal,\n });\n }\n default:\n return undefined;\n }\n}\n\n/**\n * Extracts a value from an object using dot notation path\n * e.g., getByPath({ data: { items: [1,2,3] } }, 'data.items') => [1,2,3]\n */\nfunction getByPath(obj: unknown, path: string): unknown {\n return path.split(\".\").reduce((current, key) => {\n if (current && typeof current === \"object\" && key in current) {\n return (current as Record<string, unknown>)[key];\n }\n return undefined;\n }, obj);\n}\n\n/**\n * Replaces {variable} placeholders in an endpoint path with values from the\n * variables map. E.g., \"/reps/{rep_id}/most_shared\" with { rep_id: \"42\" }\n * becomes \"/reps/42/most_shared\".\n */\nfunction interpolateVariables(\n endpoint: string,\n variables?: Record<string, string>,\n): string {\n if (!variables) return endpoint;\n const resolved = endpoint.replace(\n /\\{(\\w+)\\}/g,\n (match, key: string) => variables[key] ?? match,\n );\n const unresolved = resolved.match(/\\{(\\w+)\\}/g);\n if (unresolved) {\n console.warn(\n `[DataSource] Unresolved variable placeholders in endpoint: ${unresolved.join(\", \")}. ` +\n `Endpoint: \"${endpoint}\". Available variables: ${Object.keys(variables).join(\", \") || \"(none)\"}`,\n );\n }\n return stripAllQueryParams(resolved);\n}\n\n/**\n * Removes query parameters whose value is \"all\" from a URL.\n *\n * Convention: \"all\" is a reserved no-op value for data source preset\n * config fields. Preset authors should use \"all\" as the default option\n * for \"show everything\" filters. This function strips those params so\n * APIs that don't recognise \"all\" fall back to their default (return\n * everything) behaviour. Do not use \"all\" as a meaningful filter value\n * in preset endpoints.\n */\nfunction stripAllQueryParams(url: string): string {\n const qIndex = url.indexOf(\"?\");\n if (qIndex === -1) return url;\n\n const base = url.slice(0, qIndex);\n const query = url.slice(qIndex + 1);\n const kept = query\n .split(\"&\")\n .filter((pair) => {\n const eqIndex = pair.indexOf(\"=\");\n if (eqIndex === -1) return true;\n return pair.slice(eqIndex + 1) !== \"all\";\n })\n .join(\"&\");\n\n return kept ? `${base}?${kept}` : base;\n}\n\n/**\n * Resolves the full URL for an endpoint.\n * - Substitutes {variable} placeholders from context variables\n * - Absolute URLs (starting with http:// or https://) are used as-is\n * - Relative paths are prefixed with the context's baseUrl\n */\nfunction resolveEndpointUrl(\n endpoint: string,\n baseUrl?: string,\n variables?: Record<string, string>,\n): string {\n const resolved = interpolateVariables(endpoint, variables);\n\n // If endpoint is already absolute, use it directly\n if (resolved.startsWith(\"http://\") || resolved.startsWith(\"https://\")) {\n return resolved;\n }\n\n // If we have a baseUrl, prepend it to the relative endpoint\n if (baseUrl) {\n // Ensure proper joining (no double slashes)\n const base = baseUrl.endsWith(\"/\") ? baseUrl.slice(0, -1) : baseUrl;\n const path = resolved.startsWith(\"/\") ? resolved : `/${resolved}`;\n return `${base}${path}`;\n }\n\n // No baseUrl provided, return endpoint as-is (will likely fail for relative paths)\n return resolved;\n}\n\n/**\n * Default API fetcher implementation\n */\nexport async function apiFetcher(\n source: ApiDataSource,\n context: DataSourceContext,\n): Promise<unknown> {\n // Delegate to adapter if available for preset-backed sources\n if (context.api && source.presetId) {\n const result = await fetchViaAdapter(source, context);\n if (result !== undefined) return result;\n // Fall through to legacy fetch for unknown presets\n }\n\n const { endpoint, method = \"GET\", headers = {}, body, resultPath } = source;\n\n // Merge context variables with per-source variables (source overrides context)\n const mergedVariables = { ...context.variables, ...source.variables };\n\n // Resolve the full URL, substituting variables and using baseUrl for relative endpoints\n const url = resolveEndpointUrl(endpoint, context.baseUrl, mergedVariables);\n\n // Skip the fetch if the URL still contains unresolved {variable} placeholders\n // (e.g. customer_id not yet loaded). Returning undefined avoids a bad API request.\n if (/\\{\\w+\\}/.test(url)) {\n return undefined;\n }\n\n const fetchOptions: RequestInit = {\n method,\n headers: {\n \"content-type\": \"application/json\",\n ...context.getApiHeaders?.(),\n ...headers,\n },\n signal: context.signal,\n };\n\n if (body && (method === \"POST\" || method === \"PUT\")) {\n fetchOptions.body = JSON.stringify(body);\n }\n\n const response = await fetch(url, fetchOptions);\n\n if (!response.ok) {\n throw new Error(\n `API request failed: ${response.status} ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n\n // Extract data at resultPath if specified\n if (resultPath) {\n return getByPath(data, resultPath);\n }\n\n return data;\n}\n","import type { ResourceType } from \"../../data-source-api-types\";\nimport type {\n CustomDataSource,\n DataSourceContext,\n SelectedItem,\n} from \"../types\";\n\nconst SHAREABLE_TO_RESOURCE_TYPE: Record<string, ResourceType> = {\n Medium: \"Medium\",\n Page: \"Page\",\n Library: \"Library\",\n Product: \"Product\",\n EnrollmentPack: \"EnrollmentPack\",\n};\n\nasync function fetchItemsViaAdapter(\n items: SelectedItem[],\n context: DataSourceContext,\n): Promise<unknown[]> {\n const api = context.api!;\n\n // Use Promise.allSettled so individual failures don't blow up the whole\n // batch, but *do* surface the aggregate failure for visibility — a rep who\n // hand-picked 5 items shouldn't silently see 3 without knowing why.\n const settled = await Promise.allSettled(\n items.map(async (item) => {\n const resourceType = SHAREABLE_TO_RESOURCE_TYPE[item.shareableType];\n if (!resourceType) {\n throw new Error(\n `Unknown shareable type: ${item.shareableType} for item #${item.id}`,\n );\n }\n return api.fetchResource(resourceType, item.id, context.signal);\n }),\n );\n\n const successful: unknown[] = [];\n const failures: { item: SelectedItem; reason: unknown }[] = [];\n\n settled.forEach((result, index) => {\n const item = items[index];\n if (!item) return;\n if (result.status === \"fulfilled\") {\n successful.push(result.value);\n } else {\n failures.push({ item, reason: result.reason });\n }\n });\n\n if (failures.length > 0) {\n // Log once with aggregate context so Sentry/logs show the full picture\n // rather than N scattered warnings that are hard to correlate.\n console.error(\n `[CustomFetcher] ${failures.length}/${items.length} items failed to fetch:`,\n failures.map((f) => ({\n shareableType: f.item.shareableType,\n id: f.item.id,\n error: f.reason instanceof Error ? f.reason.message : f.reason,\n })),\n );\n }\n\n if (successful.length === 0 && items.length > 0) {\n const firstErr = failures[0]?.reason;\n throw new Error(\n `Failed to fetch all ${items.length} item(s)${firstErr instanceof Error ? `: ${firstErr.message}` : \"\"}`,\n );\n }\n\n return successful;\n}\n\n/**\n * Custom fetcher that fetches selected items via the injected DataSourceApi adapter.\n *\n * Fetches all items in parallel for performance.\n * Returns an array of successfully fetched items, preserving order.\n * Logs warnings for failed fetches but doesn't throw unless all items fail.\n */\nexport async function customFetcher(\n source: CustomDataSource,\n context: DataSourceContext,\n): Promise<unknown[]> {\n const { selectedItems } = source;\n if (!selectedItems || selectedItems.length === 0) {\n return [];\n }\n\n if (!context.api) {\n throw new Error(\n \"customFetcher requires context.api — ensure a DataSourceApiProvider wraps this tree.\",\n );\n }\n\n return fetchItemsViaAdapter(selectedItems, context);\n}\n","import type {\n StaticDataSource,\n DataSourceContext,\n StaticSourceType,\n} from \"../types\";\n\n/**\n * Static data source fetcher.\n *\n * Delegates to the injected DataSourceApi adapter to fetch products filtered\n * by collection, category, or tag.\n */\nexport async function staticFetcher(\n source: StaticDataSource,\n context: DataSourceContext,\n): Promise<unknown[]> {\n const { staticType, selectedId } = source;\n\n if (!context.api) {\n throw new Error(\n \"staticFetcher requires context.api — ensure a DataSourceApiProvider wraps this tree.\",\n );\n }\n\n // Validate filterId once at the shared delegation point so BFF and legacy\n // adapters behave identically. Tags are a known-unsupported type the\n // adapters throw for separately.\n if (staticType !== \"tags\" && Number.isNaN(Number(selectedId))) {\n throw new Error(\n `staticFetcher: selectedId must be numeric, got \"${selectedId}\"`,\n );\n }\n\n return context.api.fetchProductsByFilter(\n staticType,\n selectedId,\n context.signal,\n );\n}\n\n/**\n * Endpoints for listing static source items (collections, categories, tags).\n * Used by the portal builder UI for populating selection dropdowns.\n */\nexport const LIST_ENDPOINTS: Record<\n StaticSourceType,\n { endpoint: string; resultKey: string }\n> = {\n collections: {\n endpoint: \"/company/v1/collections\",\n resultKey: \"collections\",\n },\n categories: { endpoint: \"/company/v1/categories\", resultKey: \"categories\" },\n tags: { endpoint: \"/company/v1/tags\", resultKey: \"tags\" },\n};\n","/**\n * Widget Transformers\n *\n * Transform functions that map API response data to widget-specific prop shapes.\n * Each widget has one transformer that handles all data structure variants:\n * - Standard: Direct field name match\n * - Legacy: Different field names that need mapping\n * - Minimal: Bare minimum fields that need defaults\n *\n * Usage:\n * 1. Transformers are registered in the DataSourceRegistry\n * 2. Reference by name in ApiDataSource.transform\n * 3. Applied after resultPath extraction, before targetProps assignment\n */\n\nimport type { DataTransformer, DataSource } from \"./types\";\n\n/**\n * Helper to extract image URL from various API response structures.\n * Handles:\n * - Flat fields (Medium, Page, Product): image_url, imageUrl, thumbnail_url, src\n * - Nested images array (EnrollmentPack): images[0].image_url\n * - Nested library_items (Library): library_items[0].relateable.image_url\n */\nfunction extractImageUrl(d: Record<string, unknown>): string {\n // Try flat fields first (Medium, Page, Product)\n if (d.image_url) return d.image_url as string;\n if (d.imageUrl) return d.imageUrl as string;\n if (d.thumbnail_url) return d.thumbnail_url as string;\n if (d.src) return d.src as string;\n\n // Try nested images array (EnrollmentPack)\n const images = d.images as Array<Record<string, unknown>> | undefined;\n if (images && images.length > 0) {\n const firstImage = images[0];\n if (firstImage?.image_url) return firstImage.image_url as string;\n if (firstImage?.url) return firstImage.url as string;\n }\n\n // Try nested library_items (Library/Playlist)\n const libraryItems = d.library_items as\n | Array<Record<string, unknown>>\n | undefined;\n if (libraryItems && libraryItems.length > 0) {\n const firstItem = libraryItems[0];\n const relateable = firstItem?.relateable as\n | Record<string, unknown>\n | undefined;\n if (relateable?.image_url) return relateable.image_url as string;\n if (relateable?.imageUrl) return relateable.imageUrl as string;\n if (relateable?.thumbnail_url) return relateable.thumbnail_url as string;\n }\n\n return \"\";\n}\n\n/**\n * Helper to extract description from various API response structures.\n * Handles different field names across endpoints.\n */\nfunction extractDescription(d: Record<string, unknown>): string {\n // Try various description field names\n const desc =\n d.description ?? d.stripped ?? d.stripped_description ?? d.body ?? \"\";\n\n // Handle nested description object (some APIs return { body: \"...\" })\n if (typeof desc === \"object\" && desc !== null && \"body\" in desc) {\n return ((desc as Record<string, unknown>).body as string) ?? \"\";\n }\n\n return desc as string;\n}\n\n/**\n * Helper to extract custom widget config from a selected item.\n */\nfunction extractCustomWidgetConfig(\n d: Record<string, unknown>,\n source: DataSource | undefined,\n): Record<string, unknown> {\n if (source === undefined || source.type !== \"custom\") return {};\n\n const selectedItem = source.selectedItems.find(\n (s) => String(s.id) === String(d.id),\n );\n return selectedItem?.widgetConfig ?? {};\n}\n\n/**\n * ImageWidget transformer from shareable data\n */\nconst toImagePropsFromShareable: DataTransformer = (data) => {\n const item = Array.isArray(data) ? data[0] : data;\n if (!item || typeof item !== \"object\") {\n return { src: \"\", alt: \"Image\", objectFit: \"cover\" };\n }\n\n const d = item as Record<string, unknown>;\n return {\n src: extractImageUrl(d),\n alt: (d.title ?? d.name ?? d.alt ?? \"Image\") as string,\n objectFit: \"cover\" as const,\n };\n};\n\n/**\n * VideoWidget transformer from shareable data\n */\nconst toVideoPropsFromShareable: DataTransformer = (data) => {\n const item = Array.isArray(data) ? data[0] : data;\n if (!item || typeof item !== \"object\") {\n return { src: \"\", poster: \"\", caption: \"\" };\n }\n\n const d = item as Record<string, unknown>;\n return {\n src: ((d.video_url ?? d.videoUrl ?? d.src) as string) || \"\",\n poster: extractImageUrl(d),\n caption: (d.title ?? d.name ?? d.caption ?? \"\") as string,\n };\n};\n\n/**\n * Shareable content transformer\n * Normalizes shareable API responses to a consistent format\n */\nconst toShareableProps: DataTransformer = (data, source) => {\n if (!Array.isArray(data)) return [];\n\n // Derive a fallback shareable type from the data source configuration.\n // API presets pass shareable_type in their variables (e.g., \"products\").\n // Custom sources store it per-item (handled below).\n const sourceTypeHint =\n source?.type === \"api\" ? source.variables?.shareable_type : undefined;\n\n return data.map((item: unknown) => {\n const d = item as Record<string, unknown>;\n\n const widgetConfig = extractCustomWidgetConfig(d, source);\n\n // Resolve shareable type from the item itself, then fall back to source hint\n const shareableType = (d.type ??\n d.relateable_type ??\n d.shareable_type ??\n d.shareableType ??\n sourceTypeHint ??\n \"\") as string;\n\n return {\n ...d,\n id: d.id,\n title: (d.title ?? d.name ?? \"\") as string,\n description: extractDescription(d),\n imageUrl: extractImageUrl(d),\n videoUrl: ((d.video_url ?? d.videoUrl) as string) || null,\n shareableType,\n kind: (d.kind ?? \"image\") as string,\n status: (d.status ?? \"active\") as string,\n wholesalePrice: d.display_wholesale_price ?? d.wholesale_price ?? null,\n subscriptionPrice: d.subscription_price ?? null,\n outOfStock: d.out_of_stock ?? false,\n lowInStock: d.low_in_stock ?? false,\n ...widgetConfig,\n };\n });\n};\n\n/**\n * Carousel slides from shareables transformer\n */\nconst toCarouselSlidesFromShareables: DataTransformer = (data, source) => {\n if (!Array.isArray(data)) return [];\n\n return data.map((item: unknown, index: number) => {\n const d = item as Record<string, unknown>;\n\n const widgetConfig = extractCustomWidgetConfig(d, source);\n\n const imageUrl = extractImageUrl(d);\n const isVideo = d.kind === \"video\" || d.videoUrl || d.video_url;\n const title = (d.title ?? d.name ?? \"\") as string;\n\n const content = isVideo\n ? {\n type: \"VideoWidget\",\n props: {\n src: ((d.videoUrl ?? d.video_url) as string) || \"\",\n poster: imageUrl,\n caption: title,\n autoplay: true,\n loop: true,\n muted: true,\n controls: true,\n },\n }\n : {\n type: \"ImageWidget\",\n props: {\n src: imageUrl,\n alt: title || \"Slide image\",\n objectFit: \"cover\",\n },\n };\n\n const baseSlide = {\n id: String(d.id ?? `slide-${index}`),\n content,\n title,\n description: extractDescription(d),\n };\n\n return {\n ...baseSlide,\n ...widgetConfig,\n };\n });\n};\n\n/**\n * Orders table transformer\n * Normalizes order list data into ShareableItem rows + column definitions.\n * Returns { data, columns } so multi-targetProp mapping sends each to the widget.\n */\nconst toOrderTableProps: DataTransformer = (data) => {\n const orders = Array.isArray(data) ? data : [];\n\n const columns = [\n { key: \"imageUrl\", label: \"Image\", sortable: false },\n { key: \"order_number\", label: \"Order #\", sortable: true },\n { key: \"price\", label: \"Total\", sortable: true },\n { key: \"status\", label: \"Status\", sortable: true },\n ];\n\n const rows = orders.map((item: unknown) => {\n const d = item as Record<string, unknown>;\n const firstItem = d.first_item as Record<string, unknown> | undefined;\n const amount = parseFloat(String(d.amount ?? \"0\")) || 0;\n\n return {\n ...d,\n id: d.id ?? d.token,\n shareableType: \"Order\",\n imageUrl: (firstItem?.image_url as string) || \"\",\n title: (firstItem?.title as string) || \"\",\n order_number: d.order_number ?? \"\",\n price: amount,\n display_price: (d.total_display_amount as string) ?? d.amount ?? \"\",\n status: (d.status as string) ?? \"unknown\",\n created_at: d.created_at,\n };\n });\n\n return { data: rows, columns };\n};\n\n/**\n * Subscriptions table transformer\n * Normalizes subscription list data into ShareableItem rows + column definitions.\n */\nconst toSubscriptionTableProps: DataTransformer = (data) => {\n const subscriptions = Array.isArray(data) ? data : [];\n\n const columns = [\n { key: \"imageUrl\", label: \"Image\", sortable: false },\n { key: \"title\", label: \"Product\", sortable: true },\n { key: \"price\", label: \"Price\", sortable: true },\n { key: \"status\", label: \"Status\", sortable: true },\n ];\n\n const rows = subscriptions.map((item: unknown) => {\n const d = item as Record<string, unknown>;\n const variant = d.variant as Record<string, unknown> | undefined;\n const product = variant?.product as Record<string, unknown> | undefined;\n\n return {\n ...d,\n id: d.id ?? d.subscription_token,\n shareableType: \"Subscription\",\n imageUrl: (product?.image_url as string) || \"\",\n title: (product?.title as string) || \"\",\n price: parseFloat(String(d.price ?? \"0\")) || 0,\n display_price:\n (product?.price_in_currency as string) ?? String(d.price ?? \"\"),\n status: (d.status as string) ?? \"unknown\",\n next_bill_date: d.next_bill_date,\n };\n });\n\n return { data: rows, columns };\n};\n\n/**\n * All widget transformers bundled for registration\n */\nexport const WIDGET_TRANSFORMERS: Record<string, DataTransformer> = {\n toShareableProps,\n toCarouselSlidesFromShareables,\n toImagePropsFromShareable,\n toVideoPropsFromShareable,\n toOrderTableProps,\n toSubscriptionTableProps,\n};\n","import type {\n DataSourceRegistry,\n DataFetcher,\n DataTransformer,\n DataSourceType,\n} from \"./types\";\nimport { apiFetcher } from \"./fetchers/api\";\nimport { customFetcher } from \"./fetchers/custom\";\nimport { staticFetcher } from \"./fetchers/static\";\nimport { WIDGET_TRANSFORMERS } from \"./transformers\";\n\nexport interface CreateDataSourceRegistryOptions {\n /** Custom fetchers to add or override */\n fetchers?: Partial<Record<DataSourceType, DataFetcher>>;\n /** Custom transform functions */\n transformers?: Record<string, DataTransformer>;\n}\n\n/**\n * Creates a data source registry with default fetchers.\n * Users can extend this with custom fetchers and transformers.\n */\nexport function createDataSourceRegistry(\n options?: CreateDataSourceRegistryOptions,\n): DataSourceRegistry {\n return {\n fetchers: {\n api: apiFetcher,\n custom: customFetcher,\n static: staticFetcher,\n ...options?.fetchers,\n } as Record<DataSourceType, DataFetcher>,\n transformers: {\n ...WIDGET_TRANSFORMERS,\n ...options?.transformers,\n },\n };\n}\n\n/** Default registry instance */\nexport const DEFAULT_DATA_SOURCE_REGISTRY: DataSourceRegistry =\n createDataSourceRegistry();\n","import type React from \"react\";\nimport { createContext, useContext, useMemo, type ReactNode } from \"react\";\n\nexport interface DataSourceContextValue {\n baseUrl?: string | undefined;\n getApiHeaders?: (() => Record<string, string>) | undefined;\n}\n\nconst DataSourceContext = createContext<DataSourceContextValue>({});\n\nexport interface DataSourceProviderProps {\n baseUrl?: string | undefined;\n getApiHeaders?: (() => Record<string, string>) | undefined;\n children: ReactNode;\n}\n\nexport function DataSourceProvider({\n baseUrl,\n getApiHeaders,\n children,\n}: DataSourceProviderProps): React.JSX.Element {\n const value = useMemo(\n () => ({ baseUrl, getApiHeaders }),\n [baseUrl, getApiHeaders],\n );\n\n return (\n <DataSourceContext.Provider value={value}>\n {children}\n </DataSourceContext.Provider>\n );\n}\n\nexport function useDataSourceConfig(): DataSourceContextValue {\n return useContext(DataSourceContext);\n}\n","import type React from \"react\";\nimport { createContext, useContext, useMemo, type ReactNode } from \"react\";\nimport type { DataSourceRegistry } from \"@fluid-app/portal-core/data-sources/types\";\nimport { DEFAULT_DATA_SOURCE_REGISTRY } from \"@fluid-app/portal-core/data-sources/registry\";\nimport { DataSourceProvider } from \"./context\";\n\ninterface DataSourceRegistryContextValue {\n registry: DataSourceRegistry;\n baseUrl?: string | undefined;\n /** Get API headers function */\n getApiHeaders?: (() => Record<string, string>) | undefined;\n /** Dynamic variables for endpoint path substitution (e.g., { rep_id: \"123\" }) */\n variables?: Record<string, string> | undefined;\n}\n\nconst DataSourceRegistryContext = createContext<DataSourceRegistryContextValue>(\n {\n registry: DEFAULT_DATA_SOURCE_REGISTRY,\n },\n);\n\nexport interface DataSourceRegistryProviderProps {\n registry?: DataSourceRegistry | undefined;\n /** Base URL for API calls (e.g., \"https://api.fluid.app/api\") */\n baseUrl?: string | undefined;\n /**\n * Get API headers function\n */\n getApiHeaders?: (() => Record<string, string>) | undefined;\n /** Dynamic variables for endpoint path substitution (e.g., { rep_id: \"123\" }) */\n variables?: Record<string, string> | undefined;\n children: ReactNode;\n}\n\n/**\n * Provides data source registry and configuration to all descendants.\n * If no registry is provided, uses the default.\n * Also provides the shared DataSourceProvider from portal-core so that\n * portal-widgets hooks can access baseUrl and getApiHeaders.\n *\n * The DataSourceApi adapter is provided separately via DataSourceApiProvider.\n */\nexport function DataSourceRegistryProvider({\n registry,\n baseUrl,\n getApiHeaders,\n variables,\n children,\n}: DataSourceRegistryProviderProps): React.JSX.Element {\n const value = useMemo(\n () => ({\n registry: registry ?? DEFAULT_DATA_SOURCE_REGISTRY,\n baseUrl,\n getApiHeaders,\n variables,\n }),\n [registry, baseUrl, getApiHeaders, variables],\n );\n\n return (\n <DataSourceRegistryContext.Provider value={value}>\n <DataSourceProvider baseUrl={baseUrl} getApiHeaders={getApiHeaders}>\n {children}\n </DataSourceProvider>\n </DataSourceRegistryContext.Provider>\n );\n}\n\n/**\n * Hook to access the data source registry.\n */\nexport function useDataSourceRegistry(): DataSourceRegistry {\n return useContext(DataSourceRegistryContext).registry;\n}\n\n/**\n * Hook to access the full data source registry context (registry + config).\n */\nexport function useDataSourceRegistryConfig(): DataSourceRegistryContextValue {\n return useContext(DataSourceRegistryContext);\n}\n"],"mappings":"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"}