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 CHANGED
@@ -1,10 +1,10 @@
1
1
  # ZX
2
2
 
3
- A Zig library for building web applications with JSX-like syntax. Write declarative UI components using familiar JSX patterns, transpiled to efficient Zig code.
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. ZX is significantly faster than frameworks like Next.js at SSR.
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
- **[Full Documentation →](https://ziex.dev)**
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>{[char:c]}</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>{[user.age:d]}</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] `while` nested
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
- - [ ] CSS
106
- - [ ] JS
107
- - [ ] HTML
108
- - [ ] Middleware
109
- - [ ] API Endpoints
110
- - [ ] Server Actions
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 (_Alpha_)
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
- * [VSCode](https://marketplace.visualstudio.com/items?itemName=nurulhudaapon.zx)/[Cursor](https://marketplace.visualstudio.com/items?itemName=nurulhudaapon.zx) Extension
126
- - [x] Syntax Highlighting
127
- - [x] LSP Support
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
- * [Yew](https://github.com/yewstack/yew) - Rust / Wasm framework for creating reliable and efficient web applications
138
- * [ZTS](https://github.com/zigster64/zts) — Zig Templates made Simple, a templating system for Zig
139
- * [zmpl](https://github.com/jetzig-framework/zmpl) Mode-based templating language that compiles to Zig functions at build time, used in Jetzig
140
- * [mustache-zig](https://github.com/batiati/mustache-zig) Mustache template engine implementation in Zig
141
- * [etch](https://github.com/haze/etch) — Compile-time tuned templating engine focusing on speed and simplicity
142
- * [Zap](https://github.com/zigzap/zap) — High-performance backend framework in Zig
143
- * [http.zig](https://github.com/karlseguin/http.zig) Low-level HTTP/1.1 server written entirely in Zig (_ZX_'s backend)
144
- * [tokamak](https://github.com/cztomsik/tokamak) — Server-side framework for Zig
145
- * [zig-router](https://github.com/Cloudef/zig-router) — Straightforward HTTP-like request routing library for Zig
146
- * [zig-webui](https://github.com/webui-dev/zig-webui/) — Zig library that allows using any web browser as a GUI
147
- * [Zine](https://github.com/kristoff-it/zine) Fast, scalable, flexible static site generator (SSG) written in Zig
148
- * [Zinc](https://github.com/zon-dev/zinc/) Web framework written in pure Zig with focus on high performance, usability, security, and extensibility
149
- * [zUI](https://github.com/thienpow/zui) UI kit for Jetzig framework with reusable components and styles
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.1-dev.270",
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
- url: "git+https://github.com/nurulhudaapon/cliz.git#aff3b54879e7514afaf8c87f1abe22121b8992d4",
16
- hash: "zli-4.3.0-LeUjpu_fAABOSVASSCW2fFh8SFVNHrxQGDXGPNzcSE_i"
15
+ path: "vendor/cliz"
17
16
  },
18
17
  zig_js: {
19
- url: "git+https://github.com/nurulhudaapon/jsz.git#04db83c617da1956ac5adc1cb9ba1e434c1cb6fd",
20
- hash: "zig_js-0.0.0-rjCAV-6GAADxFug7rDmPH-uM_XcnJ5NmuAMJCAscMjhi"
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
- "version": "0.0.1-dev.7"
33
- }
32
+ "types": "index.d.ts"
33
+ }
package/react/dom.d.ts CHANGED
@@ -52,7 +52,7 @@ export type PreparedComponent = {
52
52
  * @example
53
53
  * ```tsx
54
54
  * // In ZX file:
55
- * <MyComponent @rendering={.csr}>
55
+ * <MyComponent @rendering={.react}>
56
56
  * <p>Child content</p>
57
57
  * </MyComponent>
58
58
  *
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={.csr}` or `@rendering={.csz}` in a
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={.csr} max_count={10} />
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: "csr",
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={.csr} />
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 CSZ
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={.csr} />
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={.csr} />
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
- * - **"csr"** (Client Side React): The component is a React component that will be rendered
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
- * - **"csz"** (Client Side Zig): The component is a Zig component that will be compiled to
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 (`.csr` or `.csz`).
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={.csr} max_count={10} />
135
- * // type: "csr"
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
- * // CSZ component (Zig/WASM):
146
- * <CounterComponent @rendering={.csz} />
147
- * // type: "csz"
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: "csr" | "csz";
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 CSZ components, the import mechanism depends on the WASM module structure.
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
- // node_modules/jsz/js/src/zigjs.ts
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
- actions;
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
- #actionWrapper(name, ...args) {
201
- const func = this.exports[name];
202
- if (typeof func !== "function")
203
- throw new Error(`Action ${name} is not a function`);
204
- const eventId = this.addEvent(args[0]);
205
- return func(eventId);
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;