torch-glare 2.5.5 → 2.6.0

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 (359) hide show
  1. package/README.md +4 -3
  2. package/dist/bin/index.js +9 -24
  3. package/dist/bin/index.js.map +1 -1
  4. package/dist/src/commands/add.d.ts +2 -2
  5. package/dist/src/commands/add.d.ts.map +1 -1
  6. package/dist/src/commands/add.js +4 -70
  7. package/dist/src/commands/add.js.map +1 -1
  8. package/dist/src/commands/hook.d.ts +5 -4
  9. package/dist/src/commands/hook.d.ts.map +1 -1
  10. package/dist/src/commands/hook.js +7 -75
  11. package/dist/src/commands/hook.js.map +1 -1
  12. package/dist/src/commands/init.js +1 -1
  13. package/dist/src/commands/init.js.map +1 -1
  14. package/dist/src/commands/layout.d.ts +5 -4
  15. package/dist/src/commands/layout.d.ts.map +1 -1
  16. package/dist/src/commands/layout.js +7 -75
  17. package/dist/src/commands/layout.js.map +1 -1
  18. package/dist/src/commands/provider.d.ts +5 -4
  19. package/dist/src/commands/provider.d.ts.map +1 -1
  20. package/dist/src/commands/provider.js +7 -75
  21. package/dist/src/commands/provider.js.map +1 -1
  22. package/dist/src/commands/update.d.ts.map +1 -1
  23. package/dist/src/commands/update.js +78 -43
  24. package/dist/src/commands/update.js.map +1 -1
  25. package/dist/src/commands/utils.d.ts +5 -4
  26. package/dist/src/commands/utils.d.ts.map +1 -1
  27. package/dist/src/commands/utils.js +7 -80
  28. package/dist/src/commands/utils.js.map +1 -1
  29. package/dist/src/shared/addFromRegistry.d.ts +16 -0
  30. package/dist/src/shared/addFromRegistry.d.ts.map +1 -0
  31. package/dist/src/shared/addFromRegistry.js +88 -0
  32. package/dist/src/shared/addFromRegistry.js.map +1 -0
  33. package/dist/src/shared/getInstallCommand.d.ts.map +1 -1
  34. package/dist/src/shared/getInstallCommand.js +5 -0
  35. package/dist/src/shared/getInstallCommand.js.map +1 -1
  36. package/dist/src/shared/installDependencies.d.ts +0 -10
  37. package/dist/src/shared/installDependencies.d.ts.map +1 -1
  38. package/dist/src/shared/installDependencies.js +0 -17
  39. package/dist/src/shared/installDependencies.js.map +1 -1
  40. package/dist/src/shared/installFromPlan.d.ts +7 -5
  41. package/dist/src/shared/installFromPlan.d.ts.map +1 -1
  42. package/dist/src/shared/installFromPlan.js +103 -36
  43. package/dist/src/shared/installFromPlan.js.map +1 -1
  44. package/dist/src/shared/loadRegistry.d.ts +12 -3
  45. package/dist/src/shared/loadRegistry.d.ts.map +1 -1
  46. package/dist/src/shared/loadRegistry.js +19 -20
  47. package/dist/src/shared/loadRegistry.js.map +1 -1
  48. package/dist/src/shared/registryClient.d.ts +19 -0
  49. package/dist/src/shared/registryClient.d.ts.map +1 -0
  50. package/dist/src/shared/registryClient.js +128 -0
  51. package/dist/src/shared/registryClient.js.map +1 -0
  52. package/dist/src/shared/resolveEntry.d.ts +10 -7
  53. package/dist/src/shared/resolveEntry.d.ts.map +1 -1
  54. package/dist/src/shared/resolveEntry.js +18 -13
  55. package/dist/src/shared/resolveEntry.js.map +1 -1
  56. package/dist/src/shared/suggestOtherCommand.d.ts +7 -1
  57. package/dist/src/shared/suggestOtherCommand.d.ts.map +1 -1
  58. package/dist/src/shared/suggestOtherCommand.js +29 -23
  59. package/dist/src/shared/suggestOtherCommand.js.map +1 -1
  60. package/dist/src/types/main.d.ts +31 -2
  61. package/dist/src/types/main.d.ts.map +1 -1
  62. package/package.json +6 -11
  63. package/apps/lib/components/ActionButton.tsx +0 -93
  64. package/apps/lib/components/ActionsGroup.tsx +0 -27
  65. package/apps/lib/components/AlertDialog.tsx +0 -204
  66. package/apps/lib/components/Avatar.tsx +0 -46
  67. package/apps/lib/components/Badge.tsx +0 -250
  68. package/apps/lib/components/BadgeField.tsx +0 -338
  69. package/apps/lib/components/Breadcrumb.tsx +0 -280
  70. package/apps/lib/components/Button.tsx +0 -317
  71. package/apps/lib/components/ButtonGroup.tsx +0 -190
  72. package/apps/lib/components/Calendar.tsx +0 -115
  73. package/apps/lib/components/Card.tsx +0 -95
  74. package/apps/lib/components/Checkbox.tsx +0 -42
  75. package/apps/lib/components/ColorPicker.tsx +0 -441
  76. package/apps/lib/components/ConclusionHeader.tsx +0 -148
  77. package/apps/lib/components/ContextMenu.tsx +0 -571
  78. package/apps/lib/components/CountBadge.tsx +0 -52
  79. package/apps/lib/components/DataTable.tsx +0 -213
  80. package/apps/lib/components/DataViews/badge.ts +0 -49
  81. package/apps/lib/components/DataViews/cell.tsx +0 -324
  82. package/apps/lib/components/DataViews/context.ts +0 -144
  83. package/apps/lib/components/DataViews/data-views.tsx +0 -383
  84. package/apps/lib/components/DataViews/filters/children.tsx +0 -98
  85. package/apps/lib/components/DataViews/filters/custom.tsx +0 -34
  86. package/apps/lib/components/DataViews/filters/filters.tsx +0 -157
  87. package/apps/lib/components/DataViews/filters/index.ts +0 -4
  88. package/apps/lib/components/DataViews/filters/labelled.tsx +0 -20
  89. package/apps/lib/components/DataViews/filters/presets.tsx +0 -65
  90. package/apps/lib/components/DataViews/filters/sync.tsx +0 -35
  91. package/apps/lib/components/DataViews/filters/values.ts +0 -173
  92. package/apps/lib/components/DataViews/header.tsx +0 -220
  93. package/apps/lib/components/DataViews/hooks/index.ts +0 -5
  94. package/apps/lib/components/DataViews/hooks/useActiveRow.ts +0 -22
  95. package/apps/lib/components/DataViews/hooks/useControllable.ts +0 -52
  96. package/apps/lib/components/DataViews/index.ts +0 -84
  97. package/apps/lib/components/DataViews/panel/columns.tsx +0 -153
  98. package/apps/lib/components/DataViews/panel/controls.tsx +0 -106
  99. package/apps/lib/components/DataViews/panel/index.ts +0 -3
  100. package/apps/lib/components/DataViews/panel/panel.tsx +0 -164
  101. package/apps/lib/components/DataViews/panel/saved-views.tsx +0 -67
  102. package/apps/lib/components/DataViews/panel/section.tsx +0 -81
  103. package/apps/lib/components/DataViews/panel/sort.tsx +0 -42
  104. package/apps/lib/components/DataViews/panel/tab.tsx +0 -31
  105. package/apps/lib/components/DataViews/slots.ts +0 -63
  106. package/apps/lib/components/DataViews/states.tsx +0 -38
  107. package/apps/lib/components/DataViews/types.ts +0 -510
  108. package/apps/lib/components/DataViews/views/board-view.tsx +0 -381
  109. package/apps/lib/components/DataViews/views/card-rows.tsx +0 -36
  110. package/apps/lib/components/DataViews/views/inbox-view.tsx +0 -260
  111. package/apps/lib/components/DataViews/views/pane-views.tsx +0 -196
  112. package/apps/lib/components/DataViews/views/table-view.tsx +0 -493
  113. package/apps/lib/components/DataViews/views/tree-view.tsx +0 -367
  114. package/apps/lib/components/DatePicker.tsx +0 -232
  115. package/apps/lib/components/Dialog.tsx +0 -116
  116. package/apps/lib/components/Divider.tsx +0 -28
  117. package/apps/lib/components/Drawer.tsx +0 -420
  118. package/apps/lib/components/DropdownMenu.tsx +0 -540
  119. package/apps/lib/components/FieldHint.tsx +0 -69
  120. package/apps/lib/components/Form.tsx +0 -182
  121. package/apps/lib/components/FormBuilder/context.ts +0 -73
  122. package/apps/lib/components/FormBuilder/field-kind.ts +0 -28
  123. package/apps/lib/components/FormBuilder/fields/ChoiceFields.tsx +0 -60
  124. package/apps/lib/components/FormBuilder/fields/ColorField.tsx +0 -59
  125. package/apps/lib/components/FormBuilder/fields/CustomField.tsx +0 -11
  126. package/apps/lib/components/FormBuilder/fields/DateField.tsx +0 -32
  127. package/apps/lib/components/FormBuilder/fields/FieldArray.tsx +0 -74
  128. package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +0 -163
  129. package/apps/lib/components/FormBuilder/fields/FileField.tsx +0 -39
  130. package/apps/lib/components/FormBuilder/fields/OptionListFields.tsx +0 -132
  131. package/apps/lib/components/FormBuilder/fields/OtpField.tsx +0 -31
  132. package/apps/lib/components/FormBuilder/fields/PhoneField.tsx +0 -109
  133. package/apps/lib/components/FormBuilder/fields/RichTextEditorField.tsx +0 -31
  134. package/apps/lib/components/FormBuilder/fields/SelectField.tsx +0 -91
  135. package/apps/lib/components/FormBuilder/fields/SignatureField.tsx +0 -157
  136. package/apps/lib/components/FormBuilder/fields/SliderField.tsx +0 -67
  137. package/apps/lib/components/FormBuilder/fields/SwitchBoxField.tsx +0 -41
  138. package/apps/lib/components/FormBuilder/fields/TableField.tsx +0 -336
  139. package/apps/lib/components/FormBuilder/fields/TextField.tsx +0 -213
  140. package/apps/lib/components/FormBuilder/fields/TreeSelectField.tsx +0 -43
  141. package/apps/lib/components/FormBuilder/fields/countries.ts +0 -303
  142. package/apps/lib/components/FormBuilder/fields/index.ts +0 -25
  143. package/apps/lib/components/FormBuilder/form-builder.tsx +0 -198
  144. package/apps/lib/components/FormBuilder/index.ts +0 -31
  145. package/apps/lib/components/FormBuilder/numberFormat.ts +0 -16
  146. package/apps/lib/components/FormBuilder/submit.tsx +0 -47
  147. package/apps/lib/components/FormBuilder/types.ts +0 -311
  148. package/apps/lib/components/FormRenderer/FormDrawer.tsx +0 -128
  149. package/apps/lib/components/FormRenderer/detail.tsx +0 -207
  150. package/apps/lib/components/FormRenderer/form-renderer.tsx +0 -297
  151. package/apps/lib/components/FormRenderer/header.tsx +0 -88
  152. package/apps/lib/components/FormRenderer/index.ts +0 -15
  153. package/apps/lib/components/FormRenderer/section.tsx +0 -39
  154. package/apps/lib/components/FormRenderer/stepper.tsx +0 -339
  155. package/apps/lib/components/FormRenderer/types.ts +0 -78
  156. package/apps/lib/components/FormSummary.tsx +0 -282
  157. package/apps/lib/components/HeaderBar.tsx +0 -117
  158. package/apps/lib/components/ImageAttachment.tsx +0 -209
  159. package/apps/lib/components/InnerLabelField.tsx +0 -154
  160. package/apps/lib/components/Input.tsx +0 -224
  161. package/apps/lib/components/InputField.tsx +0 -147
  162. package/apps/lib/components/InputOTP.tsx +0 -84
  163. package/apps/lib/components/Label.tsx +0 -129
  164. package/apps/lib/components/LabelField.tsx +0 -76
  165. package/apps/lib/components/LabeledCheckBox.tsx +0 -51
  166. package/apps/lib/components/LabeledRadio.tsx +0 -51
  167. package/apps/lib/components/LinkButton.tsx +0 -94
  168. package/apps/lib/components/LoginButton.tsx +0 -51
  169. package/apps/lib/components/PasswordLevel.tsx +0 -58
  170. package/apps/lib/components/Popover.tsx +0 -312
  171. package/apps/lib/components/ProfileMenu.tsx +0 -85
  172. package/apps/lib/components/Radio.tsx +0 -59
  173. package/apps/lib/components/RadioCard.tsx +0 -50
  174. package/apps/lib/components/ScrollArea.tsx +0 -54
  175. package/apps/lib/components/SearchField.tsx +0 -62
  176. package/apps/lib/components/SearchableSelect.tsx +0 -318
  177. package/apps/lib/components/SearchableTable.tsx +0 -344
  178. package/apps/lib/components/SearchableTree.tsx +0 -485
  179. package/apps/lib/components/SearchableTreeDialog.tsx +0 -502
  180. package/apps/lib/components/SectionBlock.tsx +0 -147
  181. package/apps/lib/components/Select.tsx +0 -347
  182. package/apps/lib/components/SimpleSelect.tsx +0 -225
  183. package/apps/lib/components/Skeleton.tsx +0 -12
  184. package/apps/lib/components/SlideDatePicker.tsx +0 -253
  185. package/apps/lib/components/SpinLoading.tsx +0 -174
  186. package/apps/lib/components/Stepper.tsx +0 -480
  187. package/apps/lib/components/Switch.tsx +0 -82
  188. package/apps/lib/components/TabFormItem.tsx +0 -153
  189. package/apps/lib/components/TabSwitch.tsx +0 -172
  190. package/apps/lib/components/Table.tsx +0 -610
  191. package/apps/lib/components/TextEditor/ChartBlockTool.ts +0 -676
  192. package/apps/lib/components/TextEditor/RichTextField.tsx +0 -46
  193. package/apps/lib/components/TextEditor/TableDnDWrapper.ts +0 -462
  194. package/apps/lib/components/TextEditor/TextEditor.tsx +0 -1164
  195. package/apps/lib/components/TextEditor/TextEditorToolbar.tsx +0 -429
  196. package/apps/lib/components/TextEditor/editor-tools/AlignmentTune.ts +0 -70
  197. package/apps/lib/components/TextEditor/editor-tools/ColorInlineTool.ts +0 -50
  198. package/apps/lib/components/TextEditor/editor-tools/StrikethroughInlineTool.ts +0 -48
  199. package/apps/lib/components/TextEditor/editor-tools/inlineFormat.ts +0 -98
  200. package/apps/lib/components/TextEditor/editorjs.d.ts +0 -60
  201. package/apps/lib/components/TextEditor/index.ts +0 -7
  202. package/apps/lib/components/TextEditor/markdownParser.ts +0 -346
  203. package/apps/lib/components/Textarea.tsx +0 -117
  204. package/apps/lib/components/Timeline.tsx +0 -263
  205. package/apps/lib/components/Toast.tsx +0 -87
  206. package/apps/lib/components/Toggle.tsx +0 -125
  207. package/apps/lib/components/ToggleButton.tsx +0 -140
  208. package/apps/lib/components/Tooltip.tsx +0 -116
  209. package/apps/lib/components/TransparentLabel.tsx +0 -71
  210. package/apps/lib/components/TreeDropDown.tsx +0 -115
  211. package/apps/lib/components/TreeFolder/TreeFolder.tsx +0 -380
  212. package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +0 -75
  213. package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +0 -354
  214. package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +0 -60
  215. package/apps/lib/components/TreeFolder/icons.tsx +0 -60
  216. package/apps/lib/components/TreeFolder/index.ts +0 -24
  217. package/apps/lib/components/TreeFolder/treeFolderUtils.ts +0 -109
  218. package/apps/lib/components/TreeFolder/types.ts +0 -77
  219. package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +0 -118
  220. package/apps/lib/hooks/useActiveTreeItem.ts +0 -58
  221. package/apps/lib/hooks/useClickOutside.ts +0 -27
  222. package/apps/lib/hooks/useDragDrop.tsx +0 -365
  223. package/apps/lib/hooks/useInfiniteScroll.ts +0 -108
  224. package/apps/lib/hooks/useIsMobile.ts +0 -21
  225. package/apps/lib/hooks/useResize.ts +0 -67
  226. package/apps/lib/hooks/useTagSelection.ts +0 -214
  227. package/apps/lib/layouts/CNLayout.tsx +0 -372
  228. package/apps/lib/layouts/DataViewCard.tsx +0 -62
  229. package/apps/lib/layouts/FieldSection.tsx +0 -91
  230. package/apps/lib/layouts/TreeSubLayout.tsx +0 -173
  231. package/apps/lib/providers/ThemeProvider.tsx +0 -84
  232. package/apps/lib/registry.json +0 -1201
  233. package/apps/lib/tsconfig.json +0 -9
  234. package/apps/lib/tsconfig.tsbuildinfo +0 -1
  235. package/apps/lib/utils/cn.ts +0 -6
  236. package/apps/lib/utils/color.ts +0 -175
  237. package/apps/lib/utils/dataViews/path.ts +0 -67
  238. package/apps/lib/utils/dataViews/query.ts +0 -73
  239. package/apps/lib/utils/dataViews/types.ts +0 -187
  240. package/apps/lib/utils/dateFormat.ts +0 -108
  241. package/apps/lib/utils/resize.ts +0 -31
  242. package/apps/lib/utils/types.ts +0 -16
  243. package/docs/BLOCKS.md +0 -129
  244. package/docs/CHANGELOG-1.1.16.md +0 -108
  245. package/docs/Cover.png +0 -0
  246. package/docs/README.md +0 -215
  247. package/docs/components/action-button.md +0 -638
  248. package/docs/components/actions-group.md +0 -708
  249. package/docs/components/alert-dialog.md +0 -920
  250. package/docs/components/avatar.md +0 -709
  251. package/docs/components/badge-field.md +0 -712
  252. package/docs/components/badge.md +0 -301
  253. package/docs/components/breadcrumb.md +0 -930
  254. package/docs/components/button-group.md +0 -650
  255. package/docs/components/button.md +0 -639
  256. package/docs/components/calendar.md +0 -555
  257. package/docs/components/card.md +0 -622
  258. package/docs/components/chart-block-tool.md +0 -129
  259. package/docs/components/checkbox.md +0 -699
  260. package/docs/components/cn-layout.md +0 -854
  261. package/docs/components/color-picker.md +0 -101
  262. package/docs/components/conclusion-header.md +0 -80
  263. package/docs/components/context-menu.md +0 -483
  264. package/docs/components/count-badge.md +0 -560
  265. package/docs/components/data-table.md +0 -854
  266. package/docs/components/data-views/backend-response.md +0 -324
  267. package/docs/components/data-views/examples/a11y-rtl.md +0 -250
  268. package/docs/components/data-views/examples/api-orders-route.md +0 -130
  269. package/docs/components/data-views/examples/fields.md +0 -362
  270. package/docs/components/data-views/examples/filters.md +0 -307
  271. package/docs/components/data-views/examples/inbox-routing.md +0 -218
  272. package/docs/components/data-views/examples/index.md +0 -29
  273. package/docs/components/data-views/examples/overview.md +0 -244
  274. package/docs/components/data-views/examples/panel.md +0 -212
  275. package/docs/components/data-views/examples/scale.md +0 -231
  276. package/docs/components/data-views/examples/server-side.md +0 -210
  277. package/docs/components/data-views/examples/state.md +0 -250
  278. package/docs/components/data-views/examples/tree-custom.md +0 -388
  279. package/docs/components/data-views/examples/view-registry.md +0 -313
  280. package/docs/components/data-views/examples/views.md +0 -534
  281. package/docs/components/data-views/guide.md +0 -405
  282. package/docs/components/data-views/index.md +0 -1495
  283. package/docs/components/data-views/migration.md +0 -79
  284. package/docs/components/date-picker.md +0 -857
  285. package/docs/components/dialog.md +0 -929
  286. package/docs/components/divider.md +0 -766
  287. package/docs/components/drawer.md +0 -654
  288. package/docs/components/dropdown-menu.md +0 -668
  289. package/docs/components/field-hint.md +0 -898
  290. package/docs/components/field-section.md +0 -781
  291. package/docs/components/form-builder.md +0 -276
  292. package/docs/components/form-renderer.md +0 -326
  293. package/docs/components/form-summary.md +0 -138
  294. package/docs/components/form.md +0 -785
  295. package/docs/components/header-bar.md +0 -188
  296. package/docs/components/image-attachment.md +0 -906
  297. package/docs/components/inner-label-field.md +0 -819
  298. package/docs/components/input-field.md +0 -623
  299. package/docs/components/input-otp.md +0 -756
  300. package/docs/components/input.md +0 -634
  301. package/docs/components/label-field.md +0 -770
  302. package/docs/components/label.md +0 -761
  303. package/docs/components/labeled-check-box.md +0 -642
  304. package/docs/components/labeled-radio.md +0 -796
  305. package/docs/components/link-button.md +0 -685
  306. package/docs/components/login-button.md +0 -872
  307. package/docs/components/password-level.md +0 -803
  308. package/docs/components/popover.md +0 -649
  309. package/docs/components/profile-menu.md +0 -656
  310. package/docs/components/radio-card.md +0 -801
  311. package/docs/components/radio.md +0 -735
  312. package/docs/components/scroll-area.md +0 -691
  313. package/docs/components/search-field.md +0 -702
  314. package/docs/components/searchable-select.md +0 -368
  315. package/docs/components/searchable-table.md +0 -438
  316. package/docs/components/searchable-tree-dialog.md +0 -190
  317. package/docs/components/searchable-tree.md +0 -200
  318. package/docs/components/section-block.md +0 -477
  319. package/docs/components/select.md +0 -709
  320. package/docs/components/simple-select.md +0 -741
  321. package/docs/components/skeleton.md +0 -706
  322. package/docs/components/slide-date-picker.md +0 -837
  323. package/docs/components/spin-loading.md +0 -696
  324. package/docs/components/stepper.md +0 -316
  325. package/docs/components/switch.md +0 -770
  326. package/docs/components/tab-form-item.md +0 -773
  327. package/docs/components/tab-switch.md +0 -170
  328. package/docs/components/table-dnd-wrapper.md +0 -107
  329. package/docs/components/table.md +0 -1088
  330. package/docs/components/text-editor.md +0 -735
  331. package/docs/components/textarea.md +0 -681
  332. package/docs/components/timeline.md +0 -254
  333. package/docs/components/toast.md +0 -773
  334. package/docs/components/toggle-button.md +0 -643
  335. package/docs/components/toggle.md +0 -882
  336. package/docs/components/tooltip.md +0 -513
  337. package/docs/components/transparent-label.md +0 -721
  338. package/docs/components/tree-drop-down.md +0 -740
  339. package/docs/components/tree-folder.md +0 -110
  340. package/docs/components/tree-sub-layout.md +0 -707
  341. package/docs/explanation/architecture.md +0 -54
  342. package/docs/explanation/design-system.md +0 -52
  343. package/docs/how-to/form-and-list-recipes.md +0 -386
  344. package/docs/how-to/forms-with-form-builder.md +0 -472
  345. package/docs/how-to/guides.md +0 -1027
  346. package/docs/migration/changelog.md +0 -54
  347. package/docs/migration/form-builder-2.5.2.md +0 -113
  348. package/docs/reference/cli.md +0 -112
  349. package/docs/reference/components.md +0 -572
  350. package/docs/reference/hooks.md +0 -1500
  351. package/docs/reference/providers.md +0 -866
  352. package/docs/reference/tailwind-plugins.md +0 -942
  353. package/docs/reference/theme.md +0 -85
  354. package/docs/reference/types.md +0 -1016
  355. package/docs/reference/utilities.md +0 -704
  356. package/docs/tutorials/building-first-form.md +0 -846
  357. package/docs/tutorials/component-composition.md +0 -882
  358. package/docs/tutorials/getting-started.md +0 -302
  359. package/docs/tutorials/theming-basics.md +0 -785
