@pfern/elements 0.1.6 → 0.1.7

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.
Files changed (2) hide show
  1. package/elements.js +20 -6
  2. package/package.json +1 -1
package/elements.js CHANGED
@@ -26,6 +26,8 @@ const rootMap = new WeakMap()
26
26
 
27
27
  const isNodeEnv = typeof document === 'undefined'
28
28
 
29
+ let componentUpdateDepth = 0
30
+
29
31
  /**
30
32
  * Determines whether two nodes have changed enough to require replacement.
31
33
  * Compares type, string value, or element tag.
@@ -185,8 +187,12 @@ const renderTree = (node, isRoot = true) => {
185
187
  }
186
188
 
187
189
  if (Array.isArray(node) && node[0] === 'wrap') {
188
- const [_tag, _props, child] = node
189
- return renderTree(child, true)
190
+ const [_tag, props = {}, child] = node
191
+ const el = renderTree(child, true)
192
+ if (props && typeof props === 'object' && props.__instance) {
193
+ rootMap.set(props.__instance, el)
194
+ }
195
+ return el
190
196
  }
191
197
 
192
198
  const [tag, props = {}, ...children] = node
@@ -298,17 +304,25 @@ export const render = (vtree, container = null) => {
298
304
  * @returns {(...args: any[]) => any} - A callable component that can manage its own subtree.
299
305
  */
300
306
  export const component = fn => {
307
+ const instance = {}
301
308
  return (...args) => {
302
309
  try {
310
+ const prevEl = rootMap.get(instance)
311
+ const canUpdateInPlace = !!prevEl?.parentNode && componentUpdateDepth === 0
312
+
313
+ componentUpdateDepth++
303
314
  const vnode = fn(...args)
304
- const prevEl = rootMap.get(vnode)
305
- if (prevEl?.parentNode) {
306
- const replacement = renderTree(['wrap', {}, vnode], true)
315
+ componentUpdateDepth--
316
+
317
+ if (canUpdateInPlace) {
318
+ const replacement = renderTree(['wrap', { __instance: instance }, vnode], true)
307
319
  prevEl.parentNode.replaceChild(replacement, prevEl)
308
320
  return replacement.__vnode
309
321
  }
310
- return ['wrap', {}, vnode]
322
+
323
+ return ['wrap', { __instance: instance }, vnode]
311
324
  } catch (err) {
325
+ componentUpdateDepth = Math.max(0, componentUpdateDepth - 1)
312
326
  console.error('Component error:', err)
313
327
  return ['div', {}, `Error: ${err.message}`]
314
328
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pfern/elements",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "A minimalist, pure functional declarative UI toolkit.",
5
5
  "type": "module",
6
6
  "main": "elements.js",