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,22 +0,0 @@
1
- "use client";
2
-
3
- import type { Row } from "../../../utils/dataViews/types";
4
- import { useDataViewsData, useDataViewsView } from "../context";
5
-
6
- /**
7
- * The row the inbox (or board, or tree) has open, ready to render in a detail pane. Returns
8
- * `null` when nothing is selected.
9
- *
10
- * ```tsx
11
- * function Detail() {
12
- * const row = useActiveRow();
13
- * return row ? <h2>{row.subject}</h2> : null;
14
- * }
15
- * ```
16
- */
17
- export function useActiveRow(): Row | null {
18
- const { rows, getRowId } = useDataViewsData();
19
- const { activeId } = useDataViewsView();
20
- if (activeId === null) return null;
21
- return rows.find((row, i) => getRowId(row, i) === activeId) ?? null;
22
- }
@@ -1,52 +0,0 @@
1
- "use client";
2
-
3
- import { useCallback, useRef, useState } from "react";
4
-
5
- /**
6
- * One controlled/uncontrolled pair, written once.
7
- *
8
- * Pass `value` to control it; omit `value` to let the component keep its own. `onChange` fires
9
- * either way, so a consumer can observe without taking ownership.
10
- *
11
- * `set` accepts an updater, because the thing this now holds — the query — is patched rather than
12
- * replaced: changing a filter has to read the page it is resetting.
13
- */
14
- export function useControllable<T>(
15
- value: T | undefined,
16
- onChange: ((next: T) => void) | undefined,
17
- fallback: T,
18
- ): [T, (next: T | ((prev: T) => T)) => void] {
19
- const [internal, setInternal] = useState<T>(fallback);
20
-
21
- // `value !== undefined` decides the mode. Latch the first answer so a consumer that
22
- // accidentally flips between the two gets a warning-free, stable component rather than
23
- // React's "changing an uncontrolled input to controlled" class of bug.
24
- const controlledRef = useRef(value !== undefined);
25
- const isControlled = controlledRef.current;
26
-
27
- const current = isControlled ? (value as T) : internal;
28
-
29
- /**
30
- * The value an updater builds on.
31
- *
32
- * Reset to `current` on every render, and advanced *synchronously* by `set` — so two patches in
33
- * one tick chain instead of racing. Without that, restoring a saved view (which puts back the
34
- * sort and the filters one after the other) silently drops the first: both would read the value
35
- * from the last render, and the second would win.
36
- */
37
- const pendingRef = useRef(current);
38
- pendingRef.current = current;
39
-
40
- const set = useCallback(
41
- (next: T | ((prev: T) => T)) => {
42
- const resolved =
43
- typeof next === "function" ? (next as (prev: T) => T)(pendingRef.current) : next;
44
- pendingRef.current = resolved;
45
- if (!controlledRef.current) setInternal(resolved);
46
- onChange?.(resolved);
47
- },
48
- [onChange],
49
- );
50
-
51
- return [current, set];
52
- }
@@ -1,84 +0,0 @@
1
- // Enumerated, never `export *` — the same convention as `FormBuilder/index.ts`, so what this
2
- // folder offers is readable in one screen.
3
- //
4
- // Almost everything is reached through the compound root: `DataViews.Table`, `DataViews.Panel`,
5
- // `DataViews.Filters`, and so on. The loose exports below are the pieces you need when writing a
6
- // part of your own.
7
-
8
- export { DataViews } from "./data-views";
9
-
10
- // The query's wire format, both directions. A page needs the first two; a route handler that
11
- // serves one of these lists needs `parseQuery`.
12
- export { emptyQuery, parseQuery, queryToParams } from "../../utils/dataViews/query";
13
-
14
- // Reach into the component's state from inside a custom child — a detail pane, a bespoke filter,
15
- // a toolbar button that clears the selection.
16
- export {
17
- useDataViewsData,
18
- useDataViewsFilters,
19
- useDataViewsPanel,
20
- useDataViewsPanelTabs,
21
- useDataViewsView,
22
- } from "./context";
23
- export { useActiveRow } from "./hooks";
24
-
25
- // Paint one field the way the views paint it, in your own layout.
26
- export { Cell } from "./cell";
27
-
28
- // A view of your own gets the loading state the built-in four get: read `loading` from
29
- // `useDataViewsData()` and lay these out in your own shape. There is no `Empty` counterpart —
30
- // nothing to show is shown as nothing.
31
- export { SkeletonBar, skeletonKeys } from "./states";
32
-
33
- // Wrapping a part in a component of your own — a preset panel, a project-standard header — hides
34
- // the marker the root recognises it by, so the wrapper has to carry the marker itself:
35
- //
36
- // ```tsx
37
- // const AppPanel = markPanel(function AppPanel() { return <DataViews.Panel>…</DataViews.Panel>; });
38
- // ```
39
- export { markHeader, markPanel, markView } from "./slots";
40
- export { resolveBadgeVariant } from "./badge";
41
-
42
- export type { ResolvedBadgeProps } from "./badge";
43
- export type {
44
- DataContextValue,
45
- FiltersContextValue,
46
- PanelContextValue,
47
- PanelTab,
48
- PanelTabsContextValue,
49
- RegisteredView,
50
- ViewContextValue,
51
- } from "./context";
52
- export type * from "./types";
53
-
54
- // The vocabulary — the shapes **you** construct and hand in: a row, a field, the query, a tree of
55
- // nodes, a board's groups. They live in `utils/dataViews` because the route handler that serves
56
- // these lists imports them too, and are re-exported here so that one import line is enough:
57
- // every prop above is typed in terms of them.
58
- export type {
59
- BadgeVariant,
60
- ColumnColor,
61
- ColumnState,
62
- CurrencyOptions,
63
- DataViewsQuery,
64
- FieldConfig,
65
- FieldType,
66
- FilterFieldDescriptor,
67
- FilterState,
68
- FilterValue,
69
- MoveIntent,
70
- Path,
71
- Preset,
72
- Row,
73
- RowGroup,
74
- Sort,
75
- TreeNode,
76
- } from "../../utils/dataViews/types";
77
-
78
- // Reading a value the way `Cell` reads it — dotted paths included — and the id rule the component
79
- // falls back to. A custom view or a `renderCell` that has to reach a second field needs these.
80
- export { defaultGetRowId, formatPathLabel, getByPath, getString } from "../../utils/dataViews/path";
81
-
82
- // The board's card body, so a card of your own — in the board or the tree's pane — is built from
83
- // the same pairs the built-in one uses.
84
- export { buildCardRows } from "./views/card-rows";
@@ -1,153 +0,0 @@
1
- "use client";
2
-
3
- import React from "react";
4
- import { cn } from "../../../utils/cn";
5
- import { DragList, useDragDrop, useDragItem } from "../../../hooks/useDragDrop";
6
- import { formatPathLabel } from "../../../utils/dataViews/path";
7
- import type { ColumnState } from "../../../utils/dataViews/types";
8
- import { useDataViewsData, useDataViewsView } from "../context";
9
- import { DataViewsSwitch } from "./controls";
10
- import { Section } from "./section";
11
- import type { PanelColumnsProps } from "../types";
12
-
13
- /** The 2×3 grip dots on a draggable column row. Hand-drawn — there is no icon for this shape. */
14
- function GripDots() {
15
- return (
16
- <svg aria-hidden width="16" height="16" viewBox="0 0 16 16" className="text-white/60" fill="currentColor">
17
- {[5.33, 9.33].flatMap((cx) =>
18
- [3.33, 8, 12.67].map((cy) => <circle key={`${cx}-${cy}`} cx={cx} cy={cy} r="1" />),
19
- )}
20
- </svg>
21
- );
22
- }
23
-
24
- /** The insertion line shown between rows while dragging one. */
25
- function DropLine() {
26
- return (
27
- <div className="pointer-events-none relative h-0">
28
- <div className="absolute -top-[1px] left-0 right-0 h-[2px] rounded-full bg-[#005ECC]" />
29
- </div>
30
- );
31
- }
32
-
33
- /**
34
- * `DataViews.Panel.Columns` — show/hide and reorder the columns.
35
- *
36
- * The column list is the root's, read and written through `useDataViewsView()` — this part takes
37
- * no `value`/`onValueChange` of its own. The root is what turns `columns` into the ordered
38
- * `visibleFields` every view paints from, so hiding a column here also retitles the board's cards. When `columns` has never been set, the list is seeded from
39
- * `fields` on first edit, so you are not forced to declare a redundant array to get this working.
40
- */
41
- export function Columns({
42
- title = "Table Columns",
43
- // Figma writes this line under the header; it is the section's own words, so it is the default
44
- // rather than something every caller has to remember to pass.
45
- description = "Show or hide columns in table view",
46
- className,
47
- }: PanelColumnsProps) {
48
- const { fields } = useDataViewsData();
49
- const { columns, setColumns } = useDataViewsView();
50
-
51
- // What the panel shows: the user's arrangement if there is one, otherwise the declared fields.
52
- const current: ColumnState[] =
53
- columns.length > 0
54
- ? columns.slice()
55
- : fields
56
- .filter((f) => f.type !== "hidden")
57
- .map((f) => ({
58
- path: f.path,
59
- label: f.label ?? formatPathLabel(f.path),
60
- visible: f.visible !== false,
61
- }));
62
-
63
- // Rows are identified by path — the same key the table and every other view uses.
64
- const ids = current.map((c) => c.path);
65
-
66
- const { DndContext, contextProps, activeId, overId } = useDragDrop({
67
- mode: "list",
68
- onMove: ({ id, to }) => {
69
- const from = ids.indexOf(id);
70
- const target = ids.indexOf(String(to));
71
- if (from < 0 || target < 0 || from === target) return;
72
- const next = current.slice();
73
- const [moved] = next.splice(from, 1);
74
- next.splice(target, 0, moved);
75
- setColumns(next);
76
- },
77
- });
78
-
79
- const toggle = (path: string) =>
80
- setColumns(current.map((c) => (c.path === path ? { ...c, visible: !c.visible } : c)));
81
-
82
- return (
83
- <Section title={title} description={description} className={className}>
84
- <DndContext {...contextProps}>
85
- <DragList ids={ids}>
86
- <div data-theme="dark" className="flex flex-col gap-2">
87
- {current.map((column, index) => (
88
- <ColumnRow
89
- key={`${column.path}-${index}`}
90
- column={column}
91
- onToggle={() => toggle(column.path)}
92
- showDropLine={overId === column.path && activeId !== null && activeId !== column.path}
93
- />
94
- ))}
95
- </div>
96
- </DragList>
97
- </DndContext>
98
- </Section>
99
- );
100
- }
101
-
102
- /**
103
- * One column row.
104
- *
105
- * A separate component because `useDragItem` is a hook, and a hook cannot be called inside the
106
- * `.map()` that paints the list.
107
- */
108
- function ColumnRow({
109
- column,
110
- onToggle,
111
- showDropLine,
112
- }: {
113
- column: ColumnState;
114
- onToggle: () => void;
115
- showDropLine: boolean;
116
- }) {
117
- const { ref, handleProps, style, isDragging } = useDragItem(column.path);
118
-
119
- return (
120
- <React.Fragment>
121
- {showDropLine && <DropLine />}
122
- <div
123
- ref={ref}
124
- style={style}
125
- {...handleProps}
126
- className={cn(
127
- // SB-Column-Item: a standalone #1C1D1F pill with a #252729 border, rounded hard
128
- // on the trailing edge and softly on the leading one.
129
- "flex cursor-grab items-center gap-2 rounded-e-[99px] rounded-s-[60px] border",
130
- "border-[#252729] bg-[#1C1D1F] p-[8.8px] transition-colors active:cursor-grabbing",
131
- isDragging ? "opacity-50" : "hover:bg-[#252729]",
132
- )}
133
- >
134
- <span className="flex shrink-0 items-center justify-center">
135
- <GripDots />
136
- </span>
137
- <span className="flex-1 text-[14px] text-white">{column.label}</span>
138
- {/* Stop the switch from starting a drag: the row is the handle, and a press on the
139
- toggle is not a press on the row. */}
140
- <span
141
- className="flex shrink-0 items-center"
142
- onPointerDown={(e) => e.stopPropagation()}
143
- >
144
- <DataViewsSwitch
145
- checked={column.visible}
146
- onCheckedChange={onToggle}
147
- aria-label={`Show ${column.label}`}
148
- />
149
- </span>
150
- </div>
151
- </React.Fragment>
152
- );
153
- }
@@ -1,106 +0,0 @@
1
- "use client";
2
-
3
- import React from "react";
4
- import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
5
- import { cn } from "../../../utils/cn";
6
- import { Switch } from "../../Switch";
7
-
8
- /**
9
- * The form controls the settings rail is built from.
10
- *
11
- * The rail is wrapped in `data-theme="dark"`, so themed components resolve dark tokens on their
12
- * own. The literals below are the exceptions — values chosen against pure black in Figma that
13
- * sit outside the theme system entirely.
14
- */
15
-
16
- /** The bright-green checked track from the Figma Switcher-1.0 "On" state. */
17
- const SWITCH_GREEN = "data-[state=checked]:bg-[#0AC713] data-[state=checked]:border-[#0AC713]";
18
-
19
- export function DataViewsSwitch(props: React.ComponentProps<typeof Switch>) {
20
- return <Switch {...props} className={cn(SWITCH_GREEN, props.className)} />;
21
- }
22
-
23
- /**
24
- * A radio row. The whole 32px row is the Radix item, so the label is part of the click target
25
- * rather than something you have to hit the 14px ring for.
26
- */
27
- export function DataViewRadio({
28
- value,
29
- label,
30
- children,
31
- className,
32
- }: {
33
- value: string;
34
- label?: string;
35
- children?: React.ReactNode;
36
- className?: string;
37
- }) {
38
- return (
39
- <RadioGroupPrimitive.Item
40
- value={value}
41
- className={cn(
42
- "group flex h-[32px] w-full items-center gap-1.5 py-1 ps-2",
43
- "cursor-pointer rounded-[8px] text-left outline-none transition-colors",
44
- "hover:bg-background-presentation-action-contstyle-hover focus-visible:bg-background-presentation-action-contstyle-hover",
45
- className,
46
- )}
47
- >
48
- <span
49
- className={cn(
50
- "flex h-[14px] w-[14px] shrink-0 items-center justify-center rounded-full",
51
- // Literals so the indicator stays dark inside the rail regardless of the host theme,
52
- // matching the always-dark panel chrome. Unselected ring is the CheckBox-Primary border
53
- // (#626467) over the BorderStyle fill; selected is the focus blue.
54
- "border border-[#626467] bg-white/5 transition-colors",
55
- "group-data-[state=checked]:border-transparent",
56
- "group-data-[state=checked]:bg-[#0075FF]",
57
- )}
58
- >
59
- <RadioGroupPrimitive.Indicator className="flex items-center justify-center">
60
- <span className="h-[6px] w-[6px] rounded-full bg-white" />
61
- </RadioGroupPrimitive.Indicator>
62
- </span>
63
- <span className="typography-body-medium-regular text-content-presentation-global-primary flex-1">
64
- {children ?? label}
65
- </span>
66
- </RadioGroupPrimitive.Item>
67
- );
68
- }
69
-
70
- /**
71
- * A `#1C1D1F` pill holding a list of radio rows, with hairlines between them.
72
- *
73
- * The two `:has()` rules hide the hairline above and below the row being hovered, so the hover
74
- * highlight reads as one continuous block instead of being sliced by a line.
75
- */
76
- export function RadioGroup({
77
- value,
78
- onValueChange,
79
- items,
80
- className,
81
- }: {
82
- value: string;
83
- onValueChange: (value: string) => void;
84
- items: readonly { value: string; label: string }[];
85
- className?: string;
86
- }) {
87
- return (
88
- <RadioGroupPrimitive.Root
89
- value={value}
90
- onValueChange={onValueChange}
91
- className={cn(
92
- "flex flex-col space-y-0 rounded-[12px] bg-[#1C1D1F] p-1",
93
- "[&>div:has(>[role=radio]:hover)>.dv-divider]:opacity-0",
94
- "[&>div:has(>[role=radio]:hover)+div>.dv-divider]:opacity-0",
95
- className,
96
- )}
97
- >
98
- {items.map((item, i) => (
99
- <div key={item.value}>
100
- {i > 0 && <div className="dv-divider h-px bg-[#2C2D2E]" />}
101
- <DataViewRadio value={item.value} label={item.label} />
102
- </div>
103
- ))}
104
- </RadioGroupPrimitive.Root>
105
- );
106
- }
@@ -1,3 +0,0 @@
1
- // The rail. `panel.tsx` assembles the compound surface; the rest is one component per file, the
2
- // same shape as `views/`.
3
- export { Panel } from "./panel";
@@ -1,164 +0,0 @@
1
- "use client";
2
-
3
- import React, { Children, useEffect, useMemo, useRef, useState } from "react";
4
- import { X } from "lucide-react";
5
- import { cn } from "../../../utils/cn";
6
- import { PanelTabsContext, useDataViewsPanel, type PanelTab } from "../context";
7
- import { markPanel } from "../slots";
8
- import { Columns } from "./columns";
9
- import { SavedViews } from "./saved-views";
10
- import { Section } from "./section";
11
- import { Sort } from "./sort";
12
- import { Tab, isTabElement } from "./tab";
13
- import type { PanelProps } from "../types";
14
-
15
- /**
16
- * `DataViews.Panel` — the settings rail, opened by `DataViews.PanelToggle`.
17
- *
18
- * Always dark: `data-theme="dark"` on the root makes the Buttons, Switches and Radios inside
19
- * resolve dark tokens against the black, even when the host app runs light. The width animates
20
- * from 0 so the content beside it reflows rather than being covered.
21
- *
22
- * Tabs, like views, exist because you rendered them: the strip is built from the `Panel.Tab`
23
- * children found here and disappears when there is only one.
24
- *
25
- * Open/closed lives on the root, because the toggle that drives it is in the header — this
26
- * component's sibling. Which tab is showing lives here, because nothing outside this rail cares.
27
- */
28
- function PanelRoot({ children, defaultTab, title, className }: PanelProps) {
29
- const { open, setOpen } = useDataViewsPanel();
30
-
31
- // Mount at width 0, then flip to the open width on the next frame so the transition has two
32
- // values to animate between; on close, keep it mounted until the animation finishes.
33
- const [mounted, setMounted] = useState(open);
34
- const [expanded, setExpanded] = useState(false);
35
- const closeTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
36
-
37
- useEffect(() => {
38
- if (open) {
39
- if (closeTimer.current) clearTimeout(closeTimer.current);
40
- setMounted(true);
41
- const raf = requestAnimationFrame(() => requestAnimationFrame(() => setExpanded(true)));
42
- return () => cancelAnimationFrame(raf);
43
- }
44
- setExpanded(false);
45
- closeTimer.current = setTimeout(() => setMounted(false), 300);
46
- return () => {
47
- if (closeTimer.current) clearTimeout(closeTimer.current);
48
- };
49
- }, [open]);
50
-
51
- const childArray = Children.toArray(children);
52
- const tabElements = childArray.filter(isTabElement);
53
- const loose = childArray.filter((n) => !isTabElement(n));
54
-
55
- // Keyed on the tab identities rather than the (always-new) child array — same reasoning as the
56
- // view registry in `data-views.tsx`.
57
- const tabKey = tabElements.map((el) => `${el.props.value}|${el.props.label}`).join(",");
58
- const tabs = useMemo<PanelTab[]>(
59
- () =>
60
- tabElements.map((el) => ({ value: el.props.value, label: el.props.label, icon: el.props.icon })),
61
- // eslint-disable-next-line react-hooks/exhaustive-deps -- keyed on `tabKey`, see above
62
- [tabKey],
63
- );
64
-
65
- const [currentTab, setTab] = useState(defaultTab ?? "");
66
- const known = tabs.some((t) => t.value === currentTab);
67
- const fallbackTab = tabs[0]?.value ?? "";
68
- // A tab that stops being rendered falls back to the first, which also covers the first render
69
- // when no `defaultTab` was given.
70
- const activeTab = known ? currentTab : fallbackTab;
71
-
72
- const value = useMemo(() => ({ tab: activeTab, setTab, tabs }), [activeTab, setTab, tabs]);
73
-
74
- if (!mounted) return null;
75
-
76
- return (
77
- <PanelTabsContext.Provider value={value}>
78
- <div
79
- className={cn(
80
- "shrink-0 overflow-hidden transition-[width] duration-300 ease-in-out",
81
- expanded ? "w-[260px]" : "w-0",
82
- )}
83
- >
84
- <aside
85
- data-theme="dark"
86
- data-state={expanded ? "open" : "closed"}
87
- className={cn(
88
- "flex h-full w-[260px] flex-col overflow-hidden rounded-[16px] bg-black",
89
- "transition-opacity duration-200 ease-in-out",
90
- expanded ? "opacity-100" : "opacity-0",
91
- className,
92
- )}
93
- >
94
- <div className="flex items-center gap-2 px-3 py-3">
95
- {tabs.length > 1 ? (
96
- <div className="flex flex-1 items-center gap-[2px] rounded-[10px] bg-[#252729] p-[2px] shadow-[inset_0_0_5px_0_rgba(0,0,0,0.16)]">
97
- {tabs.map((t) => {
98
- const active = t.value === activeTab;
99
- return (
100
- <button
101
- key={t.value}
102
- type="button"
103
- role="tab"
104
- aria-selected={active}
105
- onClick={() => setTab(t.value)}
106
- className={cn(
107
- "flex h-6 flex-1 items-center justify-center gap-1 rounded-[8px] px-3",
108
- "text-[14px] font-[510] leading-none transition-all duration-200 ease-in-out",
109
- active
110
- ? "bg-white text-black shadow-[0_0_10px_2px_rgba(0,0,0,0.25)]"
111
- : "bg-transparent text-white hover:bg-white/5",
112
- )}
113
- >
114
- {t.icon && (
115
- <span className="flex h-[14px] w-[14px] items-center justify-center [&_svg]:h-[14px] [&_svg]:w-[14px]">
116
- {t.icon}
117
- </span>
118
- )}
119
- {t.label}
120
- </button>
121
- );
122
- })}
123
- </div>
124
- ) : (
125
- <span className="flex-1 text-[18px] font-[510] leading-[1.32] tracking-[-0.01em] text-white">
126
- {title ?? tabs[0]?.label ?? ""}
127
- </span>
128
- )}
129
-
130
- <button
131
- type="button"
132
- aria-label="Close settings panel"
133
- onClick={() => setOpen(false)}
134
- className="hover:bg-background-presentation-state-negative-primary flex h-7 w-7 shrink-0 items-center justify-center rounded-[8px] bg-white/[0.15] text-white transition-colors hover:text-white"
135
- >
136
- <X className="h-[18px] w-[18px]" />
137
- </button>
138
- </div>
139
-
140
- <div className="h-px w-full bg-[#2C2D2E]" />
141
-
142
- <div className="flex flex-1 flex-col gap-6 overflow-y-auto px-3 py-4">
143
- {tabElements}
144
- {loose}
145
- </div>
146
- </aside>
147
- </div>
148
- </PanelTabsContext.Provider>
149
- );
150
- }
151
-
152
-
153
- markPanel(PanelRoot);
154
-
155
- /**
156
- * The rail's compound surface, assembled in one place so what it offers is readable at a glance.
157
- */
158
- export const Panel = Object.assign(PanelRoot, {
159
- Tab,
160
- Section,
161
- Columns,
162
- Sort,
163
- SavedViews,
164
- });
@@ -1,67 +0,0 @@
1
- "use client";
2
-
3
- import { useState } from "react";
4
- import { Plus } from "lucide-react";
5
- import { Button } from "../../Button";
6
- import { useDataViewsFilters, useDataViewsView } from "../context";
7
- import { RadioGroup } from "./controls";
8
- import { Section } from "./section";
9
- import type { PanelSavedViewsProps } from "../types";
10
-
11
- /**
12
- * `DataViews.Panel.SavedViews` — pick a saved arrangement, or save the current one.
13
- *
14
- * Persistence is yours. `onSave` is handed the full snapshot — filters, sort and columns — which
15
- * is the part the old panel got wrong: its save callback took no arguments, so there was nothing
16
- * a host could actually store.
17
- */
18
- export function SavedViews({
19
- title = "Saved View",
20
- views = [],
21
- onValueChange,
22
- onSave,
23
- saveLabel = "Save a New View",
24
- className,
25
- }: PanelSavedViewsProps) {
26
- const { sort, setSort, columns, setColumns } = useDataViewsView();
27
- const { filters, setFilters } = useDataViewsFilters();
28
- // Which view is selected is UI state like any other — the caller stores the snapshots, not the
29
- // cursor into them.
30
- const [active, setActive] = useState("");
31
-
32
- /** Selecting a view is the other half of saving one: put back exactly what was stored. */
33
- const restore = (id: string) => {
34
- setActive(id);
35
- const snapshot = views.find((v) => v.id === id)?.snapshot;
36
- if (snapshot) {
37
- setColumns(snapshot.columns);
38
- setSort(snapshot.sort);
39
- setFilters(snapshot.filters);
40
- }
41
- onValueChange?.(id);
42
- };
43
-
44
- return (
45
- <Section title={title} className={className}>
46
- {views.length > 0 && (
47
- <RadioGroup
48
- value={active}
49
- onValueChange={restore}
50
- items={views.map((v) => ({ value: v.id, label: v.label }))}
51
- />
52
- )}
53
- {onSave && (
54
- <Button
55
- type="button"
56
- variant="BorderStyle"
57
- size="M"
58
- className="w-full"
59
- onClick={() => onSave({ filters, sort, columns })}
60
- >
61
- <Plus className="h-4 w-4" />
62
- {saveLabel}
63
- </Button>
64
- )}
65
- </Section>
66
- );
67
- }