@carbon/react
Version:
React components for the Carbon Design System
224 lines (216 loc) • 7.41 kB
JavaScript
/**
* Copyright IBM Corp. 2016, 2023
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js');
var cx = require('classnames');
var PropTypes = require('prop-types');
var React = require('react');
var Filename = require('./Filename.js');
var FileUploaderButton = require('./FileUploaderButton.js');
var Button = require('../Button/Button.js');
var keys = require('../../internal/keyboard/keys.js');
var match = require('../../internal/keyboard/match.js');
var usePrefix = require('../../internal/usePrefix.js');
require('../Text/index.js');
var useId = require('../../internal/useId.js');
var Text = require('../Text/Text.js');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var cx__default = /*#__PURE__*/_interopDefaultLegacy(cx);
var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes);
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
const FileUploader = /*#__PURE__*/React__default["default"].forwardRef(({
accept,
buttonKind,
buttonLabel,
className,
disabled,
filenameStatus,
iconDescription,
labelDescription,
labelTitle,
multiple,
name,
onChange,
onClick,
onDelete,
size,
...other
}, ref) => {
const fileUploaderInstanceId = useId.useId('file-uploader');
const [state, updateState] = React.useState({
fileNames: []
});
const nodes = [];
const prefix = usePrefix.usePrefix();
const handleChange = evt => {
evt.stopPropagation();
const filenames = Array.prototype.map.call(evt.target.files, file => file.name);
updateState(prevState => ({
fileNames: multiple ? [...new Set([...prevState.fileNames, ...filenames])] : filenames
}));
if (onChange) {
onChange(evt);
}
};
const handleClick = (evt, {
index,
filenameStatus
}) => {
if (filenameStatus === 'edit') {
evt.stopPropagation();
const filteredArray = state.fileNames.filter(filename => filename !== nodes[index]?.innerText?.trim());
updateState({
fileNames: filteredArray
});
if (onDelete) {
onDelete(evt);
uploaderButton.current?.focus?.();
}
onClick?.(evt);
}
};
React.useImperativeHandle(ref, () => ({
clearFiles() {
updateState({
fileNames: []
});
}
}));
const uploaderButton = /*#__PURE__*/React__default["default"].createRef();
const classes = cx__default["default"]({
[`${prefix}--form-item`]: true,
[className]: className
});
const getHelperLabelClasses = baseClass => cx__default["default"](baseClass, {
[`${prefix}--label-description--disabled`]: disabled
});
const selectedFileClasses = cx__default["default"](`${prefix}--file__selected-file`, {
[`${prefix}--file__selected-file--md`]: size === 'field' || size === 'md',
[`${prefix}--file__selected-file--sm`]: size === 'small' || size === 'sm'
});
return /*#__PURE__*/React__default["default"].createElement("div", _rollupPluginBabelHelpers["extends"]({
className: classes
}, other), !labelTitle ? null : /*#__PURE__*/React__default["default"].createElement(Text.Text, {
as: "h3",
className: getHelperLabelClasses(`${prefix}--file--label`)
}, labelTitle), /*#__PURE__*/React__default["default"].createElement(Text.Text, {
as: "p",
className: getHelperLabelClasses(`${prefix}--label-description`),
id: fileUploaderInstanceId
}, labelDescription), /*#__PURE__*/React__default["default"].createElement(FileUploaderButton["default"], {
innerRef: uploaderButton,
disabled: disabled,
labelText: buttonLabel,
multiple: multiple,
buttonKind: buttonKind,
onChange: handleChange,
disableLabelChanges: true,
accept: accept,
name: name,
size: size,
"aria-describedby": fileUploaderInstanceId
}), /*#__PURE__*/React__default["default"].createElement("div", {
className: `${prefix}--file-container`
}, state.fileNames.length === 0 ? null : state.fileNames.map((name, index) => /*#__PURE__*/React__default["default"].createElement("span", _rollupPluginBabelHelpers["extends"]({
key: index,
className: selectedFileClasses,
ref: node => {
nodes[index] = node;
} // eslint-disable-line
}, other), /*#__PURE__*/React__default["default"].createElement(Text.Text, {
as: "p",
className: `${prefix}--file-filename`,
id: name
}, name), /*#__PURE__*/React__default["default"].createElement("span", {
className: `${prefix}--file__state-container`
}, /*#__PURE__*/React__default["default"].createElement(Filename["default"], {
name: name,
iconDescription: iconDescription,
status: filenameStatus,
onKeyDown: evt => {
if (match.matches(evt, [keys.Enter, keys.Space])) {
handleClick(evt, {
index,
filenameStatus
});
}
},
onClick: evt => handleClick(evt, {
index,
filenameStatus
})
}))))));
});
FileUploader.propTypes = {
/**
* Specify the types of files that this input should be able to receive
*/
accept: PropTypes__default["default"].arrayOf(PropTypes__default["default"].string),
/**
* Specify the type of the `<FileUploaderButton>`
*/
buttonKind: PropTypes__default["default"].oneOf(Button.ButtonKinds),
/**
* Provide the label text to be read by screen readers when interacting with
* the `<FileUploaderButton>`
*/
buttonLabel: PropTypes__default["default"].string,
/**
* Provide a custom className to be applied to the container node
*/
className: PropTypes__default["default"].string,
/**
* Specify whether file input is disabled
*/
disabled: PropTypes__default["default"].bool,
/**
* Specify the status of the File Upload
*/
filenameStatus: PropTypes__default["default"].oneOf(['edit', 'complete', 'uploading']).isRequired,
/**
* Provide a description for the complete/close icon that can be read by screen readers
*/
iconDescription: PropTypes__default["default"].string,
/**
* Specify the description text of this `<FileUploader>`
*/
labelDescription: PropTypes__default["default"].string,
/**
* Specify the title text of this `<FileUploader>`
*/
labelTitle: PropTypes__default["default"].string,
/**
* Specify if the component should accept multiple files to upload
*/
multiple: PropTypes__default["default"].bool,
/**
* Provide a name for the underlying `<input>` node
*/
name: PropTypes__default["default"].string,
/**
* Provide an optional `onChange` hook that is called each time the input is
* changed
*/
onChange: PropTypes__default["default"].func,
/**
* Provide an optional `onClick` hook that is called each time the
* FileUploader is clicked
*/
onClick: PropTypes__default["default"].func,
/**
* Provide an optional `onDelete` hook that is called when an uploaded item
* is removed
*/
onDelete: PropTypes__default["default"].func,
/**
* Specify the size of the FileUploaderButton, from a list of available
* sizes.
*/
size: PropTypes__default["default"].oneOf(['sm', 'md', 'lg'])
};
exports["default"] = FileUploader;