@astryxdesign/core 0.6.2-canary.bc93547 → 0.6.2-canary.da998a2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/BottomSheet/BottomSheet.d.ts +1 -1
  2. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  3. package/dist/BottomSheet/BottomSheet.js +3 -1
  4. package/dist/BottomSheet/BottomSheetPanel.d.ts +7 -5
  5. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  6. package/dist/BottomSheet/BottomSheetPanel.js +56 -19
  7. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  8. package/dist/PowerSearch/PowerSearchEditPopover.js +58 -30
  9. package/dist/ToggleButton/ToggleButton.d.ts +2 -1
  10. package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
  11. package/dist/ToggleButton/ToggleButton.js +7 -1
  12. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  13. package/dist/Typeahead/BaseTypeahead.js +9 -4
  14. package/dist/astryx.css +3 -1
  15. package/dist/hooks/scrollKeyboardDelegation.d.ts +3 -0
  16. package/dist/hooks/scrollKeyboardDelegation.d.ts.map +1 -0
  17. package/dist/hooks/scrollKeyboardDelegation.js +146 -0
  18. package/dist/hooks/useScrollableArea.d.ts +6 -2
  19. package/dist/hooks/useScrollableArea.d.ts.map +1 -1
  20. package/dist/hooks/useScrollableArea.js +17 -5
  21. package/package.json +3 -3
  22. package/src/BottomSheet/BottomSheet.doc.mjs +8 -1
  23. package/src/BottomSheet/BottomSheet.spec.md +46 -20
  24. package/src/BottomSheet/BottomSheet.test.tsx +6 -3
  25. package/src/BottomSheet/BottomSheet.tsx +3 -1
  26. package/src/BottomSheet/BottomSheetKeyboard.test.tsx +195 -0
  27. package/src/BottomSheet/BottomSheetPanel.test.tsx +11 -1
  28. package/src/BottomSheet/BottomSheetPanel.tsx +49 -16
  29. package/src/BottomSheet/__tests__/BottomSheetKeyboard.a11y.browser.spec.ts +344 -0
  30. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +150 -1
  31. package/src/PowerSearch/PowerSearchEditPopover.tsx +63 -28
  32. package/src/ScrollableArea/modules/useScrollableArea.spec.md +50 -22
  33. package/src/ToggleButton/ToggleButton.test.tsx +133 -0
  34. package/src/ToggleButton/ToggleButton.tsx +9 -2
  35. package/src/ToggleButton/__tests__/ToggleButton.a11y.chromium.spec.ts +209 -0
  36. package/src/Typeahead/BaseTypeahead.spec.md +4 -3
  37. package/src/Typeahead/BaseTypeahead.tsx +9 -4
  38. package/src/Typeahead/Typeahead.test.tsx +53 -0
  39. package/src/hooks/scrollKeyboardDelegation.test.ts +155 -0
  40. package/src/hooks/scrollKeyboardDelegation.ts +233 -0
  41. package/src/hooks/useScrollableArea.doc.mjs +15 -3
  42. package/src/hooks/useScrollableArea.test.tsx +59 -1
  43. package/src/hooks/useScrollableArea.ts +34 -10
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @file BottomSheet.tsx
3
- * @input Uses React, StyleX, core hooks/utils, BottomSheetPanel, BottomSheetSwitcherContext
3
+ * @input Uses React, StyleX, core hooks/utils, named BottomSheetPanel, BottomSheetSwitcherContext
4
4
  * @output Exports BottomSheet component and BottomSheetProps
5
5
  * @position Public BottomSheet router plus private standalone/switcher hosts
6
6
  *
@@ -1 +1 @@
1
- {"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/BottomSheet.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAOL,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,WAAW,CAAC;AAgB7C,YAAY,EAAC,iBAAiB,EAAE,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AAChF,OAAO,KAAK,EAAC,iBAAiB,EAAE,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AAyEhF,UAAU,sBAAuB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAChE,qDAAqD;IACrD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEhC,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IAEd,0EAA0E;IAC1E,QAAQ,EAAE,SAAS,CAAC;IAEpB,wGAAwG;IACxG,MAAM,CAAC,EAAE,iBAAiB,GAAG,MAAM,GAAG,MAAM,CAAC;IAE7C;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;IAEjD;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,UAAU,0BAA2B,SAAQ,sBAAsB;IACjE,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC9C,OAAO,CAAC,EAAE,KAAK,CAAC;CACjB;AAED,UAAU,wBAAyB,SAAQ,sBAAsB;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED,MAAM,MAAM,gBAAgB,GAC1B,0BAA0B,GAAG,wBAAwB,CAAC;AA4XxD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,+BA6BlD;yBA7Be,WAAW"}
1
+ {"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/BottomSheet.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAOL,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,WAAW,CAAC;AAgB7C,YAAY,EAAC,iBAAiB,EAAE,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AAChF,OAAO,KAAK,EAAC,iBAAiB,EAAE,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AAyEhF,UAAU,sBAAuB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAChE,qDAAqD;IACrD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEhC,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IAEd,0EAA0E;IAC1E,QAAQ,EAAE,SAAS,CAAC;IAEpB,wGAAwG;IACxG,MAAM,CAAC,EAAE,iBAAiB,GAAG,MAAM,GAAG,MAAM,CAAC;IAE7C;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;IAEjD;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,UAAU,0BAA2B,SAAQ,sBAAsB;IACjE,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC9C,OAAO,CAAC,EAAE,KAAK,CAAC;CACjB;AAED,UAAU,wBAAyB,SAAQ,sBAAsB;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED,MAAM,MAAM,gBAAgB,GAC1B,0BAA0B,GAAG,wBAAwB,CAAC;AA8XxD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,+BA6BlD;yBA7Be,WAAW"}
@@ -4,7 +4,7 @@
4
4
 
