@carbon/ibm-products 1.8.0 → 1.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|