71 lines
1.8 KiB
Vue
71 lines
1.8 KiB
Vue
<template>
|
|
<div
|
|
class="mx-2 grid grid-cols-2 items-center border-b-2 border-gray-100 py-2 last:border-b-0"
|
|
:key="key"
|
|
>
|
|
<label :for="key">{{ prop.title }}</label>
|
|
<input
|
|
v-if="prop.type === 'string'"
|
|
:class="classes"
|
|
:id="key"
|
|
type="text"
|
|
:value="value"
|
|
@input="emit('update', ($event.target as HTMLInputElement)?.value)"
|
|
/>
|
|
<ColorInput
|
|
v-else-if="prop.type === 'color'"
|
|
:for-id="key"
|
|
:model-value="(value as string)"
|
|
@update:model-value="(newValue) => emit('update', newValue)"
|
|
/>
|
|
<input
|
|
v-else-if="prop.type === 'number'"
|
|
:class="classes"
|
|
:id="key"
|
|
type="number"
|
|
:value="value"
|
|
@input="emit('update', ($event.target as HTMLInputElement)?.value)"
|
|
/>
|
|
<input
|
|
v-else-if="prop.type === 'boolean'"
|
|
:class="classes"
|
|
:id="key"
|
|
type="checkbox"
|
|
:checked="(value as boolean)"
|
|
@input="emit('update', ($event.target as HTMLInputElement)?.checked)"
|
|
/>
|
|
<select
|
|
v-else-if="prop.type === 'select'"
|
|
:class="classes"
|
|
:id="key"
|
|
:value="value"
|
|
@input="emit('update', ($event.target as HTMLInputElement)?.value)"
|
|
>
|
|
<option v-for="option of prop.options" :value="option.value">
|
|
{{ option.title }}
|
|
</option>
|
|
</select>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed } from '@vue/reactivity';
|
|
import ColorInput from '../ColorInput.vue';
|
|
import { ObjectProperty } from './interfaces/properties.interfaces';
|
|
|
|
const props = defineProps<{
|
|
id: number;
|
|
prop: ObjectProperty;
|
|
value: unknown;
|
|
}>();
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'update', value: unknown): void;
|
|
}>();
|
|
|
|
const key = computed(() => `${props.prop.key}-${props.id}`);
|
|
const classes = [
|
|
'px-1 py-1 focus:ring-2 focus:ring-blue-200 border-gray-300 rounded-sm',
|
|
];
|
|
</script>
|