@carbon/ibm-products 1.32.1 → 1.33.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. package/css/index-full-carbon.css +132 -13
  2. package/css/index-full-carbon.css.map +1 -1
  3. package/css/index-full-carbon.min.css +5 -1
  4. package/css/index-full-carbon.min.css.map +1 -1
  5. package/css/index-without-carbon-released-only.css +6 -2
  6. package/css/index-without-carbon-released-only.css.map +1 -1
  7. package/css/index-without-carbon-released-only.min.css +5 -1
  8. package/css/index-without-carbon-released-only.min.css.map +1 -1
  9. package/css/index-without-carbon.css +132 -13
  10. package/css/index-without-carbon.css.map +1 -1
  11. package/css/index-without-carbon.min.css +5 -1
  12. package/css/index-without-carbon.min.css.map +1 -1
  13. package/css/index.css +132 -13
  14. package/css/index.css.map +1 -1
  15. package/css/index.min.css +5 -1
  16. package/css/index.min.css.map +1 -1
  17. package/es/components/CreateTearsheetNarrow/CreateTearsheetNarrow.js +2 -2
  18. package/es/components/DataSpreadsheet/hooks/useMultipleKeyTracking.js +4 -3
  19. package/es/components/Datagrid/Datagrid/DatagridContent.js +29 -6
  20. package/es/components/Datagrid/Datagrid/addons/InlineEdit/InlineEditCell/InlineEditCell.js +84 -38
  21. package/es/components/Datagrid/Datagrid/addons/InlineEdit/handleGridKeyPress.js +2 -2
  22. package/es/components/Datagrid/Datagrid/addons/InlineEdit/handleMultipleKeys.js +21 -0
  23. package/es/components/Datagrid/utils/getInlineEditColumns.js +25 -7
  24. package/es/components/Datagrid/utils/makeData.js +10 -1
  25. package/lib/components/CreateTearsheetNarrow/CreateTearsheetNarrow.js +2 -2
  26. package/lib/components/DataSpreadsheet/hooks/useMultipleKeyTracking.js +4 -3
  27. package/lib/components/Datagrid/Datagrid/DatagridContent.js +28 -4
  28. package/lib/components/Datagrid/Datagrid/addons/InlineEdit/InlineEditCell/InlineEditCell.js +84 -38
  29. package/lib/components/Datagrid/Datagrid/addons/InlineEdit/handleGridKeyPress.js +2 -2
  30. package/lib/components/Datagrid/Datagrid/addons/InlineEdit/handleMultipleKeys.js +22 -0
  31. package/lib/components/Datagrid/utils/getInlineEditColumns.js +25 -7
  32. package/lib/components/Datagrid/utils/makeData.js +10 -1
  33. package/package.json +2 -2
  34. package/scss/components/Datagrid/_storybook-styles.scss +7 -0
  35. package/scss/components/Datagrid/styles/_datagrid.scss +0 -5
  36. package/scss/components/Datagrid/styles/_useInlineEdit.scss +177 -2
  37. package/scss/components/InlineEdit/_inline-edit.scss +4 -2
@@ -24,7 +24,7 @@ import { usePreviousValue } from '../../../../../../global/js/hooks';
24
24
  import { prepareProps } from '../../../../../../global/js/utils/props-helper';
25
25
  var blockClass = "".concat(pkg.prefix, "--datagrid");
26
26
  export var InlineEditCell = function InlineEditCell(_ref) {
27
- var _cx3;
27
+ var _config$validator, _cx3;
28
28
 
29
29
  var cell = _ref.cell,
30
30
  config = _ref.config,
@@ -89,7 +89,24 @@ export var InlineEditCell = function InlineEditCell(_ref) {
89
89
  return item.id === columnId;
90
90
  });
91
91
  setCellLabel(typeof columnLabel.Header === 'string' ? columnLabel.Header : 'Inline edit cell label'); // eslint-disable-next-line react-hooks/exhaustive-deps
92
- }, []); // If you are in edit mode and click outside of the cell,
92
+ }, []); // Reverts cellValue back to initialValue when exiting edit mode via clicking outside
93
+ // of the cell (either on a regular cell or clicking into another inline edit cell) and the
94
+ // edit input is in an invalid state
95
+
96
+ useEffect(function () {
97
+ if ((previousState === null || previousState === void 0 ? void 0 : previousState.editId) === cellId && !editId || (previousState === null || previousState === void 0 ? void 0 : previousState.editId) === cellId && cellId !== editId) {
98
+ var _ref3 = config || {},
99
+ validator = _ref3.validator;
100
+
101
+ var isInvalid = validator === null || validator === void 0 ? void 0 : validator(cellValue);
102
+
103
+ if (isInvalid) {
104
+ setCellValue(initialValue);
105
+ saveCellData(initialValue);
106
+ return;
107
+ }
108
+ }
109
+ }, [previousState === null || previousState === void 0 ? void 0 : previousState.editId, editId, cellId, cellValue, config, initialValue, saveCellData]); // If you are in edit mode and click outside of the cell,
93
110
  // this changes the cell back to the InlineEditButton
