genCall,
} from './generators/utils'
import { setTemplateRefIdent } from './generators/templateRef'
+import { createForwardedSlotIdent } from './generators/slotOutlet'
export type CodegenOptions = Omit<BaseCodegenOptions, 'optimizeImports'>
`const ${setTemplateRefIdent} = ${context.helper('createTemplateRefSetter')}()`,
)
}
+ if (ir.hasForwardedSlot) {
+ push(
+ NEWLINE,
+ `const ${createForwardedSlotIdent} = ${context.helper('forwardedSlotCreator')}()`,
+ )
+ }
push(...genBlockContent(ir.block, context, true))
push(INDENT_END, NEWLINE)
import { type CodeFragment, NEWLINE, buildCodeFragment, genCall } from './utils'
import { genRawProps } from './component'
+export const createForwardedSlotIdent = `_createForwardedSlot`
+
export function genSlotOutlet(
oper: SlotOutletIRNode,
context: CodegenContext,
): CodeFragment[] {
const { helper } = context
- const { id, name, fallback } = oper
+ const { id, name, fallback, forwarded } = oper
const [frag, push] = buildCodeFragment()
const nameExpr = name.isStatic
NEWLINE,
`const n${id} = `,
...genCall(
- helper('createSlot'),
+ forwarded ? createForwardedSlotIdent : helper('createSlot'),
nameExpr,
genRawProps(oper.props, context) || 'null',
fallbackArg,
directive: Set<string>
block: BlockIRNode
hasTemplateRef: boolean
+ hasForwardedSlot: boolean
}
export interface IfIRNode extends BaseIRNode {
name: SimpleExpressionNode
props: IRProps[]
fallback?: BlockIRNode
+ forwarded?: boolean
parent?: number
anchor?: number
}
directive: new Set(),
block: newBlock(node),
hasTemplateRef: false,
+ hasForwardedSlot: false,
}
const context = new TransformContext(ir, node, options)
ErrorCodes,
NodeTypes,
type SimpleExpressionNode,
+ type TemplateChildNode,
createCompilerError,
createSimpleExpression,
isStaticArgOf,
}
return () => {
+ let forwarded = false
+ const slotNode = context.block.node
+ if (slotNode.type === NodeTypes.ELEMENT) {
+ forwarded = hasForwardedSlots(slotNode.children)
+ }
+ if (forwarded) context.ir.hasForwardedSlot = true
+
exitBlock && exitBlock()
context.dynamic.operation = {
type: IRNodeTypes.SLOT_OUTLET_NODE,
name: slotName,
props: irProps,
fallback,
+ forwarded,
}
}
}
context.reference()
return [fallback, exitBlock]
}
+
+// TODO
+function hasForwardedSlots(children: TemplateChildNode[]): boolean {
+ for (let i = 0; i < children.length; i++) {
+ const child = children[i]
+ switch (child.type) {
+ case NodeTypes.ELEMENT:
+ if (
+ child.tagType === ElementTypes.SLOT ||
+ hasForwardedSlots(child.children)
+ ) {
+ return true
+ }
+ break
+ }
+ }
+ return false
+}
}
}
+export function forwardedSlotCreator(): (
+ name: string | (() => string),
+ rawProps?: LooseRawProps | null,
+ fallback?: VaporSlot,
+) => Block {
+ const instance = currentInstance as VaporComponentInstance
+ return (
+ name: string | (() => string),
+ rawProps?: LooseRawProps | null,
+ fallback?: VaporSlot,
+ ) => createSlot(name, rawProps, fallback, instance)
+}
+
export function createSlot(
name: string | (() => string),
rawProps?: LooseRawProps | null,
fallback?: VaporSlot,
+ i?: VaporComponentInstance,
): Block {
const _insertionParent = insertionParent
const _insertionAnchor = insertionAnchor
locateHydrationNode()
}
- const instance = currentInstance as VaporComponentInstance
+ const instance = i || (currentInstance as VaporComponentInstance)
const rawSlots = instance.rawSlots
const slotProps = rawProps
? new Proxy(rawProps, rawPropsProxyHandlers)
export { setInsertionState } from './insertionState'
export { createComponent, createComponentWithFallback } from './component'
export { renderEffect } from './renderEffect'
-export { createSlot } from './componentSlots'
+export { createSlot, forwardedSlotCreator } from './componentSlots'
export { template } from './dom/template'
export { createTextNode, child, nthChild, next } from './dom/node'
export {