@astryxdesign/core 0.1.8-canary.0db5dfd → 0.1.8-canary.17d83c9

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 (155) hide show
  1. package/dist/Avatar/Avatar.d.ts +18 -2
  2. package/dist/Avatar/Avatar.d.ts.map +1 -1
  3. package/dist/Avatar/Avatar.js +63 -7
  4. package/dist/Breadcrumbs/BreadcrumbItem.d.ts +31 -2
  5. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  6. package/dist/Breadcrumbs/BreadcrumbItem.js +208 -6
  7. package/dist/Breadcrumbs/index.d.ts +5 -0
  8. package/dist/Breadcrumbs/index.d.ts.map +1 -1
  9. package/dist/Breadcrumbs/index.js +9 -1
  10. package/dist/Chat/ChatComposer.d.ts.map +1 -1
  11. package/dist/Chat/ChatComposer.js +15 -1
  12. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  13. package/dist/Chat/ChatComposerInput.js +16 -0
  14. package/dist/Chat/ChatContext.d.ts +33 -0
  15. package/dist/Chat/ChatContext.d.ts.map +1 -1
  16. package/dist/Chat/ChatContext.js +16 -2
  17. package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
  18. package/dist/Chat/ChatDictationButton.js +1 -1
  19. package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
  20. package/dist/Chat/ChatLayoutScrollButton.js +4 -4
  21. package/dist/Chat/ChatSendButton.d.ts.map +1 -1
  22. package/dist/Chat/ChatSendButton.js +7 -1
  23. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  24. package/dist/Chat/ChatToolCalls.js +6 -6
  25. package/dist/Chat/index.d.ts +2 -1
  26. package/dist/Chat/index.d.ts.map +1 -1
  27. package/dist/Chat/index.js +1 -1
  28. package/dist/CheckboxInput/CheckboxInput.js +1 -1
  29. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  30. package/dist/CheckboxList/CheckboxListItem.js +4 -10
  31. package/dist/ClickableCard/ClickableCard.js +2 -2
  32. package/dist/CommandPalette/CommandPalette.d.ts +1 -1
  33. package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
  34. package/dist/CommandPalette/CommandPalette.js +3 -1
  35. package/dist/DateInput/DateInput.d.ts +47 -1
  36. package/dist/DateInput/DateInput.d.ts.map +1 -1
  37. package/dist/DateInput/DateInput.js +26 -2
  38. package/dist/DateInput/index.d.ts +1 -1
  39. package/dist/DateInput/index.d.ts.map +1 -1
  40. package/dist/Dialog/Dialog.d.ts.map +1 -1
  41. package/dist/Dialog/Dialog.js +4 -3
  42. package/dist/Divider/Divider.js +1 -1
  43. package/dist/Field/Field.d.ts.map +1 -1
  44. package/dist/Field/Field.js +2 -3
  45. package/dist/Field/FieldLabel.d.ts +1 -1
  46. package/dist/Field/FieldLabel.d.ts.map +1 -1
  47. package/dist/Field/FieldLabel.js +42 -15
  48. package/dist/Popover/Popover.d.ts.map +1 -1
  49. package/dist/Popover/Popover.js +3 -2
  50. package/dist/Popover/usePopover.d.ts.map +1 -1
  51. package/dist/Popover/usePopover.js +3 -9
  52. package/dist/SelectableCard/SelectableCard.js +2 -2
  53. package/dist/Slider/Slider.d.ts.map +1 -1
  54. package/dist/Slider/Slider.js +4 -1
  55. package/dist/Table/BaseTable.d.ts.map +1 -1
  56. package/dist/Table/BaseTable.js +3 -2
  57. package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
  58. package/dist/Table/useBaseTablePlugins.js +5 -3
  59. package/dist/Thumbnail/Thumbnail.d.ts +16 -9
  60. package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
  61. package/dist/Thumbnail/Thumbnail.js +65 -86
  62. package/dist/Thumbnail/thumbnail.markers.stylex.d.ts +9 -0
  63. package/dist/Thumbnail/thumbnail.markers.stylex.d.ts.map +1 -0
  64. package/dist/Thumbnail/thumbnail.markers.stylex.js +14 -0
  65. package/dist/Timestamp/Timestamp.d.ts +3 -1
  66. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  67. package/dist/Timestamp/Timestamp.js +8 -6
  68. package/dist/Toast/useToast.d.ts.map +1 -1
  69. package/dist/Toast/useToast.js +2 -5
  70. package/dist/astryx.css +6 -10
  71. package/dist/astryx.umd.js +47 -47
  72. package/dist/astryx.umd.js.map +4 -4
  73. package/dist/hooks/index.d.ts +1 -0
  74. package/dist/hooks/index.d.ts.map +1 -1
  75. package/dist/hooks/index.js +2 -1
  76. package/dist/hooks/useDevWarning.d.ts +18 -0
  77. package/dist/hooks/useDevWarning.d.ts.map +1 -0
  78. package/dist/hooks/useDevWarning.js +49 -0
  79. package/dist/hooks/useOverflow.d.ts.map +1 -1
  80. package/dist/hooks/useOverflow.js +2 -3
  81. package/dist/i18n/resolve.d.ts.map +1 -1
  82. package/dist/i18n/resolve.js +7 -18
  83. package/dist/theme/Theme.d.ts.map +1 -1
  84. package/dist/theme/Theme.js +2 -7
  85. package/dist/theme/syntax/defineSyntaxTheme.d.ts.map +1 -1
  86. package/dist/theme/syntax/defineSyntaxTheme.js +2 -1
  87. package/dist/utils/devWarning.d.ts +42 -0
  88. package/dist/utils/devWarning.d.ts.map +1 -0
  89. package/dist/utils/devWarning.js +88 -0
  90. package/dist/utils/index.d.ts +3 -1
  91. package/dist/utils/index.d.ts.map +1 -1
  92. package/dist/utils/index.js +3 -2
  93. package/dist/utils/plainDate.d.ts +30 -0
  94. package/dist/utils/plainDate.d.ts.map +1 -1
  95. package/dist/utils/plainDate.js +53 -0
  96. package/package.json +1 -1
  97. package/src/Avatar/Avatar.doc.mjs +10 -0
  98. package/src/Avatar/Avatar.test.tsx +156 -1
  99. package/src/Avatar/Avatar.tsx +96 -4
  100. package/src/Breadcrumbs/BreadcrumbItem.doc.mjs +26 -0
  101. package/src/Breadcrumbs/BreadcrumbItem.tsx +333 -14
  102. package/src/Breadcrumbs/Breadcrumbs.doc.mjs +2 -0
  103. package/src/Breadcrumbs/Breadcrumbs.test.tsx +284 -2
  104. package/src/Breadcrumbs/index.ts +27 -0
  105. package/src/Chat/ChatComposer.doc.mjs +3 -3
  106. package/src/Chat/ChatComposer.test.tsx +82 -2
  107. package/src/Chat/ChatComposer.tsx +15 -0
  108. package/src/Chat/ChatComposerInput.test.tsx +16 -0
  109. package/src/Chat/ChatComposerInput.tsx +14 -0
  110. package/src/Chat/ChatContext.tsx +37 -10
  111. package/src/Chat/ChatDictationButton.tsx +4 -1
  112. package/src/Chat/ChatLayoutScrollButton.tsx +4 -1
  113. package/src/Chat/ChatSendButton.tsx +6 -0
  114. package/src/Chat/ChatToolCalls.tsx +12 -3
  115. package/src/Chat/index.ts +5 -1
  116. package/src/CheckboxInput/CheckboxInput.tsx +1 -1
  117. package/src/CheckboxList/CheckboxListItem.tsx +11 -19
  118. package/src/ClickableCard/ClickableCard.tsx +2 -2
  119. package/src/CommandPalette/CommandPalette.tsx +3 -1
  120. package/src/DateInput/DateInput.doc.mjs +16 -0
  121. package/src/DateInput/DateInput.test.tsx +108 -0
  122. package/src/DateInput/DateInput.tsx +68 -3
  123. package/src/DateInput/index.ts +1 -0
  124. package/src/Dialog/Dialog.tsx +6 -4
  125. package/src/Divider/Divider.tsx +2 -2
  126. package/src/Field/Field.tsx +6 -5
  127. package/src/Field/FieldLabel.tsx +8 -0
  128. package/src/Popover/Popover.tsx +7 -4
  129. package/src/Popover/usePopover.tsx +9 -13
  130. package/src/SelectableCard/SelectableCard.tsx +2 -2
  131. package/src/Slider/Slider.test.tsx +13 -0
  132. package/src/Slider/Slider.tsx +6 -4
  133. package/src/Table/BaseTable.tsx +3 -5
  134. package/src/Table/useBaseTablePlugins.ts +10 -6
  135. package/src/Thumbnail/Thumbnail.doc.mjs +13 -13
  136. package/src/Thumbnail/Thumbnail.test.tsx +47 -21
  137. package/src/Thumbnail/Thumbnail.tsx +103 -79
  138. package/src/Thumbnail/thumbnail.markers.stylex.ts +12 -0
  139. package/src/Timestamp/Timestamp.doc.mjs +4 -4
  140. package/src/Timestamp/Timestamp.test.tsx +32 -0
  141. package/src/Timestamp/Timestamp.tsx +28 -8
  142. package/src/Toast/useToast.tsx +7 -8
  143. package/src/hooks/index.ts +2 -0
  144. package/src/hooks/useDevWarning.test.tsx +45 -0
  145. package/src/hooks/useDevWarning.ts +54 -0
  146. package/src/hooks/useOverflow.ts +8 -11
  147. package/src/i18n/InternationalizationProvider.doc.mjs +22 -0
  148. package/src/i18n/resolve.ts +9 -21
  149. package/src/theme/Theme.tsx +11 -14
  150. package/src/theme/syntax/defineSyntaxTheme.ts +5 -6
  151. package/src/utils/devWarning.test.ts +56 -0
  152. package/src/utils/devWarning.ts +102 -0
  153. package/src/utils/index.ts +6 -0
  154. package/src/utils/plainDate.test.ts +22 -0
  155. package/src/utils/plainDate.ts +61 -0
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * @file Avatar.tsx
3
- * @input Uses React, HTMLAttributes, ReactNode, useState
3
+ * @input Uses React, HTMLAttributes, ReactNode, useState; useTooltip
4
+ * (Tooltip hook) for the optional name-on-hover tooltip
4
5
  * @output Exports Avatar component, AvatarProps, AvatarSize types
