@meonode/ui 0.2.10 → 0.2.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.12] - 2025-09-11
9
+
10
+ ### Fixed
11
+ - **core.node**: Removed the child processing cache to fix a critical bug that caused infinite page loads in server-side rendering environments.
12
+ - **helper**: Corrected the element type retrieval logic within the hashing function used for child node processing.
13
+
14
+ ## [0.2.11] - 2025-09-11
15
+
16
+ ### Enhanced
17
+ - **core.node**: Significantly improved JSDoc documentation for the `BaseNode` class, providing better clarity on prop processing, child handling, and rendering logic.
18
+ - **core.node**: Overhauled the child processing and caching mechanism to improve server-side performance and resolve a memory leak. This includes a move from object stringification to a more performant hashing strategy for cache keys and the introduction of a cache management policy.
19
+
20
+ ### Fixed
21
+ - **helper**: Corrected an issue in flexbox style processing where an unnecessary string check was performed.
22
+ - **core.node**: Updated a function placeholder to adhere to the unused parameter naming convention.
23
+
8
24
  ## [0.2.10] - 2025-09-10
9
25
 
10
26
  ### Added
@@ -58,7 +74,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
58
74
  Div<{ field: string }>({ field: 'Hello' })
59
75
 
60
76
  // Override existing React props
