67 lines
1.8 KiB
JavaScript
67 lines
1.8 KiB
JavaScript
import { noChange } from 'lit';
|
|
import { directive, PartType } from 'lit/directive.js';
|
|
import { AsyncDirective } from 'lit/async-directive.js';
|
|
|
|
class FlowComponentDirective extends AsyncDirective {
|
|
constructor(partInfo) {
|
|
super(partInfo);
|
|
if (partInfo.type !== PartType.CHILD) {
|
|
throw new Error(`${this.constructor.directiveName}() can only be used in child bindings`);
|
|
}
|
|
}
|
|
|
|
update(part, [appid, nodeid]) {
|
|
this.updateContent(part, appid, nodeid);
|
|
return noChange;
|
|
}
|
|
|
|
updateContent(part, appid, nodeid) {
|
|
const { parentNode, startNode } = part;
|
|
|
|
const hasNewNodeId = nodeid !== undefined && nodeid !== null;
|
|
const newNode = hasNewNodeId ? this.getNewNode(appid, nodeid) : null;
|
|
const oldNode = this.getOldNode(part);
|
|
|
|
clearTimeout(this.__nodeRetryTimeout);
|
|
|
|
if (hasNewNodeId && !newNode) {
|
|
// If the node is not found, try again later.
|
|
this.__nodeRetryTimeout = setTimeout(() => this.updateContent(part, appid, nodeid));
|
|
} else if (oldNode === newNode) {
|
|
return;
|
|
} else if (oldNode && newNode) {
|
|
parentNode.replaceChild(newNode, oldNode);
|
|
} else if (oldNode) {
|
|
parentNode.removeChild(oldNode);
|
|
} else if (newNode) {
|
|
startNode.after(newNode);
|
|
}
|
|
}
|
|
|
|
getNewNode(appid, nodeid) {
|
|
return window.Vaadin.Flow.clients[appid].getByNodeId(nodeid);
|
|
}
|
|
|
|
getOldNode(part) {
|
|
const { startNode, endNode } = part;
|
|
if (startNode.nextSibling === endNode) {
|
|
return;
|
|
}
|
|
return startNode.nextSibling;
|
|
}
|
|
|
|
disconnected() {
|
|
clearTimeout(this.__nodeRetryTimeout);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Renders the given flow component node.
|
|
*
|
|
* WARNING: This directive is not intended for public use.
|
|
*
|
|
* @param {string} appid
|
|
* @param {number} nodeid
|
|
* @private
|
|
*/
|
|
export const flowComponentDirective = directive(FlowComponentDirective);
|