import { pauseTracking, proxyRefs, resetTracking } from '@vue/reactivity'
import { EMPTY_OBJ, invokeArrayFns, isFunction, isString } from '@vue/shared'
import {
+ type DynamicPropsSource,
type RawProps,
getPropsProxyHandlers,
hasFallthroughAttrs,
import { setStyle } from './dom/style'
import { setClass, setDynamicProp } from './dom/prop'
import {
+ type DynamicSlotSource,
type RawSlots,
type Slot,
type StaticSlots,
__emitsOptions?: ObjectEmitsOptions
}
+// In TypeScript, it is actually impossible to have a record type with only
+// specific properties that have a different type from the indexed type.
+// This makes our rawProps / rawSlots shape difficult to satisfy when calling
+// `createComponent` - luckily this is not user-facing, so we don't need to be
+// 100% strict. Here we use intentionally wider types to make `createComponent`
+// more ergonomic in tests and internal call sites, where we immediately cast
+// them into the stricter types.
+type LooseRawProps = Record<string, (() => unknown) | DynamicPropsSource[]> & {
+ $?: DynamicPropsSource[]
+}
+
+type LooseRawSlots = Record<string, Slot | DynamicSlotSource[]> & {
+ $?: DynamicSlotSource[]
+}
+
export function createComponent(
component: VaporComponent,
- rawProps?: RawProps | null,
- rawSlots?: RawSlots | null,
+ rawProps?: LooseRawProps | null,
+ rawSlots?: LooseRawSlots | null,
isSingleRoot?: boolean,
appContext?: GenericAppContext,
): VaporComponentInstance {
) {
const attrs = currentInstance.attrs
if (rawProps) {
- ;(rawProps.$ || (rawProps.$ = [])).push(() => attrs)
+ ;((rawProps as RawProps).$ || ((rawProps as RawProps).$ = [])).push(
+ () => attrs,
+ )
} else {
rawProps = { $: [() => attrs] } as RawProps
}
const instance = new VaporComponentInstance(
component,
- rawProps,
- rawSlots,
+ rawProps as RawProps,
+ rawSlots as RawSlots,
appContext,
)
import { renderEffect } from './renderEffect'
export type RawSlots = Record<string, Slot> & {
- $?: (StaticSlots | DynamicSlotFn)[]
+ $?: DynamicSlotSource[]
}
export type StaticSlots = Record<string, Slot>
export type Slot = BlockFn
export type DynamicSlot = { name: string; fn: Slot }
export type DynamicSlotFn = () => DynamicSlot | DynamicSlot[]
+export type DynamicSlotSource = StaticSlots | DynamicSlotFn
export const dynamicSlotsProxyHandlers: ProxyHandler<RawSlots> = {
get: getSlot,