feat: Replaced class merge with tailwind-merge in Input component
This commit is contained in:
15
package-lock.json
generated
15
package-lock.json
generated
@@ -15,6 +15,7 @@
|
|||||||
"flowbite": "1.5.4",
|
"flowbite": "1.5.4",
|
||||||
"lodash-es": "4.17.21",
|
"lodash-es": "4.17.21",
|
||||||
"nanoid": "4.0.0",
|
"nanoid": "4.0.0",
|
||||||
|
"tailwind-merge": "^1.14.0",
|
||||||
"tailwindcss": "^3"
|
"tailwindcss": "^3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -4450,6 +4451,15 @@
|
|||||||
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
|
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/tailwind-merge": {
|
||||||
|
"version": "1.14.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-1.14.0.tgz",
|
||||||
|
"integrity": "sha512-3mFKyCo/MBcgyOTlrY8T7odzZFx+w+qKSMAmdFzRvqBfLlSigU6TZnlFHK0lkMwj9Bj8OYU+9yW9lmGuS0QEnQ==",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/dcastil"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tailwindcss": {
|
"node_modules/tailwindcss": {
|
||||||
"version": "3.2.4",
|
"version": "3.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz",
|
||||||
@@ -8612,6 +8622,11 @@
|
|||||||
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
|
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"tailwind-merge": {
|
||||||
|
"version": "1.14.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-1.14.0.tgz",
|
||||||
|
"integrity": "sha512-3mFKyCo/MBcgyOTlrY8T7odzZFx+w+qKSMAmdFzRvqBfLlSigU6TZnlFHK0lkMwj9Bj8OYU+9yW9lmGuS0QEnQ=="
|
||||||
|
},
|
||||||
"tailwindcss": {
|
"tailwindcss": {
|
||||||
"version": "3.2.4",
|
"version": "3.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz",
|
||||||
|
|||||||
@@ -72,6 +72,7 @@
|
|||||||
"flowbite": "1.5.4",
|
"flowbite": "1.5.4",
|
||||||
"lodash-es": "4.17.21",
|
"lodash-es": "4.17.21",
|
||||||
"nanoid": "4.0.0",
|
"nanoid": "4.0.0",
|
||||||
|
"tailwind-merge": "^1.14.0",
|
||||||
"tailwindcss": "^3"
|
"tailwindcss": "^3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@@ -5,20 +5,12 @@
|
|||||||
<div v-if="$slots.prefix" class="w-10 flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none overflow-hidden">
|
<div v-if="$slots.prefix" class="w-10 flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none overflow-hidden">
|
||||||
<slot name="prefix" />
|
<slot name="prefix" />
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input v-bind="$attrs" v-model="model" :disabled="disabled" :type="type" :required="required" :class="[inputClasses, $slots.prefix ? 'pl-10' : '']" />
|
||||||
v-bind="$attrs"
|
|
||||||
v-model="model"
|
|
||||||
:disabled="disabled"
|
|
||||||
:type="type"
|
|
||||||
:required='required'
|
|
||||||
|
|
||||||
:class="[inputClasses, $slots.prefix ? 'pl-10' : '']"
|
|
||||||
/>
|
|
||||||
<div v-if="$slots.suffix" class="absolute right-2.5 bottom-2.5">
|
<div v-if="$slots.suffix" class="absolute right-2.5 bottom-2.5">
|
||||||
<slot name="suffix" />
|
<slot name="suffix" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p v-if="$slots.validationMessage" class="mt-2 text-sm" :class="validationWrapperClasses">
|
<p v-if="$slots.validationMessage" :class="validationWrapperClasses">
|
||||||
<slot name="validationMessage" />
|
<slot name="validationMessage" />
|
||||||
</p>
|
</p>
|
||||||
<p v-if="$slots.helper" class="mt-2 text-sm text-gray-500 dark:text-gray-400">
|
<p v-if="$slots.helper" class="mt-2 text-sm text-gray-500 dark:text-gray-400">
|
||||||
@@ -31,15 +23,38 @@ import { ValidationStatus, type InputSize } from '@/components/Input/types'
|
|||||||
import { useInputClasses } from '@/components/Input/composables/useInputClasses'
|
import { useInputClasses } from '@/components/Input/composables/useInputClasses'
|
||||||
import { computed, toRefs } from 'vue'
|
import { computed, toRefs } from 'vue'
|
||||||
import { useVModel } from '@vueuse/core'
|
import { useVModel } from '@vueuse/core'
|
||||||
|
import { twMerge } from 'tailwind-merge'
|
||||||
|
|
||||||
interface InputProps {
|
interface InputProps {
|
||||||
label?: string;
|
label?: string
|
||||||
disabled?: boolean;
|
disabled?: boolean
|
||||||
type?: 'button' | 'checkbox' | 'color' | 'date' | 'datetime-local' | 'email' | 'file' | 'hidden' | 'image' | 'month' | 'number' | 'password' | 'radio' | 'range' | 'reset' | 'search' | 'submit' | 'tel' | 'text' | 'time' | 'url' | 'week';
|
type?:
|
||||||
size?: InputSize;
|
| 'button'
|
||||||
required?: boolean;
|
| 'checkbox'
|
||||||
modelValue: string;
|
| 'color'
|
||||||
validationStatus?: ValidationStatus;
|
| 'date'
|
||||||
|
| 'datetime-local'
|
||||||
|
| 'email'
|
||||||
|
| 'file'
|
||||||
|
| 'hidden'
|
||||||
|
| 'image'
|
||||||
|
| 'month'
|
||||||
|
| 'number'
|
||||||
|
| 'password'
|
||||||
|
| 'radio'
|
||||||
|
| 'range'
|
||||||
|
| 'reset'
|
||||||
|
| 'search'
|
||||||
|
| 'submit'
|
||||||
|
| 'tel'
|
||||||
|
| 'text'
|
||||||
|
| 'time'
|
||||||
|
| 'url'
|
||||||
|
| 'week'
|
||||||
|
size?: InputSize
|
||||||
|
required?: boolean
|
||||||
|
modelValue: string
|
||||||
|
validationStatus?: ValidationStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<InputProps>(), {
|
const props = withDefaults(defineProps<InputProps>(), {
|
||||||
@@ -56,5 +71,11 @@ const model = useVModel(props, 'modelValue')
|
|||||||
|
|
||||||
const { inputClasses, labelClasses } = useInputClasses(toRefs(props))
|
const { inputClasses, labelClasses } = useInputClasses(toRefs(props))
|
||||||
|
|
||||||
const validationWrapperClasses = computed(() => props.validationStatus === ValidationStatus.Success ? 'text-green-600 dark:text-green-500' : (props.validationStatus === ValidationStatus.Error ? 'text-red-600 dark:text-red-500' : ''))
|
const validationWrapperClasses = computed(() => {
|
||||||
|
return twMerge(
|
||||||
|
'mt-2 text-sm',
|
||||||
|
props.validationStatus === ValidationStatus.Success ? 'text-green-600 dark:text-green-500' : '',
|
||||||
|
props.validationStatus === ValidationStatus.Error ? 'text-red-600 dark:text-red-500' : '',
|
||||||
|
)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import type { Ref } from 'vue'
|
import type { Ref } from 'vue'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { ValidationStatus, type InputSize } from '@/components/Input/types'
|
import { ValidationStatus, type InputSize } from '@/components/Input/types'
|
||||||
import { simplifyTailwindClasses } from '@/utils/simplifyTailwindClasses'
|
import { twMerge } from 'tailwind-merge'
|
||||||
|
|
||||||
// LABEL
|
// LABEL
|
||||||
const baseLabelClasses = 'block mb-2 text-sm font-medium'
|
const baseLabelClasses = 'block mb-2 text-sm font-medium'
|
||||||
|
|
||||||
// INPUT
|
// INPUT
|
||||||
const defaultInputClasses = 'bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500'
|
const defaultInputClasses =
|
||||||
|
'bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500'
|
||||||
const disabledInputClasses = 'cursor-not-allowed bg-gray-100'
|
const disabledInputClasses = 'cursor-not-allowed bg-gray-100'
|
||||||
const inputSizeClasses: Record<InputSize, string> = {
|
const inputSizeClasses: Record<InputSize, string> = {
|
||||||
lg: 'p-4',
|
lg: 'p-4',
|
||||||
@@ -15,7 +15,8 @@ const inputSizeClasses: Record<InputSize, string> = {
|
|||||||
sm: 'p-2 text-sm',
|
sm: 'p-2 text-sm',
|
||||||
}
|
}
|
||||||
|
|
||||||
const successInputClasses = 'bg-green-50 border-green-500 dark:border-green-500 text-green-900 dark:text-green-400 placeholder-green-700 dark:placeholder-green-500 focus:ring-green-500 focus:border-green-500'
|
const successInputClasses =
|
||||||
|
'bg-green-50 border-green-500 dark:border-green-500 text-green-900 dark:text-green-400 placeholder-green-700 dark:placeholder-green-500 focus:ring-green-500 focus:border-green-500'
|
||||||
const errorInputClasses = 'bg-red-50 border-red-500 text-red-900 placeholder-red-700 focus:ring-red-500 focus:border-red-500 dark:text-red-500 dark:placeholder-red-500 dark:border-red-500'
|
const errorInputClasses = 'bg-red-50 border-red-500 text-red-900 placeholder-red-700 focus:ring-red-500 focus:border-red-500 dark:text-red-500 dark:placeholder-red-500 dark:border-red-500'
|
||||||
|
|
||||||
export type UseInputClassesProps = {
|
export type UseInputClassesProps = {
|
||||||
@@ -30,14 +31,14 @@ export function useInputClasses(props: UseInputClassesProps): {
|
|||||||
} {
|
} {
|
||||||
const inputClasses = computed(() => {
|
const inputClasses = computed(() => {
|
||||||
const vs = props.validationStatus.value
|
const vs = props.validationStatus.value
|
||||||
const classByStatus = vs === ValidationStatus.Success ? successInputClasses : (vs == ValidationStatus.Error ? errorInputClasses : '')
|
const classByStatus = vs === ValidationStatus.Success ? successInputClasses : vs == ValidationStatus.Error ? errorInputClasses : ''
|
||||||
return simplifyTailwindClasses(defaultInputClasses, classByStatus, inputSizeClasses[props.size.value], props.disabled.value ? disabledInputClasses : '')
|
return twMerge(defaultInputClasses, classByStatus, inputSizeClasses[props.size.value], props.disabled.value ? disabledInputClasses : '')
|
||||||
})
|
})
|
||||||
|
|
||||||
const labelClasses = computed(() => {
|
const labelClasses = computed(() => {
|
||||||
const vs = props.validationStatus.value
|
const vs = props.validationStatus.value
|
||||||
const classByStatus = vs === ValidationStatus.Success ? 'text-green-700 dark:text-green-500' : (vs == ValidationStatus.Error ? 'text-red-700 dark:text-red-500' : 'text-gray-900 dark:text-gray-300')
|
const classByStatus = vs === ValidationStatus.Success ? 'text-green-700 dark:text-green-500' : vs == ValidationStatus.Error ? 'text-red-700 dark:text-red-500' : 'text-gray-900 dark:text-gray-300'
|
||||||
return baseLabelClasses + ' ' + classByStatus
|
return twMerge(baseLabelClasses, classByStatus)
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user