canvu-react 0.4.63 → 0.4.65
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/chatbot.d.cts +1 -1
- package/dist/chatbot.d.ts +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +746 -97
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +18 -3
- package/dist/react.d.ts +18 -3
- package/dist/react.js +746 -97
- package/dist/react.js.map +1 -1
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.d.cts +1 -1
- package/dist/realtime.d.ts +1 -1
- package/dist/realtime.js.map +1 -1
- package/dist/{types-C_PMen-D.d.ts → types-BZUp3LpC.d.ts} +211 -3
- package/dist/{types--jCoyZIF.d.cts → types-Bw3REwrb.d.cts} +211 -3
- package/package.json +1 -1
package/dist/react.js
CHANGED
|
@@ -3146,7 +3146,9 @@ function ToolPluginComponent({
|
|
|
3146
3146
|
toolTransform,
|
|
3147
3147
|
createItem,
|
|
3148
3148
|
selectAfterCreate,
|
|
3149
|
-
onSelectModeItemClick
|
|
3149
|
+
onSelectModeItemClick,
|
|
3150
|
+
onBeforeInteraction,
|
|
3151
|
+
onAfterInteraction
|
|
3150
3152
|
}) {
|
|
3151
3153
|
const contribution = useMemo(
|
|
3152
3154
|
() => ({
|
|
@@ -3159,9 +3161,27 @@ function ToolPluginComponent({
|
|
|
3159
3161
|
selectAfterCreate,
|
|
3160
3162
|
onSelectModeItemClick
|
|
3161
3163
|
}
|
|
3162
|
-
] : void 0
|
|
3164
|
+
] : void 0,
|
|
3165
|
+
interactionHooks: onBeforeInteraction || onAfterInteraction ? {
|
|
3166
|
+
onBeforeInteraction: onBeforeInteraction ? (detail) => {
|
|
3167
|
+
if (detail.toolId !== tool.id) return void 0;
|
|
3168
|
+
return onBeforeInteraction(detail);
|
|
3169
|
+
} : void 0,
|
|
3170
|
+
onAfterInteraction: onAfterInteraction ? (detail) => {
|
|
3171
|
+
if (detail.toolId !== tool.id) return;
|
|
3172
|
+
onAfterInteraction(detail);
|
|
3173
|
+
} : void 0
|
|
3174
|
+
} : void 0
|
|
3163
3175
|
}),
|
|
3164
|
-
[
|
|
3176
|
+
[
|
|
3177
|
+
createItem,
|
|
3178
|
+
onAfterInteraction,
|
|
3179
|
+
onBeforeInteraction,
|
|
3180
|
+
onSelectModeItemClick,
|
|
3181
|
+
selectAfterCreate,
|
|
3182
|
+
tool,
|
|
3183
|
+
toolTransform
|
|
3184
|
+
]
|
|
3165
3185
|
);
|
|
3166
3186
|
useCanvuPluginContribution(pluginId, contribution);
|
|
3167
3187
|
return null;
|
|
@@ -3172,6 +3192,8 @@ function createToolPlugin(options) {
|
|
|
3172
3192
|
toolTransform,
|
|
3173
3193
|
selectAfterCreate,
|
|
3174
3194
|
onSelectModeItemClick,
|
|
3195
|
+
onBeforeInteraction,
|
|
3196
|
+
onAfterInteraction,
|
|
3175
3197
|
...tool
|
|
3176
3198
|
} = options;
|
|
3177
3199
|
const pluginId = `canvu.plugin.tool:${tool.id}`;
|
|
@@ -3186,7 +3208,9 @@ function createToolPlugin(options) {
|
|
|
3186
3208
|
toolTransform,
|
|
3187
3209
|
createItem,
|
|
3188
3210
|
selectAfterCreate,
|
|
3189
|
-
onSelectModeItemClick
|
|
3211
|
+
onSelectModeItemClick,
|
|
3212
|
+
onBeforeInteraction,
|
|
3213
|
+
onAfterInteraction
|
|
3190
3214
|
}
|
|
3191
3215
|
);
|
|
3192
3216
|
}
|
|
@@ -5622,7 +5646,7 @@ function attachViewportInput(options) {
|
|
|
5622
5646
|
if (touchMomentum) {
|
|
5623
5647
|
touchMomentum.cancel();
|
|
5624
5648
|
}
|
|
5625
|
-
const panOk = allowPrimaryPointerPan();
|
|
5649
|
+
const panOk = allowPrimaryPointerPan(e);
|
|
5626
5650
|
if (e.pointerType === "mouse" && e.button === 0) {
|
|
5627
5651
|
if (!panOk) {
|
|
5628
5652
|
return;
|
|
@@ -7646,6 +7670,93 @@ function PresenceRemoteLayer({
|
|
|
7646
7670
|
);
|
|
7647
7671
|
}
|
|
7648
7672
|
|
|
7673
|
+
// src/react/read-only-activation.ts
|
|
7674
|
+
function findReadOnlyItemClickPlacement(item, placements) {
|
|
7675
|
+
const toolId = item.customToolId;
|
|
7676
|
+
if (!toolId) return null;
|
|
7677
|
+
return [...placements].reverse().find(
|
|
7678
|
+
(placement) => placement.toolId === toolId && placement.onSelectModeItemClick
|
|
7679
|
+
) ?? null;
|
|
7680
|
+
}
|
|
7681
|
+
function resolveReadOnlyActivationTarget(input) {
|
|
7682
|
+
const {
|
|
7683
|
+
pointer,
|
|
7684
|
+
camera,
|
|
7685
|
+
container,
|
|
7686
|
+
items,
|
|
7687
|
+
detailItems = items,
|
|
7688
|
+
placements,
|
|
7689
|
+
scope,
|
|
7690
|
+
selectedIds
|
|
7691
|
+
} = input;
|
|
7692
|
+
const rect = container.getBoundingClientRect();
|
|
7693
|
+
const world = camera.screenToWorld(
|
|
7694
|
+
pointer.clientX - rect.left,
|
|
7695
|
+
pointer.clientY - rect.top
|
|
7696
|
+
);
|
|
7697
|
+
const hit = hitTestWorldPoint(items, world.worldX, world.worldY, {
|
|
7698
|
+
lineHitWorld: 10 / camera.zoom,
|
|
7699
|
+
ignoreLocked: true
|
|
7700
|
+
});
|
|
7701
|
+
if (!hit) return null;
|
|
7702
|
+
const customPlacement = findReadOnlyItemClickPlacement(hit, placements);
|
|
7703
|
+
if (customPlacement?.onSelectModeItemClick) {
|
|
7704
|
+
return {
|
|
7705
|
+
item: hit,
|
|
7706
|
+
activation: "custom",
|
|
7707
|
+
worldX: world.worldX,
|
|
7708
|
+
worldY: world.worldY
|
|
7709
|
+
};
|
|
7710
|
+
}
|
|
7711
|
+
if (scope === "all") {
|
|
7712
|
+
return {
|
|
7713
|
+
item: hit,
|
|
7714
|
+
activation: "read-only",
|
|
7715
|
+
worldX: world.worldX,
|
|
7716
|
+
worldY: world.worldY
|
|
7717
|
+
};
|
|
7718
|
+
}
|
|
7719
|
+
if (typeof scope === "function") {
|
|
7720
|
+
const allowed = scope({
|
|
7721
|
+
item: hit,
|
|
7722
|
+
worldX: world.worldX,
|
|
7723
|
+
worldY: world.worldY,
|
|
7724
|
+
clientX: pointer.clientX,
|
|
7725
|
+
clientY: pointer.clientY,
|
|
7726
|
+
pointerType: pointer.pointerType,
|
|
7727
|
+
shiftKey: pointer.shiftKey,
|
|
7728
|
+
altKey: pointer.altKey,
|
|
7729
|
+
metaKey: pointer.metaKey,
|
|
7730
|
+
ctrlKey: pointer.ctrlKey,
|
|
7731
|
+
items: detailItems,
|
|
7732
|
+
selectedIds
|
|
7733
|
+
});
|
|
7734
|
+
if (allowed) {
|
|
7735
|
+
return {
|
|
7736
|
+
item: hit,
|
|
7737
|
+
activation: "read-only",
|
|
7738
|
+
worldX: world.worldX,
|
|
7739
|
+
worldY: world.worldY
|
|
7740
|
+
};
|
|
7741
|
+
}
|
|
7742
|
+
}
|
|
7743
|
+
return null;
|
|
7744
|
+
}
|
|
7745
|
+
function createReadOnlyActivationSession(target, pointer) {
|
|
7746
|
+
return {
|
|
7747
|
+
pointerId: pointer.pointerId,
|
|
7748
|
+
itemId: target.item.id,
|
|
7749
|
+
activation: target.activation,
|
|
7750
|
+
startWorld: { x: target.worldX, y: target.worldY },
|
|
7751
|
+
startScreen: { x: pointer.clientX, y: pointer.clientY }
|
|
7752
|
+
};
|
|
7753
|
+
}
|
|
7754
|
+
function didReadOnlyActivationMovePastTap(session, pointer, tapPx) {
|
|
7755
|
+
const dx = pointer.clientX - session.startScreen.x;
|
|
7756
|
+
const dy = pointer.clientY - session.startScreen.y;
|
|
7757
|
+
return Math.hypot(dx, dy) > tapPx;
|
|
7758
|
+
}
|
|
7759
|
+
|
|
7649
7760
|
// src/react/stable-selection.ts
|
|
7650
7761
|
function shallowEqualStringArray(a, b) {
|
|
7651
7762
|
if (a === b) return true;
|
|
@@ -7999,13 +8110,6 @@ function isDefaultMarkerToolStyle(style) {
|
|
|
7999
8110
|
function tagCustomPlacementItem(item, toolId) {
|
|
8000
8111
|
return item.customToolId === toolId ? item : { ...item, customToolId: toolId };
|
|
8001
8112
|
}
|
|
8002
|
-
function findSelectModeItemClickPlacement(item, placements) {
|
|
8003
|
-
const toolId = item.customToolId;
|
|
8004
|
-
if (!toolId) return null;
|
|
8005
|
-
return [...placements].reverse().find(
|
|
8006
|
-
(placement) => placement.toolId === toolId && placement.onSelectModeItemClick
|
|
8007
|
-
) ?? null;
|
|
8008
|
-
}
|
|
8009
8113
|
function mergeToolListById(baseTools, pluginTools) {
|
|
8010
8114
|
const next = [...baseTools];
|
|
8011
8115
|
for (const tool of pluginTools) {
|
|
@@ -8133,9 +8237,12 @@ var VectorViewport = forwardRef(
|
|
|
8133
8237
|
toolId = "hand",
|
|
8134
8238
|
applePencilNav = false,
|
|
8135
8239
|
interactive = false,
|
|
8240
|
+
readOnlyInteraction,
|
|
8136
8241
|
selectedIds: selectedIdsProp,
|
|
8137
8242
|
onSelectionChange,
|
|
8138
8243
|
onItemsChange: consumerOnItemsChange,
|
|
8244
|
+
onBeforeInteraction: consumerOnBeforeInteraction,
|
|
8245
|
+
onAfterInteraction: consumerOnAfterInteraction,
|
|
8139
8246
|
onActivateLink,
|
|
8140
8247
|
onWorldPointerDown: consumerOnWorldPointerDown,
|
|
8141
8248
|
toolbar,
|
|
@@ -8261,6 +8368,24 @@ var VectorViewport = forwardRef(
|
|
|
8261
8368
|
(contribution) => contribution.callbacks?.onCameraChange
|
|
8262
8369
|
)
|
|
8263
8370
|
);
|
|
8371
|
+
const beforeInteractionHooks = useMemo(
|
|
8372
|
+
() => [
|
|
8373
|
+
consumerOnBeforeInteraction,
|
|
8374
|
+
...orderedPluginContributions.map(
|
|
8375
|
+
(contribution) => contribution.interactionHooks?.onBeforeInteraction
|
|
8376
|
+
)
|
|
8377
|
+
].filter((hook) => hook != null),
|
|
8378
|
+
[consumerOnBeforeInteraction, orderedPluginContributions]
|
|
8379
|
+
);
|
|
8380
|
+
const afterInteractionHooks = useMemo(
|
|
8381
|
+
() => [
|
|
8382
|
+
consumerOnAfterInteraction,
|
|
8383
|
+
...orderedPluginContributions.map(
|
|
8384
|
+
(contribution) => contribution.interactionHooks?.onAfterInteraction
|
|
8385
|
+
)
|
|
8386
|
+
].filter((hook) => hook != null),
|
|
8387
|
+
[consumerOnAfterInteraction, orderedPluginContributions]
|
|
8388
|
+
);
|
|
8264
8389
|
const onItemsChange = useMemo(() => {
|
|
8265
8390
|
const middlewares = orderedPluginContributions.map((contribution) => contribution.wrapOnItemsChange).filter(
|
|
8266
8391
|
(middleware) => middleware != null
|
|
@@ -8315,6 +8440,8 @@ var VectorViewport = forwardRef(
|
|
|
8315
8440
|
);
|
|
8316
8441
|
const toolIdRef = useRef(toolId);
|
|
8317
8442
|
const interactiveRef = useRef(interactive);
|
|
8443
|
+
const readOnlyInteractionRef = useRef(readOnlyInteraction);
|
|
8444
|
+
readOnlyInteractionRef.current = readOnlyInteraction;
|
|
8318
8445
|
const reducedMotionRef = useRef(false);
|
|
8319
8446
|
const itemsRef = useRef(items);
|
|
8320
8447
|
const onWorldPointerDownRef = useRef(onWorldPointerDown);
|
|
@@ -8328,6 +8455,7 @@ var VectorViewport = forwardRef(
|
|
|
8328
8455
|
const allCustomPlacementsRef = useRef(allCustomPlacements);
|
|
8329
8456
|
allCustomPlacementsRef.current = allCustomPlacements;
|
|
8330
8457
|
const dragStateRef = useRef({ kind: "idle" });
|
|
8458
|
+
const readOnlyItemClickStateRef = useRef(null);
|
|
8331
8459
|
const clipboardRef = useRef(null);
|
|
8332
8460
|
const undoStackRef = useRef([]);
|
|
8333
8461
|
const redoStackRef = useRef([]);
|
|
@@ -8404,6 +8532,81 @@ var VectorViewport = forwardRef(
|
|
|
8404
8532
|
[items]
|
|
8405
8533
|
);
|
|
8406
8534
|
itemsRef.current = normalizedItems;
|
|
8535
|
+
const beforeInteractionHooksRef = useRef(beforeInteractionHooks);
|
|
8536
|
+
beforeInteractionHooksRef.current = beforeInteractionHooks;
|
|
8537
|
+
const afterInteractionHooksRef = useRef(afterInteractionHooks);
|
|
8538
|
+
afterInteractionHooksRef.current = afterInteractionHooks;
|
|
8539
|
+
const canvuInteractionSeqRef = useRef(0);
|
|
8540
|
+
const activeCanvuInteractionRef = useRef(null);
|
|
8541
|
+
const makeInteractionPoint = useCallback(
|
|
8542
|
+
(input) => ({
|
|
8543
|
+
worldX: input.worldX,
|
|
8544
|
+
worldY: input.worldY,
|
|
8545
|
+
clientX: input.clientX,
|
|
8546
|
+
clientY: input.clientY
|
|
8547
|
+
}),
|
|
8548
|
+
[]
|
|
8549
|
+
);
|
|
8550
|
+
const startCanvuInteraction = useCallback(
|
|
8551
|
+
(input) => {
|
|
8552
|
+
const start = makeInteractionPoint(input);
|
|
8553
|
+
const detail = {
|
|
8554
|
+
interactionId: `canvu-interaction-${++canvuInteractionSeqRef.current}`,
|
|
8555
|
+
kind: input.kind,
|
|
8556
|
+
toolId: input.toolId,
|
|
8557
|
+
pointerType: input.pointerType,
|
|
8558
|
+
button: input.button,
|
|
8559
|
+
shiftKey: input.shiftKey,
|
|
8560
|
+
altKey: input.altKey,
|
|
8561
|
+
metaKey: input.metaKey,
|
|
8562
|
+
ctrlKey: input.ctrlKey,
|
|
8563
|
+
start,
|
|
8564
|
+
current: start,
|
|
8565
|
+
selectedIds: [...effectiveSelectedIdsRef.current],
|
|
8566
|
+
itemIds: [...input.itemIds ?? []],
|
|
8567
|
+
items: itemsRef.current
|
|
8568
|
+
};
|
|
8569
|
+
for (const hook of beforeInteractionHooksRef.current) {
|
|
8570
|
+
if (hook(detail) === "handled") {
|
|
8571
|
+
return null;
|
|
8572
|
+
}
|
|
8573
|
+
}
|
|
8574
|
+
activeCanvuInteractionRef.current = detail;
|
|
8575
|
+
return detail;
|
|
8576
|
+
},
|
|
8577
|
+
[makeInteractionPoint]
|
|
8578
|
+
);
|
|
8579
|
+
const updateCanvuInteractionCurrent = useCallback(
|
|
8580
|
+
(input) => {
|
|
8581
|
+
const detail = activeCanvuInteractionRef.current;
|
|
8582
|
+
if (!detail) return;
|
|
8583
|
+
activeCanvuInteractionRef.current = {
|
|
8584
|
+
...detail,
|
|
8585
|
+
current: makeInteractionPoint(input)
|
|
8586
|
+
};
|
|
8587
|
+
},
|
|
8588
|
+
[makeInteractionPoint]
|
|
8589
|
+
);
|
|
8590
|
+
const finishCanvuInteraction = useCallback(
|
|
8591
|
+
(outcome, options) => {
|
|
8592
|
+
const detail = activeCanvuInteractionRef.current;
|
|
8593
|
+
if (!detail) return;
|
|
8594
|
+
activeCanvuInteractionRef.current = null;
|
|
8595
|
+
const current = options?.current ? makeInteractionPoint(options.current) : detail.current;
|
|
8596
|
+
const info = options?.info;
|
|
8597
|
+
const afterDetail = {
|
|
8598
|
+
...detail,
|
|
8599
|
+
current,
|
|
8600
|
+
itemIds: detail.itemIds.length > 0 ? detail.itemIds : [...info?.itemIds ?? []],
|
|
8601
|
+
outcome,
|
|
8602
|
+
...info ? { info } : {}
|
|
8603
|
+
};
|
|
8604
|
+
for (const hook of afterInteractionHooksRef.current) {
|
|
8605
|
+
hook(afterDetail);
|
|
8606
|
+
}
|
|
8607
|
+
},
|
|
8608
|
+
[makeInteractionPoint]
|
|
8609
|
+
);
|
|
8407
8610
|
onWorldPointerDownRef.current = onWorldPointerDown;
|
|
8408
8611
|
const originalOnItemsChangeRef = useRef(onItemsChange);
|
|
8409
8612
|
originalOnItemsChangeRef.current = onItemsChange;
|
|
@@ -8430,6 +8633,31 @@ var VectorViewport = forwardRef(
|
|
|
8430
8633
|
);
|
|
8431
8634
|
const resolvedItemsRef = useRef(resolvedItems);
|
|
8432
8635
|
resolvedItemsRef.current = resolvedItems;
|
|
8636
|
+
const readOnlyActivationResolutionCacheRef = useRef(/* @__PURE__ */ new WeakMap());
|
|
8637
|
+
const resolveReadOnlyActivation = useCallback(
|
|
8638
|
+
(pointer) => {
|
|
8639
|
+
const cache = readOnlyActivationResolutionCacheRef.current;
|
|
8640
|
+
if (cache.has(pointer)) return cache.get(pointer) ?? null;
|
|
8641
|
+
let target = null;
|
|
8642
|
+
const cam = cameraRef.current;
|
|
8643
|
+
const container = sceneContainerRef.current;
|
|
8644
|
+
if (!interactiveRef.current && toolIdRef.current === "select" && cam && container) {
|
|
8645
|
+
target = resolveReadOnlyActivationTarget({
|
|
8646
|
+
pointer,
|
|
8647
|
+
camera: cam,
|
|
8648
|
+
container,
|
|
8649
|
+
items: resolvedItemsRef.current,
|
|
8650
|
+
detailItems: itemsRef.current,
|
|
8651
|
+
placements: allCustomPlacementsRef.current,
|
|
8652
|
+
scope: readOnlyInteractionRef.current?.itemClicks ?? "custom",
|
|
8653
|
+
selectedIds: effectiveSelectedIdsRef.current
|
|
8654
|
+
});
|
|
8655
|
+
}
|
|
8656
|
+
cache.set(pointer, target);
|
|
8657
|
+
return target;
|
|
8658
|
+
},
|
|
8659
|
+
[]
|
|
8660
|
+
);
|
|
8433
8661
|
const liveId = useId();
|
|
8434
8662
|
const reducedMotion = usePrefersReducedMotion();
|
|
8435
8663
|
reducedMotionRef.current = reducedMotion;
|
|
@@ -8644,9 +8872,14 @@ var VectorViewport = forwardRef(
|
|
|
8644
8872
|
);
|
|
8645
8873
|
if (item) {
|
|
8646
8874
|
const exists = itemsRef.current.some((it) => it.id === id);
|
|
8875
|
+
const info = {
|
|
8876
|
+
motive: "draw",
|
|
8877
|
+
itemIds: [id],
|
|
8878
|
+
toolId: args.tool
|
|
8879
|
+
};
|
|
8647
8880
|
change(
|
|
8648
8881
|
exists ? replaceItem(itemsRef.current, id, item) : [...itemsRef.current, item],
|
|
8649
|
-
|
|
8882
|
+
info
|
|
8650
8883
|
);
|
|
8651
8884
|
patchCurrentStrokeStyle({
|
|
8652
8885
|
stroke: item.stroke ?? DEFAULT_STROKE_STYLE.stroke,
|
|
@@ -8654,10 +8887,15 @@ var VectorViewport = forwardRef(
|
|
|
8654
8887
|
strokeOpacity: item.strokeOpacity,
|
|
8655
8888
|
strokeDash: item.strokeDash
|
|
8656
8889
|
});
|
|
8890
|
+
if (!shouldKeepToolForContinuousPenInput(args.tool, args.pointerType)) {
|
|
8891
|
+
requestAutoResetTool(args.tool);
|
|
8892
|
+
}
|
|
8893
|
+
return info;
|
|
8657
8894
|
}
|
|
8658
8895
|
if (!shouldKeepToolForContinuousPenInput(args.tool, args.pointerType)) {
|
|
8659
8896
|
requestAutoResetTool(args.tool);
|
|
8660
8897
|
}
|
|
8898
|
+
return void 0;
|
|
8661
8899
|
},
|
|
8662
8900
|
[
|
|
8663
8901
|
patchCurrentStrokeStyle,
|
|
@@ -8788,17 +9026,19 @@ var VectorViewport = forwardRef(
|
|
|
8788
9026
|
}
|
|
8789
9027
|
emitRemoteStrokePreviewClear();
|
|
8790
9028
|
setPlacementPreview(null);
|
|
8791
|
-
commitCompletedStroke({
|
|
9029
|
+
const info = commitCompletedStroke({
|
|
8792
9030
|
tool,
|
|
8793
9031
|
pointerType,
|
|
8794
9032
|
points: [...pts],
|
|
8795
9033
|
style,
|
|
8796
9034
|
itemId
|
|
8797
9035
|
});
|
|
9036
|
+
finishCanvuInteraction("completed", { info });
|
|
8798
9037
|
},
|
|
8799
9038
|
[
|
|
8800
9039
|
commitCompletedStroke,
|
|
8801
9040
|
emitRemoteStrokePreviewClear,
|
|
9041
|
+
finishCanvuInteraction,
|
|
8802
9042
|
releaseInteractionPointer,
|
|
8803
9043
|
renderSceneWithLivePenStroke
|
|
8804
9044
|
]
|
|
@@ -8847,12 +9087,14 @@ var VectorViewport = forwardRef(
|
|
|
8847
9087
|
onUpdate: renderFrame,
|
|
8848
9088
|
wheelElement: wrapperRef.current ?? void 0,
|
|
8849
9089
|
touchHandledElsewhere: applePencilNav,
|
|
8850
|
-
allowPrimaryPointerPan: () => {
|
|
9090
|
+
allowPrimaryPointerPan: (event) => {
|
|
8851
9091
|
if (interactiveRef.current) {
|
|
8852
9092
|
return toolIdRef.current === "hand";
|
|
8853
9093
|
}
|
|
8854
9094
|
const t = toolIdRef.current;
|
|
8855
|
-
|
|
9095
|
+
if (t === "hand") return true;
|
|
9096
|
+
if (t !== "select") return false;
|
|
9097
|
+
return resolveReadOnlyActivation(event) === null;
|
|
8856
9098
|
}
|
|
8857
9099
|
});
|
|
8858
9100
|
let detachPencil;
|
|
@@ -8873,7 +9115,7 @@ var VectorViewport = forwardRef(
|
|
|
8873
9115
|
cameraRef.current = null;
|
|
8874
9116
|
setCameraForOverlay(null);
|
|
8875
9117
|
};
|
|
8876
|
-
}, [applePencilNav, renderFrame]);
|
|
9118
|
+
}, [applePencilNav, renderFrame, resolveReadOnlyActivation]);
|
|
8877
9119
|
useEffect(() => {
|
|
8878
9120
|
rendererRef.current?.setInteractionState({
|
|
8879
9121
|
selectedIds: effectiveSelectedIds,
|
|
@@ -9387,6 +9629,29 @@ var VectorViewport = forwardRef(
|
|
|
9387
9629
|
const rect = el.getBoundingClientRect();
|
|
9388
9630
|
return cam.screenToWorld(clientX - rect.left, clientY - rect.top);
|
|
9389
9631
|
}, []);
|
|
9632
|
+
const buildSelectModeItemClickDetail = useCallback(
|
|
9633
|
+
(item, world, pointer) => ({
|
|
9634
|
+
item,
|
|
9635
|
+
worldX: world.worldX,
|
|
9636
|
+
worldY: world.worldY,
|
|
9637
|
+
clientX: pointer.clientX,
|
|
9638
|
+
clientY: pointer.clientY,
|
|
9639
|
+
pointerType: pointer.pointerType,
|
|
9640
|
+
shiftKey: pointer.shiftKey,
|
|
9641
|
+
altKey: pointer.altKey,
|
|
9642
|
+
metaKey: pointer.metaKey,
|
|
9643
|
+
ctrlKey: pointer.ctrlKey,
|
|
9644
|
+
items: itemsRef.current,
|
|
9645
|
+
updateItem: (next) => {
|
|
9646
|
+
onItemsChangeRef.current?.(replaceItem(itemsRef.current, item.id, next), {
|
|
9647
|
+
motive: "custom",
|
|
9648
|
+
itemIds: [item.id]
|
|
9649
|
+
});
|
|
9650
|
+
},
|
|
9651
|
+
setSelectedIds: (ids) => setEffectiveSelectedIdsRef.current(ids)
|
|
9652
|
+
}),
|
|
9653
|
+
[]
|
|
9654
|
+
);
|
|
9390
9655
|
const handleOverlayContextMenu = useCallback(
|
|
9391
9656
|
(e) => {
|
|
9392
9657
|
if (!interactiveRef.current || !onItemsChangeRef.current) return;
|
|
@@ -9813,6 +10078,118 @@ var VectorViewport = forwardRef(
|
|
|
9813
10078
|
},
|
|
9814
10079
|
[screenToWorld]
|
|
9815
10080
|
);
|
|
10081
|
+
useEffect(() => {
|
|
10082
|
+
const root = interactionRootRef.current;
|
|
10083
|
+
if (!root) return;
|
|
10084
|
+
const onReadOnlyPointerDownCapture = (e) => {
|
|
10085
|
+
if (e.button !== 0) return;
|
|
10086
|
+
if (readOnlyItemClickStateRef.current) return;
|
|
10087
|
+
const target = resolveReadOnlyActivation(e);
|
|
10088
|
+
if (!target) return;
|
|
10089
|
+
const accepted = startCanvuInteraction({
|
|
10090
|
+
kind: "select-mode-item-click",
|
|
10091
|
+
toolId: "select",
|
|
10092
|
+
pointerType: e.pointerType,
|
|
10093
|
+
button: e.button,
|
|
10094
|
+
worldX: target.worldX,
|
|
10095
|
+
worldY: target.worldY,
|
|
10096
|
+
clientX: e.clientX,
|
|
10097
|
+
clientY: e.clientY,
|
|
10098
|
+
shiftKey: e.shiftKey,
|
|
10099
|
+
altKey: e.altKey,
|
|
10100
|
+
metaKey: e.metaKey,
|
|
10101
|
+
ctrlKey: e.ctrlKey,
|
|
10102
|
+
itemIds: [target.item.id]
|
|
10103
|
+
});
|
|
10104
|
+
if (!accepted) {
|
|
10105
|
+
e.preventDefault();
|
|
10106
|
+
e.stopPropagation();
|
|
10107
|
+
return;
|
|
10108
|
+
}
|
|
10109
|
+
wrapperRef.current?.focus({ preventScroll: true });
|
|
10110
|
+
readOnlyItemClickStateRef.current = createReadOnlyActivationSession(
|
|
10111
|
+
target,
|
|
10112
|
+
e
|
|
10113
|
+
);
|
|
10114
|
+
e.preventDefault();
|
|
10115
|
+
e.stopPropagation();
|
|
10116
|
+
};
|
|
10117
|
+
root.addEventListener("pointerdown", onReadOnlyPointerDownCapture, {
|
|
10118
|
+
capture: true
|
|
10119
|
+
});
|
|
10120
|
+
return () => {
|
|
10121
|
+
root.removeEventListener("pointerdown", onReadOnlyPointerDownCapture, {
|
|
10122
|
+
capture: true
|
|
10123
|
+
});
|
|
10124
|
+
};
|
|
10125
|
+
}, [resolveReadOnlyActivation, startCanvuInteraction]);
|
|
10126
|
+
useEffect(() => {
|
|
10127
|
+
const finishReadOnlyClick = (ev) => {
|
|
10128
|
+
const st = readOnlyItemClickStateRef.current;
|
|
10129
|
+
if (!st || st.pointerId !== ev.pointerId) return;
|
|
10130
|
+
readOnlyItemClickStateRef.current = null;
|
|
10131
|
+
const world = screenToWorld(ev.clientX, ev.clientY);
|
|
10132
|
+
const current = {
|
|
10133
|
+
worldX: world.worldX,
|
|
10134
|
+
worldY: world.worldY,
|
|
10135
|
+
clientX: ev.clientX,
|
|
10136
|
+
clientY: ev.clientY
|
|
10137
|
+
};
|
|
10138
|
+
updateCanvuInteractionCurrent(current);
|
|
10139
|
+
if (ev.type === "pointercancel") {
|
|
10140
|
+
finishCanvuInteraction("cancelled", { current });
|
|
10141
|
+
return;
|
|
10142
|
+
}
|
|
10143
|
+
if (didReadOnlyActivationMovePastTap(st, ev, TAP_PX)) {
|
|
10144
|
+
finishCanvuInteraction("cancelled", { current });
|
|
10145
|
+
return;
|
|
10146
|
+
}
|
|
10147
|
+
const item = itemsRef.current.find((candidate) => candidate.id === st.itemId) ?? resolvedItemsRef.current.find((candidate) => candidate.id === st.itemId);
|
|
10148
|
+
if (!item) {
|
|
10149
|
+
finishCanvuInteraction("cancelled", { current });
|
|
10150
|
+
return;
|
|
10151
|
+
}
|
|
10152
|
+
const detail = buildSelectModeItemClickDetail(item, world, ev);
|
|
10153
|
+
if (st.activation === "custom") {
|
|
10154
|
+
const placement = findReadOnlyItemClickPlacement(
|
|
10155
|
+
item,
|
|
10156
|
+
allCustomPlacementsRef.current
|
|
10157
|
+
);
|
|
10158
|
+
const onSelectModeItemClick = placement?.onSelectModeItemClick;
|
|
10159
|
+
if (!onSelectModeItemClick) {
|
|
10160
|
+
finishCanvuInteraction("cancelled", { current });
|
|
10161
|
+
return;
|
|
10162
|
+
}
|
|
10163
|
+
onSelectModeItemClick(detail);
|
|
10164
|
+
finishCanvuInteraction("completed", {
|
|
10165
|
+
current,
|
|
10166
|
+
info: { motive: "custom", itemIds: [item.id], toolId: "select" }
|
|
10167
|
+
});
|
|
10168
|
+
return;
|
|
10169
|
+
}
|
|
10170
|
+
const handled = readOnlyInteractionRef.current?.onItemClick?.(detail) === "handled";
|
|
10171
|
+
if (!handled) {
|
|
10172
|
+
const cur = effectiveSelectedIdsRef.current;
|
|
10173
|
+
const next = ev.shiftKey ? cur.includes(item.id) ? cur.filter((id) => id !== item.id) : [...cur, item.id] : [item.id];
|
|
10174
|
+
setEffectiveSelectedIdsRef.current(next);
|
|
10175
|
+
}
|
|
10176
|
+
finishCanvuInteraction("completed", {
|
|
10177
|
+
current,
|
|
10178
|
+
info: { motive: "custom", itemIds: [item.id], toolId: "select" }
|
|
10179
|
+
});
|
|
10180
|
+
};
|
|
10181
|
+
document.addEventListener("pointerup", finishReadOnlyClick);
|
|
10182
|
+
document.addEventListener("pointercancel", finishReadOnlyClick);
|
|
10183
|
+
return () => {
|
|
10184
|
+
document.removeEventListener("pointerup", finishReadOnlyClick);
|
|
10185
|
+
document.removeEventListener("pointercancel", finishReadOnlyClick);
|
|
10186
|
+
};
|
|
10187
|
+
}, [
|
|
10188
|
+
buildSelectModeItemClickDetail,
|
|
10189
|
+
finishCanvuInteraction,
|
|
10190
|
+
screenToWorld,
|
|
10191
|
+
updateCanvuInteractionCurrent
|
|
10192
|
+
]);
|
|
9816
10193
|
const handleOverlayPointerDown = useCallback(
|
|
9817
10194
|
(e) => {
|
|
9818
10195
|
let currentDragState = dragStateRef.current;
|
|
@@ -9868,12 +10245,26 @@ var VectorViewport = forwardRef(
|
|
|
9868
10245
|
if (!raw) return void 0;
|
|
9869
10246
|
return raw.toolKind === "arrow" && raw.arrowBind ? bakeArrowItemToAbsolute(raw, canonical) : raw;
|
|
9870
10247
|
};
|
|
10248
|
+
const startInteraction = (kind, itemIds) => startCanvuInteraction({
|
|
10249
|
+
kind,
|
|
10250
|
+
toolId: tool,
|
|
10251
|
+
pointerType: e.pointerType,
|
|
10252
|
+
button: e.button,
|
|
10253
|
+
worldX,
|
|
10254
|
+
worldY,
|
|
10255
|
+
clientX: e.clientX,
|
|
10256
|
+
clientY: e.clientY,
|
|
10257
|
+
shiftKey: e.shiftKey,
|
|
10258
|
+
altKey: e.altKey,
|
|
10259
|
+
metaKey: e.metaKey,
|
|
10260
|
+
ctrlKey: e.ctrlKey,
|
|
10261
|
+
itemIds
|
|
10262
|
+
});
|
|
10263
|
+
const stopHandledInteraction = () => {
|
|
10264
|
+
e.preventDefault();
|
|
10265
|
+
e.stopPropagation();
|
|
10266
|
+
};
|
|
9871
10267
|
if (tool === "eraser") {
|
|
9872
|
-
dragStateRef.current = { kind: "erase" };
|
|
9873
|
-
eraserPreviewIdsRef.current = /* @__PURE__ */ new Set();
|
|
9874
|
-
setEraserPreviewIds([]);
|
|
9875
|
-
setEraserTrail([{ x: worldX, y: worldY, t: Date.now() }]);
|
|
9876
|
-
setEraserActive(true);
|
|
9877
10268
|
const toErase = collectEraserTargetsAtWorldPoint(
|
|
9878
10269
|
resolved,
|
|
9879
10270
|
worldX,
|
|
@@ -9883,6 +10274,15 @@ var VectorViewport = forwardRef(
|
|
|
9883
10274
|
ignoreLocked: true
|
|
9884
10275
|
}
|
|
9885
10276
|
);
|
|
10277
|
+
if (!startInteraction("erase", toErase)) {
|
|
10278
|
+
stopHandledInteraction();
|
|
10279
|
+
return;
|
|
10280
|
+
}
|
|
10281
|
+
dragStateRef.current = { kind: "erase" };
|
|
10282
|
+
eraserPreviewIdsRef.current = /* @__PURE__ */ new Set();
|
|
10283
|
+
setEraserPreviewIds([]);
|
|
10284
|
+
setEraserTrail([{ x: worldX, y: worldY, t: Date.now() }]);
|
|
10285
|
+
setEraserActive(true);
|
|
9886
10286
|
if (toErase.length > 0) {
|
|
9887
10287
|
for (const id of toErase) {
|
|
9888
10288
|
eraserPreviewIdsRef.current.add(id);
|
|
@@ -9915,6 +10315,10 @@ var VectorViewport = forwardRef(
|
|
|
9915
10315
|
const snapSpin = bakedSnapshot(selected.id);
|
|
9916
10316
|
if (!snapSpin) return;
|
|
9917
10317
|
const pivot = itemPivotWorld(selected);
|
|
10318
|
+
if (!startInteraction("rotate", [selected.id])) {
|
|
10319
|
+
stopHandledInteraction();
|
|
10320
|
+
return;
|
|
10321
|
+
}
|
|
9918
10322
|
dragStateRef.current = {
|
|
9919
10323
|
kind: "rotate",
|
|
9920
10324
|
id: selected.id,
|
|
@@ -9939,6 +10343,10 @@ var VectorViewport = forwardRef(
|
|
|
9939
10343
|
if (hb) {
|
|
9940
10344
|
const snapRs = bakedSnapshot(selected.id);
|
|
9941
10345
|
if (!snapRs) return;
|
|
10346
|
+
if (!startInteraction("resize", [selected.id])) {
|
|
10347
|
+
stopHandledInteraction();
|
|
10348
|
+
return;
|
|
10349
|
+
}
|
|
9942
10350
|
dragStateRef.current = {
|
|
9943
10351
|
kind: "resize",
|
|
9944
10352
|
id: selected.id,
|
|
@@ -9960,7 +10368,7 @@ var VectorViewport = forwardRef(
|
|
|
9960
10368
|
ignoreLocked: true
|
|
9961
10369
|
});
|
|
9962
10370
|
if (hit) {
|
|
9963
|
-
const selectModeClickPlacement = !e.shiftKey ?
|
|
10371
|
+
const selectModeClickPlacement = !e.shiftKey ? findReadOnlyItemClickPlacement(hit, allCustomPlacementsRef.current) : null;
|
|
9964
10372
|
if (selectModeClickPlacement) {
|
|
9965
10373
|
const isAlreadySelected = cur.includes(hit.id);
|
|
9966
10374
|
const moveIds = isAlreadySelected ? [...cur] : [hit.id];
|
|
@@ -9971,6 +10379,10 @@ var VectorViewport = forwardRef(
|
|
|
9971
10379
|
moveSnapshots[id] = snap;
|
|
9972
10380
|
}
|
|
9973
10381
|
}
|
|
10382
|
+
if (!startInteraction("select-mode-item-click", [hit.id])) {
|
|
10383
|
+
stopHandledInteraction();
|
|
10384
|
+
return;
|
|
10385
|
+
}
|
|
9974
10386
|
dragStateRef.current = {
|
|
9975
10387
|
kind: "select-mode-item-click",
|
|
9976
10388
|
id: hit.id,
|
|
@@ -9987,7 +10399,14 @@ var VectorViewport = forwardRef(
|
|
|
9987
10399
|
}
|
|
9988
10400
|
if (e.shiftKey) {
|
|
9989
10401
|
const next = cur.includes(hit.id) ? cur.filter((id) => id !== hit.id) : [...cur, hit.id];
|
|
10402
|
+
if (!startInteraction("select-mode-item-click", [hit.id])) {
|
|
10403
|
+
stopHandledInteraction();
|
|
10404
|
+
return;
|
|
10405
|
+
}
|
|
9990
10406
|
setEffectiveSelectedIdsRef.current(next);
|
|
10407
|
+
finishCanvuInteraction("completed", {
|
|
10408
|
+
info: { motive: "custom", itemIds: [hit.id], toolId: tool }
|
|
10409
|
+
});
|
|
9991
10410
|
e.preventDefault();
|
|
9992
10411
|
e.stopPropagation();
|
|
9993
10412
|
return;
|
|
@@ -9995,7 +10414,6 @@ var VectorViewport = forwardRef(
|
|
|
9995
10414
|
let idsToMove;
|
|
9996
10415
|
if (!cur.includes(hit.id)) {
|
|
9997
10416
|
idsToMove = [hit.id];
|
|
9998
|
-
setEffectiveSelectedIdsRef.current(idsToMove);
|
|
9999
10417
|
} else {
|
|
10000
10418
|
idsToMove = [...cur];
|
|
10001
10419
|
}
|
|
@@ -10006,6 +10424,13 @@ var VectorViewport = forwardRef(
|
|
|
10006
10424
|
snapshots[id] = snap;
|
|
10007
10425
|
}
|
|
10008
10426
|
}
|
|
10427
|
+
if (!startInteraction("move", idsToMove)) {
|
|
10428
|
+
stopHandledInteraction();
|
|
10429
|
+
return;
|
|
10430
|
+
}
|
|
10431
|
+
if (!cur.includes(hit.id)) {
|
|
10432
|
+
setEffectiveSelectedIdsRef.current(idsToMove);
|
|
10433
|
+
}
|
|
10009
10434
|
dragStateRef.current = {
|
|
10010
10435
|
kind: "move",
|
|
10011
10436
|
ids: idsToMove,
|
|
@@ -10030,9 +10455,14 @@ var VectorViewport = forwardRef(
|
|
|
10030
10455
|
}
|
|
10031
10456
|
}
|
|
10032
10457
|
if (Object.keys(snapshots).length > 0) {
|
|
10458
|
+
const moveIds = Object.keys(snapshots);
|
|
10459
|
+
if (!startInteraction("move", moveIds)) {
|
|
10460
|
+
stopHandledInteraction();
|
|
10461
|
+
return;
|
|
10462
|
+
}
|
|
10033
10463
|
dragStateRef.current = {
|
|
10034
10464
|
kind: "move",
|
|
10035
|
-
ids:
|
|
10465
|
+
ids: moveIds,
|
|
10036
10466
|
snapshots,
|
|
10037
10467
|
startWorld: { x: worldX, y: worldY }
|
|
10038
10468
|
};
|
|
@@ -10043,6 +10473,10 @@ var VectorViewport = forwardRef(
|
|
|
10043
10473
|
}
|
|
10044
10474
|
}
|
|
10045
10475
|
}
|
|
10476
|
+
if (!startInteraction("marquee")) {
|
|
10477
|
+
stopHandledInteraction();
|
|
10478
|
+
return;
|
|
10479
|
+
}
|
|
10046
10480
|
dragStateRef.current = {
|
|
10047
10481
|
kind: "marquee",
|
|
10048
10482
|
startWorld: { x: worldX, y: worldY },
|
|
@@ -10071,6 +10505,10 @@ var VectorViewport = forwardRef(
|
|
|
10071
10505
|
);
|
|
10072
10506
|
const straightLine = tool === "draw" ? createStraightStrokeState(startPoint, e.clientX, e.clientY) : void 0;
|
|
10073
10507
|
const directPenStroke = e.pointerType === "pen" && (tool === "draw" || tool === "marker");
|
|
10508
|
+
if (!startInteraction("stroke")) {
|
|
10509
|
+
stopHandledInteraction();
|
|
10510
|
+
return;
|
|
10511
|
+
}
|
|
10074
10512
|
let itemId;
|
|
10075
10513
|
if (directPenStroke) {
|
|
10076
10514
|
itemId = createShapeId();
|
|
@@ -10114,6 +10552,10 @@ var VectorViewport = forwardRef(
|
|
|
10114
10552
|
return;
|
|
10115
10553
|
}
|
|
10116
10554
|
if (tool === "text" || tool === "image") {
|
|
10555
|
+
if (!startInteraction("tap")) {
|
|
10556
|
+
stopHandledInteraction();
|
|
10557
|
+
return;
|
|
10558
|
+
}
|
|
10117
10559
|
dragStateRef.current = {
|
|
10118
10560
|
kind: "tap",
|
|
10119
10561
|
tool,
|
|
@@ -10127,6 +10569,10 @@ var VectorViewport = forwardRef(
|
|
|
10127
10569
|
}
|
|
10128
10570
|
const cp = customPlacementRef.current;
|
|
10129
10571
|
if (tool === "rect" || tool === "ellipse" || tool === "architectural-cloud" || tool === "line" || tool === "arrow" || cp && tool === cp.toolId) {
|
|
10572
|
+
if (!startInteraction("place")) {
|
|
10573
|
+
stopHandledInteraction();
|
|
10574
|
+
return;
|
|
10575
|
+
}
|
|
10130
10576
|
dragStateRef.current = {
|
|
10131
10577
|
kind: "place",
|
|
10132
10578
|
tool,
|
|
@@ -10144,8 +10590,10 @@ var VectorViewport = forwardRef(
|
|
|
10144
10590
|
captureInteractionPointer,
|
|
10145
10591
|
emitRemoteStrokePreview,
|
|
10146
10592
|
finalizeStrokeDragState,
|
|
10593
|
+
finishCanvuInteraction,
|
|
10147
10594
|
renderSceneWithLivePenStroke,
|
|
10148
10595
|
screenToWorld,
|
|
10596
|
+
startCanvuInteraction,
|
|
10149
10597
|
startOrRestartStraightStrokeHoldTimer
|
|
10150
10598
|
]
|
|
10151
10599
|
);
|
|
@@ -10174,14 +10622,32 @@ var VectorViewport = forwardRef(
|
|
|
10174
10622
|
e.stopImmediatePropagation();
|
|
10175
10623
|
return;
|
|
10176
10624
|
}
|
|
10177
|
-
wrapperRef.current?.focus({ preventScroll: true });
|
|
10178
|
-
setContextMenu(null);
|
|
10179
10625
|
const startPoint = pointerSampleToWorldPoint(
|
|
10180
10626
|
screenToWorld,
|
|
10181
10627
|
e.clientX,
|
|
10182
10628
|
e.clientY,
|
|
10183
10629
|
e.pressure
|
|
10184
10630
|
);
|
|
10631
|
+
if (!startCanvuInteraction({
|
|
10632
|
+
kind: "stroke",
|
|
10633
|
+
toolId: tool,
|
|
10634
|
+
pointerType: e.pointerType,
|
|
10635
|
+
button: e.button,
|
|
10636
|
+
worldX: startPoint.x,
|
|
10637
|
+
worldY: startPoint.y,
|
|
10638
|
+
clientX: e.clientX,
|
|
10639
|
+
clientY: e.clientY,
|
|
10640
|
+
shiftKey: e.shiftKey,
|
|
10641
|
+
altKey: e.altKey,
|
|
10642
|
+
metaKey: e.metaKey,
|
|
10643
|
+
ctrlKey: e.ctrlKey
|
|
10644
|
+
})) {
|
|
10645
|
+
e.preventDefault();
|
|
10646
|
+
e.stopImmediatePropagation();
|
|
10647
|
+
return;
|
|
10648
|
+
}
|
|
10649
|
+
wrapperRef.current?.focus({ preventScroll: true });
|
|
10650
|
+
setContextMenu(null);
|
|
10185
10651
|
const straightLine = tool === "draw" ? createStraightStrokeState(startPoint, e.clientX, e.clientY) : void 0;
|
|
10186
10652
|
const itemId = createShapeId();
|
|
10187
10653
|
const item = createFreehandStrokeItem(
|
|
@@ -10229,6 +10695,7 @@ var VectorViewport = forwardRef(
|
|
|
10229
10695
|
interactive,
|
|
10230
10696
|
renderSceneWithLivePenStroke,
|
|
10231
10697
|
screenToWorld,
|
|
10698
|
+
startCanvuInteraction,
|
|
10232
10699
|
startOrRestartStraightStrokeHoldTimer
|
|
10233
10700
|
]);
|
|
10234
10701
|
useEffect(() => {
|
|
@@ -10279,15 +10746,32 @@ var VectorViewport = forwardRef(
|
|
|
10279
10746
|
stopTouchEvent(ev);
|
|
10280
10747
|
return;
|
|
10281
10748
|
}
|
|
10282
|
-
wrapperRef.current?.focus({ preventScroll: true });
|
|
10283
|
-
setContextMenu(null);
|
|
10284
|
-
penDetectedRef.current = true;
|
|
10285
10749
|
const startPoint = pointerSampleToWorldPoint(
|
|
10286
10750
|
screenToWorld,
|
|
10287
10751
|
touch.clientX,
|
|
10288
10752
|
touch.clientY,
|
|
10289
10753
|
touchPressure(touch)
|
|
10290
10754
|
);
|
|
10755
|
+
if (!startCanvuInteraction({
|
|
10756
|
+
kind: "stroke",
|
|
10757
|
+
toolId: tool,
|
|
10758
|
+
pointerType: "pen",
|
|
10759
|
+
button: 0,
|
|
10760
|
+
worldX: startPoint.x,
|
|
10761
|
+
worldY: startPoint.y,
|
|
10762
|
+
clientX: touch.clientX,
|
|
10763
|
+
clientY: touch.clientY,
|
|
10764
|
+
shiftKey: ev.shiftKey,
|
|
10765
|
+
altKey: ev.altKey,
|
|
10766
|
+
metaKey: ev.metaKey,
|
|
10767
|
+
ctrlKey: ev.ctrlKey
|
|
10768
|
+
})) {
|
|
10769
|
+
stopTouchEvent(ev);
|
|
10770
|
+
return;
|
|
10771
|
+
}
|
|
10772
|
+
wrapperRef.current?.focus({ preventScroll: true });
|
|
10773
|
+
setContextMenu(null);
|
|
10774
|
+
penDetectedRef.current = true;
|
|
10291
10775
|
const straightLine = tool === "draw" ? createStraightStrokeState(startPoint, touch.clientX, touch.clientY) : void 0;
|
|
10292
10776
|
const itemId = createShapeId();
|
|
10293
10777
|
const item = createFreehandStrokeItem(
|
|
@@ -10333,6 +10817,12 @@ var VectorViewport = forwardRef(
|
|
|
10333
10817
|
touch.clientY,
|
|
10334
10818
|
touchPressure(touch)
|
|
10335
10819
|
);
|
|
10820
|
+
updateCanvuInteractionCurrent({
|
|
10821
|
+
worldX: endpoint.x,
|
|
10822
|
+
worldY: endpoint.y,
|
|
10823
|
+
clientX: touch.clientX,
|
|
10824
|
+
clientY: touch.clientY
|
|
10825
|
+
});
|
|
10336
10826
|
if (updateStraightStrokeForMove(st, touch.clientX, touch.clientY, endpoint)) {
|
|
10337
10827
|
debugApplePencilPointer("touchmove-stroke", {
|
|
10338
10828
|
touchId: touch.identifier,
|
|
@@ -10374,16 +10864,42 @@ var VectorViewport = forwardRef(
|
|
|
10374
10864
|
if (st.kind !== "stroke") return;
|
|
10375
10865
|
const touch = findChangedTouch(ev.changedTouches);
|
|
10376
10866
|
if (!touch) return;
|
|
10867
|
+
const currentPoint = pointerSampleToWorldPoint(
|
|
10868
|
+
screenToWorld,
|
|
10869
|
+
touch.clientX,
|
|
10870
|
+
touch.clientY,
|
|
10871
|
+
touchPressure(touch)
|
|
10872
|
+
);
|
|
10873
|
+
updateCanvuInteractionCurrent({
|
|
10874
|
+
worldX: currentPoint.x,
|
|
10875
|
+
worldY: currentPoint.y,
|
|
10876
|
+
clientX: touch.clientX,
|
|
10877
|
+
clientY: touch.clientY
|
|
10878
|
+
});
|
|
10879
|
+
if (ev.type === "touchcancel") {
|
|
10880
|
+
clearStraightStrokeHoldTimer(st);
|
|
10881
|
+
dragStateRef.current = { kind: "idle" };
|
|
10882
|
+
releaseInteractionPointer();
|
|
10883
|
+
if (st.itemId) {
|
|
10884
|
+
renderSceneWithLivePenStroke(null);
|
|
10885
|
+
}
|
|
10886
|
+
emitRemoteStrokePreviewClear();
|
|
10887
|
+
setPlacementPreview(null);
|
|
10888
|
+
finishCanvuInteraction("cancelled", {
|
|
10889
|
+
current: {
|
|
10890
|
+
worldX: currentPoint.x,
|
|
10891
|
+
worldY: currentPoint.y,
|
|
10892
|
+
clientX: touch.clientX,
|
|
10893
|
+
clientY: touch.clientY
|
|
10894
|
+
}
|
|
10895
|
+
});
|
|
10896
|
+
stopTouchEvent(ev);
|
|
10897
|
+
return;
|
|
10898
|
+
}
|
|
10377
10899
|
const cam = cameraRef.current;
|
|
10378
10900
|
if (cam) {
|
|
10379
10901
|
if (st.straightLine?.active) {
|
|
10380
|
-
|
|
10381
|
-
screenToWorld,
|
|
10382
|
-
touch.clientX,
|
|
10383
|
-
touch.clientY,
|
|
10384
|
-
touchPressure(touch)
|
|
10385
|
-
);
|
|
10386
|
-
setStraightStrokeEndpoint(st, endpoint);
|
|
10902
|
+
setStraightStrokeEndpoint(st, currentPoint);
|
|
10387
10903
|
} else {
|
|
10388
10904
|
const completedPoints = appendTouchToStrokePoints(
|
|
10389
10905
|
st.points,
|
|
@@ -10434,12 +10950,17 @@ var VectorViewport = forwardRef(
|
|
|
10434
10950
|
}, [
|
|
10435
10951
|
applePencilNav,
|
|
10436
10952
|
emitRemoteStrokePreview,
|
|
10953
|
+
emitRemoteStrokePreviewClear,
|
|
10437
10954
|
finalizeStrokeDragState,
|
|
10955
|
+
finishCanvuInteraction,
|
|
10438
10956
|
interactive,
|
|
10957
|
+
releaseInteractionPointer,
|
|
10439
10958
|
renderSceneWithLivePenStroke,
|
|
10440
10959
|
screenToWorld,
|
|
10441
10960
|
setStraightStrokeEndpoint,
|
|
10961
|
+
startCanvuInteraction,
|
|
10442
10962
|
startOrRestartStraightStrokeHoldTimer,
|
|
10963
|
+
updateCanvuInteractionCurrent,
|
|
10443
10964
|
updateStraightStrokeForMove
|
|
10444
10965
|
]);
|
|
10445
10966
|
useEffect(() => {
|
|
@@ -10452,6 +10973,12 @@ var VectorViewport = forwardRef(
|
|
|
10452
10973
|
if (st.kind === "tap") return;
|
|
10453
10974
|
if (st.kind === "marquee") {
|
|
10454
10975
|
const { worldX: worldX2, worldY: worldY2 } = screenToWorld(ev.clientX, ev.clientY);
|
|
10976
|
+
updateCanvuInteractionCurrent({
|
|
10977
|
+
worldX: worldX2,
|
|
10978
|
+
worldY: worldY2,
|
|
10979
|
+
clientX: ev.clientX,
|
|
10980
|
+
clientY: ev.clientY
|
|
10981
|
+
});
|
|
10455
10982
|
const raw = rectFromCorners(st.startWorld, { x: worldX2, y: worldY2 });
|
|
10456
10983
|
setPlacementPreview({ kind: "marquee", rect: raw });
|
|
10457
10984
|
const nextCand = collectItemIdsInRect(
|
|
@@ -10479,6 +11006,12 @@ var VectorViewport = forwardRef(
|
|
|
10479
11006
|
ev.clientY,
|
|
10480
11007
|
ev.pointerType === "pen" ? ev.pressure : void 0
|
|
10481
11008
|
);
|
|
11009
|
+
updateCanvuInteractionCurrent({
|
|
11010
|
+
worldX: endpoint.x,
|
|
11011
|
+
worldY: endpoint.y,
|
|
11012
|
+
clientX: ev.clientX,
|
|
11013
|
+
clientY: ev.clientY
|
|
11014
|
+
});
|
|
10482
11015
|
if (updateStraightStrokeForMove(st, ev.clientX, ev.clientY, endpoint)) {
|
|
10483
11016
|
return;
|
|
10484
11017
|
}
|
|
@@ -10527,6 +11060,12 @@ var VectorViewport = forwardRef(
|
|
|
10527
11060
|
}
|
|
10528
11061
|
if (st.kind === "erase") {
|
|
10529
11062
|
const { worldX: worldX2, worldY: worldY2 } = screenToWorld(ev.clientX, ev.clientY);
|
|
11063
|
+
updateCanvuInteractionCurrent({
|
|
11064
|
+
worldX: worldX2,
|
|
11065
|
+
worldY: worldY2,
|
|
11066
|
+
clientX: ev.clientX,
|
|
11067
|
+
clientY: ev.clientY
|
|
11068
|
+
});
|
|
10530
11069
|
const lineHitWorld = 10 / cam.zoom;
|
|
10531
11070
|
setEraserTrail(
|
|
10532
11071
|
(prev) => pruneEraserTrail([...prev, { x: worldX2, y: worldY2, t: Date.now() }])
|
|
@@ -10552,6 +11091,12 @@ var VectorViewport = forwardRef(
|
|
|
10552
11091
|
const change = onItemsChangeRef.current;
|
|
10553
11092
|
if (!change) return;
|
|
10554
11093
|
const { worldX, worldY } = screenToWorld(ev.clientX, ev.clientY);
|
|
11094
|
+
updateCanvuInteractionCurrent({
|
|
11095
|
+
worldX,
|
|
11096
|
+
worldY,
|
|
11097
|
+
clientX: ev.clientX,
|
|
11098
|
+
clientY: ev.clientY
|
|
11099
|
+
});
|
|
10555
11100
|
if (st.kind === "select-mode-item-click") {
|
|
10556
11101
|
const screenDx = ev.clientX - st.startScreen.x;
|
|
10557
11102
|
const screenDy = ev.clientY - st.startScreen.y;
|
|
@@ -10684,48 +11229,69 @@ var VectorViewport = forwardRef(
|
|
|
10684
11229
|
setPlacementPreview(null);
|
|
10685
11230
|
marqueeCandidateIdsRef.current = [];
|
|
10686
11231
|
setMarqueeCandidateIds([]);
|
|
11232
|
+
finishCanvuInteraction("cancelled");
|
|
10687
11233
|
return;
|
|
10688
11234
|
}
|
|
11235
|
+
const finishOutcome = ev.type === "pointercancel" ? "cancelled" : "completed";
|
|
11236
|
+
const currentWorld = screenToWorld(ev.clientX, ev.clientY);
|
|
11237
|
+
const currentInteractionPoint = {
|
|
11238
|
+
worldX: currentWorld.worldX,
|
|
11239
|
+
worldY: currentWorld.worldY,
|
|
11240
|
+
clientX: ev.clientX,
|
|
11241
|
+
clientY: ev.clientY
|
|
11242
|
+
};
|
|
11243
|
+
updateCanvuInteractionCurrent(currentInteractionPoint);
|
|
10689
11244
|
if (st.kind === "move" || st.kind === "resize" || st.kind === "rotate") {
|
|
11245
|
+
const info = st.kind === "move" ? { motive: "move", itemIds: [...st.ids] } : st.kind === "resize" ? { motive: "resize", itemIds: [st.id] } : { motive: "rotate", itemIds: [st.id] };
|
|
10690
11246
|
dragStateRef.current = { kind: "idle" };
|
|
10691
11247
|
releaseInteractionPointer();
|
|
11248
|
+
finishCanvuInteraction(finishOutcome, {
|
|
11249
|
+
current: currentInteractionPoint,
|
|
11250
|
+
...finishOutcome === "completed" ? { info } : {}
|
|
11251
|
+
});
|
|
10692
11252
|
return;
|
|
10693
11253
|
}
|
|
10694
11254
|
if (st.kind === "select-mode-item-click") {
|
|
10695
11255
|
dragStateRef.current = { kind: "idle" };
|
|
10696
11256
|
releaseInteractionPointer();
|
|
10697
|
-
if (
|
|
11257
|
+
if (finishOutcome === "cancelled") {
|
|
11258
|
+
finishCanvuInteraction("cancelled", {
|
|
11259
|
+
current: currentInteractionPoint
|
|
11260
|
+
});
|
|
11261
|
+
return;
|
|
11262
|
+
}
|
|
10698
11263
|
const dx = ev.clientX - st.startScreen.x;
|
|
10699
11264
|
const dy = ev.clientY - st.startScreen.y;
|
|
10700
|
-
if (Math.hypot(dx, dy) > TAP_PX)
|
|
11265
|
+
if (Math.hypot(dx, dy) > TAP_PX) {
|
|
11266
|
+
finishCanvuInteraction("cancelled", {
|
|
11267
|
+
current: currentInteractionPoint
|
|
11268
|
+
});
|
|
11269
|
+
return;
|
|
11270
|
+
}
|
|
10701
11271
|
const item = itemsRef.current.find((candidate) => candidate.id === st.id) ?? resolvedItemsRef.current.find((candidate) => candidate.id === st.id);
|
|
10702
|
-
if (!item)
|
|
10703
|
-
|
|
11272
|
+
if (!item) {
|
|
11273
|
+
finishCanvuInteraction("cancelled", {
|
|
11274
|
+
current: currentInteractionPoint
|
|
11275
|
+
});
|
|
11276
|
+
return;
|
|
11277
|
+
}
|
|
11278
|
+
const placement = findReadOnlyItemClickPlacement(
|
|
10704
11279
|
item,
|
|
10705
11280
|
allCustomPlacementsRef.current
|
|
10706
11281
|
);
|
|
10707
11282
|
const onSelectModeItemClick = placement?.onSelectModeItemClick;
|
|
10708
|
-
if (!onSelectModeItemClick)
|
|
10709
|
-
|
|
10710
|
-
|
|
10711
|
-
|
|
10712
|
-
|
|
10713
|
-
|
|
10714
|
-
|
|
10715
|
-
|
|
10716
|
-
|
|
10717
|
-
|
|
10718
|
-
|
|
10719
|
-
|
|
10720
|
-
ctrlKey: ev.ctrlKey,
|
|
10721
|
-
items: itemsRef.current,
|
|
10722
|
-
updateItem: (next) => {
|
|
10723
|
-
onItemsChangeRef.current?.(
|
|
10724
|
-
replaceItem(itemsRef.current, item.id, next),
|
|
10725
|
-
{ motive: "custom", itemIds: [item.id] }
|
|
10726
|
-
);
|
|
10727
|
-
},
|
|
10728
|
-
setSelectedIds: (ids) => setEffectiveSelectedIdsRef.current(ids)
|
|
11283
|
+
if (!onSelectModeItemClick) {
|
|
11284
|
+
finishCanvuInteraction("cancelled", {
|
|
11285
|
+
current: currentInteractionPoint
|
|
11286
|
+
});
|
|
11287
|
+
return;
|
|
11288
|
+
}
|
|
11289
|
+
onSelectModeItemClick(
|
|
11290
|
+
buildSelectModeItemClickDetail(item, currentWorld, ev)
|
|
11291
|
+
);
|
|
11292
|
+
finishCanvuInteraction("completed", {
|
|
11293
|
+
current: currentInteractionPoint,
|
|
11294
|
+
info: { motive: "custom", itemIds: [item.id], toolId: "select" }
|
|
10729
11295
|
});
|
|
10730
11296
|
return;
|
|
10731
11297
|
}
|
|
@@ -10735,16 +11301,25 @@ var VectorViewport = forwardRef(
|
|
|
10735
11301
|
setPlacementPreview(null);
|
|
10736
11302
|
marqueeCandidateIdsRef.current = [];
|
|
10737
11303
|
setMarqueeCandidateIds([]);
|
|
10738
|
-
const { worldX, worldY } =
|
|
11304
|
+
const { worldX, worldY } = currentWorld;
|
|
10739
11305
|
const raw = rectFromCorners(st.startWorld, { x: worldX, y: worldY });
|
|
10740
11306
|
const br = normalizeRect(raw);
|
|
10741
11307
|
const screenDx = ev.clientX - st.startScreen.x;
|
|
10742
11308
|
const screenDy = ev.clientY - st.startScreen.y;
|
|
11309
|
+
if (finishOutcome === "cancelled") {
|
|
11310
|
+
finishCanvuInteraction("cancelled", {
|
|
11311
|
+
current: currentInteractionPoint
|
|
11312
|
+
});
|
|
11313
|
+
return;
|
|
11314
|
+
}
|
|
10743
11315
|
const tooSmall = Math.hypot(screenDx, screenDy) < TAP_PX || br.width < MIN_MARQUEE_WORLD && br.height < MIN_MARQUEE_WORLD;
|
|
10744
11316
|
if (tooSmall) {
|
|
10745
11317
|
if (!st.shiftKey) {
|
|
10746
11318
|
setEffectiveSelectedIdsRef.current([]);
|
|
10747
11319
|
}
|
|
11320
|
+
finishCanvuInteraction("cancelled", {
|
|
11321
|
+
current: currentInteractionPoint
|
|
11322
|
+
});
|
|
10748
11323
|
return;
|
|
10749
11324
|
}
|
|
10750
11325
|
const picked = collectItemIdsInRect(resolvedItemsRef.current, br);
|
|
@@ -10761,9 +11336,26 @@ var VectorViewport = forwardRef(
|
|
|
10761
11336
|
} else {
|
|
10762
11337
|
setEffectiveSelectedIdsRef.current(picked);
|
|
10763
11338
|
}
|
|
11339
|
+
finishCanvuInteraction("completed", {
|
|
11340
|
+
current: currentInteractionPoint
|
|
11341
|
+
});
|
|
10764
11342
|
return;
|
|
10765
11343
|
}
|
|
10766
11344
|
if (st.kind === "stroke") {
|
|
11345
|
+
if (finishOutcome === "cancelled") {
|
|
11346
|
+
clearStraightStrokeHoldTimer(st);
|
|
11347
|
+
dragStateRef.current = { kind: "idle" };
|
|
11348
|
+
releaseInteractionPointer();
|
|
11349
|
+
if (st.itemId) {
|
|
11350
|
+
renderSceneWithLivePenStroke(null);
|
|
11351
|
+
}
|
|
11352
|
+
emitRemoteStrokePreviewClear();
|
|
11353
|
+
setPlacementPreview(null);
|
|
11354
|
+
finishCanvuInteraction("cancelled", {
|
|
11355
|
+
current: currentInteractionPoint
|
|
11356
|
+
});
|
|
11357
|
+
return;
|
|
11358
|
+
}
|
|
10767
11359
|
const completedPoints = (() => {
|
|
10768
11360
|
if (st.straightLine?.active) {
|
|
10769
11361
|
const endpoint = pointerSampleToWorldPoint(
|
|
@@ -10794,15 +11386,20 @@ var VectorViewport = forwardRef(
|
|
|
10794
11386
|
}
|
|
10795
11387
|
if (st.kind === "erase") {
|
|
10796
11388
|
const change = onItemsChangeRef.current;
|
|
11389
|
+
const erasedIds = [...eraserPreviewIdsRef.current];
|
|
11390
|
+
const info = erasedIds.length > 0 ? {
|
|
11391
|
+
motive: "erase",
|
|
11392
|
+
itemIds: erasedIds,
|
|
11393
|
+
toolId: "eraser"
|
|
11394
|
+
} : void 0;
|
|
10797
11395
|
if (change && eraserPreviewIdsRef.current.size > 0) {
|
|
10798
11396
|
const idSet = new Set(eraserPreviewIdsRef.current);
|
|
10799
|
-
|
|
10800
|
-
|
|
10801
|
-
|
|
10802
|
-
|
|
10803
|
-
|
|
10804
|
-
|
|
10805
|
-
);
|
|
11397
|
+
if (finishOutcome === "completed") {
|
|
11398
|
+
change(
|
|
11399
|
+
itemsRef.current.filter((i) => !idSet.has(i.id)),
|
|
11400
|
+
info
|
|
11401
|
+
);
|
|
11402
|
+
}
|
|
10806
11403
|
}
|
|
10807
11404
|
eraserPreviewIdsRef.current.clear();
|
|
10808
11405
|
setEraserPreviewIds([]);
|
|
@@ -10810,7 +11407,13 @@ var VectorViewport = forwardRef(
|
|
|
10810
11407
|
setEraserActive(false);
|
|
10811
11408
|
dragStateRef.current = { kind: "idle" };
|
|
10812
11409
|
releaseInteractionPointer();
|
|
10813
|
-
|
|
11410
|
+
if (finishOutcome === "completed") {
|
|
11411
|
+
requestAutoResetTool("eraser");
|
|
11412
|
+
}
|
|
11413
|
+
finishCanvuInteraction(finishOutcome, {
|
|
11414
|
+
current: currentInteractionPoint,
|
|
11415
|
+
...finishOutcome === "completed" && info ? { info } : {}
|
|
11416
|
+
});
|
|
10814
11417
|
return;
|
|
10815
11418
|
}
|
|
10816
11419
|
if (st.kind === "tap") {
|
|
@@ -10818,11 +11421,22 @@ var VectorViewport = forwardRef(
|
|
|
10818
11421
|
const dy = ev.clientY - st.startScreen.y;
|
|
10819
11422
|
dragStateRef.current = { kind: "idle" };
|
|
10820
11423
|
releaseInteractionPointer();
|
|
10821
|
-
if (Math.hypot(dx, dy) > TAP_PX)
|
|
11424
|
+
if (finishOutcome === "cancelled" || Math.hypot(dx, dy) > TAP_PX) {
|
|
11425
|
+
finishCanvuInteraction("cancelled", {
|
|
11426
|
+
current: currentInteractionPoint
|
|
11427
|
+
});
|
|
11428
|
+
return;
|
|
11429
|
+
}
|
|
10822
11430
|
const change = onItemsChangeRef.current;
|
|
10823
|
-
if (!change)
|
|
11431
|
+
if (!change) {
|
|
11432
|
+
finishCanvuInteraction("cancelled", {
|
|
11433
|
+
current: currentInteractionPoint
|
|
11434
|
+
});
|
|
11435
|
+
return;
|
|
11436
|
+
}
|
|
10824
11437
|
const id = createShapeId();
|
|
10825
11438
|
const { x: worldX, y: worldY } = st.startWorld;
|
|
11439
|
+
let info;
|
|
10826
11440
|
if (st.tool === "text") {
|
|
10827
11441
|
const fs = strokeStyleRef.current.textFontSize;
|
|
10828
11442
|
const baseline = textBaselineYFor(fs);
|
|
@@ -10845,11 +11459,12 @@ var VectorViewport = forwardRef(
|
|
|
10845
11459
|
bounds: { ...newItem.bounds }
|
|
10846
11460
|
};
|
|
10847
11461
|
const hidden = applyTextDraftWhileEditing(newItem, "");
|
|
10848
|
-
|
|
11462
|
+
info = {
|
|
10849
11463
|
motive: "text-create",
|
|
10850
11464
|
itemIds: [id],
|
|
10851
11465
|
toolId: st.tool
|
|
10852
|
-
}
|
|
11466
|
+
};
|
|
11467
|
+
change([...itemsRef.current, hidden], info);
|
|
10853
11468
|
setEffectiveSelectedIdsRef.current([id]);
|
|
10854
11469
|
setEditingTextId(id);
|
|
10855
11470
|
setDraftText("");
|
|
@@ -10858,6 +11473,10 @@ var VectorViewport = forwardRef(
|
|
|
10858
11473
|
imageInputRef.current?.click();
|
|
10859
11474
|
}
|
|
10860
11475
|
requestAutoResetTool(st.tool);
|
|
11476
|
+
finishCanvuInteraction("completed", {
|
|
11477
|
+
current: currentInteractionPoint,
|
|
11478
|
+
...info ? { info } : {}
|
|
11479
|
+
});
|
|
10861
11480
|
return;
|
|
10862
11481
|
}
|
|
10863
11482
|
if (st.kind === "place") {
|
|
@@ -10868,11 +11487,19 @@ var VectorViewport = forwardRef(
|
|
|
10868
11487
|
dragStateRef.current = { kind: "idle" };
|
|
10869
11488
|
releaseInteractionPointer();
|
|
10870
11489
|
setPlacementPreview(null);
|
|
10871
|
-
if (!change)
|
|
11490
|
+
if (finishOutcome === "cancelled" || !change) {
|
|
11491
|
+
finishCanvuInteraction("cancelled", {
|
|
11492
|
+
current: currentInteractionPoint
|
|
11493
|
+
});
|
|
11494
|
+
return;
|
|
11495
|
+
}
|
|
10872
11496
|
if (st.tool === "arrow") {
|
|
10873
11497
|
const screenDx = ev.clientX - st.startScreen.x;
|
|
10874
11498
|
const screenDy = ev.clientY - st.startScreen.y;
|
|
10875
11499
|
if (Math.hypot(screenDx, screenDy) < MIN_ARROW_DRAG_PX) {
|
|
11500
|
+
finishCanvuInteraction("cancelled", {
|
|
11501
|
+
current: currentInteractionPoint
|
|
11502
|
+
});
|
|
10876
11503
|
return;
|
|
10877
11504
|
}
|
|
10878
11505
|
const maxDist = ARROW_BIND_SNAP_PX / cam.zoom;
|
|
@@ -10904,18 +11531,23 @@ var VectorViewport = forwardRef(
|
|
|
10904
11531
|
...snapB ? { end: snapB.binding } : {}
|
|
10905
11532
|
};
|
|
10906
11533
|
}
|
|
11534
|
+
const info2 = {
|
|
11535
|
+
motive: "place",
|
|
11536
|
+
itemIds: [id2],
|
|
11537
|
+
toolId: st.tool
|
|
11538
|
+
};
|
|
10907
11539
|
change(
|
|
10908
11540
|
[
|
|
10909
11541
|
...itemsRef.current,
|
|
10910
11542
|
createLineItem(id2, rawArrow, line, "arrow", pen2, arrowBind)
|
|
10911
11543
|
],
|
|
10912
|
-
|
|
10913
|
-
motive: "place",
|
|
10914
|
-
itemIds: [id2],
|
|
10915
|
-
toolId: st.tool
|
|
10916
|
-
}
|
|
11544
|
+
info2
|
|
10917
11545
|
);
|
|
10918
11546
|
setEffectiveSelectedIdsRef.current([id2]);
|
|
11547
|
+
finishCanvuInteraction("completed", {
|
|
11548
|
+
current: currentInteractionPoint,
|
|
11549
|
+
info: info2
|
|
11550
|
+
});
|
|
10919
11551
|
return;
|
|
10920
11552
|
}
|
|
10921
11553
|
let raw = rectFromCorners(a, b);
|
|
@@ -10940,47 +11572,61 @@ var VectorViewport = forwardRef(
|
|
|
10940
11572
|
}
|
|
10941
11573
|
const id = createShapeId();
|
|
10942
11574
|
const pen = strokeStyleRef.current;
|
|
11575
|
+
let info;
|
|
10943
11576
|
if (cpUp && st.tool === cpUp.toolId) {
|
|
10944
11577
|
const item = tagCustomPlacementItem(
|
|
10945
11578
|
cpUp.createItem({ id, bounds: br }),
|
|
10946
11579
|
cpUp.toolId
|
|
10947
11580
|
);
|
|
10948
|
-
|
|
11581
|
+
info = {
|
|
10949
11582
|
motive: "place",
|
|
10950
11583
|
itemIds: [id],
|
|
10951
11584
|
toolId: st.tool
|
|
10952
|
-
}
|
|
11585
|
+
};
|
|
11586
|
+
change(itemsRef.current.concat(item), info);
|
|
10953
11587
|
if (cpUp.selectAfterCreate !== false) {
|
|
10954
11588
|
setEffectiveSelectedIdsRef.current([id]);
|
|
10955
11589
|
}
|
|
11590
|
+
finishCanvuInteraction("completed", {
|
|
11591
|
+
current: currentInteractionPoint,
|
|
11592
|
+
info
|
|
11593
|
+
});
|
|
10956
11594
|
return;
|
|
10957
11595
|
}
|
|
10958
11596
|
if (st.tool === "rect") {
|
|
10959
|
-
|
|
11597
|
+
info = {
|
|
10960
11598
|
motive: "place",
|
|
10961
11599
|
itemIds: [id],
|
|
10962
11600
|
toolId: st.tool
|
|
10963
|
-
}
|
|
11601
|
+
};
|
|
11602
|
+
change([...itemsRef.current, createRectangleItem(id, raw, pen)], info);
|
|
10964
11603
|
setEffectiveSelectedIdsRef.current([id]);
|
|
10965
11604
|
} else if (st.tool === "ellipse") {
|
|
10966
|
-
|
|
11605
|
+
info = {
|
|
10967
11606
|
motive: "place",
|
|
10968
11607
|
itemIds: [id],
|
|
10969
11608
|
toolId: st.tool
|
|
10970
|
-
}
|
|
11609
|
+
};
|
|
11610
|
+
change([...itemsRef.current, createEllipseItem(id, raw, pen)], info);
|
|
10971
11611
|
setEffectiveSelectedIdsRef.current([id]);
|
|
10972
11612
|
} else if (st.tool === "architectural-cloud") {
|
|
11613
|
+
info = {
|
|
11614
|
+
motive: "place",
|
|
11615
|
+
itemIds: [id],
|
|
11616
|
+
toolId: st.tool
|
|
11617
|
+
};
|
|
10973
11618
|
change(
|
|
10974
11619
|
[...itemsRef.current, createArchitecturalCloudItem(id, raw, pen)],
|
|
10975
|
-
|
|
10976
|
-
motive: "place",
|
|
10977
|
-
itemIds: [id],
|
|
10978
|
-
toolId: st.tool
|
|
10979
|
-
}
|
|
11620
|
+
info
|
|
10980
11621
|
);
|
|
10981
11622
|
setEffectiveSelectedIdsRef.current([id]);
|
|
10982
11623
|
} else if (st.tool === "line" || st.tool === "arrow") {
|
|
10983
11624
|
const line = lineEndpointsToLocal(raw, lineA, lineB);
|
|
11625
|
+
info = {
|
|
11626
|
+
motive: "place",
|
|
11627
|
+
itemIds: [id],
|
|
11628
|
+
toolId: st.tool
|
|
11629
|
+
};
|
|
10984
11630
|
change(
|
|
10985
11631
|
[
|
|
10986
11632
|
...itemsRef.current,
|
|
@@ -10992,15 +11638,15 @@ var VectorViewport = forwardRef(
|
|
|
10992
11638
|
pen
|
|
10993
11639
|
)
|
|
10994
11640
|
],
|
|
10995
|
-
|
|
10996
|
-
motive: "place",
|
|
10997
|
-
itemIds: [id],
|
|
10998
|
-
toolId: st.tool
|
|
10999
|
-
}
|
|
11641
|
+
info
|
|
11000
11642
|
);
|
|
11001
11643
|
setEffectiveSelectedIdsRef.current([id]);
|
|
11002
11644
|
}
|
|
11003
11645
|
requestAutoResetTool(st.tool);
|
|
11646
|
+
finishCanvuInteraction("completed", {
|
|
11647
|
+
current: currentInteractionPoint,
|
|
11648
|
+
...info ? { info } : {}
|
|
11649
|
+
});
|
|
11004
11650
|
}
|
|
11005
11651
|
};
|
|
11006
11652
|
document.addEventListener("pointermove", onMove);
|
|
@@ -11012,17 +11658,20 @@ var VectorViewport = forwardRef(
|
|
|
11012
11658
|
document.removeEventListener("pointercancel", onUp);
|
|
11013
11659
|
};
|
|
11014
11660
|
}, [
|
|
11661
|
+
buildSelectModeItemClickDetail,
|
|
11015
11662
|
emitRemoteStrokePreview,
|
|
11016
11663
|
emitRemoteStrokePreviewClear,
|
|
11017
11664
|
interactive,
|
|
11018
11665
|
pruneEraserTrail,
|
|
11019
11666
|
pruneLaserTrail,
|
|
11020
11667
|
finalizeStrokeDragState,
|
|
11668
|
+
finishCanvuInteraction,
|
|
11021
11669
|
renderSceneWithLivePenStroke,
|
|
11022
11670
|
releaseInteractionPointer,
|
|
11023
11671
|
requestAutoResetTool,
|
|
11024
11672
|
screenToWorld,
|
|
11025
11673
|
setStraightStrokeEndpoint,
|
|
11674
|
+
updateCanvuInteractionCurrent,
|
|
11026
11675
|
updateStraightStrokeForMove
|
|
11027
11676
|
]);
|
|
11028
11677
|
const selectedItemsForOverlay = useMemo(() => {
|