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.cjs
CHANGED
|
@@ -3153,7 +3153,9 @@ function ToolPluginComponent({
|
|
|
3153
3153
|
toolTransform,
|
|
3154
3154
|
createItem,
|
|
3155
3155
|
selectAfterCreate,
|
|
3156
|
-
onSelectModeItemClick
|
|
3156
|
+
onSelectModeItemClick,
|
|
3157
|
+
onBeforeInteraction,
|
|
3158
|
+
onAfterInteraction
|
|
3157
3159
|
}) {
|
|
3158
3160
|
const contribution = react.useMemo(
|
|
3159
3161
|
() => ({
|
|
@@ -3166,9 +3168,27 @@ function ToolPluginComponent({
|
|
|
3166
3168
|
selectAfterCreate,
|
|
3167
3169
|
onSelectModeItemClick
|
|
3168
3170
|
}
|
|
3169
|
-
] : void 0
|
|
3171
|
+
] : void 0,
|
|
3172
|
+
interactionHooks: onBeforeInteraction || onAfterInteraction ? {
|
|
3173
|
+
onBeforeInteraction: onBeforeInteraction ? (detail) => {
|
|
3174
|
+
if (detail.toolId !== tool.id) return void 0;
|
|
3175
|
+
return onBeforeInteraction(detail);
|
|
3176
|
+
} : void 0,
|
|
3177
|
+
onAfterInteraction: onAfterInteraction ? (detail) => {
|
|
3178
|
+
if (detail.toolId !== tool.id) return;
|
|
3179
|
+
onAfterInteraction(detail);
|
|
3180
|
+
} : void 0
|
|
3181
|
+
} : void 0
|
|
3170
3182
|
}),
|
|
3171
|
-
[
|
|
3183
|
+
[
|
|
3184
|
+
createItem,
|
|
3185
|
+
onAfterInteraction,
|
|
3186
|
+
onBeforeInteraction,
|
|
3187
|
+
onSelectModeItemClick,
|
|
3188
|
+
selectAfterCreate,
|
|
3189
|
+
tool,
|
|
3190
|
+
toolTransform
|
|
3191
|
+
]
|
|
3172
3192
|
);
|
|
3173
3193
|
useCanvuPluginContribution(pluginId, contribution);
|
|
3174
3194
|
return null;
|
|
@@ -3179,6 +3199,8 @@ function createToolPlugin(options) {
|
|
|
3179
3199
|
toolTransform,
|
|
3180
3200
|
selectAfterCreate,
|
|
3181
3201
|
onSelectModeItemClick,
|
|
3202
|
+
onBeforeInteraction,
|
|
3203
|
+
onAfterInteraction,
|
|
3182
3204
|
...tool
|
|
3183
3205
|
} = options;
|
|
3184
3206
|
const pluginId = `canvu.plugin.tool:${tool.id}`;
|
|
@@ -3193,7 +3215,9 @@ function createToolPlugin(options) {
|
|
|
3193
3215
|
toolTransform,
|
|
3194
3216
|
createItem,
|
|
3195
3217
|
selectAfterCreate,
|
|
3196
|
-
onSelectModeItemClick
|
|
3218
|
+
onSelectModeItemClick,
|
|
3219
|
+
onBeforeInteraction,
|
|
3220
|
+
onAfterInteraction
|
|
3197
3221
|
}
|
|
3198
3222
|
);
|
|
3199
3223
|
}
|
|
@@ -5629,7 +5653,7 @@ function attachViewportInput(options) {
|
|
|
5629
5653
|
if (touchMomentum) {
|
|
5630
5654
|
touchMomentum.cancel();
|
|
5631
5655
|
}
|
|
5632
|
-
const panOk = allowPrimaryPointerPan();
|
|
5656
|
+
const panOk = allowPrimaryPointerPan(e);
|
|
5633
5657
|
if (e.pointerType === "mouse" && e.button === 0) {
|
|
5634
5658
|
if (!panOk) {
|
|
5635
5659
|
return;
|
|
@@ -7653,6 +7677,93 @@ function PresenceRemoteLayer({
|
|
|
7653
7677
|
);
|
|
7654
7678
|
}
|
|
7655
7679
|
|
|
7680
|
+
// src/react/read-only-activation.ts
|
|
7681
|
+
function findReadOnlyItemClickPlacement(item, placements) {
|
|
7682
|
+
const toolId = item.customToolId;
|
|
7683
|
+
if (!toolId) return null;
|
|
7684
|
+
return [...placements].reverse().find(
|
|
7685
|
+
(placement) => placement.toolId === toolId && placement.onSelectModeItemClick
|
|
7686
|
+
) ?? null;
|
|
7687
|
+
}
|
|
7688
|
+
function resolveReadOnlyActivationTarget(input) {
|
|
7689
|
+
const {
|
|
7690
|
+
pointer,
|
|
7691
|
+
camera,
|
|
7692
|
+
container,
|
|
7693
|
+
items,
|
|
7694
|
+
detailItems = items,
|
|
7695
|
+
placements,
|
|
7696
|
+
scope,
|
|
7697
|
+
selectedIds
|
|
7698
|
+
} = input;
|
|
7699
|
+
const rect = container.getBoundingClientRect();
|
|
7700
|
+
const world = camera.screenToWorld(
|
|
7701
|
+
pointer.clientX - rect.left,
|
|
7702
|
+
pointer.clientY - rect.top
|
|
7703
|
+
);
|
|
7704
|
+
const hit = hitTestWorldPoint(items, world.worldX, world.worldY, {
|
|
7705
|
+
lineHitWorld: 10 / camera.zoom,
|
|
7706
|
+
ignoreLocked: true
|
|
7707
|
+
});
|
|
7708
|
+
if (!hit) return null;
|
|
7709
|
+
const customPlacement = findReadOnlyItemClickPlacement(hit, placements);
|
|
7710
|
+
if (customPlacement?.onSelectModeItemClick) {
|
|
7711
|
+
return {
|
|
7712
|
+
item: hit,
|
|
7713
|
+
activation: "custom",
|
|
7714
|
+
worldX: world.worldX,
|
|
7715
|
+
worldY: world.worldY
|
|
7716
|
+
};
|
|
7717
|
+
}
|
|
7718
|
+
if (scope === "all") {
|
|
7719
|
+
return {
|
|
7720
|
+
item: hit,
|
|
7721
|
+
activation: "read-only",
|
|
7722
|
+
worldX: world.worldX,
|
|
7723
|
+
worldY: world.worldY
|
|
7724
|
+
};
|
|
7725
|
+
}
|
|
7726
|
+
if (typeof scope === "function") {
|
|
7727
|
+
const allowed = scope({
|
|
7728
|
+
item: hit,
|
|
7729
|
+
worldX: world.worldX,
|
|
7730
|
+
worldY: world.worldY,
|
|
7731
|
+
clientX: pointer.clientX,
|
|
7732
|
+
clientY: pointer.clientY,
|
|
7733
|
+
pointerType: pointer.pointerType,
|
|
7734
|
+
shiftKey: pointer.shiftKey,
|
|
7735
|
+
altKey: pointer.altKey,
|
|
7736
|
+
metaKey: pointer.metaKey,
|
|
7737
|
+
ctrlKey: pointer.ctrlKey,
|
|
7738
|
+
items: detailItems,
|
|
7739
|
+
selectedIds
|
|
7740
|
+
});
|
|
7741
|
+
if (allowed) {
|
|
7742
|
+
return {
|
|
7743
|
+
item: hit,
|
|
7744
|
+
activation: "read-only",
|
|
7745
|
+
worldX: world.worldX,
|
|
7746
|
+
worldY: world.worldY
|
|
7747
|
+
};
|
|
7748
|
+
}
|
|
7749
|
+
}
|
|
7750
|
+
return null;
|
|
7751
|
+
}
|
|
7752
|
+
function createReadOnlyActivationSession(target, pointer) {
|
|
7753
|
+
return {
|
|
7754
|
+
pointerId: pointer.pointerId,
|
|
7755
|
+
itemId: target.item.id,
|
|
7756
|
+
activation: target.activation,
|
|
7757
|
+
startWorld: { x: target.worldX, y: target.worldY },
|
|
7758
|
+
startScreen: { x: pointer.clientX, y: pointer.clientY }
|
|
7759
|
+
};
|
|
7760
|
+
}
|
|
7761
|
+
function didReadOnlyActivationMovePastTap(session, pointer, tapPx) {
|
|
7762
|
+
const dx = pointer.clientX - session.startScreen.x;
|
|
7763
|
+
const dy = pointer.clientY - session.startScreen.y;
|
|
7764
|
+
return Math.hypot(dx, dy) > tapPx;
|
|
7765
|
+
}
|
|
7766
|
+
|
|
7656
7767
|
// src/react/stable-selection.ts
|
|
7657
7768
|
function shallowEqualStringArray(a, b) {
|
|
7658
7769
|
if (a === b) return true;
|
|
@@ -8006,13 +8117,6 @@ function isDefaultMarkerToolStyle(style) {
|
|
|
8006
8117
|
function tagCustomPlacementItem(item, toolId) {
|
|
8007
8118
|
return item.customToolId === toolId ? item : { ...item, customToolId: toolId };
|
|
8008
8119
|
}
|
|
8009
|
-
function findSelectModeItemClickPlacement(item, placements) {
|
|
8010
|
-
const toolId = item.customToolId;
|
|
8011
|
-
if (!toolId) return null;
|
|
8012
|
-
return [...placements].reverse().find(
|
|
8013
|
-
(placement) => placement.toolId === toolId && placement.onSelectModeItemClick
|
|
8014
|
-
) ?? null;
|
|
8015
|
-
}
|
|
8016
8120
|
function mergeToolListById(baseTools, pluginTools) {
|
|
8017
8121
|
const next = [...baseTools];
|
|
8018
8122
|
for (const tool of pluginTools) {
|
|
@@ -8140,9 +8244,12 @@ var VectorViewport = react.forwardRef(
|
|
|
8140
8244
|
toolId = "hand",
|
|
8141
8245
|
applePencilNav = false,
|
|
8142
8246
|
interactive = false,
|
|
8247
|
+
readOnlyInteraction,
|
|
8143
8248
|
selectedIds: selectedIdsProp,
|
|
8144
8249
|
onSelectionChange,
|
|
8145
8250
|
onItemsChange: consumerOnItemsChange,
|
|
8251
|
+
onBeforeInteraction: consumerOnBeforeInteraction,
|
|
8252
|
+
onAfterInteraction: consumerOnAfterInteraction,
|
|
8146
8253
|
onActivateLink,
|
|
8147
8254
|
onWorldPointerDown: consumerOnWorldPointerDown,
|
|
8148
8255
|
toolbar,
|
|
@@ -8268,6 +8375,24 @@ var VectorViewport = react.forwardRef(
|
|
|
8268
8375
|
(contribution) => contribution.callbacks?.onCameraChange
|
|
8269
8376
|
)
|
|
8270
8377
|
);
|
|
8378
|
+
const beforeInteractionHooks = react.useMemo(
|
|
8379
|
+
() => [
|
|
8380
|
+
consumerOnBeforeInteraction,
|
|
8381
|
+
...orderedPluginContributions.map(
|
|
8382
|
+
(contribution) => contribution.interactionHooks?.onBeforeInteraction
|
|
8383
|
+
)
|
|
8384
|
+
].filter((hook) => hook != null),
|
|
8385
|
+
[consumerOnBeforeInteraction, orderedPluginContributions]
|
|
8386
|
+
);
|
|
8387
|
+
const afterInteractionHooks = react.useMemo(
|
|
8388
|
+
() => [
|
|
8389
|
+
consumerOnAfterInteraction,
|
|
8390
|
+
...orderedPluginContributions.map(
|
|
8391
|
+
(contribution) => contribution.interactionHooks?.onAfterInteraction
|
|
8392
|
+
)
|
|
8393
|
+
].filter((hook) => hook != null),
|
|
8394
|
+
[consumerOnAfterInteraction, orderedPluginContributions]
|
|
8395
|
+
);
|
|
8271
8396
|
const onItemsChange = react.useMemo(() => {
|
|
8272
8397
|
const middlewares = orderedPluginContributions.map((contribution) => contribution.wrapOnItemsChange).filter(
|
|
8273
8398
|
(middleware) => middleware != null
|
|
@@ -8322,6 +8447,8 @@ var VectorViewport = react.forwardRef(
|
|
|
8322
8447
|
);
|
|
8323
8448
|
const toolIdRef = react.useRef(toolId);
|
|
8324
8449
|
const interactiveRef = react.useRef(interactive);
|
|
8450
|
+
const readOnlyInteractionRef = react.useRef(readOnlyInteraction);
|
|
8451
|
+
readOnlyInteractionRef.current = readOnlyInteraction;
|
|
8325
8452
|
const reducedMotionRef = react.useRef(false);
|
|
8326
8453
|
const itemsRef = react.useRef(items);
|
|
8327
8454
|
const onWorldPointerDownRef = react.useRef(onWorldPointerDown);
|
|
@@ -8335,6 +8462,7 @@ var VectorViewport = react.forwardRef(
|
|
|
8335
8462
|
const allCustomPlacementsRef = react.useRef(allCustomPlacements);
|
|
8336
8463
|
allCustomPlacementsRef.current = allCustomPlacements;
|
|
8337
8464
|
const dragStateRef = react.useRef({ kind: "idle" });
|
|
8465
|
+
const readOnlyItemClickStateRef = react.useRef(null);
|
|
8338
8466
|
const clipboardRef = react.useRef(null);
|
|
8339
8467
|
const undoStackRef = react.useRef([]);
|
|
8340
8468
|
const redoStackRef = react.useRef([]);
|
|
@@ -8411,6 +8539,81 @@ var VectorViewport = react.forwardRef(
|
|
|
8411
8539
|
[items]
|
|
8412
8540
|
);
|
|
8413
8541
|
itemsRef.current = normalizedItems;
|
|
8542
|
+
const beforeInteractionHooksRef = react.useRef(beforeInteractionHooks);
|
|
8543
|
+
beforeInteractionHooksRef.current = beforeInteractionHooks;
|
|
8544
|
+
const afterInteractionHooksRef = react.useRef(afterInteractionHooks);
|
|
8545
|
+
afterInteractionHooksRef.current = afterInteractionHooks;
|
|
8546
|
+
const canvuInteractionSeqRef = react.useRef(0);
|
|
8547
|
+
const activeCanvuInteractionRef = react.useRef(null);
|
|
8548
|
+
const makeInteractionPoint = react.useCallback(
|
|
8549
|
+
(input) => ({
|
|
8550
|
+
worldX: input.worldX,
|
|
8551
|
+
worldY: input.worldY,
|
|
8552
|
+
clientX: input.clientX,
|
|
8553
|
+
clientY: input.clientY
|
|
8554
|
+
}),
|
|
8555
|
+
[]
|
|
8556
|
+
);
|
|
8557
|
+
const startCanvuInteraction = react.useCallback(
|
|
8558
|
+
(input) => {
|
|
8559
|
+
const start = makeInteractionPoint(input);
|
|
8560
|
+
const detail = {
|
|
8561
|
+
interactionId: `canvu-interaction-${++canvuInteractionSeqRef.current}`,
|
|
8562
|
+
kind: input.kind,
|
|
8563
|
+
toolId: input.toolId,
|
|
8564
|
+
pointerType: input.pointerType,
|
|
8565
|
+
button: input.button,
|
|
8566
|
+
shiftKey: input.shiftKey,
|
|
8567
|
+
altKey: input.altKey,
|
|
8568
|
+
metaKey: input.metaKey,
|
|
8569
|
+
ctrlKey: input.ctrlKey,
|
|
8570
|
+
start,
|
|
8571
|
+
current: start,
|
|
8572
|
+
selectedIds: [...effectiveSelectedIdsRef.current],
|
|
8573
|
+
itemIds: [...input.itemIds ?? []],
|
|
8574
|
+
items: itemsRef.current
|
|
8575
|
+
};
|
|
8576
|
+
for (const hook of beforeInteractionHooksRef.current) {
|
|
8577
|
+
if (hook(detail) === "handled") {
|
|
8578
|
+
return null;
|
|
8579
|
+
}
|
|
8580
|
+
}
|
|
8581
|
+
activeCanvuInteractionRef.current = detail;
|
|
8582
|
+
return detail;
|
|
8583
|
+
},
|
|
8584
|
+
[makeInteractionPoint]
|
|
8585
|
+
);
|
|
8586
|
+
const updateCanvuInteractionCurrent = react.useCallback(
|
|
8587
|
+
(input) => {
|
|
8588
|
+
const detail = activeCanvuInteractionRef.current;
|
|
8589
|
+
if (!detail) return;
|
|
8590
|
+
activeCanvuInteractionRef.current = {
|
|
8591
|
+
...detail,
|
|
8592
|
+
current: makeInteractionPoint(input)
|
|
8593
|
+
};
|
|
8594
|
+
},
|
|
8595
|
+
[makeInteractionPoint]
|
|
8596
|
+
);
|
|
8597
|
+
const finishCanvuInteraction = react.useCallback(
|
|
8598
|
+
(outcome, options) => {
|
|
8599
|
+
const detail = activeCanvuInteractionRef.current;
|
|
8600
|
+
if (!detail) return;
|
|
8601
|
+
activeCanvuInteractionRef.current = null;
|
|
8602
|
+
const current = options?.current ? makeInteractionPoint(options.current) : detail.current;
|
|
8603
|
+
const info = options?.info;
|
|
8604
|
+
const afterDetail = {
|
|
8605
|
+
...detail,
|
|
8606
|
+
current,
|
|
8607
|
+
itemIds: detail.itemIds.length > 0 ? detail.itemIds : [...info?.itemIds ?? []],
|
|
8608
|
+
outcome,
|
|
8609
|
+
...info ? { info } : {}
|
|
8610
|
+
};
|
|
8611
|
+
for (const hook of afterInteractionHooksRef.current) {
|
|
8612
|
+
hook(afterDetail);
|
|
8613
|
+
}
|
|
8614
|
+
},
|
|
8615
|
+
[makeInteractionPoint]
|
|
8616
|
+
);
|
|
8414
8617
|
onWorldPointerDownRef.current = onWorldPointerDown;
|
|
8415
8618
|
const originalOnItemsChangeRef = react.useRef(onItemsChange);
|
|
8416
8619
|
originalOnItemsChangeRef.current = onItemsChange;
|
|
@@ -8437,6 +8640,31 @@ var VectorViewport = react.forwardRef(
|
|
|
8437
8640
|
);
|
|
8438
8641
|
const resolvedItemsRef = react.useRef(resolvedItems);
|
|
8439
8642
|
resolvedItemsRef.current = resolvedItems;
|
|
8643
|
+
const readOnlyActivationResolutionCacheRef = react.useRef(/* @__PURE__ */ new WeakMap());
|
|
8644
|
+
const resolveReadOnlyActivation = react.useCallback(
|
|
8645
|
+
(pointer) => {
|
|
8646
|
+
const cache = readOnlyActivationResolutionCacheRef.current;
|
|
8647
|
+
if (cache.has(pointer)) return cache.get(pointer) ?? null;
|
|
8648
|
+
let target = null;
|
|
8649
|
+
const cam = cameraRef.current;
|
|
8650
|
+
const container = sceneContainerRef.current;
|
|
8651
|
+
if (!interactiveRef.current && toolIdRef.current === "select" && cam && container) {
|
|
8652
|
+
target = resolveReadOnlyActivationTarget({
|
|
8653
|
+
pointer,
|
|
8654
|
+
camera: cam,
|
|
8655
|
+
container,
|
|
8656
|
+
items: resolvedItemsRef.current,
|
|
8657
|
+
detailItems: itemsRef.current,
|
|
8658
|
+
placements: allCustomPlacementsRef.current,
|
|
8659
|
+
scope: readOnlyInteractionRef.current?.itemClicks ?? "custom",
|
|
8660
|
+
selectedIds: effectiveSelectedIdsRef.current
|
|
8661
|
+
});
|
|
8662
|
+
}
|
|
8663
|
+
cache.set(pointer, target);
|
|
8664
|
+
return target;
|
|
8665
|
+
},
|
|
8666
|
+
[]
|
|
8667
|
+
);
|
|
8440
8668
|
const liveId = react.useId();
|
|
8441
8669
|
const reducedMotion = usePrefersReducedMotion();
|
|
8442
8670
|
reducedMotionRef.current = reducedMotion;
|
|
@@ -8651,9 +8879,14 @@ var VectorViewport = react.forwardRef(
|
|
|
8651
8879
|
);
|
|
8652
8880
|
if (item) {
|
|
8653
8881
|
const exists = itemsRef.current.some((it) => it.id === id);
|
|
8882
|
+
const info = {
|
|
8883
|
+
motive: "draw",
|
|
8884
|
+
itemIds: [id],
|
|
8885
|
+
toolId: args.tool
|
|
8886
|
+
};
|
|
8654
8887
|
change(
|
|
8655
8888
|
exists ? replaceItem(itemsRef.current, id, item) : [...itemsRef.current, item],
|
|
8656
|
-
|
|
8889
|
+
info
|
|
8657
8890
|
);
|
|
8658
8891
|
patchCurrentStrokeStyle({
|
|
8659
8892
|
stroke: item.stroke ?? DEFAULT_STROKE_STYLE.stroke,
|
|
@@ -8661,10 +8894,15 @@ var VectorViewport = react.forwardRef(
|
|
|
8661
8894
|
strokeOpacity: item.strokeOpacity,
|
|
8662
8895
|
strokeDash: item.strokeDash
|
|
8663
8896
|
});
|
|
8897
|
+
if (!shouldKeepToolForContinuousPenInput(args.tool, args.pointerType)) {
|
|
8898
|
+
requestAutoResetTool(args.tool);
|
|
8899
|
+
}
|
|
8900
|
+
return info;
|
|
8664
8901
|
}
|
|
8665
8902
|
if (!shouldKeepToolForContinuousPenInput(args.tool, args.pointerType)) {
|
|
8666
8903
|
requestAutoResetTool(args.tool);
|
|
8667
8904
|
}
|
|
8905
|
+
return void 0;
|
|
8668
8906
|
},
|
|
8669
8907
|
[
|
|
8670
8908
|
patchCurrentStrokeStyle,
|
|
@@ -8795,17 +9033,19 @@ var VectorViewport = react.forwardRef(
|
|
|
8795
9033
|
}
|
|
8796
9034
|
emitRemoteStrokePreviewClear();
|
|
8797
9035
|
setPlacementPreview(null);
|
|
8798
|
-
commitCompletedStroke({
|
|
9036
|
+
const info = commitCompletedStroke({
|
|
8799
9037
|
tool,
|
|
8800
9038
|
pointerType,
|
|
8801
9039
|
points: [...pts],
|
|
8802
9040
|
style,
|
|
8803
9041
|
itemId
|
|
8804
9042
|
});
|
|
9043
|
+
finishCanvuInteraction("completed", { info });
|
|
8805
9044
|
},
|
|
8806
9045
|
[
|
|
8807
9046
|
commitCompletedStroke,
|
|
8808
9047
|
emitRemoteStrokePreviewClear,
|
|
9048
|
+
finishCanvuInteraction,
|
|
8809
9049
|
releaseInteractionPointer,
|
|
8810
9050
|
renderSceneWithLivePenStroke
|
|
8811
9051
|
]
|
|
@@ -8854,12 +9094,14 @@ var VectorViewport = react.forwardRef(
|
|
|
8854
9094
|
onUpdate: renderFrame,
|
|
8855
9095
|
wheelElement: wrapperRef.current ?? void 0,
|
|
8856
9096
|
touchHandledElsewhere: applePencilNav,
|
|
8857
|
-
allowPrimaryPointerPan: () => {
|
|
9097
|
+
allowPrimaryPointerPan: (event) => {
|
|
8858
9098
|
if (interactiveRef.current) {
|
|
8859
9099
|
return toolIdRef.current === "hand";
|
|
8860
9100
|
}
|
|
8861
9101
|
const t = toolIdRef.current;
|
|
8862
|
-
|
|
9102
|
+
if (t === "hand") return true;
|
|
9103
|
+
if (t !== "select") return false;
|
|
9104
|
+
return resolveReadOnlyActivation(event) === null;
|
|
8863
9105
|
}
|
|
8864
9106
|
});
|
|
8865
9107
|
let detachPencil;
|
|
@@ -8880,7 +9122,7 @@ var VectorViewport = react.forwardRef(
|
|
|
8880
9122
|
cameraRef.current = null;
|
|
8881
9123
|
setCameraForOverlay(null);
|
|
8882
9124
|
};
|
|
8883
|
-
}, [applePencilNav, renderFrame]);
|
|
9125
|
+
}, [applePencilNav, renderFrame, resolveReadOnlyActivation]);
|
|
8884
9126
|
react.useEffect(() => {
|
|
8885
9127
|
rendererRef.current?.setInteractionState({
|
|
8886
9128
|
selectedIds: effectiveSelectedIds,
|
|
@@ -9394,6 +9636,29 @@ var VectorViewport = react.forwardRef(
|
|
|
9394
9636
|
const rect = el.getBoundingClientRect();
|
|
9395
9637
|
return cam.screenToWorld(clientX - rect.left, clientY - rect.top);
|
|
9396
9638
|
}, []);
|
|
9639
|
+
const buildSelectModeItemClickDetail = react.useCallback(
|
|
9640
|
+
(item, world, pointer) => ({
|
|
9641
|
+
item,
|
|
9642
|
+
worldX: world.worldX,
|
|
9643
|
+
worldY: world.worldY,
|
|
9644
|
+
clientX: pointer.clientX,
|
|
9645
|
+
clientY: pointer.clientY,
|
|
9646
|
+
pointerType: pointer.pointerType,
|
|
9647
|
+
shiftKey: pointer.shiftKey,
|
|
9648
|
+
altKey: pointer.altKey,
|
|
9649
|
+
metaKey: pointer.metaKey,
|
|
9650
|
+
ctrlKey: pointer.ctrlKey,
|
|
9651
|
+
items: itemsRef.current,
|
|
9652
|
+
updateItem: (next) => {
|
|
9653
|
+
onItemsChangeRef.current?.(replaceItem(itemsRef.current, item.id, next), {
|
|
9654
|
+
motive: "custom",
|
|
9655
|
+
itemIds: [item.id]
|
|
9656
|
+
});
|
|
9657
|
+
},
|
|
9658
|
+
setSelectedIds: (ids) => setEffectiveSelectedIdsRef.current(ids)
|
|
9659
|
+
}),
|
|
9660
|
+
[]
|
|
9661
|
+
);
|
|
9397
9662
|
const handleOverlayContextMenu = react.useCallback(
|
|
9398
9663
|
(e) => {
|
|
9399
9664
|
if (!interactiveRef.current || !onItemsChangeRef.current) return;
|
|
@@ -9820,6 +10085,118 @@ var VectorViewport = react.forwardRef(
|
|
|
9820
10085
|
},
|
|
9821
10086
|
[screenToWorld]
|
|
9822
10087
|
);
|
|
10088
|
+
react.useEffect(() => {
|
|
10089
|
+
const root = interactionRootRef.current;
|
|
10090
|
+
if (!root) return;
|
|
10091
|
+
const onReadOnlyPointerDownCapture = (e) => {
|
|
10092
|
+
if (e.button !== 0) return;
|
|
10093
|
+
if (readOnlyItemClickStateRef.current) return;
|
|
10094
|
+
const target = resolveReadOnlyActivation(e);
|
|
10095
|
+
if (!target) return;
|
|
10096
|
+
const accepted = startCanvuInteraction({
|
|
10097
|
+
kind: "select-mode-item-click",
|
|
10098
|
+
toolId: "select",
|
|
10099
|
+
pointerType: e.pointerType,
|
|
10100
|
+
button: e.button,
|
|
10101
|
+
worldX: target.worldX,
|
|
10102
|
+
worldY: target.worldY,
|
|
10103
|
+
clientX: e.clientX,
|
|
10104
|
+
clientY: e.clientY,
|
|
10105
|
+
shiftKey: e.shiftKey,
|
|
10106
|
+
altKey: e.altKey,
|
|
10107
|
+
metaKey: e.metaKey,
|
|
10108
|
+
ctrlKey: e.ctrlKey,
|
|
10109
|
+
itemIds: [target.item.id]
|
|
10110
|
+
});
|
|
10111
|
+
if (!accepted) {
|
|
10112
|
+
e.preventDefault();
|
|
10113
|
+
e.stopPropagation();
|
|
10114
|
+
return;
|
|
10115
|
+
}
|
|
10116
|
+
wrapperRef.current?.focus({ preventScroll: true });
|
|
10117
|
+
readOnlyItemClickStateRef.current = createReadOnlyActivationSession(
|
|
10118
|
+
target,
|
|
10119
|
+
e
|
|
10120
|
+
);
|
|
10121
|
+
e.preventDefault();
|
|
10122
|
+
e.stopPropagation();
|
|
10123
|
+
};
|
|
10124
|
+
root.addEventListener("pointerdown", onReadOnlyPointerDownCapture, {
|
|
10125
|
+
capture: true
|
|
10126
|
+
});
|
|
10127
|
+
return () => {
|
|
10128
|
+
root.removeEventListener("pointerdown", onReadOnlyPointerDownCapture, {
|
|
10129
|
+
capture: true
|
|
10130
|
+
});
|
|
10131
|
+
};
|
|
10132
|
+
}, [resolveReadOnlyActivation, startCanvuInteraction]);
|
|
10133
|
+
react.useEffect(() => {
|
|
10134
|
+
const finishReadOnlyClick = (ev) => {
|
|
10135
|
+
const st = readOnlyItemClickStateRef.current;
|
|
10136
|
+
if (!st || st.pointerId !== ev.pointerId) return;
|
|
10137
|
+
readOnlyItemClickStateRef.current = null;
|
|
10138
|
+
const world = screenToWorld(ev.clientX, ev.clientY);
|
|
10139
|
+
const current = {
|
|
10140
|
+
worldX: world.worldX,
|
|
10141
|
+
worldY: world.worldY,
|
|
10142
|
+
clientX: ev.clientX,
|
|
10143
|
+
clientY: ev.clientY
|
|
10144
|
+
};
|
|
10145
|
+
updateCanvuInteractionCurrent(current);
|
|
10146
|
+
if (ev.type === "pointercancel") {
|
|
10147
|
+
finishCanvuInteraction("cancelled", { current });
|
|
10148
|
+
return;
|
|
10149
|
+
}
|
|
10150
|
+
if (didReadOnlyActivationMovePastTap(st, ev, TAP_PX)) {
|
|
10151
|
+
finishCanvuInteraction("cancelled", { current });
|
|
10152
|
+
return;
|
|
10153
|
+
}
|
|
10154
|
+
const item = itemsRef.current.find((candidate) => candidate.id === st.itemId) ?? resolvedItemsRef.current.find((candidate) => candidate.id === st.itemId);
|
|
10155
|
+
if (!item) {
|
|
10156
|
+
finishCanvuInteraction("cancelled", { current });
|
|
10157
|
+
return;
|
|
10158
|
+
}
|
|
10159
|
+
const detail = buildSelectModeItemClickDetail(item, world, ev);
|
|
10160
|
+
if (st.activation === "custom") {
|
|
10161
|
+
const placement = findReadOnlyItemClickPlacement(
|
|
10162
|
+
item,
|
|
10163
|
+
allCustomPlacementsRef.current
|
|
10164
|
+
);
|
|
10165
|
+
const onSelectModeItemClick = placement?.onSelectModeItemClick;
|
|
10166
|
+
if (!onSelectModeItemClick) {
|
|
10167
|
+
finishCanvuInteraction("cancelled", { current });
|
|
10168
|
+
return;
|
|
10169
|
+
}
|
|
10170
|
+
onSelectModeItemClick(detail);
|
|
10171
|
+
finishCanvuInteraction("completed", {
|
|
10172
|
+
current,
|
|
10173
|
+
info: { motive: "custom", itemIds: [item.id], toolId: "select" }
|
|
10174
|
+
});
|
|
10175
|
+
return;
|
|
10176
|
+
}
|
|
10177
|
+
const handled = readOnlyInteractionRef.current?.onItemClick?.(detail) === "handled";
|
|
10178
|
+
if (!handled) {
|
|
10179
|
+
const cur = effectiveSelectedIdsRef.current;
|
|
10180
|
+
const next = ev.shiftKey ? cur.includes(item.id) ? cur.filter((id) => id !== item.id) : [...cur, item.id] : [item.id];
|
|
10181
|
+
setEffectiveSelectedIdsRef.current(next);
|
|
10182
|
+
}
|
|
10183
|
+
finishCanvuInteraction("completed", {
|
|
10184
|
+
current,
|
|
10185
|
+
info: { motive: "custom", itemIds: [item.id], toolId: "select" }
|
|
10186
|
+
});
|
|
10187
|
+
};
|
|
10188
|
+
document.addEventListener("pointerup", finishReadOnlyClick);
|
|
10189
|
+
document.addEventListener("pointercancel", finishReadOnlyClick);
|
|
10190
|
+
return () => {
|
|
10191
|
+
document.removeEventListener("pointerup", finishReadOnlyClick);
|
|
10192
|
+
document.removeEventListener("pointercancel", finishReadOnlyClick);
|
|
10193
|
+
};
|
|
10194
|
+
}, [
|
|
10195
|
+
buildSelectModeItemClickDetail,
|
|
10196
|
+
finishCanvuInteraction,
|
|
10197
|
+
screenToWorld,
|
|
10198
|
+
updateCanvuInteractionCurrent
|
|
10199
|
+
]);
|
|
9823
10200
|
const handleOverlayPointerDown = react.useCallback(
|
|
9824
10201
|
(e) => {
|
|
9825
10202
|
let currentDragState = dragStateRef.current;
|
|
@@ -9875,12 +10252,26 @@ var VectorViewport = react.forwardRef(
|
|
|
9875
10252
|
if (!raw) return void 0;
|
|
9876
10253
|
return raw.toolKind === "arrow" && raw.arrowBind ? bakeArrowItemToAbsolute(raw, canonical) : raw;
|
|
9877
10254
|
};
|
|
10255
|
+
const startInteraction = (kind, itemIds) => startCanvuInteraction({
|
|
10256
|
+
kind,
|
|
10257
|
+
toolId: tool,
|
|
10258
|
+
pointerType: e.pointerType,
|
|
10259
|
+
button: e.button,
|
|
10260
|
+
worldX,
|
|
10261
|
+
worldY,
|
|
10262
|
+
clientX: e.clientX,
|
|
10263
|
+
clientY: e.clientY,
|
|
10264
|
+
shiftKey: e.shiftKey,
|
|
10265
|
+
altKey: e.altKey,
|
|
10266
|
+
metaKey: e.metaKey,
|
|
10267
|
+
ctrlKey: e.ctrlKey,
|
|
10268
|
+
itemIds
|
|
10269
|
+
});
|
|
10270
|
+
const stopHandledInteraction = () => {
|
|
10271
|
+
e.preventDefault();
|
|
10272
|
+
e.stopPropagation();
|
|
10273
|
+
};
|
|
9878
10274
|
if (tool === "eraser") {
|
|
9879
|
-
dragStateRef.current = { kind: "erase" };
|
|
9880
|
-
eraserPreviewIdsRef.current = /* @__PURE__ */ new Set();
|
|
9881
|
-
setEraserPreviewIds([]);
|
|
9882
|
-
setEraserTrail([{ x: worldX, y: worldY, t: Date.now() }]);
|
|
9883
|
-
setEraserActive(true);
|
|
9884
10275
|
const toErase = collectEraserTargetsAtWorldPoint(
|
|
9885
10276
|
resolved,
|
|
9886
10277
|
worldX,
|
|
@@ -9890,6 +10281,15 @@ var VectorViewport = react.forwardRef(
|
|
|
9890
10281
|
ignoreLocked: true
|
|
9891
10282
|
}
|
|
9892
10283
|
);
|
|
10284
|
+
if (!startInteraction("erase", toErase)) {
|
|
10285
|
+
stopHandledInteraction();
|
|
10286
|
+
return;
|
|
10287
|
+
}
|
|
10288
|
+
dragStateRef.current = { kind: "erase" };
|
|
10289
|
+
eraserPreviewIdsRef.current = /* @__PURE__ */ new Set();
|
|
10290
|
+
setEraserPreviewIds([]);
|
|
10291
|
+
setEraserTrail([{ x: worldX, y: worldY, t: Date.now() }]);
|
|
10292
|
+
setEraserActive(true);
|
|
9893
10293
|
if (toErase.length > 0) {
|
|
9894
10294
|
for (const id of toErase) {
|
|
9895
10295
|
eraserPreviewIdsRef.current.add(id);
|
|
@@ -9922,6 +10322,10 @@ var VectorViewport = react.forwardRef(
|
|
|
9922
10322
|
const snapSpin = bakedSnapshot(selected.id);
|
|
9923
10323
|
if (!snapSpin) return;
|
|
9924
10324
|
const pivot = itemPivotWorld(selected);
|
|
10325
|
+
if (!startInteraction("rotate", [selected.id])) {
|
|
10326
|
+
stopHandledInteraction();
|
|
10327
|
+
return;
|
|
10328
|
+
}
|
|
9925
10329
|
dragStateRef.current = {
|
|
9926
10330
|
kind: "rotate",
|
|
9927
10331
|
id: selected.id,
|
|
@@ -9946,6 +10350,10 @@ var VectorViewport = react.forwardRef(
|
|
|
9946
10350
|
if (hb) {
|
|
9947
10351
|
const snapRs = bakedSnapshot(selected.id);
|
|
9948
10352
|
if (!snapRs) return;
|
|
10353
|
+
if (!startInteraction("resize", [selected.id])) {
|
|
10354
|
+
stopHandledInteraction();
|
|
10355
|
+
return;
|
|
10356
|
+
}
|
|
9949
10357
|
dragStateRef.current = {
|
|
9950
10358
|
kind: "resize",
|
|
9951
10359
|
id: selected.id,
|
|
@@ -9967,7 +10375,7 @@ var VectorViewport = react.forwardRef(
|
|
|
9967
10375
|
ignoreLocked: true
|
|
9968
10376
|
});
|
|
9969
10377
|
if (hit) {
|
|
9970
|
-
const selectModeClickPlacement = !e.shiftKey ?
|
|
10378
|
+
const selectModeClickPlacement = !e.shiftKey ? findReadOnlyItemClickPlacement(hit, allCustomPlacementsRef.current) : null;
|
|
9971
10379
|
if (selectModeClickPlacement) {
|
|
9972
10380
|
const isAlreadySelected = cur.includes(hit.id);
|
|
9973
10381
|
const moveIds = isAlreadySelected ? [...cur] : [hit.id];
|
|
@@ -9978,6 +10386,10 @@ var VectorViewport = react.forwardRef(
|
|
|
9978
10386
|
moveSnapshots[id] = snap;
|
|
9979
10387
|
}
|
|
9980
10388
|
}
|
|
10389
|
+
if (!startInteraction("select-mode-item-click", [hit.id])) {
|
|
10390
|
+
stopHandledInteraction();
|
|
10391
|
+
return;
|
|
10392
|
+
}
|
|
9981
10393
|
dragStateRef.current = {
|
|
9982
10394
|
kind: "select-mode-item-click",
|
|
9983
10395
|
id: hit.id,
|
|
@@ -9994,7 +10406,14 @@ var VectorViewport = react.forwardRef(
|
|
|
9994
10406
|
}
|
|
9995
10407
|
if (e.shiftKey) {
|
|
9996
10408
|
const next = cur.includes(hit.id) ? cur.filter((id) => id !== hit.id) : [...cur, hit.id];
|
|
10409
|
+
if (!startInteraction("select-mode-item-click", [hit.id])) {
|
|
10410
|
+
stopHandledInteraction();
|
|
10411
|
+
return;
|
|
10412
|
+
}
|
|
9997
10413
|
setEffectiveSelectedIdsRef.current(next);
|
|
10414
|
+
finishCanvuInteraction("completed", {
|
|
10415
|
+
info: { motive: "custom", itemIds: [hit.id], toolId: tool }
|
|
10416
|
+
});
|
|
9998
10417
|
e.preventDefault();
|
|
9999
10418
|
e.stopPropagation();
|
|
10000
10419
|
return;
|
|
@@ -10002,7 +10421,6 @@ var VectorViewport = react.forwardRef(
|
|
|
10002
10421
|
let idsToMove;
|
|
10003
10422
|
if (!cur.includes(hit.id)) {
|
|
10004
10423
|
idsToMove = [hit.id];
|
|
10005
|
-
setEffectiveSelectedIdsRef.current(idsToMove);
|
|
10006
10424
|
} else {
|
|
10007
10425
|
idsToMove = [...cur];
|
|
10008
10426
|
}
|
|
@@ -10013,6 +10431,13 @@ var VectorViewport = react.forwardRef(
|
|
|
10013
10431
|
snapshots[id] = snap;
|
|
10014
10432
|
}
|
|
10015
10433
|
}
|
|
10434
|
+
if (!startInteraction("move", idsToMove)) {
|
|
10435
|
+
stopHandledInteraction();
|
|
10436
|
+
return;
|
|
10437
|
+
}
|
|
10438
|
+
if (!cur.includes(hit.id)) {
|
|
10439
|
+
setEffectiveSelectedIdsRef.current(idsToMove);
|
|
10440
|
+
}
|
|
10016
10441
|
dragStateRef.current = {
|
|
10017
10442
|
kind: "move",
|
|
10018
10443
|
ids: idsToMove,
|
|
@@ -10037,9 +10462,14 @@ var VectorViewport = react.forwardRef(
|
|
|
10037
10462
|
}
|
|
10038
10463
|
}
|
|
10039
10464
|
if (Object.keys(snapshots).length > 0) {
|
|
10465
|
+
const moveIds = Object.keys(snapshots);
|
|
10466
|
+
if (!startInteraction("move", moveIds)) {
|
|
10467
|
+
stopHandledInteraction();
|
|
10468
|
+
return;
|
|
10469
|
+
}
|
|
10040
10470
|
dragStateRef.current = {
|
|
10041
10471
|
kind: "move",
|
|
10042
|
-
ids:
|
|
10472
|
+
ids: moveIds,
|
|
10043
10473
|
snapshots,
|
|
10044
10474
|
startWorld: { x: worldX, y: worldY }
|
|
10045
10475
|
};
|
|
@@ -10050,6 +10480,10 @@ var VectorViewport = react.forwardRef(
|
|
|
10050
10480
|
}
|
|
10051
10481
|
}
|
|
10052
10482
|
}
|
|
10483
|
+
if (!startInteraction("marquee")) {
|
|
10484
|
+
stopHandledInteraction();
|
|
10485
|
+
return;
|
|
10486
|
+
}
|
|
10053
10487
|
dragStateRef.current = {
|
|
10054
10488
|
kind: "marquee",
|
|
10055
10489
|
startWorld: { x: worldX, y: worldY },
|
|
@@ -10078,6 +10512,10 @@ var VectorViewport = react.forwardRef(
|
|
|
10078
10512
|
);
|
|
10079
10513
|
const straightLine = tool === "draw" ? createStraightStrokeState(startPoint, e.clientX, e.clientY) : void 0;
|
|
10080
10514
|
const directPenStroke = e.pointerType === "pen" && (tool === "draw" || tool === "marker");
|
|
10515
|
+
if (!startInteraction("stroke")) {
|
|
10516
|
+
stopHandledInteraction();
|
|
10517
|
+
return;
|
|
10518
|
+
}
|
|
10081
10519
|
let itemId;
|
|
10082
10520
|
if (directPenStroke) {
|
|
10083
10521
|
itemId = createShapeId();
|
|
@@ -10121,6 +10559,10 @@ var VectorViewport = react.forwardRef(
|
|
|
10121
10559
|
return;
|
|
10122
10560
|
}
|
|
10123
10561
|
if (tool === "text" || tool === "image") {
|
|
10562
|
+
if (!startInteraction("tap")) {
|
|
10563
|
+
stopHandledInteraction();
|
|
10564
|
+
return;
|
|
10565
|
+
}
|
|
10124
10566
|
dragStateRef.current = {
|
|
10125
10567
|
kind: "tap",
|
|
10126
10568
|
tool,
|
|
@@ -10134,6 +10576,10 @@ var VectorViewport = react.forwardRef(
|
|
|
10134
10576
|
}
|
|
10135
10577
|
const cp = customPlacementRef.current;
|
|
10136
10578
|
if (tool === "rect" || tool === "ellipse" || tool === "architectural-cloud" || tool === "line" || tool === "arrow" || cp && tool === cp.toolId) {
|
|
10579
|
+
if (!startInteraction("place")) {
|
|
10580
|
+
stopHandledInteraction();
|
|
10581
|
+
return;
|
|
10582
|
+
}
|
|
10137
10583
|
dragStateRef.current = {
|
|
10138
10584
|
kind: "place",
|
|
10139
10585
|
tool,
|
|
@@ -10151,8 +10597,10 @@ var VectorViewport = react.forwardRef(
|
|
|
10151
10597
|
captureInteractionPointer,
|
|
10152
10598
|
emitRemoteStrokePreview,
|
|
10153
10599
|
finalizeStrokeDragState,
|
|
10600
|
+
finishCanvuInteraction,
|
|
10154
10601
|
renderSceneWithLivePenStroke,
|
|
10155
10602
|
screenToWorld,
|
|
10603
|
+
startCanvuInteraction,
|
|
10156
10604
|
startOrRestartStraightStrokeHoldTimer
|
|
10157
10605
|
]
|
|
10158
10606
|
);
|
|
@@ -10181,14 +10629,32 @@ var VectorViewport = react.forwardRef(
|
|
|
10181
10629
|
e.stopImmediatePropagation();
|
|
10182
10630
|
return;
|
|
10183
10631
|
}
|
|
10184
|
-
wrapperRef.current?.focus({ preventScroll: true });
|
|
10185
|
-
setContextMenu(null);
|
|
10186
10632
|
const startPoint = pointerSampleToWorldPoint(
|
|
10187
10633
|
screenToWorld,
|
|
10188
10634
|
e.clientX,
|
|
10189
10635
|
e.clientY,
|
|
10190
10636
|
e.pressure
|
|
10191
10637
|
);
|
|
10638
|
+
if (!startCanvuInteraction({
|
|
10639
|
+
kind: "stroke",
|
|
10640
|
+
toolId: tool,
|
|
10641
|
+
pointerType: e.pointerType,
|
|
10642
|
+
button: e.button,
|
|
10643
|
+
worldX: startPoint.x,
|
|
10644
|
+
worldY: startPoint.y,
|
|
10645
|
+
clientX: e.clientX,
|
|
10646
|
+
clientY: e.clientY,
|
|
10647
|
+
shiftKey: e.shiftKey,
|
|
10648
|
+
altKey: e.altKey,
|
|
10649
|
+
metaKey: e.metaKey,
|
|
10650
|
+
ctrlKey: e.ctrlKey
|
|
10651
|
+
})) {
|
|
10652
|
+
e.preventDefault();
|
|
10653
|
+
e.stopImmediatePropagation();
|
|
10654
|
+
return;
|
|
10655
|
+
}
|
|
10656
|
+
wrapperRef.current?.focus({ preventScroll: true });
|
|
10657
|
+
setContextMenu(null);
|
|
10192
10658
|
const straightLine = tool === "draw" ? createStraightStrokeState(startPoint, e.clientX, e.clientY) : void 0;
|
|
10193
10659
|
const itemId = createShapeId();
|
|
10194
10660
|
const item = createFreehandStrokeItem(
|
|
@@ -10236,6 +10702,7 @@ var VectorViewport = react.forwardRef(
|
|
|
10236
10702
|
interactive,
|
|
10237
10703
|
renderSceneWithLivePenStroke,
|
|
10238
10704
|
screenToWorld,
|
|
10705
|
+
startCanvuInteraction,
|
|
10239
10706
|
startOrRestartStraightStrokeHoldTimer
|
|
10240
10707
|
]);
|
|
10241
10708
|
react.useEffect(() => {
|
|
@@ -10286,15 +10753,32 @@ var VectorViewport = react.forwardRef(
|
|
|
10286
10753
|
stopTouchEvent(ev);
|
|
10287
10754
|
return;
|
|
10288
10755
|
}
|
|
10289
|
-
wrapperRef.current?.focus({ preventScroll: true });
|
|
10290
|
-
setContextMenu(null);
|
|
10291
|
-
penDetectedRef.current = true;
|
|
10292
10756
|
const startPoint = pointerSampleToWorldPoint(
|
|
10293
10757
|
screenToWorld,
|
|
10294
10758
|
touch.clientX,
|
|
10295
10759
|
touch.clientY,
|
|
10296
10760
|
touchPressure(touch)
|
|
10297
10761
|
);
|
|
10762
|
+
if (!startCanvuInteraction({
|
|
10763
|
+
kind: "stroke",
|
|
10764
|
+
toolId: tool,
|
|
10765
|
+
pointerType: "pen",
|
|
10766
|
+
button: 0,
|
|
10767
|
+
worldX: startPoint.x,
|
|
10768
|
+
worldY: startPoint.y,
|
|
10769
|
+
clientX: touch.clientX,
|
|
10770
|
+
clientY: touch.clientY,
|
|
10771
|
+
shiftKey: ev.shiftKey,
|
|
10772
|
+
altKey: ev.altKey,
|
|
10773
|
+
metaKey: ev.metaKey,
|
|
10774
|
+
ctrlKey: ev.ctrlKey
|
|
10775
|
+
})) {
|
|
10776
|
+
stopTouchEvent(ev);
|
|
10777
|
+
return;
|
|
10778
|
+
}
|
|
10779
|
+
wrapperRef.current?.focus({ preventScroll: true });
|
|
10780
|
+
setContextMenu(null);
|
|
10781
|
+
penDetectedRef.current = true;
|
|
10298
10782
|
const straightLine = tool === "draw" ? createStraightStrokeState(startPoint, touch.clientX, touch.clientY) : void 0;
|
|
10299
10783
|
const itemId = createShapeId();
|
|
10300
10784
|
const item = createFreehandStrokeItem(
|
|
@@ -10340,6 +10824,12 @@ var VectorViewport = react.forwardRef(
|
|
|
10340
10824
|
touch.clientY,
|
|
10341
10825
|
touchPressure(touch)
|
|
10342
10826
|
);
|
|
10827
|
+
updateCanvuInteractionCurrent({
|
|
10828
|
+
worldX: endpoint.x,
|
|
10829
|
+
worldY: endpoint.y,
|
|
10830
|
+
clientX: touch.clientX,
|
|
10831
|
+
clientY: touch.clientY
|
|
10832
|
+
});
|
|
10343
10833
|
if (updateStraightStrokeForMove(st, touch.clientX, touch.clientY, endpoint)) {
|
|
10344
10834
|
debugApplePencilPointer("touchmove-stroke", {
|
|
10345
10835
|
touchId: touch.identifier,
|
|
@@ -10381,16 +10871,42 @@ var VectorViewport = react.forwardRef(
|
|
|
10381
10871
|
if (st.kind !== "stroke") return;
|
|
10382
10872
|
const touch = findChangedTouch(ev.changedTouches);
|
|
10383
10873
|
if (!touch) return;
|
|
10874
|
+
const currentPoint = pointerSampleToWorldPoint(
|
|
10875
|
+
screenToWorld,
|
|
10876
|
+
touch.clientX,
|
|
10877
|
+
touch.clientY,
|
|
10878
|
+
touchPressure(touch)
|
|
10879
|
+
);
|
|
10880
|
+
updateCanvuInteractionCurrent({
|
|
10881
|
+
worldX: currentPoint.x,
|
|
10882
|
+
worldY: currentPoint.y,
|
|
10883
|
+
clientX: touch.clientX,
|
|
10884
|
+
clientY: touch.clientY
|
|
10885
|
+
});
|
|
10886
|
+
if (ev.type === "touchcancel") {
|
|
10887
|
+
clearStraightStrokeHoldTimer(st);
|
|
10888
|
+
dragStateRef.current = { kind: "idle" };
|
|
10889
|
+
releaseInteractionPointer();
|
|
10890
|
+
if (st.itemId) {
|
|
10891
|
+
renderSceneWithLivePenStroke(null);
|
|
10892
|
+
}
|
|
10893
|
+
emitRemoteStrokePreviewClear();
|
|
10894
|
+
setPlacementPreview(null);
|
|
10895
|
+
finishCanvuInteraction("cancelled", {
|
|
10896
|
+
current: {
|
|
10897
|
+
worldX: currentPoint.x,
|
|
10898
|
+
worldY: currentPoint.y,
|
|
10899
|
+
clientX: touch.clientX,
|
|
10900
|
+
clientY: touch.clientY
|
|
10901
|
+
}
|
|
10902
|
+
});
|
|
10903
|
+
stopTouchEvent(ev);
|
|
10904
|
+
return;
|
|
10905
|
+
}
|
|
10384
10906
|
const cam = cameraRef.current;
|
|
10385
10907
|
if (cam) {
|
|
10386
10908
|
if (st.straightLine?.active) {
|
|
10387
|
-
|
|
10388
|
-
screenToWorld,
|
|
10389
|
-
touch.clientX,
|
|
10390
|
-
touch.clientY,
|
|
10391
|
-
touchPressure(touch)
|
|
10392
|
-
);
|
|
10393
|
-
setStraightStrokeEndpoint(st, endpoint);
|
|
10909
|
+
setStraightStrokeEndpoint(st, currentPoint);
|
|
10394
10910
|
} else {
|
|
10395
10911
|
const completedPoints = appendTouchToStrokePoints(
|
|
10396
10912
|
st.points,
|
|
@@ -10441,12 +10957,17 @@ var VectorViewport = react.forwardRef(
|
|
|
10441
10957
|
}, [
|
|
10442
10958
|
applePencilNav,
|
|
10443
10959
|
emitRemoteStrokePreview,
|
|
10960
|
+
emitRemoteStrokePreviewClear,
|
|
10444
10961
|
finalizeStrokeDragState,
|
|
10962
|
+
finishCanvuInteraction,
|
|
10445
10963
|
interactive,
|
|
10964
|
+
releaseInteractionPointer,
|
|
10446
10965
|
renderSceneWithLivePenStroke,
|
|
10447
10966
|
screenToWorld,
|
|
10448
10967
|
setStraightStrokeEndpoint,
|
|
10968
|
+
startCanvuInteraction,
|
|
10449
10969
|
startOrRestartStraightStrokeHoldTimer,
|
|
10970
|
+
updateCanvuInteractionCurrent,
|
|
10450
10971
|
updateStraightStrokeForMove
|
|
10451
10972
|
]);
|
|
10452
10973
|
react.useEffect(() => {
|
|
@@ -10459,6 +10980,12 @@ var VectorViewport = react.forwardRef(
|
|
|
10459
10980
|
if (st.kind === "tap") return;
|
|
10460
10981
|
if (st.kind === "marquee") {
|
|
10461
10982
|
const { worldX: worldX2, worldY: worldY2 } = screenToWorld(ev.clientX, ev.clientY);
|
|
10983
|
+
updateCanvuInteractionCurrent({
|
|
10984
|
+
worldX: worldX2,
|
|
10985
|
+
worldY: worldY2,
|
|
10986
|
+
clientX: ev.clientX,
|
|
10987
|
+
clientY: ev.clientY
|
|
10988
|
+
});
|
|
10462
10989
|
const raw = rectFromCorners(st.startWorld, { x: worldX2, y: worldY2 });
|
|
10463
10990
|
setPlacementPreview({ kind: "marquee", rect: raw });
|
|
10464
10991
|
const nextCand = collectItemIdsInRect(
|
|
@@ -10486,6 +11013,12 @@ var VectorViewport = react.forwardRef(
|
|
|
10486
11013
|
ev.clientY,
|
|
10487
11014
|
ev.pointerType === "pen" ? ev.pressure : void 0
|
|
10488
11015
|
);
|
|
11016
|
+
updateCanvuInteractionCurrent({
|
|
11017
|
+
worldX: endpoint.x,
|
|
11018
|
+
worldY: endpoint.y,
|
|
11019
|
+
clientX: ev.clientX,
|
|
11020
|
+
clientY: ev.clientY
|
|
11021
|
+
});
|
|
10489
11022
|
if (updateStraightStrokeForMove(st, ev.clientX, ev.clientY, endpoint)) {
|
|
10490
11023
|
return;
|
|
10491
11024
|
}
|
|
@@ -10534,6 +11067,12 @@ var VectorViewport = react.forwardRef(
|
|
|
10534
11067
|
}
|
|
10535
11068
|
if (st.kind === "erase") {
|
|
10536
11069
|
const { worldX: worldX2, worldY: worldY2 } = screenToWorld(ev.clientX, ev.clientY);
|
|
11070
|
+
updateCanvuInteractionCurrent({
|
|
11071
|
+
worldX: worldX2,
|
|
11072
|
+
worldY: worldY2,
|
|
11073
|
+
clientX: ev.clientX,
|
|
11074
|
+
clientY: ev.clientY
|
|
11075
|
+
});
|
|
10537
11076
|
const lineHitWorld = 10 / cam.zoom;
|
|
10538
11077
|
setEraserTrail(
|
|
10539
11078
|
(prev) => pruneEraserTrail([...prev, { x: worldX2, y: worldY2, t: Date.now() }])
|
|
@@ -10559,6 +11098,12 @@ var VectorViewport = react.forwardRef(
|
|
|
10559
11098
|
const change = onItemsChangeRef.current;
|
|
10560
11099
|
if (!change) return;
|
|
10561
11100
|
const { worldX, worldY } = screenToWorld(ev.clientX, ev.clientY);
|
|
11101
|
+
updateCanvuInteractionCurrent({
|
|
11102
|
+
worldX,
|
|
11103
|
+
worldY,
|
|
11104
|
+
clientX: ev.clientX,
|
|
11105
|
+
clientY: ev.clientY
|
|
11106
|
+
});
|
|
10562
11107
|
if (st.kind === "select-mode-item-click") {
|
|
10563
11108
|
const screenDx = ev.clientX - st.startScreen.x;
|
|
10564
11109
|
const screenDy = ev.clientY - st.startScreen.y;
|
|
@@ -10691,48 +11236,69 @@ var VectorViewport = react.forwardRef(
|
|
|
10691
11236
|
setPlacementPreview(null);
|
|
10692
11237
|
marqueeCandidateIdsRef.current = [];
|
|
10693
11238
|
setMarqueeCandidateIds([]);
|
|
11239
|
+
finishCanvuInteraction("cancelled");
|
|
10694
11240
|
return;
|
|
10695
11241
|
}
|
|
11242
|
+
const finishOutcome = ev.type === "pointercancel" ? "cancelled" : "completed";
|
|
11243
|
+
const currentWorld = screenToWorld(ev.clientX, ev.clientY);
|
|
11244
|
+
const currentInteractionPoint = {
|
|
11245
|
+
worldX: currentWorld.worldX,
|
|
11246
|
+
worldY: currentWorld.worldY,
|
|
11247
|
+
clientX: ev.clientX,
|
|
11248
|
+
clientY: ev.clientY
|
|
11249
|
+
};
|
|
11250
|
+
updateCanvuInteractionCurrent(currentInteractionPoint);
|
|
10696
11251
|
if (st.kind === "move" || st.kind === "resize" || st.kind === "rotate") {
|
|
11252
|
+
const info = st.kind === "move" ? { motive: "move", itemIds: [...st.ids] } : st.kind === "resize" ? { motive: "resize", itemIds: [st.id] } : { motive: "rotate", itemIds: [st.id] };
|
|
10697
11253
|
dragStateRef.current = { kind: "idle" };
|
|
10698
11254
|
releaseInteractionPointer();
|
|
11255
|
+
finishCanvuInteraction(finishOutcome, {
|
|
11256
|
+
current: currentInteractionPoint,
|
|
11257
|
+
...finishOutcome === "completed" ? { info } : {}
|
|
11258
|
+
});
|
|
10699
11259
|
return;
|
|
10700
11260
|
}
|
|
10701
11261
|
if (st.kind === "select-mode-item-click") {
|
|
10702
11262
|
dragStateRef.current = { kind: "idle" };
|
|
10703
11263
|
releaseInteractionPointer();
|
|
10704
|
-
if (
|
|
11264
|
+
if (finishOutcome === "cancelled") {
|
|
11265
|
+
finishCanvuInteraction("cancelled", {
|
|
11266
|
+
current: currentInteractionPoint
|
|
11267
|
+
});
|
|
11268
|
+
return;
|
|
11269
|
+
}
|
|
10705
11270
|
const dx = ev.clientX - st.startScreen.x;
|
|
10706
11271
|
const dy = ev.clientY - st.startScreen.y;
|
|
10707
|
-
if (Math.hypot(dx, dy) > TAP_PX)
|
|
11272
|
+
if (Math.hypot(dx, dy) > TAP_PX) {
|
|
11273
|
+
finishCanvuInteraction("cancelled", {
|
|
11274
|
+
current: currentInteractionPoint
|
|
11275
|
+
});
|
|
11276
|
+
return;
|
|
11277
|
+
}
|
|
10708
11278
|
const item = itemsRef.current.find((candidate) => candidate.id === st.id) ?? resolvedItemsRef.current.find((candidate) => candidate.id === st.id);
|
|
10709
|
-
if (!item)
|
|
10710
|
-
|
|
11279
|
+
if (!item) {
|
|
11280
|
+
finishCanvuInteraction("cancelled", {
|
|
11281
|
+
current: currentInteractionPoint
|
|
11282
|
+
});
|
|
11283
|
+
return;
|
|
11284
|
+
}
|
|
11285
|
+
const placement = findReadOnlyItemClickPlacement(
|
|
10711
11286
|
item,
|
|
10712
11287
|
allCustomPlacementsRef.current
|
|
10713
11288
|
);
|
|
10714
11289
|
const onSelectModeItemClick = placement?.onSelectModeItemClick;
|
|
10715
|
-
if (!onSelectModeItemClick)
|
|
10716
|
-
|
|
10717
|
-
|
|
10718
|
-
|
|
10719
|
-
|
|
10720
|
-
|
|
10721
|
-
|
|
10722
|
-
|
|
10723
|
-
|
|
10724
|
-
|
|
10725
|
-
|
|
10726
|
-
|
|
10727
|
-
ctrlKey: ev.ctrlKey,
|
|
10728
|
-
items: itemsRef.current,
|
|
10729
|
-
updateItem: (next) => {
|
|
10730
|
-
onItemsChangeRef.current?.(
|
|
10731
|
-
replaceItem(itemsRef.current, item.id, next),
|
|
10732
|
-
{ motive: "custom", itemIds: [item.id] }
|
|
10733
|
-
);
|
|
10734
|
-
},
|
|
10735
|
-
setSelectedIds: (ids) => setEffectiveSelectedIdsRef.current(ids)
|
|
11290
|
+
if (!onSelectModeItemClick) {
|
|
11291
|
+
finishCanvuInteraction("cancelled", {
|
|
11292
|
+
current: currentInteractionPoint
|
|
11293
|
+
});
|
|
11294
|
+
return;
|
|
11295
|
+
}
|
|
11296
|
+
onSelectModeItemClick(
|
|
11297
|
+
buildSelectModeItemClickDetail(item, currentWorld, ev)
|
|
11298
|
+
);
|
|
11299
|
+
finishCanvuInteraction("completed", {
|
|
11300
|
+
current: currentInteractionPoint,
|
|
11301
|
+
info: { motive: "custom", itemIds: [item.id], toolId: "select" }
|
|
10736
11302
|
});
|
|
10737
11303
|
return;
|
|
10738
11304
|
}
|
|
@@ -10742,16 +11308,25 @@ var VectorViewport = react.forwardRef(
|
|
|
10742
11308
|
setPlacementPreview(null);
|
|
10743
11309
|
marqueeCandidateIdsRef.current = [];
|
|
10744
11310
|
setMarqueeCandidateIds([]);
|
|
10745
|
-
const { worldX, worldY } =
|
|
11311
|
+
const { worldX, worldY } = currentWorld;
|
|
10746
11312
|
const raw = rectFromCorners(st.startWorld, { x: worldX, y: worldY });
|
|
10747
11313
|
const br = normalizeRect(raw);
|
|
10748
11314
|
const screenDx = ev.clientX - st.startScreen.x;
|
|
10749
11315
|
const screenDy = ev.clientY - st.startScreen.y;
|
|
11316
|
+
if (finishOutcome === "cancelled") {
|
|
11317
|
+
finishCanvuInteraction("cancelled", {
|
|
11318
|
+
current: currentInteractionPoint
|
|
11319
|
+
});
|
|
11320
|
+
return;
|
|
11321
|
+
}
|
|
10750
11322
|
const tooSmall = Math.hypot(screenDx, screenDy) < TAP_PX || br.width < MIN_MARQUEE_WORLD && br.height < MIN_MARQUEE_WORLD;
|
|
10751
11323
|
if (tooSmall) {
|
|
10752
11324
|
if (!st.shiftKey) {
|
|
10753
11325
|
setEffectiveSelectedIdsRef.current([]);
|
|
10754
11326
|
}
|
|
11327
|
+
finishCanvuInteraction("cancelled", {
|
|
11328
|
+
current: currentInteractionPoint
|
|
11329
|
+
});
|
|
10755
11330
|
return;
|
|
10756
11331
|
}
|
|
10757
11332
|
const picked = collectItemIdsInRect(resolvedItemsRef.current, br);
|
|
@@ -10768,9 +11343,26 @@ var VectorViewport = react.forwardRef(
|
|
|
10768
11343
|
} else {
|
|
10769
11344
|
setEffectiveSelectedIdsRef.current(picked);
|
|
10770
11345
|
}
|
|
11346
|
+
finishCanvuInteraction("completed", {
|
|
11347
|
+
current: currentInteractionPoint
|
|
11348
|
+
});
|
|
10771
11349
|
return;
|
|
10772
11350
|
}
|
|
10773
11351
|
if (st.kind === "stroke") {
|
|
11352
|
+
if (finishOutcome === "cancelled") {
|
|
11353
|
+
clearStraightStrokeHoldTimer(st);
|
|
11354
|
+
dragStateRef.current = { kind: "idle" };
|
|
11355
|
+
releaseInteractionPointer();
|
|
11356
|
+
if (st.itemId) {
|
|
11357
|
+
renderSceneWithLivePenStroke(null);
|
|
11358
|
+
}
|
|
11359
|
+
emitRemoteStrokePreviewClear();
|
|
11360
|
+
setPlacementPreview(null);
|
|
11361
|
+
finishCanvuInteraction("cancelled", {
|
|
11362
|
+
current: currentInteractionPoint
|
|
11363
|
+
});
|
|
11364
|
+
return;
|
|
11365
|
+
}
|
|
10774
11366
|
const completedPoints = (() => {
|
|
10775
11367
|
if (st.straightLine?.active) {
|
|
10776
11368
|
const endpoint = pointerSampleToWorldPoint(
|
|
@@ -10801,15 +11393,20 @@ var VectorViewport = react.forwardRef(
|
|
|
10801
11393
|
}
|
|
10802
11394
|
if (st.kind === "erase") {
|
|
10803
11395
|
const change = onItemsChangeRef.current;
|
|
11396
|
+
const erasedIds = [...eraserPreviewIdsRef.current];
|
|
11397
|
+
const info = erasedIds.length > 0 ? {
|
|
11398
|
+
motive: "erase",
|
|
11399
|
+
itemIds: erasedIds,
|
|
11400
|
+
toolId: "eraser"
|
|
11401
|
+
} : void 0;
|
|
10804
11402
|
if (change && eraserPreviewIdsRef.current.size > 0) {
|
|
10805
11403
|
const idSet = new Set(eraserPreviewIdsRef.current);
|
|
10806
|
-
|
|
10807
|
-
|
|
10808
|
-
|
|
10809
|
-
|
|
10810
|
-
|
|
10811
|
-
|
|
10812
|
-
);
|
|
11404
|
+
if (finishOutcome === "completed") {
|
|
11405
|
+
change(
|
|
11406
|
+
itemsRef.current.filter((i) => !idSet.has(i.id)),
|
|
11407
|
+
info
|
|
11408
|
+
);
|
|
11409
|
+
}
|
|
10813
11410
|
}
|
|
10814
11411
|
eraserPreviewIdsRef.current.clear();
|
|
10815
11412
|
setEraserPreviewIds([]);
|
|
@@ -10817,7 +11414,13 @@ var VectorViewport = react.forwardRef(
|
|
|
10817
11414
|
setEraserActive(false);
|
|
10818
11415
|
dragStateRef.current = { kind: "idle" };
|
|
10819
11416
|
releaseInteractionPointer();
|
|
10820
|
-
|
|
11417
|
+
if (finishOutcome === "completed") {
|
|
11418
|
+
requestAutoResetTool("eraser");
|
|
11419
|
+
}
|
|
11420
|
+
finishCanvuInteraction(finishOutcome, {
|
|
11421
|
+
current: currentInteractionPoint,
|
|
11422
|
+
...finishOutcome === "completed" && info ? { info } : {}
|
|
11423
|
+
});
|
|
10821
11424
|
return;
|
|
10822
11425
|
}
|
|
10823
11426
|
if (st.kind === "tap") {
|
|
@@ -10825,11 +11428,22 @@ var VectorViewport = react.forwardRef(
|
|
|
10825
11428
|
const dy = ev.clientY - st.startScreen.y;
|
|
10826
11429
|
dragStateRef.current = { kind: "idle" };
|
|
10827
11430
|
releaseInteractionPointer();
|
|
10828
|
-
if (Math.hypot(dx, dy) > TAP_PX)
|
|
11431
|
+
if (finishOutcome === "cancelled" || Math.hypot(dx, dy) > TAP_PX) {
|
|
11432
|
+
finishCanvuInteraction("cancelled", {
|
|
11433
|
+
current: currentInteractionPoint
|
|
11434
|
+
});
|
|
11435
|
+
return;
|
|
11436
|
+
}
|
|
10829
11437
|
const change = onItemsChangeRef.current;
|
|
10830
|
-
if (!change)
|
|
11438
|
+
if (!change) {
|
|
11439
|
+
finishCanvuInteraction("cancelled", {
|
|
11440
|
+
current: currentInteractionPoint
|
|
11441
|
+
});
|
|
11442
|
+
return;
|
|
11443
|
+
}
|
|
10831
11444
|
const id = createShapeId();
|
|
10832
11445
|
const { x: worldX, y: worldY } = st.startWorld;
|
|
11446
|
+
let info;
|
|
10833
11447
|
if (st.tool === "text") {
|
|
10834
11448
|
const fs = strokeStyleRef.current.textFontSize;
|
|
10835
11449
|
const baseline = textBaselineYFor(fs);
|
|
@@ -10852,11 +11466,12 @@ var VectorViewport = react.forwardRef(
|
|
|
10852
11466
|
bounds: { ...newItem.bounds }
|
|
10853
11467
|
};
|
|
10854
11468
|
const hidden = applyTextDraftWhileEditing(newItem, "");
|
|
10855
|
-
|
|
11469
|
+
info = {
|
|
10856
11470
|
motive: "text-create",
|
|
10857
11471
|
itemIds: [id],
|
|
10858
11472
|
toolId: st.tool
|
|
10859
|
-
}
|
|
11473
|
+
};
|
|
11474
|
+
change([...itemsRef.current, hidden], info);
|
|
10860
11475
|
setEffectiveSelectedIdsRef.current([id]);
|
|
10861
11476
|
setEditingTextId(id);
|
|
10862
11477
|
setDraftText("");
|
|
@@ -10865,6 +11480,10 @@ var VectorViewport = react.forwardRef(
|
|
|
10865
11480
|
imageInputRef.current?.click();
|
|
10866
11481
|
}
|
|
10867
11482
|
requestAutoResetTool(st.tool);
|
|
11483
|
+
finishCanvuInteraction("completed", {
|
|
11484
|
+
current: currentInteractionPoint,
|
|
11485
|
+
...info ? { info } : {}
|
|
11486
|
+
});
|
|
10868
11487
|
return;
|
|
10869
11488
|
}
|
|
10870
11489
|
if (st.kind === "place") {
|
|
@@ -10875,11 +11494,19 @@ var VectorViewport = react.forwardRef(
|
|
|
10875
11494
|
dragStateRef.current = { kind: "idle" };
|
|
10876
11495
|
releaseInteractionPointer();
|
|
10877
11496
|
setPlacementPreview(null);
|
|
10878
|
-
if (!change)
|
|
11497
|
+
if (finishOutcome === "cancelled" || !change) {
|
|
11498
|
+
finishCanvuInteraction("cancelled", {
|
|
11499
|
+
current: currentInteractionPoint
|
|
11500
|
+
});
|
|
11501
|
+
return;
|
|
11502
|
+
}
|
|
10879
11503
|
if (st.tool === "arrow") {
|
|
10880
11504
|
const screenDx = ev.clientX - st.startScreen.x;
|
|
10881
11505
|
const screenDy = ev.clientY - st.startScreen.y;
|
|
10882
11506
|
if (Math.hypot(screenDx, screenDy) < MIN_ARROW_DRAG_PX) {
|
|
11507
|
+
finishCanvuInteraction("cancelled", {
|
|
11508
|
+
current: currentInteractionPoint
|
|
11509
|
+
});
|
|
10883
11510
|
return;
|
|
10884
11511
|
}
|
|
10885
11512
|
const maxDist = ARROW_BIND_SNAP_PX / cam.zoom;
|
|
@@ -10911,18 +11538,23 @@ var VectorViewport = react.forwardRef(
|
|
|
10911
11538
|
...snapB ? { end: snapB.binding } : {}
|
|
10912
11539
|
};
|
|
10913
11540
|
}
|
|
11541
|
+
const info2 = {
|
|
11542
|
+
motive: "place",
|
|
11543
|
+
itemIds: [id2],
|
|
11544
|
+
toolId: st.tool
|
|
11545
|
+
};
|
|
10914
11546
|
change(
|
|
10915
11547
|
[
|
|
10916
11548
|
...itemsRef.current,
|
|
10917
11549
|
createLineItem(id2, rawArrow, line, "arrow", pen2, arrowBind)
|
|
10918
11550
|
],
|
|
10919
|
-
|
|
10920
|
-
motive: "place",
|
|
10921
|
-
itemIds: [id2],
|
|
10922
|
-
toolId: st.tool
|
|
10923
|
-
}
|
|
11551
|
+
info2
|
|
10924
11552
|
);
|
|
10925
11553
|
setEffectiveSelectedIdsRef.current([id2]);
|
|
11554
|
+
finishCanvuInteraction("completed", {
|
|
11555
|
+
current: currentInteractionPoint,
|
|
11556
|
+
info: info2
|
|
11557
|
+
});
|
|
10926
11558
|
return;
|
|
10927
11559
|
}
|
|
10928
11560
|
let raw = rectFromCorners(a, b);
|
|
@@ -10947,47 +11579,61 @@ var VectorViewport = react.forwardRef(
|
|
|
10947
11579
|
}
|
|
10948
11580
|
const id = createShapeId();
|
|
10949
11581
|
const pen = strokeStyleRef.current;
|
|
11582
|
+
let info;
|
|
10950
11583
|
if (cpUp && st.tool === cpUp.toolId) {
|
|
10951
11584
|
const item = tagCustomPlacementItem(
|
|
10952
11585
|
cpUp.createItem({ id, bounds: br }),
|
|
10953
11586
|
cpUp.toolId
|
|
10954
11587
|
);
|
|
10955
|
-
|
|
11588
|
+
info = {
|
|
10956
11589
|
motive: "place",
|
|
10957
11590
|
itemIds: [id],
|
|
10958
11591
|
toolId: st.tool
|
|
10959
|
-
}
|
|
11592
|
+
};
|
|
11593
|
+
change(itemsRef.current.concat(item), info);
|
|
10960
11594
|
if (cpUp.selectAfterCreate !== false) {
|
|
10961
11595
|
setEffectiveSelectedIdsRef.current([id]);
|
|
10962
11596
|
}
|
|
11597
|
+
finishCanvuInteraction("completed", {
|
|
11598
|
+
current: currentInteractionPoint,
|
|
11599
|
+
info
|
|
11600
|
+
});
|
|
10963
11601
|
return;
|
|
10964
11602
|
}
|
|
10965
11603
|
if (st.tool === "rect") {
|
|
10966
|
-
|
|
11604
|
+
info = {
|
|
10967
11605
|
motive: "place",
|
|
10968
11606
|
itemIds: [id],
|
|
10969
11607
|
toolId: st.tool
|
|
10970
|
-
}
|
|
11608
|
+
};
|
|
11609
|
+
change([...itemsRef.current, createRectangleItem(id, raw, pen)], info);
|
|
10971
11610
|
setEffectiveSelectedIdsRef.current([id]);
|
|
10972
11611
|
} else if (st.tool === "ellipse") {
|
|
10973
|
-
|
|
11612
|
+
info = {
|
|
10974
11613
|
motive: "place",
|
|
10975
11614
|
itemIds: [id],
|
|
10976
11615
|
toolId: st.tool
|
|
10977
|
-
}
|
|
11616
|
+
};
|
|
11617
|
+
change([...itemsRef.current, createEllipseItem(id, raw, pen)], info);
|
|
10978
11618
|
setEffectiveSelectedIdsRef.current([id]);
|
|
10979
11619
|
} else if (st.tool === "architectural-cloud") {
|
|
11620
|
+
info = {
|
|
11621
|
+
motive: "place",
|
|
11622
|
+
itemIds: [id],
|
|
11623
|
+
toolId: st.tool
|
|
11624
|
+
};
|
|
10980
11625
|
change(
|
|
10981
11626
|
[...itemsRef.current, createArchitecturalCloudItem(id, raw, pen)],
|
|
10982
|
-
|
|
10983
|
-
motive: "place",
|
|
10984
|
-
itemIds: [id],
|
|
10985
|
-
toolId: st.tool
|
|
10986
|
-
}
|
|
11627
|
+
info
|
|
10987
11628
|
);
|
|
10988
11629
|
setEffectiveSelectedIdsRef.current([id]);
|
|
10989
11630
|
} else if (st.tool === "line" || st.tool === "arrow") {
|
|
10990
11631
|
const line = lineEndpointsToLocal(raw, lineA, lineB);
|
|
11632
|
+
info = {
|
|
11633
|
+
motive: "place",
|
|
11634
|
+
itemIds: [id],
|
|
11635
|
+
toolId: st.tool
|
|
11636
|
+
};
|
|
10991
11637
|
change(
|
|
10992
11638
|
[
|
|
10993
11639
|
...itemsRef.current,
|
|
@@ -10999,15 +11645,15 @@ var VectorViewport = react.forwardRef(
|
|
|
10999
11645
|
pen
|
|
11000
11646
|
)
|
|
11001
11647
|
],
|
|
11002
|
-
|
|
11003
|
-
motive: "place",
|
|
11004
|
-
itemIds: [id],
|
|
11005
|
-
toolId: st.tool
|
|
11006
|
-
}
|
|
11648
|
+
info
|
|
11007
11649
|
);
|
|
11008
11650
|
setEffectiveSelectedIdsRef.current([id]);
|
|
11009
11651
|
}
|
|
11010
11652
|
requestAutoResetTool(st.tool);
|
|
11653
|
+
finishCanvuInteraction("completed", {
|
|
11654
|
+
current: currentInteractionPoint,
|
|
11655
|
+
...info ? { info } : {}
|
|
11656
|
+
});
|
|
11011
11657
|
}
|
|
11012
11658
|
};
|
|
11013
11659
|
document.addEventListener("pointermove", onMove);
|
|
@@ -11019,17 +11665,20 @@ var VectorViewport = react.forwardRef(
|
|
|
11019
11665
|
document.removeEventListener("pointercancel", onUp);
|
|
11020
11666
|
};
|
|
11021
11667
|
}, [
|
|
11668
|
+
buildSelectModeItemClickDetail,
|
|
11022
11669
|
emitRemoteStrokePreview,
|
|
11023
11670
|
emitRemoteStrokePreviewClear,
|
|
11024
11671
|
interactive,
|
|
11025
11672
|
pruneEraserTrail,
|
|
11026
11673
|
pruneLaserTrail,
|
|
11027
11674
|
finalizeStrokeDragState,
|
|
11675
|
+
finishCanvuInteraction,
|
|
11028
11676
|
renderSceneWithLivePenStroke,
|
|
11029
11677
|
releaseInteractionPointer,
|
|
11030
11678
|
requestAutoResetTool,
|
|
11031
11679
|
screenToWorld,
|
|
11032
11680
|
setStraightStrokeEndpoint,
|
|
11681
|
+
updateCanvuInteractionCurrent,
|
|
11033
11682
|
updateStraightStrokeForMove
|
|
11034
11683
|
]);
|
|
11035
11684
|
const selectedItemsForOverlay = react.useMemo(() => {
|