@dashforge/tw 0.8.0-beta → 0.8.1-beta
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/CHANGELOG.md +62 -0
- package/dist/index.esm.js +83 -118
- package/dist/src/components/DataGrid/DataGrid.d.ts.map +1 -1
- package/dist/src/components/DataGrid/visibility/ColumnVisibilityMenu.d.ts +40 -0
- package/dist/src/components/DataGrid/visibility/ColumnVisibilityMenu.d.ts.map +1 -0
- package/dist/src/components/Table/Table.d.ts.map +1 -1
- package/dist/src/components/Table/table.types.d.ts +1 -3
- package/dist/src/components/Table/table.types.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/components/DataGrid/DataGrid.test.tsx +13 -17
- package/src/components/DataGrid/DataGrid.tsx +3 -8
- package/src/components/DataGrid/visibility/ColumnVisibilityMenu.tsx +169 -0
- package/src/components/Table/Table.tsx +1 -4
- package/src/components/Table/table.types.ts +1 -3
- package/dist/src/components/DataGrid/visibility/ColumnVisibilityDialog.d.ts +0 -33
- package/dist/src/components/DataGrid/visibility/ColumnVisibilityDialog.d.ts.map +0 -1
- package/src/components/DataGrid/visibility/ColumnVisibilityDialog.tsx +0 -200
package/CHANGELOG.md
CHANGED
|
@@ -12,6 +12,68 @@ This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
12
12
|
> duplicated intentionally — no shared "lowest common denominator" headless
|
|
13
13
|
> layer.
|
|
14
14
|
|
|
15
|
+
## [0.8.1-beta] — 2026-05-19
|
|
16
|
+
|
|
17
|
+
**UX swap on `DataGrid` column visibility.** The "Columns" toolbar
|
|
18
|
+
button now opens a lightweight **`<Popover>` menu** anchored to the
|
|
19
|
+
button instead of a modal `<Dialog>`. Toggles **auto-commit on
|
|
20
|
+
click** — no draft state, no "Done" button, dismissed via
|
|
21
|
+
outside-click / Esc. Matches the AG-Grid / MUI DataGrid v6 / TanStack
|
|
22
|
+
pattern for the same affordance.
|
|
23
|
+
|
|
24
|
+
Rationale: the previous Dialog was too heavyweight for a settings
|
|
25
|
+
toggle. A modal interrupts the user's interaction with the grid
|
|
26
|
+
(the very thing they're configuring), traps focus, and requires an
|
|
27
|
+
explicit commit step. The Popover variant reads as a "settings
|
|
28
|
+
panel": the user can keep referring to the grid while picking
|
|
29
|
+
columns, and changes flow into the model immediately.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- **`ColumnVisibilityTrigger`** (internal component used by
|
|
34
|
+
`<DataGrid enableColumnVisibility>`) — switched from `<Dialog>` to
|
|
35
|
+
`<Popover>`. Public DataGrid API surface unchanged: the
|
|
36
|
+
`enableColumnVisibility` flag, `hiddenColumns` /
|
|
37
|
+
`onHiddenColumnsChange` controllable state, and per-column
|
|
38
|
+
`hideable` / `defaultHidden` axes work identically.
|
|
39
|
+
|
|
40
|
+
- **`TableLabels`** — two now-unused keys removed:
|
|
41
|
+
- `columnsDescription` (the Dialog had a description line; the
|
|
42
|
+
Popover doesn't need one)
|
|
43
|
+
- `columnsDone` (no explicit commit step anymore — toggles
|
|
44
|
+
auto-commit)
|
|
45
|
+
The remaining four keys (`columnsButton`, `columnsTitle`,
|
|
46
|
+
`columnsShowAll`, `columnsHideAll`) are unchanged. Default for
|
|
47
|
+
`columnsTitle` adjusted from `"Manage columns"` to
|
|
48
|
+
`"Toggle columns"` (the action is now lighter).
|
|
49
|
+
|
|
50
|
+
### Migration
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pnpm up @dashforge/tw@^0.8.1-beta
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
If you customized the column-visibility labels via the `labels`
|
|
57
|
+
prop, drop the two removed keys:
|
|
58
|
+
|
|
59
|
+
```diff
|
|
60
|
+
<DataGrid
|
|
61
|
+
rows={rows}
|
|
62
|
+
cols={cols}
|
|
63
|
+
labels={{
|
|
64
|
+
columnsButton: 'Colonne',
|
|
65
|
+
columnsTitle: 'Mostra colonne',
|
|
66
|
+
- columnsDescription: 'Mostra o nascondi colonne…',
|
|
67
|
+
columnsShowAll: 'Mostra tutte',
|
|
68
|
+
columnsHideAll: 'Nascondi tutte',
|
|
69
|
+
- columnsDone: 'Fatto',
|
|
70
|
+
}}
|
|
71
|
+
/>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
If you don't customize the labels (>99% of consumers), no action
|
|
75
|
+
required — the visual swap happens automatically.
|
|
76
|
+
|
|
15
77
|
## [0.8.0-beta] — 2026-05-19
|
|
16
78
|
|
|
17
79
|
**Sprint 4.2-bis — DataGrid v1-bis.** Ships the five power-user
|
package/dist/index.esm.js
CHANGED
|
@@ -8675,11 +8675,9 @@ const DEFAULT_LABELS$1 = {
|
|
|
8675
8675
|
densityComfortable: 'Comfortable',
|
|
8676
8676
|
densitySpacious: 'Spacious',
|
|
8677
8677
|
columnsButton: 'Columns',
|
|
8678
|
-
columnsTitle: '
|
|
8679
|
-
columnsDescription: 'Show or hide columns. Required columns cannot be toggled.',
|
|
8678
|
+
columnsTitle: 'Toggle columns',
|
|
8680
8679
|
columnsShowAll: 'Show all',
|
|
8681
|
-
columnsHideAll: 'Hide all'
|
|
8682
|
-
columnsDone: 'Done'
|
|
8680
|
+
columnsHideAll: 'Hide all'
|
|
8683
8681
|
};
|
|
8684
8682
|
const DEFAULT_GET_ROW_ID = (_row, index)=>String(index);
|
|
8685
8683
|
/**
|
|
@@ -10216,11 +10214,9 @@ function FilterIcon() {
|
|
|
10216
10214
|
|
|
10217
10215
|
const DEFAULT_VISIBILITY_LABELS = {
|
|
10218
10216
|
columnsButton: 'Columns',
|
|
10219
|
-
columnsTitle: '
|
|
10220
|
-
columnsDescription: 'Show or hide columns. Required columns cannot be toggled.',
|
|
10217
|
+
columnsTitle: 'Toggle columns',
|
|
10221
10218
|
columnsShowAll: 'Show all',
|
|
10222
|
-
columnsHideAll: 'Hide all'
|
|
10223
|
-
columnsDone: 'Done'
|
|
10219
|
+
columnsHideAll: 'Hide all'
|
|
10224
10220
|
};
|
|
10225
10221
|
function ColumnVisibilityTrigger(props) {
|
|
10226
10222
|
const { cols, hiddenColumns, onChange, disabled, labels: labelsProp } = props;
|
|
@@ -10230,118 +10226,91 @@ function ColumnVisibilityTrigger(props) {
|
|
|
10230
10226
|
// defaults to `true` — a column is hideable unless explicitly opted
|
|
10231
10227
|
// out with `hideable: false` (structurally required column).
|
|
10232
10228
|
const hideableCols = cols.filter((c)=>c.hideable !== false);
|
|
10233
|
-
return jsxs(Fragment$1, {
|
|
10234
|
-
children: [
|
|
10235
|
-
jsxs("button", {
|
|
10236
|
-
type: "button",
|
|
10237
|
-
onClick: ()=>setOpen(true),
|
|
10238
|
-
disabled: disabled,
|
|
10239
|
-
className: cn('inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-md', 'text-sm text-neutral-700 hover:text-neutral-900', 'border border-neutral-300 bg-neutral-50 hover:bg-neutral-100', 'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500', 'transition-colors motion-reduce:transition-none', 'disabled:opacity-50 disabled:cursor-not-allowed'),
|
|
10240
|
-
children: [
|
|
10241
|
-
jsx(ColumnsIcon, {}),
|
|
10242
|
-
jsx("span", {
|
|
10243
|
-
children: labels.columnsButton
|
|
10244
|
-
})
|
|
10245
|
-
]
|
|
10246
|
-
}),
|
|
10247
|
-
jsx(Dialog, {
|
|
10248
|
-
open: open,
|
|
10249
|
-
onOpenChange: setOpen,
|
|
10250
|
-
title: labels.columnsTitle,
|
|
10251
|
-
description: labels.columnsDescription,
|
|
10252
|
-
size: "sm",
|
|
10253
|
-
children: jsx(ColumnVisibilityBody, {
|
|
10254
|
-
cols: hideableCols,
|
|
10255
|
-
hiddenColumns: hiddenColumns,
|
|
10256
|
-
onChange: onChange,
|
|
10257
|
-
onDone: ()=>setOpen(false),
|
|
10258
|
-
labels: labels
|
|
10259
|
-
})
|
|
10260
|
-
})
|
|
10261
|
-
]
|
|
10262
|
-
});
|
|
10263
|
-
}
|
|
10264
|
-
// ───── Dialog body ─────
|
|
10265
|
-
function ColumnVisibilityBody(props) {
|
|
10266
|
-
const { cols, hiddenColumns, onChange, onDone, labels } = props;
|
|
10267
|
-
// Local draft so the user can stage changes; commit on Done.
|
|
10268
|
-
const [draft, setDraft] = useState(hiddenColumns);
|
|
10269
|
-
// Re-sync when the dialog re-opens with a different external state.
|
|
10270
|
-
useEffect(()=>{
|
|
10271
|
-
setDraft(hiddenColumns);
|
|
10272
|
-
}, [
|
|
10273
|
-
hiddenColumns
|
|
10274
|
-
]);
|
|
10275
10229
|
const toggle = (field)=>{
|
|
10276
|
-
|
|
10277
|
-
|
|
10278
|
-
|
|
10279
|
-
|
|
10230
|
+
onChange(hiddenColumns.includes(field) ? hiddenColumns.filter((f)=>f !== field) : [
|
|
10231
|
+
...hiddenColumns,
|
|
10232
|
+
field
|
|
10233
|
+
]);
|
|
10280
10234
|
};
|
|
10281
|
-
const showAll = ()=>
|
|
10282
|
-
const hideAll = ()=>
|
|
10283
|
-
return
|
|
10284
|
-
|
|
10285
|
-
|
|
10286
|
-
|
|
10287
|
-
|
|
10288
|
-
|
|
10289
|
-
|
|
10290
|
-
|
|
10291
|
-
|
|
10292
|
-
|
|
10293
|
-
|
|
10294
|
-
|
|
10295
|
-
|
|
10296
|
-
|
|
10297
|
-
|
|
10298
|
-
|
|
10299
|
-
|
|
10300
|
-
type: "button",
|
|
10301
|
-
onClick: hideAll,
|
|
10302
|
-
className: "text-xs text-neutral-600 hover:text-neutral-900 underline-offset-2 hover:underline focus:outline-none focus-visible:underline",
|
|
10303
|
-
children: labels.columnsHideAll
|
|
10304
|
-
})
|
|
10305
|
-
]
|
|
10306
|
-
}),
|
|
10307
|
-
jsx("ul", {
|
|
10308
|
-
className: "flex flex-col gap-1.5 max-h-72 overflow-auto",
|
|
10309
|
-
children: cols.map((col)=>{
|
|
10310
|
-
const field = col.field;
|
|
10311
|
-
const hidden = draft.includes(field);
|
|
10312
|
-
const header = typeof col.header === 'function' ? col.header() : col.header;
|
|
10313
|
-
return jsx("li", {
|
|
10314
|
-
children: jsxs("label", {
|
|
10315
|
-
className: "flex items-center gap-2 cursor-pointer py-1 px-1 rounded hover:bg-neutral-100",
|
|
10235
|
+
const showAll = ()=>onChange([]);
|
|
10236
|
+
const hideAll = ()=>onChange(hideableCols.map((c)=>c.field));
|
|
10237
|
+
return jsx(Popover, {
|
|
10238
|
+
open: open,
|
|
10239
|
+
onOpenChange: setOpen,
|
|
10240
|
+
side: "bottom",
|
|
10241
|
+
align: "end",
|
|
10242
|
+
content: jsxs("div", {
|
|
10243
|
+
className: "flex flex-col gap-2 min-w-[220px]",
|
|
10244
|
+
children: [
|
|
10245
|
+
jsxs("div", {
|
|
10246
|
+
className: "flex items-center justify-between pb-2 border-b border-neutral-200",
|
|
10247
|
+
children: [
|
|
10248
|
+
jsx("span", {
|
|
10249
|
+
className: "text-xs font-semibold text-neutral-700 uppercase tracking-wide",
|
|
10250
|
+
children: labels.columnsTitle
|
|
10251
|
+
}),
|
|
10252
|
+
jsxs("div", {
|
|
10253
|
+
className: "flex items-center gap-2",
|
|
10316
10254
|
children: [
|
|
10317
|
-
jsx("
|
|
10318
|
-
type: "
|
|
10319
|
-
|
|
10320
|
-
|
|
10321
|
-
|
|
10255
|
+
jsx("button", {
|
|
10256
|
+
type: "button",
|
|
10257
|
+
onClick: showAll,
|
|
10258
|
+
className: "text-xs text-neutral-600 hover:text-neutral-900 underline-offset-2 hover:underline focus:outline-none focus-visible:underline",
|
|
10259
|
+
children: labels.columnsShowAll
|
|
10322
10260
|
}),
|
|
10323
10261
|
jsx("span", {
|
|
10324
|
-
className: "text-
|
|
10325
|
-
|
|
10262
|
+
className: "text-neutral-300",
|
|
10263
|
+
"aria-hidden": "true",
|
|
10264
|
+
children: "\u00B7"
|
|
10265
|
+
}),
|
|
10266
|
+
jsx("button", {
|
|
10267
|
+
type: "button",
|
|
10268
|
+
onClick: hideAll,
|
|
10269
|
+
className: "text-xs text-neutral-600 hover:text-neutral-900 underline-offset-2 hover:underline focus:outline-none focus-visible:underline",
|
|
10270
|
+
children: labels.columnsHideAll
|
|
10326
10271
|
})
|
|
10327
10272
|
]
|
|
10328
10273
|
})
|
|
10329
|
-
|
|
10274
|
+
]
|
|
10275
|
+
}),
|
|
10276
|
+
jsx("ul", {
|
|
10277
|
+
className: "flex flex-col gap-0.5 max-h-72 overflow-auto",
|
|
10278
|
+
children: hideableCols.map((col)=>{
|
|
10279
|
+
const field = col.field;
|
|
10280
|
+
const hidden = hiddenColumns.includes(field);
|
|
10281
|
+
const header = typeof col.header === 'function' ? col.header() : col.header;
|
|
10282
|
+
return jsx("li", {
|
|
10283
|
+
children: jsxs("label", {
|
|
10284
|
+
className: "flex items-center gap-2 cursor-pointer py-1 px-1 rounded hover:bg-neutral-100",
|
|
10285
|
+
children: [
|
|
10286
|
+
jsx("input", {
|
|
10287
|
+
type: "checkbox",
|
|
10288
|
+
checked: !hidden,
|
|
10289
|
+
onChange: ()=>toggle(field),
|
|
10290
|
+
className: "cursor-pointer"
|
|
10291
|
+
}),
|
|
10292
|
+
jsx("span", {
|
|
10293
|
+
className: "text-sm text-neutral-900",
|
|
10294
|
+
children: header
|
|
10295
|
+
})
|
|
10296
|
+
]
|
|
10297
|
+
})
|
|
10298
|
+
}, field);
|
|
10299
|
+
})
|
|
10330
10300
|
})
|
|
10331
|
-
|
|
10332
|
-
|
|
10333
|
-
|
|
10334
|
-
|
|
10335
|
-
|
|
10336
|
-
|
|
10337
|
-
|
|
10338
|
-
|
|
10339
|
-
|
|
10340
|
-
|
|
10341
|
-
children: labels.columnsDone
|
|
10301
|
+
]
|
|
10302
|
+
}),
|
|
10303
|
+
children: jsxs("button", {
|
|
10304
|
+
type: "button",
|
|
10305
|
+
disabled: disabled,
|
|
10306
|
+
className: cn('inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-md', 'text-sm text-neutral-700 hover:text-neutral-900', 'border border-neutral-300 bg-neutral-50 hover:bg-neutral-100', 'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500', 'transition-colors motion-reduce:transition-none', 'disabled:opacity-50 disabled:cursor-not-allowed'),
|
|
10307
|
+
children: [
|
|
10308
|
+
jsx(ColumnsIcon, {}),
|
|
10309
|
+
jsx("span", {
|
|
10310
|
+
children: labels.columnsButton
|
|
10342
10311
|
})
|
|
10343
|
-
|
|
10344
|
-
|
|
10312
|
+
]
|
|
10313
|
+
})
|
|
10345
10314
|
});
|
|
10346
10315
|
}
|
|
10347
10316
|
// ───── Icon ─────
|
|
@@ -10550,11 +10519,9 @@ const DEFAULT_LABELS = {
|
|
|
10550
10519
|
densityComfortable: 'Comfortable',
|
|
10551
10520
|
densitySpacious: 'Spacious',
|
|
10552
10521
|
columnsButton: 'Columns',
|
|
10553
|
-
columnsTitle: '
|
|
10554
|
-
columnsDescription: 'Show or hide columns. Required columns cannot be toggled.',
|
|
10522
|
+
columnsTitle: 'Toggle columns',
|
|
10555
10523
|
columnsShowAll: 'Show all',
|
|
10556
|
-
columnsHideAll: 'Hide all'
|
|
10557
|
-
columnsDone: 'Done'
|
|
10524
|
+
columnsHideAll: 'Hide all'
|
|
10558
10525
|
};
|
|
10559
10526
|
/**
|
|
10560
10527
|
* Dashforge TW `<DataGrid>` — virtualized data table.
|
|
@@ -10805,7 +10772,7 @@ const DEFAULT_LABELS = {
|
|
|
10805
10772
|
]
|
|
10806
10773
|
}),
|
|
10807
10774
|
enableColumnVisibility && jsx(ColumnVisibilityTrigger, {
|
|
10808
|
-
cols: cols.filter((c)=>// RBAC-hidden columns are never offered in the
|
|
10775
|
+
cols: cols.filter((c)=>// RBAC-hidden columns are never offered in the menu.
|
|
10809
10776
|
!c.access || c.access.onUnauthorized !== 'hide'),
|
|
10810
10777
|
hiddenColumns: hiddenColumns,
|
|
10811
10778
|
onChange: setHiddenColumns,
|
|
@@ -10813,10 +10780,8 @@ const DEFAULT_LABELS = {
|
|
|
10813
10780
|
labels: {
|
|
10814
10781
|
columnsButton: labels.columnsButton,
|
|
10815
10782
|
columnsTitle: labels.columnsTitle,
|
|
10816
|
-
columnsDescription: labels.columnsDescription,
|
|
10817
10783
|
columnsShowAll: labels.columnsShowAll,
|
|
10818
|
-
columnsHideAll: labels.columnsHideAll
|
|
10819
|
-
columnsDone: labels.columnsDone
|
|
10784
|
+
columnsHideAll: labels.columnsHideAll
|
|
10820
10785
|
}
|
|
10821
10786
|
})
|
|
10822
10787
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataGrid.d.ts","sourceRoot":"","sources":["../../../../src/components/DataGrid/DataGrid.tsx"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"DataGrid.d.ts","sourceRoot":"","sources":["../../../../src/components/DataGrid/DataGrid.tsx"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AA0CzD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,kDAkhBjE"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { TableColumn } from '../../Table/table.types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Column visibility menu for DataGrid.
|
|
4
|
+
*
|
|
5
|
+
* Renders a toolbar button (the trigger) that opens a `<Popover>`
|
|
6
|
+
* with one checkbox per `hideable` column. Auto-commits on every
|
|
7
|
+
* toggle — there's no draft / commit step. Outside-click and Esc
|
|
8
|
+
* close the popover (Radix-managed).
|
|
9
|
+
*
|
|
10
|
+
* UX rationale for Popover-over-Dialog:
|
|
11
|
+
* - Lightweight, non-modal: the user can keep referring to the grid
|
|
12
|
+
* while picking columns. A modal Dialog would interrupt the flow.
|
|
13
|
+
* - Auto-commit reads as a "settings panel" rather than a
|
|
14
|
+
* "configuration form" — matches AG-Grid / MUI DataGrid v6 /
|
|
15
|
+
* TanStack examples.
|
|
16
|
+
* - No focus trap on the rest of the page; the user can scroll the
|
|
17
|
+
* grid or click the column resize handles without dismissing the
|
|
18
|
+
* panel first.
|
|
19
|
+
*
|
|
20
|
+
* Columns with `hideable: false` are NEVER shown in the menu —
|
|
21
|
+
* those are considered structurally required (e.g. an ID column).
|
|
22
|
+
*
|
|
23
|
+
* RBAC-hidden columns (`access.onUnauthorized === 'hide'`) are also
|
|
24
|
+
* excluded — they're already removed from `visibleCols` upstream.
|
|
25
|
+
*/
|
|
26
|
+
export interface ColumnVisibilityLabels {
|
|
27
|
+
columnsButton?: string;
|
|
28
|
+
columnsTitle?: string;
|
|
29
|
+
columnsShowAll?: string;
|
|
30
|
+
columnsHideAll?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface ColumnVisibilityTriggerProps<T extends object> {
|
|
33
|
+
cols: TableColumn<T>[];
|
|
34
|
+
hiddenColumns: string[];
|
|
35
|
+
onChange: (next: string[]) => void;
|
|
36
|
+
disabled?: boolean;
|
|
37
|
+
labels?: ColumnVisibilityLabels;
|
|
38
|
+
}
|
|
39
|
+
export declare function ColumnVisibilityTrigger<T extends object>(props: ColumnVisibilityTriggerProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
40
|
+
//# sourceMappingURL=ColumnVisibilityMenu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ColumnVisibilityMenu.d.ts","sourceRoot":"","sources":["../../../../../src/components/DataGrid/visibility/ColumnVisibilityMenu.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,WAAW,sBAAsB;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AASD,MAAM,WAAW,4BAA4B,CAAC,CAAC,SAAS,MAAM;IAC5D,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,sBAAsB,CAAC;CACjC;AAED,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,MAAM,EACtD,KAAK,EAAE,4BAA4B,CAAC,CAAC,CAAC,2CA6FvC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Table.d.ts","sourceRoot":"","sources":["../../../../src/components/Table/Table.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EACV,UAAU,EAKX,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"Table.d.ts","sourceRoot":"","sources":["../../../../src/components/Table/Table.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EACV,UAAU,EAKX,MAAM,kBAAkB,CAAC;AAqC1B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,kDAgW3D"}
|
|
@@ -245,13 +245,11 @@ export interface TableLabels {
|
|
|
245
245
|
densityCompact?: string;
|
|
246
246
|
densityComfortable?: string;
|
|
247
247
|
densitySpacious?: string;
|
|
248
|
-
/** Column visibility
|
|
248
|
+
/** Column visibility menu (Popover-based, auto-commit). */
|
|
249
249
|
columnsButton?: string;
|
|
250
250
|
columnsTitle?: string;
|
|
251
|
-
columnsDescription?: string;
|
|
252
251
|
columnsShowAll?: string;
|
|
253
252
|
columnsHideAll?: string;
|
|
254
|
-
columnsDone?: string;
|
|
255
253
|
}
|
|
256
254
|
export interface TableSlotProps {
|
|
257
255
|
root?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table.types.d.ts","sourceRoot":"","sources":["../../../../src/components/Table/table.types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"table.types.d.ts","sourceRoot":"","sources":["../../../../src/components/Table/table.types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dashforge/tw",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.1-beta",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.esm.js",
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
"tailwind-variants": "^3.1.1",
|
|
32
32
|
"vitest": "*",
|
|
33
33
|
"@dashforge/forms": "0.2.3-beta",
|
|
34
|
-
"@dashforge/
|
|
35
|
-
"@dashforge/
|
|
34
|
+
"@dashforge/rbac": "0.2.3-beta",
|
|
35
|
+
"@dashforge/ui-core": "0.2.3-beta"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"react": "^18.0.0 || ^19.0.0",
|
|
39
|
-
"@dashforge/tw-
|
|
40
|
-
"@dashforge/tw-
|
|
39
|
+
"@dashforge/tw-theme": "0.1.0-beta",
|
|
40
|
+
"@dashforge/tw-tokens": "0.1.0-beta"
|
|
41
41
|
}
|
|
42
42
|
}
|
|
@@ -667,11 +667,11 @@ describe('DataGrid — column visibility', () => {
|
|
|
667
667
|
expect(screen.queryByRole('button', { name: 'Columns' })).toBeNull();
|
|
668
668
|
});
|
|
669
669
|
|
|
670
|
-
it('opens
|
|
670
|
+
it('opens a popover menu with one checkbox per hideable column', () => {
|
|
671
671
|
const cols: TableColumn<User>[] = [
|
|
672
672
|
{ field: 'name', header: 'Name' },
|
|
673
673
|
{ field: 'email', header: 'Email' },
|
|
674
|
-
// hideable: false → not shown in the
|
|
674
|
+
// hideable: false → not shown in the menu (structurally required)
|
|
675
675
|
{ field: 'age', header: 'Age', hideable: false },
|
|
676
676
|
];
|
|
677
677
|
render(
|
|
@@ -684,16 +684,13 @@ describe('DataGrid — column visibility', () => {
|
|
|
684
684
|
/>,
|
|
685
685
|
);
|
|
686
686
|
fireEvent.click(screen.getByRole('button', { name: 'Columns' }));
|
|
687
|
+
// Radix Popover content has role="dialog" too.
|
|
687
688
|
expect(screen.queryByRole('dialog')).not.toBeNull();
|
|
688
|
-
// The
|
|
689
|
-
const
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
expect(dialog.textContent).toContain('Name');
|
|
694
|
-
expect(dialog.textContent).toContain('Email');
|
|
695
|
-
expect(dialog.textContent).not.toContain('Age');
|
|
696
|
-
void labels;
|
|
689
|
+
// The menu should expose checkboxes for Name + Email (not Age).
|
|
690
|
+
const menu = screen.getByRole('dialog');
|
|
691
|
+
expect(menu.textContent).toContain('Name');
|
|
692
|
+
expect(menu.textContent).toContain('Email');
|
|
693
|
+
expect(menu.textContent).not.toContain('Age');
|
|
697
694
|
});
|
|
698
695
|
|
|
699
696
|
it('respects col.defaultHidden on first render', () => {
|
|
@@ -716,7 +713,7 @@ describe('DataGrid — column visibility', () => {
|
|
|
716
713
|
expect(screen.queryByText('Name')).not.toBeNull();
|
|
717
714
|
});
|
|
718
715
|
|
|
719
|
-
it('toggling a column
|
|
716
|
+
it('toggling a column auto-commits via onHiddenColumnsChange (no Done button)', () => {
|
|
720
717
|
const onHiddenColumnsChange = vi.fn();
|
|
721
718
|
render(
|
|
722
719
|
<DataGrid
|
|
@@ -729,18 +726,17 @@ describe('DataGrid — column visibility', () => {
|
|
|
729
726
|
/>,
|
|
730
727
|
);
|
|
731
728
|
fireEvent.click(screen.getByRole('button', { name: 'Columns' }));
|
|
732
|
-
// Uncheck "Email" inside the
|
|
733
|
-
const
|
|
729
|
+
// Uncheck "Email" inside the popover menu
|
|
730
|
+
const menu = screen.getByRole('dialog');
|
|
734
731
|
const emailCheckbox = Array.from(
|
|
735
|
-
|
|
732
|
+
menu.querySelectorAll('input[type="checkbox"]'),
|
|
736
733
|
).find((el) => {
|
|
737
734
|
const li = el.closest('label');
|
|
738
735
|
return li?.textContent?.includes('Email');
|
|
739
736
|
}) as HTMLInputElement | undefined;
|
|
740
737
|
expect(emailCheckbox).toBeDefined();
|
|
741
738
|
fireEvent.click(emailCheckbox!);
|
|
742
|
-
//
|
|
743
|
-
fireEvent.click(screen.getByRole('button', { name: 'Done' }));
|
|
739
|
+
// Auto-commit on toggle — no Done button anymore
|
|
744
740
|
expect(onHiddenColumnsChange).toHaveBeenCalledWith(['email']);
|
|
745
741
|
});
|
|
746
742
|
|
|
@@ -33,7 +33,7 @@ import type {
|
|
|
33
33
|
} from '../Table/table.types.js';
|
|
34
34
|
import type { DataGridProps } from './dataGrid.types.js';
|
|
35
35
|
import { ColumnFilterTrigger } from './filters/ColumnFilters.js';
|
|
36
|
-
import { ColumnVisibilityTrigger } from './visibility/
|
|
36
|
+
import { ColumnVisibilityTrigger } from './visibility/ColumnVisibilityMenu.js';
|
|
37
37
|
import { useColumnResize } from './resize/useColumnResize.js';
|
|
38
38
|
import {
|
|
39
39
|
useColumnReorder,
|
|
@@ -68,12 +68,9 @@ const DEFAULT_LABELS: Required<TableLabels> = {
|
|
|
68
68
|
densityComfortable: 'Comfortable',
|
|
69
69
|
densitySpacious: 'Spacious',
|
|
70
70
|
columnsButton: 'Columns',
|
|
71
|
-
columnsTitle: '
|
|
72
|
-
columnsDescription:
|
|
73
|
-
'Show or hide columns. Required columns cannot be toggled.',
|
|
71
|
+
columnsTitle: 'Toggle columns',
|
|
74
72
|
columnsShowAll: 'Show all',
|
|
75
73
|
columnsHideAll: 'Hide all',
|
|
76
|
-
columnsDone: 'Done',
|
|
77
74
|
};
|
|
78
75
|
|
|
79
76
|
/**
|
|
@@ -414,7 +411,7 @@ export function DataGrid<T extends object>(props: DataGridProps<T>) {
|
|
|
414
411
|
<ColumnVisibilityTrigger
|
|
415
412
|
cols={cols.filter(
|
|
416
413
|
(c) =>
|
|
417
|
-
// RBAC-hidden columns are never offered in the
|
|
414
|
+
// RBAC-hidden columns are never offered in the menu.
|
|
418
415
|
!c.access || c.access.onUnauthorized !== 'hide',
|
|
419
416
|
)}
|
|
420
417
|
hiddenColumns={hiddenColumns}
|
|
@@ -423,10 +420,8 @@ export function DataGrid<T extends object>(props: DataGridProps<T>) {
|
|
|
423
420
|
labels={{
|
|
424
421
|
columnsButton: labels.columnsButton,
|
|
425
422
|
columnsTitle: labels.columnsTitle,
|
|
426
|
-
columnsDescription: labels.columnsDescription,
|
|
427
423
|
columnsShowAll: labels.columnsShowAll,
|
|
428
424
|
columnsHideAll: labels.columnsHideAll,
|
|
429
|
-
columnsDone: labels.columnsDone,
|
|
430
425
|
}}
|
|
431
426
|
/>
|
|
432
427
|
)}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { useState, type ReactNode } from 'react';
|
|
2
|
+
import { Popover } from '../../Popover/Popover.js';
|
|
3
|
+
import { cn } from '../../../utils/cn.js';
|
|
4
|
+
import type { TableColumn } from '../../Table/table.types.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Column visibility menu for DataGrid.
|
|
8
|
+
*
|
|
9
|
+
* Renders a toolbar button (the trigger) that opens a `<Popover>`
|
|
10
|
+
* with one checkbox per `hideable` column. Auto-commits on every
|
|
11
|
+
* toggle — there's no draft / commit step. Outside-click and Esc
|
|
12
|
+
* close the popover (Radix-managed).
|
|
13
|
+
*
|
|
14
|
+
* UX rationale for Popover-over-Dialog:
|
|
15
|
+
* - Lightweight, non-modal: the user can keep referring to the grid
|
|
16
|
+
* while picking columns. A modal Dialog would interrupt the flow.
|
|
17
|
+
* - Auto-commit reads as a "settings panel" rather than a
|
|
18
|
+
* "configuration form" — matches AG-Grid / MUI DataGrid v6 /
|
|
19
|
+
* TanStack examples.
|
|
20
|
+
* - No focus trap on the rest of the page; the user can scroll the
|
|
21
|
+
* grid or click the column resize handles without dismissing the
|
|
22
|
+
* panel first.
|
|
23
|
+
*
|
|
24
|
+
* Columns with `hideable: false` are NEVER shown in the menu —
|
|
25
|
+
* those are considered structurally required (e.g. an ID column).
|
|
26
|
+
*
|
|
27
|
+
* RBAC-hidden columns (`access.onUnauthorized === 'hide'`) are also
|
|
28
|
+
* excluded — they're already removed from `visibleCols` upstream.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
export interface ColumnVisibilityLabels {
|
|
32
|
+
columnsButton?: string;
|
|
33
|
+
columnsTitle?: string;
|
|
34
|
+
columnsShowAll?: string;
|
|
35
|
+
columnsHideAll?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const DEFAULT_VISIBILITY_LABELS: Required<ColumnVisibilityLabels> = {
|
|
39
|
+
columnsButton: 'Columns',
|
|
40
|
+
columnsTitle: 'Toggle columns',
|
|
41
|
+
columnsShowAll: 'Show all',
|
|
42
|
+
columnsHideAll: 'Hide all',
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export interface ColumnVisibilityTriggerProps<T extends object> {
|
|
46
|
+
cols: TableColumn<T>[];
|
|
47
|
+
hiddenColumns: string[];
|
|
48
|
+
onChange: (next: string[]) => void;
|
|
49
|
+
disabled?: boolean;
|
|
50
|
+
labels?: ColumnVisibilityLabels;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function ColumnVisibilityTrigger<T extends object>(
|
|
54
|
+
props: ColumnVisibilityTriggerProps<T>,
|
|
55
|
+
) {
|
|
56
|
+
const { cols, hiddenColumns, onChange, disabled, labels: labelsProp } = props;
|
|
57
|
+
const labels = { ...DEFAULT_VISIBILITY_LABELS, ...labelsProp };
|
|
58
|
+
const [open, setOpen] = useState(false);
|
|
59
|
+
|
|
60
|
+
// Hideable cols are the only ones the user can toggle. `hideable`
|
|
61
|
+
// defaults to `true` — a column is hideable unless explicitly opted
|
|
62
|
+
// out with `hideable: false` (structurally required column).
|
|
63
|
+
const hideableCols = cols.filter((c) => c.hideable !== false);
|
|
64
|
+
|
|
65
|
+
const toggle = (field: string) => {
|
|
66
|
+
onChange(
|
|
67
|
+
hiddenColumns.includes(field)
|
|
68
|
+
? hiddenColumns.filter((f) => f !== field)
|
|
69
|
+
: [...hiddenColumns, field],
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const showAll = () => onChange([]);
|
|
74
|
+
const hideAll = () => onChange(hideableCols.map((c) => c.field as string));
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<Popover
|
|
78
|
+
open={open}
|
|
79
|
+
onOpenChange={setOpen}
|
|
80
|
+
side="bottom"
|
|
81
|
+
align="end"
|
|
82
|
+
content={
|
|
83
|
+
<div className="flex flex-col gap-2 min-w-[220px]">
|
|
84
|
+
<div className="flex items-center justify-between pb-2 border-b border-neutral-200">
|
|
85
|
+
<span className="text-xs font-semibold text-neutral-700 uppercase tracking-wide">
|
|
86
|
+
{labels.columnsTitle}
|
|
87
|
+
</span>
|
|
88
|
+
<div className="flex items-center gap-2">
|
|
89
|
+
<button
|
|
90
|
+
type="button"
|
|
91
|
+
onClick={showAll}
|
|
92
|
+
className="text-xs text-neutral-600 hover:text-neutral-900 underline-offset-2 hover:underline focus:outline-none focus-visible:underline"
|
|
93
|
+
>
|
|
94
|
+
{labels.columnsShowAll}
|
|
95
|
+
</button>
|
|
96
|
+
<span className="text-neutral-300" aria-hidden="true">·</span>
|
|
97
|
+
<button
|
|
98
|
+
type="button"
|
|
99
|
+
onClick={hideAll}
|
|
100
|
+
className="text-xs text-neutral-600 hover:text-neutral-900 underline-offset-2 hover:underline focus:outline-none focus-visible:underline"
|
|
101
|
+
>
|
|
102
|
+
{labels.columnsHideAll}
|
|
103
|
+
</button>
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
<ul className="flex flex-col gap-0.5 max-h-72 overflow-auto">
|
|
107
|
+
{hideableCols.map((col) => {
|
|
108
|
+
const field = col.field as string;
|
|
109
|
+
const hidden = hiddenColumns.includes(field);
|
|
110
|
+
const header =
|
|
111
|
+
typeof col.header === 'function' ? col.header() : col.header;
|
|
112
|
+
return (
|
|
113
|
+
<li key={field}>
|
|
114
|
+
<label className="flex items-center gap-2 cursor-pointer py-1 px-1 rounded hover:bg-neutral-100">
|
|
115
|
+
<input
|
|
116
|
+
type="checkbox"
|
|
117
|
+
checked={!hidden}
|
|
118
|
+
onChange={() => toggle(field)}
|
|
119
|
+
className="cursor-pointer"
|
|
120
|
+
/>
|
|
121
|
+
<span className="text-sm text-neutral-900">{header}</span>
|
|
122
|
+
</label>
|
|
123
|
+
</li>
|
|
124
|
+
);
|
|
125
|
+
})}
|
|
126
|
+
</ul>
|
|
127
|
+
</div>
|
|
128
|
+
}
|
|
129
|
+
>
|
|
130
|
+
<button
|
|
131
|
+
type="button"
|
|
132
|
+
disabled={disabled}
|
|
133
|
+
className={cn(
|
|
134
|
+
'inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-md',
|
|
135
|
+
'text-sm text-neutral-700 hover:text-neutral-900',
|
|
136
|
+
'border border-neutral-300 bg-neutral-50 hover:bg-neutral-100',
|
|
137
|
+
'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',
|
|
138
|
+
'transition-colors motion-reduce:transition-none',
|
|
139
|
+
'disabled:opacity-50 disabled:cursor-not-allowed',
|
|
140
|
+
)}
|
|
141
|
+
>
|
|
142
|
+
<ColumnsIcon />
|
|
143
|
+
<span>{labels.columnsButton}</span>
|
|
144
|
+
</button>
|
|
145
|
+
</Popover>
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ───── Icon ─────
|
|
150
|
+
|
|
151
|
+
function ColumnsIcon(): ReactNode {
|
|
152
|
+
return (
|
|
153
|
+
<svg
|
|
154
|
+
width="0.875em"
|
|
155
|
+
height="0.875em"
|
|
156
|
+
viewBox="0 0 16 16"
|
|
157
|
+
fill="none"
|
|
158
|
+
stroke="currentColor"
|
|
159
|
+
strokeWidth="1.5"
|
|
160
|
+
strokeLinecap="round"
|
|
161
|
+
strokeLinejoin="round"
|
|
162
|
+
aria-hidden="true"
|
|
163
|
+
>
|
|
164
|
+
<rect x="2" y="3" width="3.5" height="10" rx="0.5" />
|
|
165
|
+
<rect x="6.25" y="3" width="3.5" height="10" rx="0.5" />
|
|
166
|
+
<rect x="10.5" y="3" width="3.5" height="10" rx="0.5" />
|
|
167
|
+
</svg>
|
|
168
|
+
);
|
|
169
|
+
}
|
|
@@ -52,12 +52,9 @@ const DEFAULT_LABELS: Required<TableLabels> = {
|
|
|
52
52
|
densityComfortable: 'Comfortable',
|
|
53
53
|
densitySpacious: 'Spacious',
|
|
54
54
|
columnsButton: 'Columns',
|
|
55
|
-
columnsTitle: '
|
|
56
|
-
columnsDescription:
|
|
57
|
-
'Show or hide columns. Required columns cannot be toggled.',
|
|
55
|
+
columnsTitle: 'Toggle columns',
|
|
58
56
|
columnsShowAll: 'Show all',
|
|
59
57
|
columnsHideAll: 'Hide all',
|
|
60
|
-
columnsDone: 'Done',
|
|
61
58
|
};
|
|
62
59
|
|
|
63
60
|
const DEFAULT_GET_ROW_ID = <T extends object>(_row: T, index: number) => String(index);
|
|
@@ -288,13 +288,11 @@ export interface TableLabels {
|
|
|
288
288
|
densityCompact?: string;
|
|
289
289
|
densityComfortable?: string;
|
|
290
290
|
densitySpacious?: string;
|
|
291
|
-
/** Column visibility
|
|
291
|
+
/** Column visibility menu (Popover-based, auto-commit). */
|
|
292
292
|
columnsButton?: string;
|
|
293
293
|
columnsTitle?: string;
|
|
294
|
-
columnsDescription?: string;
|
|
295
294
|
columnsShowAll?: string;
|
|
296
295
|
columnsHideAll?: string;
|
|
297
|
-
columnsDone?: string;
|
|
298
296
|
}
|
|
299
297
|
|
|
300
298
|
// ───── Slot props ─────
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import type { TableColumn } from '../../Table/table.types.js';
|
|
2
|
-
/**
|
|
3
|
-
* Column visibility dialog for DataGrid.
|
|
4
|
-
*
|
|
5
|
-
* Renders a toolbar button (the trigger) that opens a `<Dialog>` with
|
|
6
|
-
* one checkbox per `hideable` column. The consumer can:
|
|
7
|
-
* - Show/hide individual columns
|
|
8
|
-
* - "Show all" / "Hide all" shortcuts
|
|
9
|
-
* - Persist visibility via the controllable `hiddenColumns` model
|
|
10
|
-
*
|
|
11
|
-
* Columns with `hideable: false` are NEVER shown in the dialog —
|
|
12
|
-
* those are considered structurally required (e.g. an ID column).
|
|
13
|
-
*
|
|
14
|
-
* RBAC-hidden columns (`access.onUnauthorized === 'hide'`) are also
|
|
15
|
-
* excluded — they're already removed from `visibleCols` upstream.
|
|
16
|
-
*/
|
|
17
|
-
export interface ColumnVisibilityLabels {
|
|
18
|
-
columnsButton?: string;
|
|
19
|
-
columnsTitle?: string;
|
|
20
|
-
columnsDescription?: string;
|
|
21
|
-
columnsShowAll?: string;
|
|
22
|
-
columnsHideAll?: string;
|
|
23
|
-
columnsDone?: string;
|
|
24
|
-
}
|
|
25
|
-
export interface ColumnVisibilityTriggerProps<T extends object> {
|
|
26
|
-
cols: TableColumn<T>[];
|
|
27
|
-
hiddenColumns: string[];
|
|
28
|
-
onChange: (next: string[]) => void;
|
|
29
|
-
disabled?: boolean;
|
|
30
|
-
labels?: ColumnVisibilityLabels;
|
|
31
|
-
}
|
|
32
|
-
export declare function ColumnVisibilityTrigger<T extends object>(props: ColumnVisibilityTriggerProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
33
|
-
//# sourceMappingURL=ColumnVisibilityDialog.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ColumnVisibilityDialog.d.ts","sourceRoot":"","sources":["../../../../../src/components/DataGrid/visibility/ColumnVisibilityDialog.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,sBAAsB;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAWD,MAAM,WAAW,4BAA4B,CAAC,CAAC,SAAS,MAAM;IAC5D,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,sBAAsB,CAAC;CACjC;AAED,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,MAAM,EACtD,KAAK,EAAE,4BAA4B,CAAC,CAAC,CAAC,2CA8CvC"}
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import { useState, useEffect, type ReactNode } from 'react';
|
|
2
|
-
import { Dialog } from '../../Dialog/Dialog.js';
|
|
3
|
-
import { cn } from '../../../utils/cn.js';
|
|
4
|
-
import type { TableColumn } from '../../Table/table.types.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Column visibility dialog for DataGrid.
|
|
8
|
-
*
|
|
9
|
-
* Renders a toolbar button (the trigger) that opens a `<Dialog>` with
|
|
10
|
-
* one checkbox per `hideable` column. The consumer can:
|
|
11
|
-
* - Show/hide individual columns
|
|
12
|
-
* - "Show all" / "Hide all" shortcuts
|
|
13
|
-
* - Persist visibility via the controllable `hiddenColumns` model
|
|
14
|
-
*
|
|
15
|
-
* Columns with `hideable: false` are NEVER shown in the dialog —
|
|
16
|
-
* those are considered structurally required (e.g. an ID column).
|
|
17
|
-
*
|
|
18
|
-
* RBAC-hidden columns (`access.onUnauthorized === 'hide'`) are also
|
|
19
|
-
* excluded — they're already removed from `visibleCols` upstream.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
export interface ColumnVisibilityLabels {
|
|
23
|
-
columnsButton?: string;
|
|
24
|
-
columnsTitle?: string;
|
|
25
|
-
columnsDescription?: string;
|
|
26
|
-
columnsShowAll?: string;
|
|
27
|
-
columnsHideAll?: string;
|
|
28
|
-
columnsDone?: string;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const DEFAULT_VISIBILITY_LABELS: Required<ColumnVisibilityLabels> = {
|
|
32
|
-
columnsButton: 'Columns',
|
|
33
|
-
columnsTitle: 'Manage columns',
|
|
34
|
-
columnsDescription: 'Show or hide columns. Required columns cannot be toggled.',
|
|
35
|
-
columnsShowAll: 'Show all',
|
|
36
|
-
columnsHideAll: 'Hide all',
|
|
37
|
-
columnsDone: 'Done',
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export interface ColumnVisibilityTriggerProps<T extends object> {
|
|
41
|
-
cols: TableColumn<T>[];
|
|
42
|
-
hiddenColumns: string[];
|
|
43
|
-
onChange: (next: string[]) => void;
|
|
44
|
-
disabled?: boolean;
|
|
45
|
-
labels?: ColumnVisibilityLabels;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function ColumnVisibilityTrigger<T extends object>(
|
|
49
|
-
props: ColumnVisibilityTriggerProps<T>,
|
|
50
|
-
) {
|
|
51
|
-
const { cols, hiddenColumns, onChange, disabled, labels: labelsProp } = props;
|
|
52
|
-
const labels = { ...DEFAULT_VISIBILITY_LABELS, ...labelsProp };
|
|
53
|
-
const [open, setOpen] = useState(false);
|
|
54
|
-
|
|
55
|
-
// Hideable cols are the only ones the user can toggle. `hideable`
|
|
56
|
-
// defaults to `true` — a column is hideable unless explicitly opted
|
|
57
|
-
// out with `hideable: false` (structurally required column).
|
|
58
|
-
const hideableCols = cols.filter((c) => c.hideable !== false);
|
|
59
|
-
|
|
60
|
-
return (
|
|
61
|
-
<>
|
|
62
|
-
<button
|
|
63
|
-
type="button"
|
|
64
|
-
onClick={() => setOpen(true)}
|
|
65
|
-
disabled={disabled}
|
|
66
|
-
className={cn(
|
|
67
|
-
'inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-md',
|
|
68
|
-
'text-sm text-neutral-700 hover:text-neutral-900',
|
|
69
|
-
'border border-neutral-300 bg-neutral-50 hover:bg-neutral-100',
|
|
70
|
-
'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',
|
|
71
|
-
'transition-colors motion-reduce:transition-none',
|
|
72
|
-
'disabled:opacity-50 disabled:cursor-not-allowed',
|
|
73
|
-
)}
|
|
74
|
-
>
|
|
75
|
-
<ColumnsIcon />
|
|
76
|
-
<span>{labels.columnsButton}</span>
|
|
77
|
-
</button>
|
|
78
|
-
<Dialog
|
|
79
|
-
open={open}
|
|
80
|
-
onOpenChange={setOpen}
|
|
81
|
-
title={labels.columnsTitle}
|
|
82
|
-
description={labels.columnsDescription}
|
|
83
|
-
size="sm"
|
|
84
|
-
>
|
|
85
|
-
<ColumnVisibilityBody
|
|
86
|
-
cols={hideableCols}
|
|
87
|
-
hiddenColumns={hiddenColumns}
|
|
88
|
-
onChange={onChange}
|
|
89
|
-
onDone={() => setOpen(false)}
|
|
90
|
-
labels={labels}
|
|
91
|
-
/>
|
|
92
|
-
</Dialog>
|
|
93
|
-
</>
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// ───── Dialog body ─────
|
|
98
|
-
|
|
99
|
-
function ColumnVisibilityBody<T extends object>(props: {
|
|
100
|
-
cols: TableColumn<T>[];
|
|
101
|
-
hiddenColumns: string[];
|
|
102
|
-
onChange: (next: string[]) => void;
|
|
103
|
-
onDone: () => void;
|
|
104
|
-
labels: Required<ColumnVisibilityLabels>;
|
|
105
|
-
}) {
|
|
106
|
-
const { cols, hiddenColumns, onChange, onDone, labels } = props;
|
|
107
|
-
// Local draft so the user can stage changes; commit on Done.
|
|
108
|
-
const [draft, setDraft] = useState<string[]>(hiddenColumns);
|
|
109
|
-
|
|
110
|
-
// Re-sync when the dialog re-opens with a different external state.
|
|
111
|
-
useEffect(() => {
|
|
112
|
-
setDraft(hiddenColumns);
|
|
113
|
-
}, [hiddenColumns]);
|
|
114
|
-
|
|
115
|
-
const toggle = (field: string) => {
|
|
116
|
-
setDraft((prev) =>
|
|
117
|
-
prev.includes(field) ? prev.filter((f) => f !== field) : [...prev, field],
|
|
118
|
-
);
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
const showAll = () => setDraft([]);
|
|
122
|
-
const hideAll = () => setDraft(cols.map((c) => c.field as string));
|
|
123
|
-
|
|
124
|
-
return (
|
|
125
|
-
<div className="flex flex-col gap-3">
|
|
126
|
-
<div className="flex items-center gap-2 pb-2 border-b border-neutral-200">
|
|
127
|
-
<button
|
|
128
|
-
type="button"
|
|
129
|
-
onClick={showAll}
|
|
130
|
-
className="text-xs text-neutral-600 hover:text-neutral-900 underline-offset-2 hover:underline focus:outline-none focus-visible:underline"
|
|
131
|
-
>
|
|
132
|
-
{labels.columnsShowAll}
|
|
133
|
-
</button>
|
|
134
|
-
<span className="text-neutral-300">·</span>
|
|
135
|
-
<button
|
|
136
|
-
type="button"
|
|
137
|
-
onClick={hideAll}
|
|
138
|
-
className="text-xs text-neutral-600 hover:text-neutral-900 underline-offset-2 hover:underline focus:outline-none focus-visible:underline"
|
|
139
|
-
>
|
|
140
|
-
{labels.columnsHideAll}
|
|
141
|
-
</button>
|
|
142
|
-
</div>
|
|
143
|
-
<ul className="flex flex-col gap-1.5 max-h-72 overflow-auto">
|
|
144
|
-
{cols.map((col) => {
|
|
145
|
-
const field = col.field as string;
|
|
146
|
-
const hidden = draft.includes(field);
|
|
147
|
-
const header =
|
|
148
|
-
typeof col.header === 'function' ? col.header() : col.header;
|
|
149
|
-
return (
|
|
150
|
-
<li key={field}>
|
|
151
|
-
<label className="flex items-center gap-2 cursor-pointer py-1 px-1 rounded hover:bg-neutral-100">
|
|
152
|
-
<input
|
|
153
|
-
type="checkbox"
|
|
154
|
-
checked={!hidden}
|
|
155
|
-
onChange={() => toggle(field)}
|
|
156
|
-
className="cursor-pointer"
|
|
157
|
-
/>
|
|
158
|
-
<span className="text-sm text-neutral-900">{header}</span>
|
|
159
|
-
</label>
|
|
160
|
-
</li>
|
|
161
|
-
);
|
|
162
|
-
})}
|
|
163
|
-
</ul>
|
|
164
|
-
<div className="flex justify-end gap-2 pt-2 border-t border-neutral-200">
|
|
165
|
-
<button
|
|
166
|
-
type="button"
|
|
167
|
-
onClick={() => {
|
|
168
|
-
onChange(draft);
|
|
169
|
-
onDone();
|
|
170
|
-
}}
|
|
171
|
-
className="text-sm bg-primary-500 text-white rounded-md hover:bg-primary-600 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 px-3 py-1.5"
|
|
172
|
-
>
|
|
173
|
-
{labels.columnsDone}
|
|
174
|
-
</button>
|
|
175
|
-
</div>
|
|
176
|
-
</div>
|
|
177
|
-
);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// ───── Icon ─────
|
|
181
|
-
|
|
182
|
-
function ColumnsIcon(): ReactNode {
|
|
183
|
-
return (
|
|
184
|
-
<svg
|
|
185
|
-
width="0.875em"
|
|
186
|
-
height="0.875em"
|
|
187
|
-
viewBox="0 0 16 16"
|
|
188
|
-
fill="none"
|
|
189
|
-
stroke="currentColor"
|
|
190
|
-
strokeWidth="1.5"
|
|
191
|
-
strokeLinecap="round"
|
|
192
|
-
strokeLinejoin="round"
|
|
193
|
-
aria-hidden="true"
|
|
194
|
-
>
|
|
195
|
-
<rect x="2" y="3" width="3.5" height="10" rx="0.5" />
|
|
196
|
-
<rect x="6.25" y="3" width="3.5" height="10" rx="0.5" />
|
|
197
|
-
<rect x="10.5" y="3" width="3.5" height="10" rx="0.5" />
|
|
198
|
-
</svg>
|
|
199
|
-
);
|
|
200
|
-
}
|