@pixerate/editor-svelte 0.21.0 → 0.22.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 +2 -1
- package/dist/canvas/CanvasGuidesLayer.svelte +32 -2
- package/dist/canvas/CanvasGuidesLayer.svelte.d.ts +2 -0
- package/dist/canvas/CanvasGuidesLayer.svelte.d.ts.map +1 -1
- package/dist/canvas/createCanvasArrange.svelte.d.ts +16 -1
- package/dist/canvas/createCanvasArrange.svelte.d.ts.map +1 -1
- package/dist/canvas/createCanvasArrange.svelte.js +19 -2
- package/dist/canvas/createCanvasMeasure.svelte.d.ts +53 -0
- package/dist/canvas/createCanvasMeasure.svelte.d.ts.map +1 -0
- package/dist/canvas/createCanvasMeasure.svelte.js +80 -0
- package/dist/canvas/index.d.ts +2 -0
- package/dist/canvas/index.d.ts.map +1 -1
- package/dist/canvas/index.js +3 -0
- package/dist/commands/CommandPalette.svelte +129 -0
- package/dist/commands/CommandPalette.svelte.d.ts +13 -0
- package/dist/commands/CommandPalette.svelte.d.ts.map +1 -0
- package/dist/commands/commandShortcuts.svelte.d.ts +30 -0
- package/dist/commands/commandShortcuts.svelte.d.ts.map +1 -0
- package/dist/commands/commandShortcuts.svelte.js +37 -0
- package/dist/commands/index.d.ts +7 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +3 -0
- package/dist/commands/palette.svelte.d.ts +34 -0
- package/dist/commands/palette.svelte.d.ts.map +1 -0
- package/dist/commands/palette.svelte.js +61 -0
- package/dist/history/createHistoryShortcuts.d.ts +1 -1
- package/dist/history/createHistoryShortcuts.d.ts.map +1 -1
- package/dist/history/createHistoryShortcuts.js +10 -32
- package/dist/history/history.svelte.d.ts +13 -4
- package/dist/history/history.svelte.d.ts.map +1 -1
- package/dist/history/history.svelte.js +10 -0
- package/dist/history/historyDirty.svelte.d.ts +31 -0
- package/dist/history/historyDirty.svelte.d.ts.map +1 -0
- package/dist/history/historyDirty.svelte.js +30 -0
- package/dist/history/index.d.ts +1 -0
- package/dist/history/index.d.ts.map +1 -1
- package/dist/history/index.js +1 -0
- package/dist/image-editor/ImageEditor.svelte +39 -0
- package/dist/image-editor/ImageEditor.svelte.d.ts.map +1 -1
- package/dist/image-editor/imageEditorState.svelte.d.ts +2 -0
- package/dist/image-editor/imageEditorState.svelte.d.ts.map +1 -1
- package/dist/image-editor/imageEditorState.svelte.js +4 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/spreadsheet/SpreadsheetEditor.svelte +3 -2
- package/dist/spreadsheet/SpreadsheetEditor.svelte.d.ts.map +1 -1
- package/dist/spreadsheet/spreadsheet.svelte.d.ts.map +1 -1
- package/package.json +10 -2
package/README.md
CHANGED
|
@@ -73,9 +73,10 @@ Requires **Svelte 5** (the components use runes). Components ship as `.svelte` s
|
|
|
73
73
|
|
|
74
74
|
| Import | Exports |
|
|
75
75
|
| :--- | :--- |
|
|
76
|
-
| `@pixerate/editor-svelte` | `EditableTextNodeEditor`, `BubbleMenu`, `TemplateRenderer`, `initiateEditor`, `createReactiveEditor`, `createHistory`, `createHistoryShortcuts`, `navigationGuard` (action), `createNavigationGuard`, `SpreadsheetEditor`, `FormulaBar`, `FormulaHints`, `createReactiveSpreadsheet`, `DirtyTracker` |
|
|
76
|
+
| `@pixerate/editor-svelte` | `EditableTextNodeEditor`, `BubbleMenu`, `TemplateRenderer`, `initiateEditor`, `createReactiveEditor`, `createHistory`, `createHistoryDirty`, `createHistoryShortcuts`, `navigationGuard` (action), `createNavigationGuard`, `SpreadsheetEditor`, `FormulaBar`, `FormulaHints`, `createReactiveSpreadsheet`, `DirtyTracker` |
|
|
77
77
|
| `@pixerate/editor-svelte/spreadsheet` | `SpreadsheetEditor`, `FormulaBar`, `FormulaHints`, `SpreadsheetContextMenu`, `SpreadsheetGroupRow`, `createReactiveSpreadsheet` (also re-exported from the root entry) |
|
|
78
78
|
| `@pixerate/editor-svelte/image-editor` | `ImageEditor`, `createReactiveImageEditor`: crop, rotate/flip, adjustments, annotations, depth masks, and `onInpaint` / `onRemoveBackground` AI hooks |
|
|
79
|
+
| `@pixerate/editor-svelte/commands` | `CommandPalette`, `createCommandPalette` (`hotkey: "Mod+K"`; call `destroy()` when done), `createCommandShortcuts`, `useRegisterCommands` over a `CommandRegistry` from `@pixerate/editor/commands` (also re-exported from the root entry) |
|
|
79
80
|
| `@pixerate/editor-svelte/canvas` | Runes for `@xyflow/svelte`: `createCanvasGraph`, `createCanvasClipboard`, `createCanvasDocking`, `createCanvasShortcuts`, `createCanvasInteractions`, `createCanvasExplosion`, `createCanvasNodeSync`, `createCanvasMultiDrag`, `createStreamingCanvas`, `AgentPresenceLayer`, `FloatingHorizontalScrollbar`, plus layout helpers |
|
|
80
81
|
|
|
81
82
|
Prop types are exported alongside each component, for example `EditableTextNodeEditorProps`, `BubbleMenuProps`, `ImageEditorProps` and `SpreadsheetEditorProps`.
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
color?: string;
|
|
11
11
|
/** Colour of equal-spacing guides. */
|
|
12
12
|
spacingColor?: string;
|
|
13
|
+
/** Colour of measuring lines, their labels and extension lines. */
|
|
14
|
+
measureColor?: string;
|
|
13
15
|
class?: string;
|
|
14
16
|
}
|
|
15
17
|
|
|
@@ -18,6 +20,7 @@
|
|
|
18
20
|
viewport = { x: 0, y: 0, zoom: 1 },
|
|
19
21
|
color = '#f59e0b',
|
|
20
22
|
spacingColor = '#ec4899',
|
|
23
|
+
measureColor = '#ef4444',
|
|
21
24
|
class: className = ''
|
|
22
25
|
}: Props = $props();
|
|
23
26
|
|
|
@@ -42,11 +45,38 @@
|
|
|
42
45
|
y1={a.y}
|
|
43
46
|
x2={b.x}
|
|
44
47
|
y2={b.y}
|
|
45
|
-
stroke={guide.kind === '
|
|
48
|
+
stroke={guide.kind === 'measure' || guide.kind === 'extension'
|
|
49
|
+
? measureColor
|
|
50
|
+
: guide.kind === 'spacing'
|
|
51
|
+
? spacingColor
|
|
52
|
+
: color}
|
|
46
53
|
stroke-width="1"
|
|
47
|
-
stroke-dasharray={guide.kind === 'centre' ? '4 3' : undefined}
|
|
54
|
+
stroke-dasharray={guide.kind === 'centre' ? '4 3' : guide.kind === 'extension' ? '3 3' : undefined}
|
|
48
55
|
shape-rendering="crispEdges"
|
|
49
56
|
/>
|
|
50
57
|
{/each}
|
|
58
|
+
{#each guides as guide, i (i)}
|
|
59
|
+
{#if guide.label}
|
|
60
|
+
{@const mid = toScreen((guide.x1 + guide.x2) / 2, (guide.y1 + guide.y2) / 2)}
|
|
61
|
+
{@const vertical = guide.orientation === 'vertical'}
|
|
62
|
+
{@const width = guide.label.length * 6.5 + 8}
|
|
63
|
+
<!-- Labels sit beside vertical lines and below horizontal ones. -->
|
|
64
|
+
<g
|
|
65
|
+
class="pixerate-canvas-guides__label"
|
|
66
|
+
data-label={guide.label}
|
|
67
|
+
transform="translate({vertical ? mid.x + 4 : mid.x - width / 2} {vertical ? mid.y - 8 : mid.y + 4})"
|
|
68
|
+
>
|
|
69
|
+
<rect {width} height="16" rx="3" fill={measureColor} />
|
|
70
|
+
<text
|
|
71
|
+
x={width / 2}
|
|
72
|
+
y="11.5"
|
|
73
|
+
text-anchor="middle"
|
|
74
|
+
font-size="11"
|
|
75
|
+
font-family="system-ui, sans-serif"
|
|
76
|
+
fill="#fff">{guide.label}</text
|
|
77
|
+
>
|
|
78
|
+
</g>
|
|
79
|
+
{/if}
|
|
80
|
+
{/each}
|
|
51
81
|
</svg>
|
|
52
82
|
{/if}
|
|
@@ -8,6 +8,8 @@ interface Props {
|
|
|
8
8
|
color?: string;
|
|
9
9
|
/** Colour of equal-spacing guides. */
|
|
10
10
|
spacingColor?: string;
|
|
11
|
+
/** Colour of measuring lines, their labels and extension lines. */
|
|
12
|
+
measureColor?: string;
|
|
11
13
|
class?: string;
|
|
12
14
|
}
|
|
13
15
|
declare const CanvasGuidesLayer: import("svelte").Component<Props, {}, "">;
|
|
@@ -1 +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;
|
|
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,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAgDF,QAAA,MAAM,iBAAiB,2CAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
|
|
@@ -16,10 +16,21 @@ export interface CreateCanvasArrangeOptions<TNode extends CanvasNode = CanvasNod
|
|
|
16
16
|
* Wire snapping to SvelteFlow with `onnodedragstart={() => arrange.beginDrag()}`,
|
|
17
17
|
* `onnodedrag={({ nodes }) => arrange.drag(nodes.map((n) => n.id))}` and
|
|
18
18
|
* `onnodedragstop={() => arrange.endDrag()}`, and render `arrange.guides` with
|
|
19
|
-
* `<CanvasGuidesLayer>`.
|
|
19
|
+
* `<CanvasGuidesLayer>`. Snap resizes with `<NodeResizer {...arrange.resizerHandlers(id)} />`.
|
|
20
20
|
*/
|
|
21
21
|
export declare function createCanvasArrange<TNode extends CanvasNode = CanvasNode>(options: CreateCanvasArrangeOptions<TNode>): {
|
|
22
22
|
guides: GuideLine[];
|
|
23
|
+
/**
|
|
24
|
+
* Resize snapping for SvelteFlow's `<NodeResizer>` / `<NodeResizeControl>`:
|
|
25
|
+
* `<NodeResizer {...arrange.resizerHandlers(id)} />`. The resizer writes the raw size
|
|
26
|
+
* to the nodes after `onResize`, so snapping runs a microtask later and writes the
|
|
27
|
+
* snapped box back. Locked nodes snap back to their starting box.
|
|
28
|
+
*/
|
|
29
|
+
resizerHandlers(id: string): {
|
|
30
|
+
onResizeStart: () => void;
|
|
31
|
+
onResize: () => void;
|
|
32
|
+
onResizeEnd: () => void;
|
|
33
|
+
};
|
|
23
34
|
apply: (name: string, updates: import("@pixerate/editor/canvas").CanvasNodeUpdate[]) => import("@pixerate/editor/canvas").CanvasNodeUpdate[];
|
|
24
35
|
align(edge: import("@pixerate/editor/canvas").AlignEdge, ids?: Iterable<string>, alignOptions?: import("@pixerate/editor/canvas").AlignNodesOptions): import("@pixerate/editor/canvas").CanvasNodeUpdate[];
|
|
25
36
|
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[];
|
|
@@ -44,6 +55,10 @@ export declare function createCanvasArrange<TNode extends CanvasNode = CanvasNod
|
|
|
44
55
|
beginDrag(ids?: Iterable<string>): void;
|
|
45
56
|
drag(ids?: Iterable<string>): import("@pixerate/editor/canvas").SnapNodeDragResult | null;
|
|
46
57
|
snapPositionChanges<TChange extends import("@pixerate/editor/canvas").PositionChangeLike>(changes: TChange[]): TChange[];
|
|
58
|
+
beginResize(id: string): void;
|
|
59
|
+
resize(id: string, handle?: import("@pixerate/editor/canvas").ResizeHandle): import("@pixerate/editor/canvas").SnapNodeResizeResult | null;
|
|
60
|
+
endResize(): void;
|
|
61
|
+
snapResizeChanges<TChange extends import("@pixerate/editor/canvas").PositionChangeLike>(changes: TChange[]): TChange[];
|
|
47
62
|
endDrag(): void;
|
|
48
63
|
};
|
|
49
64
|
export type CanvasArrange<TNode extends CanvasNode = CanvasNode> = ReturnType<typeof createCanvasArrange<TNode>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createCanvasArrange.svelte.d.ts","sourceRoot":"","sources":["../../src/canvas/createCanvasArrange.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,8BAA8B,EACnC,KAAK,SAAS,EACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,KAAK,WAAW,GAAG,8BAA8B,CAAC,GAAG,CAAC,CAAC;AAEvD,MAAM,WAAW,0BAA0B,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,CAChF,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,UAAU,GAAG,gBAAgB,CAAC;IACrE,QAAQ,EAAE,MAAM,KAAK,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;CAC/C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,EACxE,OAAO,EAAE,0BAA0B,CAAC,KAAK,CAAC
|
|
1
|
+
{"version":3,"file":"createCanvasArrange.svelte.d.ts","sourceRoot":"","sources":["../../src/canvas/createCanvasArrange.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,8BAA8B,EACnC,KAAK,SAAS,EACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,KAAK,WAAW,GAAG,8BAA8B,CAAC,GAAG,CAAC,CAAC;AAEvD,MAAM,WAAW,0BAA0B,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,CAChF,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,UAAU,GAAG,gBAAgB,CAAC;IACrE,QAAQ,EAAE,MAAM,KAAK,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;CAC/C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,EACxE,OAAO,EAAE,0BAA0B,CAAC,KAAK,CAAC;;IAkBzC;;;;;OAKG;wBACiB,MAAM;;;;;;;;;;sBAoD+j/C,CAAC;sBAAiE,CAAC;sBAAiE,CAAC;oBAA+D,CAAC;cAAyD,CAAC;gBAAiD,CAAC;;;;;;;;;0BAA8tC,CAAC;;;;;;;;;;EAxC1miD;AAED,MAAM,MAAM,aAAa,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,IAAI,UAAU,CAAC,OAAO,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;AAEjH,MAAM,WAAW,6BAA6B;IAC7C,OAAO,EAAE;QAAE,SAAS,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,OAAO,CAAA;KAAE,CAAC;IACjE,uEAAuE;IACvE,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,OAAO,CAAA;KAAE,CAAC;IAC1D,aAAa,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IACrC,QAAQ,CAAC,EAAE,SAAS,sBAAsB,EAAE,CAAC;CAC7C;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,6BAA6B,GAAG,MAAM,IAAI,CAqB/F"}
|
|
@@ -9,7 +9,7 @@ import { createCanvasArrangeController, matchArrangeShortcut } from '@pixerate/e
|
|
|
9
9
|
* Wire snapping to SvelteFlow with `onnodedragstart={() => arrange.beginDrag()}`,
|
|
10
10
|
* `onnodedrag={({ nodes }) => arrange.drag(nodes.map((n) => n.id))}` and
|
|
11
11
|
* `onnodedragstop={() => arrange.endDrag()}`, and render `arrange.guides` with
|
|
12
|
-
* `<CanvasGuidesLayer>`.
|
|
12
|
+
* `<CanvasGuidesLayer>`. Snap resizes with `<NodeResizer {...arrange.resizerHandlers(id)} />`.
|
|
13
13
|
*/
|
|
14
14
|
export function createCanvasArrange(options) {
|
|
15
15
|
let guides = $state.raw([]);
|
|
@@ -22,9 +22,26 @@ export function createCanvasArrange(options) {
|
|
|
22
22
|
});
|
|
23
23
|
return {
|
|
24
24
|
...controller,
|
|
25
|
-
/** Guide segments (flow coordinates) for the active drag; empty otherwise. */
|
|
25
|
+
/** Guide segments (flow coordinates) for the active drag or resize; empty otherwise. */
|
|
26
26
|
get guides() {
|
|
27
27
|
return guides;
|
|
28
|
+
},
|
|
29
|
+
/**
|
|
30
|
+
* Resize snapping for SvelteFlow's `<NodeResizer>` / `<NodeResizeControl>`:
|
|
31
|
+
* `<NodeResizer {...arrange.resizerHandlers(id)} />`. The resizer writes the raw size
|
|
32
|
+
* to the nodes after `onResize`, so snapping runs a microtask later and writes the
|
|
33
|
+
* snapped box back. Locked nodes snap back to their starting box.
|
|
34
|
+
*/
|
|
35
|
+
resizerHandlers(id) {
|
|
36
|
+
return {
|
|
37
|
+
onResizeStart: () => controller.beginResize(id),
|
|
38
|
+
onResize: () => {
|
|
39
|
+
queueMicrotask(() => controller.resize(id));
|
|
40
|
+
},
|
|
41
|
+
onResizeEnd: () => {
|
|
42
|
+
queueMicrotask(() => controller.endResize());
|
|
43
|
+
}
|
|
44
|
+
};
|
|
28
45
|
}
|
|
29
46
|
};
|
|
30
47
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type NodeRectOptions } from '@pixerate/editor/canvas';
|
|
2
|
+
import type { CanvasNode } from './types.js';
|
|
3
|
+
export interface CreateCanvasMeasureOptions<TNode extends CanvasNode = CanvasNode> {
|
|
4
|
+
getNodes: () => TNode[];
|
|
5
|
+
/** Ids measured from (default: nodes with `selected: true`). */
|
|
6
|
+
getSelectedIds?: () => string[];
|
|
7
|
+
/** Turns measuring off (default `true`). Read reactively. */
|
|
8
|
+
enabled?: boolean | (() => boolean);
|
|
9
|
+
/** Measure only while Alt / Option is held (default `true`); `false` always measures. */
|
|
10
|
+
requireModifier?: boolean;
|
|
11
|
+
rectOptions?: NodeRectOptions;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Headless Svelte 5 rune for Alt-hover distance measuring: hold Alt / Option and hover a
|
|
15
|
+
* node to see red distance lines with labels from the selection to it (or to the selection's
|
|
16
|
+
* parent when hovering the selection or empty space).
|
|
17
|
+
*
|
|
18
|
+
* Wire it with `$effect(() => measure.listen())`, `onnodepointerenter={measure.onnodepointerenter}`
|
|
19
|
+
* and `onnodepointerleave={measure.onnodepointerleave}` on `<SvelteFlow>`, and render
|
|
20
|
+
* `measure.guides` with `<CanvasGuidesLayer>` (concatenate with `arrange.guides` to share one).
|
|
21
|
+
*/
|
|
22
|
+
export declare function createCanvasMeasure<TNode extends CanvasNode = CanvasNode>(options: CreateCanvasMeasureOptions<TNode>): {
|
|
23
|
+
/** Measuring lines (flow coordinates) for `<CanvasGuidesLayer>`. */
|
|
24
|
+
readonly guides: import("@pixerate/editor/canvas").MeasureGuide[];
|
|
25
|
+
/** The box measured to (outline it), or `null`. */
|
|
26
|
+
readonly target: import("@pixerate/editor/canvas").Rect | null;
|
|
27
|
+
/** Whether measuring is showing. */
|
|
28
|
+
readonly active: boolean;
|
|
29
|
+
readonly hoveredId: string | null;
|
|
30
|
+
setHovered(id: string | null): void;
|
|
31
|
+
/** Sets the modifier state by hand (e.g. from a toolbar toggle). */
|
|
32
|
+
setModifier(held: boolean): void;
|
|
33
|
+
onnodepointerenter: ({ node, event }: {
|
|
34
|
+
node: {
|
|
35
|
+
id: string;
|
|
36
|
+
};
|
|
37
|
+
event?: {
|
|
38
|
+
altKey?: boolean;
|
|
39
|
+
};
|
|
40
|
+
}) => void;
|
|
41
|
+
onnodepointerleave: ({ node }: {
|
|
42
|
+
node: {
|
|
43
|
+
id: string;
|
|
44
|
+
};
|
|
45
|
+
}) => void;
|
|
46
|
+
/**
|
|
47
|
+
* Tracks the Alt key on `target` (default `window`) and resets it when the window
|
|
48
|
+
* loses focus. Returns a cleanup function.
|
|
49
|
+
*/
|
|
50
|
+
listen(target?: HTMLElement | Window | null): () => void;
|
|
51
|
+
};
|
|
52
|
+
export type CanvasMeasure = ReturnType<typeof createCanvasMeasure>;
|
|
53
|
+
//# sourceMappingURL=createCanvasMeasure.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createCanvasMeasure.svelte.d.ts","sourceRoot":"","sources":["../../src/canvas/createCanvasMeasure.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,KAAK,eAAe,EACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,0BAA0B,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU;IAChF,QAAQ,EAAE,MAAM,KAAK,EAAE,CAAC;IACxB,gEAAgE;IAChE,cAAc,CAAC,EAAE,MAAM,MAAM,EAAE,CAAC;IAChC,6DAA6D;IAC7D,OAAO,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,CAAC;IACpC,yFAAyF;IACzF,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,eAAe,CAAC;CAC9B;AAID;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,SAAS,UAAU,GAAG,UAAU,EAAE,OAAO,EAAE,0BAA0B,CAAC,KAAK,CAAC;IAcnH,oEAAoE;;IAIpE,mDAAmD;;IAInD,oCAAoC;;;mBAOrB,MAAM,GAAG,IAAI;IAG5B,oEAAoE;sBAClD,OAAO;0CAGa;QAAE,IAAI,EAAE;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,KAAK,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,OAAO,CAAA;SAAE,CAAA;KAAE;mCAI7D;QAAE,IAAI,EAAE;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE;IAGvD;;;OAGG;oBACY,WAAW,GAAG,MAAM,GAAG,IAAI,GAAmD,MAAM,IAAI;EAmBxG;AAED,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { isMeasureModifierHeld, measureSelection } from '@pixerate/editor/canvas';
|
|
2
|
+
const EMPTY = { guides: [], target: null, selection: null };
|
|
3
|
+
/**
|
|
4
|
+
* Headless Svelte 5 rune for Alt-hover distance measuring: hold Alt / Option and hover a
|
|
5
|
+
* node to see red distance lines with labels from the selection to it (or to the selection's
|
|
6
|
+
* parent when hovering the selection or empty space).
|
|
7
|
+
*
|
|
8
|
+
* Wire it with `$effect(() => measure.listen())`, `onnodepointerenter={measure.onnodepointerenter}`
|
|
9
|
+
* and `onnodepointerleave={measure.onnodepointerleave}` on `<SvelteFlow>`, and render
|
|
10
|
+
* `measure.guides` with `<CanvasGuidesLayer>` (concatenate with `arrange.guides` to share one).
|
|
11
|
+
*/
|
|
12
|
+
export function createCanvasMeasure(options) {
|
|
13
|
+
let hoveredId = $state(null);
|
|
14
|
+
let modifier = $state(false);
|
|
15
|
+
const enabled = () => (typeof options.enabled === 'function' ? options.enabled() : options.enabled !== false);
|
|
16
|
+
const active = $derived(enabled() && (options.requireModifier === false || modifier));
|
|
17
|
+
const result = $derived.by(() => {
|
|
18
|
+
if (!active)
|
|
19
|
+
return EMPTY;
|
|
20
|
+
const nodes = options.getNodes();
|
|
21
|
+
const ids = options.getSelectedIds?.() ?? nodes.filter((n) => n.selected).map((n) => n.id);
|
|
22
|
+
return measureSelection(nodes, ids, hoveredId, options.rectOptions);
|
|
23
|
+
});
|
|
24
|
+
return {
|
|
25
|
+
/** Measuring lines (flow coordinates) for `<CanvasGuidesLayer>`. */
|
|
26
|
+
get guides() {
|
|
27
|
+
return result.guides;
|
|
28
|
+
},
|
|
29
|
+
/** The box measured to (outline it), or `null`. */
|
|
30
|
+
get target() {
|
|
31
|
+
return result.target;
|
|
32
|
+
},
|
|
33
|
+
/** Whether measuring is showing. */
|
|
34
|
+
get active() {
|
|
35
|
+
return active;
|
|
36
|
+
},
|
|
37
|
+
get hoveredId() {
|
|
38
|
+
return hoveredId;
|
|
39
|
+
},
|
|
40
|
+
setHovered(id) {
|
|
41
|
+
hoveredId = id;
|
|
42
|
+
},
|
|
43
|
+
/** Sets the modifier state by hand (e.g. from a toolbar toggle). */
|
|
44
|
+
setModifier(held) {
|
|
45
|
+
modifier = held;
|
|
46
|
+
},
|
|
47
|
+
onnodepointerenter: ({ node, event }) => {
|
|
48
|
+
hoveredId = node.id;
|
|
49
|
+
if (event && typeof event.altKey === 'boolean')
|
|
50
|
+
modifier = event.altKey;
|
|
51
|
+
},
|
|
52
|
+
onnodepointerleave: ({ node }) => {
|
|
53
|
+
if (hoveredId === node.id)
|
|
54
|
+
hoveredId = null;
|
|
55
|
+
},
|
|
56
|
+
/**
|
|
57
|
+
* Tracks the Alt key on `target` (default `window`) and resets it when the window
|
|
58
|
+
* loses focus. Returns a cleanup function.
|
|
59
|
+
*/
|
|
60
|
+
listen(target = typeof window !== 'undefined' ? window : null) {
|
|
61
|
+
if (!target)
|
|
62
|
+
return () => { };
|
|
63
|
+
const onKey = (event) => {
|
|
64
|
+
modifier = isMeasureModifierHeld(event);
|
|
65
|
+
};
|
|
66
|
+
const onBlur = () => {
|
|
67
|
+
modifier = false;
|
|
68
|
+
};
|
|
69
|
+
target.addEventListener('keydown', onKey);
|
|
70
|
+
target.addEventListener('keyup', onKey);
|
|
71
|
+
const win = typeof window !== 'undefined' ? window : null;
|
|
72
|
+
win?.addEventListener('blur', onBlur);
|
|
73
|
+
return () => {
|
|
74
|
+
target.removeEventListener('keydown', onKey);
|
|
75
|
+
target.removeEventListener('keyup', onKey);
|
|
76
|
+
win?.removeEventListener('blur', onBlur);
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
package/dist/canvas/index.d.ts
CHANGED
|
@@ -17,6 +17,8 @@ export { createStreamingCanvas, type CreateStreamingCanvasOptions } from './crea
|
|
|
17
17
|
export { createCanvasArrange, createCanvasArrangeShortcuts, type CanvasArrange, type CreateCanvasArrangeOptions, type CanvasArrangeShortcutsOptions } from './createCanvasArrange.svelte.js';
|
|
18
18
|
export { createCanvasScenes, type CanvasScenes, type CreateCanvasScenesOptions } from './createCanvasScenes.svelte.js';
|
|
19
19
|
export { default as CanvasGuidesLayer } from './CanvasGuidesLayer.svelte';
|
|
20
|
+
export { createCanvasMeasure, type CanvasMeasure, type CreateCanvasMeasureOptions } from './createCanvasMeasure.svelte.js';
|
|
21
|
+
export { measureBetween, measureToLine, measureSelection, measureLabel, isMeasureModifierHeld, snapToGrid, snapResize, snapNodeResize, inferResizeHandle, resizeHandleAxes, getResizingNodeRect, RESIZE_HANDLES, fitCubics, fitCubicRun, fitPathData, fitFreehandPath, cubicsToPathData, cubicPointAt, isStraightCubic, type MeasureGuide, type MeasureSelectionResult, type MeasureSelectionOptions, type ResizeHandle, type SnapResizeOptions, type SnapResizeResult, type SnapNodeResizeOptions, type SnapNodeResizeResult, type CubicSegment, type FitCubicsOptions, type FitPathDataOptions } from '@pixerate/editor/canvas';
|
|
20
22
|
export { alignNodes, distributeNodes, matchSize, reorderNodes, applyNodeUpdates, invertNodeUpdates, lockNodes, unlockNodes, toggleLockNodes, isLocked, getNodeSize, getNodeRect, getAbsolutePosition, readStyleSize, withStyleSize, computeSnapGuides, createGuideIndex, createNodeGuideIndex, snapNodeDrag, findConnectorSnap, nearestHandlePositions, handlePoint, positionToSide, sideToPosition, oppositePosition, CONNECTION_LINE_TYPES, CanvasScenesStore, createCanvasScenesStore, parseCanvasScenes, fitViewportToRect, fitViewportToNodes, matchArrangeShortcut, DEFAULT_ARRANGE_SHORTCUTS, type AlignEdge, type DistributeAxis, type DistributeMode, type SizeDimension, type ZOrderOperation, type CanvasNodeUpdate, type GuideLine, type GuideIndex, type SnapGuidesOptions, type SnapResult, type ConnectorSnap, type ConnectorSnapTarget, type CanvasConnectionLineType, type CanvasScene, type CanvasScenesState, type CanvasViewport, type CanvasArrangeAction, type ArrangeShortcutBinding } from '@pixerate/editor/canvas';
|
|
21
23
|
export { default as ShapeNode } from './ShapeNode.svelte';
|
|
22
24
|
export { combineShapeNodes, canCombineShapeNodes, applyShapeCombination, revertShapeCombination, shapeNodeToPolygon, isShapeNode, getNodeShape, SHAPE_DATA_KEY, SHAPE_NODE_TYPE, SHAPE_OPERATIONS, SHAPE_KINDS, isShapeDescription, shapeToPolygon, getShapeSvg, getShapeRenderData, parseSvgPath, flattenSvgPath, polygonToSvgPath, simplifyRing, polygonBoolean, unionPolygons, intersectPolygons, subtractPolygons, xorPolygons, dividePolygons, polygonArea, multiPolygonArea, multiPolygonBounds, ringSignedArea, pointInRings, pointInMultiPolygon, type ShapeOperation, type ShapeDescription, type ShapeKind, type ShapePaint, type ShapeSize, type ShapeRenderData, type RectShape, type EllipseShape, type RegularPolygonShape, type StarShape, type PathShape, type PathCommand, type FlattenOptions, type PolygonToPathOptions, type CombineShapeNodesOptions, type CombineShapeNodesResult, type CombineShapeNodesRefusal, type ShapeNodePolygonOptions, type MultiPolygon, type PolygonWithHoles, type PolygonRing, type PolygonFillRule, type PolygonOperand, type PolygonInput, type PolygonPiece, type PolygonBooleanOperation, type PolygonBooleanOptions } from '@pixerate/editor/canvas';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/canvas/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAC;AAG3B,OAAO,EACN,iBAAiB,EACjB,yBAAyB,EACzB,kBAAkB,EAClB,KAAK,wBAAwB,EAC7B,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EACN,gBAAgB,EAChB,uBAAuB,EACvB,WAAW,EACX,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,QAAQ,EACR,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EACN,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,UAAU,EACV,KAAK,4BAA4B,EACjC,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EACN,mBAAmB,EACnB,KAAK,0BAA0B,EAC/B,KAAK,YAAY,EACjB,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EACN,qBAAqB,EACrB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EACN,wBAAwB,EACxB,uBAAuB,EACvB,oBAAoB,EACpB,yBAAyB,EACzB,KAAK,+BAA+B,EACpC,MAAM,sCAAsC,CAAC;AAG9C,OAAO,EACN,gBAAgB,EAChB,wBAAwB,EACxB,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,EACtB,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EACN,uBAAuB,EACvB,gCAAgC,EAChC,2BAA2B,EAC3B,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EACN,qBAAqB,EACrB,KAAK,iBAAiB,EACtB,KAAK,4BAA4B,EACjC,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EACN,oBAAoB,EACpB,wBAAwB,EACxB,oBAAoB,EACpB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,2BAA2B,EAChC,MAAM,kCAAkC,CAAC;AAG1C,OAAO,EACN,qBAAqB,EACrB,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC5B,KAAK,4BAA4B,EACjC,KAAK,iBAAiB,EACtB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EACN,yBAAyB,EACzB,sBAAsB,EACtB,KAAK,sBAAsB,EAC3B,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAAE,OAAO,IAAI,2BAA2B,EAAE,MAAM,sCAAsC,CAAC;AAG9F,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAG5E,OAAO,EACN,qBAAqB,EACrB,KAAK,4BAA4B,EACjC,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EACN,mBAAmB,EACnB,4BAA4B,EAC5B,KAAK,aAAa,EAClB,KAAK,0BAA0B,EAC/B,KAAK,6BAA6B,EAClC,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACN,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,yBAAyB,EAC9B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/canvas/index.ts"],"names":[],"mappings":"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"}
|
package/dist/canvas/index.js
CHANGED
|
@@ -34,6 +34,9 @@ export { createStreamingCanvas } from './createStreamingCanvas.svelte.js';
|
|
|
34
34
|
export { createCanvasArrange, createCanvasArrangeShortcuts } from './createCanvasArrange.svelte.js';
|
|
35
35
|
export { createCanvasScenes } from './createCanvasScenes.svelte.js';
|
|
36
36
|
export { default as CanvasGuidesLayer } from './CanvasGuidesLayer.svelte';
|
|
37
|
+
// Distance measuring (Alt-hover), resize / grid snapping and curve fitting
|
|
38
|
+
export { createCanvasMeasure } from './createCanvasMeasure.svelte.js';
|
|
39
|
+
export { measureBetween, measureToLine, measureSelection, measureLabel, isMeasureModifierHeld, snapToGrid, snapResize, snapNodeResize, inferResizeHandle, resizeHandleAxes, getResizingNodeRect, RESIZE_HANDLES, fitCubics, fitCubicRun, fitPathData, fitFreehandPath, cubicsToPathData, cubicPointAt, isStraightCubic } from '@pixerate/editor/canvas';
|
|
37
40
|
export { alignNodes, distributeNodes, matchSize, reorderNodes, applyNodeUpdates, invertNodeUpdates, lockNodes, unlockNodes, toggleLockNodes, isLocked, getNodeSize, getNodeRect, getAbsolutePosition, readStyleSize, withStyleSize, computeSnapGuides, createGuideIndex, createNodeGuideIndex, snapNodeDrag, findConnectorSnap, nearestHandlePositions, handlePoint, positionToSide, sideToPosition, oppositePosition, CONNECTION_LINE_TYPES, CanvasScenesStore, createCanvasScenesStore, parseCanvasScenes, fitViewportToRect, fitViewportToNodes, matchArrangeShortcut, DEFAULT_ARRANGE_SHORTCUTS } from '@pixerate/editor/canvas';
|
|
38
41
|
export { default as ShapeNode } from './ShapeNode.svelte';
|
|
39
42
|
// Shape nodes and boolean operations (Unite / Intersect / Subtract / Exclude / Divide)
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
// Ids only render while the palette is open (client side), so a counter is enough
|
|
3
|
+
// (`$props.id()` needs Svelte 5.20, newer than our peer range).
|
|
4
|
+
let nextId = 0;
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<script lang="ts">
|
|
8
|
+
import type { CommandPaletteItem } from '@pixerate/editor/commands';
|
|
9
|
+
import type { SvelteCommandPalette } from './palette.svelte.js';
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
/** State from `createCommandPalette`. */
|
|
13
|
+
palette: SvelteCommandPalette;
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
emptyMessage?: string;
|
|
16
|
+
/** Extra classes for the dialog panel. */
|
|
17
|
+
class?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let {
|
|
21
|
+
palette,
|
|
22
|
+
placeholder = 'Type a command…',
|
|
23
|
+
emptyMessage = 'No matching commands',
|
|
24
|
+
class: className = ''
|
|
25
|
+
}: Props = $props();
|
|
26
|
+
|
|
27
|
+
const baseId = `command-palette-${++nextId}`;
|
|
28
|
+
const listId = `${baseId}-list`;
|
|
29
|
+
const optionId = (index: number) => `${baseId}-option-${index}`;
|
|
30
|
+
|
|
31
|
+
let inputEl = $state<HTMLInputElement | null>(null);
|
|
32
|
+
let listEl = $state<HTMLUListElement | null>(null);
|
|
33
|
+
|
|
34
|
+
$effect(() => {
|
|
35
|
+
if (palette.open) inputEl?.focus();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
$effect(() => {
|
|
39
|
+
void palette.activeIndex;
|
|
40
|
+
if (!palette.open) return;
|
|
41
|
+
const active = listEl?.querySelector<HTMLElement>('[aria-selected="true"]');
|
|
42
|
+
active?.scrollIntoView?.({ block: 'nearest' });
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const segments = (item: CommandPaletteItem) => {
|
|
46
|
+
const marked = new Set(item.labelIndices);
|
|
47
|
+
return Array.from(item.label).map((ch, i) => ({ ch, match: marked.has(i) }));
|
|
48
|
+
};
|
|
49
|
+
</script>
|
|
50
|
+
|
|
51
|
+
{#if palette.open}
|
|
52
|
+
<!-- Headless-styled command palette: Arrow keys move, Enter runs, Escape or a backdrop press closes. -->
|
|
53
|
+
<div
|
|
54
|
+
class="fixed inset-0 z-50 flex items-start justify-center bg-black/30 px-4 pt-[15vh]"
|
|
55
|
+
data-command-palette-backdrop=""
|
|
56
|
+
role="presentation"
|
|
57
|
+
onmousedown={(e) => {
|
|
58
|
+
if (e.target === e.currentTarget) palette.setOpen(false);
|
|
59
|
+
}}
|
|
60
|
+
>
|
|
61
|
+
<div
|
|
62
|
+
role="dialog"
|
|
63
|
+
aria-modal="true"
|
|
64
|
+
aria-label="Command palette"
|
|
65
|
+
class="w-full max-w-lg overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-xl {className}"
|
|
66
|
+
style="background: var(--popover, var(--background, #fff));"
|
|
67
|
+
>
|
|
68
|
+
<input
|
|
69
|
+
bind:this={inputEl}
|
|
70
|
+
type="text"
|
|
71
|
+
role="combobox"
|
|
72
|
+
aria-expanded="true"
|
|
73
|
+
aria-controls={listId}
|
|
74
|
+
aria-autocomplete="list"
|
|
75
|
+
aria-activedescendant={palette.items.length ? optionId(palette.activeIndex) : undefined}
|
|
76
|
+
aria-label="Search commands"
|
|
77
|
+
{placeholder}
|
|
78
|
+
value={palette.query}
|
|
79
|
+
oninput={(e) => palette.setQuery(e.currentTarget.value)}
|
|
80
|
+
onkeydown={(e) => {
|
|
81
|
+
if (palette.handleKeyDown(e)) e.stopPropagation();
|
|
82
|
+
}}
|
|
83
|
+
class="w-full border-b border-border bg-transparent px-3 py-2 text-sm outline-none placeholder:text-muted-foreground"
|
|
84
|
+
/>
|
|
85
|
+
{#if palette.items.length === 0}
|
|
86
|
+
<div class="px-3 py-6 text-center text-sm text-muted-foreground">{emptyMessage}</div>
|
|
87
|
+
{:else}
|
|
88
|
+
<ul bind:this={listEl} id={listId} role="listbox" aria-label="Commands" class="max-h-80 overflow-y-auto py-1">
|
|
89
|
+
{#each palette.items as item, index (item.id)}
|
|
90
|
+
<li
|
|
91
|
+
id={optionId(index)}
|
|
92
|
+
role="option"
|
|
93
|
+
aria-selected={index === palette.activeIndex}
|
|
94
|
+
aria-disabled={!item.enabled || undefined}
|
|
95
|
+
data-command-id={item.id}
|
|
96
|
+
data-recent={item.recent ? '' : undefined}
|
|
97
|
+
title={item.disabledReason}
|
|
98
|
+
onmousemove={() => index !== palette.activeIndex && palette.setActiveIndex(index)}
|
|
99
|
+
onmousedown={(e) => e.preventDefault()}
|
|
100
|
+
onclick={() => palette.run(item.id)}
|
|
101
|
+
onkeydown={() => {}}
|
|
102
|
+
class="flex cursor-pointer items-center gap-2 px-3 py-1.5 text-sm {index === palette.activeIndex
|
|
103
|
+
? 'bg-muted'
|
|
104
|
+
: ''} {item.enabled ? '' : 'cursor-default opacity-50'}"
|
|
105
|
+
>
|
|
106
|
+
<span class="min-w-0 flex-1 truncate">
|
|
107
|
+
{#each segments(item) as segment, i (i)}{#if segment.match}<span
|
|
108
|
+
class="font-semibold text-foreground"
|
|
109
|
+
data-match="">{segment.ch}</span
|
|
110
|
+
>{:else}{segment.ch}{/if}{/each}
|
|
111
|
+
{#if item.disabledReason}
|
|
112
|
+
<span class="ml-2 text-xs text-muted-foreground" data-disabled-reason="">{item.disabledReason}</span>
|
|
113
|
+
{/if}
|
|
114
|
+
</span>
|
|
115
|
+
{#if item.group}
|
|
116
|
+
<span class="shrink-0 text-xs text-muted-foreground">{item.group}</span>
|
|
117
|
+
{/if}
|
|
118
|
+
{#if item.shortcut}
|
|
119
|
+
<kbd class="shrink-0 rounded border border-border px-1.5 font-mono text-[10px] text-muted-foreground"
|
|
120
|
+
>{item.shortcut}</kbd
|
|
121
|
+
>
|
|
122
|
+
{/if}
|
|
123
|
+
</li>
|
|
124
|
+
{/each}
|
|
125
|
+
</ul>
|
|
126
|
+
{/if}
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
{/if}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SvelteCommandPalette } from './palette.svelte.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
/** State from `createCommandPalette`. */
|
|
4
|
+
palette: SvelteCommandPalette;
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
emptyMessage?: string;
|
|
7
|
+
/** Extra classes for the dialog panel. */
|
|
8
|
+
class?: string;
|
|
9
|
+
}
|
|
10
|
+
declare const CommandPalette: import("svelte").Component<Props, {}, "">;
|
|
11
|
+
type CommandPalette = ReturnType<typeof CommandPalette>;
|
|
12
|
+
export default CommandPalette;
|
|
13
|
+
//# sourceMappingURL=CommandPalette.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandPalette.svelte.d.ts","sourceRoot":"","sources":["../../src/commands/CommandPalette.svelte.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAG9D,UAAU,KAAK;IACb,yCAAyC;IACzC,OAAO,EAAE,oBAAoB,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA8EH,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { CommandRegistry, CommandResult, CommandSpec } from "@pixerate/editor/commands";
|
|
2
|
+
type MaybeGetter<T> = T | (() => T);
|
|
3
|
+
export interface CommandShortcutsOptions<TContext = any> {
|
|
4
|
+
/** Element or window to listen on (default: `window`). */
|
|
5
|
+
target?: Window | HTMLElement | null;
|
|
6
|
+
/** Active scopes, most specific first; a getter is read on every keydown. */
|
|
7
|
+
scopes?: MaybeGetter<string | readonly string[] | undefined>;
|
|
8
|
+
/** Context for the commands (default: the registry's); a getter is read on every keydown. */
|
|
9
|
+
context?: MaybeGetter<TContext | undefined>;
|
|
10
|
+
/** Fire even while typing in inputs / contenteditable (default: per binding). */
|
|
11
|
+
allowInEditable?: boolean;
|
|
12
|
+
/** Called after a shortcut ran a command. */
|
|
13
|
+
onRun?: (result: CommandResult) => void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Runs the registry's commands from their keyboard shortcuts (`registry.handleKeyDown`).
|
|
17
|
+
* Typing in inputs and editors is never hijacked, and disabled commands leave the event
|
|
18
|
+
* alone. Returns `{ destroy }`.
|
|
19
|
+
*/
|
|
20
|
+
export declare function createCommandShortcuts<TContext = any>(registry: CommandRegistry<TContext>, options?: CommandShortcutsOptions<TContext>): {
|
|
21
|
+
destroy: () => void;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Registers commands for the lifetime of the calling component (call it during
|
|
25
|
+
* component initialisation). Pass a getter to react to changes: when it returns a
|
|
26
|
+
* different array, the old commands are unregistered.
|
|
27
|
+
*/
|
|
28
|
+
export declare function useRegisterCommands<TContext = any>(registry: MaybeGetter<CommandRegistry<TContext> | null | undefined>, specs: MaybeGetter<readonly CommandSpec<TContext>[] | null | undefined>): void;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=commandShortcuts.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commandShortcuts.svelte.d.ts","sourceRoot":"","sources":["../../src/commands/commandShortcuts.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE7F,KAAK,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AAKpC,MAAM,WAAW,uBAAuB,CAAC,QAAQ,GAAG,GAAG;IACrD,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;IACrC,6EAA6E;IAC7E,MAAM,CAAC,EAAE,WAAW,CAAC,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IAC7D,6FAA6F;IAC7F,OAAO,CAAC,EAAE,WAAW,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;IAC5C,iFAAiF;IACjF,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,6CAA6C;IAC7C,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;CACzC;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,GAAG,GAAG,EACnD,QAAQ,EAAE,eAAe,CAAC,QAAQ,CAAC,EACnC,OAAO,GAAE,uBAAuB,CAAC,QAAQ,CAAM,GAC9C;IAAE,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,CAczB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,GAAG,GAAG,EAChD,QAAQ,EAAE,WAAW,CAAC,eAAe,CAAC,QAAQ,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC,EACnE,KAAK,EAAE,WAAW,CAAC,SAAS,WAAW,CAAC,QAAQ,CAAC,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC,GACtE,IAAI,CAON"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const read = (value) => typeof value === "function" ? value() : value;
|
|
2
|
+
/**
|
|
3
|
+
* Runs the registry's commands from their keyboard shortcuts (`registry.handleKeyDown`).
|
|
4
|
+
* Typing in inputs and editors is never hijacked, and disabled commands leave the event
|
|
5
|
+
* alone. Returns `{ destroy }`.
|
|
6
|
+
*/
|
|
7
|
+
export function createCommandShortcuts(registry, options = {}) {
|
|
8
|
+
const target = options.target ?? (typeof window !== "undefined" ? window : null);
|
|
9
|
+
if (!target)
|
|
10
|
+
return { destroy: () => { } };
|
|
11
|
+
const onKeyDown = (event) => {
|
|
12
|
+
const context = options.context === undefined ? undefined : read(options.context);
|
|
13
|
+
const result = registry.handleKeyDown(event, {
|
|
14
|
+
scopes: options.scopes === undefined ? undefined : read(options.scopes),
|
|
15
|
+
...(options.allowInEditable !== undefined ? { allowInEditable: options.allowInEditable } : {}),
|
|
16
|
+
...(context !== undefined ? { context } : {}),
|
|
17
|
+
});
|
|
18
|
+
if (result)
|
|
19
|
+
options.onRun?.(result);
|
|
20
|
+
};
|
|
21
|
+
target.addEventListener("keydown", onKeyDown);
|
|
22
|
+
return { destroy: () => target.removeEventListener("keydown", onKeyDown) };
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Registers commands for the lifetime of the calling component (call it during
|
|
26
|
+
* component initialisation). Pass a getter to react to changes: when it returns a
|
|
27
|
+
* different array, the old commands are unregistered.
|
|
28
|
+
*/
|
|
29
|
+
export function useRegisterCommands(registry, specs) {
|
|
30
|
+
$effect(() => {
|
|
31
|
+
const currentRegistry = read(registry);
|
|
32
|
+
const currentSpecs = read(specs);
|
|
33
|
+
if (!currentRegistry || !currentSpecs || currentSpecs.length === 0)
|
|
34
|
+
return;
|
|
35
|
+
return currentRegistry.register(currentSpecs);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ComponentProps } from "svelte";
|
|
2
|
+
import type CommandPaletteComponent from "./CommandPalette.svelte";
|
|
3
|
+
export { default as CommandPalette } from "./CommandPalette.svelte";
|
|
4
|
+
export * from "./palette.svelte.js";
|
|
5
|
+
export * from "./commandShortcuts.svelte.js";
|
|
6
|
+
export type CommandPaletteProps = ComponentProps<typeof CommandPaletteComponent>;
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/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,qBAAqB,CAAC;AACpC,cAAc,8BAA8B,CAAC;AAE7C,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,OAAO,uBAAuB,CAAC,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type CommandPaletteController, type CommandPaletteItem, type CommandPaletteOptions, type CommandRegistry, type CommandResult } from "@pixerate/editor/commands";
|
|
2
|
+
export interface CreateCommandPaletteOptions<TContext = any> extends CommandPaletteOptions<TContext> {
|
|
3
|
+
/** Chord that toggles the palette from anywhere, also while typing (e.g. `Mod+K`). */
|
|
4
|
+
hotkey?: string;
|
|
5
|
+
/** Element or window the hotkey listens on (default: `window`). */
|
|
6
|
+
hotkeyTarget?: Window | HTMLElement | null;
|
|
7
|
+
}
|
|
8
|
+
export interface SvelteCommandPalette {
|
|
9
|
+
readonly open: boolean;
|
|
10
|
+
readonly query: string;
|
|
11
|
+
readonly activeIndex: number;
|
|
12
|
+
readonly items: CommandPaletteItem[];
|
|
13
|
+
readonly recents: string[];
|
|
14
|
+
readonly lastResult: CommandResult | null;
|
|
15
|
+
readonly controller: CommandPaletteController;
|
|
16
|
+
setOpen(open: boolean): void;
|
|
17
|
+
toggle(): void;
|
|
18
|
+
setQuery(query: string): void;
|
|
19
|
+
setActiveIndex(index: number): void;
|
|
20
|
+
move(delta: number): void;
|
|
21
|
+
run(id: string): CommandResult | null;
|
|
22
|
+
runActive(): CommandResult | null;
|
|
23
|
+
handleKeyDown(event: KeyboardEvent): boolean;
|
|
24
|
+
/** Stops following the registry and removes the hotkey listener. */
|
|
25
|
+
destroy(): void;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Reactive command palette state over a `CommandRegistry` (Svelte 5 runes): ranked rows
|
|
29
|
+
* with shortcuts and disabled reasons, active row and recents. Render it with
|
|
30
|
+
* `<CommandPalette palette={…} />` or your own markup. Call `destroy()` when done
|
|
31
|
+
* (e.g. in `onDestroy`).
|
|
32
|
+
*/
|
|
33
|
+
export declare function createCommandPalette<TContext = any>(registry: CommandRegistry<TContext>, options?: CreateCommandPaletteOptions<TContext>): SvelteCommandPalette;
|
|
34
|
+
//# sourceMappingURL=palette.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"palette.svelte.d.ts","sourceRoot":"","sources":["../../src/commands/palette.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,wBAAwB,EAC7B,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAE1B,KAAK,eAAe,EACpB,KAAK,aAAa,EACnB,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,2BAA2B,CAAC,QAAQ,GAAG,GAAG,CAAE,SAAQ,qBAAqB,CAAC,QAAQ,CAAC;IAClG,sFAAsF;IACtF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;CAC5C;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,kBAAkB,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,aAAa,GAAG,IAAI,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,wBAAwB,CAAC;IAC9C,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7B,MAAM,IAAI,IAAI,CAAC;IACf,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAAC;IACtC,SAAS,IAAI,aAAa,GAAG,IAAI,CAAC;IAClC,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC;IAC7C,oEAAoE;IACpE,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,GAAG,GAAG,EACjD,QAAQ,EAAE,eAAe,CAAC,QAAQ,CAAC,EACnC,OAAO,GAAE,2BAA2B,CAAC,QAAQ,CAAM,GAClD,oBAAoB,CAsDtB"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { createCommandPaletteController, matchPaletteHotkey, } from "@pixerate/editor/commands";
|
|
2
|
+
/**
|
|
3
|
+
* Reactive command palette state over a `CommandRegistry` (Svelte 5 runes): ranked rows
|
|
4
|
+
* with shortcuts and disabled reasons, active row and recents. Render it with
|
|
5
|
+
* `<CommandPalette palette={…} />` or your own markup. Call `destroy()` when done
|
|
6
|
+
* (e.g. in `onDestroy`).
|
|
7
|
+
*/
|
|
8
|
+
export function createCommandPalette(registry, options = {}) {
|
|
9
|
+
const controller = createCommandPaletteController(registry, options);
|
|
10
|
+
let state = $state.raw(controller.getState());
|
|
11
|
+
const unsubscribe = controller.subscribe((next) => {
|
|
12
|
+
state = next;
|
|
13
|
+
});
|
|
14
|
+
let removeHotkey = () => { };
|
|
15
|
+
const { hotkey } = options;
|
|
16
|
+
const target = options.hotkeyTarget ?? (typeof window !== "undefined" ? window : null);
|
|
17
|
+
if (hotkey && target) {
|
|
18
|
+
const onKeyDown = (event) => {
|
|
19
|
+
const e = event;
|
|
20
|
+
if (e.defaultPrevented || !matchPaletteHotkey(e, hotkey, options.platform))
|
|
21
|
+
return;
|
|
22
|
+
e.preventDefault();
|
|
23
|
+
controller.toggle();
|
|
24
|
+
};
|
|
25
|
+
target.addEventListener("keydown", onKeyDown);
|
|
26
|
+
removeHotkey = () => target.removeEventListener("keydown", onKeyDown);
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
get open() {
|
|
30
|
+
return state.open;
|
|
31
|
+
},
|
|
32
|
+
get query() {
|
|
33
|
+
return state.query;
|
|
34
|
+
},
|
|
35
|
+
get activeIndex() {
|
|
36
|
+
return state.activeIndex;
|
|
37
|
+
},
|
|
38
|
+
get items() {
|
|
39
|
+
return state.items;
|
|
40
|
+
},
|
|
41
|
+
get recents() {
|
|
42
|
+
return state.recents;
|
|
43
|
+
},
|
|
44
|
+
get lastResult() {
|
|
45
|
+
return state.lastResult;
|
|
46
|
+
},
|
|
47
|
+
controller,
|
|
48
|
+
setOpen: controller.setOpen,
|
|
49
|
+
toggle: controller.toggle,
|
|
50
|
+
setQuery: controller.setQuery,
|
|
51
|
+
setActiveIndex: controller.setActiveIndex,
|
|
52
|
+
move: controller.move,
|
|
53
|
+
run: controller.run,
|
|
54
|
+
runActive: controller.runActive,
|
|
55
|
+
handleKeyDown: controller.handleKeyDown,
|
|
56
|
+
destroy() {
|
|
57
|
+
unsubscribe();
|
|
58
|
+
removeHotkey();
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createHistoryShortcuts.d.ts","sourceRoot":"","sources":["../../src/history/createHistoryShortcuts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"createHistoryShortcuts.d.ts","sourceRoot":"","sources":["../../src/history/createHistoryShortcuts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG/D,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;IACrC;;;OAGG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,cAAc,EACvB,OAAO,GAAE,uBAA4B,GACpC;IAAE,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,CAqCzB"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { matchHistoryShortcut } from "@pixerate/editor/commands";
|
|
1
2
|
/**
|
|
2
3
|
* Attaches keyboard listeners for Undo (Mod+Z) and Redo (Mod+Shift+Z / Mod+Y).
|
|
3
4
|
* Returns an object with a `destroy()` function for lifecycle cleanup.
|
|
@@ -13,39 +14,16 @@ export function createHistoryShortcuts(manager, options = {}) {
|
|
|
13
14
|
}
|
|
14
15
|
const handleKeyDown = (event) => {
|
|
15
16
|
const e = event;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const targetEl = (e.target || document.activeElement);
|
|
23
|
-
if (targetEl && targetEl.tagName) {
|
|
24
|
-
const tagName = targetEl.tagName.toLowerCase();
|
|
25
|
-
const isInput = tagName === "input" || tagName === "textarea";
|
|
26
|
-
const isContentEditable = targetEl.isContentEditable ||
|
|
27
|
-
targetEl.getAttribute?.("contenteditable") === "true";
|
|
28
|
-
if (isInput || isContentEditable) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
17
|
+
// Default bindings from the command system: Mod+Z, Mod+Shift+Z and (off macOS) Mod+Y,
|
|
18
|
+
// matched by `event.code` with `Mod` = ⌘ on macOS and Ctrl elsewhere.
|
|
19
|
+
const action = matchHistoryShortcut(e, { allowInEditable: !ignoreEditableElements });
|
|
20
|
+
if (action === "undo" && manager.getState().canUndo) {
|
|
21
|
+
e.preventDefault();
|
|
22
|
+
manager.undo();
|
|
32
23
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (manager.getState().canUndo) {
|
|
37
|
-
e.preventDefault();
|
|
38
|
-
manager.undo();
|
|
39
|
-
}
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
// Redo: Mod+Shift+Z or (on non-Mac) Mod+Y
|
|
43
|
-
const isRedoKey = (key === "z" && e.shiftKey) || (!isMac && key === "y" && !e.shiftKey);
|
|
44
|
-
if (isRedoKey) {
|
|
45
|
-
if (manager.getState().canRedo) {
|
|
46
|
-
e.preventDefault();
|
|
47
|
-
manager.redo();
|
|
48
|
-
}
|
|
24
|
+
else if (action === "redo" && manager.getState().canRedo) {
|
|
25
|
+
e.preventDefault();
|
|
26
|
+
manager.redo();
|
|
49
27
|
}
|
|
50
28
|
};
|
|
51
29
|
eventTarget.addEventListener("keydown", handleKeyDown);
|
|
@@ -1,14 +1,23 @@
|
|
|
1
|
-
import { HistoryManager, HistoryState, Command, HistoryManagerOptions } from "@pixerate/editor/history";
|
|
1
|
+
import { HistoryManager, HistoryState, HistoryEntry, HistoryMark, MergedExecutionOptions, Command, HistoryManagerOptions } from "@pixerate/editor/history";
|
|
2
2
|
export interface SvelteHistory extends HistoryState {
|
|
3
3
|
readonly manager: HistoryManager;
|
|
4
|
+
/** History panel rows (undo steps, then redo steps). */
|
|
5
|
+
readonly entries: HistoryEntry[];
|
|
4
6
|
undo(): boolean;
|
|
5
7
|
redo(): boolean;
|
|
6
8
|
clear(): void;
|
|
7
9
|
execute(command: Command): void;
|
|
8
|
-
executeMerged(command: Command, options?:
|
|
9
|
-
windowMs?: number;
|
|
10
|
-
}): void;
|
|
10
|
+
executeMerged(command: Command, options?: MergedExecutionOptions): void;
|
|
11
11
|
batch(name: string, fn: () => void): void;
|
|
12
|
+
/** Undoes / redoes until the entry at `index` is current (`-1` = before all). */
|
|
13
|
+
goTo(index: number): number;
|
|
14
|
+
/** Captures the current point, e.g. when a drag starts. */
|
|
15
|
+
mark(): HistoryMark;
|
|
16
|
+
/** Takes back every step since `mark` without leaving redo (Escape-cancel). */
|
|
17
|
+
revertTo(mark: HistoryMark): number;
|
|
18
|
+
/** Joins every merged execute into one step until `endGesture`. */
|
|
19
|
+
beginGesture(key: string): void;
|
|
20
|
+
endGesture(): void;
|
|
12
21
|
subscribe(run: (value: HistoryState) => void): () => void;
|
|
13
22
|
}
|
|
14
23
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"history.svelte.d.ts","sourceRoot":"","sources":["../../src/history/history.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,YAAY,EACZ,OAAO,EAEP,qBAAqB,EACtB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,IAAI,IAAI,OAAO,CAAC;IAChB,IAAI,IAAI,OAAO,CAAC;IAChB,KAAK,IAAI,IAAI,CAAC;IACd,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAChC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;
|
|
1
|
+
{"version":3,"file":"history.svelte.d.ts","sourceRoot":"","sources":["../../src/history/history.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,sBAAsB,EACtB,OAAO,EAEP,qBAAqB,EACtB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,wDAAwD;IACxD,QAAQ,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC;IACjC,IAAI,IAAI,OAAO,CAAC;IAChB,IAAI,IAAI,OAAO,CAAC;IAChB,KAAK,IAAI,IAAI,CAAC;IACd,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAChC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;IACxE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAC1C,iFAAiF;IACjF,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,2DAA2D;IAC3D,IAAI,IAAI,WAAW,CAAC;IACpB,+EAA+E;IAC/E,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAAC;IACpC,mEAAmE;IACnE,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,UAAU,IAAI,IAAI,CAAC;IACnB,SAAS,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAC3D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,gBAAgB,CAAC,EAAE,cAAc,GAAG,qBAAqB,GACxD,aAAa,CAqDf"}
|
|
@@ -32,12 +32,22 @@ export function createHistory(managerOrOptions) {
|
|
|
32
32
|
get manager() {
|
|
33
33
|
return manager;
|
|
34
34
|
},
|
|
35
|
+
get entries() {
|
|
36
|
+
// Reading `state` makes the getter reactive; getEntries() is cached per change.
|
|
37
|
+
void state;
|
|
38
|
+
return manager.getEntries();
|
|
39
|
+
},
|
|
35
40
|
undo: () => manager.undo(),
|
|
36
41
|
redo: () => manager.redo(),
|
|
37
42
|
clear: () => manager.clear(),
|
|
38
43
|
execute: (cmd) => manager.execute(cmd),
|
|
39
44
|
executeMerged: (cmd, opts) => manager.executeMerged(cmd, opts),
|
|
40
45
|
batch: (name, fn) => manager.batch(name, fn),
|
|
46
|
+
goTo: (index) => manager.goTo(index),
|
|
47
|
+
mark: () => manager.mark(),
|
|
48
|
+
revertTo: (m) => manager.revertTo(m),
|
|
49
|
+
beginGesture: (key) => manager.beginGesture(key),
|
|
50
|
+
endGesture: () => manager.endGesture(),
|
|
41
51
|
subscribe: (run) => manager.subscribe(run),
|
|
42
52
|
};
|
|
43
53
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { DirtyTracker, type DirtyTrackerOptions, type HistoryManager } from "@pixerate/editor/history";
|
|
2
|
+
export interface CreateHistoryDirtyOptions<T> extends DirtyTrackerOptions<T> {
|
|
3
|
+
/** The history whose changes re-check the document (a `createHistory().manager`). */
|
|
4
|
+
history: HistoryManager;
|
|
5
|
+
/** Reads the current document value. */
|
|
6
|
+
getValue: () => T;
|
|
7
|
+
/** Existing tracker to drive. */
|
|
8
|
+
tracker?: DirtyTracker<T>;
|
|
9
|
+
}
|
|
10
|
+
export interface SvelteHistoryDirty<T> {
|
|
11
|
+
/** Whether the document differs from the saved state (reactive). */
|
|
12
|
+
readonly isDirty: boolean;
|
|
13
|
+
/** Marks the current document as saved. */
|
|
14
|
+
markClean(): void;
|
|
15
|
+
/** Runs a load / restore without marking the document dirty (re-entrant). */
|
|
16
|
+
suppress<R>(fn: () => R): R;
|
|
17
|
+
/** Re-checks after a change made outside the history. */
|
|
18
|
+
refresh(): boolean;
|
|
19
|
+
readonly tracker: DirtyTracker<T>;
|
|
20
|
+
/** Stops following the history. */
|
|
21
|
+
destroy(): void;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Svelte 5 rune: dirty-vs-saved tracking bound to a HistoryManager. Undoing
|
|
25
|
+
* back to the saved state makes the document clean again, so a navigation
|
|
26
|
+
* guard fed with `isDirty` stops prompting.
|
|
27
|
+
*
|
|
28
|
+
* Usage: `createNavigationGuard({ isDirty: () => dirty.isDirty })`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function createHistoryDirty<T>(options: CreateHistoryDirtyOptions<T>): SvelteHistoryDirty<T>;
|
|
31
|
+
//# sourceMappingURL=historyDirty.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"historyDirty.svelte.d.ts","sourceRoot":"","sources":["../../src/history/historyDirty.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAEZ,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACpB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,yBAAyB,CAAC,CAAC,CAAE,SAAQ,mBAAmB,CAAC,CAAC,CAAC;IAC1E,qFAAqF;IACrF,OAAO,EAAE,cAAc,CAAC;IACxB,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAClB,iCAAiC;IACjC,OAAO,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC;IACnC,oEAAoE;IACpE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,2CAA2C;IAC3C,SAAS,IAAI,IAAI,CAAC;IAClB,6EAA6E;IAC7E,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAC5B,yDAAyD;IACzD,OAAO,IAAI,OAAO,CAAC;IACnB,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,mCAAmC;IACnC,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,OAAO,EAAE,yBAAyB,CAAC,CAAC,CAAC,GACpC,kBAAkB,CAAC,CAAC,CAAC,CAsBvB"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { bindDirtyToHistory, } from "@pixerate/editor/history";
|
|
2
|
+
/**
|
|
3
|
+
* Svelte 5 rune: dirty-vs-saved tracking bound to a HistoryManager. Undoing
|
|
4
|
+
* back to the saved state makes the document clean again, so a navigation
|
|
5
|
+
* guard fed with `isDirty` stops prompting.
|
|
6
|
+
*
|
|
7
|
+
* Usage: `createNavigationGuard({ isDirty: () => dirty.isDirty })`.
|
|
8
|
+
*/
|
|
9
|
+
export function createHistoryDirty(options) {
|
|
10
|
+
const binding = bindDirtyToHistory(options);
|
|
11
|
+
let isDirty = $state(binding.dirty);
|
|
12
|
+
const unsubscribe = binding.subscribe((dirty) => {
|
|
13
|
+
isDirty = dirty;
|
|
14
|
+
});
|
|
15
|
+
return {
|
|
16
|
+
get isDirty() {
|
|
17
|
+
return isDirty;
|
|
18
|
+
},
|
|
19
|
+
markClean: () => binding.markClean(),
|
|
20
|
+
suppress: (fn) => binding.suppress(fn),
|
|
21
|
+
refresh: () => binding.refresh(),
|
|
22
|
+
get tracker() {
|
|
23
|
+
return binding.tracker;
|
|
24
|
+
},
|
|
25
|
+
destroy() {
|
|
26
|
+
unsubscribe();
|
|
27
|
+
binding.destroy();
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
package/dist/history/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/history/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/history/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,0BAA0B,CAAC"}
|
package/dist/history/index.js
CHANGED
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
getCropCursor,
|
|
17
17
|
calculateCropDrag,
|
|
18
18
|
hitTestAnnotation,
|
|
19
|
+
normalizeProcessVersion,
|
|
20
|
+
LATEST_PROCESS_VERSION,
|
|
19
21
|
} from '@pixerate/editor/image-editor';
|
|
20
22
|
import { onDestroy, untrack } from 'svelte';
|
|
21
23
|
import { createReactiveImageEditor, type ReactiveImageEditor } from './imageEditorState.svelte.js';
|
|
@@ -47,6 +49,9 @@
|
|
|
47
49
|
const internalEditor = createReactiveImageEditor();
|
|
48
50
|
const editor = $derived(propEditor || internalEditor);
|
|
49
51
|
onDestroy(() => internalEditor.destroy());
|
|
52
|
+
const legacyProcess = $derived(
|
|
53
|
+
normalizeProcessVersion(editor.state.adjustments.process) < LATEST_PROCESS_VERSION
|
|
54
|
+
);
|
|
50
55
|
|
|
51
56
|
let canvasEl = $state<HTMLCanvasElement | null>(null);
|
|
52
57
|
let containerEl = $state<HTMLDivElement | null>(null);
|
|
@@ -961,6 +966,40 @@
|
|
|
961
966
|
/>
|
|
962
967
|
</div>
|
|
963
968
|
|
|
969
|
+
<!-- Tint (process 2 white balance) -->
|
|
970
|
+
<div>
|
|
971
|
+
<div class="flex justify-between text-slate-400 mb-1">
|
|
972
|
+
<span>Tint</span>
|
|
973
|
+
<span class="font-mono">{editor.state.adjustments.tint ?? 0}</span>
|
|
974
|
+
</div>
|
|
975
|
+
<input
|
|
976
|
+
type="range"
|
|
977
|
+
min="-100"
|
|
978
|
+
max="100"
|
|
979
|
+
aria-label="Tint"
|
|
980
|
+
disabled={legacyProcess}
|
|
981
|
+
value={editor.state.adjustments.tint ?? 0}
|
|
982
|
+
oninput={(e) => editor.setAdjustments({ tint: Number((e.target as HTMLInputElement).value) })}
|
|
983
|
+
class="w-full accent-indigo-500 disabled:opacity-40"
|
|
984
|
+
/>
|
|
985
|
+
</div>
|
|
986
|
+
|
|
987
|
+
{#if legacyProcess}
|
|
988
|
+
<div
|
|
989
|
+
class="flex items-center justify-between gap-2 rounded border border-amber-500/30 bg-amber-500/10 px-2 py-1.5 text-[10px] text-amber-200"
|
|
990
|
+
data-testid="image-editor-process-notice"
|
|
991
|
+
>
|
|
992
|
+
<span>Legacy rendering (process 1). Tint needs the current process.</span>
|
|
993
|
+
<button
|
|
994
|
+
type="button"
|
|
995
|
+
onclick={() => editor.upgradeProcess()}
|
|
996
|
+
class="shrink-0 rounded bg-amber-500/20 px-2 py-0.5 hover:bg-amber-500/30"
|
|
997
|
+
>
|
|
998
|
+
Update
|
|
999
|
+
</button>
|
|
1000
|
+
</div>
|
|
1001
|
+
{/if}
|
|
1002
|
+
|
|
964
1003
|
<!-- Blur -->
|
|
965
1004
|
<div>
|
|
966
1005
|
<div class="flex justify-between text-slate-400 mb-1">
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageEditor.svelte.d.ts","sourceRoot":"","sources":["../../src/image-editor/ImageEditor.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAIR,aAAa,EAGb,WAAW,EACX,oBAAoB,EACpB,kBAAkB,EACnB,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"ImageEditor.svelte.d.ts","sourceRoot":"","sources":["../../src/image-editor/ImageEditor.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAIR,aAAa,EAGb,WAAW,EACX,oBAAoB,EACpB,kBAAkB,EACnB,MAAM,+BAA+B,CAAC;AAWzC,OAAO,EAA6B,KAAK,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAGjG,UAAU,KAAK;IACb,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,kBAAkB,CAAC,EAAE,oBAAoB,CAAC;IAC1C,OAAO,CAAC,EAAE,kBAAkB,CAAC;CAC9B;AAojCH,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
|
|
@@ -14,6 +14,8 @@ export declare function createReactiveImageEditor(options?: ImageEditorOptions):
|
|
|
14
14
|
flipVertical(): void;
|
|
15
15
|
setAdjustments(partial: Partial<ImageAdjustments>, commitToHistory?: boolean): void;
|
|
16
16
|
resetAdjustments(): void;
|
|
17
|
+
/** Update to Current Process: re-render the adjustments with the latest process (one undo step). */
|
|
18
|
+
upgradeProcess(): boolean;
|
|
17
19
|
setDepthMask(partial: Partial<DepthMaskOptions>): void;
|
|
18
20
|
resetDepthMask(): void;
|
|
19
21
|
addAnnotation(ann: CreateAnnotationPayload): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"imageEditorState.svelte.d.ts","sourceRoot":"","sources":["../../src/image-editor/imageEditorState.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,uBAAuB,EAC5B,KAAK,aAAa,EAClB,KAAK,0BAA0B,EAC/B,KAAK,UAAU,EAChB,MAAM,+BAA+B,CAAC;AAEvC,wBAAgB,yBAAyB,CAAC,OAAO,GAAE,kBAAuB;;;;;kBA0BxD,eAAe;kBAGf,OAAO,GAAG,IAAI;2BAGL,WAAW;;oBAMlB,MAAM;yBAGD,MAAM;;;4BASH,OAAO,CAAC,gBAAgB,CAAC;;
|
|
1
|
+
{"version":3,"file":"imageEditorState.svelte.d.ts","sourceRoot":"","sources":["../../src/image-editor/imageEditorState.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,uBAAuB,EAC5B,KAAK,aAAa,EAClB,KAAK,0BAA0B,EAC/B,KAAK,UAAU,EAChB,MAAM,+BAA+B,CAAC;AAEvC,wBAAgB,yBAAyB,CAAC,OAAO,GAAE,kBAAuB;;;;;kBA0BxD,eAAe;kBAGf,OAAO,GAAG,IAAI;2BAGL,WAAW;;oBAMlB,MAAM;yBAGD,MAAM;;;4BASH,OAAO,CAAC,gBAAgB,CAAC;;IAMjD,oGAAoG;;0BAI9E,OAAO,CAAC,gBAAgB,CAAC;;uBAM5B,uBAAuB;yBAGrB,MAAM,WAAW,OAAO,CAAC,UAAU,CAAC;yBAGpC,MAAM;;yBAMN,MAAM,GAAG,IAAI;;;;oBAYlB,MAAM;qBAGL,MAAM;;kBAMT,MAAM;gBAGR,UAAU;4BAGE,OAAO;mBAGhB,MAAM,GAAG,gBAAgB;qBAGvB,aAAa;kBAGhB,aAAa;;mBAMZ,0BAA0B;sBAGvB;QAAE,cAAc,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE;yBAG5C;QAAE,cAAc,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE;2BAG7C,IAAI,CAAC,aAAa,EAAE,QAAQ,GAAG,SAAS,CAAC;oCAGhC,MAAM;4CAGE,MAAM;IAG9C,8EAA8E;;EAKjF;AAED,MAAM,MAAM,mBAAmB,GAAG,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC"}
|
|
@@ -53,6 +53,10 @@ export function createReactiveImageEditor(options = {}) {
|
|
|
53
53
|
resetAdjustments() {
|
|
54
54
|
controller.resetAdjustments();
|
|
55
55
|
},
|
|
56
|
+
/** Update to Current Process: re-render the adjustments with the latest process (one undo step). */
|
|
57
|
+
upgradeProcess() {
|
|
58
|
+
return controller.upgradeProcess();
|
|
59
|
+
},
|
|
56
60
|
setDepthMask(partial) {
|
|
57
61
|
controller.setDepthMask(partial);
|
|
58
62
|
},
|
package/dist/index.d.ts
CHANGED
|
@@ -11,8 +11,8 @@ export * from "./history/index.js";
|
|
|
11
11
|
export * from "./fileImport.svelte.js";
|
|
12
12
|
export * from "./agentTools.svelte.js";
|
|
13
13
|
export * from "./outline.svelte.js";
|
|
14
|
-
export { DirtyTracker, createDirtyTracker, defaultIsEqual, HistoryManager, createHistoryManager, } from "@pixerate/editor";
|
|
15
|
-
export type { DirtyTrackerOptions, Command, HistoryState, HistoryManagerOptions, } from "@pixerate/editor";
|
|
14
|
+
export { DirtyTracker, createDirtyTracker, defaultIsEqual, HistoryManager, createHistoryManager, bindDirtyToHistory, withoutDirty, } from "@pixerate/editor";
|
|
15
|
+
export type { DirtyTrackerOptions, Command, HistoryState, HistoryManagerOptions, HistoryEntry, HistoryMark, MergedExecutionOptions, HistoryDirtyBinding, BindDirtyToHistoryOptions, } from "@pixerate/editor";
|
|
16
16
|
export type EditableTextNodeEditorProps = ComponentProps<typeof EditableTextNodeEditorComponent>;
|
|
17
17
|
export type BubbleMenuProps = ComponentProps<typeof BubbleMenuComponent>;
|
|
18
18
|
export type TemplateRendererProps = ComponentProps<typeof TemplateRendererComponent>;
|
|
@@ -28,4 +28,5 @@ export type { PromptValues, PromptDiagnostic, VariableFormField, } from "@pixera
|
|
|
28
28
|
export * from "./spreadsheet/index.js";
|
|
29
29
|
export * from "./image-editor/index.js";
|
|
30
30
|
export * from "./review/index.js";
|
|
31
|
+
export * from "./commands/index.js";
|
|
31
32
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAE7C,OAAO,KAAK,+BAA+B,MAAM,iCAAiC,CAAC;AACnF,OAAO,KAAK,mBAAmB,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,yBAAyB,MAAM,2BAA2B,CAAC;AACvE,OAAO,KAAK,qBAAqB,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,qBAAqB,MAAM,uBAAuB,CAAC;AAE/D,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mCAAmC,CAAC;AAClD,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AAEpC,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,oBAAoB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAE7C,OAAO,KAAK,+BAA+B,MAAM,iCAAiC,CAAC;AACnF,OAAO,KAAK,mBAAmB,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,yBAAyB,MAAM,2BAA2B,CAAC;AACvE,OAAO,KAAK,qBAAqB,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,qBAAqB,MAAM,uBAAuB,CAAC;AAE/D,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mCAAmC,CAAC;AAClD,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AAEpC,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,kBAAkB,EAClB,YAAY,GACb,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,mBAAmB,EACnB,OAAO,EACP,YAAY,EACZ,qBAAqB,EACrB,YAAY,EACZ,WAAW,EACX,sBAAsB,EACtB,mBAAmB,EACnB,yBAAyB,GAC1B,MAAM,kBAAkB,CAAC;AAG1B,MAAM,MAAM,2BAA2B,GAAG,cAAc,CACtD,OAAO,+BAA+B,CACvC,CAAC;AACF,MAAM,MAAM,eAAe,GAAG,cAAc,CAAC,OAAO,mBAAmB,CAAC,CAAC;AACzE,MAAM,MAAM,qBAAqB,GAAG,cAAc,CAChD,OAAO,yBAAyB,CACjC,CAAC;AACF,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAE7E,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChE,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAC7E,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAEhE,YAAY,EACV,QAAQ,EACR,eAAe,EACf,KAAK,EACL,SAAS,EACT,aAAa,EACb,qBAAqB,EACrB,YAAY,GACb,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAE1B,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ export * from "./history/index.js";
|
|
|
5
5
|
export * from "./fileImport.svelte.js";
|
|
6
6
|
export * from "./agentTools.svelte.js";
|
|
7
7
|
export * from "./outline.svelte.js";
|
|
8
|
-
export { DirtyTracker, createDirtyTracker, defaultIsEqual, HistoryManager, createHistoryManager, } from "@pixerate/editor";
|
|
8
|
+
export { DirtyTracker, createDirtyTracker, defaultIsEqual, HistoryManager, createHistoryManager, bindDirtyToHistory, withoutDirty, } from "@pixerate/editor";
|
|
9
9
|
export { default as EditableTextNodeEditor } from "./EditableTextNodeEditor.svelte";
|
|
10
10
|
export { default as BubbleMenu } from "./BubbleMenu.svelte";
|
|
11
11
|
export { default as TemplateRenderer } from "./TemplateRenderer.svelte";
|
|
@@ -14,3 +14,4 @@ export { default as OutlinePanel } from "./OutlinePanel.svelte";
|
|
|
14
14
|
export * from "./spreadsheet/index.js";
|
|
15
15
|
export * from "./image-editor/index.js";
|
|
16
16
|
export * from "./review/index.js";
|
|
17
|
+
export * from "./commands/index.js";
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
type CellRange,
|
|
13
13
|
type SpreadsheetMenuItem,
|
|
14
14
|
type SpreadsheetViewColumn,
|
|
15
|
-
type SpreadsheetViewRow
|
|
15
|
+
type SpreadsheetViewRow,
|
|
16
|
+
formatCellDisplay
|
|
16
17
|
} from '@pixerate/editor/spreadsheet';
|
|
17
18
|
import FormulaBar from './FormulaBar.svelte';
|
|
18
19
|
import SpreadsheetContextMenu from './SpreadsheetContextMenu.svelte';
|
|
@@ -589,7 +590,7 @@
|
|
|
589
590
|
class="truncate block max-w-full {cell.error ? 'text-destructive font-semibold' : ''}"
|
|
590
591
|
title={cell.error ? (cell.errorMessage ?? cell.error) : undefined}
|
|
591
592
|
>
|
|
592
|
-
{
|
|
593
|
+
{formatCellDisplay(cell)}
|
|
593
594
|
</span>
|
|
594
595
|
{/if}
|
|
595
596
|
{#if activeSpill && rangeContains(activeSpill.range, rIdx, cIdx)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpreadsheetEditor.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/SpreadsheetEditor.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAMH,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,QAAQ,
|
|
1
|
+
{"version":3,"file":"SpreadsheetEditor.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/SpreadsheetEditor.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAMH,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,QAAQ,EAMd,MAAM,8BAA8B,CAAC;AAKxC,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAIlE,UAAU,KAAK;IACb,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EACf,OAAO,CAAC,CAAC,QAAQ,EAAE,iBAAiB,EAAE,cAAc,CAAC,CAAC,GACtD,OAAO,CAAC,CAAC;QAAE,GAAG,EAAE,cAAc,CAAC;QAAC,GAAG,EAAE,iBAAiB,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC,CAAC;IAC/E,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACvD,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzD;AA+hBH,QAAA,MAAM,iBAAiB,2CAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
|
|
@@ -1 +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;;
|
|
1
|
+
{"version":3,"file":"spreadsheet.svelte.d.ts","sourceRoot":"","sources":["../../src/spreadsheet/spreadsheet.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EAErB,KAAK,4BAA4B,EACjC,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC3B,MAAM,8BAA8B,CAAC;AAEtC,wBAAgB,yBAAyB,CAAC,OAAO,GAAE,4BAAiC;;aAmLy20B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBA/Gt60B,MAAM;;mBAMX,MAAM,SAAS,MAAM,GAAG,QAAQ;wBAG3B,MAAM,SAAS,MAAM,OAAO,MAAM;oBAItC,MAAM,OAAO,MAAM;uBAKhB,SAAS;uBAIT,MAAM,QAAQ,MAAM,eAAe,MAAM;wBAMxC,MAAM;;oBAWV,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO;wBAK5B,MAAM,WAAW,OAAO,CAAC,iBAAiB,CAAC;wBAI3C,MAAM;qBAIT,MAAM,WAAW,OAAO,CAAC,cAAc,CAAC;qBAIxC,MAAM;0BAID,MAAM,SAAS,MAAM;8BAIjB,MAAM,gBAAgB,MAAM;2BAI/B,mBAAmB;;2BAanB,qBAAqB;6BAInB,MAAM,GAAG,SAAS;;wBAQvB,SAAS,GAAG,IAAI;wBAGhB,MAAM;;;EAc7B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pixerate/editor-svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "Svelte bindings and prompt/rich-text components for @pixerate/editor",
|
|
5
5
|
"author": "Pixerate",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,6 +33,11 @@
|
|
|
33
33
|
"svelte": "./dist/image-editor/index.js",
|
|
34
34
|
"default": "./dist/image-editor/index.js"
|
|
35
35
|
},
|
|
36
|
+
"./commands": {
|
|
37
|
+
"types": "./dist/commands/index.d.ts",
|
|
38
|
+
"svelte": "./dist/commands/index.js",
|
|
39
|
+
"default": "./dist/commands/index.js"
|
|
40
|
+
},
|
|
36
41
|
"./package.json": "./package.json"
|
|
37
42
|
},
|
|
38
43
|
"typesVersions": {
|
|
@@ -45,6 +50,9 @@
|
|
|
45
50
|
],
|
|
46
51
|
"image-editor": [
|
|
47
52
|
"./dist/image-editor/index.d.ts"
|
|
53
|
+
],
|
|
54
|
+
"commands": [
|
|
55
|
+
"./dist/commands/index.d.ts"
|
|
48
56
|
]
|
|
49
57
|
}
|
|
50
58
|
},
|
|
@@ -59,7 +67,7 @@
|
|
|
59
67
|
"@tiptap/extension-bubble-menu": "^2.11.5",
|
|
60
68
|
"@tiptap/extension-placeholder": "^2.11.5",
|
|
61
69
|
"@tiptap/starter-kit": "^2.11.5",
|
|
62
|
-
"@pixerate/editor": "0.
|
|
70
|
+
"@pixerate/editor": "0.23.0"
|
|
63
71
|
},
|
|
64
72
|
"peerDependencies": {
|
|
65
73
|
"@dagrejs/dagre": "^1.1.4",
|