@nexub/mcp 6.2.0 → 6.3.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.
|
@@ -12,6 +12,8 @@ Feature-rich data table with sorting and row selection powered by TanStack Table
|
|
|
12
12
|
| --- | --- | --- | --- |
|
|
13
13
|
| `columns` (required) | `DataTableColumn<TData>[]` | | TanStack Table column definitions (`DataTableColumn` is exported from @nexub/react). Set `meta: { align: 'end' }` for numeric columns; headers, sort buttons and cells follow it. |
|
|
14
14
|
| `data` (required) | `TData[]` | | Array of row data objects to render. |
|
|
15
|
+
| `getSubRows` | `(row, index) => TData[] \| undefined` | | Nested rows (a tree table). The first column gets an expand toggle (`aria-expanded`) and indents each level; sorting sorts within each level. |
|
|
16
|
+
| `expanded / defaultExpanded / onExpandedChange` | `ExpandedState` | | Expanded rows by row id (see `getRowId`), or `true` for all. |
|
|
15
17
|
| `caption` | `ReactNode` | | Names the table for assistive tech (and its scroll region). Shown below the table; add `captionHidden` to keep it screen-reader only. |
|
|
16
18
|
| `enableSorting` | `boolean` | `false` | Click a header to sort; Shift+click adds more columns, numbered 1, 2… (5.3). |
|
|
17
19
|
| `enableRowSelection` | `boolean` | `false` | Turns on row selection state. |
|
|
@@ -242,6 +244,56 @@ export default function Example() {
|
|
|
242
244
|
}
|
|
243
245
|
```
|
|
244
246
|
|
|
247
|
+
## Example: Tree rows
|
|
248
|
+
|
|
249
|
+
`getSubRows` nests rows: the first column gets an expand toggle and indents each level. With pages, a parent and its children stay on one page.
|
|
250
|
+
|
|
251
|
+
```tsx
|
|
252
|
+
'use client';
|
|
253
|
+
|
|
254
|
+
import { DataTable, type DataTableColumn } from '@nexub/react';
|
|
255
|
+
|
|
256
|
+
type Account = { name: string; owner: string; arr: number; children?: Account[] };
|
|
257
|
+
|
|
258
|
+
const data: Account[] = [
|
|
259
|
+
{
|
|
260
|
+
name: 'Acme Group',
|
|
261
|
+
owner: 'Ada',
|
|
262
|
+
arr: 420000,
|
|
263
|
+
children: [
|
|
264
|
+
{ name: 'Acme EU', owner: 'Grace', arr: 180000, children: [{ name: 'Acme Berlin', owner: 'Grace', arr: 60000 }] },
|
|
265
|
+
{ name: 'Acme US', owner: 'Alan', arr: 240000 },
|
|
266
|
+
],
|
|
267
|
+
},
|
|
268
|
+
{ name: 'Globex', owner: 'Linus', arr: 95000 },
|
|
269
|
+
];
|
|
270
|
+
|
|
271
|
+
const columns: DataTableColumn<Account>[] = [
|
|
272
|
+
{ accessorKey: 'name', header: 'Account' },
|
|
273
|
+
{ accessorKey: 'owner', header: 'Owner' },
|
|
274
|
+
{
|
|
275
|
+
accessorKey: 'arr',
|
|
276
|
+
header: 'ARR',
|
|
277
|
+
meta: { align: 'end' },
|
|
278
|
+
cell: ({ getValue }) => new Intl.NumberFormat('en', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 }).format(getValue<number>()),
|
|
279
|
+
},
|
|
280
|
+
];
|
|
281
|
+
|
|
282
|
+
export default function Example() {
|
|
283
|
+
return (
|
|
284
|
+
<DataTable
|
|
285
|
+
caption="Accounts by region"
|
|
286
|
+
captionHidden
|
|
287
|
+
columns={columns}
|
|
288
|
+
data={data}
|
|
289
|
+
getSubRows={(row) => row.children}
|
|
290
|
+
getRowId={(row) => row.name}
|
|
291
|
+
defaultExpanded={{ 'Acme Group': true }}
|
|
292
|
+
/>
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
245
297
|
## Accessibility
|
|
246
298
|
|
|
247
299
|
- Roles: table (default), grid (with `grid`), columnheader with aria-sort when sortable
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Tree View
|
|
2
|
+
|
|
3
|
+
A keyboard-friendly hierarchy (ARIA tree) with lazy children and tri-state checkboxes.
|
|
4
|
+
|
|
5
|
+
- Package: `@nexub/react` · Category: Navigation · Status: beta
|
|
6
|
+
- Import: `import { TreeView } from '@nexub/react';`
|
|
7
|
+
- Docs: https://nexub-ds-docs.pages.dev/components/tree-view
|
|
8
|
+
|
|
9
|
+
## Props
|
|
10
|
+
|
|
11
|
+
| Prop | Type | Default | Description |
|
|
12
|
+
| --- | --- | --- | --- |
|
|
13
|
+
| `nodes` (required) | `TreeNode[]` | | `{ id, label, textValue?, icon?, children?, hasChildren?, disabled? }`. |
|
|
14
|
+
| `aria-label / aria-labelledby` (required) | `string` | | Names the tree. |
|
|
15
|
+
| `expanded / defaultExpanded / onExpandedChange` | `string[]` | | Open node ids. |
|
|
16
|
+
| `selected / defaultSelected / onSelectedChange` | `string \| null` | | Single selection, set by click, Enter or Space. |
|
|
17
|
+
| `checkable` | `boolean` | | Checkboxes instead of selection. A parent is checked when all its children are and mixed when some are. |
|
|
18
|
+
| `checked / defaultChecked / onCheckedChange` | `string[]` | | Every checked id, parents included. |
|
|
19
|
+
| `onLoadChildren` | `(node) => Promise` | | Called when a `hasChildren` node without `children` opens. Load them and pass the new `nodes`; the item is `aria-busy` meanwhile. |
|
|
20
|
+
|
|
21
|
+
## Example: Lazy loading and selection
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
'use client';
|
|
25
|
+
|
|
26
|
+
import * as React from 'react';
|
|
27
|
+
import { TreeView, type TreeNode } from '@nexub/react';
|
|
28
|
+
|
|
29
|
+
export default function Example() {
|
|
30
|
+
const [nodes, setNodes] = React.useState<TreeNode[]>([
|
|
31
|
+
{
|
|
32
|
+
id: 'eng',
|
|
33
|
+
label: 'Engineering',
|
|
34
|
+
children: [
|
|
35
|
+
{ id: 'web', label: 'Web', children: [{ id: 'ada', label: 'Ada Lovelace' }, { id: 'alan', label: 'Alan Turing' }] },
|
|
36
|
+
{ id: 'mobile', label: 'Mobile', hasChildren: true },
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
{ id: 'design', label: 'Design', children: [{ id: 'grace', label: 'Grace Hopper' }] },
|
|
40
|
+
]);
|
|
41
|
+
const [selected, setSelected] = React.useState<string | null>('ada');
|
|
42
|
+
|
|
43
|
+
// Pretend server call: fills Mobile's children the first time it opens.
|
|
44
|
+
const load = async (node: TreeNode) => {
|
|
45
|
+
await new Promise((r) => setTimeout(r, 700));
|
|
46
|
+
const fill = (list: TreeNode[]): TreeNode[] =>
|
|
47
|
+
list.map((n) =>
|
|
48
|
+
n.id === node.id
|
|
49
|
+
? { ...n, children: [{ id: 'linus', label: 'Linus Torvalds' }, { id: 'margaret', label: 'Margaret Hamilton' }] }
|
|
50
|
+
: { ...n, children: n.children && fill(n.children) },
|
|
51
|
+
);
|
|
52
|
+
setNodes(fill);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<div className="flex w-full max-w-xs flex-col gap-2">
|
|
57
|
+
<TreeView aria-label="Teams" nodes={nodes} defaultExpanded={['eng', 'web']} selected={selected} onSelectedChange={setSelected} onLoadChildren={load} />
|
|
58
|
+
<p className="text-body-sm text-[var(--color-on-surface-muted)]">Selected: {selected ?? 'none'}</p>
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Example: Checkboxes
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
'use client';
|
|
68
|
+
|
|
69
|
+
import * as React from 'react';
|
|
70
|
+
import { TreeView, type TreeNode } from '@nexub/react';
|
|
71
|
+
|
|
72
|
+
const nodes: TreeNode[] = [
|
|
73
|
+
{
|
|
74
|
+
id: 'reports',
|
|
75
|
+
label: 'Reports',
|
|
76
|
+
children: [
|
|
77
|
+
{ id: 'revenue', label: 'Revenue' },
|
|
78
|
+
{ id: 'churn', label: 'Churn' },
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
{ id: 'settings', label: 'Settings', children: [{ id: 'billing', label: 'Billing' }, { id: 'members', label: 'Members' }] },
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
export default function Example() {
|
|
85
|
+
const [checked, setChecked] = React.useState<string[]>(['revenue']);
|
|
86
|
+
return (
|
|
87
|
+
<div className="flex w-full max-w-xs flex-col gap-2">
|
|
88
|
+
<TreeView aria-label="Permissions" nodes={nodes} checkable defaultExpanded={['reports', 'settings']} checked={checked} onCheckedChange={setChecked} />
|
|
89
|
+
<p className="text-body-sm text-[var(--color-on-surface-muted)]">Granted: {checked.join(', ') || 'nothing'}</p>
|
|
90
|
+
</div>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Accessibility
|
|
96
|
+
|
|
97
|
+
- Roles: tree, treeitem with aria-level, aria-setsize, aria-posinset, aria-expanded, group
|
|
98
|
+
- `ArrowDown / ArrowUp`: Next or previous visible item.
|
|
99
|
+
- `ArrowRight`: Opens a closed item, or moves to its first child. Mirrored in RTL.
|
|
100
|
+
- `ArrowLeft`: Closes an open item, or moves to its parent. Mirrored in RTL.
|
|
101
|
+
- `Home / End`: First or last visible item.
|
|
102
|
+
- `Enter / Space`: Selects the item, or toggles its checkbox.
|
|
103
|
+
- `Type a letter`: Moves to the next item starting with the typed text.
|
|
104
|
+
- The tree is one tab stop (roving tabindex); it returns to the last focused or the selected item.
|
|
105
|
+
|
|
106
|
+
Related: [data-table](data-table.md), [sidebar](sidebar.md)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Component index
|
|
2
2
|
|
|
3
|
-
Nexub DS v6.
|
|
3
|
+
Nexub DS v6.3.0. Open `components/<slug>.md` for props, examples and accessibility notes.
|
|
4
4
|
Never use a component marked deprecated.
|
|
5
5
|
|
|
6
6
|
## Components — Actions
|
|
@@ -157,6 +157,7 @@ Never use a component marked deprecated.
|
|
|
157
157
|
- [Pagination](components/pagination.md) `@nexub/react`: Page navigation control with prev/next and page number buttons.
|
|
158
158
|
- [Saved Views](components/saved-views.md) `@nexub/react`: A menu to switch, save, update and delete saved filter views. Your app stores them.
|
|
159
159
|
- [Tabs](components/tabs.md) `@nexub/react`: Layered content panels switched by tab triggers. Built on Radix UI Tabs.
|
|
160
|
+
- [Tree View](components/tree-view.md) `@nexub/react`: A keyboard-friendly hierarchy (ARIA tree) with lazy children and tri-state checkboxes.
|
|
160
161
|
|
|
161
162
|
## Components — Overlays
|
|
162
163
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Tokens
|
|
2
2
|
|
|
3
|
-
Nexub DS v6.
|
|
3
|
+
Nexub DS v6.3.0. Every token is a CSS custom property from `@nexub/tokens/css` (loaded by `@nexub/themes/base`).
|
|
4
4
|
The Tailwind preset (`@nexub/tokens/tailwind`) maps them to utilities. Never hardcode a hex, px spacing or shadow that a token covers.
|
|
5
5
|
|
|
6
6
|
## Color roles
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexub/mcp",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.3.0",
|
|
4
4
|
"description": "MCP server for Nexub Design System: gives Claude, Cursor and any MCP client the components, patterns, tokens and design rules of the installed release.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|