sketchmark 2.0.0 → 2.1.1

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 (56) hide show
  1. package/README.md +274 -188
  2. package/bin/editor-ui.cjs +2285 -0
  3. package/bin/preview-ui.cjs +74 -0
  4. package/bin/sketchmark.cjs +648 -2008
  5. package/dist/src/animatable.d.ts +21 -0
  6. package/dist/src/animatable.js +439 -0
  7. package/dist/src/builders/index.d.ts +1 -11
  8. package/dist/src/builders/index.js +1 -19
  9. package/dist/src/diagnostics.js +1 -64
  10. package/dist/src/edit.d.ts +27 -0
  11. package/dist/src/edit.js +162 -0
  12. package/dist/src/index.d.ts +4 -13
  13. package/dist/src/index.js +4 -13
  14. package/dist/src/keyframes.d.ts +48 -0
  15. package/dist/src/keyframes.js +182 -0
  16. package/dist/src/motion.d.ts +4 -0
  17. package/dist/src/motion.js +262 -0
  18. package/dist/src/normalize.js +120 -151
  19. package/dist/src/presets/characters.d.ts +15 -0
  20. package/dist/src/presets/characters.js +113 -0
  21. package/dist/src/presets/compose.d.ts +5 -0
  22. package/dist/src/presets/compose.js +80 -0
  23. package/dist/src/presets/effects.d.ts +40 -0
  24. package/dist/src/presets/effects.js +79 -0
  25. package/dist/src/presets/helpers.d.ts +33 -0
  26. package/dist/src/presets/helpers.js +165 -0
  27. package/dist/src/presets/index.d.ts +9 -0
  28. package/dist/src/presets/index.js +48 -0
  29. package/dist/src/presets/motions.d.ts +33 -0
  30. package/dist/src/presets/motions.js +75 -0
  31. package/dist/src/presets/scenes.d.ts +35 -0
  32. package/dist/src/presets/scenes.js +134 -0
  33. package/dist/src/presets/shapes.d.ts +71 -0
  34. package/dist/src/presets/shapes.js +96 -0
  35. package/dist/src/presets/transitions.d.ts +29 -0
  36. package/dist/src/presets/transitions.js +113 -0
  37. package/dist/src/presets/types.d.ts +34 -0
  38. package/dist/src/presets/types.js +2 -0
  39. package/dist/src/render/html.js +1 -4
  40. package/dist/src/render/svg.d.ts +2 -2
  41. package/dist/src/render/svg.js +86 -82
  42. package/dist/src/render/three-html.js +67 -113
  43. package/dist/src/scenes.js +1 -0
  44. package/dist/src/schema.js +218 -280
  45. package/dist/src/shapes/builtins.js +11 -47
  46. package/dist/src/shapes/common.js +12 -11
  47. package/dist/src/shapes/registry.d.ts +0 -1
  48. package/dist/src/shapes/registry.js +0 -4
  49. package/dist/src/shapes/types.d.ts +1 -3
  50. package/dist/src/types.d.ts +57 -288
  51. package/dist/src/utils.d.ts +2 -11
  52. package/dist/src/utils.js +13 -70
  53. package/dist/src/validate.js +321 -275
  54. package/dist/tests/run.js +576 -510
  55. package/package.json +46 -52
  56. package/schema/visual.schema.json +1086 -930
@@ -1,13 +1,35 @@
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;
1
+ export type KernelElementType = "path" | "text" | "image" | "point" | "group";
2
+ export type VisualElementType = KernelElementType;
4
3
  export type Align = "left" | "center" | "right";
5
4
  export type VAlign = "top" | "middle" | "bottom";
6
- export type AnchorName = "center" | "left" | "right" | "top" | "bottom" | "top-left" | "top-right" | "bottom-left" | "bottom-right";
7
5
  export type Point2 = [number, number];
