@carbon/ibm-products 1.8.0 → 1.11.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 (111) hide show
  1. package/css/index-full-carbon.css +270 -5656
  2. package/css/index-full-carbon.css.map +1 -1
  3. package/css/index-full-carbon.min.css +6 -6
  4. package/css/index-full-carbon.min.css.map +1 -1
  5. package/css/index-without-carbon-released-only.css +58 -3432
  6. package/css/index-without-carbon-released-only.css.map +1 -1
  7. package/css/index-without-carbon-released-only.min.css +3 -3
  8. package/css/index-without-carbon-released-only.min.css.map +1 -1
  9. package/css/index-without-carbon.css +238 -3922
  10. package/css/index-without-carbon.css.map +1 -1
  11. package/css/index-without-carbon.min.css +6 -6
  12. package/css/index-without-carbon.min.css.map +1 -1
  13. package/css/index.css +238 -3923
  14. package/css/index.css.map +1 -1
  15. package/css/index.min.css +6 -6
  16. package/css/index.min.css.map +1 -1
  17. package/es/components/AddSelect/AddSelect.js +147 -53
  18. package/es/components/AddSelect/AddSelectBreadcrumbs.js +4 -4
  19. package/es/components/AddSelect/AddSelectColumn.js +195 -0
  20. package/es/components/AddSelect/AddSelectList.js +67 -8
  21. package/es/components/AddSelect/AddSelectSidebar.js +8 -15
  22. package/es/components/AddSelect/add-select-utils.js +64 -0
  23. package/es/components/BreadcrumbWithOverflow/BreadcrumbWithOverflow.js +2 -1
  24. package/es/components/ButtonMenu/ButtonMenu.js +1 -1
  25. package/es/components/DataSpreadsheet/DataSpreadsheet.js +505 -167
  26. package/es/components/DataSpreadsheet/DataSpreadsheetBody.js +244 -17
  27. package/es/components/DataSpreadsheet/DataSpreadsheetHeader.js +74 -8
  28. package/es/components/DataSpreadsheet/hooks/useMoveActiveCell.js +27 -0
  29. package/es/components/DataSpreadsheet/hooks/useResetSpreadsheetFocus.js +28 -0
  30. package/es/components/DataSpreadsheet/hooks/useSpreadsheetOutsideClick.js +41 -0
  31. package/es/components/DataSpreadsheet/utils/checkActiveHeaderCell.js +34 -0
  32. package/es/components/DataSpreadsheet/utils/createActiveCellFn.js +58 -0
  33. package/es/components/DataSpreadsheet/utils/createCellSelectionArea.js +49 -0
  34. package/es/components/DataSpreadsheet/{generateData.js → utils/generateData.js} +6 -0
  35. package/es/components/DataSpreadsheet/{getCellSize.js → utils/getCellSize.js} +0 -0
  36. package/es/components/DataSpreadsheet/utils/handleHeaderCellSelection.js +46 -0
  37. package/es/components/DataSpreadsheet/utils/handleMultipleKeys.js +82 -0
  38. package/es/components/DataSpreadsheet/utils/removeCellSelections.js +30 -0
  39. package/es/components/InlineEdit/InlineEdit.js +80 -39
  40. package/es/components/OptionsTile/OptionsTile.js +31 -21
  41. package/es/components/OptionsTile/index.js +1 -1
  42. package/es/components/PageHeader/PageHeader.js +26 -15
  43. package/es/components/PageHeader/PageHeaderTitle.js +2 -1
  44. package/es/components/PageHeader/PageHeaderUtils.js +24 -29
  45. package/es/components/TagSet/TagSet.js +12 -3
  46. package/es/components/UserProfileImage/UserProfileImage.js +2 -1
  47. package/es/global/js/utils/DisplayBox.js +31 -0
  48. package/es/global/js/utils/deepCloneObject.js +26 -0
  49. package/lib/components/AddSelect/AddSelect.js +150 -54
  50. package/lib/components/AddSelect/AddSelectBreadcrumbs.js +2 -3
  51. package/lib/components/AddSelect/AddSelectColumn.js +219 -0
  52. package/lib/components/AddSelect/AddSelectList.js +65 -8
  53. package/lib/components/AddSelect/AddSelectSidebar.js +14 -15
  54. package/lib/components/AddSelect/add-select-utils.js +78 -0
  55. package/lib/components/BreadcrumbWithOverflow/BreadcrumbWithOverflow.js +2 -1
  56. package/lib/components/ButtonMenu/ButtonMenu.js +1 -1
  57. package/lib/components/DataSpreadsheet/DataSpreadsheet.js +514 -170
  58. package/lib/components/DataSpreadsheet/DataSpreadsheetBody.js +251 -18
  59. package/lib/components/DataSpreadsheet/DataSpreadsheetHeader.js +82 -9
  60. package/lib/components/DataSpreadsheet/hooks/useMoveActiveCell.js +37 -0
  61. package/lib/components/DataSpreadsheet/hooks/useResetSpreadsheetFocus.js +39 -0
  62. package/lib/components/DataSpreadsheet/hooks/useSpreadsheetOutsideClick.js +52 -0
  63. package/lib/components/DataSpreadsheet/utils/checkActiveHeaderCell.js +45 -0
  64. package/lib/components/DataSpreadsheet/{createActiveCellFn.js → utils/createActiveCellFn.js} +22 -9
  65. package/lib/components/DataSpreadsheet/utils/createCellSelectionArea.js +60 -0
  66. package/lib/components/DataSpreadsheet/{generateData.js → utils/generateData.js} +6 -0
  67. package/lib/components/DataSpreadsheet/{getCellSize.js → utils/getCellSize.js} +0 -0
  68. package/lib/components/DataSpreadsheet/utils/handleHeaderCellSelection.js +59 -0
  69. package/lib/components/DataSpreadsheet/utils/handleMultipleKeys.js +92 -0
  70. package/lib/components/DataSpreadsheet/utils/removeCellSelections.js +41 -0
  71. package/lib/components/InlineEdit/InlineEdit.js +82 -40
  72. package/lib/components/OptionsTile/OptionsTile.js +30 -20
  73. package/lib/components/PageHeader/PageHeader.js +25 -15
  74. package/lib/components/PageHeader/PageHeaderTitle.js +2 -1
  75. package/lib/components/PageHeader/PageHeaderUtils.js +24 -29
  76. package/lib/components/TagSet/TagSet.js +13 -3
  77. package/lib/components/UserProfileImage/UserProfileImage.js +2 -1
  78. package/lib/global/js/utils/DisplayBox.js +46 -0
  79. package/lib/global/js/utils/deepCloneObject.js +37 -0
  80. package/package.json +17 -17
  81. package/scss/components/ActionBar/_storybook-styles.scss +8 -0
  82. package/scss/components/ActionSet/_storybook-styles.scss +1 -3
  83. package/scss/components/AddSelect/_add-select.scss +99 -14
  84. package/scss/components/BreadcrumbWithOverflow/_breadcrumb-with-overflow.scss +7 -3
  85. package/scss/components/BreadcrumbWithOverflow/_storybook-styles.scss +8 -0
  86. package/scss/components/ButtonSetWithOverflow/_storybook-styles.scss +8 -0
  87. package/scss/components/CreateInfluencer/_create-influencer.scss +2 -0
  88. package/scss/components/CreateModal/_create-modal.scss +1 -0
  89. package/scss/components/CreateSidePanel/_create-side-panel.scss +1 -1
  90. package/scss/components/CreateSidePanel/_storybook-styles.scss +1 -1
  91. package/scss/components/CreateTearsheet/_create-tearsheet.scss +1 -0
  92. package/scss/components/CreateTearsheetNarrow/_create-tearsheet-narrow.scss +1 -0
  93. package/scss/components/DataSpreadsheet/_data-spreadsheet.scss +42 -6
  94. package/scss/components/EditSidePanel/_edit-side-panel.scss +9 -0
  95. package/scss/components/EditSidePanel/_storybook-styles.scss +1 -1
  96. package/scss/components/InlineEdit/_inline-edit.scss +53 -43
  97. package/scss/components/InlineEdit/_storybook-styles.scss +2 -0
  98. package/scss/components/LoadingBar/_loading-bar.scss +13 -0
  99. package/scss/components/NotificationsPanel/_notifications-panel.scss +3 -0
  100. package/scss/components/OptionsTile/_index.scss +1 -1
  101. package/scss/components/OptionsTile/_options-tile.scss +17 -17
  102. package/scss/components/OptionsTile/_storybook-styles.scss +4 -4
  103. package/scss/components/PageHeader/_page-header.scss +5 -2
  104. package/scss/components/SidePanel/_side-panel.scss +19 -12
  105. package/scss/components/StatusIcon/_status-icon.scss +1 -0
  106. package/scss/components/TagSet/_storybook-styles.scss +8 -0
  107. package/scss/components/Tearsheet/_tearsheet.scss +1 -2
  108. package/scss/components/UserProfileImage/_user-profile-image.scss +9 -0
  109. package/scss/components/WebTerminal/_web-terminal.scss +2 -0
  110. package/scss/global/styles/_display-box.scss +62 -0
  111. package/es/components/DataSpreadsheet/createActiveCellFn.js +0 -45
