@atlaskit/react-select 2.6.6 → 2.7.1
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 +15 -0
- package/dist/cjs/accessibility/index.js +3 -49
- package/dist/cjs/compiled/components/indicators.js +6 -4
- package/dist/cjs/compiled/components/live-region.js +8 -72
- package/dist/cjs/compiled/components/multi-value.js +4 -3
- package/dist/cjs/emotion/components/indicators.js +6 -4
- package/dist/cjs/emotion/components/live-region.js +10 -76
- package/dist/cjs/emotion/components/multi-value.js +4 -3
- package/dist/cjs/select.js +141 -99
- package/dist/es2019/accessibility/index.js +3 -50
- package/dist/es2019/compiled/components/indicators.js +6 -4
- package/dist/es2019/compiled/components/live-region.js +7 -71
- package/dist/es2019/compiled/components/multi-value.js +3 -2
- package/dist/es2019/emotion/components/indicators.js +6 -4
- package/dist/es2019/emotion/components/live-region.js +7 -72
- package/dist/es2019/emotion/components/multi-value.js +3 -2
- package/dist/es2019/select.js +117 -82
- package/dist/esm/accessibility/index.js +3 -49
- package/dist/esm/compiled/components/indicators.js +6 -4
- package/dist/esm/compiled/components/live-region.js +9 -73
- package/dist/esm/compiled/components/multi-value.js +3 -2
- package/dist/esm/emotion/components/indicators.js +6 -4
- package/dist/esm/emotion/components/live-region.js +9 -74
- package/dist/esm/emotion/components/multi-value.js +3 -2
- package/dist/esm/select.js +139 -98
- package/dist/types/accessibility/index.d.ts +0 -2
- package/dist/types/compiled/components/live-region.d.ts +0 -2
- package/dist/types/emotion/components/live-region.d.ts +0 -2
- package/dist/types/select.d.ts +5 -6
- package/dist/types-ts4.5/accessibility/index.d.ts +0 -2
- package/dist/types-ts4.5/compiled/components/live-region.d.ts +0 -2
- package/dist/types-ts4.5/emotion/components/live-region.d.ts +0 -2
- package/dist/types-ts4.5/select.d.ts +5 -6
- package/package.json +2 -5
package/dist/es2019/select.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
2
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
3
|
-
/* eslint-disable @atlaskit/platform/ensure-feature-flag-prefix */
|
|
4
3
|
import React, { Component } from 'react';
|
|
5
|
-
import { isAppleDevice } from '@atlaskit/ds-lib/device-check';
|
|
4
|
+
import { isAppleDevice, isSafari } from '@atlaskit/ds-lib/device-check';
|
|
6
5
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
7
6
|
import { formatGroupLabel as formatGroupLabelBuiltin, getOptionLabel as getOptionLabelBuiltin, getOptionValue as getOptionValueBuiltin, isOptionDisabled as isOptionDisabledBuiltin } from './builtins';
|
|
8
7
|
import { defaultComponents } from './components';
|
|
@@ -14,9 +13,6 @@ import { createFilter } from './filters';
|
|
|
14
13
|
import { defaultStyles } from './styles';
|
|
15
14
|
import { classNames, cleanValue, filterUnsupportedSelectors, isDocumentElement, isMobileDevice, isTouchCapable, multiValueAsValue, noop, notNullish, scrollIntoView, singleValueAsValue, valueTernary } from './utils';
|
|
16
15
|
export const defaultProps = {
|
|
17
|
-
// aria-live is by default with the live region so we don't need it
|
|
18
|
-
// eslint-disable-next-line @atlaskit/platform/no-module-level-eval
|
|
19
|
-
'aria-live': fg('design_system_select-a11y-improvement') ? undefined : 'polite',
|
|
20
16
|
backspaceRemovesValue: true,
|
|
21
17
|
blurInputOnSelect: isTouchCapable(),
|
|
22
18
|
captureMenuScroll: !isTouchCapable(),
|
|
@@ -230,7 +226,6 @@ export default class Select extends Component {
|
|
|
230
226
|
_defineProperty(this, "initialTouchY", 0);
|
|
231
227
|
_defineProperty(this, "openAfterFocus", false);
|
|
232
228
|
_defineProperty(this, "scrollToFocusedOptionOnUpdate", false);
|
|
233
|
-
_defineProperty(this, "isVoiceOver", fg('design_system_select-a11y-improvement') && isAppleDevice());
|
|
234
229
|
// Refs
|
|
235
230
|
// ------------------------------
|
|
236
231
|
_defineProperty(this, "controlRef", null);
|
|
@@ -992,15 +987,62 @@ export default class Select extends Component {
|
|
|
992
987
|
openAtIndex = selectedIndex;
|
|
993
988
|
}
|
|
994
989
|
}
|
|
990
|
+
const focusedOption = focusableOptions[openAtIndex];
|
|
995
991
|
|
|
996
992
|
// only scroll if the menu isn't already open
|
|
997
993
|
this.scrollToFocusedOptionOnUpdate = !(isFocused && this.menuListRef);
|
|
998
994
|
this.setState({
|
|
999
995
|
inputIsHiddenAfterUpdate: false,
|
|
1000
996
|
focusedValue: null,
|
|
1001
|
-
focusedOption:
|
|
1002
|
-
focusedOptionId: this.getFocusedOptionId(
|
|
997
|
+
focusedOption: focusedOption,
|
|
998
|
+
focusedOptionId: this.getFocusedOptionId(focusedOption)
|
|
1003
999
|
}, () => this.onMenuOpen());
|
|
1000
|
+
isSafari() && focusedOption && this.updateInputLabel(this.calculateInputLabel(focusedOption, openAtIndex));
|
|
1001
|
+
}
|
|
1002
|
+
updateInputLabel(inputLabel) {
|
|
1003
|
+
if (inputLabel) {
|
|
1004
|
+
var _this$inputRef;
|
|
1005
|
+
(_this$inputRef = this.inputRef) === null || _this$inputRef === void 0 ? void 0 : _this$inputRef.setAttribute('aria-label', inputLabel);
|
|
1006
|
+
setTimeout(() => {
|
|
1007
|
+
const normalizedLabel = this.props['aria-label'] || this.props.label;
|
|
1008
|
+
if (normalizedLabel) {
|
|
1009
|
+
var _this$inputRef2;
|
|
1010
|
+
(_this$inputRef2 = this.inputRef) === null || _this$inputRef2 === void 0 ? void 0 : _this$inputRef2.setAttribute('aria-label', normalizedLabel);
|
|
1011
|
+
} else {
|
|
1012
|
+
var _this$inputRef3;
|
|
1013
|
+
(_this$inputRef3 = this.inputRef) === null || _this$inputRef3 === void 0 ? void 0 : _this$inputRef3.removeAttribute('aria-label');
|
|
1014
|
+
}
|
|
1015
|
+
}, 500);
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
calculateInputLabel(focusedOption, optionIndex) {
|
|
1019
|
+
const {
|
|
1020
|
+
options
|
|
1021
|
+
} = this.props;
|
|
1022
|
+
const isOptionsGrouped = options === null || options === void 0 ? void 0 : options.every(obj => typeof obj === 'object' && obj !== null && 'options' in obj);
|
|
1023
|
+
let inputLabel = this.getOptionLabel(focusedOption);
|
|
1024
|
+
const isOptionFocused = option => {
|
|
1025
|
+
return this.getOptionLabel(option) === inputLabel;
|
|
1026
|
+
};
|
|
1027
|
+
const groupData = options === null || options === void 0 ? void 0 : options.find(option => {
|
|
1028
|
+
var _groupCandidate$optio, _groupCandidate$optio2;
|
|
1029
|
+
const groupCandidate = option;
|
|
1030
|
+
return (_groupCandidate$optio = (_groupCandidate$optio2 = groupCandidate.options) === null || _groupCandidate$optio2 === void 0 ? void 0 : _groupCandidate$optio2.some(isOptionFocused)) !== null && _groupCandidate$optio !== void 0 ? _groupCandidate$optio : false;
|
|
1031
|
+
});
|
|
1032
|
+
if (isOptionsGrouped) {
|
|
1033
|
+
var _groupData$options$fi;
|
|
1034
|
+
const groupOptionIndex = (_groupData$options$fi = groupData === null || groupData === void 0 ? void 0 : groupData.options.findIndex(isOptionFocused)) !== null && _groupData$options$fi !== void 0 ? _groupData$options$fi : 0;
|
|
1035
|
+
const totalLength = options === null || options === void 0 ? void 0 : options.reduce((acc, currentGroup) => {
|
|
1036
|
+
var _group$options;
|
|
1037
|
+
const group = currentGroup;
|
|
1038
|
+
acc += group === null || group === void 0 ? void 0 : (_group$options = group.options) === null || _group$options === void 0 ? void 0 : _group$options.length;
|
|
1039
|
+
return acc;
|
|
1040
|
+
}, 0);
|
|
1041
|
+
inputLabel = `${inputLabel}, ${groupData === null || groupData === void 0 ? void 0 : groupData.label} (${groupOptionIndex + 1} of ${totalLength})`;
|
|
1042
|
+
} else {
|
|
1043
|
+
inputLabel = `${inputLabel} (${optionIndex + 1} of ${options === null || options === void 0 ? void 0 : options.length})`;
|
|
1044
|
+
}
|
|
1045
|
+
return inputLabel;
|
|
1004
1046
|
}
|
|
1005
1047
|
focusValue(direction) {
|
|
1006
1048
|
const {
|
|
@@ -1174,28 +1216,38 @@ export default class Select extends Component {
|
|
|
1174
1216
|
formatGroupLabel(data) {
|
|
1175
1217
|
return this.props.formatGroupLabel(data);
|
|
1176
1218
|
}
|
|
1177
|
-
calculateDescription(
|
|
1178
|
-
const descriptionProp = this.props['aria-describedby'] || this.props
|
|
1219
|
+
calculateDescription() {
|
|
1220
|
+
const descriptionProp = this.props['aria-describedby'] || this.props.descriptionId;
|
|
1179
1221
|
const {
|
|
1180
1222
|
isMulti
|
|
1181
1223
|
} = this.props;
|
|
1182
|
-
const
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
const
|
|
1186
|
-
|
|
1187
|
-
|
|
1224
|
+
const hasValue = this.state.selectValue.length > 0;
|
|
1225
|
+
|
|
1226
|
+
// Determine base description based on selection state
|
|
1227
|
+
const baseDescriptionId = hasValue ? isMulti ? '' : this.getElementId('single-value') : this.getElementId('placeholder');
|
|
1228
|
+
|
|
1229
|
+
// Fast path for single select with no description prop
|
|
1230
|
+
if (!isMulti && !descriptionProp) {
|
|
1231
|
+
return {
|
|
1232
|
+
'aria-describedby': baseDescriptionId
|
|
1233
|
+
};
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
// Build the describedby string efficiently
|
|
1237
|
+
let describedBy = baseDescriptionId;
|
|
1238
|
+
// Add description prop if it exists
|
|
1239
|
+
if (descriptionProp) {
|
|
1240
|
+
describedBy = describedBy ? `${descriptionProp} ${describedBy}` : descriptionProp;
|
|
1188
1241
|
}
|
|
1242
|
+
|
|
1243
|
+
// For multi-select, always add multi-message ID
|
|
1189
1244
|
if (isMulti) {
|
|
1190
1245
|
const multiMessage = this.getElementId('multi-message');
|
|
1191
|
-
|
|
1192
|
-
'aria-describedby': descriptionProp ? [descriptionProp, defaultDescription, multiMessage].join(' ') : [defaultDescription, multiMessage].join(' ')
|
|
1193
|
-
};
|
|
1194
|
-
} else {
|
|
1195
|
-
return {
|
|
1196
|
-
'aria-describedby': descriptionProp ? [descriptionProp, defaultDescription].join(' ') : defaultDescription
|
|
1197
|
-
};
|
|
1246
|
+
describedBy = describedBy ? `${describedBy} ${multiMessage}` : multiMessage;
|
|
1198
1247
|
}
|
|
1248
|
+
return {
|
|
1249
|
+
'aria-describedby': describedBy
|
|
1250
|
+
};
|
|
1199
1251
|
}
|
|
1200
1252
|
// ==============================
|
|
1201
1253
|
// Composition Handlers
|
|
@@ -1246,7 +1298,6 @@ export default class Select extends Component {
|
|
|
1246
1298
|
// ==============================
|
|
1247
1299
|
renderInput() {
|
|
1248
1300
|
const {
|
|
1249
|
-
descriptionId,
|
|
1250
1301
|
form,
|
|
1251
1302
|
inputId,
|
|
1252
1303
|
inputValue,
|
|
@@ -1265,8 +1316,7 @@ export default class Select extends Component {
|
|
|
1265
1316
|
Input
|
|
1266
1317
|
} = this.getComponents();
|
|
1267
1318
|
const {
|
|
1268
|
-
inputIsHidden
|
|
1269
|
-
ariaSelection
|
|
1319
|
+
inputIsHidden
|
|
1270
1320
|
} = this.state;
|
|
1271
1321
|
const {
|
|
1272
1322
|
commonProps
|
|
@@ -1280,7 +1330,6 @@ export default class Select extends Component {
|
|
|
1280
1330
|
'aria-expanded': menuIsOpen,
|
|
1281
1331
|
// TODO: aria-haspopup is implied as listbox with role="combobox" and was deprecated for aria 1.2, we still might need to keep it for back compat
|
|
1282
1332
|
'aria-haspopup': this.props['UNSAFE_is_experimental_generic'] ? 'dialog' : 'listbox',
|
|
1283
|
-
'aria-describedby': this.props['aria-describedby'] || descriptionId,
|
|
1284
1333
|
'aria-invalid': this.props['aria-invalid'] || isInvalid,
|
|
1285
1334
|
'aria-label': this.props['aria-label'] || label,
|
|
1286
1335
|
'aria-labelledby': this.props['aria-labelledby'] || labelId,
|
|
@@ -1294,7 +1343,7 @@ export default class Select extends Component {
|
|
|
1294
1343
|
...(!isSearchable && {
|
|
1295
1344
|
'aria-readonly': true
|
|
1296
1345
|
}),
|
|
1297
|
-
...this.calculateDescription(
|
|
1346
|
+
...this.calculateDescription()
|
|
1298
1347
|
};
|
|
1299
1348
|
if (!isSearchable) {
|
|
1300
1349
|
// use a dummy input to maintain focus/blur functionality
|
|
@@ -1410,7 +1459,10 @@ export default class Select extends Component {
|
|
|
1410
1459
|
const singleValue = selectValue[0];
|
|
1411
1460
|
return /*#__PURE__*/React.createElement(SingleValue, _extends({}, commonProps, {
|
|
1412
1461
|
data: singleValue,
|
|
1413
|
-
isDisabled: isDisabled
|
|
1462
|
+
isDisabled: isDisabled,
|
|
1463
|
+
innerProps: {
|
|
1464
|
+
id: this.getElementId('single-value')
|
|
1465
|
+
}
|
|
1414
1466
|
}), this.formatOptionLabel(singleValue, 'value'));
|
|
1415
1467
|
}
|
|
1416
1468
|
renderClearIndicator() {
|
|
@@ -1548,8 +1600,6 @@ export default class Select extends Component {
|
|
|
1548
1600
|
noOptionsMessage,
|
|
1549
1601
|
onMenuScrollToTop,
|
|
1550
1602
|
onMenuScrollToBottom,
|
|
1551
|
-
labelId,
|
|
1552
|
-
label,
|
|
1553
1603
|
testId
|
|
1554
1604
|
} = this.props;
|
|
1555
1605
|
if (!menuIsOpen) {
|
|
@@ -1578,8 +1628,8 @@ export default class Select extends Component {
|
|
|
1578
1628
|
role: this.props['UNSAFE_is_experimental_generic'] ? 'listitem' : 'option',
|
|
1579
1629
|
'aria-selected': this.props['UNSAFE_is_experimental_generic'] ? undefined : isSelected,
|
|
1580
1630
|
// We don't want aria-disabled if it's false. It's just noisy.
|
|
1581
|
-
'aria-disabled': !isDisabled
|
|
1582
|
-
'aria-describedby':
|
|
1631
|
+
'aria-disabled': !isDisabled ? undefined : isDisabled,
|
|
1632
|
+
'aria-describedby': headingId,
|
|
1583
1633
|
...(testId && {
|
|
1584
1634
|
'data-testid': `${testId}-select--option-${id}`
|
|
1585
1635
|
})
|
|
@@ -1657,26 +1707,6 @@ export default class Select extends Component {
|
|
|
1657
1707
|
menuPosition,
|
|
1658
1708
|
menuShouldScrollIntoView
|
|
1659
1709
|
};
|
|
1660
|
-
const calculateListboxLabel = () => {
|
|
1661
|
-
var _this$inputRef;
|
|
1662
|
-
// First in name calculation, overwrites aria-label
|
|
1663
|
-
if (labelId) {
|
|
1664
|
-
return {
|
|
1665
|
-
'aria-labelledby': labelId
|
|
1666
|
-
};
|
|
1667
|
-
}
|
|
1668
|
-
// Second in name calcuation, overwrites everything else except aria-labelledby
|
|
1669
|
-
if (label) {
|
|
1670
|
-
return {
|
|
1671
|
-
'aria-label': label
|
|
1672
|
-
};
|
|
1673
|
-
}
|
|
1674
|
-
// Fallback if no label or labelId is provided, might catch label via <label for> otherwise
|
|
1675
|
-
// will most likely not have an accessible name
|
|
1676
|
-
return {
|
|
1677
|
-
'aria-labelledby': ((_this$inputRef = this.inputRef) === null || _this$inputRef === void 0 ? void 0 : _this$inputRef.id) || this.getElementId('input')
|
|
1678
|
-
};
|
|
1679
|
-
};
|
|
1680
1710
|
const menuElement = /*#__PURE__*/React.createElement(MenuPlacer, _extends({}, commonProps, menuPlacementProps), ({
|
|
1681
1711
|
ref,
|
|
1682
1712
|
placerProps: {
|
|
@@ -1700,28 +1730,35 @@ export default class Select extends Component {
|
|
|
1700
1730
|
onTopArrive: onMenuScrollToTop,
|
|
1701
1731
|
onBottomArrive: onMenuScrollToBottom,
|
|
1702
1732
|
lockEnabled: menuShouldBlockScroll
|
|
1703
|
-
}, scrollTargetRef =>
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1733
|
+
}, scrollTargetRef => {
|
|
1734
|
+
var _this$inputRef4, _this$inputRef5;
|
|
1735
|
+
return /*#__PURE__*/React.createElement(MenuList, _extends({}, commonProps, {
|
|
1736
|
+
innerRef: instance => {
|
|
1737
|
+
this.getMenuListRef(instance);
|
|
1738
|
+
scrollTargetRef(instance);
|
|
1739
|
+
},
|
|
1740
|
+
innerProps: {
|
|
1741
|
+
role: this.props['UNSAFE_is_experimental_generic'] ? 'dialog' : 'listbox',
|
|
1742
|
+
...(this.props['UNSAFE_is_experimental_generic'] && {
|
|
1743
|
+
'aria-labelledby': ((_this$inputRef4 = this.inputRef) === null || _this$inputRef4 === void 0 ? void 0 : _this$inputRef4.id) || this.getElementId('input')
|
|
1744
|
+
}),
|
|
1745
|
+
'aria-multiselectable': !commonProps.isMulti || this.props['UNSAFE_is_experimental_generic'] ? undefined : commonProps.isMulti,
|
|
1746
|
+
id: this.getElementId('listbox'),
|
|
1747
|
+
...(testId && {
|
|
1748
|
+
'data-testid': `${testId}-select--listbox`
|
|
1749
|
+
}),
|
|
1750
|
+
// add aditional label on listbox for safari to announce first option
|
|
1751
|
+
...(isSafari() && !this.props['UNSAFE_is_experimental_generic'] && {
|
|
1752
|
+
'aria-describedby': ((_this$inputRef5 = this.inputRef) === null || _this$inputRef5 === void 0 ? void 0 : _this$inputRef5.id) || this.getElementId('input')
|
|
1753
|
+
})
|
|
1754
|
+
},
|
|
1755
|
+
isLoading: isLoading,
|
|
1756
|
+
maxHeight: maxHeight,
|
|
1757
|
+
focusedOption: focusedOption
|
|
1758
|
+
}), this.props['UNSAFE_is_experimental_generic'] ? /*#__PURE__*/React.createElement("div", {
|
|
1759
|
+
role: "list"
|
|
1760
|
+
}, menuUI) : menuUI);
|
|
1761
|
+
})));
|
|
1725
1762
|
|
|
1726
1763
|
// positioning behaviour is almost identical for portalled and fixed,
|
|
1727
1764
|
// so we use the same component. the actual portalling logic is forked
|
|
@@ -1789,8 +1826,6 @@ export default class Select extends Component {
|
|
|
1789
1826
|
} = this;
|
|
1790
1827
|
const {
|
|
1791
1828
|
ariaSelection,
|
|
1792
|
-
focusedOption,
|
|
1793
|
-
focusedValue,
|
|
1794
1829
|
isFocused,
|
|
1795
1830
|
selectValue
|
|
1796
1831
|
} = this.state;
|
|
@@ -1798,22 +1833,22 @@ export default class Select extends Component {
|
|
|
1798
1833
|
return /*#__PURE__*/React.createElement(LiveRegion, _extends({}, commonProps, {
|
|
1799
1834
|
id: this.getElementId('live-region'),
|
|
1800
1835
|
ariaSelection: ariaSelection,
|
|
1801
|
-
focusedOption: focusedOption,
|
|
1802
|
-
focusedValue: focusedValue,
|
|
1803
1836
|
isFocused: isFocused,
|
|
1804
1837
|
selectValue: selectValue,
|
|
1805
|
-
focusableOptions: focusableOptions
|
|
1806
|
-
isAppleDevice: this.isVoiceOver
|
|
1838
|
+
focusableOptions: focusableOptions
|
|
1807
1839
|
}));
|
|
1808
1840
|
}
|
|
1809
1841
|
renderMultiselectMessage() {
|
|
1842
|
+
// In the future, when we actually support touch devices, we'll need to update this to not be keyboard specific.
|
|
1843
|
+
// Also, since this is rendered onscreen, it should be transtlated automatically.
|
|
1844
|
+
const msg = `, multiple selections available, ${this.state.selectValue.length ? 'Use left or right arrow keys to navigate selected items' : ''}`;
|
|
1810
1845
|
return (
|
|
1811
1846
|
/*#__PURE__*/
|
|
1812
1847
|
// eslint-disable-next-line @atlaskit/design-system/use-primitives-text
|
|
1813
1848
|
React.createElement("span", {
|
|
1814
1849
|
id: this.getElementId('multi-message'),
|
|
1815
1850
|
hidden: true
|
|
1816
|
-
},
|
|
1851
|
+
}, msg)
|
|
1817
1852
|
);
|
|
1818
1853
|
}
|
|
1819
1854
|
render() {
|
|
@@ -1,73 +1,27 @@
|
|
|
1
1
|
/* eslint-disable @atlaskit/platform/ensure-feature-flag-prefix */
|
|
2
2
|
|
|
3
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
4
3
|
export var defaultAriaLiveMessages = {
|
|
5
|
-
guidance: function guidance(props) {
|
|
6
|
-
var isSearchable = props.isSearchable,
|
|
7
|
-
isMulti = props.isMulti,
|
|
8
|
-
tabSelectsValue = props.tabSelectsValue,
|
|
9
|
-
context = props.context,
|
|
10
|
-
isInitialFocus = props.isInitialFocus;
|
|
11
|
-
switch (context) {
|
|
12
|
-
case 'menu':
|
|
13
|
-
return "Use Up and Down to choose options, press Enter to select the currently focused option, press Escape to exit the menu".concat(tabSelectsValue ? ', press Tab to select the option and exit the menu' : '', ".");
|
|
14
|
-
case 'input':
|
|
15
|
-
return isInitialFocus ? "".concat(props['aria-label'] || 'Select', " is focused ").concat(isSearchable ? ',type to refine list' : '', ", press Down to open the menu, ").concat(isMulti ? ' press left to focus selected values' : '') : '';
|
|
16
|
-
case 'value':
|
|
17
|
-
return 'Use left and right to toggle between focused values, press Backspace to remove the currently focused value';
|
|
18
|
-
default:
|
|
19
|
-
return '';
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
4
|
onChange: function onChange(props) {
|
|
23
5
|
var action = props.action,
|
|
24
6
|
_props$label = props.label,
|
|
25
7
|
label = _props$label === void 0 ? '' : _props$label,
|
|
26
|
-
labels = props.labels,
|
|
27
8
|
isDisabled = props.isDisabled;
|
|
28
9
|
switch (action) {
|
|
29
10
|
case 'deselect-option':
|
|
30
11
|
case 'pop-value':
|
|
31
12
|
case 'remove-value':
|
|
32
|
-
return label.length
|
|
33
|
-
// TODO: this should be handled on backspace|delete if no value, but doing it here first
|
|
13
|
+
return label.length ? "option ".concat(label, ", deselected") : '';
|
|
34
14
|
case 'clear':
|
|
35
15
|
return 'All selected options have been cleared.';
|
|
36
|
-
case 'initial-input-focus':
|
|
37
|
-
return label.length && fg('design_system_select-a11y-improvement') || !fg('design_system_select-a11y-improvement') ? "option".concat(labels.length > 1 ? 's' : '', " ").concat(labels.join(','), ", selected.") : '';
|
|
38
16
|
case 'select-option':
|
|
39
|
-
return
|
|
17
|
+
return label.length && !isDisabled ? "option ".concat(label, ", selected.") : '';
|
|
40
18
|
default:
|
|
41
19
|
return '';
|
|
42
20
|
}
|
|
43
21
|
},
|
|
44
|
-
onFocus: function onFocus(props) {
|
|
45
|
-
var context = props.context,
|
|
46
|
-
focused = props.focused,
|
|
47
|
-
options = props.options,
|
|
48
|
-
_props$label2 = props.label,
|
|
49
|
-
label = _props$label2 === void 0 ? '' : _props$label2,
|
|
50
|
-
selectValue = props.selectValue,
|
|
51
|
-
isDisabled = props.isDisabled,
|
|
52
|
-
isSelected = props.isSelected;
|
|
53
|
-
var getArrayIndex = function getArrayIndex(arr, item) {
|
|
54
|
-
return arr && arr.length ? "(".concat(arr.indexOf(item) + 1, " of ").concat(arr.length, ")") : '';
|
|
55
|
-
};
|
|
56
|
-
if (context === 'value' && selectValue) {
|
|
57
|
-
return "value ".concat(label, " focused, ").concat(getArrayIndex(selectValue, focused), ".");
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// No longer needed after fg('design_system_select-a11y-improvement') is cleaned up
|
|
61
|
-
if (context === 'menu' && !fg('design_system_select-a11y-improvement')) {
|
|
62
|
-
var disabled = isDisabled ? ' disabled' : '';
|
|
63
|
-
var status = "".concat(isSelected ? ' selected' : ' not selected').concat(disabled);
|
|
64
|
-
return "".concat(label).concat(status, ", ").concat(getArrayIndex(options, focused), ", completion selected");
|
|
65
|
-
}
|
|
66
|
-
return '';
|
|
67
|
-
},
|
|
68
22
|
onFilter: function onFilter(props) {
|
|
69
23
|
var inputValue = props.inputValue,
|
|
70
24
|
resultsMessage = props.resultsMessage;
|
|
71
|
-
return "".concat(resultsMessage
|
|
25
|
+
return inputValue ? "".concat(resultsMessage, " for search term ").concat(inputValue, ".") : '';
|
|
72
26
|
}
|
|
73
27
|
};
|
|
@@ -9,8 +9,8 @@ import { ax, ix } from "@compiled/react/runtime";
|
|
|
9
9
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
10
10
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
11
11
|
import { cx } from '@compiled/react';
|
|
12
|
-
import DownIcon from '@atlaskit/icon/
|
|
13
|
-
import CrossIcon from '@atlaskit/icon/
|
|
12
|
+
import DownIcon from '@atlaskit/icon/core/migration/chevron-down';
|
|
13
|
+
import CrossIcon from '@atlaskit/icon/core/migration/cross-circle--select-clear';
|
|
14
14
|
import { Inline, Pressable } from '@atlaskit/primitives/compiled';
|
|
15
15
|
import Spinner from '@atlaskit/spinner';
|
|
16
16
|
import { getStyleProps } from '../../utils';
|
|
@@ -64,7 +64,8 @@ export var DropdownIndicator = function DropdownIndicator(props) {
|
|
|
64
64
|
}, /*#__PURE__*/React.createElement(DownIcon, {
|
|
65
65
|
color: "currentColor",
|
|
66
66
|
label: "open",
|
|
67
|
-
LEGACY_margin: "var(--ds-space-negative-075, -0.375rem)"
|
|
67
|
+
LEGACY_margin: "var(--ds-space-negative-075, -0.375rem)",
|
|
68
|
+
size: "small"
|
|
68
69
|
})));
|
|
69
70
|
};
|
|
70
71
|
export var clearIndicatorCSS = function clearIndicatorCSS() {
|
|
@@ -102,7 +103,8 @@ export var ClearIndicator = function ClearIndicator(props) {
|
|
|
102
103
|
label: "",
|
|
103
104
|
color: "currentColor",
|
|
104
105
|
LEGACY_size: "small",
|
|
105
|
-
LEGACY_margin: "var(--ds-space-negative-025, -0.125rem)"
|
|
106
|
+
LEGACY_margin: "var(--ds-space-negative-025, -0.125rem)",
|
|
107
|
+
size: "small"
|
|
106
108
|
})));
|
|
107
109
|
};
|
|
108
110
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
2
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
3
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
-
import React, { Fragment, useMemo
|
|
5
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
4
|
+
import React, { Fragment, useMemo } from 'react';
|
|
6
5
|
import { defaultAriaLiveMessages } from '../../accessibility';
|
|
7
6
|
import A11yText from './internal/a11y-text';
|
|
8
7
|
|
|
@@ -12,32 +11,21 @@ import A11yText from './internal/a11y-text';
|
|
|
12
11
|
|
|
13
12
|
var LiveRegion = function LiveRegion(props) {
|
|
14
13
|
var ariaSelection = props.ariaSelection,
|
|
15
|
-
focusedOption = props.focusedOption,
|
|
16
|
-
focusedValue = props.focusedValue,
|
|
17
14
|
focusableOptions = props.focusableOptions,
|
|
18
15
|
isFocused = props.isFocused,
|
|
19
16
|
selectValue = props.selectValue,
|
|
20
17
|
selectProps = props.selectProps,
|
|
21
|
-
id = props.id
|
|
22
|
-
isAppleDevice = props.isAppleDevice;
|
|
18
|
+
id = props.id;
|
|
23
19
|
var ariaLiveMessages = selectProps.ariaLiveMessages,
|
|
24
20
|
getOptionLabel = selectProps.getOptionLabel,
|
|
25
21
|
inputValue = selectProps.inputValue,
|
|
26
|
-
isMulti = selectProps.isMulti,
|
|
27
22
|
isOptionDisabled = selectProps.isOptionDisabled,
|
|
28
|
-
isSearchable = selectProps.isSearchable,
|
|
29
|
-
label = selectProps.label,
|
|
30
23
|
menuIsOpen = selectProps.menuIsOpen,
|
|
31
24
|
options = selectProps.options,
|
|
32
25
|
screenReaderStatus = selectProps.screenReaderStatus,
|
|
33
|
-
tabSelectsValue = selectProps.tabSelectsValue,
|
|
34
26
|
isLoading = selectProps.isLoading;
|
|
35
|
-
var ariaLabel = selectProps['aria-label'] || label;
|
|
36
27
|
var ariaLive = selectProps['aria-live'];
|
|
37
28
|
|
|
38
|
-
// for safari, we will use minimum support from aria-live region
|
|
39
|
-
var isA11yImprovementEnabled = fg('design_system_select-a11y-improvement') && !isAppleDevice;
|
|
40
|
-
|
|
41
29
|
// Update aria live message configuration when prop changes
|
|
42
30
|
var messages = useMemo(function () {
|
|
43
31
|
return _objectSpread(_objectSpread({}, defaultAriaLiveMessages), ariaLiveMessages || {});
|
|
@@ -46,7 +34,7 @@ var LiveRegion = function LiveRegion(props) {
|
|
|
46
34
|
// Update aria live selected option when prop changes
|
|
47
35
|
var ariaSelected = useMemo(function () {
|
|
48
36
|
var message = '';
|
|
49
|
-
if (
|
|
37
|
+
if (menuIsOpen) {
|
|
50
38
|
// we don't need to have selected message when the menu is open
|
|
51
39
|
return '';
|
|
52
40
|
}
|
|
@@ -63,12 +51,12 @@ var LiveRegion = function LiveRegion(props) {
|
|
|
63
51
|
|
|
64
52
|
// If there is just one item from the action then get its label
|
|
65
53
|
var selected = removedValue || option || asOption(value);
|
|
66
|
-
var
|
|
54
|
+
var label = selected ? getOptionLabel(selected) : '';
|
|
67
55
|
|
|
68
56
|
// If there are multiple items from the action then return an array of labels
|
|
69
57
|
var multiSelected = selectedOptions || removedValues || undefined;
|
|
70
58
|
var labels = multiSelected ? multiSelected.map(getOptionLabel) : [];
|
|
71
|
-
if (
|
|
59
|
+
if (!label && !labels.length) {
|
|
72
60
|
// return empty string if no labels provided
|
|
73
61
|
return '';
|
|
74
62
|
}
|
|
@@ -76,39 +64,13 @@ var LiveRegion = function LiveRegion(props) {
|
|
|
76
64
|
// multiSelected items are usually items that have already been selected
|
|
77
65
|
// or set by the user as a default value so we assume they are not disabled
|
|
78
66
|
isDisabled: selected && isOptionDisabled(selected, selectValue),
|
|
79
|
-
label:
|
|
67
|
+
label: label,
|
|
80
68
|
labels: labels
|
|
81
69
|
}, ariaSelection);
|
|
82
70
|
message = messages.onChange(onChangeProps);
|
|
83
71
|
}
|
|
84
72
|
return message;
|
|
85
|
-
}, [ariaSelection, messages, isOptionDisabled, selectValue, getOptionLabel,
|
|
86
|
-
var prevInputValue = useRef('');
|
|
87
|
-
var ariaFocused = useMemo(function () {
|
|
88
|
-
var focusMsg = '';
|
|
89
|
-
var focused = focusedOption || focusedValue;
|
|
90
|
-
var isSelected = !!(focusedOption && selectValue && selectValue.includes(focusedOption));
|
|
91
|
-
if (inputValue === prevInputValue.current && isA11yImprovementEnabled) {
|
|
92
|
-
// only announce focus option when searching when ff is on and the input value changed
|
|
93
|
-
// for safari, we will announce for all
|
|
94
|
-
return '';
|
|
95
|
-
}
|
|
96
|
-
if (focused && messages.onFocus) {
|
|
97
|
-
var onFocusProps = {
|
|
98
|
-
focused: focused,
|
|
99
|
-
label: getOptionLabel(focused),
|
|
100
|
-
isDisabled: isOptionDisabled(focused, selectValue),
|
|
101
|
-
isSelected: isSelected,
|
|
102
|
-
options: focusableOptions,
|
|
103
|
-
context: focused === focusedOption ? 'menu' : 'value',
|
|
104
|
-
selectValue: selectValue,
|
|
105
|
-
isMulti: isMulti
|
|
106
|
-
};
|
|
107
|
-
focusMsg = messages.onFocus(onFocusProps);
|
|
108
|
-
}
|
|
109
|
-
prevInputValue.current = inputValue;
|
|
110
|
-
return focusMsg;
|
|
111
|
-
}, [inputValue, focusedOption, focusedValue, getOptionLabel, isOptionDisabled, messages, focusableOptions, selectValue, isA11yImprovementEnabled, isMulti]);
|
|
73
|
+
}, [ariaSelection, messages, isOptionDisabled, selectValue, getOptionLabel, menuIsOpen]);
|
|
112
74
|
var ariaResults = useMemo(function () {
|
|
113
75
|
var resultsMsg = '';
|
|
114
76
|
if (isLoading) {
|
|
@@ -129,43 +91,17 @@ var LiveRegion = function LiveRegion(props) {
|
|
|
129
91
|
return resultsMsg;
|
|
130
92
|
}, [focusableOptions, inputValue, menuIsOpen, messages, options, screenReaderStatus, isLoading]);
|
|
131
93
|
var isInitialFocus = (ariaSelection === null || ariaSelection === void 0 ? void 0 : ariaSelection.action) === 'initial-input-focus';
|
|
132
|
-
var ariaGuidance = useMemo(function () {
|
|
133
|
-
if (fg('design_system_select-a11y-improvement')) {
|
|
134
|
-
// don't announce guidance at all when ff is on
|
|
135
|
-
return '';
|
|
136
|
-
}
|
|
137
|
-
var guidanceMsg = '';
|
|
138
|
-
if (messages.guidance) {
|
|
139
|
-
var context = focusedValue ? 'value' : menuIsOpen ? 'menu' : 'input';
|
|
140
|
-
guidanceMsg = messages.guidance({
|
|
141
|
-
'aria-label': ariaLabel,
|
|
142
|
-
context: context,
|
|
143
|
-
isDisabled: focusedOption && isOptionDisabled(focusedOption, selectValue),
|
|
144
|
-
isMulti: isMulti,
|
|
145
|
-
isSearchable: isSearchable,
|
|
146
|
-
tabSelectsValue: tabSelectsValue,
|
|
147
|
-
isInitialFocus: isInitialFocus
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
return guidanceMsg;
|
|
151
|
-
}, [ariaLabel, focusedOption, focusedValue, isMulti, isOptionDisabled, isSearchable, menuIsOpen, messages, selectValue, tabSelectsValue, isInitialFocus]);
|
|
152
94
|
var ScreenReaderText = /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement("span", {
|
|
153
95
|
id: "aria-selection"
|
|
154
96
|
}, ariaSelected), /*#__PURE__*/React.createElement("span", {
|
|
155
97
|
id: "aria-results"
|
|
156
|
-
}, ariaResults)
|
|
157
|
-
id: "aria-focused"
|
|
158
|
-
}, ariaFocused), /*#__PURE__*/React.createElement("span", {
|
|
159
|
-
id: "aria-guidance"
|
|
160
|
-
}, ariaGuidance)));
|
|
98
|
+
}, ariaResults));
|
|
161
99
|
return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement(A11yText, {
|
|
162
100
|
id: id
|
|
163
101
|
}, isInitialFocus && ScreenReaderText), /*#__PURE__*/React.createElement(A11yText, {
|
|
164
102
|
"aria-live": ariaLive // Should be undefined by default unless a specific use case requires it
|
|
165
103
|
,
|
|
166
|
-
"
|
|
167
|
-
"aria-relevant": fg('design_system_select-a11y-improvement') ? undefined : 'additions text',
|
|
168
|
-
role: fg('design_system_select-a11y-improvement') ? 'status' : 'log'
|
|
104
|
+
role: "status"
|
|
169
105
|
}, isFocused && !isInitialFocus && ScreenReaderText));
|
|
170
106
|
};
|
|
171
107
|
|
|
@@ -7,8 +7,8 @@ import { ax, ix } from "@compiled/react/runtime";
|
|
|
7
7
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
8
8
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
9
9
|
import { cx } from '@compiled/react';
|
|
10
|
+
import CrossIcon from '@atlaskit/icon/core/close';
|
|
10
11
|
import LegacySelectClearIcon from '@atlaskit/icon/glyph/select-clear';
|
|
11
|
-
import CrossIcon from '@atlaskit/icon/utility/cross';
|
|
12
12
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
13
13
|
import { getStyleProps } from '../../utils';
|
|
14
14
|
var multiValueStyles = {
|
|
@@ -84,7 +84,8 @@ export function MultiValueRemove(_ref3) {
|
|
|
84
84
|
LEGACY_fallbackIcon: LegacySelectClearIcon,
|
|
85
85
|
LEGACY_primaryColor: "transparent",
|
|
86
86
|
LEGACY_secondaryColor: "inherit",
|
|
87
|
-
LEGACY_size: "small"
|
|
87
|
+
LEGACY_size: "small",
|
|
88
|
+
size: "small"
|
|
88
89
|
})));
|
|
89
90
|
}
|
|
90
91
|
var MultiValue = function MultiValue(props) {
|
|
@@ -11,8 +11,8 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
11
11
|
|
|
12
12
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled
|
|
13
13
|
import { jsx } from '@emotion/react';
|
|
14
|
-
import DownIcon from '@atlaskit/icon/
|
|
15
|
-
import CrossIcon from '@atlaskit/icon/
|
|
14
|
+
import DownIcon from '@atlaskit/icon/core/migration/chevron-down';
|
|
15
|
+
import CrossIcon from '@atlaskit/icon/core/migration/cross-circle--select-clear';
|
|
16
16
|
import { Inline, Pressable, xcss } from '@atlaskit/primitives';
|
|
17
17
|
import Spinner from '@atlaskit/spinner';
|
|
18
18
|
import { getStyleProps } from '../../utils';
|
|
@@ -65,7 +65,8 @@ export var DropdownIndicator = function DropdownIndicator(props) {
|
|
|
65
65
|
}, jsx(DownIcon, {
|
|
66
66
|
color: "currentColor",
|
|
67
67
|
label: "open",
|
|
68
|
-
LEGACY_margin: "var(--ds-space-negative-075, -0.375rem)"
|
|
68
|
+
LEGACY_margin: "var(--ds-space-negative-075, -0.375rem)",
|
|
69
|
+
size: "small"
|
|
69
70
|
})));
|
|
70
71
|
};
|
|
71
72
|
export var clearIndicatorCSS = function clearIndicatorCSS(_ref2) {
|
|
@@ -98,7 +99,8 @@ export var ClearIndicator = function ClearIndicator(props) {
|
|
|
98
99
|
label: "",
|
|
99
100
|
color: "currentColor",
|
|
100
101
|
LEGACY_size: "small",
|
|
101
|
-
LEGACY_margin: "var(--ds-space-negative-025, -0.125rem)"
|
|
102
|
+
LEGACY_margin: "var(--ds-space-negative-025, -0.125rem)",
|
|
103
|
+
size: "small"
|
|
102
104
|
})));
|
|
103
105
|
};
|
|
104
106
|
|