@carbon/ibm-products 1.32.1 → 1.34.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. package/css/index-full-carbon.css +210 -158
  2. package/css/index-full-carbon.css.map +1 -1
  3. package/css/index-full-carbon.min.css +7 -3
  4. package/css/index-full-carbon.min.css.map +1 -1
  5. package/css/index-without-carbon-released-only.css +12 -144
  6. package/css/index-without-carbon-released-only.css.map +1 -1
  7. package/css/index-without-carbon-released-only.min.css +7 -3
  8. package/css/index-without-carbon-released-only.min.css.map +1 -1
  9. package/css/index-without-carbon.css +193 -156
  10. package/css/index-without-carbon.css.map +1 -1
  11. package/css/index-without-carbon.min.css +7 -3
  12. package/css/index-without-carbon.min.css.map +1 -1
  13. package/css/index.css +208 -156
  14. package/css/index.css.map +1 -1
  15. package/css/index.min.css +7 -3
  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 +30 -7
  20. package/es/components/Datagrid/Datagrid/addons/CustomizeColumns/Columns.js +0 -1
  21. package/es/components/Datagrid/Datagrid/addons/InlineEdit/InlineEditCell/InlineEditCell.js +84 -38
  22. package/es/components/Datagrid/Datagrid/addons/InlineEdit/handleGridKeyPress.js +2 -2
  23. package/es/components/Datagrid/Datagrid/addons/InlineEdit/handleMultipleKeys.js +21 -0
  24. package/es/components/Datagrid/utils/getArgTypes.js +4 -0
  25. package/es/components/Datagrid/utils/getInlineEditColumns.js +25 -7
  26. package/es/components/Datagrid/utils/makeData.js +10 -1
  27. package/es/components/InlineEditV2/InlineEditV2.js +249 -0
  28. package/es/components/InlineEditV2/index.js +1 -0
  29. package/es/components/PageHeader/PageHeaderTitle.js +3 -1
  30. package/es/components/SidePanel/SidePanel.js +44 -51
  31. package/es/components/SidePanel/motion/variants.js +39 -0
  32. package/es/components/index.js +2 -1
  33. package/es/global/js/package-settings.js +2 -1
  34. package/es/global/js/utils/getBezierValues.js +20 -0
  35. package/es/global/js/utils/motionConstants.js +45 -0
  36. package/lib/components/CreateTearsheetNarrow/CreateTearsheetNarrow.js +2 -2
  37. package/lib/components/DataSpreadsheet/hooks/useMultipleKeyTracking.js +4 -3
  38. package/lib/components/Datagrid/Datagrid/DatagridContent.js +29 -5
  39. package/lib/components/Datagrid/Datagrid/addons/CustomizeColumns/Columns.js +0 -1
  40. package/lib/components/Datagrid/Datagrid/addons/InlineEdit/InlineEditCell/InlineEditCell.js +84 -38
  41. package/lib/components/Datagrid/Datagrid/addons/InlineEdit/handleGridKeyPress.js +2 -2
  42. package/lib/components/Datagrid/Datagrid/addons/InlineEdit/handleMultipleKeys.js +22 -0
  43. package/lib/components/Datagrid/utils/getArgTypes.js +4 -0
  44. package/lib/components/Datagrid/utils/getInlineEditColumns.js +25 -7
  45. package/lib/components/Datagrid/utils/makeData.js +10 -1
  46. package/lib/components/InlineEditV2/InlineEditV2.js +277 -0
  47. package/lib/components/InlineEditV2/index.js +13 -0
  48. package/lib/components/PageHeader/PageHeaderTitle.js +3 -1
  49. package/lib/components/SidePanel/SidePanel.js +45 -50
  50. package/lib/components/SidePanel/motion/variants.js +49 -0
  51. package/lib/components/index.js +9 -1
  52. package/lib/global/js/package-settings.js +2 -1
  53. package/lib/global/js/utils/getBezierValues.js +29 -0
  54. package/lib/global/js/utils/motionConstants.js +55 -0
  55. package/package.json +14 -13
  56. package/scss/components/Datagrid/_storybook-styles.scss +11 -0
  57. package/scss/components/Datagrid/styles/_datagrid.scss +0 -5
  58. package/scss/components/Datagrid/styles/_useInlineEdit.scss +177 -2
  59. package/scss/components/InlineEdit/_inline-edit.scss +4 -2
  60. package/scss/components/InlineEditV2/_index.scss +10 -0
  61. package/scss/components/InlineEditV2/_inline-edit-v2.scss +81 -0
  62. package/scss/components/ModifiedTabs/_modified-tabs.scss +1 -1
  63. package/scss/components/PageHeader/_page-header.scss +4 -0
  64. package/scss/components/SidePanel/_side-panel.scss +0 -75
  65. package/scss/components/_index.scss +2 -0
