@astryxdesign/core 0.5.2-canary.4a88299 → 0.5.2-canary.4f39c7e
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/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +6 -2
- package/dist/Banner/Banner.d.ts +5 -0
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +7 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +3 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +22 -15
- package/dist/Chat/ChatComposer.d.ts +2 -2
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +24 -3
- package/dist/CheckboxList/CheckboxListItem.d.ts +5 -3
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.d.ts +30 -5
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +17 -4
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +81 -44
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +8 -9
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +125 -77
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +55 -26
- package/dist/Tokenizer/useEndLaneReserve.d.ts +30 -0
- package/dist/Tokenizer/useEndLaneReserve.d.ts.map +1 -0
- package/dist/Tokenizer/useEndLaneReserve.js +127 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +52 -17
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +79 -66
- package/dist/Typeahead/busyIndicatorLane.d.ts +33 -0
- package/dist/Typeahead/busyIndicatorLane.d.ts.map +1 -0
- package/dist/Typeahead/busyIndicatorLane.js +46 -0
- package/dist/astryx.css +7 -5
- package/package.json +2 -2
- package/src/AppShell/AppShell.test.tsx +21 -0
- package/src/AppShell/AppShell.tsx +8 -2
- package/src/Banner/Banner.doc.mjs +5 -1
- package/src/Banner/Banner.tsx +12 -1
- package/src/BottomSheet/BottomSheet.spec.md +2 -1
- package/src/Breadcrumbs/BreadcrumbItem.tsx +18 -9
- package/src/Breadcrumbs/Breadcrumbs.doc.mjs +4 -1
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +12 -0
- package/src/Chat/ChatComposer.doc.mjs +7 -4
- package/src/Chat/ChatComposer.test.tsx +84 -2
- package/src/Chat/ChatComposer.tsx +48 -3
- package/src/CheckboxList/CheckboxList.spec.md +2 -1
- package/src/CheckboxList/CheckboxList.test.tsx +45 -0
- package/src/CheckboxList/CheckboxListItem.doc.mjs +11 -9
- package/src/CheckboxList/CheckboxListItem.tsx +5 -3
- package/src/CommandPalette/CommandPalette.spec.md +2 -1
- package/src/ComplexSelector/ComplexSelector.spec.md +2 -1
- package/src/ContextMenu/ContextMenu.spec.md +2 -1
- package/src/DateTimeInput/DateTimeInput.doc.mjs +3 -3
- package/src/Divider/Divider.spec.md +2 -1
- package/src/DropdownMenu/DropdownMenu.spec.md +2 -1
- package/src/FieldStatus/FieldStatus.spec.md +2 -1
- package/src/Grid/Grid.spec.md +2 -1
- package/src/Icon/Icon.spec.md +2 -1
- package/src/Kbd/Kbd.spec.md +2 -1
- package/src/Layout/Layout.spec.md +2 -1
- package/src/Lightbox/Lightbox.spec.md +2 -1
- package/src/Markdown/Markdown.spec.md +2 -1
- package/src/MobileNav/MobileNav.spec.md +2 -1
- package/src/MoreMenu/MoreMenu.spec.md +2 -1
- package/src/MultiSelector/MultiSelector.spec.md +2 -1
- package/src/NavIcon/NavIcon.spec.md +2 -1
- package/src/NavMenu/NavHeadingMenu.spec.md +2 -1
- package/src/Outline/Outline.spec.md +2 -1
- package/src/OverflowList/OverflowList.spec.md +2 -1
- package/src/Pagination/Pagination.spec.md +2 -1
- package/src/Popover/Popover.doc.mjs +3 -3
- package/src/Popover/Popover.spec.md +2 -1
- package/src/PowerSearch/PowerSearch.spec.md +2 -1
- package/src/ProgressBar/ProgressBar.spec.md +2 -1
- package/src/RadioList/RadioList.test.tsx +136 -2
- package/src/RadioList/RadioListItem.doc.mjs +30 -11
- package/src/RadioList/RadioListItem.tsx +44 -8
- package/src/Resizable/Resizable.spec.md +2 -1
- package/src/Resizable/ResizeHandle.test.tsx +99 -54
- package/src/Resizable/ResizeHandle.tsx +98 -45
- package/src/Section/Section.spec.md +2 -1
- package/src/SegmentedControl/SegmentedControl.spec.md +2 -1
- package/src/Selector/Selector.spec.md +2 -1
- package/src/SideNav/SideNav.test.tsx +3 -3
- package/src/SideNav/SideNavItem.doc.mjs +1 -1
- package/src/Skeleton/Skeleton.spec.md +2 -1
- package/src/Slider/Slider.spec.md +2 -1
- package/src/Spinner/Spinner.doc.mjs +5 -5
- package/src/Spinner/Spinner.test.tsx +32 -7
- package/src/Spinner/Spinner.tsx +25 -13
- package/src/Stack/Stack.spec.md +2 -1
- package/src/StatusDot/StatusDot.spec.md +2 -1
- package/src/Stepper/Stepper.doc.mjs +1 -1
- package/src/Switch/Switch.spec.md +2 -1
- package/src/Table/Table.spec.md +93 -53
- package/src/Table/plugins/rowStatus/useTableRowStatus.spec.md +354 -0
- package/src/Table/useTableGroupedRows.doc.mjs +2 -2
- package/src/Text/Text.spec.md +2 -1
- package/src/TextArea/TextArea.spec.md +2 -1
- package/src/Toast/ToastViewport.test.tsx +194 -0
- package/src/Toast/ToastViewport.tsx +136 -58
- package/src/Tokenizer/Tokenizer.doc.mjs +2 -0
- package/src/Tokenizer/Tokenizer.spec.md +2 -1
- package/src/Tokenizer/Tokenizer.test.tsx +264 -1
- package/src/Tokenizer/Tokenizer.tsx +67 -34
- package/src/Tokenizer/useEndLaneReserve.ts +128 -0
- package/src/Toolbar/Toolbar.spec.md +2 -1
- package/src/Tooltip/Tooltip.spec.md +2 -1
- package/src/TreeList/TreeList.spec.md +2 -1
- package/src/Typeahead/BaseTypeahead.tsx +57 -16
- package/src/Typeahead/Typeahead.doc.mjs +6 -0
- package/src/Typeahead/Typeahead.spec.md +9 -2
- package/src/Typeahead/Typeahead.test.tsx +370 -1
- package/src/Typeahead/Typeahead.tsx +147 -69
- package/src/Typeahead/busyIndicatorLane.tsx +52 -0
- package/src/theme/themingTargets.test.ts +39 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppShell.d.ts","sourceRoot":"","sources":["../../src/AppShell/AppShell.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAmBf,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAO5C,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,SAAS,CAAC;AA+BhD;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;AAE7D;;;;;;;GAOG;AAEH;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,kBAAkB,CAAC;AAEvD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAEzC;;;;OAIG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IAEpB;;;OAGG;IACH,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAEhC;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,aAAc,SAAQ,SAAS,CAAC,cAAc,CAAC;IAC9D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,eAAe,CAAC;IAE1B;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IAEnB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,WAAW,CAAC;IAE7B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAEzB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,SAAS,CAAC,EAAE,KAAK,GAAG,eAAe,GAAG,SAAS,CAAC;IAEhD;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IAEpB;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"AppShell.d.ts","sourceRoot":"","sources":["../../src/AppShell/AppShell.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAmBf,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAO5C,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,SAAS,CAAC;AA+BhD;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;AAE7D;;;;;;;GAOG;AAEH;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,kBAAkB,CAAC;AAEvD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAEzC;;;;OAIG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IAEpB;;;OAGG;IACH,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAEhC;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,aAAc,SAAQ,SAAS,CAAC,cAAc,CAAC;IAC9D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,eAAe,CAAC;IAE1B;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IAEnB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,WAAW,CAAC;IAE7B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAEzB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,SAAS,CAAC,EAAE,KAAK,GAAG,eAAe,GAAG,SAAS,CAAC;IAEhD;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IAEpB;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AA4KD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,QAAQ,CAAC,EACvB,OAAoB,EACpB,MAAM,EACN,QAAQ,EACR,cAAc,EACd,aAAa,EAAE,UAAU,EACzB,MAAe,EACf,SAAS,EACT,OAAO,EACP,MAAM,EACN,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,IAAI,EACR,EAAE,aAAa,qBAkZf;yBAjae,QAAQ"}
|
|
@@ -105,6 +105,7 @@ const styles = {
|
|
|
105
105
|
k1xSpc: "x78zum5",
|
|
106
106
|
kXwgrk: "xdt5ytf",
|
|
107
107
|
kVAEAm: "x1n2onr6",
|
|
108
|
+
kVQacm: "x7giv3",
|
|
108
109
|
$$css: true
|
|
109
110
|
},
|
|
110
111
|
variantWash: {
|
|
@@ -294,6 +295,9 @@ export function AppShell({
|
|
|
294
295
|
const navHasDividers = variant === 'section';
|
|
295
296
|
const isElevated = variant === 'elevated';
|
|
296
297
|
const navAreaStyle = variant === 'wash' || variant === 'elevated' ? styles.navAreaWash : variant === 'surface' ? styles.navAreaSurface : undefined;
|
|
298
|
+
// Section normally inherits the shell's surface background. Its auto-height
|
|
299
|
+
// header needs to paint that surface itself while content scrolls beneath it.
|
|
300
|
+
const headerAreaStyle = navAreaStyle ?? (isAuto && variant === 'section' ? styles.navAreaSurface : undefined);
|
|
297
301
|
const contentAreaStyle = variant === 'wash' ? styles.contentBgWash : variant === 'elevated' && hasTopNav && hasSideNav && !isBelowBreakpoint ? styles.contentBgTransparent : variant === 'surface' || variant === 'elevated' ? styles.contentBgSurface : undefined;
|
|
298
302
|
|
|
299
303
|
// Background for sticky elements in auto mode — must be opaque so content
|
|
@@ -395,7 +399,7 @@ export function AppShell({
|
|
|
395
399
|
role: "banner",
|
|
396
400
|
...mergeProps(themeProps('app-shell-header', {
|
|
397
401
|
variant
|
|
398
|
-
}), stylex.props(
|
|
402
|
+
}), stylex.props(headerAreaStyle, isAuto && styles.headerSticky)),
|
|
399
403
|
children: headerInner
|
|
400
404
|
}) : undefined;
|
|
401
405
|
|
|
@@ -473,7 +477,7 @@ export function AppShell({
|
|
|
473
477
|
role: headerContent == null ? 'banner' : undefined,
|
|
474
478
|
...mergeProps(themeProps('app-shell-header', {
|
|
475
479
|
variant
|
|
476
|
-
}), stylex.props(
|
|
480
|
+
}), stylex.props(headerAreaStyle, isAuto && styles.headerSticky)),
|
|
477
481
|
children: /*#__PURE__*/_jsx(LayoutHeader, {
|
|
478
482
|
padding: 0,
|
|
479
483
|
hasDivider: navHasDividers,
|
package/dist/Banner/Banner.d.ts
CHANGED
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
* - Status icon (themeProps 'banner-icon'): the target rides on the default
|
|
12
12
|
* <Icon> itself — the element that paints — so 'status:X' overrides reach
|
|
13
13
|
* the glyph (#4166); for a custom `icon` node it stays on the layout wrapper
|
|
14
|
+
* - Description (themeProps 'banner-description'): the supporting line owns its
|
|
15
|
+
* own colour and type, and the space between it and the title
|
|
16
|
+
* - The end area carries no target: it is a layout row (flex, wrap, edge
|
|
17
|
+
* compensation) rather than a painted surface, and a theme that wants the
|
|
18
|
+
* header to grow around its buttons sets `padding-block` on 'banner'
|
|
14
19
|
* - No left border accent — color is expressed through the full header background
|
|
15
20
|
* - Each visual area owns its own border-radius (no overflow:clip on the container)
|
|
16
21
|
* - Children are collapsible by default: a toggle appears in the header end
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Banner.d.ts","sourceRoot":"","sources":["../../src/Banner/Banner.tsx"],"names":[],"mappings":"AAIA
|
|
1
|
+
{"version":3,"file":"Banner.d.ts","sourceRoot":"","sources":["../../src/Banner/Banner.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,EAA0B,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAE9D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAgB5C,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,+BAA+B,CAAC;AAErE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAI9C,OAAO,KAAK,EAAC,eAAe,EAAE,kBAAkB,EAAC,MAAM,SAAS,CAAC;AAMjE;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,kBAAkB,CAAC;AAEvD,MAAM,WAAW,WAAY,SAAQ,SAAS,CAAC,cAAc,CAAC;IAC5D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;OAEG;IACH,MAAM,EAAE,YAAY,CAAC;IACrB;;OAEG;IACH,KAAK,EAAE,SAAS,CAAC;IACjB;;OAEG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;;;;;;;;;;;;;;;OAkBG;IACH,WAAW,CAAC,EAAE,OAAO,GAAG,iBAAiB,CAAC;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAmND;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,wBAAgB,MAAM,CAAC,EACrB,MAAM,EACN,KAAK,EACL,WAAW,EACX,IAAI,EACJ,aAAqB,EACrB,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAkB,EAClB,SAAkB,EAClB,WAAkB,EAClB,QAAQ,EACR,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,cAAc,EACd,oBAAoB,EACpB,GAAG,IAAI,EACR,EAAE,WAAW,sCAmPb;yBAvQe,MAAM"}
|
package/dist/Banner/Banner.js
CHANGED
|
@@ -15,6 +15,11 @@
|
|
|
15
15
|
* - Status icon (themeProps 'banner-icon'): the target rides on the default
|
|
16
16
|
* <Icon> itself — the element that paints — so 'status:X' overrides reach
|
|
17
17
|
* the glyph (#4166); for a custom `icon` node it stays on the layout wrapper
|
|
18
|
+
* - Description (themeProps 'banner-description'): the supporting line owns its
|
|
19
|
+
* own colour and type, and the space between it and the title
|
|
20
|
+
* - The end area carries no target: it is a layout row (flex, wrap, edge
|
|
21
|
+
* compensation) rather than a painted surface, and a theme that wants the
|
|
22
|
+
* header to grow around its buttons sets `padding-block` on 'banner'
|
|
18
23
|
* - No left border accent — color is expressed through the full header background
|
|
19
24
|
* - Each visual area owns its own border-radius (no overflow:clip on the container)
|
|
20
25
|
* - Children are collapsible by default: a toggle appears in the header end
|
|
@@ -429,9 +434,9 @@ export function Banner({
|
|
|
429
434
|
},
|
|
430
435
|
children: title
|
|
431
436
|
}), isRenderable(description) && /*#__PURE__*/_jsx("div", {
|
|
432
|
-
...{
|
|
437
|
+
...mergeProps(themeProps('banner-description'), {
|
|
433
438
|
className: "x1ghz6dp xjb2p0i x141an7d x1sodnla x1ltkj2j xv1l7n4 xj0a0fe"
|
|
434
|
-
},
|
|
439
|
+
}),
|
|
435
440
|
children: description
|
|
436
441
|
})]
|
|
437
442
|
}), showEndArea && /*#__PURE__*/_jsxs("div", {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file BreadcrumbItem.tsx
|
|
3
3
|
* @input Uses React use/useRef/useEffect, stylex, theme tokens, BreadcrumbContext,
|
|
4
|
-
*
|
|
5
|
-
* (renderDropdownItems,
|
|
4
|
+
* rtlStyles for the contextual default slash, and (for the menu trigger)
|
|
5
|
+
* usePopover + the shared DropdownMenu item API (renderDropdownItems,
|
|
6
|
+
* DropdownMenuContext, MENU_ITEM_SELECTOR, useListFocus)
|
|
6
7
|
* @output Exports BreadcrumbItem component and BreadcrumbItemProps
|
|
7
8
|
* @position Individual breadcrumb item; used inside Breadcrumbs
|
|
8
9
|
*
|
|
@@ -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;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,EAOZ,KAAK,SAAS,EACd,KAAK,UAAU,EAChB,MAAM,OAAO,CAAC;AAWf,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,eAAe,CAAC;AAErD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAS5C,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,qCAAqC,CAAC;AAM7C,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,8BAA8B,CAAC;AAOrE,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;AAqID;;;;;;;;;;;;;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,qBAkMrB;yBAjNe,cAAc"}
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* @file BreadcrumbItem.tsx
|
|
7
7
|
* @input Uses React use/useRef/useEffect, stylex, theme tokens, BreadcrumbContext,
|
|
8
|
-
*
|
|
9
|
-
* (renderDropdownItems,
|
|
8
|
+
* rtlStyles for the contextual default slash, and (for the menu trigger)
|
|
9
|
+
* usePopover + the shared DropdownMenu item API (renderDropdownItems,
|
|
10
|
+
* DropdownMenuContext, MENU_ITEM_SELECTOR, useListFocus)
|
|
10
11
|
* @output Exports BreadcrumbItem component and BreadcrumbItemProps
|
|
11
12
|
* @position Individual breadcrumb item; used inside Breadcrumbs
|
|
12
13
|
*
|
|
@@ -27,7 +28,7 @@ import "../theme/tokens.stylex.js";
|
|
|
27
28
|
import { colorVars, spacingVars, typeScaleVars, radiusVars, fontWeightVars } from "../theme/tokens.stylex.js";
|
|
28
29
|
import { BreadcrumbContext } from "./Breadcrumbs.js";
|
|
29
30
|
import { useLinkComponent } from "../Link/useLinkComponent.js";
|
|
30
|
-
import { mergeProps } from "../utils/index.js";
|
|
31
|
+
import { mergeProps, rtlStyles } from "../utils/index.js";
|
|
31
32
|
import { themeProps } from "../utils/themeProps.js";
|
|
32
33
|
import { focusOutlineProps } from "../utils/focusOutline.stylex.js";
|
|
33
34
|
import { Icon } from "../Icon/index.js";
|
|
@@ -99,6 +100,20 @@ const itemStyles = {
|
|
|
99
100
|
$$css: true
|
|
100
101
|
}
|
|
101
102
|
};
|
|
103
|
+
function BreadcrumbSeparator({
|
|
104
|
+
separator
|
|
105
|
+
}) {
|
|
106
|
+
return /*#__PURE__*/_jsx("span", {
|
|
107
|
+
"aria-hidden": "true",
|
|
108
|
+
...{
|
|
109
|
+
className: "x11ke7fs x6s0dn4 xv1l7n4 xu0wf1k x87ps6o"
|
|
110
|
+
},
|
|
111
|
+
children: separator === '/' ? /*#__PURE__*/_jsx("span", {
|
|
112
|
+
...stylex.props(rtlStyles.mirror),
|
|
113
|
+
children: "/"
|
|
114
|
+
}) : separator
|
|
115
|
+
});
|
|
116
|
+
}
|
|
102
117
|
const menuStyles = {
|
|
103
118
|
popover: {
|
|
104
119
|
k7Eaqz: "x5w4yej",
|
|
@@ -220,12 +235,8 @@ export function BreadcrumbItem({
|
|
|
220
235
|
}), stylex.props(itemStyles.root, isSupporting ? itemStyles.supportingSize : itemStyles.defaultSize, xstyle), className, style),
|
|
221
236
|
"data-testid": testId,
|
|
222
237
|
...rest,
|
|
223
|
-
children: [/*#__PURE__*/_jsx(
|
|
224
|
-
|
|
225
|
-
...{
|
|
226
|
-
className: "x11ke7fs x6s0dn4 xv1l7n4 xu0wf1k x87ps6o"
|
|
227
|
-
},
|
|
228
|
-
children: ctx.separator
|
|
238
|
+
children: [/*#__PURE__*/_jsx(BreadcrumbSeparator, {
|
|
239
|
+
separator: ctx.separator
|
|
229
240
|
}), hasMenu ?
|
|
230
241
|
/*#__PURE__*/
|
|
231
242
|
// A current crumb can also open a sibling menu — the trigger keeps
|
|
@@ -262,12 +273,8 @@ export function BreadcrumbItem({
|
|
|
262
273
|
}), stylex.props(itemStyles.root, isSupporting ? itemStyles.supportingSize : itemStyles.defaultSize, xstyle), className, style),
|
|
263
274
|
"data-testid": testId,
|
|
264
275
|
...rest,
|
|
265
|
-
children: [/*#__PURE__*/_jsx(
|
|
266
|
-
|
|
267
|
-
...{
|
|
268
|
-
className: "x11ke7fs x6s0dn4 xv1l7n4 xu0wf1k x87ps6o"
|
|
269
|
-
},
|
|
270
|
-
children: ctx.separator
|
|
276
|
+
children: [/*#__PURE__*/_jsx(BreadcrumbSeparator, {
|
|
277
|
+
separator: ctx.separator
|
|
271
278
|
}), hasMenu ? /*#__PURE__*/_jsx(BreadcrumbMenuTrigger, {
|
|
272
279
|
ref: contentRef,
|
|
273
280
|
menu: menu,
|
|
@@ -46,8 +46,8 @@ export interface ChatComposerProps extends Omit<BaseProps<HTMLDivElement>, 'onCh
|
|
|
46
46
|
/**
|
|
47
47
|
* Resting elevation of the composer body. `low` (the default) keeps today's
|
|
48
48
|
* raised look — low at rest, bumping to med on hover / focus. `none` flattens
|
|
49
|
-
* it and draws a border
|
|
50
|
-
*
|
|
49
|
+
* it and draws a border. Keyboard focus in the editor adds the shared focus
|
|
50
|
+
* ring in either presentation; pointer focus does not add that ring.
|
|
51
51
|
* @default 'low'
|
|
52
52
|
*/
|
|
53
53
|
elevation?: 'none' | 'low';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatComposer.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatComposer.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"ChatComposer.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatComposer.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,EAMZ,KAAK,SAAS,EAGf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AA+B5C,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;AA8MD;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,qBA6MpD;yBA7Me,YAAY"}
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* - /apps/storybook/stories/ChatComposer.stories.tsx
|
|
23
23
|
* - /packages/cli/assets/templates/blocks/components/ChatComposer/ (block examples)
|
|
24
24
|
*/
|
|
25
|
-
import React, { useState, useCallback, useRef, useMemo } from 'react';
|
|
25
|
+
import React, { useState, useEffect, useCallback, useRef, useMemo } from 'react';
|
|
26
26
|
import * as stylex from '@stylexjs/stylex';
|
|
27
27
|
import "../theme/tokens.stylex.js";
|
|
28
28
|
import { colorVars, spacingVars, radiusVars, shadowVars, durationVars, easeVars, borderVars, typeScaleVars, typographyVars } from "../theme/tokens.stylex.js";
|
|
@@ -33,6 +33,8 @@ import { ChatComposerContext } from "./ChatContext.js";
|
|
|
33
33
|
import { ChatSendButton } from "./ChatSendButton.js";
|
|
34
34
|
import { themeProps } from "../utils/themeProps.js";
|
|
35
35
|
import { useTranslator } from "../i18n/index.js";
|
|
36
|
+
import { focusOutlineStyles } from "../utils/focusOutline.stylex.js";
|
|
37
|
+
import { getInteractionModality, trackInteractionModality } from "../utils/interactionModality.js";
|
|
36
38
|
|
|
37
39
|
// =============================================================================
|
|
38
40
|
// Types
|
|
@@ -65,7 +67,8 @@ const styles = {
|
|
|
65
67
|
|
|
66
68
|
// Resting elevation for the composer body, narrowed to two steps.
|
|
67
69
|
// - `low` (default) preserves today's look: low at rest, bumping to med on
|
|
68
|
-
// hover / focus-within
|
|
70
|
+
// hover / focus-within. The WCAG focus indicator is a separate shared ring,
|
|
71
|
+
// gated to keyboard focus in the editor; the shadow change remains depth.
|
|
69
72
|
// - `none` is flat; depth comes from a border + inset rings instead. The
|
|
70
73
|
// border is drawn *inside* the padding — its width is subtracted from every
|
|
71
74
|
// side (like Card) so total inset (border + padding) equals the elevated
|
|
@@ -88,6 +91,9 @@ const elevationStyles = {
|
|
|
88
91
|
$$css: true
|
|
89
92
|
}
|
|
90
93
|
};
|
|
94
|
+
function isComposerEditor(target) {
|
|
95
|
+
return target instanceof HTMLElement && target.matches('textarea, [contenteditable="true"], [role="textbox"], input:not([type]), input[type="text"], input[type="search"], input[type="email"], input[type="url"], input[type="tel"], input[type="password"]');
|
|
96
|
+
}
|
|
91
97
|
|
|
92
98
|
// =============================================================================
|
|
93
99
|
// Component
|
|
@@ -134,6 +140,10 @@ export function ChatComposer(props) {
|
|
|
134
140
|
} = props;
|
|
135
141
|
const placeholder = placeholderFromProps ?? t('@astryx.chat.composer.placeholder');
|
|
136
142
|
const [internalValue, setInternalValue] = useState('');
|
|
143
|
+
const [hasKeyboardEditorFocus, setHasKeyboardEditorFocus] = useState(false);
|
|
144
|
+
useEffect(() => {
|
|
145
|
+
trackInteractionModality();
|
|
146
|
+
}, []);
|
|
137
147
|
const isControlled = controlledValue !== undefined;
|
|
138
148
|
const currentValue = isControlled ? controlledValue : internalValue;
|
|
139
149
|
const updateValue = useCallback(newValue => {
|
|
@@ -175,6 +185,14 @@ export function ChatComposer(props) {
|
|
|
175
185
|
const editable = bodyRef.current?.querySelector('[contenteditable="true"], textarea');
|
|
176
186
|
editable?.focus();
|
|
177
187
|
}, []);
|
|
188
|
+
const handleBodyFocusCapture = useCallback(event => {
|
|
189
|
+
setHasKeyboardEditorFocus(isComposerEditor(event.target) && getInteractionModality() === 'keyboard');
|
|
190
|
+
}, []);
|
|
191
|
+
const handleBodyBlurCapture = useCallback(event => {
|
|
192
|
+
if (!event.currentTarget.contains(event.relatedTarget)) {
|
|
193
|
+
setHasKeyboardEditorFocus(false);
|
|
194
|
+
}
|
|
195
|
+
}, []);
|
|
178
196
|
const statusEl = status ? /*#__PURE__*/_jsxs("div", {
|
|
179
197
|
role: status.type === 'error' ? 'alert' : 'status',
|
|
180
198
|
...{
|
|
@@ -238,7 +256,10 @@ export function ChatComposer(props) {
|
|
|
238
256
|
children: [statusPosition === 'top' && statusEl, drawer, /*#__PURE__*/_jsxs("div", {
|
|
239
257
|
ref: bodyRef,
|
|
240
258
|
onClick: handleBodyClick,
|
|
241
|
-
|
|
259
|
+
onPointerDownCapture: () => setHasKeyboardEditorFocus(false),
|
|
260
|
+
onFocusCapture: handleBodyFocusCapture,
|
|
261
|
+
onBlurCapture: handleBodyBlurCapture,
|
|
262
|
+
...stylex.props(styles.body, elevationStyles[elevation], hasKeyboardEditorFocus && focusOutlineStyles.focusWithin, density === 'compact' && styles.compact, xstyle),
|
|
242
263
|
children: [(headerActions || headerContext) && /*#__PURE__*/_jsxs("div", {
|
|
243
264
|
...{
|
|
244
265
|
className: "x78zum5 x6s0dn4 x1qughib x1txdalj xe0p6wg"
|
|
@@ -19,7 +19,9 @@ export interface CheckboxListItemProps extends BaseProps<HTMLLIElement> {
|
|
|
19
19
|
*
|
|
20
20
|
* Accepts a plain string (single-line truncation applied automatically)
|
|
21
21
|
* or a ReactNode for rich content (no truncation constraints —
|
|
22
|
-
* child components control their own text behavior).
|
|
22
|
+
* child components control their own text behavior). Links and buttons in
|
|
23
|
+
* the label keep their own behavior; only non-interactive row clicks
|
|
24
|
+
* delegate to the checkbox.
|
|
23
25
|
*/
|
|
24
26
|
label: ReactNode;
|
|
25
27
|
/**
|
|
@@ -47,9 +49,9 @@ export interface CheckboxListItemProps extends BaseProps<HTMLLIElement> {
|
|
|
47
49
|
*/
|
|
48
50
|
value?: string;
|
|
49
51
|
/**
|
|
50
|
-
* Secondary
|
|
52
|
+
* Secondary content below the label. Accepts a plain string or a ReactNode.
|
|
51
53
|
*/
|
|
52
|
-
description?:
|
|
54
|
+
description?: ReactNode;
|
|
53
55
|
/**
|
|
54
56
|
* Content rendered after the label area.
|
|
55
57
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CheckboxListItem.d.ts","sourceRoot":"","sources":["../../src/CheckboxList/CheckboxListItem.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAc,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAIlD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAsB5C,MAAM,WAAW,qBAAsB,SAAQ,SAAS,CAAC,aAAa,CAAC;IACrE
|
|
1
|
+
{"version":3,"file":"CheckboxListItem.d.ts","sourceRoot":"","sources":["../../src/CheckboxList/CheckboxListItem.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAc,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAIlD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAsB5C,MAAM,WAAW,qBAAsB,SAAQ,SAAS,CAAC,aAAa,CAAC;IACrE;;;;;;;;OAQG;IACH,KAAK,EAAE,SAAS,CAAC;IACjB;;;;;;;;;;;;;;;;;OAiBG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;;OAEG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,eAAe,CAAC;IACtC;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACrC,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;CAChC;AAMD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,YAAY,EAAE,SAAS,EACvB,KAAK,EACL,WAAW,EACX,UAAU,EACV,UAAU,EAAE,cAAsB,EAClC,SAAS,EAAE,aAAqB,EAChC,SAAS,EACT,OAAO,EACP,GAAG,EACH,MAAM,EACN,SAAS,EACT,KAAK,EACL,OAAO,EAAE,WAAW,EACpB,GAAG,SAAS,EACb,EAAE,qBAAqB,+BAqIvB;yBArJe,gBAAgB"}
|
|
@@ -18,17 +18,42 @@ import type { BaseProps } from '../BaseProps';
|
|
|
18
18
|
export interface RadioListItemProps extends BaseProps<HTMLDivElement> {
|
|
19
19
|
ref?: React.Ref<HTMLDivElement>;
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
21
|
+
* Primary label for the radio item.
|
|
22
|
+
*
|
|
23
|
+
* Accepts a plain string or a ReactNode for rich content. Links and buttons
|
|
24
|
+
* in the label keep their own behavior; only non-interactive row clicks
|
|
25
|
+
* delegate to the radio. The radio points at the rendered label for its
|
|
26
|
+
* accessible name, so a rich label still names it from its own text — pass
|
|
27
|
+
* `aria-label` when that text is absent or too noisy to announce.
|
|
22
28
|
*/
|
|
23
|
-
label:
|
|
29
|
+
label: ReactNode;
|
|
30
|
+
/**
|
|
31
|
+
* Plain-text accessible name for the radio, applied to the control rather
|
|
32
|
+
* than the row. It replaces the name the label would otherwise supply — a
|
|
33
|
+
* plain string label included — so reach for it when a rich label's own
|
|
34
|
+
* text is absent or reads badly, not as a routine addition.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```
|
|
38
|
+
* <RadioListItem
|
|
39
|
+
* label={<span>Pro plan <Badge label="Recommended" /></span>}
|
|
40
|
+
* aria-label="Pro plan"
|
|
41
|
+
* value="pro"
|
|
42
|
+
* />
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
'aria-label'?: string;
|
|
24
46
|
/**
|
|
25
47
|
* Value of this radio item.
|
|
26
48
|
*/
|
|
27
49
|
value: string;
|
|
28
50
|
/**
|
|
29
|
-
*
|
|
51
|
+
* Secondary content displayed below the label. Accepts a plain string or a
|
|
52
|
+
* ReactNode. Links and buttons anywhere in the row keep their own click
|
|
53
|
+
* behaviour — the row only delegates clicks from its non-interactive
|
|
54
|
+
* surface to the radio.
|
|
30
55
|
*/
|
|
31
|
-
description?:
|
|
56
|
+
description?: ReactNode;
|
|
32
57
|
/**
|
|
33
58
|
* Whether this individual radio item is disabled.
|
|
34
59
|
* @default false
|
|
@@ -56,7 +81,7 @@ export interface RadioListItemProps extends BaseProps<HTMLDivElement> {
|
|
|
56
81
|
* />
|
|
57
82
|
* ```
|
|
58
83
|
*/
|
|
59
|
-
export declare function RadioListItem({ ref, label, value, description, isDisabled: isItemDisabled, startContent, endContent, xstyle, className, style, onClick, ...rest }: RadioListItemProps): React.JSX.Element;
|
|
84
|
+
export declare function RadioListItem({ ref, label, 'aria-label': ariaLabel, value, description, isDisabled: isItemDisabled, startContent, endContent, xstyle, className, style, onClick, ...rest }: RadioListItemProps): React.JSX.Element;
|
|
60
85
|
export declare namespace RadioListItem {
|
|
61
86
|
var displayName: string;
|
|
62
87
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RadioListItem.d.ts","sourceRoot":"","sources":["../../src/RadioList/RadioListItem.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,EAAqB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAGhE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAyF5C,MAAM,WAAW,kBAAmB,SAAQ,SAAS,CAAC,cAAc,CAAC;IACnE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC
|
|
1
|
+
{"version":3,"file":"RadioListItem.d.ts","sourceRoot":"","sources":["../../src/RadioList/RadioListItem.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,EAAqB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAGhE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAyF5C,MAAM,WAAW,kBAAmB,SAAQ,SAAS,CAAC,cAAc,CAAC;IACnE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;;;;;;OAQG;IACH,KAAK,EAAE,SAAS,CAAC;IACjB;;;;;;;;;;;;;;OAcG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB;;OAEG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;CACxB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,EAC5B,GAAG,EACH,KAAK,EACL,YAAY,EAAE,SAAS,EACvB,KAAK,EACL,WAAW,EACX,UAAU,EAAE,cAAsB,EAClC,YAAY,EACZ,UAAU,EACV,MAAM,EACN,SAAS,EACT,KAAK,EACL,OAAO,EACP,GAAG,IAAI,EACR,EAAE,kBAAkB,qBAsJpB;yBApKe,aAAa"}
|
|
@@ -94,6 +94,7 @@ const rowStyles = {
|
|
|
94
94
|
export function RadioListItem({
|
|
95
95
|
ref,
|
|
96
96
|
label,
|
|
97
|
+
'aria-label': ariaLabel,
|
|
97
98
|
value,
|
|
98
99
|
description,
|
|
99
100
|
isDisabled: isItemDisabled = false,
|
|
@@ -110,6 +111,7 @@ export function RadioListItem({
|
|
|
110
111
|
throw new Error('RadioListItem must be used within an RadioList');
|
|
111
112
|
}
|
|
112
113
|
const id = useId();
|
|
114
|
+
const labelID = useId();
|
|
113
115
|
const descriptionID = useId();
|
|
114
116
|
const isDisabled = context.isDisabled || isItemDisabled;
|
|
115
117
|
// When the whole group is disabled with a disabledMessage, radios stay
|
|
@@ -118,6 +120,10 @@ export function RadioListItem({
|
|
|
118
120
|
// and always uses the native disabled attribute.
|
|
119
121
|
const keepsFocusableForMessage = context.hasDisabledMessage && !isItemDisabled;
|
|
120
122
|
const isChecked = context.value === value;
|
|
123
|
+
// One predicate for both the rendered element and the aria-describedby that
|
|
124
|
+
// points at it. A ReactNode description can be `false` or `''`, which render
|
|
125
|
+
// nothing — a `!= null` check would leave the link dangling.
|
|
126
|
+
const hasDescription = isRenderable(description);
|
|
121
127
|
const size = context.size;
|
|
122
128
|
// The radio visual is an indicator: a theme can restyle it through the
|
|
123
129
|
// `radio` / `radio-dot` targets or replace the component outright.
|
|
@@ -148,7 +154,6 @@ export function RadioListItem({
|
|
|
148
154
|
name: context.name,
|
|
149
155
|
value: value,
|
|
150
156
|
checked: isChecked,
|
|
151
|
-
"aria-label": label,
|
|
152
157
|
disabled: isDisabled && !keepsFocusableForMessage,
|
|
153
158
|
"aria-disabled": keepsFocusableForMessage ? 'true' : undefined
|
|
154
159
|
// A focusable-disabled radio is not natively disabled, so detach it
|
|
@@ -167,8 +172,15 @@ export function RadioListItem({
|
|
|
167
172
|
// both direct control clicks and row-surface clicks the row delegates
|
|
168
173
|
// to the input — the same routing CheckboxListItem uses.
|
|
169
174
|
,
|
|
170
|
-
onClick: onClick
|
|
171
|
-
|
|
175
|
+
onClick: onClick
|
|
176
|
+
// The radio names itself from the visible label element, which works
|
|
177
|
+
// for a rich label as well as a plain string. `aria-label` replaces
|
|
178
|
+
// that name rather than adding to it, so the two are mutually
|
|
179
|
+
// exclusive — aria-labelledby would otherwise win over it.
|
|
180
|
+
,
|
|
181
|
+
"aria-label": ariaLabel,
|
|
182
|
+
"aria-labelledby": ariaLabel == null ? labelID : undefined,
|
|
183
|
+
"aria-describedby": hasDescription ? descriptionID : undefined,
|
|
172
184
|
...stylex.props(styles.input, wrapperSizeStyles[size], isDisabled && styles.inputDisabled)
|
|
173
185
|
}), /*#__PURE__*/_jsx("span", {
|
|
174
186
|
ref: indicatorRef,
|
|
@@ -195,9 +207,10 @@ export function RadioListItem({
|
|
|
195
207
|
interactiveRef: radioRef,
|
|
196
208
|
isDisabled: isDisabled,
|
|
197
209
|
label: /*#__PURE__*/_jsx("span", {
|
|
210
|
+
id: labelID,
|
|
198
211
|
children: label
|
|
199
212
|
}),
|
|
200
|
-
description:
|
|
213
|
+
description: hasDescription ? /*#__PURE__*/_jsx("span", {
|
|
201
214
|
id: descriptionID,
|
|
202
215
|
children: description
|
|
203
216
|
}) : undefined,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResizeHandle.d.ts","sourceRoot":"","sources":["../../src/Resizable/ResizeHandle.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ResizeHandle.d.ts","sourceRoot":"","sources":["../../src/Resizable/ResizeHandle.tsx"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAErC,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAU5C,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,gBAAgB,CAAC;AAQnD,KAAK,aAAa,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAyOzD,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAC7C,SAAS,CAAC,cAAc,CAAC,EACzB,OAAO,CACR;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEhC;;;OAGG;IACH,SAAS,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IAEtC;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAEhC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAE9B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,6CAA6C;IAC7C,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B,yDAAyD;IACzD,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,EAC3B,SAAwB,EACxB,QAAQ,EAAE,YAAuB,EACjC,UAAkB,EAClB,UAAkB,EAClB,UAAkB,EAClB,eAAsB,EACtB,aAAsB,EACtB,KAAK,EAAE,cAAc,EACrB,SAAS,EACT,QAAQ,EACR,MAAM,EACN,SAAS,EACT,GAAG,EACH,GAAG,KAAK,EACT,EAAE,iBAAiB,+BA0TnB;yBAzUe,YAAY"}
|
|
@@ -21,6 +21,15 @@
|
|
|
21
21
|
* While the panel is collapsed, aria-valuenow is clamped to aria-valuemin
|
|
22
22
|
* (a value below the minimum is invalid per WCAG 4.1.2) and a localized
|
|
23
23
|
* "Collapsed" aria-valuetext announces the real state.
|
|
24
|
+
*
|
|
25
|
+
* Dragging takes pointer capture on the grab zone, so the rest of the gesture
|
|
26
|
+
* is delivered to that element instead of being hit-tested against whatever
|
|
27
|
+
* the cursor happens to be over. A resizable region that contains an embedded
|
|
28
|
+
* frame otherwise loses the drag the moment the cursor crosses the frame: the
|
|
29
|
+
* events go to the guest document, and a listener on the host window never
|
|
30
|
+
* hears them again. Captured events are delivered to the capturing element,
|
|
31
|
+
* so the move/up/cancel handlers live on the grab zone (as in Slider), not on
|
|
32
|
+
* window.
|
|
24
33
|
*/
|
|
25
34
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
26
35
|
import * as stylex from '@stylexjs/stylex';
|
|
@@ -66,6 +75,20 @@ function hitAreaBiasDir(effectiveSide) {
|
|
|
66
75
|
}
|
|
67
76
|
return effectiveSide === 'start' ? -1 : 1;
|
|
68
77
|
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Drag feedback lives on `<body>`, not on the handle: the pointer spends the
|
|
81
|
+
* drag off the handle, over whatever the panels contain, and the resize cursor
|
|
82
|
+
* has to hold there. Module scope so the writes stay outside the component.
|
|
83
|
+
*/
|
|
84
|
+
function applyBodyDragStyles(isHorizontal) {
|
|
85
|
+
document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';
|
|
86
|
+
document.body.style.userSelect = 'none';
|
|
87
|
+
}
|
|
88
|
+
function clearBodyDragStyles() {
|
|
89
|
+
document.body.style.cursor = '';
|
|
90
|
+
document.body.style.userSelect = '';
|
|
91
|
+
}
|
|
69
92
|
const styles = {
|
|
70
93
|
handle: {
|
|
71
94
|
kVAEAm: "x1n2onr6",
|
|
@@ -273,9 +296,10 @@ export function ResizeHandle({
|
|
|
273
296
|
const t = useTranslator();
|
|
274
297
|
const label = labelFromProps ?? t('@astryx.resizable.handle.label');
|
|
275
298
|
const handleRef = useRef(null);
|
|
276
|
-
//
|
|
277
|
-
//
|
|
278
|
-
|
|
299
|
+
// The pointer that owns the in-flight drag, plus the values its deltas are
|
|
300
|
+
// measured against. A ref so moves don't re-render, and so unmount can tell
|
|
301
|
+
// a live drag from a finished one.
|
|
302
|
+
const dragRef = useRef(null);
|
|
279
303
|
const [isDragging, setIsDragging] = useState(false);
|
|
280
304
|
const [isHovered, setIsHovered] = useState(false);
|
|
281
305
|
const [isFocused, setIsFocused] = useState(false);
|
|
@@ -296,47 +320,56 @@ export function ResizeHandle({
|
|
|
296
320
|
const isInteracting = isHovered || isFocused;
|
|
297
321
|
|
|
298
322
|
// --- Pointer drag ---
|
|
323
|
+
const clearDrag = useCallback(() => {
|
|
324
|
+
dragRef.current = null;
|
|
325
|
+
setIsDragging(false);
|
|
326
|
+
clearBodyDragStyles();
|
|
327
|
+
}, []);
|
|
299
328
|
const handlePointerDown = useCallback(e => {
|
|
300
|
-
if (isDisabled || !resizable) {
|
|
329
|
+
if (isDisabled || !resizable || dragRef.current) {
|
|
301
330
|
return;
|
|
302
331
|
}
|
|
303
332
|
e.preventDefault();
|
|
304
333
|
e.stopPropagation();
|
|
334
|
+
// Take the pointer for the whole gesture. Without capture the browser
|
|
335
|
+
// re-hit-tests every move, so a frame anywhere under the drag path
|
|
336
|
+
// swallows the rest of it into the guest document.
|
|
337
|
+
e.currentTarget.setPointerCapture?.(e.pointerId);
|
|
338
|
+
dragRef.current = {
|
|
339
|
+
pointerId: e.pointerId,
|
|
340
|
+
startPos: isHorizontal ? e.clientX : e.clientY,
|
|
341
|
+
rtl: isHorizontal ? getRTLMultiplier() : 1
|
|
342
|
+
};
|
|
305
343
|
setIsDragging(true);
|
|
306
344
|
resizable._onResizeStart();
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
const delta = (currentPos - startPos) * rtl * sign;
|
|
314
|
-
resizable._onResizeMove(delta);
|
|
315
|
-
};
|
|
316
|
-
const onUp = () => {
|
|
317
|
-
cleanup();
|
|
318
|
-
setIsDragging(false);
|
|
319
|
-
resizable._onResizeEnd();
|
|
320
|
-
document.body.style.cursor = '';
|
|
321
|
-
document.body.style.userSelect = '';
|
|
322
|
-
};
|
|
323
|
-
const onCancel = () => {
|
|
324
|
-
cleanup();
|
|
325
|
-
setIsDragging(false);
|
|
326
|
-
document.body.style.cursor = '';
|
|
327
|
-
document.body.style.userSelect = '';
|
|
328
|
-
};
|
|
329
|
-
function cleanup() {
|
|
330
|
-
window.removeEventListener('pointermove', onMove);
|
|
331
|
-
window.removeEventListener('pointerup', onUp);
|
|
332
|
-
window.removeEventListener('pointercancel', onCancel);
|
|
333
|
-
dragCleanupRef.current = null;
|
|
345
|
+
applyBodyDragStyles(isHorizontal);
|
|
346
|
+
}, [isDisabled, resizable, isHorizontal, getRTLMultiplier]);
|
|
347
|
+
const handlePointerMove = useCallback(e => {
|
|
348
|
+
const drag = dragRef.current;
|
|
349
|
+
if (!drag || drag.pointerId !== e.pointerId || !resizable) {
|
|
350
|
+
return;
|
|
334
351
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
352
|
+
const currentPos = isHorizontal ? e.clientX : e.clientY;
|
|
353
|
+
resizable._onResizeMove((currentPos - drag.startPos) * drag.rtl * sign);
|
|
354
|
+
}, [resizable, isHorizontal, sign]);
|
|
355
|
+
const handlePointerUp = useCallback(e => {
|
|
356
|
+
if (dragRef.current?.pointerId !== e.pointerId) {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
clearDrag();
|
|
360
|
+
resizable?._onResizeEnd();
|
|
361
|
+
}, [clearDrag, resizable]);
|
|
362
|
+
|
|
363
|
+
// Serves pointercancel and lostpointercapture alike: an interrupted drag
|
|
364
|
+
// ends without signalling a resize end. lostpointercapture also fires on the
|
|
365
|
+
// implicit release after every pointerup/pointercancel, by which point the
|
|
366
|
+
// drag is already cleared and this is a no-op.
|
|
367
|
+
const cancelDrag = useCallback(e => {
|
|
368
|
+
if (dragRef.current?.pointerId !== e.pointerId) {
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
clearDrag();
|
|
372
|
+
}, [clearDrag]);
|
|
340
373
|
|
|
341
374
|
// --- Keyboard ---
|
|
342
375
|
const handleKeyDown = useCallback(e => {
|
|
@@ -406,16 +439,16 @@ export function ResizeHandle({
|
|
|
406
439
|
}, [isDisabled, resizable]);
|
|
407
440
|
|
|
408
441
|
// --- Cleanup on unmount ---
|
|
409
|
-
//
|
|
410
|
-
//
|
|
411
|
-
//
|
|
412
|
-
//
|
|
442
|
+
// Removing the grab zone implicitly releases its captured pointer and takes
|
|
443
|
+
// its listeners with it, so an in-flight drag stops driving the region on
|
|
444
|
+
// its own. The body cursor/user-select overrides are not on the element,
|
|
445
|
+
// though, so they have to be released here or they stick after the handle
|
|
446
|
+
// is gone.
|
|
413
447
|
useEffect(() => {
|
|
414
448
|
return () => {
|
|
415
|
-
if (
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
document.body.style.userSelect = '';
|
|
449
|
+
if (dragRef.current) {
|
|
450
|
+
dragRef.current = null;
|
|
451
|
+
clearBodyDragStyles();
|
|
419
452
|
}
|
|
420
453
|
};
|
|
421
454
|
}, []);
|
|
@@ -464,6 +497,10 @@ export function ResizeHandle({
|
|
|
464
497
|
// construction so the two stay aligned in LTR and RTL alike.
|
|
465
498
|
hitBiasDir == null ? isHorizontal ? rtlStyles.centerInline('0px') : styles.hitAreaCenteredY : isHorizontal ? dynamicStyles.hitAreaOffsetX(hitBiasDir) : dynamicStyles.hitAreaOffsetY(hitBiasDir), isDisabled && styles.disabled),
|
|
466
499
|
onPointerDown: handlePointerDown,
|
|
500
|
+
onPointerMove: handlePointerMove,
|
|
501
|
+
onPointerUp: handlePointerUp,
|
|
502
|
+
onPointerCancel: cancelDrag,
|
|
503
|
+
onLostPointerCapture: cancelDrag,
|
|
467
504
|
onPointerEnter: () => setIsHovered(true),
|
|
468
505
|
onPointerLeave: () => {
|
|
469
506
|
if (!isDragging) {
|