@dark-engine/core
Version:
The lightweight and powerful UI rendering engine without dependencies and written in TypeScript (Browser, Node.js, Android, iOS, Windows, Linux, macOS)
122 lines (121 loc) • 3.65 kB
JavaScript
import { detectIsComponent } from '../component';
import { detectIsArray, detectIsEmpty } from '../utils';
import { REPLACER, KEY_ATTR } from '../constants';
import { $$scope } from '../scope';
const $$vNode = Symbol('vNode');
const PROP_PROPS = 'props';
const PROP_ATTRS = 'attrs';
const PROP_NAME = 'name';
const PROP_TYPE = 'type';
const PROP_CHILDREN = 'children';
class VirtualNode {
type = null;
constructor(type) {
this.type = type;
}
}
class TagVirtualNode extends VirtualNode {
name;
attrs;
children;
constructor(name, attrs, children) {
super(NodeType.TAG);
this.name = name;
this.attrs = attrs;
this.children = children;
}
}
class TextVirtualNode extends VirtualNode {
value;
constructor(source) {
super(NodeType.TEXT);
this.value = String(source);
}
}
class CommentVirtualNode extends VirtualNode {
value = '';
constructor(text) {
super(NodeType.COMMENT);
this.value = text;
}
}
const View = options => {
const factory = () => {
const { as: name, slot, _void = false, ...attrs } = options;
const children = _void ? [] : detectIsArray(slot) ? slot : !detectIsEmpty(slot) ? [slot] : [];
return new TagVirtualNode(name, attrs, children);
};
factory[$$vNode] = true;
factory[PROP_TYPE] = options.as;
factory[KEY_ATTR] = options.key;
return factory;
};
const Text = source => new TextVirtualNode(source);
Text.from = x => (detectIsTextVirtualNode(x) ? x.value : String(x));
const Comment = text => new CommentVirtualNode(text);
const createReplacer = () => new CommentVirtualNode(REPLACER);
const detectIsVirtualNode = x => x instanceof VirtualNode;
const detectIsTagVirtualNode = x => x instanceof TagVirtualNode;
const detectIsCommentVirtualNode = x => x instanceof CommentVirtualNode;
const detectIsTextVirtualNode = x => x instanceof TextVirtualNode;
const detectIsVirtualNodeFactory = x => x?.[$$vNode];
const detectIsPlainVirtualNode = x => !detectIsTagVirtualNode(x);
const getElementType = inst => inst[PROP_NAME] ?? inst[PROP_TYPE] ?? null;
const getElementKey = inst => {
return inst
? inst[PROP_PROPS]
? inst[PROP_PROPS][KEY_ATTR] ?? null
: inst[PROP_ATTRS]
? inst[PROP_ATTRS][KEY_ATTR] ?? null
: inst[KEY_ATTR] ?? null
: null;
};
const hasChildrenProp = inst => {
return inst?.[PROP_CHILDREN] !== undefined;
};
const detectAreSameInstanceTypes = (prevInst, nextInst) => {
if (process.env.NODE_ENV !== 'production') {
if (process.env.NODE_ENV === 'development' && $$scope().getIsHot()) {
if (detectIsComponent(prevInst) && detectIsComponent(nextInst)) {
return prevInst.displayName === nextInst.displayName;
}
}
}
return getElementType(prevInst) === getElementType(nextInst);
};
const detectAreSameComponentTypesWithSameKeys = (prevInst, nextInst) => {
return (
detectIsComponent(prevInst) &&
detectIsComponent(nextInst) &&
detectAreSameInstanceTypes(prevInst, nextInst) &&
getElementKey(prevInst) === getElementKey(nextInst)
);
};
export var NodeType;
(function (NodeType) {
NodeType['TAG'] = 'TAG';
NodeType['TEXT'] = 'TEXT';
NodeType['COMMENT'] = 'COMMENT';
})(NodeType || (NodeType = {}));
export {
View,
Text,
Comment,
VirtualNode,
TagVirtualNode,
TextVirtualNode,
CommentVirtualNode,
createReplacer,
getElementKey,
getElementType,
hasChildrenProp,
detectIsVirtualNode,
detectIsTagVirtualNode,
detectIsCommentVirtualNode,
detectIsTextVirtualNode,
detectIsPlainVirtualNode,
detectIsVirtualNodeFactory,
detectAreSameInstanceTypes,
detectAreSameComponentTypesWithSameKeys,
};
//# sourceMappingURL=view.js.map