torch-glare 2.4.0 → 2.4.1

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 (264) hide show
  1. package/README.md +8 -0
  2. package/apps/lib/components/ActionButton.tsx +7 -12
  3. package/apps/lib/components/ActionsGroup.tsx +4 -15
  4. package/apps/lib/components/AlertDialog.tsx +173 -191
  5. package/apps/lib/components/Avatar.tsx +13 -16
  6. package/apps/lib/components/Badge.tsx +1 -3
  7. package/apps/lib/components/BadgeField.tsx +76 -71
  8. package/apps/lib/components/Breadcrumb.tsx +49 -85
  9. package/apps/lib/components/Button.tsx +20 -19
  10. package/apps/lib/components/ButtonGroup.tsx +31 -41
  11. package/apps/lib/components/Calendar.tsx +51 -29
  12. package/apps/lib/components/Card.tsx +2 -13
  13. package/apps/lib/components/ChartBlockTool.ts +17 -52
  14. package/apps/lib/components/Checkbox.tsx +9 -16
  15. package/apps/lib/components/ContextMenu.tsx +97 -96
  16. package/apps/lib/components/CountBadge.tsx +4 -6
  17. package/apps/lib/components/DataTable.tsx +196 -216
  18. package/apps/lib/components/DataViews/DataViewRadio.tsx +1 -6
  19. package/apps/lib/components/DataViews/DataViewsConfigPanel.tsx +13 -47
  20. package/apps/lib/components/DataViews/DataViewsHeader.tsx +1 -3
  21. package/apps/lib/components/DataViews/DataViewsLayout.tsx +5 -12
  22. package/apps/lib/components/DataViews/FilterPanel.tsx +155 -149
  23. package/apps/lib/components/DataViews/HeaderSearch.tsx +1 -5
  24. package/apps/lib/components/DataViews/InboxView.tsx +22 -68
  25. package/apps/lib/components/DataViews/InboxViewCard.tsx +68 -77
  26. package/apps/lib/components/DataViews/KanbanView.tsx +8 -25
  27. package/apps/lib/components/DataViews/PanelControls.tsx +3 -13
  28. package/apps/lib/components/DataViews/SettingsPanel.tsx +83 -89
  29. package/apps/lib/components/DataViews/TableView.tsx +8 -28
  30. package/apps/lib/components/DataViews/TreeView.tsx +12 -40
  31. package/apps/lib/components/DataViews/badgeAdapter.ts +32 -28
  32. package/apps/lib/components/DataViews/fieldRenderers.tsx +106 -141
  33. package/apps/lib/components/DataViews/filters/DatePickerRangeFilter.tsx +30 -23
  34. package/apps/lib/components/DataViews/filters/DateRangePopover.tsx +39 -32
  35. package/apps/lib/components/DataViews/filters/PresetChips.tsx +15 -15
  36. package/apps/lib/components/DataViews/filters/RangeSliderWithInputs.tsx +69 -58
  37. package/apps/lib/components/DataViews/index.ts +26 -26
  38. package/apps/lib/components/DataViews/tree/TreeDrawer.tsx +12 -16
  39. package/apps/lib/components/DataViews/tree/TreeSidebar.tsx +28 -31
  40. package/apps/lib/components/DataViews/types.ts +104 -115
  41. package/apps/lib/components/DatePicker.tsx +198 -196
  42. package/apps/lib/components/Dialog.tsx +92 -105
  43. package/apps/lib/components/Divider.tsx +21 -24
  44. package/apps/lib/components/Drawer.tsx +79 -139
  45. package/apps/lib/components/DropdownMenu.tsx +131 -171
  46. package/apps/lib/components/FieldHint.tsx +4 -11
  47. package/apps/lib/components/Form.tsx +146 -155
  48. package/apps/lib/components/FormStepper.tsx +9 -39
  49. package/apps/lib/components/HeaderBar.tsx +1 -9
  50. package/apps/lib/components/ImageAttachment.tsx +111 -73
  51. package/apps/lib/components/InnerLabelField.tsx +20 -16
  52. package/apps/lib/components/Input.tsx +171 -172
  53. package/apps/lib/components/InputField.tsx +44 -45
  54. package/apps/lib/components/InputOTP.tsx +68 -69
  55. package/apps/lib/components/Label.tsx +31 -35
  56. package/apps/lib/components/LabelField.tsx +4 -5
  57. package/apps/lib/components/LabeledCheckBox.tsx +8 -12
  58. package/apps/lib/components/LabeledRadio.tsx +7 -5
  59. package/apps/lib/components/LinkButton.tsx +2 -9
  60. package/apps/lib/components/LoginButton.tsx +4 -9
  61. package/apps/lib/components/PasswordLevel.tsx +5 -5
  62. package/apps/lib/components/Popover.tsx +15 -33
  63. package/apps/lib/components/ProfileMenu.tsx +67 -72
  64. package/apps/lib/components/Radio.tsx +1 -5
  65. package/apps/lib/components/RadioCard.tsx +9 -28
  66. package/apps/lib/components/ScrollArea.tsx +45 -43
  67. package/apps/lib/components/SearchField.tsx +49 -39
  68. package/apps/lib/components/SearchableSelect.tsx +8 -14
  69. package/apps/lib/components/SearchableTable.tsx +108 -118
  70. package/apps/lib/components/SearchableTree.tsx +469 -0
  71. package/apps/lib/components/SearchableTreeDialog.tsx +493 -0
  72. package/apps/lib/components/SectionBlock.tsx +4 -16
  73. package/apps/lib/components/Select.tsx +53 -80
  74. package/apps/lib/components/SimpleSelect.tsx +196 -187
  75. package/apps/lib/components/Skeleton.tsx +9 -12
  76. package/apps/lib/components/SlideDatePicker.tsx +215 -166
  77. package/apps/lib/components/SpinLoading.tsx +33 -49
  78. package/apps/lib/components/Stepper.tsx +13 -56
  79. package/apps/lib/components/Switch.tsx +8 -10
  80. package/apps/lib/components/TabFormItem.tsx +3 -12
  81. package/apps/lib/components/TabSwitch.tsx +7 -34
  82. package/apps/lib/components/Table.tsx +60 -75
  83. package/apps/lib/components/TableDnDWrapper.ts +15 -48
  84. package/apps/lib/components/TextEditor.tsx +93 -104
  85. package/apps/lib/components/Textarea.tsx +8 -12
  86. package/apps/lib/components/Timeline.tsx +21 -41
  87. package/apps/lib/components/Toast.tsx +83 -83
  88. package/apps/lib/components/Toggle.tsx +112 -114
  89. package/apps/lib/components/ToggleButton.tsx +1 -1
  90. package/apps/lib/components/Tooltip.tsx +24 -19
  91. package/apps/lib/components/TransparentLabel.tsx +61 -62
  92. package/apps/lib/components/TreeDropDown.tsx +86 -52
  93. package/apps/lib/components/TreeFolder/TreeFolder.tsx +15 -48
  94. package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +16 -21
  95. package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +9 -20
  96. package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +3 -3
  97. package/apps/lib/components/TreeFolder/icons.tsx +14 -17
  98. package/apps/lib/components/TreeFolder/index.ts +15 -8
  99. package/apps/lib/components/TreeFolder/treeFolderUtils.ts +47 -52
  100. package/apps/lib/components/TreeFolder/types.ts +32 -32
  101. package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +117 -123
  102. package/apps/lib/hooks/useActiveTreeItem.ts +52 -55
  103. package/apps/lib/hooks/useClickOutside.ts +21 -20
  104. package/apps/lib/hooks/useDataViewsState.ts +86 -80
  105. package/apps/lib/hooks/useIsMobile.ts +12 -12
  106. package/apps/lib/hooks/useResize.ts +54 -65
  107. package/apps/lib/hooks/useTagSelection.ts +201 -201
  108. package/apps/lib/layouts/CNLayout.tsx +181 -140
  109. package/apps/lib/layouts/DataViewCard.tsx +4 -18
  110. package/apps/lib/layouts/FieldSection.tsx +2 -6
  111. package/apps/lib/layouts/TreeSubLayout.tsx +24 -38
  112. package/apps/lib/providers/ThemeProvider.tsx +8 -23
  113. package/apps/lib/registry.json +1004 -0
  114. package/apps/lib/tsconfig.json +9 -0
  115. package/apps/lib/utils/cn.ts +1 -1
  116. package/apps/lib/utils/dataViews/columnUtils.ts +46 -44
  117. package/apps/lib/utils/dataViews/fieldUtils.ts +70 -71
  118. package/apps/lib/utils/dataViews/nestedDataUtils.tsx +129 -122
  119. package/apps/lib/utils/dataViews/pathUtils.ts +74 -67
  120. package/apps/lib/utils/dataViews/rangeUtils.ts +121 -112
  121. package/apps/lib/utils/dataViews/treeUtils.ts +204 -211
  122. package/apps/lib/utils/dateFormat.ts +64 -54
  123. package/apps/lib/utils/markdownParser.ts +2 -7
  124. package/apps/lib/utils/resize.ts +21 -25
  125. package/apps/lib/utils/types.ts +13 -13
  126. package/dist/bin/index.js +8 -2
  127. package/dist/bin/index.js.map +1 -1
  128. package/dist/src/shared/getAvailableFiles.d.ts.map +1 -1
  129. package/dist/src/shared/getAvailableFiles.js +6 -1
  130. package/dist/src/shared/getAvailableFiles.js.map +1 -1
  131. package/dist/src/shared/loadRegistry.d.ts +7 -0
  132. package/dist/src/shared/loadRegistry.d.ts.map +1 -0
  133. package/dist/src/shared/loadRegistry.js +31 -0
  134. package/dist/src/shared/loadRegistry.js.map +1 -0
  135. package/dist/src/shared/resolveInstallPlan.d.ts +12 -0
  136. package/dist/src/shared/resolveInstallPlan.d.ts.map +1 -0
  137. package/dist/src/shared/resolveInstallPlan.js +39 -0
  138. package/dist/src/shared/resolveInstallPlan.js.map +1 -0
  139. package/dist/src/types/main.d.ts +24 -0
  140. package/dist/src/types/main.d.ts.map +1 -1
  141. package/docs/README.md +10 -2
  142. package/docs/components/action-button.md +30 -24
  143. package/docs/components/actions-group.md +26 -20
  144. package/docs/components/alert-dialog.md +45 -45
  145. package/docs/components/avatar.md +6 -2
  146. package/docs/components/badge-field.md +6 -2
  147. package/docs/components/badge.md +7 -1
  148. package/docs/components/breadcrumb.md +15 -40
  149. package/docs/components/button-group.md +13 -10
  150. package/docs/components/button.md +58 -33
  151. package/docs/components/calendar.md +26 -19
  152. package/docs/components/card.md +19 -16
  153. package/docs/components/chart-block-tool.md +128 -0
  154. package/docs/components/checkbox.md +16 -8
  155. package/docs/components/cn-layout.md +7 -1
  156. package/docs/components/context-menu.md +18 -25
  157. package/docs/components/count-badge.md +7 -1
  158. package/docs/components/data-table.md +45 -33
  159. package/docs/components/data-views-config-panel.md +15 -11
  160. package/docs/components/data-views-layout.md +13 -16
  161. package/docs/components/date-picker.md +30 -23
  162. package/docs/components/dialog.md +43 -42
  163. package/docs/components/divider.md +10 -4
  164. package/docs/components/drawer.md +8 -33
  165. package/docs/components/dropdown-menu.md +25 -34
  166. package/docs/components/field-hint.md +37 -25
  167. package/docs/components/field-section.md +9 -3
  168. package/docs/components/form-stepper.md +6 -0
  169. package/docs/components/form.md +17 -20
  170. package/docs/components/header-bar.md +6 -0
  171. package/docs/components/image-attachment.md +33 -41
  172. package/docs/components/inbox-view.md +16 -5
  173. package/docs/components/inner-label-field.md +34 -24
  174. package/docs/components/input-field.md +18 -10
  175. package/docs/components/input-otp.md +14 -11
  176. package/docs/components/input.md +22 -16
  177. package/docs/components/kanban-view.md +15 -5
  178. package/docs/components/label-field.md +32 -22
  179. package/docs/components/label.md +43 -32
  180. package/docs/components/labeled-check-box.md +16 -8
  181. package/docs/components/labeled-radio.md +18 -11
  182. package/docs/components/link-button.md +7 -1
  183. package/docs/components/login-button.md +8 -2
  184. package/docs/components/password-level.md +37 -24
  185. package/docs/components/popover.md +26 -23
  186. package/docs/components/profile-menu.md +38 -27
  187. package/docs/components/radio-card.md +16 -9
  188. package/docs/components/radio.md +16 -8
  189. package/docs/components/scroll-area.md +6 -2
  190. package/docs/components/search-field.md +14 -6
  191. package/docs/components/searchable-select.md +19 -14
  192. package/docs/components/searchable-table.md +18 -13
  193. package/docs/components/searchable-tree-dialog.md +190 -0
  194. package/docs/components/searchable-tree.md +200 -0
  195. package/docs/components/section-block.md +12 -4
  196. package/docs/components/select.md +23 -18
  197. package/docs/components/simple-select.md +14 -10
  198. package/docs/components/skeleton.md +43 -33
  199. package/docs/components/slide-date-picker.md +37 -29
  200. package/docs/components/spin-loading.md +32 -23
  201. package/docs/components/stepper.md +6 -0
  202. package/docs/components/switch.md +14 -6
  203. package/docs/components/tab-form-item.md +7 -1
  204. package/docs/components/tab-switch.md +13 -6
  205. package/docs/components/table-dnd-wrapper.md +105 -0
  206. package/docs/components/table-view.md +15 -5
  207. package/docs/components/table.md +28 -28
  208. package/docs/components/text-editor.md +19 -13
  209. package/docs/components/textarea.md +15 -7
  210. package/docs/components/timeline.md +6 -0
  211. package/docs/components/toast.md +35 -26
  212. package/docs/components/toggle-button.md +24 -21
  213. package/docs/components/toggle.md +23 -15
  214. package/docs/components/tooltip.md +42 -30
  215. package/docs/components/transparent-label.md +29 -20
  216. package/docs/components/tree-drop-down.md +31 -23
  217. package/docs/components/tree-sub-layout.md +6 -2
  218. package/docs/components/tree-view.md +16 -5
  219. package/docs/explanation/architecture.md +54 -0
  220. package/docs/explanation/design-system.md +52 -0
  221. package/docs/how-to/data-views-from-backend-response.md +6 -4
  222. package/docs/how-to/guides.md +24 -18
  223. package/docs/migration/changelog.md +38 -0
  224. package/docs/reference/cli.md +87 -0
  225. package/docs/reference/components.md +11 -12
  226. package/docs/reference/hooks.md +8 -8
  227. package/docs/reference/providers.md +22 -22
  228. package/docs/reference/tailwind-plugins.md +2 -2
  229. package/docs/reference/theme.md +85 -0
  230. package/docs/reference/types.md +4 -4
  231. package/docs/reference/utilities.md +19 -26
  232. package/docs/tutorials/building-first-form.md +20 -13
  233. package/docs/tutorials/component-composition.md +34 -50
  234. package/docs/tutorials/getting-started.md +2 -2
  235. package/docs/tutorials/theming-basics.md +13 -10
  236. package/package.json +31 -3
  237. package/dist/src/commands/block.d.ts +0 -5
  238. package/dist/src/commands/block.d.ts.map +0 -1
  239. package/dist/src/commands/block.js +0 -255
  240. package/dist/src/commands/block.js.map +0 -1
  241. package/dist/src/shared/configureFonts.d.ts +0 -6
  242. package/dist/src/shared/configureFonts.d.ts.map +0 -1
  243. package/dist/src/shared/configureFonts.js +0 -106
  244. package/dist/src/shared/configureFonts.js.map +0 -1
  245. package/dist/src/shared/configureGlobalCss.d.ts +0 -6
  246. package/dist/src/shared/configureGlobalCss.d.ts.map +0 -1
  247. package/dist/src/shared/configureGlobalCss.js +0 -154
  248. package/dist/src/shared/configureGlobalCss.js.map +0 -1
  249. package/dist/src/shared/configureTailwind.d.ts +0 -7
  250. package/dist/src/shared/configureTailwind.d.ts.map +0 -1
  251. package/dist/src/shared/configureTailwind.js +0 -163
  252. package/dist/src/shared/configureTailwind.js.map +0 -1
  253. package/dist/src/shared/detectFramework.d.ts +0 -23
  254. package/dist/src/shared/detectFramework.d.ts.map +0 -1
  255. package/dist/src/shared/detectFramework.js +0 -119
  256. package/dist/src/shared/detectFramework.js.map +0 -1
  257. package/dist/src/shared/installBaseUtils.d.ts +0 -5
  258. package/dist/src/shared/installBaseUtils.d.ts.map +0 -1
  259. package/dist/src/shared/installBaseUtils.js +0 -79
  260. package/dist/src/shared/installBaseUtils.js.map +0 -1
  261. package/dist/src/shared/resolveAliases.d.ts +0 -24
  262. package/dist/src/shared/resolveAliases.d.ts.map +0 -1
  263. package/dist/src/shared/resolveAliases.js +0 -98
  264. package/dist/src/shared/resolveAliases.js.map +0 -1
