@jielga/tmdatagrid 1.0.0 → 1.0.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.
- package/README.md +8 -8
- package/dist/index.d.ts +225 -225
- package/dist/index.js +58 -50
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +3 -2
- package/skills/appearance/SKILL.md +322 -0
- package/skills/cell-selection/SKILL.md +240 -0
- package/skills/columns/SKILL.md +261 -86
- package/skills/data/SKILL.md +289 -0
- package/skills/editing/SKILL.md +492 -0
- package/skills/editing/references/editing-api.md +124 -0
- package/skills/editing/references/editors-and-validation.md +198 -0
- package/skills/filtering/SKILL.md +344 -0
- package/skills/getting-started/SKILL.md +48 -27
- package/skills/grouping/SKILL.md +264 -0
- package/skills/options/SKILL.md +31 -20
- package/skills/rows/SKILL.md +369 -0
- package/skills/rows/references/rows-api.md +117 -0
- package/skills/server-side/SKILL.md +7 -7
- package/skills/testing/SKILL.md +12 -12
- package/src/tmdatagrid/TMDataGridContext.ts +2 -2
- package/src/tmdatagrid/components/TMDataGrid.module.css +2 -2
- package/src/tmdatagrid/components/TMDataGrid.tsx +5 -5
- package/src/tmdatagrid/components/TMDataGridCellEditor.tsx +4 -4
- package/src/tmdatagrid/components/TMDataGridColumnsPanel.tsx +2 -2
- package/src/tmdatagrid/components/TMDataGridDetailsColumn.tsx +6 -6
- package/src/tmdatagrid/components/TMDataGridEditActions.tsx +2 -2
- package/src/tmdatagrid/components/TMDataGridEditColumn.tsx +4 -4
- package/src/tmdatagrid/components/TMDataGridEntryRows.tsx +6 -6
- package/src/tmdatagrid/components/TMDataGridFilterPanel.tsx +6 -6
- package/src/tmdatagrid/components/TMDataGridFilterPills.module.css +2 -2
- package/src/tmdatagrid/components/TMDataGridFilterPills.tsx +1 -1
- package/src/tmdatagrid/components/TMDataGridFooter.module.css +1 -1
- package/src/tmdatagrid/components/TMDataGridFooter.tsx +12 -6
- package/src/tmdatagrid/components/TMDataGridGroupColumn.module.css +1 -1
- package/src/tmdatagrid/components/TMDataGridGroupColumn.tsx +5 -5
- package/src/tmdatagrid/components/TMDataGridHeaderCell.module.css +8 -8
- package/src/tmdatagrid/components/TMDataGridHeaderCell.tsx +12 -12
- package/src/tmdatagrid/components/TMDataGridRowNumberColumn.tsx +4 -4
- package/src/tmdatagrid/components/TMDataGridSearch.tsx +5 -5
- package/src/tmdatagrid/components/TMDataGridSelectColumn.tsx +8 -8
- package/src/tmdatagrid/components/TMDataGridTable.module.css +18 -18
- package/src/tmdatagrid/components/TMDataGridTable.tsx +116 -116
- package/src/tmdatagrid/components/TMDataGridToolbar.tsx +5 -5
- package/src/tmdatagrid/components/editors/TMDataGridBooleanEditor.tsx +1 -1
- package/src/tmdatagrid/components/editors/TMDataGridDateEditor.tsx +2 -2
- package/src/tmdatagrid/components/editors/TMDataGridMultiSelectEditor.tsx +1 -1
- package/src/tmdatagrid/components/editors/TMDataGridNumberEditor.tsx +1 -1
- package/src/tmdatagrid/components/editors/TMDataGridSelectEditor.tsx +2 -2
- package/src/tmdatagrid/components/editors/editorShared.ts +3 -3
- package/src/tmdatagrid/components/filters/DgDateRangeFilter.tsx +1 -1
- package/src/tmdatagrid/components/filters/DgRangeSliderFilter.tsx +1 -1
- package/src/tmdatagrid/components/filters/DgTriStateFilter.tsx +1 -1
- package/src/tmdatagrid/components/filters/TMDataGridFilterValueInput.tsx +2 -2
- package/src/tmdatagrid/components/sticky.module.css +8 -8
- package/src/tmdatagrid/core/autosize.ts +4 -4
- package/src/tmdatagrid/core/capabilities.ts +17 -17
- package/src/tmdatagrid/core/cellExport.ts +13 -13
- package/src/tmdatagrid/core/cellNavigation.ts +6 -6
- package/src/tmdatagrid/core/cellRange.ts +4 -4
- package/src/tmdatagrid/core/columnOptions.ts +2 -2
- package/src/tmdatagrid/core/columnOrdering.ts +2 -2
- package/src/tmdatagrid/core/columnUtils.ts +3 -3
- package/src/tmdatagrid/core/editEngine.ts +49 -49
- package/src/tmdatagrid/core/expanding.ts +5 -5
- package/src/tmdatagrid/core/filterControls.ts +5 -5
- package/src/tmdatagrid/core/filterOperators.ts +14 -14
- package/src/tmdatagrid/core/labels.ts +8 -8
- package/src/tmdatagrid/core/matchHighlight.ts +4 -4
- package/src/tmdatagrid/core/persistence.ts +8 -8
- package/src/tmdatagrid/core/quickSearch.ts +8 -8
- package/src/tmdatagrid/core/rowPinning.ts +3 -3
- package/src/tmdatagrid/core/rowSelection.ts +12 -12
- package/src/tmdatagrid/core/sizes.ts +1 -1
- package/src/tmdatagrid/core/summary.ts +3 -3
- package/src/tmdatagrid/useTMDataGrid.tsx +79 -79
- package/skills/features/SKILL.md +0 -352
|
@@ -10,7 +10,7 @@ export type TMDataGridSearchProps = {
|
|
|
10
10
|
placeholder?: string;
|
|
11
11
|
/**
|
|
12
12
|
* How long typing pauses before the filter is applied, in ms. Defaults to
|
|
13
|
-
* 250. `0` writes on every keystroke
|
|
13
|
+
* 250. `0` writes on every keystroke - what the tests use, and fine for
|
|
14
14
|
* small client-side data sets.
|
|
15
15
|
*/
|
|
16
16
|
debounce?: number;
|
|
@@ -19,7 +19,7 @@ export type TMDataGridSearchProps = {
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* Quick search over every column
|
|
22
|
+
* Quick search over every column - a debounced input writing the table's
|
|
23
23
|
* `globalFilter` state through the `"includesString"` filter the grid
|
|
24
24
|
* configures by default.
|
|
25
25
|
*
|
|
@@ -32,12 +32,12 @@ export type TMDataGridSearchProps = {
|
|
|
32
32
|
* ```
|
|
33
33
|
*
|
|
34
34
|
* Renders nothing under `enableGlobalFilter: false`. Columns opt out with
|
|
35
|
-
* their own `enableGlobalFilter: false`
|
|
35
|
+
* their own `enableGlobalFilter: false` - the generated lanes already do.
|
|
36
36
|
*
|
|
37
37
|
* The state is TanStack's `globalFilter`, so everything around it comes free:
|
|
38
38
|
* `manualFiltering` grids forward it to the server, and it is one of the
|
|
39
39
|
* persisted `data` slices. A grid that wants its own input entirely writes
|
|
40
|
-
* `table.setGlobalFilter` itself
|
|
40
|
+
* `table.setGlobalFilter` itself - this component is only the built-in one.
|
|
41
41
|
*/
|
|
42
42
|
export function TMDataGridSearch({
|
|
43
43
|
placeholder,
|
|
@@ -60,7 +60,7 @@ export function TMDataGridSearch({
|
|
|
60
60
|
// for an external change that should overwrite what is being typed.
|
|
61
61
|
const lastWrittenRef = useRef(globalFilter);
|
|
62
62
|
|
|
63
|
-
// External writes
|
|
63
|
+
// External writes - a consumer's `setGlobalFilter`, a persistence restore -
|
|
64
64
|
// win over the draft; the input is a mirror, not an owner.
|
|
65
65
|
useEffect(() => {
|
|
66
66
|
if (globalFilter === lastWrittenRef.current) return;
|
|
@@ -19,7 +19,7 @@ export const SELECT_COLUMN_ID = "__select__";
|
|
|
19
19
|
* the selection off the render they were handed.
|
|
20
20
|
*
|
|
21
21
|
* A cell is rendered by `flexRender`, which mounts the cell function as its own
|
|
22
|
-
* component
|
|
22
|
+
* component - but the body cell above it keeps the same props across a
|
|
23
23
|
* selection change (row, column and layout identities all survive it), so the
|
|
24
24
|
* React Compiler reuses the memoized element and the subtree never re-renders.
|
|
25
25
|
* The row highlight would update, from state `TMDataGridTable` subscribes to,
|
|
@@ -59,7 +59,7 @@ function SelectAllCheckbox<TData extends RowData>({
|
|
|
59
59
|
* feature flags rather than `table.options.enableMultiRowSelection` directly:
|
|
60
60
|
* the flags are re-derived from a fresh object every render, so the switch
|
|
61
61
|
* cannot be cached along with a `table` identity that survives an options
|
|
62
|
-
* change
|
|
62
|
+
* change - the same reason the rest of the chrome reads them. See
|
|
63
63
|
* readFeatureFlags.
|
|
64
64
|
*/
|
|
65
65
|
function SelectAllHeader<TData extends RowData>({
|
|
@@ -78,10 +78,10 @@ function SelectRowCheckbox<TData extends RowData>({
|
|
|
78
78
|
row: Row<TMDataGridFeatures, TData>;
|
|
79
79
|
}) {
|
|
80
80
|
// Cells render inside the grid's provider, so the checkbox can reach the
|
|
81
|
-
// chrome store
|
|
81
|
+
// chrome store - it needs the shift-click pivot, and the feature flags to know
|
|
82
82
|
// which row model a range is measured over.
|
|
83
83
|
const { ui, features, labels } = useTMDataGridContext();
|
|
84
|
-
// Out of the tab order once the grid has a cell cursor
|
|
84
|
+
// Out of the tab order once the grid has a cell cursor - see
|
|
85
85
|
// useCellControlTabIndex. Enter on the lane still steps in, and Space on any
|
|
86
86
|
// cell of the row ticks it.
|
|
87
87
|
const tabIndex = useCellControlTabIndex();
|
|
@@ -90,7 +90,7 @@ function SelectRowCheckbox<TData extends RowData>({
|
|
|
90
90
|
// A group row is never selected by id: `rowSelection` only ever holds the
|
|
91
91
|
// leaves, and TanStack's `getIsSelected()` is a plain lookup in that map. So
|
|
92
92
|
// a group asks about its descendants instead, which is also the honest
|
|
93
|
-
// reading
|
|
93
|
+
// reading - the box means "all of these", and it goes indeterminate as soon
|
|
94
94
|
// as that stops being true.
|
|
95
95
|
const selected = useSelector(row.table.store, () =>
|
|
96
96
|
isGroupRow ? row.getIsAllSubRowsSelected() : row.getIsSelected(),
|
|
@@ -117,7 +117,7 @@ function SelectRowCheckbox<TData extends RowData>({
|
|
|
117
117
|
checked={selected}
|
|
118
118
|
disabled={selectableIds.length === 0}
|
|
119
119
|
indeterminate={someSelected && !selected}
|
|
120
|
-
// Every tick goes through the resolver, shift held or not
|
|
120
|
+
// Every tick goes through the resolver, shift held or not - plain becomes
|
|
121
121
|
// a toggle that moves the pivot, so a later shift-click extends from the
|
|
122
122
|
// box the user last touched.
|
|
123
123
|
//
|
|
@@ -138,7 +138,7 @@ function SelectRowCheckbox<TData extends RowData>({
|
|
|
138
138
|
extend: isMouse && native.shiftKey,
|
|
139
139
|
},
|
|
140
140
|
selection: row.table.store.state.rowSelection,
|
|
141
|
-
// A checkbox is only ever additive
|
|
141
|
+
// A checkbox is only ever additive - ticking one has never cleared
|
|
142
142
|
// the others, so `canReplaceSelection` stays false whatever is held.
|
|
143
143
|
canReplaceSelection: false,
|
|
144
144
|
});
|
|
@@ -168,7 +168,7 @@ export function createSelectColumn<TData extends RowData>(
|
|
|
168
168
|
enableOrdering: false,
|
|
169
169
|
},
|
|
170
170
|
// A system lane: as wide as the control it holds and no wider. Fixed at
|
|
171
|
-
// every scale
|
|
171
|
+
// every scale - the control does not grow with the font size, so neither
|
|
172
172
|
// should its track.
|
|
173
173
|
size: 36,
|
|
174
174
|
minSize: 36,
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/* The scrolled-under shadow: a soft band under the header, only while body
|
|
37
|
-
rows are actually beneath it. On the last header row
|
|
38
|
-
boundary
|
|
37
|
+
rows are actually beneath it. On the last header row - the header/body
|
|
38
|
+
boundary - not on every stacked group row. A scroll-driven animation, like
|
|
39
39
|
the pinned-lane gradients: the shadow tracks the scroll on the compositor
|
|
40
40
|
with no listener and no render, and an inactive timeline (nothing to
|
|
41
41
|
scroll) leaves `opacity: 0` standing, so a grid that fits shows nothing.
|
|
42
|
-
Where unsupported there is simply no shadow
|
|
42
|
+
Where unsupported there is simply no shadow - the header's border already
|
|
43
43
|
draws the boundary. */
|
|
44
44
|
.headerRow[data-dg-header-last]::after {
|
|
45
45
|
content: "";
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
/* A group row takes no background of its own. Collapsed, every row on screen is
|
|
98
98
|
a group row, so a tint would grey out the whole grid and read as if
|
|
99
99
|
everything were selected. The bold label and the chevron carry the
|
|
100
|
-
distinction instead
|
|
100
|
+
distinction instead - and `--dg-row-group-bg` is there for a consumer who
|
|
101
101
|
wants the tint back. Declared before the selection rules, so a selected or
|
|
102
102
|
highlighted group still reads as one. */
|
|
103
103
|
.bodyRow[data-grouped="true"] {
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
|
|
115
115
|
/* Being selected and being painted for it are separate: a row is always
|
|
116
116
|
`data-selected`, but only takes the background when `showSelectedBackground`
|
|
117
|
-
is on
|
|
117
|
+
is on - the default under `"row"`, off with checkboxes. */
|
|
118
118
|
.bodyRow[data-selected-bg="true"] {
|
|
119
119
|
--row-bg: var(--dg-row-selected-bg);
|
|
120
120
|
}
|
|
@@ -138,19 +138,19 @@
|
|
|
138
138
|
outline-offset: -2px;
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
/* Clipping lives on .cellContent, not here
|
|
141
|
+
/* Clipping lives on .cellContent, not here - a pinned cell has to let its
|
|
142
142
|
boundary gradient escape past its own right/left edge. */
|
|
143
143
|
.bodyCell {
|
|
144
144
|
display: flex;
|
|
145
145
|
align-items: center;
|
|
146
146
|
padding: 0 var(--dg-padding);
|
|
147
147
|
border-bottom: 1px solid var(--mantine-color-default-border);
|
|
148
|
-
/* Inherited from .bodyRow
|
|
148
|
+
/* Inherited from .bodyRow - sticky cells need an opaque background. */
|
|
149
149
|
background-color: var(--row-bg);
|
|
150
150
|
font-size: var(--dg-font-size);
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
/* A control lane
|
|
153
|
+
/* A control lane - the checkbox, the details chevron - is a fixed 36px track
|
|
154
154
|
holding a control of a known width, not text that can ellipsize. Cell padding
|
|
155
155
|
is sized for text and grows with the scale, so at `xl` its 18px a side left
|
|
156
156
|
12px for a 16px box and the checkbox was clipped. The lane centres its
|
|
@@ -185,8 +185,8 @@
|
|
|
185
185
|
positioned against a scrolling grid with sticky lanes in it.
|
|
186
186
|
|
|
187
187
|
Four shadows are always laid down and each is transparent until its edge
|
|
188
|
-
says otherwise. `box-shadow` does not accumulate across rules
|
|
189
|
-
declaration replaces the first
|
|
188
|
+
says otherwise. `box-shadow` does not accumulate across rules - a second
|
|
189
|
+
declaration replaces the first - so the alternative is one rule per corner
|
|
190
190
|
combination, and a cell can be on any of fifteen of them. */
|
|
191
191
|
.bodyCell[data-selected="true"] {
|
|
192
192
|
--dg-edge-top: transparent;
|
|
@@ -219,7 +219,7 @@
|
|
|
219
219
|
/* The cell the keyboard is on, under `cellSelection`.
|
|
220
220
|
|
|
221
221
|
Painted from `data-focused` rather than `:focus-visible`, because the ring
|
|
222
|
-
has to stay while the focus steps into a control inside the cell
|
|
222
|
+
has to stay while the focus steps into a control inside the cell - that is
|
|
223
223
|
still where the arrow keys resume from. The offset keeps it inside the
|
|
224
224
|
cell's own box, so a pinned neighbour cannot clip it. */
|
|
225
225
|
.bodyCell[data-focused="true"] {
|
|
@@ -275,7 +275,7 @@
|
|
|
275
275
|
border-right-color: var(--mantine-primary-color-filled);
|
|
276
276
|
}
|
|
277
277
|
|
|
278
|
-
/* Invalid wins over dirty
|
|
278
|
+
/* Invalid wins over dirty - a cell is usually both. */
|
|
279
279
|
.bodyCell[data-invalid]::after {
|
|
280
280
|
border-top-color: var(--mantine-color-error);
|
|
281
281
|
border-right-color: var(--mantine-color-error);
|
|
@@ -295,7 +295,7 @@
|
|
|
295
295
|
}
|
|
296
296
|
|
|
297
297
|
/* The panel an expanded row opens. Its own grid row inside .bodyRow, spanning
|
|
298
|
-
every column track
|
|
298
|
+
every column track - so it is measured together with the row above it.
|
|
299
299
|
|
|
300
300
|
It takes `--row-bg` rather than a colour of its own: the panel belongs to its
|
|
301
301
|
row, and a selected or highlighted row whose panel stayed white would read as
|
|
@@ -330,7 +330,7 @@
|
|
|
330
330
|
}
|
|
331
331
|
|
|
332
332
|
/* Marked deleted under batch: struck through and inert until submitAll
|
|
333
|
-
reports it. Interaction off wholesale
|
|
333
|
+
reports it. Interaction off wholesale - a row about to go away must not
|
|
334
334
|
keep taking edits. */
|
|
335
335
|
.bodyRow[data-deleted="true"] {
|
|
336
336
|
text-decoration: line-through;
|
|
@@ -338,7 +338,7 @@
|
|
|
338
338
|
pointer-events: none;
|
|
339
339
|
}
|
|
340
340
|
|
|
341
|
-
/* The entry block
|
|
341
|
+
/* The entry block - one row per edit.addRow(), under the header on the same
|
|
342
342
|
subgrid tracks as everything else. The *block* is the sticky element, not
|
|
343
343
|
the rows: sticky siblings would all compete for the same `top` and stack
|
|
344
344
|
onto one spot, while a single sticky wrapper lets its rows flow normally
|
|
@@ -359,7 +359,7 @@
|
|
|
359
359
|
grid-template-columns: subgrid;
|
|
360
360
|
}
|
|
361
361
|
|
|
362
|
-
/* The pinned edge blocks
|
|
362
|
+
/* The pinned edge blocks - user-pinned rows held at the top or bottom of the
|
|
363
363
|
body, on the entry block's sticky mechanics: the block is the sticky
|
|
364
364
|
element, its rows flow normally inside it. The top block stacks under the
|
|
365
365
|
entry block when both exist; `--dg-entry-height` is measured only then, so
|
|
@@ -417,7 +417,7 @@
|
|
|
417
417
|
|
|
418
418
|
/* The matched slice of a cell's text, while `enableMatchHighlighting` is on
|
|
419
419
|
and a contains-family filter or the quick search is active. `mark` resets
|
|
420
|
-
the browser's default so the colour is the grid's to state
|
|
420
|
+
the browser's default so the colour is the grid's to state - override with
|
|
421
421
|
`--dg-match-highlight-bg` on the grid. */
|
|
422
422
|
.matchHighlight {
|
|
423
423
|
background-color: var(
|
|
@@ -428,7 +428,7 @@
|
|
|
428
428
|
border-radius: 2px;
|
|
429
429
|
}
|
|
430
430
|
|
|
431
|
-
/* The summary row
|
|
431
|
+
/* The summary row - one sticky row of column footers along the bottom edge,
|
|
432
432
|
rendered only while at least one column defines `footer`. Same subgrid
|
|
433
433
|
placement as the header, so its cells sit exactly on the body's tracks. */
|
|
434
434
|
.summaryRow {
|