2025-06-30 18:58:24 +02:00
|
|
|
<!--
|
|
|
|
SPDX-FileCopyrightText: © 2025 Hornwitser <code@hornwitser.no>
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
-->
|
2025-06-27 18:20:24 +02:00
|
|
|
<template>
|
|
|
|
<div
|
|
|
|
class="select"
|
|
|
|
@focusin="dropdownComponent?.focusin()"
|
|
|
|
@focusout="dropdownComponent?.focusout()"
|
|
|
|
@keyup.esc="dropdownComponent?.esc()"
|
|
|
|
>
|
|
|
|
<div class="selected">
|
|
|
|
<div
|
|
|
|
v-for="id of selectedIds"
|
|
|
|
:key="id"
|
|
|
|
class="item"
|
|
|
|
>
|
|
|
|
{{ entities.get(id)?.name ?? id }}
|
|
|
|
<button
|
|
|
|
@click="selectedIds.delete(id)"
|
|
|
|
>x</button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<SelectDropdown
|
|
|
|
ref="dropdown"
|
|
|
|
v-model="selectedIds"
|
|
|
|
:multi="true"
|
|
|
|
:entities
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
|
import type { ApiEntity } from '~/shared/types/api';
|
|
|
|
import type { Id } from '~/shared/types/common';
|
|
|
|
import type { ClientEntity } from '~/utils/client-entity';
|
|
|
|
|
|
|
|
const selectedIds = defineModel<Set<Id>>({ required: true });
|
|
|
|
defineProps<{
|
|
|
|
entities: ClientMap<ClientEntity<ApiEntity> & { name?: string }>,
|
|
|
|
}>();
|
|
|
|
|
|
|
|
const dropdownComponent = useTemplateRef("dropdown");
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
.select {
|
|
|
|
display: flex;
|
|
|
|
flex-wrap: wrap;
|
|
|
|
position: relative;
|
|
|
|
}
|
|
|
|
.selected {
|
|
|
|
display: flex;
|
|
|
|
flex-wrap: wrap;
|
|
|
|
gap: 0.2rem;
|
|
|
|
}
|
|
|
|
.item {
|
|
|
|
background-color: color-mix(in srgb, Canvas, CanvasText 10%);
|
|
|
|
border-radius: 0.3rem;
|
|
|
|
padding-inline: 0.2rem;
|
|
|
|
padding-block: 0.1rem;
|
|
|
|
margin-inline-end: 0.2rem;
|
|
|
|
white-space: pre-wrap;
|
|
|
|
}
|
|
|
|
.item button {
|
|
|
|
line-height: 0.7;
|
|
|
|
}
|
|
|
|
</style>
|