5
5
  /**
6
6
  * @file BottomSheet.tsx
7
- * @input Uses React, StyleX, core hooks/utils, BottomSheetPanel, BottomSheetSwitcherContext
7
+ * @input Uses React, StyleX, core hooks/utils, named BottomSheetPanel, BottomSheetSwitcherContext
8
8
  * @output Exports BottomSheet component and BottomSheetProps
9
9
  * @position Public BottomSheet router plus private standalone/switcher hosts
10
10
  *
@@ -266,6 +266,7 @@ function StandaloneBottomSheet({
266
266
  ref: ref,
267
267
  state: panelState,
268
268
  height: height,
269
+ label: label,
269
270
  snapPoints: snapPoints,
270
271
  isSwipeDismissAllowed: purpose === 'info',
271
272
  isPageScrollLocked: shouldPresent && hasScrim,
@@ -397,6 +398,7 @@ function SwitcherBottomSheetItem({
397
398
  ref: ref,
398
399
  state: panelState,
399
400
  height: height,
401
+ label: label,
400
402
  snapPoints: snapPoints,
401
403
  isSwipeDismissAllowed: purpose === 'info',
402
404
  isPageScrollLocked: hasScrim,
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * @file BottomSheetPanel.tsx
3
- * @input Uses React, StyleX, theme tokens, useSheetGestures
4
- * @output Internal BottomSheetPanel surface and motion-state types
3
+ * @input Uses React, StyleX, theme tokens, sheet gestures, shared scroll behavior, and the host label
4
+ * @output Internal BottomSheetPanel with a keyboard-reachable scrolling body and motion-state types
5
5
  * @position Shared presentation layer for standalone and switcher BottomSheets
6
6
  *
7
7
  * This component owns everything intrinsic to a sheet surface: height budgets,
8
8
  * drag and snap gestures, the handle and scrolling body, motion styles, and
9
- * transition completion. It deliberately does not own a dialog, focus, inert
10
- * state, or switcher registration; those belong to the hosting controller.
9
+ * transition completion. It owns the body's keyboard access; dialog focus
10
+ * entry/return, inert state, and switcher registration belong to the host.
11
11
  *
12
12
  * SYNC: When modified, update these files to stay in sync:
13
13
  * - /packages/core/src/BottomSheet/BottomSheet.tsx
@@ -44,6 +44,8 @@ interface BottomSheetPanelProps extends BaseProps<HTMLDivElement> {
44
44
  ref?: React.Ref<HTMLDivElement>;
45
45
  state: BottomSheetPanelState;
46
46
  height: BottomSheetHeight | number | string;
47
+ /** Existing host name, reused for the keyboard scrolling group. */
48
+ label: string;
47
49
  children: ReactNode;
48
50
  snapPoints?: ReadonlyArray<BottomSheetSnapPoint>;
49
51
  isSwipeDismissAllowed?: boolean;
@@ -56,7 +58,7 @@ interface BottomSheetPanelProps extends BaseProps<HTMLDivElement> {
56
58
  onMotionComplete?: (motion: BottomSheetPanelMotion) => void;
57
59
  }
58
60
  /** Internal visual and gesture surface shared by every BottomSheet host. */
59
- export declare function BottomSheetPanel({ ref, state, height, children, snapPoints, className, style, tabIndex, xstyle, isSwipeDismissAllowed, isPageScrollLocked, onDismiss, onScrimOpacity, onElementChange, onMotionStart, onMotionComplete, ...props }: BottomSheetPanelProps): import("react").JSX.Element;
61
+ export declare function BottomSheetPanel({ ref, state, height, label, children, snapPoints, className, style, tabIndex, xstyle, isSwipeDismissAllowed, isPageScrollLocked, onDismiss, onScrimOpacity, onElementChange, onMotionStart, onMotionComplete, ...props }: BottomSheetPanelProps): import("react").JSX.Element;
60
62
  export declare namespace BottomSheetPanel {
61
63
  var displayName: string;
62
64
  }
@@ -1 +1 @@
1
- {"version":3,"file":"BottomSheetPanel.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/BottomSheetPanel.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAc5C,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAC;AAIvB,QAAA,MAAM,cAAc;;;;CAIV,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,MAAM,OAAO,cAAc,CAAC;AAC5D,YAAY,EAAC,oBAAoB,EAAC,CAAC;AA2LnC,MAAM,MAAM,sBAAsB,GAChC,UAAU,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEjD,MAAM,MAAM,qBAAqB,GAC7B;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAC,GAChB;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAC,GACjC;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC1C,eAAe,EAAE,MAAM,CAAC;CACzB,GACD;IAAC,IAAI,EAAE,SAAS,CAAA;CAAC,CAAC;AAEtB,UAAU,qBAAsB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAC/D,+CAA+C;IAC/C,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,KAAK,EAAE,qBAAqB,CAAC;IAC7B,MAAM,EAAE,iBAAiB,GAAG,MAAM,GAAG,MAAM,CAAC;IAC5C,QAAQ,EAAE,SAAS,CAAC;IACpB,UAAU,CAAC,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;IACjD,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,gFAAgF;IAChF,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,cAAc,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,KAAK,IAAI,CAAC;IAC3D,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACzD,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,IAAI,CAAC;CAC7D;AA+GD,4EAA4E;AAC5E,wBAAgB,gBAAgB,CAAC,EAC/B,GAAG,EACH,KAAK,EACL,MAAM,EACN,QAAQ,EACR,UAAU,EACV,SAAS,EACT,KAAK,EACL,QAAQ,EACR,MAAM,EACN,qBAA4B,EAC5B,kBAA0B,EAC1B,SAAS,EACT,cAAc,EACd,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,GAAG,KAAK,EACT,EAAE,qBAAqB,+BAyQvB;yBA3Re,gBAAgB"}
1
+ {"version":3,"file":"BottomSheetPanel.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/BottomSheetPanel.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAiB5C,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAC;AAIvB,QAAA,MAAM,cAAc;;;;CAIV,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,MAAM,OAAO,cAAc,CAAC;AAC5D,YAAY,EAAC,oBAAoB,EAAC,CAAC;AAsMnC,MAAM,MAAM,sBAAsB,GAChC,UAAU,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEjD,MAAM,MAAM,qBAAqB,GAC7B;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAC,GAChB;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAC,GACjC;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC1C,eAAe,EAAE,MAAM,CAAC;CACzB,GACD;IAAC,IAAI,EAAE,SAAS,CAAA;CAAC,CAAC;AAEtB,UAAU,qBAAsB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAC/D,+CAA+C;IAC/C,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,KAAK,EAAE,qBAAqB,CAAC;IAC7B,MAAM,EAAE,iBAAiB,GAAG,MAAM,GAAG,MAAM,CAAC;IAC5C,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;IACpB,UAAU,CAAC,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;IACjD,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,gFAAgF;IAChF,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,cAAc,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,KAAK,IAAI,CAAC;IAC3D,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACzD,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,IAAI,CAAC;CAC7D;AA+GD,4EAA4E;AAC5E,wBAAgB,gBAAgB,CAAC,EAC/B,GAAG,EACH,KAAK,EACL,MAAM,EACN,KAAK,EACL,QAAQ,EACR,UAAU,EACV,SAAS,EACT,KAAK,EACL,QAAQ,EACR,MAAM,EACN,qBAA4B,EAC5B,kBAA0B,EAC1B,SAAS,EACT,cAAc,EACd,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,GAAG,KAAK,EACT,EAAE,qBAAqB,+BAyRvB;yBA5Se,gBAAgB"}
@@ -4,14 +4,14 @@
4
4
 
