@svgrid/grid 3.0.4 → 3.0.6

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 (176) hide show
  1. package/README.md +32 -11
  2. package/dist/GridMenus.svelte +34 -4
  3. package/dist/SvGrid.controller.svelte.d.ts +33 -5
  4. package/dist/SvGrid.controller.svelte.js +397 -58
  5. package/dist/SvGrid.css +200 -2
  6. package/dist/SvGrid.svelte +350 -40
  7. package/dist/SvGrid.types.d.ts +433 -7
  8. package/dist/SvGridDropdown.svelte +20 -0
  9. package/dist/SvGridDropdown.svelte.d.ts +12 -0
  10. package/dist/SvModal.svelte +22 -0
  11. package/dist/SvModal.svelte.d.ts +7 -0
  12. package/dist/a11y/dismissable.d.ts +10 -0
  13. package/dist/a11y/dismissable.js +24 -2
  14. package/dist/build-api.js +92 -37
  15. package/dist/cdn/{GridMenus-BL7ZgQvU.js → GridMenus-C-NtjlrJ.js} +155 -146
  16. package/dist/cdn/GridMenus-TssHej3q.js +644 -0
  17. package/dist/cdn/{SvChartMenu-FBSMINA6.js → SvChartMenu-BFSTpvB-.js} +1 -1
  18. package/dist/cdn/{SvChartMenu-Bl6PBbkT.js → SvChartMenu-BZ1Iwv0y.js} +1 -1
  19. package/dist/cdn/{SvDateTimePicker-DQwt4UAs.js → SvDateTimePicker-D9u_cOf8.js} +1 -1
  20. package/dist/cdn/{SvDateTimePicker-vNU6bZ-q.js → SvDateTimePicker-s_6IUpI7.js} +1 -1
  21. package/dist/cdn/{SvGridCellEditor-B1p-vCK5.js → SvGridCellEditor-BlyCSp0q.js} +1 -1
  22. package/dist/cdn/{SvGridCellEditor-D_0q4xAu.js → SvGridCellEditor-ClRRA9lW.js} +1 -1
  23. package/dist/cdn/{SvGridChart-DzLkSwCH.js → SvGridChart-B4EV8U6t.js} +4 -4
  24. package/dist/cdn/{SvGridChart-C3EWAZaM.js → SvGridChart-DsmwTyZF.js} +4 -4
  25. package/dist/cdn/{SvGridChartBuilder-CfII62sZ.js → SvGridChartBuilder-cHloHobN.js} +4 -4
  26. package/dist/cdn/{SvGridChartBuilder-BE2T1ykB.js → SvGridChartBuilder-vOl7C0Za.js} +4 -4
  27. package/dist/cdn/{SvGridChartPanel-xf4sWVTo.js → SvGridChartPanel-AcqF-Ll5.js} +5 -5
  28. package/dist/cdn/{SvGridChartPanel-CCX5_Wgd.js → SvGridChartPanel-biMtSBPA.js} +5 -5
  29. package/dist/cdn/{SvGridChartView-DYwabQWj.js → SvGridChartView-Dx_GmZuL.js} +2 -2
  30. package/dist/cdn/{SvGridChartView-CfuXmY5I.js → SvGridChartView-I3rDHXAq.js} +2 -2
  31. package/dist/cdn/{SvGridDropdown-D0VdjeR8.js → SvGridDropdown-BWeM3lMe.js} +46 -46
  32. package/dist/cdn/{SvGridDropdown-D13MtJ2j.js → SvGridDropdown-CJ6QqTxu.js} +67 -67
  33. package/dist/cdn/{SvModal-CIZWCcad.js → SvModal-ClxGmpAc.js} +187 -186
  34. package/dist/cdn/{SvModal-BAE-pjZX.js → SvModal-DhB_VMFR.js} +148 -147
  35. package/dist/cdn/{cell-formatting-C2Hf5gqd.js → cell-formatting-DVVKOSI9.js} +1 -1
  36. package/dist/cdn/{chart-Dz7SqMXH.js → chart-DEZxwC0i.js} +1 -1
  37. package/dist/cdn/{chart-panel-messages-CUbf2R4i.js → chart-panel-messages-D12XcTZJ.js} +1 -1
  38. package/dist/cdn/{chart-panel-messages-CmNrMdsr.js → chart-panel-messages-DguS7gC5.js} +1 -1
  39. package/dist/cdn/{chart-summary-BJW_tg_X.js → chart-summary-CMAXBGY-.js} +1 -1
  40. package/dist/cdn/{chart-trend-CaN9mDEV.js → chart-trend-BkEp61Gj.js} +1 -1
  41. package/dist/cdn/{dismissable-DAHetSNk.js → dismissable-Brc4EZU1.js} +5 -1
  42. package/dist/cdn/{export-format-CUDLy2yn.js → export-format-YzdwBww2.js} +1 -1
  43. package/dist/cdn/{row-resize-niQCp040.js → row-resize-DtOS1KG6.js} +41 -32
  44. package/dist/cdn/server-block-cache-DIqb3VZn.js +241 -0
  45. package/dist/cdn/{src-V1uu8iE9.js → src-CgoeSM8k.js} +5339 -4753
  46. package/dist/cdn/{src-BKhZ6eXd.js → src-DfwxB1TH.js} +9817 -9231
  47. package/dist/cdn/svgrid.js +28 -27
  48. package/dist/cdn/svgrid.svelte-external.js +28 -27
  49. package/dist/cdn/validate-AZoD8BoR.js +80 -0
  50. package/dist/cell-formatting.js +18 -1
  51. package/dist/cell-render.js +25 -6
  52. package/dist/clipboard.d.ts +2 -2
  53. package/dist/clipboard.js +72 -23
  54. package/dist/columns.js +7 -2
  55. package/dist/conditional-formatting.d.ts +2 -0
  56. package/dist/conditional-formatting.js +2 -0
  57. package/dist/core.d.ts +22 -6
  58. package/dist/core.js +401 -38
  59. package/dist/editing.js +34 -0
  60. package/dist/gantt-view.svelte.d.ts +24 -0
  61. package/dist/gantt-view.svelte.js +13 -0
  62. package/dist/grid-icons.d.ts +2 -2
  63. package/dist/grid-icons.js +2 -2
  64. package/dist/grid-messages.d.ts +10 -0
  65. package/dist/grid-messages.js +9 -0
  66. package/dist/headless.d.ts +5 -0
  67. package/dist/headless.js +12 -0
  68. package/dist/history.d.ts +21 -0
  69. package/dist/history.js +34 -4
  70. package/dist/index.d.ts +5 -4
  71. package/dist/index.js +3 -3
  72. package/dist/keyboard-handlers.js +24 -1
  73. package/dist/keyboard.js +4 -0
  74. package/dist/row-drag-touch.d.ts +1 -1
  75. package/dist/row-drag.js +35 -1
  76. package/dist/row-model.d.ts +139 -0
  77. package/dist/row-model.js +16 -0
  78. package/dist/row-resize.js +22 -1
  79. package/dist/selection.d.ts +2 -1
  80. package/dist/selection.js +31 -3
  81. package/dist/server-block-cache.d.ts +219 -0
  82. package/dist/server-block-cache.js +539 -0
  83. package/dist/server-data-source.d.ts +274 -8
  84. package/dist/server-data-source.js +229 -20
  85. package/dist/server.d.ts +13 -0
  86. package/dist/server.js +13 -0
  87. package/dist/sparkline.js +7 -5
  88. package/dist/svgrid-wrapper.types.d.ts +33 -0
  89. package/dist/validate.d.ts +4 -0
  90. package/dist/validate.js +29 -3
  91. package/package.json +11 -1
  92. package/src/GridMenus.svelte +34 -4
  93. package/src/SvGrid.controller.svelte.ts +397 -61
  94. package/src/SvGrid.css +200 -2
  95. package/src/SvGrid.svelte +350 -40
  96. package/src/SvGrid.types.ts +453 -7
  97. package/src/SvGridDropdown.svelte +20 -0
  98. package/src/SvModal.svelte +22 -0
  99. package/src/SvModal.test.ts +30 -1
  100. package/src/a11y/dismissable.test.ts +10 -1
  101. package/src/a11y/dismissable.ts +22 -2
  102. package/src/build-api.ts +96 -31
  103. package/src/cell-formatting.test.ts +17 -0
  104. package/src/cell-formatting.ts +18 -1
  105. package/src/cell-render.test.ts +24 -2
  106. package/src/cell-render.ts +24 -8
  107. package/src/clipboard.test.ts +107 -0
  108. package/src/clipboard.ts +62 -23
  109. package/src/columns.test.ts +4 -4
  110. package/src/columns.ts +7 -2
  111. package/src/conditional-formatting.test.ts +8 -0
  112. package/src/conditional-formatting.ts +3 -0
  113. package/src/core.rowmodel-cache.test.ts +51 -0
  114. package/src/core.tick-repair.test.ts +287 -0
  115. package/src/core.ts +407 -38
  116. package/src/editing.test.ts +52 -0
  117. package/src/editing.ts +33 -0
  118. package/src/gantt-stub.test.svelte +38 -0
  119. package/src/gantt-view.svelte.ts +35 -0
  120. package/src/grid-icons.ts +2 -2
  121. package/src/grid-messages.test.ts +7 -0
  122. package/src/grid-messages.ts +22 -0
  123. package/src/headless.ts +24 -0
  124. package/src/history.test.ts +49 -1
  125. package/src/history.ts +48 -2
  126. package/src/icon-seam.test.ts +2 -4
  127. package/src/index.ts +38 -10
  128. package/src/keyboard-handlers.coverage.test.ts +65 -0
  129. package/src/keyboard-handlers.ts +26 -1
  130. package/src/keyboard.ts +3 -0
  131. package/src/row-drag-touch.ts +2 -2
  132. package/src/row-drag.test.ts +51 -0
  133. package/src/row-drag.ts +35 -2
  134. package/src/row-model.ts +152 -0
  135. package/src/row-resize.ts +24 -1
  136. package/src/selection.test.ts +3 -0
  137. package/src/selection.ts +33 -3
  138. package/src/server-block-cache.test.ts +672 -0
  139. package/src/server-block-cache.ts +690 -0
  140. package/src/server-data-source.infinite.test.ts +405 -0
  141. package/src/server-data-source.test.ts +19 -0
  142. package/src/server-data-source.ts +496 -29
  143. package/src/server.ts +49 -0
  144. package/src/sparkline.test.ts +7 -0
  145. package/src/sparkline.ts +6 -4
  146. package/src/svgrid-wrapper.types.ts +32 -0
  147. package/src/svgrid.api.test.ts +21 -0
  148. package/src/svgrid.charting.test.ts +12 -4
  149. package/src/svgrid.context-menu.test.ts +12 -0
  150. package/src/svgrid.detail-rows.svelte.test.ts +187 -0
  151. package/src/svgrid.filter-menu-scroll.test.ts +9 -0
  152. package/src/svgrid.gantt-seam.test.ts +199 -0
  153. package/src/svgrid.live-update-paths.svelte.test.ts +184 -0
  154. package/src/svgrid.menu-scroll-close.test.ts +10 -0
  155. package/src/svgrid.row-model-prop.svelte.test.ts +352 -0
  156. package/src/svgrid.row-model-seam.svelte.test.ts +305 -0
  157. package/src/svgrid.row-pinning.test.ts +15 -1
  158. package/src/svgrid.selection-bar-seam.test.ts +1 -1
  159. package/src/svgrid.sticky-groups.svelte.test.ts +145 -0
  160. package/src/svgrid.upsell-license.test.ts +8 -5
  161. package/src/test-setup.ts +12 -0
  162. package/src/transaction.test.ts +58 -0
  163. package/src/validate.test.ts +29 -0
  164. package/src/validate.ts +34 -3
  165. package/dist/SvGroupCell.svelte +0 -141
  166. package/dist/SvGroupCell.svelte.d.ts +0 -49
  167. package/dist/SvRowGroupPanel.svelte +0 -186
  168. package/dist/SvRowGroupPanel.svelte.d.ts +0 -25
  169. package/dist/cdn/GridMenus-7kbpnnBW.js +0 -635
  170. package/dist/cdn/validate-_CDJzgIo.js +0 -75
  171. package/dist/server-group-model.d.ts +0 -98
  172. package/dist/server-group-model.js +0 -263
  173. package/src/SvGroupCell.svelte +0 -141
  174. package/src/SvRowGroupPanel.svelte +0 -186
  175. package/src/server-group-model.test.ts +0 -294
  176. package/src/server-group-model.ts +0 -370
