carbon-react 95.0.2 → 95.1.3

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.
Files changed (37) hide show
  1. package/lib/__internal__/tooltip-provider/index.d.ts +2 -0
  2. package/lib/__internal__/tooltip-provider/index.js +6 -3
  3. package/lib/__internal__/validations/validation-icon.component.js +3 -1
  4. package/lib/components/button-toggle-group/button-toggle-group.component.js +11 -3
  5. package/lib/components/button-toggle-group/button-toggle-group.d.ts +2 -0
  6. package/lib/components/checkbox/checkbox.component.js +6 -1
  7. package/lib/components/checkbox/checkbox.d.ts +2 -0
  8. package/lib/components/date/date.component.js +2 -1
  9. package/lib/components/decimal/decimal.component.js +4 -1
  10. package/lib/components/grouped-character/grouped-character.component.js +4 -1
  11. package/lib/components/heading/heading.component.js +8 -2
  12. package/lib/components/help/help.component.js +24 -7
  13. package/lib/components/help/help.d.ts +2 -0
  14. package/lib/components/icon/icon-config.js +3 -1
  15. package/lib/components/icon/icon.component.js +14 -3
  16. package/lib/components/icon/icon.style.js +8 -1
  17. package/lib/components/numeral-date/numeral-date.component.js +11 -3
  18. package/lib/components/numeral-date/numeral-date.d.ts +2 -0
  19. package/lib/components/radio-button/radio-button.component.js +5 -0
  20. package/lib/components/radio-button/radio-button.d.ts +2 -0
  21. package/lib/components/select/filterable-select/filterable-select.component.js +25 -10
  22. package/lib/components/select/multi-select/multi-select.component.js +13 -16
  23. package/lib/components/select/simple-select/simple-select.component.js +6 -4
  24. package/lib/components/select/simple-select/simple-select.d.ts +1 -1
  25. package/lib/components/select/utils/is-expected-option.js +8 -0
  26. package/lib/components/switch/switch.component.js +6 -1
  27. package/lib/components/switch/switch.d.ts +2 -0
  28. package/lib/components/tabs/__internal__/tab-title/tab-title.style.js +13 -7
  29. package/lib/components/tabs/__internal__/tabs-header/tabs-header.style.js +2 -3
  30. package/lib/components/tabs/tabs.component.js +9 -2
  31. package/lib/components/textarea/textarea.component.js +6 -1
  32. package/lib/components/textarea/textarea.d.ts +2 -0
  33. package/lib/components/textbox/textbox.component.js +8 -3
  34. package/lib/components/textbox/textbox.d.ts +3 -1
  35. package/package.json +9 -3
  36. package/scripts/check_carbon_version.js +30 -0
  37. package/scripts/check_rfcs.js +49 -0
@@ -9,6 +9,8 @@ export interface TooltipProviderProps {
9
9
  tooltipPosition?: "top" | "bottom" | "left" | "right";
10
10
  /** Control whether the tooltip is visible */
11
11
  children: React.ReactNode;
12
+ /** Aria label for rendered help component */
13
+ helpAriaLabel?: string;
12
14
  }
13
15
 
14
16
  declare const ToolbarContext: React.Context<ToolbarContextProps>;
@@ -17,15 +17,18 @@ exports.TooltipContext = TooltipContext;
17
17
 
18
18
  const TooltipProvider = ({
19
19
  children,
20
- tooltipPosition
20
+ tooltipPosition,
21
+ helpAriaLabel
21
22
  }) => /*#__PURE__*/_react.default.createElement(TooltipContext.Provider, {
22
23
  value: {
23
- tooltipPosition
24
+ tooltipPosition,
25
+ helpAriaLabel
24
26
  }
25
27
  }, children);
26
28
 
27
29
  exports.TooltipProvider = TooltipProvider;
28
30
  TooltipProvider.propTypes = {
29
31
  children: _propTypes.default.node.isRequired,
30
- tooltipPosition: _propTypes.default.oneOf(["top", "bottom", "left", "right"])
32
+ tooltipPosition: _propTypes.default.oneOf(["top", "bottom", "left", "right"]),
33
+ helpAriaLabel: _propTypes.default.string
31
34
  };
@@ -100,7 +100,9 @@ const ValidationIcon = ({
100
100
  tooltipVisible: hasFocus || hasMouseOver || groupHasFocus || groupHasMouseOver || triggeredByIcon,
101
101
  tooltipFlipOverrides: isPartOfInput && !tooltipFlipOverrides ? ["top", "bottom"] : tooltipFlipOverrides,
102
102
  isPartOfInput: isPartOfInput,
103
- inputSize: size
103
+ inputSize: size,
104
+ "aria-hidden": "true",
105
+ focusable: false
104
106
  }));
105
107
  };
106
108
 
@@ -25,6 +25,8 @@ var _inputBehaviour = require("../../__internal__/input-behaviour");
25
25
 
26
26
  var _utils = require("../../style/utils");
27
27
 
28
+ var _tooltipProvider = require("../../__internal__/tooltip-provider");
29
+
28
30
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
29
31
 
30
32
  function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
