diff --git a/packages/core/createReusableTemplate/index.ts b/packages/core/createReusableTemplate/index.ts index ba1ccb1c6e4..4d253cabdd7 100644 --- a/packages/core/createReusableTemplate/index.ts +++ b/packages/core/createReusableTemplate/index.ts @@ -2,29 +2,35 @@ import type { DefineComponent, Slot } from 'vue-demi' import { defineComponent, isVue3, shallowRef, version } from 'vue-demi' import { camelize, makeDestructurable } from '@vueuse/shared' +type ObjectLiteralWithPotentialObjectLiterals = Record | undefined> + +type GenerateSlotsFromSlotMap = { + [K in keyof T]: Slot +} + export type DefineTemplateComponent< - Bindings extends object, - Slots extends Record, -> = DefineComponent<{}> & { - new(): { $slots: { default: (_: Bindings & { $slots: Slots }) => any } } + Bindings extends Record, + MapSlotNameToSlotProps extends ObjectLiteralWithPotentialObjectLiterals, +> = DefineComponent & { + new(): { $slots: { default: (_: Bindings & { $slots: GenerateSlotsFromSlotMap }) => any } } } export type ReuseTemplateComponent< - Bindings extends object, - Slots extends Record, + Bindings extends Record, + MapSlotNameToSlotProps extends ObjectLiteralWithPotentialObjectLiterals, > = DefineComponent & { - new(): { $slots: Slots } + new(): { $slots: GenerateSlotsFromSlotMap } } export type ReusableTemplatePair< - Bindings extends object, - Slots extends Record, + Bindings extends Record, + MapSlotNameToSlotProps extends ObjectLiteralWithPotentialObjectLiterals, > = [ - DefineTemplateComponent, - ReuseTemplateComponent, + DefineTemplateComponent, + ReuseTemplateComponent, ] & { - define: DefineTemplateComponent - reuse: ReuseTemplateComponent + define: DefineTemplateComponent + reuse: ReuseTemplateComponent } export interface CreateReusableTemplateOptions { @@ -43,11 +49,11 @@ export interface CreateReusableTemplateOptions { * @see https://vueuse.org/createReusableTemplate */ export function createReusableTemplate< - Bindings extends object, - Slots extends Record = Record, + Bindings extends Record, + MapSlotNameToSlotProps extends ObjectLiteralWithPotentialObjectLiterals = Record<'default', undefined>, >( options: CreateReusableTemplateOptions = {}, -): ReusableTemplatePair { +): ReusableTemplatePair { // compatibility: Vue 2.7 or above if (!isVue3 && !version.startsWith('2.7.')) { if (process.env.NODE_ENV !== 'production') @@ -68,7 +74,7 @@ export function createReusableTemplate< render.value = slots.default } }, - }) as unknown as DefineTemplateComponent + }) as unknown as DefineTemplateComponent const reuse = defineComponent({ inheritAttrs, @@ -77,10 +83,11 @@ export function createReusableTemplate< if (!render.value && process.env.NODE_ENV !== 'production') throw new Error('[VueUse] Failed to find the definition of reusable template') const vnode = render.value?.({ ...keysToCamelKebabCase(attrs), $slots: slots }) + return (inheritAttrs && vnode?.length === 1) ? vnode[0] : vnode } }, - }) as unknown as ReuseTemplateComponent + }) as unknown as ReuseTemplateComponent return makeDestructurable( { define, reuse },