@pixerate/editor-svelte 0.22.0 → 0.24.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 (163) hide show
  1. package/README.md +6 -2
  2. package/dist/MergePreview.svelte +201 -0
  3. package/dist/MergePreview.svelte.d.ts +25 -0
  4. package/dist/MergePreview.svelte.d.ts.map +1 -0
  5. package/dist/StylesGallery.svelte +169 -0
  6. package/dist/StylesGallery.svelte.d.ts +27 -0
  7. package/dist/StylesGallery.svelte.d.ts.map +1 -0
  8. package/dist/TemplateRenderer.svelte +4 -10
  9. package/dist/TemplateRenderer.svelte.d.ts.map +1 -1
  10. package/dist/canvas/TokenBindingPicker.svelte +93 -0
  11. package/dist/canvas/TokenBindingPicker.svelte.d.ts +20 -0
  12. package/dist/canvas/TokenBindingPicker.svelte.d.ts.map +1 -0
  13. package/dist/canvas/TokenModeSwitcher.svelte +55 -0
  14. package/dist/canvas/TokenModeSwitcher.svelte.d.ts +18 -0
  15. package/dist/canvas/TokenModeSwitcher.svelte.d.ts.map +1 -0
  16. package/dist/canvas/createCanvasArrange.svelte.d.ts +4 -0
  17. package/dist/canvas/createCanvasArrange.svelte.d.ts.map +1 -1
  18. package/dist/canvas/createCanvasAutoLayout.svelte.d.ts +68 -0
  19. package/dist/canvas/createCanvasAutoLayout.svelte.d.ts.map +1 -0
  20. package/dist/canvas/createCanvasAutoLayout.svelte.js +78 -0
  21. package/dist/canvas/createCanvasTokens.svelte.d.ts +31 -0
  22. package/dist/canvas/createCanvasTokens.svelte.d.ts.map +1 -0
  23. package/dist/canvas/createCanvasTokens.svelte.js +50 -0
  24. package/dist/canvas/index.d.ts +7 -0
  25. package/dist/canvas/index.d.ts.map +1 -1
  26. package/dist/canvas/index.js +10 -0
  27. package/dist/fileImport.svelte.d.ts +8 -1
  28. package/dist/fileImport.svelte.d.ts.map +1 -1
  29. package/dist/fileImport.svelte.js +11 -1
  30. package/dist/find-replace/FindReplaceBar.svelte +203 -0
  31. package/dist/find-replace/FindReplaceBar.svelte.d.ts +15 -0
  32. package/dist/find-replace/FindReplaceBar.svelte.d.ts.map +1 -0
  33. package/dist/find-replace/findReplace.svelte.d.ts +27 -0
  34. package/dist/find-replace/findReplace.svelte.d.ts.map +1 -0
  35. package/dist/find-replace/findReplace.svelte.js +79 -0
  36. package/dist/find-replace/index.d.ts +6 -0
  37. package/dist/find-replace/index.d.ts.map +1 -0
  38. package/dist/find-replace/index.js +2 -0
  39. package/dist/generation/AssetMentionChips.svelte +130 -0
  40. package/dist/generation/AssetMentionChips.svelte.d.ts +21 -0
  41. package/dist/generation/AssetMentionChips.svelte.d.ts.map +1 -0
  42. package/dist/generation/GenerationHistory.svelte +161 -0
  43. package/dist/generation/GenerationHistory.svelte.d.ts +28 -0
  44. package/dist/generation/GenerationHistory.svelte.d.ts.map +1 -0
  45. package/dist/generation/GenerationSettings.svelte +174 -0
  46. package/dist/generation/GenerationSettings.svelte.d.ts +23 -0
  47. package/dist/generation/GenerationSettings.svelte.d.ts.map +1 -0
  48. package/dist/generation/JobProgress.svelte +53 -0
  49. package/dist/generation/JobProgress.svelte.d.ts +17 -0
  50. package/dist/generation/JobProgress.svelte.d.ts.map +1 -0
  51. package/dist/generation/index.d.ts +17 -0
  52. package/dist/generation/index.d.ts.map +1 -0
  53. package/dist/generation/index.js +7 -0
  54. package/dist/generation/plan.svelte.d.ts +16 -0
  55. package/dist/generation/plan.svelte.d.ts.map +1 -0
  56. package/dist/generation/plan.svelte.js +26 -0
  57. package/dist/generation/progress.svelte.d.ts +25 -0
  58. package/dist/generation/progress.svelte.d.ts.map +1 -0
  59. package/dist/generation/progress.svelte.js +36 -0
  60. package/dist/generation/records.svelte.d.ts +18 -0
  61. package/dist/generation/records.svelte.d.ts.map +1 -0
  62. package/dist/generation/records.svelte.js +66 -0
  63. package/dist/image-editor/AdjustmentLayersPanel.svelte +309 -0
  64. package/dist/image-editor/AdjustmentLayersPanel.svelte.d.ts +11 -0
  65. package/dist/image-editor/AdjustmentLayersPanel.svelte.d.ts.map +1 -0
  66. package/dist/image-editor/ControlSlider.svelte +39 -0
  67. package/dist/image-editor/ControlSlider.svelte.d.ts +13 -0
  68. package/dist/image-editor/ControlSlider.svelte.d.ts.map +1 -0
  69. package/dist/image-editor/CurvesEditor.svelte +105 -0
  70. package/dist/image-editor/CurvesEditor.svelte.d.ts +13 -0
  71. package/dist/image-editor/CurvesEditor.svelte.d.ts.map +1 -0
  72. package/dist/image-editor/Histogram.svelte +49 -0
  73. package/dist/image-editor/Histogram.svelte.d.ts +12 -0
  74. package/dist/image-editor/Histogram.svelte.d.ts.map +1 -0
  75. package/dist/image-editor/ImageEditor.svelte +104 -141
  76. package/dist/image-editor/ImageEditor.svelte.d.ts.map +1 -1
  77. package/dist/image-editor/RefineEdgePanel.svelte +180 -0
  78. package/dist/image-editor/RefineEdgePanel.svelte.d.ts +13 -0
  79. package/dist/image-editor/RefineEdgePanel.svelte.d.ts.map +1 -0
  80. package/dist/image-editor/SelectionOptionsBar.svelte +135 -0
  81. package/dist/image-editor/SelectionOptionsBar.svelte.d.ts +15 -0
  82. package/dist/image-editor/SelectionOptionsBar.svelte.d.ts.map +1 -0
  83. package/dist/image-editor/imageEditorState.svelte.d.ts +14 -1
  84. package/dist/image-editor/imageEditorState.svelte.d.ts.map +1 -1
  85. package/dist/image-editor/imageEditorState.svelte.js +40 -0
  86. package/dist/image-editor/index.d.ts +18 -0
  87. package/dist/image-editor/index.d.ts.map +1 -1
  88. package/dist/image-editor/index.js +6 -0
  89. package/dist/index.d.ts +12 -1
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +7 -0
  92. package/dist/merge.svelte.d.ts +51 -0
  93. package/dist/merge.svelte.d.ts.map +1 -0
  94. package/dist/merge.svelte.js +117 -0
  95. package/dist/paragraphStyles.svelte.d.ts +30 -0
  96. package/dist/paragraphStyles.svelte.d.ts.map +1 -0
  97. package/dist/paragraphStyles.svelte.js +44 -0
  98. package/dist/persistence/RecoveryPrompt.svelte +57 -0
  99. package/dist/persistence/RecoveryPrompt.svelte.d.ts +18 -0
  100. package/dist/persistence/RecoveryPrompt.svelte.d.ts.map +1 -0
  101. package/dist/persistence/autosave.svelte.d.ts +63 -0
  102. package/dist/persistence/autosave.svelte.d.ts.map +1 -0
  103. package/dist/persistence/autosave.svelte.js +110 -0
  104. package/dist/persistence/index.d.ts +6 -0
  105. package/dist/persistence/index.d.ts.map +1 -0
  106. package/dist/persistence/index.js +2 -0
  107. package/dist/review/TrackedChangesList.svelte +67 -0
  108. package/dist/review/TrackedChangesList.svelte.d.ts +13 -0
  109. package/dist/review/TrackedChangesList.svelte.d.ts.map +1 -0
  110. package/dist/review/documentCompare.svelte.d.ts +21 -0
  111. package/dist/review/documentCompare.svelte.d.ts.map +1 -0
  112. package/dist/review/documentCompare.svelte.js +23 -0
  113. package/dist/review/index.d.ts +4 -0
  114. package/dist/review/index.d.ts.map +1 -1
  115. package/dist/review/index.js +2 -0
  116. package/dist/review/review.svelte.d.ts +6 -0
  117. package/dist/review/review.svelte.d.ts.map +1 -1
  118. package/dist/review/review.svelte.js +3 -0
  119. package/dist/spreadsheet/FormulaBar.svelte +13 -4
  120. package/dist/spreadsheet/FormulaBar.svelte.d.ts.map +1 -1
  121. package/dist/spreadsheet/FormulaHints.svelte +7 -5
  122. package/dist/spreadsheet/FormulaHints.svelte.d.ts +3 -0
  123. package/dist/spreadsheet/FormulaHints.svelte.d.ts.map +1 -1
  124. package/dist/spreadsheet/NameManager.svelte +165 -0
  125. package/dist/spreadsheet/NameManager.svelte.d.ts +11 -0
  126. package/dist/spreadsheet/NameManager.svelte.d.ts.map +1 -0
  127. package/dist/spreadsheet/SheetTabs.svelte +161 -0
  128. package/dist/spreadsheet/SheetTabs.svelte.d.ts +10 -0
  129. package/dist/spreadsheet/SheetTabs.svelte.d.ts.map +1 -0
  130. package/dist/spreadsheet/SpreadsheetConditionalFormatPanel.svelte +184 -0
  131. package/dist/spreadsheet/SpreadsheetConditionalFormatPanel.svelte.d.ts +9 -0
  132. package/dist/spreadsheet/SpreadsheetConditionalFormatPanel.svelte.d.ts.map +1 -0
  133. package/dist/spreadsheet/SpreadsheetContextMenu.svelte +13 -5
  134. package/dist/spreadsheet/SpreadsheetContextMenu.svelte.d.ts +5 -1
  135. package/dist/spreadsheet/SpreadsheetContextMenu.svelte.d.ts.map +1 -1
  136. package/dist/spreadsheet/SpreadsheetDataValidationPanel.svelte +141 -0
  137. package/dist/spreadsheet/SpreadsheetDataValidationPanel.svelte.d.ts +9 -0
  138. package/dist/spreadsheet/SpreadsheetDataValidationPanel.svelte.d.ts.map +1 -0
  139. package/dist/spreadsheet/SpreadsheetEditor.svelte +199 -11
  140. package/dist/spreadsheet/SpreadsheetEditor.svelte.d.ts +2 -0
  141. package/dist/spreadsheet/SpreadsheetEditor.svelte.d.ts.map +1 -1
  142. package/dist/spreadsheet/SpreadsheetValidationDialog.svelte +92 -0
  143. package/dist/spreadsheet/SpreadsheetValidationDialog.svelte.d.ts +9 -0
  144. package/dist/spreadsheet/SpreadsheetValidationDialog.svelte.d.ts.map +1 -0
  145. package/dist/spreadsheet/index.d.ts +9 -0
  146. package/dist/spreadsheet/index.d.ts.map +1 -1
  147. package/dist/spreadsheet/index.js +5 -0
  148. package/dist/spreadsheet/spreadsheet.svelte.d.ts +57 -2
  149. package/dist/spreadsheet/spreadsheet.svelte.d.ts.map +1 -1
  150. package/dist/spreadsheet/spreadsheet.svelte.js +105 -6
  151. package/dist/tokens/TokenSwatch.svelte +14 -0
  152. package/dist/tokens/TokenSwatch.svelte.d.ts +8 -0
  153. package/dist/tokens/TokenSwatch.svelte.d.ts.map +1 -0
  154. package/dist/tokens/TokensPanel.svelte +323 -0
  155. package/dist/tokens/TokensPanel.svelte.d.ts +14 -0
  156. package/dist/tokens/TokensPanel.svelte.d.ts.map +1 -0
  157. package/dist/tokens/createTokens.svelte.d.ts +31 -0
  158. package/dist/tokens/createTokens.svelte.d.ts.map +1 -0
  159. package/dist/tokens/createTokens.svelte.js +43 -0
  160. package/dist/tokens/index.d.ts +7 -0
  161. package/dist/tokens/index.d.ts.map +1 -0
  162. package/dist/tokens/index.js +3 -0
  163. package/package.json +26 -2
