carbon-react 107.1.3 → 107.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/esm/__internal__/input/input.component.js +3 -0
  2. package/esm/__internal__/label/icon-wrapper.style.d.ts +2 -0
  3. package/esm/__internal__/label/icon-wrapper.style.js +4 -4
  4. package/esm/__internal__/label/index.d.ts +2 -1
  5. package/esm/__internal__/label/label.component.d.ts +27 -0
  6. package/esm/__internal__/label/label.component.js +42 -80
  7. package/esm/__internal__/label/label.style.d.ts +23 -3
  8. package/esm/__internal__/label/label.style.js +4 -19
  9. package/esm/__internal__/utils/helpers/events/events.d.ts +0 -58
  10. package/esm/__internal__/utils/helpers/events/events.js +12 -128
  11. package/esm/__spec_helper__/test-utils.d.ts +4 -25
  12. package/esm/__spec_helper__/test-utils.js +12 -25
  13. package/esm/components/action-popover/action-popover-menu/action-popover-menu.component.js +2 -2
  14. package/esm/components/anchor-navigation/anchor-navigation-item/anchor-navigation-item.component.d.ts +19 -0
  15. package/esm/components/anchor-navigation/anchor-navigation-item/anchor-navigation-item.component.js +14 -21
  16. package/esm/components/anchor-navigation/anchor-navigation-item/anchor-navigation-item.style.d.ts +5 -0
  17. package/esm/components/anchor-navigation/anchor-navigation-item/anchor-navigation-item.style.js +0 -4
  18. package/esm/components/anchor-navigation/anchor-navigation.component.d.ts +14 -0
  19. package/esm/components/anchor-navigation/anchor-navigation.component.js +55 -72
  20. package/esm/components/anchor-navigation/anchor-navigation.style.d.ts +4 -0
  21. package/esm/components/anchor-navigation/anchor-section-divider.component.d.ts +4 -0
  22. package/esm/components/anchor-navigation/{anchor-section-divider/anchor-section-divider.style.js → anchor-section-divider.component.js} +3 -2
  23. package/esm/components/anchor-navigation/index.d.ts +5 -3
  24. package/esm/components/anchor-navigation/index.js +1 -1
  25. package/esm/components/date/__internal__/date-picker/date-picker.component.js +10 -1
  26. package/esm/components/flat-table/flat-table-cell/flat-table-cell.component.js +1 -0
  27. package/esm/components/flat-table/flat-table-checkbox/flat-table-checkbox.component.js +1 -0
  28. package/esm/components/flat-table/flat-table-header/flat-table-header.component.js +1 -0
  29. package/esm/components/flat-table/flat-table-row/flat-table-row.component.js +3 -3
  30. package/esm/components/flat-table/flat-table-row-header/flat-table-row-header.component.js +1 -0
  31. package/esm/components/help/help.style.d.ts +2 -0
  32. package/esm/components/menu/__internal__/spec-helper/index.js +1 -2
  33. package/esm/components/menu/__internal__/submenu/submenu.component.js +1 -1
  34. package/esm/components/multi-action-button/multi-action-button.component.js +3 -0
  35. package/esm/components/numeral-date/numeral-date.component.js +1 -1
  36. package/esm/components/search/search.component.js +1 -2
  37. package/esm/components/tabs/tabs.component.js +28 -20
  38. package/lib/__internal__/input/input.component.js +3 -0
  39. package/lib/__internal__/label/icon-wrapper.style.d.ts +2 -0
  40. package/lib/__internal__/label/icon-wrapper.style.js +2 -2
  41. package/lib/__internal__/label/index.d.ts +2 -1
  42. package/lib/__internal__/label/label.component.d.ts +27 -0
  43. package/lib/__internal__/label/label.component.js +40 -78
  44. package/lib/__internal__/label/label.style.d.ts +23 -3
  45. package/lib/__internal__/label/label.style.js +4 -22
  46. package/lib/__internal__/utils/helpers/events/events.d.ts +0 -58
  47. package/lib/__internal__/utils/helpers/events/events.js +12 -128
  48. package/lib/__spec_helper__/test-utils.d.ts +4 -25
  49. package/lib/__spec_helper__/test-utils.js +12 -25
  50. package/lib/components/action-popover/action-popover-menu/action-popover-menu.component.js +2 -2
  51. package/lib/components/anchor-navigation/anchor-navigation-item/anchor-navigation-item.component.d.ts +19 -0
  52. package/lib/components/anchor-navigation/anchor-navigation-item/anchor-navigation-item.component.js +14 -21
  53. package/lib/components/anchor-navigation/anchor-navigation-item/anchor-navigation-item.style.d.ts +5 -0
  54. package/lib/components/anchor-navigation/anchor-navigation-item/anchor-navigation-item.style.js +0 -7
  55. package/lib/components/anchor-navigation/anchor-navigation.component.d.ts +14 -0
  56. package/lib/components/anchor-navigation/anchor-navigation.component.js +57 -73
  57. package/lib/components/anchor-navigation/anchor-navigation.style.d.ts +4 -0
  58. package/lib/components/anchor-navigation/anchor-section-divider.component.d.ts +4 -0
  59. package/lib/components/anchor-navigation/{anchor-section-divider/anchor-section-divider.style.js → anchor-section-divider.component.js} +3 -2
  60. package/lib/components/anchor-navigation/index.d.ts +5 -3
  61. package/lib/components/anchor-navigation/index.js +1 -1
  62. package/lib/components/date/__internal__/date-picker/date-picker.component.js +10 -1
  63. package/lib/components/flat-table/flat-table-cell/flat-table-cell.component.js +1 -0
  64. package/lib/components/flat-table/flat-table-checkbox/flat-table-checkbox.component.js +1 -0
  65. package/lib/components/flat-table/flat-table-header/flat-table-header.component.js +1 -0
  66. package/lib/components/flat-table/flat-table-row/flat-table-row.component.js +2 -4
  67. package/lib/components/flat-table/flat-table-row-header/flat-table-row-header.component.js +1 -0
  68. package/lib/components/help/help.style.d.ts +2 -0
  69. package/lib/components/menu/__internal__/spec-helper/index.js +1 -2
  70. package/lib/components/menu/__internal__/submenu/submenu.component.js +1 -1
  71. package/lib/components/multi-action-button/multi-action-button.component.js +3 -0
  72. package/lib/components/numeral-date/numeral-date.component.js +1 -1
  73. package/lib/components/search/search.component.js +1 -3
  74. package/lib/components/tabs/tabs.component.js +28 -20
  75. package/package.json +4 -4
  76. package/esm/__internal__/label/label.d.ts +0 -43
  77. package/esm/components/anchor-navigation/anchor-navigation-item/anchor-navigation-item.d.ts +0 -23
  78. package/esm/components/anchor-navigation/anchor-navigation.d.ts +0 -11
  79. package/esm/components/anchor-navigation/anchor-section-divider/anchor-section-divider.d.ts +0 -12
  80. package/lib/__internal__/label/label.d.ts +0 -43
  81. package/lib/components/anchor-navigation/anchor-navigation-item/anchor-navigation-item.d.ts +0 -23
  82. package/lib/components/anchor-navigation/anchor-navigation.d.ts +0 -11
  83. package/lib/components/anchor-navigation/anchor-section-divider/anchor-section-divider.d.ts +0 -12
