PronounsPage/components/IconSelector.vue

70 lines
1.9 KiB
Vue

<script setup lang="ts">
import iconsMetadata from '~/src/iconsMetadata.ts';
import type { IconMetadata } from '~/src/iconsMetadata.ts';
const props = withDefaults(defineProps<{
styles?: IconMetadata['styles'];
skipIcons?: string[];
}>(), {
styles: () => ['light'],
skipIcons: () => [],
});
const emit = defineEmits<{
change: [icon: string];
}>();
const filter = ref('');
const showAll = ref(false);
const displayLimit = 27;
const matches = (icon: IconMetadata) => {
return !props.skipIcons.includes(icon.name) &&
icon.styles.filter((v) => props.styles.includes(v)).length > 0 &&
(
filter.value === '' ||
icon.searchTerms.filter((t) => t.includes(filter.value.toLowerCase())).length > 0
)
;
};
const visibleIcons = computed(() => {
return iconsMetadata.filter(matches).slice(0, showAll.value ? undefined : displayLimit);
});
const filterBar = useTemplateRef('filterBar');
onMounted(() => {
filterBar.value?.focus();
});
</script>
<template>
<div class="bg-light border rounded">
<FilterBar ref="filterBar" v-model="filter" />
<ul class="list-unstyled icons-list p-2 text-center">
<li
v-for="icon in visibleIcons"
:key="icon.name"
class="list-inline-item"
>
<button type="button" class="btn btn-outline-dark border-0 my-2" @click="emit('change', icon.name)">
<Icon :v="icon.name" />
</button>
</li>
<li v-if="!showAll && visibleIcons.length >= displayLimit" class="list-inline-item">
<button type="button" class="btn btn-outline-dark border-0 my-2" @click="showAll = true">
<T>crud.loadAll</T>
</button>
</li>
</ul>
</div>
</template>
<style lang="scss" scoped>
.icons-list {
height: 200px;
overflow-y: auto;
}
</style>