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.
- package/index.ts +59 -48
- 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
|
|
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
|
-
//
|
|
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).
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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.
|
|
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
|
|
544
|
+
return createTextElement(String(child));
|
|
546
545
|
}
|
|
547
546
|
|
|
548
|
-
//
|
|
549
|
-
|
|
550
|
-
|
|
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
|
-
|
|
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
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
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
|
-
|
|
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
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
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);
|