@jielga/tmdatagrid 2.0.0-beta.8 → 2.0.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 (155) hide show
  1. package/README.md +5 -212
  2. package/dist/index.d.ts +1323 -796
  3. package/dist/index.js +4719 -3193
  4. package/dist/index.js.map +1 -1
  5. package/dist/styles.css +1 -1
  6. package/docs/adding-rows.md +132 -0
  7. package/docs/anatomy.md +119 -0
  8. package/docs/card-view.md +108 -0
  9. package/docs/cell-selection.md +194 -0
  10. package/docs/column-layout.md +182 -0
  11. package/docs/column-menu.md +66 -0
  12. package/docs/columns.md +268 -0
  13. package/docs/components.md +311 -0
  14. package/docs/draft-store.md +242 -0
  15. package/docs/editing.md +303 -0
  16. package/docs/editors.md +250 -0
  17. package/docs/export.md +319 -0
  18. package/docs/filtering.md +362 -0
  19. package/docs/getting-started.md +123 -0
  20. package/docs/grouping.md +165 -0
  21. package/docs/loading-and-empty.md +92 -0
  22. package/docs/localization.md +79 -0
  23. package/docs/menu.md +143 -0
  24. package/docs/migrating-to-2.md +163 -0
  25. package/docs/pagination.md +144 -0
  26. package/docs/persistence.md +114 -0
  27. package/docs/portfolio-rebalancer.md +94 -0
  28. package/docs/query-builder.md +179 -0
  29. package/docs/quick-search.md +84 -0
  30. package/docs/row-details.md +115 -0
  31. package/docs/row-interaction.md +149 -0
  32. package/docs/row-pinning.md +132 -0
  33. package/docs/row-selection.md +136 -0
  34. package/docs/row-styling.md +133 -0
  35. package/docs/scrolling.md +112 -0
  36. package/docs/server-query.md +246 -0
  37. package/docs/server-side.md +206 -0
  38. package/docs/sorting.md +101 -0
  39. package/docs/styling.md +126 -0
  40. package/docs/summary-row.md +76 -0
  41. package/docs/testing.md +744 -0
  42. package/docs/toolbar.md +161 -0
  43. package/docs/use-tm-data-grid.md +361 -0
  44. package/package.json +22 -46
  45. package/skills/appearance/SKILL.md +72 -19
  46. package/skills/cell-selection/SKILL.md +69 -78
  47. package/skills/columns/SKILL.md +90 -34
  48. package/skills/data/SKILL.md +86 -16
  49. package/skills/editing/SKILL.md +83 -50
  50. package/skills/editing/references/common-mistakes.md +77 -69
  51. package/skills/editing/references/editing-api.md +31 -23
  52. package/skills/editing/references/editors-and-validation.md +24 -17
  53. package/skills/filtering/SKILL.md +148 -40
  54. package/skills/getting-started/SKILL.md +17 -15
  55. package/skills/grouping/SKILL.md +31 -16
  56. package/skills/options/SKILL.md +8 -8
  57. package/skills/rows/SKILL.md +22 -18
  58. package/skills/server-side/SKILL.md +170 -17
  59. package/skills/testing/SKILL.md +150 -32
  60. package/skills/testing-components/SKILL.md +230 -0
  61. package/skills/testing-editing/SKILL.md +240 -0
  62. package/src/{tmdatagrid/TMDataGridContext.ts → TMDataGridContext.ts} +7 -19
  63. package/src/{tmdatagrid/components → components}/TMDataGrid.module.css +7 -1
  64. package/src/{tmdatagrid/components → components}/TMDataGrid.tsx +38 -21
  65. package/src/{tmdatagrid/components → components}/TMDataGridCellEditor.tsx +73 -7
  66. package/src/{tmdatagrid/components → components}/TMDataGridColumnsPanel.module.css +5 -1
  67. package/src/{tmdatagrid/components → components}/TMDataGridColumnsPanel.tsx +47 -55
  68. package/src/{tmdatagrid/components → components}/TMDataGridDetailsColumn.tsx +9 -55
  69. package/src/{tmdatagrid/components → components}/TMDataGridDraftActions.tsx +41 -24
  70. package/src/{tmdatagrid/components → components}/TMDataGridEditColumn.tsx +23 -63
  71. package/src/components/TMDataGridEntryRows.tsx +354 -0
  72. package/src/components/TMDataGridExportPicker.module.css +77 -0
  73. package/src/components/TMDataGridExportPicker.tsx +234 -0
  74. package/src/components/TMDataGridFilterPanel.module.css +54 -0
  75. package/src/components/TMDataGridFilterPanel.tsx +348 -0
  76. package/src/{tmdatagrid/components → components}/TMDataGridFilterPills.tsx +15 -8
  77. package/src/components/TMDataGridFilterSurface.module.css +54 -0
  78. package/src/components/TMDataGridFilterSurface.tsx +167 -0
  79. package/src/{tmdatagrid/components → components}/TMDataGridFooter.tsx +53 -90
  80. package/src/{tmdatagrid/components → components}/TMDataGridGroupColumn.tsx +9 -72
  81. package/src/{tmdatagrid/components → components}/TMDataGridHeaderCell.module.css +12 -2
  82. package/src/{tmdatagrid/components → components}/TMDataGridHeaderCell.tsx +58 -21
  83. package/src/components/TMDataGridHeaderFilterRow.module.css +51 -0
  84. package/src/components/TMDataGridHeaderFilterRow.tsx +301 -0
  85. package/src/components/TMDataGridMenu.tsx +357 -0
  86. package/src/{tmdatagrid/components → components}/TMDataGridSelectColumn.tsx +15 -53
  87. package/src/{tmdatagrid/components → components}/TMDataGridTable.module.css +88 -65
  88. package/src/{tmdatagrid/components → components}/TMDataGridTable.tsx +579 -165
  89. package/src/{tmdatagrid/components → components}/TMDataGridToolbar.module.css +5 -0
  90. package/src/components/TMDataGridToolbar.tsx +181 -0
  91. package/src/{tmdatagrid/components → components}/editors/TMDataGridBooleanEditor.tsx +3 -3
  92. package/src/{tmdatagrid/components → components}/editors/TMDataGridDateEditor.tsx +3 -3
  93. package/src/{tmdatagrid/components → components}/editors/TMDataGridMultiSelectEditor.tsx +3 -3
  94. package/src/{tmdatagrid/components → components}/editors/TMDataGridNumberEditor.tsx +3 -3
  95. package/src/{tmdatagrid/components → components}/editors/TMDataGridSelectEditor.tsx +3 -3
  96. package/src/{tmdatagrid/components → components}/editors/TMDataGridStringEditor.tsx +3 -3
  97. package/src/{tmdatagrid/components → components}/editors/editorShared.ts +16 -2
  98. package/src/{tmdatagrid/components → components}/filters/DgAutocompleteFilter.tsx +5 -4
  99. package/src/{tmdatagrid/components → components}/filters/DgDateRangeFilter.tsx +22 -5
  100. package/src/{tmdatagrid/components → components}/filters/DgRangeSliderFilter.tsx +5 -1
  101. package/src/{tmdatagrid/components → components}/filters/DgTriStateFilter.tsx +5 -1
  102. package/src/{tmdatagrid/components → components}/filters/TMDataGridFilterValueInput.tsx +44 -28
  103. package/src/components/filters/controlLayout.ts +32 -0
  104. package/src/components/filters/filterControlFor.ts +65 -0
  105. package/src/components/generatedColumns.tsx +187 -0
  106. package/src/{tmdatagrid/components → components}/icons.ts +1 -0
  107. package/src/{tmdatagrid/components → components}/sticky.module.css +44 -0
  108. package/src/components/useHideableColumns.ts +52 -0
  109. package/src/{tmdatagrid/core → core}/autosize.ts +5 -2
  110. package/src/{tmdatagrid/core → core}/capabilities.ts +5 -5
  111. package/src/{tmdatagrid/core → core}/columnOptions.ts +60 -8
  112. package/src/{tmdatagrid/core → core}/columnOrdering.ts +33 -14
  113. package/src/{tmdatagrid/core → core}/columnUtils.ts +44 -5
  114. package/src/core/controlledStateSync.ts +108 -0
  115. package/src/core/deletedRows.ts +34 -0
  116. package/src/core/dom.ts +74 -0
  117. package/src/{tmdatagrid/core → core}/editEngine.ts +1172 -388
  118. package/src/{tmdatagrid/core → core}/editorFocus.ts +8 -4
  119. package/src/core/export.ts +704 -0
  120. package/src/{tmdatagrid/core → core}/filterControls.ts +38 -1
  121. package/src/{tmdatagrid/core → core}/filterOperators.ts +64 -1
  122. package/src/core/filterSurface.ts +99 -0
  123. package/src/{tmdatagrid/core → core}/grouping.ts +21 -0
  124. package/src/{tmdatagrid/core → core}/labels.ts +51 -6
  125. package/src/{tmdatagrid/core → core}/labelsSv.ts +27 -6
  126. package/src/core/pageReset.ts +120 -0
  127. package/src/core/pagination.ts +81 -0
  128. package/src/{tmdatagrid/core → core}/persistence.ts +22 -5
  129. package/src/{tmdatagrid/core → core}/summary.ts +20 -4
  130. package/src/{tmdatagrid/index.ts → index.ts} +70 -36
  131. package/src/{tmdatagrid/useTMDataGrid.tsx → useTMDataGrid.tsx} +534 -123
  132. package/src/useTMDataGridExport.ts +78 -0
  133. package/src/tmdatagrid/components/TMDataGridEntryRows.tsx +0 -298
  134. package/src/tmdatagrid/components/TMDataGridFilterPanel.module.css +0 -35
  135. package/src/tmdatagrid/components/TMDataGridFilterPanel.tsx +0 -354
  136. package/src/tmdatagrid/components/TMDataGridToolbar.tsx +0 -161
  137. package/src/tmdatagrid/core/cellExport.ts +0 -320
  138. /package/src/{tmdatagrid/components → components}/TMDataGridDetailsColumn.module.css +0 -0
  139. /package/src/{tmdatagrid/components → components}/TMDataGridFilterPills.module.css +0 -0
  140. /package/src/{tmdatagrid/components → components}/TMDataGridFooter.module.css +0 -0
  141. /package/src/{tmdatagrid/components → components}/TMDataGridGroupColumn.module.css +0 -0
  142. /package/src/{tmdatagrid/components → components}/TMDataGridRowNumberColumn.tsx +0 -0
  143. /package/src/{tmdatagrid/components → components}/TMDataGridSearch.tsx +0 -0
  144. /package/src/{tmdatagrid/core → core}/cellNavigation.ts +0 -0
  145. /package/src/{tmdatagrid/core → core}/cellRange.ts +0 -0
  146. /package/src/{tmdatagrid/core → core}/controlledState.ts +0 -0
  147. /package/src/{tmdatagrid/core → core}/draftCellContext.ts +0 -0
  148. /package/src/{tmdatagrid/core → core}/expanding.ts +0 -0
  149. /package/src/{tmdatagrid/core → core}/matchHighlight.ts +0 -0
  150. /package/src/{tmdatagrid/core → core}/quickSearch.ts +0 -0
  151. /package/src/{tmdatagrid/core → core}/resizePreview.ts +0 -0
  152. /package/src/{tmdatagrid/core → core}/rowPinning.ts +0 -0
  153. /package/src/{tmdatagrid/core → core}/rowSelection.ts +0 -0
  154. /package/src/{tmdatagrid/core → core}/sizes.ts +0 -0
  155. /package/src/{tmdatagrid/core → core}/useSettledTableState.ts +0 -0
