@spaced-out/ui-design-system 0.3.46 → 0.3.47-beta.0

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 (48) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/lib/components/AvatarGroup/AvatarGroup.js.flow +2 -2
  3. package/lib/components/ButtonDropdown/ButtonDropdown.js +22 -10
  4. package/lib/components/ButtonDropdown/ButtonDropdown.js.flow +58 -33
  5. package/lib/components/ButtonDropdown/ButtonDropdown.module.css +8 -1
  6. package/lib/components/ButtonDropdown/SimpleButtonDropdown.js +3 -0
  7. package/lib/components/ButtonDropdown/SimpleButtonDropdown.js.flow +6 -1
  8. package/lib/components/ButtonTabs/ButtonTabDropdown.js +13 -6
  9. package/lib/components/ButtonTabs/ButtonTabDropdown.js.flow +40 -24
  10. package/lib/components/ButtonTabs/ButtonTabDropdown.module.css +4 -0
  11. package/lib/components/ButtonTabs/ButtonTabs.js +2 -0
  12. package/lib/components/ButtonTabs/ButtonTabs.js.flow +4 -0
  13. package/lib/components/Dropdown/Dropdown.js +23 -8
  14. package/lib/components/Dropdown/Dropdown.js.flow +57 -32
  15. package/lib/components/Dropdown/Dropdown.module.css +5 -0
  16. package/lib/components/Dropdown/SimpleDropdown.js +2 -0
  17. package/lib/components/Dropdown/SimpleDropdown.js.flow +4 -0
  18. package/lib/components/InlineDropdown/InlineDropdown.js +25 -8
  19. package/lib/components/InlineDropdown/InlineDropdown.js.flow +57 -30
  20. package/lib/components/InlineDropdown/InlineDropdown.module.css +5 -0
  21. package/lib/components/InlineDropdown/SimpleInlineDropdown.js +2 -0
  22. package/lib/components/InlineDropdown/SimpleInlineDropdown.js.flow +4 -0
  23. package/lib/components/Table/StaticTable.js +1 -1
  24. package/lib/components/Table/StaticTable.js.flow +1 -1
  25. package/lib/components/Table/Table.docs.js +1 -1
  26. package/lib/components/Table/Table.docs.js.flow +1 -1
  27. package/lib/components/Tabs/TabList/TabDropdown.js +14 -7
  28. package/lib/components/Tabs/TabList/TabDropdown.js.flow +38 -22
  29. package/lib/components/Tabs/TabList/TabDropdown.module.css +4 -0
  30. package/lib/components/Tabs/TabList/TabList.js +4 -2
  31. package/lib/components/Tabs/TabList/TabList.js.flow +4 -0
  32. package/lib/components/TokenListInput/TokenListInput.js +26 -7
  33. package/lib/components/TokenListInput/TokenListInput.js.flow +58 -32
  34. package/lib/components/TokenListInput/TokenListInput.module.css +5 -0
  35. package/lib/components/Tooltip/Tooltip.js +2 -1
  36. package/lib/components/Tooltip/Tooltip.js.flow +2 -2
  37. package/lib/components/Typeahead/SimpleTypeahead.js +3 -1
  38. package/lib/components/Typeahead/SimpleTypeahead.js.flow +4 -0
  39. package/lib/components/Typeahead/Typeahead.js +25 -8
  40. package/lib/components/Typeahead/Typeahead.js.flow +58 -30
  41. package/lib/components/Typeahead/Typeahead.module.css +5 -0
  42. package/lib/hooks/index.js +11 -0
  43. package/lib/hooks/index.js.flow +1 -0
  44. package/lib/hooks/useReferenceElementWidth/index.js +16 -0
  45. package/lib/hooks/useReferenceElementWidth/index.js.flow +3 -0
  46. package/lib/hooks/useReferenceElementWidth/useReferenceElementWidth.js +21 -0
  47. package/lib/hooks/useReferenceElementWidth/useReferenceElementWidth.js.flow +23 -0
  48. package/package.json +1 -1
@@ -11,6 +11,7 @@ var _classify = require("../../../utils/classify");
11
11
  var _clickAway = require("../../../utils/click-away");
12
12
  var _mergeRefs = require("../../../utils/merge-refs");
13
13
  var _Menu = require("../../Menu");
14
+ var _Tooltip = require("../../Tooltip");
14
15
  var _Tab = require("../Tab");
15
16
  var _TabDropdownModule = _interopRequireDefault(require("./TabDropdown.module.css"));