@@ -16,7 +16,8 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
16
16
  * LICENSE file in the root directory of this source tree.
17
17
  */
18
18
  // Import portions of React that are needed.
19
- import React, { useState, useEffect, useRef } from 'react'; // Other standard imports.
19
+ import React, { useState, useEffect, useRef } from 'react';
20
+ import { motion, AnimatePresence } from 'framer-motion'; // Other standard imports.
20
21
 
21
22
  import PropTypes from 'prop-types';
22
23
  import cx from 'classnames';
@@ -32,6 +33,7 @@ import { usePreviousValue } from '../../global/js/hooks'; // Carbon and package
32
33
  import { Button } from 'carbon-components-react';
33
34
  import { Close20, ArrowLeft20 } from '@carbon/icons-react';
34
35
  import { ActionSet } from '../ActionSet';
36
+ import { overlayVariants, panelVariants } from './motion/variants';
35
37
  var blockClass = "".concat(pkg.prefix, "--side-panel");
36
38
  var componentName = 'SidePanel'; // NOTE: the component SCSS is not imported here: it is rolled up separately.
37
39
  // Default values for props
@@ -82,20 +84,15 @@ export var SidePanel = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
82
84
  title = _ref.title,
83
85
  rest = _objectWithoutProperties(_ref, _excluded);
84
86
 
85
- var _useState = useState(open),
87
+ var _useState = useState(false),
86
88
  _useState2 = _slicedToArray(_useState, 2),
87
- shouldRender = _useState2[0],
88
- setRender = _useState2[1];
89
+ animationComplete = _useState2[0],
90
+ setAnimationComplete = _useState2[1];
89
91
 
90
- var _useState3 = useState(false),
92
+ var _useState3 = useState(0),
91
93
  _useState4 = _slicedToArray(_useState3, 2),
92
- animationComplete = _useState4[0],
93
- setAnimationComplete = _useState4[1];
94
-
95
- var _useState5 = useState(0),
96
- _useState6 = _slicedToArray(_useState5, 2),
97
- panelHeight = _useState6[0],
98
- setPanelHeight = _useState6[1];
94
+ panelHeight = _useState4[0],
95
+ setPanelHeight = _useState4[1];
99
96
 
100
97
  var sidePanelRef = useRef();
101
98
  var sidePanelOverlayRef = useRef();
@@ -125,8 +122,10 @@ export var SidePanel = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
125
122
  // height css custom property
126
123
 
127
124
  if ((previousState === null || previousState === void 0 ? void 0 : previousState.size) !== size) {
125
+ var _sidePanelOuter$style;
126
+
128
127
  scrollableSection.scrollTop = 0;
129
- sidePanelOuter.style.setProperty("--".concat(blockClass, "--title-container-height"), "".concat(Number(initialTitleHeight), "px"));
128
+ sidePanelOuter === null || sidePanelOuter === void 0 ? void 0 : (_sidePanelOuter$style = sidePanelOuter.style) === null || _sidePanelOuter$style === void 0 ? void 0 : _sidePanelOuter$style.setProperty("--".concat(blockClass, "--title-container-height"), "".concat(Number(initialTitleHeight), "px"));
130
129
  }
131
130
  }
132
131
  }, [currentStep, ref, size, previousState === null || previousState === void 0 ? void 0 : previousState.size]); // set initial focus when side panel opens
