@pilotiq/pilotiq 0.24.1 → 0.24.2

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 (480) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/boost/guidelines.md +566 -0
  3. package/boost/skills/pilotiq-fields/SKILL.md +47 -0
  4. package/boost/skills/pilotiq-fields/rules/field-catalog.md +288 -0
  5. package/boost/skills/pilotiq-fields/rules/reactive-fields.md +199 -0
  6. package/boost/skills/pilotiq-fields/rules/validation.md +198 -0
  7. package/boost/skills/pilotiq-relations/SKILL.md +47 -0
  8. package/boost/skills/pilotiq-relations/rules/relation-managers.md +256 -0
  9. package/boost/skills/pilotiq-relations/rules/repeater-relationship.md +177 -0
  10. package/boost/skills/pilotiq-resource/SKILL.md +61 -0
  11. package/boost/skills/pilotiq-resource/rules/authorization.md +242 -0
  12. package/boost/skills/pilotiq-resource/rules/defining-resources.md +228 -0
  13. package/boost/skills/pilotiq-resource/rules/page-overrides.md +296 -0
  14. package/package.json +6 -1
  15. package/.turbo/turbo-build.log +0 -8
  16. package/CLAUDE.md +0 -265
  17. package/src/Cluster.test.ts +0 -283
  18. package/src/Cluster.ts +0 -83
  19. package/src/Column.test.ts +0 -199
  20. package/src/Column.ts +0 -710
  21. package/src/Global.test.ts +0 -367
  22. package/src/Global.ts +0 -169
  23. package/src/Page.test.ts +0 -114
  24. package/src/Page.ts +0 -208
  25. package/src/Pilotiq.perf.test.ts +0 -252
  26. package/src/Pilotiq.test.ts +0 -129
  27. package/src/Pilotiq.ts +0 -1158
  28. package/src/PilotiqRegistry.ts +0 -36
  29. package/src/PilotiqServiceProvider.ts +0 -121
  30. package/src/RelationManager.test.ts +0 -400
  31. package/src/RelationManager.ts +0 -527
  32. package/src/RenderHook.test.ts +0 -252
  33. package/src/RenderHook.ts +0 -242
  34. package/src/Resource.test.ts +0 -284
  35. package/src/Resource.ts +0 -526
  36. package/src/RightPanel.test.ts +0 -202
  37. package/src/RightPanel.ts +0 -132
  38. package/src/Tab.test.ts +0 -91
  39. package/src/Tab.ts +0 -156
  40. package/src/UserMenuItem.ts +0 -145
  41. package/src/actions/Action.test.ts +0 -2526
  42. package/src/actions/Action.ts +0 -1515
  43. package/src/actions/ActionGroup.test.ts +0 -112
  44. package/src/actions/ActionGroup.ts +0 -173
  45. package/src/actions/attachFactory.ts +0 -172
  46. package/src/actions/bulkFactories.ts +0 -168
  47. package/src/actions/crudFactories.ts +0 -220
  48. package/src/actions/exportFactory.ts +0 -225
  49. package/src/actions/factoryHelpers.ts +0 -177
  50. package/src/actions/importFactory.ts +0 -243
  51. package/src/actions/index.ts +0 -17
  52. package/src/actions/m2mFactories.ts +0 -193
  53. package/src/actions/relationFactories.ts +0 -372
  54. package/src/applyPageHooks.test.ts +0 -463
  55. package/src/applyPageHooks.ts +0 -330
  56. package/src/authorization.test.ts +0 -483
  57. package/src/breadcrumbs.test.ts +0 -238
  58. package/src/cells/coerce.test.ts +0 -85
  59. package/src/cells/coerce.ts +0 -84
  60. package/src/clusterPaths.ts +0 -35
  61. package/src/columns/BadgeColumn.test.ts +0 -54
  62. package/src/columns/BadgeColumn.ts +0 -32
  63. package/src/columns/BooleanColumn.test.ts +0 -41
  64. package/src/columns/BooleanColumn.ts +0 -18
  65. package/src/columns/ColorColumn.test.ts +0 -37
  66. package/src/columns/ColorColumn.ts +0 -38
  67. package/src/columns/IconColumn.test.ts +0 -54
  68. package/src/columns/IconColumn.ts +0 -37
  69. package/src/columns/ImageColumn.test.ts +0 -41
  70. package/src/columns/ImageColumn.ts +0 -28
  71. package/src/columns/SelectColumn.ts +0 -98
  72. package/src/columns/TextColumn.test.ts +0 -190
  73. package/src/columns/TextColumn.ts +0 -20
  74. package/src/columns/TextInputColumn.ts +0 -68
  75. package/src/columns/ToggleColumn.ts +0 -46
  76. package/src/columns/editableColumns.test.ts +0 -238
  77. package/src/columns/index.ts +0 -9
  78. package/src/defaultGlobalPages.ts +0 -95
  79. package/src/defaultPages.test.ts +0 -634
  80. package/src/defaultPages.ts +0 -617
  81. package/src/defaultViewPage.test.ts +0 -147
  82. package/src/elements/Form.test.ts +0 -223
  83. package/src/elements/Form.ts +0 -416
  84. package/src/elements/ListTabs.ts +0 -28
  85. package/src/elements/Table.test.ts +0 -422
  86. package/src/elements/Table.ts +0 -850
  87. package/src/elements/TableGroup.test.ts +0 -260
  88. package/src/elements/TableGroup.ts +0 -334
  89. package/src/elements/dispatchAction.test.ts +0 -463
  90. package/src/elements/dispatchAction.ts +0 -355
  91. package/src/elements/dispatchForm.test.ts +0 -477
  92. package/src/elements/dispatchForm.ts +0 -1993
  93. package/src/elements/dispatchTable.test.ts +0 -1514
  94. package/src/elements/dispatchTable.ts +0 -745
  95. package/src/elements/index.ts +0 -21
  96. package/src/entries/BadgeEntry.ts +0 -39
  97. package/src/entries/CodeEntry.test.ts +0 -40
  98. package/src/entries/CodeEntry.ts +0 -52
  99. package/src/entries/ColorEntry.ts +0 -63
  100. package/src/entries/ComponentEntry.test.ts +0 -173
  101. package/src/entries/ComponentEntry.ts +0 -95
  102. package/src/entries/Entry.ts +0 -304
  103. package/src/entries/IconEntry.ts +0 -49
  104. package/src/entries/ImageEntry.ts +0 -61
  105. package/src/entries/KeyValueEntry.ts +0 -47
  106. package/src/entries/RepeatableEntry.test.ts +0 -239
  107. package/src/entries/RepeatableEntry.ts +0 -173
  108. package/src/entries/TextEntry.test.ts +0 -394
  109. package/src/entries/TextEntry.ts +0 -60
  110. package/src/entries/index.ts +0 -12
  111. package/src/entries/leaves.test.ts +0 -306
  112. package/src/entries/registry.ts +0 -54
  113. package/src/fields/BuilderField.test.ts +0 -1188
  114. package/src/fields/BuilderField.ts +0 -605
  115. package/src/fields/BuilderRelationship.test.ts +0 -811
  116. package/src/fields/CheckboxField.test.ts +0 -44
  117. package/src/fields/CheckboxField.ts +0 -27
  118. package/src/fields/CheckboxListField.test.ts +0 -99
  119. package/src/fields/CheckboxListField.ts +0 -66
  120. package/src/fields/ColorPickerField.test.ts +0 -33
  121. package/src/fields/ColorPickerField.ts +0 -25
  122. package/src/fields/DateField.ts +0 -54
  123. package/src/fields/DateTimeField.test.ts +0 -55
  124. package/src/fields/EmailField.ts +0 -16
  125. package/src/fields/Field.test.ts +0 -654
  126. package/src/fields/Field.ts +0 -817
  127. package/src/fields/FileUploadField.test.ts +0 -143
  128. package/src/fields/FileUploadField.ts +0 -159
  129. package/src/fields/HiddenField.test.ts +0 -27
  130. package/src/fields/HiddenField.ts +0 -28
  131. package/src/fields/KeyValueField.test.ts +0 -105
  132. package/src/fields/KeyValueField.ts +0 -55
  133. package/src/fields/MarkdownField.test.ts +0 -167
  134. package/src/fields/MarkdownField.ts +0 -162
  135. package/src/fields/NumberField.ts +0 -33
  136. package/src/fields/RadioField.test.ts +0 -94
  137. package/src/fields/RadioField.ts +0 -67
  138. package/src/fields/RepeaterField.test.ts +0 -1806
  139. package/src/fields/RepeaterField.ts +0 -939
  140. package/src/fields/RepeaterRelationship.test.ts +0 -1923
  141. package/src/fields/RepeaterSimple.test.ts +0 -248
  142. package/src/fields/RowButton.test.ts +0 -219
  143. package/src/fields/RowButton.ts +0 -135
  144. package/src/fields/SelectField.test.ts +0 -192
  145. package/src/fields/SelectField.ts +0 -235
  146. package/src/fields/SliderField.test.ts +0 -50
  147. package/src/fields/SliderField.ts +0 -53
  148. package/src/fields/SlugField.ts +0 -24
  149. package/src/fields/TagsInputField.test.ts +0 -154
  150. package/src/fields/TagsInputField.ts +0 -133
  151. package/src/fields/TextField.test.ts +0 -213
  152. package/src/fields/TextField.ts +0 -177
  153. package/src/fields/TextareaField.test.ts +0 -58
  154. package/src/fields/TextareaField.ts +0 -59
  155. package/src/fields/ToggleButtonsField.test.ts +0 -106
  156. package/src/fields/ToggleButtonsField.ts +0 -59
  157. package/src/fields/ToggleField.ts +0 -16
  158. package/src/fields/disableOptionsWhenSelectedInSiblingRepeaterItems.test.ts +0 -319
  159. package/src/fields/optionsResolver.ts +0 -95
  160. package/src/fields/resolveField.ts +0 -28
  161. package/src/filters/BooleanFilter.ts +0 -35
  162. package/src/filters/DateRangeFilter.test.ts +0 -194
  163. package/src/filters/DateRangeFilter.ts +0 -148
  164. package/src/filters/Filter.test.ts +0 -268
  165. package/src/filters/Filter.ts +0 -184
  166. package/src/filters/FormFilter.test.ts +0 -238
  167. package/src/filters/FormFilter.ts +0 -215
  168. package/src/filters/MultiSelectFilter.test.ts +0 -119
  169. package/src/filters/MultiSelectFilter.ts +0 -78
  170. package/src/filters/QueryBuilderFilter.test.ts +0 -662
  171. package/src/filters/QueryBuilderFilter.ts +0 -398
  172. package/src/filters/SelectFilter.ts +0 -46
  173. package/src/filters/TernaryFilter.test.ts +0 -160
  174. package/src/filters/TernaryFilter.ts +0 -72
  175. package/src/filters/TrashedFilter.test.ts +0 -149
  176. package/src/filters/TrashedFilter.ts +0 -55
  177. package/src/filters/queryBuilder/BooleanConstraint.ts +0 -31
  178. package/src/filters/queryBuilder/Constraint.ts +0 -115
  179. package/src/filters/queryBuilder/DateConstraint.ts +0 -69
  180. package/src/filters/queryBuilder/NumberConstraint.ts +0 -66
  181. package/src/filters/queryBuilder/SelectConstraint.ts +0 -72
  182. package/src/filters/queryBuilder/TextConstraint.ts +0 -64
  183. package/src/filters/queryBuilder/index.ts +0 -12
  184. package/src/icons/index.ts +0 -2
  185. package/src/icons/lucide.ts +0 -204
  186. package/src/icons/registry.test.ts +0 -56
  187. package/src/icons/registry.ts +0 -41
  188. package/src/icons/types.ts +0 -47
  189. package/src/index.ts +0 -525
  190. package/src/io/csv.test.ts +0 -142
  191. package/src/io/csv.ts +0 -170
  192. package/src/nestedRelationManagerData.test.ts +0 -547
  193. package/src/notifications/Notification.test.ts +0 -210
  194. package/src/notifications/Notification.ts +0 -354
  195. package/src/notifications/broadcast.test.ts +0 -110
  196. package/src/notifications/broadcast.ts +0 -95
  197. package/src/notifications/database.test.ts +0 -383
  198. package/src/notifications/database.ts +0 -398
  199. package/src/notifications/databaseNotifications.test.ts +0 -187
  200. package/src/notifications/dispatchNotificationAction.test.ts +0 -341
  201. package/src/notifications/dispatchNotificationAction.ts +0 -142
  202. package/src/notifications/flash.test.ts +0 -89
  203. package/src/notifications/flash.ts +0 -71
  204. package/src/notifications/index.ts +0 -45
  205. package/src/notifications/registerBroadcastAuth.test.ts +0 -134
  206. package/src/notifications/registerBroadcastAuth.ts +0 -100
  207. package/src/notifications/resolveSavedNotification.test.ts +0 -82
  208. package/src/notifications/resolveSavedNotification.ts +0 -59
  209. package/src/notifications/types.ts +0 -93
  210. package/src/orm/m2mAccessor.ts +0 -66
  211. package/src/orm/modelDefaults.test.ts +0 -633
  212. package/src/orm/modelDefaults.ts +0 -666
  213. package/src/pageData/breadcrumbs.ts +0 -288
  214. package/src/pageData/forms.ts +0 -578
  215. package/src/pageData/helpers.ts +0 -857
  216. package/src/pageData/misc.ts +0 -347
  217. package/src/pageData/navigation.ts +0 -842
  218. package/src/pageData/relationPages.ts +0 -1248
  219. package/src/pageData/relationTabs.ts +0 -286
  220. package/src/pageData/resourcePages.ts +0 -609
  221. package/src/pageData.test.ts +0 -1545
  222. package/src/pageData.ts +0 -341
  223. package/src/plugins/index.ts +0 -8
  224. package/src/plugins/themeEditor.test.ts +0 -36
  225. package/src/plugins/themeEditor.ts +0 -45
  226. package/src/react/AppShell.tsx +0 -251
  227. package/src/react/CollabExtensionFactoryRegistry.ts +0 -55
  228. package/src/react/CollabRoomContext.ts +0 -98
  229. package/src/react/CollabTextRendererRegistry.ts +0 -102
  230. package/src/react/CommandPalette.tsx +0 -375
  231. package/src/react/CurrentUserContext.tsx +0 -50
  232. package/src/react/CustomPageWrapperGate.tsx +0 -69
  233. package/src/react/CustomPageWrapperRegistry.ts +0 -45
  234. package/src/react/FieldFocusReporterRegistry.ts +0 -37
  235. package/src/react/FieldLabelSlotRegistry.ts +0 -30
  236. package/src/react/FieldPresenceRegistry.ts +0 -46
  237. package/src/react/FormCollabBindingRegistry.ts +0 -242
  238. package/src/react/FormStateContext.tsx +0 -591
  239. package/src/react/HeadHooks.tsx +0 -126
  240. package/src/react/MarkdownEditorRegistry.test.ts +0 -38
  241. package/src/react/MarkdownEditorRegistry.ts +0 -107
  242. package/src/react/NotificationActionStrip.tsx +0 -263
  243. package/src/react/NotificationBell.tsx +0 -426
  244. package/src/react/PendingSuggestionApplierRegistry.test.ts +0 -97
  245. package/src/react/PendingSuggestionApplierRegistry.ts +0 -98
  246. package/src/react/PendingSuggestionOverlayRegistry.ts +0 -54
  247. package/src/react/PendingSuggestionsContext.tsx +0 -172
  248. package/src/react/RecordWrapperGate.tsx +0 -58
  249. package/src/react/RecordWrapperRegistry.ts +0 -39
  250. package/src/react/RenderHookSlot.tsx +0 -32
  251. package/src/react/RightSidebar.tsx +0 -257
  252. package/src/react/RightSidebarContext.tsx +0 -234
  253. package/src/react/RightSidebarTrigger.tsx +0 -53
  254. package/src/react/RowCoordsContext.tsx +0 -23
  255. package/src/react/SchemaRenderer.tsx +0 -549
  256. package/src/react/SearchTrigger.tsx +0 -46
  257. package/src/react/ThemeProvider.tsx +0 -93
  258. package/src/react/ThemeSettingsPage.tsx +0 -579
  259. package/src/react/ThemeToggle.tsx +0 -20
  260. package/src/react/Toaster.tsx +0 -158
  261. package/src/react/UserMenu.tsx +0 -196
  262. package/src/react/WidgetDataContext.tsx +0 -157
  263. package/src/react/cells/EditableCell.tsx +0 -389
  264. package/src/react/component-slots.test.ts +0 -103
  265. package/src/react/component-slots.ts +0 -116
  266. package/src/react/fieldJsHandler.test.ts +0 -166
  267. package/src/react/fieldJsHandler.ts +0 -79
  268. package/src/react/fields/BuilderInput.tsx +0 -1078
  269. package/src/react/fields/CheckboxInput.tsx +0 -39
  270. package/src/react/fields/CheckboxListInput.tsx +0 -102
  271. package/src/react/fields/ColorInput.tsx +0 -71
  272. package/src/react/fields/DateFieldInput.tsx +0 -70
  273. package/src/react/fields/DateTimeInput.tsx +0 -62
  274. package/src/react/fields/FieldShell.tsx +0 -348
  275. package/src/react/fields/FileUploadInput.tsx +0 -639
  276. package/src/react/fields/HiddenInput.tsx +0 -17
  277. package/src/react/fields/KeyValueInput.tsx +0 -230
  278. package/src/react/fields/MarkdownInput.tsx +0 -560
  279. package/src/react/fields/RadioInput.tsx +0 -81
  280. package/src/react/fields/RepeaterInput.test.ts +0 -116
  281. package/src/react/fields/RepeaterInput.tsx +0 -1420
  282. package/src/react/fields/SelectFieldInput.tsx +0 -280
  283. package/src/react/fields/SliderInput.tsx +0 -81
  284. package/src/react/fields/TagsInput.tsx +0 -283
  285. package/src/react/fields/TextLikeInput.tsx +0 -256
  286. package/src/react/fields/ToggleButtonsInput.tsx +0 -60
  287. package/src/react/fields/ToggleFieldInput.tsx +0 -56
  288. package/src/react/fields/relationshipRenameDispatch.test.ts +0 -106
  289. package/src/react/fields/relationshipRenameDispatch.ts +0 -97
  290. package/src/react/fields/repeaterReconcile.test.ts +0 -114
  291. package/src/react/fields/repeaterReconcile.ts +0 -104
  292. package/src/react/fields/rowChromeButton.tsx +0 -336
  293. package/src/react/fields/rowState.ts +0 -106
  294. package/src/react/fields/syncRowGates.test.ts +0 -202
  295. package/src/react/fields/syncRowGates.ts +0 -66
  296. package/src/react/fields/textInputControls.tsx +0 -238
  297. package/src/react/fields/useRowReorderDnd.ts +0 -78
  298. package/src/react/formStateHelpers.test.ts +0 -508
  299. package/src/react/formStateHelpers.ts +0 -381
  300. package/src/react/hooks/use-mobile.ts +0 -19
  301. package/src/react/icon-context.tsx +0 -60
  302. package/src/react/index.ts +0 -194
  303. package/src/react/layouts/SidebarLayout.tsx +0 -250
  304. package/src/react/layouts/TopbarLayout.tsx +0 -258
  305. package/src/react/navigate.tsx +0 -37
  306. package/src/react/onProviderSynced.test.ts +0 -90
  307. package/src/react/parseRecordEditUrl.test.ts +0 -122
  308. package/src/react/parseRecordEditUrl.ts +0 -94
  309. package/src/react/persistedState.ts +0 -40
  310. package/src/react/registry.ts +0 -48
  311. package/src/react/right-panel-registry.tsx +0 -47
  312. package/src/react/schemaRenderer/AlertRenderer.tsx +0 -112
  313. package/src/react/schemaRenderer/EntryRenderer.tsx +0 -501
  314. package/src/react/schemaRenderer/SectionRenderer.tsx +0 -120
  315. package/src/react/schemaRenderer/SimpleElements.tsx +0 -306
  316. package/src/react/schemaRenderer/TabsRenderer.tsx +0 -62
  317. package/src/react/schemaRenderer/WizardRenderer.tsx +0 -338
  318. package/src/react/schemaRenderer/action/ActionGroupTrigger.tsx +0 -177
  319. package/src/react/schemaRenderer/action/ActionModalDialog.tsx +0 -273
  320. package/src/react/schemaRenderer/action/ConfirmActionDialog.tsx +0 -61
  321. package/src/react/schemaRenderer/action/HandlerActionButton.tsx +0 -43
  322. package/src/react/schemaRenderer/action/MethodActionButton.tsx +0 -64
  323. package/src/react/schemaRenderer/action/buttons.tsx +0 -99
  324. package/src/react/schemaRenderer/action/helpers.ts +0 -140
  325. package/src/react/schemaRenderer/action/renderAction.tsx +0 -245
  326. package/src/react/schemaRenderer/columnFormat.ts +0 -65
  327. package/src/react/schemaRenderer/constants.ts +0 -50
  328. package/src/react/schemaRenderer/form/FormRenderer.tsx +0 -274
  329. package/src/react/schemaRenderer/form/renderField.tsx +0 -511
  330. package/src/react/schemaRenderer/helpers.tsx +0 -81
  331. package/src/react/schemaRenderer/table/CardsLayoutBody.tsx +0 -308
  332. package/src/react/schemaRenderer/table/TableRenderer.tsx +0 -123
  333. package/src/react/schemaRenderer/table/TableRendererBody.tsx +0 -974
  334. package/src/react/schemaRenderer/table/filters.tsx +0 -1233
  335. package/src/react/schemaRenderer/table/formatCell.tsx +0 -264
  336. package/src/react/schemaRenderer/table/links.tsx +0 -112
  337. package/src/react/schemaRenderer/table/renderRowActions.tsx +0 -52
  338. package/src/react/schemaRenderer/table/url.tsx +0 -143
  339. package/src/react/theme-preview/apply.ts +0 -99
  340. package/src/react/theme-preview/build-html.ts +0 -436
  341. package/src/react/ui/button.tsx +0 -51
  342. package/src/react/ui/calendar.tsx +0 -67
  343. package/src/react/ui/checkbox.tsx +0 -29
  344. package/src/react/ui/dialog.tsx +0 -108
  345. package/src/react/ui/dropdown-menu.tsx +0 -97
  346. package/src/react/ui/input.tsx +0 -20
  347. package/src/react/ui/label.tsx +0 -21
  348. package/src/react/ui/popover.tsx +0 -50
  349. package/src/react/ui/select.tsx +0 -169
  350. package/src/react/ui/separator.tsx +0 -25
  351. package/src/react/ui/sheet.tsx +0 -136
  352. package/src/react/ui/sidebar.tsx +0 -723
  353. package/src/react/ui/skeleton.tsx +0 -13
  354. package/src/react/ui/slider.tsx +0 -34
  355. package/src/react/ui/switch.tsx +0 -28
  356. package/src/react/ui/table.tsx +0 -105
  357. package/src/react/ui/tabs.tsx +0 -63
  358. package/src/react/ui/textarea.tsx +0 -18
  359. package/src/react/ui/tooltip.tsx +0 -64
  360. package/src/react/useResizableWidth.ts +0 -139
  361. package/src/react/utils.ts +0 -6
  362. package/src/react/widgetRegistry.test.ts +0 -43
  363. package/src/react/widgetRegistry.ts +0 -50
  364. package/src/react/widgets/StatsOverviewRenderer.tsx +0 -232
  365. package/src/react/widgets/TableWidgetRenderer.tsx +0 -231
  366. package/src/react/widgets/ViewRenderer.tsx +0 -71
  367. package/src/relationManagerData.test.ts +0 -1595
  368. package/src/richtext/index.ts +0 -8
  369. package/src/richtext/registry.ts +0 -89
  370. package/src/routes/globals.ts +0 -148
  371. package/src/routes/guard.test.ts +0 -325
  372. package/src/routes/helpers.ts +0 -704
  373. package/src/routes/pages.ts +0 -175
  374. package/src/routes/panel.ts +0 -204
  375. package/src/routes/relations.ts +0 -1243
  376. package/src/routes/resources.ts +0 -781
  377. package/src/routes/theme.ts +0 -91
  378. package/src/routes-nested-relations.test.ts +0 -676
  379. package/src/routes-relations.test.ts +0 -972
  380. package/src/routes.test.ts +0 -2027
  381. package/src/routes.ts +0 -303
  382. package/src/schema/Alert.test.ts +0 -109
  383. package/src/schema/Alert.ts +0 -131
  384. package/src/schema/Block.ts +0 -169
  385. package/src/schema/Breadcrumbs.ts +0 -40
  386. package/src/schema/Card.ts +0 -35
  387. package/src/schema/Divider.ts +0 -20
  388. package/src/schema/Element.ts +0 -219
  389. package/src/schema/EmptyState.test.ts +0 -37
  390. package/src/schema/EmptyState.ts +0 -63
  391. package/src/schema/Fieldset.ts +0 -43
  392. package/src/schema/Grid.ts +0 -43
  393. package/src/schema/Group.ts +0 -30
  394. package/src/schema/Heading.ts +0 -39
  395. package/src/schema/Html.ts +0 -67
  396. package/src/schema/Icon.ts +0 -54
  397. package/src/schema/Image.ts +0 -57
  398. package/src/schema/LinkTag.ts +0 -41
  399. package/src/schema/Markdown.ts +0 -85
  400. package/src/schema/MetaTag.ts +0 -41
  401. package/src/schema/RelationTabs.ts +0 -71
  402. package/src/schema/ScriptTag.ts +0 -55
  403. package/src/schema/Section.ts +0 -160
  404. package/src/schema/ServerDataElement.test.ts +0 -140
  405. package/src/schema/ServerDataElement.ts +0 -156
  406. package/src/schema/SlotComponent.test.ts +0 -77
  407. package/src/schema/SlotComponent.ts +0 -71
  408. package/src/schema/Split.ts +0 -50
  409. package/src/schema/Stat.test.ts +0 -118
  410. package/src/schema/Stat.ts +0 -154
  411. package/src/schema/StatsOverview.test.ts +0 -141
  412. package/src/schema/StatsOverview.ts +0 -119
  413. package/src/schema/StyleTag.ts +0 -35
  414. package/src/schema/TableWidget.test.ts +0 -297
  415. package/src/schema/TableWidget.ts +0 -289
  416. package/src/schema/Tabs.ts +0 -79
  417. package/src/schema/Text.ts +0 -58
  418. package/src/schema/UnorderedList.ts +0 -49
  419. package/src/schema/View.test.ts +0 -111
  420. package/src/schema/View.ts +0 -127
  421. package/src/schema/Wizard.ts +0 -220
  422. package/src/schema/containers.test.ts +0 -564
  423. package/src/schema/headTags.test.ts +0 -134
  424. package/src/schema/index.ts +0 -40
  425. package/src/schema/primes.test.ts +0 -269
  426. package/src/schema/resolveSchema.test.ts +0 -379
  427. package/src/schema/resolveSchema.ts +0 -917
  428. package/src/schema/sanitize.ts +0 -58
  429. package/src/search.test.ts +0 -446
  430. package/src/search.ts +0 -178
  431. package/src/sessionFilters.test.ts +0 -375
  432. package/src/sessionFilters.ts +0 -143
  433. package/src/slot-components/index.ts +0 -10
  434. package/src/slot-components/registry.ts +0 -56
  435. package/src/styles/file-upload.css +0 -13
  436. package/src/summarizers/Summarizer.test.ts +0 -84
  437. package/src/summarizers/Summarizer.ts +0 -123
  438. package/src/summarizers/index.ts +0 -11
  439. package/src/theme/base-colors.ts +0 -68
  440. package/src/theme/chart-colors.ts +0 -50
  441. package/src/theme/colors.ts +0 -447
  442. package/src/theme/generate-css.test.ts +0 -139
  443. package/src/theme/generate-css.ts +0 -44
  444. package/src/theme/generate-scale.test.ts +0 -106
  445. package/src/theme/generate-scale.ts +0 -97
  446. package/src/theme/icon-map.ts +0 -42
  447. package/src/theme/index.ts +0 -34
  448. package/src/theme/migrate.test.ts +0 -178
  449. package/src/theme/migrate.ts +0 -81
  450. package/src/theme/presets.ts +0 -135
  451. package/src/theme/radius.ts +0 -18
  452. package/src/theme/resolve.test.ts +0 -238
  453. package/src/theme/resolve.ts +0 -96
  454. package/src/theme/spacing.ts +0 -18
  455. package/src/theme/storage.test.ts +0 -126
  456. package/src/theme/storage.ts +0 -106
  457. package/src/theme/theme-colors.ts +0 -88
  458. package/src/theme/types.ts +0 -125
  459. package/src/uploads/UploadAdapter.ts +0 -35
  460. package/src/uploads/index.ts +0 -2
  461. package/src/uploads/localUpload.test.ts +0 -70
  462. package/src/uploads/localUpload.ts +0 -84
  463. package/src/validation/Validator.ts +0 -49
  464. package/src/validation/index.ts +0 -28
  465. package/src/validation/rules.ts +0 -78
  466. package/src/validation/runValidators.ts +0 -435
  467. package/src/validation/uniqueValidator.test.ts +0 -196
  468. package/src/validation/uniqueValidator.ts +0 -133
  469. package/src/validation/validators.test.ts +0 -268
  470. package/src/vite.test.ts +0 -184
  471. package/src/vite.ts +0 -787
  472. package/src/widgets/index.ts +0 -10
  473. package/src/widgets/registry.ts +0 -45
  474. package/src/widgets.test.ts +0 -592
  475. package/tsconfig.build.json +0 -11
  476. package/tsconfig.json +0 -4
  477. package/tsconfig.test.json +0 -10
  478. package/views/react/Dashboard.tsx +0 -27
  479. package/views/react/Resources/Form.tsx +0 -102
  480. package/views/react/Resources/Index.tsx +0 -49