16
17
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -22,14 +23,15 @@ const TabDropdown = _ref => {
22
23
  size,
23
24
  onOptionSelect,
24
25
  props,
26
+ elevation = 'modal',
25
27
  classNames
26
28
  } = _ref;
27
- const menuBtnRef = React.useRef();
28
29
  const {
29
30
  x,
30
31
  y,
31
32
  refs,
32
- strategy
33
+ strategy,
34
+ context
33
35
  } = (0, _react2.useFloating)({
34
36
  open: true,
35
37
  strategy: 'absolute',
@@ -47,8 +49,7 @@ const TabDropdown = _ref => {
47
49
  } = _ref2;
48
50
  return /*#__PURE__*/React.createElement("div", {
49
51
  "data-testid": "TabDropdown",
50
- className: (0, _classify.classify)(_TabDropdownModule.default.tabDropdownContainer, classNames?.wrapper),
51
- ref: menuBtnRef
52
+ className: (0, _classify.classify)(_TabDropdownModule.default.tabDropdownContainer, classNames?.wrapper)
52
53
  }, /*#__PURE__*/React.createElement(_Tab.Tab, _extends({}, props?.tab, {
53
54
  size: size,
54
55
  ref: (0, _mergeRefs.mergeRefs)([refs.setReference, triggerRef]),
@@ -60,13 +61,19 @@ const TabDropdown = _ref => {
60
61
  wrapper: _TabDropdownModule.default.dotTabWrapper,
61
62
  iconTextWrap: _TabDropdownModule.default.dotTextWrap
62
63
  }
63
- })), isOpen && props?.menu && /*#__PURE__*/React.createElement("div", {
64
+ })), isOpen && props?.menu && /*#__PURE__*/React.createElement(_react2.FloatingPortal, null, /*#__PURE__*/React.createElement(_react2.FloatingFocusManager, {
65
+ modal: false,
66
+ context: context,
67
+ initialFocus: refs.reference
68
+ }, /*#__PURE__*/React.createElement("div", {
64
69
  ref: (0, _mergeRefs.mergeRefs)([refs.setFloating, boundaryRef]),
70
+ className: _TabDropdownModule.default.menuWrapper,
65
71
  style: {
66
72
  display: 'flex',
67
73
  position: strategy,
68
74
  top: y ?? _space.spaceNone,
69
- left: x ?? _space.spaceNone
75
+ left: x ?? _space.spaceNone,
76
+ '--menu-elevation': (0, _Tooltip.getElevationValue)(elevation)
70
77
  }
71
78
  }, /*#__PURE__*/React.createElement(_Menu.Menu, _extends({}, props.menu, {
72
79
  onSelect: (option, e) => {
@@ -75,7 +82,7 @@ const TabDropdown = _ref => {
75
82
  },
76
83
  size: props.menu.size || size,
77
84
  onTabOut: clickAway
78
- }))));
85
+ }))))));
79
86
  });
80
87
  };
81
88
  exports.TabDropdown = TabDropdown;
