@ktjs/core 0.21.1 → 0.22.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 +9 -4
- package/dist/index.iife.js +136 -100
- package/dist/index.legacy.js +133 -97
- package/dist/index.mjs +136 -100
- package/dist/jsx/index.d.ts +6 -3
- package/dist/jsx/index.mjs +136 -100
- package/dist/jsx/jsx-runtime.d.ts +6 -3
- package/dist/jsx/jsx-runtime.mjs +112 -76
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -3,14 +3,8 @@ const $isArray = Array.isArray;
|
|
|
3
3
|
const $entries = Object.entries;
|
|
4
4
|
const $isThenable = (o) => typeof o === 'object' && o !== null && typeof o.then === 'function';
|
|
5
5
|
|
|
6
|
-
// Error handling utilities
|
|
7
|
-
const $throw = (message) => {
|
|
8
|
-
throw new Error('@ktjs/shared: ' + message);
|
|
9
|
-
};
|
|
10
|
-
|
|
11
6
|
// DOM manipulation utilities
|
|
12
7
|
// # dom natives
|
|
13
|
-
const $replaceWith = Element.prototype.replaceWith;
|
|
14
8
|
/**
|
|
15
9
|
* & Remove `bind` because it is shockingly slower than wrapper
|
|
16
10
|
* & `window.document` is safe because it is not configurable and its setter is undefined
|
|
@@ -47,10 +41,108 @@ const $append = // for ie 9/10/11
|
|
|
47
41
|
}
|
|
48
42
|
};
|
|
49
43
|
const { get: $buttonDisabledGetter, set: $buttonDisabledSetter } = Object.getOwnPropertyDescriptor(HTMLButtonElement.prototype, 'disabled');
|
|
44
|
+
/**
|
|
45
|
+
* Used for `k-model`
|
|
46
|
+
*/
|
|
47
|
+
const applyModel = (element, valueRef, propName, eventName) => {
|
|
48
|
+
element[propName] = valueRef.value; // initialize
|
|
49
|
+
valueRef.addOnChange((newValue) => (element[propName] = newValue));
|
|
50
|
+
element.addEventListener(eventName, () => (valueRef.value = element[propName]));
|
|
51
|
+
};
|
|
50
52
|
|
|
51
53
|
// Shared utilities and cached native methods for kt.js framework
|
|
52
54
|
// Re-export all utilities
|
|
53
|
-
Object.defineProperty(window, '
|
|
55
|
+
Object.defineProperty(window, '__ktjs__', { value: '0.22.2' });
|
|
56
|
+
|
|
57
|
+
class KTRef {
|
|
58
|
+
/**
|
|
59
|
+
* Indicates that this is a KTRef instance
|
|
60
|
+
*/
|
|
61
|
+
isKT = true;
|
|
62
|
+
/**
|
|
63
|
+
* @internal
|
|
64
|
+
*/
|
|
65
|
+
_value;
|
|
66
|
+
/**
|
|
67
|
+
* @internal
|
|
68
|
+
*/
|
|
69
|
+
_onChanges;
|
|
70
|
+
constructor(_value, _onChanges) {
|
|
71
|
+
this._value = _value;
|
|
72
|
+
this._onChanges = _onChanges;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* If new value and old value are both nodes, the old one will be replaced in the DOM
|
|
76
|
+
*/
|
|
77
|
+
get value() {
|
|
78
|
+
return this._value;
|
|
79
|
+
}
|
|
80
|
+
set value(newValue) {
|
|
81
|
+
if (newValue === this._value) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
// replace the old node with the new one in the DOM if both are nodes
|
|
85
|
+
if (this._value instanceof Node && newValue instanceof Node) {
|
|
86
|
+
if (newValue.contains(this._value)) {
|
|
87
|
+
this._value.remove();
|
|
88
|
+
}
|
|
89
|
+
this._value.replaceWith(newValue);
|
|
90
|
+
}
|
|
91
|
+
const oldValue = this._value;
|
|
92
|
+
this._value = newValue;
|
|
93
|
+
for (let i = 0; i < this._onChanges.length; i++) {
|
|
94
|
+
this._onChanges[i](newValue, oldValue);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
addOnChange(callback) {
|
|
98
|
+
this._onChanges.push(callback);
|
|
99
|
+
}
|
|
100
|
+
removeOnChange(callback) {
|
|
101
|
+
for (let i = this._onChanges.length - 1; i >= 0; i--) {
|
|
102
|
+
if (this._onChanges[i] === callback) {
|
|
103
|
+
this._onChanges.splice(i, 1);
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const isKTRef = (obj) => {
|
|
111
|
+
return typeof obj === 'object' && obj !== null && obj.isKT === true;
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Reference to the created HTML element.
|
|
115
|
+
* - **Only** respond to `ref.value` changes, not reactive to internal changes of the element.
|
|
116
|
+
* - can alse be used to store normal values, but it is not reactive.
|
|
117
|
+
* @param value mostly an HTMLElement
|
|
118
|
+
*/
|
|
119
|
+
function ref(value, onChange) {
|
|
120
|
+
return new KTRef(value, onChange ? [onChange] : []);
|
|
121
|
+
}
|
|
122
|
+
function kcollect() {
|
|
123
|
+
const newObj = {};
|
|
124
|
+
const entries = $entries(this);
|
|
125
|
+
for (let i = 0; i < entries.length; i++) {
|
|
126
|
+
const key = entries[i][0];
|
|
127
|
+
if (key === 'kcollect') {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
newObj[key] = entries[i][1].value;
|
|
131
|
+
}
|
|
132
|
+
return newObj;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Make all first-level properties of the object a `KTRef`.
|
|
136
|
+
* - `obj.a.b` is not reactive
|
|
137
|
+
*/
|
|
138
|
+
const surfaceRef = (obj) => {
|
|
139
|
+
const entries = $entries(obj);
|
|
140
|
+
const newObj = { kcollect };
|
|
141
|
+
for (let i = 0; i < entries.length; i++) {
|
|
142
|
+
newObj[entries[i][0]] = ref(entries[i][1]);
|
|
143
|
+
}
|
|
144
|
+
return newObj;
|
|
145
|
+
};
|
|
54
146
|
|
|
55
147
|
const booleanHandler = (element, key, value) => {
|
|
56
148
|
if (key in element) {
|
|
@@ -116,6 +208,7 @@ function attrIsObject(element, attr) {
|
|
|
116
208
|
key === 'style' ||
|
|
117
209
|
key === 'children' ||
|
|
118
210
|
key === 'k-if' ||
|
|
211
|
+
key.startsWith('k-model') ||
|
|
119
212
|
key === 'ref') {
|
|
120
213
|
continue;
|
|
121
214
|
}
|
|
@@ -138,7 +231,7 @@ function applyAttr(element, attr) {
|
|
|
138
231
|
attrIsObject(element, attr);
|
|
139
232
|
}
|
|
140
233
|
else {
|
|
141
|
-
throw new Error('kt.js
|
|
234
|
+
throw new Error('[kt.js error] attr must be an object.');
|
|
142
235
|
}
|
|
143
236
|
}
|
|
144
237
|
|
|
@@ -193,6 +286,30 @@ function applyContent(element, content) {
|
|
|
193
286
|
}
|
|
194
287
|
}
|
|
195
288
|
|
|
289
|
+
function applyKModel(element, valueRef) {
|
|
290
|
+
if (!isKTRef(valueRef)) {
|
|
291
|
+
console.warn('[kt.js warn] k-model value must be a KTRef.');
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
if (element instanceof HTMLInputElement) {
|
|
295
|
+
if (element.type === 'radio' || element.type === 'checkbox') {
|
|
296
|
+
applyModel(element, valueRef, 'checked', 'change');
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
applyModel(element, valueRef, 'value', 'input');
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
else if (element instanceof HTMLSelectElement) {
|
|
303
|
+
applyModel(element, valueRef, 'value', 'change');
|
|
304
|
+
}
|
|
305
|
+
else if (element instanceof HTMLTextAreaElement) {
|
|
306
|
+
applyModel(element, valueRef, 'value', 'input');
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
console.warn('[kt.js warn] not supported element for k-model:');
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
196
313
|
const htmlCreator = (tag) => document.createElement(tag);
|
|
197
314
|
const svgCreator = (tag) => document.createElementNS('http://www.w3.org/2000/svg', tag);
|
|
198
315
|
const mathMLCreator = (tag) => document.createElementNS('http://www.w3.org/1998/Math/MathML', tag);
|
|
@@ -210,7 +327,7 @@ const MATHML_ATTR_FLAG = '__kt_mathml__';
|
|
|
210
327
|
* ## About
|
|
211
328
|
* @package @ktjs/core
|
|
212
329
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
213
|
-
* @version 0.
|
|
330
|
+
* @version 0.22.2 (Last Update: 2026.02.02 20:28:37.901)
|
|
214
331
|
* @license MIT
|
|
215
332
|
* @link https://github.com/baendlorel/kt.js
|
|
216
333
|
* @link https://baendlorel.github.io/ Welcome to my site!
|
|
@@ -219,7 +336,7 @@ const MATHML_ATTR_FLAG = '__kt_mathml__';
|
|
|
219
336
|
*/
|
|
220
337
|
const h = (tag, attr, content) => {
|
|
221
338
|
if (typeof tag !== 'string') {
|
|
222
|
-
|
|
339
|
+
throw new Error('[kt.js error] tagName must be a string.');
|
|
223
340
|
}
|
|
224
341
|
if (attr) {
|
|
225
342
|
if (SVG_ATTR_FLAG in attr) {
|
|
@@ -239,97 +356,16 @@ const h = (tag, attr, content) => {
|
|
|
239
356
|
// * Handle content
|
|
240
357
|
applyAttr(element, attr);
|
|
241
358
|
applyContent(element, content);
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Indicates that this is a KTRef instance
|
|
248
|
-
*/
|
|
249
|
-
isKT = true;
|
|
250
|
-
/**
|
|
251
|
-
* @internal
|
|
252
|
-
*/
|
|
253
|
-
_value;
|
|
254
|
-
/**
|
|
255
|
-
* @internal
|
|
256
|
-
*/
|
|
257
|
-
_onChanges;
|
|
258
|
-
constructor(_value, _onChanges) {
|
|
259
|
-
this._value = _value;
|
|
260
|
-
this._onChanges = _onChanges;
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* If new value and old value are both nodes, the old one will be replaced in the DOM
|
|
264
|
-
*/
|
|
265
|
-
get value() {
|
|
266
|
-
return this._value;
|
|
267
|
-
}
|
|
268
|
-
set value(newValue) {
|
|
269
|
-
if (newValue === this._value) {
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
// replace the old node with the new one in the DOM if both are nodes
|
|
273
|
-
if (this._value instanceof Node && newValue instanceof Node) {
|
|
274
|
-
if (newValue.contains(this._value)) {
|
|
275
|
-
this._value.remove();
|
|
276
|
-
}
|
|
277
|
-
this._value.replaceWith(newValue);
|
|
278
|
-
}
|
|
279
|
-
const oldValue = this._value;
|
|
280
|
-
this._value = newValue;
|
|
281
|
-
for (let i = 0; i < this._onChanges.length; i++) {
|
|
282
|
-
this._onChanges[i](newValue, oldValue);
|
|
359
|
+
if (typeof attr === 'object' && attr !== null && 'k-model' in attr) {
|
|
360
|
+
const kmodel = attr['k-model'];
|
|
361
|
+
if (isKTRef(kmodel)) {
|
|
362
|
+
applyKModel(element, kmodel);
|
|
283
363
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
this._onChanges.push(callback);
|
|
287
|
-
}
|
|
288
|
-
removeOnChange(callback) {
|
|
289
|
-
for (let i = this._onChanges.length - 1; i >= 0; i--) {
|
|
290
|
-
if (this._onChanges[i] === callback) {
|
|
291
|
-
this._onChanges.splice(i, 1);
|
|
292
|
-
return true;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
return false;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
const isKTRef = (obj) => {
|
|
299
|
-
return typeof obj === 'object' && obj !== null && obj.isKT === true;
|
|
300
|
-
};
|
|
301
|
-
/**
|
|
302
|
-
* Reference to the created HTML element.
|
|
303
|
-
* - **Only** respond to `ref.value` changes, not reactive to internal changes of the element.
|
|
304
|
-
* - can alse be used to store normal values, but it is not reactive.
|
|
305
|
-
* @param value mostly an HTMLElement
|
|
306
|
-
*/
|
|
307
|
-
function ref(value, onChange) {
|
|
308
|
-
return new KTRef(value, onChange ? [onChange] : []);
|
|
309
|
-
}
|
|
310
|
-
function kcollect() {
|
|
311
|
-
const newObj = {};
|
|
312
|
-
const entries = $entries(this);
|
|
313
|
-
for (let i = 0; i < entries.length; i++) {
|
|
314
|
-
const key = entries[i][0];
|
|
315
|
-
if (key === 'kcollect') {
|
|
316
|
-
continue;
|
|
364
|
+
else {
|
|
365
|
+
throw new Error('[kt.js error] k-model value must be a KTRef.');
|
|
317
366
|
}
|
|
318
|
-
newObj[key] = entries[i][1].value;
|
|
319
|
-
}
|
|
320
|
-
return newObj;
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* Make all first-level properties of the object a `KTRef`.
|
|
324
|
-
* - `obj.a.b` is not reactive
|
|
325
|
-
*/
|
|
326
|
-
const surfaceRef = (obj) => {
|
|
327
|
-
const entries = $entries(obj);
|
|
328
|
-
const newObj = { kcollect };
|
|
329
|
-
for (let i = 0; i < entries.length; i++) {
|
|
330
|
-
newObj[entries[i][0]] = ref(entries[i][1]);
|
|
331
367
|
}
|
|
332
|
-
return
|
|
368
|
+
return element;
|
|
333
369
|
};
|
|
334
370
|
|
|
335
371
|
const dummyRef = { value: null };
|
|
@@ -360,7 +396,7 @@ function jsx(tag, props) {
|
|
|
360
396
|
}
|
|
361
397
|
const oldEl = el;
|
|
362
398
|
el = newValue ? create(tag, props) : placeholder();
|
|
363
|
-
|
|
399
|
+
oldEl.replaceWith(el);
|
|
364
400
|
maybeDummyRef.value = el;
|
|
365
401
|
});
|
|
366
402
|
condition = kif.value;
|
|
@@ -381,7 +417,7 @@ function jsx(tag, props) {
|
|
|
381
417
|
* Note: kt.js doesn't have a real Fragment concept,
|
|
382
418
|
*/
|
|
383
419
|
function Fragment(_props) {
|
|
384
|
-
throw new Error("kt.js doesn't have a Fragment concept");
|
|
420
|
+
throw new Error("[kt.js error] doesn't have a Fragment concept");
|
|
385
421
|
// const { children } = props ?? {};
|
|
386
422
|
// if (!children) {
|
|
387
423
|
// return ;
|
package/dist/jsx/index.d.ts
CHANGED
|
@@ -66,12 +66,15 @@ interface KTBaseAttribute {
|
|
|
66
66
|
// # kt-specific attributes
|
|
67
67
|
ref?: KTRef<JSX.Element>;
|
|
68
68
|
|
|
69
|
-
// todo 是否要让k-if是KTRef的时候具备响应能力?
|
|
70
69
|
/**
|
|
71
70
|
* If a `KTRef` is bound, it will be reactive; otherwise, it will be static.
|
|
72
71
|
*/
|
|
73
72
|
'k-if'?: any;
|
|
74
|
-
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Register two-way data binding between an input element and a KTRef.
|
|
76
|
+
* - Default to regist `input` event and `value` property(`checked` for checkboxes and radios).
|
|
77
|
+
*/
|
|
75
78
|
'k-model'?: KTRef<any>;
|
|
76
79
|
|
|
77
80
|
// # normal HTML attributes
|
|
@@ -143,7 +146,7 @@ type KTAttribute = KTBaseAttribute & KTPrefixedEventHandlers;
|
|
|
143
146
|
* ## About
|
|
144
147
|
* @package @ktjs/core
|
|
145
148
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
146
|
-
* @version 0.
|
|
149
|
+
* @version 0.22.2 (Last Update: 2026.02.02 20:28:37.901)
|
|
147
150
|
* @license MIT
|
|
148
151
|
* @link https://github.com/baendlorel/kt.js
|
|
149
152
|
* @link https://baendlorel.github.io/ Welcome to my site!
|
package/dist/jsx/index.mjs
CHANGED
|
@@ -3,14 +3,8 @@ const $isArray = Array.isArray;
|
|
|
3
3
|
const $entries = Object.entries;
|
|
4
4
|
const $isThenable = (o) => typeof o === 'object' && o !== null && typeof o.then === 'function';
|
|
5
5
|
|
|
6
|
-
// Error handling utilities
|
|
7
|
-
const $throw = (message) => {
|
|
8
|
-
throw new Error('@ktjs/shared: ' + message);
|
|
9
|
-
};
|
|
10
|
-
|
|
11
6
|
// DOM manipulation utilities
|
|
12
7
|
// # dom natives
|
|
13
|
-
const $replaceWith = Element.prototype.replaceWith;
|
|
14
8
|
/**
|
|
15
9
|
* & Remove `bind` because it is shockingly slower than wrapper
|
|
16
10
|
* & `window.document` is safe because it is not configurable and its setter is undefined
|
|
@@ -47,10 +41,108 @@ const $append = // for ie 9/10/11
|
|
|
47
41
|
}
|
|
48
42
|
};
|
|
49
43
|
const { get: $buttonDisabledGetter, set: $buttonDisabledSetter } = Object.getOwnPropertyDescriptor(HTMLButtonElement.prototype, 'disabled');
|
|
44
|
+
/**
|
|
45
|
+
* Used for `k-model`
|
|
46
|
+
*/
|
|
47
|
+
const applyModel = (element, valueRef, propName, eventName) => {
|
|
48
|
+
element[propName] = valueRef.value; // initialize
|
|
49
|
+
valueRef.addOnChange((newValue) => (element[propName] = newValue));
|
|
50
|
+
element.addEventListener(eventName, () => (valueRef.value = element[propName]));
|
|
51
|
+
};
|
|
50
52
|
|
|
51
53
|
// Shared utilities and cached native methods for kt.js framework
|
|
52
54
|
// Re-export all utilities
|
|
53
|
-
Object.defineProperty(window, '
|
|
55
|
+
Object.defineProperty(window, '__ktjs__', { value: '0.22.2' });
|
|
56
|
+
|
|
57
|
+
class KTRef {
|
|
58
|
+
/**
|
|
59
|
+
* Indicates that this is a KTRef instance
|
|
60
|
+
*/
|
|
61
|
+
isKT = true;
|
|
62
|
+
/**
|
|
63
|
+
* @internal
|
|
64
|
+
*/
|
|
65
|
+
_value;
|
|
66
|
+
/**
|
|
67
|
+
* @internal
|
|
68
|
+
*/
|
|
69
|
+
_onChanges;
|
|
70
|
+
constructor(_value, _onChanges) {
|
|
71
|
+
this._value = _value;
|
|
72
|
+
this._onChanges = _onChanges;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* If new value and old value are both nodes, the old one will be replaced in the DOM
|
|
76
|
+
*/
|
|
77
|
+
get value() {
|
|
78
|
+
return this._value;
|
|
79
|
+
}
|
|
80
|
+
set value(newValue) {
|
|
81
|
+
if (newValue === this._value) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
// replace the old node with the new one in the DOM if both are nodes
|
|
85
|
+
if (this._value instanceof Node && newValue instanceof Node) {
|
|
86
|
+
if (newValue.contains(this._value)) {
|
|
87
|
+
this._value.remove();
|
|
88
|
+
}
|
|
89
|
+
this._value.replaceWith(newValue);
|
|
90
|
+
}
|
|
91
|
+
const oldValue = this._value;
|
|
92
|
+
this._value = newValue;
|
|
93
|
+
for (let i = 0; i < this._onChanges.length; i++) {
|
|
94
|
+
this._onChanges[i](newValue, oldValue);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
addOnChange(callback) {
|
|
98
|
+
this._onChanges.push(callback);
|
|
99
|
+
}
|
|
100
|
+
removeOnChange(callback) {
|
|
101
|
+
for (let i = this._onChanges.length - 1; i >= 0; i--) {
|
|
102
|
+
if (this._onChanges[i] === callback) {
|
|
103
|
+
this._onChanges.splice(i, 1);
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const isKTRef = (obj) => {
|
|
111
|
+
return typeof obj === 'object' && obj !== null && obj.isKT === true;
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Reference to the created HTML element.
|
|
115
|
+
* - **Only** respond to `ref.value` changes, not reactive to internal changes of the element.
|
|
116
|
+
* - can alse be used to store normal values, but it is not reactive.
|
|
117
|
+
* @param value mostly an HTMLElement
|
|
118
|
+
*/
|
|
119
|
+
function ref(value, onChange) {
|
|
120
|
+
return new KTRef(value, onChange ? [onChange] : []);
|
|
121
|
+
}
|
|
122
|
+
function kcollect() {
|
|
123
|
+
const newObj = {};
|
|
124
|
+
const entries = $entries(this);
|
|
125
|
+
for (let i = 0; i < entries.length; i++) {
|
|
126
|
+
const key = entries[i][0];
|
|
127
|
+
if (key === 'kcollect') {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
newObj[key] = entries[i][1].value;
|
|
131
|
+
}
|
|
132
|
+
return newObj;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Make all first-level properties of the object a `KTRef`.
|
|
136
|
+
* - `obj.a.b` is not reactive
|
|
137
|
+
*/
|
|
138
|
+
const surfaceRef = (obj) => {
|
|
139
|
+
const entries = $entries(obj);
|
|
140
|
+
const newObj = { kcollect };
|
|
141
|
+
for (let i = 0; i < entries.length; i++) {
|
|
142
|
+
newObj[entries[i][0]] = ref(entries[i][1]);
|
|
143
|
+
}
|
|
144
|
+
return newObj;
|
|
145
|
+
};
|
|
54
146
|
|
|
55
147
|
const booleanHandler = (element, key, value) => {
|
|
56
148
|
if (key in element) {
|
|
@@ -116,6 +208,7 @@ function attrIsObject(element, attr) {
|
|
|
116
208
|
key === 'style' ||
|
|
117
209
|
key === 'children' ||
|
|
118
210
|
key === 'k-if' ||
|
|
211
|
+
key.startsWith('k-model') ||
|
|
119
212
|
key === 'ref') {
|
|
120
213
|
continue;
|
|
121
214
|
}
|
|
@@ -138,7 +231,7 @@ function applyAttr(element, attr) {
|
|
|
138
231
|
attrIsObject(element, attr);
|
|
139
232
|
}
|
|
140
233
|
else {
|
|
141
|
-
throw new Error('kt.js
|
|
234
|
+
throw new Error('[kt.js error] attr must be an object.');
|
|
142
235
|
}
|
|
143
236
|
}
|
|
144
237
|
|
|
@@ -193,6 +286,30 @@ function applyContent(element, content) {
|
|
|
193
286
|
}
|
|
194
287
|
}
|
|
195
288
|
|
|
289
|
+
function applyKModel(element, valueRef) {
|
|
290
|
+
if (!isKTRef(valueRef)) {
|
|
291
|
+
console.warn('[kt.js warn] k-model value must be a KTRef.');
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
if (element instanceof HTMLInputElement) {
|
|
295
|
+
if (element.type === 'radio' || element.type === 'checkbox') {
|
|
296
|
+
applyModel(element, valueRef, 'checked', 'change');
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
applyModel(element, valueRef, 'value', 'input');
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
else if (element instanceof HTMLSelectElement) {
|
|
303
|
+
applyModel(element, valueRef, 'value', 'change');
|
|
304
|
+
}
|
|
305
|
+
else if (element instanceof HTMLTextAreaElement) {
|
|
306
|
+
applyModel(element, valueRef, 'value', 'input');
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
console.warn('[kt.js warn] not supported element for k-model:');
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
196
313
|
const htmlCreator = (tag) => document.createElement(tag);
|
|
197
314
|
const svgCreator = (tag) => document.createElementNS('http://www.w3.org/2000/svg', tag);
|
|
198
315
|
const mathMLCreator = (tag) => document.createElementNS('http://www.w3.org/1998/Math/MathML', tag);
|
|
@@ -210,7 +327,7 @@ const MATHML_ATTR_FLAG = '__kt_mathml__';
|
|
|
210
327
|
* ## About
|
|
211
328
|
* @package @ktjs/core
|
|
212
329
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
213
|
-
* @version 0.
|
|
330
|
+
* @version 0.22.2 (Last Update: 2026.02.02 20:28:37.901)
|
|
214
331
|
* @license MIT
|
|
215
332
|
* @link https://github.com/baendlorel/kt.js
|
|
216
333
|
* @link https://baendlorel.github.io/ Welcome to my site!
|
|
@@ -219,7 +336,7 @@ const MATHML_ATTR_FLAG = '__kt_mathml__';
|
|
|
219
336
|
*/
|
|
220
337
|
const h = (tag, attr, content) => {
|
|
221
338
|
if (typeof tag !== 'string') {
|
|
222
|
-
|
|
339
|
+
throw new Error('[kt.js error] tagName must be a string.');
|
|
223
340
|
}
|
|
224
341
|
if (attr) {
|
|
225
342
|
if (SVG_ATTR_FLAG in attr) {
|
|
@@ -239,97 +356,16 @@ const h = (tag, attr, content) => {
|
|
|
239
356
|
// * Handle content
|
|
240
357
|
applyAttr(element, attr);
|
|
241
358
|
applyContent(element, content);
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Indicates that this is a KTRef instance
|
|
248
|
-
*/
|
|
249
|
-
isKT = true;
|
|
250
|
-
/**
|
|
251
|
-
* @internal
|
|
252
|
-
*/
|
|
253
|
-
_value;
|
|
254
|
-
/**
|
|
255
|
-
* @internal
|
|
256
|
-
*/
|
|
257
|
-
_onChanges;
|
|
258
|
-
constructor(_value, _onChanges) {
|
|
259
|
-
this._value = _value;
|
|
260
|
-
this._onChanges = _onChanges;
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* If new value and old value are both nodes, the old one will be replaced in the DOM
|
|
264
|
-
*/
|
|
265
|
-
get value() {
|
|
266
|
-
return this._value;
|
|
267
|
-
}
|
|
268
|
-
set value(newValue) {
|
|
269
|
-
if (newValue === this._value) {
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
// replace the old node with the new one in the DOM if both are nodes
|
|
273
|
-
if (this._value instanceof Node && newValue instanceof Node) {
|
|
274
|
-
if (newValue.contains(this._value)) {
|
|
275
|
-
this._value.remove();
|
|
276
|
-
}
|
|
277
|
-
this._value.replaceWith(newValue);
|
|
278
|
-
}
|
|
279
|
-
const oldValue = this._value;
|
|
280
|
-
this._value = newValue;
|
|
281
|
-
for (let i = 0; i < this._onChanges.length; i++) {
|
|
282
|
-
this._onChanges[i](newValue, oldValue);
|
|
359
|
+
if (typeof attr === 'object' && attr !== null && 'k-model' in attr) {
|
|
360
|
+
const kmodel = attr['k-model'];
|
|
361
|
+
if (isKTRef(kmodel)) {
|
|
362
|
+
applyKModel(element, kmodel);
|
|
283
363
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
this._onChanges.push(callback);
|
|
287
|
-
}
|
|
288
|
-
removeOnChange(callback) {
|
|
289
|
-
for (let i = this._onChanges.length - 1; i >= 0; i--) {
|
|
290
|
-
if (this._onChanges[i] === callback) {
|
|
291
|
-
this._onChanges.splice(i, 1);
|
|
292
|
-
return true;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
return false;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
const isKTRef = (obj) => {
|
|
299
|
-
return typeof obj === 'object' && obj !== null && obj.isKT === true;
|
|
300
|
-
};
|
|
301
|
-
/**
|
|
302
|
-
* Reference to the created HTML element.
|
|
303
|
-
* - **Only** respond to `ref.value` changes, not reactive to internal changes of the element.
|
|
304
|
-
* - can alse be used to store normal values, but it is not reactive.
|
|
305
|
-
* @param value mostly an HTMLElement
|
|
306
|
-
*/
|
|
307
|
-
function ref(value, onChange) {
|
|
308
|
-
return new KTRef(value, onChange ? [onChange] : []);
|
|
309
|
-
}
|
|
310
|
-
function kcollect() {
|
|
311
|
-
const newObj = {};
|
|
312
|
-
const entries = $entries(this);
|
|
313
|
-
for (let i = 0; i < entries.length; i++) {
|
|
314
|
-
const key = entries[i][0];
|
|
315
|
-
if (key === 'kcollect') {
|
|
316
|
-
continue;
|
|
364
|
+
else {
|
|
365
|
+
throw new Error('[kt.js error] k-model value must be a KTRef.');
|
|
317
366
|
}
|
|
318
|
-
newObj[key] = entries[i][1].value;
|
|
319
|
-
}
|
|
320
|
-
return newObj;
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* Make all first-level properties of the object a `KTRef`.
|
|
324
|
-
* - `obj.a.b` is not reactive
|
|
325
|
-
*/
|
|
326
|
-
const surfaceRef = (obj) => {
|
|
327
|
-
const entries = $entries(obj);
|
|
328
|
-
const newObj = { kcollect };
|
|
329
|
-
for (let i = 0; i < entries.length; i++) {
|
|
330
|
-
newObj[entries[i][0]] = ref(entries[i][1]);
|
|
331
367
|
}
|
|
332
|
-
return
|
|
368
|
+
return element;
|
|
333
369
|
};
|
|
334
370
|
|
|
335
371
|
const dummyRef = { value: null };
|
|
@@ -360,7 +396,7 @@ function jsx(tag, props) {
|
|
|
360
396
|
}
|
|
361
397
|
const oldEl = el;
|
|
362
398
|
el = newValue ? create(tag, props) : placeholder();
|
|
363
|
-
|
|
399
|
+
oldEl.replaceWith(el);
|
|
364
400
|
maybeDummyRef.value = el;
|
|
365
401
|
});
|
|
366
402
|
condition = kif.value;
|
|
@@ -381,7 +417,7 @@ function jsx(tag, props) {
|
|
|
381
417
|
* Note: kt.js doesn't have a real Fragment concept,
|
|
382
418
|
*/
|
|
383
419
|
function Fragment(_props) {
|
|
384
|
-
throw new Error("kt.js doesn't have a Fragment concept");
|
|
420
|
+
throw new Error("[kt.js error] doesn't have a Fragment concept");
|
|
385
421
|
// const { children } = props ?? {};
|
|
386
422
|
// if (!children) {
|
|
387
423
|
// return ;
|
|
@@ -45,12 +45,15 @@ interface KTBaseAttribute {
|
|
|
45
45
|
// # kt-specific attributes
|
|
46
46
|
ref?: KTRef<JSX.Element>;
|
|
47
47
|
|
|
48
|
-
// todo 是否要让k-if是KTRef的时候具备响应能力?
|
|
49
48
|
/**
|
|
50
49
|
* If a `KTRef` is bound, it will be reactive; otherwise, it will be static.
|
|
51
50
|
*/
|
|
52
51
|
'k-if'?: any;
|
|
53
|
-
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Register two-way data binding between an input element and a KTRef.
|
|
55
|
+
* - Default to regist `input` event and `value` property(`checked` for checkboxes and radios).
|
|
56
|
+
*/
|
|
54
57
|
'k-model'?: KTRef<any>;
|
|
55
58
|
|
|
56
59
|
// # normal HTML attributes
|
|
@@ -122,7 +125,7 @@ type KTAttribute = KTBaseAttribute & KTPrefixedEventHandlers;
|
|
|
122
125
|
* ## About
|
|
123
126
|
* @package @ktjs/core
|
|
124
127
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
125
|
-
* @version 0.
|
|
128
|
+
* @version 0.22.2 (Last Update: 2026.02.02 20:28:37.901)
|
|
126
129
|
* @license MIT
|
|
127
130
|
* @link https://github.com/baendlorel/kt.js
|
|
128
131
|
* @link https://baendlorel.github.io/ Welcome to my site!
|