type InnerComponentDef = ConcreteComponent & CustomElementOptions
export abstract class VueElementBase<
+ E = Element,
+ C = Component,
Def extends CustomElementOptions & { props?: any } = InnerComponentDef,
>
extends BaseClass
/**
* @internal
*/
- _root: Element | ShadowRoot
+ _root!: Element | ShadowRoot
/**
* @internal
*/
protected _def: Def
protected _props: Record<string, any>
- protected _createApp: CreateAppFunction<Element>
+ protected _createApp: CreateAppFunction<E, C>
protected _connected = false
protected _resolved = false
protected _numberProps: Record<string, true> | null = null
protected _ob?: MutationObserver | null = null
protected _slots?: Record<string, Node[]>
+ protected abstract _hasPreRendered(): boolean | undefined
+ protected abstract _mountComponent(def: Def): void
+ protected abstract _updateComponent(): void
+ protected abstract _unmountComponent(): void
+
constructor(
/**
* Component def - note this may be an AsyncWrapper, and this._def will
* be overwritten by the inner component when resolved.
*/
def: Def,
- props: Record<string, any> = {},
- createAppFn: CreateAppFunction<Element> = createApp,
+ props: Record<string, any> | undefined = {},
+ createAppFn: CreateAppFunction<E, C>,
) {
super()
this._def = def
this._props = props
this._createApp = createAppFn
this._nonce = def.nonce
- if (this.shadowRoot && createAppFn !== createApp) {
- this._root = this.shadowRoot
- } else {
- if (__DEV__ && this.shadowRoot) {
- warn(
- `Custom element has pre-rendered declarative shadow root but is not ` +
- `defined as hydratable. Use \`defineSSRCustomElement\`.`,
- )
- }
+
+ if (this._hasPreRendered()) {
if (def.shadowRoot !== false) {
this.attachShadow(
extend({}, def.shadowRootOptions, {
}
}
- protected abstract _mountComponent(def: Def): void
- protected abstract _updateComponent(): void
- protected abstract _unmountComponent(): void
-
protected _setParent(
parent: VueElementBase | undefined = this._parent,
): void {
}
}
-export class VueElement extends VueElementBase<InnerComponentDef> {
+export class VueElement extends VueElementBase<
+ Element,
+ Component,
+ InnerComponentDef
+> {
+ constructor(
+ def: InnerComponentDef,
+ props: Record<string, any> | undefined = {},
+ createAppFn: CreateAppFunction<Element, Component> = createApp,
+ ) {
+ super(def, props, createAppFn)
+ }
+
+ protected _hasPreRendered(): boolean | undefined {
+ if (this.shadowRoot && this._createApp !== createApp) {
+ this._root = this.shadowRoot
+ } else {
+ if (__DEV__ && this.shadowRoot) {
+ warn(
+ `Custom element has pre-rendered declarative shadow root but is not ` +
+ `defined as hydratable. Use \`defineSSRCustomElement\`.`,
+ )
+ }
+ return true
+ }
+ }
+
protected _mountComponent(def: InnerComponentDef): void {
if ((__DEV__ || __FEATURE_PROD_DEVTOOLS__) && !def.name) {
// @ts-expect-error
import { extend, isPlainObject } from '@vue/shared'
-import { defineVaporComponent } from '.'
+import { createVaporApp, defineVaporComponent } from '.'
import {
type CreateAppFunction,
type CustomElementOptions,
VueElementBase,
+ warn,
} from '@vue/runtime-dom'
import type { ObjectVaporComponent, VaporComponent } from './component'
// TODO type inference
/*@__NO_SIDE_EFFECTS__*/
-export function defineCustomElement(
+export function defineVaporCustomElement(
options: any,
extraOptions?: Omit<ObjectVaporComponent, 'setup'>,
/**
* @internal
*/
- _createApp?: CreateAppFunction<Element>,
+ _createApp?: CreateAppFunction<ParentNode, VaporComponent>,
): VaporElementConstructor {
let Comp = defineVaporComponent(options, extraOptions)
if (isPlainObject(Comp)) Comp = extend({}, Comp, extraOptions)
return VaporCustomElement
}
+/*@__NO_SIDE_EFFECTS__*/
+export const defineVaporSSRCustomElement = ((
+ options: any,
+ extraOptions?: Omit<ObjectVaporComponent, 'setup'>,
+) => {
+ // @ts-expect-error
+ return defineVaporCustomElement(options, extraOptions, createVaporSSRApp)
+}) as typeof defineVaporCustomElement
+
type VaporInnerComponentDef = VaporComponent & CustomElementOptions
-export class VaporElement extends VueElementBase<VaporInnerComponentDef> {
+export class VaporElement extends VueElementBase<
+ ParentNode,
+ VaporComponent,
+ VaporInnerComponentDef
+> {
+ constructor(
+ def: VaporInnerComponentDef,
+ props: Record<string, any> | undefined = {},
+ createAppFn: CreateAppFunction<ParentNode, VaporComponent> = createVaporApp,
+ ) {
+ super(def, props, createAppFn)
+ }
+
+ protected _hasPreRendered(): boolean | undefined {
+ if (this.shadowRoot && this._createApp !== createVaporApp) {
+ this._root = this.shadowRoot
+ } else {
+ if (__DEV__ && this.shadowRoot) {
+ warn(
+ `Custom element has pre-rendered declarative shadow root but is not ` +
+ `defined as hydratable. Use \`defineVaporSSRCustomElement\`.`,
+ )
+ }
+ return true
+ }
+ }
protected _mountComponent(def: VaporInnerComponentDef): void {
throw new Error('Method not implemented.')
}