@ktjs/core 0.8.5 → 0.10.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
@@ -17,6 +17,11 @@ Core DOM manipulation utilities for KT.js framework.
17
17
  - Special `@<eventName>` syntax for event handlers
18
18
  - Function attributes automatically treated as event listeners
19
19
  - Full TypeScript support with intelligent type inference
20
+ - **KTAsync Component**: Handle async components with ease
21
+ - Automatic handling of Promise-based components
22
+ - Seamless integration with JSX/TSX
23
+ - Fallback placeholder during async loading
24
+ - Type-safe async component support
20
25
  - **DOM Utilities**: Helper functions for common DOM operations
21
26
  - Native method caching for performance
22
27
  - Symbol-based private properties for internal state
@@ -24,10 +29,6 @@ Core DOM manipulation utilities for KT.js framework.
24
29
  - Accurate HTMLElement type inference
25
30
  - Event handler type hints with proper event types
26
31
  - Support for custom attributes and properties
27
- - **`ktnull`**: Special value for filtering null/undefined in DOM operations
28
- - Works as a placeholder that won't create DOM nodes
29
- - Can be used in attribute or content positions
30
- - Preserves native DOM behavior while enabling conditional rendering
31
32
  - **ES5 Compatible**: Transpiled to ES5 for maximum browser compatibility
32
33
  - **Zero Dependencies**: Fully self-contained implementation
33
34
 
@@ -93,23 +94,43 @@ const input = h('input', {
93
94
  });
94
95
  ```
95
96
 
96
- ### Using ktnull for Conditional Rendering
97
+ ### Async Components
97
98
 
98
99
  ```typescript
99
- import { h, ktnull } from '@ktjs/core';
100
-
101
- const items = [1, 2, 3, 4, 5];
100
+ import { KTAsync } from '@ktjs/core';
101
+
102
+ // Define an async component that returns a Promise
103
+ const AsyncComponent = function () {
104
+ return new Promise<HTMLElement>((resolve) => {
105
+ setTimeout(() => {
106
+ const element = h('div', { class: 'loaded' }, 'Content loaded!');
107
+ resolve(element);
108
+ }, 1000);
109
+ });
110
+ };
111
+
112
+ // Use KTAsync to handle the async component
113
+ const container = h('div', {}, [
114
+ h('h1', {}, 'Loading...'),
115
+ KTAsync({ component: AsyncComponent }),
116
+ ]);
102
117
 
