@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.
- package/README.md +6 -2
- package/dist/MergePreview.svelte +201 -0
- package/dist/MergePreview.svelte.d.ts +25 -0
- package/dist/MergePreview.svelte.d.ts.map +1 -0
- package/dist/StylesGallery.svelte +169 -0
- package/dist/StylesGallery.svelte.d.ts +27 -0
- package/dist/StylesGallery.svelte.d.ts.map +1 -0
- package/dist/TemplateRenderer.svelte +4 -10
- package/dist/TemplateRenderer.svelte.d.ts.map +1 -1
- package/dist/canvas/TokenBindingPicker.svelte +93 -0
- package/dist/canvas/TokenBindingPicker.svelte.d.ts +20 -0
- package/dist/canvas/TokenBindingPicker.svelte.d.ts.map +1 -0
- package/dist/canvas/TokenModeSwitcher.svelte +55 -0
- package/dist/canvas/TokenModeSwitcher.svelte.d.ts +18 -0
- package/dist/canvas/TokenModeSwitcher.svelte.d.ts.map +1 -0
- package/dist/canvas/createCanvasArrange.svelte.d.ts +4 -0
- package/dist/canvas/createCanvasArrange.svelte.d.ts.map +1 -1
- package/dist/canvas/createCanvasAutoLayout.svelte.d.ts +68 -0
- package/dist/canvas/createCanvasAutoLayout.svelte.d.ts.map +1 -0
- package/dist/canvas/createCanvasAutoLayout.svelte.js +78 -0
- package/dist/canvas/createCanvasTokens.svelte.d.ts +31 -0
- package/dist/canvas/createCanvasTokens.svelte.d.ts.map +1 -0
- package/dist/canvas/createCanvasTokens.svelte.js +50 -0
- package/dist/canvas/index.d.ts +7 -0
- package/dist/canvas/index.d.ts.map +1 -1
- package/dist/canvas/index.js +10 -0
- package/dist/fileImport.svelte.d.ts +8 -1
- package/dist/fileImport.svelte.d.ts.map +1 -1
- package/dist/fileImport.svelte.js +11 -1
- package/dist/find-replace/FindReplaceBar.svelte +203 -0
- package/dist/find-replace/FindReplaceBar.svelte.d.ts +15 -0
- package/dist/find-replace/FindReplaceBar.svelte.d.ts.map +1 -0
- package/dist/find-replace/findReplace.svelte.d.ts +27 -0
- package/dist/find-replace/findReplace.svelte.d.ts.map +1 -0
- package/dist/find-replace/findReplace.svelte.js +79 -0
- package/dist/find-replace/index.d.ts +6 -0
- package/dist/find-replace/index.d.ts.map +1 -0
- package/dist/find-replace/index.js +2 -0
- package/dist/generation/AssetMentionChips.svelte +130 -0
- package/dist/generation/AssetMentionChips.svelte.d.ts +21 -0
- package/dist/generation/AssetMentionChips.svelte.d.ts.map +1 -0
- package/dist/generation/GenerationHistory.svelte +161 -0
- package/dist/generation/GenerationHistory.svelte.d.ts +28 -0
- package/dist/generation/GenerationHistory.svelte.d.ts.map +1 -0
- package/dist/generation/GenerationSettings.svelte +174 -0
- package/dist/generation/GenerationSettings.svelte.d.ts +23 -0
- package/dist/generation/GenerationSettings.svelte.d.ts.map +1 -0
- package/dist/generation/JobProgress.svelte +53 -0
- package/dist/generation/JobProgress.svelte.d.ts +17 -0
- package/dist/generation/JobProgress.svelte.d.ts.map +1 -0
- package/dist/generation/index.d.ts +17 -0
- package/dist/generation/index.d.ts.map +1 -0
- package/dist/generation/index.js +7 -0
- package/dist/generation/plan.svelte.d.ts +16 -0
- package/dist/generation/plan.svelte.d.ts.map +1 -0
- package/dist/generation/plan.svelte.js +26 -0
- package/dist/generation/progress.svelte.d.ts +25 -0
- package/dist/generation/progress.svelte.d.ts.map +1 -0
- package/dist/generation/progress.svelte.js +36 -0
- package/dist/generation/records.svelte.d.ts +18 -0
- package/dist/generation/records.svelte.d.ts.map +1 -0
- package/dist/generation/records.svelte.js +66 -0
- package/dist/image-editor/AdjustmentLayersPanel.svelte +309 -0
- package/dist/image-editor/AdjustmentLayersPanel.svelte.d.ts +11 -0
- package/dist/image-editor/AdjustmentLayersPanel.svelte.d.ts.map +1 -0
- package/dist/image-editor/ControlSlider.svelte +39 -0
- package/dist/image-editor/ControlSlider.svelte.d.ts +13 -0
- package/dist/image-editor/ControlSlider.svelte.d.ts.map +1 -0
- package/dist/image-editor/CurvesEditor.svelte +105 -0
- package/dist/image-editor/CurvesEditor.svelte.d.ts +13 -0
- package/dist/image-editor/CurvesEditor.svelte.d.ts.map +1 -0
- package/dist/image-editor/Histogram.svelte +49 -0
- package/dist/image-editor/Histogram.svelte.d.ts +12 -0
- package/dist/image-editor/Histogram.svelte.d.ts.map +1 -0
- package/dist/image-editor/ImageEditor.svelte +104 -141
- package/dist/image-editor/ImageEditor.svelte.d.ts.map +1 -1
- package/dist/image-editor/RefineEdgePanel.svelte +180 -0
- package/dist/image-editor/RefineEdgePanel.svelte.d.ts +13 -0
- package/dist/image-editor/RefineEdgePanel.svelte.d.ts.map +1 -0
- package/dist/image-editor/SelectionOptionsBar.svelte +135 -0
- package/dist/image-editor/SelectionOptionsBar.svelte.d.ts +15 -0
- package/dist/image-editor/SelectionOptionsBar.svelte.d.ts.map +1 -0
- package/dist/image-editor/imageEditorState.svelte.d.ts +14 -1
- package/dist/image-editor/imageEditorState.svelte.d.ts.map +1 -1
- package/dist/image-editor/imageEditorState.svelte.js +40 -0
- package/dist/image-editor/index.d.ts +18 -0
- package/dist/image-editor/index.d.ts.map +1 -1
- package/dist/image-editor/index.js +6 -0
- package/dist/index.d.ts +12 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/merge.svelte.d.ts +51 -0
- package/dist/merge.svelte.d.ts.map +1 -0
- package/dist/merge.svelte.js +117 -0
- package/dist/paragraphStyles.svelte.d.ts +30 -0
- package/dist/paragraphStyles.svelte.d.ts.map +1 -0
- package/dist/paragraphStyles.svelte.js +44 -0
- package/dist/persistence/RecoveryPrompt.svelte +57 -0
- package/dist/persistence/RecoveryPrompt.svelte.d.ts +18 -0
- package/dist/persistence/RecoveryPrompt.svelte.d.ts.map +1 -0
- package/dist/persistence/autosave.svelte.d.ts +63 -0
- package/dist/persistence/autosave.svelte.d.ts.map +1 -0
- package/dist/persistence/autosave.svelte.js +110 -0
- package/dist/persistence/index.d.ts +6 -0
- package/dist/persistence/index.d.ts.map +1 -0
- package/dist/persistence/index.js +2 -0
- package/dist/review/TrackedChangesList.svelte +67 -0
- package/dist/review/TrackedChangesList.svelte.d.ts +13 -0
- package/dist/review/TrackedChangesList.svelte.d.ts.map +1 -0
- package/dist/review/documentCompare.svelte.d.ts +21 -0
- package/dist/review/documentCompare.svelte.d.ts.map +1 -0
- package/dist/review/documentCompare.svelte.js +23 -0
- package/dist/review/index.d.ts +4 -0
- package/dist/review/index.d.ts.map +1 -1
- package/dist/review/index.js +2 -0
- package/dist/review/review.svelte.d.ts +6 -0
- package/dist/review/review.svelte.d.ts.map +1 -1
- package/dist/review/review.svelte.js +3 -0
- package/dist/spreadsheet/FormulaBar.svelte +13 -4
- package/dist/spreadsheet/FormulaBar.svelte.d.ts.map +1 -1
- package/dist/spreadsheet/FormulaHints.svelte +7 -5
- package/dist/spreadsheet/FormulaHints.svelte.d.ts +3 -0
- package/dist/spreadsheet/FormulaHints.svelte.d.ts.map +1 -1
- package/dist/spreadsheet/NameManager.svelte +165 -0
- package/dist/spreadsheet/NameManager.svelte.d.ts +11 -0
- package/dist/spreadsheet/NameManager.svelte.d.ts.map +1 -0
- package/dist/spreadsheet/SheetTabs.svelte +161 -0
- package/dist/spreadsheet/SheetTabs.svelte.d.ts +10 -0
- package/dist/spreadsheet/SheetTabs.svelte.d.ts.map +1 -0
- package/dist/spreadsheet/SpreadsheetConditionalFormatPanel.svelte +184 -0
- package/dist/spreadsheet/SpreadsheetConditionalFormatPanel.svelte.d.ts +9 -0
- package/dist/spreadsheet/SpreadsheetConditionalFormatPanel.svelte.d.ts.map +1 -0
- package/dist/spreadsheet/SpreadsheetContextMenu.svelte +13 -5
- package/dist/spreadsheet/SpreadsheetContextMenu.svelte.d.ts +5 -1
- package/dist/spreadsheet/SpreadsheetContextMenu.svelte.d.ts.map +1 -1
- package/dist/spreadsheet/SpreadsheetDataValidationPanel.svelte +141 -0
- package/dist/spreadsheet/SpreadsheetDataValidationPanel.svelte.d.ts +9 -0
- package/dist/spreadsheet/SpreadsheetDataValidationPanel.svelte.d.ts.map +1 -0
- package/dist/spreadsheet/SpreadsheetEditor.svelte +199 -11
- package/dist/spreadsheet/SpreadsheetEditor.svelte.d.ts +2 -0
- package/dist/spreadsheet/SpreadsheetEditor.svelte.d.ts.map +1 -1
- package/dist/spreadsheet/SpreadsheetValidationDialog.svelte +92 -0
- package/dist/spreadsheet/SpreadsheetValidationDialog.svelte.d.ts +9 -0
- package/dist/spreadsheet/SpreadsheetValidationDialog.svelte.d.ts.map +1 -0
- package/dist/spreadsheet/index.d.ts +9 -0
- package/dist/spreadsheet/index.d.ts.map +1 -1
- package/dist/spreadsheet/index.js +5 -0
- package/dist/spreadsheet/spreadsheet.svelte.d.ts +57 -2
- package/dist/spreadsheet/spreadsheet.svelte.d.ts.map +1 -1
- package/dist/spreadsheet/spreadsheet.svelte.js +105 -6
- package/dist/tokens/TokenSwatch.svelte +14 -0
- package/dist/tokens/TokenSwatch.svelte.d.ts +8 -0
- package/dist/tokens/TokenSwatch.svelte.d.ts.map +1 -0
- package/dist/tokens/TokensPanel.svelte +323 -0
- package/dist/tokens/TokensPanel.svelte.d.ts +14 -0
- package/dist/tokens/TokensPanel.svelte.d.ts.map +1 -0
- package/dist/tokens/createTokens.svelte.d.ts +31 -0
- package/dist/tokens/createTokens.svelte.d.ts.map +1 -0
- package/dist/tokens/createTokens.svelte.js +43 -0
- package/dist/tokens/index.d.ts +7 -0
- package/dist/tokens/index.d.ts.map +1 -0
- package/dist/tokens/index.js +3 -0
- package/package.json +26 -2
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { createAutosaveController, createRevisionTracker, } from "@pixerate/editor/persistence";
|
|
2
|
+
/**
|
|
3
|
+
* Svelte 5 rune: crash-recovery autosave bound to a history and dirty flag,
|
|
4
|
+
* with page lifecycle flushing and a recovery check (see
|
|
5
|
+
* `createAutosaveController` in `@pixerate/editor/persistence`). Render
|
|
6
|
+
* `<RecoveryPrompt>` with `recovery`, `restore` and `discard`.
|
|
7
|
+
*/
|
|
8
|
+
export function createAutosave(options) {
|
|
9
|
+
const revisions = createRevisionTracker({ history: options.history, dirty: options.dirty });
|
|
10
|
+
const controller = createAutosaveController({
|
|
11
|
+
storage: options.storage,
|
|
12
|
+
key: options.key,
|
|
13
|
+
getSnapshot: options.getSnapshot,
|
|
14
|
+
serialize: options.serialize,
|
|
15
|
+
deserialize: options.deserialize,
|
|
16
|
+
name: options.name,
|
|
17
|
+
revision: revisions.revision,
|
|
18
|
+
savedRevision: revisions.savedRevision,
|
|
19
|
+
interval: options.interval,
|
|
20
|
+
debounceMs: options.debounceMs,
|
|
21
|
+
retryBaseMs: options.retryBaseMs,
|
|
22
|
+
retryMaxMs: options.retryMaxMs,
|
|
23
|
+
});
|
|
24
|
+
const recover = options.recover !== false;
|
|
25
|
+
let status = $state.raw(controller.getStatus());
|
|
26
|
+
let recovery = $state.raw(null);
|
|
27
|
+
let pendingRecovery = $state(recover);
|
|
28
|
+
let loaded = options.ready !== false;
|
|
29
|
+
let destroyed = false;
|
|
30
|
+
const maybeReady = () => {
|
|
31
|
+
if (!destroyed && loaded && !pendingRecovery)
|
|
32
|
+
controller.ready();
|
|
33
|
+
};
|
|
34
|
+
const unsubscribeStatus = controller.subscribe((info) => {
|
|
35
|
+
status = info;
|
|
36
|
+
});
|
|
37
|
+
const unsubscribeRevisions = revisions.subscribe(() => controller.notify());
|
|
38
|
+
const checked = recover
|
|
39
|
+
? controller
|
|
40
|
+
.checkRecovery()
|
|
41
|
+
.catch(() => null)
|
|
42
|
+
.then((found) => {
|
|
43
|
+
if (destroyed)
|
|
44
|
+
return;
|
|
45
|
+
recovery = found;
|
|
46
|
+
pendingRecovery = found !== null;
|
|
47
|
+
maybeReady();
|
|
48
|
+
})
|
|
49
|
+
: Promise.resolve();
|
|
50
|
+
maybeReady();
|
|
51
|
+
let removeListeners = () => { };
|
|
52
|
+
if (options.flushOnHide !== false && typeof window !== "undefined") {
|
|
53
|
+
const flush = () => void controller.flushNow();
|
|
54
|
+
const onVisibility = () => {
|
|
55
|
+
if (document.visibilityState === "hidden")
|
|
56
|
+
flush();
|
|
57
|
+
};
|
|
58
|
+
window.addEventListener("pagehide", flush);
|
|
59
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
60
|
+
removeListeners = () => {
|
|
61
|
+
window.removeEventListener("pagehide", flush);
|
|
62
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
get status() {
|
|
67
|
+
return status;
|
|
68
|
+
},
|
|
69
|
+
get recovery() {
|
|
70
|
+
return recovery;
|
|
71
|
+
},
|
|
72
|
+
get pendingRecovery() {
|
|
73
|
+
return pendingRecovery;
|
|
74
|
+
},
|
|
75
|
+
restore() {
|
|
76
|
+
const snapshot = recovery?.snapshot;
|
|
77
|
+
recovery = null;
|
|
78
|
+
pendingRecovery = false;
|
|
79
|
+
// Deferred so the caller can apply the snapshot first.
|
|
80
|
+
queueMicrotask(maybeReady);
|
|
81
|
+
return snapshot;
|
|
82
|
+
},
|
|
83
|
+
async discard() {
|
|
84
|
+
await controller.discardRecovery();
|
|
85
|
+
recovery = null;
|
|
86
|
+
pendingRecovery = false;
|
|
87
|
+
maybeReady();
|
|
88
|
+
},
|
|
89
|
+
ready() {
|
|
90
|
+
loaded = true;
|
|
91
|
+
maybeReady();
|
|
92
|
+
},
|
|
93
|
+
flushNow: () => controller.flushNow(),
|
|
94
|
+
async markClean() {
|
|
95
|
+
revisions.markSaved();
|
|
96
|
+
await controller.markClean();
|
|
97
|
+
},
|
|
98
|
+
notifyChange: () => revisions.bump(),
|
|
99
|
+
checked,
|
|
100
|
+
controller,
|
|
101
|
+
destroy() {
|
|
102
|
+
destroyed = true;
|
|
103
|
+
removeListeners();
|
|
104
|
+
unsubscribeStatus();
|
|
105
|
+
unsubscribeRevisions();
|
|
106
|
+
revisions.destroy();
|
|
107
|
+
controller.destroy();
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ComponentProps } from "svelte";
|
|
2
|
+
import type RecoveryPromptComponent from "./RecoveryPrompt.svelte";
|
|
3
|
+
export { default as RecoveryPrompt } from "./RecoveryPrompt.svelte";
|
|
4
|
+
export * from "./autosave.svelte.js";
|
|
5
|
+
export type RecoveryPromptProps = ComponentProps<typeof RecoveryPromptComponent>;
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/persistence/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,KAAK,uBAAuB,MAAM,yBAAyB,CAAC;AAEnE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACpE,cAAc,sBAAsB,CAAC;AAErC,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,OAAO,uBAAuB,CAAC,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Editor } from "@tiptap/core";
|
|
3
|
+
import { trackedChangeLabel } from "@pixerate/editor";
|
|
4
|
+
import { createTrackChanges, type SvelteTrackChanges } from "./review.svelte.js";
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
editor?: Editor | null;
|
|
8
|
+
class?: string;
|
|
9
|
+
itemClass?: string;
|
|
10
|
+
activeItemClass?: string;
|
|
11
|
+
/** Text shown when there are no changes. */
|
|
12
|
+
emptyState?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let {
|
|
16
|
+
editor = null,
|
|
17
|
+
class: className = "flex flex-col gap-1 text-sm",
|
|
18
|
+
itemClass = "flex items-center gap-2 rounded px-2 py-1 hover:bg-muted/50",
|
|
19
|
+
activeItemClass = "bg-primary/10",
|
|
20
|
+
emptyState = "No tracked changes.",
|
|
21
|
+
}: Props = $props();
|
|
22
|
+
|
|
23
|
+
const buttonClass =
|
|
24
|
+
"rounded px-1.5 py-0.5 text-xs text-foreground hover:bg-muted disabled:opacity-40";
|
|
25
|
+
|
|
26
|
+
let review = $state.raw<SvelteTrackChanges>(createTrackChanges(null));
|
|
27
|
+
|
|
28
|
+
$effect(() => {
|
|
29
|
+
const r = createTrackChanges(editor);
|
|
30
|
+
review = r;
|
|
31
|
+
return () => r.destroy();
|
|
32
|
+
});
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
{#if review.changes.length === 0}
|
|
36
|
+
<div class={className} data-tracked-changes-list="">
|
|
37
|
+
<div class="pixerate-changes-empty text-xs text-muted-foreground">{emptyState}</div>
|
|
38
|
+
</div>
|
|
39
|
+
{:else}
|
|
40
|
+
<ul class={className} role="list" aria-label="Tracked changes" data-tracked-changes-list="">
|
|
41
|
+
{#each review.changes as change (`${change.type}:${change.id}`)}
|
|
42
|
+
<li
|
|
43
|
+
class={change.id === review.currentChangeId ? `${itemClass} ${activeItemClass}` : itemClass}
|
|
44
|
+
data-change-type={change.type}
|
|
45
|
+
data-change-id={change.id}
|
|
46
|
+
>
|
|
47
|
+
<button
|
|
48
|
+
type="button"
|
|
49
|
+
class="min-w-0 flex-1 truncate text-left text-xs"
|
|
50
|
+
title={`${change.author.name}: ${change.description}`}
|
|
51
|
+
onclick={() => review.select(change.id)}
|
|
52
|
+
>
|
|
53
|
+
<span class="font-medium">{trackedChangeLabel(change)}</span>{change.author.name
|
|
54
|
+
? ` · ${change.author.name}`
|
|
55
|
+
: ""}
|
|
56
|
+
<span class="block truncate text-muted-foreground">{change.description}</span>
|
|
57
|
+
</button>
|
|
58
|
+
<button type="button" class={buttonClass} onclick={() => review.accept(change.id)}>
|
|
59
|
+
Accept
|
|
60
|
+
</button>
|
|
61
|
+
<button type="button" class={buttonClass} onclick={() => review.reject(change.id)}>
|
|
62
|
+
Reject
|
|
63
|
+
</button>
|
|
64
|
+
</li>
|
|
65
|
+
{/each}
|
|
66
|
+
</ul>
|
|
67
|
+
{/if}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Editor } from "@tiptap/core";
|
|
2
|
+
interface Props {
|
|
3
|
+
editor?: Editor | null;
|
|
4
|
+
class?: string;
|
|
5
|
+
itemClass?: string;
|
|
6
|
+
activeItemClass?: string;
|
|
7
|
+
/** Text shown when there are no changes. */
|
|
8
|
+
emptyState?: string;
|
|
9
|
+
}
|
|
10
|
+
declare const TrackedChangesList: import("svelte").Component<Props, {}, "">;
|
|
11
|
+
type TrackedChangesList = ReturnType<typeof TrackedChangesList>;
|
|
12
|
+
export default TrackedChangesList;
|
|
13
|
+
//# sourceMappingURL=TrackedChangesList.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TrackedChangesList.svelte.d.ts","sourceRoot":"","sources":["../../src/review/TrackedChangesList.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAKzC,UAAU,KAAK;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAsDH,QAAA,MAAM,kBAAkB,2CAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Editor } from "@tiptap/core";
|
|
2
|
+
import { type CompareSource, type CompareSummary, type EditorCompareOptions } from "@pixerate/editor";
|
|
3
|
+
export type { CompareSource, CompareSummary, EditorCompareOptions } from "@pixerate/editor";
|
|
4
|
+
export interface SvelteDocumentCompare {
|
|
5
|
+
/** Summary of the last comparison, or `null` (reactive). */
|
|
6
|
+
readonly summary: CompareSummary | null;
|
|
7
|
+
/**
|
|
8
|
+
* Replaces the editor content with the comparison of two versions (nodes,
|
|
9
|
+
* JSON or HTML) as tracked changes, ready to review with `ReviewToolbar`.
|
|
10
|
+
* Returns the summary, or `null` without an editor.
|
|
11
|
+
*/
|
|
12
|
+
compare(original: CompareSource, revised: CompareSource, options?: EditorCompareOptions): CompareSummary | null;
|
|
13
|
+
/** Forgets the last summary. */
|
|
14
|
+
clear(): void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Compare two document versions into an editor using `TrackChanges`.
|
|
18
|
+
* `options` are defaults for every comparison.
|
|
19
|
+
*/
|
|
20
|
+
export declare function createDocumentCompare(editor: Editor | null | undefined, options?: EditorCompareOptions): SvelteDocumentCompare;
|
|
21
|
+
//# sourceMappingURL=documentCompare.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentCompare.svelte.d.ts","sourceRoot":"","sources":["../../src/review/documentCompare.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAC1B,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE5F,MAAM,WAAW,qBAAqB;IACpC,4DAA4D;IAC5D,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;IACxC;;;;OAIG;IACH,OAAO,CACL,QAAQ,EAAE,aAAa,EACvB,OAAO,EAAE,aAAa,EACtB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,cAAc,GAAG,IAAI,CAAC;IACzB,gCAAgC;IAChC,KAAK,IAAI,IAAI,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACjC,OAAO,CAAC,EAAE,oBAAoB,GAC7B,qBAAqB,CAgBvB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { applyDocumentComparison, } from "@pixerate/editor";
|
|
2
|
+
/**
|
|
3
|
+
* Compare two document versions into an editor using `TrackChanges`.
|
|
4
|
+
* `options` are defaults for every comparison.
|
|
5
|
+
*/
|
|
6
|
+
export function createDocumentCompare(editor, options) {
|
|
7
|
+
let summary = $state.raw(null);
|
|
8
|
+
return {
|
|
9
|
+
get summary() {
|
|
10
|
+
return summary;
|
|
11
|
+
},
|
|
12
|
+
compare(original, revised, overrides) {
|
|
13
|
+
if (!editor || editor.isDestroyed)
|
|
14
|
+
return null;
|
|
15
|
+
const result = applyDocumentComparison(editor, original, revised, { ...options, ...overrides });
|
|
16
|
+
summary = result.summary;
|
|
17
|
+
return result.summary;
|
|
18
|
+
},
|
|
19
|
+
clear() {
|
|
20
|
+
summary = null;
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
package/dist/review/index.d.ts
CHANGED
|
@@ -2,10 +2,14 @@ import type { ComponentProps } from "svelte";
|
|
|
2
2
|
import type CommentsPanelComponent from "./CommentsPanel.svelte";
|
|
3
3
|
import type ReviewToolbarComponent from "./ReviewToolbar.svelte";
|
|
4
4
|
import type CommentButtonComponent from "./CommentButton.svelte";
|
|
5
|
+
import type TrackedChangesListComponent from "./TrackedChangesList.svelte";
|
|
6
|
+
export { default as TrackedChangesList } from "./TrackedChangesList.svelte";
|
|
7
|
+
export type TrackedChangesListProps = ComponentProps<typeof TrackedChangesListComponent>;
|
|
5
8
|
export { default as CommentsPanel } from "./CommentsPanel.svelte";
|
|
6
9
|
export { default as ReviewToolbar } from "./ReviewToolbar.svelte";
|
|
7
10
|
export { default as CommentButton } from "./CommentButton.svelte";
|
|
8
11
|
export * from "./review.svelte.js";
|
|
12
|
+
export * from "./documentCompare.svelte.js";
|
|
9
13
|
export type CommentsPanelProps = ComponentProps<typeof CommentsPanelComponent>;
|
|
10
14
|
export type ReviewToolbarProps = ComponentProps<typeof ReviewToolbarComponent>;
|
|
11
15
|
export type CommentButtonProps = ComponentProps<typeof CommentButtonComponent>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/review/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,KAAK,sBAAsB,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,sBAAsB,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,sBAAsB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/review/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,KAAK,sBAAsB,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,sBAAsB,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,sBAAsB,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,2BAA2B,MAAM,6BAA6B,CAAC;AAE3E,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,MAAM,MAAM,uBAAuB,GAAG,cAAc,CAAC,OAAO,2BAA2B,CAAC,CAAC;AACzF,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAClE,cAAc,oBAAoB,CAAC;AACnC,cAAc,6BAA6B,CAAC;AAE5C,MAAM,MAAM,kBAAkB,GAAG,cAAc,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAC/E,MAAM,MAAM,kBAAkB,GAAG,cAAc,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAC/E,MAAM,MAAM,kBAAkB,GAAG,cAAc,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
|
package/dist/review/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
export { default as TrackedChangesList } from "./TrackedChangesList.svelte";
|
|
1
2
|
export { default as CommentsPanel } from "./CommentsPanel.svelte";
|
|
2
3
|
export { default as ReviewToolbar } from "./ReviewToolbar.svelte";
|
|
3
4
|
export { default as CommentButton } from "./CommentButton.svelte";
|
|
4
5
|
export * from "./review.svelte.js";
|
|
6
|
+
export * from "./documentCompare.svelte.js";
|
|
@@ -29,6 +29,12 @@ export interface SvelteTrackChanges extends TrackChangesSnapshot {
|
|
|
29
29
|
rejectAll(): void;
|
|
30
30
|
next(): void;
|
|
31
31
|
previous(): void;
|
|
32
|
+
/** Selects a change in the editor. */
|
|
33
|
+
select(id: string): void;
|
|
34
|
+
/** Accepts a tracked move (both ends). */
|
|
35
|
+
acceptMove(id: string): void;
|
|
36
|
+
/** Rejects a tracked move (both ends). */
|
|
37
|
+
rejectMove(id: string): void;
|
|
32
38
|
subscribe(run: (value: TrackChangesSnapshot) => void): () => void;
|
|
33
39
|
destroy(): void;
|
|
34
40
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review.svelte.d.ts","sourceRoot":"","sources":["../../src/review/review.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,aAAa,EACnB,MAAM,kBAAkB,CAAC;AAE1B,eAAO,MAAM,uBAAuB,EAAE,oBAGZ,CAAC;AAE3B,eAAO,MAAM,4BAA4B,EAAE,oBAKjB,CAAC;AAE3B,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAMpE;AAED,2EAA2E;AAC3E,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,GAAG,SAAS,GAC/C,YAAY,GAAG,IAAI,CAErB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;IAC3C,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IACpC,SAAS,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAClE,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,GAAG,SAAS,GAAG,cAAc,CA4B/F;AAED,MAAM,WAAW,kBAAmB,SAAQ,oBAAoB;IAC9D,QAAQ,CAAC,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7C,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACnC,MAAM,IAAI,IAAI,CAAC;IACf,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,IAAI,IAAI,CAAC;IAClB,SAAS,IAAI,IAAI,CAAC;IAClB,IAAI,IAAI,IAAI,CAAC;IACb,QAAQ,IAAI,IAAI,CAAC;IACjB,SAAS,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAClE,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,kBAAkB,
|
|
1
|
+
{"version":3,"file":"review.svelte.d.ts","sourceRoot":"","sources":["../../src/review/review.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,aAAa,EACnB,MAAM,kBAAkB,CAAC;AAE1B,eAAO,MAAM,uBAAuB,EAAE,oBAGZ,CAAC;AAE3B,eAAO,MAAM,4BAA4B,EAAE,oBAKjB,CAAC;AAE3B,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAMpE;AAED,2EAA2E;AAC3E,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,GAAG,SAAS,GAC/C,YAAY,GAAG,IAAI,CAErB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;IAC3C,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IACpC,SAAS,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAClE,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,GAAG,SAAS,GAAG,cAAc,CA4B/F;AAED,MAAM,WAAW,kBAAmB,SAAQ,oBAAoB;IAC9D,QAAQ,CAAC,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IAC7C,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACnC,MAAM,IAAI,IAAI,CAAC;IACf,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,IAAI,IAAI,CAAC;IAClB,SAAS,IAAI,IAAI,CAAC;IAClB,IAAI,IAAI,IAAI,CAAC;IACb,QAAQ,IAAI,IAAI,CAAC;IACjB,sCAAsC;IACtC,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,0CAA0C;IAC1C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAClE,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,kBAAkB,CAkDxF"}
|
|
@@ -92,6 +92,9 @@ export function createTrackChanges(editor) {
|
|
|
92
92
|
rejectAll: () => run((e) => e.commands.rejectAllChanges()),
|
|
93
93
|
next: () => run((e) => e.chain().focus().selectNextChange().run()),
|
|
94
94
|
previous: () => run((e) => e.chain().focus().selectPreviousChange().run()),
|
|
95
|
+
select: (id) => run((e) => e.chain().focus().selectChange(id).run()),
|
|
96
|
+
acceptMove: (id) => run((e) => e.commands.acceptMove(id)),
|
|
97
|
+
rejectMove: (id) => run((e) => e.commands.rejectMove(id)),
|
|
95
98
|
subscribe(runFn) {
|
|
96
99
|
if (!store) {
|
|
97
100
|
runFn(EMPTY_TRACK_CHANGES_SNAPSHOT);
|
|
@@ -46,6 +46,13 @@
|
|
|
46
46
|
return value;
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
+
// Defined names for formula autocomplete.
|
|
50
|
+
let nameSuggestions = $derived.by(() => {
|
|
51
|
+
if (!sheetState) return [];
|
|
52
|
+
void sheetState.document;
|
|
53
|
+
return sheetState.controller.getNameSuggestions();
|
|
54
|
+
});
|
|
55
|
+
|
|
49
56
|
// A spilled cell shows its anchor's formula greyed out (it has no formula of its own).
|
|
50
57
|
let spillFormula = $derived.by(() => {
|
|
51
58
|
if (!sheetState || sheetState.editingCell || !sheetState.activeCell || effectiveValue) return '';
|
|
@@ -63,10 +70,12 @@
|
|
|
63
70
|
if (sheetState && sheetState.activeCell) {
|
|
64
71
|
const row = sheetState.document.rows[sheetState.activeCell.row];
|
|
65
72
|
const col = sheetState.document.columns[sheetState.activeCell.col];
|
|
66
|
-
|
|
67
|
-
|
|
73
|
+
// Committed with data validation: invalid input waits for the alert.
|
|
74
|
+
if (sheetState.editingCell) {
|
|
75
|
+
sheetState.commitEditing(effectiveValue);
|
|
76
|
+
} else if (row && col) {
|
|
77
|
+
sheetState.commitCellInput(row.id, col.id, effectiveValue);
|
|
68
78
|
}
|
|
69
|
-
sheetState.commitEditing();
|
|
70
79
|
}
|
|
71
80
|
onCommit?.(effectiveValue);
|
|
72
81
|
} else if (e.key === 'Escape') {
|
|
@@ -116,5 +125,5 @@
|
|
|
116
125
|
oninput={handleInput}
|
|
117
126
|
onkeydown={handleKeyDown}
|
|
118
127
|
/>
|
|
119
|
-
<FormulaHints input={inputEl} value={effectiveValue} onAccept={setValue} />
|
|
128
|
+
<FormulaHints input={inputEl} value={effectiveValue} onAccept={setValue} names={nameSuggestions} />
|
|
120
129
|
</div>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormulaBar.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/FormulaBar.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAIvE,UAAU,KAAK;IACb,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC;IAC1D,WAAW,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;
|
|
1
|
+
{"version":3,"file":"FormulaBar.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/FormulaBar.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAIvE,UAAU,KAAK;IACb,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC;IAC1D,WAAW,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAiHH,QAAA,MAAM,UAAU,gDAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { tick } from 'svelte';
|
|
3
|
-
import { applyFormulaSuggestion, getFormulaHints } from '@pixerate/editor/spreadsheet';
|
|
3
|
+
import { applyFormulaSuggestion, getFormulaHints, type FormulaNameSuggestionSource } from '@pixerate/editor/spreadsheet';
|
|
4
4
|
|
|
5
5
|
interface Props {
|
|
6
6
|
/** The input being edited (a cell editor or the formula bar). */
|
|
@@ -11,9 +11,11 @@
|
|
|
11
11
|
onAccept?: (value: string) => void;
|
|
12
12
|
/** Maximum number of function suggestions (default 8). */
|
|
13
13
|
limit?: number;
|
|
14
|
+
/** Defined names to suggest too (e.g. `controller.getNameSuggestions()`). */
|
|
15
|
+
names?: readonly FormulaNameSuggestionSource[];
|
|
14
16
|
}
|
|
15
17
|
|
|
16
|
-
let { input = null, value = '', onAccept, limit = 8 }: Props = $props();
|
|
18
|
+
let { input = null, value = '', onAccept, limit = 8, names }: Props = $props();
|
|
17
19
|
|
|
18
20
|
let caret = $state<number | null>(null);
|
|
19
21
|
let focused = $state(false);
|
|
@@ -21,7 +23,7 @@
|
|
|
21
23
|
let dismissed = $state(false);
|
|
22
24
|
let position = $state<{ top: number; left: number; width: number } | null>(null);
|
|
23
25
|
|
|
24
|
-
let hints = $derived(getFormulaHints(value, caret ?? value.length, { limit }));
|
|
26
|
+
let hints = $derived(getFormulaHints(value, caret ?? value.length, { limit, names }));
|
|
25
27
|
let suggestions = $derived(dismissed ? [] : hints.suggestions);
|
|
26
28
|
let selectedIndex = $derived(Math.max(0, Math.min(selected, suggestions.length - 1)));
|
|
27
29
|
let visible = $derived(
|
|
@@ -31,7 +33,7 @@
|
|
|
31
33
|
async function accept(index: number) {
|
|
32
34
|
const suggestion = suggestions[index];
|
|
33
35
|
if (!suggestion || !input) return;
|
|
34
|
-
const next = applyFormulaSuggestion(value, caret ?? value.length, suggestion
|
|
36
|
+
const next = applyFormulaSuggestion(value, caret ?? value.length, suggestion);
|
|
35
37
|
caret = next.caret;
|
|
36
38
|
selected = 0;
|
|
37
39
|
onAccept?.(next.value);
|
|
@@ -127,7 +129,7 @@
|
|
|
127
129
|
{/if}
|
|
128
130
|
{#if suggestions.length > 0}
|
|
129
131
|
<ul role="listbox" aria-label="Formula suggestions" class="max-h-64 overflow-auto m-0 list-none p-0 py-1">
|
|
130
|
-
{#each suggestions as s, i (s.name)}
|
|
132
|
+
{#each suggestions as s, i (`${s.kind ?? "fn"}:${s.name}`)}
|
|
131
133
|
<li
|
|
132
134
|
role="option"
|
|
133
135
|
aria-selected={i === selectedIndex}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type FormulaNameSuggestionSource } from '@pixerate/editor/spreadsheet';
|
|
1
2
|
interface Props {
|
|
2
3
|
/** The input being edited (a cell editor or the formula bar). */
|
|
3
4
|
input?: HTMLInputElement | null;
|
|
@@ -7,6 +8,8 @@ interface Props {
|
|
|
7
8
|
onAccept?: (value: string) => void;
|
|
8
9
|
/** Maximum number of function suggestions (default 8). */
|
|
9
10
|
limit?: number;
|
|
11
|
+
/** Defined names to suggest too (e.g. `controller.getNameSuggestions()`). */
|
|
12
|
+
names?: readonly FormulaNameSuggestionSource[];
|
|
10
13
|
}
|
|
11
14
|
declare const FormulaHints: import("svelte").Component<Props, {}, "">;
|
|
12
15
|
type FormulaHints = ReturnType<typeof FormulaHints>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormulaHints.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/FormulaHints.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FormulaHints.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/FormulaHints.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,EAA2C,KAAK,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAGvH,UAAU,KAAK;IACb,iEAAiE;IACjE,KAAK,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAChC,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,KAAK,CAAC,EAAE,SAAS,2BAA2B,EAAE,CAAC;CAChD;AAoIH,QAAA,MAAM,YAAY,2CAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { getNameManagerRows, parseFormula, type SpreadsheetNameRow } from '@pixerate/editor/spreadsheet';
|
|
3
|
+
import type { createReactiveSpreadsheet } from './spreadsheet.svelte.js';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
sheetState: ReturnType<typeof createReactiveSpreadsheet>;
|
|
7
|
+
readOnly?: boolean;
|
|
8
|
+
onClose?: () => void;
|
|
9
|
+
class?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let { sheetState, readOnly = false, onClose, class: className = '' }: Props = $props();
|
|
13
|
+
|
|
14
|
+
interface Draft {
|
|
15
|
+
/** The name being edited (null for a new one). */
|
|
16
|
+
original: { name: string; sheetId?: string } | null;
|
|
17
|
+
name: string;
|
|
18
|
+
refersTo: string;
|
|
19
|
+
/** Sheet id, or '' for workbook scope. */
|
|
20
|
+
scope: string;
|
|
21
|
+
comment: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const EMPTY_DRAFT: Draft = { original: null, name: '', refersTo: '=', scope: '', comment: '' };
|
|
25
|
+
|
|
26
|
+
let draft = $state<Draft>({ ...EMPTY_DRAFT });
|
|
27
|
+
let error = $state<string | null>(null);
|
|
28
|
+
|
|
29
|
+
const rows = $derived.by(() => {
|
|
30
|
+
void sheetState.document;
|
|
31
|
+
void sheetState.names;
|
|
32
|
+
return getNameManagerRows(sheetState.controller);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
function edit(row: SpreadsheetNameRow) {
|
|
36
|
+
error = null;
|
|
37
|
+
draft = {
|
|
38
|
+
original: { name: row.name, sheetId: row.sheetId },
|
|
39
|
+
name: row.name,
|
|
40
|
+
refersTo: row.refersTo,
|
|
41
|
+
scope: row.sheetId ?? '',
|
|
42
|
+
comment: row.comment ?? ''
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function save(e: SubmitEvent) {
|
|
47
|
+
e.preventDefault();
|
|
48
|
+
const scope = draft.scope ? { sheet: draft.scope } : {};
|
|
49
|
+
try {
|
|
50
|
+
// Check before changing anything, so a failed edit keeps the old name.
|
|
51
|
+
const invalid = sheetState.controller.validateDefinedName(draft.name.trim());
|
|
52
|
+
if (invalid) throw new Error(invalid);
|
|
53
|
+
const formula = draft.refersTo.trim().startsWith('=') ? draft.refersTo.trim() : `=${draft.refersTo.trim()}`;
|
|
54
|
+
try {
|
|
55
|
+
parseFormula(formula);
|
|
56
|
+
} catch (err: any) {
|
|
57
|
+
throw new Error(`There's a problem with this formula: ${err?.message ?? formula}`);
|
|
58
|
+
}
|
|
59
|
+
const original = draft.original;
|
|
60
|
+
if (original) {
|
|
61
|
+
const originalScope = original.sheetId ? { sheet: original.sheetId } : {};
|
|
62
|
+
if ((original.sheetId ?? '') !== draft.scope) {
|
|
63
|
+
sheetState.deleteName(original.name, originalScope);
|
|
64
|
+
} else if (original.name !== draft.name.trim()) {
|
|
65
|
+
sheetState.renameName(original.name, draft.name.trim(), originalScope);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
sheetState.defineName(draft.name.trim(), draft.refersTo, { ...scope, comment: draft.comment || undefined });
|
|
69
|
+
draft = { ...EMPTY_DRAFT };
|
|
70
|
+
error = null;
|
|
71
|
+
} catch (err: any) {
|
|
72
|
+
error = err?.message ?? String(err);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function remove(row: SpreadsheetNameRow) {
|
|
77
|
+
sheetState.deleteName(row.name, row.sheetId ? { sheet: row.sheetId } : {});
|
|
78
|
+
if (draft.original?.name === row.name && (draft.original.sheetId ?? '') === (row.sheetId ?? '')) draft = { ...EMPTY_DRAFT };
|
|
79
|
+
}
|
|
80
|
+
</script>
|
|
81
|
+
|
|
82
|
+
<!--
|
|
83
|
+
A simple Name Manager: lists defined names (name, current value, formula,
|
|
84
|
+
scope) and adds, edits, renames and deletes them. Renaming a name rewrites
|
|
85
|
+
the formulas that use it; deleting one leaves them showing #NAME?.
|
|
86
|
+
-->
|
|
87
|
+
<section aria-label="Name Manager" class="flex flex-col gap-2 text-xs {className}" data-name-manager="">
|
|
88
|
+
<div class="flex items-center justify-between">
|
|
89
|
+
<h3 class="m-0 text-sm font-semibold">Name Manager</h3>
|
|
90
|
+
{#if onClose}
|
|
91
|
+
<button type="button" aria-label="Close Name Manager" class="rounded px-2 hover:bg-muted" onclick={onClose}>×</button>
|
|
92
|
+
{/if}
|
|
93
|
+
</div>
|
|
94
|
+
<table class="w-full border-collapse">
|
|
95
|
+
<thead>
|
|
96
|
+
<tr class="text-left text-muted-foreground">
|
|
97
|
+
<th class="px-1 font-medium">Name</th>
|
|
98
|
+
<th class="px-1 font-medium">Value</th>
|
|
99
|
+
<th class="px-1 font-medium">Refers to</th>
|
|
100
|
+
<th class="px-1 font-medium">Scope</th>
|
|
101
|
+
{#if !readOnly}<th class="px-1"></th>{/if}
|
|
102
|
+
</tr>
|
|
103
|
+
</thead>
|
|
104
|
+
<tbody>
|
|
105
|
+
{#if rows.length === 0}
|
|
106
|
+
<tr><td colspan="5" class="px-1 py-2 text-muted-foreground">No names yet.</td></tr>
|
|
107
|
+
{/if}
|
|
108
|
+
{#each rows as row (`${row.sheetId ?? ''}!${row.name}`)}
|
|
109
|
+
<tr data-name={row.name} class="border-t border-border" title={row.comment}>
|
|
110
|
+
<td class="px-1 py-0.5 font-mono font-semibold">{row.name}</td>
|
|
111
|
+
<td class="px-1 py-0.5">{row.value}</td>
|
|
112
|
+
<td class="px-1 py-0.5 font-mono">{row.refersTo}</td>
|
|
113
|
+
<td class="px-1 py-0.5">{row.scopeLabel}</td>
|
|
114
|
+
{#if !readOnly}
|
|
115
|
+
<td class="whitespace-nowrap px-1 py-0.5 text-right">
|
|
116
|
+
<button type="button" aria-label="Edit {row.name}" class="rounded px-1 hover:bg-muted" onclick={() => edit(row)}>Edit</button>
|
|
117
|
+
<button type="button" aria-label="Delete {row.name}" class="rounded px-1 text-destructive hover:bg-muted" onclick={() => remove(row)}>
|
|
118
|
+
Delete
|
|
119
|
+
</button>
|
|
120
|
+
</td>
|
|
121
|
+
{/if}
|
|
122
|
+
</tr>
|
|
123
|
+
{/each}
|
|
124
|
+
</tbody>
|
|
125
|
+
</table>
|
|
126
|
+
{#if !readOnly}
|
|
127
|
+
<form
|
|
128
|
+
class="grid grid-cols-[auto_1fr] items-center gap-x-2 gap-y-1"
|
|
129
|
+
onsubmit={save}
|
|
130
|
+
aria-label={draft.original ? `Edit name ${draft.original.name}` : 'New name'}
|
|
131
|
+
>
|
|
132
|
+
<label for="pixerate-name-manager-name">Name</label>
|
|
133
|
+
<input id="pixerate-name-manager-name" class="rounded border border-border bg-background px-1 py-0.5" bind:value={draft.name} />
|
|
134
|
+
<label for="pixerate-name-manager-refers">Refers to</label>
|
|
135
|
+
<input id="pixerate-name-manager-refers" class="rounded border border-border bg-background px-1 py-0.5 font-mono" bind:value={draft.refersTo} />
|
|
136
|
+
<label for="pixerate-name-manager-scope">Scope</label>
|
|
137
|
+
<select id="pixerate-name-manager-scope" class="rounded border border-border bg-background px-1 py-0.5" bind:value={draft.scope}>
|
|
138
|
+
<option value="">Workbook</option>
|
|
139
|
+
{#each sheetState.sheets as sheet (sheet.id)}
|
|
140
|
+
<option value={sheet.id}>{sheet.name}</option>
|
|
141
|
+
{/each}
|
|
142
|
+
</select>
|
|
143
|
+
<label for="pixerate-name-manager-comment">Comment</label>
|
|
144
|
+
<input id="pixerate-name-manager-comment" class="rounded border border-border bg-background px-1 py-0.5" bind:value={draft.comment} />
|
|
145
|
+
<div class="col-span-2 flex gap-2">
|
|
146
|
+
<button type="submit" class="rounded bg-primary px-2 py-0.5 text-primary-foreground">{draft.original ? 'Save' : 'Add name'}</button>
|
|
147
|
+
{#if draft.original}
|
|
148
|
+
<button
|
|
149
|
+
type="button"
|
|
150
|
+
class="rounded px-2 py-0.5 hover:bg-muted"
|
|
151
|
+
onclick={() => {
|
|
152
|
+
draft = { ...EMPTY_DRAFT };
|
|
153
|
+
error = null;
|
|
154
|
+
}}
|
|
155
|
+
>
|
|
156
|
+
Cancel
|
|
157
|
+
</button>
|
|
158
|
+
{/if}
|
|
159
|
+
</div>
|
|
160
|
+
</form>
|
|
161
|
+
{/if}
|
|
162
|
+
{#if error}
|
|
163
|
+
<div role="alert" class="text-destructive">{error}</div>
|
|
164
|
+
{/if}
|
|
165
|
+
</section>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { createReactiveSpreadsheet } from './spreadsheet.svelte.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
sheetState: ReturnType<typeof createReactiveSpreadsheet>;
|
|
4
|
+
readOnly?: boolean;
|
|
5
|
+
onClose?: () => void;
|
|
6
|
+
class?: string;
|
|
7
|
+
}
|
|
8
|
+
declare const NameManager: import("svelte").Component<Props, {}, "">;
|
|
9
|
+
type NameManager = ReturnType<typeof NameManager>;
|
|
10
|
+
export default NameManager;
|
|
11
|
+
//# sourceMappingURL=NameManager.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NameManager.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/NameManager.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAGvE,UAAU,KAAK;IACb,UAAU,EAAE,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC;IACzD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAwJH,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
|