5
6
  * @position Core implementation; consumed by index.ts
6
7
  *
@@ -70,6 +71,19 @@ export interface AvatarProps extends BaseProps<HTMLDivElement> {
70
71
  * Typically used for status indicators or badges.
71
72
  */
72
73
  status?: ReactNode;
74
+ /**
75
+ * Tooltip shown on hover (and keyboard focus).
76
+ * - omitted / `true`: show the avatar's `name`
77
+ * - a string: show that text instead
78
+ * - `false`: no tooltip
79
+ *
80
+ * The avatar owns this tooltip. It is NOT auto-disabled when wrapped in your
81
+ * own Tooltip/HoverCard — set `tooltip={false}` if you provide your own
82
+ * overlay. No tooltip is shown if `tooltip` is `true`/omitted and there is
83
+ * no (non-whitespace) `name`.
84
+ * @default true
85
+ */
86
+ tooltip?: string | boolean;
73
87
  }
74
88
  /**
75
89
  * Avatar component for displaying user profile pictures.
@@ -82,9 +96,11 @@ export interface AvatarProps extends BaseProps<HTMLDivElement> {
82
96
  * <Avatar src="/user.jpg" name="John Doe" />
83
97
  * <Avatar name="Jane Smith" size="xl" />
84
98
  * <Avatar src="/user.jpg" status={<OnlineIndicator />} />
99
+ * <Avatar name="jsmith" tooltip="Jane Smith, Staff Engineer" />
100
+ * <Avatar name="Jane" tooltip={false} />
85
101
  * ```
86
102
  */