@@ -13,12 +13,23 @@
13
13
  type SpreadsheetMenuItem,
14
14
  type SpreadsheetViewColumn,
15
15
  type SpreadsheetViewRow,
16
- formatCellDisplay
16
+ formatCellForDisplay,
17
+ numberFormatColorToCss,
18
+ getConditionalFormatCss,
19
+ getConditionalFormatIcon,
20
+ getDataBarCss,
21
+ conditionalFormatStyleString,
22
+ type SpreadsheetPanelId,
23
+ type SpreadsheetValidationAction
17
24
  } from '@pixerate/editor/spreadsheet';
18
25
  import FormulaBar from './FormulaBar.svelte';
26
+ import SpreadsheetValidationDialog from './SpreadsheetValidationDialog.svelte';
27
+ import SpreadsheetConditionalFormatPanel from './SpreadsheetConditionalFormatPanel.svelte';
28
+ import SpreadsheetDataValidationPanel from './SpreadsheetDataValidationPanel.svelte';
19
29
  import SpreadsheetContextMenu from './SpreadsheetContextMenu.svelte';
20
30
  import SpreadsheetGroupRow from './SpreadsheetGroupRow.svelte';
21
31
  import FormulaHints from './FormulaHints.svelte';
32
+ import SheetTabs from './SheetTabs.svelte';
22
33
  import { createReactiveSpreadsheet } from './spreadsheet.svelte.js';
