beez-ui 2.7.1 → 3.0.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.
Files changed (110) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/README.md +43 -13
  3. package/THIRD_PARTY_NOTICES.md +1 -1
  4. package/dist/components/account-menu.d.ts +4 -3
  5. package/dist/components/account-menu.js +63 -54
  6. package/dist/components/alert.d.ts +15 -15
  7. package/dist/components/alert.js +289 -270
  8. package/dist/components/animated-theme-toggler.js +1 -1
  9. package/dist/components/avatar.d.ts +56 -31
  10. package/dist/components/avatar.js +394 -277
  11. package/dist/components/badge.d.ts +8 -28
  12. package/dist/components/badge.js +55 -108
  13. package/dist/components/calendar.d.ts +36 -26
  14. package/dist/components/calendar.js +132 -1227
  15. package/dist/components/card.d.ts +36 -25
  16. package/dist/components/card.js +895 -72
  17. package/dist/components/carousel.d.ts +63 -47
  18. package/dist/components/carousel.js +496 -777
  19. package/dist/components/data-table.d.ts +5 -4
  20. package/dist/components/data-table.js +7 -6
  21. package/dist/components/dialog-surface.d.ts +23 -1
  22. package/dist/components/dialog-surface.js +99 -3
  23. package/dist/components/dialog.d.ts +80 -45
  24. package/dist/components/dialog.js +258 -503
  25. package/dist/components/dropdown-menu.d.ts +56 -73
  26. package/dist/components/dropdown-menu.js +79 -714
  27. package/dist/components/field.d.ts +3 -1
  28. package/dist/components/field.js +49 -39
  29. package/dist/components/filter-presets-bar.js +2 -2
  30. package/dist/components/filter-query-bar.js +1 -1
  31. package/dist/components/hover-card.d.ts +42 -41
  32. package/dist/components/hover-card.js +57 -483
  33. package/dist/components/pagination.d.ts +53 -31
  34. package/dist/components/pagination.js +176 -412
  35. package/dist/components/popover.d.ts +11 -23
  36. package/dist/components/popover.js +19 -304
  37. package/dist/components/{alert-dialog.d.ts → primitives/alert-dialog.d.ts} +17 -5
  38. package/dist/components/{alert-dialog.js → primitives/alert-dialog.js} +102 -54
  39. package/dist/components/primitives/avatar.d.ts +46 -0
  40. package/dist/components/primitives/avatar.js +267 -0
  41. package/dist/components/primitives/calendar.d.ts +37 -0
  42. package/dist/components/primitives/calendar.js +1250 -0
  43. package/dist/components/primitives/carousel.d.ts +106 -0
  44. package/dist/components/primitives/carousel.js +928 -0
  45. package/dist/components/primitives/dialog.d.ts +62 -0
  46. package/dist/components/primitives/dialog.js +490 -0
  47. package/dist/components/primitives/dropdown-menu-items.d.ts +59 -0
  48. package/dist/components/primitives/dropdown-menu-items.js +265 -0
  49. package/dist/components/primitives/dropdown-menu.d.ts +64 -0
  50. package/dist/components/primitives/dropdown-menu.js +557 -0
  51. package/dist/components/primitives/hover-card.d.ts +50 -0
  52. package/dist/components/primitives/hover-card.js +507 -0
  53. package/dist/components/primitives/pagination.d.ts +65 -0
  54. package/dist/components/primitives/pagination.js +373 -0
  55. package/dist/components/primitives/popover.d.ts +22 -0
  56. package/dist/components/primitives/popover.js +213 -0
  57. package/dist/components/primitives/select.d.ts +36 -0
  58. package/dist/components/primitives/select.js +407 -0
  59. package/dist/components/primitives/tooltip.d.ts +30 -0
  60. package/dist/components/primitives/tooltip.js +277 -0
  61. package/dist/components/radio-group.d.ts +30 -17
  62. package/dist/components/radio-group.js +266 -315
  63. package/dist/components/rich-link-editor.js +1 -1
  64. package/dist/components/select.d.ts +51 -42
  65. package/dist/components/select.js +163 -495
  66. package/dist/components/skeleton.d.ts +16 -15
  67. package/dist/components/skeleton.js +99 -205
  68. package/dist/components/split-button.js +1 -1
  69. package/dist/components/switch.d.ts +3 -6
  70. package/dist/components/switch.js +163 -170
  71. package/dist/components/tabs.d.ts +3 -11
  72. package/dist/components/tabs.js +61 -75
  73. package/dist/components/themed-toaster.d.ts +1 -1
  74. package/dist/components/themed-toaster.js +1 -1
  75. package/dist/components/toaster.d.ts +1 -1
  76. package/dist/components/toaster.js +1 -1
  77. package/dist/components/tooltip.d.ts +36 -31
  78. package/dist/components/tooltip.js +44 -284
  79. package/dist/constants/alert.d.ts +5 -1
  80. package/dist/constants/alert.js +5 -1
  81. package/dist/constants/avatar.d.ts +24 -1
  82. package/dist/constants/avatar.js +19 -0
  83. package/dist/constants/calendar.d.ts +12 -0
  84. package/dist/constants/calendar.js +12 -0
  85. package/dist/constants/card.d.ts +23 -0
  86. package/dist/constants/card.js +20 -0
  87. package/dist/constants/carousel.d.ts +31 -13
  88. package/dist/constants/carousel.js +32 -11
  89. package/dist/constants/dialog.d.ts +6 -1
  90. package/dist/constants/dialog.js +5 -1
  91. package/dist/constants/dropdown-menu.d.ts +2 -2
  92. package/dist/constants/dropdown-menu.js +2 -2
  93. package/dist/constants/pagination.d.ts +13 -2
  94. package/dist/constants/pagination.js +13 -2
  95. package/dist/constants/select.d.ts +4 -2
  96. package/dist/constants/select.js +4 -2
  97. package/dist/constants/switch.d.ts +5 -16
  98. package/dist/constants/switch.js +6 -14
  99. package/dist/hooks/use-today.d.ts +7 -0
  100. package/dist/hooks/use-today.js +50 -0
  101. package/dist/hooks.d.ts +1 -0
  102. package/dist/hooks.js +1 -0
  103. package/dist/index.d.ts +0 -1
  104. package/dist/index.js +0 -1
  105. package/dist/motion/glide-indicator.d.ts +1 -1
  106. package/dist/motion/glide-indicator.js +1 -1
  107. package/dist/motion/presence.d.ts +0 -1
  108. package/dist/motion/presence.js +0 -1
  109. package/dist/styles.css +1 -1
  110. package/package.json +1 -6