94
111
 
95
112
  useEffect(function () {
@@ -201,6 +218,16 @@ export var InlineEditCell = function InlineEditCell(_ref) {
201
218
  return;
202
219
  }
203
220
 
221
+ var _ref4 = config || {},
222
+ validator = _ref4.validator;
223
+
224
+ var isInvalid = validator === null || validator === void 0 ? void 0 : validator(cellValue); // If an invalid state is detected, Tab/Enter should not do anything
225
+ // until the input has a valid state once again
226
+
227
+ if (isInvalid) {
228
+ return;
229
+ }
230
+
204
231
  var newCellId = getNewCellId(key);
205
232
  saveCellData(cellValue);
206
233
  setInitialValue(cellValue);
@@ -251,8 +278,8 @@ export var InlineEditCell = function InlineEditCell(_ref) {
251
278
  };
252
279
 
253
280
  var renderSelectCell = function renderSelectCell() {
254
- var _ref3 = config || {},
255
- inputProps = _ref3.inputProps;
281
+ var _ref5 = config || {},
282
+ inputProps = _ref5.inputProps;
256
283
 
257
284
  return /*#__PURE__*/React.createElement(Dropdown, _extends({
258
285
  id: cellId,
@@ -288,8 +315,8 @@ export var InlineEditCell = function InlineEditCell(_ref) {
288
315
  },
289
316
  downshiftProps: {
290
317
  onStateChange: function onStateChange(downshiftState) {
291
- var _ref4 = downshiftState || {},
292
- isOpen = _ref4.isOpen; // !isOpen does not work in this case because a state change occurs on hover of the
318
+ var _ref6 = downshiftState || {},
319
+ isOpen = _ref6.isOpen; // !isOpen does not work in this case because a state change occurs on hover of the
293
320
  // menu items and isOpen is changed to undefined which causes dispatch to be called unexpectedly
294
321
 
295
322
 
@@ -390,6 +417,55 @@ export var InlineEditCell = function InlineEditCell(_ref) {
390
417
  return null;
391
418
  };
392
419
 
420
+ var renderNumberInput = function renderNumberInput() {
421
+ var _ref7 = config || {},
422
+ validator = _ref7.validator;
423
+
424
+ return /*#__PURE__*/React.createElement(NumberInput, _extends({
425
+ placeholder: placeholder,
426
+ label: cellLabel
427
+ }, inputProps, {
428
+ id: cellId,
429
+ hideLabel: true,
430
+ defaultValue: cellValue,
431
+ invalid: validator === null || validator === void 0 ? void 0 : validator(cellValue),
432
+ invalidText: (inputProps === null || inputProps === void 0 ? void 0 : inputProps.invalidText) || 'Provide missing invalidText',
433
+ onChange: function onChange(event) {
434
+ setCellValue(event.imaginaryTarget.value);
435
+
436
+ if (inputProps.onChange) {
437
+ inputProps.onChange(event.imaginaryTarget.value);
438
+ }
439
+ },
440
+ ref: numberInputRef
441
+ }));
442
+ };
443
+
444
+ var renderTextInput = function renderTextInput() {
445
+ var _ref8 = config || {},
446
+ validator = _ref8.validator;
447
+
448
+ var isInvalid = validator === null || validator === void 0 ? void 0 : validator(cellValue);
449
+ return /*#__PURE__*/React.createElement(TextInput, _extends({
450
+ labelText: cellLabel,
451
+ placeholder: placeholder
452
+ }, inputProps, {
453
+ id: cellId,
454
+ hideLabel: true,
455
+ defaultValue: cellValue,
456
+ invalid: isInvalid,
457
+ invalidText: (inputProps === null || inputProps === void 0 ? void 0 : inputProps.invalidText) || 'Provide missing invalidText',
458
+ onChange: function onChange(event) {
459
+ setCellValue(event.target.value);
460
+
461
+ if (inputProps.onChange) {
462
+ inputProps.onChange(event.target.value);
463
+ }
464
+ },
465
+ ref: textInputRef
466
+ }));
467
+ };
468
+
393
469
  return (
394
470
  /*#__PURE__*/
395
471
  // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
@@ -402,7 +478,7 @@ export var InlineEditCell = function InlineEditCell(_ref) {
402
478
  "data-inline-type": type,
403
479
  onClick: !nonEditCell ? handleInlineCellClick : addActiveState,
404
480
  onKeyDown: !nonEditCell ? handleKeyDown : null,
405
- className: cx("".concat(blockClass, "__inline-edit--outer-cell-button"), (_cx3 = {}, _defineProperty(_cx3, "".concat(blockClass, "__inline-edit--outer-cell-button--").concat(rowSize), rowSize), _defineProperty(_cx3, "".concat(blockClass, "__inline-edit--outer-cell-button--lg"), !rowSize), _cx3))
481
+ className: cx("".concat(blockClass, "__inline-edit--outer-cell-button"), (_cx3 = {}, _defineProperty(_cx3, "".concat(blockClass, "__inline-edit--outer-cell-button--").concat(rowSize), rowSize), _defineProperty(_cx3, "".concat(blockClass, "__inline-edit--outer-cell-button--lg"), !rowSize), _defineProperty(_cx3, "".concat(blockClass, "__inline-edit--outer-cell-button--invalid"), config === null || config === void 0 ? void 0 : (_config$validator = config.validator) === null || _config$validator === void 0 ? void 0 : _config$validator.call(config, cellValue)), _cx3))
406
482
  }, !inEditMode && /*#__PURE__*/React.createElement(InlineEditButton, {
407
483
  isActiveCell: cellId === activeCellId,
408
484
  renderIcon: setRenderIcon(),
@@ -415,37 +491,7 @@ export var InlineEditCell = function InlineEditCell(_ref) {
415
491
  totalInlineEditColumns: totalInlineEditColumns,
416
492
  totalColumns: totalColumns,
417
493
  type: type
418
- }), !nonEditCell && inEditMode && cellId === activeCellId && /*#__PURE__*/React.createElement(React.Fragment, null, type === 'text' && /*#__PURE__*/React.createElement(TextInput, _extends({
419
- labelText: cellLabel,
420
- placeholder: placeholder
421
- }, inputProps, {
422
- id: cellId,
423
- hideLabel: true,
424
- defaultValue: cellValue,
425
- onChange: function onChange(event) {
426
- setCellValue(event.target.value);
427
-
428
- if (inputProps.onChange) {
429
- inputProps.onChange(event.target.value);
430
- }
431
- },
432
- ref: textInputRef
433
- })), type === 'number' && /*#__PURE__*/React.createElement(NumberInput, _extends({
434
- placeholder: placeholder,
435
- label: cellLabel
436
- }, inputProps, {
437
- id: cellId,
438
- hideLabel: true,
439
- defaultValue: cellValue,
440
- onChange: function onChange(event) {
441
- setCellValue(event.imaginaryTarget.value);
442
-
443
- if (inputProps.onChange) {
444
- inputProps.onChange(event.imaginaryTarget.value);
445
- }
446
- },
447
- ref: numberInputRef
448
- })), type === 'selection' && renderSelectCell(), type === 'date' && renderDateCell()))
494
+ }), !nonEditCell && inEditMode && cellId === activeCellId && /*#__PURE__*/React.createElement(React.Fragment, null, type === 'text' && renderTextInput(), type === 'number' && renderNumberInput(), type === 'selection' && renderSelectCell(), type === 'date' && renderDateCell()))
449
495
  );
450
496
  };
451
497
  InlineEditCell.propTypes = {
@@ -35,11 +35,11 @@ export var handleGridKeyPress = function handleGridKeyPress(_ref) {
35
35
  type: 'EXIT_EDIT_MODE',
36
36
  payload: activeCellId
37
37
  });
38
+ var inlineEditArea = document.querySelector("#".concat(instance.tableId, " .").concat(blockClass, "__table-with-inline-edit"));
39
+ inlineEditArea.focus();
38
40
  }
39
41
 
40
42
  event.preventDefault();
41
- var inlineEditArea = document.querySelector("#".concat(instance.tableId, " .").concat(blockClass, "__table-with-inline-edit"));
42
- inlineEditArea.focus();
43
43
  return;
44
44
  }
45
45
 
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import { includesResourceKey } from '../../../../DataSpreadsheet/utils/handleMultipleKeys';
8
8
  import { pkg } from '../../../../../settings';
9
+ import { getFocusableElements } from '../../../../../global/js/utils/getFocusableElements';
9
10
  var blockClass = "".concat(pkg.prefix, "--datagrid");
10
11
  export var handleMultipleKeys = function handleMultipleKeys(_ref) {
11
12
  var usingMac = _ref.usingMac,
@@ -62,5 +63,25 @@ export var handleMultipleKeys = function handleMultipleKeys(_ref) {
62
63
  });
63
64
  }, 250);
