@mortenbrudvik/waveui 0.9.0 → 0.11.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 (264) hide show
  1. package/README.md +758 -152
  2. package/dist/components/button/Toolbar.cjs +1 -1
  3. package/dist/components/button/Toolbar.cjs.map +1 -1
  4. package/dist/components/button/Toolbar.mjs +25 -30
  5. package/dist/components/button/Toolbar.mjs.map +1 -1
  6. package/dist/components/button/Toolbar.navigation.cjs +2 -0
  7. package/dist/components/button/Toolbar.navigation.cjs.map +1 -0
  8. package/dist/components/button/Toolbar.navigation.mjs +17 -0
  9. package/dist/components/button/Toolbar.navigation.mjs.map +1 -0
  10. package/dist/components/data-display/Avatar.cjs +1 -1
  11. package/dist/components/data-display/Avatar.cjs.map +1 -1
  12. package/dist/components/data-display/Avatar.context.cjs +2 -0
  13. package/dist/components/data-display/Avatar.context.cjs.map +1 -0
  14. package/dist/components/data-display/Avatar.context.mjs +9 -0
  15. package/dist/components/data-display/Avatar.context.mjs.map +1 -0
  16. package/dist/components/data-display/Avatar.mjs +66 -61
  17. package/dist/components/data-display/Avatar.mjs.map +1 -1
  18. package/dist/components/data-display/InteractionTag.cjs +2 -0
  19. package/dist/components/data-display/InteractionTag.cjs.map +1 -0
  20. package/dist/components/data-display/InteractionTag.mjs +234 -0
  21. package/dist/components/data-display/InteractionTag.mjs.map +1 -0
  22. package/dist/components/data-display/Tag.cjs +1 -1
  23. package/dist/components/data-display/Tag.cjs.map +1 -1
  24. package/dist/components/data-display/Tag.mjs +222 -90
  25. package/dist/components/data-display/Tag.mjs.map +1 -1
  26. package/dist/components/data-display/TagGroup.cjs +2 -0
  27. package/dist/components/data-display/TagGroup.cjs.map +1 -0
  28. package/dist/components/data-display/TagGroup.context.cjs +2 -0
  29. package/dist/components/data-display/TagGroup.context.cjs.map +1 -0
  30. package/dist/components/data-display/TagGroup.context.mjs +113 -0
  31. package/dist/components/data-display/TagGroup.context.mjs.map +1 -0
  32. package/dist/components/data-display/TagGroup.mjs +149 -0
  33. package/dist/components/data-display/TagGroup.mjs.map +1 -0
  34. package/dist/components/data-display/tagStyles.cjs +2 -0
  35. package/dist/components/data-display/tagStyles.cjs.map +1 -0
  36. package/dist/components/data-display/tagStyles.mjs +108 -0
  37. package/dist/components/data-display/tagStyles.mjs.map +1 -0
  38. package/dist/components/feedback/Toaster.cjs +1 -1
  39. package/dist/components/feedback/Toaster.cjs.map +1 -1
  40. package/dist/components/feedback/Toaster.mjs +213 -181
  41. package/dist/components/feedback/Toaster.mjs.map +1 -1
  42. package/dist/components/input/Calendar.cjs +2 -0
  43. package/dist/components/input/Calendar.cjs.map +1 -0
  44. package/dist/components/input/Calendar.mjs +352 -0
  45. package/dist/components/input/Calendar.mjs.map +1 -0
  46. package/dist/components/input/Calendar.views.cjs +2 -0
  47. package/dist/components/input/Calendar.views.cjs.map +1 -0
  48. package/dist/components/input/Calendar.views.mjs +194 -0
  49. package/dist/components/input/Calendar.views.mjs.map +1 -0
  50. package/dist/components/input/ColorArea.cjs +1 -1
  51. package/dist/components/input/ColorArea.cjs.map +1 -1
  52. package/dist/components/input/ColorArea.mjs +18 -18
  53. package/dist/components/input/ColorArea.mjs.map +1 -1
  54. package/dist/components/input/Combobox.cjs +1 -1
  55. package/dist/components/input/Combobox.cjs.map +1 -1
  56. package/dist/components/input/Combobox.expand.cjs +1 -1
  57. package/dist/components/input/Combobox.expand.cjs.map +1 -1
  58. package/dist/components/input/Combobox.expand.mjs +7 -7
  59. package/dist/components/input/Combobox.expand.mjs.map +1 -1
  60. package/dist/components/input/Combobox.mjs +232 -156
  61. package/dist/components/input/Combobox.mjs.map +1 -1
  62. package/dist/components/input/Combobox.text.cjs +2 -0
  63. package/dist/components/input/Combobox.text.cjs.map +1 -0
  64. package/dist/components/input/Combobox.text.mjs +24 -0
  65. package/dist/components/input/Combobox.text.mjs.map +1 -0
  66. package/dist/components/input/DatePicker.cjs +1 -1
  67. package/dist/components/input/DatePicker.cjs.map +1 -1
  68. package/dist/components/input/DatePicker.mjs +203 -288
  69. package/dist/components/input/DatePicker.mjs.map +1 -1
  70. package/dist/components/input/Dropdown.cjs +1 -1
  71. package/dist/components/input/Dropdown.cjs.map +1 -1
  72. package/dist/components/input/Dropdown.mjs +135 -109
  73. package/dist/components/input/Dropdown.mjs.map +1 -1
  74. package/dist/components/input/Listbox.cjs +2 -0
  75. package/dist/components/input/Listbox.cjs.map +1 -0
  76. package/dist/components/input/Listbox.mjs +134 -0
  77. package/dist/components/input/Listbox.mjs.map +1 -0
  78. package/dist/components/input/Option.cjs +1 -1
  79. package/dist/components/input/Option.cjs.map +1 -1
  80. package/dist/components/input/Option.mjs +163 -97
  81. package/dist/components/input/Option.mjs.map +1 -1
  82. package/dist/components/input/SwatchPicker.cjs +1 -1
  83. package/dist/components/input/SwatchPicker.cjs.map +1 -1
  84. package/dist/components/input/SwatchPicker.context.cjs +2 -0
  85. package/dist/components/input/SwatchPicker.context.cjs.map +1 -0
  86. package/dist/components/input/SwatchPicker.context.mjs +35 -0
  87. package/dist/components/input/SwatchPicker.context.mjs.map +1 -0
  88. package/dist/components/input/SwatchPicker.mjs +131 -103
  89. package/dist/components/input/SwatchPicker.mjs.map +1 -1
  90. package/dist/components/input/SwatchPicker.swatches.cjs +2 -0
  91. package/dist/components/input/SwatchPicker.swatches.cjs.map +1 -0
  92. package/dist/components/input/SwatchPicker.swatches.mjs +207 -0
  93. package/dist/components/input/SwatchPicker.swatches.mjs.map +1 -0
  94. package/dist/components/input/TagPicker.cjs +1 -1
  95. package/dist/components/input/TagPicker.cjs.map +1 -1
  96. package/dist/components/input/TagPicker.context.cjs +2 -0
  97. package/dist/components/input/TagPicker.context.cjs.map +1 -0
  98. package/dist/components/input/TagPicker.context.mjs +20 -0
  99. package/dist/components/input/TagPicker.context.mjs.map +1 -0
  100. package/dist/components/input/TagPicker.create.cjs +2 -0
  101. package/dist/components/input/TagPicker.create.cjs.map +1 -0
  102. package/dist/components/input/TagPicker.create.mjs +24 -0
  103. package/dist/components/input/TagPicker.create.mjs.map +1 -0
  104. package/dist/components/input/TagPicker.mjs +13 -274
  105. package/dist/components/input/TagPicker.mjs.map +1 -1
  106. package/dist/components/input/TagPicker.option.cjs +2 -0
  107. package/dist/components/input/TagPicker.option.cjs.map +1 -0
  108. package/dist/components/input/TagPicker.option.mjs +45 -0
  109. package/dist/components/input/TagPicker.option.mjs.map +1 -0
  110. package/dist/components/input/TagPicker.overflow.cjs +2 -0
  111. package/dist/components/input/TagPicker.overflow.cjs.map +1 -0
  112. package/dist/components/input/TagPicker.overflow.mjs +153 -0
  113. package/dist/components/input/TagPicker.overflow.mjs.map +1 -0
  114. package/dist/components/input/TagPicker.parts.cjs +2 -0
  115. package/dist/components/input/TagPicker.parts.cjs.map +1 -0
  116. package/dist/components/input/TagPicker.parts.mjs +425 -0
  117. package/dist/components/input/TagPicker.parts.mjs.map +1 -0
  118. package/dist/components/input/TagPicker.root.cjs +2 -0
  119. package/dist/components/input/TagPicker.root.cjs.map +1 -0
  120. package/dist/components/input/TagPicker.root.mjs +416 -0
  121. package/dist/components/input/TagPicker.root.mjs.map +1 -0
  122. package/dist/components/input/TimePicker.cjs +1 -1
  123. package/dist/components/input/TimePicker.cjs.map +1 -1
  124. package/dist/components/input/TimePicker.mjs +77 -77
  125. package/dist/components/input/TimePicker.mjs.map +1 -1
  126. package/dist/components/input/dateUtils.cjs +1 -1
  127. package/dist/components/input/dateUtils.cjs.map +1 -1
  128. package/dist/components/input/dateUtils.mjs +114 -96
  129. package/dist/components/input/dateUtils.mjs.map +1 -1
  130. package/dist/components/input/pickerLabels.cjs +2 -0
  131. package/dist/components/input/pickerLabels.cjs.map +1 -0
  132. package/dist/components/input/pickerLabels.mjs +16 -0
  133. package/dist/components/input/pickerLabels.mjs.map +1 -0
  134. package/dist/components/input/pickerValues.cjs +2 -0
  135. package/dist/components/input/pickerValues.cjs.map +1 -0
  136. package/dist/components/input/pickerValues.mjs +24 -0
  137. package/dist/components/input/pickerValues.mjs.map +1 -0
  138. package/dist/components/layout/Accordion.cjs.map +1 -1
  139. package/dist/components/layout/Accordion.mjs.map +1 -1
  140. package/dist/components/navigation/Hamburger.cjs +2 -0
  141. package/dist/components/navigation/Hamburger.cjs.map +1 -0
  142. package/dist/components/navigation/Hamburger.mjs +54 -0
  143. package/dist/components/navigation/Hamburger.mjs.map +1 -0
  144. package/dist/components/navigation/Nav.cjs +1 -1
  145. package/dist/components/navigation/Nav.cjs.map +1 -1
  146. package/dist/components/navigation/Nav.context.cjs +2 -0
  147. package/dist/components/navigation/Nav.context.cjs.map +1 -0
  148. package/dist/components/navigation/Nav.context.mjs +137 -0
  149. package/dist/components/navigation/Nav.context.mjs.map +1 -0
  150. package/dist/components/navigation/Nav.mjs +151 -258
  151. package/dist/components/navigation/Nav.mjs.map +1 -1
  152. package/dist/components/navigation/Nav.parts.cjs +2 -0
  153. package/dist/components/navigation/Nav.parts.cjs.map +1 -0
  154. package/dist/components/navigation/Nav.parts.mjs +77 -0
  155. package/dist/components/navigation/Nav.parts.mjs.map +1 -0
  156. package/dist/components/navigation/Nav.root.cjs +2 -0
  157. package/dist/components/navigation/Nav.root.cjs.map +1 -0
  158. package/dist/components/navigation/Nav.root.mjs +78 -0
  159. package/dist/components/navigation/Nav.root.mjs.map +1 -0
  160. package/dist/components/navigation/NavDrawer.cjs +2 -0
  161. package/dist/components/navigation/NavDrawer.cjs.map +1 -0
  162. package/dist/components/navigation/NavDrawer.context.cjs +2 -0
  163. package/dist/components/navigation/NavDrawer.context.cjs.map +1 -0
  164. package/dist/components/navigation/NavDrawer.context.mjs +11 -0
  165. package/dist/components/navigation/NavDrawer.context.mjs.map +1 -0
  166. package/dist/components/navigation/NavDrawer.mjs +179 -0
  167. package/dist/components/navigation/NavDrawer.mjs.map +1 -0
  168. package/dist/components/overlays/Dialog.cjs +1 -1
  169. package/dist/components/overlays/Dialog.cjs.map +1 -1
  170. package/dist/components/overlays/Dialog.mjs +190 -125
  171. package/dist/components/overlays/Dialog.mjs.map +1 -1
  172. package/dist/components/overlays/Dialog.shared.cjs +1 -1
  173. package/dist/components/overlays/Dialog.shared.cjs.map +1 -1
  174. package/dist/components/overlays/Dialog.shared.mjs +157 -81
  175. package/dist/components/overlays/Dialog.shared.mjs.map +1 -1
  176. package/dist/components/overlays/Dialog.slots.cjs +2 -0
  177. package/dist/components/overlays/Dialog.slots.cjs.map +1 -0
  178. package/dist/components/overlays/Dialog.slots.mjs +129 -0
  179. package/dist/components/overlays/Dialog.slots.mjs.map +1 -0
  180. package/dist/components/overlays/Drawer.cjs +1 -1
  181. package/dist/components/overlays/Drawer.cjs.map +1 -1
  182. package/dist/components/overlays/Drawer.context.cjs +2 -0
  183. package/dist/components/overlays/Drawer.context.cjs.map +1 -0
  184. package/dist/components/overlays/Drawer.context.mjs +29 -0
  185. package/dist/components/overlays/Drawer.context.mjs.map +1 -0
  186. package/dist/components/overlays/Drawer.mjs +12 -187
  187. package/dist/components/overlays/Drawer.mjs.map +1 -1
  188. package/dist/components/overlays/Drawer.panel.cjs +2 -0
  189. package/dist/components/overlays/Drawer.panel.cjs.map +1 -0
  190. package/dist/components/overlays/Drawer.panel.mjs +159 -0
  191. package/dist/components/overlays/Drawer.panel.mjs.map +1 -0
  192. package/dist/components/overlays/Drawer.parts.cjs +2 -0
  193. package/dist/components/overlays/Drawer.parts.cjs.map +1 -0
  194. package/dist/components/overlays/Drawer.parts.mjs +152 -0
  195. package/dist/components/overlays/Drawer.parts.mjs.map +1 -0
  196. package/dist/components/overlays/Drawer.root.cjs +2 -0
  197. package/dist/components/overlays/Drawer.root.cjs.map +1 -0
  198. package/dist/components/overlays/Drawer.root.mjs +207 -0
  199. package/dist/components/overlays/Drawer.root.mjs.map +1 -0
  200. package/dist/components/overlays/Drawer.scroll.cjs +2 -0
  201. package/dist/components/overlays/Drawer.scroll.cjs.map +1 -0
  202. package/dist/components/overlays/Drawer.scroll.mjs +42 -0
  203. package/dist/components/overlays/Drawer.scroll.mjs.map +1 -0
  204. package/dist/components/table/useGridNavigation.cjs +1 -1
  205. package/dist/components/table/useGridNavigation.cjs.map +1 -1
  206. package/dist/components/table/useGridNavigation.mjs +67 -70
  207. package/dist/components/table/useGridNavigation.mjs.map +1 -1
  208. package/dist/hooks/useActiveDescendant.cjs +2 -0
  209. package/dist/hooks/useActiveDescendant.cjs.map +1 -0
  210. package/dist/hooks/useActiveDescendant.mjs +56 -0
  211. package/dist/hooks/useActiveDescendant.mjs.map +1 -0
  212. package/dist/hooks/useDismiss.cjs.map +1 -1
  213. package/dist/hooks/useDismiss.mjs.map +1 -1
  214. package/dist/hooks/useFocusTrap.cjs +1 -1
  215. package/dist/hooks/useFocusTrap.cjs.map +1 -1
  216. package/dist/hooks/useFocusTrap.mjs +115 -98
  217. package/dist/hooks/useFocusTrap.mjs.map +1 -1
  218. package/dist/hooks/useListbox.cjs +1 -1
  219. package/dist/hooks/useListbox.cjs.map +1 -1
  220. package/dist/hooks/useListbox.mjs +250 -210
  221. package/dist/hooks/useListbox.mjs.map +1 -1
  222. package/dist/hooks/useModalLayer.cjs +1 -1
  223. package/dist/hooks/useModalLayer.cjs.map +1 -1
  224. package/dist/hooks/useModalLayer.mjs +35 -22
  225. package/dist/hooks/useModalLayer.mjs.map +1 -1
  226. package/dist/hooks/useRestoreFocus.cjs +1 -1
  227. package/dist/hooks/useRestoreFocus.cjs.map +1 -1
  228. package/dist/hooks/useRestoreFocus.mjs +91 -78
  229. package/dist/hooks/useRestoreFocus.mjs.map +1 -1
  230. package/dist/hooks/useRovingGrid.cjs +2 -0
  231. package/dist/hooks/useRovingGrid.cjs.map +1 -0
  232. package/dist/hooks/useRovingGrid.mjs +69 -0
  233. package/dist/hooks/useRovingGrid.mjs.map +1 -0
  234. package/dist/hooks/useRovingTabIndex.cjs +1 -1
  235. package/dist/hooks/useRovingTabIndex.cjs.map +1 -1
  236. package/dist/hooks/useRovingTabIndex.mjs +102 -78
  237. package/dist/hooks/useRovingTabIndex.mjs.map +1 -1
  238. package/dist/index.cjs +1 -1
  239. package/dist/index.d.cts +4391 -394
  240. package/dist/index.d.ts +4391 -394
  241. package/dist/index.mjs +115 -101
  242. package/dist/lib/classNames.cjs +1 -1
  243. package/dist/lib/classNames.cjs.map +1 -1
  244. package/dist/lib/classNames.mjs +170 -74
  245. package/dist/lib/classNames.mjs.map +1 -1
  246. package/dist/lib/date.cjs +2 -0
  247. package/dist/lib/date.cjs.map +1 -0
  248. package/dist/lib/date.mjs +44 -0
  249. package/dist/lib/date.mjs.map +1 -0
  250. package/dist/lib/focus.cjs +1 -1
  251. package/dist/lib/focus.cjs.map +1 -1
  252. package/dist/lib/focus.mjs +5 -2
  253. package/dist/lib/focus.mjs.map +1 -1
  254. package/dist/lib/icons.cjs +1 -1
  255. package/dist/lib/icons.cjs.map +1 -1
  256. package/dist/lib/icons.mjs +13 -6
  257. package/dist/lib/icons.mjs.map +1 -1
  258. package/dist/lib/layers.cjs +1 -1
  259. package/dist/lib/layers.cjs.map +1 -1
  260. package/dist/lib/layers.mjs +53 -47
  261. package/dist/lib/layers.mjs.map +1 -1
  262. package/dist/styles.css +1 -1
  263. package/package.json +1 -1
  264. package/src/styles/tokens.css +25 -0
