@carbon/react 1.97.0-rc.0 → 1.98.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 +1010 -975
- 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/ComposedModal/ComposedModal.js +3 -2
- 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/DataTableSkeleton/DataTableSkeleton.d.ts +1 -1
- package/es/components/DataTableSkeleton/DataTableSkeleton.js +1 -1
- 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 +9 -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/Menu/index.d.ts +4 -3
- package/es/components/Modal/Modal.js +3 -2
- package/es/components/Notification/Notification.js +3 -2
- package/es/components/Pagination/Pagination.js +5 -5
- package/es/components/Popover/index.js +2 -2
- package/es/components/Select/Select.js +27 -33
- 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 +8 -6
- package/es/internal/OptimizedResize.js +4 -5
- package/es/internal/wrapFocus.d.ts +4 -2
- package/es/internal/wrapFocus.js +5 -4
- 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/ComposedModal/ComposedModal.js +3 -2
- 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/DataTableSkeleton/DataTableSkeleton.d.ts +1 -1
- package/lib/components/DataTableSkeleton/DataTableSkeleton.js +1 -1
- 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 +9 -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/Menu/index.d.ts +4 -3
- package/lib/components/Modal/Modal.js +3 -2
- package/lib/components/Notification/Notification.js +3 -2
- package/lib/components/Pagination/Pagination.js +5 -5
- package/lib/components/Popover/index.js +2 -2
- package/lib/components/Select/Select.js +27 -33
- 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 +8 -6
- package/lib/internal/OptimizedResize.js +4 -5
- package/lib/internal/wrapFocus.d.ts +4 -2
- package/lib/internal/wrapFocus.js +5 -4
- package/lib/tools/events.d.ts +1 -1
- package/package.json +20 -27
- package/telemetry.yml +2 -0
|
@@ -8,7 +8,9 @@ import React, { type HTMLAttributes } from 'react';
|
|
|
8
8
|
interface FileItem {
|
|
9
9
|
name: string;
|
|
10
10
|
uuid: string;
|
|
11
|
-
file: File
|
|
11
|
+
file: File & {
|
|
12
|
+
invalidFileType?: boolean;
|
|
13
|
+
};
|
|
12
14
|
}
|
|
13
15
|
export interface FileChangeData {
|
|
14
16
|
addedFiles: FileItem[];
|
|
@@ -58,6 +60,10 @@ export interface FileUploaderProps extends HTMLAttributes<HTMLSpanElement> {
|
|
|
58
60
|
* Specify the title text of this `<FileUploader>`
|
|
59
61
|
*/
|
|
60
62
|
labelTitle?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Maximum file size allowed in bytes. Files larger than this will be marked invalid
|
|
65
|
+
*/
|
|
66
|
+
maxFileSize?: number;
|
|
61
67
|
/**
|
|
62
68
|
* Specify if the component should accept multiple files to upload
|
|
63
69
|
*/
|
|
@@ -66,24 +72,32 @@ export interface FileUploaderProps extends HTMLAttributes<HTMLSpanElement> {
|
|
|
66
72
|
* Provide a name for the underlying `<input>` node
|
|
67
73
|
*/
|
|
68
74
|
name?: string;
|
|
75
|
+
/**
|
|
76
|
+
* Event handler that is called after files are added to the uploader
|
|
77
|
+
*/
|
|
78
|
+
onAddFiles?: (event: React.SyntheticEvent<HTMLElement>, content: {
|
|
79
|
+
addedFiles: Array<File & {
|
|
80
|
+
invalidFileType?: boolean;
|
|
81
|
+
}>;
|
|
82
|
+
}) => void;
|
|
69
83
|
/**
|
|
70
84
|
* Provide an optional `onChange` hook that is called each time the input is changed.
|
|
71
85
|
* When 'enable-enhanced-file-uploader' feature flag is enabled:
|
|
72
86
|
* - Also fires for file deletions and clearFiles operations
|
|
73
87
|
* - Event includes enhanced file information in event.target
|
|
74
88
|
*/
|
|
75
|
-
onChange?: (event:
|
|
89
|
+
onChange?: (event: React.SyntheticEvent<HTMLElement>, data?: FileChangeData) => void;
|
|
76
90
|
/**
|
|
77
91
|
* Provide an optional `onClick` hook that is called each time the
|
|
78
92
|
* FileUploader is clicked
|
|
79
93
|
*/
|
|
80
|
-
onClick?: (event:
|
|
94
|
+
onClick?: (event: React.SyntheticEvent<HTMLElement>) => void;
|
|
81
95
|
/**
|
|
82
96
|
* Provide an optional `onDelete` hook that is called when an uploaded item is removed.
|
|
83
97
|
* When 'enable-enhanced-file-uploader' feature flag is enabled:
|
|
84
98
|
* - Event includes deleted file information in event.target
|
|
85
99
|
*/
|
|
86
|
-
onDelete?: (event:
|
|
100
|
+
onDelete?: (event: React.SyntheticEvent<HTMLElement>, data?: FileDeleteData) => void;
|
|
87
101
|
/**
|
|
88
102
|
* Specify the size of the FileUploaderButton, from a list of available
|
|
89
103
|
* sizes.
|
|
@@ -101,9 +115,10 @@ export interface FileUploaderHandle {
|
|
|
101
115
|
getCurrentFiles?: () => FileItem[];
|
|
102
116
|
}
|
|
103
117
|
declare const FileUploader: {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
118
|
+
(props: FileUploaderProps): React.ReactElement;
|
|
119
|
+
displayName?: string;
|
|
120
|
+
propTypes?: unknown;
|
|
121
|
+
contextTypes?: unknown;
|
|
122
|
+
defaultProps?: unknown;
|
|
108
123
|
};
|
|
109
124
|
export default FileUploader;
|
|
@@ -24,7 +24,6 @@ require('../Text/TextDirection.js');
|
|
|
24
24
|
var useId = require('../../internal/useId.js');
|
|
25
25
|
var index = require('../FeatureFlags/index.js');
|
|
26
26
|
|
|
27
|
-
// eslint-disable-next-line react/display-name -- https://github.com/carbon-design-system/carbon/issues/20452
|
|
28
27
|
const FileUploader = /*#__PURE__*/React.forwardRef(({
|
|
29
28
|
accept,
|
|
30
29
|
buttonKind,
|
|
@@ -35,8 +34,10 @@ const FileUploader = /*#__PURE__*/React.forwardRef(({
|
|
|
35
34
|
iconDescription,
|
|
36
35
|
labelDescription,
|
|
37
36
|
labelTitle,
|
|
37
|
+
maxFileSize,
|
|
38
38
|
multiple,
|
|
39
39
|
name,
|
|
40
|
+
onAddFiles,
|
|
40
41
|
onChange,
|
|
41
42
|
onClick,
|
|
42
43
|
onDelete,
|
|
@@ -48,20 +49,51 @@ const FileUploader = /*#__PURE__*/React.forwardRef(({
|
|
|
48
49
|
const enhancedFileUploaderEnabled = index.useFeatureFlag('enable-enhanced-file-uploader');
|
|
49
50
|
const [fileItems, setFileItems] = React.useState([]);
|
|
50
51
|
const [legacyFileNames, setLegacyFileNames] = React.useState([]);
|
|
51
|
-
|
|
52
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- https://github.com/carbon-design-system/carbon/issues/20452
|
|
53
|
-
const [fileObjects, setFileObjects] = React.useState(new Map());
|
|
52
|
+
const uploaderButton = /*#__PURE__*/React.createRef();
|
|
54
53
|
const nodes = [];
|
|
55
|
-
const createFileItem = file => ({
|
|
54
|
+
const createFileItem = React.useCallback(file => ({
|
|
56
55
|
name: file.name,
|
|
57
56
|
uuid: `${fileUploaderInstanceId}-${Date.now()}-${Array.from(crypto.getRandomValues(new Uint8Array(8))).map(b => b.toString(36)).join('')}`,
|
|
58
57
|
file
|
|
59
|
-
});
|
|
58
|
+
}), [fileUploaderInstanceId]);
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Validates files based on file size restrictions.
|
|
62
|
+
* Marks invalid files with `invalidFileType: true` but includes them in the result.
|
|
63
|
+
*
|
|
64
|
+
* Note: The `accept` prop is passed to the native HTML input element (`FileUploaderButton`),
|
|
65
|
+
* which provides UI-level filtering in the file picker dialog, but there is no JavaScript validation
|
|
66
|
+
* for file types - users can bypass this by changing the file type filter in the dialog.
|
|
67
|
+
* https://github.com/carbon-design-system/carbon/issues/21166
|
|
68
|
+
*/
|
|
69
|
+
const validateFiles = React.useCallback(files => {
|
|
70
|
+
return files.map(file => {
|
|
71
|
+
if (maxFileSize && file.size > maxFileSize) {
|
|
72
|
+
file.invalidFileType = true;
|
|
73
|
+
}
|
|
74
|
+
return file;
|
|
75
|
+
});
|
|
76
|
+
}, [maxFileSize]);
|
|
60
77
|
const handleChange = React.useCallback(evt => {
|
|
61
78
|
evt.stopPropagation();
|
|
62
|
-
const
|
|
79
|
+
const incomingFiles = Array.from(evt.target.files);
|
|
80
|
+
const filesToValidate = multiple ? incomingFiles : [incomingFiles[0]];
|
|
81
|
+
const validatedFiles = validateFiles(filesToValidate);
|
|
82
|
+
if (onAddFiles) {
|
|
83
|
+
onAddFiles(evt, {
|
|
84
|
+
addedFiles: validatedFiles
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Filter out invalid files since FileUploader cannot display them
|
|
89
|
+
// (FileUploaderDropContainer returns all files because parent uses FileUploaderItem to display errors)
|
|
90
|
+
// https://github.com/carbon-design-system/carbon/issues/21166
|
|
91
|
+
const validFiles = validatedFiles.filter(file => !file.invalidFileType);
|
|
92
|
+
if (validFiles.length === 0) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
63
95
|
if (enhancedFileUploaderEnabled) {
|
|
64
|
-
const newFileItems =
|
|
96
|
+
const newFileItems = validFiles.map(createFileItem);
|
|
65
97
|
let updatedFileItems;
|
|
66
98
|
if (multiple) {
|
|
67
99
|
const existingNames = new Set(fileItems.map(item => item.name));
|
|
@@ -88,23 +120,14 @@ const FileUploader = /*#__PURE__*/React.forwardRef(({
|
|
|
88
120
|
onChange(enhancedEvent);
|
|
89
121
|
}
|
|
90
122
|
} else {
|
|
91
|
-
const filenames =
|
|
123
|
+
const filenames = validFiles.map(file => file.name);
|
|
92
124
|
const updatedFileNames = multiple ? [...new Set([...legacyFileNames, ...filenames])] : filenames;
|
|
93
125
|
setLegacyFileNames(updatedFileNames);
|
|
94
|
-
setFileObjects(prevMap => {
|
|
95
|
-
const newMap = multiple ? new Map(prevMap) : new Map();
|
|
96
|
-
newFiles.forEach(file => {
|
|
97
|
-
newMap.set(file.name, file);
|
|
98
|
-
});
|
|
99
|
-
return newMap;
|
|
100
|
-
});
|
|
101
126
|
if (onChange) {
|
|
102
127
|
onChange(evt);
|
|
103
128
|
}
|
|
104
129
|
}
|
|
105
|
-
},
|
|
106
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps -- https://github.com/carbon-design-system/carbon/issues/20452
|
|
107
|
-
[enhancedFileUploaderEnabled, fileItems, legacyFileNames, multiple, onChange]);
|
|
130
|
+
}, [enhancedFileUploaderEnabled, fileItems, legacyFileNames, multiple, onAddFiles, onChange, createFileItem, validateFiles]);
|
|
108
131
|
const handleClick = React.useCallback((evt, {
|
|
109
132
|
index,
|
|
110
133
|
filenameStatus
|
|
@@ -141,15 +164,6 @@ const FileUploader = /*#__PURE__*/React.forwardRef(({
|
|
|
141
164
|
const deletedFileName = legacyFileNames[index];
|
|
142
165
|
const filteredArray = legacyFileNames.filter(filename => filename !== deletedFileName);
|
|
143
166
|
setLegacyFileNames(filteredArray);
|
|
144
|
-
|
|
145
|
-
// Update File objects
|
|
146
|
-
setFileObjects(prevMap => {
|
|
147
|
-
const newMap = new Map(prevMap);
|
|
148
|
-
if (deletedFileName) {
|
|
149
|
-
newMap.delete(deletedFileName);
|
|
150
|
-
}
|
|
151
|
-
return newMap;
|
|
152
|
-
});
|
|
153
167
|
if (onDelete) {
|
|
154
168
|
onDelete(evt);
|
|
155
169
|
}
|
|
@@ -159,9 +173,7 @@ const FileUploader = /*#__PURE__*/React.forwardRef(({
|
|
|
159
173
|
}
|
|
160
174
|
uploaderButton.current?.focus?.();
|
|
161
175
|
}
|
|
162
|
-
},
|
|
163
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps -- https://github.com/carbon-design-system/carbon/issues/20452
|
|
164
|
-
[enhancedFileUploaderEnabled, fileItems, legacyFileNames, onDelete, onChange, onClick]);
|
|
176
|
+
}, [enhancedFileUploaderEnabled, fileItems, legacyFileNames, onDelete, onChange, onClick, uploaderButton]);
|
|
165
177
|
React.useImperativeHandle(ref, () => ({
|
|
166
178
|
clearFiles() {
|
|
167
179
|
if (enhancedFileUploaderEnabled) {
|
|
@@ -184,7 +196,6 @@ const FileUploader = /*#__PURE__*/React.forwardRef(({
|
|
|
184
196
|
}
|
|
185
197
|
} else {
|
|
186
198
|
setLegacyFileNames([]);
|
|
187
|
-
setFileObjects(new Map());
|
|
188
199
|
}
|
|
189
200
|
},
|
|
190
201
|
...(enhancedFileUploaderEnabled && {
|
|
@@ -193,7 +204,6 @@ const FileUploader = /*#__PURE__*/React.forwardRef(({
|
|
|
193
204
|
}
|
|
194
205
|
})
|
|
195
206
|
}), [enhancedFileUploaderEnabled, fileItems, onChange]);
|
|
196
|
-
const uploaderButton = /*#__PURE__*/React.createRef();
|
|
197
207
|
const classes = cx({
|
|
198
208
|
[`${prefix}--form-item`]: true,
|
|
199
209
|
[className]: className
|
|
@@ -267,6 +277,7 @@ const FileUploader = /*#__PURE__*/React.forwardRef(({
|
|
|
267
277
|
})
|
|
268
278
|
}))))));
|
|
269
279
|
});
|
|
280
|
+
FileUploader.displayName = 'FileUploader';
|
|
270
281
|
FileUploader.propTypes = {
|
|
271
282
|
/**
|
|
272
283
|
* Specify the types of files that this input should be able to receive
|
|
@@ -305,6 +316,10 @@ FileUploader.propTypes = {
|
|
|
305
316
|
* Specify the title text of this `<FileUploader>`
|
|
306
317
|
*/
|
|
307
318
|
labelTitle: PropTypes.string,
|
|
319
|
+
/**
|
|
320
|
+
* Maximum file size allowed in bytes. Files larger than this will be marked invalid
|
|
321
|
+
*/
|
|
322
|
+
maxFileSize: PropTypes.number,
|
|
308
323
|
/**
|
|
309
324
|
* Specify if the component should accept multiple files to upload
|
|
310
325
|
*/
|
|
@@ -313,6 +328,11 @@ FileUploader.propTypes = {
|
|
|
313
328
|
* Provide a name for the underlying `<input>` node
|
|
314
329
|
*/
|
|
315
330
|
name: PropTypes.string,
|
|
331
|
+
/**
|
|
332
|
+
* Event handler that is called after files are added to the uploader
|
|
333
|
+
* The event handler signature looks like `onAddFiles(evt, { addedFiles })`
|
|
334
|
+
*/
|
|
335
|
+
onAddFiles: PropTypes.func,
|
|
316
336
|
/**
|
|
317
337
|
* Provide an optional `onChange` hook that is called each time the input is
|
|
318
338
|
* changed
|
|
@@ -40,10 +40,10 @@ function FileUploaderButton({
|
|
|
40
40
|
const prefix = usePrefix.usePrefix();
|
|
41
41
|
const [labelText, setLabelText] = React.useState(ownerLabelText);
|
|
42
42
|
const [prevOwnerLabelText, setPrevOwnerLabelText] = React.useState(ownerLabelText);
|
|
43
|
-
|
|
43
|
+
const generatedId = useId.useId();
|
|
44
44
|
const {
|
|
45
45
|
current: inputId
|
|
46
|
-
} = React.useRef(id ||
|
|
46
|
+
} = React.useRef(id || generatedId);
|
|
47
47
|
const inputNode = React.useRef(null);
|
|
48
48
|
const classes = cx(`${prefix}--btn`, className, {
|
|
49
49
|
[`${prefix}--btn--${buttonKind}`]: buttonKind,
|
|
@@ -28,6 +28,10 @@ export interface FileUploaderDropContainerProps extends Omit<HTMLAttributes<HTML
|
|
|
28
28
|
* this control
|
|
29
29
|
*/
|
|
30
30
|
labelText?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Maximum file size allowed in bytes. Files larger than this will be marked invalid
|
|
33
|
+
*/
|
|
34
|
+
maxFileSize?: number;
|
|
31
35
|
/**
|
|
32
36
|
* Specify if the component should accept multiple files to upload
|
|
33
37
|
*/
|
|
@@ -40,7 +44,7 @@ export interface FileUploaderDropContainerProps extends Omit<HTMLAttributes<HTML
|
|
|
40
44
|
* Event handler that is called after files are added to the uploader
|
|
41
45
|
*/
|
|
42
46
|
onAddFiles?: (event: React.SyntheticEvent<HTMLElement>, content: {
|
|
43
|
-
addedFiles:
|
|
47
|
+
addedFiles: AddedFile[];
|
|
44
48
|
}) => void;
|
|
45
49
|
/**
|
|
46
50
|
* Provide an optional function to be called when the button element
|
|
@@ -64,7 +68,10 @@ export interface FileUploaderDropContainerProps extends Omit<HTMLAttributes<HTML
|
|
|
64
68
|
*/
|
|
65
69
|
tabIndex?: number | string;
|
|
66
70
|
}
|
|
67
|
-
|
|
71
|
+
interface AddedFile extends File {
|
|
72
|
+
invalidFileType?: boolean;
|
|
73
|
+
}
|
|
74
|
+
declare function FileUploaderDropContainer({ accept, className, id, disabled, labelText, maxFileSize, multiple, name, onAddFiles, onClick, pattern, innerRef, ...rest }: FileUploaderDropContainerProps): import("react/jsx-runtime").JSX.Element;
|
|
68
75
|
declare namespace FileUploaderDropContainer {
|
|
69
76
|
var propTypes: {
|
|
70
77
|
/**
|
|
@@ -88,6 +95,10 @@ declare namespace FileUploaderDropContainer {
|
|
|
88
95
|
* this control
|
|
89
96
|
*/
|
|
90
97
|
labelText: PropTypes.Validator<string>;
|
|
98
|
+
/**
|
|
99
|
+
* Maximum file size allowed in bytes. Files larger than this will be marked invalid
|
|
100
|
+
*/
|
|
101
|
+
maxFileSize: PropTypes.Requireable<number>;
|
|
91
102
|
/**
|
|
92
103
|
* Specify if the component should accept multiple files to upload
|
|
93
104
|
*/
|
|
@@ -27,6 +27,7 @@ function FileUploaderDropContainer({
|
|
|
27
27
|
id,
|
|
28
28
|
disabled,
|
|
29
29
|
labelText = 'Add file',
|
|
30
|
+
maxFileSize,
|
|
30
31
|
multiple = false,
|
|
31
32
|
name,
|
|
32
33
|
onAddFiles = noopFn.noopFn,
|
|
@@ -37,10 +38,10 @@ function FileUploaderDropContainer({
|
|
|
37
38
|
}) {
|
|
38
39
|
const prefix = usePrefix.usePrefix();
|
|
39
40
|
const inputRef = React.useRef(null);
|
|
40
|
-
|
|
41
|
+
const generatedId = useId.useId();
|
|
41
42
|
const {
|
|
42
43
|
current: uid
|
|
43
|
-
} = React.useRef(id ||
|
|
44
|
+
} = React.useRef(id || generatedId);
|
|
44
45
|
const [isActive, setActive] = React.useState(false);
|
|
45
46
|
const dropareaClasses = cx(`${prefix}--file__drop-container`, `${prefix}--file-browse-btn`, {
|
|
46
47
|
[`${prefix}--file__drop-container--drag-over`]: isActive,
|
|
@@ -48,12 +49,9 @@ function FileUploaderDropContainer({
|
|
|
48
49
|
}, className);
|
|
49
50
|
|
|
50
51
|
/**
|
|
51
|
-
* Filters the array of added files based on file type restrictions
|
|
52
|
+
* Filters the array of added files based on file type and size restrictions
|
|
52
53
|
*/
|
|
53
54
|
function validateFiles(transferredFiles) {
|
|
54
|
-
if (!accept.length) {
|
|
55
|
-
return transferredFiles;
|
|
56
|
-
}
|
|
57
55
|
const acceptedTypes = new Set(accept);
|
|
58
56
|
return transferredFiles.reduce((acc, curr) => {
|
|
59
57
|
const {
|
|
@@ -62,6 +60,13 @@ function FileUploaderDropContainer({
|
|
|
62
60
|
} = curr;
|
|
63
61
|
const fileExtensionRegExp = new RegExp(pattern, 'i');
|
|
64
62
|
const [fileExtension] = name.match(fileExtensionRegExp) ?? [];
|
|
63
|
+
if (maxFileSize && curr.size > maxFileSize) {
|
|
64
|
+
curr.invalidFileType = true;
|
|
65
|
+
return acc.concat([curr]);
|
|
66
|
+
}
|
|
67
|
+
if (!accept.length) {
|
|
68
|
+
return acc.concat([curr]);
|
|
69
|
+
}
|
|
65
70
|
if (fileExtension === undefined) {
|
|
66
71
|
return acc;
|
|
67
72
|
}
|
|
@@ -174,6 +179,10 @@ FileUploaderDropContainer.propTypes = {
|
|
|
174
179
|
* this control
|
|
175
180
|
*/
|
|
176
181
|
labelText: PropTypes.string.isRequired,
|
|
182
|
+
/**
|
|
183
|
+
* Maximum file size allowed in bytes. Files larger than this will be marked invalid
|
|
184
|
+
*/
|
|
185
|
+
maxFileSize: PropTypes.number,
|
|
177
186
|
/**
|
|
178
187
|
* Specify if the component should accept multiple files to upload
|
|
179
188
|
*/
|
|
@@ -40,10 +40,10 @@ function FileUploaderItem({
|
|
|
40
40
|
const textRef = React.useRef(null);
|
|
41
41
|
const [isEllipsisApplied, setIsEllipsisApplied] = React.useState(false);
|
|
42
42
|
const prefix = usePrefix.usePrefix();
|
|
43
|
-
|
|
43
|
+
const generatedId = useId.useId();
|
|
44
44
|
const {
|
|
45
45
|
current: id
|
|
46
|
-
} = React.useRef(uuid ||
|
|
46
|
+
} = React.useRef(uuid || generatedId);
|
|
47
47
|
const classes = cx(`${prefix}--file__selected-file`, className, {
|
|
48
48
|
[`${prefix}--file__selected-file--invalid`]: invalid,
|
|
49
49
|
[`${prefix}--file__selected-file--md`]: size === 'md',
|
|
@@ -53,11 +53,14 @@ function FileUploaderItem({
|
|
|
53
53
|
const filterSpaceName = name => {
|
|
54
54
|
return name?.replace(/\s+/g, '');
|
|
55
55
|
};
|
|
56
|
-
|
|
57
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20452
|
|
58
56
|
const isEllipsisActive = element => {
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
if (!element) {
|
|
58
|
+
setIsEllipsisApplied(false);
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
const isActive = element.offsetWidth < element.scrollWidth;
|
|
62
|
+
setIsEllipsisApplied(isActive);
|
|
63
|
+
return isActive;
|
|
61
64
|
};
|
|
62
65
|
React.useLayoutEffect(() => {
|
|
63
66
|
isEllipsisActive(textRef.current);
|
|
@@ -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 { Menu } from './Menu';
|
|
8
|
-
import { MenuItem, MenuItemDivider, MenuItemGroup, MenuItemRadioGroup, MenuItemSelectable } from './MenuItem';
|
|
9
|
-
export { Menu, MenuItem, MenuItemDivider, MenuItemGroup, MenuItemRadioGroup, MenuItemSelectable, };
|
|
7
|
+
import { Menu, type MenuProps } from './Menu';
|
|
8
|
+
import { MenuItem, MenuItemDivider, MenuItemGroup, MenuItemRadioGroup, MenuItemSelectable, type MenuItemProps, type MenuItemDividerProps, type MenuItemGroupProps, type MenuItemRadioGroupProps, type MenuItemSelectableProps } from './MenuItem';
|
|
9
|
+
export { Menu, MenuItem, MenuItemDivider, MenuItemGroup, MenuItemRadioGroup, MenuItemSelectable, type MenuProps, type MenuItemProps, type MenuItemDividerProps, type MenuItemGroupProps, type MenuItemRadioGroupProps, type MenuItemSelectableProps, };
|
|
10
|
+
export default Menu;
|
|
@@ -171,7 +171,7 @@ const ModalDialog = /*#__PURE__*/React.forwardRef(function ModalDialog({
|
|
|
171
171
|
// behavior by explicitly setting preventCloseOnClickOutside to false,
|
|
172
172
|
// rather than just leaving it undefined.
|
|
173
173
|
!passiveModal && preventCloseOnClickOutside === false;
|
|
174
|
-
if (shouldCloseOnOutsideClick && target instanceof Node && !wrapFocus.elementOrParentIsFloatingMenu(target, selectorsFloatingMenus) && innerModal.current && !innerModal.current.contains(target)) {
|
|
174
|
+
if (shouldCloseOnOutsideClick && target instanceof Node && !wrapFocus.elementOrParentIsFloatingMenu(target, selectorsFloatingMenus, prefix) && innerModal.current && !innerModal.current.contains(target)) {
|
|
175
175
|
onRequestClose(evt);
|
|
176
176
|
}
|
|
177
177
|
}
|
|
@@ -198,7 +198,8 @@ const ModalDialog = /*#__PURE__*/React.forwardRef(function ModalDialog({
|
|
|
198
198
|
endTrapNode,
|
|
199
199
|
currentActiveNode,
|
|
200
200
|
oldActiveNode,
|
|
201
|
-
selectorsFloatingMenus
|
|
201
|
+
selectorsFloatingMenus,
|
|
202
|
+
prefix
|
|
202
203
|
});
|
|
203
204
|
if (wrapFocusTimeout.current) {
|
|
204
205
|
clearTimeout(wrapFocusTimeout.current);
|
|
@@ -511,7 +511,7 @@ function ActionableNotification({
|
|
|
511
511
|
const focusTrapWithoutSentinels = focusTrapWithoutSentinelsFlag || deprecatedFlag;
|
|
512
512
|
useIsomorphicEffect.default(() => {
|
|
513
513
|
if (hasFocus && role === 'alertdialog') {
|
|
514
|
-
const button = document.querySelector(
|
|
514
|
+
const button = document.querySelector(`button.${prefix}--actionable-notification__action-button`);
|
|
515
515
|
button?.focus();
|
|
516
516
|
}
|
|
517
517
|
});
|
|
@@ -534,7 +534,8 @@ function ActionableNotification({
|
|
|
534
534
|
startTrapNode,
|
|
535
535
|
endTrapNode,
|
|
536
536
|
currentActiveNode,
|
|
537
|
-
oldActiveNode
|
|
537
|
+
oldActiveNode,
|
|
538
|
+
prefix
|
|
538
539
|
});
|
|
539
540
|
}
|
|
540
541
|
}
|
|
@@ -11,16 +11,16 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
11
11
|
|
|
12
12
|
var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js');
|
|
13
13
|
var iconsReact = require('@carbon/icons-react');
|
|
14
|
-
var cx = require('classnames');
|
|
15
|
-
var PropTypes = require('prop-types');
|
|
16
14
|
var React = require('react');
|
|
15
|
+
var index = require('../IconButton/index.js');
|
|
16
|
+
var PropTypes = require('prop-types');
|
|
17
17
|
var Select = require('../Select/Select.js');
|
|
18
18
|
require('../Select/Select.Skeleton.js');
|
|
19
19
|
var SelectItem = require('../SelectItem/SelectItem.js');
|
|
20
|
+
var cx = require('classnames');
|
|
21
|
+
var isEqual = require('react-fast-compare');
|
|
20
22
|
var useId = require('../../internal/useId.js');
|
|
21
23
|
var usePrefix = require('../../internal/usePrefix.js');
|
|
22
|
-
var index = require('../IconButton/index.js');
|
|
23
|
-
var isEqual = require('react-fast-compare');
|
|
24
24
|
|
|
25
25
|
var _CaretLeft, _CaretRight;
|
|
26
26
|
function mapPageSizesToObject(sizes) {
|
|
@@ -270,7 +270,7 @@ const Pagination = /*#__PURE__*/React.forwardRef(({
|
|
|
270
270
|
onClick: decrementPage,
|
|
271
271
|
ref: backBtnRef
|
|
272
272
|
}, _CaretLeft || (_CaretLeft = /*#__PURE__*/React.createElement(iconsReact.CaretLeft, null))), /*#__PURE__*/React.createElement(index.IconButton, {
|
|
273
|
-
align: "top
|
|
273
|
+
align: "top",
|
|
274
274
|
disabled: forwardButtonDisabled || isLastPage,
|
|
275
275
|
kind: "ghost",
|
|
276
276
|
className: forwardButtonClasses,
|
|
@@ -118,8 +118,8 @@ forwardRef) {
|
|
|
118
118
|
// If a value is not set via a custom property, provide a default value that matches the
|
|
119
119
|
// default values defined in the sass style file
|
|
120
120
|
const getStyle = window.getComputedStyle(popover.current, null);
|
|
121
|
-
const offsetProperty = getStyle.getPropertyValue(
|
|
122
|
-
const caretProperty = getStyle.getPropertyValue(
|
|
121
|
+
const offsetProperty = getStyle.getPropertyValue(`--${prefix}-popover-offset`);
|
|
122
|
+
const caretProperty = getStyle.getPropertyValue(`--${prefix}-popover-caret-height`);
|
|
123
123
|
|
|
124
124
|
// Handle if the property values are in px or rem.
|
|
125
125
|
// We want to store just the base number value without a unit suffix
|
|
@@ -18,12 +18,12 @@ var deprecate = require('../../prop-types/deprecate.js');
|
|
|
18
18
|
var usePrefix = require('../../internal/usePrefix.js');
|
|
19
19
|
require('../FluidForm/FluidForm.js');
|
|
20
20
|
var FormContext = require('../FluidForm/FormContext.js');
|
|
21
|
-
var useId = require('../../internal/useId.js');
|
|
22
21
|
var events = require('../../tools/events.js');
|
|
23
22
|
var Text = require('../Text/Text.js');
|
|
24
23
|
require('../Text/TextDirection.js');
|
|
25
24
|
var index = require('../AILabel/index.js');
|
|
26
25
|
var utils = require('../../internal/utils.js');
|
|
26
|
+
var useNormalizedInputProps = require('../../internal/useNormalizedInputProps.js');
|
|
27
27
|
|
|
28
28
|
const Select = /*#__PURE__*/React.forwardRef(({
|
|
29
29
|
className,
|
|
@@ -53,7 +53,6 @@ const Select = /*#__PURE__*/React.forwardRef(({
|
|
|
53
53
|
isFluid
|
|
54
54
|
} = React.useContext(FormContext.FormContext);
|
|
55
55
|
const [isFocused, setIsFocused] = React.useState(false);
|
|
56
|
-
const selectInstanceId = useId.useId();
|
|
57
56
|
// Convert children to an array of valid elements once using type narrowing
|
|
58
57
|
const validChildren = React.Children.toArray(children).filter(child => /*#__PURE__*/React.isValidElement(child));
|
|
59
58
|
|
|
@@ -65,55 +64,50 @@ const Select = /*#__PURE__*/React.forwardRef(({
|
|
|
65
64
|
// otherwise, fallback to the first option's text
|
|
66
65
|
const initialTitle = other?.title || selectedOption?.props?.text || validChildren[0]?.props?.text || '';
|
|
67
66
|
const [title, setTitle] = React.useState(initialTitle);
|
|
67
|
+
const normalizedProps = useNormalizedInputProps.useNormalizedInputProps({
|
|
68
|
+
id,
|
|
69
|
+
disabled,
|
|
70
|
+
readOnly,
|
|
71
|
+
invalid,
|
|
72
|
+
invalidText,
|
|
73
|
+
warn,
|
|
74
|
+
warnText
|
|
75
|
+
});
|
|
68
76
|
const selectClasses = cx({
|
|
69
77
|
[`${prefix}--select`]: true,
|
|
70
78
|
[`${prefix}--select--inline`]: inline,
|
|
71
79
|
[`${prefix}--select--light`]: light,
|
|
72
|
-
[`${prefix}--select--invalid`]: invalid,
|
|
73
|
-
[`${prefix}--select--disabled`]: disabled,
|
|
80
|
+
[`${prefix}--select--invalid`]: normalizedProps.invalid,
|
|
81
|
+
[`${prefix}--select--disabled`]: normalizedProps.disabled,
|
|
74
82
|
[`${prefix}--select--readonly`]: readOnly,
|
|
75
|
-
[`${prefix}--select--warning`]: warn,
|
|
76
|
-
[`${prefix}--select--fluid--invalid`]: isFluid && invalid,
|
|
83
|
+
[`${prefix}--select--warning`]: normalizedProps.warn,
|
|
84
|
+
[`${prefix}--select--fluid--invalid`]: isFluid && normalizedProps.invalid,
|
|
77
85
|
[`${prefix}--select--fluid--focus`]: isFluid && isFocused,
|
|
78
86
|
[`${prefix}--select--slug`]: slug,
|
|
79
87
|
[`${prefix}--select--decorator`]: decorator
|
|
80
88
|
});
|
|
81
89
|
const labelClasses = cx(`${prefix}--label`, {
|
|
82
90
|
[`${prefix}--visually-hidden`]: hideLabel,
|
|
83
|
-
[`${prefix}--label--disabled`]: disabled
|
|
91
|
+
[`${prefix}--label--disabled`]: normalizedProps.disabled
|
|
84
92
|
});
|
|
85
93
|
const inputClasses = cx({
|
|
86
94
|
[`${prefix}--select-input`]: true,
|
|
87
95
|
[`${prefix}--select-input--${size}`]: size
|
|
88
96
|
});
|
|
89
|
-
const
|
|
90
|
-
const errorText = (() => {
|
|
91
|
-
if (invalid) {
|
|
92
|
-
return invalidText;
|
|
93
|
-
}
|
|
94
|
-
if (warn) {
|
|
95
|
-
return warnText;
|
|
96
|
-
}
|
|
97
|
-
})();
|
|
98
|
-
const error = invalid || warn ? /*#__PURE__*/React.createElement(Text.Text, {
|
|
99
|
-
as: "div",
|
|
100
|
-
className: `${prefix}--form-requirement`,
|
|
101
|
-
id: errorId
|
|
102
|
-
}, errorText) : null;
|
|
97
|
+
const error = normalizedProps.validation;
|
|
103
98
|
const helperTextClasses = cx(`${prefix}--form__helper-text`, {
|
|
104
|
-
[`${prefix}--form__helper-text--disabled`]: disabled
|
|
99
|
+
[`${prefix}--form__helper-text--disabled`]: normalizedProps.disabled
|
|
105
100
|
});
|
|
106
|
-
const helperId = !helperText ? undefined : `select-helper-text-${selectInstanceId}`;
|
|
107
101
|
const helper = helperText ? /*#__PURE__*/React.createElement(Text.Text, {
|
|
108
102
|
as: "div",
|
|
109
|
-
id: helperId,
|
|
103
|
+
id: normalizedProps.helperId,
|
|
110
104
|
className: helperTextClasses
|
|
111
105
|
}, helperText) : null;
|
|
112
106
|
const ariaProps = {};
|
|
113
|
-
if (invalid) {
|
|
114
|
-
ariaProps['aria-describedby'] =
|
|
107
|
+
if (normalizedProps.invalid) {
|
|
108
|
+
ariaProps['aria-describedby'] = normalizedProps.invalidId;
|
|
115
109
|
} else if (!inline && !isFluid) {
|
|
116
|
-
ariaProps['aria-describedby'] = helper ? helperId : undefined;
|
|
110
|
+
ariaProps['aria-describedby'] = helper ? normalizedProps.helperId : undefined;
|
|
117
111
|
}
|
|
118
112
|
const handleFocus = evt => {
|
|
119
113
|
setIsFocused(evt.type === 'focus' ? true : false);
|
|
@@ -150,8 +144,8 @@ const Select = /*#__PURE__*/React.forwardRef(({
|
|
|
150
144
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("select", _rollupPluginBabelHelpers.extends({}, other, ariaProps, {
|
|
151
145
|
id: id,
|
|
152
146
|
className: inputClasses,
|
|
153
|
-
disabled: disabled || undefined,
|
|
154
|
-
"aria-invalid": invalid || undefined,
|
|
147
|
+
disabled: normalizedProps.disabled || undefined,
|
|
148
|
+
"aria-invalid": normalizedProps.invalid || undefined,
|
|
155
149
|
"aria-readonly": readOnly || undefined,
|
|
156
150
|
title: title,
|
|
157
151
|
onChange: events.composeEventHandlers([onChange, handleChange])
|
|
@@ -159,9 +153,9 @@ const Select = /*#__PURE__*/React.forwardRef(({
|
|
|
159
153
|
ref: ref
|
|
160
154
|
}), children), /*#__PURE__*/React.createElement(iconsReact.ChevronDown, {
|
|
161
155
|
className: `${prefix}--select__arrow`
|
|
162
|
-
}), invalid && /*#__PURE__*/React.createElement(iconsReact.WarningFilled, {
|
|
156
|
+
}), normalizedProps.invalid && /*#__PURE__*/React.createElement(iconsReact.WarningFilled, {
|
|
163
157
|
className: `${prefix}--select__invalid-icon`
|
|
164
|
-
}), !invalid && warn && /*#__PURE__*/React.createElement(iconsReact.WarningAltFilled, {
|
|
158
|
+
}), !normalizedProps.invalid && normalizedProps.warn && /*#__PURE__*/React.createElement(iconsReact.WarningAltFilled, {
|
|
165
159
|
className: `${prefix}--select__invalid-icon ${prefix}--select__invalid-icon--warning`
|
|
166
160
|
}));
|
|
167
161
|
})();
|
|
@@ -177,10 +171,10 @@ const Select = /*#__PURE__*/React.forwardRef(({
|
|
|
177
171
|
className: `${prefix}--select-input--inline__wrapper`
|
|
178
172
|
}, /*#__PURE__*/React.createElement("div", {
|
|
179
173
|
className: `${prefix}--select-input__wrapper`,
|
|
180
|
-
"data-invalid": invalid || null
|
|
174
|
+
"data-invalid": normalizedProps.invalid || null
|
|
181
175
|
}, input), error), !inline && /*#__PURE__*/React.createElement("div", {
|
|
182
176
|
className: `${prefix}--select-input__wrapper`,
|
|
183
|
-
"data-invalid": invalid || null,
|
|
177
|
+
"data-invalid": normalizedProps.invalid || null,
|
|
184
178
|
onFocus: handleFocus,
|
|
185
179
|
onBlur: handleFocus
|
|
186
180
|
}, input, slug ? normalizedDecorator : decorator ? /*#__PURE__*/React.createElement("div", {
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
'use strict';
|
|
9
9
|
|
|
10
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
11
|
+
|
|
10
12
|
var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js');
|
|
11
13
|
var cx = require('classnames');
|
|
12
14
|
var PropTypes = require('prop-types');
|
|
@@ -289,3 +291,4 @@ exports.ToggletipActions = ToggletipActions;
|
|
|
289
291
|
exports.ToggletipButton = ToggletipButton;
|
|
290
292
|
exports.ToggletipContent = ToggletipContent;
|
|
291
293
|
exports.ToggletipLabel = ToggletipLabel;
|
|
294
|
+
exports.default = Toggletip;
|
|
@@ -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;
|