@@ -1,4 +1,4 @@
1
- /* Anchors the filter panel, which floats over the first body rows. */
1
+ /* Anchors the filter popup, which floats over the first body rows. */
2
2
  .tableWrapper {
3
3
  position: relative;
4
4
  flex: 1;
@@ -7,9 +7,17 @@
7
7
  flex-direction: column;
8
8
  }
9
9
 
10
+ /* The sidebar surface is a second column of the wrapper rather than a layer
11
+ over the rows, so the wrapper lays its children out side by side. The
12
+ sidebar's own module decides which side it lands on. */
13
+ .tableWrapper[data-dg-filter-sidebar] {
14
+ flex-direction: row;
15
+ }
16
+
10
17
  .scrollContainer {
11
18
  position: relative;
12
19
  flex: 1;
20
+ min-width: 0;
13
21
  min-height: 0;
14
22
  overflow: auto;
15
23
  /* Lets .messageRow size itself to the scrollport (100cqi) instead of the
@@ -20,6 +28,25 @@
20
28
  /* Column tracks are set inline via gridTemplateColumns. */
21
29
  .grid {
22
30
  display: grid;
31
+ /* The grid is the containing block every sticky row inside it is held by, so
32
+ it has to reach the bottom of the scrollport even when the rows do not fill
33
+ it - that is what puts the summary row on the bottom edge of a short body.
34
+ `align-content` keeps the free space out of the row tracks; distributed
35
+ into them it would stretch every row instead. */
36
+ min-height: 100%;
37
+ align-content: start;
38
+ }
39
+
40
+ /* The pair of focusable elements bracketing the body, which is how the body
41
+ stays one tab stop. Out of flow so neither claims a row track in the grid,
42
+ and zero-sized so neither can be seen or clicked; the outline is dropped
43
+ because focus only ever rests here for the instant of a Tab. */
44
+ .tabGuard {
45
+ position: absolute;
46
+ width: 0;
47
+ height: 0;
48
+ overflow: hidden;
49
+ outline: none;
23
50
  }
24
51
 
25
52
  /* Rows are real layout boxes (not display: contents) so position: sticky works,
@@ -33,46 +60,6 @@
33
60
  z-index: var(--dg-z-header, 6);
34
61
  }
35
62
 
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 - the header/body
38
- boundary - not on every stacked group row. A scroll-driven animation, like
39
- the pinned-lane gradients: the shadow tracks the scroll on the compositor
40
- with no listener and no render, and an inactive timeline (nothing to
41
- scroll) leaves `opacity: 0` standing, so a grid that fits shows nothing.
42
- Where unsupported there is simply no shadow - the header's border already
43
- draws the boundary. */
44
- .headerRow[data-dg-header-last]::after {
45
- content: "";
46
- position: absolute;
47
- inset: 100% 0 auto 0;
48
- height: 6px;
49
- pointer-events: none;
50
- background: linear-gradient(
51
- to bottom,
52
- var(--dg-header-shadow-color, rgba(0, 0, 0, 0.14)),
53
- transparent
54
- );
55
- opacity: 0;
56
- }
57
-
58
- @supports (animation-timeline: scroll()) {
59
- .headerRow[data-dg-header-last]::after {
60
- animation: dg-header-shadow linear both;
61
- animation-timeline: scroll(nearest block);
62
- /* Arrives over the first rows leaving, reads as depth not as a fade. */
63
- animation-range: 0px 24px;
64
- }
65
- }
66
-
67
- @keyframes dg-header-shadow {
68
- from {
69
- opacity: 0;
70
- }
71
- to {
72
- opacity: 1;
73
- }
74
- }
75
-
76
63
  .bodyRow {
77
64
  --row-bg: var(--mantine-color-body);
78
65
  display: grid;
@@ -90,6 +77,13 @@
90
77
  --row-bg: var(--dg-row-striped-bg);
91
78
  }
92
79
 
80
+ /* An entered row committed into the draft store, sorted in with the body.
81
+ The same tint the entry block gives it; declared before the hover and
82
+ selection rules, which win at equal specificity. */
83
+ .bodyRow[data-new="true"] {
84
+ --row-bg: var(--dg-row-new-bg, var(--mantine-color-body));
85
+ }
86
+
93
87
  .bodyRow:hover {
94
88
  --row-bg: var(--mantine-color-default-hover);
95
89
  }
@@ -145,8 +139,13 @@
145
139
  align-items: center;
146
140
  padding: 0 var(--dg-padding);
147
141
  border-bottom: 1px solid var(--mantine-color-default-border);
148
- /* Inherited from .bodyRow - sticky cells need an opaque background. */
149
- background-color: var(--row-bg);
142
+ /* Two layers, not one. The base is the theme's body colour and `--row-bg`
143
+ (inherited from .bodyRow) is a tint painted over it, so a consumer whose
144
+ row token is translucent - a `color-mix(..., transparent)` - is safe under
145
+ the sticky lanes: a single translucent `background-color` would let the
146
+ scrolled body read through every pinned cell and pinned row. */
147
+ background-color: var(--mantine-color-body);
148
+ background-image: linear-gradient(var(--row-bg), var(--row-bg));
150
149
  font-size: var(--dg-font-size);
151
150
  }
