nexa-runtime 0.7.0 → 0.7.2

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/dist/index.js CHANGED
@@ -19,7 +19,10 @@ export function mount(vnode, containerOrSelector) {
19
19
  ? domOptions.querySelector(containerOrSelector)
20
20
  : containerOrSelector;
21
21
  if (!container) {
22
- throw new Error(`Target container not found: ${containerOrSelector}`);
22
+ const selector = typeof containerOrSelector === 'string' ? containerOrSelector : String(containerOrSelector);
23
+ throw new Error(`Target container not found: "${selector}". ` +
24
+ `Make sure the element exists in the DOM before calling mount(). ` +
25
+ `Use mount(vnode, document.getElementById('app')) or ensure your HTML has <${selector.replace(/^[#.]/, '')}>.`);
23
26
  }
24
27
  return baseMount(vnode, container, domOptions);
25
28
  }
package/dist/vdom/diff.js CHANGED
@@ -85,10 +85,68 @@ function diffProps(oldV, newV) {
85
85
  function diffChildren(oldV, newV, container, patches) {
86
86
  const oldChildren = (oldV.children ?? []);
87
87
  const newChildren = (newV.children ?? []);
88
- const maxLen = Math.max(oldChildren.length, newChildren.length);
88
+ const oldKeyMap = new Map();
89
+ const oldKeyIdx = new Map();
90
+ const oldUnkeyed = [];
91
+ for (let i = 0; i < oldChildren.length; i++) {
92
+ const child = oldChildren[i];
93
+ if (child.key != null) {
94
+ oldKeyMap.set(child.key, child);
95
+ oldKeyIdx.set(child.key, i);
96
+ }
97
+ else {
98
+ oldUnkeyed.push(child);
99
+ }
100
+ }
101
+ const matchedKeys = new Set();
102
+ const newUnkeyed = [];
103
+ for (let newIdx = 0; newIdx < newChildren.length; newIdx++) {
104
+ const newChild = newChildren[newIdx];
105
+ if (newChild.key != null) {
106
+ if (oldKeyMap.has(newChild.key)) {
107
+ const oldChild = oldKeyMap.get(newChild.key);
108
+ matchedKeys.add(newChild.key);
109
+ const oldIdx = oldKeyIdx.get(newChild.key);
110
+ if (oldIdx !== newIdx) {
111
+ patches.push({
112
+ type: 'replace',
113
+ oldVNode: oldChild,
114
+ newVNode: newChild,
115
+ parent: container,
116
+ anchor: null,
117
+ });
118
+ }
119
+ else {
120
+ diffVNode(oldChild, newChild, container, patches);
121
+ }
122
+ }
123
+ else {
124
+ patches.push({
125
+ type: 'create',
126
+ newVNode: newChild,
127
+ parent: container,
128
+ anchor: null,
129
+ });
130
+ }
131
+ }
132
+ else {
133
+ newUnkeyed.push(newChild);
134
+ }
135
+ }
136
+ for (const oldChild of oldChildren) {
137
+ if (oldChild.key != null && !matchedKeys.has(oldChild.key)) {
138
+ patches.push({
139
+ type: 'remove',
140
+ oldVNode: oldChild,
141
+ parent: container,
142
+ anchor: null,
143
+ });
144
+ }
145
+ }
146
+ const maxLen = Math.max(oldUnkeyed.length, newUnkeyed.length);
89
147
  for (let i = 0; i < maxLen; i++) {
90
- const oldChild = oldChildren[i];
91
- const newChild = newChildren[i];
148
+ const oldChild = oldUnkeyed[i];
149
+ const newChild = newUnkeyed[i];
92
150
  if (!oldChild && newChild) {
93
151
  patches.push({
94
152
  type: 'create',
package/dist/vdom/dom.js CHANGED
@@ -94,6 +94,10 @@ export const domOptions = {
94
94
  else if (key === 'htmlFor') {
95
95
  el.setAttribute('for', String(nextValue));
96
96
  }
97
+ else if (key === 'ref') {
98
+ if (typeof nextValue === 'function')
99
+ nextValue(el);
100
+ }
97
101
  else if (typeof nextValue === 'boolean') {
98
102
  if (nextValue)
99
103
  el.setAttribute(key, '');
package/dist/vdom/hmr.js CHANGED
@@ -23,14 +23,63 @@ export function unregisterInstance(instance) {
23
23
  instances.delete(instance);
24
24
  }
25
25
  }
26
+ function deepClonePreservingSignals(obj) {
27
+ if (!obj || typeof obj !== 'object')
28
+ return obj;
29
+ if (Array.isArray(obj))
30
+ return obj.map(deepClonePreservingSignals);
31
+ const clone = {};
32
+ for (const key in obj) {
33
+ const val = obj[key];
34
+ if (val && typeof val === 'object' && 'value' in val && typeof val.peek === 'function') {
35
+ clone[key] = val;
36
+ }
37
+ else if (val && typeof val === 'object' && 'peek' in val) {
38
+ clone[key] = val;
39
+ }
40
+ else {
41
+ clone[key] = deepClonePreservingSignals(val);
42
+ }
43
+ }
44
+ return clone;
45
+ }
26
46
  export function reloadComponent(id, newComp) {
27
47
  const instances = componentInstances.get(id);
28
48
  if (!instances)
29
49
  return;
30
50
  for (const instance of instances) {
31
- // Update the component definition
32
- instance.component.render = newComp.render;
33
- // Trigger update
51
+ const hasNewSetup = typeof newComp.setup === 'function';
52
+ const hasNewRender = typeof newComp.render === 'function';
53
+ if (hasNewSetup && instance.component.setup) {
54
+ const oldPropsValue = deepClonePreservingSignals(instance.props.value);
55
+ instance.component.setup = newComp.setup;
56
+ instance.component.render = newComp.render;
57
+ if (instance.slots) {
58
+ const slotsCtx = {
59
+ emit: (event, ...args) => {
60
+ const key = `on${event[0].toUpperCase()}${event.slice(1)}`;
61
+ const resolvedProps = instance.props.value;
62
+ const handler = resolvedProps?.[key];
63
+ if (handler)
64
+ handler(...args);
65
+ },
66
+ slots: instance.slots.value,
67
+ };
68
+ const propsProxy = new Proxy({}, {
69
+ get(_, key) {
70
+ const val = instance.props.value[key];
71
+ return val !== undefined ? val : oldPropsValue[key];
72
+ },
73
+ });
74
+ const newSetupState = newComp.setup(propsProxy, slotsCtx);
75
+ if (typeof newSetupState === 'object' && newSetupState !== null) {
76
+ instance.setupState = newSetupState;
77
+ }
78
+ }
79
+ }
80
+ else if (hasNewRender) {
81
+ instance.component.render = newComp.render;
82
+ }
34
83
  if (instance.update && typeof instance.update.run === 'function') {
35
84
  instance.update.run();
36
85
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexa-runtime",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -13,7 +13,7 @@
13
13
  }
14
14
  },
15
15
  "dependencies": {
16
- "nexa-reactivity": "0.7.0"
16
+ "nexa-reactivity": "0.7.2"
17
17
  },
18
18
  "files": [
19
19
  "dist"