78 lines
2.3 KiB
Plaintext
78 lines
2.3 KiB
Plaintext
|
import { isPromise } from "../../util.js";
|
||
|
import { renderChild } from "../any.js";
|
||
|
import { isAPropagatingComponent } from "./factory.js";
|
||
|
import { isHeadAndContent } from "./head-and-content.js";
|
||
|
const astroComponentInstanceSym = Symbol.for("astro.componentInstance");
|
||
|
class AstroComponentInstance {
|
||
|
[astroComponentInstanceSym] = true;
|
||
|
result;
|
||
|
props;
|
||
|
slotValues;
|
||
|
factory;
|
||
|
returnValue;
|
||
|
constructor(result, props, slots, factory) {
|
||
|
this.result = result;
|
||
|
this.props = props;
|
||
|
this.factory = factory;
|
||
|
this.slotValues = {};
|
||
|
for (const name in slots) {
|
||
|
let didRender = false;
|
||
|
let value = slots[name](result);
|
||
|
this.slotValues[name] = () => {
|
||
|
if (!didRender) {
|
||
|
didRender = true;
|
||
|
return value;
|
||
|
}
|
||
|
return slots[name](result);
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
async init(result) {
|
||
|
if (this.returnValue !== void 0)
|
||
|
return this.returnValue;
|
||
|
this.returnValue = this.factory(result, this.props, this.slotValues);
|
||
|
return this.returnValue;
|
||
|
}
|
||
|
async render(destination) {
|
||
|
if (this.returnValue === void 0) {
|
||
|
await this.init(this.result);
|
||
|
}
|
||
|
let value = this.returnValue;
|
||
|
if (isPromise(value)) {
|
||
|
value = await value;
|
||
|
}
|
||
|
if (isHeadAndContent(value)) {
|
||
|
await value.content.render(destination);
|
||
|
} else {
|
||
|
await renderChild(destination, value);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function validateComponentProps(props, displayName) {
|
||
|
if (props != null) {
|
||
|
for (const prop of Object.keys(props)) {
|
||
|
if (prop.startsWith("client:")) {
|
||
|
console.warn(
|
||
|
`You are attempting to render <${displayName} ${prop} />, but ${displayName} is an Astro component. Astro components do not render in the client and should not have a hydration directive. Please use a framework component for client rendering.`
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function createAstroComponentInstance(result, displayName, factory, props, slots = {}) {
|
||
|
validateComponentProps(props, displayName);
|
||
|
const instance = new AstroComponentInstance(result, props, slots, factory);
|
||
|
if (isAPropagatingComponent(result, factory)) {
|
||
|
result._metadata.propagators.add(instance);
|
||
|
}
|
||
|
return instance;
|
||
|
}
|
||
|
function isAstroComponentInstance(obj) {
|
||
|
return typeof obj === "object" && !!obj[astroComponentInstanceSym];
|
||
|
}
|
||
|
export {
|
||
|
AstroComponentInstance,
|
||
|
createAstroComponentInstance,
|
||
|
isAstroComponentInstance
|
||
|
};
|