@ktjs/core 0.14.5 → 0.15.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 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.13.0
15
+ **Current Version:** 0.14.6
16
16
 
17
17
  ## Features
18
18
 
@@ -25,7 +25,9 @@ Core DOM manipulation utilities for KT.js framework with built-in JSX/TSX suppor
25
25
  - Zero virtual DOM - JSX compiles directly to `h()` function calls
26
26
  - Full HTML element type inference (`<button>` returns `HTMLButtonElement`)
27
27
  - Support for function components
28
- - **NEW**: `redraw()` method for controlled re-rendering
28
+ - `redraw()` method for controlled re-rendering
29
+ - **k-if directive**: Conditional element creation with `k-if` attribute
30
+ - Array children support for seamless list rendering
29
31
  - **KTAsync Component**: Handle async components with ease
30
32
  - Automatic handling of Promise-based components
31
33
  - Seamless integration with JSX/TSX
@@ -87,7 +89,7 @@ const button1 = h(
87
89
  {
88
90
  'on:click': () => alert('Clicked!'),
89
91
  },
90
- 'Button 1'
92
+ 'Button 1',
91
93
  );
92
94
 
93
95
  // Function attribute (also treated as event listener)
@@ -97,7 +99,7 @@ const button2 = h(
97
99
  click: (e) => console.log('Event:', e),
98
100
  'data-id': '123', // Regular attribute
99
101
  },
100
- 'Button 2'
102
+ 'Button 2',
101
103
  );
102
104
 
103
105
  // Both regular and event handler for same name
