vaderjs 2.3.13 → 2.3.14

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/index.ts +59 -48
  2. package/package.json +1 -1
package/index.ts CHANGED
@@ -174,12 +174,10 @@ function isSvgElement(fiber: Fiber): boolean {
174
174
  * @param {object} prevProps - The previous properties.
175
175
  * @param {object} nextProps - The new properties.
176
176
  */
177
- function updateDom(dom: Node, prevProps: any, nextProps: any): void {
177
+ function updateDom(dom: Node, prevProps: any, nextProps: any, isSvg: boolean = false): void {
178
178
  prevProps = prevProps || {};
179
179
  nextProps = nextProps || {};
180
180
 
181
- const isSvg = dom instanceof SVGElement;
182
-
183
181
  if (dom.nodeType === Node.TEXT_NODE) {
184
182
  if (prevProps.nodeValue !== nextProps.nodeValue) {
185
183
  (dom as Text).nodeValue = nextProps.nodeValue;
@@ -187,7 +185,7 @@ function updateDom(dom: Node, prevProps: any, nextProps: any): void {
187
185
  return;
188
186
  }
189
187
 
190
- // Handle ref updates - IMPORTANT: This must come BEFORE event listeners
188
+ // Handle ref updates
191
189
  if (prevProps.ref && prevProps.ref !== nextProps.ref) {
192
190
  if (prevProps.ref.current === dom) {
193
191
  prevProps.ref.current = null;
@@ -197,7 +195,7 @@ function updateDom(dom: Node, prevProps: any, nextProps: any): void {
197
195
  nextProps.ref.current = dom;
198
196
  }
199
197
 
200
- // Remove old event listeners
198
+ // Remove old event listeners
201
199
  Object.keys(prevProps)
202
200
  .filter(key => key.startsWith("on"))
203
201
  .filter(key => !(key in nextProps) || isNew(prevProps, nextProps)(key))
@@ -209,13 +207,14 @@ function updateDom(dom: Node, prevProps: any, nextProps: any): void {
209
207
  }
210
208
  });
211
209
 
210
+ // ✅ FIX: Handle className updates properly
212
211
  // Remove old properties
213
212
  Object.keys(prevProps)
214
213
  .filter(isProperty)
215
214
  .filter(isGone(prevProps, nextProps))
216
215
  .forEach(name => {
217
216
  if (name === 'className' || name === 'class') {
218
- (dom as Element).removeAttribute('class');
217
+ (dom as Element).setAttribute('class', '');
219
218
  } else if (name === 'style') {
220
219
  (dom as HTMLElement).style.cssText = '';
221
220
  } else if (name in dom && !isSvg) {
@@ -225,7 +224,7 @@ function updateDom(dom: Node, prevProps: any, nextProps: any): void {
225
224
  }
226
225
  });
227
226
 
228
- // Set new or changed properties
227
+ // ✅ FIX: Set new or changed properties - IMPORTANT FIX for className
229
228
  Object.keys(nextProps)
230
229
  .filter(isProperty)
231
230
  .filter(isNew(prevProps, nextProps))
@@ -236,13 +235,18 @@ function updateDom(dom: Node, prevProps: any, nextProps: any): void {
236
235
  if (typeof value === 'string') {
237
236
  (dom as HTMLElement).style.cssText = value;
238
237
  } else if (typeof value === 'object' && value !== null) {
239
- for (const [key, val] of Object.entries(value)) {
238
+ Object.entries(value).forEach(([key, val]) => {
240
239
  const cssKey = key.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`);
241
240
  (dom as HTMLElement).style[cssKey as any] = val;
242
- }
241
+ });
243
242
  }
244
243
  } else if (name === 'className' || name === 'class') {
245
- (dom as Element).setAttribute('class', value);
244
+ // FIX: Set the entire className, don't append!
245
+ if (value) {
246
+ (dom as Element).setAttribute('class', value);
247
+ } else {
248
+ (dom as Element).removeAttribute('class');
249
+ }
246
250
  } else if (typeof value === 'boolean') {
247
251
  if (value) {
248
252
  (dom as Element).setAttribute(name, '');
@@ -262,7 +266,7 @@ function updateDom(dom: Node, prevProps: any, nextProps: any): void {
262
266
  }
263
267
  });
264
268
 
265
- // Add new event listeners - This is the crucial part!
269
+ // Add new event listeners
266
270
  Object.keys(nextProps)
267
271
  .filter(key => key.startsWith("on"))
268
272
  .filter(isNew(prevProps, nextProps))
@@ -533,21 +537,26 @@ function normalizeChildren(children: any, parentFiber: Fiber): VNode[] {
533
537
  if (!children) return [];
534
538
 
535
539
  // Handle arrays, single elements, and conditional rendering
536
- let arr = Array.isArray(children) ? children : [children];
540
+ let arr = Array.isArray(children) ? children.flat() : [children];
537
541
 
538
- return arr.flatMap((child, index) => {
539
- // Skip null, undefined, false, true (conditional rendering)
540
- if (child == null || typeof child === "boolean") {
541
- return [];
542
- }
543
-
542
+ return arr.filter(child => child != null && typeof child !== "boolean").map((child, index) => {
544
543
  if (typeof child === "string" || typeof child === "number") {
545
- return [createTextElement(String(child))];
544
+ return createTextElement(String(child));
546
545
  }
547
546
 
548
- // Ensure every child has a stable key
549
- const key = child.key ?? child.props?.id ?? `${parentFiber.key ?? "root"}-${index}`;
550
- return [{ ...child, key }];
547
+ // FIX: Preserve existing key or create a stable one
548
+ if (typeof child === "object") {
549
+ // If child already has a key, keep it
550
+ if (child.key != null) {
551
+ return child;
552
+ }
553
+
554
+ // Otherwise create a stable key
555
+ const key = `${parentFiber.key || "root"}-${child.type?.name || child.type || "child"}-${index}`;
556
+ return { ...child, key };
557
+ }
558
+
559
+ return child;
551
560
  });
552
561
  }
553
562
  /**
@@ -556,9 +565,11 @@ function normalizeChildren(children: any, parentFiber: Fiber): VNode[] {
556
565
  */
557
566
  function updateHostComponent(fiber: Fiber): void {
558
567
  if (!fiber.dom) fiber.dom = createDom(fiber);
559
-
560
- const children = normalizeChildren(fiber.props.children, fiber);
568
+ if(fiber?.props?.children)
569
+ {
570
+ const children = normalizeChildren(fiber.props.children, fiber);
561
571
  reconcileChildren(fiber, children);
572
+ }
562
573
  }
563
574
 
564
575
  /**
@@ -571,19 +582,18 @@ function reconcileChildren(wipFiber: Fiber, elements: VNode[]) {
571
582
  let oldFiber = wipFiber.alternate?.child;
572
583
  let prevSibling: Fiber | null = null;
573
584
 
574
- // Build a map of existing fibers by key
585
+ // ✅ FIX: Build a map of existing fibers by key
575
586
  const existingFibers = new Map<string | number | null, Fiber>();
576
- while (oldFiber) {
577
- const key = oldFiber.key ?? `index-${index}`;
578
- existingFibers.set(key, oldFiber);
579
- oldFiber = oldFiber.sibling;
580
- index++;
587
+ let tempOldFiber = oldFiber;
588
+ let tempIndex = 0;
589
+ while (tempOldFiber) {
590
+ const key = tempOldFiber.key ?? `index-${tempIndex}`;
591
+ existingFibers.set(key, tempOldFiber);
592
+ tempOldFiber = tempOldFiber.sibling;
593
+ tempIndex++;
581
594
  }
582
595
 
583
- index = 0;
584
- let newChildFiber: Fiber | null = null;
585
-
586
- // Process each element
596
+ // FIX: Process each element in order
587
597
  for (let i = 0; i < elements.length; i++) {
588
598
  const element = elements[i];
589
599
 
@@ -592,13 +602,16 @@ function reconcileChildren(wipFiber: Fiber, elements: VNode[]) {
592
602
  continue;
593
603
  }
594
604
 
605
+ // ✅ FIX: Use the same key logic as when building the map
595
606
  const key = element.key ?? `index-${index}`;
596
607
  const oldFiber = existingFibers.get(key);
597
608
 
598
609
  const sameType = oldFiber && element.type === oldFiber.type;
599
610
 
611
+ let newChildFiber: Fiber | null = null;
612
+
600
613
  if (sameType) {
601
- // Update existing fiber
614
+ // ✅ FIX: Update existing fiber
602
615
  newChildFiber = {
603
616
  type: oldFiber.type,
604
617
  props: element.props,
@@ -614,18 +627,16 @@ function reconcileChildren(wipFiber: Fiber, elements: VNode[]) {
614
627
  existingFibers.delete(key);
615
628
  } else {
616
629
  // Create new fiber
617
- if (element) {
618
- newChildFiber = {
619
- type: element.type,
620
- props: element.props,
621
- dom: null,
622
- parent: wipFiber,
623
- alternate: null,
624
- effectTag: "PLACEMENT",
625
- key,
626
- ref: element.ref,
627
- };
628
- }
630
+ newChildFiber = {
631
+ type: element.type,
632
+ props: element.props,
633
+ dom: null,
634
+ parent: wipFiber,
635
+ alternate: null,
636
+ effectTag: "PLACEMENT",
637
+ key,
638
+ ref: element.ref,
639
+ };
629
640
 
630
641
  // Mark old fiber for deletion if it exists
631
642
  if (oldFiber) {
@@ -646,7 +657,7 @@ function reconcileChildren(wipFiber: Fiber, elements: VNode[]) {
646
657
  }
647
658
  }
648
659
 
649
- // Mark any remaining old fibers for deletion
660
+ // ✅ FIX: Mark any remaining old fibers for deletion
650
661
  existingFibers.forEach(fiber => {
651
662
  fiber.effectTag = "DELETION";
652
663
  deletions.push(fiber);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vaderjs",
3
- "version": "2.3.13",
3
+ "version": "2.3.14",
4
4
  "description": "A simple and powerful JavaScript library for building modern web applications.",
5
5
  "bin": {
6
6
  "vaderjs": "./main.js"