Files
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 13:17:32 +08:00

297 lines
6.2 KiB
Svelte

<script lang="ts">
import { click_outside } from "./utils/events";
import {
Layers,
Clear,
ArrowUp,
ArrowDown,
Plus,
Visibility,
VisibilityOff
} from "@gradio/icons";
import { IconButton } from "@gradio/atoms";
import type { Writable } from "svelte/store";
let {
layers,
enable_additional_layers = true,
enable_layers = true,
show_layers = false,
onnew_layer,
onchange_layer,
onmove_layer,
ondelete_layer,
ontoggle_layer_visibility
}: {
layers: Writable<{
active_layer: string;
layers: {
name: string;
id: string;
user_created: boolean;
visible: boolean;
}[];
}>;
enable_additional_layers?: boolean;
enable_layers?: boolean;
show_layers?: boolean;
onnew_layer?: () => void;
onchange_layer?: (id: string) => void;
onmove_layer?: (value: { id: string; direction: "up" | "down" }) => void;
ondelete_layer?: (id: string) => void;
ontoggle_layer_visibility?: (id: string) => void;
} = $props();
function new_layer(): void {
onnew_layer?.();
}
function change_layer(id: string): void {
onchange_layer?.(id);
show_layers = false;
}
function move_layer(id: string, direction: "up" | "down"): void {
onmove_layer?.({ id, direction });
}
function delete_layer(id: string): void {
ondelete_layer?.(id);
}
</script>
{#if enable_layers}
<div
class="layer-wrap"
class:closed={!show_layers}
use:click_outside={() => (show_layers = false)}
>
<button
class="layer-title-button"
aria-label="Show Layers"
onclick={(event) => {
event.stopPropagation();
show_layers = !show_layers;
}}
>
{show_layers
? "Layers"
: $layers.layers.find((l) => l.id === $layers.active_layer)?.name}
<span class="icon"><Layers /></span>
</button>
{#if show_layers}
<ul>
{#each $layers.layers as { id, name, user_created, visible }, i (i)}
<li>
{#if !visible}
<IconButton
Icon={VisibilityOff}
size="small"
onclick={(e) => {
e.stopPropagation();
ontoggle_layer_visibility?.(id);
}}
/>
{:else}
<IconButton
Icon={Visibility}
size="small"
onclick={(e) => {
e.stopPropagation();
ontoggle_layer_visibility?.(id);
}}
/>
{/if}
<button
class:selected_layer={$layers.active_layer === id}
aria-label={`layer-${i + 1}`}
onclick={(event) => {
event.stopPropagation();
change_layer(id);
}}>{name}</button
>
{#if $layers.layers.length > 1}
<div>
{#if i > 0}
<IconButton
onclick={(e) => {
e.stopPropagation();
move_layer(id, "up");
}}
Icon={ArrowUp}
size="x-small"
/>
{/if}
{#if i < $layers.layers.length - 1}
<IconButton
onclick={(e) => {
e.stopPropagation();
move_layer(id, "down");
}}
Icon={ArrowDown}
size="x-small"
/>
{/if}
{#if $layers.layers.length > 1 && user_created}
<IconButton
onclick={(e) => {
e.stopPropagation();
delete_layer(id);
}}
Icon={Clear}
size="x-small"
/>
{/if}
</div>
{/if}
</li>
{/each}
{#if enable_additional_layers}
<li class="add-layer">
<IconButton
Icon={Plus}
label="Add Layer"
onclick={(e) => {
e.stopPropagation();
new_layer();
}}
size="x-small"
/>
</li>
{/if}
</ul>
{/if}
</div>
{/if}
<style>
.add-layer {
display: flex;
justify-content: center;
align-items: center;
margin: var(--spacing-sm) 0 0 0;
}
.add-layer :global(button) {
width: 100%;
}
.icon {
width: 14px;
color: var(--body-text-color);
transition: color 0.15s ease;
}
.layer-wrap {
/* position: absolute; */
display: flex;
justify-content: center;
align-items: center;
/* border: 1px solid var(--border-color-primary); */
/* z-index: var(--layer-1); */
/* border-radius: var(--radius-sm); */
/* background-color: var(--block-background-fill); */
width: 100%;
flex-direction: column;
/* bottom: 5px; */
/* right: 5px; */
/* border-bottom: 0;
border-right: 0; */
/* box-shadow: var(--shadow-drop); */
}
.layer-wrap button {
justify-content: space-between;
align-items: center;
width: 100%;
display: flex;
font-size: var(--text-sm);
line-height: var(--line-sm);
transition: all 0.15s ease;
padding: var(--spacing-md) var(--spacing-lg);
/* padding-right: var(--spacing-lg); */
border-radius: var(--radius-sm);
/* padding-left: 30px; */
}
button.layer-title-button {
width: 100%;
/* padding-left: 30px; */
}
.layer-wrap button:hover .icon {
color: var(--color-accent);
}
.selected_layer {
color: var(--color-accent);
font-weight: var(--weight-semibold);
}
ul {
/* position: absolute; */
bottom: 0;
right: 0;
/* background: var(--block-background-fill); */
width: 100%;
/* min-width: 100%; */
list-style: none;
z-index: var(--layer-top);
/* border: 1px solid var(--border-color-primary); */
/* border-radius: var(--radius-sm); */
/* box-shadow: var(--shadow-drop-lg); */
padding: var(--spacing-sm);
/* transform: translate(-1px, 1px); */
border-top: 1px solid var(--border-color-primary);
}
/* .sep {
height: 12px;
background-color: var(--block-border-color);
width: 1px;
display: block;
margin-left: var(--spacing-xl);
} */
li {
display: flex;
justify-content: space-between;
align-items: center;
/* border-radius: var(--radius-sm); */
transition: background-color 0.15s ease;
border-bottom: 1px solid var(--border-color-primary);
}
.layer-wrap ul > li > button {
padding-left: calc(var(--spacing-md));
}
li:hover {
background-color: var(--background-fill-secondary);
}
li:last-child {
border-bottom: none;
}
li:last-child:hover {
background-color: unset;
}
li div {
display: flex;
gap: var(--spacing-sm);
padding: var(--spacing-sm);
}
li > button {
padding: var(--spacing-sm) var(--spacing-md);
}
/* li > div > button {
opacity: 0.7;
transition: opacity 0.15s ease;
}
li > div > button:hover {
opacity: 1;
} */
</style>