@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.
- package/dist/Chat/ChatTokenizedText.d.ts +2 -0
- package/dist/Chat/ChatTokenizedText.d.ts.map +1 -1
- package/dist/Chat/ChatTokenizedText.js +11 -6
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +20 -6
- package/dist/TabList/TabList.d.ts +28 -4
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +297 -9
- package/dist/TabList/index.d.ts +1 -1
- package/dist/TabList/index.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +8 -0
- package/dist/astryx.css +19 -1
- package/dist/utils/sharedResizeObserver.d.ts.map +1 -1
- package/dist/utils/sharedResizeObserver.js +10 -1
- package/package.json +2 -2
- package/src/Chat/ChatTokenizedText.tsx +17 -10
- package/src/Markdown/parser.perf.test.ts +37 -5
- package/src/PowerSearch/PowerSearch.tsx +6 -1
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +201 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +17 -2
- package/src/TabList/TabList.doc.mjs +11 -3
- package/src/TabList/TabList.test.tsx +350 -0
- package/src/TabList/TabList.tsx +403 -8
- package/src/TabList/index.ts +1 -1
- package/src/Typeahead/BaseTypeahead.tsx +8 -0
- package/src/Typeahead/Typeahead.test.tsx +25 -0
- package/src/utils/sharedResizeObserver.ts +10 -2
|
@@ -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
|
|
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(
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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":"AAIA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,EAOZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,EAGL,KAAK,yBAAyB,EAC/B,MAAM,cAAc,CAAC;AAMtB,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,SAAS,CAAC;AAEtC,OAAO,KAAK,EAAC,WAAW,EAAE,kBAAkB,EAAC,MAAM,UAAU,CAAC;AAuB9D,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EAIjB,qBAAqB,EACrB,iBAAiB,EAIjB,qBAAqB,EACtB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"PowerSearch.d.ts","sourceRoot":"","sources":["../../src/PowerSearch/PowerSearch.tsx"],"names":[],"mappings":"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"}
|
|
@@ -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;
|
|
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
|
-
*
|
|
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
|
|
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"}
|
package/dist/TabList/TabList.js
CHANGED
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file TabList.tsx
|
|
7
|
-
* @input Uses React, StyleX, TabListContext, useListFocus, useKeyboardHint
|
|
8
|
-
*
|
|
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 {
|
|
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
|
-
|
|
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: [
|
|
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
|
}
|
package/dist/TabList/index.d.ts
CHANGED
|
@@ -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;
|
|
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,
|
|
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();
|