@@ -1,15 +1,15 @@
1
- "use client"
2
-
3
- import { Fragment } from "react"
4
- import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
5
- import { Button } from "../Button"
6
- import { Badge } from "../Badge"
7
- import { X } from "lucide-react"
8
- import { Checkbox } from "../Checkbox"
9
- import { Divider } from "../Divider"
10
- import { Label } from "../Label"
11
- import { DataViewRadio } from "./DataViewRadio"
12
- import { cn } from "../../utils/cn"
1
+ "use client";
2
+
3
+ import { Fragment } from "react";
4
+ import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
5
+ import { Button } from "../Button";
6
+ import { Badge } from "../Badge";
7
+ import { X } from "lucide-react";
8
+ import { Checkbox } from "../Checkbox";
9
+ import { Divider } from "../Divider";
10
+ import { Label } from "../Label";
11
+ import { DataViewRadio } from "./DataViewRadio";
12
+ import { cn } from "../../utils/cn";
13
13
  import type {
14
14
  DynamicRecord,
15
15
  DynamicFilterConfig,
@@ -19,8 +19,8 @@ import type {
19
19
  FilterValue,
20
20
  NumericRangeFilter,
21
21
  DateRangeFilter,
22
- } from "./types"
23
- import { getByPath, formatPathLabel } from "../../utils/dataViews/pathUtils"
22
+ } from "./types";
23
+ import { getByPath, formatPathLabel } from "../../utils/dataViews/pathUtils";
24
24
  import {
25
25
  computeNumericExtremes,
26
26
  countActiveFilters,
@@ -28,29 +28,29 @@ import {
28
28
  isDateRange,
29
29
  isNumericRange,
30
30
  resolvePresets,
31
- } from "../../utils/dataViews/rangeUtils"
32
- import { RangeSliderWithInputs } from "./filters/RangeSliderWithInputs"
33
- import { DatePickerRangeFilter } from "./filters/DatePickerRangeFilter"
34
- import { PresetChips } from "./filters/PresetChips"
35
- import { resolveBadgeVariant } from "./badgeAdapter"
36
- import { SearchableSelect } from "../SearchableSelect"
37
- import type { SearchableSelectOption } from "../SearchableSelect"
31
+ } from "../../utils/dataViews/rangeUtils";
32
+ import { RangeSliderWithInputs } from "./filters/RangeSliderWithInputs";
33
+ import { DatePickerRangeFilter } from "./filters/DatePickerRangeFilter";
34
+ import { PresetChips } from "./filters/PresetChips";
35
+ import { resolveBadgeVariant } from "./badgeAdapter";
36
+ import { SearchableSelect } from "../SearchableSelect";
37
+ import type { SearchableSelectOption } from "../SearchableSelect";
38
38
 
