carbon-react 120.0.0 → 120.2.0

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 (78) hide show
  1. package/esm/__spec_helper__/test-utils.js +16 -8
  2. package/esm/components/button-toggle/button-toggle-group/button-toggle-group.component.js +2 -0
  3. package/esm/components/flat-table/__internal__/build-position-map.d.ts +2 -0
  4. package/esm/components/flat-table/__internal__/build-position-map.js +14 -0
  5. package/esm/components/flat-table/__internal__/index.d.ts +2 -0
  6. package/esm/components/flat-table/__internal__/index.js +2 -0
  7. package/esm/components/flat-table/__internal__/use-calculate-sticky-cells.d.ts +12 -0
  8. package/esm/components/flat-table/__internal__/use-calculate-sticky-cells.js +28 -0
  9. package/esm/components/flat-table/flat-table-cell/flat-table-cell.component.d.ts +2 -41
  10. package/esm/components/flat-table/flat-table-cell/flat-table-cell.component.js +26 -25
  11. package/esm/components/flat-table/flat-table-cell/flat-table-cell.style.d.ts +7 -2
  12. package/esm/components/flat-table/flat-table-checkbox/flat-table-checkbox.component.d.ts +3 -25
  13. package/esm/components/flat-table/flat-table-checkbox/flat-table-checkbox.component.js +21 -14
  14. package/esm/components/flat-table/flat-table-checkbox/flat-table-checkbox.style.d.ts +3 -1
  15. package/esm/components/flat-table/flat-table-head/flat-table-head.component.d.ts +4 -0
  16. package/esm/components/flat-table/flat-table-head/flat-table-head.component.js +21 -24
  17. package/esm/components/flat-table/flat-table-header/flat-table-header.component.d.ts +2 -26
  18. package/esm/components/flat-table/flat-table-header/flat-table-header.component.js +15 -13
  19. package/esm/components/flat-table/flat-table-header/flat-table-header.style.d.ts +3 -1
  20. package/esm/components/flat-table/flat-table-row/__internal__/flat-table-row-context.d.ts +12 -0
  21. package/esm/components/flat-table/flat-table-row/__internal__/flat-table-row-context.js +6 -0
  22. package/esm/components/flat-table/flat-table-row/__internal__/flat-table-row-draggable.component.d.ts +3 -1
  23. package/esm/components/flat-table/flat-table-row/__internal__/flat-table-row-draggable.component.js +17 -3
  24. package/esm/components/flat-table/flat-table-row/__internal__/sub-row-provider.d.ts +15 -0
  25. package/esm/components/flat-table/flat-table-row/__internal__/sub-row-provider.js +28 -0
  26. package/esm/components/flat-table/flat-table-row/flat-table-row.component.d.ts +1 -15
  27. package/esm/components/flat-table/flat-table-row/flat-table-row.component.js +85 -74
  28. package/esm/components/flat-table/flat-table-row/flat-table-row.style.d.ts +4 -1
  29. package/esm/components/flat-table/flat-table-row/flat-table-row.style.js +1 -9
  30. package/esm/components/flat-table/flat-table-row-header/flat-table-row-header.component.d.ts +4 -42
  31. package/esm/components/flat-table/flat-table-row-header/flat-table-row-header.component.js +33 -20
  32. package/esm/components/flat-table/flat-table-row-header/flat-table-row-header.style.d.ts +7 -1
  33. package/esm/components/flat-table/flat-table-row-header/flat-table-row-header.style.js +5 -1
  34. package/esm/components/flat-table/flat-table.component.js +24 -7
  35. package/esm/components/heading/heading.style.d.ts +1 -1
  36. package/esm/components/typography/typography.component.d.ts +4 -1
  37. package/esm/components/typography/typography.component.js +3 -1
  38. package/esm/components/typography/typography.style.js +4 -1
  39. package/lib/__spec_helper__/test-utils.js +16 -8
  40. package/lib/components/button-toggle/button-toggle-group/button-toggle-group.component.js +2 -0
  41. package/lib/components/flat-table/__internal__/build-position-map.d.ts +2 -0
  42. package/lib/components/flat-table/__internal__/build-position-map.js +21 -0
  43. package/lib/components/flat-table/__internal__/index.d.ts +2 -0
  44. package/lib/components/flat-table/__internal__/index.js +20 -0
  45. package/lib/components/flat-table/__internal__/package.json +6 -0
  46. package/lib/components/flat-table/__internal__/use-calculate-sticky-cells.d.ts +12 -0
  47. package/lib/components/flat-table/__internal__/use-calculate-sticky-cells.js +36 -0
  48. package/lib/components/flat-table/flat-table-cell/flat-table-cell.component.d.ts +2 -41
  49. package/lib/components/flat-table/flat-table-cell/flat-table-cell.component.js +25 -24
  50. package/lib/components/flat-table/flat-table-cell/flat-table-cell.style.d.ts +7 -2
  51. package/lib/components/flat-table/flat-table-checkbox/flat-table-checkbox.component.d.ts +3 -25
  52. package/lib/components/flat-table/flat-table-checkbox/flat-table-checkbox.component.js +20 -13
  53. package/lib/components/flat-table/flat-table-checkbox/flat-table-checkbox.style.d.ts +3 -1
  54. package/lib/components/flat-table/flat-table-head/flat-table-head.component.d.ts +4 -0
  55. package/lib/components/flat-table/flat-table-head/flat-table-head.component.js +23 -25
  56. package/lib/components/flat-table/flat-table-header/flat-table-header.component.d.ts +2 -26
  57. package/lib/components/flat-table/flat-table-header/flat-table-header.component.js +14 -12
  58. package/lib/components/flat-table/flat-table-header/flat-table-header.style.d.ts +3 -1
  59. package/lib/components/flat-table/flat-table-row/__internal__/flat-table-row-context.d.ts +12 -0
  60. package/lib/components/flat-table/flat-table-row/__internal__/flat-table-row-context.js +13 -0
  61. package/lib/components/flat-table/flat-table-row/__internal__/flat-table-row-draggable.component.d.ts +3 -1
  62. package/lib/components/flat-table/flat-table-row/__internal__/flat-table-row-draggable.component.js +17 -3
  63. package/lib/components/flat-table/flat-table-row/__internal__/sub-row-provider.d.ts +15 -0
  64. package/lib/components/flat-table/flat-table-row/__internal__/sub-row-provider.js +38 -0
  65. package/lib/components/flat-table/flat-table-row/flat-table-row.component.d.ts +1 -15
  66. package/lib/components/flat-table/flat-table-row/flat-table-row.component.js +84 -73
  67. package/lib/components/flat-table/flat-table-row/flat-table-row.style.d.ts +4 -1
  68. package/lib/components/flat-table/flat-table-row/flat-table-row.style.js +1 -9
  69. package/lib/components/flat-table/flat-table-row-header/flat-table-row-header.component.d.ts +4 -42
  70. package/lib/components/flat-table/flat-table-row-header/flat-table-row-header.component.js +32 -19
  71. package/lib/components/flat-table/flat-table-row-header/flat-table-row-header.style.d.ts +7 -1
  72. package/lib/components/flat-table/flat-table-row-header/flat-table-row-header.style.js +5 -1
  73. package/lib/components/flat-table/flat-table.component.js +24 -7
  74. package/lib/components/heading/heading.style.d.ts +1 -1
  75. package/lib/components/typography/typography.component.d.ts +4 -1
  76. package/lib/components/typography/typography.component.js +3 -1
  77. package/lib/components/typography/typography.style.js +4 -1
  78. package/package.json +3 -2
