@svgrid/grid 1.1.0 → 1.1.1

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 (117) hide show
  1. package/dist/GridMenus.svelte +205 -127
  2. package/dist/SvGrid.controller.svelte.d.ts +44 -1
  3. package/dist/SvGrid.controller.svelte.js +223 -38
  4. package/dist/SvGrid.css +2012 -1709
  5. package/dist/SvGrid.helpers.test.d.ts +1 -0
  6. package/dist/SvGrid.helpers.test.js +298 -0
  7. package/dist/SvGrid.svelte +2346 -2043
  8. package/dist/SvGrid.types.d.ts +91 -4
  9. package/dist/aligned-grids.d.ts +6 -0
  10. package/dist/aligned-grids.js +84 -0
  11. package/dist/aligned-grids.test.d.ts +1 -0
  12. package/dist/aligned-grids.test.js +75 -0
  13. package/dist/build-api.coverage.test.d.ts +20 -0
  14. package/dist/build-api.coverage.test.js +505 -0
  15. package/dist/build-api.js +59 -29
  16. package/dist/cell-render.test.d.ts +1 -0
  17. package/dist/cell-render.test.js +338 -0
  18. package/dist/chart-export.test.d.ts +1 -0
  19. package/dist/chart-export.test.js +302 -0
  20. package/dist/chart.coverage.test.d.ts +1 -0
  21. package/dist/chart.coverage.test.js +748 -0
  22. package/dist/clipboard.js +88 -24
  23. package/dist/clipboard.test.d.ts +1 -0
  24. package/dist/clipboard.test.js +700 -0
  25. package/dist/collaboration.coverage.test.d.ts +1 -0
  26. package/dist/collaboration.coverage.test.js +200 -0
  27. package/dist/column-groups.d.ts +19 -0
  28. package/dist/column-groups.js +62 -0
  29. package/dist/column-groups.test.d.ts +1 -0
  30. package/dist/column-groups.test.js +56 -0
  31. package/dist/column-types.d.ts +10 -0
  32. package/dist/column-types.js +63 -0
  33. package/dist/column-types.test.d.ts +1 -0
  34. package/dist/column-types.test.js +62 -0
  35. package/dist/columns.test.d.ts +1 -0
  36. package/dist/columns.test.js +625 -0
  37. package/dist/core.d.ts +85 -0
  38. package/dist/editing.d.ts +7 -0
  39. package/dist/editing.js +191 -5
  40. package/dist/editing.test.d.ts +1 -0
  41. package/dist/editing.test.js +732 -0
  42. package/dist/editors/cell-editors.coverage.test.d.ts +1 -0
  43. package/dist/editors/cell-editors.coverage.test.js +139 -0
  44. package/dist/facet-buckets.test.d.ts +1 -0
  45. package/dist/facet-buckets.test.js +296 -0
  46. package/dist/filter-operators.test.d.ts +1 -0
  47. package/dist/filter-operators.test.js +135 -0
  48. package/dist/hyperformula-adapter.test.d.ts +1 -0
  49. package/dist/hyperformula-adapter.test.js +205 -0
  50. package/dist/index.d.ts +5 -2
  51. package/dist/index.js +4 -1
  52. package/dist/keyboard-handlers.coverage.test.d.ts +1 -0
  53. package/dist/keyboard-handlers.coverage.test.js +495 -0
  54. package/dist/keyboard-handlers.js +7 -2
  55. package/dist/menus.js +1 -0
  56. package/dist/menus.test.d.ts +1 -0
  57. package/dist/menus.test.js +560 -0
  58. package/dist/named-views.coverage.test.d.ts +1 -0
  59. package/dist/named-views.coverage.test.js +180 -0
  60. package/dist/row-drag.d.ts +49 -0
  61. package/dist/row-drag.js +221 -0
  62. package/dist/row-drag.test.d.ts +1 -0
  63. package/dist/row-drag.test.js +142 -0
  64. package/dist/row-resize.test.d.ts +1 -0
  65. package/dist/row-resize.test.js +329 -0
  66. package/dist/scroll-sync.js +3 -0
  67. package/dist/scroll-sync.test.d.ts +1 -0
  68. package/dist/scroll-sync.test.js +290 -0
  69. package/dist/selection.d.ts +7 -1
  70. package/dist/selection.js +76 -36
  71. package/dist/selection.multi-range.test.d.ts +1 -0
  72. package/dist/selection.multi-range.test.js +55 -0
  73. package/dist/selection.test.d.ts +1 -0
  74. package/dist/selection.test.js +647 -0
  75. package/dist/server-data-source.coverage.test.d.ts +1 -0
  76. package/dist/server-data-source.coverage.test.js +154 -0
  77. package/dist/spreadsheet.d.ts +30 -0
  78. package/dist/spreadsheet.js +48 -0
  79. package/dist/spreadsheet.test.d.ts +1 -0
  80. package/dist/spreadsheet.test.js +446 -0
  81. package/dist/sv-grid-scrollbar.js +13 -1
  82. package/dist/svgrid-wrapper.types.d.ts +19 -0
  83. package/dist/svgrid.behavior.test.js +20 -0
  84. package/dist/svgrid.interaction.test.js +31 -0
  85. package/dist/svgrid.new-features.wrapper.test.js +34 -2
  86. package/dist/test-setup.js +9 -3
  87. package/dist/virtualization/scroll-scaling.d.ts +17 -0
  88. package/dist/virtualization/scroll-scaling.js +35 -0
  89. package/dist/virtualization/scroll-scaling.test.js +42 -1
  90. package/package.json +2 -1
  91. package/src/GridMenus.svelte +205 -127
  92. package/src/SvGrid.controller.svelte.ts +2352 -2195
  93. package/src/SvGrid.css +2012 -1747
  94. package/src/SvGrid.svelte +2346 -2047
  95. package/src/SvGrid.types.ts +537 -456
  96. package/src/aligned-grids.test.ts +80 -0
  97. package/src/aligned-grids.ts +87 -0
  98. package/src/build-api.ts +683 -663
  99. package/src/clipboard.test.ts +49 -0
  100. package/src/clipboard.ts +51 -23
  101. package/src/column-groups.test.ts +59 -0
  102. package/src/column-groups.ts +80 -0
  103. package/src/column-types.test.ts +68 -0
  104. package/src/column-types.ts +82 -0
  105. package/src/core.ts +78 -0
  106. package/src/editing.ts +669 -513
  107. package/src/index.ts +12 -0
  108. package/src/menus.ts +1 -0
  109. package/src/row-drag.test.ts +168 -0
  110. package/src/row-drag.ts +255 -0
  111. package/src/scroll-sync.ts +2 -0
  112. package/src/selection.multi-range.test.ts +61 -0
  113. package/src/selection.ts +71 -37
  114. package/src/spreadsheet.test.ts +489 -445
  115. package/src/spreadsheet.ts +304 -246
  116. package/src/svgrid-wrapper.types.ts +19 -0
  117. package/src/svgrid.new-features.wrapper.test.ts +2 -2
