torch-glare 2.1.2 → 2.1.4
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.
- package/apps/lib/components/Avatar.tsx +1 -1
- package/apps/lib/components/Card.tsx +68 -54
- package/apps/lib/components/DataViews/DataViewRadio.tsx +47 -0
- package/apps/lib/components/DataViews/DataViewsConfigPanel.tsx +56 -45
- package/apps/lib/components/DataViews/DataViewsHeader.tsx +130 -28
- package/apps/lib/components/DataViews/DataViewsLayout.tsx +32 -2
- package/apps/lib/components/DataViews/FilterPanel.tsx +148 -3
- package/apps/lib/components/DataViews/HeaderSearch.tsx +97 -0
- package/apps/lib/components/DataViews/InboxView.tsx +263 -282
- package/apps/lib/components/DataViews/InboxViewCard.tsx +136 -0
- package/apps/lib/components/DataViews/KanbanView.tsx +264 -153
- package/apps/lib/components/DataViews/PanelControls.tsx +10 -41
- package/apps/lib/components/DataViews/TreeView.tsx +220 -191
- package/apps/lib/components/DataViews/index.ts +6 -0
- package/apps/lib/components/DataViews/types.ts +30 -1
- package/apps/lib/components/Radio.tsx +18 -21
- package/apps/lib/components/Switch.tsx +3 -1
- package/apps/lib/components/Table.tsx +1 -1
- package/apps/lib/components/TreeFolder/TreeFolder.tsx +160 -137
- package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +221 -93
- package/apps/lib/components/TreeFolder/types.ts +9 -0
- package/apps/lib/layouts/DataViewCard.tsx +76 -0
- package/dist/src/shared/copyComponentsRecursively.js +9 -1
- package/dist/src/shared/copyComponentsRecursively.js.map +1 -1
- package/dist/src/shared/getDependenciesAndInstallNestedComponents.d.ts.map +1 -1
- package/dist/src/shared/getDependenciesAndInstallNestedComponents.js +9 -1
- package/dist/src/shared/getDependenciesAndInstallNestedComponents.js.map +1 -1
- package/docs/components/data-views-config-panel.md +204 -0
- package/docs/components/data-views-layout.md +270 -0
- package/package.json +1 -1
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: DataViewsConfigPanel
|
|
3
|
+
description: Slide-in side panel for DataViews — Saved View list, show/hide & drag-reorder columns, default sort, and a Filters tab. Used automatically by DataViewsLayout, or rendered standalone in composable mode.
|
|
4
|
+
group: Data Display
|
|
5
|
+
keywords: [data-views, config panel, config-panel, settings panel, saved view, saved-view, column visibility, reorder columns, default sort, filters tab, side panel, dark panel]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# DataViewsConfigPanel
|
|
9
|
+
|
|
10
|
+
> The settings/filters side panel for DataViews. In tab mode `DataViewsLayout`
|
|
11
|
+
> mounts and animates this for you. Render it yourself only in composable mode
|
|
12
|
+
> (custom layouts) or when you need real Saved View persistence.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
Part of `torch-glare`. Ships with the `DataViews` folder when you run
|
|
17
|
+
`npx torch-glare add DataViews` — no separate install. It depends on the
|
|
18
|
+
shared `Radio`, `Switch`, `Label`, `FilterPanel`, and a colocated internal
|
|
19
|
+
`PanelControls` file (see "Internal: PanelControls" below).
|
|
20
|
+
|
|
21
|
+
## Import
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
import { DataViewsConfigPanel } from "torch-glare"
|
|
25
|
+
import type { DataViewsConfigPanelProps } from "torch-glare"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## When to use it directly
|
|
29
|
+
|
|
30
|
+
| Situation | Use |
|
|
31
|
+
|---|---|
|
|
32
|
+
| Standard tabbed dashboard | **Don't.** Use `DataViewsLayout` — it renders this panel for you via the header settings cog. |
|
|
33
|
+
| Custom composed layout (e.g. Table + Kanban side by side) | Render `DataViewsConfigPanel` yourself alongside `useDataViewsState`. |
|
|
34
|
+
| You need working Saved View persistence | Render it yourself and pass `savedViews` + `onSavedViewChange` + `onSaveNewView` wired to your store. (Not possible through `DataViewsLayout` today — see "Saved View status".) |
|
|
35
|
+
|
|
36
|
+
## Standalone Example (composable mode)
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
import {
|
|
40
|
+
DataViewsConfigPanel,
|
|
41
|
+
TableView,
|
|
42
|
+
useDataViewsState,
|
|
43
|
+
} from "torch-glare"
|
|
44
|
+
import { useState } from "react"
|
|
45
|
+
|
|
46
|
+
function CustomScreen({ data, fields }) {
|
|
47
|
+
const s = useDataViewsState({ data, fields })
|
|
48
|
+
const [panelOpen, setPanelOpen] = useState(true)
|
|
49
|
+
|
|
50
|
+
// Your own saved-view persistence:
|
|
51
|
+
const [savedViews] = useState([
|
|
52
|
+
{ id: "all", label: "All Records" },
|
|
53
|
+
{ id: "mine", label: "Assigned to Me" },
|
|
54
|
+
])
|
|
55
|
+
const [activeView, setActiveView] = useState("all")
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<div className="flex h-screen gap-2 bg-black p-2">
|
|
59
|
+
<div className="min-w-0 flex-1">
|
|
60
|
+
<TableView
|
|
61
|
+
data={s.flatItems}
|
|
62
|
+
fields={s.resolvedFields}
|
|
63
|
+
config={s.config}
|
|
64
|
+
filterState={s.filterState}
|
|
65
|
+
onFilterChange={s.setFilterState}
|
|
66
|
+
showFilters={false}
|
|
67
|
+
/>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
{panelOpen && (
|
|
71
|
+
<DataViewsConfigPanel
|
|
72
|
+
state="open"
|
|
73
|
+
config={s.config}
|
|
74
|
+
onConfigChange={s.setConfig}
|
|
75
|
+
onClose={() => setPanelOpen(false)}
|
|
76
|
+
currentView={s.currentView}
|
|
77
|
+
fields={s.resolvedFields}
|
|
78
|
+
data={s.flatItems}
|
|
79
|
+
filterState={s.filterState}
|
|
80
|
+
onFilterChange={s.setFilterState}
|
|
81
|
+
savedViews={savedViews}
|
|
82
|
+
activeSavedView={activeView}
|
|
83
|
+
onSavedViewChange={setActiveView}
|
|
84
|
+
onSaveNewView={() => {
|
|
85
|
+
/* open your "name this view" modal, then persist */
|
|
86
|
+
}}
|
|
87
|
+
/>
|
|
88
|
+
)}
|
|
89
|
+
</div>
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## API Reference
|
|
95
|
+
|
|
96
|
+
### `DataViewsConfigPanelProps`
|
|
97
|
+
|
|
98
|
+
| Prop | Type | Required | Description |
|
|
99
|
+
|---|---|---|---|
|
|
100
|
+
| `config` | `ViewConfig` | ✅ | Current view config. `tableColumns` drives the column list; `sortBy`/`sortOrder` drive Default Sort. |
|
|
101
|
+
| `onConfigChange` | `(config: Partial<ViewConfig>) => void` | ✅ | Called with a partial patch when columns are toggled/reordered or a sort field is picked. Merge it into your config state. |
|
|
102
|
+
| `onClose` | `() => void` | ✅ | Fires when the panel's close (X) button is pressed. |
|
|
103
|
+
| `currentView` | `ViewType` | ✅ | **Currently unused inside the panel body** (declared on the prop type but not read). Still required by the type; pass the active view for forward-compatibility. |
|
|
104
|
+
| `fields` | `FieldConfig[]` | ✅ | Same field map you pass to the views. Drives the Filters tab and the column labels. |
|
|
105
|
+
| `data` | `DynamicRecord[]` | ✅ | Flat records — passed to the Filters tab (`FilterPanel`) to compute filter options. |
|
|
106
|
+
| `filterState` | `FilterState` | ✅ | Current filter values. The Filters tab reads/writes this. |
|
|
107
|
+
| `onFilterChange` | `(filters: FilterState) => void` | ✅ | Called with the full next filter object on any filter change (and on "Clear all" → `{}`). |
|
|
108
|
+
| `filterConfig` | `DynamicFilterConfig[]` | — | Optional explicit filter config forwarded to `FilterPanel`. |
|
|
109
|
+
| `savedViews` | `{ id: string; label: string }[]` | — | Saved View radio list. Defaults to a single `{ id: "default", label: "Default View" }`. |
|
|
110
|
+
| `activeSavedView` | `string` | — | Controlled selected saved-view id. If supplied, the panel is controlled (see "Controlled vs uncontrolled"). |
|
|
111
|
+
| `onSavedViewChange` | `(id: string) => void` | — | Called when a saved-view radio is selected. Required for controlled behaviour. |
|
|
112
|
+
| `onSaveNewView` | `() => void` | — | Called when "Save a New View" is clicked. No-op if omitted. |
|
|
113
|
+
| `state` | `"open" \| "closed"` | — | Drives the slide/opacity animation. Default `"open"`. Keep the panel mounted through the close animation, then unmount. |
|
|
114
|
+
|
|
115
|
+
> Note: `DataViewsConfigPanelProps` is a plain `type` (not extending HTML
|
|
116
|
+
> attributes). There is no `className`/`theme` passthrough — the panel is
|
|
117
|
+
> intentionally always-dark chrome (see "Theming").
|
|
118
|
+
|
|
119
|
+
### Controlled vs uncontrolled Saved View
|
|
120
|
+
|
|
121
|
+
The Saved View list follows the standard controlled/uncontrolled pattern:
|
|
122
|
+
|
|
123
|
+
- **Controlled** — pass both `activeSavedView` and `onSavedViewChange`. You own
|
|
124
|
+
the selected id; the panel reflects it.
|
|
125
|
+
- **Uncontrolled** — omit them. The panel keeps internal state (initialised to
|
|
126
|
+
`savedViews[0]?.id`) so the radios are still interactive, but nothing
|
|
127
|
+
persists and it resets on unmount.
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
// Controlled
|
|
131
|
+
<DataViewsConfigPanel activeSavedView={id} onSavedViewChange={setId} ... />
|
|
132
|
+
|
|
133
|
+
// Uncontrolled (still clickable, local only)
|
|
134
|
+
<DataViewsConfigPanel savedViews={views} ... />
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Saved View status
|
|
138
|
+
|
|
139
|
+
Through `DataViewsLayout` (tab mode) the four `savedView*` props are **not
|
|
140
|
+
forwarded**, so Saved View there is presentational only. To get real behaviour,
|
|
141
|
+
render `DataViewsConfigPanel` yourself (example above) or extend the layout
|
|
142
|
+
(below).
|
|
143
|
+
|
|
144
|
+
## Sections
|
|
145
|
+
|
|
146
|
+
| Section | Backed by | Behaviour |
|
|
147
|
+
|---|---|---|
|
|
148
|
+
| Saved View | `savedViews` / `activeSavedView` | Radio list + "Save a New View" button. |
|
|
149
|
+
| Table Columns | `config.tableColumns` | Green `Switch` per column toggles `visible`; rows are drag-reorderable (HTML5 DnD) and patch `order`. |
|
|
150
|
+
| Default Sort | `config.sortBy` | Single-choice radio; selecting sets `sortBy`. Direction stays on `config.sortOrder`. |
|
|
151
|
+
| Filters tab | `filterState` + `fields` | Renders `FilterPanel` restyled full-width/transparent. |
|
|
152
|
+
|
|
153
|
+
## Internal: PanelControls
|
|
154
|
+
|
|
155
|
+
The panel's radio rows and column toggle are a colocated, **non-exported**
|
|
156
|
+
file: `DataViews/PanelControls.tsx` (`RadioRow`, `DataViewsSwitch`). They are
|
|
157
|
+
deliberately **not** shared library components — the panel chrome is always
|
|
158
|
+
dark and hardcodes Figma hex values, which conflicts with the design-system
|
|
159
|
+
token / `data-theme` convention used by public components.
|
|
160
|
+
|
|
161
|
+
You normally never import these. They ship automatically because the CLI
|
|
162
|
+
copies the entire `DataViews/` folder recursively, so the relative import
|
|
163
|
+
`./PanelControls` resolves in the consumer's copy with no registry wiring.
|
|
164
|
+
|
|
165
|
+
If you need a themed radio elsewhere, use the shared `Radio` component instead
|
|
166
|
+
— not `PanelControls`.
|
|
167
|
+
|
|
168
|
+
## Extending the panel
|
|
169
|
+
|
|
170
|
+
Common changes and where to make them:
|
|
171
|
+
|
|
172
|
+
| You want to… | Do this |
|
|
173
|
+
|---|---|
|
|
174
|
+
| Make Saved View work through `DataViewsLayout` | Add `savedViews` / `activeSavedView` / `onSavedViewChange` / `onSaveNewView` to `DataViewsLayoutProps`, hold them in layout state (or accept from the host), and forward them to `<DataViewsConfigPanel>` at its render site in `DataViewsLayout.tsx`. |
|
|
175
|
+
| Add a new Config section | Add a new block inside the Config. tab in `DataViewsConfigPanel.tsx`, backed by a `config.*` field so `onConfigChange` persists it. |
|
|
176
|
+
| Restyle a radio/toggle | Edit `PanelControls.tsx`. Keep values matching the Figma spec; do not swap in the shared `Radio`/`Label` (they impose theming/layout that fights the dark panel — this was deliberate). |
|
|
177
|
+
| Change the dark chrome | The root forces `data-theme="dark"` and uses hardcoded hex (`#1C1D1F`, `#252729`, `#005ECC`, `#626467`, `#0AC713`). These are intentional Figma values, not tokens. |
|
|
178
|
+
|
|
179
|
+
After any change to the panel docs or component, update this file and rebuild
|
|
180
|
+
the MCP server (`cd mcp && pnpm build`) so the docs the server serves stay in
|
|
181
|
+
sync.
|
|
182
|
+
|
|
183
|
+
## Accessibility
|
|
184
|
+
|
|
185
|
+
- Saved View / Default Sort use Radix `RadioGroup`; the whole row is the click
|
|
186
|
+
target with keyboard support.
|
|
187
|
+
- Column toggles are accessible `Switch`es; reorder is pointer-based HTML5 DnD
|
|
188
|
+
(provide a non-DnD path if your audience needs keyboard reordering).
|
|
189
|
+
- The close button has `aria-label="Close panel"`; tab buttons expose
|
|
190
|
+
`aria-pressed`.
|
|
191
|
+
|
|
192
|
+
## Theming
|
|
193
|
+
|
|
194
|
+
Intentionally **always dark**. The root sets `data-theme="dark"` so child
|
|
195
|
+
themed components resolve dark tokens even when the host app runs light, and
|
|
196
|
+
the panel-specific chrome uses hardcoded Figma hex values rather than design
|
|
197
|
+
tokens. There is no `theme` prop — this is by design to match the Figma
|
|
198
|
+
"Cun" (#000000) panel spec.
|
|
199
|
+
|
|
200
|
+
## Related
|
|
201
|
+
|
|
202
|
+
- [`DataViewsLayout`](./data-views-layout.md) — renders this panel for you in tab mode
|
|
203
|
+
- [`Radio`](./radio.md) — the themed radio to use **outside** this panel
|
|
204
|
+
- [`Switch`](./switch.md) — the shared switch the column toggles wrap
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: DataViewsLayout
|
|
3
|
+
description: Composable multi-view layout that renders any backend response as Table, Kanban, Inbox, and/or Tree, with per-screen selection of which views to show.
|
|
4
|
+
group: Data Display
|
|
5
|
+
keywords: [data-views, layout, table, kanban, inbox, tree, multi-view, filter, switcher, dashboard, dynamic-data, fields]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# DataViewsLayout
|
|
9
|
+
|
|
10
|
+
> One backend response → many UI shapes. Pass an array of records plus a declarative list of fields, then pick which views the screen needs (`{ table: true, kanban: true }`, etc.). Filters and the settings cog are togglable per-screen.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
The component is part of `torch-glare`. It depends on `@radix-ui/react-slider`, `react-day-picker`, `lucide-react`, and `vaul` (all already vendored by the library). No extra install needed.
|
|
15
|
+
|
|
16
|
+
## Import
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
import { DataViewsLayout } from "torch-glare"
|
|
20
|
+
import type { FieldConfig, ViewVisibility } from "torch-glare"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Examples
|
|
24
|
+
|
|
25
|
+
### 1. All views, auto-detected
|
|
26
|
+
|
|
27
|
+
Just pass `data` — every primitive field becomes a column, all four views appear, the Tree tab auto-hides if no `children`/`parentId` is found.
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
const employees = [
|
|
31
|
+
{ id: 1, name: "Ada Lovelace", role: "Engineer", salary: 120000, joinDate: "2024-04-12" },
|
|
32
|
+
{ id: 2, name: "Linus Torvalds", role: "Engineer", salary: 145000, joinDate: "2023-09-01" },
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
<DataViewsLayout title="Employees" data={employees} />
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 2. Pick specific views only
|
|
39
|
+
|
|
40
|
+
Use `views` to enable only what this screen needs. Tabs for the others are hidden.
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
<DataViewsLayout
|
|
44
|
+
title="Orders"
|
|
45
|
+
data={orders}
|
|
46
|
+
views={{ table: true, kanban: true }} // only Table + Kanban tabs render
|
|
47
|
+
kanbanGroupBy="status"
|
|
48
|
+
/>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 3. Declarative fields with badges and filters
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
const fields: FieldConfig[] = [
|
|
55
|
+
{ path: "id", label: "Order #", type: "number" },
|
|
56
|
+
{ path: "customer", type: "text" },
|
|
57
|
+
{
|
|
58
|
+
path: "status",
|
|
59
|
+
type: "enum-badge",
|
|
60
|
+
variants: { Pending: "yellow", Shipped: "blue", Delivered: "green" },
|
|
61
|
+
filterable: true,
|
|
62
|
+
},
|
|
63
|
+
{ path: "total", type: "currency", currency: "USD", filterable: true },
|
|
64
|
+
{ path: "createdAt", type: "date-format", dateFormat: "YYYY-MM-DD", filterable: true },
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
<DataViewsLayout
|
|
68
|
+
title="Orders"
|
|
69
|
+
data={orders}
|
|
70
|
+
fields={fields}
|
|
71
|
+
views={{ table: true, kanban: true }}
|
|
72
|
+
kanbanGroupBy="status"
|
|
73
|
+
/>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 4. Disable filters and the settings cog
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
<DataViewsLayout
|
|
80
|
+
data={orders}
|
|
81
|
+
fields={fields}
|
|
82
|
+
views={{ table: true }}
|
|
83
|
+
showFilters={false}
|
|
84
|
+
showSettings={false}
|
|
85
|
+
/>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 5. Controlled filter state (wire to backend pagination)
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
const [filterState, setFilterState] = useState<FilterState>({})
|
|
92
|
+
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
fetchFromBackend({ filters: filterState }).then(setRows)
|
|
95
|
+
}, [filterState])
|
|
96
|
+
|
|
97
|
+
<DataViewsLayout
|
|
98
|
+
data={rows}
|
|
99
|
+
fields={fields}
|
|
100
|
+
filterState={filterState}
|
|
101
|
+
onFilterChange={setFilterState}
|
|
102
|
+
/>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 6. Hierarchical data
|
|
106
|
+
|
|
107
|
+
When records carry a `children: []` array (or a `parentId` reference), the Tree tab auto-appears. Override the detection with `treeConfig`.
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
<DataViewsLayout
|
|
111
|
+
data={departments} // each has children[]
|
|
112
|
+
treeConfig={{ childrenField: "children", nodeLabel: "name", defaultExpanded: "roots" }}
|
|
113
|
+
fields={fields}
|
|
114
|
+
/>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### 7. Inbox shape (read/starred/priority)
|
|
118
|
+
|
|
119
|
+
Inbox auto-detects `isRead`, `isStarred`, `hasAttachment`, `priority`. Override with `inboxConfig`.
|
|
120
|
+
|
|
121
|
+
```tsx
|
|
122
|
+
<DataViewsLayout
|
|
123
|
+
data={messages}
|
|
124
|
+
fields={fields}
|
|
125
|
+
views={{ inbox: true }}
|
|
126
|
+
inboxConfig={{ titlePath: "subject", previewPath: "from.name" }}
|
|
127
|
+
/>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## API Reference
|
|
131
|
+
|
|
132
|
+
### `DataViewsLayoutProps`
|
|
133
|
+
|
|
134
|
+
| Prop | Type | Default | Description |
|
|
135
|
+
|---|---|---|---|
|
|
136
|
+
| `data` | `DynamicRecord[]` | `[]` | Array of records of any shape. Fields are auto-detected from the first records. |
|
|
137
|
+
| `fields` | `FieldConfig[]` | auto-detected | Declarative field map: `path`, `type`, `filterable`, `variants`, `currency`, etc. |
|
|
138
|
+
| `title` | `string` | `"Data Views"` | Header title (hidden when `showTitle={false}`). |
|
|
139
|
+
| `description` | `string` | `"Unified data visualization across multiple views"` | Subtitle under the title. |
|
|
140
|
+
| `views` | `ViewVisibility` | all on (tree auto) | Per-view toggle: `{ table?, kanban?, inbox?, tree? }`. Omitted keys default to `true` (Tree auto-hides without hierarchy). |
|
|
141
|
+
| `kanbanGroupBy` | `string` | `"status"` | Dot-path to the field used for Kanban columns. |
|
|
142
|
+
| `inboxConfig` | `InboxConfig` | auto-detected | Map of starred/read/attachment/priority field paths for Inbox. |
|
|
143
|
+
| `treeConfig` | `TreeConfig` | auto-detected | `childrenField`, `parentField`, `idField`, `nodeLabel`, `defaultExpanded`. |
|
|
144
|
+
| `filterState` | `FilterState` | uncontrolled | Controlled filter state. Pair with `onFilterChange`. |
|
|
145
|
+
| `onFilterChange` | `(state: FilterState) => void` | — | Fires when any filter changes. When provided, the layout is controlled. |
|
|
146
|
+
| `showFilters` | `boolean` | `true` | Hide the filter panel inside every view. |
|
|
147
|
+
| `showSettings` | `boolean` | `true` | Hide the settings cog + side panel. |
|
|
148
|
+
| `showTitle` | `boolean` | `true` | Hide the header bar entirely. Useful when embedding. |
|
|
149
|
+
| `config` | `Partial<ViewConfig>` | — | Initial config: `defaultView`, `sortBy`, `sortOrder`, etc. |
|
|
150
|
+
| `className` | `string` | — | Forwarded to the root `<div>`. |
|
|
151
|
+
| `theme` | `"dark" \| "light" \| "default"` | — | Applied as `data-theme` on the root. |
|
|
152
|
+
|
|
153
|
+
### `FieldConfig`
|
|
154
|
+
|
|
155
|
+
| Prop | Type | Description |
|
|
156
|
+
|---|---|---|
|
|
157
|
+
| `path` | `string` | Dot-path into the record (`"contact.email"`). |
|
|
158
|
+
| `label` | `string` | Display label. Auto-formatted from path tail if omitted. |
|
|
159
|
+
| `type` | `FieldType` | Renderer key (see below). Auto-inferred if omitted. |
|
|
160
|
+
| `visible` | `boolean` | Show in cells. Default `true`. |
|
|
161
|
+
| `order` | `number` | Display order. |
|
|
162
|
+
| `filterable` | `boolean` | Surface this field in the filter panel. |
|
|
163
|
+
| `variants` | `Record<string, BadgeVariant>` | For `enum-badge`: per-value color map. |
|
|
164
|
+
| `currency` | `string \| CurrencyOptions` | For `currency`: ISO code or `{ symbol, locale, decimals, code }`. |
|
|
165
|
+
| `thresholds` | `[number, number]` | For `progress-bar`: warning/ok thresholds. |
|
|
166
|
+
| `max` | `number` | For `star-rating`: stars displayed. |
|
|
167
|
+
| `dateFormat` | `string \| Intl.DateTimeFormatOptions` | For `date-format`: token like `"YYYY-MM-DD"` or Intl options. |
|
|
168
|
+
| `render` | `(value, row) => ReactNode` | Escape hatch for custom JSX. |
|
|
169
|
+
|
|
170
|
+
### `FieldType` (built-in renderers)
|
|
171
|
+
|
|
172
|
+
`text` · `number` · `date` · `date-format` · `boolean` · `currency` · `number-format` · `enum-badge` · `badge-array` · `progress-bar` · `star-rating` · `icon-text` · `two-line` · `avatar` · `link` · `image` · `hidden`
|
|
173
|
+
|
|
174
|
+
### `BadgeVariant`
|
|
175
|
+
|
|
176
|
+
`green` · `greenLight` · `cocktailGreen` · `yellow` · `redOrange` · `redLight` · `rose` · `purple` · `bluePurple` · `blue` · `navy` · `gray` · `highlight`
|
|
177
|
+
|
|
178
|
+
### `ViewVisibility`
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
type ViewVisibility = {
|
|
182
|
+
table?: boolean
|
|
183
|
+
kanban?: boolean
|
|
184
|
+
inbox?: boolean
|
|
185
|
+
tree?: boolean
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Config & Filters Panel
|
|
190
|
+
|
|
191
|
+
The settings cog in the header (shown unless `showSettings={false}`) opens a
|
|
192
|
+
slide-in side panel — [`DataViewsConfigPanel`](./data-views-config-panel.md).
|
|
193
|
+
`DataViewsLayout` mounts and animates it for you; you do not render it yourself
|
|
194
|
+
in tab mode. It has two tabs:
|
|
195
|
+
|
|
196
|
+
| Tab | Section | What it does | Wired through `DataViewsLayout`? |
|
|
197
|
+
|---|---|---|---|
|
|
198
|
+
| **Config.** | Saved View | Radio list of named views + "Save a New View" button. | ❌ **Presentational only.** The layout does not pass `savedViews` / `onSavedViewChange` / `onSaveNewView`, so the panel shows a single fallback "Default View" and selection is local-state only (it does not persist or change `config`). See "Saved View status" below. |
|
|
199
|
+
| **Config.** | Table Columns | Show/hide each column (green `Switch`) and drag-reorder them. | ✅ Reads/writes `config.tableColumns` via the layout's internal config state. |
|
|
200
|
+
| **Config.** | Default Sort | Single-choice radio list that sets `config.sortBy`. | ✅ Writes `config.sortBy` (sort direction stays on `config.sortOrder`). |
|
|
201
|
+
| **Filters** | — | Delegates to `FilterPanel` for the same `fields` you passed. | ✅ Reads/writes the layout's `filterState` (and your `onFilterChange` if controlled). |
|
|
202
|
+
|
|
203
|
+
### Saved View status (read this before relying on it)
|
|
204
|
+
|
|
205
|
+
Saved View is currently a **presentational shell**. The props exist on
|
|
206
|
+
`DataViewsConfigPanel` (`savedViews`, `activeSavedView`, `onSavedViewChange`,
|
|
207
|
+
`onSaveNewView`) but `DataViewsLayout` does **not** thread them through. In tab
|
|
208
|
+
mode you therefore cannot supply or persist saved views today — clicking a row
|
|
209
|
+
updates the panel's internal state only and resets on unmount.
|
|
210
|
+
|
|
211
|
+
To get real saved-view behaviour you have two options:
|
|
212
|
+
|
|
213
|
+
1. Use **Composable Mode** (below) and render `DataViewsConfigPanel` yourself,
|
|
214
|
+
passing `savedViews` + `onSavedViewChange` wired to your own persistence.
|
|
215
|
+
2. Extend `DataViewsLayout` to forward the four `savedView*` props down to the
|
|
216
|
+
panel (see "Extending the panel" in the
|
|
217
|
+
[`DataViewsConfigPanel` doc](./data-views-config-panel.md)).
|
|
218
|
+
|
|
219
|
+
This limitation is documented honestly so an agent does not generate code that
|
|
220
|
+
passes `savedViews` to `DataViewsLayout` expecting it to work.
|
|
221
|
+
|
|
222
|
+
## Composable Mode (no tabs)
|
|
223
|
+
|
|
224
|
+
When you want a custom layout (e.g. Table on the left, Kanban on the right), bypass `DataViewsLayout` and compose the views directly.
|
|
225
|
+
|
|
226
|
+
```tsx
|
|
227
|
+
import { TableView, KanbanView, FilterPanel, useDataViewsState } from "torch-glare"
|
|
228
|
+
|
|
229
|
+
function CustomScreen({ data, fields }: Props) {
|
|
230
|
+
const state = useDataViewsState({ data, fields })
|
|
231
|
+
return (
|
|
232
|
+
<div className="grid grid-cols-2 gap-4 h-screen">
|
|
233
|
+
<TableView
|
|
234
|
+
data={state.flatItems}
|
|
235
|
+
fields={state.resolvedFields}
|
|
236
|
+
config={state.config}
|
|
237
|
+
filterState={state.filterState}
|
|
238
|
+
onFilterChange={state.setFilterState}
|
|
239
|
+
showFilters={false}
|
|
240
|
+
/>
|
|
241
|
+
<KanbanView
|
|
242
|
+
data={state.flatItems}
|
|
243
|
+
fields={state.resolvedFields}
|
|
244
|
+
config={state.config}
|
|
245
|
+
groupByField="status"
|
|
246
|
+
/>
|
|
247
|
+
</div>
|
|
248
|
+
)
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Accessibility
|
|
253
|
+
|
|
254
|
+
- The view-switcher uses `TabFormItem` (button-based, full keyboard support via Tab/Enter/Space).
|
|
255
|
+
- Tree rows expose `role="treeitem"` with `aria-expanded` and `aria-selected`.
|
|
256
|
+
- Filter checkboxes carry labels and `htmlFor` linkage.
|
|
257
|
+
- Settings panel buttons have `aria-pressed` for sort direction.
|
|
258
|
+
|
|
259
|
+
## Theming
|
|
260
|
+
|
|
261
|
+
The component uses only `*-presentation-*` design tokens. Wrap with `ThemeProvider` or pass `theme="dark" | "light" | "default"` to control color scheme.
|
|
262
|
+
|
|
263
|
+
## Related
|
|
264
|
+
|
|
265
|
+
- [`DataViewsConfigPanel`](./data-views-config-panel.md) — the settings/filters side panel (Saved View, columns, sort)
|
|
266
|
+
- [`TableView`](./table-view.md) — standalone table
|
|
267
|
+
- [`KanbanView`](./kanban-view.md) — standalone kanban
|
|
268
|
+
- [`InboxView`](./inbox-view.md) — standalone inbox
|
|
269
|
+
- [`TreeView`](./tree-view.md) — standalone tree
|
|
270
|
+
- [How-to: Render a backend response with DataViews](../how-to/data-views-from-backend-response.md) — recipes by data shape.
|