carbon-react 114.12.2 → 114.13.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/esm/components/anchor-navigation/anchor-navigation.component.js +30 -33
- package/esm/components/anchor-navigation/anchor-navigation.style.js +4 -0
- package/esm/components/date/__internal__/date-picker/date-picker.component.js +11 -7
- package/esm/components/select/multi-select/multi-select.component.js +1 -6
- package/lib/components/anchor-navigation/anchor-navigation.component.js +30 -32
- package/lib/components/anchor-navigation/anchor-navigation.style.js +4 -0
- package/lib/components/date/__internal__/date-picker/date-picker.component.js +11 -7
- package/lib/components/select/multi-select/multi-select.component.js +1 -6
- package/package.json +1 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import React, { useState, useRef, useEffect, useMemo, useCallback
|
|
1
|
+
import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
|
|
2
2
|
import PropTypes from "prop-types";
|
|
3
3
|
import { isFragment } from "react-is";
|
|
4
4
|
import invariant from "invariant";
|
|
5
5
|
import throttle from "lodash/throttle";
|
|
6
|
+
import { defaultFocusableSelectors } from "../../__internal__/focus-trap/focus-trap-utils";
|
|
6
7
|
import Event from "../../__internal__/utils/helpers/events";
|
|
7
8
|
import { StyledAnchorNavigation, StyledNavigation, StyledContent } from "./anchor-navigation.style";
|
|
8
9
|
import AnchorNavigationItem from "./anchor-navigation-item/anchor-navigation-item.component";
|
|
@@ -23,9 +24,6 @@ const AnchorNavigation = ({
|
|
|
23
24
|
!hasCorrectItemStructure ? process.env.NODE_ENV !== "production" ? invariant(false, `\`stickyNavigation\` prop in \`AnchorNavigation\` should be a React Fragment that only contains children of type \`${AnchorNavigationItem.displayName}\``) : invariant(false) : void 0;
|
|
24
25
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
25
26
|
const sectionRefs = useRef(React.Children.map(stickyNavigation.props.children, child => child.props.target));
|
|
26
|
-
const anchorRefs = useRef(Array.from({
|
|
27
|
-
length: React.Children.count(stickyNavigation.props.children)
|
|
28
|
-
}, () => /*#__PURE__*/createRef()));
|
|
29
27
|
const contentRef = useRef(null);
|
|
30
28
|
const navigationRef = useRef(null);
|
|
31
29
|
const isUserScroll = useRef(true);
|
|
@@ -51,8 +49,13 @@ const AnchorNavigation = ({
|
|
|
51
49
|
if (isUserScroll.current) {
|
|
52
50
|
setSelectedAnchorBasedOnScroll();
|
|
53
51
|
} else {
|
|
54
|
-
if (isUserScrollTimer.current !== undefined)
|
|
55
|
-
|
|
52
|
+
if (isUserScrollTimer.current !== undefined) {
|
|
53
|
+
window.clearTimeout(isUserScrollTimer.current);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
isUserScrollTimer.current = setTimeout(
|
|
57
|
+
/* istanbul ignore next */
|
|
58
|
+
() => {
|
|
56
59
|
isUserScroll.current = true;
|
|
57
60
|
}, SCROLL_THROTTLE + 50);
|
|
58
61
|
}
|
|
@@ -62,23 +65,30 @@ const AnchorNavigation = ({
|
|
|
62
65
|
return () => window.removeEventListener("scroll", scrollHandler, true);
|
|
63
66
|
}, [scrollHandler]);
|
|
64
67
|
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (firstFocusableElement) {
|
|
70
|
-
firstFocusableElement.focus({
|
|
71
|
-
preventScroll: true
|
|
72
|
-
});
|
|
68
|
+
const focusSection = section => {
|
|
69
|
+
if (!section.matches(defaultFocusableSelectors)) {
|
|
70
|
+
section.setAttribute("tabindex", "-1");
|
|
73
71
|
}
|
|
72
|
+
|
|
73
|
+
section.focus({
|
|
74
|
+
preventScroll: true
|
|
75
|
+
});
|
|
74
76
|
};
|
|
75
77
|
|
|
76
78
|
const scrollToSection = index => {
|
|
77
79
|
const sectionToScroll = sectionRefs.current[index].current; // istanbul ignore if
|
|
78
80
|
// function is called only after component is rendered, so ref cannot hold a null value
|
|
79
81
|
|
|
80
|
-
if (sectionToScroll === null) return;
|
|
81
|
-
|
|
82
|
+
if (sectionToScroll === null) return; // ensure section has the appropriate element to remove the default focus styles.
|
|
83
|
+
// Can ignore else branch because there's no harm in setting this to "true" twice (it can't hold any other value),
|
|
84
|
+
// but it's probably more efficient not to.
|
|
85
|
+
// istanbul ignore else
|
|
86
|
+
|
|
87
|
+
if (!sectionToScroll.dataset.carbonAnchornavRef) {
|
|
88
|
+
sectionToScroll.dataset.carbonAnchornavRef = "true";
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
focusSection(sectionToScroll); // workaround due to preventScroll focus method option on firefox not working consistently
|
|
82
92
|
|
|
83
93
|
window.setTimeout(() => {
|
|
84
94
|
isUserScroll.current = false;
|
|
@@ -91,26 +101,13 @@ const AnchorNavigation = ({
|
|
|
91
101
|
}, 10);
|
|
92
102
|
};
|
|
93
103
|
|
|
94
|
-
const focusNavItem = index => {
|
|
95
|
-
var _anchorRefs$current$c;
|
|
96
|
-
|
|
97
|
-
const noOfRefs = anchorRefs.current.length;
|
|
98
|
-
(_anchorRefs$current$c = anchorRefs.current[(index % noOfRefs + noOfRefs) % noOfRefs].current) === null || _anchorRefs$current$c === void 0 ? void 0 : _anchorRefs$current$c.focus();
|
|
99
|
-
};
|
|
100
|
-
|
|
101
104
|
const handleClick = (event, index) => {
|
|
102
105
|
event.preventDefault();
|
|
103
106
|
scrollToSection(index);
|
|
104
107
|
};
|
|
105
108
|
|
|
106
109
|
const handleKeyDown = (event, index) => {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (Event.isUpKey(event)) {
|
|
110
|
-
focusNavItem(index - 1);
|
|
111
|
-
} else if (Event.isDownKey(event)) {
|
|
112
|
-
focusNavItem(index + 1);
|
|
113
|
-
} else if (Event.isEnterKey(event) || Event.isSpaceKey(event)) {
|
|
110
|
+
if (Event.isEnterKey(event)) {
|
|
114
111
|
scrollToSection(index);
|
|
115
112
|
}
|
|
116
113
|
};
|
|
@@ -122,11 +119,11 @@ const AnchorNavigation = ({
|
|
|
122
119
|
ref: navigationRef,
|
|
123
120
|
"data-element": "anchor-sticky-navigation"
|
|
124
121
|
}, React.Children.map(stickyNavigation.props.children, (child, index) => /*#__PURE__*/React.cloneElement(child, {
|
|
122
|
+
href: child.props.href || "#",
|
|
123
|
+
// need to pass an href to ensure the link is tabbable by default
|
|
125
124
|
isSelected: index === selectedIndex,
|
|
126
|
-
tabIndex: index === selectedIndex ? 0 : -1,
|
|
127
125
|
onClick: event => handleClick(event, index),
|
|
128
|
-
onKeyDown: event => handleKeyDown(event, index)
|
|
129
|
-
ref: anchorRefs.current[index]
|
|
126
|
+
onKeyDown: event => handleKeyDown(event, index)
|
|
130
127
|
}))), /*#__PURE__*/React.createElement(StyledContent, null, children));
|
|
131
128
|
};
|
|
132
129
|
|
|
@@ -46,13 +46,17 @@ const DatePicker = /*#__PURE__*/React.forwardRef(({
|
|
|
46
46
|
const weekdaysLong = useMemo(() => Array.from({
|
|
47
47
|
length: 7
|
|
48
48
|
}).map((_, i) => localize.day(i)), [localize]);
|
|
49
|
-
const weekdaysShort = useMemo(() =>
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
const weekdaysShort = useMemo(() => {
|
|
50
|
+
const isGivenLocale = str => l.locale().includes(str);
|
|
51
|
+
|
|
52
|
+
return Array.from({
|
|
53
|
+
length: 7
|
|
54
|
+
}).map((_, i) => localize.day(i, ["de", "pl"].some(isGivenLocale) ? {
|
|
55
|
+
width: "wide"
|
|
56
|
+
} : {
|
|
57
|
+
width: "abbreviated"
|
|
58
|
+
}).substring(0, isGivenLocale("de") ? 2 : 3));
|
|
59
|
+
}, [l, localize]);
|
|
56
60
|
|
|
57
61
|
const handleDayClick = (date, {
|
|
58
62
|
disabled
|
|
@@ -353,11 +353,6 @@ const MultiSelect = /*#__PURE__*/React.forwardRef(({
|
|
|
353
353
|
|
|
354
354
|
setTextValue("");
|
|
355
355
|
const isAlreadySelected = actualValue.findIndex(val => isExpectedValue(val, newValue)) !== -1;
|
|
356
|
-
|
|
357
|
-
if (!isAlreadySelected && isControlled.current && onChange) {
|
|
358
|
-
onChange(createCustomEvent([...actualValue, newValue]));
|
|
359
|
-
}
|
|
360
|
-
|
|
361
356
|
textboxRef.focus();
|
|
362
357
|
isMouseDownReported.current = false;
|
|
363
358
|
updateValue(previousValue => {
|
|
@@ -367,7 +362,7 @@ const MultiSelect = /*#__PURE__*/React.forwardRef(({
|
|
|
367
362
|
|
|
368
363
|
return [...previousValue, newValue];
|
|
369
364
|
});
|
|
370
|
-
}, [
|
|
365
|
+
}, [textboxRef, actualValue, updateValue]);
|
|
371
366
|
|
|
372
367
|
function onSelectListClose() {
|
|
373
368
|
setOpenState(false);
|
|
@@ -15,6 +15,8 @@ var _invariant = _interopRequireDefault(require("invariant"));
|
|
|
15
15
|
|
|
16
16
|
var _throttle = _interopRequireDefault(require("lodash/throttle"));
|
|
17
17
|
|
|
18
|
+
var _focusTrapUtils = require("../../__internal__/focus-trap/focus-trap-utils");
|
|
19
|
+
|
|
18
20
|
var _events = _interopRequireDefault(require("../../__internal__/utils/helpers/events"));
|
|
19
21
|
|
|
20
22
|
var _anchorNavigation = require("./anchor-navigation.style");
|
|
@@ -45,9 +47,6 @@ const AnchorNavigation = ({
|
|
|
45
47
|
!hasCorrectItemStructure ? process.env.NODE_ENV !== "production" ? (0, _invariant.default)(false, `\`stickyNavigation\` prop in \`AnchorNavigation\` should be a React Fragment that only contains children of type \`${_anchorNavigationItem.default.displayName}\``) : (0, _invariant.default)(false) : void 0;
|
|
46
48
|
const [selectedIndex, setSelectedIndex] = (0, _react.useState)(0);
|
|
47
49
|
const sectionRefs = (0, _react.useRef)(_react.default.Children.map(stickyNavigation.props.children, child => child.props.target));
|
|
48
|
-
const anchorRefs = (0, _react.useRef)(Array.from({
|
|
49
|
-
length: _react.default.Children.count(stickyNavigation.props.children)
|
|
50
|
-
}, () => /*#__PURE__*/(0, _react.createRef)()));
|
|
51
50
|
const contentRef = (0, _react.useRef)(null);
|
|
52
51
|
const navigationRef = (0, _react.useRef)(null);
|
|
53
52
|
const isUserScroll = (0, _react.useRef)(true);
|
|
@@ -73,8 +72,13 @@ const AnchorNavigation = ({
|
|
|
73
72
|
if (isUserScroll.current) {
|
|
74
73
|
setSelectedAnchorBasedOnScroll();
|
|
75
74
|
} else {
|
|
76
|
-
if (isUserScrollTimer.current !== undefined)
|
|
77
|
-
|
|
75
|
+
if (isUserScrollTimer.current !== undefined) {
|
|
76
|
+
window.clearTimeout(isUserScrollTimer.current);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
isUserScrollTimer.current = setTimeout(
|
|
80
|
+
/* istanbul ignore next */
|
|
81
|
+
() => {
|
|
78
82
|
isUserScroll.current = true;
|
|
79
83
|
}, SCROLL_THROTTLE + 50);
|
|
80
84
|
}
|
|
@@ -84,23 +88,30 @@ const AnchorNavigation = ({
|
|
|
84
88
|
return () => window.removeEventListener("scroll", scrollHandler, true);
|
|
85
89
|
}, [scrollHandler]);
|
|
86
90
|
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (firstFocusableElement) {
|
|
92
|
-
firstFocusableElement.focus({
|
|
93
|
-
preventScroll: true
|
|
94
|
-
});
|
|
91
|
+
const focusSection = section => {
|
|
92
|
+
if (!section.matches(_focusTrapUtils.defaultFocusableSelectors)) {
|
|
93
|
+
section.setAttribute("tabindex", "-1");
|
|
95
94
|
}
|
|
95
|
+
|
|
96
|
+
section.focus({
|
|
97
|
+
preventScroll: true
|
|
98
|
+
});
|
|
96
99
|
};
|
|
97
100
|
|
|
98
101
|
const scrollToSection = index => {
|
|
99
102
|
const sectionToScroll = sectionRefs.current[index].current; // istanbul ignore if
|
|
100
103
|
// function is called only after component is rendered, so ref cannot hold a null value
|
|
101
104
|
|
|
102
|
-
if (sectionToScroll === null) return;
|
|
103
|
-
|
|
105
|
+
if (sectionToScroll === null) return; // ensure section has the appropriate element to remove the default focus styles.
|
|
106
|
+
// Can ignore else branch because there's no harm in setting this to "true" twice (it can't hold any other value),
|
|
107
|
+
// but it's probably more efficient not to.
|
|
108
|
+
// istanbul ignore else
|
|
109
|
+
|
|
110
|
+
if (!sectionToScroll.dataset.carbonAnchornavRef) {
|
|
111
|
+
sectionToScroll.dataset.carbonAnchornavRef = "true";
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
focusSection(sectionToScroll); // workaround due to preventScroll focus method option on firefox not working consistently
|
|
104
115
|
|
|
105
116
|
window.setTimeout(() => {
|
|
106
117
|
isUserScroll.current = false;
|
|
@@ -113,26 +124,13 @@ const AnchorNavigation = ({
|
|
|
113
124
|
}, 10);
|
|
114
125
|
};
|
|
115
126
|
|
|
116
|
-
const focusNavItem = index => {
|
|
117
|
-
var _anchorRefs$current$c;
|
|
118
|
-
|
|
119
|
-
const noOfRefs = anchorRefs.current.length;
|
|
120
|
-
(_anchorRefs$current$c = anchorRefs.current[(index % noOfRefs + noOfRefs) % noOfRefs].current) === null || _anchorRefs$current$c === void 0 ? void 0 : _anchorRefs$current$c.focus();
|
|
121
|
-
};
|
|
122
|
-
|
|
123
127
|
const handleClick = (event, index) => {
|
|
124
128
|
event.preventDefault();
|
|
125
129
|
scrollToSection(index);
|
|
126
130
|
};
|
|
127
131
|
|
|
128
132
|
const handleKeyDown = (event, index) => {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if (_events.default.isUpKey(event)) {
|
|
132
|
-
focusNavItem(index - 1);
|
|
133
|
-
} else if (_events.default.isDownKey(event)) {
|
|
134
|
-
focusNavItem(index + 1);
|
|
135
|
-
} else if (_events.default.isEnterKey(event) || _events.default.isSpaceKey(event)) {
|
|
133
|
+
if (_events.default.isEnterKey(event)) {
|
|
136
134
|
scrollToSection(index);
|
|
137
135
|
}
|
|
138
136
|
};
|
|
@@ -144,11 +142,11 @@ const AnchorNavigation = ({
|
|
|
144
142
|
ref: navigationRef,
|
|
145
143
|
"data-element": "anchor-sticky-navigation"
|
|
146
144
|
}, _react.default.Children.map(stickyNavigation.props.children, (child, index) => /*#__PURE__*/_react.default.cloneElement(child, {
|
|
145
|
+
href: child.props.href || "#",
|
|
146
|
+
// need to pass an href to ensure the link is tabbable by default
|
|
147
147
|
isSelected: index === selectedIndex,
|
|
148
|
-
tabIndex: index === selectedIndex ? 0 : -1,
|
|
149
148
|
onClick: event => handleClick(event, index),
|
|
150
|
-
onKeyDown: event => handleKeyDown(event, index)
|
|
151
|
-
ref: anchorRefs.current[index]
|
|
149
|
+
onKeyDown: event => handleKeyDown(event, index)
|
|
152
150
|
}))), /*#__PURE__*/_react.default.createElement(_anchorNavigation.StyledContent, null, children));
|
|
153
151
|
};
|
|
154
152
|
|
|
@@ -70,13 +70,17 @@ const DatePicker = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
70
70
|
const weekdaysLong = (0, _react.useMemo)(() => Array.from({
|
|
71
71
|
length: 7
|
|
72
72
|
}).map((_, i) => localize.day(i)), [localize]);
|
|
73
|
-
const weekdaysShort = (0, _react.useMemo)(() =>
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
73
|
+
const weekdaysShort = (0, _react.useMemo)(() => {
|
|
74
|
+
const isGivenLocale = str => l.locale().includes(str);
|
|
75
|
+
|
|
76
|
+
return Array.from({
|
|
77
|
+
length: 7
|
|
78
|
+
}).map((_, i) => localize.day(i, ["de", "pl"].some(isGivenLocale) ? {
|
|
79
|
+
width: "wide"
|
|
80
|
+
} : {
|
|
81
|
+
width: "abbreviated"
|
|
82
|
+
}).substring(0, isGivenLocale("de") ? 2 : 3));
|
|
83
|
+
}, [l, localize]);
|
|
80
84
|
|
|
81
85
|
const handleDayClick = (date, {
|
|
82
86
|
disabled
|
|
@@ -383,11 +383,6 @@ const MultiSelect = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
383
383
|
|
|
384
384
|
setTextValue("");
|
|
385
385
|
const isAlreadySelected = actualValue.findIndex(val => (0, _isExpectedValue.default)(val, newValue)) !== -1;
|
|
386
|
-
|
|
387
|
-
if (!isAlreadySelected && isControlled.current && onChange) {
|
|
388
|
-
onChange(createCustomEvent([...actualValue, newValue]));
|
|
389
|
-
}
|
|
390
|
-
|
|
391
386
|
textboxRef.focus();
|
|
392
387
|
isMouseDownReported.current = false;
|
|
393
388
|
updateValue(previousValue => {
|
|
@@ -397,7 +392,7 @@ const MultiSelect = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
397
392
|
|
|
398
393
|
return [...previousValue, newValue];
|
|
399
394
|
});
|
|
400
|
-
}, [
|
|
395
|
+
}, [textboxRef, actualValue, updateValue]);
|
|
401
396
|
|
|
402
397
|
function onSelectListClose() {
|
|
403
398
|
setOpenState(false);
|