@mizchi/luna 0.1.4

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.
@@ -0,0 +1,2 @@
1
+ // JSX Dev Runtime types - re-export from jsx-runtime
2
+ export { jsx, jsxs, jsxDEV, Fragment, JSX } from "./jsx-runtime.js";
@@ -0,0 +1,2 @@
1
+ // JSX Dev Runtime - re-export from jsx-runtime
2
+ export { jsx, jsxs, jsxDEV, Fragment } from "./jsx-runtime.js";
@@ -0,0 +1,123 @@
1
+ /**
2
+ * JSX Runtime types for @mizchi/ui
3
+ */
4
+
5
+ import type { Node, AttrValue } from "./dom";
6
+
7
+ export namespace JSX {
8
+ type Element = Node;
9
+
10
+ interface IntrinsicElements {
11
+ // Block elements
12
+ div: HTMLAttributes;
13
+ p: HTMLAttributes;
14
+ form: HTMLAttributes & FormAttributes;
15
+
16
+ // Heading elements
17
+ h1: HTMLAttributes;
18
+ h2: HTMLAttributes;
19
+ h3: HTMLAttributes;
20
+
21
+ // List elements
22
+ ul: HTMLAttributes;
23
+ ol: HTMLAttributes;
24
+ li: HTMLAttributes;
25
+
26
+ // Inline elements
27
+ span: HTMLAttributes;
28
+ a: HTMLAttributes & AnchorAttributes;
29
+ button: HTMLAttributes & ButtonAttributes;
30
+ label: HTMLAttributes & LabelAttributes;
31
+
32
+ // Form elements
33
+ input: HTMLAttributes & InputAttributes;
34
+ textarea: HTMLAttributes & TextareaAttributes;
35
+
36
+ // Media elements
37
+ img: HTMLAttributes & ImageAttributes;
38
+
39
+ // Other elements
40
+ br: {};
41
+ hr: HTMLAttributes;
42
+ }
43
+
44
+ interface HTMLAttributes {
45
+ // Core attributes
46
+ id?: string;
47
+ className?: string | (() => string);
48
+ class?: string | (() => string);
49
+ style?: Record<string, string> | (() => [string, string][]);
50
+
51
+ // Event handlers
52
+ onClick?: (event: MouseEvent) => void;
53
+ onInput?: (event: InputEvent) => void;
54
+ onChange?: (event: Event) => void;
55
+ onSubmit?: (event: Event) => void;
56
+ onKeyDown?: (event: KeyboardEvent) => void;
57
+ onKeyUp?: (event: KeyboardEvent) => void;
58
+ onFocus?: (event: FocusEvent) => void;
59
+ onBlur?: (event: FocusEvent) => void;
60
+ onMouseEnter?: (event: MouseEvent) => void;
61
+ onMouseLeave?: (event: MouseEvent) => void;
62
+
63
+ // Children
64
+ children?: Node | Node[] | string | number | (Node | string | number)[];
65
+
66
+ // Allow any other attributes
67
+ [key: string]: unknown;
68
+ }
69
+
70
+ interface InputAttributes {
71
+ type?: string;
72
+ placeholder?: string;
73
+ value?: string | (() => string);
74
+ disabled?: boolean | (() => boolean);
75
+ }
76
+
77
+ interface TextareaAttributes {
78
+ placeholder?: string;
79
+ value?: string | (() => string);
80
+ disabled?: boolean | (() => boolean);
81
+ }
82
+
83
+ interface AnchorAttributes {
84
+ href?: string;
85
+ }
86
+
87
+ interface ImageAttributes {
88
+ src?: string;
89
+ alt?: string;
90
+ }
91
+
92
+ interface ButtonAttributes {
93
+ type?: string;
94
+ disabled?: boolean | (() => boolean);
95
+ }
96
+
97
+ interface FormAttributes {
98
+ action?: string;
99
+ method?: string;
100
+ }
101
+
102
+ interface LabelAttributes {
103
+ htmlFor?: string;
104
+ }
105
+
106
+ interface ElementChildrenAttribute {
107
+ children: {};
108
+ }
109
+ }
110
+
111
+ export function jsx(
112
+ type: string | ((props: any) => Node),
113
+ props: Record<string, unknown> | null
114
+ ): Node;
115
+
116
+ export function jsxs(
117
+ type: string | ((props: any) => Node),
118
+ props: Record<string, unknown> | null
119
+ ): Node;
120
+
121
+ export function Fragment(props: { children?: Node | Node[] }): Node[];
122
+
123
+ export const jsxDEV: typeof jsx;
package/jsx-runtime.js ADDED
@@ -0,0 +1,119 @@
1
+ // JSX Runtime for @mizchi/ui
2
+ // Usage: Configure tsconfig.json with:
3
+ // "jsx": "react-jsx",
4
+ // "jsxImportSource": "@mizchi/ui"
5
+
6
+ import { text, textDyn, createElement } from "./dom.js";
7
+
8
+ // Convert style object to CSS string
9
+ function styleToString(style) {
10
+ if (typeof style === "string") return style;
11
+ if (typeof style !== "object" || style === null) return "";
12
+ return Object.entries(style)
13
+ .map(([key, value]) => {
14
+ // Convert camelCase to kebab-case
15
+ const cssKey = key.replace(/([A-Z])/g, "-$1").toLowerCase();
16
+ return `${cssKey}: ${value}`;
17
+ })
18
+ .join("; ");
19
+ }
20
+
21
+ // Convert JSX props to createElement attrs format
22
+ function convertProps(props) {
23
+ if (!props) return [];
24
+ const attrs = [];
25
+ for (const [key, value] of Object.entries(props)) {
26
+ if (key === "children") continue;
27
+
28
+ // Map JSX prop names to DOM attribute format
29
+ let attrName = key;
30
+ let attrValue;
31
+
32
+ // Handle className -> class
33
+ if (key === "className") {
34
+ attrName = "class";
35
+ }
36
+
37
+ // Handle style object -> CSS string
38
+ if (key === "style") {
39
+ const cssString = styleToString(value);
40
+ attrValue = { $tag: 0, _0: cssString }; // AttrValue.Static
41
+ attrs.push({ _0: attrName, _1: attrValue });
42
+ continue;
43
+ }
44
+
45
+ // Handle event handlers (onClick -> click for addEventListener)
46
+ if (key.startsWith("on") && typeof value === "function") {
47
+ // Remove "on" prefix and lowercase first char: onClick -> click
48
+ attrName = key.slice(2).toLowerCase();
49
+ attrValue = { $tag: 2, _0: value }; // AttrValue.Handler
50
+ attrs.push({ _0: attrName, _1: attrValue });
51
+ continue;
52
+ }
53
+
54
+ // Handle dynamic values (functions)
55
+ if (typeof value === "function") {
56
+ attrValue = { $tag: 1, _0: value }; // AttrValue.Dynamic
57
+ } else {
58
+ attrValue = { $tag: 0, _0: String(value) }; // AttrValue.Static
59
+ }
60
+
61
+ attrs.push({ _0: attrName, _1: attrValue });
62
+ }
63
+ return attrs;
64
+ }
65
+
66
+ function convertChildren(children) {
67
+ if (!children) return [];
68
+ if (!Array.isArray(children)) {
69
+ children = [children];
70
+ }
71
+ return children.flat().map((child) => {
72
+ if (typeof child === "string") {
73
+ return text(child);
74
+ }
75
+ if (typeof child === "number") {
76
+ return text(String(child));
77
+ }
78
+ // Handle functions:
79
+ // - No args (length === 0): signal accessor -> textDyn
80
+ // - With args (length > 0): render function -> pass through
81
+ if (typeof child === "function") {
82
+ if (child.length === 0) {
83
+ return textDyn(() => String(child()));
84
+ }
85
+ // Render function, pass through as-is
86
+ return child;
87
+ }
88
+ return child;
89
+ }).filter(Boolean);
90
+ }
91
+
92
+ // JSX factory function
93
+ export function jsx(type, props) {
94
+ const { children, ...rest } = props || {};
95
+ const attrs = convertProps(rest);
96
+ const childNodes = convertChildren(children);
97
+
98
+ if (typeof type === "string") {
99
+ return createElement(type, attrs, childNodes);
100
+ }
101
+
102
+ // Function component
103
+ if (typeof type === "function") {
104
+ return type({ ...rest, children });
105
+ }
106
+
107
+ throw new Error(`Invalid JSX type: ${type}`);
108
+ }
109
+
110
+ // jsxs is the same as jsx for our implementation
111
+ export const jsxs = jsx;
112
+
113
+ // Fragment just returns children as-is (flattened)
114
+ export function Fragment({ children }) {
115
+ return convertChildren(children);
116
+ }
117
+
118
+ // Export jsxDEV for development mode
119
+ export const jsxDEV = jsx;
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@mizchi/luna",
3
+ "version": "0.1.4",
4
+ "description": "Fine-grained reactive UI library for Moonbit/JS",
5
+ "type": "module",
6
+ "main": "./index.js",
7
+ "types": "./index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./index.d.ts",
11
+ "import": "./index.js"
12
+ },
13
+ "./jsx-runtime": {
14
+ "types": "./jsx-runtime.d.ts",
15
+ "import": "./jsx-runtime.js"
16
+ },
17
+ "./jsx-dev-runtime": {
18
+ "types": "./jsx-runtime.d.ts",
19
+ "import": "./jsx-runtime.js"
20
+ }
21
+ },
22
+ "scripts": {
23
+ "test": "vitest run"
24
+ },
25
+ "devDependencies": {
26
+ "global-jsdom": "^27.0.0",
27
+ "jsdom": "^27.3.0"
28
+ },
29
+ "repository": {
30
+ "directory": "js/luna",
31
+ "url": "https://github.com/mizchi/luna.mbt"
32
+ },
33
+ "files": [
34
+ "*.js",
35
+ "*.d.ts"
36
+ ]
37
+ }