@@ -1,346 +1,463 @@
1
1
  "use client";
2
2
  import { c as _c } from "react/compiler-runtime";
3
- import { Avatar as AvatarPrimitive } from "@base-ui/react/avatar";
4
- import { AnimatePresence, motion } from "motion/react";
5
- import { AVATAR_STATUS_HIDDEN_SCALE, AVATAR_STATUS_LABEL } from "../constants/avatar.js";
3
+ /**
4
+ * Arc's Avatar and Avatar group (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md). The avatar is a round
5
+ * portrait named once for assistive technology, with the first two initials standing in until the photo loads or when
6
+ * it fails, and a presence dot that pops in and out. The group overlaps several avatars, collapses the rest into a +N
7
+ * chip whose count rolls the way it moved, opens and closes the slot of members who join or leave, and on fine
8
+ * pointers fans apart while the pointed-at person lifts and shows their name.
9
+ */
10
+ import { useState } from "react";
11
+ import { AnimatePresence, motion, useIsPresent } from "motion/react";
12
+ import { AVATAR_GROUP_COUNT_OFFSET_EM, AVATAR_GROUP_DEFAULT_LABEL, AVATAR_GROUP_DEFAULT_MAX, AVATAR_GROUP_OVERFLOW_SUFFIX, AVATAR_GROUP_SLOT_HIDDEN_SCALE, AVATAR_LABEL_SEPARATOR, AVATAR_SIZE_PX, AVATAR_STATUS_LABEL } from "../constants/avatar.js";
6
13
  import { usePrefersReducedMotion } from "../hooks/use-prefers-reduced-motion.js";
14
+ import { getNameInitials } from "../lib/name-initials.js";
7
15
  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";
10
- import { useBeezUIComponents } from "../providers/beez-ui-provider.js";
16
+ import { ARC_BLUR, ARC_DURATION, ARC_EASE, ARC_SPRING_MORPH } from "../motion/arc-tokens.js";
17
+ import { AvatarBadge, AvatarFallback, AvatarImage, AvatarRoot } from "./primitives/avatar.js";
11
18
  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
