adf0d17497
publish / version_or_publish (push) Has been cancelled
storybook-build / changes (push) Has been cancelled
storybook-build / :storybook-build (push) Has been cancelled
Sync Gradio Skills to Hugging Face / sync-skills (push) Has been cancelled
functional / changes (push) Has been cancelled
functional / build-frontend (push) Has been cancelled
functional / functional-test-SSR=false (push) Has been cancelled
functional / functional-reload (push) Has been cancelled
js / changes (push) Has been cancelled
js / js-test (push) Has been cancelled
docs-build / changes (push) Has been cancelled
docs-build / docs-build (push) Has been cancelled
docs-build / website-build (push) Has been cancelled
functional / functional-test-SSR=true (push) Has been cancelled
hygiene / hygiene-test (push) Has been cancelled
python / changes (push) Has been cancelled
python / build (push) Has been cancelled
python / test-ubuntu-latest-flaky (push) Has been cancelled
python / test-ubuntu-latest-not-flaky (push) Has been cancelled
python / test-windows-latest-flaky (push) Has been cancelled
python / test-windows-latest-not-flaky (push) Has been cancelled
209 lines
4.8 KiB
Svelte
209 lines
4.8 KiB
Svelte
<script lang="ts">
|
|
import { Copy, Check } from "@gradio/icons";
|
|
import { FullscreenButton } from "@gradio/atoms";
|
|
import { IconButton } from "@gradio/atoms";
|
|
|
|
let {
|
|
show_fullscreen_button = false,
|
|
show_copy_button = false,
|
|
show_search = "none",
|
|
fullscreen = false,
|
|
on_copy,
|
|
on_commit_filter,
|
|
current_search_query = null,
|
|
onsearch,
|
|
onfullscreen
|
|
}: {
|
|
show_fullscreen_button?: boolean;
|
|
show_copy_button?: boolean;
|
|
show_search?: "none" | "search" | "filter";
|
|
fullscreen?: boolean;
|
|
on_copy: () => Promise<void>;
|
|
on_commit_filter: () => void;
|
|
current_search_query?: string | null;
|
|
onsearch?: (query: string | null) => void;
|
|
onfullscreen?: () => void;
|
|
} = $props();
|
|
|
|
let copied = $state(false);
|
|
let timer: ReturnType<typeof setTimeout>;
|
|
let input_value = $state("");
|
|
|
|
function handle_search_input(e: Event): void {
|
|
const target = e.target as HTMLTextAreaElement;
|
|
input_value = target.value;
|
|
const new_query = input_value || null;
|
|
if (current_search_query !== new_query) {
|
|
current_search_query = new_query;
|
|
onsearch?.(current_search_query);
|
|
}
|
|
}
|
|
|
|
function copy_feedback(): void {
|
|
copied = true;
|
|
if (timer) clearTimeout(timer);
|
|
timer = setTimeout(() => {
|
|
copied = false;
|
|
}, 2000);
|
|
}
|
|
|
|
async function handle_copy(): Promise<void> {
|
|
await on_copy();
|
|
copy_feedback();
|
|
}
|
|
|
|
$effect(() => {
|
|
return () => {
|
|
if (timer) clearTimeout(timer);
|
|
};
|
|
});
|
|
</script>
|
|
|
|
<div class="toolbar" role="toolbar" aria-label="Table actions">
|
|
<div class="toolbar-buttons">
|
|
{#if show_search !== "none"}
|
|
<div class="search-container">
|
|
<input
|
|
type="text"
|
|
value={current_search_query || ""}
|
|
oninput={handle_search_input}
|
|
placeholder={show_search === "filter" ? "Filter..." : "Search..."}
|
|
class="search-input"
|
|
class:filter-mode={show_search === "filter"}
|
|
title={`Enter text to ${show_search} the table`}
|
|
/>
|
|
{#if current_search_query && show_search === "filter"}
|
|
<button
|
|
class="toolbar-button check-button"
|
|
onclick={on_commit_filter}
|
|
aria-label="Apply filter and update dataframe values"
|
|
title="Apply filter and update dataframe values"
|
|
>
|
|
<Check />
|
|
</button>
|
|
{/if}
|
|
</div>
|
|
{/if}
|
|
{#if show_copy_button}
|
|
<IconButton
|
|
Icon={copied ? Check : Copy}
|
|
label={copied ? "Copied to clipboard" : "Copy table data"}
|
|
onclick={handle_copy}
|
|
/>
|
|
{/if}
|
|
{#if show_fullscreen_button}
|
|
<FullscreenButton {fullscreen} onclick={(_fs) => onfullscreen?.()} />
|
|
{/if}
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.toolbar {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--size-2);
|
|
flex: 0 0 auto;
|
|
font-family: var(--font-sans);
|
|
}
|
|
|
|
.toolbar-buttons {
|
|
display: flex;
|
|
gap: var(--size-1);
|
|
flex-wrap: nowrap;
|
|
align-items: center;
|
|
}
|
|
|
|
.toolbar-button {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: var(--size-6);
|
|
height: var(--size-6);
|
|
padding: var(--size-1);
|
|
border: none;
|
|
border-radius: var(--radius-sm);
|
|
background: transparent;
|
|
color: var(--body-text-color-subdued);
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.toolbar-button:hover {
|
|
background: var(--background-fill-secondary);
|
|
color: var(--body-text-color);
|
|
}
|
|
|
|
.toolbar-button :global(svg) {
|
|
width: var(--size-4);
|
|
height: var(--size-4);
|
|
}
|
|
|
|
.search-container {
|
|
position: relative;
|
|
}
|
|
|
|
.search-input {
|
|
width: var(--size-full);
|
|
height: var(--size-6);
|
|
padding: var(--size-2);
|
|
padding-right: var(--size-8);
|
|
border: 1px solid var(--border-color-primary);
|
|
border-radius: var(--table-radius);
|
|
font-size: var(--text-sm);
|
|
color: var(--body-text-color);
|
|
background: var(--background-fill-secondary);
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.search-input:hover {
|
|
border-color: var(--border-color-secondary);
|
|
background: var(--background-fill-primary);
|
|
}
|
|
|
|
.search-input:focus {
|
|
outline: none;
|
|
border-color: var(--color-accent);
|
|
background: var(--background-fill-primary);
|
|
box-shadow: 0 0 0 1px var(--color-accent);
|
|
}
|
|
|
|
.check-button {
|
|
position: absolute;
|
|
right: var(--size-1);
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
background: var(--color-accent);
|
|
color: white;
|
|
border: none;
|
|
width: var(--size-4);
|
|
height: var(--size-4);
|
|
border-radius: var(--radius-sm);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: var(--size-1);
|
|
}
|
|
|
|
.check-button :global(svg) {
|
|
width: var(--size-3);
|
|
height: var(--size-3);
|
|
}
|
|
|
|
.check-button:hover {
|
|
background: var(--color-accent-soft);
|
|
}
|
|
|
|
.toolbar-buttons :global(.icon-button) {
|
|
background: transparent !important;
|
|
height: var(--size-6);
|
|
width: var(--size-6);
|
|
}
|
|
|
|
.toolbar-buttons :global(.icon-button:hover) {
|
|
background: var(--background-fill-secondary) !important;
|
|
color: var(--body-text-color) !important;
|
|
border: 1px solid var(--border-color-primary);
|
|
border-radius: var(--radius-sm) !important;
|
|
}
|
|
</style>
|