canvu-react 0.3.34 → 0.3.36
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/index.cjs +17 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +17 -10
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +264 -97
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +264 -97
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
package/dist/react.js
CHANGED
|
@@ -1818,6 +1818,67 @@ function useCanvuChromeContext() {
|
|
|
1818
1818
|
return useContext(CanvuChromeContext);
|
|
1819
1819
|
}
|
|
1820
1820
|
|
|
1821
|
+
// src/math/item-transform.ts
|
|
1822
|
+
init_rect();
|
|
1823
|
+
function getItemRotationRad(item) {
|
|
1824
|
+
return item.rotation ?? 0;
|
|
1825
|
+
}
|
|
1826
|
+
function itemLocalToWorld(lx, ly, itemX, itemY, w, h, rotationRad) {
|
|
1827
|
+
const c = { x: w / 2, y: h / 2 };
|
|
1828
|
+
const dlx = lx - c.x;
|
|
1829
|
+
const dly = ly - c.y;
|
|
1830
|
+
const cos = Math.cos(rotationRad);
|
|
1831
|
+
const sin = Math.sin(rotationRad);
|
|
1832
|
+
return {
|
|
1833
|
+
x: itemX + c.x + cos * dlx - sin * dly,
|
|
1834
|
+
y: itemY + c.y + sin * dlx + cos * dly
|
|
1835
|
+
};
|
|
1836
|
+
}
|
|
1837
|
+
function worldToItemLocal(wx, wy, itemX, itemY, w, h, rotationRad) {
|
|
1838
|
+
const c = { x: w / 2, y: h / 2 };
|
|
1839
|
+
const vx = wx - itemX;
|
|
1840
|
+
const vy = wy - itemY;
|
|
1841
|
+
const dx = vx - c.x;
|
|
1842
|
+
const dy = vy - c.y;
|
|
1843
|
+
const cos = Math.cos(-rotationRad);
|
|
1844
|
+
const sin = Math.sin(-rotationRad);
|
|
1845
|
+
const lx = cos * dx - sin * dy;
|
|
1846
|
+
const ly = sin * dx + cos * dy;
|
|
1847
|
+
return { x: c.x + lx, y: c.y + ly };
|
|
1848
|
+
}
|
|
1849
|
+
function itemPivotWorld(item) {
|
|
1850
|
+
const r = normalizeRect(item.bounds);
|
|
1851
|
+
return { x: r.x + r.width / 2, y: r.y + r.height / 2 };
|
|
1852
|
+
}
|
|
1853
|
+
function boundsAabbForRotatedItem(item) {
|
|
1854
|
+
const rot = getItemRotationRad(item);
|
|
1855
|
+
if (Math.abs(rot) < 1e-12 && item.bounds.width >= 0 && item.bounds.height >= 0) {
|
|
1856
|
+
return item.bounds;
|
|
1857
|
+
}
|
|
1858
|
+
const r = normalizeRect(item.bounds);
|
|
1859
|
+
if (Math.abs(rot) < 1e-12) {
|
|
1860
|
+
return r;
|
|
1861
|
+
}
|
|
1862
|
+
const corners = [
|
|
1863
|
+
[0, 0],
|
|
1864
|
+
[r.width, 0],
|
|
1865
|
+
[r.width, r.height],
|
|
1866
|
+
[0, r.height]
|
|
1867
|
+
];
|
|
1868
|
+
let minX = Infinity;
|
|
1869
|
+
let minY = Infinity;
|
|
1870
|
+
let maxX = -Infinity;
|
|
1871
|
+
let maxY = -Infinity;
|
|
1872
|
+
for (const [lx, ly] of corners) {
|
|
1873
|
+
const p = itemLocalToWorld(lx, ly, item.x, item.y, r.width, r.height, rot);
|
|
1874
|
+
minX = Math.min(minX, p.x);
|
|
1875
|
+
minY = Math.min(minY, p.y);
|
|
1876
|
+
maxX = Math.max(maxX, p.x);
|
|
1877
|
+
maxY = Math.max(maxY, p.y);
|
|
1878
|
+
}
|
|
1879
|
+
return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1821
1882
|
// src/scene/clone-item.ts
|
|
1822
1883
|
init_shape_builders();
|
|
1823
1884
|
function cloneVectorSceneItemWithNewId(item) {
|
|
@@ -1857,20 +1918,25 @@ function markImageAsManaged(item) {
|
|
|
1857
1918
|
};
|
|
1858
1919
|
}
|
|
1859
1920
|
function restackManagedImages(items) {
|
|
1860
|
-
let
|
|
1921
|
+
let anchorAabbY = Infinity;
|
|
1922
|
+
let anchorCenterX = 0;
|
|
1861
1923
|
for (const item of items) {
|
|
1862
1924
|
if (!isManagedImage(item)) continue;
|
|
1863
|
-
|
|
1925
|
+
const aabb = boundsAabbForRotatedItem(item);
|
|
1926
|
+
if (aabb.y < anchorAabbY) {
|
|
1927
|
+
anchorAabbY = aabb.y;
|
|
1928
|
+
anchorCenterX = aabb.x + aabb.width / 2;
|
|
1929
|
+
}
|
|
1864
1930
|
}
|
|
1865
|
-
if (!
|
|
1866
|
-
|
|
1867
|
-
const anchorTopY = anchor.bounds.y;
|
|
1868
|
-
let cursorY = anchorTopY;
|
|
1931
|
+
if (!Number.isFinite(anchorAabbY)) return [...items];
|
|
1932
|
+
let cursorY = anchorAabbY;
|
|
1869
1933
|
return items.map((item) => {
|
|
1870
1934
|
if (!isManagedImage(item)) return item;
|
|
1935
|
+
const aabb = boundsAabbForRotatedItem(item);
|
|
1936
|
+
const centerY = cursorY + aabb.height / 2;
|
|
1871
1937
|
const newX = anchorCenterX - item.bounds.width / 2;
|
|
1872
|
-
const newY =
|
|
1873
|
-
cursorY
|
|
1938
|
+
const newY = centerY - item.bounds.height / 2;
|
|
1939
|
+
cursorY += aabb.height + STACK_GAP_WORLD;
|
|
1874
1940
|
if (item.bounds.x === newX && item.bounds.y === newY) return item;
|
|
1875
1941
|
return {
|
|
1876
1942
|
...item,
|
|
@@ -1890,8 +1956,10 @@ function copyManagedImage(items, id) {
|
|
|
1890
1956
|
return restackManagedImages(inserted);
|
|
1891
1957
|
}
|
|
1892
1958
|
function rotateManagedImage(items, id) {
|
|
1893
|
-
return
|
|
1894
|
-
|
|
1959
|
+
return restackManagedImages(
|
|
1960
|
+
items.map(
|
|
1961
|
+
(i) => i.id === id ? { ...i, rotation: ((i.rotation ?? 0) + Math.PI / 2) % (Math.PI * 2) } : i
|
|
1962
|
+
)
|
|
1895
1963
|
);
|
|
1896
1964
|
}
|
|
1897
1965
|
function deleteManagedImage(items, id) {
|
|
@@ -2338,69 +2406,6 @@ function getBoardPositionStyle(position, inset = 12, zIndex = 40) {
|
|
|
2338
2406
|
return base2;
|
|
2339
2407
|
}
|
|
2340
2408
|
}
|
|
2341
|
-
|
|
2342
|
-
// src/math/item-transform.ts
|
|
2343
|
-
init_rect();
|
|
2344
|
-
function getItemRotationRad(item) {
|
|
2345
|
-
return item.rotation ?? 0;
|
|
2346
|
-
}
|
|
2347
|
-
function itemLocalToWorld(lx, ly, itemX, itemY, w, h, rotationRad) {
|
|
2348
|
-
const c = { x: w / 2, y: h / 2 };
|
|
2349
|
-
const dlx = lx - c.x;
|
|
2350
|
-
const dly = ly - c.y;
|
|
2351
|
-
const cos = Math.cos(rotationRad);
|
|
2352
|
-
const sin = Math.sin(rotationRad);
|
|
2353
|
-
return {
|
|
2354
|
-
x: itemX + c.x + cos * dlx - sin * dly,
|
|
2355
|
-
y: itemY + c.y + sin * dlx + cos * dly
|
|
2356
|
-
};
|
|
2357
|
-
}
|
|
2358
|
-
function worldToItemLocal(wx, wy, itemX, itemY, w, h, rotationRad) {
|
|
2359
|
-
const c = { x: w / 2, y: h / 2 };
|
|
2360
|
-
const vx = wx - itemX;
|
|
2361
|
-
const vy = wy - itemY;
|
|
2362
|
-
const dx = vx - c.x;
|
|
2363
|
-
const dy = vy - c.y;
|
|
2364
|
-
const cos = Math.cos(-rotationRad);
|
|
2365
|
-
const sin = Math.sin(-rotationRad);
|
|
2366
|
-
const lx = cos * dx - sin * dy;
|
|
2367
|
-
const ly = sin * dx + cos * dy;
|
|
2368
|
-
return { x: c.x + lx, y: c.y + ly };
|
|
2369
|
-
}
|
|
2370
|
-
function itemPivotWorld(item) {
|
|
2371
|
-
const r = normalizeRect(item.bounds);
|
|
2372
|
-
return { x: r.x + r.width / 2, y: r.y + r.height / 2 };
|
|
2373
|
-
}
|
|
2374
|
-
function boundsAabbForRotatedItem(item) {
|
|
2375
|
-
const rot = getItemRotationRad(item);
|
|
2376
|
-
if (Math.abs(rot) < 1e-12 && item.bounds.width >= 0 && item.bounds.height >= 0) {
|
|
2377
|
-
return item.bounds;
|
|
2378
|
-
}
|
|
2379
|
-
const r = normalizeRect(item.bounds);
|
|
2380
|
-
if (Math.abs(rot) < 1e-12) {
|
|
2381
|
-
return r;
|
|
2382
|
-
}
|
|
2383
|
-
const corners = [
|
|
2384
|
-
[0, 0],
|
|
2385
|
-
[r.width, 0],
|
|
2386
|
-
[r.width, r.height],
|
|
2387
|
-
[0, r.height]
|
|
2388
|
-
];
|
|
2389
|
-
let minX = Infinity;
|
|
2390
|
-
let minY = Infinity;
|
|
2391
|
-
let maxX = -Infinity;
|
|
2392
|
-
let maxY = -Infinity;
|
|
2393
|
-
for (const [lx, ly] of corners) {
|
|
2394
|
-
const p = itemLocalToWorld(lx, ly, item.x, item.y, r.width, r.height, rot);
|
|
2395
|
-
minX = Math.min(minX, p.x);
|
|
2396
|
-
minY = Math.min(minY, p.y);
|
|
2397
|
-
maxX = Math.max(maxX, p.x);
|
|
2398
|
-
maxY = Math.max(maxY, p.y);
|
|
2399
|
-
}
|
|
2400
|
-
return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
|
|
2401
|
-
}
|
|
2402
|
-
|
|
2403
|
-
// src/react/navmenu/minimap.tsx
|
|
2404
2409
|
init_rect();
|
|
2405
2410
|
var NavMenuMinimapSlotContext = createContext(null);
|
|
2406
2411
|
function noop() {
|
|
@@ -7275,6 +7280,8 @@ body[data-canvu-pen-active="true"] [data-slot="shape-context-menu"] * {
|
|
|
7275
7280
|
-webkit-touch-callout: none !important;
|
|
7276
7281
|
}
|
|
7277
7282
|
`;
|
|
7283
|
+
var STRAIGHT_STROKE_HOLD_DURATION_MS = 1e3;
|
|
7284
|
+
var STRAIGHT_STROKE_JITTER_TOLERANCE_SQUARED = 5 * 5;
|
|
7278
7285
|
function debugApplePencilPointer(phase, detail) {
|
|
7279
7286
|
return;
|
|
7280
7287
|
}
|
|
@@ -7422,6 +7429,28 @@ function appendTouchToStrokePoints(points, touch, zoom, screenToWorldFn) {
|
|
|
7422
7429
|
);
|
|
7423
7430
|
return appendInterpolatedPoints(points, nextPoint);
|
|
7424
7431
|
}
|
|
7432
|
+
function createStraightStrokeState(anchorPoint, clientX, clientY) {
|
|
7433
|
+
return {
|
|
7434
|
+
active: false,
|
|
7435
|
+
anchorPoint,
|
|
7436
|
+
holdScreen: { x: clientX, y: clientY },
|
|
7437
|
+
holdTimer: null
|
|
7438
|
+
};
|
|
7439
|
+
}
|
|
7440
|
+
function clearStraightStrokeHoldTimer(strokeState) {
|
|
7441
|
+
const straightLine = strokeState.straightLine;
|
|
7442
|
+
if (!straightLine?.holdTimer) return;
|
|
7443
|
+
clearTimeout(straightLine.holdTimer);
|
|
7444
|
+
straightLine.holdTimer = null;
|
|
7445
|
+
}
|
|
7446
|
+
function lastStrokePoint(points) {
|
|
7447
|
+
return points[points.length - 1] ?? null;
|
|
7448
|
+
}
|
|
7449
|
+
function hasMovedPastStraightStrokeJitter(straightLine, clientX, clientY) {
|
|
7450
|
+
const deltaX = clientX - straightLine.holdScreen.x;
|
|
7451
|
+
const deltaY = clientY - straightLine.holdScreen.y;
|
|
7452
|
+
return deltaX * deltaX + deltaY * deltaY > STRAIGHT_STROKE_JITTER_TOLERANCE_SQUARED;
|
|
7453
|
+
}
|
|
7425
7454
|
var VectorViewport = forwardRef(
|
|
7426
7455
|
function VectorViewport2({
|
|
7427
7456
|
items,
|
|
@@ -7956,6 +7985,76 @@ var VectorViewport = forwardRef(
|
|
|
7956
7985
|
},
|
|
7957
7986
|
[]
|
|
7958
7987
|
);
|
|
7988
|
+
const updateStrokePreviewPoints = useCallback(
|
|
7989
|
+
(strokeState, points) => {
|
|
7990
|
+
strokeState.points = points;
|
|
7991
|
+
if (strokeState.itemId && strokeState.tool !== "laser") {
|
|
7992
|
+
const item = createFreehandStrokeItem(
|
|
7993
|
+
strokeState.itemId,
|
|
7994
|
+
points,
|
|
7995
|
+
strokeState.tool,
|
|
7996
|
+
strokeStyleRef.current
|
|
7997
|
+
);
|
|
7998
|
+
if (item) {
|
|
7999
|
+
renderSceneWithLivePenStroke(item);
|
|
8000
|
+
}
|
|
8001
|
+
setPlacementPreview(null);
|
|
8002
|
+
emitRemoteStrokePreview(strokeState.tool, points);
|
|
8003
|
+
return;
|
|
8004
|
+
}
|
|
8005
|
+
if (strokeState.tool === "laser") return;
|
|
8006
|
+
setPlacementPreview({
|
|
8007
|
+
kind: "stroke",
|
|
8008
|
+
tool: strokeState.tool,
|
|
8009
|
+
points,
|
|
8010
|
+
style: { ...strokeStyleRef.current }
|
|
8011
|
+
});
|
|
8012
|
+
},
|
|
8013
|
+
[emitRemoteStrokePreview, renderSceneWithLivePenStroke]
|
|
8014
|
+
);
|
|
8015
|
+
const setStraightStrokeEndpoint = useCallback(
|
|
8016
|
+
(strokeState, endpoint) => {
|
|
8017
|
+
const straightLine = strokeState.straightLine;
|
|
8018
|
+
if (!straightLine) return;
|
|
8019
|
+
straightLine.active = true;
|
|
8020
|
+
updateStrokePreviewPoints(strokeState, [straightLine.anchorPoint, endpoint]);
|
|
8021
|
+
},
|
|
8022
|
+
[updateStrokePreviewPoints]
|
|
8023
|
+
);
|
|
8024
|
+
const startOrRestartStraightStrokeHoldTimer = useCallback(
|
|
8025
|
+
(strokeState) => {
|
|
8026
|
+
const straightLine = strokeState.straightLine;
|
|
8027
|
+
if (!straightLine || strokeState.tool !== "draw") return;
|
|
8028
|
+
clearStraightStrokeHoldTimer(strokeState);
|
|
8029
|
+
straightLine.holdTimer = window.setTimeout(() => {
|
|
8030
|
+
straightLine.holdTimer = null;
|
|
8031
|
+
const currentStrokeState = dragStateRef.current;
|
|
8032
|
+
if (currentStrokeState.kind !== "stroke" || currentStrokeState !== strokeState) {
|
|
8033
|
+
return;
|
|
8034
|
+
}
|
|
8035
|
+
const endpoint = lastStrokePoint(currentStrokeState.points);
|
|
8036
|
+
if (!endpoint) return;
|
|
8037
|
+
setStraightStrokeEndpoint(currentStrokeState, endpoint);
|
|
8038
|
+
}, STRAIGHT_STROKE_HOLD_DURATION_MS);
|
|
8039
|
+
},
|
|
8040
|
+
[setStraightStrokeEndpoint]
|
|
8041
|
+
);
|
|
8042
|
+
const updateStraightStrokeForMove = useCallback(
|
|
8043
|
+
(strokeState, clientX, clientY, endpoint) => {
|
|
8044
|
+
const straightLine = strokeState.straightLine;
|
|
8045
|
+
if (!straightLine || strokeState.tool !== "draw") return false;
|
|
8046
|
+
if (straightLine.active) {
|
|
8047
|
+
setStraightStrokeEndpoint(strokeState, endpoint);
|
|
8048
|
+
return true;
|
|
8049
|
+
}
|
|
8050
|
+
if (straightLine.holdTimer && hasMovedPastStraightStrokeJitter(straightLine, clientX, clientY)) {
|
|
8051
|
+
straightLine.holdScreen = { x: clientX, y: clientY };
|
|
8052
|
+
startOrRestartStraightStrokeHoldTimer(strokeState);
|
|
8053
|
+
}
|
|
8054
|
+
return false;
|
|
8055
|
+
},
|
|
8056
|
+
[setStraightStrokeEndpoint, startOrRestartStraightStrokeHoldTimer]
|
|
8057
|
+
);
|
|
7959
8058
|
const finalizeStrokeDragState = useCallback(
|
|
7960
8059
|
(strokeState) => {
|
|
7961
8060
|
const tool = strokeState.tool;
|
|
@@ -7966,6 +8065,7 @@ var VectorViewport = forwardRef(
|
|
|
7966
8065
|
debugApplePencilPointer("finalize-stroke", {
|
|
7967
8066
|
points: pts.length
|
|
7968
8067
|
});
|
|
8068
|
+
clearStraightStrokeHoldTimer(strokeState);
|
|
7969
8069
|
dragStateRef.current = { kind: "idle" };
|
|
7970
8070
|
releaseInteractionPointer();
|
|
7971
8071
|
if (itemId) {
|
|
@@ -9077,6 +9177,7 @@ var VectorViewport = forwardRef(
|
|
|
9077
9177
|
e.clientY,
|
|
9078
9178
|
e.pointerType === "pen" ? e.pressure : void 0
|
|
9079
9179
|
);
|
|
9180
|
+
const straightLine = tool === "draw" ? createStraightStrokeState(startPoint, e.clientX, e.clientY) : void 0;
|
|
9080
9181
|
const directPenStroke = e.pointerType === "pen" && (tool === "draw" || tool === "marker");
|
|
9081
9182
|
let itemId;
|
|
9082
9183
|
if (directPenStroke) {
|
|
@@ -9091,13 +9192,16 @@ var VectorViewport = forwardRef(
|
|
|
9091
9192
|
renderSceneWithLivePenStroke(item);
|
|
9092
9193
|
}
|
|
9093
9194
|
}
|
|
9094
|
-
|
|
9195
|
+
const nextDragState = {
|
|
9095
9196
|
kind: "stroke",
|
|
9096
9197
|
tool,
|
|
9097
9198
|
points: [startPoint],
|
|
9098
9199
|
pointerType: e.pointerType,
|
|
9099
|
-
...itemId ? { itemId } : {}
|
|
9200
|
+
...itemId ? { itemId } : {},
|
|
9201
|
+
...straightLine ? { straightLine } : {}
|
|
9100
9202
|
};
|
|
9203
|
+
dragStateRef.current = nextDragState;
|
|
9204
|
+
startOrRestartStraightStrokeHoldTimer(nextDragState);
|
|
9101
9205
|
if (tool === "laser") {
|
|
9102
9206
|
setLaserTrail([{ x: worldX, y: worldY, t: Date.now() }]);
|
|
9103
9207
|
setPlacementPreview(null);
|
|
@@ -9149,7 +9253,8 @@ var VectorViewport = forwardRef(
|
|
|
9149
9253
|
emitRemoteStrokePreview,
|
|
9150
9254
|
finalizeStrokeDragState,
|
|
9151
9255
|
renderSceneWithLivePenStroke,
|
|
9152
|
-
screenToWorld
|
|
9256
|
+
screenToWorld,
|
|
9257
|
+
startOrRestartStraightStrokeHoldTimer
|
|
9153
9258
|
]
|
|
9154
9259
|
);
|
|
9155
9260
|
useEffect(() => {
|
|
@@ -9185,6 +9290,7 @@ var VectorViewport = forwardRef(
|
|
|
9185
9290
|
e.clientY,
|
|
9186
9291
|
e.pressure
|
|
9187
9292
|
);
|
|
9293
|
+
const straightLine = tool === "draw" ? createStraightStrokeState(startPoint, e.clientX, e.clientY) : void 0;
|
|
9188
9294
|
const itemId = createShapeId();
|
|
9189
9295
|
const item = createFreehandStrokeItem(
|
|
9190
9296
|
itemId,
|
|
@@ -9195,13 +9301,16 @@ var VectorViewport = forwardRef(
|
|
|
9195
9301
|
if (item) {
|
|
9196
9302
|
renderSceneWithLivePenStroke(item);
|
|
9197
9303
|
}
|
|
9198
|
-
|
|
9304
|
+
const nextDragState = {
|
|
9199
9305
|
kind: "stroke",
|
|
9200
9306
|
tool,
|
|
9201
9307
|
points: [startPoint],
|
|
9202
9308
|
pointerType: e.pointerType,
|
|
9203
|
-
itemId
|
|
9309
|
+
itemId,
|
|
9310
|
+
...straightLine ? { straightLine } : {}
|
|
9204
9311
|
};
|
|
9312
|
+
dragStateRef.current = nextDragState;
|
|
9313
|
+
startOrRestartStraightStrokeHoldTimer(nextDragState);
|
|
9205
9314
|
activeInteractionPointerIdRef.current = e.pointerId;
|
|
9206
9315
|
activeInteractionPointerTargetRef.current = null;
|
|
9207
9316
|
setPlacementPreview(null);
|
|
@@ -9227,7 +9336,8 @@ var VectorViewport = forwardRef(
|
|
|
9227
9336
|
finalizeStrokeDragState,
|
|
9228
9337
|
interactive,
|
|
9229
9338
|
renderSceneWithLivePenStroke,
|
|
9230
|
-
screenToWorld
|
|
9339
|
+
screenToWorld,
|
|
9340
|
+
startOrRestartStraightStrokeHoldTimer
|
|
9231
9341
|
]);
|
|
9232
9342
|
useEffect(() => {
|
|
9233
9343
|
if (!interactive) return;
|
|
@@ -9286,6 +9396,7 @@ var VectorViewport = forwardRef(
|
|
|
9286
9396
|
touch.clientY,
|
|
9287
9397
|
touchPressure(touch)
|
|
9288
9398
|
);
|
|
9399
|
+
const straightLine = tool === "draw" ? createStraightStrokeState(startPoint, touch.clientX, touch.clientY) : void 0;
|
|
9289
9400
|
const itemId = createShapeId();
|
|
9290
9401
|
const item = createFreehandStrokeItem(
|
|
9291
9402
|
itemId,
|
|
@@ -9296,13 +9407,16 @@ var VectorViewport = forwardRef(
|
|
|
9296
9407
|
if (item) {
|
|
9297
9408
|
renderSceneWithLivePenStroke(item);
|
|
9298
9409
|
}
|
|
9299
|
-
|
|
9410
|
+
const nextDragState = {
|
|
9300
9411
|
kind: "stroke",
|
|
9301
9412
|
tool,
|
|
9302
9413
|
points: [startPoint],
|
|
9303
9414
|
pointerType: "pen",
|
|
9304
|
-
itemId
|
|
9415
|
+
itemId,
|
|
9416
|
+
...straightLine ? { straightLine } : {}
|
|
9305
9417
|
};
|
|
9418
|
+
dragStateRef.current = nextDragState;
|
|
9419
|
+
startOrRestartStraightStrokeHoldTimer(nextDragState);
|
|
9306
9420
|
activeInteractionPointerIdRef.current = null;
|
|
9307
9421
|
activeInteractionPointerTargetRef.current = null;
|
|
9308
9422
|
activeInteractionTouchIdRef.current = touch.identifier;
|
|
@@ -9321,6 +9435,21 @@ var VectorViewport = forwardRef(
|
|
|
9321
9435
|
if (!touch) return;
|
|
9322
9436
|
const cam = cameraRef.current;
|
|
9323
9437
|
if (!cam) return;
|
|
9438
|
+
const endpoint = pointerSampleToWorldPoint(
|
|
9439
|
+
screenToWorld,
|
|
9440
|
+
touch.clientX,
|
|
9441
|
+
touch.clientY,
|
|
9442
|
+
touchPressure(touch)
|
|
9443
|
+
);
|
|
9444
|
+
if (updateStraightStrokeForMove(st, touch.clientX, touch.clientY, endpoint)) {
|
|
9445
|
+
debugApplePencilPointer("touchmove-stroke", {
|
|
9446
|
+
touchId: touch.identifier,
|
|
9447
|
+
points: st.points.length,
|
|
9448
|
+
force: touchPressure(touch)
|
|
9449
|
+
});
|
|
9450
|
+
stopTouchEvent(ev);
|
|
9451
|
+
return;
|
|
9452
|
+
}
|
|
9324
9453
|
const interpolated = appendTouchToStrokePoints(
|
|
9325
9454
|
st.points,
|
|
9326
9455
|
touch,
|
|
@@ -9355,13 +9484,23 @@ var VectorViewport = forwardRef(
|
|
|
9355
9484
|
if (!touch) return;
|
|
9356
9485
|
const cam = cameraRef.current;
|
|
9357
9486
|
if (cam) {
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
|
|
9364
|
-
|
|
9487
|
+
if (st.straightLine?.active) {
|
|
9488
|
+
const endpoint = pointerSampleToWorldPoint(
|
|
9489
|
+
screenToWorld,
|
|
9490
|
+
touch.clientX,
|
|
9491
|
+
touch.clientY,
|
|
9492
|
+
touchPressure(touch)
|
|
9493
|
+
);
|
|
9494
|
+
setStraightStrokeEndpoint(st, endpoint);
|
|
9495
|
+
} else {
|
|
9496
|
+
const completedPoints = appendTouchToStrokePoints(
|
|
9497
|
+
st.points,
|
|
9498
|
+
touch,
|
|
9499
|
+
cam.zoom,
|
|
9500
|
+
screenToWorld
|
|
9501
|
+
);
|
|
9502
|
+
st.points = completedPoints;
|
|
9503
|
+
}
|
|
9365
9504
|
}
|
|
9366
9505
|
debugApplePencilPointer("touchend-stroke", {
|
|
9367
9506
|
touchId: touch.identifier,
|
|
@@ -9406,7 +9545,10 @@ var VectorViewport = forwardRef(
|
|
|
9406
9545
|
finalizeStrokeDragState,
|
|
9407
9546
|
interactive,
|
|
9408
9547
|
renderSceneWithLivePenStroke,
|
|
9409
|
-
screenToWorld
|
|
9548
|
+
screenToWorld,
|
|
9549
|
+
setStraightStrokeEndpoint,
|
|
9550
|
+
startOrRestartStraightStrokeHoldTimer,
|
|
9551
|
+
updateStraightStrokeForMove
|
|
9410
9552
|
]);
|
|
9411
9553
|
useEffect(() => {
|
|
9412
9554
|
if (!interactive) return;
|
|
@@ -9439,6 +9581,15 @@ var VectorViewport = forwardRef(
|
|
|
9439
9581
|
pressure: ev.pointerType === "pen" ? ev.pressure : void 0
|
|
9440
9582
|
});
|
|
9441
9583
|
}
|
|
9584
|
+
const endpoint = pointerSampleToWorldPoint(
|
|
9585
|
+
screenToWorld,
|
|
9586
|
+
ev.clientX,
|
|
9587
|
+
ev.clientY,
|
|
9588
|
+
ev.pointerType === "pen" ? ev.pressure : void 0
|
|
9589
|
+
);
|
|
9590
|
+
if (updateStraightStrokeForMove(st, ev.clientX, ev.clientY, endpoint)) {
|
|
9591
|
+
return;
|
|
9592
|
+
}
|
|
9442
9593
|
const interpolated = appendPointerEventSamplesToStrokePoints(
|
|
9443
9594
|
st.points,
|
|
9444
9595
|
ev,
|
|
@@ -9606,6 +9757,7 @@ var VectorViewport = forwardRef(
|
|
|
9606
9757
|
const cam = cameraRef.current;
|
|
9607
9758
|
if (!cam) {
|
|
9608
9759
|
if (st.kind === "stroke") {
|
|
9760
|
+
clearStraightStrokeHoldTimer(st);
|
|
9609
9761
|
emitRemoteStrokePreviewClear();
|
|
9610
9762
|
}
|
|
9611
9763
|
if (st.kind === "erase") {
|
|
@@ -9661,13 +9813,26 @@ var VectorViewport = forwardRef(
|
|
|
9661
9813
|
return;
|
|
9662
9814
|
}
|
|
9663
9815
|
if (st.kind === "stroke") {
|
|
9664
|
-
const completedPoints =
|
|
9665
|
-
st.
|
|
9666
|
-
|
|
9667
|
-
|
|
9668
|
-
|
|
9669
|
-
|
|
9670
|
-
|
|
9816
|
+
const completedPoints = (() => {
|
|
9817
|
+
if (st.straightLine?.active) {
|
|
9818
|
+
const endpoint = pointerSampleToWorldPoint(
|
|
9819
|
+
screenToWorld,
|
|
9820
|
+
ev.clientX,
|
|
9821
|
+
ev.clientY,
|
|
9822
|
+
ev.pointerType === "pen" ? ev.pressure : void 0
|
|
9823
|
+
);
|
|
9824
|
+
setStraightStrokeEndpoint(st, endpoint);
|
|
9825
|
+
return st.points;
|
|
9826
|
+
}
|
|
9827
|
+
const points = appendPointerEventSamplesToStrokePoints(
|
|
9828
|
+
st.points,
|
|
9829
|
+
ev,
|
|
9830
|
+
cam.zoom,
|
|
9831
|
+
screenToWorld
|
|
9832
|
+
);
|
|
9833
|
+
st.points = points;
|
|
9834
|
+
return points;
|
|
9835
|
+
})();
|
|
9671
9836
|
debugApplePencilPointer("pointerup-stroke-points", {
|
|
9672
9837
|
pointerType: ev.pointerType,
|
|
9673
9838
|
pointerId: ev.pointerId,
|
|
@@ -9854,7 +10019,9 @@ var VectorViewport = forwardRef(
|
|
|
9854
10019
|
renderSceneWithLivePenStroke,
|
|
9855
10020
|
releaseInteractionPointer,
|
|
9856
10021
|
requestAutoResetTool,
|
|
9857
|
-
screenToWorld
|
|
10022
|
+
screenToWorld,
|
|
10023
|
+
setStraightStrokeEndpoint,
|
|
10024
|
+
updateStraightStrokeForMove
|
|
9858
10025
|
]);
|
|
9859
10026
|
const selectedItemsForOverlay = useMemo(() => {
|
|
9860
10027
|
return effectiveSelectedIds.map((id) => resolvedItems.find((i) => i.id === id)).filter((i) => i != null);
|