fix(components): move remaining classes to config (#1039)

This commit is contained in:
Benjamin Canac
2023-11-30 16:31:48 +01:00
committed by GitHub
parent 5718dfd69a
commit e408eabd8b
44 changed files with 196 additions and 117 deletions

View File

@@ -4,7 +4,7 @@
<UIcon v-if="icon" :name="icon" :class="ui.icon.base" />
<UAvatar v-if="avatar" v-bind="{ size: ui.avatar.size, ...avatar }" :class="ui.avatar.base" />
<div class="w-0 flex-1">
<div :class="ui.inner">
<p :class="ui.title">
<slot name="title" :title="title">
{{ title }}

View File

@@ -32,7 +32,7 @@ export default defineComponent({
default: () => ''
},
ui: {
type: Object as PropType<Partial<typeof avatarGroupConfig & { strategy?: Strategy }>>,
type: Object as PropType<Partial<typeof avatarGroupConfig> & { strategy?: Strategy }>,
default: () => ({})
}
},

View File

@@ -5,7 +5,7 @@
</slot>
<slot>
<span v-if="label" :class="[truncate ? 'text-left break-all line-clamp-1' : '']">
<span v-if="label" :class="[truncate ? ui.truncate : '']">
{{ label }}
</span>
</slot>
@@ -154,7 +154,7 @@ export default defineComponent({
ui.value.gap[size.value],
props.padded && ui.value[isSquare.value ? 'square' : 'padding'][size.value],
variant?.replaceAll('{color}', props.color),
props.block ? 'w-full flex justify-center items-center' : 'inline-flex items-center'
props.block ? ui.value.block : ui.value.inline
), props.class)
})
@@ -178,7 +178,7 @@ export default defineComponent({
return twJoin(
ui.value.icon.base,
ui.value.icon.size[size.value],
props.loading && 'animate-spin'
props.loading && ui.value.icon.loading
)
})
@@ -186,11 +186,13 @@ export default defineComponent({
return twJoin(
ui.value.icon.base,
ui.value.icon.size[size.value],
props.loading && !isLeading.value && 'animate-spin'
props.loading && !isLeading.value && ui.value.icon.loading
)
})
return {
// eslint-disable-next-line vue/no-dupe-keys
ui,
attrs,
isLeading,
isTrailing,

View File

@@ -35,7 +35,7 @@ export default defineComponent({
default: () => ''
},
ui: {
type: Object as PropType<Partial<typeof buttonGroupConfig & { strategy?: Strategy }>>,
type: Object as PropType<Partial<typeof buttonGroupConfig> & { strategy?: Strategy }>,
default: () => ({})
}
},
@@ -52,20 +52,7 @@ export default defineComponent({
), props.class)
})
const rounded = computed(() => {
const roundedMap = {
'rounded-none': { horizontal: { start: 'rounded-s-none', end: 'rounded-e-none' }, vertical: { start: 'rounded-t-none', end: 'rounded-b-none' } },
'rounded-sm': { horizontal: { start: 'rounded-s-sm', end: 'rounded-e-sm' }, vertical: { start: 'rounded-t-sm', end: 'rounded-b-sm' } },
rounded: { horizontal: { start: 'rounded-s', end: 'rounded-e' }, vertical: { start: 'rounded-t', end: 'rounded-b' } },
'rounded-md': { horizontal: { start: 'rounded-s-md', end: 'rounded-e-md' }, vertical: { start: 'rounded-t-md', end: 'rounded-b-md' } },
'rounded-lg': { horizontal: { start: 'rounded-s-lg', end: 'rounded-e-lg' }, vertical: { start: 'rounded-t-lg', end: 'rounded-b-lg' } },
'rounded-xl': { horizontal: { start: 'rounded-s-xl', end: 'rounded-e-xl' }, vertical: { start: 'rounded-t-xl', end: 'rounded-b-xl' } },
'rounded-2xl': { horizontal: { start: 'rounded-s-2xl', end: 'rounded-e-2xl' }, vertical: { start: 'rounded-t-2xl', end: 'rounded-b-2xl' } },
'rounded-3xl': { horizontal: { start: 'rounded-s-3xl', end: 'rounded-e-3xl' }, vertical: { start: 'rounded-t-3xl', end: 'rounded-b-3xl' } },
'rounded-full': { horizontal: { start: 'rounded-s-full', end: 'rounded-e-full' }, vertical: { start: 'rounded-t-full', end: 'rounded-b-full' } }
}
return roundedMap[ui.value.rounded][props.orientation]
})
const rounded = computed(() => ui.value.orientation[ui.value.rounded][props.orientation])
useProvideButtonGroup({ orientation: toRef(props, 'orientation'), size: toRef(props, 'size'), ui, rounded })

