Skip to content

Commit

Permalink
docs: show exposed properties for components forwarding Elements
Browse files Browse the repository at this point in the history
closes #19180
  • Loading branch information
KaelWD committed Aug 26, 2024
1 parent 7e9a1b7 commit 42dba04
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 32 deletions.
35 changes: 10 additions & 25 deletions packages/api-generator/templates/component.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { AllowedComponentProps, ComponentPublicInstance, FunctionalComponent, RenderFunction, VNodeChild, VNodeProps } from 'vue'
import type { AllowedComponentProps, ComponentOptionsBase, VNodeChild, VNodeProps, UnwrapRef } from 'vue'
import type { UnionToIntersection } from '@/util'
import type { __component__ } from '@/__name__'

type StripProps = keyof VNodeProps | keyof AllowedComponentProps | 'v-slots' | '$children' | `v-slot:${string}`
Expand Down Expand Up @@ -26,17 +27,6 @@ type Events<T> = T extends { $props: infer P extends object }
export type ComponentProps = Props<__component__>
export type ComponentEvents = Events<__component__>

type RemoveIndex<T> = {
[K in keyof T as string extends K
? never
: number extends K
? never
: symbol extends K
? never
: K
]: T[K]
}

type Slot<T extends any[] = any[]> = (...args: T) => VNodeChild
type Slots<
T extends { $props: any },
Expand All @@ -50,18 +40,13 @@ type ExcludeEmpty<T> = T extends AtLeastOne<T> ? T : never

export type ComponentSlots = Slots<__component__>

type ExtractExposed<T> = T extends (...args: any[]) => infer R
? R extends Promise<any>
? never
: R extends RenderFunction
? never
: R extends void
? never
: R extends HTMLElement
? never
: R extends object
? RemoveIndex<R>
: never
type ExtractExposed<T> = T extends ComponentOptionsBase<any, infer B, any, any, any, any, any, any>
? B extends void ? never
: B extends { _allExposed: infer E } ? E
: B extends object ? B
: never
: never

export type ComponentExposed = ExtractExposed<__component__['$options']['setup']>
type Pretty<T> = { [K in keyof T]: UnwrapRef<T[K]> }

export type ComponentExposed = Pretty<UnionToIntersection<ExtractExposed<__component__['$options']>>>
31 changes: 24 additions & 7 deletions packages/vuetify/src/composables/forwardRefs.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
// Types
import type { ComponentPublicInstance, Ref, UnwrapRef } from 'vue'
import type { ComponentOptionsBase, ComponentPublicInstance, Ref, UnwrapRef } from 'vue'
import type { UnionToIntersection } from '@/util'

const Refs = Symbol('Forwarded refs')

/** Omit properties starting with P */
type OmitPrefix<T, P extends string> = [Extract<keyof T, `${P}${any}`>] extends [never] ? T : Omit<T, `${P}${any}`>

type OmitPrefix<
T,
P extends string,
E = Extract<keyof T, `${P}${any}`>,
> = [E] extends [never] ? T : Omit<T, `${P}${any}`>
type OmitPrivate<T> = OmitPrefix<T, '$'>

/** Omit keyof $props from T */
type OmitProps<T> = T extends { $props: any } ? Omit<T, keyof T['$props']> : T

function getDescriptor (obj: any, key: PropertyKey) {
Expand All @@ -19,10 +25,21 @@ function getDescriptor (obj: any, key: PropertyKey) {
return undefined
}

export function forwardRefs<T extends {}, U extends Ref<HTMLElement | Omit<ComponentPublicInstance, '$emit' | '$slots'> | undefined>[]> (
target: T,
...refs: U
): T & UnionToIntersection<{ [K in keyof U]: OmitPrefix<OmitProps<NonNullable<UnwrapRef<U[K]>>>, '$'> }[number]> {
export function forwardRefs<
T extends {},
U extends Ref<HTMLElement | Omit<ComponentPublicInstance, '$emit' | '$slots'> | undefined>[],
UU = { [K in keyof U]: NonNullable<UnwrapRef<U[K]>> }[number],
UC = { [K in keyof U]: OmitPrivate<OmitProps<NonNullable<UnwrapRef<U[K]>>>> }[number],
R = T & UnionToIntersection<UC> & {
_allExposed: T | (
UU extends { $options: infer O }
? O extends ComponentOptionsBase<any, infer E, any, any, any, any, any, any>
? E
: never
: never
)
}
> (target: T, ...refs: U): R {
(target as any)[Refs] = refs

return new Proxy(target, {
Expand Down

0 comments on commit 42dba04

Please sign in to comment.