Skip to content

Commit

Permalink
feat: Adds dropzone standalone component
Browse files Browse the repository at this point in the history
  • Loading branch information
Katie George committed Oct 17, 2024
1 parent 02361cc commit 418089e
Show file tree
Hide file tree
Showing 10 changed files with 432 additions and 171 deletions.
97 changes: 97 additions & 0 deletions pages/file-dropzone/container.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React, { useEffect, useRef, useState } from 'react';

import {
Box,
Checkbox,
Container,
FileDropzone,
FileInput,
FileUploadProps,
Header,
SpaceBetween,
Table,
} from '~components';

import { useContractFilesForm } from '../file-upload/page-helpers';
import { validateContractFiles } from '../file-upload/validations';

export default function FileUploadScenarioStandalone() {
const contractsRef = useRef<FileUploadProps.Ref>(null);

const [acceptMultiple, setAcceptMultiple] = useState(true);
const formState = useContractFilesForm();

const hasError = formState.status === 'error';
useEffect(() => {
if (hasError) {
contractsRef.current?.focus();
}
}, [hasError]);

const handleFilesChange = (newFiles: File[]) => {
const newValue = acceptMultiple ? [...formState.files, ...newFiles] : newFiles[0] ? newFiles : [...formState.files];
formState.onFilesChange(newValue);
formState.onUploadFiles(!validateContractFiles(newValue) ? newValue : []);
};

return (
<Box margin="xl">
<SpaceBetween size="xl">
<Header variant="h1">File dropzone: in container</Header>

<Checkbox checked={acceptMultiple} onChange={(event: any) => setAcceptMultiple(event.detail.checked)}>
Accept multiple files
</Checkbox>
<Container header={<Header>Attachments</Header>}>
<SpaceBetween size="l">
<FileDropzone onChange={(event: any) => handleFilesChange(event.detail.value)}>
<FileInput
onChange={(event: any) => handleFilesChange(event.detail.value)}
value={formState.files}
i18nStrings={{ uploadButtonText: (multiple: boolean) => (multiple ? 'Choose files' : 'Choose file') }}
multiple={acceptMultiple}
/>
<Box padding={{ top: 'xxs' }} fontWeight="bold" color="text-body-secondary">
{acceptMultiple ? 'or drop files here' : 'or drop file here'}
</Box>
</FileDropzone>
<Table
variant="embedded"
empty={'No files uploaded'}
columnDefinitions={[
{
id: 'file-name',
header: 'File name',
cell: item => item.name || '-',
sortingField: 'name',
isRowHeader: true,
},
{
id: 'file-type',
header: 'File type',
cell: item => item.type || '-',
sortingField: 'alt',
},
{
id: 'file-size',
header: 'File size',
cell: item => item.size || '-',
},
]}
enableKeyboardNavigation={true}
items={formState.files.map(file => ({
name: file.name,
type: file.type,
size: file.size,
}))}
loadingText="Loading resources"
sortingDisabled={true}
/>
</SpaceBetween>
</Container>
</SpaceBetween>
</Box>
);
}
134 changes: 49 additions & 85 deletions pages/file-upload/deconstructed.page.tsx
Original file line number Diff line number Diff line change
@@ -1,63 +1,26 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React, { useEffect, useRef, useState } from 'react';
import clsx from 'clsx';

import { Box, Checkbox, FileInput, FileTokenGroup, FileUploadProps, FormField, Header, PromptInput } from '~components';
import {
Box,
Checkbox,
FileDropzone,
FileInput,
FileTokenGroup,
FileUploadProps,
FormField,
Header,
Icon,
PromptInput,
} from '~components';
import SpaceBetween from '~components/space-between';

import { useContractFilesForm } from './page-helpers';
import { i18nStrings } from './shared';
import { useDropzoneVisible } from './use-dropzone-visible';
import { validateContractFiles } from './validations';

import styles from './styles.scss';

interface DropzoneProps {
onChange: (files: File[]) => void;
children: React.ReactNode;
}

