torch-glare 2.1.3 → 2.1.5
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/DataViews/DataViewsLayout.tsx +9 -0
- package/apps/lib/components/DataViews/FilterPanel.tsx +4 -3
- package/apps/lib/components/DataViews/InboxView.tsx +15 -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-layout.md +2 -0
- package/docs/components/inbox-view.md +159 -0
- package/docs/components/kanban-view.md +125 -0
- package/docs/components/table-view.md +131 -0
- package/docs/components/tree-view.md +136 -0
- package/docs/how-to/data-views-from-backend-response.md +191 -0
- package/package.json +3 -2
- package/apps/lib/components/DataViews/ARCHITECTURE.md +0 -439
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
useMemo,
|
|
8
8
|
useRef,
|
|
9
9
|
useState,
|
|
10
|
+
type ElementType,
|
|
10
11
|
type ReactNode,
|
|
11
12
|
} from "react";
|
|
12
13
|
import { List, LayoutGrid, Inbox as InboxIcon, Network } from "lucide-react";
|
|
@@ -61,6 +62,12 @@ export type DataViewsLayoutProps = {
|
|
|
61
62
|
addNewLabel?: string;
|
|
62
63
|
|
|
63
64
|
inboxItemHref?: (item: DynamicRecord, id: any) => string;
|
|
65
|
+
/**
|
|
66
|
+
* Component used to render inbox item links when `inboxItemHref` is set.
|
|
67
|
+
* Defaults to a plain `<a>` (full-page navigation). Pass your router's link
|
|
68
|
+
* (e.g. Next.js `Link`, React Router `Link`) for client-side navigation.
|
|
69
|
+
*/
|
|
70
|
+
inboxLinkComponent?: ElementType;
|
|
64
71
|
inboxSelectedId?: any;
|
|
65
72
|
inboxRenderDetail?: (item: DynamicRecord | null) => ReactNode;
|
|
66
73
|
|
|
@@ -108,6 +115,7 @@ export const DataViewsLayout = forwardRef<HTMLDivElement, DataViewsLayoutProps>(
|
|
|
108
115
|
onAddNew,
|
|
109
116
|
addNewLabel,
|
|
110
117
|
inboxItemHref,
|
|
118
|
+
inboxLinkComponent,
|
|
111
119
|
inboxSelectedId,
|
|
112
120
|
inboxRenderDetail,
|
|
113
121
|
searchValue,
|
|
@@ -276,6 +284,7 @@ export const DataViewsLayout = forwardRef<HTMLDivElement, DataViewsLayoutProps>(
|
|
|
276
284
|
onFilterChange={setFilterState}
|
|
277
285
|
showFilters={false}
|
|
278
286
|
itemHref={inboxItemHref}
|
|
287
|
+
linkComponent={inboxLinkComponent}
|
|
279
288
|
selectedItemId={inboxSelectedId}
|
|
280
289
|
renderDetail={inboxRenderDetail}
|
|
281
290
|
/>
|
|
@@ -222,7 +222,8 @@ export function FilterPanel({
|
|
|
222
222
|
<Badge
|
|
223
223
|
{...countBadge}
|
|
224
224
|
label={String(totalFilters)}
|
|
225
|
-
|
|
225
|
+
showIcon={false}
|
|
226
|
+
className="h-5 w-5 min-w-0 justify-center rounded-full p-0 text-xs"
|
|
226
227
|
size="XS"
|
|
227
228
|
/>
|
|
228
229
|
)}
|
|
@@ -270,9 +271,9 @@ export function FilterPanel({
|
|
|
270
271
|
<Badge
|
|
271
272
|
{...countBadge}
|
|
272
273
|
label={String(totalFilters)}
|
|
273
|
-
|
|
274
|
+
showIcon={false}
|
|
275
|
+
className="h-5 w-5 min-w-0 justify-center rounded-full p-0 text-xs"
|
|
274
276
|
size="XS"
|
|
275
|
-
|
|
276
277
|
/>
|
|
277
278
|
)}
|
|
278
279
|
</div>
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
useEffect,
|
|
5
|
+
useMemo,
|
|
6
|
+
useState,
|
|
7
|
+
type ElementType,
|
|
8
|
+
type ReactNode,
|
|
9
|
+
} from "react";
|
|
4
10
|
import { Badge } from "../Badge";
|
|
5
11
|
import { FilterPanel } from "./FilterPanel";
|
|
6
12
|
import {
|
|
@@ -57,6 +63,12 @@ export type InboxViewProps = {
|
|
|
57
63
|
onFilterChange?: (filters: FilterState) => void;
|
|
58
64
|
showFilters?: boolean;
|
|
59
65
|
itemHref?: (item: DynamicRecord, id: any) => string;
|
|
66
|
+
/**
|
|
67
|
+
* Component used to render each item's link when `itemHref` is set. Defaults
|
|
68
|
+
* to a plain `<a>` (full-page navigation). Pass your router's link
|
|
69
|
+
* (e.g. Next.js `Link`, React Router `Link`) for client-side navigation.
|
|
70
|
+
*/
|
|
71
|
+
linkComponent?: ElementType;
|
|
60
72
|
selectedItemId?: any;
|
|
61
73
|
renderDetail?: (item: DynamicRecord | null) => ReactNode;
|
|
62
74
|
};
|
|
@@ -100,6 +112,7 @@ export function InboxView({
|
|
|
100
112
|
onFilterChange,
|
|
101
113
|
showFilters = true,
|
|
102
114
|
itemHref,
|
|
115
|
+
linkComponent,
|
|
103
116
|
selectedItemId,
|
|
104
117
|
renderDetail,
|
|
105
118
|
}: InboxViewProps) {
|
|
@@ -350,6 +363,7 @@ export function InboxView({
|
|
|
350
363
|
selected={selected}
|
|
351
364
|
onSelect={() => handleSelectItem(item)}
|
|
352
365
|
href={itemHref?.(item, itemId)}
|
|
366
|
+
linkComponent={linkComponent}
|
|
353
367
|
/>
|
|
354
368
|
);
|
|
355
369
|
})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getDependenciesAndInstallNestedComponents.d.ts","sourceRoot":"","sources":["../../../cli/src/shared/getDependenciesAndInstallNestedComponents.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getDependenciesAndInstallNestedComponents.d.ts","sourceRoot":"","sources":["../../../cli/src/shared/getDependenciesAndInstallNestedComponents.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,yCAAyC,CACrD,aAAa,EAAE,MAAM,EACrB,qBAAqB,EAAE,GAAG,CAAC,MAAM,CAAC,GACnC,GAAG,CAAC,MAAM,CAAC,CAsEb"}
|
|
@@ -2,6 +2,7 @@ import * as fs from "fs";
|
|
|
2
2
|
import * as path from "path";
|
|
3
3
|
import { addUtil } from "../commands/utils.js";
|
|
4
4
|
import { addHook } from "../commands/hook.js";
|
|
5
|
+
import { addLayout } from "../commands/layout.js";
|
|
5
6
|
import { add } from "../commands/add.js";
|
|
6
7
|
/**
|
|
7
8
|
* Walk a copied component file's imports and (a) collect 3rd-party deps to
|
|
@@ -65,6 +66,13 @@ export function getDependenciesAndInstallNestedComponents(componentPath, install
|
|
|
65
66
|
addHook(`${hookEntry}.ts`);
|
|
66
67
|
}
|
|
67
68
|
}
|
|
69
|
+
else if (head === "layouts") {
|
|
70
|
+
// layouts/DataViewCard → copy from apps/lib/layouts (NOT components)
|
|
71
|
+
const layoutEntry = rest[1];
|
|
72
|
+
if (layoutEntry) {
|
|
73
|
+
addLayout(layoutEntry);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
68
76
|
else if (head === "components") {
|
|
69
77
|
const compEntry = rest[1];
|
|
70
78
|
if (compEntry) {
|
|
@@ -126,7 +134,7 @@ function routeByLocation(absPath) {
|
|
|
126
134
|
addUtil(entry);
|
|
127
135
|
break;
|
|
128
136
|
case "layouts":
|
|
129
|
-
|
|
137
|
+
addLayout(stripExt(entry));
|
|
130
138
|
break;
|
|
131
139
|
}
|
|
132
140
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getDependenciesAndInstallNestedComponents.js","sourceRoot":"","sources":["../../../cli/src/shared/getDependenciesAndInstallNestedComponents.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"getDependenciesAndInstallNestedComponents.js","sourceRoot":"","sources":["../../../cli/src/shared/getDependenciesAndInstallNestedComponents.ts"],"names":[],"mappings":"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"}
|
|
@@ -140,6 +140,8 @@ Inbox auto-detects `isRead`, `isStarred`, `hasAttachment`, `priority`. Override
|
|
|
140
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
141
|
| `kanbanGroupBy` | `string` | `"status"` | Dot-path to the field used for Kanban columns. |
|
|
142
142
|
| `inboxConfig` | `InboxConfig` | auto-detected | Map of starred/read/attachment/priority field paths for Inbox. |
|
|
143
|
+
| `inboxItemHref` | `(item, id) => string` | — | When set, each Inbox row becomes a link to the returned href. |
|
|
144
|
+
| `inboxLinkComponent` | `ElementType` | `"a"` | Component used to render Inbox item links when `inboxItemHref` is set. Pass your router's link (Next.js `Link`, React Router `Link`) for client-side navigation; defaults to a plain `<a>` (full-page nav). |
|
|
143
145
|
| `treeConfig` | `TreeConfig` | auto-detected | `childrenField`, `parentField`, `idField`, `nodeLabel`, `defaultExpanded`. |
|
|
144
146
|
| `filterState` | `FilterState` | uncontrolled | Controlled filter state. Pair with `onFilterChange`. |
|
|
145
147
|
| `onFilterChange` | `(state: FilterState) => void` | — | Fires when any filter changes. When provided, the layout is controlled. |
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: InboxView
|
|
3
|
+
description: Standalone inbox/list view for DataViews — a master list with read/starred/priority states and an optional detail pane. Use inside DataViewsLayout (tab mode) or directly in Composable Mode.
|
|
4
|
+
group: Data Display
|
|
5
|
+
keywords: [data-views, inbox-view, inbox, list, master-detail, read, starred, priority, attachment, composable, dynamic-data]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# InboxView
|
|
9
|
+
|
|
10
|
+
> The inbox renderer behind `DataViewsLayout`'s "Inbox" tab. It renders records as a scannable list with read / starred / priority / attachment affordances, plus an optional detail pane. In tab mode the layout renders it for you; render it directly only in **Composable Mode**.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
Part of `torch-glare`. Ships with the `DataViews` folder when you run `npx torch-glare add DataViews` — no separate install. It depends on the shared `Badge`, `Button`, `Avatar`, `Card`, `Divider`, and `TabFormItem` components plus `lucide-react`.
|
|
15
|
+
|
|
16
|
+
## Import
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
import { InboxView, useDataViewsState } from "torch-glare"
|
|
20
|
+
import type { InboxViewProps, InboxConfig, FieldConfig } from "torch-glare"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## When to use it directly
|
|
24
|
+
|
|
25
|
+
| Situation | Use |
|
|
26
|
+
|---|---|
|
|
27
|
+
| You want the standard tabbed multi-view UI | `DataViewsLayout` with `views={{ inbox: true }}` — it mounts `InboxView` for you. |
|
|
28
|
+
| You want a custom master-detail layout | Render `InboxView` directly with state from `useDataViewsState`, and supply `renderDetail`. |
|
|
29
|
+
|
|
30
|
+
## Field auto-detection
|
|
31
|
+
|
|
32
|
+
InboxView auto-detects these record fields and maps them to UI affordances.
|
|
33
|
+
Override any of them with `inboxConfig`.
|
|
34
|
+
|
|
35
|
+
| Detected field | Affordance |
|
|
36
|
+
|---|---|
|
|
37
|
+
| `isRead` | Read/unread weight |
|
|
38
|
+
| `isStarred` | Star toggle |
|
|
39
|
+
| `hasAttachment` | Paperclip icon |
|
|
40
|
+
| `priority` | Priority flag |
|
|
41
|
+
|
|
42
|
+
## Composable Mode example
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
import { InboxView, useDataViewsState } from "torch-glare"
|
|
46
|
+
import type { FieldConfig, InboxConfig } from "torch-glare"
|
|
47
|
+
|
|
48
|
+
const messages = [
|
|
49
|
+
{ id: 1, subject: "Welcome", from: { name: "Ada" }, isRead: false, isStarred: true, sentAt: "2024-06-01" },
|
|
50
|
+
{ id: 2, subject: "Invoice", from: { name: "Billing" }, isRead: true, hasAttachment: true, sentAt: "2024-06-02" },
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
const fields: FieldConfig[] = [
|
|
54
|
+
{ path: "subject", type: "text" },
|
|
55
|
+
{ path: "from.name", label: "From", type: "text" },
|
|
56
|
+
{ path: "sentAt", type: "date-format", dateFormat: "YYYY-MM-DD" },
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
const inboxConfig: InboxConfig = {
|
|
60
|
+
titlePath: "subject",
|
|
61
|
+
previewPath: "from.name",
|
|
62
|
+
dateField: "sentAt",
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function Mailbox() {
|
|
66
|
+
const state = useDataViewsState({ data: messages, fields })
|
|
67
|
+
const [selectedId, setSelectedId] = useState<number | null>(null)
|
|
68
|
+
return (
|
|
69
|
+
<InboxView
|
|
70
|
+
data={state.flatItems}
|
|
71
|
+
fields={state.resolvedFields}
|
|
72
|
+
config={state.config}
|
|
73
|
+
inboxConfig={inboxConfig}
|
|
74
|
+
selectedItemId={selectedId}
|
|
75
|
+
renderDetail={(item) =>
|
|
76
|
+
item ? <MessageDetail message={item} /> : <Empty />
|
|
77
|
+
}
|
|
78
|
+
/>
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Link rows to routes (framework-agnostic)
|
|
84
|
+
|
|
85
|
+
`itemHref` turns each row into a link. By default the card renders a plain `<a>`
|
|
86
|
+
(full-page navigation), so it works in any framework. For client-side routing,
|
|
87
|
+
pass your router's link via `linkComponent` — this is what makes navigation
|
|
88
|
+
behave consistently across environments. Without it you get a normal `<a>`.
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
// Next.js
|
|
92
|
+
import Link from "next/link"
|
|
93
|
+
|
|
94
|
+
<InboxView
|
|
95
|
+
data={state.flatItems}
|
|
96
|
+
fields={state.resolvedFields}
|
|
97
|
+
config={state.config}
|
|
98
|
+
itemHref={(item, id) => `/messages/${id}`}
|
|
99
|
+
linkComponent={Link} // React Router users pass their <Link> the same way
|
|
100
|
+
/>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
> Via `DataViewsLayout` (tab mode) the same prop is named `inboxLinkComponent`.
|
|
104
|
+
|
|
105
|
+
## API Reference
|
|
106
|
+
|
|
107
|
+
### `InboxViewProps`
|
|
108
|
+
|
|
109
|
+
| Prop | Type | Default | Description |
|
|
110
|
+
|---|---|---|---|
|
|
111
|
+
| `data` | `DynamicRecord[]` | — (required) | Records to render as list items. Pass `state.flatItems`. |
|
|
112
|
+
| `fields` | `FieldConfig[]` | — (required) | Field map controlling list-item content. Pass `state.resolvedFields`. |
|
|
113
|
+
| `config` | `ViewConfig` | — (required) | View config from `useDataViewsState`. |
|
|
114
|
+
| `inboxConfig` | `InboxConfig` | auto-detected | Overrides for which record paths map to title/preview/avatar/date/read/starred/attachment/priority. |
|
|
115
|
+
| `columns` | `DynamicColumnConfig[]` | `undefined` | Explicit column overrides. Usually derived from `fields`. |
|
|
116
|
+
| `onDataUpdate` | `(data: DynamicRecord[]) => void` | `undefined` | Called when item data changes (e.g. toggling read/starred). |
|
|
117
|
+
| `filters` | `DynamicFilterConfig[]` | `undefined` | Explicit filter definitions. Usually inferred from `filterable` fields. |
|
|
118
|
+
| `filterState` | `FilterState` | uncontrolled | Controlled filter state. Pair with `onFilterChange`. |
|
|
119
|
+
| `onFilterChange` | `(filters: FilterState) => void` | `undefined` | Fires when a filter changes. |
|
|
120
|
+
| `showFilters` | `boolean` | `true` | Show the integrated filter panel. |
|
|
121
|
+
| `itemHref` | `(item: DynamicRecord, id: any) => string` | `undefined` | When set, each row becomes a link to the returned href. |
|
|
122
|
+
| `linkComponent` | `ElementType` | `"a"` | Component used to render each item's link when `itemHref` is set. Pass your router's link (Next.js `Link`, React Router `Link`) for client-side navigation. Defaults to a plain `<a>` (full-page nav). |
|
|
123
|
+
| `selectedItemId` | `any` | `undefined` | Id of the currently selected row (drives the detail pane + highlight). |
|
|
124
|
+
| `renderDetail` | `(item: DynamicRecord \| null) => ReactNode` | `undefined` | Renders the right-hand detail pane for the selected item. |
|
|
125
|
+
|
|
126
|
+
### `InboxConfig`
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
type InboxConfig = {
|
|
130
|
+
starredField?: string
|
|
131
|
+
readField?: string
|
|
132
|
+
attachmentField?: string
|
|
133
|
+
priorityField?: string
|
|
134
|
+
titlePath?: string
|
|
135
|
+
previewPath?: string
|
|
136
|
+
avatarPath?: string
|
|
137
|
+
dateField?: string
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
See [`DataViewsLayout`](./data-views-layout.md#fieldconfig) for `FieldConfig`,
|
|
142
|
+
`FilterState`, and related shapes.
|
|
143
|
+
|
|
144
|
+
## Accessibility
|
|
145
|
+
|
|
146
|
+
- The all/starred/priority switcher uses [`TabFormItem`](./tab-form-item.md) (full keyboard support).
|
|
147
|
+
- Star/archive/delete actions are real `<button>`s with accessible labels.
|
|
148
|
+
- Avatars fall back to initials via [`Avatar`](./avatar.md).
|
|
149
|
+
|
|
150
|
+
## Theming
|
|
151
|
+
|
|
152
|
+
Uses only `*-presentation-*` design tokens. Control the scheme via the parent
|
|
153
|
+
`DataViewsLayout`'s `theme`.
|
|
154
|
+
|
|
155
|
+
## Related
|
|
156
|
+
|
|
157
|
+
- [`DataViewsLayout`](./data-views-layout.md) — the tabbed container that renders this for you
|
|
158
|
+
- [`TableView`](./table-view.md) · [`KanbanView`](./kanban-view.md) · [`TreeView`](./tree-view.md) — sibling views
|
|
159
|
+
- [How-to: Render a backend response with DataViews](../how-to/data-views-from-backend-response.md)
|
|
@@ -0,0 +1,125 @@
|
|
|
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
|
+
Part of `torch-glare`. Ships with the `DataViews` folder when you run `npx torch-glare add DataViews` — no separate install. It depends on the shared `Button` component, the `DataViewCard` layout, and `lucide-react`.
|
|
15
|
+
|
|
16
|
+
## Import
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
import { KanbanView, useDataViewsState } from "torch-glare"
|
|
20
|
+
import type { KanbanViewProps, FieldConfig } from "torch-glare"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## When to use it directly
|
|
24
|
+
|
|
25
|
+
| Situation | Use |
|
|
26
|
+
|---|---|
|
|
27
|
+
| You want the standard tabbed multi-view UI | `DataViewsLayout` with `views={{ kanban: true }}` — it mounts `KanbanView` for you. |
|
|
28
|
+
| You want a custom layout (e.g. kanban beside a table) | Render `KanbanView` directly with state from `useDataViewsState`. |
|
|
29
|
+
|
|
30
|
+
## Composable Mode example
|
|
31
|
+
|
|
32
|
+
`KanbanView` groups by the `groupByField` path — every distinct value becomes a
|
|
33
|
+
column. Column colors are assigned deterministically, or per-value via the
|
|
34
|
+
field's `kanbanVariants`.
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { KanbanView, useDataViewsState } from "torch-glare"
|
|
38
|
+
import type { FieldConfig } from "torch-glare"
|
|
39
|
+
|
|
40
|
+
const tasks = [
|
|
41
|
+
{ id: 1, title: "Spec API", status: "Todo", assignee: "Ada" },
|
|
42
|
+
{ id: 2, title: "Build UI", status: "In Progress", assignee: "Linus" },
|
|
43
|
+
{ id: 3, title: "Ship", status: "Done", assignee: "Grace" },
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
const fields: FieldConfig[] = [
|
|
47
|
+
{ path: "title", type: "text" },
|
|
48
|
+
{
|
|
49
|
+
path: "status",
|
|
50
|
+
type: "enum-badge",
|
|
51
|
+
kanbanVariants: {
|
|
52
|
+
Todo: { label: "To Do", color: "gray" },
|
|
53
|
+
"In Progress": { label: "In Progress", color: "blue" },
|
|
54
|
+
Done: { label: "Done", color: "green" },
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
{ path: "assignee", type: "text" },
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
function TaskBoard() {
|
|
61
|
+
const state = useDataViewsState({ data: tasks, fields })
|
|
62
|
+
return (
|
|
63
|
+
<KanbanView
|
|
64
|
+
data={state.flatItems}
|
|
65
|
+
fields={state.resolvedFields}
|
|
66
|
+
config={state.config}
|
|
67
|
+
groupByField="status"
|
|
68
|
+
titleField="title"
|
|
69
|
+
/>
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Column header actions
|
|
75
|
+
|
|
76
|
+
Pass `onColumnAction` to show an overflow (⋯) button on each column header. When
|
|
77
|
+
omitted the button is hidden.
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
<KanbanView
|
|
81
|
+
data={state.flatItems}
|
|
82
|
+
fields={state.resolvedFields}
|
|
83
|
+
config={state.config}
|
|
84
|
+
groupByField="status"
|
|
85
|
+
onColumnAction={(columnId) => openColumnMenu(columnId)}
|
|
86
|
+
/>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## API Reference
|
|
90
|
+
|
|
91
|
+
### `KanbanViewProps`
|
|
92
|
+
|
|
93
|
+
| Prop | Type | Default | Description |
|
|
94
|
+
|---|---|---|---|
|
|
95
|
+
| `data` | `DynamicRecord[]` | — (required) | Records to group into columns. Pass `state.flatItems` in composable mode. |
|
|
96
|
+
| `fields` | `FieldConfig[]` | — (required) | Field map controlling card content. Pass `state.resolvedFields`. |
|
|
97
|
+
| `config` | `ViewConfig` | — (required) | View config from `useDataViewsState`. |
|
|
98
|
+
| `groupByField` | `string` | `"status"` | Dot-path to the field whose distinct values become columns. |
|
|
99
|
+
| `titleField` | `string` | first visible non-group field | Dot-path of the field rendered as the card title. |
|
|
100
|
+
| `columns` | `DynamicColumnConfig[]` | `undefined` | Explicit column overrides. Usually derived from `fields`. |
|
|
101
|
+
| `onDataUpdate` | `(data: DynamicRecord[]) => void` | `undefined` | Called when a card moves between columns (updates the group-by value). |
|
|
102
|
+
| `onColumnAction` | `(columnId: string) => void` | `undefined` | Click handler for the column header overflow button. When omitted, the button is hidden. |
|
|
103
|
+
|
|
104
|
+
Per-column colors come from each field's `kanbanVariants` map
|
|
105
|
+
(`{ [value]: { label?, color? } }`). Available `color` keys: `gray`, `purple`,
|
|
106
|
+
`orange`, `blue`, `green`, `red`. See
|
|
107
|
+
[`DataViewsLayout`](./data-views-layout.md#fieldconfig) for the full
|
|
108
|
+
`FieldConfig` shape.
|
|
109
|
+
|
|
110
|
+
## Accessibility
|
|
111
|
+
|
|
112
|
+
- Cards are keyboard-focusable; the column overflow button is a real `<button>`.
|
|
113
|
+
- Card titles use semantic heading markup within each [`DataViewCard`](./card.md).
|
|
114
|
+
|
|
115
|
+
## Theming
|
|
116
|
+
|
|
117
|
+
Uses `*-presentation-*` tokens plus a small set of deeply-saturated column-header
|
|
118
|
+
fills matched to `glare-torch-mode` raw tokens. Control the scheme via the
|
|
119
|
+
parent `DataViewsLayout`'s `theme`.
|
|
120
|
+
|
|
121
|
+
## Related
|
|
122
|
+
|
|
123
|
+
- [`DataViewsLayout`](./data-views-layout.md) — the tabbed container that renders this for you
|
|
124
|
+
- [`TableView`](./table-view.md) · [`InboxView`](./inbox-view.md) · [`TreeView`](./tree-view.md) — sibling views
|
|
125
|
+
- [How-to: Render a backend response with DataViews](../how-to/data-views-from-backend-response.md)
|
|
@@ -0,0 +1,131 @@
|
|
|
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
|
+
Part of `torch-glare`. Ships with the `DataViews` folder when you run `npx torch-glare add DataViews` — no separate install. It depends on the shared `Card`, `Checkbox`, and `Table` components plus the colocated `FilterPanel`.
|
|
15
|
+
|
|
16
|
+
## Import
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
import { TableView, useDataViewsState } from "torch-glare"
|
|
20
|
+
import type { TableViewProps, FieldConfig } from "torch-glare"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## When to use it directly
|
|
24
|
+
|
|
25
|
+
| Situation | Use |
|
|
26
|
+
|---|---|
|
|
27
|
+
| You want the standard tabbed multi-view UI | `DataViewsLayout` — it mounts `TableView` for you. Don't render this yourself. |
|
|
28
|
+
| You want a custom layout (e.g. table beside a kanban) | Render `TableView` directly with state from `useDataViewsState`. |
|
|
29
|
+
| You only ever need a table and nothing else | Render `TableView` directly, or just use the simpler [`Table`](./table.md) / [`DataTable`](./data-table.md). |
|
|
30
|
+
|
|
31
|
+
## Composable Mode example
|
|
32
|
+
|
|
33
|
+
`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.
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
import { TableView, useDataViewsState } from "torch-glare"
|
|
37
|
+
import type { FieldConfig } from "torch-glare"
|
|
38
|
+
|
|
39
|
+
const employees = [
|
|
40
|
+
{ id: 1, name: "Ada Lovelace", role: "Engineer", salary: 120000, joinDate: "2024-04-12" },
|
|
41
|
+
{ id: 2, name: "Linus Torvalds", role: "Engineer", salary: 145000, joinDate: "2023-09-01" },
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
const fields: FieldConfig[] = [
|
|
45
|
+
{ path: "name", label: "Name", type: "text" },
|
|
46
|
+
{ path: "role", type: "text", filterable: true },
|
|
47
|
+
{ path: "salary", type: "currency", currency: "USD" },
|
|
48
|
+
{ path: "joinDate", type: "date-format", dateFormat: "YYYY-MM-DD" },
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
function EmployeesTable() {
|
|
52
|
+
const state = useDataViewsState({ data: employees, fields })
|
|
53
|
+
return (
|
|
54
|
+
<TableView
|
|
55
|
+
data={state.flatItems}
|
|
56
|
+
fields={state.resolvedFields}
|
|
57
|
+
config={state.config}
|
|
58
|
+
onSortChange={(sortBy, sortOrder) =>
|
|
59
|
+
state.setConfig({ ...state.config, sortBy, sortOrder })
|
|
60
|
+
}
|
|
61
|
+
filterState={state.filterState}
|
|
62
|
+
onFilterChange={state.setFilterState}
|
|
63
|
+
/>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Hide the inline filter panel
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
<TableView
|
|
72
|
+
data={state.flatItems}
|
|
73
|
+
fields={state.resolvedFields}
|
|
74
|
+
config={state.config}
|
|
75
|
+
showFilters={false}
|
|
76
|
+
/>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Controlled sorting
|
|
80
|
+
|
|
81
|
+
`TableView` does not sort internally — it calls `onSortChange` and reads the
|
|
82
|
+
active sort from `config.sortBy` / `config.sortOrder`. Wire it to your config
|
|
83
|
+
state (or your backend) to make headers interactive.
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
<TableView
|
|
87
|
+
data={rows}
|
|
88
|
+
fields={fields}
|
|
89
|
+
config={{ defaultView: "table", sortBy: "name", sortOrder: "asc" }}
|
|
90
|
+
onSortChange={(sortBy, sortOrder) => refetch({ sortBy, sortOrder })}
|
|
91
|
+
/>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## API Reference
|
|
95
|
+
|
|
96
|
+
### `TableViewProps`
|
|
97
|
+
|
|
98
|
+
| Prop | Type | Default | Description |
|
|
99
|
+
|---|---|---|---|
|
|
100
|
+
| `data` | `DynamicRecord[]` | — (required) | Flat array of rows to render. In composable mode pass `state.flatItems`. |
|
|
101
|
+
| `fields` | `FieldConfig[]` | — (required) | Field map controlling which columns render and how cells format. Pass `state.resolvedFields` for auto-detected fields. |
|
|
102
|
+
| `config` | `ViewConfig` | — (required) | View config. `sortBy` / `sortOrder` drive the active sort indicator. |
|
|
103
|
+
| `columns` | `DynamicColumnConfig[]` | `undefined` | Explicit column overrides (visibility/order). Usually derived from `fields`. |
|
|
104
|
+
| `onDataUpdate` | `(data: DynamicRecord[]) => void` | `undefined` | Called when row data changes (e.g. inline selection). |
|
|
105
|
+
| `onSortChange` | `(sortBy: string, sortOrder: "asc" \| "desc") => void` | `undefined` | Fires on header click. When omitted, headers are not sortable. |
|
|
106
|
+
| `filters` | `DynamicFilterConfig[]` | `undefined` | Explicit filter definitions. Usually inferred from `filterable` fields. |
|
|
107
|
+
| `filterState` | `FilterState` | uncontrolled | Controlled filter state. Pair with `onFilterChange`. |
|
|
108
|
+
| `onFilterChange` | `(filters: FilterState) => void` | `undefined` | Fires when a filter changes. When provided, the view is controlled. |
|
|
109
|
+
| `showFilters` | `boolean` | `true` | Show the integrated filter panel. |
|
|
110
|
+
|
|
111
|
+
`DynamicColumnConfig`, `DynamicFilterConfig`, `FilterState`, and `FieldConfig`
|
|
112
|
+
share the same shapes documented in
|
|
113
|
+
[`DataViewsLayout`](./data-views-layout.md#api-reference).
|
|
114
|
+
|
|
115
|
+
## Accessibility
|
|
116
|
+
|
|
117
|
+
- Built on the accessible [`Table`](./table.md) primitive (semantic `<table>` markup, sortable headers).
|
|
118
|
+
- Row selection uses `TableCheckbox` with proper labelling.
|
|
119
|
+
- Filter checkboxes carry labels and `htmlFor` linkage.
|
|
120
|
+
|
|
121
|
+
## Theming
|
|
122
|
+
|
|
123
|
+
Uses only `*-presentation-*` design tokens. Wrap with `ThemeProvider` or pass a
|
|
124
|
+
`theme` to the parent `DataViewsLayout` to control the color scheme.
|
|
125
|
+
|
|
126
|
+
## Related
|
|
127
|
+
|
|
128
|
+
- [`DataViewsLayout`](./data-views-layout.md) — the tabbed multi-view container that renders this for you
|
|
129
|
+
- [`KanbanView`](./kanban-view.md) · [`InboxView`](./inbox-view.md) · [`TreeView`](./tree-view.md) — the sibling views
|
|
130
|
+
- [`Table`](./table.md) / [`DataTable`](./data-table.md) — lower-level table components
|
|
131
|
+
- [How-to: Render a backend response with DataViews](../how-to/data-views-from-backend-response.md)
|