5
5
  /**
6
6
  * @file BottomSheetPanel.tsx
7
- * @input Uses React, StyleX, theme tokens, useSheetGestures
8
- * @output Internal BottomSheetPanel surface and motion-state types
7
+ * @input Uses React, StyleX, theme tokens, sheet gestures, shared scroll behavior, and the host label
8
+ * @output Internal BottomSheetPanel with a keyboard-reachable scrolling body and motion-state types
9
9
  * @position Shared presentation layer for standalone and switcher BottomSheets
10
10
  *
11
11
  * This component owns everything intrinsic to a sheet surface: height budgets,
12
12
  * drag and snap gestures, the handle and scrolling body, motion styles, and
13
- * transition completion. It deliberately does not own a dialog, focus, inert
14
- * state, or switcher registration; those belong to the hosting controller.
13
+ * transition completion. It owns the body's keyboard access; dialog focus
14
+ * entry/return, inert state, and switcher registration belong to the host.
15
15
  *
16
16
  * SYNC: When modified, update these files to stay in sync:
17
17
  * - /packages/core/src/BottomSheet/BottomSheet.tsx
@@ -23,9 +23,11 @@
23
23
  import { useCallback, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef } from 'react';
24
24
  import * as stylex from '@stylexjs/stylex';
25
25
  import { useDevWarning } from "../hooks/index.js";
26
+ import { useScrollableArea } from "../hooks/useScrollableArea.js";
26
27
  import "../theme/tokens.stylex.js";
27
- import { borderVars, colorVars, durationVars, easeVars, radiusVars, shadowVars, sizeVars, spacingVars } from "../theme/tokens.stylex.js";
28
+ import { borderVars, colorVars, durationVars, easeVars, focusVars, radiusVars, shadowVars, sizeVars, spacingVars } from "../theme/tokens.stylex.js";
28
29
  import { mergeProps, themeProps } from "../utils/index.js";
30
+ import { focusOutlineStyles } from "../utils/focusOutline.stylex.js";
29
31
  import { overlayPaddingReset } from "../Layout/padding.stylex.js";
30
32
  import { isValidSnapPoint, resolveSnapPoints } from "./snapOffsets.js";
31
33
  import { useMobileKeyboard } from "./useMobileKeyboard.js";
@@ -120,6 +122,24 @@ const styles = {
120
122
  kfzvcC: "x47corl",
121
123
  $$css: true
122
124
  },
125
+ body: {
126
+ kzQI83: "x1iyjqo2",
127
+ kAzted: "x2lwn1j",
128
+ kB7OPa: "x9f619",
129
+ kFalU9: "xx69xxh",
130
+ kInvED: "x1wfwxd8 x1nw7mhf",
131
+ kWkggS: "x10xzikg",
132
+ kGO01o: "x18d9i69",
133
+ $$css: true
134
+ },
135
+ tallKeyboardBody: {
136
+ kFlMNQ: "xrw9175",
137
+ k5JduY: "x1s928wv",
138
+ kc3QkE: "xhkezso",
139
+ k4zj60: "xu6fald",
140
+ kloYau: "x2q1x1w",
141
+ $$css: true
142
+ },
123
143
  budget: {
124
144
  kZKoxP: "x1tpcejd",
125
145
  $$css: true
@@ -222,6 +242,7 @@ export function BottomSheetPanel({
222
242
  ref,
223
243
  state,
224
244
  height,
245
+ label,
225
246
  children,
226
247
  snapPoints,
227
248
  className,
@@ -312,6 +333,22 @@ export function BottomSheetPanel({
312
333
  snapHeights,
313
334
  onScrimOpacity
314
335
  });
336
+ const {
337
+ getViewportProps,
338
+ getContentProps
339
+ } = useScrollableArea({
340
+ // The previous overflow-y:auto also computed overflow-x:auto. Keep wide
341
+ // content reachable instead of clipping that existing inline scroll path.
342
+ axis: 'both',
343
+ keyboardAccess: {
344
+ owner: 'contentOrViewport',
345
+ label
346
+ },
347
+ overscroll: 'contain',
348
+ // The sheet body deliberately remains the boundary for sheet-local sticky
349
+ // content while fitting, as it was before shared scroll adoption.
350
+ stickyContainment: 'always'
351
+ });
315
352
  const setElement = useCallback(element => {
316
353
  sheetRef(element);
317
354
  elementRef.current = element;
@@ -438,20 +475,20 @@ export function BottomSheetPanel({
438
475
  }
439
476
  })
440
477
  }), /*#__PURE__*/_jsx("div", {
441
- ...mergeProps({
442
- 0: {
443
- className: "x1iyjqo2 x2lwn1j x9f619 x1odjw0f x8du1vd xx69xxh x10xzikg x18d9i69"
444
- },
445
- 1: {
446
- className: "x1iyjqo2 x2lwn1j x9f619 x1odjw0f x8du1vd xx69xxh x10xzikg x18d9i69 xrw9175 x1s928wv xhkezso xu6fald x2q1x1w"
447
- }
448
- }[!!(height === 'tall') << 0], scrollPreservationInset > 0 ? {
449
- style: {
450
- paddingBlockEnd: `${scrollPreservationInset}px`
451
- }
452
- } : {}),
453
- ...bodyProps,
454
- children: children
478
+ ...getViewportProps({
479
+ ...bodyProps,
480
+ ...mergeProps(stylex.props(focusOutlineStyles.focusVisible, styles.body, height === 'tall' && styles.tallKeyboardBody), scrollPreservationInset > 0 ? {
481
+ style: {
482
+ paddingBlockEnd: `${scrollPreservationInset}px`
483
+ }
484
+ } : {})
485
+ }),
486
+ children: /*#__PURE__*/_jsx("div", {
487
+ ...getContentProps({
488
+ className: "xufnvkl x9f619 x5yr21d x121v3j4"
489
+ }),
490
+ children: children
491
+ })
455
492
  })]
