mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-15 04:29:37 +01:00
feat(module)!: use tailwind-merge for app.config & move config to components & type props (#692)
Co-authored-by: Pooya Parsa <pooya@pi0.io>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div :class="wrapperClass">
|
||||
<div :class="ui.wrapper">
|
||||
<div class="flex items-center h-5">
|
||||
<input
|
||||
:id="name"
|
||||
@@ -32,16 +32,17 @@
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { omit } from '../../utils/lodash'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { defuTwMerge } from '../../utils'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import { useAppConfig } from '#imports'
|
||||
// TODO: Remove
|
||||
import { mergeConfig } from '../../utils'
|
||||
import type { Strategy } from '../../types'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
import { checkbox } from '#ui/ui.config'
|
||||
import colors from '#ui-colors'
|
||||
|
||||
// const appConfig = useAppConfig()
|
||||
const config = mergeConfig<typeof checkbox>(appConfig.ui.strategy, appConfig.ui.checkbox, checkbox)
|
||||
|
||||
export default defineComponent({
|
||||
inheritAttrs: false,
|
||||
@@ -83,8 +84,8 @@ export default defineComponent({
|
||||
default: false
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.checkbox.default.color,
|
||||
type: String as PropType<typeof colors[number]>,
|
||||
default: () => config.default.color,
|
||||
validator (value: string) {
|
||||
return appConfig.ui.colors.includes(value)
|
||||
}
|
||||
@@ -94,16 +95,13 @@ export default defineComponent({
|
||||
default: ''
|
||||
},
|
||||
ui: {
|
||||
type: Object as PropType<Partial<typeof appConfig.ui.checkbox>>,
|
||||
default: () => ({})
|
||||
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
emits: ['update:modelValue', 'change'],
|
||||
setup (props, { emit, attrs }) {
|
||||
// TODO: Remove
|
||||
const appConfig = useAppConfig()
|
||||
|
||||
const ui = computed<Partial<typeof appConfig.ui.checkbox>>(() => defuTwMerge({}, props.ui, appConfig.ui.checkbox))
|
||||
setup (props, { emit }) {
|
||||
const { ui, attrs } = useUI('checkbox', props.ui, config, { mergeWrapper: true })
|
||||
|
||||
const { emitFormChange, formGroup } = useFormGroup()
|
||||
const color = computed(() => formGroup?.error?.value ? 'red' : props.color)
|
||||
@@ -122,8 +120,6 @@ export default defineComponent({
|
||||
emitFormChange()
|
||||
}
|
||||
|
||||
const wrapperClass = computed(() => twMerge(ui.value.wrapper, attrs.class as string))
|
||||
|
||||
const inputClass = computed(() => {
|
||||
return twMerge(twJoin(
|
||||
ui.value.base,
|
||||
@@ -136,11 +132,10 @@ export default defineComponent({
|
||||
})
|
||||
|
||||
return {
|
||||
attrs: computed(() => omit(attrs, ['class'])),
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
ui,
|
||||
attrs,
|
||||
toggle,
|
||||
wrapperClass,
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
inputClass,
|
||||
onChange
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div :class="wrapperClass" v-bind="attrs">
|
||||
<div :class="ui.wrapper" v-bind="attrs">
|
||||
<div v-if="label" :class="[ui.label.wrapper, size]">
|
||||
<label :for="labelFor" :class="[ui.label.base, required ? ui.label.required : '']">{{ label }}</label>
|
||||
<span v-if="hint" :class="[ui.hint]">{{ hint }}</span>
|
||||
@@ -20,18 +20,16 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, provide, inject } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { omit } from '../../utils/lodash'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import type { FormError, InjectedFormGroupValue } from '../../types/form'
|
||||
import { defuTwMerge } from '../../utils'
|
||||
import { useAppConfig } from '#imports'
|
||||
// TODO: Remove
|
||||
import { computed, defineComponent, provide, inject, ref } from 'vue'
|
||||
import type { Ref, PropType } from 'vue'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { mergeConfig } from '../../utils'
|
||||
import type { FormError, InjectedFormGroupValue, Strategy } from '../../types'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
import { formGroup } from '#ui/ui.config'
|
||||
|
||||
// const appConfig = useAppConfig()
|
||||
const config = mergeConfig<typeof formGroup>(appConfig.ui.strategy, appConfig.ui.formGroup, formGroup)
|
||||
|
||||
let increment = 0
|
||||
|
||||
@@ -43,10 +41,10 @@ export default defineComponent({
|
||||
default: null
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
type: String as PropType<keyof typeof config.size>,
|
||||
default: null,
|
||||
validator (value: string) {
|
||||
return Object.keys(appConfig.ui.formGroup.size).includes(value)
|
||||
return Object.keys(config.size).includes(value)
|
||||
}
|
||||
},
|
||||
label: {
|
||||
@@ -74,17 +72,12 @@ export default defineComponent({
|
||||
default: null
|
||||
},
|
||||
ui: {
|
||||
type: Object as PropType<Partial<typeof appConfig.ui.formGroup>>,
|
||||
default: () => ({})
|
||||
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
setup (props, { attrs }) {
|
||||
// TODO: Remove
|
||||
const appConfig = useAppConfig()
|
||||
|
||||
const ui = computed<Partial<typeof appConfig.ui.formGroup>>(() => defuTwMerge({}, props.ui, appConfig.ui.formGroup))
|
||||
|
||||
const wrapperClass = computed(() => twMerge(ui.value.wrapper, attrs.class as string))
|
||||
setup (props) {
|
||||
const { ui, attrs } = useUI('formGroup', props.ui, config, { mergeWrapper: true })
|
||||
|
||||
const formErrors = inject<Ref<FormError[]> | null>('form-errors', null)
|
||||
|
||||
@@ -94,7 +87,7 @@ export default defineComponent({
|
||||
: formErrors?.value?.find((error) => error.path === props.name)?.message
|
||||
})
|
||||
|
||||
const size = computed(() => ui.value.size[props.size ?? appConfig.ui.input.default.size])
|
||||
const size = computed(() => ui.value.size[props.size ?? config.default.size])
|
||||
const labelFor = ref(`${props.name || 'lf'}-${increment = increment < 1000000 ? increment + 1 : 0}`)
|
||||
|
||||
provide<InjectedFormGroupValue>('form-group', {
|
||||
@@ -105,11 +98,10 @@ export default defineComponent({
|
||||
})
|
||||
|
||||
return {
|
||||
labelFor,
|
||||
attrs: computed(() => omit(attrs, ['class'])),
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
ui,
|
||||
wrapperClass,
|
||||
attrs,
|
||||
labelFor,
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
size,
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div :class="wrapperClass">
|
||||
<div :class="ui.wrapper">
|
||||
<input
|
||||
:id="labelFor"
|
||||
:id="id"
|
||||
ref="input"
|
||||
:name="name"
|
||||
:value="modelValue"
|
||||
@@ -34,17 +34,18 @@
|
||||
<script lang="ts">
|
||||
import { ref, computed, onMounted, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { omit } from '../../utils/lodash'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import { defuTwMerge } from '../../utils'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import { useAppConfig } from '#imports'
|
||||
// TODO: Remove
|
||||
import { mergeConfig } from '../../utils'
|
||||
import type { NestedKeyOf, Strategy } from '../../types'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
import { input } from '#ui/ui.config'
|
||||
import colors from '#ui-colors'
|
||||
|
||||
// const appConfig = useAppConfig()
|
||||
const config = mergeConfig<typeof input>(appConfig.ui.strategy, appConfig.ui.input, input)
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@@ -90,7 +91,7 @@ export default defineComponent({
|
||||
},
|
||||
loadingIcon: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.input.default.loadingIcon
|
||||
default: () => config.default.loadingIcon
|
||||
},
|
||||
leadingIcon: {
|
||||
type: String,
|
||||
@@ -117,26 +118,26 @@ export default defineComponent({
|
||||
default: true
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.input.default.size,
|
||||
type: String as PropType<keyof typeof config.size>,
|
||||
default: () => config.default.size,
|
||||
validator (value: string) {
|
||||
return Object.keys(appConfig.ui.input.size).includes(value)
|
||||
return Object.keys(config.size).includes(value)
|
||||
}
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.input.default.color,
|
||||
type: String as PropType<keyof typeof config.color | typeof colors[number]>,
|
||||
default: () => config.default.color,
|
||||
validator (value: string) {
|
||||
return [...appConfig.ui.colors, ...Object.keys(appConfig.ui.input.color)].includes(value)
|
||||
return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value)
|
||||
}
|
||||
},
|
||||
variant: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.input.default.variant,
|
||||
type: String as PropType<keyof typeof config.variant | NestedKeyOf<typeof config.color>>,
|
||||
default: () => config.default.variant,
|
||||
validator (value: string) {
|
||||
return [
|
||||
...Object.keys(appConfig.ui.input.variant),
|
||||
...Object.values(appConfig.ui.input.color).flatMap(value => Object.keys(value))
|
||||
...Object.keys(config.variant),
|
||||
...Object.values(config.color).flatMap(value => Object.keys(value))
|
||||
].includes(value)
|
||||
}
|
||||
},
|
||||
@@ -145,21 +146,18 @@ export default defineComponent({
|
||||
default: null
|
||||
},
|
||||
ui: {
|
||||
type: Object as PropType<Partial<typeof appConfig.ui.input>>,
|
||||
default: () => ({})
|
||||
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
emits: ['update:modelValue', 'blur'],
|
||||
setup (props, { emit, attrs, slots }) {
|
||||
// TODO: Remove
|
||||
const appConfig = useAppConfig()
|
||||
|
||||
const ui = computed<Partial<typeof appConfig.ui.input>>(() => defuTwMerge({}, props.ui, appConfig.ui.input))
|
||||
setup (props, { emit, slots }) {
|
||||
const { ui, attrs } = useUI('input', props.ui, config, { mergeWrapper: true })
|
||||
|
||||
const { emitFormBlur, emitFormInput, formGroup } = useFormGroup(props)
|
||||
const color = computed(() => formGroup?.error?.value ? 'red' : props.color)
|
||||
const size = computed(() => formGroup?.size?.value ?? props.size)
|
||||
const labelFor = formGroup?.labelFor
|
||||
const id = formGroup?.labelFor
|
||||
|
||||
const input = ref<HTMLInputElement | null>(null)
|
||||
|
||||
@@ -185,8 +183,6 @@ export default defineComponent({
|
||||
}, 100)
|
||||
})
|
||||
|
||||
const wrapperClass = computed(() => twMerge(ui.value.wrapper, attrs.class as string))
|
||||
|
||||
const inputClass = computed(() => {
|
||||
const variant = ui.value.color?.[color.value as string]?.[props.variant as string] || ui.value.variant[props.variant]
|
||||
|
||||
@@ -261,14 +257,14 @@ export default defineComponent({
|
||||
})
|
||||
|
||||
return {
|
||||
labelFor,
|
||||
attrs: computed(() => omit(attrs, ['class', labelFor ? 'id' : null ])),
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
ui,
|
||||
attrs,
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
id,
|
||||
input,
|
||||
isLeading,
|
||||
isTrailing,
|
||||
wrapperClass,
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
inputClass,
|
||||
leadingIconName,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div :class="wrapperClass">
|
||||
<div :class="ui.wrapper">
|
||||
<div class="flex items-center h-5">
|
||||
<input
|
||||
:id="`${name}-${value}`"
|
||||
@@ -29,16 +29,17 @@
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { omit } from '../../utils/lodash'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { defuTwMerge } from '../../utils'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import { useAppConfig } from '#imports'
|
||||
// TODO: Remove
|
||||
import { mergeConfig } from '../../utils'
|
||||
import type { Strategy } from '../../types'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
import { radio } from '#ui/ui.config'
|
||||
import colors from '#ui-colors'
|
||||
|
||||
// const appConfig = useAppConfig()
|
||||
const config = mergeConfig<typeof radio>(appConfig.ui.strategy, appConfig.ui.radio, radio)
|
||||
|
||||
export default defineComponent({
|
||||
inheritAttrs: false,
|
||||
@@ -72,8 +73,8 @@ export default defineComponent({
|
||||
default: false
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.radio.default.color,
|
||||
type: String as PropType<typeof colors[number]>,
|
||||
default: () => config.default.color,
|
||||
validator (value: string) {
|
||||
return appConfig.ui.colors.includes(value)
|
||||
}
|
||||
@@ -83,16 +84,13 @@ export default defineComponent({
|
||||
default: null
|
||||
},
|
||||
ui: {
|
||||
type: Object as PropType<Partial<typeof appConfig.ui.radio>>,
|
||||
default: () => ({})
|
||||
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
setup (props, { emit, attrs }) {
|
||||
// TODO: Remove
|
||||
const appConfig = useAppConfig()
|
||||
|
||||
const ui = computed<Partial<typeof appConfig.ui.radio>>(() => defuTwMerge({}, props.ui, appConfig.ui.radio))
|
||||
setup (props, { emit }) {
|
||||
const { ui, attrs } = useUI('radio', props.ui, config, { mergeWrapper: true })
|
||||
|
||||
const { emitFormChange, formGroup } = useFormGroup()
|
||||
const color = computed(() => formGroup?.error?.value ? 'red' : props.color)
|
||||
@@ -109,8 +107,6 @@ export default defineComponent({
|
||||
}
|
||||
})
|
||||
|
||||
const wrapperClass = computed(() => twMerge(ui.value.wrapper, attrs.class as string))
|
||||
|
||||
const inputClass = computed(() => {
|
||||
return twMerge(twJoin(
|
||||
ui.value.base,
|
||||
@@ -122,11 +118,10 @@ export default defineComponent({
|
||||
})
|
||||
|
||||
return {
|
||||
attrs: computed(() => omit(attrs, ['class'])),
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
ui,
|
||||
attrs,
|
||||
pick,
|
||||
wrapperClass,
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
inputClass
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div :class="wrapperClass">
|
||||
<input
|
||||
:id="labelFor"
|
||||
:id="id"
|
||||
ref="input"
|
||||
v-model.number="value"
|
||||
:name="name"
|
||||
@@ -22,14 +22,17 @@
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { omit } from '../../utils/lodash'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { defuTwMerge } from '../../utils'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import { useAppConfig } from '#imports'
|
||||
// TODO: Remove
|
||||
import { mergeConfig } from '../../utils'
|
||||
import type { Strategy } from '../../types'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
import { range } from '#ui/ui.config'
|
||||
import colors from '#ui-colors'
|
||||
|
||||
const config = mergeConfig<typeof range>(appConfig.ui.strategy, appConfig.ui.range, range)
|
||||
|
||||
export default defineComponent({
|
||||
inheritAttrs: false,
|
||||
@@ -63,15 +66,15 @@ export default defineComponent({
|
||||
default: 1
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.range.default.size,
|
||||
type: String as PropType<keyof typeof config.size>,
|
||||
default: () => config.default.size,
|
||||
validator (value: string) {
|
||||
return Object.keys(appConfig.ui.range.size).includes(value)
|
||||
return Object.keys(config.size).includes(value)
|
||||
}
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.range.default.color,
|
||||
type: String as PropType<typeof colors[number]>,
|
||||
default: () => config.default.color,
|
||||
validator (value: string) {
|
||||
return appConfig.ui.colors.includes(value)
|
||||
}
|
||||
@@ -81,21 +84,18 @@ export default defineComponent({
|
||||
default: null
|
||||
},
|
||||
ui: {
|
||||
type: Object as PropType<Partial<typeof appConfig.ui.range>>,
|
||||
default: () => ({})
|
||||
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
emits: ['update:modelValue', 'change'],
|
||||
setup (props, { emit, attrs }) {
|
||||
// TODO: Remove
|
||||
const appConfig = useAppConfig()
|
||||
|
||||
const ui = computed<Partial<typeof appConfig.ui.range>>(() => defuTwMerge({}, props.ui, appConfig.ui.range))
|
||||
setup (props, { emit }) {
|
||||
const { ui, attrs, attrsClass } = useUI('range', props.ui, config)
|
||||
|
||||
const { emitFormChange, formGroup } = useFormGroup(props)
|
||||
const color = computed(() => formGroup?.error?.value ? 'red' : props.color)
|
||||
const size = computed(() => formGroup?.size?.value ?? props.size)
|
||||
const labelFor = formGroup?.labelFor
|
||||
const id = formGroup?.labelFor
|
||||
|
||||
const value = computed({
|
||||
get () {
|
||||
@@ -115,7 +115,7 @@ export default defineComponent({
|
||||
return twMerge(twJoin(
|
||||
ui.value.wrapper,
|
||||
ui.value.size[size.value]
|
||||
), attrs.class as string)
|
||||
), attrsClass)
|
||||
})
|
||||
|
||||
const inputClass = computed(() => {
|
||||
@@ -167,10 +167,11 @@ export default defineComponent({
|
||||
})
|
||||
|
||||
return {
|
||||
labelFor,
|
||||
attrs: computed(() => omit(attrs, ['class', labelFor ? 'id' : null ])),
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
ui,
|
||||
attrs,
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
id,
|
||||
value,
|
||||
wrapperClass,
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div :class="wrapperClass">
|
||||
<div :class="ui.wrapper">
|
||||
<select
|
||||
:id="labelFor"
|
||||
:id="id"
|
||||
:name="name"
|
||||
:value="modelValue"
|
||||
:required="required"
|
||||
@@ -56,17 +56,18 @@
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent } from 'vue'
|
||||
import type { PropType, ComputedRef } from 'vue'
|
||||
import { get, omit } from '../../utils/lodash'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import { defuTwMerge } from '../../utils'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import { useAppConfig } from '#imports'
|
||||
// TODO: Remove
|
||||
import { mergeConfig, get } from '../../utils'
|
||||
import type { NestedKeyOf, Strategy } from '../../types'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
import { select } from '#ui/ui.config'
|
||||
import colors from '#ui-colors'
|
||||
|
||||
// const appConfig = useAppConfig()
|
||||
const config = mergeConfig<typeof select>(appConfig.ui.strategy, appConfig.ui.select, select)
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@@ -104,7 +105,7 @@ export default defineComponent({
|
||||
},
|
||||
loadingIcon: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.input.default.loadingIcon
|
||||
default: () => config.default.loadingIcon
|
||||
},
|
||||
leadingIcon: {
|
||||
type: String,
|
||||
@@ -112,7 +113,7 @@ export default defineComponent({
|
||||
},
|
||||
trailingIcon: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.select.default.trailingIcon
|
||||
default: () => config.default.trailingIcon
|
||||
},
|
||||
trailing: {
|
||||
type: Boolean,
|
||||
@@ -135,26 +136,26 @@ export default defineComponent({
|
||||
default: () => []
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.select.default.size,
|
||||
type: String as PropType<keyof typeof config.size>,
|
||||
default: () => config.default.size,
|
||||
validator (value: string) {
|
||||
return Object.keys(appConfig.ui.select.size).includes(value)
|
||||
return Object.keys(config.size).includes(value)
|
||||
}
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.select.default.color,
|
||||
type: String as PropType<keyof typeof config.color | typeof colors[number]>,
|
||||
default: () => config.default.color,
|
||||
validator (value: string) {
|
||||
return [...appConfig.ui.colors, ...Object.keys(appConfig.ui.select.color)].includes(value)
|
||||
return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value)
|
||||
}
|
||||
},
|
||||
variant: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.select.default.variant,
|
||||
type: String as PropType<keyof typeof config.variant | NestedKeyOf<typeof config.color>>,
|
||||
default: () => config.default.variant,
|
||||
validator (value: string) {
|
||||
return [
|
||||
...Object.keys(appConfig.ui.select.variant),
|
||||
...Object.values(appConfig.ui.select.color).flatMap(value => Object.keys(value))
|
||||
...Object.keys(config.variant),
|
||||
...Object.values(config.color).flatMap(value => Object.keys(value))
|
||||
].includes(value)
|
||||
}
|
||||
},
|
||||
@@ -171,22 +172,18 @@ export default defineComponent({
|
||||
default: null
|
||||
},
|
||||
ui: {
|
||||
type: Object as PropType<Partial<typeof appConfig.ui.select>>,
|
||||
default: () => ({})
|
||||
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
emits: ['update:modelValue', 'change'],
|
||||
setup (props, { emit, attrs, slots }) {
|
||||
// TODO: Remove
|
||||
const appConfig = useAppConfig()
|
||||
|
||||
const ui = computed<Partial<typeof appConfig.ui.select>>(() => defuTwMerge({}, props.ui, appConfig.ui.select))
|
||||
setup (props, { emit, slots }) {
|
||||
const { ui, attrs } = useUI('select', props.ui, config, { mergeWrapper: true })
|
||||
|
||||
const { emitFormChange, formGroup } = useFormGroup(props)
|
||||
const color = computed(() => formGroup?.error?.value ? 'red' : props.color)
|
||||
const size = computed(() => formGroup?.size?.value ?? props.size)
|
||||
const labelFor = formGroup?.labelFor
|
||||
|
||||
const id = formGroup?.labelFor
|
||||
|
||||
const onInput = (event: InputEvent) => {
|
||||
emit('update:modelValue', (event.target as HTMLInputElement).value)
|
||||
@@ -249,8 +246,6 @@ export default defineComponent({
|
||||
return foundOption[props.valueAttribute]
|
||||
})
|
||||
|
||||
const wrapperClass = computed(() => twMerge(ui.value.wrapper, attrs.class as string))
|
||||
|
||||
const selectClass = computed(() => {
|
||||
const variant = ui.value.color?.[color.value as string]?.[props.variant as string] || ui.value.variant[props.variant]
|
||||
|
||||
@@ -324,15 +319,15 @@ export default defineComponent({
|
||||
})
|
||||
|
||||
return {
|
||||
attrs: computed(() => omit(attrs, ['class', labelFor ? 'id' : null ])),
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
ui,
|
||||
labelFor,
|
||||
attrs,
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
id,
|
||||
normalizedOptionsWithPlaceholder,
|
||||
normalizedValue,
|
||||
isLeading,
|
||||
isTrailing,
|
||||
wrapperClass,
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
selectClass,
|
||||
leadingIconName,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
:multiple="multiple"
|
||||
:disabled="disabled || loading"
|
||||
as="div"
|
||||
:class="wrapperClass"
|
||||
:class="ui.wrapper"
|
||||
@update:model-value="onUpdate"
|
||||
>
|
||||
<input
|
||||
@@ -28,7 +28,7 @@
|
||||
class="inline-flex w-full"
|
||||
>
|
||||
<slot :open="open" :disabled="disabled" :loading="loading">
|
||||
<button :id="labelFor" :class="selectClass" :disabled="disabled || loading" type="button" v-bind="attrs">
|
||||
<button :id="id" :class="selectClass" :disabled="disabled || loading" type="button" v-bind="attrs">
|
||||
<span v-if="(isLeading && leadingIconName) || $slots.leading" :class="leadingWrapperIconClass">
|
||||
<slot name="leading" :disabled="disabled" :loading="loading">
|
||||
<UIcon :name="leadingIconName" :class="leadingIconClass" />
|
||||
@@ -131,20 +131,22 @@ import {
|
||||
} from '@headlessui/vue'
|
||||
import { computedAsync, useDebounceFn } from '@vueuse/core'
|
||||
import { defu } from 'defu'
|
||||
import { omit } from '../../utils/lodash'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import UAvatar from '../elements/Avatar.vue'
|
||||
import { defuTwMerge } from '../../utils'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { usePopper } from '../../composables/usePopper'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import type { PopperOptions } from '../../types/popper'
|
||||
import { useAppConfig } from '#imports'
|
||||
// TODO: Remove
|
||||
import { mergeConfig } from '../../utils'
|
||||
import type { PopperOptions, NestedKeyOf, Strategy } from '../../types'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
import { select, selectMenu } from '#ui/ui.config'
|
||||
import colors from '#ui-colors'
|
||||
|
||||
// const appConfig = useAppConfig()
|
||||
const config = mergeConfig<typeof select>(appConfig.ui.strategy, appConfig.ui.select, select)
|
||||
|
||||
const configMenu = mergeConfig<typeof selectMenu>(appConfig.ui.strategy, appConfig.ui.selectMenu, selectMenu)
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@@ -192,7 +194,7 @@ export default defineComponent({
|
||||
},
|
||||
loadingIcon: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.input.default.loadingIcon
|
||||
default: () => config.default.loadingIcon
|
||||
},
|
||||
leadingIcon: {
|
||||
type: String,
|
||||
@@ -200,7 +202,7 @@ export default defineComponent({
|
||||
},
|
||||
trailingIcon: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.select.default.trailingIcon
|
||||
default: () => config.default.trailingIcon
|
||||
},
|
||||
trailing: {
|
||||
type: Boolean,
|
||||
@@ -216,7 +218,7 @@ export default defineComponent({
|
||||
},
|
||||
selectedIcon: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.selectMenu.default.selectedIcon
|
||||
default: () => configMenu.default.selectedIcon
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
@@ -251,26 +253,26 @@ export default defineComponent({
|
||||
default: true
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.select.default.size,
|
||||
type: String as PropType<keyof typeof config.size>,
|
||||
default: () => config.default.size,
|
||||
validator (value: string) {
|
||||
return Object.keys(appConfig.ui.select.size).includes(value)
|
||||
return Object.keys(config.size).includes(value)
|
||||
}
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.select.default.color,
|
||||
type: String as PropType<keyof typeof config.color | typeof colors[number]>,
|
||||
default: () => config.default.color,
|
||||
validator (value: string) {
|
||||
return [...appConfig.ui.colors, ...Object.keys(appConfig.ui.select.color)].includes(value)
|
||||
return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value)
|
||||
}
|
||||
},
|
||||
variant: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.select.default.variant,
|
||||
type: String as PropType<keyof typeof config.variant | NestedKeyOf<typeof config.color>>,
|
||||
default: () => config.default.variant,
|
||||
validator (value: string) {
|
||||
return [
|
||||
...Object.keys(appConfig.ui.select.variant),
|
||||
...Object.values(appConfig.ui.select.color).flatMap(value => Object.keys(value))
|
||||
...Object.keys(config.variant),
|
||||
...Object.values(config.color).flatMap(value => Object.keys(value))
|
||||
].includes(value)
|
||||
}
|
||||
},
|
||||
@@ -295,21 +297,19 @@ export default defineComponent({
|
||||
default: null
|
||||
},
|
||||
ui: {
|
||||
type: Object as PropType<Partial<typeof appConfig.ui.select>>,
|
||||
default: () => ({})
|
||||
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
|
||||
default: undefined
|
||||
},
|
||||
uiMenu: {
|
||||
type: Object as PropType<Partial<typeof appConfig.ui.selectMenu>>,
|
||||
default: () => ({})
|
||||
type: Object as PropType<Partial<typeof configMenu & { strategy?: Strategy }>>,
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
emits: ['update:modelValue', 'open', 'close', 'change'],
|
||||
setup (props, { emit, attrs, slots }) {
|
||||
// TODO: Remove
|
||||
const appConfig = useAppConfig()
|
||||
setup (props, { emit, slots }) {
|
||||
const { ui, attrs } = useUI('select', props.ui, config, { mergeWrapper: true })
|
||||
|
||||
const ui = computed<Partial<typeof appConfig.ui.select>>(() => defuTwMerge({}, props.ui, appConfig.ui.select))
|
||||
const uiMenu = computed<Partial<typeof appConfig.ui.selectMenu>>(() => defuTwMerge({}, props.uiMenu, appConfig.ui.selectMenu))
|
||||
const { ui: uiMenu } = useUI('selectMenu', props.uiMenu, configMenu)
|
||||
|
||||
const popper = computed<PopperOptions>(() => defu({}, props.popper, uiMenu.value.popper as PopperOptions))
|
||||
|
||||
@@ -317,13 +317,11 @@ export default defineComponent({
|
||||
const { emitFormBlur, emitFormChange, formGroup } = useFormGroup(props)
|
||||
const color = computed(() => formGroup?.error?.value ? 'red' : props.color)
|
||||
const size = computed(() => formGroup?.size?.value ?? props.size)
|
||||
const labelFor = formGroup?.labelFor
|
||||
const id = formGroup?.labelFor
|
||||
|
||||
const query = ref('')
|
||||
const searchInput = ref<ComponentPublicInstance<HTMLElement>>()
|
||||
|
||||
const wrapperClass = computed(() => twMerge(ui.value.wrapper, attrs.class as string))
|
||||
|
||||
const selectClass = computed(() => {
|
||||
const variant = ui.value.color?.[color.value as string]?.[props.variant as string] || ui.value.variant[props.variant]
|
||||
|
||||
@@ -442,15 +440,17 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
return {
|
||||
labelFor,
|
||||
attrs: computed(() => omit(attrs, ['class', labelFor ? 'id' : null ])),
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
ui,
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
uiMenu,
|
||||
attrs,
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
id,
|
||||
trigger,
|
||||
container,
|
||||
isLeading,
|
||||
isTrailing,
|
||||
wrapperClass,
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
selectClass,
|
||||
leadingIconName,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div :class="wrapperClass">
|
||||
<div :class="ui.wrapper">
|
||||
<textarea
|
||||
:id="labelFor"
|
||||
:id="id"
|
||||
ref="textarea"
|
||||
:value="modelValue"
|
||||
:name="name"
|
||||
@@ -21,16 +21,17 @@
|
||||
<script lang="ts">
|
||||
import { ref, computed, watch, onMounted, nextTick, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { omit } from '../../utils/lodash'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import { defuTwMerge } from '../../utils'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import { useAppConfig } from '#imports'
|
||||
// TODO: Remove
|
||||
import { mergeConfig } from '../../utils'
|
||||
import type { NestedKeyOf, Strategy } from '../../types'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
import { textarea } from '#ui/ui.config'
|
||||
import colors from '#ui-colors'
|
||||
|
||||
// const appConfig = useAppConfig()
|
||||
const config = mergeConfig<typeof textarea>(appConfig.ui.strategy, appConfig.ui.textarea, textarea)
|
||||
|
||||
export default defineComponent({
|
||||
inheritAttrs: false,
|
||||
@@ -80,26 +81,26 @@ export default defineComponent({
|
||||
default: true
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.textarea.default.size,
|
||||
type: String as PropType<keyof typeof config.size>,
|
||||
default: () => config.default.size,
|
||||
validator (value: string) {
|
||||
return Object.keys(appConfig.ui.textarea.size).includes(value)
|
||||
return Object.keys(config.size).includes(value)
|
||||
}
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.textarea.default.color,
|
||||
type: String as PropType<keyof typeof config.color | typeof colors[number]>,
|
||||
default: () => config.default.color,
|
||||
validator (value: string) {
|
||||
return [...appConfig.ui.colors, ...Object.keys(appConfig.ui.textarea.color)].includes(value)
|
||||
return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value)
|
||||
}
|
||||
},
|
||||
variant: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.textarea.default.variant,
|
||||
type: String as PropType<keyof typeof config.variant | NestedKeyOf<typeof config.color>>,
|
||||
default: () => config.default.variant,
|
||||
validator (value: string) {
|
||||
return [
|
||||
...Object.keys(appConfig.ui.textarea.variant),
|
||||
...Object.values(appConfig.ui.textarea.color).flatMap(value => Object.keys(value))
|
||||
...Object.keys(config.variant),
|
||||
...Object.values(config.color).flatMap(value => Object.keys(value))
|
||||
].includes(value)
|
||||
}
|
||||
},
|
||||
@@ -108,23 +109,20 @@ export default defineComponent({
|
||||
default: null
|
||||
},
|
||||
ui: {
|
||||
type: Object as PropType<Partial<typeof appConfig.ui.textarea>>,
|
||||
default: () => ({})
|
||||
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
emits: ['update:modelValue', 'blur'],
|
||||
setup (props, { emit, attrs }) {
|
||||
const textarea = ref<HTMLTextAreaElement | null>(null)
|
||||
|
||||
// TODO: Remove
|
||||
const appConfig = useAppConfig()
|
||||
|
||||
const ui = computed<Partial<typeof appConfig.ui.textarea>>(() => defuTwMerge({}, props.ui, appConfig.ui.textarea))
|
||||
setup (props, { emit }) {
|
||||
const { ui, attrs } = useUI('textarea', props.ui, config, { mergeWrapper: true })
|
||||
|
||||
const { emitFormBlur, emitFormInput, formGroup } = useFormGroup(props)
|
||||
const color = computed(() => formGroup?.error?.value ? 'red' : props.color)
|
||||
const size = computed(() => formGroup?.size?.value ?? props.size)
|
||||
const labelFor = formGroup?.labelFor
|
||||
const id = formGroup?.labelFor
|
||||
|
||||
const textarea = ref<HTMLTextAreaElement | null>(null)
|
||||
|
||||
const autoFocus = () => {
|
||||
if (props.autofocus) {
|
||||
@@ -183,8 +181,6 @@ export default defineComponent({
|
||||
}, 100)
|
||||
})
|
||||
|
||||
const wrapperClass = computed(() => twMerge(ui.value.wrapper, attrs.class as string))
|
||||
|
||||
const textareaClass = computed(() => {
|
||||
const variant = ui.value.color?.[color.value as string]?.[props.variant as string] || ui.value.variant[props.variant]
|
||||
|
||||
@@ -200,10 +196,12 @@ export default defineComponent({
|
||||
})
|
||||
|
||||
return {
|
||||
labelFor,
|
||||
attrs: computed(() => omit(attrs, ['class', labelFor ? 'id' : null ])),
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
ui,
|
||||
attrs,
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
id,
|
||||
textarea,
|
||||
wrapperClass,
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
textareaClass,
|
||||
onInput,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<HSwitch
|
||||
:id="labelFor"
|
||||
:id="id"
|
||||
v-model="active"
|
||||
:name="name"
|
||||
:disabled="disabled"
|
||||
@@ -22,17 +22,18 @@
|
||||
import { computed, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { Switch as HSwitch } from '@headlessui/vue'
|
||||
import { omit } from '../../utils/lodash'
|
||||
import { twMerge, twJoin } from 'tailwind-merge'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import { defuTwMerge } from '../../utils'
|
||||
import { useUI } from '../../composables/useUI'
|
||||
import { useFormGroup } from '../../composables/useFormGroup'
|
||||
import { useAppConfig } from '#imports'
|
||||
// TODO: Remove
|
||||
import { mergeConfig } from '../../utils'
|
||||
import type { Strategy } from '../../types'
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
import { toggle } from '#ui/ui.config'
|
||||
import colors from '#ui-colors'
|
||||
|
||||
// const appConfig = useAppConfig()
|
||||
const config = mergeConfig<typeof toggle>(appConfig.ui.strategy, appConfig.ui.toggle, toggle)
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@@ -59,34 +60,31 @@ export default defineComponent({
|
||||
},
|
||||
onIcon: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.toggle.default.onIcon
|
||||
default: () => config.default.onIcon
|
||||
},
|
||||
offIcon: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.toggle.default.offIcon
|
||||
default: () => config.default.offIcon
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.toggle.default.color,
|
||||
type: String as PropType<typeof colors[number]>,
|
||||
default: () => config.default.color,
|
||||
validator (value: string) {
|
||||
return appConfig.ui.colors.includes(value)
|
||||
}
|
||||
},
|
||||
ui: {
|
||||
type: Object as PropType<Partial<typeof appConfig.ui.toggle>>,
|
||||
default: () => ({})
|
||||
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
setup (props, { emit, attrs }) {
|
||||
// TODO: Remove
|
||||
const appConfig = useAppConfig()
|
||||
|
||||
const ui = computed<Partial<typeof appConfig.ui.toggle>>(() => defuTwMerge({}, props.ui, appConfig.ui.toggle))
|
||||
setup (props, { emit }) {
|
||||
const { ui, attrs, attrsClass } = useUI('toggle', props.ui, config)
|
||||
|
||||
const { emitFormChange, formGroup } = useFormGroup(props)
|
||||
const color = computed(() => formGroup?.error?.value ? 'red' : props.color)
|
||||
const labelFor = formGroup?.labelFor
|
||||
const id = formGroup?.labelFor
|
||||
|
||||
const active = computed({
|
||||
get () {
|
||||
@@ -104,7 +102,7 @@ export default defineComponent({
|
||||
ui.value.rounded,
|
||||
ui.value.ring.replaceAll('{color}', color.value),
|
||||
(active.value ? ui.value.active : ui.value.inactive).replaceAll('{color}', color.value)
|
||||
), attrs.class as string)
|
||||
), attrsClass)
|
||||
})
|
||||
|
||||
const onIconClass = computed(() => {
|
||||
@@ -120,10 +118,11 @@ export default defineComponent({
|
||||
})
|
||||
|
||||
return {
|
||||
labelFor,
|
||||
attrs: computed(() => omit(attrs, ['class', labelFor ? 'id' : null ])),
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
ui,
|
||||
attrs,
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
id,
|
||||
active,
|
||||
switchClass,
|
||||
onIconClass,
|
||||
|
||||
Reference in New Issue
Block a user