@teaui/react
Version:
React Reconciler and renderer for TeaUI
303 lines • 11.1 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.render = render;
exports.run = run;
const react_reconciler_1 = __importDefault(require("react-reconciler"));
const core_1 = require("@teaui/core");
const TextReact_1 = require("./components/TextReact");
const isSame_1 = require("./isSame");
function createInstance(type, props) {
switch (type) {
// views
case 'br':
case 'tui-br':
return new TextReact_1.TextLiteral('\n');
case 'checkbox':
case 'tui-checkbox':
return new core_1.Checkbox(props);
case 'collapsible-text':
case 'tui-collapsible-text':
return new core_1.CollapsibleText(props);
case 'console':
case 'tui-console':
return new core_1.ConsoleLog(props);
case 'digits':
case 'tui-digits':
return new core_1.Digits(props);
case 'h1':
case 'tui-h1':
return (0, core_1.H1)(props.text ?? '');
case 'h2':
case 'tui-h2':
return (0, core_1.H2)(props.text ?? '');
case 'h3':
case 'tui-h3':
return (0, core_1.H3)(props.text ?? '');
case 'h4':
case 'tui-h4':
return (0, core_1.H4)(props.text ?? '');
case 'h5':
case 'tui-h5':
return (0, core_1.H5)(props.text ?? '');
case 'h6':
case 'tui-h6':
return (0, core_1.H6)(props.text ?? '');
case 'input':
case 'tui-input':
return new core_1.Input(props);
case 'separator':
case 'tui-separator':
return new core_1.Separator(props);
case 'slider':
case 'tui-slider':
return new core_1.Slider(props);
case 'space':
case 'tui-space':
return new core_1.Space(props);
case 'toggle-group':
case 'tui-toggle-group':
return new core_1.ToggleGroup(props);
// "simple" containers
case 'box':
case 'tui-box':
return new core_1.Box(props);
case 'button':
case 'tui-button':
return new core_1.Button(props);
case 'collapsible':
case 'tui-collapsible':
return new core_1.Collapsible(props);
case 'stack':
case 'tui-stack':
return new core_1.Stack(props);
case 'scrollable':
case 'tui-scrollable':
return new core_1.Scrollable(props);
case 'style':
case 'tui-style':
return new TextReact_1.TextStyle(props);
case 'tui-text':
return new TextReact_1.TextProvider(props);
// "complex" containers
case 'accordion':
case 'tui-accordion':
return new core_1.Accordion(props);
case 'accordion-section':
case 'tui-accordion-section':
return new core_1.Accordion.Section(props);
case 'drawer':
case 'tui-drawer':
return new core_1.Drawer(props);
case 'tabs':
case 'tui-tabs':
return new core_1.Tabs(props);
case 'tabs-section':
case 'tui-tabs-section':
return new core_1.Tabs.Section(props);
default:
throw new Error(`unknown component "${type}"`);
}
}
function render(screen, window, rootNode) {
function rerender() {
screen.render();
}
function removeFromTextContainer(container, child) {
// find TextContainer with child in it, and remove
for (const node of container.children) {
if (node instanceof TextReact_1.TextContainer && node.children.includes(child)) {
node.removeChild(child);
if (node.children.length === 0) {
container.removeChild(node);
}
return;
}
}
}
function removeChild(container, child) {
if (child.parent === container) {
container.removeChild(child);
}
else if (child instanceof TextReact_1.TextLiteral || child instanceof TextReact_1.TextStyle) {
removeFromTextContainer(container, child);
}
}
function appendChild(parentInstance, child, before) {
if (parentInstance instanceof TextReact_1.TextStyle &&
(child instanceof TextReact_1.TextLiteral || child instanceof TextReact_1.TextStyle)) {
// do not do the TextContainer song and dance
}
else if (child instanceof TextReact_1.TextLiteral || child instanceof TextReact_1.TextStyle) {
// find the last child (checking 'before')
let lastChild = parentInstance.children.at(-1);
if (before) {
const index = parentInstance.children.indexOf(before);
if (~index) {
lastChild = parentInstance.children.at(index - 1);
}
}
let textContainer;
if (lastChild instanceof TextReact_1.TextContainer) {
textContainer = lastChild;
}
else {
textContainer = new TextReact_1.TextContainer();
parentInstance.add(textContainer);
}
textContainer.add(child);
return;
}
let index = before
? parentInstance.children.indexOf(before)
: -1;
if (index === -1) {
index = undefined;
}
parentInstance.add(child, index);
}
const reconciler = (0, react_reconciler_1.default)({
supportsMutation: true,
supportsPersistence: false,
supportsHydration: false,
noTimeout: undefined,
isPrimaryRenderer: true,
getRootHostContext(rootWindow) {
return { screen, window: rootWindow };
},
getChildHostContext(_parentHostContext, type, _rootWindow) {
return { type };
},
clearContainer(rootWindow) {
rootWindow.removeAllChildren();
},
createInstance(type, props, _rootWindow, _hostContext, _internalInstanceHandle) {
if ('children' in props) {
const { children, ...remainder } = props;
props = remainder;
}
if ('child' in props) {
const { child, ...remainder } = props;
props = remainder;
}
return createInstance(type, props);
},
createTextInstance(text) {
return new TextReact_1.TextLiteral(text);
},
appendInitialChild(parentInstance, child) {
appendChild(parentInstance, child, undefined);
},
appendChild(parentInstance, child) {
appendChild(parentInstance, child, undefined);
},
insertBefore(parentInstance, child, beforeChild) {
appendChild(parentInstance, child, beforeChild);
},
appendChildToContainer(rootWindow, child) {
appendChild(rootWindow, child);
},
insertInContainerBefore(rootWindow, child, beforeChild) {
appendChild(rootWindow, child, beforeChild);
},
removeChild(container, child) {
removeChild(container, child);
},
removeChildFromContainer(container, child) {
removeChild(container, child);
},
detachDeletedInstance(node) { },
finalizeInitialChildren(instance) {
return false;
},
prepareForCommit() {
return null;
},
resetAfterCommit() {
rerender();
},
commitMount(_instance, _type, _newProps, _internalInstanceHandle) {
// not needed as long as finalizeInitialChildren returns `false`
},
commitTextUpdate(textInstance, _oldText, newText) {
textInstance.text = newText;
},
resetTextContent(instance) {
instance.text = '';
},
shouldSetTextContent(type, _props) {
return false;
},
prepareUpdate(_instance, _type, oldProps, newProps, _rootContainer, _hostContext) {
for (const prop in oldProps) {
if (!Object.hasOwn(oldProps, prop)) {
continue;
}
if (!(0, isSame_1.isSame)(oldProps[prop], newProps[prop])) {
// difference found - we just return a non-null here to indicate "difference"
return [];
}
}
for (const prop in newProps) {
// if we already checked it, or it isn't an own-prop on newProps, continue
if (Object.hasOwn(oldProps, prop) || !Object.hasOwn(newProps, prop)) {
continue;
}
if (!(0, isSame_1.isSame)(oldProps[prop], newProps[prop])) {
// difference found - we just return a non-null here to indicate "difference"
return [];
}
}
return null;
},
commitUpdate(node, _updatePayload, _type, _oldProps, newProps, _internalInstanceHandle) {
const { children, ...updates } = newProps;
// if (children !== undefined && node instanceof TextLiteral) {
// updates.text = childrenToText(children)
// }
node.update(updates);
},
getPublicInstance(_instance) {
throw new Error('Function not implemented.');
},
preparePortalMount(_containerInfo) {
throw new Error('Function not implemented.');
},
scheduleTimeout(_fn, _delay) {
throw new Error('Function not implemented.');
},
cancelTimeout(_id) {
throw new Error('Function not implemented.');
},
getCurrentEventPriority() {
throw new Error('Function not implemented.');
},
getInstanceFromNode() {
throw new Error('Function not implemented.');
},
beforeActiveInstanceBlur() {
throw new Error('Function not implemented.');
},
afterActiveInstanceBlur() {
throw new Error('Function not implemented.');
},
prepareScopeUpdate() {
throw new Error('Function not implemented.');
},
getInstanceFromScope() {
throw new Error('Function not implemented.');
},
});
const fiber = reconciler.createContainer(window, 0, null, false, null, '', () => { }, null);
reconciler.updateContainer(rootNode, fiber, null /* parentComponent */, null /* callback */);
}
async function run(component) {
const window = new core_1.Window();
const start = await core_1.Screen.start(window);
const [screen, _] = start;
render(screen, window, component);
return [screen, window, component];
}
//# sourceMappingURL=reconciler.js.map