61
- Input<{ onChange: (e: { target: { value: string } }) => void }>({
77
+ Input<{ onChange: (e: { target: { value: string } }) => void }>({
62
78
  onChange: ({ target }) => console.log(target.value),
63
79
  })
64
80
  ```
@@ -15,87 +15,186 @@ export declare class BaseNode<E extends NodeElement> implements NodeInstance<E>
15
15
  element: E;
16
16
  /** Original props passed during construction, preserved for cloning/recreation */
17
17
  rawProps: RawNodeProps<E>;
18
- /** Processed props after theme resolution, style processing, and child normalization */
19
- props: FinalNodeProps;
20
18
  /** Flag to identify BaseNode instances */
21
19
  readonly isBaseNode: boolean;
20
+ /** Processed props after theme resolution, style processing, and child normalization */
21
+ private _props?;
22
22
  /** DOM element used for portal rendering */
23
23
  private _portalDOMElement;
24
24
  /** React root instance for portal rendering */
25
25
  private _portalReactRoot;
26
+ /** Hash of the current children and theme to detect changes */
27
+ private _childrenHash?;
28
+ /** Cache for normalized children */
29
+ private _normalizedChildren?;
26
30
  /**
27
- * Creates a new BaseNode instance that wraps a React element.
28
- * Processes raw props by:
29
- * - Extracting and resolving theme-aware styles
30
- * - Processing DOM-related props
31
- * - Normalizing children with theme inheritance
32
- * @param element The React element/component to wrap
33
- * @param rawProps Initial props including theme, styles, and children
31
+ * Constructs a new BaseNode instance.
32
+ *
33
+ * This constructor initializes a node with a given React element or component type
34
+ * and the raw props passed to it. The props are not processed until they are
35
+ * accessed via the `props` getter, allowing for lazy evaluation.
36
+ * @param element The React element or component type this node will represent.
37
+ * @param rawProps The initial, unprocessed props for the element.
34
38
  */
35
39
  constructor(element: E, rawProps?: RawNodeProps<E>);
40
+ /**
41
+ * Lazily processes and retrieves the final, normalized props for the node.
42
+ *
43
+ * The first time this getter is accessed, it triggers `_processProps` to resolve
44
+ * themes, styles, and children. Subsequent accesses return the cached result
45
+ * until the node is cloned or recreated.
46
+ * @returns The fully processed and normalized `FinalNodeProps`.
47
+ */
48
+ get props(): FinalNodeProps;
49
+ /**
50
+ * Performs the core logic of processing raw props into their final, normalized form.
51
+ *
52
+ * This method is called by the `props` getter on its first access. It handles:
53
+ * 1. **Theme Resolution**: Selects the active theme from `theme` or `nodetheme` props.
54
+ * 2. **Prop Resolution**: Resolves theme-aware values (functions) in `rawProps` and `nativeProps.style`.
55
+ * 3. **Style Extraction**: Separates style-related props (`css`, `style`) from other DOM/component props.
56
+ * 4. **Default Style Merging**: Combines default styles with resolved style props.
57
+ * 5. **Child Processing**: Normalizes the `children` prop, propagating the theme.
58
+ * @returns The processed `FinalNodeProps` object.
59
+ * @private
60
+ */
61
+ private _processProps;
62
+ /**
63
+ * Processes raw children, wrapping them in `BaseNode` instances where necessary
64
+ * and propagating the theme.
65
+ *
66
+ * This method recursively processes each child to ensure consistent theme handling
67
+ * and to convert valid elements into `BaseNode` instances. It uses caching to
68
+ * optimize performance, with different strategies for server-side (string-based key)
69
+ * and client-side (WeakMap-based key) environments.
70
+ * @param children The raw child or array of children to process.
71
+ * @param theme The theme to propagate to the children.
72
+ * @returns The processed children, ready to be normalized for rendering.
73
+ * @private
74
+ */
36
75
  private _processChildren;
37
76
  /**
38
- * Renders a processed NodeElement into a ReactNode, applying theme and key if needed.
77
+ * Renders a processed `NodeElement` into a `ReactNode`, applying a theme and key if necessary.
39
78
  *
40
- * Handles the following cases:
41
- * 1. If the element is a BaseNode instance, it re-wraps it to apply the key and theme if needed.
42
- * 2. If the element is a React class component type, it wraps it in a BaseNode.
43
- * 3. If the element is a NodeInstance object, it calls its render method.
44
- * 4. If the element is a React.Component instance, it calls its render method.
45
- * 5. If the element is a functional component, it creates a React element with the provided key.
46
- * 6. For all other valid ReactNode types, it returns the element as-is.
47
- * @param processedElement The processed node element to render.
48
- * @param passedTheme The theme to apply, if any.
49
- * @param passedKey The key to assign, if any.
50
- * @returns The rendered ReactNode.
79
+ * This static method centralizes the logic for converting various types of processed elements
80
+ * into renderable React nodes. It handles:
81
+ * - `BaseNode` instances: Re-wraps them to apply a new key or theme.
82
+ * - React class components: Wraps them in a new `BaseNode`.
83
+ * - `NodeInstance` objects: Invokes their `render()` method.
84
+ * - React component instances: Invokes their `render()` method.
85
+ * - Functional components: Creates a React element from them.
86
+ * - Other valid `ReactNode` types (strings, numbers, etc.): Returns them as-is.
87
+ * @param processedElement The node element to render.
88
+ * @param passedTheme The theme to propagate.
89
+ * @param passedKey The React key to assign.
90
+ * @returns A renderable `ReactNode`.
91
+ * @private
92
+ * @static
51
93
  */
52
94
  static _renderProcessedNode(processedElement: NodeElement, passedTheme: Theme | undefined, passedKey: string | undefined): ReactNode;
53
95
  /**
54
- * Renders the result of a function child, supporting theme propagation.
96
+ * Renders the output of a function-as-a-child, ensuring theme propagation.
55
97
  *
56
- * Used for children that are functions (`() => Children`). If the returned value is a `BaseNode`
57
- * without an explicit theme, the parent theme is injected. Otherwise, the result is rendered as-is.
58
- * @template E - The type of ReactNode or NodeInstance.
59
- * @param props Renderer props.
60
- * @param props.render Function to invoke for rendering the child.
61
- * @param props.passedTheme Theme to provide to the child, if applicable.
62
- * @param props.passedKey Key to assign to the rendered node.
63
- * @param props.processRawNode Function to process raw nodes.
64
- * @returns The rendered ReactNode, with theme applied if necessary.
98
+ * This method is designed to handle "render prop" style children (`() => ReactNode`).
99
+ * It invokes the function, processes its result, and ensures the parent's theme is
100
+ * correctly passed down to any `BaseNode` instances returned by the function.
101
+ * @param props The properties for the function renderer.
102
+ * @param props.render The function to execute to get the child content.
103
+ * @param props.passedTheme The theme to propagate to the rendered child.
104
+ * @param props.passedKey The React key to assign to the rendered node.
105
+ * @param props.processRawNode A reference to the `_processRawNode` method for recursive processing.
106
+ * @returns The rendered `ReactNode`.
107
+ * @private
65
108
  */
66
109
  private _functionRenderer;
67
110
  /**
68
- * Processes a single raw child element, converting it into a ProcessedChild.
69
- * If the child is part of an array and lacks an explicit key, a stable indexed key
70
- * (`elementName_child_index`) is generated for new BaseNode instances.
71
- * @param rawNode The raw child element to process.
72
- * @param parentTheme The theme inherited from the parent node.
73
- * @param nodeIndex Optional index of the child if it's part of an array.
74
- * @returns The processed child.
111
+ * Generates a stable key for a node, especially for elements within an array.
112
+ *
113
+ * If an `existingKey` is provided, it is returned. Otherwise, a key is generated
114
+ * based on the element's type name and its index within a list of siblings.
115
+ * This helps prevent re-rendering issues in React when dealing with dynamic lists.
116
+ * @param options The options for key generation.
117
+ * @param options.nodeIndex The index of the node in an array of children.
118
+ * @param options.element The element for which to generate a key.
119
+ * @param options.existingKey An existing key, if one was already provided.
120
+ * @param options.children The children of the node, used to add complexity to the key.
121
+ * @returns A React key, or `undefined` if no key could be generated.
122
+ * @private
123
+ */
124
+ private _generateKey;
125
+ /**
126
+ * Processes a single raw node, recursively converting it into a `BaseNode` or other renderable type.
127
+ *
128
+ * This is a central method for normalizing children. It handles various types of input:
129
+ * - **`BaseNode` instances**: Re-creates them to ensure the correct theme and key are applied.
130
+ * - **Primitives**: Returns strings, numbers, booleans, null, and undefined as-is.
131
+ * - **Functions (Render Props)**: Wraps them in a `BaseNode` that uses `_functionRenderer` to delay execution.
132
+ * - **Valid React Elements**: Converts them into `BaseNode` instances, extracting props and propagating the theme.
133
+ * - **React Component Types**: Wraps them in a `BaseNode` with the parent theme.
134
+ * - **React Component Instances**: Renders them and processes the output recursively.
135
+ *
136
+ * It also generates a stable key for elements within an array if one is not provided.
137
+ * @param rawNode The raw child node to process.
138
+ * @param parentTheme The theme inherited from the parent.
139
+ * @param nodeIndex The index of the child if it is in an array, used for key generation.
140
+ * @returns A processed `NodeElement` (typically a `BaseNode` instance or a primitive).
141
+ * @private
75
142
  */
76
- _processRawNode(rawNode: NodeElement, parentTheme?: Theme, nodeIndex?: number): NodeElement;
143
+ private _processRawNode;
77
144
  /**
78
- * Normalizes a child node into a renderable ReactNode.
79
- * Processes different types of child nodes to ensure they can be properly rendered
80
- * while maintaining theme inheritance.
145
+ * Normalizes a processed child node into a final, renderable `ReactNode`.
81
146
  *
82
- * Handles:
83
- * - BaseNode instances (applies theme if needed)
84
- * - React.Component instances (applies theme if needed)
85
- * - Other valid React element types (returned as-is)
86
- * - null/undefined values (returned as-is)
87
- * @param child The child node to normalize into a renderable form
88
- * @returns The normalized ReactNode that can be rendered by React
89
- * @throws Error if child is an invalid element type
147
+ * This method is called during the `render` phase. It takes a child that has already
148
+ * been processed by `_processChildren` and prepares it for `React.createElement`.
149
+ *
150
+ * - For `BaseNode` instances, it calls their `render()` method, ensuring the theme is consistent.
151
+ * - It validates that other children are valid React element types.
152
+ * - Primitives and other valid nodes are returned as-is.
153
+ * @param child The processed child node to normalize.
154
+ * @returns A renderable `ReactNode`.
155
+ * @throws {Error} If the child is not a valid React element type.
156
+ * @private
90
157
  */
91
158
  private _normalizeChild;
92
159
  /**
93
- * Converts this BaseNode instance into a renderable React node.
94
- * Recursively processes child nodes and uses `React.createElement` to construct the final React element.
95
- * @returns A ReactNode representing the rendered element.
160
+ * Renders the `BaseNode` into a `ReactElement`.
161
+ *
162
+ * This method is the final step in the rendering pipeline. It constructs a React element
163
+ * by:
164
+ * 1. Validating that the node's `element` type is renderable.
165
+ * 2. Normalizing processed children into `ReactNode`s using `_normalizeChild`.
166
+ * 3. Caching normalized children to avoid re-processing on subsequent renders.
167
+ * 4. Assembling the final props, including `key`, `style`, and other attributes.
168
+ * 5. If the element has a `css` prop, it may be wrapped in a `StyledRenderer` to handle
169
+ * CSS-in-JS styling.
170
+ * 6. Finally, calling `React.createElement` with the element, props, and children.
171
+ * @returns The rendered `ReactElement`.
172
+ * @throws {Error} If the node's `element` is not a valid React element type.
96
173
  */
97
174
  render(): ReactElement;
175
+ /**
176
+ * Ensures the necessary DOM elements for portal rendering are created and attached.
177
+ *
178
+ * On the client-side, this method checks for or creates a `div` element appended
179
+ * to the `document.body` and initializes a React root on it. This setup is
180
+ * required for the `toPortal` method to function. It is idempotent and safe
181
+ * to call multiple times.
182
+ * @returns `true` if the portal infrastructure is ready, `false` if on the server.
183
+ * @private
184
+ */
98
185
  private _ensurePortalInfrastructure;
186
+ /**
187
+ * Renders the node into a React Portal.
188
+ *
189
+ * This method mounts the node's rendered content into a separate DOM tree
190
+ * attached to the `document.body`. It's useful for rendering components like
191
+ * modals, tooltips, or notifications that need to appear above other UI elements.
192
+ *
193
+ * The returned object includes an `unmount` function to clean up the portal.
194
+ * @returns A `ReactDOMRoot` instance for managing the portal, or `null` if
195
+ * called in a server-side environment. The returned instance is enhanced
196
+ * with a custom `unmount` method that also cleans up the associated DOM element.
197
+ */
99
198
  toPortal(): ReactDOMRoot | null;
100
199
  }
101
200
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"core.node.d.ts","sourceRoot":"","sources":["../src/core.node.ts"],"names":[],"mappings":"AACA,OAAc,EAAgD,KAAK,WAAW,EAA4B,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAA;AAC1J,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EAEd,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,SAAS,EACT,OAAO,EACP,YAAY,EACZ,KAAK,EACN,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAAc,KAAK,IAAI,IAAI,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAIxE;;;;;;;;GAQG;AACH,qBAAa,QAAQ,CAAC,CAAC,SAAS,WAAW,CAAE,YAAW,YAAY,CAAC,CAAC,CAAC;IACrE,+EAA+E;IACxE,OAAO,EAAE,CAAC,CAAA;IAEjB,kFAAkF;IAC3E,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,CAAK;IAErC,wFAAwF;IACjF,KAAK,EAAE,cAAc,CAAA;IAE5B,0CAA0C;IAC1C,SAAgB,UAAU,UAAO;IAEjC,4CAA4C;IAC5C,OAAO,CAAC,iBAAiB,CAA8B;IAEvD,+CAA+C;IAC/C,OAAO,CAAC,gBAAgB,CAA4B;IAEpD;;;;;;;;OAQG;IACH,YAAY,OAAO,EAAE,CAAC,EAAE,QAAQ,GAAE,YAAY,CAAC,CAAC,CAAM,EAsCrD;IAED,OAAO,CAAC,gBAAgB;IAYxB;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,oBAAoB,CAAC,gBAAgB,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAsCnI;IAED;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,iBAAiB;IAgCzB;;;;;;;;OAQG;IACI,eAAe,CACpB,OAAO,EAAE,WAAW,EACpB,WAAW,CAAC,EAAE,KAAK,EACnB,SAAS,CAAC,EAAE,MAAM,GACjB,WAAW,CAkGb;IAED;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,eAAe,CAwBtB;IAED;;;;OAIG;IACI,MAAM,IAAI,YAAY,CA4D5B;IAED,OAAO,CAAC,2BAA2B;IAsB5B,QAAQ,IAAI,YAAY,GAAG,IAAI,CAqBrC;CACF;AAED;;;;;;;;GAQG;AACH,wBAAgB,IAAI,CAAC,eAAe,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC,SAAS,WAAW,EACrF,OAAO,EAAE,CAAC,EACV,KAAK,GAAE,WAAW,CAAC,CAAC,EAAE,eAAe,CAAyC,EAC9E,eAAe,GAAE,eAAuC,GACvD,YAAY,CAAC,CAAC,CAAC,CAOjB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CAAC,sBAAsB,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC,SAAS,WAAW,EAClG,OAAO,EAAE,CAAC,EACV,YAAY,CAAC,EAAE,WAAW,CAAC,CAAC,EAAE,sBAAsB,CAAC,GACpD,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,GACxC,CAAC,CAAC,eAAe,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,EAAE,eAAe,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG;IAAE,OAAO,EAAE,CAAC,CAAA;CAAE,GACjJ,CAAC,CAAC,eAAe,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,CAAC,EAAE,WAAW,CAAC,CAAC,EAAE,eAAe,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG;IAAE,OAAO,EAAE,CAAC,CAAA;CAAE,CAMrJ;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CAAC,sBAAsB,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC,SAAS,WAAW,EAC/G,OAAO,EAAE,CAAC,EACV,YAAY,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,sBAAsB,GAAG,UAAU,CAAC,GAAG,sBAAsB,GACpG,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,GACxC,CAAC,CAAC,eAAe,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACjE,QAAQ,EAAE,WAAW,GAAG,WAAW,EAAE,EACrC,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,eAAe,CAAC,EAAE,UAAU,CAAC,KACrD,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG;IAAE,OAAO,EAAE,CAAC,CAAA;CAAE,GACtC,CAAC,CAAC,eAAe,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACjE,QAAQ,CAAC,EAAE,WAAW,GAAG,WAAW,EAAE,EACtC,KAAK,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,eAAe,CAAC,EAAE,UAAU,CAAC,KACtD,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG;IAAE,OAAO,EAAE,CAAC,CAAA;CAAE,CAQzC"}
1
+ {"version":3,"file":"core.node.d.ts","sourceRoot":"","sources":["../src/core.node.ts"],"names":[],"mappings":"AACA,OAAc,EAAgD,KAAK,WAAW,EAA4B,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAA;AAC1J,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EAEd,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,SAAS,EACT,OAAO,EACP,YAAY,EACZ,KAAK,EACN,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAAc,KAAK,IAAI,IAAI,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAKxE;;;;;;;;GAQG;AACH,qBAAa,QAAQ,CAAC,CAAC,SAAS,WAAW,CAAE,YAAW,YAAY,CAAC,CAAC,CAAC;IACrE,+EAA+E;IACxE,OAAO,EAAE,CAAC,CAAA;IACjB,kFAAkF;IAC3E,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,CAAK;IACrC,0CAA0C;IAC1C,SAAgB,UAAU,UAAO;IAEjC,wFAAwF;IACxF,OAAO,CAAC,MAAM,CAAC,CAAgB;IAC/B,4CAA4C;IAC5C,OAAO,CAAC,iBAAiB,CAA8B;IACvD,+CAA+C;IAC/C,OAAO,CAAC,gBAAgB,CAA4B;IACpD,+DAA+D;IAC/D,OAAO,CAAC,aAAa,CAAC,CAAQ;IAC9B,oCAAoC;IACpC,OAAO,CAAC,mBAAmB,CAAC,CAAW;IAEvC;;;;;;;;OAQG;IACH,YAAY,OAAO,EAAE,CAAC,EAAE,QAAQ,GAAE,YAAY,CAAC,CAAC,CAAM,EAGrD;IAED;;;;;;;OAOG;IACH,IAAW,KAAK,IAAI,cAAc,CAKjC;IAED;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,aAAa;IAqCrB;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,gBAAgB;IAOxB;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CAAC,oBAAoB,CAAC,gBAAgB,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CA8CnI;IAED;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,iBAAiB;IAgCzB;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,YAAY,CAwBnB;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,eAAe;IA0FvB;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,eAAe,CAwBtB;IAED;;;;;;;;;;;;;;OAcG;IACI,MAAM,IAAI,YAAY,CA4D5B;IAED;;;;;;;;;OASG;IACH,OAAO,CAAC,2BAA2B;IAsBnC;;;;;;;;;;;OAWG;IACI,QAAQ,IAAI,YAAY,GAAG,IAAI,CAqBrC;CACF;AAED;;;;;;;;GAQG;AACH,wBAAgB,IAAI,CAAC,eAAe,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC,SAAS,WAAW,EACrF,OAAO,EAAE,CAAC,EACV,KAAK,GAAE,WAAW,CAAC,CAAC,EAAE,eAAe,CAAyC,EAC9E,eAAe,GAAE,eAAuC,GACvD,YAAY,CAAC,CAAC,CAAC,CAOjB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CAAC,sBAAsB,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC,SAAS,WAAW,EAClG,OAAO,EAAE,CAAC,EACV,YAAY,CAAC,EAAE,WAAW,CAAC,CAAC,EAAE,sBAAsB,CAAC,GACpD,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,GACxC,CAAC,CAAC,eAAe,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,EAAE,eAAe,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG;IAAE,OAAO,EAAE,CAAC,CAAA;CAAE,GACjJ,CAAC,CAAC,eAAe,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,CAAC,EAAE,WAAW,CAAC,CAAC,EAAE,eAAe,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG;IAAE,OAAO,EAAE,CAAC,CAAA;CAAE,CAMrJ;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CAAC,sBAAsB,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC,SAAS,WAAW,EAC/G,OAAO,EAAE,CAAC,EACV,YAAY,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,sBAAsB,GAAG,UAAU,CAAC,GAAG,sBAAsB,GACpG,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,GACxC,CAAC,CAAC,eAAe,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACjE,QAAQ,EAAE,WAAW,GAAG,WAAW,EAAE,EACrC,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,eAAe,CAAC,EAAE,UAAU,CAAC,KACrD,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG;IAAE,OAAO,EAAE,CAAC,CAAA;CAAE,GACtC,CAAC,CAAC,eAAe,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACjE,QAAQ,CAAC,EAAE,WAAW,GAAG,WAAW,EAAE,EACtC,KAAK,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,eAAe,CAAC,EAAE,UAAU,CAAC,KACtD,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG;IAAE,OAAO,EAAE,CAAC,CAAA;CAAE,CAQzC"}
package/dist/core.node.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var _excluded=["ref","key","children","nodetheme","theme","props"],_excluded2=["style"],_excluded3=["style","css"],_excluded4=["style"],_excluded5=["children","key","nativeProps"];function _typeof(a){"@babel/helpers - typeof";return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a},_typeof(a)}function _objectWithoutProperties(a,b){if(null==a)return{};var c,d,e=_objectWithoutPropertiesLoose(a,b);if(Object.getOwnPropertySymbols){var f=Object.getOwnPropertySymbols(a);for(d=0;d<f.length;d++)c=f[d],-1===b.indexOf(c)&&{}.propertyIsEnumerable.call(a,c)&&(e[c]=a[c])}return e}function _objectWithoutPropertiesLoose(a,b){if(null==a)return{};var c={};for(var d in a)if({}.hasOwnProperty.call(a,d)){if(-1!==b.indexOf(d))continue;c[d]=a[d]}return c}function ownKeys(a,b){var c=Object.keys(a);if(Object.getOwnPropertySymbols){var d=Object.getOwnPropertySymbols(a);b&&(d=d.filter(function(b){return Object.getOwnPropertyDescriptor(a,b).enumerable})),c.push.apply(c,d)}return c}function _objectSpread(a){for(var b,c=1;c<arguments.length;c++)b=null==arguments[c]?{}:arguments[c],c%2?ownKeys(Object(b),!0).forEach(function(c){_defineProperty(a,c,b[c])}):Object.getOwnPropertyDescriptors?Object.defineProperties(a,Object.getOwnPropertyDescriptors(b)):ownKeys(Object(b)).forEach(function(c){Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))});return a}function _defineProperty(a,b,c){return(b=_toPropertyKey(b))in a?Object.defineProperty(a,b,{value:c,enumerable:!0,configurable:!0,writable:!0}):a[b]=c,a}function _toPropertyKey(a){var b=_toPrimitive(a,"string");return"symbol"==_typeof(b)?b:b+""}function _toPrimitive(a,b){if("object"!=_typeof(a)||!a)return a;var c=a[Symbol.toPrimitive];if(void 0!==c){var d=c.call(a,b||"default");if("object"!=_typeof(d))return d;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===b?String:Number)(a)}import React,{Fragment,createElement,isValidElement}from"react";import{isNodeInstance,resolveDefaultStyle,resolveObjWithTheme}from"./helper/node.helper.js";import{isForwardRef,isFragment,isMemo,isReactClassComponent,isValidElementType}from"./helper/react-is.helper.js";import{createRoot}from"react-dom/client";import{getComponentType,getCSSProps,getDOMProps,getElementTypeName,hasNoStyleTag}from"./helper/common.helper.js";import StyledRenderer from"./components/styled-renderer.client.js";/**
1
+ "use strict";var _excluded=["ref","key","children","nodetheme","theme","props"],_excluded2=["style"],_excluded3=["style","css"],_excluded4=["style"],_excluded5=["children","key","nativeProps"];function _typeof(a){"@babel/helpers - typeof";return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a},_typeof(a)}function _objectWithoutProperties(a,b){if(null==a)return{};var c,d,e=_objectWithoutPropertiesLoose(a,b);if(Object.getOwnPropertySymbols){var f=Object.getOwnPropertySymbols(a);for(d=0;d<f.length;d++)c=f[d],-1===b.indexOf(c)&&{}.propertyIsEnumerable.call(a,c)&&(e[c]=a[c])}return e}function _objectWithoutPropertiesLoose(a,b){if(null==a)return{};var c={};for(var d in a)if({}.hasOwnProperty.call(a,d)){if(-1!==b.indexOf(d))continue;c[d]=a[d]}return c}function ownKeys(a,b){var c=Object.keys(a);if(Object.getOwnPropertySymbols){var d=Object.getOwnPropertySymbols(a);b&&(d=d.filter(function(b){return Object.getOwnPropertyDescriptor(a,b).enumerable})),c.push.apply(c,d)}return c}function _objectSpread(a){for(var b,c=1;c<arguments.length;c++)b=null==arguments[c]?{}:arguments[c],c%2?ownKeys(Object(b),!0).forEach(function(c){_defineProperty(a,c,b[c])}):Object.getOwnPropertyDescriptors?Object.defineProperties(a,Object.getOwnPropertyDescriptors(b)):ownKeys(Object(b)).forEach(function(c){Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))});return a}function _defineProperty(a,b,c){return(b=_toPropertyKey(b))in a?Object.defineProperty(a,b,{value:c,enumerable:!0,configurable:!0,writable:!0}):a[b]=c,a}function _toPropertyKey(a){var b=_toPrimitive(a,"string");return"symbol"==_typeof(b)?b:b+""}function _toPrimitive(a,b){if("object"!=_typeof(a)||!a)return a;var c=a[Symbol.toPrimitive];if(void 0!==c){var d=c.call(a,b||"default");if("object"!=_typeof(d))return d;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===b?String:Number)(a)}import React,{Fragment,createElement,isValidElement}from"react";import{createStableHash,isNodeInstance,resolveDefaultStyle}from"./helper/node.helper.js";import{isForwardRef,isFragment,isMemo,isReactClassComponent,isValidElementType}from"./helper/react-is.helper.js";import{createRoot}from"react-dom/client";import{getComponentType,getCSSProps,getDOMProps,getElementTypeName,hasNoStyleTag,shallowEqual}from"./helper/common.helper.js";import StyledRenderer from"./components/styled-renderer.client.js";import{resolveObjWithTheme}from"./helper/theme.helper.js";/**
2
2
  * Represents a node in a React component tree with theme and styling capabilities.
3
3
  * This class wraps React elements and handles:
4
4
  * - Props processing and normalization
@@ -6,114 +6,199 @@
6
6
  * - Child node processing and management
7
7
  * - Style processing with theme variables
8
8
  * @template E The type of React element or component this node represents
9
- */export class BaseNode{/**
10
- * Creates a new BaseNode instance that wraps a React element.
11
- * Processes raw props by:
12
- * - Extracting and resolving theme-aware styles
13
- * - Processing DOM-related props
14
- * - Normalizing children with theme inheritance
15
- * @param element The React element/component to wrap
16
- * @param rawProps Initial props including theme, styles, and children
17
- */constructor(a){var b=this,c=1<arguments.length&&arguments[1]!==void 0?arguments[1]:{};_defineProperty(this,"rawProps",{}),_defineProperty(this,"isBaseNode",!0),_defineProperty(this,"_portalDOMElement",null),_defineProperty(this,"_portalReactRoot",null),_defineProperty(this,"_normalizeChild",function(a){var c,d;if(!a)return a;var e=(null===(c=b.rawProps)||void 0===c?void 0:c.nodetheme)||(null===(d=b.rawProps)||void 0===d?void 0:d.theme)||b.props.nodetheme||b.props.theme;// For BaseNode instances, apply current theme if child has no theme
9
+ */export class BaseNode{/** Hash of the current children and theme to detect changes *//** Cache for normalized children *//**
10
+ * Constructs a new BaseNode instance.
11
+ *
12
+ * This constructor initializes a node with a given React element or component type
13
+ * and the raw props passed to it. The props are not processed until they are
14
+ * accessed via the `props` getter, allowing for lazy evaluation.
15
+ * @param element The React element or component type this node will represent.
16
+ * @param rawProps The initial, unprocessed props for the element.
17
+ */constructor(a){var b=this,c=1<arguments.length&&arguments[1]!==void 0?arguments[1]:{};/** The underlying React element or component type that this node represents *//** Original props passed during construction, preserved for cloning/recreation *//** Flag to identify BaseNode instances *//** DOM element used for portal rendering *//** React root instance for portal rendering *//**
18
+ * Generates a stable key for a node, especially for elements within an array.
19
+ *
20
+ * If an `existingKey` is provided, it is returned. Otherwise, a key is generated
21
+ * based on the element's type name and its index within a list of siblings.
22
+ * This helps prevent re-rendering issues in React when dealing with dynamic lists.
23
+ * @param options The options for key generation.
24
+ * @param options.nodeIndex The index of the node in an array of children.
25
+ * @param options.element The element for which to generate a key.
26
+ * @param options.existingKey An existing key, if one was already provided.
27
+ * @param options.children The children of the node, used to add complexity to the key.
28
+ * @returns A React key, or `undefined` if no key could be generated.
29
+ * @private
30
+ *//**
31
+ * Normalizes a processed child node into a final, renderable `ReactNode`.
32
+ *
33
+ * This method is called during the `render` phase. It takes a child that has already
34
+ * been processed by `_processChildren` and prepares it for `React.createElement`.
35
+ *
36
+ * - For `BaseNode` instances, it calls their `render()` method, ensuring the theme is consistent.
37
+ * - It validates that other children are valid React element types.
38
+ * - Primitives and other valid nodes are returned as-is.
39
+ * @param child The processed child node to normalize.
40
+ * @returns A renderable `ReactNode`.
41
+ * @throws {Error} If the child is not a valid React element type.
42
+ * @private
43
+ */_defineProperty(this,"rawProps",{}),_defineProperty(this,"isBaseNode",!0),_defineProperty(this,"_portalDOMElement",null),_defineProperty(this,"_portalReactRoot",null),_defineProperty(this,"_generateKey",function(a){var b=a.nodeIndex,c=a.element,d=a.existingKey,e=a.children;if(d)return d;var f,g=getElementTypeName(c);return f=Array.isArray(e)&&0<e.length?void 0===b?"".concat(g,"-").concat(e.length):"".concat(g,"-").concat(b,"-").concat(e.length):void 0===b?g:"".concat(g,"-").concat(b),f}),_defineProperty(this,"_normalizeChild",function(a){var c,d;if(!a)return a;var e=(null===(c=b.rawProps)||void 0===c?void 0:c.nodetheme)||(null===(d=b.rawProps)||void 0===d?void 0:d.theme)||b.props.nodetheme||b.props.theme;// For BaseNode instances, apply current theme if child has no theme
18
44
  if(a instanceof BaseNode){var f;return null!==(f=a.rawProps)&&void 0!==f&&f.nodetheme||void 0===e?a.render():new BaseNode(a.element,_objectSpread(_objectSpread({},a.rawProps),{},{nodetheme:e})).render()}// Validate element type before returning
19
45
  if(!isValidElementType(a)){var g=getComponentType(a);throw new Error("Invalid element type: ".concat(g," provided!"))}// Return valid React elements as-is
20
- return a}),this.element=a,this.rawProps=c;// Destructure raw props into relevant parts
21
- var d=c.ref,e=c.key,f=c.children,g=c.nodetheme,h=c.theme,i=c.props,j=void 0===i?{}:i,k=_objectWithoutProperties(c,_excluded),l=h||g,m=j,n=m.style,o=_objectWithoutProperties(m,_excluded2),p=resolveObjWithTheme(k,l),q=resolveObjWithTheme(n,l),r=p.style,s=p.css,t=_objectWithoutProperties(p,_excluded3),u=getCSSProps(t),v=getDOMProps(t),w=resolveDefaultStyle(_objectSpread(_objectSpread({},u),r)),x=this._processChildren(f,l);// Process children while maintaining theme inheritance
46
+ return a}),this.element=a,this.rawProps=c}/**
47
+ * Lazily processes and retrieves the final, normalized props for the node.
48
+ *
49
+ * The first time this getter is accessed, it triggers `_processProps` to resolve
50
+ * themes, styles, and children. Subsequent accesses return the cached result
51
+ * until the node is cloned or recreated.
52
+ * @returns The fully processed and normalized `FinalNodeProps`.
53
+ */get props(){return this._props||(this._props=this._processProps()),this._props}/**
54
+ * Performs the core logic of processing raw props into their final, normalized form.
55
+ *
56
+ * This method is called by the `props` getter on its first access. It handles:
57
+ * 1. **Theme Resolution**: Selects the active theme from `theme` or `nodetheme` props.
58
+ * 2. **Prop Resolution**: Resolves theme-aware values (functions) in `rawProps` and `nativeProps.style`.
59
+ * 3. **Style Extraction**: Separates style-related props (`css`, `style`) from other DOM/component props.
60
+ * 4. **Default Style Merging**: Combines default styles with resolved style props.
61
+ * 5. **Child Processing**: Normalizes the `children` prop, propagating the theme.
62
+ * @returns The processed `FinalNodeProps` object.
63
+ * @private
64
+ */_processProps(){// Destructure raw props into relevant parts
65
+ var a=this.rawProps,b=a.ref,c=a.key,d=a.children,e=a.nodetheme,f=a.theme,g=a.props,h=void 0===g?{}:g,i=_objectWithoutProperties(a,_excluded),j=f||e,k=h,l=k.style,m=_objectWithoutProperties(k,_excluded2),n=resolveObjWithTheme(i,j),o=resolveObjWithTheme(l,j),p=n.style,q=n.css,r=_objectWithoutProperties(n,_excluded3),s=getCSSProps(r),t=getDOMProps(r),u=resolveDefaultStyle(_objectSpread(_objectSpread({},s),p)),v=this._processChildren(d,j);// Process children while maintaining theme inheritance
22
66
  // Combine processed props into final normalized form
23
- this.props=_objectSpread(_objectSpread({ref:d,key:e,nodetheme:l,theme:h,css:_objectSpread(_objectSpread({},w),s),style:q},v),{},{nativeProps:o,children:x})}_processChildren(a,b){var c=this;return a?Array.isArray(a)?a.map(function(a,d){return c._processRawNode(a,b,d)}):this._processRawNode(a,b):void 0}/**
24
- * Renders a processed NodeElement into a ReactNode, applying theme and key if needed.
67
+ return _objectSpread(_objectSpread({ref:b,key:c,nodetheme:j,theme:f,css:_objectSpread(_objectSpread({},u),q),style:o},t),{},{nativeProps:m,children:v})}/**
68
+ * Processes raw children, wrapping them in `BaseNode` instances where necessary
69
+ * and propagating the theme.
25
70
  *
26
- * Handles the following cases:
27
- * 1. If the element is a BaseNode instance, it re-wraps it to apply the key and theme if needed.
28
- * 2. If the element is a React class component type, it wraps it in a BaseNode.
29
- * 3. If the element is a NodeInstance object, it calls its render method.
30
- * 4. If the element is a React.Component instance, it calls its render method.
31
- * 5. If the element is a functional component, it creates a React element with the provided key.
32
- * 6. For all other valid ReactNode types, it returns the element as-is.
33
- * @param processedElement The processed node element to render.
34
- * @param passedTheme The theme to apply, if any.
35
- * @param passedKey The key to assign, if any.
36
- * @returns The rendered ReactNode.
71
+ * This method recursively processes each child to ensure consistent theme handling
72
+ * and to convert valid elements into `BaseNode` instances. It uses caching to
73
+ * optimize performance, with different strategies for server-side (string-based key)
74
+ * and client-side (WeakMap-based key) environments.
75
+ * @param children The raw child or array of children to process.
76
+ * @param theme The theme to propagate to the children.
77
+ * @returns The processed children, ready to be normalized for rendering.
78
+ * @private
79
+ */_processChildren(a,b){var c=this;return a?Array.isArray(a)?a.map(function(a,d){return c._processRawNode(a,b,d)}):this._processRawNode(a,b):void 0;// No caching on the client, as it was ineffective and complex.
80
+ }/**
81
+ * Renders a processed `NodeElement` into a `ReactNode`, applying a theme and key if necessary.
82
+ *
83
+ * This static method centralizes the logic for converting various types of processed elements
84
+ * into renderable React nodes. It handles:
85
+ * - `BaseNode` instances: Re-wraps them to apply a new key or theme.
86
+ * - React class components: Wraps them in a new `BaseNode`.
87
+ * - `NodeInstance` objects: Invokes their `render()` method.
88
+ * - React component instances: Invokes their `render()` method.
89
+ * - Functional components: Creates a React element from them.
90
+ * - Other valid `ReactNode` types (strings, numbers, etc.): Returns them as-is.
91
+ * @param processedElement The node element to render.
92
+ * @param passedTheme The theme to propagate.
93
+ * @param passedKey The React key to assign.
94
+ * @returns A renderable `ReactNode`.
95
+ * @private
96
+ * @static
37
97
  */static _renderProcessedNode(a,b,c){var d={};// 1. BaseNode instance: re-wrap to apply key/theme if needed
38
- if(void 0!==c&&(d.key=c),a instanceof BaseNode){var e,f,g=(null===(e=a.rawProps)||void 0===e?void 0:e.theme)||(null===(f=a.rawProps)||void 0===f?void 0:f.nodetheme)||b;return new BaseNode(a.element,_objectSpread(_objectSpread(_objectSpread({},a.rawProps),d),{},{nodetheme:g})).render()}// 2. React class component type: wrap in BaseNode
98
+ if(void 0!==c&&(d.key=c),a instanceof BaseNode){var e,f,g,h,i,j=(null===(e=a.rawProps)||void 0===e?void 0:e.theme)||(null===(f=a.rawProps)||void 0===f?void 0:f.nodetheme)||b;// Avoid creating new BaseNode if props are identical
99
+ return shallowEqual(d,{key:null===(g=a.rawProps)||void 0===g?void 0:g.key})&&j===((null===(h=a.rawProps)||void 0===h?void 0:h.nodetheme)||(null===(i=a.rawProps)||void 0===i?void 0:i.theme))?a.render():new BaseNode(a.element,_objectSpread(_objectSpread(_objectSpread({},a.rawProps),d),{},{nodetheme:j})).render()}// 2. React class component type: wrap in BaseNode
39
100
  return isReactClassComponent(a)?new BaseNode(a,d).render():isNodeInstance(a)?a.render():a instanceof React.Component?a.render():"function"==typeof a?createElement(a,{key:c}):a;// 3. NodeInstance object: call its render
40
101
  // 4. React.Component instance: call its render
41
102
  // 5. Functional component: create element with key
42
103
  // 6. Other valid ReactNode types
43
104
  }/**
44
- * Renders the result of a function child, supporting theme propagation.
105
+ * Renders the output of a function-as-a-child, ensuring theme propagation.
45
106
  *
46
- * Used for children that are functions (`() => Children`). If the returned value is a `BaseNode`
47
- * without an explicit theme, the parent theme is injected. Otherwise, the result is rendered as-is.
48
- * @template E - The type of ReactNode or NodeInstance.
49
- * @param props Renderer props.
50
- * @param props.render Function to invoke for rendering the child.
51
- * @param props.passedTheme Theme to provide to the child, if applicable.
52
- * @param props.passedKey Key to assign to the rendered node.
53
- * @param props.processRawNode Function to process raw nodes.
54
- * @returns The rendered ReactNode, with theme applied if necessary.
107
+ * This method is designed to handle "render prop" style children (`() => ReactNode`).
108
+ * It invokes the function, processes its result, and ensures the parent's theme is
109
+ * correctly passed down to any `BaseNode` instances returned by the function.
110
+ * @param props The properties for the function renderer.
111
+ * @param props.render The function to execute to get the child content.
112
+ * @param props.passedTheme The theme to propagate to the rendered child.
113
+ * @param props.passedKey The React key to assign to the rendered node.
114
+ * @param props.processRawNode A reference to the `_processRawNode` method for recursive processing.
115
+ * @returns The rendered `ReactNode`.
116
+ * @private
55
117
  */_functionRenderer(a){var b=a.render,c=a.passedTheme,d=a.passedKey,e=a.processRawNode,f=b();// Invoke the render function to get the child node.
56
118
  // Handle React.Component instance
57
119
  if(f instanceof React.Component){var g=f.render(),h=e(g,c);return BaseNode._renderProcessedNode(h,c,d)}// Handle BaseNode instance
58
120
  if(f instanceof BaseNode||isNodeInstance(f)){var i,j=f;return void 0===(null===(i=j.rawProps)||void 0===i?void 0:i.nodetheme)&&void 0!==c?new BaseNode(j.element,_objectSpread(_objectSpread({key:d},j.rawProps),{},{nodetheme:c})).render():j.render()}// Process other result types
59
121
  var k=e(f,c);return k?BaseNode._renderProcessedNode(k,c,d):f}/**
60
- * Processes a single raw child element, converting it into a ProcessedChild.
61
- * If the child is part of an array and lacks an explicit key, a stable indexed key
62
- * (`elementName_child_index`) is generated for new BaseNode instances.
63
- * @param rawNode The raw child element to process.
64
- * @param parentTheme The theme inherited from the parent node.
65
- * @param nodeIndex Optional index of the child if it's part of an array.
66
- * @returns The processed child.
122
+ * Processes a single raw node, recursively converting it into a `BaseNode` or other renderable type.
123
+ *
124
+ * This is a central method for normalizing children. It handles various types of input:
125
+ * - **`BaseNode` instances**: Re-creates them to ensure the correct theme and key are applied.
126
+ * - **Primitives**: Returns strings, numbers, booleans, null, and undefined as-is.
127
+ * - **Functions (Render Props)**: Wraps them in a `BaseNode` that uses `_functionRenderer` to delay execution.
128
+ * - **Valid React Elements**: Converts them into `BaseNode` instances, extracting props and propagating the theme.
129
+ * - **React Component Types**: Wraps them in a `BaseNode` with the parent theme.
130
+ * - **React Component Instances**: Renders them and processes the output recursively.
131
+ *
132
+ * It also generates a stable key for elements within an array if one is not provided.
133
+ * @param rawNode The raw child node to process.
134
+ * @param parentTheme The theme inherited from the parent.
135
+ * @param nodeIndex The index of the child if it is in an array, used for key generation.
136
+ * @returns A processed `NodeElement` (typically a `BaseNode` instance or a primitive).
137
+ * @private
67
138
  */_processRawNode(a,b,c// Index for generating stable keys for array children
68
- ){var d=getComponentType(a),e=function generateKey(a){var b=a.element,d=a.existingKey,e=a.children;if(d)return d;var f=getElementTypeName(b);return Array.isArray(e)&&0<e.length?void 0===c?"".concat(f,"-").concat(e.length):"".concat(f,"-").concat(c,"-").concat(e.length):void 0===c?f:"".concat(f,"-").concat(c)};// Determine the type of the raw node
69
- // Helper to generate an indexed key if no explicit key is present and an index is available.
139
+ ){var d=getComponentType(a);// Determine the type of the raw node
70
140
  // Case 1: Child is already a BaseNode instance
71
- if(a instanceof BaseNode){var f=a,g=f.rawProps||{},h=g.theme||g.nodetheme||b,i=e({element:f.element,existingKey:g.key,children:g.children});// Get initial raw props of the child
141
+ if(a instanceof BaseNode){var e=a,f=e.rawProps||{},g=f.theme||f.nodetheme||b;// Get initial raw props of the child
72
142
  // Prefer child's own theme
73
- // Generate key if needed
74
- return new BaseNode(f.element,_objectSpread(_objectSpread({},g),{},{nodetheme:h,// Use the determined theme for the new node
75
- key:i}));// Create a new BaseNode with merged props and theme
143
+ // Check if we can reuse the existing node
144
+ if(f.nodetheme===g&&f.key!==void 0)return e;var h=this._generateKey({nodeIndex:c,element:e.element,existingKey:f.key,children:f.children});// Generate key if needed
145
+ return new BaseNode(e.element,_objectSpread(_objectSpread({},f),{},{nodetheme:g,// Use the determined theme for the new node
146
+ key:h}));// Create a new BaseNode with merged props and theme
76
147
  }// Case 2: Child is a primitive (string, number, boolean, null, undefined)
77
148
  if("string"===d||"number"===d||"boolean"===d||null===a||void 0===a)return a;// Case 3: Child is a function that needs to be called during render (FunctionRenderer).
78
149
  if("function"===d&&!isReactClassComponent(a)&&!isMemo(a)&&!isForwardRef(a)){// The key is for the BaseNode that wraps the _functionRenderer component.
79
150
  // Functions themselves don't have a .key prop that we can access here.
80
- var j=e({element:this._functionRenderer});// Generate key for function renderer
81
- return new BaseNode(this._functionRenderer,{processRawNode:this._processRawNode.bind(this),render:a,passedTheme:b,key:j})}// Case 4: Child is a React Element (JSX element like <div> or <MyComponent>)
82
- if(isValidElement(a)){var k=a.props,l=k.style,m=_objectWithoutProperties(k,_excluded4),n=_objectSpread(_objectSpread({},m),l||{}),o=n.theme||n.nodetheme||b,p=e({element:a.type,existingKey:a.key,children:n.children});// Combine top-level props from the element with its flattened style object properties
83
- return new BaseNode(a.type,_objectSpread(_objectSpread({},n),{},{// Pass the combined props
84
- nodetheme:o,key:p}))}// Case 5: Child is an ElementType (string tag, class component, Memo/ForwardRef)
85
- if(isReactClassComponent(a)||"object"===d&&(isMemo(a)||isForwardRef(a))){var q,r=e({element:a,children:"object"===_typeof(a)&&"props"in a?null===(q=a.props)||void 0===q?void 0:q.children:void 0});// ElementTypes don't have an intrinsic key from the rawNode itself.
151
+ var i=this._generateKey({nodeIndex:c,element:this._functionRenderer});// Generate key for function renderer
152
+ return new BaseNode(this._functionRenderer,{processRawNode:this._processRawNode.bind(this),render:a,passedTheme:b,key:i})}// Case 4: Child is a React Element (JSX element like <div> or <MyComponent>)
153
+ if(isValidElement(a)){var j=a.props,k=j.style,l=_objectWithoutProperties(j,_excluded4),m=_objectSpread(_objectSpread({},l),k||{}),n=m.theme||m.nodetheme||b,o=this._generateKey({nodeIndex:c,element:a.type,existingKey:a.key,children:m.children});// Combine top-level props from the element with its flattened style object properties
154
+ return new BaseNode(a.type,_objectSpread(_objectSpread({},m),{},{// Pass the combined props
155
+ nodetheme:n,key:o}))}// Case 5: Child is an ElementType (string tag, class component, Memo/ForwardRef)
156
+ if(isReactClassComponent(a)||"object"===d&&(isMemo(a)||isForwardRef(a))){var p,q=this._generateKey({nodeIndex:c,element:a,children:"object"===_typeof(a)&&"props"in a?null===(p=a.props)||void 0===p?void 0:p.children:void 0});// ElementTypes don't have an intrinsic key from the rawNode itself.
86
157
  return new BaseNode(a,{nodetheme:b,// Apply parent theme
87
- key:r})}// Case 6: Handle instances of React.Component
88
- if(a instanceof React.Component){var s=a.render();// Recursively process the rendered element with a parent theme and index if available
89
- return this._processRawNode(s,b,c)}// Case 7: Fallback for other ReactNode types (e.g., Fragments, Portals if not caught by isValidElement)
158
+ key:q})}// Case 6: Handle instances of React.Component
159
+ if(a instanceof React.Component){var r=a.render();// Recursively process the rendered element with a parent theme and index if available
160
+ return this._processRawNode(r,b,c)}// Case 7: Fallback for other ReactNode types (e.g., Fragments, Portals if not caught by isValidElement)
90
161
  // These are returned as-is. If they are elements within an array, React expects them to have keys.
91
162
  // This logic primarily adds keys to BaseNode instances we create, other ReactNodes are returned as-is.
92
163
  return a}/**
93
- * Normalizes a child node into a renderable ReactNode.
94
- * Processes different types of child nodes to ensure they can be properly rendered
95
- * while maintaining theme inheritance.
164
+ * Renders the `BaseNode` into a `ReactElement`.
96
165
  *
97
- * Handles:
98
- * - BaseNode instances (applies theme if needed)
99
- * - React.Component instances (applies theme if needed)
100
- * - Other valid React element types (returned as-is)
101
- * - null/undefined values (returned as-is)
102
- * @param child The child node to normalize into a renderable form
103
- * @returns The normalized ReactNode that can be rendered by React
104
- * @throws Error if child is an invalid element type
105
- *//**
106
- * Converts this BaseNode instance into a renderable React node.
107
- * Recursively processes child nodes and uses `React.createElement` to construct the final React element.
108
- * @returns A ReactNode representing the rendered element.
166
+ * This method is the final step in the rendering pipeline. It constructs a React element
167
+ * by:
168
+ * 1. Validating that the node's `element` type is renderable.
169
+ * 2. Normalizing processed children into `ReactNode`s using `_normalizeChild`.
170
+ * 3. Caching normalized children to avoid re-processing on subsequent renders.
171
+ * 4. Assembling the final props, including `key`, `style`, and other attributes.
172
+ * 5. If the element has a `css` prop, it may be wrapped in a `StyledRenderer` to handle
173
+ * CSS-in-JS styling.
174
+ * 6. Finally, calling `React.createElement` with the element, props, and children.
175
+ * @returns The rendered `ReactElement`.
176
+ * @throws {Error} If the node's `element` is not a valid React element type.
109
177
  */render(){var a=this;if(!isValidElementType(this.element)){var b=getComponentType(this.element);throw new Error("Invalid element type: ".concat(b," provided!"))}// Extract children and key
110
- var c=this.props,d=c.children,e=c.key,f=c.nativeProps,g=_objectWithoutProperties(c,_excluded5),h=void 0;if(void 0!==d&&null!==d)if(!Array.isArray(d))h=this._normalizeChild(d);else if(0<d.length){// Normalize each child in the array
111
- var i=d.map(function(b){return a._normalizeChild(b)});// Check if all children are null/undefined (e.g., conditional rendering resulted in nothing)
112
- h=i.every(function(a){return null===a||void 0===a})?void 0:i}else// Empty array of children
113
- h=void 0;// Prepare props for React.createElement
178
+ var c=this.props,d=c.children,e=c.key,f=c.nativeProps,g=_objectWithoutProperties(c,_excluded5),h=void 0;if(void 0!==d&&null!==d){if(!this._normalizedChildren||this._childrenHash!==createStableHash(d,this.props.nodetheme||this.props.theme))if(!Array.isArray(d))this._normalizedChildren=this._normalizeChild(d);else if(0<d.length){var i=d.map(function(b){return a._normalizeChild(b)});this._normalizedChildren=i.every(function(a){return null===a||void 0===a})?void 0:i}else this._normalizedChildren=void 0;h=this._normalizedChildren}// Prepare props for React.createElement
114
179
  var j;// If the element has a `css` prop and has style tag, render using the `StyledRenderer` component
115
180
  // This enables emotion-based style handling for the element
116
- return j=this.element===Fragment||isFragment(this.element)?{key:e}:_objectSpread(_objectSpread(_objectSpread({},g),{},{key:e},f),{},{suppressHydrationWarning:!0}),this.element&&!hasNoStyleTag(this.element)&&j.css?createElement(StyledRenderer,_objectSpread({element:this.element},j),h):createElement(this.element,j,h)}_ensurePortalInfrastructure(){if("undefined"==typeof window)return!1;if(this._portalDOMElement&&this._portalReactRoot)return!0;if(this._portalDOMElement&&!this._portalDOMElement.isConnected&&(this._portalDOMElement=null,this._portalDOMElement=null),this._portalDOMElement||(this._portalDOMElement=document.createElement("div"),document.body.appendChild(this._portalDOMElement)),!this._portalReactRoot){if(!this._portalDOMElement)return!1;this._portalReactRoot=createRoot(this._portalDOMElement)}return!0}toPortal(){var a=this;if(!this._ensurePortalInfrastructure()||!this._portalReactRoot)return null;var b=this.render();return this._portalReactRoot.render(b),_objectSpread(_objectSpread({},this._portalReactRoot),{},{unmount:function unmount(){a._portalReactRoot&&(a._portalReactRoot.unmount(),a._portalReactRoot=null),a._portalDOMElement&&(a._portalDOMElement.parentNode&&a._portalDOMElement.parentNode.removeChild(a._portalDOMElement),a._portalDOMElement=null)}})}}/**
181
+ return j=this.element===Fragment||isFragment(this.element)?{key:e}:_objectSpread(_objectSpread(_objectSpread({},g),{},{key:e},f),{},{suppressHydrationWarning:!0}),this.element&&!hasNoStyleTag(this.element)&&j.css?createElement(StyledRenderer,_objectSpread({element:this.element},j),h):createElement(this.element,j,h)}/**
182
+ * Ensures the necessary DOM elements for portal rendering are created and attached.
183
+ *
184
+ * On the client-side, this method checks for or creates a `div` element appended
185
+ * to the `document.body` and initializes a React root on it. This setup is
186
+ * required for the `toPortal` method to function. It is idempotent and safe
187
+ * to call multiple times.
188
+ * @returns `true` if the portal infrastructure is ready, `false` if on the server.
189
+ * @private
190
+ */_ensurePortalInfrastructure(){if("undefined"==typeof window)return!1;if(this._portalDOMElement&&this._portalReactRoot)return!0;if(this._portalDOMElement&&!this._portalDOMElement.isConnected&&(this._portalDOMElement=null,this._portalDOMElement=null),this._portalDOMElement||(this._portalDOMElement=document.createElement("div"),document.body.appendChild(this._portalDOMElement)),!this._portalReactRoot){if(!this._portalDOMElement)return!1;this._portalReactRoot=createRoot(this._portalDOMElement)}return!0}/**
191
+ * Renders the node into a React Portal.
192
+ *
193
+ * This method mounts the node's rendered content into a separate DOM tree
194
+ * attached to the `document.body`. It's useful for rendering components like
195
+ * modals, tooltips, or notifications that need to appear above other UI elements.
196
+ *
197
+ * The returned object includes an `unmount` function to clean up the portal.
198
+ * @returns A `ReactDOMRoot` instance for managing the portal, or `null` if
199
+ * called in a server-side environment. The returned instance is enhanced
200
+ * with a custom `unmount` method that also cleans up the associated DOM element.
201
+ */toPortal(){var a=this;if(!this._ensurePortalInfrastructure()||!this._portalReactRoot)return null;var b=this.render();return this._portalReactRoot.render(b),_objectSpread(_objectSpread({},this._portalReactRoot),{},{unmount:function unmount(){a._portalReactRoot&&(a._portalReactRoot.unmount(),a._portalReactRoot=null),a._portalDOMElement&&(a._portalDOMElement.parentNode&&a._portalDOMElement.parentNode.removeChild(a._portalDOMElement),a._portalDOMElement=null)}})}}/**
117
202
  * Factory function to create a `BaseNode` instance.
118
203
  * @template AdditionalProps Additional props to merge with node props.
119
204
  * @template E The React element or component type.
@@ -77,4 +77,6 @@ export declare function getDOMProps<E extends ElementType, T extends ComponentPr
77
77
  * @returns `true` if the tag is in the no-style set, otherwise `false`.
78
78
  */
79
79
  export declare function hasNoStyleTag(tag?: NodeElement): boolean;
80
+ // Shallow comparison utility
81
+ export declare function shallowEqual(obj1: any, obj2: any): boolean;
80
82
  //# sourceMappingURL=common.helper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"common.helper.d.ts","sourceRoot":"","sources":["../../src/helper/common.helper.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEpE,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAGvE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,iCAE1B,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,gBAAgB,qCAmC5B,CAAA;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAsFxD;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,GAAG,CAAC,MAAM,CAA0B,CAAA;AAEjE;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAU3F;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,WAAW,EAAE,CAAC,SAAS,cAAc,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,CAUjH;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,CAAC,EAAE,WAAW,GAAG,OAAO,CAGxD"}
1
+ {"version":3,"file":"common.helper.d.ts","sourceRoot":"","sources":["../../src/helper/common.helper.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEpE,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAGvE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,iCAE1B,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,gBAAgB,qCAmC5B,CAAA;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAsFxD;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,GAAG,CAAC,MAAM,CAA0B,CAAA;AAEjE;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAU3F;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,WAAW,EAAE,CAAC,SAAS,cAAc,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,CAUjH;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,CAAC,EAAE,WAAW,GAAG,OAAO,CAGxD;AAED,6BAA6B;AAC7B,wBAAgB,YAAY,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAgB1D"}
@@ -61,4 +61,5 @@ function _typeof(a){"@babel/helpers - typeof";return _typeof="function"==typeof
61
61
  * Checks if a given tag is in the set of tags that should not receive style props.
62
62
  * @param tag The tag name to check (e.g., 'script', 'style').
63
63
  * @returns `true` if the tag is in the no-style set, otherwise `false`.
64
- */export function hasNoStyleTag(a){return!!(a&&"string"==typeof a)&&noStyleTagsSet.has(a.toLowerCase())}
64
+ */export function hasNoStyleTag(a){return!!(a&&"string"==typeof a)&&noStyleTagsSet.has(a.toLowerCase())}// Shallow comparison utility
65
+ export function shallowEqual(a,b){if(a===b)return!0;if(!a||!b)return!1;if("object"!==_typeof(a)||"object"!==_typeof(b))return a===b;var c=Object.keys(a),d=Object.keys(b);if(c.length!==d.length)return!1;for(var e,f=0,g=c;f<g.length;f++)if(e=g[f],!(e in b)||a[e]!==b[e])return!1;return!0}
@@ -1,5 +1,5 @@
1
1
  import type { CSSProperties } from 'react';
2
- import type { NodeInstance } from '../node.type.js';
2
+ import type { NodeElement, NodeInstance, Theme } from '../node.type.js';
3
3
  /**
4
4
  * Type guard to check if an object is a NodeInstance.
5
5
  *
@@ -12,21 +12,6 @@ import type { NodeInstance } from '../node.type.js';
12
12
  * @returns True if the object is a NodeInstance, false otherwise.
13
13
  */
14
14
  export declare const isNodeInstance: (obj: unknown) => obj is NodeInstance<any>;
15
- /**
16
- * Resolves theme variable references in an object's values recursively.
17
- * This function performs a "smart merge" to maintain object reference identity
18
- * for parts of the object that do not contain resolved theme variables or
19
- * other modifications. Only creates new objects or properties when a change occurs.
20
- * Handles nested objects and arrays, and prevents circular references.
21
- * Theme variables are referenced using the format "theme.path.to.value".
22
- * @param obj The object (or array) whose values should be resolved against the theme. Defaults to an empty object.
23
- * @param theme The theme object containing variable definitions. Optional.
24
- * @returns A new object (or array) with all theme variables resolved to their corresponding values,
25
- * or the original object (or array) if no changes were necessary.
26
- */
27
- export declare const resolveObjWithTheme: (obj?: Record<string, any>, theme?: Partial<{
28
- [key: string]: any;
29
- }> | undefined) => any;
30
15
  /**
31
16
  * Resolves default CSS styles to fix common flexbox layout issues.
32
17
  *
@@ -908,4 +893,25 @@ export declare const resolveDefaultStyle: (style: CSSProperties) => {
908
893
  minHeight: import("csstype").Property.MinHeight<string | number>;
909
894
  minWidth: import("csstype").Property.MinWidth<string | number>;
910
895
  };
896
+ /**
897
+ * Creates a stable hash string based on the provided children and optional theme.
898
+ *
899
+ * This function generates a hash that represents the structure and types of the given
900
+ * children nodes, along with an optional theme. The hash is designed to be stable across
901
+ * renders, meaning that the same input will always produce the same hash output.
902
+ *
903
+ * The hashing strategy includes:
904
+ * - For arrays of children, it includes the length and samples the types of the first few children.
905
+ * - For single child nodes, it includes the type of the node.
906
+ * - For primitive values (strings, numbers, etc.), it includes their type.
907
+ * - If a theme is provided, it includes a stringified version of the theme.
908
+ *
909
+ * This approach avoids deep traversal of potentially large or complex node trees,
910
+ * focusing instead on key characteristics that are likely to change when the structure
911
+ * or content changes.
912
+ * @param children The child nodes to hash, which can be a single node or an array of nodes.
913
+ * @param theme An optional theme object or string to include in the hash.
914
+ * @returns A stable hash string representing the structure and types of the children and theme.
915
+ */
916
+ export declare function createStableHash(children: NodeElement | NodeElement[], theme?: Theme): string;
911
917
  //# sourceMappingURL=node.helper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"node.helper.d.ts","sourceRoot":"","sources":["../../src/helper/node.helper.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAS,MAAM,mBAAmB,CAAA;AAG5D;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,4CAS1B,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB;;sBA+G/B,CAAA;AA+DD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiE/B,CAAA"}
1
+ {"version":3,"file":"node.helper.d.ts","sourceRoot":"","sources":["../../src/helper/node.helper.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAIzE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,4CAS1B,CAAA;AA4DD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiE/B,CAAA;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,WAAW,GAAG,WAAW,EAAE,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CA0B7F"}
@@ -1,4 +1,4 @@
1
- "use strict";var _excluded=["flex"];function _objectWithoutProperties(a,b){if(null==a)return{};var c,d,e=_objectWithoutPropertiesLoose(a,b);if(Object.getOwnPropertySymbols){var f=Object.getOwnPropertySymbols(a);for(d=0;d<f.length;d++)c=f[d],-1===b.indexOf(c)&&{}.propertyIsEnumerable.call(a,c)&&(e[c]=a[c])}return e}function _objectWithoutPropertiesLoose(a,b){if(null==a)return{};var c={};for(var d in a)if({}.hasOwnProperty.call(a,d)){if(-1!==b.indexOf(d))continue;c[d]=a[d]}return c}function ownKeys(a,b){var c=Object.keys(a);if(Object.getOwnPropertySymbols){var d=Object.getOwnPropertySymbols(a);b&&(d=d.filter(function(b){return Object.getOwnPropertyDescriptor(a,b).enumerable})),c.push.apply(c,d)}return c}function _objectSpread(a){for(var b,c=1;c<arguments.length;c++)b=null==arguments[c]?{}:arguments[c],c%2?ownKeys(Object(b),!0).forEach(function(c){_defineProperty(a,c,b[c])}):Object.getOwnPropertyDescriptors?Object.defineProperties(a,Object.getOwnPropertyDescriptors(b)):ownKeys(Object(b)).forEach(function(c){Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))});return a}function _defineProperty(a,b,c){return(b=_toPropertyKey(b))in a?Object.defineProperty(a,b,{value:c,enumerable:!0,configurable:!0,writable:!0}):a[b]=c,a}function _toPropertyKey(a){var b=_toPrimitive(a,"string");return"symbol"==_typeof(b)?b:b+""}function _toPrimitive(a,b){if("object"!=_typeof(a)||!a)return a;var c=a[Symbol.toPrimitive];if(void 0!==c){var d=c.call(a,b||"default");if("object"!=_typeof(d))return d;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===b?String:Number)(a)}function _typeof(a){"@babel/helpers - typeof";return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a},_typeof(a)}import{getValueByPath}from"./common.helper.js";/**
1
+ "use strict";var _excluded=["flex"];function ownKeys(a,b){var c=Object.keys(a);if(Object.getOwnPropertySymbols){var d=Object.getOwnPropertySymbols(a);b&&(d=d.filter(function(b){return Object.getOwnPropertyDescriptor(a,b).enumerable})),c.push.apply(c,d)}return c}function _objectSpread(a){for(var b,c=1;c<arguments.length;c++)b=null==arguments[c]?{}:arguments[c],c%2?ownKeys(Object(b),!0).forEach(function(c){_defineProperty(a,c,b[c])}):Object.getOwnPropertyDescriptors?Object.defineProperties(a,Object.getOwnPropertyDescriptors(b)):ownKeys(Object(b)).forEach(function(c){Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))});return a}function _defineProperty(a,b,c){return(b=_toPropertyKey(b))in a?Object.defineProperty(a,b,{value:c,enumerable:!0,configurable:!0,writable:!0}):a[b]=c,a}function _toPropertyKey(a){var b=_toPrimitive(a,"string");return"symbol"==_typeof(b)?b:b+""}function _toPrimitive(a,b){if("object"!=_typeof(a)||!a)return a;var c=a[Symbol.toPrimitive];if(void 0!==c){var d=c.call(a,b||"default");if("object"!=_typeof(d))return d;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===b?String:Number)(a)}function _objectWithoutProperties(a,b){if(null==a)return{};var c,d,e=_objectWithoutPropertiesLoose(a,b);if(Object.getOwnPropertySymbols){var f=Object.getOwnPropertySymbols(a);for(d=0;d<f.length;d++)c=f[d],-1===b.indexOf(c)&&{}.propertyIsEnumerable.call(a,c)&&(e[c]=a[c])}return e}function _objectWithoutPropertiesLoose(a,b){if(null==a)return{};var c={};for(var d in a)if({}.hasOwnProperty.call(a,d)){if(-1!==b.indexOf(d))continue;c[d]=a[d]}return c}function _typeof(a){"@babel/helpers - typeof";return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a},_typeof(a)}import{getElementTypeName}from"./common.helper.js";import{ObjHelper}from"./obj.helper.js";/**
2
2
  * Type guard to check if an object is a NodeInstance.
3
3
  *
4
4
  * A NodeInstance is expected to be a non-null object with:
@@ -9,32 +9,6 @@
9
9
  * @param obj The object to check.
10
10
  * @returns True if the object is a NodeInstance, false otherwise.
11
11
  */export var isNodeInstance=function isNodeInstance(a){return"object"===_typeof(a)&&null!==a&&"element"in a&&"function"==typeof a.render&&"function"==typeof a.toPortal&&"isBaseNode"in a};/**
12
- * Resolves theme variable references in an object's values recursively.
13
- * This function performs a "smart merge" to maintain object reference identity
14
- * for parts of the object that do not contain resolved theme variables or
15
- * other modifications. Only creates new objects or properties when a change occurs.
16
- * Handles nested objects and arrays, and prevents circular references.
17
- * Theme variables are referenced using the format "theme.path.to.value".
18
- * @param obj The object (or array) whose values should be resolved against the theme. Defaults to an empty object.
19
- * @param theme The theme object containing variable definitions. Optional.
20
- * @returns A new object (or array) with all theme variables resolved to their corresponding values,
21
- * or the original object (or array) if no changes were necessary.
22
- */export var resolveObjWithTheme=function resolveObjWithTheme(){var a=0<arguments.length&&arguments[0]!==void 0?arguments[0]:{},b=1<arguments.length?arguments[1]:void 0;if(!b||!!b&&"object"===_typeof(b)&&0===Object.keys(b).length||0===Object.keys(a).length)return a;/**
23
- * Recursively resolves theme variables within an object or array.
24
- * It tracks visited objects to prevent infinite recursion caused by circular references.
25
- * This function implements a "smart merge" to preserve object/array identity for unchanged parts.
26
- * @param currentObj The current object or array being processed in the recursion.
27
- * @param visited A Set to keep track of objects that have already been visited to detect circular references.
28
- * @returns The processed object/array with theme variables resolved, or the original `currentObj`
29
- * if no changes were made to it or its direct children (excluding deeper nested changes).
30
- */var c=function resolveRecursively(a,d){// Base cases for non-objects/null, or already visited objects (circular reference)
31
- if(null===a||"object"!==_typeof(a))return a;if(d.has(a))return a;// Handle Arrays
32
- if(d.add(a),Array.isArray(a)){for(var e=a,f=!1,g=0;g<a.length;g++){var h=a[g],j=c(h,d);j===h?f&&(e[g]=h):(!f&&(e=[...a],f=!0),e[g]=j)}return e}// Handle Plain Objects (only process objects created with {})
33
- var k=a,l=!1,m=function _loop(){// Ensure it's an own property
34
- var e=a[n],f=e;if("function"==typeof e||"object"===_typeof(e)&&null!==e&&!Array.isArray(e)&&Object.getPrototypeOf(e)!==Object.prototype||// Exclude plain objects and arrays
35
- "object"!==_typeof(e)&&"string"!=typeof e)f=e;else if("string"==typeof e&&e.includes("theme.")){var g=e,h=!1;g=g.replace(/theme\.([a-zA-Z0-9_.-]+)/g,function(a,c){var d=getValueByPath(b,c);return void 0!==d&&null!==d?(h=!0,"object"===_typeof(d)&&!Array.isArray(d)&&"default"in d?d["default"]:d):a}),f=h&&g!==e?g:e}else"object"===_typeof(e)&&null!==e&&(// Recursively process nested objects or arrays
36
- f=c(e,d));f===e?l&&(k[n]=e):(!l&&(k=_objectSpread({},a),l=!0),k[n]=f)};for(var n in a)m();return k};// Initial call, ensure `obj` could be an array as well
37
- return c(a,new Set)};/**
38
12
  * Parsed flex shorthand components for CSS flex property
39
13
  * @interface FlexComponents
40
14
  * @property grow - The flex-grow value (how much the item should grow)
@@ -59,8 +33,7 @@ return c(a,new Set)};/**
59
33
  * parseFlexShorthand('1 0 auto') // → {grow: 1, shrink: 0, basis: 'auto'}
60
34
  */function parseFlexShorthand(a){// Early returns for invalid inputs
61
35
  if(null===a||a===void 0)return null;// Handle numeric flex values (e.g., flex: 1)
62
- if("number"==typeof a)return{grow:a,shrink:1,basis:"0%"};// Only process string values
63
- if("string"!=typeof a)return null;var b=a.trim().toLowerCase();if(!b)return null;// Handle CSS keyword values
36
+ if("number"==typeof a)return{grow:a,shrink:1,basis:"0%"};var b=a.trim().toLowerCase();if(!b)return null;// Handle CSS keyword values
64
37
  return"none"===b?{grow:0,shrink:0,basis:"auto"}:"auto"===b?{grow:1,shrink:1,basis:"auto"}:"initial"===b?{grow:0,shrink:1,basis:"auto"}:null}/**
65
38
  * Resolves default CSS styles to fix common flexbox layout issues.
66
39
  *
@@ -136,4 +109,23 @@ if(!f){var k="column"===d.flexDirection||"column-reverse"===d.flexDirection,l="r
136
109
  return _objectSpread({flex:c,// Preserve original flex shorthand
137
110
  flexShrink:j,// Apply computed or explicit flexShrink
138
111
  minHeight:0,// Fix flex item scrolling issues
139
- minWidth:0},d)};
112
+ minWidth:0},d)};/**
113
+ * Creates a stable hash string based on the provided children and optional theme.
114
+ *
115
+ * This function generates a hash that represents the structure and types of the given
116
+ * children nodes, along with an optional theme. The hash is designed to be stable across
117
+ * renders, meaning that the same input will always produce the same hash output.
118
+ *
119
+ * The hashing strategy includes:
120
+ * - For arrays of children, it includes the length and samples the types of the first few children.
121
+ * - For single child nodes, it includes the type of the node.
122
+ * - For primitive values (strings, numbers, etc.), it includes their type.
123
+ * - If a theme is provided, it includes a stringified version of the theme.
124
+ *
125
+ * This approach avoids deep traversal of potentially large or complex node trees,
126
+ * focusing instead on key characteristics that are likely to change when the structure
127
+ * or content changes.
128
+ * @param children The child nodes to hash, which can be a single node or an array of nodes.
129
+ * @param theme An optional theme object or string to include in the hash.
130
+ * @returns A stable hash string representing the structure and types of the children and theme.
131
+ */export function createStableHash(a,b){var c=Math.min,d="";if(b&&(d+="t:".concat("object"===_typeof(b)?ObjHelper.stringify(b):b+"",";")),Array.isArray(a)){d+="a:".concat(a.length,";");for(var e,f=c(3,a.length),g=0;g<f;g++)e=a[g],d+=e&&"object"===_typeof(e)&&"type"in e?"c".concat(g,":").concat(getElementTypeName(e),";"):"c".concat(g,":").concat(_typeof(e),";")}else d+=a&&"object"===_typeof(a)&&"type"in a?"s:".concat(getElementTypeName(a),";"):"s:".concat(_typeof(a),";");return d}
@@ -0,0 +1,6 @@
1
+ export declare class ObjHelper {
2
+ private constructor();
3
+ static stringify(obj: any, space?: number): string;
4
+ static parse(str: string): any;
5
+ }
6
+ //# sourceMappingURL=obj.helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"obj.helper.d.ts","sourceRoot":"","sources":["../../src/helper/obj.helper.ts"],"names":[],"mappings":"AAWA,qBAAa,SAAS;IACpB,OAAO,eAAiB;IAExB,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,SAAI,GAAG,MAAM,CAiD5C;IAED,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CA+C7B;CACF"}
@@ -0,0 +1 @@
1
+ function _typeof(a){"@babel/helpers - typeof";return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a},_typeof(a)}export class ObjHelper{constructor(){}static stringify(a){var b=1<arguments.length&&arguments[1]!==void 0?arguments[1]:2,c=new Map,d=new Map,e=0,f=0,g=function replacer(a,b){if("function"==typeof b)return d.has(b)||d.set(b,f++),{$type:"Function",name:b.name||"",id:d.get(b)};if("symbol"===_typeof(b)){var g;return{$type:"Symbol",key:null!==(g=b.description)&&void 0!==g?g:""}}if("bigint"==typeof b)return{$type:"BigInt",value:b.toString()};if(b instanceof Date)return{$type:"Date",value:b.toISOString()};if(b instanceof RegExp)return{$type:"RegExp",source:b.source,flags:b.flags};if(b instanceof Map)return{$type:"Map",entries:Array.from(b.entries())};if(b instanceof Set)return{$type:"Set",values:Array.from(b.values())};if("object"===_typeof(b)&&null!==b){if(c.has(b))return{$type:"Circular",ref:c.get(b)};c.set(b,e++)}return b};return JSON.stringify(a,g,b)}static parse(a){var b=[],c=function reviver(a,b){if(b&&"object"===_typeof(b)&&"$type"in b)switch(b.$type){case"Function":return function FunctionPlaceholder(){throw new Error("Function placeholder called: ".concat(b.name||"anonymous","#").concat(b.id))};case"Symbol":return Symbol(b.key);case"BigInt":return BigInt(b.value);case"Date":return new Date(b.value);case"RegExp":return new RegExp(b.source,b.flags);case"Map":return new Map(b.entries);case"Set":return new Set(b.values);case"Circular":return{$circularRef:b.ref}}return b},d=JSON.parse(a,c),e=function fixCirculars(a){if(a&&"object"===_typeof(a)){if(a.$circularRef!==void 0)return b[a.$circularRef];if(!b.includes(a)){b.push(a);for(var c,d=0,f=Object.keys(a);d<f.length;d++)c=f[d],a[c]=e(a[c])}}return a};return e(d)}}
@@ -0,0 +1,79 @@
1
+ import type { Theme } from '../node.type.js';
2
+ /**
3
+ * Cache manager for theme resolution operations.
4
+ * Provides singleton-based caching with different strategies for server vs client environments.
5
+ */
6
+ declare class ThemeResolverCache {
7
+ private static _instance;
8
+ private readonly _resolutionCache;
9
+ private readonly _pathLookupCache;
10
+ private readonly _themeRegex;
11
+ // Track cache statistics for performance monitoring
12
+ private _stats;
13
+ private constructor();
14
+ /**
15
+ * Get the singleton instance of the cache manager
16
+ */
17
+ static getInstance(): ThemeResolverCache;
18
+ /**
19
+ * Generate a stable cache key from object and theme
20
+ */
21
+ private _generateCacheKey;
22
+ /**
23
+ * Check if resolution result exists in cache
24
+ */
25
+ getResolution(obj: Record<string, any>, theme: Theme): any | null;
26
+ /**
27
+ * Store resolution result in cache
28
+ */
29
+ setResolution(obj: Record<string, any>, theme: Theme, result: any): void;
30
+ /**
31
+ * Get cached theme path lookup
32
+ */
33
+ getPathLookup(theme: Theme, path: string): any | null;
34
+ /**
35
+ * Cache theme path lookup result
36
+ */
37
+ setPathLookup(theme: Theme, path: string, value: any): void;
38
+ /**
39
+ * Get the shared regex instance (reused for performance)
40
+ */
41
+ getThemeRegex(): RegExp;
42
+ /**
43
+ * Clear all caches (useful for testing or memory management)
44
+ */
45
+ clearCaches(): void;
46
+ /**
47
+ * Get cache statistics for performance monitoring
48
+ */
49
+ getStats(): {
50
+ hits: number;
51
+ misses: number;
52
+ pathHits: number;
53
+ pathMisses: number;
54
+ };
55
+ /**
56
+ * Check if we should use caching (server-side only for RSC optimization)
57
+ */
58
+ shouldCache(): boolean;
59
+ }
60
+ // Module-level cache instance
61
+ declare const themeCache: ThemeResolverCache;
62
+ /**
63
+ * Resolves theme variable references in an object's values recursively.
64
+ * This function performs a "smart merge" to maintain object reference identity
65
+ * for parts of the object that do not contain resolved theme variables or
66
+ * other modifications. Only creates new objects or properties when a change occurs.
67
+ * Handles nested objects and arrays, and prevents circular references.
68
+ * Theme variables are referenced using the format "theme.path.to.value".
69
+ * @param obj The object (or array) whose values should be resolved against the theme. Defaults to an empty object.
70
+ * @param theme The theme object containing variable definitions. Optional.
71
+ * @returns A new object (or array) with all theme variables resolved to their corresponding values,
72
+ * or the original object (or array) if no changes were necessary.
73
+ */
74
+ export declare const resolveObjWithTheme: (obj?: Record<string, any>, theme?: Partial<{
75
+ [key: string]: any;
76
+ }> | undefined) => any;
77
+ // Export cache instance for testing and monitoring
78
+ export { themeCache as ThemeResolverCache };
79
+ //# sourceMappingURL=theme.helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.helper.d.ts","sourceRoot":"","sources":["../../src/helper/theme.helper.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAG9C;;;GAGG;AACH,cAAM,kBAAkB;IACtB,OAAO,CAAC,MAAM,CAAC,SAAS,CAAkC;IAE1D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAyB;IAC1D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAyB;IAC1D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA8B;IAE1D,oDAAoD;IACpD,OAAO,CAAC,MAAM,CAKb;IAED,OAAO,eAEN;IAED;;OAEG;IACH,MAAM,CAAC,WAAW,IAAI,kBAAkB,CAKvC;IAED;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAKzB;;OAEG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,GAAG,GAAG,IAAI,CAUhE;IAED;;OAEG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,GAAG,IAAI,CAGvE;IAED;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAUpD;IAED;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI,CAG1D;IAED;;OAEG;IACH,aAAa,IAAI,MAAM,CAItB;IAED;;OAEG;IACH,WAAW,IAAI,IAAI,CAIlB;IAED;;OAEG;IACH,QAAQ;;;;;MAEP;IAED;;OAEG;IACH,WAAW,IAAI,OAAO,CAErB;CACF;AAED,8BAA8B;AAC9B,QAAA,MAAM,UAAU,oBAAmC,CAAA;AAEnD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB;;sBAwI/B,CAAA;AAED,mDAAmD;AACnD,OAAO,EAAE,UAAU,IAAI,kBAAkB,EAAE,CAAA"}
@@ -0,0 +1,59 @@
1
+ function _typeof(a){"@babel/helpers - typeof";return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a},_typeof(a)}function ownKeys(a,b){var c=Object.keys(a);if(Object.getOwnPropertySymbols){var d=Object.getOwnPropertySymbols(a);b&&(d=d.filter(function(b){return Object.getOwnPropertyDescriptor(a,b).enumerable})),c.push.apply(c,d)}return c}function _objectSpread(a){for(var b,c=1;c<arguments.length;c++)b=null==arguments[c]?{}:arguments[c],c%2?ownKeys(Object(b),!0).forEach(function(c){_defineProperty(a,c,b[c])}):Object.getOwnPropertyDescriptors?Object.defineProperties(a,Object.getOwnPropertyDescriptors(b)):ownKeys(Object(b)).forEach(function(c){Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))});return a}function _defineProperty(a,b,c){return(b=_toPropertyKey(b))in a?Object.defineProperty(a,b,{value:c,enumerable:!0,configurable:!0,writable:!0}):a[b]=c,a}function _toPropertyKey(a){var b=_toPrimitive(a,"string");return"symbol"==_typeof(b)?b:b+""}function _toPrimitive(a,b){if("object"!=_typeof(a)||!a)return a;var c=a[Symbol.toPrimitive];if(void 0!==c){var d=c.call(a,b||"default");if("object"!=_typeof(d))return d;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===b?String:Number)(a)}import{getValueByPath}from"./common.helper.js";import{ObjHelper}from"./obj.helper.js";/**
2
+ * Cache manager for theme resolution operations.
3
+ * Provides singleton-based caching with different strategies for server vs client environments.
4
+ */class ThemeResolverCache{constructor(){// Track cache statistics for performance monitoring
5
+ _defineProperty(this,"_resolutionCache",new Map),_defineProperty(this,"_pathLookupCache",new Map),_defineProperty(this,"_themeRegex",/theme\.([a-zA-Z0-9_.-]+)/g),_defineProperty(this,"_stats",{hits:0,misses:0,pathHits:0,pathMisses:0})}// Private constructor for singleton pattern
6
+ /**
7
+ * Get the singleton instance of the cache manager
8
+ */static getInstance(){return ThemeResolverCache._instance||(ThemeResolverCache._instance=new ThemeResolverCache),ThemeResolverCache._instance}/**
9
+ * Generate a stable cache key from object and theme
10
+ */_generateCacheKey(a,b){// Use a more efficient key generation for better performance
11
+ return"".concat(ObjHelper.stringify(a),"_").concat(ObjHelper.stringify(b))}/**
12
+ * Check if resolution result exists in cache
13
+ */getResolution(a,b){var c=this._generateCacheKey(a,b);return this._resolutionCache.has(c)?(this._stats.hits++,this._resolutionCache.get(c)):(this._stats.misses++,null)}/**
14
+ * Store resolution result in cache
15
+ */setResolution(a,b,c){var d=this._generateCacheKey(a,b);this._resolutionCache.set(d,c)}/**
16
+ * Get cached theme path lookup
17
+ */getPathLookup(a,b){var c="".concat(ObjHelper.stringify(a),"_").concat(b);return this._pathLookupCache.has(c)?(this._stats.pathHits++,this._pathLookupCache.get(c)):(this._stats.pathMisses++,null)}/**
18
+ * Cache theme path lookup result
19
+ */setPathLookup(a,b,c){var d="".concat(ObjHelper.stringify(a),"_").concat(b);this._pathLookupCache.set(d,c)}/**
20
+ * Get the shared regex instance (reused for performance)
21
+ */getThemeRegex(){return this._themeRegex.lastIndex=0,this._themeRegex}/**
22
+ * Clear all caches (useful for testing or memory management)
23
+ */clearCaches(){this._resolutionCache.clear(),this._pathLookupCache.clear(),this._stats={hits:0,misses:0,pathHits:0,pathMisses:0}}/**
24
+ * Get cache statistics for performance monitoring
25
+ */getStats(){return _objectSpread({},this._stats)}/**
26
+ * Check if we should use caching (server-side only for RSC optimization)
27
+ */shouldCache(){return"undefined"==typeof window}}// Module-level cache instance
28
+ _defineProperty(ThemeResolverCache,"_instance",null);var themeCache=ThemeResolverCache.getInstance();/**
29
+ * Resolves theme variable references in an object's values recursively.
30
+ * This function performs a "smart merge" to maintain object reference identity
31
+ * for parts of the object that do not contain resolved theme variables or
32
+ * other modifications. Only creates new objects or properties when a change occurs.
33
+ * Handles nested objects and arrays, and prevents circular references.
34
+ * Theme variables are referenced using the format "theme.path.to.value".
35
+ * @param obj The object (or array) whose values should be resolved against the theme. Defaults to an empty object.
36
+ * @param theme The theme object containing variable definitions. Optional.
37
+ * @returns A new object (or array) with all theme variables resolved to their corresponding values,
38
+ * or the original object (or array) if no changes were necessary.
39
+ */export var resolveObjWithTheme=function resolveObjWithTheme(){var a=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{},b=1<arguments.length?arguments[1]:void 0;if(!b||!!b&&"object"===_typeof(b)&&0===Object.keys(b).length||0===Object.keys(a).length)return a;// Check cache first (only on server-side for RSC optimization)
40
+ if(themeCache.shouldCache()){var c=themeCache.getResolution(a,b);if(null!==c)return c}/**
41
+ * Recursively resolves theme variables within an object or array.
42
+ * It tracks visited objects to prevent infinite recursion caused by circular references.
43
+ * This function implements a "smart merge" to preserve object/array identity for unchanged parts.
44
+ * @param currentObj The current object or array being processed in the recursion.
45
+ * @param visited A Set to keep track of objects that have already been visited to detect circular references.
46
+ * @returns The processed object/array with theme variables resolved, or the original `currentObj`
47
+ * if no changes were made to it or its direct children (excluding deeper nested changes).
48
+ */var d=function resolveRecursively(a,c){// Base cases for non-objects/null, or already visited objects (circular reference)
49
+ if(null===a||"object"!==_typeof(a))return a;if(c.has(a))return a;// Handle Arrays
50
+ if(c.add(a),Array.isArray(a)){for(var e=a,f=!1,g=0;g<a.length;g++){var h=a[g],j=d(h,c);j===h?f&&(e[g]=h):(!f&&(e=[...a],f=!0),e[g]=j)}return e}// Handle Plain Objects (only process objects created with {})
51
+ var k=a,l=!1,m=function _loop(){// Ensure it's an own property
52
+ var e=a[n],f=e;if("function"==typeof e||"object"===_typeof(e)&&null!==e&&!Array.isArray(e)&&Object.getPrototypeOf(e)!==Object.prototype||// Exclude plain objects and arrays
53
+ "object"!==_typeof(e)&&"string"!=typeof e)f=e;else if("string"==typeof e&&e.includes("theme.")){var g=e,h=!1,i=themeCache.getThemeRegex();// Use cached regex instance
54
+ g=g.replace(i,function(a,c){// Check path lookup cache first
55
+ var d=themeCache.getPathLookup(b,c);return null===d&&(d=getValueByPath(b,c),themeCache.setPathLookup(b,c,d)),void 0!==d&&null!==d?(h=!0,"object"===_typeof(d)&&!Array.isArray(d)&&"default"in d?d["default"]:d):a}),f=h&&g!==e?g:e}else"object"===_typeof(e)&&null!==e&&(// Recursively process nested objects or arrays
56
+ f=d(e,c));f===e?l&&(k[n]=e):(!l&&(k=_objectSpread({},a),l=!0),k[n]=f)};for(var n in a)m();return k},e=d(a,new Set);// Perform the resolution
57
+ // Cache the result (only on server-side)
58
+ return themeCache.shouldCache()&&themeCache.setResolution(a,b,e),e};// Export cache instance for testing and monitoring
59
+ export{themeCache as ThemeResolverCache};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meonode/ui",
3
3
  "description": "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.",
4
- "version": "0.2.10",
4
+ "version": "0.2.12",
5
5
  "type": "module",
6
6
  "main": "./dist/main.js",
7
7
  "types": "./dist/main.d.ts",
@@ -53,10 +53,10 @@
53
53
  "babel-plugin-module-resolver": "^5.0.2",
54
54
  "babel-preset-minify": "^0.5.2",
55
55
  "eslint": "^9.35.0",
56
- "eslint-plugin-jsdoc": "^54.7.0",
56
+ "eslint-plugin-jsdoc": "^55.4.0",
57
57
  "eslint-plugin-prettier": "^5.5.4",
58
58
  "eslint-plugin-unused-imports": "^4.2.0",
59
- "next": "^15.5.2",
59
+ "next": "^15.5.3",
60
60
  "prettier": "^3.6.2",
61
61
  "react-dom": "^19.1.1",
62
62
  "tsc-alias": "^1.8.16",