UNPKG

@meonode/ui

Version:

A structured approach to component composition, direct CSS-first prop styling, built-in theming, smart prop handling (including raw property pass-through), and dynamic children.

184 lines 10.7 kB
import React, { type ReactNode } from 'react'; import type { FunctionRendererProps, NodeElement, NodeElementType, NodeFunction, NodeInstance, NodeProps, DependencyList, FinalNodeProps } from '../types/node.type.js'; /** * NodeUtil provides a collection of static utility methods and properties * used internally by BaseNode for various tasks such as hashing, shallow comparison, * and stable element ID generation. This centralizes common helper functions, * improving modularity and maintainability of the core library. */ export declare class NodeUtil { private constructor(); private static readBooleanFlag; static isServer: boolean; private static get _functionSignatureCache(); private static readonly CRITICAL_PROPS; private static _propFuncCache; /** * Detects React/Next client reference functions used by RSC. * These must not be invoked on the server. */ static isClientReference(value: unknown): boolean; /** * Detects function components that explicitly opt in to receiving MeoNode * `css` prop in server execution paths. */ static acceptsServerCss(value: unknown): boolean; /** * Detects components that provide a theme scope for server-side style resolution. */ static providesServerTheme(value: unknown): boolean; /** * Type guard to check if an object is a NodeInstance. * * A NodeInstance is expected to be a non-null object with: * - an 'element' property, * - a 'render' method, * - a 'toPortal' method, * - and an 'isBaseNode' property. * @param obj The object to check. * @returns True if the object is a NodeInstance, false otherwise. */ static isNodeInstance: (obj: unknown) => obj is NodeInstance; /** * Determines if a given string `k` is a valid CSS style property. * This check is performed only on the client-side by checking if the property exists in `document.body.style`. * On the server-side, it always returns `false`. * @param k The string to check. * @returns True if the string is a valid CSS style property, false otherwise. */ static isStyleProp: (k: string) => boolean; /** * Combines FNV-1a and djb2 hash functions for a more robust signature. * This hybrid approach provides better distribution than either algorithm alone. * @param str The string to hash. * @returns A combined hash string in base-36 format. */ static hashString(str: string): string; /** * Generates a fast structural hash for CSS objects without full serialization. * This is an optimized hashing method that samples the first 10 keys for performance. * @param css The CSS object to hash. * @returns A hash string representing the CSS object structure. */ /** * Generates a fast structural hash for CSS objects without full serialization. * This is an optimized hashing method that samples the first 10 keys for performance. * @param css The CSS object to hash. * @returns A hash string representing the CSS object structure. */ private static hashCSS; /** * Creates a unique, stable signature from the element type and props. * This signature includes the element's type to prevent collisions between different components * and handles primitive values in arrays and objects for better caching. * On server environments, returns undefined as signatures are not needed for server-side rendering. * @param element The element type to include in the signature. * @param props The props object to include in the signature. * @returns A unique signature string or undefined on the server. */ static createPropSignature(element: NodeElementType, props: Record<string, unknown>): string | undefined; /** * Extracts "critical" props from a given set of props. Critical props are those * that are frequently used for styling or event handling, such as `on*` handlers, * `aria-*` attributes, `data-*` attributes, `css`, `className`, and `style`. * This method is used to optimize prop processing by focusing on props that are * most likely to influence rendering or behavior. * @param props The original props object. * @param keys The keys to process from the props object. * @returns An object containing only the critical props with an added count property. */ static extractCriticalProps(props: Record<string, unknown>, keys: string[]): Record<string, unknown>; /** * The main prop processing pipeline. It separates cacheable and non-cacheable props, * generates a signature for caching, and assembles the final props object. * This method applies optimizations like fast-path for simple props and hybrid caching strategy. * @param rawProps The original props to process. * @param stableKey The stable key used for child normalization (optional). * @returns The processed props object ready for rendering. */ static processProps(rawProps?: Partial<NodeProps>, stableKey?: string): FinalNodeProps; /** * Processes and normalizes children of the node. * Converts raw children (React elements, primitives, or other BaseNodes) into a consistent format. * Applies optimizations for single and multiple children scenarios. * @param children The raw children to process. * @param disableEmotion If true, emotion styling will be disabled for these children. * @param parentStableKey The stable key of the parent node, used for generating unique keys for children. * @returns The processed children in normalized format. */ private static _processChildren; /** * Determines if a given `NodeInstance` should be cached. * Caching is enabled only on the client-side and if the node has both a `stableKey` * (indicating it's a stable, identifiable element) and `dependencies` (suggesting its render * output might be stable across re-renders if dependencies don't change). * @param node The `NodeInstance` to check for cacheability. * @returns `true` if the node should be cached, `false` otherwise. */ static shouldCacheElement<E extends NodeInstance>(node: E): node is E & { stableKey: string; dependencies: DependencyList; }; /** * Determines if a node should update based on its dependency array. * Uses a shallow comparison, similar to React's `useMemo` and `useCallback`. * On server environments, always returns true since SSR has no concept of re-renders. * @param prevDeps Previous dependency array to compare. * @param newDeps New dependency array to compare. * @param parentBlocked Flag indicating if the parent is blocked from updating. * @returns True if the node should update, false otherwise. */ static shouldNodeUpdate(prevDeps: DependencyList | undefined, newDeps: DependencyList | undefined, parentBlocked: boolean): boolean; /** * The core normalization function for a single child. It takes any valid `NodeElement` * (primitive, React element, function, `BaseNode` instance) and converts it into a standardized `BaseNode` * instance if it isn't one already. This ensures a consistent structure for the iterative renderer. * Handles various node types including primitives, BaseNode instances, function-as-children, React elements, * component classes, and component instances. * @param node The node element to process and normalize. * @param disableEmotion If true, emotion styling will be disabled for this node. * @param stableKey The stable key for positional information in parent-child relationships. * @returns The normalized node element in BaseNode format. */ static processRawNode(node: NodeElement, disableEmotion?: boolean, stableKey?: string): NodeElement; /** * A helper to reliably identify if a given function is a "function-as-a-child" (render prop) * rather than a standard Function Component. * Distinguishes between render prop functions and component functions by checking for React component signatures. * @param node The node to check. * @returns True if the node is a function-as-a-child, false otherwise. */ static isFunctionChild<E extends NodeElementType>(node: NodeElement): node is NodeFunction<E>; /** * A special internal React component used to render "function-as-a-child" (render prop) patterns. * When a `BaseNode` receives a function as its `children` prop, it wraps that function * inside this `functionRenderer` component. This component then executes the render function * and processes its return value, normalizing it into a renderable ReactNode. * * This allows `BaseNode` to support render props while maintaining its internal processing * and normalization logic for the dynamically generated content. * @param render The function-as-a-child to execute. * @param disableEmotion Inherited flag to disable Emotion styling for children. * @returns The processed and rendered output of the render function, or null if an error occurs. */ static functionRenderer<E extends NodeElementType>({ render, disableEmotion }: FunctionRendererProps<E>): ReactNode | null | undefined; /** * Renders a processed `NodeElement` into a ReactNode. * This helper is primarily used by `functionRenderer` to handle the output of render props, * ensuring that `BaseNode` instances are correctly rendered and other React elements or primitives * are passed through. It also applies `disableEmotion` and `key` props as needed. * * This method is part of the child processing pipeline, converting internal `NodeElement` representations * into actual React elements that can be rendered by React. * @param processedElement The processed node element to render. * @param passedKey Optional key to apply to the rendered element. * @param disableEmotion Flag to disable emotion styling if needed. * @returns The rendered ReactNode. */ static renderProcessedNode({ processedElement, passedKey, disableEmotion, }: { processedElement: NodeElement; passedKey?: string; disableEmotion?: boolean; }): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | React.ReactElement<any, string | React.JSXElementConstructor<any>> | null | undefined; } //# sourceMappingURL=node.util.d.ts.map