beez-ui 2.5.0 → 2.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/THIRD_PARTY_NOTICES.md +1 -1
  3. package/dist/components/alert-dialog.d.ts +15 -4
  4. package/dist/components/alert-dialog.js +84 -44
  5. package/dist/components/alert.d.ts +30 -9
  6. package/dist/components/alert.js +360 -39
  7. package/dist/components/avatar.d.ts +33 -10
  8. package/dist/components/avatar.js +110 -30
  9. package/dist/components/badge.d.ts +39 -7
  10. package/dist/components/badge.js +348 -24
  11. package/dist/components/calendar.d.ts +29 -2
  12. package/dist/components/calendar.js +1035 -223
  13. package/dist/components/card.d.ts +17 -1
  14. package/dist/components/card.js +34 -8
  15. package/dist/components/carousel.d.ts +29 -2
  16. package/dist/components/carousel.js +471 -90
  17. package/dist/components/checkbox.d.ts +13 -2
  18. package/dist/components/checkbox.js +301 -41
  19. package/dist/components/dialog-surface.d.ts +27 -0
  20. package/dist/components/dialog-surface.js +137 -0
  21. package/dist/components/dialog.d.ts +21 -4
  22. package/dist/components/dialog.js +163 -96
  23. package/dist/components/dropdown-menu.d.ts +30 -16
  24. package/dist/components/dropdown-menu.js +139 -83
  25. package/dist/components/hover-card.d.ts +46 -3
  26. package/dist/components/hover-card.js +423 -60
  27. package/dist/components/pagination.d.ts +32 -14
  28. package/dist/components/pagination.js +136 -59
  29. package/dist/components/popover.d.ts +14 -5
  30. package/dist/components/popover.js +78 -36
  31. package/dist/components/radio-group.d.ts +19 -3
  32. package/dist/components/radio-group.js +400 -57
  33. package/dist/components/select.d.ts +17 -6
  34. package/dist/components/select.js +83 -71
  35. package/dist/components/sheet.js +37 -26
  36. package/dist/components/sidebar.js +11 -0
  37. package/dist/components/skeleton.d.ts +19 -5
  38. package/dist/components/skeleton.js +434 -14
  39. package/dist/components/switch.d.ts +14 -4
  40. package/dist/components/switch.js +424 -40
  41. package/dist/components/tabs.d.ts +38 -5
  42. package/dist/components/tabs.js +564 -97
  43. package/dist/components/themed-toaster.d.ts +6 -2
  44. package/dist/components/themed-toaster.js +80 -50
  45. package/dist/components/tooltip.d.ts +33 -2
  46. package/dist/components/tooltip.js +197 -69
  47. package/dist/constants/alert.d.ts +12 -0
  48. package/dist/constants/alert.js +9 -0
  49. package/dist/constants/avatar.d.ts +10 -0
  50. package/dist/constants/avatar.js +7 -0
  51. package/dist/constants/badge.d.ts +6 -0
  52. package/dist/constants/badge.js +6 -0
  53. package/dist/constants/calendar.d.ts +24 -0
  54. package/dist/constants/calendar.js +22 -0
  55. package/dist/constants/carousel.d.ts +37 -0
  56. package/dist/constants/carousel.js +53 -0
  57. package/dist/constants/checkbox.d.ts +17 -0
  58. package/dist/constants/checkbox.js +17 -0
  59. package/dist/constants/dialog.d.ts +6 -0
  60. package/dist/constants/dialog.js +6 -0
  61. package/dist/constants/dropdown-menu.d.ts +5 -0
  62. package/dist/constants/dropdown-menu.js +5 -0
  63. package/dist/constants/hover-card.d.ts +37 -0
  64. package/dist/constants/hover-card.js +85 -0
  65. package/dist/constants/pagination.d.ts +9 -0
  66. package/dist/constants/pagination.js +9 -0
  67. package/dist/constants/popover.d.ts +7 -0
  68. package/dist/constants/popover.js +39 -0
  69. package/dist/constants/radio-group.d.ts +10 -0
  70. package/dist/constants/radio-group.js +10 -0
  71. package/dist/constants/select.d.ts +3 -0
  72. package/dist/constants/select.js +3 -0
  73. package/dist/constants/skeleton.d.ts +17 -0
  74. package/dist/constants/skeleton.js +17 -0
  75. package/dist/constants/switch.d.ts +44 -0
  76. package/dist/constants/switch.js +49 -0
  77. package/dist/constants/tabs.d.ts +17 -0
  78. package/dist/constants/tabs.js +17 -0
  79. package/dist/constants/toast.d.ts +3 -0
  80. package/dist/constants/toast.js +3 -0
  81. package/dist/constants/tooltip.d.ts +13 -0
  82. package/dist/constants/tooltip.js +52 -0
  83. package/dist/lib/toast-layer.d.ts +24 -0
  84. package/dist/lib/toast-layer.js +76 -0
  85. package/dist/motion/arc-floating-slot.d.ts +40 -0
  86. package/dist/motion/arc-floating-slot.js +167 -0
  87. package/dist/motion/glide-indicator.d.ts +6 -7
  88. package/dist/motion/glide-indicator.js +5 -3
  89. package/dist/motion/overlay-warmth.d.ts +24 -0
  90. package/dist/motion/overlay-warmth.js +70 -0
  91. package/dist/styles.css +1 -1
  92. package/package.json +1 -1