@@ -7,6 +7,10 @@ import {
7
7
  // $FlowFixMe[untyped-import]
8
8
  flip,
9
9
  // $FlowFixMe[untyped-import]
10
+ FloatingFocusManager,
11
+ // $FlowFixMe[untyped-import]
12
+ FloatingPortal,
13
+ // $FlowFixMe[untyped-import]
10
14
  offset,
11
15
  // $FlowFixMe[untyped-import]
12
16
  shift,
@@ -21,6 +25,8 @@ import {mergeRefs} from '../../../utils/merge-refs';
21
25
  import type {AnchorType} from '../../ButtonDropdown';
22
26
  import type {MenuOption, MenuProps} from '../../Menu';
23
27
  import {Menu} from '../../Menu';
28
+ import type {ElevationType} from '../../Tooltip';
29
+ import {getElevationValue} from '../../Tooltip';
24
30
  import type {TabProps} from '../Tab';
25
31
  import {Tab} from '../Tab';
26
32
 
@@ -40,6 +46,7 @@ export type TabDropdownProps = {
40
46
  classNames?: ClassNames,
41
47
  selected?: boolean,
42
48
  disabled?: boolean,
49
+ elevation?: ElevationType,
43
50
  };
44
51
 
45
52
  export const TabDropdown = ({
@@ -47,10 +54,10 @@ export const TabDropdown = ({
47
54
  size,
48
55
  onOptionSelect,
49
56
  props,
57
+ elevation = 'modal',
50
58
  classNames,
51
59
  }: TabDropdownProps): React.Node => {
52
- const menuBtnRef = React.useRef();
53
- const {x, y, refs, strategy} = useFloating({
60
+ const {x, y, refs, strategy, context} = useFloating({
54
61
  open: true,
55
62
  strategy: 'absolute',
56
63
  placement: anchorPosition,
@@ -64,7 +71,6 @@ export const TabDropdown = ({
64
71
  <div
65
72
  data-testid="TabDropdown"
66
73
  className={classify(css.tabDropdownContainer, classNames?.wrapper)}
67
- ref={menuBtnRef}
68
74
  >
69
75
  <Tab
70
76
  {...props?.tab}
@@ -80,25 +86,35 @@ export const TabDropdown = ({
80
86
  }}
81
87
  />
82
88
  {isOpen && props?.menu && (
83
- <div
84
- ref={mergeRefs([refs.setFloating, boundaryRef])}
85
- style={{
86
- display: 'flex',
87
- position: strategy,
88
- top: y ?? spaceNone,
89
- left: x ?? spaceNone,
90
- }}
91
- >
92
- <Menu
93
- {...props.menu}
94
- onSelect={(option, e) => {
95
- onOptionSelect && onOptionSelect(option, e);
96
- clickAway();
97
- }}
98
- size={props.menu.size || size}
99
- onTabOut={clickAway}
100
- />
101
- </div>
89
+ <FloatingPortal>
90
+ <FloatingFocusManager
91
+ modal={false}
92
+ context={context}
93
+ initialFocus={refs.reference}
94
+ >
95
+ <div
96
+ ref={mergeRefs([refs.setFloating, boundaryRef])}
97
+ className={css.menuWrapper}
98
+ style={{
99
+ display: 'flex',
100
+ position: strategy,
101
+ top: y ?? spaceNone,
102
+ left: x ?? spaceNone,
103
+ '--menu-elevation': getElevationValue(elevation),
104
+ }}
105
+ >
106
+ <Menu
107
+ {...props.menu}
108
+ onSelect={(option, e) => {
109
+ onOptionSelect && onOptionSelect(option, e);
110
+ clickAway();
111
+ }}
112
+ size={props.menu.size || size}
113
+ onTabOut={clickAway}
114
+ />
115
+ </div>
116
+ </FloatingFocusManager>
117
+ </FloatingPortal>
102
118
  )}
103
119
  </div>
104
120
  )}
@@ -20,3 +20,7 @@
20
20
  .dotTextWrap {
21
21
  width: spaceFluid;
22
22
  }
23
+
24
+ .menuWrapper {
25
+ z-index: var(--menu-elevation);
26
+ }
@@ -20,7 +20,8 @@ const TabList = exports.TabList = /*#__PURE__*/React.forwardRef((_ref, forwardRe
20
20
  size,
21
21
  onSelect,
22
22
  selectedTab,
23
- menuWidth
23
+ menuWidth,
24
+ elevation = 'modal'
24
25
  } = _ref;
25
26
  const ref = React.useRef(null);
26
27
  React.useImperativeHandle(forwardRef, () => ref.current);
@@ -104,7 +105,8 @@ const TabList = exports.TabList = /*#__PURE__*/React.forwardRef((_ref, forwardRe
104
105
  selectedKeys,
105
106
  width: menuWidth
106
107
  }
107
- }
108
+ },
109
+ elevation: elevation
108
110
  }) : null;
109
111
  nodes = [...tabListNodes, tabDropDownNode];
110
112
  return nodes;
@@ -6,6 +6,7 @@ import {useWindowSize} from '../../../hooks/useWindowSize/useWindowSize';
6
6
  import {size36, size100} from '../../../styles/variables/_size';
7
7
  import {spaceMedium} from '../../../styles/variables/_space';
8
8
  import {classify} from '../../../utils/classify';
9
+ import type {ElevationType} from '../../Tooltip';
9
10
 
10
11
  import {TabDropdown} from './TabDropdown';
11
12
 
@@ -21,6 +22,7 @@ export type TabListProps = {
21
22
  size?: 'medium',
22
23
  selectedTab?: {tabId: string, label?: string},
23
24
  menuWidth?: string,
25
+ elevation?: ElevationType,
24
26
  };
25
27
 
26
28
  export const TabList: React$AbstractComponent<TabListProps, HTMLDivElement> =
@@ -33,6 +35,7 @@ export const TabList: React$AbstractComponent<TabListProps, HTMLDivElement> =
33
35
  onSelect,
34
36
  selectedTab,
35
37
  menuWidth,
38
+ elevation = 'modal',
36
39
  }: TabListProps,
37
40
  forwardRef,
38
41
  ): React.Node => {
@@ -120,6 +123,7 @@ export const TabList: React$AbstractComponent<TabListProps, HTMLDivElement> =
120
123
  width: menuWidth,
121
124
  },
122
125
  }}
126
+ elevation={elevation}
123
127
  />
124
128
  ) : null;
125
129
 
@@ -8,7 +8,7 @@ exports.TokenListInput = TokenListInput;
8
8
  var React = _interopRequireWildcard(require("react"));
9
9
  var _react2 = require("@floating-ui/react");
10
10
  var _without = _interopRequireDefault(require("lodash/without"));
11
- var _size = require("../../styles/variables/_size");
11
+ var _hooks = require("../../hooks");
12
12
  var _space = require("../../styles/variables/_space");
13
13
  var _typography = require("../../types/typography");
14
14
  var _classify = _interopRequireDefault(require("../../utils/classify"));
@@ -20,6 +20,7 @@ var _CircularLoader = require("../CircularLoader");
20
20
  var _Icon = require("../Icon");
21
21
  var _Menu = require("../Menu");
22
22
  var _Text = require("../Text");
23
+ var _Tooltip = require("../Tooltip");
23
24
  var _TokenValueChips = require("./TokenValueChips");
24
25
  var _TokenListInputModule = _interopRequireDefault(require("./TokenListInput.module.css"));
25
26
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -55,14 +56,16 @@ function TokenListInput(props) {
55
56
  tabIndex,
56
57
  values,
57
58
  resolveTokenValue,
58
- inputProps
59
+ inputProps,
60
+ elevation = 'modal'
59
61
  } = props;
60
62
  const menuRef = React.useRef(null);
61
63
  const {
62
64
  x,
63
65
  y,
64
66
  refs,
65
- strategy
67
+ strategy,
68
+ context
66
69
  } = (0, _react2.useFloating)({
67
70
  open: true,
68
71
  strategy: _ButtonDropdown.STRATEGY_TYPE.absolute,
@@ -71,6 +74,7 @@ function TokenListInput(props) {
71
74
  middleware: [(0, _react2.flip)(), (0, _react2.offset)(parseInt(_space.spaceXXSmall))]
72
75
  });
73
76
  const inputRef = React.useRef();
77
+ const dropdownWidth = (0, _hooks.useReferenceElementWidth)(refs.reference?.current);
74
78
  const onOpenToggle = isOpen => {
75
79
  if (isOpen) {
76
80
  onMenuOpen?.();
@@ -152,8 +156,9 @@ function TokenListInput(props) {
152
156
  triggerRef
153
157
  } = _ref;
154
158
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
159
+ ref: menuRef,
155
160
  className: (0, _classify.default)(_TokenListInputModule.default.tokenListContainer, classNames?.wrapper),
156
- ref: menuRef
161
+ "data-testid": "TokenListInput"
157
162
  }, /*#__PURE__*/React.createElement("div", {
158
163
  onClick: () => {
159
164
  if (disabled || locked || values.length >= limit) {
@@ -224,13 +229,27 @@ function TokenListInput(props) {
224
229
  color: _typography.TEXT_COLORS.danger
225
230
  }, errorText) : typeof helperText === 'string' ? /*#__PURE__*/React.createElement(_Text.BodySmall, {
226
231
  color: _typography.TEXT_COLORS.secondary
227
- }, helperText) : helperText), !locked && isOpen && menu && /*#__PURE__*/React.createElement("div", {
232
+ }, helperText) : helperText), !locked && isOpen && menu && /*#__PURE__*/React.createElement(_react2.FloatingPortal, null, /*#__PURE__*/React.createElement(_react2.FloatingFocusManager, {
233
+ modal: false,
234
+ context: context,
235
+ returnFocus: false,
236
+ initialFocus: refs.reference
237
+ }, /*#__PURE__*/React.createElement("div", {
238
+ className: _TokenListInputModule.default.menuWrapper,
228
239
  ref: (0, _mergeRefs.mergeRefs)([refs.setFloating, boundaryRef]),
229
240
  style: {
230
241
  position: strategy,
231
242
  top: y ?? _space.spaceNone,
232
243
  left: x ?? _space.spaceNone,
233
- width: _size.sizeFluid
244
+ /* NOTE(Sharad): The FloatingPortal renders the menu outside the normal DOM structure,
245
+ so its parent is effectively the <body> element. This means the menu
246
+ would otherwise default to the body's width. To support fluid width,
247
+ we must manually set the dropdown width here; otherwise, it uses a fixed width.
248
+ Also, Only treat menu as non-fluid if isFluid is strictly false, since default is true in menu and undefined means fluid. */
249
+ ...(menu.isFluid !== false && {
250
+ '--dropdown-width': dropdownWidth
251
+ }),
252
+ '--menu-elevation': (0, _Tooltip.getElevationValue)(elevation)
234
253
  }
235
254
  }, /*#__PURE__*/React.createElement(_Menu.Menu, _extends({}, menu, {
236
255
  onSelect: option => {
@@ -246,7 +265,7 @@ function TokenListInput(props) {
246
265
  size: menu.size || size,
247
266
  onTabOut: clickAway,
248
267
  ref: menuRef
249
- })))));
268
+ })))))));
250
269
  });
