@ktjs/core 0.28.2 → 0.29.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/dist/index.d.ts +434 -1472
- package/dist/index.mjs +826 -1023
- package/package.json +2 -2
- package/LICENSE +0 -21
- package/dist/index.iife.js +0 -1144
- package/dist/index.legacy.js +0 -1153
- package/dist/jsx/index.d.ts +0 -1331
- package/dist/jsx/index.mjs +0 -676
- package/dist/jsx/jsx-runtime.d.ts +0 -237
- package/dist/jsx/jsx-runtime.mjs +0 -676
package/dist/index.mjs
CHANGED
|
@@ -1,1115 +1,918 @@
|
|
|
1
|
-
|
|
2
|
-
const $isArray = Array.isArray;
|
|
3
|
-
const $is = Object.is;
|
|
4
|
-
const $entries = Object.entries;
|
|
5
|
-
const $random = Math.random;
|
|
6
|
-
const $isThenable = (o) => typeof o?.then === 'function';
|
|
7
|
-
|
|
8
|
-
if (typeof Symbol === 'undefined') {
|
|
9
|
-
window.Symbol = function Symbol(description) {
|
|
10
|
-
return `@@SYMBOL_${description || ''}_${$random().toString(36).slice(2)}`;
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// Shared constants
|
|
15
|
-
// Empty for now - can be extended with framework-wide constants
|
|
16
|
-
/**
|
|
17
|
-
* Mark the attribute as SVG to handle special cases during rendering.
|
|
18
|
-
*/
|
|
19
|
-
const SVG_ATTR_FLAG = '__kt_svg__';
|
|
20
|
-
/**
|
|
21
|
-
* Mark the attribute as MathML to handle special cases during rendering.
|
|
22
|
-
*/
|
|
23
|
-
const MATHML_ATTR_FLAG = '__kt_mathml__';
|
|
24
|
-
|
|
25
|
-
// DOM manipulation utilities
|
|
26
|
-
// # dom natives
|
|
27
|
-
const $isNode = (x) => x?.nodeType > 0;
|
|
28
|
-
/**
|
|
29
|
-
* Safe replace `oldNode` With `newNode`
|
|
30
|
-
*/
|
|
31
|
-
const $replaceNode = (oldNode, newNode) => {
|
|
32
|
-
if ($isNode(oldNode) && $isNode(newNode)) {
|
|
33
|
-
if (newNode.contains(oldNode)) {
|
|
34
|
-
newNode.remove();
|
|
35
|
-
}
|
|
36
|
-
oldNode.replaceWith(newNode);
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
/**
|
|
40
|
-
* & Remove `bind` because it is shockingly slower than wrapper
|
|
41
|
-
* & `window.document` is safe because it is not configurable and its setter is undefined
|
|
42
|
-
*/
|
|
43
|
-
const $appendChild = HTMLElement.prototype.appendChild;
|
|
44
|
-
const originAppend = HTMLElement.prototype.append;
|
|
45
|
-
const $append = // for ie 9/10/11
|
|
46
|
-
typeof originAppend === 'function'
|
|
47
|
-
? originAppend
|
|
48
|
-
: function (...nodes) {
|
|
49
|
-
if (nodes.length < 50) {
|
|
50
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
51
|
-
const node = nodes[i];
|
|
52
|
-
if (typeof node === 'string') {
|
|
53
|
-
$appendChild.call(this, document.createTextNode(node));
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
$appendChild.call(this, node);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
const fragment = document.createDocumentFragment();
|
|
62
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
63
|
-
const node = nodes[i];
|
|
64
|
-
if (typeof node === 'string') {
|
|
65
|
-
$appendChild.call(fragment, document.createTextNode(node));
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
$appendChild.call(fragment, node);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
$appendChild.call(this, fragment);
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
const { get: $buttonDisabledGetter, set: $buttonDisabledSetter } = Object.getOwnPropertyDescriptor(HTMLButtonElement.prototype, 'disabled');
|
|
75
|
-
/**
|
|
76
|
-
* Used for `k-model`
|
|
77
|
-
*/
|
|
78
|
-
const $applyModel = (element, valueRef, propName, eventName) => {
|
|
79
|
-
element[propName] = valueRef.value; // initialize
|
|
80
|
-
valueRef.addOnChange((newValue) => (element[propName] = newValue));
|
|
81
|
-
element.addEventListener(eventName, () => (valueRef.value = element[propName]));
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
// String manipulation utilities
|
|
85
|
-
/**
|
|
86
|
-
* Default empty function
|
|
87
|
-
*/
|
|
88
|
-
const $emptyFn = (() => true);
|
|
89
|
-
/**
|
|
90
|
-
* Safe and quick forEach implementation that works with array-like objects and handles sparse arrays.
|
|
91
|
-
*/
|
|
92
|
-
const $forEach = (array, callback) => {
|
|
93
|
-
const len = array.length;
|
|
94
|
-
for (let i = 0; i < len; i++) {
|
|
95
|
-
callback(array[i], i, array);
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
// incase that symbol is not supported
|
|
100
|
-
Object.defineProperty(window, '__ktjs__', { value: '0.23.11' });
|
|
1
|
+
import { $isArray, $isThenable, $append, $isNode, $emptyFn, $is, $replaceNode, $entries, $applyModel, $forEach } from '@ktjs/shared';
|
|
101
2
|
|
|
3
|
+
var KTReactiveType = /* @__PURE__ */ ((KTReactiveType2) => {
|
|
4
|
+
KTReactiveType2[KTReactiveType2["REF"] = 1] = "REF";
|
|
5
|
+
KTReactiveType2[KTReactiveType2["COMPUTED"] = 2] = "COMPUTED";
|
|
6
|
+
return KTReactiveType2;
|
|
7
|
+
})(KTReactiveType || {});
|
|
102
8
|
const isKT = (obj) => obj?.isKT;
|
|
103
|
-
const isRef = (obj) => obj?.ktType === 1 /*
|
|
104
|
-
const isComputed = (obj) => obj?.ktType === 2 /*
|
|
9
|
+
const isRef = (obj) => obj?.ktType === 1 /* REF */;
|
|
10
|
+
const isComputed = (obj) => obj?.ktType === 2 /* COMPUTED */;
|
|
105
11
|
|
|
106
12
|
const booleanHandler = (element, key, value) => {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
13
|
+
if (key in element) {
|
|
14
|
+
element[key] = !!value;
|
|
15
|
+
} else {
|
|
16
|
+
element.setAttribute(key, value);
|
|
17
|
+
}
|
|
113
18
|
};
|
|
114
19
|
const valueHandler = (element, key, value) => {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
20
|
+
if (key in element) {
|
|
21
|
+
element[key] = value;
|
|
22
|
+
} else {
|
|
23
|
+
element.setAttribute(key, value);
|
|
24
|
+
}
|
|
121
25
|
};
|
|
122
|
-
// Attribute handlers map for optimized lookup
|
|
123
26
|
const handlers = {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
27
|
+
checked: booleanHandler,
|
|
28
|
+
selected: booleanHandler,
|
|
29
|
+
value: valueHandler,
|
|
30
|
+
valueAsDate: valueHandler,
|
|
31
|
+
valueAsNumber: valueHandler,
|
|
32
|
+
defaultValue: valueHandler,
|
|
33
|
+
defaultChecked: booleanHandler,
|
|
34
|
+
defaultSelected: booleanHandler,
|
|
35
|
+
disabled: booleanHandler,
|
|
36
|
+
readOnly: booleanHandler,
|
|
37
|
+
multiple: booleanHandler,
|
|
38
|
+
required: booleanHandler,
|
|
39
|
+
autofocus: booleanHandler,
|
|
40
|
+
open: booleanHandler,
|
|
41
|
+
controls: booleanHandler,
|
|
42
|
+
autoplay: booleanHandler,
|
|
43
|
+
loop: booleanHandler,
|
|
44
|
+
muted: booleanHandler,
|
|
45
|
+
defer: booleanHandler,
|
|
46
|
+
async: booleanHandler,
|
|
47
|
+
hidden: (element, _key, value) => element.hidden = !!value
|
|
145
48
|
};
|
|
146
49
|
|
|
147
50
|
const defaultHandler = (element, key, value) => element.setAttribute(key, value);
|
|
148
51
|
const setElementStyle = (element, style) => {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
52
|
+
if (typeof style === "string") {
|
|
53
|
+
element.style.cssText = style;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
for (const key in style) {
|
|
57
|
+
element.style[key] = style[key];
|
|
58
|
+
}
|
|
156
59
|
};
|
|
157
60
|
function attrIsObject(element, attr) {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
if (style) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
if (key.startsWith('on:')) {
|
|
207
|
-
element.addEventListener(key.slice(3), o); // chop off the `on:`
|
|
208
|
-
}
|
|
209
|
-
// normal attributes
|
|
210
|
-
else {
|
|
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
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
61
|
+
const classValue = attr.class || attr.className;
|
|
62
|
+
if (classValue !== void 0) {
|
|
63
|
+
if (isKT(classValue)) {
|
|
64
|
+
element.setAttribute("class", classValue.value);
|
|
65
|
+
classValue.addOnChange((v) => element.setAttribute("class", v));
|
|
66
|
+
} else {
|
|
67
|
+
element.setAttribute("class", classValue);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const style = attr.style;
|
|
71
|
+
if (style) {
|
|
72
|
+
if (typeof style === "string") {
|
|
73
|
+
element.setAttribute("style", style);
|
|
74
|
+
} else if (typeof style === "object") {
|
|
75
|
+
if (isKT(style)) {
|
|
76
|
+
setElementStyle(element, style.value);
|
|
77
|
+
style.addOnChange((v) => setElementStyle(element, v));
|
|
78
|
+
} else {
|
|
79
|
+
setElementStyle(element, style);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if ("k-html" in attr) {
|
|
84
|
+
const html = attr["k-html"];
|
|
85
|
+
if (isKT(html)) {
|
|
86
|
+
element.innerHTML = html.value;
|
|
87
|
+
html.addOnChange((v) => element.innerHTML = v);
|
|
88
|
+
} else {
|
|
89
|
+
element.innerHTML = html;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
for (const key in attr) {
|
|
93
|
+
if (key === "k-if" || key === "k-model" || key === "ref" || key === "class" || key === "className" || key === "style" || key === "children" || key === "k-html") {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const o = attr[key];
|
|
97
|
+
if (key.startsWith("on:")) {
|
|
98
|
+
element.addEventListener(key.slice(3), o);
|
|
99
|
+
} else {
|
|
100
|
+
const handler = handlers[key] || defaultHandler;
|
|
101
|
+
if (isKT(o)) {
|
|
102
|
+
handler(element, key, o.value);
|
|
103
|
+
o.addOnChange((v) => handler(element, key, v));
|
|
104
|
+
} else {
|
|
105
|
+
handler(element, key, o);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
221
109
|
}
|
|
222
110
|
function applyAttr(element, attr) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
111
|
+
if (!attr) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (typeof attr === "object" && attr !== null) {
|
|
115
|
+
attrIsObject(element, attr);
|
|
116
|
+
} else {
|
|
117
|
+
throw new Error("[@ktjs/core error] attr must be an object.");
|
|
118
|
+
}
|
|
232
119
|
}
|
|
233
120
|
|
|
234
|
-
const assureNode = (o) =>
|
|
121
|
+
const assureNode = (o) => $isNode(o) ? o : document.createTextNode(o);
|
|
235
122
|
function apdSingle(element, c) {
|
|
236
|
-
|
|
237
|
-
|
|
123
|
+
if (c === false || c === void 0 || c === null) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (isKT(c)) {
|
|
127
|
+
let node = assureNode(c.value);
|
|
128
|
+
$append.call(element, node);
|
|
129
|
+
c.addOnChange((newValue, oldValue) => {
|
|
130
|
+
if ($isNode(newValue) && $isNode(oldValue)) {
|
|
238
131
|
return;
|
|
132
|
+
}
|
|
133
|
+
const oldNode = node;
|
|
134
|
+
node = assureNode(newValue);
|
|
135
|
+
oldNode.replaceWith(node);
|
|
136
|
+
});
|
|
137
|
+
} else {
|
|
138
|
+
$append.call(element, c);
|
|
139
|
+
const list = c.__kt_for_list__;
|
|
140
|
+
if ($isArray(list)) {
|
|
141
|
+
apd(element, list);
|
|
239
142
|
}
|
|
240
|
-
|
|
241
|
-
let node = assureNode(c.value);
|
|
242
|
-
$append.call(element, node);
|
|
243
|
-
c.addOnChange((newValue, oldValue) => {
|
|
244
|
-
if ($isNode(newValue) && $isNode(oldValue)) {
|
|
245
|
-
// & this case is handled automically in `class KTRef`
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
248
|
-
const oldNode = node;
|
|
249
|
-
node = assureNode(newValue);
|
|
250
|
-
oldNode.replaceWith(node);
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
else {
|
|
254
|
-
$append.call(element, c);
|
|
255
|
-
// Handle KTFor anchor
|
|
256
|
-
// todo Maybe not needed anymore
|
|
257
|
-
const list = c.__kt_for_list__;
|
|
258
|
-
if ($isArray(list)) {
|
|
259
|
-
apd(element, list);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
143
|
+
}
|
|
262
144
|
}
|
|
263
145
|
function apd(element, c) {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
}
|
|
281
|
-
else {
|
|
282
|
-
// & here is thened, so must be a simple elementj
|
|
283
|
-
apdSingle(element, c);
|
|
284
|
-
}
|
|
146
|
+
if ($isThenable(c)) {
|
|
147
|
+
c.then((r) => apd(element, r));
|
|
148
|
+
} else if ($isArray(c)) {
|
|
149
|
+
for (let i = 0; i < c.length; i++) {
|
|
150
|
+
const ci = c[i];
|
|
151
|
+
if ($isThenable(ci)) {
|
|
152
|
+
const comment = document.createComment("ktjs-promise-placeholder");
|
|
153
|
+
$append.call(element, comment);
|
|
154
|
+
ci.then((awaited) => comment.replaceWith(awaited));
|
|
155
|
+
} else {
|
|
156
|
+
apdSingle(element, ci);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
} else {
|
|
160
|
+
apdSingle(element, c);
|
|
161
|
+
}
|
|
285
162
|
}
|
|
286
163
|
function applyContent(element, content) {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
else {
|
|
293
|
-
apd(element, content);
|
|
164
|
+
if ($isArray(content)) {
|
|
165
|
+
for (let i = 0; i < content.length; i++) {
|
|
166
|
+
apd(element, content[i]);
|
|
294
167
|
}
|
|
168
|
+
} else {
|
|
169
|
+
apd(element, content);
|
|
170
|
+
}
|
|
295
171
|
}
|
|
296
172
|
|
|
297
173
|
class KTRef {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
174
|
+
/**
|
|
175
|
+
* Indicates that this is a KTRef instance
|
|
176
|
+
*/
|
|
177
|
+
isKT = true;
|
|
178
|
+
ktType = KTReactiveType.REF;
|
|
179
|
+
/**
|
|
180
|
+
* @internal
|
|
181
|
+
*/
|
|
182
|
+
_value;
|
|
183
|
+
/**
|
|
184
|
+
* @internal
|
|
185
|
+
*/
|
|
186
|
+
_onChanges;
|
|
187
|
+
/**
|
|
188
|
+
* @internal
|
|
189
|
+
*/
|
|
190
|
+
_emit(newValue, oldValue) {
|
|
191
|
+
for (let i = 0; i < this._onChanges.length; i++) {
|
|
192
|
+
this._onChanges[i](newValue, oldValue);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
constructor(_value, _onChanges) {
|
|
196
|
+
this._value = _value;
|
|
197
|
+
this._onChanges = _onChanges;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* If new value and old value are both nodes, the old one will be replaced in the DOM
|
|
201
|
+
*/
|
|
202
|
+
get value() {
|
|
203
|
+
return this._value;
|
|
204
|
+
}
|
|
205
|
+
set value(newValue) {
|
|
206
|
+
if ($is(newValue, this._value)) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const oldValue = this._value;
|
|
210
|
+
$replaceNode(oldValue, newValue);
|
|
211
|
+
this._value = newValue;
|
|
212
|
+
this._emit(newValue, oldValue);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Force all listeners to run even when reference identity has not changed.
|
|
216
|
+
* Useful for in-place array/object mutations.
|
|
217
|
+
*/
|
|
218
|
+
notify() {
|
|
219
|
+
this._emit(this._value, this._value);
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Mutate current value in-place and notify listeners once.
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
* const items = ref<number[]>([1, 2]);
|
|
226
|
+
* items.mutate((list) => list.push(3));
|
|
227
|
+
*/
|
|
228
|
+
mutate(mutator) {
|
|
229
|
+
if (typeof mutator !== "function") {
|
|
230
|
+
throw new Error("[@ktjs/core error] KTRef.mutate: mutator must be a function");
|
|
231
|
+
}
|
|
232
|
+
const oldValue = this._value;
|
|
233
|
+
const result = mutator(this._value);
|
|
234
|
+
this._emit(this._value, oldValue);
|
|
235
|
+
return result;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Register a callback when the value changes
|
|
239
|
+
* @param callback (newValue, oldValue) => xxx
|
|
240
|
+
*/
|
|
241
|
+
addOnChange(callback) {
|
|
242
|
+
if (typeof callback !== "function") {
|
|
243
|
+
throw new Error("[@ktjs/core error] KTRef.addOnChange: callback must be a function");
|
|
244
|
+
}
|
|
245
|
+
this._onChanges.push(callback);
|
|
246
|
+
}
|
|
247
|
+
removeOnChange(callback) {
|
|
248
|
+
for (let i = this._onChanges.length - 1; i >= 0; i--) {
|
|
249
|
+
if (this._onChanges[i] === callback) {
|
|
250
|
+
this._onChanges.splice(i, 1);
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
380
256
|
}
|
|
381
|
-
/**
|
|
382
|
-
* Reference to the created HTML element.
|
|
383
|
-
* - **Only** respond to `ref.value` changes, not reactive to internal changes of the element.
|
|
384
|
-
* - can alse be used to store normal values, but it is not reactive.
|
|
385
|
-
* - if the value is already a `KTRef`, it will be returned **directly**.
|
|
386
|
-
* @param value mostly an HTMLElement
|
|
387
|
-
*/
|
|
388
257
|
function ref(value, onChange) {
|
|
389
|
-
|
|
258
|
+
return new KTRef(value, onChange ? [onChange] : []);
|
|
390
259
|
}
|
|
391
|
-
/**
|
|
392
|
-
* Convert a value to `KTRef`.
|
|
393
|
-
* - Returns the original value if it is already a `KTRef`.
|
|
394
|
-
* - Throws error if the value is a `KTComputed`.
|
|
395
|
-
* - Otherwise wraps the value with `ref()`.
|
|
396
|
-
* @param o value to convert
|
|
397
|
-
*/
|
|
398
260
|
const toRef = (o) => {
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
return ref(o);
|
|
407
|
-
}
|
|
261
|
+
if (isRef(o)) {
|
|
262
|
+
return o;
|
|
263
|
+
} else if (isComputed(o)) {
|
|
264
|
+
throw new Error("[@ktjs/core error] Computed values cannot be used as KTRef.");
|
|
265
|
+
} else {
|
|
266
|
+
return ref(o);
|
|
267
|
+
}
|
|
408
268
|
};
|
|
409
269
|
function kcollect() {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
270
|
+
const newObj = {};
|
|
271
|
+
const entries = $entries(this);
|
|
272
|
+
for (let i = 0; i < entries.length; i++) {
|
|
273
|
+
const key = entries[i][0];
|
|
274
|
+
if (key === "kcollect") {
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
newObj[key] = entries[i][1].value;
|
|
278
|
+
}
|
|
279
|
+
return newObj;
|
|
420
280
|
}
|
|
421
|
-
/**
|
|
422
|
-
* Make all first-level properties of the object a `KTRef`.
|
|
423
|
-
* - `obj.a.b` is not reactive
|
|
424
|
-
*/
|
|
425
281
|
const surfaceRef = (obj) => {
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
282
|
+
const entries = $entries(obj);
|
|
283
|
+
const newObj = { kcollect };
|
|
284
|
+
for (let i = 0; i < entries.length; i++) {
|
|
285
|
+
newObj[entries[i][0]] = ref(entries[i][1]);
|
|
286
|
+
}
|
|
287
|
+
return newObj;
|
|
432
288
|
};
|
|
433
|
-
// # asserts
|
|
434
|
-
/**
|
|
435
|
-
* Assert k-model to be a ref object
|
|
436
|
-
*/
|
|
437
289
|
const $modelOrRef = (props, defaultValue) => {
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
}
|
|
448
|
-
return ref(defaultValue);
|
|
290
|
+
if ("k-model" in props) {
|
|
291
|
+
const kmodel = props["k-model"];
|
|
292
|
+
if (isRef(kmodel)) {
|
|
293
|
+
return kmodel;
|
|
294
|
+
} else {
|
|
295
|
+
throw new Error(`[@ktjs/core error] k-model data must be a KTRef object, please use 'ref(...)' to wrap it.`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return ref(defaultValue);
|
|
449
299
|
};
|
|
450
|
-
const $
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
300
|
+
const $refSetter = (props, node) => props.ref.value = node;
|
|
301
|
+
const $initRef = (props, node) => {
|
|
302
|
+
if (!("ref" in props)) {
|
|
303
|
+
return $emptyFn;
|
|
304
|
+
}
|
|
305
|
+
const r = props.ref;
|
|
306
|
+
if (isRef(r)) {
|
|
307
|
+
r.value = node;
|
|
308
|
+
return $refSetter;
|
|
309
|
+
} else {
|
|
310
|
+
throw new Error("[@ktjs/core error] Fragment: ref must be a KTRef");
|
|
311
|
+
}
|
|
460
312
|
};
|
|
461
313
|
|
|
462
314
|
class KTComputed {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
this._emit(newValue, oldValue);
|
|
497
|
-
}
|
|
498
|
-
return;
|
|
499
|
-
}
|
|
500
|
-
this._value = newValue;
|
|
501
|
-
$replaceNode(oldValue, newValue);
|
|
315
|
+
/**
|
|
316
|
+
* Indicates that this is a KTRef instance
|
|
317
|
+
*/
|
|
318
|
+
isKT = true;
|
|
319
|
+
ktType = KTReactiveType.COMPUTED;
|
|
320
|
+
/**
|
|
321
|
+
* @internal
|
|
322
|
+
*/
|
|
323
|
+
_calculator;
|
|
324
|
+
/**
|
|
325
|
+
* @internal
|
|
326
|
+
*/
|
|
327
|
+
_value;
|
|
328
|
+
/**
|
|
329
|
+
* @internal
|
|
330
|
+
*/
|
|
331
|
+
_onChanges = [];
|
|
332
|
+
/**
|
|
333
|
+
* @internal
|
|
334
|
+
*/
|
|
335
|
+
_emit(newValue, oldValue) {
|
|
336
|
+
for (let i = 0; i < this._onChanges.length; i++) {
|
|
337
|
+
this._onChanges[i](newValue, oldValue);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* @internal
|
|
342
|
+
*/
|
|
343
|
+
_recalculate(forceEmit = false) {
|
|
344
|
+
const oldValue = this._value;
|
|
345
|
+
const newValue = this._calculator();
|
|
346
|
+
if (oldValue === newValue) {
|
|
347
|
+
if (forceEmit) {
|
|
502
348
|
this._emit(newValue, oldValue);
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
349
|
+
}
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
this._value = newValue;
|
|
353
|
+
$replaceNode(oldValue, newValue);
|
|
354
|
+
this._emit(newValue, oldValue);
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* @internal
|
|
358
|
+
*/
|
|
359
|
+
_subscribe(reactives) {
|
|
360
|
+
for (let i = 0; i < reactives.length; i++) {
|
|
361
|
+
const reactive = reactives[i];
|
|
362
|
+
reactive.addOnChange(() => this._recalculate());
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
constructor(_calculator, reactives) {
|
|
366
|
+
this._calculator = _calculator;
|
|
367
|
+
this._value = _calculator();
|
|
368
|
+
this._subscribe(reactives);
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* If new value and old value are both nodes, the old one will be replaced in the DOM
|
|
372
|
+
*/
|
|
373
|
+
get value() {
|
|
374
|
+
return this._value;
|
|
375
|
+
}
|
|
376
|
+
set value(_newValue) {
|
|
377
|
+
throw new Error("[@ktjs/core error] KTComputed: cannot set value of a computed value");
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Force listeners to run once with the latest computed result.
|
|
381
|
+
*/
|
|
382
|
+
notify() {
|
|
383
|
+
this._recalculate(true);
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Computed values are derived from dependencies and should not be mutated manually.
|
|
387
|
+
*/
|
|
388
|
+
mutate() {
|
|
389
|
+
console.warn('[@ktjs/core warn]',"KTComputed.mutate: computed is derived automatically; manual mutate is ignored. Use notify() instead");
|
|
390
|
+
return this._value;
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Register a callback when the value changes
|
|
394
|
+
* @param callback (newValue, oldValue) => xxx
|
|
395
|
+
*/
|
|
396
|
+
addOnChange(callback) {
|
|
397
|
+
if (typeof callback !== "function") {
|
|
398
|
+
throw new Error("[@ktjs/core error] KTRef.addOnChange: callback must be a function");
|
|
399
|
+
}
|
|
400
|
+
this._onChanges.push(callback);
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Unregister a callback
|
|
404
|
+
* @param callback (newValue, oldValue) => xxx
|
|
405
|
+
*/
|
|
406
|
+
removeOnChange(callback) {
|
|
407
|
+
for (let i = this._onChanges.length - 1; i >= 0; i--) {
|
|
408
|
+
if (this._onChanges[i] === callback) {
|
|
409
|
+
this._onChanges.splice(i, 1);
|
|
410
|
+
return true;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return false;
|
|
414
|
+
}
|
|
563
415
|
}
|
|
564
|
-
/**
|
|
565
|
-
* Create a reactive computed value
|
|
566
|
-
* @param computeFn
|
|
567
|
-
* @param reactives refs and computeds that this computed depends on
|
|
568
|
-
*/
|
|
569
416
|
function computed(computeFn, reactives) {
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
417
|
+
if (reactives.some((v) => !isKT(v))) {
|
|
418
|
+
throw new Error("[@ktjs/core error] computed: all reactives must be KTRef or KTComputed instances");
|
|
419
|
+
}
|
|
420
|
+
return new KTComputed(computeFn, reactives);
|
|
574
421
|
}
|
|
575
422
|
|
|
576
|
-
/**
|
|
577
|
-
* Register a reactive effect with options.
|
|
578
|
-
* @param effectFn The effect function to run when dependencies change
|
|
579
|
-
* @param reactives The reactive dependencies
|
|
580
|
-
* @param options Effect options: lazy, onCleanup, debugName
|
|
581
|
-
* @returns stop function to remove all listeners
|
|
582
|
-
*/
|
|
583
423
|
function effect(effectFn, reactives, options) {
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
424
|
+
const { lazy = false, onCleanup = $emptyFn, debugName = "" } = Object(options);
|
|
425
|
+
let active = true;
|
|
426
|
+
const run = () => {
|
|
427
|
+
if (!active) {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
onCleanup();
|
|
431
|
+
try {
|
|
432
|
+
effectFn();
|
|
433
|
+
} catch (err) {
|
|
434
|
+
console.debug('[@ktjs/core debug]',"effect error:", debugName, err);
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
for (let i = 0; i < reactives.length; i++) {
|
|
438
|
+
reactives[i].addOnChange(run);
|
|
439
|
+
}
|
|
440
|
+
if (!lazy) {
|
|
441
|
+
run();
|
|
442
|
+
}
|
|
443
|
+
return () => {
|
|
444
|
+
if (!active) {
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
active = false;
|
|
600
448
|
for (let i = 0; i < reactives.length; i++) {
|
|
601
|
-
|
|
602
|
-
}
|
|
603
|
-
// auto run unless lazy
|
|
604
|
-
if (!lazy) {
|
|
605
|
-
run();
|
|
449
|
+
reactives[i].removeOnChange(run);
|
|
606
450
|
}
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
if (!active) {
|
|
610
|
-
return;
|
|
611
|
-
}
|
|
612
|
-
active = false;
|
|
613
|
-
for (let i = 0; i < reactives.length; i++) {
|
|
614
|
-
reactives[i].removeOnChange(run);
|
|
615
|
-
}
|
|
616
|
-
// final cleanup
|
|
617
|
-
onCleanup();
|
|
618
|
-
};
|
|
451
|
+
onCleanup();
|
|
452
|
+
};
|
|
619
453
|
}
|
|
620
454
|
|
|
621
455
|
const toReactive = (value, onChange) => {
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
}
|
|
456
|
+
if (isKT(value)) {
|
|
457
|
+
if (onChange) {
|
|
458
|
+
value.addOnChange(onChange);
|
|
459
|
+
}
|
|
460
|
+
return value;
|
|
461
|
+
} else {
|
|
462
|
+
return ref(value, onChange);
|
|
463
|
+
}
|
|
631
464
|
};
|
|
632
|
-
/**
|
|
633
|
-
* Extracts the value from a KTReactive, or returns the value directly if it's not reactive.
|
|
634
|
-
*/
|
|
635
465
|
function dereactive(value) {
|
|
636
|
-
|
|
466
|
+
return isKT(value) ? value.value : value;
|
|
637
467
|
}
|
|
638
468
|
|
|
639
469
|
function applyKModel(element, valueRef) {
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
}
|
|
658
|
-
else {
|
|
659
|
-
console.warn('[kt.js warn]','not supported element for k-model:');
|
|
660
|
-
}
|
|
470
|
+
if (!isKT(valueRef)) {
|
|
471
|
+
console.warn('[@ktjs/core warn]',"k-model value must be a KTRef.");
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
if (element instanceof HTMLInputElement) {
|
|
475
|
+
if (element.type === "radio" || element.type === "checkbox") {
|
|
476
|
+
$applyModel(element, valueRef, "checked", "change");
|
|
477
|
+
} else {
|
|
478
|
+
$applyModel(element, valueRef, "value", "input");
|
|
479
|
+
}
|
|
480
|
+
} else if (element instanceof HTMLSelectElement) {
|
|
481
|
+
$applyModel(element, valueRef, "value", "change");
|
|
482
|
+
} else if (element instanceof HTMLTextAreaElement) {
|
|
483
|
+
$applyModel(element, valueRef, "value", "input");
|
|
484
|
+
} else {
|
|
485
|
+
console.warn('[@ktjs/core warn]',"not supported element for k-model:");
|
|
486
|
+
}
|
|
661
487
|
}
|
|
662
488
|
|
|
663
489
|
const htmlCreator = (tag) => document.createElement(tag);
|
|
664
|
-
const svgCreator = (tag) => document.createElementNS(
|
|
665
|
-
const mathMLCreator = (tag) => document.createElementNS(
|
|
490
|
+
const svgCreator = (tag) => document.createElementNS("http://www.w3.org/2000/svg", tag);
|
|
491
|
+
const mathMLCreator = (tag) => document.createElementNS("http://www.w3.org/1998/Math/MathML", tag);
|
|
666
492
|
let creator = htmlCreator;
|
|
667
|
-
/**
|
|
668
|
-
* Create an enhanced HTMLElement.
|
|
669
|
-
* - Only supports HTMLElements, **NOT** SVGElements or other Elements.
|
|
670
|
-
* @param tag tag of an `HTMLElement`
|
|
671
|
-
* @param attr attribute object or className
|
|
672
|
-
* @param content a string or an array of HTMLEnhancedElement as child nodes
|
|
673
|
-
*
|
|
674
|
-
* ## About
|
|
675
|
-
* @package @ktjs/core
|
|
676
|
-
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
677
|
-
* @version 0.28.2 (Last Update: 2026.02.10 14:46:21.243)
|
|
678
|
-
* @license MIT
|
|
679
|
-
* @link https://github.com/baendlorel/kt.js
|
|
680
|
-
* @link https://baendlorel.github.io/ Welcome to my site!
|
|
681
|
-
* @description Core functionality for kt.js - DOM manipulation utilities with JSX/TSX support
|
|
682
|
-
* @copyright Copyright (c) 2026 Kasukabe Tsumugi. All rights reserved.
|
|
683
|
-
*/
|
|
684
493
|
const h = (tag, attr, content) => {
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
if (typeof attr === 'object' && attr !== null && 'k-model' in attr) {
|
|
707
|
-
applyKModel(element, attr['k-model']);
|
|
708
|
-
}
|
|
709
|
-
return element;
|
|
494
|
+
if (typeof tag !== "string") {
|
|
495
|
+
throw new Error("[@ktjs/core error] tagName must be a string.");
|
|
496
|
+
}
|
|
497
|
+
if (attr) {
|
|
498
|
+
if ("__svg" in attr) {
|
|
499
|
+
delete attr["__svg"];
|
|
500
|
+
creator = svgCreator;
|
|
501
|
+
} else if ("__mathml" in attr) {
|
|
502
|
+
delete attr["__mathml"];
|
|
503
|
+
creator = mathMLCreator;
|
|
504
|
+
} else {
|
|
505
|
+
creator = htmlCreator;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
const element = creator(tag);
|
|
509
|
+
applyAttr(element, attr);
|
|
510
|
+
applyContent(element, content);
|
|
511
|
+
if (typeof attr === "object" && attr !== null && "k-model" in attr) {
|
|
512
|
+
applyKModel(element, attr["k-model"]);
|
|
513
|
+
}
|
|
514
|
+
return element;
|
|
710
515
|
};
|
|
711
516
|
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
517
|
+
const FRAGMENT_MOUNT_PATCHED = "__kt_fragment_mount_patched__";
|
|
518
|
+
const FRAGMENT_MOUNT = "__kt_fragment_mount__";
|
|
519
|
+
if (typeof Node !== "undefined" && !globalThis[FRAGMENT_MOUNT_PATCHED]) {
|
|
520
|
+
globalThis[FRAGMENT_MOUNT_PATCHED] = true;
|
|
521
|
+
const originAppendChild = Node.prototype.appendChild;
|
|
522
|
+
Node.prototype.appendChild = function(node) {
|
|
523
|
+
const result = originAppendChild.call(this, node);
|
|
524
|
+
const mount = node[FRAGMENT_MOUNT];
|
|
525
|
+
if (typeof mount === "function") {
|
|
526
|
+
mount();
|
|
527
|
+
}
|
|
528
|
+
return result;
|
|
529
|
+
};
|
|
530
|
+
const originInsertBefore = Node.prototype.insertBefore;
|
|
531
|
+
Node.prototype.insertBefore = function(node, child) {
|
|
532
|
+
const result = originInsertBefore.call(this, node, child);
|
|
533
|
+
const mount = node[FRAGMENT_MOUNT];
|
|
534
|
+
if (typeof mount === "function") {
|
|
535
|
+
mount();
|
|
536
|
+
}
|
|
537
|
+
return result;
|
|
538
|
+
};
|
|
539
|
+
}
|
|
731
540
|
function Fragment$1(props) {
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
541
|
+
const elements = [];
|
|
542
|
+
const anchor = document.createComment("kt-fragment");
|
|
543
|
+
let inserted = false;
|
|
544
|
+
let observer;
|
|
545
|
+
const redraw = () => {
|
|
546
|
+
const newElements = childrenRef.value;
|
|
547
|
+
const parent = anchor.parentNode;
|
|
548
|
+
if (!parent) {
|
|
549
|
+
elements.length = 0;
|
|
550
|
+
for (let i = 0; i < newElements.length; i++) {
|
|
551
|
+
elements.push(newElements[i]);
|
|
552
|
+
}
|
|
553
|
+
anchor.__kt_fragment_list__ = elements;
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
for (let i = 0; i < elements.length; i++) {
|
|
557
|
+
elements[i].remove();
|
|
558
|
+
}
|
|
559
|
+
const fragment = document.createDocumentFragment();
|
|
560
|
+
elements.length = 0;
|
|
561
|
+
for (let i = 0; i < newElements.length; i++) {
|
|
562
|
+
const element = newElements[i];
|
|
563
|
+
elements.push(element);
|
|
564
|
+
fragment.appendChild(element);
|
|
565
|
+
}
|
|
566
|
+
parent.insertBefore(fragment, anchor.nextSibling);
|
|
567
|
+
inserted = true;
|
|
568
|
+
delete anchor[FRAGMENT_MOUNT];
|
|
569
|
+
observer?.disconnect();
|
|
570
|
+
observer = void 0;
|
|
571
|
+
anchor.__kt_fragment_list__ = elements;
|
|
572
|
+
};
|
|
573
|
+
const childrenRef = toReactive(props.children, redraw);
|
|
574
|
+
const renderInitial = () => {
|
|
575
|
+
const current = childrenRef.value;
|
|
576
|
+
elements.length = 0;
|
|
577
|
+
const fragment = document.createDocumentFragment();
|
|
578
|
+
for (let i = 0; i < current.length; i++) {
|
|
579
|
+
const element = current[i];
|
|
580
|
+
elements.push(element);
|
|
581
|
+
fragment.appendChild(element);
|
|
582
|
+
}
|
|
583
|
+
anchor.__kt_fragment_list__ = elements;
|
|
584
|
+
const parent = anchor.parentNode;
|
|
585
|
+
if (parent && !inserted) {
|
|
586
|
+
parent.insertBefore(fragment, anchor.nextSibling);
|
|
587
|
+
inserted = true;
|
|
588
|
+
}
|
|
589
|
+
};
|
|
590
|
+
renderInitial();
|
|
591
|
+
anchor[FRAGMENT_MOUNT] = () => {
|
|
592
|
+
if (!inserted && anchor.parentNode) {
|
|
593
|
+
redraw();
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
observer = new MutationObserver(() => {
|
|
597
|
+
if (anchor.parentNode && !inserted) {
|
|
598
|
+
redraw();
|
|
599
|
+
observer?.disconnect();
|
|
600
|
+
observer = void 0;
|
|
601
|
+
}
|
|
602
|
+
});
|
|
603
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
604
|
+
$initRef(props, anchor);
|
|
605
|
+
return anchor;
|
|
778
606
|
}
|
|
779
|
-
/**
|
|
780
|
-
* Convert KTRawContent to HTMLElement array
|
|
781
|
-
*/
|
|
782
607
|
function convertChildrenToElements(children) {
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
};
|
|
811
|
-
processChild(children);
|
|
812
|
-
return elements;
|
|
608
|
+
const elements = [];
|
|
609
|
+
const processChild = (child) => {
|
|
610
|
+
if (child === void 0 || child === null || child === false || child === true) {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
if ($isArray(child)) {
|
|
614
|
+
$forEach(child, processChild);
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
if (typeof child === "string" || typeof child === "number") {
|
|
618
|
+
const span = document.createElement("span");
|
|
619
|
+
span.textContent = String(child);
|
|
620
|
+
elements.push(span);
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
if (child instanceof HTMLElement) {
|
|
624
|
+
elements.push(child);
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
if (isKT(child)) {
|
|
628
|
+
processChild(child.value);
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
console.warn("Fragment: unsupported child type", child);
|
|
632
|
+
};
|
|
633
|
+
processChild(children);
|
|
634
|
+
return elements;
|
|
813
635
|
}
|
|
814
636
|
|
|
815
|
-
const
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
}
|
|
637
|
+
const jsxh = (tag, props) => {
|
|
638
|
+
if (typeof tag === "function") {
|
|
639
|
+
return tag(props);
|
|
640
|
+
} else {
|
|
641
|
+
return h(tag, props, props.children);
|
|
642
|
+
}
|
|
822
643
|
};
|
|
823
|
-
const placeholder = () => document.createComment(
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
644
|
+
const placeholder = (data) => document.createComment(data);
|
|
645
|
+
|
|
646
|
+
function kif(tag, props) {
|
|
647
|
+
const kif2 = toReactive(props["k-if"]);
|
|
648
|
+
let el = kif2.value ? jsxh(tag, props) : placeholder("k-if");
|
|
649
|
+
el.__kif__ = kif2;
|
|
650
|
+
const setter = $initRef(props, el);
|
|
651
|
+
kif2.addOnChange((newValue) => {
|
|
652
|
+
const old = el;
|
|
653
|
+
el = newValue ? jsxh(tag, props) : placeholder("k-if");
|
|
654
|
+
el.__kif__ = kif2;
|
|
655
|
+
setter(props, el);
|
|
656
|
+
$replaceNode(old, el);
|
|
657
|
+
});
|
|
658
|
+
return el;
|
|
659
|
+
}
|
|
660
|
+
function kelse(tag, props) {
|
|
661
|
+
let el = placeholder("k-else");
|
|
662
|
+
const setter = $initRef(props, el);
|
|
663
|
+
el.__kelse__ = (newValue) => {
|
|
664
|
+
const old = el;
|
|
665
|
+
el = newValue ? placeholder("k-else") : jsxh(tag, props);
|
|
666
|
+
el.__kelse__ = old.__kelse__;
|
|
667
|
+
setter(props, el);
|
|
668
|
+
$replaceNode(old, el);
|
|
669
|
+
};
|
|
670
|
+
return el;
|
|
671
|
+
}
|
|
672
|
+
function kifelseApply(el) {
|
|
673
|
+
const childNodes = el.childNodes;
|
|
674
|
+
if (childNodes.length === 0) {
|
|
675
|
+
return;
|
|
676
|
+
}
|
|
677
|
+
if (childNodes[0].__kelse__) {
|
|
678
|
+
throw new Error("[@ktjs/core error] k-else cannot be the first child of its parent element.");
|
|
679
|
+
}
|
|
680
|
+
for (let i = 1; i < childNodes.length; i++) {
|
|
681
|
+
const child = childNodes[i];
|
|
682
|
+
if (!child.__kelse__) {
|
|
683
|
+
continue;
|
|
684
|
+
}
|
|
685
|
+
const last = childNodes[i - 1];
|
|
686
|
+
if (!("__kif__" in last)) {
|
|
687
|
+
throw new Error("[@ktjs/core error] k-else must be immediately preceded by a k-if element.");
|
|
688
|
+
}
|
|
689
|
+
const kif2 = last.__kif__;
|
|
690
|
+
if (!kif2) {
|
|
691
|
+
continue;
|
|
692
|
+
}
|
|
693
|
+
if (!isKT(kif2)) {
|
|
694
|
+
continue;
|
|
695
|
+
}
|
|
696
|
+
kif2.addOnChange(child.__kelse__);
|
|
697
|
+
if (!kif2.value) {
|
|
698
|
+
child.__kelse__(false);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
|
|
828
703
|
function jsx(tag, props) {
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
const oldEl = el;
|
|
843
|
-
$setRef(props, (el = newValue ? create(tag, props) : placeholder()));
|
|
844
|
-
$replaceNode(oldEl, el);
|
|
845
|
-
});
|
|
846
|
-
condition = kif.value;
|
|
847
|
-
}
|
|
848
|
-
if (!condition) {
|
|
849
|
-
// & make comment placeholder in case that ref might be redrawn later
|
|
850
|
-
$setRef(props, (el = placeholder()));
|
|
851
|
-
return el;
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
$setRef(props, (el = create(tag, props)));
|
|
855
|
-
return el;
|
|
704
|
+
if (isComputed(props.ref)) {
|
|
705
|
+
throw new Error("[@ktjs/core error] Cannot assign a computed value to an element.");
|
|
706
|
+
}
|
|
707
|
+
if ("k-if" in props) {
|
|
708
|
+
return kif(tag, props);
|
|
709
|
+
}
|
|
710
|
+
if ("k-else" in props) {
|
|
711
|
+
return kelse(tag, props);
|
|
712
|
+
}
|
|
713
|
+
const el = jsxh(tag, props);
|
|
714
|
+
$initRef(props, el);
|
|
715
|
+
kifelseApply(el);
|
|
716
|
+
return el;
|
|
856
717
|
}
|
|
857
|
-
/**
|
|
858
|
-
* Fragment support - returns an array of children
|
|
859
|
-
* Enhanced Fragment component that manages arrays of elements
|
|
860
|
-
*/
|
|
861
718
|
function Fragment(props) {
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
719
|
+
const { children } = props ?? {};
|
|
720
|
+
if (!children) {
|
|
721
|
+
return placeholder("kt-fragment-empty");
|
|
722
|
+
}
|
|
723
|
+
const elements = convertChildrenToElements(children);
|
|
724
|
+
return Fragment$1({ children: elements });
|
|
868
725
|
}
|
|
869
|
-
/**
|
|
870
|
-
* JSX Development runtime - same as jsx but with additional dev checks
|
|
871
|
-
*/
|
|
872
726
|
const jsxDEV = (...args) => {
|
|
873
|
-
|
|
874
|
-
// console.log('children', (args[1] as any)?.children);
|
|
875
|
-
return jsx(...args);
|
|
727
|
+
return jsx(...args);
|
|
876
728
|
};
|
|
877
|
-
/**
|
|
878
|
-
* JSX runtime for React 17+ automatic runtime
|
|
879
|
-
* This is called when using jsx: "react-jsx" or "react-jsxdev"
|
|
880
|
-
*/
|
|
881
729
|
const jsxs = jsx;
|
|
882
|
-
/**
|
|
883
|
-
* A helper to create redrawable elements
|
|
884
|
-
* ```tsx
|
|
885
|
-
* export function MyComponent() {
|
|
886
|
-
* let aa = 10;
|
|
887
|
-
* // ...
|
|
888
|
-
* // aa might be changed
|
|
889
|
-
* return createRedrawable(() => <div>{aa}</div>);
|
|
890
|
-
* }
|
|
891
|
-
* ```
|
|
892
|
-
* Then the returned element has a `redraw` method to redraw itself with new values.
|
|
893
|
-
* @param creator a simple creator function that returns an element
|
|
894
|
-
* @returns created element's ref
|
|
895
|
-
*/
|
|
896
730
|
function createRedrawable(creator) {
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
731
|
+
const elRef = ref();
|
|
732
|
+
const redraw = () => {
|
|
733
|
+
elRef.value = creator();
|
|
734
|
+
elRef.redraw = redraw;
|
|
735
|
+
return elRef.value;
|
|
736
|
+
};
|
|
737
|
+
redraw();
|
|
738
|
+
return elRef;
|
|
905
739
|
}
|
|
906
740
|
|
|
907
741
|
function KTAsync(props) {
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
return comp;
|
|
742
|
+
const raw = props.component(props);
|
|
743
|
+
let comp = props.skeleton ?? document.createComment("ktjs-suspense-placeholder");
|
|
744
|
+
if ($isThenable(raw)) {
|
|
745
|
+
raw.then((resolved) => comp.replaceWith(resolved));
|
|
746
|
+
} else {
|
|
747
|
+
comp = raw;
|
|
748
|
+
}
|
|
749
|
+
return comp;
|
|
917
750
|
}
|
|
918
751
|
|
|
919
|
-
/**
|
|
920
|
-
* KTFor - List rendering component with key-based optimization
|
|
921
|
-
* Returns a Comment anchor node with rendered elements in __kt_for_list__
|
|
922
|
-
*/
|
|
923
752
|
function KTFor(props) {
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
const node = currentMap(item, index, newList);
|
|
935
|
-
nodeMap.set(itemKey, node);
|
|
936
|
-
newElements.push(node);
|
|
937
|
-
}
|
|
938
|
-
anchor.__kt_for_list__ = newElements;
|
|
939
|
-
return anchor;
|
|
940
|
-
}
|
|
941
|
-
const oldLength = anchor.__kt_for_list__.length;
|
|
942
|
-
const newLength = newList.length;
|
|
943
|
-
// Fast path: empty list
|
|
944
|
-
if (newLength === 0) {
|
|
945
|
-
nodeMap.forEach((node) => node.remove());
|
|
946
|
-
nodeMap.clear();
|
|
947
|
-
anchor.__kt_for_list__ = [];
|
|
948
|
-
return anchor;
|
|
949
|
-
}
|
|
950
|
-
// Fast path: all new items
|
|
951
|
-
if (oldLength === 0) {
|
|
952
|
-
const newElements = [];
|
|
953
|
-
const fragment = document.createDocumentFragment();
|
|
954
|
-
for (let i = 0; i < newLength; i++) {
|
|
955
|
-
const item = newList[i];
|
|
956
|
-
const itemKey = currentKey(item, i, newList);
|
|
957
|
-
const node = currentMap(item, i, newList);
|
|
958
|
-
nodeMap.set(itemKey, node);
|
|
959
|
-
newElements.push(node);
|
|
960
|
-
fragment.appendChild(node);
|
|
961
|
-
}
|
|
962
|
-
parent.insertBefore(fragment, anchor.nextSibling);
|
|
963
|
-
anchor.__kt_for_list__ = newElements;
|
|
964
|
-
return anchor;
|
|
965
|
-
}
|
|
966
|
-
// Build key index map and new elements array in one pass
|
|
967
|
-
const newKeyToNewIndex = new Map();
|
|
968
|
-
const newElements = new Array(newLength);
|
|
969
|
-
let maxNewIndexSoFar = 0;
|
|
970
|
-
let moved = false;
|
|
971
|
-
for (let i = 0; i < newLength; i++) {
|
|
972
|
-
const item = newList[i];
|
|
973
|
-
const itemKey = currentKey(item, i, newList);
|
|
974
|
-
newKeyToNewIndex.set(itemKey, i);
|
|
975
|
-
if (nodeMap.has(itemKey)) {
|
|
976
|
-
// Reuse existing node
|
|
977
|
-
const node = nodeMap.get(itemKey);
|
|
978
|
-
newElements[i] = node;
|
|
979
|
-
// Track if items moved
|
|
980
|
-
if (i < maxNewIndexSoFar) {
|
|
981
|
-
moved = true;
|
|
982
|
-
}
|
|
983
|
-
else {
|
|
984
|
-
maxNewIndexSoFar = i;
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
else {
|
|
988
|
-
// Create new node
|
|
989
|
-
newElements[i] = currentMap(item, i, newList);
|
|
990
|
-
}
|
|
991
|
-
}
|
|
992
|
-
// Remove nodes not in new list
|
|
993
|
-
const toRemove = [];
|
|
994
|
-
nodeMap.forEach((node, key) => {
|
|
995
|
-
if (!newKeyToNewIndex.has(key)) {
|
|
996
|
-
toRemove.push(node);
|
|
997
|
-
}
|
|
998
|
-
});
|
|
999
|
-
for (let i = 0; i < toRemove.length; i++) {
|
|
1000
|
-
toRemove[i].remove();
|
|
1001
|
-
}
|
|
1002
|
-
// Update DOM with minimal operations
|
|
1003
|
-
if (moved) {
|
|
1004
|
-
// Use longest increasing subsequence to minimize moves
|
|
1005
|
-
const seq = getSequence(newElements.map((el, i) => (nodeMap.has(currentKey(newList[i], i, newList)) ? i : -1)));
|
|
1006
|
-
let j = seq.length - 1;
|
|
1007
|
-
let anchor = null;
|
|
1008
|
-
// Traverse from end to start for stable insertions
|
|
1009
|
-
for (let i = newLength - 1; i >= 0; i--) {
|
|
1010
|
-
const node = newElements[i];
|
|
1011
|
-
if (j < 0 || i !== seq[j]) {
|
|
1012
|
-
// Node needs to be moved or inserted
|
|
1013
|
-
if (anchor) {
|
|
1014
|
-
parent.insertBefore(node, anchor);
|
|
1015
|
-
}
|
|
1016
|
-
else {
|
|
1017
|
-
// Insert at end
|
|
1018
|
-
let nextSibling = anchor.nextSibling;
|
|
1019
|
-
let temp = nextSibling;
|
|
1020
|
-
while (temp && newElements.includes(temp)) {
|
|
1021
|
-
temp = temp.nextSibling;
|
|
1022
|
-
}
|
|
1023
|
-
parent.insertBefore(node, temp);
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
1026
|
-
else {
|
|
1027
|
-
j--;
|
|
1028
|
-
}
|
|
1029
|
-
anchor = node;
|
|
1030
|
-
}
|
|
1031
|
-
}
|
|
1032
|
-
else {
|
|
1033
|
-
// No moves needed, just insert new nodes
|
|
1034
|
-
let currentNode = anchor.nextSibling;
|
|
1035
|
-
for (let i = 0; i < newLength; i++) {
|
|
1036
|
-
const node = newElements[i];
|
|
1037
|
-
if (currentNode !== node) {
|
|
1038
|
-
parent.insertBefore(node, currentNode);
|
|
1039
|
-
}
|
|
1040
|
-
else {
|
|
1041
|
-
currentNode = currentNode.nextSibling;
|
|
1042
|
-
}
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
// Update maps
|
|
1046
|
-
nodeMap.clear();
|
|
1047
|
-
for (let i = 0; i < newLength; i++) {
|
|
1048
|
-
const itemKey = currentKey(newList[i], i, newList);
|
|
1049
|
-
nodeMap.set(itemKey, newElements[i]);
|
|
1050
|
-
}
|
|
1051
|
-
anchor.__kt_for_list__ = newElements;
|
|
1052
|
-
return anchor;
|
|
1053
|
-
};
|
|
1054
|
-
const { key: currentKey = (item) => item, map: currentMap } = props;
|
|
1055
|
-
const listRef = toReactive(props.list, redraw);
|
|
1056
|
-
const anchor = document.createComment('kt-for');
|
|
1057
|
-
// Map to track rendered nodes by key
|
|
1058
|
-
const nodeMap = new Map();
|
|
1059
|
-
// Render initial list
|
|
1060
|
-
const elements = [];
|
|
1061
|
-
for (let index = 0; index < listRef.value.length; index++) {
|
|
1062
|
-
const item = listRef.value[index];
|
|
1063
|
-
const itemKey = currentKey(item, index, listRef.value);
|
|
1064
|
-
const node = currentMap(item, index, listRef.value);
|
|
753
|
+
const redraw = () => {
|
|
754
|
+
const newList = listRef.value;
|
|
755
|
+
const parent = anchor.parentNode;
|
|
756
|
+
if (!parent) {
|
|
757
|
+
const newElements2 = [];
|
|
758
|
+
nodeMap.clear();
|
|
759
|
+
for (let index = 0; index < newList.length; index++) {
|
|
760
|
+
const item = newList[index];
|
|
761
|
+
const itemKey = currentKey(item, index, newList);
|
|
762
|
+
const node = currentMap(item, index, newList);
|
|
1065
763
|
nodeMap.set(itemKey, node);
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
764
|
+
newElements2.push(node);
|
|
765
|
+
}
|
|
766
|
+
anchor.__kt_for_list__ = newElements2;
|
|
767
|
+
return anchor;
|
|
768
|
+
}
|
|
769
|
+
const oldLength = anchor.__kt_for_list__.length;
|
|
770
|
+
const newLength = newList.length;
|
|
771
|
+
if (newLength === 0) {
|
|
772
|
+
nodeMap.forEach((node) => node.remove());
|
|
773
|
+
nodeMap.clear();
|
|
774
|
+
anchor.__kt_for_list__ = [];
|
|
775
|
+
return anchor;
|
|
776
|
+
}
|
|
777
|
+
if (oldLength === 0) {
|
|
778
|
+
const newElements2 = [];
|
|
779
|
+
const fragment = document.createDocumentFragment();
|
|
780
|
+
for (let i = 0; i < newLength; i++) {
|
|
781
|
+
const item = newList[i];
|
|
782
|
+
const itemKey = currentKey(item, i, newList);
|
|
783
|
+
const node = currentMap(item, i, newList);
|
|
784
|
+
nodeMap.set(itemKey, node);
|
|
785
|
+
newElements2.push(node);
|
|
786
|
+
fragment.appendChild(node);
|
|
787
|
+
}
|
|
788
|
+
parent.insertBefore(fragment, anchor.nextSibling);
|
|
789
|
+
anchor.__kt_for_list__ = newElements2;
|
|
790
|
+
return anchor;
|
|
791
|
+
}
|
|
792
|
+
const newKeyToNewIndex = /* @__PURE__ */ new Map();
|
|
793
|
+
const newElements = new Array(newLength);
|
|
794
|
+
let maxNewIndexSoFar = 0;
|
|
795
|
+
let moved = false;
|
|
796
|
+
for (let i = 0; i < newLength; i++) {
|
|
797
|
+
const item = newList[i];
|
|
798
|
+
const itemKey = currentKey(item, i, newList);
|
|
799
|
+
newKeyToNewIndex.set(itemKey, i);
|
|
800
|
+
if (nodeMap.has(itemKey)) {
|
|
801
|
+
const node = nodeMap.get(itemKey);
|
|
802
|
+
newElements[i] = node;
|
|
803
|
+
if (i < maxNewIndexSoFar) {
|
|
804
|
+
moved = true;
|
|
805
|
+
} else {
|
|
806
|
+
maxNewIndexSoFar = i;
|
|
807
|
+
}
|
|
808
|
+
} else {
|
|
809
|
+
newElements[i] = currentMap(item, i, newList);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
const toRemove = [];
|
|
813
|
+
nodeMap.forEach((node, key) => {
|
|
814
|
+
if (!newKeyToNewIndex.has(key)) {
|
|
815
|
+
toRemove.push(node);
|
|
816
|
+
}
|
|
817
|
+
});
|
|
818
|
+
for (let i = 0; i < toRemove.length; i++) {
|
|
819
|
+
toRemove[i].remove();
|
|
820
|
+
}
|
|
821
|
+
if (moved) {
|
|
822
|
+
const seq = getSequence(newElements.map((el, i) => nodeMap.has(currentKey(newList[i], i, newList)) ? i : -1));
|
|
823
|
+
let j = seq.length - 1;
|
|
824
|
+
let anchor2 = null;
|
|
825
|
+
for (let i = newLength - 1; i >= 0; i--) {
|
|
826
|
+
const node = newElements[i];
|
|
827
|
+
if (j < 0 || i !== seq[j]) {
|
|
828
|
+
if (anchor2) {
|
|
829
|
+
parent.insertBefore(node, anchor2);
|
|
830
|
+
} else {
|
|
831
|
+
let nextSibling = anchor2.nextSibling;
|
|
832
|
+
let temp = nextSibling;
|
|
833
|
+
while (temp && newElements.includes(temp)) {
|
|
834
|
+
temp = temp.nextSibling;
|
|
835
|
+
}
|
|
836
|
+
parent.insertBefore(node, temp);
|
|
837
|
+
}
|
|
838
|
+
} else {
|
|
839
|
+
j--;
|
|
840
|
+
}
|
|
841
|
+
anchor2 = node;
|
|
842
|
+
}
|
|
843
|
+
} else {
|
|
844
|
+
let currentNode = anchor.nextSibling;
|
|
845
|
+
for (let i = 0; i < newLength; i++) {
|
|
846
|
+
const node = newElements[i];
|
|
847
|
+
if (currentNode !== node) {
|
|
848
|
+
parent.insertBefore(node, currentNode);
|
|
849
|
+
} else {
|
|
850
|
+
currentNode = currentNode.nextSibling;
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
nodeMap.clear();
|
|
855
|
+
for (let i = 0; i < newLength; i++) {
|
|
856
|
+
const itemKey = currentKey(newList[i], i, newList);
|
|
857
|
+
nodeMap.set(itemKey, newElements[i]);
|
|
858
|
+
}
|
|
859
|
+
anchor.__kt_for_list__ = newElements;
|
|
1070
860
|
return anchor;
|
|
861
|
+
};
|
|
862
|
+
const { key: currentKey = (item) => item, map: currentMap } = props;
|
|
863
|
+
const listRef = toReactive(props.list, redraw);
|
|
864
|
+
const anchor = document.createComment("kt-for");
|
|
865
|
+
const nodeMap = /* @__PURE__ */ new Map();
|
|
866
|
+
const elements = [];
|
|
867
|
+
for (let index = 0; index < listRef.value.length; index++) {
|
|
868
|
+
const item = listRef.value[index];
|
|
869
|
+
const itemKey = currentKey(item, index, listRef.value);
|
|
870
|
+
const node = currentMap(item, index, listRef.value);
|
|
871
|
+
nodeMap.set(itemKey, node);
|
|
872
|
+
elements.push(node);
|
|
873
|
+
}
|
|
874
|
+
anchor.__kt_for_list__ = elements;
|
|
875
|
+
$initRef(props, anchor);
|
|
876
|
+
return anchor;
|
|
1071
877
|
}
|
|
1072
|
-
// Longest Increasing Subsequence algorithm (optimized for diff)
|
|
1073
878
|
function getSequence(arr) {
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
}
|
|
1112
|
-
return result;
|
|
879
|
+
const p = arr.slice();
|
|
880
|
+
const result = [0];
|
|
881
|
+
let i, j, u, v, c;
|
|
882
|
+
const len = arr.length;
|
|
883
|
+
for (i = 0; i < len; i++) {
|
|
884
|
+
const arrI = arr[i];
|
|
885
|
+
if (arrI === -1) continue;
|
|
886
|
+
j = result[result.length - 1];
|
|
887
|
+
if (arr[j] < arrI) {
|
|
888
|
+
p[i] = j;
|
|
889
|
+
result.push(i);
|
|
890
|
+
continue;
|
|
891
|
+
}
|
|
892
|
+
u = 0;
|
|
893
|
+
v = result.length - 1;
|
|
894
|
+
while (u < v) {
|
|
895
|
+
c = (u + v) / 2 | 0;
|
|
896
|
+
if (arr[result[c]] < arrI) {
|
|
897
|
+
u = c + 1;
|
|
898
|
+
} else {
|
|
899
|
+
v = c;
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
if (arrI < arr[result[u]]) {
|
|
903
|
+
if (u > 0) {
|
|
904
|
+
p[i] = result[u - 1];
|
|
905
|
+
}
|
|
906
|
+
result[u] = i;
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
u = result.length;
|
|
910
|
+
v = result[u - 1];
|
|
911
|
+
while (u-- > 0) {
|
|
912
|
+
result[u] = v;
|
|
913
|
+
v = p[v];
|
|
914
|
+
}
|
|
915
|
+
return result;
|
|
1113
916
|
}
|
|
1114
917
|
|
|
1115
|
-
export { $
|
|
918
|
+
export { $initRef, $modelOrRef, Fragment, KTAsync, KTComputed, KTFor, KTReactiveType, KTRef, computed, h as createElement, createRedrawable, dereactive, effect, h, isComputed, isKT, isRef, jsx, jsxDEV, jsxs, ref, surfaceRef, toReactive, toRef };
|