64
65
  }
66
+ } // Shift + Tab
67
+ // This should remove the active grid state
68
+
69
+
70
+ if ((keysPressedList.includes('ShiftLeft') || keysPressedList.includes('ShiftRight')) && keysPressedList.includes('Tab')) {
71
+ dispatch({
72
+ type: 'REMOVE_GRID_ACTIVE_FOCUS',
73
+ payload: activeCellId
74
+ });
75
+ var tableElement = document.querySelector("#".concat(instance.tableId));
76
+ var datagridFocusableElements = getFocusableElements(tableElement);
77
+ var indexOfTable = datagridFocusableElements.findIndex(function (item) {
78
+ return item instanceof HTMLTableElement;
79
+ });
80
+
81
+ if (indexOfTable && Number.isFinite(indexOfTable)) {
82
+ var _datagridFocusableEle;
83
+
84
+ (_datagridFocusableEle = datagridFocusableElements[indexOfTable]) === null || _datagridFocusableEle === void 0 ? void 0 : _datagridFocusableEle.focus();
85
+ }
65
86
  }
66
87
  };
@@ -31,25 +31,43 @@ export var getInlineEditColumns = function getInlineEditColumns() {
31
31
  accessor: 'firstName',
32
32
  inlineEdit: {
33
33
  type: 'text',
34
- inputProps: {} // These props are passed to the Carbon component used for inline editing
35
-
34
+ // required for including validation, this is used to set the invalid prop internally
35
+ validator: function validator(n) {
36
+ return n.length >= 40;
37
+ },
38
+ // These props are passed to the Carbon component used for inline editing
39
+ inputProps: {
40
+ invalidText: 'Invalid text, character count must be less than 40'
41
+ }
36
42
  }
37
43
  }, {
38
44
  Header: 'Last Name',
39
45
  accessor: 'lastName',
40
46
  inlineEdit: {
41
47
  type: 'text',
42
- inputProps: {} // These props are passed to the Carbon component used for inline editing
43
-
48
+ // required for including validation, this is used to set the invalid prop internally
49
+ validator: function validator(n) {
50
+ return n.length >= 40;
51
+ },
52
+ // These props are passed to the Carbon component used for inline editing
53
+ inputProps: {
54
+ invalidText: 'Invalid text, character count must be less than 40'
55
+ }
44
56
  }
45
57
  }, {
46
58
  Header: 'Age',
47
59
  accessor: 'age',
48
60
  width: 120,
49
61
  inlineEdit: {
62
+ // required for including validation, this is used to set the invalid prop internally
63
+ validator: function validator(n) {
64
+ return n && n < 18;
65
+ },
50
66
  type: 'number',
51
- inputProps: {} // These props are passed to the Carbon component used for inline editing
52
-
67
+ // These props are passed to the Carbon component used for inline editing
68
+ inputProps: {
69
+ invalidText: 'Invalid number, must be 18 or greater'
70
+ }
53
71
  }
54
72
  }, {
55
73
  Header: 'Visits',
@@ -86,7 +104,7 @@ export var getInlineEditColumns = function getInlineEditColumns() {
86
104
  // These props are passed to the Carbon component used for inline editing
87
105
  items: inlineEditSelectItems,
88
106
  onChange: function onChange(item) {
89
- return console.log(item);
107
+ console.log(item);
90
108
  }
91
109
  }
92
110
  }
