torch-glare 2.4.4 → 2.5.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 (147) hide show
  1. package/apps/lib/components/DataViews/{badgeAdapter.ts → badge.ts} +2 -2
  2. package/apps/lib/components/DataViews/cell.tsx +324 -0
  3. package/apps/lib/components/DataViews/context.ts +144 -0
  4. package/apps/lib/components/DataViews/data-views.tsx +383 -0
  5. package/apps/lib/components/DataViews/filters/children.tsx +98 -0
  6. package/apps/lib/components/DataViews/filters/custom.tsx +34 -0
  7. package/apps/lib/components/DataViews/filters/filters.tsx +163 -0
  8. package/apps/lib/components/DataViews/filters/index.ts +4 -0
  9. package/apps/lib/components/DataViews/filters/labelled.tsx +20 -0
  10. package/apps/lib/components/DataViews/filters/presets.tsx +65 -0
  11. package/apps/lib/components/DataViews/filters/summary.tsx +65 -0
  12. package/apps/lib/components/DataViews/filters/sync.tsx +35 -0
  13. package/apps/lib/components/DataViews/filters/values.ts +173 -0
  14. package/apps/lib/components/DataViews/header.tsx +217 -0
  15. package/apps/lib/components/DataViews/hooks/index.ts +5 -0
  16. package/apps/lib/components/DataViews/hooks/useActiveRow.ts +22 -0
  17. package/apps/lib/components/DataViews/hooks/useControllable.ts +52 -0
  18. package/apps/lib/components/DataViews/index.ts +74 -26
  19. package/apps/lib/components/DataViews/panel/columns.tsx +153 -0
  20. package/apps/lib/components/DataViews/panel/controls.tsx +106 -0
  21. package/apps/lib/components/DataViews/panel/index.ts +3 -0
  22. package/apps/lib/components/DataViews/panel/panel.tsx +164 -0
  23. package/apps/lib/components/DataViews/panel/saved-views.tsx +67 -0
  24. package/apps/lib/components/DataViews/panel/section.tsx +79 -0
  25. package/apps/lib/components/DataViews/panel/sort.tsx +42 -0
  26. package/apps/lib/components/DataViews/panel/tab.tsx +31 -0
  27. package/apps/lib/components/DataViews/slots.ts +63 -0
  28. package/apps/lib/components/DataViews/states.tsx +38 -0
  29. package/apps/lib/components/DataViews/types.ts +485 -178
  30. package/apps/lib/components/DataViews/views/board-view.tsx +379 -0
  31. package/apps/lib/components/DataViews/views/card-rows.tsx +36 -0
  32. package/apps/lib/components/DataViews/views/inbox-view.tsx +257 -0
  33. package/apps/lib/components/DataViews/views/pane-views.tsx +192 -0
  34. package/apps/lib/components/DataViews/views/table-view.tsx +426 -0
  35. package/apps/lib/components/DataViews/views/tree-view.tsx +365 -0
  36. package/apps/lib/components/FormBuilder/context.ts +20 -6
  37. package/apps/lib/components/FormBuilder/field-kind.ts +28 -0
  38. package/apps/lib/components/FormBuilder/fields/DateField.tsx +3 -3
  39. package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +7 -6
  40. package/apps/lib/components/FormBuilder/fields/PhoneField.tsx +30 -4
  41. package/apps/lib/components/FormBuilder/fields/SelectField.tsx +7 -7
  42. package/apps/lib/components/FormBuilder/fields/TableField.tsx +80 -52
  43. package/apps/lib/components/FormBuilder/fields/TextField.tsx +9 -9
  44. package/apps/lib/components/FormBuilder/form-builder.tsx +66 -6
  45. package/apps/lib/components/FormBuilder/index.ts +3 -1
  46. package/apps/lib/components/FormBuilder/types.ts +40 -0
  47. package/apps/lib/components/Input.tsx +3 -0
  48. package/apps/lib/components/SearchableTable.tsx +5 -4
  49. package/apps/lib/components/SectionBlock.tsx +58 -11
  50. package/apps/lib/components/Select.tsx +3 -1
  51. package/apps/lib/components/TabSwitch.tsx +16 -4
  52. package/apps/lib/components/Table.tsx +265 -67
  53. package/apps/lib/components/TreeFolder/TreeFolder.tsx +6 -3
  54. package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +16 -14
  55. package/apps/lib/components/TreeFolder/index.ts +1 -1
  56. package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +70 -207
  57. package/apps/lib/hooks/useDragDrop.tsx +365 -0
  58. package/apps/lib/hooks/useInfiniteScroll.ts +108 -0
  59. package/apps/lib/registry.json +159 -4
  60. package/apps/lib/tsconfig.tsbuildinfo +1 -1
  61. package/apps/lib/utils/dataViews/path.ts +67 -0
  62. package/apps/lib/utils/dataViews/query.ts +73 -0
  63. package/apps/lib/utils/dataViews/types.ts +187 -0
  64. package/docs/components/breadcrumb.md +1 -1
  65. package/docs/components/button-group.md +1 -1
  66. package/docs/components/button.md +1 -1
  67. package/docs/components/card.md +1 -1
  68. package/docs/components/checkbox.md +1 -1
  69. package/docs/components/data-views/backend-response.md +324 -0
  70. package/docs/components/data-views/examples/a11y-rtl.md +250 -0
  71. package/docs/components/data-views/examples/api-orders-route.md +130 -0
  72. package/docs/components/data-views/examples/fields.md +362 -0
  73. package/docs/components/data-views/examples/filters.md +308 -0
  74. package/docs/components/data-views/examples/inbox-routing.md +218 -0
  75. package/docs/components/data-views/examples/index.md +29 -0
  76. package/docs/components/data-views/examples/overview.md +244 -0
  77. package/docs/components/data-views/examples/panel.md +212 -0
  78. package/docs/components/data-views/examples/scale.md +231 -0
  79. package/docs/components/data-views/examples/server-side.md +210 -0
  80. package/docs/components/data-views/examples/state.md +250 -0
  81. package/docs/components/data-views/examples/tree-custom.md +388 -0
  82. package/docs/components/data-views/examples/view-registry.md +313 -0
  83. package/docs/components/data-views/examples/views.md +534 -0
  84. package/docs/components/data-views/guide.md +405 -0
  85. package/docs/components/data-views/index.md +1504 -0
  86. package/docs/components/data-views/migration.md +79 -0
  87. package/docs/components/date-picker.md +0 -1
  88. package/docs/components/form-builder.md +19 -8
  89. package/docs/components/form-renderer.md +2 -1
  90. package/docs/components/form.md +1 -1
  91. package/docs/components/input-field.md +1 -1
  92. package/docs/components/input-otp.md +1 -1
  93. package/docs/components/input.md +1 -1
  94. package/docs/components/labeled-check-box.md +1 -1
  95. package/docs/components/labeled-radio.md +1 -1
  96. package/docs/components/radio-card.md +1 -1
  97. package/docs/components/radio.md +1 -1
  98. package/docs/components/search-field.md +1 -1
  99. package/docs/components/section-block.md +79 -3
  100. package/docs/components/select.md +1 -1
  101. package/docs/components/simple-select.md +1 -1
  102. package/docs/components/switch.md +1 -1
  103. package/docs/components/tab-switch.md +1 -1
  104. package/docs/components/table.md +45 -8
  105. package/docs/components/text-editor.md +1 -1
  106. package/docs/components/textarea.md +1 -1
  107. package/docs/components/toggle-button.md +1 -1
  108. package/docs/components/toggle.md +1 -1
  109. package/docs/components/tree-folder.md +110 -0
  110. package/docs/how-to/forms-with-form-builder.md +6 -4
  111. package/docs/reference/components.md +16 -6
  112. package/docs/tutorials/component-composition.md +11 -13
  113. package/package.json +3 -2
  114. package/apps/lib/components/DataViews/DataViewRadio.tsx +0 -49
  115. package/apps/lib/components/DataViews/DataViewsConfigPanel.tsx +0 -393
  116. package/apps/lib/components/DataViews/DataViewsHeader.tsx +0 -207
  117. package/apps/lib/components/DataViews/DataViewsLayout.tsx +0 -332
  118. package/apps/lib/components/DataViews/FilterPanel.tsx +0 -493
  119. package/apps/lib/components/DataViews/HeaderSearch.tsx +0 -93
  120. package/apps/lib/components/DataViews/InboxView.tsx +0 -463
  121. package/apps/lib/components/DataViews/InboxViewCard.tsx +0 -127
  122. package/apps/lib/components/DataViews/KanbanView.tsx +0 -336
  123. package/apps/lib/components/DataViews/PanelControls.tsx +0 -39
  124. package/apps/lib/components/DataViews/SettingsPanel.tsx +0 -279
  125. package/apps/lib/components/DataViews/TableView.tsx +0 -212
  126. package/apps/lib/components/DataViews/TreeView.tsx +0 -364
  127. package/apps/lib/components/DataViews/fieldRenderers.tsx +0 -299
  128. package/apps/lib/components/DataViews/filters/DatePickerRangeFilter.tsx +0 -87
  129. package/apps/lib/components/DataViews/filters/DateRangePopover.tsx +0 -120
  130. package/apps/lib/components/DataViews/filters/PresetChips.tsx +0 -45
  131. package/apps/lib/components/DataViews/filters/RangeSliderWithInputs.tsx +0 -165
  132. package/apps/lib/components/DataViews/tree/TreeDrawer.tsx +0 -50
  133. package/apps/lib/components/DataViews/tree/TreeSidebar.tsx +0 -74
  134. package/apps/lib/hooks/useDataViewsState.ts +0 -175
  135. package/apps/lib/utils/dataViews/columnUtils.ts +0 -132
  136. package/apps/lib/utils/dataViews/fieldUtils.ts +0 -197
  137. package/apps/lib/utils/dataViews/nestedDataUtils.tsx +0 -371
  138. package/apps/lib/utils/dataViews/pathUtils.ts +0 -139
  139. package/apps/lib/utils/dataViews/rangeUtils.ts +0 -234
  140. package/apps/lib/utils/dataViews/treeUtils.ts +0 -396
  141. package/docs/components/data-views-config-panel.md +0 -208
  142. package/docs/components/data-views-layout.md +0 -291
  143. package/docs/components/inbox-view.md +0 -170
  144. package/docs/components/kanban-view.md +0 -135
  145. package/docs/components/table-view.md +0 -141
  146. package/docs/components/tree-view.md +0 -147
  147. package/docs/how-to/data-views-from-backend-response.md +0 -194
