gradio/js/file/shared/FilePreview.svelte
pngwn 5bf00b7524
make all component SSR compatible (#9187)
* asd

* fixes

* make all components ssr compatible

* remove files

* add changeset

* add changeset

* review

* format

* clean

* address comments

* tweaks utils

* add changeset

* fix plot and audio

* format

* fix nativeplot

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
2024-08-31 06:19:51 +00:00

202 lines
4.4 KiB
Svelte
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script lang="ts">
import type { FileData } from "@gradio/client";
import { prettyBytes } from "./utils";
import { createEventDispatcher } from "svelte";
import type { I18nFormatter, SelectData } from "@gradio/utils";
import { DownloadLink } from "@gradio/wasm/svelte";
const dispatch = createEventDispatcher<{
select: SelectData;
change: FileData[] | FileData;
delete: FileData;
}>();
export let value: FileData | FileData[];
export let selectable = false;
export let height: number | undefined = undefined;
export let i18n: I18nFormatter;
function split_filename(filename: string): [string, string] {
const last_dot = filename.lastIndexOf(".");
if (last_dot === -1) {
return [filename, ""];
}
return [filename.slice(0, last_dot), filename.slice(last_dot)];
}
$: normalized_files = (Array.isArray(value) ? value : [value]).map((file) => {
const [filename_stem, filename_ext] = split_filename(file.orig_name ?? "");
return {
...file,
filename_stem,
filename_ext
};
});
function handle_row_click(
event: MouseEvent & { currentTarget: HTMLTableRowElement },
index: number
): void {
const tr = event.currentTarget;
const should_select =
event.target === tr || // Only select if the click is on the row itself
(tr &&
tr.firstElementChild &&
event.composedPath().includes(tr.firstElementChild)); // Or if the click is on the name column
if (should_select) {
dispatch("select", { value: normalized_files[index].orig_name, index });
}
}
function remove_file(index: number): void {
const removed = normalized_files.splice(index, 1);
normalized_files = [...normalized_files];
value = normalized_files;
dispatch("delete", removed[0]);
dispatch("change", normalized_files);
}
const is_browser = typeof window !== "undefined";
</script>
<div
class="file-preview-holder"
style="max-height: {typeof height === undefined ? 'auto' : height + 'px'};"
>
<table class="file-preview">
<tbody>
{#each normalized_files as file, i (file)}
<tr
class="file"
class:selectable
on:click={(event) => {
handle_row_click(event, i);
}}
>
<td class="filename" aria-label={file.orig_name}>
<span class="stem">{file.filename_stem}</span>
<span class="ext">{file.filename_ext}</span>
</td>
<td class="download">
{#if file.url}
<DownloadLink
href={file.url}
download={is_browser && window.__is_colab__
? null
: file.orig_name}
>
{@html file.size != null
? prettyBytes(file.size)
: "(size unknown)"}&nbsp;&#8675;
</DownloadLink>
{:else}
{i18n("file.uploading")}
{/if}
</td>
{#if normalized_files.length > 1}
<td>
<button
class="label-clear-button"
aria-label="Remove this file"
on:click={() => {
remove_file(i);
}}
on:keydown={(event) => {
if (event.key === "Enter") {
remove_file(i);
}
}}
>×
</button>
</td>
{/if}
</tr>
{/each}
</tbody>
</table>
</div>
<style>
.label-clear-button {
color: var(--body-text-color-subdued);
position: relative;
left: -3px;
}
.label-clear-button:hover {
color: var(--body-text-color);
}
.file-preview {
table-layout: fixed;
width: var(--size-full);
max-height: var(--size-60);
overflow-y: auto;
margin-top: var(--size-1);
color: var(--body-text-color);
}
.file-preview-holder {
overflow: auto;
}
.file {
display: flex;
width: var(--size-full);
}
.file > * {
padding: var(--size-1) var(--size-2-5);
}
.filename {
flex-grow: 1;
display: flex;
overflow: hidden;
}
.filename .stem {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.filename .ext {
white-space: nowrap;
}
.download {
min-width: 8rem;
width: 10%;
white-space: nowrap;
text-align: right;
}
.download:hover {
text-decoration: underline;
}
.download > :global(a) {
color: var(--link-text-color);
}
.download > :global(a:hover) {
color: var(--link-text-color-hover);
}
.download > :global(a:visited) {
color: var(--link-text-color-visited);
}
.download > :global(a:active) {
color: var(--link-text-color-active);
}
.selectable {
cursor: pointer;
}
tbody > tr:nth-child(even) {
background: var(--block-background-fill);
}
tbody > tr:nth-child(odd) {
background: var(--table-odd-background-fill);
}
</style>