@svgrid/grid 1.0.2 → 1.1.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 (143) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +137 -39
  3. package/dist/GridFooter.svelte +164 -0
  4. package/dist/GridFooter.svelte.d.ts +29 -0
  5. package/dist/GridMenus.svelte +570 -0
  6. package/dist/GridMenus.svelte.d.ts +31 -0
  7. package/dist/SvGrid.controller.svelte.d.ts +429 -0
  8. package/dist/SvGrid.controller.svelte.js +1732 -0
  9. package/dist/SvGrid.css +1709 -0
  10. package/dist/SvGrid.helpers.d.ts +35 -0
  11. package/dist/SvGrid.helpers.js +160 -0
  12. package/dist/SvGrid.svelte +344 -7043
  13. package/dist/SvGrid.svelte.d.ts +4 -357
  14. package/dist/SvGrid.types.d.ts +436 -0
  15. package/dist/SvGrid.types.js +1 -0
  16. package/dist/SvGridChart.svelte +1060 -23
  17. package/dist/SvGridChart.svelte.d.ts +17 -0
  18. package/dist/build-api.d.ts +5 -0
  19. package/dist/build-api.js +527 -0
  20. package/dist/cell-render.d.ts +15 -0
  21. package/dist/cell-render.js +246 -0
  22. package/dist/cell-values.d.ts +28 -0
  23. package/dist/cell-values.js +89 -0
  24. package/dist/chart.d.ts +370 -3
  25. package/dist/chart.js +1135 -42
  26. package/dist/clipboard.d.ts +15 -0
  27. package/dist/clipboard.js +356 -0
  28. package/dist/columns.d.ts +30 -0
  29. package/dist/columns.js +277 -0
  30. package/dist/core.d.ts +1 -1
  31. package/dist/css.d.ts +3 -0
  32. package/dist/editing.d.ts +24 -0
  33. package/dist/editing.js +343 -0
  34. package/dist/editors/cell-editors.d.ts +1 -1
  35. package/dist/facet-buckets.d.ts +13 -0
  36. package/dist/facet-buckets.js +54 -0
  37. package/dist/features.d.ts +5 -0
  38. package/dist/features.js +30 -0
  39. package/dist/filter-operators.d.ts +16 -0
  40. package/dist/filter-operators.js +69 -0
  41. package/dist/hyperformula-adapter.d.ts +82 -0
  42. package/dist/hyperformula-adapter.js +73 -0
  43. package/dist/index.d.ts +5 -2
  44. package/dist/index.js +5 -2
  45. package/dist/keyboard-handlers.d.ts +7 -0
  46. package/dist/keyboard-handlers.js +197 -0
  47. package/dist/menus.d.ts +40 -0
  48. package/dist/menus.js +389 -0
  49. package/dist/named-views.d.ts +27 -0
  50. package/dist/named-views.js +39 -0
  51. package/dist/row-resize.d.ts +43 -0
  52. package/dist/row-resize.js +158 -0
  53. package/dist/scroll-sync.d.ts +9 -0
  54. package/dist/scroll-sync.js +86 -0
  55. package/dist/selection.d.ts +26 -0
  56. package/dist/selection.js +387 -0
  57. package/dist/spreadsheet.d.ts +80 -0
  58. package/dist/spreadsheet.js +194 -0
  59. package/dist/summaries.d.ts +12 -0
  60. package/dist/summaries.js +65 -0
  61. package/dist/svgrid-wrapper.types.d.ts +12 -1
  62. package/dist/svgrid.comments-autocomplete.test.d.ts +1 -0
  63. package/dist/svgrid.comments-autocomplete.test.js +96 -0
  64. package/dist/svgrid.context-menu.test.d.ts +1 -0
  65. package/dist/svgrid.context-menu.test.js +102 -0
  66. package/dist/svgrid.new-features.wrapper.test.js +30 -4
  67. package/dist/svgrid.wrapper.test.js +27 -1
  68. package/dist/virtualization/column-virtualizer.d.ts +2 -0
  69. package/dist/virtualization/scroll-scaling.d.ts +28 -0
  70. package/dist/virtualization/scroll-scaling.js +64 -0
  71. package/dist/virtualization/scroll-scaling.test.d.ts +1 -0
  72. package/dist/virtualization/scroll-scaling.test.js +86 -0
  73. package/dist/virtualization/svelte-virtualizer.svelte.d.ts +2 -0
  74. package/dist/virtualization/svelte-virtualizer.svelte.js +2 -0
  75. package/dist/virtualization/virtualizer.d.ts +7 -0
  76. package/dist/virtualization/virtualizer.js +30 -0
  77. package/package.json +1 -1
  78. package/src/GridFooter.svelte +164 -0
  79. package/src/GridMenus.svelte +570 -0
  80. package/src/SvGrid.controller.svelte.ts +2195 -0
  81. package/src/SvGrid.css +1747 -0
  82. package/src/SvGrid.helpers.test.ts +415 -0
  83. package/src/SvGrid.helpers.ts +185 -0
  84. package/src/SvGrid.svelte +348 -7043
  85. package/src/SvGrid.types.ts +456 -0
  86. package/src/SvGridChart.svelte +1060 -23
  87. package/src/build-api.coverage.test.ts +532 -0
  88. package/src/build-api.ts +663 -0
  89. package/src/cell-render.test.ts +451 -0
  90. package/src/cell-render.ts +426 -0
  91. package/src/cell-values.ts +114 -0
  92. package/src/chart-export.test.ts +370 -0
  93. package/src/chart.coverage.test.ts +814 -0
  94. package/src/chart.ts +1352 -47
  95. package/src/clipboard.test.ts +731 -0
  96. package/src/clipboard.ts +524 -0
  97. package/src/collaboration.coverage.test.ts +220 -0
  98. package/src/columns.test.ts +702 -0
  99. package/src/columns.ts +419 -0
  100. package/src/core.ts +8 -0
  101. package/src/css.d.ts +3 -0
  102. package/src/editing.test.ts +837 -0
  103. package/src/editing.ts +513 -0
  104. package/src/editors/cell-editors.coverage.test.ts +156 -0
  105. package/src/editors/cell-editors.ts +1 -0
  106. package/src/facet-buckets.test.ts +353 -0
  107. package/src/facet-buckets.ts +67 -0
  108. package/src/features.ts +128 -0
  109. package/src/filter-operators.test.ts +174 -0
  110. package/src/filter-operators.ts +87 -0
  111. package/src/hyperformula-adapter.test.ts +256 -0
  112. package/src/hyperformula-adapter.ts +124 -0
  113. package/src/index.ts +37 -0
  114. package/src/keyboard-handlers.coverage.test.ts +560 -0
  115. package/src/keyboard-handlers.ts +353 -0
  116. package/src/keyboard.ts +97 -97
  117. package/src/menus.test.ts +620 -0
  118. package/src/menus.ts +554 -0
  119. package/src/named-views.coverage.test.ts +210 -0
  120. package/src/named-views.ts +48 -0
  121. package/src/row-resize.test.ts +369 -0
  122. package/src/row-resize.ts +171 -0
  123. package/src/scroll-sync.test.ts +330 -0
  124. package/src/scroll-sync.ts +216 -0
  125. package/src/selection.test.ts +722 -0
  126. package/src/selection.ts +545 -0
  127. package/src/server-data-source.coverage.test.ts +180 -0
  128. package/src/spreadsheet.test.ts +445 -0
  129. package/src/spreadsheet.ts +246 -0
  130. package/src/summaries.ts +204 -0
  131. package/src/sv-grid-scrollbar.ts +13 -1
  132. package/src/svgrid-wrapper.types.ts +12 -1
  133. package/src/svgrid.behavior.test.ts +22 -0
  134. package/src/svgrid.comments-autocomplete.test.ts +112 -0
  135. package/src/svgrid.context-menu.test.ts +126 -0
  136. package/src/svgrid.interaction.test.ts +30 -0
  137. package/src/svgrid.new-features.wrapper.test.ts +65 -4
  138. package/src/svgrid.wrapper.test.ts +27 -1
  139. package/src/test-setup.ts +9 -6
  140. package/src/virtualization/scroll-scaling.test.ts +148 -0
  141. package/src/virtualization/scroll-scaling.ts +121 -0
  142. package/src/virtualization/svelte-virtualizer.svelte.ts +2 -0
  143. package/src/virtualization/virtualizer.ts +26 -0