@@ -1,4 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
4
 
3
5
  /**
4
6
  * Copyright IBM Corp. 2022, 2022
@@ -6,23 +8,101 @@ import _extends from "@babel/runtime/helpers/extends";
6
8
  * This source code is licensed under the Apache-2.0 license found in the
7
9
  * LICENSE file in the root directory of this source tree.
8
10
  */
9
- import React, { useRef, useCallback, useEffect } from 'react';
11
+ import React, { useRef, useCallback, useEffect, forwardRef } from 'react';
10
12
  import PropTypes from 'prop-types';
11
13
  import { FixedSizeList } from 'react-window';
12
14
  import cx from 'classnames';
13
15
  import { pkg } from '../../settings';
16
+ import { deepCloneObject } from '../../global/js/utils/deepCloneObject';
17
+ import uuidv4 from '../../global/js/utils/uuidv4';
18
+ import { removeCellSelections } from './utils/removeCellSelections';
19
+ import { createCellSelectionArea } from './utils/createCellSelectionArea';
20
+ import { checkActiveHeaderCell } from './utils/checkActiveHeaderCell';
21
+ import { handleHeaderCellSelection } from './utils/handleHeaderCellSelection';
14
22
  var blockClass = "".concat(pkg.prefix, "--data-spreadsheet");
