@neta-art/cohub 5.3.3 → 5.4.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/codec.d.ts +2 -0
- package/dist/board/codec.js +18 -13
- package/dist/board/core/arrow-geometry.d.ts +23 -0
- package/dist/board/core/arrow-geometry.js +109 -0
- package/dist/board/core/connections.d.ts +83 -0
- package/dist/board/core/connections.js +399 -0
- package/dist/board/core/export-plan.d.ts +15 -4
- package/dist/board/core/export-plan.js +49 -16
- package/dist/board/core/shape-definition.js +1 -1
- package/dist/board/core/shape-types.d.ts +8 -2
- package/dist/board/core/shape-types.js +1 -1
- package/dist/board/core/tool-styles.d.ts +9 -3
- package/dist/board/core/tool-styles.js +10 -6
- package/dist/board/export/index.js +1 -0
- package/dist/board/export/scene.d.ts +3 -0
- package/dist/board/export/scene.js +18 -1
- package/dist/board/index.d.ts +8 -5
- package/dist/board/index.js +8 -5
- package/dist/board/render/connection-layer.d.ts +48 -0
- package/dist/board/render/connection-layer.js +223 -0
- package/dist/board/render/index.d.ts +2 -1
- package/dist/board/render/index.js +3 -2
- package/dist/board/render/renderers/arrow-card-renderer.js +35 -48
- package/dist/chunks/http.d.ts +53 -1
- package/dist/chunks/http.js +287 -1
- package/dist/chunks/websocket.d.ts +296 -57
- package/dist/http.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +17 -56
- package/dist/protocol/dist/board-connection.d.ts +310 -0
- package/dist/protocol/dist/board-connection.js +215 -0
- package/dist/protocol/dist/board-constants.d.ts +11 -1
- package/dist/protocol/dist/board-constants.js +15 -1
- package/dist/protocol/dist/board-document.d.ts +106 -60
- package/dist/protocol/dist/board-document.js +57 -17
- package/dist/protocol/dist/board.d.ts +1 -0
- package/dist/protocol/dist/board.js +3 -0
- package/dist/protocol/dist/index.d.ts +2 -1
- package/dist/protocol/dist/index.js +2 -1
- package/dist/protocol/dist/realtime/board-awareness.js +15 -15
- package/package.json +1 -1
- package/dist/board/core/bindings.d.ts +0 -45
- package/dist/board/core/bindings.js +0 -162
|
@@ -35,6 +35,20 @@ const BOARD_BUILTIN_EFFECT_KINDS = ["effects.pulse", "effects.float"];
|
|
|
35
35
|
*/
|
|
36
36
|
const BOARD_TEXT_FONT_FAMILY = "Geist";
|
|
37
37
|
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
|
+
const BOARD_STROKE_MIN_SIZE = 1;
|
|
47
|
+
const BOARD_STROKE_MAX_SIZE = 64;
|
|
48
|
+
function clampBoardStrokeSize(size) {
|
|
49
|
+
if (!Number.isFinite(size)) return BOARD_CONNECTION_STROKE_SIZE;
|
|
50
|
+
return Math.min(64, Math.max(1, size));
|
|
51
|
+
}
|
|
38
52
|
/**
|
|
39
53
|
* Font stacks used by every board renderer.
|
|
40
54
|
*
|
|
@@ -58,4 +72,4 @@ const BOARD_BUILTIN_CAPABILITIES = [...BOARD_BUILTIN_CLIP_KINDS.map((id) => ({
|
|
|
58
72
|
renderers: ["webgpu", "webgl"]
|
|
59
73
|
}))];
|
|
60
74
|
//#endregion
|
|
61
|
-
export { BOARD_ARROW_STROKE_SIZE, BOARD_BUILTIN_CAPABILITIES, BOARD_BUILTIN_CLIP_KINDS, BOARD_BUILTIN_EFFECT_KINDS, BOARD_FONT_STACK, BOARD_MONO_FONT_STACK, BOARD_TEXT_FONT_FAMILY, DEFAULT_BOARD_RENDER_LIMITS };
|
|
75
|
+
export { BOARD_ARROW_STROKE_SIZE, BOARD_BUILTIN_CAPABILITIES, BOARD_BUILTIN_CLIP_KINDS, BOARD_BUILTIN_EFFECT_KINDS, BOARD_CONNECTION_STROKE_SIZE, BOARD_FONT_STACK, BOARD_MONO_FONT_STACK, BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, BOARD_TEXT_FONT_FAMILY, DEFAULT_BOARD_RENDER_LIMITS, clampBoardStrokeSize };
|
|
@@ -150,6 +150,11 @@ declare const DrawPointSchema: z.ZodObject<{
|
|
|
150
150
|
y: z.ZodNumber;
|
|
151
151
|
p: z.ZodDefault<z.ZodNumber>;
|
|
152
152
|
}, z.core.$strip>;
|
|
153
|
+
/** A world-space point. */
|
|
154
|
+
declare const BoardPointSchema: z.ZodObject<{
|
|
155
|
+
x: z.ZodNumber;
|
|
156
|
+
y: z.ZodNumber;
|
|
157
|
+
}, z.core.$strip>;
|
|
153
158
|
declare const BoardDrawItemSchema: z.ZodObject<{
|
|
154
159
|
id: z.ZodString;
|
|
155
160
|
frame: z.ZodObject<{
|
|
@@ -187,18 +192,15 @@ declare const BoardDrawItemSchema: z.ZodObject<{
|
|
|
187
192
|
color: z.ZodDefault<z.ZodString>;
|
|
188
193
|
size: z.ZodDefault<z.ZodNumber>;
|
|
189
194
|
}, z.core.$strip>;
|
|
190
|
-
/**
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
ny: z.ZodDefault<z.ZodNumber>;
|
|
200
|
-
precise: z.ZodDefault<z.ZodBoolean>;
|
|
201
|
-
}, z.core.$strip>]>;
|
|
195
|
+
/**
|
|
196
|
+
* A free arrow — a standalone annotation stroke between two world points.
|
|
197
|
+
*
|
|
198
|
+
* Arrows do not relate nodes. A relation between two nodes is a
|
|
199
|
+
* `BoardConnection`, which is stored separately and resolves its geometry from
|
|
200
|
+
* the live node frames. Keeping the two apart is what lets an arrow be a plain
|
|
201
|
+
* shape (its own frame, freely movable) while a connection stays purely
|
|
202
|
+
* semantic — neither has to pretend to be the other.
|
|
203
|
+
*/
|
|
202
204
|
declare const BoardArrowItemSchema: z.ZodObject<{
|
|
203
205
|
id: z.ZodString;
|
|
204
206
|
frame: z.ZodObject<{
|
|
@@ -228,28 +230,14 @@ declare const BoardArrowItemSchema: z.ZodObject<{
|
|
|
228
230
|
}, z.core.$strip>>;
|
|
229
231
|
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
230
232
|
type: z.ZodLiteral<"arrow">;
|
|
231
|
-
start: z.
|
|
232
|
-
kind: z.ZodLiteral<"point">;
|
|
233
|
+
start: z.ZodObject<{
|
|
233
234
|
x: z.ZodNumber;
|
|
234
235
|
y: z.ZodNumber;
|
|
235
|
-
}, z.core.$strip
|
|
236
|
-
|
|
237
|
-
target: z.ZodString;
|
|
238
|
-
nx: z.ZodDefault<z.ZodNumber>;
|
|
239
|
-
ny: z.ZodDefault<z.ZodNumber>;
|
|
240
|
-
precise: z.ZodDefault<z.ZodBoolean>;
|
|
241
|
-
}, z.core.$strip>]>;
|
|
242
|
-
end: z.ZodUnion<readonly [z.ZodObject<{
|
|
243
|
-
kind: z.ZodLiteral<"point">;
|
|
236
|
+
}, z.core.$strip>;
|
|
237
|
+
end: z.ZodObject<{
|
|
244
238
|
x: z.ZodNumber;
|
|
245
239
|
y: z.ZodNumber;
|
|
246
|
-
}, z.core.$strip
|
|
247
|
-
kind: z.ZodLiteral<"binding">;
|
|
248
|
-
target: z.ZodString;
|
|
249
|
-
nx: z.ZodDefault<z.ZodNumber>;
|
|
250
|
-
ny: z.ZodDefault<z.ZodNumber>;
|
|
251
|
-
precise: z.ZodDefault<z.ZodBoolean>;
|
|
252
|
-
}, z.core.$strip>]>;
|
|
240
|
+
}, z.core.$strip>;
|
|
253
241
|
bend: z.ZodDefault<z.ZodNumber>;
|
|
254
242
|
color: z.ZodDefault<z.ZodString>;
|
|
255
243
|
size: z.ZodDefault<z.ZodNumber>;
|
|
@@ -677,26 +665,12 @@ declare const BoardItemSchema: z.ZodPipe<z.ZodAny, z.ZodTransform<BoardUnknownIt
|
|
|
677
665
|
metadata?: Record<string, unknown> | undefined;
|
|
678
666
|
type: "arrow";
|
|
679
667
|
start: {
|
|
680
|
-
kind: "point";
|
|
681
668
|
x: number;
|
|
682
669
|
y: number;
|
|
683
|
-
} | {
|
|
684
|
-
kind: "binding";
|
|
685
|
-
target: string;
|
|
686
|
-
nx: number;
|
|
687
|
-
ny: number;
|
|
688
|
-
precise: boolean;
|
|
689
670
|
};
|
|
690
671
|
end: {
|
|
691
|
-
kind: "point";
|
|
692
672
|
x: number;
|
|
693
673
|
y: number;
|
|
694
|
-
} | {
|
|
695
|
-
kind: "binding";
|
|
696
|
-
target: string;
|
|
697
|
-
nx: number;
|
|
698
|
-
ny: number;
|
|
699
|
-
precise: boolean;
|
|
700
674
|
};
|
|
701
675
|
bend: number;
|
|
702
676
|
color: string;
|
|
@@ -966,26 +940,12 @@ declare const BoardDocumentSchema: z.ZodObject<{
|
|
|
966
940
|
metadata?: Record<string, unknown> | undefined;
|
|
967
941
|
type: "arrow";
|
|
968
942
|
start: {
|
|
969
|
-
kind: "point";
|
|
970
943
|
x: number;
|
|
971
944
|
y: number;
|
|
972
|
-
} | {
|
|
973
|
-
kind: "binding";
|
|
974
|
-
target: string;
|
|
975
|
-
nx: number;
|
|
976
|
-
ny: number;
|
|
977
|
-
precise: boolean;
|
|
978
945
|
};
|
|
979
946
|
end: {
|
|
980
|
-
kind: "point";
|
|
981
947
|
x: number;
|
|
982
948
|
y: number;
|
|
983
|
-
} | {
|
|
984
|
-
kind: "binding";
|
|
985
|
-
target: string;
|
|
986
|
-
nx: number;
|
|
987
|
-
ny: number;
|
|
988
|
-
precise: boolean;
|
|
989
949
|
};
|
|
990
950
|
bend: number;
|
|
991
951
|
color: string;
|
|
@@ -1016,6 +976,76 @@ declare const BoardDocumentSchema: z.ZodObject<{
|
|
|
1016
976
|
label: string;
|
|
1017
977
|
color: string;
|
|
1018
978
|
}, any>>>;
|
|
979
|
+
connections: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
980
|
+
id: z.ZodString;
|
|
981
|
+
source: z.ZodObject<{
|
|
982
|
+
nodeId: z.ZodString;
|
|
983
|
+
anchor: z.ZodDefault<z.ZodUnion<readonly [z.ZodObject<{
|
|
984
|
+
kind: z.ZodLiteral<"auto">;
|
|
985
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
986
|
+
kind: z.ZodLiteral<"side">;
|
|
987
|
+
side: z.ZodEnum<{
|
|
988
|
+
bottom: "bottom";
|
|
989
|
+
left: "left";
|
|
990
|
+
right: "right";
|
|
991
|
+
top: "top";
|
|
992
|
+
}>;
|
|
993
|
+
offset: z.ZodDefault<z.ZodNumber>;
|
|
994
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
995
|
+
kind: z.ZodLiteral<"fixed">;
|
|
996
|
+
nx: z.ZodNumber;
|
|
997
|
+
ny: z.ZodNumber;
|
|
998
|
+
}, z.core.$strip>]>>;
|
|
999
|
+
}, z.core.$strip>;
|
|
1000
|
+
target: z.ZodObject<{
|
|
1001
|
+
nodeId: z.ZodString;
|
|
1002
|
+
anchor: z.ZodDefault<z.ZodUnion<readonly [z.ZodObject<{
|
|
1003
|
+
kind: z.ZodLiteral<"auto">;
|
|
1004
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
1005
|
+
kind: z.ZodLiteral<"side">;
|
|
1006
|
+
side: z.ZodEnum<{
|
|
1007
|
+
bottom: "bottom";
|
|
1008
|
+
left: "left";
|
|
1009
|
+
right: "right";
|
|
1010
|
+
top: "top";
|
|
1011
|
+
}>;
|
|
1012
|
+
offset: z.ZodDefault<z.ZodNumber>;
|
|
1013
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
1014
|
+
kind: z.ZodLiteral<"fixed">;
|
|
1015
|
+
nx: z.ZodNumber;
|
|
1016
|
+
ny: z.ZodNumber;
|
|
1017
|
+
}, z.core.$strip>]>>;
|
|
1018
|
+
}, z.core.$strip>;
|
|
1019
|
+
relation: z.ZodDefault<z.ZodString>;
|
|
1020
|
+
direction: z.ZodDefault<z.ZodEnum<{
|
|
1021
|
+
backward: "backward";
|
|
1022
|
+
both: "both";
|
|
1023
|
+
forward: "forward";
|
|
1024
|
+
none: "none";
|
|
1025
|
+
}>>;
|
|
1026
|
+
label: z.ZodDefault<z.ZodString>;
|
|
1027
|
+
routing: z.ZodDefault<z.ZodObject<{
|
|
1028
|
+
kind: z.ZodDefault<z.ZodEnum<{
|
|
1029
|
+
curve: "curve";
|
|
1030
|
+
orthogonal: "orthogonal";
|
|
1031
|
+
straight: "straight";
|
|
1032
|
+
}>>;
|
|
1033
|
+
bend: z.ZodDefault<z.ZodNumber>;
|
|
1034
|
+
waypoints: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
1035
|
+
x: z.ZodNumber;
|
|
1036
|
+
y: z.ZodNumber;
|
|
1037
|
+
}, z.core.$strip>>>;
|
|
1038
|
+
}, z.core.$strip>>;
|
|
1039
|
+
style: z.ZodDefault<z.ZodObject<{
|
|
1040
|
+
color: z.ZodDefault<z.ZodString>;
|
|
1041
|
+
size: z.ZodDefault<z.ZodNumber>;
|
|
1042
|
+
line: z.ZodDefault<z.ZodEnum<{
|
|
1043
|
+
dashed: "dashed";
|
|
1044
|
+
solid: "solid";
|
|
1045
|
+
}>>;
|
|
1046
|
+
}, z.core.$strip>>;
|
|
1047
|
+
metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1048
|
+
}, z.core.$strip>>>;
|
|
1019
1049
|
}, z.core.$strip>;
|
|
1020
1050
|
type BoardFrame = z.infer<typeof BoardFrameSchema>;
|
|
1021
1051
|
type BoardViewport = z.infer<typeof BoardViewportSchema>;
|
|
@@ -1026,8 +1056,8 @@ type BoardMediaSnapshot = z.infer<typeof BoardMediaSnapshotSchema>;
|
|
|
1026
1056
|
type BoardTextItem = z.infer<typeof BoardTextItemSchema>;
|
|
1027
1057
|
type BoardGeoItem = z.infer<typeof BoardGeoItemSchema>;
|
|
1028
1058
|
type DrawPoint = z.infer<typeof DrawPointSchema>;
|
|
1059
|
+
type BoardPoint = z.infer<typeof BoardPointSchema>;
|
|
1029
1060
|
type BoardDrawItem = z.infer<typeof BoardDrawItemSchema>;
|
|
1030
|
-
type ArrowEndpoint = z.infer<typeof ArrowEndpointSchema>;
|
|
1031
1061
|
type BoardArrowItem = z.infer<typeof BoardArrowItemSchema>;
|
|
1032
1062
|
type BoardFrameItem = z.infer<typeof BoardFrameItemSchema>;
|
|
1033
1063
|
type BoardImageItem = z.infer<typeof BoardImageItemSchema>;
|
|
@@ -1039,9 +1069,25 @@ type BoardKnownItem = BoardImageItem | BoardVideoItem | BoardFileItem | BoardTex
|
|
|
1039
1069
|
/** Any item, including forward-compatible unknown types. */
|
|
1040
1070
|
type BoardItem = BoardKnownItem | BoardUnknownItem;
|
|
1041
1071
|
type BoardDocument = z.infer<typeof BoardDocumentSchema>;
|
|
1072
|
+
/**
|
|
1073
|
+
* Parse a board document and drop connections whose endpoints are missing.
|
|
1074
|
+
*
|
|
1075
|
+
* The schema alone cannot express "every endpoint must name an existing item",
|
|
1076
|
+
* so referential integrity is enforced here, at the single place a document
|
|
1077
|
+
* enters the system. A dangling connection is dropped rather than repaired:
|
|
1078
|
+
* there is no correct node to invent, and keeping it would render nothing while
|
|
1079
|
+
* still counting as data.
|
|
1080
|
+
*
|
|
1081
|
+
* Item parsing stays lenient (see parseBoardItemLoose) — nodes carry content and
|
|
1082
|
+
* are never discarded — while connections are pure references and are only
|
|
1083
|
+
* meaningful with both ends present.
|
|
1084
|
+
*/
|
|
1085
|
+
declare function parseBoardDocument(input: unknown): BoardDocument;
|
|
1086
|
+
/** Keep only the connections whose endpoints both exist in `items`. */
|
|
1087
|
+
declare function withResolvedConnections(document: BoardDocument): BoardDocument;
|
|
1042
1088
|
declare function isUnknownItem(item: BoardItem): item is BoardUnknownItem;
|
|
1043
1089
|
declare function isMediaItem(item: BoardItem): item is BoardImageItem | BoardVideoItem;
|
|
1044
1090
|
/** Whether an item references a workspace file (image, video or file card). */
|
|
1045
1091
|
declare function isFileBackedItem(item: BoardItem): item is BoardImageItem | BoardVideoItem | BoardFileItem;
|
|
1046
1092
|
//#endregion
|
|
1047
|
-
export {
|
|
1093
|
+
export { BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BoardAppearance, BoardAppearanceSchema, BoardArrowItem, BoardArrowItemSchema, BoardDocument, BoardDocumentSchema, BoardDrawItem, BoardDrawItemSchema, BoardFileItem, BoardFileItemSchema, BoardFileSnapshot, BoardFileSnapshotSchema, BoardFrame, BoardFrameItem, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItem, BoardGeoItemSchema, BoardImageItem, BoardImageItemSchema, BoardItem, BoardItemSchema, BoardItemStyle, BoardItemStyleSchema, BoardKnownItem, BoardMediaSnapshot, BoardMediaSnapshotSchema, BoardPoint, BoardPointSchema, BoardTextItem, BoardTextItemSchema, BoardUnknownItem, BoardVideoItem, BoardVideoItemSchema, BoardViewport, BoardViewportSchema, DrawPoint, DrawPointSchema, KNOWN_BOARD_ITEM_TYPES, KnownBoardItemType, SpaceFileRef, SpaceFileRefSchema, UNKNOWN_BOARD_ITEM_TYPE, isFileBackedItem, isMediaItem, isUnknownItem, parseBoardDocument, parseBoardItemLoose, unknownRealType, withResolvedConnections };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BOARD_ARROW_STROKE_SIZE } from "./board-constants.js";
|
|
2
|
+
import { BoardConnectionSchema } from "./board-connection.js";
|
|
2
3
|
import { BOARD_DOCUMENT_KIND, BOARD_EXTENSION } from "./board.js";
|
|
3
4
|
import { z } from "zod";
|
|
4
5
|
//#region ../protocol/dist/board-document.js
|
|
@@ -110,29 +111,31 @@ const DrawPointSchema = z.object({
|
|
|
110
111
|
y: z.number().finite(),
|
|
111
112
|
p: z.number().finite().min(0).max(1).default(.5)
|
|
112
113
|
});
|
|
114
|
+
/** A world-space point. */
|
|
115
|
+
const BoardPointSchema = z.object({
|
|
116
|
+
x: z.number().finite(),
|
|
117
|
+
y: z.number().finite()
|
|
118
|
+
});
|
|
113
119
|
const BoardDrawItemSchema = BoardItemBaseSchema.extend({
|
|
114
120
|
type: z.literal("draw"),
|
|
115
121
|
points: z.array(DrawPointSchema).default([]),
|
|
116
122
|
color: z.string().min(1).default("brand"),
|
|
117
123
|
size: z.number().finite().positive().default(4)
|
|
118
124
|
});
|
|
119
|
-
/**
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
ny: z.number().finite().default(.5),
|
|
129
|
-
precise: z.boolean().default(true)
|
|
130
|
-
})]);
|
|
125
|
+
/**
|
|
126
|
+
* A free arrow — a standalone annotation stroke between two world points.
|
|
127
|
+
*
|
|
128
|
+
* Arrows do not relate nodes. A relation between two nodes is a
|
|
129
|
+
* `BoardConnection`, which is stored separately and resolves its geometry from
|
|
130
|
+
* the live node frames. Keeping the two apart is what lets an arrow be a plain
|
|
131
|
+
* shape (its own frame, freely movable) while a connection stays purely
|
|
132
|
+
* semantic — neither has to pretend to be the other.
|
|
133
|
+
*/
|
|
131
134
|
const BoardArrowItemSchema = BoardItemBaseSchema.extend({
|
|
132
135
|
type: z.literal("arrow"),
|
|
133
|
-
start:
|
|
134
|
-
end:
|
|
135
|
-
bend: z.number().finite().default(0),
|
|
136
|
+
start: BoardPointSchema,
|
|
137
|
+
end: BoardPointSchema,
|
|
138
|
+
bend: z.number().finite().min(-.85).max(.85).default(0),
|
|
136
139
|
color: z.string().min(1).default("brand"),
|
|
137
140
|
size: z.number().finite().positive().default(BOARD_ARROW_STROKE_SIZE),
|
|
138
141
|
arrowStart: z.boolean().default(false),
|
|
@@ -305,8 +308,45 @@ const BoardDocumentSchema = z.object({
|
|
|
305
308
|
mood: "clean"
|
|
306
309
|
}),
|
|
307
310
|
viewport: BoardViewportSchema,
|
|
308
|
-
items: z.array(BoardItemSchema)
|
|
311
|
+
items: z.array(BoardItemSchema),
|
|
312
|
+
/**
|
|
313
|
+
* Node relations. Separate from `items` because a connection has no frame of
|
|
314
|
+
* its own — its geometry is derived from the nodes it joins, so it is a
|
|
315
|
+
* relation over the item set rather than a member of it.
|
|
316
|
+
*
|
|
317
|
+
* Connections referencing a missing node are dropped on parse: a relation to
|
|
318
|
+
* nothing is not a relation, and keeping one would let an invisible dangling
|
|
319
|
+
* edge accumulate silently. Callers that need to know write through the
|
|
320
|
+
* transaction API, which reports the reference error instead.
|
|
321
|
+
*/
|
|
322
|
+
connections: z.array(BoardConnectionSchema).default([])
|
|
309
323
|
});
|
|
324
|
+
/**
|
|
325
|
+
* Parse a board document and drop connections whose endpoints are missing.
|
|
326
|
+
*
|
|
327
|
+
* The schema alone cannot express "every endpoint must name an existing item",
|
|
328
|
+
* so referential integrity is enforced here, at the single place a document
|
|
329
|
+
* enters the system. A dangling connection is dropped rather than repaired:
|
|
330
|
+
* there is no correct node to invent, and keeping it would render nothing while
|
|
331
|
+
* still counting as data.
|
|
332
|
+
*
|
|
333
|
+
* Item parsing stays lenient (see parseBoardItemLoose) — nodes carry content and
|
|
334
|
+
* are never discarded — while connections are pure references and are only
|
|
335
|
+
* meaningful with both ends present.
|
|
336
|
+
*/
|
|
337
|
+
function parseBoardDocument(input) {
|
|
338
|
+
return withResolvedConnections(BoardDocumentSchema.parse(input));
|
|
339
|
+
}
|
|
340
|
+
/** Keep only the connections whose endpoints both exist in `items`. */
|
|
341
|
+
function withResolvedConnections(document) {
|
|
342
|
+
if (document.connections.length === 0) return document;
|
|
343
|
+
const ids = new Set(document.items.map((item) => item.id));
|
|
344
|
+
const connections = document.connections.filter((connection) => ids.has(connection.source.nodeId) && ids.has(connection.target.nodeId));
|
|
345
|
+
return connections.length === document.connections.length ? document : {
|
|
346
|
+
...document,
|
|
347
|
+
connections
|
|
348
|
+
};
|
|
349
|
+
}
|
|
310
350
|
function isUnknownItem(item) {
|
|
311
351
|
return item.type === UNKNOWN_BOARD_ITEM_TYPE;
|
|
312
352
|
}
|
|
@@ -318,4 +358,4 @@ function isFileBackedItem(item) {
|
|
|
318
358
|
return item.type === "image" || item.type === "video" || item.type === "file";
|
|
319
359
|
}
|
|
320
360
|
//#endregion
|
|
321
|
-
export {
|
|
361
|
+
export { BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BoardAppearanceSchema, BoardArrowItemSchema, BoardDocumentSchema, BoardDrawItemSchema, BoardFileItemSchema, BoardFileSnapshotSchema, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItemSchema, BoardImageItemSchema, BoardItemSchema, BoardItemStyleSchema, BoardMediaSnapshotSchema, BoardPointSchema, BoardTextItemSchema, BoardVideoItemSchema, BoardViewportSchema, DrawPointSchema, KNOWN_BOARD_ITEM_TYPES, SpaceFileRefSchema, UNKNOWN_BOARD_ITEM_TYPE, isFileBackedItem, isMediaItem, isUnknownItem, parseBoardDocument, parseBoardItemLoose, unknownRealType, withResolvedConnections };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import "./board-constants.js";
|
|
2
|
+
import { BoardConnectionSchema } from "./board-connection.js";
|
|
2
3
|
import { z } from "zod";
|
|
3
4
|
//#region ../protocol/dist/board.js
|
|
4
5
|
const BOARD_EXTENSION = ".board";
|
|
@@ -149,6 +150,7 @@ z.object({
|
|
|
149
150
|
title: z.string().min(1).max(255).optional(),
|
|
150
151
|
metadata: jsonObjectSchema.optional(),
|
|
151
152
|
nodes: z.array(BoardNodeInputSchema).max(5e4).optional(),
|
|
153
|
+
connections: z.array(BoardConnectionSchema).max(5e4).optional(),
|
|
152
154
|
effects: z.array(BoardEffectSchema.omit({
|
|
153
155
|
boardId: true,
|
|
154
156
|
revision: true
|
|
@@ -164,6 +166,7 @@ z.object({
|
|
|
164
166
|
z.object({
|
|
165
167
|
include: z.array(z.enum([
|
|
166
168
|
"nodes",
|
|
169
|
+
"connections",
|
|
167
170
|
"effects",
|
|
168
171
|
"sequences",
|
|
169
172
|
"clips",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BoardCapability, BoardRenderCost } from "./board-constants.js";
|
|
2
|
+
import { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BoardConnection, BoardConnectionAnchor, BoardConnectionAnchorSchema, BoardConnectionDirection, BoardConnectionEndpoint, BoardConnectionEndpointSchema, BoardConnectionInput, BoardConnectionLine, BoardConnectionPatch, BoardConnectionPatchSchema, BoardConnectionRecord, BoardConnectionRouting, BoardConnectionRoutingConfig, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionSide, BoardConnectionStyle, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardRelationSchema, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_RELATION, connectionNodeIds, connectionOtherNodeId, connectionTouchesNode, createBoardConnection, flipBoardConnection, normalizeBoardConnectionStyle } from "./board-connection.js";
|
|
2
3
|
import { BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BoardAssetRef, BoardAssetRefSchema, BoardClip, BoardClipSchema, BoardDiagnostic, BoardEffect, BoardEffectSchema, BoardManifest, BoardManifestSchema, BoardNodeInput, BoardNodeRecord, BoardRecord, BoardSequence, BoardSequenceSchema, BoardTarget, BoardTargetSchema, BoardValidationResult, InvalidBoardFileError, isBoardPath, parseBoardManifest, serializeBoardManifest } from "./board.js";
|
|
3
4
|
import "./realtime/board-awareness.js";
|
|
4
5
|
import "./work.js";
|
|
5
6
|
import "./realtime/types.js";
|
|
6
|
-
export { BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BoardAssetRef, BoardAssetRefSchema, BoardClip, BoardClipSchema, BoardDiagnostic, BoardEffect, BoardEffectSchema, BoardManifest, BoardManifestSchema, BoardNodeInput, BoardNodeRecord, BoardRecord, BoardSequence, BoardSequenceSchema, BoardTarget, BoardTargetSchema, BoardValidationResult, InvalidBoardFileError, isBoardPath, parseBoardManifest, serializeBoardManifest };
|
|
7
|
+
export { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BoardAssetRef, BoardAssetRefSchema, BoardClip, BoardClipSchema, BoardConnection, BoardConnectionAnchor, BoardConnectionAnchorSchema, BoardConnectionDirection, BoardConnectionEndpoint, BoardConnectionEndpointSchema, BoardConnectionInput, BoardConnectionLine, BoardConnectionPatch, BoardConnectionPatchSchema, BoardConnectionRecord, BoardConnectionRouting, BoardConnectionRoutingConfig, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionSide, BoardConnectionStyle, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardDiagnostic, BoardEffect, BoardEffectSchema, BoardManifest, BoardManifestSchema, BoardNodeInput, BoardNodeRecord, BoardRecord, BoardRelationSchema, BoardSequence, BoardSequenceSchema, BoardTarget, BoardTargetSchema, BoardValidationResult, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_RELATION, InvalidBoardFileError, connectionNodeIds, connectionOtherNodeId, connectionTouchesNode, createBoardConnection, flipBoardConnection, isBoardPath, normalizeBoardConnectionStyle, parseBoardManifest, serializeBoardManifest };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import "./board-constants.js";
|
|
2
|
+
import { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BoardConnectionAnchorSchema, BoardConnectionEndpointSchema, BoardConnectionPatchSchema, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardRelationSchema, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_RELATION, connectionNodeIds, connectionOtherNodeId, connectionTouchesNode, createBoardConnection, flipBoardConnection, normalizeBoardConnectionStyle } from "./board-connection.js";
|
|
2
3
|
import { BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BOARD_MANIFEST_KIND, BoardAssetRefSchema, BoardClipSchema, BoardEffectSchema, BoardKeyframeSchema, BoardManifestSchema, BoardNodeInputSchema, BoardSequenceSchema, BoardTargetSchema, InvalidBoardFileError, isBoardPath, parseBoardManifest, serializeBoardManifest } from "./board.js";
|
|
3
4
|
import { BoardAwarenessDrawPointSchema, BoardAwarenessFrameSchema, BoardAwarenessGestureSchema, BoardAwarenessNodePreviewSchema, BoardAwarenessPointSchema, BoardAwarenessStateUpdateSchema, BoardAwarenessUpdateSchema } from "./realtime/board-awareness.js";
|
|
4
5
|
import { COHUB_SOURCE_HEADER } from "./provenance.js";
|
|
5
6
|
import { RESERVED_PLATFORM_PATH_SEGMENTS } from "./public-identifiers.js";
|
|
6
7
|
import "./work-view-stats.js";
|
|
7
|
-
export { BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BOARD_MANIFEST_KIND, BoardAssetRefSchema, BoardAwarenessDrawPointSchema, BoardAwarenessFrameSchema, BoardAwarenessGestureSchema, BoardAwarenessNodePreviewSchema, BoardAwarenessPointSchema, BoardAwarenessStateUpdateSchema, BoardAwarenessUpdateSchema, BoardClipSchema, BoardEffectSchema, BoardKeyframeSchema, BoardManifestSchema, BoardNodeInputSchema, BoardSequenceSchema, BoardTargetSchema, COHUB_SOURCE_HEADER, InvalidBoardFileError, RESERVED_PLATFORM_PATH_SEGMENTS, isBoardPath, parseBoardManifest, serializeBoardManifest };
|
|
8
|
+
export { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BOARD_DOCUMENT_KIND, BOARD_EXTENSION, BOARD_MANIFEST_KIND, BoardAssetRefSchema, BoardAwarenessDrawPointSchema, BoardAwarenessFrameSchema, BoardAwarenessGestureSchema, BoardAwarenessNodePreviewSchema, BoardAwarenessPointSchema, BoardAwarenessStateUpdateSchema, BoardAwarenessUpdateSchema, BoardClipSchema, BoardConnectionAnchorSchema, BoardConnectionEndpointSchema, BoardConnectionPatchSchema, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardEffectSchema, BoardKeyframeSchema, BoardManifestSchema, BoardNodeInputSchema, BoardRelationSchema, BoardSequenceSchema, BoardTargetSchema, COHUB_SOURCE_HEADER, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_RELATION, InvalidBoardFileError, RESERVED_PLATFORM_PATH_SEGMENTS, connectionNodeIds, connectionOtherNodeId, connectionTouchesNode, createBoardConnection, flipBoardConnection, isBoardPath, normalizeBoardConnectionStyle, parseBoardManifest, serializeBoardManifest };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BOARD_ARROW_STROKE_SIZE } from "../board-constants.js";
|
|
1
|
+
import { BOARD_ARROW_STROKE_SIZE, BOARD_CONNECTION_STROKE_SIZE } from "../board-constants.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
//#region ../protocol/dist/realtime/board-awareness.js
|
|
4
4
|
const idSchema = z.string().min(1).max(160);
|
|
@@ -15,23 +15,13 @@ const BoardAwarenessFrameSchema = z.object({
|
|
|
15
15
|
height: finiteSchema.positive(),
|
|
16
16
|
rotation: finiteSchema
|
|
17
17
|
});
|
|
18
|
-
const arrowEndpointSchema = z.union([z.object({
|
|
19
|
-
kind: z.literal("point"),
|
|
20
|
-
x: finiteSchema,
|
|
21
|
-
y: finiteSchema
|
|
22
|
-
}), z.object({
|
|
23
|
-
kind: z.literal("binding"),
|
|
24
|
-
target: idSchema,
|
|
25
|
-
nx: finiteSchema,
|
|
26
|
-
ny: finiteSchema,
|
|
27
|
-
precise: z.boolean()
|
|
28
|
-
})]);
|
|
29
18
|
const BoardAwarenessNodePreviewSchema = z.object({
|
|
30
19
|
nodeId: idSchema,
|
|
31
20
|
frame: BoardAwarenessFrameSchema,
|
|
21
|
+
/** Live endpoints of a free arrow being dragged. */
|
|
32
22
|
arrow: z.object({
|
|
33
|
-
start:
|
|
34
|
-
end:
|
|
23
|
+
start: BoardAwarenessPointSchema,
|
|
24
|
+
end: BoardAwarenessPointSchema,
|
|
35
25
|
bend: finiteSchema
|
|
36
26
|
}).optional()
|
|
37
27
|
});
|
|
@@ -80,6 +70,15 @@ const BoardAwarenessGestureSchema = z.discriminatedUnion("kind", [
|
|
|
80
70
|
color: z.string().min(1).max(64),
|
|
81
71
|
geo: z.string().min(1).max(40)
|
|
82
72
|
}),
|
|
73
|
+
z.object({
|
|
74
|
+
kind: z.literal("connection"),
|
|
75
|
+
id: idSchema,
|
|
76
|
+
sourceNodeId: idSchema,
|
|
77
|
+
targetNodeId: idSchema.nullable(),
|
|
78
|
+
current: BoardAwarenessPointSchema,
|
|
79
|
+
color: z.string().min(1).max(64),
|
|
80
|
+
size: finiteSchema.positive().max(256).default(BOARD_CONNECTION_STROKE_SIZE)
|
|
81
|
+
}),
|
|
83
82
|
z.object({
|
|
84
83
|
kind: z.literal("transform"),
|
|
85
84
|
id: idSchema,
|
|
@@ -87,7 +86,8 @@ const BoardAwarenessGestureSchema = z.discriminatedUnion("kind", [
|
|
|
87
86
|
"translate",
|
|
88
87
|
"resize",
|
|
89
88
|
"rotate",
|
|
90
|
-
"arrow"
|
|
89
|
+
"arrow",
|
|
90
|
+
"connection"
|
|
91
91
|
]),
|
|
92
92
|
nodes: z.array(BoardAwarenessNodePreviewSchema).max(64),
|
|
93
93
|
bounds: BoardAwarenessFrameSchema.nullable()
|
package/package.json
CHANGED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { ArrowEndpoint, BoardArrowItem, BoardFrame } from "../../protocol/dist/board-document.js";
|
|
2
|
-
import { Rect, WorldPoint } from "../geometry.js";
|
|
3
|
-
//#region src/board/core/bindings.d.ts
|
|
4
|
-
type FrameLookup = (id: string) => BoardFrame | undefined;
|
|
5
|
-
/** Denormalize a binding anchor to a world point on the (rotated) frame. */
|
|
6
|
-
declare function anchorToWorld(frame: BoardFrame, nx: number, ny: number): WorldPoint;
|
|
7
|
-
/** Normalize a world point to a binding anchor on the (rotated) frame, clamped. */
|
|
8
|
-
declare function worldToAnchor(frame: BoardFrame, point: WorldPoint): {
|
|
9
|
-
nx: number;
|
|
10
|
-
ny: number;
|
|
11
|
-
};
|
|
12
|
-
/** Resolve an endpoint to a world point, or null if a binding target is gone. */
|
|
13
|
-
declare function resolveEndpoint(endpoint: ArrowEndpoint, getFrame: FrameLookup): WorldPoint | null;
|
|
14
|
-
type ResolvedArrow = {
|
|
15
|
-
start: WorldPoint;
|
|
16
|
-
end: WorldPoint;
|
|
17
|
-
/** Quadratic control point (already bent); equals midpoint when bend is 0. */
|
|
18
|
-
control: WorldPoint;
|
|
19
|
-
};
|
|
20
|
-
/** Resolve both endpoints and compute the bent control point. */
|
|
21
|
-
declare function resolveArrow(item: BoardArrowItem, getFrame: FrameLookup): ResolvedArrow | null;
|
|
22
|
-
/** World-space bounds of an arrow, sampling the curve for accuracy. */
|
|
23
|
-
declare function arrowBounds(item: BoardArrowItem, getFrame: FrameLookup): Rect | null;
|
|
24
|
-
/** Sample the arrow's quadratic curve into world points (for render/hit-test). */
|
|
25
|
-
declare function sampleQuadratic(resolved: ResolvedArrow, segments: number): WorldPoint[];
|
|
26
|
-
/** Distance from a world point to the arrow curve (hit testing). */
|
|
27
|
-
declare function distanceToArrow(item: BoardArrowItem, getFrame: FrameLookup, point: WorldPoint): number;
|
|
28
|
-
/**
|
|
29
|
-
* Turn a free endpoint into a binding if a candidate target frame contains the
|
|
30
|
-
* point; otherwise keep it free. Used while dragging an arrow handle so the
|
|
31
|
-
* arrow "connects" to shapes it lands on.
|
|
32
|
-
*/
|
|
33
|
-
declare function bindEndpointAt(point: WorldPoint, target: {
|
|
34
|
-
id: string;
|
|
35
|
-
frame: BoardFrame;
|
|
36
|
-
} | null): ArrowEndpoint;
|
|
37
|
-
/**
|
|
38
|
-
* Translate an arrow by a delta: free endpoints move; bindings stay attached to
|
|
39
|
-
* their targets (so a bound end anchors while the rest of the arrow moves). The
|
|
40
|
-
* frame — a derived bounding box, not a transform — is recomputed from the new
|
|
41
|
-
* endpoint geometry.
|
|
42
|
-
*/
|
|
43
|
-
declare function translateArrow(item: BoardArrowItem, dx: number, dy: number, getFrame: FrameLookup): BoardArrowItem;
|
|
44
|
-
//#endregion
|
|
45
|
-
export { FrameLookup, ResolvedArrow, anchorToWorld, arrowBounds, bindEndpointAt, distanceToArrow, resolveArrow, resolveEndpoint, sampleQuadratic, translateArrow, worldToAnchor };
|