@jielga/tmdatagrid 2.3.0 → 2.5.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.
Files changed (43) hide show
  1. package/dist/index.d.ts +289 -9
  2. package/dist/index.js +1418 -1280
  3. package/dist/index.js.map +1 -1
  4. package/docs/columns.md +8 -0
  5. package/docs/editors.md +31 -0
  6. package/docs/filtering.md +2 -1
  7. package/docs/grouping.md +1 -1
  8. package/docs/localization.md +3 -3
  9. package/docs/persistence.md +88 -0
  10. package/docs/typed-deep-links.md +169 -0
  11. package/package.json +1 -1
  12. package/skills/appearance/SKILL.md +1 -1
  13. package/skills/appearance/references/labels.md +3 -3
  14. package/skills/cell-selection/SKILL.md +1 -1
  15. package/skills/columns/SKILL.md +5 -2
  16. package/skills/columns/references/columns-api.md +1 -0
  17. package/skills/data/SKILL.md +1 -1
  18. package/skills/editing/SKILL.md +15 -2
  19. package/skills/editing/references/editing-api.md +2 -1
  20. package/skills/editing/references/editors-and-validation.md +24 -0
  21. package/skills/filtering/SKILL.md +3 -2
  22. package/skills/getting-started/SKILL.md +2 -2
  23. package/skills/grouping/SKILL.md +2 -2
  24. package/skills/migrating-to-2/SKILL.md +1 -1
  25. package/skills/options/SKILL.md +30 -6
  26. package/skills/options/references/typed-links.md +134 -0
  27. package/skills/rows/SKILL.md +1 -1
  28. package/skills/server-side/SKILL.md +1 -1
  29. package/skills/testing/SKILL.md +1 -1
  30. package/skills/testing-components/SKILL.md +1 -1
  31. package/skills/testing-editing/SKILL.md +1 -1
  32. package/src/components/TMDataGridFilterPills.tsx +15 -1
  33. package/src/components/TMDataGridGroupColumn.tsx +19 -4
  34. package/src/components/TMDataGridHeaderFilterRow.tsx +7 -1
  35. package/src/core/editEngine.ts +101 -5
  36. package/src/core/filterOperators.ts +41 -18
  37. package/src/core/grouping.ts +11 -3
  38. package/src/core/labels.ts +4 -3
  39. package/src/core/persistence.ts +9 -1
  40. package/src/core/urlState.ts +439 -0
  41. package/src/core/valueText.ts +46 -0
  42. package/src/index.ts +15 -0
  43. package/src/useTMDataGrid.tsx +51 -8
