torch-glare 2.1.1 → 2.1.2

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 (62) hide show
  1. package/apps/lib/components/BadgeField.tsx +2 -2
  2. package/apps/lib/components/DataViews/ARCHITECTURE.md +439 -0
  3. package/apps/lib/components/DataViews/DataViewsConfigPanel.tsx +416 -0
  4. package/apps/lib/components/DataViews/DataViewsHeader.tsx +126 -0
  5. package/apps/lib/components/DataViews/DataViewsLayout.tsx +300 -0
  6. package/apps/lib/components/DataViews/FilterPanel.tsx +324 -0
  7. package/apps/lib/components/DataViews/InboxView.tsx +514 -0
  8. package/apps/lib/components/DataViews/KanbanView.tsx +242 -0
  9. package/apps/lib/components/DataViews/PanelControls.tsx +80 -0
  10. package/apps/lib/components/DataViews/SettingsPanel.tsx +285 -0
  11. package/apps/lib/components/DataViews/TableView.tsx +232 -0
  12. package/apps/lib/components/DataViews/TreeView.tsx +363 -0
  13. package/apps/lib/components/DataViews/badgeAdapter.ts +45 -0
  14. package/apps/lib/components/DataViews/fieldRenderers.tsx +334 -0
  15. package/apps/lib/components/DataViews/filters/DateRangePopover.tsx +113 -0
  16. package/apps/lib/components/DataViews/filters/PresetChips.tsx +45 -0
  17. package/apps/lib/components/DataViews/filters/RangeSliderWithInputs.tsx +154 -0
  18. package/apps/lib/components/DataViews/index.ts +30 -0
  19. package/apps/lib/components/DataViews/tree/TreeDrawer.tsx +54 -0
  20. package/apps/lib/components/DataViews/tree/TreeSidebar.tsx +77 -0
  21. package/apps/lib/components/DataViews/types.ts +177 -0
  22. package/apps/lib/components/TreeFolder/TreeFolder.tsx +387 -0
  23. package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +80 -0
  24. package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +235 -0
  25. package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +60 -0
  26. package/apps/lib/components/TreeFolder/icons.tsx +63 -0
  27. package/apps/lib/components/TreeFolder/index.ts +17 -0
  28. package/apps/lib/components/TreeFolder/treeFolderUtils.ts +114 -0
  29. package/apps/lib/components/TreeFolder/types.ts +68 -0
  30. package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +261 -0
  31. package/apps/lib/hooks/useDataViewsState.ts +169 -0
  32. package/apps/lib/hooks/useIsMobile.ts +21 -0
  33. package/apps/lib/utils/dataViews/columnUtils.ts +130 -0
  34. package/apps/lib/utils/dataViews/fieldUtils.ts +198 -0
  35. package/apps/lib/utils/dataViews/nestedDataUtils.tsx +364 -0
  36. package/apps/lib/utils/dataViews/pathUtils.ts +132 -0
  37. package/apps/lib/utils/dataViews/rangeUtils.ts +225 -0
  38. package/apps/lib/utils/dataViews/treeUtils.ts +403 -0
  39. package/dist/bin/index.js +3 -3
  40. package/dist/bin/index.js.map +1 -1
  41. package/dist/src/commands/add.d.ts.map +1 -1
  42. package/dist/src/commands/add.js +29 -6
  43. package/dist/src/commands/add.js.map +1 -1
  44. package/dist/src/commands/utils.d.ts.map +1 -1
  45. package/dist/src/commands/utils.js +22 -2
  46. package/dist/src/commands/utils.js.map +1 -1
  47. package/dist/src/shared/copyComponentsRecursively.d.ts.map +1 -1
  48. package/dist/src/shared/copyComponentsRecursively.js +8 -1
  49. package/dist/src/shared/copyComponentsRecursively.js.map +1 -1
  50. package/dist/src/shared/getDependenciesAndInstallNestedComponents.d.ts +18 -4
  51. package/dist/src/shared/getDependenciesAndInstallNestedComponents.d.ts.map +1 -1
  52. package/dist/src/shared/getDependenciesAndInstallNestedComponents.js +110 -40
  53. package/dist/src/shared/getDependenciesAndInstallNestedComponents.js.map +1 -1
  54. package/docs/components/form-stepper.md +244 -0
  55. package/docs/components/stepper.md +215 -0
  56. package/docs/components/timeline.md +248 -0
  57. package/package.json +6 -6
  58. package/apps/lib/components/Charts-dev.tsx +0 -365
  59. package/apps/lib/components/Command-dev.tsx +0 -151
  60. package/apps/lib/components/IosDatePicker-dev.tsx +0 -341
  61. /package/docs/components/{labeled-checkbox.md → labeled-check-box.md} +0 -0
  62. /package/docs/components/{tree-dropdown.md → tree-drop-down.md} +0 -0
