@carbon/react 1.61.0-rc.0 → 1.61.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -77,6 +77,63 @@ declare namespace Tabs {
77
77
  selectedIndex: PropTypes.Requireable<number>;
78
78
  };
79
79
  }
80
+ export interface TabsVerticalProps {
81
+ /**
82
+ * Provide child elements to be rendered inside the `TabsVertical`.
83
+ * These elements should render either `TabsListVertical` or `TabsPanels`
84
+ */
85
+ children?: ReactNode;
86
+ /**
87
+ * Specify which content tab should be initially selected when the component
88
+ * is first rendered
89
+ */
90
+ defaultSelectedIndex?: number;
91
+ /**
92
+ * Option to set a height style only if using vertical variation
93
+ */
94
+ height?: string;
95
+ /**
96
+ * Provide an optional function which is called
97
+ * whenever the state of the `Tabs` changes
98
+ */
99
+ onChange?(state: {
100
+ selectedIndex: number;
101
+ }): void;
102
+ /**
103
+ * Control which content panel is currently selected. This puts the component
104
+ * in a controlled mode and should be used along with `onChange`
105
+ */
106
+ selectedIndex?: number;
107
+ }
108
+ declare function TabsVertical({ children, height, defaultSelectedIndex, onChange, selectedIndex: controlledSelectedIndex, ...rest }: TabsVerticalProps): import("react/jsx-runtime").JSX.Element;
109
+ declare namespace TabsVertical {
110
+ var propTypes: {
111
+ /**
112
+ * Provide child elements to be rendered inside the `TabsVertical`.
113
+ * These elements should render either `TabsListVertical` or `TabsPanels`
114
+ */
115
+ children: PropTypes.Requireable<PropTypes.ReactNodeLike>;
116
+ /**
117
+ * Specify which content tab should be initially selected when the component
118
+ * is first rendered
119
+ */
120
+ defaultSelectedIndex: PropTypes.Requireable<number>;
121
+ /**
122
+ * Option to set a height style only if using vertical variation
123
+ */
124
+ height: PropTypes.Requireable<string>;
125
+ /**
126
+ * Provide an optional function which is called whenever the state of the
127
+ * `Tabs` changes
128
+ */
129
+ onChange: PropTypes.Requireable<(...args: any[]) => any>;
130
+ /**
131
+ * Control which content panel is currently selected. This puts the component
132
+ * in a controlled mode and should be used along with `onChange`
133
+ */
134
+ selectedIndex: PropTypes.Requireable<number>;
135
+ };
136
+ }
80
137
  /**
81
138
  * TabList
82
139
  */
@@ -195,6 +252,59 @@ declare namespace TabList {
195
252
  scrollIntoView: PropTypes.Requireable<boolean>;
196
253
  };
197
254
  }
255
+ /**
256
+ * TabListVertical
257
+ */
258
+ export interface TabListVerticalProps extends DivAttributes {
259
+ /**
260
+ * Specify whether the content tab should be activated automatically or
261
+ * manually
262
+ */
263
+ activation?: 'automatic' | 'manual';
264
+ /**
265
+ * Provide an accessible label to be read when a user interacts with this
266
+ * component
267
+ */
268
+ 'aria-label': string;
269
+ /**
270
+ * Provide child elements to be rendered inside `ContentTabs`.
271
+ * These elements should render a `ContentTab`
272
+ */
273
+ children?: ReactNode;
274
+ /**
275
+ * Specify an optional className to be added to the container node
276
+ */
277
+ className?: string;
278
+ /**
279
+ * Choose whether to automatically scroll to newly selected tabs
280
+ * on component rerender
281
+ */
282
+ scrollIntoView?: boolean;
283
+ }
284
+ declare function TabListVertical({ activation, 'aria-label': label, children, className: customClassName, scrollIntoView, ...rest }: TabListVerticalProps): import("react/jsx-runtime").JSX.Element;
285
+ declare namespace TabListVertical {
286
+ var propTypes: {
287
+ /**
288
+ * Specify whether the content tab should be activated automatically or
289
+ * manually
290
+ */
291
+ activation: PropTypes.Requireable<string>;
292
+ /**
293
+ * Provide an accessible label to be read when a user interacts with this
294
+ * component
295
+ */
296
+ 'aria-label': PropTypes.Validator<string>;
297
+ /**
298
+ * Provide child elements to be rendered inside `ContentTabs`.
299
+ * These elements should render a `ContentTab`
300
+ */
301
+ children: PropTypes.Requireable<PropTypes.ReactNodeLike>;
302
+ /**
303
+ * Specify an optional className to be added to the container node
304
+ */
305
+ className: PropTypes.Requireable<string>;
306
+ };
307
+ }
198
308
  /**
199
309
  * Tab
200
310
  */