@@ -1,55 +1,134 @@
1
1
  "use client";
2
2
  import { c as _c } from "react/compiler-runtime";
3
- import * as React from "react";
4
3
  import { Avatar as AvatarPrimitive } from "@base-ui/react/avatar";
5
- import { MotionSlot } from "../motion/motion-slot.js";
4
+ import { AnimatePresence, motion } from "motion/react";
5
+ import { AVATAR_STATUS_HIDDEN_SCALE, AVATAR_STATUS_LABEL } from "../constants/avatar.js";
6
+ import { usePrefersReducedMotion } from "../hooks/use-prefers-reduced-motion.js";
6
7
  import { cn } from "../lib/utils.js";
8
+ import { ARC_DURATION, ARC_SPRING_SNAPPY } from "../motion/arc-tokens.js";
9
+ import { MotionSlot } from "../motion/motion-slot.js";
7
10
  import { useBeezUIComponents } from "../providers/beez-ui-provider.js";
8
- import { jsx as _jsx } from "react/jsx-runtime";
11
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
12
+ /** The presence ring: a surface-coloured gap plus a faint hairline, so the dot reads on photos and fills alike. */
13
+ const presenceRingClassName = "shadow-[0_0_0_2px_var(--surface),0_0_0_3px_color-mix(in_oklab,var(--border)_70%,transparent)]";
14
+ /**
15
+ * A person or account, as a photo with initials as fallback.
16
+ * @param props - Size, optional presence and the Base UI avatar root props.
17
+ * @returns The avatar root.
18
+ */
9
19
  function Avatar(t0) {
10
- const $ = _c(10);
20
+ const $ = _c(24);
21
+ let children;
11
22
  let className;
12
23
  let props;
24
+ let status;
25
+ let statusLabel;
13
26
  let t1;
14
27
  if ($[0] !== t0) {
15
- ({className, size: t1, ...props} = t0);
28
+ ({className, size: t1, status, statusLabel, children, ...props} = t0);
16
29
  $[0] = t0;
17
- $[1] = className;
18
- $[2] = props;
19
- $[3] = t1;
30
+ $[1] = children;
31
+ $[2] = className;
32
+ $[3] = props;
33
+ $[4] = status;
34
+ $[5] = statusLabel;
35
+ $[6] = t1;
20
36
  } else {
21
- className = $[1];
22
- props = $[2];
23
- t1 = $[3];
37
+ children = $[1];
38
+ className = $[2];
39
+ props = $[3];
40
+ status = $[4];
41
+ statusLabel = $[5];
42
+ t1 = $[6];
24
43
  }
25
44
  const size = t1 === undefined ? "default" : t1;
45
+ const reduceMotion = usePrefersReducedMotion();
26
46
  let t2;
27
- if ($[4] !== className) {
28
- t2 = cn("group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten", className);
29
- $[4] = className;
30
- $[5] = t2;
47
+ if ($[7] !== className) {
48
+ t2 = cn("group/avatar relative inline-grid size-8 shrink-0 place-items-center rounded-(--radius-pill) border border-border bg-surface-muted text-xs font-medium text-foreground select-none data-[size=lg]:size-10 data-[size=lg]:text-sm data-[size=sm]:size-6 data-[size=sm]:text-[10px] data-[size=xl]:size-22 data-[size=xl]:text-xl", className);
49
+ $[7] = className;
50
+ $[8] = t2;
31
51
  } else {
32
- t2 = $[5];
52
+ t2 = $[8];
33
53
  }
34
54
  let t3;
35
- if ($[6] !== props || $[7] !== size || $[8] !== t2) {
36
- t3 = /* @__PURE__ */ _jsx(MotionSlot, {
55
+ if ($[9] !== status || $[10] !== statusLabel) {
56
+ t3 = status ? /* @__PURE__ */ _jsx("span", {
57
+ className: "sr-only",
58
+ children: statusLabel ?? AVATAR_STATUS_LABEL[status]
59
+ }) : null;
60
+ $[9] = status;
61
+ $[10] = statusLabel;
62
+ $[11] = t3;
63
+ } else {
64
+ t3 = $[11];
65
+ }
66
+ let t4;
67
+ if ($[12] !== reduceMotion || $[13] !== status) {
68
+ t4 = status ? /* @__PURE__ */ _jsx(motion.span, {
69
+ "data-slot": "avatar-status",
70
+ "data-status": status,
71
+ "aria-hidden": "true",
72
+ className: cn("absolute right-0 bottom-0 z-10 size-2.5 rounded-(--radius-pill) data-[status=offline]:bg-text-muted data-[status=online]:bg-success group-data-[size=lg]/avatar:size-3 group-data-[size=sm]/avatar:size-2 group-data-[size=xl]/avatar:right-1 group-data-[size=xl]/avatar:bottom-1 group-data-[size=xl]/avatar:size-3.5 group-has-data-[slot=avatar-badge]/avatar:top-0 group-has-data-[slot=avatar-badge]/avatar:bottom-auto group-data-[size=xl]/avatar:group-has-data-[slot=avatar-badge]/avatar:top-1", presenceRingClassName),
73
+ initial: {
74
+ opacity: 0,
75
+ scale: AVATAR_STATUS_HIDDEN_SCALE
76
+ },
77
+ animate: {
78
+ opacity: 1,
79
+ scale: 1
80
+ },
81
+ exit: {
82
+ opacity: 0,
83
+ scale: AVATAR_STATUS_HIDDEN_SCALE,
84
+ transition: { duration: reduceMotion ? 0 : ARC_DURATION.fast }
85
+ },
86
+ transition: reduceMotion ? { duration: 0 } : ARC_SPRING_SNAPPY
87
+ }, status) : null;
88
+ $[12] = reduceMotion;
89
+ $[13] = status;
90
+ $[14] = t4;
91
+ } else {
92
+ t4 = $[14];
93
+ }
94
+ let t5;
95
+ if ($[15] !== t4) {
96
+ t5 = /* @__PURE__ */ _jsx(AnimatePresence, {
97
+ initial: false,
98
+ children: t4
99
+ });
100
+ $[15] = t4;
101
+ $[16] = t5;
102
+ } else {
103
+ t5 = $[16];
104
+ }
105
+ let t6;
106
+ if ($[17] !== children || $[18] !== props || $[19] !== size || $[20] !== t2 || $[21] !== t3 || $[22] !== t5) {
107
+ t6 = /* @__PURE__ */ _jsx(MotionSlot, {
37
108
  kind: "fade",
38
- children: /* @__PURE__ */ _jsx(AvatarPrimitive.Root, {
109
+ children: /* @__PURE__ */ _jsxs(AvatarPrimitive.Root, {
39
110
  "data-slot": "avatar",
40
111
  "data-size": size,
41
112
  className: t2,
42
- ...props
113
+ ...props,
114
+ children: [
115
+ children,
116
+ t3,
117
+ t5
118
+ ]
43
119
  })
44
120
  });
45
- $[6] = props;
46
- $[7] = size;
47
- $[8] = t2;
48
- $[9] = t3;
121
+ $[17] = children;
122
+ $[18] = props;
123
+ $[19] = size;
124
+ $[20] = t2;
125
+ $[21] = t3;
126
+ $[22] = t5;
127
+ $[23] = t6;
49
128
  } else {
50
- t3 = $[9];
129
+ t6 = $[23];
51
130
  }
52
- return t3;
131
+ return t6;
53
132
  }
54
133
  /** Delegates loading, failure and fallback synchronization to the avatar primitive; loaded images develop in place. */
55
134
  function AvatarImage(t0) {
@@ -84,7 +163,7 @@ function AvatarImage(t0) {
84
163
  }
85
164
  let t4;
86
165
  if ($[7] !== className) {
87
- t4 = cn("absolute inset-0 aspect-square size-full rounded-full object-cover data-[loading]:opacity-0 data-[error]:hidden", className);
166
+ t4 = cn("pointer-events-none absolute inset-0 aspect-square size-full rounded-full object-cover data-[loading]:opacity-0 data-[error]:hidden", className);
88
167
  $[7] = className;
89
168
  $[8] = t4;
90
169
  } else {
@@ -133,7 +212,7 @@ function AvatarFallback(t0) {
133
212
  }
134
213
  let t1;
135
214
  if ($[3] !== className) {
136
- t1 = cn("flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs", className);
215
+ t1 = cn("flex size-full items-center justify-center rounded-full bg-surface-muted text-[length:inherit] font-medium text-foreground", className);
137
216
  $[3] = className;
138
217
  $[4] = t1;
139
218
  } else {
@@ -154,6 +233,7 @@ function AvatarFallback(t0) {
154
233
  }
155
234
  return t2;
156
235
  }
236
+ /** A custom corner badge, drawn with the same ring as Arc's presence dot. Prefer `status` for presence. */
157
237
  function AvatarBadge(t0) {
158
238
  const $ = _c(8);
159
239
  let className;
@@ -169,7 +249,7 @@ function AvatarBadge(t0) {
169
249
  }
170
250
  let t1;
171
251
  if ($[3] !== className) {
172
- t1 = cn("absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground bg-blend-color ring-2 ring-background select-none", "group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden", "group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2", "group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2", className);
252
+ t1 = cn("absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground bg-blend-color select-none", presenceRingClassName, "group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden", "group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2", "group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2", "group-data-[size=xl]/avatar:right-1 group-data-[size=xl]/avatar:bottom-1 group-data-[size=xl]/avatar:size-3.5 group-data-[size=xl]/avatar:[&>svg]:size-2.5", className);
173
253
  $[3] = className;
174
254
  $[4] = t1;
175
255
  } else {
@@ -242,7 +322,7 @@ function AvatarGroupCount(t0) {
242
322
  }
243
323
  let t1;
244
324
  if ($[3] !== className) {
245
- t1 = cn("relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-sm text-muted-foreground ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3", className);
325
+ t1 = cn("relative flex size-8 shrink-0 items-center justify-center rounded-full border border-border bg-surface-muted text-xs font-medium text-text-secondary ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 group-has-data-[size=xl]/avatar-group:size-22 group-has-data-[size=xl]/avatar-group:text-xl [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3 group-has-data-[size=xl]/avatar-group:[&>svg]:size-8", className);
246
326
  $[3] = className;
247
327
  $[4] = t1;
248
328
  } else {
@@ -1,9 +1,41 @@
1
- import * as React from "react";
2
- import { type VariantProps } from "class-variance-authority";
3
- declare const badgeVariants: (props?: ({
4
- variant?: "default" | "destructive" | "ghost" | "link" | "outline" | "secondary" | null | undefined;
5
- } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
- declare function Badge({ className, variant, asChild, ...props }: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & {
1
+ import type { ComponentProps, ReactNode } from "react";
2
+ /** shadcn-compatible visual variants, each drawn with one of Arc's tones. */
3
+ export type BadgeVariant = "default" | "secondary" | "destructive" | "outline" | "ghost" | "link";
4
+ /** Arc's semantic tones; a `tone` wins over the tone implied by `variant`. */
5
+ export type BadgeTone = "neutral" | "success" | "info" | "warning" | "danger";
6
+ /** Arc's badge heights: 26px (`md`) and 22px (`sm`). */
7
+ export type BadgeSize = "sm" | "md";
8
+ /** Options of `badgeVariants`, for styling links or other elements as badges. */
9
+ export type BadgeVariantsOptions = {
10
+ variant?: BadgeVariant | null;
11
+ tone?: BadgeTone | null;
12
+ size?: BadgeSize | null;
13
+ className?: string;
14
+ };
15
+ /**
16
+ * Arc's badge classes for any element. Without a `tone`, the tone implied by `variant` is used, as in `Badge`.
17
+ * @param options - Variant, tone, size and extra classes.
18
+ * @returns The class list.
19
+ */
20
+ declare function badgeVariants({ variant, tone, size, className }?: BadgeVariantsOptions): string;
21
+ export type BadgeProps = ComponentProps<"span"> & {
22
+ /** shadcn-compatible variant, drawn with an Arc tone: default (info), secondary, outline and ghost (neutral),
23
+ * destructive (danger) and link (info, underlined on hover). */
24
+ variant?: BadgeVariant | null;
25
+ /** Arc's semantic tone; overrides the tone implied by `variant`. */
26
+ tone?: BadgeTone;
27
+ /** Arc's height: `md` (26px, default) or `sm` (22px). */
28
+ size?: BadgeSize;
29
+ /** A leading icon tinted with the tone, hidden from assistive technology. */
30
+ icon?: ReactNode;
31
+ /** Renders the child element instead of a span, merging the badge props into it. Text and icon swaps are off. */
7
32
  asChild?: boolean;
8
- }): React.JSX.Element;
33
+ };
34
+ /**
35
+ * A small label for status, category or metadata. Text children swap in place with Arc's motion and the pill springs
36
+ * to the new width; other children render as they are.
37
+ * @param props - Variant, tone, size, optional icon and native span attributes.
38
+ * @returns The badge.
39
+ */
40
+ declare function Badge({ className, variant, tone, size, icon, asChild, children, ...props }: BadgeProps): import("react").JSX.Element;
9
41
  export { Badge, badgeVariants };
@@ -1,30 +1,354 @@
1
- import * as React from "react";
1
+ "use client";
2
+ import { c as _c } from "react/compiler-runtime";
3
+ /**
4
+ * Arc's Badge (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md): a small pill for status, category or
5
+ * metadata on Arc's tones and tokens. A new text label rises in while the pill springs to its new width, and a new
6
+ * icon crossfades in place. The shadcn variants are kept and mapped onto Arc's tones.
7
+ */
8
+ import { isValidElement, useRef } from "react";
2
9
  import { cva } from "class-variance-authority";
10
+ import { AnimatePresence, motion, useIsPresent } from "motion/react";
3
11
  import { Slot } from "radix-ui";
4
- import { MotionSlot } from "../motion/motion-slot.js";
12
+ import { BADGE_LABEL_OFFSET_EM } from "../constants/badge.js";
13
+ import { usePrefersReducedMotion } from "../hooks/use-prefers-reduced-motion.js";
5
14
  import { cn } from "../lib/utils.js";
6
- import { jsx as _jsx } from "react/jsx-runtime";
7
- const badgeVariants = cva("group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!", {
8
- variants: { variant: {
9
- default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
10
- secondary: "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
11
- destructive: "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
12
- outline: "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
13
- ghost: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
14
- link: "text-primary underline-offset-4 hover:underline"
15
- } },
16
- defaultVariants: { variant: "default" }
15
+ import { ARC_BLUR, ARC_DURATION, ARC_EASE } from "../motion/arc-tokens.js";
16
+ import { ARC_ICON_ENTER, ARC_ICON_EXIT, ARC_ICON_TRANSITION, ARC_REDUCED_EXIT, ARC_REDUCED_TRANSITION, ARC_SWAP_EXIT_TRANSITION, ARC_SWAP_REST } from "../motion/arc-swap.js";
17
+ import { MotionSlot } from "../motion/motion-slot.js";
18
+ import { useMorphWidth } from "../motion/use-morph-width.js";
19
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
20
+ /** The Arc tone each shadcn variant is drawn with when no explicit `tone` is passed. */
21
+ const VARIANT_TONE = {
22
+ default: "info",
23
+ secondary: "neutral",
24
+ destructive: "danger",
25
+ outline: "neutral",
26
+ ghost: "neutral",
27
+ link: "info"
28
+ };
29
+ /**
30
+ * Arc's badge recipe. Each tone sets the pill's colour roles as custom properties, so hover can mix the tone into the
31
+ * border and fill; variants only adjust the fill and border afterwards. Hover answers on fine pointers only.
32
+ */
33
+ const badgeRecipe = cva("group/badge inline-flex w-fit shrink-0 items-center justify-center overflow-clip rounded-(--radius-pill) border border-(--badge-border) bg-(--badge-background) leading-none font-medium tracking-[-.01em] whitespace-nowrap text-(--badge-foreground) transition-[border-color,background-color,color] duration-(--duration-standard) ease-(--ease-standard) motion-reduce:duration-(--duration-instant) hover-fine:border-[color-mix(in_oklab,var(--badge-color)_32%,var(--border))] hover-fine:bg-[color-mix(in_oklab,var(--badge-color)_10%,var(--surface))] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-danger [&>svg]:pointer-events-none [&>svg]:size-3! [&>svg]:text-(--badge-color)", {
34
+ variants: {
35
+ tone: {
36
+ neutral: "[--badge-background:var(--surface-muted)] [--badge-border:var(--border)] [--badge-color:var(--text-secondary)] [--badge-foreground:var(--text-secondary)]",
37
+ success: "[--badge-background:color-mix(in_oklab,var(--success)_10%,var(--surface))] [--badge-border:color-mix(in_oklab,var(--success)_25%,var(--border))] [--badge-color:var(--success)] [--badge-foreground:var(--success)]",
38
+ info: "[--badge-background:var(--accent-subtle)] [--badge-border:color-mix(in_oklab,var(--accent)_24%,var(--border))] [--badge-color:var(--accent)] [--badge-foreground:var(--accent-strong)]",
39
+ warning: "[--badge-background:color-mix(in_oklab,var(--warning)_11%,var(--surface))] [--badge-border:color-mix(in_oklab,var(--warning)_27%,var(--border))] [--badge-color:var(--warning)] [--badge-foreground:var(--warning)]",
40
+ danger: "[--badge-background:color-mix(in_oklab,var(--danger)_10%,var(--surface))] [--badge-border:color-mix(in_oklab,var(--danger)_26%,var(--border))] [--badge-color:var(--danger)] [--badge-foreground:var(--danger)]"
41
+ },
42
+ variant: {
43
+ default: "",
44
+ secondary: "",
45
+ destructive: "",
46
+ outline: "[--badge-background:var(--surface)] [--badge-foreground:var(--foreground)]",
47
+ ghost: "[--badge-background:transparent] [--badge-border:transparent]",
48
+ link: "[--badge-background:transparent] [--badge-border:transparent] underline-offset-4 hover-fine:border-transparent hover-fine:bg-transparent hover-fine:underline"
49
+ },
50
+ size: {
51
+ sm: "min-h-[22px] gap-1 px-2 text-[11px]",
52
+ md: "min-h-[26px] gap-[5px] px-2.5 text-xs"
53
+ }
54
+ },
55
+ defaultVariants: {
56
+ variant: "default",
57
+ size: "md"
58
+ }
17
59
  });
18
- function Badge({ className, variant = "default", asChild = false, ...props }) {
19
- const Comp = asChild ? Slot.Root : "span";
20
- return /* @__PURE__ */ _jsx(MotionSlot, {
21
- kind: "fade",
22
- children: /* @__PURE__ */ _jsx(Comp, {
23
- "data-slot": "badge",
24
- "data-variant": variant,
25
- className: cn(badgeVariants({ variant }), className),
26
- ...props
27
- })
28
- });
60
+ /**
61
+ * Arc's badge classes for any element. Without a `tone`, the tone implied by `variant` is used, as in `Badge`.
62
+ * @param options - Variant, tone, size and extra classes.
63
+ * @returns The class list.
64
+ */
65
+ function badgeVariants({ variant, tone, size, className } = {}) {
66
+ return cn(badgeRecipe({
67
+ tone: tone ?? VARIANT_TONE[variant ?? "default"],
68
+ variant,
69
+ size
70
+ }), className);
71
+ }
72
+ /** A new label rises out of a soft blur; the old one lifts away faster. */
73
+ const labelEnter = {
74
+ opacity: 0,
75
+ y: `${BADGE_LABEL_OFFSET_EM.enter}em`,
76
+ filter: `blur(${ARC_BLUR.soft}px)`
77
+ };
78
+ const labelExit = {
79
+ opacity: 0,
80
+ y: `${BADGE_LABEL_OFFSET_EM.exit}em`,
81
+ filter: `blur(${ARC_BLUR.subtle}px)`,
82
+ transition: ARC_SWAP_EXIT_TRANSITION
83
+ };
84
+ const labelTransition = {
85
+ duration: ARC_DURATION.standard,
86
+ ease: [...ARC_EASE.enter]
87
+ };
88
+ const reducedEnter = { opacity: 0 };
89
+ /** Outgoing copies are hidden from assistive technology while they fade, so only the current one is read. */
90
+ function BadgeSwap(props) {
91
+ const $ = _c(3);
92
+ const isPresent = useIsPresent();
93
+ const t0 = isPresent ? props["aria-hidden"] : true;
94
+ let t1;
95
+ if ($[0] !== props || $[1] !== t0) {
96
+ t1 = /* @__PURE__ */ _jsx(motion.span, {
97
+ ...props,
98
+ "aria-hidden": t0
99
+ });
100
+ $[0] = props;
101
+ $[1] = t0;
102
+ $[2] = t1;
103
+ } else {
104
+ t1 = $[2];
105
+ }
106
+ return t1;
107
+ }
108
+ /** Keys an icon by its component, so a new icon crossfades in while re-rendering the same icon stays still. */
109
+ function getIconKey(icon) {
110
+ if (!isValidElement(icon)) return "icon";
111
+ const iconType = icon.type;
112
+ return typeof iconType === "string" ? iconType : iconType.displayName ?? iconType.name ?? "icon";
113
+ }
114
+ /** Arc's swapping content: the icon and text change in place while the pill springs to the new width. */
115
+ function BadgeContent(t0) {
116
+ const $ = _c(19);
117
+ const { icon, label, reduceMotion } = t0;
118
+ const contentRef = useRef(null);
119
+ let t1;
120
+ if ($[0] !== icon) {
121
+ t1 = icon ? getIconKey(icon) : "";
122
+ $[0] = icon;
123
+ $[1] = t1;
124
+ } else {
125
+ t1 = $[1];
126
+ }
127
+ const iconKey = t1;
128
+ const width = useMorphWidth(contentRef, `${iconKey}\n${label}`, reduceMotion);
129
+ let t2;
130
+ if ($[2] !== width) {
131
+ t2 = { width };
132
+ $[2] = width;
133
+ $[3] = t2;
134
+ } else {
135
+ t2 = $[3];
136
+ }
137
+ let t3;
138
+ if ($[4] !== icon || $[5] !== iconKey || $[6] !== reduceMotion) {
139
+ t3 = icon ? /* @__PURE__ */ _jsx(BadgeIcon, {
140
+ icon,
141
+ iconKey,
142
+ reduceMotion
143
+ }) : null;
144
+ $[4] = icon;
145
+ $[5] = iconKey;
146
+ $[6] = reduceMotion;
147
+ $[7] = t3;
148
+ } else {
149
+ t3 = $[7];
150
+ }
151
+ const t4 = reduceMotion ? reducedEnter : labelEnter;
152
+ const t5 = reduceMotion ? ARC_REDUCED_EXIT : labelExit;
153
+ const t6 = reduceMotion ? ARC_REDUCED_TRANSITION : labelTransition;
154
+ let t7;
155
+ if ($[8] !== label || $[9] !== t4 || $[10] !== t5 || $[11] !== t6) {
156
+ t7 = /* @__PURE__ */ _jsx("span", {
157
+ className: "relative inline-flex items-center",
158
+ children: /* @__PURE__ */ _jsx(AnimatePresence, {
159
+ mode: "popLayout",
160
+ initial: false,
161
+ children: /* @__PURE__ */ _jsx(BadgeSwap, {
162
+ className: "block",
163
+ initial: t4,
164
+ animate: ARC_SWAP_REST,
165
+ exit: t5,
166
+ transition: t6,
167
+ children: label
168
+ }, label)
169
+ })
170
+ });
171
+ $[8] = label;
172
+ $[9] = t4;
173
+ $[10] = t5;
174
+ $[11] = t6;
175
+ $[12] = t7;
176
+ } else {
177
+ t7 = $[12];
178
+ }
179
+ let t8;
180
+ if ($[13] !== t3 || $[14] !== t7) {
181
+ t8 = /* @__PURE__ */ _jsxs("span", {
182
+ ref: contentRef,
183
+ className: "relative inline-flex w-max items-center gap-[inherit]",
184
+ children: [t3, t7]
185
+ });
186
+ $[13] = t3;
187
+ $[14] = t7;
188
+ $[15] = t8;
189
+ } else {
190
+ t8 = $[15];
191
+ }
192
+ let t9;
193
+ if ($[16] !== t2 || $[17] !== t8) {
194
+ t9 = /* @__PURE__ */ _jsx(motion.span, {
195
+ "data-slot": "badge-content",
196
+ className: "block gap-[inherit] data-morphing:overflow-clip",
197
+ style: t2,
198
+ children: t8
199
+ });
200
+ $[16] = t2;
201
+ $[17] = t8;
202
+ $[18] = t9;
203
+ } else {
204
+ t9 = $[18];
205
+ }
206
+ return t9;
207
+ }
208
+ /** The leading icon, tinted with the tone; a different icon component crossfades in. */
209
+ function BadgeIcon(t0) {
210
+ const $ = _c(6);
211
+ const { icon, iconKey, reduceMotion } = t0;
212
+ const t1 = reduceMotion ? reducedEnter : ARC_ICON_ENTER;
213
+ const t2 = reduceMotion ? ARC_REDUCED_EXIT : ARC_ICON_EXIT;
214
+ const t3 = reduceMotion ? ARC_REDUCED_TRANSITION : ARC_ICON_TRANSITION;
215
+ let t4;
216
+ if ($[0] !== icon || $[1] !== iconKey || $[2] !== t1 || $[3] !== t2 || $[4] !== t3) {
217
+ t4 = /* @__PURE__ */ _jsx("span", {
218
+ "data-slot": "badge-icon",
219
+ "aria-hidden": "true",
220
+ className: "relative inline-flex flex-none items-center justify-center leading-none text-(--badge-color) [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-3",
221
+ children: /* @__PURE__ */ _jsx(AnimatePresence, {
222
+ mode: "popLayout",
223
+ initial: false,
224
+ children: /* @__PURE__ */ _jsx(BadgeSwap, {
225
+ className: "relative inline-flex items-center",
226
+ initial: t1,
227
+ animate: ARC_SWAP_REST,
228
+ exit: t2,
229
+ transition: t3,
230
+ children: icon
231
+ }, iconKey)
232
+ })
233
+ });
234
+ $[0] = icon;
235
+ $[1] = iconKey;
236
+ $[2] = t1;
237
+ $[3] = t2;
238
+ $[4] = t3;
239
+ $[5] = t4;
240
+ } else {
241
+ t4 = $[5];
242
+ }
243
+ return t4;
244
+ }
245
+ /**
246
+ * A small label for status, category or metadata. Text children swap in place with Arc's motion and the pill springs
247
+ * to the new width; other children render as they are.
248
+ * @param props - Variant, tone, size, optional icon and native span attributes.
249
+ * @returns The badge.
250
+ */
251
+ function Badge(t0) {
252
+ const $ = _c(28);
253
+ let children;
254
+ let className;
255
+ let icon;
256
+ let props;
257
+ let t1;
258
+ let t2;
259
+ let t3;
260
+ let tone;
261
+ if ($[0] !== t0) {
262
+ ({className, variant: t1, tone, size: t2, icon, asChild: t3, children, ...props} = t0);
263
+ $[0] = t0;
264
+ $[1] = children;
265
+ $[2] = className;
266
+ $[3] = icon;
267
+ $[4] = props;
268
+ $[5] = t1;
269
+ $[6] = t2;
270
+ $[7] = t3;
271
+ $[8] = tone;
272
+ } else {
273
+ children = $[1];
274
+ className = $[2];
275
+ icon = $[3];
276
+ props = $[4];
277
+ t1 = $[5];
278
+ t2 = $[6];
279
+ t3 = $[7];
280
+ tone = $[8];
281
+ }
282
+ const variant = t1 === undefined ? "default" : t1;
283
+ const size = t2 === undefined ? "md" : t2;
284
+ const asChild = t3 === undefined ? false : t3;
285
+ const reduceMotion = usePrefersReducedMotion();
286
+ const resolvedVariant = variant ?? "default";
287
+ const resolvedTone = tone ?? VARIANT_TONE[resolvedVariant];
288
+ const label = typeof children === "string" || typeof children === "number" ? String(children) : null;
289
+ const Component = asChild ? Slot.Root : "span";
290
+ let t4;
291
+ if ($[9] !== asChild || $[10] !== children || $[11] !== icon || $[12] !== label || $[13] !== reduceMotion) {
292
+ t4 = asChild ? children : label === null ? /* @__PURE__ */ _jsxs(_Fragment, { children: [icon ? /* @__PURE__ */ _jsx(BadgeIcon, {
293
+ icon,
294
+ iconKey: getIconKey(icon),
295
+ reduceMotion
296
+ }) : null, children] }) : /* @__PURE__ */ _jsx(BadgeContent, {
297
+ icon,
298
+ label,
299
+ reduceMotion
300
+ });
301
+ $[9] = asChild;
302
+ $[10] = children;
303
+ $[11] = icon;
304
+ $[12] = label;
305
+ $[13] = reduceMotion;
306
+ $[14] = t4;
307
+ } else {
308
+ t4 = $[14];
309
+ }
310
+ const content = t4;
311
+ let t5;
312
+ if ($[15] !== className || $[16] !== resolvedTone || $[17] !== resolvedVariant || $[18] !== size) {
313
+ t5 = badgeVariants({
314
+ tone: resolvedTone,
315
+ variant: resolvedVariant,
316
+ size,
317
+ className
318
+ });
319
+ $[15] = className;
320
+ $[16] = resolvedTone;
321
+ $[17] = resolvedVariant;
322
+ $[18] = size;
323
+ $[19] = t5;
324
+ } else {
325
+ t5 = $[19];
326
+ }
327
+ let t6;
328
+ if ($[20] !== Component || $[21] !== content || $[22] !== props || $[23] !== resolvedTone || $[24] !== resolvedVariant || $[25] !== size || $[26] !== t5) {
329
+ t6 = /* @__PURE__ */ _jsx(MotionSlot, {
330
+ kind: "fade",
331
+ children: /* @__PURE__ */ _jsx(Component, {
332
+ "data-slot": "badge",
333
+ "data-variant": resolvedVariant,
334
+ "data-tone": resolvedTone,
335
+ "data-size": size,
336
+ className: t5,
337
+ ...props,
338
+ children: content
339
+ })
340
+ });
341
+ $[20] = Component;
342
+ $[21] = content;
343
+ $[22] = props;
344
+ $[23] = resolvedTone;
345
+ $[24] = resolvedVariant;
346
+ $[25] = size;
347
+ $[26] = t5;
348
+ $[27] = t6;
349
+ } else {
350
+ t6 = $[27];
351
+ }
352
+ return t6;
29
353
  }
30
354
  export { Badge, badgeVariants };
@@ -1,10 +1,37 @@
1
+ /**
2
+ * Arc's Calendar (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md) on react-day-picker: round day cells
3
+ * on a 4px grid, the month title on the left with quiet pill controls on the right, today marked by a dot under its
4
+ * number, a selected disc that glides between days and an optional Today button. react-day-picker keeps selection
5
+ * modes, ranges, dropdowns, locales and keyboard navigation; only the design and the motion come from Arc.
6
+ */
1
7
  import * as React from "react";
2
8
  import { DayPicker, type DayButton, type Locale } from "react-day-picker";
3
9
  import { ControlButton } from "./control-button.js";
4
- declare function Calendar({ className, classNames, showOutsideDays, captionLayout, buttonVariant, locale, formatters, components, ...props }: React.ComponentProps<typeof DayPicker> & {
10
+ type CalendarProps = React.ComponentProps<typeof DayPicker> & {
11
+ /** Variant of the month navigation buttons, kept for compatibility; Arc's look is the default `ghost`. */
5
12
  buttonVariant?: React.ComponentProps<typeof ControlButton>["variant"];
6
- }): React.JSX.Element;
13
+ /**
14
+ * Adds Arc's Today button before the month controls: it goes back to the month holding today and, in single
15
+ * selection mode, selects today when it is available. It rests dimmed while there is nothing left to do.
16
+ */
17
+ showToday?: boolean;
18
+ /** Copy of the Today button. Defaults to "Hoy". */
19
+ todayLabel?: string;
20
+ };
21
+ /**
22
+ * A month grid for picking a day, several days or a range, controlled or uncontrolled like react-day-picker.
23
+ * @param props - Every react-day-picker prop plus the Arc additions `showToday` and `todayLabel`.
24
+ * @returns The calendar, in Spanish by default.
25
+ */
26
+ declare function Calendar({ className, classNames, showOutsideDays, captionLayout, buttonVariant, locale, formatters, components, showToday, todayLabel, ...props }: CalendarProps): React.JSX.Element;
27
+ /**
28
+ * One day of the grid: a round cell whose fill answers hover on fine pointers, presses in slightly and marks today
29
+ * with a dot under its number that takes the number's colour.
30
+ * @param props - react-day-picker day button properties plus the locale used for `data-day`.
31
+ * @returns The day button.
32
+ */
7
33
  declare function CalendarDayButton({ className, day, modifiers, locale, ...props }: React.ComponentProps<typeof DayButton> & {
8
34
  locale?: Partial<Locale>;
9
35
  }): React.JSX.Element;
10
36
  export { Calendar, CalendarDayButton };
37
+ export type { CalendarProps };