carbon-react 120.3.0 → 120.3.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.
Files changed (23) hide show
  1. package/esm/components/flat-table/__internal__/index.d.ts +1 -1
  2. package/esm/components/flat-table/__internal__/index.js +1 -1
  3. package/esm/components/flat-table/__internal__/{use-calculate-sticky-cells.d.ts → use-table-cell.d.ts} +3 -0
  4. package/esm/components/flat-table/__internal__/{use-calculate-sticky-cells.js → use-table-cell.js} +21 -3
  5. package/esm/components/flat-table/flat-table-cell/flat-table-cell.component.js +10 -14
  6. package/esm/components/flat-table/flat-table-header/flat-table-header.component.js +2 -2
  7. package/esm/components/flat-table/flat-table-row/__internal__/flat-table-row-context.d.ts +2 -0
  8. package/esm/components/flat-table/flat-table-row/flat-table-row.component.js +9 -11
  9. package/esm/components/flat-table/flat-table-row-header/flat-table-row-header.component.js +10 -12
  10. package/esm/components/flat-table/flat-table.component.d.ts +1 -2
  11. package/esm/components/flat-table/flat-table.component.js +9 -29
  12. package/lib/components/flat-table/__internal__/index.d.ts +1 -1
  13. package/lib/components/flat-table/__internal__/index.js +3 -3
  14. package/lib/components/flat-table/__internal__/{use-calculate-sticky-cells.d.ts → use-table-cell.d.ts} +3 -0
  15. package/lib/components/flat-table/__internal__/{use-calculate-sticky-cells.js → use-table-cell.js} +20 -2
  16. package/lib/components/flat-table/flat-table-cell/flat-table-cell.component.js +9 -13
  17. package/lib/components/flat-table/flat-table-header/flat-table-header.component.js +2 -2
  18. package/lib/components/flat-table/flat-table-row/__internal__/flat-table-row-context.d.ts +2 -0
  19. package/lib/components/flat-table/flat-table-row/flat-table-row.component.js +9 -11
  20. package/lib/components/flat-table/flat-table-row-header/flat-table-row-header.component.js +9 -11
  21. package/lib/components/flat-table/flat-table.component.d.ts +1 -2
  22. package/lib/components/flat-table/flat-table.component.js +9 -29
  23. package/package.json +1 -1
@@ -1,2 +1,2 @@
1
- export { default as useCalculateStickyCells } from "./use-calculate-sticky-cells";
1
+ export { default as useTableCell } from "./use-table-cell";
2
2
  export { default as buildPositionMap } from "./build-position-map";
@@ -1,2 +1,2 @@
1
- export { default as useCalculateStickyCells } from "./use-calculate-sticky-cells";
1
+ export { default as useTableCell } from "./use-table-cell";
2
2
  export { default as buildPositionMap } from "./build-position-map";
@@ -8,5 +8,8 @@ declare const _default: (id: string) => {
8
8
  onKeyDown: ((ev: import("react").KeyboardEvent<HTMLElement>) => void) | undefined;
9
9
  isFirstCell: boolean;
10
10
  isExpandableCell: boolean | undefined;
11
+ tabIndex: number;
12
+ isInHighlightedRow: boolean | undefined;
13
+ isInSelectedRow: boolean | undefined;
11
14
  };
12
15
  export default _default;
@@ -1,6 +1,11 @@
1
- import { useContext } from "react";
1
+ import { useContext, useEffect, useState } from "react";
2
2
  import FlatTableRowContext from "../flat-table-row/__internal__/flat-table-row-context";