@@ -53,6 +55,7 @@ const ButtonToggleGroup = ({
53
55
  "data-component": dataComponent,
54
56
  "data-element": dataElement,
55
57
  "data-role": dataRole,
58
+ helpAriaLabel,
56
59
  ...props
57
60
  }) => {
58
61
  const validationProps = {
@@ -60,7 +63,9 @@ const ButtonToggleGroup = ({
60
63
  warning,
61
64
  info
62
65
  };
63
- return /*#__PURE__*/_react.default.createElement(_inputBehaviour.InputGroupBehaviour, null, /*#__PURE__*/_react.default.createElement(_formField.default, _extends({
66
+ return /*#__PURE__*/_react.default.createElement(_tooltipProvider.TooltipProvider, {
67
+ helpAriaLabel: helpAriaLabel
68
+ }, /*#__PURE__*/_react.default.createElement(_inputBehaviour.InputGroupBehaviour, null, /*#__PURE__*/_react.default.createElement(_formField.default, _extends({
64
69
  useValidationIcon: validationOnLabel,
65
70
  label: label,
66
71
  labelHelp: labelHelp,
@@ -84,7 +89,7 @@ const ButtonToggleGroup = ({
84
89
  value: value
85
90
  }, children), !validationOnLabel && /*#__PURE__*/_react.default.createElement(_validationIcon.default, _extends({}, validationProps, {
86
91
  tooltipFlipOverrides: ["top", "bottom"]
87
- })))));
92
+ }))))));
88
93
  };
89
94
 
90
95
  ButtonToggleGroup.propTypes = { ...marginPropTypes,
@@ -171,7 +176,10 @@ ButtonToggleGroup.propTypes = { ...marginPropTypes,
171
176
  onBlur: _propTypes.default.func,
172
177
 
173
178
  /** The value of the Button Toggle Group */
174
- value: _propTypes.default.string
179
+ value: _propTypes.default.string,
180
+
181
+ /** Aria label for rendered help component */
182
+ helpAriaLabel: _propTypes.default.string
175
183
  };
176
184
  ButtonToggleGroup.defaultProps = {
177
185
  validationOnLabel: false,
@@ -49,6 +49,8 @@ export interface ButtonToggleGroupProps
49
49
  onChange?: (ev: React.ChangeEvent<HTMLInputElement>) => void;
50
50
  /** The value of the Button Toggle Group */
51
51
  value?: string;
52
+ /** Aria label for rendered help component */
53
+ helpAriaLabel?: string;
52
54
  }
53
55
 
54
56
  declare function ButtonToggleGroup(props: ButtonToggleGroupProps): JSX.Element;
@@ -60,6 +60,7 @@ const Checkbox = ({
60
60
  "data-component": dataComponent,
61
61
  "data-element": dataElement,
62
62
  "data-role": dataRole,
63
+ helpAriaLabel,
63
64
  ...props
64
65
  }) => {
65
66
  const largeScreen = (0, _useIsAboveBreakpoint.default)(adaptiveSpacingBreakpoint);
@@ -93,6 +94,7 @@ const Checkbox = ({
93
94
  ...props
94
95
  };
95
96
  return /*#__PURE__*/_react.default.createElement(_tooltipProvider.TooltipProvider, {
97
+ helpAriaLabel: helpAriaLabel,
96
98
  tooltipPosition: tooltipPosition
97
99
  }, /*#__PURE__*/_react.default.createElement(_checkbox.default, _extends({
98
100
  "data-component": dataComponent,
@@ -206,7 +208,10 @@ Checkbox.propTypes = {
206
208
  required: _propTypes.default.bool,
207
209
 
208
210
  /** Overrides the default tooltip position */
209
- tooltipPosition: _propTypes.default.oneOf(["top", "bottom", "left", "right"])
211
+ tooltipPosition: _propTypes.default.oneOf(["top", "bottom", "left", "right"]),
212
+
213
+ /** Aria label for rendered help component */
214
+ helpAriaLabel: _propTypes.default.string
210
215
  };
211
216
  Checkbox.defaultProps = {
212
217
  reverse: false,
@@ -15,6 +15,8 @@ export interface CheckboxProps extends CommonCheckableInputProps, MarginProps {
15
15
  value?: string;
16
16
  /** Overrides the default tooltip position */
17
17
  tooltipPosition?: "top" | "bottom" | "left" | "right";
18
+ /** Aria label for rendered help component */
19
+ helpAriaLabel?: string;
18
20
  }
19
21
 
20
22
  declare function Checkbox(props: CheckboxProps): JSX.Element;
@@ -619,7 +619,8 @@ let BaseDateInput = /*#__PURE__*/function (_React$Component) {
619
619
  }),
620
620
  inputRef: this.assignInput,
621
621
  adaptiveLabelBreakpoint: adaptiveLabelBreakpoint,
622
- tooltipPosition: tooltipPosition
622
+ tooltipPosition: tooltipPosition,
623
+ helpAriaLabel: this.props.helpAriaLabel
623
624
  }, events)), this.renderHiddenInput(), this.renderDatePicker({
624
625
  minDate,
625
626
  maxDate
@@ -361,7 +361,10 @@ Decimal.propTypes = {
361
361
  /**
362
362
  * Override the locale string, default from I18nProvider
363
363
  */
364
- locale: _propTypes.default.string
364
+ locale: _propTypes.default.string,
365
+
366
+ /** Aria label for rendered help component */
367
+ helpAriaLabel: _propTypes.default.string
365
368
  };
366
369
  Decimal.defaultProps = {
367
370
  align: "right",
@@ -164,7 +164,10 @@ GroupedCharacter.propTypes = { ...marginPropTypes,
164
164
  onBlur: _propTypes.default.func,
165
165
 
166
166
  /** Flag to configure component as mandatory */
167
- required: _propTypes.default.bool
167
+ required: _propTypes.default.bool,
168
+
169
+ /** Aria label for rendered help component */
170
+ helpAriaLabel: _propTypes.default.string
168
171
  };
169
172
  var _default = GroupedCharacter;
170
173
  exports.default = _default;
@@ -71,7 +71,8 @@ let Heading = /*#__PURE__*/function (_React$Component) {
71
71
  return /*#__PURE__*/_react.default.createElement(_heading.StyledHeaderHelp, {
72
72
  "data-element": "help",
73
73
  tooltipPosition: "right",
74
- href: this.props.helpLink
74
+ href: this.props.helpLink,
75
+ ariaLabel: this.props.helpAriaLabel
75
76
  }, this.props.help);
76
77
  }
77
78
  /**
@@ -255,7 +256,12 @@ Heading.propTypes = { ...marginPropTypes,
255
256
  /**
256
257
  * Pills that will be added after the title.
257
258
  */
258
- pills: _propTypes.default.node
259
+ pills: _propTypes.default.node,
260
+
261
+ /**
262
+ * Aria label for rendered help component
263
+ */
264
+ helpAriaLabel: _propTypes.default.string
259
265
  };
260
266
  Heading.defaultProps = {
261
267
  divider: true,
@@ -19,6 +19,8 @@ var _help = _interopRequireDefault(require("./help.style"));
19
19
 
20
20
  var _events = _interopRequireDefault(require("../../__internal__/utils/helpers/events"));
21
21
 
22
+ var _tooltipProvider = require("../../__internal__/tooltip-provider");
23
+
22
24
  var _utils = require("../../style/utils");
23
25
 
24
26
  var _help2 = require("./help.config");
@@ -46,10 +48,14 @@ const Help = ({
46
48
  tooltipBgColor,
47
49
  tooltipFontColor,
48
50
  tooltipFlipOverrides,
51
+ ariaLabel,
49
52
  ...rest
50
53
  }) => {
51
54
  const helpElement = (0, _react.useRef)(null);
52
55
  const [isTooltipVisible, updateTooltipVisible] = (0, _react.useState)(false);
56
+ const {
57
+ helpAriaLabel
58
+ } = (0, _react.useContext)(_tooltipProvider.TooltipContext);
53
59
  (0, _react.useEffect)(() => {
54
60
  document.addEventListener("keydown", handleKeyPress);
55
61
  return function cleanup() {
@@ -72,13 +78,10 @@ const Help = ({
72
78
  }
73
79
 
74
80
  return /*#__PURE__*/_react.default.createElement(_help.default, _extends({
75
- role: "tooltip",
76
81
  className: className,
77
82
  as: tagType,
78
83
  href: href,
79
84
  id: helpId,
80
- target: "_blank",
81
- rel: "noopener noreferrer",
82
85
  ref: helpElement,
83
86
  onClick: () => {
84
87
  helpElement.current.focus();
@@ -89,15 +92,26 @@ const Help = ({
89
92
  onMouseLeave: handleFocusBlur(false)
90
93
  }, (0, _tags.default)("help", rest), {
91
94
  tabIndex: tabIndex
92
- }, (0, _utils.filterStyledSystemMarginProps)(rest), rest), /*#__PURE__*/_react.default.createElement(_icon.default, {
95
+ }, href ? {
96
+ target: "_blank",
97
+ rel: "noopener noreferrer"
98
+ } : {
99
+ role: "tooltip",
100
+ "aria-label": ariaLabel || helpAriaLabel
101
+ }, (0, _utils.filterStyledSystemMarginProps)(rest), rest), /*#__PURE__*/_react.default.createElement(_icon.default, _extends({
93
102
  type: type,
94
103
  tooltipMessage: children,
95
104
  tooltipPosition: tooltipPosition,
96
105
  tooltipVisible: isFocused || isTooltipVisible,
97
106
  tooltipBgColor: tooltipBgColor,
98
107
  tooltipFontColor: tooltipFontColor,
99
- tooltipFlipOverrides: tooltipFlipOverrides
100
- }));
108
+ tooltipFlipOverrides: tooltipFlipOverrides,
109
+ focusable: false,
110
+ "aria-hidden": "true"
111
+ }, href && {
112
+ role: "tooltip",
113
+ ariaLabel: ariaLabel || helpAriaLabel
114
+ })));
101
115
  };
102
116
 
103
117
  Help.propTypes = { ...marginPropTypes,
@@ -150,7 +164,10 @@ Help.propTypes = { ...marginPropTypes,
150
164
 
151
165
  return new Error( // eslint-disable-next-line max-len
152
166
  `The \`${propName}\` prop supplied to \`${componentName}\` must be an array containing some or all of ["top", "bottom", "left", "right"].`);
153
- }
167
+ },
168
+
169
+ /** Aria label */
170
+ ariaLabel: _propTypes.default.string
154
171
  };
155
172
  Help.defaultProps = {
156
173
  tooltipPosition: "top",
@@ -30,6 +30,8 @@ export interface HelpProps extends MarginProps {
30
30
  tooltipPosition?: "top" | "bottom" | "left" | "right";
31
31
  /** Help Icon type */
32
32
  type?: IconType;
33
+ /** Aria label */
34
+ ariaLabel?: string;
33
35
  }
34
36
 
35
37
  declare function Help(props: HelpProps): JSX.Element;
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = exports.ICONS = exports.ICON_SIZES = exports.ICON_SHAPES = exports.ICON_TOOLTIP_POSITIONS = void 0;
6
+ exports.default = exports.ICONS = exports.ICON_FONT_SIZES = exports.ICON_SIZES = exports.ICON_SHAPES = exports.ICON_TOOLTIP_POSITIONS = void 0;
7
7
  const dlsConfig = {
8
8
  backgroundSize: {
9
9
  "extra-small": "16px",
@@ -30,6 +30,8 @@ const ICON_SHAPES = ["circle", "rounded-rect", "square"];
30
30
  exports.ICON_SHAPES = ICON_SHAPES;
31
31
  const ICON_SIZES = ["extra-small", "small", "medium", "large", "extra-large"];
32
32
  exports.ICON_SIZES = ICON_SIZES;
33
+ const ICON_FONT_SIZES = ["small", "medium", "large", "extra-large"];
34
+ exports.ICON_FONT_SIZES = ICON_FONT_SIZES;
33
35
  const ICONS = ["add", "alert", "analysis", "arrow_down", "arrow_left", "arrow_left_boxed", "arrow_left_right_small", "arrow_left_small", "arrow_right", "arrow_right_small", "arrow_up", "attach", "bank", "basket", "basket_with_squares", "bin", "blocked", "blocked_square", "block_arrow_right", "bold", "boxed_shapes", "bulk_destroy", "bullet_list", "bullet_list_dotted", "bullet_list_numbers", "business", "calendar", "calendar_today", "call", "camera", "card_view", "caret_down", "caret_left", "caret_right", "caret_up", "caret_large_down", "caret_large_left", "caret_large_right", "caret_large_up", "cart", "chat", "chart_bar", "chart_line", "chart_pie", "chat_notes", "chevron_down", "chevron_left", "chevron_right", "chevron_up", "chevron_down_thick", "chevron_left_thick", "chevron_right_thick", "chevron_up_thick", "circle_with_dots", "circles_connection", "clock", "close", "coins", "collaborate", "computer_clock", "connect", "copy", "credit_card", "credit_card_slash", "cross", "cross_circle", "csv", "delete", "delivery", "disputed", "document_right_align", "document_tick", "document_vertical_lines", "download", "drag", "drag_vertical", "draft", "dropdown", "duplicate", "edit", "edited", "email", "email_switch", "ellipsis_horizontal", "ellipsis_vertical", "envelope_dollar", "envelope_euro", "error", "error_square", "euro", "expand", "factory", "favourite", "favourite_lined", "fax", "feedback", "file_excel", "file_generic", "file_image", "file_pdf", "file_word", "files_leaning", "filter", "filter_new", "fit_height", "fit_width", "flag", "folder", "gift", "graph", "grid", "help", "hide", "home", "image", "in_progress", "in_transit", "individual", "info", "italic", "key", "ledger", "ledger_arrow_left", "ledger_arrow_right", "link", "list_view", "locked", "location", "logout", "lookup", "marker", "message", "messages", "minus", "minus_large", "mobile", "money_bag", "pause", "pause_circle", "pdf", "people", "people_switch", "person", "person_info", "person_tick", "phone", "play", "play_circle", "plus", "plus_large", "pound", "print", "progress", "progressed", "question", "refresh", "refresh_clock", "remove", "sage_coin", "save", "scan", "search", "services", "settings", "share", "shop", "sort_down", "sort_up", "spanner", "split", "split_container", "square_dot", "squares_nine", "stacked_boxes", "stacked_squares", "submitted", "sync", "tag", "three_boxes", "tick", "tick_circle", "undo", "unlocked", "upload", "uploaded", "video", "view", "warning", "admin", "arrow", "contacts", "create", "disconnect", "entry", "go", "lightbulb_off", "lightbulb_on", "none", "old_warning", "piggy_bank", "question_hollow", "question_mark", "settings_old", "talk", "true_tick"];
34
36
  exports.ICONS = ICONS;
35
37
  var _default = dlsConfig;
@@ -51,6 +51,9 @@ const Icon = /*#__PURE__*/_react.default.forwardRef(({
51
51
  tabIndex,
52
52
  isPartOfInput,
53
53
  inputSize,
54
+ role,
55
+ ariaLabel,
56
+ focusable = true,
54
57
  ...rest
55
58
  }, ref) => {
56
59
  const isInteractive = !!tooltipMessage && !disabled;
@@ -80,6 +83,7 @@ const Icon = /*#__PURE__*/_react.default.forwardRef(({
80
83
  }
81
84
  };
82
85
 
86
+ const hasTooltip = !disabled && tooltipMessage && focusable;
83
87
  const styleProps = {
84
88
  bg,
85
89
  bgSize,
@@ -88,8 +92,8 @@ const Icon = /*#__PURE__*/_react.default.forwardRef(({
88
92
  disabled,
89
93
  fontSize,
90
94
  isInteractive,
91
- tabIndex,
92
95
  type: iconType(),
96
+ tabIndex: hasTooltip && tabIndex === undefined ? 0 : tabIndex,
93
97
  ...(0, _utils.filterStyledSystemMarginProps)(rest)
94
98
  };
95
99
 
@@ -98,7 +102,11 @@ const Icon = /*#__PURE__*/_react.default.forwardRef(({
98
102
  key: "icon",
99
103
  className: className || null,
100
104
  "data-element": iconType()
101
- }, (0, _tags.default)("icon", rest), styleProps));
105
+ }, (0, _tags.default)("icon", rest), styleProps, {
106
+ hasTooltip: hasTooltip,
107
+ "aria-label": ariaLabel,
108
+ role: hasTooltip && role === undefined ? "tooltip" : role
109
+ }));
102
110
 
103
111
  const {
104
112
  tooltipPosition: tooltipPositionFromContext
@@ -197,7 +205,10 @@ Icon.propTypes = { ...marginPropTypes,
197
205
  inputSize: _propTypes.default.oneOf(["small", "medium", "large"]),
198
206
 
199
207
  /** @ignore @private */
200
- tabIndex: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.number])
208
+ tabIndex: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]),
209
+
210
+ /** @ignore @private */
211
+ focusable: _propTypes.default.bool
201
212
  };
202
213
  Icon.defaultProps = {
203
214
  bgSize: "small",
@@ -65,7 +65,8 @@ const StyledIcon = _styledComponents.default.span`
65
65
  bgShape,
66
66
  type,
67
67
  fontSize,
68
- disabled
68
+ disabled,
69
+ hasTooltip
69
70
  }) => {
70
71
  let finalColor;
71
72
  let finalHoverColor;
@@ -153,6 +154,12 @@ const StyledIcon = _styledComponents.default.span`
153
154
  display: block;
154
155
  }
155
156
 
157
+ ${hasTooltip && `
158
+ :focus {
159
+ outline: 2px solid ${theme.colors.focus};
160
+ }
161
+ `}
162
+
156
163
  ${_styledSystem.margin}
157
164
  `;
158
165
  }}
@@ -29,6 +29,8 @@ var _formField = _interopRequireDefault(require("../../__internal__/form-field")
29
29
 
30
30
  var _inputBehaviour = require("../../__internal__/input-behaviour");
31
31
 
32
+ var _tooltipProvider = require("../../__internal__/tooltip-provider");
33
+
32
34
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
33
35
 
34
36
  function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
@@ -82,6 +84,7 @@ const NumeralDate = ({
82
84
  enableInternalError,
83
85
  enableInternalWarning,
84
86
  tooltipPosition,
87
+ helpAriaLabel,
85
88
  ...rest
86
89
  }) => {
87
90
  const l = (0, _useLocale.default)();
@@ -165,7 +168,9 @@ const NumeralDate = ({
165
168
  const internalMessage = Object.keys(internalMessages).reduce((string, key) => internalMessages[key] ? `${string + internalMessages[key]}\n` : string, "");
166
169
  const internalError = enableInternalError ? internalMessage + error : error;
167
170
  const internalWarning = enableInternalWarning ? internalMessage + warning : warning;
168
- return /*#__PURE__*/_react.default.createElement(_inputBehaviour.InputGroupBehaviour, null, /*#__PURE__*/_react.default.createElement(_formField.default, _extends({
171
+ return /*#__PURE__*/_react.default.createElement(_tooltipProvider.TooltipProvider, {
172
+ helpAriaLabel: helpAriaLabel
173
+ }, /*#__PURE__*/_react.default.createElement(_inputBehaviour.InputGroupBehaviour, null, /*#__PURE__*/_react.default.createElement(_formField.default, _extends({
169
174
  "data-component": dataComponent,
170
175
  "data-element": dataElement,
171
176
  "data-role": dataRole,
@@ -225,7 +230,7 @@ const NumeralDate = ({
225
230
  size: size,
226
231
  tooltipPosition: tooltipPosition
227
232
  })));
228
- }))));
233
+ })))));
229
234
  };
230
235
 
231
236
  NumeralDate.propTypes = {
@@ -338,7 +343,10 @@ NumeralDate.propTypes = {
338
343
  size: _propTypes.default.oneOf(["small", "medium", "large"]),
339
344
 
340
345
  /** Overrides the default tooltip position */
341
- tooltipPosition: _propTypes.default.oneOf(["top", "bottom", "left", "right"])
346
+ tooltipPosition: _propTypes.default.oneOf(["top", "bottom", "left", "right"]),
347
+
348
+ /** Aria label for rendered help component */
349
+ helpAriaLabel: _propTypes.default.string
342
350
  };
343
351
  var _default = NumeralDate;
344
352
  exports.default = _default;
@@ -88,6 +88,8 @@ export interface NumeralDateProps extends ValidationPropTypes, MarginProps {
88
88
  validationOnLabel?: boolean;
89
89
  /** Overrides the default tooltip position */
90
90
  tooltipPosition?: "top" | "bottom" | "left" | "right";
91
+ /** Aria label for rendered help component */
92
+ helpAriaLabel?: string;
91
93
  }
92
94
 
93
95
  declare function NumeralDate(props: NumeralDateProps): JSX.Element;
@@ -68,6 +68,7 @@ const RadioButton = /*#__PURE__*/_react.default.forwardRef(({
68
68
  "data-component": dataComponent,
69
69
  "data-element": dataElement,
70
70
  "data-role": dataRole,
71
+ helpAriaLabel,
71
72
  ...props
72
73
  }, ref) => {
73
74
  const marginProps = (0, _utils.filterStyledSystemMarginProps)(props);
@@ -113,6 +114,7 @@ const RadioButton = /*#__PURE__*/_react.default.forwardRef(({
113
114
  ...props
114
115
  };
115
116
  return /*#__PURE__*/_react.default.createElement(_tooltipProvider.TooltipProvider, {
117
+ helpAriaLabel: helpAriaLabel,
116
118
  tooltipPosition: tooltipPosition
117
119
  }, /*#__PURE__*/_react.default.createElement(_radioButton.default, _extends({
118
120
  "data-component": dataComponent,
@@ -209,6 +211,9 @@ RadioButton.propTypes = { ...marginPropTypes,
209
211
 
210
212
  /** Overrides the default tooltip position */
211
213
  tooltipPosition: _propTypes.default.oneOf(["top", "bottom", "left", "right"]),
214
+
215
+ /** Aria label for rendered help component */
216
+ helpAriaLabel: _propTypes.default.string,
212
217
  ...radioButtonGroupPassedProps
213
218
  };
214
219
  RadioButton.defaultProps = {
@@ -18,6 +18,8 @@ export interface RadioButtonProps
18
18
  value: string;
19
19
  /** Overrides the default tooltip position */
20
20
  tooltipPosition?: "top" | "bottom" | "left" | "right";
21
+ /** Aria label for rendered help component */
22
+ helpAriaLabel?: string;
21
23
  }
22
24
 
23
25
  declare function RadioButton(
@@ -78,7 +78,7 @@ const FilterableSelect = /*#__PURE__*/_react.default.forwardRef(({
78
78
  const [textboxRef, setTextboxRef] = (0, _react.useState)();
79
79
  const [isOpen, setOpen] = (0, _react.useState)(false);
80
80
  const [textValue, setTextValue] = (0, _react.useState)("");
81
- const [selectedValue, setSelectedValue] = (0, _react.useState)("");
81
+ const [selectedValue, setSelectedValue] = (0, _react.useState)(value || defaultValue || "");
82
82
  const [highlightedValue, setHighlightedValue] = (0, _react.useState)("");
83
83
  const [filterText, setFilterText] = (0, _react.useState)("");
84
84
  const createCustomEvent = (0, _react.useCallback)(newValue => {
@@ -187,21 +187,33 @@ const FilterableSelect = /*#__PURE__*/_react.default.forwardRef(({
187
187
  }
188
188
  }, [setMatchingText, selectedValue]);
189
189
  (0, _react.useEffect)(() => {
190
- const newValue = value || defaultValue;
191
190
  const modeSwitchedMessage = "Input elements should not switch from uncontrolled to controlled (or vice versa). " + "Decide between using a controlled or uncontrolled input element for the lifetime of the component";
192
191
  const onChangeMissingMessage = "onChange prop required when using a controlled input element";
193
192
  (0, _invariant.default)(isControlled.current === (value !== undefined), modeSwitchedMessage);
194
193
  (0, _invariant.default)(!isControlled.current || isControlled.current && onChange, onChangeMissingMessage);
195
- setSelectedValue(prevValue => {
196
- if (value && isControlled.current && prevValue !== newValue) {
197
- setMatchingText(newValue);
194
+
195
+ if (isControlled.current) {
196
+ setSelectedValue(prevValue => {
197
+ if (value && prevValue !== value) {
198
+ setMatchingText(value);
199
+ }
200
+
201
+ return value;
202
+ });
203
+ setHighlightedValue(value);
204
+ } else {
205
+ if (textValue !== selectedValue) {
206
+ setMatchingText(selectedValue);
198
207
  }
199
208
 
200
- return newValue;
201
- });
202
- setHighlightedValue(newValue); // prevent value update on filter change
209
+ if (highlightedValue !== selectedValue) {
210
+ setHighlightedValue(selectedValue);
211
+ }
212
+ } // prevent value update on filter change
213
+ // selectedValue and highlightedValue omitted from deps, only want uncontrolled change if onChange/children update
203
214
  // eslint-disable-next-line react-hooks/exhaustive-deps
204
- }, [value, defaultValue, onChange, children]);
215
+
216
+ }, [value, onChange, children]);
205
217
  (0, _react.useEffect)(() => {
206
218
  if (!isOpen) {
207
219
  setFilterText("");
@@ -215,8 +227,11 @@ const FilterableSelect = /*#__PURE__*/_react.default.forwardRef(({
215
227
  (0, _invariant.default)(!hasListActionButton || hasListActionButton && onListAction, onListActionMissingMessage);
216
228
  }, [listActionButton, onListAction]);
217
229
  (0, _react.useEffect)(() => {
218
- setMatchingText(value || defaultValue); // update text value only when children are changing
230
+ if (isControlled.current) {
231
+ setMatchingText(value);
232
+ } // update text value only when children are changing
219
233
  // eslint-disable-next-line react-hooks/exhaustive-deps
234
+
220
235
  }, [value, children]);
221
236
  (0, _react.useEffect)(() => {
222
237
  if (onFilterChange) {
@@ -82,7 +82,7 @@ const MultiSelect = /*#__PURE__*/_react.default.forwardRef(({
82
82
  const [textboxRef, setTextboxRef] = (0, _react.useState)();
83
83
  const [isOpen, setOpenState] = (0, _react.useState)(false);
84
84
  const [textValue, setTextValue] = (0, _react.useState)("");
85
- const [selectedValue, setSelectedValue] = (0, _react.useState)([]);
85
+ const [selectedValue, setSelectedValue] = (0, _react.useState)(value || defaultValue || []);
86
86
  const [highlightedValue, setHighlightedValue] = (0, _react.useState)("");
87
87
  const [filterText, setFilterText] = (0, _react.useState)("");
88
88
  const [placeholderOverride, setPlaceholderOverride] = (0, _react.useState)();
@@ -124,7 +124,7 @@ const MultiSelect = /*#__PURE__*/_react.default.forwardRef(({
124
124
  setSelectedValue(previousValue => {
125
125
  isClickTriggeredBySelect.current = true;
126
126
 
127
- if (previousValue.length === 0) {
127
+ if (!previousValue.length) {
128
128
  return previousValue;
129
129
  }
130
130
 
@@ -185,7 +185,7 @@ const MultiSelect = /*#__PURE__*/_react.default.forwardRef(({
185
185
  const mapValuesToPills = (0, _react.useCallback)(() => {
186
186
  const canDelete = !disabled && !readOnly;
187
187
 
188
- if (selectedValue.length === 0) {
188
+ if (!selectedValue.length) {
189
189
  return "";
190
190
  }
191
191
 
@@ -205,31 +205,28 @@ const MultiSelect = /*#__PURE__*/_react.default.forwardRef(({
205
205
  const {
206
206
  title
207
207
  } = pillProps;
208
+ const key = title + ((matchingOption === null || matchingOption === void 0 ? void 0 : matchingOption.props.value) || index);
208
209
  return /*#__PURE__*/_react.default.createElement(_multiSelect.StyledSelectPillContainer, {
209
- key: title
210
+ key: key
210
211
  }, /*#__PURE__*/_react.default.createElement(_pill.default, _extends({
211
212
  onDelete: canDelete ? () => removeSelectedValue(index) : undefined
212
213
  }, pillProps), title));
213
214
  }); // eslint-disable-next-line react-hooks/exhaustive-deps
214
215
  }, [children, disabled, readOnly, selectedValue]);
215
216
  (0, _react.useEffect)(() => {
216
- const newValue = value || defaultValue;
217
217
  const modeSwitchedMessage = "Input elements should not switch from uncontrolled to controlled (or vice versa). " + "Decide between using a controlled or uncontrolled input element for the lifetime of the component";
218
- const onChageMissingMessage = "onChange prop required when using a controlled input element";
218
+ const onChangeMissingMessage = "onChange prop required when using a controlled input element";
219
219
  (0, _invariant.default)(isControlled.current === (value !== undefined), modeSwitchedMessage);
220
- (0, _invariant.default)(!isControlled.current || isControlled.current && onChange, onChageMissingMessage);
221
- setSelectedValue(previousValue => {
222
- if (!newValue && previousValue.length === 0) {
223
- return previousValue;
224
- }
220
+ (0, _invariant.default)(!isControlled.current || isControlled.current && onChange, onChangeMissingMessage);
225
221
 
226
- return newValue;
227
- });
228
- }, [value, defaultValue, onChange]); // removes placeholder when a value is present
222
+ if (isControlled.current) {
223
+ setSelectedValue(value);
224
+ }
225
+ }, [value, onChange]); // removes placeholder when a value is present
229
226
 
230
227
  (0, _react.useEffect)(() => {
231
- const hasValue = value && value.length > 0;
232
- const hasSelectedValue = selectedValue && selectedValue.length > 0;
228
+ const hasValue = value === null || value === void 0 ? void 0 : value.length;
229
+ const hasSelectedValue = selectedValue === null || selectedValue === void 0 ? void 0 : selectedValue.length;
233
230
 
234
231
  if (hasValue || hasSelectedValue) {
235
232
  setPlaceholderOverride(" ");
@@ -77,7 +77,7 @@ const SimpleSelect = /*#__PURE__*/_react.default.forwardRef(({
77
77
  const [textboxRef, setTextboxRef] = (0, _react.useState)();
78
78
  const [isOpen, setOpenState] = (0, _react.useState)(false);
79
79
  const [textValue, setTextValue] = (0, _react.useState)("");
80
- const [selectedValue, setSelectedValue] = (0, _react.useState)("");
80
+ const [selectedValue, setSelectedValue] = (0, _react.useState)(value || defaultValue || "");
81
81
  const childOptions = (0, _react.useMemo)(() => _react.default.Children.toArray(children), [children]);
82
82
  const createCustomEvent = (0, _react.useCallback)(newValue => {
83
83
  const customEvent = {
@@ -176,13 +176,15 @@ const SimpleSelect = /*#__PURE__*/_react.default.forwardRef(({
176
176
  isClickTriggeredBySelect.current = false;
177
177
  }, []);
178
178
  (0, _react.useEffect)(() => {
179
- const newValue = value || defaultValue;
180
179
  const modeSwitchedMessage = "Input elements should not switch from uncontrolled to controlled (or vice versa). " + "Decide between using a controlled or uncontrolled input element for the lifetime of the component";
181
180
  const onChangeMissingMessage = "onChange prop required when using a controlled input element";
182
181
  (0, _invariant.default)(isControlled.current === (value !== undefined), modeSwitchedMessage);
183
182
  (0, _invariant.default)(!isControlled.current || isControlled.current && onChange, onChangeMissingMessage);
184
- setSelectedValue(newValue);
185
- }, [value, defaultValue, onChange]);
183
+
184
+ if (isControlled.current) {
185
+ setSelectedValue(value);
186
+ }
187
+ }, [value, onChange]);
186
188
  (0, _react.useEffect)(() => {
187
189
  const matchingOption = childOptions.find(child => (0, _isExpectedOption.default)(child, selectedValue));
188
190
  let newText = "";
@@ -55,7 +55,7 @@ export interface SimpleSelectProps
55
55
  | "left-start"
56
56
  | "left-end";
57
57
  /** Use the opposite list placement if the set placement does not fit */
58
- flipEnabled?: bool;
58
+ flipEnabled?: boolean;
59
59
  }
60
60
 
61
61
  declare function SimpleSelect(
@@ -22,5 +22,13 @@ function isExpectedOption(element, expectedValue) {
22
22
  return false;
23
23
  }
24
24
 
25
+ const {
26
+ length
27
+ } = typeof expectedValue === "string" ? expectedValue : Object.keys(expectedValue);
28
+
29
+ if (!length) {
30
+ return false;
31
+ }
32
+
25
33
  return (0, _isExpectedValue.default)(element.props.value, expectedValue);
26
34
  }
@@ -59,6 +59,7 @@ const Switch = ({
59
59
  "data-component": dataComponent,
60
60
  "data-element": dataElement,
61
61
  "data-role": dataRole,
62
+ helpAriaLabel,
62
63
  ...rest
63
64
  }) => {
64
65
  const isControlled = checked !== undefined;
@@ -123,6 +124,7 @@ const Switch = ({
123
124
  ...rest
124
125
  };
125
126
  return /*#__PURE__*/_react.default.createElement(_tooltipProvider.TooltipProvider, {
127
+ helpAriaLabel: helpAriaLabel,
126
128
  tooltipPosition: tooltipPosition
127
129
  }, /*#__PURE__*/_react.default.createElement(_switch.default, switchStyleProps, /*#__PURE__*/_react.default.createElement(_checkableInput.default, inputProps, /*#__PURE__*/_react.default.createElement(_switchSlider.default, switchSliderProps))));
128
130
  };
@@ -241,7 +243,10 @@ Switch.propTypes = {
241
243
  required: _propTypes.default.bool,
242
244
 
243
245
  /** Overrides the default tooltip position */
244
- tooltipPosition: _propTypes.default.oneOf(["top", "bottom", "left", "right"])
246
+ tooltipPosition: _propTypes.default.oneOf(["top", "bottom", "left", "right"]),
247
+
248
+ /** Aria label for rendered help component */
249
+ helpAriaLabel: _propTypes.default.string
245
250
  };
246
251
  Switch.defaultProps = {
247
252
  labelInline: false,
@@ -29,6 +29,8 @@ export interface SwitchProps extends CommonCheckableInputProps, MarginProps {
29
29
  value?: string;
30
30
  /** Overrides the default tooltip position */
31
31
  tooltipPosition?: "top" | "bottom" | "left" | "right";
32
+ /** Aria label for rendered help component */
33
+ helpAriaLabel?: string;
32
34
  }
33
35
 
34
36
  declare function Switch(props: SwitchProps): JSX.Element;
@@ -90,7 +90,7 @@ const StyledTitleContent = _styledComponents.default.div`
90
90
  ${size === "large" && position === "left" && (0, _styledComponents.css)`
91
91
  font-size: 16px;
92
92
  padding: 22px 24px;
93
- ${!isTabSelected && !alternateStyling && (error || warning || info) && `margin-right: -2px;`}
93
+ ${!isTabSelected && !alternateStyling && error && `margin-right: -2px;`}
94
94
  `}
95
95
 
96
96
  ${size === "default" && (0, _styledComponents.css)`
@@ -99,7 +99,7 @@ const StyledTitleContent = _styledComponents.default.div`
99
99
  padding-bottom: 8px;
100
100
  `}
101
101
 
102
- ${position === "left" && !isTabSelected && !alternateStyling && (error || warning || info) && `margin-right: -2px;`}
102
+ ${position === "left" && !isTabSelected && !alternateStyling && error && `margin-right: -2px;`}
103
103
  `}
104
104
  `}
105
105
 
@@ -370,21 +370,23 @@ const StyledTabTitle = _styledComponents.default.li`
370
370
  alternateStyling,
371
371
  error,
372
372
  warning,
373
- info
373
+ info,
374
+ isInSidebar
374
375
  }) => position === "left" && (0, _styledComponents.css)`
375
376
  background-color: transparent;
376
377
  border-bottom: 0px;
377
378
 
379
+ ${!isInSidebar && (0, _styledComponents.css)`
380
+ border-right: ${alternateStyling ? "1px" : "2px"} solid
381
+ ${theme.tab.background};
382
+ `}
383
+
378
384
  ${!borders && (0, _styledComponents.css)`
379
385
  ${StyledTitleContent} {
380
386
  border-bottom: none;
381
387
  }
382
388
  `}
383
389
 
384
- ${!alternateStyling && (0, _styledComponents.css)`
385
- border-right: 2px solid ${theme.tab.background};
386
- `}
387
-
388
390
  display: block;
389
391
  height: auto;
390
392
  margin-left: 0px;
@@ -397,6 +399,10 @@ const StyledTabTitle = _styledComponents.default.li`
397
399
  ${alternateStyling && `border-right-color: ${theme.tab.background};`}
398
400
  }
399
401
 
402
+ ${(warning || info) && (0, _styledComponents.css)`
403
+ border-right: none;
404
+ `}
405
+
400
406
  ${({
401
407
  isTabSelected
402
408
  }) => isTabSelected && (0, _styledComponents.css)`
@@ -75,11 +75,10 @@ const StyledTabsHeaderList = _styledComponents.default.ul`
75
75
 
76
76
  ${({
77
77
  position,
78
- noRightBorder,
79
- theme
78
+ noRightBorder
80
79
  }) => position === "left" && (0, _styledComponents.css)`
81
80
  flex-direction: column;
82
- box-shadow: inset ${computeLineWidth} 0px 0px 0px ${theme.tab.background};
81
+ box-shadow: none;
83
82
 
84
83
  ${noRightBorder && (0, _styledComponents.css)`
85
84
  box-shadow: none;
@@ -282,8 +282,15 @@ const Tabs = ({
282
282
  tab = child;
283
283
  }
284
284
  });
285
- return tab ? /*#__PURE__*/(0, _react.cloneElement)(tab, {
286
- isTabSelected: isTabSelected(tab.props.tabId)
285
+ return tab ? /*#__PURE__*/(0, _react.cloneElement)(tab, { ...tab.props,
286
+ role: "tabpanel",
287
+ position,
288
+ isTabSelected: isTabSelected(tab.props.tabId),
289
+ key: `${tab.props.tabId}-tab`,
290
+ ariaLabelledby: `${tab.props.tabId}-tab`,
291
+ updateErrors,
292
+ updateWarnings,
293
+ updateInfos
287
294
  }) : null;
288
295
  };
289
296
  /** Builds all tabs where non selected tabs have class of hidden */
@@ -190,9 +190,11 @@ let Textarea = /*#__PURE__*/function (_React$Component) {
190
190
  "data-component": dataComponent,
191
191
  "data-element": dataElement,
192
192
  "data-role": dataRole,
193
+ helpAriaLabel,
193
194
  ...props
194
195
  } = this.props;
195
196
  return /*#__PURE__*/_react.default.createElement(_tooltipProvider.TooltipProvider, {
197
+ helpAriaLabel: helpAriaLabel,
196
198
  tooltipPosition: tooltipPosition
197
199
  }, /*#__PURE__*/_react.default.createElement(_inputBehaviour.InputBehaviour, null, /*#__PURE__*/_react.default.createElement(_textarea.default, _extends({
198
200
  labelInline: labelInline,
@@ -374,7 +376,10 @@ Textarea.propTypes = { ...marginPropTypes,
374
376
  required: _propTypes.default.bool,
375
377
 
376
378
  /** Overrides the default tooltip position */
377
- tooltipPosition: _propTypes.default.oneOf(["top", "bottom", "left", "right"])
379
+ tooltipPosition: _propTypes.default.oneOf(["top", "bottom", "left", "right"]),
380
+
381
+ /** Aria label for rendered help component */
382
+ helpAriaLabel: _propTypes.default.string
378
383
  };
379
384
  Textarea.defaultProps = {
380
385
  labelWidth: 30,
@@ -70,6 +70,8 @@ export interface TextareaProps
70
70
  warnOverLimit?: boolean;
71
71
  /** Overrides the default tooltip position */
72
72
  tooltipPosition?: "top" | "bottom" | "left" | "right";
73
+ /** Aria label for rendered help component */
74
+ helpAriaLabel?: string;
73
75
  }
74
76
 
75
77
  declare class Textarea extends React.Component<TextareaProps> {}
@@ -86,10 +86,12 @@ const Textbox = ({
86
86
  enforceCharacterLimit = true,
87
87
  characterLimit,
88
88
  warnOverLimit = false,
89
+ helpAriaLabel,
89
90
  ...props
90
91
  }) => {
91
92
  const [maxLength, characterCount] = (0, _useCharacterCount.default)(value, characterLimit, warnOverLimit, enforceCharacterLimit);
92
93
  return /*#__PURE__*/_react.default.createElement(_tooltipProvider.TooltipProvider, {
94
+ helpAriaLabel: helpAriaLabel,
93
95
  tooltipPosition: tooltipPosition
94
96
  }, /*#__PURE__*/_react.default.createElement(_inputBehaviour.InputBehaviour, null, /*#__PURE__*/_react.default.createElement(_formField.default, _extends({
95
97
  disabled: disabled,
@@ -218,10 +220,10 @@ Textbox.propTypes = {
218
220
  /** Event handler for the mouse down event */
219
221
  onMouseDown: _propTypes.default.func,
220
222
 
221
- /** Defered callback called after the onChange event */
223
+ /** Deferred callback called after the onChange event */
222
224
  onChangeDeferred: _propTypes.default.func,
223
225
 
224
- /** Integer to determine timeout for defered callback */
226
+ /** Integer to determine timeout for deferred callback */
225
227
  deferTimeout: _propTypes.default.number,
226
228
 
227
229
  /** Unique identifier for the input. Will use a randomly generated GUID if none is provided */
@@ -347,7 +349,10 @@ Textbox.propTypes = {
347
349
  characterLimit: _propTypes.default.string,
348
350
 
349
351
  /** Whether to display the character count message in red */
350
- warnOverLimit: _propTypes.default.bool
352
+ warnOverLimit: _propTypes.default.bool,
353
+
354
+ /** Aria label for rendered help component */
355
+ helpAriaLabel: _propTypes.default.string
351
356
  };
352
357
  Textbox.defaultProps = {
353
358
  labelWidth: 30,
@@ -57,7 +57,7 @@ export interface CommonTextboxProps
57
57
  labelWidth?: number;
58
58
  /** Specify a callback triggered on change */
59
59
  onChange?: (ev: React.ChangeEvent<HTMLInputElement>) => void;
60
- /** Defered callback to be called after the onChange event */
60
+ /** Deferred callback to be called after the onChange event */
61
61
  onChangeDeferred?: () => void;
62
62
  /** Specify a callback triggered on click */
63
63
  onClick?: (ev: React.MouseEvent<HTMLElement>) => void;
@@ -95,6 +95,8 @@ export interface CommonTextboxProps
95
95
  inputRef?: (input: React.RefObject<HTMLInputElement>) => void;
96
96
  /** Overrides the default tooltip position */
97
97
  tooltipPosition?: "top" | "bottom" | "left" | "right";
98
+ /** Aria label for rendered help component */
99
+ helpAriaLabel?: string;
98
100
  }
99
101
 
100
102
  export interface TextboxProps extends CommonTextboxProps {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "carbon-react",
3
- "version": "95.0.2",
3
+ "version": "95.1.3",
4
4
  "description": "A library of reusable React components for easily building user interfaces.",
5
5
  "engineStrict": true,
6
6
  "engines": {
@@ -8,10 +8,12 @@
8
8
  "node": ">=14.16.0"
9
9
  },
10
10
  "files": [
11
- "lib"
11
+ "lib",
12
+ "scripts/check_carbon_version.js",
13
+ "scripts/check_rfcs.js"
12
14
  ],
13
15
  "scripts": {
14
- "start": "node ./check_version.js && start-storybook -p 9001 -s .assets -c .storybook",
16
+ "start": "node ./scripts/check_node_version.js && start-storybook -p 9001 -s .assets -c .storybook",
15
17
  "start:debug-theme": "cross-env STORYBOOK_DEBUG_THEME=true npm run start",
16
18
  "test": "jest --config=./jest.conf.json",
17
19
  "test-update": "jest --config=./jest.conf.json --updateSnapshot",
@@ -22,6 +24,7 @@
22
24
  "lint": "eslint ./src",
23
25
  "precompile": "npm run clean-lib && npm run copy-files && npm run babel",
24
26
  "prepublishOnly": "npm run precompile",
27
+ "postinstall": "node ./scripts/check_carbon_version.js && node ./scripts/check_rfcs.js",
25
28
  "watch": "npm run clean-lib && npm run copy-files -- --watch & npm run babel -- --watch",
26
29
  "build-storybook": "build-storybook -c .storybook -s .assets",
27
30
  "start:static": "npx http-server -p 9001 ./storybook-static",
@@ -132,16 +135,19 @@
132
135
  "typescript": "^3.9.5"
133
136
  },
134
137
  "dependencies": {
138
+ "@octokit/rest": "^18.12.0",
135
139
  "@popperjs/core": "^2.9.0",
136
140
  "@sage/design-tokens": "^1.73.0",
137
141
  "@styled-system/prop-types": "^5.1.5",
138
142
  "@tippyjs/react": "^4.2.5",
139
143
  "classnames": "~2.2.6",
140
144
  "crypto-js": "~3.3.0",
145
+ "dotenv": "^10.0.0",
141
146
  "immutable": "~3.8.2",
142
147
  "invariant": "^2.2.4",
143
148
  "lodash": "^4.17.20",
144
149
  "moment": "~2.20.1",
150
+ "node-fetch": "^2.6.1",
145
151
  "polished": "^4.0.5",
146
152
  "prop-types": "^15.7.2",
147
153
  "react-day-picker": "~6.1.1",
@@ -0,0 +1,30 @@
1
+ /* eslint-disable no-console */
2
+ const fetch = require("node-fetch");
3
+ const dotenv = require("dotenv");
4
+ const chalk = require("chalk");
5
+ const { version } = require("../package.json");
6
+
7
+ dotenv.config();
8
+ const majorVersion = version.split(".")[0];
9
+
10
+ const checkCarbonVersion = () => {
11
+ fetch("https://registry.npmjs.com/carbon-react")
12
+ .then((res) => res.json())
13
+ .then((data) => {
14
+ const { latest } = data["dist-tags"];
15
+ const latestMajor = latest.split(".")[0];
16
+
17
+ const diff = Number(latestMajor) - Number(majorVersion);
18
+
19
+ if (diff > 1) {
20
+ console.log(
21
+ `carbon-react version installed is currently ${chalk.yellow(
22
+ diff
23
+ )} major versions behind the latest.`
24
+ );
25
+ }
26
+ })
27
+ .catch((err) => console.log(err));
28
+ };
29
+
30
+ if (!process.env.CARBON_INSTALL) checkCarbonVersion();
@@ -0,0 +1,49 @@
1
+ /* eslint-disable no-console */
2
+ const { Octokit } = require("@octokit/rest");
3
+ const dotenv = require("dotenv");
4
+ const chalk = require("chalk");
5
+
6
+ dotenv.config();
7
+ const octokit = new Octokit({
8
+ baseUrl: "https://api.github.com",
9
+ });
10
+
11
+ const method = "GET";
12
+ const owner = "sage";
13
+ const path = "pulls";
14
+ const repo = "carbon";
15
+ const url = "/repos/{owner}/{repo}/{path}";
16
+
17
+ const getOpenRfcs = async () => {
18
+ const { data } = await octokit.request({
19
+ owner,
20
+ repo,
21
+ url,
22
+ method,
23
+ path,
24
+ });
25
+
26
+ return data.filter((item) => {
27
+ const labels = item.labels.filter((label) => label.name === "RFC");
28
+
29
+ return labels.length > 0;
30
+ });
31
+ };
32
+
33
+ const getRfcTitle = (rfc) => rfc.title.split(": ")[1];
34
+
35
+ const checkRfcs = async () => {
36
+ const openRfcs = await getOpenRfcs();
37
+
38
+ if (openRfcs.length > 0) {
39
+ console.log("\ncarbon-react currently has open RFCs:");
40
+
41
+ openRfcs.forEach((item) => {
42
+ const title = getRfcTitle(item);
43
+ console.log(`- ${title}: ${chalk.cyan(item.html_url)}`);
44
+ });
45
+ console.log("\n");
46
+ }
47
+ };
48
+
49
+ if (!process.env.CARBON_INSTALL) checkRfcs();