@unblessed/react
Version:
React renderer for unblessed with flexbox layout support
932 lines (926 loc) • 29.8 kB
JavaScript
import { Box as Box$1, Text as Text$1, Button as Button$1, Textbox, BigText as BigText$1, List as List$1, colors, setRuntime, Screen } from '@unblessed/core';
import { forwardRef } from 'react';
import { updateLayoutNode, WidgetDescriptor, LayoutManager } from '@unblessed/layout';
import { jsx } from 'react/jsx-runtime';
import createReconciler from 'react-reconciler';
import { DefaultEventPriority } from 'react-reconciler/constants.js';
// src/components/BigText.tsx
function buildBorder(props) {
if (!Number(props.border) && !Number(props.borderTop) && !Number(props.borderBottom) && !Number(props.borderLeft) && !Number(props.borderRight)) {
return null;
}
const border = {
type: "line",
style: props.borderStyle || "single"
};
border.top = props.borderTop !== void 0 ? Number(props.borderTop) > 0 : true;
border.bottom = props.borderBottom !== void 0 ? Number(props.borderBottom) > 0 : true;
border.left = props.borderLeft !== void 0 ? Number(props.borderLeft) > 0 : true;
border.right = props.borderRight !== void 0 ? Number(props.borderRight) > 0 : true;
if (props.borderColor) {
border.fg = colors.convert(props.borderColor);
}
if (props.borderTopColor) {
border.topColor = colors.convert(props.borderTopColor);
}
if (props.borderBottomColor) {
border.bottomColor = colors.convert(props.borderBottomColor);
}
if (props.borderLeftColor) {
border.leftColor = colors.convert(props.borderLeftColor);
}
if (props.borderRightColor) {
border.rightColor = colors.convert(props.borderRightColor);
}
if (props.borderDimColor !== void 0) {
border.dim = props.borderDimColor;
}
if (props.borderTopDim !== void 0) {
border.borderTopDim = props.borderTopDim;
}
if (props.borderBottomDim !== void 0) {
border.borderBottomDim = props.borderBottomDim;
}
if (props.borderLeftDim !== void 0) {
border.borderLeftDim = props.borderLeftDim;
}
if (props.borderRightDim !== void 0) {
border.borderRightDim = props.borderRightDim;
}
return border;
}
function prepareBorderStyle(border) {
if (!border) return {};
return {
border: {
fg: border.fg
}
};
}
function buildTextStyles(props) {
if (!props.color && !props.backgroundColor && !props.bold && !props.italic && !props.underline && !props.strikethrough && !props.reverse && !props.blink && !props.hide && !props.dim) {
return null;
}
const style = {};
if (props.color) {
style.fg = colors.convert(props.color);
}
if (props.backgroundColor) {
style.bg = colors.convert(props.backgroundColor);
}
if (props.bold) style.bold = true;
if (props.italic) style.italic = true;
if (props.underline) style.underline = true;
if (props.strikethrough) style.strikethrough = true;
if (props.reverse) style.inverse = true;
if (props.blink) style.blink = true;
if (props.hide) style.invisible = true;
if (props.dim) style.dim = true;
return style;
}
function buildFocusableOptions(props, defaultTabIndex) {
const options = {};
if (props.tabIndex !== void 0) {
options.tabIndex = props.tabIndex;
} else if (defaultTabIndex !== void 0) {
options.tabIndex = defaultTabIndex;
}
if (options.tabIndex !== void 0) {
options.keyable = true;
options.clickable = true;
}
return options;
}
function mergeStyles(...styles) {
const merged = {};
for (const style of styles) {
if (!style) continue;
for (const [key, value] of Object.entries(style)) {
if (key === "border" && merged.border) {
merged.border = { ...merged.border, ...value };
} else {
merged[key] = value;
}
}
}
return Object.keys(merged).length > 0 ? merged : null;
}
function buildBorderStyleObject(borderStyle) {
const border = {};
const fg = borderStyle.color ?? borderStyle.fg;
const bg = borderStyle.bg ?? borderStyle.background ?? borderStyle.backgroundColor;
if (fg) border.fg = colors.convert(fg);
if (bg) border.bg = colors.convert(bg);
if (borderStyle.topColor)
border.topColor = colors.convert(borderStyle.topColor);
if (borderStyle.bottomColor)
border.bottomColor = colors.convert(borderStyle.bottomColor);
if (borderStyle.leftColor)
border.leftColor = colors.convert(borderStyle.leftColor);
if (borderStyle.rightColor)
border.rightColor = colors.convert(borderStyle.rightColor);
if (borderStyle.dim !== void 0) border.dim = borderStyle.dim;
if (borderStyle.topDim !== void 0) border.topDim = borderStyle.topDim;
if (borderStyle.bottomDim !== void 0)
border.bottomDim = borderStyle.bottomDim;
if (borderStyle.leftDim !== void 0) border.leftDim = borderStyle.leftDim;
if (borderStyle.rightDim !== void 0)
border.rightDim = borderStyle.rightDim;
return border;
}
function buildStyleObject(styleObj) {
if (!styleObj) return {};
const style = {};
const fg = styleObj.fg ?? styleObj.color;
const bg = styleObj.bg ?? styleObj.background ?? styleObj.backgroundColor;
if (fg) style.fg = colors.convert(fg);
if (bg) style.bg = colors.convert(bg);
if (styleObj.bold !== void 0) style.bold = styleObj.bold;
if (styleObj.italic !== void 0) style.italic = styleObj.italic;
if (styleObj.underline !== void 0) style.underline = styleObj.underline;
if (styleObj.strikethrough !== void 0)
style.strikethrough = styleObj.strikethrough;
if (styleObj.reverse !== void 0) style.inverse = styleObj.reverse;
if (styleObj.dim !== void 0) style.dim = styleObj.dim;
if (styleObj.blink !== void 0) style.blink = styleObj.blink;
if (styleObj.hide !== void 0) style.invisible = styleObj.hide;
if (styleObj.border) {
style.border = buildBorderStyleObject(styleObj.border);
}
return style;
}
function extractStyleProps(props) {
const styleObj = {};
if (props.color !== void 0) styleObj.color = props.color;
if (props.fg !== void 0) styleObj.fg = props.fg;
if (props.backgroundColor !== void 0)
styleObj.backgroundColor = props.backgroundColor;
if (props.bg !== void 0) styleObj.bg = props.bg;
if (props.background !== void 0) styleObj.background = props.background;
if (props.bold !== void 0) styleObj.bold = props.bold;
if (props.italic !== void 0) styleObj.italic = props.italic;
if (props.underline !== void 0) styleObj.underline = props.underline;
if (props.strikethrough !== void 0)
styleObj.strikethrough = props.strikethrough;
if (props.reverse !== void 0) styleObj.reverse = props.reverse;
if (props.dim !== void 0) styleObj.dim = props.dim;
if (props.blink !== void 0) styleObj.blink = props.blink;
if (props.hide !== void 0) styleObj.hide = props.hide;
return styleObj;
}
var COMMON_WIDGET_OPTIONS = {
tags: true,
mouse: true,
keys: true,
clickable: true
};
var BoxDescriptor = class extends WidgetDescriptor {
constructor() {
super(...arguments);
this.type = "box";
}
get flexProps() {
const {
flexGrow,
flexShrink,
flexBasis,
flexDirection,
flexWrap,
justifyContent,
alignItems,
alignSelf,
width,
height,
minWidth,
minHeight,
maxWidth,
maxHeight,
padding,
paddingX,
paddingY,
paddingTop,
paddingBottom,
paddingLeft,
paddingRight,
border,
borderTop,
borderBottom,
borderLeft,
borderRight,
margin,
marginX,
marginY,
marginTop,
marginBottom,
marginLeft,
marginRight,
gap,
rowGap,
columnGap,
position,
display
} = this.props;
const flexboxProps = {};
if (flexGrow !== void 0) flexboxProps.flexGrow = flexGrow;
if (flexShrink !== void 0) flexboxProps.flexShrink = flexShrink;
if (flexBasis !== void 0) flexboxProps.flexBasis = flexBasis;
if (flexDirection !== void 0) flexboxProps.flexDirection = flexDirection;
if (flexWrap !== void 0) flexboxProps.flexWrap = flexWrap;
if (justifyContent !== void 0)
flexboxProps.justifyContent = justifyContent;
if (alignItems !== void 0) flexboxProps.alignItems = alignItems;
if (alignSelf !== void 0) flexboxProps.alignSelf = alignSelf;
if (width !== void 0) flexboxProps.width = width;
if (height !== void 0) flexboxProps.height = height;
if (minWidth !== void 0) flexboxProps.minWidth = minWidth;
if (minHeight !== void 0) flexboxProps.minHeight = minHeight;
if (maxWidth !== void 0) flexboxProps.maxWidth = maxWidth;
if (maxHeight !== void 0) flexboxProps.maxHeight = maxHeight;
if (padding !== void 0) flexboxProps.padding = padding;
if (paddingX !== void 0) flexboxProps.paddingX = paddingX;
if (paddingY !== void 0) flexboxProps.paddingY = paddingY;
if (paddingTop !== void 0) flexboxProps.paddingTop = paddingTop;
if (paddingBottom !== void 0) flexboxProps.paddingBottom = paddingBottom;
if (paddingLeft !== void 0) flexboxProps.paddingLeft = paddingLeft;
if (paddingRight !== void 0) flexboxProps.paddingRight = paddingRight;
if (border !== void 0) flexboxProps.border = border ? 1 : 0;
if (borderTop !== void 0) flexboxProps.borderTop = borderTop;
if (borderBottom !== void 0) flexboxProps.borderBottom = borderBottom;
if (borderLeft !== void 0) flexboxProps.borderLeft = borderLeft;
if (borderRight !== void 0) flexboxProps.borderRight = borderRight;
if (margin !== void 0) flexboxProps.margin = margin;
if (marginX !== void 0) flexboxProps.marginX = marginX;
if (marginY !== void 0) flexboxProps.marginY = marginY;
if (marginTop !== void 0) flexboxProps.marginTop = marginTop;
if (marginBottom !== void 0) flexboxProps.marginBottom = marginBottom;
if (marginLeft !== void 0) flexboxProps.marginLeft = marginLeft;
if (marginRight !== void 0) flexboxProps.marginRight = marginRight;
if (gap !== void 0) flexboxProps.gap = gap;
if (rowGap !== void 0) flexboxProps.rowGap = rowGap;
if (columnGap !== void 0) flexboxProps.columnGap = columnGap;
if (position !== void 0) flexboxProps.position = position;
if (display !== void 0) flexboxProps.display = display;
return flexboxProps;
}
get widgetOptions() {
const widgetOptions = {};
const border = buildBorder(this.props);
if (border) {
widgetOptions.border = border;
widgetOptions.style = prepareBorderStyle(border);
} else {
widgetOptions.style = {};
}
if (this.props.hover?.border || this.props.focus?.border) {
widgetOptions.style.border = widgetOptions.style.border || {};
}
Object.assign(widgetOptions, buildFocusableOptions(this.props));
const defaultStyle = extractStyleProps(this.props);
const baseStyle = buildStyleObject(defaultStyle);
if (Object.keys(baseStyle).length > 0) {
widgetOptions.style = mergeStyles(widgetOptions.style, baseStyle);
}
if (this.props.hover) {
widgetOptions.hoverEffects = buildStyleObject(this.props.hover);
}
if (this.props.focus) {
widgetOptions.focusEffects = buildStyleObject(this.props.focus);
}
if (this.props.content !== void 0) {
widgetOptions.content = this.props.content;
}
if (this.props.tags !== void 0) {
widgetOptions.tags = this.props.tags;
}
return widgetOptions;
}
get eventHandlers() {
const handlers = {};
if (this.props.onClick) handlers.click = this.props.onClick;
if (this.props.onMouseDown) handlers.mousedown = this.props.onMouseDown;
if (this.props.onMouseUp) handlers.mouseup = this.props.onMouseUp;
if (this.props.onMouseMove) handlers.mousemove = this.props.onMouseMove;
if (this.props.onMouseOver) handlers.mouseover = this.props.onMouseOver;
if (this.props.onMouseOut) handlers.mouseout = this.props.onMouseOut;
if (this.props.onMouseWheel) handlers.mousewheel = this.props.onMouseWheel;
if (this.props.onWheelDown) handlers.wheeldown = this.props.onWheelDown;
if (this.props.onWheelUp) handlers.wheelup = this.props.onWheelUp;
if (this.props.onKeyPress) handlers.keypress = this.props.onKeyPress;
if (this.props.onFocus) handlers.focus = this.props.onFocus;
if (this.props.onBlur) handlers.blur = this.props.onBlur;
return handlers;
}
createWidget(layout, screen) {
return new Box$1({
screen,
...COMMON_WIDGET_OPTIONS,
top: layout.top,
left: layout.left,
width: layout.width,
height: layout.height,
...this.widgetOptions
});
}
};
var Box = forwardRef(
({ children, ...props }, ref) => {
return /* @__PURE__ */ jsx("box", { ref, ...props, children });
}
);
Box.displayName = "Box";
var BigTextDescriptor = class extends BoxDescriptor {
constructor() {
super(...arguments);
this.type = "bigtext";
}
get widgetOptions() {
const options = super.widgetOptions;
if (this.props.font) options.font = this.props.font;
if (this.props.fontBold) options.fontBold = this.props.fontBold;
if (this.props.char) options.fch = this.props.char;
if (this.props.content !== void 0) options.content = this.props.content;
return options;
}
createWidget(layout, screen) {
return new BigText$1({
screen,
...COMMON_WIDGET_OPTIONS,
top: layout.top,
left: layout.left,
width: layout.width,
height: layout.height,
...this.widgetOptions
});
}
};
var BigText = forwardRef(
({ children, ...props }, ref) => {
const fontHeight = 14;
const fontWidth = 8;
return /* @__PURE__ */ jsx(
"bigtext",
{
ref,
color: "white",
height: fontHeight,
width: (children?.length || 0) * fontWidth,
...props,
children
}
);
}
);
BigText.displayName = "BigText";
var ButtonDescriptor = class extends BoxDescriptor {
constructor() {
super(...arguments);
this.type = "button";
}
get widgetOptions() {
const options = super.widgetOptions;
Object.assign(options, buildFocusableOptions(this.props, 0));
if (this.props.content !== void 0) options.content = this.props.content;
return options;
}
get eventHandlers() {
const handlers = super.eventHandlers;
if (this.props.onPress) handlers.press = this.props.onPress;
return handlers;
}
createWidget(layout, screen) {
return new Button$1({
screen,
...COMMON_WIDGET_OPTIONS,
top: layout.top,
left: layout.left,
width: layout.width,
height: layout.height,
...this.widgetOptions
});
}
};
var Button = forwardRef(
({ children, ...props }, ref) => {
return /* @__PURE__ */ jsx("tbutton", { ref, border: 1, minHeight: 3, ...props, children });
}
);
Button.displayName = "Button";
var InputDescriptor = class extends BoxDescriptor {
constructor() {
super(...arguments);
this.type = "input";
}
get widgetOptions() {
const options = super.widgetOptions;
Object.assign(options, buildFocusableOptions(this.props, 0));
if (this.props.value !== void 0) {
options.value = this.props.value;
} else if (this.props.defaultValue !== void 0) {
options.value = this.props.defaultValue;
}
return options;
}
get eventHandlers() {
const handlers = {};
if (this.props.onSubmit) handlers.submit = this.props.onSubmit;
if (this.props.onCancel) handlers.cancel = this.props.onCancel;
return handlers;
}
createWidget(layout, screen) {
return new Textbox({
screen,
...COMMON_WIDGET_OPTIONS,
inputOnFocus: true,
top: layout.top,
left: layout.left,
width: layout.width,
height: layout.height,
...this.widgetOptions
});
}
updateWidget(widget, layout) {
super.updateWidget(widget, layout);
if (this.props.value !== void 0) {
widget.setValue(this.props.value);
}
}
};
var Input = forwardRef(({ ...props }, ref) => {
return /* @__PURE__ */ jsx("textinput", { ref, border: 1, height: 3, color: "white", ...props });
});
Input.displayName = "Input";
var ListDescriptor = class extends BoxDescriptor {
constructor() {
super(...arguments);
this.type = "list";
}
get widgetOptions() {
const options = super.widgetOptions;
Object.assign(options, buildFocusableOptions(this.props, 0));
options.items = this.props.items || [];
options.label = this.props.label;
options.mouse = true;
options.keys = true;
options.tags = true;
options.inputOnFocus = true;
options.interactive = !this.props.disabled;
options.vi = this.props.vi ?? false;
if (this.props.scrollbar !== false) {
options.scrollbar = {
ch: this.props.scrollbarChar || " "
};
if (this.props.scrollbarFg) options.scrollbar.fg = this.props.scrollbarFg;
if (this.props.scrollbarBg) options.scrollbar.bg = this.props.scrollbarBg;
if (this.props.scrollbarTrack) {
options.scrollbar.track = {
ch: this.props.scrollbarTrackChar
};
if (this.props.scrollbarTrackFg)
options.scrollbar.track.fg = this.props.scrollbarTrackFg;
if (this.props.scrollbarTrackBg)
options.scrollbar.track.bg = this.props.scrollbarTrackBg;
}
}
if (this.props.itemSelected) {
const selectedStyle = buildStyleObject(this.props.itemSelected);
if (selectedStyle.fg !== void 0) options.selectedFg = selectedStyle.fg;
if (selectedStyle.bg !== void 0) options.selectedBg = selectedStyle.bg;
if (selectedStyle.bold !== void 0)
options.selectedBold = selectedStyle.bold;
if (selectedStyle.underline !== void 0)
options.selectedUnderline = selectedStyle.underline;
if (selectedStyle.blink !== void 0)
options.selectedBlink = selectedStyle.blink;
if (selectedStyle.inverse !== void 0)
options.selectedInverse = selectedStyle.reverse;
}
if (this.props.itemStyle) {
const itemStyleObj = buildStyleObject(this.props.itemStyle);
if (itemStyleObj.fg !== void 0) options.itemFg = itemStyleObj.fg;
if (itemStyleObj.bg !== void 0) options.itemBg = itemStyleObj.bg;
if (itemStyleObj.bold !== void 0) options.itemBold = itemStyleObj.bold;
if (itemStyleObj.underline !== void 0)
options.itemUnderline = itemStyleObj.underline;
if (itemStyleObj.blink !== void 0)
options.itemBlink = itemStyleObj.blink;
if (itemStyleObj.inverse !== void 0)
options.itemInverse = itemStyleObj.reverse;
}
if (this.props.itemHover) {
const hoverStyle = buildStyleObject(this.props.itemHover);
if (hoverStyle.bg !== void 0) options.itemHoverBg = hoverStyle.bg;
}
return options;
}
get eventHandlers() {
const handlers = super.eventHandlers;
if (this.props.onSelect) handlers.select = this.props.onSelect;
if (this.props.onCancel) handlers.cancel = this.props.onCancel;
return handlers;
}
createWidget(layout, screen) {
return new List$1({
screen,
...COMMON_WIDGET_OPTIONS,
top: layout.top,
left: layout.left,
width: layout.width,
height: layout.height,
...this.widgetOptions
});
}
updateWidget(widget, layout) {
super.updateWidget(widget, layout);
const newItems = this.widgetOptions.items || [];
widget.setItems(newItems);
}
};
var List = forwardRef(({ ...props }, ref) => {
return /* @__PURE__ */ jsx(
"list",
{
ref,
border: 1,
minHeight: 5,
itemSelected: { bg: "white", color: "black" },
...props
}
);
});
List.displayName = "List";
var SpacerDescriptor = class extends WidgetDescriptor {
constructor() {
super(...arguments);
this.type = "spacer";
}
get flexProps() {
return {
...this.props,
flexGrow: this.props.flexGrow !== void 0 ? this.props.flexGrow : 1
};
}
get widgetOptions() {
return {};
}
get eventHandlers() {
return {};
}
createWidget(layout, screen) {
return new Box$1({
screen,
top: layout.top,
left: layout.left,
width: layout.width,
height: layout.height
});
}
};
var Spacer = (props) => {
return /* @__PURE__ */ jsx("spacer", { ...props });
};
Spacer.displayName = "Spacer";
var TextDescriptor = class extends WidgetDescriptor {
constructor() {
super(...arguments);
this.type = "text";
}
get flexProps() {
return {};
}
get widgetOptions() {
const widgetOptions = {};
const textStyles = buildTextStyles(this.props);
if (textStyles) {
widgetOptions.style = textStyles;
}
if (this.props.content !== void 0) {
widgetOptions.content = this.props.content;
}
widgetOptions.tags = true;
return widgetOptions;
}
get eventHandlers() {
return {};
}
createWidget(layout, screen) {
return new Text$1({
screen,
...COMMON_WIDGET_OPTIONS,
clickable: false,
top: layout.top,
left: layout.left,
width: layout.width,
height: layout.height,
...this.widgetOptions
});
}
};
var Text = forwardRef(
({ children, ...props }, ref) => {
return /* @__PURE__ */ jsx("text", { ref, ...props, children });
}
);
Text.displayName = "Text";
// src/dom.ts
function createElement(type, layoutNode, props = {}) {
return {
type,
layoutNode,
props,
parentNode: null,
childNodes: []
};
}
function createTextNode(text, layoutNode, props = {}) {
return {
type: "#text",
nodeValue: text,
props,
parentNode: null,
layoutNode
};
}
function appendChild(parent, child) {
child.parentNode = parent;
parent.childNodes.push(child);
}
function insertBefore(parent, child, beforeChild) {
const index = parent.childNodes.indexOf(beforeChild);
if (index === -1) {
throw new Error("Reference child not found in parent");
}
child.parentNode = parent;
parent.childNodes.splice(index, 0, child);
}
function removeChild(parent, child) {
const index = parent.childNodes.indexOf(child);
if (index === -1) return;
parent.childNodes.splice(index, 1);
child.parentNode = null;
}
function updateNodeProps(node, props) {
node.props = props;
}
// src/widget-descriptors/factory.ts
var descriptorRegistry = /* @__PURE__ */ new Map([
["box", BoxDescriptor],
["text", TextDescriptor],
["button", ButtonDescriptor],
["tbutton", ButtonDescriptor],
// Alias to avoid conflict with HTML <button>
["input", InputDescriptor],
["textinput", InputDescriptor],
// Alias to avoid conflict with HTML <input>
["bigtext", BigTextDescriptor],
["spacer", SpacerDescriptor],
["list", ListDescriptor]
]);
function createDescriptor(type, props = {}) {
const DescriptorClass = descriptorRegistry.get(type);
if (!DescriptorClass) {
throw new Error(
`Unknown widget type: "${type}". Available types: ${Array.from(descriptorRegistry.keys()).join(", ")}`
);
}
return new DescriptorClass(props);
}
// src/reconciler.ts
var currentLayoutManager = null;
function setLayoutManager(manager) {
currentLayoutManager = manager;
}
function getLayoutManager() {
if (!currentLayoutManager) {
throw new Error(
"LayoutManager not set - this is a bug in @unblessed/react"
);
}
return currentLayoutManager;
}
var reconciler = createReconciler({
supportsMutation: true,
supportsPersistence: false,
supportsHydration: false,
isPrimaryRenderer: true,
getRootHostContext() {
return {};
},
getChildHostContext() {
return {};
},
// Node creation
createInstance(type, props) {
const manager = getLayoutManager();
const descriptor = createDescriptor(type, props);
const layoutNode = manager.createNode(
type,
descriptor.flexProps,
descriptor.widgetOptions
);
layoutNode._descriptor = descriptor;
layoutNode.eventHandlers = descriptor.eventHandlers;
return createElement(type, layoutNode, props);
},
createTextInstance(text) {
const manager = getLayoutManager();
const layoutNode = manager.createNode(
"#text",
{ height: 1, width: text.length },
{ content: text, tags: true }
);
return createTextNode(text, layoutNode, {});
},
// Tree manipulation
appendInitialChild(parent, child) {
appendChild(parent, child);
const manager = getLayoutManager();
manager.appendChild(parent.layoutNode, child.layoutNode);
},
appendChild(parent, child) {
appendChild(parent, child);
const manager = getLayoutManager();
manager.appendChild(parent.layoutNode, child.layoutNode);
},
insertBefore(parent, child, beforeChild) {
insertBefore(parent, child, beforeChild);
const manager = getLayoutManager();
manager.insertBefore(
parent.layoutNode,
child.layoutNode,
beforeChild.layoutNode
);
},
removeChild(parent, child) {
removeChild(parent, child);
const manager = getLayoutManager();
manager.removeChild(parent.layoutNode, child.layoutNode);
},
removeChildFromContainer(container, child) {
if (container.childNodes.includes(child)) {
removeChild(container, child);
const manager = getLayoutManager();
manager.removeChild(container.layoutNode, child.layoutNode);
}
},
appendChildToContainer(container, child) {
appendChild(container, child);
const manager = getLayoutManager();
manager.appendChild(container.layoutNode, child.layoutNode);
},
insertInContainerBefore(container, child, beforeChild) {
insertBefore(container, child, beforeChild);
const manager = getLayoutManager();
manager.insertBefore(
container.layoutNode,
child.layoutNode,
beforeChild.layoutNode
);
},
// Updates
prepareUpdate() {
return true;
},
commitUpdate(instance, _updatePayload, type, _oldProps, newProps) {
updateNodeProps(instance, newProps);
const descriptor = createDescriptor(type, newProps);
updateLayoutNode(instance.layoutNode, descriptor.flexProps);
instance.layoutNode.widgetOptions = descriptor.widgetOptions;
instance.layoutNode.eventHandlers = descriptor.eventHandlers;
instance.layoutNode._descriptor = descriptor;
},
commitTextUpdate(textInstance, _oldText, newText) {
textInstance.nodeValue = newText;
textInstance.layoutNode.widgetOptions = { content: newText };
textInstance.layoutNode.yogaNode.setWidth(newText.length);
textInstance.layoutNode.props.width = newText.length;
},
// Commit hooks
prepareForCommit: () => null,
resetAfterCommit(rootNode) {
if (rootNode.onComputeLayout) {
rootNode.onComputeLayout();
}
},
preparePortalMount: () => null,
clearContainer: () => false,
// Instance management
getPublicInstance: (instance) => instance,
finalizeInitialChildren: () => false,
shouldSetTextContent: () => false,
// Visibility
hideInstance(instance) {
instance.layoutNode.props.display = "none";
instance.layoutNode.yogaNode.setDisplay(1);
},
unhideInstance(instance) {
instance.layoutNode.props.display = "flex";
instance.layoutNode.yogaNode.setDisplay(0);
},
hideTextInstance(instance) {
instance.nodeValue = "";
instance.layoutNode.widgetOptions = { content: "" };
},
unhideTextInstance(instance, text) {
instance.nodeValue = text;
instance.layoutNode.widgetOptions = { content: text };
},
// Reset methods
resetTextContent: () => {
},
// Scheduling
scheduleTimeout: setTimeout,
cancelTimeout: clearTimeout,
noTimeout: -1,
getCurrentEventPriority: () => DefaultEventPriority,
// Update priority
// @ts-expect-error
setCurrentUpdatePriority: () => {
},
// Scope (unused)
getInstanceFromNode: () => null,
prepareScopeUpdate: () => {
},
getInstanceFromScope: () => null,
// Deletion
detachDeletedInstance: () => {
},
// Active instance (unused)
beforeActiveInstanceBlur: () => {
},
afterActiveInstanceBlur: () => {
}
});
var reconciler_default = reconciler;
// src/render.ts
function render(element, options) {
setRuntime(options.runtime);
const screen = options.screen || new Screen({
smartCSR: true,
fullUnicode: true
});
const screenCreatedByRender = !options.screen;
const manager = new LayoutManager({
screen,
debug: options.debug
});
setLayoutManager(manager);
const rootDescriptor = new BoxDescriptor({
width: screen.width || 80,
height: screen.height || 24
});
const rootLayoutNode = manager.createNode(
"root",
rootDescriptor.flexProps,
rootDescriptor.widgetOptions
);
rootLayoutNode._descriptor = rootDescriptor;
const rootDOMNode = createElement("root", rootLayoutNode, {});
rootDOMNode.screen = screen;
rootDOMNode.onComputeLayout = () => {
manager.performLayout(rootLayoutNode);
};
const container = reconciler_default.createContainer(
rootDOMNode,
0,
// LegacyRoot
null,
// hydration callbacks
false,
// isStrictMode
null,
// concurrentUpdatesByDefaultOverride
"",
// identifierPrefix
(error) => console.error(error),
// onRecoverableError
null
// transitionCallbacks
);
let resolveExitPromise = () => {
};
const exitPromise = new Promise((resolve) => {
resolveExitPromise = resolve;
});
reconciler_default.updateContainer(element, container, null, () => {
});
return {
screen,
unmount: () => {
reconciler_default.updateContainer(null, container, null, () => {
});
manager.destroy(rootLayoutNode);
if (screenCreatedByRender) {
screen.destroy();
}
resolveExitPromise();
},
rerender: (newElement) => {
reconciler_default.updateContainer(newElement, container, null, () => {
});
},
waitUntilExit: () => exitPromise
};
}
export { BigText, Box, Button, Input, List, Spacer, Text, render };
//# sourceMappingURL=index.js.map
//# sourceMappingURL=index.js.map