@svgrid/grid 1.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 (213) hide show
  1. package/LICENSE +33 -0
  2. package/README.md +39 -0
  3. package/dist/FlexRender.svelte +96 -0
  4. package/dist/FlexRender.svelte.d.ts +49 -0
  5. package/dist/SvGrid.svelte +8742 -0
  6. package/dist/SvGrid.svelte.d.ts +381 -0
  7. package/dist/SvGridChart.svelte +653 -0
  8. package/dist/SvGridChart.svelte.d.ts +25 -0
  9. package/dist/SvGridChart.test.d.ts +1 -0
  10. package/dist/SvGridChart.test.js +62 -0
  11. package/dist/SvGridDropdown.svelte +675 -0
  12. package/dist/SvGridDropdown.svelte.d.ts +40 -0
  13. package/dist/a11y.contract.test.d.ts +1 -0
  14. package/dist/a11y.contract.test.js +39 -0
  15. package/dist/a11y.d.ts +38 -0
  16. package/dist/a11y.js +37 -0
  17. package/dist/a11y.test.d.ts +1 -0
  18. package/dist/a11y.test.js +44 -0
  19. package/dist/cell-formatting.d.ts +17 -0
  20. package/dist/cell-formatting.js +141 -0
  21. package/dist/cell-formatting.test.d.ts +1 -0
  22. package/dist/cell-formatting.test.js +234 -0
  23. package/dist/chart-export.d.ts +14 -0
  24. package/dist/chart-export.js +112 -0
  25. package/dist/chart.d.ts +226 -0
  26. package/dist/chart.js +732 -0
  27. package/dist/chart.test.d.ts +1 -0
  28. package/dist/chart.test.js +289 -0
  29. package/dist/collaboration.d.ts +74 -0
  30. package/dist/collaboration.js +98 -0
  31. package/dist/collaboration.test.d.ts +1 -0
  32. package/dist/collaboration.test.js +65 -0
  33. package/dist/conditional-formatting.d.ts +91 -0
  34. package/dist/conditional-formatting.js +170 -0
  35. package/dist/conditional-formatting.test.d.ts +1 -0
  36. package/dist/conditional-formatting.test.js +87 -0
  37. package/dist/core.coverage.test.d.ts +1 -0
  38. package/dist/core.coverage.test.js +186 -0
  39. package/dist/core.d.ts +370 -0
  40. package/dist/core.js +568 -0
  41. package/dist/core.performance.test.d.ts +1 -0
  42. package/dist/core.performance.test.js +29 -0
  43. package/dist/createGrid.svelte.d.ts +6 -0
  44. package/dist/createGrid.svelte.js +17 -0
  45. package/dist/createGrid.test.d.ts +1 -0
  46. package/dist/createGrid.test.js +9 -0
  47. package/dist/createGridState.svelte.d.ts +3 -0
  48. package/dist/createGridState.svelte.js +13 -0
  49. package/dist/editors/cell-editors.d.ts +23 -0
  50. package/dist/editors/cell-editors.js +97 -0
  51. package/dist/editors/cell-editors.test.d.ts +1 -0
  52. package/dist/editors/cell-editors.test.js +75 -0
  53. package/dist/fill-patterns.d.ts +30 -0
  54. package/dist/fill-patterns.js +207 -0
  55. package/dist/fill-patterns.test.d.ts +1 -0
  56. package/dist/fill-patterns.test.js +81 -0
  57. package/dist/filtering/excel-filters.d.ts +26 -0
  58. package/dist/filtering/excel-filters.js +64 -0
  59. package/dist/filtering/excel-filters.test.d.ts +1 -0
  60. package/dist/filtering/excel-filters.test.js +116 -0
  61. package/dist/filtering/locale-filter.test.d.ts +13 -0
  62. package/dist/filtering/locale-filter.test.js +189 -0
  63. package/dist/flex-render.d.ts +1 -0
  64. package/dist/flex-render.js +2 -0
  65. package/dist/flex-render.test.d.ts +1 -0
  66. package/dist/flex-render.test.js +142 -0
  67. package/dist/group-aggregate.test.d.ts +1 -0
  68. package/dist/group-aggregate.test.js +32 -0
  69. package/dist/index.d.ts +29 -0
  70. package/dist/index.js +27 -0
  71. package/dist/keyboard.d.ts +8 -0
  72. package/dist/keyboard.js +91 -0
  73. package/dist/keyboard.test.d.ts +1 -0
  74. package/dist/keyboard.test.js +27 -0
  75. package/dist/merge-objects.d.ts +9 -0
  76. package/dist/merge-objects.js +28 -0
  77. package/dist/named-views.d.ts +42 -0
  78. package/dist/named-views.js +80 -0
  79. package/dist/named-views.test.d.ts +1 -0
  80. package/dist/named-views.test.js +57 -0
  81. package/dist/new-features.test.d.ts +1 -0
  82. package/dist/new-features.test.js +183 -0
  83. package/dist/render-component.d.ts +13 -0
  84. package/dist/render-component.js +14 -0
  85. package/dist/render-component.test.d.ts +1 -0
  86. package/dist/render-component.test.js +41 -0
  87. package/dist/server-data-source.d.ts +76 -0
  88. package/dist/server-data-source.js +83 -0
  89. package/dist/server-data-source.test.d.ts +1 -0
  90. package/dist/server-data-source.test.js +81 -0
  91. package/dist/sparkline.d.ts +56 -0
  92. package/dist/sparkline.js +97 -0
  93. package/dist/sparkline.test.d.ts +1 -0
  94. package/dist/sparkline.test.js +52 -0
  95. package/dist/static-functions.d.ts +1 -0
  96. package/dist/static-functions.js +1 -0
  97. package/dist/subscribe.d.ts +9 -0
  98. package/dist/subscribe.js +31 -0
  99. package/dist/subscribe.test.d.ts +1 -0
  100. package/dist/subscribe.test.js +93 -0
  101. package/dist/sv-grid-scrollbar.d.ts +1 -0
  102. package/dist/sv-grid-scrollbar.js +310 -0
  103. package/dist/svgrid-wrapper.types.d.ts +341 -0
  104. package/dist/svgrid-wrapper.types.js +1 -0
  105. package/dist/svgrid.api-extensions.test.d.ts +14 -0
  106. package/dist/svgrid.api-extensions.test.js +334 -0
  107. package/dist/svgrid.api.test.d.ts +15 -0
  108. package/dist/svgrid.api.test.js +169 -0
  109. package/dist/svgrid.behavior.test.d.ts +15 -0
  110. package/dist/svgrid.behavior.test.js +605 -0
  111. package/dist/svgrid.column-reorder.test.d.ts +15 -0
  112. package/dist/svgrid.column-reorder.test.js +224 -0
  113. package/dist/svgrid.features.test.d.ts +1 -0
  114. package/dist/svgrid.features.test.js +129 -0
  115. package/dist/svgrid.interaction.test.d.ts +9 -0
  116. package/dist/svgrid.interaction.test.js +318 -0
  117. package/dist/svgrid.locale-filtering.test.d.ts +15 -0
  118. package/dist/svgrid.locale-filtering.test.js +261 -0
  119. package/dist/svgrid.new-features.wrapper.test.d.ts +1 -0
  120. package/dist/svgrid.new-features.wrapper.test.js +136 -0
  121. package/dist/svgrid.row-pinning.test.d.ts +14 -0
  122. package/dist/svgrid.row-pinning.test.js +250 -0
  123. package/dist/svgrid.set-filter.test.d.ts +17 -0
  124. package/dist/svgrid.set-filter.test.js +268 -0
  125. package/dist/svgrid.wrapper.test.d.ts +1 -0
  126. package/dist/svgrid.wrapper.test.js +33 -0
  127. package/dist/test-setup.d.ts +1 -0
  128. package/dist/test-setup.js +29 -0
  129. package/dist/transaction.test.d.ts +1 -0
  130. package/dist/transaction.test.js +89 -0
  131. package/dist/virtualization/column-virtualizer.d.ts +20 -0
  132. package/dist/virtualization/column-virtualizer.js +19 -0
  133. package/dist/virtualization/column-virtualizer.test.d.ts +1 -0
  134. package/dist/virtualization/column-virtualizer.test.js +25 -0
  135. package/dist/virtualization/svelte-virtualizer.svelte.d.ts +11 -0
  136. package/dist/virtualization/svelte-virtualizer.svelte.js +20 -0
  137. package/dist/virtualization/types.d.ts +28 -0
  138. package/dist/virtualization/types.js +1 -0
  139. package/dist/virtualization/virtualizer.d.ts +13 -0
  140. package/dist/virtualization/virtualizer.js +232 -0
  141. package/dist/virtualization/virtualizer.test.d.ts +1 -0
  142. package/dist/virtualization/virtualizer.test.js +41 -0
  143. package/package.json +69 -0
  144. package/src/FlexRender.svelte +96 -0
  145. package/src/SvGrid.svelte +8742 -0
  146. package/src/SvGridChart.svelte +653 -0
  147. package/src/SvGridChart.test.ts +69 -0
  148. package/src/SvGridDropdown.svelte +675 -0
  149. package/src/a11y.contract.test.ts +49 -0
  150. package/src/a11y.test.ts +59 -0
  151. package/src/a11y.ts +59 -0
  152. package/src/cell-formatting.test.ts +273 -0
  153. package/src/cell-formatting.ts +169 -0
  154. package/src/chart-export.ts +144 -0
  155. package/src/chart.test.ts +311 -0
  156. package/src/chart.ts +934 -0
  157. package/src/collaboration.test.ts +74 -0
  158. package/src/collaboration.ts +161 -0
  159. package/src/conditional-formatting.test.ts +107 -0
  160. package/src/conditional-formatting.ts +239 -0
  161. package/src/core.coverage.test.ts +230 -0
  162. package/src/core.performance.test.ts +30 -0
  163. package/src/core.ts +991 -0
  164. package/src/createGrid.svelte.ts +42 -0
  165. package/src/createGrid.test.ts +10 -0
  166. package/src/createGridState.svelte.ts +17 -0
  167. package/src/editors/cell-editors.test.ts +80 -0
  168. package/src/editors/cell-editors.ts +127 -0
  169. package/src/fill-patterns.test.ts +93 -0
  170. package/src/fill-patterns.ts +229 -0
  171. package/src/filtering/excel-filters.test.ts +131 -0
  172. package/src/filtering/excel-filters.ts +101 -0
  173. package/src/filtering/locale-filter.test.ts +220 -0
  174. package/src/flex-render.test.ts +143 -0
  175. package/src/flex-render.ts +3 -0
  176. package/src/group-aggregate.test.ts +48 -0
  177. package/src/index.ts +159 -0
  178. package/src/keyboard.test.ts +59 -0
  179. package/src/keyboard.ts +97 -0
  180. package/src/merge-objects.ts +48 -0
  181. package/src/named-views.test.ts +66 -0
  182. package/src/named-views.ts +120 -0
  183. package/src/new-features.test.ts +217 -0
  184. package/src/render-component.test.ts +51 -0
  185. package/src/render-component.ts +28 -0
  186. package/src/server-data-source.test.ts +88 -0
  187. package/src/server-data-source.ts +163 -0
  188. package/src/sparkline.test.ts +59 -0
  189. package/src/sparkline.ts +164 -0
  190. package/src/static-functions.ts +11 -0
  191. package/src/subscribe.test.ts +103 -0
  192. package/src/subscribe.ts +38 -0
  193. package/src/sv-grid-scrollbar.ts +347 -0
  194. package/src/svgrid-wrapper.types.ts +382 -0
  195. package/src/svgrid.api-extensions.test.ts +362 -0
  196. package/src/svgrid.api.test.ts +192 -0
  197. package/src/svgrid.behavior.test.ts +657 -0
  198. package/src/svgrid.column-reorder.test.ts +234 -0
  199. package/src/svgrid.features.test.ts +157 -0
  200. package/src/svgrid.interaction.test.ts +355 -0
  201. package/src/svgrid.locale-filtering.test.ts +259 -0
  202. package/src/svgrid.new-features.wrapper.test.ts +164 -0
  203. package/src/svgrid.row-pinning.test.ts +266 -0
  204. package/src/svgrid.set-filter.test.ts +270 -0
  205. package/src/svgrid.wrapper.test.ts +35 -0
  206. package/src/test-setup.ts +37 -0
  207. package/src/transaction.test.ts +100 -0
  208. package/src/virtualization/column-virtualizer.test.ts +27 -0
  209. package/src/virtualization/column-virtualizer.ts +30 -0
  210. package/src/virtualization/svelte-virtualizer.svelte.ts +24 -0
  211. package/src/virtualization/types.ts +30 -0
  212. package/src/virtualization/virtualizer.test.ts +47 -0
  213. package/src/virtualization/virtualizer.ts +270 -0