8
- export type Point3 = [number, number, number];
9
- export type Point = Point2 | Point3;
10
- export type Endpoint = Point | string;
6
+ export type JsonMotionObject = {
7
+ [key: string]: JsonMotionValue;
8
+ };
9
+ export type JsonMotionValue = number | string | boolean | null | JsonMotionValue[] | JsonMotionObject;
10
+ export type MotionValue = number | string | Point2 | number[] | string[] | JsonMotionObject;
11
+ export type TimelineTrackValue = MotionValue;
12
+ export type TimelineCurve = {
13
+ type: "graph";
14
+ points: Point2[];
15
+ } | {
16
+ type: "cubicBezier";
17
+ x1: number;
18
+ y1: number;
19
+ x2: number;
20
+ y2: number;
21
+ } | {
22
+ type: "hold";
23
+ };
24
+ export type TimelineKeyframeTuple = [number, TimelineTrackValue];
25
+ export interface TimelineKeyframeObject {
26
+ time: number;
27
+ value: TimelineTrackValue;
28
+ in?: TimelineCurve;
29
+ out?: TimelineCurve;
30
+ interpolation?: TimelineCurve;
31
+ }
32
+ export type TimelineKeyframe = TimelineKeyframeTuple | TimelineKeyframeObject;
11
33
  export type GradientStop = [number, string] | {
12
34
  offset: number;
13
35
  color: string;
@@ -34,10 +56,14 @@ export type Paint = string | {
34
56
  fit?: ImageFit;
35
57
  opacity?: number;
36
58
  };
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;
59
+ export type ClipShape = {
60
+ type: "path";
61
+ d: string;
62
+ };
63
+ export type MaskShape = {
64
+ type: "path";
65
+ d: string;
66
+ opacity?: number;
41
67
  };
42
68
  export interface VisualCanvas {
43
69
  width: number;
@@ -45,16 +71,16 @@ export interface VisualCanvas {
45
71
  background?: string;
46
72
  duration?: number;
47
73
  fps?: number;
48
- space?: "2d" | "3d";
49
- renderer?: "svg" | "three";
50
74
  }
51
- export interface AnimationValue {
52
- from?: number | string;
53
- to?: number | string;
54
- duration?: number;
55
- delay?: number;
75
+ export interface TimelineTrack {
76
+ keyframes: TimelineKeyframe[];
77
+ curve?: TimelineCurve;
56
78
  ease?: "linear" | "ease-in" | "ease-out" | "ease-in-out" | string;
57
- keyframes?: Array<[number, number | string]>;
79
+ }
80
+ export interface ElementTimeline {
81
+ start?: number;
82
+ end?: number;
83
+ tracks?: Record<string, TimelineTrack>;
58
84
  }
59
85
  export interface ShadowEffect {
60
86
  dx: number;
@@ -71,44 +97,9 @@ export interface VisualEffects {
71
97
  hueRotate?: number;
72
98
  shadow?: ShadowEffect;
73
99
  }
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
100
  export interface VisualElementBase {
110
101
  id?: string;
111
- type: VisualElementType | string;
102
+ type: KernelElementType | string;
112
103
  opacity?: number;
113
104
  fill?: Paint;
114
105
  stroke?: Paint;
@@ -126,77 +117,16 @@ export interface VisualElementBase {
126
117
  scale?: number;
127
118
  scaleX?: number;
128
119
  scaleY?: number;
129
- origin?: AnchorName | Point2;
120
+ origin?: Point2;
130
121
  clip?: ClipShape;
131
122
  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[];
123
+ timeline?: ElementTimeline;
196
124
  }
197
125
  export interface PathElement extends VisualElementBase {
198
126
  type: "path";
199
127
  d: string;
128
+ x?: number;
129
+ y?: number;
200
130
  }
201
131
  export interface TextElement extends VisualElementBase {
202
132
  type: "text";
@@ -214,7 +144,6 @@ export interface TextElement extends VisualElementBase {
214
144
  letterSpacing?: number;
215
145
  maxWidth?: number;
216
146
  wrap?: boolean;
217
- fit?: boolean;
218
147
  }
219
148
  export interface ImageElement extends VisualElementBase {
220
149
  type: "image";
@@ -233,6 +162,11 @@ export interface ImageElement extends VisualElementBase {
233
162
  imageHeight: number;
234
163
  };
235
164
  }
165
+ export interface PointElement extends VisualElementBase {
166
+ type: "point";
167
+ x: number;
168
+ y: number;
169
+ }
236
170
  export interface GroupElement extends VisualElementBase {
237
171
  type: "group";
238
172
  x: number;
@@ -241,168 +175,16 @@ export interface GroupElement extends VisualElementBase {
241
175
  height?: number;
242
176
  children: VisualElement[];
243
177
  }
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
- };
178
+ export type VisualElement = PathElement | TextElement | ImageElement | PointElement | GroupElement;
179
+ export type KernelElement = VisualElement;
386
180
  export interface VisualDocument {
387
181
  version: 1;
388
182
  canvas: VisualCanvas;
389
183
  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
184
  }
400
185
  export interface ResolvedVisualDocument extends VisualDocument {
401
186
  elements: VisualElement[];
402
187
  }
403
- export interface KernelVisualDocument extends Omit<VisualDocument, "elements" | "scenes" | "sequences"> {
404
- elements: KernelElement[];
405
- }
406
188
  export interface ValidationIssue {
407
189
  path: string;
408
190
  code: string;
@@ -423,17 +205,4 @@ export interface ValidationResult {
423
205
  export interface RenderOptions {
424
206
  time?: number;
425
207
  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
208
  }
@@ -1,11 +1,6 @@
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>;
1
+ import type { Point2, TextElement, VisualElement } from "./types";
6
2
  export declare function isFiniteNumber(value: unknown): value is number;
7
3
  export declare function isPoint2(value: unknown): value is Point2;
8
- export declare function isPoint2Array(value: unknown, minLength: number): value is Point2[];
9
4
  export declare function clone<T>(value: T): T;
10
5
  export interface Box {
11
6
  x: number;
@@ -16,10 +11,6 @@ export interface Box {
16
11
  export declare function elementBox(element: VisualElement): Box | undefined;
17
12
  export declare function pointsBox(points: Point2[] | undefined): Box | undefined;
18
13
  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
14
  export declare function flattenElements(elements: VisualElement[]): VisualElement[];
25
15
  export declare function easing(name: string | undefined, t: number): number;
16
+ export declare function clamp(value: number, min: number, max: number): number;
package/dist/src/utils.js CHANGED
@@ -1,36 +1,28 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ANCHORS = exports.COMPOUND_TYPES = exports.THREE_TYPES = exports.CORE_TYPES = void 0;
4
3
  exports.isFiniteNumber = isFiniteNumber;
5
4
  exports.isPoint2 = isPoint2;
6
- exports.isPoint2Array = isPoint2Array;
7
5
  exports.clone = clone;
8
6
  exports.elementBox = elementBox;
9
7
  exports.pointsBox = pointsBox;
10
8
  exports.textLines = textLines;
11
- exports.anchorPoint = anchorPoint;
12
- exports.parseReference = parseReference;
13
9
  exports.flattenElements = flattenElements;
14
10
  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"]);
11
+ exports.clamp = clamp;
12
+ const path_sampling_1 = require("./path-sampling");
19
13
  function isFiniteNumber(value) {
20
14
  return typeof value === "number" && Number.isFinite(value);
21
15
  }
22
16
  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));
17
+ return Array.isArray(value) && value.length === 2 && isFiniteNumber(value[0]) && isFiniteNumber(value[1]);
27
18
  }
28
19
  function clone(value) {
20
+ if (value === undefined)
21
+ return value;
29
22
  return JSON.parse(JSON.stringify(value));
30
23
  }
31
24
  function elementBox(element) {
32
25
  switch (element.type) {
33
- case "rect":
34
26
  case "image":
35
27
  case "group":
36
28
  if (isFiniteNumber(element.x) && isFiniteNumber(element.y) && isFiniteNumber(element.width) && isFiniteNumber(element.height)) {
@@ -51,32 +43,9 @@ function elementBox(element) {
51
43
  return { x, y, width, height };
52
44
  }
53
45
  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);
46
+ return isFiniteNumber(element.x) && isFiniteNumber(element.y) ? { x: element.x, y: element.y, width: 0, height: 0 } : undefined;
47
+ case "path":
48
+ return typeof element.d === "string" ? pointsBox((0, path_sampling_1.samplePath)(element.d)) : undefined;
80
49
  default:
81
50
  return undefined;
82
51
  }
@@ -103,46 +72,17 @@ function textLines(element) {
103
72
  return element.lines.map((line) => String(line));
104
73
  return String(element.text ?? "").split(/\r?\n/);
105
74
  }
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
75
  function flattenElements(elements) {
135
76
  const out = [];
136
77
  for (const element of elements) {
137
78
  out.push(element);
138
- if (element.type === "group" && Array.isArray(element.children)) {
79
+ if (element.type === "group" && Array.isArray(element.children))
139
80
  out.push(...flattenElements(element.children));
140
- }
141
81
  }
142
82
  return out;
143
83
  }
144
84
  function easing(name, t) {
145
- const x = Math.max(0, Math.min(1, t));
85
+ const x = clamp(t, 0, 1);
146
86
  switch (name) {
147
87
  case "ease-in":
148
88
  return x * x;
@@ -155,3 +95,6 @@ function easing(name, t) {
155
95
  return x;
156
96
  }
157
97
  }
98
+ function clamp(value, min, max) {
99
+ return Math.max(min, Math.min(max, value));
100
+ }