fix(useComponentIcons): reactivity when using defu

This commit is contained in:
Benjamin Canac
2024-05-10 17:57:53 +02:00
parent 52cf471099
commit 45454fae45
5 changed files with 17 additions and 16 deletions

View File

@@ -44,7 +44,7 @@ const slots = defineSlots<ButtonSlots>()
const linkProps = useForwardProps(reactiveOmit(props, 'type', 'label', 'color', 'variant', 'size', 'icon', 'leading', 'leadingIcon', 'trailing', 'trailingIcon', 'loading', 'loadingIcon', 'square', 'block', 'disabled', 'truncate', 'class', 'ui'))
const { orientation, size: buttonSize } = useButtonGroup<ButtonProps>(props)
const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons<ButtonProps>(props)
const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(props)
const ui = computed(() => tv({ extend: button, slots: props.ui })({
color: props.color,

View File

@@ -60,7 +60,7 @@ const [modelValue, modelModifiers] = defineModel<string | number>()
const { emitFormBlur, emitFormInput, size: formGroupSize, color, id, name, disabled } = useFormField<InputProps>(props)
const { orientation, size: buttonGroupSize } = useButtonGroup<InputProps>(props)
const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons<InputProps>(props)
const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(props)
const inputSize = computed(() => buttonGroupSize.value || formGroupSize.value)

View File

@@ -103,7 +103,7 @@ const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', '
const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, position: 'popper' }) as ComboboxContentProps)
const { emitFormBlur, emitFormChange, size: formGroupSize, color, id, name, disabled } = useFormField<InputProps>(props)
const { orientation, size: buttonGroupSize } = useButtonGroup<InputProps>(props)
const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons<InputProps>(defu(props, { trailingIcon: appConfig.ui.icons.chevronDown }))
const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(toRef(() => defu(props, { trailingIcon: appConfig.ui.icons.chevronDown })))
const inputSize = computed(() => buttonGroupSize.value || formGroupSize.value)

View File

@@ -85,7 +85,7 @@ const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffse
const { emitFormChange, size: formGroupSize, color, id, name, disabled } = useFormField<InputProps>(props)
const { orientation, size: buttonGroupSize } = useButtonGroup<InputProps>(props)
const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons<InputProps>(defu(props, { trailingIcon: appConfig.ui.icons.chevronDown }))
const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(toRef(() => defu(props, { trailingIcon: appConfig.ui.icons.chevronDown })))
const selectSize = computed(() => buttonGroupSize.value || formGroupSize.value)

View File

@@ -1,9 +1,8 @@
import { computed } from 'vue'
import { computed, toValue, type MaybeRefOrGetter } from 'vue'
import { useAppConfig } from '#imports'
import type { GetObjectField } from '#ui/types/utils'
export interface UseComponentIconsProps {
/** Display an icon based on the `leading` and `trailing` props. */
/** Display an icon based on the `leading` and `trailing` props.value. */
icon?: string
/** When `true`, the icon will be displayed on the left side. */
leading?: boolean
@@ -22,25 +21,27 @@ export interface UseComponentIconsProps {
loadingIcon?: string
}
export function useComponentIcons<T>(props: UseComponentIconsProps & { size: GetObjectField<T, 'size'> }) {
export function useComponentIcons(componentProps: MaybeRefOrGetter<UseComponentIconsProps>) {
const appConfig = useAppConfig()
const isLeading = computed(() => (props.icon && props.leading) || (props.icon && !props.trailing) || (props.loading && !props.trailing && !props.trailingIcon) || !!props.leadingIcon)
const isTrailing = computed(() => (props.icon && props.trailing) || (props.loading && props.trailing) || !!props.trailingIcon)
const props = computed(() => toValue(componentProps))
const isLeading = computed(() => (props.value.icon && props.value.leading) || (props.value.icon && !props.value.trailing) || (props.value.loading && !props.value.trailing && !props.value.trailingIcon) || !!props.value.leadingIcon)
const isTrailing = computed(() => (props.value.icon && props.value.trailing) || (props.value.loading && props.value.trailing) || !!props.value.trailingIcon)
const leadingIconName = computed(() => {
if (props.loading) {
return props.loadingIcon || appConfig.ui.icons.loading
if (props.value.loading) {
return props.value.loadingIcon || appConfig.ui.icons.loading
}
return props.leadingIcon || props.icon
return props.value.leadingIcon || props.value.icon
})
const trailingIconName = computed(() => {
if (props.loading && !isLeading.value) {
return props.loadingIcon || appConfig.ui.icons.loading
if (props.value.loading && !isLeading.value) {
return props.value.loadingIcon || appConfig.ui.icons.loading
}
return props.trailingIcon || props.icon
return props.value.trailingIcon || props.value.icon
})
return {