@ktjs/core 0.26.9 → 0.27.1

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.
@@ -1,6 +1,42 @@
1
1
  var __ktjs_core__ = (function (exports) {
2
2
  'use strict';
3
3
 
4
+ // Cached native methods for performance optimization
5
+ const $isArray = Array.isArray;
6
+ const $is = Object.is;
7
+ const $entries = Object.entries;
8
+ const $random = Math.random;
9
+ const $isThenable = (o) => typeof o?.then === 'function';
10
+
11
+ if (typeof Symbol === 'undefined') {
12
+ window.Symbol = function Symbol(description) {
13
+ return `@@SYMBOL_${description || ''}_${$random().toString(36).slice(2)}`;
14
+ };
15
+ }
16
+
17
+ // String manipulation utilities
18
+ /**
19
+ * Default empty function
20
+ */
21
+ const $emptyFn = (() => true);
22
+ const $emptyArray = [];
23
+ /**
24
+ * Safe and quick forEach implementation that works with array-like objects and handles sparse arrays.
25
+ */
26
+ const $forEach = (array, callback) => {
27
+ const len = array.length;
28
+ for (let i = 0; i < len; i++) {
29
+ callback(array[i], i, array);
30
+ }
31
+ };
32
+
33
+ const $emptyChildrenRef = { value: $emptyArray };
34
+ // each instance shares the same empty array, but it will be replaced when used
35
+ Comment.prototype.kisFragmentAnchor = false;
36
+ Comment.prototype.kFragmentList = $emptyArray;
37
+ Comment.prototype.kredraw = $emptyFn;
38
+ Comment.prototype.kchildrenRef = $emptyChildrenRef;
39
+
4
40
  // Shared constants
5
41
  // Empty for now - can be extended with framework-wide constants
6
42
  /**
@@ -12,13 +48,6 @@ var __ktjs_core__ = (function (exports) {
12
48
  */
13
49
  const MATHML_ATTR_FLAG = '__kt_mathml__';
14
50
 
15
- // Cached native methods for performance optimization
16
- const $isArray = Array.isArray;
17
- const $is = Object.is;
18
- const $entries = Object.entries;
19
- const $random = Math.random;
20
- const $isThenable = (o) => typeof o?.then === 'function';
21
-
22
51
  // DOM manipulation utilities
23
52
  // # dom natives
24
53
  const $isNode = (x) => x?.nodeType > 0;
@@ -72,26 +101,14 @@ var __ktjs_core__ = (function (exports) {
72
101
  /**
73
102
  * Used for `k-model`
74
103
  */
75
- const applyModel = (element, valueRef, propName, eventName) => {
104
+ const $applyModel = (element, valueRef, propName, eventName) => {
76
105
  element[propName] = valueRef.value; // initialize
77
106
  valueRef.addOnChange((newValue) => (element[propName] = newValue));
78
107
  element.addEventListener(eventName, () => (valueRef.value = element[propName]));
79
108
  };
80
109
 
81
- // String manipulation utilities
82
- /**
83
- * Default empty function
84
- */
85
- const $emptyFn = (() => true);
86
-
87
- if (typeof Symbol === 'undefined') {
88
- window.Symbol = function Symbol(description) {
89
- return `@@SYMBOL_${description || ''}_${$random().toString(36).slice(2)}`;
90
- };
91
- }
92
-
93
- // Shared utilities and cached native methods for kt.js framework
94
- Object.defineProperty(window, '__ktjs__', { value: '0.23.3' });
110
+ // incase that symbol is not supported
111
+ Object.defineProperty(window, '__ktjs__', { value: '0.23.10' });
95
112
 
96
113
  var isKT = function (obj) { return obj === null || obj === void 0 ? void 0 : obj.isKT; };
97
114
  var isRef = function (obj) { return (obj === null || obj === void 0 ? void 0 : obj.ktType) === 1 /* KTReactiveType.REF */; };
@@ -252,6 +269,7 @@ var __ktjs_core__ = (function (exports) {
252
269
  else {
253
270
  $append.call(element, c);
254
271
  // Handle KTFor anchor
272
+ // todo Maybe not needed anymore
255
273
  var list = c.__kt_for_list__;
256
274
  if ($isArray(list)) {
257
275
  apd(element, list);
@@ -410,13 +428,26 @@ var __ktjs_core__ = (function (exports) {
410
428
  // & props is an object. Won't use it in any other place
411
429
  if ('k-model' in props) {
412
430
  var kmodel = props['k-model'];
413
- if (!(kmodel === null || kmodel === void 0 ? void 0 : kmodel.isKT)) {
431
+ if (isRef(kmodel)) {
432
+ return kmodel;
433
+ }
434
+ else {
414
435
  throw new Error("[kt.js error] k-model data must be a KTRef object, please use 'ref(...)' to wrap it.");
415
436
  }
416
- return kmodel;
417
437
  }
418
438
  return ref(defaultValue);
419
439
  };
440
+ var $setRef = function (props, node) {
441
+ if ('ref' in props) {
442
+ var r = props.ref;
443
+ if (isRef(r)) {
444
+ r.value = node;
445
+ }
446
+ else {
447
+ throw new Error('[kt.js error] Fragment: ref must be a KTRef');
448
+ }
449
+ }
450
+ };
420
451
 
421
452
  var KTComputed = /** @class */ (function () {
422
453
  function KTComputed(_calculator, reactives) {
@@ -567,17 +598,17 @@ var __ktjs_core__ = (function (exports) {
567
598
  }
568
599
  if (element instanceof HTMLInputElement) {
569
600
  if (element.type === 'radio' || element.type === 'checkbox') {
570
- applyModel(element, valueRef, 'checked', 'change');
601
+ $applyModel(element, valueRef, 'checked', 'change');
571
602
  }
572
603
  else {
573
- applyModel(element, valueRef, 'value', 'input');
604
+ $applyModel(element, valueRef, 'value', 'input');
574
605
  }
575
606
  }
576
607
  else if (element instanceof HTMLSelectElement) {
577
- applyModel(element, valueRef, 'value', 'change');
608
+ $applyModel(element, valueRef, 'value', 'change');
578
609
  }
579
610
  else if (element instanceof HTMLTextAreaElement) {
580
- applyModel(element, valueRef, 'value', 'input');
611
+ $applyModel(element, valueRef, 'value', 'input');
581
612
  }
582
613
  else {
583
614
  console.warn('[kt.js warn]','not supported element for k-model:');
@@ -598,7 +629,7 @@ var __ktjs_core__ = (function (exports) {
598
629
  * ## About
599
630
  * @package @ktjs/core
600
631
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
601
- * @version 0.26.9 (Last Update: 2026.02.06 16:29:24.402)
632
+ * @version 0.27.1 (Last Update: 2026.02.10 01:30:30.991)
602
633
  * @license MIT
603
634
  * @link https://github.com/baendlorel/kt.js
604
635
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -633,7 +664,110 @@ var __ktjs_core__ = (function (exports) {
633
664
  return element;
634
665
  };
635
666
 
636
- var dummyRef = { value: null };
667
+ var kredraw = function () {
668
+ var newElements = this.kchildrenRef.value;
669
+ var parent = this.parentNode;
670
+ if (!parent) {
671
+ // If anchor is not in DOM, only update internal state
672
+ this.kFragmentList.length = 0;
673
+ for (var i = 0; i < newElements.length; i++) {
674
+ this.kFragmentList.push(newElements[i]);
675
+ }
676
+ return;
677
+ }
678
+ // Simple replacement algorithm: remove all old elements, insert all new elements
679
+ // todo Future enhancement: key-based optimization
680
+ // 1. Remove all old elements
681
+ for (var i = 0; i < this.kFragmentList.length; i++) {
682
+ this.kFragmentList[i].remove();
683
+ }
684
+ // 2. Insert all new elements
685
+ var fragment = document.createDocumentFragment();
686
+ this.kFragmentList.length = 0;
687
+ for (var i = 0; i < newElements.length; i++) {
688
+ var element = newElements[i];
689
+ this.kFragmentList.push(element);
690
+ fragment.appendChild(element);
691
+ }
692
+ // Insert after anchor
693
+ parent.insertBefore(fragment, this.nextSibling);
694
+ };
695
+ /**
696
+ * Fragment - Container component for managing arrays of child elements
697
+ *
698
+ * Features:
699
+ * 1. Returns a comment anchor node, child elements are inserted after the anchor
700
+ * 2. Supports reactive arrays, automatically updates DOM when array changes
701
+ * 3. Basic version uses simple replacement algorithm (remove all old elements, insert all new elements)
702
+ * 4. Future enhancement: key-based optimization
703
+ *
704
+ * Usage example:
705
+ * ```tsx
706
+ * const children = ref([<div>A</div>, <div>B</div>]);
707
+ * const fragment = <Fragment children={children} />;
708
+ * document.body.appendChild(fragment);
709
+ *
710
+ * // Automatic update
711
+ * children.value = [<div>C</div>, <div>D</div>];
712
+ * ```
713
+ */
714
+ function Fragment$1(props) {
715
+ // key parameter reserved for future enhancement, currently unused
716
+ props.key;
717
+ var childrenRef = toReactive(props.children, function () { return anchor.kredraw(); });
718
+ var anchor = document.createComment('kt-fragment');
719
+ anchor.kredraw = kredraw;
720
+ anchor.kchildrenRef = childrenRef;
721
+ anchor.kFragmentList = [];
722
+ anchor.kisFragmentAnchor = true;
723
+ // Observe DOM insertion
724
+ var observer = new MutationObserver(function () {
725
+ if (anchor.isConnected) {
726
+ anchor.kredraw();
727
+ observer.disconnect();
728
+ }
729
+ });
730
+ observer.observe(document.body, { childList: true, subtree: true });
731
+ // Set ref reference
732
+ $setRef(props, anchor);
733
+ return anchor;
734
+ }
735
+ /**
736
+ * Convert KTRawContent to HTMLElement array
737
+ */
738
+ function convertChildrenToElements(children) {
739
+ var elements = [];
740
+ var processChild = function (child) {
741
+ if (child == null || child === false || child === true) {
742
+ // Ignore null, undefined, false, true
743
+ return;
744
+ }
745
+ if ($isArray(child)) {
746
+ // Recursively process array
747
+ $forEach(child, processChild);
748
+ return;
749
+ }
750
+ if (typeof child === 'string' || typeof child === 'number') {
751
+ // & Wrap text in span element? No! use text node instead
752
+ var textNode = document.createTextNode(String(child));
753
+ elements.push(textNode);
754
+ return;
755
+ }
756
+ if (child instanceof HTMLElement) {
757
+ elements.push(child);
758
+ return;
759
+ }
760
+ if (isKT(child)) {
761
+ processChild(child.value);
762
+ return;
763
+ }
764
+ // Other types ignored or converted to string
765
+ console.warn('[kt.js warn]','Fragment: unsupported child type', child);
766
+ };
767
+ processChild(children);
768
+ return elements;
769
+ }
770
+
637
771
  var create = function (tag, props) {
638
772
  if (typeof tag === 'function') {
639
773
  return tag(props);
@@ -651,7 +785,6 @@ var __ktjs_core__ = (function (exports) {
651
785
  if (isComputed(props.ref)) {
652
786
  throw new Error('[kt.js error] Cannot assign a computed value to an element.');
653
787
  }
654
- var maybeDummyRef = isRef(props.ref) ? props.ref : dummyRef;
655
788
  var el;
656
789
  if ('k-if' in props) {
657
790
  var kif = props['k-if'];
@@ -663,49 +796,31 @@ var __ktjs_core__ = (function (exports) {
663
796
  return;
664
797
  }
665
798
  var oldEl = el;
666
- el = newValue ? create(tag, props) : placeholder();
799
+ $setRef(props, (el = newValue ? create(tag, props) : placeholder()));
667
800
  $replaceNode(oldEl, el);
668
- maybeDummyRef.value = el;
669
801
  });
670
802
  condition = kif.value;
671
803
  }
672
804
  if (!condition) {
673
805
  // & make comment placeholder in case that ref might be redrawn later
674
- el = placeholder();
675
- maybeDummyRef.value = el;
806
+ $setRef(props, (el = placeholder()));
676
807
  return el;
677
808
  }
678
809
  }
679
- el = create(tag, props);
680
- maybeDummyRef.value = el;
810
+ $setRef(props, (el = create(tag, props)));
681
811
  return el;
682
812
  }
683
813
  /**
684
814
  * Fragment support - returns an array of children
685
- * Note: kt.js doesn't have a real Fragment concept,
815
+ * Enhanced Fragment component that manages arrays of elements
686
816
  */
687
- function Fragment(_props) {
688
- throw new Error("[kt.js error] doesn't have a Fragment concept");
689
- // const { children } = props ?? {};
690
- // if (!children) {
691
- // return ;
692
- // }
693
- // // If single child, return it directly
694
- // if (!Array.isArray(children)) {
695
- // return children as HTMLElement;
696
- // }
697
- // // For multiple children, create a document fragment wrapper
698
- // // This is a limitation - JSX fragments must be wrapped in kt.js
699
- // const wrapper = document.createElement('div');
700
- // wrapper.setAttribute('data-kt-fragment', 'true');
701
- // children.forEach((child) => {
702
- // if (typeof child === 'string') {
703
- // wrapper.appendChild(document.createTextNode(child));
704
- // } else if (child instanceof HTMLElement) {
705
- // wrapper.appendChild(child);
706
- // }
707
- // });
708
- // return wrapper;
817
+ function Fragment(props) {
818
+ var children = (props !== null && props !== void 0 ? props : {}).children;
819
+ if (!children) {
820
+ return document.createComment('kt-fragment-empty');
821
+ }
822
+ var elements = convertChildrenToElements(children);
823
+ return Fragment$1({ children: elements });
709
824
  }
710
825
  /**
711
826
  * JSX Development runtime - same as jsx but with additional dev checks
@@ -767,47 +882,17 @@ var __ktjs_core__ = (function (exports) {
767
882
  * Returns a Comment anchor node with rendered elements in __kt_for_list__
768
883
  */
769
884
  function KTFor(props) {
770
- var _a;
771
- var list = props.list, map = props.map;
772
- var key = (_a = props.key) !== null && _a !== void 0 ? _a : (function (item) { return item; });
773
- // Create anchor comment node
774
- var anchor = document.createComment('kt-for');
775
- // Store current state
776
- var currentList = list;
777
- var currentKey = key;
778
- var currentMap = map;
779
- // Map to track rendered nodes by key
780
- var nodeMap = new Map();
781
- // Render initial list
782
- var elements = [];
783
- for (var index = 0; index < currentList.length; index++) {
784
- var item = currentList[index];
785
- var itemKey = currentKey(item, index, currentList);
786
- var node = currentMap(item, index, currentList);
787
- nodeMap.set(itemKey, node);
788
- elements.push(node);
789
- }
790
- // Attach elements array to anchor
791
- anchor.__kt_for_list__ = elements;
792
- // Redraw function for updates
793
- anchor.redraw = function (newProps) {
794
- var _a, _b, _c;
795
- var newList = ((_a = newProps === null || newProps === void 0 ? void 0 : newProps.list) !== null && _a !== void 0 ? _a : currentList);
796
- var newKey = ((_b = newProps === null || newProps === void 0 ? void 0 : newProps.key) !== null && _b !== void 0 ? _b : currentKey);
797
- var newMap = ((_c = newProps === null || newProps === void 0 ? void 0 : newProps.map) !== null && _c !== void 0 ? _c : currentMap);
798
- // Update stored values
799
- currentList = newList;
800
- currentKey = newKey;
801
- currentMap = newMap;
885
+ var redraw = function () {
886
+ var newList = listRef.value;
802
887
  var parent = anchor.parentNode;
803
888
  if (!parent) {
804
889
  // If not in DOM yet, just rebuild the list
805
890
  var newElements_1 = [];
806
891
  nodeMap.clear();
807
- for (var index = 0; index < currentList.length; index++) {
808
- var item = currentList[index];
809
- var itemKey = currentKey(item, index, currentList);
810
- var node = currentMap(item, index, currentList);
892
+ for (var index = 0; index < newList.length; index++) {
893
+ var item = newList[index];
894
+ var itemKey = currentKey(item, index, newList);
895
+ var node = currentMap(item, index, newList);
811
896
  nodeMap.set(itemKey, node);
812
897
  newElements_1.push(node);
813
898
  }
@@ -829,8 +914,8 @@ var __ktjs_core__ = (function (exports) {
829
914
  var fragment = document.createDocumentFragment();
830
915
  for (var i = 0; i < newLength; i++) {
831
916
  var item = newList[i];
832
- var itemKey = newKey(item, i, newList);
833
- var node = newMap(item, i, newList);
917
+ var itemKey = currentKey(item, i, newList);
918
+ var node = currentMap(item, i, newList);
834
919
  nodeMap.set(itemKey, node);
835
920
  newElements_2.push(node);
836
921
  fragment.appendChild(node);
@@ -846,7 +931,7 @@ var __ktjs_core__ = (function (exports) {
846
931
  var moved = false;
847
932
  for (var i = 0; i < newLength; i++) {
848
933
  var item = newList[i];
849
- var itemKey = newKey(item, i, newList);
934
+ var itemKey = currentKey(item, i, newList);
850
935
  newKeyToNewIndex.set(itemKey, i);
851
936
  if (nodeMap.has(itemKey)) {
852
937
  // Reuse existing node
@@ -862,7 +947,7 @@ var __ktjs_core__ = (function (exports) {
862
947
  }
863
948
  else {
864
949
  // Create new node
865
- newElements[i] = newMap(item, i, newList);
950
+ newElements[i] = currentMap(item, i, newList);
866
951
  }
867
952
  }
868
953
  // Remove nodes not in new list
@@ -878,7 +963,7 @@ var __ktjs_core__ = (function (exports) {
878
963
  // Update DOM with minimal operations
879
964
  if (moved) {
880
965
  // Use longest increasing subsequence to minimize moves
881
- var seq = getSequence(newElements.map(function (el, i) { return (nodeMap.has(newKey(newList[i], i, newList)) ? i : -1); }));
966
+ var seq = getSequence(newElements.map(function (el, i) { return (nodeMap.has(currentKey(newList[i], i, newList)) ? i : -1); }));
882
967
  var j = seq.length - 1;
883
968
  var anchor_1 = null;
884
969
  // Traverse from end to start for stable insertions
@@ -921,16 +1006,28 @@ var __ktjs_core__ = (function (exports) {
921
1006
  // Update maps
922
1007
  nodeMap.clear();
923
1008
  for (var i = 0; i < newLength; i++) {
924
- var itemKey = newKey(newList[i], i, newList);
1009
+ var itemKey = currentKey(newList[i], i, newList);
925
1010
  nodeMap.set(itemKey, newElements[i]);
926
1011
  }
927
1012
  anchor.__kt_for_list__ = newElements;
928
1013
  return anchor;
929
1014
  };
930
- // Set ref if provided
931
- if (isRef(props.ref)) {
932
- props.ref.value = anchor;
1015
+ var _a = props.key, currentKey = _a === void 0 ? function (item) { return item; } : _a, currentMap = props.map;
1016
+ var listRef = toReactive(props.list, redraw);
1017
+ var anchor = document.createComment('kt-for');
1018
+ // Map to track rendered nodes by key
1019
+ var nodeMap = new Map();
1020
+ // Render initial list
1021
+ var elements = [];
1022
+ for (var index = 0; index < listRef.value.length; index++) {
1023
+ var item = listRef.value[index];
1024
+ var itemKey = currentKey(item, index, listRef.value);
1025
+ var node = currentMap(item, index, listRef.value);
1026
+ nodeMap.set(itemKey, node);
1027
+ elements.push(node);
933
1028
  }
1029
+ anchor.__kt_for_list__ = elements;
1030
+ $setRef(props, anchor);
934
1031
  return anchor;
935
1032
  }
936
1033
  // Longest Increasing Subsequence algorithm (optimized for diff)
@@ -977,6 +1074,7 @@ var __ktjs_core__ = (function (exports) {
977
1074
  }
978
1075
 
979
1076
  exports.$modelOrRef = $modelOrRef;
1077
+ exports.$setRef = $setRef;
980
1078
  exports.Fragment = Fragment;
981
1079
  exports.KTAsync = KTAsync;
982
1080
  exports.KTComputed = KTComputed;