@ktjs/core 0.15.5 → 0.16.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 +64 -2
- package/dist/index.d.ts +80 -4
- package/dist/index.iife.js +199 -1
- package/dist/index.legacy.js +199 -1
- package/dist/index.mjs +198 -2
- package/dist/jsx/index.d.ts +20 -2
- package/dist/jsx/index.mjs +1 -1
- package/dist/jsx/jsx-runtime.d.ts +20 -2
- package/dist/jsx/jsx-runtime.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ Core DOM manipulation utilities for KT.js framework with built-in JSX/TSX suppor
|
|
|
12
12
|
|
|
13
13
|
`@ktjs/core` is the foundation of KT.js, providing the essential `h` function and DOM utilities for building web applications with direct DOM manipulation. It emphasizes performance, type safety, and minimal abstraction over native DOM APIs.
|
|
14
14
|
|
|
15
|
-
**Current Version:** 0.
|
|
15
|
+
**Current Version:** 0.16.0
|
|
16
16
|
|
|
17
17
|
## Features
|
|
18
18
|
|
|
@@ -28,6 +28,12 @@ Core DOM manipulation utilities for KT.js framework with built-in JSX/TSX suppor
|
|
|
28
28
|
- `redraw()` method for controlled re-rendering
|
|
29
29
|
- **k-if directive**: Conditional element creation with `k-if` attribute
|
|
30
30
|
- Array children support for seamless list rendering
|
|
31
|
+
- **KTFor Component**: Efficient list rendering with key-based optimization (v0.16.0)
|
|
32
|
+
- Key-based DOM reuse similar to Svelte's `{#each}` blocks
|
|
33
|
+
- Minimal DOM operations - only updates what changed
|
|
34
|
+
- Returns Comment anchor node for flexible positioning
|
|
35
|
+
- Type-safe with full TypeScript generics support
|
|
36
|
+
- `KTForStatic` variant for simple lists without key optimization
|
|
31
37
|
- **KTAsync Component**: Handle async components with ease
|
|
32
38
|
- Automatic handling of Promise-based components
|
|
33
39
|
- Seamless integration with JSX/TSX
|
|
@@ -200,6 +206,62 @@ const div = (<div>Old content</div>) as KTHTMLElement;
|
|
|
200
206
|
div.redraw(undefined, 'New content');
|
|
201
207
|
```
|
|
202
208
|
|
|
209
|
+
### List Rendering with KTFor (v0.16.0)
|
|
210
|
+
|
|
211
|
+
The `KTFor` component provides efficient list rendering with key-based DOM reuse:
|
|
212
|
+
|
|
213
|
+
```tsx
|
|
214
|
+
import { KTFor, KTForStatic, KTForAnchor } from '@ktjs/core';
|
|
215
|
+
|
|
216
|
+
interface Todo {
|
|
217
|
+
id: number;
|
|
218
|
+
text: string;
|
|
219
|
+
done: boolean;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
let todos: Todo[] = [
|
|
223
|
+
{ id: 1, text: 'Buy milk', done: false },
|
|
224
|
+
{ id: 2, text: 'Write code', done: true },
|
|
225
|
+
];
|
|
226
|
+
|
|
227
|
+
// Create optimized list with key-based reuse
|
|
228
|
+
const todoList = (
|
|
229
|
+
<KTFor
|
|
230
|
+
list={todos}
|
|
231
|
+
key={(item) => item.id} // Stable key for efficient updates
|
|
232
|
+
mapper={(item, index) => (
|
|
233
|
+
<div class={`todo ${item.done ? 'done' : ''}`}>
|
|
234
|
+
<input type="checkbox" checked={item.done} />
|
|
235
|
+
<span>{item.text}</span>
|
|
236
|
+
<button on:click={() => deleteTodo(item.id)}>Delete</button>
|
|
237
|
+
</div>
|
|
238
|
+
)}
|
|
239
|
+
/>
|
|
240
|
+
) as KTForAnchor;
|
|
241
|
+
|
|
242
|
+
// Add to DOM (anchor + all items are rendered)
|
|
243
|
+
document.body.appendChild(todoList);
|
|
244
|
+
|
|
245
|
+
// Update the list - only changed items are updated
|
|
246
|
+
todos = [...todos, { id: 3, text: 'New task', done: false }];
|
|
247
|
+
todoList.redraw({ list: todos });
|
|
248
|
+
|
|
249
|
+
// For simple static lists, use KTForStatic (no key optimization)
|
|
250
|
+
const simpleList = (
|
|
251
|
+
<KTForStatic list={['Apple', 'Banana', 'Orange']} mapper={(item) => <div>{item}</div>} />
|
|
252
|
+
) as KTForAnchor;
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**How it works:**
|
|
256
|
+
|
|
257
|
+
- Returns a Comment node (`<!-- kt-for -->`) as anchor point
|
|
258
|
+
- All list items are rendered as siblings after the anchor
|
|
259
|
+
- Uses key-based diff algorithm to reuse DOM nodes
|
|
260
|
+
- Only adds/removes/moves nodes that changed
|
|
261
|
+
- Similar to Svelte's `{#each}` blocks
|
|
262
|
+
|
|
263
|
+
````
|
|
264
|
+
|
|
203
265
|
### Array Children Support (v0.14.1+)
|
|
204
266
|
|
|
205
267
|
Children can now be arrays for easier list rendering:
|
|
@@ -231,7 +293,7 @@ const TodoList = ({ todos }: { todos: string[] }) => (
|
|
|
231
293
|
</ul>
|
|
232
294
|
</div>
|
|
233
295
|
);
|
|
234
|
-
|
|
296
|
+
````
|
|
235
297
|
|
|
236
298
|
### Async Components
|
|
237
299
|
|
package/dist/index.d.ts
CHANGED
|
@@ -98,7 +98,7 @@ interface KTBaseAttribute {
|
|
|
98
98
|
title?: string;
|
|
99
99
|
placeholder?: string;
|
|
100
100
|
contenteditable?: boolean;
|
|
101
|
-
value?:
|
|
101
|
+
value?: any;
|
|
102
102
|
valueAsDate?: Date;
|
|
103
103
|
valueAsNumber?: number;
|
|
104
104
|
label?: string;
|
|
@@ -120,12 +120,30 @@ type KTPrefixedEventHandlers = {
|
|
|
120
120
|
};
|
|
121
121
|
|
|
122
122
|
type KTSpecialEventHandlers = {
|
|
123
|
+
/**
|
|
124
|
+
* Directly extract `value` from the input element
|
|
125
|
+
*/
|
|
123
126
|
'on:ktchange'?: (value: string) => void;
|
|
127
|
+
/**
|
|
128
|
+
* Directly extract `value` and trim it
|
|
129
|
+
*/
|
|
124
130
|
'ontrim:ktchange'?: (value: string) => void;
|
|
131
|
+
/**
|
|
132
|
+
* Directly extract `value` and parse it to number
|
|
133
|
+
*/
|
|
125
134
|
'on:ktchangenumber'?: (value: number) => void;
|
|
126
135
|
|
|
136
|
+
/**
|
|
137
|
+
* Directly extract `value` from the input element
|
|
138
|
+
*/
|
|
127
139
|
'on:ktinput'?: (value: string) => void;
|
|
140
|
+
/**
|
|
141
|
+
* Directly extract `value` and trim it
|
|
142
|
+
*/
|
|
128
143
|
'ontrim:ktinput'?: (value: string) => void;
|
|
144
|
+
/**
|
|
145
|
+
* Directly extract `value` and parse it to number
|
|
146
|
+
*/
|
|
129
147
|
'on:ktinputnumber'?: (value: number) => void;
|
|
130
148
|
};
|
|
131
149
|
|
|
@@ -150,7 +168,7 @@ type HTML<T extends (HTMLTag | SVGTag) & otherstring> = T extends SVGTag ? SVGEl
|
|
|
150
168
|
* ## About
|
|
151
169
|
* @package @ktjs/core
|
|
152
170
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
153
|
-
* @version 0.
|
|
171
|
+
* @version 0.16.0 (Last Update: 2026.01.27 17:30:39.673)
|
|
154
172
|
* @license MIT
|
|
155
173
|
* @link https://github.com/baendlorel/kt.js
|
|
156
174
|
* @link https://baendlorel.github.io/ Welcome to my site!
|
|
@@ -224,5 +242,63 @@ declare function KTAsync<T extends KTComponent>(props: {
|
|
|
224
242
|
children?: KTRawContent;
|
|
225
243
|
} & ExtractComponentProps<T>): KTHTMLElement;
|
|
226
244
|
|
|
227
|
-
|
|
228
|
-
|
|
245
|
+
interface KTForProps<T> {
|
|
246
|
+
list: T[];
|
|
247
|
+
/**
|
|
248
|
+
* Key function to uniquely identify each item
|
|
249
|
+
* Using stable keys enables efficient DOM reuse and updates
|
|
250
|
+
*/
|
|
251
|
+
key: (item: T, index: number) => string | number;
|
|
252
|
+
/**
|
|
253
|
+
* Mapper function to render each item
|
|
254
|
+
*/
|
|
255
|
+
mapper: (item: T, index: number) => HTMLElement;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Extended Comment node with redraw capability for KTFor
|
|
259
|
+
*/
|
|
260
|
+
interface KTForAnchor extends Comment {
|
|
261
|
+
redraw: (newProps?: {
|
|
262
|
+
list?: any[];
|
|
263
|
+
mapper?: (item: any, index: number) => HTMLElement;
|
|
264
|
+
}) => void;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* KTFor component - Efficient list rendering with key-based DOM reuse
|
|
268
|
+
* Similar to Svelte's {#each} blocks, provides optimized updates
|
|
269
|
+
*
|
|
270
|
+
* Returns a Comment node as anchor point. All list items are rendered after this anchor.
|
|
271
|
+
*
|
|
272
|
+
* @example
|
|
273
|
+
* ```tsx
|
|
274
|
+
* const listAnchor = <KTFor
|
|
275
|
+
* list={items}
|
|
276
|
+
* key={(item) => item.id}
|
|
277
|
+
* mapper={(item) => <div>{item.name}</div>}
|
|
278
|
+
* /> as KTForAnchor;
|
|
279
|
+
*
|
|
280
|
+
* document.body.appendChild(listAnchor); // Anchor + all items are rendered
|
|
281
|
+
*
|
|
282
|
+
* // Update the list
|
|
283
|
+
* listAnchor.redraw({ list: newItems });
|
|
284
|
+
* ```
|
|
285
|
+
*/
|
|
286
|
+
declare function KTFor<T>(props: KTForProps<T>): KTForAnchor;
|
|
287
|
+
/**
|
|
288
|
+
* Simple list rendering without key optimization
|
|
289
|
+
* Rebuilds the entire list on each update - use for small static lists
|
|
290
|
+
*
|
|
291
|
+
* Returns a Comment anchor node. All items are rendered after this anchor.
|
|
292
|
+
*
|
|
293
|
+
* @example
|
|
294
|
+
* ```tsx
|
|
295
|
+
* const listAnchor = <KTForStatic
|
|
296
|
+
* list={items}
|
|
297
|
+
* mapper={(item) => <div>{item}</div>}
|
|
298
|
+
* /> as KTForAnchor;
|
|
299
|
+
* ```
|
|
300
|
+
*/
|
|
301
|
+
declare function KTForStatic<T>(props: Omit<KTForProps<T>, 'key'>): KTForAnchor;
|
|
302
|
+
|
|
303
|
+
export { Fragment, KTAsync, KTFor, KTForStatic, h as createElement, createRedrawable, createRedrawableNoref, h, jsx, jsxDEV, jsxs, ref };
|
|
304
|
+
export type { EventHandler, HTMLTag, KTAttribute, KTForAnchor, KTForProps, KTHTMLElement, KTRawAttr, KTRawContent, KTRawContents, KTRef };
|
package/dist/index.iife.js
CHANGED
|
@@ -206,7 +206,7 @@ var __ktjs_core__ = (function (exports) {
|
|
|
206
206
|
* ## About
|
|
207
207
|
* @package @ktjs/core
|
|
208
208
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
209
|
-
* @version 0.
|
|
209
|
+
* @version 0.16.0 (Last Update: 2026.01.27 17:30:39.673)
|
|
210
210
|
* @license MIT
|
|
211
211
|
* @link https://github.com/baendlorel/kt.js
|
|
212
212
|
* @link https://baendlorel.github.io/ Welcome to my site!
|
|
@@ -378,8 +378,206 @@ var __ktjs_core__ = (function (exports) {
|
|
|
378
378
|
return comp;
|
|
379
379
|
}
|
|
380
380
|
|
|
381
|
+
/**
|
|
382
|
+
* KTFor component - Efficient list rendering with key-based DOM reuse
|
|
383
|
+
* Similar to Svelte's {#each} blocks, provides optimized updates
|
|
384
|
+
*
|
|
385
|
+
* Returns a Comment node as anchor point. All list items are rendered after this anchor.
|
|
386
|
+
*
|
|
387
|
+
* @example
|
|
388
|
+
* ```tsx
|
|
389
|
+
* const listAnchor = <KTFor
|
|
390
|
+
* list={items}
|
|
391
|
+
* key={(item) => item.id}
|
|
392
|
+
* mapper={(item) => <div>{item.name}</div>}
|
|
393
|
+
* /> as KTForAnchor;
|
|
394
|
+
*
|
|
395
|
+
* document.body.appendChild(listAnchor); // Anchor + all items are rendered
|
|
396
|
+
*
|
|
397
|
+
* // Update the list
|
|
398
|
+
* listAnchor.redraw({ list: newItems });
|
|
399
|
+
* ```
|
|
400
|
+
*/
|
|
401
|
+
function KTFor(props) {
|
|
402
|
+
const { list: initList, key: getKey, mapper } = props;
|
|
403
|
+
// Cache: key -> { node: HTMLElement, item: T }
|
|
404
|
+
const nodeCache = new Map();
|
|
405
|
+
// Current key order
|
|
406
|
+
let currentKeys = [];
|
|
407
|
+
// Create anchor comment node - marks the position of the list
|
|
408
|
+
const anchor = document.createComment('kt-for');
|
|
409
|
+
/**
|
|
410
|
+
* Get all nodes currently in the DOM that belong to this list
|
|
411
|
+
* They are all siblings after the anchor node
|
|
412
|
+
*/
|
|
413
|
+
const getListNodes = () => {
|
|
414
|
+
const nodes = [];
|
|
415
|
+
if (!anchor.parentNode)
|
|
416
|
+
return nodes;
|
|
417
|
+
let current = anchor.nextSibling;
|
|
418
|
+
new Set(currentKeys);
|
|
419
|
+
// Collect nodes that belong to this list
|
|
420
|
+
while (current) {
|
|
421
|
+
const isListNode = Array.from(nodeCache.values()).some((cached) => cached.node === current);
|
|
422
|
+
if (!isListNode)
|
|
423
|
+
break;
|
|
424
|
+
nodes.push(current);
|
|
425
|
+
current = current.nextSibling;
|
|
426
|
+
}
|
|
427
|
+
return nodes;
|
|
428
|
+
};
|
|
429
|
+
/**
|
|
430
|
+
* Initialize list - append all initial items after anchor
|
|
431
|
+
*/
|
|
432
|
+
const initialize = () => {
|
|
433
|
+
for (let i = 0; i < initList.length; i++) {
|
|
434
|
+
const item = initList[i];
|
|
435
|
+
const key = getKey(item, i);
|
|
436
|
+
const node = mapper(item, i);
|
|
437
|
+
nodeCache.set(key, { node, item });
|
|
438
|
+
currentKeys.push(key);
|
|
439
|
+
// Append to parent if anchor is already in DOM
|
|
440
|
+
if (anchor.parentNode) {
|
|
441
|
+
const lastNode = getListNodes()[getListNodes().length - 1];
|
|
442
|
+
if (lastNode) {
|
|
443
|
+
lastNode.after(node);
|
|
444
|
+
}
|
|
445
|
+
else {
|
|
446
|
+
anchor.after(node);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
/**
|
|
452
|
+
* Smart update method - only modifies DOM nodes that changed
|
|
453
|
+
* Uses key-based diff algorithm to minimize DOM operations
|
|
454
|
+
*/
|
|
455
|
+
const smartUpdate = (newList, newMapper) => {
|
|
456
|
+
const mapperFn = newMapper ?? mapper;
|
|
457
|
+
const newKeys = newList.map((item, index) => getKey(item, index));
|
|
458
|
+
if (!anchor.parentNode) {
|
|
459
|
+
// If anchor is not in DOM yet, just update cache
|
|
460
|
+
nodeCache.clear();
|
|
461
|
+
currentKeys = [];
|
|
462
|
+
for (let i = 0; i < newList.length; i++) {
|
|
463
|
+
const item = newList[i];
|
|
464
|
+
const key = newKeys[i];
|
|
465
|
+
const node = mapperFn(item, i);
|
|
466
|
+
nodeCache.set(key, { node, item });
|
|
467
|
+
currentKeys.push(key);
|
|
468
|
+
}
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
// Find keys to remove (exist in current but not in new)
|
|
472
|
+
const keysToRemove = currentKeys.filter((k) => !newKeys.includes(k));
|
|
473
|
+
for (let i = 0; i < keysToRemove.length; i++) {
|
|
474
|
+
const key = keysToRemove[i];
|
|
475
|
+
const cached = nodeCache.get(key);
|
|
476
|
+
if (cached && cached.node.parentNode) {
|
|
477
|
+
cached.node.parentNode.removeChild(cached.node);
|
|
478
|
+
}
|
|
479
|
+
nodeCache.delete(key);
|
|
480
|
+
}
|
|
481
|
+
// Update/add nodes in correct order
|
|
482
|
+
let previousNode = anchor;
|
|
483
|
+
for (let i = 0; i < newList.length; i++) {
|
|
484
|
+
const item = newList[i];
|
|
485
|
+
const key = newKeys[i];
|
|
486
|
+
let cached = nodeCache.get(key);
|
|
487
|
+
// New item: create and cache
|
|
488
|
+
if (!cached) {
|
|
489
|
+
const node = mapperFn(item, i);
|
|
490
|
+
cached = { node, item };
|
|
491
|
+
nodeCache.set(key, cached);
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
// Update cached item reference
|
|
495
|
+
cached.item = item;
|
|
496
|
+
}
|
|
497
|
+
// Ensure node is at correct position (right after previousNode)
|
|
498
|
+
if (previousNode.nextSibling !== cached.node) {
|
|
499
|
+
if (previousNode.nextSibling) {
|
|
500
|
+
anchor.parentNode.insertBefore(cached.node, previousNode.nextSibling);
|
|
501
|
+
}
|
|
502
|
+
else {
|
|
503
|
+
anchor.parentNode.appendChild(cached.node);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
previousNode = cached.node;
|
|
507
|
+
}
|
|
508
|
+
currentKeys = newKeys;
|
|
509
|
+
};
|
|
510
|
+
// Mount redraw method on anchor
|
|
511
|
+
anchor.redraw = (newProps) => {
|
|
512
|
+
if (newProps?.list) {
|
|
513
|
+
smartUpdate(newProps.list, newProps.mapper);
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
// Initialize the list
|
|
517
|
+
initialize();
|
|
518
|
+
return anchor;
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Simple list rendering without key optimization
|
|
522
|
+
* Rebuilds the entire list on each update - use for small static lists
|
|
523
|
+
*
|
|
524
|
+
* Returns a Comment anchor node. All items are rendered after this anchor.
|
|
525
|
+
*
|
|
526
|
+
* @example
|
|
527
|
+
* ```tsx
|
|
528
|
+
* const listAnchor = <KTForStatic
|
|
529
|
+
* list={items}
|
|
530
|
+
* mapper={(item) => <div>{item}</div>}
|
|
531
|
+
* /> as KTForAnchor;
|
|
532
|
+
* ```
|
|
533
|
+
*/
|
|
534
|
+
function KTForStatic(props) {
|
|
535
|
+
const { list: initList, mapper } = props;
|
|
536
|
+
// Create anchor comment node
|
|
537
|
+
const anchor = document.createComment('kt-for-static');
|
|
538
|
+
let nodes = [];
|
|
539
|
+
// Simple rebuild on redraw
|
|
540
|
+
const rebuild = (newList) => {
|
|
541
|
+
// Remove all old nodes
|
|
542
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
543
|
+
const node = nodes[i];
|
|
544
|
+
if (node.parentNode) {
|
|
545
|
+
node.parentNode.removeChild(node);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
nodes = [];
|
|
549
|
+
// Create new nodes
|
|
550
|
+
let previousNode = anchor;
|
|
551
|
+
for (let i = 0; i < newList.length; i++) {
|
|
552
|
+
const item = newList[i];
|
|
553
|
+
const node = mapper(item, i);
|
|
554
|
+
nodes.push(node);
|
|
555
|
+
if (anchor.parentNode) {
|
|
556
|
+
if (previousNode.nextSibling) {
|
|
557
|
+
anchor.parentNode.insertBefore(node, previousNode.nextSibling);
|
|
558
|
+
}
|
|
559
|
+
else {
|
|
560
|
+
anchor.parentNode.appendChild(node);
|
|
561
|
+
}
|
|
562
|
+
previousNode = node;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
};
|
|
566
|
+
// Initial render
|
|
567
|
+
rebuild(initList);
|
|
568
|
+
// Mount redraw
|
|
569
|
+
anchor.redraw = (newProps) => {
|
|
570
|
+
if (newProps?.list) {
|
|
571
|
+
rebuild(newProps.list);
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
return anchor;
|
|
575
|
+
}
|
|
576
|
+
|
|
381
577
|
exports.Fragment = Fragment;
|
|
382
578
|
exports.KTAsync = KTAsync;
|
|
579
|
+
exports.KTFor = KTFor;
|
|
580
|
+
exports.KTForStatic = KTForStatic;
|
|
383
581
|
exports.createElement = h;
|
|
384
582
|
exports.createRedrawable = createRedrawable;
|
|
385
583
|
exports.createRedrawableNoref = createRedrawableNoref;
|
package/dist/index.legacy.js
CHANGED
|
@@ -231,7 +231,7 @@ var __ktjs_core__ = (function (exports) {
|
|
|
231
231
|
* ## About
|
|
232
232
|
* @package @ktjs/core
|
|
233
233
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
234
|
-
* @version 0.
|
|
234
|
+
* @version 0.16.0 (Last Update: 2026.01.27 17:30:39.673)
|
|
235
235
|
* @license MIT
|
|
236
236
|
* @link https://github.com/baendlorel/kt.js
|
|
237
237
|
* @link https://baendlorel.github.io/ Welcome to my site!
|
|
@@ -443,8 +443,206 @@ var __ktjs_core__ = (function (exports) {
|
|
|
443
443
|
return comp;
|
|
444
444
|
}
|
|
445
445
|
|
|
446
|
+
/**
|
|
447
|
+
* KTFor component - Efficient list rendering with key-based DOM reuse
|
|
448
|
+
* Similar to Svelte's {#each} blocks, provides optimized updates
|
|
449
|
+
*
|
|
450
|
+
* Returns a Comment node as anchor point. All list items are rendered after this anchor.
|
|
451
|
+
*
|
|
452
|
+
* @example
|
|
453
|
+
* ```tsx
|
|
454
|
+
* const listAnchor = <KTFor
|
|
455
|
+
* list={items}
|
|
456
|
+
* key={(item) => item.id}
|
|
457
|
+
* mapper={(item) => <div>{item.name}</div>}
|
|
458
|
+
* /> as KTForAnchor;
|
|
459
|
+
*
|
|
460
|
+
* document.body.appendChild(listAnchor); // Anchor + all items are rendered
|
|
461
|
+
*
|
|
462
|
+
* // Update the list
|
|
463
|
+
* listAnchor.redraw({ list: newItems });
|
|
464
|
+
* ```
|
|
465
|
+
*/
|
|
466
|
+
function KTFor(props) {
|
|
467
|
+
var initList = props.list, getKey = props.key, mapper = props.mapper;
|
|
468
|
+
// Cache: key -> { node: HTMLElement, item: T }
|
|
469
|
+
var nodeCache = new Map();
|
|
470
|
+
// Current key order
|
|
471
|
+
var currentKeys = [];
|
|
472
|
+
// Create anchor comment node - marks the position of the list
|
|
473
|
+
var anchor = document.createComment('kt-for');
|
|
474
|
+
/**
|
|
475
|
+
* Get all nodes currently in the DOM that belong to this list
|
|
476
|
+
* They are all siblings after the anchor node
|
|
477
|
+
*/
|
|
478
|
+
var getListNodes = function () {
|
|
479
|
+
var nodes = [];
|
|
480
|
+
if (!anchor.parentNode)
|
|
481
|
+
return nodes;
|
|
482
|
+
var current = anchor.nextSibling;
|
|
483
|
+
new Set(currentKeys);
|
|
484
|
+
// Collect nodes that belong to this list
|
|
485
|
+
while (current) {
|
|
486
|
+
var isListNode = Array.from(nodeCache.values()).some(function (cached) { return cached.node === current; });
|
|
487
|
+
if (!isListNode)
|
|
488
|
+
break;
|
|
489
|
+
nodes.push(current);
|
|
490
|
+
current = current.nextSibling;
|
|
491
|
+
}
|
|
492
|
+
return nodes;
|
|
493
|
+
};
|
|
494
|
+
/**
|
|
495
|
+
* Initialize list - append all initial items after anchor
|
|
496
|
+
*/
|
|
497
|
+
var initialize = function () {
|
|
498
|
+
for (var i = 0; i < initList.length; i++) {
|
|
499
|
+
var item = initList[i];
|
|
500
|
+
var key = getKey(item, i);
|
|
501
|
+
var node = mapper(item, i);
|
|
502
|
+
nodeCache.set(key, { node: node, item: item });
|
|
503
|
+
currentKeys.push(key);
|
|
504
|
+
// Append to parent if anchor is already in DOM
|
|
505
|
+
if (anchor.parentNode) {
|
|
506
|
+
var lastNode = getListNodes()[getListNodes().length - 1];
|
|
507
|
+
if (lastNode) {
|
|
508
|
+
lastNode.after(node);
|
|
509
|
+
}
|
|
510
|
+
else {
|
|
511
|
+
anchor.after(node);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
/**
|
|
517
|
+
* Smart update method - only modifies DOM nodes that changed
|
|
518
|
+
* Uses key-based diff algorithm to minimize DOM operations
|
|
519
|
+
*/
|
|
520
|
+
var smartUpdate = function (newList, newMapper) {
|
|
521
|
+
var mapperFn = newMapper !== null && newMapper !== void 0 ? newMapper : mapper;
|
|
522
|
+
var newKeys = newList.map(function (item, index) { return getKey(item, index); });
|
|
523
|
+
if (!anchor.parentNode) {
|
|
524
|
+
// If anchor is not in DOM yet, just update cache
|
|
525
|
+
nodeCache.clear();
|
|
526
|
+
currentKeys = [];
|
|
527
|
+
for (var i = 0; i < newList.length; i++) {
|
|
528
|
+
var item = newList[i];
|
|
529
|
+
var key = newKeys[i];
|
|
530
|
+
var node = mapperFn(item, i);
|
|
531
|
+
nodeCache.set(key, { node: node, item: item });
|
|
532
|
+
currentKeys.push(key);
|
|
533
|
+
}
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
// Find keys to remove (exist in current but not in new)
|
|
537
|
+
var keysToRemove = currentKeys.filter(function (k) { return !newKeys.includes(k); });
|
|
538
|
+
for (var i = 0; i < keysToRemove.length; i++) {
|
|
539
|
+
var key = keysToRemove[i];
|
|
540
|
+
var cached = nodeCache.get(key);
|
|
541
|
+
if (cached && cached.node.parentNode) {
|
|
542
|
+
cached.node.parentNode.removeChild(cached.node);
|
|
543
|
+
}
|
|
544
|
+
nodeCache.delete(key);
|
|
545
|
+
}
|
|
546
|
+
// Update/add nodes in correct order
|
|
547
|
+
var previousNode = anchor;
|
|
548
|
+
for (var i = 0; i < newList.length; i++) {
|
|
549
|
+
var item = newList[i];
|
|
550
|
+
var key = newKeys[i];
|
|
551
|
+
var cached = nodeCache.get(key);
|
|
552
|
+
// New item: create and cache
|
|
553
|
+
if (!cached) {
|
|
554
|
+
var node = mapperFn(item, i);
|
|
555
|
+
cached = { node: node, item: item };
|
|
556
|
+
nodeCache.set(key, cached);
|
|
557
|
+
}
|
|
558
|
+
else {
|
|
559
|
+
// Update cached item reference
|
|
560
|
+
cached.item = item;
|
|
561
|
+
}
|
|
562
|
+
// Ensure node is at correct position (right after previousNode)
|
|
563
|
+
if (previousNode.nextSibling !== cached.node) {
|
|
564
|
+
if (previousNode.nextSibling) {
|
|
565
|
+
anchor.parentNode.insertBefore(cached.node, previousNode.nextSibling);
|
|
566
|
+
}
|
|
567
|
+
else {
|
|
568
|
+
anchor.parentNode.appendChild(cached.node);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
previousNode = cached.node;
|
|
572
|
+
}
|
|
573
|
+
currentKeys = newKeys;
|
|
574
|
+
};
|
|
575
|
+
// Mount redraw method on anchor
|
|
576
|
+
anchor.redraw = function (newProps) {
|
|
577
|
+
if (newProps === null || newProps === void 0 ? void 0 : newProps.list) {
|
|
578
|
+
smartUpdate(newProps.list, newProps.mapper);
|
|
579
|
+
}
|
|
580
|
+
};
|
|
581
|
+
// Initialize the list
|
|
582
|
+
initialize();
|
|
583
|
+
return anchor;
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Simple list rendering without key optimization
|
|
587
|
+
* Rebuilds the entire list on each update - use for small static lists
|
|
588
|
+
*
|
|
589
|
+
* Returns a Comment anchor node. All items are rendered after this anchor.
|
|
590
|
+
*
|
|
591
|
+
* @example
|
|
592
|
+
* ```tsx
|
|
593
|
+
* const listAnchor = <KTForStatic
|
|
594
|
+
* list={items}
|
|
595
|
+
* mapper={(item) => <div>{item}</div>}
|
|
596
|
+
* /> as KTForAnchor;
|
|
597
|
+
* ```
|
|
598
|
+
*/
|
|
599
|
+
function KTForStatic(props) {
|
|
600
|
+
var initList = props.list, mapper = props.mapper;
|
|
601
|
+
// Create anchor comment node
|
|
602
|
+
var anchor = document.createComment('kt-for-static');
|
|
603
|
+
var nodes = [];
|
|
604
|
+
// Simple rebuild on redraw
|
|
605
|
+
var rebuild = function (newList) {
|
|
606
|
+
// Remove all old nodes
|
|
607
|
+
for (var i = 0; i < nodes.length; i++) {
|
|
608
|
+
var node = nodes[i];
|
|
609
|
+
if (node.parentNode) {
|
|
610
|
+
node.parentNode.removeChild(node);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
nodes = [];
|
|
614
|
+
// Create new nodes
|
|
615
|
+
var previousNode = anchor;
|
|
616
|
+
for (var i = 0; i < newList.length; i++) {
|
|
617
|
+
var item = newList[i];
|
|
618
|
+
var node = mapper(item, i);
|
|
619
|
+
nodes.push(node);
|
|
620
|
+
if (anchor.parentNode) {
|
|
621
|
+
if (previousNode.nextSibling) {
|
|
622
|
+
anchor.parentNode.insertBefore(node, previousNode.nextSibling);
|
|
623
|
+
}
|
|
624
|
+
else {
|
|
625
|
+
anchor.parentNode.appendChild(node);
|
|
626
|
+
}
|
|
627
|
+
previousNode = node;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
// Initial render
|
|
632
|
+
rebuild(initList);
|
|
633
|
+
// Mount redraw
|
|
634
|
+
anchor.redraw = function (newProps) {
|
|
635
|
+
if (newProps === null || newProps === void 0 ? void 0 : newProps.list) {
|
|
636
|
+
rebuild(newProps.list);
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
return anchor;
|
|
640
|
+
}
|
|
641
|
+
|
|
446
642
|
exports.Fragment = Fragment;
|
|
447
643
|
exports.KTAsync = KTAsync;
|
|
644
|
+
exports.KTFor = KTFor;
|
|
645
|
+
exports.KTForStatic = KTForStatic;
|
|
448
646
|
exports.createElement = h;
|
|
449
647
|
exports.createRedrawable = createRedrawable;
|
|
450
648
|
exports.createRedrawableNoref = createRedrawableNoref;
|
package/dist/index.mjs
CHANGED
|
@@ -203,7 +203,7 @@ let creator = defaultCreator;
|
|
|
203
203
|
* ## About
|
|
204
204
|
* @package @ktjs/core
|
|
205
205
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
206
|
-
* @version 0.
|
|
206
|
+
* @version 0.16.0 (Last Update: 2026.01.27 17:30:39.673)
|
|
207
207
|
* @license MIT
|
|
208
208
|
* @link https://github.com/baendlorel/kt.js
|
|
209
209
|
* @link https://baendlorel.github.io/ Welcome to my site!
|
|
@@ -375,4 +375,200 @@ function KTAsync(props) {
|
|
|
375
375
|
return comp;
|
|
376
376
|
}
|
|
377
377
|
|
|
378
|
-
|
|
378
|
+
/**
|
|
379
|
+
* KTFor component - Efficient list rendering with key-based DOM reuse
|
|
380
|
+
* Similar to Svelte's {#each} blocks, provides optimized updates
|
|
381
|
+
*
|
|
382
|
+
* Returns a Comment node as anchor point. All list items are rendered after this anchor.
|
|
383
|
+
*
|
|
384
|
+
* @example
|
|
385
|
+
* ```tsx
|
|
386
|
+
* const listAnchor = <KTFor
|
|
387
|
+
* list={items}
|
|
388
|
+
* key={(item) => item.id}
|
|
389
|
+
* mapper={(item) => <div>{item.name}</div>}
|
|
390
|
+
* /> as KTForAnchor;
|
|
391
|
+
*
|
|
392
|
+
* document.body.appendChild(listAnchor); // Anchor + all items are rendered
|
|
393
|
+
*
|
|
394
|
+
* // Update the list
|
|
395
|
+
* listAnchor.redraw({ list: newItems });
|
|
396
|
+
* ```
|
|
397
|
+
*/
|
|
398
|
+
function KTFor(props) {
|
|
399
|
+
const { list: initList, key: getKey, mapper } = props;
|
|
400
|
+
// Cache: key -> { node: HTMLElement, item: T }
|
|
401
|
+
const nodeCache = new Map();
|
|
402
|
+
// Current key order
|
|
403
|
+
let currentKeys = [];
|
|
404
|
+
// Create anchor comment node - marks the position of the list
|
|
405
|
+
const anchor = document.createComment('kt-for');
|
|
406
|
+
/**
|
|
407
|
+
* Get all nodes currently in the DOM that belong to this list
|
|
408
|
+
* They are all siblings after the anchor node
|
|
409
|
+
*/
|
|
410
|
+
const getListNodes = () => {
|
|
411
|
+
const nodes = [];
|
|
412
|
+
if (!anchor.parentNode)
|
|
413
|
+
return nodes;
|
|
414
|
+
let current = anchor.nextSibling;
|
|
415
|
+
new Set(currentKeys);
|
|
416
|
+
// Collect nodes that belong to this list
|
|
417
|
+
while (current) {
|
|
418
|
+
const isListNode = Array.from(nodeCache.values()).some((cached) => cached.node === current);
|
|
419
|
+
if (!isListNode)
|
|
420
|
+
break;
|
|
421
|
+
nodes.push(current);
|
|
422
|
+
current = current.nextSibling;
|
|
423
|
+
}
|
|
424
|
+
return nodes;
|
|
425
|
+
};
|
|
426
|
+
/**
|
|
427
|
+
* Initialize list - append all initial items after anchor
|
|
428
|
+
*/
|
|
429
|
+
const initialize = () => {
|
|
430
|
+
for (let i = 0; i < initList.length; i++) {
|
|
431
|
+
const item = initList[i];
|
|
432
|
+
const key = getKey(item, i);
|
|
433
|
+
const node = mapper(item, i);
|
|
434
|
+
nodeCache.set(key, { node, item });
|
|
435
|
+
currentKeys.push(key);
|
|
436
|
+
// Append to parent if anchor is already in DOM
|
|
437
|
+
if (anchor.parentNode) {
|
|
438
|
+
const lastNode = getListNodes()[getListNodes().length - 1];
|
|
439
|
+
if (lastNode) {
|
|
440
|
+
lastNode.after(node);
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
anchor.after(node);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
/**
|
|
449
|
+
* Smart update method - only modifies DOM nodes that changed
|
|
450
|
+
* Uses key-based diff algorithm to minimize DOM operations
|
|
451
|
+
*/
|
|
452
|
+
const smartUpdate = (newList, newMapper) => {
|
|
453
|
+
const mapperFn = newMapper ?? mapper;
|
|
454
|
+
const newKeys = newList.map((item, index) => getKey(item, index));
|
|
455
|
+
if (!anchor.parentNode) {
|
|
456
|
+
// If anchor is not in DOM yet, just update cache
|
|
457
|
+
nodeCache.clear();
|
|
458
|
+
currentKeys = [];
|
|
459
|
+
for (let i = 0; i < newList.length; i++) {
|
|
460
|
+
const item = newList[i];
|
|
461
|
+
const key = newKeys[i];
|
|
462
|
+
const node = mapperFn(item, i);
|
|
463
|
+
nodeCache.set(key, { node, item });
|
|
464
|
+
currentKeys.push(key);
|
|
465
|
+
}
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
// Find keys to remove (exist in current but not in new)
|
|
469
|
+
const keysToRemove = currentKeys.filter((k) => !newKeys.includes(k));
|
|
470
|
+
for (let i = 0; i < keysToRemove.length; i++) {
|
|
471
|
+
const key = keysToRemove[i];
|
|
472
|
+
const cached = nodeCache.get(key);
|
|
473
|
+
if (cached && cached.node.parentNode) {
|
|
474
|
+
cached.node.parentNode.removeChild(cached.node);
|
|
475
|
+
}
|
|
476
|
+
nodeCache.delete(key);
|
|
477
|
+
}
|
|
478
|
+
// Update/add nodes in correct order
|
|
479
|
+
let previousNode = anchor;
|
|
480
|
+
for (let i = 0; i < newList.length; i++) {
|
|
481
|
+
const item = newList[i];
|
|
482
|
+
const key = newKeys[i];
|
|
483
|
+
let cached = nodeCache.get(key);
|
|
484
|
+
// New item: create and cache
|
|
485
|
+
if (!cached) {
|
|
486
|
+
const node = mapperFn(item, i);
|
|
487
|
+
cached = { node, item };
|
|
488
|
+
nodeCache.set(key, cached);
|
|
489
|
+
}
|
|
490
|
+
else {
|
|
491
|
+
// Update cached item reference
|
|
492
|
+
cached.item = item;
|
|
493
|
+
}
|
|
494
|
+
// Ensure node is at correct position (right after previousNode)
|
|
495
|
+
if (previousNode.nextSibling !== cached.node) {
|
|
496
|
+
if (previousNode.nextSibling) {
|
|
497
|
+
anchor.parentNode.insertBefore(cached.node, previousNode.nextSibling);
|
|
498
|
+
}
|
|
499
|
+
else {
|
|
500
|
+
anchor.parentNode.appendChild(cached.node);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
previousNode = cached.node;
|
|
504
|
+
}
|
|
505
|
+
currentKeys = newKeys;
|
|
506
|
+
};
|
|
507
|
+
// Mount redraw method on anchor
|
|
508
|
+
anchor.redraw = (newProps) => {
|
|
509
|
+
if (newProps?.list) {
|
|
510
|
+
smartUpdate(newProps.list, newProps.mapper);
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
// Initialize the list
|
|
514
|
+
initialize();
|
|
515
|
+
return anchor;
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Simple list rendering without key optimization
|
|
519
|
+
* Rebuilds the entire list on each update - use for small static lists
|
|
520
|
+
*
|
|
521
|
+
* Returns a Comment anchor node. All items are rendered after this anchor.
|
|
522
|
+
*
|
|
523
|
+
* @example
|
|
524
|
+
* ```tsx
|
|
525
|
+
* const listAnchor = <KTForStatic
|
|
526
|
+
* list={items}
|
|
527
|
+
* mapper={(item) => <div>{item}</div>}
|
|
528
|
+
* /> as KTForAnchor;
|
|
529
|
+
* ```
|
|
530
|
+
*/
|
|
531
|
+
function KTForStatic(props) {
|
|
532
|
+
const { list: initList, mapper } = props;
|
|
533
|
+
// Create anchor comment node
|
|
534
|
+
const anchor = document.createComment('kt-for-static');
|
|
535
|
+
let nodes = [];
|
|
536
|
+
// Simple rebuild on redraw
|
|
537
|
+
const rebuild = (newList) => {
|
|
538
|
+
// Remove all old nodes
|
|
539
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
540
|
+
const node = nodes[i];
|
|
541
|
+
if (node.parentNode) {
|
|
542
|
+
node.parentNode.removeChild(node);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
nodes = [];
|
|
546
|
+
// Create new nodes
|
|
547
|
+
let previousNode = anchor;
|
|
548
|
+
for (let i = 0; i < newList.length; i++) {
|
|
549
|
+
const item = newList[i];
|
|
550
|
+
const node = mapper(item, i);
|
|
551
|
+
nodes.push(node);
|
|
552
|
+
if (anchor.parentNode) {
|
|
553
|
+
if (previousNode.nextSibling) {
|
|
554
|
+
anchor.parentNode.insertBefore(node, previousNode.nextSibling);
|
|
555
|
+
}
|
|
556
|
+
else {
|
|
557
|
+
anchor.parentNode.appendChild(node);
|
|
558
|
+
}
|
|
559
|
+
previousNode = node;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
// Initial render
|
|
564
|
+
rebuild(initList);
|
|
565
|
+
// Mount redraw
|
|
566
|
+
anchor.redraw = (newProps) => {
|
|
567
|
+
if (newProps?.list) {
|
|
568
|
+
rebuild(newProps.list);
|
|
569
|
+
}
|
|
570
|
+
};
|
|
571
|
+
return anchor;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
export { Fragment, KTAsync, KTFor, KTForStatic, h as createElement, createRedrawable, createRedrawableNoref, h, jsx, jsxDEV, jsxs, ref };
|
package/dist/jsx/index.d.ts
CHANGED
|
@@ -92,7 +92,7 @@ interface KTBaseAttribute {
|
|
|
92
92
|
title?: string;
|
|
93
93
|
placeholder?: string;
|
|
94
94
|
contenteditable?: boolean;
|
|
95
|
-
value?:
|
|
95
|
+
value?: any;
|
|
96
96
|
valueAsDate?: Date;
|
|
97
97
|
valueAsNumber?: number;
|
|
98
98
|
label?: string;
|
|
@@ -114,12 +114,30 @@ type KTPrefixedEventHandlers = {
|
|
|
114
114
|
};
|
|
115
115
|
|
|
116
116
|
type KTSpecialEventHandlers = {
|
|
117
|
+
/**
|
|
118
|
+
* Directly extract `value` from the input element
|
|
119
|
+
*/
|
|
117
120
|
'on:ktchange'?: (value: string) => void;
|
|
121
|
+
/**
|
|
122
|
+
* Directly extract `value` and trim it
|
|
123
|
+
*/
|
|
118
124
|
'ontrim:ktchange'?: (value: string) => void;
|
|
125
|
+
/**
|
|
126
|
+
* Directly extract `value` and parse it to number
|
|
127
|
+
*/
|
|
119
128
|
'on:ktchangenumber'?: (value: number) => void;
|
|
120
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Directly extract `value` from the input element
|
|
132
|
+
*/
|
|
121
133
|
'on:ktinput'?: (value: string) => void;
|
|
134
|
+
/**
|
|
135
|
+
* Directly extract `value` and trim it
|
|
136
|
+
*/
|
|
122
137
|
'ontrim:ktinput'?: (value: string) => void;
|
|
138
|
+
/**
|
|
139
|
+
* Directly extract `value` and parse it to number
|
|
140
|
+
*/
|
|
123
141
|
'on:ktinputnumber'?: (value: number) => void;
|
|
124
142
|
};
|
|
125
143
|
|
|
@@ -136,7 +154,7 @@ type HTML<T extends (HTMLTag | SVGTag) & otherstring> = T extends SVGTag ? SVGEl
|
|
|
136
154
|
* ## About
|
|
137
155
|
* @package @ktjs/core
|
|
138
156
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
139
|
-
* @version 0.
|
|
157
|
+
* @version 0.16.0 (Last Update: 2026.01.27 17:30:39.673)
|
|
140
158
|
* @license MIT
|
|
141
159
|
* @link https://github.com/baendlorel/kt.js
|
|
142
160
|
* @link https://baendlorel.github.io/ Welcome to my site!
|
package/dist/jsx/index.mjs
CHANGED
|
@@ -203,7 +203,7 @@ let creator = defaultCreator;
|
|
|
203
203
|
* ## About
|
|
204
204
|
* @package @ktjs/core
|
|
205
205
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
206
|
-
* @version 0.
|
|
206
|
+
* @version 0.16.0 (Last Update: 2026.01.27 17:30:39.673)
|
|
207
207
|
* @license MIT
|
|
208
208
|
* @link https://github.com/baendlorel/kt.js
|
|
209
209
|
* @link https://baendlorel.github.io/ Welcome to my site!
|
|
@@ -86,7 +86,7 @@ interface KTBaseAttribute {
|
|
|
86
86
|
title?: string;
|
|
87
87
|
placeholder?: string;
|
|
88
88
|
contenteditable?: boolean;
|
|
89
|
-
value?:
|
|
89
|
+
value?: any;
|
|
90
90
|
valueAsDate?: Date;
|
|
91
91
|
valueAsNumber?: number;
|
|
92
92
|
label?: string;
|
|
@@ -108,12 +108,30 @@ type KTPrefixedEventHandlers = {
|
|
|
108
108
|
};
|
|
109
109
|
|
|
110
110
|
type KTSpecialEventHandlers = {
|
|
111
|
+
/**
|
|
112
|
+
* Directly extract `value` from the input element
|
|
113
|
+
*/
|
|
111
114
|
'on:ktchange'?: (value: string) => void;
|
|
115
|
+
/**
|
|
116
|
+
* Directly extract `value` and trim it
|
|
117
|
+
*/
|
|
112
118
|
'ontrim:ktchange'?: (value: string) => void;
|
|
119
|
+
/**
|
|
120
|
+
* Directly extract `value` and parse it to number
|
|
121
|
+
*/
|
|
113
122
|
'on:ktchangenumber'?: (value: number) => void;
|
|
114
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Directly extract `value` from the input element
|
|
126
|
+
*/
|
|
115
127
|
'on:ktinput'?: (value: string) => void;
|
|
128
|
+
/**
|
|
129
|
+
* Directly extract `value` and trim it
|
|
130
|
+
*/
|
|
116
131
|
'ontrim:ktinput'?: (value: string) => void;
|
|
132
|
+
/**
|
|
133
|
+
* Directly extract `value` and parse it to number
|
|
134
|
+
*/
|
|
117
135
|
'on:ktinputnumber'?: (value: number) => void;
|
|
118
136
|
};
|
|
119
137
|
|
|
@@ -130,7 +148,7 @@ type HTML<T extends (HTMLTag | SVGTag) & otherstring> = T extends SVGTag ? SVGEl
|
|
|
130
148
|
* ## About
|
|
131
149
|
* @package @ktjs/core
|
|
132
150
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
133
|
-
* @version 0.
|
|
151
|
+
* @version 0.16.0 (Last Update: 2026.01.27 17:30:39.673)
|
|
134
152
|
* @license MIT
|
|
135
153
|
* @link https://github.com/baendlorel/kt.js
|
|
136
154
|
* @link https://baendlorel.github.io/ Welcome to my site!
|
package/dist/jsx/jsx-runtime.mjs
CHANGED
|
@@ -203,7 +203,7 @@ let creator = defaultCreator;
|
|
|
203
203
|
* ## About
|
|
204
204
|
* @package @ktjs/core
|
|
205
205
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
206
|
-
* @version 0.
|
|
206
|
+
* @version 0.16.0 (Last Update: 2026.01.27 17:30:39.673)
|
|
207
207
|
* @license MIT
|
|
208
208
|
* @link https://github.com/baendlorel/kt.js
|
|
209
209
|
* @link https://baendlorel.github.io/ Welcome to my site!
|