@freighttech/ui 0.13.18

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 (1477) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +31 -0
  3. package/dist/backend/AppShell.js +1289 -0
  4. package/dist/backend/AppShell.js.map +7 -0
  5. package/dist/backend/BackendChromeProvider.js +83 -0
  6. package/dist/backend/BackendChromeProvider.js.map +7 -0
  7. package/dist/backend/BackendPageSurface.js +19 -0
  8. package/dist/backend/BackendPageSurface.js.map +7 -0
  9. package/dist/backend/CollapsibleNavSection.js +149 -0
  10. package/dist/backend/CollapsibleNavSection.js.map +7 -0
  11. package/dist/backend/ContextHelp.js +33 -0
  12. package/dist/backend/ContextHelp.js.map +7 -0
  13. package/dist/backend/CrudForm.js +3163 -0
  14. package/dist/backend/CrudForm.js.map +7 -0
  15. package/dist/backend/DataTable.js +2091 -0
  16. package/dist/backend/DataTable.js.map +7 -0
  17. package/dist/backend/EmptyState.js +52 -0
  18. package/dist/backend/EmptyState.js.map +7 -0
  19. package/dist/backend/FilterBar.js +147 -0
  20. package/dist/backend/FilterBar.js.map +7 -0
  21. package/dist/backend/FilterOverlay.js +337 -0
  22. package/dist/backend/FilterOverlay.js.map +7 -0
  23. package/dist/backend/FlashMessages.js +158 -0
  24. package/dist/backend/FlashMessages.js.map +7 -0
  25. package/dist/backend/HtmlRichTextEditor.js +129 -0
  26. package/dist/backend/HtmlRichTextEditor.js.map +7 -0
  27. package/dist/backend/IntegrationsButton.js +25 -0
  28. package/dist/backend/IntegrationsButton.js.map +7 -0
  29. package/dist/backend/JsonBuilder.js +323 -0
  30. package/dist/backend/JsonBuilder.js.map +7 -0
  31. package/dist/backend/JsonDisplay.js +207 -0
  32. package/dist/backend/JsonDisplay.js.map +7 -0
  33. package/dist/backend/NextStepCallout.js +79 -0
  34. package/dist/backend/NextStepCallout.js.map +7 -0
  35. package/dist/backend/Page.js +27 -0
  36. package/dist/backend/Page.js.map +7 -0
  37. package/dist/backend/PerspectiveSidebar.js +456 -0
  38. package/dist/backend/PerspectiveSidebar.js.map +7 -0
  39. package/dist/backend/ProfileDropdown.js +341 -0
  40. package/dist/backend/ProfileDropdown.js.map +7 -0
  41. package/dist/backend/RowActions.js +155 -0
  42. package/dist/backend/RowActions.js.map +7 -0
  43. package/dist/backend/SectionHeader.js +74 -0
  44. package/dist/backend/SectionHeader.js.map +7 -0
  45. package/dist/backend/SettingsButton.js +25 -0
  46. package/dist/backend/SettingsButton.js.map +7 -0
  47. package/dist/backend/Sidebar.js +510 -0
  48. package/dist/backend/Sidebar.js.map +7 -0
  49. package/dist/backend/Sidebar.stories.js +166 -0
  50. package/dist/backend/Sidebar.stories.js.map +7 -0
  51. package/dist/backend/TruncatedCell.js +92 -0
  52. package/dist/backend/TruncatedCell.js.map +7 -0
  53. package/dist/backend/UserMenu.js +146 -0
  54. package/dist/backend/UserMenu.js.map +7 -0
  55. package/dist/backend/ValueIcons.js +34 -0
  56. package/dist/backend/ValueIcons.js.map +7 -0
  57. package/dist/backend/WebhookSetupGuide.js +79 -0
  58. package/dist/backend/WebhookSetupGuide.js.map +7 -0
  59. package/dist/backend/charts/BarChart.js +154 -0
  60. package/dist/backend/charts/BarChart.js.map +7 -0
  61. package/dist/backend/charts/ChartUtils.js +141 -0
  62. package/dist/backend/charts/ChartUtils.js.map +7 -0
  63. package/dist/backend/charts/ComboChart.js +261 -0
  64. package/dist/backend/charts/ComboChart.js.map +7 -0
  65. package/dist/backend/charts/ComboChart.stories.js +88 -0
  66. package/dist/backend/charts/ComboChart.stories.js.map +7 -0
  67. package/dist/backend/charts/KpiCard.js +96 -0
  68. package/dist/backend/charts/KpiCard.js.map +7 -0
  69. package/dist/backend/charts/LineChart.js +165 -0
  70. package/dist/backend/charts/LineChart.js.map +7 -0
  71. package/dist/backend/charts/PieChart.js +121 -0
  72. package/dist/backend/charts/PieChart.js.map +7 -0
  73. package/dist/backend/charts/ScatterChart.js +320 -0
  74. package/dist/backend/charts/ScatterChart.js.map +7 -0
  75. package/dist/backend/charts/TopNTable.js +91 -0
  76. package/dist/backend/charts/TopNTable.js.map +7 -0
  77. package/dist/backend/charts/WaterfallChart.js +136 -0
  78. package/dist/backend/charts/WaterfallChart.js.map +7 -0
  79. package/dist/backend/charts/index.js +30 -0
  80. package/dist/backend/charts/index.js.map +7 -0
  81. package/dist/backend/columns/ColumnChooserPanel.js +244 -0
  82. package/dist/backend/columns/ColumnChooserPanel.js.map +7 -0
  83. package/dist/backend/confirm-dialog/ConfirmDialog.js +214 -0
  84. package/dist/backend/confirm-dialog/ConfirmDialog.js.map +7 -0
  85. package/dist/backend/confirm-dialog/index.js +7 -0
  86. package/dist/backend/confirm-dialog/index.js.map +7 -0
  87. package/dist/backend/confirm-dialog/useConfirmDialog.js +113 -0
  88. package/dist/backend/confirm-dialog/useConfirmDialog.js.map +7 -0
  89. package/dist/backend/custom-fields/FieldDefinitionsEditor.js +1352 -0
  90. package/dist/backend/custom-fields/FieldDefinitionsEditor.js.map +7 -0
  91. package/dist/backend/custom-fields/FieldDefinitionsManager.js +332 -0
  92. package/dist/backend/custom-fields/FieldDefinitionsManager.js.map +7 -0
  93. package/dist/backend/dashboard/DashboardScreen.js +598 -0
  94. package/dist/backend/dashboard/DashboardScreen.js.map +7 -0
  95. package/dist/backend/dashboard/index.js +5 -0
  96. package/dist/backend/dashboard/index.js.map +7 -0
  97. package/dist/backend/dashboard/widgetRegistry.js +55 -0
  98. package/dist/backend/dashboard/widgetRegistry.js.map +7 -0
  99. package/dist/backend/date-range/DateRangeSelect.js +39 -0
  100. package/dist/backend/date-range/DateRangeSelect.js.map +7 -0
  101. package/dist/backend/date-range/InlineDateRangeSelect.js +42 -0
  102. package/dist/backend/date-range/InlineDateRangeSelect.js.map +7 -0
  103. package/dist/backend/date-range/InlineGranularitySelect.js +40 -0
  104. package/dist/backend/date-range/InlineGranularitySelect.js.map +7 -0
  105. package/dist/backend/date-range/dateRanges.js +176 -0
  106. package/dist/backend/date-range/dateRanges.js.map +7 -0
  107. package/dist/backend/date-range/index.js +25 -0
  108. package/dist/backend/date-range/index.js.map +7 -0
  109. package/dist/backend/detail/AccessDeniedMessage.js +28 -0
  110. package/dist/backend/detail/AccessDeniedMessage.js.map +7 -0
  111. package/dist/backend/detail/ActivitiesSection.js +947 -0
  112. package/dist/backend/detail/ActivitiesSection.js.map +7 -0
  113. package/dist/backend/detail/AddressEditor.js +417 -0
  114. package/dist/backend/detail/AddressEditor.js.map +7 -0
  115. package/dist/backend/detail/AddressTiles.js +441 -0
  116. package/dist/backend/detail/AddressTiles.js.map +7 -0
  117. package/dist/backend/detail/AddressesSection.js +274 -0
  118. package/dist/backend/detail/AddressesSection.js.map +7 -0
  119. package/dist/backend/detail/AttachmentDeleteDialog.js +41 -0
  120. package/dist/backend/detail/AttachmentDeleteDialog.js.map +7 -0
  121. package/dist/backend/detail/AttachmentMetadataDialog.js +519 -0
  122. package/dist/backend/detail/AttachmentMetadataDialog.js.map +7 -0
  123. package/dist/backend/detail/AttachmentVisualPreview.js +132 -0
  124. package/dist/backend/detail/AttachmentVisualPreview.js.map +7 -0
  125. package/dist/backend/detail/AttachmentsSection.js +281 -0
  126. package/dist/backend/detail/AttachmentsSection.js.map +7 -0
  127. package/dist/backend/detail/CustomDataSection.js +575 -0
  128. package/dist/backend/detail/CustomDataSection.js.map +7 -0
  129. package/dist/backend/detail/DetailFieldsSection.js +85 -0
  130. package/dist/backend/detail/DetailFieldsSection.js.map +7 -0
  131. package/dist/backend/detail/ErrorMessage.js +28 -0
  132. package/dist/backend/detail/ErrorMessage.js.map +7 -0
  133. package/dist/backend/detail/InlineEditors.js +697 -0
  134. package/dist/backend/detail/InlineEditors.js.map +7 -0
  135. package/dist/backend/detail/LoadingMessage.js +14 -0
  136. package/dist/backend/detail/LoadingMessage.js.map +7 -0
  137. package/dist/backend/detail/NotesSection.js +1022 -0
  138. package/dist/backend/detail/NotesSection.js.map +7 -0
  139. package/dist/backend/detail/TabEmptyState.js +25 -0
  140. package/dist/backend/detail/TabEmptyState.js.map +7 -0
  141. package/dist/backend/detail/TagsSection.js +375 -0
  142. package/dist/backend/detail/TagsSection.js.map +7 -0
  143. package/dist/backend/detail/addressFormat.js +77 -0
  144. package/dist/backend/detail/addressFormat.js.map +7 -0
  145. package/dist/backend/detail/index.js +36 -0
  146. package/dist/backend/detail/index.js.map +7 -0
  147. package/dist/backend/devtools/UmesDevToolsPanel.js +109 -0
  148. package/dist/backend/devtools/UmesDevToolsPanel.js.map +7 -0
  149. package/dist/backend/devtools/components/ConflictWarnings.js +32 -0
  150. package/dist/backend/devtools/components/ConflictWarnings.js.map +7 -0
  151. package/dist/backend/devtools/components/EnricherTiming.js +46 -0
  152. package/dist/backend/devtools/components/EnricherTiming.js.map +7 -0
  153. package/dist/backend/devtools/components/EventFlow.js +34 -0
  154. package/dist/backend/devtools/components/EventFlow.js.map +7 -0
  155. package/dist/backend/devtools/components/ExtensionPointList.js +58 -0
  156. package/dist/backend/devtools/components/ExtensionPointList.js.map +7 -0
  157. package/dist/backend/devtools/components/InterceptorActivity.js +36 -0
  158. package/dist/backend/devtools/components/InterceptorActivity.js.map +7 -0
  159. package/dist/backend/devtools/index.js +7 -0
  160. package/dist/backend/devtools/index.js.map +7 -0
  161. package/dist/backend/devtools/useUmesDevTools.js +125 -0
  162. package/dist/backend/devtools/useUmesDevTools.js.map +7 -0
  163. package/dist/backend/document-viewer/RegionOverlay.js +92 -0
  164. package/dist/backend/document-viewer/RegionOverlay.js.map +7 -0
  165. package/dist/backend/document-viewer/index.js +6 -0
  166. package/dist/backend/document-viewer/index.js.map +7 -0
  167. package/dist/backend/dynamic-grid/DynamicGrid.js +130 -0
  168. package/dist/backend/dynamic-grid/DynamicGrid.js.map +7 -0
  169. package/dist/backend/dynamic-grid/adapters.js +34 -0
  170. package/dist/backend/dynamic-grid/adapters.js.map +7 -0
  171. package/dist/backend/dynamic-grid/components/GridCell.js +149 -0
  172. package/dist/backend/dynamic-grid/components/GridCell.js.map +7 -0
  173. package/dist/backend/dynamic-grid/components/GridRow.js +32 -0
  174. package/dist/backend/dynamic-grid/components/GridRow.js.map +7 -0
  175. package/dist/backend/dynamic-grid/hooks/useGridKeyboardNav.js +115 -0
  176. package/dist/backend/dynamic-grid/hooks/useGridKeyboardNav.js.map +7 -0
  177. package/dist/backend/dynamic-grid/index.js +9 -0
  178. package/dist/backend/dynamic-grid/index.js.map +7 -0
  179. package/dist/backend/dynamic-grid/types.js +1 -0
  180. package/dist/backend/dynamic-grid/types.js.map +7 -0
  181. package/dist/backend/dynamic-table/DynamicTable.js +2607 -0
  182. package/dist/backend/dynamic-table/DynamicTable.js.map +7 -0
  183. package/dist/backend/dynamic-table/DynamicTable.stories.js +233 -0
  184. package/dist/backend/dynamic-table/DynamicTable.stories.js.map +7 -0
  185. package/dist/backend/dynamic-table/components/ActiveFilterChips.js +60 -0
  186. package/dist/backend/dynamic-table/components/ActiveFilterChips.js.map +7 -0
  187. package/dist/backend/dynamic-table/components/BulkActionsBar.js +58 -0
  188. package/dist/backend/dynamic-table/components/BulkActionsBar.js.map +7 -0
  189. package/dist/backend/dynamic-table/components/Cell.js +155 -0
  190. package/dist/backend/dynamic-table/components/Cell.js.map +7 -0
  191. package/dist/backend/dynamic-table/components/CellCommentDialog.js +726 -0
  192. package/dist/backend/dynamic-table/components/CellCommentDialog.js.map +7 -0
  193. package/dist/backend/dynamic-table/components/CellCommentHoverPopup.js +77 -0
  194. package/dist/backend/dynamic-table/components/CellCommentHoverPopup.js.map +7 -0
  195. package/dist/backend/dynamic-table/components/ColumnFilterPopover.js +485 -0
  196. package/dist/backend/dynamic-table/components/ColumnFilterPopover.js.map +7 -0
  197. package/dist/backend/dynamic-table/components/ColumnHeaderMenu.js +173 -0
  198. package/dist/backend/dynamic-table/components/ColumnHeaderMenu.js.map +7 -0
  199. package/dist/backend/dynamic-table/components/ColumnHeaders.js +528 -0
  200. package/dist/backend/dynamic-table/components/ColumnHeaders.js.map +7 -0
  201. package/dist/backend/dynamic-table/components/CompactLabelCell.js +64 -0
  202. package/dist/backend/dynamic-table/components/CompactLabelCell.js.map +7 -0
  203. package/dist/backend/dynamic-table/components/ConfigureViewFields.js +139 -0
  204. package/dist/backend/dynamic-table/components/ConfigureViewFields.js.map +7 -0
  205. package/dist/backend/dynamic-table/components/ConfigureViewFilters.js +305 -0
  206. package/dist/backend/dynamic-table/components/ConfigureViewFilters.js.map +7 -0
  207. package/dist/backend/dynamic-table/components/ConfigureViewFormatting.js +169 -0
  208. package/dist/backend/dynamic-table/components/ConfigureViewFormatting.js.map +7 -0
  209. package/dist/backend/dynamic-table/components/ConfigureViewFormulas.js +298 -0
  210. package/dist/backend/dynamic-table/components/ConfigureViewFormulas.js.map +7 -0
  211. package/dist/backend/dynamic-table/components/ConfigureViewGrouping.js +224 -0
  212. package/dist/backend/dynamic-table/components/ConfigureViewGrouping.js.map +7 -0
  213. package/dist/backend/dynamic-table/components/ConfigureViewLinkedColumns.js +167 -0
  214. package/dist/backend/dynamic-table/components/ConfigureViewLinkedColumns.js.map +7 -0
  215. package/dist/backend/dynamic-table/components/ConfigureViewPanel.js +592 -0
  216. package/dist/backend/dynamic-table/components/ConfigureViewPanel.js.map +7 -0
  217. package/dist/backend/dynamic-table/components/ConfigureViewRollups.js +269 -0
  218. package/dist/backend/dynamic-table/components/ConfigureViewRollups.js.map +7 -0
  219. package/dist/backend/dynamic-table/components/ConfigureViewSorting.js +107 -0
  220. package/dist/backend/dynamic-table/components/ConfigureViewSorting.js.map +7 -0
  221. package/dist/backend/dynamic-table/components/ContextMenu.js +91 -0
  222. package/dist/backend/dynamic-table/components/ContextMenu.js.map +7 -0
  223. package/dist/backend/dynamic-table/components/DateCell.js +80 -0
  224. package/dist/backend/dynamic-table/components/DateCell.js.map +7 -0
  225. package/dist/backend/dynamic-table/components/Debugger.js +311 -0
  226. package/dist/backend/dynamic-table/components/Debugger.js.map +7 -0
  227. package/dist/backend/dynamic-table/components/DensityControl.js +289 -0
  228. package/dist/backend/dynamic-table/components/DensityControl.js.map +7 -0
  229. package/dist/backend/dynamic-table/components/EmptyState.js +42 -0
  230. package/dist/backend/dynamic-table/components/EmptyState.js.map +7 -0
  231. package/dist/backend/dynamic-table/components/EntitySearchEditor.js +369 -0
  232. package/dist/backend/dynamic-table/components/EntitySearchEditor.js.map +7 -0
  233. package/dist/backend/dynamic-table/components/ExportMenu.js +63 -0
  234. package/dist/backend/dynamic-table/components/ExportMenu.js.map +7 -0
  235. package/dist/backend/dynamic-table/components/FilterDatePicker.js +165 -0
  236. package/dist/backend/dynamic-table/components/FilterDatePicker.js.map +7 -0
  237. package/dist/backend/dynamic-table/components/FilterValueInput.js +200 -0
  238. package/dist/backend/dynamic-table/components/FilterValueInput.js.map +7 -0
  239. package/dist/backend/dynamic-table/components/FooterTotalsRow.js +165 -0
  240. package/dist/backend/dynamic-table/components/FooterTotalsRow.js.map +7 -0
  241. package/dist/backend/dynamic-table/components/FullscreenOverlay.js +51 -0
  242. package/dist/backend/dynamic-table/components/FullscreenOverlay.js.map +7 -0
  243. package/dist/backend/dynamic-table/components/GroupHeaderRow.js +108 -0
  244. package/dist/backend/dynamic-table/components/GroupHeaderRow.js.map +7 -0
  245. package/dist/backend/dynamic-table/components/GroupSummaryRow.js +134 -0
  246. package/dist/backend/dynamic-table/components/GroupSummaryRow.js.map +7 -0
  247. package/dist/backend/dynamic-table/components/ImportPanel.js +341 -0
  248. package/dist/backend/dynamic-table/components/ImportPanel.js.map +7 -0
  249. package/dist/backend/dynamic-table/components/ImportPreviewGrid.js +114 -0
  250. package/dist/backend/dynamic-table/components/ImportPreviewGrid.js.map +7 -0
  251. package/dist/backend/dynamic-table/components/LoadErrorState.js +23 -0
  252. package/dist/backend/dynamic-table/components/LoadErrorState.js.map +7 -0
  253. package/dist/backend/dynamic-table/components/MentionPopup.js +149 -0
  254. package/dist/backend/dynamic-table/components/MentionPopup.js.map +7 -0
  255. package/dist/backend/dynamic-table/components/PerspectiveDeleteDialog.js +57 -0
  256. package/dist/backend/dynamic-table/components/PerspectiveDeleteDialog.js.map +7 -0
  257. package/dist/backend/dynamic-table/components/PerspectivePublishDialog.js +100 -0
  258. package/dist/backend/dynamic-table/components/PerspectivePublishDialog.js.map +7 -0
  259. package/dist/backend/dynamic-table/components/PerspectiveTabMenu.js +159 -0
  260. package/dist/backend/dynamic-table/components/PerspectiveTabMenu.js.map +7 -0
  261. package/dist/backend/dynamic-table/components/PerspectiveTabs.js +319 -0
  262. package/dist/backend/dynamic-table/components/PerspectiveTabs.js.map +7 -0
  263. package/dist/backend/dynamic-table/components/PerspectiveTemplateMenu.js +90 -0
  264. package/dist/backend/dynamic-table/components/PerspectiveTemplateMenu.js.map +7 -0
  265. package/dist/backend/dynamic-table/components/RowHeaderCell.js +58 -0
  266. package/dist/backend/dynamic-table/components/RowHeaderCell.js.map +7 -0
  267. package/dist/backend/dynamic-table/components/SearchBar.js +221 -0
  268. package/dist/backend/dynamic-table/components/SearchBar.js.map +7 -0
  269. package/dist/backend/dynamic-table/components/SelectMenu.js +186 -0
  270. package/dist/backend/dynamic-table/components/SelectMenu.js.map +7 -0
  271. package/dist/backend/dynamic-table/components/StaleDataBar.js +26 -0
  272. package/dist/backend/dynamic-table/components/StaleDataBar.js.map +7 -0
  273. package/dist/backend/dynamic-table/components/TableDeleteDialog.js +48 -0
  274. package/dist/backend/dynamic-table/components/TableDeleteDialog.js.map +7 -0
  275. package/dist/backend/dynamic-table/components/TablePagination.js +69 -0
  276. package/dist/backend/dynamic-table/components/TablePagination.js.map +7 -0
  277. package/dist/backend/dynamic-table/components/TableSkeleton.js +43 -0
  278. package/dist/backend/dynamic-table/components/TableSkeleton.js.map +7 -0
  279. package/dist/backend/dynamic-table/components/ToolbarOverflow.js +204 -0
  280. package/dist/backend/dynamic-table/components/ToolbarOverflow.js.map +7 -0
  281. package/dist/backend/dynamic-table/components/ViewModeSwitch.js +50 -0
  282. package/dist/backend/dynamic-table/components/ViewModeSwitch.js.map +7 -0
  283. package/dist/backend/dynamic-table/components/VirtualRow.js +214 -0
  284. package/dist/backend/dynamic-table/components/VirtualRow.js.map +7 -0
  285. package/dist/backend/dynamic-table/components/editors.js +1483 -0
  286. package/dist/backend/dynamic-table/components/editors.js.map +7 -0
  287. package/dist/backend/dynamic-table/components/renderers.js +131 -0
  288. package/dist/backend/dynamic-table/components/renderers.js.map +7 -0
  289. package/dist/backend/dynamic-table/events/events.js +73 -0
  290. package/dist/backend/dynamic-table/events/events.js.map +7 -0
  291. package/dist/backend/dynamic-table/formula/check.js +243 -0
  292. package/dist/backend/dynamic-table/formula/check.js.map +7 -0
  293. package/dist/backend/dynamic-table/formula/evaluate.js +302 -0
  294. package/dist/backend/dynamic-table/formula/evaluate.js.map +7 -0
  295. package/dist/backend/dynamic-table/formula/functions.js +602 -0
  296. package/dist/backend/dynamic-table/formula/functions.js.map +7 -0
  297. package/dist/backend/dynamic-table/formula/index.js +47 -0
  298. package/dist/backend/dynamic-table/formula/index.js.map +7 -0
  299. package/dist/backend/dynamic-table/formula/parse.js +293 -0
  300. package/dist/backend/dynamic-table/formula/parse.js.map +7 -0
  301. package/dist/backend/dynamic-table/formula/types.js +24 -0
  302. package/dist/backend/dynamic-table/formula/types.js.map +7 -0
  303. package/dist/backend/dynamic-table/handlers/cellWrites.js +143 -0
  304. package/dist/backend/dynamic-table/handlers/cellWrites.js.map +7 -0
  305. package/dist/backend/dynamic-table/handlers/index.js +504 -0
  306. package/dist/backend/dynamic-table/handlers/index.js.map +7 -0
  307. package/dist/backend/dynamic-table/handlers/perspectiveHandlers.js +377 -0
  308. package/dist/backend/dynamic-table/handlers/perspectiveHandlers.js.map +7 -0
  309. package/dist/backend/dynamic-table/hooks/index.js +524 -0
  310. package/dist/backend/dynamic-table/hooks/index.js.map +7 -0
  311. package/dist/backend/dynamic-table/hooks/useAbbreviations.js +19 -0
  312. package/dist/backend/dynamic-table/hooks/useAbbreviations.js.map +7 -0
  313. package/dist/backend/dynamic-table/hooks/useAnnotations.js +115 -0
  314. package/dist/backend/dynamic-table/hooks/useAnnotations.js.map +7 -0
  315. package/dist/backend/dynamic-table/hooks/useColumnVirtualizer.js +155 -0
  316. package/dist/backend/dynamic-table/hooks/useColumnVirtualizer.js.map +7 -0
  317. package/dist/backend/dynamic-table/hooks/useColumnWidthPersistence.js +135 -0
  318. package/dist/backend/dynamic-table/hooks/useColumnWidthPersistence.js.map +7 -0
  319. package/dist/backend/dynamic-table/hooks/useDensityPreference.js +203 -0
  320. package/dist/backend/dynamic-table/hooks/useDensityPreference.js.map +7 -0
  321. package/dist/backend/dynamic-table/hooks/useDynamicTablePage.js +1005 -0
  322. package/dist/backend/dynamic-table/hooks/useDynamicTablePage.js.map +7 -0
  323. package/dist/backend/dynamic-table/hooks/useEscapeLayer.js +32 -0
  324. package/dist/backend/dynamic-table/hooks/useEscapeLayer.js.map +7 -0
  325. package/dist/backend/dynamic-table/hooks/useGrouping.js +256 -0
  326. package/dist/backend/dynamic-table/hooks/useGrouping.js.map +7 -0
  327. package/dist/backend/dynamic-table/hooks/useSuggestionFetch.js +63 -0
  328. package/dist/backend/dynamic-table/hooks/useSuggestionFetch.js.map +7 -0
  329. package/dist/backend/dynamic-table/hooks/useTableDateFormat.js +11 -0
  330. package/dist/backend/dynamic-table/hooks/useTableDateFormat.js.map +7 -0
  331. package/dist/backend/dynamic-table/index.js +476 -0
  332. package/dist/backend/dynamic-table/index.js.map +7 -0
  333. package/dist/backend/dynamic-table/registry/ContentRegistryContext.js +126 -0
  334. package/dist/backend/dynamic-table/registry/ContentRegistryContext.js.map +7 -0
  335. package/dist/backend/dynamic-table/registry/TableRegistryContext.js +43 -0
  336. package/dist/backend/dynamic-table/registry/TableRegistryContext.js.map +7 -0
  337. package/dist/backend/dynamic-table/registry/filterAccessibleTables.js +13 -0
  338. package/dist/backend/dynamic-table/registry/filterAccessibleTables.js.map +7 -0
  339. package/dist/backend/dynamic-table/registry/index.js +44 -0
  340. package/dist/backend/dynamic-table/registry/index.js.map +7 -0
  341. package/dist/backend/dynamic-table/registry/lazyTable.js +55 -0
  342. package/dist/backend/dynamic-table/registry/lazyTable.js.map +7 -0
  343. package/dist/backend/dynamic-table/registry/types.js +1 -0
  344. package/dist/backend/dynamic-table/registry/types.js.map +7 -0
  345. package/dist/backend/dynamic-table/registry/widgetCatalog.js +96 -0
  346. package/dist/backend/dynamic-table/registry/widgetCatalog.js.map +7 -0
  347. package/dist/backend/dynamic-table/server/aggregate.js +261 -0
  348. package/dist/backend/dynamic-table/server/aggregate.js.map +7 -0
  349. package/dist/backend/dynamic-table/server/dateWindows.js +105 -0
  350. package/dist/backend/dynamic-table/server/dateWindows.js.map +7 -0
  351. package/dist/backend/dynamic-table/server/filterParser.js +97 -0
  352. package/dist/backend/dynamic-table/server/filterParser.js.map +7 -0
  353. package/dist/backend/dynamic-table/server/filterSuggestions.js +70 -0
  354. package/dist/backend/dynamic-table/server/filterSuggestions.js.map +7 -0
  355. package/dist/backend/dynamic-table/server/index.js +47 -0
  356. package/dist/backend/dynamic-table/server/index.js.map +7 -0
  357. package/dist/backend/dynamic-table/server/makeDynamicTableRoute.js +270 -0
  358. package/dist/backend/dynamic-table/server/makeDynamicTableRoute.js.map +7 -0
  359. package/dist/backend/dynamic-table/split-view/ContentPicker.js +171 -0
  360. package/dist/backend/dynamic-table/split-view/ContentPicker.js.map +7 -0
  361. package/dist/backend/dynamic-table/split-view/EmptySlot.js +47 -0
  362. package/dist/backend/dynamic-table/split-view/EmptySlot.js.map +7 -0
  363. package/dist/backend/dynamic-table/split-view/SplitViewHost.js +863 -0
  364. package/dist/backend/dynamic-table/split-view/SplitViewHost.js.map +7 -0
  365. package/dist/backend/dynamic-table/split-view/WidgetPane.js +280 -0
  366. package/dist/backend/dynamic-table/split-view/WidgetPane.js.map +7 -0
  367. package/dist/backend/dynamic-table/split-view/WorkspaceFilterBar.js +524 -0
  368. package/dist/backend/dynamic-table/split-view/WorkspaceFilterBar.js.map +7 -0
  369. package/dist/backend/dynamic-table/split-view/index.js +61 -0
  370. package/dist/backend/dynamic-table/split-view/index.js.map +7 -0
  371. package/dist/backend/dynamic-table/split-view/layoutPersistence.js +91 -0
  372. package/dist/backend/dynamic-table/split-view/layoutPersistence.js.map +7 -0
  373. package/dist/backend/dynamic-table/split-view/sharedCriteria.js +62 -0
  374. package/dist/backend/dynamic-table/split-view/sharedCriteria.js.map +7 -0
  375. package/dist/backend/dynamic-table/split-view/types.js +426 -0
  376. package/dist/backend/dynamic-table/split-view/types.js.map +7 -0
  377. package/dist/backend/dynamic-table/split-view/useSplitViewLayouts.js +79 -0
  378. package/dist/backend/dynamic-table/split-view/useSplitViewLayouts.js.map +7 -0
  379. package/dist/backend/dynamic-table/store/index.js +611 -0
  380. package/dist/backend/dynamic-table/store/index.js.map +7 -0
  381. package/dist/backend/dynamic-table/styles/ContextMenu.css.js +2 -0
  382. package/dist/backend/dynamic-table/styles/DynamicTable.css.js +2 -0
  383. package/dist/backend/dynamic-table/styles/DynamicTable.v2.css.js +2 -0
  384. package/dist/backend/dynamic-table/styles/SearchBar.css.js +2 -0
  385. package/dist/backend/dynamic-table/styles/dateCell.css.js +2 -0
  386. package/dist/backend/dynamic-table/styles/density.css.js +2 -0
  387. package/dist/backend/dynamic-table/types/density.js +29 -0
  388. package/dist/backend/dynamic-table/types/density.js.map +7 -0
  389. package/dist/backend/dynamic-table/types/filters.js +124 -0
  390. package/dist/backend/dynamic-table/types/filters.js.map +7 -0
  391. package/dist/backend/dynamic-table/types/grouping.js +34 -0
  392. package/dist/backend/dynamic-table/types/grouping.js.map +7 -0
  393. package/dist/backend/dynamic-table/types/import.js +7 -0
  394. package/dist/backend/dynamic-table/types/import.js.map +7 -0
  395. package/dist/backend/dynamic-table/types/index.js +46 -0
  396. package/dist/backend/dynamic-table/types/index.js.map +7 -0
  397. package/dist/backend/dynamic-table/types/perspective.js +79 -0
  398. package/dist/backend/dynamic-table/types/perspective.js.map +7 -0
  399. package/dist/backend/dynamic-table/types/rollup.js +13 -0
  400. package/dist/backend/dynamic-table/types/rollup.js.map +7 -0
  401. package/dist/backend/dynamic-table/utils/abbreviations.js +228 -0
  402. package/dist/backend/dynamic-table/utils/abbreviations.js.map +7 -0
  403. package/dist/backend/dynamic-table/utils/anchoredPosition.js +21 -0
  404. package/dist/backend/dynamic-table/utils/anchoredPosition.js.map +7 -0
  405. package/dist/backend/dynamic-table/utils/badgeAutoFit.js +35 -0
  406. package/dist/backend/dynamic-table/utils/badgeAutoFit.js.map +7 -0
  407. package/dist/backend/dynamic-table/utils/clipboard.js +172 -0
  408. package/dist/backend/dynamic-table/utils/clipboard.js.map +7 -0
  409. package/dist/backend/dynamic-table/utils/coerceCellValue.js +52 -0
  410. package/dist/backend/dynamic-table/utils/coerceCellValue.js.map +7 -0
  411. package/dist/backend/dynamic-table/utils/colorAdjacency.js +27 -0
  412. package/dist/backend/dynamic-table/utils/colorAdjacency.js.map +7 -0
  413. package/dist/backend/dynamic-table/utils/columnFill.js +36 -0
  414. package/dist/backend/dynamic-table/utils/columnFill.js.map +7 -0
  415. package/dist/backend/dynamic-table/utils/columnSpacerStyle.js +21 -0
  416. package/dist/backend/dynamic-table/utils/columnSpacerStyle.js.map +7 -0
  417. package/dist/backend/dynamic-table/utils/columnWindow.js +293 -0
  418. package/dist/backend/dynamic-table/utils/columnWindow.js.map +7 -0
  419. package/dist/backend/dynamic-table/utils/conditionalFormat.js +188 -0
  420. package/dist/backend/dynamic-table/utils/conditionalFormat.js.map +7 -0
  421. package/dist/backend/dynamic-table/utils/exportTable.js +82 -0
  422. package/dist/backend/dynamic-table/utils/exportTable.js.map +7 -0
  423. package/dist/backend/dynamic-table/utils/fillGeometry.js +92 -0
  424. package/dist/backend/dynamic-table/utils/fillGeometry.js.map +7 -0
  425. package/dist/backend/dynamic-table/utils/fillPatterns.js +241 -0
  426. package/dist/backend/dynamic-table/utils/fillPatterns.js.map +7 -0
  427. package/dist/backend/dynamic-table/utils/formatAggregate.js +82 -0
  428. package/dist/backend/dynamic-table/utils/formatAggregate.js.map +7 -0
  429. package/dist/backend/dynamic-table/utils/formatDateCompact.js +508 -0
  430. package/dist/backend/dynamic-table/utils/formatDateCompact.js.map +7 -0
  431. package/dist/backend/dynamic-table/utils/formatLabelCompact.js +312 -0
  432. package/dist/backend/dynamic-table/utils/formatLabelCompact.js.map +7 -0
  433. package/dist/backend/dynamic-table/utils/formulaColumns.js +158 -0
  434. package/dist/backend/dynamic-table/utils/formulaColumns.js.map +7 -0
  435. package/dist/backend/dynamic-table/utils/importMapping.js +118 -0
  436. package/dist/backend/dynamic-table/utils/importMapping.js.map +7 -0
  437. package/dist/backend/dynamic-table/utils/importParse.js +121 -0
  438. package/dist/backend/dynamic-table/utils/importParse.js.map +7 -0
  439. package/dist/backend/dynamic-table/utils/lookupColumns.js +28 -0
  440. package/dist/backend/dynamic-table/utils/lookupColumns.js.map +7 -0
  441. package/dist/backend/dynamic-table/utils/perspectiveTransforms.js +191 -0
  442. package/dist/backend/dynamic-table/utils/perspectiveTransforms.js.map +7 -0
  443. package/dist/backend/dynamic-table/utils/rollupColumns.js +81 -0
  444. package/dist/backend/dynamic-table/utils/rollupColumns.js.map +7 -0
  445. package/dist/backend/dynamic-table/validators/index.js +36 -0
  446. package/dist/backend/dynamic-table/validators/index.js.map +7 -0
  447. package/dist/backend/fields/registry.generated.js +8 -0
  448. package/dist/backend/fields/registry.generated.js.map +7 -0
  449. package/dist/backend/fields/registry.js +29 -0
  450. package/dist/backend/fields/registry.js.map +7 -0
  451. package/dist/backend/filters/AdvancedFilterBuilder.js +280 -0
  452. package/dist/backend/filters/AdvancedFilterBuilder.js.map +7 -0
  453. package/dist/backend/forms/ActionsDropdown.js +160 -0
  454. package/dist/backend/forms/ActionsDropdown.js.map +7 -0
  455. package/dist/backend/forms/FormActionButtons.js +59 -0
  456. package/dist/backend/forms/FormActionButtons.js.map +7 -0
  457. package/dist/backend/forms/FormFooter.js +18 -0
  458. package/dist/backend/forms/FormFooter.js.map +7 -0
  459. package/dist/backend/forms/FormHeader.js +125 -0
  460. package/dist/backend/forms/FormHeader.js.map +7 -0
  461. package/dist/backend/forms/index.js +11 -0
  462. package/dist/backend/forms/index.js.map +7 -0
  463. package/dist/backend/hooks/useAdvancedFilter.js +64 -0
  464. package/dist/backend/hooks/useAdvancedFilter.js.map +7 -0
  465. package/dist/backend/indexes/PartialIndexBanner.js +74 -0
  466. package/dist/backend/indexes/PartialIndexBanner.js.map +7 -0
  467. package/dist/backend/indexes/store.js +62 -0
  468. package/dist/backend/indexes/store.js.map +7 -0
  469. package/dist/backend/injection/ComponentOverrideProvider.js +55 -0
  470. package/dist/backend/injection/ComponentOverrideProvider.js.map +7 -0
  471. package/dist/backend/injection/InjectedField.js +166 -0
  472. package/dist/backend/injection/InjectedField.js.map +7 -0
  473. package/dist/backend/injection/InjectionSpot.js +323 -0
  474. package/dist/backend/injection/InjectionSpot.js.map +7 -0
  475. package/dist/backend/injection/InjectionWizard.js +256 -0
  476. package/dist/backend/injection/InjectionWizard.js.map +7 -0
  477. package/dist/backend/injection/PageInjectionBoundary.js +26 -0
  478. package/dist/backend/injection/PageInjectionBoundary.js.map +7 -0
  479. package/dist/backend/injection/SseEventIndicator.js +8 -0
  480. package/dist/backend/injection/SseEventIndicator.js.map +7 -0
  481. package/dist/backend/injection/StatusBadgeInjectionSpot.js +34 -0
  482. package/dist/backend/injection/StatusBadgeInjectionSpot.js.map +7 -0
  483. package/dist/backend/injection/StatusBadgeRenderer.js +58 -0
  484. package/dist/backend/injection/StatusBadgeRenderer.js.map +7 -0
  485. package/dist/backend/injection/WidgetSharedState.js +49 -0
  486. package/dist/backend/injection/WidgetSharedState.js.map +7 -0
  487. package/dist/backend/injection/WizardInjectionSpot.js +30 -0
  488. package/dist/backend/injection/WizardInjectionSpot.js.map +7 -0
  489. package/dist/backend/injection/eventBridge.js +129 -0
  490. package/dist/backend/injection/eventBridge.js.map +7 -0
  491. package/dist/backend/injection/helpers.js +26 -0
  492. package/dist/backend/injection/helpers.js.map +7 -0
  493. package/dist/backend/injection/mergeMenuItems.js +49 -0
  494. package/dist/backend/injection/mergeMenuItems.js.map +7 -0
  495. package/dist/backend/injection/mutationEvents.js +20 -0
  496. package/dist/backend/injection/mutationEvents.js.map +7 -0
  497. package/dist/backend/injection/resolveInjectedIcon.js +23 -0
  498. package/dist/backend/injection/resolveInjectedIcon.js.map +7 -0
  499. package/dist/backend/injection/spotIds.js +72 -0
  500. package/dist/backend/injection/spotIds.js.map +7 -0
  501. package/dist/backend/injection/useAppEvent.js +35 -0
  502. package/dist/backend/injection/useAppEvent.js.map +7 -0
  503. package/dist/backend/injection/useGuardedMutation.js +71 -0
  504. package/dist/backend/injection/useGuardedMutation.js.map +7 -0
  505. package/dist/backend/injection/useInjectedMenuItems.js +49 -0
  506. package/dist/backend/injection/useInjectedMenuItems.js.map +7 -0
  507. package/dist/backend/injection/useInjectionDataWidgets.js +36 -0
  508. package/dist/backend/injection/useInjectionDataWidgets.js.map +7 -0
  509. package/dist/backend/injection/useOperationProgress.js +64 -0
  510. package/dist/backend/injection/useOperationProgress.js.map +7 -0
  511. package/dist/backend/injection/useRegisteredComponent.js +89 -0
  512. package/dist/backend/injection/useRegisteredComponent.js.map +7 -0
  513. package/dist/backend/injection/useWidgetSharedState.js +26 -0
  514. package/dist/backend/injection/useWidgetSharedState.js.map +7 -0
  515. package/dist/backend/injection/visibility-utils.js +29 -0
  516. package/dist/backend/injection/visibility-utils.js.map +7 -0
  517. package/dist/backend/injection/widgetRegistry.js +55 -0
  518. package/dist/backend/injection/widgetRegistry.js.map +7 -0
  519. package/dist/backend/inputs/ComboboxInput.js +228 -0
  520. package/dist/backend/inputs/ComboboxInput.js.map +7 -0
  521. package/dist/backend/inputs/DatePicker.js +148 -0
  522. package/dist/backend/inputs/DatePicker.js.map +7 -0
  523. package/dist/backend/inputs/DateTimePicker.js +188 -0
  524. package/dist/backend/inputs/DateTimePicker.js.map +7 -0
  525. package/dist/backend/inputs/EventPatternInput.js +38 -0
  526. package/dist/backend/inputs/EventPatternInput.js.map +7 -0
  527. package/dist/backend/inputs/EventSelect.js +115 -0
  528. package/dist/backend/inputs/EventSelect.js.map +7 -0
  529. package/dist/backend/inputs/LookupSelect.js +197 -0
  530. package/dist/backend/inputs/LookupSelect.js.map +7 -0
  531. package/dist/backend/inputs/PhoneNumberField.js +133 -0
  532. package/dist/backend/inputs/PhoneNumberField.js.map +7 -0
  533. package/dist/backend/inputs/SwitchableMarkdownInput.js +73 -0
  534. package/dist/backend/inputs/SwitchableMarkdownInput.js.map +7 -0
  535. package/dist/backend/inputs/TagsInput.js +258 -0
  536. package/dist/backend/inputs/TagsInput.js.map +7 -0
  537. package/dist/backend/inputs/TimeInput.js +132 -0
  538. package/dist/backend/inputs/TimeInput.js.map +7 -0
  539. package/dist/backend/inputs/TimePicker.js +105 -0
  540. package/dist/backend/inputs/TimePicker.js.map +7 -0
  541. package/dist/backend/inputs/index.js +12 -0
  542. package/dist/backend/inputs/index.js.map +7 -0
  543. package/dist/backend/markdown/MarkdownContent.js +20 -0
  544. package/dist/backend/markdown/MarkdownContent.js.map +7 -0
  545. package/dist/backend/markdown/index.js +3 -0
  546. package/dist/backend/markdown/index.js.map +7 -0
  547. package/dist/backend/markdown/useMarkdownRemarkPlugins.js +33 -0
  548. package/dist/backend/markdown/useMarkdownRemarkPlugins.js.map +7 -0
  549. package/dist/backend/messages/MessageComposer.js +158 -0
  550. package/dist/backend/messages/MessageComposer.js.map +7 -0
  551. package/dist/backend/messages/MessageObjectDetail.js +81 -0
  552. package/dist/backend/messages/MessageObjectDetail.js.map +7 -0
  553. package/dist/backend/messages/MessageObjectPreview.js +48 -0
  554. package/dist/backend/messages/MessageObjectPreview.js.map +7 -0
  555. package/dist/backend/messages/MessageObjectRecordPicker.js +89 -0
  556. package/dist/backend/messages/MessageObjectRecordPicker.js.map +7 -0
  557. package/dist/backend/messages/MessagePrioritySelector.js +74 -0
  558. package/dist/backend/messages/MessagePrioritySelector.js.map +7 -0
  559. package/dist/backend/messages/MessagesIcon.js +22 -0
  560. package/dist/backend/messages/MessagesIcon.js.map +7 -0
  561. package/dist/backend/messages/SendObjectMessageDialog.js +65 -0
  562. package/dist/backend/messages/SendObjectMessageDialog.js.map +7 -0
  563. package/dist/backend/messages/index.js +17 -0
  564. package/dist/backend/messages/index.js.map +7 -0
  565. package/dist/backend/messages/message-compose-form-groups.js +333 -0
  566. package/dist/backend/messages/message-compose-form-groups.js.map +7 -0
  567. package/dist/backend/messages/message-composer.types.js +1 -0
  568. package/dist/backend/messages/message-composer.types.js.map +7 -0
  569. package/dist/backend/messages/message-priority.js +40 -0
  570. package/dist/backend/messages/message-priority.js.map +7 -0
  571. package/dist/backend/messages/useMessageCompose.js +488 -0
  572. package/dist/backend/messages/useMessageCompose.js.map +7 -0
  573. package/dist/backend/messages/useMessageComposeOperations.js +163 -0
  574. package/dist/backend/messages/useMessageComposeOperations.js.map +7 -0
  575. package/dist/backend/messages/useMessagesPoll.js +79 -0
  576. package/dist/backend/messages/useMessagesPoll.js.map +7 -0
  577. package/dist/backend/notifications/NotificationBell.js +83 -0
  578. package/dist/backend/notifications/NotificationBell.js.map +7 -0
  579. package/dist/backend/notifications/NotificationCountBadge.js +9 -0
  580. package/dist/backend/notifications/NotificationCountBadge.js.map +7 -0
  581. package/dist/backend/notifications/NotificationDispatcher.js +165 -0
  582. package/dist/backend/notifications/NotificationDispatcher.js.map +7 -0
  583. package/dist/backend/notifications/NotificationItem.js +187 -0
  584. package/dist/backend/notifications/NotificationItem.js.map +7 -0
  585. package/dist/backend/notifications/NotificationPanel.js +146 -0
  586. package/dist/backend/notifications/NotificationPanel.js.map +7 -0
  587. package/dist/backend/notifications/index.js +19 -0
  588. package/dist/backend/notifications/index.js.map +7 -0
  589. package/dist/backend/notifications/useNotificationActions.js +124 -0
  590. package/dist/backend/notifications/useNotificationActions.js.map +7 -0
  591. package/dist/backend/notifications/useNotificationEffect.js +13 -0
  592. package/dist/backend/notifications/useNotificationEffect.js.map +7 -0
  593. package/dist/backend/notifications/useNotifications.js +11 -0
  594. package/dist/backend/notifications/useNotifications.js.map +7 -0
  595. package/dist/backend/notifications/useNotificationsPoll.js +135 -0
  596. package/dist/backend/notifications/useNotificationsPoll.js.map +7 -0
  597. package/dist/backend/notifications/useNotificationsSse.js +173 -0
  598. package/dist/backend/notifications/useNotificationsSse.js.map +7 -0
  599. package/dist/backend/operations/LastOperationBanner.js +80 -0
  600. package/dist/backend/operations/LastOperationBanner.js.map +7 -0
  601. package/dist/backend/operations/store.js +183 -0
  602. package/dist/backend/operations/store.js.map +7 -0
  603. package/dist/backend/progress/ProgressTopBar.js +129 -0
  604. package/dist/backend/progress/ProgressTopBar.js.map +7 -0
  605. package/dist/backend/progress/useProgress.js +11 -0
  606. package/dist/backend/progress/useProgress.js.map +7 -0
  607. package/dist/backend/progress/useProgressPoll.js +69 -0
  608. package/dist/backend/progress/useProgressPoll.js.map +7 -0
  609. package/dist/backend/progress/useProgressSse.js +104 -0
  610. package/dist/backend/progress/useProgressSse.js.map +7 -0
  611. package/dist/backend/schedule/ScheduleAgenda.js +107 -0
  612. package/dist/backend/schedule/ScheduleAgenda.js.map +7 -0
  613. package/dist/backend/schedule/ScheduleGrid.js +107 -0
  614. package/dist/backend/schedule/ScheduleGrid.js.map +7 -0
  615. package/dist/backend/schedule/ScheduleToolbar.js +166 -0
  616. package/dist/backend/schedule/ScheduleToolbar.js.map +7 -0
  617. package/dist/backend/schedule/ScheduleView.js +168 -0
  618. package/dist/backend/schedule/ScheduleView.js.map +7 -0
  619. package/dist/backend/schedule/index.js +6 -0
  620. package/dist/backend/schedule/index.js.map +7 -0
  621. package/dist/backend/schedule/recurrence.js +83 -0
  622. package/dist/backend/schedule/recurrence.js.map +7 -0
  623. package/dist/backend/schedule/types.js +1 -0
  624. package/dist/backend/schedule/types.js.map +7 -0
  625. package/dist/backend/section-page/SectionNav.js +104 -0
  626. package/dist/backend/section-page/SectionNav.js.map +7 -0
  627. package/dist/backend/section-page/SectionPage.js +33 -0
  628. package/dist/backend/section-page/SectionPage.js.map +7 -0
  629. package/dist/backend/section-page/index.js +7 -0
  630. package/dist/backend/section-page/index.js.map +7 -0
  631. package/dist/backend/section-page/types.js +1 -0
  632. package/dist/backend/section-page/types.js.map +7 -0
  633. package/dist/backend/settings/SettingsNavigation.js +43 -0
  634. package/dist/backend/settings/SettingsNavigation.js.map +7 -0
  635. package/dist/backend/settings/SettingsPageWrapper.js +66 -0
  636. package/dist/backend/settings/SettingsPageWrapper.js.map +7 -0
  637. package/dist/backend/settings/index.js +6 -0
  638. package/dist/backend/settings/index.js.map +7 -0
  639. package/dist/backend/upgrades/UpgradeActionBanner.js +91 -0
  640. package/dist/backend/upgrades/UpgradeActionBanner.js.map +7 -0
  641. package/dist/backend/utils/api.js +178 -0
  642. package/dist/backend/utils/api.js.map +7 -0
  643. package/dist/backend/utils/apiCall.js +68 -0
  644. package/dist/backend/utils/apiCall.js.map +7 -0
  645. package/dist/backend/utils/crud.js +126 -0
  646. package/dist/backend/utils/crud.js.map +7 -0
  647. package/dist/backend/utils/customFieldColumns.js +100 -0
  648. package/dist/backend/utils/customFieldColumns.js.map +7 -0
  649. package/dist/backend/utils/customFieldDefs.js +143 -0
  650. package/dist/backend/utils/customFieldDefs.js.map +7 -0
  651. package/dist/backend/utils/customFieldFilters.js +151 -0
  652. package/dist/backend/utils/customFieldFilters.js.map +7 -0
  653. package/dist/backend/utils/customFieldForms.js +169 -0
  654. package/dist/backend/utils/customFieldForms.js.map +7 -0
  655. package/dist/backend/utils/customFieldRelationDisplay.js +239 -0
  656. package/dist/backend/utils/customFieldRelationDisplay.js.map +7 -0
  657. package/dist/backend/utils/customFieldValues.js +26 -0
  658. package/dist/backend/utils/customFieldValues.js.map +7 -0
  659. package/dist/backend/utils/flash.js +16 -0
  660. package/dist/backend/utils/flash.js.map +7 -0
  661. package/dist/backend/utils/nav.js +280 -0
  662. package/dist/backend/utils/nav.js.map +7 -0
  663. package/dist/backend/utils/richTextSanitizer.js +11 -0
  664. package/dist/backend/utils/richTextSanitizer.js.map +7 -0
  665. package/dist/backend/utils/scopedHeaderStack.js +44 -0
  666. package/dist/backend/utils/scopedHeaderStack.js.map +7 -0
  667. package/dist/backend/utils/serverErrors.js +237 -0
  668. package/dist/backend/utils/serverErrors.js.map +7 -0
  669. package/dist/backend/utils/useAutoDiscoveredFields.js +96 -0
  670. package/dist/backend/utils/useAutoDiscoveredFields.js.map +7 -0
  671. package/dist/backend/version-history/VersionHistoryAction.js +67 -0
  672. package/dist/backend/version-history/VersionHistoryAction.js.map +7 -0
  673. package/dist/backend/version-history/VersionHistoryDetail.js +57 -0
  674. package/dist/backend/version-history/VersionHistoryDetail.js.map +7 -0
  675. package/dist/backend/version-history/VersionHistoryPanel.js +270 -0
  676. package/dist/backend/version-history/VersionHistoryPanel.js.map +7 -0
  677. package/dist/backend/version-history/index.js +13 -0
  678. package/dist/backend/version-history/index.js.map +7 -0
  679. package/dist/backend/version-history/labels.js +52 -0
  680. package/dist/backend/version-history/labels.js.map +7 -0
  681. package/dist/backend/version-history/types.js +1 -0
  682. package/dist/backend/version-history/types.js.map +7 -0
  683. package/dist/backend/version-history/useAuditPermissions.js +72 -0
  684. package/dist/backend/version-history/useAuditPermissions.js.map +7 -0
  685. package/dist/backend/version-history/useVersionHistory.js +141 -0
  686. package/dist/backend/version-history/useVersionHistory.js.map +7 -0
  687. package/dist/backend/views/NewViewForm.js +56 -0
  688. package/dist/backend/views/NewViewForm.js.map +7 -0
  689. package/dist/backend/views/ShareForm.js +49 -0
  690. package/dist/backend/views/ShareForm.js.map +7 -0
  691. package/dist/backend/views/ViewChip.js +112 -0
  692. package/dist/backend/views/ViewChip.js.map +7 -0
  693. package/dist/backend/views/ViewChipMenu.js +89 -0
  694. package/dist/backend/views/ViewChipMenu.js.map +7 -0
  695. package/dist/backend/views/types.js +1 -0
  696. package/dist/backend/views/types.js.map +7 -0
  697. package/dist/frontend/AuthFooter.js +23 -0
  698. package/dist/frontend/AuthFooter.js.map +7 -0
  699. package/dist/frontend/LanguageSwitcher.js +57 -0
  700. package/dist/frontend/LanguageSwitcher.js.map +7 -0
  701. package/dist/frontend/Layout.js +14 -0
  702. package/dist/frontend/Layout.js.map +7 -0
  703. package/dist/hooks/useIsMobile.js +21 -0
  704. package/dist/hooks/useIsMobile.js.map +7 -0
  705. package/dist/index.js +40 -0
  706. package/dist/index.js.map +7 -0
  707. package/dist/portal/PortalContext.js +113 -0
  708. package/dist/portal/PortalContext.js.map +7 -0
  709. package/dist/portal/PortalLayoutProvider.js +5 -0
  710. package/dist/portal/PortalLayoutProvider.js.map +7 -0
  711. package/dist/portal/PortalLayoutShell.js +44 -0
  712. package/dist/portal/PortalLayoutShell.js.map +7 -0
  713. package/dist/portal/PortalShell.js +229 -0
  714. package/dist/portal/PortalShell.js.map +7 -0
  715. package/dist/portal/components/PortalCard.js +31 -0
  716. package/dist/portal/components/PortalCard.js.map +7 -0
  717. package/dist/portal/components/PortalEmptyState.js +16 -0
  718. package/dist/portal/components/PortalEmptyState.js.map +7 -0
  719. package/dist/portal/components/PortalFeatureCard.js +21 -0
  720. package/dist/portal/components/PortalFeatureCard.js.map +7 -0
  721. package/dist/portal/components/PortalNotificationBell.js +67 -0
  722. package/dist/portal/components/PortalNotificationBell.js.map +7 -0
  723. package/dist/portal/components/PortalNotificationPanel.js +158 -0
  724. package/dist/portal/components/PortalNotificationPanel.js.map +7 -0
  725. package/dist/portal/components/PortalPageHeader.js +16 -0
  726. package/dist/portal/components/PortalPageHeader.js.map +7 -0
  727. package/dist/portal/components/index.js +18 -0
  728. package/dist/portal/components/index.js.map +7 -0
  729. package/dist/portal/hooks/useCustomerAuth.js +69 -0
  730. package/dist/portal/hooks/useCustomerAuth.js.map +7 -0
  731. package/dist/portal/hooks/usePortalAppEvent.js +26 -0
  732. package/dist/portal/hooks/usePortalAppEvent.js.map +7 -0
  733. package/dist/portal/hooks/usePortalDashboardWidgets.js +37 -0
  734. package/dist/portal/hooks/usePortalDashboardWidgets.js.map +7 -0
  735. package/dist/portal/hooks/usePortalEventBridge.js +129 -0
  736. package/dist/portal/hooks/usePortalEventBridge.js.map +7 -0
  737. package/dist/portal/hooks/usePortalInjectedMenuItems.js +88 -0
  738. package/dist/portal/hooks/usePortalInjectedMenuItems.js.map +7 -0
  739. package/dist/portal/hooks/usePortalNotifications.js +85 -0
  740. package/dist/portal/hooks/usePortalNotifications.js.map +7 -0
  741. package/dist/portal/hooks/useTenantContext.js +53 -0
  742. package/dist/portal/hooks/useTenantContext.js.map +7 -0
  743. package/dist/primitives/DataLoader.js +68 -0
  744. package/dist/primitives/DataLoader.js.map +7 -0
  745. package/dist/primitives/ErrorNotice.js +14 -0
  746. package/dist/primitives/ErrorNotice.js.map +7 -0
  747. package/dist/primitives/Notice.js +55 -0
  748. package/dist/primitives/Notice.js.map +7 -0
  749. package/dist/primitives/alert.js +38 -0
  750. package/dist/primitives/alert.js.map +7 -0
  751. package/dist/primitives/badge.js +33 -0
  752. package/dist/primitives/badge.js.map +7 -0
  753. package/dist/primitives/button.js +45 -0
  754. package/dist/primitives/button.js.map +7 -0
  755. package/dist/primitives/calendar.js +62 -0
  756. package/dist/primitives/calendar.js.map +7 -0
  757. package/dist/primitives/card.js +91 -0
  758. package/dist/primitives/card.js.map +7 -0
  759. package/dist/primitives/checkbox.js +28 -0
  760. package/dist/primitives/checkbox.js.map +7 -0
  761. package/dist/primitives/dialog.js +101 -0
  762. package/dist/primitives/dialog.js.map +7 -0
  763. package/dist/primitives/form-field.js +78 -0
  764. package/dist/primitives/form-field.js.map +7 -0
  765. package/dist/primitives/icon-button.js +40 -0
  766. package/dist/primitives/icon-button.js.map +7 -0
  767. package/dist/primitives/input.js +22 -0
  768. package/dist/primitives/input.js.map +7 -0
  769. package/dist/primitives/label.js +21 -0
  770. package/dist/primitives/label.js.map +7 -0
  771. package/dist/primitives/popover.js +36 -0
  772. package/dist/primitives/popover.js.map +7 -0
  773. package/dist/primitives/primitives.stories.js +187 -0
  774. package/dist/primitives/primitives.stories.js.map +7 -0
  775. package/dist/primitives/progress.js +28 -0
  776. package/dist/primitives/progress.js.map +7 -0
  777. package/dist/primitives/separator.js +9 -0
  778. package/dist/primitives/separator.js.map +7 -0
  779. package/dist/primitives/sheet.js +103 -0
  780. package/dist/primitives/sheet.js.map +7 -0
  781. package/dist/primitives/spinner.js +24 -0
  782. package/dist/primitives/spinner.js.map +7 -0
  783. package/dist/primitives/status-badge.js +38 -0
  784. package/dist/primitives/status-badge.js.map +7 -0
  785. package/dist/primitives/switch.js +80 -0
  786. package/dist/primitives/switch.js.map +7 -0
  787. package/dist/primitives/table.js +29 -0
  788. package/dist/primitives/table.js.map +7 -0
  789. package/dist/primitives/tabs.js +90 -0
  790. package/dist/primitives/tabs.js.map +7 -0
  791. package/dist/primitives/textarea.js +21 -0
  792. package/dist/primitives/textarea.js.map +7 -0
  793. package/dist/primitives/tooltip.js +60 -0
  794. package/dist/primitives/tooltip.js.map +7 -0
  795. package/dist/primitives-v2/Alert.js +69 -0
  796. package/dist/primitives-v2/Alert.js.map +7 -0
  797. package/dist/primitives-v2/Alert.stories.js +42 -0
  798. package/dist/primitives-v2/Alert.stories.js.map +7 -0
  799. package/dist/primitives-v2/Avatar.js +93 -0
  800. package/dist/primitives-v2/Avatar.js.map +7 -0
  801. package/dist/primitives-v2/Avatar.stories.js +57 -0
  802. package/dist/primitives-v2/Avatar.stories.js.map +7 -0
  803. package/dist/primitives-v2/Badge.js +50 -0
  804. package/dist/primitives-v2/Badge.js.map +7 -0
  805. package/dist/primitives-v2/Badge.stories.js +66 -0
  806. package/dist/primitives-v2/Badge.stories.js.map +7 -0
  807. package/dist/primitives-v2/Breadcrumb.js +53 -0
  808. package/dist/primitives-v2/Breadcrumb.js.map +7 -0
  809. package/dist/primitives-v2/Breadcrumb.stories.js +70 -0
  810. package/dist/primitives-v2/Breadcrumb.stories.js.map +7 -0
  811. package/dist/primitives-v2/Button.js +85 -0
  812. package/dist/primitives-v2/Button.js.map +7 -0
  813. package/dist/primitives-v2/Button.stories.js +48 -0
  814. package/dist/primitives-v2/Button.stories.js.map +7 -0
  815. package/dist/primitives-v2/Checkbox.js +65 -0
  816. package/dist/primitives-v2/Checkbox.js.map +7 -0
  817. package/dist/primitives-v2/Checkbox.stories.js +31 -0
  818. package/dist/primitives-v2/Checkbox.stories.js.map +7 -0
  819. package/dist/primitives-v2/IconButton.js +13 -0
  820. package/dist/primitives-v2/IconButton.js.map +7 -0
  821. package/dist/primitives-v2/IconButton.stories.js +37 -0
  822. package/dist/primitives-v2/IconButton.stories.js.map +7 -0
  823. package/dist/primitives-v2/Input.js +74 -0
  824. package/dist/primitives-v2/Input.js.map +7 -0
  825. package/dist/primitives-v2/Input.stories.js +56 -0
  826. package/dist/primitives-v2/Input.stories.js.map +7 -0
  827. package/dist/primitives-v2/NavGroup.js +54 -0
  828. package/dist/primitives-v2/NavGroup.js.map +7 -0
  829. package/dist/primitives-v2/NavGroup.stories.js +39 -0
  830. package/dist/primitives-v2/NavGroup.stories.js.map +7 -0
  831. package/dist/primitives-v2/NavItem.js +61 -0
  832. package/dist/primitives-v2/NavItem.js.map +7 -0
  833. package/dist/primitives-v2/NavItem.stories.js +56 -0
  834. package/dist/primitives-v2/NavItem.stories.js.map +7 -0
  835. package/dist/primitives-v2/SearchInput.js +93 -0
  836. package/dist/primitives-v2/SearchInput.js.map +7 -0
  837. package/dist/primitives-v2/SearchInput.stories.js +41 -0
  838. package/dist/primitives-v2/SearchInput.stories.js.map +7 -0
  839. package/dist/primitives-v2/Sidebar.js +48 -0
  840. package/dist/primitives-v2/Sidebar.js.map +7 -0
  841. package/dist/primitives-v2/Sidebar.stories.js +76 -0
  842. package/dist/primitives-v2/Sidebar.stories.js.map +7 -0
  843. package/dist/primitives-v2/Tab.js +78 -0
  844. package/dist/primitives-v2/Tab.js.map +7 -0
  845. package/dist/primitives-v2/Tab.stories.js +51 -0
  846. package/dist/primitives-v2/Tab.stories.js.map +7 -0
  847. package/dist/primitives-v2/Tag.js +61 -0
  848. package/dist/primitives-v2/Tag.js.map +7 -0
  849. package/dist/primitives-v2/Tag.stories.js +121 -0
  850. package/dist/primitives-v2/Tag.stories.js.map +7 -0
  851. package/dist/primitives-v2/Toggle.js +72 -0
  852. package/dist/primitives-v2/Toggle.js.map +7 -0
  853. package/dist/primitives-v2/Toggle.stories.js +34 -0
  854. package/dist/primitives-v2/Toggle.stories.js.map +7 -0
  855. package/dist/primitives-v2/Topbar.js +24 -0
  856. package/dist/primitives-v2/Topbar.js.map +7 -0
  857. package/dist/primitives-v2/Topbar.stories.js +58 -0
  858. package/dist/primitives-v2/Topbar.stories.js.map +7 -0
  859. package/dist/primitives-v2/index.js +41 -0
  860. package/dist/primitives-v2/index.js.map +7 -0
  861. package/dist/primitives-v2/utils.js +7 -0
  862. package/dist/primitives-v2/utils.js.map +7 -0
  863. package/dist/theme/BrandThemeProvider.js +49 -0
  864. package/dist/theme/BrandThemeProvider.js.map +7 -0
  865. package/dist/theme/QueryProvider.js +44 -0
  866. package/dist/theme/QueryProvider.js.map +7 -0
  867. package/dist/theme/ThemeProvider.js +96 -0
  868. package/dist/theme/ThemeProvider.js.map +7 -0
  869. package/dist/theme/ThemeToggle.js +88 -0
  870. package/dist/theme/ThemeToggle.js.map +7 -0
  871. package/dist/theme/index.js +12 -0
  872. package/dist/theme/index.js.map +7 -0
  873. package/dist/theme/m3.css.js +2 -0
  874. package/dist/theme/tokens.v2.css.js +2 -0
  875. package/dist/theme/typography.css.js +2 -0
  876. package/dist/theme/typography.stories.js +123 -0
  877. package/dist/theme/typography.stories.js.map +7 -0
  878. package/dist/theme/typography.tokens.js +281 -0
  879. package/dist/theme/typography.tokens.js.map +7 -0
  880. package/dist/types/react-big-calendar.d.js +1 -0
  881. package/dist/types/react-big-calendar.d.js.map +7 -0
  882. package/package.json +411 -0
  883. package/src/backend/AppShell.tsx +1606 -0
  884. package/src/backend/BackendChromeProvider.tsx +99 -0
  885. package/src/backend/BackendPageSurface.tsx +57 -0
  886. package/src/backend/CollapsibleNavSection.tsx +201 -0
  887. package/src/backend/ContextHelp.tsx +40 -0
  888. package/src/backend/CrudForm.tsx +3796 -0
  889. package/src/backend/DataTable.tsx +2584 -0
  890. package/src/backend/EmptyState.tsx +65 -0
  891. package/src/backend/FilterBar.tsx +171 -0
  892. package/src/backend/FilterOverlay.tsx +388 -0
  893. package/src/backend/FlashMessages.tsx +189 -0
  894. package/src/backend/HtmlRichTextEditor.tsx +124 -0
  895. package/src/backend/IntegrationsButton.tsx +29 -0
  896. package/src/backend/JsonBuilder.tsx +359 -0
  897. package/src/backend/JsonDisplay.tsx +258 -0
  898. package/src/backend/NextStepCallout.tsx +134 -0
  899. package/src/backend/Page.tsx +30 -0
  900. package/src/backend/PerspectiveSidebar.tsx +506 -0
  901. package/src/backend/ProfileDropdown.tsx +369 -0
  902. package/src/backend/RowActions.tsx +158 -0
  903. package/src/backend/SectionHeader.tsx +119 -0
  904. package/src/backend/SettingsButton.tsx +28 -0
  905. package/src/backend/Sidebar.stories.tsx +183 -0
  906. package/src/backend/Sidebar.tsx +737 -0
  907. package/src/backend/TruncatedCell.tsx +133 -0
  908. package/src/backend/UserMenu.tsx +153 -0
  909. package/src/backend/ValueIcons.tsx +48 -0
  910. package/src/backend/WebhookSetupGuide.tsx +127 -0
  911. package/src/backend/__tests__/AppShell.test.tsx +392 -0
  912. package/src/backend/__tests__/CrudForm.custom-fields.test.tsx +180 -0
  913. package/src/backend/__tests__/CrudForm.datetime.test.tsx +95 -0
  914. package/src/backend/__tests__/CrudForm.defaults.test.tsx +195 -0
  915. package/src/backend/__tests__/CrudForm.navigation.test.tsx +156 -0
  916. package/src/backend/__tests__/CrudForm.render.test.tsx +146 -0
  917. package/src/backend/__tests__/CrudForm.transformData.test.tsx +231 -0
  918. package/src/backend/__tests__/CrudForm.unsavedNavigation.test.tsx +145 -0
  919. package/src/backend/__tests__/CrudForm.validation.test.tsx +178 -0
  920. package/src/backend/__tests__/CustomDataSection.test.tsx +465 -0
  921. package/src/backend/__tests__/DataTable.extensions.test.tsx +339 -0
  922. package/src/backend/__tests__/DataTable.namespaces.test.ts +32 -0
  923. package/src/backend/__tests__/DataTable.render.test.tsx +48 -0
  924. package/src/backend/__tests__/FieldDefinitionsEditor.test.tsx +64 -0
  925. package/src/backend/__tests__/FlashMessages.test.tsx +105 -0
  926. package/src/backend/__tests__/FormHeader.test.tsx +81 -0
  927. package/src/backend/__tests__/NotificationDispatcher.test.ts +172 -0
  928. package/src/backend/__tests__/VersionHistoryPanel.test.tsx +109 -0
  929. package/src/backend/__tests__/component-replacement.test.tsx +270 -0
  930. package/src/backend/__tests__/custom-field-filters.test.ts +72 -0
  931. package/src/backend/__tests__/custom-field-forms.test.ts +54 -0
  932. package/src/backend/__tests__/nav-utils.test.ts +175 -0
  933. package/src/backend/__tests__/serverErrors.test.ts +83 -0
  934. package/src/backend/__tests__/useAuditPermissions.test.tsx +51 -0
  935. package/src/backend/__tests__/useNotifications.strategy.test.ts +58 -0
  936. package/src/backend/__tests__/useProgress.strategy.test.ts +62 -0
  937. package/src/backend/charts/BarChart.tsx +208 -0
  938. package/src/backend/charts/ChartUtils.tsx +196 -0
  939. package/src/backend/charts/ComboChart.stories.tsx +103 -0
  940. package/src/backend/charts/ComboChart.tsx +350 -0
  941. package/src/backend/charts/KpiCard.tsx +155 -0
  942. package/src/backend/charts/LineChart.tsx +207 -0
  943. package/src/backend/charts/PieChart.tsx +157 -0
  944. package/src/backend/charts/ScatterChart.tsx +498 -0
  945. package/src/backend/charts/TopNTable.tsx +141 -0
  946. package/src/backend/charts/WaterfallChart.tsx +213 -0
  947. package/src/backend/charts/index.ts +21 -0
  948. package/src/backend/columns/ColumnChooserPanel.tsx +293 -0
  949. package/src/backend/confirm-dialog/ConfirmDialog.tsx +275 -0
  950. package/src/backend/confirm-dialog/index.ts +7 -0
  951. package/src/backend/confirm-dialog/useConfirmDialog.tsx +146 -0
  952. package/src/backend/custom-fields/FieldDefinitionsEditor.tsx +1413 -0
  953. package/src/backend/custom-fields/FieldDefinitionsManager.tsx +381 -0
  954. package/src/backend/dashboard/DashboardScreen.tsx +706 -0
  955. package/src/backend/dashboard/__tests__/DashboardScreen.test.tsx +114 -0
  956. package/src/backend/dashboard/index.ts +1 -0
  957. package/src/backend/dashboard/widgetRegistry.ts +68 -0
  958. package/src/backend/date-range/DateRangeSelect.tsx +50 -0
  959. package/src/backend/date-range/InlineDateRangeSelect.tsx +52 -0
  960. package/src/backend/date-range/InlineGranularitySelect.tsx +63 -0
  961. package/src/backend/date-range/__tests__/dateRanges.test.ts +224 -0
  962. package/src/backend/date-range/dateRanges.ts +218 -0
  963. package/src/backend/date-range/index.ts +15 -0
  964. package/src/backend/detail/AccessDeniedMessage.tsx +32 -0
  965. package/src/backend/detail/ActivitiesSection.tsx +1261 -0
  966. package/src/backend/detail/AddressEditor.tsx +479 -0
  967. package/src/backend/detail/AddressTiles.tsx +591 -0
  968. package/src/backend/detail/AddressesSection.tsx +362 -0
  969. package/src/backend/detail/AttachmentDeleteDialog.tsx +56 -0
  970. package/src/backend/detail/AttachmentMetadataDialog.tsx +674 -0
  971. package/src/backend/detail/AttachmentVisualPreview.tsx +155 -0
  972. package/src/backend/detail/AttachmentsSection.tsx +327 -0
  973. package/src/backend/detail/CustomDataSection.tsx +700 -0
  974. package/src/backend/detail/DetailFieldsSection.tsx +163 -0
  975. package/src/backend/detail/ErrorMessage.tsx +32 -0
  976. package/src/backend/detail/InlineEditors.tsx +894 -0
  977. package/src/backend/detail/LoadingMessage.tsx +14 -0
  978. package/src/backend/detail/NotesSection.tsx +1266 -0
  979. package/src/backend/detail/TabEmptyState.tsx +48 -0
  980. package/src/backend/detail/TagsSection.tsx +470 -0
  981. package/src/backend/detail/__tests__/InlineEditors.test.tsx +59 -0
  982. package/src/backend/detail/addressFormat.tsx +121 -0
  983. package/src/backend/detail/index.ts +46 -0
  984. package/src/backend/devtools/UmesDevToolsPanel.tsx +122 -0
  985. package/src/backend/devtools/components/ConflictWarnings.tsx +36 -0
  986. package/src/backend/devtools/components/EnricherTiming.tsx +50 -0
  987. package/src/backend/devtools/components/EventFlow.tsx +45 -0
  988. package/src/backend/devtools/components/ExtensionPointList.tsx +59 -0
  989. package/src/backend/devtools/components/InterceptorActivity.tsx +48 -0
  990. package/src/backend/devtools/index.ts +2 -0
  991. package/src/backend/devtools/useUmesDevTools.ts +188 -0
  992. package/src/backend/document-viewer/RegionOverlay.tsx +150 -0
  993. package/src/backend/document-viewer/index.ts +2 -0
  994. package/src/backend/dynamic-grid/DynamicGrid.tsx +161 -0
  995. package/src/backend/dynamic-grid/adapters.ts +57 -0
  996. package/src/backend/dynamic-grid/components/GridCell.tsx +194 -0
  997. package/src/backend/dynamic-grid/components/GridRow.tsx +40 -0
  998. package/src/backend/dynamic-grid/hooks/useGridKeyboardNav.ts +134 -0
  999. package/src/backend/dynamic-grid/index.ts +4 -0
  1000. package/src/backend/dynamic-grid/types.ts +55 -0
  1001. package/src/backend/dynamic-table/DynamicTable.stories.tsx +274 -0
  1002. package/src/backend/dynamic-table/DynamicTable.tsx +4419 -0
  1003. package/src/backend/dynamic-table/README.md +1199 -0
  1004. package/src/backend/dynamic-table/URL_FILTERING.md +217 -0
  1005. package/src/backend/dynamic-table/__e2e__/GridHarness.ts +1155 -0
  1006. package/src/backend/dynamic-table/__e2e__/SplitViewHarness.ts +366 -0
  1007. package/src/backend/dynamic-table/__tests__/BulkActionsBar.test.tsx +143 -0
  1008. package/src/backend/dynamic-table/__tests__/ColumnQuickFilter.test.tsx +607 -0
  1009. package/src/backend/dynamic-table/__tests__/ConfigureViewFilters.suggestions.test.tsx +177 -0
  1010. package/src/backend/dynamic-table/__tests__/ConfigureViewFormatting.test.tsx +125 -0
  1011. package/src/backend/dynamic-table/__tests__/ConfigureViewFormulas.test.tsx +228 -0
  1012. package/src/backend/dynamic-table/__tests__/ConfigureViewGrouping.aggregations.test.tsx +131 -0
  1013. package/src/backend/dynamic-table/__tests__/ConfigureViewPanel.baseView.test.tsx +162 -0
  1014. package/src/backend/dynamic-table/__tests__/ConfigureViewPanel.focus.test.tsx +54 -0
  1015. package/src/backend/dynamic-table/__tests__/ConfigureViewPanel.sections.test.tsx +142 -0
  1016. package/src/backend/dynamic-table/__tests__/ConfigureViewRollups.test.tsx +228 -0
  1017. package/src/backend/dynamic-table/__tests__/ContextMenu.test.tsx +89 -0
  1018. package/src/backend/dynamic-table/__tests__/DynamicTable.density.test.tsx +299 -0
  1019. package/src/backend/dynamic-table/__tests__/DynamicTable.exportTruncation.test.tsx +145 -0
  1020. package/src/backend/dynamic-table/__tests__/DynamicTable.loadError.test.tsx +173 -0
  1021. package/src/backend/dynamic-table/__tests__/DynamicTable.wiring.test.tsx +357 -0
  1022. package/src/backend/dynamic-table/__tests__/EmptyState.test.tsx +70 -0
  1023. package/src/backend/dynamic-table/__tests__/ExportMenu.test.tsx +82 -0
  1024. package/src/backend/dynamic-table/__tests__/FooterTotalsRow.test.tsx +154 -0
  1025. package/src/backend/dynamic-table/__tests__/GroupSummaryRow.render.test.tsx +131 -0
  1026. package/src/backend/dynamic-table/__tests__/LoadErrorState.test.tsx +74 -0
  1027. package/src/backend/dynamic-table/__tests__/MentionPopup.search.test.tsx +127 -0
  1028. package/src/backend/dynamic-table/__tests__/PerspectiveTabs.test.tsx +170 -0
  1029. package/src/backend/dynamic-table/__tests__/RowHeaderCell.selection.test.tsx +80 -0
  1030. package/src/backend/dynamic-table/__tests__/abbreviationsSubscription.test.ts +171 -0
  1031. package/src/backend/dynamic-table/__tests__/aggregate.spec.test.ts +224 -0
  1032. package/src/backend/dynamic-table/__tests__/aggregateDimension.test.tsx +191 -0
  1033. package/src/backend/dynamic-table/__tests__/anchoredPosition.test.ts +88 -0
  1034. package/src/backend/dynamic-table/__tests__/badgeAutoFit.test.ts +121 -0
  1035. package/src/backend/dynamic-table/__tests__/cellHandlers.save.test.ts +282 -0
  1036. package/src/backend/dynamic-table/__tests__/cellWrites.test.ts +274 -0
  1037. package/src/backend/dynamic-table/__tests__/clipboard.test.ts +230 -0
  1038. package/src/backend/dynamic-table/__tests__/coerceCellValue.test.ts +117 -0
  1039. package/src/backend/dynamic-table/__tests__/colorAdjacency.test.ts +151 -0
  1040. package/src/backend/dynamic-table/__tests__/columnFill.test.ts +66 -0
  1041. package/src/backend/dynamic-table/__tests__/columnHeaderHandlers.sort.test.ts +100 -0
  1042. package/src/backend/dynamic-table/__tests__/columnHeaderReorder.test.tsx +209 -0
  1043. package/src/backend/dynamic-table/__tests__/columnReorderPersistence.test.tsx +127 -0
  1044. package/src/backend/dynamic-table/__tests__/columnVirtualization.render.test.tsx +420 -0
  1045. package/src/backend/dynamic-table/__tests__/columnVisibilityPersistence.test.tsx +136 -0
  1046. package/src/backend/dynamic-table/__tests__/columnWindow.test.ts +643 -0
  1047. package/src/backend/dynamic-table/__tests__/commentAudience.test.tsx +137 -0
  1048. package/src/backend/dynamic-table/__tests__/commentScope.test.tsx +214 -0
  1049. package/src/backend/dynamic-table/__tests__/conditionalFormat.test.ts +175 -0
  1050. package/src/backend/dynamic-table/__tests__/contentRegistry.test.ts +267 -0
  1051. package/src/backend/dynamic-table/__tests__/dateWindows.test.ts +149 -0
  1052. package/src/backend/dynamic-table/__tests__/density.test.ts +204 -0
  1053. package/src/backend/dynamic-table/__tests__/exportTable.test.ts +146 -0
  1054. package/src/backend/dynamic-table/__tests__/fillGeometry.test.ts +201 -0
  1055. package/src/backend/dynamic-table/__tests__/fillPatterns.test.ts +272 -0
  1056. package/src/backend/dynamic-table/__tests__/filterParser.presets.test.ts +64 -0
  1057. package/src/backend/dynamic-table/__tests__/filterParser.relative.test.ts +109 -0
  1058. package/src/backend/dynamic-table/__tests__/filterSuggestions.test.ts +152 -0
  1059. package/src/backend/dynamic-table/__tests__/formatAggregate.test.ts +99 -0
  1060. package/src/backend/dynamic-table/__tests__/formatDateCompact.test.ts +489 -0
  1061. package/src/backend/dynamic-table/__tests__/formatLabelCompact.test.ts +717 -0
  1062. package/src/backend/dynamic-table/__tests__/formula.check.test.ts +257 -0
  1063. package/src/backend/dynamic-table/__tests__/formula.evaluate.test.ts +274 -0
  1064. package/src/backend/dynamic-table/__tests__/formula.functions.test.ts +226 -0
  1065. package/src/backend/dynamic-table/__tests__/formula.noEval.test.ts +92 -0
  1066. package/src/backend/dynamic-table/__tests__/formula.parse.test.ts +233 -0
  1067. package/src/backend/dynamic-table/__tests__/formulaColumns.test.tsx +213 -0
  1068. package/src/backend/dynamic-table/__tests__/handlerIdentity.test.ts +77 -0
  1069. package/src/backend/dynamic-table/__tests__/importMapping.test.ts +174 -0
  1070. package/src/backend/dynamic-table/__tests__/importParse.test.ts +130 -0
  1071. package/src/backend/dynamic-table/__tests__/importServerOnly.test.ts +37 -0
  1072. package/src/backend/dynamic-table/__tests__/layoutPersistence.test.ts +372 -0
  1073. package/src/backend/dynamic-table/__tests__/mouseHandlers.doubleClick.test.ts +155 -0
  1074. package/src/backend/dynamic-table/__tests__/perspectivePersonalization.test.ts +188 -0
  1075. package/src/backend/dynamic-table/__tests__/perspectiveResolver.test.ts +133 -0
  1076. package/src/backend/dynamic-table/__tests__/perspectiveState.defaultGrouping.test.ts +306 -0
  1077. package/src/backend/dynamic-table/__tests__/perspectiveState.defaults.test.ts +107 -0
  1078. package/src/backend/dynamic-table/__tests__/perspectiveTemplates.test.tsx +269 -0
  1079. package/src/backend/dynamic-table/__tests__/perspectiveTransforms.aggregations.test.ts +105 -0
  1080. package/src/backend/dynamic-table/__tests__/perspectiveTransforms.conditionalFormats.test.ts +107 -0
  1081. package/src/backend/dynamic-table/__tests__/perspectiveTransforms.dateFormat.test.ts +61 -0
  1082. package/src/backend/dynamic-table/__tests__/perspectiveTransforms.formulas.test.ts +85 -0
  1083. package/src/backend/dynamic-table/__tests__/perspectiveTransforms.frozenColumns.test.ts +124 -0
  1084. package/src/backend/dynamic-table/__tests__/rollupColumns.test.ts +149 -0
  1085. package/src/backend/dynamic-table/__tests__/sharedCriteria.test.ts +255 -0
  1086. package/src/backend/dynamic-table/__tests__/splitViewTree.test.ts +324 -0
  1087. package/src/backend/dynamic-table/__tests__/store.clipboardMarker.test.ts +143 -0
  1088. package/src/backend/dynamic-table/__tests__/store.fillPreview.test.ts +168 -0
  1089. package/src/backend/dynamic-table/__tests__/store.mutations.test.ts +345 -0
  1090. package/src/backend/dynamic-table/__tests__/store.selection.test.ts +157 -0
  1091. package/src/backend/dynamic-table/__tests__/store.undo.test.ts +225 -0
  1092. package/src/backend/dynamic-table/__tests__/store.valueSource.test.tsx +204 -0
  1093. package/src/backend/dynamic-table/__tests__/useAnnotations.legacyOptions.test.tsx +58 -0
  1094. package/src/backend/dynamic-table/__tests__/useColumnVirtualizer.test.ts +290 -0
  1095. package/src/backend/dynamic-table/__tests__/useDensityPreference.test.ts +435 -0
  1096. package/src/backend/dynamic-table/__tests__/useDynamicTablePage.duplicate.test.tsx +99 -0
  1097. package/src/backend/dynamic-table/__tests__/useDynamicTablePage.export.test.tsx +281 -0
  1098. package/src/backend/dynamic-table/__tests__/useDynamicTablePage.personalization.test.tsx +313 -0
  1099. package/src/backend/dynamic-table/__tests__/useDynamicTablePage.perspectiveRestore.test.tsx +126 -0
  1100. package/src/backend/dynamic-table/__tests__/useGrouping.aggregations.test.ts +158 -0
  1101. package/src/backend/dynamic-table/__tests__/useGrouping.groupKey.test.ts +58 -0
  1102. package/src/backend/dynamic-table/__tests__/useKeyboardNavigation.test.ts +594 -0
  1103. package/src/backend/dynamic-table/__tests__/useStickyOffsets.memo.test.tsx +75 -0
  1104. package/src/backend/dynamic-table/__tests__/useStickyOffsets.test.ts +106 -0
  1105. package/src/backend/dynamic-table/__tests__/widgetPane.test.tsx +338 -0
  1106. package/src/backend/dynamic-table/components/ActiveFilterChips.tsx +109 -0
  1107. package/src/backend/dynamic-table/components/BulkActionsBar.tsx +89 -0
  1108. package/src/backend/dynamic-table/components/Cell.tsx +292 -0
  1109. package/src/backend/dynamic-table/components/CellCommentDialog.tsx +887 -0
  1110. package/src/backend/dynamic-table/components/CellCommentHoverPopup.tsx +94 -0
  1111. package/src/backend/dynamic-table/components/ColumnFilterPopover.tsx +775 -0
  1112. package/src/backend/dynamic-table/components/ColumnHeaderMenu.tsx +189 -0
  1113. package/src/backend/dynamic-table/components/ColumnHeaders.tsx +867 -0
  1114. package/src/backend/dynamic-table/components/CompactLabelCell.tsx +293 -0
  1115. package/src/backend/dynamic-table/components/ConfigureViewFields.tsx +173 -0
  1116. package/src/backend/dynamic-table/components/ConfigureViewFilters.tsx +346 -0
  1117. package/src/backend/dynamic-table/components/ConfigureViewFormatting.tsx +205 -0
  1118. package/src/backend/dynamic-table/components/ConfigureViewFormulas.tsx +423 -0
  1119. package/src/backend/dynamic-table/components/ConfigureViewGrouping.tsx +264 -0
  1120. package/src/backend/dynamic-table/components/ConfigureViewLinkedColumns.tsx +249 -0
  1121. package/src/backend/dynamic-table/components/ConfigureViewPanel.tsx +857 -0
  1122. package/src/backend/dynamic-table/components/ConfigureViewRollups.tsx +364 -0
  1123. package/src/backend/dynamic-table/components/ConfigureViewSorting.tsx +121 -0
  1124. package/src/backend/dynamic-table/components/ContextMenu.tsx +140 -0
  1125. package/src/backend/dynamic-table/components/DateCell.tsx +205 -0
  1126. package/src/backend/dynamic-table/components/Debugger.tsx +340 -0
  1127. package/src/backend/dynamic-table/components/DensityControl.tsx +441 -0
  1128. package/src/backend/dynamic-table/components/EmptyState.tsx +103 -0
  1129. package/src/backend/dynamic-table/components/EntitySearchEditor.tsx +528 -0
  1130. package/src/backend/dynamic-table/components/ExportMenu.tsx +90 -0
  1131. package/src/backend/dynamic-table/components/FilterDatePicker.tsx +194 -0
  1132. package/src/backend/dynamic-table/components/FilterValueInput.tsx +294 -0
  1133. package/src/backend/dynamic-table/components/FooterTotalsRow.tsx +291 -0
  1134. package/src/backend/dynamic-table/components/FullscreenOverlay.tsx +66 -0
  1135. package/src/backend/dynamic-table/components/GroupHeaderRow.tsx +136 -0
  1136. package/src/backend/dynamic-table/components/GroupSummaryRow.tsx +184 -0
  1137. package/src/backend/dynamic-table/components/ImportPanel.tsx +445 -0
  1138. package/src/backend/dynamic-table/components/ImportPreviewGrid.tsx +155 -0
  1139. package/src/backend/dynamic-table/components/LoadErrorState.tsx +70 -0
  1140. package/src/backend/dynamic-table/components/MentionPopup.tsx +224 -0
  1141. package/src/backend/dynamic-table/components/PerspectiveDeleteDialog.tsx +96 -0
  1142. package/src/backend/dynamic-table/components/PerspectivePublishDialog.tsx +152 -0
  1143. package/src/backend/dynamic-table/components/PerspectiveTabMenu.tsx +215 -0
  1144. package/src/backend/dynamic-table/components/PerspectiveTabs.tsx +426 -0
  1145. package/src/backend/dynamic-table/components/PerspectiveTemplateMenu.tsx +135 -0
  1146. package/src/backend/dynamic-table/components/RowHeaderCell.tsx +73 -0
  1147. package/src/backend/dynamic-table/components/SearchBar.tsx +309 -0
  1148. package/src/backend/dynamic-table/components/SelectMenu.tsx +237 -0
  1149. package/src/backend/dynamic-table/components/StaleDataBar.tsx +74 -0
  1150. package/src/backend/dynamic-table/components/TableDeleteDialog.tsx +74 -0
  1151. package/src/backend/dynamic-table/components/TablePagination.tsx +96 -0
  1152. package/src/backend/dynamic-table/components/TableSkeleton.tsx +123 -0
  1153. package/src/backend/dynamic-table/components/ToolbarOverflow.tsx +284 -0
  1154. package/src/backend/dynamic-table/components/ViewModeSwitch.tsx +92 -0
  1155. package/src/backend/dynamic-table/components/VirtualRow.tsx +346 -0
  1156. package/src/backend/dynamic-table/components/editors.tsx +1727 -0
  1157. package/src/backend/dynamic-table/components/renderers.tsx +162 -0
  1158. package/src/backend/dynamic-table/events/events.ts +107 -0
  1159. package/src/backend/dynamic-table/formula/check.ts +359 -0
  1160. package/src/backend/dynamic-table/formula/evaluate.ts +473 -0
  1161. package/src/backend/dynamic-table/formula/functions.ts +737 -0
  1162. package/src/backend/dynamic-table/formula/index.ts +57 -0
  1163. package/src/backend/dynamic-table/formula/parse.ts +414 -0
  1164. package/src/backend/dynamic-table/formula/types.ts +151 -0
  1165. package/src/backend/dynamic-table/handlers/cellWrites.ts +362 -0
  1166. package/src/backend/dynamic-table/handlers/index.ts +789 -0
  1167. package/src/backend/dynamic-table/handlers/perspectiveHandlers.ts +684 -0
  1168. package/src/backend/dynamic-table/hooks/index.ts +888 -0
  1169. package/src/backend/dynamic-table/hooks/useAbbreviations.ts +67 -0
  1170. package/src/backend/dynamic-table/hooks/useAnnotations.ts +215 -0
  1171. package/src/backend/dynamic-table/hooks/useColumnVirtualizer.ts +303 -0
  1172. package/src/backend/dynamic-table/hooks/useColumnWidthPersistence.ts +214 -0
  1173. package/src/backend/dynamic-table/hooks/useDensityPreference.ts +451 -0
  1174. package/src/backend/dynamic-table/hooks/useDynamicTablePage.tsx +1681 -0
  1175. package/src/backend/dynamic-table/hooks/useEscapeLayer.ts +72 -0
  1176. package/src/backend/dynamic-table/hooks/useGrouping.ts +428 -0
  1177. package/src/backend/dynamic-table/hooks/useSuggestionFetch.ts +109 -0
  1178. package/src/backend/dynamic-table/hooks/useTableDateFormat.tsx +19 -0
  1179. package/src/backend/dynamic-table/index.ts +497 -0
  1180. package/src/backend/dynamic-table/registry/ContentRegistryContext.tsx +244 -0
  1181. package/src/backend/dynamic-table/registry/TableRegistryContext.tsx +84 -0
  1182. package/src/backend/dynamic-table/registry/filterAccessibleTables.ts +36 -0
  1183. package/src/backend/dynamic-table/registry/index.ts +38 -0
  1184. package/src/backend/dynamic-table/registry/lazyTable.tsx +80 -0
  1185. package/src/backend/dynamic-table/registry/types.ts +181 -0
  1186. package/src/backend/dynamic-table/registry/widgetCatalog.ts +226 -0
  1187. package/src/backend/dynamic-table/server/aggregate.ts +474 -0
  1188. package/src/backend/dynamic-table/server/dateWindows.ts +201 -0
  1189. package/src/backend/dynamic-table/server/filterParser.ts +132 -0
  1190. package/src/backend/dynamic-table/server/filterSuggestions.ts +150 -0
  1191. package/src/backend/dynamic-table/server/index.ts +47 -0
  1192. package/src/backend/dynamic-table/server/makeDynamicTableRoute.ts +426 -0
  1193. package/src/backend/dynamic-table/split-view/ContentPicker.tsx +251 -0
  1194. package/src/backend/dynamic-table/split-view/EmptySlot.tsx +69 -0
  1195. package/src/backend/dynamic-table/split-view/SplitViewHost.tsx +1336 -0
  1196. package/src/backend/dynamic-table/split-view/WidgetPane.tsx +390 -0
  1197. package/src/backend/dynamic-table/split-view/WorkspaceFilterBar.tsx +728 -0
  1198. package/src/backend/dynamic-table/split-view/index.ts +48 -0
  1199. package/src/backend/dynamic-table/split-view/layoutPersistence.ts +185 -0
  1200. package/src/backend/dynamic-table/split-view/sharedCriteria.ts +196 -0
  1201. package/src/backend/dynamic-table/split-view/types.ts +778 -0
  1202. package/src/backend/dynamic-table/split-view/useSplitViewLayouts.ts +97 -0
  1203. package/src/backend/dynamic-table/store/index.ts +1011 -0
  1204. package/src/backend/dynamic-table/styles/ContextMenu.css +387 -0
  1205. package/src/backend/dynamic-table/styles/DynamicTable.css +3659 -0
  1206. package/src/backend/dynamic-table/styles/DynamicTable.v2.css +2651 -0
  1207. package/src/backend/dynamic-table/styles/SearchBar.css +426 -0
  1208. package/src/backend/dynamic-table/styles/dateCell.css +146 -0
  1209. package/src/backend/dynamic-table/styles/density.css +690 -0
  1210. package/src/backend/dynamic-table/types/density.ts +179 -0
  1211. package/src/backend/dynamic-table/types/filters.ts +156 -0
  1212. package/src/backend/dynamic-table/types/grouping.ts +189 -0
  1213. package/src/backend/dynamic-table/types/import.ts +132 -0
  1214. package/src/backend/dynamic-table/types/index.ts +1198 -0
  1215. package/src/backend/dynamic-table/types/perspective.ts +436 -0
  1216. package/src/backend/dynamic-table/types/rollup.ts +111 -0
  1217. package/src/backend/dynamic-table/utils/abbreviations.ts +556 -0
  1218. package/src/backend/dynamic-table/utils/anchoredPosition.ts +106 -0
  1219. package/src/backend/dynamic-table/utils/badgeAutoFit.ts +108 -0
  1220. package/src/backend/dynamic-table/utils/clipboard.ts +294 -0
  1221. package/src/backend/dynamic-table/utils/coerceCellValue.ts +96 -0
  1222. package/src/backend/dynamic-table/utils/colorAdjacency.ts +87 -0
  1223. package/src/backend/dynamic-table/utils/columnFill.ts +93 -0
  1224. package/src/backend/dynamic-table/utils/columnSpacerStyle.ts +53 -0
  1225. package/src/backend/dynamic-table/utils/columnWindow.ts +668 -0
  1226. package/src/backend/dynamic-table/utils/conditionalFormat.ts +300 -0
  1227. package/src/backend/dynamic-table/utils/exportTable.ts +140 -0
  1228. package/src/backend/dynamic-table/utils/fillGeometry.ts +187 -0
  1229. package/src/backend/dynamic-table/utils/fillPatterns.ts +422 -0
  1230. package/src/backend/dynamic-table/utils/formatAggregate.ts +145 -0
  1231. package/src/backend/dynamic-table/utils/formatDateCompact.ts +879 -0
  1232. package/src/backend/dynamic-table/utils/formatLabelCompact.ts +640 -0
  1233. package/src/backend/dynamic-table/utils/formulaColumns.tsx +237 -0
  1234. package/src/backend/dynamic-table/utils/importMapping.ts +202 -0
  1235. package/src/backend/dynamic-table/utils/importParse.ts +220 -0
  1236. package/src/backend/dynamic-table/utils/lookupColumns.tsx +47 -0
  1237. package/src/backend/dynamic-table/utils/perspectiveTransforms.ts +368 -0
  1238. package/src/backend/dynamic-table/utils/rollupColumns.ts +162 -0
  1239. package/src/backend/dynamic-table/validators/index.ts +40 -0
  1240. package/src/backend/fields/registry.generated.ts +8 -0
  1241. package/src/backend/fields/registry.ts +38 -0
  1242. package/src/backend/filters/AdvancedFilterBuilder.tsx +339 -0
  1243. package/src/backend/forms/ActionsDropdown.tsx +198 -0
  1244. package/src/backend/forms/FormActionButtons.tsx +98 -0
  1245. package/src/backend/forms/FormFooter.tsx +27 -0
  1246. package/src/backend/forms/FormHeader.tsx +204 -0
  1247. package/src/backend/forms/index.ts +4 -0
  1248. package/src/backend/hooks/useAdvancedFilter.ts +77 -0
  1249. package/src/backend/indexes/PartialIndexBanner.tsx +86 -0
  1250. package/src/backend/indexes/store.ts +88 -0
  1251. package/src/backend/injection/ComponentOverrideProvider.tsx +66 -0
  1252. package/src/backend/injection/InjectedField.tsx +196 -0
  1253. package/src/backend/injection/InjectionSpot.tsx +457 -0
  1254. package/src/backend/injection/InjectionWizard.tsx +335 -0
  1255. package/src/backend/injection/PageInjectionBoundary.tsx +31 -0
  1256. package/src/backend/injection/SseEventIndicator.tsx +11 -0
  1257. package/src/backend/injection/StatusBadgeInjectionSpot.tsx +50 -0
  1258. package/src/backend/injection/StatusBadgeRenderer.tsx +100 -0
  1259. package/src/backend/injection/WidgetSharedState.ts +58 -0
  1260. package/src/backend/injection/WizardInjectionSpot.tsx +46 -0
  1261. package/src/backend/injection/eventBridge.ts +158 -0
  1262. package/src/backend/injection/helpers.ts +35 -0
  1263. package/src/backend/injection/mergeMenuItems.ts +80 -0
  1264. package/src/backend/injection/mutationEvents.ts +22 -0
  1265. package/src/backend/injection/resolveInjectedIcon.tsx +30 -0
  1266. package/src/backend/injection/spotIds.ts +64 -0
  1267. package/src/backend/injection/useAppEvent.ts +76 -0
  1268. package/src/backend/injection/useGuardedMutation.ts +101 -0
  1269. package/src/backend/injection/useInjectedMenuItems.ts +67 -0
  1270. package/src/backend/injection/useInjectionDataWidgets.ts +41 -0
  1271. package/src/backend/injection/useOperationProgress.ts +105 -0
  1272. package/src/backend/injection/useRegisteredComponent.tsx +106 -0
  1273. package/src/backend/injection/useWidgetSharedState.ts +28 -0
  1274. package/src/backend/injection/visibility-utils.ts +31 -0
  1275. package/src/backend/injection/widgetRegistry.ts +68 -0
  1276. package/src/backend/inputs/ComboboxInput.tsx +272 -0
  1277. package/src/backend/inputs/DatePicker.tsx +162 -0
  1278. package/src/backend/inputs/DateTimePicker.tsx +199 -0
  1279. package/src/backend/inputs/EventPatternInput.tsx +46 -0
  1280. package/src/backend/inputs/EventSelect.tsx +183 -0
  1281. package/src/backend/inputs/LookupSelect.tsx +253 -0
  1282. package/src/backend/inputs/PhoneNumberField.tsx +166 -0
  1283. package/src/backend/inputs/SwitchableMarkdownInput.tsx +106 -0
  1284. package/src/backend/inputs/TagsInput.tsx +297 -0
  1285. package/src/backend/inputs/TimeInput.tsx +146 -0
  1286. package/src/backend/inputs/TimePicker.tsx +120 -0
  1287. package/src/backend/inputs/__tests__/DatePicker.test.tsx +76 -0
  1288. package/src/backend/inputs/__tests__/DateTimePicker.logic.test.ts +126 -0
  1289. package/src/backend/inputs/__tests__/PhoneNumberField.test.tsx +73 -0
  1290. package/src/backend/inputs/__tests__/TagsInput.test.tsx +78 -0
  1291. package/src/backend/inputs/__tests__/TimeInput.test.tsx +134 -0
  1292. package/src/backend/inputs/__tests__/TimePicker.test.tsx +50 -0
  1293. package/src/backend/inputs/index.ts +11 -0
  1294. package/src/backend/markdown/MarkdownContent.tsx +33 -0
  1295. package/src/backend/markdown/index.ts +2 -0
  1296. package/src/backend/markdown/useMarkdownRemarkPlugins.ts +39 -0
  1297. package/src/backend/messages/MessageComposer.tsx +197 -0
  1298. package/src/backend/messages/MessageObjectDetail.tsx +95 -0
  1299. package/src/backend/messages/MessageObjectPreview.tsx +64 -0
  1300. package/src/backend/messages/MessageObjectRecordPicker.tsx +149 -0
  1301. package/src/backend/messages/MessagePrioritySelector.tsx +78 -0
  1302. package/src/backend/messages/MessagesIcon.tsx +32 -0
  1303. package/src/backend/messages/SendObjectMessageDialog.tsx +74 -0
  1304. package/src/backend/messages/__tests__/MessageComposer.test.tsx +350 -0
  1305. package/src/backend/messages/__tests__/SendObjectMessageDialog.test.tsx +77 -0
  1306. package/src/backend/messages/index.ts +22 -0
  1307. package/src/backend/messages/message-compose-form-groups.tsx +383 -0
  1308. package/src/backend/messages/message-composer.types.ts +82 -0
  1309. package/src/backend/messages/message-priority.ts +53 -0
  1310. package/src/backend/messages/useMessageCompose.ts +666 -0
  1311. package/src/backend/messages/useMessageComposeOperations.ts +259 -0
  1312. package/src/backend/messages/useMessagesPoll.ts +118 -0
  1313. package/src/backend/notifications/NotificationBell.tsx +91 -0
  1314. package/src/backend/notifications/NotificationCountBadge.tsx +14 -0
  1315. package/src/backend/notifications/NotificationDispatcher.ts +213 -0
  1316. package/src/backend/notifications/NotificationItem.tsx +262 -0
  1317. package/src/backend/notifications/NotificationPanel.tsx +225 -0
  1318. package/src/backend/notifications/__tests__/NotificationCountBadge.test.tsx +34 -0
  1319. package/src/backend/notifications/index.ts +20 -0
  1320. package/src/backend/notifications/useNotificationActions.ts +161 -0
  1321. package/src/backend/notifications/useNotificationEffect.ts +17 -0
  1322. package/src/backend/notifications/useNotifications.ts +12 -0
  1323. package/src/backend/notifications/useNotificationsPoll.ts +167 -0
  1324. package/src/backend/notifications/useNotificationsSse.ts +220 -0
  1325. package/src/backend/operations/LastOperationBanner.tsx +85 -0
  1326. package/src/backend/operations/__tests__/LastOperationBanner.test.tsx +101 -0
  1327. package/src/backend/operations/store.ts +230 -0
  1328. package/src/backend/progress/ProgressTopBar.tsx +189 -0
  1329. package/src/backend/progress/useProgress.ts +12 -0
  1330. package/src/backend/progress/useProgressPoll.ts +100 -0
  1331. package/src/backend/progress/useProgressSse.ts +118 -0
  1332. package/src/backend/schedule/ScheduleAgenda.tsx +136 -0
  1333. package/src/backend/schedule/ScheduleGrid.tsx +136 -0
  1334. package/src/backend/schedule/ScheduleToolbar.tsx +178 -0
  1335. package/src/backend/schedule/ScheduleView.tsx +201 -0
  1336. package/src/backend/schedule/index.ts +5 -0
  1337. package/src/backend/schedule/recurrence.ts +99 -0
  1338. package/src/backend/schedule/types.ts +26 -0
  1339. package/src/backend/section-page/SectionNav.tsx +140 -0
  1340. package/src/backend/section-page/SectionPage.tsx +34 -0
  1341. package/src/backend/section-page/index.ts +3 -0
  1342. package/src/backend/section-page/types.ts +30 -0
  1343. package/src/backend/settings/SettingsNavigation.tsx +74 -0
  1344. package/src/backend/settings/SettingsPageWrapper.tsx +78 -0
  1345. package/src/backend/settings/index.ts +3 -0
  1346. package/src/backend/upgrades/UpgradeActionBanner.tsx +128 -0
  1347. package/src/backend/utils/__tests__/api.scoped-headers.test.ts +58 -0
  1348. package/src/backend/utils/__tests__/api.test.ts +148 -0
  1349. package/src/backend/utils/__tests__/apiCall.scoped-request-headers.test.ts +58 -0
  1350. package/src/backend/utils/__tests__/apiCall.test.ts +109 -0
  1351. package/src/backend/utils/__tests__/crud.test.ts +87 -0
  1352. package/src/backend/utils/__tests__/customFieldDefs.test.ts +25 -0
  1353. package/src/backend/utils/__tests__/customFieldValues.test.ts +35 -0
  1354. package/src/backend/utils/__tests__/richTextSanitizer.test.ts +57 -0
  1355. package/src/backend/utils/api.ts +214 -0
  1356. package/src/backend/utils/apiCall.ts +123 -0
  1357. package/src/backend/utils/crud.ts +174 -0
  1358. package/src/backend/utils/customFieldColumns.ts +118 -0
  1359. package/src/backend/utils/customFieldDefs.ts +247 -0
  1360. package/src/backend/utils/customFieldFilters.ts +174 -0
  1361. package/src/backend/utils/customFieldForms.ts +203 -0
  1362. package/src/backend/utils/customFieldRelationDisplay.ts +302 -0
  1363. package/src/backend/utils/customFieldValues.ts +41 -0
  1364. package/src/backend/utils/flash.ts +17 -0
  1365. package/src/backend/utils/nav.ts +402 -0
  1366. package/src/backend/utils/richTextSanitizer.ts +7 -0
  1367. package/src/backend/utils/scopedHeaderStack.ts +49 -0
  1368. package/src/backend/utils/serverErrors.ts +313 -0
  1369. package/src/backend/utils/useAutoDiscoveredFields.ts +138 -0
  1370. package/src/backend/version-history/VersionHistoryAction.tsx +76 -0
  1371. package/src/backend/version-history/VersionHistoryDetail.tsx +87 -0
  1372. package/src/backend/version-history/VersionHistoryPanel.tsx +331 -0
  1373. package/src/backend/version-history/index.ts +9 -0
  1374. package/src/backend/version-history/labels.ts +56 -0
  1375. package/src/backend/version-history/types.ts +27 -0
  1376. package/src/backend/version-history/useAuditPermissions.ts +94 -0
  1377. package/src/backend/version-history/useVersionHistory.ts +173 -0
  1378. package/src/backend/views/NewViewForm.tsx +54 -0
  1379. package/src/backend/views/ShareForm.tsx +62 -0
  1380. package/src/backend/views/ViewChip.tsx +123 -0
  1381. package/src/backend/views/ViewChipMenu.tsx +94 -0
  1382. package/src/backend/views/types.ts +4 -0
  1383. package/src/frontend/AuthFooter.tsx +29 -0
  1384. package/src/frontend/LanguageSwitcher.tsx +66 -0
  1385. package/src/frontend/Layout.tsx +13 -0
  1386. package/src/hooks/useIsMobile.ts +27 -0
  1387. package/src/index.ts +40 -0
  1388. package/src/portal/PortalContext.tsx +180 -0
  1389. package/src/portal/PortalLayoutProvider.tsx +5 -0
  1390. package/src/portal/PortalLayoutShell.tsx +64 -0
  1391. package/src/portal/PortalShell.tsx +370 -0
  1392. package/src/portal/components/PortalCard.tsx +77 -0
  1393. package/src/portal/components/PortalEmptyState.tsx +32 -0
  1394. package/src/portal/components/PortalFeatureCard.tsx +41 -0
  1395. package/src/portal/components/PortalNotificationBell.tsx +81 -0
  1396. package/src/portal/components/PortalNotificationPanel.tsx +230 -0
  1397. package/src/portal/components/PortalPageHeader.tsx +33 -0
  1398. package/src/portal/components/index.ts +6 -0
  1399. package/src/portal/hooks/useCustomerAuth.ts +97 -0
  1400. package/src/portal/hooks/usePortalAppEvent.ts +56 -0
  1401. package/src/portal/hooks/usePortalDashboardWidgets.ts +50 -0
  1402. package/src/portal/hooks/usePortalEventBridge.ts +162 -0
  1403. package/src/portal/hooks/usePortalInjectedMenuItems.ts +130 -0
  1404. package/src/portal/hooks/usePortalNotifications.ts +116 -0
  1405. package/src/portal/hooks/useTenantContext.ts +83 -0
  1406. package/src/primitives/DataLoader.tsx +93 -0
  1407. package/src/primitives/ErrorNotice.tsx +17 -0
  1408. package/src/primitives/Notice.tsx +83 -0
  1409. package/src/primitives/alert.tsx +59 -0
  1410. package/src/primitives/badge.tsx +43 -0
  1411. package/src/primitives/button.tsx +60 -0
  1412. package/src/primitives/calendar.tsx +69 -0
  1413. package/src/primitives/card.tsx +92 -0
  1414. package/src/primitives/checkbox.tsx +34 -0
  1415. package/src/primitives/dialog.tsx +122 -0
  1416. package/src/primitives/form-field.tsx +106 -0
  1417. package/src/primitives/icon-button.tsx +48 -0
  1418. package/src/primitives/input.tsx +26 -0
  1419. package/src/primitives/label.tsx +18 -0
  1420. package/src/primitives/popover.tsx +37 -0
  1421. package/src/primitives/primitives.stories.tsx +223 -0
  1422. package/src/primitives/progress.tsx +28 -0
  1423. package/src/primitives/separator.tsx +7 -0
  1424. package/src/primitives/sheet.tsx +137 -0
  1425. package/src/primitives/spinner.tsx +27 -0
  1426. package/src/primitives/status-badge.tsx +62 -0
  1427. package/src/primitives/switch.tsx +92 -0
  1428. package/src/primitives/table.tsx +27 -0
  1429. package/src/primitives/tabs.tsx +131 -0
  1430. package/src/primitives/textarea.tsx +20 -0
  1431. package/src/primitives/tooltip.tsx +85 -0
  1432. package/src/primitives-v2/AGENTS.md +66 -0
  1433. package/src/primitives-v2/Alert.stories.tsx +56 -0
  1434. package/src/primitives-v2/Alert.tsx +108 -0
  1435. package/src/primitives-v2/Avatar.stories.tsx +60 -0
  1436. package/src/primitives-v2/Avatar.tsx +139 -0
  1437. package/src/primitives-v2/Badge.stories.tsx +80 -0
  1438. package/src/primitives-v2/Badge.tsx +99 -0
  1439. package/src/primitives-v2/Breadcrumb.stories.tsx +61 -0
  1440. package/src/primitives-v2/Breadcrumb.tsx +96 -0
  1441. package/src/primitives-v2/Button.stories.tsx +72 -0
  1442. package/src/primitives-v2/Button.tsx +178 -0
  1443. package/src/primitives-v2/Checkbox.stories.tsx +34 -0
  1444. package/src/primitives-v2/Checkbox.tsx +103 -0
  1445. package/src/primitives-v2/IconButton.stories.tsx +40 -0
  1446. package/src/primitives-v2/IconButton.tsx +40 -0
  1447. package/src/primitives-v2/Input.stories.tsx +60 -0
  1448. package/src/primitives-v2/Input.tsx +113 -0
  1449. package/src/primitives-v2/NavGroup.stories.tsx +50 -0
  1450. package/src/primitives-v2/NavGroup.tsx +76 -0
  1451. package/src/primitives-v2/NavItem.stories.tsx +68 -0
  1452. package/src/primitives-v2/NavItem.tsx +105 -0
  1453. package/src/primitives-v2/SearchInput.stories.tsx +44 -0
  1454. package/src/primitives-v2/SearchInput.tsx +123 -0
  1455. package/src/primitives-v2/Sidebar.stories.tsx +91 -0
  1456. package/src/primitives-v2/Sidebar.tsx +92 -0
  1457. package/src/primitives-v2/Tab.stories.tsx +62 -0
  1458. package/src/primitives-v2/Tab.tsx +148 -0
  1459. package/src/primitives-v2/Tag.stories.tsx +123 -0
  1460. package/src/primitives-v2/Tag.tsx +115 -0
  1461. package/src/primitives-v2/Toggle.stories.tsx +37 -0
  1462. package/src/primitives-v2/Toggle.tsx +93 -0
  1463. package/src/primitives-v2/Topbar.stories.tsx +65 -0
  1464. package/src/primitives-v2/Topbar.tsx +37 -0
  1465. package/src/primitives-v2/index.ts +31 -0
  1466. package/src/primitives-v2/utils.ts +9 -0
  1467. package/src/theme/BrandThemeProvider.tsx +122 -0
  1468. package/src/theme/QueryProvider.tsx +46 -0
  1469. package/src/theme/ThemeProvider.tsx +120 -0
  1470. package/src/theme/ThemeToggle.tsx +88 -0
  1471. package/src/theme/index.ts +4 -0
  1472. package/src/theme/m3.css +622 -0
  1473. package/src/theme/tokens.v2.css +559 -0
  1474. package/src/theme/typography.css +163 -0
  1475. package/src/theme/typography.stories.tsx +157 -0
  1476. package/src/theme/typography.tokens.ts +326 -0
  1477. package/src/types/react-big-calendar.d.ts +16 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/backend/dynamic-table/hooks/useDynamicTablePage.tsx"],
