kt.js 0.23.0 → 0.24.1

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.
Files changed (3) hide show
  1. package/README.md +116 -161
  2. package/dist/jsx-runtime.mjs +120 -100
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -1,43 +1,54 @@
1
- <img src="https://raw.githubusercontent.com/baendlorel/kt.js/dev/.assets/ktjs-0.0.1.svg" alt="KT.js Logo" width="150"/>
1
+ # KT.js
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/kt.js.svg)](https://www.npmjs.com/package/kt.js) [![license](https://img.shields.io/github/license/baendlorel/kt.js.svg)](https://github.com/baendlorel/kt.js/blob/main/LICENSE)
3
+ A lightweight, manual‑control web framework that creates real DOM elements with built‑in reactive state management.
4
4
 
5
- [CHANGLOG✨](../../CHANGELOG.md)
5
+ [![npm version](https://img.shields.io/npm/v/kt.js.svg)](https://www.npmjs.com/package/kt.js)
6
+ [![npm downloads](https://img.shields.io/npm/dm/kt.js.svg)](https://www.npmjs.com/package/kt.js)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
8
 
7
- > Note: This framework is still under development. APIs, type declarations, and other parts **may change frequently**. If you use it, please watch for updates in the near future. Feel free to mail me if you have any questions!
9
+ [Changelog](../../CHANGELOG.md)
8
10
 
9
- KT.js is a tiny DOM utility focused on direct DOM manipulation. It favors not forcing re-renders and aims to keep DOM updates to the absolute minimum for maximum performance.
11
+ ## Features
10
12
 
11
- For more awesome packages, check out [my homepage💛](https://baendlorel.github.io/?repoType=npm)
13
+ - **Real DOM** – JSX compiles directly to `HTMLElement` creation, with zero virtual‑DOM overhead.
14
+ - **Manual Updates** – You decide when the DOM updates; no automatic re‑renders.
15
+ - **Reactive State** – Built‑in `ref()` and `computed()` for reactive values with change listeners.
16
+ - **Zero Forced Re‑renders** – Update only what changes; avoid full‑component repaints.
17
+ - **Full TypeScript Support** – Accurate type inference and JSX/TSX integration.
18
+ - **Lightweight** – Small bundle size, no unnecessary dependencies.
12
19
 
13
- ## Architecture
20
+ ## Quick Start
14
21
 
15
- KT.js is now a **monorepo** containing multiple packages:
16
-
17
- - **[kt.js](./packages/kt.js)**: Main entry package that re-exports all functionality
18
- - **[@ktjs/core](./packages/core)**: Core DOM manipulation utilities and the `h` function. SX/TSX support with full TypeScript integration (included in kt.js package)
19
- - **[@ktjs/router](./packages/router)**: Client-side routing with navigation guards (not included in kt.js package)
20
- - **[@ktjs/mui](./packages/mui)**: Material UI components built on top of KT.js (not included in kt.js package)
21
-
22
- You can install the full package or individual packages as needed:
22
+ ### Installation
23
23
 
24
24
  ```bash
25
+ # Full package (includes core)
25
26
  pnpm add kt.js
26
27
 
27
- # Or install individual packages
28
- pnpm add @ktjs/router # Client-side router (requires @ktjs/core)
29
- pnpm add @ktjs/mui # Material UI components (requires @ktjs/core)
28
+ # Individual packages
29
+ pnpm add @ktjs/core @ktjs/router
30
30
  ```
31
31
 
32
- ## Philosophy
32
+ ### Basic Usage
33
33
 
34
- As a web framework, repeatedly creating a large number of variables and objects is unacceptable. So I created KT.js.
34
+ ```tsx
35
+ import { ref } from 'kt.js';
35
36
 
36
- KT.js follows one rule: **full control of DOM and avoid unnecessary repainting**.
37
+ function Counter() {
38
+ const count = ref(0);
37
39
 
38
- ## Configuration
40
+ const button = <button on:click={() => count.value++}>Count: {count.value}</button>;
39
41
 
40
- for TSX/JSX support, add this to your `tsconfig.json`:
42
+ return button;
43
+ }
44
+
45
+ // Mount to DOM
46
+ document.body.appendChild(Counter());
47
+ ```
48
+
49
+ ### TypeScript Configuration
50
+
51
+ For JSX/TSX support, set your `tsconfig.json`:
41
52
 
42
53
  ```json
43
54
  {
@@ -48,192 +59,136 @@ for TSX/JSX support, add this to your `tsconfig.json`:
48
59
  }
49
60
  ```
50
61
 
51
- ## Core Features (@ktjs/core)
62
+ ## Core Features
52
63
 
53
- ### JSX/TSX Support
54
-
55
- KT.js provides first-class JSX/TSX support with zero virtual DOM overhead. JSX compiles directly to `h()` function calls.
64
+ ### Reactive System
56
65
 
57
66
  ```tsx
58
- // Function components
59
- const Button = ({ onClick, children }) => (
60
- <button on:click={onClick} class="btn">
61
- {children}
62
- </button>
63
- );
64
-
65
- // Conditional rendering with k-if
66
- const UserCard = ({ user, showDetails }) => (
67
- <div class="card">
68
- <h3>{user.name}</h3>
69
- <div k-if={showDetails}>
70
- <p>Email: {user.email}</p>
71
- <p>Role: {user.role}</p>
72
- </div>
73
- </div>
74
- );
67
+ import { ref, computed } from 'kt.js';
75
68
 
76
- // List rendering with KTFor
77
- const UserList = ({ users }) => <KTFor list={users} key={(user) => user.id} map={(user) => <UserCard user={user} />} />;
69
+ // Reactive references
70
+ const count = ref(0);
71
+ const double = computed(() => count.value * 2, [count]);
78
72
 
79
- // Async components
80
- const AsyncContent = async () => {
81
- const data = await fetchData();
82
- return <div>{data}</div>;
83
- };
84
- ```
73
+ // Listen to changes
74
+ count.addOnChange((newVal, oldVal) => {
75
+ console.log(`Count changed from ${oldVal} to ${newVal}`);
76
+ });
85
77
 
86
- ### Directives
78
+ // Update triggers change listeners
79
+ count.value = 10;
80
+ ```
87
81
 
88
- #### `k-if`: Conditional rendering.
82
+ ### Conditional Rendering
89
83
 
90
84
  ```tsx
91
- <div k-if={condition}>This will render only if condition is true.</div>
92
- ```
85
+ const show = ref(true);
93
86
 
94
- If a `ref` instance is bound, the element will automatically redraw on changes.
87
+ const element = <div k-if={show}>This content is conditionally rendered</div>;
95
88
 
96
- #### `k-model`: Two-way data binding for form elements.
89
+ // Toggle visibility
90
+ show.value = false; // Element becomes a comment placeholder
91
+ ```
97
92
 
98
- Must bind to a `ref` instance.
93
+ ### List Rendering
99
94
 
100
95
  ```tsx
101
- import { ref } from 'kt.js';
102
- const name = ref('');
96
+ import { KTFor, ref } from 'kt.js';
103
97
 
104
- function NameInput() {
105
- return (
106
- <div>
107
- <input type="text" k-model={name} />
108
- </div>
109
- );
110
- }
98
+ const items = ref([
99
+ { id: 1, name: 'Item 1' },
100
+ { id: 2, name: 'Item 2' },
101
+ ]);
111
102
 
112
- name.value = 'New Name'; // Updates input value
113
- ```
103
+ const list = <KTFor list={items.value} key={(item) => item.id} map={(item) => <div>{item.name}</div>} />;
114
104
 
115
- ### CreateRedrawable
105
+ // Update list
106
+ items.value = [...items.value, { id: 3, name: 'Item 3' }];
107
+ ```
116
108
 
117
- Create redrawable components with `createRedrawable()`.
109
+ ### Two‑way Data Binding
118
110
 
119
111
  ```tsx
120
- import { createRedrawable } from '@ktjs/core';
121
- let text = 'aa';
122
- const el = createRedrawable(() => <div>{text}</div>);
123
- // el is now `<div>aa</div>`
124
- text = 'bb';
125
- el.redraw();
126
- // el is now `<div>bb</div>`
112
+ function InputComponent() {
113
+ const text = ref('');
114
+
115
+ return <input k-model={text} />;
116
+ }
127
117
  ```
128
118
 
129
- ### Reactive References
119
+ ### Redrawable Components
130
120
 
131
- Create reactive values with `ref()` and listen to changes.
121
+ ```tsx
122
+ import { createRedrawable, ref } from 'kt.js';
132
123
 
133
- ```typescript
134
- import { ref } from '@ktjs/core';
124
+ function DynamicCounter() {
125
+ const count = ref(0);
135
126
 
136
- const count = ref(0);
137
- count.addOnChange((newVal, oldVal) => {
138
- console.log(`Count changed from ${oldVal} to ${newVal}`);
139
- });
127
+ const counter = createRedrawable(() => (
128
+ <div>
129
+ Count: {count.value}
130
+ <button on:click={() => count.value++}>+</button>
131
+ </div>
132
+ ));
140
133
 
141
- // Update triggers change listeners
142
- count.value = 1;
134
+ // Redraw when count changes
135
+ count.addOnChange(() => counter.redraw());
136
+
137
+ return counter;
138
+ }
143
139
  ```
144
140
 
145
- #### Surface Reactive Objects
141
+ ## Package Structure
146
142
 
147
- Create depth-1 reactive objects with `surfaceRef()`.
148
- Basically a helper of wrapping each property with `ref()`.
143
+ - **[@ktjs/core](./packages/core)** Core framework with JSX, reactivity, and DOM utilities.
144
+ - **[@ktjs/router](./packages/router)** Client‑side router with navigation guards.
145
+ - **[@ktjs/mui](./packages/mui)** – Material UI components built on top of KT.js.
149
146
 
150
- ```tsx
151
- const obj = surfaceRef({ a: 1, b: 2 });
152
- obj.a.value = 3; // Triggers change listeners for obj.a
147
+ ## Philosophy
153
148
 
154
- const data = obj.kcollect(); // Deref to the original object { a: 3, b: 2 }
155
- ```
149
+ KT.js follows one rule: **full control of the DOM and avoid unnecessary repainting**.
150
+
151
+ As a web framework, repeatedly creating a large number of variables and objects is unacceptable. That’s why KT.js was built.
156
152
 
157
- ### Redraw Mechanism
153
+ ## Advanced Usage
158
154
 
159
- `<KTFor... />` elements in-place with `redraw()` for minimal DOM updates.
155
+ ### Surface References
160
156
 
161
157
  ```tsx
162
- const element = <KTFor list={someArray} map={(v) => 2 * v} />;
163
- element.redraw({ list: [1, 2, 3] });
164
- ```
158
+ import { surfaceRef } from 'kt.js';
165
159
 
166
- ## Router (@ktjs/router)
167
-
168
- Client-side hash-based routing with async navigation guards.
169
-
170
- ### Basic Routing
171
-
172
- ```typescript
173
- import { createRouter } from '@ktjs/router';
174
-
175
- const router = createRouter({
176
- routes: [
177
- {
178
- path: '/',
179
- name: 'home',
180
- component: () => <HomePage />
181
- },
182
- {
183
- path: '/user/:id',
184
- name: 'user',
185
- component: (to) => <UserPage id={to.params.id} />
186
- }
187
- ],
188
- beforeEach: async (to, from) => {
189
- // Auth check
190
- if (to.path === '/admin' && !isAdmin()) {
191
- return '/login';
192
- }
193
- }
160
+ const user = surfaceRef({
161
+ name: 'John',
162
+ age: 30,
194
163
  });
195
- ```
196
-
197
- ### Navigation
198
164
 
199
- ```typescript
200
- // Programmatic navigation
201
- router.push('/user/123');
202
- router.push({ name: 'user', params: { id: '456' } });
165
+ // Access reactive properties
166
+ user.name.value = 'Jane';
203
167
 
204
- // Access current route
205
- console.log(router.current?.path, router.current?.params);
168
+ // Get the original object
169
+ const original = user.kcollect();
206
170
  ```
207
171
 
208
- ## Installation
172
+ ### Event Handling
209
173
 
210
- ```bash
211
- # Full package (includes core)
212
- pnpm add kt.js
174
+ ```tsx
175
+ const handleClick = (event) => {
176
+ console.log('Clicked!', event);
177
+ };
213
178
 
214
- # Individual packages
215
- pnpm add @ktjs/core @ktjs/router
179
+ const button = <button on:click={handleClick}>Click me</button>;
216
180
  ```
217
181
 
218
- ## TypeScript Configuration
219
-
220
- For JSX/TSX support, configure your `tsconfig.json`:
182
+ ## Performance Benefits
221
183
 
222
- ```json
223
- {
224
- "compilerOptions": {
225
- "jsx": "react-jsx",
226
- "jsxImportSource": "@ktjs/core"
227
- }
228
- }
229
- ```
184
+ - **No Virtual DOM** – Direct DOM manipulation eliminates reconciliation overhead.
185
+ - **Manual Updates** – Only update what you need, when you need it.
186
+ - **Minimal Abstraction** – Close to native DOM APIs for maximum performance.
187
+ - **Small Bundle** – Minimal runtime overhead.
230
188
 
231
- ## Philosophy
189
+ ## Browser Support
232
190
 
233
- - **Direct DOM Manipulation**: No virtual DOM, minimal abstraction
234
- - **Zero Re-renders**: Update only what changes, avoid full component re-renders
235
- - **Type Safety**: Full TypeScript support with accurate type inference
236
- - **Lightweight**: Small bundle size, no unnecessary dependencies
191
+ KT.js supports all modern browsers and IE11+ with appropriate polyfills.
237
192
 
238
193
  ## License
239
194
 
@@ -1,10 +1,34 @@
1
+ // Shared constants
2
+ // Empty for now - can be extended with framework-wide constants
3
+ /**
4
+ * Mark the attribute as SVG to handle special cases during rendering.
5
+ */
6
+ const SVG_ATTR_FLAG = '__kt_svg__';
7
+ /**
8
+ * Mark the attribute as MathML to handle special cases during rendering.
9
+ */
10
+ const MATHML_ATTR_FLAG = '__kt_mathml__';
11
+
1
12
  // Cached native methods for performance optimization
2
13
  const $isArray = Array.isArray;
3
- const $isThenable = (o) => typeof o === 'object' && o !== null && typeof o.then === 'function';
14
+ const $is = Object.is;
15
+ const $random = Math.random;
16
+ const $isThenable = (o) => typeof o?.then === 'function';
4
17
 
5
18
  // DOM manipulation utilities
6
19
  // # dom natives
7
20
  const $isNode = (x) => x?.nodeType > 0;
21
+ /**
22
+ * Safe replace `oldNode` With `newNode`
23
+ */
24
+ const $replaceNode = (oldNode, newNode) => {
25
+ if ($isNode(oldNode) && $isNode(newNode)) {
26
+ if (newNode.contains(oldNode)) {
27
+ newNode.remove();
28
+ }
29
+ oldNode.replaceWith(newNode);
30
+ }
31
+ };
8
32
  /**
9
33
  * & Remove `bind` because it is shockingly slower than wrapper
10
34
  * & `window.document` is safe because it is not configurable and its setter is undefined
@@ -50,85 +74,21 @@ const applyModel = (element, valueRef, propName, eventName) => {
50
74
  element.addEventListener(eventName, () => (valueRef.value = element[propName]));
51
75
  };
52
76
 
77
+ if (typeof Symbol === 'undefined') {
78
+ window.Symbol = function Symbol(description) {
79
+ return `@@SYMBOL_${description || ''}_${$random().toString(36).slice(2)}`;
80
+ };
81
+ }
82
+
53
83
  // Shared utilities and cached native methods for kt.js framework
54
- // import './misc/symbol-polyfill.js';
55
- // Re-export all utilities
56
- Object.defineProperty(window, '__ktjs__', { value: '0.22.3' });
84
+ Object.defineProperty(window, '__ktjs__', { value: '0.22.6' });
57
85
 
58
- class KTRef {
59
- /**
60
- * Indicates that this is a KTRef instance
61
- */
62
- isKT = true;
63
- /**
64
- * @internal
65
- */
66
- _value;
67
- /**
68
- * @internal
69
- */
70
- _onChanges;
71
- constructor(_value, _onChanges) {
72
- this._value = _value;
73
- this._onChanges = _onChanges;
74
- }
75
- /**
76
- * If new value and old value are both nodes, the old one will be replaced in the DOM
77
- */
78
- get value() {
79
- return this._value;
80
- }
81
- set value(newValue) {
82
- if (newValue === this._value) {
83
- return;
84
- }
85
- // replace the old node with the new one in the DOM if both are nodes
86
- if (this._value instanceof Node && newValue instanceof Node) {
87
- if (newValue.contains(this._value)) {
88
- this._value.remove();
89
- }
90
- this._value.replaceWith(newValue);
91
- }
92
- const oldValue = this._value;
93
- this._value = newValue;
94
- for (let i = 0; i < this._onChanges.length; i++) {
95
- this._onChanges[i](newValue, oldValue);
96
- }
97
- }
98
- /**
99
- * Register a callback when the value changes
100
- * @param callback (newValue, oldValue) => xxx
101
- */
102
- addOnChange(callback) {
103
- if (typeof callback !== 'function') {
104
- throw new Error('[kt.js error] KTRef.addOnChange: callback must be a function');
105
- }
106
- this._onChanges.push(callback);
107
- }
108
- removeOnChange(callback) {
109
- for (let i = this._onChanges.length - 1; i >= 0; i--) {
110
- if (this._onChanges[i] === callback) {
111
- this._onChanges.splice(i, 1);
112
- return true;
113
- }
114
- }
115
- return false;
116
- }
117
- }
118
- const isKTRef = (obj) => obj?.isKT === true;
119
- /**
120
- * Reference to the created HTML element.
121
- * - **Only** respond to `ref.value` changes, not reactive to internal changes of the element.
122
- * - can alse be used to store normal values, but it is not reactive.
123
- * - if the value is already a `KTRef`, it will be returned **directly**.
124
- * @param value mostly an HTMLElement
125
- */
126
- function ref(value, onChange) {
127
- if (isKTRef(value)) {
128
- return value;
129
- }
130
- return new KTRef(value, []);
131
- }
86
+ // export const KT_TYPE_REF = 1 as const;
87
+ // export const KT_TYPE_COMPUTED = 2 as const;
88
+ // export type KTReactiveTypeEnum = typeof KT_TYPE_REF | typeof KT_TYPE_COMPUTED;
89
+ const isKT = (obj) => obj?.isKT;
90
+ const isRef = (obj) => obj?.ktType === 1 /* KTReactiveType.REF */;
91
+ const isComputed = (obj) => obj?.ktType === 2 /* KTReactiveType.COMPUTED */;
132
92
 
133
93
  const booleanHandler = (element, key, value) => {
134
94
  if (key in element) {
@@ -190,7 +150,7 @@ function attrIsObject(element, attr) {
190
150
  }
191
151
  if ('k-html' in attr) {
192
152
  const html = attr['k-html'];
193
- if (isKTRef(html)) {
153
+ if (isKT(html)) {
194
154
  element.innerHTML = html.value;
195
155
  html.addOnChange((v) => (element.innerHTML = v));
196
156
  }
@@ -199,14 +159,14 @@ function attrIsObject(element, attr) {
199
159
  }
200
160
  }
201
161
  for (const key in attr) {
202
- if (key === 'class' ||
162
+ if (key === 'k-if' ||
163
+ key === 'k-model' ||
164
+ key === 'ref' ||
165
+ key === 'class' ||
203
166
  key === 'className' ||
204
167
  key === 'style' ||
205
168
  key === 'children' ||
206
- key === 'k-if' ||
207
- key === 'k-model' ||
208
- key === 'k-html' ||
209
- key === 'ref') {
169
+ key === 'k-html') {
210
170
  continue;
211
171
  }
212
172
  const o = attr[key];
@@ -239,7 +199,7 @@ function apdSingle(element, c) {
239
199
  if (c === false || c === undefined || c === null) {
240
200
  return;
241
201
  }
242
- if (isKTRef(c)) {
202
+ if (isKT(c)) {
243
203
  let node = assureNode(c.value);
244
204
  $append.call(element, node);
245
205
  c.addOnChange((newValue, oldValue) => {
@@ -296,8 +256,74 @@ function applyContent(element, content) {
296
256
  }
297
257
  }
298
258
 
259
+ class KTRef {
260
+ /**
261
+ * Indicates that this is a KTRef instance
262
+ */
263
+ isKT = true;
264
+ ktType = 1 /* KTReactiveType.REF */;
265
+ /**
266
+ * @internal
267
+ */
268
+ _value;
269
+ /**
270
+ * @internal
271
+ */
272
+ _onChanges;
273
+ constructor(_value, _onChanges) {
274
+ this._value = _value;
275
+ this._onChanges = _onChanges;
276
+ }
277
+ /**
278
+ * If new value and old value are both nodes, the old one will be replaced in the DOM
279
+ */
280
+ get value() {
281
+ return this._value;
282
+ }
283
+ set value(newValue) {
284
+ if ($is(newValue, this._value)) {
285
+ return;
286
+ }
287
+ const oldValue = this._value;
288
+ $replaceNode(oldValue, newValue);
289
+ this._value = newValue;
290
+ for (let i = 0; i < this._onChanges.length; i++) {
291
+ this._onChanges[i](newValue, oldValue);
292
+ }
293
+ }
294
+ /**
295
+ * Register a callback when the value changes
296
+ * @param callback (newValue, oldValue) => xxx
297
+ */
298
+ addOnChange(callback) {
299
+ if (typeof callback !== 'function') {
300
+ throw new Error('[kt.js error] KTRef.addOnChange: callback must be a function');
301
+ }
302
+ this._onChanges.push(callback);
303
+ }
304
+ removeOnChange(callback) {
305
+ for (let i = this._onChanges.length - 1; i >= 0; i--) {
306
+ if (this._onChanges[i] === callback) {
307
+ this._onChanges.splice(i, 1);
308
+ return true;
309
+ }
310
+ }
311
+ return false;
312
+ }
313
+ }
314
+ /**
315
+ * Reference to the created HTML element.
316
+ * - **Only** respond to `ref.value` changes, not reactive to internal changes of the element.
317
+ * - can alse be used to store normal values, but it is not reactive.
318
+ * - if the value is already a `KTRef`, it will be returned **directly**.
319
+ * @param value mostly an HTMLElement
320
+ */
321
+ function ref(value, onChange) {
322
+ return new KTRef(value, []);
323
+ }
324
+
299
325
  function applyKModel(element, valueRef) {
300
- if (!isKTRef(valueRef)) {
326
+ if (!isKT(valueRef)) {
301
327
  console.warn('[kt.js warn] k-model value must be a KTRef.');
302
328
  return;
303
329
  }
@@ -324,9 +350,6 @@ const htmlCreator = (tag) => document.createElement(tag);
324
350
  const svgCreator = (tag) => document.createElementNS('http://www.w3.org/2000/svg', tag);
325
351
  const mathMLCreator = (tag) => document.createElementNS('http://www.w3.org/1998/Math/MathML', tag);
326
352
  let creator = htmlCreator;
327
- // # consts
328
- const SVG_ATTR_FLAG = '__kt_svg__';
329
- const MATHML_ATTR_FLAG = '__kt_mathml__';
330
353
  /**
331
354
  * Create an enhanced HTMLElement.
332
355
  * - Only supports HTMLElements, **NOT** SVGElements or other Elements.
@@ -337,7 +360,7 @@ const MATHML_ATTR_FLAG = '__kt_mathml__';
337
360
  * ## About
338
361
  * @package @ktjs/core
339
362
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
340
- * @version 0.23.0 (Last Update: 2026.02.03 17:15:01.812)
363
+ * @version 0.24.1 (Last Update: 2026.02.05 12:51:38.436)
341
364
  * @license MIT
342
365
  * @link https://github.com/baendlorel/kt.js
343
366
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -367,13 +390,7 @@ const h = (tag, attr, content) => {
367
390
  applyAttr(element, attr);
368
391
  applyContent(element, content);
369
392
  if (typeof attr === 'object' && attr !== null && 'k-model' in attr) {
370
- const kmodel = attr['k-model'];
371
- if (isKTRef(kmodel)) {
372
- applyKModel(element, kmodel);
373
- }
374
- else {
375
- throw new Error('[kt.js error] k-model value must be a KTRef.');
376
- }
393
+ applyKModel(element, attr['k-model']);
377
394
  }
378
395
  return element;
379
396
  };
@@ -393,20 +410,23 @@ const placeholder = () => document.createComment('k-if');
393
410
  * @param props properties/attributes
394
411
  */
395
412
  function jsx(tag, props) {
396
- const maybeDummyRef = isKTRef(props.ref) ? props.ref : dummyRef;
413
+ if (isComputed(props.ref)) {
414
+ throw new Error('[kt.js error] Cannot assign a computed value to an element.');
415
+ }
416
+ const maybeDummyRef = isRef(props.ref) ? props.ref : dummyRef;
397
417
  let el;
398
418
  if ('k-if' in props) {
399
419
  const kif = props['k-if'];
400
420
  let condition = kif; // assume boolean by default
401
421
  // Handle reactive k-if
402
- if (isKTRef(kif)) {
422
+ if (isKT(kif)) {
403
423
  kif.addOnChange((newValue, oldValue) => {
404
424
  if (newValue === oldValue) {
405
425
  return;
406
426
  }
407
427
  const oldEl = el;
408
428
  el = newValue ? create(tag, props) : placeholder();
409
- oldEl.replaceWith(el);
429
+ $replaceNode(oldEl, el);
410
430
  maybeDummyRef.value = el;
411
431
  });
412
432
  condition = kif.value;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kt.js",
3
- "version": "0.23.0",
3
+ "version": "0.24.1",
4
4
  "author": {
5
5
  "name": "Kasukabe Tsumugi",
6
6
  "email": "futami16237@gmail.com"
@@ -41,7 +41,7 @@
41
41
  ],
42
42
  "license": "MIT",
43
43
  "dependencies": {
44
- "@ktjs/core": "0.23.0"
44
+ "@ktjs/core": "0.24.1"
45
45
  },
46
46
  "scripts": {
47
47
  "build": "rollup -c rollup.config.mjs",