@ktjs/core 0.17.3 → 0.18.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
@@ -81,6 +81,10 @@ const card = h('div', { class: 'card' }, [
81
81
  h('p', {}, 'Description'),
82
82
  h('button', {}, 'Click me'),
83
83
  ]);
84
+
85
+ // Note: attr parameter must be an object
86
+ // String className shorthand is NOT supported:
87
+ // h('div', 'my-class') ❌ - This will throw an error
84
88
  ```
85
89
 
86
90
  ### Event Handlers
@@ -344,7 +348,7 @@ Creates an HTMLElement with the specified tag, attributes, and content.
344
348
  **Parameters:**
345
349
 
346
350
  - `tag` (string): HTML tag name (e.g., 'div', 'span', 'button')
347
- - `attributes` (object, optional): Element attributes and event handlers
351
+ - `attributes` (object, optional): Element attributes and event handlers. **Must be an object** - string className shorthand is not supported.
348
352
  - `content` (string | HTMLElement | Array, optional): Element content
349
353
 
350
354
  **Returns:** HTMLElement
@@ -354,8 +358,9 @@ Creates an HTMLElement with the specified tag, attributes, and content.
354
358
  The package includes comprehensive TypeScript definitions:
355
359
 
356
360
  - `HTMLTag`: Union type of all valid HTML tag names
357
- - `KAttribute`: Attribute object type with string or function values
358
- - `KContent`: Valid content types (string, Element, Array, etc.)
361
+ - `KTAttribute`: Attribute object type for element attributes and event handlers
362
+ - `KTRawAttr`: Union type for raw attribute parameter (`KTAttribute | null | undefined | '' | false`)
363
+ - `KTRawContent`: Valid content types (string, Element, Array, Promise, etc.)
359
364
  - Event handler types with proper event object types
360
365
 
361
366
  ## Performance Considerations
package/dist/index.d.ts CHANGED
@@ -6,9 +6,15 @@ type otherstring = string & {};
6
6
  type HTMLTag = keyof HTMLElementTagNameMap;
7
7
  type SVGTag = keyof SVGElementTagNameMap;
8
8
 
9
+ type ChangeHandler<T> = (newValue: T, oldValue: T) => void;
9
10
  interface KTRef<T> {
11
+ /**
12
+ * If new value and old value are both nodes, the old one will be replaced in the DOM
13
+ */
10
14
  value: T;
11
15
  isKT: true;
16
+ addOnChange: (callback: ChangeHandler<T>) => void;
17
+ removeOnChange: (callback: ChangeHandler<T>) => void;
12
18
  }
13
19
  /**
14
20
  * Reference to the created HTML element.
@@ -48,7 +54,7 @@ declare global {
48
54
  type SingleContent = KTRef<any> | HTMLElement | Element | Node | string | number | boolean | null | undefined;
49
55
  type KTAvailableContent = SingleContent | KTAvailableContent[];
50
56
  type KTRawContent = KTAvailableContent | Promise<KTAvailableContent>;
51
- type KTRawAttr = KTAttribute | string;
57
+ type KTRawAttr = KTAttribute | null | undefined | '' | false;
52
58
  type KTRawContents = KTAvailableContent;
53
59
 
54
60
  /**
@@ -172,7 +178,7 @@ type HTML<T extends (HTMLTag | SVGTag) & otherstring> = T extends SVGTag ? SVGEl
172
178
  * ## About
173
179
  * @package @ktjs/core
174
180
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
175
- * @version 0.17.3 (Last Update: 2026.01.28 16:50:39.470)
181
+ * @version 0.18.0 (Last Update: 2026.01.30 21:16:15.994)
176
182
  * @license MIT
177
183
  * @link https://github.com/baendlorel/kt.js
178
184
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -97,14 +97,14 @@ var __ktjs_core__ = (function (exports) {
97
97
  }
98
98
  }
99
99
  function applyAttr(element, attr) {
100
+ if (!attr) {
101
+ return;
102
+ }
100
103
  if (typeof attr === 'object' && attr !== null) {
101
104
  attrIsObject(element, attr);
102
105
  }
103
- else if (typeof attr === 'string') {
104
- element.className = attr;
105
- }
106
106
  else {
107
- throw new Error('kt.js: attr must be an object/string.');
107
+ throw new Error('kt.js: attr must be an object.');
108
108
  }
109
109
  }
110
110
 
@@ -204,8 +204,7 @@ var __ktjs_core__ = (function (exports) {
204
204
  }
205
205
  }
206
206
 
207
- const defaultCreator = (tag) => document.createElement(tag);
208
- let creator = defaultCreator;
207
+ const svgTempWrapper = document.createElement('div');
209
208
  /**
210
209
  * Create an enhanced HTMLElement.
211
210
  * - Only supports HTMLElements, **NOT** SVGElements or other Elements.
@@ -216,7 +215,7 @@ var __ktjs_core__ = (function (exports) {
216
215
  * ## About
217
216
  * @package @ktjs/core
218
217
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
219
- * @version 0.17.3 (Last Update: 2026.01.28 16:50:39.470)
218
+ * @version 0.18.0 (Last Update: 2026.01.30 21:16:15.994)
220
219
  * @license MIT
221
220
  * @link https://github.com/baendlorel/kt.js
222
221
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -228,14 +227,13 @@ var __ktjs_core__ = (function (exports) {
228
227
  $throw('tagName must be a string.');
229
228
  }
230
229
  // * start creating the element
231
- const element = creator(tag);
230
+ const element = document.createElement(tag);
232
231
  // * Handle content
233
232
  applyAttr(element, attr);
234
233
  applyContent(element, content);
235
234
  if (tag === 'svg') {
236
- const div = document.createElement('div');
237
- div.innerHTML = element.outerHTML;
238
- return div.firstChild;
235
+ svgTempWrapper.innerHTML = element.outerHTML;
236
+ return svgTempWrapper.firstChild;
239
237
  }
240
238
  return element;
241
239
  };
@@ -246,11 +244,44 @@ var __ktjs_core__ = (function (exports) {
246
244
  * @param value mostly an HTMLElement
247
245
  */
248
246
  function ref(value) {
249
- return { value: value, isKT: true };
247
+ let _value = value;
248
+ let _onChanges = [];
249
+ return {
250
+ isKT: true,
251
+ get value() {
252
+ return _value;
253
+ },
254
+ set value(newValue) {
255
+ if (newValue === _value) {
256
+ return;
257
+ }
258
+ // replace the old node with the new one in the DOM if both are nodes
259
+ if (_value instanceof Node && newValue instanceof Node) {
260
+ if (newValue.contains(_value)) {
261
+ _value.remove();
262
+ }
263
+ _value.replaceWith(newValue);
264
+ }
265
+ const oldValue = _value;
266
+ _value = newValue;
267
+ for (let i = 0; i < _onChanges.length; i++) {
268
+ _onChanges[i](newValue, oldValue);
269
+ }
270
+ },
271
+ addOnChange: (callback) => _onChanges.push(callback),
272
+ removeOnChange: (callback) => {
273
+ for (let i = _onChanges.length - 1; i >= 0; i--) {
274
+ if (_onChanges[i] === callback) {
275
+ _onChanges.splice(i, 1);
276
+ return true;
277
+ }
278
+ }
279
+ return false;
280
+ },
281
+ };
250
282
  }
251
283
 
252
284
  const dummyRef = { value: null };
253
- // todo 是否进一步削减h函数的分支,比如去掉string为attr的情况
254
285
  /**
255
286
  * @param tag html tag or function component
256
287
  * @param props properties/attributes
@@ -109,14 +109,14 @@ var __ktjs_core__ = (function (exports) {
109
109
  }
110
110
  }
111
111
  function applyAttr(element, attr) {
112
+ if (!attr) {
113
+ return;
114
+ }
112
115
  if (typeof attr === 'object' && attr !== null) {
113
116
  attrIsObject(element, attr);
114
117
  }
115
- else if (typeof attr === 'string') {
116
- element.className = attr;
117
- }
118
118
  else {
119
- throw new Error('kt.js: attr must be an object/string.');
119
+ throw new Error('kt.js: attr must be an object.');
120
120
  }
121
121
  }
122
122
 
@@ -229,8 +229,7 @@ var __ktjs_core__ = (function (exports) {
229
229
  }
230
230
  }
231
231
 
232
- var defaultCreator = function (tag) { return document.createElement(tag); };
233
- var creator = defaultCreator;
232
+ var svgTempWrapper = document.createElement('div');
234
233
  /**
235
234
  * Create an enhanced HTMLElement.
236
235
  * - Only supports HTMLElements, **NOT** SVGElements or other Elements.
@@ -241,7 +240,7 @@ var __ktjs_core__ = (function (exports) {
241
240
  * ## About
242
241
  * @package @ktjs/core
243
242
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
244
- * @version 0.17.3 (Last Update: 2026.01.28 16:50:39.470)
243
+ * @version 0.18.0 (Last Update: 2026.01.30 21:16:15.994)
245
244
  * @license MIT
246
245
  * @link https://github.com/baendlorel/kt.js
247
246
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -253,14 +252,13 @@ var __ktjs_core__ = (function (exports) {
253
252
  $throw('tagName must be a string.');
254
253
  }
255
254
  // * start creating the element
256
- var element = creator(tag);
255
+ var element = document.createElement(tag);
257
256
  // * Handle content
258
257
  applyAttr(element, attr);
259
258
  applyContent(element, content);
260
259
  if (tag === 'svg') {
261
- var div = document.createElement('div');
262
- div.innerHTML = element.outerHTML;
263
- return div.firstChild;
260
+ svgTempWrapper.innerHTML = element.outerHTML;
261
+ return svgTempWrapper.firstChild;
264
262
  }
265
263
  return element;
266
264
  };
@@ -304,11 +302,44 @@ var __ktjs_core__ = (function (exports) {
304
302
  * @param value mostly an HTMLElement
305
303
  */
306
304
  function ref(value) {
307
- return { value: value, isKT: true };
305
+ var _value = value;
306
+ var _onChanges = [];
307
+ return {
308
+ isKT: true,
309
+ get value() {
310
+ return _value;
311
+ },
312
+ set value(newValue) {
313
+ if (newValue === _value) {
314
+ return;
315
+ }
316
+ // replace the old node with the new one in the DOM if both are nodes
317
+ if (_value instanceof Node && newValue instanceof Node) {
318
+ if (newValue.contains(_value)) {
319
+ _value.remove();
320
+ }
321
+ _value.replaceWith(newValue);
322
+ }
323
+ var oldValue = _value;
324
+ _value = newValue;
325
+ for (var i = 0; i < _onChanges.length; i++) {
326
+ _onChanges[i](newValue, oldValue);
327
+ }
328
+ },
329
+ addOnChange: function (callback) { return _onChanges.push(callback); },
330
+ removeOnChange: function (callback) {
331
+ for (var i = _onChanges.length - 1; i >= 0; i--) {
332
+ if (_onChanges[i] === callback) {
333
+ _onChanges.splice(i, 1);
334
+ return true;
335
+ }
336
+ }
337
+ return false;
338
+ },
339
+ };
308
340
  }
309
341
 
310
342
  var dummyRef = { value: null };
311
- // todo 是否进一步削减h函数的分支,比如去掉string为attr的情况
312
343
  /**
313
344
  * @param tag html tag or function component
314
345
  * @param props properties/attributes
package/dist/index.mjs CHANGED
@@ -94,14 +94,14 @@ function attrIsObject(element, attr) {
94
94
  }
95
95
  }
96
96
  function applyAttr(element, attr) {
97
+ if (!attr) {
98
+ return;
99
+ }
97
100
  if (typeof attr === 'object' && attr !== null) {
98
101
  attrIsObject(element, attr);
99
102
  }
100
- else if (typeof attr === 'string') {
101
- element.className = attr;
102
- }
103
103
  else {
104
- throw new Error('kt.js: attr must be an object/string.');
104
+ throw new Error('kt.js: attr must be an object.');
105
105
  }
106
106
  }
107
107
 
@@ -201,8 +201,7 @@ function applyContent(element, content) {
201
201
  }
202
202
  }
203
203
 
204
- const defaultCreator = (tag) => document.createElement(tag);
205
- let creator = defaultCreator;
204
+ const svgTempWrapper = document.createElement('div');
206
205
  /**
207
206
  * Create an enhanced HTMLElement.
208
207
  * - Only supports HTMLElements, **NOT** SVGElements or other Elements.
@@ -213,7 +212,7 @@ let creator = defaultCreator;
213
212
  * ## About
214
213
  * @package @ktjs/core
215
214
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
216
- * @version 0.17.3 (Last Update: 2026.01.28 16:50:39.470)
215
+ * @version 0.18.0 (Last Update: 2026.01.30 21:16:15.994)
217
216
  * @license MIT
218
217
  * @link https://github.com/baendlorel/kt.js
219
218
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -225,14 +224,13 @@ const h = (tag, attr, content) => {
225
224
  $throw('tagName must be a string.');
226
225
  }
227
226
  // * start creating the element
228
- const element = creator(tag);
227
+ const element = document.createElement(tag);
229
228
  // * Handle content
230
229
  applyAttr(element, attr);
231
230
  applyContent(element, content);
232
231
  if (tag === 'svg') {
233
- const div = document.createElement('div');
234
- div.innerHTML = element.outerHTML;
235
- return div.firstChild;
232
+ svgTempWrapper.innerHTML = element.outerHTML;
233
+ return svgTempWrapper.firstChild;
236
234
  }
237
235
  return element;
238
236
  };
@@ -243,11 +241,44 @@ const h = (tag, attr, content) => {
243
241
  * @param value mostly an HTMLElement
244
242
  */
245
243
  function ref(value) {
246
- return { value: value, isKT: true };
244
+ let _value = value;
245
+ let _onChanges = [];
246
+ return {
247
+ isKT: true,
248
+ get value() {
249
+ return _value;
250
+ },
251
+ set value(newValue) {
252
+ if (newValue === _value) {
253
+ return;
254
+ }
255
+ // replace the old node with the new one in the DOM if both are nodes
256
+ if (_value instanceof Node && newValue instanceof Node) {
257
+ if (newValue.contains(_value)) {
258
+ _value.remove();
259
+ }
260
+ _value.replaceWith(newValue);
261
+ }
262
+ const oldValue = _value;
263
+ _value = newValue;
264
+ for (let i = 0; i < _onChanges.length; i++) {
265
+ _onChanges[i](newValue, oldValue);
266
+ }
267
+ },
268
+ addOnChange: (callback) => _onChanges.push(callback),
269
+ removeOnChange: (callback) => {
270
+ for (let i = _onChanges.length - 1; i >= 0; i--) {
271
+ if (_onChanges[i] === callback) {
272
+ _onChanges.splice(i, 1);
273
+ return true;
274
+ }
275
+ }
276
+ return false;
277
+ },
278
+ };
247
279
  }
248
280
 
249
281
  const dummyRef = { value: null };
250
- // todo 是否进一步削减h函数的分支,比如去掉string为attr的情况
251
282
  /**
252
283
  * @param tag html tag or function component
253
284
  * @param props properties/attributes
@@ -6,9 +6,15 @@ type otherstring = string & {};
6
6
  type HTMLTag = keyof HTMLElementTagNameMap;
7
7
  type SVGTag = keyof SVGElementTagNameMap;
8
8
 
9
+ type ChangeHandler<T> = (newValue: T, oldValue: T) => void;
9
10
  interface KTRef<T> {
11
+ /**
12
+ * If new value and old value are both nodes, the old one will be replaced in the DOM
13
+ */
10
14
  value: T;
11
15
  isKT: true;
16
+ addOnChange: (callback: ChangeHandler<T>) => void;
17
+ removeOnChange: (callback: ChangeHandler<T>) => void;
12
18
  }
13
19
  /**
14
20
  * Reference to the created HTML element.
@@ -48,7 +54,7 @@ declare global {
48
54
  type SingleContent = KTRef<any> | HTMLElement | Element | Node | string | number | boolean | null | undefined;
49
55
  type KTAvailableContent = SingleContent | KTAvailableContent[];
50
56
  type KTRawContent = KTAvailableContent | Promise<KTAvailableContent>;
51
- type KTRawAttr = KTAttribute | string;
57
+ type KTRawAttr = KTAttribute | null | undefined | '' | false;
52
58
 
53
59
  /**
54
60
  * Used to create enhanced HTML elements
@@ -158,7 +164,7 @@ type HTML<T extends (HTMLTag | SVGTag) & otherstring> = T extends SVGTag ? SVGEl
158
164
  * ## About
159
165
  * @package @ktjs/core
160
166
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
161
- * @version 0.17.3 (Last Update: 2026.01.28 16:50:39.470)
167
+ * @version 0.18.0 (Last Update: 2026.01.30 21:16:15.994)
162
168
  * @license MIT
163
169
  * @link https://github.com/baendlorel/kt.js
164
170
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -94,14 +94,14 @@ function attrIsObject(element, attr) {
94
94
  }
95
95
  }
96
96
  function applyAttr(element, attr) {
97
+ if (!attr) {
98
+ return;
99
+ }
97
100
  if (typeof attr === 'object' && attr !== null) {
98
101
  attrIsObject(element, attr);
99
102
  }
100
- else if (typeof attr === 'string') {
101
- element.className = attr;
102
- }
103
103
  else {
104
- throw new Error('kt.js: attr must be an object/string.');
104
+ throw new Error('kt.js: attr must be an object.');
105
105
  }
106
106
  }
107
107
 
@@ -201,8 +201,7 @@ function applyContent(element, content) {
201
201
  }
202
202
  }
203
203
 
204
- const defaultCreator = (tag) => document.createElement(tag);
205
- let creator = defaultCreator;
204
+ const svgTempWrapper = document.createElement('div');
206
205
  /**
207
206
  * Create an enhanced HTMLElement.
208
207
  * - Only supports HTMLElements, **NOT** SVGElements or other Elements.
@@ -213,7 +212,7 @@ let creator = defaultCreator;
213
212
  * ## About
214
213
  * @package @ktjs/core
215
214
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
216
- * @version 0.17.3 (Last Update: 2026.01.28 16:50:39.470)
215
+ * @version 0.18.0 (Last Update: 2026.01.30 21:16:15.994)
217
216
  * @license MIT
218
217
  * @link https://github.com/baendlorel/kt.js
219
218
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -225,14 +224,13 @@ const h = (tag, attr, content) => {
225
224
  $throw('tagName must be a string.');
226
225
  }
227
226
  // * start creating the element
228
- const element = creator(tag);
227
+ const element = document.createElement(tag);
229
228
  // * Handle content
230
229
  applyAttr(element, attr);
231
230
  applyContent(element, content);
232
231
  if (tag === 'svg') {
233
- const div = document.createElement('div');
234
- div.innerHTML = element.outerHTML;
235
- return div.firstChild;
232
+ svgTempWrapper.innerHTML = element.outerHTML;
233
+ return svgTempWrapper.firstChild;
236
234
  }
237
235
  return element;
238
236
  };
@@ -243,11 +241,44 @@ const h = (tag, attr, content) => {
243
241
  * @param value mostly an HTMLElement
244
242
  */
245
243
  function ref(value) {
246
- return { value: value, isKT: true };
244
+ let _value = value;
245
+ let _onChanges = [];
246
+ return {
247
+ isKT: true,
248
+ get value() {
249
+ return _value;
250
+ },
251
+ set value(newValue) {
252
+ if (newValue === _value) {
253
+ return;
254
+ }
255
+ // replace the old node with the new one in the DOM if both are nodes
256
+ if (_value instanceof Node && newValue instanceof Node) {
257
+ if (newValue.contains(_value)) {
258
+ _value.remove();
259
+ }
260
+ _value.replaceWith(newValue);
261
+ }
262
+ const oldValue = _value;
263
+ _value = newValue;
264
+ for (let i = 0; i < _onChanges.length; i++) {
265
+ _onChanges[i](newValue, oldValue);
266
+ }
267
+ },
268
+ addOnChange: (callback) => _onChanges.push(callback),
269
+ removeOnChange: (callback) => {
270
+ for (let i = _onChanges.length - 1; i >= 0; i--) {
271
+ if (_onChanges[i] === callback) {
272
+ _onChanges.splice(i, 1);
273
+ return true;
274
+ }
275
+ }
276
+ return false;
277
+ },
278
+ };
247
279
  }
248
280
 
249
281
  const dummyRef = { value: null };
250
- // todo 是否进一步削减h函数的分支,比如去掉string为attr的情况
251
282
  /**
252
283
  * @param tag html tag or function component
253
284
  * @param props properties/attributes
@@ -6,9 +6,15 @@ type otherstring = string & {};
6
6
  type HTMLTag = keyof HTMLElementTagNameMap;
7
7
  type SVGTag = keyof SVGElementTagNameMap;
8
8
 
9
+ type ChangeHandler<T> = (newValue: T, oldValue: T) => void;
9
10
  interface KTRef<T> {
11
+ /**
12
+ * If new value and old value are both nodes, the old one will be replaced in the DOM
13
+ */
10
14
  value: T;
11
15
  isKT: true;
16
+ addOnChange: (callback: ChangeHandler<T>) => void;
17
+ removeOnChange: (callback: ChangeHandler<T>) => void;
12
18
  }
13
19
 
14
20
  type Redraw = (props?: KTAttribute, ...args: any[]) => KTHTMLElement;
@@ -42,7 +48,7 @@ declare global {
42
48
  type SingleContent = KTRef<any> | HTMLElement | Element | Node | string | number | boolean | null | undefined;
43
49
  type KTAvailableContent = SingleContent | KTAvailableContent[];
44
50
  type KTRawContent = KTAvailableContent | Promise<KTAvailableContent>;
45
- type KTRawAttr = KTAttribute | string;
51
+ type KTRawAttr = KTAttribute | null | undefined | '' | false;
46
52
 
47
53
  /**
48
54
  * Used to create enhanced HTML elements
@@ -152,7 +158,7 @@ type HTML<T extends (HTMLTag | SVGTag) & otherstring> = T extends SVGTag ? SVGEl
152
158
  * ## About
153
159
  * @package @ktjs/core
154
160
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
155
- * @version 0.17.3 (Last Update: 2026.01.28 16:50:39.470)
161
+ * @version 0.18.0 (Last Update: 2026.01.30 21:16:15.994)
156
162
  * @license MIT
157
163
  * @link https://github.com/baendlorel/kt.js
158
164
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -94,14 +94,14 @@ function attrIsObject(element, attr) {
94
94
  }
95
95
  }
96
96
  function applyAttr(element, attr) {
97
+ if (!attr) {
98
+ return;
99
+ }
97
100
  if (typeof attr === 'object' && attr !== null) {
98
101
  attrIsObject(element, attr);
99
102
  }
100
- else if (typeof attr === 'string') {
101
- element.className = attr;
102
- }
103
103
  else {
104
- throw new Error('kt.js: attr must be an object/string.');
104
+ throw new Error('kt.js: attr must be an object.');
105
105
  }
106
106
  }
107
107
 
@@ -201,8 +201,7 @@ function applyContent(element, content) {
201
201
  }
202
202
  }
203
203
 
204
- const defaultCreator = (tag) => document.createElement(tag);
205
- let creator = defaultCreator;
204
+ const svgTempWrapper = document.createElement('div');
206
205
  /**
207
206
  * Create an enhanced HTMLElement.
208
207
  * - Only supports HTMLElements, **NOT** SVGElements or other Elements.
@@ -213,7 +212,7 @@ let creator = defaultCreator;
213
212
  * ## About
214
213
  * @package @ktjs/core
215
214
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
216
- * @version 0.17.3 (Last Update: 2026.01.28 16:50:39.470)
215
+ * @version 0.18.0 (Last Update: 2026.01.30 21:16:15.994)
217
216
  * @license MIT
218
217
  * @link https://github.com/baendlorel/kt.js
219
218
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -225,14 +224,13 @@ const h = (tag, attr, content) => {
225
224
  $throw('tagName must be a string.');
226
225
  }
227
226
  // * start creating the element
228
- const element = creator(tag);
227
+ const element = document.createElement(tag);
229
228
  // * Handle content
230
229
  applyAttr(element, attr);
231
230
  applyContent(element, content);
232
231
  if (tag === 'svg') {
233
- const div = document.createElement('div');
234
- div.innerHTML = element.outerHTML;
235
- return div.firstChild;
232
+ svgTempWrapper.innerHTML = element.outerHTML;
233
+ return svgTempWrapper.firstChild;
236
234
  }
237
235
  return element;
238
236
  };
@@ -243,11 +241,44 @@ const h = (tag, attr, content) => {
243
241
  * @param value mostly an HTMLElement
244
242
  */
245
243
  function ref(value) {
246
- return { value: value, isKT: true };
244
+ let _value = value;
245
+ let _onChanges = [];
246
+ return {
247
+ isKT: true,
248
+ get value() {
249
+ return _value;
250
+ },
251
+ set value(newValue) {
252
+ if (newValue === _value) {
253
+ return;
254
+ }
255
+ // replace the old node with the new one in the DOM if both are nodes
256
+ if (_value instanceof Node && newValue instanceof Node) {
257
+ if (newValue.contains(_value)) {
258
+ _value.remove();
259
+ }
260
+ _value.replaceWith(newValue);
261
+ }
262
+ const oldValue = _value;
263
+ _value = newValue;
264
+ for (let i = 0; i < _onChanges.length; i++) {
265
+ _onChanges[i](newValue, oldValue);
266
+ }
267
+ },
268
+ addOnChange: (callback) => _onChanges.push(callback),
269
+ removeOnChange: (callback) => {
270
+ for (let i = _onChanges.length - 1; i >= 0; i--) {
271
+ if (_onChanges[i] === callback) {
272
+ _onChanges.splice(i, 1);
273
+ return true;
274
+ }
275
+ }
276
+ return false;
277
+ },
278
+ };
247
279
  }
248
280
 
249
281
  const dummyRef = { value: null };
250
- // todo 是否进一步削减h函数的分支,比如去掉string为attr的情况
251
282
  /**
252
283
  * @param tag html tag or function component
253
284
  * @param props properties/attributes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ktjs/core",
3
- "version": "0.17.3",
3
+ "version": "0.18.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",