valyrian.js 7.2.1 → 7.2.3

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.
@@ -24,54 +24,71 @@ __export(signal_exports, {
24
24
  module.exports = __toCommonJS(signal_exports);
25
25
  var import_valyrian = require("valyrian.js");
26
26
  function Signal(initialValue) {
27
- const context = { ...import_valyrian.current };
28
- if (context.vnode) {
29
- if (!context.vnode.signals) {
30
- context.vnode.signals = context.oldVnode?.signals || [];
31
- context.vnode.calls = -1;
32
- context.vnode.subscribers = context.oldVnode?.subscribers || [];
33
- context.vnode.initialChildren = [...context.vnode.children];
27
+ const { vnode, component } = { ...import_valyrian.current };
28
+ if (vnode) {
29
+ if (!vnode.components) {
30
+ vnode.components = [];
34
31
  }
35
- let signal2 = context.vnode.signals[++context.vnode.calls];
32
+ if (vnode.components.indexOf(component) === -1) {
33
+ vnode.signal_calls = -1;
34
+ vnode.components.push(component);
35
+ if (!component.signals) {
36
+ component.signals = [];
37
+ (0, import_valyrian.onUnmount)(() => Reflect.deleteProperty(component, "signals"));
38
+ }
39
+ }
40
+ let signal2 = component.signals[++vnode.signal_calls];
36
41
  if (signal2) {
42
+ signal2[3].length = 0;
37
43
  return signal2;
38
44
  }
39
45
  }
40
46
  let value = initialValue;
41
- const subscribers = [];
47
+ const subscriptions = [];
42
48
  const subscribe = (callback) => {
43
- if (subscribers.indexOf(callback) === -1) {
44
- subscribers.push(callback);
49
+ if (subscriptions.indexOf(callback) === -1) {
50
+ subscriptions.push(callback);
51
+ }
52
+ };
53
+ let vnodesToUpdate = [];
54
+ const updateVnodes = () => {
55
+ let vnodesToUpdateCopy = vnodesToUpdate.filter((vnode2, index, self) => {
56
+ return self.findIndex((v2) => v2.dom === vnode2.dom) === index;
57
+ });
58
+ for (let i = 0, l = vnodesToUpdateCopy.length; i < l; i++) {
59
+ const vnode2 = vnodesToUpdateCopy[i];
60
+ let newVnode = (0, import_valyrian.v)(vnode2.tag, vnode2.props, ...vnode2.initialChildren);
61
+ newVnode.dom = vnode2.dom;
62
+ newVnode.isSVG = vnode2.isSVG;
63
+ (0, import_valyrian.updateVnode)(newVnode, vnode2);
45
64
  }
46
65
  };
47
66
  function get() {
67
+ const { vnode: vnode2 } = import_valyrian.current;
68
+ if (vnode2 && vnodesToUpdate.indexOf(vnode2) === -1) {
69
+ if (!vnode2.initialChildren) {
70
+ vnode2.initialChildren = [...vnode2.children];
71
+ }
72
+ vnodesToUpdate.push(vnode2);
73
+ subscribe(updateVnodes);
74
+ }
48
75
  return value;
49
76
  }
50
- get.value = value;
51
- get.toJSON = get.valueOf = get;
52
- get.toString = () => `${value}`;
53
77
  const set = (newValue) => {
54
- value = newValue;
55
- get.value = value;
56
- for (let i = 0, l = subscribers.length; i < l; i++) {
57
- subscribers[i](value);
78
+ if (import_valyrian.current.event) {
79
+ import_valyrian.current.event.preventDefault();
80
+ }
81
+ if (newValue === value) {
82
+ return;
58
83
  }
59
- if (context.vnode) {
60
- let newVnode = (0, import_valyrian.v)(context.vnode.tag, context.vnode.props, ...context.vnode.initialChildren);
61
- newVnode.dom = context.vnode.dom;
62
- newVnode.isSVG = context.vnode.isSVG;
63
- context.vnode.subscribers.forEach(
64
- (subscribers2) => subscribers2.length = 0
65
- );
66
- context.vnode.subscribers = [];
67
- return (0, import_valyrian.updateVnode)(newVnode, context.vnode);
84
+ value = newValue;
85
+ for (let i = 0, l = subscriptions.length; i < l; i++) {
86
+ subscriptions[i](value);
68
87
  }
69
- return (0, import_valyrian.update)();
70
88
  };
71
- let signal = [get, set, subscribe];
72
- if (context.vnode) {
73
- context.vnode.signals.push(signal);
74
- context.vnode.subscribers.push(subscribers);
89
+ let signal = [get, set, subscribe, subscriptions];
90
+ if (vnode) {
91
+ component.signals.push(signal);
75
92
  }
76
93
  return signal;
77
94
  }
@@ -1,54 +1,71 @@
1
1
  // lib/signal/index.ts
2
- import { current, update, updateVnode, v } from "valyrian.js";
2
+ import { current, onUnmount, updateVnode, v } from "valyrian.js";
3
3
  function Signal(initialValue) {
4
- const context = { ...current };
5
- if (context.vnode) {
6
- if (!context.vnode.signals) {
7
- context.vnode.signals = context.oldVnode?.signals || [];
8
- context.vnode.calls = -1;
9
- context.vnode.subscribers = context.oldVnode?.subscribers || [];
10
- context.vnode.initialChildren = [...context.vnode.children];
11
- }
12
- let signal2 = context.vnode.signals[++context.vnode.calls];
4
+ const { vnode, component } = { ...current };
5
+ if (vnode) {
6
+ if (!vnode.components) {
7
+ vnode.components = [];
8
+ }
9
+ if (vnode.components.indexOf(component) === -1) {
10
+ vnode.signal_calls = -1;
11
+ vnode.components.push(component);
12
+ if (!component.signals) {
13
+ component.signals = [];
14
+ onUnmount(() => Reflect.deleteProperty(component, "signals"));
15
+ }
16
+ }
17
+ let signal2 = component.signals[++vnode.signal_calls];
13
18
  if (signal2) {
19
+ signal2[3].length = 0;
14
20
  return signal2;
15
21
  }
16
22
  }
17
23
  let value = initialValue;
18
- const subscribers = [];
24
+ const subscriptions = [];
19
25
  const subscribe = (callback) => {
20
- if (subscribers.indexOf(callback) === -1) {
21
- subscribers.push(callback);
26
+ if (subscriptions.indexOf(callback) === -1) {
27
+ subscriptions.push(callback);
28
+ }
29
+ };
30
+ let vnodesToUpdate = [];
31
+ const updateVnodes = () => {
32
+ let vnodesToUpdateCopy = vnodesToUpdate.filter((vnode2, index, self) => {
33
+ return self.findIndex((v2) => v2.dom === vnode2.dom) === index;
34
+ });
35
+ for (let i = 0, l = vnodesToUpdateCopy.length; i < l; i++) {
36
+ const vnode2 = vnodesToUpdateCopy[i];
37
+ let newVnode = v(vnode2.tag, vnode2.props, ...vnode2.initialChildren);
38
+ newVnode.dom = vnode2.dom;
39
+ newVnode.isSVG = vnode2.isSVG;
40
+ updateVnode(newVnode, vnode2);
22
41
  }
23
42
  };
24
43
  function get() {
44
+ const { vnode: vnode2 } = current;
45
+ if (vnode2 && vnodesToUpdate.indexOf(vnode2) === -1) {
46
+ if (!vnode2.initialChildren) {
47
+ vnode2.initialChildren = [...vnode2.children];
48
+ }
49
+ vnodesToUpdate.push(vnode2);
50
+ subscribe(updateVnodes);
51
+ }
25
52
  return value;
26
53
  }
27
- get.value = value;
28
- get.toJSON = get.valueOf = get;
29
- get.toString = () => `${value}`;
30
54
  const set = (newValue) => {
55
+ if (current.event) {
56
+ current.event.preventDefault();
57
+ }
58
+ if (newValue === value) {
59
+ return;
60
+ }
31
61
  value = newValue;
32
- get.value = value;
33
- for (let i = 0, l = subscribers.length; i < l; i++) {
34
- subscribers[i](value);
35
- }
36
- if (context.vnode) {
37
- let newVnode = v(context.vnode.tag, context.vnode.props, ...context.vnode.initialChildren);
38
- newVnode.dom = context.vnode.dom;
39
- newVnode.isSVG = context.vnode.isSVG;
40
- context.vnode.subscribers.forEach(
41
- (subscribers2) => subscribers2.length = 0
42
- );
43
- context.vnode.subscribers = [];
44
- return updateVnode(newVnode, context.vnode);
45
- }
46
- return update();
62
+ for (let i = 0, l = subscriptions.length; i < l; i++) {
63
+ subscriptions[i](value);
64
+ }
47
65
  };
48
- let signal = [get, set, subscribe];
49
- if (context.vnode) {
50
- context.vnode.signals.push(signal);
51
- context.vnode.subscribers.push(subscribers);
66
+ let signal = [get, set, subscribe, subscriptions];
67
+ if (vnode) {
68
+ component.signals.push(signal);
52
69
  }
53
70
  return signal;
54
71
  }
@@ -34,35 +34,37 @@ export const createHook = function createHook({
34
34
  returnValue
35
35
  }: HookDefinition): Hook {
36
36
  return (...args: any[]) => {
37
- let { component, vnode, oldVnode } = current as CurrentOnPatch;
37
+ let { component, vnode } = current as CurrentOnPatch;
38
38
 
39
- // Init the components array for the current vnode
40
- if (!vnode.components) {
41
- vnode.components = [];
42
- onUnmount(() => Reflect.deleteProperty(vnode, "components"));
43
- }
39
+ let hook = null;
44
40
 
45
- // Add the component to the components array if it's not already there
46
- if (vnode.components.indexOf(component) === -1) {
47
- vnode.components.push(component);
48
- }
41
+ if (vnode) {
42
+ // Init the components array for the current vnode
43
+ if (!vnode.components) {
44
+ vnode.components = [];
45
+ }
49
46
 
50
- // Init the component hooks array
51
- if (!component.hooks) {
52
- component.hooks = [];
53
- onUnmount(() => Reflect.deleteProperty(component, "hooks"));
54
- }
47
+ if (vnode.components.indexOf(component) === -1) {
48
+ vnode.hook_calls = -1;
49
+ vnode.components.push(component);
50
+ if (!component.hooks) {
51
+ component.hooks = [];
52
+ onUnmount(() => Reflect.deleteProperty(component, "hooks"));
53
+ }
54
+ }
55
55
 
56
- let hook: Hook = undefined;
56
+ hook = component.hooks[++vnode.hook_calls];
57
+ }
57
58
 
58
- // if no old vnode or old vnode has no components or old vnode's last component is not the current component
59
- // we are mounting the component for the first time so we create a new hook
60
- if (!oldVnode || !oldVnode.components || oldVnode.components[vnode.components.length - 1] !== component) {
59
+ // If the hook doesn't exist, create it
60
+ if (!hook) {
61
61
  // create a new hook
62
62
  hook = onCreate(...args);
63
63
 
64
- // add the hook to the component's hooks array
65
- component.hooks.push(hook);
64
+ if (vnode) {
65
+ // Add the hook to the component
66
+ component.hooks.push(hook);
67
+ }
66
68
 
67
69
  // if we have a onRemove hook, add it to the onUnmount set
68
70
  if (onRemove) {
@@ -70,24 +72,6 @@ export const createHook = function createHook({
70
72
  onUnmount(() => onRemove(hook));
71
73
  }
72
74
  } else {
73
- // old vnode has components, we are updating the component
74
-
75
- // Set the calls property to the current component if it's not already set
76
- if ("calls" in component === false) {
77
- component.calls = -1;
78
- onUnmount(() => Reflect.deleteProperty(component, "calls"));
79
- }
80
-
81
- // Reset the calls property to -1 on cleanup so we can detect if the component is updated again
82
- onCleanup(() => (component.calls = -1));
83
-
84
- // Increment the calls property
85
- component.calls++;
86
-
87
- // Get the current hook from the component's hooks array
88
- hook = component.hooks[component.calls];
89
-
90
- // If we have an onUpdate hook, call it
91
75
  if (onUpdateHook) {
92
76
  onUpdateHook(hook, ...args);
93
77
  }
@@ -118,22 +102,27 @@ function delayedUpdate() {
118
102
  // Use state hook
119
103
  export const useState = createHook({
120
104
  onCreate: (value) => {
121
- let stateObj = Object.create(null);
122
- stateObj.value = value;
123
- stateObj.toJSON =
124
- stateObj.toString =
125
- stateObj.valueOf =
126
- () => (typeof stateObj.value === "function" ? stateObj.value() : stateObj.value);
127
-
128
- return [
129
- stateObj,
130
- (value: any) => {
131
- if (stateObj.value !== value) {
132
- stateObj.value = value;
133
- delayedUpdate();
134
- }
105
+ function get() {
106
+ return value;
107
+ }
108
+ get.value = value;
109
+ get.toJSON = get.valueOf = get;
110
+ get.toString = () => `${value}`;
111
+
112
+ function set(newValue) {
113
+ // Prevent default event if it exists
114
+ if (current.event) {
115
+ current.event.preventDefault();
116
+ }
117
+
118
+ if (value !== newValue) {
119
+ value = newValue;
120
+ get.value = newValue;
121
+ delayedUpdate();
135
122
  }
136
- ];
123
+ }
124
+
125
+ return [get, set];
137
126
  }
138
127
  });
139
128
 
package/lib/index.ts CHANGED
@@ -113,6 +113,8 @@ export interface Current {
113
113
  vnode: VnodeWithDom | null;
114
114
  // The old virtual node. It must have a DOM element associated with it.
115
115
  oldVnode?: VnodeWithDom | null;
116
+ // The current event. It can be an event or null.
117
+ event: Event | null;
116
118
  }
117
119
 
118
120
  // The V function is the main function for creating virtual nodes.
@@ -178,7 +180,7 @@ function domToVnode(dom: any): VnodeWithDom {
178
180
  // Set the 'dom' property of the 'Vnode' instance to the child DOM node.
179
181
  // Push the 'Vnode' instance to the 'children' array.
180
182
  if (childDom.nodeType === 3) {
181
- let vnode = new Vnode(textTag, {}, []);
183
+ let vnode = new Vnode(textTag, {}, [childDom.nodeValue]);
182
184
  vnode.dom = childDom;
183
185
  children.push(vnode as VnodeWithDom);
184
186
  continue;
@@ -233,7 +235,8 @@ let isMounted = false;
233
235
  export const current: Current = {
234
236
  vnode: null,
235
237
  oldVnode: null,
236
- component: null
238
+ component: null,
239
+ event: null
237
240
  };
238
241
 
239
242
  /* Reserved props ----------------------------------------------------------- */
@@ -302,6 +305,9 @@ const eventListenerNames: Record<string, true> = {};
302
305
 
303
306
  // This function is called when an event occurs
304
307
  function eventListener(e: Event) {
308
+ // Set the current event to the event that occurred so that it can be prevented if necessary
309
+ current.event = e;
310
+
305
311
  // Convert the target of the event to a DOM element
306
312
  let dom = e.target as DomElement;
307
313
 
@@ -323,6 +329,8 @@ function eventListener(e: Event) {
323
329
  }
324
330
  dom = dom.parentNode as DomElement;
325
331
  }
332
+
333
+ current.event = null;
326
334
  }
327
335
 
328
336
  /* Directives --------------------------------------------------------------- */
@@ -574,15 +582,12 @@ function sharedSetAttribute(name: string, value: any, newVnode: VnodeWithDom, ol
574
582
  // If the attribute value is a function, add an event listener for the attribute
575
583
  // name to the DOM element represented by mainVnode.
576
584
  if (typeof value === "function") {
577
- // We change the name of the event to lowercase to avoid issues with case sensitivity.
578
- // Ex "onClick" and "onclick" are the same event.
579
- let lowercaseName = name.toLowerCase();
580
585
  // Only add the event listener if it hasn't been added yet.
581
- if (lowercaseName in eventListenerNames === false) {
582
- (mainVnode as VnodeWithDom).dom.addEventListener(lowercaseName.slice(2), eventListener);
583
- eventListenerNames[lowercaseName] = true;
586
+ if (name in eventListenerNames === false) {
587
+ (mainVnode as VnodeWithDom).dom.addEventListener(name.slice(2), eventListener);
588
+ eventListenerNames[name] = true;
584
589
  }
585
- newVnode.dom[`v-${lowercaseName}`] = value;
590
+ newVnode.dom[`v-${name}`] = value;
586
591
  return;
587
592
  }
588
593
 
@@ -660,6 +665,12 @@ export function updateAttributes(newVnode: VnodeWithDom, oldVnode?: VnodeWithDom
660
665
 
661
666
  // Patch a DOM node with a new VNode tree
662
667
  export function patch(newVnode: VnodeWithDom, oldVnode?: VnodeWithDom): void {
668
+ // If the new tree has no children, set the text content of the parent DOM element to an empty string
669
+ if (newVnode.children.length === 0) {
670
+ newVnode.dom.textContent = "";
671
+ return;
672
+ }
673
+
663
674
  // Get the children of the new and old virtual DOM nodes
664
675
  let newTree = newVnode.children;
665
676
  let oldTree = oldVnode?.children || [];
@@ -751,24 +762,22 @@ export function patch(newVnode: VnodeWithDom, oldVnode?: VnodeWithDom): void {
751
762
  let newChild = newTree[i];
752
763
 
753
764
  // If the new child is a Vnode and is not a text node
754
- if (newChild instanceof Vnode && newChild.tag !== textTag) {
755
- // If the new child tag is a string just continue the loop
756
- if (typeof newChild.tag === "string") {
757
- continue;
765
+ if (newChild instanceof Vnode) {
766
+ // If the tag of the new child is not a string, it is a component
767
+ if (typeof newChild.tag !== "string") {
768
+ // Set the current component to the tag of the new child
769
+ current.component = newChild.tag;
770
+ // Replace the new child with the result of calling its view or bind method, passing in the props and children as arguments
771
+ newTree.splice(
772
+ i--,
773
+ 1,
774
+ ("view" in newChild.tag ? newChild.tag.view.bind(newChild.tag) : newChild.tag.bind(newChild.tag))(
775
+ newChild.props,
776
+ ...newChild.children
777
+ )
778
+ );
758
779
  }
759
780
 
760
- // If the tag of the new child is not a string, it is a component
761
- // Set the current component to the tag of the new child
762
- current.component = newChild.tag;
763
- // Replace the new child with the result of calling its view or bind method, passing in the props and children as arguments
764
- newTree.splice(
765
- i--,
766
- 1,
767
- ("view" in newChild.tag ? newChild.tag.view.bind(newChild.tag) : newChild.tag.bind(newChild.tag))(
768
- newChild.props,
769
- ...newChild.children
770
- )
771
- );
772
781
  continue;
773
782
  }
774
783
 
@@ -785,38 +794,28 @@ export function patch(newVnode: VnodeWithDom, oldVnode?: VnodeWithDom): void {
785
794
  }
786
795
 
787
796
  // If the new child is a Vnode, set the text of the Vnode to the text content of its dom property
788
- if (newChild instanceof Vnode) {
789
- // Set the new child to the text content of its dom property
790
- newChild.children[0] = (newChild as VnodeWithDom).dom.textContent;
791
- continue;
792
- }
793
-
794
- // If the new child is not a Vnode, wrap it in a text Vnode
795
- newChild = newTree[i] = new Vnode(textTag, {}, [newChild]);
797
+ newTree[i] = new Vnode(textTag, {}, [newChild]);
796
798
  }
797
799
 
798
800
  // Patch the the old tree
799
801
  for (let i = 0; i < newTree.length; i++) {
800
802
  let newChild = newTree[i];
801
803
 
802
- // If the new child is a text vnode
803
804
  if (newChild.tag === textTag) {
805
+ // If no old child exists at the same index
806
+ if (i >= oldTreeLength) {
807
+ // Create a new text node for the new child
808
+ newChild.dom = document.createTextNode(newChild.children[0]);
809
+ // Append the new text node to the dom
810
+ newVnode.dom.appendChild(newChild.dom);
811
+ continue;
812
+ }
813
+
804
814
  // If there is an old child at the same index
805
- if (i < oldTreeLength) {
806
- let oldChild = oldTree[i];
807
-
808
- // If the old child is a text node
809
- if (oldChild.tag === textTag) {
810
- // Set the dom property of the text Vnode to the dom property of the old child
811
- newChild.dom = oldChild.dom;
812
- // If the text content of the old child is different from the new child, update the text content of the old child
813
- // eslint-disable-next-line eqeqeq
814
- if (newChild.children[0] != oldChild.dom.textContent) {
815
- oldChild.dom.textContent = newChild.children[0];
816
- }
817
- continue;
818
- }
815
+ let oldChild = oldTree[i];
819
816
 
817
+ // If the old child is not a text node
818
+ if (oldChild.tag !== textTag) {
820
819
  // Create a new text node for the new child
821
820
  newChild.dom = document.createTextNode(newChild.children[0]);
822
821
  // Replace the old child in the dom with the new text node
@@ -824,10 +823,14 @@ export function patch(newVnode: VnodeWithDom, oldVnode?: VnodeWithDom): void {
824
823
  continue;
825
824
  }
826
825
 
827
- // Create a new text node for the new child
828
- newChild.dom = document.createTextNode(newChild.children[0]);
829
- // Append the new text node to the dom
830
- newVnode.dom.appendChild(newChild.dom);
826
+ // If the old child is a text node
827
+ // Set the dom property of the text Vnode to the dom property of the old child
828
+ newChild.dom = oldChild.dom;
829
+ // If the text content of the old child is different from the new child, update the text content of the old child
830
+ // eslint-disable-next-line eqeqeq
831
+ if (newChild.children[0] != oldChild.dom.textContent) {
832
+ oldChild.dom.textContent = newChild.children[0];
833
+ }
831
834
  continue;
832
835
  }
833
836
 
@@ -835,26 +838,24 @@ export function patch(newVnode: VnodeWithDom, oldVnode?: VnodeWithDom): void {
835
838
  // Set the isSVG flag for the new child if it is an SVG element or if the parent is an SVG element
836
839
  newChild.isSVG = newVnode.isSVG || newChild.tag === "svg";
837
840
 
838
- // If there is an old child at the same index
839
- if (i < oldTreeLength) {
840
- let oldChild = oldTree[i];
841
- // If the tag of the new child is the same as the tag of the old child
842
- if (newChild.tag === oldChild.tag) {
843
- // Set the dom property of the new child to the dom property of the old child
844
- newChild.dom = oldChild.dom;
845
- // If the v-keep prop is the same for both the new and old child, set the children of the new child to the children of the old child
846
- if ("v-keep" in newChild.props && newChild.props["v-keep"] === oldChild.props["v-keep"]) {
847
- newChild.children = oldChild.children;
848
- continue;
849
- }
841
+ // If there is no old child at the same index
842
+ if (i >= oldTreeLength) {
843
+ // Create a new dom element for the new child
844
+ newChild.dom = createDomElement(newChild.tag as string, newChild.isSVG);
845
+ // Update the attributes of the new child
846
+ updateAttributes(newChild as VnodeWithDom);
847
+ // Append the new child to the dom
848
+ newVnode.dom.appendChild(newChild.dom);
849
+ // Recursively patch the new child
850
+ patch(newChild as VnodeWithDom);
851
+ continue;
852
+ }
850
853
 
851
- // Update the attributes of the new child based on the old child
852
- updateAttributes(newChild as VnodeWithDom, oldChild);
853
- // Recursively patch the new and old children
854
- patch(newChild as VnodeWithDom, oldChild);
855
- continue;
856
- }
854
+ // If there is an old child at the same index
855
+ let oldChild = oldTree[i];
857
856
 
857
+ // If the tag of the new child is different from the tag of the old child
858
+ if (newChild.tag !== oldChild.tag) {
858
859
  // Create a new dom element for the new child
859
860
  newChild.dom = createDomElement(newChild.tag as string, newChild.isSVG);
860
861
  // Update the attributes of the new child
@@ -866,14 +867,19 @@ export function patch(newVnode: VnodeWithDom, oldVnode?: VnodeWithDom): void {
866
867
  continue;
867
868
  }
868
869
 
869
- // Create a new dom element for the new child
870
- newChild.dom = createDomElement(newChild.tag as string, newChild.isSVG);
871
- // Update the attributes of the new child
872
- updateAttributes(newChild as VnodeWithDom);
873
- // Append the new child to the dom
874
- newVnode.dom.appendChild(newChild.dom);
875
- // Recursively patch the new child
876
- patch(newChild as VnodeWithDom);
870
+ // If the tag of the new child is the same as the tag of the old child
871
+ // Set the dom property of the new child to the dom property of the old child
872
+ newChild.dom = oldChild.dom;
873
+ // If the v-keep prop is the same for both the new and old child, set the children of the new child to the children of the old child
874
+ if ("v-keep" in newChild.props && newChild.props["v-keep"] === oldChild.props["v-keep"]) {
875
+ newChild.children = oldChild.children;
876
+ continue;
877
+ }
878
+
879
+ // Update the attributes of the new child based on the old child
880
+ updateAttributes(newChild as VnodeWithDom, oldChild);
881
+ // Recursively patch the new and old children
882
+ patch(newChild as VnodeWithDom, oldChild);
877
883
  }
878
884
 
879
885
  // Remove any old children that are no longer present in the new tree
@@ -929,10 +935,13 @@ export function updateVnode(vnode: VnodeWithDom, oldVnode: VnodeWithDom): string
929
935
  // Recursively patch the new and old main Vnodes
930
936
  patch(vnode, oldVnode);
931
937
 
932
- // Set the vnode properties to the old vnode
938
+ // Set the oldVnode's tag, props, children, dom, and isSVG properties to the newVnode's tag, props, children, dom, and isSVG properties
939
+ // This is necessary to allow for the oldVnode to be used as the newVnode in the next update with the normal update function
933
940
  oldVnode.tag = vnode.tag;
934
941
  oldVnode.props = { ...vnode.props };
935
942
  oldVnode.children = [...vnode.children];
943
+ oldVnode.dom = vnode.dom;
944
+ oldVnode.isSVG = vnode.isSVG;
936
945
 
937
946
  // Call any update or mount functions that are registered with the onUpdateSet or onMountSet set
938
947
  callSet(isMounted ? onUpdateSet : onMountSet);
package/lib/interfaces.ts CHANGED
@@ -63,6 +63,7 @@ declare module "valyrian.js" {
63
63
  component: Component | POJOComponent | null;
64
64
  vnode: VnodeWithDom | null;
65
65
  oldVnode?: VnodeWithDom | null;
66
+ event: Event | null;
66
67
  }
67
68
  export interface V {
68
69
  (tagOrComponent: string | Component | POJOComponent, props: Props | null, ...children: Children):