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.cjs
CHANGED
|
@@ -1825,6 +1825,67 @@ function useCanvuChromeContext() {
|
|
|
1825
1825
|
return react.useContext(CanvuChromeContext);
|
|
1826
1826
|
}
|
|
1827
1827
|
|
|
1828
|
+
// src/math/item-transform.ts
|
|
1829
|
+
init_rect();
|
|
1830
|
+
function getItemRotationRad(item) {
|
|
1831
|
+
return item.rotation ?? 0;
|
|
1832
|
+
}
|
|
1833
|
+
function itemLocalToWorld(lx, ly, itemX, itemY, w, h, rotationRad) {
|
|
1834
|
+
const c = { x: w / 2, y: h / 2 };
|
|
1835
|
+
const dlx = lx - c.x;
|
|
1836
|
+
const dly = ly - c.y;
|
|
1837
|
+
const cos = Math.cos(rotationRad);
|
|
1838
|
+
const sin = Math.sin(rotationRad);
|
|
1839
|
+
return {
|
|
1840
|
+
x: itemX + c.x + cos * dlx - sin * dly,
|
|
1841
|
+
y: itemY + c.y + sin * dlx + cos * dly
|
|
1842
|
+
};
|
|
1843
|
+
}
|
|
1844
|
+
function worldToItemLocal(wx, wy, itemX, itemY, w, h, rotationRad) {
|
|
1845
|
+
const c = { x: w / 2, y: h / 2 };
|
|
1846
|
+
const vx = wx - itemX;
|
|
1847
|
+
const vy = wy - itemY;
|
|
1848
|
+
const dx = vx - c.x;
|
|
1849
|
+
const dy = vy - c.y;
|
|
1850
|
+
const cos = Math.cos(-rotationRad);
|
|
1851
|
+
const sin = Math.sin(-rotationRad);
|
|
1852
|
+
const lx = cos * dx - sin * dy;
|
|
1853
|
+
const ly = sin * dx + cos * dy;
|
|
1854
|
+
return { x: c.x + lx, y: c.y + ly };
|
|
1855
|
+
}
|
|
1856
|
+
function itemPivotWorld(item) {
|
|
1857
|
+
const r = normalizeRect(item.bounds);
|
|
1858
|
+
return { x: r.x + r.width / 2, y: r.y + r.height / 2 };
|
|
1859
|
+
}
|
|
1860
|
+
function boundsAabbForRotatedItem(item) {
|
|
1861
|
+
const rot = getItemRotationRad(item);
|
|
1862
|
+
if (Math.abs(rot) < 1e-12 && item.bounds.width >= 0 && item.bounds.height >= 0) {
|
|
1863
|
+
return item.bounds;
|
|
1864
|
+
}
|
|
1865
|
+
const r = normalizeRect(item.bounds);
|
|
1866
|
+
if (Math.abs(rot) < 1e-12) {
|
|
1867
|
+
return r;
|
|
1868
|
+
}
|
|
1869
|
+
const corners = [
|
|
1870
|
+
[0, 0],
|
|
1871
|
+
[r.width, 0],
|
|
1872
|
+
[r.width, r.height],
|
|
1873
|
+
[0, r.height]
|
|
1874
|
+
];
|
|
1875
|
+
let minX = Infinity;
|
|
1876
|
+
let minY = Infinity;
|
|
1877
|
+
let maxX = -Infinity;
|
|
1878
|
+
let maxY = -Infinity;
|
|
1879
|
+
for (const [lx, ly] of corners) {
|
|
1880
|
+
const p = itemLocalToWorld(lx, ly, item.x, item.y, r.width, r.height, rot);
|
|
1881
|
+
minX = Math.min(minX, p.x);
|
|
1882
|
+
minY = Math.min(minY, p.y);
|
|
1883
|
+
maxX = Math.max(maxX, p.x);
|
|
1884
|
+
maxY = Math.max(maxY, p.y);
|
|
1885
|
+
}
|
|
1886
|
+
return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1828
1889
|
// src/scene/clone-item.ts
|
|
1829
1890
|
init_shape_builders();
|
|
1830
1891
|
function cloneVectorSceneItemWithNewId(item) {
|
|
@@ -1864,20 +1925,25 @@ function markImageAsManaged(item) {
|
|
|
1864
1925
|
};
|
|
1865
1926
|
}
|
|
1866
1927
|
function restackManagedImages(items) {
|
|
1867
|
-
let
|
|
1928
|
+
let anchorAabbY = Infinity;
|
|
1929
|
+
let anchorCenterX = 0;
|
|
1868
1930
|
for (const item of items) {
|
|
1869
1931
|
if (!isManagedImage(item)) continue;
|
|
1870
|
-
|
|
1932
|
+
const aabb = boundsAabbForRotatedItem(item);
|
|
1933
|
+
if (aabb.y < anchorAabbY) {
|
|
1934
|
+
anchorAabbY = aabb.y;
|
|
1935
|
+
anchorCenterX = aabb.x + aabb.width / 2;
|
|
1936
|
+
}
|
|
1871
1937
|
}
|
|
1872
|
-
if (!
|
|
1873
|
-
|
|
1874
|
-
const anchorTopY = anchor.bounds.y;
|
|
1875
|
-
let cursorY = anchorTopY;
|
|
1938
|
+
if (!Number.isFinite(anchorAabbY)) return [...items];
|
|
1939
|
+
let cursorY = anchorAabbY;
|
|
1876
1940
|
return items.map((item) => {
|
|
1877
1941
|
if (!isManagedImage(item)) return item;
|
|
1942
|
+
const aabb = boundsAabbForRotatedItem(item);
|
|
1943
|
+
const centerY = cursorY + aabb.height / 2;
|
|
1878
1944
|
const newX = anchorCenterX - item.bounds.width / 2;
|
|
1879
|
-
const newY =
|
|
1880
|
-
cursorY
|
|
1945
|
+
const newY = centerY - item.bounds.height / 2;
|
|
1946
|
+
cursorY += aabb.height + STACK_GAP_WORLD;
|
|
1881
1947
|
if (item.bounds.x === newX && item.bounds.y === newY) return item;
|
|
1882
1948
|
return {
|
|
1883
1949
|
...item,
|
|
@@ -1897,8 +1963,10 @@ function copyManagedImage(items, id) {
|
|
|
1897
1963
|
return restackManagedImages(inserted);
|
|
1898
1964
|
}
|
|
1899
1965
|
function rotateManagedImage(items, id) {
|
|
1900
|
-
return
|
|
1901
|
-
|
|
1966
|
+
return restackManagedImages(
|
|
1967
|
+
items.map(
|
|
1968
|
+
(i) => i.id === id ? { ...i, rotation: ((i.rotation ?? 0) + Math.PI / 2) % (Math.PI * 2) } : i
|
|
1969
|
+
)
|
|
1902
1970
|
);
|
|
1903
1971
|
}
|
|
1904
1972
|
function deleteManagedImage(items, id) {
|
|
@@ -2345,69 +2413,6 @@ function getBoardPositionStyle(position, inset = 12, zIndex = 40) {
|
|
|
2345
2413
|
return base2;
|
|
2346
2414
|
}
|
|
2347
2415
|
}
|
|
2348
|
-
|
|
2349
|
-
// src/math/item-transform.ts
|
|
2350
|
-
init_rect();
|
|
2351
|
-
function getItemRotationRad(item) {
|
|
2352
|
-
return item.rotation ?? 0;
|
|
2353
|
-
}
|
|
2354
|
-
function itemLocalToWorld(lx, ly, itemX, itemY, w, h, rotationRad) {
|
|
2355
|
-
const c = { x: w / 2, y: h / 2 };
|
|
2356
|
-
const dlx = lx - c.x;
|
|
2357
|
-
const dly = ly - c.y;
|
|
2358
|
-
const cos = Math.cos(rotationRad);
|
|
2359
|
-
const sin = Math.sin(rotationRad);
|
|
2360
|
-
return {
|
|
2361
|
-
x: itemX + c.x + cos * dlx - sin * dly,
|
|
2362
|
-
y: itemY + c.y + sin * dlx + cos * dly
|
|
2363
|
-
};
|
|
2364
|
-
}
|
|
2365
|
-
function worldToItemLocal(wx, wy, itemX, itemY, w, h, rotationRad) {
|
|
2366
|
-
const c = { x: w / 2, y: h / 2 };
|
|
2367
|
-
const vx = wx - itemX;
|
|
2368
|
-
const vy = wy - itemY;
|
|
2369
|
-
const dx = vx - c.x;
|
|
2370
|
-
const dy = vy - c.y;
|
|
2371
|
-
const cos = Math.cos(-rotationRad);
|
|
2372
|
-
const sin = Math.sin(-rotationRad);
|
|
2373
|
-
const lx = cos * dx - sin * dy;
|
|
2374
|
-
const ly = sin * dx + cos * dy;
|
|
2375
|
-
return { x: c.x + lx, y: c.y + ly };
|
|
2376
|
-
}
|
|
2377
|
-
function itemPivotWorld(item) {
|
|
2378
|
-
const r = normalizeRect(item.bounds);
|
|
2379
|
-
return { x: r.x + r.width / 2, y: r.y + r.height / 2 };
|
|
2380
|
-
}
|
|
2381
|
-
function boundsAabbForRotatedItem(item) {
|
|
2382
|
-
const rot = getItemRotationRad(item);
|
|
2383
|
-
if (Math.abs(rot) < 1e-12 && item.bounds.width >= 0 && item.bounds.height >= 0) {
|
|
2384
|
-
return item.bounds;
|
|
2385
|
-
}
|
|
2386
|
-
const r = normalizeRect(item.bounds);
|
|
2387
|
-
if (Math.abs(rot) < 1e-12) {
|
|
2388
|
-
return r;
|
|
2389
|
-
}
|
|
2390
|
-
const corners = [
|
|
2391
|
-
[0, 0],
|
|
2392
|
-
[r.width, 0],
|
|
2393
|
-
[r.width, r.height],
|
|
2394
|
-
[0, r.height]
|
|
2395
|
-
];
|
|
2396
|
-
let minX = Infinity;
|
|
2397
|
-
let minY = Infinity;
|
|
2398
|
-
let maxX = -Infinity;
|
|
2399
|
-
let maxY = -Infinity;
|
|
2400
|
-
for (const [lx, ly] of corners) {
|
|
2401
|
-
const p = itemLocalToWorld(lx, ly, item.x, item.y, r.width, r.height, rot);
|
|
2402
|
-
minX = Math.min(minX, p.x);
|
|
2403
|
-
minY = Math.min(minY, p.y);
|
|
2404
|
-
maxX = Math.max(maxX, p.x);
|
|
2405
|
-
maxY = Math.max(maxY, p.y);
|
|
2406
|
-
}
|
|
2407
|
-
return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
|
|
2408
|
-
}
|
|
2409
|
-
|
|
2410
|
-
// src/react/navmenu/minimap.tsx
|
|
2411
2416
|
init_rect();
|
|
2412
2417
|
var NavMenuMinimapSlotContext = react.createContext(null);
|
|
2413
2418
|
function noop() {
|
|
@@ -7282,6 +7287,8 @@ body[data-canvu-pen-active="true"] [data-slot="shape-context-menu"] * {
|
|
|
7282
7287
|
-webkit-touch-callout: none !important;
|
|
7283
7288
|
}
|
|
7284
7289
|
`;
|
|
7290
|
+
var STRAIGHT_STROKE_HOLD_DURATION_MS = 1e3;
|
|
7291
|
+
var STRAIGHT_STROKE_JITTER_TOLERANCE_SQUARED = 5 * 5;
|
|
7285
7292
|
function debugApplePencilPointer(phase, detail) {
|
|
7286
7293
|
return;
|
|
7287
7294
|
}
|
|
@@ -7429,6 +7436,28 @@ function appendTouchToStrokePoints(points, touch, zoom, screenToWorldFn) {
|
|
|
7429
7436
|
);
|
|
7430
7437
|
return appendInterpolatedPoints(points, nextPoint);
|
|
7431
7438
|
}
|
|
7439
|
+
function createStraightStrokeState(anchorPoint, clientX, clientY) {
|
|
7440
|
+
return {
|
|
7441
|
+
active: false,
|
|
7442
|
+
anchorPoint,
|
|
7443
|
+
holdScreen: { x: clientX, y: clientY },
|
|
7444
|
+
holdTimer: null
|
|
7445
|
+
};
|
|
7446
|
+
}
|
|
7447
|
+
function clearStraightStrokeHoldTimer(strokeState) {
|
|
7448
|
+
const straightLine = strokeState.straightLine;
|
|
7449
|
+
if (!straightLine?.holdTimer) return;
|
|
7450
|
+
clearTimeout(straightLine.holdTimer);
|
|
7451
|
+
straightLine.holdTimer = null;
|
|
7452
|
+
}
|
|
7453
|
+
function lastStrokePoint(points) {
|
|
7454
|
+
return points[points.length - 1] ?? null;
|
|
7455
|
+
}
|
|
7456
|
+
function hasMovedPastStraightStrokeJitter(straightLine, clientX, clientY) {
|
|
7457
|
+
const deltaX = clientX - straightLine.holdScreen.x;
|
|
7458
|
+
const deltaY = clientY - straightLine.holdScreen.y;
|
|
7459
|
+
return deltaX * deltaX + deltaY * deltaY > STRAIGHT_STROKE_JITTER_TOLERANCE_SQUARED;
|
|
7460
|
+
}
|
|
7432
7461
|
var VectorViewport = react.forwardRef(
|
|
7433
7462
|
function VectorViewport2({
|
|
7434
7463
|
items,
|
|
@@ -7963,6 +7992,76 @@ var VectorViewport = react.forwardRef(
|
|
|
7963
7992
|
},
|
|
7964
7993
|
[]
|
|
7965
7994
|
);
|
|
7995
|
+
const updateStrokePreviewPoints = react.useCallback(
|
|
7996
|
+
(strokeState, points) => {
|
|
7997
|
+
strokeState.points = points;
|
|
7998
|
+
if (strokeState.itemId && strokeState.tool !== "laser") {
|
|
7999
|
+
const item = createFreehandStrokeItem(
|
|
8000
|
+
strokeState.itemId,
|
|
8001
|
+
points,
|
|
8002
|
+
strokeState.tool,
|
|
8003
|
+
strokeStyleRef.current
|
|
8004
|
+
);
|
|
8005
|
+
if (item) {
|
|
8006
|
+
renderSceneWithLivePenStroke(item);
|
|
8007
|
+
}
|
|
8008
|
+
setPlacementPreview(null);
|
|
8009
|
+
emitRemoteStrokePreview(strokeState.tool, points);
|
|
8010
|
+
return;
|
|
8011
|
+
}
|
|
8012
|
+
if (strokeState.tool === "laser") return;
|
|
8013
|
+
setPlacementPreview({
|
|
8014
|
+
kind: "stroke",
|
|
8015
|
+
tool: strokeState.tool,
|
|
8016
|
+
points,
|
|
8017
|
+
style: { ...strokeStyleRef.current }
|
|
8018
|
+
});
|
|
8019
|
+
},
|
|
8020
|
+
[emitRemoteStrokePreview, renderSceneWithLivePenStroke]
|
|
8021
|
+
);
|
|
8022
|
+
const setStraightStrokeEndpoint = react.useCallback(
|
|
8023
|
+
(strokeState, endpoint) => {
|
|
8024
|
+
const straightLine = strokeState.straightLine;
|
|
8025
|
+
if (!straightLine) return;
|
|
8026
|
+
straightLine.active = true;
|
|
8027
|
+
updateStrokePreviewPoints(strokeState, [straightLine.anchorPoint, endpoint]);
|
|
8028
|
+
},
|
|
8029
|
+
[updateStrokePreviewPoints]
|
|
8030
|
+
);
|
|
8031
|
+
const startOrRestartStraightStrokeHoldTimer = react.useCallback(
|
|
8032
|
+
(strokeState) => {
|
|
8033
|
+
const straightLine = strokeState.straightLine;
|
|
8034
|
+
if (!straightLine || strokeState.tool !== "draw") return;
|
|
8035
|
+
clearStraightStrokeHoldTimer(strokeState);
|
|
8036
|
+
straightLine.holdTimer = window.setTimeout(() => {
|
|
8037
|
+
straightLine.holdTimer = null;
|
|
8038
|
+
const currentStrokeState = dragStateRef.current;
|
|
8039
|
+
if (currentStrokeState.kind !== "stroke" || currentStrokeState !== strokeState) {
|
|
8040
|
+
return;
|
|
8041
|
+
}
|
|
8042
|
+
const endpoint = lastStrokePoint(currentStrokeState.points);
|
|
8043
|
+
if (!endpoint) return;
|
|
8044
|
+
setStraightStrokeEndpoint(currentStrokeState, endpoint);
|
|
8045
|
+
}, STRAIGHT_STROKE_HOLD_DURATION_MS);
|
|
8046
|
+
},
|
|
8047
|
+
[setStraightStrokeEndpoint]
|
|
8048
|
+
);
|
|
8049
|
+
const updateStraightStrokeForMove = react.useCallback(
|
|
8050
|
+
(strokeState, clientX, clientY, endpoint) => {
|
|
8051
|
+
const straightLine = strokeState.straightLine;
|
|
8052
|
+
if (!straightLine || strokeState.tool !== "draw") return false;
|
|
8053
|
+
if (straightLine.active) {
|
|
8054
|
+
setStraightStrokeEndpoint(strokeState, endpoint);
|
|
8055
|
+
return true;
|
|
8056
|
+
}
|
|
8057
|
+
if (straightLine.holdTimer && hasMovedPastStraightStrokeJitter(straightLine, clientX, clientY)) {
|
|
8058
|
+
straightLine.holdScreen = { x: clientX, y: clientY };
|
|
8059
|
+
startOrRestartStraightStrokeHoldTimer(strokeState);
|
|
8060
|
+
}
|
|
8061
|
+
return false;
|
|
8062
|
+
},
|
|
8063
|
+
[setStraightStrokeEndpoint, startOrRestartStraightStrokeHoldTimer]
|
|
8064
|
+
);
|
|
7966
8065
|
const finalizeStrokeDragState = react.useCallback(
|
|
7967
8066
|
(strokeState) => {
|
|
7968
8067
|
const tool = strokeState.tool;
|
|
@@ -7973,6 +8072,7 @@ var VectorViewport = react.forwardRef(
|
|
|
7973
8072
|
debugApplePencilPointer("finalize-stroke", {
|
|
7974
8073
|
points: pts.length
|
|
7975
8074
|
});
|
|
8075
|
+
clearStraightStrokeHoldTimer(strokeState);
|
|
7976
8076
|
dragStateRef.current = { kind: "idle" };
|
|
7977
8077
|
releaseInteractionPointer();
|
|
7978
8078
|
if (itemId) {
|
|
@@ -9084,6 +9184,7 @@ var VectorViewport = react.forwardRef(
|
|
|
9084
9184
|
e.clientY,
|
|
9085
9185
|
e.pointerType === "pen" ? e.pressure : void 0
|
|
9086
9186
|
);
|
|
9187
|
+
const straightLine = tool === "draw" ? createStraightStrokeState(startPoint, e.clientX, e.clientY) : void 0;
|
|
9087
9188
|
const directPenStroke = e.pointerType === "pen" && (tool === "draw" || tool === "marker");
|
|
9088
9189
|
let itemId;
|
|
9089
9190
|
if (directPenStroke) {
|
|
@@ -9098,13 +9199,16 @@ var VectorViewport = react.forwardRef(
|
|
|
9098
9199
|
renderSceneWithLivePenStroke(item);
|
|
9099
9200
|
}
|
|
9100
9201
|
}
|
|
9101
|
-
|
|
9202
|
+
const nextDragState = {
|
|
9102
9203
|
kind: "stroke",
|
|
9103
9204
|
tool,
|
|
9104
9205
|
points: [startPoint],
|
|
9105
9206
|
pointerType: e.pointerType,
|
|
9106
|
-
...itemId ? { itemId } : {}
|
|
9207
|
+
...itemId ? { itemId } : {},
|
|
9208
|
+
...straightLine ? { straightLine } : {}
|
|
9107
9209
|
};
|
|
9210
|
+
dragStateRef.current = nextDragState;
|
|
9211
|
+
startOrRestartStraightStrokeHoldTimer(nextDragState);
|
|
9108
9212
|
if (tool === "laser") {
|
|
9109
9213
|
setLaserTrail([{ x: worldX, y: worldY, t: Date.now() }]);
|
|
9110
9214
|
setPlacementPreview(null);
|
|
@@ -9156,7 +9260,8 @@ var VectorViewport = react.forwardRef(
|
|
|
9156
9260
|
emitRemoteStrokePreview,
|
|
9157
9261
|
finalizeStrokeDragState,
|
|
9158
9262
|
renderSceneWithLivePenStroke,
|
|
9159
|
-
screenToWorld
|
|
9263
|
+
screenToWorld,
|
|
9264
|
+
startOrRestartStraightStrokeHoldTimer
|
|
9160
9265
|
]
|
|
9161
9266
|
);
|
|
9162
9267
|
react.useEffect(() => {
|
|
@@ -9192,6 +9297,7 @@ var VectorViewport = react.forwardRef(
|
|
|
9192
9297
|
e.clientY,
|
|
9193
9298
|
e.pressure
|
|
9194
9299
|
);
|
|
9300
|
+
const straightLine = tool === "draw" ? createStraightStrokeState(startPoint, e.clientX, e.clientY) : void 0;
|
|
9195
9301
|
const itemId = createShapeId();
|
|
9196
9302
|
const item = createFreehandStrokeItem(
|
|
9197
9303
|
itemId,
|
|
@@ -9202,13 +9308,16 @@ var VectorViewport = react.forwardRef(
|
|
|
9202
9308
|
if (item) {
|
|
9203
9309
|
renderSceneWithLivePenStroke(item);
|
|
9204
9310
|
}
|
|
9205
|
-
|
|
9311
|
+
const nextDragState = {
|
|
9206
9312
|
kind: "stroke",
|
|
9207
9313
|
tool,
|
|
9208
9314
|
points: [startPoint],
|
|
9209
9315
|
pointerType: e.pointerType,
|
|
9210
|
-
itemId
|
|
9316
|
+
itemId,
|
|
9317
|
+
...straightLine ? { straightLine } : {}
|
|
9211
9318
|
};
|
|
9319
|
+
dragStateRef.current = nextDragState;
|
|
9320
|
+
startOrRestartStraightStrokeHoldTimer(nextDragState);
|
|
9212
9321
|
activeInteractionPointerIdRef.current = e.pointerId;
|
|
9213
9322
|
activeInteractionPointerTargetRef.current = null;
|
|
9214
9323
|
setPlacementPreview(null);
|
|
@@ -9234,7 +9343,8 @@ var VectorViewport = react.forwardRef(
|
|
|
9234
9343
|
finalizeStrokeDragState,
|
|
9235
9344
|
interactive,
|
|
9236
9345
|
renderSceneWithLivePenStroke,
|
|
9237
|
-
screenToWorld
|
|
9346
|
+
screenToWorld,
|
|
9347
|
+
startOrRestartStraightStrokeHoldTimer
|
|
9238
9348
|
]);
|
|
9239
9349
|
react.useEffect(() => {
|
|
9240
9350
|
if (!interactive) return;
|
|
@@ -9293,6 +9403,7 @@ var VectorViewport = react.forwardRef(
|
|
|
9293
9403
|
touch.clientY,
|
|
9294
9404
|
touchPressure(touch)
|
|
9295
9405
|
);
|
|
9406
|
+
const straightLine = tool === "draw" ? createStraightStrokeState(startPoint, touch.clientX, touch.clientY) : void 0;
|
|
9296
9407
|
const itemId = createShapeId();
|
|
9297
9408
|
const item = createFreehandStrokeItem(
|
|
9298
9409
|
itemId,
|
|
@@ -9303,13 +9414,16 @@ var VectorViewport = react.forwardRef(
|
|
|
9303
9414
|
if (item) {
|
|
9304
9415
|
renderSceneWithLivePenStroke(item);
|
|
9305
9416
|
}
|
|
9306
|
-
|
|
9417
|
+
const nextDragState = {
|
|
9307
9418
|
kind: "stroke",
|
|
9308
9419
|
tool,
|
|
9309
9420
|
points: [startPoint],
|
|
9310
9421
|
pointerType: "pen",
|
|
9311
|
-
itemId
|
|
9422
|
+
itemId,
|
|
9423
|
+
...straightLine ? { straightLine } : {}
|
|
9312
9424
|
};
|
|
9425
|
+
dragStateRef.current = nextDragState;
|
|
9426
|
+
startOrRestartStraightStrokeHoldTimer(nextDragState);
|
|
9313
9427
|
activeInteractionPointerIdRef.current = null;
|
|
9314
9428
|
activeInteractionPointerTargetRef.current = null;
|
|
9315
9429
|
activeInteractionTouchIdRef.current = touch.identifier;
|
|
@@ -9328,6 +9442,21 @@ var VectorViewport = react.forwardRef(
|
|
|
9328
9442
|
if (!touch) return;
|
|
9329
9443
|
const cam = cameraRef.current;
|
|
9330
9444
|
if (!cam) return;
|
|
9445
|
+
const endpoint = pointerSampleToWorldPoint(
|
|
9446
|
+
screenToWorld,
|
|
9447
|
+
touch.clientX,
|
|
9448
|
+
touch.clientY,
|
|
9449
|
+
touchPressure(touch)
|
|
9450
|
+
);
|
|
9451
|
+
if (updateStraightStrokeForMove(st, touch.clientX, touch.clientY, endpoint)) {
|
|
9452
|
+
debugApplePencilPointer("touchmove-stroke", {
|
|
9453
|
+
touchId: touch.identifier,
|
|
9454
|
+
points: st.points.length,
|
|
9455
|
+
force: touchPressure(touch)
|
|
9456
|
+
});
|
|
9457
|
+
stopTouchEvent(ev);
|
|
9458
|
+
return;
|
|
9459
|
+
}
|
|
9331
9460
|
const interpolated = appendTouchToStrokePoints(
|
|
9332
9461
|
st.points,
|
|
9333
9462
|
touch,
|
|
@@ -9362,13 +9491,23 @@ var VectorViewport = react.forwardRef(
|
|
|
9362
9491
|
if (!touch) return;
|
|
9363
9492
|
const cam = cameraRef.current;
|
|
9364
9493
|
if (cam) {
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
|
|
9369
|
-
|
|
9370
|
-
|
|
9371
|
-
|
|
9494
|
+
if (st.straightLine?.active) {
|
|
9495
|
+
const endpoint = pointerSampleToWorldPoint(
|
|
9496
|
+
screenToWorld,
|
|
9497
|
+
touch.clientX,
|
|
9498
|
+
touch.clientY,
|
|
9499
|
+
touchPressure(touch)
|
|
9500
|
+
);
|
|
9501
|
+
setStraightStrokeEndpoint(st, endpoint);
|
|
9502
|
+
} else {
|
|
9503
|
+
const completedPoints = appendTouchToStrokePoints(
|
|
9504
|
+
st.points,
|
|
9505
|
+
touch,
|
|
9506
|
+
cam.zoom,
|
|
9507
|
+
screenToWorld
|
|
9508
|
+
);
|
|
9509
|
+
st.points = completedPoints;
|
|
9510
|
+
}
|
|
9372
9511
|
}
|
|
9373
9512
|
debugApplePencilPointer("touchend-stroke", {
|
|
9374
9513
|
touchId: touch.identifier,
|
|
@@ -9413,7 +9552,10 @@ var VectorViewport = react.forwardRef(
|
|
|
9413
9552
|
finalizeStrokeDragState,
|
|
9414
9553
|
interactive,
|
|
9415
9554
|
renderSceneWithLivePenStroke,
|
|
9416
|
-
screenToWorld
|
|
9555
|
+
screenToWorld,
|
|
9556
|
+
setStraightStrokeEndpoint,
|
|
9557
|
+
startOrRestartStraightStrokeHoldTimer,
|
|
9558
|
+
updateStraightStrokeForMove
|
|
9417
9559
|
]);
|
|
9418
9560
|
react.useEffect(() => {
|
|
9419
9561
|
if (!interactive) return;
|
|
@@ -9446,6 +9588,15 @@ var VectorViewport = react.forwardRef(
|
|
|
9446
9588
|
pressure: ev.pointerType === "pen" ? ev.pressure : void 0
|
|
9447
9589
|
});
|
|
9448
9590
|
}
|
|
9591
|
+
const endpoint = pointerSampleToWorldPoint(
|
|
9592
|
+
screenToWorld,
|
|
9593
|
+
ev.clientX,
|
|
9594
|
+
ev.clientY,
|
|
9595
|
+
ev.pointerType === "pen" ? ev.pressure : void 0
|
|
9596
|
+
);
|
|
9597
|
+
if (updateStraightStrokeForMove(st, ev.clientX, ev.clientY, endpoint)) {
|
|
9598
|
+
return;
|
|
9599
|
+
}
|
|
9449
9600
|
const interpolated = appendPointerEventSamplesToStrokePoints(
|
|
9450
9601
|
st.points,
|
|
9451
9602
|
ev,
|
|
@@ -9613,6 +9764,7 @@ var VectorViewport = react.forwardRef(
|
|
|
9613
9764
|
const cam = cameraRef.current;
|
|
9614
9765
|
if (!cam) {
|
|
9615
9766
|
if (st.kind === "stroke") {
|
|
9767
|
+
clearStraightStrokeHoldTimer(st);
|
|
9616
9768
|
emitRemoteStrokePreviewClear();
|
|
9617
9769
|
}
|
|
9618
9770
|
if (st.kind === "erase") {
|
|
@@ -9668,13 +9820,26 @@ var VectorViewport = react.forwardRef(
|
|
|
9668
9820
|
return;
|
|
9669
9821
|
}
|
|
9670
9822
|
if (st.kind === "stroke") {
|
|
9671
|
-
const completedPoints =
|
|
9672
|
-
st.
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9823
|
+
const completedPoints = (() => {
|
|
9824
|
+
if (st.straightLine?.active) {
|
|
9825
|
+
const endpoint = pointerSampleToWorldPoint(
|
|
9826
|
+
screenToWorld,
|
|
9827
|
+
ev.clientX,
|
|
9828
|
+
ev.clientY,
|
|
9829
|
+
ev.pointerType === "pen" ? ev.pressure : void 0
|
|
9830
|
+
);
|
|
9831
|
+
setStraightStrokeEndpoint(st, endpoint);
|
|
9832
|
+
return st.points;
|
|
9833
|
+
}
|
|
9834
|
+
const points = appendPointerEventSamplesToStrokePoints(
|
|
9835
|
+
st.points,
|
|
9836
|
+
ev,
|
|
9837
|
+
cam.zoom,
|
|
9838
|
+
screenToWorld
|
|
9839
|
+
);
|
|
9840
|
+
st.points = points;
|
|
9841
|
+
return points;
|
|
9842
|
+
})();
|
|
9678
9843
|
debugApplePencilPointer("pointerup-stroke-points", {
|
|
9679
9844
|
pointerType: ev.pointerType,
|
|
9680
9845
|
pointerId: ev.pointerId,
|
|
@@ -9861,7 +10026,9 @@ var VectorViewport = react.forwardRef(
|
|
|
9861
10026
|
renderSceneWithLivePenStroke,
|
|
9862
10027
|
releaseInteractionPointer,
|
|
9863
10028
|
requestAutoResetTool,
|
|
9864
|
-
screenToWorld
|
|
10029
|
+
screenToWorld,
|
|
10030
|
+
setStraightStrokeEndpoint,
|
|
10031
|
+
updateStraightStrokeForMove
|
|
9865
10032
|
]);
|
|
9866
10033
|
const selectedItemsForOverlay = react.useMemo(() => {
|
|
9867
10034
|
return effectiveSelectedIds.map((id) => resolvedItems.find((i) => i.id === id)).filter((i) => i != null);
|