torch-glare 2.5.6 → 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 (362) 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 -403
  69. package/apps/lib/components/Breadcrumb.tsx +0 -280
  70. package/apps/lib/components/Button.tsx +0 -325
  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 -395
  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 -88
  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 -72
  106. package/apps/lib/components/DataViews/states.tsx +0 -73
  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 -451
  118. package/apps/lib/components/DropdownMenu.tsx +0 -554
  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 -85
  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 -168
  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 -114
  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 -67
  147. package/apps/lib/components/FormBuilder/types.ts +0 -316
  148. package/apps/lib/components/FormRenderer/FormDrawer.tsx +0 -250
  149. package/apps/lib/components/FormRenderer/detail.tsx +0 -256
  150. package/apps/lib/components/FormRenderer/form-renderer.tsx +0 -358
  151. package/apps/lib/components/FormRenderer/header.tsx +0 -88
  152. package/apps/lib/components/FormRenderer/index.ts +0 -17
  153. package/apps/lib/components/FormRenderer/notch-action.tsx +0 -64
  154. package/apps/lib/components/FormRenderer/section.tsx +0 -39
  155. package/apps/lib/components/FormRenderer/stepper.tsx +0 -393
  156. package/apps/lib/components/FormRenderer/types.ts +0 -115
  157. package/apps/lib/components/FormSummary.tsx +0 -282
  158. package/apps/lib/components/HeaderBar.tsx +0 -117
  159. package/apps/lib/components/ImageAttachment.tsx +0 -209
  160. package/apps/lib/components/InnerLabelField.tsx +0 -154
  161. package/apps/lib/components/Input.tsx +0 -224
  162. package/apps/lib/components/InputField.tsx +0 -147
  163. package/apps/lib/components/InputOTP.tsx +0 -84
  164. package/apps/lib/components/Label.tsx +0 -129
  165. package/apps/lib/components/LabelField.tsx +0 -76
  166. package/apps/lib/components/LabeledCheckBox.tsx +0 -51
  167. package/apps/lib/components/LabeledRadio.tsx +0 -51
  168. package/apps/lib/components/LinkButton.tsx +0 -94
  169. package/apps/lib/components/LoginButton.tsx +0 -51
  170. package/apps/lib/components/PasswordLevel.tsx +0 -58
  171. package/apps/lib/components/Popover.tsx +0 -312
  172. package/apps/lib/components/ProfileMenu.tsx +0 -85
  173. package/apps/lib/components/Radio.tsx +0 -59
  174. package/apps/lib/components/RadioCard.tsx +0 -50
  175. package/apps/lib/components/ScrollArea.tsx +0 -54
  176. package/apps/lib/components/SearchField.tsx +0 -62
  177. package/apps/lib/components/SearchableSelect.tsx +0 -318
  178. package/apps/lib/components/SearchableTable.tsx +0 -344
  179. package/apps/lib/components/SearchableTree.tsx +0 -485
  180. package/apps/lib/components/SearchableTreeDialog.tsx +0 -502
  181. package/apps/lib/components/SectionBlock.tsx +0 -168
  182. package/apps/lib/components/Select.tsx +0 -347
  183. package/apps/lib/components/SimpleSelect.tsx +0 -225
  184. package/apps/lib/components/Skeleton.tsx +0 -12
  185. package/apps/lib/components/SlideDatePicker.tsx +0 -255
  186. package/apps/lib/components/SpinLoading.tsx +0 -174
  187. package/apps/lib/components/Stepper.tsx +0 -480
  188. package/apps/lib/components/Switch.tsx +0 -82
  189. package/apps/lib/components/TabFormItem.tsx +0 -153
  190. package/apps/lib/components/TabSwitch.tsx +0 -172
  191. package/apps/lib/components/Table.tsx +0 -597
  192. package/apps/lib/components/TextEditor/ChartBlockTool.ts +0 -676
  193. package/apps/lib/components/TextEditor/RichTextField.tsx +0 -46
  194. package/apps/lib/components/TextEditor/TableDnDWrapper.ts +0 -462
  195. package/apps/lib/components/TextEditor/TextEditor.tsx +0 -1164
  196. package/apps/lib/components/TextEditor/TextEditorToolbar.tsx +0 -429
  197. package/apps/lib/components/TextEditor/editor-tools/AlignmentTune.ts +0 -70
  198. package/apps/lib/components/TextEditor/editor-tools/ColorInlineTool.ts +0 -50
  199. package/apps/lib/components/TextEditor/editor-tools/StrikethroughInlineTool.ts +0 -48
  200. package/apps/lib/components/TextEditor/editor-tools/inlineFormat.ts +0 -98
  201. package/apps/lib/components/TextEditor/editorjs.d.ts +0 -60
  202. package/apps/lib/components/TextEditor/index.ts +0 -7
  203. package/apps/lib/components/TextEditor/markdownParser.ts +0 -346
  204. package/apps/lib/components/Textarea.tsx +0 -117
  205. package/apps/lib/components/Timeline.tsx +0 -263
  206. package/apps/lib/components/Toast.tsx +0 -87
  207. package/apps/lib/components/Toggle.tsx +0 -125
  208. package/apps/lib/components/ToggleButton.tsx +0 -140
  209. package/apps/lib/components/Tooltip.tsx +0 -116
  210. package/apps/lib/components/TransparentLabel.tsx +0 -71
  211. package/apps/lib/components/TreeDropDown.tsx +0 -115
  212. package/apps/lib/components/TreeFolder/TreeFolder.tsx +0 -380
  213. package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +0 -75
  214. package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +0 -354
  215. package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +0 -60
  216. package/apps/lib/components/TreeFolder/icons.tsx +0 -60
  217. package/apps/lib/components/TreeFolder/index.ts +0 -24
  218. package/apps/lib/components/TreeFolder/treeFolderUtils.ts +0 -109
  219. package/apps/lib/components/TreeFolder/types.ts +0 -77
  220. package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +0 -118
  221. package/apps/lib/hooks/useActiveTreeItem.ts +0 -61
  222. package/apps/lib/hooks/useClickOutside.ts +0 -27
  223. package/apps/lib/hooks/useDragDrop.tsx +0 -365
  224. package/apps/lib/hooks/useHtmlDir.ts +0 -31
  225. package/apps/lib/hooks/useInfiniteScroll.ts +0 -108
  226. package/apps/lib/hooks/useIsMobile.ts +0 -21
  227. package/apps/lib/hooks/useResize.ts +0 -67
  228. package/apps/lib/hooks/useTagSelection.ts +0 -300
  229. package/apps/lib/layouts/CNLayout.tsx +0 -372
  230. package/apps/lib/layouts/DataViewCard.tsx +0 -62
  231. package/apps/lib/layouts/FieldSection.tsx +0 -91
  232. package/apps/lib/layouts/TreeSubLayout.tsx +0 -173
  233. package/apps/lib/providers/ThemeProvider.tsx +0 -84
  234. package/apps/lib/registry.json +0 -1217
  235. package/apps/lib/tsconfig.json +0 -9
  236. package/apps/lib/tsconfig.tsbuildinfo +0 -1
  237. package/apps/lib/utils/cn.ts +0 -6
  238. package/apps/lib/utils/color.ts +0 -175
  239. package/apps/lib/utils/dataViews/path.ts +0 -67
  240. package/apps/lib/utils/dataViews/query.ts +0 -73
  241. package/apps/lib/utils/dataViews/types.ts +0 -187
  242. package/apps/lib/utils/dateFormat.ts +0 -108
  243. package/apps/lib/utils/resize.ts +0 -31
  244. package/apps/lib/utils/scroller.ts +0 -26
  245. package/apps/lib/utils/types.ts +0 -16
  246. package/docs/BLOCKS.md +0 -129
  247. package/docs/CHANGELOG-1.1.16.md +0 -108
  248. package/docs/Cover.png +0 -0
  249. package/docs/README.md +0 -215
  250. package/docs/components/action-button.md +0 -638
  251. package/docs/components/actions-group.md +0 -708
  252. package/docs/components/alert-dialog.md +0 -920
  253. package/docs/components/avatar.md +0 -709
  254. package/docs/components/badge-field.md +0 -738
  255. package/docs/components/badge.md +0 -301
  256. package/docs/components/breadcrumb.md +0 -930
  257. package/docs/components/button-group.md +0 -650
  258. package/docs/components/button.md +0 -639
  259. package/docs/components/calendar.md +0 -555
  260. package/docs/components/card.md +0 -622
  261. package/docs/components/chart-block-tool.md +0 -129
  262. package/docs/components/checkbox.md +0 -699
  263. package/docs/components/cn-layout.md +0 -854
  264. package/docs/components/color-picker.md +0 -101
  265. package/docs/components/conclusion-header.md +0 -80
  266. package/docs/components/context-menu.md +0 -483
  267. package/docs/components/count-badge.md +0 -560
  268. package/docs/components/data-table.md +0 -854
  269. package/docs/components/data-views/backend-response.md +0 -324
  270. package/docs/components/data-views/examples/a11y-rtl.md +0 -250
  271. package/docs/components/data-views/examples/api-orders-route.md +0 -130
  272. package/docs/components/data-views/examples/fields.md +0 -362
  273. package/docs/components/data-views/examples/filters.md +0 -307
  274. package/docs/components/data-views/examples/inbox-routing.md +0 -218
  275. package/docs/components/data-views/examples/index.md +0 -29
  276. package/docs/components/data-views/examples/overview.md +0 -244
  277. package/docs/components/data-views/examples/panel.md +0 -212
  278. package/docs/components/data-views/examples/scale.md +0 -231
  279. package/docs/components/data-views/examples/server-side.md +0 -210
  280. package/docs/components/data-views/examples/state.md +0 -250
  281. package/docs/components/data-views/examples/tree-custom.md +0 -388
  282. package/docs/components/data-views/examples/view-registry.md +0 -313
  283. package/docs/components/data-views/examples/views.md +0 -534
  284. package/docs/components/data-views/guide.md +0 -405
  285. package/docs/components/data-views/index.md +0 -1521
  286. package/docs/components/data-views/migration.md +0 -81
  287. package/docs/components/date-picker.md +0 -857
  288. package/docs/components/dialog.md +0 -929
  289. package/docs/components/divider.md +0 -766
  290. package/docs/components/drawer.md +0 -654
  291. package/docs/components/dropdown-menu.md +0 -668
  292. package/docs/components/field-hint.md +0 -898
  293. package/docs/components/field-section.md +0 -781
  294. package/docs/components/form-builder.md +0 -284
  295. package/docs/components/form-renderer.md +0 -396
  296. package/docs/components/form-summary.md +0 -138
  297. package/docs/components/form.md +0 -785
  298. package/docs/components/header-bar.md +0 -188
  299. package/docs/components/image-attachment.md +0 -906
  300. package/docs/components/inner-label-field.md +0 -819
  301. package/docs/components/input-field.md +0 -623
  302. package/docs/components/input-otp.md +0 -756
  303. package/docs/components/input.md +0 -634
  304. package/docs/components/label-field.md +0 -770
  305. package/docs/components/label.md +0 -761
  306. package/docs/components/labeled-check-box.md +0 -642
  307. package/docs/components/labeled-radio.md +0 -796
  308. package/docs/components/link-button.md +0 -685
  309. package/docs/components/login-button.md +0 -872
  310. package/docs/components/password-level.md +0 -803
  311. package/docs/components/popover.md +0 -649
  312. package/docs/components/profile-menu.md +0 -656
  313. package/docs/components/radio-card.md +0 -801
  314. package/docs/components/radio.md +0 -735
  315. package/docs/components/scroll-area.md +0 -691
  316. package/docs/components/search-field.md +0 -702
  317. package/docs/components/searchable-select.md +0 -368
  318. package/docs/components/searchable-table.md +0 -438
  319. package/docs/components/searchable-tree-dialog.md +0 -190
  320. package/docs/components/searchable-tree.md +0 -200
  321. package/docs/components/section-block.md +0 -483
  322. package/docs/components/select.md +0 -709
  323. package/docs/components/simple-select.md +0 -741
  324. package/docs/components/skeleton.md +0 -706
  325. package/docs/components/slide-date-picker.md +0 -837
  326. package/docs/components/spin-loading.md +0 -696
  327. package/docs/components/stepper.md +0 -316
  328. package/docs/components/switch.md +0 -770
  329. package/docs/components/tab-form-item.md +0 -773
  330. package/docs/components/tab-switch.md +0 -170
  331. package/docs/components/table-dnd-wrapper.md +0 -107
  332. package/docs/components/table.md +0 -1088
  333. package/docs/components/text-editor.md +0 -735
  334. package/docs/components/textarea.md +0 -681
  335. package/docs/components/timeline.md +0 -254
  336. package/docs/components/toast.md +0 -773
  337. package/docs/components/toggle-button.md +0 -643
  338. package/docs/components/toggle.md +0 -882
  339. package/docs/components/tooltip.md +0 -513
  340. package/docs/components/transparent-label.md +0 -721
  341. package/docs/components/tree-drop-down.md +0 -740
  342. package/docs/components/tree-folder.md +0 -110
  343. package/docs/components/tree-sub-layout.md +0 -707
  344. package/docs/explanation/architecture.md +0 -54
  345. package/docs/explanation/design-system.md +0 -52
  346. package/docs/how-to/form-and-list-recipes.md +0 -386
  347. package/docs/how-to/forms-with-form-builder.md +0 -472
  348. package/docs/how-to/guides.md +0 -1027
  349. package/docs/migration/changelog.md +0 -60
  350. package/docs/migration/form-builder-2.5.2.md +0 -113
  351. package/docs/reference/cli.md +0 -112
  352. package/docs/reference/components.md +0 -572
  353. package/docs/reference/hooks.md +0 -1523
  354. package/docs/reference/providers.md +0 -866
  355. package/docs/reference/tailwind-plugins.md +0 -942
  356. package/docs/reference/theme.md +0 -85
  357. package/docs/reference/types.md +0 -1016
  358. package/docs/reference/utilities.md +0 -726
  359. package/docs/tutorials/building-first-form.md +0 -846
  360. package/docs/tutorials/component-composition.md +0 -882
  361. package/docs/tutorials/getting-started.md +0 -302
  362. package/docs/tutorials/theming-basics.md +0 -785
