@carbon/react 1.97.0 → 1.99.0-rc.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.
- package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +1002 -967
- package/es/components/ButtonSet/ButtonSet.d.ts +5 -0
- package/es/components/ButtonSet/ButtonSet.js +68 -4
- package/es/components/CodeSnippet/CodeSnippet.d.ts +1 -1
- package/es/components/Copy/Copy.d.ts +1 -1
- package/es/components/CopyButton/CopyButton.d.ts +1 -1
- package/es/components/DataTable/DataTable.d.ts +2 -1
- package/es/components/DataTable/TableContainer.d.ts +10 -2
- package/es/components/DataTable/TableContainer.js +15 -3
- package/es/components/DataTable/state/sorting.d.ts +2 -4
- package/es/components/DatePicker/DatePicker.d.ts +3 -2
- package/es/components/DatePicker/DatePicker.js +18 -135
- package/es/components/DatePicker/DatePickerLocales.d.ts +12 -0
- package/es/components/DatePicker/DatePickerLocales.js +135 -0
- package/es/components/DatePickerInput/DatePickerInput.js +50 -28
- package/es/components/Dropdown/Dropdown.js +13 -1
- package/es/components/FileUploader/FileUploader.d.ts +23 -8
- package/es/components/FileUploader/FileUploader.js +53 -33
- package/es/components/FileUploader/FileUploaderButton.js +2 -2
- package/es/components/FileUploader/FileUploaderDropContainer.d.ts +13 -2
- package/es/components/FileUploader/FileUploaderDropContainer.js +15 -6
- package/es/components/FileUploader/FileUploaderItem.js +9 -6
- package/es/components/Link/Link.js +1 -1
- package/es/components/Menu/index.d.ts +4 -3
- package/es/components/MultiSelect/FilterableMultiSelect.js +1 -0
- package/es/components/MultiSelect/MultiSelect.js +1 -0
- package/es/components/NumberInput/NumberInput.d.ts +6 -2
- package/es/components/NumberInput/NumberInput.js +17 -5
- package/es/components/Pagination/Pagination.js +5 -5
- package/es/components/Popover/index.d.ts +1 -1
- package/es/components/Popover/index.js +27 -13
- package/es/components/Select/Select.js +27 -33
- package/es/components/Tabs/Tabs.js +1 -1
- package/es/components/TextArea/TextArea.js +14 -4
- package/es/components/TextInput/PasswordInput.js +3 -2
- package/es/components/Toggletip/index.d.ts +1 -0
- package/es/components/Toggletip/index.js +1 -1
- package/es/components/Tooltip/index.d.ts +3 -2
- package/es/internal/FloatingMenu.js +6 -5
- package/es/internal/OptimizedResize.js +4 -5
- package/es/tools/events.d.ts +1 -1
- package/lib/components/ButtonSet/ButtonSet.d.ts +5 -0
- package/lib/components/ButtonSet/ButtonSet.js +67 -3
- package/lib/components/CodeSnippet/CodeSnippet.d.ts +1 -1
- package/lib/components/Copy/Copy.d.ts +1 -1
- package/lib/components/CopyButton/CopyButton.d.ts +1 -1
- package/lib/components/DataTable/DataTable.d.ts +2 -1
- package/lib/components/DataTable/TableContainer.d.ts +10 -2
- package/lib/components/DataTable/TableContainer.js +15 -3
- package/lib/components/DataTable/state/sorting.d.ts +2 -4
- package/lib/components/DatePicker/DatePicker.d.ts +3 -2
- package/lib/components/DatePicker/DatePicker.js +18 -135
- package/lib/components/DatePicker/DatePickerLocales.d.ts +12 -0
- package/lib/components/DatePicker/DatePickerLocales.js +137 -0
- package/lib/components/DatePickerInput/DatePickerInput.js +49 -27
- package/lib/components/Dropdown/Dropdown.js +13 -1
- package/lib/components/FileUploader/FileUploader.d.ts +23 -8
- package/lib/components/FileUploader/FileUploader.js +53 -33
- package/lib/components/FileUploader/FileUploaderButton.js +2 -2
- package/lib/components/FileUploader/FileUploaderDropContainer.d.ts +13 -2
- package/lib/components/FileUploader/FileUploaderDropContainer.js +15 -6
- package/lib/components/FileUploader/FileUploaderItem.js +9 -6
- package/lib/components/Link/Link.js +1 -1
- package/lib/components/Menu/index.d.ts +4 -3
- package/lib/components/MultiSelect/FilterableMultiSelect.js +1 -0
- package/lib/components/MultiSelect/MultiSelect.js +1 -0
- package/lib/components/NumberInput/NumberInput.d.ts +6 -2
- package/lib/components/NumberInput/NumberInput.js +17 -5
- package/lib/components/Pagination/Pagination.js +5 -5
- package/lib/components/Popover/index.d.ts +1 -1
- package/lib/components/Popover/index.js +27 -13
- package/lib/components/Select/Select.js +27 -33
- package/lib/components/Tabs/Tabs.js +1 -1
- package/lib/components/TextArea/TextArea.js +14 -4
- package/lib/components/TextInput/PasswordInput.js +3 -2
- package/lib/components/Toggletip/index.d.ts +1 -0
- package/lib/components/Toggletip/index.js +3 -0
- package/lib/components/Tooltip/index.d.ts +3 -2
- package/lib/internal/FloatingMenu.js +6 -5
- package/lib/internal/OptimizedResize.js +4 -5
- package/lib/tools/events.d.ts +1 -1
- package/package.json +21 -29
- package/telemetry.yml +3 -0
|
@@ -126,6 +126,7 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
|
|
|
126
126
|
max,
|
|
127
127
|
min,
|
|
128
128
|
onBlur,
|
|
129
|
+
onStepperBlur,
|
|
129
130
|
onChange,
|
|
130
131
|
onClick,
|
|
131
132
|
onKeyUp,
|
|
@@ -426,6 +427,7 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
|
|
|
426
427
|
if (disableWheelProp) {
|
|
427
428
|
e.target.removeEventListener('wheel', disableWheel);
|
|
428
429
|
}
|
|
430
|
+
let parsedValueForBlur;
|
|
429
431
|
if (type === 'text') {
|
|
430
432
|
// When isControlled, the current inputValue needs re-parsed
|
|
431
433
|
// because the consumer's onChange hasn't been called yet and
|
|
@@ -441,6 +443,7 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
|
|
|
441
443
|
// causing the _numberValue to mismatch the formatted value in
|
|
442
444
|
// the input. To avoid this, formattedValue is re-parsed.
|
|
443
445
|
const parsedFormattedNewValue = numberParser.parse(formattedValue);
|
|
446
|
+
parsedValueForBlur = parsedFormattedNewValue;
|
|
444
447
|
if (onChange && isValid) {
|
|
445
448
|
const state = {
|
|
446
449
|
value: parsedFormattedNewValue,
|
|
@@ -466,7 +469,12 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
|
|
|
466
469
|
}
|
|
467
470
|
}
|
|
468
471
|
if (onBlur) {
|
|
469
|
-
|
|
472
|
+
if (type === 'number') {
|
|
473
|
+
onBlur(e, value);
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
const parsedTextValue = parsedValueForBlur ?? (isControlled ? numberParser.parse(inputValue) : numberValue);
|
|
477
|
+
onBlur(e, parsedTextValue);
|
|
470
478
|
}
|
|
471
479
|
},
|
|
472
480
|
pattern: pattern,
|
|
@@ -486,7 +494,7 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
|
|
|
486
494
|
className: `${prefix}--number__control-btn down-icon`,
|
|
487
495
|
disabled: disabled || readOnly,
|
|
488
496
|
onClick: event => handleStepperClick(event, 'down'),
|
|
489
|
-
onBlur:
|
|
497
|
+
onBlur: onStepperBlur,
|
|
490
498
|
tabIndex: -1,
|
|
491
499
|
title: decrementNumLabel || iconDescription,
|
|
492
500
|
type: "button"
|
|
@@ -499,7 +507,7 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
|
|
|
499
507
|
className: `${prefix}--number__control-btn up-icon`,
|
|
500
508
|
disabled: disabled || readOnly,
|
|
501
509
|
onClick: event => handleStepperClick(event, 'up'),
|
|
502
|
-
onBlur:
|
|
510
|
+
onBlur: onStepperBlur,
|
|
503
511
|
tabIndex: -1,
|
|
504
512
|
title: incrementNumLabel || iconDescription,
|
|
505
513
|
type: "button"
|
|
@@ -610,10 +618,14 @@ NumberInput.propTypes = {
|
|
|
610
618
|
*/
|
|
611
619
|
stepStartValue: PropTypes.number,
|
|
612
620
|
/**
|
|
613
|
-
* Provide an optional handler that is called when the input
|
|
614
|
-
* buttons are blurred.
|
|
621
|
+
* Provide an optional handler that is called when the input is blurred.
|
|
615
622
|
*/
|
|
616
623
|
onBlur: PropTypes.func,
|
|
624
|
+
/**
|
|
625
|
+
* Provide an optional handler that is called when the stepper
|
|
626
|
+
* buttons are blurred.
|
|
627
|
+
*/
|
|
628
|
+
onStepperBlur: PropTypes.func,
|
|
617
629
|
/**
|
|
618
630
|
* Provide an optional handler that is called when the internal state of
|
|
619
631
|
* NumberInput changes. This handler is called with event and state info.
|
|
@@ -7,16 +7,16 @@
|
|
|
7
7
|
|
|
8
8
|
import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
9
9
|
import { CaretLeft, CaretRight } from '@carbon/icons-react';
|
|
10
|
-
import cx from 'classnames';
|
|
11
|
-
import PropTypes from 'prop-types';
|
|
12
10
|
import React, { useRef, useState, useEffect } from 'react';
|
|
11
|
+
import { IconButton } from '../IconButton/index.js';
|
|
12
|
+
import PropTypes from 'prop-types';
|
|
13
13
|
import Select from '../Select/Select.js';
|
|
14
14
|
import '../Select/Select.Skeleton.js';
|
|
15
15
|
import SelectItem from '../SelectItem/SelectItem.js';
|
|
16
|
+
import cx from 'classnames';
|
|
17
|
+
import isEqual from 'react-fast-compare';
|
|
16
18
|
import { useFallbackId } from '../../internal/useId.js';
|
|
17
19
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
18
|
-
import { IconButton } from '../IconButton/index.js';
|
|
19
|
-
import isEqual from 'react-fast-compare';
|
|
20
20
|
|
|
21
21
|
var _CaretLeft, _CaretRight;
|
|
22
22
|
function mapPageSizesToObject(sizes) {
|
|
@@ -266,7 +266,7 @@ const Pagination = /*#__PURE__*/React.forwardRef(({
|
|
|
266
266
|
onClick: decrementPage,
|
|
267
267
|
ref: backBtnRef
|
|
268
268
|
}, _CaretLeft || (_CaretLeft = /*#__PURE__*/React.createElement(CaretLeft, null))), /*#__PURE__*/React.createElement(IconButton, {
|
|
269
|
-
align: "top
|
|
269
|
+
align: "top",
|
|
270
270
|
disabled: forwardButtonDisabled || isLastPage,
|
|
271
271
|
kind: "ghost",
|
|
272
272
|
className: forwardButtonClasses,
|
|
@@ -60,27 +60,41 @@ forwardRef) {
|
|
|
60
60
|
const caretRef = useRef(null);
|
|
61
61
|
const popover = useRef(null);
|
|
62
62
|
const enableFloatingStyles = useFeatureFlag('enable-v12-dynamic-floating-styles') || autoAlign;
|
|
63
|
+
const lastClickWasInsidePopoverContent = useRef(false);
|
|
63
64
|
let align = mapPopoverAlign(initialAlign);
|
|
64
65
|
|
|
66
|
+
// Tracks clicks inside PopoverContent to prevent it from closing when clicked, this handles an edge
|
|
67
|
+
// case where the popover will close when clicking non-focusable elements (e.g. text)
|
|
68
|
+
useEvent(popover, 'mousedown', event => {
|
|
69
|
+
const target = event.target;
|
|
70
|
+
lastClickWasInsidePopoverContent.current = refs.floating.current?.contains(target) || false;
|
|
71
|
+
|
|
72
|
+
// reset flag
|
|
73
|
+
if (lastClickWasInsidePopoverContent.current) {
|
|
74
|
+
setTimeout(() => {
|
|
75
|
+
lastClickWasInsidePopoverContent.current = false;
|
|
76
|
+
}, 0);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
65
80
|
// The `Popover` should close whenever it and its children loses focus
|
|
66
81
|
useEvent(popover, 'focusout', event => {
|
|
67
82
|
const relatedTarget = event.relatedTarget;
|
|
68
|
-
if (isTabTip) {
|
|
69
|
-
if (relatedTarget && !popover.current?.contains(relatedTarget)) {
|
|
70
|
-
onRequestClose?.();
|
|
71
|
-
}
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
83
|
if (!relatedTarget) {
|
|
84
|
+
// do not close if PopoverContent was clicked
|
|
85
|
+
if (lastClickWasInsidePopoverContent.current) {
|
|
86
|
+
lastClickWasInsidePopoverContent.current = false;
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
75
89
|
onRequestClose?.();
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const isOutsideFloating = enableFloatingStyles && refs.floating.current ? !refs.floating.current.contains(relatedTarget) : true;
|
|
90
|
+
} else if (relatedTarget && !popover.current?.contains(relatedTarget)) {
|
|
91
|
+
const isOutsideFloating = enableFloatingStyles && refs.floating.current ? !refs.floating.current.contains(relatedTarget) : true;
|
|
92
|
+
const isFocusableWrapper = relatedTarget && popover.current && relatedTarget.contains(popover.current);
|
|
80
93
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
94
|
+
// Only close if focus moved outside both containers and not to an interactive parent wrapper
|
|
95
|
+
if (isOutsideFloating && !isFocusableWrapper) {
|
|
96
|
+
onRequestClose?.();
|
|
97
|
+
}
|
|
84
98
|
}
|
|
85
99
|
});
|
|
86
100
|
useWindowEvent('click', ({
|
|
@@ -14,12 +14,12 @@ import { deprecate } from '../../prop-types/deprecate.js';
|
|
|
14
14
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
15
15
|
import '../FluidForm/FluidForm.js';
|
|
16
16
|
import { FormContext } from '../FluidForm/FormContext.js';
|
|
17
|
-
import { useId } from '../../internal/useId.js';
|
|
18
17
|
import { composeEventHandlers } from '../../tools/events.js';
|
|
19
18
|
import { Text } from '../Text/Text.js';
|
|
20
19
|
import '../Text/TextDirection.js';
|
|
21
20
|
import { AILabel } from '../AILabel/index.js';
|
|
22
21
|
import { isComponentElement } from '../../internal/utils.js';
|
|
22
|
+
import { useNormalizedInputProps } from '../../internal/useNormalizedInputProps.js';
|
|
23
23
|
|
|
24
24
|
const Select = /*#__PURE__*/React.forwardRef(({
|
|
25
25
|
className,
|
|
@@ -49,7 +49,6 @@ const Select = /*#__PURE__*/React.forwardRef(({
|
|
|
49
49
|
isFluid
|
|
50
50
|
} = useContext(FormContext);
|
|
51
51
|
const [isFocused, setIsFocused] = useState(false);
|
|
52
|
-
const selectInstanceId = useId();
|
|
53
52
|
// Convert children to an array of valid elements once using type narrowing
|
|
54
53
|
const validChildren = React.Children.toArray(children).filter(child => /*#__PURE__*/React.isValidElement(child));
|
|
55
54
|
|
|
@@ -61,55 +60,50 @@ const Select = /*#__PURE__*/React.forwardRef(({
|
|
|
61
60
|
// otherwise, fallback to the first option's text
|
|
62
61
|
const initialTitle = other?.title || selectedOption?.props?.text || validChildren[0]?.props?.text || '';
|
|
63
62
|
const [title, setTitle] = useState(initialTitle);
|
|
63
|
+
const normalizedProps = useNormalizedInputProps({
|
|
64
|
+
id,
|
|
65
|
+
disabled,
|
|
66
|
+
readOnly,
|
|
67
|
+
invalid,
|
|
68
|
+
invalidText,
|
|
69
|
+
warn,
|
|
70
|
+
warnText
|
|
71
|
+
});
|
|
64
72
|
const selectClasses = cx({
|
|
65
73
|
[`${prefix}--select`]: true,
|
|
66
74
|
[`${prefix}--select--inline`]: inline,
|
|
67
75
|
[`${prefix}--select--light`]: light,
|
|
68
|
-
[`${prefix}--select--invalid`]: invalid,
|
|
69
|
-
[`${prefix}--select--disabled`]: disabled,
|
|
76
|
+
[`${prefix}--select--invalid`]: normalizedProps.invalid,
|
|
77
|
+
[`${prefix}--select--disabled`]: normalizedProps.disabled,
|
|
70
78
|
[`${prefix}--select--readonly`]: readOnly,
|
|
71
|
-
[`${prefix}--select--warning`]: warn,
|
|
72
|
-
[`${prefix}--select--fluid--invalid`]: isFluid && invalid,
|
|
79
|
+
[`${prefix}--select--warning`]: normalizedProps.warn,
|
|
80
|
+
[`${prefix}--select--fluid--invalid`]: isFluid && normalizedProps.invalid,
|
|
73
81
|
[`${prefix}--select--fluid--focus`]: isFluid && isFocused,
|
|
74
82
|
[`${prefix}--select--slug`]: slug,
|
|
75
83
|
[`${prefix}--select--decorator`]: decorator
|
|
76
84
|
});
|
|
77
85
|
const labelClasses = cx(`${prefix}--label`, {
|
|
78
86
|
[`${prefix}--visually-hidden`]: hideLabel,
|
|
79
|
-
[`${prefix}--label--disabled`]: disabled
|
|
87
|
+
[`${prefix}--label--disabled`]: normalizedProps.disabled
|
|
80
88
|
});
|
|
81
89
|
const inputClasses = cx({
|
|
82
90
|
[`${prefix}--select-input`]: true,
|
|
83
91
|
[`${prefix}--select-input--${size}`]: size
|
|
84
92
|
});
|
|
85
|
-
const
|
|
86
|
-
const errorText = (() => {
|
|
87
|
-
if (invalid) {
|
|
88
|
-
return invalidText;
|
|
89
|
-
}
|
|
90
|
-
if (warn) {
|
|
91
|
-
return warnText;
|
|
92
|
-
}
|
|
93
|
-
})();
|
|
94
|
-
const error = invalid || warn ? /*#__PURE__*/React.createElement(Text, {
|
|
95
|
-
as: "div",
|
|
96
|
-
className: `${prefix}--form-requirement`,
|
|
97
|
-
id: errorId
|
|
98
|
-
}, errorText) : null;
|
|
93
|
+
const error = normalizedProps.validation;
|
|
99
94
|
const helperTextClasses = cx(`${prefix}--form__helper-text`, {
|
|
100
|
-
[`${prefix}--form__helper-text--disabled`]: disabled
|
|
95
|
+
[`${prefix}--form__helper-text--disabled`]: normalizedProps.disabled
|
|
101
96
|
});
|
|
102
|
-
const helperId = !helperText ? undefined : `select-helper-text-${selectInstanceId}`;
|
|
103
97
|
const helper = helperText ? /*#__PURE__*/React.createElement(Text, {
|
|
104
98
|
as: "div",
|
|
105
|
-
id: helperId,
|
|
99
|
+
id: normalizedProps.helperId,
|
|
106
100
|
className: helperTextClasses
|
|
107
101
|
}, helperText) : null;
|
|
108
102
|
const ariaProps = {};
|
|
109
|
-
if (invalid) {
|
|
110
|
-
ariaProps['aria-describedby'] =
|
|
103
|
+
if (normalizedProps.invalid) {
|
|
104
|
+
ariaProps['aria-describedby'] = normalizedProps.invalidId;
|
|
111
105
|
} else if (!inline && !isFluid) {
|
|
112
|
-
ariaProps['aria-describedby'] = helper ? helperId : undefined;
|
|
106
|
+
ariaProps['aria-describedby'] = helper ? normalizedProps.helperId : undefined;
|
|
113
107
|
}
|
|
114
108
|
const handleFocus = evt => {
|
|
115
109
|
setIsFocused(evt.type === 'focus' ? true : false);
|
|
@@ -146,8 +140,8 @@ const Select = /*#__PURE__*/React.forwardRef(({
|
|
|
146
140
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("select", _extends({}, other, ariaProps, {
|
|
147
141
|
id: id,
|
|
148
142
|
className: inputClasses,
|
|
149
|
-
disabled: disabled || undefined,
|
|
150
|
-
"aria-invalid": invalid || undefined,
|
|
143
|
+
disabled: normalizedProps.disabled || undefined,
|
|
144
|
+
"aria-invalid": normalizedProps.invalid || undefined,
|
|
151
145
|
"aria-readonly": readOnly || undefined,
|
|
152
146
|
title: title,
|
|
153
147
|
onChange: composeEventHandlers([onChange, handleChange])
|
|
@@ -155,9 +149,9 @@ const Select = /*#__PURE__*/React.forwardRef(({
|
|
|
155
149
|
ref: ref
|
|
156
150
|
}), children), /*#__PURE__*/React.createElement(ChevronDown, {
|
|
157
151
|
className: `${prefix}--select__arrow`
|
|
158
|
-
}), invalid && /*#__PURE__*/React.createElement(WarningFilled, {
|
|
152
|
+
}), normalizedProps.invalid && /*#__PURE__*/React.createElement(WarningFilled, {
|
|
159
153
|
className: `${prefix}--select__invalid-icon`
|
|
160
|
-
}), !invalid && warn && /*#__PURE__*/React.createElement(WarningAltFilled, {
|
|
154
|
+
}), !normalizedProps.invalid && normalizedProps.warn && /*#__PURE__*/React.createElement(WarningAltFilled, {
|
|
161
155
|
className: `${prefix}--select__invalid-icon ${prefix}--select__invalid-icon--warning`
|
|
162
156
|
}));
|
|
163
157
|
})();
|
|
@@ -173,10 +167,10 @@ const Select = /*#__PURE__*/React.forwardRef(({
|
|
|
173
167
|
className: `${prefix}--select-input--inline__wrapper`
|
|
174
168
|
}, /*#__PURE__*/React.createElement("div", {
|
|
175
169
|
className: `${prefix}--select-input__wrapper`,
|
|
176
|
-
"data-invalid": invalid || null
|
|
170
|
+
"data-invalid": normalizedProps.invalid || null
|
|
177
171
|
}, input), error), !inline && /*#__PURE__*/React.createElement("div", {
|
|
178
172
|
className: `${prefix}--select-input__wrapper`,
|
|
179
|
-
"data-invalid": invalid || null,
|
|
173
|
+
"data-invalid": normalizedProps.invalid || null,
|
|
180
174
|
onFocus: handleFocus,
|
|
181
175
|
onBlur: handleFocus
|
|
182
176
|
}, input, slug ? normalizedDecorator : decorator ? /*#__PURE__*/React.createElement("div", {
|
|
@@ -886,7 +886,7 @@ const Tab = /*#__PURE__*/forwardRef(({
|
|
|
886
886
|
})
|
|
887
887
|
}, /*#__PURE__*/React.createElement("button", {
|
|
888
888
|
type: "button",
|
|
889
|
-
tabIndex:
|
|
889
|
+
tabIndex: -1,
|
|
890
890
|
"aria-disabled": disabled,
|
|
891
891
|
"aria-hidden": selectedIndex === index && dismissable ? 'false' : 'true',
|
|
892
892
|
disabled: disabled,
|
|
@@ -202,8 +202,10 @@ const TextArea = frFn((props, forwardRef) => {
|
|
|
202
202
|
}, labelText) : null;
|
|
203
203
|
const counter = enableCounter && maxCount && (counterMode === 'character' || counterMode === 'word') ? /*#__PURE__*/React.createElement(Text, {
|
|
204
204
|
as: "div",
|
|
205
|
-
className: counterClasses
|
|
205
|
+
className: counterClasses,
|
|
206
|
+
"aria-hidden": "true"
|
|
206
207
|
}, `${textCount}/${maxCount}`) : null;
|
|
208
|
+
const counterDescriptionId = enableCounter && maxCount ? `${id}-counter-desc` : undefined;
|
|
207
209
|
const helperId = !helperText ? undefined : `text-area-helper-text-${textAreaInstanceId}`;
|
|
208
210
|
const helper = helperText ? /*#__PURE__*/React.createElement(Text, {
|
|
209
211
|
as: "div",
|
|
@@ -234,8 +236,13 @@ const TextArea = frFn((props, forwardRef) => {
|
|
|
234
236
|
let ariaDescribedBy;
|
|
235
237
|
if (invalid) {
|
|
236
238
|
ariaDescribedBy = errorId;
|
|
237
|
-
} else if (
|
|
238
|
-
ariaDescribedBy =
|
|
239
|
+
} else if (warn && !isFluid) {
|
|
240
|
+
ariaDescribedBy = warnId;
|
|
241
|
+
} else {
|
|
242
|
+
const ids = [];
|
|
243
|
+
if (!isFluid && helperText && helperId) ids.push(helperId);
|
|
244
|
+
if (counterDescriptionId) ids.push(counterDescriptionId);
|
|
245
|
+
ariaDescribedBy = ids.length > 0 ? ids.join(' ') : undefined;
|
|
239
246
|
}
|
|
240
247
|
if (enableCounter) {
|
|
241
248
|
// handle different counter mode
|
|
@@ -292,7 +299,10 @@ const TextArea = frFn((props, forwardRef) => {
|
|
|
292
299
|
className: formItemClasses
|
|
293
300
|
}, /*#__PURE__*/React.createElement("div", {
|
|
294
301
|
className: `${prefix}--text-area__label-wrapper`
|
|
295
|
-
}, label, counter), /*#__PURE__*/React.createElement("
|
|
302
|
+
}, label, counter), enableCounter && maxCount && /*#__PURE__*/React.createElement("span", {
|
|
303
|
+
id: counterDescriptionId,
|
|
304
|
+
className: `${prefix}--visually-hidden`
|
|
305
|
+
}, counterMode === 'word' ? `Word limit ${maxCount}` : `Character limit ${maxCount}`), /*#__PURE__*/React.createElement("div", {
|
|
296
306
|
ref: wrapperRef,
|
|
297
307
|
className: textAreaWrapperClasses,
|
|
298
308
|
"data-invalid": invalid || null
|
|
@@ -135,6 +135,7 @@ const PasswordInput = /*#__PURE__*/React.forwardRef(({
|
|
|
135
135
|
[`${prefix}--tooltip--${tooltipPosition}`]: tooltipPosition,
|
|
136
136
|
[`${prefix}--tooltip--align-${tooltipAlignment}`]: tooltipAlignment
|
|
137
137
|
});
|
|
138
|
+
const tooltipClasses = cx(`${prefix}--toggle-password-tooltip`, `${prefix}--icon-tooltip`);
|
|
138
139
|
let align = undefined;
|
|
139
140
|
if (tooltipPosition === 'top' || tooltipPosition === 'bottom') {
|
|
140
141
|
if (tooltipAlignment === 'center') {
|
|
@@ -172,12 +173,12 @@ const PasswordInput = /*#__PURE__*/React.forwardRef(({
|
|
|
172
173
|
className: `${prefix}--text-input__divider`
|
|
173
174
|
}), /*#__PURE__*/React.createElement(Tooltip, {
|
|
174
175
|
align: align,
|
|
175
|
-
className:
|
|
176
|
+
className: tooltipClasses,
|
|
176
177
|
label: passwordIsVisible ? hidePasswordLabel : showPasswordLabel
|
|
177
178
|
}, /*#__PURE__*/React.createElement("button", {
|
|
178
179
|
type: "button",
|
|
179
180
|
className: passwordVisibilityToggleClasses,
|
|
180
|
-
disabled: disabled
|
|
181
|
+
disabled: disabled,
|
|
181
182
|
onClick: handleTogglePasswordVisibility
|
|
182
183
|
}, passwordVisibilityIcon)));
|
|
183
184
|
useEffect(() => {
|
|
@@ -282,4 +282,4 @@ ToggletipActions.propTypes = {
|
|
|
282
282
|
className: PropTypes.string
|
|
283
283
|
};
|
|
284
284
|
|
|
285
|
-
export { Toggletip, ToggletipActions, ToggletipButton, ToggletipContent, ToggletipLabel };
|
|
285
|
+
export { Toggletip, ToggletipActions, ToggletipButton, ToggletipContent, ToggletipLabel, Toggletip as default };
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
import { DefinitionTooltip } from './DefinitionTooltip';
|
|
7
|
+
import { DefinitionTooltip, type DefinitionTooltipProps } from './DefinitionTooltip';
|
|
8
8
|
import { Tooltip, type TooltipProps } from './Tooltip';
|
|
9
|
-
export { DefinitionTooltip, Tooltip, type TooltipProps };
|
|
9
|
+
export { DefinitionTooltip, Tooltip, type DefinitionTooltipProps, type TooltipProps, };
|
|
10
|
+
export default Tooltip;
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
import React, { useContext, useState, useRef, useCallback, useEffect, cloneElement } from 'react';
|
|
9
9
|
import * as FeatureFlags from '@carbon/feature-flags';
|
|
10
10
|
import ReactDOM from 'react-dom';
|
|
11
|
-
import window from 'window-or-global';
|
|
12
11
|
import { Tab } from './keyboard/keys.js';
|
|
13
12
|
import { match } from './keyboard/match.js';
|
|
14
13
|
import { selectorTabbable, selectorFocusable } from './keyboard/navigation.js';
|
|
@@ -109,14 +108,16 @@ const FloatingMenu = ({
|
|
|
109
108
|
const menuSize = menuBody.getBoundingClientRect();
|
|
110
109
|
const refPosition = triggerEl ? triggerEl.getBoundingClientRect() : undefined;
|
|
111
110
|
const offsetValue = typeof menuOffset === 'function' ? menuOffset(menuBody, menuDirection, triggerEl, flipped) : menuOffset;
|
|
111
|
+
const scrollX = globalThis.scrollX ?? 0;
|
|
112
|
+
const scrollY = globalThis.scrollY ?? 0;
|
|
112
113
|
if (updateOrientation) {
|
|
113
114
|
updateOrientation({
|
|
114
115
|
menuSize,
|
|
115
116
|
refPosition,
|
|
116
117
|
direction: menuDirection,
|
|
117
118
|
offset: offsetValue,
|
|
118
|
-
scrollX
|
|
119
|
-
scrollY
|
|
119
|
+
scrollX,
|
|
120
|
+
scrollY,
|
|
120
121
|
container: {
|
|
121
122
|
rect: target().getBoundingClientRect(),
|
|
122
123
|
position: getComputedStyle(target()).position
|
|
@@ -136,8 +137,8 @@ const FloatingMenu = ({
|
|
|
136
137
|
},
|
|
137
138
|
offset: offsetValue,
|
|
138
139
|
direction: menuDirection,
|
|
139
|
-
scrollX
|
|
140
|
-
scrollY
|
|
140
|
+
scrollX,
|
|
141
|
+
scrollY,
|
|
141
142
|
container: {
|
|
142
143
|
rect: target().getBoundingClientRect(),
|
|
143
144
|
position: getComputedStyle(target()).position
|
|
@@ -5,9 +5,8 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
// mdn resize function
|
|
8
|
+
// Use `globalThis` for universal access to global object (browser, workers, Node).
|
|
9
|
+
const win = globalThis;
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* A callback function to be executed on `resize`.
|
|
@@ -25,7 +24,7 @@ const OptimizedResize = (() => {
|
|
|
25
24
|
const handleResize = () => {
|
|
26
25
|
if (!running) {
|
|
27
26
|
running = true;
|
|
28
|
-
|
|
27
|
+
win.requestAnimationFrame(runCallbacks);
|
|
29
28
|
}
|
|
30
29
|
};
|
|
31
30
|
const addCallback = callback => {
|
|
@@ -38,7 +37,7 @@ const OptimizedResize = (() => {
|
|
|
38
37
|
/** Adds a callback function to be executed on window `resize`. */
|
|
39
38
|
add: callback => {
|
|
40
39
|
if (!callbacks.length) {
|
|
41
|
-
|
|
40
|
+
win.addEventListener('resize', handleResize);
|
|
42
41
|
}
|
|
43
42
|
addCallback(callback);
|
|
44
43
|
return {
|
package/es/tools/events.d.ts
CHANGED
|
@@ -14,4 +14,4 @@ import type { SyntheticEvent } from 'react';
|
|
|
14
14
|
* @param handlers - An array of event handler functions.
|
|
15
15
|
* @returns A composite event handler.
|
|
16
16
|
*/
|
|
17
|
-
export declare const composeEventHandlers: <E extends SyntheticEvent = SyntheticEvent
|
|
17
|
+
export declare const composeEventHandlers: <E extends SyntheticEvent = SyntheticEvent<Element, Event>>(handlers: (((event: E, ...args: any[]) => void) | undefined)[]) => (event: E, ...args: any[]) => void;
|
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import React from 'react';
|
|
8
8
|
export interface ButtonSetProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
9
|
+
/**
|
|
10
|
+
* fluid: button set resize to the size of the container up to a maximum dependant on the
|
|
11
|
+
* number of buttons. Overrides `stacked` property.
|
|
12
|
+
*/
|
|
13
|
+
fluid?: boolean;
|
|
9
14
|
/**
|
|
10
15
|
* Specify the button arrangement of the set (vertically stacked or
|
|
11
16
|
* horizontal)
|
|
@@ -14,22 +14,81 @@ var React = require('react');
|
|
|
14
14
|
var PropTypes = require('prop-types');
|
|
15
15
|
var cx = require('classnames');
|
|
16
16
|
var usePrefix = require('../../internal/usePrefix.js');
|
|
17
|
+
var useIsomorphicEffect = require('../../internal/useIsomorphicEffect.js');
|
|
17
18
|
|
|
19
|
+
const buttonOrder = kind => ({
|
|
20
|
+
ghost: 1,
|
|
21
|
+
'danger--ghost': 2,
|
|
22
|
+
tertiary: 3,
|
|
23
|
+
danger: 5,
|
|
24
|
+
primary: 6
|
|
25
|
+
})[kind] ?? 4;
|
|
26
|
+
const getButtonKind = element => {
|
|
27
|
+
if (/*#__PURE__*/React.isValidElement(element) && element.props && typeof element.props === 'object') {
|
|
28
|
+
const props = element.props;
|
|
29
|
+
return props.kind ?? 'primary';
|
|
30
|
+
}
|
|
31
|
+
return 'primary';
|
|
32
|
+
};
|
|
18
33
|
const ButtonSet = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
19
34
|
const {
|
|
20
35
|
children,
|
|
21
36
|
className,
|
|
37
|
+
fluid,
|
|
22
38
|
stacked,
|
|
23
39
|
...rest
|
|
24
40
|
} = props;
|
|
25
41
|
const prefix = usePrefix.usePrefix();
|
|
42
|
+
const fluidInnerRef = React.useRef(null);
|
|
43
|
+
const [isStacked, setIsStacked] = React.useState(false);
|
|
44
|
+
const [sortedChildren, setSortedChildren] = React.useState(React.Children.toArray(children));
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Used to determine if the buttons are currently stacked
|
|
48
|
+
*/
|
|
49
|
+
useIsomorphicEffect.default(() => {
|
|
50
|
+
const checkStacking = () => {
|
|
51
|
+
let newIsStacked = stacked || false;
|
|
52
|
+
if (fluidInnerRef && fluidInnerRef.current) {
|
|
53
|
+
const computedStyle = window.getComputedStyle(fluidInnerRef.current);
|
|
54
|
+
newIsStacked = computedStyle?.getPropertyValue?.('--flex-direction') === 'column';
|
|
55
|
+
}
|
|
56
|
+
return newIsStacked;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/* initial value not dependant on observer */
|
|
60
|
+
setIsStacked(checkStacking());
|
|
61
|
+
if (!fluidInnerRef.current) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
65
|
+
setIsStacked(checkStacking());
|
|
66
|
+
});
|
|
67
|
+
resizeObserver.observe(fluidInnerRef.current);
|
|
68
|
+
return () => resizeObserver.disconnect();
|
|
69
|
+
}, [isStacked, stacked]);
|
|
70
|
+
React.useEffect(() => {
|
|
71
|
+
const newSortedChildren = React.Children.toArray(children);
|
|
72
|
+
newSortedChildren.sort((a, b) => {
|
|
73
|
+
return (buttonOrder(getButtonKind(a)) - buttonOrder(getButtonKind(b))) * (isStacked ? -1 : 1);
|
|
74
|
+
});
|
|
75
|
+
setSortedChildren(newSortedChildren);
|
|
76
|
+
|
|
77
|
+
// adding sortedChildren to deps causes an infinite loop
|
|
78
|
+
}, [children, isStacked]);
|
|
26
79
|
const buttonSetClasses = cx(className, `${prefix}--btn-set`, {
|
|
27
|
-
[`${prefix}--btn-set--stacked`]:
|
|
80
|
+
[`${prefix}--btn-set--stacked`]: isStacked,
|
|
81
|
+
[`${prefix}--btn-set--fluid`]: fluid
|
|
28
82
|
});
|
|
29
83
|
return /*#__PURE__*/React.createElement("div", _rollupPluginBabelHelpers.extends({}, rest, {
|
|
30
84
|
className: buttonSetClasses,
|
|
31
85
|
ref: ref
|
|
32
|
-
}),
|
|
86
|
+
}), fluid ? /*#__PURE__*/React.createElement("div", {
|
|
87
|
+
ref: fluidInnerRef,
|
|
88
|
+
className: cx(`${prefix}--btn-set__fluid-inner`, {
|
|
89
|
+
[`${prefix}--btn-set__fluid-inner--auto-stack`]: true
|
|
90
|
+
})
|
|
91
|
+
}, sortedChildren) : children);
|
|
33
92
|
});
|
|
34
93
|
ButtonSet.displayName = 'ButtonSet';
|
|
35
94
|
ButtonSet.propTypes = {
|
|
@@ -41,9 +100,14 @@ ButtonSet.propTypes = {
|
|
|
41
100
|
* Specify an optional className to be added to your ButtonSet
|
|
42
101
|
*/
|
|
43
102
|
className: PropTypes.string,
|
|
103
|
+
/**
|
|
104
|
+
* fluid: button set resize to the size of the container up to a maximum dependant on the
|
|
105
|
+
* number of buttons.
|
|
106
|
+
*/
|
|
107
|
+
fluid: PropTypes.bool,
|
|
44
108
|
/**
|
|
45
109
|
* Specify the button arrangement of the set (vertically stacked or
|
|
46
|
-
* horizontal)
|
|
110
|
+
* horizontal) - ignored when fluid is true
|
|
47
111
|
*/
|
|
48
112
|
stacked: PropTypes.bool
|
|
49
113
|
};
|
|
@@ -111,7 +111,7 @@ declare namespace CodeSnippet {
|
|
|
111
111
|
/**
|
|
112
112
|
* Specify how the trigger should align with the tooltip
|
|
113
113
|
*/
|
|
114
|
-
align: PropTypes.Requireable<
|
|
114
|
+
align: PropTypes.Requireable<string> | PropTypes.Validator<string>;
|
|
115
115
|
/**
|
|
116
116
|
* Specify a label to be read by screen readers on the containing textbox
|
|
117
117
|
* node
|
|
@@ -50,7 +50,7 @@ declare namespace Copy {
|
|
|
50
50
|
/**
|
|
51
51
|
* Specify how the trigger should align with the tooltip
|
|
52
52
|
*/
|
|
53
|
-
align: PropTypes.Requireable<
|
|
53
|
+
align: PropTypes.Requireable<string> | PropTypes.Validator<string>;
|
|
54
54
|
/**
|
|
55
55
|
* **Experimental**: Will attempt to automatically align the tooltip. Requires
|
|
56
56
|
* React v17+
|
|
@@ -51,7 +51,7 @@ declare namespace CopyButton {
|
|
|
51
51
|
/**
|
|
52
52
|
* Specify how the trigger should align with the tooltip
|
|
53
53
|
*/
|
|
54
|
-
align: PropTypes.Requireable<
|
|
54
|
+
align: PropTypes.Requireable<string> | PropTypes.Validator<string>;
|
|
55
55
|
/**
|
|
56
56
|
* **Experimental**: Will attempt to automatically align the tooltip. Requires
|
|
57
57
|
* React v17+
|
|
@@ -282,11 +282,12 @@ export declare const DataTable: {
|
|
|
282
282
|
};
|
|
283
283
|
TableCell: React.ForwardRefExoticComponent<import("./TableCell").TableCellProps & React.RefAttributes<HTMLTableCellElement>>;
|
|
284
284
|
TableContainer: {
|
|
285
|
-
({ aiEnabled, className, children, title, description, stickyHeader, useStaticWidth, ...rest }: import("./TableContainer").TableContainerProps): import("react/jsx-runtime").JSX.Element;
|
|
285
|
+
({ aiEnabled, className, children, decorator, title, description, stickyHeader, useStaticWidth, ...rest }: import("./TableContainer").TableContainerProps): import("react/jsx-runtime").JSX.Element;
|
|
286
286
|
propTypes: {
|
|
287
287
|
aiEnabled: PropTypes.Requireable<boolean>;
|
|
288
288
|
children: PropTypes.Requireable<PropTypes.ReactNodeLike>;
|
|
289
289
|
className: PropTypes.Requireable<string>;
|
|
290
|
+
decorator: PropTypes.Requireable<PropTypes.ReactNodeLike>;
|
|
290
291
|
description: PropTypes.Requireable<PropTypes.ReactNodeLike>;
|
|
291
292
|
stickyHeader: PropTypes.Requireable<boolean>;
|
|
292
293
|
title: PropTypes.Requireable<PropTypes.ReactNodeLike>;
|