@@ -27,43 +27,6 @@ const Events = {
27
27
  return ev.type === type;
28
28
  },
29
29
 
30
- /**
31
- * A method to determine whether a key down event was an arrow key
32
- * */
33
- isNavigationKeyup: ev => {
34
- if (!Events.isEventType(ev, "keyup")) {
35
- return false;
36
- }
37
-
38
- return Events.isNavigationKey(ev);
39
- },
40
-
41
- /**
42
- * A method to determine whether a key down event was an enter key
43
- * */
44
- isEnterKeyup: ev => {
45
- if (!Events.isEventType(ev, "keyup")) {
46
- return false;
47
- }
48
-
49
- return Events.isEnterKey(ev);
50
- },
51
-
52
- /**
53
- * A method to determine whether a key up event is allowed or not.
54
- * */
55
- isValidKeypress: ev => {
56
- if (!Events.isEventType(ev, "keyup")) {
57
- return false;
58
- }
59
-
60
- if (Events.isNumberKey(ev) || Events.isAlphabetKey(ev) || Events.isNumpadKey(ev) || Events.isSymbolKey(ev) || Events.isSpaceKey(ev) || Events.isDeletingKey(ev) || Events.isBackspaceKey(ev)) {
61
- return true;
62
- }
63
-
64
- return false;
65
- },
66
-
67
30
  /**
68
31
  * Determines if a number key along the top of the keyboard or a number key on the
69
32
  * keypad is pressed
@@ -75,167 +38,88 @@ const Events = {
75
38
  return charCode !== undefined && charCode >= 48 && charCode <= 57;
76
39
  },
77
40
 
78
- /**
79
- * Determines if the key pressed is part of the numpad
80
- * includes symbols
81
- * */
82
- isNumpadKey: ev => {
83
- return ev.which !== undefined && ev.which >= 96 && ev.which <= 111;
84
- },
85
-
86
- /**
87
- * Determines if the key pressed is a alphabet key
88
- * Case insensitive
89
- * */
90
- isAlphabetKey: ev => {
91
- return ev.which !== undefined && ev.which >= 65 && ev.which <= 90;
92
- },
93
-
94
- /**
95
- * Determines if the key pressed is a valid symbol
96
- * */
97
- isSymbolKey: ev => {
98
- return ev.which !== undefined && (ev.which >= 58 && ev.which <= 64 || ev.which >= 106 && ev.which <= 107 || ev.which >= 186 && ev.which <= 192 || ev.which >= 219 && ev.which <= 222);
99
- },
100
-
101
- /**
102
- * Determines if the key pressed is a navigation key
103
- * */
104
- isNavigationKey: ev => {
105
- return ev.which !== undefined && ev.which >= 37 && ev.which <= 40;
106
- },
107
-
108
41
  /**
109
42
  * Determines if the key pressed is a navigation left key
110
43
  * */