@@ -136,9 +138,43 @@ const Greeting = ({ name }: { name: string }) => (
136
138
  const app = <Greeting name="World" />;
137
139
  ```
138
140
 
141
+ ### Conditional Rendering with k-if (v0.14.6+)
142
+
143
+ The `k-if` directive allows conditional element creation:
144
+
145
+ ```tsx
146
+ import { h } from '@ktjs/core';
147
+
148
+ // Element will only be created if condition is true
149
+ const isVisible = true;
150
+ const element = <div k-if={isVisible}>This will be rendered</div>;
151
+
152
+ // Element will not be created if condition is false
153
+ const isHidden = false;
154
+ const hidden = <div k-if={isHidden}>This will NOT be rendered</div>;
155
+ // hidden will be undefined/null
156
+
157
+ // Practical example
158
+ const UserProfile = ({ user, isLoggedIn }: { user: any; isLoggedIn: boolean }) => (
159
+ <div>
160
+ <h1>User Profile</h1>
161
+ <div k-if={isLoggedIn}>
162
+ <p>Welcome, {user.name}!</p>
163
+ <button>Logout</button>
164
+ </div>
165
+ <div k-if={!isLoggedIn}>
166
+ <p>Please log in to continue</p>
167
+ <button>Login</button>
168
+ </div>
169
+ </div>
170
+ );
171
+ ```
172
+
173
+ **Note**: `k-if` is evaluated **once** at element creation time. It's not reactive - if you need dynamic visibility, use CSS or manually recreate the element.
174
+
139
175
  ### Redraw Mechanism (v0.11+)
140
176
 
141
- The new `redraw()` method allows you to update components efficiently:
177
+ The `redraw()` method allows you to update components efficiently:
142
178
 
143
179
  ```tsx
144
180
  import { h, KTHTMLElement } from '@ktjs/core';
@@ -164,6 +200,39 @@ const div = (<div>Old content</div>) as KTHTMLElement;
164
200
  div.redraw(undefined, 'New content');
165
201
  ```
166
202
 
203
+ ### Array Children Support (v0.14.1+)
204
+
205
+ Children can now be arrays for easier list rendering:
206
+
207
+ ```tsx
208
+ import { h } from '@ktjs/core';
209
+
210
+ // Map arrays directly as children
211
+ const items = ['Apple', 'Banana', 'Orange'];
212
+ const list = (
213
+ <ul>
214
+ {items.map((item) => (
215
+ <li>{item}</li>
216
+ ))}
217
+ </ul>
218
+ );
219
+
220
+ // Mix mapped elements with other elements
221
+ const TodoList = ({ todos }: { todos: string[] }) => (
222
+ <div>
223
+ <h2>Todo List</h2>
224
+ <ul>
225
+ {todos.map((todo) => (
226
+ <li>{todo}</li>
227
+ ))}
228
+ <li>
229
+ <button>Add More</button>
230
+ </li>
231
+ </ul>
232
+ </div>
233
+ );
234
+ ```
235
+
167
236
  ### Async Components
168
237
 
169
238
  ```typescript
package/dist/index.d.ts CHANGED
@@ -16,12 +16,12 @@ interface KTRef<T> {
16
16
  */
17
17
  declare function ref<T = HTMLElement>(value?: T): KTRef<T>;
18
18
 
19
- type KTHTMLElement = HTMLElement & {
19
+ type KTHTMLElement<El extends HTMLElement = HTMLElement> = El & {
20
20
  /**
21
21
  * Automically generate a redraw function if it is not provided
22
22
  * @param props
23
23
  */
24
- redraw: (props?: KTAttribute, children?: KTRawContent) => KTHTMLElement;
24
+ redraw: (props?: KTAttribute, ...args: any[]) => KTHTMLElement;
25
25
  };
26
26
 
27
27
  declare global {
@@ -153,7 +153,7 @@ type H = (<T extends HTMLTag>(tag: T, attr?: KTRawAttr, content?: KTRawContent)
153
153
  * ## About
154
154
  * @package @ktjs/core
155
155
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
156
- * @version 0.14.5 (Last Update: 2026.01.17 09:00:04.049)
156
+ * @version 0.15.0 (Last Update: 2026.01.24 00:25:38.464)
157
157
  * @license MIT
158
158
  * @link https://github.com/baendlorel/kt.js
159
159
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -196,7 +196,7 @@ declare const jsxs: typeof jsx;
196
196
  * }
197
197
  * ```
198
198
  * Then the returned element has a `redraw` method to redraw itself with new values.
199
- * @param creator
199
+ * @param creator a simple creator function that returns an element
200
200
  * @returns created element
201
201
  */
202
202
  declare function createRedrawable(creator: () => KTHTMLElement): KTHTMLElement;
@@ -56,17 +56,10 @@ var __ktjs_core__ = (function (exports) {
56
56
 
57
57
  const defaultHandler = (element, key, value) => element.setAttribute(key, value);
58
58
  function attrIsObject(element, attr) {
59
- // & deal k-if first
60
- if ('k-if' in attr) {
61
- if (!attr['k-if']) {
62
- return false;
63
- }
64
- }
65
59
  const classValue = attr.class;
66
60
  const style = attr.style;
67
61
  if (classValue !== undefined) {
68
62
  element.className = classValue;
69
- delete attr.class;
70
63
  }
71
64
  if (style) {
72
65
  if (typeof style === 'string') {
@@ -77,45 +70,33 @@ var __ktjs_core__ = (function (exports) {
77
70
  element.style[key] = style[key];
78
71
  }
79
72
  }
80
- delete attr.style;
81
73
  }
82
74
  for (const key in attr) {
75
+ if (key === 'class' || key === 'style' || key === 'children' || key === 'k-if' || key === 'ref') {
76
+ continue;
77
+ }
83
78
  const o = attr[key];
84
- // force register on:xxx as an event handler
85
- // !if o is not valid, the throwing job will be done by `on`, not kt.js
86
79
  // # special handling for kt.js specific events
87
80
  const ktEvent = ktEventHandlers[key];
88
81
  if (ktEvent) {
89
82
  ktEvent(element, o);
90
- continue;
91
83
  }
92
- // # normal event handler
93
- if (key.startsWith('on:')) {
84
+ // normal event handler
85
+ else if (key.startsWith('on:')) {
94
86
  element.addEventListener(key.slice(3), o); // chop off the `@`
95
- continue;
96
- }
97
- if (typeof o === 'function') {
98
- (handlers[key] || defaultHandler)(element, key, o());
99
87
  }
88
+ // normal attributes
100
89
  else {
101
90
  (handlers[key] || defaultHandler)(element, key, o);
102
91
  }
103
92
  }
104
- if (classValue !== undefined) {
105
- attr.class = classValue;
106
- }
107
- if (style !== undefined) {
108
- attr.style = style;
109
- }
110
- return true;
111
93
  }
112
94
  function applyAttr(element, attr) {
113
95
  if (typeof attr === 'string') {
114
96
  element.className = attr;
115
- return true;
116
97
  }
117
98
  else if (typeof attr === 'object' && attr !== null) {
118
- return attrIsObject(element, attr);
99
+ attrIsObject(element, attr);
119
100
  }
120
101
  else {
121
102
  throw new Error('kt.js: attr must be an object/string.');
@@ -223,7 +204,7 @@ var __ktjs_core__ = (function (exports) {
223
204
  * ## About
224
205
  * @package @ktjs/core
225
206
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
226
- * @version 0.14.5 (Last Update: 2026.01.17 09:00:04.049)
207
+ * @version 0.15.0 (Last Update: 2026.01.24 00:25:38.464)
227
208
  * @license MIT
228
209
  * @link https://github.com/baendlorel/kt.js
229
210
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -237,68 +218,43 @@ var __ktjs_core__ = (function (exports) {
237
218
  // * start creating the element
238
219
  const element = document.createElement(tag);
239
220
  // * Handle content
240
- const kif = applyAttr(element, attr);
241
- if (!kif) {
242
- return document.createComment('k-if');
243
- }
221
+ applyAttr(element, attr);
244
222
  applyContent(element, content);
245
223
  return element;
246
224
  });
247
225
 
226
+ const dummyRef = { value: null };
248
227
  /**
249
228
  * @param tag html tag or function component
250
229
  * @param props properties/attributes
251
230
  */
231
+ // todo 加入对k-if的全面支持
252
232
  function jsx(tag, props = {}) {
253
- const ref = props.ref?.isKT ? props.ref : null;
254
- if (ref) {
255
- delete props.ref;
233
+ const ref = props.ref?.isKT ? props.ref : dummyRef;
234
+ let el;
235
+ const redraw = (newProps) => {
236
+ props = newProps ? { ...props, ...newProps } : props;
237
+ const old = el;
238
+ el = jsx(tag, props);
239
+ old.replaceWith(el);
240
+ return el;
241
+ };
242
+ if ('k-if' in props && !props['k-if']) {
243
+ el = document.createComment('k-if');
244
+ ref.value = el;
245
+ el.redraw = redraw;
246
+ return el;
256
247
  }
257
248
  // Handle function components
258
249
  if (typeof tag === 'function') {
259
- let el = tag(props);
260
- if (!el.redraw) {
261
- el.redraw = (newProps) => {
262
- props = newProps ? { ...props, ...newProps } : props;
263
- // $ same as below
264
- const old = el;
265
- el = tag(props);
266
- el.redraw = old.redraw; // inherit redraw
267
- if (ref) {
268
- ref.value = el;
269
- }
270
- old.replaceWith(el);
271
- return el;
272
- };
273
- }
274
- if (ref) {
275
- ref.value = el;
276
- }
277
- return el;
250
+ el = tag(props);
278
251
  }
279
252
  else {
280
- // & deal children here
281
- let children = props.children;
282
- delete props.children;
283
- let el = h(tag, props, children);
284
- if (ref) {
285
- ref.value = el;
286
- }
287
- el.redraw = (newProps, newChildren) => {
288
- props = newProps ? { ...props, ...newProps } : props;
289
- children = (newChildren ?? children);
290
- // $ same as above
291
- const old = el;
292
- el = h(tag, props, children);
293
- el.redraw = old.redraw; // inherit redraw
294
- if (ref) {
295
- ref.value = el;
296
- }
297
- old.replaceWith(el);
298
- return el;
299
- };
300
- return el;
253
+ el = h(tag, props, props.children);
301
254
  }
255
+ el.redraw ??= redraw;
256
+ ref.value = el;
257
+ return el;
302
258
  }
303
259
  /**
304
260
  * Fragment support - returns an array of children
@@ -351,20 +307,20 @@ var __ktjs_core__ = (function (exports) {
351
307
  * }
352
308
  * ```
353
309
  * Then the returned element has a `redraw` method to redraw itself with new values.
354
- * @param creator
310
+ * @param creator a simple creator function that returns an element
355
311
  * @returns created element
356
312
  */
357
313
  function createRedrawable(creator) {
358
- let element = creator();
314
+ let el = creator();
359
315
  const redraw = () => {
360
- const old = element;
361
- element = creator();
362
- old.replaceWith(element);
363
- element.redraw = redraw;
364
- return element;
316
+ const old = el;
317
+ el = creator();
318
+ old.replaceWith(el);
319
+ el.redraw = redraw;
320
+ return el;
365
321
  };
366
- element.redraw = redraw;
367
- return element;
322
+ el.redraw = redraw;
323
+ return el;
368
324
  }
369
325
 
370
326
  /**
@@ -68,17 +68,10 @@ var __ktjs_core__ = (function (exports) {
68
68
 
69
69
  var defaultHandler = function (element, key, value) { return element.setAttribute(key, value); };
70
70
  function attrIsObject(element, attr) {
71
- // & deal k-if first
72
- if ('k-if' in attr) {
73
- if (!attr['k-if']) {
74
- return false;
75
- }
76
- }
77
71
  var classValue = attr.class;
78
72
  var style = attr.style;
79
73
  if (classValue !== undefined) {
80
74
  element.className = classValue;
81
- delete attr.class;
82
75
  }
83
76
  if (style) {
84
77
  if (typeof style === 'string') {
@@ -89,45 +82,33 @@ var __ktjs_core__ = (function (exports) {
89
82
  element.style[key] = style[key];
90
83
  }
91
84
  }
92
- delete attr.style;
93
85
  }
94
86
  for (var key in attr) {
87
+ if (key === 'class' || key === 'style' || key === 'children' || key === 'k-if' || key === 'ref') {
88
+ continue;
89
+ }
95
90
  var o = attr[key];
96
- // force register on:xxx as an event handler
97
- // !if o is not valid, the throwing job will be done by `on`, not kt.js
98
91
  // # special handling for kt.js specific events
99
92
  var ktEvent = ktEventHandlers[key];
100
93
  if (ktEvent) {
101
94
  ktEvent(element, o);
102
- continue;
103
95
  }
104
- // # normal event handler
105
- if (key.startsWith('on:')) {
96
+ // normal event handler
97
+ else if (key.startsWith('on:')) {
106
98
  element.addEventListener(key.slice(3), o); // chop off the `@`
107
- continue;
108
- }
109
- if (typeof o === 'function') {
110
- (handlers[key] || defaultHandler)(element, key, o());
111
99
  }
100
+ // normal attributes
112
101
  else {
113
102
  (handlers[key] || defaultHandler)(element, key, o);
114
103
  }
115
104
  }
116
- if (classValue !== undefined) {
117
- attr.class = classValue;
118
- }
119
- if (style !== undefined) {
120
- attr.style = style;
121
- }
122
- return true;
123
105
  }
124
106
  function applyAttr(element, attr) {
125
107
  if (typeof attr === 'string') {
126
108
  element.className = attr;
127
- return true;
128
109
  }
129
110
  else if (typeof attr === 'object' && attr !== null) {
130
- return attrIsObject(element, attr);
111
+ attrIsObject(element, attr);
131
112
  }
132
113
  else {
133
114
  throw new Error('kt.js: attr must be an object/string.');
@@ -248,7 +229,7 @@ var __ktjs_core__ = (function (exports) {
248
229
  * ## About
249
230
  * @package @ktjs/core
250
231
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
251
- * @version 0.14.5 (Last Update: 2026.01.17 09:00:04.049)
232
+ * @version 0.15.0 (Last Update: 2026.01.24 00:25:38.464)
252
233
  * @license MIT
253
234
  * @link https://github.com/baendlorel/kt.js
254
235
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -264,10 +245,7 @@ var __ktjs_core__ = (function (exports) {
264
245
  // * start creating the element
265
246
  var element = document.createElement(tag);
266
247
  // * Handle content
267
- var kif = applyAttr(element, attr);
268
- if (!kif) {
269
- return document.createComment('k-if');
270
- }
248
+ applyAttr(element, attr);
271
249
  applyContent(element, content);
272
250
  return element;
273
251
  });
@@ -305,62 +283,40 @@ var __ktjs_core__ = (function (exports) {
305
283
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
306
284
  };
307
285
 
286
+ var dummyRef = { value: null };
308
287
  /**
309
288
  * @param tag html tag or function component
310
289
  * @param props properties/attributes
311
290
  */
291
+ // todo 加入对k-if的全面支持
312
292
  function jsx(tag, props) {
313
- var _a;
293
+ var _a, _b;
314
294
  if (props === void 0) { props = {}; }
315
- var ref = ((_a = props.ref) === null || _a === void 0 ? void 0 : _a.isKT) ? props.ref : null;
316
- if (ref) {
317
- delete props.ref;
295
+ var ref = ((_a = props.ref) === null || _a === void 0 ? void 0 : _a.isKT) ? props.ref : dummyRef;
296
+ var el;
297
+ var redraw = function (newProps) {
298
+ props = newProps ? __assign(__assign({}, props), newProps) : props;
299
+ var old = el;
300
+ el = jsx(tag, props);
301
+ old.replaceWith(el);
302
+ return el;
303
+ };
304
+ if ('k-if' in props && !props['k-if']) {
305
+ el = document.createComment('k-if');
306
+ ref.value = el;
307
+ el.redraw = redraw;
308
+ return el;
318
309
  }
319
310
  // Handle function components
320
311
  if (typeof tag === 'function') {
321
- var el_1 = tag(props);
322
- if (!el_1.redraw) {
323
- el_1.redraw = function (newProps) {
324
- props = newProps ? __assign(__assign({}, props), newProps) : props;
325
- // $ same as below
326
- var old = el_1;
327
- el_1 = tag(props);
328
- el_1.redraw = old.redraw; // inherit redraw
329
- if (ref) {
330
- ref.value = el_1;
331
- }
332
- old.replaceWith(el_1);
333
- return el_1;
334
- };
335
- }
336
- if (ref) {
337
- ref.value = el_1;
338
- }
339
- return el_1;
312
+ el = tag(props);
340
313
  }
341
314
  else {
342
- // & deal children here
343
- var children_1 = props.children;
344
- delete props.children;
345
- var el_2 = h(tag, props, children_1);
346
- if (ref) {
347
- ref.value = el_2;
348
- }
349
- el_2.redraw = function (newProps, newChildren) {
350
- props = newProps ? __assign(__assign({}, props), newProps) : props;
351
- children_1 = (newChildren !== null && newChildren !== void 0 ? newChildren : children_1);
352
- // $ same as above
353
- var old = el_2;
354
- el_2 = h(tag, props, children_1);
355
- el_2.redraw = old.redraw; // inherit redraw
356
- if (ref) {
357
- ref.value = el_2;
358
- }
359
- old.replaceWith(el_2);
360
- return el_2;
361
- };
362
- return el_2;
315
+ el = h(tag, props, props.children);
363
316
  }
317
+ (_b = el.redraw) !== null && _b !== void 0 ? _b : (el.redraw = redraw);
318
+ ref.value = el;
319
+ return el;
364
320
  }
365
321
  /**
366
322
  * Fragment support - returns an array of children
@@ -417,20 +373,20 @@ var __ktjs_core__ = (function (exports) {
417
373
  * }
418
374
  * ```
419
375
  * Then the returned element has a `redraw` method to redraw itself with new values.
420
- * @param creator
376
+ * @param creator a simple creator function that returns an element
421
377
  * @returns created element
422
378
  */
423
379
  function createRedrawable(creator) {
424
- var element = creator();
380
+ var el = creator();
425
381
  var redraw = function () {
426
- var old = element;
427
- element = creator();
428
- old.replaceWith(element);
429
- element.redraw = redraw;
430
- return element;
382
+ var old = el;
383
+ el = creator();
384
+ old.replaceWith(el);
385
+ el.redraw = redraw;
386
+ return el;
431
387
  };
432
- element.redraw = redraw;
433
- return element;
388
+ el.redraw = redraw;
389
+ return el;
434
390
  }
435
391
 
436
392
  /**
package/dist/index.mjs CHANGED
@@ -53,17 +53,10 @@ const ktEventHandlers = {
53
53
 
54
54
  const defaultHandler = (element, key, value) => element.setAttribute(key, value);
55
55
  function attrIsObject(element, attr) {
56
- // & deal k-if first
57
- if ('k-if' in attr) {
58
- if (!attr['k-if']) {
59
- return false;
60
- }
61
- }
62
56
  const classValue = attr.class;
63
57
  const style = attr.style;
64
58
  if (classValue !== undefined) {
65
59
  element.className = classValue;
66
- delete attr.class;
67
60
  }
68
61
  if (style) {
69
62
  if (typeof style === 'string') {
@@ -74,45 +67,33 @@ function attrIsObject(element, attr) {
74
67
  element.style[key] = style[key];
75
68
  }
76
69
  }
77
- delete attr.style;
78
70
  }
79
71
  for (const key in attr) {
72
+ if (key === 'class' || key === 'style' || key === 'children' || key === 'k-if' || key === 'ref') {
73
+ continue;
74
+ }
80
75
  const o = attr[key];
81
- // force register on:xxx as an event handler
82
- // !if o is not valid, the throwing job will be done by `on`, not kt.js
83
76
  // # special handling for kt.js specific events
84
77
  const ktEvent = ktEventHandlers[key];
85
78
  if (ktEvent) {
86
79
  ktEvent(element, o);
87
- continue;
88
80
  }
89
- // # normal event handler
90
- if (key.startsWith('on:')) {
81
+ // normal event handler
82
+ else if (key.startsWith('on:')) {
91
83
  element.addEventListener(key.slice(3), o); // chop off the `@`
92
- continue;
93
- }
94
- if (typeof o === 'function') {
95
- (handlers[key] || defaultHandler)(element, key, o());
96
84
  }
85
+ // normal attributes
97
86
  else {
98
87
  (handlers[key] || defaultHandler)(element, key, o);
99
88
  }
100
89
  }
101
- if (classValue !== undefined) {
102
- attr.class = classValue;
103
- }
104
- if (style !== undefined) {
105
- attr.style = style;
106
- }
107
- return true;
108
90
  }
109
91
  function applyAttr(element, attr) {
110
92
  if (typeof attr === 'string') {
111
93
  element.className = attr;
112
- return true;
113
94
  }
114
95
  else if (typeof attr === 'object' && attr !== null) {
115
- return attrIsObject(element, attr);
96
+ attrIsObject(element, attr);
116
97
  }
117
98
  else {
118
99
  throw new Error('kt.js: attr must be an object/string.');
@@ -220,7 +201,7 @@ function applyContent(element, content) {
220
201
  * ## About
221
202
  * @package @ktjs/core
222
203
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
223
- * @version 0.14.5 (Last Update: 2026.01.17 09:00:04.049)
204
+ * @version 0.15.0 (Last Update: 2026.01.24 00:25:38.464)
224
205
  * @license MIT
225
206
  * @link https://github.com/baendlorel/kt.js
226
207
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -234,68 +215,43 @@ const h = ((tag, attr = '', content = '') => {
234
215
  // * start creating the element
235
216
  const element = document.createElement(tag);
236
217
  // * Handle content
237
- const kif = applyAttr(element, attr);
238
- if (!kif) {
239
- return document.createComment('k-if');
240
- }
218
+ applyAttr(element, attr);
241
219
  applyContent(element, content);
242
220
  return element;
243
221
  });
244
222
 
223
+ const dummyRef = { value: null };
245
224
  /**
246
225
  * @param tag html tag or function component
247
226
  * @param props properties/attributes
248
227
  */
228
+ // todo 加入对k-if的全面支持
249
229
  function jsx(tag, props = {}) {
250
- const ref = props.ref?.isKT ? props.ref : null;
251
- if (ref) {
252
- delete props.ref;
230
+ const ref = props.ref?.isKT ? props.ref : dummyRef;
231
+ let el;
232
+ const redraw = (newProps) => {
233
+ props = newProps ? { ...props, ...newProps } : props;
234
+ const old = el;
235
+ el = jsx(tag, props);
236
+ old.replaceWith(el);
237
+ return el;
238
+ };
239
+ if ('k-if' in props && !props['k-if']) {
240
+ el = document.createComment('k-if');
241
+ ref.value = el;
242
+ el.redraw = redraw;
243
+ return el;
253
244
  }
254
245
  // Handle function components
255
246
  if (typeof tag === 'function') {
256
- let el = tag(props);
257
- if (!el.redraw) {
258
- el.redraw = (newProps) => {
259
- props = newProps ? { ...props, ...newProps } : props;
260
- // $ same as below
261
- const old = el;
262
- el = tag(props);
263
- el.redraw = old.redraw; // inherit redraw
264
- if (ref) {
265
- ref.value = el;
266
- }
267
- old.replaceWith(el);
268
- return el;
269
- };
270
- }
271
- if (ref) {
272
- ref.value = el;
273
- }
274
- return el;
247
+ el = tag(props);
275
248
  }
276
249
  else {
277
- // & deal children here
278
- let children = props.children;
279
- delete props.children;
280
- let el = h(tag, props, children);
281
- if (ref) {
282
- ref.value = el;
283
- }
284
- el.redraw = (newProps, newChildren) => {
285
- props = newProps ? { ...props, ...newProps } : props;
286
- children = (newChildren ?? children);
287
- // $ same as above
288
- const old = el;
289
- el = h(tag, props, children);
290
- el.redraw = old.redraw; // inherit redraw
291
- if (ref) {
292
- ref.value = el;
293
- }
294
- old.replaceWith(el);
295
- return el;
296
- };
297
- return el;
250
+ el = h(tag, props, props.children);
298
251
  }
252
+ el.redraw ??= redraw;
253
+ ref.value = el;
254
+ return el;
299
255
  }
300
256
  /**
301
257
  * Fragment support - returns an array of children
@@ -348,20 +304,20 @@ const jsxs = jsx;
348
304
  * }
349
305
  * ```
350
306
  * Then the returned element has a `redraw` method to redraw itself with new values.
351
- * @param creator
307
+ * @param creator a simple creator function that returns an element
352
308
  * @returns created element
353
309
  */
354
310
  function createRedrawable(creator) {
355
- let element = creator();
311
+ let el = creator();
356
312
  const redraw = () => {
357
- const old = element;
358
- element = creator();
359
- old.replaceWith(element);
360
- element.redraw = redraw;
361
- return element;
313
+ const old = el;
314
+ el = creator();
315
+ old.replaceWith(el);
316
+ el.redraw = redraw;
317
+ return el;
362
318
  };
363
- element.redraw = redraw;
364
- return element;
319
+ el.redraw = redraw;
320
+ return el;
365
321
  }
366
322
 
367
323
  /**
@@ -16,12 +16,12 @@ interface KTRef<T> {
16
16
  */
17
17
  declare function ref<T = HTMLElement>(value?: T): KTRef<T>;
18
18
 
19
- type KTHTMLElement = HTMLElement & {
19
+ type KTHTMLElement<El extends HTMLElement = HTMLElement> = El & {
20
20
  /**
21
21
  * Automically generate a redraw function if it is not provided
22
22
  * @param props
23
23
  */
24
- redraw: (props?: KTAttribute, children?: KTRawContent) => KTHTMLElement;
24
+ redraw: (props?: KTAttribute, ...args: any[]) => KTHTMLElement;
25
25
  };
26
26
 
27
27
  declare global {
@@ -139,7 +139,7 @@ type H = (<T extends HTMLTag>(tag: T, attr?: KTRawAttr, content?: KTRawContent)
139
139
  * ## About
140
140
  * @package @ktjs/core
141
141
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
142
- * @version 0.14.5 (Last Update: 2026.01.17 09:00:04.049)
142
+ * @version 0.15.0 (Last Update: 2026.01.24 00:25:38.464)
143
143
  * @license MIT
144
144
  * @link https://github.com/baendlorel/kt.js
145
145
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -182,7 +182,7 @@ declare const jsxs: typeof jsx;
182
182
  * }
183
183
  * ```
184
184
  * Then the returned element has a `redraw` method to redraw itself with new values.
185
- * @param creator
185
+ * @param creator a simple creator function that returns an element
186
186
  * @returns created element
187
187
  */
188
188
  declare function createRedrawable(creator: () => KTHTMLElement): KTHTMLElement;
@@ -53,17 +53,10 @@ const ktEventHandlers = {
53
53
 
54
54
  const defaultHandler = (element, key, value) => element.setAttribute(key, value);
55
55
  function attrIsObject(element, attr) {
56
- // & deal k-if first
57
- if ('k-if' in attr) {
58
- if (!attr['k-if']) {
59
- return false;
60
- }
61
- }
62
56
  const classValue = attr.class;
63
57
  const style = attr.style;
64
58
  if (classValue !== undefined) {
65
59
  element.className = classValue;
66
- delete attr.class;
67
60
  }
68
61
  if (style) {
69
62
  if (typeof style === 'string') {
@@ -74,45 +67,33 @@ function attrIsObject(element, attr) {
74
67
  element.style[key] = style[key];
75
68
  }
76
69
  }
77
- delete attr.style;
78
70
  }
79
71
  for (const key in attr) {
72
+ if (key === 'class' || key === 'style' || key === 'children' || key === 'k-if' || key === 'ref') {
73
+ continue;
74
+ }
80
75
  const o = attr[key];
81
- // force register on:xxx as an event handler
82
- // !if o is not valid, the throwing job will be done by `on`, not kt.js
83
76
  // # special handling for kt.js specific events
84
77
  const ktEvent = ktEventHandlers[key];
85
78
  if (ktEvent) {
86
79
  ktEvent(element, o);
87
- continue;
88
80
  }
89
- // # normal event handler
90
- if (key.startsWith('on:')) {
81
+ // normal event handler
82
+ else if (key.startsWith('on:')) {
91
83
  element.addEventListener(key.slice(3), o); // chop off the `@`
92
- continue;
93
- }
94
- if (typeof o === 'function') {
95
- (handlers[key] || defaultHandler)(element, key, o());
96
84
  }
85
+ // normal attributes
97
86
  else {
98
87
  (handlers[key] || defaultHandler)(element, key, o);
99
88
  }
100
89
  }
101
- if (classValue !== undefined) {
102
- attr.class = classValue;
103
- }
104
- if (style !== undefined) {
105
- attr.style = style;
106
- }
107
- return true;
108
90
  }
109
91
  function applyAttr(element, attr) {
110
92
  if (typeof attr === 'string') {
111
93
  element.className = attr;
112
- return true;
113
94
  }
114
95
  else if (typeof attr === 'object' && attr !== null) {
115
- return attrIsObject(element, attr);
96
+ attrIsObject(element, attr);
116
97
  }
117
98
  else {
118
99
  throw new Error('kt.js: attr must be an object/string.');
@@ -220,7 +201,7 @@ function applyContent(element, content) {
220
201
  * ## About
221
202
  * @package @ktjs/core
222
203
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
223
- * @version 0.14.5 (Last Update: 2026.01.17 09:00:04.049)
204
+ * @version 0.15.0 (Last Update: 2026.01.24 00:25:38.464)
224
205
  * @license MIT
225
206
  * @link https://github.com/baendlorel/kt.js
226
207
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -234,68 +215,43 @@ const h = ((tag, attr = '', content = '') => {
234
215
  // * start creating the element
235
216
  const element = document.createElement(tag);
236
217
  // * Handle content
237
- const kif = applyAttr(element, attr);
238
- if (!kif) {
239
- return document.createComment('k-if');
240
- }
218
+ applyAttr(element, attr);
241
219
  applyContent(element, content);
242
220
  return element;
243
221
  });
244
222
 
223
+ const dummyRef = { value: null };
245
224
  /**
246
225
  * @param tag html tag or function component
247
226
  * @param props properties/attributes
248
227
  */
228
+ // todo 加入对k-if的全面支持
249
229
  function jsx(tag, props = {}) {
250
- const ref = props.ref?.isKT ? props.ref : null;
251
- if (ref) {
252
- delete props.ref;
230
+ const ref = props.ref?.isKT ? props.ref : dummyRef;
231
+ let el;
232
+ const redraw = (newProps) => {
233
+ props = newProps ? { ...props, ...newProps } : props;
234
+ const old = el;
235
+ el = jsx(tag, props);
236
+ old.replaceWith(el);
237
+ return el;
238
+ };
239
+ if ('k-if' in props && !props['k-if']) {
240
+ el = document.createComment('k-if');
241
+ ref.value = el;
242
+ el.redraw = redraw;
243
+ return el;
253
244
  }
254
245
  // Handle function components
255
246
  if (typeof tag === 'function') {
256
- let el = tag(props);
257
- if (!el.redraw) {
258
- el.redraw = (newProps) => {
259
- props = newProps ? { ...props, ...newProps } : props;
260
- // $ same as below
261
- const old = el;
262
- el = tag(props);
263
- el.redraw = old.redraw; // inherit redraw
264
- if (ref) {
265
- ref.value = el;
266
- }
267
- old.replaceWith(el);
268
- return el;
269
- };
270
- }
271
- if (ref) {
272
- ref.value = el;
273
- }
274
- return el;
247
+ el = tag(props);
275
248
  }
276
249
  else {
277
- // & deal children here
278
- let children = props.children;
279
- delete props.children;
280
- let el = h(tag, props, children);
281
- if (ref) {
282
- ref.value = el;
283
- }
284
- el.redraw = (newProps, newChildren) => {
285
- props = newProps ? { ...props, ...newProps } : props;
286
- children = (newChildren ?? children);
287
- // $ same as above
288
- const old = el;
289
- el = h(tag, props, children);
290
- el.redraw = old.redraw; // inherit redraw
291
- if (ref) {
292
- ref.value = el;
293
- }
294
- old.replaceWith(el);
295
- return el;
296
- };
297
- return el;
250
+ el = h(tag, props, props.children);
298
251
  }
252
+ el.redraw ??= redraw;
253
+ ref.value = el;
254
+ return el;
299
255
  }
300
256
  /**
301
257
  * Fragment support - returns an array of children
@@ -348,20 +304,20 @@ const jsxs = jsx;
348
304
  * }
349
305
  * ```
350
306
  * Then the returned element has a `redraw` method to redraw itself with new values.
351
- * @param creator
307
+ * @param creator a simple creator function that returns an element
352
308
  * @returns created element
353
309
  */
354
310
  function createRedrawable(creator) {
355
- let element = creator();
311
+ let el = creator();
356
312
  const redraw = () => {
357
- const old = element;
358
- element = creator();
359
- old.replaceWith(element);
360
- element.redraw = redraw;
361
- return element;
313
+ const old = el;
314
+ el = creator();
315
+ old.replaceWith(el);
316
+ el.redraw = redraw;
317
+ return el;
362
318
  };
363
- element.redraw = redraw;
364
- return element;
319
+ el.redraw = redraw;
320
+ return el;
365
321
  }
366
322
 
367
323
  /**
@@ -10,12 +10,12 @@ interface KTRef<T> {
10
10
  isKT: true;
11
11
  }
12
12
 
13
- type KTHTMLElement = HTMLElement & {
13
+ type KTHTMLElement<El extends HTMLElement = HTMLElement> = El & {
14
14
  /**
15
15
  * Automically generate a redraw function if it is not provided
16
16
  * @param props
17
17
  */
18
- redraw: (props?: KTAttribute, children?: KTRawContent) => KTHTMLElement;
18
+ redraw: (props?: KTAttribute, ...args: any[]) => KTHTMLElement;
19
19
  };
20
20
 
21
21
  declare global {
@@ -133,7 +133,7 @@ type H = (<T extends HTMLTag>(tag: T, attr?: KTRawAttr, content?: KTRawContent)
133
133
  * ## About
134
134
  * @package @ktjs/core
135
135
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
136
- * @version 0.14.5 (Last Update: 2026.01.17 09:00:04.049)
136
+ * @version 0.15.0 (Last Update: 2026.01.24 00:25:38.464)
137
137
  * @license MIT
138
138
  * @link https://github.com/baendlorel/kt.js
139
139
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -176,7 +176,7 @@ declare const jsxs: typeof jsx;
176
176
  * }
177
177
  * ```
178
178
  * Then the returned element has a `redraw` method to redraw itself with new values.
179
- * @param creator
179
+ * @param creator a simple creator function that returns an element
180
180
  * @returns created element
181
181
  */
182
182
  declare function createRedrawable(creator: () => KTHTMLElement): KTHTMLElement;
@@ -53,17 +53,10 @@ const ktEventHandlers = {
53
53
 
54
54
  const defaultHandler = (element, key, value) => element.setAttribute(key, value);
55
55
  function attrIsObject(element, attr) {
56
- // & deal k-if first
57
- if ('k-if' in attr) {
58
- if (!attr['k-if']) {
59
- return false;
60
- }
61
- }
62
56
  const classValue = attr.class;
63
57
  const style = attr.style;
64
58
  if (classValue !== undefined) {
65
59
  element.className = classValue;
66
- delete attr.class;
67
60
  }
68
61
  if (style) {
69
62
  if (typeof style === 'string') {
@@ -74,45 +67,33 @@ function attrIsObject(element, attr) {
74
67
  element.style[key] = style[key];
75
68
  }
76
69
  }
77
- delete attr.style;
78
70
  }
79
71
  for (const key in attr) {
72
+ if (key === 'class' || key === 'style' || key === 'children' || key === 'k-if' || key === 'ref') {
73
+ continue;
74
+ }
80
75
  const o = attr[key];
81
- // force register on:xxx as an event handler
82
- // !if o is not valid, the throwing job will be done by `on`, not kt.js
83
76
  // # special handling for kt.js specific events
84
77
  const ktEvent = ktEventHandlers[key];
85
78
  if (ktEvent) {
86
79
  ktEvent(element, o);
87
- continue;
88
80
  }
89
- // # normal event handler
90
- if (key.startsWith('on:')) {
81
+ // normal event handler
82
+ else if (key.startsWith('on:')) {
91
83
  element.addEventListener(key.slice(3), o); // chop off the `@`
92
- continue;
93
- }
94
- if (typeof o === 'function') {
95
- (handlers[key] || defaultHandler)(element, key, o());
96
84
  }
85
+ // normal attributes
97
86
  else {
98
87
  (handlers[key] || defaultHandler)(element, key, o);
99
88
  }
100
89
  }
101
- if (classValue !== undefined) {
102
- attr.class = classValue;
103
- }
104
- if (style !== undefined) {
105
- attr.style = style;
106
- }
107
- return true;
108
90
  }
109
91
  function applyAttr(element, attr) {
110
92
  if (typeof attr === 'string') {
111
93
  element.className = attr;
112
- return true;
113
94
  }
114
95
  else if (typeof attr === 'object' && attr !== null) {
115
- return attrIsObject(element, attr);
96
+ attrIsObject(element, attr);
116
97
  }
117
98
  else {
118
99
  throw new Error('kt.js: attr must be an object/string.');
@@ -220,7 +201,7 @@ function applyContent(element, content) {
220
201
  * ## About
221
202
  * @package @ktjs/core
222
203
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
223
- * @version 0.14.5 (Last Update: 2026.01.17 09:00:04.049)
204
+ * @version 0.15.0 (Last Update: 2026.01.24 00:25:38.464)
224
205
  * @license MIT
225
206
  * @link https://github.com/baendlorel/kt.js
226
207
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -234,68 +215,43 @@ const h = ((tag, attr = '', content = '') => {
234
215
  // * start creating the element
235
216
  const element = document.createElement(tag);
236
217
  // * Handle content
237
- const kif = applyAttr(element, attr);
238
- if (!kif) {
239
- return document.createComment('k-if');
240
- }
218
+ applyAttr(element, attr);
241
219
  applyContent(element, content);
242
220
  return element;
243
221
  });
244
222
 
223
+ const dummyRef = { value: null };
245
224
  /**
246
225
  * @param tag html tag or function component
247
226
  * @param props properties/attributes
248
227
  */
228
+ // todo 加入对k-if的全面支持
249
229
  function jsx(tag, props = {}) {
250
- const ref = props.ref?.isKT ? props.ref : null;
251
- if (ref) {
252
- delete props.ref;
230
+ const ref = props.ref?.isKT ? props.ref : dummyRef;
231
+ let el;
232
+ const redraw = (newProps) => {
233
+ props = newProps ? { ...props, ...newProps } : props;
234
+ const old = el;
235
+ el = jsx(tag, props);
236
+ old.replaceWith(el);
237
+ return el;
238
+ };
239
+ if ('k-if' in props && !props['k-if']) {
240
+ el = document.createComment('k-if');
241
+ ref.value = el;
242
+ el.redraw = redraw;
243
+ return el;
253
244
  }
254
245
  // Handle function components
255
246
  if (typeof tag === 'function') {
256
- let el = tag(props);
257
- if (!el.redraw) {
258
- el.redraw = (newProps) => {
259
- props = newProps ? { ...props, ...newProps } : props;
260
- // $ same as below
261
- const old = el;
262
- el = tag(props);
263
- el.redraw = old.redraw; // inherit redraw
264
- if (ref) {
265
- ref.value = el;
266
- }
267
- old.replaceWith(el);
268
- return el;
269
- };
270
- }
271
- if (ref) {
272
- ref.value = el;
273
- }
274
- return el;
247
+ el = tag(props);
275
248
  }
276
249
  else {
277
- // & deal children here
278
- let children = props.children;
279
- delete props.children;
280
- let el = h(tag, props, children);
281
- if (ref) {
282
- ref.value = el;
283
- }
284
- el.redraw = (newProps, newChildren) => {
285
- props = newProps ? { ...props, ...newProps } : props;
286
- children = (newChildren ?? children);
287
- // $ same as above
288
- const old = el;
289
- el = h(tag, props, children);
290
- el.redraw = old.redraw; // inherit redraw
291
- if (ref) {
292
- ref.value = el;
293
- }
294
- old.replaceWith(el);
295
- return el;
296
- };
297
- return el;
250
+ el = h(tag, props, props.children);
298
251
  }
252
+ el.redraw ??= redraw;
253
+ ref.value = el;
254
+ return el;
299
255
  }
300
256
  /**
301
257
  * Fragment support - returns an array of children
@@ -348,20 +304,20 @@ const jsxs = jsx;
348
304
  * }
349
305
  * ```
350
306
  * Then the returned element has a `redraw` method to redraw itself with new values.
351
- * @param creator
307
+ * @param creator a simple creator function that returns an element
352
308
  * @returns created element
353
309
  */
354
310
  function createRedrawable(creator) {
355
- let element = creator();
311
+ let el = creator();
356
312
  const redraw = () => {
357
- const old = element;
358
- element = creator();
359
- old.replaceWith(element);
360
- element.redraw = redraw;
361
- return element;
313
+ const old = el;
314
+ el = creator();
315
+ old.replaceWith(el);
316
+ el.redraw = redraw;
317
+ return el;
362
318
  };
363
- element.redraw = redraw;
364
- return element;
319
+ el.redraw = redraw;
320
+ return el;
365
321
  }
366
322
 
367
323
  export { Fragment, h as createElement, createRedrawable, h, jsx, jsxDEV, jsxs };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ktjs/core",
3
- "version": "0.14.5",
3
+ "version": "0.15.0",
4
4
  "description": "Core functionality for kt.js - DOM manipulation utilities with JSX/TSX support",
5
5
  "type": "module",
6
6
  "module": "./dist/index.mjs",