@tangle-network/agent-app 0.26.0 → 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/brand-extraction/index.d.ts +212 -0
- package/dist/brand-extraction/index.js +446 -0
- package/dist/brand-extraction/index.js.map +1 -0
- 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-FSUR2752.js → chunk-7I37CO5D.js} +274 -388
- 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-LPAVBGVY.js → chunk-YEWTVDDT.js} +399 -860
- 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 +80 -618
- package/dist/design-canvas-react/index.js +85 -172
- 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 +33 -3
- package/dist/DesignCanvas-MA5EH324.js +0 -10
- package/dist/DesignCanvasEditor-YLCO7I5I.js +0 -9
- 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-FSUR2752.js.map +0 -1
- package/dist/chunk-JZAJE3JL.js.map +0 -1
- package/dist/chunk-LPAVBGVY.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-MA5EH324.js.map → DesignCanvas-AOIVN3SJ.js.map} +0 -0
- /package/dist/{DesignCanvasEditor-YLCO7I5I.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
|
@@ -1,564 +1,29 @@
|
|
|
1
|
+
import {
|
|
2
|
+
addPageCommand,
|
|
3
|
+
bindSlotCommand,
|
|
4
|
+
createSceneCommandStack,
|
|
5
|
+
deleteElementCommand,
|
|
6
|
+
deletePageCommand,
|
|
7
|
+
duplicatePageCommand,
|
|
8
|
+
groupElementsCommand,
|
|
9
|
+
multiSetAttrsCommand,
|
|
10
|
+
reorderElementCommand,
|
|
11
|
+
reorderPageCommand,
|
|
12
|
+
setAttrsCommand,
|
|
13
|
+
setPageGuidesCommand,
|
|
14
|
+
setPagePropsCommand,
|
|
15
|
+
ungroupElementCommand
|
|
16
|
+
} from "./chunk-XWJXZ6WE.js";
|
|
1
17
|
import {
|
|
2
18
|
SIZE_PRESETS,
|
|
3
|
-
applySceneOperation,
|
|
4
|
-
applySceneOperations,
|
|
5
19
|
findElement,
|
|
6
20
|
matchPreset,
|
|
7
|
-
requireElement,
|
|
8
21
|
requirePage
|
|
9
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-M2EBUDZ7.js";
|
|
10
23
|
|
|
11
24
|
// src/design-canvas-react/components/DesignCanvas.tsx
|
|
12
25
|
import { useCallback as useCallback2, useEffect as useEffect3, useMemo, useRef as useRef5, useState as useState5, useSyncExternalStore } from "react";
|
|
13
26
|
|
|
14
|
-
// src/design-canvas-react/engine/command-stack.ts
|
|
15
|
-
var SCENE_COMMAND_HISTORY_LIMIT = 200;
|
|
16
|
-
function createSceneCommandStack(document2, activePageId) {
|
|
17
|
-
let state = {
|
|
18
|
-
document: document2,
|
|
19
|
-
activePageId,
|
|
20
|
-
selectedElementIds: [],
|
|
21
|
-
zoom: 1,
|
|
22
|
-
panX: 0,
|
|
23
|
-
panY: 0,
|
|
24
|
-
gridEnabled: false,
|
|
25
|
-
gridSize: 10,
|
|
26
|
-
snapEnabled: true,
|
|
27
|
-
showRulers: true,
|
|
28
|
-
showBleed: false
|
|
29
|
-
};
|
|
30
|
-
const undoStack = [];
|
|
31
|
-
const redoStack = [];
|
|
32
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
33
|
-
const notify = () => {
|
|
34
|
-
for (const listener of [...listeners]) listener();
|
|
35
|
-
};
|
|
36
|
-
return {
|
|
37
|
-
execute(command) {
|
|
38
|
-
state = command.execute(state);
|
|
39
|
-
undoStack.push(command);
|
|
40
|
-
if (undoStack.length > SCENE_COMMAND_HISTORY_LIMIT) {
|
|
41
|
-
undoStack.splice(0, undoStack.length - SCENE_COMMAND_HISTORY_LIMIT);
|
|
42
|
-
}
|
|
43
|
-
redoStack.length = 0;
|
|
44
|
-
notify();
|
|
45
|
-
},
|
|
46
|
-
// Both transforms run BEFORE the stacks move: a throwing transform (e.g.
|
|
47
|
-
// missing element after reset()) leaves history and state exactly as they
|
|
48
|
-
// were. The entry is never silently destroyed — the caller can retry after
|
|
49
|
-
// the next server refresh restores the target.
|
|
50
|
-
undo() {
|
|
51
|
-
const command = undoStack[undoStack.length - 1];
|
|
52
|
-
if (!command) throw new Error("nothing to undo \u2014 guard with canUndo() before calling undo()");
|
|
53
|
-
state = command.undo(state);
|
|
54
|
-
undoStack.pop();
|
|
55
|
-
redoStack.push(command);
|
|
56
|
-
notify();
|
|
57
|
-
return command;
|
|
58
|
-
},
|
|
59
|
-
redo() {
|
|
60
|
-
const command = redoStack[redoStack.length - 1];
|
|
61
|
-
if (!command) throw new Error("nothing to redo \u2014 guard with canRedo() before calling redo()");
|
|
62
|
-
state = command.execute(state);
|
|
63
|
-
redoStack.pop();
|
|
64
|
-
undoStack.push(command);
|
|
65
|
-
notify();
|
|
66
|
-
return command;
|
|
67
|
-
},
|
|
68
|
-
canUndo() {
|
|
69
|
-
return undoStack.length > 0;
|
|
70
|
-
},
|
|
71
|
-
canRedo() {
|
|
72
|
-
return redoStack.length > 0;
|
|
73
|
-
},
|
|
74
|
-
subscribe(listener) {
|
|
75
|
-
listeners.add(listener);
|
|
76
|
-
return () => {
|
|
77
|
-
listeners.delete(listener);
|
|
78
|
-
};
|
|
79
|
-
},
|
|
80
|
-
getState() {
|
|
81
|
-
return state;
|
|
82
|
-
},
|
|
83
|
-
setView(patch) {
|
|
84
|
-
state = { ...state, ...patch };
|
|
85
|
-
notify();
|
|
86
|
-
},
|
|
87
|
-
rollback(command) {
|
|
88
|
-
const idx = undoStack.lastIndexOf(command);
|
|
89
|
-
if (idx === -1) return;
|
|
90
|
-
state = command.undo(state);
|
|
91
|
-
undoStack.splice(idx, 1);
|
|
92
|
-
redoStack.length = 0;
|
|
93
|
-
notify();
|
|
94
|
-
},
|
|
95
|
-
/** Rebase onto a server-refreshed document. History survives; selection
|
|
96
|
-
* drops ids the refresh removed so view state never dangles. */
|
|
97
|
-
reset(newDocument) {
|
|
98
|
-
const liveElementIds = /* @__PURE__ */ new Set();
|
|
99
|
-
for (const page of newDocument.pages) {
|
|
100
|
-
collectElementIds(page.elements, liveElementIds);
|
|
101
|
-
}
|
|
102
|
-
const activePageExists = newDocument.pages.some((p) => p.id === state.activePageId);
|
|
103
|
-
const activePageId2 = activePageExists ? state.activePageId : newDocument.pages[0]?.id ?? state.activePageId;
|
|
104
|
-
state = {
|
|
105
|
-
...state,
|
|
106
|
-
document: newDocument,
|
|
107
|
-
activePageId: activePageId2,
|
|
108
|
-
selectedElementIds: state.selectedElementIds.filter((id) => liveElementIds.has(id))
|
|
109
|
-
};
|
|
110
|
-
notify();
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
function collectElementIds(elements, ids) {
|
|
115
|
-
for (const el of elements) {
|
|
116
|
-
ids.add(el.id);
|
|
117
|
-
if (el.kind === "group" && Array.isArray(el.children)) {
|
|
118
|
-
collectElementIds(el.children, ids);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// src/design-canvas-react/engine/commands.ts
|
|
124
|
-
function applyOps(state, ops) {
|
|
125
|
-
return { ...state, document: applySceneOperations(state.document, ops) };
|
|
126
|
-
}
|
|
127
|
-
function applyOp(state, op) {
|
|
128
|
-
return { ...state, document: applySceneOperation(state.document, op) };
|
|
129
|
-
}
|
|
130
|
-
function addElementCommand(input) {
|
|
131
|
-
const addOp = {
|
|
132
|
-
type: "add_element",
|
|
133
|
-
pageId: input.pageId,
|
|
134
|
-
element: structuredClone(input.element),
|
|
135
|
-
...input.index !== void 0 ? { index: input.index } : {},
|
|
136
|
-
...input.parentGroupId !== void 0 ? { parentGroupId: input.parentGroupId } : {}
|
|
137
|
-
};
|
|
138
|
-
const deleteOp = {
|
|
139
|
-
type: "delete_element",
|
|
140
|
-
pageId: input.pageId,
|
|
141
|
-
elementId: input.element.id
|
|
142
|
-
};
|
|
143
|
-
return {
|
|
144
|
-
label: `Add ${input.element.kind}`,
|
|
145
|
-
execute: (state) => applyOp(state, addOp),
|
|
146
|
-
undo: (state) => applyOp(state, deleteOp),
|
|
147
|
-
operations: () => [structuredClone(addOp)],
|
|
148
|
-
inverseOperations: () => [structuredClone(deleteOp)]
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
function setAttrsCommand(input) {
|
|
152
|
-
const forwardOp = {
|
|
153
|
-
type: "set_attrs",
|
|
154
|
-
pageId: input.pageId,
|
|
155
|
-
elementId: input.elementId,
|
|
156
|
-
attrs: structuredClone(input.attrs)
|
|
157
|
-
};
|
|
158
|
-
const inverseOp = {
|
|
159
|
-
type: "set_attrs",
|
|
160
|
-
pageId: input.pageId,
|
|
161
|
-
elementId: input.elementId,
|
|
162
|
-
attrs: structuredClone(input.priorAttrs)
|
|
163
|
-
};
|
|
164
|
-
return {
|
|
165
|
-
label: "Edit element",
|
|
166
|
-
execute: (state) => applyOp(state, forwardOp),
|
|
167
|
-
undo: (state) => applyOp(state, inverseOp),
|
|
168
|
-
operations: () => [structuredClone(forwardOp)],
|
|
169
|
-
inverseOperations: () => [structuredClone(inverseOp)]
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
function multiSetAttrsCommand(entries) {
|
|
173
|
-
if (entries.length === 0) throw new Error("multiSetAttrsCommand: entries must not be empty");
|
|
174
|
-
const forwardOps = entries.map((e) => ({
|
|
175
|
-
type: "set_attrs",
|
|
176
|
-
pageId: e.pageId,
|
|
177
|
-
elementId: e.elementId,
|
|
178
|
-
attrs: structuredClone(e.attrs)
|
|
179
|
-
}));
|
|
180
|
-
const inverseOps = entries.map((e) => ({
|
|
181
|
-
type: "set_attrs",
|
|
182
|
-
pageId: e.pageId,
|
|
183
|
-
elementId: e.elementId,
|
|
184
|
-
attrs: structuredClone(e.priorAttrs)
|
|
185
|
-
}));
|
|
186
|
-
return {
|
|
187
|
-
label: `Edit ${entries.length} elements`,
|
|
188
|
-
execute: (state) => applyOps(state, forwardOps),
|
|
189
|
-
undo: (state) => applyOps(state, inverseOps),
|
|
190
|
-
operations: () => structuredClone(forwardOps),
|
|
191
|
-
inverseOperations: () => structuredClone(inverseOps)
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
function reorderElementCommand(input) {
|
|
195
|
-
let capturedFromIndex = null;
|
|
196
|
-
const forwardOp = {
|
|
197
|
-
type: "reorder_element",
|
|
198
|
-
pageId: input.pageId,
|
|
199
|
-
elementId: input.elementId,
|
|
200
|
-
toIndex: input.toIndex
|
|
201
|
-
};
|
|
202
|
-
return {
|
|
203
|
-
label: "Reorder element",
|
|
204
|
-
execute: (state) => {
|
|
205
|
-
if (capturedFromIndex === null) {
|
|
206
|
-
const page = requirePage(state.document, input.pageId);
|
|
207
|
-
const { index } = requireElement(page, input.elementId);
|
|
208
|
-
capturedFromIndex = index;
|
|
209
|
-
}
|
|
210
|
-
return applyOp(state, forwardOp);
|
|
211
|
-
},
|
|
212
|
-
undo: (state) => {
|
|
213
|
-
if (capturedFromIndex === null) {
|
|
214
|
-
throw new Error("reorderElementCommand: undo called before execute");
|
|
215
|
-
}
|
|
216
|
-
return applyOp(state, {
|
|
217
|
-
type: "reorder_element",
|
|
218
|
-
pageId: input.pageId,
|
|
219
|
-
elementId: input.elementId,
|
|
220
|
-
toIndex: capturedFromIndex
|
|
221
|
-
});
|
|
222
|
-
},
|
|
223
|
-
operations: () => [structuredClone(forwardOp)],
|
|
224
|
-
inverseOperations: () => {
|
|
225
|
-
if (capturedFromIndex === null) {
|
|
226
|
-
throw new Error("reorderElementCommand: inverseOperations called before execute");
|
|
227
|
-
}
|
|
228
|
-
return [{
|
|
229
|
-
type: "reorder_element",
|
|
230
|
-
pageId: input.pageId,
|
|
231
|
-
elementId: input.elementId,
|
|
232
|
-
toIndex: capturedFromIndex
|
|
233
|
-
}];
|
|
234
|
-
}
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
function deleteElementCommand(input) {
|
|
238
|
-
const page = requirePage(input.document, input.pageId);
|
|
239
|
-
const { element, owner, index } = requireElement(page, input.elementId);
|
|
240
|
-
const snapshot = structuredClone(element);
|
|
241
|
-
const parentGroupId = findParentGroupId(page, owner);
|
|
242
|
-
const deleteOp = {
|
|
243
|
-
type: "delete_element",
|
|
244
|
-
pageId: input.pageId,
|
|
245
|
-
elementId: input.elementId
|
|
246
|
-
};
|
|
247
|
-
const addOp = {
|
|
248
|
-
type: "add_element",
|
|
249
|
-
pageId: input.pageId,
|
|
250
|
-
element: snapshot,
|
|
251
|
-
index,
|
|
252
|
-
...parentGroupId !== void 0 ? { parentGroupId } : {}
|
|
253
|
-
};
|
|
254
|
-
return {
|
|
255
|
-
label: `Delete ${element.kind}`,
|
|
256
|
-
execute: (state) => {
|
|
257
|
-
const next = applyOp(state, deleteOp);
|
|
258
|
-
return {
|
|
259
|
-
...next,
|
|
260
|
-
selectedElementIds: next.selectedElementIds.filter((id) => id !== input.elementId)
|
|
261
|
-
};
|
|
262
|
-
},
|
|
263
|
-
undo: (state) => applyOp(state, addOp),
|
|
264
|
-
operations: () => [structuredClone(deleteOp)],
|
|
265
|
-
inverseOperations: () => [structuredClone(addOp)]
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
function findParentGroupId(page, owner) {
|
|
269
|
-
if (owner === page.elements) return void 0;
|
|
270
|
-
return findGroupWithChildren(page.elements, owner);
|
|
271
|
-
}
|
|
272
|
-
function findGroupWithChildren(elements, target) {
|
|
273
|
-
for (const el of elements) {
|
|
274
|
-
if (el.kind === "group") {
|
|
275
|
-
if (el.children === target) return el.id;
|
|
276
|
-
const found = findGroupWithChildren(el.children, target);
|
|
277
|
-
if (found !== void 0) return found;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
return void 0;
|
|
281
|
-
}
|
|
282
|
-
function groupElementsCommand(input) {
|
|
283
|
-
if (input.elementIds.length < 2) {
|
|
284
|
-
throw new Error("groupElementsCommand: requires \u2265 2 elementIds");
|
|
285
|
-
}
|
|
286
|
-
const groupOp = {
|
|
287
|
-
type: "group_elements",
|
|
288
|
-
pageId: input.pageId,
|
|
289
|
-
elementIds: input.elementIds.slice(),
|
|
290
|
-
groupId: input.groupId,
|
|
291
|
-
...input.name !== void 0 ? { name: input.name } : {}
|
|
292
|
-
};
|
|
293
|
-
const ungroupOp = {
|
|
294
|
-
type: "ungroup_element",
|
|
295
|
-
pageId: input.pageId,
|
|
296
|
-
groupId: input.groupId
|
|
297
|
-
};
|
|
298
|
-
return {
|
|
299
|
-
label: `Group ${input.elementIds.length} elements`,
|
|
300
|
-
execute: (state) => {
|
|
301
|
-
const next = applyOp(state, groupOp);
|
|
302
|
-
return {
|
|
303
|
-
...next,
|
|
304
|
-
selectedElementIds: [input.groupId]
|
|
305
|
-
};
|
|
306
|
-
},
|
|
307
|
-
undo: (state) => {
|
|
308
|
-
const next = applyOp(state, ungroupOp);
|
|
309
|
-
return { ...next, selectedElementIds: input.elementIds.slice() };
|
|
310
|
-
},
|
|
311
|
-
operations: () => [structuredClone(groupOp)],
|
|
312
|
-
inverseOperations: () => [structuredClone(ungroupOp)]
|
|
313
|
-
};
|
|
314
|
-
}
|
|
315
|
-
function ungroupElementCommand(input) {
|
|
316
|
-
const page = requirePage(input.document, input.pageId);
|
|
317
|
-
const { element } = requireElement(page, input.groupId);
|
|
318
|
-
if (element.kind !== "group") {
|
|
319
|
-
throw new Error(`ungroupElementCommand: element ${input.groupId} is kind ${element.kind}, not group`);
|
|
320
|
-
}
|
|
321
|
-
const childIds = element.children.map((c) => c.id);
|
|
322
|
-
const ungroupOp = {
|
|
323
|
-
type: "ungroup_element",
|
|
324
|
-
pageId: input.pageId,
|
|
325
|
-
groupId: input.groupId
|
|
326
|
-
};
|
|
327
|
-
const regroupOp = {
|
|
328
|
-
type: "group_elements",
|
|
329
|
-
pageId: input.pageId,
|
|
330
|
-
elementIds: childIds,
|
|
331
|
-
groupId: input.groupId,
|
|
332
|
-
name: element.name
|
|
333
|
-
};
|
|
334
|
-
return {
|
|
335
|
-
label: `Ungroup`,
|
|
336
|
-
execute: (state) => {
|
|
337
|
-
const next = applyOp(state, ungroupOp);
|
|
338
|
-
return { ...next, selectedElementIds: childIds.slice() };
|
|
339
|
-
},
|
|
340
|
-
undo: (state) => {
|
|
341
|
-
const next = applyOp(state, regroupOp);
|
|
342
|
-
return { ...next, selectedElementIds: [input.groupId] };
|
|
343
|
-
},
|
|
344
|
-
operations: () => [structuredClone(ungroupOp)],
|
|
345
|
-
inverseOperations: () => [structuredClone(regroupOp)]
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
function addPageCommand(input) {
|
|
349
|
-
const addOp = {
|
|
350
|
-
type: "add_page",
|
|
351
|
-
pageId: input.pageId,
|
|
352
|
-
...input.options !== void 0 ? { options: input.options } : {},
|
|
353
|
-
...input.index !== void 0 ? { index: input.index } : {}
|
|
354
|
-
};
|
|
355
|
-
const deleteOp = { type: "delete_page", pageId: input.pageId };
|
|
356
|
-
return {
|
|
357
|
-
label: "Add page",
|
|
358
|
-
execute: (state) => {
|
|
359
|
-
const next = applyOp(state, addOp);
|
|
360
|
-
return { ...next, activePageId: input.pageId };
|
|
361
|
-
},
|
|
362
|
-
undo: (state) => {
|
|
363
|
-
const next = applyOp(state, deleteOp);
|
|
364
|
-
const activeExists = next.document.pages.some((p) => p.id === next.activePageId);
|
|
365
|
-
return activeExists ? next : { ...next, activePageId: next.document.pages[0].id };
|
|
366
|
-
},
|
|
367
|
-
operations: () => [structuredClone(addOp)],
|
|
368
|
-
inverseOperations: () => [structuredClone(deleteOp)]
|
|
369
|
-
};
|
|
370
|
-
}
|
|
371
|
-
function duplicatePageCommand(input) {
|
|
372
|
-
requirePage(input.document, input.sourcePageId);
|
|
373
|
-
const dupOp = {
|
|
374
|
-
type: "duplicate_page",
|
|
375
|
-
sourcePageId: input.sourcePageId,
|
|
376
|
-
pageId: input.pageId
|
|
377
|
-
};
|
|
378
|
-
const deleteOp = { type: "delete_page", pageId: input.pageId };
|
|
379
|
-
return {
|
|
380
|
-
label: "Duplicate page",
|
|
381
|
-
execute: (state) => {
|
|
382
|
-
const next = applyOp(state, dupOp);
|
|
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: input.sourcePageId };
|
|
389
|
-
},
|
|
390
|
-
operations: () => [structuredClone(dupOp)],
|
|
391
|
-
inverseOperations: () => [structuredClone(deleteOp)]
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
function deletePageCommand(input) {
|
|
395
|
-
if (input.document.pages.length <= 1) {
|
|
396
|
-
throw new Error("deletePageCommand: cannot delete the last page");
|
|
397
|
-
}
|
|
398
|
-
const page = requirePage(input.document, input.pageId);
|
|
399
|
-
const currentIndex = input.document.pages.findIndex((p) => p.id === input.pageId);
|
|
400
|
-
const snapshot = structuredClone(page);
|
|
401
|
-
const deleteOp = { type: "delete_page", pageId: input.pageId };
|
|
402
|
-
function buildRestoreOps() {
|
|
403
|
-
const ops = [
|
|
404
|
-
{
|
|
405
|
-
type: "add_page",
|
|
406
|
-
pageId: snapshot.id,
|
|
407
|
-
options: {
|
|
408
|
-
name: snapshot.name,
|
|
409
|
-
width: snapshot.width,
|
|
410
|
-
height: snapshot.height,
|
|
411
|
-
background: snapshot.background
|
|
412
|
-
},
|
|
413
|
-
index: currentIndex
|
|
414
|
-
}
|
|
415
|
-
];
|
|
416
|
-
if (snapshot.bleed) {
|
|
417
|
-
ops.push({ type: "set_page_props", pageId: snapshot.id, bleed: snapshot.bleed });
|
|
418
|
-
}
|
|
419
|
-
if (snapshot.guides.vertical.length > 0 || snapshot.guides.horizontal.length > 0) {
|
|
420
|
-
ops.push({ type: "set_page_guides", pageId: snapshot.id, guides: snapshot.guides });
|
|
421
|
-
}
|
|
422
|
-
for (let i = 0; i < snapshot.elements.length; i++) {
|
|
423
|
-
ops.push({
|
|
424
|
-
type: "add_element",
|
|
425
|
-
pageId: snapshot.id,
|
|
426
|
-
element: structuredClone(snapshot.elements[i]),
|
|
427
|
-
index: i
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
|
-
return ops;
|
|
431
|
-
}
|
|
432
|
-
return {
|
|
433
|
-
label: "Delete page",
|
|
434
|
-
execute: (state) => {
|
|
435
|
-
const next = applyOp(state, deleteOp);
|
|
436
|
-
const activeExists = next.document.pages.some((p) => p.id === next.activePageId);
|
|
437
|
-
if (activeExists) return next;
|
|
438
|
-
const fallbackIndex = Math.min(currentIndex, next.document.pages.length - 1);
|
|
439
|
-
return { ...next, activePageId: next.document.pages[fallbackIndex].id };
|
|
440
|
-
},
|
|
441
|
-
undo: (state) => {
|
|
442
|
-
const next = applyOps(state, buildRestoreOps());
|
|
443
|
-
return { ...next, activePageId: input.pageId };
|
|
444
|
-
},
|
|
445
|
-
operations: () => [structuredClone(deleteOp)],
|
|
446
|
-
inverseOperations: () => buildRestoreOps()
|
|
447
|
-
};
|
|
448
|
-
}
|
|
449
|
-
function reorderPageCommand(input) {
|
|
450
|
-
let capturedFromIndex = null;
|
|
451
|
-
const forwardOp = {
|
|
452
|
-
type: "reorder_page",
|
|
453
|
-
pageId: input.pageId,
|
|
454
|
-
toIndex: input.toIndex
|
|
455
|
-
};
|
|
456
|
-
return {
|
|
457
|
-
label: "Reorder page",
|
|
458
|
-
execute: (state) => {
|
|
459
|
-
if (capturedFromIndex === null) {
|
|
460
|
-
capturedFromIndex = state.document.pages.findIndex((p) => p.id === input.pageId);
|
|
461
|
-
if (capturedFromIndex === -1) throw new Error(`reorderPageCommand: page ${input.pageId} not found`);
|
|
462
|
-
}
|
|
463
|
-
return applyOp(state, forwardOp);
|
|
464
|
-
},
|
|
465
|
-
undo: (state) => {
|
|
466
|
-
if (capturedFromIndex === null) throw new Error("reorderPageCommand: undo called before execute");
|
|
467
|
-
return applyOp(state, {
|
|
468
|
-
type: "reorder_page",
|
|
469
|
-
pageId: input.pageId,
|
|
470
|
-
toIndex: capturedFromIndex
|
|
471
|
-
});
|
|
472
|
-
},
|
|
473
|
-
operations: () => [structuredClone(forwardOp)],
|
|
474
|
-
inverseOperations: () => {
|
|
475
|
-
if (capturedFromIndex === null) throw new Error("reorderPageCommand: inverseOperations called before execute");
|
|
476
|
-
return [{ type: "reorder_page", pageId: input.pageId, toIndex: capturedFromIndex }];
|
|
477
|
-
}
|
|
478
|
-
};
|
|
479
|
-
}
|
|
480
|
-
function setPagePropsCommand(input) {
|
|
481
|
-
const page = requirePage(input.document, input.pageId);
|
|
482
|
-
const prior = {
|
|
483
|
-
type: "set_page_props",
|
|
484
|
-
pageId: input.pageId,
|
|
485
|
-
...input.props.name !== void 0 ? { name: page.name } : {},
|
|
486
|
-
...input.props.width !== void 0 ? { width: page.width } : {},
|
|
487
|
-
...input.props.height !== void 0 ? { height: page.height } : {},
|
|
488
|
-
...input.props.background !== void 0 ? { background: page.background } : {},
|
|
489
|
-
...input.props.bleed !== void 0 ? { bleed: page.bleed } : {}
|
|
490
|
-
};
|
|
491
|
-
const forwardOp = {
|
|
492
|
-
type: "set_page_props",
|
|
493
|
-
pageId: input.pageId,
|
|
494
|
-
...input.props
|
|
495
|
-
};
|
|
496
|
-
return {
|
|
497
|
-
label: "Edit page",
|
|
498
|
-
execute: (state) => applyOp(state, forwardOp),
|
|
499
|
-
undo: (state) => applyOp(state, prior),
|
|
500
|
-
operations: () => [structuredClone(forwardOp)],
|
|
501
|
-
inverseOperations: () => [structuredClone(prior)]
|
|
502
|
-
};
|
|
503
|
-
}
|
|
504
|
-
function setPageGuidesCommand(input) {
|
|
505
|
-
const page = requirePage(input.document, input.pageId);
|
|
506
|
-
const priorGuides = structuredClone(page.guides);
|
|
507
|
-
const forwardOp = {
|
|
508
|
-
type: "set_page_guides",
|
|
509
|
-
pageId: input.pageId,
|
|
510
|
-
guides: structuredClone(input.guides)
|
|
511
|
-
};
|
|
512
|
-
const inverseOp = {
|
|
513
|
-
type: "set_page_guides",
|
|
514
|
-
pageId: input.pageId,
|
|
515
|
-
guides: priorGuides
|
|
516
|
-
};
|
|
517
|
-
return {
|
|
518
|
-
label: "Edit guides",
|
|
519
|
-
execute: (state) => applyOp(state, forwardOp),
|
|
520
|
-
undo: (state) => applyOp(state, inverseOp),
|
|
521
|
-
operations: () => [structuredClone(forwardOp)],
|
|
522
|
-
inverseOperations: () => [structuredClone(inverseOp)]
|
|
523
|
-
};
|
|
524
|
-
}
|
|
525
|
-
function bindSlotCommand(input) {
|
|
526
|
-
const page = requirePage(input.document, input.pageId);
|
|
527
|
-
const { element } = requireElement(page, input.elementId);
|
|
528
|
-
const priorSlot = element.slot ?? null;
|
|
529
|
-
const forwardOp = {
|
|
530
|
-
type: "bind_slot",
|
|
531
|
-
pageId: input.pageId,
|
|
532
|
-
elementId: input.elementId,
|
|
533
|
-
slot: input.slot
|
|
534
|
-
};
|
|
535
|
-
const inverseOp = {
|
|
536
|
-
type: "bind_slot",
|
|
537
|
-
pageId: input.pageId,
|
|
538
|
-
elementId: input.elementId,
|
|
539
|
-
slot: priorSlot
|
|
540
|
-
};
|
|
541
|
-
return {
|
|
542
|
-
label: input.slot === null ? "Unbind slot" : `Bind slot "${input.slot}"`,
|
|
543
|
-
execute: (state) => applyOp(state, forwardOp),
|
|
544
|
-
undo: (state) => applyOp(state, inverseOp),
|
|
545
|
-
operations: () => [structuredClone(forwardOp)],
|
|
546
|
-
inverseOperations: () => [structuredClone(inverseOp)]
|
|
547
|
-
};
|
|
548
|
-
}
|
|
549
|
-
function setDocumentTitleCommand(input) {
|
|
550
|
-
const priorTitle = input.document.title;
|
|
551
|
-
const forwardOp = { type: "set_document_title", title: input.title };
|
|
552
|
-
const inverseOp = { type: "set_document_title", title: priorTitle };
|
|
553
|
-
return {
|
|
554
|
-
label: `Rename document`,
|
|
555
|
-
execute: (state) => applyOp(state, forwardOp),
|
|
556
|
-
undo: (state) => applyOp(state, inverseOp),
|
|
557
|
-
operations: () => [structuredClone(forwardOp)],
|
|
558
|
-
inverseOperations: () => [structuredClone(inverseOp)]
|
|
559
|
-
};
|
|
560
|
-
}
|
|
561
|
-
|
|
562
27
|
// src/design-canvas-react/components/ruler-math.ts
|
|
563
28
|
var TICK_STEP_CANDIDATES_PX = [1, 2, 5, 10, 25, 50, 100, 250, 500, 1e3, 2500, 5e3];
|
|
564
29
|
function selectTickStep(input) {
|
|
@@ -731,6 +196,7 @@ function glyph(paths) {
|
|
|
731
196
|
}
|
|
732
197
|
var UndoGlyph = glyph(/* @__PURE__ */ jsx2("path", { d: "M3 7v6h6M3 13a9 9 0 1 0 3-7.7" }));
|
|
733
198
|
var RedoGlyph = glyph(/* @__PURE__ */ jsx2("path", { d: "M21 7v6h-6M21 13a9 9 0 1 1-3-7.7" }));
|
|
199
|
+
var SwapGlyph = glyph(/* @__PURE__ */ jsx2("path", { d: "M7 4 3 8l4 4M3 8h14M17 20l4-4-4-4M21 16H7" }));
|
|
734
200
|
var EyeGlyph = glyph(
|
|
735
201
|
/* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
736
202
|
/* @__PURE__ */ jsx2("path", { d: "M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7z" }),
|
|
@@ -795,7 +261,6 @@ var BoldGlyph = glyph(/* @__PURE__ */ jsx2("path", { d: "M6 4h8a4 4 0 0 1 0 8H6z
|
|
|
795
261
|
var ItalicGlyph = glyph(/* @__PURE__ */ jsx2("path", { d: "M11 4h6M7 20h6M14 4 8 20" }));
|
|
796
262
|
var PlusGlyph = glyph(/* @__PURE__ */ jsx2("path", { d: "M12 5v14M5 12h14" }));
|
|
797
263
|
var ChevronDownGlyph = glyph(/* @__PURE__ */ jsx2("path", { d: "m6 9 6 6 6-6" }));
|
|
798
|
-
var ChevronRightGlyph = glyph(/* @__PURE__ */ jsx2("path", { d: "m9 18 6-6-6-6" }));
|
|
799
264
|
var RectGlyph = glyph(/* @__PURE__ */ jsx2("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }));
|
|
800
265
|
var EllipseGlyph = glyph(/* @__PURE__ */ jsx2("ellipse", { cx: "12", cy: "12", rx: "10", ry: "7" }));
|
|
801
266
|
var LineGlyph = glyph(/* @__PURE__ */ jsx2("path", { d: "M5 19 19 5" }));
|
|
@@ -819,12 +284,6 @@ var SlotGlyph = glyph(
|
|
|
819
284
|
/* @__PURE__ */ jsx2("path", { d: "M12 1v4M12 19v4M4.2 4.2l2.8 2.8M17 17l2.8 2.8M1 12h4M19 12h4M4.2 19.8l2.8-2.8M17 7 19.8 4.2" })
|
|
820
285
|
] })
|
|
821
286
|
);
|
|
822
|
-
var FitGlyph = glyph(
|
|
823
|
-
/* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
824
|
-
/* @__PURE__ */ jsx2("path", { d: "M3 3h4v4H3zM17 3h4v4h-4zM3 17h4v4H3zM17 17h4v4h-4z" }),
|
|
825
|
-
/* @__PURE__ */ jsx2("path", { d: "M7 5h10M5 7v10M19 7v10M7 19h10" })
|
|
826
|
-
] })
|
|
827
|
-
);
|
|
828
287
|
var PageGlyph = glyph(
|
|
829
288
|
/* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
830
289
|
/* @__PURE__ */ jsx2("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
|
|
@@ -873,11 +332,24 @@ var ShapesGlyph = glyph(
|
|
|
873
332
|
] })
|
|
874
333
|
);
|
|
875
334
|
|
|
335
|
+
// src/design-canvas-react/components/icon-button.tsx
|
|
336
|
+
import { forwardRef } from "react";
|
|
337
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
338
|
+
var BTN_BASE = "items-center justify-center rounded border border-[var(--border-default)] text-[var(--text-secondary)] transition hover:text-[var(--text-primary)] focus:outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--ring))] focus-visible:ring-offset-1 focus-visible:ring-offset-[var(--bg-input)] disabled:cursor-default disabled:opacity-40";
|
|
339
|
+
var BTN_ACTIVE_EXTRA = " border-[var(--brand-primary)] text-[var(--brand-primary)] hover:text-[var(--brand-primary)]";
|
|
340
|
+
var BTN = `flex h-7 w-7 ${BTN_BASE}`;
|
|
341
|
+
var BTN_ACTIVE = BTN + BTN_ACTIVE_EXTRA;
|
|
342
|
+
var BTN_SM = `flex h-6 w-6 ${BTN_BASE}`;
|
|
343
|
+
var BTN_SM_ACTIVE = BTN_SM + BTN_ACTIVE_EXTRA;
|
|
344
|
+
var IconButton = forwardRef(function IconButton2({ active = false, size = "md", className = "", type = "button", ...rest }, ref) {
|
|
345
|
+
const base = size === "sm" ? active ? BTN_SM_ACTIVE : BTN_SM : active ? BTN_ACTIVE : BTN;
|
|
346
|
+
return /* @__PURE__ */ jsx3("button", { ref, type, className: className ? `${base} ${className}` : base, ...rest });
|
|
347
|
+
});
|
|
348
|
+
|
|
876
349
|
// src/design-canvas-react/components/PagesStrip.tsx
|
|
877
|
-
import { jsx as
|
|
350
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
878
351
|
var THUMBNAIL_W = 80;
|
|
879
352
|
var THUMBNAIL_H = 56;
|
|
880
|
-
var BTN = "flex h-6 w-6 items-center justify-center rounded border border-[var(--border-default)] text-[var(--text-secondary)] transition hover:text-[var(--text-primary)] disabled:cursor-default disabled:opacity-40";
|
|
881
353
|
function PagesStrip({
|
|
882
354
|
pages,
|
|
883
355
|
activePageId,
|
|
@@ -887,7 +359,8 @@ function PagesStrip({
|
|
|
887
359
|
onAddPage,
|
|
888
360
|
onDuplicatePage,
|
|
889
361
|
onDeletePage,
|
|
890
|
-
onReorderPage
|
|
362
|
+
onReorderPage,
|
|
363
|
+
canManagePages = true
|
|
891
364
|
}) {
|
|
892
365
|
const [thumbnails, setThumbnails] = useState({});
|
|
893
366
|
const thumbnailVersionRef = useRef(0);
|
|
@@ -927,10 +400,6 @@ function PagesStrip({
|
|
|
927
400
|
return /* @__PURE__ */ jsxs3(
|
|
928
401
|
"div",
|
|
929
402
|
{
|
|
930
|
-
role: "button",
|
|
931
|
-
tabIndex: 0,
|
|
932
|
-
"aria-label": `Page ${index + 1}: ${page.name}${isActive ? " (active)" : ""}`,
|
|
933
|
-
"aria-pressed": isActive,
|
|
934
403
|
draggable: canWrite,
|
|
935
404
|
onDragStart: () => {
|
|
936
405
|
dragIndexRef.current = index;
|
|
@@ -953,38 +422,43 @@ function PagesStrip({
|
|
|
953
422
|
dragIndexRef.current = null;
|
|
954
423
|
setDragOverIndex(null);
|
|
955
424
|
},
|
|
956
|
-
onClick: () => onSelectPage(page.id),
|
|
957
|
-
onKeyDown: (event) => {
|
|
958
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
959
|
-
event.preventDefault();
|
|
960
|
-
onSelectPage(page.id);
|
|
961
|
-
}
|
|
962
|
-
},
|
|
963
425
|
className: [
|
|
964
|
-
"group relative flex shrink-0
|
|
426
|
+
"group relative flex shrink-0 flex-col items-center gap-1 rounded p-1 transition",
|
|
965
427
|
isActive ? "ring-2 ring-[var(--brand-primary)]" : "hover:bg-[var(--border-default)]/40",
|
|
966
428
|
dragOverIndex === index ? "ring-1 ring-[var(--brand-primary)]/60" : ""
|
|
967
429
|
].join(" "),
|
|
968
430
|
children: [
|
|
969
|
-
/* @__PURE__ */
|
|
970
|
-
"
|
|
431
|
+
/* @__PURE__ */ jsxs3(
|
|
432
|
+
"button",
|
|
971
433
|
{
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
434
|
+
type: "button",
|
|
435
|
+
"aria-label": `Page ${index + 1}: ${page.name}${isActive ? " (active)" : ""}`,
|
|
436
|
+
"aria-pressed": isActive,
|
|
437
|
+
onClick: () => onSelectPage(page.id),
|
|
438
|
+
className: "flex cursor-pointer flex-col items-center gap-1 rounded focus:outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--ring))]",
|
|
439
|
+
children: [
|
|
440
|
+
/* @__PURE__ */ jsx4(
|
|
441
|
+
"div",
|
|
442
|
+
{
|
|
443
|
+
className: "overflow-hidden rounded border border-[var(--border-default)] bg-[hsl(var(--card))]",
|
|
444
|
+
style: { width: THUMBNAIL_W, height: THUMBNAIL_H },
|
|
445
|
+
children: thumbUrl ? /* @__PURE__ */ jsx4(
|
|
446
|
+
"img",
|
|
447
|
+
{
|
|
448
|
+
src: thumbUrl,
|
|
449
|
+
alt: page.name,
|
|
450
|
+
className: "h-full w-full object-cover",
|
|
451
|
+
draggable: false
|
|
452
|
+
}
|
|
453
|
+
) : /* @__PURE__ */ jsx4("div", { className: "flex h-full w-full items-center justify-center", children: /* @__PURE__ */ jsx4(PageGlyph, { className: "h-5 w-5 text-[var(--text-muted)]" }) })
|
|
454
|
+
}
|
|
455
|
+
),
|
|
456
|
+
/* @__PURE__ */ jsx4("span", { className: "max-w-[80px] truncate text-[10px] text-[var(--text-secondary)]", children: page.name })
|
|
457
|
+
]
|
|
983
458
|
}
|
|
984
459
|
),
|
|
985
|
-
/* @__PURE__ */
|
|
986
|
-
|
|
987
|
-
/* @__PURE__ */ jsx3(
|
|
460
|
+
canWrite && canManagePages ? /* @__PURE__ */ jsxs3("div", { className: "pointer-events-none absolute -top-1 right-0 flex gap-0.5 opacity-0 transition-opacity group-hover:pointer-events-auto group-hover:opacity-100", children: [
|
|
461
|
+
/* @__PURE__ */ jsx4(
|
|
988
462
|
"button",
|
|
989
463
|
{
|
|
990
464
|
type: "button",
|
|
@@ -993,11 +467,11 @@ function PagesStrip({
|
|
|
993
467
|
event.stopPropagation();
|
|
994
468
|
onDuplicatePage(page.id);
|
|
995
469
|
},
|
|
996
|
-
className:
|
|
997
|
-
children: /* @__PURE__ */
|
|
470
|
+
className: BTN_SM,
|
|
471
|
+
children: /* @__PURE__ */ jsx4(DuplicateGlyph, { className: "h-3 w-3" })
|
|
998
472
|
}
|
|
999
473
|
),
|
|
1000
|
-
/* @__PURE__ */
|
|
474
|
+
/* @__PURE__ */ jsx4(
|
|
1001
475
|
"button",
|
|
1002
476
|
{
|
|
1003
477
|
type: "button",
|
|
@@ -1007,8 +481,8 @@ function PagesStrip({
|
|
|
1007
481
|
event.stopPropagation();
|
|
1008
482
|
if (pages.length > 1) onDeletePage(page.id);
|
|
1009
483
|
},
|
|
1010
|
-
className:
|
|
1011
|
-
children: /* @__PURE__ */
|
|
484
|
+
className: BTN_SM,
|
|
485
|
+
children: /* @__PURE__ */ jsx4(TrashGlyph, { className: "h-3 w-3 text-[var(--text-danger)]" })
|
|
1012
486
|
}
|
|
1013
487
|
)
|
|
1014
488
|
] }) : null
|
|
@@ -1017,16 +491,16 @@ function PagesStrip({
|
|
|
1017
491
|
page.id
|
|
1018
492
|
);
|
|
1019
493
|
}),
|
|
1020
|
-
canWrite ? /* @__PURE__ */ jsxs3(
|
|
494
|
+
canWrite && canManagePages ? /* @__PURE__ */ jsxs3(
|
|
1021
495
|
"button",
|
|
1022
496
|
{
|
|
1023
497
|
type: "button",
|
|
1024
498
|
"aria-label": "Add page",
|
|
1025
499
|
onClick: onAddPage,
|
|
1026
|
-
className: "flex h-[72px] w-[80px] shrink-0 flex-col items-center justify-center gap-1 rounded border border-dashed border-[var(--border-default)] text-[var(--text-muted)] transition hover:border-[var(--brand-primary)] hover:text-[var(--brand-primary)]",
|
|
500
|
+
className: "flex h-[72px] w-[80px] shrink-0 flex-col items-center justify-center gap-1 rounded border border-dashed border-[var(--border-default)] text-[var(--text-muted)] transition hover:border-[var(--brand-primary)] hover:text-[var(--brand-primary)] focus:outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--ring))]",
|
|
1027
501
|
children: [
|
|
1028
|
-
/* @__PURE__ */
|
|
1029
|
-
/* @__PURE__ */
|
|
502
|
+
/* @__PURE__ */ jsx4(PlusGlyph, { className: "h-4 w-4" }),
|
|
503
|
+
/* @__PURE__ */ jsx4("span", { className: "text-[10px]", children: "Add page" })
|
|
1030
504
|
]
|
|
1031
505
|
}
|
|
1032
506
|
) : null
|
|
@@ -1037,20 +511,20 @@ function PagesStrip({
|
|
|
1037
511
|
|
|
1038
512
|
// src/design-canvas-react/components/Rulers.tsx
|
|
1039
513
|
import { useRef as useRef2, useState as useState2 } from "react";
|
|
1040
|
-
import { Fragment as Fragment3, jsx as
|
|
514
|
+
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1041
515
|
var RULER_SIZE_PX = 20;
|
|
1042
516
|
var DELETE_THRESHOLD_PX = RULER_SIZE_PX + 4;
|
|
1043
517
|
function Rulers({ pageWidth, pageHeight, zoom, scrollLeft, scrollTop, showRulers, guides, onGuidesChange }) {
|
|
1044
518
|
if (!showRulers) return null;
|
|
1045
519
|
return /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1046
|
-
/* @__PURE__ */
|
|
520
|
+
/* @__PURE__ */ jsx5(
|
|
1047
521
|
"div",
|
|
1048
522
|
{
|
|
1049
523
|
className: "absolute top-0 left-0 z-20 shrink-0 border-b border-r border-[var(--border-default)] bg-[var(--bg-input)]",
|
|
1050
524
|
style: { width: RULER_SIZE_PX, height: RULER_SIZE_PX }
|
|
1051
525
|
}
|
|
1052
526
|
),
|
|
1053
|
-
/* @__PURE__ */
|
|
527
|
+
/* @__PURE__ */ jsx5(
|
|
1054
528
|
HorizontalRuler,
|
|
1055
529
|
{
|
|
1056
530
|
pageWidth,
|
|
@@ -1060,7 +534,7 @@ function Rulers({ pageWidth, pageHeight, zoom, scrollLeft, scrollTop, showRulers
|
|
|
1060
534
|
onGuidesChange
|
|
1061
535
|
}
|
|
1062
536
|
),
|
|
1063
|
-
/* @__PURE__ */
|
|
537
|
+
/* @__PURE__ */ jsx5(
|
|
1064
538
|
VerticalRuler,
|
|
1065
539
|
{
|
|
1066
540
|
pageHeight,
|
|
@@ -1148,18 +622,18 @@ function HorizontalRuler({ pageWidth, zoom, scrollLeft, guides, onGuidesChange }
|
|
|
1148
622
|
children: [
|
|
1149
623
|
ticks.map((tick) => {
|
|
1150
624
|
const screenX = tick.position * zoom - scrollLeft * zoom;
|
|
1151
|
-
return /* @__PURE__ */
|
|
625
|
+
return /* @__PURE__ */ jsx5(
|
|
1152
626
|
"div",
|
|
1153
627
|
{
|
|
1154
628
|
className: `absolute bottom-0 w-px bg-[var(--border-default)] ${tick.label !== null ? "top-1.5" : "top-[14px]"}`,
|
|
1155
629
|
style: { left: screenX },
|
|
1156
|
-
children: tick.label !== null ? /* @__PURE__ */
|
|
630
|
+
children: tick.label !== null ? /* @__PURE__ */ jsx5("span", { className: "absolute -top-1 left-0.5 whitespace-nowrap font-mono text-[9px] leading-none text-[var(--text-muted)]", children: tick.label }) : null
|
|
1157
631
|
},
|
|
1158
632
|
tick.position
|
|
1159
633
|
);
|
|
1160
634
|
}),
|
|
1161
|
-
pointerX !== null ? /* @__PURE__ */
|
|
1162
|
-
dragGuideX !== null ? /* @__PURE__ */
|
|
635
|
+
pointerX !== null ? /* @__PURE__ */ jsx5("div", { className: "pointer-events-none absolute top-0 bottom-0 w-px bg-[var(--brand-primary)]/60", style: { left: pointerX } }) : null,
|
|
636
|
+
dragGuideX !== null ? /* @__PURE__ */ jsx5(
|
|
1163
637
|
"div",
|
|
1164
638
|
{
|
|
1165
639
|
className: "pointer-events-none absolute top-0 bottom-0 w-px bg-[var(--brand-primary)]",
|
|
@@ -1242,12 +716,12 @@ function VerticalRuler({ pageHeight, zoom, scrollTop, guides, onGuidesChange })
|
|
|
1242
716
|
children: [
|
|
1243
717
|
ticks.map((tick) => {
|
|
1244
718
|
const screenY = tick.position * zoom - scrollTop * zoom;
|
|
1245
|
-
return /* @__PURE__ */
|
|
719
|
+
return /* @__PURE__ */ jsx5(
|
|
1246
720
|
"div",
|
|
1247
721
|
{
|
|
1248
722
|
className: `absolute right-0 h-px bg-[var(--border-default)] ${tick.label !== null ? "left-1.5" : "left-[14px]"}`,
|
|
1249
723
|
style: { top: screenY },
|
|
1250
|
-
children: tick.label !== null ? /* @__PURE__ */
|
|
724
|
+
children: tick.label !== null ? /* @__PURE__ */ jsx5(
|
|
1251
725
|
"span",
|
|
1252
726
|
{
|
|
1253
727
|
className: "absolute top-0.5 left-0 whitespace-nowrap font-mono text-[9px] leading-none text-[var(--text-muted)]",
|
|
@@ -1259,8 +733,8 @@ function VerticalRuler({ pageHeight, zoom, scrollTop, guides, onGuidesChange })
|
|
|
1259
733
|
tick.position
|
|
1260
734
|
);
|
|
1261
735
|
}),
|
|
1262
|
-
pointerY !== null ? /* @__PURE__ */
|
|
1263
|
-
dragGuideY !== null ? /* @__PURE__ */
|
|
736
|
+
pointerY !== null ? /* @__PURE__ */ jsx5("div", { className: "pointer-events-none absolute left-0 right-0 h-px bg-[var(--brand-primary)]/60", style: { top: pointerY } }) : null,
|
|
737
|
+
dragGuideY !== null ? /* @__PURE__ */ jsx5(
|
|
1264
738
|
"div",
|
|
1265
739
|
{
|
|
1266
740
|
className: "pointer-events-none absolute left-0 right-0 h-px bg-[var(--brand-primary)]",
|
|
@@ -1274,7 +748,7 @@ function VerticalRuler({ pageHeight, zoom, scrollTop, guides, onGuidesChange })
|
|
|
1274
748
|
|
|
1275
749
|
// src/design-canvas-react/components/Toolbar.tsx
|
|
1276
750
|
import { useEffect as useEffect2, useRef as useRef3, useState as useState3 } from "react";
|
|
1277
|
-
import { Fragment as Fragment4, jsx as
|
|
751
|
+
import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1278
752
|
var FONT_FAMILIES = [
|
|
1279
753
|
"Inter",
|
|
1280
754
|
"Arial",
|
|
@@ -1289,9 +763,7 @@ var FONT_FAMILIES = [
|
|
|
1289
763
|
"Brush Script MT",
|
|
1290
764
|
"Impact"
|
|
1291
765
|
];
|
|
1292
|
-
var
|
|
1293
|
-
var BTN_ACTIVE = `${BTN2} border-[var(--brand-primary)] text-[var(--brand-primary)] hover:text-[var(--brand-primary)]`;
|
|
1294
|
-
var SEP = /* @__PURE__ */ jsx5("div", { className: "mx-1 h-5 w-px shrink-0 bg-[var(--border-default)]" });
|
|
766
|
+
var SEP = /* @__PURE__ */ jsx6("div", { className: "mx-1 h-5 w-px shrink-0 bg-[var(--border-default)]" });
|
|
1295
767
|
var POPOVER_PANEL = "absolute top-full left-0 z-50 mt-1 flex flex-col rounded border border-[var(--border-default)] bg-[var(--bg-input)] shadow-lg";
|
|
1296
768
|
function Popover({
|
|
1297
769
|
open,
|
|
@@ -1336,8 +808,8 @@ function NumberInput({
|
|
|
1336
808
|
setRaw(null);
|
|
1337
809
|
}
|
|
1338
810
|
return /* @__PURE__ */ jsxs5("label", { className: "flex flex-col items-center gap-0.5", children: [
|
|
1339
|
-
/* @__PURE__ */
|
|
1340
|
-
/* @__PURE__ */
|
|
811
|
+
/* @__PURE__ */ jsx6("span", { className: FIELD_LABEL, children: label }),
|
|
812
|
+
/* @__PURE__ */ jsx6(
|
|
1341
813
|
"input",
|
|
1342
814
|
{
|
|
1343
815
|
type: "number",
|
|
@@ -1366,8 +838,8 @@ function SelectControl({
|
|
|
1366
838
|
const [open, setOpen] = useState3(false);
|
|
1367
839
|
const current = options.find((o) => o.value === value);
|
|
1368
840
|
return /* @__PURE__ */ jsxs5("label", { className: "flex flex-col items-center gap-0.5", children: [
|
|
1369
|
-
/* @__PURE__ */
|
|
1370
|
-
/* @__PURE__ */
|
|
841
|
+
/* @__PURE__ */ jsx6("span", { className: FIELD_LABEL, children: label }),
|
|
842
|
+
/* @__PURE__ */ jsx6(
|
|
1371
843
|
Popover,
|
|
1372
844
|
{
|
|
1373
845
|
open,
|
|
@@ -1382,12 +854,12 @@ function SelectControl({
|
|
|
1382
854
|
onClick: () => setOpen((v) => !v),
|
|
1383
855
|
className: `${buttonClassName} flex items-center justify-between gap-1 rounded border border-[var(--border-default)] bg-[var(--bg-input)] px-2 py-0.5 text-left text-[12px] text-[var(--text-primary)] outline-none hover:border-[var(--brand-primary)] disabled:cursor-default disabled:opacity-40`,
|
|
1384
856
|
children: [
|
|
1385
|
-
/* @__PURE__ */
|
|
1386
|
-
/* @__PURE__ */
|
|
857
|
+
/* @__PURE__ */ jsx6("span", { className: "truncate", children: current?.label ?? value }),
|
|
858
|
+
/* @__PURE__ */ jsx6("span", { className: "text-[8px] text-[var(--text-muted)]", children: "\u25BE" })
|
|
1387
859
|
]
|
|
1388
860
|
}
|
|
1389
861
|
),
|
|
1390
|
-
children: /* @__PURE__ */
|
|
862
|
+
children: /* @__PURE__ */ jsx6("div", { role: "listbox", className: `${POPOVER_PANEL} max-h-64 w-44 overflow-y-auto py-1`, children: options.map((opt) => /* @__PURE__ */ jsx6(
|
|
1391
863
|
"button",
|
|
1392
864
|
{
|
|
1393
865
|
type: "button",
|
|
@@ -1416,8 +888,8 @@ function FontPicker({
|
|
|
1416
888
|
const families = FONT_FAMILIES.includes(value) ? [...FONT_FAMILIES] : [value, ...FONT_FAMILIES];
|
|
1417
889
|
const filtered = families.filter((f) => f.toLowerCase().includes(query.trim().toLowerCase()));
|
|
1418
890
|
return /* @__PURE__ */ jsxs5("label", { className: "flex flex-col items-center gap-0.5", children: [
|
|
1419
|
-
/* @__PURE__ */
|
|
1420
|
-
/* @__PURE__ */
|
|
891
|
+
/* @__PURE__ */ jsx6("span", { className: FIELD_LABEL, children: "Font" }),
|
|
892
|
+
/* @__PURE__ */ jsx6(
|
|
1421
893
|
Popover,
|
|
1422
894
|
{
|
|
1423
895
|
open,
|
|
@@ -1437,13 +909,13 @@ function FontPicker({
|
|
|
1437
909
|
className: "flex w-28 items-center justify-between gap-1 rounded border border-[var(--border-default)] bg-[var(--bg-input)] px-2 py-0.5 text-left text-[12px] text-[var(--text-primary)] outline-none hover:border-[var(--brand-primary)] disabled:cursor-default disabled:opacity-40",
|
|
1438
910
|
style: { fontFamily: value },
|
|
1439
911
|
children: [
|
|
1440
|
-
/* @__PURE__ */
|
|
1441
|
-
/* @__PURE__ */
|
|
912
|
+
/* @__PURE__ */ jsx6("span", { className: "truncate", children: value }),
|
|
913
|
+
/* @__PURE__ */ jsx6("span", { className: "text-[8px] text-[var(--text-muted)]", children: "\u25BE" })
|
|
1442
914
|
]
|
|
1443
915
|
}
|
|
1444
916
|
),
|
|
1445
917
|
children: /* @__PURE__ */ jsxs5("div", { className: `${POPOVER_PANEL} w-52`, children: [
|
|
1446
|
-
/* @__PURE__ */
|
|
918
|
+
/* @__PURE__ */ jsx6(
|
|
1447
919
|
"input",
|
|
1448
920
|
{
|
|
1449
921
|
autoFocus: true,
|
|
@@ -1454,7 +926,7 @@ function FontPicker({
|
|
|
1454
926
|
className: "m-1 rounded border border-[var(--border-default)] bg-transparent px-2 py-1 text-[12px] text-[var(--text-primary)] outline-none focus:border-[var(--brand-primary)]"
|
|
1455
927
|
}
|
|
1456
928
|
),
|
|
1457
|
-
/* @__PURE__ */
|
|
929
|
+
/* @__PURE__ */ jsx6("div", { role: "listbox", className: "max-h-60 overflow-y-auto py-1", children: filtered.length === 0 ? /* @__PURE__ */ jsx6("div", { className: "px-3 py-2 text-[11px] text-[var(--text-muted)]", children: "No matches" }) : filtered.map((family) => /* @__PURE__ */ jsx6(
|
|
1458
930
|
"button",
|
|
1459
931
|
{
|
|
1460
932
|
type: "button",
|
|
@@ -1480,13 +952,13 @@ function ColorSwatch({ label, value, onCommit, disabled }) {
|
|
|
1480
952
|
const [open, setOpen] = useState3(false);
|
|
1481
953
|
const normalized = value.startsWith("#") ? value : "#ffffff";
|
|
1482
954
|
return /* @__PURE__ */ jsxs5("div", { className: "flex flex-col items-center gap-0.5", children: [
|
|
1483
|
-
/* @__PURE__ */
|
|
1484
|
-
/* @__PURE__ */
|
|
955
|
+
/* @__PURE__ */ jsx6("span", { className: FIELD_LABEL, children: label }),
|
|
956
|
+
/* @__PURE__ */ jsx6(
|
|
1485
957
|
Popover,
|
|
1486
958
|
{
|
|
1487
959
|
open,
|
|
1488
960
|
onClose: () => setOpen(false),
|
|
1489
|
-
trigger: /* @__PURE__ */
|
|
961
|
+
trigger: /* @__PURE__ */ jsx6(
|
|
1490
962
|
"button",
|
|
1491
963
|
{
|
|
1492
964
|
type: "button",
|
|
@@ -1498,7 +970,7 @@ function ColorSwatch({ label, value, onCommit, disabled }) {
|
|
|
1498
970
|
}
|
|
1499
971
|
),
|
|
1500
972
|
children: /* @__PURE__ */ jsxs5("div", { className: `${POPOVER_PANEL} w-40 gap-2 p-2`, children: [
|
|
1501
|
-
/* @__PURE__ */
|
|
973
|
+
/* @__PURE__ */ jsx6(
|
|
1502
974
|
"input",
|
|
1503
975
|
{
|
|
1504
976
|
type: "color",
|
|
@@ -1508,7 +980,7 @@ function ColorSwatch({ label, value, onCommit, disabled }) {
|
|
|
1508
980
|
className: "h-8 w-full cursor-pointer rounded border border-[var(--border-default)] p-0.5"
|
|
1509
981
|
}
|
|
1510
982
|
),
|
|
1511
|
-
/* @__PURE__ */
|
|
983
|
+
/* @__PURE__ */ jsx6(
|
|
1512
984
|
"input",
|
|
1513
985
|
{
|
|
1514
986
|
type: "text",
|
|
@@ -1527,6 +999,7 @@ function Toolbar({
|
|
|
1527
999
|
page,
|
|
1528
1000
|
selectedElements,
|
|
1529
1001
|
canWrite,
|
|
1002
|
+
mode = "edit",
|
|
1530
1003
|
canUndo,
|
|
1531
1004
|
canRedo,
|
|
1532
1005
|
gridEnabled,
|
|
@@ -1562,46 +1035,55 @@ function Toolbar({
|
|
|
1562
1035
|
const selectedIds = selectedElements.map((e) => e.id);
|
|
1563
1036
|
const isGroup = single?.kind === "group";
|
|
1564
1037
|
const groupable = selectedElements.length >= 2;
|
|
1038
|
+
const review = mode === "review";
|
|
1565
1039
|
return /* @__PURE__ */ jsxs5("div", { className: "flex min-h-11 shrink-0 flex-wrap items-center gap-x-2 gap-y-1 border-b border-[var(--border-default)] bg-[var(--bg-input)] px-3 py-1", children: [
|
|
1566
1040
|
/* @__PURE__ */ jsxs5("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
1567
|
-
/* @__PURE__ */
|
|
1568
|
-
/* @__PURE__ */
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1041
|
+
/* @__PURE__ */ jsx6("button", { type: "button", "aria-label": "Undo", disabled: !canUndo || !canWrite, onClick: onUndo, className: BTN, children: /* @__PURE__ */ jsx6(UndoGlyph, { className: "h-3.5 w-3.5" }) }),
|
|
1042
|
+
/* @__PURE__ */ jsx6("button", { type: "button", "aria-label": "Redo", disabled: !canRedo || !canWrite, onClick: onRedo, className: BTN, children: /* @__PURE__ */ jsx6(RedoGlyph, { className: "h-3.5 w-3.5" }) }),
|
|
1043
|
+
!review ? /* @__PURE__ */ jsxs5(Fragment4, { children: [
|
|
1044
|
+
SEP,
|
|
1045
|
+
/* @__PURE__ */ jsx6("button", { type: "button", "aria-label": "Toggle rulers", "aria-pressed": showRulers, onClick: onToggleRulers, className: showRulers ? BTN_ACTIVE : BTN, children: /* @__PURE__ */ jsx6(RulerGlyph, { className: "h-3.5 w-3.5" }) }),
|
|
1046
|
+
/* @__PURE__ */ jsx6("button", { type: "button", "aria-label": "Toggle grid", "aria-pressed": gridEnabled, onClick: onToggleGrid, className: gridEnabled ? BTN_ACTIVE : BTN, children: /* @__PURE__ */ jsx6(GridGlyph, { className: "h-3.5 w-3.5" }) }),
|
|
1047
|
+
/* @__PURE__ */ jsx6("button", { type: "button", "aria-label": "Toggle snap", "aria-pressed": snapEnabled, onClick: onToggleSnap, className: snapEnabled ? BTN_ACTIVE : BTN, children: /* @__PURE__ */ jsx6(MagnetGlyph, { className: "h-3.5 w-3.5" }) }),
|
|
1048
|
+
/* @__PURE__ */ jsx6("button", { type: "button", "aria-label": "Toggle bleed overlay", "aria-pressed": showBleed, onClick: onToggleBleed, className: showBleed ? BTN_ACTIVE : BTN, disabled: !page.bleed, children: /* @__PURE__ */ jsx6(BleedGlyph, { className: "h-3.5 w-3.5" }) })
|
|
1049
|
+
] }) : null
|
|
1574
1050
|
] }),
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1051
|
+
/* @__PURE__ */ jsx6("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-1", children: hasSelection ? /* @__PURE__ */ jsxs5(Fragment4, { children: [
|
|
1052
|
+
SEP,
|
|
1053
|
+
/* @__PURE__ */ jsx6(
|
|
1054
|
+
SelectionControls,
|
|
1055
|
+
{
|
|
1056
|
+
elements: selectedElements,
|
|
1057
|
+
single,
|
|
1058
|
+
isGroup,
|
|
1059
|
+
groupable,
|
|
1060
|
+
allSameKind,
|
|
1061
|
+
firstKind,
|
|
1062
|
+
canWrite,
|
|
1063
|
+
review,
|
|
1064
|
+
patchAll,
|
|
1065
|
+
reorderSingle,
|
|
1066
|
+
onGroup: () => onGroup(selectedIds),
|
|
1067
|
+
onUngroup: () => {
|
|
1068
|
+
if (single) onUngroup(single.id);
|
|
1069
|
+
},
|
|
1070
|
+
onDelete: () => onDelete(selectedIds),
|
|
1071
|
+
onBindSlot: single ? (slot) => onBindSlot(single.id, slot) : void 0,
|
|
1072
|
+
currentSlot: single?.slot ?? null
|
|
1073
|
+
}
|
|
1074
|
+
)
|
|
1075
|
+
] }) : !review ? /* @__PURE__ */ jsxs5(Fragment4, { children: [
|
|
1076
|
+
SEP,
|
|
1077
|
+
/* @__PURE__ */ jsx6(
|
|
1078
|
+
PagePropsControls,
|
|
1079
|
+
{
|
|
1080
|
+
page,
|
|
1081
|
+
canWrite,
|
|
1082
|
+
onSetPageProps,
|
|
1083
|
+
onSetPageGuides
|
|
1084
|
+
}
|
|
1085
|
+
)
|
|
1086
|
+
] }) : null })
|
|
1605
1087
|
] });
|
|
1606
1088
|
}
|
|
1607
1089
|
function SelectionControls({
|
|
@@ -1612,6 +1094,7 @@ function SelectionControls({
|
|
|
1612
1094
|
allSameKind,
|
|
1613
1095
|
firstKind,
|
|
1614
1096
|
canWrite,
|
|
1097
|
+
review,
|
|
1615
1098
|
patchAll,
|
|
1616
1099
|
reorderSingle,
|
|
1617
1100
|
onGroup,
|
|
@@ -1624,12 +1107,12 @@ function SelectionControls({
|
|
|
1624
1107
|
const [slotInput, setSlotInput] = useState3("");
|
|
1625
1108
|
const firstEl = elements[0];
|
|
1626
1109
|
return /* @__PURE__ */ jsxs5(Fragment4, { children: [
|
|
1627
|
-
allSameKind && firstKind === "text" && single ? /* @__PURE__ */
|
|
1628
|
-
allSameKind && firstKind === "rect" && single ? /* @__PURE__ */
|
|
1629
|
-
allSameKind && firstKind === "ellipse" && single ? /* @__PURE__ */
|
|
1630
|
-
allSameKind && firstKind === "image" && single ? /* @__PURE__ */
|
|
1110
|
+
allSameKind && firstKind === "text" && single ? /* @__PURE__ */ jsx6(TextControls, { element: single, canWrite, onPatch: (attrs) => patchAll(attrs) }) : null,
|
|
1111
|
+
allSameKind && firstKind === "rect" && single ? /* @__PURE__ */ jsx6(ShapeControls, { element: single, canWrite, onPatch: (attrs) => patchAll(attrs), showCornerRadius: true }) : null,
|
|
1112
|
+
allSameKind && firstKind === "ellipse" && single ? /* @__PURE__ */ jsx6(ShapeControls, { element: single, canWrite, onPatch: (attrs) => patchAll(attrs), showCornerRadius: false }) : null,
|
|
1113
|
+
allSameKind && firstKind === "image" && single ? /* @__PURE__ */ jsx6(ImageControls, { element: single, canWrite, onPatch: (attrs) => patchAll(attrs) }) : null,
|
|
1631
1114
|
SEP,
|
|
1632
|
-
/* @__PURE__ */
|
|
1115
|
+
/* @__PURE__ */ jsx6(
|
|
1633
1116
|
NumberInput,
|
|
1634
1117
|
{
|
|
1635
1118
|
label: "Opacity",
|
|
@@ -1639,7 +1122,7 @@ function SelectionControls({
|
|
|
1639
1122
|
className: "w-14"
|
|
1640
1123
|
}
|
|
1641
1124
|
),
|
|
1642
|
-
/* @__PURE__ */
|
|
1125
|
+
/* @__PURE__ */ jsx6(
|
|
1643
1126
|
NumberInput,
|
|
1644
1127
|
{
|
|
1645
1128
|
label: "Rotation",
|
|
@@ -1648,152 +1131,225 @@ function SelectionControls({
|
|
|
1648
1131
|
className: "w-14"
|
|
1649
1132
|
}
|
|
1650
1133
|
),
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
"aria-label": currentSlot ? `Slot: ${currentSlot}` : "Bind slot",
|
|
1680
|
-
onClick: () => {
|
|
1681
|
-
setSlotInput(currentSlot ?? "");
|
|
1682
|
-
setSlotPopoverOpen((v) => !v);
|
|
1683
|
-
},
|
|
1684
|
-
className: currentSlot ? BTN_ACTIVE : BTN2,
|
|
1685
|
-
title: currentSlot ? `Slot: ${currentSlot}` : "Bind slot",
|
|
1686
|
-
children: /* @__PURE__ */ jsx5(SlotGlyph, { className: "h-3.5 w-3.5" })
|
|
1687
|
-
}
|
|
1688
|
-
),
|
|
1689
|
-
children: /* @__PURE__ */ jsxs5("div", { className: `${POPOVER_PANEL} w-48 gap-2 p-2`, children: [
|
|
1690
|
-
/* @__PURE__ */ jsx5(
|
|
1691
|
-
"input",
|
|
1134
|
+
review ? null : /* @__PURE__ */ jsxs5(Fragment4, { children: [
|
|
1135
|
+
SEP,
|
|
1136
|
+
single ? /* @__PURE__ */ jsxs5(Fragment4, { children: [
|
|
1137
|
+
/* @__PURE__ */ jsx6("button", { type: "button", "aria-label": "Bring to front", disabled: !canWrite, onClick: () => reorderSingle("front"), className: BTN, children: /* @__PURE__ */ jsx6(BringFrontGlyph, { className: "h-3.5 w-3.5" }) }),
|
|
1138
|
+
/* @__PURE__ */ jsx6("button", { type: "button", "aria-label": "Send to back", disabled: !canWrite, onClick: () => reorderSingle("back"), className: BTN, children: /* @__PURE__ */ jsx6(SendBackGlyph, { className: "h-3.5 w-3.5" }) }),
|
|
1139
|
+
SEP
|
|
1140
|
+
] }) : null,
|
|
1141
|
+
groupable ? /* @__PURE__ */ jsx6("button", { type: "button", "aria-label": "Group elements", disabled: !canWrite, onClick: onGroup, className: BTN, children: /* @__PURE__ */ jsx6(GroupGlyph, { className: "h-3.5 w-3.5" }) }) : null,
|
|
1142
|
+
isGroup ? /* @__PURE__ */ jsx6("button", { type: "button", "aria-label": "Ungroup", disabled: !canWrite, onClick: onUngroup, className: BTN, children: /* @__PURE__ */ jsx6(UngroupGlyph, { className: "h-3.5 w-3.5" }) }) : null,
|
|
1143
|
+
single ? /* @__PURE__ */ jsx6(
|
|
1144
|
+
"button",
|
|
1145
|
+
{
|
|
1146
|
+
type: "button",
|
|
1147
|
+
"aria-label": single.locked ? "Unlock element" : "Lock element",
|
|
1148
|
+
"aria-pressed": !!single.locked,
|
|
1149
|
+
disabled: !canWrite,
|
|
1150
|
+
onClick: () => patchAll({ locked: !single.locked }),
|
|
1151
|
+
className: single.locked ? BTN_ACTIVE : BTN,
|
|
1152
|
+
children: single.locked ? /* @__PURE__ */ jsx6(LockGlyph, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx6(UnlockGlyph, { className: "h-3.5 w-3.5" })
|
|
1153
|
+
}
|
|
1154
|
+
) : null,
|
|
1155
|
+
single && onBindSlot ? /* @__PURE__ */ jsx6(
|
|
1156
|
+
Popover,
|
|
1157
|
+
{
|
|
1158
|
+
open: slotPopoverOpen,
|
|
1159
|
+
onClose: () => setSlotPopoverOpen(false),
|
|
1160
|
+
trigger: /* @__PURE__ */ jsx6(
|
|
1161
|
+
"button",
|
|
1692
1162
|
{
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1163
|
+
type: "button",
|
|
1164
|
+
"aria-label": currentSlot ? `Slot: ${currentSlot}` : "Bind slot",
|
|
1165
|
+
"aria-pressed": !!currentSlot,
|
|
1166
|
+
"aria-haspopup": "dialog",
|
|
1167
|
+
"aria-expanded": slotPopoverOpen,
|
|
1168
|
+
onClick: () => {
|
|
1169
|
+
setSlotInput(currentSlot ?? "");
|
|
1170
|
+
setSlotPopoverOpen((v) => !v);
|
|
1171
|
+
},
|
|
1172
|
+
className: currentSlot ? BTN_ACTIVE : BTN,
|
|
1173
|
+
title: currentSlot ? `Slot: ${currentSlot}` : "Bind slot",
|
|
1174
|
+
children: /* @__PURE__ */ jsx6(SlotGlyph, { className: "h-3.5 w-3.5" })
|
|
1698
1175
|
}
|
|
1699
1176
|
),
|
|
1700
|
-
/* @__PURE__ */ jsxs5("div", { className:
|
|
1701
|
-
/* @__PURE__ */
|
|
1702
|
-
"
|
|
1177
|
+
children: /* @__PURE__ */ jsxs5("div", { className: `${POPOVER_PANEL} w-48 gap-2 p-2`, children: [
|
|
1178
|
+
/* @__PURE__ */ jsx6(
|
|
1179
|
+
"input",
|
|
1703
1180
|
{
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
className: "flex-1 rounded border border-[var(--brand-primary)] px-2 py-0.5 text-[11px] text-[var(--brand-primary)] hover:bg-[var(--brand-primary)]/10",
|
|
1710
|
-
children: slotInput.trim() ? "Bind" : "Unbind"
|
|
1181
|
+
autoFocus: true,
|
|
1182
|
+
value: slotInput,
|
|
1183
|
+
onChange: (event) => setSlotInput(event.target.value),
|
|
1184
|
+
placeholder: "slot-name",
|
|
1185
|
+
className: "rounded border border-[var(--border-default)] bg-transparent px-2 py-1 text-[12px] text-[var(--text-primary)] outline-none focus:border-[var(--brand-primary)]"
|
|
1711
1186
|
}
|
|
1712
1187
|
),
|
|
1713
|
-
/* @__PURE__ */
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1188
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex gap-2", children: [
|
|
1189
|
+
/* @__PURE__ */ jsx6(
|
|
1190
|
+
"button",
|
|
1191
|
+
{
|
|
1192
|
+
type: "button",
|
|
1193
|
+
onClick: () => {
|
|
1194
|
+
onBindSlot(slotInput.trim() || null);
|
|
1195
|
+
setSlotPopoverOpen(false);
|
|
1196
|
+
},
|
|
1197
|
+
className: "flex-1 rounded border border-[var(--brand-primary)] px-2 py-0.5 text-[11px] text-[var(--brand-primary)] hover:bg-[var(--brand-primary)]/10",
|
|
1198
|
+
children: slotInput.trim() ? "Bind" : "Unbind"
|
|
1199
|
+
}
|
|
1200
|
+
),
|
|
1201
|
+
/* @__PURE__ */ jsx6(
|
|
1202
|
+
"button",
|
|
1203
|
+
{
|
|
1204
|
+
type: "button",
|
|
1205
|
+
onClick: () => setSlotPopoverOpen(false),
|
|
1206
|
+
className: "rounded border border-[var(--border-default)] px-2 py-0.5 text-[11px] text-[var(--text-secondary)]",
|
|
1207
|
+
children: "Cancel"
|
|
1208
|
+
}
|
|
1209
|
+
)
|
|
1210
|
+
] })
|
|
1722
1211
|
] })
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1212
|
+
}
|
|
1213
|
+
) : null,
|
|
1214
|
+
SEP,
|
|
1215
|
+
/* @__PURE__ */ jsx6("button", { type: "button", "aria-label": "Delete selection", disabled: !canWrite, onClick: onDelete, className: BTN, children: /* @__PURE__ */ jsx6(TrashGlyph, { className: "h-3.5 w-3.5 text-[var(--text-danger)]" }) })
|
|
1216
|
+
] })
|
|
1728
1217
|
] });
|
|
1729
1218
|
}
|
|
1730
1219
|
function TextControls({ element, canWrite, onPatch }) {
|
|
1731
1220
|
return /* @__PURE__ */ jsxs5(Fragment4, { children: [
|
|
1732
|
-
/* @__PURE__ */
|
|
1733
|
-
/* @__PURE__ */
|
|
1734
|
-
/* @__PURE__ */
|
|
1221
|
+
/* @__PURE__ */ jsx6(FontPicker, { value: element.fontFamily, disabled: !canWrite, onChange: (fontFamily) => onPatch({ fontFamily }) }),
|
|
1222
|
+
/* @__PURE__ */ jsx6(NumberInput, { label: "Size", value: element.fontSize, min: 1, onCommit: (v) => onPatch({ fontSize: v }), className: "w-12" }),
|
|
1223
|
+
/* @__PURE__ */ jsx6(
|
|
1735
1224
|
"button",
|
|
1736
1225
|
{
|
|
1737
1226
|
type: "button",
|
|
1738
1227
|
"aria-label": "Bold",
|
|
1228
|
+
"aria-pressed": !!element.fontStyle?.includes("bold"),
|
|
1739
1229
|
disabled: !canWrite,
|
|
1740
1230
|
onClick: () => onPatch({ fontStyle: element.fontStyle === "bold" || element.fontStyle === "bold italic" ? element.fontStyle === "bold italic" ? "italic" : "normal" : element.fontStyle === "italic" ? "bold italic" : "bold" }),
|
|
1741
|
-
className: element.fontStyle?.includes("bold") ? BTN_ACTIVE :
|
|
1742
|
-
children: /* @__PURE__ */
|
|
1231
|
+
className: element.fontStyle?.includes("bold") ? BTN_ACTIVE : BTN,
|
|
1232
|
+
children: /* @__PURE__ */ jsx6(BoldGlyph, { className: "h-3.5 w-3.5" })
|
|
1743
1233
|
}
|
|
1744
1234
|
),
|
|
1745
|
-
/* @__PURE__ */
|
|
1235
|
+
/* @__PURE__ */ jsx6(
|
|
1746
1236
|
"button",
|
|
1747
1237
|
{
|
|
1748
1238
|
type: "button",
|
|
1749
1239
|
"aria-label": "Italic",
|
|
1240
|
+
"aria-pressed": !!element.fontStyle?.includes("italic"),
|
|
1750
1241
|
disabled: !canWrite,
|
|
1751
1242
|
onClick: () => onPatch({ fontStyle: element.fontStyle === "italic" || element.fontStyle === "bold italic" ? element.fontStyle === "bold italic" ? "bold" : "normal" : element.fontStyle === "bold" ? "bold italic" : "italic" }),
|
|
1752
|
-
className: element.fontStyle?.includes("italic") ? BTN_ACTIVE :
|
|
1753
|
-
children: /* @__PURE__ */
|
|
1243
|
+
className: element.fontStyle?.includes("italic") ? BTN_ACTIVE : BTN,
|
|
1244
|
+
children: /* @__PURE__ */ jsx6(ItalicGlyph, { className: "h-3.5 w-3.5" })
|
|
1754
1245
|
}
|
|
1755
1246
|
),
|
|
1756
|
-
["left", "center", "right"].map((align) => /* @__PURE__ */
|
|
1247
|
+
/* @__PURE__ */ jsx6("div", { role: "radiogroup", "aria-label": "Text alignment", className: "flex items-center gap-2", children: ["left", "center", "right"].map((align) => /* @__PURE__ */ jsx6(
|
|
1757
1248
|
"button",
|
|
1758
1249
|
{
|
|
1759
1250
|
type: "button",
|
|
1251
|
+
role: "radio",
|
|
1760
1252
|
"aria-label": `Align ${align}`,
|
|
1253
|
+
"aria-checked": element.align === align,
|
|
1761
1254
|
disabled: !canWrite,
|
|
1762
1255
|
onClick: () => onPatch({ align }),
|
|
1763
|
-
className: element.align === align ? BTN_ACTIVE :
|
|
1764
|
-
children: align === "left" ? /* @__PURE__ */
|
|
1256
|
+
className: element.align === align ? BTN_ACTIVE : BTN,
|
|
1257
|
+
children: align === "left" ? /* @__PURE__ */ jsx6(AlignLeftGlyph, { className: "h-3.5 w-3.5" }) : align === "center" ? /* @__PURE__ */ jsx6(AlignCenterGlyph, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx6(AlignRightGlyph, { className: "h-3.5 w-3.5" })
|
|
1765
1258
|
},
|
|
1766
1259
|
align
|
|
1767
|
-
)),
|
|
1768
|
-
/* @__PURE__ */
|
|
1769
|
-
/* @__PURE__ */
|
|
1770
|
-
/* @__PURE__ */
|
|
1260
|
+
)) }),
|
|
1261
|
+
/* @__PURE__ */ jsx6(NumberInput, { label: "Line H", value: element.lineHeight, step: 0.1, min: 0.5, onCommit: (v) => onPatch({ lineHeight: v }), className: "w-12" }),
|
|
1262
|
+
/* @__PURE__ */ jsx6(NumberInput, { label: "Spacing", value: element.letterSpacing, step: 0.5, onCommit: (v) => onPatch({ letterSpacing: v }), className: "w-14" }),
|
|
1263
|
+
/* @__PURE__ */ jsx6(ColorSwatch, { label: "Fill", value: element.fill, onCommit: (v) => onPatch({ fill: v }), disabled: !canWrite })
|
|
1771
1264
|
] });
|
|
1772
1265
|
}
|
|
1773
1266
|
function ShapeControls({ element, canWrite, onPatch, showCornerRadius }) {
|
|
1774
1267
|
return /* @__PURE__ */ jsxs5(Fragment4, { children: [
|
|
1775
|
-
/* @__PURE__ */
|
|
1776
|
-
/* @__PURE__ */
|
|
1777
|
-
/* @__PURE__ */
|
|
1778
|
-
showCornerRadius && "cornerRadius" in element ? /* @__PURE__ */
|
|
1268
|
+
/* @__PURE__ */ jsx6(ColorSwatch, { label: "Fill", value: element.fill, onCommit: (v) => onPatch({ fill: v }), disabled: !canWrite }),
|
|
1269
|
+
/* @__PURE__ */ jsx6(ColorSwatch, { label: "Stroke", value: element.stroke ?? "#000000", onCommit: (v) => onPatch({ stroke: v }), disabled: !canWrite }),
|
|
1270
|
+
/* @__PURE__ */ jsx6(NumberInput, { label: "Stroke W", value: element.strokeWidth ?? 0, min: 0, onCommit: (v) => onPatch({ strokeWidth: v }), className: "w-14" }),
|
|
1271
|
+
showCornerRadius && "cornerRadius" in element ? /* @__PURE__ */ jsx6(NumberInput, { label: "Corner R", value: element.cornerRadius ?? 0, min: 0, onCommit: (v) => onPatch({ cornerRadius: v }), className: "w-14" }) : null
|
|
1779
1272
|
] });
|
|
1780
1273
|
}
|
|
1781
1274
|
function ImageControls({ element, canWrite, onPatch }) {
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1275
|
+
const [swapOpen, setSwapOpen] = useState3(false);
|
|
1276
|
+
const [swapUrl, setSwapUrl] = useState3("");
|
|
1277
|
+
return /* @__PURE__ */ jsxs5(Fragment4, { children: [
|
|
1278
|
+
/* @__PURE__ */ jsx6(
|
|
1279
|
+
SelectControl,
|
|
1280
|
+
{
|
|
1281
|
+
label: "Fit",
|
|
1282
|
+
value: element.fit,
|
|
1283
|
+
disabled: !canWrite,
|
|
1284
|
+
onChange: (fit) => onPatch({ fit }),
|
|
1285
|
+
buttonClassName: "w-24",
|
|
1286
|
+
options: [
|
|
1287
|
+
{ value: "fill", label: "Fill" },
|
|
1288
|
+
{ value: "cover", label: "Cover" },
|
|
1289
|
+
{ value: "contain", label: "Contain" }
|
|
1290
|
+
]
|
|
1291
|
+
}
|
|
1292
|
+
),
|
|
1293
|
+
/* @__PURE__ */ jsx6(
|
|
1294
|
+
Popover,
|
|
1295
|
+
{
|
|
1296
|
+
open: swapOpen,
|
|
1297
|
+
onClose: () => setSwapOpen(false),
|
|
1298
|
+
trigger: /* @__PURE__ */ jsx6(
|
|
1299
|
+
"button",
|
|
1300
|
+
{
|
|
1301
|
+
type: "button",
|
|
1302
|
+
"aria-label": "Replace image",
|
|
1303
|
+
disabled: !canWrite,
|
|
1304
|
+
onClick: () => {
|
|
1305
|
+
setSwapUrl(element.src);
|
|
1306
|
+
setSwapOpen((v) => !v);
|
|
1307
|
+
},
|
|
1308
|
+
className: BTN,
|
|
1309
|
+
title: "Replace image",
|
|
1310
|
+
children: /* @__PURE__ */ jsx6(SwapGlyph, { className: "h-3.5 w-3.5" })
|
|
1311
|
+
}
|
|
1312
|
+
),
|
|
1313
|
+
children: /* @__PURE__ */ jsxs5("div", { className: `${POPOVER_PANEL} w-64 gap-2 p-2`, children: [
|
|
1314
|
+
/* @__PURE__ */ jsx6(
|
|
1315
|
+
"input",
|
|
1316
|
+
{
|
|
1317
|
+
autoFocus: true,
|
|
1318
|
+
value: swapUrl,
|
|
1319
|
+
onChange: (event) => setSwapUrl(event.target.value),
|
|
1320
|
+
placeholder: "https://\u2026 image URL",
|
|
1321
|
+
"aria-label": "New image URL",
|
|
1322
|
+
className: "rounded border border-[var(--border-default)] bg-transparent px-2 py-1 text-[12px] text-[var(--text-primary)] outline-none focus:border-[var(--brand-primary)]"
|
|
1323
|
+
}
|
|
1324
|
+
),
|
|
1325
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex gap-2", children: [
|
|
1326
|
+
/* @__PURE__ */ jsx6(
|
|
1327
|
+
"button",
|
|
1328
|
+
{
|
|
1329
|
+
type: "button",
|
|
1330
|
+
disabled: !swapUrl.trim() || swapUrl.trim() === element.src,
|
|
1331
|
+
onClick: () => {
|
|
1332
|
+
onPatch({ src: swapUrl.trim() });
|
|
1333
|
+
setSwapOpen(false);
|
|
1334
|
+
},
|
|
1335
|
+
className: "flex-1 rounded border border-[var(--brand-primary)] px-2 py-0.5 text-[11px] text-[var(--brand-primary)] hover:bg-[var(--brand-primary)]/10 disabled:cursor-default disabled:opacity-40",
|
|
1336
|
+
children: "Replace"
|
|
1337
|
+
}
|
|
1338
|
+
),
|
|
1339
|
+
/* @__PURE__ */ jsx6(
|
|
1340
|
+
"button",
|
|
1341
|
+
{
|
|
1342
|
+
type: "button",
|
|
1343
|
+
onClick: () => setSwapOpen(false),
|
|
1344
|
+
className: "rounded border border-[var(--border-default)] px-2 py-0.5 text-[11px] text-[var(--text-secondary)]",
|
|
1345
|
+
children: "Cancel"
|
|
1346
|
+
}
|
|
1347
|
+
)
|
|
1348
|
+
] })
|
|
1349
|
+
] })
|
|
1350
|
+
}
|
|
1351
|
+
)
|
|
1352
|
+
] });
|
|
1797
1353
|
}
|
|
1798
1354
|
function PagePropsControls({ page, canWrite, onSetPageProps, onSetPageGuides }) {
|
|
1799
1355
|
const matchedPreset = matchPreset(page.width, page.height);
|
|
@@ -1810,7 +1366,7 @@ function PagePropsControls({ page, canWrite, onSetPageProps, onSetPageGuides })
|
|
|
1810
1366
|
...SIZE_PRESETS.map((p) => ({ value: p.id, label: p.label }))
|
|
1811
1367
|
];
|
|
1812
1368
|
return /* @__PURE__ */ jsxs5(Fragment4, { children: [
|
|
1813
|
-
/* @__PURE__ */
|
|
1369
|
+
/* @__PURE__ */ jsx6(
|
|
1814
1370
|
"input",
|
|
1815
1371
|
{
|
|
1816
1372
|
type: "text",
|
|
@@ -1822,7 +1378,7 @@ function PagePropsControls({ page, canWrite, onSetPageProps, onSetPageGuides })
|
|
|
1822
1378
|
}
|
|
1823
1379
|
),
|
|
1824
1380
|
SEP,
|
|
1825
|
-
/* @__PURE__ */
|
|
1381
|
+
/* @__PURE__ */ jsx6(
|
|
1826
1382
|
SelectControl,
|
|
1827
1383
|
{
|
|
1828
1384
|
label: "Preset",
|
|
@@ -1836,8 +1392,8 @@ function PagePropsControls({ page, canWrite, onSetPageProps, onSetPageGuides })
|
|
|
1836
1392
|
}
|
|
1837
1393
|
),
|
|
1838
1394
|
/* @__PURE__ */ jsxs5("label", { className: "flex flex-col items-center gap-0.5", children: [
|
|
1839
|
-
/* @__PURE__ */
|
|
1840
|
-
/* @__PURE__ */
|
|
1395
|
+
/* @__PURE__ */ jsx6("span", { className: FIELD_LABEL, children: "W" }),
|
|
1396
|
+
/* @__PURE__ */ jsx6(
|
|
1841
1397
|
"input",
|
|
1842
1398
|
{
|
|
1843
1399
|
type: "number",
|
|
@@ -1854,10 +1410,10 @@ function PagePropsControls({ page, canWrite, onSetPageProps, onSetPageGuides })
|
|
|
1854
1410
|
}
|
|
1855
1411
|
)
|
|
1856
1412
|
] }),
|
|
1857
|
-
/* @__PURE__ */
|
|
1413
|
+
/* @__PURE__ */ jsx6("span", { className: "text-[var(--text-muted)]", children: "\xD7" }),
|
|
1858
1414
|
/* @__PURE__ */ jsxs5("label", { className: "flex flex-col items-center gap-0.5", children: [
|
|
1859
|
-
/* @__PURE__ */
|
|
1860
|
-
/* @__PURE__ */
|
|
1415
|
+
/* @__PURE__ */ jsx6("span", { className: FIELD_LABEL, children: "H" }),
|
|
1416
|
+
/* @__PURE__ */ jsx6(
|
|
1861
1417
|
"input",
|
|
1862
1418
|
{
|
|
1863
1419
|
type: "number",
|
|
@@ -1875,9 +1431,9 @@ function PagePropsControls({ page, canWrite, onSetPageProps, onSetPageGuides })
|
|
|
1875
1431
|
)
|
|
1876
1432
|
] }),
|
|
1877
1433
|
SEP,
|
|
1878
|
-
/* @__PURE__ */
|
|
1434
|
+
/* @__PURE__ */ jsx6(ColorSwatch, { label: "BG", value: page.background, onCommit: (v) => onSetPageProps({ background: v }), disabled: !canWrite }),
|
|
1879
1435
|
SEP,
|
|
1880
|
-
/* @__PURE__ */
|
|
1436
|
+
/* @__PURE__ */ jsx6(BleedControls, { page, canWrite, onSetPageProps })
|
|
1881
1437
|
] });
|
|
1882
1438
|
}
|
|
1883
1439
|
function BleedControls({ page, canWrite, onSetPageProps }) {
|
|
@@ -1887,20 +1443,20 @@ function BleedControls({ page, canWrite, onSetPageProps }) {
|
|
|
1887
1443
|
onSetPageProps({ bleed: { ...current, [side]: value } });
|
|
1888
1444
|
}
|
|
1889
1445
|
if (!bleed) {
|
|
1890
|
-
return /* @__PURE__ */
|
|
1446
|
+
return /* @__PURE__ */ jsx6(
|
|
1891
1447
|
"button",
|
|
1892
1448
|
{
|
|
1893
1449
|
type: "button",
|
|
1894
1450
|
disabled: !canWrite,
|
|
1895
1451
|
onClick: () => onSetPageProps({ bleed: { top: 3, right: 3, bottom: 3, left: 3 } }),
|
|
1896
|
-
className:
|
|
1452
|
+
className: BTN,
|
|
1897
1453
|
title: "Enable bleed",
|
|
1898
|
-
children: /* @__PURE__ */
|
|
1454
|
+
children: /* @__PURE__ */ jsx6(BleedGlyph, { className: "h-3.5 w-3.5" })
|
|
1899
1455
|
}
|
|
1900
1456
|
);
|
|
1901
1457
|
}
|
|
1902
1458
|
return /* @__PURE__ */ jsxs5(Fragment4, { children: [
|
|
1903
|
-
["top", "right", "bottom", "left"].map((side) => /* @__PURE__ */
|
|
1459
|
+
["top", "right", "bottom", "left"].map((side) => /* @__PURE__ */ jsx6(
|
|
1904
1460
|
NumberInput,
|
|
1905
1461
|
{
|
|
1906
1462
|
label: `Bleed ${side[0].toUpperCase()}`,
|
|
@@ -1911,13 +1467,13 @@ function BleedControls({ page, canWrite, onSetPageProps }) {
|
|
|
1911
1467
|
},
|
|
1912
1468
|
side
|
|
1913
1469
|
)),
|
|
1914
|
-
/* @__PURE__ */
|
|
1470
|
+
/* @__PURE__ */ jsx6(
|
|
1915
1471
|
"button",
|
|
1916
1472
|
{
|
|
1917
1473
|
type: "button",
|
|
1918
1474
|
disabled: !canWrite,
|
|
1919
1475
|
onClick: () => onSetPageProps({ bleed: null }),
|
|
1920
|
-
className:
|
|
1476
|
+
className: BTN,
|
|
1921
1477
|
title: "Remove bleed",
|
|
1922
1478
|
children: "\xD7"
|
|
1923
1479
|
}
|
|
@@ -1926,11 +1482,10 @@ function BleedControls({ page, canWrite, onSetPageProps }) {
|
|
|
1926
1482
|
}
|
|
1927
1483
|
|
|
1928
1484
|
// src/design-canvas-react/components/ZoomControls.tsx
|
|
1929
|
-
import { jsx as
|
|
1485
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1930
1486
|
var STEP = 0.1;
|
|
1931
1487
|
var MIN = 0.05;
|
|
1932
1488
|
var MAX = 32;
|
|
1933
|
-
var BTN3 = "flex h-6 w-6 items-center justify-center rounded border border-[var(--border-default)] text-[var(--text-secondary)] transition hover:text-[var(--text-primary)] disabled:cursor-default disabled:opacity-40";
|
|
1934
1489
|
function ZoomControls({ zoom, onZoom, onFit }) {
|
|
1935
1490
|
function zoomOut() {
|
|
1936
1491
|
onZoom(Math.max(MIN, parseFloat((zoom - STEP).toFixed(4))));
|
|
@@ -1942,26 +1497,26 @@ function ZoomControls({ zoom, onZoom, onFit }) {
|
|
|
1942
1497
|
onZoom(1);
|
|
1943
1498
|
}
|
|
1944
1499
|
return /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1 px-2", children: [
|
|
1945
|
-
/* @__PURE__ */
|
|
1500
|
+
/* @__PURE__ */ jsx7(
|
|
1946
1501
|
"button",
|
|
1947
1502
|
{
|
|
1948
1503
|
type: "button",
|
|
1949
1504
|
"aria-label": "Fit page to viewport",
|
|
1950
1505
|
onClick: onFit,
|
|
1951
|
-
className:
|
|
1506
|
+
className: BTN_SM,
|
|
1952
1507
|
title: "Fit page (F)",
|
|
1953
|
-
children: /* @__PURE__ */
|
|
1508
|
+
children: /* @__PURE__ */ jsx7(ZoomFitGlyph, { className: "h-3.5 w-3.5" })
|
|
1954
1509
|
}
|
|
1955
1510
|
),
|
|
1956
|
-
/* @__PURE__ */
|
|
1511
|
+
/* @__PURE__ */ jsx7(
|
|
1957
1512
|
"button",
|
|
1958
1513
|
{
|
|
1959
1514
|
type: "button",
|
|
1960
1515
|
"aria-label": "Zoom out",
|
|
1961
1516
|
onClick: zoomOut,
|
|
1962
1517
|
disabled: zoom <= MIN,
|
|
1963
|
-
className:
|
|
1964
|
-
children: /* @__PURE__ */
|
|
1518
|
+
className: BTN_SM,
|
|
1519
|
+
children: /* @__PURE__ */ jsx7("span", { className: "text-base leading-none", children: "\u2212" })
|
|
1965
1520
|
}
|
|
1966
1521
|
),
|
|
1967
1522
|
/* @__PURE__ */ jsxs6(
|
|
@@ -1970,7 +1525,7 @@ function ZoomControls({ zoom, onZoom, onFit }) {
|
|
|
1970
1525
|
type: "button",
|
|
1971
1526
|
"aria-label": "Reset to 100%",
|
|
1972
1527
|
onClick: resetHundred,
|
|
1973
|
-
className: "rounded px-1.5 py-0.5 font-mono text-[11px] tabular-nums text-[var(--text-secondary)] transition hover:bg-[var(--border-default)] hover:text-[var(--text-primary)]",
|
|
1528
|
+
className: "rounded px-1.5 py-0.5 font-mono text-[11px] tabular-nums text-[var(--text-secondary)] transition hover:bg-[var(--border-default)] hover:text-[var(--text-primary)] focus:outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--ring))]",
|
|
1974
1529
|
title: "Reset to 100%",
|
|
1975
1530
|
children: [
|
|
1976
1531
|
Math.round(zoom * 100),
|
|
@@ -1978,15 +1533,15 @@ function ZoomControls({ zoom, onZoom, onFit }) {
|
|
|
1978
1533
|
]
|
|
1979
1534
|
}
|
|
1980
1535
|
),
|
|
1981
|
-
/* @__PURE__ */
|
|
1536
|
+
/* @__PURE__ */ jsx7(
|
|
1982
1537
|
"button",
|
|
1983
1538
|
{
|
|
1984
1539
|
type: "button",
|
|
1985
1540
|
"aria-label": "Zoom in",
|
|
1986
1541
|
onClick: zoomIn,
|
|
1987
1542
|
disabled: zoom >= MAX,
|
|
1988
|
-
className:
|
|
1989
|
-
children: /* @__PURE__ */
|
|
1543
|
+
className: BTN_SM,
|
|
1544
|
+
children: /* @__PURE__ */ jsx7("span", { className: "text-sm leading-none", children: "+" })
|
|
1990
1545
|
}
|
|
1991
1546
|
)
|
|
1992
1547
|
] });
|
|
@@ -1994,7 +1549,7 @@ function ZoomControls({ zoom, onZoom, onFit }) {
|
|
|
1994
1549
|
|
|
1995
1550
|
// src/design-canvas-react/components/ExportControl.tsx
|
|
1996
1551
|
import { useRef as useRef4, useState as useState4 } from "react";
|
|
1997
|
-
import { jsx as
|
|
1552
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1998
1553
|
var FORMATS = [
|
|
1999
1554
|
{ id: "png", label: "PNG" },
|
|
2000
1555
|
{ id: "jpeg", label: "JPEG" }
|
|
@@ -2028,9 +1583,9 @@ function ExportControl({ defaults, onExport, className }) {
|
|
|
2028
1583
|
},
|
|
2029
1584
|
className: "flex h-8 items-center gap-1.5 rounded-md border border-[var(--border-default)] px-2.5 text-xs font-medium text-[var(--text-primary)] transition-colors hover:border-[var(--brand-primary)]/40",
|
|
2030
1585
|
children: [
|
|
2031
|
-
/* @__PURE__ */
|
|
1586
|
+
/* @__PURE__ */ jsx8(ExportGlyph, { className: "h-3.5 w-3.5" }),
|
|
2032
1587
|
"Export",
|
|
2033
|
-
/* @__PURE__ */
|
|
1588
|
+
/* @__PURE__ */ jsx8(ChevronDownGlyph, { className: "h-3 w-3 text-[var(--text-muted)]" })
|
|
2034
1589
|
]
|
|
2035
1590
|
}
|
|
2036
1591
|
),
|
|
@@ -2047,8 +1602,8 @@ function ExportControl({ defaults, onExport, className }) {
|
|
|
2047
1602
|
className: "absolute right-0 top-full z-50 mt-1 flex w-52 flex-col gap-3 rounded-md border border-[var(--border-default)] bg-[var(--bg-input)] p-3 shadow-lg",
|
|
2048
1603
|
children: [
|
|
2049
1604
|
/* @__PURE__ */ jsxs7("div", { className: "flex flex-col gap-1.5", children: [
|
|
2050
|
-
/* @__PURE__ */
|
|
2051
|
-
/* @__PURE__ */
|
|
1605
|
+
/* @__PURE__ */ jsx8("span", { className: "text-[11px] font-medium text-[var(--text-muted)]", children: "Format" }),
|
|
1606
|
+
/* @__PURE__ */ jsx8("div", { className: "flex gap-1.5", children: FORMATS.map((f) => /* @__PURE__ */ jsx8(
|
|
2052
1607
|
"button",
|
|
2053
1608
|
{
|
|
2054
1609
|
type: "button",
|
|
@@ -2061,8 +1616,8 @@ function ExportControl({ defaults, onExport, className }) {
|
|
|
2061
1616
|
)) })
|
|
2062
1617
|
] }),
|
|
2063
1618
|
/* @__PURE__ */ jsxs7("div", { className: "flex flex-col gap-1.5", children: [
|
|
2064
|
-
/* @__PURE__ */
|
|
2065
|
-
/* @__PURE__ */
|
|
1619
|
+
/* @__PURE__ */ jsx8("span", { className: "text-[11px] font-medium text-[var(--text-muted)]", children: "Scale" }),
|
|
1620
|
+
/* @__PURE__ */ jsx8("div", { className: "flex gap-1.5", children: SCALES.map((s) => /* @__PURE__ */ jsx8(
|
|
2066
1621
|
"button",
|
|
2067
1622
|
{
|
|
2068
1623
|
type: "button",
|
|
@@ -2074,7 +1629,7 @@ function ExportControl({ defaults, onExport, className }) {
|
|
|
2074
1629
|
s.value
|
|
2075
1630
|
)) })
|
|
2076
1631
|
] }),
|
|
2077
|
-
/* @__PURE__ */
|
|
1632
|
+
/* @__PURE__ */ jsx8(
|
|
2078
1633
|
"button",
|
|
2079
1634
|
{
|
|
2080
1635
|
type: "button",
|
|
@@ -2091,7 +1646,7 @@ function ExportControl({ defaults, onExport, className }) {
|
|
|
2091
1646
|
}
|
|
2092
1647
|
|
|
2093
1648
|
// src/design-canvas-react/components/DesignCanvas.tsx
|
|
2094
|
-
import { jsx as
|
|
1649
|
+
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2095
1650
|
function mintId() {
|
|
2096
1651
|
const uuid = globalThis.crypto && "randomUUID" in globalThis.crypto ? globalThis.crypto.randomUUID() : null;
|
|
2097
1652
|
return `local-${uuid ?? `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`}`;
|
|
@@ -2126,6 +1681,7 @@ function DesignCanvas({
|
|
|
2126
1681
|
document: initialDocument,
|
|
2127
1682
|
rev: initialRev,
|
|
2128
1683
|
canWrite,
|
|
1684
|
+
mode = "edit",
|
|
2129
1685
|
onApplyOperations,
|
|
2130
1686
|
onSelectionChange,
|
|
2131
1687
|
renderAgentPanel,
|
|
@@ -2135,6 +1691,7 @@ function DesignCanvas({
|
|
|
2135
1691
|
className,
|
|
2136
1692
|
fitOnMount,
|
|
2137
1693
|
onReady,
|
|
1694
|
+
render,
|
|
2138
1695
|
renderWorkspace,
|
|
2139
1696
|
renderThumbnail
|
|
2140
1697
|
}) {
|
|
@@ -2317,12 +1874,7 @@ function DesignCanvas({
|
|
|
2317
1874
|
void onApplyOperations(command.inverseOperations()).then((result) => {
|
|
2318
1875
|
if (result.document) stack.reset(result.document);
|
|
2319
1876
|
}).catch((error) => {
|
|
2320
|
-
|
|
2321
|
-
try {
|
|
2322
|
-
stack.redo();
|
|
2323
|
-
} catch {
|
|
2324
|
-
}
|
|
2325
|
-
}
|
|
1877
|
+
stack.reexecute(command);
|
|
2326
1878
|
setCommitError(error instanceof Error ? error.message : String(error));
|
|
2327
1879
|
});
|
|
2328
1880
|
}, [stack, canWrite, onApplyOperations]);
|
|
@@ -2338,12 +1890,7 @@ function DesignCanvas({
|
|
|
2338
1890
|
void onApplyOperations(command.operations()).then((result) => {
|
|
2339
1891
|
if (result.document) stack.reset(result.document);
|
|
2340
1892
|
}).catch((error) => {
|
|
2341
|
-
|
|
2342
|
-
try {
|
|
2343
|
-
stack.undo();
|
|
2344
|
-
} catch {
|
|
2345
|
-
}
|
|
2346
|
-
}
|
|
1893
|
+
stack.reundo(command);
|
|
2347
1894
|
setCommitError(error instanceof Error ? error.message : String(error));
|
|
2348
1895
|
});
|
|
2349
1896
|
}, [stack, canWrite, onApplyOperations]);
|
|
@@ -2385,8 +1932,9 @@ function DesignCanvas({
|
|
|
2385
1932
|
if (!activePage) return [];
|
|
2386
1933
|
return editorState.selectedElementIds.map((id) => activePage.elements.find((el) => el.id === id)).filter((el) => el !== void 0);
|
|
2387
1934
|
}, [activePage, editorState.selectedElementIds]);
|
|
1935
|
+
const review = mode === "review";
|
|
2388
1936
|
if (!activePage) {
|
|
2389
|
-
return /* @__PURE__ */
|
|
1937
|
+
return /* @__PURE__ */ jsx9("div", { className: `flex h-full items-center justify-center bg-[var(--bg-input)] text-[var(--text-muted)] ${className ?? ""}`, children: "No pages in document" });
|
|
2390
1938
|
}
|
|
2391
1939
|
const bleedScreen = editorState.showBleed && activePage.bleed ? {
|
|
2392
1940
|
top: activePage.bleed.top * editorState.zoom,
|
|
@@ -2395,15 +1943,16 @@ function DesignCanvas({
|
|
|
2395
1943
|
left: activePage.bleed.left * editorState.zoom
|
|
2396
1944
|
} : null;
|
|
2397
1945
|
return /* @__PURE__ */ jsxs8("div", { className: `flex h-full min-h-0 bg-[var(--bg-input)] text-[var(--text-primary)] ${className ?? ""}`, children: [
|
|
2398
|
-
renderSidePanel ? /* @__PURE__ */
|
|
1946
|
+
renderSidePanel && !review ? /* @__PURE__ */ jsx9("aside", { className: "flex w-64 shrink-0 flex-col overflow-hidden border-r border-[var(--border-default)]", children: renderSidePanel() }) : null,
|
|
2399
1947
|
/* @__PURE__ */ jsxs8("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
2400
1948
|
/* @__PURE__ */ jsxs8("div", { className: "flex shrink-0 items-stretch", children: [
|
|
2401
|
-
/* @__PURE__ */
|
|
1949
|
+
/* @__PURE__ */ jsx9("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx9(
|
|
2402
1950
|
Toolbar,
|
|
2403
1951
|
{
|
|
2404
1952
|
page: activePage,
|
|
2405
1953
|
selectedElements,
|
|
2406
1954
|
canWrite,
|
|
1955
|
+
mode,
|
|
2407
1956
|
canUndo: stack.canUndo(),
|
|
2408
1957
|
canRedo: stack.canRedo(),
|
|
2409
1958
|
gridEnabled: editorState.gridEnabled,
|
|
@@ -2426,7 +1975,7 @@ function DesignCanvas({
|
|
|
2426
1975
|
onBindSlot: handleBindSlot
|
|
2427
1976
|
}
|
|
2428
1977
|
) }),
|
|
2429
|
-
onExport ? /* @__PURE__ */
|
|
1978
|
+
onExport ? /* @__PURE__ */ jsx9("div", { className: "flex shrink-0 items-center border-b border-l border-[var(--border-default)] bg-[var(--bg-input)] px-2", children: /* @__PURE__ */ jsx9(
|
|
2430
1979
|
ExportControl,
|
|
2431
1980
|
{
|
|
2432
1981
|
defaults: exportDefaults,
|
|
@@ -2437,11 +1986,11 @@ function DesignCanvas({
|
|
|
2437
1986
|
commitError ? /* @__PURE__ */ jsxs8(
|
|
2438
1987
|
"div",
|
|
2439
1988
|
{
|
|
2440
|
-
className: "flex shrink-0 items-center justify-between gap-3 border-b border-
|
|
1989
|
+
className: "flex shrink-0 items-center justify-between gap-3 border-b border-[hsl(var(--destructive)/0.3)] bg-[hsl(var(--destructive)/0.1)] px-3 py-1.5 text-xs text-[var(--text-danger)]",
|
|
2441
1990
|
role: "alert",
|
|
2442
1991
|
children: [
|
|
2443
|
-
/* @__PURE__ */
|
|
2444
|
-
/* @__PURE__ */
|
|
1992
|
+
/* @__PURE__ */ jsx9("span", { className: "min-w-0 truncate", children: commitError }),
|
|
1993
|
+
/* @__PURE__ */ jsx9(
|
|
2445
1994
|
"button",
|
|
2446
1995
|
{
|
|
2447
1996
|
type: "button",
|
|
@@ -2454,7 +2003,7 @@ function DesignCanvas({
|
|
|
2454
2003
|
}
|
|
2455
2004
|
) : null,
|
|
2456
2005
|
/* @__PURE__ */ jsxs8("div", { className: "relative min-h-0 flex-1", children: [
|
|
2457
|
-
/* @__PURE__ */
|
|
2006
|
+
/* @__PURE__ */ jsx9(
|
|
2458
2007
|
Rulers,
|
|
2459
2008
|
{
|
|
2460
2009
|
pageWidth: activePage.width,
|
|
@@ -2467,12 +2016,12 @@ function DesignCanvas({
|
|
|
2467
2016
|
onGuidesChange: handleSetPageGuides
|
|
2468
2017
|
}
|
|
2469
2018
|
),
|
|
2470
|
-
bleedScreen && activePage.bleed ? /* @__PURE__ */
|
|
2019
|
+
bleedScreen && activePage.bleed ? /* @__PURE__ */ jsx9(
|
|
2471
2020
|
"div",
|
|
2472
2021
|
{
|
|
2473
2022
|
className: "pointer-events-none absolute inset-0 z-10 overflow-hidden",
|
|
2474
2023
|
"aria-hidden": true,
|
|
2475
|
-
children: /* @__PURE__ */
|
|
2024
|
+
children: /* @__PURE__ */ jsx9(
|
|
2476
2025
|
"div",
|
|
2477
2026
|
{
|
|
2478
2027
|
style: {
|
|
@@ -2480,7 +2029,7 @@ function DesignCanvas({
|
|
|
2480
2029
|
left: editorState.panX,
|
|
2481
2030
|
top: editorState.panY
|
|
2482
2031
|
},
|
|
2483
|
-
children: /* @__PURE__ */
|
|
2032
|
+
children: /* @__PURE__ */ jsx9(
|
|
2484
2033
|
BleedTrimOverlay,
|
|
2485
2034
|
{
|
|
2486
2035
|
pageWidthPx: activePage.width * editorState.zoom,
|
|
@@ -2510,18 +2059,20 @@ function DesignCanvas({
|
|
|
2510
2059
|
onExportRef: exportRef,
|
|
2511
2060
|
fitOnMount,
|
|
2512
2061
|
onReady,
|
|
2062
|
+
render,
|
|
2513
2063
|
onZoomChange: setZoom,
|
|
2514
2064
|
onPanChange: setPan,
|
|
2515
2065
|
onSelectElements: setSelectedElements
|
|
2516
2066
|
})
|
|
2517
2067
|
] }),
|
|
2518
2068
|
/* @__PURE__ */ jsxs8("div", { className: "flex shrink-0 items-stretch border-t border-[var(--border-default)]", children: [
|
|
2519
|
-
/* @__PURE__ */
|
|
2069
|
+
/* @__PURE__ */ jsx9("div", { className: "min-w-0 flex-1 overflow-hidden", children: /* @__PURE__ */ jsx9(
|
|
2520
2070
|
PagesStrip,
|
|
2521
2071
|
{
|
|
2522
2072
|
pages: editorState.document.pages,
|
|
2523
2073
|
activePageId: editorState.activePageId,
|
|
2524
2074
|
canWrite,
|
|
2075
|
+
canManagePages: !review,
|
|
2525
2076
|
renderThumbnail,
|
|
2526
2077
|
onSelectPage: setActivePage,
|
|
2527
2078
|
onAddPage: handleAddPage,
|
|
@@ -2530,7 +2081,7 @@ function DesignCanvas({
|
|
|
2530
2081
|
onReorderPage: handleReorderPage
|
|
2531
2082
|
}
|
|
2532
2083
|
) }),
|
|
2533
|
-
/* @__PURE__ */
|
|
2084
|
+
/* @__PURE__ */ jsx9("div", { className: "flex shrink-0 items-center border-l border-[var(--border-default)]", children: /* @__PURE__ */ jsx9(
|
|
2534
2085
|
ZoomControls,
|
|
2535
2086
|
{
|
|
2536
2087
|
zoom: editorState.zoom,
|
|
@@ -2540,29 +2091,12 @@ function DesignCanvas({
|
|
|
2540
2091
|
) })
|
|
2541
2092
|
] })
|
|
2542
2093
|
] }),
|
|
2543
|
-
renderAgentPanel ? /* @__PURE__ */
|
|
2094
|
+
renderAgentPanel ? /* @__PURE__ */ jsx9("aside", { className: "flex w-80 shrink-0 flex-col overflow-hidden border-l border-[var(--border-default)]", children: renderAgentPanel({ selectedElements, activePageId: editorState.activePageId }) }) : null
|
|
2544
2095
|
] });
|
|
2545
2096
|
}
|
|
2546
2097
|
var DesignCanvas_default = DesignCanvas;
|
|
2547
2098
|
|
|
2548
2099
|
export {
|
|
2549
|
-
SCENE_COMMAND_HISTORY_LIMIT,
|
|
2550
|
-
createSceneCommandStack,
|
|
2551
|
-
addElementCommand,
|
|
2552
|
-
setAttrsCommand,
|
|
2553
|
-
multiSetAttrsCommand,
|
|
2554
|
-
reorderElementCommand,
|
|
2555
|
-
deleteElementCommand,
|
|
2556
|
-
groupElementsCommand,
|
|
2557
|
-
ungroupElementCommand,
|
|
2558
|
-
addPageCommand,
|
|
2559
|
-
duplicatePageCommand,
|
|
2560
|
-
deletePageCommand,
|
|
2561
|
-
reorderPageCommand,
|
|
2562
|
-
setPagePropsCommand,
|
|
2563
|
-
setPageGuidesCommand,
|
|
2564
|
-
bindSlotCommand,
|
|
2565
|
-
setDocumentTitleCommand,
|
|
2566
2100
|
selectTickStep,
|
|
2567
2101
|
buildRulerTicks,
|
|
2568
2102
|
formatRulerLabel,
|
|
@@ -2580,6 +2114,11 @@ export {
|
|
|
2580
2114
|
VideoGlyph,
|
|
2581
2115
|
SlotGlyph,
|
|
2582
2116
|
ShapesGlyph,
|
|
2117
|
+
BTN,
|
|
2118
|
+
BTN_ACTIVE,
|
|
2119
|
+
BTN_SM,
|
|
2120
|
+
BTN_SM_ACTIVE,
|
|
2121
|
+
IconButton,
|
|
2583
2122
|
PagesStrip,
|
|
2584
2123
|
Rulers,
|
|
2585
2124
|
Toolbar,
|
|
@@ -2588,4 +2127,4 @@ export {
|
|
|
2588
2127
|
DesignCanvas,
|
|
2589
2128
|
DesignCanvas_default
|
|
2590
2129
|
};
|
|
2591
|
-
//# sourceMappingURL=chunk-
|
|
2130
|
+
//# sourceMappingURL=chunk-YEWTVDDT.js.map
|