39
39
  type FilterPanelProps = {
40
- data: DynamicRecord[]
41
- fields: FieldConfig[]
42
- filters: FilterState
43
- onFilterChange: (path: string, value: FilterValue) => void
44
- onClearAll: () => void
45
- filterConfig?: DynamicFilterConfig[]
40
+ data: DynamicRecord[];
41
+ fields: FieldConfig[];
42
+ filters: FilterState;
43
+ onFilterChange: (path: string, value: FilterValue) => void;
44
+ onClearAll: () => void;
45
+ filterConfig?: DynamicFilterConfig[];
46
46
  /**
47
47
  * "default": standalone left-rail style (border, padding, light surface).
48
48
  * "panel": matches the Config tab inside DataViewsConfigPanel — no outer
49
49
  * chrome, white section headers, categorical options inside a #1C1D1F
50
50
  * rounded container, sections separated by #2C2D2E dividers.
51
51
  */
52
- variant?: "default" | "panel"
53
- }
52
+ variant?: "default" | "panel";
53
+ };
54
54
 
55
55
  const NUMERIC_TYPES: FieldType[] = [
56
56
  "number",
@@ -58,19 +58,19 @@ const NUMERIC_TYPES: FieldType[] = [
58
58
  "currency",
59
59
  "progress-bar",
60
60
  "star-rating",
61
- ]
61
+ ];
62
62
 