@@ -0,0 +1,46 @@
1
+ import type { TMDataGridOption } from "./columnOptions";
2
+ import type { TMDataGridColumnType } from "./filterOperators";
3
+ import type { TMDataGridLabels } from "./labels";
4
+
5
+ /** The English boolean labels - the defaults `TMDATAGRID_LABELS_EN` takes. */
6
+ export const BOOLEAN_LABELS_EN = {
7
+ booleanTrue: "Yes",
8
+ booleanFalse: "No",
9
+ } as const satisfies Pick<TMDataGridLabels, "booleanTrue" | "booleanFalse">;
10
+
11
+ export type TMDataGridValueTextOptions = {
12
+ /** The column's `meta.type`. A `boolean` column's `"true"` / `"false"` filter strings read as booleans. */
13
+ type?: TMDataGridColumnType;
14
+ /** The column's resolved options: a value with an option reads as its label. */
15
+ options?: ReadonlyArray<TMDataGridOption>;
16
+ /** What `true` and `false` read as. Defaults to English. */
17
+ labels?: Pick<TMDataGridLabels, "booleanTrue" | "booleanFalse">;
18
+ };
19
+
20
+ /**
21
+ * A value as the grid's chrome writes it in words - on a filter pill, in a
22
+ * group row - rather than `String(value)`, which writes `true`, an option's
23
+ * key instead of its label, and a `Date` as an English timestamp.
24
+ */
25
+ export function formatValueText(
26
+ value: unknown,
27
+ { type, options, labels = BOOLEAN_LABELS_EN }: TMDataGridValueTextOptions = {},
28
+ ): string {
29
+ if (Array.isArray(value)) {
30
+ return value
31
+ .map((entry) => formatValueText(entry, { type, options, labels }))
32
+ .join(", ");
33
+ }
34
+ if (value === true || (type === "boolean" && value === "true")) {
35
+ return labels.booleanTrue;
36
+ }
37
+ if (value === false || (type === "boolean" && value === "false")) {
38
+ return labels.booleanFalse;
39
+ }
40
+ if (value instanceof Date) {
41
+ return Number.isNaN(value.getTime()) ? "" : value.toLocaleDateString();
42
+ }
43
+ const text = String(value);
44
+ const option = options?.find((candidate) => candidate.value === text);
45
+ return option?.label ?? text;
46
+ }
package/src/index.ts CHANGED
@@ -110,6 +110,8 @@ export {
110
110
  type TMDataGridEditRowProjection,
111
111
  type TMDataGridEditRowSnapshot,
112
112
  type TMDataGridEditState,
113
+ type TMDataGridEditCommitMap,
114
+ type TMDataGridEditCommitMapArgs,
113
115
  type TMDataGridEditValueMap,
114
116
  type TMDataGridEditValueMapArgs,
115
117
  type TMDataGridFieldValidate,
@@ -264,6 +266,19 @@ export {
264
266
  type TMDataGridStorageMode,
265
267
  type TMDataGridUrlStorage,
266
268
  } from "./core/persistence";
269
+ export {
270
+ createTMDataGridUrlState,
271
+ type TMDataGridColumnInfo,
272
+ type TMDataGridColumnInfoOf,
273
+ type TMDataGridDateInput,
274
+ type TMDataGridTypedColumn,
275
+ type TMDataGridUrlFiltersInput,
276
+ type TMDataGridUrlInput,
277
+ type TMDataGridUrlPayload,
278
+ type TMDataGridUrlSearchStorage,
279
+ type TMDataGridUrlSortableId,
280
+ type TMDataGridUrlState,
281
+ } from "./core/urlState";
267
282
  export type {
268
283
  TMDataGridCellEventArgs,
269
284
  TMDataGridRowContextMenuArgs,
@@ -77,6 +77,7 @@ import {
77
77
  import {
78
78
  emptyValueForOperator,
79
79
  type TMDataGridColumnType,
80
+ type TMDataGridFilterOperator,
80
81
  tmDataGridFilterFn,
81
82
  } from "./core/filterOperators";
82
83
  import {
@@ -137,6 +138,12 @@ import {
137
138
  type TMDataGridQueryTable,
138
139
  } from "./core/pageReset";
139
140
  import type { TMDataGridCellRange } from "./core/cellRange";
141
+ import type {
142
+ TMDataGridAccessorColumnId,
143
+ TMDataGridColumnInfoHints,
144
+ TMDataGridColumnInfoOf,
145
+ TMDataGridTypedColumn,
146
+ } from "./core/urlState";
140
147
  import {
141
148
  resolveExportOptions,
142
149
  type TMDataGridExportOptions,
@@ -361,6 +368,13 @@ type WithRowTypedMeta<TDef, TData extends RowData> = TDef extends unknown
361
368
  * TanStack's column helper with `meta` typed against `TData`, so the
362
369
  * `meta.options` and `meta.edit.enabled` callbacks receive
363
370
  * `Row<TMDataGridFeatures, TData>`.
371
+ *
372
+ * Every column it returns also carries `TMDataGridColumnInfo` in its type,
373
+ * read from the literal values of `id`, `meta.type`,
374
+ * `meta.filter.operators`, `meta.filter.url`, `enableColumnFilter` and
375
+ * `enableSorting`. `createTMDataGridUrlState` reads it to type the links into
376
+ * the grid. TanStack's own return type keeps none of this: it types
377
+ * `accessorKey` as a plain string.
364
378
  */
365
379
  export type TMDataGridColumnHelper<TData extends RowData> = {
366
380
  accessor: <
@@ -370,6 +384,12 @@ export type TMDataGridColumnHelper<TData extends RowData> = {
370
384
  : TAccessor extends DeepKeys<TData>
371
385
  ? DeepValue<TData, TAccessor>
372
386
  : never,
387
+ const TId extends string = never,
388
+ TType extends TMDataGridColumnType = "string",
389
+ TOperator extends TMDataGridFilterOperator = TMDataGridFilterOperator,
390
+ TFilterable extends boolean = true,
391
+ TSortable extends boolean = true,
392
+ TUrl extends boolean = true,
373
393
  >(
374
394
  accessor: TAccessor,
375
395
  column: WithRowTypedMeta<
@@ -377,20 +397,43 @@ export type TMDataGridColumnHelper<TData extends RowData> = {
377
397
  ? DisplayColumnDef<TMDataGridFeatures, TData, TValue>
378
398
  : IdentifiedColumnDef<TMDataGridFeatures, TData, TValue>,
379
399
  TData
380
- >,
381
- ) => TAccessor extends AccessorFn<TData>
400
+ > &
401
+ TMDataGridColumnInfoHints<
402
+ TId,
403
+ TType,
404
+ TOperator,
405
+ TFilterable,
406
+ TSortable,
407
+ TUrl
408
+ >,
409
+ ) => (TAccessor extends AccessorFn<TData>
382
410
  ? AccessorFnColumnDef<TMDataGridFeatures, TData, TValue>
383
- : AccessorKeyColumnDef<TMDataGridFeatures, TData, TValue>;
411
+ : AccessorKeyColumnDef<TMDataGridFeatures, TData, TValue>) &
412
+ TMDataGridTypedColumn<{
413
+ id: TMDataGridAccessorColumnId<TAccessor, TId>;
414
+ type: TType;
415
+ value: TValue;
416
+ operators: TOperator;
417
+ filterable: TFilterable;
418
+ sortable: TSortable;
419
+ url: TUrl;
420
+ }>;
384
421
  columns: ColumnHelper<TMDataGridFeatures, TData>["columns"];
385
422
  display: (
386
423
  column: WithRowTypedMeta<DisplayColumnDef<TMDataGridFeatures, TData>, TData>,
387
424
  ) => DisplayColumnDef<TMDataGridFeatures, TData, unknown>;
388
- group: (
425
+ /** A header group. Carries the column info of every column under it. */
426
+ group: <
427
+ const TChildren extends ReadonlyArray<
428
+ ColumnDef<TMDataGridFeatures, TData, any>
429
+ >,
430
+ >(
389
431
  column: WithRowTypedMeta<
390
- GroupColumnDef<TMDataGridFeatures, TData, unknown>,
432
+ Omit<GroupColumnDef<TMDataGridFeatures, TData, unknown>, "columns">,
391
433
  TData
392
- >,
393
- ) => GroupColumnDef<TMDataGridFeatures, TData, unknown>;
434
+ > & { columns: TChildren },
435
+ ) => GroupColumnDef<TMDataGridFeatures, TData, unknown> &
436
+ TMDataGridTypedColumn<TMDataGridColumnInfoOf<TChildren[number]>>;
394
437
  };
395
438
 
396
439
  export function createTMDataGridColumnHelper<
@@ -734,7 +777,7 @@ type TMDataGridEditingCallbacks<TData extends RowData> = {
734
777
  * One TanStack Form per editing row; drafts survive scrolling because the
735
778
  * forms live outside the DOM, keyed by row id. Which columns edit, and with
736
779
  * what, is declared per column under `meta.edit`: `meta.type` picks the
737
- * built-in editor, and `enabled`, `field`, `editor`, `validate` and `mapValue`
780
+ * built-in editor, and `enabled`, `field`, `editor`, `validate`, `mapValue` and `mapCommitValue`
738
781
  * override the rest.
739
782
  */
740
783
  export type TMDataGridEditingOptions<TData extends RowData> =