UNPKG

@mskcc/carbon-react

Version:

Carbon react components for the MSKCC DSM

171 lines (166 loc) 5.19 kB
/** * MSKCC 2021, 2024 */ import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js'; import cx from 'classnames'; import PropTypes from 'prop-types'; import React__default, { useState, useRef } from 'react'; import uniqueId from '../../tools/uniqueId.js'; import { usePrefix } from '../../internal/usePrefix.js'; import deprecate from '../../prop-types/deprecate.js'; import { ButtonKinds } from '../Button/Button.js'; import '../Button/Button.Skeleton.js'; import { matches } from '../../internal/keyboard/match.js'; import { Enter, Space } from '../../internal/keyboard/keys.js'; function noop() {} function FileUploaderButton(_ref) { let { accept, buttonKind = 'primary', className, disabled = false, disableLabelChanges = false, id, labelText: ownerLabelText = 'Add file', multiple = false, onChange = noop, name, size = 'md', // eslint-disable-next-line react/prop-types innerRef, ...other } = _ref; const prefix = usePrefix(); const [labelText, setLabelText] = useState(ownerLabelText); const [prevOwnerLabelText, setPrevOwnerLabelText] = useState(ownerLabelText); const { current: inputId } = useRef(id || uniqueId()); const inputNode = useRef(null); const classes = cx(`${prefix}--btn`, className, { [`${prefix}--btn--${buttonKind}`]: buttonKind, [`${prefix}--btn--disabled`]: disabled, // V11: remove field, small [`${prefix}--btn--md`]: size === 'md', [`${prefix}--btn--sm`]: 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 (matches(event, [Enter, Space]) && 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__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement("button", _extends({ type: "button", disabled: disabled, className: classes, onClick: onClick, onKeyDown: onKeyDown }, other, { tabIndex: other.tabIndex !== undefined ? parseInt(other.tabIndex) : undefined }), labelText), /*#__PURE__*/React__default.createElement("label", { className: `${prefix}--visually-hidden`, ref: innerRef, htmlFor: inputId }, /*#__PURE__*/React__default.createElement("span", null, labelText)), /*#__PURE__*/React__default.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(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(PropTypes.number, 'The `tabIndex` prop for `FileUploaderButton` has ' + 'been deprecated since it now renders a button element by default.') }; export { FileUploaderButton as default };