@canvas-harness/core 0.1.5 → 0.1.6
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 +39 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +39 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1454,9 +1454,33 @@ type InteractionState = {
|
|
|
1454
1454
|
resizeLockAspect: boolean;
|
|
1455
1455
|
/** Whether the user is holding Alt during a resize (resize from center). */
|
|
1456
1456
|
resizeFromCenter: boolean;
|
|
1457
|
+
/**
|
|
1458
|
+
* Live in-progress geometry of the resized node — written every
|
|
1459
|
+
* pointermove, committed to the store once on pointer-up. While
|
|
1460
|
+
* present, `store.getNode(id)` still returns the original geometry;
|
|
1461
|
+
* the renderer overlays this draft via `mapDragPositions` for the
|
|
1462
|
+
* interactive layer paint. Mirrors how `dragDelta` works for drag.
|
|
1463
|
+
*/
|
|
1464
|
+
resizeDraft: {
|
|
1465
|
+
x: number;
|
|
1466
|
+
y: number;
|
|
1467
|
+
w: number;
|
|
1468
|
+
h: number;
|
|
1469
|
+
angle: number;
|
|
1470
|
+
} | null;
|
|
1457
1471
|
marqueeRect: WorldRect | null;
|
|
1458
1472
|
/** Whether the marquee should add to (true, shift held) or replace selection. */
|
|
1459
1473
|
marqueeAdditive: boolean;
|
|
1474
|
+
/**
|
|
1475
|
+
* Live in-progress cubic controls of an edge being mid-point-dragged.
|
|
1476
|
+
* Written every pointermove, committed to the store once on
|
|
1477
|
+
* pointer-up. Same draft+commit model as `resizeDraft` and
|
|
1478
|
+
* `dragDelta` — keeps mid-gesture mutations off the 'change' bus.
|
|
1479
|
+
*/
|
|
1480
|
+
midpointDraft: {
|
|
1481
|
+
edgeId: EdgeId;
|
|
1482
|
+
control: [Vec2, Vec2];
|
|
1483
|
+
} | null;
|
|
1460
1484
|
draftEdge: {
|
|
1461
1485
|
source: EdgeEnd;
|
|
1462
1486
|
target: EdgeEnd;
|
package/dist/index.d.ts
CHANGED
|
@@ -1454,9 +1454,33 @@ type InteractionState = {
|
|
|
1454
1454
|
resizeLockAspect: boolean;
|
|
1455
1455
|
/** Whether the user is holding Alt during a resize (resize from center). */
|
|
1456
1456
|
resizeFromCenter: boolean;
|
|
1457
|
+
/**
|
|
1458
|
+
* Live in-progress geometry of the resized node — written every
|
|
1459
|
+
* pointermove, committed to the store once on pointer-up. While
|
|
1460
|
+
* present, `store.getNode(id)` still returns the original geometry;
|
|
1461
|
+
* the renderer overlays this draft via `mapDragPositions` for the
|
|
1462
|
+
* interactive layer paint. Mirrors how `dragDelta` works for drag.
|
|
1463
|
+
*/
|
|
1464
|
+
resizeDraft: {
|
|
1465
|
+
x: number;
|
|
1466
|
+
y: number;
|
|
1467
|
+
w: number;
|
|
1468
|
+
h: number;
|
|
1469
|
+
angle: number;
|
|
1470
|
+
} | null;
|
|
1457
1471
|
marqueeRect: WorldRect | null;
|
|
1458
1472
|
/** Whether the marquee should add to (true, shift held) or replace selection. */
|
|
1459
1473
|
marqueeAdditive: boolean;
|
|
1474
|
+
/**
|
|
1475
|
+
* Live in-progress cubic controls of an edge being mid-point-dragged.
|
|
1476
|
+
* Written every pointermove, committed to the store once on
|
|
1477
|
+
* pointer-up. Same draft+commit model as `resizeDraft` and
|
|
1478
|
+
* `dragDelta` — keeps mid-gesture mutations off the 'change' bus.
|
|
1479
|
+
*/
|
|
1480
|
+
midpointDraft: {
|
|
1481
|
+
edgeId: EdgeId;
|
|
1482
|
+
control: [Vec2, Vec2];
|
|
1483
|
+
} | null;
|
|
1460
1484
|
draftEdge: {
|
|
1461
1485
|
source: EdgeEnd;
|
|
1462
1486
|
target: EdgeEnd;
|
package/dist/index.js
CHANGED
|
@@ -1048,7 +1048,6 @@ var COMPOSITE = /* @__PURE__ */ new Set([
|
|
|
1048
1048
|
var isCompositePrimitive = (type) => COMPOSITE.has(type);
|
|
1049
1049
|
var isDrawablePrimitive = (type) => ATOMIC.has(type) || COMPOSITE.has(type);
|
|
1050
1050
|
var PLAIN_RECT_CORNER_THRESHOLD_PX = 1.5;
|
|
1051
|
-
var STROKE_VISIBILITY_THRESHOLD_PX = 0.5;
|
|
1052
1051
|
var LAYERED_OFFSET = 12;
|
|
1053
1052
|
var drawShape = (ctx, node, scale, theme, opts) => {
|
|
1054
1053
|
if (!isDrawablePrimitive(node.type)) return;
|
|
@@ -1067,7 +1066,7 @@ var drawAtomic = (ctx, type, w, h, style, scale, theme, opts) => {
|
|
|
1067
1066
|
const fill = resolveColor(style, "backgroundColor", DEFAULT_STYLE.backgroundColor, theme);
|
|
1068
1067
|
const stroke = resolveColor(style, "strokeColor", DEFAULT_STYLE.strokeColor, theme);
|
|
1069
1068
|
const fillVisible = !isFullyTransparent(fill);
|
|
1070
|
-
const strokeVisible = strokeWidth > 0 &&
|
|
1069
|
+
const strokeVisible = strokeWidth > 0 && !isFullyTransparent(stroke);
|
|
1071
1070
|
if (!fillVisible && !strokeVisible) return;
|
|
1072
1071
|
const cornerRadius = (style?.roundness ?? DEFAULT_STYLE.roundness) * 4;
|
|
1073
1072
|
switch (type) {
|
|
@@ -1104,7 +1103,7 @@ var drawAtomic = (ctx, type, w, h, style, scale, theme, opts) => {
|
|
|
1104
1103
|
}
|
|
1105
1104
|
if (strokeVisible && !opts?.skipStroke) {
|
|
1106
1105
|
ctx.strokeStyle = stroke;
|
|
1107
|
-
ctx.lineWidth = strokeWidth;
|
|
1106
|
+
ctx.lineWidth = Math.max(strokeWidth, 1 / scale);
|
|
1108
1107
|
ctx.setLineDash(dashPatternFor(style?.strokeStyle, strokeWidth));
|
|
1109
1108
|
ctx.stroke();
|
|
1110
1109
|
}
|
|
@@ -1480,13 +1479,16 @@ var paintAtomicRough = (rc, ctx, type, w, h, style, scale, theme, seed) => {
|
|
|
1480
1479
|
const isDark = theme?.("mode") === "dark";
|
|
1481
1480
|
const fill = resolveColor(style, "backgroundColor", DEFAULT_STYLE.backgroundColor, theme);
|
|
1482
1481
|
const strokeColor = deriveRoughStrokeColor(rawStroke, fill, isDark);
|
|
1483
|
-
const
|
|
1484
|
-
if (
|
|
1482
|
+
const rawStrokeWidth = resolveStrokeWidth(style, theme);
|
|
1483
|
+
if (rawStrokeWidth <= 0) return;
|
|
1485
1484
|
const roughness = style?.roughness ?? 0;
|
|
1486
1485
|
if (roughness <= 0) return;
|
|
1486
|
+
const isNoBorderIntent = isFullyTransparent(rawStroke);
|
|
1487
|
+
const effectiveStrokeStyle = isNoBorderIntent ? "solid" : style?.strokeStyle ?? "solid";
|
|
1488
|
+
const strokeWidth = isNoBorderIntent ? DEFAULT_STYLE.strokeWidth : rawStrokeWidth;
|
|
1487
1489
|
const cornerRadius = (style?.roundness ?? DEFAULT_STYLE.roundness) * 4;
|
|
1488
1490
|
const radius = Math.max(0, Math.min(cornerRadius, w / 2, h / 2));
|
|
1489
|
-
const dash = dashPatternFor(
|
|
1491
|
+
const dash = dashPatternFor(effectiveStrokeStyle, strokeWidth);
|
|
1490
1492
|
const detail = apparentDetail(Math.max(w, h), scale);
|
|
1491
1493
|
const cacheKey = [
|
|
1492
1494
|
type,
|
|
@@ -1495,7 +1497,7 @@ var paintAtomicRough = (rc, ctx, type, w, h, style, scale, theme, seed) => {
|
|
|
1495
1497
|
radius.toFixed(1),
|
|
1496
1498
|
strokeColor,
|
|
1497
1499
|
strokeWidth.toFixed(2),
|
|
1498
|
-
|
|
1500
|
+
effectiveStrokeStyle,
|
|
1499
1501
|
roughness.toFixed(2),
|
|
1500
1502
|
seed,
|
|
1501
1503
|
detail.curveStepCount,
|
|
@@ -2646,7 +2648,7 @@ var DEFAULT_EDGE_STYLE = {
|
|
|
2646
2648
|
sourceArrowhead: "none",
|
|
2647
2649
|
targetArrowhead: "arrow-filled"
|
|
2648
2650
|
};
|
|
2649
|
-
var
|
|
2651
|
+
var STROKE_VISIBILITY_THRESHOLD_PX = 0.5;
|
|
2650
2652
|
var ARROWHEAD_VISIBILITY_THRESHOLD_PX = 2;
|
|
2651
2653
|
var samplePaintStride = (scale) => {
|
|
2652
2654
|
if (scale < 0.15) return 8;
|
|
@@ -2660,7 +2662,7 @@ var drawEdge = (ctx, edge, geom, sourceNode, targetNode, scale, theme, opts) =>
|
|
|
2660
2662
|
if (samples.length < 2) return;
|
|
2661
2663
|
const style = edge.style;
|
|
2662
2664
|
const strokeWidth = typeof style?.strokeWidth === "number" ? style.strokeWidth : theme?.("strokeWidth") ?? DEFAULT_EDGE_STYLE.strokeWidth;
|
|
2663
|
-
if (strokeWidth * scale <
|
|
2665
|
+
if (strokeWidth * scale < STROKE_VISIBILITY_THRESHOLD_PX) return;
|
|
2664
2666
|
const strokeColor = typeof style?.strokeColor === "string" ? style.strokeColor : theme?.("edge.strokeColor") ?? DEFAULT_EDGE_STYLE.strokeColor;
|
|
2665
2667
|
const sourceArrowhead = style?.sourceArrowhead ?? DEFAULT_EDGE_STYLE.sourceArrowhead;
|
|
2666
2668
|
const targetArrowhead = style?.targetArrowhead ?? DEFAULT_EDGE_STYLE.targetArrowhead;
|
|
@@ -3376,6 +3378,8 @@ var idleInteractionState = () => ({
|
|
|
3376
3378
|
resizeHandle: null,
|
|
3377
3379
|
resizeLockAspect: false,
|
|
3378
3380
|
resizeFromCenter: false,
|
|
3381
|
+
resizeDraft: null,
|
|
3382
|
+
midpointDraft: null,
|
|
3379
3383
|
marqueeRect: null,
|
|
3380
3384
|
marqueeAdditive: false,
|
|
3381
3385
|
draftEdge: null,
|
|
@@ -4952,7 +4956,9 @@ var createRenderer = (opts) => {
|
|
|
4952
4956
|
const scale = camera.z * surface.dpr;
|
|
4953
4957
|
const interaction = store.getInteractionState();
|
|
4954
4958
|
const excludedNodes = interaction.mode === "dragging" || interaction.mode === "resizing" ? new Set(interaction.draggedIds) : null;
|
|
4955
|
-
const
|
|
4959
|
+
const baseExcludedEdges = excludedNodes ? incidentEdgeIds(excludedNodes) : null;
|
|
4960
|
+
const midpointEdgeId = interaction.midpointDraft?.edgeId ?? null;
|
|
4961
|
+
const excludedEdges = midpointEdgeId !== null ? /* @__PURE__ */ new Set([...baseExcludedEdges ?? [], midpointEdgeId]) : baseExcludedEdges;
|
|
4956
4962
|
paintBackground(surface.ctx, { viewport, zoom: camera.z, background });
|
|
4957
4963
|
const visible = visibleNodes(camera, viewport);
|
|
4958
4964
|
const isMoving2 = interaction.mode === "panning" || interaction.mode === "zooming" || interaction.mode === "dragging" || interaction.mode === "resizing" || interaction.mode === "rotating";
|
|
@@ -5364,6 +5370,23 @@ var createRenderer = (opts) => {
|
|
|
5364
5370
|
}
|
|
5365
5371
|
}
|
|
5366
5372
|
}
|
|
5373
|
+
if (interaction.midpointDraft) {
|
|
5374
|
+
const { edgeId, control } = interaction.midpointDraft;
|
|
5375
|
+
const edge = store.getEdge(edgeId);
|
|
5376
|
+
if (edge) {
|
|
5377
|
+
const draftEdge = { ...edge, control };
|
|
5378
|
+
const geom = computeEdgeGeometry(draftEdge, (id) => store.getNode(id));
|
|
5379
|
+
if (geom) {
|
|
5380
|
+
const sourceNode = geom.sourceNodeId ? store.getNode(geom.sourceNodeId) ?? null : null;
|
|
5381
|
+
const targetNode = geom.targetNodeId ? store.getNode(geom.targetNodeId) ?? null : null;
|
|
5382
|
+
drawEdge(ctx, draftEdge, geom, sourceNode, targetNode, scale, theme, {
|
|
5383
|
+
zoom: camera.z,
|
|
5384
|
+
dpr: interactiveSurface.dpr,
|
|
5385
|
+
isMoving: true
|
|
5386
|
+
});
|
|
5387
|
+
}
|
|
5388
|
+
}
|
|
5389
|
+
}
|
|
5367
5390
|
const selection = store.getSelection();
|
|
5368
5391
|
const selectedNodeIds = [];
|
|
5369
5392
|
const selectedEdgeIds = [];
|
|
@@ -5436,7 +5459,12 @@ var createRenderer = (opts) => {
|
|
|
5436
5459
|
y: orig.y + interaction.dragDelta.y
|
|
5437
5460
|
});
|
|
5438
5461
|
} else {
|
|
5439
|
-
|
|
5462
|
+
const d = interaction.resizeDraft;
|
|
5463
|
+
if (d) {
|
|
5464
|
+
m.set(orig.id, { ...live, x: d.x, y: d.y, w: d.w, h: d.h, angle: d.angle });
|
|
5465
|
+
} else {
|
|
5466
|
+
m.set(orig.id, live);
|
|
5467
|
+
}
|
|
5440
5468
|
}
|
|
5441
5469
|
}
|
|
5442
5470
|
return m;
|