sketchmark 2.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.
Files changed (64) hide show
  1. package/README.md +188 -0
  2. package/bin/sketchmark.cjs +2008 -0
  3. package/dist/src/builders/index.d.ts +74 -0
  4. package/dist/src/builders/index.js +230 -0
  5. package/dist/src/compounds.d.ts +13 -0
  6. package/dist/src/compounds.js +118 -0
  7. package/dist/src/deck.d.ts +4 -0
  8. package/dist/src/deck.js +91 -0
  9. package/dist/src/diagnostics.d.ts +5 -0
  10. package/dist/src/diagnostics.js +113 -0
  11. package/dist/src/export/index.d.ts +8 -0
  12. package/dist/src/export/index.js +15 -0
  13. package/dist/src/index.d.ts +19 -0
  14. package/dist/src/index.js +35 -0
  15. package/dist/src/kernel.d.ts +8 -0
  16. package/dist/src/kernel.js +68 -0
  17. package/dist/src/normalize.d.ts +6 -0
  18. package/dist/src/normalize.js +191 -0
  19. package/dist/src/patch.d.ts +5 -0
  20. package/dist/src/patch.js +72 -0
  21. package/dist/src/path-sampling.d.ts +3 -0
  22. package/dist/src/path-sampling.js +275 -0
  23. package/dist/src/player/index.d.ts +68 -0
  24. package/dist/src/player/index.js +600 -0
  25. package/dist/src/project.d.ts +11 -0
  26. package/dist/src/project.js +107 -0
  27. package/dist/src/render/html.d.ts +2 -0
  28. package/dist/src/render/html.js +13 -0
  29. package/dist/src/render/raw-three.d.ts +7 -0
  30. package/dist/src/render/raw-three.js +17 -0
  31. package/dist/src/render/svg.d.ts +3 -0
  32. package/dist/src/render/svg.js +277 -0
  33. package/dist/src/render/three-html.d.ts +2 -0
  34. package/dist/src/render/three-html.js +303 -0
  35. package/dist/src/render/three-preview-svg.d.ts +3 -0
  36. package/dist/src/render/three-preview-svg.js +102 -0
  37. package/dist/src/scenes.d.ts +4 -0
  38. package/dist/src/scenes.js +25 -0
  39. package/dist/src/schema.d.ts +2 -0
  40. package/dist/src/schema.js +403 -0
  41. package/dist/src/sequences.d.ts +43 -0
  42. package/dist/src/sequences.js +109 -0
  43. package/dist/src/shapes/builtins.d.ts +2 -0
  44. package/dist/src/shapes/builtins.js +429 -0
  45. package/dist/src/shapes/common.d.ts +9 -0
  46. package/dist/src/shapes/common.js +75 -0
  47. package/dist/src/shapes/geometry.d.ts +22 -0
  48. package/dist/src/shapes/geometry.js +166 -0
  49. package/dist/src/shapes/index.d.ts +2 -0
  50. package/dist/src/shapes/index.js +18 -0
  51. package/dist/src/shapes/registry.d.ts +9 -0
  52. package/dist/src/shapes/registry.js +35 -0
  53. package/dist/src/shapes/types.d.ts +34 -0
  54. package/dist/src/shapes/types.js +2 -0
  55. package/dist/src/types.d.ts +439 -0
  56. package/dist/src/types.js +2 -0
  57. package/dist/src/utils.d.ts +25 -0
  58. package/dist/src/utils.js +157 -0
  59. package/dist/src/validate.d.ts +2 -0
  60. package/dist/src/validate.js +434 -0
  61. package/dist/tests/run.d.ts +1 -0
  62. package/dist/tests/run.js +651 -0
  63. package/package.json +52 -0
  64. package/schema/visual.schema.json +930 -0
