@tangle-network/agent-app 0.27.2 → 0.28.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/dist/DesignCanvas-AOIVN3SJ.js +12 -0
- package/dist/DesignCanvasEditor-TN7CWUJW.js +13 -0
- package/dist/{TimelineEditor-JDG54OBP.js → TimelineEditor-Z7C6BFP5.js} +2 -2
- package/dist/{apply-Cp8c3K9D.d.ts → apply-Gk4raT2j.d.ts} +3 -1
- package/dist/{chunk-AFDROJ64.js → chunk-2QI7XV2T.js} +1 -1
- package/dist/chunk-2QI7XV2T.js.map +1 -0
- package/dist/{chunk-LUE4HO5C.js → chunk-4IQMTTNE.js} +10 -10
- package/dist/chunk-4IQMTTNE.js.map +1 -0
- package/dist/{chunk-HABVCJJT.js → chunk-7I37CO5D.js} +271 -404
- package/dist/chunk-7I37CO5D.js.map +1 -0
- package/dist/{chunk-5RT6KY4G.js → chunk-GQRL6VNU.js} +1 -1
- package/dist/chunk-GQRL6VNU.js.map +1 -0
- package/dist/{chunk-SCG5JJ4C.js → chunk-HFC4BTWJ.js} +32 -4
- package/dist/chunk-HFC4BTWJ.js.map +1 -0
- package/dist/{chunk-7QCIYDGC.js → chunk-IOREXWLM.js} +2 -2
- package/dist/chunk-J7JNV5BH.js +14 -0
- package/dist/chunk-J7JNV5BH.js.map +1 -0
- package/dist/{chunk-6UOE5CTA.js → chunk-JT6HHO5P.js} +5 -10
- package/dist/chunk-JT6HHO5P.js.map +1 -0
- package/dist/{chunk-JZAJE3JL.js → chunk-M2EBUDZ7.js} +19 -5
- package/dist/chunk-M2EBUDZ7.js.map +1 -0
- package/dist/{chunk-RJ2ZHK5D.js → chunk-S6WS2B32.js} +132 -7
- package/dist/chunk-S6WS2B32.js.map +1 -0
- package/dist/chunk-SQV7NUEM.js +136 -0
- package/dist/chunk-SQV7NUEM.js.map +1 -0
- package/dist/chunk-UAKFCMWK.js +1 -0
- package/dist/chunk-UAKFCMWK.js.map +1 -0
- package/dist/chunk-V5XZKHCL.js +296 -0
- package/dist/chunk-V5XZKHCL.js.map +1 -0
- package/dist/chunk-XWJXZ6WE.js +604 -0
- package/dist/chunk-XWJXZ6WE.js.map +1 -0
- package/dist/chunk-Y2SZVW35.js +125 -0
- package/dist/chunk-Y2SZVW35.js.map +1 -0
- package/dist/{chunk-27LQXQSS.js → chunk-YEWTVDDT.js} +224 -767
- package/dist/chunk-YEWTVDDT.js.map +1 -0
- package/dist/{chunk-UDXMR3AD.js → chunk-YNALYIQ3.js} +56 -18
- package/dist/chunk-YNALYIQ3.js.map +1 -0
- package/dist/command-stack-CkjelfK_.d.ts +267 -0
- package/dist/design-canvas/drizzle.d.ts +2 -2
- package/dist/design-canvas/index.d.ts +7 -6
- package/dist/design-canvas/index.js +3 -2
- package/dist/design-canvas-react/engine.d.ts +349 -0
- package/dist/design-canvas-react/engine.js +86 -0
- package/dist/design-canvas-react/engine.js.map +1 -0
- package/dist/design-canvas-react/index.d.ts +69 -649
- package/dist/design-canvas-react/index.js +84 -173
- package/dist/design-canvas-react/index.js.map +1 -1
- package/dist/design-canvas-react/lazy.d.ts +6 -0
- package/dist/design-canvas-react/lazy.js +9 -0
- package/dist/design-canvas-react/lazy.js.map +1 -0
- package/dist/{export-presets-Dl5Aa5xj.d.ts → export-presets-DAsU5Wal.d.ts} +2 -143
- package/dist/flow-types-Cb_AblZs.d.ts +25 -0
- package/dist/index.d.ts +11 -8
- package/dist/index.js +21 -8
- package/dist/lazy-BHHqS8-j.d.ts +72 -0
- package/dist/missions/index.d.ts +12 -0
- package/dist/missions/index.js +1 -1
- package/dist/{model-BHLN208Z.d.ts → model-BBwyOuWG.d.ts} +3 -1
- package/dist/operations-DLIvvD00.d.ts +144 -0
- package/dist/platform/index.js +1 -1
- package/dist/runtime/index.d.ts +33 -33
- package/dist/runtime/index.js +1 -1
- package/dist/sequences/index.d.ts +1 -1
- package/dist/sequences/index.js +2 -1
- package/dist/sequences-react/index.d.ts +15 -1
- package/dist/sequences-react/index.js +2 -2
- package/dist/{store-CUStmtdH.d.ts → store-CFyxgTlD.d.ts} +1 -1
- package/dist/theme/index.d.ts +80 -0
- package/dist/theme/index.js +14 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme/tailwind-preset.d.ts +65 -0
- package/dist/theme/tailwind-preset.js +33 -0
- package/dist/theme/tailwind-preset.js.map +1 -0
- package/dist/theme/tokens.css +95 -0
- package/dist/trace/index.d.ts +2 -18
- package/dist/trace/index.js +2 -2
- package/dist/web/index.d.ts +25 -2
- package/dist/web/index.js +3 -1
- package/dist/web-react/index.d.ts +71 -31
- package/dist/web-react/index.js +625 -486
- package/dist/web-react/index.js.map +1 -1
- package/package.json +28 -3
- package/dist/DesignCanvas-73IUJJUP.js +0 -10
- package/dist/DesignCanvasEditor-6F2UTOSW.js +0 -9
- package/dist/chunk-27LQXQSS.js.map +0 -1
- package/dist/chunk-5RT6KY4G.js.map +0 -1
- package/dist/chunk-6UOE5CTA.js.map +0 -1
- package/dist/chunk-AFDROJ64.js.map +0 -1
- package/dist/chunk-HABVCJJT.js.map +0 -1
- package/dist/chunk-JZAJE3JL.js.map +0 -1
- package/dist/chunk-LUE4HO5C.js.map +0 -1
- package/dist/chunk-RJ2ZHK5D.js.map +0 -1
- package/dist/chunk-SCG5JJ4C.js.map +0 -1
- package/dist/chunk-UDXMR3AD.js.map +0 -1
- /package/dist/{DesignCanvas-73IUJJUP.js.map → DesignCanvas-AOIVN3SJ.js.map} +0 -0
- /package/dist/{DesignCanvasEditor-6F2UTOSW.js.map → DesignCanvasEditor-TN7CWUJW.js.map} +0 -0
- /package/dist/{TimelineEditor-JDG54OBP.js.map → TimelineEditor-Z7C6BFP5.js.map} +0 -0
- /package/dist/{chunk-7QCIYDGC.js.map → chunk-IOREXWLM.js.map} +0 -0
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
import {
|
|
2
|
+
applySceneOperation,
|
|
3
|
+
applySceneOperations,
|
|
4
|
+
requireElement,
|
|
5
|
+
requirePage
|
|
6
|
+
} from "./chunk-M2EBUDZ7.js";
|
|
7
|
+
|
|
8
|
+
// src/design-canvas-react/engine/command-stack.ts
|
|
9
|
+
var SCENE_COMMAND_HISTORY_LIMIT = 200;
|
|
10
|
+
function createSceneCommandStack(document, activePageId) {
|
|
11
|
+
let state = {
|
|
12
|
+
document,
|
|
13
|
+
activePageId,
|
|
14
|
+
selectedElementIds: [],
|
|
15
|
+
zoom: 1,
|
|
16
|
+
panX: 0,
|
|
17
|
+
panY: 0,
|
|
18
|
+
gridEnabled: false,
|
|
19
|
+
gridSize: 10,
|
|
20
|
+
snapEnabled: true,
|
|
21
|
+
showRulers: true,
|
|
22
|
+
showBleed: false
|
|
23
|
+
};
|
|
24
|
+
const undoStack = [];
|
|
25
|
+
const redoStack = [];
|
|
26
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
27
|
+
const notify = () => {
|
|
28
|
+
for (const listener of [...listeners]) listener();
|
|
29
|
+
};
|
|
30
|
+
return {
|
|
31
|
+
execute(command) {
|
|
32
|
+
state = command.execute(state);
|
|
33
|
+
undoStack.push(command);
|
|
34
|
+
if (undoStack.length > SCENE_COMMAND_HISTORY_LIMIT) {
|
|
35
|
+
undoStack.splice(0, undoStack.length - SCENE_COMMAND_HISTORY_LIMIT);
|
|
36
|
+
}
|
|
37
|
+
redoStack.length = 0;
|
|
38
|
+
notify();
|
|
39
|
+
},
|
|
40
|
+
// Both transforms run BEFORE the stacks move: a throwing transform (e.g.
|
|
41
|
+
// missing element after reset()) leaves history and state exactly as they
|
|
42
|
+
// were. The entry is never silently destroyed — the caller can retry after
|
|
43
|
+
// the next server refresh restores the target.
|
|
44
|
+
undo() {
|
|
45
|
+
const command = undoStack[undoStack.length - 1];
|
|
46
|
+
if (!command) throw new Error("nothing to undo \u2014 guard with canUndo() before calling undo()");
|
|
47
|
+
state = command.undo(state);
|
|
48
|
+
undoStack.pop();
|
|
49
|
+
redoStack.push(command);
|
|
50
|
+
notify();
|
|
51
|
+
return command;
|
|
52
|
+
},
|
|
53
|
+
redo() {
|
|
54
|
+
const command = redoStack[redoStack.length - 1];
|
|
55
|
+
if (!command) throw new Error("nothing to redo \u2014 guard with canRedo() before calling redo()");
|
|
56
|
+
state = command.execute(state);
|
|
57
|
+
redoStack.pop();
|
|
58
|
+
undoStack.push(command);
|
|
59
|
+
notify();
|
|
60
|
+
return command;
|
|
61
|
+
},
|
|
62
|
+
canUndo() {
|
|
63
|
+
return undoStack.length > 0;
|
|
64
|
+
},
|
|
65
|
+
canRedo() {
|
|
66
|
+
return redoStack.length > 0;
|
|
67
|
+
},
|
|
68
|
+
subscribe(listener) {
|
|
69
|
+
listeners.add(listener);
|
|
70
|
+
return () => {
|
|
71
|
+
listeners.delete(listener);
|
|
72
|
+
};
|
|
73
|
+
},
|
|
74
|
+
getState() {
|
|
75
|
+
return state;
|
|
76
|
+
},
|
|
77
|
+
setView(patch) {
|
|
78
|
+
state = { ...state, ...patch };
|
|
79
|
+
notify();
|
|
80
|
+
},
|
|
81
|
+
// A persisted UNDO rejected: the server still has `command` applied, but the
|
|
82
|
+
// local undo already removed it (and a later execute may have cleared the
|
|
83
|
+
// redo stack). Deterministically re-converge — mirror of `rollback`, in the
|
|
84
|
+
// forward direction: re-apply the command's FORWARD transform to current
|
|
85
|
+
// state and ensure it lives on the undo stack (so a later undo can remove it
|
|
86
|
+
// again). Idempotent: if the command is already on the undo stack (the undo
|
|
87
|
+
// never actually left local history), this is a no-op. For disjoint edits the
|
|
88
|
+
// forward transform commutes past commands executed while the undo was
|
|
89
|
+
// pending, so their net effect is preserved.
|
|
90
|
+
reexecute(command) {
|
|
91
|
+
if (undoStack.includes(command)) return;
|
|
92
|
+
state = command.execute(state);
|
|
93
|
+
const redoIdx = redoStack.lastIndexOf(command);
|
|
94
|
+
if (redoIdx !== -1) redoStack.splice(redoIdx, 1);
|
|
95
|
+
undoStack.push(command);
|
|
96
|
+
notify();
|
|
97
|
+
},
|
|
98
|
+
// A persisted REDO rejected: the server does NOT have `command` applied, but
|
|
99
|
+
// the local redo just applied it forward and put it on the undo stack.
|
|
100
|
+
// Re-apply its INVERSE and move it to the redo stack — the redo-side mirror
|
|
101
|
+
// of `reexecute`. No-op if the command is not on the undo stack.
|
|
102
|
+
reundo(command) {
|
|
103
|
+
const undoIdx = undoStack.lastIndexOf(command);
|
|
104
|
+
if (undoIdx === -1) return;
|
|
105
|
+
state = command.undo(state);
|
|
106
|
+
undoStack.splice(undoIdx, 1);
|
|
107
|
+
if (!redoStack.includes(command)) redoStack.push(command);
|
|
108
|
+
notify();
|
|
109
|
+
},
|
|
110
|
+
rollback(command) {
|
|
111
|
+
const idx = undoStack.lastIndexOf(command);
|
|
112
|
+
if (idx === -1) return;
|
|
113
|
+
state = command.undo(state);
|
|
114
|
+
undoStack.splice(idx, 1);
|
|
115
|
+
redoStack.length = 0;
|
|
116
|
+
notify();
|
|
117
|
+
},
|
|
118
|
+
/** Rebase onto a server-refreshed document. History survives; selection
|
|
119
|
+
* drops ids the refresh removed so view state never dangles. */
|
|
120
|
+
reset(newDocument) {
|
|
121
|
+
const liveElementIds = /* @__PURE__ */ new Set();
|
|
122
|
+
for (const page of newDocument.pages) {
|
|
123
|
+
collectElementIds(page.elements, liveElementIds);
|
|
124
|
+
}
|
|
125
|
+
const activePageExists = newDocument.pages.some((p) => p.id === state.activePageId);
|
|
126
|
+
const activePageId2 = activePageExists ? state.activePageId : newDocument.pages[0]?.id ?? state.activePageId;
|
|
127
|
+
state = {
|
|
128
|
+
...state,
|
|
129
|
+
document: newDocument,
|
|
130
|
+
activePageId: activePageId2,
|
|
131
|
+
selectedElementIds: state.selectedElementIds.filter((id) => liveElementIds.has(id))
|
|
132
|
+
};
|
|
133
|
+
notify();
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function collectElementIds(elements, ids) {
|
|
138
|
+
for (const el of elements) {
|
|
139
|
+
ids.add(el.id);
|
|
140
|
+
if (el.kind === "group" && Array.isArray(el.children)) {
|
|
141
|
+
collectElementIds(el.children, ids);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// src/design-canvas-react/engine/commands.ts
|
|
147
|
+
function applyOps(state, ops) {
|
|
148
|
+
return { ...state, document: applySceneOperations(state.document, ops) };
|
|
149
|
+
}
|
|
150
|
+
function applyOp(state, op) {
|
|
151
|
+
return { ...state, document: applySceneOperation(state.document, op) };
|
|
152
|
+
}
|
|
153
|
+
function addElementCommand(input) {
|
|
154
|
+
const addOp = {
|
|
155
|
+
type: "add_element",
|
|
156
|
+
pageId: input.pageId,
|
|
157
|
+
element: structuredClone(input.element),
|
|
158
|
+
...input.index !== void 0 ? { index: input.index } : {},
|
|
159
|
+
...input.parentGroupId !== void 0 ? { parentGroupId: input.parentGroupId } : {}
|
|
160
|
+
};
|
|
161
|
+
const deleteOp = {
|
|
162
|
+
type: "delete_element",
|
|
163
|
+
pageId: input.pageId,
|
|
164
|
+
elementId: input.element.id
|
|
165
|
+
};
|
|
166
|
+
return {
|
|
167
|
+
label: `Add ${input.element.kind}`,
|
|
168
|
+
execute: (state) => applyOp(state, addOp),
|
|
169
|
+
undo: (state) => applyOp(state, deleteOp),
|
|
170
|
+
operations: () => [structuredClone(addOp)],
|
|
171
|
+
inverseOperations: () => [structuredClone(deleteOp)]
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function setAttrsCommand(input) {
|
|
175
|
+
const forwardOp = {
|
|
176
|
+
type: "set_attrs",
|
|
177
|
+
pageId: input.pageId,
|
|
178
|
+
elementId: input.elementId,
|
|
179
|
+
attrs: structuredClone(input.attrs)
|
|
180
|
+
};
|
|
181
|
+
const inverseOp = {
|
|
182
|
+
type: "set_attrs",
|
|
183
|
+
pageId: input.pageId,
|
|
184
|
+
elementId: input.elementId,
|
|
185
|
+
attrs: structuredClone(input.priorAttrs)
|
|
186
|
+
};
|
|
187
|
+
return {
|
|
188
|
+
label: "Edit element",
|
|
189
|
+
execute: (state) => applyOp(state, forwardOp),
|
|
190
|
+
undo: (state) => applyOp(state, inverseOp),
|
|
191
|
+
operations: () => [structuredClone(forwardOp)],
|
|
192
|
+
inverseOperations: () => [structuredClone(inverseOp)]
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function multiSetAttrsCommand(entries) {
|
|
196
|
+
if (entries.length === 0) throw new Error("multiSetAttrsCommand: entries must not be empty");
|
|
197
|
+
const forwardOps = entries.map((e) => ({
|
|
198
|
+
type: "set_attrs",
|
|
199
|
+
pageId: e.pageId,
|
|
200
|
+
elementId: e.elementId,
|
|
201
|
+
attrs: structuredClone(e.attrs)
|
|
202
|
+
}));
|
|
203
|
+
const inverseOps = entries.map((e) => ({
|
|
204
|
+
type: "set_attrs",
|
|
205
|
+
pageId: e.pageId,
|
|
206
|
+
elementId: e.elementId,
|
|
207
|
+
attrs: structuredClone(e.priorAttrs)
|
|
208
|
+
}));
|
|
209
|
+
return {
|
|
210
|
+
label: `Edit ${entries.length} elements`,
|
|
211
|
+
execute: (state) => applyOps(state, forwardOps),
|
|
212
|
+
undo: (state) => applyOps(state, inverseOps),
|
|
213
|
+
operations: () => structuredClone(forwardOps),
|
|
214
|
+
inverseOperations: () => structuredClone(inverseOps)
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
function reorderElementCommand(input) {
|
|
218
|
+
let capturedFromIndex = null;
|
|
219
|
+
const forwardOp = {
|
|
220
|
+
type: "reorder_element",
|
|
221
|
+
pageId: input.pageId,
|
|
222
|
+
elementId: input.elementId,
|
|
223
|
+
toIndex: input.toIndex
|
|
224
|
+
};
|
|
225
|
+
return {
|
|
226
|
+
label: "Reorder element",
|
|
227
|
+
execute: (state) => {
|
|
228
|
+
if (capturedFromIndex === null) {
|
|
229
|
+
const page = requirePage(state.document, input.pageId);
|
|
230
|
+
const { index } = requireElement(page, input.elementId);
|
|
231
|
+
capturedFromIndex = index;
|
|
232
|
+
}
|
|
233
|
+
return applyOp(state, forwardOp);
|
|
234
|
+
},
|
|
235
|
+
undo: (state) => {
|
|
236
|
+
if (capturedFromIndex === null) {
|
|
237
|
+
throw new Error("reorderElementCommand: undo called before execute");
|
|
238
|
+
}
|
|
239
|
+
return applyOp(state, {
|
|
240
|
+
type: "reorder_element",
|
|
241
|
+
pageId: input.pageId,
|
|
242
|
+
elementId: input.elementId,
|
|
243
|
+
toIndex: capturedFromIndex
|
|
244
|
+
});
|
|
245
|
+
},
|
|
246
|
+
operations: () => [structuredClone(forwardOp)],
|
|
247
|
+
inverseOperations: () => {
|
|
248
|
+
if (capturedFromIndex === null) {
|
|
249
|
+
throw new Error("reorderElementCommand: inverseOperations called before execute");
|
|
250
|
+
}
|
|
251
|
+
return [{
|
|
252
|
+
type: "reorder_element",
|
|
253
|
+
pageId: input.pageId,
|
|
254
|
+
elementId: input.elementId,
|
|
255
|
+
toIndex: capturedFromIndex
|
|
256
|
+
}];
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
function deleteElementCommand(input) {
|
|
261
|
+
const page = requirePage(input.document, input.pageId);
|
|
262
|
+
const { element, owner, index } = requireElement(page, input.elementId);
|
|
263
|
+
const snapshot = structuredClone(element);
|
|
264
|
+
const parentGroupId = findParentGroupId(page, owner);
|
|
265
|
+
const deleteOp = {
|
|
266
|
+
type: "delete_element",
|
|
267
|
+
pageId: input.pageId,
|
|
268
|
+
elementId: input.elementId
|
|
269
|
+
};
|
|
270
|
+
const addOp = {
|
|
271
|
+
type: "add_element",
|
|
272
|
+
pageId: input.pageId,
|
|
273
|
+
element: snapshot,
|
|
274
|
+
index,
|
|
275
|
+
...parentGroupId !== void 0 ? { parentGroupId } : {}
|
|
276
|
+
};
|
|
277
|
+
return {
|
|
278
|
+
label: `Delete ${element.kind}`,
|
|
279
|
+
execute: (state) => {
|
|
280
|
+
const next = applyOp(state, deleteOp);
|
|
281
|
+
return {
|
|
282
|
+
...next,
|
|
283
|
+
selectedElementIds: next.selectedElementIds.filter((id) => id !== input.elementId)
|
|
284
|
+
};
|
|
285
|
+
},
|
|
286
|
+
undo: (state) => applyOp(state, addOp),
|
|
287
|
+
operations: () => [structuredClone(deleteOp)],
|
|
288
|
+
inverseOperations: () => [structuredClone(addOp)]
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
function findParentGroupId(page, owner) {
|
|
292
|
+
if (owner === page.elements) return void 0;
|
|
293
|
+
return findGroupWithChildren(page.elements, owner);
|
|
294
|
+
}
|
|
295
|
+
function findGroupWithChildren(elements, target) {
|
|
296
|
+
for (const el of elements) {
|
|
297
|
+
if (el.kind === "group") {
|
|
298
|
+
if (el.children === target) return el.id;
|
|
299
|
+
const found = findGroupWithChildren(el.children, target);
|
|
300
|
+
if (found !== void 0) return found;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return void 0;
|
|
304
|
+
}
|
|
305
|
+
function groupElementsCommand(input) {
|
|
306
|
+
if (input.elementIds.length < 2) {
|
|
307
|
+
throw new Error("groupElementsCommand: requires \u2265 2 elementIds");
|
|
308
|
+
}
|
|
309
|
+
const groupOp = {
|
|
310
|
+
type: "group_elements",
|
|
311
|
+
pageId: input.pageId,
|
|
312
|
+
elementIds: input.elementIds.slice(),
|
|
313
|
+
groupId: input.groupId,
|
|
314
|
+
...input.name !== void 0 ? { name: input.name } : {}
|
|
315
|
+
};
|
|
316
|
+
const ungroupOp = {
|
|
317
|
+
type: "ungroup_element",
|
|
318
|
+
pageId: input.pageId,
|
|
319
|
+
groupId: input.groupId
|
|
320
|
+
};
|
|
321
|
+
return {
|
|
322
|
+
label: `Group ${input.elementIds.length} elements`,
|
|
323
|
+
execute: (state) => {
|
|
324
|
+
const next = applyOp(state, groupOp);
|
|
325
|
+
return {
|
|
326
|
+
...next,
|
|
327
|
+
selectedElementIds: [input.groupId]
|
|
328
|
+
};
|
|
329
|
+
},
|
|
330
|
+
undo: (state) => {
|
|
331
|
+
const next = applyOp(state, ungroupOp);
|
|
332
|
+
return { ...next, selectedElementIds: input.elementIds.slice() };
|
|
333
|
+
},
|
|
334
|
+
operations: () => [structuredClone(groupOp)],
|
|
335
|
+
inverseOperations: () => [structuredClone(ungroupOp)]
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
function ungroupElementCommand(input) {
|
|
339
|
+
const page = requirePage(input.document, input.pageId);
|
|
340
|
+
const { element } = requireElement(page, input.groupId);
|
|
341
|
+
if (element.kind !== "group") {
|
|
342
|
+
throw new Error(`ungroupElementCommand: element ${input.groupId} is kind ${element.kind}, not group`);
|
|
343
|
+
}
|
|
344
|
+
const childIds = element.children.map((c) => c.id);
|
|
345
|
+
const ungroupOp = {
|
|
346
|
+
type: "ungroup_element",
|
|
347
|
+
pageId: input.pageId,
|
|
348
|
+
groupId: input.groupId
|
|
349
|
+
};
|
|
350
|
+
const regroupOp = {
|
|
351
|
+
type: "group_elements",
|
|
352
|
+
pageId: input.pageId,
|
|
353
|
+
elementIds: childIds,
|
|
354
|
+
groupId: input.groupId,
|
|
355
|
+
name: element.name
|
|
356
|
+
};
|
|
357
|
+
return {
|
|
358
|
+
label: `Ungroup`,
|
|
359
|
+
execute: (state) => {
|
|
360
|
+
const next = applyOp(state, ungroupOp);
|
|
361
|
+
return { ...next, selectedElementIds: childIds.slice() };
|
|
362
|
+
},
|
|
363
|
+
undo: (state) => {
|
|
364
|
+
const next = applyOp(state, regroupOp);
|
|
365
|
+
return { ...next, selectedElementIds: [input.groupId] };
|
|
366
|
+
},
|
|
367
|
+
operations: () => [structuredClone(ungroupOp)],
|
|
368
|
+
inverseOperations: () => [structuredClone(regroupOp)]
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
function addPageCommand(input) {
|
|
372
|
+
const addOp = {
|
|
373
|
+
type: "add_page",
|
|
374
|
+
pageId: input.pageId,
|
|
375
|
+
...input.options !== void 0 ? { options: input.options } : {},
|
|
376
|
+
...input.index !== void 0 ? { index: input.index } : {}
|
|
377
|
+
};
|
|
378
|
+
const deleteOp = { type: "delete_page", pageId: input.pageId };
|
|
379
|
+
return {
|
|
380
|
+
label: "Add page",
|
|
381
|
+
execute: (state) => {
|
|
382
|
+
const next = applyOp(state, addOp);
|
|
383
|
+
return { ...next, activePageId: input.pageId };
|
|
384
|
+
},
|
|
385
|
+
undo: (state) => {
|
|
386
|
+
const next = applyOp(state, deleteOp);
|
|
387
|
+
const activeExists = next.document.pages.some((p) => p.id === next.activePageId);
|
|
388
|
+
return activeExists ? next : { ...next, activePageId: next.document.pages[0].id };
|
|
389
|
+
},
|
|
390
|
+
operations: () => [structuredClone(addOp)],
|
|
391
|
+
inverseOperations: () => [structuredClone(deleteOp)]
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
function duplicatePageCommand(input) {
|
|
395
|
+
requirePage(input.document, input.sourcePageId);
|
|
396
|
+
const dupOp = {
|
|
397
|
+
type: "duplicate_page",
|
|
398
|
+
sourcePageId: input.sourcePageId,
|
|
399
|
+
pageId: input.pageId
|
|
400
|
+
};
|
|
401
|
+
const deleteOp = { type: "delete_page", pageId: input.pageId };
|
|
402
|
+
return {
|
|
403
|
+
label: "Duplicate page",
|
|
404
|
+
execute: (state) => {
|
|
405
|
+
const next = applyOp(state, dupOp);
|
|
406
|
+
return { ...next, activePageId: input.pageId };
|
|
407
|
+
},
|
|
408
|
+
undo: (state) => {
|
|
409
|
+
const next = applyOp(state, deleteOp);
|
|
410
|
+
const activeExists = next.document.pages.some((p) => p.id === next.activePageId);
|
|
411
|
+
return activeExists ? next : { ...next, activePageId: input.sourcePageId };
|
|
412
|
+
},
|
|
413
|
+
operations: () => [structuredClone(dupOp)],
|
|
414
|
+
inverseOperations: () => [structuredClone(deleteOp)]
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
function deletePageCommand(input) {
|
|
418
|
+
if (input.document.pages.length <= 1) {
|
|
419
|
+
throw new Error("deletePageCommand: cannot delete the last page");
|
|
420
|
+
}
|
|
421
|
+
const page = requirePage(input.document, input.pageId);
|
|
422
|
+
const currentIndex = input.document.pages.findIndex((p) => p.id === input.pageId);
|
|
423
|
+
const snapshot = structuredClone(page);
|
|
424
|
+
const deleteOp = { type: "delete_page", pageId: input.pageId };
|
|
425
|
+
function buildRestoreOps() {
|
|
426
|
+
const ops = [
|
|
427
|
+
{
|
|
428
|
+
type: "add_page",
|
|
429
|
+
pageId: snapshot.id,
|
|
430
|
+
options: {
|
|
431
|
+
name: snapshot.name,
|
|
432
|
+
width: snapshot.width,
|
|
433
|
+
height: snapshot.height,
|
|
434
|
+
background: snapshot.background
|
|
435
|
+
},
|
|
436
|
+
index: currentIndex
|
|
437
|
+
}
|
|
438
|
+
];
|
|
439
|
+
if (snapshot.bleed) {
|
|
440
|
+
ops.push({ type: "set_page_props", pageId: snapshot.id, bleed: snapshot.bleed });
|
|
441
|
+
}
|
|
442
|
+
if (snapshot.guides.vertical.length > 0 || snapshot.guides.horizontal.length > 0) {
|
|
443
|
+
ops.push({ type: "set_page_guides", pageId: snapshot.id, guides: snapshot.guides });
|
|
444
|
+
}
|
|
445
|
+
for (let i = 0; i < snapshot.elements.length; i++) {
|
|
446
|
+
ops.push({
|
|
447
|
+
type: "add_element",
|
|
448
|
+
pageId: snapshot.id,
|
|
449
|
+
element: structuredClone(snapshot.elements[i]),
|
|
450
|
+
index: i
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
return ops;
|
|
454
|
+
}
|
|
455
|
+
return {
|
|
456
|
+
label: "Delete page",
|
|
457
|
+
execute: (state) => {
|
|
458
|
+
const next = applyOp(state, deleteOp);
|
|
459
|
+
const activeExists = next.document.pages.some((p) => p.id === next.activePageId);
|
|
460
|
+
if (activeExists) return next;
|
|
461
|
+
const fallbackIndex = Math.min(currentIndex, next.document.pages.length - 1);
|
|
462
|
+
return { ...next, activePageId: next.document.pages[fallbackIndex].id };
|
|
463
|
+
},
|
|
464
|
+
undo: (state) => {
|
|
465
|
+
const next = applyOps(state, buildRestoreOps());
|
|
466
|
+
return { ...next, activePageId: input.pageId };
|
|
467
|
+
},
|
|
468
|
+
operations: () => [structuredClone(deleteOp)],
|
|
469
|
+
inverseOperations: () => buildRestoreOps()
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
function reorderPageCommand(input) {
|
|
473
|
+
let capturedFromIndex = null;
|
|
474
|
+
const forwardOp = {
|
|
475
|
+
type: "reorder_page",
|
|
476
|
+
pageId: input.pageId,
|
|
477
|
+
toIndex: input.toIndex
|
|
478
|
+
};
|
|
479
|
+
return {
|
|
480
|
+
label: "Reorder page",
|
|
481
|
+
execute: (state) => {
|
|
482
|
+
if (capturedFromIndex === null) {
|
|
483
|
+
capturedFromIndex = state.document.pages.findIndex((p) => p.id === input.pageId);
|
|
484
|
+
if (capturedFromIndex === -1) throw new Error(`reorderPageCommand: page ${input.pageId} not found`);
|
|
485
|
+
}
|
|
486
|
+
return applyOp(state, forwardOp);
|
|
487
|
+
},
|
|
488
|
+
undo: (state) => {
|
|
489
|
+
if (capturedFromIndex === null) throw new Error("reorderPageCommand: undo called before execute");
|
|
490
|
+
return applyOp(state, {
|
|
491
|
+
type: "reorder_page",
|
|
492
|
+
pageId: input.pageId,
|
|
493
|
+
toIndex: capturedFromIndex
|
|
494
|
+
});
|
|
495
|
+
},
|
|
496
|
+
operations: () => [structuredClone(forwardOp)],
|
|
497
|
+
inverseOperations: () => {
|
|
498
|
+
if (capturedFromIndex === null) throw new Error("reorderPageCommand: inverseOperations called before execute");
|
|
499
|
+
return [{ type: "reorder_page", pageId: input.pageId, toIndex: capturedFromIndex }];
|
|
500
|
+
}
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
function setPagePropsCommand(input) {
|
|
504
|
+
const page = requirePage(input.document, input.pageId);
|
|
505
|
+
const prior = {
|
|
506
|
+
type: "set_page_props",
|
|
507
|
+
pageId: input.pageId,
|
|
508
|
+
...input.props.name !== void 0 ? { name: page.name } : {},
|
|
509
|
+
...input.props.width !== void 0 ? { width: page.width } : {},
|
|
510
|
+
...input.props.height !== void 0 ? { height: page.height } : {},
|
|
511
|
+
...input.props.background !== void 0 ? { background: page.background } : {},
|
|
512
|
+
...input.props.bleed !== void 0 ? { bleed: page.bleed } : {}
|
|
513
|
+
};
|
|
514
|
+
const forwardOp = {
|
|
515
|
+
type: "set_page_props",
|
|
516
|
+
pageId: input.pageId,
|
|
517
|
+
...input.props
|
|
518
|
+
};
|
|
519
|
+
return {
|
|
520
|
+
label: "Edit page",
|
|
521
|
+
execute: (state) => applyOp(state, forwardOp),
|
|
522
|
+
undo: (state) => applyOp(state, prior),
|
|
523
|
+
operations: () => [structuredClone(forwardOp)],
|
|
524
|
+
inverseOperations: () => [structuredClone(prior)]
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
function setPageGuidesCommand(input) {
|
|
528
|
+
const page = requirePage(input.document, input.pageId);
|
|
529
|
+
const priorGuides = structuredClone(page.guides);
|
|
530
|
+
const forwardOp = {
|
|
531
|
+
type: "set_page_guides",
|
|
532
|
+
pageId: input.pageId,
|
|
533
|
+
guides: structuredClone(input.guides)
|
|
534
|
+
};
|
|
535
|
+
const inverseOp = {
|
|
536
|
+
type: "set_page_guides",
|
|
537
|
+
pageId: input.pageId,
|
|
538
|
+
guides: priorGuides
|
|
539
|
+
};
|
|
540
|
+
return {
|
|
541
|
+
label: "Edit guides",
|
|
542
|
+
execute: (state) => applyOp(state, forwardOp),
|
|
543
|
+
undo: (state) => applyOp(state, inverseOp),
|
|
544
|
+
operations: () => [structuredClone(forwardOp)],
|
|
545
|
+
inverseOperations: () => [structuredClone(inverseOp)]
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
function bindSlotCommand(input) {
|
|
549
|
+
const page = requirePage(input.document, input.pageId);
|
|
550
|
+
const { element } = requireElement(page, input.elementId);
|
|
551
|
+
const priorSlot = element.slot ?? null;
|
|
552
|
+
const forwardOp = {
|
|
553
|
+
type: "bind_slot",
|
|
554
|
+
pageId: input.pageId,
|
|
555
|
+
elementId: input.elementId,
|
|
556
|
+
slot: input.slot
|
|
557
|
+
};
|
|
558
|
+
const inverseOp = {
|
|
559
|
+
type: "bind_slot",
|
|
560
|
+
pageId: input.pageId,
|
|
561
|
+
elementId: input.elementId,
|
|
562
|
+
slot: priorSlot
|
|
563
|
+
};
|
|
564
|
+
return {
|
|
565
|
+
label: input.slot === null ? "Unbind slot" : `Bind slot "${input.slot}"`,
|
|
566
|
+
execute: (state) => applyOp(state, forwardOp),
|
|
567
|
+
undo: (state) => applyOp(state, inverseOp),
|
|
568
|
+
operations: () => [structuredClone(forwardOp)],
|
|
569
|
+
inverseOperations: () => [structuredClone(inverseOp)]
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
function setDocumentTitleCommand(input) {
|
|
573
|
+
const priorTitle = input.document.title;
|
|
574
|
+
const forwardOp = { type: "set_document_title", title: input.title };
|
|
575
|
+
const inverseOp = { type: "set_document_title", title: priorTitle };
|
|
576
|
+
return {
|
|
577
|
+
label: `Rename document`,
|
|
578
|
+
execute: (state) => applyOp(state, forwardOp),
|
|
579
|
+
undo: (state) => applyOp(state, inverseOp),
|
|
580
|
+
operations: () => [structuredClone(forwardOp)],
|
|
581
|
+
inverseOperations: () => [structuredClone(inverseOp)]
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
export {
|
|
586
|
+
SCENE_COMMAND_HISTORY_LIMIT,
|
|
587
|
+
createSceneCommandStack,
|
|
588
|
+
addElementCommand,
|
|
589
|
+
setAttrsCommand,
|
|
590
|
+
multiSetAttrsCommand,
|
|
591
|
+
reorderElementCommand,
|
|
592
|
+
deleteElementCommand,
|
|
593
|
+
groupElementsCommand,
|
|
594
|
+
ungroupElementCommand,
|
|
595
|
+
addPageCommand,
|
|
596
|
+
duplicatePageCommand,
|
|
597
|
+
deletePageCommand,
|
|
598
|
+
reorderPageCommand,
|
|
599
|
+
setPagePropsCommand,
|
|
600
|
+
setPageGuidesCommand,
|
|
601
|
+
bindSlotCommand,
|
|
602
|
+
setDocumentTitleCommand
|
|
603
|
+
};
|
|
604
|
+
//# sourceMappingURL=chunk-XWJXZ6WE.js.map
|