4
+ "sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { useState, useMemo, useRef, useEffect, useCallback } from 'react'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport { apiCall } from '../../utils/apiCall'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { flash } from '../../FlashMessages'\nimport { dispatch, useEventHandlers } from '../events/events'\nimport {\n apiToDynamicTable,\n apiTemplateToDynamicTable,\n dynamicTableToApi,\n} from '../utils/perspectiveTransforms'\nimport TableDeleteDialog from '../components/TableDeleteDialog'\nimport type {\n ColumnDef,\n FilterRow,\n DynamicTableProps,\n PaginationProps,\n TableUIConfig,\n CellEditSaveEvent,\n CellSaveStartEvent,\n CellSaveSuccessEvent,\n CellSaveErrorEvent,\n NewRowSaveEvent,\n NewRowSaveErrorEvent,\n KeyboardShortcutsConfig,\n OnRowAction,\n LoadLookupSources,\n ExportAllResult,\n} from '../types/index'\nimport { TableEvents } from '../types/index'\nimport { mergeSharedFilters } from '../split-view/sharedCriteria'\nimport { lookupColumnsToParam } from '../utils/lookupColumns'\nimport { rollupColumnsToParam } from '../utils/rollupColumns'\nimport type { LoadRollupSources, RollupColumnRef } from '../types/rollup'\nimport type { AggregationRule, AggregateResult, GroupRule } from '../types/grouping'\nimport type {\n PerspectiveConfig,\n PerspectiveSaveEvent,\n PerspectiveSelectEvent,\n PerspectiveRenameEvent,\n PerspectiveDeleteEvent,\n PerspectiveChangeEvent,\n PerspectiveDuplicateEvent,\n PerspectiveSetDefaultEvent,\n PerspectivePublishEvent,\n PerspectiveTemplateCopyEvent,\n PerspectiveTemplate,\n SortRule,\n LookupColumnRef,\n TableViewMode,\n} from '../types/perspective'\nimport { BASE_VIEW_PERSPECTIVE_NAME, PERSPECTIVE_NAME_MAX_LENGTH } from '../types/perspective'\nimport type {\n PerspectivesIndexResponse,\n PerspectiveDto,\n PerspectiveSaveResponse,\n} from '@open-mercato/shared/modules/perspectives/types'\n\n// Stable identity so it can sit in effect dependency arrays without churning.\nconst EMPTY_COLUMNS: string[] = []\n\n/**\n * The one perspective-write failure a user can actually act on.\n *\n * The upstream table SOFT-deletes views, but its unique index on\n * `(user, tenant, org, table, name)` ignores `deleted_at` \u2014 so a name you used\n * on a view you deleted earlier is still taken, forever, and the write comes\n * back as a duplicate-key 500 with no field-level detail. Every generic\n * \"Failed to \u2026\" message sent the user round the same loop; naming the cause\n * tells them the one thing that will work.\n */\nfunction perspectiveWriteError(response: { result?: unknown }, fallback: string): string {\n const message = (response.result as { message?: string } | undefined)?.message ?? ''\n return message.includes('duplicate key')\n ? 'A view you deleted earlier still holds this name. Pick a different name.'\n : fallback\n}\n\nconst LAST_PERSPECTIVE_KEY_PREFIX = 'dt:lastPerspective:'\n\n/**\n * How long a burst of single-cell saves is allowed to accumulate before ONE\n * list refetch runs. Long enough to swallow a paste/fill (whose per-cell PUTs\n * land within a few tens of ms of each other) and a human typing across\n * adjacent cells; short enough that a server-derived column updates while the\n * user is still looking at the row they changed.\n */\nconst LIST_REFETCH_COALESCE_MS = 400\n\n/**\n * Remember which view the user was last on, per table. Session-scoped: it must\n * survive navigating into a record and back (the actual complaint) without\n * outliving the browser session or needing a server round-trip. Storage access\n * is guarded \u2014 SSR has no `window`, and Safari private mode throws on write.\n */\nfunction readLastPerspectiveId(tableId: string | undefined): string | null {\n if (!tableId || typeof window === 'undefined') return null\n try {\n return window.sessionStorage.getItem(`${LAST_PERSPECTIVE_KEY_PREFIX}${tableId}`)\n } catch {\n return null\n }\n}\n\nfunction writeLastPerspectiveId(tableId: string | undefined, id: string | null): void {\n if (!tableId || typeof window === 'undefined') return\n try {\n const key = `${LAST_PERSPECTIVE_KEY_PREFIX}${tableId}`\n if (id) window.sessionStorage.setItem(key, id)\n else window.sessionStorage.removeItem(key)\n } catch {\n /* storage unavailable \u2014 last-view memory is best-effort */\n }\n}\n\n// \u2500\u2500\u2500 Config Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface DynamicTablePageDeleteConfig<TRow = any> {\n title?: string | ((row: TRow) => string)\n description?: string | ((row: TRow) => string)\n nameColumn?: string\n /** Base URL or function returning full URL for the DELETE request */\n url?: string | ((row: TRow) => string)\n}\n\nexport interface DynamicTablePageCellEditConfig {\n url?: string | ((payload: CellEditSaveEvent, rowData: any) => string)\n method?: 'PUT' | 'PATCH' | 'POST'\n mapPayload?: (payload: CellEditSaveEvent, rowData: any) => Record<string, unknown>\n}\n\nexport interface DynamicTableCreateHandlerContext {\n tableRef: React.RefObject<HTMLElement>\n invalidate: () => void\n}\n\nexport interface DynamicTablePageCreateConfig {\n url?: string\n mapPayload?: (rowData: any) => Record<string, unknown>\n /** Fully custom create flow. Replaces built-in logic. Handler must dispatch NEW_ROW_SAVE_START/SUCCESS/ERROR events. */\n handler?: (payload: NewRowSaveEvent, ctx: DynamicTableCreateHandlerContext) => Promise<void>\n}\n\nexport interface DynamicTablePageHooks<TRow = any> {\n beforeCellEdit?: (\n payload: CellEditSaveEvent,\n rowData: any\n ) => { url?: string; payload?: Record<string, unknown>; method?: 'PUT' | 'PATCH' | 'POST' } | void\n beforeCreate?: (rowData: any) => Record<string, unknown> | Promise<Record<string, unknown>> | void\n validateCreate?: (rowData: any) => string | null\n afterMutation?: (\n type: 'cellEdit' | 'create' | 'delete',\n context: any\n ) => void | Promise<void>\n beforeDelete?: (row: TRow) => boolean | Promise<boolean>\n}\n\nexport interface DynamicTablePageConfig<TRow = any> {\n source: string\n columns: ColumnDef[]\n tableName: string\n\n perspectives?: string\n /**\n * Entity id for the generic `/api/entities/filter-suggestions` endpoint.\n *\n * Prefer `loadFilterSuggestions` for any list whose columns are denormalised\n * or whose values are skewed: the generic endpoint samples a page of rows and\n * de-duplicates what it sees, so it under-reports common columns and returns\n * `[]` (silently) for anything that isn't a plain column on the entity's own\n * table.\n */\n filterSuggestions?: string\n /**\n * Custom suggestion loader \u2014 takes precedence over `filterSuggestions`.\n * Point this at a module route backed by `distinctColumnValues` so the list\n * offers real, scope-constrained values for every column it shows.\n */\n loadFilterSuggestions?: (field: string, query: string) => Promise<string[]>\n /**\n * Prefix for this instance's per-table CLIENT storage keys \u2014 the last-used\n * perspective (`sessionStorage`) and column widths (`localStorage`).\n *\n * Absent or `''` \u2192 today's keys, byte-for-byte, so no existing user loses a\n * saved width. A host that can mount the same table twice (split view) passes\n * something unique per instance, e.g. `pane:{paneId}:` \u2014 without it, both\n * instances derive the same key from `tableId` and overwrite each other.\n *\n * Deliberately NOT applied to density: that stays a user-global preference,\n * so an embedded table never silently gets a different row height from the\n * same table full-page.\n *\n * Spec: .ai/specs/2026-08-04-module-table-registry.md\n */\n storageScope?: string\n /** Loads the table's FK lookup sources. When set, the Configure View drawer\n * shows a \"Linked columns\" section and the list request carries the active\n * perspective's linked columns as a `lookups` param for server enrichment. */\n loadLookupSources?: LoadLookupSources\n /**\n * Loads the table's one-to-many rollup sources. When set, the Configure View\n * drawer shows a \"Summarised columns\" section, and this hook serialises the\n * active perspective's rollup columns into a `rollups` param for the list\n * route to aggregate.\n */\n loadRollupSources?: LoadRollupSources\n\n defaultSort?: { field: string; direction: 'asc' | 'desc' }\n defaultPageSize?: number\n /** Initial filters to seed on mount (e.g., from URL params). Only read once. */\n initialFilters?: FilterRow[]\n /**\n * Filters a WORKSPACE is driving this table with, already translated into\n * this table's own field names by `mapCriteriaForTable`.\n *\n * Held in a different place from the user's own `filters` on purpose. Merging\n * them into that state would overwrite what the user set in this pane, and\n * turning the workspace toggle back off could then restore nothing \u2014 the\n * local filters would be gone. These combine with `filters` ONLY where the\n * list request is built, and a shared rule wins over a local rule on the same\n * field for that request alone (see `mergeSharedFilters`).\n *\n * Absent \u21D2 this hook behaves exactly as it did before the workspace existed.\n */\n sharedFilters?: FilterRow[]\n /**\n * The workspace search box's value, while the workspace is driving this pane.\n *\n * PRESENCE IS THE SWITCH, and the distinction matters:\n * `undefined` \u2192 no workspace search; the pane's own search box applies.\n * `''` \u2192 the workspace bar IS on and its box is empty; the pane's\n * own (now HIDDEN) search must not keep filtering, so this\n * empty needle wins.\n * Any non-empty string replaces the pane's own search for the request. This\n * mirrors the UI: while the bar is on, each pane's search row is hidden, and\n * filtering by a box nobody can see is how a user comes to distrust the grid.\n * The pane's own `search` state is left untouched throughout, so switching the\n * workspace off restores it.\n */\n sharedSearch?: string\n idColumn?: string\n\n delete?: boolean | string | DynamicTablePageDeleteConfig<TRow>\n create?: boolean | DynamicTablePageCreateConfig\n cellEdit?: false | DynamicTablePageCellEditConfig\n\n queryKey?: string\n /** Extra values appended to the query key for cache invalidation (e.g., scopeVersion) */\n queryKeyDeps?: unknown[]\n extraParams?: Record<string, string> | (() => Record<string, string>)\n mapApiItem?: (item: any) => TRow | null\n\n hooks?: DynamicTablePageHooks<TRow>\n\n tableProps?: Partial<\n Omit<\n DynamicTableProps,\n 'data' | 'columns' | 'tableRef' | 'pagination' | 'savedPerspectives' | 'activePerspectiveId' | 'tableName'\n >\n >\n}\n\n// \u2500\u2500\u2500 Return Type \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface DynamicTablePageResult<TRow = any> {\n props: DynamicTableProps\n /** Delete confirmation dialog. Render inline as {table.deleteDialog}. Returns null when no deletion is pending. */\n deleteDialog: React.ReactNode\n /** Trigger the delete dialog for a given row */\n setRowToDelete: (row: TRow | null) => void\n query: ReturnType<typeof useQuery>\n /**\n * Dataset-wide aggregate for the active view's aggregation rules. `null`\n * until it lands, or when the list route has not adopted `?aggregate=`.\n */\n aggregateResult: AggregateResult | null\n aggregateLoading: boolean\n aggregateError: boolean\n /**\n * The LIST request failed (HEDGE-119). Exposed for hosts that render their\n * own body instead of the grid, so they can refuse to draw an \"empty\"\n * affordance over a request that never landed.\n */\n isError: boolean\n isLoading: boolean\n refresh: () => void\n state: {\n page: number\n limit: number\n search: string\n filters: FilterRow[]\n sortField: string\n sortDir: 'asc' | 'desc'\n /**\n * The active grouping, mirrored up from the table.\n *\n * READ-ONLY, and it is a MIRROR, not the source: `DynamicTable` owns the\n * grouping state and reports it in PERSPECTIVE_CHANGE. A host that wants to\n * label something by the active grouping reads it here; a host that wants\n * to CHANGE it uses the Configure View drawer like everything else.\n */\n grouping: GroupRule[]\n /** How the table is currently drawing its rows. Same mirror contract. */\n viewMode: TableViewMode\n }\n}\n\n// \u2500\u2500\u2500 Hook \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function useDynamicTablePage<TRow = any>(\n config: DynamicTablePageConfig<TRow>\n): DynamicTablePageResult<TRow> {\n const {\n source,\n columns,\n tableName,\n perspectives: perspectivesTableId,\n defaultSort,\n defaultPageSize = 50,\n idColumn = 'id',\n storageScope = '',\n hooks,\n } = config\n\n const tableRef = useRef<HTMLDivElement>(null)\n const queryClient = useQueryClient()\n\n // Identity for this INSTANCE's client-side storage (last-used perspective,\n // column widths) \u2014 as opposed to `perspectivesTableId`, which identifies the\n // TABLE and must stay unscoped so every instance loads the same saved views\n // from the server. With an empty scope this is byte-identical to the old key.\n const storageTableId = perspectivesTableId\n ? `${storageScope}${perspectivesTableId}`\n : undefined\n\n // Organization scope. Features AND rows are org-scoped, and switching org\n // dispatches a client-side event with NO page reload \u2014 so without this in the\n // query key a cached table goes on showing the PREVIOUS organization's rows.\n // That is authorised data in the wrong scope, presented as current, which is\n // how someone invoices the wrong customer.\n //\n // Placed in the DEFAULT key rather than left to each table's `queryKeyDeps`:\n // only 3 of 20 tables opted in, so 17 carried the bug. One place fixes all.\n const organizationScopeVersion = useOrganizationScopeVersion()\n\n // \u2500\u2500 State \u2500\u2500\n\n const [page, setPage] = useState(1)\n const [limit, setLimit] = useState(defaultPageSize)\n const [sortField, setSortField] = useState(defaultSort?.field ?? 'id')\n const [sortDir, setSortDir] = useState<'asc' | 'desc'>(defaultSort?.direction ?? 'asc')\n const [search, setSearch] = useState('')\n const [filters, setFilters] = useState<FilterRow[]>(() => config.initialFilters ?? [])\n // Mirrors of table-owned view state, kept so a HOST can read them (a grid\n // renderer, a heading, an export label). Written only from PERSPECTIVE_CHANGE\n // \u2014 never set from here, because a second writer is a second source of truth.\n const [grouping, setGrouping] = useState<GroupRule[]>([])\n const [viewMode, setViewMode] = useState<TableViewMode>('table')\n\n const [savedPerspectives, setSavedPerspectives] = useState<PerspectiveConfig[]>([])\n // Views other people published for anyone to COPY. Never applied\n // automatically \u2014 see `PerspectiveTemplate`.\n const [sharedTemplates, setSharedTemplates] = useState<PerspectiveTemplate[]>([])\n const [activePerspectiveId, setActivePerspectiveId] = useState<string | null>(null)\n // Mirror of the active perspective's linked (lookup) columns. Synced from the\n // DynamicTable's perspective events so the list request can carry them to the\n // server for enrichment. The grid renders the columns itself from the same\n // perspective state.\n const [lookupColumns, setLookupColumns] = useState<LookupColumnRef[]>([])\n // Mirror of the active perspective's rollup (\"summarised\") columns, for the\n // same reason as `lookupColumns` \u2014 except the cost is higher: each distinct\n // SOURCE is one GROUP BY on the server, so the param carries only what the\n // active view actually asked for, and an empty param leaves the route\n // behaving byte-identically to before rollups existed.\n const [rollupColumns, setRollupColumns] = useState<RollupColumnRef[]>([])\n // Mirror of the active perspective's aggregation rules. Same reason as\n // `lookupColumns`: the grid owns the rules, but the DATASET-wide totals can\n // only be computed on the server, so the request has to carry them.\n const [aggregations, setAggregations] = useState<AggregationRule[]>([])\n\n const [pendingDelete, setPendingDelete] = useState<TRow | null>(null)\n const [isDeleting, setIsDeleting] = useState(false)\n // Bulk delete drives a confirmation modal. The promise resolver bridges the\n // modal outcome back to the DynamicTable so it only clears its selection once\n // the rows are actually deleted (and keeps it on cancel).\n const [pendingBulkDelete, setPendingBulkDelete] = useState<string[] | null>(null)\n const bulkResolverRef = useRef<{ resolve: () => void; reject: (reason?: unknown) => void } | null>(null)\n\n const queryKeyBase = config.queryKey ?? source\n\n // \u2500\u2500 List invalidation, COALESCED \u2500\u2500\n //\n // Every successful cell save used to call `invalidateQueries` on the spot, so\n // a three-cell edit produced three PUTs and three IDENTICAL GETs of the same\n // page (ledger row 9.7) \u2014 and a paste or a fill, which is one gesture, fires\n // one per written cell. The refetch is not what makes the screen correct: the\n // store writes the row object optimistically and the grid already renders the\n // new value. The refetch exists to pick up SERVER-DERIVED changes (computed\n // columns, a status recalculated by a subscriber), and for that a single\n // trailing refetch after the burst is exactly as correct as N of them.\n //\n // Trailing edge, not leading: the last write in a burst must be included.\n const listInvalidateTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const cancelPendingListInvalidation = useCallback(() => {\n if (listInvalidateTimerRef.current) {\n clearTimeout(listInvalidateTimerRef.current)\n listInvalidateTimerRef.current = null\n }\n }, [])\n const scheduleListInvalidation = useCallback(() => {\n cancelPendingListInvalidation()\n listInvalidateTimerRef.current = setTimeout(() => {\n listInvalidateTimerRef.current = null\n queryClient.invalidateQueries({ queryKey: [queryKeyBase] })\n }, LIST_REFETCH_COALESCE_MS)\n }, [cancelPendingListInvalidation, queryClient, queryKeyBase])\n /** Row-count changes (create / delete) refetch NOW \u2014 and supersede any pending burst. */\n const invalidateListNow = useCallback(() => {\n cancelPendingListInvalidation()\n queryClient.invalidateQueries({ queryKey: [queryKeyBase] })\n }, [cancelPendingListInvalidation, queryClient, queryKeyBase])\n useEffect(() => cancelPendingListInvalidation, [cancelPendingListInvalidation])\n\n // Columns the host table hides by default. Needed when rehydrating saved\n // perspectives: one saved without column config must fall back to the table's\n // defaults rather than revealing every hidden column.\n const defaultHiddenColumns = config.tableProps?.defaultHiddenColumns ?? EMPTY_COLUMNS\n\n // \u2500\u2500 Perspectives \u2500\u2500\n\n const { data: perspectivesData, isFetched: perspectivesFetched } = useQuery({\n queryKey: ['perspectives', perspectivesTableId],\n queryFn: async () => {\n const response = await apiCall<PerspectivesIndexResponse>(\n `/api/perspectives/${perspectivesTableId}`\n )\n return response.ok ? response.result : null\n },\n enabled: !!perspectivesTableId,\n })\n\n // \u2500\u2500 The list query waits for the perspective to be resolved \u2500\u2500\n //\n // Ledger 4.9: a saved view carrying rollup columns rendered every rollup cell\n // as \"\u2014\" on the FIRST load. The columns come from the perspective and paint\n // immediately; the VALUES come from `?rollups=` on the list request, and that\n // param is derived from the same perspective \u2014 which had not been fetched yet\n // when the list query fired. So load one produced a request WITHOUT the param\n // (rollup columns present, all values null), and only the second request \u2014\n // triggered when `setRollupColumns` finally changed `queryParams` \u2014 carried\n // it. Two round-trips, and a window in between where the grid confidently\n // shows em-dashes for numbers that exist.\n //\n // Gating the list on the perspective removes the wasted request rather than\n // re-timing it. `setPerspectiveHydrated(true)` is called in the SAME effect\n // that applies the restored filters/sort/lookups/rollups, so React batches\n // them into one re-render and the first request the user ever sees already\n // carries every param the view asked for.\n //\n // Two escape hatches, because a list that never loads is far worse than a\n // wasted request: a table with no `perspectives` id starts hydrated, and the\n // effect below flips the flag as soon as the perspectives request SETTLES,\n // whatever it returned (404, empty, or columns not built yet).\n const [perspectiveHydrated, setPerspectiveHydrated] = useState(!perspectivesTableId)\n\n useEffect(() => {\n if (!perspectivesTableId || !perspectivesFetched) return\n if (!perspectivesData?.perspectives || columns.length === 0) setPerspectiveHydrated(true)\n }, [perspectivesTableId, perspectivesFetched, perspectivesData, columns.length])\n\n // Guards the one-time initial perspective pick. Kept in a ref (not in the\n // effect deps) because `activePerspectiveId` used to be both read and written\n // here \u2014 which re-ran the effect and handed DynamicTable a brand-new\n // `savedPerspectives` array identity on every load.\n const initialPerspectivePickedRef = useRef(false)\n\n useEffect(() => {\n if (perspectivesData?.perspectives && columns.length > 0) {\n const allCols = columns.map((c) => c.data)\n const transformed = perspectivesData.perspectives.map((p) =>\n apiToDynamicTable(p, allCols, defaultHiddenColumns)\n )\n setSavedPerspectives(transformed)\n // Shared templates arrive on the SAME response the personal views do \u2014\n // `rolePerspectives` has always been in the payload and was simply ignored.\n setSharedTemplates(\n (perspectivesData.rolePerspectives ?? []).map((rp) =>\n apiTemplateToDynamicTable(rp, allCols, defaultHiddenColumns)\n )\n )\n if (!initialPerspectivePickedRef.current) {\n // Prefer the view the user was last on over the server default, so\n // navigating into a record and back doesn't silently reset the list.\n // With neither, fall back to this user's saved personalization of the\n // base tab, so \"Default view\" opens the way they last left it.\n const remembered = readLastPerspectiveId(storageTableId)\n const baseViewId = transformed.find((p) => p.isBaseView)?.id ?? null\n const restored = remembered && transformed.some((p) => p.id === remembered)\n ? remembered\n : (perspectivesData.defaultPerspectiveId ?? baseViewId)\n // Close the gate as soon as the views have LOADED, whether or not one was\n // restored. It used to close only inside `if (restored)`, which made the\n // feature chicken-and-egg: with no remembered view and no server default\n // the ref stayed false forever, the persist effect below returned early,\n // and a manual tab click was never written \u2014 so the list could only\n // remember a view if it already remembered one. `remembered` is read\n // above, before the gate closes, so nothing is clobbered.\n initialPerspectivePickedRef.current = true\n if (restored) {\n setActivePerspectiveId(restored)\n // Apply the view's QUERY state here, not via the grid's\n // PERSPECTIVE_CHANGE event.\n //\n // The grid applies the view to ITSELF (columns, the sort arrow in the\n // header) and announces it with PERSPECTIVE_CHANGE. On a tab click\n // that reaches us and the list refetches. On first load it does NOT:\n // the grid's dispatch effect and this hook's listener registration\n // race, child passive effects run before the parent's, and the one\n // dispatch that carries the restored view fires before\n // `useEventHandlers` has attached. Proven in the browser \u2014 a cold load\n // of a view sorted by Reference # \u2193 issued exactly one list request,\n // `sortField=containerNumber` (the table default), while the header\n // already painted the \u2193 on Reference #; clicking the same tab then\n // issued `sortField=referenceNumber&sortDir=desc`.\n //\n // Reading the config straight off the perspective we just restored\n // removes the race entirely rather than re-timing it, and it is the\n // same projection `handlePerspectiveSelect` performs for a click, so\n // the two entry points cannot drift.\n const restoredPerspective = transformed.find((p) => p.id === restored)\n if (restoredPerspective) {\n // Only when the view HAS filters: a view without them must not wipe\n // `initialFilters` seeded from the URL (deep links carry a filter).\n if (restoredPerspective.filters.length > 0) setFilters(restoredPerspective.filters)\n setLookupColumns(restoredPerspective.lookupColumns ?? [])\n setRollupColumns(restoredPerspective.rollupColumns ?? [])\n setAggregations(restoredPerspective.aggregations ?? [])\n if (restoredPerspective.sorting.length > 0) {\n setSortField(restoredPerspective.sorting[0].field)\n setSortDir(restoredPerspective.sorting[0].direction)\n }\n }\n }\n // Released in the SAME batch as the setters above, so the very first\n // list request carries the restored view's rollups/lookups/sort/filters\n // rather than being issued once without them and again with (4.9).\n setPerspectiveHydrated(true)\n }\n }\n }, [perspectivesData, columns, defaultHiddenColumns, perspectivesTableId])\n\n // Persist every subsequent switch (tab click, save, delete-active) so the\n // next mount restores it. Gated on the initial pick so the mount-time `null`\n // can't wipe the remembered view before it has been read back.\n useEffect(() => {\n if (!initialPerspectivePickedRef.current) return\n writeLastPerspectiveId(storageTableId, activePerspectiveId)\n }, [activePerspectiveId, perspectivesTableId])\n\n // \u2500\u2500 Workspace-shared criteria \u2500\u2500\n //\n // The ONLY place the workspace's criteria and this pane's own state meet.\n // Both `search`/`filters` above stay exactly what the user set here, so\n // turning the workspace off is a pure removal \u2014 nothing to restore, because\n // nothing was overwritten.\n const sharedFilters = config.sharedFilters\n const sharedSearch = config.sharedSearch\n // Identity note: with no shared filters this returns `filters` itself, so the\n // memo below sees the same reference it always did.\n const effectiveFilters = useMemo(\n () => mergeSharedFilters(filters, sharedFilters),\n [filters, sharedFilters],\n )\n const effectiveSearch = sharedSearch !== undefined ? sharedSearch : search\n\n // \u2500\u2500 Data Query \u2500\u2500\n\n const queryParams = useMemo(() => {\n const params = new URLSearchParams()\n params.set('page', String(page))\n params.set('limit', String(limit))\n params.set('pageSize', String(limit))\n params.set('sortField', sortField)\n params.set('sortDir', sortDir)\n if (effectiveSearch) {\n params.set('q', effectiveSearch)\n params.set('search', effectiveSearch)\n }\n if (effectiveFilters.length) params.set('filters', JSON.stringify(effectiveFilters))\n if (lookupColumns.length) params.set('lookups', lookupColumnsToParam(lookupColumns))\n if (rollupColumns.length) params.set('rollups', rollupColumnsToParam(rollupColumns))\n\n const extra =\n typeof config.extraParams === 'function' ? config.extraParams() : config.extraParams\n if (extra) {\n Object.entries(extra).forEach(([key, value]) => params.set(key, value))\n }\n\n return params.toString()\n }, [page, limit, sortField, sortDir, effectiveSearch, effectiveFilters, lookupColumns, rollupColumns, config.extraParams])\n\n // `organizationScopeVersion` leads the deps so EVERY table refetches when the\n // user switches organization, whether or not it opted in via `queryKeyDeps`.\n // The three tables that already pass `scopeVersion` themselves are unaffected\n // \u2014 a repeated value in a query key is idempotent.\n const queryKeyDeps = useMemo(\n () => [organizationScopeVersion, ...(config.queryKeyDeps ?? [])],\n [organizationScopeVersion, config.queryKeyDeps],\n )\n\n const dataQuery = useQuery({\n queryKey: [queryKeyBase, queryParams, ...queryKeyDeps],\n queryFn: async () => {\n const call = await apiCall<{\n items: any[]\n total: number\n totalPages?: number\n }>(`${source}?${queryParams}`)\n if (!call.ok) throw new Error(`Failed to load ${tableName}`)\n return call.result ?? { items: [], total: 0, totalPages: 1 }\n },\n // See `perspectiveHydrated` above (ledger 4.9). The skeleton stays up for\n // the extra ~50 ms the perspectives request costs; in exchange the first\n // response already carries the view's rollup values instead of a grid full\n // of em-dashes that silently corrects itself a round-trip later.\n enabled: perspectiveHydrated,\n placeholderData: (previousData) => previousData,\n })\n\n // \u2500\u2500 Dataset-wide aggregate \u2500\u2500\n //\n // A SEPARATE request, deliberately: the rows must never wait on a full-table\n // SUM. The grid shows a page-scoped fold immediately and swaps in the dataset\n // figure when it lands. It reuses `queryParams` (same filters, same search)\n // minus paging, so the total always describes exactly the filtered set the\n // page is a window onto.\n // `field:fn`, or `field:fn:dimension` when the rule partitions its aggregate\n // (per-currency totals). The third segment is optional so every previously\n // published route keeps parsing the specs it already knows.\n const aggregateSpec = useMemo(\n () =>\n aggregations\n .map((r) => (r.dimension ? `${r.field}:${r.fn}:${r.dimension}` : `${r.field}:${r.fn}`))\n .join(','),\n [aggregations],\n )\n\n const aggregateParams = useMemo(() => {\n if (!aggregateSpec) return null\n const params = new URLSearchParams(queryParams)\n params.set('aggregate', aggregateSpec)\n // One row is enough to satisfy a route that always paginates; we only read\n // the `aggregate` key off the response.\n params.set('page', '1')\n params.set('limit', '1')\n params.set('pageSize', '1')\n return params.toString()\n }, [queryParams, aggregateSpec])\n\n // PROBE ONCE per page. `makeDynamicTableRoute` has no consumers yet, so most\n // list routes simply ignore `?aggregate=` \u2014 asking again on every filter\n // keystroke would be one wasted round-trip per keystroke, forever.\n const aggregateUnsupportedRef = useRef(false)\n\n const aggregateQuery = useQuery({\n queryKey: [queryKeyBase, 'aggregate', aggregateParams, ...queryKeyDeps],\n enabled: !!aggregateParams && !aggregateUnsupportedRef.current,\n queryFn: async () => {\n const call = await apiCall<{ aggregate?: AggregateResult }>(`${source}?${aggregateParams}`)\n // Degrade, never blank. A route that has not adopted `?aggregate=`\n // (or that rejects the param outright) is not an error condition: the\n // footer already holds a page-scoped fold, and saying \"this page only\"\n // is truthful. Blanking the totals because a probe failed would be a\n // strictly worse answer than the one we already have.\n if (!call.ok || !call.result?.aggregate) {\n aggregateUnsupportedRef.current = true\n return null\n }\n return call.result.aggregate\n },\n placeholderData: (previousData) => previousData,\n })\n\n const tableData = useMemo(() => {\n const items = dataQuery.data?.items ?? []\n if (config.mapApiItem) {\n return items.map(config.mapApiItem).filter(Boolean)\n }\n return items\n }, [dataQuery.data?.items, config.mapApiItem])\n\n // \u2500\u2500 Whole-table export \u2500\u2500\n // Powers the toolbar Export button: page through `source` collecting every\n // row, ignoring the active perspective (filters + search) and pagination so\n // the export is the whole table. Keeps `extraParams` (tab/category scope) and\n // sort for stable ordering. Mapped through `mapApiItem` like the live table.\n //\n // HEDGE-123 \u2014 IT ABORTS, IT DOES NOT SHORTEN.\n //\n // This loop used to end every failure the same way it ended success: `break`,\n // then `return collected`. A page that 500'd, a page that came back `200`\n // with an unparseable body, and a walk that ran into the iteration cap all\n // produced a shorter array and nothing else. The user got a CSV that opened,\n // had headers, had rows, and was missing the rest \u2014 with no error anywhere.\n //\n // That is the same server failure as HEDGE-119 wearing different clothes:\n // there a failed fetch rendered as \"no invoices\", here it writes a short file\n // that reads as \"these are all the invoices\". The file is the more dangerous\n // of the two, because it looks like an answer and goes into a reconciliation.\n //\n // So: a failed or unparseable page THROWS (the toolbar catches it and says\n // the export failed, and no file is written), and a walk that cannot prove it\n // collected everything returns `complete: false` WITH ITS COUNTS rather than\n // a bare array.\n const exportAllRows = useCallback(async (): Promise<ExportAllResult> => {\n const pageLimit = 100 // upstream list cap\n const collected: any[] = []\n let pageNum = 1\n let expected: number | null = null\n\n // Bound the walk by what the SERVER says, not by a constant. The old\n // `guard < 1000` was a silent 100,000-row ceiling: a bigger table exported\n // short for a reason that had nothing to do with failure, and said nothing.\n // Once page 1 reports `totalPages` we know exactly how many iterations are\n // needed; the constant below is only a runaway stop for a server that never\n // reports one, and reaching it is now REPORTED rather than swallowed.\n const RUNAWAY_PAGE_CAP = 10_000\n let maxPages = RUNAWAY_PAGE_CAP\n let incomplete: string | null = null\n\n while (pageNum <= maxPages) {\n const params = new URLSearchParams()\n params.set('page', String(pageNum))\n params.set('limit', String(pageLimit))\n params.set('pageSize', String(pageLimit))\n params.set('sortField', sortField)\n params.set('sortDir', sortDir)\n const extra =\n typeof config.extraParams === 'function' ? config.extraParams() : config.extraParams\n if (extra) Object.entries(extra).forEach(([key, value]) => params.set(key, value))\n if (lookupColumns.length) params.set('lookups', lookupColumnsToParam(lookupColumns))\n if (rollupColumns.length) params.set('rollups', rollupColumnsToParam(rollupColumns))\n\n const call = await apiCall<{ items: any[]; total: number; totalPages?: number }>(\n `${source}?${params.toString()}`,\n )\n\n // The two failures that used to be indistinguishable from \"done\".\n // `!call.result` is NOT redundant with `!call.ok`: `apiCall` returns\n // `ok: true, result: null` for a 200 whose body will not parse, which is\n // exactly what a route erroring after its status line produces.\n if (!call.ok) {\n throw new Error(\n `Export failed on page ${pageNum} (HTTP ${call.status}) after ${collected.length} row(s)`,\n )\n }\n if (!call.result) {\n throw new Error(\n `Export failed on page ${pageNum}: the server returned no readable body after ${collected.length} row(s)`,\n )\n }\n\n const items = call.result.items ?? []\n collected.push(...items)\n\n if (typeof call.result.total === 'number') expected = call.result.total\n const total = call.result.total ?? collected.length\n const totalPages = call.result.totalPages ?? Math.ceil(total / pageLimit)\n // Now that the server has declared its own page count, hold the walk to\n // it. `+ 1` of slack absorbs a row appearing mid-walk without turning a\n // benign race into a hard stop.\n if (Number.isFinite(totalPages) && totalPages > 0) {\n maxPages = Math.min(RUNAWAY_PAGE_CAP, totalPages + 1)\n }\n\n if (items.length === 0 || pageNum >= totalPages) break\n pageNum++\n\n if (pageNum > maxPages) {\n incomplete =\n maxPages >= RUNAWAY_PAGE_CAP\n ? `stopped at the ${RUNAWAY_PAGE_CAP}-page safety limit`\n : `the server declared ${totalPages} page(s) but did not finish within them`\n }\n }\n\n const rows = config.mapApiItem\n ? collected.map(config.mapApiItem).filter(Boolean)\n : collected\n\n // A count shortfall is reported, never silently accepted \u2014 but it is NOT a\n // throw. Rows deleted by someone else while the walk was in flight make\n // `collected < expected` legitimately, and failing an export over a benign\n // concurrent edit would get the button distrusted. The caller decides; what\n // matters is that it is told, with both numbers.\n if (!incomplete && expected !== null && collected.length < expected) {\n incomplete = `fetched ${collected.length} of ${expected} row(s)`\n }\n\n return {\n rows,\n expected,\n complete: incomplete === null,\n ...(incomplete ? { reason: incomplete } : {}),\n }\n }, [source, sortField, sortDir, lookupColumns, rollupColumns, config.extraParams, config.mapApiItem])\n\n // \u2500\u2500 Cell Edit Handler \u2500\u2500\n\n const handleCellEditSave = useCallback(\n async (payload: CellEditSaveEvent) => {\n if (config.cellEdit === false) return\n\n dispatch(tableRef.current as HTMLElement, TableEvents.CELL_SAVE_START, {\n rowIndex: payload.rowIndex,\n colIndex: payload.colIndex,\n } as CellSaveStartEvent)\n\n try {\n const rowData = tableData[payload.rowIndex]\n if (!rowData) throw new Error('Row data not found')\n\n const cellEditConfig = typeof config.cellEdit === 'object' ? config.cellEdit : {}\n let hookResult: { url?: string; payload?: Record<string, unknown>; method?: string } | void = undefined\n\n if (hooks?.beforeCellEdit) {\n hookResult = hooks.beforeCellEdit(payload, rowData)\n }\n\n let apiUrl: string\n if (hookResult?.url) {\n apiUrl = hookResult.url\n } else if (typeof cellEditConfig.url === 'function') {\n apiUrl = cellEditConfig.url(payload, rowData)\n } else if (cellEditConfig.url) {\n apiUrl = `${cellEditConfig.url}/${(rowData as any)[idColumn]}`\n } else {\n apiUrl = `${source}/${(rowData as any)[idColumn]}`\n }\n\n let updatePayload: Record<string, unknown>\n if (hookResult?.payload) {\n updatePayload = hookResult.payload\n } else if (cellEditConfig.mapPayload) {\n updatePayload = cellEditConfig.mapPayload(payload, rowData)\n } else {\n updatePayload = { [payload.prop]: payload.newValue }\n }\n\n const method = hookResult?.method ?? cellEditConfig.method ?? 'PUT'\n\n const response = await apiCall<{ error?: string }>(apiUrl, {\n method,\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(updatePayload),\n })\n\n if (response.ok) {\n dispatch(tableRef.current as HTMLElement, TableEvents.CELL_SAVE_SUCCESS, {\n rowIndex: payload.rowIndex,\n colIndex: payload.colIndex,\n } as CellSaveSuccessEvent)\n scheduleListInvalidation()\n if (hooks?.afterMutation) await hooks.afterMutation('cellEdit', { payload, rowData })\n } else {\n const error = response.result?.error || 'Update failed'\n flash(error, 'error')\n dispatch(tableRef.current as HTMLElement, TableEvents.CELL_SAVE_ERROR, {\n rowIndex: payload.rowIndex,\n colIndex: payload.colIndex,\n error,\n } as CellSaveErrorEvent)\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error'\n flash(errorMessage, 'error')\n dispatch(tableRef.current as HTMLElement, TableEvents.CELL_SAVE_ERROR, {\n rowIndex: payload.rowIndex,\n colIndex: payload.colIndex,\n error: errorMessage,\n } as CellSaveErrorEvent)\n }\n },\n [tableData, scheduleListInvalidation, config.cellEdit, hooks, source, idColumn, queryKeyBase]\n )\n\n // \u2500\u2500 New Row Handler \u2500\u2500\n\n const handleNewRowSave = useCallback(\n async (payload: NewRowSaveEvent) => {\n if (!config.create) return\n\n const createConfig = typeof config.create === 'object' ? config.create : {}\n\n // Custom handler \u2014 fully replaces built-in flow\n if (createConfig.handler) {\n await createConfig.handler(payload, {\n tableRef: tableRef as React.RefObject<HTMLElement>,\n invalidate: () => invalidateListNow(),\n })\n return\n }\n\n try {\n let rowPayload: Record<string, unknown> = { ...payload.rowData }\n\n if (hooks?.validateCreate) {\n const validationError = hooks.validateCreate(payload.rowData)\n if (validationError) {\n flash(validationError, 'error')\n dispatch(tableRef.current as HTMLElement, TableEvents.NEW_ROW_SAVE_ERROR, {\n rowIndex: payload.rowIndex,\n error: validationError,\n } as NewRowSaveErrorEvent)\n return\n }\n }\n\n if (hooks?.beforeCreate) {\n const mapped = await hooks.beforeCreate(payload.rowData)\n if (mapped) rowPayload = mapped\n }\n\n if (createConfig.mapPayload) {\n rowPayload = createConfig.mapPayload(payload.rowData)\n }\n\n const createUrl = createConfig.url ?? source\n\n const response = await apiCall<{ id: string; error?: string }>(createUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(rowPayload),\n })\n\n if (response.ok && response.result) {\n dispatch(tableRef.current as HTMLElement, TableEvents.NEW_ROW_SAVE_SUCCESS, {\n rowIndex: payload.rowIndex,\n savedRowData: { ...payload.rowData, id: response.result.id },\n })\n invalidateListNow()\n if (hooks?.afterMutation)\n await hooks.afterMutation('create', { payload, result: response.result })\n } else {\n const error = response.result?.error || `Failed to create ${tableName}`\n flash(error, 'error')\n dispatch(tableRef.current as HTMLElement, TableEvents.NEW_ROW_SAVE_ERROR, {\n rowIndex: payload.rowIndex,\n error,\n } as NewRowSaveErrorEvent)\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : `Failed to create ${tableName}`\n flash(errorMessage, 'error')\n dispatch(tableRef.current as HTMLElement, TableEvents.NEW_ROW_SAVE_ERROR, {\n rowIndex: payload.rowIndex,\n error: errorMessage,\n } as NewRowSaveErrorEvent)\n }\n },\n [config.create, hooks, source, tableName, queryClient, queryKeyBase]\n )\n\n // \u2500\u2500 Delete Handler \u2500\u2500\n\n const handleConfirmDelete = useCallback(async () => {\n if (!pendingDelete) return\n\n if (hooks?.beforeDelete) {\n const proceed = await hooks.beforeDelete(pendingDelete)\n if (!proceed) return\n }\n\n setIsDeleting(true)\n try {\n const deleteId = (pendingDelete as any)[idColumn]\n let deleteUrl: string\n if (typeof config.delete === 'string') {\n deleteUrl = `${config.delete}/${deleteId}`\n } else if (typeof config.delete === 'object' && config.delete.url) {\n const urlConfig = config.delete.url\n deleteUrl = typeof urlConfig === 'function'\n ? urlConfig(pendingDelete)\n : `${urlConfig}/${deleteId}`\n } else {\n deleteUrl = `${source}/${deleteId}`\n }\n\n const response = await apiCall<{ error?: string }>(deleteUrl, { method: 'DELETE' })\n\n if (response.ok) {\n flash(`${tableName} deleted`, 'success')\n invalidateListNow()\n setPendingDelete(null)\n if (hooks?.afterMutation) await hooks.afterMutation('delete', { row: pendingDelete })\n } else {\n flash(response.result?.error || `Failed to delete ${tableName}`, 'error')\n }\n } catch (error) {\n flash(error instanceof Error ? error.message : `Failed to delete ${tableName}`, 'error')\n } finally {\n setIsDeleting(false)\n }\n }, [pendingDelete, hooks, idColumn, config.delete, source, tableName, queryClient, queryKeyBase])\n\n // \u2500\u2500 Bulk Delete Handler \u2500\u2500\n // Drives the DynamicTable grouped-actions bar. Deletes each selected row via\n // the same endpoint convention as the single-row delete, then refreshes the\n // list. Failures are tallied so a partial success still surfaces clearly.\n const buildDeleteUrl = useCallback(\n (id: string) => {\n if (typeof config.delete === 'string') return `${config.delete}/${id}`\n if (config.delete && typeof config.delete === 'object' && config.delete.url) {\n const urlConfig = config.delete.url\n return typeof urlConfig === 'function'\n ? urlConfig({ [idColumn]: id } as TRow)\n : `${urlConfig}/${id}`\n }\n return `${source}/${id}`\n },\n [config.delete, idColumn, source]\n )\n\n // onBulkDelete prop for DynamicTable: open the confirmation modal and return a\n // promise that resolves once the rows are deleted, or rejects if cancelled.\n const requestBulkDelete = useCallback(\n (ids: string[]) =>\n new Promise<void>((resolve, reject) => {\n if (!ids.length) {\n resolve()\n return\n }\n bulkResolverRef.current = { resolve, reject }\n setPendingBulkDelete(ids)\n }),\n []\n )\n\n const handleConfirmBulkDelete = useCallback(async () => {\n const ids = pendingBulkDelete\n if (!ids || !ids.length) return\n setIsDeleting(true)\n try {\n let deleted = 0\n let failed = 0\n for (const id of ids) {\n try {\n const response = await apiCall<{ error?: string }>(buildDeleteUrl(id), { method: 'DELETE' })\n if (response.ok) deleted += 1\n else failed += 1\n } catch {\n failed += 1\n }\n }\n if (deleted > 0) flash(`${deleted} ${tableName} deleted`, 'success')\n if (failed > 0) flash(`Failed to delete ${failed} ${tableName}`, 'error')\n invalidateListNow()\n if (hooks?.afterMutation) await hooks.afterMutation('delete', { ids })\n bulkResolverRef.current?.resolve()\n } finally {\n bulkResolverRef.current = null\n setPendingBulkDelete(null)\n setIsDeleting(false)\n }\n }, [pendingBulkDelete, buildDeleteUrl, tableName, queryClient, queryKeyBase, hooks])\n\n const cancelBulkDelete = useCallback(() => {\n bulkResolverRef.current?.reject(new Error('cancelled'))\n bulkResolverRef.current = null\n setPendingBulkDelete(null)\n }, [])\n\n // \u2500\u2500 Perspective Handlers \u2500\u2500\n\n const handlePerspectiveSave = useCallback(\n async (payload: PerspectiveSaveEvent) => {\n if (!perspectivesTableId) return\n const settings = dynamicTableToApi(payload.perspective)\n // Resolve the row to update BY ID FIRST, name only as a fallback.\n //\n // Name-only matching is what made \"rename in the Configure View drawer\"\n // create a SECOND view: the panel minted a fresh client-side id, the name\n // had just changed, nothing matched, and the upsert inserted. An id that\n // is already in `savedPerspectives` is a server uuid by construction, so\n // it is safe to send as `perspectiveId`; a client-minted id (a brand-new\n // view) matches nothing and correctly falls through to insert.\n const existingPerspective =\n savedPerspectives.find((p) => p.id === payload.perspective.id) ??\n savedPerspectives.find((p) => p.name === payload.perspective.name)\n const response = await apiCall<PerspectiveSaveResponse>(`/api/perspectives/${perspectivesTableId}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n // The upstream validator reads `perspectiveId`, not `id` \u2014 an `id` key\n // is stripped by zod and the save silently falls back to an upsert by\n // NAME. Harmless here (same name \u21D2 same row) but fatal for rename,\n // which changes the name and so used to CLONE the view.\n perspectiveId: existingPerspective?.id,\n name: payload.perspective.name,\n settings,\n }),\n })\n if (response.ok) {\n // `silent` is set for saves the user did not explicitly ask for \u2014 the\n // column order written back after a header drag. The write and the\n // refetch still happen; only the confirmation toast is dropped.\n if (!payload.silent) {\n flash(\n payload.perspective.isBaseView ? 'Default view saved' : 'Perspective saved',\n 'success',\n )\n }\n queryClient.invalidateQueries({ queryKey: ['perspectives', perspectivesTableId] })\n const savedId = response.result?.perspective?.id\n if (savedId) setActivePerspectiveId(savedId)\n } else {\n // See `perspectiveWriteError` \u2014 the deleted-name collision is the one\n // failure here a user can act on, and every perspective write can hit it.\n flash(perspectiveWriteError(response, 'Failed to save perspective'), 'error')\n }\n },\n [perspectivesTableId, savedPerspectives, queryClient]\n )\n\n const handlePerspectiveSelect = useCallback(\n (payload: PerspectiveSelectEvent) => {\n setActivePerspectiveId(payload.id)\n if (payload.config) {\n setFilters(payload.config.filters)\n setLookupColumns(payload.config.lookupColumns ?? [])\n setRollupColumns(payload.config.rollupColumns ?? [])\n setAggregations(payload.config.aggregations ?? [])\n if (payload.config.sorting.length > 0) {\n setSortField(payload.config.sorting[0].field)\n setSortDir(payload.config.sorting[0].direction)\n }\n setPage(1)\n } else {\n setFilters([])\n setLookupColumns([])\n setRollupColumns([])\n setAggregations([])\n setSortField(defaultSort?.field ?? 'id')\n setSortDir(defaultSort?.direction ?? 'asc')\n setPage(1)\n }\n },\n [defaultSort]\n )\n\n const handlePerspectiveRename = useCallback(\n async (payload: PerspectiveRenameEvent) => {\n if (!perspectivesTableId) return\n const perspective = savedPerspectives.find((p) => p.id === payload.id)\n if (perspective) {\n // Refuse locally rather than round-trip to a 400 whose body says\n // nothing. The rename input caps typing at the same limit, so this only\n // fires for a name assembled in code (a \"(copy)\" suffix on an already\n // long name) \u2014 and when it does, it names the actual problem instead of\n // \"Failed to rename perspective\".\n if (payload.newName.length > PERSPECTIVE_NAME_MAX_LENGTH) {\n flash(\n `A view name can be at most ${PERSPECTIVE_NAME_MAX_LENGTH} characters. This one is ${payload.newName.length}.`,\n 'error',\n )\n return\n }\n const settings = dynamicTableToApi(perspective)\n const response = await apiCall(`/api/perspectives/${perspectivesTableId}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n // `perspectiveId`, not `id` \u2014 see handlePerspectiveSave. With `id` the\n // rename created a SECOND view under the new name and left the old one.\n body: JSON.stringify({ perspectiveId: payload.id, name: payload.newName, settings }),\n })\n if (response.ok) {\n flash('Perspective renamed', 'success')\n queryClient.invalidateQueries({ queryKey: ['perspectives', perspectivesTableId] })\n } else {\n flash(perspectiveWriteError(response, 'Failed to rename perspective'), 'error')\n }\n }\n },\n [perspectivesTableId, savedPerspectives, queryClient]\n )\n\n /**\n * A6 \u2014 duplicate. A brand-new row (no `perspectiveId`) carrying the source's\n * settings under a new name, and explicitly NOT the default: a copy must never\n * hijack which view opens tomorrow.\n *\n * `publication` is dropped for the same reason, and it is not cosmetic. It\n * rides the settings blob as `_published`, so duplicating a view that had been\n * shared produced a SECOND view that reported itself as a published template \u2014\n * its `\u22EF` menu said \"Update shared template\u2026\" and the tab claimed a shelf\n * entry that does not exist, because duplicate never calls `applyToRoles` and\n * so writes no role rows at all. Every view is PRIVATE by default\n * (personalization model, 2026-08-03); publishing is an explicit act on the\n * copy, not something inherited from what it was copied from.\n *\n * `isBaseView` goes too: the base row owns the reserved `__base__` name and\n * there can only be one per user, so a copy carrying the flag would render as\n * a second \"Default view\".\n */\n const handlePerspectiveDuplicate = useCallback(\n async (payload: PerspectiveDuplicateEvent) => {\n if (!perspectivesTableId) return\n const settings = dynamicTableToApi({\n ...payload.perspective,\n name: payload.newName,\n isDefault: false,\n isBaseView: false,\n publication: undefined,\n })\n const response = await apiCall<PerspectiveSaveResponse>(`/api/perspectives/${perspectivesTableId}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ name: payload.newName, settings, isDefault: false }),\n })\n if (response.ok) {\n flash('View duplicated', 'success')\n queryClient.invalidateQueries({ queryKey: ['perspectives', perspectivesTableId] })\n const savedId = response.result?.perspective?.id\n if (savedId) setActivePerspectiveId(savedId)\n } else {\n flash(perspectiveWriteError(response, 'Failed to duplicate view'), 'error')\n }\n },\n [perspectivesTableId, queryClient]\n )\n\n /**\n * A4 \u2014 make a view this USER's default. `isDefault` is a first-class column\n * on the upstream entity scoped by `userId`; the service demotes the caller's\n * other views in one `nativeUpdate` and touches nobody else's rows.\n */\n const handlePerspectiveSetDefault = useCallback(\n async (payload: PerspectiveSetDefaultEvent) => {\n if (!perspectivesTableId) return\n const perspective = savedPerspectives.find((p) => p.id === payload.id)\n if (!perspective) return\n const settings = dynamicTableToApi(perspective)\n const response = await apiCall(`/api/perspectives/${perspectivesTableId}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n perspectiveId: payload.id,\n name: perspective.name,\n settings,\n isDefault: payload.isDefault,\n }),\n })\n if (response.ok) {\n flash('Default view updated', 'success')\n queryClient.invalidateQueries({ queryKey: ['perspectives', perspectivesTableId] })\n } else {\n flash('Failed to set the default view', 'error')\n }\n },\n [perspectivesTableId, savedPerspectives, queryClient]\n )\n\n /**\n * PUBLISH \u2014 make one of MY views copyable by colleagues.\n *\n * One POST does both halves, which is why it is one request and not two:\n * `applyToRoles` writes the role-scoped template rows, and the same call\n * re-saves the personal row with `_published` so the tab menu can say\n * \"Update shared template\" next time. `setRoleDefault` is pinned to `false`\n * \u2014 a template must never become anybody's default view. Publishing changes\n * nobody's screen; it only puts the view on the shelf.\n *\n * The template necessarily carries the view's own name: the upstream service\n * uses one `name` for both the personal row and the role rows, so allowing a\n * different template name here would silently RENAME the publisher's view.\n */\n const handlePerspectivePublish = useCallback(\n async (payload: PerspectivePublishEvent) => {\n if (!perspectivesTableId) return\n const perspective = savedPerspectives.find((p) => p.id === payload.id)\n if (!perspective || !payload.roleIds.length) return\n const settings = dynamicTableToApi({\n ...perspective,\n publication: { roleIds: payload.roleIds, publishedAt: new Date().toISOString() },\n })\n const response = await apiCall(`/api/perspectives/${perspectivesTableId}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n perspectiveId: payload.id,\n name: perspective.name,\n settings,\n applyToRoles: payload.roleIds,\n setRoleDefault: false,\n }),\n })\n if (response.ok) {\n flash('View shared as a template', 'success')\n queryClient.invalidateQueries({ queryKey: ['perspectives', perspectivesTableId] })\n } else {\n flash('Failed to share the view', 'error')\n }\n },\n [perspectivesTableId, savedPerspectives, queryClient],\n )\n\n /**\n * COPY A TEMPLATE \u2014 the only way a shared view reaches your screen.\n *\n * Writes a brand-new PERSONAL row (no `perspectiveId`), never the default,\n * carrying `_origin` = which template and which version it came from. That\n * record is what lets a later pass ask \"the shared template changed \u2014 update\n * yours?\" instead of the two silently diverging.\n */\n const handlePerspectiveTemplateCopy = useCallback(\n async (payload: PerspectiveTemplateCopyEvent) => {\n if (!perspectivesTableId) return\n const { template } = payload\n const settings = dynamicTableToApi({\n ...template,\n name: payload.newName,\n isDefault: false,\n isBaseView: false,\n publication: undefined,\n origin: {\n templateId: template.id,\n version: template.version,\n name: template.name,\n copiedAt: new Date().toISOString(),\n },\n })\n const response = await apiCall<PerspectiveSaveResponse>(`/api/perspectives/${perspectivesTableId}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ name: payload.newName, settings, isDefault: false }),\n })\n if (response.ok) {\n flash('Template copied to your views', 'success')\n queryClient.invalidateQueries({ queryKey: ['perspectives', perspectivesTableId] })\n const savedId = response.result?.perspective?.id\n if (savedId) setActivePerspectiveId(savedId)\n } else {\n flash(perspectiveWriteError(response, 'Failed to copy the template'), 'error')\n }\n },\n [perspectivesTableId, queryClient],\n )\n\n const handlePerspectiveDelete = useCallback(\n async (payload: PerspectiveDeleteEvent) => {\n if (!perspectivesTableId) return\n const url = payload.hardDelete\n ? `/api/perspectives/${perspectivesTableId}/${payload.id}?hardDelete=true`\n : `/api/perspectives/${perspectivesTableId}/${payload.id}`\n const response = await apiCall(url, { method: 'DELETE' })\n if (response.ok) {\n flash('Perspective deleted', 'success')\n queryClient.invalidateQueries({ queryKey: ['perspectives', perspectivesTableId] })\n if (activePerspectiveId === payload.id) {\n setActivePerspectiveId(null)\n setFilters([])\n setSortField(defaultSort?.field ?? 'id')\n setSortDir(defaultSort?.direction ?? 'asc')\n }\n } else {\n flash('Failed to delete perspective', 'error')\n }\n },\n [perspectivesTableId, activePerspectiveId, queryClient, defaultSort]\n )\n\n const handlePerspectiveChange = useCallback(\n (payload: PerspectiveChangeEvent) => {\n if (payload.config.lookupColumns) {\n setLookupColumns(payload.config.lookupColumns)\n setPage(1)\n }\n // Rollups do NOT reset the page \u2014 they add a column to the rows already\n // on screen, they do not change which rows those are.\n if (payload.config.rollupColumns) {\n setRollupColumns(payload.config.rollupColumns)\n }\n // Aggregations do NOT reset the page \u2014 they change what the footer says,\n // not which rows are shown.\n if (payload.config.aggregations) {\n setAggregations(payload.config.aggregations)\n }\n // Grouping and view mode are MIRRORED, never acted on: both are folds\n // over the rows already fetched, so neither changes the request and\n // neither may reset the page. Resetting on a grouping change would throw\n // the user back to page 1 for a purely visual regroup.\n if (payload.config.grouping) {\n setGrouping(payload.config.grouping)\n }\n if (payload.config.viewMode) {\n setViewMode(payload.config.viewMode)\n }\n if (payload.config.sorting) {\n if (payload.config.sorting.length > 0) {\n const firstSort = payload.config.sorting[0]\n setSortField(firstSort.field)\n setSortDir(firstSort.direction)\n } else {\n setSortField(defaultSort?.field ?? 'id')\n setSortDir(defaultSort?.direction ?? 'asc')\n }\n setPage(1)\n }\n },\n [defaultSort]\n )\n\n // \u2500\u2500 Register Event Handlers \u2500\u2500\n\n const eventHandlers = useMemo(() => {\n const handlers: Record<string, any> = {\n [TableEvents.COLUMN_SORT]: (payload: { columnName: string; direction: 'asc' | 'desc' | null }) => {\n setSortField(payload.columnName)\n setSortDir(payload.direction || 'asc')\n setPage(1)\n },\n [TableEvents.SEARCH]: (payload: { query: string }) => {\n setSearch(payload.query)\n setPage(1)\n },\n [TableEvents.FILTER_CHANGE]: (payload: { filters: FilterRow[] }) => {\n setFilters(payload.filters)\n setPage(1)\n },\n }\n\n if (config.cellEdit !== false) {\n handlers[TableEvents.CELL_EDIT_SAVE] = handleCellEditSave\n }\n\n if (config.create) {\n handlers[TableEvents.NEW_ROW_SAVE] = handleNewRowSave\n }\n\n if (perspectivesTableId) {\n handlers[TableEvents.PERSPECTIVE_SAVE] = handlePerspectiveSave\n handlers[TableEvents.PERSPECTIVE_SELECT] = handlePerspectiveSelect\n handlers[TableEvents.PERSPECTIVE_RENAME] = handlePerspectiveRename\n handlers[TableEvents.PERSPECTIVE_DELETE] = handlePerspectiveDelete\n handlers[TableEvents.PERSPECTIVE_CHANGE] = handlePerspectiveChange\n handlers[TableEvents.PERSPECTIVE_DUPLICATE] = handlePerspectiveDuplicate\n handlers[TableEvents.PERSPECTIVE_SET_DEFAULT] = handlePerspectiveSetDefault\n handlers[TableEvents.PERSPECTIVE_PUBLISH] = handlePerspectivePublish\n handlers[TableEvents.PERSPECTIVE_TEMPLATE_COPY] = handlePerspectiveTemplateCopy\n }\n\n return handlers\n }, [\n config.cellEdit,\n config.create,\n perspectivesTableId,\n handleCellEditSave,\n handleNewRowSave,\n handlePerspectiveSave,\n handlePerspectiveSelect,\n handlePerspectiveRename,\n handlePerspectiveDelete,\n handlePerspectiveChange,\n handlePerspectiveDuplicate,\n handlePerspectiveSetDefault,\n handlePerspectivePublish,\n handlePerspectiveTemplateCopy,\n ])\n\n useEventHandlers(eventHandlers, tableRef as React.RefObject<HTMLElement>)\n\n // \u2500\u2500 Filter Suggestions \u2500\u2500\n\n const customLoadFilterSuggestions = config.loadFilterSuggestions\n const loadFilterSuggestions = useMemo(() => {\n // An explicit loader wins: it is the only way a list can suggest values for\n // columns that aren't plain fields on its own entity table.\n if (customLoadFilterSuggestions) return customLoadFilterSuggestions\n if (!config.filterSuggestions) return undefined\n const entityType = config.filterSuggestions\n\n return async (field: string, query: string): Promise<string[]> => {\n try {\n const params = new URLSearchParams({ entityId: entityType, field, query: query || '' })\n const result = await apiCall<{ items: string[] }>(\n `/api/entities/filter-suggestions?${params.toString()}`,\n { credentials: 'include' }\n )\n if (!result.ok || !result.result) return []\n return result.result.items ?? []\n } catch {\n return []\n }\n }\n }, [config.filterSuggestions, customLoadFilterSuggestions])\n\n // \u2500\u2500 Build DynamicTable Props \u2500\u2500\n\n const pagination: PaginationProps = useMemo(\n () => ({\n currentPage: page,\n totalPages: Math.ceil((dataQuery.data?.total || 0) / limit),\n limit,\n total: dataQuery.data?.total ?? 0,\n limitOptions: [25, 50, 100],\n onPageChange: setPage,\n onLimitChange: (l: number) => {\n setLimit(l)\n setPage(1)\n },\n }),\n [page, limit, dataQuery.data?.total]\n )\n\n const dynamicTableProps: DynamicTableProps = useMemo(() => {\n const baseProps: DynamicTableProps = {\n tableRef,\n data: tableData,\n columns,\n tableName,\n // Stable identity for per-user column-width persistence. Reuse the\n // perspectives table id when present, else fall back to the entity source.\n tableId: storageTableId ?? `${storageScope}${source}`,\n idColumnName: idColumn,\n colHeaders: true,\n rowHeaders: true,\n pagination,\n // Read-only, for ONE thing: the in-grid finder's scope label says\n // \"\u2026in 100 loaded rows (filtered by \\\"abc\\\")\". Without it, a finder count\n // and a SearchBar filter can be conflated while both are active.\n // The EFFECTIVE needle, so the label names what actually narrowed the\n // rows \u2014 a workspace search when one is driving this pane, this pane's\n // own box otherwise (identical when no workspace is involved).\n searchQuery: effectiveSearch,\n onExportAll: exportAllRows,\n aggregateResult: aggregateQuery.data ?? null,\n aggregateLoading: aggregateQuery.isFetching,\n aggregateError: aggregateQuery.isError,\n // HEDGE-119 \u2014 carry the list query's FAILURE to the grid.\n //\n // `tableData` above collapses a rejected query to `[]` (there is no\n // `dataQuery.data` to read items off), so without this flag the grid\n // cannot tell \"the server refused\" from \"the server said zero rows\" and\n // paints `EmptyState` for both. That is how a 500 on the invoice queue\n // reached an accountant as the words \"Nothing here yet\".\n //\n // `placeholderData` keeps the PREVIOUS page's rows visible while a\n // refetch fails, so this is deliberately not `|| isError` on the whole\n // grid: rows we still hold are still shown, and the error state only\n // takes over the zero-row region, which is the case that lies.\n loadError: dataQuery.isError,\n onRetryLoad: () => { void dataQuery.refetch() },\n ...(perspectivesTableId\n ? {\n savedPerspectives,\n activePerspectiveId,\n // A4/A6 \u2014 which view opens by default FOR THIS USER. Comes straight\n // off the perspectives index (`isDefault` is scoped by `userId`), so\n // the star on the tab is a per-user fact, never an org-wide one.\n defaultPerspectiveId: perspectivesData?.defaultPerspectiveId ?? null,\n // Personal views + shared templates. `canPublishTemplates` is the\n // server's own answer (`perspectives.role_defaults`), not a guess:\n // a user without the feature never sees the publish affordance, and\n // the endpoint would 403 them anyway.\n sharedTemplates,\n canPublishTemplates: perspectivesData?.canApplyToRoles ?? false,\n publishableRoles: perspectivesData?.roles ?? [],\n }\n : {}),\n ...(loadFilterSuggestions ? { loadFilterSuggestions } : {}),\n ...(config.loadLookupSources ? { loadLookupSources: config.loadLookupSources } : {}),\n ...(config.loadRollupSources ? { loadRollupSources: config.loadRollupSources } : {}),\n ...(config.delete ? { onBulkDelete: requestBulkDelete } : {}),\n ...config.tableProps,\n // LAST, so it cannot be overridden: while a workspace search is driving\n // this pane, that pane's own search box is ignored (see `sharedSearch`).\n // Leaving it on screen would let a user type into a box that does\n // nothing \u2014 and the density argument for the bar only holds if the rows\n // it replaces actually go away. Absent `sharedSearch`, this spreads\n // nothing and `config.tableProps` still has the final word.\n ...(sharedSearch !== undefined ? { hideSearch: true } : {}),\n }\n\n return baseProps\n }, [\n tableData,\n columns,\n tableName,\n idColumn,\n pagination,\n effectiveSearch,\n exportAllRows,\n aggregateQuery.data,\n aggregateQuery.isFetching,\n aggregateQuery.isError,\n dataQuery.isError,\n dataQuery.refetch,\n perspectivesTableId,\n source,\n savedPerspectives,\n activePerspectiveId,\n perspectivesData?.defaultPerspectiveId,\n perspectivesData?.canApplyToRoles,\n perspectivesData?.roles,\n sharedTemplates,\n loadFilterSuggestions,\n config.loadLookupSources,\n config.loadRollupSources,\n config.delete,\n requestBulkDelete,\n config.tableProps,\n sharedSearch,\n ])\n\n // \u2500\u2500 Delete Dialog Props \u2500\u2500\n\n const deleteConfig = config.delete\n const dialogConfig = useMemo(() => {\n if (!deleteConfig) return null\n if (typeof deleteConfig === 'object' && typeof deleteConfig !== 'boolean') {\n return deleteConfig as DynamicTablePageDeleteConfig\n }\n return {} as DynamicTablePageDeleteConfig\n }, [deleteConfig])\n\n const cancelDelete = useCallback(() => setPendingDelete(null), [])\n\n // Return JSX element (not a component) so the Dialog's element type is always\n // TableDeleteDialog \u2014 React keeps it mounted across state changes, preserving\n // animation state. Using a component (function) would cause unmount/remount on\n // every dep change since the function identity changes.\n const deleteDialog = dialogConfig ? (\n <>\n <TableDeleteDialog\n row={pendingDelete}\n isDeleting={isDeleting}\n onConfirm={handleConfirmDelete}\n onCancel={cancelDelete}\n restoreFocusRef={tableRef}\n title={dialogConfig.title}\n description={dialogConfig.description}\n nameColumn={dialogConfig.nameColumn}\n />\n <TableDeleteDialog\n row={pendingBulkDelete ? ({ count: pendingBulkDelete.length } as TRow) : null}\n isDeleting={isDeleting}\n onConfirm={handleConfirmBulkDelete}\n onCancel={cancelBulkDelete}\n restoreFocusRef={tableRef}\n title={(row: any) => `Delete ${row?.count ?? ''} ${tableName}`.replace(/\\s+/g, ' ').trim()}\n description={(row: any) =>\n `Are you sure you want to delete ${row?.count ?? 'these'} selected items? This action cannot be undone.`}\n />\n </>\n ) : null\n\n return {\n props: dynamicTableProps,\n deleteDialog,\n setRowToDelete: setPendingDelete,\n query: dataQuery,\n aggregateResult: aggregateQuery.data ?? null,\n aggregateLoading: aggregateQuery.isFetching,\n aggregateError: aggregateQuery.isError,\n // HEDGE-119 \u2014 hosts that render their own body (split views, card modes)\n // need the same signal the grid now gets, so they can refuse to draw an\n // \"empty\" affordance over a request that never landed.\n isError: dataQuery.isError,\n // `!perspectiveHydrated` counts as loading. TanStack reports `isLoading`\n // false while a query is DISABLED (it is pending but not fetching), so\n // without this the host would drop its skeleton and paint an empty grid for\n // the one frame the list is waiting on the perspective.\n isLoading: (!perspectiveHydrated || dataQuery.isLoading) && !dataQuery.data,\n refresh: () => invalidateListNow(),\n state: { page, limit, search, filters, sortField, sortDir, grouping, viewMode },\n }\n}\n\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,32 @@
1
+ import { useEffect, useRef } from "react";
2
+ const layerStack = [];
3
+ function useEscapeLayer(active, onDismiss) {
4
+ const dismissRef = useRef(onDismiss);
5
+ dismissRef.current = onDismiss;
6
+ useEffect(() => {
7
+ if (!active) return;
8
+ if (typeof window === "undefined") return;
9
+ const id = Symbol("escape-layer");
10
+ layerStack.push(id);
11
+ const onKeyDown = (e) => {
12
+ if (e.key !== "Escape") return;
13
+ if (layerStack[layerStack.length - 1] !== id) return;
14
+ e.preventDefault();
15
+ e.stopPropagation();
16
+ e.stopImmediatePropagation();
17
+ dismissRef.current();
18
+ };
19
+ window.addEventListener("keydown", onKeyDown, true);
20
+ return () => {
21
+ window.removeEventListener("keydown", onKeyDown, true);
22
+ const index = layerStack.indexOf(id);
23
+ if (index >= 0) layerStack.splice(index, 1);
24
+ };
25
+ }, [active]);
26
+ }
27
+ var useEscapeLayer_default = useEscapeLayer;
28
+ export {
29
+ useEscapeLayer_default as default,
30
+ useEscapeLayer
31
+ };
32
+ //# sourceMappingURL=useEscapeLayer.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/backend/dynamic-table/hooks/useEscapeLayer.ts"],
4
+ "sourcesContent": ["import { useEffect, useRef } from 'react';\n\n/**\n * Escape must close the INNERMOST open layer, and only that one.\n *\n * Why this cannot be done with a plain `document` listener plus\n * `stopPropagation` (which is what every popup in this folder used to do, and\n * why Escape inside a Configure View dropdown tore the whole drawer down):\n *\n * Radix's `DismissableLayer` \u2014 the Sheet the Configure View panel renders in,\n * and every Dialog in the app \u2014 closes on Escape via\n * `ownerDocument.addEventListener('keydown', handler, { capture: true })`.\n * That listener is registered when the SHEET mounts, i.e. strictly before any\n * dropdown inside it opens. Capture listeners on the same node fire in\n * registration order, so Radix always ran first and the drawer was already\n * closing by the time the dropdown's own handler saw the key. `stopPropagation`\n * from a later listener on the same node cannot undo that.\n *\n * Two things fix it:\n *\n * 1. Listen on `window`, in the capture phase. `window` is the outermost node\n * of the propagation path, so a capture listener there runs BEFORE any\n * capture listener on `document` \u2014 including Radix's. `stopPropagation()`\n * then keeps the event from ever reaching `document`.\n *\n * 2. A module-level layer stack, because (1) alone inverts the nesting: window\n * capture listeners also fire in registration order, so the OUTERMOST layer\n * would win. Each active layer pushes an id; a handler that is not on top of\n * the stack returns without consuming the key, letting the innermost layer\n * handle it.\n *\n * A layer registered through this hook therefore swallows Escape only while it\n * is the top layer, and leaves it alone otherwise \u2014 so Escape with no dropdown\n * open still closes the drawer, as it should.\n */\nconst layerStack: symbol[] = [];\n\nexport function useEscapeLayer(active: boolean, onDismiss: () => void): void {\n // Held in a ref so a fresh `onDismiss` identity each render does not\n // re-register the listener (which would reorder the stack).\n const dismissRef = useRef(onDismiss);\n dismissRef.current = onDismiss;\n\n useEffect(() => {\n if (!active) return;\n if (typeof window === 'undefined') return;\n\n const id = Symbol('escape-layer');\n layerStack.push(id);\n\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key !== 'Escape') return;\n // Not the innermost layer \u2014 let the one above us take it.\n if (layerStack[layerStack.length - 1] !== id) return;\n e.preventDefault();\n e.stopPropagation();\n // `stopPropagation` alone still lets other listeners on `window` itself\n // run; the immediate variant is what guarantees exclusivity.\n e.stopImmediatePropagation();\n dismissRef.current();\n };\n\n window.addEventListener('keydown', onKeyDown, true);\n return () => {\n window.removeEventListener('keydown', onKeyDown, true);\n const index = layerStack.indexOf(id);\n if (index >= 0) layerStack.splice(index, 1);\n };\n }, [active]);\n}\n\nexport default useEscapeLayer;\n"],
5
+ "mappings": "AAAA,SAAS,WAAW,cAAc;AAmClC,MAAM,aAAuB,CAAC;AAEvB,SAAS,eAAe,QAAiB,WAA6B;AAG3E,QAAM,aAAa,OAAO,SAAS;AACnC,aAAW,UAAU;AAErB,YAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,QAAI,OAAO,WAAW,YAAa;AAEnC,UAAM,KAAK,OAAO,cAAc;AAChC,eAAW,KAAK,EAAE;AAElB,UAAM,YAAY,CAAC,MAAqB;AACtC,UAAI,EAAE,QAAQ,SAAU;AAExB,UAAI,WAAW,WAAW,SAAS,CAAC,MAAM,GAAI;AAC9C,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAGlB,QAAE,yBAAyB;AAC3B,iBAAW,QAAQ;AAAA,IACrB;AAEA,WAAO,iBAAiB,WAAW,WAAW,IAAI;AAClD,WAAO,MAAM;AACX,aAAO,oBAAoB,WAAW,WAAW,IAAI;AACrD,YAAM,QAAQ,WAAW,QAAQ,EAAE;AACnC,UAAI,SAAS,EAAG,YAAW,OAAO,OAAO,CAAC;AAAA,IAC5C;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AACb;AAEA,IAAO,yBAAQ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,256 @@
1
+ import { useState, useMemo, useCallback } from "react";
2
+ function parseNumeric(v) {
3
+ if (typeof v === "number") return Number.isFinite(v) ? v : null;
4
+ if (typeof v === "bigint") return Number(v);
5
+ if (typeof v === "boolean") return v ? 1 : 0;
6
+ if (typeof v !== "string") return null;
7
+ const s = v.trim();
8
+ if (!s) return null;
9
+ const n = Number(s);
10
+ return Number.isFinite(n) ? n : null;
11
+ }
12
+ function parseDateValue(v) {
13
+ if (v instanceof Date) {
14
+ const t2 = v.getTime();
15
+ return Number.isNaN(t2) ? null : t2;
16
+ }
17
+ if (typeof v === "number") return Number.isFinite(v) ? v : null;
18
+ if (typeof v !== "string") return null;
19
+ const s = v.trim();
20
+ if (!s) return null;
21
+ const t = Date.parse(s);
22
+ return Number.isNaN(t) ? null : t;
23
+ }
24
+ function isPresent(v) {
25
+ return v !== null && v !== void 0 && v !== "";
26
+ }
27
+ function applyAggregation(data, indices, field, fn, column) {
28
+ if (fn === "count") {
29
+ let n = 0;
30
+ for (const idx of indices) if (isPresent(data[idx]?.[field])) n += 1;
31
+ return n;
32
+ }
33
+ if (fn === "countDistinct") {
34
+ const seen = /* @__PURE__ */ new Set();
35
+ for (const idx of indices) {
36
+ const v = data[idx]?.[field];
37
+ if (isPresent(v)) seen.add(String(v));
38
+ }
39
+ return seen.size;
40
+ }
41
+ const asDate = column?.type === "date" && (fn === "min" || fn === "max");
42
+ const parse = asDate ? parseDateValue : parseNumeric;
43
+ const nums = [];
44
+ for (const idx of indices) {
45
+ const n = parse(data[idx]?.[field]);
46
+ if (n !== null) nums.push(n);
47
+ }
48
+ switch (fn) {
49
+ case "sum": {
50
+ let acc = 0;
51
+ for (const n of nums) acc += n;
52
+ return acc;
53
+ }
54
+ case "avg": {
55
+ if (nums.length === 0) return null;
56
+ let acc = 0;
57
+ for (const n of nums) acc += n;
58
+ return acc / nums.length;
59
+ }
60
+ case "min":
61
+ return nums.length === 0 ? null : Math.min(...nums);
62
+ case "max":
63
+ return nums.length === 0 ? null : Math.max(...nums);
64
+ default:
65
+ return null;
66
+ }
67
+ }
68
+ function applyAggregationByDimension(data, indices, field, fn, dimension, column) {
69
+ const buckets = /* @__PURE__ */ new Map();
70
+ for (const idx of indices) {
71
+ const raw = data[idx]?.[dimension];
72
+ const key = raw === null || raw === void 0 ? "" : String(raw);
73
+ const bucket = buckets.get(key);
74
+ if (bucket) bucket.push(idx);
75
+ else buckets.set(key, [idx]);
76
+ }
77
+ const out = [];
78
+ for (const [key, memberIndices] of buckets) {
79
+ out.push({ key, value: applyAggregation(data, memberIndices, field, fn, column) });
80
+ }
81
+ return out;
82
+ }
83
+ function computeAggregates(data, indices, aggregations, columnsByField) {
84
+ const values = {};
85
+ const fns = {};
86
+ const breakdowns = {};
87
+ for (const rule of aggregations) {
88
+ const column = columnsByField.get(rule.field);
89
+ values[rule.field] = applyAggregation(data, indices, rule.field, rule.fn, column);
90
+ fns[rule.field] = rule.fn;
91
+ if (rule.dimension) {
92
+ breakdowns[rule.field] = applyAggregationByDimension(
93
+ data,
94
+ indices,
95
+ rule.field,
96
+ rule.fn,
97
+ rule.dimension,
98
+ column
99
+ );
100
+ }
101
+ }
102
+ return { values, fns, breakdowns };
103
+ }
104
+ const EMPTY_GROUP_VALUE = "(Empty)";
105
+ function getGroupValue(row, field) {
106
+ const value = row[field];
107
+ if (value === null || value === void 0 || value === "") {
108
+ return EMPTY_GROUP_VALUE;
109
+ }
110
+ return String(value);
111
+ }
112
+ function buildGroupKey(depth, field, value, parentKey) {
113
+ return parentKey ? `${parentKey}|${field}:${value}` : `${field}:${value}`;
114
+ }
115
+ function useGrouping(data, groupRules, columns, aggregations = [], options = {}) {
116
+ const [collapsedGroups, setCollapsedGroups] = useState(/* @__PURE__ */ new Set());
117
+ const { totalRows } = options;
118
+ const aggregateScope = typeof totalRows === "number" && Number.isFinite(totalRows) && totalRows <= data.length ? "dataset" : "page";
119
+ const columnsByField = useMemo(() => {
120
+ const map = /* @__PURE__ */ new Map();
121
+ for (const col of columns) map.set(col.data, col);
122
+ return map;
123
+ }, [columns]);
124
+ const toggleGroup = useCallback((groupKey) => {
125
+ setCollapsedGroups((prev) => {
126
+ const next = new Set(prev);
127
+ if (next.has(groupKey)) {
128
+ next.delete(groupKey);
129
+ } else {
130
+ next.add(groupKey);
131
+ }
132
+ return next;
133
+ });
134
+ }, []);
135
+ const toggleAllGroups = useCallback((collapsed) => {
136
+ if (!collapsed) {
137
+ setCollapsedGroups(/* @__PURE__ */ new Set());
138
+ } else {
139
+ setCollapsedGroups((prev) => {
140
+ const allKeys = new Set(prev);
141
+ allKeys.add("__collapse_all__");
142
+ return allKeys;
143
+ });
144
+ }
145
+ }, []);
146
+ const visualRows = useMemo(() => {
147
+ if (groupRules.length === 0) return null;
148
+ const result = [];
149
+ const allGroupKeys = [];
150
+ function buildGroups(indices, rules, depth, parentKey) {
151
+ if (rules.length === 0) {
152
+ for (const idx of indices) {
153
+ result.push({ type: "dataRow", dataIndex: idx });
154
+ }
155
+ return;
156
+ }
157
+ const [currentRule, ...remainingRules] = rules;
158
+ const field = currentRule.field;
159
+ const groups = /* @__PURE__ */ new Map();
160
+ for (const idx of indices) {
161
+ const value = getGroupValue(data[idx], field);
162
+ if (!groups.has(value)) {
163
+ groups.set(value, []);
164
+ }
165
+ groups.get(value).push(idx);
166
+ }
167
+ const sortedKeys = [...groups.keys()].sort((a, b) => {
168
+ if (a === EMPTY_GROUP_VALUE) return 1;
169
+ if (b === EMPTY_GROUP_VALUE) return -1;
170
+ const cmp = a.localeCompare(b, void 0, { numeric: true, sensitivity: "base" });
171
+ return currentRule.direction === "desc" ? -cmp : cmp;
172
+ });
173
+ for (const value of sortedKeys) {
174
+ const groupIndices = groups.get(value);
175
+ const groupKey = buildGroupKey(depth, field, value, parentKey);
176
+ allGroupKeys.push(groupKey);
177
+ const isCollapsed = collapsedGroups.has(groupKey);
178
+ result.push({
179
+ type: "groupHeader",
180
+ groupKey,
181
+ field,
182
+ value,
183
+ count: groupIndices.length,
184
+ depth,
185
+ collapsed: isCollapsed,
186
+ memberDataIndices: groupIndices
187
+ });
188
+ if (!isCollapsed) {
189
+ if (aggregations.length > 0) {
190
+ const { values, fns, breakdowns } = computeAggregates(
191
+ data,
192
+ groupIndices,
193
+ aggregations,
194
+ columnsByField
195
+ );
196
+ result.push({
197
+ type: "groupSummary",
198
+ groupKey,
199
+ depth,
200
+ values,
201
+ fns,
202
+ breakdowns,
203
+ scope: aggregateScope,
204
+ rowsCovered: groupIndices.length
205
+ });
206
+ }
207
+ buildGroups(groupIndices, remainingRules, depth + 1, groupKey);
208
+ }
209
+ }
210
+ }
211
+ const allIndices = Array.from({ length: data.length }, (_, i) => i);
212
+ buildGroups(allIndices, groupRules, 0, "");
213
+ if (collapsedGroups.has("__collapse_all__")) {
214
+ setCollapsedGroups(new Set(allGroupKeys));
215
+ }
216
+ return result;
217
+ }, [data, groupRules, collapsedGroups, aggregations, columnsByField, aggregateScope]);
218
+ const dataIndexToVisualIndex = useCallback((dataIndex) => {
219
+ if (!visualRows) return dataIndex;
220
+ for (let i = 0; i < visualRows.length; i++) {
221
+ const vr = visualRows[i];
222
+ if (vr.type === "dataRow" && vr.dataIndex === dataIndex) {
223
+ return i;
224
+ }
225
+ }
226
+ return dataIndex;
227
+ }, [visualRows]);
228
+ const groupKeyByDataIndex = useMemo(() => {
229
+ if (!visualRows) return null;
230
+ const map = /* @__PURE__ */ new Map();
231
+ for (const vr of visualRows) {
232
+ if (vr.type !== "groupHeader") continue;
233
+ for (const dataIndex of vr.memberDataIndices) map.set(dataIndex, vr.groupKey);
234
+ }
235
+ return map;
236
+ }, [visualRows]);
237
+ const groupKeyOfDataIndex = useCallback(
238
+ (dataIndex) => groupKeyByDataIndex?.get(dataIndex) ?? null,
239
+ [groupKeyByDataIndex]
240
+ );
241
+ return {
242
+ visualRows,
243
+ collapsedGroups,
244
+ toggleGroup,
245
+ toggleAllGroups,
246
+ dataIndexToVisualIndex,
247
+ groupKeyOfDataIndex,
248
+ aggregateScope
249
+ };
250
+ }
251
+ export {
252
+ EMPTY_GROUP_VALUE,
253
+ computeAggregates,
254
+ useGrouping
255
+ };
256
+ //# sourceMappingURL=useGrouping.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/backend/dynamic-table/hooks/useGrouping.ts"],
4
+ "sourcesContent": ["import { useState, useMemo, useCallback } from 'react';\nimport type { ColumnDef } from '../types/index';\nimport type {\n GroupRule,\n AggregationRule,\n AggregationFn,\n AggregateBreakdownEntry,\n AggregateScope,\n VisualRow,\n} from '../types/grouping';\n\nexport interface UseGroupingOptions {\n /**\n * Total number of rows in the FILTERED DATASET, as reported by the server.\n *\n * Grouping folds over `data`, which is one server page (`pageSize <= 100`).\n * Without this the hook cannot know whether the page it holds is the whole\n * dataset, so every subtotal is labelled `'page'` \u2014 the conservative, honest\n * answer. Pass the list's `total` and a single-page result is correctly\n * labelled `'dataset'`.\n */\n totalRows?: number;\n}\n\nexport interface UseGroupingResult {\n visualRows: VisualRow[] | null;\n collapsedGroups: Set<string>;\n toggleGroup: (groupKey: string) => void;\n toggleAllGroups: (collapsed: boolean) => void;\n dataIndexToVisualIndex: (dataIndex: number) => number;\n /**\n * The key of the group a data row belongs to, or `null` when grouping is off.\n *\n * Exists because `dataIndexToVisualIndex` returns the raw `dataIndex` when the\n * row is not visible \u2014 a sensible fallback for scrolling, and silently WRONG\n * for a row hidden inside a collapsed group. A caller that wants to reveal a\n * row (the in-grid finder does) calls `toggleGroup(groupKeyOfDataIndex(i))`\n * first, so matches inside collapsed groups are found, counted, and expanded\n * on navigation rather than scrolled to the wrong place.\n */\n groupKeyOfDataIndex: (dataIndex: number) => string | null;\n /**\n * What every subtotal emitted by this hook covers. `'page'` unless the caller\n * proved via `totalRows` that the loaded page is the entire filtered dataset.\n * The UI must render this; an unlabelled subtotal is the defect.\n */\n aggregateScope: AggregateScope;\n}\n\n/** Parse a cell value to a number, or `null` when it isn't one. */\nfunction parseNumeric(v: unknown): number | null {\n if (typeof v === 'number') return Number.isFinite(v) ? v : null;\n if (typeof v === 'bigint') return Number(v);\n if (typeof v === 'boolean') return v ? 1 : 0;\n if (typeof v !== 'string') return null;\n const s = v.trim();\n if (!s) return null;\n const n = Number(s);\n return Number.isFinite(n) ? n : null;\n}\n\n/** Parse a cell value to epoch milliseconds, or `null`. */\nfunction parseDateValue(v: unknown): number | null {\n if (v instanceof Date) {\n const t = v.getTime();\n return Number.isNaN(t) ? null : t;\n }\n if (typeof v === 'number') return Number.isFinite(v) ? v : null;\n if (typeof v !== 'string') return null;\n const s = v.trim();\n if (!s) return null;\n const t = Date.parse(s);\n return Number.isNaN(t) ? null : t;\n}\n\n/** Non-empty for COUNT / COUNT(DISTINCT) purposes \u2014 mirrors SQL NULL semantics. */\nfunction isPresent(v: unknown): boolean {\n return v !== null && v !== undefined && v !== '';\n}\n\n/**\n * Apply one aggregation function over a group's member rows.\n *\n * Semantics track SQL (and Excel) so the client fold and the server aggregate\n * cannot disagree: text is ignored by the numeric functions rather than\n * counted as zero, and an empty input yields `null` for everything except\n * `sum` (0) and the counts (0).\n */\nfunction applyAggregation(\n data: any[],\n indices: number[],\n field: string,\n fn: AggregationFn,\n column?: ColumnDef,\n): number | null {\n if (fn === 'count') {\n let n = 0;\n for (const idx of indices) if (isPresent(data[idx]?.[field])) n += 1;\n return n;\n }\n\n if (fn === 'countDistinct') {\n const seen = new Set<string>();\n for (const idx of indices) {\n const v = data[idx]?.[field];\n if (isPresent(v)) seen.add(String(v));\n }\n return seen.size;\n }\n\n // MIN/MAX on a date column compare chronologically and return epoch ms.\n const asDate = column?.type === 'date' && (fn === 'min' || fn === 'max');\n const parse = asDate ? parseDateValue : parseNumeric;\n\n const nums: number[] = [];\n for (const idx of indices) {\n const n = parse(data[idx]?.[field]);\n if (n !== null) nums.push(n);\n }\n\n switch (fn) {\n case 'sum': {\n // Empty set sums to 0 \u2014 an empty column reads as \"nothing\", not \"unknown\".\n let acc = 0;\n for (const n of nums) acc += n;\n return acc;\n }\n case 'avg': {\n if (nums.length === 0) return null;\n let acc = 0;\n for (const n of nums) acc += n;\n return acc / nums.length;\n }\n case 'min':\n return nums.length === 0 ? null : Math.min(...nums);\n case 'max':\n return nums.length === 0 ? null : Math.max(...nums);\n default:\n return null;\n }\n}\n\n/**\n * Partition `indices` by the value of `dimension`, then aggregate each slice\n * with the SAME `applyAggregation` the scalar path uses.\n *\n * Slices come back in first-seen row order rather than sorted, so the breakdown\n * reads in the order the grid already presents.\n */\nfunction applyAggregationByDimension(\n data: any[],\n indices: number[],\n field: string,\n fn: AggregationFn,\n dimension: string,\n column?: ColumnDef,\n): AggregateBreakdownEntry[] {\n const buckets = new Map<string, number[]>();\n for (const idx of indices) {\n const raw = data[idx]?.[dimension];\n const key = raw === null || raw === undefined ? '' : String(raw);\n const bucket = buckets.get(key);\n if (bucket) bucket.push(idx);\n else buckets.set(key, [idx]);\n }\n const out: AggregateBreakdownEntry[] = [];\n for (const [key, memberIndices] of buckets) {\n out.push({ key, value: applyAggregation(data, memberIndices, field, fn, column) });\n }\n return out;\n}\n\n/**\n * Fold the configured aggregations over a set of row indices.\n *\n * EXPORTED because the footer-totals row needs the identical fold for its\n * page-scoped fallback (shown until the server's dataset figure lands). Two\n * folds would disagree the first time one of them was widened \u2014 which is\n * exactly the bug `AGGREGATION_FNS` was introduced to end one level up.\n *\n * A rule carrying a `dimension` additionally yields a per-dimension breakdown.\n * The scalar is still computed and returned for that field so that nothing\n * downstream sees a hole, but the renderers prefer the breakdown \u2014 for a\n * dimensioned rule the scalar is the very number that is not safe to show\n * (HEDGE-147).\n */\nexport function computeAggregates(\n data: any[],\n indices: number[],\n aggregations: AggregationRule[],\n columnsByField: Map<string, ColumnDef>,\n): {\n values: Record<string, number | null>;\n fns: Record<string, AggregationFn>;\n breakdowns: Record<string, AggregateBreakdownEntry[]>;\n} {\n const values: Record<string, number | null> = {};\n const fns: Record<string, AggregationFn> = {};\n const breakdowns: Record<string, AggregateBreakdownEntry[]> = {};\n for (const rule of aggregations) {\n const column = columnsByField.get(rule.field);\n values[rule.field] = applyAggregation(data, indices, rule.field, rule.fn, column);\n fns[rule.field] = rule.fn;\n if (rule.dimension) {\n breakdowns[rule.field] = applyAggregationByDimension(\n data,\n indices,\n rule.field,\n rule.fn,\n rule.dimension,\n column,\n );\n }\n }\n return { values, fns, breakdowns };\n}\n\n/**\n * The label a group of rows with NO value gets.\n *\n * Exported because a renderer that wants to say something domain-specific about\n * the empty group (\"No case\", \"Unassigned\") has to be able to RECOGNISE it, and\n * a hard-coded string compared against a hard-coded string in another package is\n * the kind of coupling that breaks silently the day one of them is translated.\n */\nexport const EMPTY_GROUP_VALUE = '(Empty)';\n\nfunction getGroupValue(row: any, field: string): string {\n const value = row[field];\n if (value === null || value === undefined || value === '') {\n return EMPTY_GROUP_VALUE;\n }\n return String(value);\n}\n\nfunction buildGroupKey(depth: number, field: string, value: string, parentKey: string): string {\n return parentKey ? `${parentKey}|${field}:${value}` : `${field}:${value}`;\n}\n\nexport function useGrouping(\n data: any[],\n groupRules: GroupRule[],\n columns: ColumnDef[],\n aggregations: AggregationRule[] = [],\n options: UseGroupingOptions = {},\n): UseGroupingResult {\n const [collapsedGroups, setCollapsedGroups] = useState<Set<string>>(new Set());\n const { totalRows } = options;\n\n // The loaded page is the whole dataset only when the server told us how many\n // rows match and that number is already in `data`. Unknown coverage is\n // reported as `'page'`: understating what a number covers is safe, and\n // overstating it is exactly the bug this replaces.\n const aggregateScope: AggregateScope =\n typeof totalRows === 'number' && Number.isFinite(totalRows) && totalRows <= data.length\n ? 'dataset'\n : 'page';\n\n const columnsByField = useMemo(() => {\n const map = new Map<string, ColumnDef>();\n for (const col of columns) map.set(col.data, col);\n return map;\n }, [columns]);\n\n const toggleGroup = useCallback((groupKey: string) => {\n setCollapsedGroups(prev => {\n const next = new Set(prev);\n if (next.has(groupKey)) {\n next.delete(groupKey);\n } else {\n next.add(groupKey);\n }\n return next;\n });\n }, []);\n\n const toggleAllGroups = useCallback((collapsed: boolean) => {\n if (!collapsed) {\n setCollapsedGroups(new Set());\n } else {\n // Collapse all \u2014 we'll compute the keys in the visualRows memo\n setCollapsedGroups(prev => {\n const allKeys = new Set(prev);\n // Mark a sentinel so the memo knows to collect all group keys\n allKeys.add('__collapse_all__');\n return allKeys;\n });\n }\n }, []);\n\n const visualRows = useMemo(() => {\n if (groupRules.length === 0) return null;\n\n const result: VisualRow[] = [];\n const allGroupKeys: string[] = [];\n\n // Build groups recursively\n function buildGroups(\n indices: number[],\n rules: GroupRule[],\n depth: number,\n parentKey: string,\n ) {\n if (rules.length === 0) {\n // Leaf level \u2014 emit data rows\n for (const idx of indices) {\n result.push({ type: 'dataRow', dataIndex: idx });\n }\n return;\n }\n\n const [currentRule, ...remainingRules] = rules;\n const field = currentRule.field;\n\n // Group by field value\n const groups = new Map<string, number[]>();\n for (const idx of indices) {\n const value = getGroupValue(data[idx], field);\n if (!groups.has(value)) {\n groups.set(value, []);\n }\n groups.get(value)!.push(idx);\n }\n\n // Sort group keys\n const sortedKeys = [...groups.keys()].sort((a, b) => {\n // \"(Empty)\" always last\n if (a === EMPTY_GROUP_VALUE) return 1;\n if (b === EMPTY_GROUP_VALUE) return -1;\n const cmp = a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' });\n return currentRule.direction === 'desc' ? -cmp : cmp;\n });\n\n for (const value of sortedKeys) {\n const groupIndices = groups.get(value)!;\n const groupKey = buildGroupKey(depth, field, value, parentKey);\n allGroupKeys.push(groupKey);\n\n const isCollapsed = collapsedGroups.has(groupKey);\n\n result.push({\n type: 'groupHeader',\n groupKey,\n field,\n value,\n count: groupIndices.length,\n depth,\n collapsed: isCollapsed,\n memberDataIndices: groupIndices,\n });\n\n if (!isCollapsed) {\n // Subtotal row at every level \u2014 sits directly under the group header,\n // above the group's rows / nested groups.\n if (aggregations.length > 0) {\n const { values, fns, breakdowns } = computeAggregates(\n data,\n groupIndices,\n aggregations,\n columnsByField,\n );\n result.push({\n type: 'groupSummary',\n groupKey,\n depth,\n values,\n fns,\n breakdowns,\n scope: aggregateScope,\n rowsCovered: groupIndices.length,\n });\n }\n\n buildGroups(groupIndices, remainingRules, depth + 1, groupKey);\n }\n }\n }\n\n // Create array of all data indices\n const allIndices = Array.from({ length: data.length }, (_, i) => i);\n buildGroups(allIndices, groupRules, 0, '');\n\n // Handle \"collapse all\" sentinel\n if (collapsedGroups.has('__collapse_all__')) {\n setCollapsedGroups(new Set(allGroupKeys));\n }\n\n return result;\n }, [data, groupRules, collapsedGroups, aggregations, columnsByField, aggregateScope]);\n\n const dataIndexToVisualIndex = useCallback((dataIndex: number): number => {\n if (!visualRows) return dataIndex;\n for (let i = 0; i < visualRows.length; i++) {\n const vr = visualRows[i];\n if (vr.type === 'dataRow' && vr.dataIndex === dataIndex) {\n return i;\n }\n }\n return dataIndex;\n }, [visualRows]);\n\n // Built from `memberDataIndices`, which every group header already carries \u2014\n // the lookup is derived, never a second source of truth about membership.\n const groupKeyByDataIndex = useMemo(() => {\n if (!visualRows) return null;\n const map = new Map<number, string>();\n for (const vr of visualRows) {\n if (vr.type !== 'groupHeader') continue;\n for (const dataIndex of vr.memberDataIndices) map.set(dataIndex, vr.groupKey);\n }\n return map;\n }, [visualRows]);\n\n const groupKeyOfDataIndex = useCallback(\n (dataIndex: number): string | null => groupKeyByDataIndex?.get(dataIndex) ?? null,\n [groupKeyByDataIndex],\n );\n\n return {\n visualRows,\n collapsedGroups,\n toggleGroup,\n toggleAllGroups,\n dataIndexToVisualIndex,\n groupKeyOfDataIndex,\n aggregateScope,\n };\n}\n"],
5
+ "mappings": "AAAA,SAAS,UAAU,SAAS,mBAAmB;AAkD/C,SAAS,aAAa,GAA2B;AAC/C,MAAI,OAAO,MAAM,SAAU,QAAO,OAAO,SAAS,CAAC,IAAI,IAAI;AAC3D,MAAI,OAAO,MAAM,SAAU,QAAO,OAAO,CAAC;AAC1C,MAAI,OAAO,MAAM,UAAW,QAAO,IAAI,IAAI;AAC3C,MAAI,OAAO,MAAM,SAAU,QAAO;AAClC,QAAM,IAAI,EAAE,KAAK;AACjB,MAAI,CAAC,EAAG,QAAO;AACf,QAAM,IAAI,OAAO,CAAC;AAClB,SAAO,OAAO,SAAS,CAAC,IAAI,IAAI;AAClC;AAGA,SAAS,eAAe,GAA2B;AACjD,MAAI,aAAa,MAAM;AACrB,UAAMA,KAAI,EAAE,QAAQ;AACpB,WAAO,OAAO,MAAMA,EAAC,IAAI,OAAOA;AAAA,EAClC;AACA,MAAI,OAAO,MAAM,SAAU,QAAO,OAAO,SAAS,CAAC,IAAI,IAAI;AAC3D,MAAI,OAAO,MAAM,SAAU,QAAO;AAClC,QAAM,IAAI,EAAE,KAAK;AACjB,MAAI,CAAC,EAAG,QAAO;AACf,QAAM,IAAI,KAAK,MAAM,CAAC;AACtB,SAAO,OAAO,MAAM,CAAC,IAAI,OAAO;AAClC;AAGA,SAAS,UAAU,GAAqB;AACtC,SAAO,MAAM,QAAQ,MAAM,UAAa,MAAM;AAChD;AAUA,SAAS,iBACP,MACA,SACA,OACA,IACA,QACe;AACf,MAAI,OAAO,SAAS;AAClB,QAAI,IAAI;AACR,eAAW,OAAO,QAAS,KAAI,UAAU,KAAK,GAAG,IAAI,KAAK,CAAC,EAAG,MAAK;AACnE,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,iBAAiB;AAC1B,UAAM,OAAO,oBAAI,IAAY;AAC7B,eAAW,OAAO,SAAS;AACzB,YAAM,IAAI,KAAK,GAAG,IAAI,KAAK;AAC3B,UAAI,UAAU,CAAC,EAAG,MAAK,IAAI,OAAO,CAAC,CAAC;AAAA,IACtC;AACA,WAAO,KAAK;AAAA,EACd;AAGA,QAAM,SAAS,QAAQ,SAAS,WAAW,OAAO,SAAS,OAAO;AAClE,QAAM,QAAQ,SAAS,iBAAiB;AAExC,QAAM,OAAiB,CAAC;AACxB,aAAW,OAAO,SAAS;AACzB,UAAM,IAAI,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC;AAClC,QAAI,MAAM,KAAM,MAAK,KAAK,CAAC;AAAA,EAC7B;AAEA,UAAQ,IAAI;AAAA,IACV,KAAK,OAAO;AAEV,UAAI,MAAM;AACV,iBAAW,KAAK,KAAM,QAAO;AAC7B,aAAO;AAAA,IACT;AAAA,IACA,KAAK,OAAO;AACV,UAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,UAAI,MAAM;AACV,iBAAW,KAAK,KAAM,QAAO;AAC7B,aAAO,MAAM,KAAK;AAAA,IACpB;AAAA,IACA,KAAK;AACH,aAAO,KAAK,WAAW,IAAI,OAAO,KAAK,IAAI,GAAG,IAAI;AAAA,IACpD,KAAK;AACH,aAAO,KAAK,WAAW,IAAI,OAAO,KAAK,IAAI,GAAG,IAAI;AAAA,IACpD;AACE,aAAO;AAAA,EACX;AACF;AASA,SAAS,4BACP,MACA,SACA,OACA,IACA,WACA,QAC2B;AAC3B,QAAM,UAAU,oBAAI,IAAsB;AAC1C,aAAW,OAAO,SAAS;AACzB,UAAM,MAAM,KAAK,GAAG,IAAI,SAAS;AACjC,UAAM,MAAM,QAAQ,QAAQ,QAAQ,SAAY,KAAK,OAAO,GAAG;AAC/D,UAAM,SAAS,QAAQ,IAAI,GAAG;AAC9B,QAAI,OAAQ,QAAO,KAAK,GAAG;AAAA,QACtB,SAAQ,IAAI,KAAK,CAAC,GAAG,CAAC;AAAA,EAC7B;AACA,QAAM,MAAiC,CAAC;AACxC,aAAW,CAAC,KAAK,aAAa,KAAK,SAAS;AAC1C,QAAI,KAAK,EAAE,KAAK,OAAO,iBAAiB,MAAM,eAAe,OAAO,IAAI,MAAM,EAAE,CAAC;AAAA,EACnF;AACA,SAAO;AACT;AAgBO,SAAS,kBACd,MACA,SACA,cACA,gBAKA;AACA,QAAM,SAAwC,CAAC;AAC/C,QAAM,MAAqC,CAAC;AAC5C,QAAM,aAAwD,CAAC;AAC/D,aAAW,QAAQ,cAAc;AAC/B,UAAM,SAAS,eAAe,IAAI,KAAK,KAAK;AAC5C,WAAO,KAAK,KAAK,IAAI,iBAAiB,MAAM,SAAS,KAAK,OAAO,KAAK,IAAI,MAAM;AAChF,QAAI,KAAK,KAAK,IAAI,KAAK;AACvB,QAAI,KAAK,WAAW;AAClB,iBAAW,KAAK,KAAK,IAAI;AAAA,QACvB;AAAA,QACA;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,QAAQ,KAAK,WAAW;AACnC;AAUO,MAAM,oBAAoB;AAEjC,SAAS,cAAc,KAAU,OAAuB;AACtD,QAAM,QAAQ,IAAI,KAAK;AACvB,MAAI,UAAU,QAAQ,UAAU,UAAa,UAAU,IAAI;AACzD,WAAO;AAAA,EACT;AACA,SAAO,OAAO,KAAK;AACrB;AAEA,SAAS,cAAc,OAAe,OAAe,OAAe,WAA2B;AAC7F,SAAO,YAAY,GAAG,SAAS,IAAI,KAAK,IAAI,KAAK,KAAK,GAAG,KAAK,IAAI,KAAK;AACzE;AAEO,SAAS,YACd,MACA,YACA,SACA,eAAkC,CAAC,GACnC,UAA8B,CAAC,GACZ;AACnB,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAsB,oBAAI,IAAI,CAAC;AAC7E,QAAM,EAAE,UAAU,IAAI;AAMtB,QAAM,iBACJ,OAAO,cAAc,YAAY,OAAO,SAAS,SAAS,KAAK,aAAa,KAAK,SAC7E,YACA;AAEN,QAAM,iBAAiB,QAAQ,MAAM;AACnC,UAAM,MAAM,oBAAI,IAAuB;AACvC,eAAW,OAAO,QAAS,KAAI,IAAI,IAAI,MAAM,GAAG;AAChD,WAAO;AAAA,EACT,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,cAAc,YAAY,CAAC,aAAqB;AACpD,uBAAmB,UAAQ;AACzB,YAAM,OAAO,IAAI,IAAI,IAAI;AACzB,UAAI,KAAK,IAAI,QAAQ,GAAG;AACtB,aAAK,OAAO,QAAQ;AAAA,MACtB,OAAO;AACL,aAAK,IAAI,QAAQ;AAAA,MACnB;AACA,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,QAAM,kBAAkB,YAAY,CAAC,cAAuB;AAC1D,QAAI,CAAC,WAAW;AACd,yBAAmB,oBAAI,IAAI,CAAC;AAAA,IAC9B,OAAO;AAEL,yBAAmB,UAAQ;AACzB,cAAM,UAAU,IAAI,IAAI,IAAI;AAE5B,gBAAQ,IAAI,kBAAkB;AAC9B,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,aAAa,QAAQ,MAAM;AAC/B,QAAI,WAAW,WAAW,EAAG,QAAO;AAEpC,UAAM,SAAsB,CAAC;AAC7B,UAAM,eAAyB,CAAC;AAGhC,aAAS,YACP,SACA,OACA,OACA,WACA;AACA,UAAI,MAAM,WAAW,GAAG;AAEtB,mBAAW,OAAO,SAAS;AACzB,iBAAO,KAAK,EAAE,MAAM,WAAW,WAAW,IAAI,CAAC;AAAA,QACjD;AACA;AAAA,MACF;AAEA,YAAM,CAAC,aAAa,GAAG,cAAc,IAAI;AACzC,YAAM,QAAQ,YAAY;AAG1B,YAAM,SAAS,oBAAI,IAAsB;AACzC,iBAAW,OAAO,SAAS;AACzB,cAAM,QAAQ,cAAc,KAAK,GAAG,GAAG,KAAK;AAC5C,YAAI,CAAC,OAAO,IAAI,KAAK,GAAG;AACtB,iBAAO,IAAI,OAAO,CAAC,CAAC;AAAA,QACtB;AACA,eAAO,IAAI,KAAK,EAAG,KAAK,GAAG;AAAA,MAC7B;AAGA,YAAM,aAAa,CAAC,GAAG,OAAO,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM;AAEnD,YAAI,MAAM,kBAAmB,QAAO;AACpC,YAAI,MAAM,kBAAmB,QAAO;AACpC,cAAM,MAAM,EAAE,cAAc,GAAG,QAAW,EAAE,SAAS,MAAM,aAAa,OAAO,CAAC;AAChF,eAAO,YAAY,cAAc,SAAS,CAAC,MAAM;AAAA,MACnD,CAAC;AAED,iBAAW,SAAS,YAAY;AAC9B,cAAM,eAAe,OAAO,IAAI,KAAK;AACrC,cAAM,WAAW,cAAc,OAAO,OAAO,OAAO,SAAS;AAC7D,qBAAa,KAAK,QAAQ;AAE1B,cAAM,cAAc,gBAAgB,IAAI,QAAQ;AAEhD,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA;AAAA,UACA,OAAO,aAAa;AAAA,UACpB;AAAA,UACA,WAAW;AAAA,UACX,mBAAmB;AAAA,QACrB,CAAC;AAED,YAAI,CAAC,aAAa;AAGhB,cAAI,aAAa,SAAS,GAAG;AAC3B,kBAAM,EAAE,QAAQ,KAAK,WAAW,IAAI;AAAA,cAClC;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF;AACA,mBAAO,KAAK;AAAA,cACV,MAAM;AAAA,cACN;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,OAAO;AAAA,cACP,aAAa,aAAa;AAAA,YAC5B,CAAC;AAAA,UACH;AAEA,sBAAY,cAAc,gBAAgB,QAAQ,GAAG,QAAQ;AAAA,QAC/D;AAAA,MACF;AAAA,IACF;AAGA,UAAM,aAAa,MAAM,KAAK,EAAE,QAAQ,KAAK,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC;AAClE,gBAAY,YAAY,YAAY,GAAG,EAAE;AAGzC,QAAI,gBAAgB,IAAI,kBAAkB,GAAG;AAC3C,yBAAmB,IAAI,IAAI,YAAY,CAAC;AAAA,IAC1C;AAEA,WAAO;AAAA,EACT,GAAG,CAAC,MAAM,YAAY,iBAAiB,cAAc,gBAAgB,cAAc,CAAC;AAEpF,QAAM,yBAAyB,YAAY,CAAC,cAA8B;AACxE,QAAI,CAAC,WAAY,QAAO;AACxB,aAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;AAC1C,YAAM,KAAK,WAAW,CAAC;AACvB,UAAI,GAAG,SAAS,aAAa,GAAG,cAAc,WAAW;AACvD,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT,GAAG,CAAC,UAAU,CAAC;AAIf,QAAM,sBAAsB,QAAQ,MAAM;AACxC,QAAI,CAAC,WAAY,QAAO;AACxB,UAAM,MAAM,oBAAI,IAAoB;AACpC,eAAW,MAAM,YAAY;AAC3B,UAAI,GAAG,SAAS,cAAe;AAC/B,iBAAW,aAAa,GAAG,kBAAmB,KAAI,IAAI,WAAW,GAAG,QAAQ;AAAA,IAC9E;AACA,WAAO;AAAA,EACT,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,sBAAsB;AAAA,IAC1B,CAAC,cAAqC,qBAAqB,IAAI,SAAS,KAAK;AAAA,IAC7E,CAAC,mBAAmB;AAAA,EACtB;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
6
+ "names": ["t"]
7
+ }