Refactor inpus

This commit is contained in:
Julien Nahum
2023-12-01 21:24:38 +01:00
parent 47653ebe64
commit 0eea59c5ba
33 changed files with 285 additions and 383 deletions

View File

@@ -1,10 +1,10 @@
<template>
<input-wrapper v-bind="$props">
<input-wrapper v-bind="inputWrapperProps">
<template #label>
<span />
</template>
<v-checkbox :id="id?id:name" v-model="compVal" :disabled="disabled" :name="name">
<v-checkbox :id="id?id:name" v-model="compVal" :disabled="disabled?true:null" :name="name">
<slot name="label">
{{ label }} <span v-if="required" class="text-red-500 required-dot">*</span>
</slot>
@@ -34,18 +34,8 @@ export default {
},
setup (props, context) {
const {
compVal,
inputStyle,
hasValidation,
hasError
} = useFormInput(props, context)
return {
compVal,
inputStyle,
hasValidation,
hasError
...useFormInput(props, context)
}
},

View File

@@ -1,6 +1,6 @@
<template>
<input-wrapper
v-bind="$props"
v-bind="inputWrapperProps"
>
<template #label>
<slot name="label" />
@@ -13,7 +13,7 @@
<div
:class="[theme.CodeInput.input,{ '!ring-red-500 !ring-2': hasError, '!cursor-not-allowed !bg-gray-200':disabled }]"
>
<codemirror :id="id?id:name" v-model="compVal" :disabled="disabled"
<codemirror :id="id?id:name" v-model="compVal" :disabled="disabled?true:null"
:options="cmOptions"
:style="inputStyle" :name="name"
:placeholder="placeholder"
@@ -44,18 +44,8 @@ export default {
},
setup (props, context) {
const {
compVal,
inputStyle,
hasValidation,
hasError
} = useFormInput(props, context)
return {
compVal,
inputStyle,
hasValidation,
hasError
...useFormInput(props, context)
}
},

View File

@@ -1,11 +1,11 @@
<template>
<input-wrapper v-bind="$props">
<input-wrapper v-bind="inputWrapperProps">
<template #label>
<span />
</template>
<div class="flex items-center">
<input :id="id?id:name" v-model="compVal" :disabled="disabled"
<input :id="id?id:name" v-model="compVal" :disabled="disabled?true:null"
type="color" class="mr-2"
:name="name"
>
@@ -37,13 +37,8 @@ export default {
},
setup (props, context) {
const { compVal, inputStyle, hasValidation, hasError } = useFormInput(props, context)
return {
compVal,
inputStyle,
hasValidation,
hasError
...useFormInput(props, context)
}
}
}

View File

