UNPKG

@carbon/react

Version:

React components for the Carbon Design System

120 lines (118 loc) 3.88 kB
/** * Copyright IBM Corp. 2016, 2026 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ import { usePrefix } from "../../internal/usePrefix.js"; import { Enter, Space } from "../../internal/keyboard/keys.js"; import { matches } from "../../internal/keyboard/match.js"; import { useId } from "../../internal/useId.js"; import { noopFn } from "../../internal/noopFn.js"; import { deprecate } from "../../prop-types/deprecate.js"; import { ButtonKinds } from "../Button/Button.js"; import classNames from "classnames"; import { useEffect, useRef, useState } from "react"; import PropTypes from "prop-types"; import { Fragment, jsx, jsxs } from "react/jsx-runtime"; //#region src/components/FileUploader/FileUploaderButton.tsx /** * Copyright IBM Corp. 2016, 2026 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ function FileUploaderButton({ accept, buttonKind = "primary", className, disabled = false, disableLabelChanges = false, id, labelText: ownerLabelText = "Add file", multiple = false, onChange = noopFn, name, size = "md", innerRef, ...other }) { const prefix = usePrefix(); const [labelText, setLabelText] = useState(ownerLabelText); const generatedId = useId(); const { current: inputId } = useRef(id || generatedId); const inputNode = useRef(null); const classes = classNames(`${prefix}--btn`, className, { [`${prefix}--btn--${buttonKind}`]: buttonKind, [`${prefix}--btn--disabled`]: disabled, [`${prefix}--btn--md`]: size === "field" || size === "md", [`${prefix}--btn--sm`]: size === "small" || size === "sm", [`${prefix}--layout--size-${size}`]: size }); useEffect(() => { setLabelText(ownerLabelText); }, [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])) { 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__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx("button", { type: "button", disabled, className: classes, onClick, onKeyDown, ...other, tabIndex: other.tabIndex !== void 0 ? parseInt(other.tabIndex) : void 0, children: labelText }), /* @__PURE__ */ jsx("label", { className: `${prefix}--visually-hidden`, ref: innerRef, htmlFor: inputId, children: /* @__PURE__ */ jsx("span", { children: labelText }) }), /* @__PURE__ */ jsx("input", { className: `${prefix}--visually-hidden`, ref: inputNode, id: inputId, disabled, type: "file", tabIndex: -1, multiple, accept: accept?.toString(), name, onChange: handleOnChange }) ] }); } FileUploaderButton.propTypes = { accept: PropTypes.arrayOf(PropTypes.string), buttonKind: PropTypes.oneOf(ButtonKinds), className: PropTypes.string, disableLabelChanges: PropTypes.bool, disabled: PropTypes.bool, id: PropTypes.string, labelText: PropTypes.node, multiple: PropTypes.bool, name: PropTypes.string, onChange: PropTypes.func, onClick: PropTypes.func, role: PropTypes.string, size: PropTypes.oneOf([ "sm", "md", "lg" ]), tabIndex: deprecate(PropTypes.number, "The `tabIndex` prop for `FileUploaderButton` has been deprecated since it now renders a button element by default.") }; //#endregion export { FileUploaderButton as default };