@carbon/react
Version:
React components for the Carbon Design System
180 lines (173 loc) • 5.49 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 keys = require('../../internal/keyboard/keys.js');
var match = require('../../internal/keyboard/match.js');
var useId = require('../../internal/useId.js');
var usePrefix = require('../../internal/usePrefix.js');
var deprecate = require('../../prop-types/deprecate.js');
var noopFn = require('../../internal/noopFn.js');
var Button = require('../Button/Button.js');
require('../Button/Button.Skeleton.js');
function FileUploaderButton({
accept,
buttonKind = 'primary',
className,
disabled = false,
disableLabelChanges = false,
id,
labelText: ownerLabelText = 'Add file',
multiple = false,
onChange = noopFn.noopFn,
name,
size = 'md',
innerRef,
...other
}) {
const prefix = usePrefix.usePrefix();
const [labelText, setLabelText] = React.useState(ownerLabelText);
const [prevOwnerLabelText, setPrevOwnerLabelText] = React.useState(ownerLabelText);
const generatedId = useId.useId();
const {
current: inputId
} = React.useRef(id || generatedId);
const inputNode = React.useRef(null);
const classes = cx(`${prefix}--btn`, className, {
[`${prefix}--btn--${buttonKind}`]: buttonKind,
[`${prefix}--btn--disabled`]: disabled,
// V11: remove field, small
[`${prefix}--btn--md`]: size === 'field' || size === 'md',
[`${prefix}--btn--sm`]: size === 'small' || size === 'sm',
[`${prefix}--layout--size-${size}`]: size
});
// Adjust label text state based on changes to the labelText prop
if (ownerLabelText !== prevOwnerLabelText) {
setLabelText(ownerLabelText);
setPrevOwnerLabelText(ownerLabelText);
}
function onClick(event) {
event.target.value = null;
if (inputNode.current) {
inputNode.current.value = '';
inputNode.current.click();
}
}
function onKeyDown(event) {
if (match.matches(event, [keys.Enter, keys.Space])) {
event.preventDefault();
if (inputNode.current) {
inputNode.current.value = '';
inputNode.current.click();
}
}
}
function handleOnChange(event) {
const files = event.target.files;
const length = event.target.files?.length || 0;
if (files && !disableLabelChanges) {
if (length > 1) {
setLabelText(`${length} files`);
} else if (length === 1) {
setLabelText(files[0].name);
}
}
onChange(event);
}
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", _rollupPluginBabelHelpers.extends({
type: "button",
disabled: disabled,
className: classes,
onClick: onClick,
onKeyDown: onKeyDown
}, other, {
tabIndex: other.tabIndex !== undefined ? parseInt(other.tabIndex) : undefined
}), labelText), /*#__PURE__*/React.createElement("label", {
className: `${prefix}--visually-hidden`,
ref: innerRef,
htmlFor: inputId
}, /*#__PURE__*/React.createElement("span", null, labelText)), /*#__PURE__*/React.createElement("input", {
className: `${prefix}--visually-hidden`,
ref: inputNode,
id: inputId,
disabled: disabled,
type: "file",
tabIndex: -1,
multiple: multiple,
accept: accept?.toString(),
name: name,
onChange: handleOnChange
}));
}
FileUploaderButton.propTypes = {
/**
* Specify the types of files that this input should be able to receive
*/
accept: PropTypes.arrayOf(PropTypes.string),
/**
* Specify the type of underlying button
*/
buttonKind: PropTypes.oneOf(Button.ButtonKinds),
/**
* Provide a custom className to be applied to the container node
*/
className: PropTypes.string,
/**
* Specify whether you want to disable any updates to the FileUploaderButton
* label
*/
disableLabelChanges: PropTypes.bool,
/**
* Specify whether file input is disabled
*/
disabled: PropTypes.bool,
/**
* Provide a unique id for the underlying `<input>` node
*/
id: PropTypes.string,
/**
* Provide the label text to be read by screen readers when interacting with
* this control
*/
labelText: PropTypes.node,
/**
* Specify if the component should accept multiple files to upload
*/
multiple: PropTypes.bool,
/**
* Provide a name for the underlying `<input>` node
*/
name: PropTypes.string,
/**
* Provide an optional `onChange` hook that is called each time the `<input>`
* value changes
*/
onChange: PropTypes.func,
/**
* Provide an optional `onClick` hook that is called each time the button is
* clicked
*/
onClick: PropTypes.func,
/**
* Provide an accessibility role for the `<FileUploaderButton>`
*/
role: PropTypes.string,
/**
* Specify the size of the FileUploaderButton, from a list of available
* sizes.
*/
size: PropTypes.oneOf(['sm', 'md', 'lg']),
/**
* Provide a custom tabIndex value for the `<FileUploaderButton>`
*/
tabIndex: deprecate.deprecate(PropTypes.number, 'The `tabIndex` prop for `FileUploaderButton` has ' + 'been deprecated since it now renders a button element by default.')
};
exports.default = FileUploaderButton;