View File

@@ -4,7 +4,7 @@
ref="trigger"
as="div"
:disabled="disabled"
class="inline-flex w-full"
:class="ui.trigger"
role="button"
@mouseover="onMouseOver"
>
@@ -18,7 +18,7 @@
<div v-if="open && items.length" ref="container" :class="[ui.container, ui.width]" :style="containerStyle" @mouseover="onMouseOver">
<Transition appear v-bind="ui.transition">
<div>
<div v-if="popper.arrow" data-popper-arrow :class="['invisible before:visible before:block before:rotate-45 before:z-[-1]', Object.values(ui.arrow)]" />
<div v-if="popper.arrow" data-popper-arrow :class="Object.values(ui.arrow)" />
<HMenuItems :class="[ui.base, ui.divide, ui.ring, ui.rounded, ui.shadow, ui.background, ui.height]" static>
<div v-for="(subItems, index) of items" :key="index" :class="ui.padding">
<NuxtLink v-for="(item, subIndex) of subItems" :key="subIndex" v-slot="{ href, target, rel, navigate, isExternal }" v-bind="omit(item, ['label', 'slot', 'icon', 'iconClass', 'avatar', 'shortcuts', 'disabled', 'click'])" custom>
@@ -35,7 +35,7 @@
<UIcon v-if="item.icon" :name="item.icon" :class="[ui.item.icon.base, active ? ui.item.icon.active : ui.item.icon.inactive, item.iconClass]" />
<UAvatar v-else-if="item.avatar" v-bind="{ size: ui.item.avatar.size, ...item.avatar }" :class="ui.item.avatar.base" />
<span class="truncate">{{ item.label }}</span>
<span :class="ui.item.label">{{ item.label }}</span>
<span v-if="item.shortcuts?.length" :class="ui.item.shortcuts">
<UKbd v-for="shortcut of item.shortcuts" :key="shortcut">{{ shortcut }}</UKbd>

View File

