@weasel-js/guides 1.15.0 → 1.15.2
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.js +30 -36
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useRef, useCallback, useEffect } from 'react';
|
|
2
|
-
import { sceneBoxFrames, scenePoseFrame, useLatest, viewportWorldRect, tickedSegment, measuredSegmentCommands, AUTO_POSE_DESCRIPTOR, visualBoundsViaDescriptor, rectFromPlane, unionAABB,
|
|
3
|
-
import { pointInPolygon, invert, mat3, applyToPoint, pxExtent, PATH_M, PATH_L, PATH_Z, pxExtentInFrame } from '@weasel-js/geom';
|
|
2
|
+
import { sceneBoxFrames, scenePoseFrame, useLatest, viewportWorldRect, viewWorldToScreen, tickedSegment, measuredSegmentCommands, AUTO_POSE_DESCRIPTOR, visualBoundsViaDescriptor, rectFromPlane, unionAABB, sceneMagnification, asNodeId, createTransformOp, sceneUnitScopes, screenToWorld, nodeGates, resolveStrokeWidth, resolveUnit, axisUnits, resolveScoped } from '@weasel-js/core';
|
|
3
|
+
import { pointInPolygon, invert, mat3, distance2, rectContainsPointHalfOpen, applyToPoint, pxExtent, PATH_M, PATH_L, PATH_Z, pxExtentInFrame } from '@weasel-js/geom';
|
|
4
4
|
|
|
5
5
|
// src/grid/roundToCell.ts
|
|
6
6
|
function roundToCell(value, cellSize) {
|
|
@@ -592,26 +592,27 @@ function createGuidesLayer(opts) {
|
|
|
592
592
|
const guides = opts.getGuides();
|
|
593
593
|
const gaps = opts.getGaps?.() ?? [];
|
|
594
594
|
if (guides.length === 0 && gaps.length === 0) return [];
|
|
595
|
-
const sx = (x) => (x - view.x) * view.scale.x;
|
|
596
|
-
const sy = (y) => (y - view.y) * view.scale.y;
|
|
597
595
|
const out = [];
|
|
598
596
|
for (const g of guides) {
|
|
599
597
|
const span2 = spanned ? g.span : void 0;
|
|
600
598
|
if (g.axis === "x") {
|
|
601
|
-
const
|
|
599
|
+
const lo3 = viewWorldToScreen(view, { x: g.offset, y: span2?.min ?? 0 });
|
|
600
|
+
const x = lo3.x;
|
|
602
601
|
if (x < -lineWidth || x > dims.width + lineWidth) continue;
|
|
603
|
-
const path = span2 ? tickedSegment(x,
|
|
602
|
+
const path = span2 ? tickedSegment(x, lo3.y, x, viewWorldToScreen(view, { x: g.offset, y: span2.max }).y, ticks) : tickedSegment(x, 0, x, dims.height, 0);
|
|
604
603
|
out.push({ kind: "path", path, stroke });
|
|
605
604
|
} else {
|
|
606
|
-
const
|
|
605
|
+
const lo3 = viewWorldToScreen(view, { x: span2?.min ?? 0, y: g.offset });
|
|
606
|
+
const y = lo3.y;
|
|
607
607
|
if (y < -lineWidth || y > dims.height + lineWidth) continue;
|
|
608
|
-
const path = span2 ? tickedSegment(
|
|
608
|
+
const path = span2 ? tickedSegment(lo3.x, y, viewWorldToScreen(view, { x: span2.max, y: g.offset }).x, y, ticks) : tickedSegment(0, y, dims.width, y, 0);
|
|
609
609
|
out.push({ kind: "path", path, stroke });
|
|
610
610
|
}
|
|
611
611
|
}
|
|
612
612
|
for (const g of gaps) {
|
|
613
|
-
const
|
|
614
|
-
|
|
613
|
+
const a = viewWorldToScreen(view, g.axis === "x" ? { x: g.min, y: g.at } : { x: g.at, y: g.min });
|
|
614
|
+
const b = viewWorldToScreen(view, g.axis === "x" ? { x: g.max, y: g.at } : { x: g.at, y: g.max });
|
|
615
|
+
out.push(...measuredSegmentCommands(a.x, a.y, b.x, b.y, ticks, gapStroke, format?.(g.max - g.min) ?? null, gapColor));
|
|
615
616
|
}
|
|
616
617
|
return out;
|
|
617
618
|
}
|
|
@@ -942,8 +943,6 @@ function extentAcross(q, p, axis, delta) {
|
|
|
942
943
|
const lo3 = c === "x" ? landed.x : landed.y;
|
|
943
944
|
return [lo3, lo3 + (c === "x" ? landed.width : landed.height)];
|
|
944
945
|
}
|
|
945
|
-
|
|
946
|
-
// src/sources/spacing.ts
|
|
947
946
|
var TRANSLATE = [
|
|
948
947
|
{ axis: "x", edge: "both", rate: { x: 1, y: 0 } },
|
|
949
948
|
{ axis: "y", edge: "both", rate: { x: 0, y: 1 } }
|
|
@@ -952,9 +951,9 @@ function movingSides(q) {
|
|
|
952
951
|
return q.sides ? q.sides.map((s) => ({ axis: s.axis, edge: s.side, rate: s.rate })) : TRANSLATE;
|
|
953
952
|
}
|
|
954
953
|
var measureAll = (boxes) => ({ boxes, x: measureGapSpans(boxes, "x"), y: measureGapSpans(boxes, "y") });
|
|
955
|
-
function gapMark(g, color) {
|
|
954
|
+
function gapMark(g, color, magnification) {
|
|
956
955
|
const ends = g.axis === "x" ? { from: { x: g.min, y: g.at }, to: { x: g.max, y: g.at } } : { from: { x: g.at, y: g.min }, to: { x: g.at, y: g.max } };
|
|
957
|
-
return { kind: "gap", ...ends, value: g.max - g.min, ...color === void 0 ? {} : { color } };
|
|
956
|
+
return { kind: "gap", ...ends, value: (g.max - g.min) / magnification, ...color === void 0 ? {} : { color } };
|
|
958
957
|
}
|
|
959
958
|
function spacingSnapSource(opts = {}) {
|
|
960
959
|
const fromScene = cachedPerScene(measureAll, opts.filter);
|
|
@@ -971,6 +970,7 @@ function spacingSnapSource(opts = {}) {
|
|
|
971
970
|
const reach = q.reachWorld(q.reachPx);
|
|
972
971
|
const refs = { x: referenceGaps(box, measured.x), y: referenceGaps(box, measured.y) };
|
|
973
972
|
const seen = /* @__PURE__ */ new Set();
|
|
973
|
+
const magnification = q.scene && q.ids?.length ? sceneMagnification(q.scene, q.ids.map(asNodeId)) : 1;
|
|
974
974
|
for (const { axis, edge, rate } of movingSides(q)) {
|
|
975
975
|
const speed = Math.hypot(rate.x, rate.y);
|
|
976
976
|
for (const o of spacingOffers(box, axis, edge, measured.boxes, refs[axis])) {
|
|
@@ -982,7 +982,7 @@ function spacingSnapSource(opts = {}) {
|
|
|
982
982
|
locus: sideLine(probe.at, rate, o.delta),
|
|
983
983
|
mark: (delta) => {
|
|
984
984
|
const landed = landedBox(q, delta) ?? box;
|
|
985
|
-
return equalGaps(landed, axis, o.size, measured.boxes, refs[axis]).map((g) => gapMark(g, opts.color));
|
|
985
|
+
return equalGaps(landed, axis, o.size, measured.boxes, refs[axis]).map((g) => gapMark(g, opts.color, magnification));
|
|
986
986
|
}
|
|
987
987
|
};
|
|
988
988
|
}
|
|
@@ -1033,10 +1033,13 @@ function measureAxis(from, to, axis, out) {
|
|
|
1033
1033
|
}
|
|
1034
1034
|
|
|
1035
1035
|
// src/spacingHints/distanceReadout.ts
|
|
1036
|
-
function marksOf(r, color) {
|
|
1036
|
+
function marksOf(r, color, magnification) {
|
|
1037
1037
|
const c = color === void 0 ? {} : { color };
|
|
1038
1038
|
return [
|
|
1039
|
-
...r.gaps.map((g) =>
|
|
1039
|
+
...r.gaps.map((g) => {
|
|
1040
|
+
const value = (g.max - g.min) / magnification;
|
|
1041
|
+
return g.axis === "x" ? { kind: "distance", from: { x: g.min, y: g.at }, to: { x: g.max, y: g.at }, value, ...c } : { kind: "distance", from: { x: g.at, y: g.min }, to: { x: g.at, y: g.max }, value, ...c };
|
|
1042
|
+
}),
|
|
1040
1043
|
...r.leaders.flatMap((l) => {
|
|
1041
1044
|
if (l.span === void 0) return [];
|
|
1042
1045
|
return [l.axis === "x" ? { kind: "line", from: { x: l.offset, y: l.span.min }, to: { x: l.offset, y: l.span.max }, ...c } : { kind: "line", from: { x: l.span.min, y: l.offset }, to: { x: l.span.max, y: l.offset }, ...c }];
|
|
@@ -1061,10 +1064,10 @@ function distanceReadout(opts = {}) {
|
|
|
1061
1064
|
const modifier = opts.modifier ?? "alt";
|
|
1062
1065
|
let shown = EMPTY;
|
|
1063
1066
|
let store = null;
|
|
1064
|
-
const show = (next) => {
|
|
1067
|
+
const show = (next, magnification = 1) => {
|
|
1065
1068
|
if (next === shown || next.gaps.length === 0 && shown.gaps.length === 0) return;
|
|
1066
1069
|
shown = next;
|
|
1067
|
-
store?.set(marksOf(next, opts.color));
|
|
1070
|
+
store?.set(marksOf(next, opts.color, magnification));
|
|
1068
1071
|
};
|
|
1069
1072
|
const action = {
|
|
1070
1073
|
id: `${id}.measure`,
|
|
@@ -1084,7 +1087,8 @@ function distanceReadout(opts = {}) {
|
|
|
1084
1087
|
const hit = nodeAtPoint(p.world, subtreeOf(scene, ids));
|
|
1085
1088
|
const from = worldUnionOf(scene, ids, { poseDescriptor });
|
|
1086
1089
|
const [to] = hit === null ? [] : worldBoundsOf(scene, [hit], { poseDescriptor });
|
|
1087
|
-
|
|
1090
|
+
if (from === null || to === void 0) show(EMPTY);
|
|
1091
|
+
else show(measureDistances(from, to), sceneMagnification(scene, [...ids, hit]));
|
|
1088
1092
|
}
|
|
1089
1093
|
}
|
|
1090
1094
|
};
|
|
@@ -1132,19 +1136,12 @@ function createSpacingHintsPreset(opts = {}) {
|
|
|
1132
1136
|
if (opts.readout !== false) contributions.push(distanceReadout({ ...opts.readout, ...color }));
|
|
1133
1137
|
return { id, snapSources, contributions };
|
|
1134
1138
|
}
|
|
1135
|
-
|
|
1136
|
-
// src/layout/snaps.ts
|
|
1137
|
-
function dist2(a, b) {
|
|
1138
|
-
const dx = a.x - b.x;
|
|
1139
|
-
const dy = a.y - b.y;
|
|
1140
|
-
return dx * dx + dy * dy;
|
|
1141
|
-
}
|
|
1142
1139
|
function nearestOf(targets, pointer) {
|
|
1143
1140
|
if (targets.length === 0) return null;
|
|
1144
1141
|
let best = targets[0];
|
|
1145
|
-
let bestD =
|
|
1142
|
+
let bestD = distance2(best.origin, pointer);
|
|
1146
1143
|
for (let i = 1; i < targets.length; i++) {
|
|
1147
|
-
const d =
|
|
1144
|
+
const d = distance2(targets[i].origin, pointer);
|
|
1148
1145
|
if (d < bestD) {
|
|
1149
1146
|
bestD = d;
|
|
1150
1147
|
best = targets[i];
|
|
@@ -1164,18 +1161,15 @@ function nearestWithin(opts) {
|
|
|
1164
1161
|
pickTarget(targets, pointer) {
|
|
1165
1162
|
const got = nearestOf(targets, pointer);
|
|
1166
1163
|
if (got === null) return null;
|
|
1167
|
-
return
|
|
1164
|
+
return distance2(got.origin, pointer) <= tol2 ? got : null;
|
|
1168
1165
|
}
|
|
1169
1166
|
};
|
|
1170
1167
|
}
|
|
1171
|
-
function rectContains(r, p) {
|
|
1172
|
-
return p.x >= r.x && p.x < r.x + r.width && p.y >= r.y && p.y < r.y + r.height;
|
|
1173
|
-
}
|
|
1174
1168
|
function containedThenNearest() {
|
|
1175
1169
|
return {
|
|
1176
1170
|
pickTarget(targets, pointer) {
|
|
1177
1171
|
for (const t of targets) {
|
|
1178
|
-
if (t.hitBounds &&
|
|
1172
|
+
if (t.hitBounds && rectContainsPointHalfOpen(t.hitBounds, pointer.x, pointer.y)) return t;
|
|
1179
1173
|
}
|
|
1180
1174
|
return nearestOf(targets, pointer);
|
|
1181
1175
|
}
|
|
@@ -1188,8 +1182,8 @@ function cellAt() {
|
|
|
1188
1182
|
return {
|
|
1189
1183
|
pickTarget(targets, pointer) {
|
|
1190
1184
|
for (const t of targets) {
|
|
1191
|
-
if (t.hitBounds &&
|
|
1192
|
-
if (isCellMeta(t.meta) &&
|
|
1185
|
+
if (t.hitBounds && rectContainsPointHalfOpen(t.hitBounds, pointer.x, pointer.y)) return t;
|
|
1186
|
+
if (isCellMeta(t.meta) && rectContainsPointHalfOpen(t.meta.cellRect, pointer.x, pointer.y)) return t;
|
|
1193
1187
|
}
|
|
1194
1188
|
return nearestOf(targets, pointer);
|
|
1195
1189
|
}
|