@@ -154,12 +153,14 @@ export var SidePanel = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
154
153
  }, [selectorPrimaryFocus, open, animationComplete]);
155
154
  useEffect(function () {
156
155
  if (open && actions && actions.length && animationComplete) {
156
+ var _sidePanelOuter$style2;
157
+
157
158
  var sidePanelOuter = document.querySelector("#".concat(blockClass, "-outer"));
158
159
  var actionsContainer = getActionsContainerElement();
159
160
  var actionsHeight = (actionsContainer === null || actionsContainer === void 0 ? void 0 : actionsContainer.offsetHeight) + 16; // add additional 1rem spacing to bottom padding
160
161
 
161
162
  actionsHeight = "".concat(Math.round(actionsHeight / 16), "rem");
162
- sidePanelOuter === null || sidePanelOuter === void 0 ? void 0 : sidePanelOuter.style.setProperty("--".concat(blockClass, "--content-bottom-padding"), actionsHeight);
163
+ sidePanelOuter === null || sidePanelOuter === void 0 ? void 0 : (_sidePanelOuter$style2 = sidePanelOuter.style) === null || _sidePanelOuter$style2 === void 0 ? void 0 : _sidePanelOuter$style2.setProperty("--".concat(blockClass, "--content-bottom-padding"), actionsHeight);
163
164
  }
164
165
  }, [actions, condensedActions, open, animationComplete]); // Add console warning if labelText is provided without a title.
165
166
  // This combination is not allowed.
@@ -172,13 +173,15 @@ export var SidePanel = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
172
173
  /* istanbul ignore next */
173
174
 
174
175
  var handleResize = function handleResize(width, height) {
176
+ var _sidePanelOuter$style3;
177
+
175
178
  setPanelHeight(height);
176
179
  var sidePanelOuter = document.querySelector("#".concat(blockClass, "-outer"));
177
180
  var actionsContainer = getActionsContainerElement();
178
- var actionsHeight = actionsContainer.offsetHeight + 16; // add additional 1rem spacing to bottom padding
181
+ var actionsHeight = (actionsContainer === null || actionsContainer === void 0 ? void 0 : actionsContainer.offsetHeight) + 16; // add additional 1rem spacing to bottom padding
179
182
 
180
183
  actionsHeight = "".concat(Math.round(actionsHeight / 16), "rem");
181
- sidePanelOuter.style.setProperty("--".concat(blockClass, "--content-bottom-padding"), actionsHeight);
184
+ sidePanelOuter === null || sidePanelOuter === void 0 ? void 0 : (_sidePanelOuter$style3 = sidePanelOuter.style) === null || _sidePanelOuter$style3 === void 0 ? void 0 : _sidePanelOuter$style3.setProperty("--".concat(blockClass, "--content-bottom-padding"), actionsHeight);
182
185
  };
183
186
 
184
187
  var getActionsContainerElement = function getActionsContainerElement() {
@@ -263,7 +266,7 @@ export var SidePanel = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
263
266
  });
264
267
  }
265
268
 
266
- if (open && shouldRender && !animateTitle) {
269
+ if (open && !animateTitle) {
267
270
  var _sidePanelOuter = document.querySelector("#".concat(blockClass, "-outer"));
268
271
 
269
272
  var _sidePanelTitleElement = document.querySelector(".".concat(blockClass, "__title-container .").concat(blockClass, "__title-text"));
@@ -284,7 +287,7 @@ export var SidePanel = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
284
287
  _sidePanelOuter === null || _sidePanelOuter === void 0 ? void 0 : _sidePanelOuter.style.setProperty("--".concat(blockClass, "--action-bar-container-height"), "".concat(sidePanelActionBarElementHeight, "px"));
285
288
  _sidePanelOuter === null || _sidePanelOuter === void 0 ? void 0 : _sidePanelOuter.style.setProperty("--".concat(blockClass, "--label-text-height"), "".concat(labelHeight, "px"));
286
289
  }
287
- }, [open, animateTitle, animationComplete, shouldRender, panelHeight, title, size, reducedMotion.matches]); // click outside functionality if `includeOverlay` prop is set
290
+ }, [open, animateTitle, animationComplete, panelHeight, title, size, reducedMotion.matches]); // click outside functionality if `includeOverlay` prop is set
288
291
 
