@bmsuisse/ui 0.18.0 → 0.20.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/CATALOG.md +101 -0
- package/dist/index.d.ts +197 -8
- package/dist/index.js +808 -78
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
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(
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
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
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
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:
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
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
|
-
|
|
3445
|
-
|
|
3451
|
+
] }, n);
|
|
3452
|
+
})
|
|
3453
|
+
}
|
|
3454
|
+
)
|
|
3446
3455
|
}
|
|
3447
3456
|
) }),
|
|
3448
3457
|
onNew && /* @__PURE__ */ jsxs30(
|
|
@@ -3462,11 +3471,717 @@ function Stepper({
|
|
|
3462
3471
|
);
|
|
3463
3472
|
}
|
|
3464
3473
|
|
|
3474
|
+
// src/patterns/empty-state/EmptyState.tsx
|
|
3475
|
+
import { FunnelIcon } from "@heroicons/react/24/outline";
|
|
3476
|
+
import { jsx as jsx49, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
3477
|
+
var EmptyState = ({
|
|
3478
|
+
title,
|
|
3479
|
+
description,
|
|
3480
|
+
icon: Icon2,
|
|
3481
|
+
action,
|
|
3482
|
+
size = "md",
|
|
3483
|
+
fill = false,
|
|
3484
|
+
className,
|
|
3485
|
+
...props
|
|
3486
|
+
}) => {
|
|
3487
|
+
const sm = size === "sm";
|
|
3488
|
+
return /* @__PURE__ */ jsxs31(
|
|
3489
|
+
"div",
|
|
3490
|
+
{
|
|
3491
|
+
"data-testid": "empty-state",
|
|
3492
|
+
className: cn(
|
|
3493
|
+
"flex flex-col items-center text-center",
|
|
3494
|
+
sm ? "gap-1 px-4 py-4" : "gap-1.5 px-6 py-8",
|
|
3495
|
+
fill && "min-h-0 flex-1 justify-center",
|
|
3496
|
+
className
|
|
3497
|
+
),
|
|
3498
|
+
...props,
|
|
3499
|
+
children: [
|
|
3500
|
+
Icon2 ? /* @__PURE__ */ jsx49(
|
|
3501
|
+
"div",
|
|
3502
|
+
{
|
|
3503
|
+
className: cn(
|
|
3504
|
+
"mb-1 flex items-center justify-center rounded-full bg-muted",
|
|
3505
|
+
sm ? "h-8 w-8" : "h-12 w-12"
|
|
3506
|
+
),
|
|
3507
|
+
children: /* @__PURE__ */ jsx49(Icon2, { "aria-hidden": "true", className: cn("text-muted-foreground", sm ? "h-4 w-4" : "h-6 w-6") })
|
|
3508
|
+
}
|
|
3509
|
+
) : null,
|
|
3510
|
+
/* @__PURE__ */ jsx49("p", { className: cn("font-semibold text-foreground", sm ? "text-xs" : "text-sm"), children: title }),
|
|
3511
|
+
description ? /* @__PURE__ */ jsx49("p", { className: cn("max-w-prose text-muted-foreground", sm ? "text-xs" : "text-sm"), children: description }) : null,
|
|
3512
|
+
action ? /* @__PURE__ */ jsx49("div", { className: "mt-2 flex justify-center gap-2", children: action }) : null
|
|
3513
|
+
]
|
|
3514
|
+
}
|
|
3515
|
+
);
|
|
3516
|
+
};
|
|
3517
|
+
var defaultFilteredEmptyStateLabels = {
|
|
3518
|
+
title: "No results",
|
|
3519
|
+
description: "Nothing matches the current search or filters.",
|
|
3520
|
+
reset: "Reset filters"
|
|
3521
|
+
};
|
|
3522
|
+
var FilteredEmptyState = ({
|
|
3523
|
+
onReset,
|
|
3524
|
+
labels,
|
|
3525
|
+
icon = FunnelIcon,
|
|
3526
|
+
size,
|
|
3527
|
+
...props
|
|
3528
|
+
}) => {
|
|
3529
|
+
const l = { ...defaultFilteredEmptyStateLabels, ...labels };
|
|
3530
|
+
const rootTestId = props["data-testid"];
|
|
3531
|
+
return /* @__PURE__ */ jsx49(
|
|
3532
|
+
EmptyState,
|
|
3533
|
+
{
|
|
3534
|
+
icon,
|
|
3535
|
+
size,
|
|
3536
|
+
title: l.title,
|
|
3537
|
+
description: l.description,
|
|
3538
|
+
action: /* @__PURE__ */ jsx49(
|
|
3539
|
+
Button,
|
|
3540
|
+
{
|
|
3541
|
+
type: "button",
|
|
3542
|
+
variant: "outline",
|
|
3543
|
+
size: size === "sm" ? "xs" : "sm",
|
|
3544
|
+
onClick: onReset,
|
|
3545
|
+
"data-testid": typeof rootTestId === "string" ? `${rootTestId}-reset` : void 0,
|
|
3546
|
+
children: l.reset
|
|
3547
|
+
}
|
|
3548
|
+
),
|
|
3549
|
+
...props
|
|
3550
|
+
}
|
|
3551
|
+
);
|
|
3552
|
+
};
|
|
3553
|
+
|
|
3554
|
+
// src/patterns/toast/toastStore.ts
|
|
3555
|
+
var DEFAULT_TOAST_DURATION = { info: 4e3, success: 4e3, warning: 4e3, error: 8e3 };
|
|
3556
|
+
var MAX_TOASTS = 3;
|
|
3557
|
+
var TOAST_EXIT_MS = 150;
|
|
3558
|
+
var toasts = [];
|
|
3559
|
+
var nextId = 1;
|
|
3560
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
3561
|
+
var emit = (next) => {
|
|
3562
|
+
toasts = next;
|
|
3563
|
+
for (const l of listeners) l();
|
|
3564
|
+
};
|
|
3565
|
+
var subscribeToasts = (listener) => {
|
|
3566
|
+
listeners.add(listener);
|
|
3567
|
+
return () => listeners.delete(listener);
|
|
3568
|
+
};
|
|
3569
|
+
var getToasts = () => toasts;
|
|
3570
|
+
var EMPTY = [];
|
|
3571
|
+
var getServerToasts = () => EMPTY;
|
|
3572
|
+
var remove = (id) => emit(toasts.filter((t) => t.id !== id));
|
|
3573
|
+
function dismissToast(id) {
|
|
3574
|
+
const targets = toasts.filter((t) => !t.leaving && (id === void 0 || t.id === id));
|
|
3575
|
+
if (targets.length === 0) return;
|
|
3576
|
+
const ids = new Set(targets.map((t) => t.id));
|
|
3577
|
+
emit(toasts.map((t) => ids.has(t.id) ? { ...t, leaving: true } : t));
|
|
3578
|
+
setTimeout(() => {
|
|
3579
|
+
for (const i of ids) remove(i);
|
|
3580
|
+
}, TOAST_EXIT_MS);
|
|
3581
|
+
}
|
|
3582
|
+
function show(message, options = {}) {
|
|
3583
|
+
const id = nextId++;
|
|
3584
|
+
const tone = options.tone ?? "info";
|
|
3585
|
+
const item = {
|
|
3586
|
+
id,
|
|
3587
|
+
message,
|
|
3588
|
+
description: options.description,
|
|
3589
|
+
tone,
|
|
3590
|
+
action: options.action,
|
|
3591
|
+
duration: options.duration,
|
|
3592
|
+
leaving: false
|
|
3593
|
+
};
|
|
3594
|
+
const active = toasts.filter((t) => !t.leaving);
|
|
3595
|
+
if (active.length >= MAX_TOASTS) {
|
|
3596
|
+
const victim = active.find((t) => t.duration !== Infinity) ?? active[0];
|
|
3597
|
+
if (victim) dismissToast(victim.id);
|
|
3598
|
+
}
|
|
3599
|
+
emit([...toasts, item]);
|
|
3600
|
+
return id;
|
|
3601
|
+
}
|
|
3602
|
+
var toast = Object.assign(show, {
|
|
3603
|
+
info: (message, options) => show(message, { ...options, tone: "info" }),
|
|
3604
|
+
success: (message, options) => show(message, { ...options, tone: "success" }),
|
|
3605
|
+
warning: (message, options) => show(message, { ...options, tone: "warning" }),
|
|
3606
|
+
error: (message, options) => show(message, { ...options, tone: "error" }),
|
|
3607
|
+
dismiss: dismissToast
|
|
3608
|
+
});
|
|
3609
|
+
function resetToasts() {
|
|
3610
|
+
emit([]);
|
|
3611
|
+
}
|
|
3612
|
+
|
|
3613
|
+
// src/patterns/toast/Toaster.tsx
|
|
3614
|
+
import {
|
|
3615
|
+
CheckCircleIcon as CheckCircleIcon2,
|
|
3616
|
+
ExclamationTriangleIcon as ExclamationTriangleIcon6,
|
|
3617
|
+
InformationCircleIcon as InformationCircleIcon2,
|
|
3618
|
+
XCircleIcon,
|
|
3619
|
+
XMarkIcon as XMarkIcon6
|
|
3620
|
+
} from "@heroicons/react/24/outline";
|
|
3621
|
+
import { useEffect as useEffect9, useRef as useRef9, useState as useState16, useSyncExternalStore } from "react";
|
|
3622
|
+
import { jsx as jsx50, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
3623
|
+
var defaultToasterLabels = {
|
|
3624
|
+
region: "Notifications",
|
|
3625
|
+
dismiss: "Dismiss"
|
|
3626
|
+
};
|
|
3627
|
+
var positionClass = {
|
|
3628
|
+
"bottom-center": "bottom-4 items-center pb-[env(safe-area-inset-bottom)]",
|
|
3629
|
+
"bottom-left": "bottom-4 items-start pb-[env(safe-area-inset-bottom)]",
|
|
3630
|
+
"bottom-right": "bottom-4 items-end pb-[env(safe-area-inset-bottom)]",
|
|
3631
|
+
"top-center": "top-4 items-center pt-[env(safe-area-inset-top)]",
|
|
3632
|
+
"top-left": "top-4 items-start pt-[env(safe-area-inset-top)]",
|
|
3633
|
+
"top-right": "top-4 items-end pt-[env(safe-area-inset-top)]"
|
|
3634
|
+
};
|
|
3635
|
+
var toneIcon = {
|
|
3636
|
+
info: InformationCircleIcon2,
|
|
3637
|
+
success: CheckCircleIcon2,
|
|
3638
|
+
warning: ExclamationTriangleIcon6,
|
|
3639
|
+
error: XCircleIcon
|
|
3640
|
+
};
|
|
3641
|
+
var toneIconClass = {
|
|
3642
|
+
info: "text-sky-600 dark:text-sky-400",
|
|
3643
|
+
success: "text-emerald-600 dark:text-emerald-400",
|
|
3644
|
+
warning: "text-amber-600 dark:text-amber-400",
|
|
3645
|
+
error: "text-destructive"
|
|
3646
|
+
};
|
|
3647
|
+
var Toaster = ({ position = "bottom-center", duration, labels, className }) => {
|
|
3648
|
+
const toasts2 = useSyncExternalStore(subscribeToasts, getToasts, getServerToasts);
|
|
3649
|
+
const l = { ...defaultToasterLabels, ...labels };
|
|
3650
|
+
const top = position.startsWith("top");
|
|
3651
|
+
return /* @__PURE__ */ jsx50(
|
|
3652
|
+
"section",
|
|
3653
|
+
{
|
|
3654
|
+
"aria-label": l.region,
|
|
3655
|
+
"aria-live": "polite",
|
|
3656
|
+
className: cn(
|
|
3657
|
+
"pointer-events-none fixed inset-x-0 z-[100] flex gap-2 px-4",
|
|
3658
|
+
top ? "flex-col-reverse" : "flex-col",
|
|
3659
|
+
positionClass[position],
|
|
3660
|
+
className
|
|
3661
|
+
),
|
|
3662
|
+
children: toasts2.map((t) => /* @__PURE__ */ jsx50(ToastCard, { toast: t, duration: resolveDuration(t, duration), dismissLabel: l.dismiss }, t.id))
|
|
3663
|
+
}
|
|
3664
|
+
);
|
|
3665
|
+
};
|
|
3666
|
+
var resolveDuration = (t, fallback) => t.duration ?? (typeof fallback === "number" ? fallback : fallback?.[t.tone] ?? DEFAULT_TOAST_DURATION[t.tone]);
|
|
3667
|
+
var ToastCard = ({
|
|
3668
|
+
toast: toast2,
|
|
3669
|
+
duration,
|
|
3670
|
+
dismissLabel
|
|
3671
|
+
}) => {
|
|
3672
|
+
const [entered, setEntered] = useState16(false);
|
|
3673
|
+
const [hovered, setHovered] = useState16(false);
|
|
3674
|
+
const [focused, setFocused] = useState16(false);
|
|
3675
|
+
const paused = hovered || focused;
|
|
3676
|
+
const bar = useRef9(null);
|
|
3677
|
+
const Icon2 = toneIcon[toast2.tone];
|
|
3678
|
+
const timed = Number.isFinite(duration) && duration > 0;
|
|
3679
|
+
useEffect9(() => {
|
|
3680
|
+
const raf = requestAnimationFrame(() => setEntered(true));
|
|
3681
|
+
return () => cancelAnimationFrame(raf);
|
|
3682
|
+
}, []);
|
|
3683
|
+
const remaining = useRef9(duration);
|
|
3684
|
+
const animRef = useRef9(null);
|
|
3685
|
+
useEffect9(() => {
|
|
3686
|
+
if (!timed || toast2.leaving) return;
|
|
3687
|
+
const el = bar.current;
|
|
3688
|
+
if (el && typeof el.animate === "function") {
|
|
3689
|
+
const anim = el.animate([{ transform: "scaleX(1)" }, { transform: "scaleX(0)" }], {
|
|
3690
|
+
duration,
|
|
3691
|
+
fill: "forwards"
|
|
3692
|
+
});
|
|
3693
|
+
anim.onfinish = () => dismissToast(toast2.id);
|
|
3694
|
+
animRef.current = anim;
|
|
3695
|
+
return () => {
|
|
3696
|
+
anim.onfinish = null;
|
|
3697
|
+
anim.cancel();
|
|
3698
|
+
animRef.current = null;
|
|
3699
|
+
};
|
|
3700
|
+
}
|
|
3701
|
+
return void 0;
|
|
3702
|
+
}, [timed, duration, toast2.id, toast2.leaving]);
|
|
3703
|
+
useEffect9(() => {
|
|
3704
|
+
if (!timed || toast2.leaving) return;
|
|
3705
|
+
if (animRef.current) {
|
|
3706
|
+
if (paused) animRef.current.pause();
|
|
3707
|
+
else animRef.current.play();
|
|
3708
|
+
return;
|
|
3709
|
+
}
|
|
3710
|
+
if (paused) return;
|
|
3711
|
+
const started = Date.now();
|
|
3712
|
+
const handle = setTimeout(() => dismissToast(toast2.id), remaining.current);
|
|
3713
|
+
return () => {
|
|
3714
|
+
clearTimeout(handle);
|
|
3715
|
+
remaining.current -= Date.now() - started;
|
|
3716
|
+
};
|
|
3717
|
+
}, [paused, timed, toast2.id, toast2.leaving]);
|
|
3718
|
+
const shown = entered && !toast2.leaving;
|
|
3719
|
+
return /* @__PURE__ */ jsxs32(
|
|
3720
|
+
"div",
|
|
3721
|
+
{
|
|
3722
|
+
role: toast2.tone === "error" ? "alert" : void 0,
|
|
3723
|
+
"data-testid": "toast",
|
|
3724
|
+
"data-tone": toast2.tone,
|
|
3725
|
+
"data-state": toast2.leaving ? "closed" : "open",
|
|
3726
|
+
onPointerEnter: (e) => {
|
|
3727
|
+
if (e.pointerType === "mouse") setHovered(true);
|
|
3728
|
+
},
|
|
3729
|
+
onPointerLeave: () => setHovered(false),
|
|
3730
|
+
onFocus: () => setFocused(true),
|
|
3731
|
+
onBlur: (e) => {
|
|
3732
|
+
if (!e.currentTarget.contains(e.relatedTarget)) setFocused(false);
|
|
3733
|
+
},
|
|
3734
|
+
className: cn(
|
|
3735
|
+
"pointer-events-auto relative flex w-full max-w-sm items-start gap-2 overflow-hidden rounded-lg border border-border bg-card px-3 py-2.5 text-sm text-card-foreground shadow-lg transition-[opacity,transform] duration-150 ease-out motion-reduce:transition-none",
|
|
3736
|
+
shown ? "translate-y-0 opacity-100" : "translate-y-2 opacity-0",
|
|
3737
|
+
toast2.leaving && "pointer-events-none"
|
|
3738
|
+
),
|
|
3739
|
+
children: [
|
|
3740
|
+
/* @__PURE__ */ jsx50(Icon2, { "aria-hidden": "true", className: cn("mt-0.5 h-4 w-4 shrink-0", toneIconClass[toast2.tone]) }),
|
|
3741
|
+
/* @__PURE__ */ jsxs32("div", { className: "min-w-0 flex-1", children: [
|
|
3742
|
+
/* @__PURE__ */ jsx50("p", { className: "font-medium", children: toast2.message }),
|
|
3743
|
+
toast2.description ? /* @__PURE__ */ jsx50("p", { className: "mt-0.5 text-xs text-muted-foreground", children: toast2.description }) : null
|
|
3744
|
+
] }),
|
|
3745
|
+
toast2.action ? /* @__PURE__ */ jsx50(
|
|
3746
|
+
"button",
|
|
3747
|
+
{
|
|
3748
|
+
type: "button",
|
|
3749
|
+
"data-testid": "toast-action",
|
|
3750
|
+
onClick: () => {
|
|
3751
|
+
if (toast2.leaving) return;
|
|
3752
|
+
toast2.action?.onClick();
|
|
3753
|
+
dismissToast(toast2.id);
|
|
3754
|
+
},
|
|
3755
|
+
className: "shrink-0 rounded-sm px-1.5 py-0.5 font-semibold text-foreground underline-offset-2 hover:bg-accent hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
3756
|
+
children: toast2.action.label
|
|
3757
|
+
}
|
|
3758
|
+
) : null,
|
|
3759
|
+
/* @__PURE__ */ jsx50(
|
|
3760
|
+
"button",
|
|
3761
|
+
{
|
|
3762
|
+
type: "button",
|
|
3763
|
+
"aria-label": dismissLabel,
|
|
3764
|
+
onClick: () => dismissToast(toast2.id),
|
|
3765
|
+
className: "grid h-5 w-5 shrink-0 place-items-center rounded-sm text-muted-foreground hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
3766
|
+
children: /* @__PURE__ */ jsx50(XMarkIcon6, { "aria-hidden": "true", className: "h-3.5 w-3.5" })
|
|
3767
|
+
}
|
|
3768
|
+
),
|
|
3769
|
+
timed && !toast2.leaving ? /* @__PURE__ */ jsx50(
|
|
3770
|
+
"span",
|
|
3771
|
+
{
|
|
3772
|
+
ref: bar,
|
|
3773
|
+
"aria-hidden": "true",
|
|
3774
|
+
"data-testid": "toast-progress",
|
|
3775
|
+
className: "absolute inset-x-0 bottom-0 h-0.5 origin-left bg-foreground/25 motion-reduce:opacity-0"
|
|
3776
|
+
}
|
|
3777
|
+
) : null
|
|
3778
|
+
]
|
|
3779
|
+
}
|
|
3780
|
+
);
|
|
3781
|
+
};
|
|
3782
|
+
|
|
3783
|
+
// src/patterns/date-input/DateInput.tsx
|
|
3784
|
+
import { CalendarDaysIcon } from "@heroicons/react/24/outline";
|
|
3785
|
+
import { forwardRef as forwardRef20, useEffect as useEffect11, useId as useId3, useImperativeHandle, useRef as useRef11, useState as useState18 } from "react";
|
|
3786
|
+
|
|
3787
|
+
// src/lib/dateField.ts
|
|
3788
|
+
var layoutCache = /* @__PURE__ */ new Map();
|
|
3789
|
+
function layoutOf(locale) {
|
|
3790
|
+
const cached = layoutCache.get(locale);
|
|
3791
|
+
if (cached) return cached;
|
|
3792
|
+
const parts = new Intl.DateTimeFormat(locale, { day: "2-digit", month: "2-digit", year: "numeric" }).formatToParts(
|
|
3793
|
+
new Date(2001, 1, 3)
|
|
3794
|
+
);
|
|
3795
|
+
const order = parts.filter((p) => p.type === "day" || p.type === "month" || p.type === "year").map((p) => p.type);
|
|
3796
|
+
const separator = parts.find((p) => p.type === "literal")?.value.trim() || ".";
|
|
3797
|
+
const layout = { order, separator };
|
|
3798
|
+
layoutCache.set(locale, layout);
|
|
3799
|
+
return layout;
|
|
3800
|
+
}
|
|
3801
|
+
var WORD = { day: "dd", month: "mm", year: "yyyy" };
|
|
3802
|
+
function datePlaceholder(locale) {
|
|
3803
|
+
const { order, separator } = layoutOf(locale);
|
|
3804
|
+
return order.map((part) => WORD[part]).join(separator);
|
|
3805
|
+
}
|
|
3806
|
+
var pad = (n, width) => String(n).padStart(width, "0");
|
|
3807
|
+
function formatIsoDay(iso, locale) {
|
|
3808
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})(?:[T ].*)?$/.exec(iso);
|
|
3809
|
+
if (!match) return "";
|
|
3810
|
+
const { order, separator } = layoutOf(locale);
|
|
3811
|
+
const [, year = "", month = "", day = ""] = match;
|
|
3812
|
+
const value = { year, month, day };
|
|
3813
|
+
return order.map((part) => value[part]).join(separator);
|
|
3814
|
+
}
|
|
3815
|
+
var isRealDay = (year, month, day) => {
|
|
3816
|
+
const date = new Date(year, month - 1, day);
|
|
3817
|
+
return date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day;
|
|
3818
|
+
};
|
|
3819
|
+
var TWO_DIGIT_YEAR_LOOKAHEAD = 20;
|
|
3820
|
+
function expandYear(raw) {
|
|
3821
|
+
const n = Number(raw);
|
|
3822
|
+
if (raw.length > 2) return n;
|
|
3823
|
+
const now = (/* @__PURE__ */ new Date()).getFullYear();
|
|
3824
|
+
const century = Math.floor(now / 100) * 100;
|
|
3825
|
+
return century + n > now + TWO_DIGIT_YEAR_LOOKAHEAD ? century - 100 + n : century + n;
|
|
3826
|
+
}
|
|
3827
|
+
function splitDigits(digits, order) {
|
|
3828
|
+
if (digits.length !== 6 && digits.length !== 8) return null;
|
|
3829
|
+
const width = { day: 2, month: 2, year: digits.length - 4 };
|
|
3830
|
+
const out = [];
|
|
3831
|
+
let at = 0;
|
|
3832
|
+
for (const part of order) {
|
|
3833
|
+
out.push(digits.slice(at, at + width[part]));
|
|
3834
|
+
at += width[part];
|
|
3835
|
+
}
|
|
3836
|
+
return out;
|
|
3837
|
+
}
|
|
3838
|
+
function parseIsoDay(text, locale) {
|
|
3839
|
+
const trimmed = text.trim().replace(/\.$/, "");
|
|
3840
|
+
const iso = /^(\d{4})-(\d{1,2})-(\d{1,2})(?:[T ].*)?$/.exec(trimmed);
|
|
3841
|
+
let year;
|
|
3842
|
+
let month;
|
|
3843
|
+
let day;
|
|
3844
|
+
if (iso) {
|
|
3845
|
+
[year, month, day] = [Number(iso[1]), Number(iso[2]), Number(iso[3])];
|
|
3846
|
+
} else {
|
|
3847
|
+
const { order } = layoutOf(locale);
|
|
3848
|
+
const typed = /^(\d{1,4})[./\-\s]+(\d{1,2})[./\-\s]+(\d{1,4})$/.exec(trimmed);
|
|
3849
|
+
const raw = typed ? [typed[1] ?? "", typed[2] ?? "", typed[3] ?? ""] : /^\d+$/.test(trimmed) ? splitDigits(trimmed, order) : null;
|
|
3850
|
+
if (!raw) return null;
|
|
3851
|
+
const at = (part) => raw[order.indexOf(part)] ?? "";
|
|
3852
|
+
year = expandYear(at("year"));
|
|
3853
|
+
month = Number(at("month"));
|
|
3854
|
+
day = Number(at("day"));
|
|
3855
|
+
}
|
|
3856
|
+
if (year < 1e3 || year > 9999 || !isRealDay(year, month, day)) return null;
|
|
3857
|
+
return `${pad(year, 4)}-${pad(month, 2)}-${pad(day, 2)}`;
|
|
3858
|
+
}
|
|
3859
|
+
function toLocalIsoDay(d) {
|
|
3860
|
+
return `${pad(d.getFullYear(), 4)}-${pad(d.getMonth() + 1, 2)}-${pad(d.getDate(), 2)}`;
|
|
3861
|
+
}
|
|
3862
|
+
var daysInMonth = (year, month) => new Date(year, month, 0).getDate();
|
|
3863
|
+
function shiftIsoDay(iso, by) {
|
|
3864
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})/.exec(iso);
|
|
3865
|
+
if (!match) return iso;
|
|
3866
|
+
const year = Number(match[1]);
|
|
3867
|
+
const month = Number(match[2]);
|
|
3868
|
+
const day = Number(match[3]);
|
|
3869
|
+
const total = year * 12 + (month - 1) + (by.months ?? 0);
|
|
3870
|
+
const nextYear = Math.floor(total / 12);
|
|
3871
|
+
const nextMonth = total % 12 + 1;
|
|
3872
|
+
const moved = new Date(nextYear, nextMonth - 1, Math.min(day, daysInMonth(nextYear, nextMonth)) + (by.days ?? 0));
|
|
3873
|
+
const result = moved.getFullYear();
|
|
3874
|
+
return result < 1e3 || result > 9999 ? iso : toLocalIsoDay(moved);
|
|
3875
|
+
}
|
|
3876
|
+
|
|
3877
|
+
// src/patterns/date-input/NativeDateInput.tsx
|
|
3878
|
+
import { forwardRef as forwardRef19, useEffect as useEffect10, useId as useId2, useRef as useRef10, useState as useState17 } from "react";
|
|
3879
|
+
|
|
3880
|
+
// src/patterns/date-input/shared.tsx
|
|
3881
|
+
import { useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
3882
|
+
import { jsx as jsx51 } from "react/jsx-runtime";
|
|
3883
|
+
var defaultDateInputLabels = {
|
|
3884
|
+
invalid: "Enter a valid date",
|
|
3885
|
+
outOfRange: "Date is out of range",
|
|
3886
|
+
openCalendar: "Choose date"
|
|
3887
|
+
};
|
|
3888
|
+
var toDay = (iso) => iso?.slice(0, 10) ?? "";
|
|
3889
|
+
var COARSE = "(pointer: coarse)";
|
|
3890
|
+
var subscribeCoarse = (listener) => {
|
|
3891
|
+
const mq = typeof window !== "undefined" ? window.matchMedia?.(COARSE) : void 0;
|
|
3892
|
+
mq?.addEventListener("change", listener);
|
|
3893
|
+
return () => mq?.removeEventListener("change", listener);
|
|
3894
|
+
};
|
|
3895
|
+
var isCoarse = () => typeof window !== "undefined" && !!window.matchMedia?.(COARSE).matches;
|
|
3896
|
+
var useCoarsePointer = () => useSyncExternalStore2(subscribeCoarse, isCoarse, () => false);
|
|
3897
|
+
var errorMessage = (error, l) => error === "invalid" ? l.invalid : error === "range" ? l.outOfRange : "";
|
|
3898
|
+
var DateInputMessage = ({ id, message }) => /* @__PURE__ */ jsx51("p", { id, role: "alert", className: "mt-1 text-xs text-destructive", children: message });
|
|
3899
|
+
var invalidClass = "aria-[invalid=true]:border-destructive aria-[invalid=true]:ring-destructive";
|
|
3900
|
+
|
|
3901
|
+
// src/patterns/date-input/NativeDateInput.tsx
|
|
3902
|
+
import { jsx as jsx52, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
3903
|
+
var NativeDateInput = forwardRef19(
|
|
3904
|
+
({
|
|
3905
|
+
value,
|
|
3906
|
+
onValueChange,
|
|
3907
|
+
onInvalidChange,
|
|
3908
|
+
locale: _locale,
|
|
3909
|
+
native: _native,
|
|
3910
|
+
min,
|
|
3911
|
+
max,
|
|
3912
|
+
showError = true,
|
|
3913
|
+
labels,
|
|
3914
|
+
onBlur,
|
|
3915
|
+
placeholder: _placeholder,
|
|
3916
|
+
className,
|
|
3917
|
+
name,
|
|
3918
|
+
...props
|
|
3919
|
+
}, ref) => {
|
|
3920
|
+
const l = { ...defaultDateInputLabels, ...labels };
|
|
3921
|
+
const minDay = toDay(min);
|
|
3922
|
+
const maxDay = toDay(max);
|
|
3923
|
+
const [raw, setRaw] = useState17(toDay(value));
|
|
3924
|
+
const [error, setErrorState] = useState17(null);
|
|
3925
|
+
const errorRef = useRef10(null);
|
|
3926
|
+
const messageId = useId2();
|
|
3927
|
+
const setError = (next) => {
|
|
3928
|
+
if (errorRef.current === next) return;
|
|
3929
|
+
errorRef.current = next;
|
|
3930
|
+
setErrorState(next);
|
|
3931
|
+
onInvalidChange?.(next != null, next ?? void 0);
|
|
3932
|
+
};
|
|
3933
|
+
useEffect10(() => {
|
|
3934
|
+
setRaw(toDay(value));
|
|
3935
|
+
setError(null);
|
|
3936
|
+
}, [value]);
|
|
3937
|
+
const message = errorMessage(error, l);
|
|
3938
|
+
const showMessage = showError && message !== "";
|
|
3939
|
+
const describedBy = [props["aria-describedby"], showMessage ? messageId : void 0].filter(Boolean).join(" ") || void 0;
|
|
3940
|
+
return /* @__PURE__ */ jsxs33("div", { className, children: [
|
|
3941
|
+
/* @__PURE__ */ jsx52(
|
|
3942
|
+
Input,
|
|
3943
|
+
{
|
|
3944
|
+
ref,
|
|
3945
|
+
...props,
|
|
3946
|
+
className: invalidClass,
|
|
3947
|
+
type: "date",
|
|
3948
|
+
min: minDay || void 0,
|
|
3949
|
+
max: maxDay || void 0,
|
|
3950
|
+
value: raw,
|
|
3951
|
+
"aria-invalid": error != null || props["aria-invalid"] || void 0,
|
|
3952
|
+
"aria-describedby": describedBy,
|
|
3953
|
+
onChange: (e) => {
|
|
3954
|
+
const el = e.currentTarget;
|
|
3955
|
+
const next = el.value;
|
|
3956
|
+
setRaw(next);
|
|
3957
|
+
if (el.validity.badInput) {
|
|
3958
|
+
setError(null);
|
|
3959
|
+
return;
|
|
3960
|
+
}
|
|
3961
|
+
if (next && (minDay && next < minDay || maxDay && next > maxDay)) {
|
|
3962
|
+
setError("range");
|
|
3963
|
+
return;
|
|
3964
|
+
}
|
|
3965
|
+
setError(null);
|
|
3966
|
+
if (next !== toDay(value)) onValueChange(next);
|
|
3967
|
+
},
|
|
3968
|
+
onBlur: (e) => {
|
|
3969
|
+
if (e.currentTarget.validity.badInput) setError("invalid");
|
|
3970
|
+
onBlur?.(e);
|
|
3971
|
+
}
|
|
3972
|
+
}
|
|
3973
|
+
),
|
|
3974
|
+
showMessage ? /* @__PURE__ */ jsx52(DateInputMessage, { id: messageId, message }) : null,
|
|
3975
|
+
name ? /* @__PURE__ */ jsx52("input", { type: "hidden", name, value: toDay(value) }) : null
|
|
3976
|
+
] });
|
|
3977
|
+
}
|
|
3978
|
+
);
|
|
3979
|
+
NativeDateInput.displayName = "NativeDateInput";
|
|
3980
|
+
|
|
3981
|
+
// src/patterns/date-input/DateInput.tsx
|
|
3982
|
+
import { Fragment as Fragment6, jsx as jsx53, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
3983
|
+
function check(text, locale, min, max) {
|
|
3984
|
+
if (!text.trim()) return null;
|
|
3985
|
+
const iso = parseIsoDay(text, locale);
|
|
3986
|
+
if (iso == null) return "invalid";
|
|
3987
|
+
if (min && iso < min || max && iso > max) return "range";
|
|
3988
|
+
return null;
|
|
3989
|
+
}
|
|
3990
|
+
var DateInput = forwardRef20((props, ref) => {
|
|
3991
|
+
const coarse = useCoarsePointer();
|
|
3992
|
+
const useNative = props.native === "always" || props.native !== "never" && coarse;
|
|
3993
|
+
return useNative ? /* @__PURE__ */ jsx53(NativeDateInput, { ref, ...props }) : /* @__PURE__ */ jsx53(TypedDateInput, { ref, ...props });
|
|
3994
|
+
});
|
|
3995
|
+
DateInput.displayName = "DateInput";
|
|
3996
|
+
var TypedDateInput = forwardRef20(
|
|
3997
|
+
({
|
|
3998
|
+
value,
|
|
3999
|
+
onValueChange,
|
|
4000
|
+
onInvalidChange,
|
|
4001
|
+
locale = "de-CH",
|
|
4002
|
+
min,
|
|
4003
|
+
max,
|
|
4004
|
+
showError = true,
|
|
4005
|
+
labels,
|
|
4006
|
+
onBlur,
|
|
4007
|
+
onKeyDown,
|
|
4008
|
+
onFocus,
|
|
4009
|
+
placeholder,
|
|
4010
|
+
className,
|
|
4011
|
+
name,
|
|
4012
|
+
disabled,
|
|
4013
|
+
readOnly,
|
|
4014
|
+
native: _native,
|
|
4015
|
+
...props
|
|
4016
|
+
}, ref) => {
|
|
4017
|
+
const l = { ...defaultDateInputLabels, ...labels };
|
|
4018
|
+
const minDay = toDay(min);
|
|
4019
|
+
const maxDay = toDay(max);
|
|
4020
|
+
const [text, setText] = useState18(() => formatIsoDay(value, locale));
|
|
4021
|
+
const [error, setErrorState] = useState18(null);
|
|
4022
|
+
const dirty = useRef11(false);
|
|
4023
|
+
const focused = useRef11(false);
|
|
4024
|
+
const inputRef = useRef11(null);
|
|
4025
|
+
const pickerRef = useRef11(null);
|
|
4026
|
+
const messageId = useId3();
|
|
4027
|
+
useImperativeHandle(ref, () => inputRef.current);
|
|
4028
|
+
const errorRef = useRef11(null);
|
|
4029
|
+
const setError = (next) => {
|
|
4030
|
+
if (errorRef.current === next) return;
|
|
4031
|
+
errorRef.current = next;
|
|
4032
|
+
setErrorState(next);
|
|
4033
|
+
onInvalidChange?.(next != null, next ?? void 0);
|
|
4034
|
+
};
|
|
4035
|
+
useEffect11(() => {
|
|
4036
|
+
if (focused.current && dirty.current) return;
|
|
4037
|
+
setText(formatIsoDay(value, locale));
|
|
4038
|
+
setError(null);
|
|
4039
|
+
}, [value, locale]);
|
|
4040
|
+
const live = check(text, locale, minDay, maxDay);
|
|
4041
|
+
const liveMessage = live === "invalid" ? l.invalid : live === "range" ? l.outOfRange : "";
|
|
4042
|
+
useEffect11(() => {
|
|
4043
|
+
inputRef.current?.setCustomValidity(liveMessage);
|
|
4044
|
+
}, [liveMessage]);
|
|
4045
|
+
const commitIso = (iso) => {
|
|
4046
|
+
setText(formatIsoDay(iso, locale));
|
|
4047
|
+
setError(null);
|
|
4048
|
+
if (iso !== value.slice(0, 10)) onValueChange(iso);
|
|
4049
|
+
};
|
|
4050
|
+
const commit = () => {
|
|
4051
|
+
if (!dirty.current) return;
|
|
4052
|
+
dirty.current = false;
|
|
4053
|
+
if (!text.trim()) {
|
|
4054
|
+
setError(null);
|
|
4055
|
+
if (value) onValueChange("");
|
|
4056
|
+
return;
|
|
4057
|
+
}
|
|
4058
|
+
const problem = check(text, locale, minDay, maxDay);
|
|
4059
|
+
setError(problem);
|
|
4060
|
+
if (problem) return;
|
|
4061
|
+
commitIso(parseIsoDay(text, locale));
|
|
4062
|
+
};
|
|
4063
|
+
const step = (key, shift) => {
|
|
4064
|
+
const by = key === "ArrowUp" ? { days: 1 } : key === "ArrowDown" ? { days: -1 } : key === "PageUp" ? { months: shift ? 12 : 1 } : key === "PageDown" ? { months: shift ? -12 : -1 } : null;
|
|
4065
|
+
if (!by) return null;
|
|
4066
|
+
const base = parseIsoDay(text, locale) ?? (toDay(value) || toLocalIsoDay(/* @__PURE__ */ new Date()));
|
|
4067
|
+
let next = text.trim() || value ? shiftIsoDay(base, by) : base;
|
|
4068
|
+
if (minDay && next < minDay) next = minDay;
|
|
4069
|
+
if (maxDay && next > maxDay) next = maxDay;
|
|
4070
|
+
return next;
|
|
4071
|
+
};
|
|
4072
|
+
const openPicker = () => {
|
|
4073
|
+
const el = pickerRef.current;
|
|
4074
|
+
if (!el) return;
|
|
4075
|
+
try {
|
|
4076
|
+
el.showPicker();
|
|
4077
|
+
} catch {
|
|
4078
|
+
el.click();
|
|
4079
|
+
}
|
|
4080
|
+
};
|
|
4081
|
+
const message = errorMessage(error, l);
|
|
4082
|
+
const showMessage = showError && message !== "";
|
|
4083
|
+
const pickable = !disabled && !readOnly;
|
|
4084
|
+
const describedBy = [props["aria-describedby"], showMessage ? messageId : void 0].filter(Boolean).join(" ") || void 0;
|
|
4085
|
+
return /* @__PURE__ */ jsxs34("div", { className, children: [
|
|
4086
|
+
/* @__PURE__ */ jsxs34("div", { className: "relative", children: [
|
|
4087
|
+
/* @__PURE__ */ jsx53(
|
|
4088
|
+
Input,
|
|
4089
|
+
{
|
|
4090
|
+
ref: inputRef,
|
|
4091
|
+
...props,
|
|
4092
|
+
disabled,
|
|
4093
|
+
readOnly,
|
|
4094
|
+
className: cn(invalidClass, pickable && "pr-9"),
|
|
4095
|
+
type: "text",
|
|
4096
|
+
autoComplete: "off",
|
|
4097
|
+
value: text,
|
|
4098
|
+
placeholder: placeholder ?? datePlaceholder(locale),
|
|
4099
|
+
"aria-invalid": error != null || props["aria-invalid"] || void 0,
|
|
4100
|
+
"aria-describedby": describedBy,
|
|
4101
|
+
onChange: (e) => {
|
|
4102
|
+
dirty.current = true;
|
|
4103
|
+
setText(e.target.value);
|
|
4104
|
+
setError(null);
|
|
4105
|
+
},
|
|
4106
|
+
onFocus: (e) => {
|
|
4107
|
+
focused.current = true;
|
|
4108
|
+
onFocus?.(e);
|
|
4109
|
+
},
|
|
4110
|
+
onBlur: (e) => {
|
|
4111
|
+
focused.current = false;
|
|
4112
|
+
commit();
|
|
4113
|
+
onBlur?.(e);
|
|
4114
|
+
},
|
|
4115
|
+
onKeyDown: (e) => {
|
|
4116
|
+
onKeyDown?.(e);
|
|
4117
|
+
if (e.defaultPrevented) return;
|
|
4118
|
+
if (e.key === "Enter") commit();
|
|
4119
|
+
else if (!readOnly && !disabled) {
|
|
4120
|
+
if (e.key === "ArrowDown" && e.altKey) {
|
|
4121
|
+
e.preventDefault();
|
|
4122
|
+
openPicker();
|
|
4123
|
+
} else if (!e.altKey && !e.ctrlKey && !e.metaKey) {
|
|
4124
|
+
const next = step(e.key, e.shiftKey);
|
|
4125
|
+
if (next) {
|
|
4126
|
+
e.preventDefault();
|
|
4127
|
+
dirty.current = false;
|
|
4128
|
+
commitIso(next);
|
|
4129
|
+
}
|
|
4130
|
+
}
|
|
4131
|
+
}
|
|
4132
|
+
}
|
|
4133
|
+
}
|
|
4134
|
+
),
|
|
4135
|
+
pickable ? /* @__PURE__ */ jsxs34(Fragment6, { children: [
|
|
4136
|
+
/* @__PURE__ */ jsx53(
|
|
4137
|
+
"button",
|
|
4138
|
+
{
|
|
4139
|
+
type: "button",
|
|
4140
|
+
"aria-label": l.openCalendar,
|
|
4141
|
+
onClick: openPicker,
|
|
4142
|
+
className: "absolute inset-y-0 right-0 grid w-9 place-items-center rounded-r-md text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
4143
|
+
children: /* @__PURE__ */ jsx53(CalendarDaysIcon, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
4144
|
+
}
|
|
4145
|
+
),
|
|
4146
|
+
/* @__PURE__ */ jsx53(
|
|
4147
|
+
"input",
|
|
4148
|
+
{
|
|
4149
|
+
ref: pickerRef,
|
|
4150
|
+
type: "date",
|
|
4151
|
+
tabIndex: -1,
|
|
4152
|
+
"aria-hidden": "true",
|
|
4153
|
+
form: "bmsui-date-input-picker",
|
|
4154
|
+
"data-testid": "date-input-picker",
|
|
4155
|
+
min: minDay || void 0,
|
|
4156
|
+
max: maxDay || void 0,
|
|
4157
|
+
value: toDay(value),
|
|
4158
|
+
onChange: (e) => {
|
|
4159
|
+
const iso = e.target.value;
|
|
4160
|
+
dirty.current = false;
|
|
4161
|
+
if (iso) commitIso(iso);
|
|
4162
|
+
else {
|
|
4163
|
+
setText("");
|
|
4164
|
+
setError(null);
|
|
4165
|
+
if (value) onValueChange("");
|
|
4166
|
+
}
|
|
4167
|
+
},
|
|
4168
|
+
className: "pointer-events-none absolute inset-0 h-full w-full opacity-0"
|
|
4169
|
+
}
|
|
4170
|
+
)
|
|
4171
|
+
] }) : null
|
|
4172
|
+
] }),
|
|
4173
|
+
showMessage ? /* @__PURE__ */ jsx53(DateInputMessage, { id: messageId, message }) : null,
|
|
4174
|
+
name ? /* @__PURE__ */ jsx53("input", { type: "hidden", name, value: toDay(value) }) : null
|
|
4175
|
+
] });
|
|
4176
|
+
}
|
|
4177
|
+
);
|
|
4178
|
+
TypedDateInput.displayName = "TypedDateInput";
|
|
4179
|
+
|
|
3465
4180
|
// src/patterns/animated-brand/AnimatedBrand.tsx
|
|
3466
4181
|
import {
|
|
3467
|
-
useEffect as
|
|
3468
|
-
useRef as
|
|
3469
|
-
useState as
|
|
4182
|
+
useEffect as useEffect12,
|
|
4183
|
+
useRef as useRef12,
|
|
4184
|
+
useState as useState19
|
|
3470
4185
|
} from "react";
|
|
3471
4186
|
|
|
3472
4187
|
// src/patterns/animated-brand/brandMotion.ts
|
|
@@ -3860,7 +4575,7 @@ function playBrandMotion(p, name, onComplete) {
|
|
|
3860
4575
|
}
|
|
3861
4576
|
|
|
3862
4577
|
// src/patterns/animated-brand/AnimatedBrand.tsx
|
|
3863
|
-
import { jsx as
|
|
4578
|
+
import { jsx as jsx54, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
3864
4579
|
var absolute = {
|
|
3865
4580
|
position: "absolute",
|
|
3866
4581
|
borderRadius: "50%",
|
|
@@ -3891,17 +4606,17 @@ function AnimatedBrand({
|
|
|
3891
4606
|
className,
|
|
3892
4607
|
style
|
|
3893
4608
|
}) {
|
|
3894
|
-
const ref =
|
|
3895
|
-
const completion =
|
|
3896
|
-
const [segmented, setSegmented] =
|
|
3897
|
-
|
|
4609
|
+
const ref = useRef12(null);
|
|
4610
|
+
const completion = useRef12(onComplete);
|
|
4611
|
+
const [segmented, setSegmented] = useState19(null);
|
|
4612
|
+
useEffect12(() => {
|
|
3898
4613
|
const letters2 = typeof Intl.Segmenter === "function" ? Array.from(new Intl.Segmenter(void 0, { granularity: "grapheme" }).segment(product), ({ segment }) => segment) : product ? [product] : [];
|
|
3899
4614
|
setSegmented({ product, letters: letters2 });
|
|
3900
4615
|
}, [product]);
|
|
3901
|
-
|
|
4616
|
+
useEffect12(() => {
|
|
3902
4617
|
completion.current = onComplete;
|
|
3903
4618
|
}, [onComplete]);
|
|
3904
|
-
|
|
4619
|
+
useEffect12(() => {
|
|
3905
4620
|
const element = ref.current;
|
|
3906
4621
|
if (!element || !autoPlay || segmented?.product !== product) return;
|
|
3907
4622
|
let disposed = false;
|
|
@@ -3948,13 +4663,13 @@ function AnimatedBrand({
|
|
|
3948
4663
|
color: textColor,
|
|
3949
4664
|
...style
|
|
3950
4665
|
};
|
|
3951
|
-
return /* @__PURE__ */
|
|
4666
|
+
return /* @__PURE__ */ jsx54(
|
|
3952
4667
|
"span",
|
|
3953
4668
|
{
|
|
3954
4669
|
ref,
|
|
3955
4670
|
className,
|
|
3956
4671
|
style: wrapperStyle,
|
|
3957
|
-
children: /* @__PURE__ */
|
|
4672
|
+
children: /* @__PURE__ */ jsxs35(
|
|
3958
4673
|
"span",
|
|
3959
4674
|
{
|
|
3960
4675
|
"data-logo-part": "logo",
|
|
@@ -3972,7 +4687,7 @@ function AnimatedBrand({
|
|
|
3972
4687
|
userSelect: "none"
|
|
3973
4688
|
},
|
|
3974
4689
|
children: [
|
|
3975
|
-
/* @__PURE__ */
|
|
4690
|
+
/* @__PURE__ */ jsxs35(
|
|
3976
4691
|
"span",
|
|
3977
4692
|
{
|
|
3978
4693
|
"data-logo-part": "mark",
|
|
@@ -3986,7 +4701,7 @@ function AnimatedBrand({
|
|
|
3986
4701
|
marginRight: tail ? ".04em" : 0
|
|
3987
4702
|
},
|
|
3988
4703
|
children: [
|
|
3989
|
-
/* @__PURE__ */
|
|
4704
|
+
/* @__PURE__ */ jsx54(
|
|
3990
4705
|
"span",
|
|
3991
4706
|
{
|
|
3992
4707
|
"data-logo-part": "ring",
|
|
@@ -3998,7 +4713,7 @@ function AnimatedBrand({
|
|
|
3998
4713
|
}
|
|
3999
4714
|
}
|
|
4000
4715
|
),
|
|
4001
|
-
/* @__PURE__ */
|
|
4716
|
+
/* @__PURE__ */ jsx54(
|
|
4002
4717
|
"span",
|
|
4003
4718
|
{
|
|
4004
4719
|
"data-logo-part": "core",
|
|
@@ -4011,7 +4726,7 @@ function AnimatedBrand({
|
|
|
4011
4726
|
}
|
|
4012
4727
|
}
|
|
4013
4728
|
),
|
|
4014
|
-
/* @__PURE__ */
|
|
4729
|
+
/* @__PURE__ */ jsx54(
|
|
4015
4730
|
"span",
|
|
4016
4731
|
{
|
|
4017
4732
|
"data-logo-part": "trail",
|
|
@@ -4029,7 +4744,7 @@ function AnimatedBrand({
|
|
|
4029
4744
|
}
|
|
4030
4745
|
}
|
|
4031
4746
|
),
|
|
4032
|
-
[0, 1].map((id) => /* @__PURE__ */
|
|
4747
|
+
[0, 1].map((id) => /* @__PURE__ */ jsx54(
|
|
4033
4748
|
"span",
|
|
4034
4749
|
{
|
|
4035
4750
|
"data-logo-part": "echo",
|
|
@@ -4042,7 +4757,7 @@ function AnimatedBrand({
|
|
|
4042
4757
|
},
|
|
4043
4758
|
id
|
|
4044
4759
|
)),
|
|
4045
|
-
Array.from({ length: 8 }, (_, id) => /* @__PURE__ */
|
|
4760
|
+
Array.from({ length: 8 }, (_, id) => /* @__PURE__ */ jsx54(
|
|
4046
4761
|
"span",
|
|
4047
4762
|
{
|
|
4048
4763
|
"data-logo-part": "particle",
|
|
@@ -4057,7 +4772,7 @@ function AnimatedBrand({
|
|
|
4057
4772
|
},
|
|
4058
4773
|
id
|
|
4059
4774
|
)),
|
|
4060
|
-
/* @__PURE__ */
|
|
4775
|
+
/* @__PURE__ */ jsx54(
|
|
4061
4776
|
"span",
|
|
4062
4777
|
{
|
|
4063
4778
|
"data-logo-part": "bead",
|
|
@@ -4067,7 +4782,7 @@ function AnimatedBrand({
|
|
|
4067
4782
|
]
|
|
4068
4783
|
}
|
|
4069
4784
|
),
|
|
4070
|
-
/* @__PURE__ */
|
|
4785
|
+
/* @__PURE__ */ jsxs35(
|
|
4071
4786
|
"span",
|
|
4072
4787
|
{
|
|
4073
4788
|
"data-logo-part": "tail",
|
|
@@ -4078,7 +4793,7 @@ function AnimatedBrand({
|
|
|
4078
4793
|
whiteSpace: "pre"
|
|
4079
4794
|
},
|
|
4080
4795
|
children: [
|
|
4081
|
-
letters.map((letter, index) => /* @__PURE__ */
|
|
4796
|
+
letters.map((letter, index) => /* @__PURE__ */ jsx54(
|
|
4082
4797
|
"span",
|
|
4083
4798
|
{
|
|
4084
4799
|
"data-brand-letter": "",
|
|
@@ -4087,7 +4802,7 @@ function AnimatedBrand({
|
|
|
4087
4802
|
},
|
|
4088
4803
|
`${index}-${letter}`
|
|
4089
4804
|
)),
|
|
4090
|
-
/* @__PURE__ */
|
|
4805
|
+
/* @__PURE__ */ jsx54(
|
|
4091
4806
|
"span",
|
|
4092
4807
|
{
|
|
4093
4808
|
"data-brand-baseline": "",
|
|
@@ -4127,6 +4842,7 @@ export {
|
|
|
4127
4842
|
Checkbox,
|
|
4128
4843
|
Combobox,
|
|
4129
4844
|
ConfirmDialog,
|
|
4845
|
+
DateInput,
|
|
4130
4846
|
Dialog,
|
|
4131
4847
|
DialogActions,
|
|
4132
4848
|
DialogBody,
|
|
@@ -4152,7 +4868,9 @@ export {
|
|
|
4152
4868
|
DropdownMenuSubContent,
|
|
4153
4869
|
DropdownMenuSubTrigger,
|
|
4154
4870
|
DropdownMenuTrigger,
|
|
4871
|
+
EmptyState,
|
|
4155
4872
|
ErrorState,
|
|
4873
|
+
FilteredEmptyState,
|
|
4156
4874
|
FormField,
|
|
4157
4875
|
FormModal,
|
|
4158
4876
|
InlineError,
|
|
@@ -4162,6 +4880,7 @@ export {
|
|
|
4162
4880
|
LoadingOverlay,
|
|
4163
4881
|
LoadingSpinner,
|
|
4164
4882
|
LoadingState,
|
|
4883
|
+
MAX_TOASTS,
|
|
4165
4884
|
Modal,
|
|
4166
4885
|
NavGroup,
|
|
4167
4886
|
NavItem,
|
|
@@ -4215,6 +4934,7 @@ export {
|
|
|
4215
4934
|
TabsTrigger,
|
|
4216
4935
|
TagCombobox,
|
|
4217
4936
|
Textarea,
|
|
4937
|
+
Toaster,
|
|
4218
4938
|
Tooltip,
|
|
4219
4939
|
TooltipContent,
|
|
4220
4940
|
TooltipProvider,
|
|
@@ -4224,13 +4944,23 @@ export {
|
|
|
4224
4944
|
badgeVariants,
|
|
4225
4945
|
buttonVariants,
|
|
4226
4946
|
cn,
|
|
4947
|
+
datePlaceholder,
|
|
4948
|
+
defaultDateInputLabels,
|
|
4227
4949
|
defaultErrorStateLabels,
|
|
4950
|
+
defaultFilteredEmptyStateLabels,
|
|
4951
|
+
defaultToasterLabels,
|
|
4228
4952
|
describeSpeechError,
|
|
4953
|
+
formatIsoDay,
|
|
4229
4954
|
getConfirmButtonPlacement,
|
|
4230
4955
|
isWindowsPlatform,
|
|
4231
4956
|
loadingSpinnerIconVariants,
|
|
4957
|
+
parseIsoDay,
|
|
4958
|
+
resetToasts,
|
|
4232
4959
|
sheetVariants,
|
|
4960
|
+
shiftIsoDay,
|
|
4233
4961
|
toErrorInfo,
|
|
4962
|
+
toLocalIsoDay,
|
|
4963
|
+
toast,
|
|
4234
4964
|
useDelayedFlag,
|
|
4235
4965
|
useMediaQuery,
|
|
4236
4966
|
useSidebarCollapsed,
|