@@ -1,32 +1,36 @@
<template>
<input-wrapper
v-bind="$props"
v-bind="inputWrapperProps"
>
<template #label>
<slot name="label" />
</template>
<div class="flex" v-if="!dateRange">
<input :type="useTime ? 'datetime-local' : 'date'" :id="id?id:name" v-model="fromDate" :class="inputClasses"
:disabled="disabled"
<div v-if="!dateRange" class="flex">
<input :id="id?id:name" v-model="fromDate" :type="useTime ? 'datetime-local' : 'date'" :class="inputClasses"
:disabled="disabled?true:null"
:style="inputStyle" :name="name" data-date-format="YYYY-MM-DD"
:min="setMinDate" :max="setMaxDate"
/>
>
</div>
<div :class="inputClasses" v-else>
<div v-else :class="inputClasses">
<div class="flex -mx-2">
<p class="text-gray-900 px-4">From</p>
<input :type="useTime ? 'datetime-local' : 'date'" :id="id?id:name" v-model="fromDate" :disabled="disabled"
<p class="text-gray-900 px-4">
From
</p>
<input :id="id?id:name" v-model="fromDate" :type="useTime ? 'datetime-local' : 'date'" :disabled="disabled?true:null"
:style="inputStyle" :name="name" data-date-format="YYYY-MM-DD"
class="flex-grow border-transparent focus:outline-none "
:min="setMinDate" :max="setMaxDate"
/>
<p class="text-gray-900 px-4">To</p>
<input v-if="dateRange" :type="useTime ? 'datetime-local' : 'date'" :id="id?id:name" v-model="toDate"
:disabled="disabled"
>
<p class="text-gray-900 px-4">
To
</p>
<input v-if="dateRange" :id="id?id:name" v-model="toDate" :type="useTime ? 'datetime-local' : 'date'"
:disabled="disabled?true:null"
:style="inputStyle" :name="name" class="flex-grow border-transparent focus:outline-none"
:min="setMinDate" :max="setMaxDate"
/>
>
</div>
</div>
@@ -42,7 +46,7 @@
<script>
import { inputProps, useFormInput } from './useFormInput.js'
import InputWrapper from './components/InputWrapper.vue'
import {fixedClasses} from '../../plugins/config/vue-tailwind/datePicker.js'
import { fixedClasses } from '../../plugins/config/vue-tailwind/datePicker.js'
export default {
name: 'DateInput',
@@ -51,25 +55,15 @@ export default {
props: {
...inputProps,
withTime: {type: Boolean, default: false},
dateRange: {type: Boolean, default: false},
disablePastDates: {type: Boolean, default: false},
disableFutureDates: {type: Boolean, default: false}
withTime: { type: Boolean, default: false },
dateRange: { type: Boolean, default: false },
disablePastDates: { type: Boolean, default: false },
disableFutureDates: { type: Boolean, default: false }
},
setup (props, context) {
const {
compVal,
inputStyle,
hasValidation,
hasError
} = useFormInput(props, context)
return {
compVal,
inputStyle,
hasValidation,
hasError
...useFormInput(props, context)
}
},
@@ -80,22 +74,22 @@ export default {
}),
computed: {
inputClasses() {
inputClasses () {
let str = 'border border-gray-300 dark:bg-notion-dark-light dark:border-gray-600 dark:placeholder-gray-500 dark:text-gray-300 flex-1 focus:border-transparent focus:outline-none focus:ring-2 focus:ring-opacity-100 placeholder-gray-400 px-4 py-2 rounded-lg shadow-sm text-base text-black text-gray-700'
str += this.dateRange ? ' w-50' : ' w-full'
str += this.disabled ? ' !cursor-not-allowed !bg-gray-200' : ''
return str
},
useTime() {
useTime () {
return this.withTime && !this.dateRange
},
setMinDate() {
setMinDate () {
if (this.disablePastDates) {
return new Date().toISOString().split('T')[0]
}
return false
},
setMaxDate() {
setMaxDate () {
if (this.disableFutureDates) {
return new Date().toISOString().split('T')[0]
}
@@ -105,16 +99,16 @@ export default {
watch: {
color: {
handler() {
handler () {
this.setInputColor()
},
immediate: true
},
fromDate: {
handler(val) {
handler (val) {
if (this.dateRange) {
if (!Array.isArray(this.compVal)) {
this.compVal = [];
this.compVal = []
}
this.compVal[0] = this.dateToUTC(val)
} else {
@@ -124,10 +118,10 @@ export default {
immediate: false
},
toDate: {
handler(val) {
handler (val) {
if (this.dateRange) {
if (!Array.isArray(this.compVal)) {
this.compVal = [null];
this.compVal = [null]
}
this.compVal[1] = this.dateToUTC(val)
} else {
@@ -138,7 +132,7 @@ export default {
}
},
mounted() {
mounted () {
if (this.compVal) {
if (Array.isArray(this.compVal)) {
this.fromDate = this.compVal[0] ?? null
@@ -158,17 +152,17 @@ export default {
* @param event
* @returns {boolean}
*/
onEnterPress(event) {
onEnterPress (event) {
event.preventDefault()
return false
},
setInputColor() {
setInputColor () {
if (this.$refs.datepicker) {
const dateInput = this.$refs.datepicker.$el.getElementsByTagName('input')[0]
dateInput.style.setProperty('--tw-ring-color', this.color)
}
},
dateToUTC(val) {
dateToUTC (val) {
if (!val) {
return null
}
@@ -177,7 +171,7 @@ export default {
}
return new Date(val).toISOString()
},
dateToLocal(val) {
dateToLocal (val) {
if (!val) {
return null
}
@@ -187,7 +181,7 @@ export default {
String(dateObj.getDate()).padStart(2, '0')
if (this.useTime) {
dateStr += 'T' + String(dateObj.getHours()).padStart(2, '0') + ':' +
String(dateObj.getMinutes()).padStart(2, '0');
String(dateObj.getMinutes()).padStart(2, '0')
}
return dateStr
}

View File

@@ -1,6 +1,6 @@
<template>
<input-wrapper
v-bind="$props"
v-bind="inputWrapperProps"
>
<template #label>
<slot name="label" />
@@ -94,18 +94,8 @@ export default {
},
setup (props, context) {
const {
compVal,
inputStyle,
hasValidation,
hasError
} = useFormInput(props, context)
return {
compVal,
inputStyle,
hasValidation,
hasError
...useFormInput(props, context)
}
},

View File

@@ -1,6 +1,6 @@
<template>
<input-wrapper
v-bind="$props"
v-bind="inputWrapperProps"
>
<template #label>
<slot name="label" />
@@ -51,18 +51,8 @@ export default {
multiple: { type: Boolean, default: false }
},
setup (props, context) {
const {
compVal,
inputStyle,
hasValidation,
hasError
} = useFormInput(props, context)
return {
compVal,
inputStyle,
hasValidation,
hasError
...useFormInput(props, context)
}
},
data () {
@@ -71,10 +61,10 @@ export default {
computed: {},
methods: {
onSelect (value) {
if(this.disabled){
if (this.disabled) {
return
}
if (this.multiple) {
const emitValue = Array.isArray(this.compVal) ? [...this.compVal] : []

View File

@@ -1,6 +1,6 @@
<template>
<input-wrapper
v-bind="$props"
v-bind="inputWrapperProps"
>
<template #label>
<slot name="label" />
@@ -121,18 +121,8 @@ export default {
},
setup (props, context) {
const {
compVal,
inputStyle,
hasValidation,
hasError
} = useFormInput(props, context)
return {
compVal,
inputStyle,
hasValidation,
hasError
...useFormInput(props, context)
}
},
@@ -155,8 +145,8 @@ export default {
showUploadModal: {
handler (val) {
document.removeEventListener('paste', this.onUploadPasteEvent)
if(this.showUploadModal){
document.addEventListener("paste", this.onUploadPasteEvent)
if (this.showUploadModal) {
document.addEventListener('paste', this.onUploadPasteEvent)
}
}
}
@@ -176,7 +166,7 @@ export default {
this.droppedFiles(e.dataTransfer.files)
},
onUploadPasteEvent (e) {
if(!this.showUploadModal) return
if (!this.showUploadModal) return
this.uploadDragoverEvent = false
this.uploadDragoverTracking = false
this.droppedFiles(e.clipboardData.files)

View File

@@ -1,6 +1,6 @@
<template>
<input-wrapper
v-bind="$props"
v-bind="inputWrapperProps"
>
<template #label>
<slot name="label" />
@@ -9,7 +9,7 @@
<div :id="id ? id : name" :name="name" :style="inputStyle" class="flex items-center">
<v-select v-model="selectedCountryCode" class="w-[130px]" dropdown-class="w-[300px]" input-class="rounded-r-none"
:data="countries"
:disabled="disabled || countries.length===1" :searchable="true" :search-keys="['name']" :option-key="'code'" :color="color"
:disabled="(disabled || countries.length===1)?true:null" :searchable="true" :search-keys="['name']" :option-key="'code'" :color="color"
:has-error="hasValidation && form.errors.has(name)"
:placeholder="'Select a country'" :uppercase-labels="true" :theme="theme" @update:model-value="onChangeCountryCode"
>
@@ -27,9 +27,9 @@
</div>
</template>
</v-select>
<input v-model="inputVal" type="text" class="inline-flex-grow !border-l-0 !rounded-l-none" :disabled="disabled"
:class="[theme.default.input, { '!ring-red-500 !ring-2': hasValidation && form.errors.has(name), '!cursor-not-allowed !bg-gray-200': disabled }]"
:placeholder="placeholder" :style="inputStyle" @update:model-value="onInput"
<input v-model="inputVal" type="text" class="inline-flex-grow !border-l-0 !rounded-l-none" :disabled="disabled?true:null"
:class="[theme.default.input, { '!ring-red-500 !ring-2': hasValidation && form.errors.has(name), '!cursor-not-allowed !bg-gray-200': disabled }]"
:placeholder="placeholder" :style="inputStyle" @update:model-value="onInput"
>
</div>
@@ -40,7 +40,6 @@
<template #error>
<slot name="error" />
</template>
</input-wrapper>
</template>
@@ -61,18 +60,8 @@ export default {
},
setup (props, context) {
const {
compVal,
inputStyle,
hasValidation,
hasError
} = useFormInput(props, context)
return {
compVal,
inputStyle,
hasValidation,
hasError
...useFormInput(props, context)
}
},

View File

@@ -1,12 +1,11 @@
<template>
<input-wrapper
v-bind="$props"
v-bind="inputWrapperProps"
>
<template #label>
<slot name="label" />
</template>
<div class="stars-outer">
<div v-for="i in numberOfStars" :key="i"
class="cursor-pointer inline-block text-gray-200 dark:text-gray-800"
@@ -46,22 +45,11 @@ export default {
},
setup (props, context) {
const {
compVal,
inputStyle,
hasValidation,
hasError
} = useFormInput(props, context)
return {
compVal,
inputStyle,
hasValidation,
hasError
...useFormInput(props, context)
}
},
data () {
return {
hoverRating: -1

View File

@@ -1,12 +1,12 @@
<template>
<input-wrapper
v-bind="$props"
v-bind="inputWrapperProps"
>
<template #label>
<slot name="label" />
</template>
<vue-editor :id="id?id:name" ref="editor" v-model="compVal" :disabled="disabled"
<vue-editor :id="id?id:name" ref="editor" v-model="compVal" :disabled="disabled?true:null"
:placeholder="placeholder" :class="[{ '!ring-red-500 !ring-2': hasValidation && form.errors.has(name), '!cursor-not-allowed !bg-gray-200':disabled }, theme.RichTextAreaInput.input]"
:editor-toolbar="editorToolbar" class="rich-editor resize-y"
:style="inputStyle"
@@ -41,25 +41,15 @@ export default {
[{ header: 1 }, { header: 2 }],
['bold', 'italic', 'underline', 'link'],
[{ list: 'ordered' }, { list: 'bullet' }],
[{color: []}]
[{ color: [] }]
]
}
}
},
setup (props, context) {
const {
compVal,
inputStyle,
hasValidation,
hasError
} = useFormInput(props, context)
return {
compVal,
inputStyle,
hasValidation,
hasError
...useFormInput(props, context)
}
}

View File

@@ -1,6 +1,6 @@
<template>
<input-wrapper
v-bind="$props"
v-bind="inputWrapperProps"
>
<template #label>
<slot name="label" />
@@ -41,18 +41,8 @@ export default {
},
setup (props, context) {
const {
compVal,
inputStyle,
hasValidation,
hasError
} = useFormInput(props, context)
return {
compVal,
inputStyle,
hasValidation,
hasError
...useFormInput(props, context)
}
},
@@ -62,7 +52,7 @@ export default {
computed: {
scaleList () {
let list = []
const list = []
for (let i = this.minScale; i <= this.maxScale; i += this.stepScale) {
list.push(i)
}
@@ -89,7 +79,7 @@ export default {
},
mounted () {
if (this.compVal && typeof this.compVal === 'string'){
if (this.compVal && typeof this.compVal === 'string') {
this.compVal = parseInt(this.compVal)
}
},

View File

@@ -1,6 +1,6 @@
<template>
<input-wrapper
v-bind="$props"
v-bind="inputWrapperProps"
>
<template #label>
<slot name="label" />
@@ -21,7 +21,7 @@
:theme="theme"
:has-error="hasValidation && form.errors.has(name)"
:allow-creation="allowCreation"
:disabled="disabled"
:disabled="disabled?true:null"
:help="help"
:help-position="helpPosition"
@@ -97,20 +97,11 @@ export default {
},
setup (props, context) {
const {
compVal,
inputStyle,
hasValidation,
hasError
} = useFormInput(props, context)
return {
compVal,
inputStyle,
hasValidation,
hasError
...useFormInput(props, context)
}
},
data () {
return {
additionalOptions: []

View File

@@ -1,6 +1,6 @@
<template>
<input-wrapper
v-bind="$props"
v-bind="inputWrapperProps"
>
<template #label>
<slot name="label" />
@@ -18,7 +18,7 @@
<a :class="theme.default.help" href="#" @click.prevent="clear">Clear</a>
</small>
</template>
<template #error>
<slot name="error" />
</template>
@@ -39,18 +39,8 @@ export default {
},
setup (props, context) {
const {
compVal,
inputStyle,
hasValidation,
hasError
} = useFormInput(props, context)
return {
compVal,
inputStyle,
hasValidation,
hasError
...useFormInput(props, context)
}
},

View File

@@ -1,12 +1,12 @@
<template>
<input-wrapper
v-bind="$props"
v-bind="inputWrapperProps"
>
<template #label>
<slot name="label" />
</template>
<textarea :id="id?id:name" v-model="compVal" :disabled="disabled"
<textarea :id="id?id:name" v-model="compVal" :disabled="disabled?true:null"
:class="[theme.default.input,{ '!ring-red-500 !ring-2': hasValidation && form.errors.has(name), '!cursor-not-allowed !bg-gray-200':disabled }]"
class="resize-y"
:name="name" :style="inputStyle"
@@ -16,7 +16,7 @@
<template v-if="maxCharLimit && showCharLimit" #bottom_after_help>
<small :class="theme.default.help">
{{ charCount }}/{{ maxCharLimit }}
{{ charCount }}/{{ maxCharLimit }}
</small>
</template>
@@ -38,25 +38,17 @@ export default {
props: {
...inputProps,
maxCharLimit: { type: Number, required: false, default: null },
showCharLimit: { type: Boolean, required: false, default: false },
showCharLimit: { type: Boolean, required: false, default: false }
},
setup (props, context) {
const {
compVal,
inputStyle,
hasValidation,
hasError
} = useFormInput(props, context)
setup (props, context) {
return {
compVal,
inputStyle,
hasValidation,
hasError
...useFormInput(props, context)
}
},
computed: {
charCount() {
charCount () {
return (this.compVal) ? this.compVal.length : 0
}
}

View File

@@ -1,12 +1,12 @@
<template>
<input-wrapper
v-bind="$props"
v-bind="inputWrapperProps"
>
<template #label>
<slot name="label" />
</template>
<input :id="id?id:name" v-model="compVal" :disabled="disabled"
<input :id="id?id:name" v-model="compVal" :disabled="disabled?true:null"
:type="nativeType"
:pattern="pattern"
:style="inputStyle"
@@ -18,7 +18,7 @@
<template v-if="maxCharLimit && showCharLimit" #bottom_after_help>
<small :class="theme.default.help">
{{ charCount }}/{{ maxCharLimit }}
{{ charCount }}/{{ maxCharLimit }}
</small>
</template>
@@ -48,13 +48,6 @@ export default {
},
setup (props, context) {
const {
compVal,
inputStyle,
hasValidation,
hasError
} = useFormInput(props, context, props.nativeType === 'file' ? 'file-' : null)
const onChange = (event) => {
if (props.nativeType !== 'file') return
@@ -69,10 +62,9 @@ export default {
}
return {
compVal,
inputStyle,
hasValidation,
hasError
...useFormInput(props, context, props.nativeType === 'file' ? 'file-' : null),
onEnterPress,
onChange
}
},
computed: {

View File

@@ -1,11 +1,11 @@
<template>
<input-wrapper v-bind="$props">
<input-wrapper v-bind="inputWrapperProps">
<template #label>
<span />
</template>
<div class="flex">
<v-switch :id="id?id:name" v-model="compVal" class="inline-block mr-2" :disabled="disabled" />
<v-switch :id="id?id:name" v-model="compVal" class="inline-block mr-2" :disabled="disabled?true:null" />
<slot name="label">
<span>{{ label }} <span v-if="required" class="text-red-500 required-dot">*</span></span>
</slot>
@@ -34,13 +34,8 @@ export default {
},
setup (props, context) {
const { compVal, inputStyle, hasValidation, hasError } = useFormInput(props, context)
return {
compVal,
inputStyle,
hasValidation,
hasError
...useFormInput(props, context)
}
},

View File

@@ -38,12 +38,12 @@ export default {
props: {
id: { type: String, required: false },
name: { type: String, required: false },
theme: { type: Object, required: true },
label: { type: String, required: false },
form: { type: Object, required: false },
theme: { type: Object, required: true },
wrapperClass: { type: String, required: false },
inputStyle: { type: Object, required: false },
help: { type: String, required: false },
label: { type: String, required: false },
helpPosition: { type: String, default: 'below_input' },
uppercaseLabels: { type: Boolean, default: true },
hideFieldName: { type: Boolean, default: true },

View File

@@ -7,7 +7,7 @@
type="checkbox"
:class="sizeClasses"
class="rounded border-gray-500 cursor-pointer"
:disabled="disabled"
:disabled="disabled?true:null"
@click="handleClick"
>
<label :for="id || name" class="text-gray-700 dark:text-gray-300 ml-2" :class="{'!cursor-not-allowed':disabled}">

View File

@@ -6,6 +6,7 @@ export const inputProps = {
name: { type: String, required: true },
label: { type: String, required: false },
form: { type: Object, required: false },
theme: { type: Object, default: () => themes.default },
modelValue: { required: false },
required: { type: Boolean, default: false },
disabled: { type: Boolean, default: false },
@@ -14,7 +15,6 @@ export const inputProps = {
hideFieldName: { type: Boolean, default: false },
help: { type: String, default: null },
helpPosition: { type: String, default: 'below_input' },
theme: { type: Object, default: () => themes.default },
color: { type: String, default: '#3B82F6' },
wrapperClass: { type: String, default: 'relative mb-3' }
}
@@ -58,11 +58,21 @@ export function useFormInput (props, context, formPrefixKey = null) {
}
})
const inputWrapperProps = computed(() => {
const wrapperProps = {}
Object.keys(inputProps).forEach((key) => {
if (!['modelValue', 'disabled', 'placeholder', 'color'].includes(key)) {
wrapperProps[key] = props[key]
}
})
return wrapperProps
})
// Watch for changes in props.modelValue and update the local content
watch(
() => props.modelValue,
(newValue) => {
if (content.value !== newValue){
if (content.value !== newValue) {
content.value = newValue
}
}
@@ -72,6 +82,7 @@ export function useFormInput (props, context, formPrefixKey = null) {
compVal,
inputStyle,
hasValidation,
hasError
hasError,
inputWrapperProps
}
}