kt.js 0.8.2 → 0.8.5

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
@@ -2,71 +2,238 @@
2
2
 
3
3
  <img src="https://raw.githubusercontent.com/baendlorel/kt.js/dev/.assets/ktjs-0.0.1.svg" alt="KT.js Logo" width="150"/>
4
4
 
5
- > 📦 Main entry package - For full documentation, see [KT.js](https://raw.githubusercontent.com/baendlorel/kt.js/dev/README.md).
5
+ [![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)
6
6
 
7
- Main entry package for KT.js framework - a simple and easy-to-use web framework that never re-renders.
7
+ [CHANGLOG✨](CHANGELOG.md)
8
8
 
9
- ## Overview
9
+ > 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!
10
10
 
11
- `kt.js` is the all-in-one package that re-exports everything from the KT.js ecosystem. Install this single package to get access to all features including core DOM utilities, routing, and shortcuts.
11
+ 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.
12
12
 
13
- ## Installation
13
+ For more awesome packages, check out [my homepage💛](https://baendlorel.github.io/?repoType=npm)
14
+
15
+ ## Architecture
16
+
17
+ KT.js is now a **monorepo** containing multiple packages:
18
+
19
+ - **[kt.js](./packages/kt.js)**: Main entry package that re-exports all functionality
20
+ - **[@ktjs/core](./packages/core)**: Core DOM manipulation utilities and the `h` function. SX/TSX support with full TypeScript integration (included in kt.js package)
21
+ - **[@ktjs/router](./packages/router)**: Client-side routing with navigation guards (not included in kt.js package)
22
+ - **[@ktjs/shortcuts](./packages/shortcuts)**: Convenient shortcut functions for common operations
23
+
24
+ You can install the full package or individual packages as needed:
25
+
26
+ ```bash
27
+ # Install the main package (includes core + jsx + shortcuts)
28
+ pnpm add kt.js
29
+
30
+ # Or install individual packages
31
+ pnpm add @ktjs/core # Core DOM utilities (independent)
32
+ pnpm add @ktjs/router # Client-side router (independent)
33
+ pnpm add @ktjs/shortcuts # Shortcuts (requires @ktjs/core)
34
+ ```
35
+
36
+ ## Philosophy
37
+
38
+ As a web framework, repeatedly creating a large number of variables and objects is unacceptable. So I created KT.js.
39
+
40
+ KT.js follows one rule: **full control of DOM and avoid unnecessary repainting**.
41
+
42
+ ## Key Features
43
+
44
+ - **Monorepo Architecture**: Modular packages that can be installed independently or together
45
+ - **Tiny Bundle Size**: Minimal runtime overhead with aggressive tree-shaking
46
+ - **`h` function**: Create DOM elements with a simple, flexible API
47
+ - Shortcut functions for all HTML elements (`div`, `span`, `button`, etc.)
48
+ - Event handlers with `@<eventName>` syntax or function attributes
49
+ - Full TypeScript support with intelligent type inference
50
+ - **JSX/TSX Support**: Full JSX syntax support with TypeScript integration
51
+ - Zero virtual DOM - JSX compiles directly to `h()` function calls
52
+ - Full HTML element type inference (`<button>` returns `HTMLButtonElement`)
53
+ - Support for `@click` event handler syntax
54
+ - No Fragment support - KT.js doesn't have a Fragment concept
55
+ - **Client-Side Router** (separate package):
56
+ - Hash-based routing with dynamic parameters
57
+ - Navigation guards with async/sync auto-adaptation
58
+ - Query string parsing and route matching
59
+ - Pure routing logic - no rendering, no dependencies
60
+ - **Shortcuts & Utilities**:
61
+ - `withDefaults`: Wrap element creation functions with default properties
62
+ - Convenient shorthand functions for common operations
63
+ - Form helpers and layout utilities
64
+ - **Full ES5 Compatibility**: Works in IE9+ and all modern browsers
65
+ - Transpiled to ES5 with no modern syntax
66
+ - Optional minimal Promise polyfill for older environments
67
+ - **`ktnull`**: A special value for filtering null/undefined while preserving native DOM behavior
68
+ - **Shared Runtime**: Efficient code sharing across packages with zero overhead
69
+
70
+ ## Getting started
71
+
72
+ Install via package managers:
14
73
 
15
74
  ```bash
75
+ npm install kt.js
76
+ # or
16
77
  pnpm add kt.js
17
78
  ```
18
79
 
19
- ## JSX is now Supported!!
80
+ ```ts
81
+ import { h, div } from 'kt.js';
82
+
83
+ const container = div('container', [div('header'), div('body', 'something'), div('footer')]);
84
+ const app = h('section', { id: 'app' }, container);
85
+ ```
86
+
87
+ This will create the following DOM structure:
88
+
89
+ ```html
90
+ <section id="app">
91
+ <div class="container">
92
+ <div class="header"></div>
93
+ <div class="body">something</div>
94
+ <div class="footer"></div>
95
+ </div>
96
+ </section>
97
+ ```
98
+
99
+ ### Using JSX/TSX
100
+
101
+ KT.js now has full JSX support! With the `@ktjs/jsx` package (included in the main `kt.js` package), you can write components using familiar JSX syntax:
102
+
103
+ **TypeScript Configuration** (`tsconfig.json`):
104
+
105
+ ```json
106
+ {
107
+ "compilerOptions": {
108
+ "jsx": "react-jsx",
109
+ "jsxImportSource": "@ktjs/jsx"
110
+ }
111
+ }
112
+ ```
113
+
114
+ **Basic JSX Example**:
20
115
 
21
116
  ```tsx
22
- import { ref } from 'kt.js';
23
- const myDivRef = ref<HTMLDivElement>();
24
- const myElement = <div ref={myDivRef}>Hello, KT.js with JSX!</div>;
117
+ import { jsx } from 'kt.js';
118
+
119
+ function Counter() {
120
+ const count = 0;
121
+
122
+ return (
123
+ <div class="counter">
124
+ <h1>Counter: {count}</h1>
125
+ <button @click={() => console.log('Clicked!')}>
126
+ Increment
127
+ </button>
128
+ </div>
129
+ );
130
+ }
131
+
132
+ // JSX compiles to direct h() function calls - no virtual DOM!
133
+ const counterElement = <Counter />;
134
+ ```
25
135
 
26
- // Now myDivRef.value points to the created div element
136
+ **Event Handling with @ Syntax**:
137
+
138
+ ```tsx
139
+ function App() {
140
+ const handleClick = () => alert('Button clicked!');
141
+
142
+ return (
143
+ <div>
144
+ <button @click={handleClick}>Click me</button>
145
+ <button onclick={handleClick}>Also works</button>
146
+ </div>
147
+ );
148
+ }
27
149
  ```
28
150
 
29
- ## What's Included
151
+ **Type Safety**:
30
152
 
31
- This package re-exports everything from:
153
+ ```tsx
154
+ // TypeScript knows this is an HTMLButtonElement
155
+ const button: HTMLButtonElement = <button>Click</button>;
32
156
 
33
- - **`@ktjs/core`** - Core DOM manipulation utilities
34
- - `h` function for creating elements
35
- - `ktnull` for conditional rendering
36
- - Runtime utilities and helpers
37
- - **`@ktjs/shortcuts`** - Convenient shortcuts
38
- - Element creation shortcuts (div, span, button, etc.)
39
- - `withDefaults` for creating element factories
40
- - Form helpers and layout utilities
157
+ // TypeScript knows this is an HTMLInputElement
158
+ const input: HTMLInputElement = <input type="text" value="hello" />;
41
159
 
42
- **Note:** The router (`@ktjs/router`) is a separate package and needs to be installed independently.
160
+ // TypeScript provides autocomplete for HTML attributes
161
+ const div: HTMLDivElement = <div className="container" id="main" />;
162
+ ```
43
163
 
44
- ## Quick Start
164
+ **Important Notes**:
45
165
 
46
- ```typescript
47
- import { h, div, btn, withDefaults } from 'kt.js';
166
+ - KT.js JSX has **no Fragment support** - we don't have a Fragment concept
167
+ - JSX compiles directly to `h()` function calls - **zero virtual DOM overhead**
168
+ - Use `@click` syntax for event handlers to avoid conflicts with existing attributes
169
+ - All JSX elements have proper HTML element type inference in TypeScript
48
170
 
49
- // Create elements
50
- const app = div('app', [h('h1', {}, 'Welcome to KT.js'), btn({ '@click': () => alert('Hello!') }, 'Click me')]);
171
+ If you give a function in attributes, it will be treated as an event listener, and the key will be considered as the event name. `@<eventName>` will also be considered as the handler to avoid conflicts with existing attributes:
51
172
 
52
- // Use shortcuts with defaults
53
- const card = withDefaults(div, { class: 'card' });
54
- const myCard = card('card-body', 'Card content');
173
+ ```ts
174
+ const button = btn(
175
+ {
176
+ click: () => alert('Clicked!'),
177
+ dblclick: '22',
178
+ '@dblclick': function trueHandler() {
179
+ /* ... */
180
+ },
181
+ },
182
+ 'Click me'
183
+ );
184
+
185
+ // This is equivalent to:
186
+ const button = btn(undefined, 'Click me');
187
+ button.setAttribute('dblclick', '22');
188
+ button.addEventListener('click', () => alert('Clicked!'));
189
+ button.addEventListener('dblclick', function trueHandler() {
190
+ /* ... */
191
+ });
192
+ ```
193
+
194
+ ### Working with CSS-in-JS Libraries
55
195
 
56
- document.body.appendChild(app);
196
+ KT.js works seamlessly with CSS-in-JS libraries like `@emotion/css`:
197
+
198
+ ```ts
199
+ import { css } from '@emotion/css';
200
+ import { h, div } from 'kt.js';
201
+
202
+ const className = css`
203
+ color: red;
204
+ font-size: 20px;
205
+ `;
206
+
207
+ // Pass class name as attribute
208
+ h('div', { class: className }, 'Styled text');
209
+
210
+ // Or as the first string argument
211
+ div(className, 'Styled text');
57
212
  ```
58
213
 
59
- ### Using with Router
214
+ ### Using Shortcuts with Default Values
60
215
 
61
- If you need routing, install `@ktjs/router` separately:
216
+ The `withDefaults` function allows you to create element factories with predefined properties:
62
217
 
63
- ```bash
64
- pnpm add @ktjs/router
218
+ ```ts
219
+ import { withDefaults, div, button } from 'kt.js';
220
+
221
+ // Create a styled div factory
222
+ const card = withDefaults(div, { class: 'card' });
223
+ const blueCard = withDefaults(card, { style: 'background: blue' });
224
+
225
+ // Use them
226
+ const myCard = card('card-body', 'Content'); // <div class="card"><div class="card-body">Content</div></div>
227
+ const myBlueCard = blueCard('title', 'Blue!'); // <div class="card" style="background: blue"><div class="title">Blue!</div></div>
65
228
  ```
66
229
 
67
- ```typescript
68
- import { div } from 'kt.js';
230
+ ## Router
231
+
232
+ The router is available as a separate package `@ktjs/router`:
233
+
234
+ ```ts
69
235
  import { createRouter } from '@ktjs/router';
236
+ import { div, h1 } from 'kt.js';
70
237
 
71
238
  const router = createRouter({
72
239
  routes: [
@@ -74,70 +241,98 @@ const router = createRouter({
74
241
  path: '/',
75
242
  name: 'home',
76
243
  beforeEnter: (to) => {
77
- const app = document.getElementById('app')!;
78
- app.innerHTML = '';
79
- app.appendChild(div({}, 'Home Page'));
244
+ // Render your page here
245
+ document.getElementById('app')!.innerHTML = '';
246
+ document.getElementById('app')!.appendChild(div({}, [h1({}, 'Home Page')]));
80
247
  },
81
248
  },
82
249
  {
83
- path: '/about',
84
- name: 'about',
250
+ path: '/user/:id',
251
+ name: 'user',
85
252
  beforeEnter: (to) => {
86
- const app = document.getElementById('app')!;
87
- app.innerHTML = '';
88
- app.appendChild(div({}, 'About Page'));
253
+ // Route-specific guard and rendering
254
+ console.log('Entering user page');
255
+ document.getElementById('app')!.innerHTML = '';
256
+ document.getElementById('app')!.appendChild(div({}, [h1({}, `User ${to.params.id}`)]));
257
+ return true;
89
258
  },
90
259
  },
91
260
  ],
261
+ beforeEach: async (to, from) => {
262
+ // Global navigation guard - return false to block navigation
263
+ console.log('Navigating to:', to.path);
264
+ return true;
265
+ },
266
+ afterEach: (to) => {
267
+ // Called after successful navigation
268
+ document.title = to.name || to.path;
269
+ },
270
+ onError: (error) => {
271
+ console.error('Router error:', error);
272
+ },
92
273
  });
93
274
 
94
- router.push('/');
95
- ```
96
-
97
- ## Why Use the Main Package?
98
-
99
- - **Convenience**: Single import for all KT.js functionality
100
- - **Simplicity**: No need to manage multiple package versions
101
- - **Complete**: Get all features out of the box
102
- - **Optimized**: Proper tree-shaking ensures you only bundle what you use
103
-
104
- ## When to Use Individual Packages
275
+ // Navigate programmatically
276
+ router.push('/user/123');
277
+ router.push('/user/456?page=2');
105
278
 
106
- If you only need specific functionality, you can install individual packages:
279
+ // Navigate by route name
280
+ router.push({ name: 'user', params: { id: '789' } });
107
281
 
108
- - Need only DOM utilities? → `pnpm add @ktjs/core`
109
- - Need only routing? → `pnpm add @ktjs/router`
110
- - Need only shortcuts? → `pnpm add @ktjs/shortcuts @ktjs/core`
111
- - Need everything except router? → `pnpm add kt.js` (this package)
112
- - Need everything including router? → `pnpm add kt.js @ktjs/router`
282
+ // Get current route
283
+ console.log(router.current?.path, router.current?.params, router.current?.query);
284
+ ```
113
285
 
114
- This can result in slightly smaller dependency trees in your `node_modules`.
286
+ ### Router Features
287
+
288
+ - **Hash-based Routing**: Uses URL hash for client-side navigation (`#/path`)
289
+ - **Dynamic Parameters**: Support for dynamic route segments (`/user/:id`)
290
+ - **Query Strings**: Automatic parsing of query parameters (`?key=value`)
291
+ - **Named Routes**: Navigate using route names instead of paths
292
+ - **Navigation Guards**:
293
+ - `beforeEach`: Global guard before navigation
294
+ - `beforeEnter`: Per-route guard (can also be used for rendering)
295
+ - `afterEach`: Global hook after navigation
296
+ - `after`: Per-route hook after navigation
297
+ - Async support with automatic sync fallback for non-Promise environments
298
+ - `GuardLevel` for fine-grained control over guard execution
299
+ - **Error Handling**: `onError` and `onNotFound` callbacks
300
+ - **Optimized Performance**: Pre-flattened routes and efficient matching algorithm
301
+ - **Zero Dependencies**: Fully self-contained router implementation (does not require `@ktjs/core` for runtime, only for TypeScript types)
302
+ - **Pure Routing**: No rendering logic - you control the DOM
303
+
304
+ ## `ktnull`
305
+
306
+ `ktnull`, assigned by `Object.create(null)`, is a falsy value.
307
+ It is used for filtering, you can do like this:
308
+
309
+ ```ts
310
+ import { div, ktnull } from 'kt.js';
311
+ const list = div('', [false ? div('', 'item 1') : ktnull, div('', 'Item 2'), undefined]);
312
+ ```
115
313
 
116
- ## Documentation
314
+ Then it will create:
117
315
 
118
- For complete documentation, examples, and guides, see:
316
+ ```html
317
+ <div>
318
+ <!-- there won't be <div>Item 1</div> -->
319
+ <div>Item 2</div>
320
+ undefined
321
+ </div>
322
+ ```
119
323
 
120
- - [Main Documentation](../../README.md) - Complete framework guide
121
- - [Core Package](../core/README.md) - Core DOM utilities
122
- - [Router Package](../router/README.md) - Routing documentation
123
- - [Shortcuts Package](../shortcuts/README.md) - Shortcuts and utilities
124
- - [Changelog](../../CHANGELOG.md) - Version history and updates
324
+ ## Browser Compatibility
125
325
 
126
- ## Features
326
+ KT.js is transpiled to ES5 and works in all modern browsers as well as legacy browsers including IE9+.
127
327
 
128
- - Direct DOM manipulation with zero virtual DOM overhead
129
- - ✅ Full TypeScript support with intelligent type inference
130
- - ✅ ES5 compatible (works in IE9+)
131
- - ✅ Zero dependencies (self-contained)
132
- - ✅ Tiny bundle size with excellent tree-shaking
133
- - ✅ Conditional rendering with `ktnull`
134
- - ✅ Event handler shortcuts with `@<eventName>` syntax
135
- - ✅ Element factories with `withDefaults`
136
- - ✅ Router available as separate package (`@ktjs/router`)
328
+ ### Promise Polyfill
137
329
 
138
- ## Browser Compatibility
330
+ For environments without native `Promise` support (like IE).
139
331
 
140
- KT.js works in all modern browsers and legacy browsers including IE9+. For older browsers without Promise support, navigation guards will run synchronously.
332
+ ```js
333
+ import 'some promise polyfill'; // Will fallback to sync version if Promise is not available
334
+ import { h, div, createRouter } from 'kt.js';
335
+ ```
141
336
 
142
337
  ## License
143
338
 
@@ -155,35 +155,22 @@ function applyAttr(element, attr) {
155
155
  }
156
156
  }
157
157
 
158
- const noop = () => ({});
159
- class Ref {
160
- value;
161
- update;
162
- constructor(value) {
163
- this.value = value;
164
- this.update = noop;
158
+ function apd(element, content) {
159
+ if (content && content.isKT) {
160
+ $append.call(element, content.value);
161
+ }
162
+ else {
163
+ $append.call(element, content);
165
164
  }
166
165
  }
167
-
168
166
  function applyContent(element, content) {
169
167
  if ($isArray(content)) {
170
168
  for (let i = 0; i < content.length; i++) {
171
- let c = content[i];
172
- if (c instanceof Ref) {
173
- $append.call(element, c.value);
174
- }
175
- else {
176
- $append.call(element, c);
177
- }
169
+ apd(element, content[i]);
178
170
  }
179
171
  }
180
172
  else {
181
- if (content instanceof Ref) {
182
- $append.call(element, content.value);
183
- }
184
- else {
185
- $append.call(element, content);
186
- }
173
+ apd(element, content);
187
174
  }
188
175
  }
189
176
 
@@ -197,14 +184,14 @@ function applyContent(element, content) {
197
184
  * ## About
198
185
  * @package @ktjs/core
199
186
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
200
- * @version 0.8.2 (Last Update: 2025.12.25 11:17:07.762)
187
+ * @version 0.8.5 (Last Update: 2025.12.29 10:16:21.619)
201
188
  * @license MIT
202
189
  * @link https://github.com/baendlorel/kt.js
203
190
  * @link https://baendlorel.github.io/ Welcome to my site!
204
191
  * @description Core functionality for kt.js - DOM manipulation utilities with JSX/TSX support
205
192
  * @copyright Copyright (c) 2025 Kasukabe Tsumugi. All rights reserved.
206
193
  */
207
- const h = (tag, attr = '', content = '') => {
194
+ const h = ((tag, attr = '', content = '') => {
208
195
  if (typeof tag !== 'string') {
209
196
  $throw('__func__ tagName must be a string.');
210
197
  }
@@ -214,7 +201,7 @@ const h = (tag, attr = '', content = '') => {
214
201
  applyAttr(element, attr);
215
202
  applyContent(element, content);
216
203
  return element;
217
- };
204
+ });
218
205
  $mark(h, 'h');
219
206
 
220
207
  /**
@@ -230,19 +217,13 @@ function jsx(tag, props, ..._metadata) {
230
217
  const children = propObj.children;
231
218
  delete propObj.children;
232
219
  // deal with ref attribute
233
- const ref = 'ref' in propObj && propObj.ref instanceof Ref ? propObj.ref : null;
220
+ const ref = propObj.ref?.isRef ? propObj.ref : null;
234
221
  if (ref) {
235
222
  delete propObj.ref;
236
223
  }
237
224
  const el = h(tag, propObj, children);
238
225
  if (ref) {
239
226
  ref.value = el;
240
- ref.update = () => {
241
- const old = ref.value;
242
- ref.value = h(tag, propObj, children);
243
- old.replaceWith(ref.value);
244
- return ref.value;
245
- };
246
227
  }
247
228
  return el;
248
229
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kt.js",
3
- "version": "0.8.2",
3
+ "version": "0.8.5",
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.8.2",
44
+ "@ktjs/core": "0.8.5",
45
45
  "@ktjs/shortcuts": "0.7.3"
46
46
  },
47
47
  "scripts": {