@ktjs/core 0.22.5 → 0.24.0

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,13 +1,38 @@
1
1
  var __ktjs_core__ = (function (exports) {
2
2
  'use strict';
3
3
 
4
+ // Shared constants
5
+ // Empty for now - can be extended with framework-wide constants
6
+ /**
7
+ * Mark the attribute as SVG to handle special cases during rendering.
8
+ */
9
+ const SVG_ATTR_FLAG = '__kt_svg__';
10
+ /**
11
+ * Mark the attribute as MathML to handle special cases during rendering.
12
+ */
13
+ const MATHML_ATTR_FLAG = '__kt_mathml__';
14
+
4
15
  // Cached native methods for performance optimization
5
16
  const $isArray = Array.isArray;
17
+ const $is = Object.is;
6
18
  const $entries = Object.entries;
7
- const $isThenable = (o) => typeof o === 'object' && o !== null && typeof o.then === 'function';
19
+ const $random = Math.random;
20
+ const $isThenable = (o) => typeof o?.then === 'function';
8
21
 
9
22
  // DOM manipulation utilities
10
23
  // # dom natives
24
+ const $isNode = (x) => x?.nodeType > 0;
25
+ /**
26
+ * Safe replace `oldNode` With `newNode`
27
+ */
28
+ const $replaceNode = (oldNode, newNode) => {
29
+ if ($isNode(oldNode) && $isNode(newNode)) {
30
+ if (newNode.contains(oldNode)) {
31
+ newNode.remove();
32
+ }
33
+ oldNode.replaceWith(newNode);
34
+ }
35
+ };
11
36
  /**
12
37
  * & Remove `bind` because it is shockingly slower than wrapper
13
38
  * & `window.document` is safe because it is not configurable and its setter is undefined
@@ -53,126 +78,21 @@ var __ktjs_core__ = (function (exports) {
53
78
  element.addEventListener(eventName, () => (valueRef.value = element[propName]));
54
79
  };
55
80
 
56
- // Shared utilities and cached native methods for kt.js framework
57
- // Re-export all utilities
58
- Object.defineProperty(window, '__ktjs__', { value: '0.22.2' });
59
-
60
- var KTRef = /** @class */ (function () {
61
- function KTRef(_value, _onChanges) {
62
- /**
63
- * Indicates that this is a KTRef instance
64
- */
65
- this.isKT = true;
66
- this._value = _value;
67
- this._onChanges = _onChanges;
68
- }
69
- Object.defineProperty(KTRef.prototype, "value", {
70
- /**
71
- * If new value and old value are both nodes, the old one will be replaced in the DOM
72
- */
73
- get: function () {
74
- return this._value;
75
- },
76
- set: function (newValue) {
77
- if (newValue === this._value) {
78
- return;
79
- }
80
- // replace the old node with the new one in the DOM if both are nodes
81
- if (this._value instanceof Node && newValue instanceof Node) {
82
- if (newValue.contains(this._value)) {
83
- this._value.remove();
84
- }
85
- this._value.replaceWith(newValue);
86
- }
87
- var oldValue = this._value;
88
- this._value = newValue;
89
- for (var i = 0; i < this._onChanges.length; i++) {
90
- this._onChanges[i](newValue, oldValue);
91
- }
92
- },
93
- enumerable: false,
94
- configurable: true
95
- });
96
- /**
97
- * Register a callback when the value changes
98
- * @param callback (newValue, oldValue) => xxx
99
- */
100
- KTRef.prototype.addOnChange = function (callback) {
101
- if (typeof callback !== 'function') {
102
- throw new Error('[kt.js error] KTRef.addOnChange: callback must be a function');
103
- }
104
- this._onChanges.push(callback);
105
- };
106
- KTRef.prototype.removeOnChange = function (callback) {
107
- for (var i = this._onChanges.length - 1; i >= 0; i--) {
108
- if (this._onChanges[i] === callback) {
109
- this._onChanges.splice(i, 1);
110
- return true;
111
- }
112
- }
113
- return false;
81
+ if (typeof Symbol === 'undefined') {
82
+ window.Symbol = function Symbol(description) {
83
+ return `@@SYMBOL_${description || ''}_${$random().toString(36).slice(2)}`;
114
84
  };
115
- return KTRef;
116
- }());
117
- var isKTRef = function (obj) { return (obj === null || obj === void 0 ? void 0 : obj.isKT) === true; };
118
- /**
119
- * Reference to the created HTML element.
120
- * - **Only** respond to `ref.value` changes, not reactive to internal changes of the element.
121
- * - can alse be used to store normal values, but it is not reactive.
122
- * - if the value is already a `KTRef`, it will be returned **directly**.
123
- * @param value mostly an HTMLElement
124
- */
125
- function ref(value, onChange) {
126
- if (isKTRef(value)) {
127
- if (onChange) {
128
- value.addOnChange(onChange);
129
- }
130
- return value;
131
- }
132
- return new KTRef(value, onChange ? [onChange] : []);
133
- }
134
- function deref(value) {
135
- return isKTRef(value) ? value.value : value;
136
- }
137
- function kcollect() {
138
- var newObj = {};
139
- var entries = $entries(this);
140
- for (var i = 0; i < entries.length; i++) {
141
- var key = entries[i][0];
142
- if (key === 'kcollect') {
143
- continue;
144
- }
145
- newObj[key] = entries[i][1].value;
146
- }
147
- return newObj;
148
85
  }
149
- /**
150
- * Make all first-level properties of the object a `KTRef`.
151
- * - `obj.a.b` is not reactive
152
- */
153
- var surfaceRef = function (obj) {
154
- var entries = $entries(obj);
155
- var newObj = { kcollect: kcollect };
156
- for (var i = 0; i < entries.length; i++) {
157
- newObj[entries[i][0]] = ref(entries[i][1]);
158
- }
159
- return newObj;
160
- };
161
- // # asserts
162
- /**
163
- * Assert k-model to be a ref object
164
- */
165
- var $modelOrRef = function (props, defaultValue) {
166
- // & props is an object. Won't use it in any other place
167
- if ('k-model' in props) {
168
- var kmodel = props['k-model'];
169
- if (!(kmodel === null || kmodel === void 0 ? void 0 : kmodel.isKT)) {
170
- throw new Error("[kt.js error] k-model data must be a KTRef object, please use 'ref(...)' to wrap it.");
171
- }
172
- return kmodel;
173
- }
174
- return ref(defaultValue);
175
- };
86
+
87
+ // Shared utilities and cached native methods for kt.js framework
88
+ Object.defineProperty(window, '__ktjs__', { value: '0.22.6' });
89
+
90
+ // export const KT_TYPE_REF = 1 as const;
91
+ // export const KT_TYPE_COMPUTED = 2 as const;
92
+ // export type KTReactiveTypeEnum = typeof KT_TYPE_REF | typeof KT_TYPE_COMPUTED;
93
+ var isKT = function (obj) { return obj === null || obj === void 0 ? void 0 : obj.isKT; };
94
+ var isRef = function (obj) { return (obj === null || obj === void 0 ? void 0 : obj.ktType) === 1 /* KTReactiveType.REF */; };
95
+ var isComputed = function (obj) { return (obj === null || obj === void 0 ? void 0 : obj.ktType) === 2 /* KTReactiveType.COMPUTED */; };
176
96
 
177
97
  var booleanHandler = function (element, key, value) {
178
98
  if (key in element) {
@@ -234,14 +154,25 @@ var __ktjs_core__ = (function (exports) {
234
154
  }
235
155
  }
236
156
  }
157
+ if ('k-html' in attr) {
158
+ var html = attr['k-html'];
159
+ if (isKT(html)) {
160
+ element.innerHTML = html.value;
161
+ html.addOnChange(function (v) { return (element.innerHTML = v); });
162
+ }
163
+ else {
164
+ element.innerHTML = html;
165
+ }
166
+ }
237
167
  for (var key in attr) {
238
- if (key === 'class' ||
168
+ if (key === 'k-if' ||
169
+ key === 'k-model' ||
170
+ key === 'ref' ||
171
+ key === 'class' ||
239
172
  key === 'className' ||
240
173
  key === 'style' ||
241
174
  key === 'children' ||
242
- key === 'k-if' ||
243
- key.startsWith('k-model') ||
244
- key === 'ref') {
175
+ key === 'k-html') {
245
176
  continue;
246
177
  }
247
178
  var o = attr[key];
@@ -251,6 +182,7 @@ var __ktjs_core__ = (function (exports) {
251
182
  }
252
183
  // normal attributes
253
184
  else {
185
+ // todo 这里也可以绑定ref的
254
186
  (handlers[key] || defaultHandler)(element, key, o);
255
187
  }
256
188
  }
@@ -267,13 +199,25 @@ var __ktjs_core__ = (function (exports) {
267
199
  }
268
200
  }
269
201
 
202
+ var assureNode = function (o) { return ($isNode(o) ? o : document.createTextNode(o)); };
270
203
  function apdSingle(element, c) {
271
204
  // & JSX should ignore false, undefined, and null
272
205
  if (c === false || c === undefined || c === null) {
273
206
  return;
274
207
  }
275
- if (typeof c === 'object' && c !== null && 'isKT' in c) {
276
- $append.call(element, c.value);
208
+ if (isKT(c)) {
209
+ var node_1 = assureNode(c.value);
210
+ $append.call(element, node_1);
211
+ c.addOnChange(function (newValue, oldValue) {
212
+ if ($isNode(newValue) && $isNode(oldValue)) {
213
+ // & this case is handled automically in `class KTRef`
214
+ // todo 2 cases might be able to merge into 1
215
+ return;
216
+ }
217
+ var oldNode = node_1;
218
+ node_1 = assureNode(newValue);
219
+ oldNode.replaceWith(node_1);
220
+ });
277
221
  }
278
222
  else {
279
223
  $append.call(element, c);
@@ -321,8 +265,213 @@ var __ktjs_core__ = (function (exports) {
321
265
  }
322
266
  }
323
267
 
268
+ var KTRef = /** @class */ (function () {
269
+ function KTRef(_value, _onChanges) {
270
+ /**
271
+ * Indicates that this is a KTRef instance
272
+ */
273
+ this.isKT = true;
274
+ this.ktType = 1 /* KTReactiveType.REF */;
275
+ this._value = _value;
276
+ this._onChanges = _onChanges;
277
+ }
278
+ Object.defineProperty(KTRef.prototype, "value", {
279
+ /**
280
+ * If new value and old value are both nodes, the old one will be replaced in the DOM
281
+ */
282
+ get: function () {
283
+ return this._value;
284
+ },
285
+ set: function (newValue) {
286
+ if ($is(newValue, this._value)) {
287
+ return;
288
+ }
289
+ var oldValue = this._value;
290
+ $replaceNode(oldValue, newValue);
291
+ this._value = newValue;
292
+ for (var i = 0; i < this._onChanges.length; i++) {
293
+ this._onChanges[i](newValue, oldValue);
294
+ }
295
+ },
296
+ enumerable: false,
297
+ configurable: true
298
+ });
299
+ /**
300
+ * Register a callback when the value changes
301
+ * @param callback (newValue, oldValue) => xxx
302
+ */
303
+ KTRef.prototype.addOnChange = function (callback) {
304
+ if (typeof callback !== 'function') {
305
+ throw new Error('[kt.js error] KTRef.addOnChange: callback must be a function');
306
+ }
307
+ this._onChanges.push(callback);
308
+ };
309
+ KTRef.prototype.removeOnChange = function (callback) {
310
+ for (var i = this._onChanges.length - 1; i >= 0; i--) {
311
+ if (this._onChanges[i] === callback) {
312
+ this._onChanges.splice(i, 1);
313
+ return true;
314
+ }
315
+ }
316
+ return false;
317
+ };
318
+ return KTRef;
319
+ }());
320
+ /**
321
+ * Reference to the created HTML element.
322
+ * - **Only** respond to `ref.value` changes, not reactive to internal changes of the element.
323
+ * - can alse be used to store normal values, but it is not reactive.
324
+ * - if the value is already a `KTRef`, it will be returned **directly**.
325
+ * @param value mostly an HTMLElement
326
+ */
327
+ function ref(value, onChange) {
328
+ return new KTRef(value, onChange ? [onChange] : []);
329
+ }
330
+ /**
331
+ * Convert a value to `KTRef`.
332
+ * - Returns the original value if it is already a `KTRef`.
333
+ * - Throws error if the value is a `KTComputed`.
334
+ * - Otherwise wraps the value with `ref()`.
335
+ * @param o value to convert
336
+ */
337
+ var toRef = function (o) {
338
+ if (isRef(o)) {
339
+ return o;
340
+ }
341
+ else if (isComputed(o)) {
342
+ throw new Error('[kt.js error] Computed values cannot be used as KTRef.');
343
+ }
344
+ else {
345
+ return ref(o);
346
+ }
347
+ };
348
+ function deref(value) {
349
+ return isKT(value) ? value.value : value;
350
+ }
351
+ function kcollect() {
352
+ var newObj = {};
353
+ var entries = $entries(this);
354
+ for (var i = 0; i < entries.length; i++) {
355
+ var key = entries[i][0];
356
+ if (key === 'kcollect') {
357
+ continue;
358
+ }
359
+ newObj[key] = entries[i][1].value;
360
+ }
361
+ return newObj;
362
+ }
363
+ /**
364
+ * Make all first-level properties of the object a `KTRef`.
365
+ * - `obj.a.b` is not reactive
366
+ */
367
+ var surfaceRef = function (obj) {
368
+ var entries = $entries(obj);
369
+ var newObj = { kcollect: kcollect };
370
+ for (var i = 0; i < entries.length; i++) {
371
+ newObj[entries[i][0]] = ref(entries[i][1]);
372
+ }
373
+ return newObj;
374
+ };
375
+ // # asserts
376
+ /**
377
+ * Assert k-model to be a ref object
378
+ */
379
+ var $modelOrRef = function (props, defaultValue) {
380
+ // & props is an object. Won't use it in any other place
381
+ if ('k-model' in props) {
382
+ var kmodel = props['k-model'];
383
+ if (!(kmodel === null || kmodel === void 0 ? void 0 : kmodel.isKT)) {
384
+ throw new Error("[kt.js error] k-model data must be a KTRef object, please use 'ref(...)' to wrap it.");
385
+ }
386
+ return kmodel;
387
+ }
388
+ return ref(defaultValue);
389
+ };
390
+
391
+ var KTComputed = /** @class */ (function () {
392
+ function KTComputed(_calculator, reactives) {
393
+ /**
394
+ * Indicates that this is a KTRef instance
395
+ */
396
+ this.isKT = true;
397
+ this.ktType = 2 /* KTReactiveType.COMPUTED */;
398
+ /**
399
+ * @internal
400
+ */
401
+ this._onChanges = [];
402
+ this._calculator = _calculator;
403
+ this._value = _calculator();
404
+ this._subscribe(reactives);
405
+ }
406
+ KTComputed.prototype._subscribe = function (reactives) {
407
+ var _this = this;
408
+ for (var i = 0; i < reactives.length; i++) {
409
+ var reactive = reactives[i];
410
+ reactive.addOnChange(function () {
411
+ var oldValue = _this._value;
412
+ _this._value = _this._calculator();
413
+ if (oldValue === _this._value) {
414
+ return;
415
+ }
416
+ $replaceNode(oldValue, _this._value);
417
+ for (var i_1 = 0; i_1 < _this._onChanges.length; i_1++) {
418
+ _this._onChanges[i_1](_this._value, oldValue);
419
+ }
420
+ });
421
+ }
422
+ };
423
+ Object.defineProperty(KTComputed.prototype, "value", {
424
+ /**
425
+ * If new value and old value are both nodes, the old one will be replaced in the DOM
426
+ */
427
+ get: function () {
428
+ return this._value;
429
+ },
430
+ set: function (_newValue) {
431
+ throw new Error('[kt.js error] KTComputed: cannot set value of a computed value');
432
+ },
433
+ enumerable: false,
434
+ configurable: true
435
+ });
436
+ /**
437
+ * Register a callback when the value changes
438
+ * @param callback (newValue, oldValue) => xxx
439
+ */
440
+ KTComputed.prototype.addOnChange = function (callback) {
441
+ if (typeof callback !== 'function') {
442
+ throw new Error('[kt.js error] KTRef.addOnChange: callback must be a function');
443
+ }
444
+ this._onChanges.push(callback);
445
+ };
446
+ /**
447
+ * Unregister a callback
448
+ * @param callback (newValue, oldValue) => xxx
449
+ */
450
+ KTComputed.prototype.removeOnChange = function (callback) {
451
+ for (var i = this._onChanges.length - 1; i >= 0; i--) {
452
+ if (this._onChanges[i] === callback) {
453
+ this._onChanges.splice(i, 1);
454
+ return true;
455
+ }
456
+ }
457
+ return false;
458
+ };
459
+ return KTComputed;
460
+ }());
461
+ /**
462
+ * Create a reactive computed value
463
+ * @param computeFn
464
+ * @param reactives refs and computeds that this computed depends on
465
+ */
466
+ function computed(computeFn, reactives) {
467
+ if (reactives.some(function (v) { return !isKT(v); })) {
468
+ throw new Error('[kt.js error] computed: all reactives must be KTRef or KTComputed instances');
469
+ }
470
+ return new KTComputed(computeFn, reactives);
471
+ }
472
+
324
473
  function applyKModel(element, valueRef) {
325
- if (!isKTRef(valueRef)) {
474
+ if (!isKT(valueRef)) {
326
475
  console.warn('[kt.js warn] k-model value must be a KTRef.');
327
476
  return;
328
477
  }
@@ -349,9 +498,6 @@ var __ktjs_core__ = (function (exports) {
349
498
  var svgCreator = function (tag) { return document.createElementNS('http://www.w3.org/2000/svg', tag); };
350
499
  var mathMLCreator = function (tag) { return document.createElementNS('http://www.w3.org/1998/Math/MathML', tag); };
351
500
  var creator = htmlCreator;
352
- // # consts
353
- var SVG_ATTR_FLAG = '__kt_svg__';
354
- var MATHML_ATTR_FLAG = '__kt_mathml__';
355
501
  /**
356
502
  * Create an enhanced HTMLElement.
357
503
  * - Only supports HTMLElements, **NOT** SVGElements or other Elements.
@@ -362,7 +508,7 @@ var __ktjs_core__ = (function (exports) {
362
508
  * ## About
363
509
  * @package @ktjs/core
364
510
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
365
- * @version 0.22.5 (Last Update: 2026.02.03 09:07:21.411)
511
+ * @version 0.24.0 (Last Update: 2026.02.05 12:08:54.164)
366
512
  * @license MIT
367
513
  * @link https://github.com/baendlorel/kt.js
368
514
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -392,13 +538,7 @@ var __ktjs_core__ = (function (exports) {
392
538
  applyAttr(element, attr);
393
539
  applyContent(element, content);
394
540
  if (typeof attr === 'object' && attr !== null && 'k-model' in attr) {
395
- var kmodel = attr['k-model'];
396
- if (isKTRef(kmodel)) {
397
- applyKModel(element, kmodel);
398
- }
399
- else {
400
- throw new Error('[kt.js error] k-model value must be a KTRef.');
401
- }
541
+ applyKModel(element, attr['k-model']);
402
542
  }
403
543
  return element;
404
544
  };
@@ -418,20 +558,23 @@ var __ktjs_core__ = (function (exports) {
418
558
  * @param props properties/attributes
419
559
  */
420
560
  function jsx(tag, props) {
421
- var maybeDummyRef = isKTRef(props.ref) ? props.ref : dummyRef;
561
+ if (isComputed(props.ref)) {
562
+ throw new Error('[kt.js error] Cannot assign a computed value to an element.');
563
+ }
564
+ var maybeDummyRef = isRef(props.ref) ? props.ref : dummyRef;
422
565
  var el;
423
566
  if ('k-if' in props) {
424
567
  var kif = props['k-if'];
425
568
  var condition = kif; // assume boolean by default
426
569
  // Handle reactive k-if
427
- if (isKTRef(kif)) {
570
+ if (isKT(kif)) {
428
571
  kif.addOnChange(function (newValue, oldValue) {
429
572
  if (newValue === oldValue) {
430
573
  return;
431
574
  }
432
575
  var oldEl = el;
433
576
  el = newValue ? create(tag, props) : placeholder();
434
- oldEl.replaceWith(el);
577
+ $replaceNode(oldEl, el);
435
578
  maybeDummyRef.value = el;
436
579
  });
437
580
  condition = kif.value;
@@ -534,7 +677,7 @@ var __ktjs_core__ = (function (exports) {
534
677
  * Returns a Comment anchor node with rendered elements in __kt_for_list__
535
678
  */
536
679
  function KTFor(props) {
537
- var _a, _b;
680
+ var _a;
538
681
  var list = props.list, map = props.map;
539
682
  var key = (_a = props.key) !== null && _a !== void 0 ? _a : (function (item) { return item; });
540
683
  // Create anchor comment node
@@ -695,7 +838,7 @@ var __ktjs_core__ = (function (exports) {
695
838
  return anchor;
696
839
  };
697
840
  // Set ref if provided
698
- if ((_b = props.ref) === null || _b === void 0 ? void 0 : _b.isKT) {
841
+ if (isRef(props.ref)) {
699
842
  props.ref.value = anchor;
700
843
  }
701
844
  return anchor;
@@ -746,18 +889,23 @@ var __ktjs_core__ = (function (exports) {
746
889
  exports.$modelOrRef = $modelOrRef;
747
890
  exports.Fragment = Fragment;
748
891
  exports.KTAsync = KTAsync;
892
+ exports.KTComputed = KTComputed;
749
893
  exports.KTFor = KTFor;
750
894
  exports.KTRef = KTRef;
895
+ exports.computed = computed;
751
896
  exports.createElement = h;
752
897
  exports.createRedrawable = createRedrawable;
753
898
  exports.deref = deref;
754
899
  exports.h = h;
755
- exports.isKTRef = isKTRef;
900
+ exports.isComputed = isComputed;
901
+ exports.isKT = isKT;
902
+ exports.isRef = isRef;
756
903
  exports.jsx = jsx;
757
904
  exports.jsxDEV = jsxDEV;
758
905
  exports.jsxs = jsxs;
759
906
  exports.ref = ref;
760
907
  exports.surfaceRef = surfaceRef;
908
+ exports.toRef = toRef;
761
909
 
762
910
  return exports;
763
911