@pilotiq/pilotiq 0.24.1 → 0.24.3

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 (518) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/boost/guidelines.md +571 -0
  3. package/boost/skills/pilotiq-actions/SKILL.md +49 -0
  4. package/boost/skills/pilotiq-actions/rules/dispatch-modes.md +177 -0
  5. package/boost/skills/pilotiq-actions/rules/factories.md +130 -0
  6. package/boost/skills/pilotiq-actions/rules/visibility-and-authorization.md +125 -0
  7. package/boost/skills/pilotiq-fields/SKILL.md +47 -0
  8. package/boost/skills/pilotiq-fields/rules/field-catalog.md +288 -0
  9. package/boost/skills/pilotiq-fields/rules/reactive-fields.md +199 -0
  10. package/boost/skills/pilotiq-fields/rules/validation.md +198 -0
  11. package/boost/skills/pilotiq-relations/SKILL.md +47 -0
  12. package/boost/skills/pilotiq-relations/rules/relation-managers.md +256 -0
  13. package/boost/skills/pilotiq-relations/rules/repeater-relationship.md +177 -0
  14. package/boost/skills/pilotiq-resource/SKILL.md +61 -0
  15. package/boost/skills/pilotiq-resource/rules/authorization.md +242 -0
  16. package/boost/skills/pilotiq-resource/rules/defining-resources.md +228 -0
  17. package/boost/skills/pilotiq-resource/rules/page-overrides.md +296 -0
  18. package/dist/Pilotiq.d.ts +31 -0
  19. package/dist/Pilotiq.d.ts.map +1 -1
  20. package/dist/Pilotiq.js +3 -1
  21. package/dist/Pilotiq.js.map +1 -1
  22. package/dist/PilotiqRegistry.d.ts +13 -0
  23. package/dist/PilotiqRegistry.d.ts.map +1 -1
  24. package/dist/PilotiqRegistry.js +15 -0
  25. package/dist/PilotiqRegistry.js.map +1 -1
  26. package/dist/pageData/misc.d.ts.map +1 -1
  27. package/dist/pageData/misc.js +6 -0
  28. package/dist/pageData/misc.js.map +1 -1
  29. package/dist/pageData/navigation.d.ts +1 -0
  30. package/dist/pageData/navigation.d.ts.map +1 -1
  31. package/dist/pageData/navigation.js +3 -0
  32. package/dist/pageData/navigation.js.map +1 -1
  33. package/dist/pageData/relationPages.d.ts.map +1 -1
  34. package/dist/pageData/relationPages.js +3 -0
  35. package/dist/pageData/relationPages.js.map +1 -1
  36. package/dist/pageData/resourcePages.d.ts.map +1 -1
  37. package/dist/pageData/resourcePages.js +8 -0
  38. package/dist/pageData/resourcePages.js.map +1 -1
  39. package/dist/react/AppShell.d.ts +8 -0
  40. package/dist/react/AppShell.d.ts.map +1 -1
  41. package/dist/react/AppShell.js.map +1 -1
  42. package/dist/react/layouts/SidebarLayout.d.ts.map +1 -1
  43. package/dist/react/layouts/SidebarLayout.js +10 -2
  44. package/dist/react/layouts/SidebarLayout.js.map +1 -1
  45. package/dist/react/widgets/StatsOverviewRenderer.d.ts.map +1 -1
  46. package/dist/react/widgets/StatsOverviewRenderer.js +32 -18
  47. package/dist/react/widgets/StatsOverviewRenderer.js.map +1 -1
  48. package/dist/routes/relations.d.ts.map +1 -1
  49. package/dist/routes/relations.js +25 -18
  50. package/dist/routes/relations.js.map +1 -1
  51. package/dist/routes/resources.js.map +1 -1
  52. package/package.json +10 -5
  53. package/.turbo/turbo-build.log +0 -8
  54. package/CLAUDE.md +0 -265
  55. package/src/Cluster.test.ts +0 -283
  56. package/src/Cluster.ts +0 -83
  57. package/src/Column.test.ts +0 -199
  58. package/src/Column.ts +0 -710
  59. package/src/Global.test.ts +0 -367
  60. package/src/Global.ts +0 -169
  61. package/src/Page.test.ts +0 -114
  62. package/src/Page.ts +0 -208
  63. package/src/Pilotiq.perf.test.ts +0 -252
  64. package/src/Pilotiq.test.ts +0 -129
  65. package/src/Pilotiq.ts +0 -1158
  66. package/src/PilotiqRegistry.ts +0 -36
  67. package/src/PilotiqServiceProvider.ts +0 -121
  68. package/src/RelationManager.test.ts +0 -400
  69. package/src/RelationManager.ts +0 -527
  70. package/src/RenderHook.test.ts +0 -252
  71. package/src/RenderHook.ts +0 -242
  72. package/src/Resource.test.ts +0 -284
  73. package/src/Resource.ts +0 -526
  74. package/src/RightPanel.test.ts +0 -202
  75. package/src/RightPanel.ts +0 -132
  76. package/src/Tab.test.ts +0 -91
  77. package/src/Tab.ts +0 -156
  78. package/src/UserMenuItem.ts +0 -145
  79. package/src/actions/Action.test.ts +0 -2526
  80. package/src/actions/Action.ts +0 -1515
  81. package/src/actions/ActionGroup.test.ts +0 -112
  82. package/src/actions/ActionGroup.ts +0 -173
  83. package/src/actions/attachFactory.ts +0 -172
  84. package/src/actions/bulkFactories.ts +0 -168
  85. package/src/actions/crudFactories.ts +0 -220
  86. package/src/actions/exportFactory.ts +0 -225
  87. package/src/actions/factoryHelpers.ts +0 -177
  88. package/src/actions/importFactory.ts +0 -243
  89. package/src/actions/index.ts +0 -17
  90. package/src/actions/m2mFactories.ts +0 -193
  91. package/src/actions/relationFactories.ts +0 -372
  92. package/src/applyPageHooks.test.ts +0 -463
  93. package/src/applyPageHooks.ts +0 -330
  94. package/src/authorization.test.ts +0 -483
  95. package/src/breadcrumbs.test.ts +0 -238
  96. package/src/cells/coerce.test.ts +0 -85
  97. package/src/cells/coerce.ts +0 -84
  98. package/src/clusterPaths.ts +0 -35
  99. package/src/columns/BadgeColumn.test.ts +0 -54
  100. package/src/columns/BadgeColumn.ts +0 -32
  101. package/src/columns/BooleanColumn.test.ts +0 -41
  102. package/src/columns/BooleanColumn.ts +0 -18
  103. package/src/columns/ColorColumn.test.ts +0 -37
  104. package/src/columns/ColorColumn.ts +0 -38
  105. package/src/columns/IconColumn.test.ts +0 -54
  106. package/src/columns/IconColumn.ts +0 -37
  107. package/src/columns/ImageColumn.test.ts +0 -41
  108. package/src/columns/ImageColumn.ts +0 -28
  109. package/src/columns/SelectColumn.ts +0 -98
  110. package/src/columns/TextColumn.test.ts +0 -190
  111. package/src/columns/TextColumn.ts +0 -20
  112. package/src/columns/TextInputColumn.ts +0 -68
  113. package/src/columns/ToggleColumn.ts +0 -46
  114. package/src/columns/editableColumns.test.ts +0 -238
  115. package/src/columns/index.ts +0 -9
  116. package/src/defaultGlobalPages.ts +0 -95
  117. package/src/defaultPages.test.ts +0 -634
  118. package/src/defaultPages.ts +0 -617
  119. package/src/defaultViewPage.test.ts +0 -147
  120. package/src/elements/Form.test.ts +0 -223
  121. package/src/elements/Form.ts +0 -416
  122. package/src/elements/ListTabs.ts +0 -28
  123. package/src/elements/Table.test.ts +0 -422
  124. package/src/elements/Table.ts +0 -850
  125. package/src/elements/TableGroup.test.ts +0 -260
  126. package/src/elements/TableGroup.ts +0 -334
  127. package/src/elements/dispatchAction.test.ts +0 -463
  128. package/src/elements/dispatchAction.ts +0 -355
  129. package/src/elements/dispatchForm.test.ts +0 -477
  130. package/src/elements/dispatchForm.ts +0 -1993
  131. package/src/elements/dispatchTable.test.ts +0 -1514
  132. package/src/elements/dispatchTable.ts +0 -745
  133. package/src/elements/index.ts +0 -21
  134. package/src/entries/BadgeEntry.ts +0 -39
  135. package/src/entries/CodeEntry.test.ts +0 -40
  136. package/src/entries/CodeEntry.ts +0 -52
  137. package/src/entries/ColorEntry.ts +0 -63
  138. package/src/entries/ComponentEntry.test.ts +0 -173
  139. package/src/entries/ComponentEntry.ts +0 -95
  140. package/src/entries/Entry.ts +0 -304
  141. package/src/entries/IconEntry.ts +0 -49
  142. package/src/entries/ImageEntry.ts +0 -61
  143. package/src/entries/KeyValueEntry.ts +0 -47
  144. package/src/entries/RepeatableEntry.test.ts +0 -239
  145. package/src/entries/RepeatableEntry.ts +0 -173
  146. package/src/entries/TextEntry.test.ts +0 -394
  147. package/src/entries/TextEntry.ts +0 -60
  148. package/src/entries/index.ts +0 -12
  149. package/src/entries/leaves.test.ts +0 -306
  150. package/src/entries/registry.ts +0 -54
  151. package/src/fields/BuilderField.test.ts +0 -1188
  152. package/src/fields/BuilderField.ts +0 -605
  153. package/src/fields/BuilderRelationship.test.ts +0 -811
  154. package/src/fields/CheckboxField.test.ts +0 -44
  155. package/src/fields/CheckboxField.ts +0 -27
  156. package/src/fields/CheckboxListField.test.ts +0 -99
  157. package/src/fields/CheckboxListField.ts +0 -66
  158. package/src/fields/ColorPickerField.test.ts +0 -33
  159. package/src/fields/ColorPickerField.ts +0 -25
  160. package/src/fields/DateField.ts +0 -54
  161. package/src/fields/DateTimeField.test.ts +0 -55
  162. package/src/fields/EmailField.ts +0 -16
  163. package/src/fields/Field.test.ts +0 -654
  164. package/src/fields/Field.ts +0 -817
  165. package/src/fields/FileUploadField.test.ts +0 -143
  166. package/src/fields/FileUploadField.ts +0 -159
  167. package/src/fields/HiddenField.test.ts +0 -27
  168. package/src/fields/HiddenField.ts +0 -28
  169. package/src/fields/KeyValueField.test.ts +0 -105
  170. package/src/fields/KeyValueField.ts +0 -55
  171. package/src/fields/MarkdownField.test.ts +0 -167
  172. package/src/fields/MarkdownField.ts +0 -162
  173. package/src/fields/NumberField.ts +0 -33
  174. package/src/fields/RadioField.test.ts +0 -94
  175. package/src/fields/RadioField.ts +0 -67
  176. package/src/fields/RepeaterField.test.ts +0 -1806
  177. package/src/fields/RepeaterField.ts +0 -939
  178. package/src/fields/RepeaterRelationship.test.ts +0 -1923
  179. package/src/fields/RepeaterSimple.test.ts +0 -248
  180. package/src/fields/RowButton.test.ts +0 -219
  181. package/src/fields/RowButton.ts +0 -135
  182. package/src/fields/SelectField.test.ts +0 -192
  183. package/src/fields/SelectField.ts +0 -235
  184. package/src/fields/SliderField.test.ts +0 -50
  185. package/src/fields/SliderField.ts +0 -53
  186. package/src/fields/SlugField.ts +0 -24
  187. package/src/fields/TagsInputField.test.ts +0 -154
  188. package/src/fields/TagsInputField.ts +0 -133
  189. package/src/fields/TextField.test.ts +0 -213
  190. package/src/fields/TextField.ts +0 -177
  191. package/src/fields/TextareaField.test.ts +0 -58
  192. package/src/fields/TextareaField.ts +0 -59
  193. package/src/fields/ToggleButtonsField.test.ts +0 -106
  194. package/src/fields/ToggleButtonsField.ts +0 -59
  195. package/src/fields/ToggleField.ts +0 -16
  196. package/src/fields/disableOptionsWhenSelectedInSiblingRepeaterItems.test.ts +0 -319
  197. package/src/fields/optionsResolver.ts +0 -95
  198. package/src/fields/resolveField.ts +0 -28
  199. package/src/filters/BooleanFilter.ts +0 -35
  200. package/src/filters/DateRangeFilter.test.ts +0 -194
  201. package/src/filters/DateRangeFilter.ts +0 -148
  202. package/src/filters/Filter.test.ts +0 -268
  203. package/src/filters/Filter.ts +0 -184
  204. package/src/filters/FormFilter.test.ts +0 -238
  205. package/src/filters/FormFilter.ts +0 -215
  206. package/src/filters/MultiSelectFilter.test.ts +0 -119
  207. package/src/filters/MultiSelectFilter.ts +0 -78
  208. package/src/filters/QueryBuilderFilter.test.ts +0 -662
  209. package/src/filters/QueryBuilderFilter.ts +0 -398
  210. package/src/filters/SelectFilter.ts +0 -46
  211. package/src/filters/TernaryFilter.test.ts +0 -160
  212. package/src/filters/TernaryFilter.ts +0 -72
  213. package/src/filters/TrashedFilter.test.ts +0 -149
  214. package/src/filters/TrashedFilter.ts +0 -55
  215. package/src/filters/queryBuilder/BooleanConstraint.ts +0 -31
  216. package/src/filters/queryBuilder/Constraint.ts +0 -115
  217. package/src/filters/queryBuilder/DateConstraint.ts +0 -69
  218. package/src/filters/queryBuilder/NumberConstraint.ts +0 -66
  219. package/src/filters/queryBuilder/SelectConstraint.ts +0 -72
  220. package/src/filters/queryBuilder/TextConstraint.ts +0 -64
  221. package/src/filters/queryBuilder/index.ts +0 -12
  222. package/src/icons/index.ts +0 -2
  223. package/src/icons/lucide.ts +0 -204
  224. package/src/icons/registry.test.ts +0 -56
  225. package/src/icons/registry.ts +0 -41
  226. package/src/icons/types.ts +0 -47
  227. package/src/index.ts +0 -525
  228. package/src/io/csv.test.ts +0 -142
  229. package/src/io/csv.ts +0 -170
  230. package/src/nestedRelationManagerData.test.ts +0 -547
  231. package/src/notifications/Notification.test.ts +0 -210
  232. package/src/notifications/Notification.ts +0 -354
  233. package/src/notifications/broadcast.test.ts +0 -110
  234. package/src/notifications/broadcast.ts +0 -95
  235. package/src/notifications/database.test.ts +0 -383
  236. package/src/notifications/database.ts +0 -398
  237. package/src/notifications/databaseNotifications.test.ts +0 -187
  238. package/src/notifications/dispatchNotificationAction.test.ts +0 -341
  239. package/src/notifications/dispatchNotificationAction.ts +0 -142
  240. package/src/notifications/flash.test.ts +0 -89
  241. package/src/notifications/flash.ts +0 -71
  242. package/src/notifications/index.ts +0 -45
  243. package/src/notifications/registerBroadcastAuth.test.ts +0 -134
  244. package/src/notifications/registerBroadcastAuth.ts +0 -100
  245. package/src/notifications/resolveSavedNotification.test.ts +0 -82
  246. package/src/notifications/resolveSavedNotification.ts +0 -59
  247. package/src/notifications/types.ts +0 -93
  248. package/src/orm/m2mAccessor.ts +0 -66
  249. package/src/orm/modelDefaults.test.ts +0 -633
  250. package/src/orm/modelDefaults.ts +0 -666
  251. package/src/pageData/breadcrumbs.ts +0 -288
  252. package/src/pageData/forms.ts +0 -578
  253. package/src/pageData/helpers.ts +0 -857
  254. package/src/pageData/misc.ts +0 -347
  255. package/src/pageData/navigation.ts +0 -842
  256. package/src/pageData/relationPages.ts +0 -1248
  257. package/src/pageData/relationTabs.ts +0 -286
  258. package/src/pageData/resourcePages.ts +0 -609
  259. package/src/pageData.test.ts +0 -1545
  260. package/src/pageData.ts +0 -341
  261. package/src/plugins/index.ts +0 -8
  262. package/src/plugins/themeEditor.test.ts +0 -36
  263. package/src/plugins/themeEditor.ts +0 -45
  264. package/src/react/AppShell.tsx +0 -251
  265. package/src/react/CollabExtensionFactoryRegistry.ts +0 -55
  266. package/src/react/CollabRoomContext.ts +0 -98
  267. package/src/react/CollabTextRendererRegistry.ts +0 -102
  268. package/src/react/CommandPalette.tsx +0 -375
  269. package/src/react/CurrentUserContext.tsx +0 -50
  270. package/src/react/CustomPageWrapperGate.tsx +0 -69
  271. package/src/react/CustomPageWrapperRegistry.ts +0 -45
  272. package/src/react/FieldFocusReporterRegistry.ts +0 -37
  273. package/src/react/FieldLabelSlotRegistry.ts +0 -30
  274. package/src/react/FieldPresenceRegistry.ts +0 -46
  275. package/src/react/FormCollabBindingRegistry.ts +0 -242
  276. package/src/react/FormStateContext.tsx +0 -591
  277. package/src/react/HeadHooks.tsx +0 -126
  278. package/src/react/MarkdownEditorRegistry.test.ts +0 -38
  279. package/src/react/MarkdownEditorRegistry.ts +0 -107
  280. package/src/react/NotificationActionStrip.tsx +0 -263
  281. package/src/react/NotificationBell.tsx +0 -426
  282. package/src/react/PendingSuggestionApplierRegistry.test.ts +0 -97
  283. package/src/react/PendingSuggestionApplierRegistry.ts +0 -98
  284. package/src/react/PendingSuggestionOverlayRegistry.ts +0 -54
  285. package/src/react/PendingSuggestionsContext.tsx +0 -172
  286. package/src/react/RecordWrapperGate.tsx +0 -58
  287. package/src/react/RecordWrapperRegistry.ts +0 -39
  288. package/src/react/RenderHookSlot.tsx +0 -32
  289. package/src/react/RightSidebar.tsx +0 -257
  290. package/src/react/RightSidebarContext.tsx +0 -234
  291. package/src/react/RightSidebarTrigger.tsx +0 -53
  292. package/src/react/RowCoordsContext.tsx +0 -23
  293. package/src/react/SchemaRenderer.tsx +0 -549
  294. package/src/react/SearchTrigger.tsx +0 -46
  295. package/src/react/ThemeProvider.tsx +0 -93
  296. package/src/react/ThemeSettingsPage.tsx +0 -579
  297. package/src/react/ThemeToggle.tsx +0 -20
  298. package/src/react/Toaster.tsx +0 -158
  299. package/src/react/UserMenu.tsx +0 -196
  300. package/src/react/WidgetDataContext.tsx +0 -157
  301. package/src/react/cells/EditableCell.tsx +0 -389
  302. package/src/react/component-slots.test.ts +0 -103
  303. package/src/react/component-slots.ts +0 -116
  304. package/src/react/fieldJsHandler.test.ts +0 -166
  305. package/src/react/fieldJsHandler.ts +0 -79
  306. package/src/react/fields/BuilderInput.tsx +0 -1078
  307. package/src/react/fields/CheckboxInput.tsx +0 -39
  308. package/src/react/fields/CheckboxListInput.tsx +0 -102
  309. package/src/react/fields/ColorInput.tsx +0 -71
  310. package/src/react/fields/DateFieldInput.tsx +0 -70
  311. package/src/react/fields/DateTimeInput.tsx +0 -62
  312. package/src/react/fields/FieldShell.tsx +0 -348
  313. package/src/react/fields/FileUploadInput.tsx +0 -639
  314. package/src/react/fields/HiddenInput.tsx +0 -17
  315. package/src/react/fields/KeyValueInput.tsx +0 -230
  316. package/src/react/fields/MarkdownInput.tsx +0 -560
  317. package/src/react/fields/RadioInput.tsx +0 -81
  318. package/src/react/fields/RepeaterInput.test.ts +0 -116
  319. package/src/react/fields/RepeaterInput.tsx +0 -1420
  320. package/src/react/fields/SelectFieldInput.tsx +0 -280
  321. package/src/react/fields/SliderInput.tsx +0 -81
  322. package/src/react/fields/TagsInput.tsx +0 -283
  323. package/src/react/fields/TextLikeInput.tsx +0 -256
  324. package/src/react/fields/ToggleButtonsInput.tsx +0 -60
  325. package/src/react/fields/ToggleFieldInput.tsx +0 -56
  326. package/src/react/fields/relationshipRenameDispatch.test.ts +0 -106
  327. package/src/react/fields/relationshipRenameDispatch.ts +0 -97
  328. package/src/react/fields/repeaterReconcile.test.ts +0 -114
  329. package/src/react/fields/repeaterReconcile.ts +0 -104
  330. package/src/react/fields/rowChromeButton.tsx +0 -336
  331. package/src/react/fields/rowState.ts +0 -106
  332. package/src/react/fields/syncRowGates.test.ts +0 -202
  333. package/src/react/fields/syncRowGates.ts +0 -66
  334. package/src/react/fields/textInputControls.tsx +0 -238
  335. package/src/react/fields/useRowReorderDnd.ts +0 -78
  336. package/src/react/formStateHelpers.test.ts +0 -508
  337. package/src/react/formStateHelpers.ts +0 -381
  338. package/src/react/hooks/use-mobile.ts +0 -19
  339. package/src/react/icon-context.tsx +0 -60
  340. package/src/react/index.ts +0 -194
  341. package/src/react/layouts/SidebarLayout.tsx +0 -250
  342. package/src/react/layouts/TopbarLayout.tsx +0 -258
  343. package/src/react/navigate.tsx +0 -37
  344. package/src/react/onProviderSynced.test.ts +0 -90
  345. package/src/react/parseRecordEditUrl.test.ts +0 -122
  346. package/src/react/parseRecordEditUrl.ts +0 -94
  347. package/src/react/persistedState.ts +0 -40
  348. package/src/react/registry.ts +0 -48
  349. package/src/react/right-panel-registry.tsx +0 -47
  350. package/src/react/schemaRenderer/AlertRenderer.tsx +0 -112
  351. package/src/react/schemaRenderer/EntryRenderer.tsx +0 -501
  352. package/src/react/schemaRenderer/SectionRenderer.tsx +0 -120
  353. package/src/react/schemaRenderer/SimpleElements.tsx +0 -306
  354. package/src/react/schemaRenderer/TabsRenderer.tsx +0 -62
  355. package/src/react/schemaRenderer/WizardRenderer.tsx +0 -338
  356. package/src/react/schemaRenderer/action/ActionGroupTrigger.tsx +0 -177
  357. package/src/react/schemaRenderer/action/ActionModalDialog.tsx +0 -273
  358. package/src/react/schemaRenderer/action/ConfirmActionDialog.tsx +0 -61
  359. package/src/react/schemaRenderer/action/HandlerActionButton.tsx +0 -43
  360. package/src/react/schemaRenderer/action/MethodActionButton.tsx +0 -64
  361. package/src/react/schemaRenderer/action/buttons.tsx +0 -99
  362. package/src/react/schemaRenderer/action/helpers.ts +0 -140
  363. package/src/react/schemaRenderer/action/renderAction.tsx +0 -245
  364. package/src/react/schemaRenderer/columnFormat.ts +0 -65
  365. package/src/react/schemaRenderer/constants.ts +0 -50
  366. package/src/react/schemaRenderer/form/FormRenderer.tsx +0 -274
  367. package/src/react/schemaRenderer/form/renderField.tsx +0 -511
  368. package/src/react/schemaRenderer/helpers.tsx +0 -81
  369. package/src/react/schemaRenderer/table/CardsLayoutBody.tsx +0 -308
  370. package/src/react/schemaRenderer/table/TableRenderer.tsx +0 -123
  371. package/src/react/schemaRenderer/table/TableRendererBody.tsx +0 -974
  372. package/src/react/schemaRenderer/table/filters.tsx +0 -1233
  373. package/src/react/schemaRenderer/table/formatCell.tsx +0 -264
  374. package/src/react/schemaRenderer/table/links.tsx +0 -112
  375. package/src/react/schemaRenderer/table/renderRowActions.tsx +0 -52
  376. package/src/react/schemaRenderer/table/url.tsx +0 -143
  377. package/src/react/theme-preview/apply.ts +0 -99
  378. package/src/react/theme-preview/build-html.ts +0 -436
  379. package/src/react/ui/button.tsx +0 -51
  380. package/src/react/ui/calendar.tsx +0 -67
  381. package/src/react/ui/checkbox.tsx +0 -29
  382. package/src/react/ui/dialog.tsx +0 -108
  383. package/src/react/ui/dropdown-menu.tsx +0 -97
  384. package/src/react/ui/input.tsx +0 -20
  385. package/src/react/ui/label.tsx +0 -21
  386. package/src/react/ui/popover.tsx +0 -50
  387. package/src/react/ui/select.tsx +0 -169
  388. package/src/react/ui/separator.tsx +0 -25
  389. package/src/react/ui/sheet.tsx +0 -136
  390. package/src/react/ui/sidebar.tsx +0 -723
  391. package/src/react/ui/skeleton.tsx +0 -13
  392. package/src/react/ui/slider.tsx +0 -34
  393. package/src/react/ui/switch.tsx +0 -28
  394. package/src/react/ui/table.tsx +0 -105
  395. package/src/react/ui/tabs.tsx +0 -63
  396. package/src/react/ui/textarea.tsx +0 -18
  397. package/src/react/ui/tooltip.tsx +0 -64
  398. package/src/react/useResizableWidth.ts +0 -139
  399. package/src/react/utils.ts +0 -6
  400. package/src/react/widgetRegistry.test.ts +0 -43
  401. package/src/react/widgetRegistry.ts +0 -50
  402. package/src/react/widgets/StatsOverviewRenderer.tsx +0 -232
  403. package/src/react/widgets/TableWidgetRenderer.tsx +0 -231
  404. package/src/react/widgets/ViewRenderer.tsx +0 -71
  405. package/src/relationManagerData.test.ts +0 -1595
  406. package/src/richtext/index.ts +0 -8
  407. package/src/richtext/registry.ts +0 -89
  408. package/src/routes/globals.ts +0 -148
  409. package/src/routes/guard.test.ts +0 -325
  410. package/src/routes/helpers.ts +0 -704
  411. package/src/routes/pages.ts +0 -175
  412. package/src/routes/panel.ts +0 -204
  413. package/src/routes/relations.ts +0 -1243
  414. package/src/routes/resources.ts +0 -781
  415. package/src/routes/theme.ts +0 -91
  416. package/src/routes-nested-relations.test.ts +0 -676
  417. package/src/routes-relations.test.ts +0 -972
  418. package/src/routes.test.ts +0 -2027
  419. package/src/routes.ts +0 -303
  420. package/src/schema/Alert.test.ts +0 -109
  421. package/src/schema/Alert.ts +0 -131
  422. package/src/schema/Block.ts +0 -169
  423. package/src/schema/Breadcrumbs.ts +0 -40
  424. package/src/schema/Card.ts +0 -35
  425. package/src/schema/Divider.ts +0 -20
  426. package/src/schema/Element.ts +0 -219
  427. package/src/schema/EmptyState.test.ts +0 -37
  428. package/src/schema/EmptyState.ts +0 -63
  429. package/src/schema/Fieldset.ts +0 -43
  430. package/src/schema/Grid.ts +0 -43
  431. package/src/schema/Group.ts +0 -30
  432. package/src/schema/Heading.ts +0 -39
  433. package/src/schema/Html.ts +0 -67
  434. package/src/schema/Icon.ts +0 -54
  435. package/src/schema/Image.ts +0 -57
  436. package/src/schema/LinkTag.ts +0 -41
  437. package/src/schema/Markdown.ts +0 -85
  438. package/src/schema/MetaTag.ts +0 -41
  439. package/src/schema/RelationTabs.ts +0 -71
  440. package/src/schema/ScriptTag.ts +0 -55
  441. package/src/schema/Section.ts +0 -160
  442. package/src/schema/ServerDataElement.test.ts +0 -140
  443. package/src/schema/ServerDataElement.ts +0 -156
  444. package/src/schema/SlotComponent.test.ts +0 -77
  445. package/src/schema/SlotComponent.ts +0 -71
  446. package/src/schema/Split.ts +0 -50
  447. package/src/schema/Stat.test.ts +0 -118
  448. package/src/schema/Stat.ts +0 -154
  449. package/src/schema/StatsOverview.test.ts +0 -141
  450. package/src/schema/StatsOverview.ts +0 -119
  451. package/src/schema/StyleTag.ts +0 -35
  452. package/src/schema/TableWidget.test.ts +0 -297
  453. package/src/schema/TableWidget.ts +0 -289
  454. package/src/schema/Tabs.ts +0 -79
  455. package/src/schema/Text.ts +0 -58
  456. package/src/schema/UnorderedList.ts +0 -49
  457. package/src/schema/View.test.ts +0 -111
  458. package/src/schema/View.ts +0 -127
  459. package/src/schema/Wizard.ts +0 -220
  460. package/src/schema/containers.test.ts +0 -564
  461. package/src/schema/headTags.test.ts +0 -134
  462. package/src/schema/index.ts +0 -40
  463. package/src/schema/primes.test.ts +0 -269
  464. package/src/schema/resolveSchema.test.ts +0 -379
  465. package/src/schema/resolveSchema.ts +0 -917
  466. package/src/schema/sanitize.ts +0 -58
  467. package/src/search.test.ts +0 -446
  468. package/src/search.ts +0 -178
  469. package/src/sessionFilters.test.ts +0 -375
  470. package/src/sessionFilters.ts +0 -143
  471. package/src/slot-components/index.ts +0 -10
  472. package/src/slot-components/registry.ts +0 -56
  473. package/src/styles/file-upload.css +0 -13
  474. package/src/summarizers/Summarizer.test.ts +0 -84
  475. package/src/summarizers/Summarizer.ts +0 -123
  476. package/src/summarizers/index.ts +0 -11
  477. package/src/theme/base-colors.ts +0 -68
  478. package/src/theme/chart-colors.ts +0 -50
  479. package/src/theme/colors.ts +0 -447
  480. package/src/theme/generate-css.test.ts +0 -139
  481. package/src/theme/generate-css.ts +0 -44
  482. package/src/theme/generate-scale.test.ts +0 -106
  483. package/src/theme/generate-scale.ts +0 -97
  484. package/src/theme/icon-map.ts +0 -42
  485. package/src/theme/index.ts +0 -34
  486. package/src/theme/migrate.test.ts +0 -178
  487. package/src/theme/migrate.ts +0 -81
  488. package/src/theme/presets.ts +0 -135
  489. package/src/theme/radius.ts +0 -18
  490. package/src/theme/resolve.test.ts +0 -238
  491. package/src/theme/resolve.ts +0 -96
  492. package/src/theme/spacing.ts +0 -18
  493. package/src/theme/storage.test.ts +0 -126
  494. package/src/theme/storage.ts +0 -106
  495. package/src/theme/theme-colors.ts +0 -88
  496. package/src/theme/types.ts +0 -125
  497. package/src/uploads/UploadAdapter.ts +0 -35
  498. package/src/uploads/index.ts +0 -2
  499. package/src/uploads/localUpload.test.ts +0 -70
  500. package/src/uploads/localUpload.ts +0 -84
  501. package/src/validation/Validator.ts +0 -49
  502. package/src/validation/index.ts +0 -28
  503. package/src/validation/rules.ts +0 -78
  504. package/src/validation/runValidators.ts +0 -435
  505. package/src/validation/uniqueValidator.test.ts +0 -196
  506. package/src/validation/uniqueValidator.ts +0 -133
  507. package/src/validation/validators.test.ts +0 -268
  508. package/src/vite.test.ts +0 -184
  509. package/src/vite.ts +0 -787
  510. package/src/widgets/index.ts +0 -10
  511. package/src/widgets/registry.ts +0 -45
  512. package/src/widgets.test.ts +0 -592
  513. package/tsconfig.build.json +0 -11
  514. package/tsconfig.json +0 -4
  515. package/tsconfig.test.json +0 -10
  516. package/views/react/Dashboard.tsx +0 -27
  517. package/views/react/Resources/Form.tsx +0 -102
  518. package/views/react/Resources/Index.tsx +0 -49