23
34
  import { attachSpreadsheetClipboard } from './tableInteractions.js';
24
35
 
@@ -34,6 +45,8 @@
34
45
  onAddColumnClick?: () => void;
35
46
  onColumnHeaderClick?: (col: SpreadsheetColumn) => void;
36
47
  onColumnResize?: (colId: string, width: number) => void;
48
+ /** Show the sheet tabs bar under the grid (add, switch, rename, reorder, delete sheets). */
49
+ showSheetTabs?: boolean;
37
50
  }
38
51
 
39
52
  let {
@@ -45,9 +58,16 @@
45
58
  customCellRenderer,
46
59
  onAddColumnClick,
47
60
  onColumnHeaderClick,
48
- onColumnResize
61
+ onColumnResize,
62
+ showSheetTabs = false
49
63
  }: Props = $props();
50
64
 
65
+ // Defined names for formula autocomplete in the cell editor.
66
+ let nameSuggestions = $derived.by(() => {
67
+ void sheetState.document;
68
+ return sheetState.controller.getNameSuggestions();
69
+ });
70
+
51
71
  let isReadOnly = $derived(readOnly || readonly);
52
72
 
53
73
  let gridContainer = $state<HTMLDivElement | null>(null);
@@ -84,6 +104,73 @@
84
104
 
85
105
  let fillDrag = $state.raw<{ source: CellRange; target: CellRange | null } | null>(null);
86
106
  let menu = $state.raw<{ x: number; y: number; items: SpreadsheetMenuItem[] } | null>(null);
