@sequent-org/moodboard 1.2.119 → 1.3.1
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/package.json +11 -1
- package/src/assets/icons/rotate-icon.svg +1 -1
- package/src/core/HistoryManager.js +16 -16
- package/src/core/KeyboardManager.js +48 -539
- package/src/core/PixiEngine.js +9 -9
- package/src/core/SaveManager.js +56 -31
- package/src/core/bootstrap/CoreInitializer.js +65 -0
- package/src/core/commands/DeleteObjectCommand.js +8 -0
- package/src/core/commands/GroupDeleteCommand.js +75 -0
- package/src/core/commands/GroupRotateCommand.js +6 -0
- package/src/core/commands/UpdateContentCommand.js +52 -0
- package/src/core/commands/UpdateFramePropertiesCommand.js +98 -0
- package/src/core/commands/UpdateFrameTypeCommand.js +85 -0
- package/src/core/commands/UpdateNoteStyleCommand.js +88 -0
- package/src/core/commands/UpdateTextStyleCommand.js +90 -0
- package/src/core/commands/index.js +6 -0
- package/src/core/events/Events.js +6 -0
- package/src/core/flows/ClipboardFlow.js +553 -0
- package/src/core/flows/LayerAndViewportFlow.js +283 -0
- package/src/core/flows/ObjectLifecycleFlow.js +336 -0
- package/src/core/flows/SaveFlow.js +34 -0
- package/src/core/flows/TransformFlow.js +277 -0
- package/src/core/flows/TransformFlowResizeHelpers.js +83 -0
- package/src/core/index.js +41 -1773
- package/src/core/keyboard/KeyboardClipboardImagePaste.js +190 -0
- package/src/core/keyboard/KeyboardContextGuards.js +35 -0
- package/src/core/keyboard/KeyboardEventRouter.js +92 -0
- package/src/core/keyboard/KeyboardSelectionActions.js +103 -0
- package/src/core/keyboard/KeyboardShortcutMap.js +31 -0
- package/src/core/keyboard/KeyboardToolSwitching.js +26 -0
- package/src/core/rendering/ObjectRenderer.js +3 -7
- package/src/grid/BaseGrid.js +26 -0
- package/src/grid/CrossGrid.js +7 -6
- package/src/grid/DotGrid.js +89 -33
- package/src/grid/DotGridZoomPhases.js +42 -0
- package/src/grid/LineGrid.js +22 -21
- package/src/moodboard/MoodBoard.js +31 -532
- package/src/moodboard/bootstrap/MoodBoardInitializer.js +47 -0
- package/src/moodboard/bootstrap/MoodBoardManagersFactory.js +38 -0
- package/src/moodboard/bootstrap/MoodBoardUiFactory.js +109 -0
- package/src/moodboard/integration/MoodBoardEventBindings.js +65 -0
- package/src/moodboard/integration/MoodBoardLoadApi.js +82 -0
- package/src/moodboard/integration/MoodBoardScreenshotApi.js +33 -0
- package/src/moodboard/integration/MoodBoardScreenshotCanvas.js +98 -0
- package/src/moodboard/lifecycle/MoodBoardDestroyer.js +97 -0
- package/src/objects/FileObject.js +17 -6
- package/src/objects/FrameObject.js +50 -10
- package/src/objects/NoteObject.js +5 -4
- package/src/services/BoardService.js +42 -2
- package/src/services/FrameService.js +83 -42
- package/src/services/ResizePolicyService.js +152 -0
- package/src/services/SettingsApplier.js +7 -2
- package/src/services/ZoomPanController.js +35 -9
- package/src/tools/ToolManager.js +30 -537
- package/src/tools/board-tools/PanTool.js +5 -11
- package/src/tools/manager/ToolActivationController.js +49 -0
- package/src/tools/manager/ToolEventRouter.js +396 -0
- package/src/tools/manager/ToolManagerGuards.js +33 -0
- package/src/tools/manager/ToolManagerLifecycle.js +110 -0
- package/src/tools/manager/ToolRegistry.js +33 -0
- package/src/tools/object-tools/DrawingTool.js +48 -14
- package/src/tools/object-tools/PlacementTool.js +50 -1049
- package/src/tools/object-tools/PlacementToolV2.js +88 -0
- package/src/tools/object-tools/SelectTool.js +174 -2681
- package/src/tools/object-tools/placement/GhostController.js +504 -0
- package/src/tools/object-tools/placement/PlacementCoordinateResolver.js +20 -0
- package/src/tools/object-tools/placement/PlacementEventsBridge.js +91 -0
- package/src/tools/object-tools/placement/PlacementInputRouter.js +267 -0
- package/src/tools/object-tools/placement/PlacementPayloadFactory.js +111 -0
- package/src/tools/object-tools/placement/PlacementSessionStore.js +18 -0
- package/src/tools/object-tools/selection/BoxSelectController.js +0 -5
- package/src/tools/object-tools/selection/CloneFlowController.js +71 -0
- package/src/tools/object-tools/selection/CoordinateMapper.js +10 -0
- package/src/tools/object-tools/selection/CursorController.js +78 -0
- package/src/tools/object-tools/selection/FileNameInlineEditorController.js +184 -0
- package/src/tools/object-tools/selection/HitTestService.js +102 -0
- package/src/tools/object-tools/selection/InlineEditorController.js +24 -0
- package/src/tools/object-tools/selection/InlineEditorDomFactory.js +50 -0
- package/src/tools/object-tools/selection/InlineEditorListenersRegistry.js +14 -0
- package/src/tools/object-tools/selection/InlineEditorPositioningService.js +25 -0
- package/src/tools/object-tools/selection/NoteInlineEditorController.js +113 -0
- package/src/tools/object-tools/selection/SelectInputRouter.js +267 -0
- package/src/tools/object-tools/selection/SelectToolLifecycleController.js +128 -0
- package/src/tools/object-tools/selection/SelectToolSetup.js +134 -0
- package/src/tools/object-tools/selection/SelectionOverlayService.js +81 -0
- package/src/tools/object-tools/selection/SelectionStateController.js +91 -0
- package/src/tools/object-tools/selection/TextEditorDomFactory.js +65 -0
- package/src/tools/object-tools/selection/TextEditorInteractionController.js +266 -0
- package/src/tools/object-tools/selection/TextEditorLifecycleRegistry.js +90 -0
- package/src/tools/object-tools/selection/TextEditorPositioningService.js +158 -0
- package/src/tools/object-tools/selection/TextEditorSyncService.js +110 -0
- package/src/tools/object-tools/selection/TextInlineEditorController.js +457 -0
- package/src/tools/object-tools/selection/TransformInteractionController.js +466 -0
- package/src/ui/FilePropertiesPanel.js +61 -32
- package/src/ui/FramePropertiesPanel.js +176 -101
- package/src/ui/HtmlHandlesLayer.js +121 -999
- package/src/ui/MapPanel.js +12 -7
- package/src/ui/NotePropertiesPanel.js +17 -2
- package/src/ui/TextPropertiesPanel.js +124 -738
- package/src/ui/Toolbar.js +82 -1181
- package/src/ui/Topbar.js +23 -25
- package/src/ui/ZoomPanel.js +16 -5
- package/src/ui/handles/GroupSelectionHandlesController.js +29 -0
- package/src/ui/handles/HandlesDomRenderer.js +278 -0
- package/src/ui/handles/HandlesEventBridge.js +102 -0
- package/src/ui/handles/HandlesInteractionController.js +772 -0
- package/src/ui/handles/HandlesPositioningService.js +206 -0
- package/src/ui/handles/SingleSelectionHandlesController.js +22 -0
- package/src/ui/styles/toolbar.css +2 -0
- package/src/ui/styles/workspace.css +13 -6
- package/src/ui/text-properties/TextPropertiesPanelBindings.js +92 -0
- package/src/ui/text-properties/TextPropertiesPanelEventBridge.js +77 -0
- package/src/ui/text-properties/TextPropertiesPanelMapper.js +173 -0
- package/src/ui/text-properties/TextPropertiesPanelRenderer.js +434 -0
- package/src/ui/text-properties/TextPropertiesPanelState.js +39 -0
- package/src/ui/toolbar/ToolbarActionRouter.js +193 -0
- package/src/ui/toolbar/ToolbarDialogsController.js +186 -0
- package/src/ui/toolbar/ToolbarPopupsController.js +665 -0
- package/src/ui/toolbar/ToolbarRenderer.js +97 -0
- package/src/ui/toolbar/ToolbarStateController.js +79 -0
- package/src/ui/toolbar/ToolbarTooltipController.js +52 -0
- package/src/utils/emojiLoaderNoBundler.js +1 -1
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { Events } from '../events/Events.js';
|
|
2
|
+
import {
|
|
3
|
+
GroupResizeCommand,
|
|
4
|
+
ResizeObjectCommand,
|
|
5
|
+
GroupRotateCommand
|
|
6
|
+
} from '../commands/index.js';
|
|
7
|
+
import {
|
|
8
|
+
getActiveResize,
|
|
9
|
+
normalizeResizeEndPayload,
|
|
10
|
+
normalizeResizeUpdatePayload,
|
|
11
|
+
resolveResizePositionFallback,
|
|
12
|
+
} from './TransformFlowResizeHelpers.js';
|
|
13
|
+
|
|
14
|
+
function rotateVector(vector, angleDegrees) {
|
|
15
|
+
const angleRad = angleDegrees * Math.PI / 180;
|
|
16
|
+
const cos = Math.cos(angleRad);
|
|
17
|
+
const sin = Math.sin(angleRad);
|
|
18
|
+
return {
|
|
19
|
+
x: vector.x * cos - vector.y * sin,
|
|
20
|
+
y: vector.x * sin + vector.y * cos,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function setupTransformFlow(core) {
|
|
25
|
+
core.eventBus.on(Events.Tool.ResizeStart, (data) => {
|
|
26
|
+
const objects = core.state.getObjects();
|
|
27
|
+
const object = objects.find(obj => obj.id === data.object);
|
|
28
|
+
if (object) {
|
|
29
|
+
core.resizeStartSize = { width: object.width, height: object.height };
|
|
30
|
+
core._activeResize = {
|
|
31
|
+
objectId: data.object,
|
|
32
|
+
handle: data.handle,
|
|
33
|
+
startSize: { width: object.width, height: object.height },
|
|
34
|
+
startPosition: { x: object.position.x, y: object.position.y },
|
|
35
|
+
dominantAxis: null,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
core.eventBus.on(Events.Tool.GroupResizeStart, (data) => {
|
|
41
|
+
core._groupResizeStart = data.startBounds || null;
|
|
42
|
+
core._groupResizeSnapshot = new Map();
|
|
43
|
+
for (const id of data.objects) {
|
|
44
|
+
const obj = core.state.state.objects.find(o => o.id === id);
|
|
45
|
+
const pixiObj = core.pixi.objects.get(id);
|
|
46
|
+
if (!obj || !pixiObj) continue;
|
|
47
|
+
core._groupResizeSnapshot.set(id, {
|
|
48
|
+
size: { width: obj.width, height: obj.height },
|
|
49
|
+
position: { x: obj.position.x, y: obj.position.y },
|
|
50
|
+
center: {
|
|
51
|
+
x: obj.position.x + obj.width / 2,
|
|
52
|
+
y: obj.position.y + obj.height / 2,
|
|
53
|
+
},
|
|
54
|
+
type: obj.type || null
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
core.eventBus.on(Events.Tool.GroupResizeUpdate, (data) => {
|
|
60
|
+
const { startBounds, newBounds, scale } = data;
|
|
61
|
+
const sx = scale?.x ?? (newBounds.width / startBounds.width);
|
|
62
|
+
const sy = scale?.y ?? (newBounds.height / startBounds.height);
|
|
63
|
+
const startLeft = startBounds.x;
|
|
64
|
+
const startTop = startBounds.y;
|
|
65
|
+
const rotation = data.rotation || 0;
|
|
66
|
+
const startCenter = {
|
|
67
|
+
x: startLeft + startBounds.width / 2,
|
|
68
|
+
y: startTop + startBounds.height / 2,
|
|
69
|
+
};
|
|
70
|
+
const newBoundsCenter = {
|
|
71
|
+
x: newBounds.x + newBounds.width / 2,
|
|
72
|
+
y: newBounds.y + newBounds.height / 2,
|
|
73
|
+
};
|
|
74
|
+
for (const id of data.objects) {
|
|
75
|
+
const snap = core._groupResizeSnapshot?.get(id);
|
|
76
|
+
if (!snap) continue;
|
|
77
|
+
const centerAtStart = snap.center || {
|
|
78
|
+
x: snap.position.x + snap.size.width / 2,
|
|
79
|
+
y: snap.position.y + snap.size.height / 2,
|
|
80
|
+
};
|
|
81
|
+
const relCenterLocal = rotateVector({
|
|
82
|
+
x: centerAtStart.x - startCenter.x,
|
|
83
|
+
y: centerAtStart.y - startCenter.y,
|
|
84
|
+
}, -rotation);
|
|
85
|
+
const scaledRelCenterWorld = rotateVector({
|
|
86
|
+
x: relCenterLocal.x * sx,
|
|
87
|
+
y: relCenterLocal.y * sy,
|
|
88
|
+
}, rotation);
|
|
89
|
+
const newCenter = {
|
|
90
|
+
x: newBoundsCenter.x + scaledRelCenterWorld.x,
|
|
91
|
+
y: newBoundsCenter.y + scaledRelCenterWorld.y
|
|
92
|
+
};
|
|
93
|
+
const newSize = {
|
|
94
|
+
width: Math.max(10, snap.size.width * sx),
|
|
95
|
+
height: Math.max(10, snap.size.height * sy)
|
|
96
|
+
};
|
|
97
|
+
const newPos = { x: newCenter.x - newSize.width / 2, y: newCenter.y - newSize.height / 2 };
|
|
98
|
+
core.updateObjectSizeAndPositionDirect(id, newSize, newPos, snap.type || null);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
core.eventBus.on(Events.Tool.GroupResizeEnd, (data) => {
|
|
103
|
+
const changes = [];
|
|
104
|
+
for (const id of data.objects) {
|
|
105
|
+
const before = core._groupResizeSnapshot?.get(id);
|
|
106
|
+
const obj = core.state.state.objects.find(o => o.id === id);
|
|
107
|
+
if (!before || !obj) continue;
|
|
108
|
+
const afterSize = { width: obj.width, height: obj.height };
|
|
109
|
+
const afterPos = { x: obj.position.x, y: obj.position.y };
|
|
110
|
+
if (before.size.width !== afterSize.width || before.size.height !== afterSize.height || before.position.x !== afterPos.x || before.position.y !== afterPos.y) {
|
|
111
|
+
changes.push({ id, fromSize: before.size, toSize: afterSize, fromPos: before.position, toPos: afterPos, type: before.type });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (changes.length > 0) {
|
|
115
|
+
const cmd = new GroupResizeCommand(core, changes);
|
|
116
|
+
cmd.setEventBus(core.eventBus);
|
|
117
|
+
core.history.executeCommand(cmd);
|
|
118
|
+
}
|
|
119
|
+
core._groupResizeStart = null;
|
|
120
|
+
core._groupResizeSnapshot = null;
|
|
121
|
+
if (core.selectTool && core.selectTool.selectedObjects.size > 1) {
|
|
122
|
+
core.selectTool.updateResizeHandles();
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
core.eventBus.on(Events.Tool.ResizeUpdate, (data) => {
|
|
127
|
+
const objects = core.state.getObjects();
|
|
128
|
+
const object = objects.find(obj => obj.id === data.object);
|
|
129
|
+
const objectType = object ? object.type : null;
|
|
130
|
+
const activeResize = normalizeResizeUpdatePayload(core, object, data);
|
|
131
|
+
|
|
132
|
+
let position = data.position;
|
|
133
|
+
if (!position && activeResize) {
|
|
134
|
+
position = resolveResizePositionFallback(core, data.object, data.size);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
core.updateObjectSizeAndPositionDirect(data.object, data.size, position, objectType);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
core.eventBus.on(Events.Tool.ResizeEnd, (data) => {
|
|
141
|
+
if (core.resizeStartSize && data.oldSize && data.newSize) {
|
|
142
|
+
const objects = core.state.getObjects();
|
|
143
|
+
const object = objects.find(obj => obj.id === data.object);
|
|
144
|
+
const activeResize = normalizeResizeEndPayload(core, object, data);
|
|
145
|
+
|
|
146
|
+
if (data.oldSize.width !== data.newSize.width || data.oldSize.height !== data.newSize.height) {
|
|
147
|
+
let oldPos = data.oldPosition;
|
|
148
|
+
let newPos = data.newPosition;
|
|
149
|
+
const activeResize = getActiveResize(core, data.object);
|
|
150
|
+
if ((!oldPos || !newPos) && activeResize) {
|
|
151
|
+
if (!oldPos) oldPos = { x: activeResize.startPosition.x, y: activeResize.startPosition.y };
|
|
152
|
+
if (!newPos) {
|
|
153
|
+
newPos = resolveResizePositionFallback(core, data.object, data.newSize);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const command = new ResizeObjectCommand(
|
|
157
|
+
core,
|
|
158
|
+
data.object,
|
|
159
|
+
data.oldSize,
|
|
160
|
+
data.newSize,
|
|
161
|
+
oldPos,
|
|
162
|
+
newPos
|
|
163
|
+
);
|
|
164
|
+
command.setEventBus(core.eventBus);
|
|
165
|
+
core.history.executeCommand(command);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
core.resizeStartSize = null;
|
|
169
|
+
core._activeResize = null;
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
core.eventBus.on(Events.Tool.RotateUpdate, (data) => {
|
|
173
|
+
core.pixi.updateObjectRotation(data.object, data.angle);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
core.eventBus.on(Events.Tool.RotateEnd, (data) => {
|
|
177
|
+
if (data.oldAngle !== undefined && data.newAngle !== undefined) {
|
|
178
|
+
if (Math.abs(data.oldAngle - data.newAngle) > 0.1) {
|
|
179
|
+
import('../commands/RotateObjectCommand.js').then(({ RotateObjectCommand }) => {
|
|
180
|
+
const command = new RotateObjectCommand(
|
|
181
|
+
core,
|
|
182
|
+
data.object,
|
|
183
|
+
data.oldAngle,
|
|
184
|
+
data.newAngle
|
|
185
|
+
);
|
|
186
|
+
command.setEventBus(core.eventBus);
|
|
187
|
+
core.history.executeCommand(command);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
core.eventBus.on(Events.Tool.GroupRotateStart, (data) => {
|
|
194
|
+
core._groupRotateStart = new Map();
|
|
195
|
+
for (const id of data.objects) {
|
|
196
|
+
const pixiObject = core.pixi.objects.get(id);
|
|
197
|
+
const deg = pixiObject ? (pixiObject.rotation * 180 / Math.PI) : 0;
|
|
198
|
+
const pos = pixiObject ? { x: pixiObject.x, y: pixiObject.y } : { x: 0, y: 0 };
|
|
199
|
+
core._groupRotateStart.set(id, { angle: deg, position: pos });
|
|
200
|
+
}
|
|
201
|
+
core._groupRotateCenter = data.center;
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
core.eventBus.on(Events.Tool.GroupRotateUpdate, (data) => {
|
|
205
|
+
const center = core._groupRotateCenter;
|
|
206
|
+
if (!center) return;
|
|
207
|
+
const rad = (data.angle || 0) * Math.PI / 180;
|
|
208
|
+
const cos = Math.cos(rad);
|
|
209
|
+
const sin = Math.sin(rad);
|
|
210
|
+
for (const id of data.objects) {
|
|
211
|
+
const start = core._groupRotateStart?.get(id);
|
|
212
|
+
if (!start) continue;
|
|
213
|
+
const startAngle = start.angle;
|
|
214
|
+
const newAngle = startAngle + data.angle;
|
|
215
|
+
const relX = start.position.x - center.x;
|
|
216
|
+
const relY = start.position.y - center.y;
|
|
217
|
+
const newX = center.x + relX * cos - relY * sin;
|
|
218
|
+
const newY = center.y + relX * sin + relY * cos;
|
|
219
|
+
const pObj = core.pixi.objects.get(id);
|
|
220
|
+
const halfW = (pObj?.width || 0) / 2;
|
|
221
|
+
const halfH = (pObj?.height || 0) / 2;
|
|
222
|
+
core.updateObjectPositionDirect(id, { x: newX - halfW, y: newY - halfH });
|
|
223
|
+
core.pixi.updateObjectRotation(id, newAngle);
|
|
224
|
+
core.updateObjectRotationDirect(id, newAngle);
|
|
225
|
+
}
|
|
226
|
+
core.eventBus.emit(Events.Object.TransformUpdated, { objectId: '__group__', type: 'rotation' });
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
core.eventBus.on(Events.Tool.GroupRotateEnd, (data) => {
|
|
230
|
+
const center = core._groupRotateCenter;
|
|
231
|
+
if (!center) return;
|
|
232
|
+
const changes = [];
|
|
233
|
+
for (const id of data.objects) {
|
|
234
|
+
const start = core._groupRotateStart?.get(id);
|
|
235
|
+
const pixiObject = core.pixi.objects.get(id);
|
|
236
|
+
if (!start || !pixiObject) continue;
|
|
237
|
+
const toAngle = pixiObject.rotation * 180 / Math.PI;
|
|
238
|
+
const objState = core.state.state.objects.find(o => o.id === id);
|
|
239
|
+
const toPos = objState?.position
|
|
240
|
+
? { x: objState.position.x, y: objState.position.y }
|
|
241
|
+
: (() => {
|
|
242
|
+
const halfW = (pixiObject.width || 0) / 2;
|
|
243
|
+
const halfH = (pixiObject.height || 0) / 2;
|
|
244
|
+
return { x: pixiObject.x - halfW, y: pixiObject.y - halfH };
|
|
245
|
+
})();
|
|
246
|
+
const halfW = (pixiObject.width || 0) / 2;
|
|
247
|
+
const halfH = (pixiObject.height || 0) / 2;
|
|
248
|
+
const fromPos = { x: start.position.x - halfW, y: start.position.y - halfH };
|
|
249
|
+
if (Math.abs(start.angle - toAngle) > 0.1 || Math.abs(fromPos.x - toPos.x) > 0.1 || Math.abs(fromPos.y - toPos.y) > 0.1) {
|
|
250
|
+
changes.push({ id, fromAngle: start.angle, toAngle, fromPos, toPos });
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (changes.length > 0) {
|
|
254
|
+
const cmd = new GroupRotateCommand(core, changes);
|
|
255
|
+
cmd.setEventBus(core.eventBus);
|
|
256
|
+
core.history.executeCommand(cmd);
|
|
257
|
+
}
|
|
258
|
+
core._groupRotateStart = null;
|
|
259
|
+
core._groupRotateCenter = null;
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
core.eventBus.on(Events.Object.Rotate, (data) => {
|
|
263
|
+
core.pixi.updateObjectRotation(data.objectId, data.angle);
|
|
264
|
+
core.updateObjectRotationDirect(data.objectId, data.angle);
|
|
265
|
+
core.eventBus.emit(Events.Object.TransformUpdated, {
|
|
266
|
+
objectId: data.objectId,
|
|
267
|
+
type: 'rotation',
|
|
268
|
+
angle: data.angle
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
core.eventBus.on(Events.Object.TransformUpdated, (data) => {
|
|
273
|
+
if (core.selectTool && core.selectTool.selection && core.selectTool.selection.has(data.objectId)) {
|
|
274
|
+
core.selectTool.updateResizeHandles();
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normalizeSingleResizeGeometry,
|
|
3
|
+
resolveSingleResizeDominantAxis,
|
|
4
|
+
resolveAnchoredResizePosition,
|
|
5
|
+
} from '../../services/ResizePolicyService.js';
|
|
6
|
+
|
|
7
|
+
export function shouldNormalizeSingleResize(objectType) {
|
|
8
|
+
return objectType === 'image'
|
|
9
|
+
|| objectType === 'frame'
|
|
10
|
+
|| objectType === 'emoji';
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function getActiveResize(core, objectId) {
|
|
14
|
+
return core._activeResize && core._activeResize.objectId === objectId
|
|
15
|
+
? core._activeResize
|
|
16
|
+
: null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function normalizeResizeUpdatePayload(core, object, data) {
|
|
20
|
+
const activeResize = getActiveResize(core, data.object);
|
|
21
|
+
if (!data.size || !object || !shouldNormalizeSingleResize(object.type)) {
|
|
22
|
+
return activeResize;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (activeResize && !activeResize.dominantAxis) {
|
|
26
|
+
const dominantAxis = resolveSingleResizeDominantAxis({
|
|
27
|
+
startSize: activeResize.startSize,
|
|
28
|
+
size: data.size,
|
|
29
|
+
objectType: object.type,
|
|
30
|
+
properties: object.properties || {},
|
|
31
|
+
});
|
|
32
|
+
if (dominantAxis === 'width' || dominantAxis === 'height') {
|
|
33
|
+
activeResize.dominantAxis = dominantAxis;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const normalized = normalizeSingleResizeGeometry({
|
|
38
|
+
startSize: activeResize?.startSize || { width: object.width, height: object.height },
|
|
39
|
+
startPosition: activeResize?.startPosition || object.position || null,
|
|
40
|
+
handle: activeResize?.handle || '',
|
|
41
|
+
size: data.size,
|
|
42
|
+
position: data.position,
|
|
43
|
+
objectType: object.type,
|
|
44
|
+
properties: object.properties || {},
|
|
45
|
+
preferredDominantAxis: activeResize?.dominantAxis || null,
|
|
46
|
+
});
|
|
47
|
+
data.size = normalized.size;
|
|
48
|
+
data.position = normalized.position;
|
|
49
|
+
return activeResize;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function normalizeResizeEndPayload(core, object, data) {
|
|
53
|
+
const activeResize = getActiveResize(core, data.object);
|
|
54
|
+
if (!object || !shouldNormalizeSingleResize(object.type)) {
|
|
55
|
+
return activeResize;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const normalized = normalizeSingleResizeGeometry({
|
|
59
|
+
startSize: activeResize?.startSize || data.oldSize || { width: object.width, height: object.height },
|
|
60
|
+
startPosition: activeResize?.startPosition || data.oldPosition || object.position || null,
|
|
61
|
+
handle: activeResize?.handle || '',
|
|
62
|
+
size: data.newSize,
|
|
63
|
+
position: data.newPosition,
|
|
64
|
+
objectType: object.type,
|
|
65
|
+
properties: object.properties || {},
|
|
66
|
+
preferredDominantAxis: activeResize?.dominantAxis || null,
|
|
67
|
+
});
|
|
68
|
+
data.newSize = normalized.size;
|
|
69
|
+
data.newPosition = normalized.position;
|
|
70
|
+
return activeResize;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function resolveResizePositionFallback(core, objectId, size) {
|
|
74
|
+
const activeResize = getActiveResize(core, objectId);
|
|
75
|
+
if (!activeResize) return null;
|
|
76
|
+
|
|
77
|
+
return resolveAnchoredResizePosition({
|
|
78
|
+
startPosition: activeResize.startPosition,
|
|
79
|
+
startSize: core.optimization?.startSize || activeResize.startSize,
|
|
80
|
+
normalizedSize: size,
|
|
81
|
+
handle: activeResize.handle,
|
|
82
|
+
});
|
|
83
|
+
}
|