@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
92 lines • 8.33 kB
JavaScript
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { __rest } from "tslib";
import React, { useRef, useState } from 'react';
import clsx from 'clsx';
import { warnOnce } from '@awsui/component-toolkit/internal';
import InternalBox from '../box/internal';
import { useFormFieldContext } from '../contexts/form-field';
import InternalFileDropzone from '../file-dropzone/internal';
import { useFilesDragging } from '../file-dropzone/use-files-dragging';
import InternalFileInput from '../file-input/internal';
import InternalFileTokenGroup from '../file-token-group/internal';
import { ConstraintText, FormFieldError, FormFieldWarning } from '../form-field/internal';
import { useInternalI18n } from '../i18n/context';
import { getBaseProps } from '../internal/base-component';
import { fireNonCancelableEvent } from '../internal/events';
import checkControlled from '../internal/hooks/check-controlled';
import { useListFocusController } from '../internal/hooks/use-list-focus-controller';
import { useMergeRefs } from '../internal/hooks/use-merge-refs';
import { useUniqueId } from '../internal/hooks/use-unique-id';
import { joinStrings } from '../internal/utils/strings';
import InternalSpaceBetween from '../space-between/internal';
import fileInputStyles from '../file-input/styles.css.js';
import tokenListStyles from '../internal/components/token-list/styles.css.js';
import styles from './styles.css.js';
export default React.forwardRef(InternalFileUpload);
function InternalFileUpload(_a, externalRef) {
var _b, _c, _d;
var { accept, ariaRequired, multiple = false, onChange, value, tokenLimit, showFileSize, showFileLastModified, showFileThumbnail, i18nStrings, __internalRootRef = null, constraintText, errorText, warningText, fileErrors, fileWarnings, fileTokenAlignment = 'vertical' } = _a, restProps = __rest(_a, ["accept", "ariaRequired", "multiple", "onChange", "value", "tokenLimit", "showFileSize", "showFileLastModified", "showFileThumbnail", "i18nStrings", "__internalRootRef", "constraintText", "errorText", "warningText", "fileErrors", "fileWarnings", "fileTokenAlignment"]);
const [nextFocusIndex, setNextFocusIndex] = useState(null);
const tokenListRef = useListFocusController({
nextFocusIndex,
onFocusMoved: target => {
target.focus();
setNextFocusIndex(null);
},
listItemSelector: `.${tokenListStyles['list-item']}`,
showMoreSelector: `.${tokenListStyles.toggle}`,
fallbackSelector: `.${fileInputStyles['file-input']}`,
});
const i18n = useInternalI18n('file-upload');
const baseProps = getBaseProps(restProps);
const metadata = { showFileSize, showFileLastModified, showFileThumbnail };
const errorId = useUniqueId('error-');
const warningId = useUniqueId('warning-');
const constraintTextId = useUniqueId('constraint-text-');
const fileInputRef = useRef(null);
const ref = useMergeRefs(fileInputRef, externalRef);
checkControlled('FileUpload', 'value', value, 'onChange', onChange);
if (!multiple && value.length > 1) {
warnOnce('FileUpload', 'Value must be an array of size 0 or 1 when `multiple=false`.');
}
const handleFilesChange = (newFiles) => {
const newValue = multiple ? [...value, ...newFiles] : newFiles[0] ? newFiles.slice(0, 1) : [...value];
fireNonCancelableEvent(onChange, { value: newValue });
};
const onFileRemove = (removeFileIndex) => {
const newValue = value.filter((_, fileIndex) => fileIndex !== removeFileIndex);
fireNonCancelableEvent(onChange, { value: newValue });
setNextFocusIndex(removeFileIndex);
};
const { areFilesDragging } = useFilesDragging();
const showWarning = warningText && !errorText;
if (warningText && errorText) {
warnOnce('FileUpload', 'Both `errorText` and `warningText` exist. `warningText` will not be shown.');
}
const formFieldContext = useFormFieldContext(restProps);
const ariaDescribedBy = joinStrings((_b = restProps.ariaDescribedby) !== null && _b !== void 0 ? _b : formFieldContext.ariaDescribedby, errorText ? errorId : undefined, showWarning ? warningId : undefined, constraintText ? constraintTextId : undefined);
const hasError = Boolean(errorText || (fileErrors === null || fileErrors === void 0 ? void 0 : fileErrors.filter(Boolean).length));
const invalid = restProps.invalid || formFieldContext.invalid || hasError;
return (React.createElement(InternalSpaceBetween, Object.assign({}, baseProps, { size: "xs", className: clsx(baseProps.className, styles.root), __internalRootRef: __internalRootRef, ref: tokenListRef }),
React.createElement(InternalBox, null,
areFilesDragging ? (React.createElement(InternalFileDropzone, { onChange: event => handleFilesChange(event.detail.value) }, i18n('i18nStrings.dropzoneText', (_c = i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.dropzoneText) === null || _c === void 0 ? void 0 : _c.call(i18nStrings, multiple), format => format({ multiple: `${multiple}` })))) : (React.createElement(InternalFileInput, { ref: ref, accept: accept, ariaRequired: ariaRequired, multiple: multiple, onChange: event => handleFilesChange(event.detail.value), value: value, ariaLabelledby: restProps.ariaLabelledby, controlId: restProps.controlId, ariaDescribedby: ariaDescribedBy, invalid: invalid }, i18n('i18nStrings.uploadButtonText', (_d = i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.uploadButtonText) === null || _d === void 0 ? void 0 : _d.call(i18nStrings, multiple), format => format({ multiple: `${multiple}` })))),
(constraintText || errorText || warningText) && (React.createElement("div", { className: styles.hints },
errorText && (React.createElement(FormFieldError, { id: errorId, errorIconAriaLabel: i18n('i18nStrings.errorIconAriaLabel', i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.errorIconAriaLabel) }, errorText)),
showWarning && (React.createElement(FormFieldWarning, { id: warningId, warningIconAriaLabel: i18n('i18nStrings.warningIconAriaLabel', i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.warningIconAriaLabel) }, warningText)),
constraintText && (React.createElement(ConstraintText, { id: constraintTextId, hasValidationText: !!errorText || !!warningText }, constraintText))))),
value.length > 0 ? (React.createElement(InternalFileTokenGroup, { limit: tokenLimit, alignment: fileTokenAlignment, items: value.map((file, fileIndex) => ({
file,
errorText: fileErrors === null || fileErrors === void 0 ? void 0 : fileErrors[fileIndex],
warningText: fileWarnings === null || fileWarnings === void 0 ? void 0 : fileWarnings[fileIndex],
})), showFileLastModified: metadata.showFileLastModified, showFileSize: metadata.showFileSize, showFileThumbnail: metadata.showFileThumbnail, i18nStrings: {
removeFileAriaLabel: i18n('i18nStrings.removeFileAriaLabel', i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.removeFileAriaLabel, format => fileIndex => format({ fileIndex: fileIndex + 1 })),
limitShowFewer: i18n('i18nStrings.limitShowFewer', i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.limitShowFewer),
limitShowMore: i18n('i18nStrings.limitShowMore', i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.limitShowMore),
formatFileSize: i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.formatFileSize,
formatFileLastModified: i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.formatFileLastModified,
errorIconAriaLabel: i18n('i18nStrings.errorIconAriaLabel', i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.errorIconAriaLabel),
warningIconAriaLabel: i18n('i18nStrings.warningIconAriaLabel', i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.warningIconAriaLabel),
}, onDismiss: event => onFileRemove(event.detail.fileIndex) })) : null));
}
//# sourceMappingURL=internal.js.map