@@ -65,6 +65,14 @@ var renderStatusIcon = function renderStatusIcon(statusChance) {
65
65
  return /*#__PURE__*/React.createElement(StatusIcon, iconProps);
66
66
  };
67
67
 
68
+ var renderDocLink = function renderDocLink(statusChance) {
69
+ var docLinkObj = {
70
+ href: statusChance > 0.66 ? 'http://carbondesignsystem.com/' : statusChance > 0.33 ? 'https://pages.github.ibm.com/cdai-design/pal/' : 'http://carbon-for-ibm-products.netlify.app/',
71
+ text: statusChance > 0.66 ? 'Carbon Design System' : statusChance > 0.33 ? 'Carbon for IBM Products PAL' : 'Carbon for IBM Products storybook'
72
+ };
73
+ return docLinkObj;
74
+ };
75
+
68
76
  var newPerson = function newPerson() {
69
77
  var statusChance = Math.random();
70
78
  var initialChartTypeIndex = getRandomInteger(0, 2);
@@ -169,7 +177,8 @@ var newPerson = function newPerson() {
169
177
  chartType: initialChartTypeIndex === 0 ? inlineEditSelectItems[0] : initialChartTypeIndex === 1 ? inlineEditSelectItems[1] : inlineEditSelectItems[2],
170
178
  activeSince: statusChance > 0.66 ? activeSinceDate : statusChance > 0.33 ? yesterdayDate : twoDaysAgoDate,
171
179
  bonus: "$\r".concat(getRandomInteger(100, 500, 2)),
172
- status_icon: renderStatusIcon(statusChance)
180
+ status_icon: renderStatusIcon(statusChance),
181
+ doc_link: renderDocLink(statusChance)
173
182
  };
174
183
  };
175
184
 