289
292
  useEffect(function () {
290
293
  var handleOutsideClick = function handleOutsideClick(event) {
@@ -310,18 +313,11 @@ export var SidePanel = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
310
313
  return function () {
311
314
  document.removeEventListener('click', handleOutsideClick);
312
315
  };
313
- }, [includeOverlay, onRequestClose, open, preventCloseOnClickOutside, ref, onUnmount]); // initialize the side panel to open
314
-
315
- useEffect(function () {
316
- if (open) {
317
- setRender(true);
318
- }
319
- }, [open]); // initializes the side panel to close
316
+ }, [includeOverlay, onRequestClose, open, preventCloseOnClickOutside, ref, onUnmount]); // initializes the side panel to close
320
317
 
321
318
  var onAnimationEnd = function onAnimationEnd() {
322
319
  if (!open) {
323
320
  onUnmount === null || onUnmount === void 0 ? void 0 : onUnmount();
324
- setRender(false);
325
321
  }
326
322
 
327
323
  setAnimationComplete(true);
@@ -335,13 +331,8 @@ export var SidePanel = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
335
331
  }
336
332
  }, [reducedMotion.matches]); // initializes the side panel to open
337
333
 
338
- var _onAnimationStart = function onAnimationStart(event) {
339
- event.persist();
340
- var isPanelTarget = event.target.id === "".concat(blockClass, "-outer");
341
-
342
- if (isPanelTarget) {
343
- setAnimationComplete(false);
344
- }
334
+ var _onAnimationStart = function onAnimationStart() {
335
+ setAnimationComplete(false);
345
336
  }; // used to reset margins of the slide in panel when closed/closing
346
337
 
347
338
 
@@ -358,13 +349,12 @@ export var SidePanel = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
358
349
  }, [open, placement, selectorPageContent, slideIn]);
359
350
  useEffect(function () {
360
351
  if (!open && previousState !== null && previousState !== void 0 && previousState.open && reducedMotion.matches) {
361
- setRender(false);
362
352
  onUnmount === null || onUnmount === void 0 ? void 0 : onUnmount();
363
353
  }
364
354
  }, [open, onUnmount, reducedMotion.matches, previousState === null || previousState === void 0 ? void 0 : previousState.open]); // used to set margins of content for slide in panel version
365
355
 
366
356
  useEffect(function () {
367
- if (shouldRender && slideIn) {
357
+ if (open && slideIn) {
368
358
  var pageContentElement = document.querySelector(selectorPageContent);
369
359
 
370
360
  if (placement && placement === 'right' && pageContentElement) {
@@ -377,7 +367,7 @@ export var SidePanel = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
377
367
  pageContentElement.style.marginLeft = SIDE_PANEL_SIZES[size];
378
368
  }
379
369
  }
380
- }, [slideIn, selectorPageContent, placement, shouldRender, size, reducedMotion.matches]); // adds focus trap functionality
370
+ }, [slideIn, selectorPageContent, placement, size, reducedMotion.matches, open]); // adds focus trap functionality
381
371
 
382
372
  /* istanbul ignore next */
383
373
 
@@ -475,20 +465,22 @@ export var SidePanel = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
475
465
  onResize: handleResize,
476
466
  targetRef: contentRef
477
467
  });