@@ -4,30 +4,35 @@ import { renderSlot as t, slotRendersContent as n } from "../../lib/slot.mjs";
4
4
  import { composeEventHandlers as r } from "../../lib/composeEventHandlers.mjs";
5
5
  import { avatarClassNames as i } from "../../lib/classNames.mjs";
6
6
  import { useMergedRefs as a } from "../../hooks/useMergedRefs.mjs";
7
- import { joinIds as o } from "../../lib/aria.mjs";
8
- import { PersonIcon as ee } from "../../lib/icons.mjs";
9
- import * as s from "react";
10
- import { jsx as c, jsxs as l } from "react/jsx-runtime";
7
+ import { joinIds as ee } from "../../lib/aria.mjs";
8
+ import { PersonIcon as te } from "../../lib/icons.mjs";
9
+ import { AvatarSizeContext as ne } from "./Avatar.context.mjs";
10
+ import * as o from "react";
11
+ import { jsx as s, jsxs as re } from "react/jsx-runtime";
11
12
  //#region src/components/data-display/Avatar.tsx
12
- var u = {
13
+ var c = {
13
14
  "extra-small": "w-6 h-6 text-[10px]",
14
15
  small: "w-8 h-8 text-xs",
15
16
  medium: "w-10 h-10 text-sm",
16
17
  large: "w-12 h-12 text-base",
17
18
  "extra-large": "w-14 h-14 text-lg"
18
- }, d = "w-full h-full object-cover";
19
- function te(e) {
19
+ }, ie = {
20
+ 24: c["extra-small"],
21
+ 20: "w-5 h-5 text-[10px]",
22
+ 16: "w-4 h-4 text-[10px]"
23
+ }, l = "w-full h-full object-cover";
24
+ function ae(e) {
20
25
  let t = e.trim().split(/\s+/).filter(Boolean);
21
26
  return t.length === 0 ? "" : ((Array.from(t[0])[0] ?? "") + (t.length > 1 ? Array.from(t[t.length - 1])[0] ?? "" : "")).toUpperCase();
22
27
  }
23
- function f(e) {
28
+ function u(e) {
24
29
  return e?.trim().replace(/\s+/g, " ") || void 0;
25
30
  }
26
- function ne(e) {
27
- if (s.isValidElement(e)) return e.props;
31
+ function oe(e) {
32
+ if (o.isValidElement(e)) return e.props;
28
33
  if (typeof e == "object" && e && !(Symbol.iterator in e)) return e;
29
34
  }
30
- function re(e, t, n) {
35
+ function se(e, t, n) {
31
36
  if (e === void 0) return [
32
37
  void 0,
33
38
  void 0,
@@ -40,7 +45,7 @@ function re(e, t, n) {
40
45
  e,
41
46
  void 0
42
47
  ];
43
- let r = s.isValidElement(e) ? e : void 0;
48
+ let r = o.isValidElement(e) ? e : void 0;
44
49
  return [
45
50
  r?.type,
46
51
  r?.key,
@@ -48,115 +53,115 @@ function re(e, t, n) {
48
53
  t?.srcSet
49
54
  ];
50
55
  }
51
- function p(e) {
56
+ function d(e) {
52
57
  if (typeof e != "object" || !e) return !1;
53
58
  let t = Object.getPrototypeOf(e);
54
59
  return t === Object.prototype || t === null;
55
60
  }
56
- function m(e, t) {
61
+ function f(e, t) {
57
62
  if (Object.is(e, t)) return !0;
58
- if (!p(e) || !p(t)) return !1;
63
+ if (!d(e) || !d(t)) return !1;
59
64
  let n = Object.keys(e);
60
65
  return n.length === Object.keys(t).length && n.every((n) => Object.prototype.hasOwnProperty.call(t, n) && Object.is(e[n], t[n]));
61
66
  }
62
- function ie(e, t) {
63
- return e.every((e, n) => m(e, t[n]));
67
+ function p(e, t) {
68
+ return e.every((e, n) => f(e, t[n]));
64
69
  }
65
- var h = ({ src: p, name: m, size: h = "medium", icon: g, image: _, badge: v, decorative: y = !1, className: b, ref: x, role: S, "aria-label": C, "aria-labelledby": w, "aria-describedby": T, "aria-description": ae, "aria-details": oe, ...E }) => {
66
- let D = _ == null || typeof _ == "boolean" || _ === "" ? void 0 : _, O = ne(D), k = re(D, O, p), [se, A] = s.useState(!1), [ce, le] = s.useState(k);
67
- ie(ce, k) || (le(k), A(!1));
68
- let j = s.useRef(null);
69
- s.useLayoutEffect(() => {
70
- let e = j.current?.querySelector("img");
70
+ var m = ({ src: d, name: f, size: m, icon: h, image: g, badge: _, decorative: v = !1, className: y, ref: b, role: x, "aria-label": S, "aria-labelledby": C, "aria-describedby": w, "aria-description": ce, "aria-details": le, ...T }) => {
71
+ let E = o.useContext(ne), D = g == null || typeof g == "boolean" || g === "" ? void 0 : g, O = oe(D), k = se(D, O, d), [A, j] = o.useState(!1), [ue, de] = o.useState(k);
72
+ p(ue, k) || (de(k), j(!1));
73
+ let M = o.useRef(null);
74
+ o.useLayoutEffect(() => {
75
+ let e = M.current?.querySelector("img");
71
76
  if (!e || !e.complete || e.naturalWidth !== 0) return;
72
77
  let t = !0, n = e.getAttribute("src"), r = e.getAttribute("srcset"), i = () => {
73
- t && e.isConnected && e.getAttribute("src") === n && e.getAttribute("srcset") === r && A(!0);
78
+ t && e.isConnected && e.getAttribute("src") === n && e.getAttribute("srcset") === r && j(!0);
74
79
  };
75
80
  return typeof e.decode == "function" ? e.decode().then(void 0, i) : queueMicrotask(i), () => {
76
81
  t = !1;
77
82
  };
78
83
  }, []);
79
- let M = a(x, j), N = C !== void 0 || w !== void 0, P = S !== void 0 && S !== "presentation" && S !== "none", F = f(m), I = y || N || P ? "" : F ?? "", L = () => A(!0), R = O?.alt, z = R != null, B = z ? R : I, V = {
80
- "aria-describedby": T,
81
- "aria-description": ae,
82
- "aria-details": oe
83
- }, H = !y && !N && !P && typeof B == "string" && B.trim() !== "", U = H ? V : {}, W = null;
84
- if (!se) {
85
- if (typeof D == "string") W = /* @__PURE__ */ c("img", {
84
+ let fe = a(b, M), N = S !== void 0 || C !== void 0, P = x !== void 0 && x !== "presentation" && x !== "none", F = u(f), I = v || N || P ? "" : F ?? "", L = () => j(!0), R = O?.alt, z = R != null, B = z ? R : I, V = {
85
+ "aria-describedby": w,
86
+ "aria-description": ce,
87
+ "aria-details": le
88
+ }, H = !v && !N && !P && typeof B == "string" && B.trim() !== "", U = H ? V : {}, W = null;
89
+ if (!A) {
90
+ if (typeof D == "string") W = /* @__PURE__ */ s("img", {
86
91
  src: D,
87
92
  alt: I,
88
93
  ...U,
89
- className: e(i.image, d),
94
+ className: e(i.image, l),
90
95
  onError: L
91
96
  });
92
97
  else if (D !== void 0) {
93
98
  let n = { onError: r(O?.onError, L) };
94
99
  if (z || (n.alt = I), H) {
95
100
  let e = O?.["aria-describedby"];
96
- n["aria-describedby"] = o(T, typeof e == "string" ? e : void 0);
101
+ n["aria-describedby"] = ee(w, typeof e == "string" ? e : void 0);
97
102
  }
98
- let a = s.isValidElement(D) ? s.cloneElement(D, n) : O ? {
103
+ let a = o.isValidElement(D) ? o.cloneElement(D, n) : O ? {
99
104
  ...D,
100
105
  ...n
101
106
  } : D;
102
- W = t(a, "img", e(i.image, d), {
107
+ W = t(a, "img", e(i.image, l), {
103
108
  alt: I,
104
109
  ...U
105
110
  });
106
- } else p && (W = /* @__PURE__ */ c("img", {
107
- src: p,
111
+ } else d && (W = /* @__PURE__ */ s("img", {
112
+ src: d,
108
113
  alt: I,
109
114
  ...U,
110
- className: e(i.image, d),
115
+ className: e(i.image, l),
111
116
  onError: L
112
117
  }));
113
118
  }
114
- let G = W !== null && H ? {} : V, K = W === null && g && n(g) ? t(g, "span", e(i.icon, "inline-flex"), { "aria-hidden": !0 }) : null, q = W === null && K === null && m ? te(m) : "", J, Y;
115
- W === null ? K === null ? q ? (J = /* @__PURE__ */ c("span", {
119
+ let G = W !== null && H ? {} : V, K = W === null && h && n(h) ? t(h, "span", e(i.icon, "inline-flex"), { "aria-hidden": !0 }) : null, q = W === null && K === null && f ? ae(f) : "", J, Y;
120
+ W === null ? K === null ? q ? (J = /* @__PURE__ */ s("span", {
116
121
  "aria-hidden": "true",
117
122
  className: i.initials,
118
123
  children: q
119
- }), Y = "bg-primary text-primary-foreground") : (J = /* @__PURE__ */ c(ee, {
124
+ }), Y = "bg-primary text-primary-foreground") : (J = /* @__PURE__ */ s(te, {
120
125
  size: "60%",
121
126
  className: i.icon
122
127
  }), Y = "bg-muted text-muted-foreground") : (J = K, Y = "bg-muted text-muted-foreground") : J = W;
123
- let ue = W !== null && P && typeof B == "string" ? f(B) : void 0, de = typeof R == "string" ? f(R) : void 0, X = C ?? (W === null ? F ?? de : P ? ue ?? F : void 0), Z;
124
- Z = y ? {
128
+ let pe = W !== null && P && typeof B == "string" ? u(B) : void 0, me = typeof R == "string" ? u(R) : void 0, X = S ?? (W === null ? F ?? me : P ? pe ?? F : void 0), Z;
129
+ Z = v ? {
125
130
  "aria-hidden": !0,
126
131
  ...G
127
- } : X !== void 0 || w !== void 0 ? {
128
- role: S ?? "img",
132
+ } : X !== void 0 || C !== void 0 ? {
133
+ role: x ?? "img",
129
134
  "aria-label": X,
130
- "aria-labelledby": w,
135
+ "aria-labelledby": C,
131
136
  ...G
132
- } : W !== null || S !== void 0 ? {
133
- role: S,
137
+ } : W !== null || x !== void 0 ? {
138
+ role: x,
134
139
  ...G
135
140
  } : {
136
141
  "aria-hidden": !0,
137
142
  ...G
138
143
  };
139
- let Q = v && n(v) ? t(v, "span", e(i.badge, "absolute bottom-0 end-0 inline-flex")) : null, fe = Q !== null, $ = e(i.visual, "inline-flex items-center justify-center rounded-full overflow-hidden shrink-0 font-bold", u[h], Y);
140
- return fe ? /* @__PURE__ */ l("span", {
141
- ref: x,
142
- ...E,
143
- className: e(i.root, "relative inline-flex shrink-0", b),
144
- children: [/* @__PURE__ */ c("span", {
145
- ref: j,
144
+ let Q = _ && n(_) ? t(_, "span", e(i.badge, "absolute bottom-0 end-0 inline-flex")) : null, he = Q !== null, ge = m === void 0 ? E ? ie[E.size] : c.medium : c[m], $ = e(i.visual, "inline-flex items-center justify-center rounded-full overflow-hidden shrink-0 font-bold", ge, Y);
145
+ return he ? /* @__PURE__ */ re("span", {
146
+ ref: b,
147
+ ...T,
148
+ className: e(i.root, "relative inline-flex shrink-0", y),
149
+ children: [/* @__PURE__ */ s("span", {
150
+ ref: M,
146
151
  ...Z,
147
152
  className: $,
148
153
  children: J
149
154
  }), Q]
150
- }) : /* @__PURE__ */ c("span", {
151
- ref: M,
155
+ }) : /* @__PURE__ */ s("span", {
156
+ ref: fe,
152
157
  ...Z,
153
- ...E,
154
- className: e(i.root, $, b),
158
+ ...T,
159
+ className: e(i.root, $, y),
155
160
  children: J
156
161
  });
157
162
  };
158
- h.displayName = "Avatar";
163
+ m.displayName = "Avatar";
159
164
  //#endregion
160
- export { h as Avatar, u as avatarSizeClasses };
165
+ export { m as Avatar, c as avatarSizeClasses };
161
166
 
162
167
  //# sourceMappingURL=Avatar.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.mjs","names":["React","avatarSizeClasses","IMAGE_CLASS","getInitials","parts","name","normaliseName","readSlotProps","slot","getImageKey","imageSlot","src","element","slotProps","isPlainObject","value","proto","sameKeyPart","a","b","keys","k","sameImageKey","part","i","Avatar","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaDescription","ariaDetails","rest","image","imageKey","failed","setFailed","prevImageKey","setPrevImageKey","visualRef","img","active","checkedSrc","checkedSrcSet","markFailed","rootVisualRef","useMergedRefs","ref","hasConsumerName","roleCarriesName","role","normalisedName","imageAlt","decorative","handleError","ownAlt","hasOwnAlt","renderedAlt","description","imageIsNamed","imageDescription","imageNode","cn","avatarClassNames","overrides","composeEventHandlers","ownIds","joinIds","renderSlot","visualDescription","iconNode","icon","slotRendersContent","initials","content","colorClass","PersonIcon","imageName","slotAltName","label","a11yProps","badgeNode","badge","hasBadge","visualClassName","size","className"],"sources":["../../../src/components/data-display/Avatar.tsx"],"sourcesContent":["import * as React from 'react';\nimport { joinIds } from '../../lib/aria';\nimport { cn } from '../../lib/cn';\nimport { avatarClassNames } from '../../lib/classNames';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { PersonIcon } from '../../lib/icons';\nimport type { Size, Slot } from '../../lib/types';\nimport { renderSlot, slotRendersContent } from '../../lib/slot';\n\n/** Properties for the Avatar component. */\nexport interface AvatarProps extends React.HTMLAttributes<HTMLSpanElement> {\n /**\n * URL of the avatar image. When it fails to load (also before hydration, for server-rendered\n * markup), the avatar falls back to its icon or initials; a new `src` is tried again.\n */\n src?: string;\n /**\n * Full name of the person. It names the avatar for assistive technology (the image `alt`; in\n * initials and icon mode, or with a consumer `role`, the avatar's `aria-label`, with\n * `role=\"img\"` unless `role` is given) and generates the initials shown when there is no image.\n */\n name?: string;\n /** Size of the avatar.\n * @default 'medium'\n */\n size?: Size;\n /**\n * Icon shown instead of the initials when there is no image. Rendered in an `aria-hidden`\n * `<span>` (a slot object can override its attributes). A falsy value (`null`, `false`, `''`,\n * `0`, `NaN`, e.g. `icon={count && <Icon />}`) counts as no icon, as in 0.4, and so does an\n * array, `Set` or generator whose items render nothing. Without `icon` and without a usable\n * `name`, a generic person glyph is shown.\n */\n icon?: Slot<'span'>;\n /**\n * Custom image. Accepts a URL string (treated like `src`), an element (rendered as the image\n * itself, e.g. `<img>` or a framework image component) or an object of `<img>` attributes\n * (`{ src, alt, … }`). Takes precedence over `src`; its `alt` defaults to `name` (an `alt` that\n * is `undefined` counts as not given). When its alt names the avatar, the avatar's\n * `aria-describedby` ids are joined with the slot's own, while the slot's own `aria-description`\n * and `aria-details` win over the avatar's. When the image fails to load, an avatar without a\n * `name` keeps the name of the slot's own `alt`. After a load failure, a new image is tried\n * again: another `src` or `srcSet` of any type (an equal inline object is the same image), or\n * for an element slot another component type or `key`.\n */\n image?: Slot<'img'>;\n /**\n * Badge shown at the bottom end corner, e.g. `<PresenceBadge status=\"busy\" />`. With a badge\n * the avatar is wrapped in an outer `<span>` that receives `ref`, `className` and the other\n * props; `role`, `aria-label`, `aria-labelledby`, `aria-describedby`, `aria-description` and\n * `aria-details` stay on the avatar visual, so the badge keeps its own accessible name. A falsy\n * value (`null`, `false`, `''`, `0`, `NaN`, e.g. `badge={count && <CounterBadge count={count} />}`)\n * counts as no badge, as in 0.4, and so does an array, `Set` or generator whose items render\n * nothing: the avatar then renders without the wrapper.\n */\n badge?: Slot<'span'>;\n /**\n * Hides the avatar visual from assistive technology (`aria-hidden`, empty image `alt`, no\n * `role=\"img\"`). Use it when the name is already shown next to the avatar (Persona). A badge\n * stays exposed.\n * @default false\n */\n decorative?: boolean;\n /** Ref to the root `<span>`: the avatar itself, or the badge wrapper when `badge` is set. */\n ref?: React.Ref<HTMLSpanElement>;\n}\n\n/**\n * Width, height and text size classes of the avatar per `size`. Module-only (not in the barrel):\n * AvatarGroup sizes its overflow button with the same classes, so the two always match.\n */\nexport const avatarSizeClasses: Readonly<Record<Size, string>> = {\n 'extra-small': 'w-6 h-6 text-[10px]', // 24px\n small: 'w-8 h-8 text-xs', // 32px\n medium: 'w-10 h-10 text-sm', // 40px\n large: 'w-12 h-12 text-base', // 48px\n 'extra-large': 'w-14 h-14 text-lg', // 56px\n};\n\nconst IMAGE_CLASS = 'w-full h-full object-cover';\n\n/** First letter of the first and last word, upper-cased; `''` for a blank name. */\nfunction getInitials(name: string): string {\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return '';\n const first = Array.from(parts[0]!)[0] ?? '';\n const last = parts.length > 1 ? (Array.from(parts[parts.length - 1]!)[0] ?? '') : '';\n return (first + last).toUpperCase();\n}\n\n/** A name with its whitespace collapsed, or `undefined` when it is blank. */\nfunction normaliseName(name: string | undefined): string | undefined {\n return name?.trim().replace(/\\s+/g, ' ') || undefined;\n}\n\ntype ImageErrorHandler = React.ReactEventHandler<HTMLImageElement>;\n\n/** Description props that go to the element carrying the avatar's name (data-display#19). */\ntype DescriptionProps = Pick<\n React.HTMLAttributes<HTMLElement>,\n 'aria-describedby' | 'aria-description' | 'aria-details'\n>;\n\n/** Props the avatar sets on an element or object image slot, over the slot's own. */\ninterface SlotOverrides {\n onError: ImageErrorHandler;\n alt?: string;\n 'aria-describedby'?: string;\n}\n\n/** The props of an element or object image slot that the avatar reads. */\ninterface ImageSlotProps {\n src?: unknown;\n srcSet?: unknown;\n alt?: unknown;\n onError?: unknown;\n 'aria-describedby'?: unknown;\n}\n\n/** The props of an element or object image slot (to read its `src`, `alt` and handlers). */\nfunction readSlotProps(slot: unknown): ImageSlotProps | undefined {\n if (React.isValidElement(slot)) return slot.props as ImageSlotProps;\n if (typeof slot === 'object' && slot !== null && !(Symbol.iterator in slot)) {\n return slot as ImageSlotProps;\n }\n return undefined;\n}\n\n/**\n * What identifies the image, so a load failure is kept for it and a new image is tried again\n * (data-display#4): the `src` and `srcSet`, of any type (a framework image component may take a\n * static-import object), and for an element slot also its type and `key`.\n */\ntype ImageKey = readonly [type: unknown, key: unknown, src: unknown, srcSet: unknown];\n\nfunction getImageKey(\n imageSlot: unknown,\n slotProps: ImageSlotProps | undefined,\n src: string | undefined,\n): ImageKey {\n if (imageSlot === undefined) return [undefined, undefined, src || undefined, undefined];\n if (typeof imageSlot === 'string') return [undefined, undefined, imageSlot, undefined];\n const element = React.isValidElement(imageSlot) ? imageSlot : undefined;\n return [element?.type, element?.key, slotProps?.src, slotProps?.srcSet];\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null) return false;\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n/** Same value, or plain objects with the same entries (an inline `src={{ … }}` on each render). */\nfunction sameKeyPart(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true;\n if (!isPlainObject(a) || !isPlainObject(b)) return false;\n const keys = Object.keys(a);\n return (\n keys.length === Object.keys(b).length &&\n keys.every((k) => Object.prototype.hasOwnProperty.call(b, k) && Object.is(a[k], b[k]))\n );\n}\n\nfunction sameImageKey(a: ImageKey, b: ImageKey): boolean {\n return a.every((part, i) => sameKeyPart(part, b[i]));\n}\n\n/**\n * A circular picture of a person: their image, an icon, or the initials of their `name`.\n *\n * - **Image**: `image` (URL string, element or `{ src, alt }` object) or `src`. If the image fails\n * to load, the avatar falls back to `icon`, the initials or a person glyph, with their\n * background; a new image is tried again. A server-rendered image that failed before hydration\n * is detected after mount (settled without a natural size, confirmed by `decode()`).\n * - **Accessible name**: an image uses `name` (whitespace collapsed) as its `alt`, or `''` when the\n * name is blank. Without an image (none given, or it failed to load) the avatar is `role=\"img\"`\n * with `aria-label={name}` (without a name: the image slot's own `alt`) and the initials/icon\n * are hidden; without either (and without `aria-label`/`aria-labelledby`) it is decorative\n * (`aria-hidden`). A consumer `aria-label`, `aria-labelledby` or `role` (other than\n * `presentation`/`none`) puts the name on the avatar visual, and an image inside it gets\n * `alt=\"\"`. `decorative` hides it in every mode. `aria-describedby`, `aria-description` and\n * `aria-details` go to the element that carries the name: the `<img>` when a non-blank `alt`\n * names it, otherwise the avatar visual (never an `alt=\"\"` image).\n * - **Badge**: `badge` renders at the bottom end corner (logical, RTL-safe) as a sibling of the\n * avatar visual, so a `PresenceBadge` keeps its own name. With a badge, `ref`, `className` and\n * the rest props go to the outer wrapper.\n *\n * @example\n * <Avatar name=\"Jane Doe\" src=\"/jane.jpg\" badge={<PresenceBadge status=\"available\" />} />\n */\nexport const Avatar = ({\n src,\n name,\n size = 'medium',\n icon,\n image,\n badge,\n decorative = false,\n className,\n ref,\n role,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-description': ariaDescription,\n 'aria-details': ariaDetails,\n ...rest\n}: AvatarProps) => {\n const imageSlot =\n image === null || image === undefined || typeof image === 'boolean' || image === ''\n ? undefined\n : image;\n const slotProps = readSlotProps(imageSlot);\n const imageKey = getImageKey(imageSlot, slotProps, src);\n\n // Load failure of the current image; a new image is tried again (C-HOOKS: adjust state during\n // render on prop change).\n const [failed, setFailed] = React.useState(false);\n const [prevImageKey, setPrevImageKey] = React.useState(imageKey);\n if (!sameImageKey(prevImageKey, imageKey)) {\n setPrevImageKey(imageKey);\n setFailed(false);\n }\n\n // An image that failed before hydration (a fast 404 of server-rendered markup) never reaches\n // `onError`: React attaches the listener while hydrating and does not replay the event. After\n // mount, a settled image without a natural size is broken, unless it is an SVG without one, so\n // `decode()` (which rejects for a broken image) confirms it where the browser supports it. Later\n // images, rendered by the client, report their errors through `onError`.\n const visualRef = React.useRef<HTMLSpanElement>(null);\n React.useLayoutEffect(() => {\n const img = visualRef.current?.querySelector('img');\n if (!img || !img.complete || img.naturalWidth !== 0) return;\n let active = true;\n const checkedSrc = img.getAttribute('src');\n const checkedSrcSet = img.getAttribute('srcset');\n const markFailed = () => {\n // Deferred (C-HOOKS); skipped if the image was replaced or got another source meanwhile.\n if (\n active &&\n img.isConnected &&\n img.getAttribute('src') === checkedSrc &&\n img.getAttribute('srcset') === checkedSrcSet\n ) {\n setFailed(true);\n }\n };\n if (typeof img.decode === 'function') img.decode().then(undefined, markFailed);\n else queueMicrotask(markFailed);\n return () => {\n active = false;\n };\n }, []);\n const rootVisualRef = useMergedRefs(ref, visualRef);\n\n const hasConsumerName = ariaLabel !== undefined || ariaLabelledBy !== undefined;\n // A consumer role goes to the visual span together with the name (data-display#19), so the\n // image inside it is presentational (`alt=\"\"`), as with a consumer `aria-label`: the children\n // of `role=\"img\"` are not exposed. A presentational role (`presentation`, `none`) cannot carry\n // a name, so the image keeps it.\n const roleCarriesName = role !== undefined && role !== 'presentation' && role !== 'none';\n const normalisedName = normaliseName(name);\n const imageAlt = decorative || hasConsumerName || roleCarriesName ? '' : (normalisedName ?? '');\n const handleError: ImageErrorHandler = () => setFailed(true);\n\n // The alt text the image renders with: an element or object slot's own `alt` wins over ours. An\n // `alt` that is `undefined` (an optional `alt: user.photoAlt`, a wrapper forwarding `alt={alt}`)\n // or `null` is not given, so ours applies (the slot's own value would otherwise override it).\n const ownAlt = slotProps?.alt;\n const hasOwnAlt = ownAlt !== undefined && ownAlt !== null;\n const renderedAlt: unknown = hasOwnAlt ? ownAlt : imageAlt;\n\n // The description goes to the element that carries the name: the image itself when a non-blank\n // `alt` names it (the visual span then has no role, or a presentational one), otherwise the\n // visual span. An image with an empty `alt` is presentational, and a description on it would\n // conflict with that role.\n const description: DescriptionProps = {\n 'aria-describedby': ariaDescribedBy,\n 'aria-description': ariaDescription,\n 'aria-details': ariaDetails,\n };\n const imageIsNamed =\n !decorative &&\n !hasConsumerName &&\n !roleCarriesName &&\n typeof renderedAlt === 'string' &&\n renderedAlt.trim() !== '';\n const imageDescription: DescriptionProps = imageIsNamed ? description : {};\n\n let imageNode: React.ReactNode = null;\n if (!failed) {\n if (typeof imageSlot === 'string') {\n imageNode = (\n <img\n src={imageSlot}\n alt={imageAlt}\n {...imageDescription}\n className={cn(avatarClassNames.image, IMAGE_CLASS)}\n onError={handleError}\n />\n );\n } else if (imageSlot !== undefined) {\n // The slot's own props win over renderSlot's defaults, so the composed `onError`, the\n // default `alt` (when the slot gives none) and the joined `aria-describedby` (the avatar's\n // ids, then the slot's) are set on the slot itself. A slot's own `aria-description` and\n // `aria-details` win over the avatar's.\n const overrides: SlotOverrides = {\n onError: composeEventHandlers(\n slotProps?.onError as ImageErrorHandler | undefined,\n handleError,\n ),\n };\n if (!hasOwnAlt) overrides.alt = imageAlt;\n if (imageIsNamed) {\n const ownIds = slotProps?.['aria-describedby'];\n overrides['aria-describedby'] = joinIds(\n ariaDescribedBy,\n typeof ownIds === 'string' ? ownIds : undefined,\n );\n }\n const slot = React.isValidElement(imageSlot)\n ? React.cloneElement(imageSlot as React.ReactElement<SlotOverrides>, overrides)\n : slotProps\n ? { ...(imageSlot as object), ...overrides }\n : imageSlot;\n imageNode = renderSlot(slot as Slot<'img'>, 'img', cn(avatarClassNames.image, IMAGE_CLASS), {\n alt: imageAlt,\n ...imageDescription,\n });\n } else if (src) {\n imageNode = (\n <img\n src={src}\n alt={imageAlt}\n {...imageDescription}\n className={cn(avatarClassNames.image, IMAGE_CLASS)}\n onError={handleError}\n />\n );\n }\n }\n const visualDescription = imageNode !== null && imageIsNamed ? {} : description;\n\n // A falsy icon (`icon={count && <Icon />}` with count 0) is no icon, as in 0.4, and so is a\n // collection whose items render nothing (`icon={items.map(…)}` mapping to nothing). The check\n // does not consume a generator: renderSlot still renders its items.\n const iconNode =\n imageNode === null && icon && slotRendersContent(icon)\n ? renderSlot(icon, 'span', cn(avatarClassNames.icon, 'inline-flex'), { 'aria-hidden': true })\n : null;\n const initials = imageNode === null && iconNode === null && name ? getInitials(name) : '';\n\n let content: React.ReactNode;\n let colorClass: string | undefined;\n if (imageNode !== null) {\n content = imageNode;\n } else if (iconNode !== null) {\n content = iconNode;\n colorClass = 'bg-muted text-muted-foreground';\n } else if (initials) {\n content = (\n <span aria-hidden=\"true\" className={avatarClassNames.initials}>\n {initials}\n </span>\n );\n colorClass = 'bg-primary text-primary-foreground';\n } else {\n content = <PersonIcon size=\"60%\" className={avatarClassNames.icon} />;\n colorClass = 'bg-muted text-muted-foreground';\n }\n\n // Accessible name of the avatar visual (data-display#19, #27). With a consumer role and an\n // image it is the name the image would carry: an element or object slot's own alt, else `name`.\n // Without an image (none given, or it failed to load) it is `name`, else the slot's own alt: an\n // avatar named only by its image alt keeps that name when the image fails.\n const imageName =\n imageNode !== null && roleCarriesName && typeof renderedAlt === 'string'\n ? normaliseName(renderedAlt)\n : undefined;\n const slotAltName = typeof ownAlt === 'string' ? normaliseName(ownAlt) : undefined;\n const label =\n ariaLabel ??\n (imageNode === null\n ? (normalisedName ?? slotAltName)\n : roleCarriesName\n ? (imageName ?? normalisedName)\n : undefined);\n let a11yProps: React.HTMLAttributes<HTMLSpanElement>;\n if (decorative) {\n a11yProps = { 'aria-hidden': true, ...visualDescription };\n } else if (label !== undefined || ariaLabelledBy !== undefined) {\n a11yProps = {\n role: role ?? 'img',\n 'aria-label': label,\n 'aria-labelledby': ariaLabelledBy,\n ...visualDescription,\n };\n } else if (imageNode !== null || role !== undefined) {\n a11yProps = { role, ...visualDescription };\n } else {\n a11yProps = { 'aria-hidden': true, ...visualDescription };\n }\n\n // A falsy or empty badge (`badge={count && <CounterBadge … />}` with count 0) is no badge, as in\n // 0.4 and like `icon`: no stray \"0\" in the corner, and no wrapper taking the root props.\n const badgeNode =\n badge && slotRendersContent(badge)\n ? renderSlot(badge, 'span', cn(avatarClassNames.badge, 'absolute bottom-0 end-0 inline-flex'))\n : null;\n const hasBadge = badgeNode !== null;\n\n const visualClassName = cn(\n avatarClassNames.visual,\n 'inline-flex items-center justify-center rounded-full overflow-hidden shrink-0 font-bold',\n avatarSizeClasses[size],\n colorClass,\n );\n\n if (!hasBadge) {\n return (\n <span\n ref={rootVisualRef}\n {...a11yProps}\n {...rest}\n className={cn(avatarClassNames.root, visualClassName, className)}\n >\n {content}\n </span>\n );\n }\n\n return (\n <span\n ref={ref}\n {...rest}\n className={cn(avatarClassNames.root, 'relative inline-flex shrink-0', className)}\n >\n <span ref={visualRef} {...a11yProps} className={visualClassName}>\n {content}\n </span>\n {badgeNode}\n </span>\n );\n};\n\nAvatar.displayName = 'Avatar';\n"],"mappings":"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"}
1
+ {"version":3,"file":"Avatar.mjs","names":["React","avatarSizeClasses","AVATAR_BOX_CLASSES","IMAGE_CLASS","getInitials","parts","name","normaliseName","readSlotProps","slot","getImageKey","imageSlot","src","element","slotProps","isPlainObject","value","proto","sameKeyPart","a","b","keys","k","sameImageKey","part","i","Avatar","sizeProp","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaDescription","ariaDetails","rest","box","AvatarSizeContext","image","imageKey","failed","setFailed","prevImageKey","setPrevImageKey","visualRef","img","active","checkedSrc","checkedSrcSet","markFailed","rootVisualRef","useMergedRefs","ref","hasConsumerName","roleCarriesName","role","normalisedName","imageAlt","decorative","handleError","ownAlt","hasOwnAlt","renderedAlt","description","imageIsNamed","imageDescription","imageNode","cn","avatarClassNames","overrides","composeEventHandlers","ownIds","joinIds","renderSlot","visualDescription","iconNode","icon","slotRendersContent","initials","content","colorClass","PersonIcon","imageName","slotAltName","label","a11yProps","badgeNode","badge","hasBadge","sizeClasses","visualClassName","className"],"sources":["../../../src/components/data-display/Avatar.tsx"],"sourcesContent":["import * as React from 'react';\nimport { joinIds } from '../../lib/aria';\nimport { cn } from '../../lib/cn';\nimport { avatarClassNames } from '../../lib/classNames';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { PersonIcon } from '../../lib/icons';\nimport type { Size, Slot } from '../../lib/types';\nimport { renderSlot, slotRendersContent } from '../../lib/slot';\nimport { AvatarSizeContext, type AvatarSizeContextValue } from './Avatar.context';\n\n/** Properties for the Avatar component. */\nexport interface AvatarProps extends React.HTMLAttributes<HTMLSpanElement> {\n /**\n * URL of the avatar image. When it fails to load (also before hydration, for server-rendered\n * markup), the avatar falls back to its icon or initials; a new `src` is tried again.\n */\n src?: string;\n /**\n * Full name of the person. It names the avatar for assistive technology (the image `alt`; in\n * initials and icon mode, or with a consumer `role`, the avatar's `aria-label`, with\n * `role=\"img\"` unless `role` is given) and generates the initials shown when there is no image.\n */\n name?: string;\n /**\n * Size of the avatar. Without it, an Avatar in the `media` of a tag (Tag, InteractionTag) takes\n * the tag's media box instead: 24, 20 or 16px by the tag's size.\n * @default 'medium'\n */\n size?: Size;\n /**\n * Icon shown instead of the initials when there is no image. Rendered in an `aria-hidden`\n * `<span>` (a slot object can override its attributes). A falsy value (`null`, `false`, `''`,\n * `0`, `NaN`, e.g. `icon={count && <Icon />}`) counts as no icon, as in 0.4, and so does an\n * array, `Set` or generator whose items render nothing. Without `icon` and without a usable\n * `name`, a generic person glyph is shown.\n */\n icon?: Slot<'span'>;\n /**\n * Custom image. Accepts a URL string (treated like `src`), an element (rendered as the image\n * itself, e.g. `<img>` or a framework image component) or an object of `<img>` attributes\n * (`{ src, alt, … }`). Takes precedence over `src`; its `alt` defaults to `name` (an `alt` that\n * is `undefined` counts as not given). When its alt names the avatar, the avatar's\n * `aria-describedby` ids are joined with the slot's own, while the slot's own `aria-description`\n * and `aria-details` win over the avatar's. When the image fails to load, an avatar without a\n * `name` keeps the name of the slot's own `alt`. After a load failure, a new image is tried\n * again: another `src` or `srcSet` of any type (an equal inline object is the same image), or\n * for an element slot another component type or `key`.\n */\n image?: Slot<'img'>;\n /**\n * Badge shown at the bottom end corner, e.g. `<PresenceBadge status=\"busy\" />`. With a badge\n * the avatar is wrapped in an outer `<span>` that receives `ref`, `className` and the other\n * props; `role`, `aria-label`, `aria-labelledby`, `aria-describedby`, `aria-description` and\n * `aria-details` stay on the avatar visual, so the badge keeps its own accessible name. A falsy\n * value (`null`, `false`, `''`, `0`, `NaN`, e.g. `badge={count && <CounterBadge count={count} />}`)\n * counts as no badge, as in 0.4, and so does an array, `Set` or generator whose items render\n * nothing: the avatar then renders without the wrapper.\n */\n badge?: Slot<'span'>;\n /**\n * Hides the avatar visual from assistive technology (`aria-hidden`, empty image `alt`, no\n * `role=\"img\"`). Use it when the name is already shown next to the avatar (Persona). A badge\n * stays exposed.\n * @default false\n */\n decorative?: boolean;\n /** Ref to the root `<span>`: the avatar itself, or the badge wrapper when `badge` is set. */\n ref?: React.Ref<HTMLSpanElement>;\n}\n\n/**\n * Width, height and text size classes of the avatar per `size`. Module-only (not in the barrel):\n * AvatarGroup sizes its overflow button with the same classes, so the two always match.\n */\nexport const avatarSizeClasses: Readonly<Record<Size, string>> = {\n 'extra-small': 'w-6 h-6 text-[10px]', // 24px\n small: 'w-8 h-8 text-xs', // 32px\n medium: 'w-10 h-10 text-sm', // 40px\n large: 'w-12 h-12 text-base', // 48px\n 'extra-large': 'w-14 h-14 text-lg', // 56px\n};\n\n/**\n * Width, height and text size classes of each box of {@link AvatarSizeContext}, for an Avatar\n * that sets no `size`: 24px is the `extra-small` size, 20px and 16px are internal boxes.\n */\nconst AVATAR_BOX_CLASSES: Readonly<Record<AvatarSizeContextValue['size'], string>> = {\n 24: avatarSizeClasses['extra-small'],\n 20: 'w-5 h-5 text-[10px]',\n 16: 'w-4 h-4 text-[10px]',\n};\n\nconst IMAGE_CLASS = 'w-full h-full object-cover';\n\n/** First letter of the first and last word, upper-cased; `''` for a blank name. */\nfunction getInitials(name: string): string {\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return '';\n const first = Array.from(parts[0]!)[0] ?? '';\n const last = parts.length > 1 ? (Array.from(parts[parts.length - 1]!)[0] ?? '') : '';\n return (first + last).toUpperCase();\n}\n\n/** A name with its whitespace collapsed, or `undefined` when it is blank. */\nfunction normaliseName(name: string | undefined): string | undefined {\n return name?.trim().replace(/\\s+/g, ' ') || undefined;\n}\n\ntype ImageErrorHandler = React.ReactEventHandler<HTMLImageElement>;\n\n/** Description props that go to the element carrying the avatar's name (data-display#19). */\ntype DescriptionProps = Pick<\n React.HTMLAttributes<HTMLElement>,\n 'aria-describedby' | 'aria-description' | 'aria-details'\n>;\n\n/** Props the avatar sets on an element or object image slot, over the slot's own. */\ninterface SlotOverrides {\n onError: ImageErrorHandler;\n alt?: string;\n 'aria-describedby'?: string;\n}\n\n/** The props of an element or object image slot that the avatar reads. */\ninterface ImageSlotProps {\n src?: unknown;\n srcSet?: unknown;\n alt?: unknown;\n onError?: unknown;\n 'aria-describedby'?: unknown;\n}\n\n/** The props of an element or object image slot (to read its `src`, `alt` and handlers). */\nfunction readSlotProps(slot: unknown): ImageSlotProps | undefined {\n if (React.isValidElement(slot)) return slot.props as ImageSlotProps;\n if (typeof slot === 'object' && slot !== null && !(Symbol.iterator in slot)) {\n return slot as ImageSlotProps;\n }\n return undefined;\n}\n\n/**\n * What identifies the image, so a load failure is kept for it and a new image is tried again\n * (data-display#4): the `src` and `srcSet`, of any type (a framework image component may take a\n * static-import object), and for an element slot also its type and `key`.\n */\ntype ImageKey = readonly [type: unknown, key: unknown, src: unknown, srcSet: unknown];\n\nfunction getImageKey(\n imageSlot: unknown,\n slotProps: ImageSlotProps | undefined,\n src: string | undefined,\n): ImageKey {\n if (imageSlot === undefined) return [undefined, undefined, src || undefined, undefined];\n if (typeof imageSlot === 'string') return [undefined, undefined, imageSlot, undefined];\n const element = React.isValidElement(imageSlot) ? imageSlot : undefined;\n return [element?.type, element?.key, slotProps?.src, slotProps?.srcSet];\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null) return false;\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n/** Same value, or plain objects with the same entries (an inline `src={{ … }}` on each render). */\nfunction sameKeyPart(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true;\n if (!isPlainObject(a) || !isPlainObject(b)) return false;\n const keys = Object.keys(a);\n return (\n keys.length === Object.keys(b).length &&\n keys.every((k) => Object.prototype.hasOwnProperty.call(b, k) && Object.is(a[k], b[k]))\n );\n}\n\nfunction sameImageKey(a: ImageKey, b: ImageKey): boolean {\n return a.every((part, i) => sameKeyPart(part, b[i]));\n}\n\n/**\n * A circular picture of a person: their image, an icon, or the initials of their `name`.\n *\n * - **Image**: `image` (URL string, element or `{ src, alt }` object) or `src`. If the image fails\n * to load, the avatar falls back to `icon`, the initials or a person glyph, with their\n * background; a new image is tried again. A server-rendered image that failed before hydration\n * is detected after mount (settled without a natural size, confirmed by `decode()`).\n * - **Accessible name**: an image uses `name` (whitespace collapsed) as its `alt`, or `''` when the\n * name is blank. Without an image (none given, or it failed to load) the avatar is `role=\"img\"`\n * with `aria-label={name}` (without a name: the image slot's own `alt`) and the initials/icon\n * are hidden; without either (and without `aria-label`/`aria-labelledby`) it is decorative\n * (`aria-hidden`). A consumer `aria-label`, `aria-labelledby` or `role` (other than\n * `presentation`/`none`) puts the name on the avatar visual, and an image inside it gets\n * `alt=\"\"`. `decorative` hides it in every mode. `aria-describedby`, `aria-description` and\n * `aria-details` go to the element that carries the name: the `<img>` when a non-blank `alt`\n * names it, otherwise the avatar visual (never an `alt=\"\"` image).\n * - **Badge**: `badge` renders at the bottom end corner (logical, RTL-safe) as a sibling of the\n * avatar visual, so a `PresenceBadge` keeps its own name. With a badge, `ref`, `className` and\n * the rest props go to the outer wrapper.\n *\n * @example\n * <Avatar name=\"Jane Doe\" src=\"/jane.jpg\" badge={<PresenceBadge status=\"available\" />} />\n */\nexport const Avatar = ({\n src,\n name,\n size: sizeProp,\n icon,\n image,\n badge,\n decorative = false,\n className,\n ref,\n role,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-description': ariaDescription,\n 'aria-details': ariaDetails,\n ...rest\n}: AvatarProps) => {\n // The media box of a surrounding Tag or InteractionTag, for an Avatar without its own `size`.\n const box = React.useContext(AvatarSizeContext);\n const imageSlot =\n image === null || image === undefined || typeof image === 'boolean' || image === ''\n ? undefined\n : image;\n const slotProps = readSlotProps(imageSlot);\n const imageKey = getImageKey(imageSlot, slotProps, src);\n\n // Load failure of the current image; a new image is tried again (C-HOOKS: adjust state during\n // render on prop change).\n const [failed, setFailed] = React.useState(false);\n const [prevImageKey, setPrevImageKey] = React.useState(imageKey);\n if (!sameImageKey(prevImageKey, imageKey)) {\n setPrevImageKey(imageKey);\n setFailed(false);\n }\n\n // An image that failed before hydration (a fast 404 of server-rendered markup) never reaches\n // `onError`: React attaches the listener while hydrating and does not replay the event. After\n // mount, a settled image without a natural size is broken, unless it is an SVG without one, so\n // `decode()` (which rejects for a broken image) confirms it where the browser supports it. Later\n // images, rendered by the client, report their errors through `onError`.\n const visualRef = React.useRef<HTMLSpanElement>(null);\n React.useLayoutEffect(() => {\n const img = visualRef.current?.querySelector('img');\n if (!img || !img.complete || img.naturalWidth !== 0) return;\n let active = true;\n const checkedSrc = img.getAttribute('src');\n const checkedSrcSet = img.getAttribute('srcset');\n const markFailed = () => {\n // Deferred (C-HOOKS); skipped if the image was replaced or got another source meanwhile.\n if (\n active &&\n img.isConnected &&\n img.getAttribute('src') === checkedSrc &&\n img.getAttribute('srcset') === checkedSrcSet\n ) {\n setFailed(true);\n }\n };\n if (typeof img.decode === 'function') img.decode().then(undefined, markFailed);\n else queueMicrotask(markFailed);\n return () => {\n active = false;\n };\n }, []);\n const rootVisualRef = useMergedRefs(ref, visualRef);\n\n const hasConsumerName = ariaLabel !== undefined || ariaLabelledBy !== undefined;\n // A consumer role goes to the visual span together with the name (data-display#19), so the\n // image inside it is presentational (`alt=\"\"`), as with a consumer `aria-label`: the children\n // of `role=\"img\"` are not exposed. A presentational role (`presentation`, `none`) cannot carry\n // a name, so the image keeps it.\n const roleCarriesName = role !== undefined && role !== 'presentation' && role !== 'none';\n const normalisedName = normaliseName(name);\n const imageAlt = decorative || hasConsumerName || roleCarriesName ? '' : (normalisedName ?? '');\n const handleError: ImageErrorHandler = () => setFailed(true);\n\n // The alt text the image renders with: an element or object slot's own `alt` wins over ours. An\n // `alt` that is `undefined` (an optional `alt: user.photoAlt`, a wrapper forwarding `alt={alt}`)\n // or `null` is not given, so ours applies (the slot's own value would otherwise override it).\n const ownAlt = slotProps?.alt;\n const hasOwnAlt = ownAlt !== undefined && ownAlt !== null;\n const renderedAlt: unknown = hasOwnAlt ? ownAlt : imageAlt;\n\n // The description goes to the element that carries the name: the image itself when a non-blank\n // `alt` names it (the visual span then has no role, or a presentational one), otherwise the\n // visual span. An image with an empty `alt` is presentational, and a description on it would\n // conflict with that role.\n const description: DescriptionProps = {\n 'aria-describedby': ariaDescribedBy,\n 'aria-description': ariaDescription,\n 'aria-details': ariaDetails,\n };\n const imageIsNamed =\n !decorative &&\n !hasConsumerName &&\n !roleCarriesName &&\n typeof renderedAlt === 'string' &&\n renderedAlt.trim() !== '';\n const imageDescription: DescriptionProps = imageIsNamed ? description : {};\n\n let imageNode: React.ReactNode = null;\n if (!failed) {\n if (typeof imageSlot === 'string') {\n imageNode = (\n <img\n src={imageSlot}\n alt={imageAlt}\n {...imageDescription}\n className={cn(avatarClassNames.image, IMAGE_CLASS)}\n onError={handleError}\n />\n );\n } else if (imageSlot !== undefined) {\n // The slot's own props win over renderSlot's defaults, so the composed `onError`, the\n // default `alt` (when the slot gives none) and the joined `aria-describedby` (the avatar's\n // ids, then the slot's) are set on the slot itself. A slot's own `aria-description` and\n // `aria-details` win over the avatar's.\n const overrides: SlotOverrides = {\n onError: composeEventHandlers(\n slotProps?.onError as ImageErrorHandler | undefined,\n handleError,\n ),\n };\n if (!hasOwnAlt) overrides.alt = imageAlt;\n if (imageIsNamed) {\n const ownIds = slotProps?.['aria-describedby'];\n overrides['aria-describedby'] = joinIds(\n ariaDescribedBy,\n typeof ownIds === 'string' ? ownIds : undefined,\n );\n }\n const slot = React.isValidElement(imageSlot)\n ? React.cloneElement(imageSlot as React.ReactElement<SlotOverrides>, overrides)\n : slotProps\n ? { ...(imageSlot as object), ...overrides }\n : imageSlot;\n imageNode = renderSlot(slot as Slot<'img'>, 'img', cn(avatarClassNames.image, IMAGE_CLASS), {\n alt: imageAlt,\n ...imageDescription,\n });\n } else if (src) {\n imageNode = (\n <img\n src={src}\n alt={imageAlt}\n {...imageDescription}\n className={cn(avatarClassNames.image, IMAGE_CLASS)}\n onError={handleError}\n />\n );\n }\n }\n const visualDescription = imageNode !== null && imageIsNamed ? {} : description;\n\n // A falsy icon (`icon={count && <Icon />}` with count 0) is no icon, as in 0.4, and so is a\n // collection whose items render nothing (`icon={items.map(…)}` mapping to nothing). The check\n // does not consume a generator: renderSlot still renders its items.\n const iconNode =\n imageNode === null && icon && slotRendersContent(icon)\n ? renderSlot(icon, 'span', cn(avatarClassNames.icon, 'inline-flex'), { 'aria-hidden': true })\n : null;\n const initials = imageNode === null && iconNode === null && name ? getInitials(name) : '';\n\n let content: React.ReactNode;\n let colorClass: string | undefined;\n if (imageNode !== null) {\n content = imageNode;\n } else if (iconNode !== null) {\n content = iconNode;\n colorClass = 'bg-muted text-muted-foreground';\n } else if (initials) {\n content = (\n <span aria-hidden=\"true\" className={avatarClassNames.initials}>\n {initials}\n </span>\n );\n colorClass = 'bg-primary text-primary-foreground';\n } else {\n content = <PersonIcon size=\"60%\" className={avatarClassNames.icon} />;\n colorClass = 'bg-muted text-muted-foreground';\n }\n\n // Accessible name of the avatar visual (data-display#19, #27). With a consumer role and an\n // image it is the name the image would carry: an element or object slot's own alt, else `name`.\n // Without an image (none given, or it failed to load) it is `name`, else the slot's own alt: an\n // avatar named only by its image alt keeps that name when the image fails.\n const imageName =\n imageNode !== null && roleCarriesName && typeof renderedAlt === 'string'\n ? normaliseName(renderedAlt)\n : undefined;\n const slotAltName = typeof ownAlt === 'string' ? normaliseName(ownAlt) : undefined;\n const label =\n ariaLabel ??\n (imageNode === null\n ? (normalisedName ?? slotAltName)\n : roleCarriesName\n ? (imageName ?? normalisedName)\n : undefined);\n let a11yProps: React.HTMLAttributes<HTMLSpanElement>;\n if (decorative) {\n a11yProps = { 'aria-hidden': true, ...visualDescription };\n } else if (label !== undefined || ariaLabelledBy !== undefined) {\n a11yProps = {\n role: role ?? 'img',\n 'aria-label': label,\n 'aria-labelledby': ariaLabelledBy,\n ...visualDescription,\n };\n } else if (imageNode !== null || role !== undefined) {\n a11yProps = { role, ...visualDescription };\n } else {\n a11yProps = { 'aria-hidden': true, ...visualDescription };\n }\n\n // A falsy or empty badge (`badge={count && <CounterBadge … />}` with count 0) is no badge, as in\n // 0.4 and like `icon`: no stray \"0\" in the corner, and no wrapper taking the root props.\n const badgeNode =\n badge && slotRendersContent(badge)\n ? renderSlot(badge, 'span', cn(avatarClassNames.badge, 'absolute bottom-0 end-0 inline-flex'))\n : null;\n const hasBadge = badgeNode !== null;\n\n // An own `size` wins; without one, the box of a surrounding tag's media, else medium. With a\n // badge the visual is sized, not the wrapper.\n const sizeClasses =\n sizeProp !== undefined\n ? avatarSizeClasses[sizeProp]\n : box\n ? AVATAR_BOX_CLASSES[box.size]\n : avatarSizeClasses.medium;\n const visualClassName = cn(\n avatarClassNames.visual,\n 'inline-flex items-center justify-center rounded-full overflow-hidden shrink-0 font-bold',\n sizeClasses,\n colorClass,\n );\n\n if (!hasBadge) {\n return (\n <span\n ref={rootVisualRef}\n {...a11yProps}\n {...rest}\n className={cn(avatarClassNames.root, visualClassName, className)}\n >\n {content}\n </span>\n );\n }\n\n return (\n <span\n ref={ref}\n {...rest}\n className={cn(avatarClassNames.root, 'relative inline-flex shrink-0', className)}\n >\n <span ref={visualRef} {...a11yProps} className={visualClassName}>\n {content}\n </span>\n {badgeNode}\n </span>\n );\n};\n\nAvatar.displayName = 'Avatar';\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/dev.cjs"),r=require("../../lib/slot.cjs"),i=require("../../lib/composeEventHandlers.cjs"),a=require("../../lib/classNames.cjs"),o=require("../../hooks/useEventCallback.cjs"),s=require("../../hooks/useId.cjs"),c=require("../../hooks/useMergedRefs.cjs"),l=require("../../lib/aria.cjs"),u=require("../../lib/styles.cjs"),d=require("../button/Button.slots.cjs"),f=require("../../lib/icons.cjs"),p=require("../../lib/labelInName.cjs"),m=require("../../lib/events.cjs"),h=require("./TagGroup.context.cjs"),g=require("./Avatar.context.cjs"),_=require("./tagStyles.cjs");let v=require("react");v=e.__toESM(v,1);let y=require("react/jsx-runtime");var b=()=>{};function x(){let e=0,t=!1,n=new Set,r=()=>{for(let e of n)e()};return{subscribe:e=>(n.add(e),()=>{n.delete(e)}),hasPrimary:()=>!t||e>0,register:()=>(e+=1,r(),()=>{--e,r()}),settle:()=>{t||(t=!0,r())}}}var S={subscribe:()=>b,hasPrimary:()=>!0,register:()=>b,settle:b},C=v.createContext(null);C.displayName=`InteractionTagContext`;var w={size:`medium`,shape:`circular`,look:`filled`,disabled:!1,selected:!1,pressed:void 0,dimDisabled:!0,primaryTextId:``,primaries:S,secondaryRef:null,dismiss:()=>{},toggle:()=>{}};function T(e){return v.useContext(C)||(n.reportMissingContext(e,`InteractionTag`),w)}function E(e,t){return typeof e==`string`&&Object.hasOwn(t,e)}function D(e,n){return t.cn(n?[_.INTERACTION_TAG_DISABLED_CLASSES,d.mergedAriaDisabledClasses]:_.INTERACTION_TAG_UNDIMMED_DISABLED_CLASSES,e&&u.forcedColors.disabled)}var O="InteractionTag: `selected` has no effect in a TagGroup that selects (`value`, `defaultValue` or `onValueChange`); the group's `value` decides.";function k(e,t){if(e)return t?d.MERGED_DISABLED_FOCUSABLE_PROPS:{disabled:!0}}var A=({value:e,appearance:r,size:i,shape:l,disabled:u=!1,selected:d,role:f,hidden:p,className:m,children:g,ref:b,...S})=>{let w=h.useTagGroupContext(),T=v.useRef(null),D=c.useMergedRefs(T,b),k=v.useRef(null),A=s.useId(`interaction-tag-text`),[j]=v.useState(x);v.useLayoutEffect(()=>{j.settle()},[j]);let M=E(i,_.tagSizeClasses)?i:w?.size??`medium`,N=E(r,_.tagAppearanceClasses)?r:w?.appearance??`filled`,P=E(l,_.tagShapeClasses)?l:w?.shape??`circular`,F=(w?.disabled??!1)||u,I=w?.dimDisabled??!0,L=h.useTagGroupItem(T,e),R=w?.selecting??!1,z=R?w?.isSelected(L)??!1:typeof d==`boolean`?d:void 0,B=z===!0,V=B&&!F?`selected`:N,H=R&&d!==void 0;v.useEffect(()=>{H&&n.warnOnce(`InteractionTag:selected-in-group`,O)},[H]);let U=o.useEventCallback(()=>{w?.dismiss(L),w?.deselect(L)}),W=o.useEventCallback(()=>{w?.toggle(L)}),G=w?.mode===`list`?`listitem`:void 0,K=e!==void 0&&(w?.hiddenValues?.has(e)??!1),q=v.useMemo(()=>({size:M,shape:P,look:V,disabled:F,selected:B,pressed:z,dimDisabled:I,primaryTextId:A,primaries:j,secondaryRef:k,dismiss:U,toggle:W}),[M,P,V,F,B,z,I,A,j,U,W]);return(0,y.jsx)(C.Provider,{value:q,children:(0,y.jsx)(`div`,{"data-appearance":N,"data-size":M,"data-shape":P,"data-selected":B?``:void 0,"data-disabled":F?``:void 0,"data-wave-tag-item":``,role:f??G,hidden:K||p,...S,ref:D,className:t.cn(a.interactionTagClassNames.root,`group/interaction-tag inline-flex items-stretch`,m),children:g})})};A.displayName=`InteractionTag`;var j=({media:e,icon:n,secondaryText:o,disabled:s=!1,"aria-pressed":c,className:l,children:d,onClick:f,onKeyDown:p,onFocus:b,onBlur:x,ref:S,...C})=>{let w=T(`InteractionTag.Primary`),{size:E,look:O}=w,A=w.disabled||s,j=h.useHeldFocus(A),M=w.primaries.register;v.useLayoutEffect(()=>M(),[M]);let N=r.slotRendersContent(e),P=r.slotRendersContent(n),F=r.materialiseSlotContent(o),I=r.slotRendersContent(F),L=v.useMemo(()=>({size:_.TAG_AVATAR_SIZE[E]}),[E]),R=e=>{!A&&m.isOwnEvent(e)&&w.toggle()},z=e=>{if(A||e.target!==e.currentTarget||!h.isDismissKey(e))return;let t=w.secondaryRef?.current;t&&!t.disabled&&(e.preventDefault(),t.click())},B=(0,y.jsx)(`span`,{id:w.primaryTextId||void 0,className:t.cn(a.interactionTagPrimaryClassNames.primaryText,I&&`text-caption-1 leading-3.5`),children:d});return(0,y.jsxs)(`button`,{type:`button`,"aria-pressed":w.pressed??c,"data-selected":w.selected?``:void 0,...C,ref:S,onClick:i.composeEventHandlers(f,R),...k(A,j.held),onKeyDown:i.composeEventHandlers(p,z),onFocus:i.composeEventHandlers(b,j.onFocus,{checkDefaultPrevented:!1}),onBlur:i.composeEventHandlers(x,j.onBlur,{checkDefaultPrevented:!1}),className:t.cn(a.interactionTagPrimaryClassNames.root,_.INTERACTION_TAG_BUTTON_BASE_CLASSES,_.INTERACTION_TAG_PRIMARY_BASE_CLASSES,_.tagSizeClasses[E],_.tagStartInsetClasses[E][N?`media`:P?`icon`:`text`],_.interactionTagPrimaryEndInsetClasses[E],_.interactionTagLookClasses[O],O===`selected`&&[u.forcedColors.selectedContainer,`forced-colors:border-[Highlight]`],_.tagShapeClasses[w.shape],_.INTERACTION_TAG_PRIMARY_JOINED_CLASSES,D(A,w.dimDisabled),u.focusRing,E===`extra-small`&&`before:absolute before:inset-x-0 before:-inset-y-0.5`,l),children:[N&&(0,y.jsx)(g.AvatarSizeContext.Provider,{value:L,children:r.renderSlot(e,`span`,t.cn(a.interactionTagPrimaryClassNames.media,_.tagMediaClasses[E]),{"aria-hidden":!0})}),P&&r.renderSlot(n,`span`,t.cn(a.interactionTagPrimaryClassNames.icon,_.tagIconClasses[E]),{"aria-hidden":!0}),I?(0,y.jsxs)(`span`,{className:_.TAG_TEXT_COLUMN_CLASSES,children:[B,` `,(0,y.jsx)(`span`,{className:t.cn(a.interactionTagPrimaryClassNames.secondaryText,_.TAG_SECONDARY_TEXT_CLASSES),children:F})]}):B]})};j.displayName=`InteractionTagPrimary`;var M="InteractionTag.Secondary: its content received a button. A button cannot contain a button: its children became the content of the Dismiss button and its props were dropped. Pass icon content, and handle the dismissal in `onClick` or in the TagGroup's `onDismiss`.",N=({dismissLabel:e=`Dismiss`,disabled:o=!1,"aria-label":g,"aria-labelledby":x,className:S,children:C,onClick:w,onKeyDown:E,onFocus:O,onBlur:A,ref:j,...N})=>{let P=T(`InteractionTag.Secondary`),{size:F,look:I}=P,L=P.disabled||o,R=h.useHeldFocus(L),z=s.useId(`interaction-tag-dismiss`),B=s.useId(`interaction-tag-dismiss-content`),V=v.useRef(null),H=c.useMergedRefs(V,P.secondaryRef,j);h.useDismissControlFocus(V);let{glyph:U,button:W}=d.unwrapButtonGlyph(C);v.useEffect(()=>{W&&n.warnOnce(`InteractionTag.Secondary:button-child`,M)},[W]);let G=r.materialiseSlotContent(U),K=r.slotRendersContent(G),q=K&&p.hasTextLabel(G),[J,Y]=v.useState(null),X=v.useCallback(e=>J?p.observeTextLabel(J,e):b,[J]),Z=v.useSyncExternalStore(X,()=>J?p.hasRenderedTextLabel(J):q,()=>q),Q=K&&Z,ee=v.useSyncExternalStore(P.primaries.subscribe,P.primaries.hasPrimary,()=>!0),$=g!==void 0||x!==void 0,te=$?x:l.joinIds(Q?B:z,ee?P.primaryTextId:void 0),ne=e=>{m.isOwnEvent(e)&&P.dismiss()},re=e=>{if(e.target===e.currentTarget){if(h.isRepeatedActivation(e)){e.preventDefault();return}h.isDismissKey(e)&&(e.preventDefault(),e.currentTarget.click())}};return(0,y.jsxs)(`button`,{type:`button`,"data-wave-tag-dismiss":``,"data-selected":P.selected?``:void 0,...N,ref:H,"aria-label":g,"aria-labelledby":te,onClick:i.composeEventHandlers(w,ne),...k(L,R.held),onKeyDown:i.composeEventHandlers(E,re),onFocus:i.composeEventHandlers(O,R.onFocus,{checkDefaultPrevented:!1}),onBlur:i.composeEventHandlers(A,R.onBlur,{checkDefaultPrevented:!1}),className:t.cn(a.interactionTagSecondaryClassNames.root,_.INTERACTION_TAG_BUTTON_BASE_CLASSES,_.INTERACTION_TAG_SECONDARY_BASE_CLASSES,_.interactionTagSecondarySizeClasses[F],_.interactionTagLookClasses[I],I===`selected`&&[u.forcedColors.selectedContainer,`forced-colors:border-[Highlight]`],_.interactionTagDividerClasses[I],_.interactionTagSecondaryShapeClasses[P.shape],D(L,P.dimDisabled),u.focusRing,F===`extra-small`&&`before:absolute before:inset-x-0 before:-inset-y-0.5`,S),children:[!$&&(0,y.jsx)(`span`,{id:z,className:`sr-only`,children:e}),K?(0,y.jsx)(`span`,{id:B,ref:Y,className:t.cn(a.interactionTagSecondaryClassNames.dismissIcon,`inline-flex items-center justify-center`,Q&&`px-1.5`),children:G}):(0,y.jsx)(f.DismissIcon,{size:_.TAG_DISMISS_GLYPH_SIZE[F],className:a.interactionTagSecondaryClassNames.dismissIcon})]})};N.displayName=`InteractionTagSecondary`;var P=Object.assign(A,{Primary:j,Secondary:N});exports.InteractionTag=P,exports.InteractionTagPrimary=j,exports.InteractionTagSecondary=N;
2
+ //# sourceMappingURL=InteractionTag.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InteractionTag.cjs","names":["React","cn","INTERACTION_TAG_DISABLED_CLASSES","mergedAriaDisabledClasses","INTERACTION_TAG_UNDIMMED_DISABLED_CLASSES","forcedColors","MERGED_DISABLED_FOCUSABLE_PROPS","useTagGroupContext","useMergedRefs","useId","tagSizeClasses","tagAppearanceClasses","tagShapeClasses","useTagGroupItem","useEventCallback","interactionTagClassNames","useHeldFocus","slotRendersContent","materialiseSlotContent","TAG_AVATAR_SIZE","isOwnEvent","isDismissKey","interactionTagPrimaryClassNames","composeEventHandlers","INTERACTION_TAG_BUTTON_BASE_CLASSES","INTERACTION_TAG_PRIMARY_BASE_CLASSES","tagStartInsetClasses","interactionTagPrimaryEndInsetClasses","interactionTagLookClasses","INTERACTION_TAG_PRIMARY_JOINED_CLASSES","focusRing","AvatarSizeContext","renderSlot","tagMediaClasses","tagIconClasses","TAG_TEXT_COLUMN_CLASSES","TAG_SECONDARY_TEXT_CLASSES","unwrapButtonGlyph","hasTextLabel","observeTextLabel","hasRenderedTextLabel","joinIds","isRepeatedActivation","interactionTagSecondaryClassNames","INTERACTION_TAG_SECONDARY_BASE_CLASSES","interactionTagSecondarySizeClasses","interactionTagDividerClasses","interactionTagSecondaryShapeClasses","DismissIcon","TAG_DISMISS_GLYPH_SIZE","require_runtime","require_cn","require_dev","require_slot","require_composeEventHandlers","require_classNames","require_useEventCallback","require_useId","require_useMergedRefs","require_aria","require_styles","require_Button_slots","require_icons","require_labelInName","require_events","require_TagGroup_context","require_Avatar_context","require_tagStyles","react","react_jsx_runtime","noop","createPrimaryRegistry","count","settled","listeners","notify","listener","onChange","INERT_PRIMARY_REGISTRY","InteractionTagContext","INERT_CONTEXT","useInteractionTagContext","componentName","isKeyOf","value","table","disabledClasses","dimDisabled","disabled","SELECTED_IN_GROUP_MESSAGE","buttonStateProps","held","InteractionTagRoot","appearanceProp","sizeProp","shapeProp","disabledProp","selectedProp","rest","group","rootRef","mergedRef","ref","secondaryRef","primaryTextId","primaries","size","appearance","shape","reportedValue","selecting","pressed","selected","look","selectedIgnored","dismiss","toggle","listItemRole","hiddenByHost","context","role","hidden","className","InteractionTagPrimary","ariaPressed","tag","hold","registerPrimary","hasMedia","media","hasIcon","icon","secondary","secondaryText","hasSecondary","avatarBox","handleClick","event","handleKeyDown","secondaryButton","primaryText","onClick","onKeyDown","onFocus","onBlur","BUTTON_CHILD_MESSAGE","InteractionTagSecondary","ariaLabel","ariaLabelledBy","dismissLabelId","contentId","ownRef","unwrapped","children","content","glyph","hasContent","literalTextLabel","labelTarget","setLabelTarget","subscribeToContent","contentHasTextLabel","hasLabel","hasPrimary","namedByConsumer","labelledBy","dismissLabel","InteractionTag"],"sources":["../../../src/components/data-display/InteractionTag.tsx"],"sourcesContent":["import * as React from 'react';\nimport { joinIds } from '../../lib/aria';\nimport { cn } from '../../lib/cn';\nimport {\n interactionTagClassNames,\n interactionTagPrimaryClassNames,\n interactionTagSecondaryClassNames,\n} from '../../lib/classNames';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { reportMissingContext, warnOnce } from '../../lib/dev';\nimport { isOwnEvent } from '../../lib/events';\nimport { DismissIcon } from '../../lib/icons';\nimport { hasRenderedTextLabel, hasTextLabel, observeTextLabel } from '../../lib/labelInName';\nimport { materialiseSlotContent, renderSlot, slotRendersContent } from '../../lib/slot';\nimport type { Slot } from '../../lib/slot';\nimport { focusRing, forcedColors } from '../../lib/styles';\nimport type { TagAppearance, TagShape, TagSize } from '../../lib/types';\nimport { useEventCallback } from '../../hooks/useEventCallback';\nimport { useId } from '../../hooks/useId';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport {\n MERGED_DISABLED_FOCUSABLE_PROPS,\n mergedAriaDisabledClasses,\n unwrapButtonGlyph,\n} from '../button/Button.slots';\nimport { AvatarSizeContext } from './Avatar.context';\nimport {\n isDismissKey,\n isRepeatedActivation,\n useDismissControlFocus,\n useHeldFocus,\n useTagGroupContext,\n useTagGroupItem,\n} from './TagGroup.context';\nimport {\n INTERACTION_TAG_BUTTON_BASE_CLASSES,\n INTERACTION_TAG_DISABLED_CLASSES,\n INTERACTION_TAG_EXTRA_SMALL_HIT_CLASSES,\n INTERACTION_TAG_PRIMARY_BASE_CLASSES,\n INTERACTION_TAG_PRIMARY_JOINED_CLASSES,\n INTERACTION_TAG_SECONDARY_BASE_CLASSES,\n INTERACTION_TAG_SECONDARY_LABEL_CLASSES,\n INTERACTION_TAG_SELECTED_FORCED_COLORS,\n INTERACTION_TAG_UNDIMMED_DISABLED_CLASSES,\n TAG_AVATAR_SIZE,\n TAG_DISMISS_GLYPH_SIZE,\n TAG_PRIMARY_TEXT_TWO_LINE_CLASSES,\n TAG_SECONDARY_TEXT_CLASSES,\n TAG_TEXT_COLUMN_CLASSES,\n interactionTagDividerClasses,\n interactionTagLookClasses,\n interactionTagPrimaryEndInsetClasses,\n interactionTagSecondaryShapeClasses,\n interactionTagSecondarySizeClasses,\n tagAppearanceClasses,\n tagIconClasses,\n tagMediaClasses,\n tagShapeClasses,\n tagSizeClasses,\n tagStartInsetClasses,\n} from './tagStyles';\nimport type { TagLook } from './tagStyles';\n\n/** Props of InteractionTag: the element that holds the Primary and Secondary buttons. */\nexport interface InteractionTagProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Identifies the tag in a TagGroup: the value `onDismiss` receives and the selection holds. Give\n * every tag of a group its own value.\n * @default a generated id (a development warning in a group that reports values)\n */\n value?: string;\n /**\n * Colour scheme of both buttons: `filled` (a neutral fill), `outline` (a border on the surface\n * behind it) or `brand` (a light brand tint that follows the brand ramp).\n * @default the TagGroup's `appearance`, else 'filled'\n */\n appearance?: TagAppearance;\n /**\n * `medium` (28px tall), `small` (24px) or `extra-small` (20px); an Avatar in the Primary's\n * `media` is 24, 20 or 16px. Fluent's medium tag is 32px.\n * @default the TagGroup's `size`, else 'medium'\n */\n size?: TagSize;\n /**\n * `circular` (a pill) or `rounded` (4px corners). Fluent's default is `rounded`.\n * @default the TagGroup's `shape`, else 'circular'\n */\n shape?: TagShape;\n /**\n * Disables both buttons natively (a disabled TagGroup does too; a part's own `disabled` cannot\n * re-enable it). A button that has focus when it is disabled keeps it, unavailable, until focus\n * leaves it. Rendered as `data-disabled` on the root.\n * @default false\n */\n disabled?: boolean;\n /**\n * Outside a selecting TagGroup: draws the selected look and makes the Primary a toggle:\n * `aria-pressed=\"true\"`, or `\"false\"` for `selected={false}`. Leave it `undefined` for an\n * action that is not a toggle (no `aria-pressed`). Inside a selecting TagGroup (`value`,\n * `defaultValue` or `onValueChange`) the group's `value` decides, and a defined `selected` is\n * ignored (a development warning). Rendered as `data-selected` on the root and both buttons.\n * Disabled wins over the selected look (`aria-pressed` and `data-selected` still render).\n * Fluent's `selected` is a look only.\n */\n selected?: boolean;\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Props of InteractionTag.Primary: the tag's main action (or its toggle in a selecting TagGroup). */\nexport interface InteractionTagPrimaryProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /**\n * A visual before the text (an Avatar, sized for the tag: 24, 20 or 16px, unless it sets its\n * own `size`). Decorative (`aria-hidden`): the button is named by its text.\n */\n media?: Slot<'span'>;\n /** A decorative icon before the text (`aria-hidden`), in a 20, 16 or 12px box. */\n icon?: Slot<'span'>;\n /**\n * A second, smaller line under the text. Part of the Primary's name, not of the Secondary's. A\n * small or extra-small tag grows to 28px to fit it.\n */\n secondaryText?: React.ReactNode;\n /**\n * Disables the Primary natively; or-ed with the InteractionTag's `disabled` (it cannot\n * re-enable a disabled tag).\n * @default false\n */\n disabled?: boolean;\n ref?: React.Ref<HTMLButtonElement>;\n}\n\n/** Props of InteractionTag.Secondary: the tag's separate Dismiss button. */\nexport interface InteractionTagSecondaryProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /**\n * Visually hidden text that names the button with the Primary's text (\"Dismiss Cherry\"). A text\n * label in the children replaces it (\"Remove Cherry\"); an `aria-label` replaces the whole name.\n * Localise it here. Fluent's order is the primary text, then the label (\"Cherry remove\").\n * @default 'Dismiss'\n */\n dismissLabel?: string;\n /**\n * Disables the Secondary natively; or-ed with the InteractionTag's `disabled` (it cannot\n * re-enable a disabled tag).\n * @default false\n */\n disabled?: boolean;\n ref?: React.Ref<HTMLButtonElement>;\n}\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\n/** What an InteractionTag gives its two buttons (resolved values, never `undefined` but `pressed`). */\ninterface InteractionTagContextValue {\n size: TagSize;\n shape: TagShape;\n /** The look of both buttons: the appearance, or the selected look over it. */\n look: TagLook;\n /** Whether the tag is disabled (its own `disabled`, or its TagGroup's). */\n disabled: boolean;\n /** Whether the tag is selected (`data-selected`). */\n selected: boolean;\n /** The Primary's `aria-pressed`: `undefined` for an action that is not a toggle. */\n pressed: boolean | undefined;\n /** Whether a disabled button dims itself (`false` under a host that dims the tags as a whole). */\n dimDisabled: boolean;\n /** The id of the Primary's text, the second half of the Secondary's name. */\n primaryTextId: string;\n /** Which Primaries render, so the Secondary points at the primary text only while one does. */\n primaries: PrimaryRegistry;\n /** The Secondary, which Delete and Backspace on the Primary click (read at key time). */\n secondaryRef: React.RefObject<HTMLButtonElement | null> | null;\n /**\n * Reports the dismissal to the TagGroup (its `onDismiss(value)`), after the Secondary's\n * `onClick`, and then removes the tag's value from the group's selection (D39).\n */\n dismiss: () => void;\n /** Toggles the tag's value in a selecting TagGroup's selection (the Primary's click). */\n toggle: () => void;\n}\n\nconst noop = () => {};\n\n/**\n * The Primaries an InteractionTag renders, read by its Secondary, whose name points at the\n * primary text only while a Primary renders it (no id reference to a missing element). Until the\n * root's first commit (the server render, hydration and the first client render) a Primary is\n * assumed, so the server HTML holds the whole name and a tag with a Primary renders once; a\n * Secondary without one drops the id after that commit, and takes it again when one mounts. An\n * external store (C-HOOKS): a Primary registers from a layout effect.\n */\ninterface PrimaryRegistry {\n subscribe: (onChange: () => void) => () => void;\n /** Whether the Secondary's name may point at the primary text. */\n hasPrimary: () => boolean;\n /** For a Primary's layout effect: returns its cleanup. */\n register: () => () => void;\n /** For the root's layout effect: from now on the registrations decide. */\n settle: () => void;\n}\n\nfunction createPrimaryRegistry(): PrimaryRegistry {\n let count = 0;\n let settled = false;\n const listeners = new Set<() => void>();\n const notify = () => {\n for (const listener of listeners) listener();\n };\n return {\n subscribe: (onChange) => {\n listeners.add(onChange);\n return () => {\n listeners.delete(onChange);\n };\n },\n hasPrimary: () => !settled || count > 0,\n register: () => {\n count += 1;\n notify();\n return () => {\n count -= 1;\n notify();\n };\n },\n settle: () => {\n if (settled) return;\n settled = true;\n notify();\n },\n };\n}\n\n/** The registry of the inert context: a Primary is always assumed. */\nconst INERT_PRIMARY_REGISTRY: PrimaryRegistry = {\n subscribe: () => noop,\n hasPrimary: () => true,\n register: () => noop,\n settle: noop,\n};\n\n/** Internal: `null` outside an InteractionTag. */\nconst InteractionTagContext = React.createContext<InteractionTagContextValue | null>(null);\nInteractionTagContext.displayName = 'InteractionTagContext';\n\n/** What a part reads outside an InteractionTag in production (C-CONTEXT): an enabled, unnamed tag. */\nconst INERT_CONTEXT: InteractionTagContextValue = {\n size: 'medium',\n shape: 'circular',\n look: 'filled',\n disabled: false,\n selected: false,\n pressed: undefined,\n dimDisabled: true,\n primaryTextId: '',\n primaries: INERT_PRIMARY_REGISTRY,\n secondaryRef: null,\n dismiss: () => {},\n toggle: () => {},\n};\n\nfunction useInteractionTagContext(componentName: string): InteractionTagContextValue {\n const context = React.useContext(InteractionTagContext);\n if (context) return context;\n reportMissingContext(componentName, 'InteractionTag');\n return INERT_CONTEXT;\n}\n\n/** Whether `value` is a key of `table` (an untyped value outside a union falls back). */\nfunction isKeyOf<K extends string>(\n value: unknown,\n table: Readonly<Record<K, unknown>>,\n): value is K {\n return typeof value === 'string' && Object.hasOwn(table, value);\n}\n\n/** The classes of a button's disabled states: dimmed, unless the host dims the tags itself. */\nfunction disabledClasses(disabled: boolean, dimDisabled: boolean): string {\n return cn(\n dimDisabled\n ? [INTERACTION_TAG_DISABLED_CLASSES, mergedAriaDisabledClasses]\n : INTERACTION_TAG_UNDIMMED_DISABLED_CLASSES,\n disabled && forcedColors.disabled,\n );\n}\n\nconst SELECTED_IN_GROUP_MESSAGE =\n \"InteractionTag: `selected` has no effect in a TagGroup that selects (`value`, `defaultValue` or `onValueChange`); the group's `value` decides.\";\n\n/**\n * The state props of a tag button: natively disabled, or, while it keeps the focus it had when it\n * was disabled, the focusable disabled state (its click blocked).\n */\nfunction buttonStateProps(disabled: boolean, held: boolean) {\n if (!disabled) return undefined;\n return held ? MERGED_DISABLED_FOCUSABLE_PROPS : { disabled: true };\n}\n\n// ---------------------------------------------------------------------------\n// Root\n// ---------------------------------------------------------------------------\n\n// The InteractionTag root, documented on the exported `InteractionTag` const.\nconst InteractionTagRoot = ({\n value,\n appearance: appearanceProp,\n size: sizeProp,\n shape: shapeProp,\n disabled: disabledProp = false,\n selected: selectedProp,\n role,\n hidden,\n className,\n children,\n ref,\n ...rest\n}: InteractionTagProps) => {\n const group = useTagGroupContext();\n const rootRef = React.useRef<HTMLDivElement>(null);\n const mergedRef = useMergedRefs<HTMLDivElement>(rootRef, ref);\n const secondaryRef = React.useRef<HTMLButtonElement>(null);\n const primaryTextId = useId('interaction-tag-text');\n // After the first commit, the Primaries that registered decide the Secondary's name (D43).\n const [primaries] = React.useState(createPrimaryRegistry);\n React.useLayoutEffect(() => {\n primaries.settle();\n }, [primaries]);\n\n // The tag's own look, else its TagGroup's, else the default look.\n const size: TagSize = isKeyOf(sizeProp, tagSizeClasses) ? sizeProp : (group?.size ?? 'medium');\n const appearance: TagAppearance = isKeyOf(appearanceProp, tagAppearanceClasses)\n ? appearanceProp\n : (group?.appearance ?? 'filled');\n const shape: TagShape = isKeyOf(shapeProp, tagShapeClasses)\n ? shapeProp\n : (group?.shape ?? 'circular');\n // A disabled group disables every tag: the tag's own `disabled={false}` cannot re-enable it.\n const disabled = (group?.disabled ?? false) || disabledProp;\n const dimDisabled = group?.dimDisabled ?? true;\n\n // In a group that reports dismissals or selects, the tag's value (else a generated id).\n const reportedValue = useTagGroupItem(rootRef, value);\n // In a selecting TagGroup the group's selection decides (the Primary is always a toggle there);\n // elsewhere a boolean `selected` does, and `undefined` is an action that is no toggle.\n const selecting = group?.selecting ?? false;\n const pressed = selecting\n ? (group?.isSelected(reportedValue) ?? false)\n : typeof selectedProp === 'boolean'\n ? selectedProp\n : undefined;\n const selected = pressed === true;\n // Disabled wins over the selected look; the attributes still reflect the state.\n const look: TagLook = selected && !disabled ? 'selected' : appearance;\n\n const selectedIgnored = selecting && selectedProp !== undefined;\n React.useEffect(() => {\n if (selectedIgnored) warnOnce('InteractionTag:selected-in-group', SELECTED_IN_GROUP_MESSAGE);\n }, [selectedIgnored]);\n\n // The group's `onDismiss(value)`, then the value leaves the selection (D39), in one click.\n const dismiss = useEventCallback(() => {\n group?.dismiss(reportedValue);\n group?.deselect(reportedValue);\n });\n const toggle = useEventCallback(() => {\n group?.toggle(reportedValue);\n });\n\n // In a list TagGroup the root is a list item; the consumer's role wins.\n const listItemRole = group?.mode === 'list' ? 'listitem' : undefined;\n // A host hides the tags it counts instead of showing them (TagPicker's `overflow=\"count\"`).\n const hiddenByHost = value !== undefined && (group?.hiddenValues?.has(value) ?? false);\n\n const context = React.useMemo<InteractionTagContextValue>(\n () => ({\n size,\n shape,\n look,\n disabled,\n selected,\n pressed,\n dimDisabled,\n primaryTextId,\n primaries,\n secondaryRef,\n dismiss,\n toggle,\n }),\n [\n size,\n shape,\n look,\n disabled,\n selected,\n pressed,\n dimDisabled,\n primaryTextId,\n primaries,\n dismiss,\n toggle,\n ],\n );\n\n return (\n <InteractionTagContext.Provider value={context}>\n <div\n data-appearance={appearance}\n data-size={size}\n data-shape={shape}\n data-selected={selected ? '' : undefined}\n data-disabled={disabled ? '' : undefined}\n data-wave-tag-item=\"\"\n role={role ?? listItemRole}\n hidden={hiddenByHost || hidden}\n {...rest}\n ref={mergedRef}\n className={cn(\n interactionTagClassNames.root,\n 'group/interaction-tag inline-flex items-stretch',\n className,\n )}\n >\n {children}\n </div>\n </InteractionTagContext.Provider>\n );\n};\nInteractionTagRoot.displayName = 'InteractionTag';\n\n// ---------------------------------------------------------------------------\n// Primary\n// ---------------------------------------------------------------------------\n\n/**\n * The main action of an {@link InteractionTag}: a `<button type=\"button\">` named by its text and\n * `secondaryText` (`media` and `icon` are decorative), with the InteractionTag's look. In a\n * selecting TagGroup it is a toggle (`aria-pressed`): a click, Enter or Space adds the tag's\n * `value` to the group's selection or removes it, after its `onClick` (whose `preventDefault()`\n * cancels the toggle). Elsewhere the InteractionTag's `selected` makes it a toggle. Either state\n * renders its `aria-pressed` over one passed here, which applies only when neither is set. Delete\n * and Backspace on it click the tag's Secondary when there is one. Its props, `ref` and\n * `className` go to the button. Flat name of `InteractionTag.Primary`, for React Server\n * Components.\n */\nexport const InteractionTagPrimary = ({\n media,\n icon,\n secondaryText,\n disabled: disabledProp = false,\n 'aria-pressed': ariaPressed,\n className,\n children,\n onClick,\n onKeyDown,\n onFocus,\n onBlur,\n ref,\n ...rest\n}: InteractionTagPrimaryProps) => {\n const tag = useInteractionTagContext('InteractionTag.Primary');\n const { size, look } = tag;\n const disabled = tag.disabled || disabledProp;\n const hold = useHeldFocus(disabled);\n // Its text names the Secondary while it renders (D43).\n const registerPrimary = tag.primaries.register;\n React.useLayoutEffect(() => registerPrimary(), [registerPrimary]);\n\n // Slots that render nothing render no element and take no room.\n const hasMedia = slotRendersContent(media);\n const hasIcon = slotRendersContent(icon);\n const secondary = materialiseSlotContent(secondaryText);\n const hasSecondary = slotRendersContent(secondary);\n const avatarBox = React.useMemo(() => ({ size: TAG_AVATAR_SIZE[size] }), [size]);\n\n // In a selecting TagGroup a click (also Enter and Space) toggles the tag's value, after the\n // consumer's `onClick`; never for a click from a portal opened from the Primary (C-COMPOSE).\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n if (!disabled && isOwnEvent(event)) tag.toggle();\n };\n\n // Delete and Backspace dismiss the tag through the Secondary's own click, so whatever cancels\n // that click (its `onClick`'s `preventDefault()`, a disabled or held Secondary) cancels them\n // too. Not from a portal opened from the Primary, and not while the Primary itself is held.\n const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n if (disabled || event.target !== event.currentTarget || !isDismissKey(event)) return;\n const secondaryButton = tag.secondaryRef?.current;\n if (!secondaryButton || secondaryButton.disabled) return;\n event.preventDefault();\n secondaryButton.click();\n };\n\n const primaryText = (\n <span\n id={tag.primaryTextId || undefined}\n className={cn(\n interactionTagPrimaryClassNames.primaryText,\n hasSecondary && TAG_PRIMARY_TEXT_TWO_LINE_CLASSES,\n )}\n >\n {children}\n </span>\n );\n\n return (\n <button\n type=\"button\"\n // The tag's state (`selected`, or a selecting TagGroup's value) decides; a consumer\n // `aria-pressed` applies only to a Primary that is no toggle of the tag's.\n aria-pressed={tag.pressed ?? ariaPressed}\n data-selected={tag.selected ? '' : undefined}\n {...rest}\n ref={ref}\n onClick={composeEventHandlers(onClick, handleClick)}\n // After `onClick`: a held Primary's click is blocked, the toggle included.\n {...buttonStateProps(disabled, hold.held)}\n onKeyDown={composeEventHandlers(onKeyDown, handleKeyDown)}\n onFocus={composeEventHandlers(onFocus, hold.onFocus, { checkDefaultPrevented: false })}\n onBlur={composeEventHandlers(onBlur, hold.onBlur, { checkDefaultPrevented: false })}\n className={cn(\n interactionTagPrimaryClassNames.root,\n INTERACTION_TAG_BUTTON_BASE_CLASSES,\n INTERACTION_TAG_PRIMARY_BASE_CLASSES,\n tagSizeClasses[size],\n tagStartInsetClasses[size][hasMedia ? 'media' : hasIcon ? 'icon' : 'text'],\n interactionTagPrimaryEndInsetClasses[size],\n interactionTagLookClasses[look],\n look === 'selected' && [\n forcedColors.selectedContainer,\n INTERACTION_TAG_SELECTED_FORCED_COLORS,\n ],\n tagShapeClasses[tag.shape],\n INTERACTION_TAG_PRIMARY_JOINED_CLASSES,\n disabledClasses(disabled, tag.dimDisabled),\n focusRing,\n size === 'extra-small' && INTERACTION_TAG_EXTRA_SMALL_HIT_CLASSES,\n className,\n )}\n >\n {hasMedia && (\n // An Avatar without its own `size` takes the tag's box.\n <AvatarSizeContext.Provider value={avatarBox}>\n {renderSlot(\n media,\n 'span',\n cn(interactionTagPrimaryClassNames.media, tagMediaClasses[size]),\n { 'aria-hidden': true },\n )}\n </AvatarSizeContext.Provider>\n )}\n {hasIcon &&\n renderSlot(icon, 'span', cn(interactionTagPrimaryClassNames.icon, tagIconClasses[size]), {\n 'aria-hidden': true,\n })}\n {hasSecondary ? (\n <span className={TAG_TEXT_COLUMN_CLASSES}>\n {primaryText}\n {/* A space between the two texts in the button's name (\"Katri Designer\"), whatever a\n name computation makes of the column; the column layout never renders it. */}{' '}\n <span\n className={cn(\n interactionTagPrimaryClassNames.secondaryText,\n TAG_SECONDARY_TEXT_CLASSES,\n )}\n >\n {secondary}\n </span>\n </span>\n ) : (\n primaryText\n )}\n </button>\n );\n};\nInteractionTagPrimary.displayName = 'InteractionTagPrimary';\n\n// ---------------------------------------------------------------------------\n// Secondary\n// ---------------------------------------------------------------------------\n\nconst BUTTON_CHILD_MESSAGE =\n \"InteractionTag.Secondary: its content received a button. A button cannot contain a button: its children became the content of the Dismiss button and its props were dropped. Pass icon content, and handle the dismissal in `onClick` or in the TagGroup's `onDismiss`.\";\n\n/**\n * The separate Dismiss button of an {@link InteractionTag}: a `<button type=\"button\">` after the\n * Primary, named `dismissLabel` plus the Primary's text (\"Dismiss Cherry\"). Its children replace\n * the default dismiss glyph; a text label among them replaces `dismissLabel` in the name (\"Remove\n * Cherry\"), an `aria-label` the whole name. A button passed as its child is unwrapped (its children\n * become the content). Enter, Space, a click, Delete and Backspace call its `onClick`, then, in a\n * TagGroup, the group's `onDismiss(value)`. Its props, `ref` and `className` go to the button.\n * Flat name of `InteractionTag.Secondary`, for React Server Components.\n */\nexport const InteractionTagSecondary = ({\n dismissLabel = 'Dismiss',\n disabled: disabledProp = false,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n className,\n children,\n onClick,\n onKeyDown,\n onFocus,\n onBlur,\n ref,\n ...rest\n}: InteractionTagSecondaryProps) => {\n const tag = useInteractionTagContext('InteractionTag.Secondary');\n const { size, look } = tag;\n const disabled = tag.disabled || disabledProp;\n const hold = useHeldFocus(disabled);\n const dismissLabelId = useId('interaction-tag-dismiss');\n const contentId = useId('interaction-tag-dismiss-content');\n const ownRef = React.useRef<HTMLButtonElement>(null);\n const mergedRef = useMergedRefs<HTMLButtonElement>(ownRef, tag.secondaryRef, ref);\n // Unmounting while it has focus (rendered conditionally), the Secondary hands focus to its own\n // tag's Primary; in a TagGroup, when the whole tag goes, the tag's own move applies (D35).\n useDismissControlFocus(ownRef);\n\n // Its children are the glyph inside the Dismiss button: a button there would nest buttons, so\n // it is unwrapped (C-SLOTS glyph rule).\n const { glyph, button: unwrapped } = unwrapButtonGlyph(children as Slot<'span'>);\n React.useEffect(() => {\n if (unwrapped) warnOnce('InteractionTag.Secondary:button-child', BUTTON_CHILD_MESSAGE);\n }, [unwrapped]);\n const content = materialiseSlotContent(glyph);\n const hasContent = slotRendersContent(content);\n const literalTextLabel = hasContent && hasTextLabel(content);\n\n // C-SLOTS naming (WCAG 2.5.3 Label in Name): a text label in the children replaces\n // `dismissLabel` (\"Remove Cherry\"). The literal children decide on the server and on the first\n // render; after mount, the rendered content does (text from components, later changes).\n const [labelTarget, setLabelTarget] = React.useState<HTMLSpanElement | null>(null);\n const subscribeToContent = React.useCallback(\n (onChange: () => void) => (labelTarget ? observeTextLabel(labelTarget, onChange) : noop),\n [labelTarget],\n );\n const contentHasTextLabel = React.useSyncExternalStore(\n subscribeToContent,\n () => (labelTarget ? hasRenderedTextLabel(labelTarget) : literalTextLabel),\n () => literalTextLabel,\n );\n const hasLabel = hasContent && contentHasTextLabel;\n // The primary text joins the name while a Primary renders it.\n const hasPrimary = React.useSyncExternalStore(\n tag.primaries.subscribe,\n tag.primaries.hasPrimary,\n () => true,\n );\n // A consumer `aria-label` replaces the whole name; a consumer `aria-labelledby` replaces ours.\n const namedByConsumer = ariaLabel !== undefined || ariaLabelledBy !== undefined;\n const labelledBy = namedByConsumer\n ? ariaLabelledBy\n : joinIds(hasLabel ? contentId : dismissLabelId, hasPrimary ? tag.primaryTextId : undefined);\n\n // The consumer's `onClick` first (its `preventDefault()` keeps the group from hearing of it),\n // then the TagGroup's `onDismiss(value)`; never for a click from a portal opened inside.\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n if (isOwnEvent(event)) tag.dismiss();\n };\n // Delete and Backspace dismiss as Enter does: through the button's own click, so whatever\n // cancels a click (its `onClick`'s `preventDefault()`, a held or disabled button) cancels them.\n // A held key dismisses one tag: the browser clicks a button on every repeated Enter, which\n // would reach the next tag's Dismiss control once focus moved there (D35).\n const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n if (event.target !== event.currentTarget) return;\n if (isRepeatedActivation(event)) {\n event.preventDefault();\n return;\n }\n if (!isDismissKey(event)) return;\n event.preventDefault();\n event.currentTarget.click();\n };\n\n return (\n <button\n type=\"button\"\n data-wave-tag-dismiss=\"\"\n data-selected={tag.selected ? '' : undefined}\n {...rest}\n ref={mergedRef}\n aria-label={ariaLabel}\n aria-labelledby={labelledBy}\n onClick={composeEventHandlers(onClick, handleClick)}\n {...buttonStateProps(disabled, hold.held)}\n onKeyDown={composeEventHandlers(onKeyDown, handleKeyDown)}\n onFocus={composeEventHandlers(onFocus, hold.onFocus, { checkDefaultPrevented: false })}\n onBlur={composeEventHandlers(onBlur, hold.onBlur, { checkDefaultPrevented: false })}\n className={cn(\n interactionTagSecondaryClassNames.root,\n INTERACTION_TAG_BUTTON_BASE_CLASSES,\n INTERACTION_TAG_SECONDARY_BASE_CLASSES,\n interactionTagSecondarySizeClasses[size],\n interactionTagLookClasses[look],\n look === 'selected' && [\n forcedColors.selectedContainer,\n INTERACTION_TAG_SELECTED_FORCED_COLORS,\n ],\n interactionTagDividerClasses[look],\n interactionTagSecondaryShapeClasses[tag.shape],\n disabledClasses(disabled, tag.dimDisabled),\n focusRing,\n size === 'extra-small' && INTERACTION_TAG_EXTRA_SMALL_HIT_CLASSES,\n className,\n )}\n >\n {!namedByConsumer && (\n <span id={dismissLabelId} className=\"sr-only\">\n {dismissLabel}\n </span>\n )}\n {hasContent ? (\n <span\n id={contentId}\n ref={setLabelTarget}\n className={cn(\n interactionTagSecondaryClassNames.dismissIcon,\n 'inline-flex items-center justify-center',\n // A text label keeps clear of the divider and the tag's end; a glyph needs no room.\n hasLabel && INTERACTION_TAG_SECONDARY_LABEL_CLASSES,\n )}\n >\n {content}\n </span>\n ) : (\n <DismissIcon\n size={TAG_DISMISS_GLYPH_SIZE[size]}\n className={interactionTagSecondaryClassNames.dismissIcon}\n />\n )}\n </button>\n );\n};\nInteractionTagSecondary.displayName = 'InteractionTagSecondary';\n\n// ---------------------------------------------------------------------------\n// Compound\n// ---------------------------------------------------------------------------\n\n/**\n * A tag with a main action and a separate Dismiss button: an element that holds two sibling\n * buttons, `InteractionTag.Primary` (the action) and `InteractionTag.Secondary` (Dismiss), never\n * one inside the other. Use it for a chip the user acts on (opens, toggles) and can also remove;\n * a `Tag` is a chip that only displays, or only dismisses.\n *\n * - **Two Tab stops**, the Primary then the Secondary. In a TagGroup toolbar both join its arrow\n * order (Primary, Secondary, next tag).\n * - **The Secondary is named after the Primary's text**: its `dismissLabel` plus the primary\n * text, \"Dismiss Cherry\" (never the secondary text). A text label in its children replaces\n * `dismissLabel` (\"Remove Cherry\"); an `aria-label` replaces the whole name.\n * - **Delete and Backspace** on either button dismiss the tag through the Secondary's click (a\n * held key dismisses once); without a Secondary they do nothing. Enter, Space and a click on the\n * Secondary dismiss too: remove the tag in its `onClick`, or in a TagGroup's `onDismiss(value)`,\n * which is called after it.\n * - **In a selecting TagGroup** (`value`, `defaultValue` or `onValueChange` on the group) the\n * Primary toggles the tag's `value` in the group's selection (`aria-pressed`, the selected\n * look), and dismissing a selected tag also removes its value from the selection.\n * - **`selected`**, outside a selecting TagGroup, draws the selected look and makes the Primary a\n * toggle (`aria-pressed`); leave it `undefined` for an action that is not a toggle.\n * - **Look**: `size`, `appearance` and `shape`, Tag's sizes and colours (a TagGroup gives its\n * defaults); `disabled` disables both buttons natively. The Primary takes `media` (an Avatar,\n * sized for the tag), `icon` and `secondaryText`.\n * - Fluent's `hasSecondaryAction` is not needed: the Primary squares its end corners next to a\n * Secondary by itself, also when the Secondary is rendered conditionally or wrapped.\n * - React Server Components cannot dot into a client module: import the flat names\n * `InteractionTagPrimary` and `InteractionTagSecondary` there.\n * - Renders `data-appearance`, `data-size` and `data-shape`, and while set `data-selected` and\n * `data-disabled`, on the root; `data-selected` on both buttons.\n *\n * @example\n * <InteractionTag value=\"cherry\">\n * <InteractionTag.Primary icon={<FruitIcon />} onClick={openDetails}>\n * Cherry\n * </InteractionTag.Primary>\n * <InteractionTag.Secondary onClick={() => remove('cherry')} />\n * </InteractionTag>\n */\nexport const InteractionTag = /* @__PURE__ */ Object.assign(InteractionTagRoot, {\n Primary: InteractionTagPrimary,\n Secondary: InteractionTagSecondary,\n});\n"],"mappings":"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"}