@lupinum/board-connections 0.1.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.
@@ -0,0 +1,99 @@
1
+ import { type PropType } from 'vue';
2
+ import type { Point } from '@lupinum/board-core';
3
+ /** SVG foreign-object label editor used by the connection render shell. */
4
+ export declare const ConnectionLabel: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
5
+ edgeId: {
6
+ type: StringConstructor;
7
+ required: true;
8
+ };
9
+ point: {
10
+ type: PropType<Point>;
11
+ required: true;
12
+ };
13
+ label: {
14
+ type: StringConstructor;
15
+ default: string;
16
+ };
17
+ color: {
18
+ type: StringConstructor;
19
+ default: string;
20
+ };
21
+ zoom: {
22
+ type: NumberConstructor;
23
+ required: true;
24
+ };
25
+ selected: {
26
+ type: BooleanConstructor;
27
+ default: boolean;
28
+ };
29
+ hovered: {
30
+ type: BooleanConstructor;
31
+ default: boolean;
32
+ };
33
+ editing: {
34
+ type: BooleanConstructor;
35
+ default: boolean;
36
+ };
37
+ draft: {
38
+ type: StringConstructor;
39
+ default: string;
40
+ };
41
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
42
+ [key: string]: any;
43
+ }> | null, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
44
+ edgePointerDown: (_edgeId: string, _event: PointerEvent) => true;
45
+ beginEdit: (_edgeId: string) => true;
46
+ updateDraft: (_value: string) => true;
47
+ commitEdit: () => true;
48
+ cancelEdit: () => true;
49
+ }, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
50
+ edgeId: {
51
+ type: StringConstructor;
52
+ required: true;
53
+ };
54
+ point: {
55
+ type: PropType<Point>;
56
+ required: true;
57
+ };
58
+ label: {
59
+ type: StringConstructor;
60
+ default: string;
61
+ };
62
+ color: {
63
+ type: StringConstructor;
64
+ default: string;
65
+ };
66
+ zoom: {
67
+ type: NumberConstructor;
68
+ required: true;
69
+ };
70
+ selected: {
71
+ type: BooleanConstructor;
72
+ default: boolean;
73
+ };
74
+ hovered: {
75
+ type: BooleanConstructor;
76
+ default: boolean;
77
+ };
78
+ editing: {
79
+ type: BooleanConstructor;
80
+ default: boolean;
81
+ };
82
+ draft: {
83
+ type: StringConstructor;
84
+ default: string;
85
+ };
86
+ }>> & Readonly<{
87
+ onEdgePointerDown?: ((_edgeId: string, _event: PointerEvent) => any) | undefined;
88
+ onBeginEdit?: ((_edgeId: string) => any) | undefined;
89
+ onUpdateDraft?: ((_value: string) => any) | undefined;
90
+ onCommitEdit?: (() => any) | undefined;
91
+ onCancelEdit?: (() => any) | undefined;
92
+ }>, {
93
+ label: string;
94
+ color: string;
95
+ selected: boolean;
96
+ hovered: boolean;
97
+ editing: boolean;
98
+ draft: string;
99
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,19 @@
1
+ import { type VNode } from 'vue';
2
+ import type { Point } from '@lupinum/board-core';
3
+ import type { BoardEdge } from './types.js';
4
+ export interface ConnectionToolbarOptions {
5
+ edge: BoardEdge;
6
+ screen: Point;
7
+ colorMenuOpen: boolean;
8
+ directionMenuOpen: boolean;
9
+ onDelete: () => void;
10
+ onToggleColorMenu: () => void;
11
+ onToggleDirectionMenu: () => void;
12
+ onSetColor: (color: string | undefined) => void;
13
+ onSetDirectionality: (direction: 'none' | 'to' | 'both') => void;
14
+ onResetAnchor: (end: 'from' | 'to' | 'both') => void;
15
+ onClearLabel: () => void;
16
+ onBeginLabelEdit: () => void;
17
+ }
18
+ /** Render the selected-edge toolbar without owning connection domain state. */
19
+ export declare function renderConnectionToolbar(options: ConnectionToolbarOptions): VNode;
@@ -0,0 +1,50 @@
1
+ import type { NodeId, Point } from '@lupinum/board-core';
2
+ import type { AnchorPosition, AnchorSide } from './types.js';
3
+ export type DragEnd = 'from' | 'to';
4
+ export type ReconnectDragState = {
5
+ mode: 'reconnect';
6
+ edgeId: string;
7
+ end: DragEnd;
8
+ pointerId: number;
9
+ pointerWorld: Point;
10
+ candidateNodeId: NodeId | null;
11
+ candidateAnchor: AnchorPosition | null;
12
+ };
13
+ export type CreateDragState = {
14
+ mode: 'create';
15
+ sourceNodeId: NodeId;
16
+ sourceSide: AnchorSide;
17
+ pointerId: number;
18
+ pointerWorld: Point;
19
+ candidateNodeId: NodeId | null;
20
+ candidateAnchor: AnchorPosition | null;
21
+ };
22
+ export type ConnectionDragState = ReconnectDragState | CreateDragState;
23
+ export type PendingConnectionDrag = {
24
+ mode: 'reconnect';
25
+ edgeId: string;
26
+ end: DragEnd;
27
+ pointerId: number;
28
+ startWorld: Point;
29
+ } | {
30
+ mode: 'create';
31
+ sourceNodeId: NodeId;
32
+ sourceSide: AnchorSide;
33
+ pointerId: number;
34
+ startWorld: Point;
35
+ };
36
+ interface AdvanceDragInput {
37
+ pending: PendingConnectionDrag | null;
38
+ active: ConnectionDragState | null;
39
+ pointerId: number;
40
+ pointerWorld: Point;
41
+ candidateNodeId: NodeId | null;
42
+ candidateAnchor: AnchorPosition | null;
43
+ zoom: number;
44
+ threshold: number;
45
+ }
46
+ export declare function advanceConnectionDrag(input: AdvanceDragInput): {
47
+ pending: PendingConnectionDrag | null;
48
+ active: ConnectionDragState | null;
49
+ };
50
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { EdgeEnd } from './types.js';
2
+ /** Arrow placement policy shared by connection defaults and editing commands. */
3
+ export type ConnectionDirectionality = 'none' | 'start' | 'end' | 'both';
4
+ /** Resolve a directionality choice to the persisted edge endpoint markers. */
5
+ export declare function edgeEndsForDirectionality(directionality: ConnectionDirectionality): {
6
+ fromEnd: EdgeEnd;
7
+ toEnd: EdgeEnd;
8
+ };
@@ -0,0 +1,23 @@
1
+ import { type BoardEngine, type BoardNode, type Bounds, type Point } from '@lupinum/board-core';
2
+ import type { AnchorPosition, AnchorSide, BoardEdge, ConnectionRoute, ConnectionRouting, ConnectionsApi, ResolvedConnectionEndpoint } from './types.js';
3
+ export declare function resolveAnchorPoint(node: Pick<BoardNode, 'x' | 'y' | 'width' | 'height'>, anchor: AnchorPosition): Point;
4
+ export declare function resolveAutoAnchorSide(source: Pick<BoardNode, 'x' | 'y' | 'width' | 'height'>, target: Pick<BoardNode, 'x' | 'y' | 'width' | 'height'>, _role: 'source' | 'target', previousSide?: AnchorSide): AnchorSide;
5
+ export declare function resolveConnectionEndpoint(edge: BoardEdge, node: Pick<BoardNode, 'id' | 'x' | 'y' | 'width' | 'height'>, otherNode: Pick<BoardNode, 'id' | 'x' | 'y' | 'width' | 'height'>, role: 'source' | 'target', previousSide?: AnchorSide): ResolvedConnectionEndpoint;
6
+ export declare function resolveFloatingEndpoint(pointValue: Point, otherPoint: Point, role: 'source' | 'target', previousSide?: AnchorSide): ResolvedConnectionEndpoint;
7
+ export declare function buildConnectionRoute(params: {
8
+ source: ResolvedConnectionEndpoint;
9
+ target: ResolvedConnectionEndpoint;
10
+ routing?: ConnectionRouting;
11
+ }): ConnectionRoute;
12
+ export declare function resolveEdgeRenderState(edge: BoardEdge, sourceNode: Pick<BoardNode, 'id' | 'x' | 'y' | 'width' | 'height'>, targetNode: Pick<BoardNode, 'id' | 'x' | 'y' | 'width' | 'height'>, options?: {
13
+ routing?: ConnectionRouting;
14
+ previousSourceSide?: AnchorSide;
15
+ previousTargetSide?: AnchorSide;
16
+ }): {
17
+ source: ResolvedConnectionEndpoint;
18
+ target: ResolvedConnectionEndpoint;
19
+ route: ConnectionRoute;
20
+ };
21
+ export declare function getVisibleEdges(engine: BoardEngine<{
22
+ connections: ConnectionsApi;
23
+ }>, bounds: Bounds, routing?: ConnectionRouting): BoardEdge[];
@@ -0,0 +1,11 @@
1
+ import type { BoardNode, NodeId, Point } from '@lupinum/board-core';
2
+ import type { AnchorSide } from './types.js';
3
+ export interface ConnectionNodeHandle {
4
+ nodeId: NodeId;
5
+ side: AnchorSide;
6
+ offset: number;
7
+ }
8
+ export declare function edgeIdFromTarget(target: EventTarget | null): string | null;
9
+ export declare function nodeHandleFromTarget(target: EventTarget | null): ConnectionNodeHandle | null;
10
+ export declare function sameEdgeTarget(target: EventTarget | null, edgeId: string): boolean;
11
+ export declare function resolveNodeHandleAtWorldPoint(nodes: Iterable<BoardNode>, point: Point, threshold: number, cornerClearance: number): ConnectionNodeHandle | null;
@@ -0,0 +1,17 @@
1
+ /** Install the connections plugin and its `engine.plugins.connections` API. */
2
+ export { connectionsPlugin } from './plugin.js';
3
+ /** Shared mapping from directionality choices to persisted endpoint markers. */
4
+ export { edgeEndsForDirectionality } from './directionality.js';
5
+ export type { ConnectionDirectionality } from './directionality.js';
6
+ /** Geometry helpers for resolving anchors, routes, and render state. */
7
+ export { buildConnectionRoute, getVisibleEdges, resolveAnchorPoint, resolveAutoAnchorSide, resolveConnectionEndpoint, resolveFloatingEndpoint, resolveEdgeRenderState, } from './geometry.js';
8
+ /** Arc routing helper inspired by hand-drawn arrow curves. */
9
+ export { buildArcRoute } from './routing/arc.js';
10
+ /** Options for tuning arc routing curvature. */
11
+ export type { ArcOptions } from './routing/arc.js';
12
+ /** Color helpers and presets used by edge rendering and toolbars. */
13
+ export { EDGE_COLOR_PRESETS, colorForPreset, presetForColor, resolvePresetColor, } from './colors.js';
14
+ /** Types for custom edge colors and preset names. */
15
+ export type { EdgeColorOption, EdgeColorPreset } from './colors.js';
16
+ /** Core edge model types and the connections engine API contract. */
17
+ export type { AnchorPosition, AnchorSide, BoardEdge, BoardEdgePatch, ConnectionConfig, ConnectionEndpointMode, ConnectionPluginOptions, ConnectionRoute, ConnectionRouteSegment, ConnectionRouting, ConnectionsApi, ConnectionsEventMap, CreateNodeForConnectionContext, EdgeEnd, ResolvedConnectionEndpoint, } from './types.js';
package/dist/index.js ADDED
@@ -0,0 +1,298 @@
1
+ import { asNodeId as S, asEdgeId as C, BoardNotFoundError as h, BoardConflictError as z, BoardInputError as b } from "@lupinum/board-core";
2
+ import { defineInternalBoardPlugin as T } from "@lupinum/board-core/internal";
3
+ import { e as $ } from "./colors-CI4AZ9tI.js";
4
+ import { E as Z, b as L, a as k, c as H, g as J, p as V, r as q, d as K, f as Q, h as W, i as X, j as Y } from "./colors-CI4AZ9tI.js";
5
+ const F = "connections", P = /* @__PURE__ */ new Set(["top", "right", "bottom", "left"]);
6
+ function w(r, f) {
7
+ if (r) {
8
+ if (!P.has(r.side))
9
+ throw new b(
10
+ `Cannot use ${f}: anchor side "${String(r.side)}" is unsupported.`
11
+ );
12
+ if (!Number.isFinite(r.offset) || r.offset < 0 || r.offset > 1)
13
+ throw new b(
14
+ `Cannot use ${f}: anchor offset must be a finite number from 0 to 1.`
15
+ );
16
+ }
17
+ }
18
+ function v(r) {
19
+ if (r !== void 0 && !/^[1-6]$/.test(r) && !/^#[0-9a-fA-F]{6}$/.test(r))
20
+ throw new b(
21
+ `Cannot use edge color "${r}": expected a preset from 1 to 6 or a six-digit hex color.`
22
+ );
23
+ }
24
+ const _ = {
25
+ edges: /* @__PURE__ */ new Map(),
26
+ nextZIndex: 1
27
+ };
28
+ function N(r, f, A) {
29
+ switch (f.type) {
30
+ case "EDGE_CREATED": {
31
+ const a = A ?? new Map(r.edges);
32
+ return a.set(f.edge.id, f.edge), {
33
+ edges: a,
34
+ nextZIndex: Math.max(r.nextZIndex, f.edge.zIndex + 1)
35
+ };
36
+ }
37
+ case "EDGE_UPDATED": {
38
+ const a = A ?? new Map(r.edges);
39
+ return a.set(f.id, f.after), { ...r, edges: a };
40
+ }
41
+ case "EDGE_DELETED": {
42
+ if (!r.edges.has(f.id)) return r;
43
+ const a = A ?? new Map(r.edges);
44
+ return a.delete(f.id), { ...r, edges: a };
45
+ }
46
+ }
47
+ }
48
+ function m(r) {
49
+ return {
50
+ ...r,
51
+ data: structuredClone(r.data)
52
+ };
53
+ }
54
+ function M(r) {
55
+ return {
56
+ id: r.id,
57
+ fromNode: r.from,
58
+ ...r.fromAnchor?.side ? { fromSide: r.fromAnchor.side } : {},
59
+ ...r.fromEnd ? { fromEnd: r.fromEnd } : {},
60
+ toNode: r.to,
61
+ ...r.toAnchor?.side ? { toSide: r.toAnchor.side } : {},
62
+ ...r.toEnd ? { toEnd: r.toEnd } : {},
63
+ ...r.color ? { color: r.color } : {},
64
+ ...r.label ? { label: r.label } : {}
65
+ };
66
+ }
67
+ function B(r = {}) {
68
+ const f = r.routing ?? "bezier", A = r.endpointMode ?? "auto", a = r.defaultArrow ?? "end", y = {
69
+ routing: f,
70
+ endpointMode: A,
71
+ defaultArrow: a
72
+ }, D = $(a);
73
+ return T({
74
+ name: F,
75
+ slice: {
76
+ initial: _
77
+ },
78
+ nodeDeleted(d, c) {
79
+ d.updatePluginState((s) => {
80
+ const l = new Map(s.edges);
81
+ for (const [E, n] of l)
82
+ (n.from === c || n.to === c) && l.delete(E);
83
+ return l.size === s.edges.size ? s : { ...s, edges: l };
84
+ });
85
+ },
86
+ persistence: {
87
+ exportDocument(d) {
88
+ const c = d.plugins.connections.getEdges();
89
+ return c.length === 0 ? {} : {
90
+ edges: c.map(M),
91
+ "x-vue-board": {
92
+ edges: Object.fromEntries(
93
+ c.map((s) => [
94
+ s.id,
95
+ {
96
+ zIndex: s.zIndex,
97
+ ...Object.keys(s.data).length > 0 ? { data: s.data } : {}
98
+ }
99
+ ])
100
+ )
101
+ }
102
+ };
103
+ },
104
+ loadDocument(d, c, s, l) {
105
+ const E = d.plugins.connections;
106
+ if (s === "replace")
107
+ for (const n of E.getEdges())
108
+ E.deleteEdge(n.id);
109
+ for (const n of c.edges ?? []) {
110
+ const u = S(n.fromNode), x = S(n.toNode), e = l.get(u) ?? u, o = l.get(x) ?? x;
111
+ if (!d.hasNode(e) || !d.hasNode(o))
112
+ continue;
113
+ const t = c["x-vue-board"]?.edges?.[n.id], i = s === "merge" && E.getEdge(C(n.id)) ? C(crypto.randomUUID()) : C(n.id);
114
+ E.createEdge({
115
+ id: i,
116
+ from: e,
117
+ to: o,
118
+ ...n.fromSide ? { fromAnchor: { side: n.fromSide, offset: 0.5 } } : {},
119
+ ...n.toSide ? { toAnchor: { side: n.toSide, offset: 0.5 } } : {},
120
+ ...n.fromEnd ? { fromEnd: n.fromEnd } : {},
121
+ ...n.toEnd ? { toEnd: n.toEnd } : {},
122
+ ...n.color ? { color: n.color } : {},
123
+ ...n.label ? { label: n.label } : {},
124
+ data: t?.data ?? {},
125
+ ...t?.zIndex !== void 0 ? { zIndex: t.zIndex } : {}
126
+ });
127
+ }
128
+ }
129
+ },
130
+ install(d) {
131
+ const c = () => d.getPluginState();
132
+ let s = null;
133
+ const l = (e) => d.updatePluginState((o) => d.isBatching() ? (o.edges !== s && (s = new Map(o.edges)), N(o, e, s)) : (s = null, N(o, e)));
134
+ function E(e, o) {
135
+ const t = c().edges.get(e);
136
+ if (!t)
137
+ throw new h(
138
+ `Cannot ${o} edge: edge "${e}" does not exist.`
139
+ );
140
+ return t;
141
+ }
142
+ const n = {
143
+ createEdge(e) {
144
+ return d.runCommand(
145
+ "edge:create",
146
+ [e],
147
+ () => {
148
+ if (!d.hasNode(e.from))
149
+ throw new h(
150
+ `Cannot create edge: source node "${e.from}" does not exist.`
151
+ );
152
+ if (!d.hasNode(e.to))
153
+ throw new h(
154
+ `Cannot create edge: target node "${e.to}" does not exist.`
155
+ );
156
+ const o = c(), t = e.id ?? C(crypto.randomUUID());
157
+ if (o.edges.has(t))
158
+ throw new z(
159
+ `Cannot create edge: edge "${t}" already exists.`
160
+ );
161
+ if (w(e.fromAnchor, "fromAnchor"), w(e.toAnchor, "toAnchor"), v(e.color), e.zIndex !== void 0 && !Number.isFinite(e.zIndex))
162
+ throw new b(
163
+ "Cannot create edge: zIndex must be a finite number."
164
+ );
165
+ const i = {
166
+ id: t,
167
+ from: e.from,
168
+ to: e.to,
169
+ fromAnchor: e.fromAnchor,
170
+ toAnchor: e.toAnchor,
171
+ fromEnd: e.fromEnd ?? D.fromEnd,
172
+ toEnd: e.toEnd ?? D.toEnd,
173
+ label: e.label,
174
+ color: e.color,
175
+ data: structuredClone(e.data ?? {}),
176
+ zIndex: e.zIndex ?? o.nextZIndex
177
+ };
178
+ return l({ type: "EDGE_CREATED", edge: i }), m(i);
179
+ },
180
+ { history: "record" }
181
+ );
182
+ },
183
+ updateEdge(e, o) {
184
+ const t = E(e, "update");
185
+ return d.runCommand(
186
+ "edge:update",
187
+ [e, o],
188
+ () => {
189
+ const i = "from" in o ? o.from : t.from, g = "to" in o ? o.to : t.to;
190
+ if (!i || !d.hasNode(i))
191
+ throw new h(
192
+ `Cannot update edge: source node "${i}" does not exist.`
193
+ );
194
+ if (!g || !d.hasNode(g))
195
+ throw new h(
196
+ `Cannot update edge: target node "${g}" does not exist.`
197
+ );
198
+ w(
199
+ "fromAnchor" in o ? o.fromAnchor : t.fromAnchor,
200
+ "fromAnchor"
201
+ ), w(
202
+ "toAnchor" in o ? o.toAnchor : t.toAnchor,
203
+ "toAnchor"
204
+ ), v("color" in o ? o.color : t.color);
205
+ const I = {
206
+ ...t,
207
+ from: i,
208
+ to: g,
209
+ fromAnchor: "fromAnchor" in o ? o.fromAnchor : t.fromAnchor,
210
+ toAnchor: "toAnchor" in o ? o.toAnchor : t.toAnchor,
211
+ fromEnd: "fromEnd" in o ? o.fromEnd : t.fromEnd,
212
+ toEnd: "toEnd" in o ? o.toEnd : t.toEnd,
213
+ label: "label" in o ? o.label : t.label,
214
+ color: "color" in o ? o.color : t.color,
215
+ data: "data" in o ? structuredClone(o.data ?? {}) : structuredClone(t.data)
216
+ };
217
+ return l({
218
+ type: "EDGE_UPDATED",
219
+ id: e,
220
+ after: I
221
+ }), m(I);
222
+ },
223
+ { history: "record" }
224
+ );
225
+ },
226
+ deleteEdge(e) {
227
+ c().edges.get(e) && d.runCommand(
228
+ "edge:delete",
229
+ [e],
230
+ () => {
231
+ l({ type: "EDGE_DELETED", id: e });
232
+ },
233
+ { history: "record" }
234
+ );
235
+ },
236
+ getEdge(e) {
237
+ const o = c().edges.get(e);
238
+ return o ? m(o) : void 0;
239
+ },
240
+ getEdges() {
241
+ return Array.from(
242
+ c().edges.values(),
243
+ (e) => m(e)
244
+ );
245
+ },
246
+ getEdgesFrom(e) {
247
+ return n.getEdges().filter((o) => o.from === e);
248
+ },
249
+ getEdgesTo(e) {
250
+ return n.getEdges().filter((o) => o.to === e);
251
+ },
252
+ getEdgesBetween(e, o) {
253
+ return n.getEdges().filter((t) => t.from === e && t.to === o);
254
+ },
255
+ getConfig() {
256
+ return d.assertActive(), { ...y };
257
+ }
258
+ };
259
+ d.extend("connections", n);
260
+ let u = c().edges;
261
+ const x = d.projectCommit(() => {
262
+ const e = c().edges;
263
+ if (e === u) return () => {
264
+ };
265
+ const o = u;
266
+ return () => {
267
+ s = null;
268
+ for (const [t, i] of e) {
269
+ const g = o.get(t);
270
+ g ? g !== i && d.emit("edge:updated", m(i), m(g)) : d.emit("edge:created", m(i));
271
+ }
272
+ for (const [t] of o)
273
+ e.has(t) || d.emit("edge:deleted", t);
274
+ u = e;
275
+ };
276
+ });
277
+ return () => {
278
+ x();
279
+ };
280
+ }
281
+ });
282
+ }
283
+ export {
284
+ Z as EDGE_COLOR_PRESETS,
285
+ L as buildArcRoute,
286
+ k as buildConnectionRoute,
287
+ H as colorForPreset,
288
+ B as connectionsPlugin,
289
+ $ as edgeEndsForDirectionality,
290
+ J as getVisibleEdges,
291
+ V as presetForColor,
292
+ q as resolveAnchorPoint,
293
+ K as resolveAutoAnchorSide,
294
+ Q as resolveConnectionEndpoint,
295
+ W as resolveEdgeRenderState,
296
+ X as resolveFloatingEndpoint,
297
+ Y as resolvePresetColor
298
+ };
@@ -0,0 +1,26 @@
1
+ import type { BoardEngine, BoardNode, Point } from '@lupinum/board-core';
2
+ import type { AnchorPosition, AnchorSide } from './types.js';
3
+ export interface EdgeRenderLayerContext {
4
+ toLocalPoint(clientX: number, clientY: number): Point;
5
+ }
6
+ export declare const CONNECTION_DRAG_THRESHOLD = 6;
7
+ export declare const EDGE_STROKE_LOD_FADE_START = 0.95;
8
+ export declare const EDGE_STROKE_LOD_SOFTEN_AT = 0.45;
9
+ export declare const EDGE_ARROW_MARKER_SIZE = 18;
10
+ export declare const EDGE_ARROW_SCREEN_SIZE = 16;
11
+ export declare const EDGE_ARROW_MIN_SCREEN_SIZE = 10;
12
+ export declare const EDGE_ARROW_MAX_SCREEN_SIZE = 22;
13
+ export declare const EDGE_LABEL_MIN_ZOOM = 0.1;
14
+ export declare const EDGE_LABEL_MAX_SCREEN_WIDTH = 220;
15
+ export declare const EDGE_LABEL_HORIZONTAL_PADDING = 20;
16
+ export declare const EDGE_LABEL_IDLE_HEIGHT = 18;
17
+ export declare const EDGE_LABEL_ACTIVE_HEIGHT = 24;
18
+ export declare const EDGE_LABEL_SCREEN_FONT_SIZE = 14;
19
+ export declare const EDGE_LABEL_ACTIVE_FONT_SIZE = 13;
20
+ export declare function clamp01(value: number): number;
21
+ export declare function resolveLodAmount(zoom: number, fadeStart: number, minDetailAt: number): number;
22
+ export declare function resolveArrowScreenSize(zoom: number): number;
23
+ export declare function worldPointFromClient(ctx: EdgeRenderLayerContext, engine: BoardEngine, clientX: number, clientY: number): Point;
24
+ export declare function floatingNodeAt(point: Point, role: 'source' | 'target'): Pick<BoardNode, 'id' | 'x' | 'y' | 'width' | 'height'>;
25
+ export declare function anchorForPointOnNode(node: Pick<BoardNode, 'x' | 'y' | 'width' | 'height'>, side: AnchorSide, point: Point): AnchorPosition;
26
+ export declare function sameAnchor(left: AnchorPosition | undefined, right: AnchorPosition | null): boolean;
@@ -0,0 +1,38 @@
1
+ import { type PropType } from 'vue';
2
+ import { type BoardNode } from '@lupinum/board-core';
3
+ import type { ConnectionEndpointMode, CreateNodeForConnectionContext, ConnectionRouting } from './types.js';
4
+ export declare const BoardConnectionLayer: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
5
+ routing: {
6
+ type: PropType<ConnectionRouting | undefined>;
7
+ default: undefined;
8
+ };
9
+ endpointMode: {
10
+ type: PropType<ConnectionEndpointMode | undefined>;
11
+ default: undefined;
12
+ };
13
+ createNodeForConnection: {
14
+ type: PropType<(context: CreateNodeForConnectionContext) => BoardNode | null>;
15
+ default: null;
16
+ };
17
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
18
+ [key: string]: any;
19
+ }> | import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
20
+ [key: string]: any;
21
+ }>[], {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
22
+ routing: {
23
+ type: PropType<ConnectionRouting | undefined>;
24
+ default: undefined;
25
+ };
26
+ endpointMode: {
27
+ type: PropType<ConnectionEndpointMode | undefined>;
28
+ default: undefined;
29
+ };
30
+ createNodeForConnection: {
31
+ type: PropType<(context: CreateNodeForConnectionContext) => BoardNode | null>;
32
+ default: null;
33
+ };
34
+ }>> & Readonly<{}>, {
35
+ routing: ConnectionRouting | undefined;
36
+ endpointMode: ConnectionEndpointMode | undefined;
37
+ createNodeForConnection: (context: CreateNodeForConnectionContext) => BoardNode | null;
38
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,7 @@
1
+ import { type BoardPlugin, type BoardPluginApis } from '@lupinum/board-core';
2
+ import type { ConnectionPluginOptions, ConnectionsApi, ConnectionsEventMap } from './types.js';
3
+ interface ConnectionsPluginApis extends BoardPluginApis {
4
+ connections: ConnectionsApi;
5
+ }
6
+ export declare function connectionsPlugin(options?: ConnectionPluginOptions): BoardPlugin<ConnectionsPluginApis, ConnectionsEventMap>;
7
+ export {};
@@ -0,0 +1,32 @@
1
+ import { type VNode } from 'vue';
2
+ import type { BoardNode } from '@lupinum/board-core';
3
+ import type { ConnectionDragState } from './controller.js';
4
+ import type { BoardEdge, ResolvedConnectionEndpoint } from './types.js';
5
+ import type { buildConnectionRoute } from './geometry.js';
6
+ export interface ConnectionRenderEntry {
7
+ edge: BoardEdge;
8
+ route: ReturnType<typeof buildConnectionRoute>;
9
+ }
10
+ export declare function renderDefaultEdgePath(options: {
11
+ entry: ConnectionRenderEntry;
12
+ markerId: string;
13
+ stroke: string;
14
+ opacity: number;
15
+ strokeWidth: number;
16
+ }): VNode;
17
+ interface PreviewRenderState {
18
+ edge: BoardEdge | null;
19
+ source: ResolvedConnectionEndpoint;
20
+ target: ResolvedConnectionEndpoint;
21
+ route: ReturnType<typeof buildConnectionRoute>;
22
+ candidateNode: BoardNode | null | undefined;
23
+ }
24
+ export declare function renderConnectionPreview(options: {
25
+ preview: PreviewRenderState;
26
+ drag: ConnectionDragState;
27
+ markerId: string;
28
+ zoom: number;
29
+ handleRadius: number;
30
+ strokeWidth: number;
31
+ }): Array<VNode | null>;
32
+ export {};
@@ -0,0 +1,11 @@
1
+ import type { ConnectionRoute, ResolvedConnectionEndpoint } from '../types.js';
2
+ export interface ArcOptions {
3
+ bow?: number;
4
+ stretch?: number;
5
+ stretchMin?: number;
6
+ stretchMax?: number;
7
+ padStart?: number;
8
+ padEnd?: number;
9
+ flip?: boolean;
10
+ }
11
+ export declare function buildArcRoute(source: ResolvedConnectionEndpoint, target: ResolvedConnectionEndpoint, options?: ArcOptions): ConnectionRoute;