@svgrid/grid 1.1.1 → 1.1.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 (50) hide show
  1. package/dist/FlexRender.svelte +96 -96
  2. package/dist/SvGrid.controller.svelte.js +17 -6
  3. package/dist/SvGrid.css +2012 -2012
  4. package/dist/SvGrid.svelte +2569 -2346
  5. package/dist/build-api.js +2 -2
  6. package/dist/cell-values.d.ts +1 -1
  7. package/dist/cell-values.js +7 -7
  8. package/dist/column-types.js +1 -1
  9. package/dist/core.d.ts +1 -1
  10. package/dist/core.js +2 -2
  11. package/dist/summaries.js +4 -4
  12. package/package.json +1 -1
  13. package/src/FlexRender.svelte +96 -96
  14. package/src/SvGrid.controller.svelte.ts +2363 -2352
  15. package/src/SvGrid.css +2012 -2012
  16. package/src/SvGrid.svelte +2569 -2346
  17. package/src/SvGrid.types.ts +537 -537
  18. package/src/a11y.contract.test.ts +49 -49
  19. package/src/a11y.test.ts +59 -59
  20. package/src/a11y.ts +59 -59
  21. package/src/build-api.ts +683 -683
  22. package/src/cell-formatting.ts +169 -169
  23. package/src/cell-values.ts +4 -4
  24. package/src/column-types.ts +1 -1
  25. package/src/core.performance.test.ts +30 -30
  26. package/src/core.ts +1077 -1077
  27. package/src/createGrid.svelte.ts +42 -42
  28. package/src/createGrid.test.ts +10 -10
  29. package/src/createGridState.svelte.ts +17 -17
  30. package/src/editing.ts +669 -669
  31. package/src/flex-render.ts +3 -3
  32. package/src/index.ts +208 -208
  33. package/src/keyboard.test.ts +59 -59
  34. package/src/keyboard.ts +97 -97
  35. package/src/merge-objects.ts +48 -48
  36. package/src/render-component.ts +28 -28
  37. package/src/spreadsheet.test.ts +489 -489
  38. package/src/spreadsheet.ts +304 -304
  39. package/src/static-functions.ts +11 -11
  40. package/src/subscribe.ts +38 -38
  41. package/src/summaries.ts +4 -4
  42. package/src/svgrid-wrapper.types.ts +412 -412
  43. package/src/svgrid.features.test.ts +157 -157
  44. package/src/svgrid.wrapper.test.ts +40 -40
  45. package/src/virtualization/column-virtualizer.test.ts +27 -27
  46. package/src/virtualization/column-virtualizer.ts +30 -30
  47. package/src/virtualization/svelte-virtualizer.svelte.ts +26 -26
  48. package/src/virtualization/types.ts +30 -30
  49. package/src/virtualization/virtualizer.test.ts +47 -47
  50. package/src/virtualization/virtualizer.ts +296 -296