456
493
  });
457
494
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PowerSearchEditPopover.d.ts","sourceRoot":"","sources":["../../src/PowerSearch/PowerSearchEditPopover.tsx"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AAEH,OAAO,KAA0D,MAAM,OAAO,CAAC;AAY/E,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EACV,iBAAiB,EACjB,aAAa,EAGd,MAAM,SAAS,CAAC;AA+DjB,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,cAAc,CAAC;IACvB,uCAAuC;IACvC,MAAM,EAAE,aAAa,CAAC;IACtB,qDAAqD;IACrD,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,6EAA6E;IAC7E,MAAM,EAAE,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,KAAK,IAAI,CAAC;IACnD,wDAAwD;IACxD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,kDAAkD;IAClD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAqfD,wBAAgB,sBAAsB,CAAC,EACrC,MAAM,EACN,MAAM,EAAE,aAAa,EACrB,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,eAAe,EAAE,wBAAwB,EACzC,YAAY,EACZ,UAAkB,GACnB,EAAE,2BAA2B,qBA0R7B"}
1
+ {"version":3,"file":"PowerSearchEditPopover.d.ts","sourceRoot":"","sources":["../../src/PowerSearch/PowerSearchEditPopover.tsx"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AAEH,OAAO,KAA0D,MAAM,OAAO,CAAC;AAe/E,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EACV,iBAAiB,EACjB,aAAa,EAGd,MAAM,SAAS,CAAC;AA+DjB,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,cAAc,CAAC;IACvB,uCAAuC;IACvC,MAAM,EAAE,aAAa,CAAC;IACtB,qDAAqD;IACrD,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,6EAA6E;IAC7E,MAAM,EAAE,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,KAAK,IAAI,CAAC;IACnD,wDAAwD;IACxD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,kDAAkD;IAClD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAsiBD,wBAAgB,sBAAsB,CAAC,EACrC,MAAM,EACN,MAAM,EAAE,aAAa,EACrB,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,eAAe,EAAE,wBAAwB,EACzC,YAAY,EACZ,UAAkB,GACnB,EAAE,2BAA2B,qBAyQ7B"}
@@ -229,7 +229,7 @@ function NestedSubFilterRow({
229
229
  config: config,
230
230
  maxMenuItems: maxMenuItems,
231
231
  isDisabled: isReadOnly
232
- })
232
+ }, valueEditorKey(subFilter))
233
233
  })]
234
234
  });
235
235
  }
@@ -414,6 +414,54 @@ function NestedEditor({
414
414
  });
415
415
  }
416
416
 
417
+ // =============================================================================
418
+ // Value editor cell
419
+ // =============================================================================
420
+
421
+ /**
422
+ * The value editor's identity is the (field, operator) pair it edits. Keying
423
+ * on it remounts the editor when either changes, so nothing an editor keeps
424
+ * privately — a Tokenizer's open menu, its query text, results fetched from
425
+ * the previous field's source — survives into the next field. Without the
426
+ * key, two fields sharing a value type (two `enum_list` fields, say) reuse
427
+ * one editor instance and the open menu keeps showing the old field's
428
+ * options.
429
+ */
430
+ function valueEditorKey(filter) {
431
+ return `${filter.field}\u0000${filter.operator ?? ''}`;
432
+ }
433
+
434
+ /**
435
+ * Wraps the value editor and moves focus into it once it mounts. Because the
436
+ * cell is keyed on the filter's field and operator, "mount" means both the
437
+ * popover opening and the user picking a different field or operator — the
438
+ * same focus handoff either way, so the freshly mounted editor can bootstrap
439
+ * its own suggestions.
440
+ */
441
+ function ValueEditorCell(props) {
442
+ const ref = useRef(null);
443
+ useEffect(() => {
444
+ const frame = requestAnimationFrame(() => {
445
+ const container = ref.current;
446
+ if (!container) {
447
+ return;
448
+ }
449
+ const focusable = container.querySelector('input:not([disabled]), button:not([disabled]), textarea:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])');
450
+ focusable?.focus();
451
+ });
452
+ return () => cancelAnimationFrame(frame);
453
+ }, []);
454
+ return /*#__PURE__*/_jsx("div", {
455
+ ref: ref,
456
+ ...{
457
+ className: "xgyuaek xeuugli"
458
+ },
459
+ children: /*#__PURE__*/_jsx(PowerSearchValueEditor, {
460
+ ...props
461
+ })
462
+ });
463
+ }
464
+
417
465
  // =============================================================================
418
466
  // Main popover
419
467
  // =============================================================================
@@ -431,20 +479,6 @@ export function PowerSearchEditPopover({
431
479
  const t = useTranslator();
432
480
  const saveButtonLabel = saveButtonLabelFromProps ?? t('@astryx.powersearch.editor.apply');
433
481
  const [partialFilter, setPartialFilter] = useState(initialFilter);
434
- const valueEditorRef = useRef(null);
435
-
436
- // Focus the first focusable element inside the value editor after mount
437
- useEffect(() => {
438
- const frame = requestAnimationFrame(() => {
439
- const container = valueEditorRef.current;
440
- if (!container) {
441
- return;
442
- }
443
- const focusable = container.querySelector('input:not([disabled]), button:not([disabled]), textarea:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])');
444
- focusable?.focus();
445
- });
446
- return () => cancelAnimationFrame(frame);
447
- }, []);
448
482
  const currentOperator = partialFilter.operator ? config.getOperator(partialFilter.field, partialFilter.operator) : undefined;
449
483
 
450
484
  // Build field options for the selector
@@ -651,21 +685,15 @@ export function PowerSearchEditPopover({
651
685
  isDisabled: isReadOnly,
652
686
  size: "md"
653
687
  })
654
- }), operatorValue && !isEmptyType && /*#__PURE__*/_jsx("div", {
655
- ref: valueEditorRef,
656
- ...{
657
- className: "xgyuaek xeuugli"
658
- },
659
- children: /*#__PURE__*/_jsx(PowerSearchValueEditor, {
660
- operatorValue: operatorValue,
661
- filterValue: partialFilter.value,
662
- onChange: handleValueChange,
663
- onEnter: handleSave,
664
- config: config,
665
- maxMenuItems: maxMenuItems,
666
- isDisabled: isReadOnly
667
- })
668
- })]
688
+ }), operatorValue && !isEmptyType && /*#__PURE__*/_jsx(ValueEditorCell, {
689
+ operatorValue: operatorValue,
690
+ filterValue: partialFilter.value,
691
+ onChange: handleValueChange,
692
+ onEnter: handleSave,
693
+ config: config,
694
+ maxMenuItems: maxMenuItems,
695
+ isDisabled: isReadOnly
696
+ }, valueEditorKey(partialFilter))]
669
697
  })
