@oh-just-another/scene 0.57.0
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/CHANGELOG.md +13 -0
- package/LICENSE +21 -0
- package/README.md +72 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/a11y.d.ts +23 -0
- package/dist/a11y.d.ts.map +1 -0
- package/dist/a11y.js +37 -0
- package/dist/a11y.js.map +1 -0
- package/dist/anchors.d.ts +120 -0
- package/dist/anchors.d.ts.map +1 -0
- package/dist/anchors.js +322 -0
- package/dist/anchors.js.map +1 -0
- package/dist/annotation-geometry.d.ts +11 -0
- package/dist/annotation-geometry.d.ts.map +1 -0
- package/dist/annotation-geometry.js +19 -0
- package/dist/annotation-geometry.js.map +1 -0
- package/dist/annotation.d.ts +32 -0
- package/dist/annotation.d.ts.map +1 -0
- package/dist/annotation.js +2 -0
- package/dist/annotation.js.map +1 -0
- package/dist/constants.d.ts +186 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +186 -0
- package/dist/constants.js.map +1 -0
- package/dist/container.d.ts +112 -0
- package/dist/container.d.ts.map +1 -0
- package/dist/container.js +227 -0
- package/dist/container.js.map +1 -0
- package/dist/diff.d.ts +22 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +18 -0
- package/dist/diff.js.map +1 -0
- package/dist/edge-curve.d.ts +37 -0
- package/dist/edge-curve.d.ts.map +1 -0
- package/dist/edge-curve.js +72 -0
- package/dist/edge-curve.js.map +1 -0
- package/dist/edge-geometry.d.ts +96 -0
- package/dist/edge-geometry.d.ts.map +1 -0
- package/dist/edge-geometry.js +467 -0
- package/dist/edge-geometry.js.map +1 -0
- package/dist/edge.d.ts +206 -0
- package/dist/edge.d.ts.map +1 -0
- package/dist/edge.js +2 -0
- package/dist/edge.js.map +1 -0
- package/dist/elbow-link.d.ts +23 -0
- package/dist/elbow-link.d.ts.map +1 -0
- package/dist/elbow-link.js +419 -0
- package/dist/elbow-link.js.map +1 -0
- package/dist/elbow-router.d.ts +20 -0
- package/dist/elbow-router.d.ts.map +1 -0
- package/dist/elbow-router.js +218 -0
- package/dist/elbow-router.js.map +1 -0
- package/dist/file.d.ts +41 -0
- package/dist/file.d.ts.map +1 -0
- package/dist/file.js +13 -0
- package/dist/file.js.map +1 -0
- package/dist/heading.d.ts +42 -0
- package/dist/heading.d.ts.map +1 -0
- package/dist/heading.js +77 -0
- package/dist/heading.js.map +1 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/layer.d.ts +18 -0
- package/dist/layer.d.ts.map +1 -0
- package/dist/layer.js +2 -0
- package/dist/layer.js.map +1 -0
- package/dist/layout-registry.d.ts +35 -0
- package/dist/layout-registry.d.ts.map +1 -0
- package/dist/layout-registry.js +13 -0
- package/dist/layout-registry.js.map +1 -0
- package/dist/layout.d.ts +128 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +453 -0
- package/dist/layout.js.map +1 -0
- package/dist/operations.d.ts +32 -0
- package/dist/operations.d.ts.map +1 -0
- package/dist/operations.js +105 -0
- package/dist/operations.js.map +1 -0
- package/dist/outline.d.ts +36 -0
- package/dist/outline.d.ts.map +1 -0
- package/dist/outline.js +129 -0
- package/dist/outline.js.map +1 -0
- package/dist/patch.d.ts +57 -0
- package/dist/patch.d.ts.map +1 -0
- package/dist/patch.js +47 -0
- package/dist/patch.js.map +1 -0
- package/dist/queries.d.ts +115 -0
- package/dist/queries.d.ts.map +1 -0
- package/dist/queries.js +403 -0
- package/dist/queries.js.map +1 -0
- package/dist/render-bounds.d.ts +36 -0
- package/dist/render-bounds.d.ts.map +1 -0
- package/dist/render-bounds.js +36 -0
- package/dist/render-bounds.js.map +1 -0
- package/dist/scene.d.ts +80 -0
- package/dist/scene.d.ts.map +1 -0
- package/dist/scene.js +129 -0
- package/dist/scene.js.map +1 -0
- package/dist/shape.d.ts +306 -0
- package/dist/shape.d.ts.map +1 -0
- package/dist/shape.js +192 -0
- package/dist/shape.js.map +1 -0
- package/dist/snap.d.ts +88 -0
- package/dist/snap.d.ts.map +1 -0
- package/dist/snap.js +128 -0
- package/dist/snap.js.map +1 -0
- package/dist/spatial.d.ts +38 -0
- package/dist/spatial.d.ts.map +1 -0
- package/dist/spatial.js +95 -0
- package/dist/spatial.js.map +1 -0
- package/dist/style.d.ts +87 -0
- package/dist/style.d.ts.map +1 -0
- package/dist/style.js +43 -0
- package/dist/style.js.map +1 -0
- package/dist/text-measure.d.ts +29 -0
- package/dist/text-measure.d.ts.map +1 -0
- package/dist/text-measure.js +8 -0
- package/dist/text-measure.js.map +1 -0
- package/dist/three-way-merge.d.ts +59 -0
- package/dist/three-way-merge.d.ts.map +1 -0
- package/dist/three-way-merge.js +108 -0
- package/dist/three-way-merge.js.map +1 -0
- package/dist/viewport.d.ts +78 -0
- package/dist/viewport.d.ts.map +1 -0
- package/dist/viewport.js +62 -0
- package/dist/viewport.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A*-based elbow router (Manhattan / 90° segments that detour
|
|
3
|
+
* around obstacle bboxes).
|
|
4
|
+
*
|
|
5
|
+
* Self-contained and pure: takes `from`, `to`, an `obstacles[]` list of world-
|
|
6
|
+
* space bboxes (the source / target shapes typically), and returns
|
|
7
|
+
* the polyline of axis-aligned bends — or `null` when no path
|
|
8
|
+
* exists (degenerate: same point).
|
|
9
|
+
*
|
|
10
|
+
* Algorithm:
|
|
11
|
+
* 1. Build a candidate-point set: from, to, and the four
|
|
12
|
+
* corners of each obstacle bbox inflated by `MARGIN` so
|
|
13
|
+
* the path runs *around* the box, not on its edge. Links
|
|
14
|
+
* whose two endpoints lie on the same axis (same x or same
|
|
15
|
+
* y) and don't cross any obstacle's interior become graph
|
|
16
|
+
* edges with cost = Manhattan distance.
|
|
17
|
+
* 2. A* with Manhattan-distance heuristic from `from` to `to`.
|
|
18
|
+
* 3. Post-process: collapse colinear waypoints so the returned
|
|
19
|
+
* path is the minimal bend list.
|
|
20
|
+
*
|
|
21
|
+
* The router is not a global optimum — A* on this sparse graph
|
|
22
|
+
* gives a "good enough" detour without the O(N²) cost of a full
|
|
23
|
+
* visibility graph.
|
|
24
|
+
*/
|
|
25
|
+
import { ELBOW_OBSTACLE_MARGIN, ELBOW_OBSTACLE_INTERIOR_EPSILON, ELBOW_BEND_PENALTY, } from "./constants.js";
|
|
26
|
+
const req = (v) => {
|
|
27
|
+
if (v === undefined)
|
|
28
|
+
throw new Error("packages/scene: index out of range");
|
|
29
|
+
return v;
|
|
30
|
+
};
|
|
31
|
+
const MARGIN = ELBOW_OBSTACLE_MARGIN;
|
|
32
|
+
const INTERIOR_EPS = ELBOW_OBSTACLE_INTERIOR_EPSILON;
|
|
33
|
+
const BEND_PENALTY = ELBOW_BEND_PENALTY;
|
|
34
|
+
export const elbowRoute = (from, to, obstacles, options = {}) => {
|
|
35
|
+
if (eq(from, to))
|
|
36
|
+
return [from];
|
|
37
|
+
const margin = options.margin ?? MARGIN;
|
|
38
|
+
const inflated = obstacles.map((b) => inflate(b, margin));
|
|
39
|
+
const startHeading = options.startHeading;
|
|
40
|
+
const endHeading = options.endHeading;
|
|
41
|
+
// Candidate axes — every unique x and y value from endpoints + bbox
|
|
42
|
+
// corners. The router walks the implicit grid those axes form.
|
|
43
|
+
const xs = new Set([from.x, to.x]);
|
|
44
|
+
const ys = new Set([from.y, to.y]);
|
|
45
|
+
for (const b of inflated) {
|
|
46
|
+
xs.add(b.x);
|
|
47
|
+
xs.add(b.x + b.width);
|
|
48
|
+
ys.add(b.y);
|
|
49
|
+
ys.add(b.y + b.height);
|
|
50
|
+
}
|
|
51
|
+
const xList = [...xs].sort((a, b) => a - b);
|
|
52
|
+
const yList = [...ys].sort((a, b) => a - b);
|
|
53
|
+
// Each node is "(xIndex,yIndex)" packed into one string for Map keys.
|
|
54
|
+
const nodeKey = (xi, yi) => `${xi},${yi}`;
|
|
55
|
+
const xOfIdx = (xi) => req(xList[xi]);
|
|
56
|
+
const yOfIdx = (yi) => req(yList[yi]);
|
|
57
|
+
const startXi = xList.indexOf(from.x);
|
|
58
|
+
const startYi = yList.indexOf(from.y);
|
|
59
|
+
const endXi = xList.indexOf(to.x);
|
|
60
|
+
const endYi = yList.indexOf(to.y);
|
|
61
|
+
// Manhattan heuristic — admissible on a grid with 90° edges.
|
|
62
|
+
const h = (xi, yi) => Math.abs(xOfIdx(xi) - xOfIdx(endXi)) + Math.abs(yOfIdx(yi) - yOfIdx(endYi));
|
|
63
|
+
const startNode = nodeKey(startXi, startYi);
|
|
64
|
+
const open = [
|
|
65
|
+
{ key: startNode, skey: `${startNode},0`, xi: startXi, yi: startYi, axis: 0, g: 0, f: h(startXi, startYi) },
|
|
66
|
+
];
|
|
67
|
+
// cameFrom / gScore keyed by *state* (node + arrival axis) so a node can be
|
|
68
|
+
// reached from both axes with different bend costs.
|
|
69
|
+
const cameFrom = new Map();
|
|
70
|
+
const gScore = new Map([[`${startNode},0`, 0]]);
|
|
71
|
+
while (open.length > 0) {
|
|
72
|
+
// Extract-min with a deterministic tie-break (f, then g, then key).
|
|
73
|
+
open.sort((a, b) => a.f - b.f || a.g - b.g || (a.skey < b.skey ? -1 : 1));
|
|
74
|
+
const cur = req(open.shift());
|
|
75
|
+
if (cur.xi === endXi && cur.yi === endYi) {
|
|
76
|
+
return reconstructPath(cameFrom, cur.skey, xOfIdx, yOfIdx);
|
|
77
|
+
}
|
|
78
|
+
for (const next of neighbours(cur.xi, cur.yi, xList.length, yList.length)) {
|
|
79
|
+
const fromPt = { x: xOfIdx(cur.xi), y: yOfIdx(cur.yi) };
|
|
80
|
+
const toPt = { x: xOfIdx(next.xi), y: yOfIdx(next.yi) };
|
|
81
|
+
if (segmentCrossesObstacle(fromPt, toPt, inflated))
|
|
82
|
+
continue;
|
|
83
|
+
const stepX = Math.sign(toPt.x - fromPt.x);
|
|
84
|
+
const stepY = Math.sign(toPt.y - fromPt.y);
|
|
85
|
+
// Don't let the very first move reverse the start buffer (would retrace
|
|
86
|
+
// the terminal stub) …
|
|
87
|
+
if (cur.axis === 0 &&
|
|
88
|
+
startHeading &&
|
|
89
|
+
stepX === -Math.sign(startHeading.x) &&
|
|
90
|
+
stepY === -Math.sign(startHeading.y)) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
// … and don't arrive at the goal travelling along the end-buffer heading
|
|
94
|
+
// (would make bufB→to double back).
|
|
95
|
+
if (next.xi === endXi &&
|
|
96
|
+
next.yi === endYi &&
|
|
97
|
+
endHeading &&
|
|
98
|
+
stepX === Math.sign(endHeading.x) &&
|
|
99
|
+
stepY === Math.sign(endHeading.y)) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
const stepAxis = next.xi !== cur.xi ? 1 : 2;
|
|
103
|
+
const stepCost = Math.abs(fromPt.x - toPt.x) + Math.abs(fromPt.y - toPt.y);
|
|
104
|
+
const turn = cur.axis !== 0 && cur.axis !== stepAxis ? BEND_PENALTY : 0;
|
|
105
|
+
const tentative = cur.g + stepCost + turn;
|
|
106
|
+
const nodeK = nodeKey(next.xi, next.yi);
|
|
107
|
+
const stateK = `${nodeK},${stepAxis}`;
|
|
108
|
+
const prev = gScore.get(stateK);
|
|
109
|
+
if (prev !== undefined && tentative >= prev)
|
|
110
|
+
continue;
|
|
111
|
+
gScore.set(stateK, tentative);
|
|
112
|
+
cameFrom.set(stateK, cur.skey);
|
|
113
|
+
open.push({
|
|
114
|
+
key: nodeK,
|
|
115
|
+
skey: stateK,
|
|
116
|
+
xi: next.xi,
|
|
117
|
+
yi: next.yi,
|
|
118
|
+
axis: stepAxis,
|
|
119
|
+
g: tentative,
|
|
120
|
+
f: tentative + h(next.xi, next.yi),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// No path — caller falls back to a direct elbow.
|
|
125
|
+
return null;
|
|
126
|
+
};
|
|
127
|
+
const eq = (a, b) => a.x === b.x && a.y === b.y;
|
|
128
|
+
const inflate = (b, m) => ({
|
|
129
|
+
x: b.x - m,
|
|
130
|
+
y: b.y - m,
|
|
131
|
+
width: b.width + 2 * m,
|
|
132
|
+
height: b.height + 2 * m,
|
|
133
|
+
});
|
|
134
|
+
/**
|
|
135
|
+
* Neighbours: the four orthogonal grid steps. We don't enumerate
|
|
136
|
+
* every possible (xi, yi) target — only ±1 on one axis. That
|
|
137
|
+
* yields a path that walks the axis-aligned grid one cell at a
|
|
138
|
+
* time, and the colinear-collapse pass at the end strips the
|
|
139
|
+
* intermediate waypoints.
|
|
140
|
+
*/
|
|
141
|
+
const neighbours = (xi, yi, xLen, yLen) => {
|
|
142
|
+
const out = [];
|
|
143
|
+
if (xi > 0)
|
|
144
|
+
out.push({ xi: xi - 1, yi });
|
|
145
|
+
if (xi < xLen - 1)
|
|
146
|
+
out.push({ xi: xi + 1, yi });
|
|
147
|
+
if (yi > 0)
|
|
148
|
+
out.push({ xi, yi: yi - 1 });
|
|
149
|
+
if (yi < yLen - 1)
|
|
150
|
+
out.push({ xi, yi: yi + 1 });
|
|
151
|
+
return out;
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* Returns `true` when the axis-aligned segment `from → to` passes
|
|
155
|
+
* through the *interior* of any obstacle. Link-on contact (the
|
|
156
|
+
* segment runs along the bbox boundary) is allowed — that's the
|
|
157
|
+
* whole point of the margin inflate.
|
|
158
|
+
*/
|
|
159
|
+
const segmentCrossesObstacle = (from, to, obstacles) => {
|
|
160
|
+
const minX = Math.min(from.x, to.x);
|
|
161
|
+
const maxX = Math.max(from.x, to.x);
|
|
162
|
+
const minY = Math.min(from.y, to.y);
|
|
163
|
+
const maxY = Math.max(from.y, to.y);
|
|
164
|
+
for (const o of obstacles) {
|
|
165
|
+
const oMaxX = o.x + o.width;
|
|
166
|
+
const oMaxY = o.y + o.height;
|
|
167
|
+
// Bounding-box check first.
|
|
168
|
+
if (maxX <= o.x || minX >= oMaxX || maxY <= o.y || minY >= oMaxY)
|
|
169
|
+
continue;
|
|
170
|
+
// Touching along an edge — allowed.
|
|
171
|
+
if (maxX - o.x <= INTERIOR_EPS ||
|
|
172
|
+
oMaxX - minX <= INTERIOR_EPS ||
|
|
173
|
+
maxY - o.y <= INTERIOR_EPS ||
|
|
174
|
+
oMaxY - minY <= INTERIOR_EPS) {
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
return false;
|
|
180
|
+
};
|
|
181
|
+
const reconstructPath = (cameFrom, endKey, xOfIdx, yOfIdx) => {
|
|
182
|
+
const path = [];
|
|
183
|
+
const seen = new Set();
|
|
184
|
+
let cursor = endKey;
|
|
185
|
+
// Guard against a malformed cameFrom (a predecessor cycle) — follow each
|
|
186
|
+
// state at most once. With positive edge weights the chain is always a tree,
|
|
187
|
+
// but this makes a hang structurally impossible regardless.
|
|
188
|
+
while (cursor && !seen.has(cursor)) {
|
|
189
|
+
seen.add(cursor);
|
|
190
|
+
const parts = cursor.split(",").map(Number);
|
|
191
|
+
path.unshift({ x: xOfIdx(req(parts[0])), y: yOfIdx(req(parts[1])) });
|
|
192
|
+
cursor = cameFrom.get(cursor);
|
|
193
|
+
}
|
|
194
|
+
return collapseColinear(path);
|
|
195
|
+
};
|
|
196
|
+
/**
|
|
197
|
+
* Drop intermediate points on an axis-aligned polyline that lie
|
|
198
|
+
* between their neighbours on the same axis. Three colinear points
|
|
199
|
+
* → keep first and third.
|
|
200
|
+
*/
|
|
201
|
+
const collapseColinear = (points) => {
|
|
202
|
+
if (points.length <= 2)
|
|
203
|
+
return points;
|
|
204
|
+
const out = [req(points[0])];
|
|
205
|
+
for (let i = 1; i < points.length - 1; i++) {
|
|
206
|
+
const prev = req(points[i - 1]);
|
|
207
|
+
const cur = req(points[i]);
|
|
208
|
+
const next = req(points[i + 1]);
|
|
209
|
+
const horizontal = prev.y === cur.y && cur.y === next.y;
|
|
210
|
+
const vertical = prev.x === cur.x && cur.x === next.x;
|
|
211
|
+
if (horizontal || vertical)
|
|
212
|
+
continue;
|
|
213
|
+
out.push(cur);
|
|
214
|
+
}
|
|
215
|
+
out.push(req(points[points.length - 1]));
|
|
216
|
+
return out;
|
|
217
|
+
};
|
|
218
|
+
//# sourceMappingURL=elbow-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"elbow-router.js","sourceRoot":"","sources":["../src/elbow-router.ts"],"names":[],"mappings":"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"}
|
package/dist/file.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { FileId } from "@oh-just-another/types";
|
|
2
|
+
/**
|
|
3
|
+
* Binary file entry stored in `Scene.files`. An `ImageElement` (or
|
|
4
|
+
* other binary-bearing shape type) carries just a `fileId` and
|
|
5
|
+
* resolves through this registry at render time. The actual bytes
|
|
6
|
+
* live here once, regardless of how many shapes reference them.
|
|
7
|
+
*
|
|
8
|
+
* Storage shape is intentionally minimal:
|
|
9
|
+
*
|
|
10
|
+
* • `mime` — content type ("image/png", "image/jpeg", "image/svg+xml", …)
|
|
11
|
+
* • `data` — the bytes themselves (`ArrayBuffer` so it serialises
|
|
12
|
+
* cleanly through `structuredClone`, IndexedDB, postMessage; SVG
|
|
13
|
+
* files can also use a UTF-8 encoded string round-tripped through
|
|
14
|
+
* `TextEncoder.encode().buffer`).
|
|
15
|
+
* • `name` — original filename when known, useful for downloads /
|
|
16
|
+
* export menus / accessible labels.
|
|
17
|
+
* • `createdAt` — millisecond timestamp; lets hosts age out caches
|
|
18
|
+
* and surface "added today" in file pickers.
|
|
19
|
+
*
|
|
20
|
+
* The serializer pipeline writes `files` to a separate sidecar so a
|
|
21
|
+
* pure-text scene.json stays small; on import the host re-attaches
|
|
22
|
+
* the sidecar and the shapes resolve their `fileId` lookups again.
|
|
23
|
+
*/
|
|
24
|
+
export interface BinaryFile {
|
|
25
|
+
readonly id: FileId;
|
|
26
|
+
readonly mime: string;
|
|
27
|
+
readonly data: ArrayBuffer;
|
|
28
|
+
readonly name?: string;
|
|
29
|
+
readonly createdAt: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Convenience constructor — assigns the current timestamp + a
|
|
33
|
+
* sensible default `mime` of `application/octet-stream`. Hosts
|
|
34
|
+
* normally pass an explicit `mime` from the source `Blob.type`.
|
|
35
|
+
*/
|
|
36
|
+
export declare const createBinaryFile: (id: FileId, data: ArrayBuffer, options?: {
|
|
37
|
+
readonly mime?: string;
|
|
38
|
+
readonly name?: string;
|
|
39
|
+
readonly createdAt?: number;
|
|
40
|
+
}) => BinaryFile;
|
|
41
|
+
//# sourceMappingURL=file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../src/file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAErD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAC3B,IAAI,MAAM,EACV,MAAM,WAAW,EACjB,UAAS;IAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,KAC5F,UAMD,CAAC"}
|
package/dist/file.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convenience constructor — assigns the current timestamp + a
|
|
3
|
+
* sensible default `mime` of `application/octet-stream`. Hosts
|
|
4
|
+
* normally pass an explicit `mime` from the source `Blob.type`.
|
|
5
|
+
*/
|
|
6
|
+
export const createBinaryFile = (id, data, options = {}) => ({
|
|
7
|
+
id,
|
|
8
|
+
data,
|
|
9
|
+
mime: options.mime ?? "application/octet-stream",
|
|
10
|
+
createdAt: options.createdAt ?? Date.now(),
|
|
11
|
+
...(options.name !== undefined ? { name: options.name } : {}),
|
|
12
|
+
});
|
|
13
|
+
//# sourceMappingURL=file.js.map
|
package/dist/file.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.js","sourceRoot":"","sources":["../src/file.ts"],"names":[],"mappings":"AAgCA;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,EAAU,EACV,IAAiB,EACjB,UAA2F,EAAE,EACjF,EAAE,CAAC,CAAC;IAChB,EAAE;IACF,IAAI;IACJ,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,0BAA0B;IAChD,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE;IAC1C,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;CAC9D,CAAC,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Vec2 } from "@oh-just-another/types";
|
|
2
|
+
import { type ElementBase } from "./shape.js";
|
|
3
|
+
/**
|
|
4
|
+
* Heading — the cardinal direction an elbow connector exits a shape on
|
|
5
|
+
* (standard model). One of four unit vectors. Used by the orthogonal
|
|
6
|
+
* router to push the endpoint out perpendicular to the shape's edge (the
|
|
7
|
+
* "dongle") before routing, so connectors always leave a box straight.
|
|
8
|
+
*/
|
|
9
|
+
export type Heading = Readonly<Vec2>;
|
|
10
|
+
export declare const HEADING_RIGHT: Heading;
|
|
11
|
+
export declare const HEADING_DOWN: Heading;
|
|
12
|
+
export declare const HEADING_LEFT: Heading;
|
|
13
|
+
export declare const HEADING_UP: Heading;
|
|
14
|
+
/** True for left/right headings (horizontal exit). */
|
|
15
|
+
export declare const headingIsHorizontal: (h: Heading) => boolean;
|
|
16
|
+
export declare const headingsEqual: (a: Heading, b: Heading) => boolean;
|
|
17
|
+
/** Opposite heading (reverse direction). */
|
|
18
|
+
export declare const flipHeading: (h: Heading) => Heading;
|
|
19
|
+
/**
|
|
20
|
+
* Quantise an arbitrary vector to the nearest cardinal heading. Ties on
|
|
21
|
+
* the dominant axis resolve to vertical (matches standard's
|
|
22
|
+
* `vectorToHeading`: `x > |y|` → right, `x <= -|y|` → left, else by y).
|
|
23
|
+
*/
|
|
24
|
+
export declare const vectorToHeading: (v: Vec2) => Heading;
|
|
25
|
+
/** Heading from `origin` toward `p`. */
|
|
26
|
+
export declare const headingForPoint: (p: Vec2, origin: Vec2) => Heading;
|
|
27
|
+
/**
|
|
28
|
+
* Outward normal of the AABB edge nearest to `p` — the correct exit heading
|
|
29
|
+
* for a point that sits ON the shape outline (floating / outline / ratio
|
|
30
|
+
* anchors). More accurate near corners than {@link headingForPointFromElement}
|
|
31
|
+
* (the cone test there can pick an adjacent side). For a point on the right
|
|
32
|
+
* edge → RIGHT, etc.
|
|
33
|
+
*/
|
|
34
|
+
export declare const headingForEdgePoint: (shape: ElementBase, p: Vec2) => Heading;
|
|
35
|
+
/**
|
|
36
|
+
* Which side of `shape` the world point `p` exits on. Splits the shape's
|
|
37
|
+
* (world-AABB) into four triangular cones from the centre to each corner;
|
|
38
|
+
* the cone `p` falls in decides the heading. A point dead-centre resolves
|
|
39
|
+
* via the centre→p vector. Diamonds/rotated shapes use the AABB.
|
|
40
|
+
*/
|
|
41
|
+
export declare const headingForPointFromElement: (shape: ElementBase, p: Vec2) => Heading;
|
|
42
|
+
//# sourceMappingURL=heading.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heading.d.ts","sourceRoot":"","sources":["../src/heading.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAyB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAErE;;;;;GAKG;AACH,MAAM,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;AAErC,eAAO,MAAM,aAAa,EAAE,OAAwB,CAAC;AACrD,eAAO,MAAM,YAAY,EAAE,OAAwB,CAAC;AACpD,eAAO,MAAM,YAAY,EAAE,OAAyB,CAAC;AACrD,eAAO,MAAM,UAAU,EAAE,OAAyB,CAAC;AAEnD,sDAAsD;AACtD,eAAO,MAAM,mBAAmB,GAAI,GAAG,OAAO,KAAG,OAAoB,CAAC;AAEtE,eAAO,MAAM,aAAa,GAAI,GAAG,OAAO,EAAE,GAAG,OAAO,KAAG,OAAqC,CAAC;AAE7F,4CAA4C;AAC5C,eAAO,MAAM,WAAW,GAAI,GAAG,OAAO,KAAG,OAA2C,CAAC;AAErF;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,GAAG,IAAI,KAAG,OAOzC,CAAC;AAEF,wCAAwC;AACxC,eAAO,MAAM,eAAe,GAAI,GAAG,IAAI,EAAE,QAAQ,IAAI,KAAG,OACG,CAAC;AAE5D;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,GAAI,OAAO,WAAW,EAAE,GAAG,IAAI,KAAG,OAWjE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,GAAI,OAAO,WAAW,EAAE,GAAG,IAAI,KAAG,OAkBxE,CAAC"}
|
package/dist/heading.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { getElementWorldBounds } from "./shape.js";
|
|
2
|
+
export const HEADING_RIGHT = { x: 1, y: 0 };
|
|
3
|
+
export const HEADING_DOWN = { x: 0, y: 1 };
|
|
4
|
+
export const HEADING_LEFT = { x: -1, y: 0 };
|
|
5
|
+
export const HEADING_UP = { x: 0, y: -1 };
|
|
6
|
+
/** True for left/right headings (horizontal exit). */
|
|
7
|
+
export const headingIsHorizontal = (h) => h.y === 0;
|
|
8
|
+
export const headingsEqual = (a, b) => a.x === b.x && a.y === b.y;
|
|
9
|
+
/** Opposite heading (reverse direction). */
|
|
10
|
+
export const flipHeading = (h) => ({ x: -h.x || 0, y: -h.y || 0 });
|
|
11
|
+
/**
|
|
12
|
+
* Quantise an arbitrary vector to the nearest cardinal heading. Ties on
|
|
13
|
+
* the dominant axis resolve to vertical (matches standard's
|
|
14
|
+
* `vectorToHeading`: `x > |y|` → right, `x <= -|y|` → left, else by y).
|
|
15
|
+
*/
|
|
16
|
+
export const vectorToHeading = (v) => {
|
|
17
|
+
const ax = Math.abs(v.x);
|
|
18
|
+
const ay = Math.abs(v.y);
|
|
19
|
+
if (v.x > ay)
|
|
20
|
+
return HEADING_RIGHT;
|
|
21
|
+
if (v.x <= -ay)
|
|
22
|
+
return HEADING_LEFT;
|
|
23
|
+
if (v.y > ax)
|
|
24
|
+
return HEADING_DOWN;
|
|
25
|
+
return HEADING_UP;
|
|
26
|
+
};
|
|
27
|
+
/** Heading from `origin` toward `p`. */
|
|
28
|
+
export const headingForPoint = (p, origin) => vectorToHeading({ x: p.x - origin.x, y: p.y - origin.y });
|
|
29
|
+
/**
|
|
30
|
+
* Outward normal of the AABB edge nearest to `p` — the correct exit heading
|
|
31
|
+
* for a point that sits ON the shape outline (floating / outline / ratio
|
|
32
|
+
* anchors). More accurate near corners than {@link headingForPointFromElement}
|
|
33
|
+
* (the cone test there can pick an adjacent side). For a point on the right
|
|
34
|
+
* edge → RIGHT, etc.
|
|
35
|
+
*/
|
|
36
|
+
export const headingForEdgePoint = (shape, p) => {
|
|
37
|
+
const b = getElementWorldBounds(shape);
|
|
38
|
+
const dl = Math.abs(p.x - b.x); // distance to left edge
|
|
39
|
+
const dr = Math.abs(b.x + b.width - p.x); // right
|
|
40
|
+
const dt = Math.abs(p.y - b.y); // top
|
|
41
|
+
const db = Math.abs(b.y + b.height - p.y); // bottom
|
|
42
|
+
const min = Math.min(dl, dr, dt, db);
|
|
43
|
+
if (min === dl)
|
|
44
|
+
return HEADING_LEFT;
|
|
45
|
+
if (min === dr)
|
|
46
|
+
return HEADING_RIGHT;
|
|
47
|
+
if (min === dt)
|
|
48
|
+
return HEADING_UP;
|
|
49
|
+
return HEADING_DOWN;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Which side of `shape` the world point `p` exits on. Splits the shape's
|
|
53
|
+
* (world-AABB) into four triangular cones from the centre to each corner;
|
|
54
|
+
* the cone `p` falls in decides the heading. A point dead-centre resolves
|
|
55
|
+
* via the centre→p vector. Diamonds/rotated shapes use the AABB.
|
|
56
|
+
*/
|
|
57
|
+
export const headingForPointFromElement = (shape, p) => {
|
|
58
|
+
const b = getElementWorldBounds(shape);
|
|
59
|
+
const cx = b.x + b.width / 2;
|
|
60
|
+
const cy = b.y + b.height / 2;
|
|
61
|
+
const dx = p.x - cx;
|
|
62
|
+
const dy = p.y - cy;
|
|
63
|
+
if (dx === 0 && dy === 0)
|
|
64
|
+
return HEADING_RIGHT;
|
|
65
|
+
// Compare the point's offset against the box aspect: the diagonals of the
|
|
66
|
+
// AABB split it into top/right/bottom/left cones. `dy/dx` vs `h/w`.
|
|
67
|
+
const w = b.width || 1;
|
|
68
|
+
const h = b.height || 1;
|
|
69
|
+
// Normalise offsets by half-extent so the cone test is a unit-square test.
|
|
70
|
+
const nx = dx / (w / 2);
|
|
71
|
+
const ny = dy / (h / 2);
|
|
72
|
+
if (Math.abs(nx) >= Math.abs(ny)) {
|
|
73
|
+
return nx >= 0 ? HEADING_RIGHT : HEADING_LEFT;
|
|
74
|
+
}
|
|
75
|
+
return ny >= 0 ? HEADING_DOWN : HEADING_UP;
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=heading.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heading.js","sourceRoot":"","sources":["../src/heading.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAoB,MAAM,YAAY,CAAC;AAUrE,MAAM,CAAC,MAAM,aAAa,GAAY,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AACrD,MAAM,CAAC,MAAM,YAAY,GAAY,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AACpD,MAAM,CAAC,MAAM,YAAY,GAAY,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AACrD,MAAM,CAAC,MAAM,UAAU,GAAY,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AAEnD,sDAAsD;AACtD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAU,EAAW,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AAEtE,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAU,EAAE,CAAU,EAAW,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAE7F,4CAA4C;AAC5C,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAU,EAAW,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAErF;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAO,EAAW,EAAE;IAClD,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzB,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzB,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE;QAAE,OAAO,aAAa,CAAC;IACnC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE;QAAE,OAAO,YAAY,CAAC;IACpC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE;QAAE,OAAO,YAAY,CAAC;IAClC,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC;AAEF,wCAAwC;AACxC,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAO,EAAE,MAAY,EAAW,EAAE,CAChE,eAAe,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAAkB,EAAE,CAAO,EAAW,EAAE;IAC1E,MAAM,CAAC,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IACvC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,wBAAwB;IACxD,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ;IAClD,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM;IACtC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;IACpD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IACrC,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,YAAY,CAAC;IACpC,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,aAAa,CAAC;IACrC,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,UAAU,CAAC;IAClC,OAAO,YAAY,CAAC;AACtB,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,KAAkB,EAAE,CAAO,EAAW,EAAE;IACjF,MAAM,CAAC,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IACvC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;IAC7B,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IAC9B,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;IACpB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;IACpB,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC;QAAE,OAAO,aAAa,CAAC;IAC/C,0EAA0E;IAC1E,oEAAoE;IACpE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;IACvB,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;IACxB,2EAA2E;IAC3E,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QACjC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC;IAChD,CAAC;IACD,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC;AAC7C,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export type { Style, TextStyle, LineCap, LineJoin, TextAlign, TextBaseline, FontWeight, FontStyle, TextDecoration, StrokeAlign, Roundness, } from "./style.js";
|
|
2
|
+
export { getCornerRadius, strokeOutsideExtent } from "./style.js";
|
|
3
|
+
export { ADAPTIVE_CORNER_RADIUS, PROPORTIONAL_CORNER_RADIUS } from "./constants.js";
|
|
4
|
+
export type { Element, ElementBase, BuiltinElement, RectangleElement, EllipseElement, PolygonElement, PathElement, PathCommand, TextElement, ImageElement, TemplateElement, GroupElement, FrameElement, BlockArrowElement, BrushElement, BrushPoint, ElementBounder, } from "./shape.js";
|
|
5
|
+
export type { Link, LinkEndpoint, LinkRouting, LinkArrowheads, LinkLabel, ArrowheadStyle, AnchorRef, NamedAnchor, StandardAnchor, } from "./edge.js";
|
|
6
|
+
export { getLinkEndpointWorld, getLinkPath, findLinkAt, getLinkCurvePoints, getLinkCurveSegments, getLinkWaypointMidpoints, getSelfLoopSpec, } from "./edge-geometry.js";
|
|
7
|
+
export { catmullRomBeziers, cubicWithEndTangents, flattenSegments, type BezierSegment, } from "./edge-curve.js";
|
|
8
|
+
export type { Layer } from "./layer.js";
|
|
9
|
+
export type { Viewport, GridStyle } from "./viewport.js";
|
|
10
|
+
export type { Scene } from "./scene.js";
|
|
11
|
+
export type { Patch } from "./patch.js";
|
|
12
|
+
export type { OperationResult } from "./operations.js";
|
|
13
|
+
export { isRectangle, isEllipse, isPolygon, isPath, isText, isImage, isTemplate, isGroup, isFrame, isBlockArrow, isBrush, registerBounder, getBounder, getElementLocalBounds, getElementWorldBounds, } from "./shape.js";
|
|
14
|
+
export { registerRenderOverflow, getElementRenderBounds, type RenderOverflow, } from "./render-bounds.js";
|
|
15
|
+
export { setTextMeasurer, getTextMeasurer, type TextMeasurer, type TextMeasureOpts, } from "./text-measure.js";
|
|
16
|
+
export { STANDARD_ANCHORS, STANDARD_ANCHOR_RATIOS, CARDINAL_ANCHORS, getNamedAnchorLocal, getAnchorLocal, getAnchorWorld, getAnchorOutwardNormal, listAnchorsLocal, geometryDefaultAnchorsLocal, findNearestAnchor, snapExcludedAnchors, } from "./anchors.js";
|
|
17
|
+
export type { SnapCandidate, SnapContext, SnapContributor } from "./snap.js";
|
|
18
|
+
export { SnapEngine, gridSnapper, anchorSnapper, outlineSnapper } from "./snap.js";
|
|
19
|
+
export type { OutlineSampler } from "./outline.js";
|
|
20
|
+
export { registerOutlineSampler, getOutlineSampler, getOutlinePoint, findNearestOutlinePoint, } from "./outline.js";
|
|
21
|
+
export { DEFAULT_VIEWPORT, getWorldToScreen, getScreenToWorld, panBy, zoomAt, resize, resolveSnapSpacing, isSnapToGridEnabled, } from "./viewport.js";
|
|
22
|
+
export { DEFAULT_LAYER_ID, emptyScene, apply, orderForTop, orderForBottom, orderBetween, orderBetweenMany, addBinaryFile, removeBinaryFile, getBinaryFile, } from "./scene.js";
|
|
23
|
+
export type { FractionalIndex } from "fractional-keys";
|
|
24
|
+
export type { BinaryFile } from "./file.js";
|
|
25
|
+
export { createBinaryFile } from "./file.js";
|
|
26
|
+
export { invert, batch, isNoop } from "./patch.js";
|
|
27
|
+
export { addElement, removeElement, updateElement, moveElement, addLink, removeLink, updateLink, addLayer, removeLayer, updateLayer, setViewport, addAnnotation, removeAnnotation, updateAnnotation, } from "./operations.js";
|
|
28
|
+
export type { Annotation, Comment } from "./annotation.js";
|
|
29
|
+
export { getAnnotationWorldPosition } from "./annotation-geometry.js";
|
|
30
|
+
export { getElement, getLink, getLayer, getLayersInOrder, getElementsInLayer, getLinksInLayer, getElementsInBounds, getElementsCoveredByBounds, getElementAt, buildSpatialIndex, queryByIndex, getElementAtIndexed, getChildrenOf, getElementOutline, registerElementOutline, type ElementOutlineProvider, getRootSelf, getDescendantsOf, isElementLocked, isElementHidden, } from "./queries.js";
|
|
31
|
+
export { SpatialGrid } from "./spatial.js";
|
|
32
|
+
export type { AccessibleNameResolver } from "./a11y.js";
|
|
33
|
+
export { getElementAccessibleName, registerAccessibleName } from "./a11y.js";
|
|
34
|
+
export type { LayoutFn, LayoutSpec, GridLayoutSpec, StackLayoutSpec, WrapLayoutSpec, TreeLayoutSpec, AutoLayoutSpec, } from "./layout.js";
|
|
35
|
+
export { gridLayout, stackLayout, wrapLayout, measureWrap, treeLayout, allElementsInLayer, getAutoLayoutSpec, runAutoLayout, } from "./layout.js";
|
|
36
|
+
export type { LayoutKindEntry } from "./layout-registry.js";
|
|
37
|
+
export { registerLayoutKind, unregisterLayoutKind, getLayoutKind, listLayoutKinds, } from "./layout-registry.js";
|
|
38
|
+
export { SNAP_PROBE_CULL_RADIUS, DEFAULT_GRID_SPACING, ELBOW_OBSTACLE_MARGIN, ELBOW_OBSTACLE_INTERIOR_EPSILON, FRAME_HEADER_HEIGHT, FRAME_HEADER_PADDING_X, FRAME_HEADER_FONT_SIZE, } from "./constants.js";
|
|
39
|
+
export { elbowRoute, type ElbowRouteOptions } from "./elbow-router.js";
|
|
40
|
+
export { routeElbowLink, routeElbowPreview } from "./elbow-link.js";
|
|
41
|
+
export { type Heading, HEADING_RIGHT, HEADING_DOWN, HEADING_LEFT, HEADING_UP, headingIsHorizontal, headingsEqual, flipHeading, vectorToHeading, headingForPoint, headingForPointFromElement, headingForEdgePoint, } from "./heading.js";
|
|
42
|
+
export type { SceneElementDiff } from "./diff.js";
|
|
43
|
+
export { diffSceneElements } from "./diff.js";
|
|
44
|
+
export type { ConflictResolutionInput, ThreeWayMergeConflict, ThreeWayMergeOptions, ThreeWayMergeReport, } from "./three-way-merge.js";
|
|
45
|
+
export { mergeScenesThreeWay, applyConflictResolutions } from "./three-way-merge.js";
|
|
46
|
+
export { isContainer, getContainerSpec, getDropZoneWorld, findContainerAt, expandDropZoneToFit, containerSizeForZone, registerContainerResolver, getDropZonesWorld, registerContainerZonesResolver, type ContainerSpec, type ContainerResolver, type ContainerZonesResolver, } from "./container.js";
|
|
47
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export { getCornerRadius, strokeOutsideExtent } from "./style.js";
|
|
2
|
+
export { ADAPTIVE_CORNER_RADIUS, PROPORTIONAL_CORNER_RADIUS } from "./constants.js";
|
|
3
|
+
export { getLinkEndpointWorld, getLinkPath, findLinkAt, getLinkCurvePoints, getLinkCurveSegments, getLinkWaypointMidpoints, getSelfLoopSpec, } from "./edge-geometry.js";
|
|
4
|
+
export { catmullRomBeziers, cubicWithEndTangents, flattenSegments, } from "./edge-curve.js";
|
|
5
|
+
// Element helpers + bounder registry
|
|
6
|
+
export { isRectangle, isEllipse, isPolygon, isPath, isText, isImage, isTemplate, isGroup, isFrame, isBlockArrow, isBrush, registerBounder, getBounder, getElementLocalBounds, getElementWorldBounds, } from "./shape.js";
|
|
7
|
+
export { registerRenderOverflow, getElementRenderBounds, } from "./render-bounds.js";
|
|
8
|
+
export { setTextMeasurer, getTextMeasurer, } from "./text-measure.js";
|
|
9
|
+
// Anchor helpers
|
|
10
|
+
export { STANDARD_ANCHORS, STANDARD_ANCHOR_RATIOS, CARDINAL_ANCHORS, getNamedAnchorLocal, getAnchorLocal, getAnchorWorld, getAnchorOutwardNormal, listAnchorsLocal, geometryDefaultAnchorsLocal, findNearestAnchor, snapExcludedAnchors, } from "./anchors.js";
|
|
11
|
+
export { SnapEngine, gridSnapper, anchorSnapper, outlineSnapper } from "./snap.js";
|
|
12
|
+
export { registerOutlineSampler, getOutlineSampler, getOutlinePoint, findNearestOutlinePoint, } from "./outline.js";
|
|
13
|
+
// Viewport helpers
|
|
14
|
+
export { DEFAULT_VIEWPORT, getWorldToScreen, getScreenToWorld, panBy, zoomAt, resize, resolveSnapSpacing, isSnapToGridEnabled, } from "./viewport.js";
|
|
15
|
+
// Scene constructor + apply + ordering helpers
|
|
16
|
+
export { DEFAULT_LAYER_ID, emptyScene, apply, orderForTop, orderForBottom, orderBetween, orderBetweenMany, addBinaryFile, removeBinaryFile, getBinaryFile, } from "./scene.js";
|
|
17
|
+
export { createBinaryFile } from "./file.js";
|
|
18
|
+
// Patch utilities
|
|
19
|
+
export { invert, batch, isNoop } from "./patch.js";
|
|
20
|
+
// Operations (return { scene, patch })
|
|
21
|
+
export { addElement, removeElement, updateElement, moveElement, addLink, removeLink, updateLink, addLayer, removeLayer, updateLayer, setViewport, addAnnotation, removeAnnotation, updateAnnotation, } from "./operations.js";
|
|
22
|
+
export { getAnnotationWorldPosition } from "./annotation-geometry.js";
|
|
23
|
+
// Queries
|
|
24
|
+
export { getElement, getLink, getLayer, getLayersInOrder, getElementsInLayer, getLinksInLayer, getElementsInBounds, getElementsCoveredByBounds, getElementAt, buildSpatialIndex, queryByIndex, getElementAtIndexed, getChildrenOf, getElementOutline, registerElementOutline, getRootSelf, getDescendantsOf, isElementLocked, isElementHidden, } from "./queries.js";
|
|
25
|
+
// Spatial index (the class itself, for advanced uses)
|
|
26
|
+
export { SpatialGrid } from "./spatial.js";
|
|
27
|
+
export { getElementAccessibleName, registerAccessibleName } from "./a11y.js";
|
|
28
|
+
export { gridLayout, stackLayout, wrapLayout, measureWrap, treeLayout, allElementsInLayer, getAutoLayoutSpec, runAutoLayout, } from "./layout.js";
|
|
29
|
+
export { registerLayoutKind, unregisterLayoutKind, getLayoutKind, listLayoutKinds, } from "./layout-registry.js";
|
|
30
|
+
// Tunable thresholds.
|
|
31
|
+
export { SNAP_PROBE_CULL_RADIUS, DEFAULT_GRID_SPACING, ELBOW_OBSTACLE_MARGIN, ELBOW_OBSTACLE_INTERIOR_EPSILON, FRAME_HEADER_HEIGHT, FRAME_HEADER_PADDING_X, FRAME_HEADER_FONT_SIZE, } from "./constants.js";
|
|
32
|
+
// Elbow router — A*-based obstacle-avoiding 90° routing.
|
|
33
|
+
export { elbowRoute } from "./elbow-router.js";
|
|
34
|
+
export { routeElbowLink, routeElbowPreview } from "./elbow-link.js";
|
|
35
|
+
export { HEADING_RIGHT, HEADING_DOWN, HEADING_LEFT, HEADING_UP, headingIsHorizontal, headingsEqual, flipHeading, vectorToHeading, headingForPoint, headingForPointFromElement, headingForEdgePoint, } from "./heading.js";
|
|
36
|
+
export { diffSceneElements } from "./diff.js";
|
|
37
|
+
export { mergeScenesThreeWay, applyConflictResolutions } from "./three-way-merge.js";
|
|
38
|
+
// Container / drop-zone protocol.
|
|
39
|
+
export { isContainer, getContainerSpec, getDropZoneWorld, findContainerAt, expandDropZoneToFit, containerSizeForZone, registerContainerResolver, getDropZonesWorld, registerContainerZonesResolver, } from "./container.js";
|
|
40
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/layer.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { LayerId } from "@oh-just-another/types";
|
|
2
|
+
import type { FractionalIndex } from "fractional-keys";
|
|
3
|
+
/**
|
|
4
|
+
* Layer is a named, ordered container for shapes and edges. Membership is
|
|
5
|
+
* stored on the children (via `shape.layerId` / `edge.layerId`), not on the
|
|
6
|
+
* layer itself, so cross-layer moves are O(1) updates of a single field.
|
|
7
|
+
*
|
|
8
|
+
* Layer z-order is governed by `order` (fractional index). Within a layer,
|
|
9
|
+
* child z-order is governed by each child's `order`.
|
|
10
|
+
*/
|
|
11
|
+
export interface Layer {
|
|
12
|
+
readonly id: LayerId;
|
|
13
|
+
readonly name: string;
|
|
14
|
+
readonly visible: boolean;
|
|
15
|
+
readonly locked: boolean;
|
|
16
|
+
readonly order: FractionalIndex;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=layer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layer.d.ts","sourceRoot":"","sources":["../src/layer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD;;;;;;;GAOG;AACH,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;CACjC"}
|
package/dist/layer.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layer.js","sourceRoot":"","sources":["../src/layer.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ElementId, Vec2 } from "@oh-just-another/types";
|
|
2
|
+
import type { Patch } from "./patch.js";
|
|
3
|
+
import type { Scene } from "./scene.js";
|
|
4
|
+
/**
|
|
5
|
+
* Pluggable layout registry.
|
|
6
|
+
*
|
|
7
|
+
* The built-in `AutoLayoutSpec` union is closed (grid / stack /
|
|
8
|
+
* tree); the registry lets hosts add their own kinds without
|
|
9
|
+
* widening the union. Each entry pairs a string `kind` with two
|
|
10
|
+
* functions:
|
|
11
|
+
*
|
|
12
|
+
* • `parse(metadata)` reads a shape's `metadata.autoLayout`
|
|
13
|
+
* payload and returns a validated spec (or `null` if the
|
|
14
|
+
* payload doesn't apply). This is what `getAutoLayoutSpec`
|
|
15
|
+
* consults after exhausting built-ins.
|
|
16
|
+
* • `run(scene, parentId, children, origin, spec)` produces the
|
|
17
|
+
* batched `Patch` (or `null` when nothing changed). The
|
|
18
|
+
* registry passes a pre-computed `children` list + dropzone-
|
|
19
|
+
* aware `origin` so plugins don't reimplement those.
|
|
20
|
+
*
|
|
21
|
+
* Registration is process-global — same model as the renderer
|
|
22
|
+
* registry. Hosts opt in via `registerLayoutKind("radial", ...)`;
|
|
23
|
+
* unregister returns the previous entry (mostly useful in tests).
|
|
24
|
+
*/
|
|
25
|
+
export interface LayoutKindEntry<Spec = unknown> {
|
|
26
|
+
readonly kind: string;
|
|
27
|
+
parse(metadata: unknown): Spec | null;
|
|
28
|
+
run(scene: Scene, parentId: ElementId, children: readonly ElementId[], origin: Vec2, spec: Spec): Patch | null;
|
|
29
|
+
}
|
|
30
|
+
export declare const registerLayoutKind: <S>(entry: LayoutKindEntry<S>) => void;
|
|
31
|
+
export declare const unregisterLayoutKind: (kind: string) => LayoutKindEntry | undefined;
|
|
32
|
+
export declare const getLayoutKind: (kind: string) => LayoutKindEntry | undefined;
|
|
33
|
+
/** Iterate every registered kind — useful for diagnostics / lints. */
|
|
34
|
+
export declare const listLayoutKinds: () => readonly string[];
|
|
35
|
+
//# sourceMappingURL=layout-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout-registry.d.ts","sourceRoot":"","sources":["../src/layout-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,WAAW,eAAe,CAAC,IAAI,GAAG,OAAO;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAAC;IACtC,GAAG,CACD,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,SAAS,EACnB,QAAQ,EAAE,SAAS,SAAS,EAAE,EAC9B,MAAM,EAAE,IAAI,EACZ,IAAI,EAAE,IAAI,GACT,KAAK,GAAG,IAAI,CAAC;CACjB;AAID,eAAO,MAAM,kBAAkB,GAAI,CAAC,EAAE,OAAO,eAAe,CAAC,CAAC,CAAC,KAAG,IAEjE,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,KAAG,eAAe,GAAG,SAIrE,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,KAAG,eAAe,GAAG,SAC3C,CAAC;AAErB,sEAAsE;AACtE,eAAO,MAAM,eAAe,QAAO,SAAS,MAAM,EAA0B,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const registry = new Map();
|
|
2
|
+
export const registerLayoutKind = (entry) => {
|
|
3
|
+
registry.set(entry.kind, entry);
|
|
4
|
+
};
|
|
5
|
+
export const unregisterLayoutKind = (kind) => {
|
|
6
|
+
const prev = registry.get(kind);
|
|
7
|
+
registry.delete(kind);
|
|
8
|
+
return prev;
|
|
9
|
+
};
|
|
10
|
+
export const getLayoutKind = (kind) => registry.get(kind);
|
|
11
|
+
/** Iterate every registered kind — useful for diagnostics / lints. */
|
|
12
|
+
export const listLayoutKinds = () => [...registry.keys()];
|
|
13
|
+
//# sourceMappingURL=layout-registry.js.map
|