116 lines
2.4 KiB
Svelte
116 lines
2.4 KiB
Svelte
|
<script lang="ts">
|
||
|
import UpObjectDisplay from "./display/UpObject.svelte";
|
||
|
import Selector from "./utils/Selector.svelte";
|
||
|
import IconButton from "./utils/IconButton.svelte";
|
||
|
import type { IValue } from "@upnd/upend/types";
|
||
|
import { i18n } from "../i18n";
|
||
|
import LabelBorder from "./utils/LabelBorder.svelte";
|
||
|
import { createEventDispatcher } from "svelte";
|
||
|
const dispatch = createEventDispatcher();
|
||
|
|
||
|
export let entities: string[];
|
||
|
|
||
|
export let header = "";
|
||
|
export let confirmRemoveMessage = $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();
|
||
|
|
||
|
let entityToAdd: IValue | undefined;
|
||
|
async function add() {
|
||
|
if (!entityToAdd) {
|
||
|
return;
|
||
|
}
|
||
|
dispatch("add", entityToAdd.c as string);
|
||
|
entityToAdd = undefined;
|
||
|
}
|
||
|
|
||
|
async function remove(address: string) {
|
||
|
if (confirm(confirmRemoveMessage)) {
|
||
|
dispatch("remove", address);
|
||
|
}
|
||
|
}
|
||
|
</script>
|
||
|
|
||
|
<LabelBorder>
|
||
|
<span slot="header">{header}</span>
|
||
|
|
||
|
{#if adding}
|
||
|
<div class="selector">
|
||
|
<Selector
|
||
|
bind:this={selector}
|
||
|
type="value"
|
||
|
valueTypes={["Address"]}
|
||
|
bind:value={entityToAdd}
|
||
|
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}
|
||
|
<div class="group">
|
||
|
<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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.selector {
|
||
|
width: 100%;
|
||
|
margin-bottom: 0.5rem;
|
||
|
}
|
||
|
|
||
|
.no-groups {
|
||
|
opacity: 0.66;
|
||
|
}
|
||
|
</style>
|