670
698
  }), !isEmptyType && /*#__PURE__*/_jsx("div", {
671
699
  ...{
@@ -77,7 +77,8 @@ export interface ToggleButtonProps extends BaseProps<HTMLButtonElement> {
77
77
  elevation?: Elevation;
78
78
  /**
79
79
  * Whether the button is disabled.
80
- * When used inside ToggleButtonGroup, the group's isDisabled overrides this.
80
+ * When used inside ToggleButtonGroup, a disabled group disables this button
81
+ * too, but an enabled group does not re-enable a button that disables itself.
81
82
  * @default false
82
83
  */
83
84
  isDisabled?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"ToggleButton.d.ts","sourceRoot":"","sources":["../../src/ToggleButton/ToggleButton.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,EAAgB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAI3D,OAAO,EAAS,KAAK,UAAU,EAAC,MAAM,WAAW,CAAC;AAClD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAE9C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AA4D5C,MAAM,WAAW,iBAAkB,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IACrE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,CAChB,SAAS,EAAE,OAAO,EAClB,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,KACvC,IAAI,CAAC;IAEV;;;;;;;;;;;;;;;;;OAiBG;IACH,mBAAmB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnE;;;;OAIG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;IAElB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IAEjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IAExB;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,YAAY,CAAC,EAC3B,GAAG,EACH,KAAK,EACL,SAAS,EAAE,aAAa,EACxB,eAAe,EAAE,mBAAmB,EACpC,mBAAmB,EACnB,IAAI,EAAE,QAAQ,EACd,SAAkB,EAClB,UAAU,EAAE,cAAsB,EAClC,SAAiB,EACjB,IAAI,EACJ,UAAkB,EAClB,WAAW,EACX,QAAQ,EACR,OAAO,EACP,KAAK,EACL,MAAM,EACN,SAAS,EAAE,UAAU,EACrB,KAAK,EACL,GAAG,KAAK,EACT,EAAE,iBAAiB,GAAG,SAAS,CA2G/B;yBA/He,YAAY"}
1
+ {"version":3,"file":"ToggleButton.d.ts","sourceRoot":"","sources":["../../src/ToggleButton/ToggleButton.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,EAAgB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAI3D,OAAO,EAAS,KAAK,UAAU,EAAC,MAAM,WAAW,CAAC;AAClD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAE9C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AA4D5C,MAAM,WAAW,iBAAkB,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IACrE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,CAChB,SAAS,EAAE,OAAO,EAClB,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,KACvC,IAAI,CAAC;IAEV;;;;;;;;;;;;;;;;;OAiBG;IACH,mBAAmB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnE;;;;OAIG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;IAElB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IAEjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IAExB;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,YAAY,CAAC,EAC3B,GAAG,EACH,KAAK,EACL,SAAS,EAAE,aAAa,EACxB,eAAe,EAAE,mBAAmB,EACpC,mBAAmB,EACnB,IAAI,EAAE,QAAQ,EACd,SAAkB,EAClB,UAAU,EAAE,cAAsB,EAClC,SAAiB,EACjB,IAAI,EACJ,UAAkB,EAClB,WAAW,EACX,QAAQ,EACR,OAAO,EACP,KAAK,EACL,MAAM,EACN,SAAS,EAAE,UAAU,EACrB,KAAK,EACL,GAAG,KAAK,EACT,EAAE,iBAAiB,GAAG,SAAS,CAiH/B;yBArIe,YAAY"}
@@ -99,7 +99,13 @@ export function ToggleButton({
99
99
  const group = useToggleButtonGroup();
100
100
  const committedPressed = group && value != null ? group.selectedValues.has(value) : isPressedProp ?? false;
101
101
  const size = sizeProp ?? group?.size ?? 'md';
102
- const isDisabled = group?.isDisabled ?? isDisabledProp;
102
+ // Either source disabling this button is enough. `??` could not express that:
103
+ // the group always supplies a boolean (its own prop defaults to false), so the
104
+ // fallback never ran and an enabled group handed a member that had disabled
105
+ // itself its availability back. A group still disables everything it contains
106
+ // — that is the half `??` got right — but it cannot re-enable a member
107
+ // (family:buttons FR3).
108
+ const isDisabled = (group?.isDisabled ?? false) || isDisabledProp;
103
109
 
104
110
  // Track the pressed state optimistically so the button reflects the intended
105
111
  // state immediately while an async action is pending. The optimistic update
@@ -1 +1 @@
1
- {"version":3,"file":"BaseTypeahead.d.ts","sourceRoot":"","sources":["../../src/Typeahead/BaseTypeahead.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,EAMZ,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,kBAAkB,CAAC;AAyBnD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,cAAc,EAAE,YAAY,EAAC,MAAM,SAAS,CAAC;AAS1D,MAAM,WAAW,kBAAkB,CAAC,CAAC,SAAS,cAAc,CAAE,SAAQ,IAAI,CACxE,SAAS,CAAC,WAAW,CAAC,EACtB,UAAU,CACX;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAClC;;OAEG;IACH,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAE9B;;OAEG;IACH,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IAEhB;;OAEG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC;IAEnC;;OAEG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,SAAS,CAAC;IAEpC;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;;;;;OAUG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;;;;;;OASG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAExC;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAEzC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;IAEtD;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,WAAW,CAAC,EAAE,YAAY,CAAC;IAE3B;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAE1C;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IAE/D;;;;OAIG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;CAC3B;AA+JD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,aAAa,EA2tBrB,CAAC,CAAC,SAAS,cAAc,EAC5B,KAAK,EAAE,kBAAkB,CAAC,CAAC,CAAC,KACzB,KAAK,CAAC,YAAY,CAAC"}
1
+ {"version":3,"file":"BaseTypeahead.d.ts","sourceRoot":"","sources":["../../src/Typeahead/BaseTypeahead.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,EAMZ,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,kBAAkB,CAAC;AAyBnD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,cAAc,EAAE,YAAY,EAAC,MAAM,SAAS,CAAC;AAS1D,MAAM,WAAW,kBAAkB,CAAC,CAAC,SAAS,cAAc,CAAE,SAAQ,IAAI,CACxE,SAAS,CAAC,WAAW,CAAC,EACtB,UAAU,CACX;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAClC;;OAEG;IACH,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAE9B;;OAEG;IACH,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IAEhB;;OAEG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC;IAEnC;;OAEG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,SAAS,CAAC;IAEpC;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;;;;;OAUG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;;;;;;OASG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAExC;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAEzC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;IAEtD;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,WAAW,CAAC,EAAE,YAAY,CAAC;IAE3B;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAE1C;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IAE/D;;;;OAIG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;CAC3B;AA+JD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,aAAa,EAguBrB,CAAC,CAAC,SAAS,cAAc,EAC5B,KAAK,EAAE,kBAAkB,CAAC,CAAC,CAAC,KACzB,KAAK,CAAC,YAAY,CAAC"}
@@ -274,9 +274,9 @@ export const BaseTypeahead = function BaseTypeahead({
274
274
  // Debounce ref
275
275
  const searchTimeoutRef = useRef(null);
276
276
 
277
- // Monotonic counter incremented on selection and query-clear. Async
278
- // searches that resolve after a selection compare their captured
279
- // generation to the current value and discard stale results.
277
+ // Monotonic counter incremented on selection, query-clear, and source
278
+ // replacement. Async searches that resolve afterwards compare their
279
+ // captured generation to the current value and discard stale results.
280
280
  const searchGenRef = useRef(0);
281
281
  // The generation at which results were last populated. handleFocus
282
282
  // compares this to searchGenRef — if they differ, the cached results
@@ -630,12 +630,17 @@ export const BaseTypeahead = function BaseTypeahead({
630
630
  });
631
631
  const selectedKey = value == null ? null : getKey(value.id, () => results.indexOf(value));
632
632
 
633
- // Cleanup timeout and cancel in-flight searches on unmount
633
+ // A replaced or unmounted source ends its search lifetime: drop the pending
634
+ // debounce, cancel in-flight work where the source supports it, and advance
635
+ // the generation so a late response from the old source can no longer
636
+ // commit results into a typeahead that is now reading a different source.
634
637
  useEffect(() => {
635
638
  return () => {
636
639
  if (searchTimeoutRef.current) {
637
640
  clearTimeout(searchTimeoutRef.current);
638
641
  }
642
+ // eslint-disable-next-line @eslint-react/exhaustive-deps -- a counter, not a node: the cleanup must advance the live generation
643
+ searchGenRef.current++;
639
644
  searchSource.cancel?.();
640
645
  };
641
646
  }, [searchSource]);
package/dist/astryx.css CHANGED
@@ -516,7 +516,6 @@
516
516
  .xb3r6kr:not(#\#):not(#\#){overflow:hidden}
517
517
  .x1rea2x4:not(#\#):not(#\#){overflow:visible}
518
518
  .xish69e:not(#\#):not(#\#){overscroll-behavior:contain}
519
- .x8du1vd:not(#\#):not(#\#){overscroll-behavior:none}
520
519
  .xt970qd:not(#\#):not(#\#){padding-block:0}
521
520
  .x1vn5h1t:not(#\#):not(#\#){padding-block:calc((var(--size-element-lg) - var(--spacing-5) - 2 * var(--border-width)) / 2)}
522
521
  .x1ioay2v:not(#\#):not(#\#){padding-block:calc((var(--size-element-md) - var(--spacing-5) - 2 * var(--border-width)) / 2)}
@@ -867,6 +866,7 @@
867
866
  .x1lliihq:not(#\#):not(#\#):not(#\#){display:block}
868
867
  .xjp7ctv:not(#\#):not(#\#):not(#\#){display:contents}
869
868
  .x78zum5:not(#\#):not(#\#):not(#\#){display:flex}
869
+ .xufnvkl:not(#\#):not(#\#):not(#\#){display:flow-root}
870
870
  .xrvj5dj:not(#\#):not(#\#):not(#\#){display:grid}
871
871
  .x1rg5ohu:not(#\#):not(#\#):not(#\#){display:inline-block}
872
872
  .x3nfvp2:not(#\#):not(#\#):not(#\#){display:inline-flex}
@@ -1363,6 +1363,7 @@
1363
1363
  .x1e0x2sz:focus-visible:not(#\#):not(#\#):not(#\#){outline-color:var(--color-error)}
1364
1364
  .xx47ajj:focus-visible:not(#\#):not(#\#):not(#\#){outline-color:var(--focus-outline-color)}
1365
1365
  .x7s97pk:focus-visible:not(#\#):not(#\#):not(#\#){outline-offset:2px}
1366
+ .x1nw7mhf:focus-visible:not(#\#):not(#\#):not(#\#){outline-offset:calc(-1 * var(--focus-outline-width))}
1366
1367
  .x13aywxo:focus-visible:not(#\#):not(#\#):not(#\#){outline-offset:var(--button-focus-offset)}
1367
1368
  .x1vwwbsn:focus-visible:not(#\#):not(#\#):not(#\#){outline-offset:var(--focus-outline-offset)}
1368
1369
  .xwz5zln.xwz5zln:where(.x1iwu4tg:has(:focus-visible) *):not(#\#):not(#\#):not(#\#){outline-offset:var(--focus-outline-offset)}
@@ -1676,6 +1677,7 @@
1676
1677
  .xjwf9q1:not(#\#):not(#\#):not(#\#):not(#\#){min-height:24px}
1677
1678
  .xe0p6wg:not(#\#):not(#\#):not(#\#):not(#\#){min-height:28px}
1678
1679
  .x21xpn4:not(#\#):not(#\#):not(#\#):not(#\#){min-height:32px}
1680
+ .x121v3j4:not(#\#):not(#\#):not(#\#):not(#\#){min-height:min-content}
1679
1681
  .x1xf4nls:not(#\#):not(#\#):not(#\#):not(#\#){min-height:var(--size-element-lg)}
1680
1682
  .x1uogy3y:not(#\#):not(#\#):not(#\#):not(#\#){min-height:var(--size-element-md)}
1681
1683
  .x1gdqauq:not(#\#):not(#\#):not(#\#):not(#\#){min-height:var(--size-element-sm)}
@@ -0,0 +1,3 @@
1
+ /** Attach only while automatic ownership has an effective scroll axis. */
2
+ export declare function attachScrollKeyboardDelegation(viewport: HTMLElement, content: HTMLElement): () => void;
3
+ //# sourceMappingURL=scrollKeyboardDelegation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scrollKeyboardDelegation.d.ts","sourceRoot":"","sources":["../../src/hooks/scrollKeyboardDelegation.ts"],"names":[],"mappings":"AAkIA,0EAA0E;AAC1E,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,WAAW,GACnB,MAAM,IAAI,CAkGZ"}
@@ -0,0 +1,146 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file scrollKeyboardDelegation.ts
5
+ * @input A named, overflowing viewport and its real content box
6
+ * @output Focus-time delegation with native forward and reverse Tab traversal
7
+ * @position Private useScrollableArea keyboard behavior; no DOM observers or scrolling
8
+ */
9
+
10
+ import { FOCUSABLE_SELECTOR } from "./focusableSelector.js";
11
+ import { getRegisteredScrollOwnerState } from "./scrollOwnerRegistry.js";
12
+
13
+ // Structural roles may contain ordinary links/buttons. Unknown or interactive
14
+ // roles are deliberately excluded until their navigation contract is proven.
15
+ const PASSIVE_ROLES = new Set(['article', 'banner', 'complementary', 'contentinfo', 'definition', 'directory', 'document', 'figure', 'form', 'generic', 'group', 'heading', 'list', 'listitem', 'main', 'navigation', 'none', 'note', 'paragraph', 'presentation', 'region', 'section', 'status', 'table', 'term']);
16
+ function isSequential(element) {
17
+ if (element.tabIndex < 0 || element.matches(':disabled') || element.closest('[inert], [hidden]') != null || element.getClientRects().length === 0) {
18
+ return false;
19
+ }
20
+ const visibility = getComputedStyle(element).visibility;
21
+ return visibility !== 'hidden' && visibility !== 'collapse';
22
+ }
23
+ function firstDelegationTarget(viewport, content) {
24
+ const candidates = content.querySelectorAll(FOCUSABLE_SELECTOR);
25
+ let first = content.matches(FOCUSABLE_SELECTOR) && isSequential(content) ? content : null;
26
+ for (const candidate of candidates) {
27
+ // After finding the first target, only positive tabindex can precede it.
28
+ // Ordinary trailing controls need no visibility or layout reads.
29
+ if (first != null && candidate.tabIndex <= 0) {
30
+ continue;
31
+ }
32
+ if (!isSequential(candidate)) {
33
+ continue;
34
+ }
35
+ // Positive tabindex participates before the zero-index viewport. Do not
36
+ // revisit it or skip its ordering by delegating to a later zero-index child.
37
+ if (candidate.tabIndex > 0) {
38
+ return null;
39
+ }
40
+ first ??= candidate;
41
+ }
42
+ if (first == null || first.tabIndex !== 0 || !first.matches('a[href], button') || first.closest('[aria-hidden="true"]') != null || first.matches('[aria-disabled="true"], [aria-haspopup]:not([aria-haspopup="false"])')) {
43
+ return null;
44
+ }
45
+ let ancestor = first;
46
+ while (ancestor != null && ancestor !== viewport) {
47
+ const role = ancestor.getAttribute('role')?.trim().toLowerCase();
48
+ const nativeRole = ancestor === first && (role === 'button' && first.localName === 'button' || role === 'link' && first.localName === 'a');
49
+ if (role != null && role !== '' && !nativeRole && !PASSIVE_ROLES.has(role) || ancestor === first && role != null && role !== '' && !nativeRole || ancestor.hasAttribute('aria-activedescendant') || ancestor.isContentEditable || ancestor.matches('[contenteditable]:not([contenteditable="false"])') || getRegisteredScrollOwnerState(ancestor) != null) {
50
+ return null;
51
+ }
52
+ // Also respect native scroll owners that have not adopted the shared hook.
53
+ const style = getComputedStyle(ancestor);
54
+ if (/^(auto|scroll|overlay)$/.test(style.overflowX) && ancestor.scrollWidth > ancestor.clientWidth + 1 || /^(auto|scroll|overlay)$/.test(style.overflowY) && ancestor.scrollHeight > ancestor.clientHeight + 1) {
55
+ return null;
56
+ }
57
+ ancestor = ancestor.parentElement;
58
+ }
59
+ return ancestor === viewport ? first : null;
60
+ }
61
+
62
+ /** Attach only while automatic ownership has an effective scroll axis. */
63
+ export function attachScrollKeyboardDelegation(viewport, content) {
64
+ const document = viewport.ownerDocument;
65
+ const window = document.defaultView;
66
+ if (window == null) {
67
+ return () => {};
68
+ }
69
+ let entry = null;
70
+ let origin = null;
71
+ let delegated = null;
72
+ let timer;
73
+ let restoreTabStop;
74
+ const reset = () => {
75
+ entry = null;
76
+ origin = null;
77
+ window.clearTimeout(timer);
78
+ restoreTabStop?.();
79
+ restoreTabStop = undefined;
80
+ };
81
+ const onKeyDown = event => {
82
+ reset();
83
+ if (event.key !== 'Tab' || event.ctrlKey || event.metaKey) {
84
+ return;
85
+ }
86
+ // Keep the actual event: focus() during keydown is programmatic (nonzero
87
+ // eventPhase), whereas native Tab focus follows completed event dispatch.
88
+ entry = event;
89
+ origin = event.target;
90
+ if (event.shiftKey && delegated != null && document.activeElement === delegated && viewport.contains(delegated)) {
91
+ const tabIndex = viewport.getAttribute('tabindex');
92
+ viewport.tabIndex = -1;
93
+ restoreTabStop = () => {
94
+ if (viewport.getAttribute('tabindex') === '-1') {
95
+ if (tabIndex == null) {
96
+ viewport.removeAttribute('tabindex');
97
+ } else {
98
+ viewport.setAttribute('tabindex', tabIndex);
99
+ }
100
+ }
101
+ };
102
+ }
103
+ // A canceled Tab, focus leaving the document, or a held key must not leave
104
+ // stale keyboard intent for a later pointer/programmatic focus operation.
105
+ timer = window.setTimeout(reset, 0);
106
+ };
107
+ const onFocusIn = event => {
108
+ const keyboardEntry = entry;
109
+ const previous = origin;
110
+ reset();
111
+ if (event.target !== viewport) {
112
+ if (!viewport.contains(event.target)) {
113
+ delegated = null;
114
+ }
115
+ return;
116
+ }
117
+ delegated = null;
118
+ if (keyboardEntry == null || keyboardEntry.shiftKey || keyboardEntry.defaultPrevented || keyboardEntry.eventPhase !== 0 || event.relatedTarget != null && event.relatedTarget !== previous) {
119
+ return;
120
+ }
121
+ const target = firstDelegationTarget(viewport, content);
122
+ if (target == null) {
123
+ return;
124
+ }
125
+ delegated = target;
126
+ // Let native focus reveal the action. Arrow/Page scrolling remains entirely
127
+ // browser-owned, including scroll chaining and the full viewport range.
128
+ target.focus();
129
+ if (document.activeElement !== target) {
130
+ delegated = null;
131
+ }
132
+ };
133
+ document.addEventListener('keydown', onKeyDown, true);
134
+ document.addEventListener('keyup', reset, true);
135
+ document.addEventListener('pointerdown', reset, true);
136
+ document.addEventListener('focusin', onFocusIn, true);
137
+ window.addEventListener('blur', reset);
138
+ return () => {
139
+ reset();
140
+ document.removeEventListener('keydown', onKeyDown, true);
141
+ document.removeEventListener('keyup', reset, true);
142
+ document.removeEventListener('pointerdown', reset, true);
143
+ document.removeEventListener('focusin', onFocusIn, true);
144
+ window.removeEventListener('blur', reset);
145
+ };
146
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @file useScrollableArea.ts
3
- * @input Logical scroll intent, keyboard ownership, caller-owned viewport/content props
4
- * @output Safe prop getters and stable per-axis effective scroll state
3
+ * @input Logical scroll intent, focus-time keyboard delegation, caller-owned viewport/content props
4
+ * @output Safe prop getters, native keyboard entry, and stable per-axis effective scroll state
5
5
  * @position Canonical behavior core for ScrollableArea and structure-owning adopters
6
6
  *
7
7
  * SYNC: When modified, update:
@@ -20,6 +20,10 @@ export type ScrollKeyboardAccess = {
20
20
  owner: 'viewport';
21
21
  label: string;
22
22
  role?: 'group' | 'region';
23
+ } | {
24
+ owner: 'contentOrViewport';
25
+ label: string;
26
+ role?: 'group' | 'region';
23
27
  };
24
28
  export interface ScrollAxisState {
25
29
  isScrollable: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"useScrollableArea.d.ts","sourceRoot":"","sources":["../../src/hooks/useScrollableArea.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AAEH,OAAO,EAOL,KAAK,aAAa,EAEnB,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAiB5C,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AACrD,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,SAAS,CAAC;AACnD,MAAM,MAAM,uBAAuB,GAAG,gBAAgB,GAAG,QAAQ,CAAC;AAElE,MAAM,MAAM,oBAAoB,GAC5B;IAAC,KAAK,EAAE,SAAS,CAAA;CAAC,GAClB;IAAC,KAAK,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAA;CAAC,CAAC;AAElE,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,eAAe,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,UAAU,CAAC;IACjB,cAAc,EAAE,oBAAoB,CAAC;IACrC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,iBAAiB,CAAC,EAAE,uBAAuB,CAAC;CAC7C;AAED,MAAM,MAAM,sBAAsB,CAAC,CAAC,SAAS,WAAW,IAAI,SAAS,CAAC,CAAC,CAAC,GACtE,aAAa,CAAC,CAAC,CAAC,CAAC;AAEnB,MAAM,WAAW,uBAAuB;IACtC,gBAAgB,CAAC,CAAC,SAAS,WAAW,EACpC,KAAK,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAChC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAC7B,eAAe,CAAC,CAAC,SAAS,WAAW,EACnC,KAAK,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAChC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAC7B,KAAK,EAAE,mBAAmB,CAAC;CAC5B;AAiGD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,cAAc,EACd,UAAoB,EACpB,iBAAoC,GACrC,EAAE,wBAAwB,GAAG,uBAAuB,CAwRpD"}
1
+ {"version":3,"file":"useScrollableArea.d.ts","sourceRoot":"","sources":["../../src/hooks/useScrollableArea.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AAEH,OAAO,EAOL,KAAK,aAAa,EAEnB,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAkB5C,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AACrD,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,SAAS,CAAC;AACnD,MAAM,MAAM,uBAAuB,GAAG,gBAAgB,GAAG,QAAQ,CAAC;AAElE,MAAM,MAAM,oBAAoB,GAC5B;IAAC,KAAK,EAAE,SAAS,CAAA;CAAC,GAClB;IAAC,KAAK,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAA;CAAC,GAC7D;IACE,KAAK,EAAE,mBAAmB,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC3B,CAAC;AAEN,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,eAAe,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,UAAU,CAAC;IACjB,cAAc,EAAE,oBAAoB,CAAC;IACrC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,iBAAiB,CAAC,EAAE,uBAAuB,CAAC;CAC7C;AAED,MAAM,MAAM,sBAAsB,CAAC,CAAC,SAAS,WAAW,IAAI,SAAS,CAAC,CAAC,CAAC,GACtE,aAAa,CAAC,CAAC,CAAC,CAAC;AAEnB,MAAM,WAAW,uBAAuB;IACtC,gBAAgB,CAAC,CAAC,SAAS,WAAW,EACpC,KAAK,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAChC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAC7B,eAAe,CAAC,CAAC,SAAS,WAAW,EACnC,KAAK,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAChC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAC7B,KAAK,EAAE,mBAAmB,CAAC;CAC5B;AAiGD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,cAAc,EACd,UAAoB,EACpB,iBAAoC,GACrC,EAAE,wBAAwB,GAAG,uBAAuB,CA0SpD"}