@bmsuisse/ui 0.17.0 → 0.19.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/index.js CHANGED
@@ -3369,7 +3369,9 @@ function Stepper({
3369
3369
  navLabel = "Steps",
3370
3370
  newLabel = "New",
3371
3371
  scrollTestId = "stepper-scroll",
3372
- newTestId
3372
+ newTestId,
3373
+ minWidth,
3374
+ className
3373
3375
  }) {
3374
3376
  const stepRefs = useRef8(/* @__PURE__ */ new Map());
3375
3377
  useEffect8(() => {
@@ -3380,69 +3382,76 @@ function Stepper({
3380
3382
  // onNew is pinned outside the horizontally-scrolling region below (a sibling of
3381
3383
  // it, not a child) so its own edge never scrolls off-screen along with the
3382
3384
  // later steps once the scroller's min-width doesn't fit the viewport.
3383
- /* @__PURE__ */ jsxs30("div", { className: "flex w-full shrink-0 items-center gap-2", children: [
3385
+ /* @__PURE__ */ jsxs30("div", { className: cn("flex w-full shrink-0 items-center gap-2", className), children: [
3384
3386
  /* @__PURE__ */ jsx48("nav", { "aria-label": navLabel, className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx48(
3385
3387
  "div",
3386
3388
  {
3387
3389
  "data-testid": scrollTestId,
3388
3390
  className: "flex w-full items-center gap-0 overflow-x-auto px-2 py-1",
3389
- children: /* @__PURE__ */ jsx48("ol", { className: "flex min-w-[700px] flex-1 items-start", children: steps.map(({ n, label, phase }, i) => {
3390
- const done = step > n;
3391
- const active = step === n;
3392
- const navigable = n <= maxStep && n !== step;
3393
- const last = i === steps.length - 1;
3394
- return /* @__PURE__ */ jsxs30("li", { className: cn("flex items-start", !last && "flex-1"), children: [
3395
- /* @__PURE__ */ jsxs30(
3396
- "button",
3397
- {
3398
- ref: (element) => {
3399
- if (element) stepRefs.current.set(n, element);
3400
- else stepRefs.current.delete(n);
3401
- },
3402
- "data-testid": `step-${n}`,
3403
- "aria-disabled": !navigable,
3404
- "aria-current": active ? "step" : void 0,
3405
- onClick: () => navigable && onNavigate(n),
3406
- className: cn(
3407
- "flex min-w-[68px] flex-col items-center gap-0.5 transition-opacity",
3408
- navigable ? "cursor-pointer hover:opacity-80" : "cursor-default"
3409
- ),
3410
- children: [
3411
- /* @__PURE__ */ jsx48(
3412
- "div",
3413
- {
3414
- className: cn(
3415
- "flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-[11px] font-bold transition-colors",
3416
- done ? "bg-primary/15 text-primary" : active ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"
3391
+ children: /* @__PURE__ */ jsx48(
3392
+ "ol",
3393
+ {
3394
+ className: cn("flex flex-1 items-start", minWidth === void 0 && "min-w-fit"),
3395
+ style: minWidth === void 0 ? void 0 : { minWidth },
3396
+ children: steps.map(({ n, label, phase }, i) => {
3397
+ const done = step > n;
3398
+ const active = step === n;
3399
+ const navigable = n <= maxStep && n !== step;
3400
+ const last = i === steps.length - 1;
3401
+ return /* @__PURE__ */ jsxs30("li", { className: cn("flex items-start", !last && "flex-1"), children: [
3402
+ /* @__PURE__ */ jsxs30(
3403
+ "button",
3404
+ {
3405
+ ref: (element) => {
3406
+ if (element) stepRefs.current.set(n, element);
3407
+ else stepRefs.current.delete(n);
3408
+ },
3409
+ "data-testid": `step-${n}`,
3410
+ "aria-disabled": !navigable,
3411
+ "aria-current": active ? "step" : void 0,
3412
+ onClick: () => navigable && onNavigate(n),
3413
+ className: cn(
3414
+ "flex min-w-[68px] flex-col items-center gap-0.5 transition-opacity",
3415
+ navigable ? "cursor-pointer hover:opacity-80" : "cursor-default"
3416
+ ),
3417
+ children: [
3418
+ /* @__PURE__ */ jsx48(
3419
+ "div",
3420
+ {
3421
+ className: cn(
3422
+ "flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-[11px] font-bold transition-colors",
3423
+ done ? "bg-primary/15 text-primary" : active ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"
3424
+ ),
3425
+ children: done ? /* @__PURE__ */ jsx48(CheckIcon5, { className: "h-3 w-3" }) : n
3426
+ }
3417
3427
  ),
3418
- children: done ? /* @__PURE__ */ jsx48(CheckIcon5, { className: "h-3 w-3" }) : n
3419
- }
3420
- ),
3421
- /* @__PURE__ */ jsx48(
3422
- "span",
3423
- {
3424
- className: cn(
3425
- "text-center whitespace-nowrap transition-colors",
3426
- active ? "text-[12px] font-semibold text-foreground" : done ? "text-[12px] font-medium text-primary" : "text-[12px] font-medium text-muted-foreground"
3428
+ /* @__PURE__ */ jsx48(
3429
+ "span",
3430
+ {
3431
+ className: cn(
3432
+ "text-center whitespace-nowrap transition-colors",
3433
+ active ? "text-[12px] font-semibold text-foreground" : done ? "text-[12px] font-medium text-primary" : "text-[12px] font-medium text-muted-foreground"
3434
+ ),
3435
+ children: label
3436
+ }
3427
3437
  ),
3428
- children: label
3429
- }
3430
- ),
3431
- /* @__PURE__ */ jsx48("span", { className: "text-[9px] tracking-[0.5px] text-muted-foreground/50 uppercase", children: phase })
3432
- ]
3433
- }
3434
- ),
3435
- !last && /* @__PURE__ */ jsx48(
3436
- "div",
3437
- {
3438
- className: cn(
3439
- "mx-1.5 mt-3.5 h-px flex-1 transition-colors",
3440
- done ? "bg-primary" : "bg-border"
3438
+ phase && /* @__PURE__ */ jsx48("span", { className: "text-[9px] tracking-[0.5px] text-muted-foreground/50 uppercase", children: phase })
3439
+ ]
3440
+ }
3441
+ ),
3442
+ !last && /* @__PURE__ */ jsx48(
3443
+ "div",
3444
+ {
3445
+ className: cn(
3446
+ "mx-1.5 mt-3.5 h-px flex-1 transition-colors",
3447
+ done ? "bg-primary" : "bg-border"
3448
+ )
3449
+ }
3441
3450
  )
3442
- }
3443
- )
3444
- ] }, n);
3445
- }) })
3451
+ ] }, n);
3452
+ })
3453
+ }
3454
+ )
3446
3455
  }
3447
3456
  ) }),
3448
3457
  onNew && /* @__PURE__ */ jsxs30(
@@ -3461,11 +3470,660 @@ function Stepper({
3461
3470
  ] })
3462
3471
  );
3463
3472
  }
3473
+
3474
+ // src/patterns/animated-brand/AnimatedBrand.tsx
3475
+ import {
3476
+ useEffect as useEffect9,
3477
+ useRef as useRef9,
3478
+ useState as useState16
3479
+ } from "react";
3480
+
3481
+ // src/patterns/animated-brand/brandMotion.ts
3482
+ var BRAND_ANIMATIONS = [
3483
+ { id: "bounce", label: "Bounce home" },
3484
+ { id: "orbit", label: "Orbit and settle" },
3485
+ { id: "impact", label: "Shot in, boom" },
3486
+ { id: "liquid", label: "Liquid split" },
3487
+ { id: "signature", label: "Solid to signature" },
3488
+ { id: "burst", label: "Big bang, small dot" },
3489
+ { id: "gravity", label: "Gravity press" }
3490
+ ];
3491
+ function playBrandMotion(p, name, onComplete) {
3492
+ const list = [];
3493
+ if (!p.animate || window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
3494
+ onComplete?.();
3495
+ return () => {
3496
+ };
3497
+ }
3498
+ const accent2 = "var(--bms-brand-dot)";
3499
+ const q = (s) => {
3500
+ const element = p.querySelector(s);
3501
+ if (!element) throw new Error(`Missing logo part: ${s}`);
3502
+ return element;
3503
+ }, logo = q('[data-logo-part="logo"]'), ring = q('[data-logo-part="ring"]'), bead = q('[data-logo-part="bead"]'), tail = q('[data-logo-part="tail"]'), core = q('[data-logo-part="core"]');
3504
+ const unit = parseFloat(getComputedStyle(logo).fontSize) || 48;
3505
+ const a = (el, k, d = 2e3, delay = 0) => {
3506
+ const v = el.animate(k, {
3507
+ duration: d,
3508
+ delay,
3509
+ iterations: 1,
3510
+ fill: "both",
3511
+ easing: "linear"
3512
+ });
3513
+ list.push(v);
3514
+ return v;
3515
+ };
3516
+ const t = (x, y, sx = 1, sy = sx) => `translate(${x}em,${y}em) scale(${sx},${sy})`;
3517
+ const points = (items) => items.map(([offset, x, y, sx = 1, sy = sx, color = accent2]) => ({
3518
+ offset,
3519
+ transform: t(x, y, sx, sy),
3520
+ background: color
3521
+ }));
3522
+ const shock = (delay, strength = 1) => p.querySelectorAll('[data-logo-part="echo"]').forEach((e, j) => {
3523
+ a(
3524
+ e,
3525
+ [
3526
+ { opacity: 0, transform: "scale(1)" },
3527
+ { opacity: 0.48 * strength, transform: "scale(1.6)", offset: 0.08 },
3528
+ { opacity: 0, transform: `scale(${j ? 8 : 6})`, offset: 1 }
3529
+ ],
3530
+ 650,
3531
+ delay + j * 110
3532
+ );
3533
+ });
3534
+ const sparks = (delay, out = 1) => p.querySelectorAll('[data-logo-part="particle"]').forEach((e, j) => {
3535
+ const angle = j * Math.PI / 4, x = Math.cos(angle) * out, y = Math.sin(angle) * out;
3536
+ a(
3537
+ e,
3538
+ [
3539
+ { opacity: 0, transform: t(0, 0, 0.2) },
3540
+ { opacity: 0.85, transform: t(x * 0.3, y * 0.3), offset: 0.12 },
3541
+ { opacity: 0, transform: t(x, y, 0.25), offset: 1 }
3542
+ ],
3543
+ 650,
3544
+ delay
3545
+ );
3546
+ });
3547
+ const impact = (start, duration) => {
3548
+ a(
3549
+ ring,
3550
+ [
3551
+ { offset: 0, transform: "scale(1)" },
3552
+ { offset: start - 0.015, transform: "scale(1)" },
3553
+ { offset: start + 0.045, transform: "scale(.82,1.12)" },
3554
+ { offset: start + 0.12, transform: "scale(1.06,.97)" },
3555
+ { offset: start + 0.24, transform: "scale(1)" },
3556
+ { offset: 1, transform: "scale(1)" }
3557
+ ],
3558
+ duration
3559
+ );
3560
+ a(
3561
+ tail,
3562
+ [
3563
+ { offset: 0, transform: "translateX(0)" },
3564
+ { offset: start, transform: "translateX(0)" },
3565
+ { offset: start + 0.04, transform: "translateX(-.065em)" },
3566
+ { offset: start + 0.14, transform: "translateX(.018em)" },
3567
+ { offset: start + 0.24, transform: "translateX(0)" },
3568
+ { offset: 1, transform: "translateX(0)" }
3569
+ ],
3570
+ duration
3571
+ );
3572
+ };
3573
+ if (name === "bounce") {
3574
+ const beadRect = bead.getBoundingClientRect();
3575
+ const viewportUnitX = beadRect.width > 0 ? beadRect.width / 0.2 : unit;
3576
+ const viewportUnitY = beadRect.height > 0 ? beadRect.height / 0.2 : unit;
3577
+ const originX = beadRect.x + beadRect.width / 2;
3578
+ const originY = beadRect.y + beadRect.height / 2;
3579
+ const letters = Array.from(
3580
+ p.querySelectorAll("[data-brand-letter]")
3581
+ ).reverse();
3582
+ const baseline = p.querySelector("[data-brand-baseline]")?.getBoundingClientRect().top ?? originY;
3583
+ const pen = typeof CanvasRenderingContext2D !== "undefined" ? document.createElement("canvas").getContext("2d") : null;
3584
+ if (pen) pen.font = getComputedStyle(logo).font;
3585
+ const stops = letters.length ? letters.map((letter) => {
3586
+ const rect = letter.getBoundingClientRect();
3587
+ const ascent = pen?.measureText(letter.textContent ?? "").actualBoundingBoxAscent ?? unit * 0.7;
3588
+ return {
3589
+ x: (rect.x + rect.width / 2 - originX) / viewportUnitX,
3590
+ y: (baseline - originY) / viewportUnitY - ascent / unit - 0.1
3591
+ };
3592
+ }) : [
3593
+ { x: -1.1, y: -0.7 },
3594
+ { x: -0.3, y: -0.4 },
3595
+ { x: 0.3, y: -0.4 }
3596
+ ];
3597
+ const duration = 1e3 + stops.length * 340;
3598
+ let from = { x: stops[0].x + 0.5, y: stops[0].y - 0.65 };
3599
+ const frames = [{ offset: 0, transform: t(from.x, from.y) }];
3600
+ const destinations = [...stops, { x: 0, y: 0 }];
3601
+ const jumpEnd = 0.94;
3602
+ destinations.forEach((to, index) => {
3603
+ const start = index / destinations.length * jumpEnd;
3604
+ const length = jumpEnd / destinations.length;
3605
+ for (let k = 1; k <= 10; k++) {
3606
+ const u = k / 10;
3607
+ frames.push({
3608
+ offset: start + length * u * 0.87,
3609
+ transform: t(
3610
+ from.x + (to.x - from.x) * u,
3611
+ from.y + (to.y - from.y) * u - 1.6 * u * (1 - u)
3612
+ )
3613
+ });
3614
+ }
3615
+ frames.push({
3616
+ offset: start + length * 0.94,
3617
+ transform: t(to.x, to.y + 0.018, 1.15, 0.82)
3618
+ });
3619
+ frames.push({ offset: start + length, transform: t(to.x, to.y) });
3620
+ from = to;
3621
+ });
3622
+ frames.push({ offset: 1, transform: t(0, 0) });
3623
+ a(bead, frames, duration);
3624
+ shock(duration * 0.94, 0.5);
3625
+ } else if (name === "orbit") {
3626
+ const frames = [];
3627
+ for (let step = 0; step <= 72; step++) {
3628
+ const u = step / 72;
3629
+ const angle = -Math.PI / 2 + u * Math.PI * 3.7;
3630
+ const radius = 0.683 * (1 - u ** 2.4);
3631
+ frames.push({
3632
+ offset: u,
3633
+ transform: t(Math.cos(angle) * radius, Math.sin(angle) * radius)
3634
+ });
3635
+ }
3636
+ a(bead, frames, 2500);
3637
+ a(
3638
+ ring,
3639
+ [
3640
+ { transform: "scale(1)" },
3641
+ { offset: 0.8, transform: "scale(1.06)" },
3642
+ { offset: 1, transform: "scale(1)" }
3643
+ ],
3644
+ 2500
3645
+ );
3646
+ shock(2400, 0.5);
3647
+ } else if (name === "impact") {
3648
+ const d = 1650;
3649
+ a(
3650
+ bead,
3651
+ points([
3652
+ [0, 6.5, 0, 4, 0.38],
3653
+ [0.2, 6.5, 0, 4, 0.38],
3654
+ [0.3, 1.5, 0, 4, 0.38],
3655
+ [0.33, 0, 0, 0.55, 1.55],
3656
+ [0.39, -0.09, 0, 1.35, 0.72],
3657
+ [0.48, 0.035, 0, 0.93, 1.06],
3658
+ [0.65, 0, 0, 1, 1],
3659
+ [1, 0, 0, 1, 1]
3660
+ ]),
3661
+ d
3662
+ );
3663
+ a(
3664
+ q('[data-logo-part="trail"]'),
3665
+ [
3666
+ { opacity: 0, transform: t(6.5, 0, 2, 1) },
3667
+ { opacity: 0, transform: t(6.5, 0, 2, 1), offset: 0.2 },
3668
+ { opacity: 0.6, transform: t(0.5, 0, 1.8, 1), offset: 0.32 },
3669
+ { opacity: 0, transform: t(0, 0, 0.1, 1), offset: 0.39 },
3670
+ { opacity: 0, offset: 1 }
3671
+ ],
3672
+ d
3673
+ );
3674
+ impact(0.33, d);
3675
+ shock(545);
3676
+ sparks(545, 0.94);
3677
+ } else if (name === "liquid") {
3678
+ const d = 2400;
3679
+ a(
3680
+ bead,
3681
+ points([
3682
+ [0, 0, 0, 4],
3683
+ [0.15, 0, 0, 4],
3684
+ [0.3, 0, 0, 5.2, 2.7],
3685
+ [0.43, 0, 0, 2.8, 4.4],
3686
+ [0.58, 0, 0, 1.6, 2],
3687
+ [0.74, 0, 0, 0.85, 1.15],
3688
+ [0.88, 0, 0, 1.06, 0.94],
3689
+ [1, 0, 0, 1]
3690
+ ]),
3691
+ d
3692
+ );
3693
+ a(
3694
+ ring,
3695
+ [
3696
+ { offset: 0, opacity: 0, transform: "scale(.2) rotate(-35deg)" },
3697
+ { offset: 0.36, opacity: 0, transform: "scale(.2) rotate(-35deg)" },
3698
+ { offset: 0.63, opacity: 1, transform: "scale(1.1,.9) rotate(8deg)" },
3699
+ { offset: 0.8, opacity: 1, transform: "scale(.97,1.03) rotate(-2deg)" },
3700
+ { offset: 1, opacity: 1, transform: "scale(1) rotate(0deg)" }
3701
+ ],
3702
+ d
3703
+ );
3704
+ a(
3705
+ tail,
3706
+ [
3707
+ { offset: 0, opacity: 0, transform: "translateX(-.25em)" },
3708
+ { offset: 0.35, opacity: 0, transform: "translateX(-.25em)" },
3709
+ { offset: 0.72, opacity: 1, transform: "translateX(.025em)" },
3710
+ { offset: 1, opacity: 1, transform: "translateX(0)" }
3711
+ ],
3712
+ d
3713
+ );
3714
+ } else if (name === "gravity") {
3715
+ const d = 2600;
3716
+ a(
3717
+ bead,
3718
+ points([
3719
+ [0, 0, -1.15, 4],
3720
+ [0.12, 0, -1.15, 4],
3721
+ [0.24, 0, -0.88, 4],
3722
+ [0.34, 0, -0.35, 3.7, 4.3],
3723
+ [0.4, 0, 0.15, 5.1, 2.5],
3724
+ [0.49, 0, -0.32, 3.4, 4.2],
3725
+ [0.58, 0, 0.07, 4.4, 3.5],
3726
+ [0.67, 0, 0, 3.8, 4],
3727
+ [0.81, 0, 0, 0.78, 1.22],
3728
+ [0.91, 0, 0, 1.1, 0.9],
3729
+ [1, 0, 0, 1]
3730
+ ]),
3731
+ d
3732
+ );
3733
+ a(
3734
+ ring,
3735
+ [
3736
+ { offset: 0, opacity: 0, transform: "scale(.25)" },
3737
+ { offset: 0.64, opacity: 0, transform: "scale(.25)" },
3738
+ { offset: 0.81, opacity: 1, transform: "scale(1.12,.88)" },
3739
+ { offset: 0.92, opacity: 1, transform: "scale(.97,1.03)" },
3740
+ { offset: 1, opacity: 1, transform: "scale(1)" }
3741
+ ],
3742
+ d
3743
+ );
3744
+ a(
3745
+ tail,
3746
+ [
3747
+ { offset: 0, opacity: 0, transform: "translateY(.12em)" },
3748
+ { offset: 0.43, opacity: 0, transform: "translateY(.12em)" },
3749
+ { offset: 0.72, opacity: 1, transform: "translateY(0)" },
3750
+ { offset: 1, opacity: 1, transform: "translateY(0)" }
3751
+ ],
3752
+ d
3753
+ );
3754
+ shock(1040, 0.5);
3755
+ } else if (name === "signature") {
3756
+ const d = 2200;
3757
+ a(
3758
+ core,
3759
+ [
3760
+ { opacity: 1, background: accent2, transform: "scale(1)" },
3761
+ { opacity: 1, background: accent2, transform: "scale(1.08)", offset: 0.22 },
3762
+ { opacity: 1, background: accent2, transform: "scale(.22)", offset: 0.65 },
3763
+ { opacity: 1, background: accent2, transform: "scale(.25)", offset: 0.84 },
3764
+ { opacity: 0, background: accent2, transform: "scale(.25)", offset: 1 }
3765
+ ],
3766
+ d
3767
+ );
3768
+ a(
3769
+ bead,
3770
+ [{ opacity: 0 }, { opacity: 0, offset: 0.85 }, { opacity: 1, offset: 1 }],
3771
+ d
3772
+ );
3773
+ a(
3774
+ ring,
3775
+ [
3776
+ { opacity: 0, transform: "scale(.3)" },
3777
+ { opacity: 0, transform: "scale(.3)", offset: 0.25 },
3778
+ { opacity: 1, transform: "scale(1.04)", offset: 0.65 },
3779
+ { opacity: 1, transform: "scale(1)", offset: 0.83 },
3780
+ { opacity: 1, transform: "scale(1)", offset: 1 }
3781
+ ],
3782
+ d
3783
+ );
3784
+ a(
3785
+ tail,
3786
+ [
3787
+ { opacity: 0, transform: "translateX(-.18em)" },
3788
+ { opacity: 0, transform: "translateX(-.18em)", offset: 0.22 },
3789
+ { opacity: 1, transform: "translateX(0)", offset: 0.64 },
3790
+ { opacity: 1, transform: "translateX(0)", offset: 1 }
3791
+ ],
3792
+ d
3793
+ );
3794
+ } else {
3795
+ const d = 2500;
3796
+ a(
3797
+ core,
3798
+ [
3799
+ { opacity: 1, background: accent2, transform: "scale(.92)" },
3800
+ { opacity: 1, background: accent2, transform: "scale(1.14)", offset: 0.24 },
3801
+ { opacity: 0, background: accent2, transform: "scale(.1)", offset: 0.36 },
3802
+ { opacity: 0, offset: 1 }
3803
+ ],
3804
+ d
3805
+ );
3806
+ a(
3807
+ bead,
3808
+ [
3809
+ { opacity: 0, transform: "scale(.2)" },
3810
+ { opacity: 0, transform: "scale(.2)", offset: 0.69 },
3811
+ { opacity: 1, transform: "scale(1.2)", offset: 0.84 },
3812
+ { opacity: 1, transform: "scale(1)", offset: 1 }
3813
+ ],
3814
+ d
3815
+ );
3816
+ a(
3817
+ ring,
3818
+ [
3819
+ { opacity: 0, transform: "scale(.82)" },
3820
+ { opacity: 0, transform: "scale(.82)", offset: 0.34 },
3821
+ { opacity: 0.7, transform: "scale(1.04)", offset: 0.57 },
3822
+ { opacity: 1, transform: "scale(1)", offset: 0.82 },
3823
+ { opacity: 1, transform: "scale(1)", offset: 1 }
3824
+ ],
3825
+ d
3826
+ );
3827
+ a(
3828
+ tail,
3829
+ [
3830
+ { opacity: 0.15, transform: "translateX(-.06em)" },
3831
+ { opacity: 0.15, transform: "translateX(-.06em)", offset: 0.3 },
3832
+ { opacity: 1, transform: "translateX(0)", offset: 0.68 },
3833
+ { opacity: 1, transform: "translateX(0)", offset: 1 }
3834
+ ],
3835
+ d
3836
+ );
3837
+ p.querySelectorAll('[data-logo-part="particle"]').forEach((el, j) => {
3838
+ const angle = j * Math.PI / 4, x = Math.cos(angle) * 0.86, y = Math.sin(angle) * 0.86;
3839
+ a(
3840
+ el,
3841
+ [
3842
+ { opacity: 0, transform: t(0, 0, 0.2) },
3843
+ { opacity: 0, transform: t(0, 0, 0.2), offset: 0.27 },
3844
+ { opacity: 1, transform: t(x, y, 1.2), offset: 0.43 },
3845
+ { opacity: 1, transform: t(x * 0.85, y * 0.85), offset: 0.59 },
3846
+ { opacity: 0, transform: t(0, 0, 0.5), offset: 0.82 },
3847
+ { opacity: 0, transform: t(0, 0, 0.5), offset: 1 }
3848
+ ],
3849
+ d
3850
+ );
3851
+ });
3852
+ shock(1800, 0.6);
3853
+ }
3854
+ let cancelled = false;
3855
+ void Promise.all(list.map((animation) => animation.finished)).then(
3856
+ () => {
3857
+ if (!cancelled) {
3858
+ for (const animation of list) animation.cancel();
3859
+ onComplete?.();
3860
+ }
3861
+ },
3862
+ () => {
3863
+ }
3864
+ );
3865
+ return () => {
3866
+ cancelled = true;
3867
+ for (const animation of list) animation.cancel();
3868
+ };
3869
+ }
3870
+
3871
+ // src/patterns/animated-brand/AnimatedBrand.tsx
3872
+ import { jsx as jsx49, jsxs as jsxs31 } from "react/jsx-runtime";
3873
+ var absolute = {
3874
+ position: "absolute",
3875
+ borderRadius: "50%",
3876
+ pointerEvents: "none"
3877
+ };
3878
+ var centered = {
3879
+ ...absolute,
3880
+ width: ".2em",
3881
+ height: ".2em",
3882
+ left: "50%",
3883
+ top: "50%",
3884
+ margin: "-.1em"
3885
+ };
3886
+ var accent = "var(--bms-brand-dot)";
3887
+ function AnimatedBrand({
3888
+ product = "Brain",
3889
+ dotColor = "#e60028",
3890
+ textColor = "#929292",
3891
+ oneColor,
3892
+ productColor,
3893
+ ringColor,
3894
+ mode = "full",
3895
+ animation = "random",
3896
+ size = 48,
3897
+ autoPlay = true,
3898
+ replayKey,
3899
+ onComplete,
3900
+ className,
3901
+ style
3902
+ }) {
3903
+ const ref = useRef9(null);
3904
+ const completion = useRef9(onComplete);
3905
+ const [segmented, setSegmented] = useState16(null);
3906
+ useEffect9(() => {
3907
+ const letters2 = typeof Intl.Segmenter === "function" ? Array.from(new Intl.Segmenter(void 0, { granularity: "grapheme" }).segment(product), ({ segment }) => segment) : product ? [product] : [];
3908
+ setSegmented({ product, letters: letters2 });
3909
+ }, [product]);
3910
+ useEffect9(() => {
3911
+ completion.current = onComplete;
3912
+ }, [onComplete]);
3913
+ useEffect9(() => {
3914
+ const element = ref.current;
3915
+ if (!element || !autoPlay || segmented?.product !== product) return;
3916
+ let disposed = false;
3917
+ let stop;
3918
+ let completed = false;
3919
+ const finish = () => {
3920
+ if (!disposed && !completed) {
3921
+ completed = true;
3922
+ completion.current?.();
3923
+ }
3924
+ };
3925
+ const reduced = window.matchMedia("(prefers-reduced-motion: reduce)");
3926
+ const changed = () => {
3927
+ if (reduced.matches) {
3928
+ stop?.();
3929
+ finish();
3930
+ }
3931
+ };
3932
+ reduced.addEventListener("change", changed);
3933
+ const start = () => {
3934
+ if (disposed || completed) return;
3935
+ if (reduced.matches) {
3936
+ finish();
3937
+ return;
3938
+ }
3939
+ const choice = animation === "random" ? BRAND_ANIMATIONS[Math.floor(Math.random() * BRAND_ANIMATIONS.length)].id : animation;
3940
+ stop = playBrandMotion(element, choice, finish);
3941
+ };
3942
+ void (document.fonts?.ready ?? Promise.resolve()).then(start, start);
3943
+ return () => {
3944
+ disposed = true;
3945
+ stop?.();
3946
+ reduced.removeEventListener("change", changed);
3947
+ };
3948
+ }, [product, mode, animation, size, autoPlay, replayKey, segmented]);
3949
+ const tail = mode === "full" ? `ne${product}` : mode === "one" ? "ne" : "";
3950
+ const suffix = mode === "full" && product ? segmented?.product === product ? segmented.letters : [product] : [];
3951
+ const letters = tail ? ["n", "e", ...suffix] : [];
3952
+ const label = mode === "full" ? `One${product}` : mode === "one" ? "One" : "O";
3953
+ const wrapperStyle = {
3954
+ "--bms-brand-dot": dotColor,
3955
+ display: "inline-flex",
3956
+ fontSize: size,
3957
+ color: textColor,
3958
+ ...style
3959
+ };
3960
+ return /* @__PURE__ */ jsx49(
3961
+ "span",
3962
+ {
3963
+ ref,
3964
+ className,
3965
+ style: wrapperStyle,
3966
+ children: /* @__PURE__ */ jsxs31(
3967
+ "span",
3968
+ {
3969
+ "data-logo-part": "logo",
3970
+ role: "img",
3971
+ "aria-label": label,
3972
+ style: {
3973
+ display: "inline-flex",
3974
+ position: "relative",
3975
+ alignItems: "center",
3976
+ fontSize: "inherit",
3977
+ fontWeight: 700,
3978
+ lineHeight: 1,
3979
+ letterSpacing: "-.055em",
3980
+ whiteSpace: "nowrap",
3981
+ userSelect: "none"
3982
+ },
3983
+ children: [
3984
+ /* @__PURE__ */ jsxs31(
3985
+ "span",
3986
+ {
3987
+ "data-logo-part": "mark",
3988
+ "aria-hidden": "true",
3989
+ style: {
3990
+ position: "relative",
3991
+ flex: "none",
3992
+ color: ringColor ?? oneColor,
3993
+ width: ".8em",
3994
+ height: ".8em",
3995
+ marginRight: tail ? ".04em" : 0
3996
+ },
3997
+ children: [
3998
+ /* @__PURE__ */ jsx49(
3999
+ "span",
4000
+ {
4001
+ "data-logo-part": "ring",
4002
+ style: {
4003
+ ...absolute,
4004
+ inset: 0,
4005
+ border: ".157em solid currentColor",
4006
+ boxSizing: "border-box"
4007
+ }
4008
+ }
4009
+ ),
4010
+ /* @__PURE__ */ jsx49(
4011
+ "span",
4012
+ {
4013
+ "data-logo-part": "core",
4014
+ style: {
4015
+ ...absolute,
4016
+ inset: 0,
4017
+ background: accent,
4018
+ opacity: 0,
4019
+ zIndex: 2
4020
+ }
4021
+ }
4022
+ ),
4023
+ /* @__PURE__ */ jsx49(
4024
+ "span",
4025
+ {
4026
+ "data-logo-part": "trail",
4027
+ style: {
4028
+ position: "absolute",
4029
+ width: "1.8em",
4030
+ height: ".045em",
4031
+ left: "50%",
4032
+ top: "50%",
4033
+ marginTop: "-.0225em",
4034
+ background: `linear-gradient(90deg, ${accent}, transparent)`,
4035
+ transformOrigin: "left center",
4036
+ opacity: 0,
4037
+ pointerEvents: "none"
4038
+ }
4039
+ }
4040
+ ),
4041
+ [0, 1].map((id) => /* @__PURE__ */ jsx49(
4042
+ "span",
4043
+ {
4044
+ "data-logo-part": "echo",
4045
+ style: {
4046
+ ...centered,
4047
+ border: `.025em solid ${accent}`,
4048
+ boxSizing: "border-box",
4049
+ opacity: 0
4050
+ }
4051
+ },
4052
+ id
4053
+ )),
4054
+ Array.from({ length: 8 }, (_, id) => /* @__PURE__ */ jsx49(
4055
+ "span",
4056
+ {
4057
+ "data-logo-part": "particle",
4058
+ style: {
4059
+ ...centered,
4060
+ width: ".055em",
4061
+ height: ".055em",
4062
+ margin: "-.0275em",
4063
+ background: accent,
4064
+ opacity: 0
4065
+ }
4066
+ },
4067
+ id
4068
+ )),
4069
+ /* @__PURE__ */ jsx49(
4070
+ "span",
4071
+ {
4072
+ "data-logo-part": "bead",
4073
+ style: { ...centered, background: accent, zIndex: 3 }
4074
+ }
4075
+ )
4076
+ ]
4077
+ }
4078
+ ),
4079
+ /* @__PURE__ */ jsxs31(
4080
+ "span",
4081
+ {
4082
+ "data-logo-part": "tail",
4083
+ "aria-hidden": "true",
4084
+ style: {
4085
+ display: "inline-flex",
4086
+ alignItems: "baseline",
4087
+ whiteSpace: "pre"
4088
+ },
4089
+ children: [
4090
+ letters.map((letter, index) => /* @__PURE__ */ jsx49(
4091
+ "span",
4092
+ {
4093
+ "data-brand-letter": "",
4094
+ style: { display: "inline-block", color: index < 2 ? oneColor : productColor },
4095
+ children: letter
4096
+ },
4097
+ `${index}-${letter}`
4098
+ )),
4099
+ /* @__PURE__ */ jsx49(
4100
+ "span",
4101
+ {
4102
+ "data-brand-baseline": "",
4103
+ style: {
4104
+ display: "inline-block",
4105
+ width: 0,
4106
+ height: 0,
4107
+ alignSelf: "baseline"
4108
+ }
4109
+ }
4110
+ )
4111
+ ]
4112
+ }
4113
+ )
4114
+ ]
4115
+ }
4116
+ )
4117
+ }
4118
+ );
4119
+ }
3464
4120
  export {
3465
4121
  AiButton,
3466
4122
  AiExplainButton,
3467
4123
  AlertBox,
4124
+ AnimatedBrand,
3468
4125
  AsyncBoundary,
4126
+ BRAND_ANIMATIONS,
3469
4127
  Badge,
3470
4128
  Button,
3471
4129
  ButtonGroup,