478
- return shouldRender && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", _extends({}, getDevtoolsProps(componentName), rest, {
468
+ return /*#__PURE__*/React.createElement(AnimatePresence, null, open && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(motion.div, _extends({}, getDevtoolsProps(componentName), rest, {
479
469
  id: "".concat(blockClass, "-outer"),
480
470
  className: mainPanelClassNames,
481
- style: {
482
- animation: !reducedMotion.matches ? "".concat(open ? placement === 'right' ? "side-panel-entrance-right ".concat(moderate02) : "side-panel-entrance-left ".concat(moderate02) : placement === 'right' ? "side-panel-exit-right ".concat(moderate02) : "side-panel-exit-left ".concat(moderate02)) : null
483
- },
484
- onAnimationEnd: onAnimationEnd,
485
- onAnimationStart: function onAnimationStart(event) {
486
- return _onAnimationStart(event);
487
- },
488
471
  onBlur: handleBlur,
489
472
  ref: contentRef,
490
473
  role: "complementary",
491
- "aria-label": title
474
+ "aria-label": title,
475
+ onAnimationComplete: onAnimationEnd,
476
+ onAnimationStart: function onAnimationStart(event) {
477
+ return _onAnimationStart(event);
478
+ },
479
+ variants: panelVariants,
480
+ initial: "hidden",
481
+ animate: "visible",
482
+ exit: "exit",
483
+ custom: placement
492
484
  }), /*#__PURE__*/React.createElement("span", {
493
485
  ref: startTrapRef,
494
486
  tabIndex: "0",
@@ -508,13 +500,14 @@ export var SidePanel = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
508
500
  tabIndex: "0",
509
501
  role: "link",
510
502
  className: "".concat(blockClass, "__visually-hidden")
511
- }, "Focus sentinel")), includeOverlay && /*#__PURE__*/React.createElement("div", {
503
+ }, "Focus sentinel")), /*#__PURE__*/React.createElement(AnimatePresence, null, includeOverlay && /*#__PURE__*/React.createElement(motion.div, {
504
+ variants: overlayVariants,
505
+ initial: "hidden",
506
+ animate: "visible",
507
+ exit: "exit",
512
508
  ref: sidePanelOverlayRef,
513
- className: "".concat(blockClass, "__overlay"),
514
- style: {
515
- animation: !reducedMotion.matches ? "".concat(open ? "side-panel-overlay-entrance ".concat(moderate02) : "side-panel-overlay-exit ".concat(moderate02)) : null
516
- }
517
- }));
509
+ className: "".concat(blockClass, "__overlay")
510
+ }))));
518
511
  }); // Return a placeholder if not released and not enabled by feature flag
519
512
 
520
513
  SidePanel = pkg.checkComponentEnabled(SidePanel, componentName);
@@ -0,0 +1,39 @@
1
+ import { DURATIONS, EASINGS } from '../../../global/js/utils/motionConstants';
2
+ export var overlayVariants = {
3
+ visible: {
4
+ opacity: 1,
5
+ transition: {
6
+ duration: DURATIONS.moderate02,
7
+ ease: EASINGS.productive.standard
8
+ }
9
+ },
10
+ hidden: {
11
+ opacity: 0
12
+ },
13
+ exit: {
14
+ opacity: 0
15
+ }
16
+ };
17
+ export var panelVariants = {
18
+ visible: {
19
+ x: 0,
20
+ transition: {
21
+ duration: DURATIONS.moderate02,
22
+ ease: EASINGS.productive.standard
23
+ }
24
+ },
25
+ hidden: function hidden(placement) {
26
+ return {
27
+ x: placement === 'right' ? '100%' : -320
28
+ };
29
+ },
30
+ exit: function exit(placement) {
31
+ return {
32
+ x: placement === 'right' ? '100%' : -320,
33
+ transition: {
34
+ duration: DURATIONS.moderate01,
35
+ ease: EASINGS.productive.exit
36
+ }
37
+ };
38
+ }
39
+ };
@@ -40,4 +40,5 @@ export { DataSpreadsheet } from './DataSpreadsheet';
40
40
  export { Datagrid, useDatagrid, useInfiniteScroll, useNestedRows, useSelectRows, useExpandedRow, useOnRowClick, useSortableColumns, useRowIsMouseOver, useColumnRightAlign, useDisableSelectRows, useStickyColumn, useActionsColumn, useCustomizeColumns, useSelectAllWithToggle, useColumnOrder, useInlineEdit } from './Datagrid';
41
41
  export { EditTearsheet } from './EditTearsheet';
42
42
  export { EditTearsheetNarrow } from './EditTearsheetNarrow';
