UNPKG

@awsui/components-react

Version:

On July 19th, 2022, we launched [Cloudscape Design System](https://cloudscape.design). Cloudscape is an evolution of AWS-UI. It consists of user interface guidelines, front-end components, design resources, and development tools for building intuitive, en

77 lines 5.16 kB
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 import { __rest } from "tslib"; import React, { useEffect, useRef, useState } from 'react'; import clsx from 'clsx'; import { warnOnce } from '@awsui/component-toolkit/internal'; import InternalButton from '../button/internal'; import { useFormFieldContext } from '../contexts/form-field'; import { getBaseProps } from '../internal/base-component/index.js'; import ScreenreaderOnly from '../internal/components/screenreader-only'; import { useSingleTabStopNavigation } from '../internal/context/single-tab-stop-navigation-context'; import { fireNonCancelableEvent } from '../internal/events'; import checkControlled from '../internal/hooks/check-controlled'; import useForwardFocus from '../internal/hooks/forward-focus'; import { useMergeRefs } from '../internal/hooks/use-merge-refs'; import { useUniqueId } from '../internal/hooks/use-unique-id'; import { joinStrings } from '../internal/utils/strings'; import styles from './styles.css.js'; const InternalFileInput = React.forwardRef((_a, ref) => { var _b; var { accept, ariaRequired, ariaLabel, multiple = false, value, onChange, variant = 'button', children, __internalRootRef = null, __inputClassName, __inputNativeAttributes } = _a, restProps = __rest(_a, ["accept", "ariaRequired", "ariaLabel", "multiple", "value", "onChange", "variant", "children", "__internalRootRef", "__inputClassName", "__inputNativeAttributes"]); const baseProps = getBaseProps(restProps); const uploadInputRef = useRef(null); const containerRef = useRef(null); const mergedRef = useMergeRefs(__internalRootRef, containerRef); const uploadButtonLabelId = useUniqueId('upload-button-label'); const formFieldContext = useFormFieldContext(restProps); const selfControlId = useUniqueId('upload-input'); const controlId = (_b = formFieldContext.controlId) !== null && _b !== void 0 ? _b : selfControlId; useForwardFocus(ref, uploadInputRef); const [isFocused, setIsFocused] = useState(false); const onUploadButtonClick = () => { var _a; return (_a = uploadInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }; const onUploadInputFocus = () => { var _a, _b; setIsFocused(true); (_b = (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView) === null || _b === void 0 ? void 0 : _b.call(_a); }; const onUploadInputBlur = () => setIsFocused(false); const onUploadInputChange = ({ target }) => { fireNonCancelableEvent(onChange, { value: target.files ? Array.from(target.files) : [] }); }; checkControlled('FileInput', 'value', value, 'onChange', onChange); const nativeAttributes = Object.assign({ 'aria-label': ariaLabel || children, 'aria-labelledby': joinStrings(formFieldContext.ariaLabelledby, uploadButtonLabelId), 'aria-describedby': formFieldContext.ariaDescribedby }, __inputNativeAttributes); if (formFieldContext.invalid) { nativeAttributes['aria-invalid'] = true; } if (ariaRequired) { nativeAttributes['aria-required'] = true; } if (variant === 'icon' && !ariaLabel) { warnOnce('FileInput', 'Aria label is required with icon variant.'); } // Synchronizing component's value with the native file input state. useEffect(() => { /* istanbul ignore next: The DataTransfer is not available in jsdom. */ if (window.DataTransfer) { const dataTransfer = new DataTransfer(); for (const file of value) { dataTransfer.items.add(file); } uploadInputRef.current.files = dataTransfer.files; } if (uploadInputRef.current) { uploadInputRef.current.value = ''; // reset value to allow calling onChange when the same file is uploaded again } }, [value]); const { tabIndex } = useSingleTabStopNavigation(uploadInputRef); return (React.createElement("div", Object.assign({}, baseProps, { ref: mergedRef, className: clsx(baseProps.className, styles.root) }), React.createElement("input", Object.assign({ id: controlId, ref: uploadInputRef, type: "file", hidden: false, multiple: multiple, accept: accept, onChange: onUploadInputChange, onFocus: onUploadInputFocus, onBlur: onUploadInputBlur, className: clsx(styles['file-input'], styles.hidden, __inputClassName), tabIndex: tabIndex }, nativeAttributes)), React.createElement(InternalButton, { iconName: "upload", variant: variant === 'icon' ? 'icon' : undefined, formAction: "none", onClick: onUploadButtonClick, className: clsx(styles['file-input-button'], { [styles['force-focus-outline-button']]: isFocused && variant === 'button', [styles['force-focus-outline-icon']]: isFocused && variant === 'icon', }), __nativeAttributes: { tabIndex: -1, 'aria-hidden': true } }, variant === 'button' && children), React.createElement(ScreenreaderOnly, { id: uploadButtonLabelId }, ariaLabel || children))); }); export default InternalFileInput; //# sourceMappingURL=internal.js.map