63
- const DATE_TYPES: FieldType[] = ["date", "date-format"]
63
+ const DATE_TYPES: FieldType[] = ["date", "date-format"];
64
64
 
65
- type FilterKind = "categorical" | "numeric-range" | "date-range"
65
+ type FilterKind = "categorical" | "numeric-range" | "date-range";
66
66
 
67
67
  type Entry = {
68
- path: string
69
- label: string
70
- kind: FilterKind
71
- field?: FieldConfig
72
- legacy?: DynamicFilterConfig
73
- }
68
+ path: string;
69
+ label: string;
70
+ kind: FilterKind;
71
+ field?: FieldConfig;
72
+ legacy?: DynamicFilterConfig;
73
+ };
74
74
 
75
75
  function buildFilterableEntries(
76
76
  data: DynamicRecord[],
@@ -79,41 +79,41 @@ function buildFilterableEntries(
79
79
  ): Entry[] {
80
80
  const legacyByPath = new Map(
81
81
  (legacy ?? []).filter((f) => f.enabled !== false).map((f) => [f.id, f]),
82
- )
82
+ );
83
83
 
84
- const entries: Entry[] = []
85
- const seen = new Set<string>()
84
+ const entries: Entry[] = [];
85
+ const seen = new Set<string>();
86
86
 
87
87
  for (const f of fields) {
88
- if (f.type === "hidden") continue
89
- if (f.filterable === false) continue
88
+ if (f.type === "hidden") continue;
89
+ if (f.filterable === false) continue;
90
90
 
91
- const isExplicit = f.filterable === true
91
+ const isExplicit = f.filterable === true;
92
92
  const isCategoricalAuto =
93
93
  f.type === "enum-badge" ||
94
94
  f.type === "boolean" ||
95
95
  f.type === "badge-array" ||
96
- f.type === "icon-text"
97
- const isNumeric = f.type != null && NUMERIC_TYPES.includes(f.type)
98
- const isDate = f.type != null && DATE_TYPES.includes(f.type)
96
+ f.type === "icon-text";
97
+ const isNumeric = f.type != null && NUMERIC_TYPES.includes(f.type);
98
+ const isDate = f.type != null && DATE_TYPES.includes(f.type);
99
99
 
100
- let include = isExplicit || isCategoricalAuto
100
+ let include = isExplicit || isCategoricalAuto;
101
101
 
102
102
  if (!include) {
103
- if (f.type !== "text" && f.type !== undefined) continue
104
- const unique = new Set<string>()
103
+ if (f.type !== "text" && f.type !== undefined) continue;
104
+ const unique = new Set<string>();
105
105
  for (const item of data) {
106
- const v = getByPath(item, f.path)
107
- if (v == null) continue
108
- unique.add(String(v))
109
- if (unique.size > 10) break
106
+ const v = getByPath(item, f.path);
107
+ if (v == null) continue;
108
+ unique.add(String(v));
109
+ if (unique.size > 10) break;
110
110
  }
111
- include = unique.size > 0 && unique.size <= 10
111
+ include = unique.size > 0 && unique.size <= 10;
112
112
  }
113
113
 
114
- if (!include) continue
114
+ if (!include) continue;
115
115
 
116
- const kind: FilterKind = isNumeric ? "numeric-range" : isDate ? "date-range" : "categorical"
116
+ const kind: FilterKind = isNumeric ? "numeric-range" : isDate ? "date-range" : "categorical";
117
117
 
118
118
  entries.push({
119
119
  path: f.path,
@@ -121,21 +121,21 @@ function buildFilterableEntries(
121
121
  kind,
122
122
  field: f,
123
123
  legacy: legacyByPath.get(f.path),
124
- })
125
- seen.add(f.path)
124
+ });
125
+ seen.add(f.path);
126
126
  }