152
151
 
@@ -170,13 +169,15 @@
170
169
  A tint over the row's own background rather than instead of it, so a
171
170
  selected cell on a highlighted row still reads as both. `color-mix` keeps
172
171
  one declaration for light and dark: it thins the theme's primary colour into
173
- whatever `--row-bg` the row resolved to. */
172
+ whatever `--row-bg` the row resolved to. Painted as the cell's tint layer,
173
+ over the opaque base above, for the same reason `--row-bg` is. */
174
174
  .bodyCell[data-selected="true"] {
175
- background-color: color-mix(
175
+ --dg-range-tint: color-mix(
176
176
  in srgb,
177
177
  var(--mantine-primary-color-filled) 14%,
178
178
  var(--row-bg)
179
179
  );
180
+ background-image: linear-gradient(var(--dg-range-tint), var(--dg-range-tint));
180
181
  }
181
182
 
182
183
  /* The outline around the block, drawn edge by edge: only the cells on a side
@@ -248,6 +249,15 @@
248
249
  gap: 2px;
249
250
  }
250
251
 
252
+ /* The editor's own box: the input fills it, and it is what the validation
253
+ tooltip is anchored to. */
254
+ .cellEditorField {
255
+ display: flex;
256
+ align-items: center;
257
+ flex: 1 1 auto;
258
+ min-width: 0;
259
+ }
260
+
251
261
  /* cellConfirm's ✓ / ✕ pair, beside the input. */
252
262
  .cellEditorActions {
253
263
  display: flex;
@@ -256,16 +266,19 @@
256
266
  }
257
267
 
258
268
  /* Corner triangles for a cell's edit state, drawn like a spreadsheet's: a
259
- draft not yet saved is blue, a value failing validation is red. The cell
260
- needs a positioning context; pinned and focused cells set their own inline
269
+ draft not yet saved is blue, a value failing validation is red. An entry
270
+ cell takes the red one only - everything in it is new. The cell needs a
271
+ positioning context; pinned and focused cells set their own inline
261
272
  `position`, which wins over this. */
262
273
  .bodyCell[data-dirty],
263
- .bodyCell[data-invalid] {
274
+ .bodyCell[data-invalid],
275
+ .entryCell[data-invalid] {
264
276
  position: relative;
265
277
  }
266
278
 
267
279
  .bodyCell[data-dirty]::after,
268
- .bodyCell[data-invalid]::after {
280
+ .bodyCell[data-invalid]::after,
281
+ .entryCell[data-invalid]::after {
269
282
  content: "";
270
283
  position: absolute;
271
284
  top: 0;
@@ -276,7 +289,8 @@
276
289
  }
277
290
 
278
291
  /* Invalid wins over dirty - a cell is usually both. */
279
- .bodyCell[data-invalid]::after {
292
+ .bodyCell[data-invalid]::after,
293
+ .entryCell[data-invalid]::after {
280
294
  border-top-color: var(--mantine-color-error);
281
295
  border-right-color: var(--mantine-color-error);
282
296
  }
@@ -303,7 +317,9 @@
303
317
  .detailsCell {
304
318
  grid-column: 1 / -1;
305
319
  border-bottom: 1px solid var(--mantine-color-default-border);
306
- background-color: var(--row-bg);
320
+ /* Base and tint, exactly as .bodyCell paints them. */
321
+ background-color: var(--mantine-color-body);
322
+ background-image: linear-gradient(var(--row-bg), var(--row-bg));
307
323
  padding: var(--dg-padding);
308
324
  /* The row above may be the selection control, which turns text selection off
309
325
  for everything inside it. A panel is content, so it takes both back. */
@@ -329,7 +345,7 @@
329
345
  padding: var(--mantine-spacing-xl);
330
346
  }
331
347
 
332
- /* Marked deleted under draft: struck through and inert until submitAll
348
+ /* Marked deleted under draft: struck through and inert until saveDrafts
333
349
  reports it - a row about to go away must not keep taking edits. Interaction
334
350
  comes off the data cells, not the row: `pointer-events: none` on the row
335
351
  would also kill the edit lane's Restore, which is the one control the row
@@ -365,22 +381,13 @@
365
381
  grid-template-columns: subgrid;
366
382
  }
367
383
 
368
- /* Confirmed entry rows in the scrolling flow (the default; `newRowsSticky`
369
- keeps them in the sticky block instead). Same tracks, no stickiness - they
370
- sit above the body rows and scroll with them. */
371
- .entryFlowBlock {
372
- display: grid;
373
- grid-column: 1 / -1;
374
- grid-template-columns: subgrid;
375
- }
376
-
377
384
  /* The pinned edge blocks - user-pinned rows held at the top or bottom of the
378
385
  body, on the entry block's sticky mechanics: the block is the sticky
379
386
  element, its rows flow normally inside it. The top block stacks under the
380
387
  entry block when both exist; `--dg-entry-height` is measured only then, so
381
388
  the offset is otherwise the header alone. The bottom block stacks above the
382
- summary row the same way. Rows are opaque already (`--row-bg` paints the
383
- body colour), so the blocks only add the edge borders. */
389
+ summary row the same way. The cells inside paint an opaque base under
390
+ `--row-bg` already, so the blocks only add the edge borders. */
384
391
  .pinnedTopBlock {
385
392
  display: grid;
386
393
  grid-column: 1 / -1;
@@ -428,7 +435,13 @@
428
435
  .entryRow[data-committed="true"] .entryCell {
429
436
  padding: 0 var(--dg-padding);
430
437
  border-bottom: 1px solid var(--mantine-color-default-border);
431
- background-color: var(--dg-row-new-bg, var(--mantine-color-body));
438
+ /* The tint over .entryCell's opaque base, not instead of it: the block is
439
+ sticky, so a translucent `--dg-row-new-bg` would otherwise show the body
440
+ scrolling underneath. */
441
+ background-image: linear-gradient(
442
+ var(--dg-row-new-bg, transparent),
443
+ var(--dg-row-new-bg, transparent)
444
+ );
432
445
  }
433
446
 
434
447
  .entryRow[data-committed="true"] .entryCell[data-control-column="true"] {
@@ -474,12 +487,22 @@
474
487
 
475
488
  /* The summary row - one sticky row of column footers along the bottom edge,
476
489
  rendered only while at least one column defines `footer`. Same subgrid
477
- placement as the header, so its cells sit exactly on the body's tracks. */
490
+ placement as the header, so its cells sit exactly on the body's tracks.
491
+
492
+ Both insets are set, so the row is on the scrollport's bottom edge whether
493
+ the body overflows or not. A percentage in a sticky inset resolves against
494
+ the scrollport: with too few rows to fill it, `top` pushes the row down
495
+ until `.grid` - which reaches the scrollport's bottom - stops it, flush with
496
+ the edge; with the body overflowing, `top` is already satisfied and
497
+ `bottom: 0` pins the row as it always did. Where the two conflict the top
498
+ one wins, which is why it has to be the row's own height short of 100% and
499
+ not 100%. `--dg-summary-height` is measured whenever this row exists. */
478
500
  .summaryRow {
479
501
  display: grid;
480
502
  grid-column: 1 / -1;
481
503
  grid-template-columns: subgrid;
482
504
  position: sticky;
505
+ top: calc(100% - var(--dg-summary-height, 0px));
483
506
  bottom: 0;
484
507
  z-index: var(--dg-z-summary-row, 4);
485
508
  }