fix(module): retain props reactivity through useUI (#745)

Co-authored-by: Benjamin Canac <canacb1@gmail.com>
This commit is contained in:
Aditio Pangestu
2023-09-28 19:06:57 +07:00
committed by GitHub
parent 874447cb41
commit 109ec52d50
36 changed files with 237 additions and 99 deletions

View File

@@ -10,7 +10,7 @@
"@nuxt/content": "^2.8.4",
"@nuxt/devtools": "^0.8.3",
"@nuxt/eslint-config": "^0.2.0",
"@nuxt/ui-pro": "npm:@nuxt/ui-pro-edge@0.0.1-28255017.af7c0a2",
"@nuxt/ui-pro": "npm:@nuxt/ui-pro-edge@0.0.1-28264972.7d9d1f6",
"@nuxthq/studio": "^0.14.1",
"@nuxtjs/fontaine": "^0.4.1",
"@nuxtjs/google-fonts": "^3.0.2",

16
pnpm-lock.yaml generated
View File

@@ -137,8 +137,8 @@ importers:
specifier: ^0.2.0
version: 0.2.0(eslint@8.49.0)
'@nuxt/ui-pro':
specifier: npm:@nuxt/ui-pro-edge@0.0.1-28255017.af7c0a2
version: /@nuxt/ui-pro-edge@0.0.1-28255017.af7c0a2(rollup@3.28.1)(vue@3.3.4)(webpack@5.88.2)
specifier: npm:@nuxt/ui-pro-edge@0.0.1-28264972.7d9d1f6
version: /@nuxt/ui-pro-edge@0.0.1-28264972.7d9d1f6(rollup@3.28.1)(vue@3.3.4)(webpack@5.88.2)
'@nuxthq/studio':
specifier: ^0.14.1
version: 0.14.1(rollup@3.28.1)
@@ -1032,7 +1032,6 @@ packages:
tailwindcss: ^3.0
dependencies:
tailwindcss: 3.3.3
dev: false
/@headlessui/vue@1.7.16(vue@3.3.4):
resolution: {integrity: sha512-nKT+nf/q6x198SsyK54mSszaQl/z+QxtASmgMEJtpxSX2Q0OPJX0upS/9daDyiECpeAsvjkoOrm2O/6PyBQ+Qg==}
@@ -1702,11 +1701,12 @@ packages:
- supports-color
dev: true
/@nuxt/ui-edge@2.8.1-28262323.b306138(rollup@3.28.1)(vue@3.3.4)(webpack@5.88.2):
resolution: {integrity: sha512-piljLwguAK9NH45HuKYBif2g4J5sIBI3cqSndygIxmIN84j4ZQ8lSdE3rIutoIj7YzwEdInV3Vj7RLexGMLIBA==}
/@nuxt/ui-edge@2.8.1-28264933.874447c(rollup@3.28.1)(vue@3.3.4)(webpack@5.88.2):
resolution: {integrity: sha512-+8HtwrCFGQ7Cz6MYdjvsR2fhdlawZI73OZ1J74ZFRm3KdbECsN1fY6Cy/R33kw7arZJRm5SREjkSxd37zlr3og==}
engines: {node: '>=v16.20.2'}
dependencies:
'@egoist/tailwindcss-icons': 1.1.0(tailwindcss@3.3.3)
'@headlessui/tailwindcss': 0.2.0(tailwindcss@3.3.3)
'@headlessui/vue': 1.7.16(vue@3.3.4)
'@iconify-json/heroicons': 1.1.12
'@nuxt/kit': 3.7.4(rollup@3.28.1)
@@ -1747,10 +1747,10 @@ packages:
- webpack
dev: true
/@nuxt/ui-pro-edge@0.0.1-28255017.af7c0a2(rollup@3.28.1)(vue@3.3.4)(webpack@5.88.2):
resolution: {integrity: sha512-ULHT1oKXQJRqkduLePBO2livZ/hXJIxzUtEWjuMdXqHRcTBWvr8aShoJ4u6lHcpgr6URt6VxbhhlLixdlyb2WA==}
/@nuxt/ui-pro-edge@0.0.1-28264972.7d9d1f6(rollup@3.28.1)(vue@3.3.4)(webpack@5.88.2):
resolution: {integrity: sha512-blx7a70AKStd/z75JOvpuG5mhNT467dfXoZdJU8huBU9uhUyBsw5mw199yga+aO/p20UUJvgo4VntMlmjjr18A==}
dependencies:
'@nuxt/ui': /@nuxt/ui-edge@2.8.1-28262323.b306138(rollup@3.28.1)(vue@3.3.4)(webpack@5.88.2)
'@nuxt/ui': /@nuxt/ui-edge@2.8.1-28264933.874447c(rollup@3.28.1)(vue@3.3.4)(webpack@5.88.2)
'@vueuse/core': 10.4.1(vue@3.3.4)
ofetch: 1.3.3
pathe: 1.1.1

View File

@@ -67,7 +67,7 @@
</template>
<script lang="ts">
import { ref, computed, defineComponent, toRaw } from 'vue'
import { ref, computed, defineComponent, toRaw, toRef } from 'vue'
import type { PropType } from 'vue'
import { upperFirst } from 'scule'
import { defu } from 'defu'
@@ -143,6 +143,10 @@ export default defineComponent({
type: Object as PropType<{ icon: string, label: string }>,
default: () => config.default.emptyState
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
@@ -150,7 +154,7 @@ export default defineComponent({
},
emits: ['update:modelValue'],
setup (props, { emit, attrs: $attrs }) {
const { ui, attrs } = useUI('table', props.ui, config, { mergeWrapper: true })
const { ui, attrs } = useUI('table', toRef(props, 'ui'), config, toRef(props, 'class'))
const columns = computed(() => props.columns ?? Object.keys(omit(props.rows[0] ?? {}, ['click'])).map((key) => ({ key, label: upperFirst(key), sortable: false })))

View File

@@ -40,7 +40,7 @@
</template>
<script lang="ts">
import { ref, computed, defineComponent } from 'vue'
import { ref, computed, toRef, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { Disclosure as HDisclosure, DisclosureButton as HDisclosureButton, DisclosurePanel as HDisclosurePanel } from '@headlessui/vue'
import UIcon from '../elements/Icon.vue'
@@ -88,13 +88,17 @@ export default defineComponent({
type: Boolean,
default: false
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
}
},
setup (props) {
const { ui, attrs } = useUI('accordion', props.ui, config, { mergeWrapper: true })
const { ui, attrs } = useUI('accordion', toRef(props, 'ui'), config, toRef(props, 'class'))
const uiButton = computed<Partial<typeof configButton>>(() => configButton)

View File

@@ -32,7 +32,7 @@
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { computed, toRef, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge'
import UIcon from '../elements/Icon.vue'
@@ -97,6 +97,10 @@ export default defineComponent({
].includes(value)
}
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
@@ -104,7 +108,7 @@ export default defineComponent({
},
emits: ['close'],
setup (props) {
const { ui, attrs, attrsClass } = useUI('alert', props.ui, config)
const { ui, attrs } = useUI('alert', toRef(props, 'ui'), config)
const alertClass = computed(() => {
const variant = ui.value.color?.[props.color as string]?.[props.variant as string] || ui.value.variant[props.variant]
@@ -115,7 +119,7 @@ export default defineComponent({
ui.value.shadow,
ui.value.padding,
variant?.replaceAll('{color}', props.color)
), attrsClass)
), props.class)
})
return {

View File

@@ -20,7 +20,7 @@
</template>
<script lang="ts">
import { defineComponent, ref, computed, watch } from 'vue'
import { defineComponent, ref, computed, toRef, watch } from 'vue'
import type { PropType } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge'
import UIcon from '../elements/Icon.vue'
@@ -84,13 +84,17 @@ export default defineComponent({
type: String,
default: ''
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
}
},
setup (props) {
const { ui, attrs, attrsClass } = useUI('avatar', props.ui, config)
const { ui, attrs } = useUI('avatar', toRef(props, 'ui'), config)
const url = computed(() => {
if (typeof props.src === 'boolean') {
@@ -109,7 +113,7 @@ export default defineComponent({
(error.value || !url.value) && ui.value.background,
ui.value.rounded,
ui.value.size[props.size]
), attrsClass)
), props.class)
})
const imgClass = computed(() => {

View File

@@ -1,4 +1,4 @@
import { h, cloneVNode, computed, defineComponent } from 'vue'
import { h, cloneVNode, computed, toRef, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge'
import UAvatar from './Avatar.vue'
@@ -27,13 +27,17 @@ export default defineComponent({
type: Number,
default: null
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof avatarGroupConfig & { strategy?: Strategy }>>,
default: undefined
}
},
setup (props, { slots }) {
const { ui, attrs } = useUI('avatarGroup', props.ui, avatarGroupConfig, { mergeWrapper: true })
const { ui, attrs } = useUI('avatarGroup', toRef(props, 'ui'), avatarGroupConfig, toRef(props, 'class'))
const children = computed(() => getSlotsChildren(slots))

View File

@@ -5,7 +5,7 @@
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { computed, toRef, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge'
import { useUI } from '../../composables/useUI'
@@ -49,13 +49,17 @@ export default defineComponent({
type: [String, Number],
default: null
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
}
},
setup (props) {
const { ui, attrs, attrsClass } = useUI('badge', props.ui, config)
const { ui, attrs } = useUI('badge', toRef(props, 'ui'), config)
const badgeClass = computed(() => {
const variant = ui.value.color?.[props.color as string]?.[props.variant as string] || ui.value.variant[props.variant]
@@ -66,7 +70,7 @@ export default defineComponent({
ui.value.rounded,
ui.value.size[props.size],
variant?.replaceAll('{color}', props.color)
), attrsClass)
), props.class)
})
return {

View File

@@ -17,7 +17,7 @@
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { computed, defineComponent, toRef } from 'vue'
import type { PropType } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge'
import UIcon from '../elements/Icon.vue'
@@ -118,13 +118,17 @@ export default defineComponent({
type: Boolean,
default: false
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
}
},
setup (props, { slots }) {
const { ui, attrs, attrsClass } = useUI('button', props.ui, config)
const { ui, attrs } = useUI('button', toRef(props, 'ui'), config)
const isLeading = computed(() => {
return (props.icon && props.leading) || (props.icon && !props.trailing) || (props.loading && !props.trailing) || props.leadingIcon
@@ -148,7 +152,7 @@ export default defineComponent({
props.padded && ui.value[isSquare.value ? 'square' : 'padding'][props.size],
variant?.replaceAll('{color}', props.color),
props.block ? 'w-full flex justify-center items-center' : 'inline-flex items-center'
), attrsClass)
), props.class)
})
const leadingIconName = computed(() => {

View File

@@ -1,4 +1,4 @@
import { h, cloneVNode, computed, defineComponent } from 'vue'
import { h, cloneVNode, computed, toRef, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge'
import { useUI } from '../../composables/useUI'
@@ -28,13 +28,17 @@ export default defineComponent({
return ['horizontal', 'vertical'].includes(value)
}
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof buttonGroupConfig & { strategy?: Strategy }>>,
default: undefined
}
},
setup (props, { slots }) {
const { ui, attrs, attrsClass } = useUI('buttonGroup', props.ui, buttonGroupConfig)
const { ui, attrs } = useUI('buttonGroup', toRef(props, 'ui'), buttonGroupConfig)
const children = computed(() => getSlotsChildren(slots))
@@ -80,7 +84,7 @@ export default defineComponent({
ui.value.wrapper[props.orientation],
ui.value.rounded,
ui.value.shadow
), attrsClass)
), props.class)
})
return () => h('div', { class: wrapperClass.value, ...attrs.value }, clones.value)

View File

@@ -45,7 +45,7 @@
</template>
<script lang="ts">
import { defineComponent, ref, computed, onMounted } from 'vue'
import { defineComponent, ref, computed, toRef, onMounted } from 'vue'
import type { PropType } from 'vue'
import { Menu as HMenu, MenuButton as HMenuButton, MenuItems as HMenuItems, MenuItem as HMenuItem } from '@headlessui/vue'
import { defu } from 'defu'
@@ -101,13 +101,17 @@ export default defineComponent({
type: Number,
default: 0
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
}
},
setup (props) {
const { ui, attrs } = useUI('dropdown', props.ui, config, { mergeWrapper: true })
const { ui, attrs } = useUI('dropdown', toRef(props, 'ui'), config, toRef(props, 'class'))
const popper = computed<PopperOptions>(() => defu(props.mode === 'hover' ? { offsetDistance: 0 } : {}, props.popper, ui.value.popper as PopperOptions))

View File

@@ -5,7 +5,7 @@
</template>
<script lang="ts">
import { defineComponent, computed } from 'vue'
import { toRef, defineComponent, computed } from 'vue'
import type { PropType } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge'
import { useUI } from '../../composables/useUI'
@@ -31,13 +31,17 @@ export default defineComponent({
return Object.keys(config.size).includes(value)
}
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
}
},
setup (props) {
const { ui, attrs, attrsClass } = useUI('kbd', props.ui, config)
const { ui, attrs } = useUI('kbd', toRef(props, 'ui'), config)
const kbdClass = computed(() => {
return twMerge(twJoin(
@@ -48,7 +52,7 @@ export default defineComponent({
ui.value.font,
ui.value.background,
ui.value.ring
), attrsClass)
), props.class)
})
return {

View File

@@ -30,7 +30,7 @@
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { computed, toRef, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge'
import { useUI } from '../../composables/useUI'
@@ -100,6 +100,10 @@ export default defineComponent({
type: String,
default: ''
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
@@ -107,7 +111,7 @@ export default defineComponent({
},
emits: ['update:modelValue', 'change'],
setup (props, { emit }) {
const { ui, attrs } = useUI('checkbox', props.ui, config, { mergeWrapper: true })
const { ui, attrs } = useUI('checkbox', toRef(props, 'ui'), config, toRef(props, 'class'))
const { emitFormChange, color, name, inputId } = useFormGroup(props)

View File

@@ -20,7 +20,7 @@
</template>
<script lang="ts">
import { computed, defineComponent, provide, inject, ref } from 'vue'
import { computed, defineComponent, provide, inject, ref, toRef } from 'vue'
import type { Ref, PropType } from 'vue'
import { useUI } from '../../composables/useUI'
import { mergeConfig } from '../../utils'
@@ -70,13 +70,17 @@ export default defineComponent({
type: String,
default: null
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
}
},
setup (props) {
const { ui, attrs } = useUI('formGroup', props.ui, config, { mergeWrapper: true })
const { ui, attrs } = useUI('formGroup', toRef(props, 'ui'), config, toRef(props, 'class'))
const formErrors = inject<Ref<FormError[]> | null>('form-errors', null)

View File

@@ -32,7 +32,7 @@
</template>
<script lang="ts">
import { ref, computed, onMounted, defineComponent } from 'vue'
import { ref, computed, toRef, onMounted, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge'
import UIcon from '../elements/Icon.vue'
@@ -145,6 +145,10 @@ export default defineComponent({
type: String,
default: null
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
@@ -152,7 +156,7 @@ export default defineComponent({
},
emits: ['update:modelValue', 'blur'],
setup (props, { emit, slots }) {
const { ui, attrs } = useUI('input', props.ui, config, { mergeWrapper: true })
const { ui, attrs } = useUI('input', toRef(props, 'ui'), config, toRef(props, 'class'))
const { emitFormBlur, emitFormInput, size, color, inputId, name } = useFormGroup(props, config)

View File

@@ -27,7 +27,7 @@
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { computed, toRef, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge'
import { useUI } from '../../composables/useUI'
@@ -89,6 +89,10 @@ export default defineComponent({
type: String,
default: null
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
@@ -96,7 +100,7 @@ export default defineComponent({
},
emits: ['update:modelValue'],
setup (props, { emit }) {
const { ui, attrs } = useUI('radio', props.ui, config, { mergeWrapper: true })
const { ui, attrs } = useUI('radio', toRef(props, 'ui'), config, toRef(props, 'class'))
const { emitFormChange, color, name, inputId } = useFormGroup(props)

View File

@@ -20,7 +20,7 @@
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { computed, toRef, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge'
import { useUI } from '../../composables/useUI'
@@ -83,6 +83,10 @@ export default defineComponent({
type: String,
default: null
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
@@ -90,7 +94,7 @@ export default defineComponent({
},
emits: ['update:modelValue', 'change'],
setup (props, { emit }) {
const { ui, attrs, attrsClass } = useUI('range', props.ui, config)
const { ui, attrs } = useUI('range', toRef(props, 'ui'), config)
const { emitFormChange, inputId, color, size, name } = useFormGroup(props, config)
@@ -112,7 +116,7 @@ export default defineComponent({
return twMerge(twJoin(
ui.value.wrapper,
ui.value.size[size.value]
), attrsClass)
), props.class)
})
const inputClass = computed(() => {

View File

@@ -54,7 +54,7 @@
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { computed, toRef, defineComponent } from 'vue'
import type { PropType, ComputedRef } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge'
import UIcon from '../elements/Icon.vue'
@@ -171,6 +171,10 @@ export default defineComponent({
type: String,
default: null
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
@@ -178,7 +182,7 @@ export default defineComponent({
},
emits: ['update:modelValue', 'change'],
setup (props, { emit, slots }) {
const { ui, attrs } = useUI('select', props.ui, config, { mergeWrapper: true })
const { ui, attrs } = useUI('select', toRef(props, 'ui'), config, toRef(props, 'class'))
const { emitFormChange, inputId, color, size, name } = useFormGroup(props, config)

View File

@@ -116,7 +116,7 @@
</template>
<script lang="ts">
import { ref, computed, watch, defineComponent } from 'vue'
import { ref, computed, toRef, watch, defineComponent } from 'vue'
import type { PropType, ComponentPublicInstance } from 'vue'
import {
Combobox as HCombobox,
@@ -296,6 +296,10 @@ export default defineComponent({
type: String,
default: null
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
@@ -307,9 +311,9 @@ export default defineComponent({
},
emits: ['update:modelValue', 'open', 'close', 'change'],
setup (props, { emit, slots }) {
const { ui, attrs } = useUI('select', props.ui, config, { mergeWrapper: true })
const { ui, attrs } = useUI('select', toRef(props, 'ui'), config, toRef(props, 'class'))
const { ui: uiMenu } = useUI('selectMenu', props.uiMenu, configMenu)
const { ui: uiMenu } = useUI('selectMenu', toRef(props, 'uiMenu'), configMenu)
const popper = computed<PopperOptions>(() => defu({}, props.popper, uiMenu.value.popper as PopperOptions))

View File

@@ -19,7 +19,7 @@
</template>
<script lang="ts">
import { ref, computed, watch, onMounted, nextTick, defineComponent } from 'vue'
import { ref, computed, toRef, watch, onMounted, nextTick, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge'
import { useUI } from '../../composables/useUI'
@@ -108,6 +108,10 @@ export default defineComponent({
type: String,
default: null
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
@@ -115,7 +119,7 @@ export default defineComponent({
},
emits: ['update:modelValue', 'blur'],
setup (props, { emit }) {
const { ui, attrs } = useUI('textarea', props.ui, config, { mergeWrapper: true })
const { ui, attrs } = useUI('textarea', toRef(props, 'ui'), config, toRef(props, 'class'))
const { emitFormBlur, emitFormInput, inputId, color, size, name } = useFormGroup(props, config)

View File

@@ -19,7 +19,7 @@
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { computed, toRef, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { Switch as HSwitch } from '@headlessui/vue'
import { twMerge, twJoin } from 'tailwind-merge'
@@ -73,6 +73,10 @@ export default defineComponent({
return appConfig.ui.colors.includes(value)
}
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
@@ -80,7 +84,7 @@ export default defineComponent({
},
emits: ['update:modelValue'],
setup (props, { emit }) {
const { ui, attrs, attrsClass } = useUI('toggle', props.ui, config)
const { ui, attrs } = useUI('toggle', toRef(props, 'ui'), config)
const { emitFormChange, color, inputId, name } = useFormGroup(props)
@@ -100,7 +104,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)
), attrsClass)
), props.class)
})
const onIconClass = computed(() => {

View File

@@ -17,7 +17,7 @@
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { computed, toRef, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge'
import { useUI } from '../../composables/useUI'
@@ -36,13 +36,17 @@ export default defineComponent({
type: String,
default: 'div'
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
}
},
setup (props) {
const { ui, attrs, attrsClass } = useUI('card', props.ui, config)
const { ui, attrs } = useUI('card', toRef(props, 'ui'), config)
const cardClass = computed(() => {
return twMerge(twJoin(
@@ -52,7 +56,7 @@ export default defineComponent({
ui.value.ring,
ui.value.shadow,
ui.value.background
), attrsClass)
), props.class)
})
return {

View File

@@ -5,7 +5,7 @@
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { computed, toRef, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge'
import { useUI } from '../../composables/useUI'
@@ -24,20 +24,24 @@ export default defineComponent({
type: String,
default: 'div'
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
}
},
setup (props) {
const { ui, attrs, attrsClass } = useUI('container', props.ui, config)
const { ui, attrs } = useUI('container', toRef(props, 'ui'), config)
const containerClass = computed(() => {
return twMerge(twJoin(
ui.value.base,
ui.value.padding,
ui.value.constrained
), attrsClass)
), props.class)
})
return {

View File

@@ -3,7 +3,7 @@
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { computed, toRef, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge'
import { useUI } from '../../composables/useUI'
@@ -18,20 +18,24 @@ const config = mergeConfig<typeof skeleton>(appConfig.ui.strategy, appConfig.ui.
export default defineComponent({
inheritAttrs: false,
props: {
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
}
},
setup (props) {
const { ui, attrs, attrsClass } = useUI('skeleton', props.ui, config)
const { ui, attrs } = useUI('skeleton', toRef(props, 'ui'), config)
const skeletonClass = computed(() => {
return twMerge(twJoin(
ui.value.base,
ui.value.background,
ui.value.rounded
), attrsClass)
), props.class)
})
return {

View File

@@ -62,7 +62,7 @@
</template>
<script lang="ts">
import { ref, computed, watch, onMounted, defineComponent } from 'vue'
import { ref, computed, watch, toRef, onMounted, defineComponent } from 'vue'
import { Combobox as HCombobox, ComboboxInput as HComboboxInput, ComboboxOptions as HComboboxOptions } from '@headlessui/vue'
import type { ComputedRef, PropType, ComponentPublicInstance } from 'vue'
import { useDebounceFn } from '@vueuse/core'
@@ -169,6 +169,10 @@ export default defineComponent({
type: Object as PropType<UseFuseOptions<Command>>,
default: () => ({})
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
@@ -176,7 +180,7 @@ export default defineComponent({
},
emits: ['update:modelValue', 'close'],
setup (props, { emit, expose }) {
const { ui, attrs } = useUI('commandPalette', props.ui, config, { mergeWrapper: true })
const { ui, attrs } = useUI('commandPalette', toRef(props, 'ui'), config, toRef(props, 'class'))
const query = ref('')
const comboboxInput = ref<ComponentPublicInstance<HTMLInputElement>>()

View File

@@ -40,7 +40,7 @@
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { computed, toRef, defineComponent } from 'vue'
import type { PropType } from 'vue'
import UButton from '../elements/Button.vue'
import { useUI } from '../../composables/useUI'
@@ -106,6 +106,10 @@ export default defineComponent({
type: String,
default: '…'
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
@@ -113,7 +117,7 @@ export default defineComponent({
},
emits: ['update:modelValue'],
setup (props, { emit }) {
const { ui, attrs } = useUI('pagination', props.ui, config, { mergeWrapper: true })
const { ui, attrs } = useUI('pagination', toRef(props, 'ui'), config, toRef(props, 'class'))
const currentPage = computed({
get () {

View File

@@ -49,7 +49,7 @@
</template>
<script lang="ts">
import { ref, watch, onMounted, defineComponent } from 'vue'
import { toRef, ref, watch, onMounted, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { TabGroup as HTabGroup, TabList as HTabList, Tab as HTab, TabPanels as HTabPanels, TabPanel as HTabPanel } from '@headlessui/vue'
import { useResizeObserver } from '@vueuse/core'
@@ -89,6 +89,10 @@ export default defineComponent({
type: Array as PropType<TabItem[]>,
default: () => []
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
@@ -96,7 +100,7 @@ export default defineComponent({
},
emits: ['update:modelValue', 'change'],
setup (props, { emit }) {
const { ui, attrs } = useUI('tabs', props.ui, config, { mergeWrapper: true })
const { ui, attrs } = useUI('tabs', toRef(props, 'ui'), config, toRef(props, 'class'))
const listRef = ref<HTMLElement>()
const itemRefs = ref<HTMLElement[]>([])

View File

@@ -38,7 +38,7 @@
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { toRef, defineComponent } from 'vue'
import type { PropType } from 'vue'
import UIcon from '../elements/Icon.vue'
import UAvatar from '../elements/Avatar.vue'
@@ -64,13 +64,17 @@ export default defineComponent({
type: Array as PropType<VerticalNavigationLink[]>,
default: () => []
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
}
},
setup (props) {
const { ui, attrs } = useUI('verticalNavigation', props.ui, config, { mergeWrapper: true })
const { ui, attrs } = useUI('verticalNavigation', toRef(props, 'ui'), config, toRef(props, 'class'))
return {
// eslint-disable-next-line vue/no-dupe-keys

View File

@@ -40,6 +40,10 @@ export default defineComponent({
type: Object as PropType<PopperOptions>,
default: () => ({})
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
@@ -47,7 +51,7 @@ export default defineComponent({
},
emits: ['update:modelValue', 'close'],
setup (props, { emit }) {
const { ui, attrs, attrsClass } = useUI('contextMenu', props.ui, config)
const { ui, attrs } = useUI('contextMenu', toRef(props, 'ui'), config)
const popper = computed<PopperOptions>(() => defu({}, props.popper, ui.value.popper as PopperOptions))
@@ -68,7 +72,7 @@ export default defineComponent({
return twMerge(twJoin(
ui.value.container,
ui.value.width
), attrsClass)
), props.class)
})
onClickOutside(container, () => {

View File

@@ -30,7 +30,7 @@
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { computed, toRef, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { Dialog as HDialog, DialogPanel as HDialogPanel, TransitionRoot, TransitionChild } from '@headlessui/vue'
import { useUI } from '../../composables/useUI'
@@ -75,6 +75,10 @@ export default defineComponent({
type: Boolean,
default: false
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
@@ -82,7 +86,7 @@ export default defineComponent({
},
emits: ['update:modelValue', 'close'],
setup (props, { emit }) {
const { ui, attrs } = useUI('modal', props.ui, config, { mergeWrapper: true })
const { ui, attrs } = useUI('modal', toRef(props, 'ui'), config, toRef(props, 'class'))
const isOpen = computed({
get () {

View File

@@ -39,7 +39,7 @@
</template>
<script lang="ts">
import { ref, computed, onMounted, onUnmounted, watchEffect, defineComponent } from 'vue'
import { ref, computed, toRef, onMounted, onUnmounted, watchEffect, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge'
import UIcon from '../elements/Icon.vue'
@@ -106,6 +106,10 @@ export default defineComponent({
return ['gray', ...appConfig.ui.colors].includes(value)
}
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
@@ -113,7 +117,7 @@ export default defineComponent({
},
emits: ['close'],
setup (props, { emit }) {
const { ui, attrs, attrsClass } = useUI('notification', props.ui, config)
const { ui, attrs } = useUI('notification', toRef(props, 'ui'), config)
let timer: any = null
const remaining = ref(props.timeout)
@@ -124,7 +128,7 @@ export default defineComponent({
ui.value.background,
ui.value.rounded,
ui.value.shadow
), attrsClass)
), props.class)
})
const progressClass = computed(() => {

View File

@@ -18,7 +18,7 @@
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { computed, toRef, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge'
import UNotification from './Notification.vue'
@@ -39,13 +39,17 @@ export default defineComponent({
},
inheritAttrs: false,
props: {
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
}
},
setup (props) {
const { ui, attrs, attrsClass } = useUI('notifications', props.ui, config)
const { ui, attrs } = useUI('notifications', toRef(props, 'ui'), config)
const toast = useToast()
const notifications = useState<Notification[]>('notifications', () => [])
@@ -55,7 +59,7 @@ export default defineComponent({
ui.value.wrapper,
ui.value.position,
ui.value.width
), attrsClass)
), props.class)
})
return {

View File

@@ -26,7 +26,7 @@
</template>
<script lang="ts">
import { computed, ref, onMounted, defineComponent } from 'vue'
import { computed, ref, toRef, onMounted, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { defu } from 'defu'
import { Popover as HPopover, PopoverButton as HPopoverButton, PopoverPanel as HPopoverPanel } from '@headlessui/vue'
@@ -69,13 +69,17 @@ export default defineComponent({
type: Object as PropType<PopperOptions>,
default: () => ({})
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
}
},
setup (props) {
const { ui, attrs } = useUI('popover', props.ui, config, { mergeWrapper: true })
const { ui, attrs } = useUI('popover', toRef(props, 'ui'), config, toRef(props, 'class'))
const popper = computed<PopperOptions>(() => defu(props.mode === 'hover' ? { offsetDistance: 0 } : {}, props.popper, ui.value.popper as PopperOptions))

View File

@@ -15,7 +15,7 @@
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { computed, toRef, defineComponent } from 'vue'
import type { WritableComputedRef, PropType } from 'vue'
import { Dialog as HDialog, DialogPanel as HDialogPanel, TransitionRoot, TransitionChild } from '@headlessui/vue'
import { useUI } from '../../composables/useUI'
@@ -61,6 +61,10 @@ export default defineComponent({
type: Boolean,
default: false
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
@@ -68,7 +72,7 @@ export default defineComponent({
},
emits: ['update:modelValue', 'close'],
setup (props, { emit }) {
const { ui, attrs } = useUI('slideover', props.ui, config, { mergeWrapper: true })
const { ui, attrs } = useUI('slideover', toRef(props, 'ui'), config, toRef(props, 'class'))
const isOpen: WritableComputedRef<boolean> = computed({
get () {

View File

@@ -24,7 +24,7 @@
</template>
<script lang="ts">
import { computed, ref, defineComponent } from 'vue'
import { computed, ref, toRef, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { defu } from 'defu'
import UKbd from '../elements/Kbd.vue'
@@ -68,13 +68,17 @@ export default defineComponent({
type: Object as PropType<PopperOptions>,
default: () => ({})
},
class: {
type: [String, Object, Array] as PropType<any>,
default: undefined
},
ui: {
type: Object as PropType<Partial<typeof config & { strategy?: Strategy }>>,
default: undefined
}
},
setup (props) {
const { ui, attrs } = useUI('tooltip', props.ui, config, { mergeWrapper: true })
const { ui, attrs } = useUI('tooltip', toRef(props, 'ui'), config, toRef(props, 'class'))
const popper = computed<PopperOptions>(() => defu({}, props.popper, ui.value.popper as PopperOptions))

View File

@@ -1,24 +1,30 @@
import { computed, toValue, useAttrs } from 'vue'
import type { Ref } from 'vue'
import { useAppConfig } from '#imports'
import { mergeConfig, omit, get } from '../utils'
import { Strategy } from '../types'
export const useUI = <T>(key, $ui: Partial<T & { strategy: Strategy }>, $config?: T, { mergeWrapper = false }: { mergeWrapper?: boolean } = {}) => {
export const useUI = <T>(key, $ui: Ref<Partial<T & { strategy: Strategy }> | undefined>, $config?: Ref<T> | T, $wrapperClass?: Ref<string>) => {
const $attrs = useAttrs()
const appConfig = useAppConfig()
const ui = computed(() => mergeConfig<T>(
$ui?.strategy || (appConfig.ui?.strategy as Strategy),
mergeWrapper ? { wrapper: $attrs?.class } : {},
$ui || {},
process.dev ? get(appConfig.ui, key, {}) : {},
toValue($config || {})
))
const ui = computed(() => {
const _ui = toValue($ui)
const _config = toValue($config)
const _wrapperClass = toValue($wrapperClass)
return mergeConfig<T>(
_ui?.strategy || (appConfig.ui?.strategy as Strategy),
_wrapperClass ? { wrapper: _wrapperClass } : {},
_ui || {},
process.dev ? get(appConfig.ui, key, {}) : {},
_config || {}
)
})
const attrs = computed(() => omit($attrs, ['class']))
return {
ui,
attrs,
attrsClass: mergeWrapper ? undefined : $attrs?.class as string
attrs
}
}