15
- export var DataSpreadsheetBody = function DataSpreadsheetBody(_ref) {
16
- var defaultColumn = _ref.defaultColumn,
23
+ export var DataSpreadsheetBody = /*#__PURE__*/forwardRef(function (_ref, ref) {
24
+ var columns = _ref.columns,
25
+ activeCellCoordinates = _ref.activeCellCoordinates,
26
+ defaultColumn = _ref.defaultColumn,
17
27
  getTableBodyProps = _ref.getTableBodyProps,
18
28
  id = _ref.id,
19
29
  prepareRow = _ref.prepareRow,
20
30
  rows = _ref.rows,
21
31
  setActiveCellCoordinates = _ref.setActiveCellCoordinates,
32
+ selectionAreas = _ref.selectionAreas,
33
+ setContainerHasFocus = _ref.setContainerHasFocus,
34
+ setSelectionAreas = _ref.setSelectionAreas,
22
35
  scrollBarSize = _ref.scrollBarSize,
23
- totalColumnsWidth = _ref.totalColumnsWidth;
24
- // Make sure that if the cellSize prop changes, the active
36
+ totalColumnsWidth = _ref.totalColumnsWidth,
37
+ clickAndHoldActive = _ref.clickAndHoldActive,
38
+ setClickAndHoldActive = _ref.setClickAndHoldActive,
39
+ currentMatcher = _ref.currentMatcher,
40
+ setCurrentMatcher = _ref.setCurrentMatcher;
41
+ // Create cell selection areas based on selectionAreas array
42
+ useEffect(function () {
43
+ if (selectionAreas && selectionAreas.length) {
44
+ selectionAreas.map(function (area) {
45
+ if (!area.areaCreated && area.point1 && area.point2 && area.matcher) {
46
+ // Do not create a cell selection area if point1 and point2 have the same values
47
+ // Cell selections must have two distinctly different points for an area to be created
48
+ if (area.point1.row === area.point2.row && area.point1.column === area.point2.column) {
49
+ var selectionAreasClone = deepCloneObject(selectionAreas);
50
+ var indexOfCurrentArea = selectionAreasClone.findIndex(function (item) {
51
+ return item.matcher === area.matcher;
52
+ });
53
+ selectionAreasClone[indexOfCurrentArea].areaCreated = false;
54
+ selectionAreasClone[indexOfCurrentArea].point2 = null;
55
+ return setSelectionAreas(selectionAreasClone);
56
+ }
57
+
58
+ createCellSelectionArea({
59
+ area: area,
60
+ blockClass: blockClass,
61
+ defaultColumn: defaultColumn,
62
+ selectionAreas: selectionAreas,
63
+ setSelectionAreas: setSelectionAreas
64
+ });
65
+ }
66
+
67
+ return;
68
+ });
69
+ }
70
+ }, [selectionAreas, setSelectionAreas, defaultColumn]); // Mouse up
71
+
72
+ useEffect(function () {
73
+ var handleMouseUp = function handleMouseUp(event) {
74
+ setClickAndHoldActive(false);
75
+ var cellButton = event.target.closest(".".concat(blockClass, "__body--td"));
76
+
77
+ if (cellButton) {
78
+ var endCellCoordinates = {
79
+ row: Number(cellButton.getAttribute('data-row-index')),
80
+ column: Number(cellButton.getAttribute('data-column-index'))
81
+ };
82
+ setSelectionAreas(function (prev) {
83
+ var selectionAreaClone = deepCloneObject(prev);
84
+ var indexOfItemToUpdate = selectionAreaClone.findIndex(function (item) {
85
+ return item.matcher === currentMatcher;
86
+ }); // No items in the array have an object that matches the value of currentMatcher
87
+
88
+ if (indexOfItemToUpdate === -1) {
89
+ return prev;
90
+ }
91
+
92
+ selectionAreaClone[indexOfItemToUpdate].point2 = endCellCoordinates;
93
+ selectionAreaClone[indexOfItemToUpdate].areaCreated = false;
94
+ return selectionAreaClone;
95
+ });
96
+ }
97
+ };
98
+
99
+ document.addEventListener('mouseup', handleMouseUp);
100
+ return function () {
101
+ document.removeEventListener('mouseup', handleMouseUp);
102
+ };
103
+ }, [selectionAreas, currentMatcher, setSelectionAreas, setClickAndHoldActive, setCurrentMatcher, ref]); // Make sure that if the cellSize prop changes, the active
25
104
  // cell also gets updated with the new size
105
+
26
106
  useEffect(function () {
27
107
  var listContainer = spreadsheetBodyRef === null || spreadsheetBodyRef === void 0 ? void 0 : spreadsheetBodyRef.current;
28
108
  var activeCellButton = listContainer.querySelector(".".concat(blockClass, "__active-cell--highlight"));
@@ -34,11 +114,109 @@ export var DataSpreadsheetBody = function DataSpreadsheetBody(_ref) {
34
114
  // adds the active cell highlight
35
115
 
36
116
  var handleBodyCellClick = useCallback(function (cell, columnIndex) {
37
- setActiveCellCoordinates({
38
- row: cell.row.index,
39
- column: columnIndex
40
- });
41
- }, [setActiveCellCoordinates]); // Renders each cell in the spreadsheet body
117
+ return function (event) {
118
+ event.preventDefault();
119
+ var isHoldingCommandKey = event.metaKey || event.ctrlKey;
120
+ var isHoldingShiftKey = event.shiftKey;
121
+ setContainerHasFocus(true);
122
+ var activeCoordinates = {
123
+ row: cell.row.index,
124
+ column: columnIndex
125
+ };
126
+ var tempMatcher = uuidv4();
127
+ setClickAndHoldActive(true); // prevent multiple selections unless cmd key is held
128
+ // meaning that selectionAreas should only have one item by default
129
+
130
+ if (isHoldingCommandKey) {
131
+ setActiveCellCoordinates(activeCoordinates);
132
+ setCurrentMatcher(tempMatcher);
133
+ setSelectionAreas(function (prev) {
134
+ return [].concat(_toConsumableArray(prev), [{
135
+ point1: activeCoordinates,
136
+ matcher: tempMatcher
137
+ }]);
138
+ });
139
+ } else if (isHoldingShiftKey) {
140
+ setContainerHasFocus(true);
141
+ var selectionAreaClone = deepCloneObject(selectionAreas);
142
+ var indexOfItemToUpdate = selectionAreaClone.findIndex(function (item) {
143
+ return item.matcher === currentMatcher;
144
+ });
145
+
146
+ if (indexOfItemToUpdate === -1) {
147
+ // There is always a selectionArea with a point1 object that updates
148
+ // whenever the activeCellCoordinates update, we should always be able
149
+ // to find an index, but if we do not for some reason we should return
150
+ // at this point.
151
+ return;
152
+ } else {
153
+ // Update the selectionArea that was found, do not update currentMatcher
154
+ selectionAreaClone[indexOfItemToUpdate].point1 = activeCellCoordinates;
155
+ selectionAreaClone[indexOfItemToUpdate].point2 = activeCoordinates;
156
+ selectionAreaClone[indexOfItemToUpdate].areaCreated = false;
157
+ selectionAreaClone[indexOfItemToUpdate].matcher = currentMatcher;
158
+ setSelectionAreas(selectionAreaClone);
159
+ }
160
+ } else {
161
+ setActiveCellCoordinates(activeCoordinates); // remove all previous cell selections
162
+
163
+ removeCellSelections({
164
+ spreadsheetRef: ref
165
+ });
166
+ setSelectionAreas([{
167
+ point1: activeCoordinates,
168
+ matcher: tempMatcher
169
+ }]);
170
+ setCurrentMatcher(tempMatcher);
171
+ }
172
+ };
173
+ }, [currentMatcher, activeCellCoordinates, selectionAreas, setActiveCellCoordinates, setSelectionAreas, setContainerHasFocus, setClickAndHoldActive, setCurrentMatcher, ref]);
174
+ var handleBodyCellHover = useCallback(function (cell, columnIndex) {
175
+ return function () {
176
+ if (clickAndHoldActive) {
177
+ var cellCoordinates = {
178
+ row: cell.row.index,
179
+ column: columnIndex
180
+ };
181
+ setSelectionAreas(function (prev) {
182
+ var _selectionAreaClone$i, _selectionAreaClone$i2;
183
+
184
+ var selectionAreaClone = deepCloneObject(prev);
185
+ var indexOfItemToUpdate = selectionAreaClone.findIndex(function (item) {
186
+ return item.matcher === currentMatcher;
187
+ }); // No items in the array match up with the currentMatcher value
188
+
189
+ if (indexOfItemToUpdate === -1) {
190
+ return prev;
191
+ } // Do not update state if you're still hovering on the same cell
192
+
193
+
194
+ if (((_selectionAreaClone$i = selectionAreaClone[indexOfItemToUpdate].point2) === null || _selectionAreaClone$i === void 0 ? void 0 : _selectionAreaClone$i.row) === cellCoordinates.row && ((_selectionAreaClone$i2 = selectionAreaClone[indexOfItemToUpdate].point2) === null || _selectionAreaClone$i2 === void 0 ? void 0 : _selectionAreaClone$i2.column) === cellCoordinates.column) {
195
+ return prev;
196
+ }
197
+
198
+ selectionAreaClone[indexOfItemToUpdate].point2 = cellCoordinates;
199
+ selectionAreaClone[indexOfItemToUpdate].areaCreated = false;
200
+ return selectionAreaClone;
201
+ });
202
+ }
203
+ };
204
+ }, [clickAndHoldActive, currentMatcher, setSelectionAreas]);
205
+ var handleRowHeaderClick = useCallback(function (index) {
206
+ return function () {
207
+ handleHeaderCellSelection({
208
+ type: 'row',
209
+ activeCellCoordinates: activeCellCoordinates,
210
+ rows: rows,
211
+ columns: columns,
212
+ setActiveCellCoordinates: setActiveCellCoordinates,
213
+ setCurrentMatcher: setCurrentMatcher,
214
+ setSelectionAreas: setSelectionAreas,
215
+ spreadsheetRef: ref,
216
+ index: index
217
+ });
218
+ };
219
+ }, [columns, ref, setSelectionAreas, setCurrentMatcher, setActiveCellCoordinates, activeCellCoordinates, rows]); // Renders each row/cell in the spreadsheet body
42
220
 
43
221
  var RenderRow = useCallback(function (_ref2) {
44
222
  var index = _ref2.index,
@@ -55,7 +233,8 @@ export var DataSpreadsheetBody = function DataSpreadsheetBody(_ref) {
55
233
  "data-row-index": index,
56
234
  "data-column-index": "header",
57
235
  type: "button",
58
- className: cx("".concat(blockClass, "__td"), "".concat(blockClass, "__td-th"), "".concat(blockClass, "--interactive-cell-element")),
236
+ onClick: handleRowHeaderClick(index),
237
+ className: cx("".concat(blockClass, "__td"), "".concat(blockClass, "__td-th"), "".concat(blockClass, "--interactive-cell-element"), _defineProperty({}, "".concat(blockClass, "__td-th--active-header"), (activeCellCoordinates === null || activeCellCoordinates === void 0 ? void 0 : activeCellCoordinates.row) === index || checkActiveHeaderCell(index, selectionAreas, 'row'))),
59
238
  style: {
60
239
  width: defaultColumn === null || defaultColumn === void 0 ? void 0 : defaultColumn.rowHeaderWidth
61
240
  }
@@ -65,15 +244,15 @@ export var DataSpreadsheetBody = function DataSpreadsheetBody(_ref) {
65
244
  "data-row-index": cell.row.index,
66
245
  "data-column-index": index
67
246
  }, cell.getCellProps(), {
68
- className: cx("".concat(blockClass, "__td"), "".concat(blockClass, "--interactive-cell-element")),
247
+ className: cx("".concat(blockClass, "__td"), "".concat(blockClass, "__body--td"), "".concat(blockClass, "--interactive-cell-element")),
69
248
  key: "cell_".concat(index),
70
- onClick: function onClick() {
71
- return handleBodyCellClick(cell, index);
72
- },
249
+ onMouseDown: handleBodyCellClick(cell, index),
250
+ onMouseOver: handleBodyCellHover(cell, index),
251
+ onFocus: function onFocus() {},
73
252
  type: "button"
74
253
  }), cell.render('Cell'));
75
254
  }));
76
- }, [prepareRow, rows, defaultColumn.rowHeaderWidth, handleBodyCellClick]);
255
+ }, [prepareRow, rows, defaultColumn.rowHeaderWidth, activeCellCoordinates === null || activeCellCoordinates === void 0 ? void 0 : activeCellCoordinates.row, selectionAreas, handleRowHeaderClick, handleBodyCellClick, handleBodyCellHover]);
77
256
  var spreadsheetBodyRef = useRef();