package/src/columns.ts ADDED
@@ -0,0 +1,419 @@
1
+ // columns handlers extracted from the controller. Imperative event handlers
2
+ // reading/writing controller state via the `ctx` handle; the reactive core
3
+ // ($state/$derived/$effect) stays in the controller.
4
+ import {
5
+ applyExcelFilter,
6
+ normalizeForFilter,
7
+ createColumnVirtualizer,
8
+ createCoreRowModel,
9
+ createExpandedRowModel,
10
+ createFilteredRowModel,
11
+ createGroupedRowModel,
12
+ createPaginatedRowModel,
13
+ createSvelteVirtualizer,
14
+ createSortedRowModel,
15
+ createSvGrid,
16
+ filterFns,
17
+ getGridCellA11yProps,
18
+ getGridCellDomId,
19
+ getGridHeaderA11yProps,
20
+ getGridRootA11yProps,
21
+ getGridRowA11yProps,
22
+ parseEditorValue,
23
+ normalizeEditorOptions,
24
+ sortFns,
25
+ tableFeatures,
26
+ rowSortingFeature,
27
+ columnFilteringFeature,
28
+ columnGroupingFeature,
29
+ type CellContext,
30
+ type EditorContext,
31
+ type CellEditorOption,
32
+ type CellEditorType,
33
+ type CellFormatter,
34
+ type CellFormatConfig,
35
+ type Column,
36
+ type ColumnDef,
37
+ type Row,
38
+ type RowData,
39
+ type SvGridApi,
40
+ type TableFeatures,
41
+ } from "./index";
42
+ import "./sv-grid-scrollbar";
43
+ import type { Snippet } from "svelte";
44
+ import { getKeyboardIntent, getNextActiveCell } from "./keyboard";
45
+ import {
46
+ formatNumericWithConfig,
47
+ getDateFormatter,
48
+ resolveDatePattern,
49
+ } from "./cell-formatting";
50
+ import {
51
+ RenderSnippetConfig,
52
+ RenderComponentConfig,
53
+ } from "./render-component";
54
+ import { buildFillPattern } from "./fill-patterns";
55
+ import { buildSparkline, toSparklineValues } from "./sparkline";
56
+ import {
57
+ resolveCellFormat,
58
+ computeColumnStat,
59
+ formatsNeedingStats,
60
+ type ColumnStat,
61
+ type ResolvedCellFormat,
62
+ } from "./conditional-formatting";
63
+ import SvGridDropdown from "./SvGridDropdown.svelte";
64
+ import type {
65
+ Props,
66
+ SelectionPoint,
67
+ SelectionRange,
68
+ CellEditState,
69
+ FilterOperator,
70
+ FilterOption,
71
+ MenuPosition,
72
+ } from "./SvGrid.types";
73
+ import {
74
+ cfTextStyle,
75
+ fmtStat,
76
+ getCellKey,
77
+ resolveClassList,
78
+ toDateInputValue,
79
+ toDateTimeLocalInputValue,
80
+ getEditableInputValue,
81
+ getEditorInputType,
82
+ toValueArray,
83
+ getOptionLabel,
84
+ getOptionColor,
85
+ colorfulChipStyle,
86
+ getEditorClass,
87
+ asDate,
88
+ clampMenuX,
89
+ cssEscape,
90
+ rawToNumber,
91
+ formatFacetNumber,
92
+ formatFacetDate,
93
+ } from "./SvGrid.helpers";
94
+ import { createGridApi } from "./build-api";
95
+ import { createClipboard } from "./clipboard";
96
+ import {
97
+ filterOperatorOptions,
98
+ fallbackOperatorOption,
99
+ TEXT_OPERATORS,
100
+ NUMBER_OPERATORS,
101
+ DATE_OPERATORS,
102
+ CHECKBOX_OPERATORS,
103
+ operatorOption,
104
+ operatorsForColumn,
105
+ defaultOperatorFor,
106
+ operatorLabelFor,
107
+ } from "./filter-operators";
108
+ import {
109
+ type FacetBucket,
110
+ isBucketableColumn,
111
+ buildBuckets,
112
+ isInBucket,
113
+ } from "./facet-buckets";
114
+ import {
115
+ getColumnBaseValue,
116
+ isGroupRow,
117
+ toolPanelHeaderLabel,
118
+ formatSummaryNumeric,
119
+ getColumnAlign,
120
+ getPinnedCellValue,
121
+ getColumnAccessorValue,
122
+ columnDefMatchesId,
123
+ } from "./cell-values";
124
+
125
+ export function createColumns<
126
+ TFeatures extends TableFeatures = TableFeatures,
127
+ TData extends RowData = RowData,
128
+ >(ctx: any) {
129
+ function cellPinStyle(columnId: string): string {
130
+ // z-index 30 - higher than the active-cell / selection-range stacking
131
+ // context (z=20) so a selected cell in the scrollable middle never
132
+ // bleeds over the pinned columns during horizontal scroll. Still
133
+ // sits below dropdowns (z=900+) and the column menu.
134
+ const leftOffset = ctx.pinnedOffsets.left[columnId];
135
+ if (leftOffset !== undefined) {
136
+ return `position: sticky; left: ${leftOffset}px; z-index: 30;`;
137
+ }
138
+ const rightOffset = ctx.pinnedOffsets.right[columnId];
139
+ if (rightOffset !== undefined) {
140
+ return `position: sticky; right: ${rightOffset}px; z-index: 30;`;
141
+ }
142
+ return "";
143
+ }
144
+
145
+ function isColumnPinned(columnId: string): "left" | "right" | null {
146
+ if (ctx.columnPinning.left.includes(columnId)) return "left";
147
+ if (ctx.columnPinning.right.includes(columnId)) return "right";
148
+ return null;
149
+ }
150
+
151
+ /** Compute the current full column order as displayed (pinned-left
152
+ * first, unpinned in the middle, pinned-right last). The order
153
+ * emitted via `onColumnOrderChange` matches what the user sees. */
154
+ function getCurrentColumnOrder(): string[] {
155
+ return ctx.allColumns.map((c: any) => c.id);
156
+ }
157
+
158
+ function emitColumnOrder() {
159
+ ctx.props.onColumnOrderChange?.(getCurrentColumnOrder());
160
+ }
161
+
162
+ function setColumnOrderInternal(ids: ReadonlyArray<string>) {
163
+ ctx.userColumnOrder = [...ids];
164
+ emitColumnOrder();
165
+ }
166
+
167
+ /** Drop `dragId` before / after `targetId` in the user order. We
168
+ * rebuild a clean order out of the currently-displayed columns so
169
+ * hidden columns are unaffected and pin groups stay logically
170
+ * separate (you can reorder freely within left-pinned / unpinned /
171
+ * right-pinned, but a drop across pin zones is allowed - the cell
172
+ * just lands in whichever zone the target belongs to). */
173
+ function applyColumnDrop(dragId: string, targetId: string, side: "before" | "after") {
174
+ if (dragId === targetId) return;
175
+ const current = getCurrentColumnOrder();
176
+ const without = current.filter((id: any) => id !== dragId);
177
+ let idx = without.indexOf(targetId);
178
+ if (idx < 0) return;
179
+ if (side === "after") idx++;
180
+ without.splice(idx, 0, dragId);
181
+ setColumnOrderInternal(without);
182
+ }
183
+
184
+ function onColumnHeaderDragStart(e: DragEvent, columnId: string) {
185
+ if (!(ctx.props.enableColumnReorder ?? false)) return;
186
+ ctx.colDragId = columnId;
187
+ e.dataTransfer?.setData("text/plain", columnId);
188
+ e.dataTransfer!.effectAllowed = "move";
189
+ }
190
+
191
+ function onColumnHeaderDragOver(e: DragEvent, columnId: string) {
192
+ if (!ctx.colDragId || ctx.colDragId === columnId) return;
193
+ e.preventDefault();
194
+ e.dataTransfer!.dropEffect = "move";
195
+ const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
196
+ ctx.colDropSide = e.clientX < rect.left + rect.width / 2 ? "before" : "after";
197
+ ctx.colDropOnId = columnId;
198
+ }
199
+
200
+ function onColumnHeaderDragLeave(columnId: string) {
201
+ if (ctx.colDropOnId === columnId) { ctx.colDropOnId = null; ctx.colDropSide = null; }
202
+ }
203
+
204
+ function onColumnHeaderDrop(e: DragEvent, columnId: string) {
205
+ e.preventDefault();
206
+ if (ctx.colDragId && ctx.colDropSide) applyColumnDrop(ctx.colDragId, columnId, ctx.colDropSide);
207
+ ctx.colDragId = null; ctx.colDropOnId = null; ctx.colDropSide = null;
208
+ }
209
+
210
+ function onColumnHeaderDragEnd() {
211
+ ctx.colDragId = null; ctx.colDropOnId = null; ctx.colDropSide = null;
212
+ }
213
+
214
+ function pinColumnLeft(columnId: string) {
215
+ const left = ctx.columnPinning.left.filter((id: any) => id !== columnId);
216
+ const right = ctx.columnPinning.right.filter((id: any) => id !== columnId);
217
+ ctx.columnPinning = { left: [...left, columnId], right };
218
+ ctx.closeMenus();
219
+ }
220
+
221
+ function pinColumnRight(columnId: string) {
222
+ const left = ctx.columnPinning.left.filter((id: any) => id !== columnId);
223
+ const right = ctx.columnPinning.right.filter((id: any) => id !== columnId);
224
+ ctx.columnPinning = { left, right: [columnId, ...right] };
225
+ ctx.closeMenus();
226
+ }
227
+
228
+ function unpinColumn(columnId: string) {
229
+ ctx.columnPinning = {
230
+ left: ctx.columnPinning.left.filter((id: any) => id !== columnId),
231
+ right: ctx.columnPinning.right.filter((id: any) => id !== columnId),
232
+ };
233
+ ctx.closeMenus();
234
+ }
235
+
236
+ function toggleColumnVisibleInPanel(columnId: string) {
237
+ if (ctx.hiddenColumns[columnId]) {
238
+ const next = { ...ctx.hiddenColumns };
239
+ delete next[columnId];
240
+ ctx.hiddenColumns = next;
241
+ } else {
242
+ ctx.hiddenColumns = { ...ctx.hiddenColumns, [columnId]: true };
243
+ }
244
+ }
245
+
246
+ function moveColumnInPanel(columnId: string, dir: -1 | 1) {
247
+ const current = ctx.toolPanelColumns.map((c: any) => c.id);
248
+ const i = current.indexOf(columnId);
249
+ const j = i + dir;
250
+ if (i < 0 || j < 0 || j >= current.length) return;
251
+ [current[i], current[j]] = [current[j]!, current[i]!];
252
+ ctx.userColumnOrder = current;
253
+ }
254
+
255
+ function toggleGroupInPanel(columnId: string) {
256
+ const g = (ctx.grid.getState().grouping ?? []) as string[];
257
+ ctx.grid.setGrouping(
258
+ g.includes(columnId)
259
+ ? g.filter((x) => x !== columnId)
260
+ : [...g, columnId],
261
+ );
262
+ }
263
+
264
+ /** Width before fitColumns scaling - what the columnDef/user actually set. */
265
+ function getColumnBaseWidth(columnId: string) {
266
+ if (ctx.columnWidths[columnId] !== undefined) return ctx.columnWidths[columnId];
267
+ const column = ctx.grid.getAllColumns().find((c: any) => c.id === columnId);
268
+ if (column?.columnDef.width !== undefined) return column.columnDef.width;
269
+ return ctx.props.columnWidth ?? 140;
270
+ }
271
+
272
+ function getColumnWidth(columnId: string) {
273
+ const fitted = ctx.fittedColumnWidths?.[columnId];
274
+ if (fitted !== undefined && ctx.columnWidths[columnId] === undefined)
275
+ return fitted;
276
+ return getColumnBaseWidth(columnId);
277
+ }
278
+
279
+ function startColumnResize(event: PointerEvent, columnId: string) {
280
+ event.stopPropagation();
281
+ event.preventDefault();
282
+ ctx.resizingColumnId = columnId;
283
+ ctx.resizeStartX = event.clientX;
284
+ ctx.resizeStartWidth = getColumnWidth(columnId);
285
+ document.addEventListener("pointermove", onColumnResizeMove);
286
+ document.addEventListener("pointerup", endColumnResize);
287
+ document.addEventListener("pointercancel", endColumnResize);
288
+ }
289
+
290
+ function onColumnResizeMove(event: PointerEvent) {
291
+ if (!ctx.resizingColumnId) return;
292
+ // Coalesce updates onto the animation frame: pointermove can fire many
293
+ // times per frame, and each $state mutation triggers a full reactive
294
+ // recompute of the column-layout pipeline. Without rAF coalescing the
295
+ // grid stutters during the drag.
296
+ ctx.resizePendingWidth = Math.max(
297
+ ctx.MIN_COLUMN_WIDTH,
298
+ ctx.resizeStartWidth + (event.clientX - ctx.resizeStartX),
299
+ );
300
+ if (ctx.resizeRaf !== null) return;
301
+ ctx.resizeRaf = requestAnimationFrame(() => {
302
+ ctx.resizeRaf = null;
303
+ if (!ctx.resizingColumnId) return;
304
+ ctx.columnWidths = {
305
+ ...ctx.columnWidths,
306
+ [ctx.resizingColumnId]: ctx.resizePendingWidth,
307
+ };
308
+ });
309
+ }
310
+
311
+ function endColumnResize() {
312
+ if (ctx.resizeRaf !== null) {
313
+ cancelAnimationFrame(ctx.resizeRaf);
314
+ ctx.resizeRaf = null;
315
+ }
316
+ if (ctx.resizingColumnId && ctx.resizePendingWidth) {
317
+ // Make sure the final width is committed even if the last rAF was
318
+ // canceled mid-flight.
319
+ ctx.columnWidths = {
320
+ ...ctx.columnWidths,
321
+ [ctx.resizingColumnId]: ctx.resizePendingWidth,
322
+ };
323
+ }
324
+ ctx.resizingColumnId = null;
325
+ document.removeEventListener("pointermove", onColumnResizeMove);
326
+ document.removeEventListener("pointerup", endColumnResize);
327
+ document.removeEventListener("pointercancel", endColumnResize);
328
+ }
329
+
330
+ function measureText(text: string, font: string): number {
331
+ if (!text) return 0;
332
+ if (!ctx.measureCanvas) ctx.measureCanvas = document.createElement("canvas");
333
+ const c2d = ctx.measureCanvas.getContext("2d");
334
+ if (!c2d) return 0;
335
+ c2d.font = font;
336
+ return c2d.measureText(text).width;
337
+ }
338
+
339
+ /** Snap a column to the width of its widest visible cell (header + body). */
340
+ function autosizeColumn(columnId: string) {
341
+ if (!ctx.gridRootEl) return;
342
+ const sampleCell = (ctx.gridRootEl as HTMLElement).querySelector<HTMLElement>(
343
+ `[data-col-id="${CSS.escape(columnId)}"]`,
344
+ );
345
+ if (!sampleCell) return;
346
+ const cellFont = getComputedStyle(sampleCell).font;
347
+
348
+ let max = ctx.MIN_COLUMN_WIDTH;
349
+ const header = (ctx.gridRootEl as HTMLElement).querySelector<HTMLElement>(
350
+ `[data-svgrid-header-col="${CSS.escape(columnId)}"]`,
351
+ );
352
+ if (header) {
353
+ const labelEl = header.querySelector<HTMLElement>(
354
+ ".sv-grid-header-label",
355
+ );
356
+ const target = labelEl ?? header;
357
+ const text = target.textContent ?? "";
358
+ // +70 reserves room for sort indicator + funnel + 3-dot menu button
359
+ max = Math.max(
360
+ max,
361
+ measureText(text, getComputedStyle(target).font) + 70,
362
+ );
363
+ }
364
+
365
+ const cells = (ctx.gridRootEl as HTMLElement).querySelectorAll<HTMLElement>(
366
+ `[data-col-id="${CSS.escape(columnId)}"]`,
367
+ );
368
+ cells.forEach((cell: any) => {
369
+ const text = cell.textContent ?? "";
370
+ const w = measureText(text, cellFont);
371
+ if (w > max) max = w;
372
+ });
373
+
374
+ // cell horizontal padding (~16px) + 8px breathing room
375
+ ctx.columnWidths = {
376
+ ...ctx.columnWidths,
377
+ [columnId]: Math.max(ctx.MIN_COLUMN_WIDTH, Math.ceil(max) + 24),
378
+ };
379
+ }
380
+
381
+ function autosizeAllColumns() {
382
+ for (const column of ctx.allColumns) autosizeColumn(column.id);
383
+ }
384
+
385
+ function resetColumns() {
386
+ ctx.columnWidths = {};
387
+ ctx.hiddenColumns = {};
388
+ ctx.columnPinning = { left: [], right: [] };
389
+ }
390
+
391
+ return {
392
+ cellPinStyle,
393
+ isColumnPinned,
394
+ getCurrentColumnOrder,
395
+ emitColumnOrder,
396
+ setColumnOrderInternal,
397
+ applyColumnDrop,
398
+ onColumnHeaderDragStart,
399
+ onColumnHeaderDragOver,
400
+ onColumnHeaderDragLeave,
401
+ onColumnHeaderDrop,
402
+ onColumnHeaderDragEnd,
403
+ pinColumnLeft,
404
+ pinColumnRight,
405
+ unpinColumn,
406
+ toggleColumnVisibleInPanel,
407
+ moveColumnInPanel,
408
+ toggleGroupInPanel,
409
+ getColumnBaseWidth,
410
+ getColumnWidth,
411
+ startColumnResize,
412
+ onColumnResizeMove,
413
+ endColumnResize,
414
+ measureText,
415
+ autosizeColumn,
416
+ autosizeAllColumns,
417
+ resetColumns,
418
+ };
419
+ }
package/src/core.ts CHANGED
@@ -165,6 +165,7 @@ export type ColumnDef<TFeatures extends TableFeatures, TData extends RowData> =
165
165
  | 'chips'