@@ -0,0 +1,219 @@
1
+ /**
2
+ * Block cache for server-backed rows - the engine behind infinite scrolling.
3
+ *
4
+ * Paging asks for "page 3". Infinite scrolling asks a different question: the
5
+ * user is looking at rows 4,000 to 4,020 of a table with a million rows, so
6
+ * fetch the block that covers them, keep a bounded number of recently-seen
7
+ * blocks, and render something sensible for every row nobody has fetched yet.
8
+ * That is all this module does, in plain TypeScript with no Svelte and no DOM.
9
+ *
10
+ * The shape of the problem (and most of the vocabulary) is the same one every
11
+ * grid with a server row model solves, so the options here are deliberately
12
+ * recognisable: `blockSize`, `maxBlocksInCache`, `maxConcurrentRequests`,
13
+ * `blockLoadDebounceMs`, `initialRowCount`, `overflowRows`.
14
+ *
15
+ * Three things it takes seriously:
16
+ *
17
+ * - **Unloaded rows still have to render.** `rows()` always returns a dense
18
+ * array, with a shared sentinel object in every slot that has no data. The
19
+ * grid recognises those (see {@link rowPlaceholderState}) and draws a
20
+ * skeleton or a retry affordance instead of an empty row, so the scrollbar
21
+ * never lies and scrolling never leaves a hole.
22
+ * - **The row count may be unknown.** A backend that cannot cheaply count
23
+ * says so (omit `rowCount`, or send `-1`) and the list grows by a block at
24
+ * a time until a short block proves where the end is.
25
+ * - **Requests are not free.** In-flight blocks are deduplicated, at most
26
+ * `maxConcurrentRequests` are open at once, a fast scroll debounces rather
27
+ * than firing a request per frame, and blocks abandoned by eviction or
28
+ * purge are aborted.
29
+ *
30
+ * Enterprise's server row model runs one of these per group level; the free
31
+ * flat controller runs exactly one.
32
+ */
33
+ /**
34
+ * The mark that says "this row is not data yet".
35
+ *
36
+ * A symbol, for two reasons. It cannot collide with a field in anyone's row
37
+ * data, which a string key like `__svPlaceholder` eventually would. And
38
+ * `Symbol.for` puts it in the global registry, so a placeholder still reads as
39
+ * one after it has crossed a module boundary - two copies of this file loaded
40
+ * through different specifiers would otherwise mint different symbols.
41
+ */
42
+ declare const PLACEHOLDER: unique symbol;
43
+ /** Rows the cache has not loaded. One shared object per state, not per row. */
44
+ declare const LOADING_ROW: Readonly<{
45
+ [PLACEHOLDER]: "loading";
46
+ }>;
47
+ declare const FAILED_ROW: Readonly<{
48
+ [PLACEHOLDER]: "failed";
49
+ }>;
50
+ /**
51
+ * Why a row is not real data, or `null` when it is.
52
+ *
53
+ * Deliberately NOT an identity check. The sentinels are shared objects, so
54
+ * `row === LOADING_ROW` looks like the obvious test - but rows routinely
55
+ * arrive here through something that wrapped them. Svelte is the everyday
56
+ * case: assigning the controller state into `$state` makes the row array
57
+ * deeply reactive, and every row read back out is a proxy of the original.
58
+ * Identity fails, every placeholder reads as real data, and the grid renders
59
+ * a screen of blank rows instead of skeletons. Reading the mark works through
60
+ * any wrapper that forwards property access, which is all of them.
61
+ */
62
+ export declare function rowPlaceholderState(row: unknown): 'loading' | 'failed' | null;
63
+ /**
64
+ * Mint a frozen placeholder the grid will recognise, carrying whatever
65
+ * other fields the caller wants on it. The row model uses this to give its
66
+ * placeholders a `kind`, so code reading display rows and code reading grid
67
+ * rows agree on what they are looking at.
68
+ */
69
+ export declare function createRowPlaceholder<T extends object>(state: 'loading' | 'failed', fields: T): Readonly<T & {
70
+ readonly [PLACEHOLDER]: 'loading' | 'failed';
71
+ }>;
72
+ /** What a block fetch has to answer with. `rowCount` is optional: see {@link BlockCacheOptions}. */
73
+ export type BlockFetchResult<TData> = {
74
+ rows: ReadonlyArray<TData>;
75
+ /**
76
+ * Total rows after filtering. Omit it (or send `-1`) when the backend cannot
77
+ * count cheaply - the cache then discovers the end from the first short
78
+ * block, and `lastRowKnown()` stays false until it does.
79
+ */
80
+ rowCount?: number;
81
+ };
82
+ /** What a block cache is built from: block size, caps, debounce and the fetch. */
83
+ export type BlockCacheOptions<TData> = {
84
+ /**
85
+ * Rows per request. Bigger blocks mean fewer round trips and more wasted
86
+ * rows when the user scrolls past; 100 is the usual compromise.
87
+ */
88
+ blockSize?: number;
89
+ /**
90
+ * Keep at most this many loaded blocks. Blocks outside the viewport are
91
+ * evicted least-recently-seen first, and scrolling back re-fetches them.
92
+ * Unlimited by default, which is right until the dataset is big enough that
93
+ * holding every visited block matters.
94
+ */
95
+ maxBlocksInCache?: number;
96
+ /** Requests open at once. Default 2. */
97
+ maxConcurrentRequests?: number;
98
+ /**
99
+ * Wait this long after the viewport settles before fetching. Non-zero values
100
+ * stop a drag of the scrollbar from requesting every block it flies past.
101
+ */
102
+ blockLoadDebounceMs?: number;
103
+ /**
104
+ * Rows to claim before anything is loaded, so the grid has a scrollbar (and
105
+ * `scrollToRow` has somewhere to land) on the first paint. Default 1.
106
+ */
107
+ initialRowCount?: number;
108
+ /**
109
+ * While the total is unknown, how many unloaded rows to keep past the last
110
+ * loaded one. Scrolling into them is what asks for the next block. Default 1.
111
+ */
112
+ overflowRows?: number;
113
+ /** Fetch one block. Reject, or throw, to mark it failed. */
114
+ fetch: (startRow: number, endRow: number, signal: AbortSignal) => Promise<BlockFetchResult<TData>>;
115
+ /** Called after any change to the rows, the count, or a block's state. */
116
+ onChange: (cache: BlockCacheState) => void;
117
+ /**
118
+ * How to coalesce `onChange`. Defaults to a microtask, so a burst of block
119
+ * arrivals rebuilds the row array once. Pass `(fn) => fn()` in tests to make
120
+ * every change synchronous.
121
+ */
122
+ schedule?: (flush: () => void) => void;
123
+ };
124
+ /** One block's place in the world, for diagnostics and for tests. */
125
+ export type BlockState = {
126
+ blockIndex: number;
127
+ startRow: number;
128
+ endRow: number;
129
+ status: 'loading' | 'loaded' | 'failed';
130
+ /** Monotonic counter of when the viewport last covered this block. */
131
+ lastTouched: number;
132
+ };
133
+ /** One block as `getCacheState()` reports it. */
134
+ export type BlockCacheState = {
135
+ /** Rows after filtering, or `null` while the backend has not said. */
136
+ rowCount: number | null;
137
+ /** False while the end of the data is still being discovered. */
138
+ lastRowKnown: boolean;
139
+ /** True while at least one block is in flight. */
140
+ loading: boolean;
141
+ /** Blocks whose fetch rejected. Empty unless something went wrong. */
142
+ failedBlocks: number[];
143
+ };
144
+ /**
145
+ * A block cache: rows arrive in blocks as the viewport reaches them,
146
+ * placeholders stand in until then, and blocks far from the viewport are
147
+ * evicted past the cap.
148
+ */
149
+ export type BlockCache<TData> = {
150
+ /**
151
+ * Tell the cache which rows are on screen. Fetches what is missing (after
152
+ * `blockLoadDebounceMs`) and marks those blocks as recently seen so eviction
153
+ * spares them. Safe to call on every scroll frame.
154
+ */
155
+ setViewport(startIndex: number, endIndex: number): void;
156
+ /** The dense row array to hand the grid. Placeholders fill unloaded slots. */
157
+ rows(): ReadonlyArray<TData>;
158
+ /** One row, without building the array. Returns a placeholder when unloaded. */
159
+ getRow(index: number): TData | typeof LOADING_ROW | typeof FAILED_ROW;
160
+ rowCount(): number | null;
161
+ lastRowKnown(): boolean;
162
+ /** Re-fetch the blocks that failed. */
163
+ retryFailed(): void;
164
+ /**
165
+ * Re-fetch the failed block holding `rowIndex`, and only that one; the
166
+ * Retry on a failed row. A row whose block has not failed is a no-op.
167
+ */
168
+ retryFailedAt(rowIndex: number): void;
169
+ /**
170
+ * Re-fetch the loaded blocks in place, keeping the row count and scroll
171
+ * position. What you want after a mutation lands on the server.
172
+ */
173
+ refresh(): void;
174
+ /** Drop everything and start over from the current viewport. */
175
+ purge(): void;
176
+ /** Override the total, e.g. from a count endpoint that answered separately. */
177
+ setRowCount(count: number | null, known?: boolean): void;
178
+ /**
179
+ * Write rows straight into the cache from `startRow`, as if a fetch had
180
+ * returned them, bypassing the datasource, the debounce and the
181
+ * concurrency cap. `startRow` must sit on a block boundary. An explicit
182
+ * `rowCount` settles the total; without one a short final slice does.
183
+ */
184
+ applyRows(startRow: number, rows: ReadonlyArray<TData>, rowCount?: number): void;
185
+ /** Replace one loaded row. No-op when its block is not loaded. */
186
+ patch(index: number, row: TData): boolean;
187
+ /**
188
+ * The index of the first LOADED row matching `predicate`, or -1. Rows
189
+ * that are not loaded are not visited - a transaction addressed by id
190
+ * can only touch what is in the cache.
191
+ */
192
+ findIndex(predicate: (row: TData, index: number) => boolean): number;
193
+ /**
194
+ * Insert rows at an index and grow the count. Works within whichever
195
+ * run of loaded blocks contains `index`; loaded blocks AFTER that run
196
+ * are dropped, because their rows have shifted and will be re-fetched at
197
+ * their new offsets. An index in an unloaded region grows the count
198
+ * only (the rows exist; they arrive when scrolled to). Returns whether
199
+ * the rows were placed in the cache.
200
+ */
201
+ insert(index: number, rows: ReadonlyArray<TData>): boolean;
202
+ /**
203
+ * Remove `count` rows at an index and shrink the count, with the same
204
+ * run semantics as `insert`. Returns how many rows were actually
205
+ * removed from the cache.
206
+ */
207
+ remove(index: number, count?: number): number;
208
+ /** Every block the cache is holding, for `debug` output and tests. */
209
+ getCacheState(): BlockState[];
210
+ /** Abort what is in flight and stop emitting. Call on unmount. */
211
+ dispose(): void;
212
+ };
213
+ /**
214
+ * Build a block cache over a `fetch(startRow, endRow, signal)`. The free
215
+ * infinite row model and the Enterprise server-side row model both run on
216
+ * it, one per level.
217
+ */
218
+ export declare function createBlockCache<TData>(options: BlockCacheOptions<TData>): BlockCache<TData>;
219
+ export {};