111
44
  isLeftKey: ev => {
112
- return ev.which === 37;
45
+ return ev.key === "ArrowLeft";
113
46
  },
114
47
 
115
48
  /**
116
49
  * Determines if the key pressed is a navigation up key
117
50
  * */
118
51
  isUpKey: ev => {
119
- return ev.which === 38;
52
+ return ev.key === "ArrowUp";
120
53
  },
121
54
 
122
55
  /**
123
56
  * Determines if the key pressed is a navigation right key
124
57
  * */
125
58
  isRightKey: ev => {
126
- return ev.which === 39;
59
+ return ev.key === "ArrowRight";
127
60
  },
128
61
 
129
62
  /**
130
63
  * Determines if the key pressed is a navigation down key
131
64
  * */
132
65
  isDownKey: ev => {
133
- return ev.which === 40;
134
- },
135
-
136
- /**
137
- * Determines if the key pressed is a meta key
138
- * */
139
- isMetaKey: ev => {
140
- return !!ev.metaKey;
66
+ return ev.key === "ArrowDown";
141
67
  },
142
68
 
143
69
  /**
144
70
  * Determines if the key pressed is the escape key
145
71
  * */
146
72
  isEscKey: ev => {
147
- return ev.which === 27;
73
+ return ev.key === "Escape";
148
74
  },
149
75
 
150
76
  /**
151
77
  * Determines if the key pressed is the enter key
152
78
  * */
153
79
  isEnterKey: ev => {
154
- return ev.which === 13;
80
+ return ev.key === "Enter";
155
81
  },
156
82
 
157
83
  /**
158
84
  * Determines if the key pressed is the tab key
159
85
  * */
160
86
  isTabKey: ev => {
161
- return ev.which === 9;
162
- },
163
-
164
- /**
165
- * Determines if the key pressed is the backspace key
166
- * */
167
- isBackspaceKey: ev => {
168
- return ev.key === "Backspace";
169
- },
170
-
171
- /**
172
- * Determines if the key pressed is the delete key
173
- * */
174
- isDeleteKey: ev => {
175
- return ev.key === "Delete";
176
- },
177
-
178
- /**
179
- * Determines if the key pressed is the backspace or delete key
180
- * */
181
- isDeletingKey: ev => {
182
- return Events.isDeleteKey(ev) || Events.isBackspaceKey(ev);
87
+ return ev.key === "Tab";
183
88
  },
184
89
 
185
90
  /**
186
91
  * Determines if the key pressed is the shift key
187
92
  * */
188
93
  isShiftKey: ev => {
189
- return ev.shiftKey || ev.which === 16;
94
+ return ev.shiftKey;
190
95
  },
191
96
 
192
97
  /**
193
98
  * Determines if the key pressed is the space key
194
99
  * */
195
100
  isSpaceKey: ev => {
196
- return ev.which === 32;
101
+ return ev.key === " ";
197
102
  },
198
103
 
199
104
  /**
200
105
  * Determines if the key pressed is the space key or enter key
201
106
  * */
202
107
  isEnterOrSpaceKey: ev => {
203
- return ev.which === 13 || ev.which === 32;
204
- },
205
-
206
- /**
207
- * Determines if the key pressed is the period key
208
- * */
209
- isPeriodKey: ev => {
210
- return ev.which === 190;
211
- },
212
-
213
- /**
214
- * Determines if the key pressed is the comma key
215
- * */
216
- isCommaKey: ev => {
217
- return ev.which === 188;
218
- },
219
-
220
- /**
221
- * Determines if the key pressed is the minus key
222
- * */
223
- isMinusKey: ev => {
224
- return ev.key === "-" || ev.key === "Subtract";
108
+ return ev.key === "Enter" || ev.key === " ";
225
109
  },