@@ -5,7 +5,8 @@ const FlatTableRowDraggable = ({
5
5
  children,
6
6
  id,
7
7
  findItem,
8
- moveItem
8
+ moveItem,
9
+ rowRef
9
10
  }) => {
10
11
  const originalIndex = Number(findItem?.(id).index);
11
12
  const [{
@@ -46,7 +47,17 @@ const FlatTableRowDraggable = ({
46
47
  key: originalIndex,
47
48
  id,
48
49
  isDragging,
49
- ref: node => drag(drop(node))
50
+ ref: node => {
51
+ drag(drop(node));
52
+ /* istanbul ignore else */
53
+ if (rowRef) {
54
+ if (typeof rowRef === "function") {
55
+ rowRef(node);
56
+ } else {
57
+ rowRef.current = node;
58
+ }
59
+ }
60
+ }
50
61
  });
51
62
  };
52
63
  FlatTableRowDraggable.propTypes = {
@@ -54,7 +65,10 @@ FlatTableRowDraggable.propTypes = {
54
65
  "draggable": PropTypes.bool,
55
66
  "findItem": PropTypes.func,
56
67
  "id": PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
57
- "moveItem": PropTypes.func
68
+ "moveItem": PropTypes.func,
69
+ "rowRef": PropTypes.oneOfType([PropTypes.func, PropTypes.shape({
70
+ "current": PropTypes.oneOfType([PropTypes.oneOf([null]), PropTypes.object]).isRequired
71
+ })])
58
72
  };
59
73
  export { FlatTableRowDraggable };
60
74
  FlatTableRowDraggable.displayName = "FlatTableRowDraggable";
@@ -0,0 +1,15 @@
1
+ import React from "react";
2
+ export interface SubRowContextProps {
3
+ isSubRow?: boolean;
4
+ firstRowId: string;
5
+ addRow: (id: string) => void;
6
+ removeRow: (id: string) => void;
7
+ }
8
+ export declare const SubRowContext: React.Context<SubRowContextProps>;
9
+ declare const SubRowProvider: {
10
+ ({ children }: {
11
+ children: React.ReactNode;
12
+ }): React.JSX.Element;
13
+ displayName: string;
14
+ };
15
+ export default SubRowProvider;
@@ -0,0 +1,28 @@
1
+ import React, { createContext, useCallback, useState } from "react";
2
+ export const SubRowContext = /*#__PURE__*/createContext({
3
+ isSubRow: false,
4
+ firstRowId: "",
5
+ addRow: () => {},
6
+ removeRow: () => {}
7
+ });
8
+ const SubRowProvider = ({
9
+ children
10
+ }) => {
11
+ const [rowIds, setRowIds] = useState([]);
12
+ const addRow = useCallback(id => {
13
+ setRowIds(p => [...p, id]);
14
+ }, []);
15
+ const removeRow = useCallback(id => {
16
+ setRowIds(p => p.filter(rowId => rowId !== id));
17
+ }, []);
18
+ return /*#__PURE__*/React.createElement(SubRowContext.Provider, {
19
+ value: {
20
+ isSubRow: true,
21
+ firstRowId: rowIds[0],
22
+ addRow,
23
+ removeRow
24
+ }
25
+ }, children);
26
+ };
27
+ SubRowProvider.displayName = "SubRowProvider";
28
+ export default SubRowProvider;
@@ -24,18 +24,6 @@ export interface FlatTableRowProps {
24
24
  selected?: boolean;
25
25
  /** Sub rows to be shown when the row is expanded, must be used with the `expandable` prop. */
26
26
  subRows?: React.ReactNode;
27
- /** @ignore @private */
28
- isSubRow?: boolean;
29
- /** @ignore @private */
30
- isFirstSubRow?: boolean;
31
- /** @ignore @private position in header if multiple rows */
32
- stickyOffset?: number;
33
- /** @ignore @private applies a border-left to the first child */
34
- applyBorderLeft?: boolean;
35
- /** ID for use in drag and drop functionality
36
- * @private
37
- * @ignore
38
- */
39
27
  id?: string | number;
40
28
  /**
41
29
  * @private
@@ -49,8 +37,6 @@ export interface FlatTableRowProps {
49
37
  moveItem?: FlatTableRowDraggableProps["moveItem"];
50
38
  /** @ignore @private position in header if multiple rows */
51
39
  draggable?: boolean;
52
- /** @ignore @private */
53
- ref?: React.RefObject<HTMLTableRowElement>;
54
40
  }
55
- export declare const FlatTableRow: React.ForwardRefExoticComponent<Pick<FlatTableRowProps, "draggable" | "id" | "children" | "onClick" | "selected" | "bgColor" | "expanded" | "findItem" | "moveItem" | "highlighted" | "expandable" | "horizontalBorderColor" | "stickyOffset" | "isSubRow" | "isFirstSubRow" | "applyBorderLeft" | "horizontalBorderSize" | "expandableArea" | "subRows"> & React.RefAttributes<HTMLTableRowElement>>;
41
+ export declare const FlatTableRow: React.ForwardRefExoticComponent<FlatTableRowProps & React.RefAttributes<HTMLTableRowElement>>;
56
42
  export default FlatTableRow;
@@ -1,52 +1,88 @@
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, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
2
+ import React, { useContext, useEffect, useMemo, useRef, useState, useLayoutEffect } from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import invariant from "invariant";
5
5
  import Event from "../../../__internal__/utils/helpers/events";
6
6
  import StyledFlatTableRow from "./flat-table-row.style";
7
7
  import { DrawerSidebarContext } from "../../drawer";
8
- import FlatTableCheckbox from "../flat-table-checkbox";
9
8
  import FlatTableRowHeader from "../flat-table-row-header";
10
9
  import FlatTableRowDraggable from "./__internal__/flat-table-row-draggable.component";
11
10
  import { FlatTableThemeContext } from "../flat-table.component";
12
11
  import guid from "../../../__internal__/utils/helpers/guid";
12
+ import FlatTableRowContext from "./__internal__/flat-table-row-context";
13
+ import SubRowProvider, { SubRowContext } from "./__internal__/sub-row-provider";
14
+ import { buildPositionMap } from "../__internal__";
15
+ import { FlatTableHeadContext } from "../flat-table-head/flat-table-head.component";
13
16
  const FlatTableRow = /*#__PURE__*/React.forwardRef(({
14
17
  children,
15
18
  onClick,
16
19
  expandable,
17
20
  expandableArea = "wholeRow",
18
21
  expanded = false,
19
- isSubRow,
20
- isFirstSubRow,
21
- stickyOffset,
22
22
  highlighted,
23
23
  selected,
24
24
  subRows,
25
25
  bgColor,
26
26
  horizontalBorderColor,
27
27
  horizontalBorderSize = "small",
28
- applyBorderLeft,
29
28
  id,
30
29
  draggable,
31
30
  findItem,
32
31
  moveItem,
33
32
  ...rest
34
33
  }, ref) => {
35
- const internalId = useRef(id ?? guid());
34
+ const internalId = useRef(id ? String(id) : guid());
36
35
  const [isExpanded, setIsExpanded] = useState(expanded);
37
36
  let rowRef = useRef(null);
38
37
  if (ref) {
39
38
  rowRef = ref;
40
39
  }
41
40
  const firstColumnExpandable = expandableArea === "firstColumn";
42
- const [leftStickyCellWidths, setLeftStickyCellWidths] = useState([]);
43
- const [rightStickyCellWidths, setRightStickyCellWidths] = useState([]);
44
- const [leftPositions, setLeftPositions] = useState([]);
45
- const [rightPositions, setRightPositions] = useState([]);
46
- const childrenArray = useMemo(() => React.Children.toArray(children), [children]);
47
- const lhsRowHeaderIndex = useMemo(() => childrenArray.findIndex(child => /*#__PURE__*/React.isValidElement(child) && child.type.displayName === FlatTableRowHeader.displayName && child.props.stickyAlignment !== "right"), [childrenArray]);
48
- const rhsRowHeaderIndex = useMemo(() => childrenArray.findIndex(child => /*#__PURE__*/React.isValidElement(child) && child.type.displayName === FlatTableRowHeader.displayName && child.props.stickyAlignment === "right"), [childrenArray]);
41
+ const [leftPositions, setLeftPositions] = useState({});
42
+ const [rightPositions, setRightPositions] = useState({});
43
+ const [firstCellIndex, setFirstCellIndex] = useState(0);
44
+ const [lhsRowHeaderIndex, setLhsRowHeaderIndex] = useState(-1);
45
+ const [rhsRowHeaderIndex, setRhsRowHeaderIndex] = useState(-1);
46
+ const [firstCellId, setFirstCellId] = useState(null);
47
+ const [cellsArray, setCellsArray] = useState([]);
49
48
  const [tabIndex, setTabIndex] = useState(-1);
49
+ let interactiveRowProps = {};
50
+ useLayoutEffect(() => {
51
+ const checkForPositionUpdates = (updated, current) => {
52
+ const updatedKeys = Object.keys(updated);
53
+ const currentKeys = Object.keys(current);
54
+ if (updatedKeys.length !== currentKeys.length) {
55
+ return true;
56
+ }
57
+ return updatedKeys.some(key => updated[key] !== current[key]);
58
+ };
59
+ const cells = rowRef.current?.querySelectorAll("th, td");
60
+ const cellArray = Array.from(cells || []);
61
+ setCellsArray(cellArray);
62
+ const firstIndex = cellArray.findIndex(cell => cell.getAttribute("data-component") !== "flat-table-checkbox");
63
+ const lhsIndex = cellArray.findIndex(cell => cell.getAttribute("data-sticky-align") === "left");
64
+ const rhsIndex = cellArray.findIndex(cell => cell.getAttribute("data-sticky-align") === "right");
65
+ setLhsRowHeaderIndex(lhsIndex);
66
+ setRhsRowHeaderIndex(rhsIndex);
67
+ if (firstIndex !== -1) {
68
+ setFirstCellIndex(firstIndex);
69
+ setFirstCellId(cellArray[firstIndex].getAttribute("id"));
70
+ } else {
71
+ setFirstCellIndex(0);
72
+ }
73
+ if (lhsIndex !== -1) {
74
+ const updatedLeftPositions = buildPositionMap(cellArray.slice(0, lhsRowHeaderIndex + 1), "offsetWidth");
75
+ if (checkForPositionUpdates(updatedLeftPositions, leftPositions)) {
76
+ setLeftPositions(updatedLeftPositions);
77
+ }
78
+ }
79
+ if (rhsIndex !== -1) {
80
+ const updatedRightPositions = buildPositionMap(cellArray.slice(rhsRowHeaderIndex, cellArray.length).reverse(), "offsetWidth");
81
+ if (checkForPositionUpdates(updatedRightPositions, rightPositions)) {
82
+ setRightPositions(updatedRightPositions);
83
+ }
84
+ }
85
+ }, [children, leftPositions, lhsRowHeaderIndex, rhsRowHeaderIndex, rightPositions]);
50
86
  const noStickyColumnsOverlap = useMemo(() => {
51
87
  const hasLhsColumn = lhsRowHeaderIndex !== -1;
52
88
  const hasRhsColumn = rhsRowHeaderIndex !== -1;
@@ -63,22 +99,9 @@ const FlatTableRow = /*#__PURE__*/React.forwardRef(({
63
99
  const {
64
100
  isInSidebar
65
101
  } = useContext(DrawerSidebarContext);
66
- const reportCellWidth = useCallback((width, index) => {
67
- const isLeftSticky = index < lhsRowHeaderIndex;
68
- const copiedArray = isLeftSticky ? leftStickyCellWidths : rightStickyCellWidths;
69
- if (copiedArray[index] !== undefined) {
70
- copiedArray[index] = width;
71
- } else {
72
- copiedArray.push(width);
73
- }
74
- if (isLeftSticky) {
75
- setLeftStickyCellWidths(copiedArray);
76
- } else {
77
- setRightStickyCellWidths(copiedArray);
78
- }
79
- }, [lhsRowHeaderIndex, leftStickyCellWidths, rightStickyCellWidths]);
80
- let interactiveRowProps = {};
81
- const firstCellIndex = /*#__PURE__*/React.isValidElement(childrenArray[0]) && childrenArray[0].type === FlatTableCheckbox ? 1 : 0;
102
+ const {
103
+ stickyOffsets
104
+ } = useContext(FlatTableHeadContext);
82
105
  const toggleExpanded = () => setIsExpanded(!isExpanded);
83
106
  function onKeyDown(ev) {
84
107
  const isEnterOrSpaceKey = Event.isEnterKey(ev) || Event.isSpaceKey(ev);
@@ -114,32 +137,31 @@ const FlatTableRow = /*#__PURE__*/React.forwardRef(({
114
137
  toggleExpanded();
115
138
  }
116
139
  }
117
- const buildPositionArray = (setter, widthsArray, length) => {
118
- setter([0, ...Array.from({
119
- length
120
- }).map((_, index) => widthsArray.slice(0, index + 1).reduce((a, b) => a + b, 0), 0)]);
121
- };
122
- useLayoutEffect(() => {
123
- if (leftStickyCellWidths.length && lhsRowHeaderIndex !== -1) {
124
- buildPositionArray(setLeftPositions, leftStickyCellWidths, lhsRowHeaderIndex);
125
- }
126
- }, [lhsRowHeaderIndex, leftStickyCellWidths]);
127
- useLayoutEffect(() => {
128
- if (rightStickyCellWidths.length && rhsRowHeaderIndex !== -1) {
129
- buildPositionArray(setRightPositions, rightStickyCellWidths, childrenArray.length - (rhsRowHeaderIndex + 1));
130
- }
131
- }, [rhsRowHeaderIndex, rightStickyCellWidths, childrenArray]);
132
140
  useEffect(() => {
133
141
  setIsExpanded(expanded);
134
142
  }, [expanded]);
135
143
  useEffect(() => {
136
144
  if (highlighted || selected) {
137
- setSelectedId(String(internalId.current));
145
+ setSelectedId(internalId.current);
138
146
  }
139
147
  }, [highlighted, selected, setSelectedId]);
140
148
  useEffect(() => {
141
149
  setTabIndex(selectedId === internalId.current ? 0 : -1);
142
150
  }, [selectedId]);
151
+ const {
152
+ isSubRow,
153
+ firstRowId,
154
+ addRow,
155
+ removeRow
156
+ } = useContext(SubRowContext);
157
+ useEffect(() => {
158
+ const rowId = internalId.current;
159
+ addRow(rowId);
160
+ return () => {
161
+ removeRow(rowId);
162
+ };
163
+ }, [addRow, removeRow]);
164
+ const isFirstSubRow = firstRowId === internalId.current;
143
165
  const rowComponent = () => /*#__PURE__*/React.createElement(StyledFlatTableRow, _extends({
144
166
  isInSidebar: isInSidebar,
145
167
  expandable: expandable,
@@ -155,41 +177,33 @@ const FlatTableRow = /*#__PURE__*/React.forwardRef(({
155
177
  rhsRowHeaderIndex: rhsRowHeaderIndex,
156
178
  colorTheme: colorTheme,
157
179
  size: size,
158
- stickyOffset: stickyOffset,
180
+ stickyOffset: stickyOffsets[internalId.current],
159
181
  bgColor: bgColor,
160
182
  horizontalBorderColor: horizontalBorderColor,
161
183
  horizontalBorderSize: horizontalBorderSize,
162
- applyBorderLeft: applyBorderLeft,
163
184
  draggable: draggable,
164
- totalChildren: childrenArray.length,
165
- id: String(internalId.current)
166
- }, interactiveRowProps, rest), React.Children.map(children, (child, index) => {
167
- return /*#__PURE__*/React.isValidElement(child) && /*#__PURE__*/React.cloneElement(child, {
168
- expandable: expandable && index === firstCellIndex,
169
- onClick: expandable && index === firstCellIndex && firstColumnExpandable ? () => toggleExpanded() : undefined,
170
- onKeyDown: expandable && index === firstCellIndex && firstColumnExpandable ? handleCellKeyDown : undefined,
171
- cellIndex: index,
172
- reportCellWidth: index < lhsRowHeaderIndex || rhsRowHeaderIndex !== -1 && index > rhsRowHeaderIndex ? reportCellWidth : undefined,
173
- leftPosition: leftPositions[index],
174
- rightPosition: rightPositions[childrenArray.length - (index + 1)],
175
- ...child.props
176
- });
177
- }));
185
+ totalChildren: cellsArray.length,
186
+ id: internalId.current
187
+ }, interactiveRowProps, rest), /*#__PURE__*/React.createElement(FlatTableRowContext.Provider, {
188
+ value: {
189
+ firstCellId,
190
+ expandable,
191
+ leftPositions,
192
+ rightPositions,
193
+ firstColumnExpandable,
194
+ onKeyDown: handleCellKeyDown,
195
+ onClick: () => toggleExpanded()
196
+ }
197
+ }, children));
178
198
  const draggableComponent = () => /*#__PURE__*/React.createElement(FlatTableRowDraggable, {
179
199
  id: internalId.current,
180
200
  moveItem: moveItem,
181
- findItem: findItem
201
+ findItem: findItem,
202
+ rowRef: rowRef
182
203
  }, rowComponent());
183
- return /*#__PURE__*/React.createElement(React.Fragment, null, draggable ? draggableComponent() : rowComponent(), isExpanded && subRows && React.Children.map(subRows, (child, index) => child && /*#__PURE__*/React.cloneElement(child, {
184
- isSubRow: true,
185
- isFirstSubRow: index === 0,
186
- ...( /*#__PURE__*/React.isValidElement(child) && {
187
- ...child.props
188
- })
189
- })));
204
+ return /*#__PURE__*/React.createElement(React.Fragment, null, draggable ? draggableComponent() : rowComponent(), isExpanded && subRows && /*#__PURE__*/React.createElement(SubRowProvider, null, subRows));
190
205
  });
191
206
  FlatTableRow.propTypes = {
192
- "applyBorderLeft": PropTypes.bool,
193
207
  "bgColor": PropTypes.string,
194
208
  "children": PropTypes.node,
195
209
  "draggable": PropTypes.bool,
@@ -201,12 +215,9 @@ FlatTableRow.propTypes = {
201
215
  "horizontalBorderColor": PropTypes.string,
202
216
  "horizontalBorderSize": PropTypes.oneOf(["large", "medium", "small"]),
203
217
  "id": PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
204
- "isFirstSubRow": PropTypes.bool,
205
- "isSubRow": PropTypes.bool,
206
218
  "moveItem": PropTypes.func,
207
219
  "onClick": PropTypes.func,
208
220
  "selected": PropTypes.bool,
209
- "stickyOffset": PropTypes.number,
210
221
  "subRows": PropTypes.node
211
222
  };
212
223
  export { FlatTableRow };
@@ -1,6 +1,6 @@
1
1
  import { FlatTableProps } from "..";
2
2
  import { FlatTableRowProps } from "./flat-table-row.component";
3
- interface StyledFlatTableRowProps extends Pick<FlatTableRowProps, "bgColor" | "horizontalBorderColor" | "stickyOffset" | "expandable" | "selected" | "highlighted" | "isSubRow" | "isFirstSubRow" | "applyBorderLeft" | "draggable"> {
3
+ interface StyledFlatTableRowProps extends Pick<FlatTableRowProps, "bgColor" | "horizontalBorderColor" | "expandable" | "selected" | "highlighted" | "draggable"> {
4
4
  isRowInteractive?: boolean;
5
5
  isFirstColumnInteractive?: boolean;
6
6
  lhsRowHeaderIndex: number;
@@ -13,6 +13,9 @@ interface StyledFlatTableRowProps extends Pick<FlatTableRowProps, "bgColor" | "h
13
13
  size: FlatTableProps["size"];
14
14
  isDragging?: boolean;
15
15
  horizontalBorderSize: NonNullable<FlatTableRowProps["horizontalBorderSize"]>;
16
+ isSubRow?: boolean;
17
+ isFirstSubRow?: boolean;
18
+ stickyOffset?: number;
16
19
  }
17
20
  declare const StyledFlatTableRow: import("styled-components").StyledComponent<"tr", any, StyledFlatTableRowProps, never>;
18
21
  export default StyledFlatTableRow;
@@ -115,7 +115,6 @@ const StyledFlatTableRow = styled.tr`
115
115
  isFirstSubRow,
116
116
  size,
117
117
  theme,
118
- applyBorderLeft,
119
118
  isDragging,
120
119
  draggable
121
120
  }) => {
@@ -188,7 +187,7 @@ const StyledFlatTableRow = styled.tr`
188
187
  `}
189
188
  }
190
189
 
191
- ${stickyOffset !== undefined && stickyOffset > 0 && css`
190
+ ${stickyOffset !== undefined && css`
192
191
  && th {
193
192
  top: ${stickyOffset}px;
194
193
  }
@@ -300,13 +299,6 @@ const StyledFlatTableRow = styled.tr`
300
299
  }
301
300
  `}
302
301
 
303
-
304
- ${applyBorderLeft && css`
305
- th:first-of-type {
306
- border-left: 1px solid ${customBorderColor || borderColor(colorTheme)};
307
- }
308
- `}
309
-
310
302
  ${isInSidebar && css`
311
303
  ${allCellTypes} {
312
304
  background-color: ${bgColor || "var(--colorsUtilityMajor040)"};
@@ -1,7 +1,8 @@
1
1
  import React from "react";
2
2
  import { PaddingProps } from "styled-system";
3
3
  import { TableBorderSize, TableCellAlign } from "..";
4
- export interface FlatTableRowHeaderProps extends PaddingProps {
4
+ import { TagProps } from "../../../__internal__/utils/helpers/tags/tags";
5
+ export interface FlatTableRowHeaderProps extends PaddingProps, TagProps {
5
6
  /** Content alignment */
6
7
  align?: TableCellAlign;
7
8
  /** RowHeader content */
@@ -22,50 +23,11 @@ export interface FlatTableRowHeaderProps extends PaddingProps {
22
23
  colspan?: number | string;
23
24
  /** Number of rows that a header cell should span */
24
25
  rowspan?: number | string;
25
- /** Sets an id string on the DOM element */
26
+ /** Sets an id string on the element */
26
27
  id?: string;
27
- /**
28
- * @private
29
- * @ignore
30
- */
31
- expandable?: boolean;
32
- /**
33
- * @private
34
- * @ignore
35
- */
36
- onClick?: (ev: React.MouseEvent<HTMLElement>) => void;
37
- /**
38
- * @private
39
- * @ignore
40
- */
41
- onKeyDown?: (ev: React.KeyboardEvent<HTMLElement>) => void;
42
- /**
43
- * @private
44
- * @ignore
45
- * Sets the left position when sticky column found
46
- */
47
- leftPosition?: number;
48
- /**
49
- * @private
50
- * @ignore
51
- * Sets the right position when sticky column found
52
- */
53
- rightPosition?: number;
54
- /**
55
- * @private
56
- * @ignore
57
- * Index of cell within row
58
- */
59
- cellIndex?: number;
60
- /**
61
- * @private
62
- * @ignore
63
- * Callback to report the offsetWidth
64
- */
65
- reportCellWidth?: (offset: number, index?: number) => void;
66
28
  }
67
29
  export declare const FlatTableRowHeader: {
68
- ({ align, children, width, py, px, expandable, onClick, onKeyDown, leftPosition, rightPosition, truncate, title, stickyAlignment, colspan, rowspan, ...rest }: FlatTableRowHeaderProps): React.JSX.Element;
30
+ ({ align, children, width, py, px, truncate, title, stickyAlignment, colspan, rowspan, id, ...rest }: FlatTableRowHeaderProps): React.JSX.Element;
69
31
  displayName: string;
70
32
  };
71
33
  export default FlatTableRowHeader;
@@ -1,65 +1,78 @@
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, useEffect, useContext, useState, useRef } from "react";
2
+ import React, { useCallback, useContext, useState, useRef, useEffect } 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
6
  import { FlatTableThemeContext } from "../flat-table.component";
7
7
  import guid from "../../../__internal__/utils/helpers/guid";
8
+ import tagComponent from "../../../__internal__/utils/helpers/tags/tags";
9
+ import useCalculateStickyCells from "../__internal__/use-calculate-sticky-cells";
8
10
  export const FlatTableRowHeader = ({
9
11
  align = "left",
10
12
  children,
11
13
  width,
12
14
  py,
13
15
  px,
14
- expandable = false,
15
- onClick,
16
- onKeyDown,
17
- leftPosition,
18
- rightPosition,
19
16
  truncate,
20
17
  title,
21
18
  stickyAlignment = "left",
22
19
  colspan,
23
20
  rowspan,
21
+ id,
24
22
  ...rest
25
23
  }) => {
26
- const id = useRef(guid());
24
+ const internalId = useRef(id || guid());
27
25
  const [tabIndex, setTabIndex] = useState(-1);
28
26
  const {
29
27
  selectedId
30
28
  } = useContext(FlatTableThemeContext);
29
+ const {
30
+ leftPosition,
31
+ rightPosition,
32
+ expandable,
33
+ onClick,
34
+ onKeyDown,
35
+ isFirstCell,
36
+ isExpandableCell
37
+ } = useCalculateStickyCells(internalId.current);
38
+ useEffect(() => {
39
+ setTabIndex(isExpandableCell && selectedId === internalId.current ? 0 : -1);
40
+ }, [selectedId, isExpandableCell]);
31
41
  const handleOnClick = useCallback(ev => {
32
- if (expandable && onClick) onClick(ev);
33
- }, [expandable, onClick]);
42
+ if (isExpandableCell && onClick) onClick(ev);
43
+ }, [isExpandableCell, onClick]);
34
44
  const handleOnKeyDown = useCallback(ev => {
35
- if (expandable && onKeyDown) onKeyDown(ev);
36
- }, [expandable, onKeyDown]);
37
- useEffect(() => {
38
- setTabIndex(selectedId === id.current ? 0 : -1);
39
- }, [selectedId]);
45
+ if (isExpandableCell && onKeyDown) {
46
+ onKeyDown(ev);
47
+ }
48
+ }, [isExpandableCell, onKeyDown]);
40
49
  return /*#__PURE__*/React.createElement(StyledFlatTableRowHeader, _extends({
41
50
  leftPosition: stickyAlignment === "left" ? leftPosition || 0 : undefined,
42
51
  rightPosition: stickyAlignment === "right" ? rightPosition || 0 : undefined,
43
- align: align,
52
+ align: align
53
+ }, tagComponent("flat-table-row-header", {
44
54
  "data-element": "flat-table-row-header",
55
+ ...rest
56
+ }), {
45
57
  width: width,
46
58
  py: py || "10px",
47
59
  px: px || 3,
48
60
  onClick: handleOnClick,
49
- tabIndex: expandable && onClick ? tabIndex : undefined,
61
+ tabIndex: isExpandableCell ? tabIndex : undefined,
50
62
  onKeyDown: handleOnKeyDown,
51
63
  truncate: truncate,
52
64
  expandable: expandable,
53
- stickyAlignment: stickyAlignment,
54
- id: id.current
65
+ stickyAlignment: stickyAlignment
55
66
  }, colspan !== undefined && {
56
67
  colSpan: Number(colspan)
57
68
  }, rowspan !== undefined && {
58
69
  rowSpan: Number(rowspan)
59
- }, rest), /*#__PURE__*/React.createElement(StyledFlatTableRowHeaderContent, {
70
+ }, rest, {
71
+ id: internalId.current
72
+ }), /*#__PURE__*/React.createElement(StyledFlatTableRowHeaderContent, {
60
73
  title: truncate && !title && typeof children === "string" ? children : title,
61
74
  expandable: expandable
62
- }, expandable && /*#__PURE__*/React.createElement(Icon, {
75
+ }, expandable && isFirstCell && /*#__PURE__*/React.createElement(Icon, {
63
76
  type: "chevron_down_thick",
64
77
  bgSize: "extra-small",
65
78
  mr: "8px"
@@ -1,5 +1,11 @@
1
1
  import { FlatTableRowHeaderProps } from "./flat-table-row-header.component";
2
- declare const StyledFlatTableRowHeader: import("styled-components").StyledComponent<"th", any, FlatTableRowHeaderProps, never>;
2
+ declare const StyledFlatTableRowHeader: import("styled-components").StyledComponent<"th", any, {
3
+ "data-sticky-align": "left" | "right" | undefined;
4
+ } & FlatTableRowHeaderProps & {
5
+ expandable?: boolean | undefined;
6
+ leftPosition?: number | undefined;
7
+ rightPosition?: number | undefined;
8
+ }, "data-sticky-align">;
3
9
  declare const StyledFlatTableRowHeaderContent: import("styled-components").StyledComponent<"div", any, {
4
10
  expandable?: boolean | undefined;
5
11
  }, never>;
@@ -7,7 +7,11 @@ const verticalBorderSizes = {
7
7
  medium: "2px",
8
8
  large: "4px"
9
9
  };
10
- const StyledFlatTableRowHeader = styled.th`
10
+ const StyledFlatTableRowHeader = styled.th.attrs(({
11
+ stickyAlignment
12
+ }) => ({
13
+ "data-sticky-align": stickyAlignment
14
+ }))`
11
15
  ${({
12
16
  align,
13
17
  theme,
@@ -7,7 +7,7 @@ import Events from "../../__internal__/utils/helpers/events/events";
7
7
  export const FlatTableThemeContext = /*#__PURE__*/React.createContext({
8
8
  setSelectedId: () => {}
9
9
  });
10
- const FOCUSABLE_ROW_AND_CELL_QUERY = "tbody tr, tbody tr td, tbody tr th";
10
+ const FOCUSABLE_ROW_AND_CELL_QUERY = "tbody tr[tabindex], tbody tr td[tabindex], tbody tr th[tabindex]";
11
11
  export const FlatTable = ({
12
12
  caption,
13
13
  children,
@@ -98,7 +98,7 @@ export const FlatTable = ({
98
98
  if (!focusableElements) {
99
99
  return;
100
100
  }
101
- const focusableElementsArray = Array.from(focusableElements).filter(el => el.getAttribute("tabindex") !== null);
101
+ const focusableElementsArray = Array.from(focusableElements);
102
102
  const currentFocusIndex = focusableElementsArray.findIndex(el => el === document.activeElement);
103
103
  if (Events.isDownKey(ev)) {
104
104
  ev.preventDefault();
@@ -125,13 +125,30 @@ export const FlatTable = ({
125
125
  }
126
126
  };
127
127
  useLayoutEffect(() => {
128
- const focusableElements = tableRef.current?.querySelectorAll(FOCUSABLE_ROW_AND_CELL_QUERY);
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);
129
142
 
130
- // if no other menu item is selected, we need to make the first row a tab stop
131
- if (focusableElements && !selectedId) {
132
- const focusableArray = Array.from(focusableElements).filter(el => el.getAttribute("tabindex") !== null);
133
- setSelectedId(focusableArray[0]?.getAttribute("id") || "");
143
+ /* istanbul ignore else */
144
+ if (wrapperRef.current) {
145
+ observer.observe(wrapperRef.current, {
146
+ subtree: true,
147
+ childList: true,
148
+ attributes: true
149
+ });
134
150
  }
151
+ return () => observer.disconnect();
135
152
  }, [selectedId]);
136
153
  return /*#__PURE__*/React.createElement(StyledFlatTableWrapper, _extends({
137
154
  ref: wrapperRef,