@pixerate/editor-svelte 0.23.0 → 0.25.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 (147) hide show
  1. package/README.md +4 -2
  2. package/dist/ExportDocxButton.svelte +48 -0
  3. package/dist/ExportDocxButton.svelte.d.ts +13 -0
  4. package/dist/ExportDocxButton.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/canvas/AnimationTimeline.svelte +217 -0
  9. package/dist/canvas/AnimationTimeline.svelte.d.ts +20 -0
  10. package/dist/canvas/AnimationTimeline.svelte.d.ts.map +1 -0
  11. package/dist/canvas/CanvasComponentsPanel.svelte +73 -0
  12. package/dist/canvas/CanvasComponentsPanel.svelte.d.ts +13 -0
  13. package/dist/canvas/CanvasComponentsPanel.svelte.d.ts.map +1 -0
  14. package/dist/canvas/CanvasInstanceInspector.svelte +136 -0
  15. package/dist/canvas/CanvasInstanceInspector.svelte.d.ts +16 -0
  16. package/dist/canvas/CanvasInstanceInspector.svelte.d.ts.map +1 -0
  17. package/dist/canvas/TokenBindingPicker.svelte +93 -0
  18. package/dist/canvas/TokenBindingPicker.svelte.d.ts +20 -0
  19. package/dist/canvas/TokenBindingPicker.svelte.d.ts.map +1 -0
  20. package/dist/canvas/TokenModeSwitcher.svelte +55 -0
  21. package/dist/canvas/TokenModeSwitcher.svelte.d.ts +18 -0
  22. package/dist/canvas/TokenModeSwitcher.svelte.d.ts.map +1 -0
  23. package/dist/canvas/createCanvasAnimation.svelte.d.ts +98 -0
  24. package/dist/canvas/createCanvasAnimation.svelte.d.ts.map +1 -0
  25. package/dist/canvas/createCanvasAnimation.svelte.js +79 -0
  26. package/dist/canvas/createCanvasArrange.svelte.d.ts +4 -0
  27. package/dist/canvas/createCanvasArrange.svelte.d.ts.map +1 -1
  28. package/dist/canvas/createCanvasAutoLayout.svelte.d.ts.map +1 -1
  29. package/dist/canvas/createCanvasComponents.svelte.d.ts +68 -0
  30. package/dist/canvas/createCanvasComponents.svelte.d.ts.map +1 -0
  31. package/dist/canvas/createCanvasComponents.svelte.js +31 -0
  32. package/dist/canvas/createCanvasTokens.svelte.d.ts +31 -0
  33. package/dist/canvas/createCanvasTokens.svelte.d.ts.map +1 -0
  34. package/dist/canvas/createCanvasTokens.svelte.js +50 -0
  35. package/dist/canvas/index.d.ts +12 -0
  36. package/dist/canvas/index.d.ts.map +1 -1
  37. package/dist/canvas/index.js +16 -0
  38. package/dist/docxExport.svelte.d.ts +26 -0
  39. package/dist/docxExport.svelte.d.ts.map +1 -0
  40. package/dist/docxExport.svelte.js +36 -0
  41. package/dist/fileImport.svelte.d.ts +8 -1
  42. package/dist/fileImport.svelte.d.ts.map +1 -1
  43. package/dist/fileImport.svelte.js +11 -1
  44. package/dist/generation/AssetMentionChips.svelte +130 -0
  45. package/dist/generation/AssetMentionChips.svelte.d.ts +21 -0
  46. package/dist/generation/AssetMentionChips.svelte.d.ts.map +1 -0
  47. package/dist/generation/GenerationHistory.svelte +161 -0
  48. package/dist/generation/GenerationHistory.svelte.d.ts +28 -0
  49. package/dist/generation/GenerationHistory.svelte.d.ts.map +1 -0
  50. package/dist/generation/index.d.ts +7 -0
  51. package/dist/generation/index.d.ts.map +1 -1
  52. package/dist/generation/index.js +3 -0
  53. package/dist/generation/records.svelte.d.ts +18 -0
  54. package/dist/generation/records.svelte.d.ts.map +1 -0
  55. package/dist/generation/records.svelte.js +66 -0
  56. package/dist/image-editor/ImageEditor.svelte +72 -1
  57. package/dist/image-editor/ImageEditor.svelte.d.ts.map +1 -1
  58. package/dist/image-editor/RefineEdgePanel.svelte +180 -0
  59. package/dist/image-editor/RefineEdgePanel.svelte.d.ts +13 -0
  60. package/dist/image-editor/RefineEdgePanel.svelte.d.ts.map +1 -0
  61. package/dist/image-editor/SelectionOptionsBar.svelte +135 -0
  62. package/dist/image-editor/SelectionOptionsBar.svelte.d.ts +15 -0
  63. package/dist/image-editor/SelectionOptionsBar.svelte.d.ts.map +1 -0
  64. package/dist/image-editor/index.d.ts +6 -0
  65. package/dist/image-editor/index.d.ts.map +1 -1
  66. package/dist/image-editor/index.js +2 -0
  67. package/dist/index.d.ts +9 -0
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +5 -0
  70. package/dist/paragraphStyles.svelte.d.ts +30 -0
  71. package/dist/paragraphStyles.svelte.d.ts.map +1 -0
  72. package/dist/paragraphStyles.svelte.js +44 -0
  73. package/dist/review/TrackedChangesList.svelte +67 -0
  74. package/dist/review/TrackedChangesList.svelte.d.ts +13 -0
  75. package/dist/review/TrackedChangesList.svelte.d.ts.map +1 -0
  76. package/dist/review/index.d.ts +3 -0
  77. package/dist/review/index.d.ts.map +1 -1
  78. package/dist/review/index.js +1 -0
  79. package/dist/review/review.svelte.d.ts +6 -0
  80. package/dist/review/review.svelte.d.ts.map +1 -1
  81. package/dist/review/review.svelte.js +3 -0
  82. package/dist/spreadsheet/FormulaBar.svelte +13 -4
  83. package/dist/spreadsheet/FormulaBar.svelte.d.ts.map +1 -1
  84. package/dist/spreadsheet/FormulaHints.svelte +7 -5
  85. package/dist/spreadsheet/FormulaHints.svelte.d.ts +3 -0
  86. package/dist/spreadsheet/FormulaHints.svelte.d.ts.map +1 -1
  87. package/dist/spreadsheet/NameManager.svelte +165 -0
  88. package/dist/spreadsheet/NameManager.svelte.d.ts +11 -0
  89. package/dist/spreadsheet/NameManager.svelte.d.ts.map +1 -0
  90. package/dist/spreadsheet/SheetTabs.svelte +161 -0
  91. package/dist/spreadsheet/SheetTabs.svelte.d.ts +10 -0
  92. package/dist/spreadsheet/SheetTabs.svelte.d.ts.map +1 -0
  93. package/dist/spreadsheet/SpreadsheetConditionalFormatPanel.svelte +184 -0
  94. package/dist/spreadsheet/SpreadsheetConditionalFormatPanel.svelte.d.ts +9 -0
  95. package/dist/spreadsheet/SpreadsheetConditionalFormatPanel.svelte.d.ts.map +1 -0
  96. package/dist/spreadsheet/SpreadsheetContextMenu.svelte +9 -4
  97. package/dist/spreadsheet/SpreadsheetContextMenu.svelte.d.ts +5 -1
  98. package/dist/spreadsheet/SpreadsheetContextMenu.svelte.d.ts.map +1 -1
  99. package/dist/spreadsheet/SpreadsheetDataValidationPanel.svelte +141 -0
  100. package/dist/spreadsheet/SpreadsheetDataValidationPanel.svelte.d.ts +9 -0
  101. package/dist/spreadsheet/SpreadsheetDataValidationPanel.svelte.d.ts.map +1 -0
  102. package/dist/spreadsheet/SpreadsheetEditor.svelte +273 -19
  103. package/dist/spreadsheet/SpreadsheetEditor.svelte.d.ts +8 -0
  104. package/dist/spreadsheet/SpreadsheetEditor.svelte.d.ts.map +1 -1
  105. package/dist/spreadsheet/SpreadsheetGroupRow.svelte +31 -3
  106. package/dist/spreadsheet/SpreadsheetGroupRow.svelte.d.ts +6 -0
  107. package/dist/spreadsheet/SpreadsheetGroupRow.svelte.d.ts.map +1 -1
  108. package/dist/spreadsheet/SpreadsheetValidationDialog.svelte +92 -0
  109. package/dist/spreadsheet/SpreadsheetValidationDialog.svelte.d.ts +9 -0
  110. package/dist/spreadsheet/SpreadsheetValidationDialog.svelte.d.ts.map +1 -0
  111. package/dist/spreadsheet/index.d.ts +10 -0
  112. package/dist/spreadsheet/index.d.ts.map +1 -1
  113. package/dist/spreadsheet/index.js +6 -0
  114. package/dist/spreadsheet/spreadsheet.svelte.d.ts +56 -3
  115. package/dist/spreadsheet/spreadsheet.svelte.d.ts.map +1 -1
  116. package/dist/spreadsheet/spreadsheet.svelte.js +105 -6
  117. package/dist/spreadsheet/viewport.svelte.d.ts +26 -0
  118. package/dist/spreadsheet/viewport.svelte.d.ts.map +1 -0
  119. package/dist/spreadsheet/viewport.svelte.js +93 -0
  120. package/dist/tables/InsertTableGrid.svelte +85 -0
  121. package/dist/tables/InsertTableGrid.svelte.d.ts +21 -0
  122. package/dist/tables/InsertTableGrid.svelte.d.ts.map +1 -0
  123. package/dist/tables/TableBubbleMenu.svelte +43 -0
  124. package/dist/tables/TableBubbleMenu.svelte.d.ts +18 -0
  125. package/dist/tables/TableBubbleMenu.svelte.d.ts.map +1 -0
  126. package/dist/tables/TableToolbar.svelte +81 -0
  127. package/dist/tables/TableToolbar.svelte.d.ts +19 -0
  128. package/dist/tables/TableToolbar.svelte.d.ts.map +1 -0
  129. package/dist/tables/index.d.ts +12 -0
  130. package/dist/tables/index.d.ts.map +1 -0
  131. package/dist/tables/index.js +4 -0
  132. package/dist/tables/tableMenu.svelte.d.ts +21 -0
  133. package/dist/tables/tableMenu.svelte.d.ts.map +1 -0
  134. package/dist/tables/tableMenu.svelte.js +27 -0
  135. package/dist/tokens/TokenSwatch.svelte +14 -0
  136. package/dist/tokens/TokenSwatch.svelte.d.ts +8 -0
  137. package/dist/tokens/TokenSwatch.svelte.d.ts.map +1 -0
  138. package/dist/tokens/TokensPanel.svelte +323 -0
  139. package/dist/tokens/TokensPanel.svelte.d.ts +14 -0
  140. package/dist/tokens/TokensPanel.svelte.d.ts.map +1 -0
  141. package/dist/tokens/createTokens.svelte.d.ts +31 -0
  142. package/dist/tokens/createTokens.svelte.d.ts.map +1 -0
  143. package/dist/tokens/createTokens.svelte.js +43 -0
  144. package/dist/tokens/index.d.ts +7 -0
  145. package/dist/tokens/index.d.ts.map +1 -0
  146. package/dist/tokens/index.js +3 -0
  147. package/package.json +10 -2