251
270
  }
252
271
  TokenListInput.displayName = 'TokenListInput';
@@ -7,13 +7,17 @@ import {
7
7
  // $FlowFixMe[untyped-import]
8
8
  flip,
9
9
  // $FlowFixMe[untyped-import]
10
+ FloatingFocusManager,
11
+ // $FlowFixMe[untyped-import]
12
+ FloatingPortal,
13
+ // $FlowFixMe[untyped-import]
10
14
  offset,
11
15
  // $FlowFixMe[untyped-import]
12
16
  useFloating,
13
17
  } from '@floating-ui/react';
14
18
  import without from 'lodash/without';
15
19
 
16
- import {sizeFluid} from '../../styles/variables/_size';
20
+ import {useReferenceElementWidth} from '../../hooks';
17
21
  import {spaceNone, spaceXXSmall} from '../../styles/variables/_space';
18
22
  import {TEXT_COLORS} from '../../types/typography';
19
23
  import classify from '../../utils/classify';
@@ -31,6 +35,7 @@ import type {InputProps} from '../Input';
31
35
  import type {BaseMenuProps} from '../Menu';
32
36
  import {Menu} from '../Menu';
33
37
  import {BodySmall} from '../Text';
38
+ import {type ElevationType, getElevationValue} from '../Tooltip';
34
39
 
