protected abstract _mount(def: Def): void
protected abstract _update(): void
protected abstract _unmount(): void
+ protected abstract _updateSlotNodes(slot: Map<Node, Node[]>): void
constructor(
/**
replacementNodes.push(child)
}
}
-
+ parent.removeChild(o)
slotReplacements.set(o, replacementNodes)
}
- // For Vapor: update fragment nodes before removing slots from DOM
- if (slotReplacements.size > 0 && this._instance && this._instance.vapor) {
- // @ts-expect-error TODO refactor
- this._replaceNodesInFragments(this._instance.block, slotReplacements)
- }
-
- // Now safe to remove slots from DOM
- slotReplacements.forEach((_, o) => o.parentNode!.removeChild(o))
- }
-
- /**
- * Replace slot nodes with their content in fragment nodes arrays
- * @internal
- */
- private _replaceNodesInFragments(
- block: any,
- replacements: Map<Node, Node[]>,
- ): void {
- if (!block) return
-
- if (Array.isArray(block)) {
- for (let i = 0; i < block.length; i++) {
- this._replaceNodesInFragments(block[i], replacements)
- }
- } else if (block.nodes !== undefined) {
- // This is a fragment with nodes property
- if (Array.isArray(block.nodes)) {
- // Replace slot nodes with their content
- const newNodes: any[] = []
- for (const node of block.nodes) {
- if (node instanceof Node && replacements.has(node)) {
- // Replace with the content nodes
- newNodes.push(...replacements.get(node)!)
- } else {
- newNodes.push(node)
- // Recursively process nested fragments
- this._replaceNodesInFragments(node, replacements)
- }
- }
- block.nodes = newNodes
- } else if (block.nodes instanceof Node && replacements.has(block.nodes)) {
- // Replace single node with its content
- const replacement = replacements.get(block.nodes)!
- block.nodes = replacement.length === 1 ? replacement[0] : replacement
- } else {
- this._replaceNodesInFragments(block.nodes, replacements)
- }
- }
+ this._updateSlotNodes(slotReplacements)
}
/**
this._app = this._instance = null
}
+ /**
+ * Only called when shadowRoot is false
+ */
+ protected _updateSlotNodes(replacements: Map<Node, Node[]>): void {
+ // do nothing
+ }
+
private _createVNode(): VNode<any, any> {
const baseProps: VNodeProps = {}
if (!this.shadowRoot) {
import { extend, isPlainObject } from '@vue/shared'
-import { createComponent, createVaporApp, defineVaporComponent } from '.'
+import {
+ createComponent,
+ createVaporApp,
+ defineVaporComponent,
+ isFragment,
+} from '.'
import {
type CreateAppFunction,
type CustomElementOptions,
VaporComponent,
VaporComponentInstance,
} from './component'
+import type { Block } from './block'
export type VaporElementConstructor<P = {}> = {
new (initialProps?: Record<string, any>): VaporElement & P
this._app = this._instance = null
}
+ /**
+ * Only called when shadowRoot is false
+ */
+ protected _updateSlotNodes(replacements: Map<Node, Node[]>): void {
+ this._updateFragmentNodes(
+ (this._instance! as VaporComponentInstance).block,
+ replacements,
+ )
+ }
+
+ /**
+ * Replace slot nodes with their replace content
+ * @internal
+ */
+ private _updateFragmentNodes(
+ block: Block,
+ replacements: Map<Node, Node[]>,
+ ): void {
+ if (Array.isArray(block)) {
+ block.forEach(item => this._updateFragmentNodes(item, replacements))
+ return
+ }
+
+ if (!isFragment(block)) return
+ const { nodes } = block
+ if (Array.isArray(nodes)) {
+ const newNodes: Block[] = []
+ for (const node of nodes) {
+ if (node instanceof HTMLSlotElement) {
+ newNodes.push(...replacements.get(node)!)
+ } else {
+ this._updateFragmentNodes(node, replacements)
+ newNodes.push(node)
+ }
+ }
+ block.nodes = newNodes
+ } else if (nodes instanceof HTMLSlotElement) {
+ block.nodes = replacements.get(nodes)!
+ } else {
+ this._updateFragmentNodes(nodes, replacements)
+ }
+ }
+
private _createComponent() {
this._def.ce = instance => {
this._app!._ceComponent = this._instance = instance