@@ -172,6 +172,7 @@ export const BadgeField = forwardRef<HTMLInputElement, Props>(
172
172
  style={{ width: dropDownListWidth }}
173
173
  variant={variant}
174
174
  onKeyDown={handleKeyDown}
175
+ className="p-2 flex flex-wrap gap-1"
175
176
  >
176
177
  <>
177
178
  {filteredTags.length > 0 ? (
@@ -182,8 +183,7 @@ export const BadgeField = forwardRef<HTMLInputElement, Props>(
182
183
  color={tag.variant as any}
183
184
  label={tag.name}
184
185
  onClick={() => handleSelectTag(tag.id)}
185
- className={`outline-none ${focusedPopoverIndex === index ? "ring-2 ring-blue-500" : ""
186
- } ${index !== 0 ? "mt-1" : ""}`}
186
+ className={`outline-none ${focusedPopoverIndex === index ? "ring-2 ring-blue-500" : ""}`}
187
187
  tabIndex={focusedPopoverIndex === index ? 0 : -1}
188
188
  />
189
189
  ))
@@ -0,0 +1,439 @@
1
+ # DataViews — Architecture & Component Map
2
+
3
+ Internal reference for the DataViews feature. Use this when changing UI, debugging, or syncing with the designer.
4
+
5
+ **Demo route:** `/data-views` (in `apps/app/data-views/page.tsx`)
6
+ **Library root:** `apps/lib/components/DataViews/`
7
+
8
+ ---
9
+
10
+ ## 1. What is DataViews?
11
+
12
+ A composable multi-view layout. One backend response (array of records) renders as any combination of **Table**, **Kanban**, **Inbox**, **Tree** — chosen per-screen via a `views` prop. Filters and the settings cog are togglable.
13
+
14
+ ```tsx
15
+ <DataViewsLayout
16
+ title="Orders"
17
+ data={orders}
18
+ fields={[
19
+ { path: "status", type: "enum-badge", variants: { Pending: "yellow", Shipped: "blue" }, filterable: true },
20
+ { path: "total", type: "currency", currency: "USD", filterable: true },
21
+ ]}
22
+ views={{ table: true, kanban: true }} // only these tabs render
23
+ showFilters
24
+ showSettings
25
+ />
26
+ ```
27
+
28
+ ---
29
+
30
+ ## 2. Layout vs. Components vs. Built-ins
31
+
32
+ ### 🟦 The Layout — `DataViewsLayout`
33
+
34
+ The **frame**. Orchestrator, not a UI piece on its own.
35
+
36
+ Owns:
37
+ - Page header (title + description)
38
+ - View-switcher tab bar
39
+ - Settings cog button
40
+ - Decision of which view to render
41
+ - Decision of whether to show filter panel / settings panel
42
+
43
+ Does **not** render the filter panel or settings panel directly — it passes `showFilters` down to each view, and toggles `SettingsPanel` on the side.
44
+
45
+ ### 🟩 The DataViews Components (new — 6 total)
46
+
47
+ | Component | File | Role |
48
+ |---|---|---|
49
+ | `DataViewsLayout` | `DataViewsLayout.tsx` | The frame (header + tabs + settings toggle) |
50
+ | `TableView` | `TableView.tsx` | Sortable table + search + optional filter panel |
51
+ | `KanbanView` | `KanbanView.tsx` | Drag-and-drop board grouped by an enum-badge field |
52
+ | `InboxView` | `InboxView.tsx` | Three-pane mail-style list (filters \| list \| detail) |
53
+ | `TreeView` | `TreeView.tsx` | Two-pane explorer (tree sidebar + right pane) |
54
+ | `FilterPanel` | `FilterPanel.tsx` | Left-sidebar filter panel (used by Table/Inbox/Tree) |
55
+ | `SettingsPanel` | `SettingsPanel.tsx` | Right-sidebar configurator (column toggles + sort + view-specific settings) |
56
+
57
+ ### 🟨 Built-ins (existing torch-glare components, reused)
58
+
59
+ These already exist in glare and were not modified for this feature:
60
+
61
+ - `Badge` — status/priority chips (uses `color` + `badgeStyle: "solid" | "subtle"`)
62
+ - `Button` — Settings cog, action buttons, drawer trigger
63
+ - `Card`, `CardHeader`, `CardContent` — Kanban cards, Inbox detail pane
64
+ - `Checkbox` — table row select + filter list checkboxes
65
+ - `InputField` — the search bar
66
+ - `Avatar`, `AvatarFallback`, `AvatarImage` — inbox sender avatars
67
+ - `Switch` — settings panel toggles (column visibility, show filters)
68
+ - `Divider` — separators in panels (was `Separator` in source)
69
+ - `Label` — filter / setting labels
70
+ - `RadioGroup`, `Radio` — Kanban groupBy picker in settings
71
+ - `Table`, `TableHeader`, `TableBody`, `TableHead`, `TableRow`, `TableCell`, `TableCheckbox` — the actual `<table>` primitive
72
+ - `TabFormItem` — view-switcher tabs (top variant) + inbox sidebar chips (side variant)
73
+ - `Tooltip` — *(available, not currently mounted)*
74
+ - `Drawer` (from `vaul`) — mobile tree drawer
75
+ - Radix `Popover` — date-range filter popover
76
+ - Radix `Slider` — numeric range filter
77
+
78
+ ---
79
+
80
+ ## 3. The Layout Structure
81
+
82
+ ```
83
+ ┌──────────────────────────────────────────────────────────────────────┐
84
+ │ DataViewsLayout root <div class="bg-body-primary"> (theme-aware) │
85
+ ├──────────────────────────────────────────────────────────────────────┤
86
+ │ Header (showTitle) │
87
+ │ ├── Title + description (left) │
88
+ │ └── View tabs (TabFormItem×N) + Settings button (right) │
89
+ ├──────────────────────────────────────────────────────────────────────┤
90
+ │ main (flex row, overflow-hidden) │
91
+ │ ├── Active view (one of): │
92
+ │ │ ├── TableView [FilterPanel | table+search] │
93
+ │ │ ├── KanbanView [columns of cards] │
94
+ │ │ ├── InboxView [filter+sidebar | list | detail pane] │
95
+ │ │ └── TreeView [tree sidebar | FilterPanel | right pane] │
96
+ │ │ │
97
+ │ └── SettingsPanel (slides in from right when cog clicked) │
98
+ └──────────────────────────────────────────────────────────────────────┘
99
+ ```
100
+
101
+ ### Why filters live **inside** each view, not in the layout
102
+
103
+ - **Kanban** intentionally has no filter panel (boards rarely do)
104
+ - **Tree** puts the filter panel **between** the tree sidebar and the right pane
105
+ - **Inbox** puts the filter panel **inside** its own left sidebar (mixed with starred/unread/priority chips)
106
+ - **Table** puts the filter panel at the far left, like a standard list page
107
+
108
+ Each view decides where filters go in its own internal grid. The layout just passes down `showFilters` as a boolean. Per-view `showFilters` prop also exists on each view component for composable mode.
109
+
110
+ ---
111
+
112
+ ## 4. Composable mode (no tabs)
113
+
114
+ When you want a custom layout (e.g. Table on the left, Kanban on the right), bypass `DataViewsLayout` and compose the views directly using the shared state hook:
115
+
116
+ ```tsx
117
+ import { TableView, KanbanView, FilterPanel, useDataViewsState } from "@/components/DataViews"
118
+
119
+ const state = useDataViewsState({ data, fields })
120
+
121
+ return (
122
+ <div className="grid grid-cols-2 gap-4 h-screen">
123
+ <TableView {...state} showFilters={false} />
124
+ <KanbanView {...state} groupByField="status" />
125
+ </div>
126
+ )
127
+ ```
128
+
129
+ `useDataViewsState` (`apps/lib/hooks/useDataViewsState.ts`) owns: filter state, sort state, field detection, column visibility config, tree shape detection, enabled-views resolution.
130
+
131
+ ---
132
+
133
+ ## 5. Data flow
134
+
135
+ ```
136
+ Backend → data: DynamicRecord[] (array of plain objects)
137
+
138
+
139
+ FieldConfig[] (declarative field map, optional)
140
+
141
+
142
+ useDataViewsState ──► detectFields() ─► merges with user fields
143
+ │ │
144
+ ▼ ▼
145
+ flatItems (tree → flat for non-tree views) resolvedFields
146
+
147
+
148
+ active view ──► FilterPanel (if enabled)
149
+ │ └─► filterState (controlled or internal)
150
+
151
+ renderField() per cell → torch-glare Badge / Avatar / etc.
152
+ ```
153
+
154
+ ### Where state lives
155
+
156
+ | State | Owner | Notes |
157
+ |---|---|---|
158
+ | `currentView` | `useDataViewsState` | View tab selection |
159
+ | `config` (sort, columns, kanbanGroupBy) | `useDataViewsState` | Single source of truth for sort + column visibility |
160
+ | `items` | `useDataViewsState` | Mutable copy of `data` (kanban drag-drop edits this) |
161
+ | `filterState` | `useDataViewsState` OR consumer | Controlled when `onFilterChange` is passed |
162
+ | `selectedItem` | Per view | Inbox + Tree pick their own |
163
+ | `expanded`, `selectedId` | TreeView | Tree-only |
164
+ | `searchQuery` | TableView / InboxView | Local |
165
+ | `showSettingsPanel` | `DataViewsLayout` | Toggled by cog button |
166
+
167
+ ---
168
+
169
+ ## 6. Utility files
170
+
171
+ Located in `apps/lib/utils/dataViews/`. Pure data — no React UI imports.
172
+
173
+ | File | Purpose |
174
+ |---|---|
175
+ | `pathUtils.ts` | `getByPath`, `setByPath`, `matchesFilterValues`, `formatPathLabel` — dot-path traversal & filter matching |
176
+ | `fieldUtils.ts` | `detectFields`, `mergeFields`, `inferFieldType`, `resolveInboxConfig`, `visibleFields` — declarative field API |
177
+ | `columnUtils.ts` | `detectColumns`, `mergeColumns` — legacy column config (kept for back-compat) |
178
+ | `rangeUtils.ts` | `computeNumericExtremes`, `inferStep`, `presetToFilterValue`, `resolvePresets` — numeric/date range filters |
179
+ | `treeUtils.ts` | `autoDetectTreeShape`, `buildTree`, `pruneTree`, `flattenAll` — hierarchy primitives |
180
+ | `nestedDataUtils.tsx` | `renderDetailView`, `renderNestedObject`, `isPlainObject`, `isCurrencyField` — nested-object detail rendering |
181
+
182
+ The only non-pure one is `nestedDataUtils.tsx` because it returns JSX for the inbox detail pane.
183
+
184
+ ---
185
+
186
+ ## 7. Types (`types.ts`)
187
+
188
+ Key types exported from `apps/lib/components/DataViews/types.ts`:
189
+
190
+ | Type | Shape |
191
+ |---|---|
192
+ | `DynamicRecord` | `Record<string, any>` — any backend object |
193
+ | `ViewType` | `"table" \| "kanban" \| "inbox" \| "tree"` |
194
+ | `ViewVisibility` | `{ table?, kanban?, inbox?, tree?: boolean }` |
195
+ | `FieldConfig` | The declarative field definition (path, type, variants, filterable, etc.) |
196
+ | `FieldType` | 17 renderer keys (text, number, enum-badge, currency, progress-bar, …) |
197
+ | `BadgeVariant` | Internal dataviews badge palette — translated by `badgeAdapter.ts` |
198
+ | `FilterState` | `Record<string, FilterValue>` |
199
+ | `FilterValue` | `string[] \| { kind: "number", min?, max? } \| { kind: "date", from?, to? }` |
200
+ | `ViewConfig` | `defaultView, tableColumns, kanbanGroupBy, showFilters, showPreviewPane, sortBy, sortOrder` |
201
+ | `InboxConfig` | `starredField, readField, attachmentField, priorityField, titlePath, previewPath` |
202
+ | `TreeConfig` | `childrenField, parentField, idField, nodeLabel, defaultExpanded, defaultRightPane` |
203
+
204
+ ---
205
+
206
+ ## 8. Field types (renderers)
207
+
208
+ Defined in `fieldRenderers.tsx`. Map of `FieldType` → JSX renderer:
209
+
210
+ | `type` | What it renders | Key field config props |
211
+ |---|---|---|
212
+ | `text` | Plain string | — |
213
+ | `number` | Tabular numeric | — |
214
+ | `date` | Raw date string | — |
215
+ | `date-format` | `Intl.DateTimeFormat`-style or token-based | `dateFormat: "YYYY-MM-DD"` or `Intl.DateTimeFormatOptions` |
216
+ | `boolean` | Yes/No Badge | `trueVariant`, `falseVariant`, `trueLabel`, `falseLabel` |
217
+ | `currency` | `Intl.NumberFormat` currency | `currency: "USD"` or `{ symbol, locale, decimals, code }` |
218
+ | `number-format` | `Intl.NumberFormat` formatted | `format: Intl.NumberFormatOptions` |
219
+ | `enum-badge` | Single colored badge | `variants: { Value: "green" \| "yellow" \| ... }` |
220
+ | `badge-array` | Row of badges with overflow `+N` | `variant`, `limit` |
221
+ | `progress-bar` | Horizontal bar with % | `thresholds: [warn, ok]` |
222
+ | `star-rating` | Filled-star row | `max` (default 5) |
223
+ | `icon-text` | Icon + text | `icon` (lucide name or emoji), `iconPosition` |
224
+ | `two-line` | Bold primary + small secondary | `secondaryPath` (dot-path) |
225
+ | `avatar` | torch-glare Avatar | `fallbackPath` (for initials) |
226
+ | `link` | `<a>` with mailto/tel/url | `linkType` |
227
+ | `image` | `<img>` thumbnail | — |
228
+ | `hidden` | Renders nothing | — |
229
+
230
+ Auto-inference rules live in `inferFieldType()` (fieldUtils.ts):
231
+ - `status` / `priority` keys → `enum-badge`
232
+ - `email` / `phone` / `url` / `website` → `link`
233
+ - `tags` / `labels` → `badge-array`
234
+ - `date` / `time` suffixes → `date-format`
235
+ - `salary` / `price` / `cost` / `amount` / `pay` / `fee` (or value smells like currency) → `currency`
236
+ - `rating` / `score` (and value ≤ 5) → `star-rating`
237
+ - ISO date strings → `date-format`
238
+ - Arrays → `badge-array`
239
+ - Booleans → `boolean`
240
+
241
+ The escape hatch: `field.render = (value, row) => <YourJSX />` always wins.
242
+
243
+ ---
244
+
245
+ ## 9. Badge adapter (`badgeAdapter.ts`)
246
+
247
+ The dataviews source used its own `BadgeVariant` enum (`green`, `greenLight`, `redOrange`, `bluePurple`, `navy`, etc.) that pre-dates torch-glare's current Badge API.
248
+
249
+ torch-glare Badge uses `color` (gray/slate/red/orange/yellow/green/ocean/blue/purple/rose) + `badgeStyle` (solid/subtle).
250
+
251
+ `resolveBadgeVariant(variant)` translates between the two. **Default style is `subtle`** to match glare's library default. Variants ending in `Light` or `navy` / `bluePurple` / `cocktailGreen` explicitly request solid.
252
+
253
+ Want to change badge defaults globally? → edit `badgeAdapter.ts`.
254
+ Want per-field control? → it could be exposed on `FieldConfig` as a new `badgeStyle?: "solid" | "subtle"` field (not done yet — propose it before adding).
255
+
256
+ ---
257
+
258
+ ## 10. Styling & theming
259
+
260
+ ### Background tokens used
261
+
262
+ | Surface | Token | Dark | Light |
263
+ |---|---|---|---|
264
+ | Page | `bg-background-presentation-body-primary` | `#252729` | `#F0F0F0` |
265
+ | Side panels / Kanban column headers | `bg-background-presentation-body-overlay-primary` | `#1C1D1F` | `#F0F0F0` |
266
+ | Subtle fills (chips, drop zones) | `bg-background-presentation-form-field-primary` | `#1C1D1F` | white-ish |
267
+
268
+ **Do not use `bg-background-presentation-global-*`** — those tokens don't exist in this design system. They were inherited from the original data-views source and resolve to nothing. The Tailwind classes still validate but render as transparent. We swapped them all out; if you see one come back, it's a regression.
269
+
270
+ ### Borders / text
271
+
272
+ | Token | Use |
273
+ |---|---|
274
+ | `border-border-presentation-global-primary` | Panel borders, dividers |
275
+ | `text-content-presentation-global-primary` | Primary text |
276
+ | `text-content-presentation-global-secondary` | Secondary text |
277
+ | `text-content-presentation-global-tertiary` | Muted labels |
278
+ | `text-content-presentation-action-primary` | Active state text |
279
+ | `bg-content-presentation-action-primary` | Active-tab + slider track + selected-mode bg |
280
+
281
+ These `content-presentation-global-*` tokens **do exist** for text/borders — only the `background-*-global-*` family is missing.
282
+
283
+ ### Theme switching
284
+
285
+ `DataViewsLayout` accepts `theme?: "dark" | "light" | "default"` and applies it via `data-theme={theme}`. Without it, the component inherits the nearest ancestor's `data-theme` (set by `ThemeProvider`).
286
+
287
+ ---
288
+
289
+ ## 11. Tree view internals
290
+
291
+ `TreeView.tsx` has the most complex layout. Worth a separate note.
292
+
293
+ **Three columns** in desktop mode:
294
+ 1. **Tree sidebar** (`TreeSidebar`) — the tree itself
295
+ 2. **Filter panel** (`FilterPanel`) — only when `showFilters && hasFilterableFields`
296
+ 3. **Right pane** — toggles between two modes via the toolbar:
297
+ - **Table mode** (default) — `<TableView>` over the selected node + descendants
298
+ - **Details mode** — single-record detail view with nested-object rendering
299
+
300
+ The tree owns the filter state; the embedded `TableView` is told `showFilters={false}` so it doesn't render its own filter panel.
301
+
302
+ **Mobile** collapses the tree sidebar into a left-edge drawer (`TreeDrawer` via `vaul`). The right pane gets a hamburger trigger.
303
+
304
+ **Auto-detection**: if neither `treeConfig.childrenField` nor `treeConfig.parentField` is set, the view inspects the first record:
305
+ - nested: `children`, `items`, `kids`, `subItems`, `nodes`
306
+ - flat: `parentId`, `parent_id`, `parent`, `managerId`, `manager`
307
+
308
+ If nothing matches and no `views.tree` override, the Tree tab auto-hides.
309
+
310
+ ---
311
+
312
+ ## 12. Filter panel rules
313
+
314
+ A field becomes filterable when any of:
315
+ 1. `field.filterable === true` (explicit opt-in)
316
+ 2. `type` is `enum-badge`, `boolean`, `badge-array`, or `icon-text` (auto)
317
+ 3. type is text with ≤10 unique values (heuristic fallback)
318
+
319
+ Numeric / date fields **require explicit `filterable: true`** — they get range sliders / date pickers respectively.
320
+
321
+ The panel renders three filter kinds:
322
+ - **Categorical** — checkbox list (multi-select OR semantics)
323
+ - **Numeric range** — Radix slider + min/max inputs + preset chips
324
+ - **Date range** — Radix popover with `react-day-picker` + preset chips (`Today`, `Last 7 days`, `Last 30 days`, `This year`)
325
+
326
+ Filter state shape:
327
+ ```ts
328
+ type FilterValue =
329
+ | string[] // categorical
330
+ | { kind: "number"; min?: number; max?: number } // numeric range
331
+ | { kind: "date"; from?: string; to?: string } // date range, ISO YYYY-MM-DD
332
+ ```
333
+
334
+ ---
335
+
336
+ ## 13. Settings panel sections
337
+
338
+ `SettingsPanel.tsx` renders sections conditionally based on `currentView`:
339
+
340
+ | Section | When | What it controls |
341
+ |---|---|---|
342
+ | General → Show Filters | always | `config.showFilters` |
343
+ | Table Columns | `currentView === "table"` | Column visibility (Switch) + reorder (HTML5 DnD) |
344
+ | Kanban Grouping | `currentView === "kanban"` | Radio over enum-badge fields → `kanbanGroupBy` |
345
+ | Inbox Layout → Show Preview Pane | `currentView === "inbox"` | `config.showPreviewPane` |
346
+ | Sort | always (if columns exist) | Per-column three-state: none/asc/desc |
347
+
348
+ ---
349
+
350
+ ## 14. CLI distribution
351
+
352
+ The DataViews folder + utils folder + hooks are **not yet** distributable via `torch-glare add <Component>` — the existing CLI scans top-level `.tsx` files only. Adding `DataViews/` as a unit requires extending the CLI to recognize folder-based components and copy:
353
+ - `apps/lib/components/DataViews/` (whole folder)
354
+ - `apps/lib/utils/dataViews/` (whole folder)
355
+ - `apps/lib/hooks/useDataViewsState.ts`
356
+ - `apps/lib/hooks/useIsMobile.ts`
357
+
358
+ …plus running `getDependenciesAndInstallNestedComponents` recursively across all those files to install any missing peer deps (`@radix-ui/react-slider`, `react-day-picker`, `vaul`).
359
+
360
+ ---
361
+
362
+ ## 15. MCP documentation
363
+
364
+ Public-facing docs live in `mcp/docs/`:
365
+
366
+ - `mcp/docs/components/data-views-layout.md` — main API reference
367
+ - `mcp/docs/components/table-view.md`
368
+ - `mcp/docs/components/kanban-view.md`
369
+ - `mcp/docs/components/inbox-view.md`
370
+ - `mcp/docs/components/tree-view.md`
371
+ - `mcp/docs/how-to/data-views-from-backend-response.md` — recipe guide for consumers
372
+
373
+ Registered in `mcp/docs/llms-manifest.json` under `components.dataDisplay`. Update versions there when bumping.
374
+
375
+ ---
376
+
377
+ ## 16. Common change checklist
378
+
379
+ When updating UI on this feature, touch in this order:
380
+
381
+ 1. **Token swap** — never use `*-global-*` backgrounds. Check the table in §10.
382
+ 2. **Badge** — use `resolveBadgeVariant()` in the adapter, don't bypass it. If you need a new variant, add it to both `BadgeVariant` type (types.ts) and the switch in `badgeAdapter.ts`.
383
+ 3. **Field renderer** — add new field types in `fieldRenderers.tsx` + register in the `RENDERERS` lookup table at the bottom + extend `FieldType` in types.ts.
384
+ 4. **Layout change** — if it touches all four views, update each view's root container individually; the layout doesn't own view chrome.
385
+ 5. **State change** — extend `useDataViewsState` first, then thread the new field through `DataViewsLayout` props.
386
+ 6. **Docs** — update the relevant `.md` in `mcp/docs/components/` AND `mcp/docs/how-to/data-views-from-backend-response.md` if it changes the consumer-facing API.
387
+
388
+ ---
389
+
390
+ ## 17. File inventory (quick reference)
391
+
392
+ ```
393
+ apps/lib/components/DataViews/
394
+ ├── ARCHITECTURE.md ← this file
395
+ ├── DataViewsLayout.tsx ← the frame
396
+ ├── TableView.tsx
397
+ ├── KanbanView.tsx
398
+ ├── InboxView.tsx
399
+ ├── TreeView.tsx
400
+ ├── FilterPanel.tsx
401
+ ├── SettingsPanel.tsx
402
+ ├── fieldRenderers.tsx ← per-type JSX
403
+ ├── badgeAdapter.ts ← BadgeVariant → glare Badge props
404
+ ├── types.ts ← all shared types
405
+ ├── index.ts ← public barrel
406
+ ├── filters/
407
+ │ ├── DateRangePopover.tsx
408
+ │ ├── PresetChips.tsx
409
+ │ └── RangeSliderWithInputs.tsx
410
+ └── tree/
411
+ ├── TreeDrawer.tsx
412
+ ├── TreeNodeRow.tsx
413
+ └── TreeSidebar.tsx
414
+
415
+ apps/lib/utils/dataViews/
416
+ ├── pathUtils.ts
417
+ ├── fieldUtils.ts
418
+ ├── columnUtils.ts
419
+ ├── rangeUtils.ts
420
+ ├── treeUtils.ts
421
+ └── nestedDataUtils.tsx
422
+
423
+ apps/lib/hooks/
424
+ ├── useDataViewsState.ts ← shared state machine for composable mode
425
+ └── useIsMobile.ts ← <768px detection
426
+
427
+ apps/app/data-views/
428
+ └── page.tsx ← demo page, /data-views route
429
+
430
+ mcp/docs/components/
431
+ ├── data-views-layout.md
432
+ ├── table-view.md
433
+ ├── kanban-view.md
434
+ ├── inbox-view.md
435
+ └── tree-view.md
436
+
437
+ mcp/docs/how-to/
438
+ └── data-views-from-backend-response.md
439
+ ```