107
+ // Conditional formatting / data validation manager, opened from the context menu.
108
+ let panel = $state<SpreadsheetPanelId | null>(null);
109
+ // List dropdown of a list-validated cell.
110
+ let listMenu = $state.raw<{ x: number; y: number; row: number; col: number; values: string[] } | null>(null);
111
+
112
+ // --- Data validation: list dropdown, input message, alerts ---
113
+ let activeListValues = $derived.by(() => {
114
+ void sheetState.document;
115
+ const cell = sheetState.activeCell;
116
+ return cell && !isReadOnly ? sheetState.controller.getValidationListValues(cell.row, cell.col) : null;
117
+ });
118
+ let inputMessage = $derived.by(() => {
119
+ void sheetState.document;
120
+ const cell = sheetState.activeCell;
121
+ const rule = cell ? sheetState.controller.getDataValidationAt(cell.row, cell.col) : undefined;
122
+ return rule && rule.showInputMessage !== false && (rule.inputTitle || rule.inputMessage) ? rule : null;
123
+ });
124
+
125
+ // "Circle invalid data": recomputed when the document (or the toggle) changes.
126
+ let invalidCircles = $derived.by(() => {
127
+ void sheetState.document;
128
+ if (!sheetState.controller.getInvalidDataCircles()) return null;
129
+ return new Set(sheetState.controller.findInvalidCells().map((c) => `${c.row}:${c.col}`));
130
+ });
131
+
132
+ function openListMenu(row: number, col: number, anchor?: HTMLElement | null) {
133
+ if (isReadOnly || sheetState.document.columns[col]?.readOnly) return;
134
+ const values = sheetState.controller.getValidationListValues(row, col);
135
+ if (!values) return;
136
+ const td = anchor ?? gridContainer?.querySelector<HTMLElement>(`td[data-row="${row}"][data-col="${col}"]`);
137
+ const rect = td?.getBoundingClientRect();
138
+ listMenu = { x: rect ? rect.left : 0, y: rect ? rect.bottom : 0, row, col, values };
139
+ }
140
+
141
+ // Close the list on a press outside it (or on its arrow, which toggles it).
142
+ $effect(() => {
143
+ if (!listMenu) return;
144
+ const close = (e: MouseEvent) => {
145
+ if (!(e.target as Element | null)?.closest?.('[aria-label="Allowed values"], .spreadsheet-list-arrow')) listMenu = null;
146
+ };
147
+ window.addEventListener('mousedown', close);
148
+ return () => window.removeEventListener('mousedown', close);
149
+ });
150
+
151
+ function chooseListValue(value: string) {
152
+ if (!listMenu) return;
153
+ const row = sheetState.document.rows[listMenu.row];
154
+ const col = sheetState.document.columns[listMenu.col];
155
+ listMenu = null;
156
+ if (row && col) sheetState.commitCellInput(row.id, col.id, value);
157
+ gridContainer?.focus();
158
+ }
159
+
160
+ function resolveValidation(action: SpreadsheetValidationAction) {
161
+ sheetState.resolveValidationPrompt(action);
162
+ // Back to the cell editor when it is still open (retry), else the grid.
163
+ requestAnimationFrame(() => {
164
+ if (cellInput) cellInput.focus();
165
+ else gridContainer?.focus();
166
+ });
167
+ }
168
+
169
+ /** Inline style of a cell's conditional look (fill, font), keeping the selection tint visible. */
170
+ function conditionalStyle(fill: string | undefined, css: string, selected: boolean): string {
171
+ if (!css) return '';
172
+ return ` ${css}${fill && selected ? ' box-shadow: inset 0 0 0 9999px color-mix(in srgb, var(--primary, #6366f1) 12%, transparent);' : ''}`;
173
+ }
87
174
  let filteredColIds = $derived.by(() => {
88
175
  const filter = sheetState.document.table?.filter;
89
176
  return new Set(filter?.enabled ? filter.rules.map((r) => r.colId) : []);
@@ -173,11 +260,12 @@
173
260
  sheetState.cancelEditing();
174
261
  } else if (e.key === 'Enter') {
175
262
  e.preventDefault();
176
- sheetState.commitEditing();
263
+ // Invalid input keeps the editor open behind the validation alert.
264
+ if (sheetState.commitEditing().status !== 'committed') return;
177
265
  sheetState.moveCursor('down');
178
266
  } else if (e.key === 'Tab') {
179
267
  e.preventDefault();
180
- sheetState.commitEditing();
268
+ if (sheetState.commitEditing().status !== 'committed') return;
181
269
  sheetState.moveCursor(e.shiftKey ? 'left' : 'right');
182
270
  } else {
183
271
  return;
@@ -189,7 +277,11 @@
189
277
 
190
278
  if (!sheetState.activeCell) return;
191
279
 
192
- if (e.key === 'ArrowUp') {
280
+ if (e.altKey && e.key === 'ArrowDown') {
281
+ // Alt+Down opens the list of a list-validated cell.
282
+ e.preventDefault();
283
+ openListMenu(sheetState.activeCell.row, sheetState.activeCell.col);
284
+ } else if (e.key === 'ArrowUp') {
193
285
  e.preventDefault();
194
286
  sheetState.moveCursor('up', e.shiftKey);
195
287
  } else if (e.key === 'ArrowDown') {
@@ -442,6 +534,7 @@
442
534
  }
443
535
  </script>
444
536
 
537
+ {#snippet grid()}
445
538
  <div
446
539
  bind:this={gridContainer}
447
540
  class="flex flex-col h-full w-full overflow-hidden border border-border bg-background select-none outline-none text-foreground font-sans text-xs {className}"
@@ -454,6 +547,11 @@
454
547
  {#if showFormulaBar}
455
548
  <FormulaBar {sheetState} />
456
549
  {/if}
550
+ {#if inputMessage}
551
+ <div role="note" data-validation-input-message="" class="border-b border-border bg-muted/30 px-3 py-1 text-[11px] text-muted-foreground">
552
+ {#if inputMessage.inputTitle}<span class="mr-1 font-semibold text-foreground">{inputMessage.inputTitle}</span>{/if}{inputMessage.inputMessage ?? ''}
553
+ </div>
554
+ {/if}
457
555
 
458
556
  <!-- Main Scrollable Grid -->
459
557
  <div class="relative flex-1 overflow-auto">
@@ -551,6 +649,10 @@
551
649
  {@const active = isActiveCell(rIdx, cIdx)}
552
650
  {@const isEditing = sheetState.editingCell?.row === rIdx && sheetState.editingCell?.col === cIdx}
553
651
 
652
+ {@const conditional = sheetState.conditionalFormatOverlay.get(rIdx, cIdx)}
653
+ {@const conditionalCss = conditionalFormatStyleString(getConditionalFormatCss(conditional))}
654
+ {@const circled = !!invalidCircles?.has(`${rIdx}:${cIdx}`)}
655
+ {@const showListArrow = active && !isEditing && !!activeListValues}
554
656
  {@const inFillPreview = !!fillDrag?.target && !selected && rangeContains(fillDrag.target, displayRowIndex, viewCol.index)}
555
657
  {@const showFillHandle =
556
658
  !isReadOnly &&
@@ -567,7 +669,8 @@
567
669
  rowspan={span.rowSpan}
568
670
  colspan={span.colSpan}
569
671
  class="relative border-r border-border px-2 py-1 truncate max-w-0 text-foreground transition-colors {selected ? 'bg-primary/10' : ''} {active ? 'ring-2 ring-primary ring-inset z-10' : ''} {viewCol.header ? 'font-semibold' : ''}"
570
- style="max-width: 0; overflow: hidden; {frozenCellStyle(viewRow, viewCol)}{inFillPreview ? ' outline: 1px dashed var(--primary, #6366f1); outline-offset: -1px;' : ''}"
672
+ style="max-width: 0; overflow: hidden; {frozenCellStyle(viewRow, viewCol)}{conditionalStyle(conditional?.fill, conditionalCss, selected)}{inFillPreview ? ' outline: 1px dashed var(--primary, #6366f1); outline-offset: -1px;' : ''}"
673
+ data-cf-fill={conditional?.fill}
571
674
  onclick={(e) => handleCellClick(rIdx, cIdx, e)}
572
675
  ondblclick={() => handleCellDblClick(rIdx, cIdx)}
573
676
  oncontextmenu={(e) => handleCellContextMenu(rIdx, cIdx, e)}
@@ -581,17 +684,58 @@
581
684
  bind:value={sheetState.draftValue}
582
685
  onblur={() => sheetState.commitEditing()}
583
686
  />
584
- <FormulaHints input={cellInput} value={sheetState.draftValue} onAccept={(next) => (sheetState.draftValue = next)} />
687
+ <FormulaHints input={cellInput} value={sheetState.draftValue} onAccept={(next) => (sheetState.draftValue = next)} names={nameSuggestions} />
585
688
  {:else if customCellRenderer}
586
689
  {@const cellArg = Object.assign({ row, col, cell }, cell)}
587
690
  {@render (customCellRenderer as any)(cellArg, col, row)}
588
691
  {:else}
692
+ {@const shown = formatCellForDisplay(cell)}
693
+ {@const textColor = conditional?.color ?? (shown.color ? numberFormatColorToCss(shown.color) : undefined)}
694
+ {@const icon = conditional?.icon ? getConditionalFormatIcon(conditional.icon.set, conditional.icon.index) : null}
695
+ {#if conditional?.dataBar}
696
+ <span aria-hidden="true" class="spreadsheet-data-bar" style={conditionalFormatStyleString(getDataBarCss(conditional.dataBar))}></span>
697
+ {/if}
698
+ {#snippet cellText()}
699
+ <span
700
+ class="truncate block max-w-full {cell.error ? 'text-destructive font-semibold' : ''}"
701
+ title={cell.error ? (cell.errorMessage ?? cell.error) : undefined}
702
+ data-numeric={shown.numeric ? '' : undefined}
703
+ style="{conditional?.dataBar || icon ? 'position: relative;' : ''}{icon ? ' flex: 1; min-width: 0;' : ''}{shown.numeric ? ' text-align: right;' : ''}{textColor ? ` color: ${textColor};` : ''}"
704
+ >
705
+ {conditional?.hideValue ? '' : shown.text}
706
+ </span>
707
+ {/snippet}
708
+ {#if icon && conditional?.icon}
709
+ <span class="flex items-center gap-1 min-w-0" style="position: relative;">
710
+ <span class="spreadsheet-cf-icon shrink-0" role="img" aria-label={icon.label} data-icon={conditional.icon.id} style="color: {icon.color};">{icon.glyph}</span>
711
+ {@render cellText()}
712
+ </span>
713
+ {:else}
714
+ {@render cellText()}
715
+ {/if}
716
+ {/if}
717
+ {#if circled}
589
718
  <span
590
- class="truncate block max-w-full {cell.error ? 'text-destructive font-semibold' : ''}"
591
- title={cell.error ? (cell.errorMessage ?? cell.error) : undefined}
719
+ class="spreadsheet-invalid-circle"
720
+ aria-label="Invalid value"
721
+ style="position: absolute; inset: 1px 2px; border: 2px solid #e11d48; border-radius: 50%; pointer-events: none; z-index: 6;"
722
+ ></span>
723
+ {/if}
724
+ {#if showListArrow}
725
+ <button
726
+ type="button"
727
+ class="spreadsheet-list-arrow"
728
+ aria-label="Show allowed values"
729
+ aria-haspopup="listbox"
730
+ tabindex="-1"
731
+ style="position: absolute; right: 1px; top: 1px; bottom: 1px; width: 16px; z-index: 24; font-size: 10px; line-height: 1; background: var(--muted, #f4f4f5); border: 1px solid var(--border, #e4e4e7); border-radius: 2px; cursor: pointer; padding: 0;"
732
+ onmousedown={(e) => e.stopPropagation()}
733
+ onclick={(e) => {
734
+ e.stopPropagation();
735
+ if (listMenu) listMenu = null;
736
+ else openListMenu(rIdx, cIdx, (e.currentTarget as HTMLElement).parentElement);
737
+ }}>▾</button
592
738
  >
593
- {formatCellDisplay(cell)}
594
- </span>
595
739
  {/if}
596
740
  {#if activeSpill && rangeContains(activeSpill.range, rIdx, cIdx)}
597
741
  <span aria-hidden="true" class="spreadsheet-spill-border" style={spillBorderStyle(activeSpill.range, rIdx, cIdx)}></span>
@@ -629,9 +773,53 @@
629
773
  menu = null;
630
774
  gridContainer?.focus();
631
775
  }}
776
+ onOpenPanel={(next) => (panel = next)}
632
777
  />
633
778
  {/if}
779
+ {#if panel === 'conditionalFormatting'}
780
+ <SpreadsheetConditionalFormatPanel {sheetState} onClose={() => (panel = null)} />
781
+ {:else if panel === 'dataValidation'}
782
+ <SpreadsheetDataValidationPanel {sheetState} onClose={() => (panel = null)} />
783
+ {/if}
784
+ {#if listMenu}
785
+ <div
786
+ role="listbox"
787
+ aria-label="Allowed values"
788
+ tabindex="-1"
789
+ class="fixed z-50 max-h-60 min-w-[8rem] overflow-y-auto rounded-md border border-border bg-popover py-1 text-xs text-popover-foreground shadow-lg"
790
+ style="left: {listMenu.x}px; top: {listMenu.y}px; background: var(--popover, var(--background, #fff));"
791
+ onkeydown={(e) => {
792
+ e.stopPropagation();
793
+ if (e.key === 'Escape') {
794
+ listMenu = null;
795
+ gridContainer?.focus();
796
+ }
797
+ }}
798
+ >
799
+ {#if listMenu.values.length === 0}
800
+ <div class="px-3 py-1 text-muted-foreground">No values</div>
801
+ {/if}
802
+ {#each listMenu.values as value, i (`${i}:${value}`)}
803
+ <button type="button" role="option" aria-selected="false" class="block w-full px-3 py-1 text-left hover:bg-muted" onclick={() => chooseListValue(value)}
804
+ >{value}</button
805
+ >
806
+ {/each}
807
+ </div>
808
+ {/if}
809
+ {#if sheetState.validationPrompt}
810
+ <SpreadsheetValidationDialog prompt={sheetState.validationPrompt} onResolve={resolveValidation} />
811
+ {/if}
634
812
  </div>
813
+ {/snippet}
814
+
815
+ {#if showSheetTabs}
816
+ <div class="flex h-full w-full flex-col">
817
+ <div class="min-h-0 flex-1">{@render grid()}</div>
818
+ <SheetTabs {sheetState} readOnly={isReadOnly} />
819
+ </div>
820
+ {:else}
821
+ {@render grid()}
822
+ {/if}
635
823
 
636
824
  <style>
637
825
  .col-resize-handle {
@@ -15,6 +15,8 @@ interface Props {
15
15
  onAddColumnClick?: () => void;
16
16
  onColumnHeaderClick?: (col: SpreadsheetColumn) => void;
17
17
  onColumnResize?: (colId: string, width: number) => void;
18
+ /** Show the sheet tabs bar under the grid (add, switch, rename, reorder, delete sheets). */
19
+ showSheetTabs?: boolean;
18
20
  }
19
21
  declare const SpreadsheetEditor: import("svelte").Component<Props, {}, "">;
20
22
  type SpreadsheetEditor = ReturnType<typeof SpreadsheetEditor>;
@@ -1 +1 @@
1
- {"version":3,"file":"SpreadsheetEditor.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/SpreadsheetEditor.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAMH,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,QAAQ,EAMd,MAAM,8BAA8B,CAAC;AAKxC,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAIlE,UAAU,KAAK;IACb,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EACf,OAAO,CAAC,CAAC,QAAQ,EAAE,iBAAiB,EAAE,cAAc,CAAC,CAAC,GACtD,OAAO,CAAC,CAAC;QAAE,GAAG,EAAE,cAAc,CAAC;QAAC,GAAG,EAAE,iBAAiB,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC,CAAC;IAC/E,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACvD,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzD;AA+hBH,QAAA,MAAM,iBAAiB,2CAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"SpreadsheetEditor.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/SpreadsheetEditor.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAMH,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,QAAQ,EAad,MAAM,8BAA8B,CAAC;AASxC,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAIlE,UAAU,KAAK;IACb,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EACf,OAAO,CAAC,CAAC,QAAQ,EAAE,iBAAiB,EAAE,cAAc,CAAC,CAAC,GACtD,OAAO,CAAC,CAAC;QAAE,GAAG,EAAE,cAAc,CAAC;QAAC,GAAG,EAAE,iBAAiB,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC,CAAC;IAC/E,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACvD,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,4FAA4F;IAC5F,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAwrBH,QAAA,MAAM,iBAAiB,2CAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,92 @@
1
+ <script lang="ts">
2
+ import type { SpreadsheetValidationAction, SpreadsheetValidationPrompt } from '@pixerate/editor/spreadsheet';
3
+
4
+ interface Props {
5
+ prompt: SpreadsheetValidationPrompt;
6
+ onResolve: (action: SpreadsheetValidationAction) => void;
7
+ }
8
+
9
+ let { prompt, onResolve }: Props = $props();
10
+ let firstButton = $state<HTMLButtonElement | null>(null);
11
+
12
+ const style = $derived(prompt.result.errorStyle ?? 'stop');
13
+ // Stop: Retry / Cancel; Warning: "Continue?" Yes / No / Cancel; Information: OK / Cancel.
14
+ const buttons = $derived<Array<{ label: string; action: SpreadsheetValidationAction }>>(
15
+ style === 'stop'
16
+ ? [
17
+ { label: 'Retry', action: 'retry' },
18
+ { label: 'Cancel', action: 'cancel' }
19
+ ]
20
+ : style === 'warning'
21
+ ? [
22
+ { label: 'Yes', action: 'accept' },
23
+ { label: 'No', action: 'retry' },
24
+ { label: 'Cancel', action: 'cancel' }
25
+ ]
26
+ : [
27
+ { label: 'OK', action: 'accept' },
28
+ { label: 'Cancel', action: 'cancel' }
29
+ ]
30
+ );
31
+ const icon = $derived(style === 'stop' ? '⛔' : style === 'warning' ? '⚠' : 'ℹ');
32
+
33
+ $effect(() => {
34
+ void prompt;
35
+ firstButton?.focus();
36
+ });
37
+ </script>
38
+
39
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
40
+ <div
41
+ class="fixed inset-0 z-[60] flex items-center justify-center bg-black/30"
42
+ onmousedown={(e) => e.preventDefault()}
43
+ onkeydown={(e) => {
44
+ e.stopPropagation();
45
+ if (e.key === 'Escape') {
46
+ e.preventDefault();
47
+ onResolve('cancel');
48
+ }
49
+ }}
50
+ >
51
+ <div
52
+ role="alertdialog"
53
+ aria-modal="true"
54
+ aria-labelledby="spreadsheet-validation-title"
55
+ aria-describedby="spreadsheet-validation-message"
56
+ data-error-style={style}
57
+ tabindex="-1"
58
+ class="w-[22rem] max-w-[calc(100vw-2rem)] rounded-md border border-border bg-popover p-4 text-xs text-popover-foreground shadow-xl"
59
+ style="background: var(--popover, var(--background, #fff));"
60
+ >
61
+ <div class="flex items-start gap-3">
62
+ <span aria-hidden="true" class="text-lg leading-none">{icon}</span>
63
+ <div class="min-w-0 flex-1">
64
+ <h2 id="spreadsheet-validation-title" class="mb-1 text-sm font-semibold">{prompt.result.title}</h2>
65
+ <p id="spreadsheet-validation-message" class="whitespace-pre-wrap">{prompt.result.message}</p>
66
+ {#if style === 'warning'}
67
+ <p class="mt-2">Continue?</p>
68
+ {/if}
69
+ </div>
70
+ </div>
71
+ <div class="mt-4 flex justify-end gap-2">
72
+ {#each buttons as button, i (button.action)}
73
+ {#if i === 0}
74
+ <button
75
+ bind:this={firstButton}
76
+ type="button"
77
+ data-action={button.action}
78
+ class="rounded border border-border px-3 py-1 bg-primary text-primary-foreground"
79
+ onclick={() => onResolve(button.action)}>{button.label}</button
80
+ >
81
+ {:else}
82
+ <button
83
+ type="button"
84
+ data-action={button.action}
85
+ class="rounded border border-border px-3 py-1 hover:bg-muted"
86
+ onclick={() => onResolve(button.action)}>{button.label}</button
87
+ >
88
+ {/if}
89
+ {/each}
90
+ </div>
91
+ </div>
92
+ </div>
@@ -0,0 +1,9 @@
1
+ import type { SpreadsheetValidationAction, SpreadsheetValidationPrompt } from '@pixerate/editor/spreadsheet';
2
+ interface Props {
3
+ prompt: SpreadsheetValidationPrompt;
4
+ onResolve: (action: SpreadsheetValidationAction) => void;
5
+ }
6
+ declare const SpreadsheetValidationDialog: import("svelte").Component<Props, {}, "">;
7
+ type SpreadsheetValidationDialog = ReturnType<typeof SpreadsheetValidationDialog>;
8
+ export default SpreadsheetValidationDialog;
9
+ //# sourceMappingURL=SpreadsheetValidationDialog.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SpreadsheetValidationDialog.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/SpreadsheetValidationDialog.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,2BAA2B,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAG3G,UAAU,KAAK;IACb,MAAM,EAAE,2BAA2B,CAAC;IACpC,SAAS,EAAE,CAAC,MAAM,EAAE,2BAA2B,KAAK,IAAI,CAAC;CAC1D;AAoEH,QAAA,MAAM,2BAA2B,2CAAwC,CAAC;AAC1E,KAAK,2BAA2B,GAAG,UAAU,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAClF,eAAe,2BAA2B,CAAC"}
@@ -2,14 +2,23 @@ import type { ComponentProps } from "svelte";
2
2
  import type SpreadsheetEditorComponent from "./SpreadsheetEditor.svelte";
3
3
  import type FormulaBarComponent from "./FormulaBar.svelte";
4
4
  import type FormulaHintsComponent from "./FormulaHints.svelte";
5
+ import type SheetTabsComponent from "./SheetTabs.svelte";
6
+ import type NameManagerComponent from "./NameManager.svelte";
5
7
  export { default as SpreadsheetEditor } from './SpreadsheetEditor.svelte';
6
8
  export { default as FormulaBar } from './FormulaBar.svelte';
7
9
  export { default as FormulaHints } from './FormulaHints.svelte';
10
+ export { default as SheetTabs } from './SheetTabs.svelte';
11
+ export { default as NameManager } from './NameManager.svelte';
8
12
  export * from './spreadsheet.svelte.js';
9
13
  export { default as SpreadsheetContextMenu } from './SpreadsheetContextMenu.svelte';
10
14
  export { default as SpreadsheetGroupRow } from './SpreadsheetGroupRow.svelte';
11
15
  export * from './tableInteractions.js';
16
+ export { default as SpreadsheetValidationDialog } from './SpreadsheetValidationDialog.svelte';
17
+ export { default as SpreadsheetConditionalFormatPanel } from './SpreadsheetConditionalFormatPanel.svelte';
18
+ export { default as SpreadsheetDataValidationPanel } from './SpreadsheetDataValidationPanel.svelte';
12
19
  export type SpreadsheetEditorProps = ComponentProps<typeof SpreadsheetEditorComponent>;
13
20
  export type FormulaBarProps = ComponentProps<typeof FormulaBarComponent>;
14
21
  export type FormulaHintsProps = ComponentProps<typeof FormulaHintsComponent>;
22
+ export type SheetTabsProps = ComponentProps<typeof SheetTabsComponent>;
23
+ export type NameManagerProps = ComponentProps<typeof NameManagerComponent>;
15
24
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,KAAK,0BAA0B,MAAM,4BAA4B,CAAC;AACzE,OAAO,KAAK,mBAAmB,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,qBAAqB,MAAM,uBAAuB,CAAC;AAE/D,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChE,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAC9E,cAAc,wBAAwB,CAAC;AAEvC,MAAM,MAAM,sBAAsB,GAAG,cAAc,CAAC,OAAO,0BAA0B,CAAC,CAAC;AACvF,MAAM,MAAM,eAAe,GAAG,cAAc,CAAC,OAAO,mBAAmB,CAAC,CAAC;AACzE,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,KAAK,0BAA0B,MAAM,4BAA4B,CAAC;AACzE,OAAO,KAAK,mBAAmB,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,qBAAqB,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,kBAAkB,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,oBAAoB,MAAM,sBAAsB,CAAC;AAE7D,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAC9E,cAAc,wBAAwB,CAAC;AACvC,OAAO,EAAE,OAAO,IAAI,2BAA2B,EAAE,MAAM,sCAAsC,CAAC;AAC9F,OAAO,EAAE,OAAO,IAAI,iCAAiC,EAAE,MAAM,4CAA4C,CAAC;AAC1G,OAAO,EAAE,OAAO,IAAI,8BAA8B,EAAE,MAAM,yCAAyC,CAAC;AAEpG,MAAM,MAAM,sBAAsB,GAAG,cAAc,CAAC,OAAO,0BAA0B,CAAC,CAAC;AACvF,MAAM,MAAM,eAAe,GAAG,cAAc,CAAC,OAAO,mBAAmB,CAAC,CAAC;AACzE,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAC7E,MAAM,MAAM,cAAc,GAAG,cAAc,CAAC,OAAO,kBAAkB,CAAC,CAAC;AACvE,MAAM,MAAM,gBAAgB,GAAG,cAAc,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
@@ -1,7 +1,12 @@
1
1
  export { default as SpreadsheetEditor } from './SpreadsheetEditor.svelte';
2
2
  export { default as FormulaBar } from './FormulaBar.svelte';
3
3
  export { default as FormulaHints } from './FormulaHints.svelte';
4
+ export { default as SheetTabs } from './SheetTabs.svelte';
5
+ export { default as NameManager } from './NameManager.svelte';
4
6
  export * from './spreadsheet.svelte.js';
5
7
  export { default as SpreadsheetContextMenu } from './SpreadsheetContextMenu.svelte';
6
8
  export { default as SpreadsheetGroupRow } from './SpreadsheetGroupRow.svelte';
7
9
  export * from './tableInteractions.js';
10
+ export { default as SpreadsheetValidationDialog } from './SpreadsheetValidationDialog.svelte';
11
+ export { default as SpreadsheetConditionalFormatPanel } from './SpreadsheetConditionalFormatPanel.svelte';
12
+ export { default as SpreadsheetDataValidationPanel } from './SpreadsheetDataValidationPanel.svelte';
@@ -1,4 +1,4 @@
1
- import { SpreadsheetController, type SpreadsheetControllerOptions, type SpreadsheetDocument, type CellCoordinate, type CellRange, type CellData, type SpreadsheetColumn, type SpreadsheetRow, type SpreadsheetDataSource } from '@pixerate/editor/spreadsheet';
1
+ import { SpreadsheetController, type SpreadsheetControllerOptions, type SpreadsheetDocument, type CellCoordinate, type CellRange, type CellData, type SpreadsheetColumn, type SpreadsheetRow, type SpreadsheetDataSource, type SpreadsheetNameScope, type SpreadsheetCommitResult, type SpreadsheetValidationAction, type SpreadsheetValidationPrompt } from '@pixerate/editor/spreadsheet';
2
2
  export declare function createReactiveSpreadsheet(options?: SpreadsheetControllerOptions): {
3
3
  sortRows: (keys: import("@pixerate/editor").SortKey[], options?: {
4
4
  range?: CellRange | null;
@@ -33,23 +33,58 @@ export declare function createReactiveSpreadsheet(options?: SpreadsheetControlle
33
33
  toggleGroupCollapsed: (key: string) => void;
34
34
  getGroups: () => import("@pixerate/editor").SpreadsheetRowGroup[];
35
35
  transposeRange: (range?: CellRange | null) => boolean;
36
+ setCellNumberFormat: (range: CellRange | null, code: string | null) => boolean;
37
+ setColumnNumberFormat: (colId: string, code: string | null) => void;
36
38
  exportToCsv: (options?: import("@pixerate/editor").CsvExportOptions) => string;
37
39
  importFromCsv: (csv: string, options?: import("@pixerate/editor").CsvImportOptions) => void;
38
40
  copyToClipboardData: (range?: CellRange | null) => import("@pixerate/editor").SpreadsheetClipboardData;
39
41
  pasteClipboardData: (source: import("@pixerate/editor").SpreadsheetClipboardSource, target?: import("@pixerate/editor").CellPosition) => boolean;
42
+ getConditionalFormats: () => import("@pixerate/editor").ConditionalFormatRule[];
43
+ addConditionalFormat: (rule: import("@pixerate/editor").NewConditionalFormatRule, options?: {
44
+ priority?: "first" | "last";
45
+ }) => string;
46
+ updateConditionalFormat: (id: string, changes: Partial<import("@pixerate/editor").NewConditionalFormatRule>) => boolean;
47
+ deleteConditionalFormat: (id: string) => boolean;
48
+ moveConditionalFormat: (id: string, to: number | {
49
+ by: number;
50
+ }) => boolean;
51
+ clearConditionalFormats: (range?: CellRange | null) => void;
52
+ getConditionalFormatOverlay: () => import("@pixerate/editor").ConditionalFormatOverlay;
53
+ getConditionalFormat: (row: number, col: number) => import("@pixerate/editor").ConditionalCellFormat | undefined;
54
+ getDataValidations: () => import("@pixerate/editor").DataValidationRule[];
55
+ getDataValidationAt: (row: number, col: number) => import("@pixerate/editor").DataValidationRule | undefined;
56
+ addDataValidation: (rule: import("@pixerate/editor").NewDataValidationRule) => string;
57
+ updateDataValidation: (id: string, changes: Partial<import("@pixerate/editor").NewDataValidationRule>) => boolean;
58
+ deleteDataValidation: (id: string) => boolean;
59
+ clearDataValidation: (range?: CellRange | null) => void;
60
+ validateCellInput: (row: number, col: number, raw: string) => import("@pixerate/editor").DataValidationResult;
61
+ getValidationListValues: (row: number, col: number) => string[] | null;
62
+ findInvalidCells: () => import("@pixerate/editor").CellPosition[];
63
+ setInvalidDataCircles: (show: boolean) => void;
64
+ getInvalidDataCircles: () => boolean;
65
+ isInvalidDataCircled: (row: number, col: number) => boolean;
40
66
  document: SpreadsheetDocument;
41
67
  activeCell: CellCoordinate | null;
42
68
  selectedRange: CellRange | null;
43
69
  editingCell: CellCoordinate | null;
44
70
  viewModel: import("@pixerate/editor").SpreadsheetViewModel;
45
71
  draftValue: string;
72
+ sheets: import("@pixerate/editor").SpreadsheetSheetInfo[];
73
+ activeSheetId: string;
74
+ names: import("@pixerate/editor").SpreadsheetNameInfo[];
46
75
  controller: SpreadsheetController;
47
76
  getCell(rowId: string, colId: string): CellData;
48
77
  setCellValue(rowId: string, colId: string, raw: string): void;
49
78
  selectCell(row: number, col: number, extendSelection?: boolean): void;
50
79
  selectRange(range: CellRange): void;
51
80
  startEditing(row?: number, col?: number, initialVal?: string): void;
52
- commitEditing(val?: string): void;
81
+ conditionalFormatOverlay: import("@pixerate/editor").ConditionalFormatOverlay;
82
+ validationPrompt: SpreadsheetValidationPrompt | null;
83
+ commitEditing(val?: string): SpreadsheetCommitResult;
84
+ /** Commits input from outside the cell editor (formula bar, list dropdown) with validation. */
85
+ commitCellInput(rowId: string, colId: string, raw: string): SpreadsheetCommitResult;
86
+ /** Answers the validation alert: accept (warning / information), retry or cancel. */
87
+ resolveValidationPrompt(action: SpreadsheetValidationAction): void;
53
88
  cancelEditing(): void;
54
89
  moveCursor(dir: "up" | "down" | "left" | "right", extend?: boolean): void;
55
90
  insertColumn(index: number, config?: Partial<SpreadsheetColumn>): void;
@@ -67,5 +102,25 @@ export declare function createReactiveSpreadsheet(options?: SpreadsheetControlle
67
102
  importFromTsv(data: string): void;
68
103
  undo(): void;
69
104
  redo(): void;
105
+ setActiveSheet(idOrName: string): boolean;
106
+ addSheet(options?: Parameters<(options?: {
107
+ name?: string;
108
+ index?: number;
109
+ document?: Partial<SpreadsheetDocument>;
110
+ activate?: boolean;
111
+ }) => string>[0]): string;
112
+ renameSheet(idOrName: string, newName: string): void;
113
+ moveSheet(idOrName: string, toIndex: number): boolean;
114
+ deleteSheet(idOrName: string): boolean;
115
+ duplicateSheet(idOrName: string, options?: Parameters<(idOrName: string, options?: {
116
+ name?: string;
117
+ index?: number;
118
+ activate?: boolean;
119
+ }) => string | null>[1]): string | null;
120
+ defineName(name: string, refersTo: string, options?: SpreadsheetNameScope & {
121
+ comment?: string;
122
+ }): void;
123
+ renameName(oldName: string, newName: string, options?: SpreadsheetNameScope): void;
124
+ deleteName(name: string, options?: SpreadsheetNameScope): boolean;
70
125
  };
71
126
  //# sourceMappingURL=spreadsheet.svelte.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"spreadsheet.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/spreadsheet.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EAErB,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC3B,MAAM,8BAA8B,CAAC;AAEtC,wBAAgB,yBAAyB,CAAC,OAAO,GAAE,4BAAiC;;aAmLy20B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBA/Gt60B,MAAM;;mBAMX,MAAM,SAAS,MAAM,GAAG,QAAQ;wBAG3B,MAAM,SAAS,MAAM,OAAO,MAAM;oBAItC,MAAM,OAAO,MAAM;uBAKhB,SAAS;uBAIT,MAAM,QAAQ,MAAM,eAAe,MAAM;wBAMxC,MAAM;;oBAWV,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO;wBAK5B,MAAM,WAAW,OAAO,CAAC,iBAAiB,CAAC;wBAI3C,MAAM;qBAIT,MAAM,WAAW,OAAO,CAAC,cAAc,CAAC;qBAIxC,MAAM;0BAID,MAAM,SAAS,MAAM;8BAIjB,MAAM,gBAAgB,MAAM;2BAI/B,mBAAmB;;2BAanB,qBAAqB;6BAInB,MAAM,GAAG,SAAS;;wBAQvB,SAAS,GAAG,IAAI;wBAGhB,MAAM;;;EAc7B"}
1
+ {"version":3,"file":"spreadsheet.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/spreadsheet.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EAErB,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,2BAA2B,EAChC,KAAK,2BAA2B,EACjC,MAAM,8BAA8B,CAAC;AAEtC,wBAAgB,yBAAyB,CAAC,OAAO,GAAE,4BAAiC;;aAyRuokD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAAgyW,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAnKr+6D,MAAM;;;;;mBAMX,MAAM,SAAS,MAAM,GAAG,QAAQ;wBAG3B,MAAM,SAAS,MAAM,OAAO,MAAM;oBAItC,MAAM,OAAO,MAAM;uBAKhB,SAAS;uBAIT,MAAM,QAAQ,MAAM,eAAe,MAAM;;;wBAYxC,MAAM,GAAG,uBAAuB;IAKpD,+FAA+F;2BACxE,MAAM,SAAS,MAAM,OAAO,MAAM,GAAG,uBAAuB;IAKnF,qFAAqF;oCACrD,2BAA2B;;oBAS3C,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO;wBAK5B,MAAM,WAAW,OAAO,CAAC,iBAAiB,CAAC;wBAI3C,MAAM;qBAIT,MAAM,WAAW,OAAO,CAAC,cAAc,CAAC;qBAIxC,MAAM;0BAID,MAAM,SAAS,MAAM;8BAIjB,MAAM,gBAAgB,MAAM;2BAI/B,mBAAmB;;2BAanB,qBAAqB;6BAInB,MAAM,GAAG,SAAS;;wBAQvB,SAAS,GAAG,IAAI;wBAGhB,MAAM;;;6BAaD,MAAM;uBAKZ,UAAU;YAiCyowD,CAAC;aAAuB,CAAC;gBAA0B,CAAC;gBAAgD,CAAC;iBAjCltwD,CAAC,CAAC,CAAC;0BAKtC,MAAM,WAAW,MAAM;wBAGzB,MAAM,WAAW,MAAM;0BAGrB,MAAM;6BAKH,MAAM,YAAY,UAAU;YAiBsvyD,CAAC;aAAuB,CAAC;gBAA0B,CAAC;wBAjBxwyD,CAAC,CAAC,CAAC;qBAKzE,MAAM,YAAY,MAAM,YAAY,oBAAoB,GAAG;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE;wBAG5E,MAAM,WAAW,MAAM,YAAY,oBAAoB;qBAG1D,MAAM,YAAY,oBAAoB;EAK1D"}