@@ -44,14 +44,14 @@ export default defineComponent({
},
icon: {
type: String,
default: 'i-heroicons-minus'
default: () => meterGroupConfig.default.icon
},
class: {
type: [String, Object, Array] as PropType<any>,
default: () => ''
},
ui: {
type: Object as PropType<Partial<typeof meterGroupConfig & { strategy?: Strategy }>>,
type: Object as PropType<Partial<typeof meterGroupConfig> & { strategy?: Strategy }>,
default: () => ({})
}
},
@@ -70,21 +70,7 @@ export default defineComponent({
const children = computed(() => getSlotsChildren(slots))
const rounded = computed(() => {
const roundedMap = {
'rounded-none': { left: 'rounded-s-none', right: 'rounded-e-none' },
'rounded-sm': { left: 'rounded-s-sm', right: 'rounded-e-sm' },
rounded: { left: 'rounded-s', right: 'rounded-e' },
'rounded-md': { left: 'rounded-s-md', right: 'rounded-e-md' },
'rounded-lg': { left: 'rounded-s-lg', right: 'rounded-e-lg' },
'rounded-xl': { left: 'rounded-s-xl', right: 'rounded-e-xl' },
'rounded-2xl': { left: 'rounded-s-2xl', right: 'rounded-e-2xl' },
'rounded-3xl': { left: 'rounded-s-3xl', right: 'rounded-e-3xl' },
'rounded-full': { left: 'rounded-s-full', right: 'rounded-e-full' }
}
return roundedMap[ui.value.rounded]
})
const rounded = computed(() => ui.value.orientation[ui.value.rounded])
function clampPercent (value: number, min: number, max: number): number {
if (min == max) {
@@ -198,7 +184,7 @@ export default defineComponent({
vNodeSlots[0] = slots.indicator({ percent: percent.value })
}
vNodeSlots[2] = h('ol', { class: 'list-disc list-inside' }, labels.value.map((label, key) => {
vNodeSlots[2] = h('ol', { class: ui.value.list }, labels.value.map((label, key) => {
const labelClass = computed(() => {
return twJoin(
uiMeter.value.label.base,

View File

@@ -1,6 +1,6 @@
<template>
<div :class="ui.wrapper">
<div class="flex items-center h-5">
<div :class="ui.container">
<input
:id="inputId"
v-model="toggle"
@@ -11,13 +11,12 @@
:checked="checked"
:indeterminate="indeterminate"
type="checkbox"
class="form-checkbox"
:class="inputClass"
v-bind="attrs"
@change="onChange"
>
</div>
<div v-if="label || $slots.label" class="ms-3 flex flex-col">
<div v-if="label || $slots.label" :class="ui.inner">
<label :for="inputId" :class="ui.label">
<slot name="label">{{ label }}</slot>
<span v-if="required" :class="ui.required">*</span>
@@ -130,6 +129,7 @@ export default defineComponent({
const inputClass = computed(() => {
return twMerge(twJoin(
ui.value.base,
ui.value.form,
ui.value.rounded,
ui.value.background,
ui.value.border,

View File

@@ -9,7 +9,6 @@
:required="required"
:placeholder="placeholder"
:disabled="disabled || loading"
class="form-input"
:class="inputClass"
v-bind="attrs"
@input="onInput"
@@ -234,6 +233,7 @@ export default defineComponent({
return twMerge(twJoin(
ui.value.base,
ui.value.form,
rounded.value,
ui.value.placeholder,
ui.value.size[size.value],
@@ -281,7 +281,7 @@ export default defineComponent({
ui.value.icon.base,
color.value && appConfig.ui.colors.includes(color.value) && ui.value.icon.color.replaceAll('{color}', color.value),
ui.value.icon.size[size.value],
props.loading && 'animate-spin'
props.loading && ui.value.icon.loading
)
})
@@ -298,7 +298,7 @@ export default defineComponent({
ui.value.icon.base,
color.value && appConfig.ui.colors.includes(color.value) && ui.value.icon.color.replaceAll('{color}', color.value),
ui.value.icon.size[size.value],
props.loading && !isLeading.value && 'animate-spin'
props.loading && !isLeading.value && ui.value.icon.loading
)
})

View File

@@ -1,6 +1,6 @@
<template>
<div :class="ui.wrapper">
<div class="flex items-center h-5">
<div :class="ui.container">
<input
:id="inputId"
v-model="pick"
@@ -9,12 +9,11 @@
:value="value"
:disabled="disabled"
type="radio"
class="form-radio"
:class="inputClass"
v-bind="attrs"
>
</div>
<div v-if="label || $slots.label" class="ms-3 flex flex-col">
<div v-if="label || $slots.label" :class="ui.inner">
<label :for="inputId" :class="ui.label">
<slot name="label">{{ label }}</slot>
<span v-if="required" :class="ui.required">*</span>
@@ -128,6 +127,7 @@ export default defineComponent({
const inputClass = computed(() => {
return twMerge(twJoin(
ui.value.base,
ui.value.form,
ui.value.background,
ui.value.border,
color.value && ui.value.ring.replaceAll('{color}', color.value),

View File

@@ -90,7 +90,7 @@ export default defineComponent({
default: () => ({})
},
uiRadio: {
type: Object as PropType<Partial<typeof configRadio & { strategy?: Strategy }>>,
type: Object as PropType<Partial<typeof configRadio> & { strategy?: Strategy }>,
default: () => ({})
}
},

View File

@@ -6,7 +6,6 @@
:value="modelValue"
:required="required"
:disabled="disabled || loading"
class="form-select"
:class="selectClass"
v-bind="attrs"
@input="onInput"
@@ -256,6 +255,7 @@ export default defineComponent({
return twMerge(twJoin(
ui.value.base,
ui.value.form,
rounded.value,
ui.value.size[size.value],
props.padded ? ui.value.padding[size.value] : 'p-0',
@@ -302,7 +302,7 @@ export default defineComponent({
ui.value.icon.base,
color.value && appConfig.ui.colors.includes(color.value) && ui.value.icon.color.replaceAll('{color}', color.value),
ui.value.icon.size[size.value],
props.loading && 'animate-spin'
props.loading && ui.value.icon.loading
)
})
@@ -319,7 +319,7 @@ export default defineComponent({
ui.value.icon.base,
color.value && appConfig.ui.colors.includes(color.value) && ui.value.icon.color.replaceAll('{color}', color.value),
ui.value.icon.size[size.value],
props.loading && !isLeading.value && 'animate-spin'
props.loading && !isLeading.value && ui.value.icon.loading
)
})

View File

@@ -15,7 +15,7 @@
v-if="required"
:value="modelValue"
:required="required"
class="absolute inset-0 w-px opacity-0 cursor-default"
:class="uiMenu.required"
tabindex="-1"
aria-hidden="true"
>
@@ -25,7 +25,7 @@
ref="trigger"
as="div"
role="button"
class="inline-flex w-full"
:class="uiMenu.trigger"
>
<slot :open="open" :disabled="disabled" :loading="loading">
<button :id="inputId" :class="selectClass" :disabled="disabled || loading" type="button" v-bind="attrs">
@@ -36,9 +36,9 @@
</span>
<slot name="label">
<span v-if="multiple && Array.isArray(modelValue) && modelValue.length" class="block truncate">{{ modelValue.length }} selected</span>
<span v-else-if="!multiple && modelValue" class="block truncate">{{ ['string', 'number'].includes(typeof modelValue) ? modelValue : modelValue[optionAttribute] }}</span>
<span v-else class="block truncate">{{ placeholder || '&nbsp;' }}</span>
<span v-if="multiple && Array.isArray(modelValue) && modelValue.length" :class="uiMenu.label">{{ modelValue.length }} selected</span>
<span v-else-if="!multiple && modelValue" :class="uiMenu.label">{{ ['string', 'number'].includes(typeof modelValue) ? modelValue : modelValue[optionAttribute] }}</span>
<span v-else :class="uiMenu.label">{{ placeholder || '&nbsp;' }}</span>
</slot>
<span v-if="(isTrailing && trailingIconName) || $slots.trailing" :class="trailingWrapperIconClass">
@@ -53,7 +53,8 @@
<div v-if="open" ref="container" :class="[uiMenu.container, uiMenu.width]">
<Transition appear v-bind="uiMenu.transition">
<div>
<div v-if="popper.arrow" data-popper-arrow :class="['invisible before:visible before:block before:rotate-45 before:z-[-1]', Object.values(uiMenu.arrow)]" />
<div v-if="popper.arrow" data-popper-arrow :class="Object.values(uiMenu.arrow)" />
<component :is="searchable ? 'HComboboxOptions' : 'HListboxOptions'" static :class="[uiMenu.base, uiMenu.ring, uiMenu.rounded, uiMenu.shadow, uiMenu.background, uiMenu.padding, uiMenu.height]">
<HComboboxInput
v-if="searchable"
@@ -101,7 +102,7 @@
<li :class="[uiMenu.option.base, uiMenu.option.rounded, uiMenu.option.padding, uiMenu.option.size, uiMenu.option.color, active ? uiMenu.option.active : uiMenu.option.inactive]">
<div :class="uiMenu.option.container">
<slot name="option-create" :option="queryOption" :active="active" :selected="selected">
<span class="block truncate">Create "{{ queryOption[optionAttribute] }}"</span>
<span :class="uiMenu.option.create">Create "{{ queryOption[optionAttribute] }}"</span>
</slot>
</div>
</li>
@@ -312,7 +313,7 @@ export default defineComponent({
default: () => ({})
},
uiMenu: {
type: Object as PropType<Partial<typeof configMenu & { strategy?: Strategy }>>,
type: Object as PropType<Partial<typeof configMenu> & { strategy?: Strategy }>,
default: () => ({})
}
},
@@ -339,15 +340,14 @@ export default defineComponent({
return twMerge(twJoin(
ui.value.base,
uiMenu.value.select,
rounded.value,
'text-left cursor-default',
ui.value.size[size.value],
ui.value.gap[size.value],
props.padded ? ui.value.padding[size.value] : 'p-0',
variant?.replaceAll('{color}', color.value),
(isLeading.value || slots.leading) && ui.value.leading.padding[size.value],
(isTrailing.value || slots.trailing) && ui.value.trailing.padding[size.value],
'inline-flex items-center'
(isTrailing.value || slots.trailing) && ui.value.trailing.padding[size.value]
), props.selectClass)
})
@@ -388,7 +388,7 @@ export default defineComponent({
ui.value.icon.base,
color.value && appConfig.ui.colors.includes(color.value) && ui.value.icon.color.replaceAll('{color}', color.value),
ui.value.icon.size[size.value],
props.loading && 'animate-spin'
props.loading && ui.value.icon.loading
)
})
@@ -405,7 +405,7 @@ export default defineComponent({
ui.value.icon.base,
color.value && appConfig.ui.colors.includes(color.value) && ui.value.icon.color.replaceAll('{color}', color.value),
ui.value.icon.size[size.value],
props.loading && !isLeading.value && 'animate-spin'
props.loading && !isLeading.value && ui.value.icon.loading
)
})

View File

@@ -9,7 +9,6 @@
:required="required"
:disabled="disabled"
:placeholder="placeholder"
class="form-textarea"
:class="textareaClass"
v-bind="attrs"
@input="onInput"
@@ -227,6 +226,7 @@ export default defineComponent({
return twMerge(twJoin(
ui.value.base,
ui.value.form,
ui.value.rounded,
ui.value.placeholder,
ui.value.size[size.value],

View File

@@ -91,17 +91,11 @@ export default defineComponent({
})
const borderClass = computed(() => {
const typeClass = ({
solid: 'border-solid',
dotted: 'border-dotted',
dashed: 'border-dashed'
})[props.type]
return twJoin(
ui.value.border.base,
isHorizontal.value ? ui.value.border.horizontal : ui.value.border.vertical,
isHorizontal.value ? ui.value.border.size.horizontal : ui.value.border.size.vertical,
typeClass
ui.value.border.type[props.type]
)
})

View File

@@ -311,7 +311,7 @@ export default defineComponent({
return twJoin(
ui.value.input.icon.base,
ui.value.input.icon.size,
((props.loading || isLoading.value) && props.loadingIcon) && 'animate-spin'
((props.loading || isLoading.value) && props.loadingIcon) && ui.value.input.icon.loading
)
})

View File

@@ -2,7 +2,8 @@
<div v-if="isOpen" ref="container" :class="wrapperClass" v-bind="attrs">
<Transition appear v-bind="ui.transition">
<div>
<div v-if="popper.arrow" data-popper-arrow :class="['invisible before:visible before:block before:rotate-45 before:z-[-1]', Object.values(ui.arrow)]" />
<div v-if="popper.arrow" data-popper-arrow :class="Object.values(ui.arrow)" />
<div :class="[ui.base, ui.ring, ui.rounded, ui.shadow, ui.background]">
<slot />
</div>

View File

@@ -14,10 +14,7 @@
ui.background,
ui.ring,
ui.shadow,
fullscreen ? 'w-screen' : ui.width,
fullscreen ? 'h-screen' : ui.height,
fullscreen ? 'rounded-none' : ui.rounded,
fullscreen ? 'm-0' : ui.margin
fullscreen ? ui.fullscreen : [ui.width, ui.height, ui.rounded, ui.margin],
]"
>
<slot />

View File

@@ -12,7 +12,7 @@
<UIcon v-if="icon" :name="icon" :class="iconClass" />
<UAvatar v-if="avatar" v-bind="{ size: ui.avatar.size, ...avatar }" :class="ui.avatar.base" />
<div class="w-0 flex-1">
<div :class="ui.inner">
<p :class="ui.title">
<slot name="title" :title="title">
{{ title }}

View File

@@ -4,7 +4,7 @@
ref="trigger"
as="div"
:disabled="disabled"
class="inline-flex w-full"
:class="ui.trigger"
role="button"
@mouseover="onMouseOver"
>
@@ -22,7 +22,8 @@
<div v-if="(open !== undefined) ? open : headlessOpen" ref="container" :class="[ui.container, ui.width]" :style="containerStyle" @mouseover="onMouseOver">
<Transition appear v-bind="ui.transition">
<div>
<div v-if="popper.arrow" data-popper-arrow :class="['invisible before:visible before:block before:rotate-45 before:z-[-1]', Object.values(ui.arrow)]" />
<div v-if="popper.arrow" data-popper-arrow :class="Object.values(ui.arrow)" />
<HPopoverPanel :class="[ui.base, ui.background, ui.ring, ui.rounded, ui.shadow]" static>
<slot name="panel" :open="(open !== undefined) ? open : headlessOpen" :close="close" />
</HPopoverPanel>

View File

@@ -90,10 +90,10 @@ export default defineComponent({
return {
...ui.value.transition,
enterFrom: props.side === 'left' ? '-translate-x-full' : 'translate-x-full',
enterTo: 'translate-x-0',
leaveFrom: 'translate-x-0',
leaveTo: props.side === 'left' ? '-translate-x-full' : 'translate-x-full'
enterFrom: props.side === 'left' ? ui.value.translate.left : ui.value.translate.right,
enterTo: ui.value.translate.base,
leaveFrom: ui.value.translate.base,
leaveTo: props.side === 'left' ? ui.value.translate.left : ui.value.translate.right
}
})

View File

@@ -7,7 +7,7 @@
<div v-if="open && !prevent" ref="container" :class="[ui.container, ui.width]">
<Transition appear v-bind="ui.transition">
<div>
<div v-if="popper.arrow" data-popper-arrow :class="['invisible before:visible before:block before:rotate-45 before:z-[-1]', Object.values(ui.arrow)]" />
<div v-if="popper.arrow" data-popper-arrow :class="Object.values(ui.arrow)" />
<div :class="[ui.base, ui.background, ui.color, ui.rounded, ui.shadow, ui.ring]">
<slot name="text">
@@ -15,7 +15,8 @@
</slot>
<span v-if="shortcuts?.length" :class="ui.shortcuts">
<span class="mx-1 text-gray-700 dark:text-gray-200">&middot;</span>
<span :class="ui.middot">&middot;</span>
<UKbd v-for="shortcut of shortcuts" :key="shortcut" size="xs">
{{ shortcut }}
</Ukbd>