@astryxdesign/core 0.4.7-canary.8a9c040 → 0.4.7-canary.98ea5ba

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.
@@ -10,6 +10,8 @@
10
10
  *
11
11
  * SYNC: When modified, update:
12
12
  * - /packages/core/src/Chat/index.ts
13
+ * - /packages/core/src/Chat/ChatComposerInput.tsx (token alignment must match,
14
+ * or a token moves when the message is sent)
13
15
  * - /packages/cli/assets/templates/blocks/components/ChatTokenizedText/ (block examples)
14
16
  */
15
17
  import React from 'react';
@@ -1 +1 @@
1
- {"version":3,"file":"ChatTokenizedText.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatTokenizedText.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAuB,MAAM,OAAO,CAAC;AAG5C,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AAE3D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAiB5C,MAAM,WAAW,sBAAuB,SAAQ,SAAS,CAAC,eAAe,CAAC;IACxE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACjC,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAoBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,GAAG,EACH,QAAQ,EACR,MAAM,EACN,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,IAAI,EACR,EAAE,sBAAsB,qBA+BxB;yBAvCe,iBAAiB"}
1
+ {"version":3,"file":"ChatTokenizedText.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatTokenizedText.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAuB,MAAM,OAAO,CAAC;AAG5C,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AAE3D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAqB5C,MAAM,WAAW,sBAAuB,SAAQ,SAAS,CAAC,eAAe,CAAC;IACxE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACjC,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAoBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,GAAG,EACH,QAAQ,EACR,MAAM,EACN,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,IAAI,EACR,EAAE,sBAAsB,qBA+BxB;yBAvCe,iBAAiB"}
@@ -14,6 +14,8 @@
14
14
  *
15
15
  * SYNC: When modified, update:
16
16
  * - /packages/core/src/Chat/index.ts
17
+ * - /packages/core/src/Chat/ChatComposerInput.tsx (token alignment must match,
18
+ * or a token moves when the message is sent)
17
19
  * - /packages/cli/assets/templates/blocks/components/ChatTokenizedText/ (block examples)
18
20
  */
19
21
  import React from 'react';