@@ -1,144 +0,0 @@
1
- "use client";
2
-
3
- import { createContext, useContext } from "react";
4
- import type {
5
- ColumnState,
6
- FieldConfig,
7
- FilterFieldDescriptor,
8
- FilterState,
9
- Row,
10
- Sort,
11
- } from "../../utils/dataViews/types";
12
-
13
- /**
14
- * Every context DataViews uses. As in `FormBuilder`, this is the only file that calls
15
- * `createContext` — a part never invents its own provider, so there is one place to look when
16
- * asking "where does this part get its data".
17
- */
18
-
19
- // ─── Data ─────────────────────────────────────────────────────────────────────
20
-
21
- export interface DataContextValue {
22
- /** The rows to paint, exactly as handed in. Already filtered and sorted by the app. */
23
- rows: readonly Row[];
24
- /** How to paint each field. */
25
- fields: readonly FieldConfig[];
26
- /** The visible fields, in the order the user arranged them. Resolved once by the root. */
27
- visibleFields: readonly FieldConfig[];
28
- /** Stable identity for a row — selection and drag both key off this. */
29
- getRowId: (row: Row, index: number) => string;
30
- loading: boolean;
31
- /** True while the *next* page is in flight — `loading` is the first one. */
32
- loadingMore: boolean;
33
- /** Whether there is a next page: derived from `rows.length < total`, never passed in. */
34
- hasMore: boolean;
35
- /** Ask for the next page. Undefined when the caller did not opt into scroll loading. */
36
- onLoadMore?: () => void;
37
- }
38
-
39
- export const DataContext = createContext<DataContextValue | null>(null);
40
-
41
- export function useDataViewsData(): DataContextValue {
42
- const ctx = useContext(DataContext);
43
- if (!ctx) throw new Error("DataViews parts must be rendered inside <DataViews>.");
44
- return ctx;
45
- }
46
-
47
- // ─── View ─────────────────────────────────────────────────────────────────────
48
-
49
- /** One entry in the switcher. Registered by rendering the view, never by a visibility map. */
50
- export interface RegisteredView {
51
- id: string;
52
- label: string;
53
- icon?: React.ReactNode;
54
- }
55
-
56
- /** The root's interaction state — everything the user can change that is not a row. */
57
- export interface ViewContextValue {
58
- view: string;
59
- setView: (id: string) => void;
60
- /** In the order the views were rendered. */
61
- views: readonly RegisteredView[];
62
- search: string;
63
- setSearch: (q: string) => void;
64
- sort: Sort;
65
- setSort: (sort: Sort) => void;
66
- selection: readonly string[];
67
- setSelection: (ids: readonly string[]) => void;
68
- /** The row the detail pane is showing, for the views that have one. */
69
- activeId: string | null;
70
- setActiveId: (id: string | null) => void;
71
- /** Column visibility and order. The panel edits these; the root paints from them. */
72
- columns: readonly ColumnState[];
73
- setColumns: (columns: readonly ColumnState[]) => void;
74
- }
75
-
76
- export const ViewContext = createContext<ViewContextValue | null>(null);
77
-
78
- export function useDataViewsView(): ViewContextValue {
79
- const ctx = useContext(ViewContext);
80
- if (!ctx) throw new Error("DataViews parts must be rendered inside <DataViews>.");
81
- return ctx;
82
- }
83
-
84
- // ─── Panel ────────────────────────────────────────────────────────────────────
85
-
86
- /**
87
- * Whether the settings panel is showing. Provided by the **root**, not by `Panel` — the toggle
88
- * lives in the header, which is `Panel`'s sibling, so neither can own the state the other needs.
89
- */
90
- export interface PanelContextValue {
91
- open: boolean;
92
- setOpen: (open: boolean) => void;
93
- }
94
-
95
- export const PanelContext = createContext<PanelContextValue | null>(null);
96
-
97
- export function useDataViewsPanel(): PanelContextValue {
98
- const ctx = useContext(PanelContext);
99
- if (!ctx) throw new Error("DataViews parts must be rendered inside <DataViews>.");
100
- return ctx;
101
- }
102
-
103
- /** One entry in the panel's tab strip, registered by rendering a `DataViews.Panel.Tab`. */
104
- export interface PanelTab {
105
- value: string;
106
- label: string;
107
- icon?: React.ReactNode;
108
- }
109
-
110
- /** Which tab the panel is on. Owned by `Panel`, because only its own children care. */
111
- export interface PanelTabsContextValue {
112
- tab: string;
113
- setTab: (tab: string) => void;
114
- tabs: readonly PanelTab[];
115
- }
116
-
117
- export const PanelTabsContext = createContext<PanelTabsContextValue | null>(null);
118
-
119
- export function useDataViewsPanelTabs(): PanelTabsContextValue {
120
- const ctx = useContext(PanelTabsContext);
121
- if (!ctx) throw new Error("DataViews.Panel parts must be rendered inside <DataViews.Panel>.");
122
- return ctx;
123
- }
124
-
125
- // ─── Filters ──────────────────────────────────────────────────────────────────
126
-
127
- export interface FiltersContextValue {
128
- filters: FilterState;
129
- setFilters: (filters: FilterState) => void;
130
- /**
131
- * What each filter control is, read off the `FormBuilder` children of `DataViews.Filters` —
132
- * never derived from the rows. The root collects them as well, so a consumer such as
133
- * `Filters.Presets` can resolve a field by path even when it is rendered outside `Filters`.
134
- */
135
- filterFields: readonly FilterFieldDescriptor[];
136
- }
137
-
138
- export const FiltersContext = createContext<FiltersContextValue | null>(null);
139
-
140
- export function useDataViewsFilters(): FiltersContextValue {
141
- const ctx = useContext(FiltersContext);
142
- if (!ctx) throw new Error("DataViews.Filters parts must be rendered inside <DataViews.Filters>.");
143
- return ctx;
144
- }
@@ -1,395 +0,0 @@
1
- "use client";
2
-
3
- import React, { Children, useCallback, useEffect, useMemo, useState } from "react";
4
- import { cn } from "../../utils/cn";
5
- import { defaultGetRowId } from "../../utils/dataViews/path";
6
- import { emptyQuery } from "../../utils/dataViews/query";
7
- import type {
8
- ColumnState,
9
- DataViewsQuery,
10
- FieldConfig,
11
- FilterState,
12
- Sort,
13
- } from "../../utils/dataViews/types";
14
- import {
15
- DataContext,
16
- FiltersContext,
17
- PanelContext,
18
- ViewContext,
19
- type RegisteredView,
20
- } from "./context";
21
- import { Actions, Header, PanelToggle, Search, ViewSwitch } from "./header";
22
- import { Empty } from "./states";
23
- import {
24
- isEmptyElement,
25
- isHeaderElement,
26
- isPanelElement,
27
- isViewElement,
28
- viewMetaOf,
29
- } from "./slots";
30
- import { collectFilterFields, Filters } from "./filters";
31
- import { Panel } from "./panel";
32
- import { BoardView } from "./views/board-view";
33
- import { Detail, InboxView } from "./views/inbox-view";
34
- import { TableView } from "./views/table-view";
35
- import { TreeView } from "./views/tree-view";
36
- import { useControllable } from "./hooks/useControllable";
37
- import type { DataViewsRootProps } from "./types";
38
-
39
- /**
40
- * A cheap identity for a node used only as a memo key. React elements have no stable identity
41
- * across renders, so an inline `<i className="ri-table-line"/>` would look new every time; the
42
- * element's props are what actually distinguish one icon from another.
43
- */
44
- function iconKey(icon: React.ReactNode): string {
45
- if (icon === null || icon === undefined || typeof icon === "boolean") return "";
46
- if (React.isValidElement(icon)) return JSON.stringify(icon.props ?? {});
47
- return String(icon);
48
- }
49
-
50
- // ─── Root ─────────────────────────────────────────────────────────────────────
51
-
52
- /**
53
- * Resolve which fields to paint and in what order.
54
- *
55
- * The old code sorted `visibleFields` at five call sites with subtly different tie-breaks. There
56
- * is one rule now: if `columns` is supplied it decides both visibility and order; anything not
57
- * mentioned in it keeps its declaration order at the end.
58
- */
59
- function resolveVisibleFields(
60
- fields: readonly FieldConfig[],
61
- columns: readonly ColumnState[] | undefined,
62
- ): FieldConfig[] {
63
- if (!columns || columns.length === 0) {
64
- return fields.filter((f) => f.visible !== false && f.type !== "hidden");
65
- }
66
- const byPath = new Map(fields.map((f) => [f.path, f]));
67
- const ordered: FieldConfig[] = [];
68
- for (const col of columns) {
69
- const field = byPath.get(col.path);
70
- if (field && col.visible) ordered.push(field);
71
- byPath.delete(col.path);
72
- }
73
- for (const field of byPath.values()) {
74
- if (field.visible !== false && field.type !== "hidden") ordered.push(field);
75
- }
76
- return ordered;
77
- }
78
-
79
- function DataViewsRoot({
80
- rows,
81
- fields,
82
- children,
83
- getRowId = defaultGetRowId,
84
- total = 0,
85
- loading = false,
86
- onLoadMore,
87
- loadingMore = false,
88
- query,
89
- onQueryChange,
90
- defaultQuery,
91
- defaultView,
92
- defaultPanelOpen = false,
93
- onViewChange,
94
- onSelectionChange,
95
- onActiveIdChange,
96
- theme,
97
- className,
98
- }: DataViewsRootProps) {
99
- const childArray = Children.toArray(children);
100
-
101
- // A view exists because you rendered it. `Children.toArray` drops `false`/`null`, so
102
- // `{canSeeTree && <DataViews.Tree/>}` un-registers that view — which is the intent.
103
- const viewElements = childArray.filter(isViewElement);
104
- const headerEl = childArray.find(isHeaderElement);
105
- const panelEl = childArray.find(isPanelElement);
106
- // Anything the root does not position itself — a `Filters` bar, a toolbar of your own — sits
107
- // between the header and the views, in the order you wrote it.
108
- // LOCAL PATCH (Contact Center): the empty slot. It must be excluded from `extras` too --
109
- // `extras` is the negative-space bucket, so without this the element would render twice:
110
- // once above the view and once as the body.
111
- const emptyEl = childArray.find(isEmptyElement);
112
- const extras = childArray.filter(
113
- (n) =>
114
- !isViewElement(n) && !isHeaderElement(n) && !isPanelElement(n) && !isEmptyElement(n),
115
- );
116
-
117
- // `viewElements` is a fresh array on every render, so memoising on its identity would never
118
- // hit. Key on what actually matters instead: which views are rendered and how they present.
119
- // `icon` is part of that — leave it out and swapping only an icon leaves a stale one showing.
120
- const viewKey = viewElements
121
- .map((el) => `${el.props.id}|${el.props.label}|${iconKey(el.props.icon)}`)
122
- .join(",");
123
- const registered = useMemo<RegisteredView[]>(
124
- () =>
125
- viewElements.map((el) => {
126
- const meta = viewMetaOf(el)!;
127
- return {
128
- id: el.props.id ?? meta.defaultId,
129
- label: el.props.label ?? meta.defaultLabel,
130
- icon: el.props.icon,
131
- };
132
- }),
133
- // eslint-disable-next-line react-hooks/exhaustive-deps -- keyed on `viewKey`, see above
134
- [viewKey],
135
- );
136
-
137
- const firstId = registered[0]?.id ?? "";
138
-
139
- // ── The query: the only state that leaves ──────────────────────────────────
140
- const [currentQuery, setQuery] = useControllable<DataViewsQuery>(
141
- query,
142
- onQueryChange,
143
- emptyQuery(defaultQuery),
144
- );
145
-
146
- /**
147
- * Change part of the query.
148
- *
149
- * Anything that changes *which* rows match starts a new result set, so the page goes back to 1 —
150
- * filter down to three rows while sitting on page 4 and there is no page 4 to stay on. Only the
151
- * component can do this: by the time a caller sees the change, the two have already been
152
- * conflated into one object.
153
- */
154
- const patchQuery = useCallback(
155
- (patch: Partial<DataViewsQuery>) => {
156
- setQuery((prev) => {
157
- const changesResultSet =
158
- ("search" in patch && patch.search !== prev.search) ||
159
- ("filters" in patch && patch.filters !== prev.filters) ||
160
- ("sort" in patch && patch.sort !== prev.sort) ||
161
- ("pageSize" in patch && patch.pageSize !== prev.pageSize);
162
- return { ...prev, ...patch, ...(changesResultSet ? { page: 1 } : null) };
163
- });
164
- },
165
- [setQuery],
166
- );
167
-
168
- // ── UI state: never leaves, so it is held rather than passed ───────────────
169
- const [currentView, setCurrentView] = useState(defaultView ?? firstId);
170
- const [currentColumns, setColumns] = useState<readonly ColumnState[]>([]);
171
- const [currentSelection, setSelectionState] = useState<readonly string[]>([]);
172
- const [currentActiveId, setActiveIdState] = useState<string | null>(null);
173
- const [isPanelOpen, setPanelOpen] = useState(defaultPanelOpen);
174
-
175
- // The observers are told, not asked: they report what the component decided, so an app can act
176
- // on a selection or follow the open row without owning either.
177
- const setSelection = useCallback(
178
- (ids: readonly string[]) => {
179
- setSelectionState(ids);
180
- onSelectionChange?.(ids);
181
- },
182
- [onSelectionChange],
183
- );
184
- const setActiveId = useCallback(
185
- (id: string | null) => {
186
- setActiveIdState(id);
187
- onActiveIdChange?.(id);
188
- },
189
- [onActiveIdChange],
190
- );
191
- const setView = useCallback(
192
- (id: string) => {
193
- setCurrentView(id);
194
- onViewChange?.(id);
195
- },
196
- [onViewChange],
197
- );
198
-
199
- // If the active view stops being rendered, converge on the first one — in an effect, never
200
- // during render, so a controlled consumer's state actually catches up.
201
- const known = registered.some((v) => v.id === currentView);
202
- useEffect(() => {
203
- if (!known && firstId) setView(firstId);
204
- }, [known, firstId, setView]);
205
-
206
- const activeView = known ? currentView : firstId;
207
- const activeElement = viewElements.find(
208
- (el) => (el.props.id ?? viewMetaOf(el)!.defaultId) === activeView,
209
- );
210
-
211
- const visibleFields = useMemo(
212
- () => resolveVisibleFields(fields, currentColumns),
213
- [fields, currentColumns],
214
- );
215
-
216
- const dataValue = useMemo(
217
- () => ({
218
- rows,
219
- fields,
220
- visibleFields,
221
- getRowId,
222
- loading,
223
- loadingMore,
224
- // Derived, never passed: the component has both halves already, and a `hasMore` prop that
225
- // disagreed with the rows on screen would be a second source of truth for the same fact.
226
- hasMore: rows.length < total,
227
- onLoadMore,
228
- }),
229
- [rows, fields, visibleFields, getRowId, loading, loadingMore, total, onLoadMore],
230
- );
231
-
232
- const setSearch = useCallback((search: string) => patchQuery({ search }), [patchQuery]);
233
- const setSort = useCallback((sort: Sort) => patchQuery({ sort }), [patchQuery]);
234
-
235
- const viewValue = useMemo(
236
- () => ({
237
- view: activeView,
238
- setView,
239
- views: registered,
240
- search: currentQuery.search,
241
- setSearch,
242
- sort: currentQuery.sort,
243
- setSort,
244
- selection: currentSelection,
245
- setSelection,
246
- activeId: currentActiveId,
247
- setActiveId,
248
- columns: currentColumns,
249
- setColumns,
250
- }),
251
- [
252
- activeView,
253
- setView,
254
- registered,
255
- currentQuery.search,
256
- setSearch,
257
- currentQuery.sort,
258
- setSort,
259
- currentSelection,
260
- setSelection,
261
- currentActiveId,
262
- setActiveId,
263
- currentColumns,
264
- setColumns,
265
- ],
266
- );
267
-
268
- const panelValue = useMemo(
269
- () => ({ open: isPanelOpen, setOpen: setPanelOpen }),
270
- [isPanelOpen, setPanelOpen],
271
- );
272
-
273
- // The descriptors as well as the value: a consumer such as `Filters.Presets` resolves a field by
274
- // path, and may be rendered outside `Filters` — above the table, in a toolbar — where it cannot
275
- // reach the context `Filters` provides to its own children.
276
- const filterFields = useMemo(() => collectFilterFields(children), [children]);
277
-
278
- const setFilters = useCallback(
279
- (filters: FilterState) => patchQuery({ filters }),
280
- [patchQuery],
281
- );
282
-
283
- const filtersValue = useMemo(
284
- () => ({ filters: currentQuery.filters, setFilters, filterFields }),
285
- [currentQuery.filters, setFilters, filterFields],
286
- );
287
-
288
- // The active view is what renders, unless a `DataViews.Empty` was supplied and the query has
289
- // SETTLED on nothing — then the caller's empty state takes the view's place entirely.
290
- //
291
- // LOCAL PATCH (Contact Center). `!loading` is the whole reason this is safe: rows are empty
292
- // while the first page is still in flight, so without it the empty state would replace the
293
- // view's skeleton and announce "nothing matched" before anything had been asked for — the
294
- // exact failure that made upstream ship no `Empty` at all (see `states.tsx`). Loading is still
295
- // answered by the view's own skeleton; only a settled empty result swaps the body.
296
- const body = emptyEl && !loading && rows.length === 0 ? emptyEl : activeElement;
297
-
298
- return (
299
- <DataContext.Provider value={dataValue}>
300
- <ViewContext.Provider value={viewValue}>
301
- <PanelContext.Provider value={panelValue}>
302
- <FiltersContext.Provider value={filtersValue}>
303
- <div
304
- data-theme={theme}
305
- className={cn(
306
- // The shell is always black: the dark header and the config rail sit on it, and
307
- // the Master Container is the light surface inside. `overflow-hidden` traps child
308
- // overflow — without it a tall panel body escapes and adds a page-level scrollbar
309
- // on top of the panel's own.
310
- "flex h-full min-h-0 gap-2 overflow-hidden bg-black",
311
- "text-content-presentation-global-primary",
312
- className,
313
- )}
314
- >
315
- {/* Left column: header + content. Shrinks as the panel expands. */}
316
- <div className="flex min-w-0 flex-1 flex-col gap-2">
317
- {headerEl}
318
- <main className="flex min-h-0 flex-1 overflow-hidden">
319
- {/* Master Container. It carries the surface — a form base and a 16px radius —
320
- so views paint over it where they want a different colour (the board reads
321
- grey, the split views black) and anything the root positions around one
322
- inherits it rather than landing on the black shell.
323
-
324
- No border: Figma draws one, but every view already brings its own edge — the
325
- table and the split views each draw their own panel border — so it only ever
326
- read as a second outline around the first. */}
327
- <div className="bg-background-presentation-form-base flex flex-1 overflow-hidden rounded-[16px]">
328
- {/* Clip the scrollable surface to the parent radius minus its 1px border
329
- (16 − 1). At the full 16px the opaque view background sits flush with the
330
- outer edge and bleeds past it as a hairline on the straight sides. */}
331
- <div className="flex min-h-0 flex-1 flex-col overflow-hidden rounded-[15px]">
332
- {/* Anything the root does not position itself — a `Filters` bar, a toolbar
333
- of your own — sits above the view and *inside* the light surface, since
334
- its controls are host-themed and would be stranded on the black shell. */}
335
- {extras.length > 0 && (
336
- <div className="bg-background-presentation-form-base shrink-0">{extras}</div>
337
- )}
338
- {/* A column, so the active view stretches to the full width. As a row it
339
- would size each view to its content and leave the shell showing beside
340
- a narrow one. */}
341
- <div className="flex min-h-0 flex-1 flex-col overflow-auto">{body}</div>
342
- </div>
343
- </div>
344
- </main>
345
- </div>
346
-
347
- {/* The rail is a sibling of the content, not a layer over it, so opening it narrows
348
- the view rather than covering it. */}
349
- {panelEl}
350
- </div>
351
- </FiltersContext.Provider>
352
- </PanelContext.Provider>
353
- </ViewContext.Provider>
354
- </DataContext.Provider>
355
- );
356
- }
357
-
358
- /**
359
- * DataViews — a compound, composition-based multi-view data surface. Author a screen as JSX:
360
- *
361
- * ```tsx
362
- * <DataViews rows={rows} fields={fields} total={total} onQueryChange={setQuery}>
363
- * <DataViews.Header title="Orders">
364
- * <DataViews.ViewSwitch />
365
- * <DataViews.Search />
366
- * </DataViews.Header>
367
- * <DataViews.Table />
368
- * <DataViews.Board groups={groups} />
369
- * </DataViews>
370
- * ```
371
- *
372
- * A view exists **iff you render it** — there is no visibility map. DataViews is pure UI: it
373
- * never filters, searches, sorts, groups or mutates. Hand it rows and it paints them; it hands
374
- * you back what the user did so you can go and query.
375
- */
376
- export const DataViews = Object.assign(DataViewsRoot, {
377
- // shell
378
- Header,
379
- ViewSwitch,
380
- Search,
381
- Actions,
382
- PanelToggle,
383
- // panels
384
- Panel,
385
- Filters,
386
- // views
387
- Table: TableView,
388
- Board: BoardView,
389
- Inbox: InboxView,
390
- Tree: TreeView,
391
- Detail,
392
- // states
393
- Empty,
394
- // paging
395
- });
@@ -1,98 +0,0 @@
1
- "use client";
2
-
3
- import React from "react";
4
- import { fieldKindOf } from "../../FormBuilder";
5
- import type { FilterFieldDescriptor } from "../../../utils/dataViews/types";
6
- import { toName } from "./values";
7
- import { Labelled } from "./labelled";
8
-
9
- /** How a FormBuilder field's value becomes a filter. Fields not listed here are not filters. */
10
- const AS_FILTER = {
11
- text: { kind: "text" } as const,
12
- choice: { kind: "choice", single: true } as const,
13
- multiChoice: { kind: "choice", single: false } as const,
14
- date: { kind: "date" } as const,
15
- slider: { kind: "number" } as const,
16
- };
17
-
18
- /**
19
- * Walk the children and describe every FormBuilder field among them.
20
- *
21
- * This is what `fields` used to be, except it is read from the controls you wrote rather than
22
- * declared twice. The walk follows `props.children`, so a field stays visible through a plain
23
- * wrapper; it cannot see through a component that builds the element itself, which is the same
24
- * limitation the layout markers have.
25
- *
26
- * `Checkbox`, `Number`, `File` and friends have no filter meaning — a boolean is not a query and a
27
- * file is not a value you can filter by — so they render but contribute nothing. `Filters.Custom`
28
- * is the way to drive a filter no FormBuilder field covers.
29
- */
30
- export function collectFilterFields(children: React.ReactNode): FilterFieldDescriptor[] {
31
- const out: FilterFieldDescriptor[] = [];
32
- const seen = new Set<string>();
33
-
34
- const walk = (node: React.ReactNode) => {
35
- if (Array.isArray(node)) {
36
- node.forEach(walk);
37
- return;
38
- }
39
- if (!React.isValidElement(node)) return;
40
-
41
- const props = node.props as {
42
- name?: string;
43
- label?: React.ReactNode;
44
- min?: number;
45
- max?: number;
46
- children?: React.ReactNode;
47
- };
48
- const kind = fieldKindOf(node);
49
- const as = kind ? AS_FILTER[kind as keyof typeof AS_FILTER] : undefined;
50
-
51
- if (as && props.name && !seen.has(props.name)) {
52
- seen.add(props.name);
53
- out.push({
54
- path: props.name,
55
- label: typeof props.label === "string" ? props.label : undefined,
56
- ...as,
57
- ...(as.kind === "number" ? { min: props.min ?? 0, max: props.max ?? 100 } : null),
58
- });
59
- }
60
-
61
- walk(props.children);
62
- };
63
-
64
- walk(children);
65
- return out;
66
- }
67
-
68
- /**
69
- * Render the children, with two changes to every field.
70
- *
71
- * The `name` is escaped, because RHF reads `customer.name` as object nesting — the author writes
72
- * the real path and `FilterState` stays keyed by it. Anything calling `setValue` on a filter has
73
- * to use `toName(path)` for the same reason.
74
- *
75
- * The `label` moves out of the field and into `Labelled` above it: `"bare"` mode exists precisely
76
- * to drop `FieldSection`'s label row, so a label left on the field would simply vanish.
77
- */
78
- export function renderFields(children: React.ReactNode): React.ReactNode {
79
- return React.Children.map(children, (child) => {
80
- if (!React.isValidElement(child)) return child;
81
-
82
- const props = child.props as { name?: string; label?: React.ReactNode; children?: React.ReactNode };
83
-
84
- if (fieldKindOf(child) && props.name) {
85
- return (
86
- <Labelled label={props.label}>
87
- {React.cloneElement(child, { name: toName(props.name), label: undefined } as never)}
88
- </Labelled>
89
- );
90
- }
91
-
92
- // Not a field — recurse so a control inside a wrapper still gets its name escaped.
93
- if (props.children) {
94
- return React.cloneElement(child, {} as never, renderFields(props.children));
95
- }
96
- return child;
97
- });
98
- }
@@ -1,34 +0,0 @@
1
- "use client";
2
-
3
- import { formatPathLabel } from "../../../utils/dataViews/path";
4
- import type { FilterValue } from "../../../utils/dataViews/types";
5
- import { useDataViewsFilters } from "../context";
6
- import { Labelled } from "./labelled";
7
- import type { FilterCustomProps } from "../types";
8
-
9
- /**
10
- * `Filters.Custom` — the escape hatch. Renders whatever you return against this filter's slot in
11
- * `FilterState`, bypassing the form entirely.
12
- *
13
- * Use it when no FormBuilder field produces the value you need — a bucket picker, a map region, a
14
- * tri-state toggle.
15
- *
16
- * ```tsx
17
- * <DataViews.Filters.Custom path="tags" render={({ value, setValue }) => (
18
- * <MyTagPicker value={value as string[]} onChange={setValue} />
19
- * )} />
20
- * ```
21
- */
22
- export function Custom({ path, label, render }: FilterCustomProps) {
23
- const { filters, setFilters } = useDataViewsFilters();
24
- const text = label ?? formatPathLabel(path);
25
-
26
- const setValue = (next: FilterValue | undefined) => {
27
- const copy = { ...filters };
28
- if (next === undefined) delete copy[path];
29
- else copy[path] = next;
30
- setFilters(copy);
31
- };
32
-
33
- return <Labelled label={text}>{render({ value: filters[path], setValue })}</Labelled>;
34
- }