@@ -308,4 +418,4 @@ declare namespace TabPanels {
308
418
  children: PropTypes.Requireable<PropTypes.ReactNodeLike>;
309
419
  };
310
420
  }
311
- export { Tabs, Tab, IconTab, TabPanel, TabPanels, TabList };
421
+ export { Tabs, TabsVertical, Tab, IconTab, TabPanel, TabPanels, TabList, TabListVertical, };
@@ -16,6 +16,12 @@ var cx = require('classnames');
16
16
  var debounce = require('lodash.debounce');
17
17
  var PropTypes = require('prop-types');
18
18
  var React = require('react');
19
+ require('../Grid/FlexGrid.js');
20
+ require('../Grid/Grid.js');
21
+ require('../Grid/Row.js');
22
+ require('../Grid/Column.js');
23
+ require('../Grid/ColumnHang.js');
24
+ require('../Grid/GridContext.js');
19
25
  var reactIs = require('react-is');
20
26
  require('../Tooltip/DefinitionTooltip.js');
21
27
  var Tooltip = require('../Tooltip/Tooltip.js');
@@ -63,6 +69,7 @@ const TabContext = /*#__PURE__*/React__default["default"].createContext({
63
69
  hasSecondaryLabel: false
64
70
  });
65
71
  const lgMediaQuery = `(min-width: ${layout.breakpoints.lg.width})`;
72
+ `(max-width: ${layout.breakpoints.md.width})`;
66
73
 
67
74
  // Used to keep track of position in a list of tab panels
68
75
  const TabPanelContext = /*#__PURE__*/React__default["default"].createContext(0);
@@ -141,6 +148,32 @@ Tabs.propTypes = {
141
148
  */
142
149
  selectedIndex: PropTypes__default["default"].number
143
150
  };
151
+ ({
152
+ /**
153
+ * Provide child elements to be rendered inside the `TabsVertical`.
154
+ * These elements should render either `TabsListVertical` or `TabsPanels`
155
+ */
156
+ children: PropTypes__default["default"].node,
157
+ /**
158
+ * Specify which content tab should be initially selected when the component
159
+ * is first rendered
160
+ */
161
+ defaultSelectedIndex: PropTypes__default["default"].number,
162
+ /**
163
+ * Option to set a height style only if using vertical variation
164
+ */
165
+ height: PropTypes__default["default"].string,
166
+ /**
167
+ * Provide an optional function which is called whenever the state of the
168
+ * `Tabs` changes
169
+ */
170
+ onChange: PropTypes__default["default"].func,
171
+ /**
172
+ * Control which content panel is currently selected. This puts the component
173
+ * in a controlled mode and should be used along with `onChange`
174
+ */
175
+ selectedIndex: PropTypes__default["default"].number
176
+ });
144
177
 
145
178
  /**
146
179
  * Get the next index for a given keyboard event
@@ -165,7 +198,7 @@ function getNextIndex(event, total, index) {
165
198
  * TabList
166
199
  */
167
200
 
