package list from viandwi24
This commit is contained in:
76
components/Form/Switch.vue
Normal file
76
components/Form/Switch.vue
Normal file
@@ -0,0 +1,76 @@
|
||||
<script lang="ts" setup>
|
||||
// compiler macro
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
on: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
default: undefined,
|
||||
},
|
||||
})
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
// random
|
||||
const randomId = () =>
|
||||
Math.random().toString(36).substring(2, 15) +
|
||||
Math.random().toString(36).substring(2, 15)
|
||||
|
||||
// state
|
||||
const id = ref(props.id || randomId())
|
||||
const input = ref<HTMLInputElement>()
|
||||
|
||||
// funcs
|
||||
const checked = useSyncProps<boolean>(props, 'modelValue', emit)
|
||||
const onInputChange = (e: Event) => {
|
||||
const target = e.target as HTMLInputElement
|
||||
checked.value = target.checked
|
||||
emit('update:modelValue', target.checked)
|
||||
}
|
||||
|
||||
// lifecycle
|
||||
onMounted(() => {
|
||||
if (props.on) {
|
||||
checked.value = true
|
||||
emit('update:modelValue', true)
|
||||
if (input.value) input.value.checked = true
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<label :for="id" class="flex cursor-pointer">
|
||||
<label
|
||||
:for="id"
|
||||
class="relative inline-block w-10 mr-2 align-middle select-none transition duration-200 ease-in"
|
||||
>
|
||||
<input
|
||||
:id="id"
|
||||
ref="input"
|
||||
type="checkbox"
|
||||
class="switch-checkbox absolute block w-6 h-6 rounded-full bg-white dark:bg-slate-900 border-2 border-slate-300 dark:border-slate-600 appearance-none cursor-pointer"
|
||||
:checked="checked"
|
||||
@change="onInputChange"
|
||||
/>
|
||||
<label
|
||||
:for="id"
|
||||
class="switch-label block overflow-hidden h-6 rounded-full bg-gray-200 dark:bg-slate-700 cursor-pointer border border-slate-300 dark:border-slate-500"
|
||||
/>
|
||||
</label>
|
||||
<slot />
|
||||
</label>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.switch-checkbox:checked {
|
||||
right: 0;
|
||||
}
|
||||
.switch-checkbox:checked + .switch-label {
|
||||
@apply bg-primary-500;
|
||||
}
|
||||
</style>
|
||||
97
components/Form/TextInput.vue
Normal file
97
components/Form/TextInput.vue
Normal file
@@ -0,0 +1,97 @@
|
||||
<script lang="ts" setup>
|
||||
// compiler macro
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'md',
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'default',
|
||||
},
|
||||
})
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const slots = useSlots()
|
||||
|
||||
// list styles
|
||||
const paddingStyles = reactive<{
|
||||
[key: string]: string
|
||||
}>({
|
||||
xs: 'px-1 py-0.5',
|
||||
sm: 'px-2 py-1.5',
|
||||
md: 'px-4 py-2',
|
||||
lg: 'px-5 py-3',
|
||||
})
|
||||
const fontSizeStyles = reactive<{
|
||||
[key: string]: string
|
||||
}>({
|
||||
xs: 'text-xs',
|
||||
sm: 'text-sm',
|
||||
md: 'text-base',
|
||||
lg: 'text-lg',
|
||||
})
|
||||
|
||||
// states
|
||||
const modelValue = useSyncProps<string>(props, 'modelValue', emit)
|
||||
const havePreEl = computed(
|
||||
() =>
|
||||
typeof slots.prefix !== 'undefined' ||
|
||||
typeof slots['prefix-disabled'] !== 'undefined'
|
||||
)
|
||||
const haveSuEl = computed(() => typeof slots.suffix !== 'undefined')
|
||||
const selectedBorderStyle = computed(
|
||||
() => 'border-gray-900/10 dark:border-gray-50/[0.2]'
|
||||
)
|
||||
const selectedOnHoverBorderStyle = computed(
|
||||
() => 'dark:focus:border-white focus:border-gray-900'
|
||||
)
|
||||
const selectedPaddingStyle = computed(
|
||||
() => paddingStyles[props.size] || paddingStyles.md
|
||||
)
|
||||
const selectedFontSizeStyle = computed(
|
||||
() => fontSizeStyles[props.size] || fontSizeStyles.md
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="`text-input-container relative flex`">
|
||||
<div
|
||||
v-if="slots['prefix-disabled']"
|
||||
:class="`flex rounded-l bg-gray-100 dark:bg-slate-800 text-gray-500 border ${selectedBorderStyle}`"
|
||||
>
|
||||
<slot name="prefix-disabled" />
|
||||
</div>
|
||||
<div
|
||||
v-if="slots.prefix"
|
||||
:class="`flex rounded-l border ${selectedBorderStyle}`"
|
||||
>
|
||||
<slot name="prefix" />
|
||||
</div>
|
||||
<div class="text-input-wrapper relative flex flex-1">
|
||||
<input
|
||||
v-model="modelValue"
|
||||
:class="`text-input w-full flex-1 bg-transparent outline-none border ${
|
||||
havePreEl ? '' : 'rounded-l'
|
||||
} ${
|
||||
haveSuEl ? '' : 'rounded-r'
|
||||
} ${selectedBorderStyle} ${selectedOnHoverBorderStyle} ${selectedPaddingStyle} ${selectedFontSizeStyle}`"
|
||||
:type="type"
|
||||
:placeholder="placeholder"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="slots.suffix"
|
||||
:class="`flex rounded-r border ${selectedBorderStyle}`"
|
||||
>
|
||||
<slot name="suffix" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user