refactor to ui components
This commit is contained in:
23
src/components/ui/UIButton.vue
Normal file
23
src/components/ui/UIButton.vue
Normal file
@@ -0,0 +1,23 @@
|
||||
<script setup lang="ts">
|
||||
interface Props {
|
||||
size?: string
|
||||
variant?: 'regular' | 'outline'
|
||||
color?: string
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
size: 'md',
|
||||
variant: 'regular',
|
||||
color: 'regular'
|
||||
})
|
||||
|
||||
const styleClass = computed(() => {
|
||||
const sizeClass = `btn-${props.size}`
|
||||
const variantClass = props.variant !== 'regular' ? `btn-${props.variant}` : ''
|
||||
const colorClass = props.color !== 'regular' ? `btn-${props.color}` : ''
|
||||
return [sizeClass, variantClass, colorClass]
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<button class="btn" :class="styleClass"><slot></slot></button>
|
||||
</template>
|
||||
3
src/components/ui/UIButtonGroup.vue
Normal file
3
src/components/ui/UIButtonGroup.vue
Normal file
@@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<div class="btn-group"><slot></slot></div>
|
||||
</template>
|
||||
70
src/components/ui/UIModal.vue
Normal file
70
src/components/ui/UIModal.vue
Normal file
@@ -0,0 +1,70 @@
|
||||
<script setup lang="ts">
|
||||
import { onClickOutside } from '@vueuse/core'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
open?: boolean
|
||||
persistent?: boolean
|
||||
}>(),
|
||||
{
|
||||
open: false,
|
||||
persistent: false
|
||||
}
|
||||
)
|
||||
|
||||
const show = ref<boolean>(false)
|
||||
watch(
|
||||
() => props.open,
|
||||
() => (show.value = props.open),
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
const modal = ref<HTMLElement | null>(null)
|
||||
const modalBox = ref(null)
|
||||
|
||||
const open = () => (show.value = true)
|
||||
const close = (): Promise<boolean> => {
|
||||
return new Promise((resolve) => {
|
||||
modal.value?.addEventListener('transitionend', () => resolve(true))
|
||||
show.value = false
|
||||
})
|
||||
}
|
||||
|
||||
const slotProps = { open, close }
|
||||
|
||||
if (!props.persistent) onClickOutside(modalBox, () => close())
|
||||
|
||||
const onEnter = (el: Element, done: () => void): void => {
|
||||
setTimeout(() => {
|
||||
el.classList.add('modal-open')
|
||||
done()
|
||||
})
|
||||
}
|
||||
|
||||
const onLeave = (el: Element, done: () => void): void => {
|
||||
el.classList.remove('modal-open')
|
||||
el.addEventListener('transitionend', () => done())
|
||||
}
|
||||
|
||||
defineExpose({ open, close })
|
||||
</script>
|
||||
<template>
|
||||
<slot name="activator" v-bind="slotProps"></slot>
|
||||
<Teleport to="body">
|
||||
<Transition @enter="onEnter" @leave="onLeave" appear>
|
||||
<div class="modal bg-neutral-800 bg-opacity-60" v-if="show" ref="modal">
|
||||
<div class="modal-box" ref="modalBox">
|
||||
<h3 class="text-lg font-bold" v-if="$slots.title"><slot name="title" /></h3>
|
||||
<p class="py-4">
|
||||
<slot v-bind="slotProps" />
|
||||
</p>
|
||||
<div class="modal-action">
|
||||
<slot name="actions" v-bind="slotProps">
|
||||
<button class="btn-sm btn" @click="close">Close</button>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</Teleport>
|
||||
</template>
|
||||
15
src/components/ui/UITable.vue
Normal file
15
src/components/ui/UITable.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
interface Props {
|
||||
density?: 'compact'
|
||||
}
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const styleClass = computed(() => {
|
||||
const densityClass = props.density ? 'table-compact' : ''
|
||||
return [densityClass]
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<table class="table" :class="styleClass"><slot></slot></table>
|
||||
</template>
|
||||
28
src/components/ui/UITextInput.vue
Normal file
28
src/components/ui/UITextInput.vue
Normal file
@@ -0,0 +1,28 @@
|
||||
<script setup lang="ts">
|
||||
interface Props {
|
||||
modelValue: any
|
||||
size?: 'sm' | 'md' | 'lg' | 'xl'
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
size: 'md'
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: any]
|
||||
}>()
|
||||
|
||||
const styleClass = computed(() => {
|
||||
const sizeClass = `input-${props.size}`
|
||||
return [sizeClass]
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<input
|
||||
type="text"
|
||||
:value="props.modelValue"
|
||||
@input="emit('update:modelValue', ($event.target as HTMLInputElement)?.value)"
|
||||
class="input-bordered input input-sm my-1 ml-auto mr-1 max-w-xs flex-grow"
|
||||
:class="styleClass"
|
||||
/>
|
||||
</template>
|
||||
Reference in New Issue
Block a user