@neta-art/cohub 8.23.0 → 9.0.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/dist/board/animation.d.ts +57 -181
- package/dist/board/animation.js +374 -220
- package/dist/board/core/arrow-geometry.d.ts +33 -18
- package/dist/board/core/arrow-geometry.js +283 -52
- package/dist/board/core/draw-geometry.d.ts +22 -36
- package/dist/board/core/draw-geometry.js +148 -85
- package/dist/board/core/export-assets.d.ts +3 -6
- package/dist/board/core/export-assets.js +0 -2
- package/dist/board/core/export-plan.d.ts +12 -63
- package/dist/board/core/export-plan.js +55 -94
- package/dist/board/core/palette.d.ts +4 -21
- package/dist/board/core/palette.js +8 -13
- package/dist/board/core/scene.d.ts +33 -0
- package/dist/board/core/scene.js +302 -0
- package/dist/board/core/shape-definition.d.ts +12 -24
- package/dist/board/core/shape-definition.js +0 -19
- package/dist/board/core/shape-types.d.ts +6 -120
- package/dist/board/core/shape-types.js +5 -5
- package/dist/board/core/text-metrics.d.ts +8 -11
- package/dist/board/core/text-metrics.js +5 -34
- package/dist/board/core/tool-styles.d.ts +6 -16
- package/dist/board/core/tool-styles.js +17 -25
- package/dist/board/export/index.d.ts +10 -17
- package/dist/board/export/index.js +22 -21
- package/dist/board/export/scene.d.ts +10 -16
- package/dist/board/export/scene.js +17 -30
- package/dist/board/geometry.d.ts +27 -56
- package/dist/board/geometry.js +7 -67
- package/dist/board/headless/index.d.ts +7 -27
- package/dist/board/headless/index.js +20 -19
- package/dist/board/headless/sketch.d.ts +19 -0
- package/dist/board/headless/sketch.js +146 -0
- package/dist/board/image-key.d.ts +2 -12
- package/dist/board/image-key.js +3 -13
- package/dist/board/index.d.ts +18 -20
- package/dist/board/index.js +17 -17
- package/dist/board/media-playback.d.ts +3 -6
- package/dist/board/media-playback.js +6 -6
- package/dist/board/presets.d.ts +150 -0
- package/dist/board/presets.js +226 -0
- package/dist/board/render/board-background.d.ts +5 -3
- package/dist/board/render/board-background.js +8 -7
- package/dist/board/render/clip.d.ts +14 -0
- package/dist/board/render/clip.js +47 -0
- package/dist/board/render/index.d.ts +8 -5
- package/dist/board/render/index.js +7 -4
- package/dist/board/render/media-interaction.d.ts +4 -5
- package/dist/board/render/media-interaction.js +1 -2
- package/dist/board/render/palette.d.ts +6 -2
- package/dist/board/render/palette.js +7 -1
- package/dist/board/render/renderers/arrow-card-renderer.js +69 -71
- package/dist/board/render/renderers/audio-card-renderer.js +3 -3
- package/dist/board/render/renderers/base-card-renderer.d.ts +6 -17
- package/dist/board/render/renderers/base-card-renderer.js +1 -24
- package/dist/board/render/renderers/board-renderer-registry.d.ts +20 -50
- package/dist/board/render/renderers/board-renderer-registry.js +6 -7
- package/dist/board/render/renderers/draw-card-renderer.js +89 -56
- package/dist/board/render/renderers/effect-card-renderer.d.ts +6 -0
- package/dist/board/render/renderers/effect-card-renderer.js +197 -0
- package/dist/board/render/renderers/far-plate.d.ts +4 -21
- package/dist/board/render/renderers/far-plate.js +15 -34
- package/dist/board/render/renderers/file-card-renderer.d.ts +4 -25
- package/dist/board/render/renderers/file-card-renderer.js +8 -58
- package/dist/board/render/renderers/frame-card-renderer.js +28 -28
- package/dist/board/render/renderers/image-card-renderer.d.ts +4 -3
- package/dist/board/render/renderers/image-card-renderer.js +0 -9
- package/dist/board/render/renderers/shape-card-renderer.d.ts +9 -0
- package/dist/board/render/renderers/shape-card-renderer.js +240 -0
- package/dist/board/render/renderers/sketch-card-renderer.d.ts +5 -0
- package/dist/board/render/renderers/sketch-card-renderer.js +98 -0
- package/dist/board/render/renderers/task-card-renderer.d.ts +0 -1
- package/dist/board/render/renderers/task-card-renderer.js +14 -16
- package/dist/board/render/renderers/text-card-renderer.d.ts +1 -3
- package/dist/board/render/renderers/text-card-renderer.js +56 -46
- package/dist/board/render/renderers/unknown-card-renderer.js +4 -10
- package/dist/board/render/renderers/video-card-renderer.d.ts +4 -2
- package/dist/board/render/renderers/video-card-renderer.js +2 -1
- package/dist/board/render/sketch-host.d.ts +14 -0
- package/dist/board/render/sketch-host.js +216 -0
- package/dist/board/render/stroke.d.ts +12 -0
- package/dist/board/render/stroke.js +90 -0
- package/dist/board/render/text-measurement.d.ts +6 -26
- package/dist/board/render/text-measurement.js +11 -30
- package/dist/board/replay.d.ts +6 -31
- package/dist/board/replay.js +45 -203
- package/dist/board/runtime/board-player.d.ts +24 -0
- package/dist/board/runtime/board-player.js +161 -0
- package/dist/board/task.d.ts +2 -10
- package/dist/board/task.js +1 -10
- package/dist/chunks/environment.d.ts +2296 -3864
- package/dist/chunks/host-bridge.d.ts +253 -0
- package/dist/chunks/http.d.ts +238 -58
- package/dist/chunks/http.js +1061 -1034
- package/dist/chunks/transport.js +113 -59
- package/dist/chunks/websocket.d.ts +1 -1
- package/dist/chunks/websocket.js +1 -1
- package/dist/host-bridge.d.ts +54 -0
- package/dist/host-bridge.js +322 -0
- package/dist/http.d.ts +3 -3
- package/dist/index.d.ts +76 -193
- package/dist/index.js +2037 -1191
- package/dist/protocol/dist/board-constants.d.ts +1 -29
- package/dist/protocol/dist/board-constants.js +2 -115
- package/dist/protocol/dist/board-layout.d.ts +59 -0
- package/dist/protocol/dist/board-layout.js +482 -0
- package/dist/protocol/dist/board-model.d.ts +2052 -0
- package/dist/protocol/dist/board-model.js +592 -0
- package/dist/protocol/dist/board-patch.d.ts +86 -0
- package/dist/protocol/dist/board-patch.js +734 -0
- package/dist/protocol/dist/board-schema.d.ts +33 -0
- package/dist/protocol/dist/board-schema.js +59 -0
- package/dist/protocol/dist/board-upgrade.d.ts +1 -0
- package/dist/protocol/dist/board-url.d.ts +1 -3
- package/dist/protocol/dist/board-url.js +2 -2
- package/dist/protocol/dist/board.d.ts +37 -232
- package/dist/protocol/dist/board.js +62 -160
- package/dist/protocol/dist/display/actions.d.ts +1 -0
- package/dist/protocol/dist/display/index.d.ts +2 -0
- package/dist/protocol/dist/index.d.ts +11 -12
- package/dist/protocol/dist/model/metrics.d.ts +2 -0
- package/dist/protocol/dist/model/session.d.ts +2 -1
- package/dist/protocol/dist/realtime/types.d.ts +2 -2
- package/dist/protocol/dist/runtime/index.d.ts +1 -0
- package/dist/space-picker.d.ts +1 -0
- package/dist/space-picker.js +1 -0
- package/dist/types.d.ts +2 -5
- package/package.json +9 -1
- package/dist/board/core/connections.d.ts +0 -108
- package/dist/board/core/connections.js +0 -455
- package/dist/board/mutation.d.ts +0 -6
- package/dist/board/mutation.js +0 -14
- package/dist/board/render/connection-layer.d.ts +0 -53
- package/dist/board/render/connection-layer.js +0 -375
- package/dist/board/render/renderers/geo-card-renderer.d.ts +0 -5
- package/dist/board/render/renderers/geo-card-renderer.js +0 -127
- package/dist/board/semantic-document.d.ts +0 -37
- package/dist/board/semantic-document.js +0 -288
- package/dist/board/semantic-mutation.d.ts +0 -10
- package/dist/board/semantic-mutation.js +0 -209
- package/dist/protocol/dist/board-animation.js +0 -34
- package/dist/protocol/dist/board-authoring.d.ts +0 -1326
- package/dist/protocol/dist/board-authoring.js +0 -302
- package/dist/protocol/dist/board-capability-registry.d.ts +0 -2
- package/dist/protocol/dist/board-capability-registry.js +0 -123
- package/dist/protocol/dist/board-codec.d.ts +0 -3
- package/dist/protocol/dist/board-codec.js +0 -383
- package/dist/protocol/dist/board-composition.d.ts +0 -383
- package/dist/protocol/dist/board-composition.js +0 -310
- package/dist/protocol/dist/board-connection.d.ts +0 -317
- package/dist/protocol/dist/board-connection.js +0 -219
- package/dist/protocol/dist/board-document.d.ts +0 -1566
- package/dist/protocol/dist/board-document.js +0 -456
- package/dist/protocol/dist/board-effect.d.ts +0 -96
- package/dist/protocol/dist/board-effect.js +0 -54
- package/dist/protocol/dist/board-geometry.d.ts +0 -15
- package/dist/protocol/dist/board-geometry.js +0 -137
- package/dist/protocol/dist/board-node.d.ts +0 -8
- package/dist/protocol/dist/board-node.js +0 -252
- /package/dist/protocol/dist/{board-animation.d.ts → host-bridge.d.ts} +0 -0
|
@@ -1,34 +1,6 @@
|
|
|
1
1
|
//#region ../protocol/dist/board-constants.d.ts
|
|
2
|
-
type BoardCoordinateSpace = "world" | "frame-local" | "world-offset" | "screen" | "screen-offset" | "normalized";
|
|
3
|
-
type BoardRenderCost = {
|
|
4
|
-
particles: number;
|
|
5
|
-
vertices: number;
|
|
6
|
-
dynamicVertices: number;
|
|
7
|
-
drawCalls: number;
|
|
8
|
-
filterPasses: number;
|
|
9
|
-
renderTexturePixels: number;
|
|
10
|
-
textureBytes: number;
|
|
11
|
-
bufferBytes: number;
|
|
12
|
-
simulationSteps: number;
|
|
13
|
-
};
|
|
14
|
-
type BoardCapability = {
|
|
15
|
-
kind: "preset" | "clip" | "effect" | "shader";
|
|
16
|
-
id: string;
|
|
17
|
-
version: number;
|
|
18
|
-
digest?: string;
|
|
19
|
-
renderers?: Array<"webgpu" | "webgl">;
|
|
20
|
-
fallbackId?: string;
|
|
21
|
-
schema?: Record<string, unknown>;
|
|
22
|
-
};
|
|
23
|
-
/**
|
|
24
|
-
* Stroke width bounds, shared by every stroked board entity.
|
|
25
|
-
*
|
|
26
|
-
* Defined here (not beside the editor) because the persisted schemas clamp with
|
|
27
|
-
* them: a single range is what keeps a width authored by the editor, an agent or
|
|
28
|
-
* the CLI from being silently re-clamped to something else on read.
|
|
29
|
-
*/
|
|
30
2
|
declare const BOARD_STROKE_MIN_SIZE = 1;
|
|
31
3
|
declare const BOARD_STROKE_MAX_SIZE = 64;
|
|
32
4
|
declare function clampBoardStrokeSize(size: number): number;
|
|
33
5
|
//#endregion
|
|
34
|
-
export { BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE,
|
|
6
|
+
export { BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, clampBoardStrokeSize };
|
|
@@ -1,126 +1,13 @@
|
|
|
1
1
|
//#region ../protocol/dist/board-constants.js
|
|
2
|
-
const DEFAULT_BOARD_RENDER_LIMITS = {
|
|
3
|
-
particles: 2e4,
|
|
4
|
-
vertices: 5e5,
|
|
5
|
-
dynamicVertices: 15e4,
|
|
6
|
-
drawCalls: 400,
|
|
7
|
-
filterPasses: 24,
|
|
8
|
-
renderTexturePixels: 16777216,
|
|
9
|
-
textureBytes: 536870912,
|
|
10
|
-
bufferBytes: 268435456,
|
|
11
|
-
simulationSteps: 1e5
|
|
12
|
-
};
|
|
13
|
-
const BOARD_BUILTIN_CLIP_KINDS = [
|
|
14
|
-
"motion.path",
|
|
15
|
-
"draw.reveal",
|
|
16
|
-
"text.reveal",
|
|
17
|
-
"effects.particles",
|
|
18
|
-
"effects.trail",
|
|
19
|
-
"effects.impact",
|
|
20
|
-
"effects.flash",
|
|
21
|
-
"camera.focus",
|
|
22
|
-
"camera.shake"
|
|
23
|
-
];
|
|
24
|
-
const BOARD_BUILTIN_EFFECT_KINDS = [
|
|
25
|
-
"effects.pulse",
|
|
26
|
-
"effects.float",
|
|
27
|
-
"effects.deal"
|
|
28
|
-
];
|
|
29
|
-
/**
|
|
30
|
-
* World-space typography for board text.
|
|
31
|
-
*
|
|
32
|
-
* These live here rather than beside the renderer because the document schema
|
|
33
|
-
* constrains persisted font sizes with them, and the schema must not depend on
|
|
34
|
-
* anything that draws.
|
|
35
|
-
*/
|
|
36
2
|
const BOARD_TEXT_FONT_FAMILY = "Geist";
|
|
37
3
|
const BOARD_ARROW_STROKE_SIZE = 2.5;
|
|
38
|
-
const BOARD_CONNECTION_STROKE_SIZE = 2.5;
|
|
39
|
-
/**
|
|
40
|
-
* Stroke width bounds, shared by every stroked board entity.
|
|
41
|
-
*
|
|
42
|
-
* Defined here (not beside the editor) because the persisted schemas clamp with
|
|
43
|
-
* them: a single range is what keeps a width authored by the editor, an agent or
|
|
44
|
-
* the CLI from being silently re-clamped to something else on read.
|
|
45
|
-
*/
|
|
46
4
|
const BOARD_STROKE_MIN_SIZE = 1;
|
|
47
5
|
const BOARD_STROKE_MAX_SIZE = 64;
|
|
48
6
|
function clampBoardStrokeSize(size) {
|
|
49
|
-
if (!Number.isFinite(size)) return
|
|
7
|
+
if (!Number.isFinite(size)) return BOARD_ARROW_STROKE_SIZE;
|
|
50
8
|
return Math.min(64, Math.max(1, size));
|
|
51
9
|
}
|
|
52
|
-
/**
|
|
53
|
-
* Font stacks used by every board renderer.
|
|
54
|
-
*
|
|
55
|
-
* A bare "Geist" would render CJK (and anything else outside the Latin subset)
|
|
56
|
-
* as missing-glyph boxes, because the shipped webfont is Latin-only. The stack
|
|
57
|
-
* mirrors the web `--font-sans` / `--font-mono` tokens and adds the common CJK
|
|
58
|
-
* families, so both the browser and a headless export fall back to a real face
|
|
59
|
-
* instead of tofu.
|
|
60
|
-
*/
|
|
61
10
|
const BOARD_FONT_STACK = "\"Geist\", system-ui, -apple-system, \"Noto Sans CJK SC\", \"Noto Sans SC\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif";
|
|
62
11
|
const BOARD_MONO_FONT_STACK = "\"Geist Mono\", \"Fira Code\", ui-monospace, \"Noto Sans Mono CJK SC\", monospace";
|
|
63
|
-
function clipSchema(id) {
|
|
64
|
-
switch (id) {
|
|
65
|
-
case "motion.path": return { params: { points: {
|
|
66
|
-
coordinateSpace: "world-offset",
|
|
67
|
-
unit: "board"
|
|
68
|
-
} } };
|
|
69
|
-
case "effects.particles": return { params: { bounds: {
|
|
70
|
-
coordinateSpace: "world",
|
|
71
|
-
unit: "board"
|
|
72
|
-
} } };
|
|
73
|
-
case "camera.focus": return { params: {
|
|
74
|
-
focus: {
|
|
75
|
-
coordinateSpace: "world",
|
|
76
|
-
unit: "board"
|
|
77
|
-
},
|
|
78
|
-
padding: {
|
|
79
|
-
coordinateSpace: "screen",
|
|
80
|
-
unit: "css-px"
|
|
81
|
-
},
|
|
82
|
-
minZoom: { unit: "ratio" },
|
|
83
|
-
maxZoom: { unit: "ratio" }
|
|
84
|
-
} };
|
|
85
|
-
case "camera.shake": return { params: { amount: {
|
|
86
|
-
coordinateSpace: "screen-offset",
|
|
87
|
-
unit: "css-px"
|
|
88
|
-
} } };
|
|
89
|
-
default: return;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
function effectSchema(id) {
|
|
93
|
-
switch (id) {
|
|
94
|
-
case "effects.deal": return { params: {
|
|
95
|
-
lift: { unit: "board" },
|
|
96
|
-
swing: { unit: "board" },
|
|
97
|
-
curve: { unit: "board" },
|
|
98
|
-
tilt: { unit: "degree" },
|
|
99
|
-
scale: { unit: "ratio" },
|
|
100
|
-
duration: { unit: "ms" },
|
|
101
|
-
landing: { unit: "ms" }
|
|
102
|
-
} };
|
|
103
|
-
default: return;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
const BOARD_BUILTIN_CAPABILITIES = [...BOARD_BUILTIN_CLIP_KINDS.map((id) => {
|
|
107
|
-
const schema = clipSchema(id);
|
|
108
|
-
return {
|
|
109
|
-
kind: "clip",
|
|
110
|
-
id,
|
|
111
|
-
version: 1,
|
|
112
|
-
renderers: ["webgpu", "webgl"],
|
|
113
|
-
...schema ? { schema } : {}
|
|
114
|
-
};
|
|
115
|
-
}), ...BOARD_BUILTIN_EFFECT_KINDS.map((id) => {
|
|
116
|
-
const schema = effectSchema(id);
|
|
117
|
-
return {
|
|
118
|
-
kind: "effect",
|
|
119
|
-
id,
|
|
120
|
-
version: 1,
|
|
121
|
-
renderers: ["webgpu", "webgl"],
|
|
122
|
-
...schema ? { schema } : {}
|
|
123
|
-
};
|
|
124
|
-
})];
|
|
125
12
|
//#endregion
|
|
126
|
-
export { BOARD_ARROW_STROKE_SIZE,
|
|
13
|
+
export { BOARD_ARROW_STROKE_SIZE, BOARD_FONT_STACK, BOARD_MONO_FONT_STACK, BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, BOARD_TEXT_FONT_FAMILY, clampBoardStrokeSize };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { BoardArrowAnchor, BoardArrowBinding, BoardArrowEnd, BoardDrawPoint, BoardItem, BoardTextItem, BoardVec2 } from "./board-model.js";
|
|
2
|
+
//#region ../protocol/dist/board-layout.d.ts
|
|
3
|
+
type BoardRect = {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
};
|
|
9
|
+
type BoardFrame = BoardRect & {
|
|
10
|
+
rotation: number;
|
|
11
|
+
};
|
|
12
|
+
type BoardMatrix = readonly [number, number, number, number, number, number];
|
|
13
|
+
declare const IDENTITY_MATRIX: BoardMatrix;
|
|
14
|
+
declare function multiplyMatrix(parent: BoardMatrix, child: BoardMatrix): BoardMatrix;
|
|
15
|
+
declare function invertMatrix(matrix: BoardMatrix): BoardMatrix;
|
|
16
|
+
declare function applyMatrix(matrix: BoardMatrix, point: BoardVec2): BoardVec2;
|
|
17
|
+
declare function scaleVector(scale: BoardItem["scale"]): BoardVec2;
|
|
18
|
+
type BoardTextMeasurer = (text: string, fontSize: number, fontWeight: number, font: string) => number | null;
|
|
19
|
+
declare function setBoardTextMeasurer(measurer?: BoardTextMeasurer): void;
|
|
20
|
+
declare function estimateTextWidth(text: string, fontSize: number): number;
|
|
21
|
+
type BoardTextLayout = {
|
|
22
|
+
width: number;
|
|
23
|
+
height: number;
|
|
24
|
+
lines: string[];
|
|
25
|
+
lineHeight: number;
|
|
26
|
+
};
|
|
27
|
+
declare function clampBoardFontSize(fontSize: number): number;
|
|
28
|
+
declare function layoutBoardText(props: Pick<BoardTextItem["props"], "text" | "fontSize" | "fontWeight" | "font" | "lineHeight" | "width">): BoardTextLayout;
|
|
29
|
+
declare function drawSampleRadius(strokeWidth: number, pressure: number): number;
|
|
30
|
+
declare function drawPointsBounds(points: readonly BoardDrawPoint[], strokeWidth: number): BoardRect;
|
|
31
|
+
declare function pointsRect(points: readonly BoardVec2[]): BoardRect;
|
|
32
|
+
declare function isArrowBinding(end: BoardArrowEnd): end is BoardArrowBinding;
|
|
33
|
+
declare function arrowBindings(item: BoardItem): string[];
|
|
34
|
+
declare function bendControl(start: BoardVec2, end: BoardVec2, bend: number): BoardVec2;
|
|
35
|
+
type BoardItemLookup = (id: string) => BoardItem | undefined;
|
|
36
|
+
type BoardLayout = {
|
|
37
|
+
has(id: string): boolean;
|
|
38
|
+
box(id: string): BoardRect;
|
|
39
|
+
matrix(id: string): BoardMatrix;
|
|
40
|
+
localMatrix(id: string): BoardMatrix;
|
|
41
|
+
parentMatrix(id: string): BoardMatrix;
|
|
42
|
+
bounds(id: string): BoardRect;
|
|
43
|
+
frame(id: string): BoardFrame;
|
|
44
|
+
arrowEnd(id: string, which: "start" | "end"): BoardVec2;
|
|
45
|
+
setLookup(lookup: BoardItemLookup): void;
|
|
46
|
+
invalidate(ids?: Iterable<string>): void;
|
|
47
|
+
};
|
|
48
|
+
declare function createBoardLayout(initialLookup: BoardItemLookup, dependents?: (id: string) => Iterable<string>): BoardLayout;
|
|
49
|
+
declare function rotateAround(point: BoardVec2, pivot: BoardVec2, degrees: number): BoardVec2;
|
|
50
|
+
declare function framePoint(frame: BoardFrame, nx: number, ny: number): BoardVec2;
|
|
51
|
+
declare function autoAnchorSide(frame: BoardFrame, toward: BoardVec2): "top" | "right" | "bottom" | "left";
|
|
52
|
+
declare function sideAnchor(side: "top" | "right" | "bottom" | "left", offset: number): {
|
|
53
|
+
x: number;
|
|
54
|
+
y: number;
|
|
55
|
+
};
|
|
56
|
+
declare function anchorPoint(frame: BoardFrame, anchor: BoardArrowAnchor, toward: BoardVec2): BoardVec2;
|
|
57
|
+
declare function createDocumentLayout(items: Readonly<Record<string, BoardItem>>): BoardLayout;
|
|
58
|
+
//#endregion
|
|
59
|
+
export { BoardFrame, BoardItemLookup, BoardLayout, BoardMatrix, BoardRect, BoardTextLayout, BoardTextMeasurer, IDENTITY_MATRIX, anchorPoint, applyMatrix, arrowBindings, autoAnchorSide, bendControl, clampBoardFontSize, createBoardLayout, createDocumentLayout, drawPointsBounds, drawSampleRadius, estimateTextWidth, framePoint, invertMatrix, isArrowBinding, layoutBoardText, multiplyMatrix, pointsRect, rotateAround, scaleVector, setBoardTextMeasurer, sideAnchor };
|
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
import "./board-constants.js";
|
|
2
|
+
//#region ../protocol/dist/board-layout.js
|
|
3
|
+
const IDENTITY_MATRIX = [
|
|
4
|
+
1,
|
|
5
|
+
0,
|
|
6
|
+
0,
|
|
7
|
+
1,
|
|
8
|
+
0,
|
|
9
|
+
0
|
|
10
|
+
];
|
|
11
|
+
function multiplyMatrix(parent, child) {
|
|
12
|
+
const [a1, b1, c1, d1, tx1, ty1] = parent;
|
|
13
|
+
const [a2, b2, c2, d2, tx2, ty2] = child;
|
|
14
|
+
return [
|
|
15
|
+
a1 * a2 + c1 * b2,
|
|
16
|
+
b1 * a2 + d1 * b2,
|
|
17
|
+
a1 * c2 + c1 * d2,
|
|
18
|
+
b1 * c2 + d1 * d2,
|
|
19
|
+
a1 * tx2 + c1 * ty2 + tx1,
|
|
20
|
+
b1 * tx2 + d1 * ty2 + ty1
|
|
21
|
+
];
|
|
22
|
+
}
|
|
23
|
+
function invertMatrix(matrix) {
|
|
24
|
+
const [a, b, c, d, tx, ty] = matrix;
|
|
25
|
+
const det = a * d - b * c || 1e-12;
|
|
26
|
+
return [
|
|
27
|
+
d / det,
|
|
28
|
+
-b / det,
|
|
29
|
+
-c / det,
|
|
30
|
+
a / det,
|
|
31
|
+
(c * ty - d * tx) / det,
|
|
32
|
+
(b * tx - a * ty) / det
|
|
33
|
+
];
|
|
34
|
+
}
|
|
35
|
+
function applyMatrix(matrix, point) {
|
|
36
|
+
const [a, b, c, d, tx, ty] = matrix;
|
|
37
|
+
return {
|
|
38
|
+
x: a * point.x + c * point.y + tx,
|
|
39
|
+
y: b * point.x + d * point.y + ty
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function scaleVector(scale) {
|
|
43
|
+
return typeof scale === "number" ? {
|
|
44
|
+
x: scale,
|
|
45
|
+
y: scale
|
|
46
|
+
} : scale;
|
|
47
|
+
}
|
|
48
|
+
let textMeasurer;
|
|
49
|
+
function setBoardTextMeasurer(measurer) {
|
|
50
|
+
textMeasurer = measurer;
|
|
51
|
+
textSizeCache.clear();
|
|
52
|
+
}
|
|
53
|
+
function isWideCharacter(code) {
|
|
54
|
+
return code >= 4352 && code <= 4447 || code >= 11904 && code <= 42191 || code >= 44032 && code <= 55203 || code >= 63744 && code <= 64255 || code >= 65072 && code <= 65103 || code >= 65280 && code <= 65376 || code >= 65504 && code <= 65510 || code >= 127744 && code <= 129791 || code >= 131072 && code <= 262141;
|
|
55
|
+
}
|
|
56
|
+
function estimateTextWidth(text, fontSize) {
|
|
57
|
+
let ems = 0;
|
|
58
|
+
for (const character of text) {
|
|
59
|
+
const code = character.codePointAt(0) ?? 0;
|
|
60
|
+
if (character === " ") ems += .28;
|
|
61
|
+
else if (isWideCharacter(code)) ems += 1;
|
|
62
|
+
else if (/[il.,:;'|!]/.test(character)) ems += .3;
|
|
63
|
+
else if (/[mwMW@]/.test(character)) ems += .85;
|
|
64
|
+
else if (/[A-Z0-9]/.test(character)) ems += .64;
|
|
65
|
+
else ems += .55;
|
|
66
|
+
}
|
|
67
|
+
return ems * fontSize;
|
|
68
|
+
}
|
|
69
|
+
function measureLine(text, fontSize, fontWeight, font) {
|
|
70
|
+
return textMeasurer?.(text, fontSize, fontWeight, font) ?? estimateTextWidth(text, fontSize);
|
|
71
|
+
}
|
|
72
|
+
function wrapParagraph(paragraph, width, measure) {
|
|
73
|
+
if (!paragraph) return [""];
|
|
74
|
+
const tokens = paragraph.match(/[\u1100-\u115f\u2e80-\ua4cf\uac00-\ud7a3\uf900-\ufaff\uff00-\uff60]|[^\s\u1100-\u115f\u2e80-\ua4cf\uac00-\ud7a3\uf900-\ufaff\uff00-\uff60]+|\s+/g) ?? [paragraph];
|
|
75
|
+
const lines = [];
|
|
76
|
+
let line = "";
|
|
77
|
+
for (const token of tokens) {
|
|
78
|
+
const candidate = line + token;
|
|
79
|
+
if (!line || measure(candidate.trimEnd()) <= width) {
|
|
80
|
+
line = candidate;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
lines.push(line.trimEnd());
|
|
84
|
+
line = /^\s+$/.test(token) ? "" : token;
|
|
85
|
+
}
|
|
86
|
+
lines.push(line.trimEnd());
|
|
87
|
+
return lines;
|
|
88
|
+
}
|
|
89
|
+
const textSizeCache = /* @__PURE__ */ new Map();
|
|
90
|
+
const TEXT_CACHE_LIMIT = 4096;
|
|
91
|
+
function clampBoardFontSize(fontSize) {
|
|
92
|
+
return Math.min(512, Math.max(2, fontSize));
|
|
93
|
+
}
|
|
94
|
+
function layoutBoardText(props) {
|
|
95
|
+
const fontSize = clampBoardFontSize(props.fontSize ?? 24);
|
|
96
|
+
const key = `${fontSize}|${props.fontWeight}|${props.font}|${props.lineHeight}|${props.width ?? ""}|${props.text}`;
|
|
97
|
+
const cached = textSizeCache.get(key);
|
|
98
|
+
if (cached) return cached;
|
|
99
|
+
const measure = (text) => measureLine(text, fontSize, props.fontWeight ?? 500, props.font ?? "sans");
|
|
100
|
+
const paragraphs = (props.text || "").split("\n");
|
|
101
|
+
const lines = props.width ? paragraphs.flatMap((paragraph) => wrapParagraph(paragraph, props.width, measure)) : paragraphs;
|
|
102
|
+
const lineHeight = fontSize * (props.lineHeight ?? 4 / 3);
|
|
103
|
+
const widest = lines.reduce((max, line) => Math.max(max, measure(line)), 0);
|
|
104
|
+
const layout = {
|
|
105
|
+
width: Math.max(props.width ?? 0, widest, fontSize * .5),
|
|
106
|
+
height: Math.max(1, lines.length) * lineHeight,
|
|
107
|
+
lines,
|
|
108
|
+
lineHeight
|
|
109
|
+
};
|
|
110
|
+
if (textSizeCache.size >= TEXT_CACHE_LIMIT) textSizeCache.clear();
|
|
111
|
+
textSizeCache.set(key, layout);
|
|
112
|
+
return layout;
|
|
113
|
+
}
|
|
114
|
+
function drawSampleRadius(strokeWidth, pressure) {
|
|
115
|
+
const clamped = Math.min(1, Math.max(0, pressure));
|
|
116
|
+
return Math.max(.5, strokeWidth / 2 * (.5 + clamped));
|
|
117
|
+
}
|
|
118
|
+
function drawPointsBounds(points, strokeWidth) {
|
|
119
|
+
if (points.length === 0) return {
|
|
120
|
+
x: 0,
|
|
121
|
+
y: 0,
|
|
122
|
+
width: 1,
|
|
123
|
+
height: 1
|
|
124
|
+
};
|
|
125
|
+
let minX = Number.POSITIVE_INFINITY;
|
|
126
|
+
let minY = Number.POSITIVE_INFINITY;
|
|
127
|
+
let maxX = Number.NEGATIVE_INFINITY;
|
|
128
|
+
let maxY = Number.NEGATIVE_INFINITY;
|
|
129
|
+
for (const point of points) {
|
|
130
|
+
const radius = drawSampleRadius(strokeWidth, point.p);
|
|
131
|
+
minX = Math.min(minX, point.x - radius);
|
|
132
|
+
minY = Math.min(minY, point.y - radius);
|
|
133
|
+
maxX = Math.max(maxX, point.x + radius);
|
|
134
|
+
maxY = Math.max(maxY, point.y + radius);
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
x: minX,
|
|
138
|
+
y: minY,
|
|
139
|
+
width: Math.max(1, maxX - minX),
|
|
140
|
+
height: Math.max(1, maxY - minY)
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function pointsRect(points) {
|
|
144
|
+
let minX = Number.POSITIVE_INFINITY;
|
|
145
|
+
let minY = Number.POSITIVE_INFINITY;
|
|
146
|
+
let maxX = Number.NEGATIVE_INFINITY;
|
|
147
|
+
let maxY = Number.NEGATIVE_INFINITY;
|
|
148
|
+
for (const point of points) {
|
|
149
|
+
minX = Math.min(minX, point.x);
|
|
150
|
+
minY = Math.min(minY, point.y);
|
|
151
|
+
maxX = Math.max(maxX, point.x);
|
|
152
|
+
maxY = Math.max(maxY, point.y);
|
|
153
|
+
}
|
|
154
|
+
if (!Number.isFinite(minX)) return {
|
|
155
|
+
x: 0,
|
|
156
|
+
y: 0,
|
|
157
|
+
width: 1,
|
|
158
|
+
height: 1
|
|
159
|
+
};
|
|
160
|
+
return {
|
|
161
|
+
x: minX,
|
|
162
|
+
y: minY,
|
|
163
|
+
width: Math.max(1, maxX - minX),
|
|
164
|
+
height: Math.max(1, maxY - minY)
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function isArrowBinding(end) {
|
|
168
|
+
return typeof end.item === "string";
|
|
169
|
+
}
|
|
170
|
+
function arrowBindings(item) {
|
|
171
|
+
if (item.type !== "arrow") return [];
|
|
172
|
+
const props = item.props;
|
|
173
|
+
const ids = [props.start, props.end].filter(isArrowBinding).map((end) => end.item);
|
|
174
|
+
return [...new Set(ids)];
|
|
175
|
+
}
|
|
176
|
+
function bendControl(start, end, bend) {
|
|
177
|
+
const mid = {
|
|
178
|
+
x: (start.x + end.x) / 2,
|
|
179
|
+
y: (start.y + end.y) / 2
|
|
180
|
+
};
|
|
181
|
+
if (!bend) return mid;
|
|
182
|
+
const dx = end.x - start.x;
|
|
183
|
+
const dy = end.y - start.y;
|
|
184
|
+
const length = Math.hypot(dx, dy) || 1;
|
|
185
|
+
const offset = bend * length;
|
|
186
|
+
return {
|
|
187
|
+
x: mid.x + -dy / length * offset,
|
|
188
|
+
y: mid.y + dx / length * offset
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
const MAX_DEPTH = 64;
|
|
192
|
+
function createBoardLayout(initialLookup, dependents) {
|
|
193
|
+
let lookup = initialLookup;
|
|
194
|
+
const boxes = /* @__PURE__ */ new Map();
|
|
195
|
+
const matrices = /* @__PURE__ */ new Map();
|
|
196
|
+
const bounds = /* @__PURE__ */ new Map();
|
|
197
|
+
function matrixOf(id, depth = 0) {
|
|
198
|
+
const cached = matrices.get(id);
|
|
199
|
+
if (cached) return cached;
|
|
200
|
+
const item = lookup(id);
|
|
201
|
+
if (!item) return IDENTITY_MATRIX;
|
|
202
|
+
const matrix = multiplyMatrix(item.parent && depth < MAX_DEPTH && lookup(item.parent) ? matrixOf(item.parent, depth + 1) : IDENTITY_MATRIX, localMatrixOf(id));
|
|
203
|
+
matrices.set(id, matrix);
|
|
204
|
+
return matrix;
|
|
205
|
+
}
|
|
206
|
+
function localMatrixOf(id) {
|
|
207
|
+
const item = lookup(id);
|
|
208
|
+
if (!item) return IDENTITY_MATRIX;
|
|
209
|
+
if (item.type === "arrow") return translate(item.position);
|
|
210
|
+
const box = boxOf(id);
|
|
211
|
+
const scale = scaleVector(item.scale);
|
|
212
|
+
const radians = item.rotation * Math.PI / 180;
|
|
213
|
+
const cos = Math.cos(radians);
|
|
214
|
+
const sin = Math.sin(radians);
|
|
215
|
+
const ox = box.x + item.origin.x * box.width;
|
|
216
|
+
const oy = box.y + item.origin.y * box.height;
|
|
217
|
+
const a = cos * scale.x;
|
|
218
|
+
const b = sin * scale.x;
|
|
219
|
+
const c = -sin * scale.y;
|
|
220
|
+
const d = cos * scale.y;
|
|
221
|
+
return [
|
|
222
|
+
a,
|
|
223
|
+
b,
|
|
224
|
+
c,
|
|
225
|
+
d,
|
|
226
|
+
item.position.x + ox - (a * ox + c * oy),
|
|
227
|
+
item.position.y + oy - (b * ox + d * oy)
|
|
228
|
+
];
|
|
229
|
+
}
|
|
230
|
+
function boxOf(id, depth = 0) {
|
|
231
|
+
const cached = boxes.get(id);
|
|
232
|
+
if (cached) return cached;
|
|
233
|
+
const item = lookup(id);
|
|
234
|
+
let box;
|
|
235
|
+
if (!item) box = {
|
|
236
|
+
x: 0,
|
|
237
|
+
y: 0,
|
|
238
|
+
width: 1,
|
|
239
|
+
height: 1
|
|
240
|
+
};
|
|
241
|
+
else if ("size" in item && item.size) box = {
|
|
242
|
+
x: 0,
|
|
243
|
+
y: 0,
|
|
244
|
+
width: item.size.width,
|
|
245
|
+
height: item.size.height
|
|
246
|
+
};
|
|
247
|
+
else if (item.type === "text") {
|
|
248
|
+
const layout = layoutBoardText(item.props);
|
|
249
|
+
box = {
|
|
250
|
+
x: 0,
|
|
251
|
+
y: 0,
|
|
252
|
+
width: layout.width,
|
|
253
|
+
height: layout.height
|
|
254
|
+
};
|
|
255
|
+
} else if (item.type === "draw") box = drawPointsBounds(item.props.points, item.style.strokeWidth ?? 4);
|
|
256
|
+
else if (item.type === "arrow") {
|
|
257
|
+
const props = item.props;
|
|
258
|
+
const toLocal = invertMatrix(multiplyMatrix(parentOf(item, depth), translate(item.position)));
|
|
259
|
+
const start = isArrowBinding(props.start) ? applyMatrix(toLocal, resolveBoundEnd(item, props.start, props.end, depth)) : props.start;
|
|
260
|
+
const end = isArrowBinding(props.end) ? applyMatrix(toLocal, resolveBoundEnd(item, props.end, props.start, depth)) : props.end;
|
|
261
|
+
const points = [
|
|
262
|
+
start,
|
|
263
|
+
end,
|
|
264
|
+
...props.waypoints
|
|
265
|
+
];
|
|
266
|
+
if (props.bend) points.push(bendControl(start, end, props.bend));
|
|
267
|
+
const rect = pointsRect(points);
|
|
268
|
+
const pad = Math.max(8, (item.style.strokeWidth ?? 2.5) * 2);
|
|
269
|
+
box = {
|
|
270
|
+
x: rect.x - pad,
|
|
271
|
+
y: rect.y - pad,
|
|
272
|
+
width: rect.width + pad * 2,
|
|
273
|
+
height: rect.height + pad * 2
|
|
274
|
+
};
|
|
275
|
+
} else box = {
|
|
276
|
+
x: 0,
|
|
277
|
+
y: 0,
|
|
278
|
+
width: 240,
|
|
279
|
+
height: 160
|
|
280
|
+
};
|
|
281
|
+
boxes.set(id, box);
|
|
282
|
+
return box;
|
|
283
|
+
}
|
|
284
|
+
function parentOf(item, depth) {
|
|
285
|
+
return item.parent && depth < MAX_DEPTH && lookup(item.parent) ? matrixOf(item.parent, depth + 1) : IDENTITY_MATRIX;
|
|
286
|
+
}
|
|
287
|
+
function resolveBoundEnd(arrow, end, other, depth) {
|
|
288
|
+
const target = lookup(end.item);
|
|
289
|
+
const arrowSpace = multiplyMatrix(parentOf(arrow, depth), translate(arrow.position));
|
|
290
|
+
if (!target || target.type === "arrow" || depth >= MAX_DEPTH) return applyMatrix(arrowSpace, {
|
|
291
|
+
x: 0,
|
|
292
|
+
y: 0
|
|
293
|
+
});
|
|
294
|
+
const frame = frameOf(end.item, depth + 1);
|
|
295
|
+
const toward = isArrowBinding(other) ? lookup(other.item) && lookup(other.item)?.type !== "arrow" ? center(frameOf(other.item, depth + 1)) : center(frame) : applyMatrix(arrowSpace, other);
|
|
296
|
+
return anchorPoint(frame, end.anchor, toward);
|
|
297
|
+
}
|
|
298
|
+
function frameOf(id, depth = 0) {
|
|
299
|
+
boxOf(id, depth);
|
|
300
|
+
const box = boxes.get(id);
|
|
301
|
+
const matrix = matrixOf(id, depth);
|
|
302
|
+
const [a, b, c, d] = matrix;
|
|
303
|
+
const centerPoint = applyMatrix(matrix, {
|
|
304
|
+
x: box.x + box.width / 2,
|
|
305
|
+
y: box.y + box.height / 2
|
|
306
|
+
});
|
|
307
|
+
const width = box.width * Math.hypot(a, b);
|
|
308
|
+
const height = box.height * Math.hypot(c, d);
|
|
309
|
+
return {
|
|
310
|
+
x: centerPoint.x - width / 2,
|
|
311
|
+
y: centerPoint.y - height / 2,
|
|
312
|
+
width,
|
|
313
|
+
height,
|
|
314
|
+
rotation: Math.atan2(b, a) * 180 / Math.PI
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
function boundsOf(id) {
|
|
318
|
+
const cached = bounds.get(id);
|
|
319
|
+
if (cached) return cached;
|
|
320
|
+
const box = boxOf(id);
|
|
321
|
+
const matrix = matrixOf(id);
|
|
322
|
+
const rect = pointsRect([
|
|
323
|
+
applyMatrix(matrix, {
|
|
324
|
+
x: box.x,
|
|
325
|
+
y: box.y
|
|
326
|
+
}),
|
|
327
|
+
applyMatrix(matrix, {
|
|
328
|
+
x: box.x + box.width,
|
|
329
|
+
y: box.y
|
|
330
|
+
}),
|
|
331
|
+
applyMatrix(matrix, {
|
|
332
|
+
x: box.x + box.width,
|
|
333
|
+
y: box.y + box.height
|
|
334
|
+
}),
|
|
335
|
+
applyMatrix(matrix, {
|
|
336
|
+
x: box.x,
|
|
337
|
+
y: box.y + box.height
|
|
338
|
+
})
|
|
339
|
+
]);
|
|
340
|
+
bounds.set(id, rect);
|
|
341
|
+
return rect;
|
|
342
|
+
}
|
|
343
|
+
function setLookup(nextLookup) {
|
|
344
|
+
lookup = nextLookup;
|
|
345
|
+
}
|
|
346
|
+
function invalidate(ids) {
|
|
347
|
+
if (!ids) {
|
|
348
|
+
boxes.clear();
|
|
349
|
+
matrices.clear();
|
|
350
|
+
bounds.clear();
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
const queue = [...ids];
|
|
354
|
+
const seen = /* @__PURE__ */ new Set();
|
|
355
|
+
while (queue.length) {
|
|
356
|
+
const id = queue.pop();
|
|
357
|
+
if (seen.has(id)) continue;
|
|
358
|
+
seen.add(id);
|
|
359
|
+
boxes.delete(id);
|
|
360
|
+
matrices.delete(id);
|
|
361
|
+
bounds.delete(id);
|
|
362
|
+
if (dependents) for (const next of dependents(id)) queue.push(next);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return {
|
|
366
|
+
has: (id) => lookup(id) !== void 0,
|
|
367
|
+
box: (id) => boxOf(id),
|
|
368
|
+
matrix: (id) => matrixOf(id),
|
|
369
|
+
localMatrix: (id) => localMatrixOf(id),
|
|
370
|
+
parentMatrix: (id) => {
|
|
371
|
+
const item = lookup(id);
|
|
372
|
+
return item ? parentOf(item, 0) : IDENTITY_MATRIX;
|
|
373
|
+
},
|
|
374
|
+
bounds: boundsOf,
|
|
375
|
+
frame: (id) => frameOf(id),
|
|
376
|
+
arrowEnd: (id, which) => {
|
|
377
|
+
const item = lookup(id);
|
|
378
|
+
if (item?.type !== "arrow") return {
|
|
379
|
+
x: 0,
|
|
380
|
+
y: 0
|
|
381
|
+
};
|
|
382
|
+
const arrow = item;
|
|
383
|
+
const [end, other] = which === "start" ? [arrow.props.start, arrow.props.end] : [arrow.props.end, arrow.props.start];
|
|
384
|
+
return isArrowBinding(end) ? resolveBoundEnd(arrow, end, other, 0) : applyMatrix(matrixOf(id), end);
|
|
385
|
+
},
|
|
386
|
+
invalidate,
|
|
387
|
+
setLookup
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
function translate(point) {
|
|
391
|
+
return [
|
|
392
|
+
1,
|
|
393
|
+
0,
|
|
394
|
+
0,
|
|
395
|
+
1,
|
|
396
|
+
point.x,
|
|
397
|
+
point.y
|
|
398
|
+
];
|
|
399
|
+
}
|
|
400
|
+
function center(frame) {
|
|
401
|
+
return {
|
|
402
|
+
x: frame.x + frame.width / 2,
|
|
403
|
+
y: frame.y + frame.height / 2
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
function rotateAround(point, pivot, degrees) {
|
|
407
|
+
if (!degrees) return point;
|
|
408
|
+
const radians = degrees * Math.PI / 180;
|
|
409
|
+
const cos = Math.cos(radians);
|
|
410
|
+
const sin = Math.sin(radians);
|
|
411
|
+
const dx = point.x - pivot.x;
|
|
412
|
+
const dy = point.y - pivot.y;
|
|
413
|
+
return {
|
|
414
|
+
x: pivot.x + dx * cos - dy * sin,
|
|
415
|
+
y: pivot.y + dx * sin + dy * cos
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
function framePoint(frame, nx, ny) {
|
|
419
|
+
return rotateAround({
|
|
420
|
+
x: frame.x + nx * frame.width,
|
|
421
|
+
y: frame.y + ny * frame.height
|
|
422
|
+
}, center(frame), frame.rotation);
|
|
423
|
+
}
|
|
424
|
+
function autoAnchorSide(frame, toward) {
|
|
425
|
+
const local = rotateAround(toward, center(frame), -frame.rotation);
|
|
426
|
+
const c = center(frame);
|
|
427
|
+
const dx = (local.x - c.x) / Math.max(frame.width / 2, 1e-4);
|
|
428
|
+
const dy = (local.y - c.y) / Math.max(frame.height / 2, 1e-4);
|
|
429
|
+
if (Math.abs(dx) >= Math.abs(dy)) return dx >= 0 ? "right" : "left";
|
|
430
|
+
return dy >= 0 ? "bottom" : "top";
|
|
431
|
+
}
|
|
432
|
+
function sideAnchor(side, offset) {
|
|
433
|
+
switch (side) {
|
|
434
|
+
case "top": return {
|
|
435
|
+
x: offset,
|
|
436
|
+
y: 0
|
|
437
|
+
};
|
|
438
|
+
case "bottom": return {
|
|
439
|
+
x: offset,
|
|
440
|
+
y: 1
|
|
441
|
+
};
|
|
442
|
+
case "left": return {
|
|
443
|
+
x: 0,
|
|
444
|
+
y: offset
|
|
445
|
+
};
|
|
446
|
+
default: return {
|
|
447
|
+
x: 1,
|
|
448
|
+
y: offset
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
function anchorPoint(frame, anchor, toward) {
|
|
453
|
+
if (anchor === "auto") {
|
|
454
|
+
const normalized = sideAnchor(autoAnchorSide(frame, toward), .5);
|
|
455
|
+
return framePoint(frame, normalized.x, normalized.y);
|
|
456
|
+
}
|
|
457
|
+
if ("side" in anchor) {
|
|
458
|
+
const normalized = sideAnchor(anchor.side, anchor.offset);
|
|
459
|
+
return framePoint(frame, normalized.x, normalized.y);
|
|
460
|
+
}
|
|
461
|
+
return framePoint(frame, anchor.x, anchor.y);
|
|
462
|
+
}
|
|
463
|
+
function createDocumentLayout(items) {
|
|
464
|
+
let index = null;
|
|
465
|
+
const dependents = (id) => {
|
|
466
|
+
if (!index) {
|
|
467
|
+
index = /* @__PURE__ */ new Map();
|
|
468
|
+
for (const [itemId, item] of Object.entries(items)) {
|
|
469
|
+
const refs = [...item.parent ? [item.parent] : [], ...arrowBindings(item)];
|
|
470
|
+
for (const ref of refs) {
|
|
471
|
+
const list = index.get(ref) ?? [];
|
|
472
|
+
list.push(itemId);
|
|
473
|
+
index.set(ref, list);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
return index.get(id) ?? [];
|
|
478
|
+
};
|
|
479
|
+
return createBoardLayout((id) => items[id], dependents);
|
|
480
|
+
}
|
|
481
|
+
//#endregion
|
|
482
|
+
export { IDENTITY_MATRIX, anchorPoint, applyMatrix, arrowBindings, autoAnchorSide, bendControl, clampBoardFontSize, createBoardLayout, createDocumentLayout, drawPointsBounds, drawSampleRadius, estimateTextWidth, framePoint, invertMatrix, isArrowBinding, layoutBoardText, multiplyMatrix, pointsRect, rotateAround, scaleVector, setBoardTextMeasurer, sideAnchor };
|