@meonode/ui
Version:
A structured approach to component composition with built-in theming, prop separation, and dynamic children handling.
128 lines • 6.52 kB
TypeScript
import { type ReactNode } from 'react';
import type { FinalNodeProps, NodeElement, NodeInstance, NodeProps, RawNodeProps, Theme } from './node.type.js';
import { type Root as ReactDOMRoot } from 'react-dom/client';
/**
* Represents a node in a React component tree with theme and styling capabilities.
* This class wraps React elements and handles:
* - Props processing and normalization
* - Theme inheritance and resolution
* - Child node processing and management
* - Style processing with theme variables
* @template E The type of React element or component this node represents
*/
export declare class BaseNode<E extends NodeElement = NodeElement> implements NodeInstance<E> {
/** The underlying React element or component type that this node represents */
element: E;
/** Original props passed during construction, preserved for cloning/recreation */
rawProps: RawNodeProps<E>;
/** Processed props after theme resolution, style processing, and child normalization */
props: FinalNodeProps;
readonly isBaseNode = true;
private _portalDOMElement;
private _portalReactRoot;
/**
* Creates a new BaseNode instance that wraps a React element.
* Processes raw props by:
* - Extracting and resolving theme-aware styles
* - Processing DOM-related props
* - Normalizing children with theme inheritance
* @param element The React element/component to wrap
* @param rawProps Initial props including theme, styles, and children
*/
constructor(element: E, rawProps?: RawNodeProps<E>);
/**
* Resolves default styles for a given CSSProperties object.
* This method ensures that certain default styles, such as `minHeight`, `minWidth`,
* and `flexShrink`, are applied based on the provided style properties.
*
* - If the element is a flex container:
* - Sets `flexShrink` to 0 for specific scenarios:
* - Column-based layout without wrapping.
* - Row-based layout without wrapping (a default direction is assumed to be 'row').
* - If the element is not a flex container:
* - Defaults `flexShrink` to 0.
* @param style The CSSProperties object containing style definitions.
* @returns An object with resolved default styles.
*/
private _resolveDefaultStyle;
/**
* Resolves theme variable references in an object's values recursively.
* Handles nested objects and prevents circular references.
* Theme variables are referenced using the format "theme.path.to.value".
* @param obj The object whose values should be resolved against the theme
* @param theme Optional theme object containing variable definitions
* @returns A new object with all theme variables resolved to their values
*/
private _resolveObjWithTheme;
/**
* Renders a processed NodeElement into a ReactNode, applying theme and key if needed.
*
* Handles the following cases:
* 1. If the element is a BaseNode instance, it re-wraps it to apply the key and theme if needed.
* 2. If the element is a React class component type, it wraps it in a BaseNode.
* 3. If the element is a NodeInstance object, it calls its render method.
* 4. If the element is a React.Component instance, it calls its render method.
* 5. If the element is a functional component, it creates a React element with the provided key.
* 6. For all other valid ReactNode types, it returns the element as-is.
* @param processedElement The processed node element to render.
* @param passedTheme The theme to apply, if any.
* @param passedKey The key to assign, if any.
* @returns The rendered ReactNode.
*/
private _renderProcessedNode;
/**
* Renders the result of a function child, supporting theme propagation.
*
* Used for children that are functions (`() => Children`). If the returned value is a `BaseNode`
* without an explicit theme, the parent theme is injected. Otherwise, the result is rendered as-is.
* @template E - The type of ReactNode or NodeInstance.
* @param props Renderer props.
* @param props.render Function to invoke for rendering the child.
* @param props.passedTheme Theme to provide to the child, if applicable.
* @param props.passedKey Key to assign to the rendered node.
* @param props.processRawNode Function to process raw nodes.
* @returns The rendered ReactNode, with theme applied if necessary.
*/
private _functionRenderer;
/**
* Processes a single raw child element, converting it into a ProcessedChild.
* If the child is part of an array and lacks an explicit key, a stable indexed key
* (`elementName_child_index`) is generated for new BaseNode instances.
* @param rawNode The raw child element to process.
* @param parentTheme The theme inherited from the parent node.
* @param childIndex Optional index of the child if it's part of an array.
* @returns The processed child.
*/
_processRawNode(rawNode: NodeElement, parentTheme?: Theme, childIndex?: number): NodeElement;
/**
* Normalizes a child node into a renderable ReactNode.
* Processes different types of child nodes to ensure they can be properly rendered
* while maintaining theme inheritance.
*
* Handles:
* - BaseNode instances (applies theme if needed)
* - React.Component instances (applies theme if needed)
* - Other valid React element types (returned as-is)
* - null/undefined values (returned as-is)
* @param child The child node to normalize into a renderable form
* @returns The normalized ReactNode that can be rendered by React
* @throws Error if child is an invalid element type
*/
private _normalizeChild;
/**
* Converts this BaseNode instance into a renderable React node.
* Recursively processes child nodes and uses `React.createElement` to construct the final React element.
* @returns A ReactNode representing the rendered element.
*/
render(): ReactNode;
private _ensurePortalInfrastructure;
toPortal(): ReactDOMRoot | null;
}
/**
* Factory function to create a BaseNode instance.
* @param element The React element type.
* @param props The props for the node.
* @returns NodeInstance<E> - A new BaseNode instance.
*/
export declare function Node<E extends NodeElement>(element: E, props?: Partial<NodeProps<E>>): NodeInstance<E>;
//# sourceMappingURL=core.node.d.ts.map