ziex 0.0.1-dev.7 → 0.1.0-dev.460
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 +86 -41
- package/index.js +18 -6
- package/package.json +4 -4
- package/react/dom.d.ts +1 -1
- package/react/types.d.ts +17 -17
- package/wasm/index.d.ts +17 -1
- package/wasm/index.js +79 -14
- package/zx.d.ts +1 -0
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# ZX
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A full-stack web framework for Zig. Write declarative UI components using familiar JSX patterns, transpiled to efficient Zig code.
|
|
4
4
|
|
|
5
|
-
ZX combines the power and performance of Zig with the expressiveness of JSX, enabling you to build fast, type-safe web applications.
|
|
5
|
+
ZX combines the power and performance of Zig with the expressiveness of JSX, enabling you to build fast, type-safe web applications.
|
|
6
6
|
|
|
7
|
-
**[
|
|
7
|
+
**[Documentation →](https://ziex.dev/learn)**
|
|
8
8
|
|
|
9
9
|
## Installation
|
|
10
10
|
|
|
@@ -31,7 +31,7 @@ winget install -e --id zig.zig # Windows
|
|
|
31
31
|
pub fn QuickExample(allocator: zx.Allocator) zx.Component {
|
|
32
32
|
const is_loading = true;
|
|
33
33
|
const chars = "Hello, ZX Dev!";
|
|
34
|
-
|
|
34
|
+
var i: usize = 0;
|
|
35
35
|
return (
|
|
36
36
|
<main @allocator={allocator}>
|
|
37
37
|
<section>
|
|
@@ -39,7 +39,7 @@ pub fn QuickExample(allocator: zx.Allocator) zx.Component {
|
|
|
39
39
|
</section>
|
|
40
40
|
|
|
41
41
|
<section>
|
|
42
|
-
{for (chars) |char| (<span>{
|
|
42
|
+
{for (chars) |char| (<span>{char}</span>)}
|
|
43
43
|
</section>
|
|
44
44
|
|
|
45
45
|
<section>
|
|
@@ -47,6 +47,10 @@ pub fn QuickExample(allocator: zx.Allocator) zx.Component {
|
|
|
47
47
|
<Profile name={user.name} age={user.age} role={user.role} />
|
|
48
48
|
)}
|
|
49
49
|
</section>
|
|
50
|
+
|
|
51
|
+
<section>
|
|
52
|
+
{while (i < 10) : (i += 1) (<p>{i}</p>)}
|
|
53
|
+
</section>
|
|
50
54
|
</main>
|
|
51
55
|
);
|
|
52
56
|
}
|
|
@@ -55,7 +59,7 @@ fn Profile(allocator: zx.Allocator, user: User) zx.Component {
|
|
|
55
59
|
return (
|
|
56
60
|
<div @allocator={allocator}>
|
|
57
61
|
<h1>{user.name}</h1>
|
|
58
|
-
<p>{
|
|
62
|
+
<p>{user.age}</p>
|
|
59
63
|
{switch (user.role) {
|
|
60
64
|
.admin => (<p>Admin</p>),
|
|
61
65
|
.member => (<p>Member</p>),
|
|
@@ -77,10 +81,18 @@ const zx = @import("zx");
|
|
|
77
81
|
## Feature Checklist
|
|
78
82
|
|
|
79
83
|
- [x] Server Side Rendering (SSR)
|
|
84
|
+
- [ ] `on`event handler
|
|
85
|
+
- [x] Streaming
|
|
80
86
|
- [x] Static Site Generation (SSG)
|
|
87
|
+
- [ ] `getStaticParams`, `getStaticProps`
|
|
81
88
|
- [ ] Client Side Rendering (CSR) via WebAssembly (_WIP_)
|
|
89
|
+
- [x] Virtual DOM and diffing
|
|
90
|
+
- [x] Rendering only changed nodes
|
|
91
|
+
- [x] `on`event handler
|
|
92
|
+
- [ ] State managment
|
|
93
|
+
- [ ] Hydration
|
|
94
|
+
- [ ] Lifecycle hook
|
|
82
95
|
- [x] Client Side Rendering (CSR) via React
|
|
83
|
-
- [x] Type Safety
|
|
84
96
|
- [x] Routing
|
|
85
97
|
- [x] File-system Routing
|
|
86
98
|
- [x] Search Parameters
|
|
@@ -88,65 +100,98 @@ const zx = @import("zx");
|
|
|
88
100
|
- [x] Components
|
|
89
101
|
- [x] Control Flow
|
|
90
102
|
- [x] `if`
|
|
91
|
-
- [ ] `if` nested
|
|
92
103
|
- [x] `if/else`
|
|
93
|
-
- [x] `if/else` nested
|
|
94
104
|
- [x] `for`
|
|
95
|
-
- [x] `for` nested
|
|
96
105
|
- [x] `switch`
|
|
97
|
-
- [x] `switch` nested
|
|
98
106
|
- [x] `while`
|
|
99
|
-
- [x]
|
|
107
|
+
- [x] nesting control flows
|
|
108
|
+
- [x] error/optional captures in `while` and `if`
|
|
100
109
|
- [x] Assets
|
|
101
110
|
- [x] Copying
|
|
102
111
|
- [x] Serving
|
|
103
112
|
- [ ] Assets Optimization
|
|
104
113
|
- [ ] Image
|
|
105
|
-
- [
|
|
106
|
-
- [
|
|
107
|
-
- [
|
|
108
|
-
- [ ] Middleware
|
|
109
|
-
- [ ]
|
|
110
|
-
- [ ]
|
|
114
|
+
- [x] CSS (via plugins such as Tailwind)
|
|
115
|
+
- [x] JS/TS (via esbuild)
|
|
116
|
+
- [x] HTML (optimized by default)
|
|
117
|
+
- [ ] Middleware (_cancalled_)
|
|
118
|
+
- [ ] Caching (configurable)
|
|
119
|
+
- [ ] Component
|
|
120
|
+
- [ ] Layout
|
|
121
|
+
- [x] Page
|
|
122
|
+
- [ ] Assets
|
|
123
|
+
- [ ] API Route
|
|
124
|
+
- [ ] Plugin (_Alpha_)
|
|
125
|
+
- [x] Builtin TailwindCSS and Esbuild
|
|
126
|
+
- [x] Command based plugin system
|
|
127
|
+
- [ ] Source based plugin system
|
|
128
|
+
- [ ] Context (configurable)
|
|
129
|
+
- [ ] App
|
|
130
|
+
- [ ] Layout
|
|
131
|
+
- [ ] Page
|
|
132
|
+
- [x] Component
|
|
133
|
+
- [x] `error.zx` for default and per-route error page
|
|
134
|
+
- [x] `notfound.zx` for default and per-route error page
|
|
111
135
|
- [x] CLI
|
|
112
136
|
- [x] `init` Project Template
|
|
113
137
|
- [x] `transpile` Transpile .zx files to Zig source code
|
|
114
138
|
- [x] `serve` Serve the project
|
|
115
139
|
- [x] `dev` HMR or Rebuild on Change
|
|
116
|
-
- [x] `fmt` Format the ZX source code
|
|
140
|
+
- [x] `fmt` Format the ZX source code
|
|
117
141
|
- [x] `export` Generate static site assets
|
|
118
142
|
- [x] `bundle` Bundle the ZX executable with public/assets and exe
|
|
119
143
|
- [x] `version` Show the version of the ZX CLI
|
|
120
144
|
- [x] `update` Update the version of ZX dependency
|
|
121
145
|
- [x] `upgrade` Upgrade the version of ZX CLI
|
|
146
|
+
- [ ] Platform
|
|
147
|
+
- [x] Web Server
|
|
148
|
+
- [x] Web Browser
|
|
149
|
+
- [ ] iOS
|
|
150
|
+
- [ ] Android
|
|
151
|
+
- [ ] macOS
|
|
152
|
+
- [ ] Windows
|
|
122
153
|
|
|
123
154
|
#### Editor Support
|
|
124
155
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
- [x] Auto Format
|
|
129
|
-
|
|
130
|
-
* Neovim
|
|
131
|
-
- [ ] Syntax Highlighting
|
|
132
|
-
- [ ] LSP Support
|
|
133
|
-
- [ ] Auto Format
|
|
156
|
+
- ##### [VSCode](https://marketplace.visualstudio.com/items?itemName=nurulhudaapon.zx)/[VSCode Forks](https://marketplace.visualstudio.com/items?itemName=nurulhudaapon.zx) Extension
|
|
157
|
+
- ##### [Neovim](/editors/neovim/)
|
|
158
|
+
- ##### [Zed](/editors/zed/)
|
|
134
159
|
|
|
135
160
|
## Similar Projects
|
|
136
161
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
* [
|
|
140
|
-
* [
|
|
141
|
-
* [
|
|
142
|
-
* [
|
|
143
|
-
* [
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
* [
|
|
148
|
-
* [
|
|
149
|
-
* [
|
|
162
|
+
### Rust
|
|
163
|
+
|
|
164
|
+
* [Leptos](https://github.com/leptos-rs/leptos) - Full-stack, isomorphic Rust web framework with fine-grained reactivity and JSX-like syntax
|
|
165
|
+
* [Dioxus](https://github.com/DioxusLabs/dioxus) - Cross-platform GUI framework with React-like API, supporting web, desktop, mobile, and SSR
|
|
166
|
+
* [Yew](https://github.com/yewstack/yew) - Rust / Wasm framework for creating reliable and efficient web applications with component-based architecture
|
|
167
|
+
* [Sycamore](https://github.com/sycamore-rs/sycamore) - Reactive web framework with fine-grained reactivity and minimal bundle sizes
|
|
168
|
+
* [Perseus](https://github.com/framesurge/perseus) - Full-stack framework built on Sycamore with SSR, SSG, and incremental regeneration
|
|
169
|
+
|
|
170
|
+
### Zig
|
|
171
|
+
|
|
172
|
+
* [Jetzig](https://github.com/jetzig-framework/jetzig) - Zig web framework with MVC architecture, built-in ORM, and powerful templating
|
|
173
|
+
* [ZTS](https://github.com/zigster64/zts) - Zig Templates made Simple, a templating system for Zig
|
|
174
|
+
* [zmpl](https://github.com/jetzig-framework/zmpl) - Mode-based templating language that compiles to Zig functions at build time, used in Jetzig
|
|
175
|
+
* [mustache-zig](https://github.com/batiati/mustache-zig) - Mustache template engine implementation in Zig
|
|
176
|
+
* [etch](https://github.com/haze/etch) - Compile-time tuned templating engine focusing on speed and simplicity
|
|
177
|
+
* [Zap](https://github.com/zigzap/zap) - High-performance backend framework in Zig
|
|
178
|
+
* [http.zig](https://github.com/karlseguin/http.zig) - Low-level HTTP/1.1 server written entirely in Zig (_ZX_'s backend)
|
|
179
|
+
* [tokamak](https://github.com/cztomsik/tokamak) - Server-side framework for Zig
|
|
180
|
+
* [zig-router](https://github.com/Cloudef/zig-router) - Straightforward HTTP-like request routing library for Zig
|
|
181
|
+
* [zig-webui](https://github.com/webui-dev/zig-webui/) - Zig library that allows using any web browser as a GUI
|
|
182
|
+
* [Zine](https://github.com/kristoff-it/zine) - Fast, scalable, flexible static site generator (SSG) written in Zig
|
|
183
|
+
* [Zinc](https://github.com/zon-dev/zinc/) - Web framework written in pure Zig with focus on high performance, usability, security, and extensibility
|
|
184
|
+
* [zUI](https://github.com/thienpow/zui) - UI kit for Jetzig framework with reusable components and styles
|
|
185
|
+
* [zig-pek](https://github.com/nektro/zig-pek) - Comptime HTML/XML parser and renderer in Zig
|
|
186
|
+
* [zigomponent](https://zigomp.prjct.dev/) - HTML compoenents in pure zig
|
|
187
|
+
|
|
188
|
+
## Related Projects
|
|
189
|
+
|
|
190
|
+
* [Codeberg Mirror](https://codeberg.org/nurulhudaapon/zx) - ZX repository mirror on Codeberg
|
|
191
|
+
* [zx-vscode](https://github.com/nurulhudaapon/zx-vscode) - Official VSCode/Cursor extension with syntax highlighting, LSP support, and auto-formatting
|
|
192
|
+
* [ziex.dev](https://github.com/nurulhudaapon/zx/tree/main/site) - Official documentation site of ZX made using ZX.
|
|
193
|
+
* [zx-example-portfolio](https://github.com/nurulhudaapon/zx-example-portfolio) - Demo portfolio web application built with ZX
|
|
194
|
+
* [thegates.dev](https://github.com/nurulhudaapon/thegates.dev) - Example clone demonstrating ZX capabilities
|
|
150
195
|
|
|
151
196
|
## Contributing
|
|
152
197
|
|
package/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
var zx = {
|
|
3
3
|
name: "zx",
|
|
4
|
-
version: "0.0
|
|
4
|
+
version: "0.1.0-dev.460",
|
|
5
5
|
description: "ZX is a framework for building web applications with Zig.",
|
|
6
6
|
repository: "https://github.com/nurulhudaapon/zx",
|
|
7
7
|
fingerprint: 14616285862371232000,
|
|
@@ -12,18 +12,30 @@ var zx = {
|
|
|
12
12
|
hash: "httpz-0.0.0-PNVzrBgtBwCVkSJyophIX6WHwDR0r8XhBGQr96Kk-1El"
|
|
13
13
|
},
|
|
14
14
|
zli: {
|
|
15
|
-
|
|
16
|
-
hash: "zli-4.3.0-LeUjpu_fAABOSVASSCW2fFh8SFVNHrxQGDXGPNzcSE_i"
|
|
15
|
+
path: "vendor/cliz"
|
|
17
16
|
},
|
|
18
17
|
zig_js: {
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
path: "vendor/jsz"
|
|
19
|
+
},
|
|
20
|
+
tree_sitter: {
|
|
21
|
+
path: "vendor/zig-tree-sitter"
|
|
22
|
+
},
|
|
23
|
+
tree_sitter_zx: {
|
|
24
|
+
path: "packages/tree-sitter-zx"
|
|
25
|
+
},
|
|
26
|
+
cachez: {
|
|
27
|
+
path: "vendor/cachez"
|
|
21
28
|
}
|
|
22
29
|
},
|
|
23
30
|
paths: [
|
|
24
31
|
"build.zig",
|
|
25
32
|
"build.zig.zon",
|
|
26
|
-
"src"
|
|
33
|
+
"src",
|
|
34
|
+
"packages/tree-sitter-zx",
|
|
35
|
+
"vendor/cachez",
|
|
36
|
+
"vendor/cliz",
|
|
37
|
+
"vendor/jsz",
|
|
38
|
+
"vendor/zig-tree-sitter"
|
|
27
39
|
]
|
|
28
40
|
};
|
|
29
41
|
export {
|
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ziex",
|
|
3
|
+
"version": "0.1.0-dev.460",
|
|
3
4
|
"description": "ZX is a framework for building web applications with Zig.",
|
|
4
5
|
"main": "index.js",
|
|
5
6
|
"type": "module",
|
|
@@ -11,7 +12,7 @@
|
|
|
11
12
|
"homepage": "https://github.com/nurulhudaapon/zx",
|
|
12
13
|
"repository": {
|
|
13
14
|
"type": "git",
|
|
14
|
-
"url": "https://github.com/nurulhudaapon/zx.git"
|
|
15
|
+
"url": "git+https://github.com/nurulhudaapon/zx.git"
|
|
15
16
|
},
|
|
16
17
|
"keywords": [
|
|
17
18
|
"zx",
|
|
@@ -28,6 +29,5 @@
|
|
|
28
29
|
"author": "Nurul Huda (Apon) <me@nurulhudaapon.com>",
|
|
29
30
|
"license": "MIT",
|
|
30
31
|
"module": "index.js",
|
|
31
|
-
"types": "index.d.ts"
|
|
32
|
-
|
|
33
|
-
}
|
|
32
|
+
"types": "index.d.ts"
|
|
33
|
+
}
|
package/react/dom.d.ts
CHANGED
package/react/types.d.ts
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
* Metadata for a client-side component used within a ZX file.
|
|
3
3
|
*
|
|
4
4
|
* This type represents the metadata for components that are marked with the `@rendering` attribute
|
|
5
|
-
* in ZX files. When a component is declared with `@rendering={.
|
|
5
|
+
* in ZX files. When a component is declared with `@rendering={.react}` or `@rendering={.client}` in a
|
|
6
6
|
* `.zx` file, the ZX transpiler generates a `ComponentMetadata` entry that is included in the
|
|
7
7
|
* generated `components` array.
|
|
8
8
|
*
|
|
9
9
|
* @example
|
|
10
10
|
* ```tsx
|
|
11
11
|
* // In a ZX file (page.zx):
|
|
12
|
-
* <CounterComponent @rendering={.
|
|
12
|
+
* <CounterComponent @rendering={.react} max_count={10} />
|
|
13
13
|
*
|
|
14
14
|
* // Generated components array (components.ts):
|
|
15
15
|
* export const components: ComponentMetadata[] = [
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* name: "CounterComponent",
|
|
18
18
|
* path: "./components/CounterComponent.tsx",
|
|
19
19
|
* id: "zx-dcde04c415da9d1b15ca2690d8b497ae",
|
|
20
|
-
* type: "
|
|
20
|
+
* type: "react",
|
|
21
21
|
* import: () => import('./components/CounterComponent.tsx')
|
|
22
22
|
* }
|
|
23
23
|
* ];
|
|
@@ -44,7 +44,7 @@ export type ComponentMetadata = {
|
|
|
44
44
|
* @example
|
|
45
45
|
* ```tsx
|
|
46
46
|
* // In ZX file:
|
|
47
|
-
* <CounterComponent @rendering={.
|
|
47
|
+
* <CounterComponent @rendering={.react} />
|
|
48
48
|
*
|
|
49
49
|
* // name will be: "CounterComponent"
|
|
50
50
|
* ```
|
|
@@ -54,7 +54,7 @@ export type ComponentMetadata = {
|
|
|
54
54
|
* The file path to the component module.
|
|
55
55
|
*
|
|
56
56
|
* This is the relative or absolute path to the component file that will be dynamically imported
|
|
57
|
-
* at runtime. For CSR components, this typically points to a `.tsx` or `.jsx` file. For
|
|
57
|
+
* at runtime. For CSR components, this typically points to a `.tsx` or `.jsx` file. For Client
|
|
58
58
|
* components, this points to a Zig component file.
|
|
59
59
|
*
|
|
60
60
|
* The path is determined from the `@jsImport` directive in the ZX file, or defaults to
|
|
@@ -64,7 +64,7 @@ export type ComponentMetadata = {
|
|
|
64
64
|
* ```tsx
|
|
65
65
|
* // In ZX file:
|
|
66
66
|
* const CounterComponent = @jsImport("components/Counter.tsx");
|
|
67
|
-
* <CounterComponent @rendering={.
|
|
67
|
+
* <CounterComponent @rendering={.react} />
|
|
68
68
|
*
|
|
69
69
|
* // path will be: "components/Counter.tsx"
|
|
70
70
|
* ```
|
|
@@ -72,7 +72,7 @@ export type ComponentMetadata = {
|
|
|
72
72
|
* @example
|
|
73
73
|
* ```tsx
|
|
74
74
|
* // Without explicit @jsImport:
|
|
75
|
-
* <MyComponent @rendering={.
|
|
75
|
+
* <MyComponent @rendering={.react} />
|
|
76
76
|
*
|
|
77
77
|
* // path will default to: "./MyComponent.tsx"
|
|
78
78
|
* ```
|
|
@@ -118,21 +118,21 @@ export type ComponentMetadata = {
|
|
|
118
118
|
/**
|
|
119
119
|
* The rendering type of the component, determining how it will be rendered on the client.
|
|
120
120
|
*
|
|
121
|
-
* - **"
|
|
121
|
+
* - **"react"** (Client Side React): The component is a React component that will be rendered
|
|
122
122
|
* using React's client-side rendering. The component file should export a default React
|
|
123
123
|
* component function. This is the most common type for interactive UI components.
|
|
124
124
|
*
|
|
125
|
-
* - **"
|
|
125
|
+
* - **"client"** (Client Side Zig): The component is a Zig component that will be compiled to
|
|
126
126
|
* WebAssembly and rendered on the client side. This allows you to use Zig's performance
|
|
127
127
|
* and type safety for client-side components.
|
|
128
128
|
*
|
|
129
|
-
* The type is determined by the `@rendering` attribute value in the ZX file (`.
|
|
129
|
+
* The type is determined by the `@rendering` attribute value in the ZX file (`.react` or `.client`).
|
|
130
130
|
*
|
|
131
131
|
* @example
|
|
132
132
|
* ```tsx
|
|
133
133
|
* // CSR component (React):
|
|
134
|
-
* <CounterComponent @rendering={.
|
|
135
|
-
* // type: "
|
|
134
|
+
* <CounterComponent @rendering={.react} max_count={10} />
|
|
135
|
+
* // type: "react"
|
|
136
136
|
*
|
|
137
137
|
* // Component file (CounterComponent.tsx):
|
|
138
138
|
* export default function CounterComponent({ max_count }: { max_count: number }) {
|
|
@@ -142,9 +142,9 @@ export type ComponentMetadata = {
|
|
|
142
142
|
*
|
|
143
143
|
* @example
|
|
144
144
|
* ```tsx
|
|
145
|
-
* //
|
|
146
|
-
* <CounterComponent @rendering={.
|
|
147
|
-
* // type: "
|
|
145
|
+
* // Client component (Zig/WASM):
|
|
146
|
+
* <CounterComponent @rendering={.client} />
|
|
147
|
+
* // type: "client"
|
|
148
148
|
*
|
|
149
149
|
* // Component file (CounterComponent.zig):
|
|
150
150
|
* pub fn CounterComponent(allocator: zx.Allocator) zx.Component {
|
|
@@ -152,7 +152,7 @@ export type ComponentMetadata = {
|
|
|
152
152
|
* }
|
|
153
153
|
* ```
|
|
154
154
|
*/
|
|
155
|
-
type: "
|
|
155
|
+
type: "react" | "client";
|
|
156
156
|
/**
|
|
157
157
|
* A lazy-loading function that dynamically imports the component module.
|
|
158
158
|
*
|
|
@@ -161,7 +161,7 @@ export type ComponentMetadata = {
|
|
|
161
161
|
* by only loading components when they are needed.
|
|
162
162
|
*
|
|
163
163
|
* For CSR components, the imported module should export a default React component.
|
|
164
|
-
* For
|
|
164
|
+
* For Client components, the import mechanism depends on the WASM module structure.
|
|
165
165
|
*
|
|
166
166
|
* The function is called during client-side hydration to load and render the component
|
|
167
167
|
* into its corresponding DOM container element.
|
package/wasm/index.d.ts
CHANGED
|
@@ -2,13 +2,23 @@ declare class ZXInstance {
|
|
|
2
2
|
#private;
|
|
3
3
|
exports: WebAssembly.Exports;
|
|
4
4
|
events: Event[];
|
|
5
|
-
actions: Record<string, (eventId: number) => void>;
|
|
6
5
|
constructor({ exports, events }: ZXInstanceOptions);
|
|
7
6
|
addEvent(event: Event): number;
|
|
7
|
+
/**
|
|
8
|
+
* Initialize event delegation on a root element
|
|
9
|
+
* This attaches a single event listener for each event type at the root,
|
|
10
|
+
* and uses __zx_ref to look up the corresponding VElement in WASM
|
|
11
|
+
*/
|
|
12
|
+
initEventDelegation(rootSelector?: string): void;
|
|
13
|
+
/** Get the VElement ID from a DOM element */
|
|
14
|
+
getZxRef(element: HTMLElement): number | undefined;
|
|
8
15
|
}
|
|
9
16
|
export declare function init(options?: InitOptions): Promise<void>;
|
|
10
17
|
export type InitOptions = {
|
|
18
|
+
/** URL to the WASM file (default: /assets/main.wasm) */
|
|
11
19
|
url?: string;
|
|
20
|
+
/** CSS selector for the event delegation root element (default: 'body') */
|
|
21
|
+
eventDelegationRoot?: string;
|
|
12
22
|
};
|
|
13
23
|
type ZXInstanceOptions = {
|
|
14
24
|
exports: ZXInstance['exports'];
|
|
@@ -18,5 +28,11 @@ declare global {
|
|
|
18
28
|
interface Window {
|
|
19
29
|
_zx: ZXInstance;
|
|
20
30
|
}
|
|
31
|
+
interface HTMLElement {
|
|
32
|
+
/**
|
|
33
|
+
* The VElement ID of the element
|
|
34
|
+
*/
|
|
35
|
+
__zx_ref?: number;
|
|
36
|
+
}
|
|
21
37
|
}
|
|
22
38
|
export {};
|
package/wasm/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// ../../vendor/jsz/js/src/zigjs.ts
|
|
2
2
|
var NAN_PREFIX = 2146959360;
|
|
3
3
|
var predefined = {
|
|
4
4
|
nan: 0,
|
|
@@ -170,6 +170,48 @@ class ZigJS {
|
|
|
170
170
|
// src/wasm/index.ts
|
|
171
171
|
var DEFAULT_URL = "/assets/main.wasm";
|
|
172
172
|
var MAX_EVENTS = 100;
|
|
173
|
+
var DELEGATED_EVENTS = [
|
|
174
|
+
"click",
|
|
175
|
+
"dblclick",
|
|
176
|
+
"input",
|
|
177
|
+
"change",
|
|
178
|
+
"submit",
|
|
179
|
+
"focus",
|
|
180
|
+
"blur",
|
|
181
|
+
"keydown",
|
|
182
|
+
"keyup",
|
|
183
|
+
"keypress",
|
|
184
|
+
"mouseenter",
|
|
185
|
+
"mouseleave",
|
|
186
|
+
"mousedown",
|
|
187
|
+
"mouseup",
|
|
188
|
+
"mousemove",
|
|
189
|
+
"touchstart",
|
|
190
|
+
"touchend",
|
|
191
|
+
"touchmove",
|
|
192
|
+
"scroll"
|
|
193
|
+
];
|
|
194
|
+
var EVENT_TYPE_MAP = {
|
|
195
|
+
click: 0,
|
|
196
|
+
dblclick: 1,
|
|
197
|
+
input: 2,
|
|
198
|
+
change: 3,
|
|
199
|
+
submit: 4,
|
|
200
|
+
focus: 5,
|
|
201
|
+
blur: 6,
|
|
202
|
+
keydown: 7,
|
|
203
|
+
keyup: 8,
|
|
204
|
+
keypress: 9,
|
|
205
|
+
mouseenter: 10,
|
|
206
|
+
mouseleave: 11,
|
|
207
|
+
mousedown: 12,
|
|
208
|
+
mouseup: 13,
|
|
209
|
+
mousemove: 14,
|
|
210
|
+
touchstart: 15,
|
|
211
|
+
touchend: 16,
|
|
212
|
+
touchmove: 17,
|
|
213
|
+
scroll: 18
|
|
214
|
+
};
|
|
173
215
|
var jsz = new ZigJS;
|
|
174
216
|
var importObject = {
|
|
175
217
|
module: {},
|
|
@@ -180,16 +222,10 @@ var importObject = {
|
|
|
180
222
|
class ZXInstance {
|
|
181
223
|
exports;
|
|
182
224
|
events;
|
|
183
|
-
|
|
225
|
+
#eventDelegationInitialized = false;
|
|
184
226
|
constructor({ exports, events = [] }) {
|
|
185
227
|
this.exports = exports;
|
|
186
228
|
this.events = events;
|
|
187
|
-
this.actions = {};
|
|
188
|
-
Object.entries(exports).forEach(([name, func]) => {
|
|
189
|
-
if (typeof func !== "function")
|
|
190
|
-
return;
|
|
191
|
-
this.actions[name] = this.#actionWrapper.bind(this, name);
|
|
192
|
-
});
|
|
193
229
|
}
|
|
194
230
|
addEvent(event) {
|
|
195
231
|
if (this.events.length >= MAX_EVENTS)
|
|
@@ -197,12 +233,40 @@ class ZXInstance {
|
|
|
197
233
|
const idx = this.events.push(event);
|
|
198
234
|
return idx - 1;
|
|
199
235
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
236
|
+
initEventDelegation(rootSelector = "body") {
|
|
237
|
+
if (this.#eventDelegationInitialized)
|
|
238
|
+
return;
|
|
239
|
+
const root = document.querySelector(rootSelector);
|
|
240
|
+
if (!root) {
|
|
241
|
+
console.warn(`[ZX] Event delegation root "${rootSelector}" not found`);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
for (const eventType of DELEGATED_EVENTS) {
|
|
245
|
+
root.addEventListener(eventType, (event) => {
|
|
246
|
+
this.#handleDelegatedEvent(eventType, event);
|
|
247
|
+
}, { passive: eventType.startsWith("touch") || eventType === "scroll" });
|
|
248
|
+
}
|
|
249
|
+
this.#eventDelegationInitialized = true;
|
|
250
|
+
console.debug("[ZX] Event delegation initialized on", rootSelector);
|
|
251
|
+
}
|
|
252
|
+
#handleDelegatedEvent(eventType, event) {
|
|
253
|
+
let target = event.target;
|
|
254
|
+
while (target && target !== document.body) {
|
|
255
|
+
const zxRef = target.__zx_ref;
|
|
256
|
+
if (zxRef !== undefined) {
|
|
257
|
+
const eventId = this.addEvent(event);
|
|
258
|
+
const handleEvent = this.exports.handleEvent;
|
|
259
|
+
if (typeof handleEvent === "function") {
|
|
260
|
+
const eventTypeId = EVENT_TYPE_MAP[eventType] ?? 0;
|
|
261
|
+
handleEvent(BigInt(zxRef), eventTypeId, BigInt(eventId));
|
|
262
|
+
}
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
target = target.parentElement;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
getZxRef(element) {
|
|
269
|
+
return element.__zx_ref;
|
|
206
270
|
}
|
|
207
271
|
}
|
|
208
272
|
async function init(options = {}) {
|
|
@@ -210,6 +274,7 @@ async function init(options = {}) {
|
|
|
210
274
|
const { instance } = await WebAssembly.instantiateStreaming(fetch(url), importObject);
|
|
211
275
|
jsz.memory = instance.exports.memory;
|
|
212
276
|
window._zx = new ZXInstance({ exports: instance.exports });
|
|
277
|
+
window._zx.initEventDelegation(options.eventDelegationRoot ?? "body");
|
|
213
278
|
const main = instance.exports.mainClient;
|
|
214
279
|
if (typeof main === "function")
|
|
215
280
|
main();
|
package/zx.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getZxInfo(): any;
|