@ktjs/core 0.5.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 kasukabe tsumugi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,149 @@
1
+ # @ktjs/core
2
+
3
+ <img src="https://raw.githubusercontent.com/baendlorel/kt.js/dev/.assets/ktjs-0.0.1.svg" alt="KT.js Logo" width="150"/>
4
+
5
+ > 📦 Part of [KT.js](https://raw.githubusercontent.com/baendlorel/kt.js/dev/README.md) - A simple and easy-to-use web framework that never re-renders.
6
+
7
+ Core DOM manipulation utilities for KT.js framework.
8
+
9
+ ## Overview
10
+
11
+ `@ktjs/core` is the foundation of KT.js, providing the essential `h` function and DOM utilities for building web applications with direct DOM manipulation. It emphasizes performance, type safety, and minimal abstraction over native DOM APIs.
12
+
13
+ ## Features
14
+
15
+ - **`h` Function**: Create HTMLElements with a simple, flexible API
16
+ - Support for attributes, content, and event handlers
17
+ - Special `@<eventName>` syntax for event handlers
18
+ - Function attributes automatically treated as event listeners
19
+ - Full TypeScript support with intelligent type inference
20
+ - **DOM Utilities**: Helper functions for common DOM operations
21
+ - Native method caching for performance
22
+ - Symbol-based private properties for internal state
23
+ - **Type-Safe**: Complete TypeScript definitions
24
+ - Accurate HTMLElement type inference
25
+ - Event handler type hints with proper event types
26
+ - 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
+ - **ES5 Compatible**: Transpiled to ES5 for maximum browser compatibility
32
+ - **Zero Dependencies**: Fully self-contained implementation
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ pnpm add @ktjs/core
38
+ ```
39
+
40
+ ## Usage
41
+
42
+ ### Basic Element Creation
43
+
44
+ ```typescript
45
+ import { h } from '@ktjs/core';
46
+
47
+ // Simple element
48
+ const div = h('div', { class: 'container' }, 'Hello World');
49
+
50
+ // With multiple attributes
51
+ const input = h('input', {
52
+ type: 'text',
53
+ placeholder: 'Enter text',
54
+ value: 'initial',
55
+ });
56
+
57
+ // Nested elements
58
+ const card = h('div', { class: 'card' }, [
59
+ h('h2', {}, 'Title'),
60
+ h('p', {}, 'Description'),
61
+ h('button', {}, 'Click me'),
62
+ ]);
63
+ ```
64
+
65
+ ### Event Handlers
66
+
67
+ ```typescript
68
+ import { h } from '@ktjs/core';
69
+
70
+ // Function attribute (treated as event listener)
71
+ const button1 = h(
72
+ 'button',
73
+ {
74
+ click: () => alert('Clicked!'),
75
+ },
76
+ 'Button 1'
77
+ );
78
+
79
+ // @-prefixed attribute (explicitly an event handler)
80
+ const button2 = h(
81
+ 'button',
82
+ {
83
+ '@click': (e) => console.log('Event:', e),
84
+ 'data-id': '123', // Regular attribute
85
+ },
86
+ 'Button 2'
87
+ );
88
+
89
+ // Both regular and event handler for same name
90
+ const input = h('input', {
91
+ change: 'change-value', // Regular attribute
92
+ '@change': (e) => console.log('Changed'), // Event listener
93
+ });
94
+ ```
95
+
96
+ ### Using ktnull for Conditional Rendering
97
+
98
+ ```typescript
99
+ import { h, ktnull } from '@ktjs/core';
100
+
101
+ const items = [1, 2, 3, 4, 5];
102
+
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
+ )
109
+ );
110
+ // Results in: <ul><li>Even: 2</li><li>Even: 4</li></ul>
111
+ ```
112
+
113
+ ## API Reference
114
+
115
+ ### `h(tag, attributes?, content?)`
116
+
117
+ Creates an HTMLElement with the specified tag, attributes, and content.
118
+
119
+ **Parameters:**
120
+
121
+ - `tag` (string): HTML tag name (e.g., 'div', 'span', 'button')
122
+ - `attributes` (object, optional): Element attributes and event handlers
123
+ - `content` (string | HTMLElement | Array, optional): Element content
124
+
125
+ **Returns:** HTMLElement
126
+
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
+ ## Type System
132
+
133
+ The package includes comprehensive TypeScript definitions:
134
+
135
+ - `HTMLTag`: Union type of all valid HTML tag names
136
+ - `KAttribute`: Attribute object type with string or function values
137
+ - `KContent`: Valid content types (string, Element, Array, etc.)
138
+ - Event handler types with proper event object types
139
+
140
+ ## Performance Considerations
141
+
142
+ - Native DOM methods are cached for repeated use
143
+ - Symbol-based properties avoid prototype pollution
144
+ - Minimal object creation in hot paths
145
+ - Tree-shakeable - only import what you use
146
+
147
+ ## License
148
+
149
+ MIT
@@ -0,0 +1,125 @@
1
+ interface KTRuntime {
2
+ throws: (message: string) => never;
3
+ defines: <T>(o: T, properties: PropertyDescriptorMap & ThisType<any>) => T;
4
+ mark: (func: (...args: any[]) => any, tag: string) => void;
5
+ }
6
+ declare global {
7
+ interface Window {
8
+ readonly __ktjs__: KTRuntime;
9
+ }
10
+ }
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
+ type otherstring = string & {};
19
+
20
+ /**
21
+ * Normal HTML tags like `div`, `span`, `a`, etc.
22
+ */
23
+ // & 这里也要允许其他字符串
24
+ type HTMLTag = keyof HTMLElementTagNameMap;
25
+
26
+ type KTRawContent = (HTMLElement | string | undefined)[] | HTMLElement | string;
27
+ type KTRawAttr = KTAttribute | string;
28
+
29
+ /**
30
+ * Event handler type for DOM events
31
+ */
32
+ type EventHandler<T extends Event = Event> = (this: HTMLElement, ev: T) => any;
33
+
34
+ /**
35
+ * Used to create enhanced HTML elements
36
+ */
37
+ interface KTBaseAttribute {
38
+ [k: string]: any;
39
+
40
+ id?: string;
41
+ class?: string;
42
+ style?: string | Partial<CSSStyleDeclaration>;
43
+
44
+ type?:
45
+ | 'text'
46
+ | 'password'
47
+ | 'email'
48
+ | 'number'
49
+ | 'tel'
50
+ | 'url'
51
+ | 'search'
52
+ | 'date'
53
+ | 'datetime-local'
54
+ | 'time'
55
+ | 'month'
56
+ | 'week'
57
+ | 'color'
58
+ | 'range'
59
+ | 'file'
60
+ | 'checkbox'
61
+ | 'radio'
62
+ | 'hidden'
63
+ | 'submit'
64
+ | 'reset'
65
+ | 'button'
66
+ | 'image'
67
+ | otherstring;
68
+ for?: string;
69
+
70
+ name?: string;
71
+ value?: string;
72
+ valueAsDate?: Date;
73
+ valueAsNumber?: number;
74
+ label?: string;
75
+ disabled?: string;
76
+
77
+ min?: string | number;
78
+ max?: string | number;
79
+ step?: string | number;
80
+
81
+ selected?: boolean;
82
+ checked?: boolean;
83
+
84
+ action?: string;
85
+ method?: 'POST' | 'GET' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS' | 'CONNECT' | 'TRACE' | otherstring;
86
+ }
87
+
88
+ type KTEventHandlersOrAttribute = {
89
+ [EventName in keyof HTMLElementEventMap]?: ((ev: HTMLElementEventMap[EventName]) => void) | string;
90
+ };
91
+
92
+ /**
93
+ * Event handlers with @ prefix (e.g., @click, @input)
94
+ * When key starts with @, it's always registered as an event handler
95
+ */
96
+ type KTPrefixedEventHandlers = {
97
+ [EventName in keyof HTMLElementEventMap as `@${EventName}`]?: (ev: HTMLElementEventMap[EventName]) => void;
98
+ };
99
+
100
+ type KTAttribute = KTBaseAttribute & KTEventHandlersOrAttribute & KTPrefixedEventHandlers;
101
+
102
+ type HTML<T extends HTMLTag & otherstring> = T extends HTMLTag ? HTMLElementTagNameMap[T] : HTMLElement;
103
+ /**
104
+ * Create an enhanced HTMLElement.
105
+ * - Only supports HTMLElements, **NOT** SVGElements or other Elements.
106
+ * @param tag tag of an `HTMLElement`
107
+ * @param attr attribute object or className
108
+ * @param content a string or an array of HTMLEnhancedElement as child nodes
109
+ *
110
+ * ## About
111
+ * @package @ktjs/core
112
+ * @author Kasukabe Tsumugi <futami16237@gmail.com>
113
+ * @version 0.5.0 (Last Update: 2025.11.22 16:11:52.431)
114
+ * @license MIT
115
+ * @link https://github.com/baendlorel/kt.js
116
+ * @link https://baendlorel.github.io/ Welcome to my site!
117
+ * @description Core functionality for kt.js - DOM manipulation utilities
118
+ * @copyright Copyright (c) 2025 Kasukabe Tsumugi. All rights reserved.
119
+ */
120
+ declare const h: <T extends HTMLTag>(tag: T, attr?: KTRawAttr, content?: KTRawContent) => HTML<T>;
121
+
122
+ declare function notSupportTextNode(tag: HTMLTag): boolean;
123
+
124
+ export { h, ktnull, notSupportTextNode };
125
+ export type { EventHandler, KTAttribute, KTRawAttr, KTRawContent, KTRuntime };
@@ -0,0 +1 @@
1
+ var __ktjs_core__=function(e){"use strict";const t=e=>{throw new Error("kt.js: ".concat(e))},n=Array.isArray,o=Object.keys,r=Object.defineProperties,s=(e,t)=>r(e,{t:{value:t}}),u=()=>({});"undefined"==typeof Promise&&(window.Promise={resolve:u,reject:u}),(()=>{const e=Object.create(null);r(e,{throws:{value:t,enumerable:!0},defines:{value:r,enumerable:!0},mark:{value:s,enumerable:!0}}),r(window,{o:{value:e,enumerable:!0}})})();const c=Object.create(null),i=HTMLElement.prototype.appendChild,a=HTMLElement.prototype.append,l="function"==typeof a?function(...e){const t=e.filter(e=>e!==c);return a.apply(this,t)}:function(...e){if(e.length<50)for(let t=0;t<e.length;t++){const n=e[t];"string"==typeof n?i.call(this,document.createTextNode(n)):n!==c&&i.call(this,n)}else{const t=document.createDocumentFragment();for(let n=0;n<e.length;n++){const o=e[n];"string"==typeof o?i.call(t,document.createTextNode(o)):o!==c&&i.call(t,o)}i.call(this,t)}};function f(e,t,n){t in e?e[t]=!!n:e.setAttribute(t,n)}function d(e,t,n){t in e?e[t]=n:e.setAttribute(t,n)}const m={checked:f,selected:f,value:d,valueAsDate:d,valueAsNumber:d,defaultValue:d,defaultChecked:f,defaultSelected:f,disabled:f,readOnly:f,multiple:f,required:f,autofocus:f,open:f,controls:f,autoplay:f,loop:f,muted:f,defer:f,async:f,hidden:function(e,t,n){e.hidden=!!n}},p=function(e,t,n){return e.setAttribute(t,n)};function _(e,n){"string"==typeof n?e.className=n:"object"==typeof n&&null!==n?function(e,t){const n=t.class,r=t.style;if(void 0!==n&&(e.className=n,delete t.class),r){if("string"==typeof r)e.setAttribute("style",r);else if("object"==typeof r)for(const t in r)e.style[t]=r[t];delete t.style}const s=o(t);for(let n=s.length-1;n>=0;n--){const o=s[n],r=t[o];o.startsWith("@")?e.addEventListener(o.slice(1),r):"function"!=typeof r?(m[o]||p)(e,o,r):e.addEventListener(o,r)}void 0!==n&&(t.class=n),void 0!==r&&(t.style=r)}(e,n):t("__func__ attr must be an object.")}const b=(e,o="",r="")=>{"string"!=typeof e&&t("__func__ tagName must be a string.");const s=document.createElement(e);return _(s,o),function(e,t){n(t)?l.apply(e,t):l.call(e,t)}(s,r),s};s(b,"h");const y={area:!0,audio:!0,base:!0,basefont:!0,br:!0,canvas:!0,datalist:!0,details:!0,dialog:!0,frameset:!0,head:!0,iframe:!0,img:!0,input:!0,link:!0,meta:!0,meter:!0,noembed:!0,noframes:!0,noscript:!0,optgroup:!0,param:!0,progress:!0,rp:!0,select:!0,style:!0,template:!0,textarea:!0,title:!0,video:!0,wbr:!0,embed:!0,frame:!0,keygen:!0,option:!0};return e.h=b,e.ktnull=c,e.notSupportTextNode=function(e){return y[e]},e}({});
@@ -0,0 +1 @@
1
+ var __ktjs_core__=function(e){"use strict";var t,n=function(e){throw new Error("kt.js: ".concat(e))},r=Array.isArray,o=Object.keys,a=Object.defineProperties,u=function(e,t){return a(e,{t:{value:t}})},i=function(){return{}};"undefined"==typeof Promise&&(window.Promise={resolve:i,reject:i}),t=Object.create(null),a(t,{throws:{value:n,enumerable:!0},defines:{value:a,enumerable:!0},mark:{value:u,enumerable:!0}}),a(window,{o:{value:t,enumerable:!0}});var f=Object.create(null),l=HTMLElement.prototype.appendChild,c=HTMLElement.prototype.append,s="function"==typeof c?function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];var n=e.filter(function(e){return e!==f});return c.apply(this,n)}:function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];if(e.length<50)for(var n=0;n<e.length;n++){"string"==typeof(o=e[n])?l.call(this,document.createTextNode(o)):o!==f&&l.call(this,o)}else{var r=document.createDocumentFragment();for(n=0;n<e.length;n++){var o;"string"==typeof(o=e[n])?l.call(r,document.createTextNode(o)):o!==f&&l.call(r,o)}l.call(this,r)}};function d(e,t,n){t in e?e[t]=!!n:e.setAttribute(t,n)}function v(e,t,n){t in e?e[t]=n:e.setAttribute(t,n)}var m={checked:d,selected:d,value:v,valueAsDate:v,valueAsNumber:v,defaultValue:v,defaultChecked:d,defaultSelected:d,disabled:d,readOnly:d,multiple:d,required:d,autofocus:d,open:d,controls:d,autoplay:d,loop:d,muted:d,defer:d,async:d,hidden:function(e,t,n){e.hidden=!!n}},p=function(e,t,n){return e.setAttribute(t,n)};function _(e,t){"string"==typeof t?e.className=t:"object"==typeof t&&null!==t?function(e,t){var n=t.class,r=t.style;if(void 0!==n&&(e.className=n,delete t.class),r){if("string"==typeof r)e.setAttribute("style",r);else if("object"==typeof r)for(var a in r)e.style[a]=r[a];delete t.style}for(var u=o(t),i=u.length-1;i>=0;i--){var f=t[a=u[i]];a.startsWith("@")?e.addEventListener(a.slice(1),f):"function"!=typeof f?(m[a]||p)(e,a,f):e.addEventListener(a,f)}void 0!==n&&(t.class=n),void 0!==r&&(t.style=r)}(e,t):n("__func__ attr must be an object.")}var b=function(e,t,o){void 0===t&&(t=""),void 0===o&&(o=""),"string"!=typeof e&&n("__func__ tagName must be a string.");var a=document.createElement(e);return _(a,t),function(e,t){r(t)?s.apply(e,t):s.call(e,t)}(a,o),a};u(b,"h");var y={area:!0,audio:!0,base:!0,basefont:!0,br:!0,canvas:!0,datalist:!0,details:!0,dialog:!0,frameset:!0,head:!0,iframe:!0,img:!0,input:!0,link:!0,meta:!0,meter:!0,noembed:!0,noframes:!0,noscript:!0,optgroup:!0,param:!0,progress:!0,rp:!0,select:!0,style:!0,template:!0,textarea:!0,title:!0,video:!0,wbr:!0,embed:!0,frame:!0,keygen:!0,option:!0};return e.h=b,e.ktnull=f,e.notSupportTextNode=function(e){return y[e]},e}({});
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ const e=e=>{throw new Error("kt.js: ".concat(e))},t=Array.isArray,n=Object.keys,o=Object.defineProperties,r=(e,t)=>o(e,{t:{value:t}}),s=()=>({});"undefined"==typeof Promise&&(window.Promise={resolve:s,reject:s}),(()=>{const t=Object.create(null);o(t,{throws:{value:e,enumerable:!0},defines:{value:o,enumerable:!0},mark:{value:r,enumerable:!0}}),o(window,{o:{value:t,enumerable:!0}})})();const u=Object.create(null),i=HTMLElement.prototype.appendChild,a=HTMLElement.prototype.append,c="function"==typeof a?function(...e){const t=e.filter(e=>e!==u);return a.apply(this,t)}:function(...e){if(e.length<50)for(let t=0;t<e.length;t++){const n=e[t];"string"==typeof n?i.call(this,document.createTextNode(n)):n!==u&&i.call(this,n)}else{const t=document.createDocumentFragment();for(let n=0;n<e.length;n++){const o=e[n];"string"==typeof o?i.call(t,document.createTextNode(o)):o!==u&&i.call(t,o)}i.call(this,t)}};function l(e,t,n){t in e?e[t]=!!n:e.setAttribute(t,n)}function f(e,t,n){t in e?e[t]=n:e.setAttribute(t,n)}const d={checked:l,selected:l,value:f,valueAsDate:f,valueAsNumber:f,defaultValue:f,defaultChecked:l,defaultSelected:l,disabled:l,readOnly:l,multiple:l,required:l,autofocus:l,open:l,controls:l,autoplay:l,loop:l,muted:l,defer:l,async:l,hidden:function(e,t,n){e.hidden=!!n}},m=function(e,t,n){return e.setAttribute(t,n)};function p(t,o){"string"==typeof o?t.className=o:"object"==typeof o&&null!==o?function(e,t){const o=t.class,r=t.style;if(void 0!==o&&(e.className=o,delete t.class),r){if("string"==typeof r)e.setAttribute("style",r);else if("object"==typeof r)for(const t in r)e.style[t]=r[t];delete t.style}const s=n(t);for(let n=s.length-1;n>=0;n--){const o=s[n],r=t[o];o.startsWith("@")?e.addEventListener(o.slice(1),r):"function"!=typeof r?(d[o]||m)(e,o,r):e.addEventListener(o,r)}void 0!==o&&(t.class=o),void 0!==r&&(t.style=r)}(t,o):e("__func__ attr must be an object.")}const b=(n,o="",r="")=>{"string"!=typeof n&&e("__func__ tagName must be a string.");const s=document.createElement(n);return p(s,o),function(e,n){t(n)?c.apply(e,n):c.call(e,n)}(s,r),s};r(b,"h");const y={area:!0,audio:!0,base:!0,basefont:!0,br:!0,canvas:!0,datalist:!0,details:!0,dialog:!0,frameset:!0,head:!0,iframe:!0,img:!0,input:!0,link:!0,meta:!0,meter:!0,noembed:!0,noframes:!0,noscript:!0,optgroup:!0,param:!0,progress:!0,rp:!0,select:!0,style:!0,template:!0,textarea:!0,title:!0,video:!0,wbr:!0,embed:!0,frame:!0,keygen:!0,option:!0};function _(e){return y[e]}export{b as h,u as ktnull,_ as notSupportTextNode};
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@ktjs/core",
3
+ "version": "0.5.0",
4
+ "description": "Core functionality for kt.js - DOM manipulation utilities",
5
+ "type": "module",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.mjs",
11
+ "default": "./dist/index.mjs"
12
+ },
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "keywords": [
17
+ "dom",
18
+ "dom-manipulation",
19
+ "framework",
20
+ "web"
21
+ ],
22
+ "license": "MIT",
23
+ "author": {
24
+ "name": "Kasukabe Tsumugi",
25
+ "email": "futami16237@gmail.com"
26
+ },
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/baendlorel/kt.js",
30
+ "directory": "packages/core"
31
+ },
32
+ "scripts": {
33
+ "build": "rollup -c rollup.config.mjs",
34
+ "dev": "rollup -c rollup.config.mjs -w"
35
+ }
36
+ }