@ktjs/core 0.17.0 → 0.17.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.d.ts +1 -2
- package/dist/index.iife.js +142 -29
- package/dist/index.legacy.js +142 -29
- package/dist/index.mjs +142 -29
- package/dist/jsx/index.d.ts +1 -1
- package/dist/jsx/index.mjs +1 -1
- package/dist/jsx/jsx-runtime.d.ts +1 -1
- package/dist/jsx/jsx-runtime.mjs +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -171,7 +171,7 @@ type HTML<T extends (HTMLTag | SVGTag) & otherstring> = T extends SVGTag ? SVGEl
|
|
|
171
171
|
* ## About
|
|
172
172
|
* @package @ktjs/core
|
|
173
173
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
174
|
-
* @version 0.17.
|
|
174
|
+
* @version 0.17.2 (Last Update: 2026.01.28 15:54:29.326)
|
|
175
175
|
* @license MIT
|
|
176
176
|
* @link https://github.com/baendlorel/kt.js
|
|
177
177
|
* @link https://baendlorel.github.io/ Welcome to my site!
|
|
@@ -246,7 +246,6 @@ declare function KTAsync<T extends KTComponent>(props: {
|
|
|
246
246
|
} & ExtractComponentProps<T>): KTHTMLElement;
|
|
247
247
|
|
|
248
248
|
type KForElement = KTHTMLElement & {
|
|
249
|
-
__kt_for_list__: HTMLElement[];
|
|
250
249
|
redraw: (newProps?: KTAttribute) => void;
|
|
251
250
|
};
|
|
252
251
|
interface KTForProps<T> {
|
package/dist/index.iife.js
CHANGED
|
@@ -211,7 +211,7 @@ var __ktjs_core__ = (function (exports) {
|
|
|
211
211
|
* ## About
|
|
212
212
|
* @package @ktjs/core
|
|
213
213
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
214
|
-
* @version 0.17.
|
|
214
|
+
* @version 0.17.2 (Last Update: 2026.01.28 15:54:29.326)
|
|
215
215
|
* @license MIT
|
|
216
216
|
* @link https://github.com/baendlorel/kt.js
|
|
217
217
|
* @link https://baendlorel.github.io/ Welcome to my site!
|
|
@@ -422,6 +422,7 @@ var __ktjs_core__ = (function (exports) {
|
|
|
422
422
|
if (!parent) {
|
|
423
423
|
// If not in DOM yet, just rebuild the list
|
|
424
424
|
const newElements = [];
|
|
425
|
+
nodeMap.clear();
|
|
425
426
|
for (let index = 0; index < currentList.length; index++) {
|
|
426
427
|
const item = currentList[index];
|
|
427
428
|
const itemKey = currentKey(item, index, currentList);
|
|
@@ -432,46 +433,116 @@ var __ktjs_core__ = (function (exports) {
|
|
|
432
433
|
anchor.__kt_for_list__ = newElements;
|
|
433
434
|
return anchor;
|
|
434
435
|
}
|
|
435
|
-
|
|
436
|
-
const
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
436
|
+
const oldLength = anchor.__kt_for_list__.length;
|
|
437
|
+
const newLength = newList.length;
|
|
438
|
+
// Fast path: empty list
|
|
439
|
+
if (newLength === 0) {
|
|
440
|
+
nodeMap.forEach((node) => node.remove());
|
|
441
|
+
nodeMap.clear();
|
|
442
|
+
anchor.__kt_for_list__ = [];
|
|
443
|
+
return anchor;
|
|
444
|
+
}
|
|
445
|
+
// Fast path: all new items
|
|
446
|
+
if (oldLength === 0) {
|
|
447
|
+
const newElements = [];
|
|
448
|
+
const fragment = document.createDocumentFragment();
|
|
449
|
+
for (let i = 0; i < newLength; i++) {
|
|
450
|
+
const item = newList[i];
|
|
451
|
+
const itemKey = newKey(item, i, newList);
|
|
452
|
+
const node = newMap(item, i, newList);
|
|
453
|
+
nodeMap.set(itemKey, node);
|
|
454
|
+
newElements.push(node);
|
|
455
|
+
fragment.appendChild(node);
|
|
456
|
+
}
|
|
457
|
+
parent.insertBefore(fragment, anchor.nextSibling);
|
|
458
|
+
anchor.__kt_for_list__ = newElements;
|
|
459
|
+
return anchor;
|
|
460
|
+
}
|
|
461
|
+
// Build key index map and new elements array in one pass
|
|
462
|
+
const newKeyToNewIndex = new Map();
|
|
463
|
+
const newElements = new Array(newLength);
|
|
464
|
+
let maxNewIndexSoFar = 0;
|
|
465
|
+
let moved = false;
|
|
466
|
+
for (let i = 0; i < newLength; i++) {
|
|
467
|
+
const item = newList[i];
|
|
468
|
+
const itemKey = newKey(item, i, newList);
|
|
469
|
+
newKeyToNewIndex.set(itemKey, i);
|
|
444
470
|
if (nodeMap.has(itemKey)) {
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
newElements
|
|
471
|
+
// Reuse existing node
|
|
472
|
+
const node = nodeMap.get(itemKey);
|
|
473
|
+
newElements[i] = node;
|
|
474
|
+
// Track if items moved
|
|
475
|
+
if (i < maxNewIndexSoFar) {
|
|
476
|
+
moved = true;
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
maxNewIndexSoFar = i;
|
|
480
|
+
}
|
|
448
481
|
}
|
|
449
482
|
else {
|
|
450
483
|
// Create new node
|
|
451
|
-
|
|
452
|
-
newNodeMap.set(itemKey, node);
|
|
453
|
-
newElements.push(node);
|
|
484
|
+
newElements[i] = newMap(item, i, newList);
|
|
454
485
|
}
|
|
455
486
|
}
|
|
456
|
-
// Remove nodes
|
|
487
|
+
// Remove nodes not in new list
|
|
488
|
+
const toRemove = [];
|
|
457
489
|
nodeMap.forEach((node, key) => {
|
|
458
|
-
if (!
|
|
459
|
-
|
|
490
|
+
if (!newKeyToNewIndex.has(key)) {
|
|
491
|
+
toRemove.push(node);
|
|
460
492
|
}
|
|
461
493
|
});
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
494
|
+
for (let i = 0; i < toRemove.length; i++) {
|
|
495
|
+
toRemove[i].remove();
|
|
496
|
+
}
|
|
497
|
+
// Update DOM with minimal operations
|
|
498
|
+
if (moved) {
|
|
499
|
+
// Use longest increasing subsequence to minimize moves
|
|
500
|
+
const seq = getSequence(newElements.map((el, i) => (nodeMap.has(newKey(newList[i], i, newList)) ? i : -1)));
|
|
501
|
+
let j = seq.length - 1;
|
|
502
|
+
let anchor = null;
|
|
503
|
+
// Traverse from end to start for stable insertions
|
|
504
|
+
for (let i = newLength - 1; i >= 0; i--) {
|
|
505
|
+
const node = newElements[i];
|
|
506
|
+
if (j < 0 || i !== seq[j]) {
|
|
507
|
+
// Node needs to be moved or inserted
|
|
508
|
+
if (anchor) {
|
|
509
|
+
parent.insertBefore(node, anchor);
|
|
510
|
+
}
|
|
511
|
+
else {
|
|
512
|
+
// Insert at end
|
|
513
|
+
let nextSibling = anchor.nextSibling;
|
|
514
|
+
let temp = nextSibling;
|
|
515
|
+
while (temp && newElements.includes(temp)) {
|
|
516
|
+
temp = temp.nextSibling;
|
|
517
|
+
}
|
|
518
|
+
parent.insertBefore(node, temp);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
else {
|
|
522
|
+
j--;
|
|
523
|
+
}
|
|
524
|
+
anchor = node;
|
|
469
525
|
}
|
|
470
|
-
referenceNode = node.nextSibling;
|
|
471
526
|
}
|
|
472
|
-
|
|
527
|
+
else {
|
|
528
|
+
// No moves needed, just insert new nodes
|
|
529
|
+
let currentNode = anchor.nextSibling;
|
|
530
|
+
for (let i = 0; i < newLength; i++) {
|
|
531
|
+
const node = newElements[i];
|
|
532
|
+
if (currentNode !== node) {
|
|
533
|
+
parent.insertBefore(node, currentNode);
|
|
534
|
+
}
|
|
535
|
+
else {
|
|
536
|
+
currentNode = currentNode.nextSibling;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
// Update maps
|
|
473
541
|
nodeMap.clear();
|
|
474
|
-
|
|
542
|
+
for (let i = 0; i < newLength; i++) {
|
|
543
|
+
const itemKey = newKey(newList[i], i, newList);
|
|
544
|
+
nodeMap.set(itemKey, newElements[i]);
|
|
545
|
+
}
|
|
475
546
|
anchor.__kt_for_list__ = newElements;
|
|
476
547
|
return anchor;
|
|
477
548
|
};
|
|
@@ -481,6 +552,48 @@ var __ktjs_core__ = (function (exports) {
|
|
|
481
552
|
}
|
|
482
553
|
return anchor;
|
|
483
554
|
}
|
|
555
|
+
// Longest Increasing Subsequence algorithm (optimized for diff)
|
|
556
|
+
function getSequence(arr) {
|
|
557
|
+
const p = arr.slice();
|
|
558
|
+
const result = [0];
|
|
559
|
+
let i, j, u, v, c;
|
|
560
|
+
const len = arr.length;
|
|
561
|
+
for (i = 0; i < len; i++) {
|
|
562
|
+
const arrI = arr[i];
|
|
563
|
+
if (arrI === -1)
|
|
564
|
+
continue;
|
|
565
|
+
j = result[result.length - 1];
|
|
566
|
+
if (arr[j] < arrI) {
|
|
567
|
+
p[i] = j;
|
|
568
|
+
result.push(i);
|
|
569
|
+
continue;
|
|
570
|
+
}
|
|
571
|
+
u = 0;
|
|
572
|
+
v = result.length - 1;
|
|
573
|
+
while (u < v) {
|
|
574
|
+
c = ((u + v) / 2) | 0;
|
|
575
|
+
if (arr[result[c]] < arrI) {
|
|
576
|
+
u = c + 1;
|
|
577
|
+
}
|
|
578
|
+
else {
|
|
579
|
+
v = c;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
if (arrI < arr[result[u]]) {
|
|
583
|
+
if (u > 0) {
|
|
584
|
+
p[i] = result[u - 1];
|
|
585
|
+
}
|
|
586
|
+
result[u] = i;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
u = result.length;
|
|
590
|
+
v = result[u - 1];
|
|
591
|
+
while (u-- > 0) {
|
|
592
|
+
result[u] = v;
|
|
593
|
+
v = p[v];
|
|
594
|
+
}
|
|
595
|
+
return result;
|
|
596
|
+
}
|
|
484
597
|
|
|
485
598
|
exports.Fragment = Fragment;
|
|
486
599
|
exports.KTAsync = KTAsync;
|
package/dist/index.legacy.js
CHANGED
|
@@ -236,7 +236,7 @@ var __ktjs_core__ = (function (exports) {
|
|
|
236
236
|
* ## About
|
|
237
237
|
* @package @ktjs/core
|
|
238
238
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
239
|
-
* @version 0.17.
|
|
239
|
+
* @version 0.17.2 (Last Update: 2026.01.28 15:54:29.326)
|
|
240
240
|
* @license MIT
|
|
241
241
|
* @link https://github.com/baendlorel/kt.js
|
|
242
242
|
* @link https://baendlorel.github.io/ Welcome to my site!
|
|
@@ -490,6 +490,7 @@ var __ktjs_core__ = (function (exports) {
|
|
|
490
490
|
if (!parent) {
|
|
491
491
|
// If not in DOM yet, just rebuild the list
|
|
492
492
|
var newElements_1 = [];
|
|
493
|
+
nodeMap.clear();
|
|
493
494
|
for (var index = 0; index < currentList.length; index++) {
|
|
494
495
|
var item = currentList[index];
|
|
495
496
|
var itemKey = currentKey(item, index, currentList);
|
|
@@ -500,46 +501,116 @@ var __ktjs_core__ = (function (exports) {
|
|
|
500
501
|
anchor.__kt_for_list__ = newElements_1;
|
|
501
502
|
return anchor;
|
|
502
503
|
}
|
|
503
|
-
|
|
504
|
-
var
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
504
|
+
var oldLength = anchor.__kt_for_list__.length;
|
|
505
|
+
var newLength = newList.length;
|
|
506
|
+
// Fast path: empty list
|
|
507
|
+
if (newLength === 0) {
|
|
508
|
+
nodeMap.forEach(function (node) { return node.remove(); });
|
|
509
|
+
nodeMap.clear();
|
|
510
|
+
anchor.__kt_for_list__ = [];
|
|
511
|
+
return anchor;
|
|
512
|
+
}
|
|
513
|
+
// Fast path: all new items
|
|
514
|
+
if (oldLength === 0) {
|
|
515
|
+
var newElements_2 = [];
|
|
516
|
+
var fragment = document.createDocumentFragment();
|
|
517
|
+
for (var i = 0; i < newLength; i++) {
|
|
518
|
+
var item = newList[i];
|
|
519
|
+
var itemKey = newKey(item, i, newList);
|
|
520
|
+
var node = newMap(item, i, newList);
|
|
521
|
+
nodeMap.set(itemKey, node);
|
|
522
|
+
newElements_2.push(node);
|
|
523
|
+
fragment.appendChild(node);
|
|
524
|
+
}
|
|
525
|
+
parent.insertBefore(fragment, anchor.nextSibling);
|
|
526
|
+
anchor.__kt_for_list__ = newElements_2;
|
|
527
|
+
return anchor;
|
|
528
|
+
}
|
|
529
|
+
// Build key index map and new elements array in one pass
|
|
530
|
+
var newKeyToNewIndex = new Map();
|
|
531
|
+
var newElements = new Array(newLength);
|
|
532
|
+
var maxNewIndexSoFar = 0;
|
|
533
|
+
var moved = false;
|
|
534
|
+
for (var i = 0; i < newLength; i++) {
|
|
535
|
+
var item = newList[i];
|
|
536
|
+
var itemKey = newKey(item, i, newList);
|
|
537
|
+
newKeyToNewIndex.set(itemKey, i);
|
|
512
538
|
if (nodeMap.has(itemKey)) {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
newElements
|
|
539
|
+
// Reuse existing node
|
|
540
|
+
var node = nodeMap.get(itemKey);
|
|
541
|
+
newElements[i] = node;
|
|
542
|
+
// Track if items moved
|
|
543
|
+
if (i < maxNewIndexSoFar) {
|
|
544
|
+
moved = true;
|
|
545
|
+
}
|
|
546
|
+
else {
|
|
547
|
+
maxNewIndexSoFar = i;
|
|
548
|
+
}
|
|
516
549
|
}
|
|
517
550
|
else {
|
|
518
551
|
// Create new node
|
|
519
|
-
|
|
520
|
-
newNodeMap.set(itemKey, node);
|
|
521
|
-
newElements.push(node);
|
|
552
|
+
newElements[i] = newMap(item, i, newList);
|
|
522
553
|
}
|
|
523
554
|
}
|
|
524
|
-
// Remove nodes
|
|
555
|
+
// Remove nodes not in new list
|
|
556
|
+
var toRemove = [];
|
|
525
557
|
nodeMap.forEach(function (node, key) {
|
|
526
|
-
if (!
|
|
527
|
-
|
|
558
|
+
if (!newKeyToNewIndex.has(key)) {
|
|
559
|
+
toRemove.push(node);
|
|
528
560
|
}
|
|
529
561
|
});
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
562
|
+
for (var i = 0; i < toRemove.length; i++) {
|
|
563
|
+
toRemove[i].remove();
|
|
564
|
+
}
|
|
565
|
+
// Update DOM with minimal operations
|
|
566
|
+
if (moved) {
|
|
567
|
+
// Use longest increasing subsequence to minimize moves
|
|
568
|
+
var seq = getSequence(newElements.map(function (el, i) { return (nodeMap.has(newKey(newList[i], i, newList)) ? i : -1); }));
|
|
569
|
+
var j = seq.length - 1;
|
|
570
|
+
var anchor_1 = null;
|
|
571
|
+
// Traverse from end to start for stable insertions
|
|
572
|
+
for (var i = newLength - 1; i >= 0; i--) {
|
|
573
|
+
var node = newElements[i];
|
|
574
|
+
if (j < 0 || i !== seq[j]) {
|
|
575
|
+
// Node needs to be moved or inserted
|
|
576
|
+
if (anchor_1) {
|
|
577
|
+
parent.insertBefore(node, anchor_1);
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
580
|
+
// Insert at end
|
|
581
|
+
var nextSibling = anchor_1.nextSibling;
|
|
582
|
+
var temp = nextSibling;
|
|
583
|
+
while (temp && newElements.includes(temp)) {
|
|
584
|
+
temp = temp.nextSibling;
|
|
585
|
+
}
|
|
586
|
+
parent.insertBefore(node, temp);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
else {
|
|
590
|
+
j--;
|
|
591
|
+
}
|
|
592
|
+
anchor_1 = node;
|
|
537
593
|
}
|
|
538
|
-
referenceNode = node.nextSibling;
|
|
539
594
|
}
|
|
540
|
-
|
|
595
|
+
else {
|
|
596
|
+
// No moves needed, just insert new nodes
|
|
597
|
+
var currentNode = anchor.nextSibling;
|
|
598
|
+
for (var i = 0; i < newLength; i++) {
|
|
599
|
+
var node = newElements[i];
|
|
600
|
+
if (currentNode !== node) {
|
|
601
|
+
parent.insertBefore(node, currentNode);
|
|
602
|
+
}
|
|
603
|
+
else {
|
|
604
|
+
currentNode = currentNode.nextSibling;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
// Update maps
|
|
541
609
|
nodeMap.clear();
|
|
542
|
-
|
|
610
|
+
for (var i = 0; i < newLength; i++) {
|
|
611
|
+
var itemKey = newKey(newList[i], i, newList);
|
|
612
|
+
nodeMap.set(itemKey, newElements[i]);
|
|
613
|
+
}
|
|
543
614
|
anchor.__kt_for_list__ = newElements;
|
|
544
615
|
return anchor;
|
|
545
616
|
};
|
|
@@ -549,6 +620,48 @@ var __ktjs_core__ = (function (exports) {
|
|
|
549
620
|
}
|
|
550
621
|
return anchor;
|
|
551
622
|
}
|
|
623
|
+
// Longest Increasing Subsequence algorithm (optimized for diff)
|
|
624
|
+
function getSequence(arr) {
|
|
625
|
+
var p = arr.slice();
|
|
626
|
+
var result = [0];
|
|
627
|
+
var i, j, u, v, c;
|
|
628
|
+
var len = arr.length;
|
|
629
|
+
for (i = 0; i < len; i++) {
|
|
630
|
+
var arrI = arr[i];
|
|
631
|
+
if (arrI === -1)
|
|
632
|
+
continue;
|
|
633
|
+
j = result[result.length - 1];
|
|
634
|
+
if (arr[j] < arrI) {
|
|
635
|
+
p[i] = j;
|
|
636
|
+
result.push(i);
|
|
637
|
+
continue;
|
|
638
|
+
}
|
|
639
|
+
u = 0;
|
|
640
|
+
v = result.length - 1;
|
|
641
|
+
while (u < v) {
|
|
642
|
+
c = ((u + v) / 2) | 0;
|
|
643
|
+
if (arr[result[c]] < arrI) {
|
|
644
|
+
u = c + 1;
|
|
645
|
+
}
|
|
646
|
+
else {
|
|
647
|
+
v = c;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
if (arrI < arr[result[u]]) {
|
|
651
|
+
if (u > 0) {
|
|
652
|
+
p[i] = result[u - 1];
|
|
653
|
+
}
|
|
654
|
+
result[u] = i;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
u = result.length;
|
|
658
|
+
v = result[u - 1];
|
|
659
|
+
while (u-- > 0) {
|
|
660
|
+
result[u] = v;
|
|
661
|
+
v = p[v];
|
|
662
|
+
}
|
|
663
|
+
return result;
|
|
664
|
+
}
|
|
552
665
|
|
|
553
666
|
exports.Fragment = Fragment;
|
|
554
667
|
exports.KTAsync = KTAsync;
|
package/dist/index.mjs
CHANGED
|
@@ -208,7 +208,7 @@ let creator = defaultCreator;
|
|
|
208
208
|
* ## About
|
|
209
209
|
* @package @ktjs/core
|
|
210
210
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
211
|
-
* @version 0.17.
|
|
211
|
+
* @version 0.17.2 (Last Update: 2026.01.28 15:54:29.326)
|
|
212
212
|
* @license MIT
|
|
213
213
|
* @link https://github.com/baendlorel/kt.js
|
|
214
214
|
* @link https://baendlorel.github.io/ Welcome to my site!
|
|
@@ -419,6 +419,7 @@ function KTFor(props) {
|
|
|
419
419
|
if (!parent) {
|
|
420
420
|
// If not in DOM yet, just rebuild the list
|
|
421
421
|
const newElements = [];
|
|
422
|
+
nodeMap.clear();
|
|
422
423
|
for (let index = 0; index < currentList.length; index++) {
|
|
423
424
|
const item = currentList[index];
|
|
424
425
|
const itemKey = currentKey(item, index, currentList);
|
|
@@ -429,46 +430,116 @@ function KTFor(props) {
|
|
|
429
430
|
anchor.__kt_for_list__ = newElements;
|
|
430
431
|
return anchor;
|
|
431
432
|
}
|
|
432
|
-
|
|
433
|
-
const
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
433
|
+
const oldLength = anchor.__kt_for_list__.length;
|
|
434
|
+
const newLength = newList.length;
|
|
435
|
+
// Fast path: empty list
|
|
436
|
+
if (newLength === 0) {
|
|
437
|
+
nodeMap.forEach((node) => node.remove());
|
|
438
|
+
nodeMap.clear();
|
|
439
|
+
anchor.__kt_for_list__ = [];
|
|
440
|
+
return anchor;
|
|
441
|
+
}
|
|
442
|
+
// Fast path: all new items
|
|
443
|
+
if (oldLength === 0) {
|
|
444
|
+
const newElements = [];
|
|
445
|
+
const fragment = document.createDocumentFragment();
|
|
446
|
+
for (let i = 0; i < newLength; i++) {
|
|
447
|
+
const item = newList[i];
|
|
448
|
+
const itemKey = newKey(item, i, newList);
|
|
449
|
+
const node = newMap(item, i, newList);
|
|
450
|
+
nodeMap.set(itemKey, node);
|
|
451
|
+
newElements.push(node);
|
|
452
|
+
fragment.appendChild(node);
|
|
453
|
+
}
|
|
454
|
+
parent.insertBefore(fragment, anchor.nextSibling);
|
|
455
|
+
anchor.__kt_for_list__ = newElements;
|
|
456
|
+
return anchor;
|
|
457
|
+
}
|
|
458
|
+
// Build key index map and new elements array in one pass
|
|
459
|
+
const newKeyToNewIndex = new Map();
|
|
460
|
+
const newElements = new Array(newLength);
|
|
461
|
+
let maxNewIndexSoFar = 0;
|
|
462
|
+
let moved = false;
|
|
463
|
+
for (let i = 0; i < newLength; i++) {
|
|
464
|
+
const item = newList[i];
|
|
465
|
+
const itemKey = newKey(item, i, newList);
|
|
466
|
+
newKeyToNewIndex.set(itemKey, i);
|
|
441
467
|
if (nodeMap.has(itemKey)) {
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
newElements
|
|
468
|
+
// Reuse existing node
|
|
469
|
+
const node = nodeMap.get(itemKey);
|
|
470
|
+
newElements[i] = node;
|
|
471
|
+
// Track if items moved
|
|
472
|
+
if (i < maxNewIndexSoFar) {
|
|
473
|
+
moved = true;
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
maxNewIndexSoFar = i;
|
|
477
|
+
}
|
|
445
478
|
}
|
|
446
479
|
else {
|
|
447
480
|
// Create new node
|
|
448
|
-
|
|
449
|
-
newNodeMap.set(itemKey, node);
|
|
450
|
-
newElements.push(node);
|
|
481
|
+
newElements[i] = newMap(item, i, newList);
|
|
451
482
|
}
|
|
452
483
|
}
|
|
453
|
-
// Remove nodes
|
|
484
|
+
// Remove nodes not in new list
|
|
485
|
+
const toRemove = [];
|
|
454
486
|
nodeMap.forEach((node, key) => {
|
|
455
|
-
if (!
|
|
456
|
-
|
|
487
|
+
if (!newKeyToNewIndex.has(key)) {
|
|
488
|
+
toRemove.push(node);
|
|
457
489
|
}
|
|
458
490
|
});
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
491
|
+
for (let i = 0; i < toRemove.length; i++) {
|
|
492
|
+
toRemove[i].remove();
|
|
493
|
+
}
|
|
494
|
+
// Update DOM with minimal operations
|
|
495
|
+
if (moved) {
|
|
496
|
+
// Use longest increasing subsequence to minimize moves
|
|
497
|
+
const seq = getSequence(newElements.map((el, i) => (nodeMap.has(newKey(newList[i], i, newList)) ? i : -1)));
|
|
498
|
+
let j = seq.length - 1;
|
|
499
|
+
let anchor = null;
|
|
500
|
+
// Traverse from end to start for stable insertions
|
|
501
|
+
for (let i = newLength - 1; i >= 0; i--) {
|
|
502
|
+
const node = newElements[i];
|
|
503
|
+
if (j < 0 || i !== seq[j]) {
|
|
504
|
+
// Node needs to be moved or inserted
|
|
505
|
+
if (anchor) {
|
|
506
|
+
parent.insertBefore(node, anchor);
|
|
507
|
+
}
|
|
508
|
+
else {
|
|
509
|
+
// Insert at end
|
|
510
|
+
let nextSibling = anchor.nextSibling;
|
|
511
|
+
let temp = nextSibling;
|
|
512
|
+
while (temp && newElements.includes(temp)) {
|
|
513
|
+
temp = temp.nextSibling;
|
|
514
|
+
}
|
|
515
|
+
parent.insertBefore(node, temp);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
else {
|
|
519
|
+
j--;
|
|
520
|
+
}
|
|
521
|
+
anchor = node;
|
|
466
522
|
}
|
|
467
|
-
referenceNode = node.nextSibling;
|
|
468
523
|
}
|
|
469
|
-
|
|
524
|
+
else {
|
|
525
|
+
// No moves needed, just insert new nodes
|
|
526
|
+
let currentNode = anchor.nextSibling;
|
|
527
|
+
for (let i = 0; i < newLength; i++) {
|
|
528
|
+
const node = newElements[i];
|
|
529
|
+
if (currentNode !== node) {
|
|
530
|
+
parent.insertBefore(node, currentNode);
|
|
531
|
+
}
|
|
532
|
+
else {
|
|
533
|
+
currentNode = currentNode.nextSibling;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
// Update maps
|
|
470
538
|
nodeMap.clear();
|
|
471
|
-
|
|
539
|
+
for (let i = 0; i < newLength; i++) {
|
|
540
|
+
const itemKey = newKey(newList[i], i, newList);
|
|
541
|
+
nodeMap.set(itemKey, newElements[i]);
|
|
542
|
+
}
|
|
472
543
|
anchor.__kt_for_list__ = newElements;
|
|
473
544
|
return anchor;
|
|
474
545
|
};
|
|
@@ -478,5 +549,47 @@ function KTFor(props) {
|
|
|
478
549
|
}
|
|
479
550
|
return anchor;
|
|
480
551
|
}
|
|
552
|
+
// Longest Increasing Subsequence algorithm (optimized for diff)
|
|
553
|
+
function getSequence(arr) {
|
|
554
|
+
const p = arr.slice();
|
|
555
|
+
const result = [0];
|
|
556
|
+
let i, j, u, v, c;
|
|
557
|
+
const len = arr.length;
|
|
558
|
+
for (i = 0; i < len; i++) {
|
|
559
|
+
const arrI = arr[i];
|
|
560
|
+
if (arrI === -1)
|
|
561
|
+
continue;
|
|
562
|
+
j = result[result.length - 1];
|
|
563
|
+
if (arr[j] < arrI) {
|
|
564
|
+
p[i] = j;
|
|
565
|
+
result.push(i);
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
u = 0;
|
|
569
|
+
v = result.length - 1;
|
|
570
|
+
while (u < v) {
|
|
571
|
+
c = ((u + v) / 2) | 0;
|
|
572
|
+
if (arr[result[c]] < arrI) {
|
|
573
|
+
u = c + 1;
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
v = c;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
if (arrI < arr[result[u]]) {
|
|
580
|
+
if (u > 0) {
|
|
581
|
+
p[i] = result[u - 1];
|
|
582
|
+
}
|
|
583
|
+
result[u] = i;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
u = result.length;
|
|
587
|
+
v = result[u - 1];
|
|
588
|
+
while (u-- > 0) {
|
|
589
|
+
result[u] = v;
|
|
590
|
+
v = p[v];
|
|
591
|
+
}
|
|
592
|
+
return result;
|
|
593
|
+
}
|
|
481
594
|
|
|
482
595
|
export { Fragment, KTAsync, KTFor, h as createElement, createRedrawable, createRedrawableNoref, h, jsx, jsxDEV, jsxs, ref };
|
package/dist/jsx/index.d.ts
CHANGED
|
@@ -157,7 +157,7 @@ type HTML<T extends (HTMLTag | SVGTag) & otherstring> = T extends SVGTag ? SVGEl
|
|
|
157
157
|
* ## About
|
|
158
158
|
* @package @ktjs/core
|
|
159
159
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
160
|
-
* @version 0.17.
|
|
160
|
+
* @version 0.17.2 (Last Update: 2026.01.28 15:54:29.326)
|
|
161
161
|
* @license MIT
|
|
162
162
|
* @link https://github.com/baendlorel/kt.js
|
|
163
163
|
* @link https://baendlorel.github.io/ Welcome to my site!
|
package/dist/jsx/index.mjs
CHANGED
|
@@ -208,7 +208,7 @@ let creator = defaultCreator;
|
|
|
208
208
|
* ## About
|
|
209
209
|
* @package @ktjs/core
|
|
210
210
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
211
|
-
* @version 0.17.
|
|
211
|
+
* @version 0.17.2 (Last Update: 2026.01.28 15:54:29.326)
|
|
212
212
|
* @license MIT
|
|
213
213
|
* @link https://github.com/baendlorel/kt.js
|
|
214
214
|
* @link https://baendlorel.github.io/ Welcome to my site!
|
|
@@ -151,7 +151,7 @@ type HTML<T extends (HTMLTag | SVGTag) & otherstring> = T extends SVGTag ? SVGEl
|
|
|
151
151
|
* ## About
|
|
152
152
|
* @package @ktjs/core
|
|
153
153
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
154
|
-
* @version 0.17.
|
|
154
|
+
* @version 0.17.2 (Last Update: 2026.01.28 15:54:29.326)
|
|
155
155
|
* @license MIT
|
|
156
156
|
* @link https://github.com/baendlorel/kt.js
|
|
157
157
|
* @link https://baendlorel.github.io/ Welcome to my site!
|
package/dist/jsx/jsx-runtime.mjs
CHANGED
|
@@ -208,7 +208,7 @@ let creator = defaultCreator;
|
|
|
208
208
|
* ## About
|
|
209
209
|
* @package @ktjs/core
|
|
210
210
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
211
|
-
* @version 0.17.
|
|
211
|
+
* @version 0.17.2 (Last Update: 2026.01.28 15:54:29.326)
|
|
212
212
|
* @license MIT
|
|
213
213
|
* @link https://github.com/baendlorel/kt.js
|
|
214
214
|
* @link https://baendlorel.github.io/ Welcome to my site!
|