@@ -0,0 +1,232 @@
1
+ function clamp(value, min, max) {
2
+ return Math.min(Math.max(value, min), max);
3
+ }
4
+ function sameOptions(a, b) {
5
+ return (a.count === b.count &&
6
+ a.estimateSize === b.estimateSize &&
7
+ (a.overscan ?? 6) === (b.overscan ?? 6) &&
8
+ a.viewportHeight === b.viewportHeight &&
9
+ (a.scrollOffset ?? 0) === (b.scrollOffset ?? 0));
10
+ }
11
+ function sameState(a, b) {
12
+ if (a.totalSize !== b.totalSize ||
13
+ a.startIndex !== b.startIndex ||
14
+ a.endIndex !== b.endIndex ||
15
+ a.viewportHeight !== b.viewportHeight ||
16
+ a.items.length !== b.items.length) {
17
+ return false;
18
+ }
19
+ // Per-item start+size check: catches column-resize cases where the total
20
+ // is unchanged (e.g. column A grew, column B shrunk to compensate under
21
+ // fit-to-width). Without this, the virtualizer skips the emit and the
22
+ // grid renders with stale widths.
23
+ for (let i = 0; i < a.items.length; i += 1) {
24
+ const ai = a.items[i];
25
+ const bi = b.items[i];
26
+ if (ai.index !== bi.index || ai.start !== bi.start || ai.size !== bi.size)
27
+ return false;
28
+ }
29
+ return true;
30
+ }
31
+ // Slot-based keying: the key is the POSITION of the item inside the
32
+ // visible window (slot 0 = topmost rendered row, slot 1 = next, etc.)
33
+ // - NOT the data index. As the user scrolls, the window's startIndex
34
+ // changes but the slot keys stay the same (0..N-1), so Svelte recycles
35
+ // the existing <tr> DOM nodes and only updates their data + position.
36
+ //
37
+ // This avoids the mount/unmount churn that previously fired on every
38
+ // scroll tick: with data-index keys, scrolling down 1 row meant the old
39
+ // topmost key disappeared and a new bottommost key appeared, forcing
40
+ // Svelte to unmount the top <tr> and mount a fresh one at the bottom.
41
+ // Slot-based keys keep the same N <tr> nodes alive for the lifetime of
42
+ // the grid; scroll just translates them via the top spacer.
43
+ function buildUniformItems(startIndex, endIndex, estimateSize) {
44
+ const items = [];
45
+ for (let index = startIndex; index <= endIndex; index += 1) {
46
+ const start = index * estimateSize;
47
+ items.push({
48
+ index,
49
+ start,
50
+ size: estimateSize,
51
+ end: start + estimateSize,
52
+ key: `virtual_slot_${index - startIndex}`,
53
+ });
54
+ }
55
+ return items;
56
+ }
57
+ function buildVariableItems(startIndex, endIndex, offsets) {
58
+ const items = [];
59
+ for (let index = startIndex; index <= endIndex; index += 1) {
60
+ const start = offsets[index] ?? 0;
61
+ const end = offsets[index + 1] ?? start;
62
+ items.push({
63
+ index,
64
+ start,
65
+ size: end - start,
66
+ end,
67
+ key: `virtual_slot_${index - startIndex}`,
68
+ });
69
+ }
70
+ return items;
71
+ }
72
+ function createState(options,
73
+ /** Pre-built cumulative offsets for the variable-size path. */
74
+ offsets) {
75
+ const count = Math.max(options.count, 0);
76
+ const overscan = Math.max(options.overscan ?? 6, 0);
77
+ const viewportHeight = Math.max(options.viewportHeight, 0);
78
+ if (typeof options.estimateSize === 'function' && offsets) {
79
+ const totalSize = offsets[count] ?? 0;
80
+ const maxOffset = Math.max(totalSize - viewportHeight, 0);
81
+ const scrollOffset = clamp(options.scrollOffset ?? 0, 0, maxOffset);
82
+ // First index whose end > scrollOffset.
83
+ let lo = 0;
84
+ let hi = count;
85
+ while (lo < hi) {
86
+ const mid = (lo + hi) >>> 1;
87
+ if ((offsets[mid + 1] ?? 0) <= scrollOffset)
88
+ lo = mid + 1;
89
+ else
90
+ hi = mid;
91
+ }
92
+ const visibleStart = lo;
93
+ // First index whose start >= scrollOffset + viewportHeight.
94
+ const viewportEnd = scrollOffset + viewportHeight;
95
+ lo = visibleStart;
96
+ hi = count;
97
+ while (lo < hi) {
98
+ const mid = (lo + hi) >>> 1;
99
+ if ((offsets[mid] ?? 0) < viewportEnd)
100
+ lo = mid + 1;
101
+ else
102
+ hi = mid;
103
+ }
104
+ const visibleEnd = Math.max(lo - 1, visibleStart);
105
+ const startIndex = count === 0 ? 0 : clamp(visibleStart - overscan, 0, count - 1);
106
+ const endIndex = count === 0 ? -1 : clamp(visibleEnd + overscan, 0, count - 1);
107
+ return {
108
+ items: endIndex >= startIndex ? buildVariableItems(startIndex, endIndex, offsets) : [],
109
+ totalSize,
110
+ startIndex,
111
+ endIndex,
112
+ scrollOffset,
113
+ viewportHeight,
114
+ };
115
+ }
116
+ // Uniform-size fast path (original behavior).
117
+ const estimateSize = Math.max(typeof options.estimateSize === 'number' ? options.estimateSize : 1, 1);
118
+ const totalSize = count * estimateSize;
119
+ const maxOffset = Math.max(totalSize - viewportHeight, 0);
120
+ const scrollOffset = clamp(options.scrollOffset ?? 0, 0, maxOffset);
121
+ const visibleStart = Math.floor(scrollOffset / estimateSize);
122
+ const visibleCount = Math.ceil(viewportHeight / estimateSize);
123
+ const visibleEnd = Math.min(visibleStart + visibleCount, Math.max(count - 1, 0));
124
+ const startIndex = count === 0 ? 0 : clamp(visibleStart - overscan, 0, count - 1);
125
+ const endIndex = count === 0 ? -1 : clamp(visibleEnd + overscan, 0, count - 1);
126
+ return {
127
+ items: endIndex >= startIndex ? buildUniformItems(startIndex, endIndex, estimateSize) : [],
128
+ totalSize,
129
+ startIndex,
130
+ endIndex,
131
+ scrollOffset,
132
+ viewportHeight,
133
+ };
134
+ }
135
+ export function createVirtualizer(initial) {
136
+ let options = initial;
137
+ let offsetCache = null;
138
+ function getOffsets() {
139
+ if (typeof options.estimateSize !== 'function')
140
+ return null;
141
+ const count = Math.max(options.count, 0);
142
+ if (offsetCache &&
143
+ offsetCache.fn === options.estimateSize &&
144
+ offsetCache.count === count) {
145
+ return offsetCache.offsets;
146
+ }
147
+ const sizeFn = options.estimateSize;
148
+ const offsets = new Array(count + 1);
149
+ offsets[0] = 0;
150
+ for (let i = 0; i < count; i += 1) {
151
+ offsets[i + 1] = offsets[i] + Math.max(sizeFn(i), 1);
152
+ }
153
+ offsetCache = { fn: sizeFn, count, offsets };
154
+ return offsets;
155
+ }
156
+ let state = createState(options, getOffsets());
157
+ const listeners = new Set();
158
+ function emit() {
159
+ listeners.forEach((listener) => listener());
160
+ }
161
+ function recalc() {
162
+ const next = createState(options, getOffsets());
163
+ if (sameState(state, next))
164
+ return;
165
+ state = next;
166
+ emit();
167
+ }
168
+ return {
169
+ setOptions(next) {
170
+ const merged = { ...options, ...next };
171
+ if (sameOptions(options, merged))
172
+ return;
173
+ options = merged;
174
+ recalc();
175
+ },
176
+ setScrollOffset(scrollOffset) {
177
+ if ((options.scrollOffset ?? 0) === scrollOffset)
178
+ return;
179
+ options = { ...options, scrollOffset };
180
+ recalc();
181
+ },
182
+ setViewportHeight(viewportHeight) {
183
+ if (options.viewportHeight === viewportHeight)
184
+ return;
185
+ options = { ...options, viewportHeight };
186
+ recalc();
187
+ },
188
+ scrollToIndex(index) {
189
+ const boundedIndex = clamp(index, 0, Math.max(options.count - 1, 0));
190
+ // Read the current state's totals so the offset is correct under both
191
+ // uniform and per-index sizing.
192
+ const totalSize = state.totalSize;
193
+ let targetOffset;
194
+ if (typeof options.estimateSize === 'function') {
195
+ // Use the cached cumulative offsets if present.
196
+ const offsets = getOffsets();
197
+ if (offsets) {
198
+ targetOffset = offsets[boundedIndex] ?? 0;
199
+ }
200
+ else {
201
+ let acc = 0;
202
+ const sizeFn = options.estimateSize;
203
+ for (let i = 0; i < boundedIndex; i += 1)
204
+ acc += Math.max(sizeFn(i), 1);
205
+ targetOffset = acc;
206
+ }
207
+ }
208
+ else {
209
+ targetOffset = boundedIndex * Math.max(options.estimateSize, 1);
210
+ }
211
+ const maxOffset = Math.max(totalSize - options.viewportHeight, 0);
212
+ const nextOffset = clamp(targetOffset, 0, maxOffset);
213
+ if ((options.scrollOffset ?? 0) === nextOffset)
214
+ return;
215
+ options = { ...options, scrollOffset: nextOffset };
216
+ recalc();
217
+ },
218
+ getVirtualItems() {
219
+ return state.items;
220
+ },
221
+ getTotalSize() {
222
+ return state.totalSize;
223
+ },
224
+ getState() {
225
+ return state;
226
+ },
227
+ subscribe(listener) {
228
+ listeners.add(listener);
229
+ return () => listeners.delete(listener);
230
+ },
231
+ };
232
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,41 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { createVirtualizer } from './virtualizer';
3
+ describe('virtualizer', () => {
4
+ it('computes bounded virtual range with overscan', () => {
5
+ const v = createVirtualizer({
6
+ count: 100000,
7
+ estimateSize: 36,
8
+ overscan: 8,
9
+ viewportHeight: 360,
10
+ scrollOffset: 0,
11
+ });
12
+ const items = v.getVirtualItems();
13
+ expect(items.length).toBeGreaterThan(0);
14
+ expect(items[0]?.index).toBe(0);
15
+ expect(items[items.length - 1]?.index).toBe(18);
16
+ });
17
+ it('updates range when scroll offset changes', () => {
18
+ const v = createVirtualizer({
19
+ count: 100000,
20
+ estimateSize: 40,
21
+ overscan: 5,
22
+ viewportHeight: 400,
23
+ scrollOffset: 0,
24
+ });
25
+ v.setScrollOffset(4000);
26
+ const state = v.getState();
27
+ expect(state.startIndex).toBeLessThanOrEqual(100);
28
+ expect(state.endIndex).toBeGreaterThanOrEqual(110);
29
+ });
30
+ it('scrollToIndex clamps target offset', () => {
31
+ const v = createVirtualizer({
32
+ count: 100,
33
+ estimateSize: 30,
34
+ overscan: 2,
35
+ viewportHeight: 300,
36
+ scrollOffset: 0,
37
+ });
38
+ v.scrollToIndex(9999);
39
+ expect(v.getState().scrollOffset).toBe(2700);
40
+ });
41
+ });
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@svgrid/grid",
3
+ "version": "1.0.0",
4
+ "description": "SvGrid - a headless-first, Svelte 5-native data grid engine and render component.",
5
+ "author": "jQWidgets <boikom@jqwidgets.com>",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/sv-grid/sv-grid.git",
10
+ "directory": "packages/grid"
11
+ },
12
+ "homepage": "https://svgrid.com",
13
+ "keywords": [
14
+ "svelte",
15
+ "grid",
16
+ "table",
17
+ "headless",
18
+ "datagrid"
19
+ ],
20
+ "type": "module",
21
+ "types": "dist/index.d.ts",
22
+ "module": "dist/index.js",
23
+ "svelte": "./dist/index.js",
24
+ "exports": {
25
+ ".": {
26
+ "types": "./dist/index.d.ts",
27
+ "svelte": "./dist/index.js",
28
+ "import": "./dist/index.js"
29
+ },
30
+ "./static-functions": {
31
+ "types": "./dist/static-functions.d.ts",
32
+ "svelte": "./dist/static-functions.js",
33
+ "import": "./dist/static-functions.js"
34
+ },
35
+ "./flex-render": {
36
+ "types": "./dist/flex-render.d.ts",
37
+ "svelte": "./dist/flex-render.js",
38
+ "import": "./dist/flex-render.js"
39
+ },
40
+ "./package.json": "./package.json"
41
+ },
42
+ "engines": {
43
+ "node": ">=16"
44
+ },
45
+ "files": [
46
+ "dist",
47
+ "src"
48
+ ],
49
+ "scripts": {
50
+ "clean": "rimraf ./build && rimraf ./dist",
51
+ "test:eslint": "eslint ./src",
52
+ "test:types": "svelte-check --tsconfig ./tsconfig.json",
53
+ "test:lib": "vitest run --coverage",
54
+ "test:build": "publint --strict",
55
+ "build": "svelte-package --input ./src --output ./dist"
56
+ },
57
+ "devDependencies": {
58
+ "@sveltejs/package": "^2.5.7",
59
+ "@sveltejs/vite-plugin-svelte": "^7.0.0",
60
+ "@vitest/coverage-v8": "^4.1.5",
61
+ "eslint-plugin-svelte": "^3.17.1",
62
+ "jsdom": "^29.1.1",
63
+ "svelte": "^5.55.5",
64
+ "svelte-check": "^4.4.6"
65
+ },
66
+ "peerDependencies": {
67
+ "svelte": "^5.0.0"
68
+ }
69
+ }
@@ -0,0 +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}