127
127
 
128
128
  for (const lf of legacyByPath.values()) {
129
- if (seen.has(lf.id)) continue
129
+ if (seen.has(lf.id)) continue;
130
130
  entries.push({
131
131
  path: lf.id,
132
132
  label: lf.label ?? formatPathLabel(lf.id),
133
133
  kind: "categorical",
134
134
  legacy: lf,
135
- })
135
+ });
136
136
  }
137
137
 
138
- return entries
138
+ return entries;
139
139
  }
140
140
 
141
141
  function getCategoricalOptions(
@@ -145,37 +145,37 @@ function getCategoricalOptions(
145
145
  legacy?: DynamicFilterConfig,
146
146
  ): string[] {
147
147
  if (field?.filterOptions && field.filterOptions.length > 0) {
148
- return normalizeOptions(field.filterOptions)
148
+ return normalizeOptions(field.filterOptions);
149
149
  }
150
150
  if (legacy?.options && legacy.options.length > 0) {
151
- return normalizeOptions(legacy.options)
151
+ return normalizeOptions(legacy.options);
152
152
  }
153
153
  if (field?.variants) {
154
- const fromMap = Object.keys(field.variants)
155
- const fromData = collectUnique(data, path)
156
- return Array.from(new Set([...fromMap, ...fromData]))
154
+ const fromMap = Object.keys(field.variants);
155
+ const fromData = collectUnique(data, path);
156
+ return Array.from(new Set([...fromMap, ...fromData]));
157
157
  }
158
- return collectUnique(data, path)
158
+ return collectUnique(data, path);
159
159
  }
160
160
 
161
161
  function normalizeOptions(opts: NonNullable<FieldConfig["filterOptions"]>): string[] {
162
- if (opts.length === 0) return []
163
- if (typeof opts[0] === "string") return opts as string[]
164
- return (opts as { label: string; value: string }[]).map((o) => o.value)
162
+ if (opts.length === 0) return [];
163
+ if (typeof opts[0] === "string") return opts as string[];
164
+ return (opts as { label: string; value: string }[]).map((o) => o.value);
165
165
  }
166
166
 
167
167
  function collectUnique(data: DynamicRecord[], path: string): string[] {
168
- const set = new Set<string>()
168
+ const set = new Set<string>();
169
169
  for (const item of data) {
170
- const v = getByPath(item, path)
171
- if (v == null) continue
170
+ const v = getByPath(item, path);
171
+ if (v == null) continue;
172
172
  if (Array.isArray(v)) {
173
- for (const x of v) set.add(String(x))
173
+ for (const x of v) set.add(String(x));
174
174
  } else {
175
- set.add(String(v))
175
+ set.add(String(v));
176
176
  }
177
177
  }
178
- return Array.from(set).sort()
178
+ return Array.from(set).sort();
179
179
  }
180
180
 
181
181
  export function FilterPanel({
@@ -187,30 +187,30 @@ export function FilterPanel({
187
187
  filterConfig,
188
188
  variant = "default",
189
189
  }: FilterPanelProps) {
190
- const entries = buildFilterableEntries(data, fields, filterConfig)
190
+ const entries = buildFilterableEntries(data, fields, filterConfig);
191
191
 
192
192
  const setFilter = (path: string, value: FilterValue) => {
193
- onFilterChange(path, value)
194
- const field = fields.find((f) => f.path === path)
195
- field?.onFilterChange?.(value)
193
+ onFilterChange(path, value);
194
+ const field = fields.find((f) => f.path === path);
195
+ field?.onFilterChange?.(value);
196
196
  if (Array.isArray(value)) {
197
- const legacy = filterConfig?.find((f) => f.id === path)
198
- legacy?.onChange?.(value)
197
+ const legacy = filterConfig?.find((f) => f.id === path);
198
+ legacy?.onChange?.(value);
199
199
  }
200
- }
200
+ };
201
201
 
202
202
  const toggleCategorical = (path: string, option: string) => {
203
- const current = filters[path]
204
- const arr = Array.isArray(current) ? current : []
205
- const next = arr.includes(option) ? arr.filter((v) => v !== option) : [...arr, option]
206
- setFilter(path, next)
207
- }
203
+ const current = filters[path];
204
+ const arr = Array.isArray(current) ? current : [];
205
+ const next = arr.includes(option) ? arr.filter((v) => v !== option) : [...arr, option];
206
+ setFilter(path, next);
207
+ };
208
208
 
209
- const totalFilters = countActiveFilters(filters)
209
+ const totalFilters = countActiveFilters(filters);
210
210
 
211
- if (entries.length === 0) return null
211
+ if (entries.length === 0) return null;
212
212
 
213
- const countBadge = resolveBadgeVariant("gray")
213
+ const countBadge = resolveBadgeVariant("gray");
214
214
 
215
215
  if (variant === "panel") {
216
216
  return (
@@ -261,7 +261,7 @@ export function FilterPanel({
261
261
  </Fragment>
262
262
  ))}
263
263
  </div>
264
- )
264
+ );
265
265
  }
