feat: add input component
This commit is contained in:
@@ -34,6 +34,7 @@ import { useButtonSpinner } from './composables/useButtonSpinner'
|
||||
import FlowbiteThemableChild from '@/components/utils/FlowbiteThemable/components/FlowbiteThemableChild/FlowbiteThemableChild.vue'
|
||||
|
||||
import type { ButtonGradient, ButtonMonochromeGradient, ButtonSize, ButtonVariant } from './types'
|
||||
import type { ThemableChildrenApply } from '@/components/utils/FlowbiteThemable/components/FlowbiteThemableChild/types'
|
||||
const props = defineProps({
|
||||
color: {
|
||||
type: String as PropType<ButtonVariant>,
|
||||
@@ -85,7 +86,7 @@ const loadingSuffix = computed(() => props.loading && props.loadingPosition ===
|
||||
const { wrapperClasses, spanClasses } = useButtonClasses(toRefs(props))
|
||||
const { color: spinnerColor, size: spinnerSize } = useButtonSpinner(toRefs(props))
|
||||
|
||||
const appliableTheme = computed(() => {
|
||||
const appliableTheme = computed<ThemableChildrenApply[]>(() => {
|
||||
if(['alternative', 'light'].includes(props.color)) return []
|
||||
return ['background', 'hover', 'focus']
|
||||
})
|
||||
|
||||
58
src/components/Input/Input.vue
Normal file
58
src/components/Input/Input.vue
Normal file
@@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<div>
|
||||
<label v-if="label" :class="labelClasses">{{ label }}</label>
|
||||
<div class="flex relative">
|
||||
<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" />
|
||||
</div>
|
||||
<input
|
||||
v-bind="$attrs"
|
||||
v-model="model"
|
||||
:disabled="disabled"
|
||||
:type="type"
|
||||
|
||||
:class="[inputClasses, $slots.prefix ? 'pl-10' : '']"
|
||||
/>
|
||||
<div v-if="$slots.suffix" class="absolute right-2.5 bottom-2.5">
|
||||
<slot name="suffix" />
|
||||
</div>
|
||||
</div>
|
||||
<p v-if="$slots.helper" class="mt-2 text-sm text-gray-500 dark:text-gray-400">
|
||||
<slot name="helper" />
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from 'vue'
|
||||
import type { InputSize } from '@/components/Input/types'
|
||||
import { useInputClasses } from '@/components/Input/composables/useInputClasses'
|
||||
import { toRefs } from 'vue'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
|
||||
const props = defineProps({
|
||||
label: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
type: {
|
||||
type: String as PropType<'text' | 'password'>,
|
||||
default: 'text',
|
||||
},
|
||||
size: {
|
||||
type: String as PropType<InputSize>,
|
||||
default: 'md',
|
||||
},
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const model = useVModel(props, 'modelValue')
|
||||
|
||||
const {inputClasses, labelClasses} = useInputClasses(toRefs(props))
|
||||
</script>
|
||||
39
src/components/Input/composables/useInputClasses.ts
Normal file
39
src/components/Input/composables/useInputClasses.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import type { Ref } from 'vue'
|
||||
import { computed } from 'vue'
|
||||
import type { InputSize } from '@/components/Input/types'
|
||||
import { simplifyTailwindClasses } from '@/utils/simplifyTailwindClasses'
|
||||
|
||||
// LABEL
|
||||
const defaultLabelClasses = 'block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300'
|
||||
|
||||
// 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 disabledInputClasses = 'cursor-not-allowed bg-gray-100'
|
||||
const inputSizeClasses: Record<InputSize, string> = {
|
||||
lg: 'p-4',
|
||||
md: 'p-2.5 text-sm',
|
||||
sm: 'p-2 text-sm',
|
||||
}
|
||||
|
||||
export type UseInputClassesProps = {
|
||||
size: Ref<InputSize>
|
||||
disabled: Ref<boolean>
|
||||
}
|
||||
|
||||
export function useInputClasses(props: UseInputClassesProps): {
|
||||
inputClasses: Ref<string>
|
||||
labelClasses: Ref<string>
|
||||
} {
|
||||
const inputClasses = computed(() => {
|
||||
return simplifyTailwindClasses(defaultInputClasses, inputSizeClasses[props.size.value], props.disabled.value ? disabledInputClasses : '')
|
||||
})
|
||||
|
||||
const labelClasses = computed(() => {
|
||||
return defaultLabelClasses
|
||||
})
|
||||
|
||||
return {
|
||||
inputClasses,
|
||||
labelClasses,
|
||||
}
|
||||
}
|
||||
1
src/components/Input/types.ts
Normal file
1
src/components/Input/types.ts
Normal file
@@ -0,0 +1 @@
|
||||
export type InputSize = 'sm' | 'md' | 'lg'
|
||||
@@ -1,7 +1,14 @@
|
||||
<template>
|
||||
<div id="tooltip-default" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-gray-900 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip dark:bg-gray-700">
|
||||
Tooltip content
|
||||
<div class="tooltip-arrow" data-popper-arrow></div>
|
||||
<div>
|
||||
<button data-tooltip-target="tooltip-default" type="button"
|
||||
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
|
||||
Default tooltip
|
||||
</button>
|
||||
<div id="tooltip-default" role="tooltip"
|
||||
class="inline-block absolute z-10 py-2 px-3 text-sm font-medium text-white bg-gray-900 rounded-lg shadow-sm transition-opacity duration-300 tooltip dark:bg-gray-700">
|
||||
Tooltip content
|
||||
<div class="tooltip-arrow" data-popper-arrow></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<component :is="tag" :class="simplifyTailwindClasses($attrs.class || [], classes)">
|
||||
<component :is="tag" :class="simplifyTailwindClasses(classAttr, classes)">
|
||||
<slot />
|
||||
</component>
|
||||
</template>
|
||||
@@ -11,10 +11,12 @@ import {
|
||||
import type {
|
||||
ThemableChildrenApply,
|
||||
} from '@/components/utils/FlowbiteThemable/components/FlowbiteThemableChild/types'
|
||||
import { toRefs } from 'vue'
|
||||
import { computed, toRefs, useAttrs } from 'vue'
|
||||
import { simplifyTailwindClasses } from '@/utils/simplifyTailwindClasses'
|
||||
import type { FlowbiteTheme } from '@/components/utils/FlowbiteThemable/types'
|
||||
|
||||
const attrs = useAttrs()
|
||||
|
||||
const props = defineProps({
|
||||
apply: {
|
||||
type: Array as PropType<ThemableChildrenApply[]>,
|
||||
@@ -31,4 +33,8 @@ const props = defineProps({
|
||||
})
|
||||
|
||||
const { classes } = useFlowbiteThemableChildClasses(toRefs(props))
|
||||
|
||||
const classAttr = computed<string>(() => {
|
||||
return attrs.class as string || '' // TODO:
|
||||
})
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user