78
257
  return /*#__PURE__*/React.createElement("div", _extends({
79
258
  ref: spreadsheetBodyRef,
@@ -85,8 +264,31 @@ export var DataSpreadsheetBody = function DataSpreadsheetBody(_ref) {
85
264
  itemSize: defaultColumn === null || defaultColumn === void 0 ? void 0 : defaultColumn.rowHeight,
86
265
  width: totalColumnsWidth + scrollBarSize
87
266
  }, RenderRow));
88
- };
267
+ });
89
268
  DataSpreadsheetBody.propTypes = {
269
+ /**
270
+ * Object containing the active cell coordinates
271
+ */
272
+ activeCellCoordinates: PropTypes.shape({
273
+ row: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
274
+ column: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
275
+ }),
276
+
277
+ /**
278
+ * Is the user clicking and holding in the data spreadsheet body
279
+ */
280
+ clickAndHoldActive: PropTypes.bool,
281
+
282
+ /**
283
+ * All of the spreadsheet columns
284
+ */
285
+ columns: PropTypes.array,
286
+
287
+ /**
288
+ * This represents the id of the current cell selection area
289
+ */
290
+ currentMatcher: PropTypes.string,
291
+
90
292
  /**
91
293
  * Default spreadsheet sizing values
92
294
  */
@@ -126,11 +328,36 @@ DataSpreadsheetBody.propTypes = {
126
328
  */
127
329
  scrollBarSize: PropTypes.number,
128
330
 
331
+ /**
332
+ * Array of selection areas
333
+ */
334
+ selectionAreas: PropTypes.array,
335
+
129
336
  /**
130
337
  * Setter fn for activeCellCoordinates state value
131
338
  */
132
339
  setActiveCellCoordinates: PropTypes.func,
133
340
 
341
+ /**
342
+ * Setter fn for clickAndHold state value
343
+ */
344
+ setClickAndHoldActive: PropTypes.func,
345
+
346
+ /**
347
+ * Setter fn for containerHasFocus state value
348
+ */
349
+ setContainerHasFocus: PropTypes.func,
350
+
351
+ /**
352
+ * Setter fn for currentMatcher state value
353
+ */
354
+ setCurrentMatcher: PropTypes.func,
355
+
356
+ /**
357
+ * Setter fn for selectionAreas state value
358
+ */
359
+ setSelectionAreas: PropTypes.func,
360
+
134
361
  /**
135
362
  * The total columns width
136
363
  */
@@ -1,4 +1,5 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
3
 
3
4
  /**
4
5
  * Copyright IBM Corp. 2022, 2022
@@ -6,14 +7,40 @@ import _extends from "@babel/runtime/helpers/extends";
6
7
  * This source code is licensed under the Apache-2.0 license found in the
7
8
  * LICENSE file in the root directory of this source tree.
8
9
  */
9
- import React from 'react';
10
+ import React, { forwardRef } from 'react';
10
11
  import PropTypes from 'prop-types';
11
12
  import cx from 'classnames';
12
13
  import { pkg } from '../../settings';
14
+ import { checkActiveHeaderCell } from './utils/checkActiveHeaderCell';
15
+ import { handleHeaderCellSelection } from './utils/handleHeaderCellSelection';
13
16
  var blockClass = "".concat(pkg.prefix, "--data-spreadsheet");
14
- export var DataSpreadsheetHeader = function DataSpreadsheetHeader(_ref) {
15
- var defaultColumn = _ref.defaultColumn,
16
- headerGroups = _ref.headerGroups;
17
+ export var DataSpreadsheetHeader = /*#__PURE__*/forwardRef(function (_ref, ref) {
18
+ var activeCellCoordinates = _ref.activeCellCoordinates,
19
+ columns = _ref.columns,
20
+ defaultColumn = _ref.defaultColumn,
21
+ headerGroups = _ref.headerGroups,
22
+ selectionAreas = _ref.selectionAreas,
23
+ setActiveCellCoordinates = _ref.setActiveCellCoordinates,
24
+ setCurrentMatcher = _ref.setCurrentMatcher,
25
+ setSelectionAreas = _ref.setSelectionAreas,
26
+ rows = _ref.rows;
27
+
28
+ var handleColumnHeaderClick = function handleColumnHeaderClick(index) {
29
+ return function () {
30
+ handleHeaderCellSelection({
31
+ type: 'column',
32
+ activeCellCoordinates: activeCellCoordinates,
33
+ rows: rows,
34
+ columns: columns,
35
+ setActiveCellCoordinates: setActiveCellCoordinates,
36
+ setCurrentMatcher: setCurrentMatcher,
37
+ setSelectionAreas: setSelectionAreas,
38
+ spreadsheetRef: ref,
39
+ index: index
40
+ });
41
+ };
42
+ };
43
+
17
44
  return /*#__PURE__*/React.createElement("div", {
18
45
  className: cx("".concat(blockClass, "__header--container"))
19
46
  }, headerGroups.map(function (headerGroup, index) {
@@ -26,7 +53,7 @@ export var DataSpreadsheetHeader = function DataSpreadsheetHeader(_ref) {
26
53
  "data-column-index": "header",
27
54
  type: "button",
28
55
  tabIndex: -1,
29
- className: cx("".concat(blockClass, "__th"), "".concat(blockClass, "--interactive-cell-element")),
56
+ className: cx("".concat(blockClass, "__th"), "".concat(blockClass, "--interactive-cell-element"), _defineProperty({}, "".concat(blockClass, "__th--active-header"), (activeCellCoordinates === null || activeCellCoordinates === void 0 ? void 0 : activeCellCoordinates.column) === 'header' && (activeCellCoordinates === null || activeCellCoordinates === void 0 ? void 0 : activeCellCoordinates.row) === 'header')),
30
57
  style: {
31
58
  width: defaultColumn === null || defaultColumn === void 0 ? void 0 : defaultColumn.rowHeaderWidth,
32
59
  height: defaultColumn === null || defaultColumn === void 0 ? void 0 : defaultColumn.rowHeight
@@ -37,17 +64,31 @@ export var DataSpreadsheetHeader = function DataSpreadsheetHeader(_ref) {
37
64
  "data-row-index": "header",
38
65
  "data-column-index": index,
39
66
  tabIndex: -1,
67
+ onClick: handleColumnHeaderClick(index),
40
68
  style: {
41
69
  height: defaultColumn === null || defaultColumn === void 0 ? void 0 : defaultColumn.rowHeight
42
70
  }
43
71
  }, column.getHeaderProps(), {
44
- className: cx("".concat(blockClass, "__th"), "".concat(blockClass, "--interactive-cell-element")),
72
+ className: cx("".concat(blockClass, "__th"), "".concat(blockClass, "--interactive-cell-element"), _defineProperty({}, "".concat(blockClass, "__th--active-header"), (activeCellCoordinates === null || activeCellCoordinates === void 0 ? void 0 : activeCellCoordinates.column) === index || checkActiveHeaderCell(index, selectionAreas, 'column'))),
45
73
  type: "button"
46
74
  }), column.render('Header'));
47
75
  }));
48
76
  }));
49
- };
77
+ });
50
78
  DataSpreadsheetHeader.propTypes = {
79
+ /**
80
+ * Object containing the active cell coordinates
81
+ */
82
+ activeCellCoordinates: PropTypes.shape({
83
+ row: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
84
+ column: PropTypes.oneOfType([PropTypes.number, PropTypes.string])
85
+ }),
86
+
87
+ /**
88
+ * All of the spreadsheet columns
89
+ */
90
+ columns: PropTypes.array,
91
+
51
92
  /**
52
93
  * Default spreadsheet sizing values
53
94
  */
@@ -60,5 +101,30 @@ DataSpreadsheetHeader.propTypes = {
60
101
  /**
61
102
  * Headers provided from useTable hook
62
103
  */
63
- headerGroups: PropTypes.arrayOf(PropTypes.object)
104
+ headerGroups: PropTypes.arrayOf(PropTypes.object),
105
+
106
+ /**
107
+ * All of the spreadsheet row data
108
+ */
109
+ rows: PropTypes.arrayOf(PropTypes.object),
110
+
111
+ /**
112
+ * All of the cell selection area items
113
+ */
114
+ selectionAreas: PropTypes.arrayOf(PropTypes.object),
115
+
116
+ /**
117
+ * Setter fn for activeCellCoordinates value
118
+ */
119
+ setActiveCellCoordinates: PropTypes.func,
120
+
121
+ /**
122
+ * Setter fn for currentMatcher value
123
+ */
124
+ setCurrentMatcher: PropTypes.func,
125
+
126
+ /**
127
+ * Setter fn for selectionAreas value
128
+ */
129
+ setSelectionAreas: PropTypes.func
64
130
  };
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Copyright IBM Corp. 2022, 2022
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import { useEffect } from 'react'; // Moves the placement of the active cell
8
+
9
+ export var useMoveActiveCell = function useMoveActiveCell(_ref) {
10
+ var spreadsheetRef = _ref.spreadsheetRef,
11
+ activeCellCoordinates = _ref.activeCellCoordinates,
12
+ containerHasFocus = _ref.containerHasFocus,
13
+ createActiveCell = _ref.createActiveCell;
14
+ useEffect(function () {
15
+ var activeCellPlacementElement = spreadsheetRef === null || spreadsheetRef === void 0 ? void 0 : spreadsheetRef.current.querySelector("[data-row-index=\"".concat(activeCellCoordinates === null || activeCellCoordinates === void 0 ? void 0 : activeCellCoordinates.row, "\"][data-column-index=\"").concat(activeCellCoordinates === null || activeCellCoordinates === void 0 ? void 0 : activeCellCoordinates.column, "\"]"));
16
+ var shouldPlaceActiveCellInHeader = (activeCellCoordinates === null || activeCellCoordinates === void 0 ? void 0 : activeCellCoordinates.row) === 'header' && true;
17
+ var selectAllElement = spreadsheetRef === null || spreadsheetRef === void 0 ? void 0 : spreadsheetRef.current.querySelector("[data-row-index=\"header\"][data-column-index=\"header\"]");
18
+
19
+ if (containerHasFocus) {
20
+ createActiveCell({
21
+ placementElement: activeCellCoordinates ? activeCellPlacementElement : selectAllElement,
22
+ coords: activeCellCoordinates,
23
+ addToHeader: shouldPlaceActiveCellInHeader
24
+ });
25
+ }
26
+ }, [activeCellCoordinates, spreadsheetRef, createActiveCell, containerHasFocus]);
27
+ };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Copyright IBM Corp. 2022, 2022
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import { useEffect } from 'react';
8
+ import { pkg } from '../../../settings';
9
+ export var useResetSpreadsheetFocus = function useResetSpreadsheetFocus(_ref) {
10
+ var activeKeys = _ref.activeKeys,
11
+ _ref$blockClass = _ref.blockClass,
12
+ blockClass = _ref$blockClass === void 0 ? "".concat(pkg.prefix, "--data-spreadsheet") : _ref$blockClass,
13
+ focusedElement = _ref.focusedElement,
14
+ removeActiveCell = _ref.removeActiveCell,
15
+ setContainerHasFocus = _ref.setContainerHasFocus;
16
+ // Reset everything when spreadsheet loses focus
17
+ useEffect(function () {
18
+ if (!focusedElement.classList.contains("".concat(blockClass, "--interactive-cell-element"))) {
19
+ setContainerHasFocus(false);
20
+ removeActiveCell();
21
+ activeKeys.current = [];
22
+ }
23
+
24
+ if (focusedElement.classList.contains(blockClass) || focusedElement.classList.contains("".concat(blockClass, "--interactive-cell-element"))) {
25
+ setContainerHasFocus(true);
26
+ }
27
+ }, [focusedElement, removeActiveCell, activeKeys, blockClass, setContainerHasFocus]);
28
+ };
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Copyright IBM Corp. 2022, 2022
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import { useEffect } from 'react';
8
+ import { pkg } from '../../../settings'; // Click outside useEffect for spreadsheet
9
+
10
+ export var useSpreadsheetOutsideClick = function useSpreadsheetOutsideClick(_ref) {
11
+ var spreadsheetRef = _ref.spreadsheetRef,
12
+ _ref$blockClass = _ref.blockClass,
13
+ blockClass = _ref$blockClass === void 0 ? "".concat(pkg.prefix, "--data-spreadsheet") : _ref$blockClass,
14
+ setActiveCellCoordinates = _ref.setActiveCellCoordinates,
15
+ setSelectionAreas = _ref.setSelectionAreas,
16
+ removeActiveCell = _ref.removeActiveCell,
17
+ removeCellSelections = _ref.removeCellSelections,
18
+ setContainerHasFocus = _ref.setContainerHasFocus,
19
+ activeKeys = _ref.activeKeys,
20
+ removeCellEditor = _ref.removeCellEditor;
21
+ useEffect(function () {
22
+ var handleOutsideClick = function handleOutsideClick(event) {
23
+ if (!spreadsheetRef.current || spreadsheetRef.current.contains(event.target) || event.target.classList.contains("".concat(blockClass, "__active-cell--highlight")) || event.target.classList.contains("".concat(blockClass, "--interactive-cell-element"))) {
24
+ return;
25
+ }
26
+
27
+ setActiveCellCoordinates(null);
28
+ setSelectionAreas([]);
29
+ removeActiveCell();
30
+ removeCellSelections();
31
+ setContainerHasFocus(false);
32
+ removeCellEditor();
33
+ activeKeys.current = [];
34
+ };
35
+
36
+ document.addEventListener('click', handleOutsideClick);
37
+ return function () {
38
+ document.removeEventListener('click', handleOutsideClick);
39
+ };
40
+ }, [spreadsheetRef, removeActiveCell, removeCellSelections, activeKeys, blockClass, setActiveCellCoordinates, setContainerHasFocus, setSelectionAreas, removeCellEditor]);
41
+ };
@@ -0,0 +1,34 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+
3
+ /**
4
+ * Copyright IBM Corp. 2022, 2022
5
+ *
6
+ * This source code is licensed under the Apache-2.0 license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ import { deepCloneObject } from '../../../global/js/utils/deepCloneObject'; // Determines if a row or column header cell should receive a highlight/active background color
10
+ // Check each object in selectionAreas and see if the headerIndex is between
11
+ // point1.row and point2.row, inclusive
12
+
13
+ export var checkActiveHeaderCell = function checkActiveHeaderCell(headerIndex, selectionAreas, headerType) {
14
+ var areasCloned = deepCloneObject(selectionAreas);
15
+ var activeRowIndexes = [];
16
+ areasCloned.forEach(function (area) {
17
+ var _area$point, _area$point2, _area$point3, _area$point4;
18
+
19
+ var greatestRowIndex = Math.max((_area$point = area.point1) === null || _area$point === void 0 ? void 0 : _area$point[headerType], (_area$point2 = area.point2) === null || _area$point2 === void 0 ? void 0 : _area$point2[headerType]);
20
+ var lowestRowIndex = Math.min((_area$point3 = area.point1) === null || _area$point3 === void 0 ? void 0 : _area$point3[headerType], (_area$point4 = area.point2) === null || _area$point4 === void 0 ? void 0 : _area$point4[headerType]);
21
+
22
+ for (var i = lowestRowIndex; i <= greatestRowIndex; i++) {
23
+ activeRowIndexes.push(i);
24
+ }
25
+ });
26
+
27
+ var activeRowIndexesNoDuplicates = _toConsumableArray(new Set(activeRowIndexes));
28
+
29
+ if (areasCloned !== null && areasCloned !== void 0 && areasCloned.length && activeRowIndexesNoDuplicates.includes(headerIndex)) {
30
+ return true;
31
+ }
32
+
33
+ return false;
34
+ };
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Copyright IBM Corp. 2022, 2022
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import { px } from '@carbon/layout';
8
+ import { pkg } from '../../../settings';
9
+ export var createActiveCellFn = function createActiveCellFn(_ref) {
10
+ var placementElement = _ref.placementElement,
11
+ coords = _ref.coords,
12
+ _ref$addToHeader = _ref.addToHeader,
13
+ addToHeader = _ref$addToHeader === void 0 ? false : _ref$addToHeader,
14
+ contextRef = _ref.contextRef,
15
+ _ref$blockClass = _ref.blockClass,
16
+ blockClass = _ref$blockClass === void 0 ? "".concat(pkg.prefix, "--data-spreadsheet") : _ref$blockClass,
17
+ onActiveCellChange = _ref.onActiveCellChange,
18
+ activeCellValue = _ref.activeCellValue,
19
+ activeCellRef = _ref.activeCellRef,
20
+ cellEditorRef = _ref.cellEditorRef,
21
+ defaultColumn = _ref.defaultColumn;
22
+
23
+ if (!coords) {
24
+ return;
25
+ } // If the active cell is in the column header row (very first), we need to append this element
26
+ // to `.${blockClass}__header--container`, otherwise it should be appended to `.${blockClass}__listContainer` firstElementChild
27
+
28
+
29
+ var point1Element = document.querySelector("[data-row-index=\"".concat(coords.row, "\"][data-column-index=\"").concat(coords.column, "\"]")) || document.querySelector(".".concat(blockClass, "__body--td")); // if we can't find the point1 element (this can happen in the case where a virtualized row is not present anymore in the DOM), we get the default height/width of the first body cell we find
30
+
31
+ var selectionAreaCellWidth = point1Element.offsetWidth;
32
+ var selectionAreaCellHeight = point1Element.offsetHeight;
33
+ var activeElementContainer = addToHeader ? contextRef === null || contextRef === void 0 ? void 0 : contextRef.current.querySelector(".".concat(blockClass, "__header--container")) : contextRef === null || contextRef === void 0 ? void 0 : contextRef.current.querySelector(".".concat(blockClass, "__list--container")).firstElementChild;
34
+ var relativePosition = {
35
+ top: placementElement ? placementElement.getBoundingClientRect().top - activeElementContainer.getBoundingClientRect().top : coords.row === 0 ? 0 : selectionAreaCellHeight * coords.row,
36
+ // calculate top value here if virtualized row is not in DOM
37
+ left: placementElement ? placementElement.getBoundingClientRect().left - activeElementContainer.getBoundingClientRect().left : coords.column === 0 ? 0 + (defaultColumn.rowHeaderWidth - 4) : selectionAreaCellWidth * coords.column + (defaultColumn.rowHeaderWidth - 4) // calculate left value here if virtualized row is not in DOM, accounting for row header cell width (including borders)
38
+
39
+ };
40
+ var activeCellButton = activeCellRef === null || activeCellRef === void 0 ? void 0 : activeCellRef.current;
41
+ activeCellButton.style.width = px(placementElement ? placementElement === null || placementElement === void 0 ? void 0 : placementElement.offsetWidth : selectionAreaCellWidth);
42
+ activeCellButton.style.height = px(placementElement ? placementElement === null || placementElement === void 0 ? void 0 : placementElement.offsetHeight : selectionAreaCellHeight);
43
+ activeCellButton.style.left = px(relativePosition.left);
44
+ activeCellButton.style.top = px(relativePosition.top);
45
+ activeCellButton.style.display = 'block';
46
+ activeCellButton.setAttribute('data-active-row-index', typeof (coords === null || coords === void 0 ? void 0 : coords.row) === 'number' ? coords.row : 'header');
47
+ activeCellButton.setAttribute('data-active-column-index', typeof (coords === null || coords === void 0 ? void 0 : coords.column) === 'number' ? coords.column : 'header');
48
+ activeElementContainer.appendChild(activeCellButton);
49
+ activeCellButton.focus();
50
+
51
+ if (!addToHeader) {
52
+ activeElementContainer.appendChild(cellEditorRef.current);
53
+ }
54
+
55
+ if (typeof (coords === null || coords === void 0 ? void 0 : coords.column) === 'number' && typeof (coords === null || coords === void 0 ? void 0 : coords.row) === 'number') {
56
+ onActiveCellChange === null || onActiveCellChange === void 0 ? void 0 : onActiveCellChange(activeCellValue);
57
+ }
58
+ };