@@ -0,0 +1,439 @@
1
+ export type PrimitiveType = "rect" | "circle" | "ellipse" | "point" | "line" | "arrow" | "arc" | "curve" | "polyline" | "polygon" | "path" | "text" | "image" | "group";
2
+ export type AdvancedThreeType = "cuboid" | "sphere" | "plane" | "line3d" | "text3d" | "light";
3
+ export type VisualElementType = PrimitiveType | AdvancedThreeType;
4
+ export type Align = "left" | "center" | "right";
5
+ export type VAlign = "top" | "middle" | "bottom";
6
+ export type AnchorName = "center" | "left" | "right" | "top" | "bottom" | "top-left" | "top-right" | "bottom-left" | "bottom-right";
7
+ export type Point2 = [number, number];
8
+ export type Point3 = [number, number, number];
9
+ export type Point = Point2 | Point3;
10
+ export type Endpoint = Point | string;
11
+ export type GradientStop = [number, string] | {
12
+ offset: number;
13
+ color: string;
14
+ };
15
+ export type ImageFit = "fill" | "contain" | "cover";
16
+ export type Paint = string | {
17
+ type: "linearGradient";
18
+ from: Point2;
19
+ to: Point2;
20
+ stops: GradientStop[];
21
+ } | {
22
+ type: "radialGradient";
23
+ center: Point2;
24
+ radius: number;
25
+ focus?: Point2;
26
+ stops: GradientStop[];
27
+ } | {
28
+ type: "pattern";
29
+ src: string;
30
+ x?: number;
31
+ y?: number;
32
+ width: number;
33
+ height: number;
34
+ fit?: ImageFit;
35
+ opacity?: number;
36
+ };
37
+ export type ExportFormat = "svg" | "html" | "png" | "jpg" | "mp4" | "webm" | "pdf" | "pptx";
38
+ export type SequenceTransition = "cut" | "fade" | {
39
+ type: "cut" | "fade";
40
+ duration?: number;
41
+ };
42
+ export interface VisualCanvas {
43
+ width: number;
44
+ height: number;
45
+ background?: string;
46
+ duration?: number;
47
+ fps?: number;
48
+ space?: "2d" | "3d";
49
+ renderer?: "svg" | "three";
50
+ }
51
+ export interface AnimationValue {
52
+ from?: number | string;
53
+ to?: number | string;
54
+ duration?: number;
55
+ delay?: number;
56
+ ease?: "linear" | "ease-in" | "ease-out" | "ease-in-out" | string;
57
+ keyframes?: Array<[number, number | string]>;
58
+ }
59
+ export interface ShadowEffect {
60
+ dx: number;
61
+ dy: number;
62
+ blur: number;
63
+ color: string;
64
+ opacity?: number;
65
+ }
66
+ export interface VisualEffects {
67
+ blur?: number;
68
+ brightness?: number;
69
+ contrast?: number;
70
+ saturate?: number;
71
+ hueRotate?: number;
72
+ shadow?: ShadowEffect;
73
+ }
74
+ export type ClipShape = {
75
+ type: "rect";
76
+ x: number;
77
+ y: number;
78
+ width: number;
79
+ height: number;
80
+ radius?: number;
81
+ } | {
82
+ type: "circle";
83
+ cx: number;
84
+ cy: number;
85
+ radius: number;
86
+ } | {
87
+ type: "path";
88
+ d: string;
89
+ };
90
+ export type MaskShape = {
91
+ type: "rect";
92
+ x: number;
93
+ y: number;
94
+ width: number;
95
+ height: number;
96
+ radius?: number;
97
+ opacity?: number;
98
+ } | {
99
+ type: "circle";
100
+ cx: number;
101
+ cy: number;
102
+ radius: number;
103
+ opacity?: number;
104
+ } | {
105
+ type: "path";
106
+ d: string;
107
+ opacity?: number;
108
+ };
109
+ export interface VisualElementBase {
110
+ id?: string;
111
+ type: VisualElementType | string;
112
+ opacity?: number;
113
+ fill?: Paint;
114
+ stroke?: Paint;
115
+ strokeWidth?: number;
116
+ strokeCap?: "butt" | "round" | "square";
117
+ strokeJoin?: "miter" | "round" | "bevel";
118
+ miterLimit?: number;
119
+ dashArray?: number[];
120
+ dashOffset?: number;
121
+ drawStart?: number;
122
+ drawEnd?: number;
123
+ effects?: VisualEffects;
124
+ blendMode?: string;
125
+ rotation?: number;
126
+ scale?: number;
127
+ scaleX?: number;
128
+ scaleY?: number;
129
+ origin?: AnchorName | Point2;
130
+ clip?: ClipShape;
131
+ mask?: MaskShape;
132
+ animate?: Record<string, AnimationValue>;
133
+ children?: VisualElement[];
134
+ metadata?: Record<string, unknown>;
135
+ }
136
+ export interface RectElement extends VisualElementBase {
137
+ type: "rect";
138
+ x: number;
139
+ y: number;
140
+ width: number;
141
+ height: number;
142
+ radius?: number;
143
+ }
144
+ export interface CircleElement extends VisualElementBase {
145
+ type: "circle";
146
+ cx?: number;
147
+ cy?: number;
148
+ radius: number;
149
+ follow?: string;
150
+ progress?: number | AnimationValue;
151
+ }
152
+ export interface EllipseElement extends VisualElementBase {
153
+ type: "ellipse";
154
+ cx: number;
155
+ cy: number;
156
+ rx: number;
157
+ ry: number;
158
+ }
159
+ export interface PointElement extends VisualElementBase {
160
+ type: "point";
161
+ x: number;
162
+ y: number;
163
+ }
164
+ export interface LineElement extends VisualElementBase {
165
+ type: "line" | "arrow";
166
+ from: Endpoint;
167
+ to: Endpoint;
168
+ label?: string;
169
+ labelX?: number;
170
+ labelY?: number;
171
+ }
172
+ export interface ArcElement extends VisualElementBase {
173
+ type: "arc";
174
+ cx: number;
175
+ cy: number;
176
+ radius: number;
177
+ startAngle: number;
178
+ endAngle: number;
179
+ counterclockwise?: boolean;
180
+ closed?: boolean;
181
+ }
182
+ export interface CurveElement extends VisualElementBase {
183
+ type: "curve";
184
+ from: Endpoint;
185
+ to: Endpoint;
186
+ control1: Point2;
187
+ control2?: Point2;
188
+ }
189
+ export interface PolylineElement extends VisualElementBase {
190
+ type: "polyline";
191
+ points: Point2[];
192
+ }
193
+ export interface PolygonElement extends VisualElementBase {
194
+ type: "polygon";
195
+ points: Point2[];
196
+ }
197
+ export interface PathElement extends VisualElementBase {
198
+ type: "path";
199
+ d: string;
200
+ }
201
+ export interface TextElement extends VisualElementBase {
202
+ type: "text";
203
+ x: number;
204
+ y: number;
205
+ text?: string;
206
+ lines?: string[];
207
+ align?: Align;
208
+ valign?: VAlign;
209
+ fontSize?: number;
210
+ fontFamily?: string;
211
+ weight?: number | string;
212
+ fontStyle?: string;
213
+ lineHeight?: number;
214
+ letterSpacing?: number;
215
+ maxWidth?: number;
216
+ wrap?: boolean;
217
+ fit?: boolean;
218
+ }
219
+ export interface ImageElement extends VisualElementBase {
220
+ type: "image";
221
+ src: string;
222
+ x: number;
223
+ y: number;
224
+ width: number;
225
+ height: number;
226
+ fit?: ImageFit;
227
+ source?: {
228
+ x: number;
229
+ y: number;
230
+ width: number;
231
+ height: number;
232
+ imageWidth: number;
233
+ imageHeight: number;
234
+ };
235
+ }
236
+ export interface GroupElement extends VisualElementBase {
237
+ type: "group";
238
+ x: number;
239
+ y: number;
240
+ width?: number;
241
+ height?: number;
242
+ children: VisualElement[];
243
+ }
244
+ export interface CuboidElement extends VisualElementBase {
245
+ type: "cuboid";
246
+ position: Point3;
247
+ size: Point3;
248
+ }
249
+ export interface SphereElement extends VisualElementBase {
250
+ type: "sphere";
251
+ position: Point3;
252
+ radius: number;
253
+ }
254
+ export interface PlaneElement extends VisualElementBase {
255
+ type: "plane";
256
+ position: Point3;
257
+ size: Point2;
258
+ }
259
+ export interface Line3dElement extends VisualElementBase {
260
+ type: "line3d";
261
+ from: Point3 | string;
262
+ to: Point3 | string;
263
+ }
264
+ export interface Text3dElement extends VisualElementBase {
265
+ type: "text3d";
266
+ text: string;
267
+ position: Point3;
268
+ fontSize?: number;
269
+ }
270
+ export interface LightElement extends VisualElementBase {
271
+ type: "light";
272
+ kind?: "ambient" | "directional" | "point";
273
+ position?: Point3;
274
+ intensity?: number;
275
+ }
276
+ export type VisualElement = RectElement | CircleElement | EllipseElement | PointElement | LineElement | ArcElement | CurveElement | PolylineElement | PolygonElement | PathElement | TextElement | ImageElement | GroupElement | CuboidElement | SphereElement | PlaneElement | Line3dElement | Text3dElement | LightElement;
277
+ export type Kernel2dType = "group" | "path" | "text" | "image" | "point";
278
+ export type Kernel3dType = "group3d" | "mesh3d" | "line3d" | "text3d" | "point3d" | "light";
279
+ export type KernelElementType = Kernel2dType | Kernel3dType;
280
+ export interface KernelElementBase extends Omit<VisualElementBase, "type" | "children"> {
281
+ type: KernelElementType;
282
+ children?: KernelElement[];
283
+ }
284
+ export interface KernelPathElement extends Omit<PathElement, "type" | "children"> {
285
+ type: "path";
286
+ }
287
+ export interface KernelTextElement extends Omit<TextElement, "type" | "children"> {
288
+ type: "text";
289
+ }
290
+ export interface KernelImageElement extends Omit<ImageElement, "type" | "children"> {
291
+ type: "image";
292
+ }
293
+ export interface KernelPointElement extends Omit<PointElement, "type" | "children"> {
294
+ type: "point";
295
+ }
296
+ export interface KernelGroupElement extends Omit<GroupElement, "type" | "children"> {
297
+ type: "group";
298
+ children: KernelElement[];
299
+ }
300
+ export interface KernelPoint3dElement extends KernelElementBase {
301
+ type: "point3d";
302
+ position: Point3;
303
+ }
304
+ export interface KernelMesh3dElement extends KernelElementBase {
305
+ type: "mesh3d";
306
+ vertices: Point3[];
307
+ indices: number[];
308
+ faces?: number[][];
309
+ position?: Point3;
310
+ rotationX?: number;
311
+ rotationY?: number;
312
+ rotationZ?: number;
313
+ scaleZ?: number;
314
+ }
315
+ export interface KernelLine3dElement extends Omit<Line3dElement, "type" | "children"> {
316
+ type: "line3d";
317
+ }
318
+ export interface KernelText3dElement extends Omit<Text3dElement, "type" | "children"> {
319
+ type: "text3d";
320
+ }
321
+ export interface KernelLightElement extends Omit<LightElement, "type" | "children"> {
322
+ type: "light";
323
+ }
324
+ export interface KernelGroup3dElement extends KernelElementBase {
325
+ type: "group3d";
326
+ position?: Point3;
327
+ rotationX?: number;
328
+ rotationY?: number;
329
+ rotationZ?: number;
330
+ scaleZ?: number;
331
+ children: KernelElement[];
332
+ }
333
+ export type KernelElement = KernelPathElement | KernelTextElement | KernelImageElement | KernelPointElement | KernelGroupElement | KernelPoint3dElement | KernelMesh3dElement | KernelLine3dElement | KernelText3dElement | KernelLightElement | KernelGroup3dElement;
334
+ export interface VisualScene {
335
+ id?: string;
336
+ canvas?: Partial<VisualCanvas>;
337
+ elements: VisualElement[];
338
+ steps?: VisualDeckStep[];
339
+ }
340
+ export interface VisualSequenceClip {
341
+ scene: string;
342
+ duration: number;
343
+ transition?: SequenceTransition;
344
+ }
345
+ export interface VisualSequence {
346
+ id: string;
347
+ clips: VisualSequenceClip[];
348
+ export?: {
349
+ format?: ExportFormat;
350
+ fps?: number;
351
+ };
352
+ }
353
+ export interface VisualDeckStep {
354
+ id: string;
355
+ show?: string[];
356
+ hide?: string[];
357
+ duration?: number;
358
+ }
359
+ export type VisualPatchOperation = {
360
+ op: "add";
361
+ element: VisualElement;
362
+ index?: number;
363
+ } | {
364
+ op: "update";
365
+ id: string;
366
+ set: Partial<VisualElement>;
367
+ } | {
368
+ op: "remove";
369
+ id: string;
370
+ } | {
371
+ op: "replace";
372
+ id: string;
373
+ element: VisualElement;
374
+ } | {
375
+ op: "move";
376
+ id: string;
377
+ x?: number;
378
+ y?: number;
379
+ cx?: number;
380
+ cy?: number;
381
+ } | {
382
+ op: "reorder";
383
+ id: string;
384
+ index: number;
385
+ };
386
+ export interface VisualDocument {
387
+ version: 1;
388
+ canvas: VisualCanvas;
389
+ elements?: VisualElement[];
390
+ scenes?: Record<string, VisualScene>;
391
+ sequences?: Record<string, VisualSequence>;
392
+ imports?: Record<string, string>;
393
+ assets?: Record<string, string>;
394
+ exports?: Record<string, {
395
+ format: ExportFormat;
396
+ sequence?: string;
397
+ scene?: string;
398
+ }>;
399
+ }
400
+ export interface ResolvedVisualDocument extends VisualDocument {
401
+ elements: VisualElement[];
402
+ }
403
+ export interface KernelVisualDocument extends Omit<VisualDocument, "elements" | "scenes" | "sequences"> {
404
+ elements: KernelElement[];
405
+ }
406
+ export interface ValidationIssue {
407
+ path: string;
408
+ code: string;
409
+ message: string;
410
+ suggestion?: string;
411
+ }
412
+ export interface ValidationWarning {
413
+ path: string;
414
+ code: string;
415
+ message: string;
416
+ suggestion?: string;
417
+ }
418
+ export interface ValidationResult {
419
+ ok: boolean;
420
+ issues: ValidationIssue[];
421
+ warnings: ValidationWarning[];
422
+ }
423
+ export interface RenderOptions {
424
+ time?: number;
425
+ transparent?: boolean;
426
+ threeRuntime?: string;
427
+ }
428
+ export interface ExportOptions extends RenderOptions {
429
+ format?: ExportFormat;
430
+ scene?: string;
431
+ sequence?: string;
432
+ }
433
+ export interface VisualSymbol {
434
+ id: string;
435
+ type: VisualElementType | string;
436
+ file?: string;
437
+ scene?: string;
438
+ path: string;
439
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,25 @@
1
+ import type { AnchorName, Point2, TextElement, VisualElement } from "./types";
2
+ export declare const CORE_TYPES: Set<string>;
3
+ export declare const THREE_TYPES: Set<string>;
4
+ export declare const COMPOUND_TYPES: Set<string>;
5
+ export declare const ANCHORS: Set<string>;
6
+ export declare function isFiniteNumber(value: unknown): value is number;
7
+ export declare function isPoint2(value: unknown): value is Point2;
8
+ export declare function isPoint2Array(value: unknown, minLength: number): value is Point2[];
9
+ export declare function clone<T>(value: T): T;
10
+ export interface Box {
11
+ x: number;
12
+ y: number;
13
+ width: number;
14
+ height: number;
15
+ }
16
+ export declare function elementBox(element: VisualElement): Box | undefined;
17
+ export declare function pointsBox(points: Point2[] | undefined): Box | undefined;
18
+ export declare function textLines(element: Pick<TextElement, "text" | "lines">): string[];
19
+ export declare function anchorPoint(box: Box, anchor: AnchorName): Point2;
20
+ export declare function parseReference(ref: string): {
21
+ id: string;
22
+ anchor: AnchorName;
23
+ };
24
+ export declare function flattenElements(elements: VisualElement[]): VisualElement[];
25
+ export declare function easing(name: string | undefined, t: number): number;
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ANCHORS = exports.COMPOUND_TYPES = exports.THREE_TYPES = exports.CORE_TYPES = void 0;
4
+ exports.isFiniteNumber = isFiniteNumber;
5
+ exports.isPoint2 = isPoint2;
6
+ exports.isPoint2Array = isPoint2Array;
7
+ exports.clone = clone;
8
+ exports.elementBox = elementBox;
9
+ exports.pointsBox = pointsBox;
10
+ exports.textLines = textLines;
11
+ exports.anchorPoint = anchorPoint;
12
+ exports.parseReference = parseReference;
13
+ exports.flattenElements = flattenElements;
14
+ exports.easing = easing;
15
+ exports.CORE_TYPES = new Set(["rect", "circle", "ellipse", "point", "line", "arrow", "arc", "curve", "polyline", "polygon", "path", "text", "image", "group"]);
16
+ exports.THREE_TYPES = new Set(["cuboid", "sphere", "plane", "line3d", "text3d", "light"]);
17
+ exports.COMPOUND_TYPES = new Set(["node", "flow", "packet", "callout", "row", "column", "grid"]);
18
+ exports.ANCHORS = new Set(["center", "left", "right", "top", "bottom", "top-left", "top-right", "bottom-left", "bottom-right"]);
19
+ function isFiniteNumber(value) {
20
+ return typeof value === "number" && Number.isFinite(value);
21
+ }
22
+ function isPoint2(value) {
23
+ return Array.isArray(value) && value.length >= 2 && isFiniteNumber(value[0]) && isFiniteNumber(value[1]);
24
+ }
25
+ function isPoint2Array(value, minLength) {
26
+ return Array.isArray(value) && value.length >= minLength && value.every((point) => isPoint2(point));
27
+ }
28
+ function clone(value) {
29
+ return JSON.parse(JSON.stringify(value));
30
+ }
31
+ function elementBox(element) {
32
+ switch (element.type) {
33
+ case "rect":
34
+ case "image":
35
+ case "group":
36
+ if (isFiniteNumber(element.x) && isFiniteNumber(element.y) && isFiniteNumber(element.width) && isFiniteNumber(element.height)) {
37
+ return { x: element.x, y: element.y, width: element.width, height: element.height };
38
+ }
39
+ return undefined;
40
+ case "text": {
41
+ if (!isFiniteNumber(element.x) || !isFiniteNumber(element.y))
42
+ return undefined;
43
+ const fontSize = isFiniteNumber(element.fontSize) ? element.fontSize : 16;
44
+ const lines = textLines(element);
45
+ const longest = lines.reduce((max, line) => Math.max(max, line.length), 0);
46
+ const lineHeight = isFiniteNumber(element.lineHeight) ? element.lineHeight : 1.2;
47
+ const width = isFiniteNumber(element.maxWidth) ? element.maxWidth : Math.max(1, longest * fontSize * 0.55);
48
+ const height = Math.max(1, lines.length) * fontSize * lineHeight;
49
+ const x = element.align === "center" ? element.x - width / 2 : element.align === "right" ? element.x - width : element.x;
50
+ const y = element.valign === "middle" ? element.y - height / 2 : element.valign === "bottom" ? element.y - height : element.y;
51
+ return { x, y, width, height };
52
+ }
53
+ case "point":
54
+ if (isFiniteNumber(element.x) && isFiniteNumber(element.y)) {
55
+ return { x: element.x, y: element.y, width: 0, height: 0 };
56
+ }
57
+ return undefined;
58
+ case "circle":
59
+ if (isFiniteNumber(element.cx) && isFiniteNumber(element.cy) && isFiniteNumber(element.radius)) {
60
+ return { x: element.cx - element.radius, y: element.cy - element.radius, width: element.radius * 2, height: element.radius * 2 };
61
+ }
62
+ return undefined;
63
+ case "ellipse":
64
+ if (isFiniteNumber(element.cx) && isFiniteNumber(element.cy) && isFiniteNumber(element.rx) && isFiniteNumber(element.ry)) {
65
+ return { x: element.cx - element.rx, y: element.cy - element.ry, width: element.rx * 2, height: element.ry * 2 };
66
+ }
67
+ return undefined;
68
+ case "arc":
69
+ if (isFiniteNumber(element.cx) && isFiniteNumber(element.cy) && isFiniteNumber(element.radius)) {
70
+ return { x: element.cx - element.radius, y: element.cy - element.radius, width: element.radius * 2, height: element.radius * 2 };
71
+ }
72
+ return undefined;
73
+ case "curve": {
74
+ const points = [element.from, element.control1, element.control2, element.to].filter(isPoint2);
75
+ return pointsBox(points);
76
+ }
77
+ case "polyline":
78
+ case "polygon":
79
+ return pointsBox(element.points);
80
+ default:
81
+ return undefined;
82
+ }
83
+ }
84
+ function pointsBox(points) {
85
+ if (!Array.isArray(points) || !points.length)
86
+ return undefined;
87
+ let minX = Number.POSITIVE_INFINITY;
88
+ let minY = Number.POSITIVE_INFINITY;
89
+ let maxX = Number.NEGATIVE_INFINITY;
90
+ let maxY = Number.NEGATIVE_INFINITY;
91
+ for (const point of points) {
92
+ if (!isPoint2(point))
93
+ return undefined;
94
+ minX = Math.min(minX, point[0]);
95
+ minY = Math.min(minY, point[1]);
96
+ maxX = Math.max(maxX, point[0]);
97
+ maxY = Math.max(maxY, point[1]);
98
+ }
99
+ return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
100
+ }
101
+ function textLines(element) {
102
+ if (Array.isArray(element.lines) && element.lines.length)
103
+ return element.lines.map((line) => String(line));
104
+ return String(element.text ?? "").split(/\r?\n/);
105
+ }
106
+ function anchorPoint(box, anchor) {
107
+ switch (anchor) {
108
+ case "left":
109
+ return [box.x, box.y + box.height / 2];
110
+ case "right":
111
+ return [box.x + box.width, box.y + box.height / 2];
112
+ case "top":
113
+ return [box.x + box.width / 2, box.y];
114
+ case "bottom":
115
+ return [box.x + box.width / 2, box.y + box.height];
116
+ case "top-left":
117
+ return [box.x, box.y];
118
+ case "top-right":
119
+ return [box.x + box.width, box.y];
120
+ case "bottom-left":
121
+ return [box.x, box.y + box.height];
122
+ case "bottom-right":
123
+ return [box.x + box.width, box.y + box.height];
124
+ case "center":
125
+ default:
126
+ return [box.x + box.width / 2, box.y + box.height / 2];
127
+ }
128
+ }
129
+ function parseReference(ref) {
130
+ const [id, rawAnchor] = ref.split(".");
131
+ const anchor = (rawAnchor || "center");
132
+ return { id: id || "", anchor: exports.ANCHORS.has(anchor) ? anchor : "center" };
133
+ }
134
+ function flattenElements(elements) {
135
+ const out = [];
136
+ for (const element of elements) {
137
+ out.push(element);
138
+ if (element.type === "group" && Array.isArray(element.children)) {
139
+ out.push(...flattenElements(element.children));
140
+ }
141
+ }
142
+ return out;
143
+ }
144
+ function easing(name, t) {
145
+ const x = Math.max(0, Math.min(1, t));
146
+ switch (name) {
147
+ case "ease-in":
148
+ return x * x;
149
+ case "ease-out":
150
+ return 1 - (1 - x) * (1 - x);
151
+ case "ease-in-out":
152
+ return x < 0.5 ? 2 * x * x : 1 - Math.pow(-2 * x + 2, 2) / 2;
153
+ case "linear":
154
+ default:
155
+ return x;
156
+ }
157
+ }
@@ -0,0 +1,2 @@
1
+ import type { ValidationResult, VisualDocument } from "./types";
2
+ export declare function validateVisualDocument(document: VisualDocument): ValidationResult;