@@ -9,12 +9,31 @@
9
9
  onToggle: (key: string) => void;
10
10
  /** Render a trailing cell for the "add column" column. */
11
11
  trailingCell?: boolean;
12
+ /** Every displayed column, when `columns` is a virtualised window of them (picks the label column). */
13
+ labelColumns?: SpreadsheetViewColumn[];
14
+ /** Virtualised: columns before the left spacer (the frozen ones), and the spacers' widths. */
15
+ leadingColumns?: number;
16
+ leftSpace?: number;
17
+ rightSpace?: number;
12
18
  }
13
19
 
14
- let { group, columns, groupColId, onToggle, trailingCell = false }: Props = $props();
20
+ let {
21
+ group,
22
+ columns,
23
+ groupColId,
24
+ onToggle,
25
+ trailingCell = false,
26
+ labelColumns,
27
+ leadingColumns,
28
+ leftSpace = 0,
29
+ rightSpace = 0
30
+ }: Props = $props();
15
31
 
16
32
  // The label goes in the grouping column, or the first column when that one is hidden.
17
- let labelColId = $derived(columns.some((c) => c.column.id === groupColId) ? groupColId : columns[0]?.column.id);
33
+ let labelColId = $derived.by(() => {
34
+ const candidates = labelColumns ?? columns;
35
+ return candidates.some((c) => c.column.id === groupColId) ? groupColId : candidates[0]?.column.id;
36
+ });
18
37
 