43
- export { EditFullPage } from './EditFullPage';
43
+ export { EditFullPage } from './EditFullPage';
44
+ export { InlineEditV2 } from './InlineEditV2';
@@ -69,7 +69,8 @@ var defaults = {
69
69
  Datagrid: false,
70
70
  EditTearsheet: false,
71
71
  EditTearsheetNarrow: false,
72
- EditFullPage: false
72
+ EditFullPage: false,
73
+ InlineEditV2: false
73
74
  /* new component flags here - comment used by generate CLI */
74
75
 
75
76
  },
@@ -0,0 +1,20 @@
1
+ import { motion } from '@carbon/motion';
2
+ /**
3
+ * This function turns a cubic-bezier() string to an
4
+ * array of values that we can use with framer-motion
5
+ * @param {string} type - The carbon motion type, either 'standard', 'entrance', or 'exit'
6
+ * @param {string} mode - The carbon motion mode, either 'productive', or 'expressive'
7
+ */
8
+
9
+ export var getBezierValues = function getBezierValues(type, mode) {
10
+ var cubicBezier = motion(type, mode);
11
+ var extractStringFromParens = /\(([^)]+)\)/;
12
+ var desiredBezierStrings = extractStringFromParens.exec(cubicBezier)[1];
13
+ var formattedDesiredBezierStrings = desiredBezierStrings.trim().split(',').map(Number);
14
+
15
+ if (Array.isArray(formattedDesiredBezierStrings)) {
16
+ return formattedDesiredBezierStrings;
17
+ }
18
+
19
+ return [];
20
+ };
@@ -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 { getBezierValues } from './getBezierValues';
8
+ import { fast01, fast02, moderate01, moderate02, slow01, slow02 } from '@carbon/motion';
9
+
10
+ var cleanMotionValue = function cleanMotionValue(val) {
11
+ return parseInt(val) / 1000;
12
+ };
13
+
14
+ export var DURATIONS = {
15
+ // Micro-interactions such as button and toggle
16
+ fast01: cleanMotionValue(fast01),
17
+ // '70ms'
18
+ // Micro-interactions such as fade
19
+ fast02: cleanMotionValue(fast02),
20
+ // '110ms'
21
+ // Micro-interactions, small expansion, short distance movements
22
+ moderate01: cleanMotionValue(moderate01),
23
+ // '150ms'
24
+ // Expansion, system communication, toast
25
+ moderate02: cleanMotionValue(moderate02),
26
+ // '240ms'
27
+ // Large expansion, important system notifications
28
+ slow01: cleanMotionValue(slow01),
29
+ // '400ms'
30
+ // Background dimming
31
+ slow02: cleanMotionValue(slow02) // '700ms'
32
+
33
+ };
34
+ export var EASINGS = {
35
+ productive: {
36
+ entrance: getBezierValues('entrance', 'productive'),
37
+ standard: getBezierValues('standard', 'productive'),
38
+ exit: getBezierValues('exit', 'productive')
39
+ },
40
+ expressive: {
41
+ entrance: getBezierValues('entrance', 'expressive'),
42
+ standard: getBezierValues('standard', 'expressive'),
43
+ exit: getBezierValues('exit', 'expressive')
44
+ }
45
+ };
@@ -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,8 +168,9 @@ 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
- CustomizeColumnsModal: _propTypes.default.element,
173
+ CustomizeColumnsModal: _propTypes.default.oneOfType([_propTypes.default.element, _propTypes.default.func]),
152
174
  isFetching: _propTypes.default.bool,
153
175
  leftPanel: _propTypes.default.object,
154
176
  fullHeightDatagrid: _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
  };
@@ -121,7 +121,6 @@ var Columns = function Columns(_ref) {
121
121
  }, /*#__PURE__*/_react.default.createElement(_carbonComponentsReact.Checkbox, {
122
122
  wrapperClassName: "".concat(blockClass, "__customize-columns-checkbox-wrapper"),
123
123
  checked: getVisibleColumnsCount() === columns.length,
124
- empty: !!getVisibleColumnsCount() === 0,
125
124
  indeterminate: getVisibleColumnsCount() < columns.length && getVisibleColumnsCount() > 0,
126
125
  onChange: function onChange() {
127
126
  onSelectColumn(columns, getVisibleColumnsCount() !== columns.length);
@@ -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