@dark-engine/platform-desktop
Version:
Dark renderer to desktop platforms like Windows, Linux, macOS via Nodegui and Qt
173 lines (172 loc) • 6.16 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
exports.toggle =
exports.runAtTheEndOfCommit =
exports.finishCommit =
exports.commit =
exports.createNativeElement =
void 0;
const core_1 = require('@dark-engine/core');
const native_element_1 = require('../native-element');
const events_1 = require('../events');
const constants_1 = require('../constants');
let moves = [];
let callbacks = [];
function createNativeElement(vNode) {
switch (vNode.type) {
case core_1.NodeType.TAG:
return new native_element_1.TagNativeElement(vNode.name);
case core_1.NodeType.TEXT:
return new native_element_1.TextNativeElement(vNode.value);
case core_1.NodeType.COMMENT:
return new native_element_1.CommentNativeElement(vNode.value);
}
}
exports.createNativeElement = createNativeElement;
function applyRef(ref, element) {
(0, core_1.applyRef)(ref, element.getNativeView());
}
function addAttributes(element, vNode) {
const tagElement = element;
for (const attrName in vNode.attrs) {
const attrValue = vNode.attrs[attrName];
if (attrName === core_1.REF_ATTR) {
applyRef(attrValue, tagElement);
continue;
}
if ((0, events_1.detectIsEvent)(attrName)) {
attrValue && (0, core_1.detectIsObject)(attrValue) && addEvents(tagElement, attrValue);
} else if (!(0, core_1.detectIsUndefined)(attrValue) && !core_1.ATTR_BLACK_LIST[attrName]) {
tagElement.setAttribute(attrName, attrValue);
}
}
}
function updateAttributes(element, prevVNode, nextVNode) {
const attrNames = getAttributeNames(prevVNode, nextVNode);
const tagElement = element;
for (const attrName of attrNames) {
const prevAttrValue = prevVNode.attrs[attrName];
const nextAttrValue = nextVNode.attrs[attrName];
if (attrName === core_1.REF_ATTR) {
applyRef(prevAttrValue, tagElement);
continue;
}
if (!(0, core_1.detectIsUndefined)(nextAttrValue)) {
if ((0, events_1.detectIsEvent)(attrName)) {
nextAttrValue &&
(0, core_1.detectIsObject)(nextAttrValue) &&
prevAttrValue !== nextAttrValue &&
addEvents(tagElement, nextAttrValue);
} else if (!core_1.ATTR_BLACK_LIST[attrName] && prevAttrValue !== nextAttrValue) {
tagElement.setAttribute(attrName, nextAttrValue);
}
} else {
if ((0, events_1.detectIsEvent)(attrName)) {
prevAttrValue && (0, core_1.detectIsObject)(prevAttrValue) && removeEvents(tagElement, prevAttrValue);
} else {
tagElement.removeAttribute(attrName);
}
}
}
}
function addEvents(tagElement, value) {
for (const key in value) {
tagElement.addEventListener(key, value[key]);
}
}
function removeEvents(tagElement, value) {
for (const key in value) {
tagElement.removeEventListener(key);
}
}
function commitCreation(fiber) {
const parent = (0, core_1.getFiberWithElement)(fiber.parent);
const parentElement = parent.el;
const children = parentElement.children;
if (children.length === 0 || fiber.eidx > children.length - 1) {
appendNativeElement(fiber.el, parentElement);
} else {
insertNativeElement(fiber.el, parentElement.children[fiber.eidx], parentElement);
}
(0, core_1.detectIsTagVirtualNode)(fiber.inst) && addAttributes(fiber.el, fiber.inst);
}
function commitUpdate(fiber) {
const element = fiber.el;
const prevInst = fiber.alt.inst;
const nextInst = fiber.inst;
(0, core_1.detectIsPlainVirtualNode)(nextInst)
? prevInst.value !== nextInst.value && (element.value = nextInst.value)
: updateAttributes(element, prevInst, nextInst);
}
function commitDeletion(fiber) {
const parent = (0, core_1.getFiberWithElement)(fiber.parent);
(0, core_1.walk)(fiber, onWalkInCommitDeletion(parent.el));
}
const onWalkInCommitDeletion = parentElement => (fiber, skip) => {
if (fiber.el) {
removeNativeElement(fiber.el, parentElement);
return skip();
}
};
function move(fiber) {
const sourceNodes = (0, core_1.collectElements)(fiber, x => x.el);
const sourceNode = sourceNodes[0];
const parentElement = sourceNode.parentElement;
const elementIdx = fiber.eidx;
const move = () => {
for (let i = 0; i < sourceNodes.length; i++) {
insertNativeElement(sourceNodes[i], parentElement.children[elementIdx + i], parentElement);
removeNativeElement(parentElement.children[elementIdx + i + 1], parentElement);
}
};
for (let i = 0; i < sourceNodes.length; i++) {
const node = sourceNodes[i];
insertNativeElement(new native_element_1.CommentNativeElement(`${elementIdx}:${i}`), node, parentElement);
removeNativeElement(node, parentElement);
}
moves.push(move);
}
function getAttributeNames(prevVNode, nextVNode) {
const attrNames = new Set();
const prevAttrs = Object.keys(prevVNode.attrs);
const nextAttrs = Object.keys(nextVNode.attrs);
const size = Math.max(prevAttrs.length, nextAttrs.length);
for (let i = 0; i < size; i++) {
attrNames.add(prevAttrs[i] || nextAttrs[i]);
}
return attrNames;
}
function commit(fiber) {
switch (fiber.tag) {
case core_1.CREATE_EFFECT_TAG:
fiber.el && commitCreation(fiber);
break;
case core_1.UPDATE_EFFECT_TAG:
fiber.mask & core_1.MOVE_MASK && (move(fiber), (fiber.mask &= ~core_1.MOVE_MASK));
fiber.el && commitUpdate(fiber);
break;
case core_1.DELETE_EFFECT_TAG:
commitDeletion(fiber);
break;
default:
break;
}
}
exports.commit = commit;
function finishCommit() {
callbacks.forEach(x => x());
moves.forEach(x => x());
callbacks = [];
moves = [];
}
exports.finishCommit = finishCommit;
function runAtTheEndOfCommit(cb) {
callbacks.push(cb);
}
exports.runAtTheEndOfCommit = runAtTheEndOfCommit;
const appendNativeElement = (element, parent) => parent.appendChild(element);
const insertNativeElement = (element, sibling, parent) => parent.insertBefore(element, sibling);
const removeNativeElement = (element, parent) => parent.removeChild(element);
const toggle = (element, isVisible) => element.setAttribute(constants_1.HIDDEN_ATTR, isVisible);
exports.toggle = toggle;
//# sourceMappingURL=dom.js.map