@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
JavaScript
// 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