@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.
- package/dist/Avatar/Avatar.d.ts +18 -2
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +63 -7
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +31 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +208 -6
- package/dist/Breadcrumbs/index.d.ts +5 -0
- package/dist/Breadcrumbs/index.d.ts.map +1 -1
- package/dist/Breadcrumbs/index.js +9 -1
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +15 -1
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +16 -0
- package/dist/Chat/ChatContext.d.ts +33 -0
- package/dist/Chat/ChatContext.d.ts.map +1 -1
- package/dist/Chat/ChatContext.js +16 -2
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +1 -1
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +4 -4
- package/dist/Chat/ChatSendButton.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.js +7 -1
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +6 -6
- package/dist/Chat/index.d.ts +2 -1
- package/dist/Chat/index.d.ts.map +1 -1
- package/dist/Chat/index.js +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +1 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +4 -10
- package/dist/ClickableCard/ClickableCard.js +2 -2
- package/dist/CommandPalette/CommandPalette.d.ts +1 -1
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +3 -1
- package/dist/DateInput/DateInput.d.ts +47 -1
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +26 -2
- package/dist/DateInput/index.d.ts +1 -1
- package/dist/DateInput/index.d.ts.map +1 -1
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +4 -3
- package/dist/Divider/Divider.js +1 -1
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +2 -3
- package/dist/Field/FieldLabel.d.ts +1 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +42 -15
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +3 -2
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +3 -9
- package/dist/SelectableCard/SelectableCard.js +2 -2
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +4 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +3 -2
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +5 -3
- package/dist/Thumbnail/Thumbnail.d.ts +16 -9
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +65 -86
- package/dist/Thumbnail/thumbnail.markers.stylex.d.ts +9 -0
- package/dist/Thumbnail/thumbnail.markers.stylex.d.ts.map +1 -0
- package/dist/Thumbnail/thumbnail.markers.stylex.js +14 -0
- package/dist/Timestamp/Timestamp.d.ts +3 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +8 -6
- package/dist/Toast/useToast.d.ts.map +1 -1
- package/dist/Toast/useToast.js +2 -5
- package/dist/astryx.css +6 -10
- package/dist/astryx.umd.js +47 -47
- package/dist/astryx.umd.js.map +4 -4
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +2 -1
- package/dist/hooks/useDevWarning.d.ts +18 -0
- package/dist/hooks/useDevWarning.d.ts.map +1 -0
- package/dist/hooks/useDevWarning.js +49 -0
- package/dist/hooks/useOverflow.d.ts.map +1 -1
- package/dist/hooks/useOverflow.js +2 -3
- package/dist/i18n/resolve.d.ts.map +1 -1
- package/dist/i18n/resolve.js +7 -18
- package/dist/theme/Theme.d.ts.map +1 -1
- package/dist/theme/Theme.js +2 -7
- package/dist/theme/syntax/defineSyntaxTheme.d.ts.map +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.js +2 -1
- package/dist/utils/devWarning.d.ts +42 -0
- package/dist/utils/devWarning.d.ts.map +1 -0
- package/dist/utils/devWarning.js +88 -0
- package/dist/utils/index.d.ts +3 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +3 -2
- package/dist/utils/plainDate.d.ts +30 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +53 -0
- package/package.json +1 -1
- package/src/Avatar/Avatar.doc.mjs +10 -0
- package/src/Avatar/Avatar.test.tsx +156 -1
- package/src/Avatar/Avatar.tsx +96 -4
- package/src/Breadcrumbs/BreadcrumbItem.doc.mjs +26 -0
- package/src/Breadcrumbs/BreadcrumbItem.tsx +333 -14
- package/src/Breadcrumbs/Breadcrumbs.doc.mjs +2 -0
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +284 -2
- package/src/Breadcrumbs/index.ts +27 -0
- package/src/Chat/ChatComposer.doc.mjs +3 -3
- package/src/Chat/ChatComposer.test.tsx +82 -2
- package/src/Chat/ChatComposer.tsx +15 -0
- package/src/Chat/ChatComposerInput.test.tsx +16 -0
- package/src/Chat/ChatComposerInput.tsx +14 -0
- package/src/Chat/ChatContext.tsx +37 -10
- package/src/Chat/ChatDictationButton.tsx +4 -1
- package/src/Chat/ChatLayoutScrollButton.tsx +4 -1
- package/src/Chat/ChatSendButton.tsx +6 -0
- package/src/Chat/ChatToolCalls.tsx +12 -3
- package/src/Chat/index.ts +5 -1
- package/src/CheckboxInput/CheckboxInput.tsx +1 -1
- package/src/CheckboxList/CheckboxListItem.tsx +11 -19
- package/src/ClickableCard/ClickableCard.tsx +2 -2
- package/src/CommandPalette/CommandPalette.tsx +3 -1
- package/src/DateInput/DateInput.doc.mjs +16 -0
- package/src/DateInput/DateInput.test.tsx +108 -0
- package/src/DateInput/DateInput.tsx +68 -3
- package/src/DateInput/index.ts +1 -0
- package/src/Dialog/Dialog.tsx +6 -4
- package/src/Divider/Divider.tsx +2 -2
- package/src/Field/Field.tsx +6 -5
- package/src/Field/FieldLabel.tsx +8 -0
- package/src/Popover/Popover.tsx +7 -4
- package/src/Popover/usePopover.tsx +9 -13
- package/src/SelectableCard/SelectableCard.tsx +2 -2
- package/src/Slider/Slider.test.tsx +13 -0
- package/src/Slider/Slider.tsx +6 -4
- package/src/Table/BaseTable.tsx +3 -5
- package/src/Table/useBaseTablePlugins.ts +10 -6
- package/src/Thumbnail/Thumbnail.doc.mjs +13 -13
- package/src/Thumbnail/Thumbnail.test.tsx +47 -21
- package/src/Thumbnail/Thumbnail.tsx +103 -79
- package/src/Thumbnail/thumbnail.markers.stylex.ts +12 -0
- package/src/Timestamp/Timestamp.doc.mjs +4 -4
- package/src/Timestamp/Timestamp.test.tsx +32 -0
- package/src/Timestamp/Timestamp.tsx +28 -8
- package/src/Toast/useToast.tsx +7 -8
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useDevWarning.test.tsx +45 -0
- package/src/hooks/useDevWarning.ts +54 -0
- package/src/hooks/useOverflow.ts +8 -11
- package/src/i18n/InternationalizationProvider.doc.mjs +22 -0
- package/src/i18n/resolve.ts +9 -21
- package/src/theme/Theme.tsx +11 -14
- package/src/theme/syntax/defineSyntaxTheme.ts +5 -6
- package/src/utils/devWarning.test.ts +56 -0
- package/src/utils/devWarning.ts +102 -0
- package/src/utils/index.ts +6 -0
- package/src/utils/plainDate.test.ts +22 -0
- package/src/utils/plainDate.ts +61 -0
package/dist/Avatar/Avatar.d.ts
CHANGED
|
@@ -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
|
|
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"}
|
package/dist/Avatar/Avatar.js
CHANGED
|
@@ -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
|
-
|
|
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:
|
|
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
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
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;
|
|
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":"AAIA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAML,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,cAAc,EACpB,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,cAAc,EAAE,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAarE,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAQ,KAAK,UAAU,EAAC,MAAM,UAAU,CAAC;AAShD,mEAAmE;AACnE,MAAM,WAAW,uBAAuB;IACtC,iEAAiE;IACjE,WAAW,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,MAAM,GAAG,SAAS,CAAC;IAC9D,6EAA6E;IAC7E,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,uDAAuD;IACvD,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,sBAAsB;IACtB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,MAAM,CAAC;CACxB;AAED,wFAAwF;AACxF,MAAM,MAAM,sBAAsB,GAAG;IACnC,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,GAAG,QAAQ,GAAG,WAAW,GAAG,OAAO,CAAC,CAAC;AAE/D,mFAAmF;AACnF,MAAM,MAAM,uBAAuB,GAAG;IACpC,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,MAAM,EAAE,MAAM,SAAS,CAAC;CACzB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,GAC3B,sBAAsB,GAAG,uBAAuB,CAAC;AAEnD,MAAM,MAAM,uBAAuB,GAAG,cAAc,CAAC;AAErD,MAAM,MAAM,mBAAmB,GAAG;IAChC,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;;;;;;;;OAiBG;IACH,YAAY,EAAE,YAAY,CAAC;IAC3B,kDAAkD;IAClD,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,SAAS,CAAC;IACjD;;;OAGG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,MAAM,GAAG,iBAAiB,CAAC;IAC/D;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,iBAAiB,GAAG,IAAI,CAAC;IAC1D,8DAA8D;IAC9D,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,WAAW,sBAAuB,SAAQ,IAAI,CAClD,SAAS,CAAC,cAAc,CAAC,EACzB,UAAU,GAAG,SAAS,GAAG,UAAU,CACpC;IACC,yCAAyC;IACzC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,sDAAsD;IACtD,SAAS,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IAC/C,uBAAuB;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACjC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,0IAA0I;IAC1I,OAAO,CAAC,EAAE,CACR,KAAK,EAAE,cAAc,CAAC,cAAc,CAAC,EACrC,IAAI,EAAE,MAAM,KACT,OAAO,GAAG,IAAI,CAAC;IACpB;;;;OAIG;IACH,YAAY,CAAC,EAAE,yBAAyB,GAAG,KAAK,CAAC;IACjD,8BAA8B;IAC9B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IAClC,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;;;;;;;;;;;OAaG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC;CAC5D;AA0FD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,+BAyb9D;yBAzbe,iBAAiB;;;AAicjC,wBAAgB,wBAAwB,CAAC,EAAC,KAAK,EAAC,EAAE;IAAC,KAAK,EAAE,iBAAiB,CAAA;CAAC,+BAc3E;yBAde,wBAAwB"}
|
|
@@ -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;
|