19
  /**
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.
20
+ * Builds the avatar's accessible name: the person plus, when shown, their presence.
21
+ * @param name - Text that names the person.
22
+ * @param presence - Presence text, if any.
23
+ * @returns The accessible name.
24
+ */
25
+ function buildAvatarLabel(name, presence) {
26
+ return presence ? `${name}${AVATAR_LABEL_SEPARATOR}${presence}` : name;
27
+ }
28
+ /**
29
+ * A round portrait for one person, with initials as fallback and an optional presence dot.
30
+ * @param props - Name, photo, size, presence, optional fallback and badge, plus native span attributes for the root.
31
+ * @returns The avatar, announced as one image.
18
32
  */
19
33
  function Avatar(t0) {
20
- const $ = _c(24);
21
- let children;
22
- let className;
34
+ const $ = _c(31);
35
+ let alt;
36
+ let badge;
37
+ let fallback;
38
+ let name;
23
39
  let props;
40
+ let src;
24
41
  let status;
25
42
  let statusLabel;
26
43
  let t1;
27
44
  if ($[0] !== t0) {
28
- ({className, size: t1, status, statusLabel, children, ...props} = t0);
45
+ ({name, src, size: t1, status, statusLabel, fallback, badge, alt, ...props} = t0);
29
46
  $[0] = t0;
30
- $[1] = children;
31
- $[2] = className;
32
- $[3] = props;
33
- $[4] = status;
34
- $[5] = statusLabel;
35
- $[6] = t1;
36
- } else {
37
- children = $[1];
38
- className = $[2];
39
- props = $[3];
40
- status = $[4];
41
- statusLabel = $[5];
42
- t1 = $[6];
43
- }
44
- const size = t1 === undefined ? "default" : t1;
45
- const reduceMotion = usePrefersReducedMotion();
46
- let 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;
47
+ $[1] = alt;
48
+ $[2] = badge;
49
+ $[3] = fallback;
50
+ $[4] = name;
51
+ $[5] = props;
52
+ $[6] = src;
53
+ $[7] = status;
54
+ $[8] = statusLabel;
55
+ $[9] = t1;
51
56
  } else {
52
- t2 = $[8];
57
+ alt = $[1];
58
+ badge = $[2];
59
+ fallback = $[3];
60
+ name = $[4];
61
+ props = $[5];
62
+ src = $[6];
63
+ status = $[7];
64
+ statusLabel = $[8];
65
+ t1 = $[9];
53
66
  }
67
+ const size = t1 === undefined ? "md" : t1;
68
+ const presence = status ? statusLabel ?? AVATAR_STATUS_LABEL[status] : undefined;
69
+ const t2 = alt ?? name;
54
70
  let t3;
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;
71
+ if ($[10] !== presence || $[11] !== t2) {
72
+ t3 = buildAvatarLabel(t2, presence);
73
+ $[10] = presence;
74
+ $[11] = t2;
75
+ $[12] = t3;
63
76
  } else {
64
- t3 = $[11];
77
+ t3 = $[12];
65
78
  }
66
79
  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;
80
+ if ($[13] !== size || $[14] !== src) {
81
+ t4 = src ? /* @__PURE__ */ _jsx(AvatarImage, {
82
+ src,
83
+ alt: "",
84
+ width: AVATAR_SIZE_PX[size],
85
+ height: AVATAR_SIZE_PX[size],
86
+ sizes: `${AVATAR_SIZE_PX[size]}px`
87
+ }) : null;
88
+ $[13] = size;
89
+ $[14] = src;
90
+ $[15] = t4;
91
91
  } else {
92
- t4 = $[14];
92
+ t4 = $[15];
93
93
  }
94
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;
95
+ if ($[16] !== fallback || $[17] !== name) {
96
+ t5 = fallback ?? getNameInitials(name);
97
+ $[16] = fallback;
98
+ $[17] = name;
99
+ $[18] = t5;
102
100
  } else {
103
- t5 = $[16];
101
+ t5 = $[18];
104
102
  }
105
103
  let t6;