package/dist/clipboard.js CHANGED
@@ -5,7 +5,7 @@ import { parseEditorValue, } from "./index";
5
5
  import "./sv-grid-scrollbar";
6
6
  import { buildFillPattern } from "./fill-patterns";
7
7
  import { getCellKey, } from "./SvGrid.helpers";
8
- import { getColumnBaseValue, isGroupRow, } from "./cell-values";
8
+ import { getColumnBaseValue, isGroupRow, toolPanelHeaderLabel, } from "./cell-values";
9
9
  export function createClipboard(ctx) {
10
10
  /** Read the raw underlying value for the cell at (rowIndex, columnId)
11
11
  * for pattern extraction. */
@@ -244,35 +244,99 @@ export function createClipboard(ctx) {
244
244
  };
245
245
  ctx.grid.store.setState((prev) => ({ ...prev }));
246
246
  }
247
+ /**
248
+ * Write text to the OS clipboard, with a legacy fallback for insecure
249
+ * contexts. The async Clipboard API requires a secure context (HTTPS or
250
+ * localhost); on plain HTTP - e.g. a grid served by XAMPP/Apache over a LAN
251
+ * host - `navigator.clipboard` is undefined and copy/cut would silently do
252
+ * nothing. There we fall back to a temporary <textarea> + execCommand('copy'),
253
+ * which still works in an insecure context. This MUST be called synchronously
254
+ * from the user gesture (the keydown handler) so execCommand is allowed.
255
+ */
256
+ function writeClipboardText(text) {
257
+ if (navigator.clipboard?.writeText) {
258
+ void navigator.clipboard.writeText(text).catch(() => legacyCopyText(text));
259
+ return;
260
+ }
261
+ legacyCopyText(text);
262
+ }
263
+ function legacyCopyText(text) {
264
+ if (typeof document === "undefined")
265
+ return false;
266
+ const active = document.activeElement;
267
+ const ta = document.createElement("textarea");
268
+ ta.value = text;
269
+ ta.setAttribute("readonly", "");
270
+ // Offscreen but still selectable; opacity/0-size can suppress selection.
271
+ ta.style.cssText =
272
+ "position:fixed;top:0;left:-9999px;width:1px;height:1px;padding:0;border:0;";
273
+ document.body.appendChild(ta);
274
+ let ok = false;
275
+ try {
276
+ ta.select();
277
+ ta.setSelectionRange(0, text.length);
278
+ ok = document.execCommand("copy");
279
+ }
280
+ catch {
281
+ ok = false;
282
+ }
283
+ document.body.removeChild(ta);
284
+ // Restore focus to the grid root so keyboard nav keeps working afterward.
285
+ (active ?? ctx.gridRootEl)?.focus?.({
286
+ preventScroll: true,
287
+ });
288
+ return ok;
289
+ }
247
290
  function copySelectionToClipboard() {
248
- const anchor = ctx.selectionRange.anchor;
249
- const focus = ctx.selectionRange.focus;
250
- if (!anchor || !focus)
291
+ // Copy every selected rectangle. Each range becomes a TSV block; multiple
292
+ // ranges are stacked and separated by a blank line (Sheets-style).
293
+ const rects = ctx.getSelectionRects();
294
+ if (!rects.length)
251
295
  return;
252
- const minRow = Math.min(anchor.rowIndex, focus.rowIndex);
253
- const maxRow = Math.max(anchor.rowIndex, focus.rowIndex);
254
- const minCol = Math.min(anchor.colIndex, focus.colIndex);
255
- const maxCol = Math.max(anchor.colIndex, focus.colIndex);
256
- const lines = [];
257
- for (let r = minRow; r <= maxRow; r += 1) {
258
- const row = ctx.allRows[r];
259
- if (!row || isGroupRow(row))
260
- continue;
261
- const cells = [];
262
- for (let c = minCol; c <= maxCol; c += 1) {
263
- const column = ctx.allColumns[c];
264
- if (!column) {
265
- cells.push("");
296
+ // Optional: prepend a header row (Excel "copy with headers") and/or run
297
+ // each value through a consumer hook before it hits the clipboard.
298
+ const withHeaders = ctx.props.copyHeadersToClipboard === true;
299
+ const processCell = ctx.props.processCellForClipboard;
300
+ const blocks = [];
301
+ for (const rect of rects) {
302
+ const lines = [];
303
+ if (withHeaders) {
304
+ const header = [];
305
+ for (let c = rect.minCol; c <= rect.maxCol; c += 1) {
306
+ const column = ctx.allColumns[c];
307
+ header.push(column ? toolPanelHeaderLabel(column) : "");
308
+ }
309
+ lines.push(header.join("\t"));
310
+ }
311
+ for (let r = rect.minRow; r <= rect.maxRow; r += 1) {
312
+ const row = ctx.allRows[r];
313
+ if (!row || isGroupRow(row))
266
314
  continue;
315
+ const cells = [];
316
+ for (let c = rect.minCol; c <= rect.maxCol; c += 1) {
317
+ const column = ctx.allColumns[c];
318
+ if (!column) {
319
+ cells.push("");
320
+ continue;
321
+ }
322
+ const base = getColumnBaseValue(row, column);
323
+ let value = ctx.getCellDisplayValue(row.id, column.id, base);
324
+ if (processCell) {
325
+ value = processCell({
326
+ value,
327
+ column,
328
+ row: row.original,
329
+ rowIndex: r,
330
+ columnId: column.id,
331
+ });
332
+ }
333
+ cells.push(String(value ?? ""));
267
334
  }
268
- const base = getColumnBaseValue(row, column);
269
- const display = ctx.getCellDisplayValue(row.id, column.id, base);
270
- cells.push(String(display ?? ""));
335
+ lines.push(cells.join("\t"));
271
336
  }
272
- lines.push(cells.join("\t"));
337
+ blocks.push(lines.join("\n"));
273
338
  }
274
- const text = lines.join("\n");
275
- void navigator.clipboard?.writeText(text).catch(() => { });
339
+ writeClipboardText(blocks.join("\n\n"));
276
340
  }
277
341
  /**
278
342
  * Clear every editable cell in the current selection range. Used by
@@ -0,0 +1 @@
1
+ export {};