3
+ import { FlatTableThemeContext } from "../flat-table.component";
3
4
  export default (id => {
5
+ const {
6
+ getTabStopElementId
7
+ } = useContext(FlatTableThemeContext);
8
+ const [tabIndex, setTabIndex] = useState(-1);
4
9
  const {
5
10
  expandable,
6
11
  firstCellId,
@@ -8,13 +13,23 @@ export default (id => {
8
13
  leftPositions,
9
14
  rightPositions,
10
15
  onClick,
11
- onKeyDown
16
+ onKeyDown,
17
+ highlighted,
18
+ selected
12
19
  } = useContext(FlatTableRowContext);
13
20
  const leftPosition = leftPositions[id];
14
21
  const rightPosition = rightPositions[id];
15
22
  const makeCellSticky = leftPosition !== undefined || rightPosition !== undefined;
16
23
  const isFirstCell = id === firstCellId;
17
24
  const isExpandableCell = expandable && isFirstCell && firstColumnExpandable;
25
+ useEffect(() => {
26
+ const tabstopTimer = setTimeout(() => {
27
+ setTabIndex(isExpandableCell && getTabStopElementId() === id ? 0 : -1);
28
+ }, 0);
29
+ return () => {
30
+ clearTimeout(tabstopTimer);
31
+ };
32
+ }, [getTabStopElementId, isExpandableCell, id]);
18
33
  return {
19
34
  expandable,
20
35
  leftPosition,
@@ -23,6 +38,9 @@ export default (id => {
23
38
  onClick,
24
39
  onKeyDown,
25
40
  isFirstCell,
26
- isExpandableCell
41
+ isExpandableCell,
42
+ tabIndex,
43
+ isInHighlightedRow: highlighted,
44
+ isInSelectedRow: selected
27
45
  };
28
46
  });
@@ -1,11 +1,10 @@
1
1
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
- import React, { useRef, useState, useEffect, useContext } from "react";
2
+ import React, { useRef } from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import { StyledFlatTableCell, StyledCellContent } from "./flat-table-cell.style";
5
5
  import Icon from "../../icon";
6
- import { FlatTableThemeContext } from "../flat-table.component";
7
6
  import guid from "../../../__internal__/utils/helpers/guid";
8
- import useCalculateStickyCells from "../__internal__/use-calculate-sticky-cells";
7
+ import useTableCell from "../__internal__/use-table-cell";
9
8
  export const FlatTableCell = ({
10
9
  align = "left",
11
10
  children,
@@ -18,12 +17,7 @@ export const FlatTableCell = ({
18
17
  id,
19
18
  ...rest
20
19
  }) => {
21
- const ref = useRef(null);
22
20
  const internalId = useRef(id || guid());
23
- const [tabIndex, setTabIndex] = useState(-1);
24
- const {
25
- selectedId
26
- } = useContext(FlatTableThemeContext);
27
21
  const {
28
22
  leftPosition,
29
23
  rightPosition,
@@ -32,17 +26,16 @@ export const FlatTableCell = ({
32
26
  onKeyDown,
33
27
  isFirstCell,
34
28
  isExpandableCell,
35
- makeCellSticky
36
- } = useCalculateStickyCells(internalId.current);
37
- useEffect(() => {
38
- setTabIndex(isExpandableCell && selectedId === internalId.current ? 0 : -1);
39
- }, [selectedId, isExpandableCell]);
29
+ makeCellSticky,
30
+ isInHighlightedRow,
31
+ isInSelectedRow,
32
+ tabIndex
33
+ } = useTableCell(internalId.current);
40
34
  return /*#__PURE__*/React.createElement(StyledFlatTableCell, _extends({
41
35
  leftPosition: leftPosition,
42
36
  rightPosition: rightPosition,
43
37
  makeCellSticky: makeCellSticky,
44
38
  className: makeCellSticky ? "isSticky" : undefined,
45
- ref: ref,
46
39
  align: align,
47
40
  "data-element": "flat-table-cell",
48
41
  pl: pl,
@@ -56,6 +49,9 @@ export const FlatTableCell = ({
56
49
  colSpan: Number(colspan)
57
50
  }, rowspan !== undefined && {
58
51
  rowSpan: Number(rowspan)
52
+ }, {
53
+ "data-selected": isInSelectedRow && isExpandableCell,
54
+ "data-highlighted": isInHighlightedRow && isExpandableCell
59
55
  }, rest, {
60
56
  id: internalId.current
61
57
  }), /*#__PURE__*/React.createElement(StyledCellContent, {
@@ -4,7 +4,7 @@ import PropTypes from "prop-types";
4
4
  import StyledFlatTableHeader from "./flat-table-header.style";
5
5
  import { FlatTableThemeContext } from "../flat-table.component";
6
6
  import guid from "../../../__internal__/utils/helpers/guid";
7
- import useCalculateStickyCells from "../__internal__/use-calculate-sticky-cells";
7
+ import useTableCell from "../__internal__/use-table-cell";
8
8
  export const FlatTableHeader = ({
9
9
  align,
10
10
  children,
@@ -25,7 +25,7 @@ export const FlatTableHeader = ({
25
25
  leftPosition,
26
26
  rightPosition,
27
27
  makeCellSticky
28
- } = useCalculateStickyCells(internalId.current);
28
+ } = useTableCell(internalId.current);
29
29
  return /*#__PURE__*/React.createElement(StyledFlatTableHeader, _extends({
30
30
  ref: ref,
31
31
  leftPosition: leftPosition,
@@ -7,6 +7,8 @@ export interface FlatTableRowContextProps {
7
7
  leftPositions: Record<string, number>;
8
8
  rightPositions: Record<string, number>;
9
9
  firstColumnExpandable?: boolean;
10
+ highlighted?: boolean;
11
+ selected?: boolean;
10
12
  }
11
13
  declare const _default: React.Context<FlatTableRowContextProps>;
12
14
  export default _default;
@@ -93,8 +93,7 @@ const FlatTableRow = /*#__PURE__*/React.forwardRef(({
93
93
  const {
94
94
  colorTheme,
95
95
  size,
96
- setSelectedId,
97
- selectedId
96
+ getTabStopElementId
98
97
  } = useContext(FlatTableThemeContext);
99
98
  const {
100
99
  isInSidebar
@@ -141,13 +140,8 @@ const FlatTableRow = /*#__PURE__*/React.forwardRef(({
141
140
  setIsExpanded(expanded);
142
141
  }, [expanded]);
143
142
  useEffect(() => {
144
- if (highlighted || selected) {
145
- setSelectedId(internalId.current);
146
- }
147
- }, [highlighted, selected, setSelectedId]);
148
- useEffect(() => {
149
- setTabIndex(selectedId === internalId.current ? 0 : -1);
150
- }, [selectedId]);
143
+ setTabIndex(getTabStopElementId() === internalId.current ? 0 : -1);
144
+ }, [getTabStopElementId]);
151
145
  const {
152
146
  isSubRow,
153
147
  firstRowId,
@@ -183,7 +177,9 @@ const FlatTableRow = /*#__PURE__*/React.forwardRef(({
183
177
  horizontalBorderSize: horizontalBorderSize,
184
178
  draggable: draggable,
185
179
  totalChildren: cellsArray.length,
186
- id: internalId.current
180
+ id: internalId.current,
181
+ "data-selected": selected && expandableArea === "wholeRow",
182
+ "data-highlighted": highlighted && expandableArea === "wholeRow"
187
183
  }, interactiveRowProps, rest), /*#__PURE__*/React.createElement(FlatTableRowContext.Provider, {
188
184
  value: {
189
185
  firstCellId,
@@ -192,7 +188,9 @@ const FlatTableRow = /*#__PURE__*/React.forwardRef(({
192
188
  rightPositions,
193
189
  firstColumnExpandable,
194
190
  onKeyDown: handleCellKeyDown,
195
- onClick: () => toggleExpanded()
191
+ onClick: () => toggleExpanded(),
192
+ highlighted,
193
+ selected
196
194
  }
197
195
  }, children));
198
196
  const draggableComponent = () => /*#__PURE__*/React.createElement(FlatTableRowDraggable, {
@@ -1,12 +1,11 @@
1
1
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
- import React, { useCallback, useContext, useState, useRef, useEffect } from "react";
2
+ import React, { useCallback, useRef } from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import Icon from "../../icon";
5
5
  import { StyledFlatTableRowHeader, StyledFlatTableRowHeaderContent } from "./flat-table-row-header.style";
6
- import { FlatTableThemeContext } from "../flat-table.component";
7
6
  import guid from "../../../__internal__/utils/helpers/guid";
8
7
  import tagComponent from "../../../__internal__/utils/helpers/tags/tags";
9
- import useCalculateStickyCells from "../__internal__/use-calculate-sticky-cells";
8
+ import useTableCell from "../__internal__/use-table-cell";
10
9
  export const FlatTableRowHeader = ({
11
10
  align = "left",
12
11
  children,
@@ -22,10 +21,6 @@ export const FlatTableRowHeader = ({
22
21
  ...rest
23
22
  }) => {
24
23
  const internalId = useRef(id || guid());
25
- const [tabIndex, setTabIndex] = useState(-1);
26
- const {
27
- selectedId
28
- } = useContext(FlatTableThemeContext);
29
24
  const {
30
25
  leftPosition,
31
26
  rightPosition,
@@ -33,11 +28,11 @@ export const FlatTableRowHeader = ({
33
28
  onClick,
34
29
  onKeyDown,
35
30
  isFirstCell,
36
- isExpandableCell
37
- } = useCalculateStickyCells(internalId.current);
38
- useEffect(() => {
39
- setTabIndex(isExpandableCell && selectedId === internalId.current ? 0 : -1);
40
- }, [selectedId, isExpandableCell]);
31
+ isExpandableCell,
32
+ tabIndex,
33
+ isInHighlightedRow,
34
+ isInSelectedRow
35
+ } = useTableCell(internalId.current);
41
36
  const handleOnClick = useCallback(ev => {
42
37
  if (isExpandableCell && onClick) onClick(ev);
43
38
  }, [isExpandableCell, onClick]);
@@ -67,6 +62,9 @@ export const FlatTableRowHeader = ({
67
62
  colSpan: Number(colspan)
68
63
  }, rowspan !== undefined && {
69
64
  rowSpan: Number(rowspan)
65
+ }, {
66
+ "data-selected": isInSelectedRow && isExpandableCell,
67
+ "data-highlighted": isInHighlightedRow && isExpandableCell
70
68
  }, rest, {
71
69
  id: internalId.current
72
70
  }), /*#__PURE__*/React.createElement(StyledFlatTableRowHeaderContent, {
@@ -31,8 +31,7 @@ export interface FlatTableProps extends MarginProps {
31
31
  width?: string;
32
32
  }
33
33
  export interface FlatTableThemeContextProps extends Pick<FlatTableProps, "colorTheme" | "size"> {
34
- selectedId?: string;
35
- setSelectedId: (id: string) => void;
34
+ getTabStopElementId: () => string;
36
35
  }
37
36
  export declare const FlatTableThemeContext: React.Context<FlatTableThemeContextProps>;
38
37
  export declare const FlatTable: {
@@ -5,7 +5,7 @@ import { StyledFlatTableWrapper, StyledFlatTable, StyledFlatTableFooter, StyledT
5
5
  import { DrawerSidebarContext } from "../drawer";
6
6
  import Events from "../../__internal__/utils/helpers/events/events";
7
7
  export const FlatTableThemeContext = /*#__PURE__*/React.createContext({
8
- setSelectedId: () => {}
8
+ getTabStopElementId: () => ""
9
9
  });
10
10
  const FOCUSABLE_ROW_AND_CELL_QUERY = "tbody tr[tabindex], tbody tr td[tabindex], tbody tr th[tabindex]";
11
11
  export const FlatTable = ({
@@ -31,7 +31,6 @@ export const FlatTable = ({
31
31
  const [hasHorizontalScrollbar, setHasHorizontalScrollbar] = useState(false);
32
32
  const [firstColRowSpanIndex, setFirstColRowSpanIndex] = useState(-1);
33
33
  const [lastColRowSpanIndex, setLastColRowSpanIndex] = useState(-1);
34
- const [selectedId, setSelectedId] = useState("");
35
34
  const addDefaultHeight = !height && (hasStickyHead || hasStickyFooter);
36
35
  const tableStylingProps = {
37
36
  caption,
@@ -124,32 +123,14 @@ export const FlatTable = ({
124
123
  }
125
124
  }
126
125
  };
127
- useLayoutEffect(() => {
128
- const findSelectedId = () => {
129
- const firstfocusableElement = tableRef.current?.querySelector(FOCUSABLE_ROW_AND_CELL_QUERY);
130
-
131
- // if no other menu item is selected, we need to make the first row a tab stop
132
- if (firstfocusableElement && !selectedId) {
133
- const currentlySelectedId = firstfocusableElement?.getAttribute("id");
134
-
135
- /* istanbul ignore else */
136
- if (currentlySelectedId && selectedId !== currentlySelectedId) {
137
- setSelectedId(currentlySelectedId);
138
- }
139
- }
140
- };
141
- const observer = new MutationObserver(findSelectedId);
126
+ const getTabStopElementId = () => {
127
+ const focusableElements = Array.from(tableRef.current?.querySelectorAll(FOCUSABLE_ROW_AND_CELL_QUERY) || /* istanbul ignore next */[]);
142
128
 
143
- /* istanbul ignore else */
144
- if (wrapperRef.current) {
145
- observer.observe(wrapperRef.current, {
146
- subtree: true,
147
- childList: true,
148
- attributes: true
149
- });
150
- }
151
- return () => observer.disconnect();
152
- }, [selectedId]);
129
+ // if no other row is selected/ highlighted, we need to make the first row/ cell a tab stop
130
+ const focusableElement = focusableElements.find(el => el.getAttribute("data-selected") === "true" || el.getAttribute("data-highlighted") === "true") || focusableElements[0];
131
+ const currentlySelectedId = focusableElement?.getAttribute("id") || "";
132
+ return currentlySelectedId;
133
+ };
153
134
  return /*#__PURE__*/React.createElement(StyledFlatTableWrapper, _extends({
154
135
  ref: wrapperRef,
155
136
  "data-component": "flat-table-wrapper",
@@ -184,8 +165,7 @@ export const FlatTable = ({
184
165
  value: {
185
166
  colorTheme,
186
167
  size,
187
- setSelectedId,
188
- selectedId
168
+ getTabStopElementId
189
169
  }
190
170
  }, children))), footer && /*#__PURE__*/React.createElement(StyledFlatTableFooter, {
191
171
  hasStickyFooter: hasStickyFooter
@@ -1,2 +1,2 @@
1
- export { default as useCalculateStickyCells } from "./use-calculate-sticky-cells";
1
+ export { default as useTableCell } from "./use-table-cell";
2
2
  export { default as buildPositionMap } from "./build-position-map";
@@ -9,12 +9,12 @@ Object.defineProperty(exports, "buildPositionMap", {
9
9
  return _buildPositionMap.default;
10
10
  }
11
11
  });
12
- Object.defineProperty(exports, "useCalculateStickyCells", {
12
+ Object.defineProperty(exports, "useTableCell", {
13
13
  enumerable: true,
14
14
  get: function () {
15
- return _useCalculateStickyCells.default;
15
+ return _useTableCell.default;
16
16
  }
17
17
  });
18
- var _useCalculateStickyCells = _interopRequireDefault(require("./use-calculate-sticky-cells"));
18
+ var _useTableCell = _interopRequireDefault(require("./use-table-cell"));
19
19
  var _buildPositionMap = _interopRequireDefault(require("./build-position-map"));
20
20
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -8,5 +8,8 @@ declare const _default: (id: string) => {
8
8
  onKeyDown: ((ev: import("react").KeyboardEvent<HTMLElement>) => void) | undefined;
9
9
  isFirstCell: boolean;
10
10
  isExpandableCell: boolean | undefined;
11
+ tabIndex: number;
12
+ isInHighlightedRow: boolean | undefined;
13
+ isInSelectedRow: boolean | undefined;
11
14
  };
12
15
  export default _default;
@@ -6,8 +6,13 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  var _react = require("react");
8
8
  var _flatTableRowContext = _interopRequireDefault(require("../flat-table-row/__internal__/flat-table-row-context"));
9
+ var _flatTable = require("../flat-table.component");
9
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
11
  var _default = id => {
12
+ const {
13
+ getTabStopElementId
14
+ } = (0, _react.useContext)(_flatTable.FlatTableThemeContext);
15
+ const [tabIndex, setTabIndex] = (0, _react.useState)(-1);
11
16
  const {
12
17
  expandable,
13
18
  firstCellId,
@@ -15,13 +20,23 @@ var _default = id => {
15
20
  leftPositions,
16
21
  rightPositions,
17
22
  onClick,
18
- onKeyDown
23
+ onKeyDown,
24
+ highlighted,
25
+ selected
19
26
  } = (0, _react.useContext)(_flatTableRowContext.default);
20
27
  const leftPosition = leftPositions[id];
21
28
  const rightPosition = rightPositions[id];
22
29
  const makeCellSticky = leftPosition !== undefined || rightPosition !== undefined;
23
30
  const isFirstCell = id === firstCellId;
24
31
  const isExpandableCell = expandable && isFirstCell && firstColumnExpandable;
32
+ (0, _react.useEffect)(() => {
33
+ const tabstopTimer = setTimeout(() => {
34
+ setTabIndex(isExpandableCell && getTabStopElementId() === id ? 0 : -1);
35
+ }, 0);
36
+ return () => {
37
+ clearTimeout(tabstopTimer);
38
+ };
39
+ }, [getTabStopElementId, isExpandableCell, id]);
25
40
  return {
26
41
  expandable,
27
42
  leftPosition,
@@ -30,7 +45,10 @@ var _default = id => {
30
45
  onClick,
31
46
  onKeyDown,
32
47
  isFirstCell,
33
- isExpandableCell
48
+ isExpandableCell,
49
+ tabIndex,
50
+ isInHighlightedRow: highlighted,
51
+ isInSelectedRow: selected
34
52
  };
35
53
  };
36
54
  exports.default = _default;
@@ -8,9 +8,8 @@ var _react = _interopRequireWildcard(require("react"));
8
8
  var _propTypes = _interopRequireDefault(require("prop-types"));
9
9
  var _flatTableCell = require("./flat-table-cell.style");
10
10
  var _icon = _interopRequireDefault(require("../../icon"));
11
- var _flatTable = require("../flat-table.component");
12
11
  var _guid = _interopRequireDefault(require("../../../__internal__/utils/helpers/guid"));
13
- var _useCalculateStickyCells = _interopRequireDefault(require("../__internal__/use-calculate-sticky-cells"));
12
+ var _useTableCell = _interopRequireDefault(require("../__internal__/use-table-cell"));
14
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
14
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
16
15
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && 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; }
@@ -27,12 +26,7 @@ const FlatTableCell = ({
27
26
  id,
28
27
  ...rest
29
28
  }) => {
30
- const ref = (0, _react.useRef)(null);
31
29
  const internalId = (0, _react.useRef)(id || (0, _guid.default)());
32
- const [tabIndex, setTabIndex] = (0, _react.useState)(-1);
33
- const {
34
- selectedId
35
- } = (0, _react.useContext)(_flatTable.FlatTableThemeContext);
36
30
  const {
37
31
  leftPosition,
38
32
  rightPosition,
@@ -41,17 +35,16 @@ const FlatTableCell = ({
41
35
  onKeyDown,
42
36
  isFirstCell,
43
37
  isExpandableCell,
44
- makeCellSticky
45
- } = (0, _useCalculateStickyCells.default)(internalId.current);
46
- (0, _react.useEffect)(() => {
47
- setTabIndex(isExpandableCell && selectedId === internalId.current ? 0 : -1);
48
- }, [selectedId, isExpandableCell]);
38
+ makeCellSticky,
39
+ isInHighlightedRow,
40
+ isInSelectedRow,
41
+ tabIndex
42
+ } = (0, _useTableCell.default)(internalId.current);
49
43
  return /*#__PURE__*/_react.default.createElement(_flatTableCell.StyledFlatTableCell, _extends({
50
44
  leftPosition: leftPosition,
51
45
  rightPosition: rightPosition,
52
46
  makeCellSticky: makeCellSticky,
53
47
  className: makeCellSticky ? "isSticky" : undefined,
54
- ref: ref,
55
48
  align: align,
56
49
  "data-element": "flat-table-cell",
57
50
  pl: pl,
@@ -65,6 +58,9 @@ const FlatTableCell = ({
65
58
  colSpan: Number(colspan)
66
59
  }, rowspan !== undefined && {
67
60
  rowSpan: Number(rowspan)
61
+ }, {
62
+ "data-selected": isInSelectedRow && isExpandableCell,
63
+ "data-highlighted": isInHighlightedRow && isExpandableCell
68
64
  }, rest, {
69
65
  id: internalId.current
70
66
  }), /*#__PURE__*/_react.default.createElement(_flatTableCell.StyledCellContent, {
@@ -9,7 +9,7 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
9
9
  var _flatTableHeader = _interopRequireDefault(require("./flat-table-header.style"));
10
10
  var _flatTable = require("../flat-table.component");
11
11
  var _guid = _interopRequireDefault(require("../../../__internal__/utils/helpers/guid"));
12
- var _useCalculateStickyCells = _interopRequireDefault(require("../__internal__/use-calculate-sticky-cells"));
12
+ var _useTableCell = _interopRequireDefault(require("../__internal__/use-table-cell"));
13
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
14
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
15
15
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && 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; }
@@ -34,7 +34,7 @@ const FlatTableHeader = ({
34
34
  leftPosition,
35
35
  rightPosition,
36
36
  makeCellSticky
37
- } = (0, _useCalculateStickyCells.default)(internalId.current);
37
+ } = (0, _useTableCell.default)(internalId.current);
38
38
  return /*#__PURE__*/_react.default.createElement(_flatTableHeader.default, _extends({
39
39
  ref: ref,
40
40
  leftPosition: leftPosition,
@@ -7,6 +7,8 @@ export interface FlatTableRowContextProps {
7
7
  leftPositions: Record<string, number>;
8
8
  rightPositions: Record<string, number>;
9
9
  firstColumnExpandable?: boolean;
10
+ highlighted?: boolean;
11
+ selected?: boolean;
10
12
  }
11
13
  declare const _default: React.Context<FlatTableRowContextProps>;
12
14
  export default _default;
@@ -102,8 +102,7 @@ const FlatTableRow = /*#__PURE__*/_react.default.forwardRef(({
102
102
  const {
103
103
  colorTheme,
104
104
  size,
105
- setSelectedId,
106
- selectedId
105
+ getTabStopElementId
107
106
  } = (0, _react.useContext)(_flatTable.FlatTableThemeContext);
108
107
  const {
109
108
  isInSidebar
@@ -150,13 +149,8 @@ const FlatTableRow = /*#__PURE__*/_react.default.forwardRef(({
150
149
  setIsExpanded(expanded);
151
150
  }, [expanded]);
152
151
  (0, _react.useEffect)(() => {
153
- if (highlighted || selected) {
154
- setSelectedId(internalId.current);
155
- }
156
- }, [highlighted, selected, setSelectedId]);
157
- (0, _react.useEffect)(() => {
158
- setTabIndex(selectedId === internalId.current ? 0 : -1);
159
- }, [selectedId]);
152
+ setTabIndex(getTabStopElementId() === internalId.current ? 0 : -1);
153
+ }, [getTabStopElementId]);
160
154
  const {
161
155
  isSubRow,
162
156
  firstRowId,
@@ -192,7 +186,9 @@ const FlatTableRow = /*#__PURE__*/_react.default.forwardRef(({
192
186
  horizontalBorderSize: horizontalBorderSize,
193
187
  draggable: draggable,
194
188
  totalChildren: cellsArray.length,
195
- id: internalId.current
189
+ id: internalId.current,
190
+ "data-selected": selected && expandableArea === "wholeRow",
191
+ "data-highlighted": highlighted && expandableArea === "wholeRow"
196
192
  }, interactiveRowProps, rest), /*#__PURE__*/_react.default.createElement(_flatTableRowContext.default.Provider, {
197
193
  value: {
198
194
  firstCellId,
@@ -201,7 +197,9 @@ const FlatTableRow = /*#__PURE__*/_react.default.forwardRef(({
201
197
  rightPositions,
202
198
  firstColumnExpandable,
203
199
  onKeyDown: handleCellKeyDown,
204
- onClick: () => toggleExpanded()
200
+ onClick: () => toggleExpanded(),
201
+ highlighted,
202
+ selected
205
203
  }
206
204
  }, children));
207
205
  const draggableComponent = () => /*#__PURE__*/_react.default.createElement(_flatTableRowDraggable.default, {
@@ -8,10 +8,9 @@ var _react = _interopRequireWildcard(require("react"));
8
8
  var _propTypes = _interopRequireDefault(require("prop-types"));
9
9
  var _icon = _interopRequireDefault(require("../../icon"));
10
10
  var _flatTableRowHeader = require("./flat-table-row-header.style");
11
- var _flatTable = require("../flat-table.component");
12
11
  var _guid = _interopRequireDefault(require("../../../__internal__/utils/helpers/guid"));
13
12
  var _tags = _interopRequireDefault(require("../../../__internal__/utils/helpers/tags/tags"));
14
- var _useCalculateStickyCells = _interopRequireDefault(require("../__internal__/use-calculate-sticky-cells"));
13
+ var _useTableCell = _interopRequireDefault(require("../__internal__/use-table-cell"));
15
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
15
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
17
16
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && 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; }
@@ -31,10 +30,6 @@ const FlatTableRowHeader = ({
31
30
  ...rest
32
31
  }) => {
33
32
  const internalId = (0, _react.useRef)(id || (0, _guid.default)());
34
- const [tabIndex, setTabIndex] = (0, _react.useState)(-1);
35
- const {
36
- selectedId
37
- } = (0, _react.useContext)(_flatTable.FlatTableThemeContext);
38
33
  const {
39
34
  leftPosition,
40
35
  rightPosition,
@@ -42,11 +37,11 @@ const FlatTableRowHeader = ({
42
37
  onClick,
43
38
  onKeyDown,
44
39
  isFirstCell,
45
- isExpandableCell
46
- } = (0, _useCalculateStickyCells.default)(internalId.current);
47
- (0, _react.useEffect)(() => {
48
- setTabIndex(isExpandableCell && selectedId === internalId.current ? 0 : -1);
49
- }, [selectedId, isExpandableCell]);
40
+ isExpandableCell,
41
+ tabIndex,
42
+ isInHighlightedRow,
43
+ isInSelectedRow
44
+ } = (0, _useTableCell.default)(internalId.current);
50
45
  const handleOnClick = (0, _react.useCallback)(ev => {
51
46
  if (isExpandableCell && onClick) onClick(ev);
52
47
  }, [isExpandableCell, onClick]);
@@ -76,6 +71,9 @@ const FlatTableRowHeader = ({
76
71
  colSpan: Number(colspan)
77
72
  }, rowspan !== undefined && {
78
73
  rowSpan: Number(rowspan)
74
+ }, {
75
+ "data-selected": isInSelectedRow && isExpandableCell,
76
+ "data-highlighted": isInHighlightedRow && isExpandableCell
79
77
  }, rest, {
80
78
  id: internalId.current
81
79
  }), /*#__PURE__*/_react.default.createElement(_flatTableRowHeader.StyledFlatTableRowHeaderContent, {
@@ -31,8 +31,7 @@ export interface FlatTableProps extends MarginProps {
31
31
  width?: string;
32
32
  }
33
33
  export interface FlatTableThemeContextProps extends Pick<FlatTableProps, "colorTheme" | "size"> {
34
- selectedId?: string;
35
- setSelectedId: (id: string) => void;
34
+ getTabStopElementId: () => string;
36
35
  }
37
36
  export declare const FlatTableThemeContext: React.Context<FlatTableThemeContextProps>;
38
37
  export declare const FlatTable: {
@@ -14,7 +14,7 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
14
14
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && 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
15
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
16
16
  const FlatTableThemeContext = /*#__PURE__*/_react.default.createContext({
17
- setSelectedId: () => {}
17
+ getTabStopElementId: () => ""
18
18
  });
19
19
  exports.FlatTableThemeContext = FlatTableThemeContext;
20
20
  const FOCUSABLE_ROW_AND_CELL_QUERY = "tbody tr[tabindex], tbody tr td[tabindex], tbody tr th[tabindex]";
@@ -41,7 +41,6 @@ const FlatTable = ({
41
41
  const [hasHorizontalScrollbar, setHasHorizontalScrollbar] = (0, _react.useState)(false);
42
42
  const [firstColRowSpanIndex, setFirstColRowSpanIndex] = (0, _react.useState)(-1);
43
43
  const [lastColRowSpanIndex, setLastColRowSpanIndex] = (0, _react.useState)(-1);
44
- const [selectedId, setSelectedId] = (0, _react.useState)("");
45
44
  const addDefaultHeight = !height && (hasStickyHead || hasStickyFooter);
46
45
  const tableStylingProps = {
47
46
  caption,
@@ -134,32 +133,14 @@ const FlatTable = ({
134
133
  }
135
134
  }
136
135
  };
137
- (0, _react.useLayoutEffect)(() => {
138
- const findSelectedId = () => {
139
- const firstfocusableElement = tableRef.current?.querySelector(FOCUSABLE_ROW_AND_CELL_QUERY);
140
-
141
- // if no other menu item is selected, we need to make the first row a tab stop
142
- if (firstfocusableElement && !selectedId) {
143
- const currentlySelectedId = firstfocusableElement?.getAttribute("id");
144
-
145
- /* istanbul ignore else */
146
- if (currentlySelectedId && selectedId !== currentlySelectedId) {
147
- setSelectedId(currentlySelectedId);
148
- }
149
- }
150
- };
151
- const observer = new MutationObserver(findSelectedId);
136
+ const getTabStopElementId = () => {
137
+ const focusableElements = Array.from(tableRef.current?.querySelectorAll(FOCUSABLE_ROW_AND_CELL_QUERY) || /* istanbul ignore next */[]);
152
138
 
153
- /* istanbul ignore else */
154
- if (wrapperRef.current) {
155
- observer.observe(wrapperRef.current, {
156
- subtree: true,
157
- childList: true,
158
- attributes: true
159
- });
160
- }
161
- return () => observer.disconnect();
162
- }, [selectedId]);
139
+ // if no other row is selected/ highlighted, we need to make the first row/ cell a tab stop
140
+ const focusableElement = focusableElements.find(el => el.getAttribute("data-selected") === "true" || el.getAttribute("data-highlighted") === "true") || focusableElements[0];
141
+ const currentlySelectedId = focusableElement?.getAttribute("id") || "";
142
+ return currentlySelectedId;
143
+ };
163
144
  return /*#__PURE__*/_react.default.createElement(_flatTable.StyledFlatTableWrapper, _extends({
164
145
  ref: wrapperRef,
165
146
  "data-component": "flat-table-wrapper",
@@ -194,8 +175,7 @@ const FlatTable = ({
194
175
  value: {
195
176
  colorTheme,
196
177
  size,
197
- setSelectedId,
198
- selectedId
178
+ getTabStopElementId
199
179
  }
200
180
  }, children))), footer && /*#__PURE__*/_react.default.createElement(_flatTable.StyledFlatTableFooter, {
201
181
  hasStickyFooter: hasStickyFooter
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "carbon-react",
3
- "version": "120.3.0",
3
+ "version": "120.3.1",
4
4
  "description": "A library of reusable React components for easily building user interfaces.",
5
5
  "files": [
6
6
  "lib",