adrema/resources/js/components/form/Text.vue

155 lines
3.6 KiB
Vue
Raw Normal View History

2021-04-10 19:45:11 +02:00
<template>
2024-06-28 14:04:20 +02:00
<label class="flex flex-col group" :for="id" :class="sizeClass(size)">
<f-label v-if="label" :required="required" :value="label"></f-label>
2024-06-28 10:23:42 +02:00
<div class="relative flex-none flex">
<input
2024-06-28 12:43:05 +02:00
:id="id"
2024-06-28 10:23:42 +02:00
:type="type"
:value="transformedValue"
:disabled="disabled"
placeholder=""
:min="min"
:max="max"
2024-06-28 13:43:38 +02:00
:class="[fieldHeight, fieldAppearance, paddingX]"
class="w-full"
2024-06-28 10:23:42 +02:00
@input="onInput"
@change="onChange"
2024-06-28 11:49:47 +02:00
@focus="focus = true"
@blur="focus = false"
2024-06-28 10:23:42 +02:00
/>
2024-06-28 13:43:38 +02:00
<f-hint v-if="hint" :value="hint"></f-hint>
2021-04-10 19:45:11 +02:00
</div>
</label>
</template>
2024-06-28 11:49:47 +02:00
<script setup>
2021-04-10 19:45:11 +02:00
import wNumb from 'wnumb';
2024-06-28 11:49:47 +02:00
import {ref, computed} from 'vue';
2024-06-28 13:43:38 +02:00
import useFieldSize from '../../composables/useFieldSize';
2024-06-28 14:04:20 +02:00
const {fieldHeight, fieldAppearance, paddingX, sizeClass} = useFieldSize();
2024-06-28 11:49:47 +02:00
const emit = defineEmits(['update:modelValue']);
2021-04-10 19:45:11 +02:00
var numb = {
natural: wNumb({
mark: '',
thousand: '',
decimals: 0,
2024-06-27 21:42:47 +02:00
decoder: (a) => a * 100,
encoder: (a) => a / 100,
2021-08-22 16:15:16 +02:00
}),
2021-04-10 19:45:11 +02:00
area: wNumb({
mark: ',',
thousand: '',
decimals: 2,
2024-06-27 21:42:47 +02:00
decoder: (a) => a * 100,
encoder: (a) => a / 100,
}),
2021-04-10 19:45:11 +02:00
};
var transformers = {
none: {
display: {
2024-06-27 21:42:47 +02:00
to: (v) => v,
from: (v) => v,
2021-04-10 19:45:11 +02:00
},
edit: {
2024-06-27 21:42:47 +02:00
to: (v) => v,
from: (v) => v,
},
2021-04-10 19:45:11 +02:00
},
area: {
display: {
2024-06-27 21:42:47 +02:00
to: (v) => (v === null ? '' : numb.area.to(v)),
from: (v) => (v === '' ? null : numb.area.from(v)),
2021-04-10 19:45:11 +02:00
},
edit: {
to(v) {
if (v === null) {
return '';
}
if (Math.round(v / 100) * 100 === v) {
2024-06-27 21:42:47 +02:00
return numb.natural.to(v);
}
2024-06-27 21:42:47 +02:00
return numb.area.to(v);
2021-08-22 16:15:16 +02:00
},
from(v) {
if (v === '') {
return null;
}
if (v.indexOf(',') === -1) {
2024-06-27 21:42:47 +02:00
return numb.natural.from(v);
}
2021-08-22 16:15:16 +02:00
2024-06-27 21:42:47 +02:00
return numb.area.from(v);
},
},
},
2021-04-10 19:45:11 +02:00
};
2024-06-28 11:49:47 +02:00
const props = defineProps({
mode: {
type: String,
default: () => 'none',
2021-04-10 19:45:11 +02:00
},
2024-06-28 11:49:47 +02:00
required: {
type: Boolean,
default: () => false,
2021-04-10 19:45:11 +02:00
},
2024-06-28 11:49:47 +02:00
size: {
type: String,
default: () => 'base',
2021-04-10 19:45:11 +02:00
},
2024-06-28 11:49:47 +02:00
id: {
type: String,
required: true,
},
2024-06-28 11:49:47 +02:00
hint: {
type: String,
default: () => '',
2023-12-30 22:21:08 +01:00
},
2024-06-28 11:49:47 +02:00
modelValue: {
2024-06-28 12:45:43 +02:00
validator: (v) => typeof v === 'string' || v === null,
2024-06-28 12:43:05 +02:00
required: true,
2024-06-28 11:49:47 +02:00
},
label: {
type: String,
default: () => '',
},
type: {
type: String,
default: () => 'text',
},
disabled: {
default: () => false,
type: Boolean,
},
min: {
type: Number,
default: () => undefined,
},
max: {
type: Number,
default: () => undefined,
},
});
const focus = ref(false);
2021-04-10 19:45:11 +02:00
2024-06-28 11:49:47 +02:00
const transformedValue = computed({
get: () => transformers[props.mode][focus.value ? 'edit' : 'display'].to(props.modelValue),
set: (v) => emit('update:modelValue', transformers[props.mode][focus.value ? 'edit' : 'display'].from(v)),
});
function onChange(v) {
if (props.mode !== 'none') {
transformedValue.value = v.target.value;
}
2021-04-10 19:45:11 +02:00
}
2024-06-28 11:49:47 +02:00
function onInput(v) {
if (props.mode === 'none') {
transformedValue.value = v.target.value;
}
}
</script>