166
166
  | 'select' // custom dropdown - single value, no typeahead
167
167
  | 'rich-select' // custom dropdown with a typeahead search input
168
+ | 'autocomplete' // free-text input with a live-filtered suggestion list (accepts any value)
168
169
  | 'textarea' // multi-line editor; Tab or Ctrl+Enter commits, plain Enter inserts a newline
169
170
  | 'color' // native <input type="color"> swatch
170
171
  | 'rating' // 5-star rating control
@@ -260,6 +261,13 @@ export type ColumnDef<TFeatures extends TableFeatures, TData extends RowData> =
260
261
  sparkline?: SparklineConfig
261
262
  /** Initial column width in pixels. Falls back to the grid's `columnWidth` prop. */
262
263
  width?: number
264
+ /**
265
+ * Initial visibility. Set `false` to start the column hidden while still
266
+ * listing it in the Choose Columns UI for the user to re-enable. Applied
267
+ * once at mount; after that `api.setColumnVisible` / user toggles win.
268
+ * On a group column, `false` hides the whole group's leaf columns.
269
+ */
270
+ visible?: boolean
263
271
  /**
264
272
  * Horizontal alignment for header and body cells. When omitted, the
265
273
  * default is inferred from `editorType`:
package/src/css.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ // Ambient declaration so TypeScript accepts side-effect CSS imports
2
+ // (e.g. `import "./SvGrid.css"`). The bundler resolves the actual asset.
3
+ declare module "*.css";