@ktjs/core 0.23.0 → 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,14 +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
11
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
+ };
12
36
  /**
13
37
  * & Remove `bind` because it is shockingly slower than wrapper
14
38
  * & `window.document` is safe because it is not configurable and its setter is undefined
@@ -54,127 +78,21 @@ var __ktjs_core__ = (function (exports) {
54
78
  element.addEventListener(eventName, () => (valueRef.value = element[propName]));
55
79
  };
56
80
 
57
- // Shared utilities and cached native methods for kt.js framework
58
- // import './misc/symbol-polyfill.js';
59
- // Re-export all utilities
60
- Object.defineProperty(window, '__ktjs__', { value: '0.22.3' });
61
-
62
- var KTRef = /** @class */ (function () {
63
- function KTRef(_value, _onChanges) {
64
- /**
65
- * Indicates that this is a KTRef instance
66
- */
67
- this.isKT = true;
68
- this._value = _value;
69
- this._onChanges = _onChanges;
70
- }
71
- Object.defineProperty(KTRef.prototype, "value", {
72
- /**
73
- * If new value and old value are both nodes, the old one will be replaced in the DOM
74
- */
75
- get: function () {
76
- return this._value;
77
- },
78
- set: function (newValue) {
79
- if (newValue === this._value) {
80
- return;
81
- }
82
- // replace the old node with the new one in the DOM if both are nodes
83
- if (this._value instanceof Node && newValue instanceof Node) {
84
- if (newValue.contains(this._value)) {
85
- this._value.remove();
86
- }
87
- this._value.replaceWith(newValue);
88
- }
89
- var oldValue = this._value;
90
- this._value = newValue;
91
- for (var i = 0; i < this._onChanges.length; i++) {
92
- this._onChanges[i](newValue, oldValue);
93
- }
94
- },
95
- enumerable: false,
96
- configurable: true
97
- });
98
- /**
99
- * Register a callback when the value changes
100
- * @param callback (newValue, oldValue) => xxx
101
- */
102
- KTRef.prototype.addOnChange = function (callback) {
103
- if (typeof callback !== 'function') {
104
- throw new Error('[kt.js error] KTRef.addOnChange: callback must be a function');
105
- }
106
- this._onChanges.push(callback);
81
+ if (typeof Symbol === 'undefined') {
82
+ window.Symbol = function Symbol(description) {
83
+ return `@@SYMBOL_${description || ''}_${$random().toString(36).slice(2)}`;
107
84
  };
108
- KTRef.prototype.removeOnChange = function (callback) {
109
- for (var i = this._onChanges.length - 1; i >= 0; i--) {
110
- if (this._onChanges[i] === callback) {
111
- this._onChanges.splice(i, 1);
112
- return true;
113
- }
114
- }
115
- return false;
116
- };
117
- return KTRef;
118
- }());
119
- var isKTRef = function (obj) { return (obj === null || obj === void 0 ? void 0 : obj.isKT) === true; };
120
- /**
121
- * Reference to the created HTML element.
122
- * - **Only** respond to `ref.value` changes, not reactive to internal changes of the element.
123
- * - can alse be used to store normal values, but it is not reactive.
124
- * - if the value is already a `KTRef`, it will be returned **directly**.
125
- * @param value mostly an HTMLElement
126
- */
127
- function ref(value, onChange) {
128
- if (isKTRef(value)) {
129
- if (onChange) {
130
- value.addOnChange(onChange);
131
- }
132
- return value;
133
- }
134
- return new KTRef(value, onChange ? [onChange] : []);
135
- }
136
- function deref(value) {
137
- return isKTRef(value) ? value.value : value;
138
- }
139
- function kcollect() {
140
- var newObj = {};
141
- var entries = $entries(this);
142
- for (var i = 0; i < entries.length; i++) {
143
- var key = entries[i][0];
144
- if (key === 'kcollect') {
145
- continue;
146
- }
147
- newObj[key] = entries[i][1].value;
148
- }
149
- return newObj;
150
85
  }
151
- /**
152
- * Make all first-level properties of the object a `KTRef`.
153
- * - `obj.a.b` is not reactive
154
- */
155
- var surfaceRef = function (obj) {
156
- var entries = $entries(obj);
157
- var newObj = { kcollect: kcollect };
158
- for (var i = 0; i < entries.length; i++) {
159
- newObj[entries[i][0]] = ref(entries[i][1]);
160
- }
161
- return newObj;
162
- };
163
- // # asserts
164
- /**
165
- * Assert k-model to be a ref object
166
- */
167
- var $modelOrRef = function (props, defaultValue) {
168
- // & props is an object. Won't use it in any other place
169
- if ('k-model' in props) {
170
- var kmodel = props['k-model'];
171
- if (!(kmodel === null || kmodel === void 0 ? void 0 : kmodel.isKT)) {
172
- throw new Error("[kt.js error] k-model data must be a KTRef object, please use 'ref(...)' to wrap it.");
173
- }
174
- return kmodel;
175
- }
176
- return ref(defaultValue);
177
- };
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 */; };
178
96
 
179
97
  var booleanHandler = function (element, key, value) {
180
98
  if (key in element) {
@@ -238,7 +156,7 @@ var __ktjs_core__ = (function (exports) {
238
156
  }
239
157
  if ('k-html' in attr) {
240
158
  var html = attr['k-html'];
241
- if (isKTRef(html)) {
159
+ if (isKT(html)) {
242
160
  element.innerHTML = html.value;
243
161
  html.addOnChange(function (v) { return (element.innerHTML = v); });
244
162
  }
@@ -247,14 +165,14 @@ var __ktjs_core__ = (function (exports) {
247
165
  }
248
166
  }
249
167
  for (var key in attr) {
250
- if (key === 'class' ||
168
+ if (key === 'k-if' ||
169
+ key === 'k-model' ||
170
+ key === 'ref' ||
171
+ key === 'class' ||
251
172
  key === 'className' ||
252
173
  key === 'style' ||
253
174
  key === 'children' ||
254
- key === 'k-if' ||
255
- key === 'k-model' ||
256
- key === 'k-html' ||
257
- key === 'ref') {
175
+ key === 'k-html') {
258
176
  continue;
259
177
  }
260
178
  var o = attr[key];
@@ -287,7 +205,7 @@ var __ktjs_core__ = (function (exports) {
287
205
  if (c === false || c === undefined || c === null) {
288
206
  return;
289
207
  }
290
- if (isKTRef(c)) {
208
+ if (isKT(c)) {
291
209
  var node_1 = assureNode(c.value);
292
210
  $append.call(element, node_1);
293
211
  c.addOnChange(function (newValue, oldValue) {
@@ -347,8 +265,213 @@ var __ktjs_core__ = (function (exports) {
347
265
  }
348
266
  }
349
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
+
350
473
  function applyKModel(element, valueRef) {
351
- if (!isKTRef(valueRef)) {
474
+ if (!isKT(valueRef)) {
352
475
  console.warn('[kt.js warn] k-model value must be a KTRef.');
353
476
  return;
354
477
  }
@@ -375,9 +498,6 @@ var __ktjs_core__ = (function (exports) {
375
498
  var svgCreator = function (tag) { return document.createElementNS('http://www.w3.org/2000/svg', tag); };
376
499
  var mathMLCreator = function (tag) { return document.createElementNS('http://www.w3.org/1998/Math/MathML', tag); };
377
500
  var creator = htmlCreator;
378
- // # consts
379
- var SVG_ATTR_FLAG = '__kt_svg__';
380
- var MATHML_ATTR_FLAG = '__kt_mathml__';
381
501
  /**
382
502
  * Create an enhanced HTMLElement.
383
503
  * - Only supports HTMLElements, **NOT** SVGElements or other Elements.
@@ -388,7 +508,7 @@ var __ktjs_core__ = (function (exports) {
388
508
  * ## About
389
509
  * @package @ktjs/core
390
510
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
391
- * @version 0.23.0 (Last Update: 2026.02.03 17:15:01.812)
511
+ * @version 0.24.0 (Last Update: 2026.02.05 12:08:54.164)
392
512
  * @license MIT
393
513
  * @link https://github.com/baendlorel/kt.js
394
514
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -418,13 +538,7 @@ var __ktjs_core__ = (function (exports) {
418
538
  applyAttr(element, attr);
419
539
  applyContent(element, content);
420
540
  if (typeof attr === 'object' && attr !== null && 'k-model' in attr) {
421
- var kmodel = attr['k-model'];
422
- if (isKTRef(kmodel)) {
423
- applyKModel(element, kmodel);
424
- }
425
- else {
426
- throw new Error('[kt.js error] k-model value must be a KTRef.');
427
- }
541
+ applyKModel(element, attr['k-model']);
428
542
  }
429
543
  return element;
430
544
  };
@@ -444,20 +558,23 @@ var __ktjs_core__ = (function (exports) {
444
558
  * @param props properties/attributes
445
559
  */
446
560
  function jsx(tag, props) {
447
- 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;
448
565
  var el;
449
566
  if ('k-if' in props) {
450
567
  var kif = props['k-if'];
451
568
  var condition = kif; // assume boolean by default
452
569
  // Handle reactive k-if
453
- if (isKTRef(kif)) {
570
+ if (isKT(kif)) {
454
571
  kif.addOnChange(function (newValue, oldValue) {
455
572
  if (newValue === oldValue) {
456
573
  return;
457
574
  }
458
575
  var oldEl = el;
459
576
  el = newValue ? create(tag, props) : placeholder();
460
- oldEl.replaceWith(el);
577
+ $replaceNode(oldEl, el);
461
578
  maybeDummyRef.value = el;
462
579
  });
463
580
  condition = kif.value;
@@ -560,7 +677,7 @@ var __ktjs_core__ = (function (exports) {
560
677
  * Returns a Comment anchor node with rendered elements in __kt_for_list__
561
678
  */
562
679
  function KTFor(props) {
563
- var _a, _b;
680
+ var _a;
564
681
  var list = props.list, map = props.map;
565
682
  var key = (_a = props.key) !== null && _a !== void 0 ? _a : (function (item) { return item; });
566
683
  // Create anchor comment node
@@ -721,7 +838,7 @@ var __ktjs_core__ = (function (exports) {
721
838
  return anchor;
722
839
  };
723
840
  // Set ref if provided
724
- if ((_b = props.ref) === null || _b === void 0 ? void 0 : _b.isKT) {
841
+ if (isRef(props.ref)) {
725
842
  props.ref.value = anchor;
726
843
  }
727
844
  return anchor;
@@ -772,18 +889,23 @@ var __ktjs_core__ = (function (exports) {
772
889
  exports.$modelOrRef = $modelOrRef;
773
890
  exports.Fragment = Fragment;
774
891
  exports.KTAsync = KTAsync;
892
+ exports.KTComputed = KTComputed;
775
893
  exports.KTFor = KTFor;
776
894
  exports.KTRef = KTRef;
895
+ exports.computed = computed;
777
896
  exports.createElement = h;
778
897
  exports.createRedrawable = createRedrawable;
779
898
  exports.deref = deref;
780
899
  exports.h = h;
781
- exports.isKTRef = isKTRef;
900
+ exports.isComputed = isComputed;
901
+ exports.isKT = isKT;
902
+ exports.isRef = isRef;
782
903
  exports.jsx = jsx;
783
904
  exports.jsxDEV = jsxDEV;
784
905
  exports.jsxs = jsxs;
785
906
  exports.ref = ref;
786
907
  exports.surfaceRef = surfaceRef;
908
+ exports.toRef = toRef;
787
909
 
788
910
  return exports;
789
911