103
- const list = h(
104
- 'ul',
105
- {},
106
- items.map(
107
- (item) => (item % 2 === 0 ? h('li', {}, `Even: ${item}`) : ktnull) // Won't create a DOM node
108
- )
118
+ // With JSX/TSX
119
+ const App = () => (
120
+ <div>
121
+ <h1>Loading...</h1>
122
+ <KTAsync component={AsyncComponent} />
123
+ </div>
109
124
  );
110
- // Results in: <ul><li>Even: 2</li><li>Even: 4</li></ul>
111
125
  ```
112
126
 
127
+ **How it works:**
128
+
129
+ - `KTAsync` creates a placeholder comment node immediately
130
+ - When the Promise resolves, it automatically replaces the placeholder with the actual element
131
+ - If the component returns a non-Promise value, it's used directly
132
+ - No manual DOM manipulation needed - just return a Promise from your component
133
+
113
134
  ## API Reference
114
135
 
115
136
  ### `h(tag, attributes?, content?)`
@@ -124,10 +145,6 @@ Creates an HTMLElement with the specified tag, attributes, and content.
124
145
 
125
146
  **Returns:** HTMLElement
126
147
 
127
- ### `ktnull`
128
-
129
- A special frozen empty object used to represent "no element" in content arrays. When used in place of an element, it won't create any DOM node.
130
-
131
148
  ## Type System
132
149
 
133
150
  The package includes comprehensive TypeScript definitions:
package/dist/index.d.ts CHANGED
@@ -9,12 +9,6 @@ declare global {
9
9
  }
10
10
  }
11
11
 
12
- /**
13
- * This is a `falsy` value used to indicate "no node" in `h` function.
14
- * - It's an object, so it's guaranteed to be unique and no need for polyfill of `symbol`.
15
- */
16
- declare const ktnull: any;
17
-
18
12
  type otherstring = string & {};
19
13
 
20
14
  /**
@@ -28,8 +22,12 @@ interface KTRef<T> {
28
22
  }
29
23
  declare function ref<T>(value?: T): KTRef<T>;
30
24
 
31
- type Ctt = KTRef<any> | HTMLElement | string | number | undefined;
32
- type KTRawContent = Ctt[] | Ctt;
25
+ type KTAvailableContent = KTRef<any> | HTMLElement | string | number | undefined;
26
+ type KTRawContent =
27
+ | KTAvailableContent[]
28
+ | KTAvailableContent
29
+ | Promise<KTAvailableContent[]>
30
+ | Promise<KTAvailableContent>;
33
31
  type KTRawAttr = KTAttribute | string;
34
32
  type KTRawContents = (HTMLElement | string | undefined)[];
35
33
 
@@ -98,6 +96,13 @@ type KTPrefixedEventHandlers = {
98
96
 
99
97
  type KTAttribute = KTBaseAttribute & KTPrefixedEventHandlers;
100
98
 
99
+ type KTComponent = (
100
+ props: {
101
+ ref?: KTRef<HTMLElement>;
102
+ children?: KTRawContent;
103
+ } & KTAttribute
104
+ ) => HTMLElement | Promise<HTMLElement>;
105
+
101
106
  type HTML<T extends HTMLTag & otherstring> = T extends HTMLTag ? HTMLElementTagNameMap[T] : HTMLElement;
102
107
  type H = (<T extends HTMLTag>(tag: T, attr?: KTRawAttr, content?: KTRawContent) => HTML<T>) & {
103
108
  kDepth: number;
@@ -113,7 +118,7 @@ type H = (<T extends HTMLTag>(tag: T, attr?: KTRawAttr, content?: KTRawContent)
113
118
  * ## About
114
119
  * @package @ktjs/core
115
120
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
116
- * @version 0.8.5 (Last Update: 2025.12.29 10:16:21.619)
121
+ * @version 0.10.0 (Last Update: 2025.12.30 14:19:29.793)
117
122
  * @license MIT
118
123
  * @link https://github.com/baendlorel/kt.js
119
124
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -123,19 +128,18 @@ type H = (<T extends HTMLTag>(tag: T, attr?: KTRawAttr, content?: KTRawContent)
123
128
  declare const h: H;
124
129
 
125
130
  /**
126
- * @param tag html tag
131
+ * @param tag html tag or function component
127
132
  * @param props properties/attributes
128
133
  * @param _metadata metadata is ignored
129
134
  */
130
- declare function jsx<T extends HTMLTag>(tag: T, props: KTRawAttr, ..._metadata: any[]): HTMLElementTagNameMap[T];
135
+ declare function jsx<T extends HTMLTag>(tag: T | Function, props: KTRawAttr, ..._metadata: any[]): HTMLElementTagNameMap[T] | HTMLElement;
131
136
  /**
132
137
  * Fragment support - returns an array of children
133
138
  * Note: kt.js doesn't have a real Fragment concept,
134
- * so we return ktnull for empty fragments or flatten children
135
139
  */
136
140
  declare function Fragment(props: {
137
141
  children?: KTRawContent;
138
- }): HTMLElement | typeof ktnull;
142
+ }): HTMLElement;
139
143
  /**
140
144
  * JSX Development runtime - same as jsx but with additional dev checks
141
145
  */
@@ -154,9 +158,10 @@ declare global {
154
158
  [tag: string]: KTAttribute & { children?: KTRawContent };
155
159
  }
156
160
 
157
- interface IntrinsicAttributes {
158
- key?: string | number;
159
- }
161
+ // interface IntrinsicAttributes {
162
+ // key?: string | number;
163
+ // }
164
+ type IntrinsicAttributes = KTAttribute;
160
165
 
161
166
  interface ElementChildrenAttribute {
162
167
  children: {};
@@ -164,5 +169,11 @@ declare global {
164
169
  }
165
170
  }
166
171
 
167
- export { Fragment, h as createElement, h, jsx, jsxDEV, jsxs, ktnull, ref };
172
+ declare function KTAsync(props: {
173
+ ref?: KTRef<HTMLElement>;
174
+ component: KTComponent;
175
+ children?: KTRawContent;
176
+ }): HTMLElement;
177
+
178
+ export { Fragment, KTAsync, h as createElement, h, jsx, jsxDEV, jsxs, ref };
168
179
  export type { EventHandler, HTMLTag, KTAttribute, KTRawAttr, KTRawContent, KTRawContents, KTRef, KTRuntime };
@@ -13,6 +13,7 @@ var __ktjs_core__ = (function (exports) {
13
13
  if (typeof Promise === 'undefined') {
14
14
  window.Promise = { resolve: emptyPromiseHandler, reject: emptyPromiseHandler };
15
15
  }
16
+ const $isThenable = (o) => typeof o === 'object' && o !== null && 'then' in o && typeof o.then === 'function';
16
17
 
17
18
  (() => {
18
19
  const runtimeKey = '__ktjs__';
@@ -31,12 +32,6 @@ var __ktjs_core__ = (function (exports) {
31
32
  return {};
32
33
  })();
33
34
 
34
- /**
35
- * This is a `falsy` value used to indicate "no node" in `h` function.
36
- * - It's an object, so it's guaranteed to be unique and no need for polyfill of `symbol`.
37
- */
38
- const ktnull = Object.create(null);
39
-
40
35
  /**
41
36
  * & Remove `bind` because it is shockingly slower than wrapper
42
37
  * & `window.document` is safe because it is not configurable and its setter is undefined
@@ -46,8 +41,7 @@ var __ktjs_core__ = (function (exports) {
46
41
  const $append = // for ie 9/10/11
47
42
  typeof originAppend === 'function'
48
43
  ? function (...args) {
49
- const nodes = args.filter((a) => a !== ktnull);
50
- return originAppend.apply(this, nodes);
44
+ return originAppend.apply(this, args);
51
45
  }
52
46
  : function (...nodes) {
53
47
  if (nodes.length < 50) {
@@ -56,7 +50,7 @@ var __ktjs_core__ = (function (exports) {
56
50
  if (typeof node === 'string') {
57
51
  $appendChild.call(this, document.createTextNode(node));
58
52
  }
59
- else if (node !== ktnull) {
53
+ else {
60
54
  $appendChild.call(this, node);
61
55
  }
62
56
  }
@@ -68,7 +62,7 @@ var __ktjs_core__ = (function (exports) {
68
62
  if (typeof node === 'string') {
69
63
  $appendChild.call(fragment, document.createTextNode(node));
70
64
  }
71
- else if (node !== ktnull) {
65
+ else {
72
66
  $appendChild.call(fragment, node);
73
67
  }
74
68
  }
@@ -175,12 +169,35 @@ var __ktjs_core__ = (function (exports) {
175
169
  }
176
170
  }
177
171
 
178
- function apd(element, content) {
179
- if (content && content.isKT) {
180
- $append.call(element, content.value);
172
+ function apdSingle(element, c) {
173
+ if (typeof c === 'object' && c !== null && 'isKT' in c) {
174
+ $append.call(element, c.value);
181
175
  }
182
176
  else {
183
- $append.call(element, content);
177
+ $append.call(element, c);
178
+ }
179
+ }
180
+ function apd(element, c) {
181
+ if ($isThenable(c)) {
182
+ c.then((r) => apd(element, r));
183
+ }
184
+ else if ($isArray(c)) {
185
+ for (let i = 0; i < c.length; i++) {
186
+ // & might be thenable here too
187
+ const ci = c[i];
188
+ if ($isThenable(ci)) {
189
+ const comment = document.createComment('ktjs-promise-placeholder');
190
+ $append.call(element, comment);
191
+ ci.then((awaited) => comment.replaceWith(awaited));
192
+ }
193
+ else {
194
+ apdSingle(element, ci);
195
+ }
196
+ }
197
+ }
198
+ else {
199
+ // & here is thened, so must be a simple elementj
200
+ apdSingle(element, c);
184
201
  }
185
202
  }
186
203
  function applyContent(element, content) {
@@ -204,7 +221,7 @@ var __ktjs_core__ = (function (exports) {
204
221
  * ## About
205
222
  * @package @ktjs/core
206
223
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
207
- * @version 0.8.5 (Last Update: 2025.12.29 10:16:21.619)
224
+ * @version 0.10.0 (Last Update: 2025.12.30 14:19:29.793)
208
225
  * @license MIT
209
226
  * @link https://github.com/baendlorel/kt.js
210
227
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -213,7 +230,7 @@ var __ktjs_core__ = (function (exports) {
213
230
  */
214
231
  const h = ((tag, attr = '', content = '') => {
215
232
  if (typeof tag !== 'string') {
216
- $throw('__func__ tagName must be a string.');
233
+ $throw('tagName must be a string.');
217
234
  }
218
235
  // * start creating the element
219
236
  const element = document.createElement(tag);
@@ -225,11 +242,18 @@ var __ktjs_core__ = (function (exports) {
225
242
  $mark(h, 'h');
226
243
 
227
244
  /**
228
- * @param tag html tag
245
+ * @param tag html tag or function component
229
246
  * @param props properties/attributes
230
247
  * @param _metadata metadata is ignored
231
248
  */
232
249
  function jsx(tag, props, ..._metadata) {
250
+ // Handle function components
251
+ if (typeof tag === 'function') {
252
+ const propObj = typeof props === 'string' ? { class: props } : props || {};
253
+ const children = propObj.children;
254
+ return tag({ ...propObj, children });
255
+ }
256
+ // Handle regular HTML tags
233
257
  const propObj = typeof props === 'string' ? { class: props } : props;
234
258
  if (propObj === undefined || propObj === null) {
235
259
  return h(tag);
@@ -250,13 +274,12 @@ var __ktjs_core__ = (function (exports) {
250
274
  /**
251
275
  * Fragment support - returns an array of children
252
276
  * Note: kt.js doesn't have a real Fragment concept,
253
- * so we return ktnull for empty fragments or flatten children
254
277
  */
255
278
  function Fragment(props) {
256
279
  window.__ktjs__.throws("kt.js doesn't have a Fragment concept");
257
280
  // const { children } = props || {};
258
281
  // if (!children) {
259
- // return ktnull;
282
+ // return ;
260
283
  // }
261
284
  // // If single child, return it directly
262
285
  // if (!Array.isArray(children)) {
@@ -267,13 +290,11 @@ var __ktjs_core__ = (function (exports) {
267
290
  // const wrapper = document.createElement('div');
268
291
  // wrapper.setAttribute('data-kt-fragment', 'true');
269
292
  // children.forEach((child) => {
270
- // if (child && child !== ktnull) {
271
293
  // if (typeof child === 'string') {
272
294
  // wrapper.appendChild(document.createTextNode(child));
273
295
  // } else if (child instanceof HTMLElement) {
274
296
  // wrapper.appendChild(child);
275
297
  // }
276
- // }
277
298
  // });
278
299
  // return wrapper;
279
300
  }
@@ -281,8 +302,8 @@ var __ktjs_core__ = (function (exports) {
281
302
  * JSX Development runtime - same as jsx but with additional dev checks
282
303
  */
283
304
  const jsxDEV = (...args) => {
284
- console.log('JSX DEV called:', ...args);
285
- console.log('chilren', args[1]?.children);
305
+ // console.log('JSX DEV called:', ...args);
306
+ // console.log('children', (args[1] as any)?.children);
286
307
  return jsx(...args);
287
308
  };
288
309
  /**
@@ -295,13 +316,25 @@ var __ktjs_core__ = (function (exports) {
295
316
  return { value: value, isKT: true };
296
317
  }
297
318
 
319
+ function KTAsync(props) {
320
+ const raw = props.component(props);
321
+ let comp = document.createComment('ktjs-suspense-placeholder');
322
+ if ($isThenable(raw)) {
323
+ raw.then((resolved) => comp.replaceWith(resolved));
324
+ }
325
+ else {
326
+ comp = raw;
327
+ }
328
+ return comp;
329
+ }
330
+
298
331
  exports.Fragment = Fragment;
332
+ exports.KTAsync = KTAsync;
299
333
  exports.createElement = h;
300
334
  exports.h = h;
301
335
  exports.jsx = jsx;
302
336
  exports.jsxDEV = jsxDEV;
303
337
  exports.jsxs = jsxs;
304
- exports.ktnull = ktnull;
305
338
  exports.ref = ref;
306
339
 
307
340
  return exports;
@@ -15,6 +15,9 @@ var __ktjs_core__ = (function (exports) {
15
15
  if (typeof Promise === 'undefined') {
16
16
  window.Promise = { resolve: emptyPromiseHandler, reject: emptyPromiseHandler };
17
17
  }
18
+ var $isThenable = function (o) {
19
+ return typeof o === 'object' && o !== null && 'then' in o && typeof o.then === 'function';
20
+ };
18
21
 
19
22
  ((function () {
20
23
  var _a;
@@ -34,12 +37,6 @@ var __ktjs_core__ = (function (exports) {
34
37
  return {};
35
38
  }))();
36
39
 
37
- /**
38
- * This is a `falsy` value used to indicate "no node" in `h` function.
39
- * - It's an object, so it's guaranteed to be unique and no need for polyfill of `symbol`.
40
- */
41
- var ktnull = Object.create(null);
42
-
43
40
  /**
44
41
  * & Remove `bind` because it is shockingly slower than wrapper
45
42
  * & `window.document` is safe because it is not configurable and its setter is undefined
@@ -53,8 +50,7 @@ var __ktjs_core__ = (function (exports) {
53
50
  for (var _i = 0; _i < arguments.length; _i++) {
54
51
  args[_i] = arguments[_i];
55
52
  }
56
- var nodes = args.filter(function (a) { return a !== ktnull; });
57
- return originAppend.apply(this, nodes);
53
+ return originAppend.apply(this, args);
58
54
  }
59
55
  : function () {
60
56
  var nodes = [];
@@ -67,7 +63,7 @@ var __ktjs_core__ = (function (exports) {
67
63
  if (typeof node === 'string') {
68
64
  $appendChild.call(this, document.createTextNode(node));
69
65
  }
70
- else if (node !== ktnull) {
66
+ else {
71
67
  $appendChild.call(this, node);
72
68
  }
73
69
  }
@@ -79,7 +75,7 @@ var __ktjs_core__ = (function (exports) {
79
75
  if (typeof node === 'string') {
80
76
  $appendChild.call(fragment, document.createTextNode(node));
81
77
  }
82
- else if (node !== ktnull) {
78
+ else {
83
79
  $appendChild.call(fragment, node);
84
80
  }
85
81
  }
@@ -186,12 +182,38 @@ var __ktjs_core__ = (function (exports) {
186
182
  }
187
183
  }
188
184
 
189
- function apd(element, content) {
190
- if (content && content.isKT) {
191
- $append.call(element, content.value);
185
+ function apdSingle(element, c) {
186
+ if (typeof c === 'object' && c !== null && 'isKT' in c) {
187
+ $append.call(element, c.value);
192
188
  }
193
189
  else {
194
- $append.call(element, content);
190
+ $append.call(element, c);
191
+ }
192
+ }
193
+ function apd(element, c) {
194
+ if ($isThenable(c)) {
195
+ c.then(function (r) { return apd(element, r); });
196
+ }
197
+ else if ($isArray(c)) {
198
+ var _loop_1 = function (i) {
199
+ // & might be thenable here too
200
+ var ci = c[i];
201
+ if ($isThenable(ci)) {
202
+ var comment_1 = document.createComment('ktjs-promise-placeholder');
203
+ $append.call(element, comment_1);
204
+ ci.then(function (awaited) { return comment_1.replaceWith(awaited); });
205
+ }
206
+ else {
207
+ apdSingle(element, ci);
208
+ }
209
+ };
210
+ for (var i = 0; i < c.length; i++) {
211
+ _loop_1(i);
212
+ }
213
+ }
214
+ else {
215
+ // & here is thened, so must be a simple elementj
216
+ apdSingle(element, c);
195
217
  }
196
218
  }
197
219
  function applyContent(element, content) {
@@ -215,7 +237,7 @@ var __ktjs_core__ = (function (exports) {
215
237
  * ## About
216
238
  * @package @ktjs/core
217
239
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
218
- * @version 0.8.5 (Last Update: 2025.12.29 10:16:21.619)
240
+ * @version 0.10.0 (Last Update: 2025.12.30 14:19:29.793)
219
241
  * @license MIT
220
242
  * @link https://github.com/baendlorel/kt.js
221
243
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -226,7 +248,7 @@ var __ktjs_core__ = (function (exports) {
226
248
  if (attr === void 0) { attr = ''; }
227
249
  if (content === void 0) { content = ''; }
228
250
  if (typeof tag !== 'string') {
229
- $throw('__func__ tagName must be a string.');
251
+ $throw('tagName must be a string.');
230
252
  }
231
253
  // * start creating the element
232
254
  var element = document.createElement(tag);
@@ -254,15 +276,16 @@ var __ktjs_core__ = (function (exports) {
254
276
  /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
255
277
 
256
278
 
257
- function __spreadArray(to, from, pack) {
258
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
259
- if (ar || !(i in from)) {
260
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
261
- ar[i] = from[i];
279
+ var __assign = function() {
280
+ __assign = Object.assign || function __assign(t) {
281
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
282
+ s = arguments[i];
283
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
262
284
  }
263
- }
264
- return to.concat(ar || Array.prototype.slice.call(from));
265
- }
285
+ return t;
286
+ };
287
+ return __assign.apply(this, arguments);
288
+ };
266
289
 
267
290
  typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
268
291
  var e = new Error(message);
@@ -270,12 +293,19 @@ var __ktjs_core__ = (function (exports) {
270
293
  };
271
294
 
272
295
  /**
273
- * @param tag html tag
296
+ * @param tag html tag or function component
274
297
  * @param props properties/attributes
275
298
  * @param _metadata metadata is ignored
276
299
  */
277
300
  function jsx(tag, props) {
278
301
  var _a;
302
+ // Handle function components
303
+ if (typeof tag === 'function') {
304
+ var propObj_1 = typeof props === 'string' ? { class: props } : props || {};
305
+ var children_1 = propObj_1.children;
306
+ return tag(__assign(__assign({}, propObj_1), { children: children_1 }));
307
+ }
308
+ // Handle regular HTML tags
279
309
  var propObj = typeof props === 'string' ? { class: props } : props;
280
310
  if (propObj === undefined || propObj === null) {
281
311
  return h(tag);
@@ -296,13 +326,12 @@ var __ktjs_core__ = (function (exports) {
296
326
  /**
297
327
  * Fragment support - returns an array of children
298
328
  * Note: kt.js doesn't have a real Fragment concept,
299
- * so we return ktnull for empty fragments or flatten children
300
329
  */
301
330
  function Fragment(props) {
302
331
  window.__ktjs__.throws("kt.js doesn't have a Fragment concept");
303
332
  // const { children } = props || {};
304
333
  // if (!children) {
305
- // return ktnull;
334
+ // return ;
306
335
  // }
307
336
  // // If single child, return it directly
308
337
  // if (!Array.isArray(children)) {
@@ -313,13 +342,11 @@ var __ktjs_core__ = (function (exports) {
313
342
  // const wrapper = document.createElement('div');
314
343
  // wrapper.setAttribute('data-kt-fragment', 'true');
315
344
  // children.forEach((child) => {
316
- // if (child && child !== ktnull) {
317
345
  // if (typeof child === 'string') {
318
346
  // wrapper.appendChild(document.createTextNode(child));
319
347
  // } else if (child instanceof HTMLElement) {
320
348
  // wrapper.appendChild(child);
321
349
  // }
322
- // }
323
350
  // });
324
351
  // return wrapper;
325
352
  }
@@ -327,13 +354,12 @@ var __ktjs_core__ = (function (exports) {
327
354
  * JSX Development runtime - same as jsx but with additional dev checks
328
355
  */
329
356
  var jsxDEV = function () {
330
- var _a;
331
357
  var args = [];
332
358
  for (var _i = 0; _i < arguments.length; _i++) {
333
359
  args[_i] = arguments[_i];
334
360
  }
335
- console.log.apply(console, __spreadArray(['JSX DEV called:'], args, false));
336
- console.log('chilren', (_a = args[1]) === null || _a === void 0 ? void 0 : _a.children);
361
+ // console.log('JSX DEV called:', ...args);
362
+ // console.log('children', (args[1] as any)?.children);
337
363
  return jsx.apply(void 0, args);
338
364
  };
339
365
  /**
@@ -346,13 +372,25 @@ var __ktjs_core__ = (function (exports) {
346
372
  return { value: value, isKT: true };
347
373
  }
348
374
 
375
+ function KTAsync(props) {
376
+ var raw = props.component(props);
377
+ var comp = document.createComment('ktjs-suspense-placeholder');
378
+ if ($isThenable(raw)) {
379
+ raw.then(function (resolved) { return comp.replaceWith(resolved); });
380
+ }
381
+ else {
382
+ comp = raw;
383
+ }
384
+ return comp;
385
+ }
386
+
349
387
  exports.Fragment = Fragment;
388
+ exports.KTAsync = KTAsync;
350
389
  exports.createElement = h;
351
390
  exports.h = h;
352
391
  exports.jsx = jsx;
353
392
  exports.jsxDEV = jsxDEV;
354
393
  exports.jsxs = jsxs;
355
- exports.ktnull = ktnull;
356
394
  exports.ref = ref;
357
395
 
358
396
  return exports;
package/dist/index.mjs CHANGED
@@ -10,6 +10,7 @@ const emptyPromiseHandler = () => ({});
10
10
  if (typeof Promise === 'undefined') {
11
11
  window.Promise = { resolve: emptyPromiseHandler, reject: emptyPromiseHandler };
12
12
  }
13
+ const $isThenable = (o) => typeof o === 'object' && o !== null && 'then' in o && typeof o.then === 'function';
13
14
 
14
15
  (() => {
15
16
  const runtimeKey = '__ktjs__';
@@ -28,12 +29,6 @@ if (typeof Promise === 'undefined') {
28
29
  return {};
29
30
  })();
30
31
 
31
- /**
32
- * This is a `falsy` value used to indicate "no node" in `h` function.
33
- * - It's an object, so it's guaranteed to be unique and no need for polyfill of `symbol`.
34
- */
35
- const ktnull = Object.create(null);
36
-
37
32
  /**
38
33
  * & Remove `bind` because it is shockingly slower than wrapper
39
34
  * & `window.document` is safe because it is not configurable and its setter is undefined
@@ -43,8 +38,7 @@ const originAppend = HTMLElement.prototype.append;
43
38
  const $append = // for ie 9/10/11
44
39
  typeof originAppend === 'function'
45
40
  ? function (...args) {
46
- const nodes = args.filter((a) => a !== ktnull);
47
- return originAppend.apply(this, nodes);
41
+ return originAppend.apply(this, args);
48
42
  }
49
43
  : function (...nodes) {
50
44
  if (nodes.length < 50) {
@@ -53,7 +47,7 @@ const $append = // for ie 9/10/11
53
47
  if (typeof node === 'string') {
54
48
  $appendChild.call(this, document.createTextNode(node));
55
49
  }
56
- else if (node !== ktnull) {
50
+ else {
57
51
  $appendChild.call(this, node);
58
52
  }
59
53
  }
@@ -65,7 +59,7 @@ const $append = // for ie 9/10/11
65
59
  if (typeof node === 'string') {
66
60
  $appendChild.call(fragment, document.createTextNode(node));
67
61
  }
68
- else if (node !== ktnull) {
62
+ else {
69
63
  $appendChild.call(fragment, node);
70
64
  }
71
65
  }
@@ -172,12 +166,35 @@ function applyAttr(element, attr) {
172
166
  }
173
167
  }
174
168
 
175
- function apd(element, content) {
176
- if (content && content.isKT) {
177
- $append.call(element, content.value);
169
+ function apdSingle(element, c) {
170
+ if (typeof c === 'object' && c !== null && 'isKT' in c) {
171
+ $append.call(element, c.value);
178
172
  }
179
173
  else {
180
- $append.call(element, content);
174
+ $append.call(element, c);
175
+ }
176
+ }
177
+ function apd(element, c) {
178
+ if ($isThenable(c)) {
179
+ c.then((r) => apd(element, r));
180
+ }
181
+ else if ($isArray(c)) {
182
+ for (let i = 0; i < c.length; i++) {
183
+ // & might be thenable here too
184
+ const ci = c[i];
185
+ if ($isThenable(ci)) {
186
+ const comment = document.createComment('ktjs-promise-placeholder');
187
+ $append.call(element, comment);
188
+ ci.then((awaited) => comment.replaceWith(awaited));
189
+ }
190
+ else {
191
+ apdSingle(element, ci);
192
+ }
193
+ }
194
+ }
195
+ else {
196
+ // & here is thened, so must be a simple elementj
197
+ apdSingle(element, c);
181
198
  }
182
199
  }
183
200
  function applyContent(element, content) {
@@ -201,7 +218,7 @@ function applyContent(element, content) {
201
218
  * ## About
202
219
  * @package @ktjs/core
203
220
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
204
- * @version 0.8.5 (Last Update: 2025.12.29 10:16:21.619)
221
+ * @version 0.10.0 (Last Update: 2025.12.30 14:19:29.793)
205
222
  * @license MIT
206
223
  * @link https://github.com/baendlorel/kt.js
207
224
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -210,7 +227,7 @@ function applyContent(element, content) {
210
227
  */
211
228
  const h = ((tag, attr = '', content = '') => {
212
229
  if (typeof tag !== 'string') {
213
- $throw('__func__ tagName must be a string.');
230
+ $throw('tagName must be a string.');
214
231
  }
215
232
  // * start creating the element
216
233
  const element = document.createElement(tag);
@@ -222,11 +239,18 @@ const h = ((tag, attr = '', content = '') => {
222
239
  $mark(h, 'h');
223
240
 
224
241
  /**
225
- * @param tag html tag
242
+ * @param tag html tag or function component
226
243
  * @param props properties/attributes
227
244
  * @param _metadata metadata is ignored
228
245
  */
229
246
  function jsx(tag, props, ..._metadata) {
247
+ // Handle function components
248
+ if (typeof tag === 'function') {
249
+ const propObj = typeof props === 'string' ? { class: props } : props || {};
250
+ const children = propObj.children;
251
+ return tag({ ...propObj, children });
252
+ }
253
+ // Handle regular HTML tags
230
254
  const propObj = typeof props === 'string' ? { class: props } : props;
231
255
  if (propObj === undefined || propObj === null) {
232
256
  return h(tag);
@@ -247,13 +271,12 @@ function jsx(tag, props, ..._metadata) {
247
271
  /**
248
272
  * Fragment support - returns an array of children
249
273
  * Note: kt.js doesn't have a real Fragment concept,
250
- * so we return ktnull for empty fragments or flatten children
251
274
  */
252
275
  function Fragment(props) {
253
276
  window.__ktjs__.throws("kt.js doesn't have a Fragment concept");
254
277
  // const { children } = props || {};
255
278
  // if (!children) {
256
- // return ktnull;
279
+ // return ;
257
280
  // }
258
281
  // // If single child, return it directly
259
282
  // if (!Array.isArray(children)) {
@@ -264,13 +287,11 @@ function Fragment(props) {
264
287
  // const wrapper = document.createElement('div');
265
288
  // wrapper.setAttribute('data-kt-fragment', 'true');
266
289
  // children.forEach((child) => {
267
- // if (child && child !== ktnull) {
268
290
  // if (typeof child === 'string') {
269
291
  // wrapper.appendChild(document.createTextNode(child));
270
292
  // } else if (child instanceof HTMLElement) {
271
293
  // wrapper.appendChild(child);
272
294
  // }
273
- // }
274
295
  // });
275
296
  // return wrapper;
276
297
  }
@@ -278,8 +299,8 @@ function Fragment(props) {
278
299
  * JSX Development runtime - same as jsx but with additional dev checks
279
300
  */
280
301
  const jsxDEV = (...args) => {
281
- console.log('JSX DEV called:', ...args);
282
- console.log('chilren', args[1]?.children);
302
+ // console.log('JSX DEV called:', ...args);
303
+ // console.log('children', (args[1] as any)?.children);
283
304
  return jsx(...args);
284
305
  };
285
306
  /**
@@ -292,4 +313,16 @@ function ref(value) {
292
313
  return { value: value, isKT: true };
293
314
  }
294
315
 
295
- export { Fragment, h as createElement, h, jsx, jsxDEV, jsxs, ktnull, ref };
316
+ function KTAsync(props) {
317
+ const raw = props.component(props);
318
+ let comp = document.createComment('ktjs-suspense-placeholder');
319
+ if ($isThenable(raw)) {
320
+ raw.then((resolved) => comp.replaceWith(resolved));
321
+ }
322
+ else {
323
+ comp = raw;
324
+ }
325
+ return comp;
326
+ }
327
+
328
+ export { Fragment, KTAsync, h as createElement, h, jsx, jsxDEV, jsxs, ref };
@@ -11,8 +11,12 @@ interface KTRef<T> {
11
11
  }
12
12
  declare function ref<T>(value?: T): KTRef<T>;
13
13
 
14
- type Ctt = KTRef<any> | HTMLElement | string | number | undefined;
15
- type KTRawContent = Ctt[] | Ctt;
14
+ type KTAvailableContent = KTRef<any> | HTMLElement | string | number | undefined;
15
+ type KTRawContent =
16
+ | KTAvailableContent[]
17
+ | KTAvailableContent
18
+ | Promise<KTAvailableContent[]>
19
+ | Promise<KTAvailableContent>;
16
20
  type KTRawAttr = KTAttribute | string;
17
21
 
18
22
  /**
@@ -90,7 +94,7 @@ type H = (<T extends HTMLTag>(tag: T, attr?: KTRawAttr, content?: KTRawContent)
90
94
  * ## About
91
95
  * @package @ktjs/core
92
96
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
93
- * @version 0.8.5 (Last Update: 2025.12.29 10:16:21.619)
97
+ * @version 0.10.0 (Last Update: 2025.12.30 14:19:29.793)
94
98
  * @license MIT
95
99
  * @link https://github.com/baendlorel/kt.js
96
100
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -100,25 +104,18 @@ type H = (<T extends HTMLTag>(tag: T, attr?: KTRawAttr, content?: KTRawContent)
100
104
  declare const h: H;
101
105
 
102
106
  /**
103
- * This is a `falsy` value used to indicate "no node" in `h` function.
104
- * - It's an object, so it's guaranteed to be unique and no need for polyfill of `symbol`.
105
- */
106
- declare const ktnull: any;
107
-
108
- /**
109
- * @param tag html tag
107
+ * @param tag html tag or function component
110
108
  * @param props properties/attributes
111
109
  * @param _metadata metadata is ignored
112
110
  */
113
- declare function jsx<T extends HTMLTag>(tag: T, props: KTRawAttr, ..._metadata: any[]): HTMLElementTagNameMap[T];
111
+ declare function jsx<T extends HTMLTag>(tag: T | Function, props: KTRawAttr, ..._metadata: any[]): HTMLElementTagNameMap[T] | HTMLElement;
114
112
  /**
115
113
  * Fragment support - returns an array of children
116
114
  * Note: kt.js doesn't have a real Fragment concept,
117
- * so we return ktnull for empty fragments or flatten children
118
115
  */
119
116
  declare function Fragment(props: {
120
117
  children?: KTRawContent;
121
- }): HTMLElement | typeof ktnull;
118
+ }): HTMLElement;
122
119
  /**
123
120
  * JSX Development runtime - same as jsx but with additional dev checks
124
121
  */
@@ -137,9 +134,10 @@ declare global {
137
134
  [tag: string]: KTAttribute & { children?: KTRawContent };
138
135
  }
139
136
 
140
- interface IntrinsicAttributes {
141
- key?: string | number;
142
- }
137
+ // interface IntrinsicAttributes {
138
+ // key?: string | number;
139
+ // }
140
+ type IntrinsicAttributes = KTAttribute;
143
141
 
144
142
  interface ElementChildrenAttribute {
145
143
  children: {};
@@ -10,12 +10,7 @@ const emptyPromiseHandler = () => ({});
10
10
  if (typeof Promise === 'undefined') {
11
11
  window.Promise = { resolve: emptyPromiseHandler, reject: emptyPromiseHandler };
12
12
  }
13
-
14
- /**
15
- * This is a `falsy` value used to indicate "no node" in `h` function.
16
- * - It's an object, so it's guaranteed to be unique and no need for polyfill of `symbol`.
17
- */
18
- const ktnull = Object.create(null);
13
+ const $isThenable = (o) => typeof o === 'object' && o !== null && 'then' in o && typeof o.then === 'function';
19
14
 
20
15
  /**
21
16
  * & Remove `bind` because it is shockingly slower than wrapper
@@ -26,8 +21,7 @@ const originAppend = HTMLElement.prototype.append;
26
21
  const $append = // for ie 9/10/11
27
22
  typeof originAppend === 'function'
28
23
  ? function (...args) {
29
- const nodes = args.filter((a) => a !== ktnull);
30
- return originAppend.apply(this, nodes);
24
+ return originAppend.apply(this, args);
31
25
  }
32
26
  : function (...nodes) {
33
27
  if (nodes.length < 50) {
@@ -36,7 +30,7 @@ const $append = // for ie 9/10/11
36
30
  if (typeof node === 'string') {
37
31
  $appendChild.call(this, document.createTextNode(node));
38
32
  }
39
- else if (node !== ktnull) {
33
+ else {
40
34
  $appendChild.call(this, node);
41
35
  }
42
36
  }
@@ -48,7 +42,7 @@ const $append = // for ie 9/10/11
48
42
  if (typeof node === 'string') {
49
43
  $appendChild.call(fragment, document.createTextNode(node));
50
44
  }
51
- else if (node !== ktnull) {
45
+ else {
52
46
  $appendChild.call(fragment, node);
53
47
  }
54
48
  }
@@ -155,12 +149,35 @@ function applyAttr(element, attr) {
155
149
  }
156
150
  }
157
151
 
158
- function apd(element, content) {
159
- if (content && content.isKT) {
160
- $append.call(element, content.value);
152
+ function apdSingle(element, c) {
153
+ if (typeof c === 'object' && c !== null && 'isKT' in c) {
154
+ $append.call(element, c.value);
155
+ }
156
+ else {
157
+ $append.call(element, c);
158
+ }
159
+ }
160
+ function apd(element, c) {
161
+ if ($isThenable(c)) {
162
+ c.then((r) => apd(element, r));
163
+ }
164
+ else if ($isArray(c)) {
165
+ for (let i = 0; i < c.length; i++) {
166
+ // & might be thenable here too
167
+ const ci = c[i];
168
+ if ($isThenable(ci)) {
169
+ const comment = document.createComment('ktjs-promise-placeholder');
170
+ $append.call(element, comment);
171
+ ci.then((awaited) => comment.replaceWith(awaited));
172
+ }
173
+ else {
174
+ apdSingle(element, ci);
175
+ }
176
+ }
161
177
  }
162
178
  else {
163
- $append.call(element, content);
179
+ // & here is thened, so must be a simple elementj
180
+ apdSingle(element, c);
164
181
  }
165
182
  }
166
183
  function applyContent(element, content) {
@@ -184,7 +201,7 @@ function applyContent(element, content) {
184
201
  * ## About
185
202
  * @package @ktjs/core
186
203
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
187
- * @version 0.8.5 (Last Update: 2025.12.29 10:16:21.619)
204
+ * @version 0.10.0 (Last Update: 2025.12.30 14:19:29.793)
188
205
  * @license MIT
189
206
  * @link https://github.com/baendlorel/kt.js
190
207
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -193,7 +210,7 @@ function applyContent(element, content) {
193
210
  */
194
211
  const h = ((tag, attr = '', content = '') => {
195
212
  if (typeof tag !== 'string') {
196
- $throw('__func__ tagName must be a string.');
213
+ $throw('tagName must be a string.');
197
214
  }
198
215
  // * start creating the element
199
216
  const element = document.createElement(tag);
@@ -205,11 +222,18 @@ const h = ((tag, attr = '', content = '') => {
205
222
  $mark(h, 'h');
206
223
 
207
224
  /**
208
- * @param tag html tag
225
+ * @param tag html tag or function component
209
226
  * @param props properties/attributes
210
227
  * @param _metadata metadata is ignored
211
228
  */
212
229
  function jsx(tag, props, ..._metadata) {
230
+ // Handle function components
231
+ if (typeof tag === 'function') {
232
+ const propObj = typeof props === 'string' ? { class: props } : props || {};
233
+ const children = propObj.children;
234
+ return tag({ ...propObj, children });
235
+ }
236
+ // Handle regular HTML tags
213
237
  const propObj = typeof props === 'string' ? { class: props } : props;
214
238
  if (propObj === undefined || propObj === null) {
215
239
  return h(tag);
@@ -230,13 +254,12 @@ function jsx(tag, props, ..._metadata) {
230
254
  /**
231
255
  * Fragment support - returns an array of children
232
256
  * Note: kt.js doesn't have a real Fragment concept,
233
- * so we return ktnull for empty fragments or flatten children
234
257
  */
235
258
  function Fragment(props) {
236
259
  window.__ktjs__.throws("kt.js doesn't have a Fragment concept");
237
260
  // const { children } = props || {};
238
261
  // if (!children) {
239
- // return ktnull;
262
+ // return ;
240
263
  // }
241
264
  // // If single child, return it directly
242
265
  // if (!Array.isArray(children)) {
@@ -247,13 +270,11 @@ function Fragment(props) {
247
270
  // const wrapper = document.createElement('div');
248
271
  // wrapper.setAttribute('data-kt-fragment', 'true');
249
272
  // children.forEach((child) => {
250
- // if (child && child !== ktnull) {
251
273
  // if (typeof child === 'string') {
252
274
  // wrapper.appendChild(document.createTextNode(child));
253
275
  // } else if (child instanceof HTMLElement) {
254
276
  // wrapper.appendChild(child);
255
277
  // }
256
- // }
257
278
  // });
258
279
  // return wrapper;
259
280
  }
@@ -261,8 +282,8 @@ function Fragment(props) {
261
282
  * JSX Development runtime - same as jsx but with additional dev checks
262
283
  */
263
284
  const jsxDEV = (...args) => {
264
- console.log('JSX DEV called:', ...args);
265
- console.log('chilren', args[1]?.children);
285
+ // console.log('JSX DEV called:', ...args);
286
+ // console.log('children', (args[1] as any)?.children);
266
287
  return jsx(...args);
267
288
  };
268
289
  /**
@@ -10,8 +10,12 @@ interface KTRef<T> {
10
10
  isKT: true;
11
11
  }
12
12
 
13
- type Ctt = KTRef<any> | HTMLElement | string | number | undefined;
14
- type KTRawContent = Ctt[] | Ctt;
13
+ type KTAvailableContent = KTRef<any> | HTMLElement | string | number | undefined;
14
+ type KTRawContent =
15
+ | KTAvailableContent[]
16
+ | KTAvailableContent
17
+ | Promise<KTAvailableContent[]>
18
+ | Promise<KTAvailableContent>;
15
19
  type KTRawAttr = KTAttribute | string;
16
20
 
17
21
  /**
@@ -89,7 +93,7 @@ type H = (<T extends HTMLTag>(tag: T, attr?: KTRawAttr, content?: KTRawContent)
89
93
  * ## About
90
94
  * @package @ktjs/core
91
95
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
92
- * @version 0.8.5 (Last Update: 2025.12.29 10:16:21.619)
96
+ * @version 0.10.0 (Last Update: 2025.12.30 14:19:29.793)
93
97
  * @license MIT
94
98
  * @link https://github.com/baendlorel/kt.js
95
99
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -99,25 +103,18 @@ type H = (<T extends HTMLTag>(tag: T, attr?: KTRawAttr, content?: KTRawContent)
99
103
  declare const h: H;
100
104
 
101
105
  /**
102
- * This is a `falsy` value used to indicate "no node" in `h` function.
103
- * - It's an object, so it's guaranteed to be unique and no need for polyfill of `symbol`.
104
- */
105
- declare const ktnull: any;
106
-
107
- /**
108
- * @param tag html tag
106
+ * @param tag html tag or function component
109
107
  * @param props properties/attributes
110
108
  * @param _metadata metadata is ignored
111
109
  */
112
- declare function jsx<T extends HTMLTag>(tag: T, props: KTRawAttr, ..._metadata: any[]): HTMLElementTagNameMap[T];
110
+ declare function jsx<T extends HTMLTag>(tag: T | Function, props: KTRawAttr, ..._metadata: any[]): HTMLElementTagNameMap[T] | HTMLElement;
113
111
  /**
114
112
  * Fragment support - returns an array of children
115
113
  * Note: kt.js doesn't have a real Fragment concept,
116
- * so we return ktnull for empty fragments or flatten children
117
114
  */
118
115
  declare function Fragment(props: {
119
116
  children?: KTRawContent;
120
- }): HTMLElement | typeof ktnull;
117
+ }): HTMLElement;
121
118
  /**
122
119
  * JSX Development runtime - same as jsx but with additional dev checks
123
120
  */
@@ -10,12 +10,7 @@ const emptyPromiseHandler = () => ({});
10
10
  if (typeof Promise === 'undefined') {
11
11
  window.Promise = { resolve: emptyPromiseHandler, reject: emptyPromiseHandler };
12
12
  }
13
-
14
- /**
15
- * This is a `falsy` value used to indicate "no node" in `h` function.
16
- * - It's an object, so it's guaranteed to be unique and no need for polyfill of `symbol`.
17
- */
18
- const ktnull = Object.create(null);
13
+ const $isThenable = (o) => typeof o === 'object' && o !== null && 'then' in o && typeof o.then === 'function';
19
14
 
20
15
  /**
21
16
  * & Remove `bind` because it is shockingly slower than wrapper
@@ -26,8 +21,7 @@ const originAppend = HTMLElement.prototype.append;
26
21
  const $append = // for ie 9/10/11
27
22
  typeof originAppend === 'function'
28
23
  ? function (...args) {
29
- const nodes = args.filter((a) => a !== ktnull);
30
- return originAppend.apply(this, nodes);
24
+ return originAppend.apply(this, args);
31
25
  }
32
26
  : function (...nodes) {
33
27
  if (nodes.length < 50) {
@@ -36,7 +30,7 @@ const $append = // for ie 9/10/11
36
30
  if (typeof node === 'string') {
37
31
  $appendChild.call(this, document.createTextNode(node));
38
32
  }
39
- else if (node !== ktnull) {
33
+ else {
40
34
  $appendChild.call(this, node);
41
35
  }
42
36
  }
@@ -48,7 +42,7 @@ const $append = // for ie 9/10/11
48
42
  if (typeof node === 'string') {
49
43
  $appendChild.call(fragment, document.createTextNode(node));
50
44
  }
51
- else if (node !== ktnull) {
45
+ else {
52
46
  $appendChild.call(fragment, node);
53
47
  }
54
48
  }
@@ -155,12 +149,35 @@ function applyAttr(element, attr) {
155
149
  }
156
150
  }
157
151
 
158
- function apd(element, content) {
159
- if (content && content.isKT) {
160
- $append.call(element, content.value);
152
+ function apdSingle(element, c) {
153
+ if (typeof c === 'object' && c !== null && 'isKT' in c) {
154
+ $append.call(element, c.value);
155
+ }
156
+ else {
157
+ $append.call(element, c);
158
+ }
159
+ }
160
+ function apd(element, c) {
161
+ if ($isThenable(c)) {
162
+ c.then((r) => apd(element, r));
163
+ }
164
+ else if ($isArray(c)) {
165
+ for (let i = 0; i < c.length; i++) {
166
+ // & might be thenable here too
167
+ const ci = c[i];
168
+ if ($isThenable(ci)) {
169
+ const comment = document.createComment('ktjs-promise-placeholder');
170
+ $append.call(element, comment);
171
+ ci.then((awaited) => comment.replaceWith(awaited));
172
+ }
173
+ else {
174
+ apdSingle(element, ci);
175
+ }
176
+ }
161
177
  }
162
178
  else {
163
- $append.call(element, content);
179
+ // & here is thened, so must be a simple elementj
180
+ apdSingle(element, c);
164
181
  }
165
182
  }
166
183
  function applyContent(element, content) {
@@ -184,7 +201,7 @@ function applyContent(element, content) {
184
201
  * ## About
185
202
  * @package @ktjs/core
186
203
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
187
- * @version 0.8.5 (Last Update: 2025.12.29 10:16:21.619)
204
+ * @version 0.10.0 (Last Update: 2025.12.30 14:19:29.793)
188
205
  * @license MIT
189
206
  * @link https://github.com/baendlorel/kt.js
190
207
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -193,7 +210,7 @@ function applyContent(element, content) {
193
210
  */
194
211
  const h = ((tag, attr = '', content = '') => {
195
212
  if (typeof tag !== 'string') {
196
- $throw('__func__ tagName must be a string.');
213
+ $throw('tagName must be a string.');
197
214
  }
198
215
  // * start creating the element
199
216
  const element = document.createElement(tag);
@@ -205,11 +222,18 @@ const h = ((tag, attr = '', content = '') => {
205
222
  $mark(h, 'h');
206
223
 
207
224
  /**
208
- * @param tag html tag
225
+ * @param tag html tag or function component
209
226
  * @param props properties/attributes
210
227
  * @param _metadata metadata is ignored
211
228
  */
212
229
  function jsx(tag, props, ..._metadata) {
230
+ // Handle function components
231
+ if (typeof tag === 'function') {
232
+ const propObj = typeof props === 'string' ? { class: props } : props || {};
233
+ const children = propObj.children;
234
+ return tag({ ...propObj, children });
235
+ }
236
+ // Handle regular HTML tags
213
237
  const propObj = typeof props === 'string' ? { class: props } : props;
214
238
  if (propObj === undefined || propObj === null) {
215
239
  return h(tag);
@@ -230,13 +254,12 @@ function jsx(tag, props, ..._metadata) {
230
254
  /**
231
255
  * Fragment support - returns an array of children
232
256
  * Note: kt.js doesn't have a real Fragment concept,
233
- * so we return ktnull for empty fragments or flatten children
234
257
  */
235
258
  function Fragment(props) {
236
259
  window.__ktjs__.throws("kt.js doesn't have a Fragment concept");
237
260
  // const { children } = props || {};
238
261
  // if (!children) {
239
- // return ktnull;
262
+ // return ;
240
263
  // }
241
264
  // // If single child, return it directly
242
265
  // if (!Array.isArray(children)) {
@@ -247,13 +270,11 @@ function Fragment(props) {
247
270
  // const wrapper = document.createElement('div');
248
271
  // wrapper.setAttribute('data-kt-fragment', 'true');
249
272
  // children.forEach((child) => {
250
- // if (child && child !== ktnull) {
251
273
  // if (typeof child === 'string') {
252
274
  // wrapper.appendChild(document.createTextNode(child));
253
275
  // } else if (child instanceof HTMLElement) {
254
276
  // wrapper.appendChild(child);
255
277
  // }
256
- // }
257
278
  // });
258
279
  // return wrapper;
259
280
  }
@@ -261,8 +282,8 @@ function Fragment(props) {
261
282
  * JSX Development runtime - same as jsx but with additional dev checks
262
283
  */
263
284
  const jsxDEV = (...args) => {
264
- console.log('JSX DEV called:', ...args);
265
- console.log('chilren', args[1]?.children);
285
+ // console.log('JSX DEV called:', ...args);
286
+ // console.log('children', (args[1] as any)?.children);
266
287
  return jsx(...args);
267
288
  };
268
289
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ktjs/core",
3
- "version": "0.8.5",
3
+ "version": "0.10.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",