Git-Auto-Deploy / web /src /components /form /KeyValueEditor.vue
AUXteam's picture
Upload folder using huggingface_hub
8d21f7c verified
<template>
<div class="flex flex-col gap-2">
<div v-for="(item, index) in displayItems" :key="index" class="flex gap-4">
<TextField
:id="`${id}-key-${index}`"
:model-value="item.key"
:placeholder="keyPlaceholder"
:class="{
'bg-red-100 dark:bg-red-900':
isDuplicateKey(item.key, index) || (item.key === '' && index !== displayItems.length - 1),
}"
@update:model-value="updateItem(index, 'key', $event)"
/>
<TextField
:id="`${id}-value-${index}`"
:model-value="item.value"
:placeholder="valuePlaceholder"
@update:model-value="updateItem(index, 'value', $event)"
/>
<div class="w-10 shrink-0">
<Button
v-if="index !== displayItems.length - 1"
type="button"
color="red"
class="ml-auto"
:title="deleteTitle"
@click="deleteItem(index)"
>
<Icon name="close" />
</Button>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue';
import Button from '~/components/atomic/Button.vue';
import Icon from '~/components/atomic/Icon.vue';
import TextField from '~/components/form/TextField.vue';
const props = defineProps<{
modelValue: Record<string, string>;
id?: string;
keyPlaceholder?: string;
valuePlaceholder?: string;
deleteTitle?: string;
}>();
const emit = defineEmits<{
(e: 'update:modelValue', value: Record<string, string>): void;
(e: 'update:isValid', value: boolean): void;
}>();
const items = ref(Object.entries(props.modelValue).map(([key, value]) => ({ key, value })));
const displayItems = computed(() => {
if (items.value.length === 0 || items.value.at(-1)?.key !== '') {
return [...items.value, { key: '', value: '' }];
}
return items.value;
});
function isDuplicateKey(key: string, index: number): boolean {
return items.value.some((item, i) => item.key === key && i !== index && key !== '');
}
function checkValidity() {
const isValid = items.value.every(
(item, idx) => !isDuplicateKey(item.key, idx) && (item.key !== '' || idx === items.value.length - 1),
);
emit('update:isValid', isValid);
}
function updateItem(index: number, field: 'key' | 'value', value: string) {
const newItems = [...items.value];
if (index === newItems.length) {
newItems.push({ key: '', value: '' });
}
newItems[index][field] = value;
items.value = newItems;
const newValue = Object.fromEntries(
newItems
.filter((item) => item.key !== '' && !isDuplicateKey(item.key, newItems.indexOf(item)))
.map((item) => [item.key, item.value]),
);
emit('update:modelValue', newValue);
checkValidity();
}
function deleteItem(index: number) {
items.value = items.value.filter((_, i) => i !== index);
const newValue = Object.fromEntries(
items.value
.filter((item) => item.key !== '' && !isDuplicateKey(item.key, items.value.indexOf(item)))
.map((item) => [item.key, item.value]),
);
emit('update:modelValue', newValue);
checkValidity();
}
</script>