@ktjs/core 0.24.4 → 0.26.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.
@@ -78,6 +78,12 @@ var __ktjs_core__ = (function (exports) {
78
78
  element.addEventListener(eventName, () => (valueRef.value = element[propName]));
79
79
  };
80
80
 
81
+ // String manipulation utilities
82
+ /**
83
+ * Default empty function
84
+ */
85
+ const $emptyFn = (() => true);
86
+
81
87
  if (typeof Symbol === 'undefined') {
82
88
  window.Symbol = function Symbol(description) {
83
89
  return `@@SYMBOL_${description || ''}_${$random().toString(36).slice(2)}`;
@@ -85,7 +91,7 @@ var __ktjs_core__ = (function (exports) {
85
91
  }
86
92
 
87
93
  // Shared utilities and cached native methods for kt.js framework
88
- Object.defineProperty(window, '__ktjs__', { value: '0.22.6' });
94
+ Object.defineProperty(window, '__ktjs__', { value: '0.22.8' });
89
95
 
90
96
  // export const KT_TYPE_REF = 1 as const;
91
97
  // export const KT_TYPE_COMPUTED = 2 as const;
@@ -136,19 +142,41 @@ var __ktjs_core__ = (function (exports) {
136
142
  };
137
143
 
138
144
  const defaultHandler = (element, key, value) => element.setAttribute(key, value);
145
+ const setElementStyle = (element, style) => {
146
+ if (typeof style === 'string') {
147
+ element.style.cssText = style;
148
+ return;
149
+ }
150
+ for (const key in style) {
151
+ element.style[key] = style[key];
152
+ }
153
+ };
139
154
  function attrIsObject(element, attr) {
140
155
  const classValue = attr.class || attr.className;
141
156
  if (classValue !== undefined) {
142
- element.setAttribute('class', classValue);
157
+ if (isKT(classValue)) {
158
+ element.setAttribute('class', classValue.value);
159
+ classValue.addOnChange((v) => element.setAttribute('class', v));
160
+ }
161
+ else {
162
+ // todo 这里要让undefined 排除出reactify类型工具之外
163
+ element.setAttribute('class', classValue);
164
+ }
143
165
  }
166
+ // todo 这里加入reactive支持
167
+ // todo 类型定义也要支持reactive响应式
144
168
  const style = attr.style;
145
169
  if (style) {
146
170
  if (typeof style === 'string') {
147
171
  element.setAttribute('style', style);
148
172
  }
149
173
  else if (typeof style === 'object') {
150
- for (const key in style) {
151
- element.style[key] = style[key];
174
+ if (isKT(style)) {
175
+ setElementStyle(element, style.value);
176
+ style.addOnChange((v) => setElementStyle(element, v));
177
+ }
178
+ else {
179
+ setElementStyle(element, style);
152
180
  }
153
181
  }
154
182
  }
@@ -180,8 +208,14 @@ var __ktjs_core__ = (function (exports) {
180
208
  }
181
209
  // normal attributes
182
210
  else {
183
- // todo 这里也可以绑定ref的
184
- (handlers[key] || defaultHandler)(element, key, o);
211
+ const handler = handlers[key] || defaultHandler;
212
+ if (isKT(o)) {
213
+ handler(element, key, o.value);
214
+ o.addOnChange((v) => handler(element, key, v));
215
+ }
216
+ else {
217
+ handler(element, key, o);
218
+ }
185
219
  }
186
220
  }
187
221
  }
@@ -470,6 +504,51 @@ var __ktjs_core__ = (function (exports) {
470
504
  return new KTComputed(computeFn, reactives);
471
505
  }
472
506
 
507
+ /**
508
+ * Register a reactive effect with options.
509
+ * @param effectFn The effect function to run when dependencies change
510
+ * @param reactives The reactive dependencies
511
+ * @param options Effect options: lazy, onCleanup, debugName
512
+ * @returns stop function to remove all listeners
513
+ */
514
+ function effect(effectFn, reactives, options) {
515
+ const { lazy = false, onCleanup = $emptyFn, debugName = '' } = Object(options);
516
+ let active = true;
517
+ const run = () => {
518
+ if (!active) {
519
+ return;
520
+ }
521
+ // cleanup before rerun
522
+ onCleanup();
523
+ try {
524
+ effectFn();
525
+ }
526
+ catch (err) {
527
+ console.debug('[kt.js debug]','effect error:', debugName, err);
528
+ }
529
+ };
530
+ // subscribe to dependencies
531
+ for (let i = 0; i < reactives.length; i++) {
532
+ reactives[i].addOnChange(run);
533
+ }
534
+ // auto run unless lazy
535
+ if (!lazy) {
536
+ run();
537
+ }
538
+ // stop function
539
+ return () => {
540
+ if (!active) {
541
+ return;
542
+ }
543
+ active = false;
544
+ for (let i = 0; i < reactives.length; i++) {
545
+ reactives[i].removeOnChange(run);
546
+ }
547
+ // final cleanup
548
+ onCleanup();
549
+ };
550
+ }
551
+
473
552
  const toReactive = (value, onChange) => {
474
553
  if (isKT(value)) {
475
554
  if (onChange) {
@@ -484,7 +563,7 @@ var __ktjs_core__ = (function (exports) {
484
563
 
485
564
  function applyKModel(element, valueRef) {
486
565
  if (!isKT(valueRef)) {
487
- console.warn('[kt.js warn] k-model value must be a KTRef.');
566
+ console.warn('[kt.js warn]','k-model value must be a KTRef.');
488
567
  return;
489
568
  }
490
569
  if (element instanceof HTMLInputElement) {
@@ -502,7 +581,7 @@ var __ktjs_core__ = (function (exports) {
502
581
  applyModel(element, valueRef, 'value', 'input');
503
582
  }
504
583
  else {
505
- console.warn('[kt.js warn] not supported element for k-model:');
584
+ console.warn('[kt.js warn]','not supported element for k-model:');
506
585
  }
507
586
  }
508
587
 
@@ -520,7 +599,7 @@ var __ktjs_core__ = (function (exports) {
520
599
  * ## About
521
600
  * @package @ktjs/core
522
601
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
523
- * @version 0.24.4 (Last Update: 2026.02.05 13:57:50.861)
602
+ * @version 0.26.1 (Last Update: 2026.02.05 17:35:29.547)
524
603
  * @license MIT
525
604
  * @link https://github.com/baendlorel/kt.js
526
605
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -901,6 +980,7 @@ var __ktjs_core__ = (function (exports) {
901
980
  exports.createElement = h;
902
981
  exports.createRedrawable = createRedrawable;
903
982
  exports.deref = deref;
983
+ exports.effect = effect;
904
984
  exports.h = h;
905
985
  exports.isComputed = isComputed;
906
986
  exports.isKT = isKT;
@@ -78,6 +78,12 @@ var __ktjs_core__ = (function (exports) {
78
78
  element.addEventListener(eventName, () => (valueRef.value = element[propName]));
79
79
  };
80
80
 
81
+ // String manipulation utilities
82
+ /**
83
+ * Default empty function
84
+ */
85
+ const $emptyFn = (() => true);
86
+
81
87
  if (typeof Symbol === 'undefined') {
82
88
  window.Symbol = function Symbol(description) {
83
89
  return `@@SYMBOL_${description || ''}_${$random().toString(36).slice(2)}`;
@@ -85,7 +91,7 @@ var __ktjs_core__ = (function (exports) {
85
91
  }
86
92
 
87
93
  // Shared utilities and cached native methods for kt.js framework
88
- Object.defineProperty(window, '__ktjs__', { value: '0.22.6' });
94
+ Object.defineProperty(window, '__ktjs__', { value: '0.22.8' });
89
95
 
90
96
  // export const KT_TYPE_REF = 1 as const;
91
97
  // export const KT_TYPE_COMPUTED = 2 as const;
@@ -138,19 +144,41 @@ var __ktjs_core__ = (function (exports) {
138
144
  var defaultHandler = function (element, key, value) {
139
145
  return element.setAttribute(key, value);
140
146
  };
147
+ var setElementStyle = function (element, style) {
148
+ if (typeof style === 'string') {
149
+ element.style.cssText = style;
150
+ return;
151
+ }
152
+ for (var key in style) {
153
+ element.style[key] = style[key];
154
+ }
155
+ };
141
156
  function attrIsObject(element, attr) {
142
157
  var classValue = attr.class || attr.className;
143
158
  if (classValue !== undefined) {
144
- element.setAttribute('class', classValue);
159
+ if (isKT(classValue)) {
160
+ element.setAttribute('class', classValue.value);
161
+ classValue.addOnChange(function (v) { return element.setAttribute('class', v); });
162
+ }
163
+ else {
164
+ // todo 这里要让undefined 排除出reactify类型工具之外
165
+ element.setAttribute('class', classValue);
166
+ }
145
167
  }
168
+ // todo 这里加入reactive支持
169
+ // todo 类型定义也要支持reactive响应式
146
170
  var style = attr.style;
147
171
  if (style) {
148
172
  if (typeof style === 'string') {
149
173
  element.setAttribute('style', style);
150
174
  }
151
175
  else if (typeof style === 'object') {
152
- for (var key in style) {
153
- element.style[key] = style[key];
176
+ if (isKT(style)) {
177
+ setElementStyle(element, style.value);
178
+ style.addOnChange(function (v) { return setElementStyle(element, v); });
179
+ }
180
+ else {
181
+ setElementStyle(element, style);
154
182
  }
155
183
  }
156
184
  }
@@ -164,7 +192,7 @@ var __ktjs_core__ = (function (exports) {
164
192
  element.innerHTML = html;
165
193
  }
166
194
  }
167
- for (var key in attr) {
195
+ var _loop_1 = function (key) {
168
196
  if (key === 'k-if' ||
169
197
  key === 'k-model' ||
170
198
  key === 'ref' ||
@@ -173,7 +201,7 @@ var __ktjs_core__ = (function (exports) {
173
201
  key === 'style' ||
174
202
  key === 'children' ||
175
203
  key === 'k-html') {
176
- continue;
204
+ return "continue";
177
205
  }
178
206
  var o = attr[key];
179
207
  // normal event handler
@@ -182,9 +210,18 @@ var __ktjs_core__ = (function (exports) {
182
210
  }
183
211
  // normal attributes
184
212
  else {
185
- // todo 这里也可以绑定ref的
186
- (handlers[key] || defaultHandler)(element, key, o);
213
+ var handler_1 = handlers[key] || defaultHandler;
214
+ if (isKT(o)) {
215
+ handler_1(element, key, o.value);
216
+ o.addOnChange(function (v) { return handler_1(element, key, v); });
217
+ }
218
+ else {
219
+ handler_1(element, key, o);
220
+ }
187
221
  }
222
+ };
223
+ for (var key in attr) {
224
+ _loop_1(key);
188
225
  }
189
226
  }
190
227
  function applyAttr(element, attr) {
@@ -470,6 +507,51 @@ var __ktjs_core__ = (function (exports) {
470
507
  return new KTComputed(computeFn, reactives);
471
508
  }
472
509
 
510
+ /**
511
+ * Register a reactive effect with options.
512
+ * @param effectFn The effect function to run when dependencies change
513
+ * @param reactives The reactive dependencies
514
+ * @param options Effect options: lazy, onCleanup, debugName
515
+ * @returns stop function to remove all listeners
516
+ */
517
+ function effect(effectFn, reactives, options) {
518
+ var _a = Object(options), _b = _a.lazy, lazy = _b === void 0 ? false : _b, _c = _a.onCleanup, onCleanup = _c === void 0 ? $emptyFn : _c, _d = _a.debugName, debugName = _d === void 0 ? '' : _d;
519
+ var active = true;
520
+ var run = function () {
521
+ if (!active) {
522
+ return;
523
+ }
524
+ // cleanup before rerun
525
+ onCleanup();
526
+ try {
527
+ effectFn();
528
+ }
529
+ catch (err) {
530
+ console.debug('[kt.js debug]','effect error:', debugName, err);
531
+ }
532
+ };
533
+ // subscribe to dependencies
534
+ for (var i = 0; i < reactives.length; i++) {
535
+ reactives[i].addOnChange(run);
536
+ }
537
+ // auto run unless lazy
538
+ if (!lazy) {
539
+ run();
540
+ }
541
+ // stop function
542
+ return function () {
543
+ if (!active) {
544
+ return;
545
+ }
546
+ active = false;
547
+ for (var i = 0; i < reactives.length; i++) {
548
+ reactives[i].removeOnChange(run);
549
+ }
550
+ // final cleanup
551
+ onCleanup();
552
+ };
553
+ }
554
+
473
555
  var toReactive = function (value, onChange) {
474
556
  if (isKT(value)) {
475
557
  if (onChange) {
@@ -484,7 +566,7 @@ var __ktjs_core__ = (function (exports) {
484
566
 
485
567
  function applyKModel(element, valueRef) {
486
568
  if (!isKT(valueRef)) {
487
- console.warn('[kt.js warn] k-model value must be a KTRef.');
569
+ console.warn('[kt.js warn]','k-model value must be a KTRef.');
488
570
  return;
489
571
  }
490
572
  if (element instanceof HTMLInputElement) {
@@ -502,7 +584,7 @@ var __ktjs_core__ = (function (exports) {
502
584
  applyModel(element, valueRef, 'value', 'input');
503
585
  }
504
586
  else {
505
- console.warn('[kt.js warn] not supported element for k-model:');
587
+ console.warn('[kt.js warn]','not supported element for k-model:');
506
588
  }
507
589
  }
508
590
 
@@ -520,7 +602,7 @@ var __ktjs_core__ = (function (exports) {
520
602
  * ## About
521
603
  * @package @ktjs/core
522
604
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
523
- * @version 0.24.4 (Last Update: 2026.02.05 13:57:50.861)
605
+ * @version 0.26.1 (Last Update: 2026.02.05 17:35:29.547)
524
606
  * @license MIT
525
607
  * @link https://github.com/baendlorel/kt.js
526
608
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -908,6 +990,7 @@ var __ktjs_core__ = (function (exports) {
908
990
  exports.createElement = h;
909
991
  exports.createRedrawable = createRedrawable;
910
992
  exports.deref = deref;
993
+ exports.effect = effect;
911
994
  exports.h = h;
912
995
  exports.isComputed = isComputed;
913
996
  exports.isKT = isKT;
package/dist/index.mjs CHANGED
@@ -75,6 +75,12 @@ const applyModel = (element, valueRef, propName, eventName) => {
75
75
  element.addEventListener(eventName, () => (valueRef.value = element[propName]));
76
76
  };
77
77
 
78
+ // String manipulation utilities
79
+ /**
80
+ * Default empty function
81
+ */
82
+ const $emptyFn = (() => true);
83
+
78
84
  if (typeof Symbol === 'undefined') {
79
85
  window.Symbol = function Symbol(description) {
80
86
  return `@@SYMBOL_${description || ''}_${$random().toString(36).slice(2)}`;
@@ -82,7 +88,7 @@ if (typeof Symbol === 'undefined') {
82
88
  }
83
89
 
84
90
  // Shared utilities and cached native methods for kt.js framework
85
- Object.defineProperty(window, '__ktjs__', { value: '0.22.6' });
91
+ Object.defineProperty(window, '__ktjs__', { value: '0.22.8' });
86
92
 
87
93
  // export const KT_TYPE_REF = 1 as const;
88
94
  // export const KT_TYPE_COMPUTED = 2 as const;
@@ -133,19 +139,41 @@ const handlers = {
133
139
  };
134
140
 
135
141
  const defaultHandler = (element, key, value) => element.setAttribute(key, value);
142
+ const setElementStyle = (element, style) => {
143
+ if (typeof style === 'string') {
144
+ element.style.cssText = style;
145
+ return;
146
+ }
147
+ for (const key in style) {
148
+ element.style[key] = style[key];
149
+ }
150
+ };
136
151
  function attrIsObject(element, attr) {
137
152
  const classValue = attr.class || attr.className;
138
153
  if (classValue !== undefined) {
139
- element.setAttribute('class', classValue);
154
+ if (isKT(classValue)) {
155
+ element.setAttribute('class', classValue.value);
156
+ classValue.addOnChange((v) => element.setAttribute('class', v));
157
+ }
158
+ else {
159
+ // todo 这里要让undefined 排除出reactify类型工具之外
160
+ element.setAttribute('class', classValue);
161
+ }
140
162
  }
163
+ // todo 这里加入reactive支持
164
+ // todo 类型定义也要支持reactive响应式
141
165
  const style = attr.style;
142
166
  if (style) {
143
167
  if (typeof style === 'string') {
144
168
  element.setAttribute('style', style);
145
169
  }
146
170
  else if (typeof style === 'object') {
147
- for (const key in style) {
148
- element.style[key] = style[key];
171
+ if (isKT(style)) {
172
+ setElementStyle(element, style.value);
173
+ style.addOnChange((v) => setElementStyle(element, v));
174
+ }
175
+ else {
176
+ setElementStyle(element, style);
149
177
  }
150
178
  }
151
179
  }
@@ -177,8 +205,14 @@ function attrIsObject(element, attr) {
177
205
  }
178
206
  // normal attributes
179
207
  else {
180
- // todo 这里也可以绑定ref的
181
- (handlers[key] || defaultHandler)(element, key, o);
208
+ const handler = handlers[key] || defaultHandler;
209
+ if (isKT(o)) {
210
+ handler(element, key, o.value);
211
+ o.addOnChange((v) => handler(element, key, v));
212
+ }
213
+ else {
214
+ handler(element, key, o);
215
+ }
182
216
  }
183
217
  }
184
218
  }
@@ -467,6 +501,51 @@ function computed(computeFn, reactives) {
467
501
  return new KTComputed(computeFn, reactives);
468
502
  }
469
503
 
504
+ /**
505
+ * Register a reactive effect with options.
506
+ * @param effectFn The effect function to run when dependencies change
507
+ * @param reactives The reactive dependencies
508
+ * @param options Effect options: lazy, onCleanup, debugName
509
+ * @returns stop function to remove all listeners
510
+ */
511
+ function effect(effectFn, reactives, options) {
512
+ const { lazy = false, onCleanup = $emptyFn, debugName = '' } = Object(options);
513
+ let active = true;
514
+ const run = () => {
515
+ if (!active) {
516
+ return;
517
+ }
518
+ // cleanup before rerun
519
+ onCleanup();
520
+ try {
521
+ effectFn();
522
+ }
523
+ catch (err) {
524
+ console.debug('[kt.js debug]','effect error:', debugName, err);
525
+ }
526
+ };
527
+ // subscribe to dependencies
528
+ for (let i = 0; i < reactives.length; i++) {
529
+ reactives[i].addOnChange(run);
530
+ }
531
+ // auto run unless lazy
532
+ if (!lazy) {
533
+ run();
534
+ }
535
+ // stop function
536
+ return () => {
537
+ if (!active) {
538
+ return;
539
+ }
540
+ active = false;
541
+ for (let i = 0; i < reactives.length; i++) {
542
+ reactives[i].removeOnChange(run);
543
+ }
544
+ // final cleanup
545
+ onCleanup();
546
+ };
547
+ }
548
+
470
549
  const toReactive = (value, onChange) => {
471
550
  if (isKT(value)) {
472
551
  if (onChange) {
@@ -481,7 +560,7 @@ const toReactive = (value, onChange) => {
481
560
 
482
561
  function applyKModel(element, valueRef) {
483
562
  if (!isKT(valueRef)) {
484
- console.warn('[kt.js warn] k-model value must be a KTRef.');
563
+ console.warn('[kt.js warn]','k-model value must be a KTRef.');
485
564
  return;
486
565
  }
487
566
  if (element instanceof HTMLInputElement) {
@@ -499,7 +578,7 @@ function applyKModel(element, valueRef) {
499
578
  applyModel(element, valueRef, 'value', 'input');
500
579
  }
501
580
  else {
502
- console.warn('[kt.js warn] not supported element for k-model:');
581
+ console.warn('[kt.js warn]','not supported element for k-model:');
503
582
  }
504
583
  }
505
584
 
@@ -517,7 +596,7 @@ let creator = htmlCreator;
517
596
  * ## About
518
597
  * @package @ktjs/core
519
598
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
520
- * @version 0.24.4 (Last Update: 2026.02.05 13:57:50.861)
599
+ * @version 0.26.1 (Last Update: 2026.02.05 17:35:29.547)
521
600
  * @license MIT
522
601
  * @link https://github.com/baendlorel/kt.js
523
602
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -888,4 +967,4 @@ function getSequence(arr) {
888
967
  return result;
889
968
  }
890
969
 
891
- export { $modelOrRef, Fragment, KTAsync, KTComputed, KTFor, KTRef, computed, h as createElement, createRedrawable, deref, h, isComputed, isKT, isRef, jsx, jsxDEV, jsxs, ref, surfaceRef, toReactive, toRef };
970
+ export { $modelOrRef, Fragment, KTAsync, KTComputed, KTFor, KTRef, computed, h as createElement, createRedrawable, deref, effect, h, isComputed, isKT, isRef, jsx, jsxDEV, jsxs, ref, surfaceRef, toReactive, toRef };