@svgrid/grid 2.2.32 → 2.2.34

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 (91) hide show
  1. package/dist/DockNodeView.svelte +1 -1
  2. package/dist/GridFooter.svelte +46 -47
  3. package/dist/GridMenus.svelte +0 -77
  4. package/dist/SvDateRangeInput.svelte +1 -1
  5. package/dist/SvGrid.css +10 -0
  6. package/dist/SvGrid.svelte +2 -25
  7. package/dist/SvGridChart.svelte +2 -10
  8. package/dist/SvGridSelect.svelte +0 -2
  9. package/dist/SvKbd.svelte +1 -1
  10. package/dist/SvList.svelte +1 -1
  11. package/dist/SvMenubar.svelte +1 -1
  12. package/dist/SvMultiSelect.svelte +0 -1
  13. package/dist/SvOtpInput.svelte +1 -1
  14. package/dist/SvRichText.svelte +4 -0
  15. package/dist/SvTour.svelte +4 -0
  16. package/dist/SvTreeSelect.svelte +0 -2
  17. package/dist/cdn/{GridMenus-Cyk3qpJ7.js → GridMenus-T-bZNprc.js} +153 -152
  18. package/dist/cdn/{GridMenus-C6ixSGWW.js → GridMenus-oQYElQll.js} +5 -7
  19. package/dist/cdn/{SvDateTimePicker-ClqtVIj3.js → SvDateTimePicker-CHnUkWcH.js} +163 -163
  20. package/dist/cdn/{SvDateTimePicker-CdqaP61H.js → SvDateTimePicker-CRQH_U7E.js} +570 -553
  21. package/dist/cdn/{SvGridChart-BhnFdLd0.js → SvGridChart-BEJmNNx9.js} +1 -1
  22. package/dist/cdn/{SvGridChart-BcLCYvw9.js → SvGridChart-BwVos976.js} +27 -20
  23. package/dist/cdn/{SvGridChartPanel-Cmx9DHAS.js → SvGridChartPanel-BOknOkrP.js} +2 -2
  24. package/dist/cdn/{SvGridChartPanel-DvjwxLvK.js → SvGridChartPanel-D2PjII4O.js} +22 -14
  25. package/dist/cdn/{SvGridChartView-PwqI4s02.js → SvGridChartView-00LPUHL1.js} +3 -3
  26. package/dist/cdn/{SvGridChartView-B40DTJSX.js → SvGridChartView-BhUEJ5ki.js} +2 -2
  27. package/dist/cdn/{SvGridDropdown-Dh-2ej8j.js → SvGridDropdown-D13MtJ2j.js} +5 -4
  28. package/dist/cdn/{chart-T1usDN0o.js → chart-i4XcXyHJ.js} +12 -10
  29. package/dist/cdn/disclose-version-Dr7rEVv-.js +2866 -0
  30. package/dist/cdn/{export-format-JT5pWVT8.js → export-format-Cv1Dll6k.js} +66 -245
  31. package/dist/cdn/{src-BgHjWF0Q.js → src-72QTH8lh.js} +9006 -8811
  32. package/dist/cdn/{src-CgD-wiuS.js → src-Cm7C_WOZ.js} +9206 -8927
  33. package/dist/cdn/svgrid.js +9 -9
  34. package/dist/cdn/svgrid.svelte-external.js +8 -8
  35. package/dist/chart.d.ts +2 -0
  36. package/dist/chart.js +1 -4
  37. package/dist/columns.js +9 -2
  38. package/dist/createMenu.svelte.js +0 -1
  39. package/dist/createPopoverSelect.svelte.d.ts +2 -2
  40. package/dist/editing.js +1 -1
  41. package/dist/export-format.js +3 -0
  42. package/dist/selection.js +0 -1
  43. package/package.json +3 -2
  44. package/src/DockNodeView.svelte +1 -1
  45. package/src/GridFooter.svelte +46 -47
  46. package/src/GridMenus.svelte +0 -77
  47. package/src/SvCalendar.test.ts +1 -1
  48. package/src/SvDateRangeInput.svelte +1 -1
  49. package/src/SvGrid.controller.svelte.ts +0 -5
  50. package/src/SvGrid.css +10 -0
  51. package/src/SvGrid.svelte +2 -25
  52. package/src/SvGrid.types.ts +0 -1
  53. package/src/SvGridChart.svelte +2 -10
  54. package/src/SvGridSelect.svelte +0 -2
  55. package/src/SvKbd.svelte +1 -1
  56. package/src/SvList.svelte +1 -1
  57. package/src/SvMenubar.svelte +1 -1
  58. package/src/SvMultiSelect.svelte +0 -1
  59. package/src/SvOtpInput.svelte +1 -1
  60. package/src/SvRichText.svelte +4 -0
  61. package/src/SvTour.svelte +4 -0
  62. package/src/SvTreeSelect.svelte +0 -2
  63. package/src/ai.test.ts +1 -1
  64. package/src/build-api.ts +0 -105
  65. package/src/cell-formatting.test.ts +1 -1
  66. package/src/cell-render.ts +0 -94
  67. package/src/chart.ts +1 -2
  68. package/src/clipboard.ts +0 -102
  69. package/src/columns.ts +7 -117
  70. package/src/createMenu.svelte.ts +0 -1
  71. package/src/editing.ts +2 -105
  72. package/src/editor-registry.grid.test.ts +0 -2
  73. package/src/export-format.ts +3 -0
  74. package/src/features.ts +0 -90
  75. package/src/keyboard-handlers.coverage.test.ts +1 -1
  76. package/src/keyboard-handlers.ts +0 -120
  77. package/src/menus.test.ts +0 -1
  78. package/src/menus.ts +0 -112
  79. package/src/new-features.test.ts +3 -1
  80. package/src/row-drag.test.ts +1 -1
  81. package/src/row-resize.test.ts +1 -2
  82. package/src/scroll-sync.test.ts +4 -7
  83. package/src/scroll-sync.ts +0 -122
  84. package/src/selection.ts +0 -109
  85. package/src/server-group-model.test.ts +2 -2
  86. package/src/summaries.ts +0 -112
  87. package/src/svgrid.behavior.test.ts +0 -1
  88. package/src/svgrid.column-reorder.test.ts +0 -8
  89. package/src/svgrid.footer-pagesize.svelte.test.ts +86 -0
  90. package/src/tree-row-model.test.ts +0 -1
  91. package/dist/cdn/disclose-version-DoD9AFD_.js +0 -2958