@@ -124,9 +124,9 @@ CreateTearsheetNarrow.propTypes = {
124
124
  formDescription: _propTypes.default.node,
125
125
 
126
126
  /**
127
- * Specifies a required field that provides a title for a form
127
+ * Specifies an optional field that provides a title for a form
128
128
  */
129
- formTitle: _propTypes.default.node.isRequired,
129
+ formTitle: _propTypes.default.node,
130
130
 
131
131
  /**
132
132
  * A label for the tearsheet, displayed in the header area of the tearsheet
@@ -49,7 +49,8 @@ var useMultipleKeyTracking = function useMultipleKeyTracking(_ref) {
49
49
 
50
50
  var previousState = (0, _hooks.usePreviousValue)({
51
51
  isEditing: isEditing,
52
- windowFocused: windowFocused
52
+ windowFocused: windowFocused,
53
+ containerHasFocus: containerHasFocus
53
54
  }); // useEffect to check for window focus, if window loses focus
54
55
  // we need to clear out the keysPressedList
55
56
 
@@ -136,11 +137,11 @@ var useMultipleKeyTracking = function useMultipleKeyTracking(_ref) {
136
137
  ref.current.onkeydown = undefined;
137
138
  ref.current.onkeyup = undefined;
138
139
 
139
- if (!(previousState !== null && previousState !== void 0 && previousState.isEditing) && isEditing) {
140
+ if (!(previousState !== null && previousState !== void 0 && previousState.isEditing) && isEditing || previousState !== null && previousState !== void 0 && previousState.containerHasFocus && !containerHasFocus) {
140
141
  setKeysPressedList([]);
141
142
  }
142
143
  }
143
- }, [keysPressedList, containerHasFocus, ref, isEditing, previousState === null || previousState === void 0 ? void 0 : previousState.isEditing, windowFocused, previousState === null || previousState === void 0 ? void 0 : previousState.windowFocused, usingMac]);
144
+ }, [keysPressedList, containerHasFocus, ref, isEditing, previousState === null || previousState === void 0 ? void 0 : previousState.isEditing, previousState === null || previousState === void 0 ? void 0 : previousState.containerHasFocus, windowFocused, previousState === null || previousState === void 0 ? void 0 : previousState.windowFocused, usingMac]);
144
145
  return {
145
146
  keysPressedList: keysPressedList,
146
147
  windowFocused: windowFocused,
@@ -21,6 +21,8 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
21
21
 
22
22
  var _carbonComponentsReact = require("carbon-components-react");
23
23
 
24
+ var _layout = require("@carbon/layout");
25
+
24
26
  var _DatagridHead = _interopRequireDefault(require("./DatagridHead"));
25
27
 
26
28
  var _DatagridBody = _interopRequireDefault(require("./DatagridBody"));
@@ -48,6 +50,8 @@ var TableContainer = _carbonComponentsReact.DataTable.TableContainer,
48
50
  var blockClass = "".concat(_settings.pkg.prefix, "--datagrid");
49
51
 
50
52
  var DatagridContent = function DatagridContent(_ref) {
53
+ var _cx4;
54
+
51
55
  var datagridState = _ref.datagridState;
52
56
 
53
57
  var _useContext = (0, _react.useContext)(_InlineEditContext.InlineEditContext),
@@ -69,7 +73,10 @@ var DatagridContent = function DatagridContent(_ref) {
69
73
  gridTitle = datagridState.gridTitle,
70
74
  gridDescription = datagridState.gridDescription,
71
75
  useDenseHeader = datagridState.useDenseHeader,
72
- withInlineEdit = datagridState.withInlineEdit;
76
+ withInlineEdit = datagridState.withInlineEdit,
77
+ tableId = datagridState.tableId,
78
+ DatagridActions = datagridState.DatagridActions,
79
+ totalColumnsWidth = datagridState.totalColumnsWidth;
73
80
  var rows = DatagridPagination && datagridState.page || datagridState.rows;
74
81
  var gridActive = state.gridActive,
75
82
  editId = state.editId;
@@ -124,10 +131,24 @@ var DatagridContent = function DatagridContent(_ref) {
124
131
  isEditing: !!editId
125
132
  }),
126
133
  keysPressedList = _useMultipleKeyTracki.keysPressedList,
127
- usingMac = _useMultipleKeyTracki.usingMac;
134
+ usingMac = _useMultipleKeyTracki.usingMac; // Provides a width for the region outline for useInlineEdit
135
+
128
136
 
137
+ (0, _react.useEffect)(function () {
138
+ if (!withInlineEdit) {
139
+ return;
140
+ }
141
+
142
+ var gridElement = document.querySelector("#".concat(tableId));
143
+ var tableHeader = document.querySelector(".".concat(_settings.carbon.prefix, "--data-table-header"));
144
+ gridElement.style.setProperty("--".concat(blockClass, "--grid-width"), (0, _layout.px)(totalColumnsWidth + 32));
145
+
146
+ if (gridActive) {
147
+ gridElement.style.setProperty("--".concat(blockClass, "--grid-header-height"), (0, _layout.px)((tableHeader === null || tableHeader === void 0 ? void 0 : tableHeader.clientHeight) || 0));
148
+ }
149
+ }, [withInlineEdit, tableId, totalColumnsWidth, datagridState, gridActive]);
129
150
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(TableContainer, {
130
- className: (0, _classnames.default)("".concat(blockClass, "__grid-container"), withVirtualScroll || fullHeightDatagrid ? "".concat(blockClass, "__full-height") : '', DatagridPagination ? "".concat(blockClass, "__with-pagination") : '', useDenseHeader ? "".concat(blockClass, "__dense-header") : ''),
151
+ className: (0, _classnames.default)("".concat(blockClass, "__grid-container"), withVirtualScroll || fullHeightDatagrid ? "".concat(blockClass, "__full-height") : '', DatagridPagination ? "".concat(blockClass, "__with-pagination") : '', useDenseHeader ? "".concat(blockClass, "__dense-header") : '', (_cx4 = {}, (0, _defineProperty2.default)(_cx4, "".concat(blockClass, "__grid-container-grid-active"), gridActive), (0, _defineProperty2.default)(_cx4, "".concat(blockClass, "__grid-container-inline-edit"), withInlineEdit), (0, _defineProperty2.default)(_cx4, "".concat(blockClass, "__grid-container-grid-active--without-toolbar"), withInlineEdit && !DatagridActions), _cx4)),
131
152
  title: gridTitle,
132
153
  description: gridDescription
133
154
  }, /*#__PURE__*/_react.default.createElement(_DatagridToolbar.default, datagridState), /*#__PURE__*/_react.default.createElement("div", {
@@ -147,6 +168,7 @@ DatagridContent.propTypes = {
147
168
  datagridState: _propTypes.default.shape({
148
169
  getTableProps: _propTypes.default.func,
149
170
  withVirtualScroll: _propTypes.default.bool,
171
+ DatagridActions: _propTypes.default.oneOfType([_propTypes.default.element, _propTypes.default.func]),
150
172
  DatagridPagination: _propTypes.default.oneOfType([_propTypes.default.element, _propTypes.default.func]),
151
173
  CustomizeColumnsModal: _propTypes.default.element,
152
174
  isFetching: _propTypes.default.bool,
@@ -159,6 +181,8 @@ DatagridContent.propTypes = {
159
181
  gridTitle: _propTypes.default.node,
160
182
  gridDescription: _propTypes.default.node,
161
183
  page: _propTypes.default.arrayOf(_propTypes.default.object),
162
- rows: _propTypes.default.arrayOf(_propTypes.default.object)
184
+ rows: _propTypes.default.arrayOf(_propTypes.default.object),
185
+ tableId: _propTypes.default.string,
186
+ totalColumnsWidth: _propTypes.default.number
163
187
  })
164
188
  };
@@ -46,7 +46,7 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
46
46
  var blockClass = "".concat(_settings.pkg.prefix, "--datagrid");
47
47
 
48
48
  var InlineEditCell = function InlineEditCell(_ref) {
49
- var _cx3;
49
+ var _config$validator, _cx3;
50
50
 
51
51
  var cell = _ref.cell,
52
52
  config = _ref.config,
@@ -111,7 +111,24 @@ var InlineEditCell = function InlineEditCell(_ref) {
111
111
  return item.id === columnId;
112
112
  });
113
113
  setCellLabel(typeof columnLabel.Header === 'string' ? columnLabel.Header : 'Inline edit cell label'); // eslint-disable-next-line react-hooks/exhaustive-deps
114
- }, []); // If you are in edit mode and click outside of the cell,
114
+ }, []); // Reverts cellValue back to initialValue when exiting edit mode via clicking outside
115
+ // of the cell (either on a regular cell or clicking into another inline edit cell) and the
116
+ // edit input is in an invalid state
117
+
118
+ (0, _react.useEffect)(function () {
119
+ if ((previousState === null || previousState === void 0 ? void 0 : previousState.editId) === cellId && !editId || (previousState === null || previousState === void 0 ? void 0 : previousState.editId) === cellId && cellId !== editId) {
120
+ var _ref3 = config || {},
121
+ validator = _ref3.validator;
122
+
123
+ var isInvalid = validator === null || validator === void 0 ? void 0 : validator(cellValue);
124
+
125
+ if (isInvalid) {
126
+ setCellValue(initialValue);
127
+ saveCellData(initialValue);
128
+ return;
129
+ }
130
+ }
131
+ }, [previousState === null || previousState === void 0 ? void 0 : previousState.editId, editId, cellId, cellValue, config, initialValue, saveCellData]); // If you are in edit mode and click outside of the cell,
115
132
  // this changes the cell back to the InlineEditButton