35
40
  import type {ResolveTokenValueProps} from './TokenValueChips';
36
41
  import {TokenValueChips} from './TokenValueChips';
@@ -91,6 +96,7 @@ export type Props<T> = {
91
96
  onMenuClose?: () => mixed,
92
97
  resolveTokenValue?: (ResolveTokenValueProps<T>) => React.Node,
93
98
  inputProps?: InputProps,
99
+ elevation?: ElevationType,
94
100
  };
95
101
 
96
102
  export function TokenListInput<T>(props: Props<T>): React.Node {
@@ -120,11 +126,11 @@ export function TokenListInput<T>(props: Props<T>): React.Node {
120
126
  values,
121
127
  resolveTokenValue,
122
128
  inputProps,
129
+ elevation = 'modal',
123
130
  } = props;
124
-
125
131
  const menuRef = React.useRef<HTMLDivElement | null>(null);
126
132
 
127
- const {x, y, refs, strategy} = useFloating({
133
+ const {x, y, refs, strategy, context} = useFloating({
128
134
  open: true,
129
135
  strategy: STRATEGY_TYPE.absolute,
130
136
  placement: ANCHOR_POSITION_TYPE.bottomStart,
@@ -133,6 +139,7 @@ export function TokenListInput<T>(props: Props<T>): React.Node {
133
139
  });
134
140
 
135
141
  const inputRef = React.useRef<?HTMLInputElement>();
142
+ const dropdownWidth = useReferenceElementWidth(refs.reference?.current);
136
143
 
137
144
  const onOpenToggle = (isOpen) => {
138
145
  if (isOpen) {
@@ -222,8 +229,9 @@ export function TokenListInput<T>(props: Props<T>): React.Node {
222
229
  {({isOpen, onOpen, clickAway, boundaryRef, triggerRef}) => (
223
230
  <>
224
231
  <div
225
- className={classify(css.tokenListContainer, classNames?.wrapper)}
226
232
  ref={menuRef}
233
+ className={classify(css.tokenListContainer, classNames?.wrapper)}
234
+ data-testid="TokenListInput"
227
235
  >
228
236
  <div
229
237
  onClick={() => {
@@ -324,34 +332,52 @@ export function TokenListInput<T>(props: Props<T>): React.Node {
324
332
  </div>
325
333
  )}
326
334
  {!locked && isOpen && menu && (
327
- <div
328
- ref={mergeRefs([refs.setFloating, boundaryRef])}
329
- style={{
330
- position: strategy,
331
- top: y ?? spaceNone,
332
- left: x ?? spaceNone,
333
- width: sizeFluid,
334
- }}
335
- >
336
- {/* $FlowFixMe[incompatible-type] Menu expects MenuOption but receives T */}
337
- {/* $FlowFixMe[prop-missing] MenuOption properties are missing in T */}
338
- <Menu
339
- {...menu}
340
- onSelect={(option) => {
341
- if (values.length >= limit) {
342
- return;
343
- }
344
- // $FlowFixMe[incompatible-call] option from Menu is MenuOption but addValue expects T
345
- // $FlowFixMe[prop-missing] MenuOption properties are missing in T
346
- addValue(option);
347
- clickAway();
348
- inputRef.current?.focus();
349
- }}
350
- size={menu.size || size}
351
- onTabOut={clickAway}
352
- ref={menuRef}
353
- />
354
- </div>
335
+ <FloatingPortal>
336
+ <FloatingFocusManager
337
+ modal={false}
338
+ context={context}
339
+ returnFocus={false}
340
+ initialFocus={refs.reference}
341
+ >
342
+ <div
343
+ className={css.menuWrapper}
344
+ ref={mergeRefs([refs.setFloating, boundaryRef])}
345
+ style={{
346
+ position: strategy,
347
+ top: y ?? spaceNone,
348
+ left: x ?? spaceNone,
349
+ /* NOTE(Sharad): The FloatingPortal renders the menu outside the normal DOM structure,
350
+ so its parent is effectively the <body> element. This means the menu
351
+ would otherwise default to the body's width. To support fluid width,
352
+ we must manually set the dropdown width here; otherwise, it uses a fixed width.
353
+ Also, Only treat menu as non-fluid if isFluid is strictly false, since default is true in menu and undefined means fluid. */ ...(menu.isFluid !==
354
+ false && {
355
+ '--dropdown-width': dropdownWidth,
356
+ }),
357
+ '--menu-elevation': getElevationValue(elevation),
358
+ }}
359
+ >
360
+ {/* $FlowFixMe[incompatible-type] Menu expects MenuOption but receives T */}
361
+ {/* $FlowFixMe[prop-missing] MenuOption properties are missing in T */}
362
+ <Menu
363
+ {...menu}
364
+ onSelect={(option) => {
365
+ if (values.length >= limit) {
366
+ return;
367
+ }
368
+ // $FlowFixMe[incompatible-call] option from Menu is MenuOption but addValue expects T
369
+ // $FlowFixMe[prop-missing] MenuOption properties are missing in T
370
+ addValue(option);
371
+ clickAway();
372
+ inputRef.current?.focus();
373
+ }}
374
+ size={menu.size || size}
375
+ onTabOut={clickAway}
376
+ ref={menuRef}
377
+ />
378
+ </div>
379
+ </FloatingFocusManager>
380
+ </FloatingPortal>
355
381
  )}
356
382
  </div>
357
383
  </>
@@ -150,3 +150,8 @@
150
150
  height: size26;
151
151
  margin-left: auto;
152
152
  }
153
+
154
+ .menuWrapper {
155
+ width: var(--dropdown-width);
156
+ z-index: var(--menu-elevation);
157
+ }
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.Tooltip = exports.ELEVATION_TYPES = exports.DELAY_MOTION_DURATION_TYPES = void 0;
6
+ exports.getElevationValue = exports.Tooltip = exports.ELEVATION_TYPES = exports.DELAY_MOTION_DURATION_TYPES = void 0;
7
7
  var React = _interopRequireWildcard(require("react"));
8
8
  var _react2 = require("@floating-ui/react");
9
9
  var ELEVATION = _interopRequireWildcard(require("../../styles/variables/_elevation"));
@@ -39,6 +39,7 @@ const getElevationValue = elevation => {
39
39
  const elevationKey = 'elevation' + (0, _string.capitalize)(elevation);
40
40
  return ELEVATION[elevationKey] || elevation;
41
41
  };
42
+ exports.getElevationValue = getElevationValue;
42
43
  const Tooltip = _ref => {
43
44
  let {
44
45
  classNames,
@@ -84,7 +84,7 @@ export type BaseTooltipProps = {
84
84
  titleMaxLines?: number,
85
85
  delayMotionDuration?: DelayMotionDurationType,
86
86
  hidden?: boolean,
87
- elevation?: string,
87
+ elevation?: ElevationType,
88
88
  };
89
89
 
90
90
  export type TooltipProps = {
@@ -94,7 +94,7 @@ export type TooltipProps = {
94
94
  children: any,
95
95
  };
96
96
 
97
- const getElevationValue = (elevation: string): string => {
97
+ export const getElevationValue = (elevation: string): string => {
98
98
  const elevationKey = 'elevation' + capitalize(elevation);
99
99
  return ELEVATION[elevationKey] || elevation;
100
100
  };
@@ -31,6 +31,7 @@ const SimpleTypeaheadBase = (props, ref) => {
31
31
  showLabelTooltip,
32
32
  allowInternalFilter = true,
33
33
  allowWrap = false,
34
+ elevation = 'modal',
34
35
  ...inputProps
35
36
  } = props;
36
37
  const [typeaheadInputText, setTypeaheadInputText] = React.useState('');
@@ -84,7 +85,8 @@ const SimpleTypeaheadBase = (props, ref) => {
84
85
  showLabelTooltip,
85
86
  allowWrap
86
87
  },
87
- clickAwayRef: clickAwayRef
88
+ clickAwayRef: clickAwayRef,
89
+ elevation: elevation
88
90
  }));
89
91
  };
90
92
  const SimpleTypeahead = exports.SimpleTypeahead = /*#__PURE__*/React.forwardRef(SimpleTypeaheadBase);
@@ -7,6 +7,7 @@ import type {ClickAwayRefType} from '../../utils/click-away';
7
7
  import {getTextLabelFromSelectedKeys} from '../../utils/menu';
8
8
  import type {InputProps} from '../Input';
9
9
  import type {MenuOption, Virtualization} from '../Menu';
10
+ import type {ElevationType} from '../Tooltip';
10
11
 
11
12
  import {Typeahead} from './Typeahead';
12
13
 
@@ -38,6 +39,7 @@ export type SimpleTypeaheadProps = {
38
39
  menuClassNames?: MenuClassNames,
39
40
  showLabelTooltip?: MenuLabelTooltip,
40
41
  allowWrap?: boolean,
42
+ elevation?: ElevationType,
41
43
 
42
44
  // events
43
45
  onSelect?: (option: MenuOption, ?SyntheticEvent<HTMLElement>) => mixed,
@@ -76,6 +78,7 @@ const SimpleTypeaheadBase = (props: SimpleTypeaheadProps, ref) => {
76
78
  showLabelTooltip,
77
79
  allowInternalFilter = true,
78
80
  allowWrap = false,
81
+ elevation = 'modal',
79
82
  ...inputProps
80
83
  } = props;
81
84
 
@@ -148,6 +151,7 @@ const SimpleTypeaheadBase = (props: SimpleTypeaheadProps, ref) => {
148
151
  allowWrap,
149
152
  }}
150
153
  clickAwayRef={clickAwayRef}
154
+ elevation={elevation}
151
155
  />
152
156
  );
153
157
  };
@@ -6,13 +6,14 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.Typeahead = void 0;
7
7
  var React = _interopRequireWildcard(require("react"));
8
8
  var _react2 = require("@floating-ui/react");
9
- var _size = require("../../styles/variables/_size");
9
+ var _hooks = require("../../hooks");
10
10
  var _space = require("../../styles/variables/_space");
11
11
  var _classify = require("../../utils/classify");
12
12
  var _clickAway = require("../../utils/click-away");
13
13
  var _mergeRefs = require("../../utils/merge-refs");
14
14
  var _Menu = require("../Menu");
15
15
  var _SearchInput = require("../SearchInput");
16
+ var _Tooltip = require("../Tooltip");
16
17
  var _TypeaheadModule = _interopRequireDefault(require("./Typeahead.module.css"));
17
18
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
18
19
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
@@ -33,6 +34,7 @@ const BaseTypeahead = /*#__PURE__*/React.forwardRef((_ref, ref) => {
33
34
  menuOpenOffset = 1,
34
35
  onFocus,
35
36
  clickAwayRef,
37
+ elevation = 'modal',
36
38
  ...inputProps
37
39
  } = _ref;
38
40
  const menuOptions = menu?.options;
@@ -40,7 +42,8 @@ const BaseTypeahead = /*#__PURE__*/React.forwardRef((_ref, ref) => {
40
42
  x,
41
43
  y,
42
44
  refs,
43
- strategy
45
+ strategy,
46
+ context
44
47
  } = (0, _react2.useFloating)({
45
48
  open: true,
46
49
  strategy: 'absolute',
@@ -48,6 +51,7 @@ const BaseTypeahead = /*#__PURE__*/React.forwardRef((_ref, ref) => {
48
51
  whileElementsMounted: _react2.autoUpdate,
49
52
  middleware: [(0, _react2.flip)(), (0, _react2.offset)(parseInt(_space.spaceXXSmall))]
50
53
  });
54
+ const dropdownWidth = (0, _hooks.useReferenceElementWidth)(refs.reference?.current);
51
55
  const onMenuToggle = isOpen => {
52
56
  isOpen ? onMenuOpen && onMenuOpen() : onMenuClose && onMenuClose();
53
57
  };
@@ -64,8 +68,7 @@ const BaseTypeahead = /*#__PURE__*/React.forwardRef((_ref, ref) => {
64
68
  } = _ref2;
65
69
  return /*#__PURE__*/React.createElement("div", {
66
70
  "data-testid": "Typeahead",
67
- className: (0, _classify.classify)(_TypeaheadModule.default.typeaheadContainer, classNames?.wrapper),
68
- ref: boundaryRef
71
+ className: (0, _classify.classify)(_TypeaheadModule.default.typeaheadContainer, classNames?.wrapper)
69
72
  }, /*#__PURE__*/React.createElement(_SearchInput.SearchInput, _extends({}, inputProps, {
70
73
  ref: ref,
71
74
  boxRef: (0, _mergeRefs.mergeRefs)([refs.setReference, triggerRef]),
@@ -96,13 +99,27 @@ const BaseTypeahead = /*#__PURE__*/React.forwardRef((_ref, ref) => {
96
99
  onClear: _e => {
97
100
  onClear?.();
98
101
  }
99
- })), isOpen && !isLoading && menu && menuOptions && !!menuOptions.length && /*#__PURE__*/React.createElement("div", {
100
- ref: refs.setFloating,
102
+ })), isOpen && !isLoading && menu && menuOptions && !!menuOptions.length && /*#__PURE__*/React.createElement(_react2.FloatingPortal, null, /*#__PURE__*/React.createElement(_react2.FloatingFocusManager, {
103
+ modal: false,
104
+ context: context,
105
+ returnFocus: false,
106
+ initialFocus: refs.reference
107
+ }, /*#__PURE__*/React.createElement("div", {
108
+ ref: (0, _mergeRefs.mergeRefs)([refs.setFloating, boundaryRef]),
109
+ className: _TypeaheadModule.default.menuWrapper,
101
110
  style: {
102
111
  position: strategy,
103
112
  top: y ?? _space.spaceNone,
104
113
  left: x ?? _space.spaceNone,
105
- width: _size.sizeFluid
114
+ /* NOTE(Sharad): The FloatingPortal renders the menu outside the normal DOM structure,
115
+ so its parent is effectively the <body> element. This means the menu
116
+ would otherwise default to the body's width. To support fluid width,
117
+ we must manually set the dropdown width here; otherwise, it uses a fixed width.
118
+ Also, Only treat menu as non-fluid if isFluid is strictly false, since default is true in menu and undefined means fluid. */
119
+ ...(menu.isFluid !== false && {
120
+ '--dropdown-width': dropdownWidth
121
+ }),
122
+ '--menu-elevation': (0, _Tooltip.getElevationValue)(elevation)
106
123
  }
107
124
  }, /*#__PURE__*/React.createElement(_Menu.Menu, _extends({}, menu, {
108
125
  options: menuOptions,
@@ -116,7 +133,7 @@ const BaseTypeahead = /*#__PURE__*/React.forwardRef((_ref, ref) => {
116
133
  },
117
134
  size: menu.size || size,
118
135
  onTabOut: clickAway
119
- }))));
136
+ }))))));
120
137
  });
121
138
  });
122
139
  const StatefulTypeahead = /*#__PURE__*/React.forwardRef((_ref3, ref) => {