@ktjs/core 0.20.3 → 0.22.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.
- package/README.md +1 -453
- package/dist/index.d.ts +36 -4
- package/dist/index.iife.js +161 -89
- package/dist/index.legacy.js +159 -88
- package/dist/index.mjs +160 -90
- package/dist/jsx/index.d.ts +36 -3
- package/dist/jsx/index.mjs +160 -90
- package/dist/jsx/jsx-runtime.d.ts +19 -2
- package/dist/jsx/jsx-runtime.mjs +134 -89
- package/package.json +2 -2
|
@@ -23,6 +23,14 @@ declare class KTRef<T> {
|
|
|
23
23
|
removeOnChange(callback: RefChangeHandler<T>): boolean;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
type HTML<T extends (HTMLTag | SVGTag | MathMLTag) & otherstring> = T extends SVGTag
|
|
27
|
+
? SVGElementTagNameMap[T]
|
|
28
|
+
: T extends HTMLTag
|
|
29
|
+
? HTMLElementTagNameMap[T]
|
|
30
|
+
: T extends MathMLTag
|
|
31
|
+
? MathMLElementTagNameMap[T]
|
|
32
|
+
: HTMLElement;
|
|
33
|
+
|
|
26
34
|
type SingleContent = KTRef<any> | HTMLElement | Element | Node | string | number | boolean | null | undefined;
|
|
27
35
|
type KTAvailableContent = SingleContent | KTAvailableContent[];
|
|
28
36
|
type KTRawContent = KTAvailableContent | Promise<KTAvailableContent>;
|
|
@@ -36,8 +44,18 @@ interface KTBaseAttribute {
|
|
|
36
44
|
|
|
37
45
|
// # kt-specific attributes
|
|
38
46
|
ref?: KTRef<JSX.Element>;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* If a `KTRef` is bound, it will be reactive; otherwise, it will be static.
|
|
50
|
+
*/
|
|
39
51
|
'k-if'?: any;
|
|
40
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
|
+
*/
|
|
57
|
+
'k-model'?: KTRef<any>;
|
|
58
|
+
|
|
41
59
|
// # normal HTML attributes
|
|
42
60
|
id?: string;
|
|
43
61
|
class?: string;
|
|
@@ -97,7 +115,6 @@ type KTPrefixedEventHandlers = {
|
|
|
97
115
|
|
|
98
116
|
type KTAttribute = KTBaseAttribute & KTPrefixedEventHandlers;
|
|
99
117
|
|
|
100
|
-
type HTML<T extends (HTMLTag | SVGTag | MathMLTag) & otherstring> = T extends SVGTag ? SVGElementTagNameMap[T] : T extends HTMLTag ? HTMLElementTagNameMap[T] : T extends MathMLTag ? MathMLElementTagNameMap[T] : HTMLElement;
|
|
101
118
|
/**
|
|
102
119
|
* Create an enhanced HTMLElement.
|
|
103
120
|
* - Only supports HTMLElements, **NOT** SVGElements or other Elements.
|
|
@@ -108,7 +125,7 @@ type HTML<T extends (HTMLTag | SVGTag | MathMLTag) & otherstring> = T extends SV
|
|
|
108
125
|
* ## About
|
|
109
126
|
* @package @ktjs/core
|
|
110
127
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
111
|
-
* @version 0.
|
|
128
|
+
* @version 0.22.0 (Last Update: 2026.02.02 17:11:04.703)
|
|
112
129
|
* @license MIT
|
|
113
130
|
* @link https://github.com/baendlorel/kt.js
|
|
114
131
|
* @link https://baendlorel.github.io/ Welcome to my site!
|
package/dist/jsx/jsx-runtime.mjs
CHANGED
|
@@ -6,9 +6,6 @@ const $isThenable = (o) => typeof o === 'object' && o !== null && typeof o.then
|
|
|
6
6
|
const $throw = (message) => {
|
|
7
7
|
throw new Error('@ktjs/shared: ' + message);
|
|
8
8
|
};
|
|
9
|
-
|
|
10
|
-
// DOM manipulation utilities
|
|
11
|
-
// # dom natives
|
|
12
9
|
/**
|
|
13
10
|
* & Remove `bind` because it is shockingly slower than wrapper
|
|
14
11
|
* & `window.document` is safe because it is not configurable and its setter is undefined
|
|
@@ -48,7 +45,73 @@ const { get: $buttonDisabledGetter, set: $buttonDisabledSetter } = Object.getOwn
|
|
|
48
45
|
|
|
49
46
|
// Shared utilities and cached native methods for kt.js framework
|
|
50
47
|
// Re-export all utilities
|
|
51
|
-
Object.defineProperty(window, '@ktjs/shared', { value: '0.20.
|
|
48
|
+
Object.defineProperty(window, '@ktjs/shared', { value: '0.20.2' });
|
|
49
|
+
|
|
50
|
+
class KTRef {
|
|
51
|
+
/**
|
|
52
|
+
* Indicates that this is a KTRef instance
|
|
53
|
+
*/
|
|
54
|
+
isKT = true;
|
|
55
|
+
/**
|
|
56
|
+
* @internal
|
|
57
|
+
*/
|
|
58
|
+
_value;
|
|
59
|
+
/**
|
|
60
|
+
* @internal
|
|
61
|
+
*/
|
|
62
|
+
_onChanges;
|
|
63
|
+
constructor(_value, _onChanges) {
|
|
64
|
+
this._value = _value;
|
|
65
|
+
this._onChanges = _onChanges;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* If new value and old value are both nodes, the old one will be replaced in the DOM
|
|
69
|
+
*/
|
|
70
|
+
get value() {
|
|
71
|
+
return this._value;
|
|
72
|
+
}
|
|
73
|
+
set value(newValue) {
|
|
74
|
+
if (newValue === this._value) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
// replace the old node with the new one in the DOM if both are nodes
|
|
78
|
+
if (this._value instanceof Node && newValue instanceof Node) {
|
|
79
|
+
if (newValue.contains(this._value)) {
|
|
80
|
+
this._value.remove();
|
|
81
|
+
}
|
|
82
|
+
this._value.replaceWith(newValue);
|
|
83
|
+
}
|
|
84
|
+
const oldValue = this._value;
|
|
85
|
+
this._value = newValue;
|
|
86
|
+
for (let i = 0; i < this._onChanges.length; i++) {
|
|
87
|
+
this._onChanges[i](newValue, oldValue);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
addOnChange(callback) {
|
|
91
|
+
this._onChanges.push(callback);
|
|
92
|
+
}
|
|
93
|
+
removeOnChange(callback) {
|
|
94
|
+
for (let i = this._onChanges.length - 1; i >= 0; i--) {
|
|
95
|
+
if (this._onChanges[i] === callback) {
|
|
96
|
+
this._onChanges.splice(i, 1);
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const isKTRef = (obj) => {
|
|
104
|
+
return typeof obj === 'object' && obj !== null && obj.isKT === true;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Reference to the created HTML element.
|
|
108
|
+
* - **Only** respond to `ref.value` changes, not reactive to internal changes of the element.
|
|
109
|
+
* - can alse be used to store normal values, but it is not reactive.
|
|
110
|
+
* @param value mostly an HTMLElement
|
|
111
|
+
*/
|
|
112
|
+
function ref(value, onChange) {
|
|
113
|
+
return new KTRef(value, []);
|
|
114
|
+
}
|
|
52
115
|
|
|
53
116
|
const booleanHandler = (element, key, value) => {
|
|
54
117
|
if (key in element) {
|
|
@@ -114,6 +177,7 @@ function attrIsObject(element, attr) {
|
|
|
114
177
|
key === 'style' ||
|
|
115
178
|
key === 'children' ||
|
|
116
179
|
key === 'k-if' ||
|
|
180
|
+
key.startsWith('k-model') ||
|
|
117
181
|
key === 'ref') {
|
|
118
182
|
continue;
|
|
119
183
|
}
|
|
@@ -191,7 +255,29 @@ function applyContent(element, content) {
|
|
|
191
255
|
}
|
|
192
256
|
}
|
|
193
257
|
|
|
194
|
-
|
|
258
|
+
function register(element, valueRef, propName, eventName) {
|
|
259
|
+
element[propName] = valueRef.value; // initialize
|
|
260
|
+
valueRef.addOnChange((newValue) => (element[propName] = newValue));
|
|
261
|
+
element.addEventListener(eventName, () => (valueRef.value = element[propName]));
|
|
262
|
+
}
|
|
263
|
+
function applyModel(element, valueRef) {
|
|
264
|
+
if (element instanceof HTMLInputElement) {
|
|
265
|
+
if (element.type === 'radio' || element.type === 'checkbox') {
|
|
266
|
+
register(element, valueRef, 'checked', 'change');
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
register(element, valueRef, 'value', 'input');
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
else if (element instanceof HTMLSelectElement) {
|
|
273
|
+
register(element, valueRef, 'value', 'change');
|
|
274
|
+
}
|
|
275
|
+
else if (element instanceof HTMLTextAreaElement) {
|
|
276
|
+
register(element, valueRef, 'value', 'input');
|
|
277
|
+
}
|
|
278
|
+
console.warn('[kt.js warn] not supported element for k-model:', element.tagName);
|
|
279
|
+
}
|
|
280
|
+
|
|
195
281
|
const htmlCreator = (tag) => document.createElement(tag);
|
|
196
282
|
const svgCreator = (tag) => document.createElementNS('http://www.w3.org/2000/svg', tag);
|
|
197
283
|
const mathMLCreator = (tag) => document.createElementNS('http://www.w3.org/1998/Math/MathML', tag);
|
|
@@ -209,7 +295,7 @@ const MATHML_ATTR_FLAG = '__kt_mathml__';
|
|
|
209
295
|
* ## About
|
|
210
296
|
* @package @ktjs/core
|
|
211
297
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
212
|
-
* @version 0.
|
|
298
|
+
* @version 0.22.0 (Last Update: 2026.02.02 17:11:04.703)
|
|
213
299
|
* @license MIT
|
|
214
300
|
* @link https://github.com/baendlorel/kt.js
|
|
215
301
|
* @link https://baendlorel.github.io/ Welcome to my site!
|
|
@@ -238,101 +324,60 @@ const h = (tag, attr, content) => {
|
|
|
238
324
|
// * Handle content
|
|
239
325
|
applyAttr(element, attr);
|
|
240
326
|
applyContent(element, content);
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
// if (tag === 'math') {
|
|
246
|
-
// tempWrapper.innerHTML = element.outerHTML;
|
|
247
|
-
// return tempWrapper.firstChild as HTML<T>;
|
|
248
|
-
// }
|
|
249
|
-
return element;
|
|
250
|
-
};
|
|
251
|
-
|
|
252
|
-
class KTRef {
|
|
253
|
-
/**
|
|
254
|
-
* Indicates that this is a KTRef instance
|
|
255
|
-
*/
|
|
256
|
-
isKT = true;
|
|
257
|
-
/**
|
|
258
|
-
* @internal
|
|
259
|
-
*/
|
|
260
|
-
_value;
|
|
261
|
-
/**
|
|
262
|
-
* @internal
|
|
263
|
-
*/
|
|
264
|
-
_onChanges;
|
|
265
|
-
constructor(_value, _onChanges) {
|
|
266
|
-
this._value = _value;
|
|
267
|
-
this._onChanges = _onChanges;
|
|
268
|
-
}
|
|
269
|
-
/**
|
|
270
|
-
* If new value and old value are both nodes, the old one will be replaced in the DOM
|
|
271
|
-
*/
|
|
272
|
-
get value() {
|
|
273
|
-
return this._value;
|
|
274
|
-
}
|
|
275
|
-
set value(newValue) {
|
|
276
|
-
if (newValue === this._value) {
|
|
277
|
-
return;
|
|
327
|
+
if (typeof attr === 'object' && attr !== null && 'k-model' in attr) {
|
|
328
|
+
const kmodel = attr['k-model'];
|
|
329
|
+
if (isKTRef(kmodel)) {
|
|
330
|
+
applyModel(element, kmodel);
|
|
278
331
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
if (newValue.contains(this._value)) {
|
|
282
|
-
this._value.remove();
|
|
283
|
-
}
|
|
284
|
-
this._value.replaceWith(newValue);
|
|
285
|
-
}
|
|
286
|
-
const oldValue = this._value;
|
|
287
|
-
this._value = newValue;
|
|
288
|
-
for (let i = 0; i < this._onChanges.length; i++) {
|
|
289
|
-
this._onChanges[i](newValue, oldValue);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
addOnChange(callback) {
|
|
293
|
-
this._onChanges.push(callback);
|
|
294
|
-
}
|
|
295
|
-
removeOnChange(callback) {
|
|
296
|
-
for (let i = this._onChanges.length - 1; i >= 0; i--) {
|
|
297
|
-
if (this._onChanges[i] === callback) {
|
|
298
|
-
this._onChanges.splice(i, 1);
|
|
299
|
-
return true;
|
|
300
|
-
}
|
|
332
|
+
else {
|
|
333
|
+
$throw('k-model value must be a KTRef.');
|
|
301
334
|
}
|
|
302
|
-
return false;
|
|
303
335
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
* Reference to the created HTML element.
|
|
307
|
-
* - can alse be used to store normal values, but it is not reactive.
|
|
308
|
-
* @param value mostly an HTMLElement
|
|
309
|
-
*/
|
|
310
|
-
function ref(value, onChange) {
|
|
311
|
-
return new KTRef(value, []);
|
|
312
|
-
}
|
|
336
|
+
return element;
|
|
337
|
+
};
|
|
313
338
|
|
|
314
339
|
const dummyRef = { value: null };
|
|
340
|
+
const create = (tag, props) => {
|
|
341
|
+
if (typeof tag === 'function') {
|
|
342
|
+
return tag(props);
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
return h(tag, props, props.children);
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
const placeholder = () => document.createComment('k-if');
|
|
315
349
|
/**
|
|
316
350
|
* @param tag html tag or function component
|
|
317
351
|
* @param props properties/attributes
|
|
318
352
|
*/
|
|
319
353
|
function jsx(tag, props) {
|
|
320
|
-
const
|
|
354
|
+
const maybeDummyRef = isKTRef(props.ref) ? props.ref : dummyRef;
|
|
321
355
|
let el;
|
|
322
|
-
if ('k-if' in props
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
356
|
+
if ('k-if' in props) {
|
|
357
|
+
const kif = props['k-if'];
|
|
358
|
+
let condition = kif; // assume boolean by default
|
|
359
|
+
// Handle reactive k-if
|
|
360
|
+
if (isKTRef(kif)) {
|
|
361
|
+
kif.addOnChange((newValue, oldValue) => {
|
|
362
|
+
if (newValue === oldValue) {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
const oldEl = el;
|
|
366
|
+
el = newValue ? create(tag, props) : placeholder();
|
|
367
|
+
oldEl.replaceWith(el);
|
|
368
|
+
maybeDummyRef.value = el;
|
|
369
|
+
});
|
|
370
|
+
condition = kif.value;
|
|
371
|
+
}
|
|
372
|
+
if (!condition) {
|
|
373
|
+
// & make comment placeholder in case that ref might be redrawn later
|
|
374
|
+
el = placeholder();
|
|
375
|
+
maybeDummyRef.value = el;
|
|
376
|
+
return el;
|
|
377
|
+
}
|
|
334
378
|
}
|
|
335
|
-
|
|
379
|
+
el = create(tag, props);
|
|
380
|
+
maybeDummyRef.value = el;
|
|
336
381
|
return el;
|
|
337
382
|
}
|
|
338
383
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ktjs/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "Core functionality for kt.js - DOM manipulation utilities with JSX/TSX support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"directory": "packages/core"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@ktjs/shared": "0.20.
|
|
47
|
+
"@ktjs/shared": "0.20.2"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "rollup -c rollup.config.mjs",
|