@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.
Files changed (78) hide show
  1. package/README.md +8 -8
  2. package/dist/index.d.ts +225 -225
  3. package/dist/index.js +58 -50
  4. package/dist/index.js.map +1 -1
  5. package/dist/styles.css +1 -1
  6. package/package.json +3 -2
  7. package/skills/appearance/SKILL.md +322 -0
  8. package/skills/cell-selection/SKILL.md +240 -0
  9. package/skills/columns/SKILL.md +261 -86
  10. package/skills/data/SKILL.md +289 -0
  11. package/skills/editing/SKILL.md +492 -0
  12. package/skills/editing/references/editing-api.md +124 -0
  13. package/skills/editing/references/editors-and-validation.md +198 -0
  14. package/skills/filtering/SKILL.md +344 -0
  15. package/skills/getting-started/SKILL.md +48 -27
  16. package/skills/grouping/SKILL.md +264 -0
  17. package/skills/options/SKILL.md +31 -20
  18. package/skills/rows/SKILL.md +369 -0
  19. package/skills/rows/references/rows-api.md +117 -0
  20. package/skills/server-side/SKILL.md +7 -7
  21. package/skills/testing/SKILL.md +12 -12
  22. package/src/tmdatagrid/TMDataGridContext.ts +2 -2
  23. package/src/tmdatagrid/components/TMDataGrid.module.css +2 -2
  24. package/src/tmdatagrid/components/TMDataGrid.tsx +5 -5
  25. package/src/tmdatagrid/components/TMDataGridCellEditor.tsx +4 -4
  26. package/src/tmdatagrid/components/TMDataGridColumnsPanel.tsx +2 -2
  27. package/src/tmdatagrid/components/TMDataGridDetailsColumn.tsx +6 -6
  28. package/src/tmdatagrid/components/TMDataGridEditActions.tsx +2 -2
  29. package/src/tmdatagrid/components/TMDataGridEditColumn.tsx +4 -4
  30. package/src/tmdatagrid/components/TMDataGridEntryRows.tsx +6 -6
  31. package/src/tmdatagrid/components/TMDataGridFilterPanel.tsx +6 -6
  32. package/src/tmdatagrid/components/TMDataGridFilterPills.module.css +2 -2
  33. package/src/tmdatagrid/components/TMDataGridFilterPills.tsx +1 -1
  34. package/src/tmdatagrid/components/TMDataGridFooter.module.css +1 -1
  35. package/src/tmdatagrid/components/TMDataGridFooter.tsx +12 -6
  36. package/src/tmdatagrid/components/TMDataGridGroupColumn.module.css +1 -1
  37. package/src/tmdatagrid/components/TMDataGridGroupColumn.tsx +5 -5
  38. package/src/tmdatagrid/components/TMDataGridHeaderCell.module.css +8 -8
  39. package/src/tmdatagrid/components/TMDataGridHeaderCell.tsx +12 -12
  40. package/src/tmdatagrid/components/TMDataGridRowNumberColumn.tsx +4 -4
  41. package/src/tmdatagrid/components/TMDataGridSearch.tsx +5 -5
  42. package/src/tmdatagrid/components/TMDataGridSelectColumn.tsx +8 -8
  43. package/src/tmdatagrid/components/TMDataGridTable.module.css +18 -18
  44. package/src/tmdatagrid/components/TMDataGridTable.tsx +116 -116
  45. package/src/tmdatagrid/components/TMDataGridToolbar.tsx +5 -5
  46. package/src/tmdatagrid/components/editors/TMDataGridBooleanEditor.tsx +1 -1
  47. package/src/tmdatagrid/components/editors/TMDataGridDateEditor.tsx +2 -2
  48. package/src/tmdatagrid/components/editors/TMDataGridMultiSelectEditor.tsx +1 -1
  49. package/src/tmdatagrid/components/editors/TMDataGridNumberEditor.tsx +1 -1
  50. package/src/tmdatagrid/components/editors/TMDataGridSelectEditor.tsx +2 -2
  51. package/src/tmdatagrid/components/editors/editorShared.ts +3 -3
  52. package/src/tmdatagrid/components/filters/DgDateRangeFilter.tsx +1 -1
  53. package/src/tmdatagrid/components/filters/DgRangeSliderFilter.tsx +1 -1
  54. package/src/tmdatagrid/components/filters/DgTriStateFilter.tsx +1 -1
  55. package/src/tmdatagrid/components/filters/TMDataGridFilterValueInput.tsx +2 -2
  56. package/src/tmdatagrid/components/sticky.module.css +8 -8
  57. package/src/tmdatagrid/core/autosize.ts +4 -4
  58. package/src/tmdatagrid/core/capabilities.ts +17 -17
  59. package/src/tmdatagrid/core/cellExport.ts +13 -13
  60. package/src/tmdatagrid/core/cellNavigation.ts +6 -6
  61. package/src/tmdatagrid/core/cellRange.ts +4 -4
  62. package/src/tmdatagrid/core/columnOptions.ts +2 -2
  63. package/src/tmdatagrid/core/columnOrdering.ts +2 -2
  64. package/src/tmdatagrid/core/columnUtils.ts +3 -3
  65. package/src/tmdatagrid/core/editEngine.ts +49 -49
  66. package/src/tmdatagrid/core/expanding.ts +5 -5
  67. package/src/tmdatagrid/core/filterControls.ts +5 -5
  68. package/src/tmdatagrid/core/filterOperators.ts +14 -14
  69. package/src/tmdatagrid/core/labels.ts +8 -8
  70. package/src/tmdatagrid/core/matchHighlight.ts +4 -4
  71. package/src/tmdatagrid/core/persistence.ts +8 -8
  72. package/src/tmdatagrid/core/quickSearch.ts +8 -8
  73. package/src/tmdatagrid/core/rowPinning.ts +3 -3
  74. package/src/tmdatagrid/core/rowSelection.ts +12 -12
  75. package/src/tmdatagrid/core/sizes.ts +1 -1
  76. package/src/tmdatagrid/core/summary.ts +3 -3
  77. package/src/tmdatagrid/useTMDataGrid.tsx +79 -79
  78. package/skills/features/SKILL.md +0 -352
