@atlaskit/dropdown-menu 11.5.10 → 11.5.11
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/CHANGELOG.md +6 -0
- package/dist/cjs/checkbox/dropdown-item-checkbox-group.js +1 -7
- package/dist/cjs/checkbox/dropdown-item-checkbox.js +21 -43
- package/dist/cjs/dropdown-menu-item-group.js +0 -3
- package/dist/cjs/dropdown-menu-item.js +7 -19
- package/dist/cjs/dropdown-menu.js +45 -78
- package/dist/cjs/index.js +0 -8
- package/dist/cjs/internal/components/focus-manager.js +3 -13
- package/dist/cjs/internal/components/menu-wrapper.js +19 -34
- package/dist/cjs/internal/context/checkbox-group-context.js +0 -2
- package/dist/cjs/internal/context/selection-store.js +0 -11
- package/dist/cjs/internal/hooks/use-checkbox-state.js +20 -29
- package/dist/cjs/internal/hooks/use-radio-state.js +13 -32
- package/dist/cjs/internal/hooks/use-register-item-with-focus-manager.js +1 -6
- package/dist/cjs/internal/utils/get-icon-colors.js +0 -4
- package/dist/cjs/internal/utils/handle-focus.js +6 -29
- package/dist/cjs/internal/utils/is-checkbox-item.js +0 -1
- package/dist/cjs/internal/utils/is-radio-item.js +0 -1
- package/dist/cjs/internal/utils/is-voice-over-supported.js +1 -4
- package/dist/cjs/internal/utils/reset-options-in-group.js +0 -6
- package/dist/cjs/internal/utils/use-generated-id.js +1 -5
- package/dist/cjs/radio/dropdown-item-radio-group.js +10 -31
- package/dist/cjs/radio/dropdown-item-radio.js +21 -43
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/checkbox/dropdown-item-checkbox-group.js +0 -2
- package/dist/es2019/checkbox/dropdown-item-checkbox.js +2 -6
- package/dist/es2019/dropdown-menu-item.js +0 -3
- package/dist/es2019/dropdown-menu.js +16 -17
- package/dist/es2019/internal/components/focus-manager.js +4 -4
- package/dist/es2019/internal/components/menu-wrapper.js +11 -14
- package/dist/es2019/internal/context/checkbox-group-context.js +1 -1
- package/dist/es2019/internal/context/selection-store.js +0 -5
- package/dist/es2019/internal/hooks/use-checkbox-state.js +9 -9
- package/dist/es2019/internal/hooks/use-radio-state.js +3 -7
- package/dist/es2019/internal/hooks/use-register-item-with-focus-manager.js +3 -3
- package/dist/es2019/internal/utils/get-icon-colors.js +0 -3
- package/dist/es2019/internal/utils/handle-focus.js +6 -20
- package/dist/es2019/internal/utils/is-voice-over-supported.js +1 -3
- package/dist/es2019/internal/utils/reset-options-in-group.js +2 -2
- package/dist/es2019/internal/utils/use-generated-id.js +3 -4
- package/dist/es2019/radio/dropdown-item-radio-group.js +4 -7
- package/dist/es2019/radio/dropdown-item-radio.js +2 -6
- package/dist/es2019/version.json +1 -1
- package/dist/esm/checkbox/dropdown-item-checkbox-group.js +1 -3
- package/dist/esm/checkbox/dropdown-item-checkbox.js +21 -27
- package/dist/esm/dropdown-menu-item.js +7 -11
- package/dist/esm/dropdown-menu.js +45 -56
- package/dist/esm/internal/components/focus-manager.js +4 -4
- package/dist/esm/internal/components/menu-wrapper.js +19 -23
- package/dist/esm/internal/context/checkbox-group-context.js +1 -1
- package/dist/esm/internal/context/selection-store.js +0 -5
- package/dist/esm/internal/hooks/use-checkbox-state.js +20 -24
- package/dist/esm/internal/hooks/use-radio-state.js +13 -26
- package/dist/esm/internal/hooks/use-register-item-with-focus-manager.js +4 -5
- package/dist/esm/internal/utils/get-icon-colors.js +0 -3
- package/dist/esm/internal/utils/handle-focus.js +6 -26
- package/dist/esm/internal/utils/is-voice-over-supported.js +1 -3
- package/dist/esm/internal/utils/reset-options-in-group.js +0 -4
- package/dist/esm/internal/utils/use-generated-id.js +1 -3
- package/dist/esm/radio/dropdown-item-radio-group.js +10 -20
- package/dist/esm/radio/dropdown-item-radio.js +21 -27
- package/dist/esm/version.json +1 -1
- package/package.json +4 -4
- package/report.api.md +14 -0
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
2
|
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
|
|
3
3
|
var _excluded = ["onClose", "onUpdate", "isLoading", "statusLabel", "setInitialFocusRef", "children"];
|
|
4
|
-
|
|
5
4
|
/** @jsx jsx */
|
|
6
5
|
import { useContext, useEffect, useLayoutEffect } from 'react';
|
|
7
6
|
import { css, jsx } from '@emotion/react';
|
|
@@ -14,14 +13,14 @@ import isRadioItem from '../utils/is-radio-item';
|
|
|
14
13
|
var spinnerContainerStyles = css({
|
|
15
14
|
display: 'flex',
|
|
16
15
|
minWidth: '160px',
|
|
17
|
-
padding: "var(--ds-
|
|
16
|
+
padding: "var(--ds-space-250, 20px)",
|
|
18
17
|
justifyContent: 'center'
|
|
19
18
|
});
|
|
20
|
-
|
|
21
19
|
var LoadingIndicator = function LoadingIndicator(_ref) {
|
|
22
20
|
var _ref$statusLabel = _ref.statusLabel,
|
|
23
|
-
|
|
24
|
-
return (
|
|
21
|
+
statusLabel = _ref$statusLabel === void 0 ? 'Loading' : _ref$statusLabel;
|
|
22
|
+
return (
|
|
23
|
+
// eslint-disable-next-line @repo/internal/react/use-primitives
|
|
25
24
|
jsx("div", {
|
|
26
25
|
css: spinnerContainerStyles
|
|
27
26
|
}, jsx(Spinner, {
|
|
@@ -38,44 +37,42 @@ var LoadingIndicator = function LoadingIndicator(_ref) {
|
|
|
38
37
|
* if a CheckboxItem or RadioItem is clicked.
|
|
39
38
|
* It also sets focus to the first menu item when opened.
|
|
40
39
|
*/
|
|
41
|
-
|
|
42
|
-
|
|
43
40
|
var MenuWrapper = function MenuWrapper(_ref2) {
|
|
44
41
|
var onClose = _ref2.onClose,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
42
|
+
onUpdate = _ref2.onUpdate,
|
|
43
|
+
isLoading = _ref2.isLoading,
|
|
44
|
+
statusLabel = _ref2.statusLabel,
|
|
45
|
+
setInitialFocusRef = _ref2.setInitialFocusRef,
|
|
46
|
+
children = _ref2.children,
|
|
47
|
+
props = _objectWithoutProperties(_ref2, _excluded);
|
|
52
48
|
var _useContext = useContext(FocusManagerContext),
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
menuItemRefs = _useContext.menuItemRefs;
|
|
55
50
|
var closeOnMenuItemClick = function closeOnMenuItemClick(e) {
|
|
56
51
|
var isTargetMenuItemOrDecendant = menuItemRefs.some(function (menuItem) {
|
|
57
52
|
var isCheckboxOrRadio = isCheckboxItem(menuItem) || isRadioItem(menuItem);
|
|
58
53
|
return menuItem.contains(e.target) && !isCheckboxOrRadio;
|
|
59
|
-
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Close menu if the click is triggered from a MenuItem or
|
|
60
57
|
// its descendant. Don't close the menu if the click is triggered
|
|
61
58
|
// from a MenuItemRadio or MenuItemCheckbox so that the user can
|
|
62
59
|
// select multiple items.
|
|
63
|
-
|
|
64
60
|
if (isTargetMenuItemOrDecendant && onClose) {
|
|
65
61
|
onClose(e);
|
|
66
62
|
}
|
|
67
|
-
};
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// Using useEffect here causes a flicker.
|
|
68
66
|
// useLayoutEffect ensures that the update and render happen in the same
|
|
69
67
|
// rAF tick.
|
|
70
|
-
|
|
71
|
-
|
|
72
68
|
useLayoutEffect(function () {
|
|
73
69
|
onUpdate();
|
|
74
70
|
}, [isLoading, onUpdate]);
|
|
75
71
|
useEffect(function () {
|
|
76
72
|
setInitialFocusRef === null || setInitialFocusRef === void 0 ? void 0 : setInitialFocusRef(menuItemRefs[0]);
|
|
77
73
|
}, [menuItemRefs, setInitialFocusRef]);
|
|
78
|
-
return (
|
|
74
|
+
return (
|
|
75
|
+
// eslint-disable-next-line @repo/internal/react/no-unsafe-spread-props
|
|
79
76
|
jsx(MenuGroup, _extends({
|
|
80
77
|
role: "menu",
|
|
81
78
|
onClick: closeOnMenuItemClick
|
|
@@ -84,5 +81,4 @@ var MenuWrapper = function MenuWrapper(_ref2) {
|
|
|
84
81
|
}) : children)
|
|
85
82
|
);
|
|
86
83
|
};
|
|
87
|
-
|
|
88
84
|
export default MenuWrapper;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React, { createContext, useMemo, useRef } from 'react';
|
|
2
2
|
import noop from '@atlaskit/ds-lib/noop';
|
|
3
|
-
|
|
4
3
|
/**
|
|
5
4
|
*
|
|
6
5
|
* SelectionStoreContext maintains the state of the selected items
|
|
@@ -17,7 +16,6 @@ export var SelectionStoreContext = /*#__PURE__*/createContext({
|
|
|
17
16
|
return {};
|
|
18
17
|
}
|
|
19
18
|
});
|
|
20
|
-
|
|
21
19
|
/**
|
|
22
20
|
* Selection store will persist data as long as it remains mounted.
|
|
23
21
|
* It handles the uncontrolled story for dropdown menu when the menu
|
|
@@ -32,14 +30,12 @@ var SelectionStore = function SelectionStore(props) {
|
|
|
32
30
|
if (!store.current[group]) {
|
|
33
31
|
store.current[group] = {};
|
|
34
32
|
}
|
|
35
|
-
|
|
36
33
|
store.current[group][id] = value;
|
|
37
34
|
},
|
|
38
35
|
getItemState: function getItemState(group, id) {
|
|
39
36
|
if (!store.current[group]) {
|
|
40
37
|
return undefined;
|
|
41
38
|
}
|
|
42
|
-
|
|
43
39
|
return store.current[group][id];
|
|
44
40
|
},
|
|
45
41
|
setGroupState: function setGroupState(group, value) {
|
|
@@ -54,5 +50,4 @@ var SelectionStore = function SelectionStore(props) {
|
|
|
54
50
|
value: context
|
|
55
51
|
}, children);
|
|
56
52
|
};
|
|
57
|
-
|
|
58
53
|
export default SelectionStore;
|
|
@@ -2,7 +2,6 @@ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
|
2
2
|
import { useCallback, useContext, useState } from 'react';
|
|
3
3
|
import { CheckboxGroupContext } from '../context/checkbox-group-context';
|
|
4
4
|
import { SelectionStoreContext } from '../context/selection-store';
|
|
5
|
-
|
|
6
5
|
/**
|
|
7
6
|
* Custom hook to handle checkbox state for dropdown menu.
|
|
8
7
|
* It works in tandem with the selection store context when the
|
|
@@ -10,46 +9,43 @@ import { SelectionStoreContext } from '../context/selection-store';
|
|
|
10
9
|
*/
|
|
11
10
|
var useCheckboxState = function useCheckboxState(_ref) {
|
|
12
11
|
var isSelected = _ref.isSelected,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
id = _ref.id,
|
|
13
|
+
defaultSelected = _ref.defaultSelected;
|
|
16
14
|
var _useContext = useContext(SelectionStoreContext),
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
setItemState = _useContext.setItemState,
|
|
16
|
+
getItemState = _useContext.getItemState;
|
|
20
17
|
var groupId = useContext(CheckboxGroupContext);
|
|
21
18
|
var persistedIsSelected = getItemState(groupId, id);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
19
|
+
var _useState = useState(
|
|
20
|
+
// Initial state is set depending on value being defined or not.
|
|
21
|
+
// This state is only utilised if the checkbox is uncontrolled.
|
|
22
|
+
function () {
|
|
23
|
+
return persistedIsSelected !== undefined ? persistedIsSelected : defaultSelected || false;
|
|
24
|
+
}),
|
|
25
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
26
|
+
localIsSelected = _useState2[0],
|
|
27
|
+
setLocalIsSelected = _useState2[1];
|
|
32
28
|
var setLocalState = useCallback(function (newValue) {
|
|
33
29
|
var nextValue = newValue(persistedIsSelected);
|
|
34
30
|
setLocalIsSelected(nextValue);
|
|
35
31
|
setItemState(groupId, id, nextValue);
|
|
36
|
-
}, [setItemState, persistedIsSelected, groupId, id]);
|
|
32
|
+
}, [setItemState, persistedIsSelected, groupId, id]);
|
|
37
33
|
|
|
34
|
+
// Checkbox is controlled - do nothing!
|
|
38
35
|
if (typeof isSelected === 'boolean') {
|
|
39
36
|
return [isSelected, function () {
|
|
40
37
|
return false;
|
|
41
38
|
}];
|
|
42
|
-
}
|
|
43
|
-
|
|
39
|
+
}
|
|
44
40
|
|
|
41
|
+
// Checkbox is going through its first render pass!
|
|
45
42
|
if (persistedIsSelected === undefined) {
|
|
46
43
|
// Set the item so we have this state to access next time the checkbox renders (either by mounting or re-rendering!)
|
|
47
44
|
setItemState(groupId, id, defaultSelected || false);
|
|
48
|
-
}
|
|
49
|
-
// Remember this flow is only returned if the checkbox is uncontrolled.
|
|
50
|
-
|
|
45
|
+
}
|
|
51
46
|
|
|
47
|
+
// Return the value and setter!
|
|
48
|
+
// Remember this flow is only returned if the checkbox is uncontrolled.
|
|
52
49
|
return [localIsSelected, setLocalState];
|
|
53
50
|
};
|
|
54
|
-
|
|
55
51
|
export default useCheckboxState;
|
|
@@ -1,38 +1,29 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
2
|
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
3
|
-
|
|
4
3
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
5
|
-
|
|
6
4
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
7
|
-
|
|
8
5
|
import { useCallback, useContext, useEffect, useState } from 'react';
|
|
9
6
|
import { RadioGroupContext } from '../../radio/dropdown-item-radio-group';
|
|
10
7
|
import { SelectionStoreContext } from '../context/selection-store';
|
|
11
8
|
import resetOptionsInGroup from '../utils/reset-options-in-group';
|
|
12
|
-
|
|
13
9
|
function useRadioState(_ref) {
|
|
14
10
|
var id = _ref.id,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
isSelected = _ref.isSelected,
|
|
12
|
+
defaultSelected = _ref.defaultSelected;
|
|
18
13
|
var _useContext = useContext(SelectionStoreContext),
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
setGroupState = _useContext.setGroupState,
|
|
15
|
+
getGroupState = _useContext.getGroupState;
|
|
22
16
|
var _useContext2 = useContext(RadioGroupContext),
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
17
|
+
group = _useContext2.id,
|
|
18
|
+
radioGroupState = _useContext2.radioGroupState,
|
|
19
|
+
selectRadioItem = _useContext2.selectRadioItem;
|
|
27
20
|
var persistedIsSelected = radioGroupState[id];
|
|
28
|
-
|
|
29
21
|
var _useState = useState(function () {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
22
|
+
return persistedIsSelected !== undefined ? persistedIsSelected : defaultSelected || false;
|
|
23
|
+
}),
|
|
24
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
25
|
+
localIsSelected = _useState2[0],
|
|
26
|
+
setLocalIsSelected = _useState2[1];
|
|
36
27
|
var setLocalState = useCallback(function (newValue) {
|
|
37
28
|
if (!persistedIsSelected) {
|
|
38
29
|
var nextValue = newValue(persistedIsSelected);
|
|
@@ -40,31 +31,27 @@ function useRadioState(_ref) {
|
|
|
40
31
|
setLocalIsSelected(nextValue);
|
|
41
32
|
}
|
|
42
33
|
}, [persistedIsSelected, id, selectRadioItem]);
|
|
34
|
+
|
|
43
35
|
/**
|
|
44
36
|
* - radio state changes any time a radio child is changed
|
|
45
37
|
* - when it changes we want all radio buttons to update their local state
|
|
46
38
|
* - it takes the value from radio group state and applies it locally if it exists which it will only exist, if it is selected
|
|
47
39
|
*/
|
|
48
|
-
|
|
49
40
|
useEffect(function () {
|
|
50
41
|
setLocalIsSelected(function () {
|
|
51
42
|
var existing = radioGroupState[id];
|
|
52
43
|
return existing !== undefined ? existing : defaultSelected || false;
|
|
53
44
|
});
|
|
54
45
|
}, [radioGroupState, group, id, defaultSelected]);
|
|
55
|
-
|
|
56
46
|
if (typeof isSelected === 'boolean') {
|
|
57
47
|
return [isSelected, function () {
|
|
58
48
|
return false;
|
|
59
49
|
}];
|
|
60
50
|
}
|
|
61
|
-
|
|
62
51
|
if (persistedIsSelected === undefined) {
|
|
63
52
|
var existing = getGroupState(group);
|
|
64
53
|
setGroupState(group, _objectSpread(_objectSpread({}, resetOptionsInGroup(existing || {})), {}, _defineProperty({}, id, defaultSelected || false)));
|
|
65
54
|
}
|
|
66
|
-
|
|
67
55
|
return [localIsSelected, setLocalState];
|
|
68
56
|
}
|
|
69
|
-
|
|
70
57
|
export default useRadioState;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { useContext, useEffect, useRef } from 'react';
|
|
2
|
-
import { FocusManagerContext } from '../components/focus-manager';
|
|
2
|
+
import { FocusManagerContext } from '../components/focus-manager';
|
|
3
|
+
|
|
4
|
+
// This function is called whenever a MenuItem mounts.
|
|
3
5
|
// The refs stored in the context are used to programatically
|
|
4
6
|
// control focus on a user navigates using the keyboard.
|
|
5
|
-
|
|
6
7
|
function useRegisterItemWithFocusManager() {
|
|
7
8
|
var _useContext = useContext(FocusManagerContext),
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
registerRef = _useContext.registerRef;
|
|
10
10
|
var itemRef = useRef(null);
|
|
11
11
|
useEffect(function () {
|
|
12
12
|
if (itemRef.current !== null) {
|
|
@@ -15,5 +15,4 @@ function useRegisterItemWithFocusManager() {
|
|
|
15
15
|
}, [registerRef]);
|
|
16
16
|
return itemRef;
|
|
17
17
|
}
|
|
18
|
-
|
|
19
18
|
export default useRegisterItemWithFocusManager;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { B400, N40 } from '@atlaskit/theme/colors';
|
|
2
|
-
|
|
3
2
|
var getIconColors = function getIconColors(isSelected) {
|
|
4
3
|
if (isSelected) {
|
|
5
4
|
return {
|
|
@@ -7,11 +6,9 @@ var getIconColors = function getIconColors(isSelected) {
|
|
|
7
6
|
secondary: "var(--ds-icon-inverse, ".concat(N40, ")")
|
|
8
7
|
};
|
|
9
8
|
}
|
|
10
|
-
|
|
11
9
|
return {
|
|
12
10
|
primary: "var(--ds-background-neutral, ".concat(N40, ")"),
|
|
13
11
|
secondary: "var(--ds-UNSAFE_util-transparent, ".concat(N40, ")")
|
|
14
12
|
};
|
|
15
13
|
};
|
|
16
|
-
|
|
17
14
|
export default getIconColors;
|
|
@@ -1,93 +1,73 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
-
|
|
3
2
|
var _actionMap;
|
|
4
|
-
|
|
5
3
|
import { KEY_DOWN, KEY_END, KEY_HOME, KEY_UP } from '@atlaskit/ds-lib/keycodes';
|
|
6
4
|
var actionMap = (_actionMap = {}, _defineProperty(_actionMap, KEY_DOWN, 'next'), _defineProperty(_actionMap, KEY_UP, 'prev'), _defineProperty(_actionMap, KEY_HOME, 'first'), _defineProperty(_actionMap, KEY_END, 'last'), _actionMap);
|
|
5
|
+
|
|
7
6
|
/**
|
|
8
7
|
* currentFocusedIdx + 1 will not work if the next focusable element
|
|
9
8
|
* is disabled. So, we need to iterate through the following menu items
|
|
10
9
|
* to find one that isn't disabled. If all following elements are disabled,
|
|
11
10
|
* return undefined.
|
|
12
11
|
*/
|
|
13
|
-
|
|
14
12
|
var getNextFocusableElement = function getNextFocusableElement(refs, currentFocusedIdx) {
|
|
15
13
|
while (currentFocusedIdx + 1 < refs.length) {
|
|
16
14
|
var isDisabled = refs[currentFocusedIdx + 1].getAttribute('disabled') !== null;
|
|
17
|
-
|
|
18
15
|
if (!isDisabled) {
|
|
19
16
|
return refs[currentFocusedIdx + 1];
|
|
20
17
|
}
|
|
21
|
-
|
|
22
18
|
currentFocusedIdx++;
|
|
23
19
|
}
|
|
24
20
|
};
|
|
21
|
+
|
|
25
22
|
/**
|
|
26
23
|
* currentFocusedIdx - 1 will not work if the prev focusable element
|
|
27
24
|
* is disabled. So, we need to iterate through the previous menu items
|
|
28
25
|
* to find one that isn't disabled. If all previous elements are disabled,
|
|
29
26
|
* return undefined.
|
|
30
27
|
*/
|
|
31
|
-
|
|
32
|
-
|
|
33
28
|
var getPrevFocusableElement = function getPrevFocusableElement(refs, currentFocusedIdx) {
|
|
34
29
|
while (currentFocusedIdx > 0) {
|
|
35
30
|
var isDisabled = refs[currentFocusedIdx - 1].getAttribute('disabled') !== null;
|
|
36
|
-
|
|
37
31
|
if (!isDisabled) {
|
|
38
32
|
return refs[currentFocusedIdx - 1];
|
|
39
33
|
}
|
|
40
|
-
|
|
41
34
|
currentFocusedIdx--;
|
|
42
35
|
}
|
|
43
36
|
};
|
|
44
|
-
|
|
45
37
|
export default function handleFocus(refs) {
|
|
46
38
|
return function (e) {
|
|
47
39
|
var currentFocusedIdx = refs.findIndex(function (el) {
|
|
48
40
|
var _document$activeEleme;
|
|
49
|
-
|
|
50
41
|
return (_document$activeEleme = document.activeElement) === null || _document$activeEleme === void 0 ? void 0 : _document$activeEleme.isSameNode(el);
|
|
51
42
|
});
|
|
52
43
|
var action = actionMap[e.key];
|
|
53
|
-
|
|
54
44
|
switch (action) {
|
|
55
45
|
case 'next':
|
|
56
46
|
if (currentFocusedIdx < refs.length - 1) {
|
|
57
47
|
e.preventDefault();
|
|
58
|
-
|
|
59
48
|
var _nextFocusableElement = getNextFocusableElement(refs, currentFocusedIdx);
|
|
60
|
-
|
|
61
49
|
_nextFocusableElement && _nextFocusableElement.focus();
|
|
62
50
|
}
|
|
63
|
-
|
|
64
51
|
break;
|
|
65
|
-
|
|
66
52
|
case 'prev':
|
|
67
53
|
if (currentFocusedIdx > 0) {
|
|
68
54
|
e.preventDefault();
|
|
69
|
-
|
|
70
55
|
var _prevFocusableElement = getPrevFocusableElement(refs, currentFocusedIdx);
|
|
71
|
-
|
|
72
56
|
_prevFocusableElement && _prevFocusableElement.focus();
|
|
73
57
|
}
|
|
74
|
-
|
|
75
58
|
break;
|
|
76
|
-
|
|
77
59
|
case 'first':
|
|
78
|
-
e.preventDefault();
|
|
79
|
-
|
|
60
|
+
e.preventDefault();
|
|
61
|
+
// Search for first non-disabled element if first element is disabled
|
|
80
62
|
var nextFocusableElement = getNextFocusableElement(refs, -1);
|
|
81
63
|
nextFocusableElement && nextFocusableElement.focus();
|
|
82
64
|
break;
|
|
83
|
-
|
|
84
65
|
case 'last':
|
|
85
|
-
e.preventDefault();
|
|
86
|
-
|
|
66
|
+
e.preventDefault();
|
|
67
|
+
// Search for last non-disabled element if last element is disabled
|
|
87
68
|
var prevFocusableElement = getPrevFocusableElement(refs, refs.length);
|
|
88
69
|
prevFocusableElement && prevFocusableElement.focus();
|
|
89
70
|
break;
|
|
90
|
-
|
|
91
71
|
default:
|
|
92
72
|
return;
|
|
93
73
|
}
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
var canUseDOM = function canUseDOM() {
|
|
2
2
|
return Boolean(typeof window !== 'undefined' && window.document && window.document.createElement);
|
|
3
3
|
};
|
|
4
|
+
|
|
4
5
|
/*
|
|
5
6
|
* Making sure we can fallback to browsers doesn't support voice over -
|
|
6
7
|
* we would using menuitemcheckbox / menuitemradio for these that supports voice over, and
|
|
7
8
|
* will fallback to checkbox / radio for these doesn't
|
|
8
9
|
*/
|
|
9
|
-
|
|
10
|
-
|
|
11
10
|
var isVoiceOverSupported = function isVoiceOverSupported() {
|
|
12
11
|
return /Mac OS X/.test(canUseDOM() ? navigator.userAgent : '');
|
|
13
12
|
};
|
|
14
|
-
|
|
15
13
|
export default isVoiceOverSupported;
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
-
|
|
3
2
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
4
|
-
|
|
5
3
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
6
|
-
|
|
7
4
|
var resetOptionsInGroup = function resetOptionsInGroup(group) {
|
|
8
5
|
return Object.keys(group || {}).reduce(function (accumulator, current) {
|
|
9
6
|
return _objectSpread(_objectSpread({}, accumulator), {}, _defineProperty({}, current, typeof group[current] === 'undefined' ? undefined : false));
|
|
10
7
|
}, {});
|
|
11
8
|
};
|
|
12
|
-
|
|
13
9
|
export default resetOptionsInGroup;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { useRef } from 'react';
|
|
2
2
|
var PREFIX = 'ds--dropdown--';
|
|
3
|
-
|
|
4
3
|
var generateRandomString = function generateRandomString() {
|
|
5
4
|
return (// This string is used only on client side usually triggered after a user interaction.
|
|
6
5
|
// Therefore, so there is no risk of mismatch
|
|
@@ -9,12 +8,11 @@ var generateRandomString = function generateRandomString() {
|
|
|
9
8
|
"".concat(PREFIX).concat(Math.random().toString(16).substr(2, 8))
|
|
10
9
|
);
|
|
11
10
|
};
|
|
11
|
+
|
|
12
12
|
/**
|
|
13
13
|
* useGeneratedId generates a random string which remains constant across
|
|
14
14
|
* renders when called without any parameter.
|
|
15
15
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
16
|
export default function useGeneratedId() {
|
|
19
17
|
var cachedId = useRef(generateRandomString());
|
|
20
18
|
return cachedId.current;
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
2
|
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
3
|
-
|
|
4
3
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
5
|
-
|
|
6
4
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
7
|
-
|
|
8
5
|
import React, { createContext, useContext, useState } from 'react';
|
|
9
6
|
import noop from '@atlaskit/ds-lib/noop';
|
|
10
7
|
import Section from '@atlaskit/menu/section';
|
|
11
8
|
import { SelectionStoreContext } from '../internal/context/selection-store';
|
|
12
9
|
import resetOptionsInGroup from '../internal/utils/reset-options-in-group';
|
|
13
|
-
|
|
14
10
|
/**
|
|
15
11
|
* __Radio group context__
|
|
16
12
|
* Context provider that wraps each DropdownItemRadioGroup
|
|
@@ -20,40 +16,35 @@ export var RadioGroupContext = /*#__PURE__*/createContext({
|
|
|
20
16
|
radioGroupState: {},
|
|
21
17
|
selectRadioItem: noop
|
|
22
18
|
});
|
|
19
|
+
|
|
23
20
|
/**
|
|
24
21
|
* __Dropdown item radio group__
|
|
25
22
|
* Store which manages the selection state for each DropdownItemRadio
|
|
26
23
|
* across mount and unmounts.
|
|
27
24
|
*
|
|
28
25
|
*/
|
|
29
|
-
|
|
30
26
|
var DropdownItemRadioGroup = function DropdownItemRadioGroup(props) {
|
|
31
27
|
var children = props.children,
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
id = props.id;
|
|
34
29
|
var _useContext = useContext(SelectionStoreContext),
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
setGroupState = _useContext.setGroupState,
|
|
31
|
+
getGroupState = _useContext.getGroupState;
|
|
32
|
+
|
|
37
33
|
/**
|
|
38
34
|
* - initially `radioGroupState` is from selection store, so it's safe to update without re-rendering
|
|
39
35
|
* - we flush a render by updating this local radio group state
|
|
40
36
|
*/
|
|
41
|
-
|
|
42
|
-
|
|
43
37
|
var _useState = useState(function () {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
38
|
+
return getGroupState(id);
|
|
39
|
+
}),
|
|
40
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
41
|
+
radioGroupState = _useState2[0],
|
|
42
|
+
setRadioGroupState = _useState2[1];
|
|
50
43
|
var selectRadioItem = function selectRadioItem(childId, value) {
|
|
51
44
|
var newValue = _objectSpread(_objectSpread({}, resetOptionsInGroup(getGroupState(id))), {}, _defineProperty({}, childId, value));
|
|
52
|
-
|
|
53
45
|
setRadioGroupState(newValue);
|
|
54
46
|
setGroupState(id, newValue);
|
|
55
47
|
};
|
|
56
|
-
|
|
57
48
|
return /*#__PURE__*/React.createElement(RadioGroupContext.Provider, {
|
|
58
49
|
value: {
|
|
59
50
|
id: id,
|
|
@@ -62,5 +53,4 @@ var DropdownItemRadioGroup = function DropdownItemRadioGroup(props) {
|
|
|
62
53
|
}
|
|
63
54
|
}, /*#__PURE__*/React.createElement(Section, props, children));
|
|
64
55
|
};
|
|
65
|
-
|
|
66
56
|
export default DropdownItemRadioGroup;
|
|
@@ -10,7 +10,6 @@ import useRadioState from '../internal/hooks/use-radio-state';
|
|
|
10
10
|
import useRegisterItemWithFocusManager from '../internal/hooks/use-register-item-with-focus-manager';
|
|
11
11
|
import getIconColors from '../internal/utils/get-icon-colors';
|
|
12
12
|
import isVoiceOverSupported from '../internal/utils/is-voice-over-supported';
|
|
13
|
-
|
|
14
13
|
/**
|
|
15
14
|
* __Dropdown item radio__
|
|
16
15
|
*
|
|
@@ -22,35 +21,31 @@ import isVoiceOverSupported from '../internal/utils/is-voice-over-supported';
|
|
|
22
21
|
*/
|
|
23
22
|
var DropdownItemRadio = function DropdownItemRadio(props) {
|
|
24
23
|
var id = props.id,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
24
|
+
isSelected = props.isSelected,
|
|
25
|
+
defaultSelected = props.defaultSelected,
|
|
26
|
+
_props$onClick = props.onClick,
|
|
27
|
+
providedOnClick = _props$onClick === void 0 ? noop : _props$onClick,
|
|
28
|
+
_props$shouldTitleWra = props.shouldTitleWrap,
|
|
29
|
+
shouldTitleWrap = _props$shouldTitleWra === void 0 ? true : _props$shouldTitleWra,
|
|
30
|
+
_props$shouldDescript = props.shouldDescriptionWrap,
|
|
31
|
+
shouldDescriptionWrap = _props$shouldDescript === void 0 ? true : _props$shouldDescript,
|
|
32
|
+
rest = _objectWithoutProperties(props, _excluded);
|
|
35
33
|
if (process.env.NODE_ENV !== 'production' && typeof isSelected !== 'undefined' && typeof defaultSelected !== 'undefined') {
|
|
36
34
|
// eslint-disable-next-line no-console
|
|
37
35
|
console.warn("[DropdownItemRadio] You've used both `defaultSelected` and `isSelected` props. This is dangerous and can lead to unexpected results. Use one or the other depending if you want to control the components state yourself.");
|
|
38
36
|
}
|
|
39
|
-
|
|
40
37
|
var _useRadioState = useRadioState({
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
38
|
+
id: id,
|
|
39
|
+
isSelected: isSelected,
|
|
40
|
+
defaultSelected: defaultSelected
|
|
41
|
+
}),
|
|
42
|
+
_useRadioState2 = _slicedToArray(_useRadioState, 2),
|
|
43
|
+
selected = _useRadioState2[0],
|
|
44
|
+
setSelected = _useRadioState2[1];
|
|
49
45
|
var _useState = useState(getIconColors(defaultSelected)),
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
46
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
47
|
+
iconColors = _useState2[0],
|
|
48
|
+
setIconColors = _useState2[1];
|
|
54
49
|
var onClickHandler = useCallback(function (event) {
|
|
55
50
|
setSelected(function (selected) {
|
|
56
51
|
return !selected;
|
|
@@ -74,9 +69,8 @@ var DropdownItemRadio = function DropdownItemRadio(props) {
|
|
|
74
69
|
primaryColor: iconColors.primary,
|
|
75
70
|
secondaryColor: iconColors.secondary
|
|
76
71
|
}),
|
|
77
|
-
ref: itemRef
|
|
78
|
-
|
|
72
|
+
ref: itemRef
|
|
73
|
+
// eslint-disable-next-line @repo/internal/react/no-unsafe-spread-props
|
|
79
74
|
}, rest));
|
|
80
75
|
};
|
|
81
|
-
|
|
82
76
|
export default DropdownItemRadio;
|
package/dist/esm/version.json
CHANGED