@@ -1,96 +1,96 @@
1
- <script
2
- lang="ts"
3
- generics="TData extends RowData"
4
- >
5
- import { isFunction } from './core'
6
- import {
7
- RenderComponentConfig,
8
- RenderSnippetConfig,
9
- } from './render-component'
10
- import type {
11
- Cell,
12
- CellContext,
13
- ColumnDefTemplate,
14
- Header,
15
- HeaderContext,
16
- RowData,
17
- } from './core'
18
-
19
- type Props =
20
- | {
21
- content?: ColumnDefTemplate<
22
- | HeaderContext<TData>
23
- | CellContext<TData>
24
- >
25
- context:
26
- | HeaderContext<TData>
27
- | CellContext<TData>
28
- cell?: never
29
- header?: never
30
- footer?: never
31
- }
32
- | {
33
- cell: Cell<TData>
34
- content?: never
35
- context?: never
36
- header?: never
37
- footer?: never
38
- }
39
- | {
40
- header: Header<TData>
41
- content?: never
42
- context?: never
43
- cell?: never
44
- footer?: never
45
- }
46
- | {
47
- footer: Header<TData>
48
- content?: never
49
- context?: never
50
- cell?: never
51
- header?: never
52
- }
53
-
54
- let props: Props = $props()
55
-
56
- const resolved = $derived.by(() => {
57
- if ('cell' in props && props.cell) {
58
- return {
59
- content: props.cell.column.columnDef.cell,
60
- context: props.cell.getContext(),
61
- }
62
- }
63
- if ('header' in props && props.header) {
64
- return {
65
- content: props.header.column.columnDef.header,
66
- context: props.header.getContext(),
67
- }
68
- }
69
- if ('footer' in props && props.footer) {
70
- return {
71
- content: props.footer.column.columnDef.footer,
72
- context: props.footer.getContext(),
73
- }
74
- }
75
- return {
76
- content: props.content,
77
- context: props.context,
78
- }
79
- })
80
-
81
- const result = $derived(
82
- isFunction(resolved.content)
83
- ? resolved.content(resolved.context as any)
84
- : undefined,
85
- )
86
- </script>
87
-
88
- {#if typeof resolved.content === 'string'}
89
- {resolved.content}
90
- {:else if result instanceof RenderComponentConfig}
91
- <result.component {...result.props} />
92
- {:else if result instanceof RenderSnippetConfig}
93
- {@render result.snippet(result.params)}
94
- {:else if result !== undefined}
95
- {result}
96
- {/if}
1
+ <script
2
+ lang="ts"
3
+ generics="TData extends RowData"
4
+ >
5
+ import { isFunction } from './core'
6
+ import {
7
+ RenderComponentConfig,
8
+ RenderSnippetConfig,
9
+ } from './render-component'
10
+ import type {
11
+ Cell,
12
+ CellContext,
13
+ ColumnDefTemplate,
14
+ Header,
15
+ HeaderContext,
16
+ RowData,
17
+ } from './core'
18
+
19
+ type Props =
20
+ | {
21
+ content?: ColumnDefTemplate<
22
+ | HeaderContext<TData>
23
+ | CellContext<TData>
24
+ >
25
+ context:
26
+ | HeaderContext<TData>
27
+ | CellContext<TData>
28
+ cell?: never
29
+ header?: never
30
+ footer?: never
31
+ }
32
+ | {
33
+ cell: Cell<TData>
34
+ content?: never
35
+ context?: never
36
+ header?: never
37
+ footer?: never
38
+ }
39
+ | {
40
+ header: Header<TData>
41
+ content?: never
42
+ context?: never
43
+ cell?: never
44
+ footer?: never
45
+ }
46
+ | {
47
+ footer: Header<TData>
48
+ content?: never
49
+ context?: never
50
+ cell?: never
51
+ header?: never
52
+ }
53
+
54
+ let props: Props = $props()
55
+
56
+ const resolved = $derived.by(() => {
57
+ if ('cell' in props && props.cell) {
58
+ return {
59
+ content: props.cell.column.columnDef.cell,
60
+ context: props.cell.getContext(),
61
+ }
62
+ }
63
+ if ('header' in props && props.header) {
64
+ return {
65
+ content: props.header.column.columnDef.header,
66
+ context: props.header.getContext(),
67
+ }
68
+ }
69
+ if ('footer' in props && props.footer) {
70
+ return {
71
+ content: props.footer.column.columnDef.footer,
72
+ context: props.footer.getContext(),
73
+ }
74
+ }
75
+ return {
76
+ content: props.content,
77
+ context: props.context,
78
+ }
79
+ })
80
+
81
+ const result = $derived(
82
+ isFunction(resolved.content)
83
+ ? resolved.content(resolved.context as any)
84
+ : undefined,
85
+ )
86
+ </script>
87
+
88
+ {#if typeof resolved.content === 'string'}
89
+ {resolved.content}
90
+ {:else if result instanceof RenderComponentConfig}
91
+ <result.component {...result.props} />
92
+ {:else if result instanceof RenderSnippetConfig}
93
+ {@render result.snippet(result.params)}
94
+ {:else if result !== undefined}
95
+ {result}
96
+ {/if}
@@ -263,14 +263,25 @@ export function createSvGridController(props) {
263
263
  };
264
264
  });
265
265
  /** Vertical overflow from the virtualizer's authoritative total size,
266
- * NOT from `scrollMetrics.scrollHeight`. Reading DOM dimensions
266
+ * NOT from `scrollMetrics.scrollHeight` alone. Reading DOM dimensions
267
267
  * during a Svelte derived runs BEFORE the browser paints - the table
268
268
  * hasn't laid out the new rows yet, so `scrollHeight` is briefly 0
269
269
  * even after data loads. That made the overflow flag return false,
270
- * hid the scrollbar, and broke dragging. */
270
+ * hid the scrollbar, and broke dragging.
271
+ *
272
+ * However, virtualizer.getTotalSize() uses rowHeight * numRows which
273
+ * underestimates when variable-height rows are present (e.g. master-detail
274
+ * expanded rows). We therefore take the MAX of the two sources:
275
+ * - virtualizer.getTotalSize(): correct at initial load (before first paint)
276
+ * - scrollMetrics.scrollHeight: correct after detail rows expand (DOM is live,
277
+ * ResizeObserver on gridRootEl already bumps scrollVersion at that point) */
271
278
  const hasVerticalOverflow = $derived.by(() => {
272
279
  virtualizer.version;
273
- return virtualizer.getTotalSize() > viewportHeight + 1;
280
+ const virtualizerSize = virtualizer.getTotalSize();
281
+ // scrollMetrics.scrollHeight is 0 before initial paint; once the table
282
+ // is in the DOM it reflects the true content height including expanded rows.
283
+ const domSize = scrollMetrics.scrollHeight;
284
+ return Math.max(virtualizerSize, domSize) > viewportHeight + 1;
274
285
  });
275
286
  // Effective filter-UI flags. Each show* prop wins when explicitly set;
276
287
  // otherwise the `filterMode` prop (default 'menu') picks exactly one surface.
@@ -629,12 +640,12 @@ export function createSvGridController(props) {
629
640
  if (!needs)
630
641
  continue;
631
642
  const def = column.columnDef;
632
- const accessorFn = def.accessorFn;
643
+ const fieldFn = def.fieldFn;
633
644
  const field = def.field;
634
645
  const stat = computeColumnStat((function* () {
635
646
  for (const row of allRows) {
636
- yield accessorFn
637
- ? accessorFn(row.original)
647
+ yield fieldFn
648
+ ? fieldFn(row.original)
638
649
  : field
639
650
  ? row.original[field]
640
651
  : row.getCellValueByColumnId(column.id);