116
133
 
117
134
  (0, _react.useEffect)(function () {
@@ -223,6 +240,16 @@ var InlineEditCell = function InlineEditCell(_ref) {
223
240
  return;
224
241
  }
225
242
 
243
+ var _ref4 = config || {},
244
+ validator = _ref4.validator;
245
+
246
+ var isInvalid = validator === null || validator === void 0 ? void 0 : validator(cellValue); // If an invalid state is detected, Tab/Enter should not do anything
247
+ // until the input has a valid state once again
248
+
249
+ if (isInvalid) {
250
+ return;
251
+ }
252
+
226
253
  var newCellId = getNewCellId(key);
227
254
  saveCellData(cellValue);
228
255
  setInitialValue(cellValue);
@@ -273,8 +300,8 @@ var InlineEditCell = function InlineEditCell(_ref) {
273
300
  };
274
301
 
275
302
  var renderSelectCell = function renderSelectCell() {
276
- var _ref3 = config || {},
277
- inputProps = _ref3.inputProps;
303
+ var _ref5 = config || {},
304
+ inputProps = _ref5.inputProps;
278
305
 
279
306
  return /*#__PURE__*/_react.default.createElement(_carbonComponentsReact.Dropdown, (0, _extends2.default)({
280
307
  id: cellId,
@@ -310,8 +337,8 @@ var InlineEditCell = function InlineEditCell(_ref) {
310
337
  },
311
338
  downshiftProps: {
312
339
  onStateChange: function onStateChange(downshiftState) {
313
- var _ref4 = downshiftState || {},
314
- isOpen = _ref4.isOpen; // !isOpen does not work in this case because a state change occurs on hover of the
340
+ var _ref6 = downshiftState || {},
341
+ isOpen = _ref6.isOpen; // !isOpen does not work in this case because a state change occurs on hover of the
315
342
  // menu items and isOpen is changed to undefined which causes dispatch to be called unexpectedly
316
343
 
317
344
 
@@ -412,6 +439,55 @@ var InlineEditCell = function InlineEditCell(_ref) {
412
439
  return null;
413
440
  };
414
441
 
442
+ var renderNumberInput = function renderNumberInput() {
443
+ var _ref7 = config || {},
444
+ validator = _ref7.validator;
445
+
446
+ return /*#__PURE__*/_react.default.createElement(_carbonComponentsReact.NumberInput, (0, _extends2.default)({
447
+ placeholder: placeholder,
448
+ label: cellLabel
449
+ }, inputProps, {
450
+ id: cellId,
451
+ hideLabel: true,
452
+ defaultValue: cellValue,
453
+ invalid: validator === null || validator === void 0 ? void 0 : validator(cellValue),
454
+ invalidText: (inputProps === null || inputProps === void 0 ? void 0 : inputProps.invalidText) || 'Provide missing invalidText',
455
+ onChange: function onChange(event) {
456
+ setCellValue(event.imaginaryTarget.value);
457
+
458
+ if (inputProps.onChange) {
459
+ inputProps.onChange(event.imaginaryTarget.value);
460
+ }
461
+ },
462
+ ref: numberInputRef
463
+ }));
464
+ };
465
+
466
+ var renderTextInput = function renderTextInput() {
467
+ var _ref8 = config || {},
468
+ validator = _ref8.validator;
469
+
470
+ var isInvalid = validator === null || validator === void 0 ? void 0 : validator(cellValue);
471
+ return /*#__PURE__*/_react.default.createElement(_carbonComponentsReact.TextInput, (0, _extends2.default)({
472
+ labelText: cellLabel,
473
+ placeholder: placeholder
474
+ }, inputProps, {
475
+ id: cellId,
476
+ hideLabel: true,
477
+ defaultValue: cellValue,
478
+ invalid: isInvalid,
479
+ invalidText: (inputProps === null || inputProps === void 0 ? void 0 : inputProps.invalidText) || 'Provide missing invalidText',
480
+ onChange: function onChange(event) {
481
+ setCellValue(event.target.value);
482
+
483
+ if (inputProps.onChange) {
484
+ inputProps.onChange(event.target.value);
485
+ }
486
+ },
487
+ ref: textInputRef
488
+ }));
489
+ };
490
+
415
491
  return (
416
492
  /*#__PURE__*/
417
493
  // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
@@ -424,7 +500,7 @@ var InlineEditCell = function InlineEditCell(_ref) {
424
500
  "data-inline-type": type,
425
501
  onClick: !nonEditCell ? handleInlineCellClick : addActiveState,
426
502
  onKeyDown: !nonEditCell ? handleKeyDown : null,
427
- className: (0, _classnames.default)("".concat(blockClass, "__inline-edit--outer-cell-button"), (_cx3 = {}, (0, _defineProperty2.default)(_cx3, "".concat(blockClass, "__inline-edit--outer-cell-button--").concat(rowSize), rowSize), (0, _defineProperty2.default)(_cx3, "".concat(blockClass, "__inline-edit--outer-cell-button--lg"), !rowSize), _cx3))
503
+ className: (0, _classnames.default)("".concat(blockClass, "__inline-edit--outer-cell-button"), (_cx3 = {}, (0, _defineProperty2.default)(_cx3, "".concat(blockClass, "__inline-edit--outer-cell-button--").concat(rowSize), rowSize), (0, _defineProperty2.default)(_cx3, "".concat(blockClass, "__inline-edit--outer-cell-button--lg"), !rowSize), (0, _defineProperty2.default)(_cx3, "".concat(blockClass, "__inline-edit--outer-cell-button--invalid"), config === null || config === void 0 ? void 0 : (_config$validator = config.validator) === null || _config$validator === void 0 ? void 0 : _config$validator.call(config, cellValue)), _cx3))
428
504
  }, !inEditMode && /*#__PURE__*/_react.default.createElement(_InlineEditButton.InlineEditButton, {
429
505
  isActiveCell: cellId === activeCellId,
430
506
  renderIcon: setRenderIcon(),
@@ -437,37 +513,7 @@ var InlineEditCell = function InlineEditCell(_ref) {
437
513
  totalInlineEditColumns: totalInlineEditColumns,
438
514
  totalColumns: totalColumns,
439
515
  type: type
440
- }), !nonEditCell && inEditMode && cellId === activeCellId && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, type === 'text' && /*#__PURE__*/_react.default.createElement(_carbonComponentsReact.TextInput, (0, _extends2.default)({
441
- labelText: cellLabel,
442
- placeholder: placeholder
443
- }, inputProps, {
444
- id: cellId,
445
- hideLabel: true,
446
- defaultValue: cellValue,
447
- onChange: function onChange(event) {
448
- setCellValue(event.target.value);
449
-
450
- if (inputProps.onChange) {
451
- inputProps.onChange(event.target.value);
452
- }
453
- },
454
- ref: textInputRef
455
- })), type === 'number' && /*#__PURE__*/_react.default.createElement(_carbonComponentsReact.NumberInput, (0, _extends2.default)({
456
- placeholder: placeholder,
457
- label: cellLabel
458
- }, inputProps, {
459
- id: cellId,
460
- hideLabel: true,
461
- defaultValue: cellValue,
462
- onChange: function onChange(event) {
463
- setCellValue(event.imaginaryTarget.value);
464
-
465
- if (inputProps.onChange) {
466
- inputProps.onChange(event.imaginaryTarget.value);
467
- }
468
- },
469
- ref: numberInputRef
470
- })), type === 'selection' && renderSelectCell(), type === 'date' && renderDateCell()))
516
+ }), !nonEditCell && inEditMode && cellId === activeCellId && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, type === 'text' && renderTextInput(), type === 'number' && renderNumberInput(), type === 'selection' && renderSelectCell(), type === 'date' && renderDateCell()))
471
517
  );
472
518
  };
473
519
 
@@ -42,11 +42,11 @@ var handleGridKeyPress = function handleGridKeyPress(_ref) {
42
42
  type: 'EXIT_EDIT_MODE',
43
43
  payload: activeCellId
44
44
  });
45
+ var inlineEditArea = document.querySelector("#".concat(instance.tableId, " .").concat(blockClass, "__table-with-inline-edit"));
46
+ inlineEditArea.focus();
45
47
  }