export function Dropzone({ onChange, children }: DropzoneProps) {
const [isDropzoneHovered, setDropzoneHovered] = useState(false);

const onDragOver = (event: React.DragEvent) => {
event.preventDefault();

if (event.dataTransfer) {
setDropzoneHovered(true);
event.dataTransfer.dropEffect = 'copy';
}
};

const onDragLeave = (event: React.DragEvent) => {
event.preventDefault();
setDropzoneHovered(false);

if (event.dataTransfer) {
event.dataTransfer.dropEffect = 'none';
}
};

const onDrop = (event: React.DragEvent) => {
event.preventDefault();
setDropzoneHovered(false);

onChange(Array.from(event.dataTransfer.files));
};

return (
<div
className={clsx(styles.dropzone, isDropzoneHovered && styles['dropzone-hovered'])}
onDragOver={onDragOver}
onDragLeave={onDragLeave}
onDrop={onDrop}
>
<span>{children}</span>
</div>
);
}

export default function FileUploadScenarioStandalone() {
const contractsRef = useRef<FileUploadProps.Ref>(null);
const [textareaValue, setTextareaValue] = useState('');
Expand All @@ -66,7 +29,7 @@ export default function FileUploadScenarioStandalone() {
const [verticalAlign, setVerticalAlign] = useState(false);
const formState = useContractFilesForm();

const isDropzoneVisible = useDropzoneVisible(acceptMultiple);
const isFileBeingDragged = useDropzoneVisible(acceptMultiple);

// const contractsValidationErrors = validateContractFiles(formState.files);
// const contractsErrors = contractsValidationErrors ?? formState.fileErrors;
Expand Down Expand Up @@ -103,36 +66,38 @@ export default function FileUploadScenarioStandalone() {
</Checkbox>

<FormField>
{isDropzoneVisible ? (
<Dropzone onChange={handleFilesChange}>dropping files</Dropzone>
) : (
<PromptInput
ariaLabel="Chat input"
actionButtonIconName="send"
actionButtonAriaLabel="Submit prompt"
value={textareaValue}
onChange={(event: any) => setTextareaValue(event.detail.value)}
onAction={(event: any) => window.alert(`Submitted the following: ${event.detail.value}`)}
// onFilesChange={(event: any) => handleFilesChange(event.detail.value)}
// files={formState.files}
// multiple={acceptMultiple}
placeholder="Ask a question"
maxRows={4}
disableSecondaryActionsPaddings={true}
secondaryActions={
<Box padding={{ left: 'xxs', top: 'xs' }}>
<FileInput
variant="icon"
ref={contractsRef}
multiple={acceptMultiple}
value={formState.files}
onChange={(event: any) => handleFilesChange(event.detail.value)}
i18nStrings={i18nStrings}
/>
</Box>
}
secondaryContent={
formState.files.length > 0 ? (
<PromptInput
ariaLabel="Chat input"
actionButtonIconName="send"
actionButtonAriaLabel="Submit prompt"
value={textareaValue}
onChange={(event: any) => setTextareaValue(event.detail.value)}
onAction={(event: any) => window.alert(`Submitted the following: ${event.detail.value}`)}
placeholder="Ask a question"
maxRows={4}
disableSecondaryActionsPaddings={true}
secondaryActions={
<Box padding={{ left: 'xxs', top: 'xs' }}>
<FileInput
variant="icon"
ref={contractsRef}
multiple={acceptMultiple}
value={formState.files}
onChange={(event: any) => handleFilesChange(event.detail.value)}
i18nStrings={i18nStrings}
/>
</Box>
}
secondaryContent={
isFileBeingDragged ? (
<FileDropzone onChange={(event: any) => handleFilesChange(event.detail.value)}>
<SpaceBetween size="xs" alignItems="center">
<Icon name="upload" />
Drop files here
</SpaceBetween>
</FileDropzone>
) : formState.files.length > 0 ? (
<>
<FileTokenGroup
alignment={verticalAlign ? 'vertical' : 'horizontal'}
items={formState.files.map(file => ({
Expand All @@ -145,12 +110,11 @@ export default function FileUploadScenarioStandalone() {
showFileThumbnail={true}
i18nStrings={i18nStrings}
onDismiss={onDismiss}
limit={2}
/>
) : undefined
}
/>
)}
</>
) : undefined
}
/>
</FormField>

<FormField
Expand Down
27 changes: 0 additions & 27 deletions pages/file-upload/styles.scss

This file was deleted.

Loading

0 comments on commit 418089e

Please sign in to comment.