19
38
  const formatSummary = (value: number | null) => (value === null ? '–' : String(value));
20
39
  </script>
@@ -35,8 +54,11 @@
35
54
  {group.collapsed ? '▸' : '▾'}
36
55
  </button>
37
56
  </td>
38
- {#each columns as { column } (column.id)}
57
+ {#each columns as { column }, i (column.id)}
39
58
  {@const summary = group.summaries[column.id]}
59
+ {#if leadingColumns !== undefined && i === leadingColumns && leftSpace > 0}
60
+ <td aria-hidden="true" data-spacer="" style="padding: 0;"></td>
61
+ {/if}
40
62
  <td class="border-r border-border px-2 py-1 truncate max-w-0 text-foreground" style="max-width: 0; overflow: hidden;">
41
63
  {#if column.id === labelColId}
42
64
  <span class="truncate">
@@ -47,6 +69,12 @@
47
69
  {/if}
48
70
  </td>
49
71
  {/each}
72
+ {#if leadingColumns !== undefined && leadingColumns >= columns.length && leftSpace > 0}
73
+ <td aria-hidden="true" data-spacer="" style="padding: 0;"></td>
74
+ {/if}
75
+ {#if rightSpace > 0}
76
+ <td aria-hidden="true" data-spacer="" style="padding: 0;"></td>
77
+ {/if}
50
78
  {#if trailingCell}
51
79
  <td class="w-10 min-w-[2.5rem] bg-muted/10 border-r border-border"></td>
52
80
  {/if}
@@ -7,6 +7,12 @@ interface Props {
7
7
  onToggle: (key: string) => void;
8
8
  /** Render a trailing cell for the "add column" column. */
9
9
  trailingCell?: boolean;
10
+ /** Every displayed column, when `columns` is a virtualised window of them (picks the label column). */
11
+ labelColumns?: SpreadsheetViewColumn[];
12
+ /** Virtualised: columns before the left spacer (the frozen ones), and the spacers' widths. */
13
+ leadingColumns?: number;
14
+ leftSpace?: number;
15
+ rightSpace?: number;
10
16
  }
11
17
  declare const SpreadsheetGroupRow: import("svelte").Component<Props, {}, "">;
12
18
  type SpreadsheetGroupRow = ReturnType<typeof SpreadsheetGroupRow>;
@@ -1 +1 @@
1
- {"version":3,"file":"SpreadsheetGroupRow.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/SpreadsheetGroupRow.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAG7F,UAAU,KAAK;IACb,KAAK,EAAE,mBAAmB,CAAC;IAC3B,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACjC,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,0DAA0D;IAC1D,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AA4CH,QAAA,MAAM,mBAAmB,2CAAwC,CAAC;AAClE,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAClE,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"SpreadsheetGroupRow.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/SpreadsheetGroupRow.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAG7F,UAAU,KAAK;IACb,KAAK,EAAE,mBAAmB,CAAC;IAC3B,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACjC,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,0DAA0D;IAC1D,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,uGAAuG;IACvG,YAAY,CAAC,EAAE,qBAAqB,EAAE,CAAC;IACvC,8FAA8F;IAC9F,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAkEH,QAAA,MAAM,mBAAmB,2CAAwC,CAAC;AAClE,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAClE,eAAe,mBAAmB,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,24 @@ 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>;
24
+ export * from './viewport.svelte.js';
15
25
  //# 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;AAC3E,cAAc,sBAAsB,CAAC"}
@@ -1,7 +1,13 @@
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';
13
+ export * from './viewport.svelte.js';
@@ -1,5 +1,6 @@
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
+ mergeCells: (range?: CellRange | null) => boolean;
3
4
  sortRows: (keys: import("@pixerate/editor").SortKey[], options?: {
4
5
  range?: CellRange | null;
5
6
  }) => boolean;
@@ -23,7 +24,6 @@ export declare function createReactiveSpreadsheet(options?: SpreadsheetControlle
23
24
  unhideAll: () => void;
24
25
  getMerges: () => CellRange[];
25
26
  getMergeAt: (row: number, col: number) => CellRange | null;
26
- mergeCells: (range?: CellRange | null) => boolean;
27
27
  unmergeCells: (range?: CellRange | null) => boolean;
28
28
  autofill: (source: CellRange, target: CellRange) => boolean;
29
29
  groupRowsBy: (colId: string, summaries?: import("@pixerate/editor").GroupSummary[]) => void;
@@ -39,19 +39,52 @@ export declare function createReactiveSpreadsheet(options?: SpreadsheetControlle
39
39
  importFromCsv: (csv: string, options?: import("@pixerate/editor").CsvImportOptions) => void;
40
40
  copyToClipboardData: (range?: CellRange | null) => import("@pixerate/editor").SpreadsheetClipboardData;
41
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;
42
66
  document: SpreadsheetDocument;
43
67
  activeCell: CellCoordinate | null;
44
68
  selectedRange: CellRange | null;
45
69
  editingCell: CellCoordinate | null;
46
70
  viewModel: import("@pixerate/editor").SpreadsheetViewModel;
47
71
  draftValue: string;
72
+ sheets: import("@pixerate/editor").SpreadsheetSheetInfo[];
73
+ activeSheetId: string;
74
+ names: import("@pixerate/editor").SpreadsheetNameInfo[];
48
75
  controller: SpreadsheetController;
49
76
  getCell(rowId: string, colId: string): CellData;
50
77
  setCellValue(rowId: string, colId: string, raw: string): void;
51
78
  selectCell(row: number, col: number, extendSelection?: boolean): void;
52
79
  selectRange(range: CellRange): void;
53
80
  startEditing(row?: number, col?: number, initialVal?: string): void;
54
- 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;
55
88
  cancelEditing(): void;
56
89
  moveCursor(dir: "up" | "down" | "left" | "right", extend?: boolean): void;
57
90
  insertColumn(index: number, config?: Partial<SpreadsheetColumn>): void;
@@ -69,5 +102,25 @@ export declare function createReactiveSpreadsheet(options?: SpreadsheetControlle
69
102
  importFromTsv(data: string): void;
70
103
  undo(): void;
71
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;
72
125
  };
73
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;;aAmLoz2B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBA/Gj32B,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;;;aAyRmx0D,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAA06W,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAnK3vrE,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;YAiCqxgE,CAAC;aAAuB,CAAC;gBAA0B,CAAC;gBAAgD,CAAC;iBAjC91gE,CAAC,CAAC,CAAC;0BAKtC,MAAM,WAAW,MAAM;wBAGzB,MAAM,WAAW,MAAM;0BAGrB,MAAM;6BAKH,MAAM,YAAY,UAAU;YAiBk4iE,CAAC;aAAuB,CAAC;gBAA0B,CAAC;wBAjBp5iE,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"}
@@ -13,6 +13,8 @@ export function createReactiveSpreadsheet(options = {}) {
13
13
  let selectedRange = $state(null);
14
14
  let editingCell = $state(null);
15
15
  let draftValue = $state('');
16
+ // Invalid input waiting for the user (data validation alert).
17
+ let validationPrompt = $state.raw(null);
16
18
  const controller = new SpreadsheetController({
17
19
  ...options,
18
20
  document: options.document,
@@ -43,6 +45,39 @@ export function createReactiveSpreadsheet(options = {}) {
43
45
  // transpose, CSV, clipboard). The controller reports their changes through
44
46
  // onDocumentChange / onSelectionChange, which update the state above.
45
47
  const tableActions = bindSpreadsheetTableActions(controller);
48
+ // Conditional formatting of every formatted cell (re-evaluated incrementally).
49
+ const conditionalFormatOverlay = $derived.by(() => {
50
+ void doc;
51
+ return controller.getConditionalFormatOverlay();
52
+ });
53
+ // Input breaking a data validation rule is not committed: the editor stays
54
+ // open and `validationPrompt` holds the alert until it is resolved.
55
+ function syncEditing() {
56
+ editingCell = controller.editingCell;
57
+ draftValue = controller.draftValue;
58
+ validationPrompt = controller.validationPrompt;
59
+ activeCell = controller.activeCell;
60
+ selectedRange = controller.selectedRange;
61
+ doc = { ...controller.document };
62
+ }
63
+ // Sheet tabs and defined names. Every workbook change notifies through
64
+ // onDocumentChange, so they follow `doc`.
65
+ const sheets = $derived.by(() => {
66
+ void doc;
67
+ return controller.getSheets();
68
+ });
69
+ const names = $derived.by(() => {
70
+ void doc;
71
+ return controller.getNames();
72
+ });
73
+ // Switching sheets commits the edit in progress.
74
+ function afterSheetSwitch() {
75
+ doc = { ...controller.document };
76
+ activeCell = controller.activeCell;
77
+ selectedRange = controller.selectedRange;
78
+ editingCell = controller.editingCell;
79
+ draftValue = controller.draftValue;
80
+ }
46
81
  return {
47
82
  get document() {
48
83
  return doc;
@@ -62,6 +97,18 @@ export function createReactiveSpreadsheet(options = {}) {
62
97
  get draftValue() {
63
98
  return draftValue;
64
99
  },
100
+ /** The sheets in tab order (see `SpreadsheetController.getSheets`). */
101
+ get sheets() {
102
+ return sheets;
103
+ },
104
+ get activeSheetId() {
105
+ void doc;
106
+ return controller.activeSheetId;
107
+ },
108
+ /** Defined names (see `SpreadsheetController.getNames`). */
109
+ get names() {
110
+ return names;
111
+ },
65
112
  set draftValue(val) {
66
113
  draftValue = val;
67
114
  controller.draftValue = val;
@@ -89,11 +136,27 @@ export function createReactiveSpreadsheet(options = {}) {
89
136
  editingCell = controller.editingCell;
90
137
  draftValue = controller.draftValue;
91
138
  },
139
+ get conditionalFormatOverlay() {
140
+ return conditionalFormatOverlay;
141
+ },
142
+ get validationPrompt() {
143
+ return validationPrompt;
144
+ },
92
145
  commitEditing(val) {
93
- controller.commitEditing(val);
94
- editingCell = null;
95
- draftValue = '';
96
- doc = { ...controller.document };
146
+ const result = controller.commitEditing(val);
147
+ syncEditing();
148
+ return result;
149
+ },
150
+ /** Commits input from outside the cell editor (formula bar, list dropdown) with validation. */
151
+ commitCellInput(rowId, colId, raw) {
152
+ const result = controller.commitCellInput(rowId, colId, raw);
153
+ syncEditing();
154
+ return result;
155
+ },
156
+ /** Answers the validation alert: accept (warning / information), retry or cancel. */
157
+ resolveValidationPrompt(action) {
158
+ controller.resolveValidationPrompt(action);
159
+ syncEditing();
97
160
  },
98
161
  cancelEditing() {
99
162
  controller.cancelEditing();
@@ -161,13 +224,49 @@ export function createReactiveSpreadsheet(options = {}) {
161
224
  controller.importFromTsv(data);
162
225
  doc = { ...controller.document };
163
226
  },
227
+ // Undo can switch to the sheet the step belongs to.
164
228
  undo() {
165
229
  controller.undo();
166
- doc = { ...controller.document };
230
+ afterSheetSwitch();
167
231
  },
168
232
  redo() {
169
233
  controller.redo();
170
- doc = { ...controller.document };
234
+ afterSheetSwitch();
235
+ },
236
+ setActiveSheet(idOrName) {
237
+ const changed = controller.setActiveSheet(idOrName);
238
+ afterSheetSwitch();
239
+ return changed;
240
+ },
241
+ addSheet(options) {
242
+ const id = controller.addSheet(options);
243
+ afterSheetSwitch();
244
+ return id;
245
+ },
246
+ renameSheet(idOrName, newName) {
247
+ controller.renameSheet(idOrName, newName);
248
+ },
249
+ moveSheet(idOrName, toIndex) {
250
+ return controller.moveSheet(idOrName, toIndex);
251
+ },
252
+ deleteSheet(idOrName) {
253
+ const deleted = controller.deleteSheet(idOrName);
254
+ afterSheetSwitch();
255
+ return deleted;
256
+ },
257
+ duplicateSheet(idOrName, options) {
258
+ const id = controller.duplicateSheet(idOrName, options);
259
+ afterSheetSwitch();
260
+ return id;
261
+ },
262
+ defineName(name, refersTo, options) {
263
+ controller.defineName(name, refersTo, options);
264
+ },
265
+ renameName(oldName, newName, options) {
266
+ controller.renameName(oldName, newName, options);
267
+ },
268
+ deleteName(name, options) {
269
+ return controller.deleteName(name, options);
171
270
  },
172
271
  ...tableActions
173
272
  };
@@ -0,0 +1,26 @@
1
+ import { type CellCoordinate, type CellRange, type SpreadsheetViewModel } from '@pixerate/editor/spreadsheet';
2
+ export interface SpreadsheetViewportSource {
3
+ view: () => SpreadsheetViewModel;
4
+ /** `'auto'` (default): virtualise large views only; `true` / `false` force it. */
5
+ virtualize?: () => boolean | 'auto' | undefined;
6
+ /** Merged ranges, rendered whole when they cross the window's edge. */
7
+ merges?: () => readonly CellRange[] | undefined;
8
+ /** Scrolled into view when it changes (virtualised views only). */
9
+ activeCell?: () => CellCoordinate | null | undefined;
10
+ overscanRows?: number;
11
+ overscanColumns?: number;
12
+ }
13
+ /**
14
+ * Virtualised rendering for `SpreadsheetEditor` (the Svelte counterpart of
15
+ * React's `useSpreadsheetViewport`): tracks the scroll container passed to
16
+ * `attach`, works out the window of rows and columns to render, and scrolls
17
+ * the active cell into view. Call it while a component initialises.
18
+ */
19
+ export declare function createSpreadsheetViewport(source: SpreadsheetViewportSource): {
20
+ readonly metrics: import("@pixerate/editor").SpreadsheetViewMetrics;
21
+ /** What to render; `virtual: false` renders every row and column. */
22
+ readonly window: import("@pixerate/editor").SpreadsheetViewWindow;
23
+ onScroll: () => void;
24
+ attach: (el: HTMLElement | null) => () => void;
25
+ };
26
+ //# sourceMappingURL=viewport.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewport.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/viewport.svelte.ts"],"names":[],"mappings":"AACA,OAAO,EAOL,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,oBAAoB,EAG1B,MAAM,8BAA8B,CAAC;AAEtC,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,oBAAoB,CAAC;IACjC,kFAAkF;IAClF,UAAU,CAAC,EAAE,MAAM,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IAChD,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,SAAS,SAAS,EAAE,GAAG,SAAS,CAAC;IAChD,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,cAAc,GAAG,IAAI,GAAG,SAAS,CAAC;IACrD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,yBAAyB;;IA4EvE,qEAAqE;;;iBAxCnD,WAAW,GAAG,IAAI,KAAG,MAAM,IAAI;EA+CpD"}
@@ -0,0 +1,93 @@
1
+ import { untrack } from 'svelte';
2
+ import { fullSpreadsheetViewWindow, getSpreadsheetScrollToCell, getSpreadsheetViewWindow, measureSpreadsheetView, sameSpreadsheetViewWindow, shouldVirtualizeSpreadsheet } from '@pixerate/editor/spreadsheet';
3
+ /**
4
+ * Virtualised rendering for `SpreadsheetEditor` (the Svelte counterpart of
5
+ * React's `useSpreadsheetViewport`): tracks the scroll container passed to
6
+ * `attach`, works out the window of rows and columns to render, and scrolls
7
+ * the active cell into view. Call it while a component initialises.
8
+ */
9
+ export function createSpreadsheetViewport(source) {
10
+ let viewport = $state.raw({ scrollTop: 0, scrollLeft: 0, width: 0, height: 0 });
11
+ let element = null;
12
+ const metrics = $derived(measureSpreadsheetView(source.view()));
13
+ const virtual = $derived(shouldVirtualizeSpreadsheet(source.view(), source.virtualize?.() ?? 'auto'));
14
+ const windowOptions = $derived({
15
+ merges: source.merges?.(),
16
+ overscanRows: source.overscanRows,
17
+ overscanColumns: source.overscanColumns
18
+ });
19
+ const win = $derived(virtual ? getSpreadsheetViewWindow(metrics, viewport, windowOptions) : fullSpreadsheetViewWindow(metrics));
20
+ const read = (el) => ({
21
+ scrollTop: el.scrollTop,
22
+ scrollLeft: el.scrollLeft,
23
+ width: el.clientWidth,
24
+ height: el.clientHeight
25
+ });
26
+ /** Stores a new viewport, re-rendering only when the window it gives changes. */
27
+ function update(next) {
28
+ if (!virtual)
29
+ return;
30
+ const prev = viewport;
31
+ const same = prev.width === next.width &&
32
+ prev.height === next.height &&
33
+ sameSpreadsheetViewWindow(getSpreadsheetViewWindow(metrics, prev, windowOptions), getSpreadsheetViewWindow(metrics, next, windowOptions));
34
+ if (!same)
35
+ viewport = next;
36
+ }
37
+ function onScroll() {
38
+ if (element)
39
+ update(read(element));
40
+ }
41
+ /** Tracks `el` (the scroll container); returns a cleanup function. */
42
+ function attach(el) {
43
+ element = el;
44
+ if (!el)
45
+ return () => { };
46
+ onScroll();
47
+ if (typeof ResizeObserver === 'undefined')
48
+ return () => { };
49
+ const observer = new ResizeObserver(() => onScroll());
50
+ observer.observe(el);
51
+ return () => observer.disconnect();
52
+ }
53
+ // Measure once virtualisation turns on (the element may already be attached).
54
+ $effect(() => {
55
+ if (virtual)
56
+ untrack(onScroll);
57
+ });
58
+ // Keyboard navigation and selection: bring the active cell into view.
59
+ // Only the active cell and the mode re-run it: scrolling away from the
60
+ // active cell (or an edit elsewhere) must not snap back.
61
+ $effect(() => {
62
+ const cell = source.activeCell?.();
63
+ const row = cell?.row;
64
+ const col = cell?.col;
65
+ if (!virtual || row === undefined || col === undefined)
66
+ return;
67
+ untrack(() => {
68
+ const base = element ? read(element) : viewport;
69
+ const target = getSpreadsheetScrollToCell(metrics, base, { row, col });
70
+ if (!target)
71
+ return;
72
+ if (element) {
73
+ if (target.scrollTop !== undefined)
74
+ element.scrollTop = target.scrollTop;
75
+ if (target.scrollLeft !== undefined)
76
+ element.scrollLeft = target.scrollLeft;
77
+ }
78
+ // Some environments (jsdom) never fire the scroll event.
79
+ update({ ...base, ...target });
80
+ });
81
+ });
82
+ return {
83
+ get metrics() {
84
+ return metrics;
85
+ },
86
+ /** What to render; `virtual: false` renders every row and column. */
87
+ get window() {
88
+ return win;
89
+ },
90
+ onScroll,
91
+ attach
92
+ };
93
+ }