carbon-components-svelte/src/FileUploader/FileUploader.svelte
Eric Liu f9909827d0
Align v10.34 (#621)
* feat(theme): add g80 theme

* docs(data-table): use link with icon variant

* feat(search): support expandable variant

* fix(file-uploaded): use semantic p element instead of strong

* feat(side-nav): dispatch open, close, click:overlay events

* refactor(ui-shell): remove usage of deprecated Icon component

* feat(ui-shell): allow custom hamburger menu icons

* feat(button): support xl size

* fix(code-snippet): wrap code element with pre

* refactor(button): use button specific tooltip class for icon-only variant

* feat(password-input): support warning, inline props

* feat(data-table): support medium size
2021-06-25 03:45:30 -07:00

124 lines
2.9 KiB
Svelte

<script>
/**
* @event {File[]} add
* @event {File[]} remove
*/
/**
* Specify the file uploader status
* @type {"uploading" | "edit" | "complete"}
*/
export let status = "uploading";
/**
* Specify the accepted file types
* @type {string[]}
*/
export let accept = [];
/**
* Obtain the uploaded file names
* @type {File[]}
*/
export let files = [];
/** Set to `true` to allow multiple files */
export let multiple = false;
/**
* Override the default behavior of clearing the array of uploaded files
* @type {() => void}
*/
export const clearFiles = () => {
files = [];
};
/** Specify the label description */
export let labelDescription = "";
/** Specify the label title */
export let labelTitle = "";
/**
* Specify the kind of file uploader button
* @type {"primary" | "secondary" | "tertiary" | "ghost" | "danger"}
*/
export let kind = "primary";
/** Specify the button label */
export let buttonLabel = "";
/** Specify the ARIA label used for the status icons */
export let iconDescription = "Provide icon description";
/** Specify a name attribute for the file button uploader input */
export let name = "";
import { createEventDispatcher, afterUpdate } from "svelte";
import Filename from "./Filename.svelte";
import FileUploaderButton from "./FileUploaderButton.svelte";
const dispatch = createEventDispatcher();
$: prevFiles = [];
afterUpdate(() => {
if (files.length > prevFiles.length) {
dispatch("add", files);
} else {
dispatch(
"remove",
prevFiles.filter((_) => !files.includes(_))
);
}
prevFiles = [...files];
});
</script>
<div
class:bx--form-item="{true}"
{...$$restProps}
on:click
on:mouseover
on:mouseenter
on:mouseleave
>
<p class:bx--file--label="{true}">{labelTitle}</p>
<p class:bx--label-description="{true}">{labelDescription}</p>
<FileUploaderButton
disableLabelChanges
labelText="{buttonLabel}"
accept="{accept}"
name="{name}"
multiple="{multiple}"
kind="{kind}"
on:change
on:change="{({ target }) => {
files = [...target.files];
}}"
/>
<div class:bx--file-container="{true}">
{#each files as { name }, i (name)}
<span class:bx--file__selected-file="{true}">
<p class:bx--file-filename="{true}">{name}</p>
<span class:bx--file__state-container="{true}">
<Filename
iconDescription="{iconDescription}"
status="{status}"
on:keydown
on:keydown="{({ key }) => {
if (key === ' ' || key === 'Enter') {
files = files.filter((_, index) => index !== i);
}
}}"
on:click
on:click="{() => {
files = files.filter((_, index) => index !== i);
}}"
/>
</span>
</span>
{/each}
</div>
</div>