266
266
 
267
267
  return (
@@ -305,7 +305,7 @@ export function FilterPanel({
305
305
  ))}
306
306
  </div>
307
307
  </div>
308
- )
308
+ );
309
309
  }
310
310
 
311
311
  function FilterBody({
@@ -316,21 +316,23 @@ function FilterBody({
316
316
  onSetFilter,
317
317
  variant = "default",
318
318
  }: {
319
- entry: Entry
320
- data: DynamicRecord[]
321
- value: FilterValue | undefined
322
- onCategoricalToggle: (option: string) => void
323
- onSetFilter: (next: FilterValue) => void
324
- variant?: "default" | "panel"
319
+ entry: Entry;
320
+ data: DynamicRecord[];
321
+ value: FilterValue | undefined;
322
+ onCategoricalToggle: (option: string) => void;
323
+ onSetFilter: (next: FilterValue) => void;
324
+ variant?: "default" | "panel";
325
325
  }) {
326
326
  if (entry.kind === "numeric-range" && entry.field) {
327
- const extremes = computeNumericExtremes(data, entry.path)
327
+ const extremes = computeNumericExtremes(data, entry.path);
328
328
  if (!extremes || extremes.min === extremes.max) {
329
- return <div className="text-xs text-content-presentation-global-tertiary">No range to filter.</div>
329
+ return (
330
+ <div className="text-xs text-content-presentation-global-tertiary">No range to filter.</div>
331
+ );
330
332
  }
331
- const step = inferStep(entry.field, extremes)
332
- const presets = resolvePresets(entry.field)
333
- const numericValue: NumericRangeFilter | undefined = isNumericRange(value) ? value : undefined
333
+ const step = inferStep(entry.field, extremes);
334
+ const presets = resolvePresets(entry.field);
335
+ const numericValue: NumericRangeFilter | undefined = isNumericRange(value) ? value : undefined;
334
336
  return (
335
337
  <div className="space-y-3">
336
338
  {presets.length > 0 && (
@@ -344,19 +346,19 @@ function FilterBody({
344
346
  onChange={onSetFilter}
345
347
  />
346
348
  </div>
347
- )
349
+ );
348
350
  }
349
351
 
350
352
  if (entry.kind === "date-range" && entry.field) {
351
- const dateValue: DateRangeFilter | undefined = isDateRange(value) ? value : undefined
353
+ const dateValue: DateRangeFilter | undefined = isDateRange(value) ? value : undefined;
352
354
  // Glare DatePicker in range mode — pick a from→to span. (No quick-preset
353
355
  // chips: the calendar range selection is the single intended interaction.)
354
- return <DatePickerRangeFilter value={dateValue} onChange={onSetFilter} />
356
+ return <DatePickerRangeFilter value={dateValue} onChange={onSetFilter} />;
355
357
  }
356
358
 
357
- const opts = getCategoricalOptions(data, entry.path, entry.field, entry.legacy)
358
- const selected = Array.isArray(value) ? value : []
359
- const isSingle = entry.field?.filterMode === "single"
359
+ const opts = getCategoricalOptions(data, entry.path, entry.field, entry.legacy);
360
+ const selected = Array.isArray(value) ? value : [];
361
+ const isSingle = entry.field?.filterMode === "single";
360
362
 
361
363
  // Searchable single-select dropdown — for fields with many options. Stores
362
364
  // the chosen value as a 1-element array (empty when cleared) to stay
@@ -365,8 +367,8 @@ function FilterBody({
365
367
  const selectOptions: SearchableSelectOption[] = opts.map((opt) => ({
366
368
  value: opt,
367
369
  label: opt,
368
- }))
369
- const current = selected[0] ?? null
370
+ }));
371
+ const current = selected[0] ?? null;
370
372
  return (
371
373
  <SearchableSelect
372
374
  options={selectOptions}
@@ -375,12 +377,12 @@ function FilterBody({
375
377
  placeholder={`Select ${entry.label}…`}
376
378
  icon={<i className="ri-search-line" />}
377
379
  />
378
- )
380
+ );
379
381
  }
380
382
 
381
383
  if (isSingle) {
382
- const current = selected[0] ?? ""
383
- const onSingleChange = (next: string) => onSetFilter(next ? [next] : [])
384
+ const current = selected[0] ?? "";
385
+ const onSingleChange = (next: string) => onSetFilter(next ? [next] : []);
384
386
  return (
385
387
  <RadioGroupPrimitive.Root
386
388
  value={current}
@@ -393,26 +395,26 @@ function FilterBody({
393
395
  )}
394
396
  >
395
397
  {opts.map((opt, i) => {
396
- const isSelected = current === opt
397
- const badgeVariant = entry.field?.variants?.[opt]
398
- const badgeProps = badgeVariant ? resolveBadgeVariant(badgeVariant) : null
398
+ const isSelected = current === opt;
399
+ const badgeVariant = entry.field?.variants?.[opt];
400
+ const badgeProps = badgeVariant ? resolveBadgeVariant(badgeVariant) : null;
399
401
  return (
400
402
  <div key={opt}>
401
- {i > 0 && (
402
- <div className="dv-divider h-px bg-[#2C2D2E]" />
403
- )}
403
+ {i > 0 && <div className="dv-divider h-px bg-[#2C2D2E]" />}
404
404
  <DataViewRadio value={opt}>
405
- {entry.legacy?.render
406
- ? entry.legacy.render(opt, isSelected)
407
- : badgeProps
408
- ? <Badge {...badgeProps} label={opt} size="XS" />
409
- : opt}
405
+ {entry.legacy?.render ? (
406
+ entry.legacy.render(opt, isSelected)
407
+ ) : badgeProps ? (
408
+ <Badge {...badgeProps} label={opt} size="XS" />
409
+ ) : (
410
+ opt
411
+ )}
410
412
  </DataViewRadio>
411
413
  </div>
412
- )
414
+ );
413
415
  })}
414
416
  </RadioGroupPrimitive.Root>
415
- )
417
+ );
416
418
  }
417
419
 
418
420
  if (variant === "panel") {
@@ -426,9 +428,9 @@ function FilterBody({
426
428
  )}
427
429
  >
428
430
  {opts.map((opt, i) => {
429
- const isSelected = selected.includes(opt)
430
- const badgeVariant = entry.field?.variants?.[opt]
431
- const badgeProps = badgeVariant ? resolveBadgeVariant(badgeVariant) : null
431
+ const isSelected = selected.includes(opt);
432
+ const badgeVariant = entry.field?.variants?.[opt];
433
+ const badgeProps = badgeVariant ? resolveBadgeVariant(badgeVariant) : null;
432
434
  return (
433
435
  <div key={opt}>
434
436
  {i > 0 && <div className="dv-divider h-px bg-[#2C2D2E]" />}
@@ -442,26 +444,28 @@ function FilterBody({
442
444
  onCheckedChange={() => onCategoricalToggle(opt)}
443
445
  />
444
446
  <span className="flex-1 leading-none">
445
- {entry.legacy?.render
446
- ? entry.legacy.render(opt, isSelected)
447
- : badgeProps
448
- ? <Badge {...badgeProps} label={opt} size="XS" />
449
- : opt}
447
+ {entry.legacy?.render ? (
448
+ entry.legacy.render(opt, isSelected)
449
+ ) : badgeProps ? (
450
+ <Badge {...badgeProps} label={opt} size="XS" />
451
+ ) : (
452
+ opt
453
+ )}
450
454
  </span>
451
455
  </label>
452
456
  </div>
453
- )
457
+ );
454
458
  })}
455
459
  </div>
456
- )
460
+ );
457
461
  }
458
462
 
459
463
  return (
460
464
  <div className="space-y-2">
461
465
  {opts.map((opt) => {
462
- const isSelected = selected.includes(opt)
463
- const badgeVariant = entry.field?.variants?.[opt]
464
- const badgeProps = badgeVariant ? resolveBadgeVariant(badgeVariant) : null
466
+ const isSelected = selected.includes(opt);
467
+ const badgeVariant = entry.field?.variants?.[opt];
468
+ const badgeProps = badgeVariant ? resolveBadgeVariant(badgeVariant) : null;
465
469
  return (
466
470
  <div key={opt} className="flex items-center space-x-2">
467
471
  <Checkbox
@@ -473,15 +477,17 @@ function FilterBody({
473
477
  htmlFor={`${entry.path}-${opt}`}
474
478
  className="text-sm text-content-presentation-global-primary cursor-pointer leading-none flex-1"
475
479
  >
476
- {entry.legacy?.render
477
- ? entry.legacy.render(opt, isSelected)
478
- : badgeProps
479
- ? <Badge {...badgeProps} label={opt} size="XS" />
480
- : opt}
480
+ {entry.legacy?.render ? (
481
+ entry.legacy.render(opt, isSelected)
482
+ ) : badgeProps ? (
483
+ <Badge {...badgeProps} label={opt} size="XS" />
484
+ ) : (
485
+ opt
486
+ )}
481
487
  </label>
482
488
  </div>
483
- )
489
+ );
484
490
  })}
485
491
  </div>
486
- )
492
+ );
487
493
  }
@@ -10,11 +10,7 @@ export type HeaderSearchProps = {
10
10
  placeholder?: string;
11
11
  };
12
12
 
13
- export function HeaderSearch({
14
- value,
15
- onChange,
16
- placeholder = "Search...",
17
- }: HeaderSearchProps) {
13
+ export function HeaderSearch({ value, onChange, placeholder = "Search..." }: HeaderSearchProps) {
18
14
  const [open, setOpen] = useState(false);
19
15
  const inputRef = useRef<HTMLInputElement>(null);
20
16
  const wrapRef = useRef<HTMLDivElement>(null);