package/src/Column.ts DELETED
@@ -1,710 +0,0 @@
1
- import { Element, type ElementMeta } from './schema/Element.js'
2
- import { Summarizer, type SummarizerMeta } from './summarizers/Summarizer.js'
3
- import type { SanitizeConfig } from './schema/sanitize.js'
4
- import type {
5
- Validator,
6
- ValidatorContext,
7
- SerializedRule,
8
- } from './validation/Validator.js'
9
-
10
- /** Cell content alignment. Maps to text-{start|center|end} on the cell. */
11
- export type ColumnAlignment = 'start' | 'center' | 'end'
12
-
13
- /** Visual variant. The default `text` covers most cases — formatters
14
- * (dateTime / money / since / numeric / limit) layer on top.
15
- * `badge` / `icon` / `boolean` / `image` are subclasses that change
16
- * how the cell is *rendered* rather than just *formatted*.
17
- * `textInput` / `toggle` / `select` are inline-edit subclasses — the
18
- * renderer mounts an interactive control that PATCHes a single column
19
- * via `POST {base}/{slug}/:id/_cell/:column`. */
20
- export type ColumnType =
21
- | 'text' | 'badge' | 'icon' | 'boolean' | 'image' | 'color'
22
- | 'textInput' | 'toggle' | 'select'
23
-
24
- /** Per-row predicate for `Column.disabled(fn)` — evaluated server-side
25
- * inside `loadTableRecords` so the renderer just reads the result. */
26
- export type ColumnDisabledFn = (record: Record<string, unknown>) => boolean
27
-
28
- /** Context handed to `Column.beforeStateUpdated / afterStateUpdated`
29
- * hooks on editable cell columns. `record` is the row as loaded
30
- * *before* the update; `user` is the resolved panel user. */
31
- export interface CellStateHookContext {
32
- record: Record<string, unknown>
33
- user?: unknown
34
- }
35
-
36
- /** Hook signature for `Column.beforeStateUpdated / afterStateUpdated`.
37
- * Return value is ignored — these are side-effect hooks. Throw an
38
- * Error to halt the PATCH; the thrown message lands under `errors._cell`
39
- * in the 422 response so the renderer can surface it next to the cell. */
40
- export type CellStateHook = (
41
- value: unknown,
42
- ctx: CellStateHookContext,
43
- ) => void | Promise<void>
44
-
45
- /** SelectColumn option shape — mirrors `SelectField`'s static option form. */
46
- export interface ColumnSelectOption {
47
- value: string
48
- label: string
49
- }
50
-
51
- /** Font weight preset — maps to a Tailwind `font-*` class. */
52
- export type ColumnWeight = 'normal' | 'medium' | 'semibold' | 'bold'
53
-
54
- /** Color preset for the cell text. `muted` greys the value. */
55
- export type ColumnColor = 'default' | 'muted' | 'primary' | 'destructive' | 'success' | 'warning' | 'info'
56
-
57
- /** Built-in formatters serialized to the client. `kind` drives the
58
- * client-side switch; the rest of the fields carry per-kind options. */
59
- export type ColumnFormat =
60
- | { kind: 'dateTime'; pattern?: string }
61
- | { kind: 'since' }
62
- | { kind: 'money'; currency: string; locale?: string }
63
- | { kind: 'numeric'; decimals?: number; locale?: string }
64
- | { kind: 'limit'; chars: number }
65
- | { kind: 'words'; words: number }
66
-
67
- /** Rich-text column kind — server-rendered HTML stamped per row.
68
- * Markdown values run through `marked` first; HTML values pass straight
69
- * to `sanitize-html`. Both honor `_sanitize` (default `true`). */
70
- export type ColumnRichTextKind = 'markdown' | 'html'
71
-
72
- /** Per-row formatter callback. Returns the rendered cell content as a
73
- * string. Runs server-side inside `loadTableRecords` (the function
74
- * isn't serializable to the client). */
75
- export type FormatStateHandler = (value: unknown, record: Record<string, unknown>) => string
76
-
77
- /** Per-row record-URL callback. Returns the destination URL for clicks
78
- * on this column's cell, or `undefined` to skip linking that row. Runs
79
- * server-side inside `loadTableRecords`. */
80
- export type ColumnRecordUrlHandler = (record: Record<string, unknown>) => string | undefined
81
-
82
- /** Configuration for `Column.toggleable(...)`. The user can show / hide the
83
- * column from a per-table dropdown; preference persists to localStorage so
84
- * it survives reloads + SPA navs. `initiallyHidden` flips the default state
85
- * so the column starts off-screen and the user opts in. */
86
- export interface ColumnToggleableConfig {
87
- initiallyHidden?: boolean
88
- }
89
-
90
- export interface ColumnMeta extends ElementMeta {
91
- type: 'column'
92
- name: string
93
- label: string
94
- sortable: boolean
95
- searchable: boolean
96
- columnType?: ColumnType
97
- alignment?: ColumnAlignment
98
- width?: string
99
- default?: string
100
- tooltip?: string
101
- wrap?: boolean
102
- lineClamp?: number
103
- weight?: ColumnWeight
104
- color?: ColumnColor
105
- format?: ColumnFormat
106
- /** True when a `formatStateUsing` callback is set. The renderer reads
107
- * formatted values out of `row._formatted[columnName]` instead of
108
- * re-applying the column's format spec. */
109
- hasFormatter?: boolean
110
- /** Per-column footer summarizers — kind + optional label. The actual
111
- * computed values for each summarizer land on the table meta under
112
- * `summaries[columnName]` (`SummaryResult[]`), not on the column. */
113
- summaries?: SummarizerMeta[]
114
- /** True when the user can show / hide this column from the toolbar's
115
- * "Columns" dropdown. `initiallyHidden` flips the default state so
116
- * the column starts off until the user opts in. */
117
- toggleable?: { initiallyHidden?: true }
118
- /** Render array values one-per-line (each item separated by `<br>`).
119
- * Composes with `bulleted()` — when both are set, `bulleted()` wins
120
- * and the renderer mounts a `<ul>` with bullet markers instead. */
121
- listWithLineBreaks?: true
122
- /** Render array values as a `<ul>` bullet list. Wins over
123
- * `listWithLineBreaks()` when both are set. */
124
- bulleted?: true
125
- /** Mounts a copy-to-clipboard trigger after the cell value. The string
126
- * is the toast message shown after a successful copy (default
127
- * `"Copied!"` when bare `.copyable()` is used). */
128
- copyMessage?: string
129
- /** Server-rendered rich-text discriminator. When set, the renderer
130
- * reads the rendered HTML from `row._formatted[col.name]` and
131
- * dangerouslySetsInnerHTML it (matches the existing Tiptap richtext
132
- * cell path). The kind drives server-side rendering — `markdown` runs
133
- * through `marked` first; `html` is passthrough. Sanitization applies
134
- * to both unless the column opts out. */
135
- richText?: ColumnRichTextKind
136
- /**
137
- * Per-column record-URL behavior. The default (absent) means the cell
138
- * inherits the table's `recordUrl` for click navigation. `false` opts
139
- * the column out — clicks on this column's cell don't navigate anywhere.
140
- * `true` means the column has its own URL handler; the resolved URL
141
- * is stamped onto each row under `row._columnRecordUrls[columnName]`.
142
- */
143
- recordUrl?: boolean
144
- // ─── Editable cell columns (TextInput / Toggle / Select) ───
145
- /** Confirmation message — when set, the renderer gates the PATCH
146
- * behind a Dialog confirm before firing. */
147
- confirm?: string
148
- /** Static disable. Per-row disable (`disabled(fn)`) lands on the row
149
- * under `row._cellDisabled[columnName]` — not on the column meta. */
150
- disabled?: true
151
- /** Mirrored validator descriptors — same shape as `FieldMeta.rules`,
152
- * for client-side hint rendering. The actual rules run server-side
153
- * inside the `_cell` route. */
154
- rules?: SerializedRule[]
155
- /** Default debounce (ms) for committed-after-typing PATCHes on
156
- * `TextInputColumn`. Stamped on the meta only when explicitly set;
157
- * the renderer falls back to its own default. */
158
- debounceMs?: number
159
- // Subclass-specific extras land in `_extra` to keep the meta typed.
160
- // BadgeColumn — value-to-color map.
161
- badgeColors?: Record<string, string>
162
- // IconColumn — value-to-{icon,color} map.
163
- iconOptions?: Record<string, { icon: string; color?: string }>
164
- // ImageColumn — sizing.
165
- imageSize?: number
166
- imageShape?: 'square' | 'circle'
167
- // ColorColumn — swatch shape + value-text suppression.
168
- colorShape?: 'rounded' | 'square' | 'circle'
169
- colorHideValue?: true
170
- // TextInputColumn.
171
- inputType?: 'text' | 'number' | 'email' | 'url' | 'tel'
172
- inputPlaceholder?: string
173
- inputStep?: number
174
- inputMin?: number
175
- inputMax?: number
176
- // ToggleColumn.
177
- toggleOnColor?: ColumnColor
178
- toggleOffColor?: ColumnColor
179
- toggleOnIcon?: string
180
- toggleOffIcon?: string
181
- // SelectColumn.
182
- selectOptions?: ColumnSelectOption[]
183
- selectNullable?: true
184
- /** Hide the placeholder option once a value is set. Default: keep
185
- * showing it so users can clear the value (matches Filament). */
186
- selectablePlaceholder?: false
187
- }
188
-
189
- /**
190
- * Base column primitive — used directly for text cells (the most common
191
- * case) or extended into `BadgeColumn` / `IconColumn` / `BooleanColumn` /
192
- * `ImageColumn` for visual variants. Joins the schema tree as an
193
- * Element so it serializes through the same resolver pipeline as
194
- * Fields and display elements. Lives as a child of `Table`.
195
- */
196
- export class Column extends Element {
197
- readonly name: string
198
- protected _label?: string
199
- protected _sortable = false
200
- protected _searchable = false
201
-
202
- // Visual / layout
203
- protected _columnType: ColumnType = 'text'
204
- protected _alignment?: ColumnAlignment
205
- protected _width?: string
206
- protected _default?: string
207
- protected _tooltip?: string
208
- protected _wrap = false
209
- protected _lineClamp?: number
210
- protected _weight?: ColumnWeight
211
- protected _color?: ColumnColor
212
-
213
- // Formatters
214
- protected _format?: ColumnFormat
215
- protected _formatState?: FormatStateHandler
216
-
217
- // Per-column record-URL override / opt-out. `false` disables linking
218
- // for this column; a function overrides the table's URL with a
219
- // column-specific one. Unset = inherit the table's recordUrl.
220
- protected _recordUrl?: false | ColumnRecordUrlHandler
221
-
222
- // Footer summarizers (Sum / Average / Count / Range). Computed by
223
- // `loadTableRecords` over the rendered rows; values land on the
224
- // table-level summaries map keyed by column name.
225
- protected _summarizers: Summarizer[] = []
226
-
227
- // Rich-display chrome (Filament-parity Tier-2). All optional, all
228
- // emit-only-when-set — the wire shape stays tidy on the bare-text path.
229
- protected _listWithLineBreaks = false
230
- protected _bulleted = false
231
- protected _copyMessage?: string
232
- // Rich-text rendering — either `'markdown'` or `'html'`. The dispatcher
233
- // server-renders the cell + stamps `_formatted[name] / _richtextCells[name]`.
234
- protected _richText?: ColumnRichTextKind
235
- protected _sanitize: boolean | SanitizeConfig = true
236
-
237
- // User-toggleable column visibility — `Table.toggleColumns()` opt-in
238
- // chrome reads this and stamps the toolbar dropdown. State persists
239
- // per-table to localStorage so the user's choice sticks across loads.
240
- protected _toggleable: false | ColumnToggleableConfig = false
241
-
242
- // ─── Editable cell columns (TextInput / Toggle / Select) ───
243
- // Per-cell PATCH validators — same shape as Field validators. Only
244
- // consulted when the column is editable (the route handler reads
245
- // them server-side). Inert on read-only columns.
246
- protected _required = false
247
- protected _validators: Validator[] = []
248
- protected _confirm?: string
249
- protected _staticDisabled = false
250
- protected _disabledFn?: ColumnDisabledFn
251
- protected _beforeStateUpdated?: CellStateHook
252
- protected _afterStateUpdated?: CellStateHook
253
-
254
- protected constructor(name: string) {
255
- super()
256
- this.name = name
257
- }
258
-
259
- static make(name: string): Column {
260
- return new Column(name)
261
- }
262
-
263
- // ─── Identity ─────────────────────────────────────────
264
-
265
- label(l: string): this { this._label = l; return this }
266
- sortable(v = true): this { this._sortable = v; return this }
267
- searchable(v = true): this { this._searchable = v; return this }
268
-
269
- /**
270
- * Let the user show / hide this column from the table toolbar's
271
- * "Columns" dropdown. Preference persists per-table to localStorage
272
- * under `pilotiq.table.<currentPath>.columns.<col>` so the choice
273
- * sticks across reloads + SPA navigations.
274
- *
275
- * Pass `{ initiallyHidden: true }` to start the column off-screen —
276
- * useful for technical / debug columns the user opts into.
277
- *
278
- * Column.make('email').toggleable()
279
- * Column.make('internalId').toggleable({ initiallyHidden: true })
280
- * Column.make('name').toggleable(false) // explicit opt-out
281
- *
282
- * Any non-toggleable column always renders. Hidden state is purely
283
- * presentational — the column's data still loads from the server (so
284
- * sorts / filters that reference it keep working, and a re-toggle
285
- * shows fresh values without a roundtrip).
286
- */
287
- toggleable(opts: boolean | ColumnToggleableConfig = true): this {
288
- if (opts === false) {
289
- this._toggleable = false
290
- } else if (opts === true) {
291
- this._toggleable = {}
292
- } else {
293
- this._toggleable = { ...opts }
294
- }
295
- return this
296
- }
297
-
298
- isToggleable(): boolean { return this._toggleable !== false }
299
- getToggleableConfig(): ColumnToggleableConfig | undefined {
300
- return this._toggleable === false ? undefined : this._toggleable
301
- }
302
-
303
- // ─── Layout ───────────────────────────────────────────
304
-
305
- alignment(a: ColumnAlignment): this { this._alignment = a; return this }
306
- width(w: string): this { this._width = w; return this }
307
-
308
- /** Fallback string when the cell value is null / undefined / empty. */
309
- default(s: string): this { this._default = s; return this }
310
- /** Alias for `default()` to match the Filament spelling. */
311
- placeholder(s: string): this { return this.default(s) }
312
-
313
- tooltip(t: string): this { this._tooltip = t; return this }
314
-
315
- /** Render the cell with `whitespace-normal`; long content wraps onto
316
- * multiple lines instead of getting truncated. */
317
- wrap(v = true): this { this._wrap = v; return this }
318
-
319
- /** CSS line-clamp for multi-line truncation (replaces `wrap`). */
320
- lineClamp(n: number): this { this._lineClamp = n; return this }
321
-
322
- weight(w: ColumnWeight): this { this._weight = w; return this }
323
- color(c: ColumnColor): this { this._color = c; return this }
324
-
325
- // ─── Built-in formatters ──────────────────────────────
326
-
327
- /** Format a date / datetime value via `Intl.DateTimeFormat`. The
328
- * default pattern produces "Jan 1, 2026, 9:00 AM"-style output. */
329
- dateTime(pattern?: string): this {
330
- this._format = pattern ? { kind: 'dateTime', pattern } : { kind: 'dateTime' }
331
- return this
332
- }
333
-
334
- /** Render the value as relative time ("5 minutes ago"). */
335
- since(): this {
336
- this._format = { kind: 'since' }
337
- return this
338
- }
339
-
340
- /** Format the value as currency. `currency` is the ISO 4217 code
341
- * (e.g. 'USD', 'EUR'). */
342
- money(currency: string, locale?: string): this {
343
- this._format = locale ? { kind: 'money', currency, locale } : { kind: 'money', currency }
344
- return this
345
- }
346
-
347
- /** Format the value as a decimal number. */
348
- numeric(opts: { decimals?: number; locale?: string } = {}): this {
349
- this._format = {
350
- kind: 'numeric',
351
- ...(opts.decimals !== undefined ? { decimals: opts.decimals } : {}),
352
- ...(opts.locale !== undefined ? { locale: opts.locale } : {}),
353
- }
354
- return this
355
- }
356
-
357
- /** Truncate the cell to `chars` characters with an ellipsis. */
358
- limit(chars: number): this {
359
- this._format = { kind: 'limit', chars }
360
- return this
361
- }
362
-
363
- /**
364
- * Truncate the cell to `n` words with an ellipsis. Splits on whitespace
365
- * runs (`/\s+/`) — empty lead/trail tokens collapse so a value like
366
- * `" hello world "` truncates the same as `"hello world"`. Composes
367
- * mutually-exclusively with `limit()` and `characters()` (each
368
- * formatter overwrites the previous one — last call wins).
369
- */
370
- words(n: number): this {
371
- this._format = { kind: 'words', words: n }
372
- return this
373
- }
374
-
375
- /**
376
- * Filament-parity alias for `limit(n)`. Same wire shape — both call
377
- * sites read better depending on whether you're capping by character
378
- * count or word count.
379
- */
380
- characters(n: number): this { return this.limit(n) }
381
-
382
- /**
383
- * Render array values one-per-line. Non-array values pass through
384
- * unchanged. Composes with `bulleted()` — when both are set,
385
- * `bulleted()` wins (bullet list is the strictly richer presentation;
386
- * line breaks become implicit).
387
- */
388
- listWithLineBreaks(v = true): this { this._listWithLineBreaks = v; return this }
389
-
390
- /**
391
- * Render array values as a `<ul>` bullet list. Non-array values pass
392
- * through unchanged. Wins over `listWithLineBreaks()` when both are
393
- * set.
394
- */
395
- bulleted(v = true): this { this._bulleted = v; return this }
396
-
397
- /**
398
- * Mount a copy-to-clipboard trigger next to the cell value. The
399
- * `message` (default `"Copied!"`) is the toast shown after a
400
- * successful copy. The button copies the rendered cell text — for
401
- * rich-text cells (`markdown() / html()`) the underlying source is
402
- * copied instead of the rendered HTML so users get the version they
403
- * can re-edit. Bare `copyMessage()` opts in with the default copy.
404
- */
405
- copyMessage(message?: string): this {
406
- this._copyMessage = message ?? 'Copied!'
407
- return this
408
- }
409
-
410
- /**
411
- * Render the cell's value as Markdown — server-runs through `marked`
412
- * (already a dep of pilotiq from `Markdown` prime) and the result
413
- * lands as sanitized HTML in `row._formatted[name]` with
414
- * `_richtextCells[name] = true`. The renderer recognizes the flag and
415
- * mounts the cell via `dangerouslySetInnerHTML` against the same
416
- * `prose-sm` container the Tiptap richtext path uses.
417
- *
418
- * Mutually exclusive with `html()` — the last call wins. Pair with
419
- * `.allowRaw()` / `.sanitize({ allowedTags: [...] })` to relax the
420
- * default-secure allowlist for admin-trusted content.
421
- */
422
- markdown(v = true): this {
423
- if (v) this._richText = 'markdown'
424
- else delete this._richText
425
- return this
426
- }
427
-
428
- /**
429
- * Render the cell's value as raw HTML — passes straight through
430
- * `sanitize-html` against the default-secure allowlist (no Markdown
431
- * conversion). Mutually exclusive with `markdown()`.
432
- */
433
- html(v = true): this {
434
- if (v) this._richText = 'html'
435
- else delete this._richText
436
- return this
437
- }
438
-
439
- /**
440
- * Sanitization control for `markdown()` / `html()` cells. Default
441
- * `true` — runs the rendered HTML through `DEFAULT_SANITIZE_CONFIG`
442
- * before the wire shape ships. Pass `false` (or call `.allowRaw()`)
443
- * to disable; pass a `sanitize-html` config to widen the allowlist
444
- * (e.g. legacy CMS content with embedded media). Mirrors the
445
- * `Markdown` / `Html` prime APIs so authors can carry the same
446
- * intuition into a column context.
447
- */
448
- sanitize(v: boolean | SanitizeConfig = true): this {
449
- this._sanitize = v
450
- return this
451
- }
452
-
453
- /** Sugar — opt out of the default-secure sanitizer. */
454
- allowRaw(): this { this._sanitize = false; return this }
455
-
456
- /** Custom per-row formatter — runs server-side inside `loadTableRecords`
457
- * and stashes the resulting string on `row._formatted[name]`. Wins
458
- * over the built-in `format` spec when both are set. */
459
- formatStateUsing(fn: FormatStateHandler): this {
460
- this._formatState = fn
461
- return this
462
- }
463
-
464
- /**
465
- * Per-column record-URL behavior. Pass `false` to opt this column out
466
- * of the table's row-level `recordUrl` — clicks on this column's cell
467
- * won't navigate. Pass a function to override with a column-specific
468
- * URL. Without calling this, the column inherits the table's
469
- * `recordUrl`.
470
- *
471
- * Filament parity: matches `Tables\Columns\Column::url(...)` and
472
- * `->recordUrl(false)` semantics.
473
- */
474
- recordUrl(target: false | ColumnRecordUrlHandler): this {
475
- this._recordUrl = target
476
- return this
477
- }
478
-
479
- /**
480
- * Attach summarizers (Sum / Average / Count / Range) to this column.
481
- * They render in a `<tfoot>` row under the column. Values are computed
482
- * server-side over the rows currently on screen — per-page only in
483
- * v1; cross-page aggregation is deferred.
484
- */
485
- summarize(summarizers: Summarizer[]): this {
486
- this._summarizers = summarizers
487
- return this
488
- }
489
-
490
- // ─── Editable cell columns ────────────────────────────
491
- // These are no-ops on read-only column types but live on the base so
492
- // subclass authors don't need to redeclare. `isEditable()` derives
493
- // from `_columnType` — TextInputColumn / ToggleColumn / SelectColumn
494
- // call `setColumnType()` in their `make()` factory.
495
-
496
- /** Mark the value as required for inline edits. Auto-contributes a
497
- * required check unless `validate(required())` is already present
498
- * (matches `Field.required()` semantics — see `hasRequiredValidator`). */
499
- required(v = true): this { this._required = v; return this }
500
-
501
- /**
502
- * Attach one or more server-side validators. Reuses the same `Validator`
503
- * type used by `Field.validate()` so existing rules (`required`, `email`,
504
- * `minLength`, `unique`, …) work unchanged. Validators run inside the
505
- * `POST {…}/_cell/:column` route before `R.model.update`; on failure
506
- * the response is `422 { ok:false, errors: { value: string[] } }`.
507
- */
508
- validate(v: Validator | Validator[]): this {
509
- if (Array.isArray(v)) this._validators.push(...v)
510
- else this._validators.push(v)
511
- return this
512
- }
513
-
514
- /**
515
- * Gate the PATCH behind a confirm dialog. Renderer opens a Dialog with
516
- * `message` before firing the network call; cancel rolls back the
517
- * optimistic local state.
518
- */
519
- confirm(message: string): this { this._confirm = message; return this }
520
-
521
- /**
522
- * Run a hook on the server BEFORE the editable cell's value is written
523
- * to the database. Receives the coerced + validated value plus the
524
- * current row as `{ record, user }`. Use for cross-cell invariants,
525
- * audit-log writes that must precede the update, or async availability
526
- * checks that the schema-level validators don't cover. Throw an Error
527
- * to halt — the thrown message lands under the reserved `_cell` error
528
- * key in the 422 response.
529
- */
530
- beforeStateUpdated(fn: CellStateHook): this { this._beforeStateUpdated = fn; return this }
531
-
532
- /**
533
- * Run a hook on the server AFTER the editable cell's value is written
534
- * to the database. Same context shape as `beforeStateUpdated`. Use for
535
- * notifications, broadcast events, or follow-up writes that should
536
- * fire only on a confirmed save. Throwing here returns 422 with the
537
- * message under `_cell` — the row is already updated, so prefer
538
- * surfacing the error and letting the user retry rather than rolling
539
- * back manually.
540
- */
541
- afterStateUpdated(fn: CellStateHook): this { this._afterStateUpdated = fn; return this }
542
-
543
- getBeforeStateUpdated(): CellStateHook | undefined { return this._beforeStateUpdated }
544
- getAfterStateUpdated(): CellStateHook | undefined { return this._afterStateUpdated }
545
-
546
- /**
547
- * Render the inline-edit control disabled. Pass `true` (or call with no
548
- * args) for static disable; pass a `(record) => boolean` predicate for
549
- * per-row disable — evaluated server-side inside `loadTableRecords`,
550
- * stashed under `row._cellDisabled[columnName]`.
551
- *
552
- * Independent from `R.canEdit(user, record)` — the auth check fires
553
- * regardless and a forbidden record never sees an editable affordance.
554
- */
555
- disabled(value: boolean | ColumnDisabledFn = true): this {
556
- if (typeof value === 'function') {
557
- this._disabledFn = value
558
- this._staticDisabled = false
559
- } else {
560
- this._staticDisabled = value
561
- delete this._disabledFn
562
- }
563
- return this
564
- }
565
-
566
- // ─── Column-type setter (subclass internal) ───────────
567
-
568
- protected setColumnType(t: ColumnType): this {
569
- this._columnType = t
570
- return this
571
- }
572
-
573
- // ─── Getters ──────────────────────────────────────────
574
-
575
- getLabel(): string {
576
- return this._label ?? this.name.charAt(0).toUpperCase() + this.name.slice(1)
577
- }
578
- isSortable(): boolean { return this._sortable }
579
- isSearchable(): boolean { return this._searchable }
580
- getColumnType(): ColumnType { return this._columnType }
581
- getFormatStateHandler(): FormatStateHandler | undefined { return this._formatState }
582
- hasFormatter(): boolean { return this._formatState !== undefined }
583
- /** True when a built-in `format` spec (`dateTime / since / money /
584
- * numeric / limit`) is configured. Used by walkers that want to skip
585
- * columns the user has already chosen formatting for. */
586
- hasFormat(): boolean { return this._format !== undefined }
587
- getRecordUrlHandler(): ColumnRecordUrlHandler | undefined {
588
- return typeof this._recordUrl === 'function' ? this._recordUrl : undefined
589
- }
590
- hasRecordUrlHandler(): boolean { return typeof this._recordUrl === 'function' }
591
- isRecordUrlDisabled(): boolean { return this._recordUrl === false }
592
- getSummarizers(): ReadonlyArray<Summarizer> { return this._summarizers }
593
- hasSummarizers(): boolean { return this._summarizers.length > 0 }
594
-
595
- /** Rich-text discriminator. Used by `dispatchTable` to decide whether
596
- * to server-render the cell value through `marked` + `sanitize-html`. */
597
- getRichTextKind(): ColumnRichTextKind | undefined { return this._richText }
598
- isRichText(): boolean { return this._richText !== undefined }
599
- getSanitize(): boolean | SanitizeConfig { return this._sanitize }
600
-
601
- // ─── Editable getters ─────────────────────────────────
602
-
603
- /** True for `TextInputColumn / ToggleColumn / SelectColumn`. The route
604
- * handler + `dispatchTable` per-row stamping consult this. */
605
- isEditable(): boolean {
606
- return this._columnType === 'textInput'
607
- || this._columnType === 'toggle'
608
- || this._columnType === 'select'
609
- }
610
-
611
- /** Resolve per-row disable for an editable cell. Returns `true` when
612
- * the static flag is set or the optional predicate returns truthy.
613
- * Errors in the predicate fail closed (disabled) — silently swallowing
614
- * a save attempt is the worse outcome here. */
615
- isDisabledFor(record: Record<string, unknown>): boolean {
616
- if (this._staticDisabled) return true
617
- if (this._disabledFn) {
618
- try { return Boolean(this._disabledFn(record)) }
619
- catch { return true }
620
- }
621
- return false
622
- }
623
-
624
- isRequired(): boolean { return this._required }
625
- getValidators(): ReadonlyArray<Validator> { return this._validators }
626
-
627
- /** Run the column's validators against a candidate value. Mirrors
628
- * `Field.runValidators` — including the implicit required check when
629
- * `_required` is set without an explicit `required()` validator. */
630
- async runValidators(value: unknown, ctx?: ValidatorContext): Promise<string[]> {
631
- const errors: string[] = []
632
- if (this._required && !this.hasRequiredValidator()) {
633
- if (value === undefined || value === null || value === '') {
634
- errors.push('This field is required')
635
- }
636
- }
637
- for (const v of this._validators) {
638
- const result = await v(value, ctx)
639
- if (result) errors.push(result)
640
- }
641
- return errors
642
- }
643
-
644
- private hasRequiredValidator(): boolean {
645
- return this._validators.some(v => v.serialized?.rule === 'required')
646
- }
647
-
648
- /** Serialized rule descriptors mirrored to the client. */
649
- protected getSerializedRules(): SerializedRule[] {
650
- const rules: SerializedRule[] = []
651
- if (this._required && !this.hasRequiredValidator()) {
652
- rules.push({ rule: 'required', message: 'This field is required' })
653
- }
654
- for (const v of this._validators) {
655
- if (v.serialized) rules.push(v.serialized)
656
- }
657
- return rules
658
- }
659
-
660
- // ─── Serialization ────────────────────────────────────
661
-
662
- override getType(): string { return 'column' }
663
-
664
- override toMeta(): ColumnMeta {
665
- const meta: ColumnMeta = {
666
- type: 'column',
667
- name: this.name,
668
- label: this.getLabel(),
669
- sortable: this._sortable,
670
- searchable: this._searchable,
671
- }
672
- // Only emit columnType when non-default to keep meta tidy.
673
- if (this._columnType !== 'text') meta.columnType = this._columnType
674
- if (this._alignment !== undefined) meta.alignment = this._alignment
675
- if (this._width !== undefined) meta.width = this._width
676
- if (this._default !== undefined) meta.default = this._default
677
- if (this._tooltip !== undefined) meta.tooltip = this._tooltip
678
- if (this._wrap) meta.wrap = true
679
- if (this._lineClamp !== undefined) meta.lineClamp = this._lineClamp
680
- if (this._weight !== undefined) meta.weight = this._weight
681
- if (this._color !== undefined) meta.color = this._color
682
- if (this._format !== undefined) meta.format = this._format
683
- if (this._formatState !== undefined) meta.hasFormatter = true
684
- if (this._summarizers.length > 0) meta.summaries = this._summarizers.map(s => s.toMeta())
685
- if (this._toggleable !== false) {
686
- meta.toggleable = this._toggleable.initiallyHidden ? { initiallyHidden: true } : {}
687
- }
688
- if (this._listWithLineBreaks) meta.listWithLineBreaks = true
689
- if (this._bulleted) meta.bulleted = true
690
- if (this._copyMessage !== undefined) meta.copyMessage = this._copyMessage
691
- if (this._richText !== undefined) meta.richText = this._richText
692
- if (this._recordUrl === false) meta.recordUrl = false
693
- else if (typeof this._recordUrl === 'function') meta.recordUrl = true
694
- // Editable cell columns — chrome that the renderer needs to mount
695
- // the right inline control. Per-row `_cellEditable / _cellEditUrls /
696
- // _cellDisabled` are stamped onto each row by `loadTableRecords` +
697
- // `tagCellEditUrls` and aren't part of the column's static meta.
698
- if (this.isEditable()) {
699
- if (this._confirm !== undefined) meta.confirm = this._confirm
700
- if (this._staticDisabled) meta.disabled = true
701
- const rules = this.getSerializedRules()
702
- if (rules.length > 0) meta.rules = rules
703
- }
704
- this.serializeExtras(meta)
705
- return meta
706
- }
707
-
708
- /** Hook for subclasses to add columnType-specific fields to the meta. */
709
- protected serializeExtras(_meta: ColumnMeta): void {}
710
- }