@carbon/ibm-products 1.8.0 → 1.9.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.
- package/css/index-full-carbon.css +82 -9
- package/css/index-full-carbon.css.map +1 -1
- package/css/index-full-carbon.min.css +3 -3
- package/css/index-full-carbon.min.css.map +1 -1
- package/css/index-without-carbon-released-only.css +1 -2
- package/css/index-without-carbon-released-only.css.map +1 -1
- package/css/index-without-carbon-released-only.min.css +1 -1
- package/css/index-without-carbon-released-only.min.css.map +1 -1
- package/css/index-without-carbon.css +82 -9
- package/css/index-without-carbon.css.map +1 -1
- package/css/index-without-carbon.min.css +3 -3
- package/css/index-without-carbon.min.css.map +1 -1
- package/css/index.css +82 -9
- package/css/index.css.map +1 -1
- package/css/index.min.css +3 -3
- package/css/index.min.css.map +1 -1
- package/es/components/AddSelect/AddSelect.js +104 -16
- package/es/components/AddSelect/AddSelectBreadcrumbs.js +4 -4
- package/es/components/AddSelect/AddSelectColumn.js +21 -0
- package/es/components/AddSelect/AddSelectList.js +67 -8
- package/es/components/AddSelect/AddSelectSidebar.js +7 -1
- package/es/components/DataSpreadsheet/DataSpreadsheet.js +42 -2
- package/es/components/DataSpreadsheet/DataSpreadsheetBody.js +194 -10
- package/es/components/DataSpreadsheet/createActiveCellFn.js +1 -1
- package/es/components/DataSpreadsheet/createCellSelectionArea.js +45 -0
- package/es/components/InlineEdit/InlineEdit.js +23 -13
- package/es/global/js/utils/DisplayBox.js +31 -0
- package/es/global/js/utils/deepCloneObject.js +26 -0
- package/lib/components/AddSelect/AddSelect.js +102 -15
- package/lib/components/AddSelect/AddSelectBreadcrumbs.js +2 -3
- package/lib/components/AddSelect/AddSelectColumn.js +37 -0
- package/lib/components/AddSelect/AddSelectList.js +65 -8
- package/lib/components/AddSelect/AddSelectSidebar.js +7 -1
- package/lib/components/DataSpreadsheet/DataSpreadsheet.js +42 -2
- package/lib/components/DataSpreadsheet/DataSpreadsheetBody.js +198 -10
- package/lib/components/DataSpreadsheet/createActiveCellFn.js +1 -1
- package/lib/components/DataSpreadsheet/createCellSelectionArea.js +56 -0
- package/lib/components/InlineEdit/InlineEdit.js +23 -13
- package/lib/global/js/utils/DisplayBox.js +46 -0
- package/lib/global/js/utils/deepCloneObject.js +37 -0
- package/package.json +8 -8
- package/scss/components/ActionBar/_storybook-styles.scss +8 -0
- package/scss/components/ActionSet/_storybook-styles.scss +1 -3
- package/scss/components/AddSelect/_add-select.scss +58 -2
- package/scss/components/BreadcrumbWithOverflow/_storybook-styles.scss +8 -0
- package/scss/components/ButtonSetWithOverflow/_storybook-styles.scss +8 -0
- package/scss/components/DataSpreadsheet/_data-spreadsheet.scss +18 -0
- package/scss/components/InlineEdit/_inline-edit.scss +11 -4
- package/scss/components/InlineEdit/_storybook-styles.scss +1 -0
- package/scss/components/TagSet/_storybook-styles.scss +8 -0
- package/scss/components/Tearsheet/_tearsheet.scss +1 -2
- package/scss/global/styles/_display-box.scss +62 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
2
|
+
//
|
3
|
+
// Copyright IBM Corp. 2022
|
4
|
+
//
|
5
|
+
// This source code is licensed under the Apache-2.0 license found in the
|
6
|
+
// LICENSE file in the root directory of this source tree.
|
7
|
+
//
|
8
|
+
import React from 'react'; // import PropTypes from 'prop-types';
|
9
|
+
|
10
|
+
import { pkg } from '../../settings';
|
11
|
+
import { AddSelectList } from './AddSelectList';
|
12
|
+
var componentName = 'AddSelect';
|
13
|
+
export var AddSelectColumn = function AddSelectColumn(props) {
|
14
|
+
var blockClass = "".concat(pkg.prefix, "--add-select__col");
|
15
|
+
return /*#__PURE__*/React.createElement("div", {
|
16
|
+
className: blockClass
|
17
|
+
}, /*#__PURE__*/React.createElement(AddSelectList, _extends({}, props, {
|
18
|
+
inColumn: true
|
19
|
+
})));
|
20
|
+
};
|
21
|
+
AddSelectColumn.displayName = componentName;
|
@@ -13,6 +13,7 @@ import { pkg } from '../../settings';
|
|
13
13
|
var componentName = 'AddSelectList';
|
14
14
|
export var AddSelectList = function AddSelectList(_ref) {
|
15
15
|
var filteredItems = _ref.filteredItems,
|
16
|
+
inColumn = _ref.inColumn,
|
16
17
|
multi = _ref.multi,
|
17
18
|
multiSelection = _ref.multiSelection,
|
18
19
|
path = _ref.path,
|
@@ -41,11 +42,61 @@ export var AddSelectList = function AddSelectList(_ref) {
|
|
41
42
|
|
42
43
|
var onNavigateItem = function onNavigateItem(_ref2) {
|
43
44
|
var id = _ref2.id,
|
44
|
-
title = _ref2.title
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
title = _ref2.title,
|
46
|
+
parent = _ref2.parent;
|
47
|
+
|
48
|
+
// if multi select
|
49
|
+
if (multi) {
|
50
|
+
// if top level reset the path
|
51
|
+
if (!parent) {
|
52
|
+
setPath([{
|
53
|
+
id: id,
|
54
|
+
title: title
|
55
|
+
}]);
|
56
|
+
} else {
|
57
|
+
var pathIds = path.map(function (p) {
|
58
|
+
return p.id;
|
59
|
+
}); // if item is already selected somewhere go back to that item
|
60
|
+
|
61
|
+
if (pathIds.includes(id)) {
|
62
|
+
var pathIdx = pathIds.findIndex(function (pathId) {
|
63
|
+
return pathId === id;
|
64
|
+
});
|
65
|
+
|
66
|
+
var newPath = _toConsumableArray(path).splice(0, pathIdx + 1);
|
67
|
+
|
68
|
+
setPath(_toConsumableArray(newPath));
|
69
|
+
} else {
|
70
|
+
// if the item is on the same level as another selected item start from the parent level
|
71
|
+
if (path.find(function (p) {
|
72
|
+
return p.parent === parent;
|
73
|
+
})) {
|
74
|
+
var parentIdx = path.findIndex(function (p) {
|
75
|
+
return p.id === parent;
|
76
|
+
});
|
77
|
+
|
78
|
+
var _newPath = _toConsumableArray(path).splice(0, parentIdx + 1);
|
79
|
+
|
80
|
+
setPath([].concat(_toConsumableArray(_newPath), [{
|
81
|
+
id: id,
|
82
|
+
title: title,
|
83
|
+
parent: parent
|
84
|
+
}]));
|
85
|
+
} else {
|
86
|
+
setPath([].concat(_toConsumableArray(path), [{
|
87
|
+
id: id,
|
88
|
+
title: title,
|
89
|
+
parent: parent
|
90
|
+
}]));
|
91
|
+
}
|
92
|
+
}
|
93
|
+
}
|
94
|
+
} else {
|
95
|
+
setPath([].concat(_toConsumableArray(path), [{
|
96
|
+
id: id,
|
97
|
+
title: title
|
98
|
+
}]));
|
99
|
+
}
|
49
100
|
};
|
50
101
|
|
51
102
|
return /*#__PURE__*/React.createElement("div", {
|
@@ -55,15 +106,22 @@ export var AddSelectList = function AddSelectList(_ref) {
|
|
55
106
|
className: "".concat(blockClass)
|
56
107
|
}, /*#__PURE__*/React.createElement(StructuredListBody, null, filteredItems.map(function (item) {
|
57
108
|
return /*#__PURE__*/React.createElement(StructuredListRow, {
|
58
|
-
key: item.id
|
59
|
-
|
109
|
+
key: item.id,
|
110
|
+
className: "".concat(blockClass, "-row")
|
111
|
+
}, /*#__PURE__*/React.createElement(StructuredListCell, {
|
112
|
+
className: "".concat(blockClass, "-cell")
|
113
|
+
}, /*#__PURE__*/React.createElement("div", {
|
60
114
|
className: "".concat(blockClass, "-cell-wrapper")
|
61
115
|
}, multi ? /*#__PURE__*/React.createElement(Checkbox, {
|
62
116
|
className: "".concat(blockClass, "-checkbox"),
|
63
117
|
onChange: function onChange(value) {
|
64
118
|
return handleMultiSelection(item.id, value);
|
65
119
|
},
|
66
|
-
labelText:
|
120
|
+
labelText: !inColumn ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
|
121
|
+
className: "".concat(blockClass, "-cell-title")
|
122
|
+
}, item.title), /*#__PURE__*/React.createElement("span", {
|
123
|
+
className: "".concat(blockClass, "-cell-subtitle")
|
124
|
+
}, item.subtitle)) : item.title,
|
67
125
|
id: item.id,
|
68
126
|
checked: multiSelection.includes(item.id)
|
69
127
|
}) : /*#__PURE__*/React.createElement(RadioButton, {
|
@@ -83,6 +141,7 @@ export var AddSelectList = function AddSelectList(_ref) {
|
|
83
141
|
};
|
84
142
|
AddSelectList.propTypes = {
|
85
143
|
filteredItems: PropTypes.array,
|
144
|
+
inColumn: PropTypes.bool,
|
86
145
|
multi: PropTypes.bool,
|
87
146
|
multiSelection: PropTypes.array,
|
88
147
|
path: PropTypes.array,
|
@@ -53,7 +53,13 @@ export var AddSelectSidebar = function AddSelectSidebar(_ref) {
|
|
53
53
|
id = _ref2.id;
|
54
54
|
return /*#__PURE__*/React.createElement("div", {
|
55
55
|
className: "".concat(blockClass, "-accordion-title")
|
56
|
-
}, /*#__PURE__*/React.createElement("div",
|
56
|
+
}, /*#__PURE__*/React.createElement("div", {
|
57
|
+
className: "".concat(blockClass, "-selected-item")
|
58
|
+
}, /*#__PURE__*/React.createElement("p", {
|
59
|
+
className: "".concat(blockClass, "-selected-item-title")
|
60
|
+
}, title), /*#__PURE__*/React.createElement("p", {
|
61
|
+
className: "".concat(blockClass, "-selected-item-subtitle")
|
62
|
+
}, subtitle)), /*#__PURE__*/React.createElement(Button, {
|
57
63
|
renderIcon: SubtractAlt32,
|
58
64
|
iconDescription: removeIconDescription,
|
59
65
|
hasIconOnly: true,
|
@@ -66,6 +66,21 @@ export var DataSpreadsheet = /*#__PURE__*/React.forwardRef(function (_ref, ref)
|
|
66
66
|
activeCellCoordinates = _useState4[0],
|
67
67
|
setActiveCellCoordinates = _useState4[1];
|
68
68
|
|
69
|
+
var _useState5 = useState([]),
|
70
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
71
|
+
selectionAreas = _useState6[0],
|
72
|
+
setSelectionAreas = _useState6[1];
|
73
|
+
|
74
|
+
var _useState7 = useState(false),
|
75
|
+
_useState8 = _slicedToArray(_useState7, 2),
|
76
|
+
clickAndHoldActive = _useState8[0],
|
77
|
+
setClickAndHoldActive = _useState8[1];
|
78
|
+
|
79
|
+
var _useState9 = useState(null),
|
80
|
+
_useState10 = _slicedToArray(_useState9, 2),
|
81
|
+
currentMatcher = _useState10[0],
|
82
|
+
setCurrentMatcher = _useState10[1];
|
83
|
+
|
69
84
|
var cellSizeValue = getCellSize(cellSize);
|
70
85
|
var defaultColumn = useMemo(function () {
|
71
86
|
return {
|
@@ -108,6 +123,13 @@ export var DataSpreadsheet = /*#__PURE__*/React.forwardRef(function (_ref, ref)
|
|
108
123
|
if (activeCellHighlight) {
|
109
124
|
activeCellHighlight.remove();
|
110
125
|
}
|
126
|
+
}, [spreadsheetRef]); // Removes the cell selection elements
|
127
|
+
|
128
|
+
var removeCellSelections = useCallback(function () {
|
129
|
+
var cellSelections = spreadsheetRef.current.querySelectorAll(".".concat(blockClass, "__selection-area--element"));
|
130
|
+
Array.from(cellSelections).forEach(function (element) {
|
131
|
+
return element.remove();
|
132
|
+
});
|
111
133
|
}, [spreadsheetRef]); // Click outside useEffect
|
112
134
|
|
113
135
|
useEffect(function () {
|
@@ -116,7 +138,9 @@ export var DataSpreadsheet = /*#__PURE__*/React.forwardRef(function (_ref, ref)
|
|
116
138
|
return;
|
117
139
|
}
|
118
140
|
|
141
|
+
setSelectionAreas([]);
|
119
142
|
removeActiveCell();
|
143
|
+
removeCellSelections();
|
120
144
|
setContainerHasFocus(false);
|
121
145
|
setActiveCellCoordinates(null);
|
122
146
|
};
|
@@ -125,7 +149,7 @@ export var DataSpreadsheet = /*#__PURE__*/React.forwardRef(function (_ref, ref)
|
|
125
149
|
return function () {
|
126
150
|
document.removeEventListener('click', handleOutsideClick);
|
127
151
|
};
|
128
|
-
}, [spreadsheetRef, removeActiveCell]);
|
152
|
+
}, [spreadsheetRef, removeActiveCell, removeCellSelections]);
|
129
153
|
var createActiveCell = useCallback(function (_ref2) {
|
130
154
|
var placementElement = _ref2.placementElement,
|
131
155
|
coords = _ref2.coords,
|
@@ -172,12 +196,21 @@ export var DataSpreadsheet = /*#__PURE__*/React.forwardRef(function (_ref, ref)
|
|
172
196
|
|
173
197
|
if ([35, 36, 37, 38, 39, 40].indexOf(keyCode) > -1) {
|
174
198
|
event.preventDefault();
|
199
|
+
} // Clear out all cell selection areas if user uses any arrow key
|
200
|
+
|
201
|
+
|
202
|
+
if ([37, 38, 39, 40].indexOf(keyCode) > -1) {
|
203
|
+
if (selectionAreas !== null && selectionAreas !== void 0 && selectionAreas.length) {
|
204
|
+
setSelectionAreas([]);
|
205
|
+
removeCellSelections();
|
206
|
+
}
|
175
207
|
}
|
176
208
|
|
177
209
|
switch (keyCode) {
|
178
210
|
// Tab
|
179
211
|
case 9:
|
180
212
|
{
|
213
|
+
setSelectionAreas([]);
|
181
214
|
removeActiveCell();
|
182
215
|
setContainerHasFocus(false);
|
183
216
|
setActiveCellCoordinates(null);
|
@@ -321,7 +354,7 @@ export var DataSpreadsheet = /*#__PURE__*/React.forwardRef(function (_ref, ref)
|
|
321
354
|
break;
|
322
355
|
}
|
323
356
|
}
|
324
|
-
}, [handleInitialArrowPress, activeCellCoordinates, removeActiveCell, columns.length, rows.length]); // Adds active cell highlight to correct cell onKeyDown
|
357
|
+
}, [handleInitialArrowPress, activeCellCoordinates, selectionAreas === null || selectionAreas === void 0 ? void 0 : selectionAreas.length, removeCellSelections, removeActiveCell, columns.length, rows.length]); // Adds active cell highlight to correct cell onKeyDown
|
325
358
|
|
326
359
|
useEffect(function () {
|
327
360
|
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, "\"]"));
|
@@ -354,6 +387,13 @@ export var DataSpreadsheet = /*#__PURE__*/React.forwardRef(function (_ref, ref)
|
|
354
387
|
defaultColumn: defaultColumn,
|
355
388
|
headerGroups: headerGroups
|
356
389
|
}), /*#__PURE__*/React.createElement(DataSpreadsheetBody, {
|
390
|
+
clickAndHoldActive: clickAndHoldActive,
|
391
|
+
setClickAndHoldActive: setClickAndHoldActive,
|
392
|
+
currentMatcher: currentMatcher,
|
393
|
+
setCurrentMatcher: setCurrentMatcher,
|
394
|
+
setContainerHasFocus: setContainerHasFocus,
|
395
|
+
selectionAreas: selectionAreas,
|
396
|
+
setSelectionAreas: setSelectionAreas,
|
357
397
|
cellSize: cellSize,
|
358
398
|
defaultColumn: defaultColumn,
|
359
399
|
getTableBodyProps: getTableBodyProps,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
2
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
2
3
|
|
3
4
|
/**
|
4
5
|
* Copyright IBM Corp. 2022, 2022
|
@@ -11,6 +12,9 @@ import PropTypes from 'prop-types';
|
|
11
12
|
import { FixedSizeList } from 'react-window';
|
12
13
|
import cx from 'classnames';
|
13
14
|
import { pkg } from '../../settings';
|
15
|
+
import { deepCloneObject } from '../../global/js/utils/deepCloneObject';
|
16
|
+
import uuidv4 from '../../global/js/utils/uuidv4';
|
17
|
+
import { createCellSelectionArea } from './createCellSelectionArea';
|
14
18
|
var blockClass = "".concat(pkg.prefix, "--data-spreadsheet");
|
15
19
|
export var DataSpreadsheetBody = function DataSpreadsheetBody(_ref) {
|
16
20
|
var defaultColumn = _ref.defaultColumn,
|
@@ -19,10 +23,95 @@ export var DataSpreadsheetBody = function DataSpreadsheetBody(_ref) {
|
|
19
23
|
prepareRow = _ref.prepareRow,
|
20
24
|
rows = _ref.rows,
|
21
25
|
setActiveCellCoordinates = _ref.setActiveCellCoordinates,
|
26
|
+
selectionAreas = _ref.selectionAreas,
|
27
|
+
setContainerHasFocus = _ref.setContainerHasFocus,
|
28
|
+
setSelectionAreas = _ref.setSelectionAreas,
|
22
29
|
scrollBarSize = _ref.scrollBarSize,
|
23
|
-
totalColumnsWidth = _ref.totalColumnsWidth
|
24
|
-
|
30
|
+
totalColumnsWidth = _ref.totalColumnsWidth,
|
31
|
+
clickAndHoldActive = _ref.clickAndHoldActive,
|
32
|
+
setClickAndHoldActive = _ref.setClickAndHoldActive,
|
33
|
+
currentMatcher = _ref.currentMatcher,
|
34
|
+
setCurrentMatcher = _ref.setCurrentMatcher;
|
35
|
+
// Create cell selection areas based on selectionAreas array
|
36
|
+
useEffect(function () {
|
37
|
+
if (selectionAreas && selectionAreas.length) {
|
38
|
+
selectionAreas.map(function (area) {
|
39
|
+
if (!area.areaCreated && area.point1 && area.point2 && area.matcher) {
|
40
|
+
// Do not create a cell selection area if point1 and point2 have the same values
|
41
|
+
// Cell selections must have two distinctly different points for an area to be created
|
42
|
+
if (area.point1.row === area.point2.row && area.point1.column === area.point2.column) {
|
43
|
+
var selectionAreasClone = deepCloneObject(selectionAreas);
|
44
|
+
var indexOfCurrentArea = selectionAreasClone.findIndex(function (item) {
|
45
|
+
return item.matcher === area.matcher;
|
46
|
+
});
|
47
|
+
selectionAreasClone[indexOfCurrentArea].areaCreated = false;
|
48
|
+
selectionAreasClone[indexOfCurrentArea].point2 = null;
|
49
|
+
return setSelectionAreas(selectionAreasClone);
|
50
|
+
}
|
51
|
+
|
52
|
+
createCellSelectionArea({
|
53
|
+
area: area,
|
54
|
+
blockClass: blockClass,
|
55
|
+
selectionAreas: selectionAreas,
|
56
|
+
setSelectionAreas: setSelectionAreas
|
57
|
+
});
|
58
|
+
}
|
59
|
+
|
60
|
+
return;
|
61
|
+
});
|
62
|
+
}
|
63
|
+
}, [selectionAreas, setSelectionAreas]); // Mouse up
|
64
|
+
|
65
|
+
useEffect(function () {
|
66
|
+
var handleMouseUp = function handleMouseUp(event) {
|
67
|
+
setClickAndHoldActive(false);
|
68
|
+
var cellButton = event.target.closest(".".concat(blockClass, "__body--td"));
|
69
|
+
|
70
|
+
if (cellButton) {
|
71
|
+
var endCellCoordinates = {
|
72
|
+
row: Number(cellButton.getAttribute('data-row-index')),
|
73
|
+
column: Number(cellButton.getAttribute('data-column-index'))
|
74
|
+
};
|
75
|
+
setCurrentMatcher(null);
|
76
|
+
setSelectionAreas(function (prev) {
|
77
|
+
var selectionAreaClone = deepCloneObject(prev);
|
78
|
+
var indexOfItemToUpdate = selectionAreaClone.findIndex(function (item) {
|
79
|
+
return item.matcher === currentMatcher;
|
80
|
+
}); // No items in the array have an object that matches the value of currentMatcher
|
81
|
+
|
82
|
+
if (indexOfItemToUpdate === -1) {
|
83
|
+
return prev;
|
84
|
+
}
|
85
|
+
|
86
|
+
selectionAreaClone[indexOfItemToUpdate].point2 = endCellCoordinates;
|
87
|
+
selectionAreaClone[indexOfItemToUpdate].areaCreated = false;
|
88
|
+
return selectionAreaClone;
|
89
|
+
});
|
90
|
+
} else {
|
91
|
+
var selectionAreaClone = deepCloneObject(selectionAreas);
|
92
|
+
var indexOfItemToUpdate = selectionAreaClone.findIndex(function (item) {
|
93
|
+
return item.matcher === currentMatcher;
|
94
|
+
});
|
95
|
+
|
96
|
+
if (indexOfItemToUpdate === -1) {
|
97
|
+
return;
|
98
|
+
}
|
99
|
+
|
100
|
+
var newArray = selectionAreaClone.filter(function (item) {
|
101
|
+
return item.matcher !== currentMatcher;
|
102
|
+
});
|
103
|
+
setCurrentMatcher(null);
|
104
|
+
setSelectionAreas(newArray);
|
105
|
+
}
|
106
|
+
};
|
107
|
+
|
108
|
+
document.addEventListener('mouseup', handleMouseUp);
|
109
|
+
return function () {
|
110
|
+
document.removeEventListener('mouseup', handleMouseUp);
|
111
|
+
};
|
112
|
+
}, [selectionAreas, currentMatcher, setSelectionAreas, setClickAndHoldActive, setCurrentMatcher]); // Make sure that if the cellSize prop changes, the active
|
25
113
|
// cell also gets updated with the new size
|
114
|
+
|
26
115
|
useEffect(function () {
|
27
116
|
var listContainer = spreadsheetBodyRef === null || spreadsheetBodyRef === void 0 ? void 0 : spreadsheetBodyRef.current;
|
28
117
|
var activeCellButton = listContainer.querySelector(".".concat(blockClass, "__active-cell--highlight"));
|
@@ -33,12 +122,68 @@ export var DataSpreadsheetBody = function DataSpreadsheetBody(_ref) {
|
|
33
122
|
}, [defaultColumn === null || defaultColumn === void 0 ? void 0 : defaultColumn.rowHeight]); // onClick fn for each cell in the data spreadsheet body,
|
34
123
|
// adds the active cell highlight
|
35
124
|
|
36
|
-
var handleBodyCellClick = useCallback(function (cell, columnIndex) {
|
37
|
-
|
125
|
+
var handleBodyCellClick = useCallback(function (event, cell, columnIndex) {
|
126
|
+
var isHoldingCommandKey = event.metaKey || event.ctrlKey;
|
127
|
+
setContainerHasFocus(true);
|
128
|
+
var activeCoordinates = {
|
38
129
|
row: cell.row.index,
|
39
130
|
column: columnIndex
|
40
|
-
}
|
41
|
-
|
131
|
+
};
|
132
|
+
var tempMatcher = uuidv4();
|
133
|
+
setActiveCellCoordinates(activeCoordinates); // prevent multiple selections unless cmd key is held
|
134
|
+
// meaning that selectionAreas should only have one item by default
|
135
|
+
|
136
|
+
if (isHoldingCommandKey) {
|
137
|
+
setSelectionAreas(function (prev) {
|
138
|
+
return [].concat(_toConsumableArray(prev), [{
|
139
|
+
point1: activeCoordinates,
|
140
|
+
matcher: tempMatcher
|
141
|
+
}]);
|
142
|
+
});
|
143
|
+
} else {
|
144
|
+
// remove all previous cell selections
|
145
|
+
var cellSelections = spreadsheetBodyRef.current.querySelectorAll(".".concat(blockClass, "__selection-area--element"));
|
146
|
+
Array.from(cellSelections).forEach(function (element) {
|
147
|
+
return element.remove();
|
148
|
+
});
|
149
|
+
setSelectionAreas([{
|
150
|
+
point1: activeCoordinates,
|
151
|
+
matcher: tempMatcher
|
152
|
+
}]);
|
153
|
+
}
|
154
|
+
|
155
|
+
setCurrentMatcher(tempMatcher);
|
156
|
+
setClickAndHoldActive(true);
|
157
|
+
}, [setActiveCellCoordinates, setSelectionAreas, setContainerHasFocus, setClickAndHoldActive, setCurrentMatcher]);
|
158
|
+
var handleBodyCellHover = useCallback(function (event, cell, columnIndex) {
|
159
|
+
if (clickAndHoldActive) {
|
160
|
+
var cellCoordinates = {
|
161
|
+
row: cell.row.index,
|
162
|
+
column: columnIndex
|
163
|
+
};
|
164
|
+
setSelectionAreas(function (prev) {
|
165
|
+
var _selectionAreaClone$i, _selectionAreaClone$i2;
|
166
|
+
|
167
|
+
var selectionAreaClone = deepCloneObject(prev);
|
168
|
+
var indexOfItemToUpdate = selectionAreaClone.findIndex(function (item) {
|
169
|
+
return item.matcher === currentMatcher;
|
170
|
+
}); // No items in the array match up with the currentMatcher value
|
171
|
+
|
172
|
+
if (indexOfItemToUpdate === -1) {
|
173
|
+
return prev;
|
174
|
+
} // Do not update state if you're still hovering on the same cell
|
175
|
+
|
176
|
+
|
177
|
+
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) {
|
178
|
+
return prev;
|
179
|
+
}
|
180
|
+
|
181
|
+
selectionAreaClone[indexOfItemToUpdate].point2 = cellCoordinates;
|
182
|
+
selectionAreaClone[indexOfItemToUpdate].areaCreated = false;
|
183
|
+
return selectionAreaClone;
|
184
|
+
});
|
185
|
+
}
|
186
|
+
}, [clickAndHoldActive, currentMatcher, setSelectionAreas]); // Renders each cell in the spreadsheet body
|
42
187
|
|
43
188
|
var RenderRow = useCallback(function (_ref2) {
|
44
189
|
var index = _ref2.index,
|
@@ -65,15 +210,19 @@ export var DataSpreadsheetBody = function DataSpreadsheetBody(_ref) {
|
|
65
210
|
"data-row-index": cell.row.index,
|
66
211
|
"data-column-index": index
|
67
212
|
}, cell.getCellProps(), {
|
68
|
-
className: cx("".concat(blockClass, "__td"), "".concat(blockClass, "--interactive-cell-element")),
|
213
|
+
className: cx("".concat(blockClass, "__td"), "".concat(blockClass, "__body--td"), "".concat(blockClass, "--interactive-cell-element")),
|
69
214
|
key: "cell_".concat(index),
|
70
|
-
|
71
|
-
return handleBodyCellClick(cell, index);
|
215
|
+
onMouseDown: function onMouseDown(event) {
|
216
|
+
return handleBodyCellClick(event, cell, index);
|
72
217
|
},
|
218
|
+
onMouseOver: function onMouseOver(event) {
|
219
|
+
return handleBodyCellHover(event, cell, index);
|
220
|
+
},
|
221
|
+
onFocus: function onFocus() {},
|
73
222
|
type: "button"
|
74
223
|
}), cell.render('Cell'));
|
75
224
|
}));
|
76
|
-
}, [prepareRow, rows, defaultColumn.rowHeaderWidth, handleBodyCellClick]);
|
225
|
+
}, [prepareRow, rows, defaultColumn.rowHeaderWidth, handleBodyCellClick, handleBodyCellHover]);
|
77
226
|
var spreadsheetBodyRef = useRef();
|
78
227
|
return /*#__PURE__*/React.createElement("div", _extends({
|
79
228
|
ref: spreadsheetBodyRef,
|
@@ -87,6 +236,16 @@ export var DataSpreadsheetBody = function DataSpreadsheetBody(_ref) {
|
|
87
236
|
}, RenderRow));
|
88
237
|
};
|
89
238
|
DataSpreadsheetBody.propTypes = {
|
239
|
+
/**
|
240
|
+
* Is the user clicking and holding in the data spreadsheet body
|
241
|
+
*/
|
242
|
+
clickAndHoldActive: PropTypes.bool,
|
243
|
+
|
244
|
+
/**
|
245
|
+
* This represents the id of the current cell selection area
|
246
|
+
*/
|
247
|
+
currentMatcher: PropTypes.string,
|
248
|
+
|
90
249
|
/**
|
91
250
|
* Default spreadsheet sizing values
|
92
251
|
*/
|
@@ -126,11 +285,36 @@ DataSpreadsheetBody.propTypes = {
|
|
126
285
|
*/
|
127
286
|
scrollBarSize: PropTypes.number,
|
128
287
|
|
288
|
+
/**
|
289
|
+
* Array of selection areas
|
290
|
+
*/
|
291
|
+
selectionAreas: PropTypes.array,
|
292
|
+
|
129
293
|
/**
|
130
294
|
* Setter fn for activeCellCoordinates state value
|
131
295
|
*/
|
132
296
|
setActiveCellCoordinates: PropTypes.func,
|
133
297
|
|
298
|
+
/**
|
299
|
+
* Setter fn for clickAndHold state value
|
300
|
+
*/
|
301
|
+
setClickAndHoldActive: PropTypes.func,
|
302
|
+
|
303
|
+
/**
|
304
|
+
* Setter fn for containerHasFocus state value
|
305
|
+
*/
|
306
|
+
setContainerHasFocus: PropTypes.func,
|
307
|
+
|
308
|
+
/**
|
309
|
+
* Setter fn for currentMatcher state value
|
310
|
+
*/
|
311
|
+
setCurrentMatcher: PropTypes.func,
|
312
|
+
|
313
|
+
/**
|
314
|
+
* Setter fn for selectionAreas state value
|
315
|
+
*/
|
316
|
+
setSelectionAreas: PropTypes.func,
|
317
|
+
|
134
318
|
/**
|
135
319
|
* The total columns width
|
136
320
|
*/
|
@@ -40,6 +40,6 @@ export var createActiveCellFn = function createActiveCellFn(_ref) {
|
|
40
40
|
activeCellButton.focus();
|
41
41
|
|
42
42
|
if (typeof (coords === null || coords === void 0 ? void 0 : coords.column) === 'number' && typeof (coords === null || coords === void 0 ? void 0 : coords.row) === 'number') {
|
43
|
-
onActiveCellChange(activeCellValue);
|
43
|
+
onActiveCellChange === null || onActiveCellChange === void 0 ? void 0 : onActiveCellChange(activeCellValue);
|
44
44
|
}
|
45
45
|
};
|
@@ -0,0 +1,45 @@
|
|
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 { deepCloneObject } from '../../global/js/utils/deepCloneObject';
|
9
|
+
export var createCellSelectionArea = function createCellSelectionArea(_ref) {
|
10
|
+
var area = _ref.area,
|
11
|
+
blockClass = _ref.blockClass,
|
12
|
+
selectionAreas = _ref.selectionAreas,
|
13
|
+
setSelectionAreas = _ref.setSelectionAreas;
|
14
|
+
var greatestRow = Math.max(area.point1.row, area.point2.row);
|
15
|
+
var greatestColumn = Math.max(area.point1.column, area.point2.column);
|
16
|
+
var lowestRowIndex = Math.min(area.point1.row, area.point2.row);
|
17
|
+
var lowestColumnIndex = Math.min(area.point1.column, area.point2.column);
|
18
|
+
var point1Element = document.querySelector("[data-row-index=\"".concat(area.point1.row, "\"][data-column-index=\"").concat(area.point1.column, "\"]"));
|
19
|
+
var selectionAreaCellWidth = point1Element.offsetWidth;
|
20
|
+
var selectionAreaCellHeight = point1Element.offsetHeight;
|
21
|
+
var selectionAreaTotalWidth = selectionAreaCellWidth * (greatestColumn - lowestColumnIndex + 1);
|
22
|
+
var selectionAreaTotalHeight = selectionAreaCellHeight * (greatestRow - lowestRowIndex + 1);
|
23
|
+
var bodyContainer = document.querySelector(".".concat(blockClass, "__list--container")).firstElementChild;
|
24
|
+
var placementElement = bodyContainer.querySelector("[data-row-index=\"".concat(lowestRowIndex, "\"][data-column-index=\"").concat(lowestColumnIndex, "\"]"));
|
25
|
+
var relativePosition = {
|
26
|
+
top: placementElement.getBoundingClientRect().top - bodyContainer.getBoundingClientRect().top,
|
27
|
+
left: placementElement.getBoundingClientRect().left - bodyContainer.getBoundingClientRect().left
|
28
|
+
};
|
29
|
+
var selectionAreaElement = document.querySelector("[data-matcher-id=\"".concat(area.matcher, "\"]")) || document.createElement('div');
|
30
|
+
selectionAreaElement.classList.add("".concat(blockClass, "__selection-area--element"));
|
31
|
+
selectionAreaElement.setAttribute('data-matcher-id', area.matcher);
|
32
|
+
selectionAreaElement.style.width = px(selectionAreaTotalWidth);
|
33
|
+
selectionAreaElement.style.height = px(selectionAreaTotalHeight);
|
34
|
+
selectionAreaElement.style.left = px(relativePosition.left);
|
35
|
+
selectionAreaElement.style.top = px(relativePosition.top);
|
36
|
+
bodyContainer.appendChild(selectionAreaElement);
|
37
|
+
var selectionAreasClone = deepCloneObject(selectionAreas);
|
38
|
+
var indexOfCurrentArea = selectionAreasClone.findIndex(function (item) {
|
39
|
+
return item.matcher === area.matcher;
|
40
|
+
}); // We need to add another property to the selectionAreas object array to
|
41
|
+
// let us know if an area has been created for each item already, ie createdArea: true
|
42
|
+
|
43
|
+
selectionAreasClone[indexOfCurrentArea].areaCreated = true;
|
44
|
+
setSelectionAreas(selectionAreasClone);
|
45
|
+
};
|
@@ -2,7 +2,7 @@ import _extends from "@babel/runtime/helpers/extends";
|
|
2
2
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
3
3
|
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
4
4
|
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
|
5
|
-
var _excluded = ["cancelDescription", "className", "disabled", "
|
5
|
+
var _excluded = ["cancelDescription", "className", "disabled", "editAlwaysVisible", "editDescription", "id", "invalid", "invalidText", "labelText", "light", "onCancel", "onSave", "onChange", "placeholder", "saveDescription", "size", "value", "warn", "warnText"];
|
6
6
|
|
7
7
|
/**
|
8
8
|
* Copyright IBM Corp. 2022, 2022
|
@@ -41,8 +41,8 @@ export var InlineEdit = /*#__PURE__*/React.forwardRef(function (_ref, refIn) {
|
|
41
41
|
var cancelDescription = _ref.cancelDescription,
|
42
42
|
className = _ref.className,
|
43
43
|
disabled = _ref.disabled,
|
44
|
+
editAlwaysVisible = _ref.editAlwaysVisible,
|
44
45
|
editDescription = _ref.editDescription,
|
45
|
-
editVisibleOnHoverOnly = _ref.editVisibleOnHoverOnly,
|
46
46
|
id = _ref.id,
|
47
47
|
invalid = _ref.invalid,
|
48
48
|
invalidText = _ref.invalidText,
|
@@ -89,6 +89,7 @@ export var InlineEdit = /*#__PURE__*/React.forwardRef(function (_ref, refIn) {
|
|
89
89
|
};
|
90
90
|
|
91
91
|
var handleEdit = function handleEdit(ev) {
|
92
|
+
/* istanbul ignore else */
|
92
93
|
if (!disabled) {
|
93
94
|
var rightOfInput = ev.currentTarget.classList.contains("".concat(blockClass, "__edit")) || ev.target.classList.contains("".concat(blockClass, "__after-input-elements"));
|
94
95
|
var leftOfInput = ev.currentTarget = ev.target.classList.contains("".concat(blockClass)); // clicking on the content editable element should not set either of these to true
|
@@ -135,9 +136,12 @@ export var InlineEdit = /*#__PURE__*/React.forwardRef(function (_ref, refIn) {
|
|
135
136
|
if (onChange) {
|
136
137
|
onChange(refInput.current.innerText);
|
137
138
|
}
|
138
|
-
};
|
139
|
+
}; // pasting into contentEditable not supported by userEvent
|
140
|
+
|
139
141
|
|
140
|
-
var handlePaste =
|
142
|
+
var handlePaste =
|
143
|
+
/* istanbul ignore next */
|
144
|
+
function handlePaste(ev) {
|
141
145
|
ev.preventDefault(); // Get clipboard as plain text
|
142
146
|
|
143
147
|
var text = (ev.clipboardData || window.clipboardData).getData('text/plain'); // remove \n
|
@@ -182,9 +186,16 @@ export var InlineEdit = /*#__PURE__*/React.forwardRef(function (_ref, refIn) {
|
|
182
186
|
};
|
183
187
|
|
184
188
|
var handleKeyDown = function handleKeyDown(ev) {
|
185
|
-
|
186
|
-
|
187
|
-
|
189
|
+
switch (ev.key) {
|
190
|
+
case 'Enter':
|
191
|
+
ev.preventDefault();
|
192
|
+
refInput.current.blur(); // will cause save
|
193
|
+
|
194
|
+
break;
|
195
|
+
|
196
|
+
case 'Escape':
|
197
|
+
handleCancel();
|
198
|
+
break;
|
188
199
|
}
|
189
200
|
};
|
190
201
|
/*
|
@@ -266,7 +277,7 @@ export var InlineEdit = /*#__PURE__*/React.forwardRef(function (_ref, refIn) {
|
|
266
277
|
disabled: value === internalValue
|
267
278
|
})) : /*#__PURE__*/React.createElement(Button, {
|
268
279
|
"aria-hidden": "true",
|
269
|
-
className: cx("".concat(blockClass, "__edit"), _defineProperty({}, "".concat(blockClass, "__edit--
|
280
|
+
className: cx("".concat(blockClass, "__edit"), _defineProperty({}, "".concat(blockClass, "__edit--always-visible"), editAlwaysVisible)),
|
270
281
|
kind: "ghost",
|
271
282
|
hasIconOnly: true,
|
272
283
|
iconDescription: editDescription,
|
@@ -306,15 +317,14 @@ InlineEdit.propTypes = {
|
|
306
317
|
disabled: PropTypes.bool,
|
307
318
|
|
308
319
|
/**
|
309
|
-
*
|
320
|
+
* By default the edit icon is shown on hover only.
|
310
321
|
*/
|
311
|
-
|
322
|
+
editAlwaysVisible: PropTypes.bool,
|
312
323
|
|
313
324
|
/**
|
314
|
-
*
|
315
|
-
* the edit icon is redundant. E.g. a spreadsheet a property panel.
|
325
|
+
* Label for the edit button
|
316
326
|
*/
|
317
|
-
|
327
|
+
editDescription: PropTypes.string.isRequired,
|
318
328
|
|
319
329
|
/**
|
320
330
|
* ID for inline edit
|