@@ -42,7 +42,7 @@
42
42
 
43
43
  const onMove = (ev: PointerEvent) => {
44
44
  const delta = ((vertical ? ev.clientY : ev.clientX) - startPos) / total
45
- let fa = Math.min(Math.max(startSizes[a]! + delta, minA), pairTotal - minB)
45
+ const fa = Math.min(Math.max(startSizes[a]! + delta, minA), pairTotal - minB)
46
46
  const next = startSizes.slice()
47
47
  next[a] = fa
48
48
  next[b] = pairTotal - fa
@@ -1,50 +1,12 @@
1
1
  <script lang="ts" generics="TFeatures extends TableFeatures = TableFeatures, TData extends RowData = RowData">
2
2
  import {
3
- getGridCellA11yProps,
4
- getGridCellDomId,
5
- getGridHeaderA11yProps,
6
- getGridRootA11yProps,
7
- getGridRowA11yProps,
8
- type EditorContext,
9
- type CellEditorOption,
10
- type Column,
11
- type Row,
12
3
  type RowData,
13
4
  type TableFeatures,
14
5
  } from "./index";
15
6
  import "./sv-grid-scrollbar";
16
- import type { Snippet } from "svelte";
17
7
  import {
18
- RenderSnippetConfig,
19
- RenderComponentConfig,
20
- } from "./render-component";
21
- import {
22
- buildSparkline,
23
- toSparklineValues,
24
- } from "./sparkline";
25
- import SvGridDropdown from "./SvGridDropdown.svelte";
26
- import type {
27
- Props,
28
- SelectionPoint,
29
- SelectionRange,
30
- CellEditState,
31
- FilterOperator,
32
- FilterOption,
33
- MenuPosition,
34
- } from "./SvGrid.types";
35
- import {
36
- cfTextStyle,
37
8
  fmtStat,
38
- getEditableInputValue,
39
- getEditorInputType,
40
- toValueArray,
41
- getOptionLabel,
42
- getOptionColor,
43
- colorfulChipStyle,
44
- getEditorClass,
45
9
  } from "./SvGrid.helpers";
46
- import {
47
- } from "./SvGrid.controller.svelte";
48
10
  import type { SvGridController } from "./SvGrid.controller.svelte";
49
11
 
50
12
  let {
@@ -65,12 +27,29 @@
65
27
  pageSizeOptions?: number[];
66
28
  } = $props();
67
29
 
30
+ // SvGridDropdown is ~22 KB and exists here only to pick one of four numbers.
31
+ // Importing it statically also dragged it into the base bundle and silently
32
+ // defeated the lazy `import()` in SvGrid.svelte, which loads the same
33
+ // component as a cell editor. So the closed trigger below is plain markup
34
+ // reusing the dropdown's own classes (identical appearance), and the real
35
+ // component is fetched on first open. Keep this lazy: a static import here
36
+ // re-breaks the cell-editor split too, not just the footer.
37
+ let PageSizeDropdown = $state<typeof import("./SvGridDropdown.svelte").default | null>(null);
38
+ let loadingPageSize = $state(false);
39
+
40
+ async function openPageSize() {
41
+ if (PageSizeDropdown || loadingPageSize) return;
42
+ loadingPageSize = true;
43
+ try {
44
+ PageSizeDropdown = (await import("./SvGridDropdown.svelte")).default;
45
+ } finally {
46
+ loadingPageSize = false;
47
+ }
48
+ }
49
+
68
50
  // View facade: re-bind the controller's reactive members so the markup
69
51
  // (moved verbatim from SvGrid.svelte) stays identical.
70
52
  const paginationEnabled = $derived(ctrl.paginationEnabled);
71
- const grid = $derived(ctrl.grid);
72
- const paginationState = $derived(ctrl.paginationState);
73
- const allRowsBeforePagination = $derived(ctrl.allRowsBeforePagination);
74
53
  const statusBarEnabled = $derived(ctrl.statusBarEnabled);
75
54
  const statusBarAggregates = $derived(ctrl.statusBarAggregates);
76
55
  const statusBarStats = $derived(ctrl.statusBarStats);
@@ -128,12 +107,32 @@
128
107
  <div class="sv-grid-pagination-pagesize">
129
108
  <span>{messages.pageSize}</span>
130
109
  <div class="sv-grid-pagination-pagesize-dd">
131
- <SvGridDropdown
132
- options={sizes.map((n) => ({ value: n, label: String(n) }))}
133
- value={pageSize}
134
- autoOpen={false}
135
- onChange={(v) => setPageSize(Number(v))}
136
- />
110
+ {#if PageSizeDropdown}
111
+ <!-- autoOpen so the click that triggered the load also opens the
112
+ panel, rather than making the user click a second time. -->
113
+ <PageSizeDropdown
114
+ options={sizes.map((n) => ({ value: n, label: String(n) }))}
115
+ value={pageSize}
116
+ autoOpen={true}
117
+ onChange={(v) => setPageSize(Number(v))}
118
+ />
119
+ {:else}
120
+ <!-- Mirrors SvGridDropdown's closed trigger exactly (same classes,
121
+ same ARIA) so there is no visual change and no layout shift
122
+ when the real component swaps in. -->
123
+ <div class="sv-grid-dropdown">
124
+ <button
125
+ type="button"
126
+ class="sv-grid-dropdown-trigger"
127
+ aria-haspopup="listbox"
128
+ aria-expanded="false"
129
+ onclick={openPageSize}
130
+ >
131
+ <span class="sv-grid-dropdown-label">{pageSize}</span>
132
+ <span class="sv-grid-dropdown-caret" aria-hidden="true">▾</span>
133
+ </button>
134
+ </div>
135
+ {/if}
137
136
  </div>
138
137
  </div>
139
138
  <span class="sv-grid-pagination-range">
@@ -1,97 +1,21 @@
1
1
  <script lang="ts" generics="TFeatures extends TableFeatures = TableFeatures, TData extends RowData = RowData">
2
2
  import {
3
- applyExcelFilter,
4
- normalizeForFilter,
5
3
  splitInTokens,
6
4
  trailingInToken,
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
5
  type CellEditorType,
33
- type CellFormatter,
34
- type CellFormatConfig,
35
6
  type Column,
36
- type ColumnDef,
37
- type Row,
38
7
  type RowData,
39
- type SvGridApi,
40
8
  type TableFeatures,
41
9
  } from "./index";
42
10
  import "./sv-grid-scrollbar";
43
11
  import { onScrollOutside } from "./a11y/dismissable";
44
12
  import type { Snippet } from "svelte";
45
- import { getKeyboardIntent, getNextActiveCell } from "./keyboard";
46
- import {
47
- formatNumericWithConfig,
48
- getDateFormatter,
49
- resolveDatePattern,
50
- } from "./cell-formatting";
51
- import {
52
- RenderSnippetConfig,
53
- RenderComponentConfig,
54
- } from "./render-component";
55
- import { buildFillPattern } from "./fill-patterns";
56
- import { buildSparkline, toSparklineValues } from "./sparkline";
57
- import {
58
- resolveCellFormat,
59
- computeColumnStat,
60
- formatsNeedingStats,
61
- type ColumnStat,
62
- type ResolvedCellFormat,
63
- } from "./conditional-formatting";
64
- import SvGridDropdown from "./SvGridDropdown.svelte";
65
13
  import SvListBox from "./SvListBox.svelte";
66
14
  import type {
67
- Props,
68
- SelectionPoint,
69
- SelectionRange,
70
- CellEditState,
71
15
  FilterOperator,
72
- FilterOption,
73
- MenuPosition,
74
16
  } from "./SvGrid.types";
75
17
  import {
76
- cfTextStyle,
77
- fmtStat,
78
- getCellKey,
79
- resolveClassList,
80
- toDateInputValue,
81
- toDateTimeLocalInputValue,
82
- getEditableInputValue,
83
18
  getEditorInputType,
84
- toValueArray,
85
- getOptionLabel,
86
- getOptionColor,
87
- colorfulChipStyle,
88
- getEditorClass,
89
- asDate,
90
- clampMenuX,
91
- cssEscape,
92
- rawToNumber,
93
- formatFacetNumber,
94
- formatFacetDate,
95
19
  } from "./SvGrid.helpers";
96
20
 
97
21
  import type { SvGridController } from "./SvGrid.controller.svelte";
@@ -103,7 +27,6 @@
103
27
  const groupingControlsEnabled = $derived(ctrl.groupingControlsEnabled);
104
28
  const filterMenuValues = $derived(ctrl.filterMenuValues);
105
29
  const tooltip = $derived(ctrl.tooltip);
106
- const showTooltipFor = $derived(ctrl.showTooltipFor);
107
30
  const columnMenuFor = $derived(ctrl.columnMenuFor);
108
31
  const columnMenuPos = $derived(ctrl.columnMenuPos);
109
32
  const filterMenuFor = $derived(ctrl.filterMenuFor);
@@ -20,7 +20,7 @@
20
20
  import { anchoredRect, portalToBody, popIn, type AnchoredRect } from './popover'
21
21
  import { editorAria, nextEditorId, resolveMessages, type SvEditorProps } from './editor-contract'
22
22
  import { formatDate } from './datetime/date-format'
23
- import { toDate, startOfDay, type DateLike } from './datetime/date-core'
23
+ import { startOfDay, type DateLike } from './datetime/date-core'
24
24
  import { rangeDays } from './datetime/date-selection'
25
25
  import type { CalendarPreset } from './createCalendar.svelte'
26
26
 
package/dist/SvGrid.css CHANGED
@@ -1012,6 +1012,11 @@
1012
1012
  width: 16px;
1013
1013
  height: 16px;
1014
1014
  margin: 0 auto;
1015
+ /* The UA stylesheet gives <button> "padding: 1px 6px" on top of
1016
+ "box-sizing: border-box", which leaves 2px of content width inside the
1017
+ 16px box. The glyphs below then shrink to a sliver, and the tick renders
1018
+ as a bare slanted line. Guarded by tests/e2e/selection-checkbox.spec.ts. */
1019
+ padding: 0;
1015
1020
  border: 1px solid var(--sg-input-border, #8794a8);
1016
1021
  border-radius: 4px;
1017
1022
  background: var(--sg-input-bg, #fff);
@@ -1089,6 +1094,7 @@ select.sv-grid-fr-editor {
1089
1094
 
1090
1095
  .sv-grid-checkbox[aria-checked="true"]::after {
1091
1096
  content: "";
1097
+ flex: none;
1092
1098
  width: 5px;
1093
1099
  height: 9px;
1094
1100
  border-right: 2px solid currentColor;
@@ -1098,6 +1104,7 @@ select.sv-grid-fr-editor {
1098
1104
 
1099
1105
  .sv-grid-checkbox[aria-checked="mixed"]::after {
1100
1106
  content: "";
1107
+ flex: none;
1101
1108
  width: 8px;
1102
1109
  height: 2px;
1103
1110
  border-radius: 1px;
@@ -2391,6 +2398,9 @@ select.sv-grid-fr-editor {
2391
2398
  .sv-grid-find-step, .sv-grid-find-close {
2392
2399
  display: inline-flex; align-items: center; justify-content: center;
2393
2400
  width: 22px; height: 22px;
2401
+ /* Same fixed-box + UA <button> padding trap as .sv-grid-checkbox: without
2402
+ this reset the 6px side padding squeezes the icon inside the 22px box. */
2403
+ padding: 0;
2394
2404
  background: transparent;
2395
2405
  border: 0;
2396
2406
  color: var(--sg-muted, #64748b);
@@ -17,7 +17,6 @@
17
17
  } from "./index";
18
18
  import "./sv-grid-scrollbar";
19
19
  import "./SvGrid.css";
20
- import type { Snippet } from "svelte";
21
20
  import {
22
21
  RenderSnippetConfig,
23
22
  RenderComponentConfig,
@@ -36,16 +35,10 @@
36
35
  import { timeStringToDate, dateToTimeString } from "./SvGrid.helpers";
37
36
  import type {
38
37
  Props,
39
- SelectionPoint,
40
- SelectionRange,
41
- CellEditState,
42
38
  FilterOperator,
43
- FilterOption,
44
- MenuPosition,
45
39
  } from "./SvGrid.types";
46
40
  import {
47
41
  cfTextStyle,
48
- fmtStat,
49
42
  getEditableInputValue,
50
43
  getEditorInputType,
51
44
  toValueArray,
@@ -57,7 +50,6 @@
57
50
  import {
58
51
  splitInTokens,
59
52
  trailingInToken,
60
- joinInTokens,
61
53
  } from "./filtering/excel-filters";
62
54
  import { createSvGridController } from "./SvGrid.controller.svelte";
63
55
  // GridMenus hosts tooltips + all column/filter/context menu overlays - none of
@@ -180,10 +172,8 @@
180
172
 
181
173
  // ---- View facade: re-bind the controller's reactive members as locals so the
182
174
  // markup stays identical. Assignable state + bindings + DOM refs use c.* directly.
183
- const paginationEnabled = $derived(ctrl.paginationEnabled);
184
175
  const filterRowValues = $derived(ctrl.filterRowValues);
185
176
  const filterMenuValues = $derived(ctrl.filterMenuValues);
186
- const tooltip = $derived(ctrl.tooltip);
187
177
  const showTooltipFor = $derived(ctrl.showTooltipFor);
188
178
  const hideTooltip = $derived(ctrl.hideTooltip);
189
179
  const findHits = $derived(ctrl.findHits);
@@ -284,19 +274,13 @@
284
274
  id === "__autoGroup" || id.startsWith("__group_");
285
275
  const sortDirectionByColumn = $derived(ctrl.sortDirectionByColumn);
286
276
  const groupingColumns = $derived(ctrl.groupingColumns);
287
- const paginationState = $derived(ctrl.paginationState);
288
- const allRowsBeforePagination = $derived(ctrl.allRowsBeforePagination);
289
277
  const allRows = $derived(ctrl.allRows);
290
- const statusBarEnabled = $derived(ctrl.statusBarEnabled);
291
- const statusBarAggregates = $derived(ctrl.statusBarAggregates);
292
- const statusBarStats = $derived(ctrl.statusBarStats);
293
278
  const toolPanelEnabled = $derived(ctrl.toolPanelEnabled);
294
279
  const toolPanelColumns = $derived(ctrl.toolPanelColumns);
295
280
  const toolPanelHeaderLabel = $derived(ctrl.toolPanelHeaderLabel);
296
281
  const toggleColumnVisibleInPanel = $derived(ctrl.toggleColumnVisibleInPanel);
297
282
  const moveColumnInPanel = $derived(ctrl.moveColumnInPanel);
298
283
  const toggleGroupInPanel = $derived(ctrl.toggleGroupInPanel);
299
- const virtualizer = $derived(ctrl.virtualizer);
300
284
  const rowVirtualizationEnabled = $derived(ctrl.rowVirtualizationEnabled);
301
285
  // The fixed row height, matching what the virtualized path takes from the virtualizer.
302
286
  // The non-virtualized (`virtualization={false}`) body must apply this too, else its rows
@@ -525,9 +509,6 @@
525
509
  const onHeaderSortClick = $derived(ctrl.onHeaderSortClick);
526
510
  const onGridKeyDown = $derived(ctrl.onGridKeyDown);
527
511
  const onGridPaste = $derived(ctrl.onGridPaste);
528
- const changePage = $derived(ctrl.changePage);
529
- const goToPage = $derived(ctrl.goToPage);
530
- const setPageSize = $derived(ctrl.setPageSize);
531
512
  const updateFilterRow = $derived(ctrl.updateFilterRow);
532
513
  const updateFilterMenuValue = $derived(ctrl.updateFilterMenuValue);
533
514
  const updateFilterMenuValueTo = $derived(ctrl.updateFilterMenuValueTo);
@@ -1291,7 +1272,7 @@
1291
1272
  aria-label="Edit checkbox value"
1292
1273
  onclick={(event) => {
1293
1274
  event.stopPropagation();
1294
- const nextValue = !Boolean(ctrl.editingCell?.value);
1275
+ const nextValue = !ctrl.editingCell?.value;
1295
1276
  ctrl.editingCell = ctrl.editingCell
1296
1277
  ? { ...ctrl.editingCell, value: nextValue }
1297
1278
  : ctrl.editingCell;
@@ -1300,7 +1281,7 @@
1300
1281
  onkeydown={(event) =>
1301
1282
  toggleCheckboxWithKeyboard(event, () => {
1302
1283
  event.stopPropagation();
1303
- const nextValue = !Boolean(ctrl.editingCell?.value);
1284
+ const nextValue = !ctrl.editingCell?.value;
1304
1285
  ctrl.editingCell = ctrl.editingCell
1305
1286
  ? { ...ctrl.editingCell, value: nextValue }
1306
1287
  : ctrl.editingCell;
@@ -2690,10 +2671,6 @@
2690
2671
  row,
2691
2672
  rendered.column,
2692
2673
  )}
2693
- {@const cellTooltip = computeCellTooltip(
2694
- row,
2695
- rendered.column,
2696
- )}
2697
2674
  {@const cellValidity = computeCellValidity(
2698
2675
  row,
2699
2676
  rendered.column,
@@ -213,15 +213,7 @@
213
213
  return { t0: zoom.i0 / n, t1: (zoom.i1 + 1) / n }
214
214
  })
215
215
 
216
- /** Map a brush-svg-local x to a category index in the FULL data range. */
217
- function brushXToIndex(localX: number): number {
218
- if (!brushGeo) return 0
219
- const w = brushGeo.plot.w
220
- const x = Math.max(0, Math.min(w, localX - brushGeo.plot.x))
221
- const n = spec.categories.length
222
- return Math.max(0, Math.min(n - 1, Math.floor((x / w) * n)))
223
- }
224
- type BrushDrag = { mode: 'move' | 'left' | 'right'; startX: number; startT0: number; startT1: number }
216
+ type BrushDrag ={ mode: 'move' | 'left' | 'right'; startX: number; startT0: number; startT1: number }
225
217
  let brushDrag = $state<BrushDrag | null>(null)
226
218
  function brushSvgX(e: PointerEvent, svg: SVGSVGElement): number {
227
219
  const r = svg.getBoundingClientRect()
@@ -919,7 +911,7 @@
919
911
  {#if isRadar && geo.radarCenter}
920
912
  {@const c = geo.radarCenter}
921
913
  <!-- Concentric grid rings -->
922
- {#each geo.radarRings as v, ri (ri)}
914
+ {#each geo.radarRings as _v, ri (ri)}
923
915
  {@const ringR = c.r * ((ri + 1) / geo.radarRings.length)}
924
916
  <circle class="sv-grid-chart-radar-ring" cx={c.cx} cy={c.cy} r={ringR} />
925
917
  {/each}
@@ -53,8 +53,6 @@
53
53
  labelField,
54
54
  value = $bindable<string | number | null>(null),
55
55
  onChange,
56
- onCommit,
57
- onCancel,
58
56
  placeholder = 'Select…',
59
57
  searchable = true,
60
58
  loadOptions,
package/dist/SvKbd.svelte CHANGED
@@ -21,7 +21,7 @@
21
21
 
22
22
  {#if keys}
23
23
  <span class="sv-kbd-group sv-kbd--{size}">
24
- {#each keys as k, i}
24
+ {#each keys as k, i (i)}
25
25
  {#if i > 0}<span class="sv-kbd__sep" aria-hidden="true">{separator}</span>{/if}
26
26
  <kbd class="sv-kbd">{k}</kbd>
27
27
  {/each}
@@ -37,7 +37,7 @@
37
37
  {#if children}
38
38
  {@render children()}
39
39
  {:else if items}
40
- {#each items as item}<li>{item}</li>{/each}
40
+ {#each items as item, i (i)}<li>{item}</li>{/each}
41
41
  {/if}
42
42
  </svelte:element>
43
43
 
@@ -41,7 +41,7 @@
41
41
  const resolvedDir = $derived(dir === 'ltr' || dir === 'rtl' ? dir : undefined)
42
42
  const rtl = $derived(resolvedDir === 'rtl')
43
43
 
44
- let triggerEls = $state<(HTMLButtonElement | null)[]>([])
44
+ const triggerEls = $state<(HTMLButtonElement | null)[]>([])
45
45
  let panelEl = $state<HTMLDivElement | null>(null)
46
46
  let openIndex = $state(-1)
47
47
  let activeIndex = $state(0)
@@ -50,7 +50,6 @@
50
50
  value = $bindable<ReadonlyArray<string | number>>([]),
51
51
  onChange,
52
52
  onCommit,
53
- onCancel,
54
53
  placeholder = 'Select…',
55
54
  searchable = true,
56
55
  maxTagCount = 3,
@@ -52,7 +52,7 @@
52
52
  const autoId = nextEditorId('sv-otp')
53
53
  const uid = $derived(id ?? autoId)
54
54
  const cells = $derived(otpCells(sanitizeOtp(value, length, numeric), length))
55
- let inputs = $state<HTMLInputElement[]>([])
55
+ const inputs = $state<HTMLInputElement[]>([])
56
56
 
57
57
  function commit(next: string) {
58
58
  const clean = sanitizeOtp(next, length, numeric)
@@ -90,6 +90,10 @@
90
90
  // (writing innerHTML while focused would collapse the caret).
91
91
  $effect(() => {
92
92
  const v = value ?? ''
93
+ // A contenteditable owns its own DOM: letting Svelte re-render the body
94
+ // would wipe the caret mid-typing, so the value is pushed in by hand and
95
+ // only while the editor is unfocused.
96
+ // eslint-disable-next-line svelte/no-dom-manipulating
93
97
  if (editorEl && !focused && editorEl.innerHTML !== v) editorEl.innerHTML = v
94
98
  if (editorEl) empty = editorEl.textContent!.trim().length === 0
95
99
  })
@@ -156,6 +156,10 @@
156
156
  >
157
157
  {#if step.image}
158
158
  <div class="sv-tour__media">
159
+ <!-- A step's `image` is either a URL (rendered as an img above) or
160
+ inline SVG markup the app author wrote for its own tour - never
161
+ user input, so rendering it as markup is the intent. -->
162
+ <!-- eslint-disable-next-line svelte/no-at-html-tags -->
159
163
  {#if /^(https?:|data:|\/)/.test(step.image)}<img class="sv-tour__img" src={step.image} alt="" />{:else}{@html step.image}{/if}
160
164
  </div>
161
165
  {/if}
@@ -36,8 +36,6 @@
36
36
  nodes,
37
37
  value = $bindable<string | number | null>(null),
38
38
  onChange,
39
- onCommit,
40
- onCancel,
41
39
  placeholder = 'Select…',
42
40
  showPath = false,
43
41
  expandedIds = [],