87
- export declare function Avatar({ alt, 'data-testid': testId, fallbackSrc, name, size, src, status, xstyle, className, style, ref, ...props }: AvatarProps): import("react").JSX.Element;
103
+ export declare function Avatar({ alt, 'data-testid': testId, fallbackSrc, name, size, src, status, tooltip, xstyle, className, style, ref, ...props }: AvatarProps): import("react").JSX.Element;
88
104
  export declare namespace Avatar {
89
105
  var displayName: string;
90
106
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.d.ts","sourceRoot":"","sources":["../../src/Avatar/Avatar.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAoB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AACxD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAsC5C;;;;;;GAMG;AACH,KAAK,eAAe,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEzD;;GAEG;AACH,KAAK,iBAAiB,GACpB,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAEzE;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,iBAAiB,CAAC;AAE7D;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAgBpD;AAqFD,MAAM,WAAW,WAAY,SAAQ,SAAS,CAAC,cAAc,CAAC;IAC5D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAsCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,MAAM,CAAC,EACrB,GAAG,EACH,aAAa,EAAE,MAAM,EACrB,WAAW,EACX,IAAI,EACJ,IAAW,EACX,GAAG,EACH,MAAM,EACN,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,WAAW,+BAwFb;yBArGe,MAAM"}
1
+ {"version":3,"file":"Avatar.d.ts","sourceRoot":"","sources":["../../src/Avatar/Avatar.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAoB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AACxD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAuC5C;;;;;;GAMG;AACH,KAAK,eAAe,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEzD;;GAEG;AACH,KAAK,iBAAiB,GACpB,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAEzE;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,iBAAiB,CAAC;AAE7D;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAgBpD;AAkGD,MAAM,WAAW,WAAY,SAAQ,SAAS,CAAC,cAAc,CAAC;IAC5D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5B;AAsCD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,MAAM,CAAC,EACrB,GAAG,EACH,aAAa,EAAE,MAAM,EACrB,WAAW,EACX,IAAI,EACJ,IAAW,EACX,GAAG,EACH,MAAM,EACN,OAAc,EACd,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,WAAW,+BAqJb;yBAnKe,MAAM"}
@@ -4,7 +4,8 @@
4
4
 
5
5
  /**
6
6
  * @file Avatar.tsx
7
- * @input Uses React, HTMLAttributes, ReactNode, useState
7
+ * @input Uses React, HTMLAttributes, ReactNode, useState; useTooltip
8
+ * (Tooltip hook) for the optional name-on-hover tooltip
8
9
  * @output Exports Avatar component, AvatarProps, AvatarSize types
9
10
  * @position Core implementation; consumed by index.ts
10
11
  *
@@ -20,8 +21,9 @@ import "../theme/tokens.stylex.js";
20
21
  import { colorVars, typographyVars, fontWeightVars, radiusVars } from "../theme/tokens.stylex.js";
21
22
  import { AvatarSizeContext } from "./AvatarSizeContext.js";
22
23
  import { useAvatarGroup } from "../AvatarGroup/AvatarGroupContext.js";
23
- import { mergeProps } from "../utils/index.js";
24
+ import { mergeProps, mergeRefs } from "../utils/index.js";
24
25
  import { themeProps } from "../utils/themeProps.js";
26
+ import { useTooltip } from "../Tooltip/useTooltip.js";
25
27
 
26
28
  /**
27
29
  * The offset ratio for positioning elements on a circle's edge at 45°.
@@ -35,7 +37,7 @@ import { themeProps } from "../utils/themeProps.js";
35
37
  *
36
38
  * This constant represents that ratio: (1 - 1/√2) / 2 ≈ 0.146
37
39
  */
38
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
40
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
39
41
  const CIRCLE_EDGE_OFFSET_RATIO = (1 - 1 / Math.SQRT2) / 2;
40
42
 
41
43
  /**
@@ -122,6 +124,11 @@ const styles = {
122
124
  status: {
123
125
  kVAEAm: "x10l6tqk",
124
126
  $$css: true
127
+ },
128
+ focusable: {
129
+ kI3sdo: "x17nn4n9",
130
+ kInvED: "x1wfwxd8 x7s97pk",
131
+ $$css: true
125
132
  }
126
133
  };
127
134
 
@@ -229,6 +236,8 @@ function DefaultIcon({
229
236
  * <Avatar src="/user.jpg" name="John Doe" />
230
237
  * <Avatar name="Jane Smith" size="xl" />
231
238
  * <Avatar src="/user.jpg" status={<OnlineIndicator />} />
239
+ * <Avatar name="jsmith" tooltip="Jane Smith, Staff Engineer" />
240
+ * <Avatar name="Jane" tooltip={false} />
232
241
  * ```
233
242
  */
234
243
  export function Avatar({
@@ -239,6 +248,7 @@ export function Avatar({
239
248
  size = 'md',
240
249
  src,
241
250
  status,
251
+ tooltip = true,
242
252
  xstyle,
243
253
  className,
244
254
  style,
@@ -262,18 +272,54 @@ export function Avatar({
262
272
  const avatarGroup = useAvatarGroup();
263
273
  const resolvedSize = avatarGroup?.size ?? size;
264
274
  const numericSize = useMemo(() => resolveSize(resolvedSize), [resolvedSize]);
265
- return /*#__PURE__*/_jsx(AvatarSizeContext, {
275
+
276
+ // Resolve the tooltip content:
277
+ // - `false` → no tooltip
278
+ // - a string → that string
279
+ // - `true` / omitted → the `name` (a whitespace-only name yields nothing)
280
+ // Note: the *visible* tooltip prefers `name` (not `alt`); the *accessible
281
+ // name* on the root still uses `alt || name` above, independent of this.
282
+ const tooltipContent = tooltip === false ? undefined : typeof tooltip === 'string' ? tooltip : name;
283
+ const trimmedTooltip = tooltipContent?.trim();
284
+ const showTooltip = trimmedTooltip != null && trimmedTooltip !== '';
285
+ // Whether the tooltip text is a consumer-authored override (a custom string)
286
+ // rather than the default name. A custom description is worth wiring to
287
+ // `aria-describedby` (it adds information, matching Button); the default name
288
+ // tooltip is visual-only — its text duplicates the root `aria-label`, so
289
+ // describing it too would double-announce the same name (OQ-4).
290
+ const isCustomTooltip = typeof tooltip === 'string';
291
+
292
+ // Own the name tooltip via the Tooltip hook (the Button pattern), which
293
+ // returns `describedBy` as a value we choose whether to apply — the only way
294
+ // to satisfy the per-case aria-describedby rule (default name: none; custom
295
+ // string: describe) without editing Tooltip. `focusTrigger: 'auto'` shows the
296
+ // tooltip on keyboard focus once the root is made focusable (below).
297
+ const tooltipHook = useTooltip({
298
+ placement: 'above',
299
+ isEnabled: showTooltip
300
+ });
301
+ const rootRef = mergeRefs(ref, showTooltip ? tooltipHook.ref : undefined);
302
+ const describedByProp = showTooltip && isCustomTooltip ? {
303
+ 'aria-describedby': [props['aria-describedby'], tooltipHook.describedBy].filter(Boolean).join(' ') || undefined
304
+ } : null;
305
+ const avatarElement = /*#__PURE__*/_jsx(AvatarSizeContext, {
266
306
  value: numericSize,
267
307
  children: /*#__PURE__*/_jsxs("div", {
268
308
  ...props,
269
- ref: ref,
309
+ ref: rootRef,
270
310
  role: isDecorative ? 'presentation' : 'img',
271
311
  "aria-label": isDecorative ? undefined : accessibleName,
272
- "aria-hidden": isDecorative || undefined,
312
+ "aria-hidden": isDecorative || undefined
313
+ // The root is a div[role="img"], not natively focusable. When a name
314
+ // tooltip is active, add a tab stop so keyboard users can reveal it
315
+ // (WCAG 1.4.13 / 2.1.1) — matching Timestamp/Button. Only while active.
316
+ ,
317
+ tabIndex: showTooltip ? 0 : undefined,
273
318
  "data-testid": testId,
319
+ ...describedByProp,
274
320
  ...mergeProps(themeProps('avatar', {
275
321
  size: resolvedSize
276
- }), stylex.props(styles.wrapper, avatarGroup && groupStyles.ring, avatarGroup && groupStyles.overlap, avatarGroup && groupDynamicStyles.overlap(-avatarGroup.overlap), xstyle), className, style),
322
+ }), stylex.props(styles.wrapper, showTooltip && styles.focusable, avatarGroup && groupStyles.ring, avatarGroup && groupStyles.overlap, avatarGroup && groupDynamicStyles.overlap(-avatarGroup.overlap), xstyle), className, style),
277
323
  children: [/*#__PURE__*/_jsxs("div", {
278
324
  ...stylex.props(styles.content, dynamicStyles.size(numericSize)),
279
325
  children: [showImage && /*#__PURE__*/_jsx("img", {
@@ -307,5 +353,15 @@ export function Avatar({
307
353
  })]
308
354
  })
309
355
  });
356
+ if (!showTooltip) {
357
+ return avatarElement;
358
+ }
359
+
360
+ // Render the tooltip as a sibling (no wrapper DOM) — the hook's ref is already
361
+ // attached to the root via `rootRef` above. `trimmedTooltip` is guaranteed
362
+ // non-empty here.
363
+ return /*#__PURE__*/_jsxs(_Fragment, {
364
+ children: [avatarElement, tooltipHook.renderTooltip(trimmedTooltip)]
365
+ });
310
366
  }
311
367
  Avatar.displayName = 'Avatar';
@@ -1,9 +1,15 @@
1
1
  /**
2
2
  * @file BreadcrumbItem.tsx
3
- * @input Uses React use/useRef/useEffect, stylex, theme tokens, BreadcrumbContext
3
+ * @input Uses React use/useRef/useEffect, stylex, theme tokens, BreadcrumbContext,
4
+ * and (for the menu trigger) usePopover + the shared DropdownMenu item API
5
+ * (renderDropdownItems, DropdownMenuContext, MENU_ITEM_SELECTOR, useListFocus)
4
6
  * @output Exports BreadcrumbItem component and BreadcrumbItemProps
5
7
  * @position Individual breadcrumb item; used inside Breadcrumbs
6
8
  *
9
+ * A `menu` prop turns the item's link-styled button into a menu trigger whose
10
+ * popover reuses DropdownMenu's item pipeline — the same wiring ContextMenu
11
+ * uses — so menu-item definitions are portable across the menu family.
12
+ *
7
13
  * SYNC: When modified, update these files to stay in sync:
8
14
  * - /packages/core/src/Breadcrumbs/Breadcrumbs.doc.mjs
9
15
  * - /packages/core/src/Breadcrumbs/Breadcrumbs.test.tsx
@@ -14,6 +20,8 @@
14
20
  import React, { type ReactNode, type MouseEvent } from 'react';
15
21
  import type { LinkComponentType } from '../Link/types';
16
22
  import type { BaseProps } from '../BaseProps';
23
+ import { type DropdownMenuSize } from '../DropdownMenu/DropdownMenuContext';
24
+ import type { DropdownMenuOption } from '../DropdownMenu/DropdownMenu';
17
25
  export interface BreadcrumbItemProps extends Omit<BaseProps<HTMLLIElement>, 'onClick'> {
18
26
  ref?: React.Ref<HTMLLIElement>;
19
27
  /**
@@ -44,6 +52,27 @@ export interface BreadcrumbItemProps extends Omit<BaseProps<HTMLLIElement>, 'onC
44
52
  * Optional icon rendered before the label.
45
53
  */
46
54
  startIcon?: ReactNode;
55
+ /**
56
+ * Menu opened when the item is activated. Accepts the SAME item API as
57
+ * DropdownMenu / MoreMenu / ContextMenu, so a consumer's existing menu-item
58
+ * definitions are portable into a breadcrumb with no rewrite:
59
+ * - a `DropdownMenuOption[]` data array (items, sections, dividers), or
60
+ * - composed `DropdownMenuItem` / `DropdownMenuCheckboxItem` /
61
+ * `DropdownMenuRadioGroup` children.
62
+ *
63
+ * When set, the item renders as a link-styled menu trigger (button + a
64
+ * trailing chevron, `aria-haspopup="menu"` / `aria-expanded`) whose popover
65
+ * is a `role="menu"` container that provides `DropdownMenuContext` and runs
66
+ * `useListFocus`. Takes precedence over `href` / `onClick` (which are
67
+ * ignored when `menu` is set — a dev-time warning is logged).
68
+ */
69
+ menu?: DropdownMenuOption[] | ReactNode;
70
+ /**
71
+ * Size passed to the menu items via `DropdownMenuContext` (item
72
+ * padding/typography). Defaults from the breadcrumb variant:
73
+ * `'supporting'` → `'sm'`, otherwise `'md'`.
74
+ */
75
+ menuSize?: DropdownMenuSize;
47
76
  }
48
77
  /**
49
78
  * An individual breadcrumb item. Renders as a link (`<a>`) or a span
@@ -59,7 +88,7 @@ export interface BreadcrumbItemProps extends Omit<BaseProps<HTMLLIElement>, 'onC
59
88
  * <BreadcrumbItem isCurrent>My Project</BreadcrumbItem>
60
89
  * ```
61
90
  */
62
- export declare function BreadcrumbItem({ ref, as, children, href, onClick, isCurrent: isCurrentProp, startIcon, xstyle, className, style, 'data-testid': testId, ...rest }: BreadcrumbItemProps): React.JSX.Element;
91
+ export declare function BreadcrumbItem({ ref, as, children, href, onClick, isCurrent: isCurrentProp, startIcon, menu, menuSize, xstyle, className, style, 'data-testid': testId, ...rest }: BreadcrumbItemProps): React.JSX.Element;
63
92
  export declare namespace BreadcrumbItem {
64
93
  var displayName: string;
65
94
  }
@@ -1 +1 @@
1
- {"version":3,"file":"BreadcrumbItem.d.ts","sourceRoot":"","sources":["../../src/Breadcrumbs/BreadcrumbItem.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,EAIZ,KAAK,SAAS,EACd,KAAK,UAAU,EAChB,MAAM,OAAO,CAAC;AAKf,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,eAAe,CAAC;AAErD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAO5C,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAC/C,SAAS,CAAC,aAAa,CAAC,EACxB,SAAS,CACV;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC/B;;;;OAIG;IACH,EAAE,CAAC,EAAE,iBAAiB,CAAC;IACvB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IACpB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IAC/C;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAoFD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,EAC7B,GAAG,EACH,EAAE,EACF,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,SAAS,EAAE,aAAa,EACxB,SAAS,EACT,MAAM,EACN,SAAS,EACT,KAAK,EACL,aAAa,EAAE,MAAM,EACrB,GAAG,IAAI,EACR,EAAE,mBAAmB,qBAuJrB;yBApKe,cAAc"}
1
+ {"version":3,"file":"BreadcrumbItem.d.ts","sourceRoot":"","sources":["../../src/Breadcrumbs/BreadcrumbItem.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,EAOZ,KAAK,SAAS,EACd,KAAK,UAAU,EAChB,MAAM,OAAO,CAAC;AAUf,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,eAAe,CAAC;AAErD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAQ5C,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,qCAAqC,CAAC;AAK7C,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,8BAA8B,CAAC;AAMrE,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAC/C,SAAS,CAAC,aAAa,CAAC,EACxB,SAAS,CACV;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC/B;;;;OAIG;IACH,EAAE,CAAC,EAAE,iBAAiB,CAAC;IACvB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IACpB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IAC/C;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;;;;;;;;;;OAaG;IACH,IAAI,CAAC,EAAE,kBAAkB,EAAE,GAAG,SAAS,CAAC;IACxC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,gBAAgB,CAAC;CAC7B;AA8GD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,EAC7B,GAAG,EACH,EAAE,EACF,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,SAAS,EAAE,aAAa,EACxB,SAAS,EACT,IAAI,EACJ,QAAQ,EACR,MAAM,EACN,SAAS,EACT,KAAK,EACL,aAAa,EAAE,MAAM,EACrB,GAAG,IAAI,EACR,EAAE,mBAAmB,qBAoMrB;yBAnNe,cAAc"}
@@ -4,10 +4,16 @@
4
4
 
5
5
  /**
6
6
  * @file BreadcrumbItem.tsx
7
- * @input Uses React use/useRef/useEffect, stylex, theme tokens, BreadcrumbContext
7
+ * @input Uses React use/useRef/useEffect, stylex, theme tokens, BreadcrumbContext,
8
+ * and (for the menu trigger) usePopover + the shared DropdownMenu item API
9
+ * (renderDropdownItems, DropdownMenuContext, MENU_ITEM_SELECTOR, useListFocus)
8
10
  * @output Exports BreadcrumbItem component and BreadcrumbItemProps
9
11
  * @position Individual breadcrumb item; used inside Breadcrumbs
10
12
  *
13
+ * A `menu` prop turns the item's link-styled button into a menu trigger whose
14
+ * popover reuses DropdownMenu's item pipeline — the same wiring ContextMenu
15
+ * uses — so menu-item definitions are portable across the menu family.
16
+ *
11
17
  * SYNC: When modified, update these files to stay in sync:
12
18
  * - /packages/core/src/Breadcrumbs/Breadcrumbs.doc.mjs
13
19
  * - /packages/core/src/Breadcrumbs/Breadcrumbs.test.tsx
@@ -15,14 +21,22 @@
15
21
  * - /apps/storybook/stories/Breadcrumbs.stories.tsx
16
22
  * - /packages/cli/templates/blocks/components/Breadcrumbs/ (showcase blocks)
17
23
  */
18
- import React, { use, useRef, useEffect } from 'react';
24
+ import React, { use, useCallback, useId, useMemo, useRef, useEffect } from 'react';
19
25
  import * as stylex from '@stylexjs/stylex';
20
26
  import "../theme/tokens.stylex.js";
21
- import { colorVars, spacingVars, typeScaleVars } from "../theme/tokens.stylex.js";
27
+ import { colorVars, spacingVars, typeScaleVars, radiusVars } from "../theme/tokens.stylex.js";
22
28
  import { BreadcrumbContext } from "./Breadcrumbs.js";
23
29
  import { useLinkComponent } from "../Link/useLinkComponent.js";
24
30
  import { mergeProps, mergeRefs } from "../utils/index.js";
25
31
  import { themeProps } from "../utils/themeProps.js";
32
+ import { getIcon } from "../Icon/globalIconRegistry.js";
33
+ import { usePopover } from "../Popover/usePopover.js";
34
+ import { useListFocus } from "../hooks/useListFocus.js";
35
+ import { useTypeahead } from "../hooks/useTypeahead.js";
36
+ import { layerAnimations } from "../Layer/layerAnimations.stylex.js";
37
+ import { renderDropdownItems } from "../DropdownMenu/renderDropdownItems.js";
38
+ import { DropdownMenuContext } from "../DropdownMenu/DropdownMenuContext.js";
39
+ import { MENU_ITEM_ROLES, MENU_ITEM_SELECTOR } from "../DropdownMenu/menuItemRoles.js";
26
40
 
27
41
  // =============================================================================
28
42
  // Props
@@ -52,6 +66,13 @@ const itemStyles = {
52
66
  $$css: true
53
67
  }
54
68
  };
69
+ const menuStyles = {
70
+ popover: {
71
+ k7Eaqz: "x5w4yej",
72
+ kqGvvJ: "xsq74q5",
73
+ $$css: true
74
+ }
75
+ };
55
76
 
56
77
  // =============================================================================
57
78
  // Component
@@ -79,6 +100,8 @@ export function BreadcrumbItem({
79
100
  onClick,
80
101
  isCurrent: isCurrentProp,
81
102
  startIcon,
103
+ menu,
104
+ menuSize,
82
105
  xstyle,
83
106
  className,
84
107
  style,
@@ -95,6 +118,21 @@ export function BreadcrumbItem({
95
118
  const contentRef = useRef(null);
96
119
  const isCurrent = isCurrentProp === true;
97
120
  const isAutoCandidate = isCurrentProp == null;
121
+ const hasMenu = menu != null;
122
+ const resolvedMenuSize = menuSize ?? (isSupporting ? 'sm' : 'md');
123
+
124
+ // `menu` owns the click interaction; a label can't both navigate/act and
125
+ // open a menu on the same activation. Warn once so the (ignored) href/onClick
126
+ // don't silently disappear on the consumer.
127
+ useEffect(() => {
128
+ if (process.env.NODE_ENV !== 'production' && hasMenu) {
129
+ if (href != null) {
130
+ console.warn('BreadcrumbItem: `menu` and `href` are mutually exclusive; `menu` ' + 'takes precedence and `href` is ignored.');
131
+ } else if (onClick != null) {
132
+ console.warn('BreadcrumbItem: `menu` and `onClick` are mutually exclusive; ' + '`menu` takes precedence and `onClick` is ignored.');
133
+ }
134
+ }
135
+ }, [hasMenu, href, onClick]);
98
136
 
99
137
  // Auto-detect: if no sibling has aria-current="page" and this is the last
100
138
  // non-separator item, set aria-current on our content element.
@@ -152,7 +190,19 @@ export function BreadcrumbItem({
152
190
  className: "x11ke7fs x6s0dn4 xv1l7n4 xu0wf1k x87ps6o"
153
191
  },
154
192
  children: ctx.separator
155
- }), /*#__PURE__*/_jsx("span", {
193
+ }), hasMenu ?
194
+ /*#__PURE__*/
195
+ // A current crumb can also open a sibling menu — the trigger keeps
196
+ // both aria-current="page" and aria-haspopup="menu".
197
+ _jsx(BreadcrumbMenuTrigger, {
198
+ ref: contentRef,
199
+ menu: menu,
200
+ menuSize: resolvedMenuSize,
201
+ isSupporting: isSupporting,
202
+ isCurrent: true,
203
+ label: children,
204
+ children: content
205
+ }) : /*#__PURE__*/_jsx("span", {
156
206
  ...{
157
207
  0: {
158
208
  className: "x78zum5 x6s0dn4 xzye2dw x1pd3egz x1tgivj0"
@@ -180,7 +230,14 @@ export function BreadcrumbItem({
180
230
  className: "x11ke7fs x6s0dn4 xv1l7n4 xu0wf1k x87ps6o"
181
231
  },
182
232
  children: ctx.separator
183
- }), href != null ? /*#__PURE__*/_jsx(LinkComponent, {
233
+ }), hasMenu ? /*#__PURE__*/_jsx(BreadcrumbMenuTrigger, {
234
+ ref: contentRef,
235
+ menu: menu,
236
+ menuSize: resolvedMenuSize,
237
+ isSupporting: isSupporting,
238
+ label: children,
239
+ children: content
240
+ }) : href != null ? /*#__PURE__*/_jsx(LinkComponent, {
184
241
  ref: contentRef,
185
242
  href: href,
186
243
  onClick: onClick,
@@ -220,4 +277,149 @@ export function BreadcrumbItem({
220
277
  })]
221
278
  });
222
279
  }
223
- BreadcrumbItem.displayName = 'BreadcrumbItem';
280
+ BreadcrumbItem.displayName = 'BreadcrumbItem';
281
+
282
+ // =============================================================================
283
+ // Menu trigger
284
+ // =============================================================================
285
+
286
+ /**
287
+ * The link-styled `<button>` trigger + its `role="menu"` popover. Reuses the
288
+ * DropdownMenu item pipeline (`renderDropdownItems` for arrays, the item
289
+ * components for children) inside a `useListFocus` container that provides
290
+ * `DropdownMenuContext` — the same wiring ContextMenu uses — so menu-item
291
+ * definitions are portable into a breadcrumb with no rewrite.
292
+ */
293
+ function BreadcrumbMenuTrigger({
294
+ ref,
295
+ children,
296
+ label,
297
+ menu,
298
+ menuSize,
299
+ isSupporting,
300
+ isCurrent = false
301
+ }) {
302
+ const menuId = useId();
303
+ const buttonRef = useRef(null);
304
+ const popover = usePopover({
305
+ onHide: useCallback(() => {
306
+ buttonRef.current?.focus();
307
+ }, []),
308
+ hasLightDismiss: true,
309
+ hasCloseButton: false,
310
+ hasAutoFocus: false,
311
+ // The popup's own role="menu" is the exposed semantics; a modal dialog
312
+ // wrapper would announce an unnamed dialog around the menu.
313
+ role: 'none'
314
+ });
315
+ const closeMenu = useCallback(() => {
316
+ popover.hide();
317
+ }, [popover]);
318
+ const {
319
+ listRef,
320
+ handleKeyDown: listNavKeyDown,
321
+ focusFirst,
322
+ focusItem
323
+ } = useListFocus({
324
+ itemSelector: MENU_ITEM_SELECTOR,
325
+ wrap: false,
326
+ onEscape: closeMenu
327
+ });
328
+ const getMenuItems = useCallback(() => listRef.current ? Array.from(listRef.current.querySelectorAll(MENU_ITEM_SELECTOR)) : [], [listRef]);
329
+ const typeahead = useTypeahead({
330
+ getItemLabels: () => getMenuItems().map(el => el.textContent),
331
+ onMatch: focusItem,
332
+ getCurrentIndex: () => getMenuItems().findIndex(el => el === document.activeElement || el.contains(document.activeElement))
333
+ });
334
+ const listKeyDown = useCallback(e => {
335
+ if (e.key === 'Enter' || e.key === ' ') {
336
+ e.preventDefault();
337
+ const focused = document.activeElement;
338
+ if (focused && MENU_ITEM_ROLES.has(focused.getAttribute('role') ?? '')) {
339
+ focused.click();
340
+ }
341
+ return;
342
+ }
343
+ // APG menu-button pattern: Tab closes the menu (items are tabIndex={-1}).
344
+ if (e.key === 'Tab') {
345
+ closeMenu();
346
+ return;
347
+ }
348
+ if (typeahead.onKeyDown(e)) {
349
+ e.preventDefault();
350
+ return;
351
+ }
352
+ listNavKeyDown(e);
353
+ }, [listNavKeyDown, closeMenu, typeahead]);
354
+ const openAndFocus = useCallback(() => {
355
+ popover.show();
356
+ requestAnimationFrame(() => focusFirst());
357
+ }, [popover, focusFirst]);
358
+ const handleClick = useCallback(() => {
359
+ if (popover.isOpen) {
360
+ popover.hide();
361
+ } else {
362
+ openAndFocus();
363
+ }
364
+ }, [popover, openAndFocus]);
365
+ const handleKeyDown = useCallback(e => {
366
+ if (!popover.isOpen) {
367
+ if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {
368
+ e.preventDefault();
369
+ openAndFocus();
370
+ }
371
+ }
372
+ }, [popover.isOpen, openAndFocus]);
373
+ const contextValue = useMemo(() => ({
374
+ closeMenu,
375
+ menuSize
376
+ }), [closeMenu, menuSize]);
377
+ const menuContent = Array.isArray(menu) ? renderDropdownItems(menu) : menu;
378
+ return /*#__PURE__*/_jsxs(_Fragment, {
379
+ children: [/*#__PURE__*/_jsxs("button", {
380
+ ref: mergeRefs(ref, buttonRef, popover.triggerRef),
381
+ type: "button",
382
+ onClick: handleClick,
383
+ onKeyDown: handleKeyDown,
384
+ ...mergeProps(themeProps('breadcrumb-item-menu-trigger'), {
385
+ ...popover.triggerProps,
386
+ 'aria-haspopup': 'menu',
387
+ 'aria-controls': menuId,
388
+ 'aria-current': isCurrent ? 'page' : undefined
389
+ }),
390
+ ...{
391
+ 0: {
392
+ className: "x78zum5 x6s0dn4 xzye2dw xu0wf1k x1hl2dhg x4ohgrr x1ypdohk x1717udv x1ghz6dp xln7xf2 xv1l7n4"
393
+ },
394
+ 1: {
395
+ className: "x78zum5 x6s0dn4 xzye2dw xu0wf1k x1hl2dhg x4ohgrr x1ypdohk x1717udv x1ghz6dp xln7xf2 xv1l7n4"
396
+ }
397
+ }[!!isSupporting << 0],
398
+ children: [children, /*#__PURE__*/_jsx("span", {
399
+ "aria-hidden": "true",
400
+ ...{
401
+ className: "x78zum5 x6s0dn4 x2lah0s x141an7d"
402
+ },
403
+ children: getIcon('chevronDown')
404
+ })]
405
+ }), popover.render(/*#__PURE__*/_jsx("div", {
406
+ ref: listRef,
407
+ id: menuId,
408
+ role: "menu",
409
+ "aria-label": typeof label === 'string' ? label : undefined,
410
+ onKeyDown: listKeyDown,
411
+ ...mergeProps(themeProps('breadcrumb-menu'), {
412
+ className: "x9f619 x78zum5 xdt5ytf x1lsbc85 xuyqlj2 x1odjw0f x1fcsqxe xgory14 x9epnlk x1n97fys x87ps6o"
413
+ }),
414
+ children: /*#__PURE__*/_jsx(DropdownMenuContext, {
415
+ value: contextValue,
416
+ children: menuContent
417
+ })
418
+ }), {
419
+ placement: 'below',
420
+ alignment: 'start',
421
+ xstyle: [menuStyles.popover, layerAnimations.below]
422
+ })]
423
+ });
424
+ }
425
+ BreadcrumbMenuTrigger.displayName = 'BreadcrumbMenuTrigger';
@@ -5,4 +5,9 @@ export { Breadcrumbs } from './Breadcrumbs';
5
5
  export type { BreadcrumbsProps, BreadcrumbsVariant, BreadcrumbsVariantMap, } from './Breadcrumbs';
6
6
  export { BreadcrumbItem } from './BreadcrumbItem';
7
7
  export type { BreadcrumbItemProps } from './BreadcrumbItem';
8
+ export { DropdownMenuItem as BreadcrumbMenuItem, type DropdownMenuItemProps as BreadcrumbMenuItemProps, } from '../DropdownMenu/DropdownMenuItem';
9
+ export { DropdownMenuCheckboxItem as BreadcrumbMenuCheckboxItem, type DropdownMenuCheckboxItemProps as BreadcrumbMenuCheckboxItemProps, } from '../DropdownMenu/DropdownMenuCheckboxItem';
10
+ export { DropdownMenuRadioGroup as BreadcrumbMenuRadioGroup, type DropdownMenuRadioGroupProps as BreadcrumbMenuRadioGroupProps, } from '../DropdownMenu/DropdownMenuRadioGroup';
11
+ export { DropdownMenuRadioItem as BreadcrumbMenuRadioItem, type DropdownMenuRadioItemProps as BreadcrumbMenuRadioItemProps, } from '../DropdownMenu/DropdownMenuRadioItem';
12
+ export type { DropdownMenuOption as BreadcrumbMenuOption, DropdownMenuItemData as BreadcrumbMenuItemData, DropdownMenuDivider as BreadcrumbMenuDivider, DropdownMenuSection as BreadcrumbMenuSection, } from '../DropdownMenu/DropdownMenu';
8
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Breadcrumbs/index.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAC1C,YAAY,EACV,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAChD,YAAY,EAAC,mBAAmB,EAAC,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Breadcrumbs/index.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAC1C,YAAY,EACV,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAChD,YAAY,EAAC,mBAAmB,EAAC,MAAM,kBAAkB,CAAC;AAM1D,OAAO,EACL,gBAAgB,IAAI,kBAAkB,EACtC,KAAK,qBAAqB,IAAI,uBAAuB,GACtD,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,wBAAwB,IAAI,0BAA0B,EACtD,KAAK,6BAA6B,IAAI,+BAA+B,GACtE,MAAM,0CAA0C,CAAC;AAClD,OAAO,EACL,sBAAsB,IAAI,wBAAwB,EAClD,KAAK,2BAA2B,IAAI,6BAA6B,GAClE,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,qBAAqB,IAAI,uBAAuB,EAChD,KAAK,0BAA0B,IAAI,4BAA4B,GAChE,MAAM,uCAAuC,CAAC;AAC/C,YAAY,EACV,kBAAkB,IAAI,oBAAoB,EAC1C,oBAAoB,IAAI,sBAAsB,EAC9C,mBAAmB,IAAI,qBAAqB,EAC5C,mBAAmB,IAAI,qBAAqB,GAC7C,MAAM,8BAA8B,CAAC"}
@@ -6,4 +6,12 @@
6
6
  * @file Breadcrumbs component barrel export
7
7
  */
8
8
  export { Breadcrumbs } from "./Breadcrumbs.js";
9
- export { BreadcrumbItem } from "./BreadcrumbItem.js";
9
+ export { BreadcrumbItem } from "./BreadcrumbItem.js";
10
+ // The breadcrumb `menu` prop reuses the DropdownMenu item API, so the item
11
+ // components are re-exported under `Breadcrumb*` aliases for family coherence
12
+ // and discoverability (mirroring ContextMenu). A consumer's existing
13
+ // DropdownMenu item definitions are portable into a breadcrumb menu verbatim.
14
+ export { DropdownMenuItem as BreadcrumbMenuItem } from "../DropdownMenu/DropdownMenuItem.js";
15
+ export { DropdownMenuCheckboxItem as BreadcrumbMenuCheckboxItem } from "../DropdownMenu/DropdownMenuCheckboxItem.js";
16
+ export { DropdownMenuRadioGroup as BreadcrumbMenuRadioGroup } from "../DropdownMenu/DropdownMenuRadioGroup.js";
17
+ export { DropdownMenuRadioItem as BreadcrumbMenuRadioItem } from "../DropdownMenu/DropdownMenuRadioItem.js";
@@ -1 +1 @@
1
- {"version":3,"file":"ChatComposer.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatComposer.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,EAKZ,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAyB5C,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;AAEtE,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAC7C,SAAS,CAAC,cAAc,CAAC,EACzB,UAAU,GAAG,UAAU,CACxB;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,+CAA+C;IAC/C,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,kFAAkF;IAClF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,qCAAqC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,sBAAsB;IACtB,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAI3B,6GAA6G;IAC7G,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,yHAAyH;IACzH,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,yGAAyG;IACzG,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,2DAA2D;IAC3D,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,gHAAgH;IAChH,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,gHAAgH;IAChH,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,gDAAgD;IAChD,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,iEAAiE;IACjE,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,oDAAoD;IACpD,cAAc,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;CACnC;AA8LD;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,qBAmKpD;yBAnKe,YAAY"}
1
+ {"version":3,"file":"ChatComposer.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatComposer.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,EAKZ,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AA0B5C,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;AAEtE,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAC7C,SAAS,CAAC,cAAc,CAAC,EACzB,UAAU,GAAG,UAAU,CACxB;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,+CAA+C;IAC/C,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,kFAAkF;IAClF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,qCAAqC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,sBAAsB;IACtB,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAI3B,6GAA6G;IAC7G,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,yHAAyH;IACzH,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,yGAAyG;IACzG,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,2DAA2D;IAC3D,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,gHAAgH;IAChH,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,gHAAgH;IAChH,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,gDAAgD;IAChD,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,iEAAiE;IACjE,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,oDAAoD;IACpD,cAAc,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;CACnC;AA8LD;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,qBAiLpD;yBAjLe,YAAY"}
@@ -152,6 +152,11 @@ export function ChatComposer(props) {
152
152
  }, [currentValue, isDisabled, onSubmit, updateValue]);
153
153
  const canSend = currentValue.trim().length > 0 && !isDisabled;
154
154
  const bodyRef = useRef(null);
155
+
156
+ // Input slot registers its focus (and future) control here so the shell can
157
+ // drive it without knowing its DOM shape. Stable ref — safe in the memoized
158
+ // context value.
159
+ const inputControlRef = useRef(null);
155
160
  const handleBodyClick = useCallback(e => {
156
161
  // Focus the input when clicking empty space in the body.
157
162
  // Skip if the click target is a button, link, or interactive element.
@@ -159,6 +164,14 @@ export function ChatComposer(props) {
159
164
  if (target.closest('button, a, [role="button"], [contenteditable="true"], [data-astryx-token]')) {
160
165
  return;
161
166
  }
167
+ // Prefer the input's registered control (works for any input shape,
168
+ // including editors whose focusable node isn't a bare
169
+ // contenteditable/textarea). Fall back to a DOM query so uninstrumented
170
+ // custom inputs still get click-to-focus.
171
+ if (inputControlRef.current) {
172
+ inputControlRef.current.focus();
173
+ return;
174
+ }
162
175
  const editable = bodyRef.current?.querySelector('[contenteditable="true"], textarea');
163
176
  editable?.focus();
164
177
  }, []);
@@ -204,7 +217,8 @@ export function ChatComposer(props) {
204
217
  isDisabled,
205
218
  isStopShown,
206
219
  canSend,
207
- onStop
220
+ onStop,
221
+ inputControlRef
208
222
  }), [currentValue, updateValue, handleSubmit, placeholder, isDisabled, isStopShown, canSend, onStop]);
209
223
  return /*#__PURE__*/_jsx(ChatComposerContext, {
210
224
  value: composerContext,
@@ -1 +1 @@
1
- {"version":3,"file":"ChatComposerInput.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatComposerInput.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ChatComposerInput.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatComposerInput.tsx"],"names":[],"mappings":"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"}
@@ -191,6 +191,22 @@ export function ChatComposerInput(props) {
191
191
  };
192
192
  selfRef.current = handle;
193
193
  useImperativeHandle(handleRef, () => handle);
194
+
195
+ // Register a focus control with the composer shell so body-click-to-focus
196
+ // works without the shell sniffing the input's DOM shape. Cleared on
197
+ // unmount so the shell falls back cleanly if the input goes away.
198
+ const inputControlRef = composerCtx?.inputControlRef;
199
+ useEffect(() => {
200
+ if (!inputControlRef) {
201
+ return;
202
+ }
203
+ inputControlRef.current = {
204
+ focus: () => editableRef.current?.focus()
205
+ };
206
+ return () => {
207
+ inputControlRef.current = null;
208
+ };
209
+ }, [inputControlRef]);
194
210
  useEffect(() => {
195
211
  if (controlledValue === undefined || !editableRef.current) {
196
212
  return;