106
- if ($[17] !== children || $[18] !== props || $[19] !== size || $[20] !== t2 || $[21] !== t3 || $[22] !== t5) {
107
- t6 = /* @__PURE__ */ _jsx(MotionSlot, {
108
- kind: "fade",
109
- children: /* @__PURE__ */ _jsxs(AvatarPrimitive.Root, {
110
- "data-slot": "avatar",
111
- "data-size": size,
112
- className: t2,
113
- ...props,
114
- children: [
115
- children,
116
- t3,
117
- t5
118
- ]
119
- })
104
+ if ($[19] !== t5) {
105
+ t6 = /* @__PURE__ */ _jsx(AvatarFallback, {
106
+ "aria-hidden": "true",
107
+ children: t5
120
108
  });
121
- $[17] = children;
122
- $[18] = props;
123
- $[19] = size;
124
- $[20] = t2;
125
- $[21] = t3;
126
- $[22] = t5;
127
- $[23] = t6;
109
+ $[19] = t5;
110
+ $[20] = t6;
128
111
  } else {
129
- t6 = $[23];
112
+ t6 = $[20];
130
113
  }
131
- return t6;
132
- }
133
- /** Delegates loading, failure and fallback synchronization to the avatar primitive; loaded images develop in place. */
134
- function AvatarImage(t0) {
135
- const $ = _c(15);
136
- let className;
137
- let props;
138
- let src;
139
- let t1;
140
- if ($[0] !== t0) {
141
- ({alt: t1, className, src, ...props} = t0);
142
- $[0] = t0;
143
- $[1] = className;
144
- $[2] = props;
145
- $[3] = src;
146
- $[4] = t1;
114
+ let t7;
115
+ if ($[21] !== badge) {
116
+ t7 = badge ? /* @__PURE__ */ _jsx(AvatarBadge, { children: badge }) : null;
117
+ $[21] = badge;
118
+ $[22] = t7;
147
119
  } else {
148
- className = $[1];
149
- props = $[2];
150
- src = $[3];
151
- t1 = $[4];
120
+ t7 = $[22];
152
121
  }
153
- const alt = t1 === undefined ? "" : t1;
154
- const { Image: t2 } = useBeezUIComponents();
155
- const ImageComponent = t2 === undefined ? "img" : t2;
156
- let t3;
157
- if ($[5] !== ImageComponent) {
158
- t3 = /* @__PURE__ */ _jsx(ImageComponent, {});
159
- $[5] = ImageComponent;
160
- $[6] = t3;
161
- } else {
162
- t3 = $[6];
163
- }
164
- let t4;
165
- if ($[7] !== 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);
167
- $[7] = className;
168
- $[8] = t4;
169
- } else {
170
- t4 = $[8];
171
- }
172
- const t5 = src ?? undefined;
173
- let t6;
174
- if ($[9] !== alt || $[10] !== props || $[11] !== t3 || $[12] !== t4 || $[13] !== t5) {
175
- t6 = /* @__PURE__ */ _jsx(MotionSlot, {
176
- kind: "reveal",
177
- children: /* @__PURE__ */ _jsx(AvatarPrimitive.Image, {
178
- render: t3,
179
- keepMounted: true,
180
- alt,
181
- "data-slot": "avatar-image",
182
- className: t4,
183
- src: t5,
184
- loading: "lazy",
185
- decoding: "async",
186
- ...props
187
- })
122
+ let t8;
123
+ if ($[23] !== props || $[24] !== size || $[25] !== status || $[26] !== t3 || $[27] !== t4 || $[28] !== t6 || $[29] !== t7) {
124
+ t8 = /* @__PURE__ */ _jsxs(AvatarRoot, {
125
+ role: "img",
126
+ "aria-label": t3,
127
+ size,
128
+ status,
129
+ ...props,
130
+ children: [
131
+ t4,
132
+ t6,
133
+ t7
134
+ ]
188
135
  });
189
- $[9] = alt;
190
- $[10] = props;
191
- $[11] = t3;
192
- $[12] = t4;
193
- $[13] = t5;
194
- $[14] = t6;
136
+ $[23] = props;
137
+ $[24] = size;
138
+ $[25] = status;
139
+ $[26] = t3;
140
+ $[27] = t4;
141
+ $[28] = t6;
142
+ $[29] = t7;
143
+ $[30] = t8;
195
144
  } else {
196
- t6 = $[14];
145
+ t8 = $[30];
197
146
  }
198
- return t6;
147
+ return t8;
199
148
  }
200
- function AvatarFallback(t0) {
201
- const $ = _c(8);
202
- let className;
203
- let props;
204
- if ($[0] !== t0) {
205
- ({className, ...props} = t0);
206
- $[0] = t0;
207
- $[1] = className;
208
- $[2] = props;
209
- } else {
210
- className = $[1];
211
- props = $[2];
149
+ /** The overflow count rolls the way it moved: more people rise in from below, fewer drop in from above. */
150
+ const countRoll = {
151
+ hidden: (direction) => ({
152
+ opacity: 0,
153
+ y: `${AVATAR_GROUP_COUNT_OFFSET_EM * direction}em`,
154
+ filter: `blur(${ARC_BLUR.subtle}px)`
155
+ }),
156
+ shown: {
157
+ opacity: 1,
158
+ y: 0,
159
+ filter: "blur(0px)",
160
+ transition: {
161
+ duration: ARC_DURATION.standard,
162
+ ease: [...ARC_EASE.enter]
163
+ }
164
+ },
165
+ gone: (direction) => ({
166
+ opacity: 0,
167
+ y: `${-AVATAR_GROUP_COUNT_OFFSET_EM * direction}em`,
168
+ filter: `blur(${ARC_BLUR.subtle}px)`,
169
+ transition: {
170
+ duration: ARC_DURATION.fast,
171
+ ease: [...ARC_EASE.standard]
172
+ }
173
+ })
174
+ };
175
+ /** Same keys as `countRoll`, so the settled style is identical whichever branch renders on the server. */
176
+ const countFade = {
177
+ hidden: {
178
+ opacity: 0,
179
+ y: 0,
180
+ filter: "blur(0px)"
181
+ },
182
+ shown: {
183
+ opacity: 1,
184
+ y: 0,
185
+ filter: "blur(0px)",
186
+ transition: { duration: ARC_DURATION.instant }
187
+ },
188
+ gone: {
189
+ opacity: 0,
190
+ y: 0,
191
+ filter: "blur(0px)",
192
+ transition: { duration: ARC_DURATION.instant }
212
193
  }
213
- let t1;
214
- if ($[3] !== className) {
215
- t1 = cn("flex size-full items-center justify-center rounded-full bg-surface-muted text-[length:inherit] font-medium text-foreground", className);
216
- $[3] = className;
217
- $[4] = t1;
218
- } else {
219
- t1 = $[4];
194
+ };
195
+ /** A person joining or leaving opens or closes their slot, so the rest of the stack slides instead of jumping. */
196
+ const slotPresence = {
197
+ initial: {
198
+ width: 0,
199
+ opacity: 0,
200
+ scale: AVATAR_GROUP_SLOT_HIDDEN_SCALE
201
+ },
202
+ animate: {
203
+ width: "auto",
204
+ opacity: 1,
205
+ scale: 1
206
+ },
207
+ exit: {
208
+ width: 0,
209
+ opacity: 0,
210
+ scale: AVATAR_GROUP_SLOT_HIDDEN_SCALE
220
211
  }
212
+ };
213
+ /**
214
+ * Each slot is the avatar's visible width, so a slot that opens or closes moves the rest of the stack smoothly. On fine
215
+ * pointers it carries the hover moves as custom properties: the whole stack fans out from its center, the pointed-at
216
+ * slot rises above its neighbours and they ease aside.
217
+ */
218
+ const slotClassName = "group/avatar-group-slot peer/avatar-group-slot relative inline-flex flex-none items-center [--aside:0px] [--fan:0px] [--rise:0px] pointer-fine:group-hover/avatar-group:[--fan:calc((var(--index)-(var(--count)-1)/2)*4px)] hover-fine:z-1 hover-fine:[--rise:-2px] pointer-fine:peer-hover/avatar-group-slot:[--aside:3px] pointer-fine:has-[~[data-slot=avatar-group-slot]:hover]:[--aside:-3px]";
219
+ /** One wrapper per person carries every hover move as a single translate, so the stack never changes size. */
220
+ const liftClassName = "relative -ml-1.5 inline-flex rounded-(--radius-pill) [transform:translate(calc(var(--fan)+var(--aside)),var(--rise))] transition-transform duration-(--duration-standard) ease-(--ease-standard) motion-reduce:transform-none! motion-reduce:transition-none";
221
+ /** The surface ring that separates overlapping avatars, which sharpens on the pointed-at one. */
222
+ const ringClassName = "border-2 border-surface shadow-[0_0_0_1px_var(--border)] transition-shadow duration-(--duration-fast) ease-(--ease-standard) pointer-fine:group-hover/avatar-group-slot:shadow-[0_0_0_1px_var(--border-strong)]";
223
+ /**
224
+ * One slot of the stack. A slot that is closing turns inert and hidden from assistive technology, so a person who left
225
+ * is no longer announced while the exit spring plays.
226
+ * @param props - Motion span props for the slot.
227
+ * @returns The slot.
228
+ */
229
+ function AvatarGroupSlot(props) {
230
+ const $ = _c(4);
231
+ const isPresent = useIsPresent();
232
+ const t0 = isPresent ? props["aria-hidden"] : true;
233
+ const t1 = !isPresent || undefined;
221
234
  let t2;
222
- if ($[5] !== props || $[6] !== t1) {
223
- t2 = /* @__PURE__ */ _jsx(AvatarPrimitive.Fallback, {
224
- "data-slot": "avatar-fallback",
225
- className: t1,
226
- ...props
235
+ if ($[0] !== props || $[1] !== t0 || $[2] !== t1) {
236
+ t2 = /* @__PURE__ */ _jsx(motion.span, {
237
+ "data-slot": "avatar-group-slot",
238
+ ...props,
239
+ "aria-hidden": t0,
240
+ inert: t1
227
241
  });
228
- $[5] = props;
229
- $[6] = t1;
230
- $[7] = t2;
242
+ $[0] = props;
243
+ $[1] = t0;
244
+ $[2] = t1;
245
+ $[3] = t2;
231
246
  } else {
232
- t2 = $[7];
247
+ t2 = $[3];
233
248
  }
234
249
  return t2;
235
250
  }
236
- /** A custom corner badge, drawn with the same ring as Arc's presence dot. Prefer `status` for presence. */
237
- function AvatarBadge(t0) {
238
- const $ = _c(8);
251
+ /**
252
+ * Builds the overflow chip's accessible name, as in "2 integrantes más".
253
+ * @param overflow - How many members are hidden.
254
+ * @param label - Accessible name of the group.
255
+ * @returns The chip's accessible name.
256
+ */
257
+ function buildOverflowLabel(overflow, label) {
258
+ return `${overflow} ${label.toLowerCase()} ${AVATAR_GROUP_OVERFLOW_SUFFIX}`;
259
+ }
260
+ /**
261
+ * An overlapping stack of avatars with a +N overflow chip.
262
+ * @param props - Members, optional total, how many to show, size, accessible label, classes and native root attributes.
263
+ * @returns The group.
264
+ */
265
+ function AvatarGroup(t0) {
266
+ const $ = _c(40);
239
267
  let className;
268
+ let members;
240
269
  let props;
270
+ let style;
271
+ let t1;
272
+ let t2;
273
+ let t3;
274
+ let total;
241
275
  if ($[0] !== t0) {
242
- ({className, ...props} = t0);
276
+ ({members, total, max: t1, size: t2, label: t3, className, style, ...props} = t0);
243
277
  $[0] = t0;
244
278
  $[1] = className;
245
- $[2] = props;
279
+ $[2] = members;
280
+ $[3] = props;
281
+ $[4] = style;
282
+ $[5] = t1;
283
+ $[6] = t2;
284
+ $[7] = t3;
285
+ $[8] = total;
246
286
  } else {
247
287
  className = $[1];
248
- props = $[2];
288
+ members = $[2];
289
+ props = $[3];
290
+ style = $[4];
291
+ t1 = $[5];
292
+ t2 = $[6];
293
+ t3 = $[7];
294
+ total = $[8];
249
295
  }
250
- let t1;
251
- if ($[3] !== 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);
253
- $[3] = className;
254
- $[4] = t1;
296
+ const max = t1 === undefined ? AVATAR_GROUP_DEFAULT_MAX : t1;
297
+ const size = t2 === undefined ? "md" : t2;
298
+ const label = t3 === undefined ? AVATAR_GROUP_DEFAULT_LABEL : t3;
299
+ const reduceMotion = usePrefersReducedMotion();
300
+ const visibleMembers = members.slice(0, Math.max(0, max));
301
+ const memberCount = Math.max(members.length, total ?? 0);
302
+ const overflow = Math.max(0, memberCount - visibleMembers.length);
303
+ let t4;
304
+ if ($[9] !== reduceMotion) {
305
+ t4 = reduceMotion ? { duration: 0 } : ARC_SPRING_MORPH;
306
+ $[9] = reduceMotion;
307
+ $[10] = t4;
255
308
  } else {
256
- t1 = $[4];
309
+ t4 = $[10];
257
310
  }
258
- let t2;
259
- if ($[5] !== props || $[6] !== t1) {
260
- t2 = /* @__PURE__ */ _jsx("span", {
261
- "data-slot": "avatar-badge",
262
- className: t1,
263
- ...props
264
- });
265
- $[5] = props;
266
- $[6] = t1;
267
- $[7] = t2;
311
+ const slotTransition = t4;
312
+ let t5;
313
+ if ($[11] !== overflow) {
314
+ t5 = {
315
+ overflow,
316
+ direction: 1
317
+ };
318
+ $[11] = overflow;
319
+ $[12] = t5;
268
320
  } else {
269
- t2 = $[7];
321
+ t5 = $[12];
270
322
  }
271
- return t2;
272
- }
273
- /** Overlaps avatars; the hovered one lifts slightly above its neighbours. */
274
- function AvatarGroup(t0) {
275
- const $ = _c(8);
276
- let className;
277
- let props;
278
- if ($[0] !== t0) {
279
- ({className, ...props} = t0);
280
- $[0] = t0;
281
- $[1] = className;
282
- $[2] = props;
323
+ const [shownCount, setShownCount] = useState(t5);
324
+ if (shownCount.overflow !== overflow) {
325
+ setShownCount({
326
+ overflow,
327
+ direction: overflow < shownCount.overflow ? -1 : 1
328
+ });
329
+ }
330
+ const t6 = visibleMembers.length + (overflow > 0 ? 1 : 0);
331
+ let t7;
332
+ if ($[13] !== style || $[14] !== t6) {
333
+ t7 = {
334
+ ...style,
335
+ "--count": t6
336
+ };
337
+ $[13] = style;
338
+ $[14] = t6;
339
+ $[15] = t7;
283
340
  } else {
284
- className = $[1];
285
- props = $[2];
341
+ t7 = $[15];
286
342
  }
287
- let t1;
288
- if ($[3] !== className) {
289
- t1 = cn("group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background *:data-[slot=avatar]:transition-[translate] *:data-[slot=avatar]:duration-200 *:data-[slot=avatar]:ease-out *:data-[slot=avatar]:hover:z-10 *:data-[slot=avatar]:hover:-translate-y-0.5", className);
290
- $[3] = className;
291
- $[4] = t1;
343
+ const groupStyle = t7;
344
+ const t8 = "group";
345
+ const t9 = "avatar-group";
346
+ let t10;
347
+ if ($[16] !== className) {
348
+ t10 = cn("group/avatar-group inline-flex items-center pl-1.5", className);
349
+ $[16] = className;
350
+ $[17] = t10;
292
351
  } else {
293
- t1 = $[4];
352
+ t10 = $[17];
294
353
  }
295
- let t2;
296
- if ($[5] !== props || $[6] !== t1) {
297
- t2 = /* @__PURE__ */ _jsx("div", {
298
- "data-slot": "avatar-group",
299
- className: t1,
300
- ...props
301
- });
302
- $[5] = props;
303
- $[6] = t1;
304
- $[7] = t2;
354
+ const T0 = AnimatePresence;
355
+ const t11 = false;
356
+ let t12;
357
+ if ($[18] !== size || $[19] !== slotTransition) {
358
+ t12 = (member, index) => /* @__PURE__ */ _jsx(AvatarGroupSlot, {
359
+ className: slotClassName,
360
+ style: { "--index": index },
361
+ ...slotPresence,
362
+ transition: slotTransition,
363
+ children: /* @__PURE__ */ _jsxs("span", {
364
+ className: liftClassName,
365
+ children: [/* @__PURE__ */ _jsx(Avatar, {
366
+ className: ringClassName,
367
+ name: member.name,
368
+ src: member.src,
369
+ status: member.status,
370
+ size
371
+ }), /* @__PURE__ */ _jsx("span", {
372
+ "aria-hidden": "true",
373
+ className: "pointer-events-none absolute bottom-[calc(100%+8px)] left-1/2 z-2 -translate-x-1/2 translate-y-[3px] rounded-(--radius-pill) bg-foreground px-2 py-1 text-xs leading-(--leading-body) font-medium whitespace-nowrap text-background opacity-0 transition-[opacity,translate] duration-(--duration-fast) ease-(--ease-standard) pointer-fine:group-hover/avatar-group-slot:translate-y-0 pointer-fine:group-hover/avatar-group-slot:opacity-100 pointer-fine:group-hover/avatar-group-slot:delay-60 motion-reduce:translate-y-0 motion-reduce:transition-none",
374
+ children: member.name
375
+ })]
376
+ })
377
+ }, member.key ?? member.name);
378
+ $[18] = size;
379
+ $[19] = slotTransition;
380
+ $[20] = t12;
305
381
  } else {
306
- t2 = $[7];
382
+ t12 = $[20];
307
383
  }
308
- return t2;
309
- }
310
- function AvatarGroupCount(t0) {
311
- const $ = _c(8);
312
- let className;
313
- let props;
314
- if ($[0] !== t0) {
315
- ({className, ...props} = t0);
316
- $[0] = t0;
317
- $[1] = className;
318
- $[2] = props;
384
+ const t13 = visibleMembers.map(t12);
385
+ let t14;
386
+ if ($[21] !== label || $[22] !== overflow || $[23] !== reduceMotion || $[24] !== shownCount.direction || $[25] !== size || $[26] !== slotTransition || $[27] !== visibleMembers) {
387
+ t14 = overflow > 0 ? /* @__PURE__ */ _jsx(AvatarGroupSlot, {
388
+ className: slotClassName,
389
+ style: { "--index": visibleMembers.length },
390
+ ...slotPresence,
391
+ transition: slotTransition,
392
+ children: /* @__PURE__ */ _jsx("span", {
393
+ role: "img",
394
+ "aria-label": buildOverflowLabel(overflow, label),
395
+ "data-slot": "avatar-group-count",
396
+ "data-size": size,
397
+ className: cn(liftClassName, ringClassName, "relative grid size-8 place-items-center overflow-hidden bg-surface-muted text-xs font-medium text-text-secondary tabular-nums data-[size=lg]:size-10 data-[size=lg]:text-sm data-[size=sm]:size-6 data-[size=sm]:text-[10px]"),
398
+ children: /* @__PURE__ */ _jsx(AnimatePresence, {
399
+ mode: "popLayout",
400
+ initial: false,
401
+ custom: shownCount.direction,
402
+ children: /* @__PURE__ */ _jsxs(motion.span, {
403
+ "aria-hidden": "true",
404
+ className: "inline-block",
405
+ custom: shownCount.direction,
406
+ variants: reduceMotion ? countFade : countRoll,
407
+ initial: "hidden",
408
+ animate: "shown",
409
+ exit: "gone",
410
+ children: ["+", overflow]
411
+ }, overflow)
412
+ })
413
+ })
414
+ }, "overflow") : null;
415
+ $[21] = label;
416
+ $[22] = overflow;
417
+ $[23] = reduceMotion;
418
+ $[24] = shownCount.direction;
419
+ $[25] = size;
420
+ $[26] = slotTransition;
421
+ $[27] = visibleMembers;
422
+ $[28] = t14;
319
423
  } else {
320
- className = $[1];
321
- props = $[2];
424
+ t14 = $[28];
322
425
  }
323
- let t1;
324
- if ($[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);
326
- $[3] = className;
327
- $[4] = t1;
426
+ let t15;
427
+ if ($[29] !== T0 || $[30] !== t13 || $[31] !== t14) {
428
+ t15 = /* @__PURE__ */ _jsxs(T0, {
429
+ initial: t11,
430
+ children: [t13, t14]
431
+ });
432
+ $[29] = T0;
433
+ $[30] = t13;
434
+ $[31] = t14;
435
+ $[32] = t15;
328
436
  } else {
329
- t1 = $[4];
437
+ t15 = $[32];
330
438
  }
331
- let t2;
332
- if ($[5] !== props || $[6] !== t1) {
333
- t2 = /* @__PURE__ */ _jsx("div", {
334
- "data-slot": "avatar-group-count",
335
- className: t1,
336
- ...props
439
+ let t16;
440
+ if ($[33] !== groupStyle || $[34] !== label || $[35] !== props || $[36] !== size || $[37] !== t10 || $[38] !== t15) {
441
+ t16 = /* @__PURE__ */ _jsx("div", {
442
+ ...props,
443
+ role: t8,
444
+ "aria-label": label,
445
+ "data-slot": t9,
446
+ "data-size": size,
447
+ className: t10,
448
+ style: groupStyle,
449
+ children: t15
337
450
  });
338
- $[5] = props;
339
- $[6] = t1;
340
- $[7] = t2;
451
+ $[33] = groupStyle;
452
+ $[34] = label;
453
+ $[35] = props;
454
+ $[36] = size;
455
+ $[37] = t10;
456
+ $[38] = t15;
457
+ $[39] = t16;
341
458
  } else {
342
- t2 = $[7];
459
+ t16 = $[39];
343
460
  }
344
- return t2;
461
+ return t16;
345
462
  }
346
- export { Avatar, AvatarImage, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarBadge };
463
+ export { Avatar, AvatarGroup };