@pixerate/editor-svelte 0.18.0 → 0.19.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 +22 -1
- package/dist/EditableTextNodeEditor.svelte +19 -3
- package/dist/EditableTextNodeEditor.svelte.d.ts +5 -1
- package/dist/EditableTextNodeEditor.svelte.d.ts.map +1 -1
- package/dist/OutlinePanel.svelte +85 -0
- package/dist/OutlinePanel.svelte.d.ts +25 -0
- package/dist/OutlinePanel.svelte.d.ts.map +1 -0
- package/dist/TemplateRenderer.svelte +54 -7
- package/dist/TemplateRenderer.svelte.d.ts +8 -1
- package/dist/TemplateRenderer.svelte.d.ts.map +1 -1
- package/dist/VariableForm.svelte +86 -0
- package/dist/VariableForm.svelte.d.ts +21 -0
- package/dist/VariableForm.svelte.d.ts.map +1 -0
- package/dist/agentTools.svelte.d.ts +12 -0
- package/dist/agentTools.svelte.d.ts.map +1 -0
- package/dist/agentTools.svelte.js +17 -0
- package/dist/canvas/CanvasGuidesLayer.svelte +52 -0
- package/dist/canvas/CanvasGuidesLayer.svelte.d.ts +16 -0
- package/dist/canvas/CanvasGuidesLayer.svelte.d.ts.map +1 -0
- package/dist/canvas/createCanvasArrange.svelte.d.ts +63 -0
- package/dist/canvas/createCanvasArrange.svelte.d.ts.map +1 -0
- package/dist/canvas/createCanvasArrange.svelte.js +60 -0
- package/dist/canvas/createCanvasScenes.svelte.d.ts +51 -0
- package/dist/canvas/createCanvasScenes.svelte.d.ts.map +1 -0
- package/dist/canvas/createCanvasScenes.svelte.js +62 -0
- package/dist/canvas/index.d.ts +4 -0
- package/dist/canvas/index.d.ts.map +1 -1
- package/dist/canvas/index.js +5 -0
- package/dist/fileImport.svelte.d.ts +25 -0
- package/dist/fileImport.svelte.d.ts.map +1 -0
- package/dist/fileImport.svelte.js +40 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/outline.svelte.d.ts +18 -0
- package/dist/outline.svelte.d.ts.map +1 -0
- package/dist/outline.svelte.js +27 -0
- package/dist/review/CommentButton.svelte +32 -0
- package/dist/review/CommentButton.svelte.d.ts +10 -0
- package/dist/review/CommentButton.svelte.d.ts.map +1 -0
- package/dist/review/CommentsPanel.svelte +226 -0
- package/dist/review/CommentsPanel.svelte.d.ts +18 -0
- package/dist/review/CommentsPanel.svelte.d.ts.map +1 -0
- package/dist/review/ReviewToolbar.svelte +86 -0
- package/dist/review/ReviewToolbar.svelte.d.ts +9 -0
- package/dist/review/ReviewToolbar.svelte.d.ts.map +1 -0
- package/dist/review/index.d.ts +12 -0
- package/dist/review/index.d.ts.map +1 -0
- package/dist/review/index.js +4 -0
- package/dist/review/review.svelte.d.ts +40 -0
- package/dist/review/review.svelte.d.ts.map +1 -0
- package/dist/review/review.svelte.js +104 -0
- package/dist/spreadsheet/FormulaBar.svelte +13 -5
- package/dist/spreadsheet/FormulaBar.svelte.d.ts.map +1 -1
- package/dist/spreadsheet/FormulaHints.svelte +149 -0
- package/dist/spreadsheet/FormulaHints.svelte.d.ts +14 -0
- package/dist/spreadsheet/FormulaHints.svelte.d.ts.map +1 -0
- package/dist/spreadsheet/SpreadsheetContextMenu.svelte +60 -0
- package/dist/spreadsheet/SpreadsheetContextMenu.svelte.d.ts +11 -0
- package/dist/spreadsheet/SpreadsheetContextMenu.svelte.d.ts.map +1 -0
- package/dist/spreadsheet/SpreadsheetEditor.svelte +172 -19
- package/dist/spreadsheet/SpreadsheetEditor.svelte.d.ts.map +1 -1
- package/dist/spreadsheet/SpreadsheetGroupRow.svelte +55 -0
- package/dist/spreadsheet/SpreadsheetGroupRow.svelte.d.ts +14 -0
- package/dist/spreadsheet/SpreadsheetGroupRow.svelte.d.ts.map +1 -0
- package/dist/spreadsheet/index.d.ts +6 -0
- package/dist/spreadsheet/index.d.ts.map +1 -1
- package/dist/spreadsheet/index.js +4 -0
- package/dist/spreadsheet/spreadsheet.svelte.d.ts +42 -4
- package/dist/spreadsheet/spreadsheet.svelte.d.ts.map +1 -1
- package/dist/spreadsheet/spreadsheet.svelte.js +16 -2
- package/dist/spreadsheet/tableInteractions.d.ts +28 -0
- package/dist/spreadsheet/tableInteractions.d.ts.map +1 -0
- package/dist/spreadsheet/tableInteractions.js +61 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -35,6 +35,10 @@ Requires **Svelte 5** (the components use runes). Components ship as `.svelte` s
|
|
|
35
35
|
|
|
36
36
|
`content` sets the initial document. Read later changes from the bound `editor` (for example in `onUpdate`), as above. The editor is preloaded with `createRichTextPreset()`. Pass `markdown`, `image`, `uploadImage`, `extensions` or `richTextOptions` to configure it.
|
|
37
37
|
|
|
38
|
+
`fileImport` imports dropped/pasted `.md`, `.html`, `.txt` and `.rtf` files at the drop position, and `richClipboard` copies lossless slices between editors (both opt-in). `createFileImport(() => editor)` returns reactive `isImporting` / `error` plus `openFilePicker()` and `importFiles()` for an import button.
|
|
39
|
+
|
|
40
|
+
`useAgentToolProvider(registry, () => editor && createRichTextToolProvider(editor, { id: "doc" }))` registers an agent tool provider (see `ToolRegistry` in `@pixerate/editor/agent`) for the component's lifetime. Call it during component initialisation.
|
|
41
|
+
|
|
38
42
|
## Read-only token renderer
|
|
39
43
|
|
|
40
44
|
```svelte
|
|
@@ -46,11 +50,28 @@ Requires **Svelte 5** (the components use runes). Components ship as `.svelte` s
|
|
|
46
50
|
<TemplateRenderer content={"A photo of {subject} in {{golden_hour}}"} {templates} resolve />
|
|
47
51
|
```
|
|
48
52
|
|
|
53
|
+
## Comments and tracked changes
|
|
54
|
+
|
|
55
|
+
```svelte
|
|
56
|
+
<script lang="ts">
|
|
57
|
+
import { Comments, TrackChanges } from "@pixerate/editor";
|
|
58
|
+
import { EditableTextNodeEditor, CommentsPanel, ReviewToolbar } from "@pixerate/editor-svelte";
|
|
59
|
+
let editor = $state();
|
|
60
|
+
const extensions = [Comments.configure({ author: me }), TrackChanges.configure({ author: me })];
|
|
61
|
+
</script>
|
|
62
|
+
|
|
63
|
+
<ReviewToolbar {editor} />
|
|
64
|
+
<EditableTextNodeEditor bind:editor {extensions} />
|
|
65
|
+
<CommentsPanel {editor} />
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Put `<CommentButton {editor} />` inside a `BubbleMenu` to comment on the selection. `createComments(editorOrStore)` and `createTrackChanges(editor)` are rune (and Svelte store) adapters for custom UIs.
|
|
69
|
+
|
|
49
70
|
## More exports
|
|
50
71
|
|
|
51
72
|
| Import | Exports |
|
|
52
73
|
| :--- | :--- |
|
|
53
|
-
| `@pixerate/editor-svelte` | `EditableTextNodeEditor`, `BubbleMenu`, `TemplateRenderer`, `initiateEditor`, `createReactiveEditor`, `createHistory`, `createHistoryShortcuts`, `navigationGuard` (action), `createNavigationGuard`, `SpreadsheetEditor`, `FormulaBar`, `createReactiveSpreadsheet`, `DirtyTracker` |
|
|
74
|
+
| `@pixerate/editor-svelte` | `EditableTextNodeEditor`, `BubbleMenu`, `TemplateRenderer`, `initiateEditor`, `createReactiveEditor`, `createHistory`, `createHistoryShortcuts`, `navigationGuard` (action), `createNavigationGuard`, `SpreadsheetEditor`, `FormulaBar`, `FormulaHints`, `createReactiveSpreadsheet`, `DirtyTracker` |
|
|
54
75
|
| `@pixerate/editor-svelte/image-editor` | `ImageEditor`, `createReactiveImageEditor`: crop, rotate/flip, adjustments, annotations, depth masks, and `onInpaint` / `onRemoveBackground` AI hooks |
|
|
55
76
|
| `@pixerate/editor-svelte/canvas` | Runes for `@xyflow/svelte`: `createCanvasGraph`, `createCanvasClipboard`, `createCanvasDocking`, `createCanvasShortcuts`, `createCanvasInteractions`, `createCanvasExplosion`, `createCanvasNodeSync`, `createCanvasMultiDrag`, `createStreamingCanvas`, `AgentPresenceLayer`, `FloatingHorizontalScrollbar`, plus layout helpers |
|
|
56
77
|
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Editor, Content, Extensions, FocusPosition } from "@tiptap/core";
|
|
3
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
RichTextPresetOptions,
|
|
5
|
+
MarkdownOptions,
|
|
6
|
+
ImageOptions,
|
|
7
|
+
FileImportOptions,
|
|
8
|
+
RichClipboardOptions,
|
|
9
|
+
} from "@pixerate/editor";
|
|
4
10
|
import { onDestroy, onMount } from "svelte";
|
|
5
11
|
import { initiateEditor } from "./editor.svelte.js";
|
|
6
12
|
|
|
@@ -23,6 +29,10 @@
|
|
|
23
29
|
image?: ImageOptions | boolean;
|
|
24
30
|
uploadImage?: (file: File) => Promise<string> | string;
|
|
25
31
|
onUploadError?: (error: Error, file: File) => void;
|
|
32
|
+
/** Import .md, .html, .txt and .rtf files dropped or pasted into the editor (opt-in). */
|
|
33
|
+
fileImport?: FileImportOptions | boolean;
|
|
34
|
+
/** Copy/paste lossless ProseMirror slices between editors (opt-in). */
|
|
35
|
+
richClipboard?: RichClipboardOptions | boolean;
|
|
26
36
|
}
|
|
27
37
|
|
|
28
38
|
let {
|
|
@@ -44,6 +54,8 @@
|
|
|
44
54
|
image = undefined,
|
|
45
55
|
uploadImage = undefined,
|
|
46
56
|
onUploadError = undefined,
|
|
57
|
+
fileImport = undefined,
|
|
58
|
+
richClipboard = undefined,
|
|
47
59
|
}: EditorProps = $props();
|
|
48
60
|
|
|
49
61
|
let element = $state<HTMLElement>();
|
|
@@ -75,12 +87,16 @@
|
|
|
75
87
|
},
|
|
76
88
|
}
|
|
77
89
|
: {}),
|
|
90
|
+
...(fileImport !== undefined ? { fileImport } : {}),
|
|
91
|
+
...(richClipboard !== undefined ? { richClipboard } : {}),
|
|
78
92
|
...richTextOptions,
|
|
79
93
|
},
|
|
80
94
|
editable,
|
|
81
95
|
autofocus,
|
|
82
|
-
|
|
83
|
-
|
|
96
|
+
// TipTap registers these as event listeners; passing `undefined`
|
|
97
|
+
// overrides its no-op defaults and makes `emit` throw.
|
|
98
|
+
...(onCreate ? { onCreate } : {}),
|
|
99
|
+
...(onUpdate ? { onUpdate } : {}),
|
|
84
100
|
onFocus() {
|
|
85
101
|
if (onFocus) onFocus();
|
|
86
102
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Editor, Content, Extensions, FocusPosition } from "@tiptap/core";
|
|
2
|
-
import type { RichTextPresetOptions, MarkdownOptions, ImageOptions } from "@pixerate/editor";
|
|
2
|
+
import type { RichTextPresetOptions, MarkdownOptions, ImageOptions, FileImportOptions, RichClipboardOptions } from "@pixerate/editor";
|
|
3
3
|
interface EditorProps {
|
|
4
4
|
class?: string;
|
|
5
5
|
editorClass?: string;
|
|
@@ -19,6 +19,10 @@ interface EditorProps {
|
|
|
19
19
|
image?: ImageOptions | boolean;
|
|
20
20
|
uploadImage?: (file: File) => Promise<string> | string;
|
|
21
21
|
onUploadError?: (error: Error, file: File) => void;
|
|
22
|
+
/** Import .md, .html, .txt and .rtf files dropped or pasted into the editor (opt-in). */
|
|
23
|
+
fileImport?: FileImportOptions | boolean;
|
|
24
|
+
/** Copy/paste lossless ProseMirror slices between editors (opt-in). */
|
|
25
|
+
richClipboard?: RichClipboardOptions | boolean;
|
|
22
26
|
}
|
|
23
27
|
declare const EditableTextNodeEditor: import("svelte").Component<EditorProps, {}, "editor">;
|
|
24
28
|
type EditableTextNodeEditor = ReturnType<typeof EditableTextNodeEditor>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditableTextNodeEditor.svelte.d.ts","sourceRoot":"","sources":["../src/EditableTextNodeEditor.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC/E,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"EditableTextNodeEditor.svelte.d.ts","sourceRoot":"","sources":["../src/EditableTextNodeEditor.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC/E,OAAO,KAAK,EACR,qBAAqB,EACrB,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,oBAAoB,EACrB,MAAM,kBAAkB,CAAC;AAK1B,UAAU,WAAW;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,GAAG,eAAe,CAAC;IACrC,eAAe,CAAC,EAAE,qBAAqB,CAAC;IACxC,SAAS,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC;IACpC,KAAK,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC;IAC/B,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IACvD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IACnD,yFAAyF;IACzF,UAAU,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC;IACzC,uEAAuE;IACvE,aAAa,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC;CAChD;AAoGH,QAAA,MAAM,sBAAsB,uDAAwC,CAAC;AACrE,KAAK,sBAAsB,GAAG,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC;AACxE,eAAe,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Editor } from "@tiptap/core";
|
|
3
|
+
import type { Snippet } from "svelte";
|
|
4
|
+
import { navigateToHeading, type OutlineHeading } from "@pixerate/editor";
|
|
5
|
+
import { createOutline } from "./outline.svelte.js";
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
editor?: Editor | null;
|
|
9
|
+
/** Heading shown above the list. Pass `null` to hide it. */
|
|
10
|
+
title?: string | null;
|
|
11
|
+
/** Text shown when the document has no headings. */
|
|
12
|
+
emptyText?: string;
|
|
13
|
+
/** Deepest heading level listed. Defaults to 6. */
|
|
14
|
+
maxLevel?: number;
|
|
15
|
+
/** Whether clicking an entry focuses the editor. Defaults to `true`. */
|
|
16
|
+
focusOnNavigate?: boolean;
|
|
17
|
+
class?: string;
|
|
18
|
+
itemClass?: string;
|
|
19
|
+
activeItemClass?: string;
|
|
20
|
+
/** Called after navigating to a heading. */
|
|
21
|
+
onNavigate?: (heading: OutlineHeading) => void;
|
|
22
|
+
/** Custom empty state, rendered instead of `emptyText`. */
|
|
23
|
+
empty?: Snippet;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let {
|
|
27
|
+
editor = null,
|
|
28
|
+
title = "Outline",
|
|
29
|
+
emptyText = "Add headings to see the outline.",
|
|
30
|
+
maxLevel = 6,
|
|
31
|
+
focusOnNavigate = true,
|
|
32
|
+
class: className = "flex flex-col gap-1 text-sm",
|
|
33
|
+
itemClass = "w-full truncate rounded px-2 py-1 text-left hover:bg-black/5",
|
|
34
|
+
activeItemClass = "font-semibold bg-black/5",
|
|
35
|
+
onNavigate,
|
|
36
|
+
empty,
|
|
37
|
+
}: Props = $props();
|
|
38
|
+
|
|
39
|
+
let outline = $state.raw<ReturnType<typeof createOutline> | null>(null);
|
|
40
|
+
|
|
41
|
+
$effect(() => {
|
|
42
|
+
const instance = createOutline(editor);
|
|
43
|
+
outline = instance;
|
|
44
|
+
return () => instance.destroy();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const snapshot = $derived(outline?.current ?? { headings: [], tree: [], activeId: null });
|
|
48
|
+
const visible = $derived(snapshot.headings.filter((h) => h.level <= maxLevel));
|
|
49
|
+
|
|
50
|
+
function navigate(heading: OutlineHeading) {
|
|
51
|
+
if (!editor) return;
|
|
52
|
+
if (navigateToHeading(editor, heading, { focus: focusOnNavigate })) {
|
|
53
|
+
onNavigate?.(heading);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<nav class={className} aria-label="Document outline" data-outline-panel="">
|
|
59
|
+
{#if title != null}
|
|
60
|
+
<div class="pixerate-outline-title">{title}</div>
|
|
61
|
+
{/if}
|
|
62
|
+
{#if visible.length === 0}
|
|
63
|
+
<div class="pixerate-outline-empty">
|
|
64
|
+
{#if empty}{@render empty()}{:else}{emptyText}{/if}
|
|
65
|
+
</div>
|
|
66
|
+
{:else}
|
|
67
|
+
<ul role="list" style="list-style: none; margin: 0; padding: 0;">
|
|
68
|
+
{#each visible as heading (heading.id)}
|
|
69
|
+
{@const active = heading.id === snapshot.activeId}
|
|
70
|
+
<li data-level={heading.level}>
|
|
71
|
+
<button
|
|
72
|
+
type="button"
|
|
73
|
+
class={active ? `${itemClass} ${activeItemClass}` : itemClass}
|
|
74
|
+
style="padding-left: {0.5 + heading.depth * 0.75}rem"
|
|
75
|
+
aria-current={active ? "location" : undefined}
|
|
76
|
+
data-heading-id={heading.id}
|
|
77
|
+
onclick={() => navigate(heading)}
|
|
78
|
+
>
|
|
79
|
+
{heading.text || "Untitled"}
|
|
80
|
+
</button>
|
|
81
|
+
</li>
|
|
82
|
+
{/each}
|
|
83
|
+
</ul>
|
|
84
|
+
{/if}
|
|
85
|
+
</nav>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Editor } from "@tiptap/core";
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import { type OutlineHeading } from "@pixerate/editor";
|
|
4
|
+
interface Props {
|
|
5
|
+
editor?: Editor | null;
|
|
6
|
+
/** Heading shown above the list. Pass `null` to hide it. */
|
|
7
|
+
title?: string | null;
|
|
8
|
+
/** Text shown when the document has no headings. */
|
|
9
|
+
emptyText?: string;
|
|
10
|
+
/** Deepest heading level listed. Defaults to 6. */
|
|
11
|
+
maxLevel?: number;
|
|
12
|
+
/** Whether clicking an entry focuses the editor. Defaults to `true`. */
|
|
13
|
+
focusOnNavigate?: boolean;
|
|
14
|
+
class?: string;
|
|
15
|
+
itemClass?: string;
|
|
16
|
+
activeItemClass?: string;
|
|
17
|
+
/** Called after navigating to a heading. */
|
|
18
|
+
onNavigate?: (heading: OutlineHeading) => void;
|
|
19
|
+
/** Custom empty state, rendered instead of `emptyText`. */
|
|
20
|
+
empty?: Snippet;
|
|
21
|
+
}
|
|
22
|
+
declare const OutlinePanel: import("svelte").Component<Props, {}, "">;
|
|
23
|
+
type OutlinePanel = ReturnType<typeof OutlinePanel>;
|
|
24
|
+
export default OutlinePanel;
|
|
25
|
+
//# sourceMappingURL=OutlinePanel.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OutlinePanel.svelte.d.ts","sourceRoot":"","sources":["../src/OutlinePanel.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAIxE,UAAU,KAAK;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4CAA4C;IAC5C,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;IAC/C,2DAA2D;IAC3D,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAgEH,QAAA,MAAM,YAAY,2CAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import {
|
|
3
|
-
|
|
3
|
+
evaluatePromptTokens,
|
|
4
4
|
resolveTemplates,
|
|
5
5
|
type Template,
|
|
6
6
|
type ColorGradient,
|
|
7
|
+
type PromptValues,
|
|
7
8
|
} from "@pixerate/editor";
|
|
8
9
|
|
|
9
10
|
interface Props {
|
|
@@ -11,6 +12,13 @@
|
|
|
11
12
|
templates?: Template[];
|
|
12
13
|
templateColorMap?: Map<string, ColorGradient>;
|
|
13
14
|
resolve?: boolean;
|
|
15
|
+
/** Template version bindings used when `resolve` is set. */
|
|
16
|
+
bindings?: Record<string, string>;
|
|
17
|
+
/**
|
|
18
|
+
* Variable values. When set, variables show their value (or default),
|
|
19
|
+
* sections whose condition fails are hidden, and section tags are dropped.
|
|
20
|
+
*/
|
|
21
|
+
values?: PromptValues;
|
|
14
22
|
class?: string;
|
|
15
23
|
onTemplateClick?: (templateName: string) => void;
|
|
16
24
|
onVariableClick?: (variableName: string) => void;
|
|
@@ -21,18 +29,41 @@
|
|
|
21
29
|
templates = [],
|
|
22
30
|
templateColorMap,
|
|
23
31
|
resolve = false,
|
|
32
|
+
bindings,
|
|
33
|
+
values,
|
|
24
34
|
class: className = "font-mono text-sm leading-relaxed whitespace-pre-wrap break-words",
|
|
25
35
|
onTemplateClick,
|
|
26
36
|
onVariableClick,
|
|
27
37
|
}: Props = $props();
|
|
28
38
|
|
|
39
|
+
const CONDITIONAL_PREFIX = { if: "?", unless: "!", end: "/" } as const;
|
|
40
|
+
|
|
29
41
|
let displayText = $derived(
|
|
30
42
|
resolve && templates.length > 0
|
|
31
|
-
? resolveTemplates(content, templates)
|
|
43
|
+
? resolveTemplates(content, templates, { bindings })
|
|
32
44
|
: content
|
|
33
45
|
);
|
|
34
46
|
|
|
35
|
-
let tokens = $derived(
|
|
47
|
+
let tokens = $derived(evaluatePromptTokens(displayText, values));
|
|
48
|
+
|
|
49
|
+
function variableDetails(token: (typeof tokens)[number]): string {
|
|
50
|
+
return [
|
|
51
|
+
`Variable: ${token.value}`,
|
|
52
|
+
token.description,
|
|
53
|
+
token.defaultValue !== undefined
|
|
54
|
+
? `Default: ${token.defaultValue || "(empty)"}`
|
|
55
|
+
: undefined,
|
|
56
|
+
]
|
|
57
|
+
.filter(Boolean)
|
|
58
|
+
.join("\n");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function conditionalTitle(token: (typeof tokens)[number]): string {
|
|
62
|
+
if (token.conditional === "end") return `End of section: ${token.value}`;
|
|
63
|
+
return token.conditional === "if"
|
|
64
|
+
? `Shown when "${token.value}" has a value`
|
|
65
|
+
: `Shown when "${token.value}" is empty`;
|
|
66
|
+
}
|
|
36
67
|
</script>
|
|
37
68
|
|
|
38
69
|
<div class={className}>
|
|
@@ -48,15 +79,31 @@
|
|
|
48
79
|
>
|
|
49
80
|
{`{{${token.value}}}`}
|
|
50
81
|
</span>
|
|
82
|
+
{:else if token.type === "variable" && token.resolvedValue !== undefined}
|
|
83
|
+
<!-- svelte-ignore a11y_click_events_have_key_events, a11y_no_static_element_interactions -->
|
|
84
|
+
<span
|
|
85
|
+
onclick={() => onVariableClick?.(token.value)}
|
|
86
|
+
data-variable={token.value}
|
|
87
|
+
data-value-source={token.valueSource}
|
|
88
|
+
class={token.valueSource === "value"
|
|
89
|
+
? "inline px-1 mx-0.5 rounded-md bg-emerald-400/15 text-emerald-700 border-b border-emerald-400/60 cursor-pointer"
|
|
90
|
+
: "inline px-1 mx-0.5 rounded-md bg-violet-400/10 text-violet-600 italic border-b border-dashed border-violet-400/60 cursor-pointer"}
|
|
91
|
+
title={variableDetails(token)}
|
|
92
|
+
>{token.resolvedValue}</span>
|
|
51
93
|
{:else if token.type === "variable"}
|
|
52
94
|
<!-- svelte-ignore a11y_click_events_have_key_events, a11y_no_static_element_interactions -->
|
|
53
95
|
<span
|
|
54
96
|
onclick={() => onVariableClick?.(token.value)}
|
|
97
|
+
data-variable={token.value}
|
|
55
98
|
class="inline-flex items-center px-1.5 py-0.5 mx-0.5 text-xs font-medium rounded-md border border-violet-400/40 bg-violet-400/15 text-violet-600 hover:brightness-110 cursor-pointer transition-all"
|
|
56
|
-
title={
|
|
57
|
-
>
|
|
58
|
-
|
|
59
|
-
|
|
99
|
+
title={variableDetails(token)}
|
|
100
|
+
>{`{${token.value}`}{#if token.defaultValue !== undefined}<span class="opacity-60">{`|${token.defaultValue}`}</span>{/if}{"}"}</span>
|
|
101
|
+
{:else if token.type === "conditional" && token.conditional}
|
|
102
|
+
<span
|
|
103
|
+
data-conditional={token.conditional}
|
|
104
|
+
class="inline-flex items-center px-1 py-0.5 mx-0.5 text-xs font-medium rounded-md border border-amber-400/40 bg-amber-400/15 text-amber-700"
|
|
105
|
+
title={conditionalTitle(token)}
|
|
106
|
+
>{`{${CONDITIONAL_PREFIX[token.conditional]}${token.value}}`}</span>
|
|
60
107
|
{:else if token.type === "instruction"}
|
|
61
108
|
<span
|
|
62
109
|
class="inline-flex items-center px-1.5 py-0.5 mx-0.5 text-xs italic font-medium rounded-md border border-rose-400/40 bg-rose-400/15 text-rose-600"
|
|
@@ -1,9 +1,16 @@
|
|
|
1
|
-
import { type Template, type ColorGradient } from "@pixerate/editor";
|
|
1
|
+
import { type Template, type ColorGradient, type PromptValues } from "@pixerate/editor";
|
|
2
2
|
interface Props {
|
|
3
3
|
content: string;
|
|
4
4
|
templates?: Template[];
|
|
5
5
|
templateColorMap?: Map<string, ColorGradient>;
|
|
6
6
|
resolve?: boolean;
|
|
7
|
+
/** Template version bindings used when `resolve` is set. */
|
|
8
|
+
bindings?: Record<string, string>;
|
|
9
|
+
/**
|
|
10
|
+
* Variable values. When set, variables show their value (or default),
|
|
11
|
+
* sections whose condition fails are hidden, and section tags are dropped.
|
|
12
|
+
*/
|
|
13
|
+
values?: PromptValues;
|
|
7
14
|
class?: string;
|
|
8
15
|
onTemplateClick?: (templateName: string) => void;
|
|
9
16
|
onVariableClick?: (variableName: string) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TemplateRenderer.svelte.d.ts","sourceRoot":"","sources":["../src/TemplateRenderer.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EAGH,KAAK,QAAQ,EACb,KAAK,aAAa,
|
|
1
|
+
{"version":3,"file":"TemplateRenderer.svelte.d.ts","sourceRoot":"","sources":["../src/TemplateRenderer.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EAGH,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAG1B,UAAU,KAAK;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC9C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC;;;OAGG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,eAAe,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;CAClD;AA6EH,QAAA,MAAM,gBAAgB,2CAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Inputs are nested in their labels, which associates them without ids
|
|
3
|
+
(`$props.id()` needs Svelte 5.20, newer than our peer range).
|
|
4
|
+
-->
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import {
|
|
7
|
+
compactVariableValues,
|
|
8
|
+
getVariableFormFields,
|
|
9
|
+
type PromptValues,
|
|
10
|
+
type Template,
|
|
11
|
+
} from "@pixerate/editor";
|
|
12
|
+
|
|
13
|
+
interface Props {
|
|
14
|
+
/** Prompt whose variables become form fields. */
|
|
15
|
+
content: string;
|
|
16
|
+
/** Templates searched recursively for further variables. */
|
|
17
|
+
templates?: Template[];
|
|
18
|
+
/** Template version bindings. */
|
|
19
|
+
bindings?: Record<string, string>;
|
|
20
|
+
/** Entered text per variable. Bindable. */
|
|
21
|
+
values?: Record<string, string>;
|
|
22
|
+
/**
|
|
23
|
+
* Called on every edit with the values to resolve with (blank fields
|
|
24
|
+
* dropped so defaults apply) and the raw entered text.
|
|
25
|
+
*/
|
|
26
|
+
onChange?: (values: PromptValues, entered: Record<string, string>) => void;
|
|
27
|
+
class?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let {
|
|
31
|
+
content,
|
|
32
|
+
templates,
|
|
33
|
+
bindings,
|
|
34
|
+
values = $bindable({}),
|
|
35
|
+
onChange,
|
|
36
|
+
class: className = "flex flex-col gap-3 text-sm",
|
|
37
|
+
}: Props = $props();
|
|
38
|
+
|
|
39
|
+
let fields = $derived(getVariableFormFields(content, { templates, bindings }));
|
|
40
|
+
|
|
41
|
+
function update(name: string, value: string) {
|
|
42
|
+
const next = { ...values, [name]: value };
|
|
43
|
+
values = next;
|
|
44
|
+
onChange?.(compactVariableValues(next), next);
|
|
45
|
+
}
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
{#if fields.length > 0}
|
|
49
|
+
<form class={className} onsubmit={(event) => event.preventDefault()}>
|
|
50
|
+
{#each fields as field (field.name)}
|
|
51
|
+
{#if field.conditionOnly}
|
|
52
|
+
<label
|
|
53
|
+
class="flex items-center gap-2"
|
|
54
|
+
data-variable-field={field.name}
|
|
55
|
+
>
|
|
56
|
+
<input
|
|
57
|
+
name={field.name}
|
|
58
|
+
type="checkbox"
|
|
59
|
+
checked={(values[field.name] ?? "") !== ""}
|
|
60
|
+
onchange={(event) =>
|
|
61
|
+
update(field.name, event.currentTarget.checked ? "true" : "")}
|
|
62
|
+
/>
|
|
63
|
+
<span>{field.label}</span>
|
|
64
|
+
</label>
|
|
65
|
+
{:else}
|
|
66
|
+
<label
|
|
67
|
+
class="flex flex-col gap-1"
|
|
68
|
+
data-variable-field={field.name}
|
|
69
|
+
>
|
|
70
|
+
<span class="font-medium"
|
|
71
|
+
>{field.label}{#if field.required}<span class="text-rose-500" aria-hidden="true">{" *"}</span>{/if}</span
|
|
72
|
+
>
|
|
73
|
+
<input
|
|
74
|
+
name={field.name}
|
|
75
|
+
type="text"
|
|
76
|
+
value={values[field.name] ?? ""}
|
|
77
|
+
placeholder={field.placeholder}
|
|
78
|
+
aria-required={field.required || undefined}
|
|
79
|
+
oninput={(event) => update(field.name, event.currentTarget.value)}
|
|
80
|
+
class="px-2 py-1 rounded-md border border-violet-400/40 bg-transparent"
|
|
81
|
+
/>
|
|
82
|
+
</label>
|
|
83
|
+
{/if}
|
|
84
|
+
{/each}
|
|
85
|
+
</form>
|
|
86
|
+
{/if}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type PromptValues, type Template } from "@pixerate/editor";
|
|
2
|
+
interface Props {
|
|
3
|
+
/** Prompt whose variables become form fields. */
|
|
4
|
+
content: string;
|
|
5
|
+
/** Templates searched recursively for further variables. */
|
|
6
|
+
templates?: Template[];
|
|
7
|
+
/** Template version bindings. */
|
|
8
|
+
bindings?: Record<string, string>;
|
|
9
|
+
/** Entered text per variable. Bindable. */
|
|
10
|
+
values?: Record<string, string>;
|
|
11
|
+
/**
|
|
12
|
+
* Called on every edit with the values to resolve with (blank fields
|
|
13
|
+
* dropped so defaults apply) and the raw entered text.
|
|
14
|
+
*/
|
|
15
|
+
onChange?: (values: PromptValues, entered: Record<string, string>) => void;
|
|
16
|
+
class?: string;
|
|
17
|
+
}
|
|
18
|
+
declare const VariableForm: import("svelte").Component<Props, {}, "values">;
|
|
19
|
+
type VariableForm = ReturnType<typeof VariableForm>;
|
|
20
|
+
export default VariableForm;
|
|
21
|
+
//# sourceMappingURL=VariableForm.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VariableForm.svelte.d.ts","sourceRoot":"","sources":["../src/VariableForm.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EAGH,KAAK,YAAY,EACjB,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAC;AAG1B,UAAU,KAAK;IACb,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,iCAAiC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA6CH,QAAA,MAAM,YAAY,iDAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AgentToolProvider, ToolRegistry } from "@pixerate/editor/agent";
|
|
2
|
+
type MaybeGetter<T> = T | (() => T);
|
|
3
|
+
/**
|
|
4
|
+
* Registers a tool provider with a `ToolRegistry` for the lifetime of the
|
|
5
|
+
* calling component (call it during component initialisation) and
|
|
6
|
+
* unregisters it on destroy. Pass getters to react to changes, e.g.
|
|
7
|
+
* `useAgentToolProvider(registry, () => editor && createRichTextToolProvider(editor, { id }))`:
|
|
8
|
+
* when the getter returns a different provider, the old one is unregistered.
|
|
9
|
+
*/
|
|
10
|
+
export declare function useAgentToolProvider(registry: MaybeGetter<ToolRegistry | null | undefined>, provider: MaybeGetter<AgentToolProvider | null | undefined>): void;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=agentTools.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentTools.svelte.d.ts","sourceRoot":"","sources":["../src/agentTools.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE9E,KAAK,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AAKpC;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,WAAW,CAAC,YAAY,GAAG,IAAI,GAAG,SAAS,CAAC,EACtD,QAAQ,EAAE,WAAW,CAAC,iBAAiB,GAAG,IAAI,GAAG,SAAS,CAAC,GAC1D,IAAI,CAON"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const read = (value) => typeof value === "function" ? value() : value;
|
|
2
|
+
/**
|
|
3
|
+
* Registers a tool provider with a `ToolRegistry` for the lifetime of the
|
|
4
|
+
* calling component (call it during component initialisation) and
|
|
5
|
+
* unregisters it on destroy. Pass getters to react to changes, e.g.
|
|
6
|
+
* `useAgentToolProvider(registry, () => editor && createRichTextToolProvider(editor, { id }))`:
|
|
7
|
+
* when the getter returns a different provider, the old one is unregistered.
|
|
8
|
+
*/
|
|
9
|
+
export function useAgentToolProvider(registry, provider) {
|
|
10
|
+
$effect(() => {
|
|
11
|
+
const currentRegistry = read(registry);
|
|
12
|
+
const currentProvider = read(provider);
|
|
13
|
+
if (!currentRegistry || !currentProvider)
|
|
14
|
+
return;
|
|
15
|
+
return currentRegistry.register(currentProvider);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { CanvasViewport, GuideLine } from '@pixerate/editor/canvas';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
/** Guide segments in flow coordinates (e.g. `arrange.guides`). */
|
|
6
|
+
guides: GuideLine[];
|
|
7
|
+
/** Current viewport (`useSvelteFlow().getViewport()` or the `viewport` binding). */
|
|
8
|
+
viewport?: CanvasViewport;
|
|
9
|
+
/** Colour of edge and centre guides. */
|
|
10
|
+
color?: string;
|
|
11
|
+
/** Colour of equal-spacing guides. */
|
|
12
|
+
spacingColor?: string;
|
|
13
|
+
class?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let {
|
|
17
|
+
guides = [],
|
|
18
|
+
viewport = { x: 0, y: 0, zoom: 1 },
|
|
19
|
+
color = '#f59e0b',
|
|
20
|
+
spacingColor = '#ec4899',
|
|
21
|
+
class: className = ''
|
|
22
|
+
}: Props = $props();
|
|
23
|
+
|
|
24
|
+
const toScreen = (x: number, y: number) => ({
|
|
25
|
+
x: x * viewport.zoom + viewport.x,
|
|
26
|
+
y: y * viewport.zoom + viewport.y
|
|
27
|
+
});
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
{#if guides.length > 0}
|
|
31
|
+
<svg
|
|
32
|
+
class="pixerate-canvas-guides {className}"
|
|
33
|
+
style="position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; z-index: 10;"
|
|
34
|
+
aria-hidden="true"
|
|
35
|
+
>
|
|
36
|
+
{#each guides as guide, i (i)}
|
|
37
|
+
{@const a = toScreen(guide.x1, guide.y1)}
|
|
38
|
+
{@const b = toScreen(guide.x2, guide.y2)}
|
|
39
|
+
<line
|
|
40
|
+
data-kind={guide.kind}
|
|
41
|
+
x1={a.x}
|
|
42
|
+
y1={a.y}
|
|
43
|
+
x2={b.x}
|
|
44
|
+
y2={b.y}
|
|
45
|
+
stroke={guide.kind === 'spacing' ? spacingColor : color}
|
|
46
|
+
stroke-width="1"
|
|
47
|
+
stroke-dasharray={guide.kind === 'centre' ? '4 3' : undefined}
|
|
48
|
+
shape-rendering="crispEdges"
|
|
49
|
+
/>
|
|
50
|
+
{/each}
|
|
51
|
+
</svg>
|
|
52
|
+
{/if}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { CanvasViewport, GuideLine } from '@pixerate/editor/canvas';
|
|
2
|
+
interface Props {
|
|
3
|
+
/** Guide segments in flow coordinates (e.g. `arrange.guides`). */
|
|
4
|
+
guides: GuideLine[];
|
|
5
|
+
/** Current viewport (`useSvelteFlow().getViewport()` or the `viewport` binding). */
|
|
6
|
+
viewport?: CanvasViewport;
|
|
7
|
+
/** Colour of edge and centre guides. */
|
|
8
|
+
color?: string;
|
|
9
|
+
/** Colour of equal-spacing guides. */
|
|
10
|
+
spacingColor?: string;
|
|
11
|
+
class?: string;
|
|
12
|
+
}
|
|
13
|
+
declare const CanvasGuidesLayer: import("svelte").Component<Props, {}, "">;
|
|
14
|
+
type CanvasGuidesLayer = ReturnType<typeof CanvasGuidesLayer>;
|
|
15
|
+
export default CanvasGuidesLayer;
|
|
16
|
+
//# sourceMappingURL=CanvasGuidesLayer.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CanvasGuidesLayer.svelte.d.ts","sourceRoot":"","sources":["../../src/canvas/CanvasGuidesLayer.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGxE,UAAU,KAAK;IACd,kEAAkE;IAClE,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,oFAAoF;IACpF,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AA+BF,QAAA,MAAM,iBAAiB,2CAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type ArrangeShortcutBinding, type CanvasArrangeAction, type CanvasArrangeControllerOptions, type GuideLine } from '@pixerate/editor/canvas';
|
|
2
|
+
import type { CanvasNode } from './types.js';
|
|
3
|
+
type CoreOptions = CanvasArrangeControllerOptions<any>;
|
|
4
|
+
export interface CreateCanvasArrangeOptions<TNode extends CanvasNode = CanvasNode> extends Omit<CoreOptions, 'getNodes' | 'setNodes' | 'onGuidesChange'> {
|
|
5
|
+
getNodes: () => TNode[];
|
|
6
|
+
setNodes: (nodes: TNode[]) => void;
|
|
7
|
+
onGuidesChange?: (guides: GuideLine[]) => void;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Headless Svelte 5 rune for Freeform-style arrangement: align, distribute, make same size,
|
|
11
|
+
* lock / unlock, layer order and smart guides with snap-to-shape while dragging.
|
|
12
|
+
*
|
|
13
|
+
* Actions act on `getSelectedIds()` (default: selected nodes) when called without ids and
|
|
14
|
+
* are recorded as single undoable steps when a `HistoryManager` is passed as `history`.
|
|
15
|
+
*
|
|
16
|
+
* Wire snapping to SvelteFlow with `onnodedragstart={() => arrange.beginDrag()}`,
|
|
17
|
+
* `onnodedrag={({ nodes }) => arrange.drag(nodes.map((n) => n.id))}` and
|
|
18
|
+
* `onnodedragstop={() => arrange.endDrag()}`, and render `arrange.guides` with
|
|
19
|
+
* `<CanvasGuidesLayer>`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function createCanvasArrange<TNode extends CanvasNode = CanvasNode>(options: CreateCanvasArrangeOptions<TNode>): {
|
|
22
|
+
guides: GuideLine[];
|
|
23
|
+
apply: (name: string, updates: import("@pixerate/editor/canvas").CanvasNodeUpdate[]) => import("@pixerate/editor/canvas").CanvasNodeUpdate[];
|
|
24
|
+
align(edge: import("@pixerate/editor/canvas").AlignEdge, ids?: Iterable<string>, alignOptions?: import("@pixerate/editor/canvas").AlignNodesOptions): import("@pixerate/editor/canvas").CanvasNodeUpdate[];
|
|
25
|
+
distribute(axis: import("@pixerate/editor/canvas").DistributeAxis, mode?: import("@pixerate/editor/canvas").DistributeMode, ids?: Iterable<string>, distributeOptions?: import("@pixerate/editor/canvas").DistributeNodesOptions): import("@pixerate/editor/canvas").CanvasNodeUpdate[];
|
|
26
|
+
matchSize(dimension: import("@pixerate/editor/canvas").SizeDimension, ids?: Iterable<string>, sizeOptions?: import("@pixerate/editor/canvas").MatchSizeOptions): import("@pixerate/editor/canvas").CanvasNodeUpdate[];
|
|
27
|
+
reorder(operation: import("@pixerate/editor/canvas").ZOrderOperation, ids?: Iterable<string>): import("@pixerate/editor/canvas").CanvasNodeUpdate[];
|
|
28
|
+
bringForward: (ids?: Iterable<string>) => import("@pixerate/editor/canvas").CanvasNodeUpdate[];
|
|
29
|
+
sendBackward: (ids?: Iterable<string>) => import("@pixerate/editor/canvas").CanvasNodeUpdate[];
|
|
30
|
+
bringToFront: (ids?: Iterable<string>) => import("@pixerate/editor/canvas").CanvasNodeUpdate[];
|
|
31
|
+
sendToBack: (ids?: Iterable<string>) => import("@pixerate/editor/canvas").CanvasNodeUpdate[];
|
|
32
|
+
lock: (ids?: Iterable<string>) => string[];
|
|
33
|
+
unlock: (ids?: Iterable<string>) => string[];
|
|
34
|
+
toggleLock(ids?: Iterable<string>): string[];
|
|
35
|
+
isLocked: (id: string) => boolean;
|
|
36
|
+
runAction(action: CanvasArrangeAction): boolean;
|
|
37
|
+
beginDrag(ids?: Iterable<string>): void;
|
|
38
|
+
drag(ids?: Iterable<string>): import("@pixerate/editor/canvas").SnapNodeDragResult | null;
|
|
39
|
+
snapPositionChanges<TChange extends import("@pixerate/editor/canvas").PositionChangeLike>(changes: TChange[]): TChange[];
|
|
40
|
+
endDrag(): void;
|
|
41
|
+
};
|
|
42
|
+
export type CanvasArrange<TNode extends CanvasNode = CanvasNode> = ReturnType<typeof createCanvasArrange<TNode>>;
|
|
43
|
+
export interface CanvasArrangeShortcutsOptions {
|
|
44
|
+
arrange: {
|
|
45
|
+
runAction: (action: CanvasArrangeAction) => boolean;
|
|
46
|
+
};
|
|
47
|
+
/** Scenes controller for PageDown / PageUp (next / previous scene). */
|
|
48
|
+
scenes?: {
|
|
49
|
+
next: () => unknown;
|
|
50
|
+
previous: () => unknown;
|
|
51
|
+
};
|
|
52
|
+
targetElement?: HTMLElement | Window;
|
|
53
|
+
bindings?: readonly ArrangeShortcutBinding[];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Attaches the arrange keyboard shortcuts (see `DEFAULT_ARRANGE_SHORTCUTS`). Shortcuts are
|
|
57
|
+
* ignored while typing in inputs, textareas, contenteditable or ProseMirror editors.
|
|
58
|
+
*
|
|
59
|
+
* @returns A cleanup function removing the listener.
|
|
60
|
+
*/
|
|
61
|
+
export declare function createCanvasArrangeShortcuts(options: CanvasArrangeShortcutsOptions): () => void;
|
|
62
|
+
export {};
|
|
63
|
+
//# sourceMappingURL=createCanvasArrange.svelte.d.ts.map
|