168
- function TabList(_ref2) {
201
+ function TabList(_ref4) {
169
202
  let {
170
203
  activation = 'automatic',
171
204
  'aria-label': label,
@@ -180,7 +213,7 @@ function TabList(_ref2) {
180
213
  scrollDebounceWait = 200,
181
214
  scrollIntoView,
182
215
  ...rest
183
- } = _ref2;
216
+ } = _ref4;
184
217
  const {
185
218
  activeIndex,
186
219
  selectedIndex,
@@ -337,10 +370,10 @@ function TabList(_ref2) {
337
370
  }
338
371
  }, [activation, activeIndex, selectedIndex, isScrollable, children]);
339
372
  usePressable.usePressable(previousButton, {
340
- onPress(_ref3) {
373
+ onPress(_ref5) {
341
374
  let {
342
375
  longPress
343
- } = _ref3;
376
+ } = _ref5;
344
377
  if (!longPress && ref.current) {
345
378
  setScrollLeft(Math.max(scrollLeft - ref.current.scrollWidth / tabs.current.length * 1.5, 0));
346
379
  }
@@ -350,10 +383,10 @@ function TabList(_ref2) {
350
383
  }
351
384
  });
352
385
  usePressable.usePressable(nextButton, {
353
- onPress(_ref4) {
386
+ onPress(_ref6) {
354
387
  let {
355
388
  longPress
356
- } = _ref4;
389
+ } = _ref6;
357
390
  if (!longPress && ref.current) {
358
391
  setScrollLeft(Math.min(scrollLeft + ref.current.scrollWidth / tabs.current.length * 1.5, ref.current.scrollWidth - ref.current.clientWidth));
359
392
  }
@@ -455,6 +488,27 @@ TabList.propTypes = {
455
488
  */
456
489
  scrollIntoView: PropTypes__default["default"].bool
457
490
  };
491
+ ({
492
+ /**
493
+ * Specify whether the content tab should be activated automatically or
494
+ * manually
495
+ */
496
+ activation: PropTypes__default["default"].oneOf(['automatic', 'manual']),
497
+ /**
498
+ * Provide an accessible label to be read when a user interacts with this
499
+ * component
500
+ */
501
+ 'aria-label': PropTypes__default["default"].string.isRequired,
502
+ /**
503
+ * Provide child elements to be rendered inside `ContentTabs`.
504
+ * These elements should render a `ContentTab`
505
+ */
506
+ children: PropTypes__default["default"].node,
507
+ /**
508
+ * Specify an optional className to be added to the container node
509
+ */
510
+ className: PropTypes__default["default"].string
511
+ });
458
512
 
459
513
  /**
460
514
  * Helper function to set up the behavior when a button is "long pressed".
@@ -501,7 +555,7 @@ function createLongPressBehavior(ref, direction, setScrollLeft) {
501
555
  * Tab
502
556
  */
503
557
 
504
- const Tab = /*#__PURE__*/React.forwardRef(function Tab(_ref5, forwardRef) {
558
+ const Tab = /*#__PURE__*/React.forwardRef(function Tab(_ref8, forwardRef) {
505
559
  let {
506
560
  as = 'button',
507
561
  children,
@@ -512,7 +566,7 @@ const Tab = /*#__PURE__*/React.forwardRef(function Tab(_ref5, forwardRef) {
512
566
  secondaryLabel,
513
567
  renderIcon: Icon,
514
568
  ...rest
515
- } = _ref5;
569
+ } = _ref8;
516
570
  const prefix = usePrefix.usePrefix();
517
571
  const {
518
572
  selectedIndex,
@@ -532,6 +586,11 @@ const Tab = /*#__PURE__*/React.forwardRef(function Tab(_ref5, forwardRef) {
532
586
  const [ignoreHover, setIgnoreHover] = React.useState(false);
533
587
  const id = `${baseId}-tab-${index}`;
534
588
  const panelId = `${baseId}-tabpanel-${index}`;
589
+ const [isEllipsisApplied, setIsEllipsisApplied] = React.useState(false);
590
+ const isEllipsisActive = element => {
591
+ setIsEllipsisApplied(element.offsetHeight < element.scrollHeight);
592
+ return element.offsetHeight < element.scrollHeight;
593
+ };
535
594
  const className = cx__default["default"](`${prefix}--tabs__nav-item`, `${prefix}--tabs__nav-link`, {
536
595
  [`${prefix}--tabs__nav-item--selected`]: selectedIndex === index,
537
596
  [`${prefix}--tabs__nav-item--disabled`]: disabled,
@@ -553,6 +612,18 @@ const Tab = /*#__PURE__*/React.forwardRef(function Tab(_ref5, forwardRef) {
553
612
  };
554
613
  useEvent.useEvent(dismissIconRef, 'mouseover', onDismissIconMouseEnter);
555
614
  useEvent.useEvent(dismissIconRef, 'mouseleave', onDismissIconMouseLeave);
615
+ React.useLayoutEffect(() => {
616
+ function handler() {
617
+ const elementTabId = document.getElementById(`${id}`);
618
+ const newElement = elementTabId?.getElementsByClassName(`${prefix}--tabs__nav-item-label`)[0];
619
+ isEllipsisActive(newElement);
620
+ }
621
+ handler();
622
+ window.addEventListener('resize', handler);
623
+ return () => {
624
+ window.removeEventListener('resize', handler);
625
+ };
626
+ }, [prefix, id]);
556
627
  const handleClose = evt => {
557
628
  evt.stopPropagation();
558
629
  onTabCloseRequest?.(index);
@@ -607,6 +678,46 @@ const Tab = /*#__PURE__*/React.forwardRef(function Tab(_ref5, forwardRef) {
607
678
  "aria-label": `Press delete to remove ${typeof children === 'string' ? children : ''} tab`
608
679
  })));
609
680
  const hasIcon = Icon ?? dismissable;
681
+
682
+ // should only happen for vertical variation, so no dissimisamble icon is needed here
683
+ if (isEllipsisApplied) {
684
+ return /*#__PURE__*/React__default["default"].createElement(Tooltip.Tooltip, {
685
+ label: children,
686
+ align: "top",
687
+ leaveDelayMs: 0,
688
+ autoAlign: true,
689
+ onMouseEnter: () => false,
690
+ closeOnActivation: true
691
+ }, /*#__PURE__*/React__default["default"].createElement(BaseComponent, _rollupPluginBabelHelpers["extends"]({}, rest, {
692
+ "aria-controls": panelId,
693
+ "aria-disabled": disabled,
694
+ "aria-selected": selectedIndex === index,
695
+ ref: ref,
696
+ id: id,
697
+ role: "tab",
698
+ className: className,
699
+ disabled: disabled,
700
+ title: children,
701
+ onClick: evt => {
702
+ if (disabled) {
703
+ return;
704
+ }
705
+ setSelectedIndex(index);
706
+ onClick?.(evt);
707
+ },
708
+ onKeyDown: handleKeyDown,
709
+ tabIndex: selectedIndex === index ? '0' : '-1',
710
+ type: "button"
711
+ }), /*#__PURE__*/React__default["default"].createElement("div", {
712
+ className: `${prefix}--tabs__nav-item-label-wrapper`
713
+ }, /*#__PURE__*/React__default["default"].createElement(Text.Text, {
714
+ className: `${prefix}--tabs__nav-item-label`
715
+ }, children)), hasSecondaryLabel && secondaryLabel && /*#__PURE__*/React__default["default"].createElement(Text.Text, {
716
+ as: "div",
717
+ className: `${prefix}--tabs__nav-item-secondary-label`,
718
+ title: secondaryLabel
719
+ }, secondaryLabel)));
720
+ }
610
721
  return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(BaseComponent, _rollupPluginBabelHelpers["extends"]({}, rest, {
611
722
  "aria-controls": panelId,
612
723
  "aria-disabled": disabled,
@@ -695,7 +806,7 @@ Tab.propTypes = {
695
806
  * IconTab
696
807
  */
697
808
 
698
- const IconTab = /*#__PURE__*/React__default["default"].forwardRef(function IconTab(_ref6, ref) {
809
+ const IconTab = /*#__PURE__*/React__default["default"].forwardRef(function IconTab(_ref9, ref) {
699
810
  let {
700
811
  children,
701
812
  className: customClassName,
@@ -704,7 +815,7 @@ const IconTab = /*#__PURE__*/React__default["default"].forwardRef(function IconT
704
815
  leaveDelayMs,
705
816
  label,
706
817
  ...rest
707
- } = _ref6;
818
+ } = _ref9;
708
819
  const prefix = usePrefix.usePrefix();
709
820
  const classNames = cx__default["default"](`${prefix}--tabs__nav-item--icon-only`, customClassName);
710
821
  return /*#__PURE__*/React__default["default"].createElement(Tooltip.Tooltip, {
@@ -753,12 +864,12 @@ IconTab.propTypes = {
753
864
  * TabPanel
754
865
  */
755
866
 
756
- const TabPanel = /*#__PURE__*/React__default["default"].forwardRef(function TabPanel(_ref7, forwardRef) {
867
+ const TabPanel = /*#__PURE__*/React__default["default"].forwardRef(function TabPanel(_ref10, forwardRef) {
757
868
  let {
758
869
  children,
759
870
  className: customClassName,
760
871
  ...rest
761
- } = _ref7;
872
+ } = _ref10;
762
873
  const prefix = usePrefix.usePrefix();
763
874
  const panel = React.useRef(null);
764
875
  const ref = useMergedRefs.useMergedRefs([forwardRef, panel]);
@@ -833,14 +944,50 @@ TabPanel.propTypes = {
833
944
  * TabPanels
834
945
  */
835
946
 
836
- function TabPanels(_ref8) {
947
+ function TabPanels(_ref11) {
837
948
  let {
838
949
  children
839
- } = _ref8;
950
+ } = _ref11;
951
+ const prefix = usePrefix.usePrefix();
952
+ const refs = React.useRef([]);
953
+ const hiddenStates = React.useRef([]);
954
+ React.useLayoutEffect(() => {
955
+ const tabContainer = refs.current[0]?.previousElementSibling;
956
+ const isVertical = tabContainer?.classList.contains(`${prefix}--tabs--vertical`);
957
+ const parentHasHeight = tabContainer?.parentElement?.style.height;
958
+
959
+ // Should only apply same height to vertical Tab Panels without a given height
960
+ if (isVertical && !parentHasHeight) {
961
+ hiddenStates.current = refs.current.map(ref => ref?.hidden || false);
962
+
963
+ // un-hide hidden Tab Panels to get heights
964
+ refs.current.forEach(ref => {
965
+ if (ref) {
966
+ ref.hidden = false;
967
+ }
968
+ });
969
+
970
+ // set max height to TabList
971
+ const heights = refs.current.map(ref => ref?.offsetHeight || 0);
972
+ const max = Math.max(...heights);
973
+ tabContainer.style.height = max + 'px';
974
+
975
+ // re-hide hidden Tab Panels
976
+ refs.current.forEach((ref, index) => {
977
+ if (ref) {
978
+ ref.hidden = hiddenStates.current[index];
979
+ }
980
+ });
981
+ }
982
+ });
840
983
  return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, React__default["default"].Children.map(children, (child, index) => {
841
984
  return /*#__PURE__*/React__default["default"].createElement(TabPanelContext.Provider, {
842
985
  value: index
843
- }, child);
986
+ }, /*#__PURE__*/React__default["default"].cloneElement(child, {
987
+ ref: element => {
988
+ refs.current[index] = element;
989
+ }
990
+ }));
844
991
  }));
845
992
  }
846
993
  TabPanels.propTypes = {
@@ -97,7 +97,7 @@ const TextArea = /*#__PURE__*/React__default["default"].forwardRef((props, forwa
97
97
  onKeyDown: evt => {
98
98
  if (!disabled && enableCounter && counterMode === 'word') {
99
99
  const key = evt.which;
100
- if (maxCount && textCount >= maxCount && key === 32) {
100
+ if (maxCount && textCount >= maxCount && key === 32 || maxCount && textCount >= maxCount && key === 13) {
101
101
  evt.preventDefault();
102
102
  }
103
103
  }
@@ -230,6 +230,7 @@ const TextArea = /*#__PURE__*/React__default["default"].forwardRef((props, forwa
230
230
  const ariaAnnouncement = useAnnouncer.useAnnouncer(textCount, maxCount, counterMode === 'word' ? 'words' : undefined);
231
231
  const input = /*#__PURE__*/React__default["default"].createElement("textarea", _rollupPluginBabelHelpers["extends"]({}, other, textareaProps, {
232
232
  placeholder: placeholder,
233
+ "aria-readonly": other.readOnly ? true : false,
233
234
  className: textareaClasses,
234
235
  "aria-invalid": invalid,
235
236
  "aria-describedby": ariaDescribedBy,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@carbon/react",
3
3
  "description": "React components for the Carbon Design System",
4
- "version": "1.61.0-rc.0",
4
+ "version": "1.61.0",
5
5
  "license": "Apache-2.0",
6
6
  "main": "lib/index.js",
7
7
  "module": "es/index.js",
@@ -49,9 +49,9 @@
49
49
  "dependencies": {
50
50
  "@babel/runtime": "^7.18.3",
51
51
  "@carbon/feature-flags": "^0.20.0",
52
- "@carbon/icons-react": "^11.45.0-rc.0",
52
+ "@carbon/icons-react": "^11.45.0",
53
53
  "@carbon/layout": "^11.23.0",
54
- "@carbon/styles": "^1.61.0-rc.0",
54
+ "@carbon/styles": "^1.61.0",
55
55
  "@floating-ui/react": "^0.26.0",
56
56
  "@ibm/telemetry-js": "^1.5.0",
57
57
  "classnames": "2.5.1",
@@ -68,7 +68,6 @@
68
68
  "react-is": "^18.2.0",
69
69
  "tabbable": "^6.2.0",
70
70
  "use-resize-observer": "^6.0.0",
71
- "wicg-inert": "^3.1.1",
72
71
  "window-or-global": "^1.0.1"
73
72
  },
74
73
  "devDependencies": {
@@ -142,5 +141,5 @@
142
141
  "**/*.scss",
143
142
  "**/*.css"
144
143
  ],
145
- "gitHead": "04d8d1c59329f12d94e4878e44d13c980eae68ac"
144
+ "gitHead": "4e8fc6f3f11f2946d6a4b7f3462be833a63115dc"
146
145
  }