@@ -1,311 +0,0 @@
1
- import { ReactNode } from "react";
2
- import type {
3
- ControllerRenderProps,
4
- ControllerFieldState,
5
- DefaultValues,
6
- FieldErrors,
7
- FieldValues,
8
- Resolver,
9
- UseFormReturn,
10
- } from "react-hook-form";
11
- import type { FieldDirection } from "./context";
12
- import type { SectionColor } from "../SectionBlock";
13
-
14
- /**
15
- * What shape of value a field produces, stamped on each `FormBuilder.*` field component.
16
- *
17
- * This is for consumers that have to interpret a form they did not author — `DataViews.Filters`
18
- * reads it to decide whether a child's value becomes a list, a numeric range or a date range. It
19
- * describes the field, not any one consumer's use of it.
20
- *
21
- * Read it with `fieldKindOf(element)` rather than comparing `element.type` against an imported
22
- * component: identity comparison breaks across duplicated module instances and stops matching
23
- * after a hot reload.
24
- */
25
- export type FieldKind =
26
- /** A string value — `Text`, `Textarea`, `Email`, `Password`, `Color`, `Phone`, `Otp`. */
27
- | "text"
28
- /** A number — `Number`, `Currency`. */
29
- | "number"
30
- /** One of a supplied list — `Select`, `SearchableSelect`, `RadioList`, `RadioCards`. */
31
- | "choice"
32
- /** Several of a supplied list — `MultiSelect`, `Tags`, `CheckboxGroup`, `TreeSelect`. */
33
- | "multiChoice"
34
- /** A boolean — `Checkbox`, `SwitchBox`. */
35
- | "boolean"
36
- /** A date or date range — `Date`, `DateRange`, `DateTime`, `DateMultiple`. */
37
- | "date"
38
- /** Two numbers when `range`, otherwise one — `Slider`. */
39
- | "slider"
40
- /** Whatever the caller renders — `Custom`, `File`, `Image`, `Signature`, `RichText`. */
41
- | "custom";
42
-
43
- /** Props shared by every `FormBuilder.*` field. `name` is the RHF path. */
44
- /**
45
- * One alert under a field. Mirrors `FieldHint`'s own props so the design system stays the single
46
- * source of truth for how each state looks.
47
- */
48
- export interface FieldHintSpec {
49
- label: ReactNode;
50
- state?: "info" | "warning" | "error" | "success";
51
- icon?: ReactNode;
52
- }
53
-
54
- export interface BaseFieldProps {
55
- name: string;
56
- label?: ReactNode;
57
- placeholder?: string;
58
- description?: ReactNode;
59
- required?: boolean;
60
- disabled?: boolean;
61
- hidden?: boolean;
62
- /** Span the full section width. */
63
- fullWidth?: boolean;
64
- /**
65
- * Alerts stacked under the field. The validation error, when there is one, always renders first —
66
- * it is the actionable message — and these follow in order. Ignored in `bare` mode (a
67
- * `FormBuilder.Table` cell), where errors surface as a tooltip to keep the row one line tall.
68
- */
69
- hints?: FieldHintSpec[];
70
- }
71
-
72
- export interface OptionItem {
73
- label: string;
74
- value: string;
75
- icon?: ReactNode;
76
- /** Secondary row label — shown by `FormBuilder.RadioList` / `.CheckboxGroup`. */
77
- description?: string;
78
- }
79
-
80
- /** `FormBuilder.Select` / `.SearchableSelect` — supports async option loading. */
81
- /** `FormBuilder.Select` — the plain `Select` dropdown. */
82
- export interface SelectFieldProps extends BaseFieldProps {
83
- options: OptionItem[];
84
- }
85
-
86
- /**
87
- * `FormBuilder.SearchableSelect` — the `SearchableSelect` combobox: a search box with
88
- * client-side filtering, or server-side search + infinite scroll via the async props.
89
- */
90
- export interface SearchableSelectFieldProps extends SelectFieldProps {
91
- /** Filter `options` locally (default). Set false for server-side search. */
92
- filterClientSide?: boolean;
93
- /** Debounced as the user types — refetch your data here. */
94
- onSearchChange?: (query: string) => void;
95
- /** Called when the list bottom scrolls into view and `hasMore && !loading`. */
96
- onLoadMore?: () => void;
97
- hasMore?: boolean;
98
- loading?: boolean;
99
- }
100
-
101
- /** `FormBuilder.MultiSelect` / `.Tags`, `.Radio`. */
102
- export interface OptionsFieldProps extends BaseFieldProps {
103
- options: OptionItem[];
104
- }
105
-
106
- /** `FormBuilder.Currency`. */
107
- export interface CurrencyFieldProps extends BaseFieldProps {
108
- currencySymbol?: ReactNode;
109
- }
110
-
111
- /** `FormBuilder.File` / `.Image`. */
112
- export interface FileFieldProps extends BaseFieldProps {
113
- accept?: string;
114
- multiple?: boolean;
115
- }
116
-
117
- /** `FormBuilder.Custom` — bring your own control, keeping the FieldSection + validation wiring. */
118
- export interface CustomFieldProps extends BaseFieldProps {
119
- render: (args: {
120
- field: ControllerRenderProps<FieldValues, string>;
121
- fieldState: ControllerFieldState;
122
- }) => ReactNode;
123
- }
124
-
125
- /** `FormBuilder.Date` / `.DateRange` / `.DateMultiple` / `.DateTime`. */
126
- export interface DateFieldProps extends BaseFieldProps {
127
- mode?: "single" | "multiple" | "range";
128
- timePicker?: boolean;
129
- /** Display format, e.g. "yyyy/MM/dd" (DatePicker default). */
130
- dateFormat?: string;
131
- }
132
-
133
- /** `FormBuilder.Otp` — code input; value is a string of `length` digits. */
134
- export interface OtpFieldProps extends BaseFieldProps {
135
- /** Number of digit slots (default 6). */
136
- length?: number;
137
- }
138
-
139
- /** `FormBuilder.SwitchBox` — a switch inside a `#f9f9f9` field box. */
140
- export interface SwitchBoxFieldProps extends BaseFieldProps {
141
- /** Text shown inside the box, left of the divider (the design's "Sub-Field-Header"). */
142
- subLabel?: string;
143
- }
144
-
145
- /** `FormBuilder.Checkbox` — a single boolean checkbox with an optional inline label. */
146
- export interface CheckboxFieldProps extends BaseFieldProps {
147
- /** Text shown inline next to the checkbox (in addition to the field `label`). */
148
- subLabel?: string;
149
- }
150
-
151
- /** One option for `FormBuilder.RadioCards`. */
152
- export interface RadioCardOption {
153
- label: ReactNode;
154
- value: string;
155
- description?: ReactNode;
156
- disabled?: boolean;
157
- }
158
-
159
- /** `FormBuilder.RadioCards` — radio options rendered as cards. */
160
- export interface RadioCardsFieldProps extends BaseFieldProps {
161
- options: RadioCardOption[];
162
- }
163
-
164
- /** `FormBuilder.TreeSelect` (SearchableTree) — hierarchical single-select; value = node id. */
165
- export interface TreeSelectFieldProps<T = unknown> extends BaseFieldProps {
166
- nodes: T[];
167
- getNodeId: (node: T) => string;
168
- getNodeLabel: (node: T) => ReactNode;
169
- /** Nested data: expose each node's children. */
170
- getNodeChildren?: (node: T) => T[] | undefined;
171
- /** Flat data: the key on each node pointing at its parent's id. */
172
- parentIdKey?: string;
173
- /** Allow selecting branch (folder) nodes too. */
174
- selectableFolders?: boolean;
175
- }
176
-
177
- /** `FormBuilder.Password` — optionally show a strength meter. */
178
- export interface PasswordFieldProps extends BaseFieldProps {
179
- strengthMeter?: boolean;
180
- }
181
-
182
- /** `FormBuilder.Slider` — numeric slider; value `number` (or `[number, number]` with `range`). */
183
- export interface SliderFieldProps extends BaseFieldProps {
184
- min?: number;
185
- max?: number;
186
- step?: number;
187
- /** Two thumbs — value becomes `[number, number]`. */
188
- range?: boolean;
189
- /** Appended to the value readout, e.g. `"%"` → `50%`. */
190
- suffix?: string;
191
- }
192
-
193
- /** `FormBuilder.Color` — color picker; value hex `string`. */
194
- export interface ColorFieldProps extends BaseFieldProps {
195
- presets?: string[];
196
- /** Enable the opacity slider and `#rrggbbaa` output (default true). */
197
- alpha?: boolean;
198
- }
199
-
200
- /** `FormBuilder.Phone` — country dial-code + number; value `string`. */
201
- export interface PhoneFieldProps extends BaseFieldProps {
202
- defaultCountry?: string;
203
- }
204
-
205
- /** `FormBuilder.Signature` — freehand signature pad; value is a PNG data-URL `string`. */
206
- export interface SignatureFieldProps extends BaseFieldProps {
207
- /** Stroke color (default `#111827`). */
208
- penColor?: string;
209
- }
210
-
211
- /** `FormBuilder.FieldArray` — a repeating list of sub-fields (RHF `useFieldArray`). */
212
- export interface FieldArrayProps {
213
- name: string;
214
- label?: ReactNode;
215
- description?: ReactNode;
216
- hidden?: boolean;
217
- addLabel?: ReactNode;
218
- /** Value for a newly-added row. */
219
- defaultItem?: Record<string, unknown>;
220
- /** Render a row's sub-fields; use names like `${rowName}.field`. */
221
- children: (rowName: string, index: number, remove: () => void) => ReactNode;
222
- }
223
-
224
- /** One column of `FormBuilder.Table`. `cell` renders any `FormBuilder.*` field for a row. */
225
- export interface TableColumn {
226
- header: ReactNode;
227
- /** Fixed column width in px (otherwise the column sizes to content). */
228
- width?: number;
229
- align?: "start" | "center" | "end";
230
- /**
231
- * The row-object key this column edits. Set it to make the column header **sortable** — a
232
- * sort toggle appears and clicking it reorders the rows by this key (asc/desc). Omit for
233
- * non-sortable columns.
234
- */
235
- sortKey?: string;
236
- /**
237
- * Render the cell's field. `rowName` is the array path for this row (e.g. `lines.0`), so name
238
- * sub-fields `${rowName}.<key>`. The field renders "bare" (control only, error as a tooltip).
239
- */
240
- cell: (rowName: string, index: number) => ReactNode;
241
- }
242
-
243
- /**
244
- * `FormBuilder.Table` — an editable table field (built on RHF `useFieldArray`). Each row is a
245
- * record; each column cell is any `FormBuilder.*` field. Supports per-row checkbox selection
246
- * (+ select-all + bulk delete), drag-drop reordering, and add/remove rows. Renders inside a
247
- * `SectionBlock`, so place it as a top-level child (not inside a `FormRenderer.Section`).
248
- */
249
- export interface TableFieldProps {
250
- name: string;
251
- /** SectionBlock title. */
252
- title?: ReactNode;
253
- /** SectionBlock color badge (default `"Blue"`). */
254
- color?: SectionColor;
255
- icon?: ReactNode;
256
- description?: ReactNode;
257
- hidden?: boolean;
258
- columns: TableColumn[];
259
- /** Value for a newly-added row. */
260
- defaultItem?: Record<string, unknown>;
261
- addLabel?: ReactNode;
262
- /** Per-row checkboxes + select-all + bulk delete (default `true`). */
263
- selectable?: boolean;
264
- /** Drag-drop row reordering (default `true`). */
265
- reorderable?: boolean;
266
- }
267
-
268
- /** Root `<FormBuilder>` props. */
269
- export interface FormBuilderRootProps<T extends FieldValues = FieldValues> {
270
- children: ReactNode;
271
- /** `id` on the underlying `<form>` — lets an outside button submit it via `form={id}`. */
272
- id?: string;
273
- /**
274
- * An existing react-hook-form instance. Pass one when something **outside** the
275
- * form needs the same values — e.g. a `FormSummary` rendered beside it:
276
- *
277
- * ```tsx
278
- * const form = useForm({ resolver, defaultValues })
279
- * <FormBuilder form={form} …>…</FormBuilder>
280
- * <FormSummary form={form}>…</FormSummary>
281
- * ```
282
- *
283
- * When omitted, FormBuilder creates its own from `resolver`/`defaultValues`/`values`.
284
- */
285
- form?: UseFormReturn<T>;
286
- onSubmit: (values: T) => void | Promise<void>;
287
- onInvalid?: (errors: FieldErrors<T>) => void;
288
- /** RHF resolver — e.g. `zodResolver(schema)`. Library stays validation-agnostic. */
289
- resolver?: Resolver<T>;
290
- defaultValues?: DefaultValues<T>;
291
- /** Controlled values for edit — the form re-syncs when this changes. */
292
- values?: T;
293
- /** Loading flag — Submit shows a spinner and inputs disable. */
294
- loading?: boolean;
295
- /**
296
- * Field row direction. Unset means `"flexible"` — stacked, then label-beside-control once the
297
- * field row passes the container `md` breakpoint. `FormRenderer` pins `"vertical"` in a drawer;
298
- * pass `"flexible"` there to get the responsive layout back.
299
- */
300
- fieldDirection?: FieldDirection;
301
- /** Reset to defaults after a successful submit. */
302
- resetOnSuccess?: boolean;
303
- /**
304
- * Lands on the `<form>` element itself — FormBuilder renders nothing around it. Use it to let
305
- * the form fill its parent (e.g. `"flex-1 min-h-0"` inside a flex column that has a height).
306
- *
307
- * There is no `layout` prop: the fields always fill their container. The page framing that
308
- * used to live here — the 1100px cap and 48px gutters — belongs to `FormRenderer`.
309
- */
310
- className?: string;
311
- }
@@ -1,128 +0,0 @@
1
- "use client";
2
-
3
- import { ReactNode } from "react";
4
-
5
- import {
6
- Drawer,
7
- DrawerContent,
8
- DrawerPanel,
9
- DrawerTitle,
10
- DrawerNotch,
11
- DrawerNotchClose,
12
- DrawerNotchDivider,
13
- DrawerNotchPill,
14
- } from "../Drawer";
15
- import { FormHeaderBar, type HeaderVariant } from "./header";
16
-
17
- export interface FormDrawerProps {
18
- open: boolean;
19
- onOpenChange: (open: boolean) => void;
20
- /** The `<FormBuilder>` (or any content) to host inside the drawer. */
21
- children: ReactNode;
22
- /**
23
- * The conclusion panel rendered **beside** the form, outside the drawer's scrollable
24
- * body — typically a `<FormSummary>` reading the same hoisted `form`. `FormDrawer` owns
25
- * the box around it (full height, shrinkable), which is what lets the panel's own
26
- * `h-full` and internal scrolling work. The panel sizes itself — a `FormSummary` is
27
- * 228px wide by default — and brings its own (dark) background.
28
- */
29
- summary?: ReactNode;
30
- /** @deprecated Renamed to `summary`. */
31
- childrenOutside?: ReactNode;
32
- /**
33
- * Plain title text (uppercased) in the header's title pill — also the a11y title.
34
- * A string, because it renders through the same `HeaderBar` as the page form.
35
- */
36
- title?: string;
37
- /** Badge text in the title pill. Defaults from `variant` (New / Edit / View). */
38
- badge?: string;
39
- /** Colored badge variant, matching the page form's header. Default `"new"`. */
40
- variant?: HeaderVariant;
41
- /** Action buttons shown on the right of the drawer header (e.g. a Save submit). */
42
- actions?: ReactNode;
43
- /** Shows an "Open in new tab" pill in the notch when provided. */
44
- onOpenInNewTab?: () => void;
45
- }
46
-
47
- /**
48
- * A right-anchored Glare drawer for hosting a form. This is a **FormRenderer**
49
- * concern — `FormBuilder` itself is drawer-unaware (it only displays inputs).
50
- * Wrap a `<FormBuilder>` in `<FormDrawer>` (and pass `fieldDirection="vertical"`
51
- * to the form) to show it in a drawer, or let `FormRenderer` do it via
52
- * `display: "drawer"`.
53
- *
54
- * The `wrapperClassName` includes `mt-0 h-auto` to cancel `DrawerContent`'s base
55
- * bottom-sheet offset (the Glare right-side form-drawer recipe).
56
- *
57
- * It owns the arrangement of its two slots: the form goes in a `DrawerPanel` (the light
58
- * surface), and `summary` sits beside it in the tray with a 6px gutter. The tray itself
59
- * paints nothing, so each panel brings its own background.
60
- */
61
- export function FormDrawer({
62
- open,
63
- onOpenChange,
64
- children,
65
- summary,
66
- childrenOutside,
67
- title = "Form",
68
- badge,
69
- variant,
70
- actions,
71
- onOpenInNewTab,
72
- }: FormDrawerProps) {
73
- const conclusion = summary ?? childrenOutside;
74
-
75
- return (
76
- <Drawer open={open} onOpenChange={onOpenChange} direction="right">
77
- {/* The panel fills the available width (minus the 8px insets), capped at 1048px.
78
- `gap-[6px]` is the gutter between the form panel and the conclusion beside it. */}
79
- <DrawerContent
80
- wrapperClassName="top-2 right-2 bottom-2 left-auto mt-0 h-auto w-[calc(100vw-1rem)] max-w-[1048px]"
81
- className="gap-[6px]"
82
- notch={
83
- <DrawerNotch>
84
- <DrawerNotchClose onClick={() => onOpenChange(false)} />
85
- {onOpenInNewTab && (
86
- <>
87
- <DrawerNotchDivider />
88
- <DrawerNotchPill color="Yellow" onClick={onOpenInNewTab}>
89
- Open in new tab
90
- <i className="ri-arrow-right-up-line text-[12px]" />
91
- </DrawerNotchPill>
92
- </>
93
- )}
94
- </DrawerNotch>
95
- }
96
- >
97
- <DrawerPanel className="rounded-tr-[16px] rounded-b-[16px] p-0">
98
- <div className="relative flex min-h-0 flex-1 flex-col">
99
- {/* Vaul requires a Drawer.Title for the a11y name; the visible title is the
100
- HeaderBar below, so this one is for screen readers only. */}
101
- <DrawerTitle className="sr-only">{title}</DrawerTitle>
102
-
103
- {/* The SAME floating header the page form uses, so a form's title looks
104
- identical in either surface. */}
105
- <FormHeaderBar title={title} label={badge} variant={variant}>
106
- {actions}
107
- </FormHeaderBar>
108
-
109
- {/* pt-[72px] clears the 44px header pill (inset 4px) — same as the page shell. The
110
- 48px bottom breathing-room goes on an inner wrapper, not the scroll container:
111
- FormRenderer's outer element is `h-full`, which would pin it to the content box and
112
- swallow the container's own `pb`. On a plain wrapper that `h-full` resolves to the
113
- content height, so the padding actually lengthens the scroll. The conclusion panel
114
- is a separate sibling, so it keeps its own spacing. */}
115
- <div className="h-full overflow-y-auto px-3 pt-[72px]">
116
- <div className="pb-[48px]">{children}</div>
117
- </div>
118
- </div>
119
- </DrawerPanel>
120
-
121
- {/* `flex min-h-0` so the conclusion stretches to the tray's full height and can
122
- still shrink — without `min-h-0` it would grow past the tray instead of
123
- scrolling inside it. No `flex-1`: the panel sizes itself. */}
124
- {conclusion && <div className="flex min-h-0">{conclusion}</div>}
125
- </DrawerContent>
126
- </Drawer>
127
- );
128
- }
@@ -1,207 +0,0 @@
1
- "use client";
2
-
3
- import * as React from "react";
4
- import * as TabsPrimitive from "@radix-ui/react-tabs";
5
-
6
- import { cn } from "../../utils/cn";
7
- import { formBarItemStyles } from "../TabFormItem";
8
- import { FormHeaderBar, type HeaderVariant } from "./header";
9
-
10
- /**
11
- * Detail-tabs — a display-only view where a left **sidebar** switches the main area between
12
- * **`FormRenderer.Section` panels** (a detail page, not a form). It lives on `FormRenderer`
13
- * (`FormRenderer.Sidebar` / `.Sidebar.Item` / `.Tab`) so `FormBuilder` stays form-only. Built on
14
- * the same Radix Tabs primitive shadcn uses: the sidebar is the `Tabs.List`, each `Sidebar.Item` a
15
- * `Tabs.Trigger`, each `Tab` a `Tabs.Content` — so the fixed rail and the panels share tab state.
16
- */
17
-
18
- export interface DetailSidebarProps {
19
- children: React.ReactNode;
20
- }
21
-
22
- /**
23
- * `FormRenderer.Sidebar` — the tab rail, sitting where a `FormRenderer.Stepper`'s nav would.
24
- * Renders **nothing itself**: the FormRenderer root detects it and places its `Sidebar.Item`
25
- * children (the tab triggers) into the fixed rail.
26
- */
27
- // eslint-disable-next-line @typescript-eslint/no-unused-vars -- children are read by the FormRenderer root
28
- function DetailSidebarRoot(_props: DetailSidebarProps) {
29
- return null;
30
- }
31
- (DetailSidebarRoot as unknown as { __isDetailSidebar: boolean }).__isDetailSidebar = true;
32
-
33
- export interface DetailSidebarItemProps {
34
- /** Ties this row to the `FormRenderer.Tab` of the same `value` — clicking it shows that panel. */
35
- value: string;
36
- /** Leading icon (e.g. a Remix `<i className="ri-…" />`). */
37
- icon?: React.ReactNode;
38
- children: React.ReactNode;
39
- }
40
-
41
- /**
42
- * `FormRenderer.Sidebar.Item` — a rail nav row, rendered as a Radix `Tabs.Trigger` styled with the
43
- * `TabFormItem` `tree` look. Radix drives the active state (`data-state="active"` → black pill).
44
- */
45
- function DetailSidebarItem({ value, icon, children }: DetailSidebarItemProps) {
46
- return (
47
- <TabsPrimitive.Trigger
48
- value={value}
49
- className={cn(
50
- formBarItemStyles({ componentType: "tree" }),
51
- "h-[32px] w-full justify-start gap-2 rounded-[10px] px-[6px] [&_i]:text-[16px]",
52
- // Radix sets `data-state` on the trigger; the active tab is the filled (black) pill.
53
- "data-[state=active]:bg-background-presentation-tab-topbar-selected data-[state=active]:text-content-presentation-tab-action-selected",
54
- "data-[state=active]:hover:bg-background-presentation-tab-topbar-selected data-[state=active]:hover:px-[6px]",
55
- )}
56
- >
57
- {icon}
58
- <span className="flex-1 truncate text-left typography-body-medium-medium">{children}</span>
59
- </TabsPrimitive.Trigger>
60
- );
61
- }
62
-
63
- export const DetailSidebar = Object.assign(DetailSidebarRoot, {
64
- Item: DetailSidebarItem,
65
- });
66
-
67
- export function isDetailSidebarElement(
68
- node: React.ReactNode,
69
- ): node is React.ReactElement<DetailSidebarProps> {
70
- return (
71
- React.isValidElement(node) &&
72
- (node.type as { __isDetailSidebar?: boolean })?.__isDetailSidebar === true
73
- );
74
- }
75
-
76
- export interface DetailRowProps {
77
- label: React.ReactNode;
78
- value: React.ReactNode;
79
- }
80
-
81
- /**
82
- * `FormRenderer.Row` — a read-only label/value cell for detail content (the display counterpart of a
83
- * form field). Drop several inside a `FormRenderer.Grid` within a `FormRenderer.Section`.
84
- */
85
- export function DetailRow({ label, value }: DetailRowProps) {
86
- return (
87
- <div className="flex flex-col gap-1">
88
- <span className="typography-body-small-regular text-content-presentation-global-secondary">
89
- {label}
90
- </span>
91
- <span className="typography-body-medium-medium text-content-presentation-global-primary">
92
- {value}
93
- </span>
94
- </div>
95
- );
96
- }
97
-
98
- export interface DetailGridProps {
99
- /** Column count (default 2). */
100
- columns?: 1 | 2 | 3;
101
- children: React.ReactNode;
102
- }
103
-
104
- const GRID_COLS: Record<NonNullable<DetailGridProps["columns"]>, string> = {
105
- 1: "grid-cols-1",
106
- 2: "grid-cols-2",
107
- 3: "grid-cols-3",
108
- };
109
-
110
- /**
111
- * `FormRenderer.Grid` — arranges `FormRenderer.Row`s in an equal-column grid spanning the **full
112
- * section width** (default 2 columns, so cells split in half). Padded so the rows breathe inside a
113
- * `FormRenderer.Section` (clear of the title badge, roomy row + column spacing).
114
- */
115
- export function DetailGrid({ columns = 2, children }: DetailGridProps) {
116
- return (
117
- <div className={cn("grid w-full gap-x-12 gap-y-5 py-3", GRID_COLS[columns])}>{children}</div>
118
- );
119
- }
120
-
121
- export interface DetailTabProps {
122
- /** Ties this panel to the `Sidebar.Item` of the same `value`. */
123
- value: string;
124
- /** The panel body — typically `FormRenderer.Section` display blocks. */
125
- children: React.ReactNode;
126
- }
127
-
128
- /**
129
- * `FormRenderer.Tab` — a content panel shown when its `value` is the active tab. Renders
130
- * **nothing itself**: the FormRenderer root detects it and mounts it as a Radix `Tabs.Content`
131
- * (kept mounted, inactive ones hidden).
132
- */
133
- // eslint-disable-next-line @typescript-eslint/no-unused-vars -- read by the FormRenderer root
134
- export function DetailTab(_props: DetailTabProps) {
135
- return null;
136
- }
137
- (DetailTab as unknown as { __isDetailTab: boolean }).__isDetailTab = true;
138
-
139
- export function isDetailTabElement(
140
- node: React.ReactNode,
141
- ): node is React.ReactElement<DetailTabProps> {
142
- return (
143
- React.isValidElement(node) && (node.type as { __isDetailTab?: boolean })?.__isDetailTab === true
144
- );
145
- }
146
-
147
- export interface DetailTabsViewProps {
148
- header?: { title: string; label?: string; variant?: HeaderVariant };
149
- /** Header action buttons (Print / Approve / …). */
150
- actions?: React.ReactNode;
151
- /** The `FormRenderer.Sidebar` element — its children are the tab triggers. */
152
- sidebar: React.ReactElement<DetailSidebarProps>;
153
- /** The `FormRenderer.Tab` elements — the content panels. */
154
- tabs: React.ReactElement<DetailTabProps>[];
155
- className?: string;
156
- }
157
-
158
- /**
159
- * The detail-tabs surface: the floating header over a fixed left rail (the sidebar) + a scrolling
160
- * content column showing the active tab. Radix `Tabs.Root` owns the state (uncontrolled, defaults to
161
- * the first tab). The rail matches the stepper's rail position; only the content column scrolls.
162
- */
163
- export function DetailTabsView({ header, actions, sidebar, tabs, className }: DetailTabsViewProps) {
164
- const defaultValue = tabs[0]?.props.value;
165
-
166
- return (
167
- <TabsPrimitive.Root
168
- orientation="vertical"
169
- defaultValue={defaultValue}
170
- className={cn("h-full w-full @container", className)}
171
- >
172
- {/* Scroll shell — mirrors FormBuilder's: the absolute header floats over the body. */}
173
- <div className="relative isolate flex h-full w-full flex-col overflow-hidden rounded-2xl bg-background-presentation-body-primary">
174
- {header && (
175
- <FormHeaderBar title={header.title} label={header.label} variant={header.variant}>
176
- {actions}
177
- </FormHeaderBar>
178
- )}
179
-
180
- <div className="relative z-[1] flex min-h-0 w-full flex-1 flex-row">
181
- {/* The fixed rail — the tab list. `pt-[72px]` clears the floating header. */}
182
- <TabsPrimitive.List asChild>
183
- <aside className="flex h-full w-[216px] shrink-0 flex-col gap-1 overflow-y-auto border-r border-border-presentation-global-primary bg-black-alpha-5 px-2 pb-6 pt-[72px] scrollbar-hide">
184
- {sidebar.props.children}
185
- </aside>
186
- </TabsPrimitive.List>
187
-
188
- {/* The only scrolling region — the active tab's Sections. */}
189
- <div className="flex min-h-0 w-full flex-1 flex-col overflow-y-auto px-6 py-6 pt-[72px] scrollbar-hide">
190
- <div className="mx-auto flex w-full max-w-[1100px] flex-col gap-4">
191
- {tabs.map((panel) => (
192
- <TabsPrimitive.Content
193
- key={panel.props.value}
194
- value={panel.props.value}
195
- forceMount
196
- className="flex flex-col gap-4 outline-none data-[state=inactive]:hidden"
197
- >
198
- {panel.props.children}
199
- </TabsPrimitive.Content>
200
- ))}
201
- </div>
202
- </div>
203
- </div>
204
- </div>
205
- </TabsPrimitive.Root>
206
- );
207
- }