@spaced-out/ui-design-system 0.6.35-beta.0 → 0.6.35
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/.cspell/custom-words.txt +0 -9
- package/CHANGELOG.md +9 -0
- package/lib/components/Menu/Menu.d.ts +1 -71
- package/lib/components/Menu/Menu.d.ts.map +1 -1
- package/lib/components/Menu/Menu.js +221 -1035
- package/lib/components/Menu/Menu.module.css +27 -148
- package/lib/components/Menu/MenuOptionButton.d.ts +2 -23
- package/lib/components/Menu/MenuOptionButton.d.ts.map +1 -1
- package/lib/components/Menu/MenuOptionButton.js +38 -87
- package/lib/components/Menu/index.d.ts +0 -2
- package/lib/components/Menu/index.d.ts.map +1 -1
- package/lib/components/Menu/index.js +0 -22
- package/lib/hooks/index.d.ts +0 -1
- package/lib/hooks/index.d.ts.map +1 -1
- package/lib/hooks/index.js +0 -11
- package/lib/utils/click-away/click-away.d.ts +0 -3
- package/lib/utils/click-away/click-away.d.ts.map +1 -1
- package/lib/utils/click-away/click-away.js +0 -49
- package/mcp/package.json +1 -1
- package/package.json +1 -1
- package/lib/components/Menu/menuOptionId.d.ts +0 -12
- package/lib/components/Menu/menuOptionId.d.ts.map +0 -1
- package/lib/components/Menu/menuOptionId.js +0 -18
- package/lib/components/Menu/useMenuKeyboardNavigation.d.ts +0 -93
- package/lib/components/Menu/useMenuKeyboardNavigation.d.ts.map +0 -1
- package/lib/components/Menu/useMenuKeyboardNavigation.js +0 -471
- package/lib/components/Menu/useMenuTrigger.d.ts +0 -183
- package/lib/components/Menu/useMenuTrigger.d.ts.map +0 -1
- package/lib/components/Menu/useMenuTrigger.js +0 -347
- package/lib/hooks/useInteractionModality/index.d.ts +0 -2
- package/lib/hooks/useInteractionModality/index.d.ts.map +0 -1
- package/lib/hooks/useInteractionModality/index.js +0 -16
- package/lib/hooks/useInteractionModality/useInteractionModality.d.ts +0 -15
- package/lib/hooks/useInteractionModality/useInteractionModality.d.ts.map +0 -1
- package/lib/hooks/useInteractionModality/useInteractionModality.js +0 -103
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
@value (
|
|
10
10
|
colorBackgroundSecondary,
|
|
11
11
|
colorFillSecondary,
|
|
12
|
-
colorFillPrimary,
|
|
13
12
|
colorTextDisabled,
|
|
14
13
|
colorTextPrimary,
|
|
15
14
|
colorTextSecondary,
|
|
@@ -61,17 +60,6 @@
|
|
|
61
60
|
z-index: elevationMenu;
|
|
62
61
|
}
|
|
63
62
|
|
|
64
|
-
/*
|
|
65
|
-
* The options carry their own scroll container, so the card must not scroll as
|
|
66
|
-
* well — otherwise both would show a scrollbar. `hidden` also keeps a pinned
|
|
67
|
-
* header / footer inside the border radius.
|
|
68
|
-
*/
|
|
69
|
-
.menuCardTopPaddingZero,
|
|
70
|
-
.menuCardBottomPaddingZero,
|
|
71
|
-
.menuCardNoScroll {
|
|
72
|
-
overflow: hidden;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
63
|
.menuCardTopPaddingZero {
|
|
76
64
|
padding-top: spaceNone;
|
|
77
65
|
}
|
|
@@ -80,28 +68,7 @@
|
|
|
80
68
|
padding-bottom: spaceNone;
|
|
81
69
|
}
|
|
82
70
|
|
|
83
|
-
|
|
84
|
-
* Scrolls the options only. A header / footer is a flex sibling of this element
|
|
85
|
-
* rather than something sticky inside it, so the scrollbar spans just the option
|
|
86
|
-
* list — it no longer runs the whole height of the card behind the bars — and no
|
|
87
|
-
* option can be clipped under them. `min-height: 0` is what lets a flex item
|
|
88
|
-
* actually shrink and scroll instead of growing to fit its content.
|
|
89
|
-
*/
|
|
90
|
-
.optionsScroll {
|
|
91
|
-
display: flex;
|
|
92
|
-
flex-flow: column;
|
|
93
|
-
flex: 1 1 auto;
|
|
94
|
-
min-height: 0;
|
|
95
|
-
overflow-y: auto;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/*
|
|
99
|
-
* Collapse a menu that renders nothing. `:empty` alone no longer suffices: the
|
|
100
|
-
* card always holds the (possibly empty) role="listbox" element so the trigger's
|
|
101
|
-
* aria-controls resolves, so Menu also sets `.menuCardEmpty` explicitly.
|
|
102
|
-
*/
|
|
103
|
-
.menuCard:empty,
|
|
104
|
-
.menuCard.menuCardEmpty {
|
|
71
|
+
.menuCard:empty {
|
|
105
72
|
padding: spaceNone;
|
|
106
73
|
border: none;
|
|
107
74
|
}
|
|
@@ -198,58 +165,25 @@
|
|
|
198
165
|
color: colorTextTertiary;
|
|
199
166
|
}
|
|
200
167
|
|
|
201
|
-
/*
|
|
202
|
-
* Background for the highlighted option (the "cursor"). There is only ever one —
|
|
203
|
-
* the Menu keeps it in sync across pointer and keyboard. `.active` covers the
|
|
204
|
-
* combobox active-descendant case (focus stays on the input); :hover covers a
|
|
205
|
-
* plain mouse-over.
|
|
206
|
-
*/
|
|
207
168
|
.option:hover,
|
|
208
|
-
.option:active
|
|
209
|
-
.option.active {
|
|
210
|
-
outline: none;
|
|
211
|
-
color: colorTextPrimary;
|
|
169
|
+
.option:active {
|
|
212
170
|
background: colorBackgroundSecondary;
|
|
171
|
+
color: colorTextPrimary;
|
|
213
172
|
}
|
|
214
173
|
|
|
215
|
-
.option:hover .optionTextSecondaryLabel
|
|
216
|
-
.option:active .optionTextSecondaryLabel,
|
|
217
|
-
.option.active .optionTextSecondaryLabel,
|
|
218
|
-
.option:focus .optionTextSecondaryLabel {
|
|
174
|
+
.option:hover .optionTextSecondaryLabel {
|
|
219
175
|
color: colorTextSecondary;
|
|
220
176
|
}
|
|
221
177
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
* that reads as a stray focus artefact rather than an intentional indicator. The
|
|
228
|
-
* checkbox / radio glyph carries the state in those variants, and forced-colors
|
|
229
|
-
* mode below re-expresses it as a full outline, which the radius follows cleanly.
|
|
230
|
-
*/
|
|
231
|
-
.option.selected {
|
|
232
|
-
background: colorFillSecondary;
|
|
178
|
+
.option:active .optionTextSecondaryLabel {
|
|
179
|
+
color: colorTextSecondary;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.option:focus {
|
|
233
183
|
outline: none;
|
|
234
184
|
color: colorTextPrimary;
|
|
235
185
|
}
|
|
236
186
|
|
|
237
|
-
/*
|
|
238
|
-
* Focus ring — KEYBOARD ONLY. A focus indicator has to mean "focus is here", so
|
|
239
|
-
* it must not appear under the mouse pointer:
|
|
240
|
-
*
|
|
241
|
-
* - `.activeRing` is set by Menu for the combobox modes (Dropdown / Typeahead),
|
|
242
|
-
* where DOM focus stays on the input and the active option is virtual. Menu
|
|
243
|
-
* withholds it when the highlight came from the pointer.
|
|
244
|
-
* - `:focus-visible` covers the roving menus, which move real DOM focus. It is
|
|
245
|
-
* exactly the right selector here: arrow-key navigation calls .focus() after a
|
|
246
|
-
* key press so the ring shows, while hover-driven .focus() follows a pointer
|
|
247
|
-
* interaction so it does not.
|
|
248
|
-
*
|
|
249
|
-
* Declared after `.selected`, which sets no box-shadow of its own, so a selected
|
|
250
|
-
* option that also has focus shows the ring without anything to fight over.
|
|
251
|
-
*/
|
|
252
|
-
.option.activeRing,
|
|
253
187
|
.option:focus-visible {
|
|
254
188
|
outline: none;
|
|
255
189
|
color: colorTextPrimary;
|
|
@@ -257,34 +191,20 @@
|
|
|
257
191
|
borderWidthTertiary colorFocusSecondary;
|
|
258
192
|
}
|
|
259
193
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
outline-offset: calc(-1 * borderWidthTertiary);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
/*
|
|
278
|
-
* Keyboard focus must stay distinguishable from BOTH the hover highlight and
|
|
279
|
-
* the selected state, and Highlight / SelectedItem commonly resolve to the same
|
|
280
|
-
* system color — so change the outline STYLE rather than add a third color.
|
|
281
|
-
* Declared last so a selected option that also has focus still shows it.
|
|
282
|
-
*/
|
|
283
|
-
.option.activeRing,
|
|
284
|
-
.option:focus-visible {
|
|
285
|
-
outline: borderWidthTertiary dashed Highlight;
|
|
286
|
-
outline-offset: calc(-1 * borderWidthTertiary);
|
|
287
|
-
}
|
|
194
|
+
.option:focus-within {
|
|
195
|
+
outline: none;
|
|
196
|
+
color: colorTextPrimary;
|
|
197
|
+
/* box-shadow: none; */
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.option.selected {
|
|
201
|
+
background: colorFillSecondary;
|
|
202
|
+
outline: none;
|
|
203
|
+
color: colorTextPrimary;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.option:focus .optionTextSecondaryLabel {
|
|
207
|
+
color: colorTextSecondary;
|
|
288
208
|
}
|
|
289
209
|
|
|
290
210
|
.disabled {
|
|
@@ -324,41 +244,6 @@
|
|
|
324
244
|
flex-flow: column;
|
|
325
245
|
}
|
|
326
246
|
|
|
327
|
-
/*
|
|
328
|
-
* Wraps only the option list so the listbox role contains option children
|
|
329
|
-
* exclusively (search/header/footer stay outside it). display:contents keeps
|
|
330
|
-
* the existing flex layout of .menuCard unchanged.
|
|
331
|
-
*/
|
|
332
|
-
.optionsListbox {
|
|
333
|
-
display: contents;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
/*
|
|
337
|
-
* The listbox as the element that actually scrolls. Under virtualization
|
|
338
|
-
* react-window's own scroll box carries the role (see ListboxOuter); this is the
|
|
339
|
-
* same arrangement for a plain option list, and it matters beyond tidiness: the
|
|
340
|
-
* options are not focusable themselves whenever a combobox trigger drives the
|
|
341
|
-
* menu, so a
|
|
342
|
-
* scroll container that is NOT the combobox's popup reads as an unreachable
|
|
343
|
-
* scroll area (axe `scrollable-region-focusable`). Making the listbox the
|
|
344
|
-
* scroller means the region IS the popup, which that rule exempts.
|
|
345
|
-
*/
|
|
346
|
-
.optionsListboxScroll {
|
|
347
|
-
display: flex;
|
|
348
|
-
flex-flow: column;
|
|
349
|
-
flex: 1 1 auto;
|
|
350
|
-
min-height: 0;
|
|
351
|
-
overflow-y: auto;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/*
|
|
355
|
-
* role="group" wrapper around each titled option group. display:contents keeps
|
|
356
|
-
* the existing flex layout (title + options) unchanged.
|
|
357
|
-
*/
|
|
358
|
-
.optionGroup {
|
|
359
|
-
display: contents;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
247
|
.groupTitleWrapper {
|
|
363
248
|
composes: formLabelSmall from '../../styles/typography.module.css';
|
|
364
249
|
display: flex;
|
|
@@ -375,16 +260,11 @@
|
|
|
375
260
|
margin-left: spaceSmall;
|
|
376
261
|
}
|
|
377
262
|
|
|
378
|
-
/*
|
|
379
|
-
* Pinned by living OUTSIDE the options scroll container rather than by sticking
|
|
380
|
-
* inside it, so it never has the option list's scrollbar running behind it and
|
|
381
|
-
* never has an option tucked under it. `relative` positions the divider below.
|
|
382
|
-
*/
|
|
383
263
|
.menuHeader {
|
|
384
|
-
position:
|
|
385
|
-
flex: 0 0 auto;
|
|
264
|
+
position: sticky;
|
|
386
265
|
background-color: colorBackgroundTertiary;
|
|
387
266
|
padding: spaceXSmall spaceNone;
|
|
267
|
+
top: spaceNone;
|
|
388
268
|
margin-bottom: spaceXSmall;
|
|
389
269
|
z-index: calc(elevationCard/4);
|
|
390
270
|
min-height: size50;
|
|
@@ -400,12 +280,11 @@
|
|
|
400
280
|
border-bottom: borderWidthPrimary solid colorBorderPrimary;
|
|
401
281
|
}
|
|
402
282
|
|
|
403
|
-
/* As `.menuHeader`, pinned by sitting outside the options scroll container. */
|
|
404
283
|
.menuFooter {
|
|
405
|
-
position:
|
|
406
|
-
flex: 0 0 auto;
|
|
284
|
+
position: sticky;
|
|
407
285
|
background-color: colorBackgroundTertiary;
|
|
408
286
|
padding: spaceXSmall spaceNone;
|
|
287
|
+
bottom: spaceNone;
|
|
409
288
|
margin-top: spaceXSmall;
|
|
410
289
|
min-height: size50;
|
|
411
290
|
max-height: size50;
|
|
@@ -1,31 +1,10 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import type { CSSProperties } from 'react';
|
|
3
3
|
import type { BaseMenuProps, MenuOption } from '../../components/Menu/Menu';
|
|
4
|
-
export interface MenuOptionProps extends Omit<BaseMenuProps, 'option' | 'style'> {
|
|
4
|
+
export interface MenuOptionProps extends Omit<BaseMenuProps, 'option' | 'isLastItem' | 'style'> {
|
|
5
5
|
option: MenuOption;
|
|
6
|
+
isLastItem?: boolean;
|
|
6
7
|
style?: CSSProperties | undefined;
|
|
7
|
-
/** Total option count — set for virtualized lists so AT announces "N of total". */
|
|
8
|
-
setSize?: number;
|
|
9
|
-
/** 1-based position — set for virtualized lists (windowed DOM hides the rest). */
|
|
10
|
-
posInSet?: number;
|
|
11
|
-
/**
|
|
12
|
-
* Make this option the active highlight when the pointer moves over it, so
|
|
13
|
-
* mouse and keyboard share one cursor (and roving focus follows the pointer).
|
|
14
|
-
* `clientX`/`clientY` let Menu drop no-op moves (scroll under a still cursor).
|
|
15
|
-
*/
|
|
16
|
-
onPointerActivate?: (key: string, el: HTMLElement, clientX: number, clientY: number) => void;
|
|
17
|
-
/**
|
|
18
|
-
* Key of the option the POINTER most recently highlighted. Used to keep the
|
|
19
|
-
* focus ring off a highlight the mouse created, while the background tint still
|
|
20
|
-
* follows the pointer.
|
|
21
|
-
*/
|
|
22
|
-
pointerActiveKey?: string | null;
|
|
23
|
-
/**
|
|
24
|
-
* Withhold the highlight the menu opened with. Set when the menu was opened by
|
|
25
|
-
* mouse, so it does not appear to have a cursor the user never placed; cleared
|
|
26
|
-
* as soon as they move the active option themselves.
|
|
27
|
-
*/
|
|
28
|
-
suppressInitialHighlight?: boolean;
|
|
29
8
|
testId?: string;
|
|
30
9
|
}
|
|
31
10
|
export declare const MenuOptionButton: (props: MenuOptionProps) => React.JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MenuOptionButton.d.ts","sourceRoot":"","sources":["../../../src/components/Menu/MenuOptionButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,OAAO,CAAC;AASzC,OAAO,KAAK,EAAC,aAAa,EAAE,UAAU,EAAC,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"MenuOptionButton.d.ts","sourceRoot":"","sources":["../../../src/components/Menu/MenuOptionButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,OAAO,CAAC;AASzC,OAAO,KAAK,EAAC,aAAa,EAAE,UAAU,EAAC,MAAM,0BAA0B,CAAC;AAQxE,MAAM,WAAW,eACf,SAAQ,IAAI,CAAC,aAAa,EAAE,QAAQ,GAAG,YAAY,GAAG,OAAO,CAAC;IAC9D,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,gBAAgB,GAAI,OAAO,eAAe,sBA+MtD,CAAC"}
|
|
@@ -10,7 +10,6 @@ var _qa = require("../../utils/qa");
|
|
|
10
10
|
var _Button = require("../Button");
|
|
11
11
|
var _Checkbox = require("../Checkbox");
|
|
12
12
|
var _Icon = require("../Icon");
|
|
13
|
-
var _menuOptionId = require("./menuOptionId");
|
|
14
13
|
var _RadioButton = require("../RadioButton");
|
|
15
14
|
var _Truncate = require("../Truncate");
|
|
16
15
|
var _TruncatedTextWithTooltip = require("../TruncatedTextWithTooltip");
|
|
@@ -19,6 +18,7 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
19
18
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
20
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); }
|
|
21
20
|
const MenuOptionButton = props => {
|
|
21
|
+
const lastMenuItemRef = React.useRef(null);
|
|
22
22
|
const {
|
|
23
23
|
option,
|
|
24
24
|
size = 'medium',
|
|
@@ -28,20 +28,13 @@ const MenuOptionButton = props => {
|
|
|
28
28
|
classNames,
|
|
29
29
|
optionsVariant = 'normal',
|
|
30
30
|
selectedKeys,
|
|
31
|
+
isLastItem,
|
|
32
|
+
onTabOut,
|
|
31
33
|
resolveLabel,
|
|
32
34
|
resolveSecondaryLabel,
|
|
33
35
|
style,
|
|
34
36
|
showLabelTooltip,
|
|
35
37
|
allowWrap = false,
|
|
36
|
-
allowSearch = false,
|
|
37
|
-
menuId,
|
|
38
|
-
activeOptionKey,
|
|
39
|
-
externalKeyboardNav = false,
|
|
40
|
-
setSize,
|
|
41
|
-
posInSet,
|
|
42
|
-
onPointerActivate,
|
|
43
|
-
pointerActiveKey,
|
|
44
|
-
suppressInitialHighlight = false,
|
|
45
38
|
testId
|
|
46
39
|
} = props;
|
|
47
40
|
const {
|
|
@@ -69,45 +62,24 @@ const MenuOptionButton = props => {
|
|
|
69
62
|
}
|
|
70
63
|
return selectedKeys.includes(option.key);
|
|
71
64
|
};
|
|
72
|
-
const isOptionSelected = isSelected() || key === selectedOption?.key;
|
|
73
|
-
const isOptionDisabled = Boolean(menuDisabled || disabled);
|
|
74
|
-
// Roving tabindex: Menu always passes activeOptionKey (string | null), so a
|
|
75
|
-
// single option owns the tab stop. The `undefined` fallback only matters if a
|
|
76
|
-
// MenuOptionButton is rendered outside Menu — there every option stays
|
|
77
|
-
// tabbable (default tabIndex), preserving the pre-roving behavior.
|
|
78
|
-
const isRoving = activeOptionKey !== undefined;
|
|
79
|
-
// `isActive` still drives the roving tab stop and aria-activedescendant — the
|
|
80
|
-
// menu always has an active option so the keyboard has somewhere to start.
|
|
81
|
-
// `showHighlight` is the visible half of it, withheld while the only reason an
|
|
82
|
-
// option is active is that the menu just opened under the mouse.
|
|
83
|
-
const isActive = isRoving && activeOptionKey === key;
|
|
84
|
-
const showHighlight = isActive && !suppressInitialHighlight;
|
|
85
|
-
// Focus ring. Only the combobox modes need a CLASS for it: there, DOM focus
|
|
86
|
-
// stays on the trigger input and this ring is the only cursor the user has, so
|
|
87
|
-
// it is drawn from `activeOptionKey` — minus any highlight the pointer created,
|
|
88
|
-
// since a focus indicator must not follow the mouse.
|
|
89
|
-
//
|
|
90
|
-
// Roving menus move real DOM focus, so they are left to `:focus-visible` in CSS,
|
|
91
|
-
// which the browser only matches for keyboard-driven focus. That is why merely
|
|
92
|
-
// opening a roving menu with the mouse no longer paints a ring.
|
|
93
|
-
const isVirtualFocusMode = allowSearch || externalKeyboardNav;
|
|
94
|
-
const showActiveRing = showHighlight && isVirtualFocusMode && pointerActiveKey !== key;
|
|
95
|
-
// The option is a real tab stop only under true roving focus. Under search or
|
|
96
|
-
// external combobox nav, focus stays on the input — every option is -1 and the
|
|
97
|
-
// active one is surfaced through the input's aria-activedescendant instead.
|
|
98
|
-
const optionTabIndex = externalKeyboardNav ? -1 : isRoving ? isActive && !allowSearch ? 0 : -1 : undefined;
|
|
99
|
-
const optionId = menuId ? (0, _menuOptionId.menuOptionId)(menuId, key) : undefined;
|
|
100
65
|
React.useEffect(() => {
|
|
101
66
|
setButtonSize(optionSize || size);
|
|
102
67
|
}, [optionSize, size]);
|
|
68
|
+
React.useEffect(() => {
|
|
69
|
+
const handleKeyDown = event => {
|
|
70
|
+
if (event.key === 'Tab' && !event.shiftKey) {
|
|
71
|
+
// Tab pressed without shift key, calling tab out callback
|
|
72
|
+
onTabOut?.();
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
lastMenuItemRef.current?.addEventListener('keydown', handleKeyDown);
|
|
76
|
+
return () => {
|
|
77
|
+
lastMenuItemRef.current?.removeEventListener('keydown', handleKeyDown);
|
|
78
|
+
};
|
|
79
|
+
}, [isLastItem]);
|
|
103
80
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Button.UnstyledButton, {
|
|
104
81
|
className: (0, _classify.classify)(_MenuModule.default.option, {
|
|
105
82
|
[_MenuModule.default.selected]: isSelected() || key === selectedOption?.key,
|
|
106
|
-
// Background highlight for the single active option, from either input
|
|
107
|
-
// source, so pointer and keyboard never show two cursors.
|
|
108
|
-
[_MenuModule.default.active]: showHighlight,
|
|
109
|
-
// Focus ring, keyboard-driven highlights only.
|
|
110
|
-
[_MenuModule.default.activeRing]: showActiveRing,
|
|
111
83
|
[_MenuModule.default.optionSmall]: buttonSize === 'small',
|
|
112
84
|
[_MenuModule.default.optionMedium]: buttonSize === 'medium',
|
|
113
85
|
[_MenuModule.default.disabled]: menuDisabled || disabled,
|
|
@@ -115,57 +87,36 @@ const MenuOptionButton = props => {
|
|
|
115
87
|
[_MenuModule.default.withIconRight]: !!iconRight
|
|
116
88
|
}, classNames?.option, optionClassNames?.wrapper),
|
|
117
89
|
style: style,
|
|
118
|
-
disabled:
|
|
119
|
-
role: "option",
|
|
120
|
-
"aria-selected": isOptionSelected,
|
|
121
|
-
"aria-disabled": isOptionDisabled || undefined,
|
|
122
|
-
"aria-setsize": setSize,
|
|
123
|
-
"aria-posinset": posInSet,
|
|
124
|
-
tabIndex: optionTabIndex,
|
|
125
|
-
id: optionId,
|
|
126
|
-
"data-menu-option-key": key,
|
|
90
|
+
disabled: menuDisabled || disabled,
|
|
127
91
|
onClick: e => onSelect && onSelect(option, e),
|
|
128
|
-
|
|
129
|
-
// Pointer drives the same single active highlight as the keyboard.
|
|
130
|
-
// Guarded so it only fires when crossing into a different option. The
|
|
131
|
-
// cursor coordinates are forwarded so Menu can ignore moves with no real
|
|
132
|
-
// pointer delta (the list scrolling under a stationary cursor during
|
|
133
|
-
// keyboard nav), which would otherwise steal focus from the keyboard.
|
|
134
|
-
if (isOptionDisabled || isActive) {
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
onPointerActivate?.(key, e.currentTarget, e.clientX, e.clientY);
|
|
138
|
-
},
|
|
92
|
+
autoFocus: selectedOption?.key === key,
|
|
139
93
|
testId: (0, _qa.generateTestId)({
|
|
140
94
|
base: optionTestId || testId,
|
|
141
95
|
slot: 'option-button',
|
|
142
96
|
index: key
|
|
143
97
|
}),
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
98
|
+
...(isLastItem ? {
|
|
99
|
+
ref: lastMenuItemRef
|
|
100
|
+
} : {}),
|
|
101
|
+
children: [optionVariant === 'checkbox' && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Checkbox.Checkbox, {
|
|
102
|
+
tabIndex: -1,
|
|
103
|
+
disabled: menuDisabled || disabled,
|
|
104
|
+
checked: isSelected(),
|
|
105
|
+
indeterminate: indeterminate,
|
|
106
|
+
testId: (0, _qa.generateTestId)({
|
|
107
|
+
base: optionTestId || testId,
|
|
108
|
+
slot: 'checkbox',
|
|
109
|
+
index: key
|
|
156
110
|
})
|
|
157
|
-
}), optionVariant === 'radio' && /*#__PURE__*/(0, _jsxRuntime.jsx)(
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
slot: 'radio-button',
|
|
167
|
-
index: key
|
|
168
|
-
})
|
|
111
|
+
}), optionVariant === 'radio' && /*#__PURE__*/(0, _jsxRuntime.jsx)(_RadioButton.RadioButton, {
|
|
112
|
+
disabled: menuDisabled || disabled,
|
|
113
|
+
value: option.key,
|
|
114
|
+
selectedValue: selectedKeys?.[0],
|
|
115
|
+
tabIndex: -1,
|
|
116
|
+
testId: (0, _qa.generateTestId)({
|
|
117
|
+
base: optionTestId || testId,
|
|
118
|
+
slot: 'radio-button',
|
|
119
|
+
index: key
|
|
169
120
|
})
|
|
170
121
|
}), !!iconLeft && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.Icon, {
|
|
171
122
|
name: iconLeft,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Menu/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,sCAAsC,CAAC
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Menu/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,sCAAsC,CAAC"}
|
|
@@ -24,26 +24,4 @@ Object.keys(_MenuOptionButton).forEach(function (key) {
|
|
|
24
24
|
return _MenuOptionButton[key];
|
|
25
25
|
}
|
|
26
26
|
});
|
|
27
|
-
});
|
|
28
|
-
var _useMenuTrigger = require("./useMenuTrigger");
|
|
29
|
-
Object.keys(_useMenuTrigger).forEach(function (key) {
|
|
30
|
-
if (key === "default" || key === "__esModule") return;
|
|
31
|
-
if (key in exports && exports[key] === _useMenuTrigger[key]) return;
|
|
32
|
-
Object.defineProperty(exports, key, {
|
|
33
|
-
enumerable: true,
|
|
34
|
-
get: function () {
|
|
35
|
-
return _useMenuTrigger[key];
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
var _useMenuKeyboardNavigation = require("./useMenuKeyboardNavigation");
|
|
40
|
-
Object.keys(_useMenuKeyboardNavigation).forEach(function (key) {
|
|
41
|
-
if (key === "default" || key === "__esModule") return;
|
|
42
|
-
if (key in exports && exports[key] === _useMenuKeyboardNavigation[key]) return;
|
|
43
|
-
Object.defineProperty(exports, key, {
|
|
44
|
-
enumerable: true,
|
|
45
|
-
get: function () {
|
|
46
|
-
return _useMenuKeyboardNavigation[key];
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
27
|
});
|
package/lib/hooks/index.d.ts
CHANGED
|
@@ -4,7 +4,6 @@ export * from '../hooks/useDebounce';
|
|
|
4
4
|
export * from '../hooks/useFileUpload';
|
|
5
5
|
export * from '../hooks/useFilteredOptions';
|
|
6
6
|
export * from '../hooks/useInfiniteScroll';
|
|
7
|
-
export * from '../hooks/useInteractionModality';
|
|
8
7
|
export * from '../hooks/useInputState';
|
|
9
8
|
export * from '../hooks/useLockedBody';
|
|
10
9
|
export * from '../hooks/useModal';
|
package/lib/hooks/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,sCAAsC,CAAC;AACrD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,sCAAsC,CAAC;AACrD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,oCAAoC,CAAC;AACnD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC"}
|
package/lib/hooks/index.js
CHANGED
|
@@ -69,17 +69,6 @@ Object.keys(_useInfiniteScroll).forEach(function (key) {
|
|
|
69
69
|
}
|
|
70
70
|
});
|
|
71
71
|
});
|
|
72
|
-
var _useInteractionModality = require("./useInteractionModality");
|
|
73
|
-
Object.keys(_useInteractionModality).forEach(function (key) {
|
|
74
|
-
if (key === "default" || key === "__esModule") return;
|
|
75
|
-
if (key in exports && exports[key] === _useInteractionModality[key]) return;
|
|
76
|
-
Object.defineProperty(exports, key, {
|
|
77
|
-
enumerable: true,
|
|
78
|
-
get: function () {
|
|
79
|
-
return _useInteractionModality[key];
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
72
|
var _useInputState = require("./useInputState");
|
|
84
73
|
Object.keys(_useInputState).forEach(function (key) {
|
|
85
74
|
if (key === "default" || key === "__esModule") return;
|
|
@@ -56,14 +56,11 @@ export declare class ClickAway<TTrigger extends HTMLElement = HTMLButtonElement,
|
|
|
56
56
|
el: HTMLElement | null | undefined;
|
|
57
57
|
boundaryRef: BoundaryRefType<TBoundary>;
|
|
58
58
|
triggerRef: TriggerRefType<TTrigger>;
|
|
59
|
-
previouslyFocused: HTMLElement | null;
|
|
60
|
-
closedByOutsideClick: boolean;
|
|
61
59
|
componentDidMount(): void;
|
|
62
60
|
componentDidUpdate(_prevProps: Readonly<ClickAwayProps<TTrigger, TBoundary>>, prevState: Readonly<ClickAwayState>): void;
|
|
63
61
|
componentWillUnmount(): void;
|
|
64
62
|
render(): React.ReactNode;
|
|
65
63
|
handleOpenClick: () => void;
|
|
66
|
-
restoreFocus: () => void;
|
|
67
64
|
handleCloseClick: (evt: MouseEvent) => void;
|
|
68
65
|
handleCloseOnEscapeKeypress: (evt?: KeyboardEvent) => void;
|
|
69
66
|
forceClose: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"click-away.d.ts","sourceRoot":"","sources":["../../../src/utils/click-away/click-away.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,KAAK,eAAe,CAAC,CAAC,SAAS,WAAW,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAExE,KAAK,cAAc,CAAC,CAAC,SAAS,WAAW,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAEvE,MAAM,WAAW,UAAU,CACzB,QAAQ,SAAS,WAAW,GAAG,iBAAiB,EAChD,SAAS,SAAS,WAAW,GAAG,cAAc;IAE9C,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAClC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACtC,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,WAAW,EAAE,eAAe,CAAC,SAAS,CAAC,CAAC;IACxC,UAAU,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,cAAc,CAC7B,QAAQ,SAAS,WAAW,GAAG,iBAAiB,EAChD,SAAS,SAAS,WAAW,GAAG,cAAc;IAE9C,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;IACtE,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IACxC,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACxD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,6BAA6B,CAAC,EAAE,OAAO,CAAC;CACzC;AAED,UAAU,cAAc;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAClC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CACvC;AAID,qBAAa,SAAS,CACpB,QAAQ,SAAS,WAAW,GAAG,iBAAiB,EAChD,SAAS,SAAS,WAAW,GAAG,cAAc,CAC9C,SAAQ,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,cAAc,CAAC;IAC5E,MAAM,CAAC,YAAY,EAAE;QACnB,6BAA6B,CAAC,EAAE,OAAO,CAAC;QACxC,qBAAqB,CAAC,EAAE,OAAO,CAAC;KACjC,CAGC;IAEF,KAAK,EAAE,cAAc,CAInB;IAEF,EAAE,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,CAAQ;IAC1C,WAAW,EAAE,eAAe,CAAC,SAAS,CAAC,CAAgC;IACvE,UAAU,EAAE,cAAc,CAAC,QAAQ,CAAC,CAA+B;
|
|
1
|
+
{"version":3,"file":"click-away.d.ts","sourceRoot":"","sources":["../../../src/utils/click-away/click-away.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,17 +24,6 @@ class ClickAway extends React.Component {
|
|
|
24
24
|
el = null;
|
|
25
25
|
boundaryRef = /*#__PURE__*/React.createRef();
|
|
26
26
|
triggerRef = /*#__PURE__*/React.createRef();
|
|
27
|
-
// Element that had focus right before the popup opened. Restored on close so
|
|
28
|
-
// keyboard focus returns to the trigger (Escape, a selection, Tab past the
|
|
29
|
-
// popup's edge) — the job FloatingFocusManager's returnFocus does for the
|
|
30
|
-
// dropdown family until they move onto this.
|
|
31
|
-
previouslyFocused = null;
|
|
32
|
-
// Set by handleCloseClick for the close that follows. A click on the page is
|
|
33
|
-
// the user moving on: focus belongs wherever they clicked (or on <body>), and
|
|
34
|
-
// pulling it back onto the trigger would re-run the trigger's own focus
|
|
35
|
-
// handling — a Typeahead opens its menu on focus, so it would reopen the very
|
|
36
|
-
// popup the click dismissed.
|
|
37
|
-
closedByOutsideClick = false;
|
|
38
27
|
componentDidMount() {
|
|
39
28
|
if (this.el) {
|
|
40
29
|
this.setState({
|
|
@@ -60,12 +49,6 @@ class ClickAway extends React.Component {
|
|
|
60
49
|
capture: true
|
|
61
50
|
});
|
|
62
51
|
window.document.removeEventListener('keyup', this.handleCloseOnEscapeKeypress);
|
|
63
|
-
if (this.closedByOutsideClick) {
|
|
64
|
-
this.previouslyFocused = null;
|
|
65
|
-
} else {
|
|
66
|
-
this.restoreFocus();
|
|
67
|
-
}
|
|
68
|
-
this.closedByOutsideClick = false;
|
|
69
52
|
}
|
|
70
53
|
}
|
|
71
54
|
}
|
|
@@ -109,42 +92,11 @@ class ClickAway extends React.Component {
|
|
|
109
92
|
if (this.el) {
|
|
110
93
|
pageBottom = this.pageBottom();
|
|
111
94
|
}
|
|
112
|
-
|
|
113
|
-
// Capture the focused element before opening (still the trigger at this
|
|
114
|
-
// point, before the popup mounts and moves focus into itself) so it can be
|
|
115
|
-
// restored on close.
|
|
116
|
-
if (!this.state.isOpen && typeof window.document !== 'undefined') {
|
|
117
|
-
this.previouslyFocused = window.document.activeElement;
|
|
118
|
-
}
|
|
119
95
|
this.setState({
|
|
120
96
|
isOpen: !this.state.isOpen,
|
|
121
97
|
pageBottom
|
|
122
98
|
}, this.handleOnChange);
|
|
123
99
|
};
|
|
124
|
-
|
|
125
|
-
// Return focus to the trigger when the popup closes — but only if focus was
|
|
126
|
-
// lost to the document body (the focused popup element was unmounted). If the
|
|
127
|
-
// user moved focus elsewhere (e.g. clicked another control), leave it there.
|
|
128
|
-
restoreFocus = () => {
|
|
129
|
-
const previous = this.previouslyFocused;
|
|
130
|
-
this.previouslyFocused = null;
|
|
131
|
-
if (typeof window.document === 'undefined') {
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
const active = window.document.activeElement;
|
|
135
|
-
const focusLost = !active || active === window.document.body;
|
|
136
|
-
if (!focusLost) {
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
// `previouslyFocused` is <body> whenever the opening click did not land on a
|
|
140
|
-
// natively focusable element — notably Safari and Firefox on macOS, which do
|
|
141
|
-
// not focus a <button> on click. Restoring it would be a no-op that strands
|
|
142
|
-
// focus at the top of the document, so fall back to the trigger itself.
|
|
143
|
-
const target = previous && previous !== window.document.body ? previous : this.triggerRef.current;
|
|
144
|
-
if (target && window.document.contains(target)) {
|
|
145
|
-
target.focus();
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
100
|
handleCloseClick = evt => {
|
|
149
101
|
if (evt.target instanceof Node && this.props.containsNestedFloatingPortals && this.boundaryRef.current?.parentElement && (this.boundaryRef.current.parentElement === evt.target || this.boundaryRef.current.parentElement.contains(evt.target))) {
|
|
150
102
|
return;
|
|
@@ -155,7 +107,6 @@ class ClickAway extends React.Component {
|
|
|
155
107
|
if (evt.target instanceof Node && this.triggerRef && (this.triggerRef.current === evt.target || this.triggerRef.current?.contains(evt.target))) {
|
|
156
108
|
return;
|
|
157
109
|
}
|
|
158
|
-
this.closedByOutsideClick = true;
|
|
159
110
|
this.setState({
|
|
160
111
|
isOpen: false
|
|
161
112
|
}, this.handleOnChange);
|
package/mcp/package.json
CHANGED