@@ -55,8 +55,8 @@ export type TMDataGridSettingsSlice = (typeof SETTINGS_STATE_SLICES)[number];
55
55
  /**
56
56
  * A storage key, optionally narrowed to a subset of its group's slices.
57
57
  *
58
- * - `"employees.data"` — persists every slice in the group.
59
- * - `["employees.data", ["sorting"]]` — persists only the listed slices.
58
+ * - `"employees.data"` - persists every slice in the group.
59
+ * - `["employees.data", ["sorting"]]` - persists only the listed slices.
60
60
  */
61
61
  export type TMDataGridPersistKey<TSlice extends string> =
62
62
  | string
@@ -83,7 +83,7 @@ export type TMDataGridPersistence = {
83
83
  * collide with. A payload whose version does not match is dropped whole: a
84
84
  * migration would be guessing at a shape this code no longer knows, and the
85
85
  * cost of dropping is one lost layout. Payloads written before versioning
86
- * existed (≤0.4.0) have no stamp and are dropped the same way — the 1.0
86
+ * existed (≤0.4.0) have no stamp and are dropped the same way - the 1.0
87
87
  * wave's one-time break, named in its changeset.
88
88
  */
89
89
  export const PERSIST_PAYLOAD_VERSION = 1;
@@ -163,7 +163,7 @@ const SLICE_GUARDS: Record<
163
163
  (value: unknown) => boolean
164
164
  > = {
165
165
  columnFilters: (value) => isArrayOf(value, hasStringId),
166
- // TanStack leaves the global filter value untyped — the grid's own default
166
+ // TanStack leaves the global filter value untyped - the grid's own default
167
167
  // filters on a string, but a consumer may store anything here.
168
168
  globalFilter: () => true,
169
169
  sorting: (value) =>
@@ -266,7 +266,7 @@ const defaultSerialize = (value: Partial<GridState>): string =>
266
266
  * The leaf column ids a set of column defs will produce, by TanStack's own
267
267
  * derivation: `id`, else `accessorKey` with dots replaced by underscores,
268
268
  * else a string `header`. Mirrored here so restored state can be realigned
269
- * against the columns that will actually exist — deriving ids any other way
269
+ * against the columns that will actually exist - deriving ids any other way
270
270
  * would realign against names the table never uses.
271
271
  */
272
272
  export function collectLeafColumnIds(
@@ -295,7 +295,7 @@ export function collectLeafColumnIds(
295
295
  * Drops restored entries that name columns the grid no longer has.
296
296
  *
297
297
  * A stored layout outlives the column set: a column removed between deploys
298
- * would otherwise linger forever — a ghost id in the order, a width for
298
+ * would otherwise linger forever - a ghost id in the order, a width for
299
299
  * nothing, and worse, a *filter or sort that is active but has no column to
300
300
  * show for itself*. New columns need no counterpart here: TanStack appends
301
301
  * columns missing from `columnOrder` on its own, in definition order.
@@ -337,8 +337,8 @@ function realignToColumns(
337
337
  /**
338
338
  * State to merge into `initialState`, read once on mount.
339
339
  *
340
- * With `knownColumnIds` — every id the grid is about to construct, generated
341
- * lanes included — the column-shaped slices are realigned first; see
340
+ * With `knownColumnIds` - every id the grid is about to construct, generated
341
+ * lanes included - the column-shaped slices are realigned first; see
342
342
  * {@link realignToColumns}. Without it the payload is returned as stored.
343
343
  */
344
344
  export function readPersistedState(
@@ -12,11 +12,11 @@ import {
12
12
  type TableFeatures,
13
13
  } from "@tanstack/react-table";
14
14
 
15
- /** How the quick search matches — see `quickSearchMode` on the hook options. */
15
+ /** How the quick search matches - see `quickSearchMode` on the hook options. */
16
16
  export type TMDataGridQuickSearchMode = "fuzzy" | "contains";
17
17
 
18
18
  /**
19
- * The fuzzy filter's registry name — what `globalFilterFn` resolves to while
19
+ * The fuzzy filter's registry name - what `globalFilterFn` resolves to while
20
20
  * `quickSearchMode` is `"fuzzy"`. The rank ordering keys off this name, so an
21
21
  * explicit `globalFilterFn` override switches the ordering off with it.
22
22
  */
@@ -37,8 +37,8 @@ function isFuzzyFilterMeta(value: unknown): value is FuzzyFilterMeta {
37
37
 
38
38
  /**
39
39
  * Match-sorter ranking as the global filter: a row passes when a globally
40
- * filterable column ranks above match-sorter's threshold — typos and skipped
41
- * characters forgiven — and the rank is recorded for the ordering to read.
40
+ * filterable column ranks above match-sorter's threshold - typos and skipped
41
+ * characters forgiven - and the rank is recorded for the ordering to read.
42
42
  *
43
43
  * TanStack stops probing a row's columns at the first passing one, so the
44
44
  * recorded ranks cover the columns up to and including it; the best of those
@@ -81,7 +81,7 @@ function bestRank<TFeatures extends TableFeatures, TData extends RowData>(
81
81
 
82
82
  /**
83
83
  * Whether the ranked ordering applies: the fuzzy quick search is narrowing
84
- * the grid, and nothing else claims an order — no sort, no grouping.
84
+ * the grid, and nothing else claims an order - no sort, no grouping.
85
85
  */
86
86
  function isRankingActive<TFeatures extends TableFeatures, TData extends RowData>(
87
87
  table: Table<TFeatures, TData>,
@@ -106,7 +106,7 @@ function isRankingActive<TFeatures extends TableFeatures, TData extends RowData>
106
106
 
107
107
  /**
108
108
  * The sorted row model, with one addition: while {@link isRankingActive},
109
- * rows order by match quality, best first. Declarative — the ordering is
109
+ * rows order by match quality, best first. Declarative - the ordering is
110
110
  * derived from filter state, never written into `sorting`, so no column
111
111
  * claims `aria-sort`, the persisted slice stays untouched, and the user's
112
112
  * next sort click suspends it just by existing.
@@ -121,8 +121,8 @@ export function createFuzzyRankedSortedRowModel<
121
121
  const base = createSortedRowModel<TFeatures, TData>();
122
122
  return (table) => {
123
123
  const getSorted = base(table);
124
- // One-slot memo: every input of the ordering — filter text, data, the
125
- // sorting and grouping states — changes the sorted model's identity, so
124
+ // One-slot memo: every input of the ordering - filter text, data, the
125
+ // sorting and grouping states - changes the sorted model's identity, so
126
126
  // the model alone is the cache key.
127
127
  let lastModel: RowModel<TFeatures, TData> | null = null;
128
128
  let ranked: RowModel<TFeatures, TData> | null = null;
@@ -5,7 +5,7 @@ import type { TMDataGridFeatures, TMDataGridTable } from "../useTMDataGrid";
5
5
  * The rows pinned to one edge, resolved safely and in pin order.
6
6
  *
7
7
  * Not TanStack's `getTopRows()`: that resolves each pinned id with
8
- * `getRow(id, true)`, which throws once the row's data is gone — and pinned
8
+ * `getRow(id, true)`, which throws once the row's data is gone - and pinned
9
9
  * ids outlive data. A delete, a server-side page swap, a refetch that comes
10
10
  * back without the row: any of these would take the whole grid down. Here a
11
11
  * stale id is skipped instead; it stays in state, harmless, and the row
@@ -13,8 +13,8 @@ import type { TMDataGridFeatures, TMDataGridTable } from "../useTMDataGrid";
13
13
  *
14
14
  * The semantics are TanStack's `keepPinnedRows: true`: a pinned row stays at
15
15
  * its edge even when a filter or the pager would have dropped it from the
16
- * body. Ids resolve against the pre-pagination model first — those rows carry
17
- * the live sort and filter context — with the core model as the fallback for
16
+ * body. Ids resolve against the pre-pagination model first - those rows carry
17
+ * the live sort and filter context - with the core model as the fallback for
18
18
  * rows the filters removed. A leaf whose group is collapsed stays hidden,
19
19
  * as upstream does.
20
20
  */
@@ -5,17 +5,17 @@ import type { TMDataGridFeatures, TMDataGridTable } from "../useTMDataGrid";
5
5
 
6
6
  /**
7
7
  * Rows in the order they are displayed, which is the order a shift-click range
8
- * is measured over — so a range follows the active sort and skips filtered-out
8
+ * is measured over - so a range follows the active sort and skips filtered-out
9
9
  * rows. Under pagination it is the current page, so a range cannot cross a page
10
10
  * boundary.
11
11
  *
12
12
  * Once a column is grouped this includes the group rows, and only the leaves of
13
- * groups that are open — and paging is suspended, so it is the whole tree. That
13
+ * groups that are open - and paging is suspended, so it is the whole tree. That
14
14
  * is the right list for a range: it is what the user can see, and a range that
15
15
  * swept collapsed rows would select things off screen. What a group row in the
16
16
  * range contributes is decided by {@link getSelectableRowIds}.
17
17
  *
18
- * Rows pinned to an edge leave this list — they render in their own sticky
18
+ * Rows pinned to an edge leave this list - they render in their own sticky
19
19
  * blocks, outside the scrolling order a shift-click range or the virtualizer
20
20
  * walks. See `readPinnedRows`.
21
21
  */
@@ -42,7 +42,7 @@ export function getDisplayedRows<TData extends RowData>(
42
42
  * to go looking for, and counting only the top-level rows quietly redefines
43
43
  * "rows per page" as groups per page, so a page of 25 can hold thousands of
44
44
  * rows. Rather than pick, the grid renders the whole tree and leans on the
45
- * virtualizer — which is its default mode anyway, pagination being opt-in.
45
+ * virtualizer - which is its default mode anyway, pagination being opt-in.
46
46
  *
47
47
  * `TMDataGrid.Footer` reads this too, and greys the pager out rather than
48
48
  * hiding it, so the pager going quiet is visible instead of mysterious.
@@ -56,7 +56,7 @@ export function isPagingActive<TData extends RowData>(
56
56
 
57
57
  /**
58
58
  * Which modifiers were held. Named for what they mean rather than for the keys,
59
- * because the keys differ per platform — `toggle` is Ctrl on Windows/Linux and
59
+ * because the keys differ per platform - `toggle` is Ctrl on Windows/Linux and
60
60
  * Cmd on macOS.
61
61
  */
62
62
  export type TMDataGridRowClickModifiers = {
@@ -65,7 +65,7 @@ export type TMDataGridRowClickModifiers = {
65
65
  };
66
66
 
67
67
  export type ResolveRowSelectionClickArgs<TData extends RowData> = {
68
- /** Displayed order — see {@link getDisplayedRows}. */
68
+ /** Displayed order - see {@link getDisplayedRows}. */
69
69
  rows: ReadonlyArray<Row<TMDataGridFeatures, TData>>;
70
70
  rowId: string;
71
71
  /** The pivot a shift-click extends from. */
@@ -76,7 +76,7 @@ export type ResolveRowSelectionClickArgs<TData extends RowData> = {
76
76
  * Whether this gesture is allowed to clear rows it did not touch.
77
77
  *
78
78
  * `true` for a bare row click, where replacing is the whole point. `false` for
79
- * a checkbox, which is only ever additive — ticking one box has never cleared
79
+ * a checkbox, which is only ever additive - ticking one box has never cleared
80
80
  * the others, and shift-clicking one adds the range rather than becoming it.
81
81
  */
82
82
  canReplaceSelection: boolean;
@@ -138,7 +138,7 @@ export function resolveRowSelectionClick<TData extends RowData>({
138
138
  }: ResolveRowSelectionClickArgs<TData>): ResolvedRowSelection {
139
139
  const index = rows.findIndex((row) => row.id === rowId);
140
140
  const clickedRow = rows[index];
141
- // Clicked row is not in the displayed set — nothing sensible to resolve.
141
+ // Clicked row is not in the displayed set - nothing sensible to resolve.
142
142
  if (index === -1 || clickedRow === undefined) return { selection, anchorRowId };
143
143
 
144
144
  const targets = getSelectableRowIds(clickedRow);
@@ -152,7 +152,7 @@ export function resolveRowSelectionClick<TData extends RowData>({
152
152
  //
153
153
  // This has to be enforced here. Rebuilding the map and handing it to
154
154
  // `setRowSelection` skips `mutateRowIsSelected`, which is where TanStack
155
- // clears the other rows — so without this, Ctrl and Shift would quietly
155
+ // clears the other rows - so without this, Ctrl and Shift would quietly
156
156
  // produce the multi-selection the option ruled out.
157
157
  if (!clickedRow.getCanMultiSelect()) {
158
158
  // A group stands for several rows, which single-select cannot express. The
@@ -179,12 +179,12 @@ export function resolveRowSelectionClick<TData extends RowData>({
179
179
  const from = Math.min(anchorIndex, index);
180
180
  const to = Math.max(anchorIndex, index);
181
181
  // Ctrl+Shift adds to what is already selected; Shift alone becomes the
182
- // range — unless the gesture may not replace, in which case it also adds.
182
+ // range - unless the gesture may not replace, in which case it also adds.
183
183
  const next: RowSelectionState =
184
184
  modifiers.toggle || !canReplaceSelection ? { ...selection } : {};
185
185
  for (const row of rows.slice(from, to + 1)) {
186
186
  // A group row inside the range brings its whole subtree, including leaves
187
- // that are collapsed out of `rows` — sweeping past a closed group selects
187
+ // that are collapsed out of `rows` - sweeping past a closed group selects
188
188
  // it entire, which is the only reading that matches what it displays.
189
189
  for (const id of getSelectableRowIds(row)) next[id] = true;
190
190
  }
@@ -195,7 +195,7 @@ export function resolveRowSelectionClick<TData extends RowData>({
195
195
  if (modifiers.toggle || !canReplaceSelection) {
196
196
  const next: RowSelectionState = { ...selection };
197
197
  // Asked of the targets rather than of `rowId`: a group row carries no id in
198
- // the map, so it counts as selected exactly when all of its leaves do —
198
+ // the map, so it counts as selected exactly when all of its leaves do -
199
199
  // which is also when its checkbox shows a tick rather than a dash.
200
200
  const allSelected = targets.every((id) => selection[id] === true);
201
201
  for (const id of targets) {
@@ -7,7 +7,7 @@ export const DEFAULT_TMDATAGRID_SIZE: TMDataGridSize = "md";
7
7
  /**
8
8
  * Row height per size, in px.
9
9
  *
10
- * The virtualizer needs this as a number — it cannot read the CSS variable —
10
+ * The virtualizer needs this as a number - it cannot read the CSS variable -
11
11
  * so the scale lives here and `TMDataGrid.module.css` mirrors it. `meta.rowHeight`
12
12
  * overrides it when a grid needs a height the scale doesn't offer.
13
13
  */
@@ -2,11 +2,11 @@ import { aggregationFns, type RowData } from "@tanstack/react-table";
2
2
  import type { TMDataGridRowData } from "../TMDataGridContext";
3
3
  import type { TMDataGridTable } from "../useTMDataGrid";
4
4
 
5
- /** The registered aggregation names — the same set `aggregationFn` accepts. */
5
+ /** The registered aggregation names - the same set `aggregationFn` accepts. */
6
6
  export type TMDataGridAggregationName = keyof typeof aggregationFns;
7
7
 
8
8
  /**
9
- * One column aggregated over every filtered row — the number a summary-row
9
+ * One column aggregated over every filtered row - the number a summary-row
10
10
  * `footer` wants:
11
11
  *
12
12
  * ```tsx
@@ -16,7 +16,7 @@ export type TMDataGridAggregationName = keyof typeof aggregationFns;
16
16
  * ```
17
17
  *
18
18
  * Filtered rather than paginated rows, so the total covers everything the
19
- * filters left — all pages — and follows the filters as they change. Reuses
19
+ * filters left (all pages), and follows the filters as they change. Reuses
20
20
  * TanStack's registered aggregation functions; `fn` defaults to `"sum"`.
21
21
  */
22
22
  export function aggregateColumn<TData extends RowData>({