upend/webui/src/lib/components/EntitySetEditor.svelte

122 lines
2.7 KiB
Svelte

<script lang="ts">
import UpObjectDisplay from './display/UpObject.svelte';
import Selector, { type SelectorValue } from './utils/Selector.svelte';
import IconButton from './utils/IconButton.svelte';
import { i18n } from '../i18n';
import LabelBorder from './utils/LabelBorder.svelte';
import { createEventDispatcher } from 'svelte';
import { type Address } from '@upnd/upend/types';
import Icon from '$lib/components/utils/Icon.svelte';
const dispatch = createEventDispatcher<{
highlighted: string | undefined;
add: Address;
remove: Address;
}>();
export let entities: string[];
export let hide = false;
export let header = '';
export let icon: string | null = null;
export let confirmRemoveMessage: string | null = $i18n.t('Are you sure you want to remove this?');
export let emptyMessage = $i18n.t('Nothing to show.');
let adding = false;
let selector: Selector;
$: if (adding && selector) selector.focus();
async function add(ev: CustomEvent<SelectorValue | undefined>) {
if (ev.detail?.t !== 'Address') {
return;
}
dispatch('add', ev.detail.c);
}
async function remove(address: string) {
if (!confirmRemoveMessage || confirm(confirmRemoveMessage)) {
dispatch('remove', address);
}
}
</script>
<LabelBorder {hide}>
<span slot="header"
>{#if icon}<Icon plain name={icon} />
{/if}{header}</span
>
{#if adding}
<div class="selector">
<Selector
bind:this={selector}
types={['Address', 'NewAddress']}
on:input={add}
on:focus={(ev) => {
if (!ev.detail) adding = false;
}}
placeholder={$i18n.t('Choose an entity...') || ''}
/>
</div>
{/if}
<div class="body">
<div class="group-list">
{#each entities as entity}
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div
class="group"
on:mouseenter={() => dispatch('highlighted', entity)}
on:mouseleave={() => dispatch('highlighted', undefined)}
>
<UpObjectDisplay address={entity} link />
<IconButton subdued name="x-circle" on:click={() => remove(entity)} />
</div>
{:else}
<div class="no-groups">
{emptyMessage}
</div>
{/each}
</div>
{#if !adding}
<div class="add-button">
<IconButton outline small name="folder-plus" on:click={() => (adding = true)} />
</div>
{/if}
</div>
</LabelBorder>
<style lang="scss">
.group-list {
display: flex;
flex-wrap: wrap;
gap: 0.25rem 0.2rem;
align-items: center;
}
.group {
display: inline-flex;
align-items: center;
}
.body {
display: flex;
align-items: start;
.group-list {
flex-grow: 1;
}
padding-bottom: 0.2rem;
}
.selector {
width: 100%;
margin-bottom: 0.5rem;
}
.no-groups {
opacity: 0.66;
}
</style>