@@ -1,126 +0,0 @@
1
- import { describe, it, beforeEach } from 'node:test'
2
- import assert from 'node:assert/strict'
3
- import { prismaThemeStorage } from './storage.js'
4
- import type { PanelGlobalDelegate } from './storage.js'
5
-
6
- /**
7
- * Per-test stub for the prisma panelGlobal delegate. Captures the args
8
- * each method was called with so tests can assert the exact wire shape
9
- * we send Prisma (slug, JSON-encoded data, etc).
10
- */
11
- interface PrismaStub extends PanelGlobalDelegate {
12
- rows: Map<string, { data: string | object | null }>
13
- calls: { method: string; args: unknown }[]
14
- /** When set, the next call to this method throws this error. */
15
- throwOnce?: { method: 'findUnique' | 'upsert' | 'delete'; error: unknown }
16
- }
17
-
18
- function makeStub(initial: Record<string, unknown> = {}): PrismaStub {
19
- const rows = new Map<string, { data: string | object | null }>()
20
- for (const [slug, data] of Object.entries(initial)) {
21
- rows.set(slug, { data: typeof data === 'string' ? data : JSON.stringify(data) })
22
- }
23
- const calls: { method: string; args: unknown }[] = []
24
- const stub: PrismaStub = {
25
- rows,
26
- calls,
27
- panelGlobal: {
28
- async findUnique(args) {
29
- calls.push({ method: 'findUnique', args })
30
- if (stub.throwOnce?.method === 'findUnique') {
31
- const e = stub.throwOnce.error; delete stub.throwOnce; throw e
32
- }
33
- return rows.get(args.where.slug) ?? null
34
- },
35
- async upsert(args) {
36
- calls.push({ method: 'upsert', args })
37
- if (stub.throwOnce?.method === 'upsert') {
38
- const e = stub.throwOnce.error; delete stub.throwOnce; throw e
39
- }
40
- rows.set(args.where.slug, { data: args.update.data })
41
- return undefined
42
- },
43
- async delete(args) {
44
- calls.push({ method: 'delete', args })
45
- if (stub.throwOnce?.method === 'delete') {
46
- const e = stub.throwOnce.error; delete stub.throwOnce; throw e
47
- }
48
- if (!rows.has(args.where.slug)) {
49
- const e: Error & { code?: string } = new Error('Record not found')
50
- e.code = 'P2025'
51
- throw e
52
- }
53
- rows.delete(args.where.slug)
54
- return undefined
55
- },
56
- },
57
- }
58
- return stub
59
- }
60
-
61
- describe('prismaThemeStorage', () => {
62
- let prisma: PrismaStub
63
-
64
- beforeEach(() => { prisma = makeStub() })
65
-
66
- it('load() returns null when no row exists', async () => {
67
- const storage = prismaThemeStorage(prisma, { slug: 'admin__theme' })
68
- assert.equal(await storage.load(), null)
69
- assert.deepEqual(prisma.calls, [{ method: 'findUnique', args: { where: { slug: 'admin__theme' } } }])
70
- })
71
-
72
- it('load() parses JSON-string data', async () => {
73
- prisma.rows.set('admin__theme', { data: JSON.stringify({ preset: 'nova' }) })
74
- const storage = prismaThemeStorage(prisma, { slug: 'admin__theme' })
75
- assert.deepEqual(await storage.load(), { preset: 'nova' })
76
- })
77
-
78
- it('load() passes through pre-parsed object data', async () => {
79
- prisma.rows.set('admin__theme', { data: { preset: 'maia' } })
80
- const storage = prismaThemeStorage(prisma, { slug: 'admin__theme' })
81
- assert.deepEqual(await storage.load(), { preset: 'maia' })
82
- })
83
-
84
- it('save() JSON-encodes the overrides via upsert', async () => {
85
- const storage = prismaThemeStorage(prisma, { slug: 'admin__theme' })
86
- await storage.save({ preset: 'lyra', radius: 'medium' })
87
- const stored = prisma.rows.get('admin__theme')
88
- assert.ok(stored)
89
- assert.equal(typeof stored.data, 'string')
90
- assert.deepEqual(JSON.parse(stored.data as string), { preset: 'lyra', radius: 'medium' })
91
- const upsertCall = prisma.calls.find(c => c.method === 'upsert')
92
- assert.ok(upsertCall, 'expected upsert call')
93
- })
94
-
95
- it('clear() deletes the row', async () => {
96
- prisma.rows.set('admin__theme', { data: '{}' })
97
- const storage = prismaThemeStorage(prisma, { slug: 'admin__theme' })
98
- await storage.clear()
99
- assert.equal(prisma.rows.has('admin__theme'), false)
100
- })
101
-
102
- it('clear() tolerates "row not found" (P2025)', async () => {
103
- const storage = prismaThemeStorage(prisma, { slug: 'admin__theme' })
104
- // Row does not exist — stub throws P2025 — clear() must not propagate.
105
- await storage.clear()
106
- })
107
-
108
- it('clear() rethrows non-P2025 errors', async () => {
109
- prisma.rows.set('admin__theme', { data: '{}' })
110
- prisma.throwOnce = { method: 'delete', error: new Error('connection lost') }
111
- const storage = prismaThemeStorage(prisma, { slug: 'admin__theme' })
112
- await assert.rejects(() => storage.clear(), /connection lost/)
113
- })
114
-
115
- it('save() bubbles non-P2025 errors', async () => {
116
- prisma.throwOnce = { method: 'upsert', error: new Error('connection lost') }
117
- const storage = prismaThemeStorage(prisma, { slug: 'admin__theme' })
118
- await assert.rejects(() => storage.save({ preset: 'nova' }), /connection lost/)
119
- })
120
-
121
- it('load() bubbles errors (callers swallow if they want back-compat)', async () => {
122
- prisma.throwOnce = { method: 'findUnique', error: new Error('connection lost') }
123
- const storage = prismaThemeStorage(prisma, { slug: 'admin__theme' })
124
- await assert.rejects(() => storage.load(), /connection lost/)
125
- })
126
- })
@@ -1,106 +0,0 @@
1
- import type { ThemeConfig } from './types.js'
2
-
3
- /**
4
- * Adapter that persists a panel's theme overrides — the JSON blob
5
- * written when a user edits theme settings via the `themeEditor()`
6
- * plugin and reloaded on next boot.
7
- *
8
- * The shipped implementation is `prismaThemeStorage`, which writes to
9
- * the `panelGlobal` row created by `@rudderjs/orm-prisma`. Apps on a
10
- * different ORM, key-value store, or filesystem can implement the
11
- * three methods themselves.
12
- *
13
- * Contract:
14
- *
15
- * - `load()` returns `null` when no overrides have been persisted yet
16
- * (fresh install). Throwing surfaces a configuration error to the
17
- * caller — pilotiq does not swallow.
18
- * - `save(overrides)` writes the blob verbatim. The next `load()` must
19
- * return a deep-equal copy. Throwing surfaces to the route handler
20
- * as a 500.
21
- * - `clear()` deletes the row. Tolerating "not found" is the adapter's
22
- * responsibility — `clear()` on an empty store is a no-op.
23
- */
24
- export interface ThemeStorageAdapter {
25
- load(): Promise<Partial<ThemeConfig> | null>
26
- save(overrides: Partial<ThemeConfig>): Promise<void>
27
- clear(): Promise<void>
28
- }
29
-
30
- /**
31
- * Minimal Prisma surface used by `prismaThemeStorage`. Narrow enough
32
- * to keep the import surface decoupled from `PrismaClient`'s generated
33
- * types — apps swap in any client whose `panelGlobal` delegate matches
34
- * this shape.
35
- */
36
- export interface PanelGlobalDelegate {
37
- panelGlobal: {
38
- findUnique(args: { where: { slug: string } }): Promise<{ data: string | object | null } | null>
39
- upsert(args: {
40
- where: { slug: string }
41
- update: { data: string }
42
- create: { slug: string; data: string }
43
- }): Promise<unknown>
44
- delete(args: { where: { slug: string } }): Promise<unknown>
45
- }
46
- }
47
-
48
- export interface PrismaThemeStorageOptions {
49
- /** Row key written to `panelGlobal.slug`. Pass per-panel so multiple
50
- * panels in the same app don't clobber each other. Typically
51
- * `${panel.name}__theme`. */
52
- slug: string
53
- }
54
-
55
- /**
56
- * Default storage adapter — writes JSON to the `panelGlobal` row keyed
57
- * by `opts.slug`. The Prisma delegate is dependency-injected so consumers
58
- * pick how to resolve it (e.g. `app.make('prisma')`, a direct import, a
59
- * test stub).
60
- *
61
- * @example
62
- * ```ts
63
- * import { Pilotiq } from '@pilotiq/pilotiq'
64
- * import { themeEditor, prismaThemeStorage } from '@pilotiq/pilotiq/plugins'
65
- *
66
- * const adminPanel = Pilotiq.make('Admin')
67
- * .use(themeEditor({
68
- * storage: prismaThemeStorage(prisma, { slug: 'admin__theme' }),
69
- * }))
70
- * ```
71
- */
72
- export function prismaThemeStorage(
73
- prisma: PanelGlobalDelegate,
74
- opts: PrismaThemeStorageOptions,
75
- ): ThemeStorageAdapter {
76
- const { slug } = opts
77
- return {
78
- async load() {
79
- const row = await prisma.panelGlobal.findUnique({ where: { slug } })
80
- if (!row?.data) return null
81
- const raw = typeof row.data === 'string' ? JSON.parse(row.data) : row.data
82
- return raw as Partial<ThemeConfig>
83
- },
84
- async save(overrides) {
85
- const data = JSON.stringify(overrides)
86
- await prisma.panelGlobal.upsert({
87
- where: { slug },
88
- update: { data },
89
- create: { slug, data },
90
- })
91
- },
92
- async clear() {
93
- try {
94
- await prisma.panelGlobal.delete({ where: { slug } })
95
- } catch (e) {
96
- if (!isRecordNotFound(e)) throw e
97
- }
98
- },
99
- }
100
- }
101
-
102
- function isRecordNotFound(e: unknown): boolean {
103
- return typeof e === 'object'
104
- && e !== null
105
- && (e as { code?: string }).code === 'P2025'
106
- }
@@ -1,88 +0,0 @@
1
- import { colors, HUE_NAMES, type ColorScale } from './colors.js'
2
- import type { BaseColor, HueColor, ThemeColor, PresetDefinition } from './types.js'
3
- import { parseSeedToScale } from './generate-scale.js'
4
-
5
- /**
6
- * Theme (primary) color resolution.
7
- *
8
- * The theme color drives `--primary`, `--primary-foreground`, `--ring`, and
9
- * the matching sidebar variants. Built from a `ColorScale` so adding a new
10
- * hue is just adding an entry to `colors.ts`.
11
- *
12
- * The `'base'` sentinel means "use the current base color" — resolution
13
- * pulls the matching scale from `colors[baseColor]` at call time.
14
- *
15
- * Custom seeds (raw hex / oklch strings outside the `HueColor` union) are
16
- * parsed into a synthetic 50…950 scale via `parseSeedToScale`.
17
- */
18
-
19
- /**
20
- * Build the primary/ring overrides for a given color scale.
21
- *
22
- * `isBase` toggles between two strategies:
23
- * - **base sentinel** (e.g. Theme = "Neutral"): use the strongest contrast
24
- * *within the same scale* — primary is scale[900] in light, scale[50] in
25
- * dark. Matches shadcn's neutral theme behavior (very dark/light primary).
26
- * - **hue** (e.g. Theme = "Blue"): use scale[600] in BOTH light and dark so
27
- * the brand color stays consistent across modes (instead of lifting to
28
- * scale[400] in dark, which dilutes brand identity). Foreground stays the
29
- * near-white neutral[50] for AA contrast against the saturated mid-tone.
30
- */
31
- function buildTheme(scale: ColorScale, isBase = false): PresetDefinition {
32
- if (isBase) {
33
- return {
34
- light: {
35
- '--primary': scale[900],
36
- '--primary-foreground': scale[50],
37
- '--ring': scale[400],
38
- '--sidebar-primary': scale[900],
39
- '--sidebar-primary-foreground': scale[50],
40
- '--sidebar-ring': scale[400],
41
- },
42
- dark: {
43
- '--primary': scale[50],
44
- '--primary-foreground': scale[900],
45
- '--ring': scale[600],
46
- '--sidebar-primary': scale[50],
47
- '--sidebar-primary-foreground': scale[900],
48
- '--sidebar-ring': scale[600],
49
- },
50
- }
51
- }
52
- return {
53
- light: {
54
- '--primary': scale[600],
55
- '--primary-foreground': colors.neutral[50],
56
- '--ring': scale[600],
57
- '--sidebar-primary': scale[600],
58
- '--sidebar-primary-foreground': colors.neutral[50],
59
- '--sidebar-ring': scale[600],
60
- },
61
- dark: {
62
- '--primary': scale[600],
63
- '--primary-foreground': colors.neutral[50],
64
- '--ring': scale[600],
65
- '--sidebar-primary': scale[600],
66
- '--sidebar-primary-foreground': colors.neutral[50],
67
- '--sidebar-ring': scale[600],
68
- },
69
- }
70
- }
71
-
72
- const themeColorMap: Record<HueColor, PresetDefinition> = Object.fromEntries(
73
- HUE_NAMES.map(name => [name, buildTheme(colors[name])]),
74
- ) as Record<HueColor, PresetDefinition>
75
-
76
- /**
77
- * Resolve a theme color value to its CSS variable overrides.
78
- *
79
- * @param themeColor selected value — `'base'`, a known hue, or a raw seed string
80
- * @param baseColor current base color (used to resolve `'base'` sentinel)
81
- */
82
- export function resolveThemeColor(themeColor: ThemeColor, baseColor: BaseColor): PresetDefinition {
83
- if (themeColor === 'base') return buildTheme(colors[baseColor], true)
84
- if (themeColor in themeColorMap) return themeColorMap[themeColor as HueColor]
85
- // Custom seed — parse and synthesize a scale.
86
- const synthetic = parseSeedToScale(themeColor)
87
- return synthetic ? buildTheme(synthetic) : buildTheme(colors[baseColor], true)
88
- }
@@ -1,125 +0,0 @@
1
- import { BASE_COLOR_NAMES, HUE_NAMES } from './colors.js'
2
-
3
- // ─── Style Presets ─────────────────────────────────────────
4
-
5
- /** Built-in style presets — each defines a complete set of OKLCH CSS variables.
6
- * `vega` is the Pilotiq brand (terracotta on cream, Satoshi). The other six are
7
- * placeholder neutrals awaiting visual differentiation. */
8
- export type StylePreset = 'vega' | 'nova' | 'maia' | 'lyra' | 'mira' | 'luma' | 'sera'
9
-
10
- // ─── Base Colors (gray/neutral scales) ─────────────────────
11
-
12
- /** Base color scale — controls the neutral/gray tones across the UI. */
13
- export type BaseColor = typeof BASE_COLOR_NAMES[number]
14
-
15
- // ─── Theme + Chart Colors ──────────────────────────────────
16
-
17
- /** Hue tokens shared by both the Theme color and Chart color pickers. */
18
- export type HueColor = typeof HUE_NAMES[number]
19
-
20
- /** Theme (primary) color — drives buttons, links, active states, ring.
21
- * `'base'` means "use the current base color's hue". Strings outside the
22
- * union are treated as raw hex/oklch seeds (custom color escape hatch). */
23
- export type ThemeColor = 'base' | HueColor | (string & {})
24
-
25
- /** Chart palette color — drives `--chart-1..5` as a single-hue ramp.
26
- * Same shape as `ThemeColor`. */
27
- export type ChartColor = ThemeColor
28
-
29
- // ─── Radius ────────────────────────────────────────────────
30
-
31
- /** Border radius preset. */
32
- export type RadiusPreset = 'none' | 'small' | 'default' | 'medium' | 'large' | 'xlarge'
33
-
34
- // ─── Spacing (UI density) ──────────────────────────────────
35
-
36
- /** Spacing density preset — drives Tailwind's `--spacing` multiplier so every
37
- * `p-*`, `gap-*`, `m-*` utility scales uniformly across the panel. */
38
- export type SpacingPreset = 'default' | 'compact' | 'comfortable'
39
-
40
- // ─── Icon Library ──────────────────────────────────────────
41
-
42
- /** Icon library identifier — controls which icon set is resolved. */
43
- export type IconLibrary = 'lucide' | 'tabler' | 'remix' | 'phosphor'
44
-
45
- // ─── Fonts ─────────────────────────────────────────────────
46
-
47
- export interface ThemeFonts {
48
- /** Google Fonts family name for headings, e.g. 'Space Grotesk'. */
49
- heading?: string
50
- /** Google Fonts family name for body text, e.g. 'Inter'. */
51
- body?: string
52
- }
53
-
54
- // ─── Theme Config (user-facing) ────────────────────────────
55
-
56
- /**
57
- * Theme configuration — passed to `Pilotiq.theme()`.
58
- *
59
- * @example
60
- * ```ts
61
- * Pilotiq.make('admin').theme({
62
- * preset: 'vega',
63
- * baseColor: 'taupe',
64
- * themeColor: 'orange',
65
- * chartColor: 'base',
66
- * radius: 'medium',
67
- * fonts: { heading: 'Space Grotesk', body: 'Inter' },
68
- * })
69
- * ```
70
- */
71
- export interface ThemeConfig {
72
- /** Style preset — sets all CSS variables at once. Defaults to `'vega'`. */
73
- preset?: StylePreset
74
- /** Base color scale — overrides neutral/gray tones from the preset. */
75
- baseColor?: BaseColor
76
- /** Theme (primary) color. `'base'` = derive from current base color. */
77
- themeColor?: ThemeColor
78
- /** Chart color. `'base'` = derive ramp from current base color. */
79
- chartColor?: ChartColor
80
- /** Border radius preset. Defaults to `'medium'` (Pilotiq brand). */
81
- radius?: RadiusPreset
82
- /** Spacing density preset. `'default'` falls through to the per-style value
83
- * in `PRESET_SPACING` (e.g. Mira → compact, Vega → comfortable). */
84
- spacing?: SpacingPreset
85
- /** Font families (loaded from Google Fonts / Fontshare). */
86
- fonts?: ThemeFonts
87
- /** Icon library. */
88
- iconLibrary?: IconLibrary
89
- /** Escape hatch: raw CSS variable overrides in OKLCH. Applied last, highest priority. */
90
- cssVariables?: {
91
- light?: Record<string, string>
92
- dark?: Record<string, string>
93
- }
94
- }
95
-
96
- // ─── Theme Meta (serialized, server → client) ──────────────
97
-
98
- /** Resolved theme data sent from server to client via viewProps. */
99
- export interface ThemeMeta {
100
- /** CSS variable map for :root (light mode). Keys are CSS custom property names. */
101
- light: Record<string, string>
102
- /** CSS variable map for .dark (dark mode). */
103
- dark: Record<string, string>
104
- /** Border radius value (e.g. '0.625rem'). */
105
- radius: string
106
- /** Spacing multiplier for Tailwind's `--spacing` token (e.g. '0.25rem'). */
107
- spacing: string
108
- /** Google Fonts families to load via <link> tag. */
109
- fonts?: ThemeFonts
110
- /** Font family CSS values with fallbacks (e.g. "'Inter', sans-serif"). */
111
- fontFamily?: {
112
- heading?: string
113
- body?: string
114
- }
115
- /** Icon library identifier for frontend icon resolution. */
116
- iconLibrary: IconLibrary
117
- }
118
-
119
- // ─── Preset Definition ─────────────────────────────────────
120
-
121
- /** A complete set of CSS variable values for light and dark modes (OKLCH strings). */
122
- export interface PresetDefinition {
123
- light: Record<string, string>
124
- dark: Record<string, string>
125
- }
@@ -1,35 +0,0 @@
1
- /**
2
- * Pilotiq's upload contract. Apps register an adapter via
3
- * `Pilotiq.uploads({ adapter })`; the `_uploads` route hands every
4
- * incoming file to it. Pilotiq stays storage-agnostic — disk, S3,
5
- * R2, GCS, or a custom storage backend all implement the same shape.
6
- */
7
- export interface UploadAdapter {
8
- /**
9
- * Persist the file. Receive `{ file, directory? }`; return the
10
- * URL the field should store. Throw to fail the upload — the
11
- * route handler converts thrown errors into a 500 + toast.
12
- */
13
- put(req: UploadRequest): Promise<UploadResult>
14
- }
15
-
16
- export interface UploadRequest {
17
- /** The browser-supplied File. Has `.name`, `.size`, `.type`, `.arrayBuffer()`. */
18
- file: File
19
- /** Optional sub-directory hint set by `FileUpload.directory(...)`. */
20
- directory?: string
21
- /** The source field name — useful for adapter routing or audit logs. */
22
- fieldName: string
23
- }
24
-
25
- export interface UploadResult {
26
- /** The public URL the field stores in the form value. */
27
- url: string
28
- /**
29
- * Optional metadata to round-trip alongside the URL — file size,
30
- * content type, etc. Renderers that show previews may use this.
31
- * Not part of the form value; can be used by `afterStateUpdated`
32
- * hooks server-side.
33
- */
34
- meta?: Record<string, unknown>
35
- }
@@ -1,2 +0,0 @@
1
- export type { UploadAdapter, UploadRequest, UploadResult } from './UploadAdapter.js'
2
- export { localUpload, type LocalUploadConfig } from './localUpload.js'
@@ -1,70 +0,0 @@
1
- import { describe, it, before, after } from 'node:test'
2
- import assert from 'node:assert/strict'
3
- import { mkdtempSync, existsSync, readFileSync, rmSync } from 'node:fs'
4
- import { tmpdir } from 'node:os'
5
- import { join } from 'node:path'
6
-
7
- import { localUpload } from './localUpload.js'
8
-
9
- describe('localUpload adapter', () => {
10
- let dir: string
11
-
12
- before(() => {
13
- dir = mkdtempSync(join(tmpdir(), 'pilotiq-uploads-'))
14
- })
15
-
16
- after(() => {
17
- rmSync(dir, { recursive: true, force: true })
18
- })
19
-
20
- it('writes the file under root + returns a URL', async () => {
21
- const adapter = localUpload({ root: dir, urlPrefix: '/uploads' })
22
- const file = new File([new Uint8Array([1, 2, 3, 4])], 'photo.png', { type: 'image/png' })
23
- const result = await adapter.put({ file, fieldName: 'cover' })
24
-
25
- assert.match(result.url, /^\/uploads\/[a-f0-9]{32}\.png$/)
26
- assert.deepEqual(result.meta, { name: 'photo.png', size: 4, type: 'image/png' })
27
-
28
- const filename = result.url.replace('/uploads/', '')
29
- const fullPath = join(dir, filename)
30
- assert.ok(existsSync(fullPath), 'file was written to disk')
31
- const written = readFileSync(fullPath)
32
- assert.deepEqual(Array.from(written), [1, 2, 3, 4])
33
- })
34
-
35
- it('honors the directory option', async () => {
36
- const adapter = localUpload({ root: dir, urlPrefix: '/uploads' })
37
- const file = new File([new Uint8Array([0])], 'img.jpg', { type: 'image/jpeg' })
38
- const result = await adapter.put({ file, fieldName: 'avatar', directory: 'avatars/2026' })
39
- assert.match(result.url, /^\/uploads\/avatars\/2026\/[a-f0-9]{32}\.jpg$/)
40
- })
41
-
42
- it('strips path-traversal segments from directory', async () => {
43
- const adapter = localUpload({ root: dir, urlPrefix: '/uploads' })
44
- const file = new File([new Uint8Array([0])], 'x.png', { type: 'image/png' })
45
- const result = await adapter.put({ file, fieldName: 'x', directory: '../../../etc/passwd' })
46
- assert.match(result.url, /^\/uploads\/etc\/passwd\/[a-f0-9]{32}\.png$/)
47
- })
48
-
49
- it('drops over-long extensions (anti-traversal)', async () => {
50
- const adapter = localUpload({ root: dir, urlPrefix: '/uploads' })
51
- const file = new File([new Uint8Array([0])], 'note.thisisaverylongext', { type: 'text/plain' })
52
- const result = await adapter.put({ file, fieldName: 'x' })
53
- // Disallowed ext (>10 chars) → file written without extension
54
- assert.match(result.url, /^\/uploads\/[a-f0-9]{32}$/)
55
- })
56
-
57
- it('drops extensions with non-alphanumeric chars', async () => {
58
- const adapter = localUpload({ root: dir, urlPrefix: '/uploads' })
59
- const file = new File([new Uint8Array([0])], 'note.png; rm -rf', { type: 'text/plain' })
60
- const result = await adapter.put({ file, fieldName: 'x' })
61
- assert.match(result.url, /^\/uploads\/[a-f0-9]{32}$/)
62
- })
63
-
64
- it('strips trailing slash from urlPrefix', async () => {
65
- const adapter = localUpload({ root: dir, urlPrefix: '/uploads/' })
66
- const file = new File([new Uint8Array([0])], 'x.png', { type: 'image/png' })
67
- const result = await adapter.put({ file, fieldName: 'x' })
68
- assert.match(result.url, /^\/uploads\/[a-f0-9]{32}\.png$/)
69
- })
70
- })
@@ -1,84 +0,0 @@
1
- import { mkdir, writeFile } from 'node:fs/promises'
2
- import { join, extname } from 'node:path'
3
- import { randomBytes } from 'node:crypto'
4
-
5
- import type { UploadAdapter, UploadRequest, UploadResult } from './UploadAdapter.js'
6
-
7
- export interface LocalUploadConfig {
8
- /**
9
- * Filesystem directory where files are written. Resolved relative to
10
- * `process.cwd()` if not absolute. The app's static-file middleware
11
- * must serve this directory at `urlPrefix`.
12
- *
13
- * Example: `{ root: 'public/uploads', urlPrefix: '/uploads' }` writes
14
- * to `<cwd>/public/uploads/<dir>/<id>.<ext>` and returns
15
- * `/uploads/<dir>/<id>.<ext>`.
16
- */
17
- root: string
18
- /** URL prefix the file is served from. Without trailing slash. */
19
- urlPrefix: string
20
- }
21
-
22
- /**
23
- * Disk-backed upload adapter. Writes incoming files under
24
- * `config.root/<directory>/<random-id>.<ext>` and returns the public
25
- * URL `<urlPrefix>/<directory>/<random-id>.<ext>`.
26
- *
27
- * v1: synchronous-ish (single `writeFile` per upload). No chunking,
28
- * no resumable uploads, no image processing.
29
- */
30
- export function localUpload(config: LocalUploadConfig): UploadAdapter {
31
- return {
32
- async put(req: UploadRequest): Promise<UploadResult> {
33
- const { file, directory } = req
34
- const ext = sanitizeExt(extname(file.name))
35
- const id = randomId()
36
- const subDir = sanitizeDir(directory)
37
- const fullDir = subDir
38
- ? join(config.root, subDir)
39
- : config.root
40
-
41
- await mkdir(fullDir, { recursive: true })
42
-
43
- const filename = `${id}${ext}`
44
- const fullPath = join(fullDir, filename)
45
- const buffer = Buffer.from(await file.arrayBuffer())
46
- await writeFile(fullPath, buffer)
47
-
48
- const urlParts = [config.urlPrefix.replace(/\/$/, '')]
49
- if (subDir) urlParts.push(subDir)
50
- urlParts.push(filename)
51
- return {
52
- url: urlParts.join('/'),
53
- meta: {
54
- name: file.name,
55
- size: file.size,
56
- type: file.type,
57
- },
58
- }
59
- },
60
- }
61
- }
62
-
63
- function sanitizeDir(d: string | undefined): string {
64
- if (!d) return ''
65
- // Strip leading/trailing slashes and any ../ segments to avoid path
66
- // traversal. Adapters are responsible for their own input validation.
67
- return d
68
- .replace(/^[/\\]+/, '')
69
- .replace(/[/\\]+$/, '')
70
- .split(/[/\\]/)
71
- .filter(s => s !== '' && s !== '..' && s !== '.')
72
- .join('/')
73
- }
74
-
75
- function sanitizeExt(ext: string): string {
76
- // Extension comes from a user-uploaded filename — keep it conservative.
77
- if (!ext || ext.length > 10) return ''
78
- if (!/^\.[A-Za-z0-9]+$/.test(ext)) return ''
79
- return ext.toLowerCase()
80
- }
81
-
82
- function randomId(): string {
83
- return randomBytes(16).toString('hex')
84
- }