@oh-just-another/scene 0.58.0 → 0.60.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 +57 -0
- package/README.md +36 -21
- package/dist/.tsbuildinfo +1 -1
- package/dist/anchors.d.ts.map +1 -1
- package/dist/anchors.js +2 -1
- package/dist/anchors.js.map +1 -1
- package/dist/brush-outline.d.ts +21 -0
- package/dist/brush-outline.d.ts.map +1 -0
- package/dist/brush-outline.js +142 -0
- package/dist/brush-outline.js.map +1 -0
- package/dist/constants.d.ts +78 -8
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +78 -8
- package/dist/constants.js.map +1 -1
- package/dist/edge-curve.d.ts +1 -3
- package/dist/edge-curve.d.ts.map +1 -1
- package/dist/edge-curve.js +3 -18
- package/dist/edge-curve.js.map +1 -1
- package/dist/edge-geometry.d.ts +18 -3
- package/dist/edge-geometry.d.ts.map +1 -1
- package/dist/edge-geometry.js +29 -47
- package/dist/edge-geometry.js.map +1 -1
- package/dist/edge.d.ts +19 -8
- package/dist/edge.d.ts.map +1 -1
- package/dist/edge.js +17 -1
- package/dist/edge.js.map +1 -1
- package/dist/elbow-link.d.ts +2 -2
- package/dist/elbow-link.d.ts.map +1 -1
- package/dist/elbow-link.js +4 -8
- package/dist/elbow-link.js.map +1 -1
- package/dist/elbow-router.d.ts +1 -1
- package/dist/elbow-router.d.ts.map +1 -1
- package/dist/elbow-router.js +1 -5
- package/dist/elbow-router.js.map +1 -1
- package/dist/ellipse.d.ts +8 -0
- package/dist/ellipse.d.ts.map +1 -0
- package/dist/ellipse.js +10 -0
- package/dist/ellipse.js.map +1 -0
- package/dist/heading.d.ts +4 -4
- package/dist/heading.js +2 -2
- package/dist/hydrate.d.ts +46 -0
- package/dist/hydrate.d.ts.map +1 -0
- package/dist/hydrate.js +59 -0
- package/dist/hydrate.js.map +1 -0
- package/dist/index.d.ts +14 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -5
- package/dist/index.js.map +1 -1
- package/dist/layout.d.ts +1 -6
- package/dist/layout.d.ts.map +1 -1
- package/dist/layout.js +15 -21
- package/dist/layout.js.map +1 -1
- package/dist/order.d.ts +10 -0
- package/dist/order.d.ts.map +1 -0
- package/dist/order.js +5 -0
- package/dist/order.js.map +1 -0
- package/dist/outline.d.ts +1 -1
- package/dist/outline.d.ts.map +1 -1
- package/dist/outline.js +11 -24
- package/dist/outline.js.map +1 -1
- package/dist/queries.d.ts.map +1 -1
- package/dist/queries.js +11 -24
- package/dist/queries.js.map +1 -1
- package/dist/scene.d.ts +7 -1
- package/dist/scene.d.ts.map +1 -1
- package/dist/scene.js +15 -2
- package/dist/scene.js.map +1 -1
- package/dist/shape-transform.d.ts +14 -0
- package/dist/shape-transform.d.ts.map +1 -0
- package/dist/shape-transform.js +33 -0
- package/dist/shape-transform.js.map +1 -0
- package/dist/shape.d.ts +52 -8
- package/dist/shape.d.ts.map +1 -1
- package/dist/shape.js +8 -0
- package/dist/shape.js.map +1 -1
- package/dist/snap.d.ts +2 -2
- package/dist/snap.js +5 -5
- package/dist/snap.js.map +1 -1
- package/dist/style.d.ts +2 -2
- package/dist/text-runs.d.ts +44 -0
- package/dist/text-runs.d.ts.map +1 -0
- package/dist/text-runs.js +139 -0
- package/dist/text-runs.js.map +1 -0
- package/dist/viewport.d.ts +16 -30
- package/dist/viewport.d.ts.map +1 -1
- package/dist/viewport.js +6 -13
- package/dist/viewport.js.map +1 -1
- package/package.json +5 -4
package/dist/style.d.ts
CHANGED
|
@@ -13,9 +13,9 @@ export type LineJoin = "miter" | "round" | "bevel";
|
|
|
13
13
|
export type StrokeAlign = "center" | "inside" | "outside";
|
|
14
14
|
/**
|
|
15
15
|
* Corner-rounding spec for shapes that support it (rectangle, container,
|
|
16
|
-
* box arrow, …)
|
|
16
|
+
* box arrow, …):
|
|
17
17
|
* `sharp` — no rounding (sharp corners). Equivalent to omitting the
|
|
18
|
-
* field;
|
|
18
|
+
* field; lets the value be set explicitly.
|
|
19
19
|
* `round` — rounded corners. Without `value`, falls back to the
|
|
20
20
|
* adaptive radius (fixed 32 px for big shapes, scales to
|
|
21
21
|
* 25 % of the smaller side for shapes < 128 px so they
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { TextStyle } from "./style.js";
|
|
2
|
+
import type { TextElement } from "./shape.js";
|
|
3
|
+
/**
|
|
4
|
+
* A styled segment of a text block. `text` is the raw substring; `style`
|
|
5
|
+
* is a PARTIAL overlay merged over the owning {@link TextElement}'s base
|
|
6
|
+
* `style` (element style wins for fields the run omits). Omitting `style`
|
|
7
|
+
* means "inherit the element style verbatim".
|
|
8
|
+
*
|
|
9
|
+
* Runs are an ADDITIVE overlay: the element's flat `text` stays the source
|
|
10
|
+
* of truth and MUST equal `runs.map(r => r.text).join("")`. A `TextElement`
|
|
11
|
+
* with no `runs` (or an empty array) renders exactly as before this feature
|
|
12
|
+
* existed — one uniform style — so plain-text scenes are untouched.
|
|
13
|
+
*/
|
|
14
|
+
export interface TextRun {
|
|
15
|
+
readonly text: string;
|
|
16
|
+
readonly style?: Partial<TextStyle>;
|
|
17
|
+
}
|
|
18
|
+
/** Concatenated raw text of a run list (the flat-text source of truth). */
|
|
19
|
+
export declare const runsToText: (runs: readonly TextRun[]) => string;
|
|
20
|
+
/**
|
|
21
|
+
* Drop empty-text runs and coalesce adjacent runs with identical styling.
|
|
22
|
+
* Returns a compact, canonical run list. An all-empty input yields `[]`.
|
|
23
|
+
*/
|
|
24
|
+
export declare const normalizeRuns: (runs: readonly TextRun[]) => TextRun[];
|
|
25
|
+
/**
|
|
26
|
+
* The runs that fall inside the character range `[from, to)` of a text block,
|
|
27
|
+
* clipped at the range edges. Used by the renderer to split each visual line
|
|
28
|
+
* into per-style segments. Styles are preserved verbatim (still partial
|
|
29
|
+
* overlays over the element style).
|
|
30
|
+
*/
|
|
31
|
+
export declare const sliceRuns: (el: Pick<TextElement, "text" | "runs">, from: number, to: number) => TextRun[];
|
|
32
|
+
/**
|
|
33
|
+
* Pure operation: apply a partial {@link TextStyle} overlay to the character
|
|
34
|
+
* range `[from, to)` of a text element, returning a NEW element. The flat
|
|
35
|
+
* `text` is never touched (invariant preserved). Existing runs are split at
|
|
36
|
+
* the range boundaries and the patch is merged into the overlapping portion;
|
|
37
|
+
* adjacent runs with equal styling are coalesced.
|
|
38
|
+
*
|
|
39
|
+
* When the result collapses to a single unstyled run spanning the whole text,
|
|
40
|
+
* `runs` is dropped entirely so the element reverts to a plain text block
|
|
41
|
+
* (keeps scenes minimal and round-trips cleanly). An empty range is a no-op.
|
|
42
|
+
*/
|
|
43
|
+
export declare const applyStyleToRange: (el: TextElement, from: number, to: number, patch: Partial<TextStyle>) => TextElement;
|
|
44
|
+
//# sourceMappingURL=text-runs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-runs.d.ts","sourceRoot":"","sources":["../src/text-runs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;;;;;;;GAUG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;CACrC;AAED,2EAA2E;AAC3E,eAAO,MAAM,UAAU,GAAI,MAAM,SAAS,OAAO,EAAE,KAAG,MAA0C,CAAC;AAgBjG;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,SAAS,OAAO,EAAE,KAAG,OAAO,EAe/D,CAAC;AASF;;;;;GAKG;AACH,eAAO,MAAM,SAAS,GACpB,IAAI,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC,EACtC,MAAM,MAAM,EACZ,IAAI,MAAM,KACT,OAAO,EAkBT,CAAC;AAcF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iBAAiB,GAC5B,IAAI,WAAW,EACf,MAAM,MAAM,EACZ,IAAI,MAAM,EACV,OAAO,OAAO,CAAC,SAAS,CAAC,KACxB,WAiDF,CAAC"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/** Concatenated raw text of a run list (the flat-text source of truth). */
|
|
2
|
+
export const runsToText = (runs) => runs.map((r) => r.text).join("");
|
|
3
|
+
/**
|
|
4
|
+
* Stable-ish key for a run style, used only to coalesce adjacent runs that
|
|
5
|
+
* carry identical styling. Sorts top-level keys so key order doesn't defeat
|
|
6
|
+
* the compare. A false "different" verdict only costs an extra (correct) run,
|
|
7
|
+
* never wrong rendering, so a shallow canonicalisation is sufficient.
|
|
8
|
+
*/
|
|
9
|
+
const styleKey = (style) => {
|
|
10
|
+
if (!style)
|
|
11
|
+
return "";
|
|
12
|
+
const entries = Object.entries(style)
|
|
13
|
+
.filter(([, v]) => v !== undefined)
|
|
14
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
|
|
15
|
+
return JSON.stringify(entries);
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Drop empty-text runs and coalesce adjacent runs with identical styling.
|
|
19
|
+
* Returns a compact, canonical run list. An all-empty input yields `[]`.
|
|
20
|
+
*/
|
|
21
|
+
export const normalizeRuns = (runs) => {
|
|
22
|
+
const out = [];
|
|
23
|
+
for (const run of runs) {
|
|
24
|
+
if (run.text === "")
|
|
25
|
+
continue;
|
|
26
|
+
const last = out[out.length - 1];
|
|
27
|
+
if (last !== undefined && styleKey(last.style) === styleKey(run.style)) {
|
|
28
|
+
out[out.length - 1] = {
|
|
29
|
+
text: last.text + run.text,
|
|
30
|
+
...(last.style !== undefined ? { style: last.style } : {}),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
out.push(run);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return out;
|
|
38
|
+
};
|
|
39
|
+
/** The run list to start from: explicit `runs`, else one run spanning `text`. */
|
|
40
|
+
const baseRuns = (el) => {
|
|
41
|
+
const runs = el.runs;
|
|
42
|
+
if (runs !== undefined && runs.length > 0)
|
|
43
|
+
return normalizeRuns(runs);
|
|
44
|
+
return el.text === "" ? [] : [{ text: el.text }];
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* The runs that fall inside the character range `[from, to)` of a text block,
|
|
48
|
+
* clipped at the range edges. Used by the renderer to split each visual line
|
|
49
|
+
* into per-style segments. Styles are preserved verbatim (still partial
|
|
50
|
+
* overlays over the element style).
|
|
51
|
+
*/
|
|
52
|
+
export const sliceRuns = (el, from, to) => {
|
|
53
|
+
const lo = Math.min(from, to);
|
|
54
|
+
const hi = Math.max(from, to);
|
|
55
|
+
const out = [];
|
|
56
|
+
let pos = 0;
|
|
57
|
+
for (const run of baseRuns(el)) {
|
|
58
|
+
const rStart = pos;
|
|
59
|
+
const rEnd = pos + run.text.length;
|
|
60
|
+
pos = rEnd;
|
|
61
|
+
const s = Math.max(rStart, lo);
|
|
62
|
+
const e = Math.min(rEnd, hi);
|
|
63
|
+
if (s >= e)
|
|
64
|
+
continue;
|
|
65
|
+
out.push({
|
|
66
|
+
text: run.text.slice(s - rStart, e - rStart),
|
|
67
|
+
...(run.style !== undefined ? { style: run.style } : {}),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return out;
|
|
71
|
+
};
|
|
72
|
+
/** Shallow-merge `patch` over `base`, pruning keys explicitly set to undefined. */
|
|
73
|
+
const mergeStyle = (base, patch) => {
|
|
74
|
+
const merged = { ...(base ?? {}), ...patch };
|
|
75
|
+
const entries = Object.entries(merged).filter(([, v]) => v !== undefined);
|
|
76
|
+
if (entries.length === 0)
|
|
77
|
+
return undefined;
|
|
78
|
+
const cleaned = Object.fromEntries(entries);
|
|
79
|
+
return cleaned;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Pure operation: apply a partial {@link TextStyle} overlay to the character
|
|
83
|
+
* range `[from, to)` of a text element, returning a NEW element. The flat
|
|
84
|
+
* `text` is never touched (invariant preserved). Existing runs are split at
|
|
85
|
+
* the range boundaries and the patch is merged into the overlapping portion;
|
|
86
|
+
* adjacent runs with equal styling are coalesced.
|
|
87
|
+
*
|
|
88
|
+
* When the result collapses to a single unstyled run spanning the whole text,
|
|
89
|
+
* `runs` is dropped entirely so the element reverts to a plain text block
|
|
90
|
+
* (keeps scenes minimal and round-trips cleanly). An empty range is a no-op.
|
|
91
|
+
*/
|
|
92
|
+
export const applyStyleToRange = (el, from, to, patch) => {
|
|
93
|
+
const lo = Math.max(0, Math.min(from, to));
|
|
94
|
+
const hi = Math.min(el.text.length, Math.max(from, to));
|
|
95
|
+
if (lo >= hi)
|
|
96
|
+
return el;
|
|
97
|
+
const out = [];
|
|
98
|
+
let pos = 0;
|
|
99
|
+
for (const run of baseRuns(el)) {
|
|
100
|
+
const rStart = pos;
|
|
101
|
+
const rEnd = pos + run.text.length;
|
|
102
|
+
pos = rEnd;
|
|
103
|
+
const midStart = Math.max(rStart, lo);
|
|
104
|
+
const midEnd = Math.min(rEnd, hi);
|
|
105
|
+
if (midStart >= midEnd) {
|
|
106
|
+
out.push(run);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (rStart < midStart) {
|
|
110
|
+
out.push({
|
|
111
|
+
text: run.text.slice(0, midStart - rStart),
|
|
112
|
+
...(run.style !== undefined ? { style: run.style } : {}),
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
const merged = mergeStyle(run.style, patch);
|
|
116
|
+
out.push({
|
|
117
|
+
text: run.text.slice(midStart - rStart, midEnd - rStart),
|
|
118
|
+
...(merged !== undefined ? { style: merged } : {}),
|
|
119
|
+
});
|
|
120
|
+
if (midEnd < rEnd) {
|
|
121
|
+
out.push({
|
|
122
|
+
text: run.text.slice(midEnd - rStart),
|
|
123
|
+
...(run.style !== undefined ? { style: run.style } : {}),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const normalized = normalizeRuns(out);
|
|
128
|
+
const only = normalized[0];
|
|
129
|
+
if (normalized.length === 1 &&
|
|
130
|
+
only !== undefined &&
|
|
131
|
+
(only.style === undefined || Object.keys(only.style).length === 0)) {
|
|
132
|
+
// Reverted to a single uniform style → shed the overlay entirely.
|
|
133
|
+
const { runs: _drop, ...rest } = el;
|
|
134
|
+
void _drop;
|
|
135
|
+
return rest;
|
|
136
|
+
}
|
|
137
|
+
return { ...el, runs: normalized };
|
|
138
|
+
};
|
|
139
|
+
//# sourceMappingURL=text-runs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-runs.js","sourceRoot":"","sources":["../src/text-runs.ts"],"names":[],"mappings":"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"}
|
package/dist/viewport.d.ts
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import type { Transform, Vec2 } from "@oh-just-another/types";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
* `"lines"` —
|
|
5
|
-
* `"dots"` — a dot at every grid intersection.
|
|
6
|
-
* free-form diagramming (standard style).
|
|
3
|
+
* How the background grid is painted.
|
|
4
|
+
* `"lines"` — ruled grid lines (default).
|
|
5
|
+
* `"dots"` — a dot at every grid intersection.
|
|
7
6
|
*
|
|
8
|
-
* Snap behaviour is identical between styles
|
|
9
|
-
* differs.
|
|
7
|
+
* Snap behaviour is identical between styles; only the paint differs.
|
|
10
8
|
*/
|
|
11
9
|
export type GridStyle = "lines" | "dots";
|
|
12
10
|
/**
|
|
@@ -26,37 +24,25 @@ export interface Viewport {
|
|
|
26
24
|
readonly height: number;
|
|
27
25
|
};
|
|
28
26
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* value. Snap-to-grid uses it when present and falls back to
|
|
32
|
-
* {@link DEFAULT_GRID_SPACING} when the grid is hidden but snapping
|
|
33
|
-
* is still on (see {@link resolveSnapSpacing}).
|
|
34
|
-
*/
|
|
35
|
-
readonly gridSize?: number;
|
|
36
|
-
/**
|
|
37
|
-
* How the grid is painted. Default `"lines"` for backwards-compat;
|
|
38
|
-
* snap math doesn't read this field. Renderers fall back to lines
|
|
39
|
-
* when the field is missing.
|
|
27
|
+
* Whether the background grid is drawn for this scene. Spacing is fixed
|
|
28
|
+
* at {@link DEFAULT_GRID_SPACING}; this flag controls only visibility.
|
|
40
29
|
*/
|
|
30
|
+
readonly gridEnabled: boolean;
|
|
31
|
+
/** How the grid is painted. Renderers fall back to lines when unset. */
|
|
41
32
|
readonly gridStyle?: GridStyle;
|
|
42
33
|
/**
|
|
43
|
-
*
|
|
44
|
-
* (see {@link isSnapToGridEnabled}). Snapping
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* confusing — so this flag only matters when a grid is on.
|
|
34
|
+
* Programmatic snap opt-out. `undefined` is treated as ON
|
|
35
|
+
* (see {@link isSnapToGridEnabled}). Snapping also requires the grid to be
|
|
36
|
+
* enabled — snapping to a hidden grid is confusing — so this flag only
|
|
37
|
+
* matters while `gridEnabled` is true.
|
|
48
38
|
*/
|
|
49
39
|
readonly snapToGrid?: boolean;
|
|
50
40
|
}
|
|
41
|
+
/** World-unit spacing snap-to-grid rounds to (the fixed grid spacing). */
|
|
42
|
+
export declare const resolveSnapSpacing: () => number;
|
|
51
43
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* fallback — so snapping keeps working when the grid is hidden.
|
|
55
|
-
*/
|
|
56
|
-
export declare const resolveSnapSpacing: (viewport: Viewport) => number;
|
|
57
|
-
/**
|
|
58
|
-
* Whether snap-to-grid is enabled for this viewport. `undefined`
|
|
59
|
-
* (legacy / fresh documents) counts as ON — the product default.
|
|
44
|
+
* Whether snap-to-grid is enabled for this viewport. `undefined` counts as
|
|
45
|
+
* ON — the product default.
|
|
60
46
|
*/
|
|
61
47
|
export declare const isSnapToGridEnabled: (viewport: Viewport) => boolean;
|
|
62
48
|
export declare const DEFAULT_VIEWPORT: Viewport;
|
package/dist/viewport.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"viewport.d.ts","sourceRoot":"","sources":["../src/viewport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAI9D
|
|
1
|
+
{"version":3,"file":"viewport.d.ts","sourceRoot":"","sources":["../src/viewport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAI9D;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAEzC;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;IACnB,mDAAmD;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8CAA8C;IAC9C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,wEAAwE;IACxE,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,0EAA0E;AAC1E,eAAO,MAAM,kBAAkB,QAAO,MAA8B,CAAC;AAErE;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,UAAU,QAAQ,KAAG,OAAsC,CAAC;AAEhG,eAAO,MAAM,gBAAgB,EAAE,QAO7B,CAAC;AAEH,gCAAgC;AAChC,eAAO,MAAM,gBAAgB,GAAI,UAAU,QAAQ,KAAG,SAMrD,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,gBAAgB,GAAI,UAAU,QAAQ,KAAG,SACV,CAAC;AAE7C;;;;GAIG;AACH,eAAO,MAAM,KAAK,GAAI,UAAU,QAAQ,EAAE,aAAa,IAAI,KAAG,QAM5D,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,MAAM,GAAI,UAAU,QAAQ,EAAE,QAAQ,MAAM,EAAE,aAAa,IAAI,KAAG,QAW9E,CAAC;AAEF,eAAO,MAAM,MAAM,GAAI,UAAU,QAAQ,EAAE,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAG,QAGzE,CAAC"}
|
package/dist/viewport.js
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import { matrix } from "@oh-just-another/math";
|
|
2
2
|
import { DEFAULT_GRID_SPACING } from "./constants.js";
|
|
3
|
+
/** World-unit spacing snap-to-grid rounds to (the fixed grid spacing). */
|
|
4
|
+
export const resolveSnapSpacing = () => DEFAULT_GRID_SPACING;
|
|
3
5
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* fallback — so snapping keeps working when the grid is hidden.
|
|
7
|
-
*/
|
|
8
|
-
export const resolveSnapSpacing = (viewport) => viewport.gridSize && viewport.gridSize > 0 ? viewport.gridSize : DEFAULT_GRID_SPACING;
|
|
9
|
-
/**
|
|
10
|
-
* Whether snap-to-grid is enabled for this viewport. `undefined`
|
|
11
|
-
* (legacy / fresh documents) counts as ON — the product default.
|
|
6
|
+
* Whether snap-to-grid is enabled for this viewport. `undefined` counts as
|
|
7
|
+
* ON — the product default.
|
|
12
8
|
*/
|
|
13
9
|
export const isSnapToGridEnabled = (viewport) => viewport.snapToGrid ?? true;
|
|
14
10
|
export const DEFAULT_VIEWPORT = Object.freeze({
|
|
@@ -16,11 +12,8 @@ export const DEFAULT_VIEWPORT = Object.freeze({
|
|
|
16
12
|
zoom: 1,
|
|
17
13
|
rotation: 0,
|
|
18
14
|
size: { width: 0, height: 0 },
|
|
19
|
-
// Grid
|
|
20
|
-
|
|
21
|
-
// Tune the default spacing in `constants.ts` (`DEFAULT_GRID_SPACING`); pass a
|
|
22
|
-
// scene with `gridSize: 0` (or omit it) for a gridless, snap-free canvas.
|
|
23
|
-
gridSize: DEFAULT_GRID_SPACING,
|
|
15
|
+
// Grid off by default; hosts enable it per scene via `gridEnabled`.
|
|
16
|
+
gridEnabled: false,
|
|
24
17
|
});
|
|
25
18
|
/** World → screen transform. */
|
|
26
19
|
export const getWorldToScreen = (viewport) => {
|
package/dist/viewport.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"viewport.js","sourceRoot":"","sources":["../src/viewport.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"viewport.js","sourceRoot":"","sources":["../src/viewport.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAwCtD,0EAA0E;AAC1E,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAW,EAAE,CAAC,oBAAoB,CAAC;AAErE;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,QAAkB,EAAW,EAAE,CAAC,QAAQ,CAAC,UAAU,IAAI,IAAI,CAAC;AAEhG,MAAM,CAAC,MAAM,gBAAgB,GAAa,MAAM,CAAC,MAAM,CAAC;IACtD,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;IACnB,IAAI,EAAE,CAAC;IACP,QAAQ,EAAE,CAAC;IACX,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;IAC7B,oEAAoE;IACpE,WAAW,EAAE,KAAK;CACnB,CAAC,CAAC;AAEH,gCAAgC;AAChC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,QAAkB,EAAa,EAAE;IAChE,2DAA2D;IAC3D,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5C,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;AACpE,CAAC,CAAC;AAEF,gEAAgE;AAChE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,QAAkB,EAAa,EAAE,CAChE,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC;AAE7C;;;;GAIG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,QAAkB,EAAE,WAAiB,EAAY,EAAE,CAAC,CAAC;IACzE,GAAG,QAAQ;IACX,GAAG,EAAE;QACH,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI;QACjD,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI;KAClD;CACF,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,QAAkB,EAAE,MAAc,EAAE,WAAiB,EAAY,EAAE;IACxF,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,GAAG,MAAM,CAAC;IACvC,gEAAgE;IAChE,OAAO;QACL,GAAG,QAAQ;QACX,IAAI,EAAE,OAAO;QACb,GAAG,EAAE;YACH,CAAC,EAAE,WAAW,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM;YAC5D,CAAC,EAAE,WAAW,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM;SAC7D;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,QAAkB,EAAE,KAAa,EAAE,MAAc,EAAY,EAAE,CAAC,CAAC;IACtF,GAAG,QAAQ;IACX,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;CACxB,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oh-just-another/scene",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "scene
|
|
3
|
+
"version": "0.60.0",
|
|
4
|
+
"description": "Immutable diagram scene model: elements, links, layers, patch-based operations, and a fast spatial index.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Rustam Garifulin <rustam@n69.in>",
|
|
7
7
|
"repository": {
|
|
@@ -39,15 +39,16 @@
|
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"fractional-keys": "
|
|
42
|
+
"fractional-keys": "0.1.1",
|
|
43
43
|
"@oh-just-another/types": "0.57.0",
|
|
44
|
-
"@oh-just-another/math": "0.
|
|
44
|
+
"@oh-just-another/math": "0.58.0"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"build": "tsc -b tsconfig.build.json",
|
|
48
48
|
"typecheck": "tsc --noEmit",
|
|
49
49
|
"test": "vitest run",
|
|
50
50
|
"test:watch": "vitest",
|
|
51
|
+
"bench": "vitest bench --run",
|
|
51
52
|
"lint": "eslint src tests",
|
|
52
53
|
"clean": "rm -rf dist *.tsbuildinfo"
|
|
53
54
|
}
|