46
48
 
47
49
  event.preventDefault();
48
- var inlineEditArea = document.querySelector("#".concat(instance.tableId, " .").concat(blockClass, "__table-with-inline-edit"));
49
- inlineEditArea.focus();
50
50
  return;
51
51
  }
52
52
 
@@ -9,6 +9,8 @@ var _handleMultipleKeys = require("../../../../DataSpreadsheet/utils/handleMulti
9
9
 
10
10
  var _settings = require("../../../../../settings");
11
11
 
12
+ var _getFocusableElements = require("../../../../../global/js/utils/getFocusableElements");
13
+
12
14
  /**
13
15
  * Copyright IBM Corp. 2022, 2022
14
16
  *
@@ -72,6 +74,26 @@ var handleMultipleKeys = function handleMultipleKeys(_ref) {
72
74
  });
73
75
  }, 250);
74
76
  }
77
+ } // Shift + Tab
78
+ // This should remove the active grid state
79
+
80
+
81
+ if ((keysPressedList.includes('ShiftLeft') || keysPressedList.includes('ShiftRight')) && keysPressedList.includes('Tab')) {
82
+ dispatch({
83
+ type: 'REMOVE_GRID_ACTIVE_FOCUS',
84
+ payload: activeCellId
85
+ });
86
+ var tableElement = document.querySelector("#".concat(instance.tableId));
87
+ var datagridFocusableElements = (0, _getFocusableElements.getFocusableElements)(tableElement);
88
+ var indexOfTable = datagridFocusableElements.findIndex(function (item) {
89
+ return item instanceof HTMLTableElement;
90
+ });
91
+
92
+ if (indexOfTable && Number.isFinite(indexOfTable)) {
93
+ var _datagridFocusableEle;
94
+
95
+ (_datagridFocusableEle = datagridFocusableElements[indexOfTable]) === null || _datagridFocusableEle === void 0 ? void 0 : _datagridFocusableEle.focus();
96
+ }
75
97
  }
76
98
  };
77
99