@shopify/klint 0.0.97 → 0.2.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.
@@ -1,913 +0,0 @@
1
- // src/elements/Color.tsx
2
- var Color = class {
3
- constructor() {
4
- // context: KlintContexts;
5
- /**
6
- * Array of predefined colors in the Klint color palette
7
- */
8
- this.colors = [
9
- "#E84D37",
10
- // coral
11
- "#7F4C2F",
12
- // brown
13
- "#EDBC2F",
14
- // mustard
15
- "#BF3034",
16
- // crimson
17
- "#18599D",
18
- // navy
19
- "#45A7C6",
20
- // sky
21
- "#8CB151",
22
- // olive
23
- "#252120",
24
- // charcoal
25
- "#ECA088",
26
- // peach
27
- "#C9B1B8",
28
- // rose
29
- "#8F3064",
30
- // plum
31
- "#7B8870",
32
- // sage
33
- "#C0C180",
34
- // drab
35
- "#4B423D",
36
- // taupe
37
- "#1A2A65",
38
- // midnight
39
- "#EAA550",
40
- // golden
41
- "#F17B04",
42
- // orange
43
- "#404757"
44
- // slate
45
- ];
46
- }
47
- // /**
48
- // * Creates a new Color instance
49
- // * @param ctx - The Klint context
50
- // */
51
- // constructor(ctx: KlintContexts) {
52
- // this.context = ctx;
53
- // }
54
- get coral() {
55
- return this.colors[0];
56
- }
57
- get brown() {
58
- return this.colors[1];
59
- }
60
- get mustard() {
61
- return this.colors[2];
62
- }
63
- get crimson() {
64
- return this.colors[3];
65
- }
66
- get navy() {
67
- return this.colors[4];
68
- }
69
- get sky() {
70
- return this.colors[5];
71
- }
72
- get olive() {
73
- return this.colors[6];
74
- }
75
- get charcoal() {
76
- return this.colors[7];
77
- }
78
- get peach() {
79
- return this.colors[8];
80
- }
81
- get rose() {
82
- return this.colors[9];
83
- }
84
- get plum() {
85
- return this.colors[10];
86
- }
87
- get sage() {
88
- return this.colors[11];
89
- }
90
- get drab() {
91
- return this.colors[12];
92
- }
93
- get taupe() {
94
- return this.colors[13];
95
- }
96
- get midnight() {
97
- return this.colors[14];
98
- }
99
- get golden() {
100
- return this.colors[15];
101
- }
102
- get orange() {
103
- return this.colors[16];
104
- }
105
- get slate() {
106
- return this.colors[17];
107
- }
108
- /**
109
- * Ensures a color string has a # prefix
110
- * @param color - Color string in hex format (with or without #)
111
- * @returns Hex color string with # prefix
112
- */
113
- hex(color) {
114
- return color.startsWith("#") ? color : `#${color}`;
115
- }
116
- /**
117
- * Creates an RGB color string
118
- * @param r - Red component (0-255)
119
- * @param g - Green component (0-255)
120
- * @param b - Blue component (0-255)
121
- * @returns RGB color string
122
- */
123
- rgb(r, g, b) {
124
- return `rgb(${Math.round(r)}, ${Math.round(g)}, ${Math.round(b)})`;
125
- }
126
- /**
127
- * Creates an RGBA color string
128
- * @param r - Red component (0-255)
129
- * @param g - Green component (0-255)
130
- * @param b - Blue component (0-255)
131
- * @param alpha - Alpha/opacity value (0-1)
132
- * @returns RGBA color string
133
- */
134
- rgba(r, g, b, alpha) {
135
- return `rgba(${Math.round(r)}, ${Math.round(g)}, ${Math.round(
136
- b
137
- )}, ${alpha})`;
138
- }
139
- /**
140
- * Creates a grayscale color
141
- * @param value - Gray value (0-255)
142
- * @param alpha - Optional alpha/opacity value (0-1)
143
- * @returns RGB or RGBA grayscale color string
144
- */
145
- gray(value, alpha) {
146
- return alpha !== void 0 ? `rgba(${Math.round(value)}, ${Math.round(value)}, ${Math.round(
147
- value
148
- )}, ${alpha})` : `rgb(${Math.round(value)}, ${Math.round(value)}, ${Math.round(value)})`;
149
- }
150
- /**
151
- * Creates an HSL color string
152
- * @param h - Hue (0-360)
153
- * @param s - Saturation percentage (0-100)
154
- * @param l - Lightness percentage (0-100)
155
- * @returns HSL color string
156
- */
157
- hsl(h, s, l) {
158
- return `hsl(${h % 360}, ${Math.max(0, s)}%, ${Math.max(0, l)}%)`;
159
- }
160
- /**
161
- * Creates an HSLA color string
162
- * @param h - Hue (0-360)
163
- * @param s - Saturation percentage (0-100)
164
- * @param l - Lightness percentage (0-100)
165
- * @param alpha - Alpha/opacity value (0-1)
166
- * @returns HSLA color string
167
- */
168
- hsla(h, s, l, alpha) {
169
- return `hsla(${h % 360}, ${Math.max(0, s)}%, ${Math.max(0, l)}%, ${alpha})`;
170
- }
171
- /**
172
- * Creates an LCH color string
173
- * @param l - Lightness percentage (0-100)
174
- * @param c - Chroma value
175
- * @param h - Hue (0-360)
176
- * @returns LCH color string
177
- */
178
- lch(l, c, h) {
179
- return `lch(${l}% ${c} ${h})`;
180
- }
181
- /**
182
- * Creates an LCH color string with alpha
183
- * @param l - Lightness percentage (0-100)
184
- * @param c - Chroma value
185
- * @param h - Hue (0-360)
186
- * @param alpha - Alpha/opacity value (0-1)
187
- * @returns LCH color string with alpha
188
- */
189
- lcha(l, c, h, alpha) {
190
- return `lch(${l}% ${c} ${h} / ${alpha})`;
191
- }
192
- /**
193
- * Creates a LAB color string
194
- * @param l - Lightness percentage (0-100)
195
- * @param a - A-axis value (green to red)
196
- * @param b - B-axis value (blue to yellow)
197
- * @returns LAB color string
198
- */
199
- lab(l, a, b) {
200
- return `lab(${l}% ${a} ${b})`;
201
- }
202
- /**
203
- * Creates a LAB color string with alpha
204
- * @param l - Lightness percentage (0-100)
205
- * @param a - A-axis value (green to red)
206
- * @param b - B-axis value (blue to yellow)
207
- * @param alpha - Alpha/opacity value (0-1)
208
- * @returns LAB color string with alpha
209
- */
210
- laba(l, a, b, alpha) {
211
- return `lab(${l}% ${a} ${b} / ${alpha})`;
212
- }
213
- /**
214
- * Creates an OKLCH color string
215
- * @param l - Lightness value (0-1)
216
- * @param c - Chroma value
217
- * @param h - Hue (0-360)
218
- * @returns OKLCH color string
219
- */
220
- oklch(l, c, h) {
221
- return `oklch(${l} ${c} ${h})`;
222
- }
223
- /**
224
- * Creates an OKLCH color string with alpha
225
- * @param l - Lightness value (0-1)
226
- * @param c - Chroma value
227
- * @param h - Hue (0-360)
228
- * @param alpha - Alpha/opacity value (0-1)
229
- * @returns OKLCH color string with alpha
230
- */
231
- oklcha(l, c, h, alpha) {
232
- return `oklch(${l} ${c} ${h} / ${alpha})`;
233
- }
234
- /**
235
- * Creates an OKLAB color string
236
- * @param l - Lightness value (0-1)
237
- * @param a - A-axis value (green to red)
238
- * @param b - B-axis value (blue to yellow)
239
- * @returns OKLAB color string
240
- */
241
- oklab(l, a, b) {
242
- return `oklab(${l} ${a} ${b})`;
243
- }
244
- /**
245
- * Creates an OKLAB color string with alpha
246
- * @param l - Lightness value (0-1)
247
- * @param a - A-axis value (green to red)
248
- * @param b - B-axis value (blue to yellow)
249
- * @param alpha - Alpha/opacity value (0-1)
250
- * @returns OKLAB color string with alpha
251
- */
252
- oklaba(l, a, b, alpha) {
253
- return `oklab(${l} ${a} ${b} / ${alpha})`;
254
- }
255
- /**
256
- * Blends two colors using CSS color-mix
257
- * @param colorA - First color
258
- * @param colorB - Second color
259
- * @param factor - Blend factor (0-1) where 0 is colorA and 1 is colorB
260
- * @param colorMode - Color space to blend in (e.g., "oklch", "hsl")
261
- * @returns Blended color string
262
- */
263
- blendColors(colorA, colorB, factor, colorMode = "oklch") {
264
- const t = Math.max(0, Math.min(1, factor)) * 100;
265
- return `color-mix(in ${colorMode}, ${colorA}, ${colorB} ${t}%)`;
266
- }
267
- /**
268
- * Creates a palette of colors based on a single base color
269
- * @param baseColor - The base color to create palette from
270
- * @param steps - Number of steps in each direction (lighter/darker)
271
- * @returns Array of color strings forming a palette
272
- */
273
- createPalette(baseColor, steps = 9) {
274
- const palette = [];
275
- for (let i = 1; i < steps; i++) {
276
- const factor = i / steps;
277
- palette.unshift(this.blendColors(baseColor, "#ffffff", factor, "oklch"));
278
- }
279
- palette.push(baseColor);
280
- for (let i = 1; i < steps; i++) {
281
- const factor = i / steps;
282
- palette.push(this.blendColors(baseColor, "#000000", factor, "oklch"));
283
- }
284
- return palette;
285
- }
286
- /**
287
- * Creates a complementary color (opposite on the color wheel)
288
- * @param color - Base color
289
- * @returns Complementary color string
290
- */
291
- complementary(color) {
292
- return this.blendColors(color, "hsl(180deg 100% 50%)", 1, "hsl");
293
- }
294
- /**
295
- * Creates analogous colors (adjacent on the color wheel)
296
- * @param color - Base color
297
- * @param angle - Angle of separation in degrees
298
- * @returns Tuple of two analogous color strings
299
- */
300
- analogous(color, angle = 30) {
301
- return [
302
- this.blendColors(color, `hsl(${-angle}deg 100% 50%)`, 1, "hsl"),
303
- this.blendColors(color, `hsl(${angle}deg 100% 50%)`, 1, "hsl")
304
- ];
305
- }
306
- /**
307
- * Creates a triadic color scheme (three colors evenly spaced on the color wheel)
308
- * @param color - Base color
309
- * @returns Tuple of two additional colors to form a triadic scheme
310
- */
311
- triadic(color) {
312
- return [
313
- this.blendColors(color, "hsl(120deg 100% 50%)", 1, "hsl"),
314
- this.blendColors(color, "hsl(240deg 100% 50%)", 1, "hsl")
315
- ];
316
- }
317
- /**
318
- * Increases the saturation of a color
319
- * @param color - Base color
320
- * @param amount - Amount to saturate (percentage)
321
- * @returns Saturated color string
322
- */
323
- saturate(color, amount) {
324
- return this.blendColors(
325
- color,
326
- "hsl(0deg 100% 50% / 0%)",
327
- amount / 100,
328
- "hsl"
329
- );
330
- }
331
- /**
332
- * Lightens a color by mixing with white
333
- * @param color - Base color
334
- * @param amount - Amount to lighten (percentage)
335
- * @returns Lightened color string
336
- */
337
- lighten(color, amount) {
338
- return this.blendColors(color, "white", amount / 100, "hsl");
339
- }
340
- /**
341
- * Darkens a color by mixing with black
342
- * @param color - Base color
343
- * @param amount - Amount to darken (percentage)
344
- * @returns Darkened color string
345
- */
346
- darken(color, amount) {
347
- return this.blendColors(color, "black", amount / 100, "hsl");
348
- }
349
- };
350
- var Color_default = Color;
351
-
352
- // src/elements/Easing.tsx
353
- var Easing = class {
354
- constructor(ctx) {
355
- this.normalize = (val) => {
356
- return val * 0.5 + 0.5;
357
- };
358
- this.expand = (val) => {
359
- return val * 2 - 1;
360
- };
361
- this.inout = (val, power = 2) => {
362
- const m = val - 1;
363
- const t = val * 2;
364
- if (t < 1) {
365
- return val * Math.pow(t, power - 1);
366
- }
367
- return power % 2 === 0 ? 1 - Math.pow(m, power) * Math.pow(2, power - 1) : 1 + Math.pow(m, power) * Math.pow(2, power - 1);
368
- };
369
- this.in = (val, power = 2) => {
370
- return Math.pow(val, power);
371
- };
372
- this.out = (val, power = 2) => {
373
- const m = val - 1;
374
- return power % 2 === 0 ? 1 - Math.pow(m, power) : 1 + Math.pow(m, power);
375
- };
376
- this.overshootIn = (val) => {
377
- const k = 1.70158;
378
- return val * val * (val * (k + 1) - k);
379
- };
380
- this.overshootOut = (val) => {
381
- const m = val - 1;
382
- const k = 1.70158;
383
- return 1 + m * m * (m * (k + 1) + k);
384
- };
385
- this.overshootInOut = (val) => {
386
- const m = val - 1;
387
- const t = val * 2;
388
- const k = 1.70158 * 1.525;
389
- if (val < 0.5) return val * t * (t * (k + 1) - k);
390
- return 1 + 2 * m * m * (2 * m * (k + 1) + k);
391
- };
392
- this.bounceOut = (val) => {
393
- const r = 1 / 2.75;
394
- const k1 = r;
395
- const k2 = 2 * r;
396
- const k3 = 1.5 * r;
397
- const k4 = 2.5 * r;
398
- const k5 = 2.25 * r;
399
- const k6 = 2.625 * r;
400
- const k0 = 7.5625;
401
- let t;
402
- if (val < k1) {
403
- return k0 * val * val;
404
- } else if (val < k2) {
405
- t = val - k3;
406
- return k0 * t * t + 0.75;
407
- } else if (val < k4) {
408
- t = val - k5;
409
- return k0 * t * t + 0.9375;
410
- }
411
- t = val - k6;
412
- return k0 * t * t + 0.984375;
413
- };
414
- this.bounceIn = (val) => {
415
- return 1 - this.bounceOut(1 - val);
416
- };
417
- this.bounceInOut = (val) => {
418
- const t = val * 2;
419
- if (t < 1) return 0.5 - 0.5 * this.bounceOut(1 - t);
420
- return 0.5 + 0.5 * this.bounceOut(t - 1);
421
- };
422
- this.elasticIn = (val) => {
423
- const m = val - 1;
424
- return -Math.pow(2, 10 * m) * Math.sin((m * 40 - 3) * Math.PI / 6);
425
- };
426
- this.elasticOut = (val) => {
427
- return 1 + Math.pow(2, 10 * -val) * Math.sin((-val * 40 - 3) * Math.PI / 6);
428
- };
429
- this.elasticInOut = (val) => {
430
- const s = 2 * val - 1;
431
- const k = (80 * s - 9) * Math.PI / 18;
432
- if (s < 0) return -0.5 * Math.pow(2, 10 * s) * Math.sin(k);
433
- return 1 + 0.5 * Math.pow(2, -10 * s) * Math.sin(k);
434
- };
435
- this.smoothstep = (val, x0 = 0, x1 = 1) => {
436
- let p = (val - x0) / (x1 - x0);
437
- p = p < 0 ? 0 : p > 1 ? 1 : p;
438
- return p * p * (3 - 2 * p);
439
- };
440
- this.log = () => {
441
- console.log(this);
442
- };
443
- this.context = ctx;
444
- }
445
- };
446
- var Easing_default = Easing;
447
-
448
- // src/elements/State.tsx
449
- var State = class {
450
- constructor() {
451
- this.store = /* @__PURE__ */ new Map();
452
- }
453
- set(key, value, callback) {
454
- this.store.set(key, value);
455
- callback?.(key, value);
456
- }
457
- get(key, callback) {
458
- const value = this.store.get(key);
459
- callback?.(key, value);
460
- return value;
461
- }
462
- has(key) {
463
- return this.store.has(key);
464
- }
465
- delete(key, callback) {
466
- this.store.delete(key);
467
- callback?.(key);
468
- }
469
- log() {
470
- return this.store;
471
- }
472
- };
473
- var State_default = State;
474
-
475
- // src/elements/Vector.tsx
476
- var Vector = class _Vector {
477
- /**
478
- * Creates a new Vector
479
- * @param x - X-coordinate (default: 0)
480
- * @param y - Y-coordinate (default: 0)
481
- */
482
- constructor(x = 0, y = 0) {
483
- this.x = x;
484
- this.y = y;
485
- }
486
- /**
487
- * Adds another vector to this vector
488
- * @param v - Vector to add
489
- * @returns This vector after addition
490
- */
491
- add(v) {
492
- this.x += v.x;
493
- this.y += v.y;
494
- return this;
495
- }
496
- /**
497
- * Subtracts another vector from this vector
498
- * @param v - Vector to subtract
499
- * @returns This vector after subtraction
500
- */
501
- sub(v) {
502
- this.x -= v.x;
503
- this.y -= v.y;
504
- return this;
505
- }
506
- /**
507
- * Multiplies this vector by a scalar
508
- * @param n - Scalar to multiply by
509
- * @returns This vector after multiplication
510
- */
511
- mult(n) {
512
- this.x *= n;
513
- this.y *= n;
514
- return this;
515
- }
516
- /**
517
- * Divides this vector by a scalar
518
- * @param n - Scalar to divide by
519
- * @returns This vector after division
520
- */
521
- div(n) {
522
- this.x /= n;
523
- this.y /= n;
524
- return this;
525
- }
526
- // to do : project, perp, slerp
527
- /**
528
- * Rotates this vector by an angle
529
- * @param angle - Angle in radians
530
- * @returns This vector after rotation
531
- */
532
- rotate(angle) {
533
- const cos = Math.cos(angle);
534
- const sin = Math.sin(angle);
535
- const x = this.x * cos - this.y * sin;
536
- const y = this.x * sin + this.y * cos;
537
- this.x = x;
538
- this.y = y;
539
- return this;
540
- }
541
- /**
542
- * Calculates the magnitude (length) of this vector
543
- * @returns The magnitude of the vector
544
- */
545
- mag() {
546
- return Math.sqrt(this.x * this.x + this.y * this.y);
547
- }
548
- /**
549
- * Alias for mag() - calculates the length of this vector
550
- * @returns The length of the vector
551
- */
552
- length() {
553
- return this.mag();
554
- }
555
- /**
556
- * Calculates the dot product of this vector with another vector
557
- * @param v - The other vector
558
- * @returns The dot product
559
- */
560
- dot(v) {
561
- return this.x * v.x + this.y * v.y;
562
- }
563
- /**
564
- * Calculates the distance between this vector and another vector
565
- * @param v - The other vector
566
- * @returns The distance between the vectors
567
- */
568
- dist(v) {
569
- return Math.hypot(this.x - v.x, this.y - v.y);
570
- }
571
- /**
572
- * Calculates the angle of this vector
573
- * @returns The angle in radians
574
- */
575
- angle() {
576
- return Math.atan2(-this.x, -this.y) + Math.PI;
577
- }
578
- /**
579
- * Creates a copy of this vector
580
- * @returns A new Vector with the same coordinates
581
- */
582
- copy() {
583
- return new _Vector(this.x, this.y);
584
- }
585
- /**
586
- * Normalizes this vector (sets its magnitude to 1)
587
- * @returns This vector after normalization
588
- */
589
- normalize() {
590
- const m = this.mag();
591
- return m !== 0 ? this.div(m) : this;
592
- }
593
- /**
594
- * Sets the coordinates of this vector
595
- * @param x - New X-coordinate
596
- * @param y - New Y-coordinate
597
- * @returns This vector after setting coordinates
598
- */
599
- set(x, y) {
600
- this.x = x;
601
- this.y = y;
602
- return this;
603
- }
604
- /**
605
- * Creates a new vector at a specified angle and distance from a center point
606
- * @param center - The center point vector
607
- * @param a - The angle in radians
608
- * @param r - The radius (distance from center)
609
- * @returns A new Vector at the calculated position
610
- */
611
- static fromAngle(center, a, r) {
612
- const x = Math.cos(a) * r + center.x;
613
- const y = Math.sin(a) * r + center.y;
614
- return new _Vector(x, y);
615
- }
616
- };
617
- var Vector_default = Vector;
618
-
619
- // src/elements/Time.tsx
620
- var Time = class {
621
- constructor(ctx) {
622
- this.timelines = /* @__PURE__ */ new Map();
623
- this.currentTimeline = "default";
624
- this.DEFAULT_DURATION = 8 * 60;
625
- this.staggers = [];
626
- this.context = ctx;
627
- this.timelines.set("default", {
628
- progress: 0,
629
- duration: this.DEFAULT_DURATION
630
- });
631
- }
632
- timeline(key) {
633
- if (!this.timelines.has(key)) {
634
- this.timelines.set(key, { progress: 0, duration: this.DEFAULT_DURATION });
635
- }
636
- this.currentTimeline = key;
637
- return this;
638
- }
639
- use(progress) {
640
- const timeline = this.timelines.get(this.currentTimeline);
641
- if (timeline.duration <= 0) {
642
- timeline.progress = 0;
643
- return this;
644
- }
645
- timeline.progress = timeline.duration === 1 ? Math.min(progress, 1) : progress / timeline.duration % 1;
646
- return this;
647
- }
648
- for(duration) {
649
- const timeline = this.timelines.get(this.currentTimeline);
650
- timeline.duration = duration;
651
- return this;
652
- }
653
- stagger(num, offset = 0, callback) {
654
- const timeline = this.timelines.get(this.currentTimeline);
655
- const totalduration = this.context.remap(
656
- timeline.progress,
657
- 0,
658
- 1,
659
- 0,
660
- 1 + offset
661
- );
662
- for (let i = 0; i < num; i++) {
663
- const id = 1 - i / (num - 1);
664
- const progress = this.context.constrain(
665
- totalduration - id * offset,
666
- 0,
667
- 1
668
- );
669
- if (!callback) {
670
- if (this.staggers[i]) {
671
- this.staggers[i].progress = progress;
672
- } else {
673
- this.staggers[i] = { progress, id };
674
- }
675
- } else {
676
- callback?.(progress, id, num);
677
- }
678
- }
679
- return callback ? this : this.staggers;
680
- }
681
- between(from = 0, to = 1, callback) {
682
- const timeline = this.timelines.get(this.currentTimeline);
683
- const localProgress = this.context.remap(
684
- timeline.progress,
685
- Math.max(0, from),
686
- Math.min(1, to),
687
- 0,
688
- 1
689
- );
690
- callback(localProgress);
691
- return this;
692
- }
693
- progress() {
694
- return this.timelines.get(this.currentTimeline)?.progress || 0;
695
- }
696
- };
697
- var Time_default = Time;
698
-
699
- // src/elements/Text.tsx
700
- var Text = class {
701
- constructor(ctx) {
702
- this.findTextSize = (text, dist, estimate, direction = "x") => {
703
- let low = 1;
704
- let high = estimate || this.context.__textSize * 2;
705
- let lastValidSize = low;
706
- for (let i = 0; i < 16; i++) {
707
- const mid = Math.floor((low + high) / 2);
708
- this.context.__textSize = mid;
709
- const bounds = this.textBounds(text);
710
- const size = direction === "x" ? bounds.width : bounds.height;
711
- if (size === dist) {
712
- return mid;
713
- } else if (size < dist) {
714
- lastValidSize = mid;
715
- low = mid + 1;
716
- } else {
717
- high = mid - 1;
718
- }
719
- }
720
- return lastValidSize;
721
- };
722
- this.getTextMetrics = (text) => {
723
- const ctx = this.context;
724
- const metrics = ctx.measureText(text);
725
- return {
726
- width: metrics.width,
727
- height: metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent,
728
- baseline: metrics.actualBoundingBoxAscent
729
- };
730
- };
731
- this.splitTo = (text, kind, options = {}) => {
732
- const ctx = this.context;
733
- const {
734
- maxWidth = 0,
735
- lineSpacing = 0,
736
- letterSpacing = 0,
737
- wordSpacing = 0
738
- } = options;
739
- ctx.computeFont();
740
- if (maxWidth < this.textBounds(" ").width * 2 && maxWidth !== 0) {
741
- return [];
742
- }
743
- const lines = text.split("\n");
744
- const lineHeights = lines.map((line) => this.getTextMetrics(line).height);
745
- const totalHeight = lineHeights.reduce((sum, height) => sum + height, 0) + (lines.length - 1) * (lineSpacing || 0);
746
- let y = ctx.textBaseline === "middle" ? -totalHeight / 2 : 0;
747
- return lines.flatMap((lineText, lineIndex) => {
748
- const words = lineText.split(" ");
749
- const currentLine = {
750
- text: "",
751
- width: 0,
752
- letters: []
753
- };
754
- const totalWidth = this.getTextMetrics(lineText).width;
755
- let startX = 0;
756
- switch (ctx.textAlign) {
757
- case "center":
758
- startX = -totalWidth / 2;
759
- break;
760
- case "right":
761
- startX = -totalWidth;
762
- break;
763
- }
764
- let x = startX;
765
- let letterIndex = 0;
766
- let wordIndex = 0;
767
- const lineLetters = words.flatMap((word) => {
768
- const letters = [];
769
- for (const char of word) {
770
- const charMetrics = this.getTextMetrics(char);
771
- x += charMetrics.width / 2;
772
- const letterData = {
773
- char,
774
- x,
775
- y: y + (ctx.textBaseline === "middle" ? lineHeights[lineIndex] / 2 : 0),
776
- metrics: charMetrics,
777
- ...kind === "all" && {
778
- letterIndex,
779
- wordIndex,
780
- lineIndex
781
- }
782
- };
783
- letters.push(letterData);
784
- currentLine.text += char;
785
- x += charMetrics.width / 2 + letterSpacing;
786
- letterIndex++;
787
- }
788
- if (wordIndex < words.length - 1) {
789
- const spaceMetrics = this.getTextMetrics(" ");
790
- x += spaceMetrics.width + wordSpacing;
791
- letters.push({
792
- char: " ",
793
- x,
794
- y,
795
- metrics: spaceMetrics,
796
- ...kind === "all" && {
797
- letterIndex,
798
- wordIndex,
799
- lineIndex
800
- }
801
- });
802
- currentLine.text += " ";
803
- letterIndex++;
804
- }
805
- wordIndex++;
806
- return letters;
807
- });
808
- const lineHeight = lineHeights[lineIndex];
809
- y += lineHeight + lineSpacing;
810
- return lineLetters;
811
- });
812
- };
813
- this.circularText = (text, radius = 100, fill = "fill", offset = 0, arc = Math.PI * 2) => {
814
- const totalAngle = Math.min(Math.max(arc, 0), Math.PI * 2);
815
- if (fill === "fill") {
816
- const chars = text.split("");
817
- const anglePerChar = totalAngle / (chars.length + 1);
818
- chars.forEach((char, i) => {
819
- const angle = anglePerChar * i + offset;
820
- const x = Math.cos(angle) * radius;
821
- const y = Math.sin(angle) * radius;
822
- this.context.push();
823
- this.context.textAlign = "center";
824
- this.context.translate(x, y);
825
- this.context.rotate(angle + Math.PI / 2);
826
- this.context.text(char, 0, 0);
827
- this.context.pop();
828
- });
829
- } else if (fill === "kerned") {
830
- let currentAngle = offset;
831
- text.split("").forEach((char) => {
832
- const charWidth = this.textBounds(char).width;
833
- currentAngle += charWidth / radius * 0.5;
834
- const angle = currentAngle;
835
- const x = Math.cos(angle) * radius;
836
- const y = Math.sin(angle) * radius;
837
- this.context.push();
838
- this.context.textAlign = "center";
839
- this.context.translate(x, y);
840
- this.context.rotate(angle + Math.PI / 2);
841
- this.context.text(char, 0, 0);
842
- this.context.pop();
843
- currentAngle += charWidth / radius * 0.5;
844
- });
845
- } else if (fill === "words") {
846
- const words = text.split(" ");
847
- const wordMetrics = words.map((word) => ({
848
- word,
849
- width: this.textBounds(word).width
850
- }));
851
- const spaceCount = words.length;
852
- const totalWordWidth = wordMetrics.reduce((sum, m) => sum + m.width, 0);
853
- const spaceAngle = (totalAngle - totalWordWidth / radius) / spaceCount;
854
- let currentAngle = offset;
855
- wordMetrics.forEach(({ word }, i) => {
856
- word.split("").forEach((char) => {
857
- const charWidth = this.textBounds(char).width;
858
- currentAngle += charWidth / radius * 0.5;
859
- const x = Math.cos(currentAngle) * radius;
860
- const y = Math.sin(currentAngle) * radius;
861
- this.context.push();
862
- this.context.textAlign = "center";
863
- this.context.translate(x, y);
864
- this.context.rotate(currentAngle + Math.PI / 2);
865
- this.context.text(char, 0, 0);
866
- this.context.pop();
867
- currentAngle += charWidth / radius * 0.5;
868
- });
869
- if (i < words.length - 1) {
870
- currentAngle += spaceAngle;
871
- }
872
- });
873
- }
874
- };
875
- this.textBounds = (text) => {
876
- if (this.context.font !== this.context.__computedTextFont) {
877
- this.context.font = this.context.__computedTextFont;
878
- }
879
- const metrics = this.context.measureText(text);
880
- return {
881
- x: metrics.actualBoundingBoxLeft * -1,
882
- y: metrics.actualBoundingBoxAscent * -1,
883
- width: metrics.width,
884
- height: metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent
885
- };
886
- };
887
- this.log = () => {
888
- console.log(this.context);
889
- };
890
- this.context = ctx;
891
- }
892
- };
893
- var Text_default = Text;
894
-
895
- // src/elements/Thing.tsx
896
- var Thing = class {
897
- constructor(ctx) {
898
- this.context = ctx;
899
- }
900
- log() {
901
- console.log(this.context);
902
- }
903
- };
904
- var Thing_default = Thing;
905
- export {
906
- Color_default as Color,
907
- Easing_default as Easing,
908
- State_default as State,
909
- Text_default as Text,
910
- Thing_default as Thing,
911
- Time_default as Time,
912
- Vector_default as Vector
913
- };