226
110
 
227
111
  /**
228
112
  * Determines if the key pressed is the home key
229
113
  * */
230
114
  isHomeKey: ev => {
231
- return ev.which === 36;
115
+ return ev.key === "Home";
232
116
  },
233
117
 
234
118
  /**
235
119
  * Determines if the key pressed is the end key
236
120
  * */
237
121
  isEndKey: ev => {
238
- return ev.which === 35;
122
+ return ev.key === "End";
239
123
  },
240
124
 
241
125
  /**
@@ -8,32 +8,11 @@ declare const assertStyleMatch: <Props>(styleSpec: {
8
8
  [key: string]: string | number | undefined;
9
9
  }, component: ReactWrapper<Props, {}, import("react").Component<{}, {}, any>> | ShallowWrapper<Props, {}, import("react").Component<{}, {}, any>> | ReactTestRendererJSON | ReactTestRendererJSON[] | null, opts?: jest.Options | undefined) => void;
10
10
  declare const makeArrayKeys: (n: number) => number[];
11
- declare const keyMap: {
12
- readonly UpArrow: 38;
13
- readonly DownArrow: 40;
14
- readonly RightArrow: 39;
15
- readonly LeftArrow: 37;
16
- readonly Enter: 13;
17
- readonly Tab: 9;
18
- readonly Space: 32;
19
- readonly Escape: 27;
20
- readonly End: 35;
21
- readonly Home: 36;
22
- readonly D: 68;
23
- readonly E: 69;
24
- readonly P: 80;
25
- readonly Z: 90;
26
- readonly 1: 49;
27
- };
28
- declare type Keys = keyof typeof keyMap;
29
- declare type MappedKeys = `press${Keys}`;
30
- declare type KeyboardAccumulatorType = Record<MappedKeys, () => void>;
31
- declare const keyboard: KeyboardAccumulatorType;
32
- declare type KeydownAccumulatorType = Record<MappedKeys, (wrapper: ReactWrapper<any>, options?: {
33
- shiftKey: boolean;
34
- }) => void>;
11
+ declare const keyboard: Record<string, () => void>;
35
12
  declare const simulate: {
36
- keydown: KeydownAccumulatorType;
13
+ keydown: Record<string, (target: ReactWrapper<any>, { shiftKey }?: {
14
+ shiftKey: boolean;
15
+ } | undefined) => void>;
37
16
  };
38
17
  declare const listFrom: (wrapper: ReactWrapper) => ReactWrapper<import("enzyme").HTMLAttributes, any, import("react").Component<{}, {}, any>>;
39
18
  declare const childrenFrom: (node: ReactWrapper) => ReactWrapper<any, any, import("react").Component<{}, {}, any>>;
@@ -50,30 +50,16 @@ exports.makeArrayKeys = makeArrayKeys;
50
50
 
51
51
  const dispatchKeyPress = code => {
52
52
  const ev = new KeyboardEvent("keydown", {
53
- which: code
53
+ key: code
54
54
  });
55
55
  document.dispatchEvent(ev);
56
56
  };
57
57
 
58
- const keyMap = {
59
- UpArrow: 38,
60
- DownArrow: 40,
61
- RightArrow: 39,
62
- LeftArrow: 37,
63
- Enter: 13,
64
- Tab: 9,
65
- Space: 32,
66
- Escape: 27,
67
- End: 35,
68
- Home: 36,
69
- D: 68,
70
- E: 69,
71
- P: 80,
72
- Z: 90,
73
- 1: 49
74
- };
75
- const keyboard = Object.keys(keyMap).reduce((acc, key) => {
76
- acc[`press${key}`] = () => dispatchKeyPress(keyMap[key]);
58
+ const keys = ["ArrowUp", "ArrowDown", "ArrowRight", "ArrowLeft", "Enter", "Tab", " ", "Escape", "End", "Home", "D", "E", "P", "Z", "1"];
59
+ const keyboard = keys.reduce((acc, key) => {
60
+ const methodName = `press${key === " " ? "Space" : key}`;
61
+
62
+ acc[methodName] = () => dispatchKeyPress(key);
77
63
 
78
64
  return acc;
79
65
  }, {}); // Build an object of Enzyme simulate helpers
@@ -81,16 +67,17 @@ const keyboard = Object.keys(keyMap).reduce((acc, key) => {
81
67
  // e.g. simulate.keydown.pressEscape(target)
82
68
 
83
69
  exports.keyboard = keyboard;
84
- const keydown = Object.keys(keyMap).reduce((acc, key) => {
85
- acc[`press${key}`] = (target, {
70
+ const keydown = keys.reduce((acc, key) => {
71
+ const methodName = `press${key === " " ? "Space" : key}`;
72
+
73
+ acc[methodName] = (target, {
86
74
  shiftKey
87
75
  } = {
88
76
  shiftKey: false
89
77
  }) => {
90
78
  target.simulate("keydown", {
91
79
  shiftKey,
92
- key,
93
- which: keyMap[key]
80
+ key
94
81
  });
95
82
  };
96
83
 
@@ -146,7 +133,7 @@ const assertCorrectTraversal = method => expect => ({
146
133
  expect(arraysEqual(validIndexes, indexesThatWereSelected)).toBeTruthy();
147
134
  };
148
135
 
149
- const assertKeyboardTraversal = assertCorrectTraversal(() => keyboard.pressDownArrow)(expect);
136
+ const assertKeyboardTraversal = assertCorrectTraversal(() => keyboard.pressArrowDown)(expect);
150
137
  exports.assertKeyboardTraversal = assertKeyboardTraversal;
151
138
  const assertHoverTraversal = assertCorrectTraversal(wrapper => hoverList(wrapper))(expect);
152
139
  exports.assertHoverTraversal = assertHoverTraversal;
@@ -92,8 +92,8 @@ const ActionPopoverMenu = /*#__PURE__*/_react.default.forwardRef(({
92
92
  e.preventDefault();
93
93
  e.stopPropagation();
94
94
  setFocusIndex(items.length - 1);
95
- } else if (_events.default.isAlphabetKey(e)) {
96
- // A-Za-z: focus the next item on the list that starts with the pressed key
95
+ } else if (e.key.length === 1) {
96
+ // any printable character: focus the next item on the list that starts with that character
97
97
  // selection should wrap to the start of the list
98
98
  e.stopPropagation();
99
99
  let firstMatch;
@@ -0,0 +1,19 @@
1
+ import React from "react";
2
+ export interface AnchorNavigationItemProps {
3
+ /** Reference to the section html element meant to be shown */
4
+ target?: React.RefObject<HTMLElement>;
5
+ /** href to be passed to the anchor element, can be linked with id passed to the scrollable section */
6
+ href?: string;
7
+ /** Indicates if component is selected */
8
+ isSelected?: boolean;
9
+ /** onClick handler */
10
+ onClick?: (ev: React.MouseEvent<HTMLAnchorElement>) => void;
11
+ /** OnKeyDown handler */
12
+ onKeyDown?: (ev: React.KeyboardEvent<HTMLAnchorElement>) => void;
13
+ /** tabIndex passed to the anchor element */
14
+ tabIndex?: number;
15
+ /** Children elements */
16
+ children?: React.ReactNode;
17
+ }
18
+ declare const AnchorNavigationItem: React.ForwardRefExoticComponent<AnchorNavigationItemProps & React.RefAttributes<HTMLAnchorElement>>;
19
+ export default AnchorNavigationItem;
@@ -13,7 +13,6 @@ var _anchorNavigationItem = _interopRequireDefault(require("./anchor-navigation-
13
13
 
14
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
15
 
16
- /* eslint-disable react/no-unused-prop-types */
17
16
  const AnchorNavigationItem = /*#__PURE__*/_react.default.forwardRef(({
18
17
  children,
19
18
  onKeyDown,
@@ -33,26 +32,20 @@ const AnchorNavigationItem = /*#__PURE__*/_react.default.forwardRef(({
33
32
  }, children)));
34
33
 
35
34
  AnchorNavigationItem.propTypes = {
36
- children: _propTypes.default.node,
37
-
38
- /** OnKeyDown handler */
39
- onKeyDown: _propTypes.default.func,
40
-
41
- /** onClick handler */
42
- onClick: _propTypes.default.func,
43
-
44
- /** href to be passed to the anchor element, can be linked with id passed to the scrollable section */
45
- href: _propTypes.default.string,
46
-
47
- /** tabIndex passed to the anchor element */
48
- tabIndex: _propTypes.default.number,
49
-
50
- /** Indicates if component is selected */
51
- isSelected: _propTypes.default.bool,
52
-
53
- /** Reference to the section html element meant to be shown */
54
- target: _propTypes.default.shape({
55
- current: _propTypes.default.instanceOf(Element)
35
+ "children": _propTypes.default.node,
36
+ "href": _propTypes.default.string,
37
+ "isSelected": _propTypes.default.bool,
38
+ "onClick": _propTypes.default.func,
39
+ "onKeyDown": _propTypes.default.func,
40
+ "tabIndex": _propTypes.default.number,
41
+ "target": _propTypes.default.shape({
42
+ "current": _propTypes.default.oneOfType([_propTypes.default.oneOf([null]), function (props, propName) {
43
+ if (props[propName] == null) {
44
+ return new Error("Prop '" + propName + "' is required but wasn't specified");
45
+ } else if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) {
46
+ return new Error("Expected prop '" + propName + "' to be of type Element");
47
+ }
48
+ }]).isRequired
56
49
  })
57
50
  };
58
51
  AnchorNavigationItem.displayName = "AnchorNavigationItem";
@@ -0,0 +1,5 @@
1
+ export interface StyledNavigationItemProps {
2
+ isSelected?: boolean;
3
+ }
4
+ declare const StyledNavigationItem: import("styled-components").StyledComponent<"li", any, StyledNavigationItemProps, never>;
5
+ export default StyledNavigationItem;
@@ -5,16 +5,12 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
 
8
- var _propTypes = _interopRequireDefault(require("prop-types"));
9
-
10
8
  var _styledComponents = _interopRequireWildcard(require("styled-components"));
11
9
 
12
10
  function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
13
11
 
14
12
  function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
15
13
 
16
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
-
18
14
  const StyledNavigationItem = _styledComponents.default.li`
19
15
  width: 100%;
20
16
 
@@ -46,8 +42,5 @@ const StyledNavigationItem = _styledComponents.default.li`
46
42
  `}
47
43
  }
48
44
  `;
49
- StyledNavigationItem.propTypes = {
50
- isSelected: _propTypes.default.bool
51
- };
52
45
  var _default = StyledNavigationItem;
53
46
  exports.default = _default;
@@ -0,0 +1,14 @@
1
+ import React from "react";
2
+ export interface AnchorNavigationProps {
3
+ /** Child elements */
4
+ children?: React.ReactNode;
5
+ /** The AnchorNavigationItems components to be rendered in the sticky navigation.
6
+ It is important to maintain proper structure.
7
+ List of AnchorNavigationItems has to be wrapped in React.Fragment */
8
+ stickyNavigation?: React.ReactNode;
9
+ }
10
+ declare const AnchorNavigation: {
11
+ ({ children, stickyNavigation, }: AnchorNavigationProps): JSX.Element;
12
+ displayName: string;
13
+ };
14
+ export default AnchorNavigation;
@@ -9,10 +9,12 @@ var _react = _interopRequireWildcard(require("react"));
9
9
 
10
10
  var _propTypes = _interopRequireDefault(require("prop-types"));
11
11
 
12
- var _throttle = _interopRequireDefault(require("lodash/throttle"));
13
-
14
12
  var _reactIs = require("react-is");
15
13
 
14
+ var _invariant = _interopRequireDefault(require("invariant"));
15
+
16
+ var _throttle = _interopRequireDefault(require("lodash/throttle"));
17
+
16
18
  var _events = _interopRequireDefault(require("../../__internal__/utils/helpers/events"));
17
19
 
18
20
  var _anchorNavigation = require("./anchor-navigation.style");
@@ -32,45 +34,57 @@ const AnchorNavigation = ({
32
34
  children,
33
35
  stickyNavigation
34
36
  }) => {
37
+ (0, _invariant.default)((0, _reactIs.isFragment)(stickyNavigation), "`stickyNavigation` prop in `AnchorNavigation` should be a React Fragment.");
38
+ const hasCorrectItemStructure = (0, _react.useMemo)(() => {
39
+ const incorrectChild = _react.default.Children.toArray(stickyNavigation.props.children).find(child => {
40
+ return ! /*#__PURE__*/_react.default.isValidElement(child) || child.type.displayName !== _anchorNavigationItem.default.displayName;
41
+ });
42
+
43
+ return !incorrectChild;
44
+ }, [stickyNavigation]);
45
+ (0, _invariant.default)(hasCorrectItemStructure, `\`stickyNavigation\` prop in \`AnchorNavigation\` should be a React Fragment that only contains children of type \`${_anchorNavigationItem.default.displayName}\``);
35
46
  const [selectedIndex, setSelectedIndex] = (0, _react.useState)(0);
36
47
  const sectionRefs = (0, _react.useRef)(_react.default.Children.map(stickyNavigation.props.children, child => child.props.target));
37
48
  const anchorRefs = (0, _react.useRef)(Array.from({
38
49
  length: _react.default.Children.count(stickyNavigation.props.children)
39
- }, () => /*#__PURE__*/_react.default.createRef()));
40
- const contentRef = (0, _react.useRef)();
41
- const navigationRef = (0, _react.useRef)();
50
+ }, () => /*#__PURE__*/(0, _react.createRef)()));
51
+ const contentRef = (0, _react.useRef)(null);
52
+ const navigationRef = (0, _react.useRef)(null);
42
53
  const isUserScroll = (0, _react.useRef)(true);
43
54
  const isUserScrollTimer = (0, _react.useRef)();
44
55
  const setSelectedAnchorBasedOnScroll = (0, _react.useCallback)(() => {
45
- const sectionsTopOffsets = sectionRefs.current.map(({
56
+ // istanbul ignore if
57
+ // function is called only after component is rendered, so ref cannot hold a null value
58
+ if (navigationRef.current === null) return;
59
+ const offsetsWithIndexes = sectionRefs.current.map(({
46
60
  current
47
- }) => current.getBoundingClientRect().top);
61
+ }, index) => [index, current === null || current === void 0 ? void 0 : current.getBoundingClientRect().top]).filter(offsetWithIndex => offsetWithIndex[1] !== undefined);
48
62
  const {
49
63
  top: navTopOffset
50
64
  } = navigationRef.current.getBoundingClientRect();
51
- const indexOfSmallestNegativeTopOffset = sectionsTopOffsets.reduce((currentTopIndex, sectionTopOffset, index) => {
52
- if (sectionTopOffset - SECTION_VISIBILITY_OFFSET > navTopOffset) return currentTopIndex;
53
- return sectionTopOffset > sectionsTopOffsets[currentTopIndex] ? index : currentTopIndex;
54
- }, 0);
65
+ const indexOfSmallestNegativeTopOffset = offsetsWithIndexes.reduce((currentTopIndex, offsetWithIndex) => {
66
+ const [index, offset] = offsetWithIndex;
67
+ if (offset - SECTION_VISIBILITY_OFFSET > navTopOffset) return currentTopIndex;
68
+ return offset > offsetsWithIndexes[currentTopIndex][1] ? index : currentTopIndex;
69
+ }, offsetsWithIndexes[0][0]);
55
70
  setSelectedIndex(indexOfSmallestNegativeTopOffset);
56
71
  }, []);
57
- const scrollHandler = (0, _react.useCallback)((0, _throttle.default)(() => {
72
+ const scrollHandler = (0, _react.useMemo)(() => (0, _throttle.default)(() => {
58
73
  if (isUserScroll.current) {
59
74
  setSelectedAnchorBasedOnScroll();
60
75
  } else {
61
- window.clearTimeout(isUserScrollTimer.current);
76
+ if (isUserScrollTimer.current !== undefined) window.clearTimeout(isUserScrollTimer.current);
62
77
  isUserScrollTimer.current = setTimeout(() => {
63
78
  isUserScroll.current = true;
64
79
  }, SCROLL_THROTTLE + 50);
65
80
  }
66
- }, SCROLL_THROTTLE), []);
81
+ }, SCROLL_THROTTLE), [setSelectedAnchorBasedOnScroll]);
67
82
  (0, _react.useEffect)(() => {
68
83
  window.addEventListener("scroll", scrollHandler, true);
69
84
  return () => window.removeEventListener("scroll", scrollHandler, true);
70
85
  }, [scrollHandler]);
71
86
 
72
87
  const focusFirstFocusableChild = section => {
73
- // eslint-disable-next-line max-len
74
88
  const defaultFocusableSelectors = 'button, [href], input:not([type="hidden"]), select, textarea, [tabindex]:not([tabindex="-1"])';
75
89
  const firstFocusableElement = section.querySelector(defaultFocusableSelectors);
76
90
 
@@ -81,46 +95,45 @@ const AnchorNavigation = ({
81
95
  }
82
96
  };
83
97
 
84
- const scrollToSection = section => {
85
- isUserScroll.current = false;
86
- section.scrollIntoView({
87
- block: "start",
88
- inline: "nearest",
89
- behavior: "smooth"
90
- });
91
- };
98
+ const scrollToSection = index => {
99
+ const sectionToScroll = sectionRefs.current[index].current; // istanbul ignore if
100
+ // function is called only after component is rendered, so ref cannot hold a null value
92
101
 
93
- const handleClick = (event, index) => {
94
- event.preventDefault();
95
- const sectionToScroll = sectionRefs.current[index].current;
102
+ if (sectionToScroll === null) return;
96
103
  focusFirstFocusableChild(sectionToScroll); // workaround due to preventScroll focus method option on firefox not working consistently
97
104
 
98
105
  window.setTimeout(() => {
99
- scrollToSection(sectionToScroll);
106
+ isUserScroll.current = false;
107
+ sectionToScroll.scrollIntoView({
108
+ block: "start",
109
+ inline: "nearest",
110
+ behavior: "smooth"
111
+ });
100
112
  setSelectedIndex(index);
101
113
  }, 10);
102
114
  };
103
115
 
104
- const focusNavItem = (event, index) => {
105
- event.preventDefault();
106
- let newIndex = index;
116
+ const focusNavItem = index => {
117
+ var _anchorRefs$current$c;
107
118
 
108
- if (index === -1) {
109
- newIndex = anchorRefs.current.length - 1;
110
- } else if (index === anchorRefs.current.length) {
111
- newIndex = 0;
112
- }
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
+ };
113
122
 
114
- anchorRefs.current[newIndex].current.focus();
123
+ const handleClick = (event, index) => {
124
+ event.preventDefault();
125
+ scrollToSection(index);
115
126
  };
116
127
 
117
128
  const handleKeyDown = (event, index) => {
129
+ event.preventDefault();
130
+
118
131
  if (_events.default.isUpKey(event)) {
119
- focusNavItem(event, index - 1);
132
+ focusNavItem(index - 1);
120
133
  } else if (_events.default.isDownKey(event)) {
121
- focusNavItem(event, index + 1);
134
+ focusNavItem(index + 1);
122
135
  } else if (_events.default.isEnterKey(event) || _events.default.isSpaceKey(event)) {
123
- handleClick(event, index);
136
+ scrollToSection(index);
124
137
  }
125
138
  };
126
139
 
@@ -133,45 +146,16 @@ const AnchorNavigation = ({
133
146
  }, _react.default.Children.map(stickyNavigation.props.children, (child, index) => /*#__PURE__*/_react.default.cloneElement(child, {
134
147
  isSelected: index === selectedIndex,
135
148
  tabIndex: index === selectedIndex ? 0 : -1,
136
- onClick: ev => handleClick(ev, index),
137
- onKeyDown: ev => handleKeyDown(ev, index),
149
+ onClick: event => handleClick(event, index),
150
+ onKeyDown: event => handleKeyDown(event, index),
138
151
  ref: anchorRefs.current[index]
139
152
  }))), /*#__PURE__*/_react.default.createElement(_anchorNavigation.StyledContent, null, children));
140
153
  };
141
154
 
142
155
  AnchorNavigation.propTypes = {
143
- children: _propTypes.default.node,
144
-
145
- /** The AnchorNavigationItems components to be rendered in the sticky navigation.
146
- It is important to maintain proper structure.
147
- List of AnchorNavigationItems has to be wrapped in React.Fragment */
148
- stickyNavigation: (props, propName, componentName) => {
149
- let error;
150
- const prop = props[propName];
151
- const errorsList = [];
152
-
153
- if (!(0, _reactIs.isFragment)(prop)) {
154
- errorsList.push(`Prop ${propName} container supplied to ${componentName} should be a React.Fragment.`);
155
- }
156
-
157
- let isAnyChildIncorrect = false;
158
-
159
- _react.default.Children.forEach(prop.props.children, child => {
160
- if (_anchorNavigationItem.default.displayName !== child.type.displayName) {
161
- isAnyChildIncorrect = true;
162
- }
163
- });
164
-
165
- if (isAnyChildIncorrect) {
166
- errorsList.push(`Prop ${propName} container supplied to ${componentName} only accepts children of type ${_anchorNavigationItem.default.displayName}.`);
167
- }
168
-
169
- if (errorsList.length) {
170
- error = new Error(errorsList.join(" "));
171
- }
172
-
173
- return error;
174
- }
156
+ "children": _propTypes.default.node,
157
+ "stickyNavigation": _propTypes.default.node
175
158
  };
159
+ AnchorNavigation.displayName = "AnchorNavigation";
176
160
  var _default = AnchorNavigation;
177
161
  exports.default = _default;
@@ -0,0 +1,4 @@
1
+ declare const StyledAnchorNavigation: import("styled-components").StyledComponent<"div", any, {}, never>;
2
+ declare const StyledNavigation: import("styled-components").StyledComponent<"ul", any, {}, never>;
3
+ declare const StyledContent: import("styled-components").StyledComponent<"div", any, {}, never>;
4
+ export { StyledAnchorNavigation, StyledNavigation, StyledContent };