@@ -106,12 +108,15 @@ function renderTokens(text, tokens) {
106
108
  const matched = match[0];
107
109
  const token = tokenMap.get(matched);
108
110
  if (token) {
109
- parts.push(isCustomToken(token) ? /*#__PURE__*/_jsx("span", {
110
- children: token.render()
111
- }, `${matched}-${match.index}`) : /*#__PURE__*/_jsx(Badge, {
112
- label: token.label,
113
- variant: token.variant,
114
- icon: token.icon
111
+ parts.push(/*#__PURE__*/_jsx("span", {
112
+ ...{
113
+ className: "x3nfvp2 xxymvpz"
114
+ },
115
+ children: isCustomToken(token) ? token.render() : /*#__PURE__*/_jsx(Badge, {
116
+ label: token.label,
117
+ variant: token.variant,
118
+ icon: token.icon
119
+ })
115
120
  }, `${matched}-${match.index}`));
116
121
  }
117
122
  lastIndex = match.index + matched.length;
@@ -1 +1 @@
1
- {"version":3,"file":"PowerSearch.d.ts","sourceRoot":"","sources":["../../src/PowerSearch/PowerSearch.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PowerSearch.d.ts","sourceRoot":"","sources":["../../src/PowerSearch/PowerSearch.tsx"],"names":[],"mappings":"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"}
@@ -64,7 +64,7 @@ const OPERATOR_VALUE_TYPE_TO_ICON = {
64
64
  const popoverLayerStyles = {
65
65
  layer: {
66
66
  kzqmXN: "x1xgy17j",
67
- k7Eaqz: "x13o0s5z",
67
+ k7Eaqz: "x15mybvi",
68
68
  $$css: true
69
69
  }
70
70
  };
@@ -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;AAgDjB,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,uCAAuC;IACvC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AA8eD,wBAAgB,sBAAsB,CAAC,EACrC,MAAM,EACN,MAAM,EAAE,aAAa,EACrB,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,eAAe,EAAE,wBAAwB,EACzC,UAAkB,GACnB,EAAE,2BAA2B,qBAwR7B"}
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,uCAAuC;IACvC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AA8eD,wBAAgB,sBAAsB,CAAC,EACrC,MAAM,EACN,MAAM,EAAE,aAAa,EACrB,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,eAAe,EAAE,wBAAwB,EACzC,UAAkB,GACnB,EAAE,2BAA2B,qBAwR7B"}
@@ -25,6 +25,18 @@ import { spacingVars, typeScaleVars } from "../theme/tokens.stylex.js";
25
25
  import { PowerSearchValueEditor } from "./PowerSearchValueEditor.js";
26
26
  import { resolveOperatorLabel } from "./resolveOperatorLabel.js";
27
27
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
28
+ // Below the popover layer's 400px floor (see popoverLayerStyles in
29
+ // PowerSearch.tsx) the chip rows collapse from one line to wrapped lines.
30
+ // A container query, not a viewport one, so the rows track the width the
31
+ // popover actually got (#4761).
32
+ const CHIP_ROW_COLLAPSE = '@container (max-width: 399px)';
33
+ const styles = {
34
+ chipRow: {
35
+ kwnvtZ: "xozqiw3 x1alyx8p",
36
+ $$css: true
37
+ }
38
+ };
39
+
28
40
  // =============================================================================
29
41
  // Editable filter state for recursive nesting
30
42
  // =============================================================================
@@ -178,9 +190,10 @@ function NestedSubFilterRow({
178
190
  return /*#__PURE__*/_jsxs(HStack, {
179
191
  gap: 2,
180
192
  vAlign: "center",
193
+ xstyle: styles.chipRow,
181
194
  children: [/*#__PURE__*/_jsx("div", {
182
195
  ...{
183
- className: "x2lah0s x1oysuqx"
196
+ className: "x2lah0s x1oysuqx x193iq5w"
184
197
  },
185
198
  children: /*#__PURE__*/_jsx(Selector, {
186
199
  label: t('@astryx.powersearch.editor.field'),
@@ -193,7 +206,7 @@ function NestedSubFilterRow({
193
206
  })
194
207
  }), operatorOptions.length > 0 && /*#__PURE__*/_jsx("div", {
195
208
  ...{
196
- className: "x2lah0s xzjbwwf"
209
+ className: "x2lah0s xzjbwwf x193iq5w"
197
210
  },
198
211
  children: /*#__PURE__*/_jsx(Selector, {
199
212
  label: t('@astryx.powersearch.editor.operator'),
@@ -371,7 +384,7 @@ function NestedEditor({
371
384
  },
372
385
  children: operatorOptions.length > 1 ? /*#__PURE__*/_jsx("div", {
373
386
  ...{
374
- className: "x1iyjqo2 x2lah0s"
387
+ className: "x1iyjqo2 x2lah0s x193iq5w"
375
388
  },
376
389
  children: /*#__PURE__*/_jsx(Selector, {
377
390
  label: t('@astryx.powersearch.editor.groupOperator'),
@@ -528,7 +541,7 @@ export function PowerSearchEditPopover({
528
541
  if (isNestedType) {
529
542
  return /*#__PURE__*/_jsxs("div", {
530
543
  ...{
531
- className: "xb3r6kr"
544
+ className: "xb3r6kr x12h1iku"
532
545
  },
533
546
  onKeyDown: handleKeyDown,
534
547
  children: [/*#__PURE__*/_jsx("div", {
@@ -595,7 +608,7 @@ export function PowerSearchEditPopover({
595
608
  }
596
609
  return /*#__PURE__*/_jsxs("div", {
597
610
  ...{
598
- className: "xb3r6kr"
611
+ className: "xb3r6kr x12h1iku"
599
612
  },
600
613
  onKeyDown: handleKeyDown,
601
614
  children: [/*#__PURE__*/_jsx("div", {
@@ -604,6 +617,7 @@ export function PowerSearchEditPopover({
604
617
  },
605
618
  children: /*#__PURE__*/_jsxs(HStack, {
606
619
  gap: 2,
620
+ xstyle: styles.chipRow,
607
621
  children: [/*#__PURE__*/_jsx("div", {
608
622
  ...{
609
623
  className: "x1iyjqo2 xs83m0k xeuugli"
@@ -619,7 +633,7 @@ export function PowerSearchEditPopover({
619
633
  })
620
634
  }), showOperatorSelector && operatorOptions.length > 0 && /*#__PURE__*/_jsx("div", {
621
635
  ...{
622
- className: "x1iyjqo2 x2lah0s"
636
+ className: "x1iyjqo2 x2lah0s x193iq5w"
623
637
  },
624
638
  children: /*#__PURE__*/_jsx(Selector, {
625
639
  label: t('@astryx.powersearch.editor.operator'),
@@ -1,10 +1,12 @@
1
1
  /**
2
2
  * @file TabList.tsx
3
- * @input Uses React, StyleX, TabListContext, useListFocus, useKeyboardHint
4
- * @output Exports TabList component and TabListProps type
3
+ * @input Uses React, StyleX, TabListContext, useListFocus, useKeyboardHint,
4
+ * useScrollOverflow, Icon
5
+ * @output Exports TabList component, TabListProps and TabListOverflow types
5
6
  * @position Nav wrapper; provides TabListContext to Tab and TabMenu children.
6
7
  * Owns roving-tabindex keyboard navigation (Arrow/Home/End) across the tab
7
- * strip via the shared useListFocus hook so it is a single Tab stop.
8
+ * strip via the shared useListFocus hook so it is a single Tab stop, and
9
+ * owns horizontal scrolling when the tabs are wider than the strip.
8
10
  *
9
11
  * SYNC: When modified, update:
10
12
  * - /packages/core/src/TabList/TabList.doc.mjs
@@ -16,6 +18,16 @@ import React, { type ReactNode } from 'react';
16
18
  import type { BaseProps } from '../BaseProps';
17
19
  import type { TabListSize } from './TabListContext';
18
20
  import { EDGE_COMP_ATTR } from '../Layout/edgeCompensation.stylex';
21
+ /**
22
+ * How a strip narrower than its tabs behaves.
23
+ *
24
+ * - `'auto'` — the component picks the strategy. Today that is always
25
+ * `'scroll'`.
26
+ * - `'scroll'` — the tabs scroll horizontally. Every tab stays a tab.
27
+ * - `'visible'` — no overflow handling: tabs keep their intrinsic widths and
28
+ * spill out of the strip, as they did before overflow existed.
29
+ */
30
+ export type TabListOverflow = 'auto' | 'scroll' | 'visible';
19
31
  export interface TabListProps extends Omit<BaseProps<HTMLElement>, 'onChange'> {
20
32
  ref?: React.Ref<HTMLElement>;
21
33
  /**
@@ -44,6 +56,18 @@ export interface TabListProps extends Omit<BaseProps<HTMLElement>, 'onChange'> {
44
56
  * @default false
45
57
  */
46
58
  hasDivider?: boolean;
59
+ /**
60
+ * What happens when the tabs are wider than the strip.
61
+ *
62
+ * `'auto'` lets the component choose; today it always scrolls. `'scroll'`
63
+ * scrolls the tabs horizontally, with edge fades and — for pointers that
64
+ * can hover — arrow affordances. `'visible'` turns overflow handling off and
65
+ * lets the tabs spill out of the strip.
66
+ *
67
+ * The selected tab is always scrolled back into view.
68
+ * @default 'auto'
69
+ */
70
+ overflow?: TabListOverflow;
47
71
  /**
48
72
  * Tab and TabMenu children.
49
73
  */
@@ -65,7 +89,7 @@ export interface TabListProps extends Omit<BaseProps<HTMLElement>, 'onChange'> {
65
89
  * </TabList>
66
90
  * ```
67
91
  */
68
- export declare function TabList({ ref, value, onChange, size: sizeProp, layout, hasDivider, xstyle, className, style, children, onKeyDown: onKeyDownProp, onFocus: onFocusProp, onBlur: onBlurProp, 'aria-label': ariaLabelFromProps, 'aria-orientation': _ariaOrientation, [EDGE_COMP_ATTR]: _edgeCompAttr, ...restProps }: TabListProps): React.JSX.Element;
92
+ export declare function TabList({ ref, value, onChange, size: sizeProp, layout, hasDivider, overflow, xstyle, className, style, children, onKeyDown: onKeyDownProp, onFocus: onFocusProp, onBlur: onBlurProp, 'aria-label': ariaLabelFromProps, 'aria-orientation': _ariaOrientation, [EDGE_COMP_ATTR]: _edgeCompAttr, ...restProps }: TabListProps): React.JSX.Element;
69
93
  export declare namespace TabList {
70
94
  var displayName: string;
71
95
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TabList.d.ts","sourceRoot":"","sources":["../../src/TabList/TabList.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,EAAuB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAGlE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAE5C,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAKlD,OAAO,EAAC,cAAc,EAAC,MAAM,mCAAmC,CAAC;AAYjE,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC;IAC5E,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC7B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC;;;;OAIG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AA4BD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,EACtB,GAAG,EACH,KAAK,EACL,QAAQ,EACR,IAAI,EAAE,QAAQ,EACd,MAAc,EACd,UAAkB,EAClB,MAAM,EACN,SAAS,EACT,KAAK,EACL,QAAQ,EACR,SAAS,EAAE,aAAa,EACxB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,UAAU,EAClB,YAAY,EAAE,kBAAkB,EAChC,kBAAkB,EAAE,gBAAgB,EACpC,CAAC,cAAc,CAAC,EAAE,aAAa,EAC/B,GAAG,SAAS,EACb,EAAE,YAAY,qBAkGd;yBApHe,OAAO"}
1
+ {"version":3,"file":"TabList.d.ts","sourceRoot":"","sources":["../../src/TabList/TabList.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,EAKZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAaf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAE5C,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAQlD,OAAO,EAAC,cAAc,EAAC,MAAM,mCAAmC,CAAC;AAqBjE;;;;;;;;GAQG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE5D,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC;IAC5E,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC7B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC;;;;OAIG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AAyLD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,EACtB,GAAG,EACH,KAAK,EACL,QAAQ,EACR,IAAI,EAAE,QAAQ,EACd,MAAc,EACd,UAAkB,EAClB,QAAiB,EACjB,MAAM,EACN,SAAS,EACT,KAAK,EACL,QAAQ,EACR,SAAS,EAAE,aAAa,EACxB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,UAAU,EAClB,YAAY,EAAE,kBAAkB,EAChC,kBAAkB,EAAE,gBAAgB,EACpC,CAAC,cAAc,CAAC,EAAE,aAAa,EAC/B,GAAG,SAAS,EACb,EAAE,YAAY,qBA0Rd;yBA7Se,OAAO"}
@@ -4,11 +4,13 @@
4
4
 
5
5
  /**
6
6
  * @file TabList.tsx
7
- * @input Uses React, StyleX, TabListContext, useListFocus, useKeyboardHint
8
- * @output Exports TabList component and TabListProps type
7
+ * @input Uses React, StyleX, TabListContext, useListFocus, useKeyboardHint,
8
+ * useScrollOverflow, Icon
9
+ * @output Exports TabList component, TabListProps and TabListOverflow types
9
10
  * @position Nav wrapper; provides TabListContext to Tab and TabMenu children.
10
11
  * Owns roving-tabindex keyboard navigation (Arrow/Home/End) across the tab
11
- * strip via the shared useListFocus hook so it is a single Tab stop.
12
+ * strip via the shared useListFocus hook so it is a single Tab stop, and
13
+ * owns horizontal scrolling when the tabs are wider than the strip.
12
14
  *
13
15
  * SYNC: When modified, update:
14
16
  * - /packages/core/src/TabList/TabList.doc.mjs
@@ -16,17 +18,22 @@
16
18
  * - /packages/core/src/TabList/TabList.test.tsx
17
19
  * - /packages/cli/assets/templates/blocks/components/TabList/ (showcase blocks)
18
20
  */
19
- import React, { useCallback, useMemo } from 'react';
21
+ import React, { useCallback, useEffect, useMemo, useRef } from 'react';
20
22
  import * as stylex from '@stylexjs/stylex';
21
23
  import "../theme/tokens.stylex.js";
22
- import { borderVars, colorVars, spacingVars } from "../theme/tokens.stylex.js";
24
+ import { borderVars, colorVars, durationVars, easeVars, focusVars, radiusVars, shadowVars, sizeVars, spacingVars } from "../theme/tokens.stylex.js";
23
25
  import { TabListContext } from "./TabListContext.js";
24
26
  import { useSize } from "../SizeContext/SizeContext.js";
25
- import { mergeProps } from "../utils/index.js";
27
+ import { mergeProps, rtlStyles } from "../utils/index.js";
26
28
  import { useListFocus } from "../hooks/useListFocus.js";
27
29
  import { useKeyboardHint } from "../hooks/useKeyboardHint.js";
30
+ import { useScrollOverflow } from "../hooks/useScrollOverflow.js";
31
+ import { isRtlElement } from "../hooks/isRtlElement.js";
32
+ import { Icon } from "../Icon/index.js";
28
33
  import { EDGE_COMP_ATTR } from "../Layout/edgeCompensation.stylex.js";
29
34
  import { themeProps } from "../utils/themeProps.js";
35
+ import { observeResize, unobserveResize } from "../utils/sharedResizeObserver.js";
36
+ import { focusOutlineProps } from "../utils/focusOutline.stylex.js";
30
37
  import { useTranslator } from "../i18n/index.js";
31
38
  import { useMergedRefs } from "../hooks/useMergedRefs.js";
32
39
  /**
@@ -34,8 +41,72 @@ import { useMergedRefs } from "../hooks/useMergedRefs.js";
34
41
  * (`[data-tab-value]`) and every TabMenu trigger (`[data-tab-menu]`),
35
42
  * in DOM order. Disabled stops are filtered out by the handler.
36
43
  */
37
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
44
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
38
45
  const TAB_STOP_SELECTOR = '[data-tab-value],[data-tab-menu]';
46
+ function preventFocus(e) {
47
+ e.preventDefault();
48
+ }
49
+
50
+ /** Fraction of the visible strip an arrow press scrolls. */
51
+ const SCROLL_PAGE_RATIO = 0.8;
52
+
53
+ /**
54
+ * How a strip narrower than its tabs behaves.
55
+ *
56
+ * - `'auto'` — the component picks the strategy. Today that is always
57
+ * `'scroll'`.
58
+ * - `'scroll'` — the tabs scroll horizontally. Every tab stays a tab.
59
+ * - `'visible'` — no overflow handling: tabs keep their intrinsic widths and
60
+ * spill out of the strip, as they did before overflow existed.
61
+ */
62
+
63
+ /**
64
+ * A scroll container clips at its padding box, and two things a tab paints sit
65
+ * outside its own box: the focus ring (offset + width) and the selected
66
+ * indicator, which `--_tab-indicator-bottom` pushes further down when a
67
+ * divider rail is reserved. The strip pads by that much and takes the padding
68
+ * straight back off with a negative margin, so nothing is clipped and the tabs
69
+ * stay exactly where they were.
70
+ *
71
+ * A bleed is not free, though. The padding is real geometry: the strip's
72
+ * border box sticks out of the TabList's, and any ancestor that scrolls counts
73
+ * that as something to scroll to. So the ring's share of the bleed is taken
74
+ * only while a ring is actually drawn inside the strip -- the same
75
+ * `:has(:focus-visible)` condition that draws it -- and at rest the strip is
76
+ * exactly as wide and as tall as the TabList, as it was before the strip could
77
+ * scroll. The indicator's share is always taken, because the indicator is
78
+ * always drawn.
79
+ *
80
+ * Turning the bleed on moves nothing: padding and negative margin cancel, so
81
+ * the border box grows outwards and the content stays put.
82
+ */
83
+ const RING_BLEED = `calc(${focusVars['--focus-outline-width']} + ${focusVars['--focus-outline-offset']})`;
84
+ const BLEED_VAR = '--_tab-strip-bleed';
85
+ const BLEED = `var(${BLEED_VAR})`;
86
+ const INDICATOR_BLEED = 'calc(-1 * var(--_tab-indicator-bottom, -1px))';
87
+ const BLOCK_END_BLEED = `max(${BLEED}, ${INDICATOR_BLEED})`;
88
+
89
+ /** How far the edge fade runs; wide enough to sit under an arrow. */
90
+ const FADE_WIDTH = spacingVars['--spacing-8'];
91
+
92
+ /**
93
+ * Where the fade turns fully opaque, and — the same distance, for the same
94
+ * reason — how far a revealed stop is kept clear of the edge. Declared as
95
+ * scroll-padding so the browser's own focus scrolling uses it too, and read
96
+ * back from the computed style so the arithmetic below has one source of
97
+ * truth with the CSS.
98
+ */
99
+ const SCROLL_EDGE_INSET = `calc(${BLEED} + ${FADE_WIDTH})`;
100
+
101
+ /**
102
+ * The fade reaches transparent at the strip's *own* edge, not at the bleed
103
+ * edge — otherwise the scroll container paints tabs past the TabList's box,
104
+ * past a divider rail, and past the scroll arrow that caps that edge. Masking
105
+ * the bleed costs nothing: only a faded edge is masked, and a stop at a faded
106
+ * edge never holds focus, so the bleed is still there when the ring needs it.
107
+ */
108
+ const FADE_FROM_START = `linear-gradient(to right, transparent ${BLEED}, black ${SCROLL_EDGE_INSET})`;
109
+ const FADE_FROM_END = `linear-gradient(to left, transparent ${BLEED}, black ${SCROLL_EDGE_INSET})`;
39
110
  const styles = {
40
111
  nav: {
41
112
  k1xSpc: "x78zum5",
@@ -43,6 +114,7 @@ const styles = {
43
114
  kOIVth: "x1lsbc85",
44
115
  ks0D6T: "x193iq5w",
45
116
  k7Eaqz: "xeuugli",
117
+ kVAEAm: "x1n2onr6",
46
118
  $$css: true
47
119
  },
48
120
  fill: {
@@ -56,6 +128,89 @@ const styles = {
56
128
  kGO01o: "xy143xn",
57
129
  "--_tab-indicator-bottom": "xficto1",
58
130
  $$css: true
131
+ },
132
+ strip: {
133
+ k1xSpc: "x78zum5",
134
+ kGNEyG: "x1qjc9v5",
135
+ kOIVth: "x14kbac9",
136
+ kzQI83: "x1iyjqo2",
137
+ kmuXW: "xs83m0k",
138
+ k7Eaqz: "xeuugli",
139
+ kSGwAc: "xqcrz7y",
140
+ $$css: true
141
+ },
142
+ stripScroll: {
143
+ kXHlph: "xw2csxc",
144
+ kORKVm: "x10wlt62",
145
+ kvh3hx: "x7p5m3t",
146
+ katHQp: "x1xif8ns",
147
+ k5wCbM: "x1rohswg",
148
+ khEr5k: "xkcv6ua xg83hb1",
149
+ "--_tab-strip-bleed": "x78b515 x158n88w",
150
+ kLKAdn: "xlr2r7p",
151
+ keoZOQ: "xmqyaqf",
152
+ kGO01o: "xwhchk8",
153
+ k1K539: "xlgak1e",
154
+ kg3NbH: "x1kpkw9v",
155
+ kUOVxO: "xi5l473",
156
+ kX1K2I: "xw4ya9i",
157
+ k1ekBW: "x157bb6t",
158
+ kIyJzY: "x80gvsz x12w9bfk",
159
+ kAMwcw: "xlr8y92",
160
+ $$css: true
161
+ },
162
+ fadeStart: {
163
+ kX1K2I: "x1hua2o0 x1nwey30",
164
+ $$css: true
165
+ },
166
+ fadeEnd: {
167
+ kX1K2I: "xoj6v2h x1rxa4r8",
168
+ $$css: true
169
+ },
170
+ fadeBoth: {
171
+ kX1K2I: "xq05pg6",
172
+ $$css: true
173
+ },
174
+ arrow: {
175
+ kVAEAm: "x10l6tqk",
176
+ k87sOh: "x13vifvy",
177
+ k1xSpc: "x1s85apg xqwu39o",
178
+ kGNEyG: "x6s0dn4",
179
+ kjj79g: "xl56j7k",
180
+ kmVPX3: "x1717udv",
181
+ kMzoRj: "xc342km",
182
+ ksu8eU: "xng3xce",
183
+ kaIpWk: "xjspbzw",
184
+ kWkggS: "x1prclbq",
185
+ kGVxlE: "x1i5ehqx",
186
+ kMwMTN: "xv1l7n4 x9o1np9",
187
+ kkrTdU: "x1ypdohk x16khyan",
188
+ $$css: true
189
+ },
190
+ arrowStart: {
191
+ kLqNvP: "x1o0tod",
192
+ $$css: true
193
+ },
194
+ arrowEnd: {
195
+ kt4wiu: "xtijo5x",
196
+ $$css: true
197
+ }
198
+ };
199
+ const arrowSizeStyles = {
200
+ sm: {
201
+ kzqmXN: "x1fvqzum",
202
+ kZKoxP: "x6k0iem",
203
+ $$css: true
204
+ },
205
+ md: {
206
+ kzqmXN: "x805d0l",
207
+ kZKoxP: "x1ueg155",
208
+ $$css: true
209
+ },
210
+ lg: {
211
+ kzqmXN: "x1m747yf",
212
+ kZKoxP: "xssyfek",
213
+ $$css: true
59
214
  }
60
215
  };
61
216
 
@@ -82,6 +237,7 @@ export function TabList({
82
237
  size: sizeProp,
83
238
  layout = 'hug',
84
239
  hasDivider = false,
240
+ overflow = 'auto',
85
241
  xstyle,
86
242
  className,
87
243
  style,
@@ -97,6 +253,7 @@ export function TabList({
97
253
  const t = useTranslator();
98
254
  const ariaLabel = ariaLabelFromProps ?? t('@astryx.tabList.label');
99
255
  const size = useSize(sizeProp, 'md');
256
+ const hasScroll = overflow !== 'visible';
100
257
 
101
258
  // Roving-tabindex keyboard navigation across the tab strip via the shared
102
259
  // hook. `orientation: 'both'` accepts both arrow axes per the WAI-ARIA APG
@@ -127,6 +284,99 @@ export function TabList({
127
284
  onFocus: onHintFocus,
128
285
  onBlur: onHintBlur
129
286
  } = useKeyboardHint();
287
+ const {
288
+ scrollRef,
289
+ overflowStart,
290
+ overflowEnd
291
+ } = useScrollOverflow();
292
+ const stripRef = useRef(null);
293
+ const attachStrip = useCallback(el => {
294
+ stripRef.current = el;
295
+ scrollRef(hasScroll ? el : null);
296
+ }, [hasScroll, scrollRef]);
297
+ const revealStop = useCallback(stop => {
298
+ const strip = stripRef.current;
299
+ if (!hasScroll || !strip || !stop) {
300
+ return;
301
+ }
302
+ const stripBox = strip.getBoundingClientRect();
303
+ const stopBox = stop.getBoundingClientRect();
304
+ const inset = parseFloat(getComputedStyle(strip).scrollPaddingLeft) || 0;
305
+ const pastEnd = stopBox.right - (stripBox.right - inset);
306
+ const pastStart = stopBox.left - (stripBox.left + inset);
307
+ // A stop wider than the space kept clear cannot be shown whole, so show
308
+ // its reading start, the way `scrollIntoView({inline: 'nearest'})` does.
309
+ const tooWide = stopBox.width > stripBox.width - 2 * inset;
310
+ const delta = tooWide ? isRtlElement(strip) ? pastEnd : pastStart : pastEnd > 0 ? pastEnd : pastStart < 0 ? pastStart : 0;
311
+ if (delta !== 0) {
312
+ // Not an animation: the strip has to arrive already showing the right
313
+ // tab, so this overrides the CSS smooth behaviour arrow presses use.
314
+ strip.scrollBy({
315
+ left: delta,
316
+ behavior: 'instant'
317
+ });
318
+ }
319
+ }, [hasScroll]);
320
+ const revealSelectedTab = useCallback(() => {
321
+ const strip = stripRef.current;
322
+ if (!strip) {
323
+ return;
324
+ }
325
+ revealStop(Array.from(strip.querySelectorAll('[data-tab-value]')).find(el => el.dataset.tabValue === value) ?? null);
326
+ }, [revealStop, value]);
327
+
328
+ // Both reveals below reach the callback through a ref instead of depending
329
+ // on it: its identity also changes with `overflow`, and that is not a reason
330
+ // to scroll anything.
331
+ const revealSelectedTabRef = useRef(revealSelectedTab);
332
+ useEffect(() => {
333
+ revealSelectedTabRef.current = revealSelectedTab;
334
+ }, [revealSelectedTab]);
335
+
336
+ // The tab you are on has to be visible. Selection can move without focus —
337
+ // on mount, or when the host sets `value` itself — and neither scrolls the
338
+ // strip the way clicking or arrowing to a tab does. The check is what makes
339
+ // a selection change the trigger, rather than the effect happening to run.
340
+ const revealedValueRef = useRef(null);
341
+ useEffect(() => {
342
+ if (revealedValueRef.current === value) {
343
+ return;
344
+ }
345
+ revealedValueRef.current = value;
346
+ revealSelectedTabRef.current();
347
+ }, [value]);
348
+
349
+ // ...and it has to stay visible when the strip is what moved. A strip that
350
+ // fitted at one width can hide the selected tab at a narrower one, and no
351
+ // prop changes when that happens. This one re-reveals the same selection by
352
+ // design, which is why the check above sits in the effect rather than in
353
+ // `revealSelectedTab`.
354
+ //
355
+ // The wrapper is observed rather than the strip because the shared observer
356
+ // keeps one callback per element and `useScrollOverflow` already holds the
357
+ // strip's.
358
+ useEffect(() => {
359
+ const root = listRef.current;
360
+ if (!hasScroll || !root) {
361
+ return;
362
+ }
363
+ const onResize = () => revealSelectedTabRef.current();
364
+ observeResize(root, onResize);
365
+ return () => unobserveResize(root);
366
+ }, [hasScroll, listRef]);
367
+ const scrollByPage = useCallback(direction => {
368
+ const strip = stripRef.current;
369
+ if (!strip) {
370
+ return;
371
+ }
372
+ // Under RTL the scroll axis is inverted, so flip the physical delta.
373
+ const rtlSign = isRtlElement(strip) ? -1 : 1;
374
+ strip.scrollBy({
375
+ left: rtlSign * direction * strip.clientWidth * SCROLL_PAGE_RATIO
376
+ });
377
+ }, []);
378
+ const scrollToStart = useCallback(() => scrollByPage(-1), [scrollByPage]);
379
+ const scrollToEnd = useCallback(() => scrollByPage(1), [scrollByPage]);
130
380
  const contextValue = useMemo(() => ({
131
381
  value,
132
382
  onChange,
@@ -148,7 +398,11 @@ export function TabList({
148
398
  }
149
399
  onHintFocus(e);
150
400
  handleFocus(e);
151
- }, [onFocusProp, onHintFocus, handleFocus]);
401
+ // The browser scrolls a focused element into view only when it is
402
+ // entirely outside the scrollport, so arrowing onto a half-visible stop
403
+ // leaves it cut off under the fade. Finish the job it started.
404
+ revealStop(e.target.closest(TAB_STOP_SELECTOR));
405
+ }, [onFocusProp, onHintFocus, handleFocus, revealStop]);
152
406
  const handleRootBlur = useCallback(e => {
153
407
  onBlurProp?.(e);
154
408
  if (e.defaultPrevented) {
@@ -156,6 +410,7 @@ export function TabList({
156
410
  }
157
411
  onHintBlur(e);
158
412
  }, [onBlurProp, onHintBlur]);
413
+ const fadeStyle = !hasScroll ? null : overflowStart && overflowEnd ? styles.fadeBoth : overflowStart ? styles.fadeStart : overflowEnd ? styles.fadeEnd : null;
159
414
  return /*#__PURE__*/_jsx(TabListContext, {
160
415
  value: contextValue,
161
416
  children: /*#__PURE__*/_jsxs("nav", {
@@ -169,7 +424,40 @@ export function TabList({
169
424
  ...mergeProps(themeProps('tab-list', {
170
425
  size
171
426
  }), stylex.props(styles.nav, layout === 'fill' && styles.fill, hasDivider && styles.divider, xstyle), className, style),
172
- children: [children, hintElement]
427
+ children: [/*#__PURE__*/_jsx("div", {
428
+ ref: attachStrip,
429
+ ...mergeProps(themeProps('tab-strip'), stylex.props(styles.strip, hasScroll && styles.stripScroll, fadeStyle)),
430
+ children: children
431
+ }), hasScroll && overflowStart && /*#__PURE__*/_jsx("button", {
432
+ type: "button",
433
+ "aria-hidden": "true",
434
+ tabIndex: -1
435
+ // Nothing hidden from assistive technology should end up holding
436
+ // focus, and a click would put it here.
437
+ ,
438
+ onMouseDown: preventFocus,
439
+ onClick: scrollToStart,
440
+ ...mergeProps(themeProps('tab-scroll-button'), focusOutlineProps.focusVisible(styles.arrow, styles.arrowStart, arrowSizeStyles[size])),
441
+ children: /*#__PURE__*/_jsx(Icon, {
442
+ icon: "chevronLeft",
443
+ size: "sm",
444
+ color: "inherit",
445
+ xstyle: rtlStyles.mirror
446
+ })
447
+ }), hasScroll && overflowEnd && /*#__PURE__*/_jsx("button", {
448
+ type: "button",
449
+ "aria-hidden": "true",
450
+ tabIndex: -1,
451
+ onMouseDown: preventFocus,
452
+ onClick: scrollToEnd,
453
+ ...mergeProps(themeProps('tab-scroll-button'), focusOutlineProps.focusVisible(styles.arrow, styles.arrowEnd, arrowSizeStyles[size])),
454
+ children: /*#__PURE__*/_jsx(Icon, {
455
+ icon: "chevronRight",
456
+ size: "sm",
457
+ color: "inherit",
458
+ xstyle: rtlStyles.mirror
459
+ })
460
+ }), hintElement]
173
461
  })
174
462
  });
175
463
  }
@@ -7,7 +7,7 @@
7
7
  * SYNC: When modified, update this header and /packages/core/src/TabList/TabList.doc.mjs
8
8
  */
9
9
  export { TabList } from './TabList';
10
- export type { TabListProps } from './TabList';
10
+ export type { TabListProps, TabListOverflow } from './TabList';
11
11
  export { Tab } from './Tab';
12
12
  export type { TabProps } from './Tab';
13
13
  export { TabMenu } from './TabMenu';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/TabList/index.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AAClC,YAAY,EAAC,YAAY,EAAC,MAAM,WAAW,CAAC;AAE5C,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAC;AAC1B,YAAY,EAAC,QAAQ,EAAC,MAAM,OAAO,CAAC;AAEpC,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AAClC,YAAY,EAAC,YAAY,EAAE,aAAa,EAAC,MAAM,WAAW,CAAC;AAE3D,OAAO,EAAC,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AACnD,YAAY,EAAC,WAAW,EAAE,aAAa,EAAC,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/TabList/index.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AAClC,YAAY,EAAC,YAAY,EAAE,eAAe,EAAC,MAAM,WAAW,CAAC;AAE7D,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAC;AAC1B,YAAY,EAAC,QAAQ,EAAC,MAAM,OAAO,CAAC;AAEpC,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AAClC,YAAY,EAAC,YAAY,EAAE,aAAa,EAAC,MAAM,WAAW,CAAC;AAE3D,OAAO,EAAC,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AACnD,YAAY,EAAC,WAAW,EAAE,aAAa,EAAC,MAAM,kBAAkB,CAAC"}
@@ -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;AAEf,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,kBAAkB,CAAC;AAenD,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;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;;;;OAOG;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;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,WAAW,CAAC,EAAE,YAAY,CAAC;IAE3B;;;;;;;OAOG;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;AAsGD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,aAAa,EAyjBrB,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;AAEf,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,kBAAkB,CAAC;AAenD,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;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;;;;OAOG;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;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,WAAW,CAAC,EAAE,YAAY,CAAC;IAE3B;;;;;;;OAOG;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;AAsGD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,aAAa,EAikBrB,CAAC,CAAC,SAAS,cAAc,EAC5B,KAAK,EAAE,kBAAkB,CAAC,CAAC,CAAC,KACzB,KAAK,CAAC,YAAY,CAAC"}
@@ -449,6 +449,14 @@ export const BaseTypeahead = function BaseTypeahead({
449
449
  e.preventDefault();
450
450
  popover.hide();
451
451
  break;
452
+ case 'Tab':
453
+ // Dismiss here rather than from the blur this press produces:
454
+ // hiding a top-layer popover during the focusout makes Chrome
455
+ // abandon the in-flight focus move and drop focus to <body>, so the
456
+ // user's Tab appears to do nothing. Selector and MultiSelector
457
+ // already dismiss on this keydown.
458
+ popover.hide();
459
+ break;
452
460
  case 'Home':
453
461
  if (popover.isOpen) {
454
462
  e.preventDefault();