62 lines
1.6 KiB
Vue
62 lines
1.6 KiB
Vue
<script setup>
|
|
import { computed, ref } from 'vue'
|
|
|
|
const props = defineProps({
|
|
modelValue: { type: String, default: null },
|
|
defaultColor: { type: String, default: '#000000' },
|
|
clearLabel: { type: String, default: 'Počisti' },
|
|
selectLabel: { type: String, default: 'Izberi barvo' },
|
|
})
|
|
|
|
const emit = defineEmits(['update:modelValue'])
|
|
|
|
const inputRef = ref(null)
|
|
|
|
const inputValue = computed(() => props.modelValue || props.defaultColor)
|
|
const hasValue = computed(() => !!props.modelValue)
|
|
|
|
function onInput(e) {
|
|
const val = e.target.value
|
|
emit('update:modelValue', val)
|
|
}
|
|
|
|
function clear() {
|
|
emit('update:modelValue', null)
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="flex items-center gap-2">
|
|
<div
|
|
class="relative px-2 py-1 rounded border border-gray-300 hover:bg-gray-50 inline-flex items-center gap-2 select-none"
|
|
>
|
|
<span
|
|
v-if="hasValue"
|
|
class="inline-block h-4 w-4 rounded"
|
|
:style="{ backgroundColor: modelValue }"
|
|
/>
|
|
<span class="text-sm text-gray-700">{{ hasValue ? modelValue : selectLabel }}</span>
|
|
|
|
<!-- Keep the same input element always mounted, positioned over the trigger to anchor the native picker -->
|
|
<input
|
|
ref="inputRef"
|
|
type="color"
|
|
class="absolute inset-0 opacity-0 cursor-pointer"
|
|
:value="inputValue"
|
|
@input="onInput"
|
|
aria-label="Color picker"
|
|
/>
|
|
</div>
|
|
|
|
<button
|
|
v-if="hasValue"
|
|
type="button"
|
|
class="px-2 py-1 rounded border border-gray-300 hover:bg-gray-50 text-sm"
|
|
@click="clear"
|
|
>
|
|
{{ clearLabel }}
|
|
</button>
|
|
</div>
|
|
|
|
</template>
|