@@ -1,135 +0,0 @@
1
- ---
2
- title: KanbanView
3
- description: Standalone kanban board view for DataViews — groups records into columns by a field and renders each as a card. Use inside DataViewsLayout (tab mode) or directly in Composable Mode.
4
- group: Data Display
5
- keywords: [data-views, kanban-view, kanban, board, columns, group-by, cards, composable, dynamic-data, fields]
6
- ---
7
-
8
- # KanbanView
9
-
10
- > The board renderer behind `DataViewsLayout`'s "Board" tab. It groups records into columns by `groupByField` and renders each record as a card. In tab mode the layout renders it for you; render it directly only in **Composable Mode**.
11
-
12
- ## Installation
13
-
14
- TORCH Glare is a copy-in library: the CLI copies this component's source into your project
15
- (you do **not** install it from the npm package). Run `init` once, then `add`:
16
-
17
- ```bash
18
- npx torch-glare@latest init
19
- npx torch-glare@latest add KanbanView
20
- ```
21
-
22
- `add` also copies any components, hooks, and utilities that `KanbanView` depends on.
23
-
24
- ## Import
25
-
26
- Import from your project's local path — the alias configured in `glare.json` (e.g. `@/*`):
27
-
28
- ```tsx
29
- import { KanbanView } from "@/components/KanbanView";
30
- ```
31
-
32
- ## When to use it directly
33
-
34
- | Situation | Use |
35
- |---|---|
36
- | You want the standard tabbed multi-view UI | `DataViewsLayout` with `views={{ kanban: true }}` — it mounts `KanbanView` for you. |
37
- | You want a custom layout (e.g. kanban beside a table) | Render `KanbanView` directly with state from `useDataViewsState`. |
38
-
39
- ## Composable Mode example
40
-
41
- `KanbanView` groups by the `groupByField` path — every distinct value becomes a
42
- column. Column colors are assigned deterministically, or per-value via the
43
- field's `kanbanVariants`.
44
-
45
- ```tsx
46
- import { KanbanView } from "@/components/KanbanView";
47
- import { useDataViewsState } from "@/hooks/useDataViewsState";
48
- import type { FieldConfig } from "@/components/FieldConfig";
49
-
50
- const tasks = [
51
- { id: 1, title: "Spec API", status: "Todo", assignee: "Ada" },
52
- { id: 2, title: "Build UI", status: "In Progress", assignee: "Linus" },
53
- { id: 3, title: "Ship", status: "Done", assignee: "Grace" },
54
- ]
55
-
56
- const fields: FieldConfig[] = [
57
- { path: "title", type: "text" },
58
- {
59
- path: "status",
60
- type: "enum-badge",
61
- kanbanVariants: {
62
- Todo: { label: "To Do", color: "gray" },
63
- "In Progress": { label: "In Progress", color: "blue" },
64
- Done: { label: "Done", color: "green" },
65
- },
66
- },
67
- { path: "assignee", type: "text" },
68
- ]
69
-
70
- function TaskBoard() {
71
- const state = useDataViewsState({ data: tasks, fields })
72
- return (
73
- <KanbanView
74
- data={state.flatItems}
75
- fields={state.resolvedFields}
76
- config={state.config}
77
- groupByField="status"
78
- titleField="title"
79
- />
80
- )
81
- }
82
- ```
83
-
84
- ### Column header actions
85
-
86
- Pass `onColumnAction` to show an overflow (⋯) button on each column header. When
87
- omitted the button is hidden.
88
-
89
- ```tsx
90
- <KanbanView
91
- data={state.flatItems}
92
- fields={state.resolvedFields}
93
- config={state.config}
94
- groupByField="status"
95
- onColumnAction={(columnId) => openColumnMenu(columnId)}
96
- />
97
- ```
98
-
99
- ## API Reference
100
-
101
- ### `KanbanViewProps`
102
-
103
- | Prop | Type | Default | Description |
104
- |---|---|---|---|
105
- | `data` | `DynamicRecord[]` | — (required) | Records to group into columns. Pass `state.flatItems` in composable mode. |
106
- | `fields` | `FieldConfig[]` | — (required) | Field map controlling card content. Pass `state.resolvedFields`. |
107
- | `config` | `ViewConfig` | — (required) | View config from `useDataViewsState`. |
108
- | `groupByField` | `string` | `"status"` | Dot-path to the field whose distinct values become columns. |
109
- | `titleField` | `string` | first visible non-group field | Dot-path of the field rendered as the card title. |
110
- | `columns` | `DynamicColumnConfig[]` | `undefined` | Explicit column overrides. Usually derived from `fields`. |
111
- | `onDataUpdate` | `(data: DynamicRecord[]) => void` | `undefined` | Called when a card moves between columns (updates the group-by value). |
112
- | `onColumnAction` | `(columnId: string) => void` | `undefined` | Click handler for the column header overflow button. When omitted, the button is hidden. |
113
-
114
- Per-column colors come from each field's `kanbanVariants` map
115
- (`{ [value]: { label?, color? } }`). Available `color` keys: `gray`, `purple`,
116
- `orange`, `blue`, `green`, `red`. See
117
- [`DataViewsLayout`](./data-views-layout.md#fieldconfig) for the full
118
- `FieldConfig` shape.
119
-
120
- ## Accessibility
121
-
122
- - Cards are keyboard-focusable; the column overflow button is a real `<button>`.
123
- - Card titles use semantic heading markup within each [`DataViewCard`](./card.md).
124
-
125
- ## Theming
126
-
127
- Uses `*-presentation-*` tokens plus a small set of deeply-saturated column-header
128
- fills matched to `glare-torch-mode` raw tokens. Control the scheme via the
129
- parent `DataViewsLayout`'s `theme`.
130
-
131
- ## Related
132
-
133
- - [`DataViewsLayout`](./data-views-layout.md) — the tabbed container that renders this for you
134
- - [`TableView`](./table-view.md) · [`InboxView`](./inbox-view.md) · [`TreeView`](./tree-view.md) — sibling views
135
- - [How-to: Render a backend response with DataViews](../how-to/data-views-from-backend-response.md)
@@ -1,141 +0,0 @@
1
- ---
2
- title: TableView
3
- description: Standalone table view for DataViews — sortable columns, row selection, and an integrated filter panel. Use inside DataViewsLayout (tab mode) or directly in Composable Mode.
4
- group: Data Display
5
- keywords: [data-views, table-view, table, sortable, columns, selection, filter, composable, dynamic-data, fields]
6
- ---
7
-
8
- # TableView
9
-
10
- > The table renderer behind `DataViewsLayout`'s "List" tab. In tab mode the layout renders it for you. Render it directly only in **Composable Mode** (custom layouts), wiring it with `useDataViewsState`.
11
-
12
- ## Installation
13
-
14
- TORCH Glare is a copy-in library: the CLI copies this component's source into your project
15
- (you do **not** install it from the npm package). Run `init` once, then `add`:
16
-
17
- ```bash
18
- npx torch-glare@latest init
19
- npx torch-glare@latest add TableView
20
- ```
21
-
22
- `add` also copies any components, hooks, and utilities that `TableView` depends on.
23
-
24
- ## Import
25
-
26
- Import from your project's local path — the alias configured in `glare.json` (e.g. `@/*`):
27
-
28
- ```tsx
29
- import { TableView } from "@/components/TableView";
30
- ```
31
-
32
- ## When to use it directly
33
-
34
- | Situation | Use |
35
- |---|---|
36
- | You want the standard tabbed multi-view UI | `DataViewsLayout` — it mounts `TableView` for you. Don't render this yourself. |
37
- | You want a custom layout (e.g. table beside a kanban) | Render `TableView` directly with state from `useDataViewsState`. |
38
- | You only ever need a table and nothing else | Render `TableView` directly, or just use the simpler [`Table`](./table.md) / [`DataTable`](./data-table.md). |
39
-
40
- ## Composable Mode example
41
-
42
- `TableView` is controlled — it does not own field detection or config. Pull those from `useDataViewsState` (which auto-detects fields and columns from your data) and pass them down.
43
-
44
- ```tsx
45
- import { TableView } from "@/components/TableView";
46
- import { useDataViewsState } from "@/hooks/useDataViewsState";
47
- import type { FieldConfig } from "@/components/FieldConfig";
48
-
49
- const employees = [
50
- { id: 1, name: "Ada Lovelace", role: "Engineer", salary: 120000, joinDate: "2024-04-12" },
51
- { id: 2, name: "Linus Torvalds", role: "Engineer", salary: 145000, joinDate: "2023-09-01" },
52
- ]
53
-
54
- const fields: FieldConfig[] = [
55
- { path: "name", label: "Name", type: "text" },
56
- { path: "role", type: "text", filterable: true },
57
- { path: "salary", type: "currency", currency: "USD" },
58
- { path: "joinDate", type: "date-format", dateFormat: "YYYY-MM-DD" },
59
- ]
60
-
61
- function EmployeesTable() {
62
- const state = useDataViewsState({ data: employees, fields })
63
- return (
64
- <TableView
65
- data={state.flatItems}
66
- fields={state.resolvedFields}
67
- config={state.config}
68
- onSortChange={(sortBy, sortOrder) =>
69
- state.setConfig({ ...state.config, sortBy, sortOrder })
70
- }
71
- filterState={state.filterState}
72
- onFilterChange={state.setFilterState}
73
- />
74
- )
75
- }
76
- ```
77
-
78
- ### Hide the inline filter panel
79
-
80
- ```tsx
81
- <TableView
82
- data={state.flatItems}
83
- fields={state.resolvedFields}
84
- config={state.config}
85
- showFilters={false}
86
- />
87
- ```
88
-
89
- ### Controlled sorting
90
-
91
- `TableView` does not sort internally — it calls `onSortChange` and reads the
92
- active sort from `config.sortBy` / `config.sortOrder`. Wire it to your config
93
- state (or your backend) to make headers interactive.
94
-
95
- ```tsx
96
- <TableView
97
- data={rows}
98
- fields={fields}
99
- config={{ defaultView: "table", sortBy: "name", sortOrder: "asc" }}
100
- onSortChange={(sortBy, sortOrder) => refetch({ sortBy, sortOrder })}
101
- />
102
- ```
103
-
104
- ## API Reference
105
-
106
- ### `TableViewProps`
107
-
108
- | Prop | Type | Default | Description |
109
- |---|---|---|---|
110
- | `data` | `DynamicRecord[]` | — (required) | Flat array of rows to render. In composable mode pass `state.flatItems`. |
111
- | `fields` | `FieldConfig[]` | — (required) | Field map controlling which columns render and how cells format. Pass `state.resolvedFields` for auto-detected fields. |
112
- | `config` | `ViewConfig` | — (required) | View config. `sortBy` / `sortOrder` drive the active sort indicator. |
113
- | `columns` | `DynamicColumnConfig[]` | `undefined` | Explicit column overrides (visibility/order). Usually derived from `fields`. |
114
- | `onDataUpdate` | `(data: DynamicRecord[]) => void` | `undefined` | Called when row data changes (e.g. inline selection). |
115
- | `onSortChange` | `(sortBy: string, sortOrder: "asc" \| "desc") => void` | `undefined` | Fires on header click. When omitted, headers are not sortable. |
116
- | `filters` | `DynamicFilterConfig[]` | `undefined` | Explicit filter definitions. Usually inferred from `filterable` fields. |
117
- | `filterState` | `FilterState` | uncontrolled | Controlled filter state. Pair with `onFilterChange`. |
118
- | `onFilterChange` | `(filters: FilterState) => void` | `undefined` | Fires when a filter changes. When provided, the view is controlled. |
119
- | `showFilters` | `boolean` | `true` | Show the integrated filter panel. |
120
-
121
- `DynamicColumnConfig`, `DynamicFilterConfig`, `FilterState`, and `FieldConfig`
122
- share the same shapes documented in
123
- [`DataViewsLayout`](./data-views-layout.md#api-reference).
124
-
125
- ## Accessibility
126
-
127
- - Built on the accessible [`Table`](./table.md) primitive (semantic `<table>` markup, sortable headers).
128
- - Row selection uses `TableCheckbox` with proper labelling.
129
- - Filter checkboxes carry labels and `htmlFor` linkage.
130
-
131
- ## Theming
132
-
133
- Uses only `*-presentation-*` design tokens. Wrap with `ThemeProvider` or pass a
134
- `theme` to the parent `DataViewsLayout` to control the color scheme.
135
-
136
- ## Related
137
-
138
- - [`DataViewsLayout`](./data-views-layout.md) — the tabbed multi-view container that renders this for you
139
- - [`KanbanView`](./kanban-view.md) · [`InboxView`](./inbox-view.md) · [`TreeView`](./tree-view.md) — the sibling views
140
- - [`Table`](./table.md) / [`DataTable`](./data-table.md) — lower-level table components
141
- - [How-to: Render a backend response with DataViews](../how-to/data-views-from-backend-response.md)
@@ -1,147 +0,0 @@
1
- ---
2
- title: TreeView
3
- description: Standalone hierarchical tree view for DataViews — a sidebar tree of nodes with a right pane (table or card) for the selected node. Use inside DataViewsLayout (tab mode) or directly in Composable Mode.
4
- group: Data Display
5
- keywords: [data-views, tree-view, tree, hierarchy, nested, sidebar, parent-child, children, composable, dynamic-data]
6
- ---
7
-
8
- # TreeView
9
-
10
- > The tree renderer behind `DataViewsLayout`'s "Tree" tab. It builds a hierarchy from your records (via a `children[]` array or a `parentId` reference) and shows a sidebar tree with a right pane for the selected node. In tab mode the layout renders it for you — and auto-hides the Tree tab when no hierarchy is detected. Render it directly only in **Composable Mode**.
11
-
12
- ## Installation
13
-
14
- TORCH Glare is a copy-in library: the CLI copies this component's source into your project
15
- (you do **not** install it from the npm package). Run `init` once, then `add`:
16
-
17
- ```bash
18
- npx torch-glare@latest init
19
- npx torch-glare@latest add TreeView
20
- ```
21
-
22
- `add` also copies any components, hooks, and utilities that `TreeView` depends on.
23
-
24
- ## Import
25
-
26
- Import from your project's local path — the alias configured in `glare.json` (e.g. `@/*`):
27
-
28
- ```tsx
29
- import { TreeView } from "@/components/TreeView";
30
- ```
31
-
32
- ## When to use it directly
33
-
34
- | Situation | Use |
35
- |---|---|
36
- | You want the standard tabbed multi-view UI | `DataViewsLayout` — the Tree tab appears automatically when hierarchy is detected. |
37
- | You want a custom layout with an always-on tree | Render `TreeView` directly with state from `useDataViewsState`. |
38
- | You want a file/folder tree without the data-grid pane | Use [`TreeFolder`](./tree-drop-down.md) or [`TreeSubLayout`](./tree-sub-layout.md) instead. |
39
-
40
- ## Hierarchy detection
41
-
42
- `TreeView` auto-detects shape from your data. Override with `treeConfig`:
43
-
44
- - **Nested** — each record carries a `children: []` array.
45
- - **Flat / adjacency list** — each record carries a `parentId` (or similar) pointing at its parent's id.
46
-
47
- ```tsx
48
- // nested
49
- const departments = [
50
- { id: 1, name: "Engineering", children: [
51
- { id: 2, name: "Platform" },
52
- { id: 3, name: "Product" },
53
- ]},
54
- ]
55
-
56
- // flat
57
- const rows = [
58
- { id: 1, name: "Engineering", parentId: null },
59
- { id: 2, name: "Platform", parentId: 1 },
60
- ]
61
- ```
62
-
63
- ## Composable Mode example
64
-
65
- ```tsx
66
- import { TreeView } from "@/components/TreeView";
67
- import { useDataViewsState } from "@/hooks/useDataViewsState";
68
- import type { FieldConfig } from "@/components/FieldConfig";
69
- import type { TreeConfig } from "@/components/TreeConfig";
70
-
71
- const fields: FieldConfig[] = [
72
- { path: "name", type: "text" },
73
- { path: "headcount", type: "number" },
74
- ]
75
-
76
- const treeConfig: TreeConfig = {
77
- childrenField: "children",
78
- nodeLabel: "name",
79
- defaultExpanded: "roots", // "all" | "roots" | "none"
80
- defaultRightPane: "table", // "table" | "card"
81
- }
82
-
83
- function OrgTree() {
84
- const state = useDataViewsState({ data: departments, fields, treeConfig })
85
- return (
86
- <TreeView
87
- data={state.items}
88
- fields={state.resolvedFields}
89
- config={state.config}
90
- treeConfig={treeConfig}
91
- />
92
- )
93
- }
94
- ```
95
-
96
- ## API Reference
97
-
98
- ### `TreeViewProps`
99
-
100
- | Prop | Type | Default | Description |
101
- |---|---|---|---|
102
- | `data` | `DynamicRecord[]` | — (required) | Records to build the hierarchy from. Pass `state.items` (nested) in composable mode. |
103
- | `fields` | `FieldConfig[]` | — (required) | Field map for the right-pane table/card. Pass `state.resolvedFields`. |
104
- | `config` | `ViewConfig` | — (required) | View config from `useDataViewsState`. |
105
- | `treeConfig` | `TreeConfig` | auto-detected | Hierarchy + expansion + right-pane config (see below). |
106
- | `columns` | `DynamicColumnConfig[]` | `undefined` | Explicit column overrides for the right-pane table. |
107
- | `onDataUpdate` | `(data: DynamicRecord[]) => void` | `undefined` | Called when nodes move (drag-and-drop reparent), if `dndEnabled`. |
108
- | `filters` | `DynamicFilterConfig[]` | `undefined` | Explicit filter definitions. Usually inferred from `filterable` fields. |
109
- | `filterState` | `FilterState` | uncontrolled | Controlled filter state. Pair with `onFilterChange`. |
110
- | `onFilterChange` | `(filters: FilterState) => void` | `undefined` | Fires when a filter changes. |
111
- | `showFilters` | `boolean` | `true` | Show the integrated filter panel. |
112
-
113
- ### `TreeConfig`
114
-
115
- ```ts
116
- type TreeConfig = {
117
- childrenField?: string // nested mode: array property holding children
118
- parentField?: string // flat mode: property pointing at the parent id
119
- idField?: string // id property (default "id")
120
- orderField?: string // optional ordering within siblings
121
- nodeLabel?: string // which field labels each tree node
122
- defaultExpanded?: "all" | "roots" | "none"
123
- defaultRightPane?: "table" | "card" // "details" accepted as a deprecated alias of "card"
124
- dndEnabled?: boolean // enable drag-and-drop reparenting
125
- }
126
- ```
127
-
128
- See [`DataViewsLayout`](./data-views-layout.md#fieldconfig) for `FieldConfig`,
129
- `FilterState`, and related shapes.
130
-
131
- ## Accessibility
132
-
133
- - Tree rows expose `role="treeitem"` with `aria-expanded` and `aria-selected`.
134
- - On mobile the sidebar collapses into a drawer with a labelled trigger.
135
- - The right-pane table inherits [`TableView`](./table-view.md)'s accessibility.
136
-
137
- ## Theming
138
-
139
- Uses only `*-presentation-*` design tokens. Control the scheme via the parent
140
- `DataViewsLayout`'s `theme`.
141
-
142
- ## Related
143
-
144
- - [`DataViewsLayout`](./data-views-layout.md) — the tabbed container that renders this for you
145
- - [`TableView`](./table-view.md) · [`KanbanView`](./kanban-view.md) · [`InboxView`](./inbox-view.md) — sibling views
146
- - [`TreeFolder`](./tree-drop-down.md) / [`TreeSubLayout`](./tree-sub-layout.md) — non-grid tree navigation
147
- - [How-to: Render a backend response with DataViews](../how-to/data-views-from-backend-response.md)
@@ -1,194 +0,0 @@
1
- ---
2
- title: Render a backend response with DataViews
3
- description: Recipes for turning common backend JSON shapes into a DataViewsLayout — flat lists, nested hierarchies, inbox/message shapes, and server-driven filtering.
4
- group: how-to
5
- keywords: [data-views, recipes, backend, json, api, flat, nested, hierarchy, inbox, server-side, filtering, pagination, how-to]
6
- ---
7
-
8
- # Render a backend response with DataViews
9
-
10
- The goal of [`DataViewsLayout`](../components/data-views-layout.md) is "one
11
- backend response → many UI shapes." This guide maps the JSON shapes you get
12
- back from an API to the props that turn them into a working view.
13
-
14
- ## TL;DR
15
-
16
- ```tsx
17
- import { DataViewsLayout } from "@/components/DataViewsLayout";
18
-
19
- // the simplest possible case — just pass the array
20
- <DataViewsLayout title="Records" data={await api.get("/records")} />
21
- ```
22
-
23
- Everything below is about refining that default for specific shapes.
24
-
25
- ## Recipe 1 — Flat list of objects
26
-
27
- The most common API response. Pass it straight in; every primitive field
28
- becomes a column and the Table/Kanban/Inbox tabs all work. The Tree tab
29
- auto-hides because there's no hierarchy.
30
-
31
- ```tsx
32
- // GET /employees → [{ id, name, role, salary, joinDate }, ...]
33
- <DataViewsLayout title="Employees" data={employees} />
34
- ```
35
-
36
- Add a declarative `fields` map when you want typed rendering (currencies,
37
- badges, dates) and filters:
38
-
39
- ```tsx
40
- import type { FieldConfig } from "@/components/FieldConfig";
41
-
42
- const fields: FieldConfig[] = [
43
- { path: "name", label: "Name", type: "text" },
44
- { path: "role", type: "text", filterable: true },
45
- { path: "salary", type: "currency", currency: "USD", filterable: true },
46
- { path: "joinDate", type: "date-format", dateFormat: "YYYY-MM-DD" },
47
- ]
48
-
49
- <DataViewsLayout title="Employees" data={employees} fields={fields} />
50
- ```
51
-
52
- ## Recipe 2 — Status field → Kanban board
53
-
54
- When a record has a status-like field, group it into a board. Use
55
- `enum-badge` + `kanbanVariants` to color each column.
56
-
57
- ```tsx
58
- // GET /tasks → [{ id, title, status: "Todo" | "In Progress" | "Done" }, ...]
59
- const fields: FieldConfig[] = [
60
- { path: "title", type: "text" },
61
- {
62
- path: "status",
63
- type: "enum-badge",
64
- kanbanVariants: {
65
- Todo: { label: "To Do", color: "gray" },
66
- "In Progress": { label: "In Progress", color: "blue" },
67
- Done: { label: "Done", color: "green" },
68
- },
69
- },
70
- ]
71
-
72
- <DataViewsLayout
73
- title="Tasks"
74
- data={tasks}
75
- fields={fields}
76
- views={{ table: true, kanban: true }}
77
- kanbanGroupBy="status"
78
- />
79
- ```
80
-
81
- ## Recipe 3 — Nested objects (dot-paths)
82
-
83
- APIs often nest related data. Reference it with dot-paths — no flattening
84
- needed.
85
-
86
- ```tsx
87
- // GET /orders → [{ id, total, customer: { name, email } }, ...]
88
- const fields: FieldConfig[] = [
89
- { path: "id", label: "Order #", type: "number" },
90
- { path: "customer.name", label: "Customer", type: "text" },
91
- { path: "customer.email", label: "Email", type: "link", linkType: "mailto" },
92
- { path: "total", type: "currency", currency: "USD" },
93
- ]
94
-
95
- <DataViewsLayout title="Orders" data={orders} fields={fields} />
96
- ```
97
-
98
- ## Recipe 4 — Hierarchy (nested `children[]` or flat `parentId`)
99
-
100
- When records form a tree, the Tree tab appears automatically. Both shapes work:
101
-
102
- ```tsx
103
- // Nested: GET /departments → [{ id, name, children: [...] }]
104
- <DataViewsLayout
105
- data={departments}
106
- treeConfig={{ childrenField: "children", nodeLabel: "name", defaultExpanded: "roots" }}
107
- />
108
-
109
- // Flat / adjacency list: GET /nodes → [{ id, name, parentId }]
110
- <DataViewsLayout
111
- data={nodes}
112
- treeConfig={{ parentField: "parentId", idField: "id", nodeLabel: "name" }}
113
- />
114
- ```
115
-
116
- ## Recipe 5 — Message/inbox shape
117
-
118
- For mailbox-like data, the Inbox view auto-detects `isRead`, `isStarred`,
119
- `hasAttachment`, and `priority`. Map title/preview/date with `inboxConfig`.
120
-
121
- ```tsx
122
- // GET /messages → [{ id, subject, from: { name }, isRead, isStarred, sentAt }]
123
- <DataViewsLayout
124
- data={messages}
125
- views={{ inbox: true }}
126
- inboxConfig={{ titlePath: "subject", previewPath: "from.name", dateField: "sentAt" }}
127
- />
128
- ```
129
-
130
- ## Recipe 6 — Server-driven filtering & pagination
131
-
132
- Make the layout controlled: hold `filterState` yourself and refetch when it
133
- changes. This keeps the URL/server as the source of truth.
134
-
135
- ```tsx
136
- import { useState, useEffect } from "react"
137
- import type { FilterState } from "@/components/FilterState";
138
-
139
- function ServerDriven() {
140
- const [rows, setRows] = useState([])
141
- const [filterState, setFilterState] = useState<FilterState>({})
142
-
143
- useEffect(() => {
144
- api.get("/records", { params: { filters: filterState } }).then(setRows)
145
- }, [filterState])
146
-
147
- return (
148
- <DataViewsLayout
149
- data={rows}
150
- fields={fields}
151
- filterState={filterState}
152
- onFilterChange={setFilterState}
153
- />
154
- )
155
- }
156
- ```
157
-
158
- ## Recipe 7 — Custom layout (composable mode)
159
-
160
- When tabs aren't what you want — e.g. a table beside a kanban — bypass
161
- `DataViewsLayout` and compose the views with `useDataViewsState`.
162
-
163
- ```tsx
164
- import { KanbanView } from "@/components/KanbanView";
165
- import { TableView } from "@/components/TableView";
166
- import { useDataViewsState } from "@/hooks/useDataViewsState";
167
-
168
- function SplitScreen({ data, fields }) {
169
- const state = useDataViewsState({ data, fields })
170
- return (
171
- <div className="grid grid-cols-2 gap-4 h-screen">
172
- <TableView data={state.flatItems} fields={state.resolvedFields} config={state.config} showFilters={false} />
173
- <KanbanView data={state.flatItems} fields={state.resolvedFields} config={state.config} groupByField="status" />
174
- </div>
175
- )
176
- }
177
- ```
178
-
179
- See each view's reference: [TableView](../components/table-view.md) ·
180
- [KanbanView](../components/kanban-view.md) ·
181
- [InboxView](../components/inbox-view.md) ·
182
- [TreeView](../components/tree-view.md).
183
-
184
- ## Gotchas
185
-
186
- - **Empty `data`** → all views render their empty state; pass `isLoading` upstream if you fetch async.
187
- - **Tree tab missing?** No hierarchy was detected. Supply `treeConfig` explicitly or check your `childrenField` / `parentField`.
188
- - **Unwanted filters?** The panel auto-detects filterable text fields with few unique values (e.g. `id`, `name`). Set `filterable: false` on a field to exclude it. For a field with many options, set `filterVariant: "searchable-select"` to render a searchable dropdown instead of a long checkbox list.
189
- - **Saved Views don't persist** in tab mode — that's a known limitation documented in [`DataViewsConfigPanel`](../components/data-views-config-panel.md). Use composable mode for real persistence.
190
-
191
- ## Related
192
-
193
- - [`DataViewsLayout`](../components/data-views-layout.md) — full prop reference
194
- - [`DataViewsConfigPanel`](../components/data-views-config-panel.md) — settings/filters panel