@nativewindow/webview 0.1.1

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) 2026 Francesco Saverio Cannizzaro
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,341 @@
1
+ <p align="center">
2
+ <img src="docs/public/native-window.webp" alt="native-window" width="200" />
3
+ </p>
4
+
5
+ # @nativewindow/webview
6
+
7
+ [![CI](https://github.com/nativewindow/webview/actions/workflows/ci.yml/badge.svg)](https://github.com/nativewindow/webview/actions/workflows/ci.yml)
8
+ [![npm](https://img.shields.io/npm/v/@nativewindow/webview)](https://www.npmjs.com/package/@nativewindow/webview)
9
+ [![npm](https://img.shields.io/npm/v/@nativewindow/ipc?label=native-window-ipc)](https://www.npmjs.com/package/@nativewindow/ipc)
10
+ [![npm](https://img.shields.io/npm/v/@nativewindow/react?label=native-window-ipc-react)](https://www.npmjs.com/package/@nativewindow/react)
11
+ [![npm](https://img.shields.io/npm/v/@nativewindow/tsdb?label=native-window-tsdb)](https://www.npmjs.com/package/@nativewindow/tsdb)
12
+
13
+ > [!WARNING]
14
+ > This project is in **alpha**. APIs may change without notice and some features may be incomplete or unstable.
15
+
16
+ Native OS webviews for Bun, Deno & Node.js. Create real desktop windows with embedded web content using [wry](https://github.com/tauri-apps/wry) + [tao](https://github.com/tauri-apps/tao) — providing WebKit on macOS and Linux, and WebView2 on Windows.
17
+
18
+ ## Features
19
+
20
+ - **Native webviews** — powered by [wry](https://github.com/tauri-apps/wry) + [tao](https://github.com/tauri-apps/tao) (WebKit on macOS/Linux, WebView2 on Windows), no Electron or Chromium bundled
21
+ - **Multi-window** — create and manage multiple independent windows
22
+ - **HTML & URL loading** — load inline HTML strings or navigate to URLs
23
+ - **Bidirectional IPC** — send messages between Bun/Deno/Node and the webview
24
+ - **Typesafe IPC channels** — typed message layer with schema-based validation and compile-time checked event maps
25
+ - **Full window control** — title, size, position, min/max size, decorations, transparency, always-on-top
26
+ - **Window events** — close, resize, move, focus, blur, page load, title change
27
+ - **Rust + napi-rs + wry + tao** — high-performance native addon, no runtime overhead
28
+ - **Runtime detection** — check for WebView2 availability and auto-install on Windows
29
+
30
+ ## Packages
31
+
32
+ | Package | Description |
33
+ | ----------------------------------------------------------- | --------------------------------------------------------- |
34
+ | [`@nativewindow/webview`](./packages/webview) | Rust napi-rs addon providing native window + webview APIs |
35
+ | [`@nativewindow/ipc`](./packages/ipc) | Pure TypeScript typesafe IPC channel layer |
36
+ | [`@nativewindow/react`](./packages/react) | React bindings for the typed IPC layer |
37
+ | [`@nativewindow/tsdb`](./packages/tsdb) | TanStack DB collection adapter for native-window IPC |
38
+
39
+ ## Quick Start
40
+
41
+ ```ts
42
+ import { init, pumpEvents, NativeWindow } from "native-window";
43
+
44
+ init();
45
+ const pump = setInterval(() => pumpEvents(), 16);
46
+
47
+ const win = new NativeWindow({
48
+ title: "My App",
49
+ width: 800,
50
+ height: 600,
51
+ });
52
+
53
+ win.loadHtml(`
54
+ <h1>Hello from native webview!</h1>
55
+ <button onclick="window.ipc.postMessage('clicked')">Click me</button>
56
+ `);
57
+
58
+ win.onMessage((msg) => {
59
+ console.log("From webview:", msg);
60
+ win.postMessage(`Echo: ${msg}`);
61
+ });
62
+
63
+ win.onClose(() => {
64
+ clearInterval(pump);
65
+ process.exit(0);
66
+ });
67
+ ```
68
+
69
+ ## Typed IPC
70
+
71
+ Use `native-window-ipc` for compile-time checked messaging between Bun/Deno/Node and the webview. Schemas provide both types and runtime validation.
72
+
73
+ ### Host side (Bun/Deno/Node)
74
+
75
+ ```ts
76
+ import { z } from "zod";
77
+ import { createWindow } from "native-window-ipc";
78
+
79
+ const ch = createWindow(
80
+ { title: "Typed IPC" },
81
+ {
82
+ schemas: {
83
+ "user-click": z.object({ x: z.number(), y: z.number() }),
84
+ "update-title": z.string(),
85
+ counter: z.number(),
86
+ },
87
+ },
88
+ );
89
+
90
+ ch.on("user-click", (pos) => {
91
+ // pos: { x: number; y: number }
92
+ console.log(`Click at ${pos.x}, ${pos.y}`);
93
+ });
94
+
95
+ ch.on("counter", (n) => {
96
+ // n: number
97
+ ch.send("update-title", `Count: ${n}`);
98
+ });
99
+
100
+ // ch.send("counter", "wrong"); // Type error!
101
+ // ch.send("typo", 123); // Type error!
102
+
103
+ ch.window.loadHtml(`<html>...</html>`);
104
+ ```
105
+
106
+ ### Webview side (inline HTML)
107
+
108
+ The `__channel__` object is auto-injected by `createWindow` / `createChannel`:
109
+
110
+ ```html
111
+ <script>
112
+ __channel__.send("user-click", { x: 10, y: 20 });
113
+ __channel__.on("update-title", (title) => {
114
+ document.title = title;
115
+ });
116
+ </script>
117
+ ```
118
+
119
+ ### Webview side (bundled app)
120
+
121
+ For webview apps bundled with their own build step, import the client directly:
122
+
123
+ ```ts
124
+ import { z } from "zod";
125
+ import { createChannelClient } from "native-window-ipc/client";
126
+
127
+ const ch = createChannelClient({
128
+ schemas: {
129
+ counter: z.number(),
130
+ "update-title": z.string(),
131
+ },
132
+ });
133
+ ch.send("counter", 42); // Typed!
134
+ ch.on("update-title", (t) => {
135
+ // t: string
136
+ document.title = t;
137
+ });
138
+ ```
139
+
140
+ ## Runtime Detection
141
+
142
+ On Windows 10, the WebView2 runtime may not be installed. Use `checkRuntime()` to detect it and `ensureRuntime()` to auto-install if missing.
143
+
144
+ ```ts
145
+ import { checkRuntime, ensureRuntime } from "native-window";
146
+
147
+ const info = checkRuntime();
148
+ console.log(info);
149
+ // { available: true, version: "128.0.2739.42", platform: "windows" }
150
+ // { available: false, version: undefined, platform: "windows" }
151
+ // { available: true, version: undefined, platform: "macos" }
152
+ // { available: true, version: undefined, platform: "linux" }
153
+
154
+ if (!info.available) {
155
+ console.log("WebView2 not found, installing...");
156
+ const result = ensureRuntime(); // downloads ~2MB bootstrapper, runs silently
157
+ console.log("Installed:", result.version);
158
+ }
159
+ ```
160
+
161
+ On macOS, both functions return `{ available: true }` immediately — WKWebView is a system framework. On Linux, both functions also return `{ available: true }` — WebKitGTK is assumed to be installed. On Windows 11, WebView2 is pre-installed.
162
+
163
+ ## API Reference
164
+
165
+ ### `native-window`
166
+
167
+ #### `init()`
168
+
169
+ Initialize the native window system. Must be called once before creating any windows.
170
+
171
+ #### `pumpEvents()`
172
+
173
+ Process pending native UI events. Call periodically (~16ms via `setInterval`) to keep windows responsive.
174
+
175
+ #### `checkRuntime(): RuntimeInfo`
176
+
177
+ Check if the native webview runtime is available. Returns `{ available: boolean, version?: string, platform: "macos" | "windows" | "linux" | "unsupported" }`.
178
+
179
+ #### `ensureRuntime(): RuntimeInfo`
180
+
181
+ Check for the runtime and install it if missing (Windows only). Downloads the WebView2 Evergreen Bootstrapper (~2MB) from Microsoft and runs it silently. Throws on failure.
182
+
183
+ #### `new NativeWindow(options?)`
184
+
185
+ Create a native window with an embedded webview.
186
+
187
+ **WindowOptions:**
188
+
189
+ | Option | Type | Default | Description |
190
+ | ------------------------ | --------- | ------- | ----------------------------- |
191
+ | `title` | `string` | `""` | Window title |
192
+ | `width` | `number` | `800` | Inner width (logical pixels) |
193
+ | `height` | `number` | `600` | Inner height (logical pixels) |
194
+ | `x` | `number` | — | X position |
195
+ | `y` | `number` | — | Y position |
196
+ | `minWidth` / `minHeight` | `number` | — | Minimum size |
197
+ | `maxWidth` / `maxHeight` | `number` | — | Maximum size |
198
+ | `resizable` | `boolean` | `true` | Allow resizing |
199
+ | `decorations` | `boolean` | `true` | Show title bar and borders |
200
+ | `transparent` | `boolean` | `false` | Transparent background |
201
+ | `alwaysOnTop` | `boolean` | `false` | Float above other windows |
202
+ | `visible` | `boolean` | `true` | Initially visible |
203
+ | `devtools` | `boolean` | `false` | Enable devtools |
204
+
205
+ **Content methods:**
206
+
207
+ | Method | Description |
208
+ | --------------------------- | ------------------------------------------------------------ |
209
+ | `loadUrl(url)` | Navigate to a URL |
210
+ | `loadHtml(html)` | Load an HTML string |
211
+ | `unsafe.evaluateJs(script)` | Execute JS in the webview (fire-and-forget) |
212
+ | `postMessage(msg)` | Send a string to the webview via `window.__native_message__` |
213
+
214
+ **Window control:**
215
+
216
+ | Method | Description |
217
+ | -------------------------------------------- | ---------------------------- |
218
+ | `setTitle(title)` | Set the window title |
219
+ | `setSize(w, h)` | Set the window size |
220
+ | `setMinSize(w, h)` / `setMaxSize(w, h)` | Set size constraints |
221
+ | `setPosition(x, y)` | Set window position |
222
+ | `setResizable(bool)` | Toggle resizability |
223
+ | `setDecorations(bool)` | Toggle decorations |
224
+ | `setAlwaysOnTop(bool)` | Toggle always-on-top |
225
+ | `show()` / `hide()` | Show or hide the window |
226
+ | `close()` | Close and destroy the window |
227
+ | `focus()` | Bring the window to focus |
228
+ | `maximize()` / `minimize()` / `unmaximize()` | Window state |
229
+
230
+ **Events:**
231
+
232
+ | Method | Callback signature |
233
+ | ---------------------------- | ------------------------------------------------------- |
234
+ | `onMessage(cb)` | `(message: string) => void` |
235
+ | `onClose(cb)` | `() => void` |
236
+ | `onResize(cb)` | `(width: number, height: number) => void` |
237
+ | `onMove(cb)` | `(x: number, y: number) => void` |
238
+ | `onFocus(cb)` / `onBlur(cb)` | `() => void` |
239
+ | `onPageLoad(cb)` | `(event: "started" \| "finished", url: string) => void` |
240
+ | `onTitleChanged(cb)` | `(title: string) => void` |
241
+
242
+ ### `native-window-ipc`
243
+
244
+ #### `createChannel<S>(win, options): NativeWindowChannel<InferSchemaMap<S>>`
245
+
246
+ Wrap an existing `NativeWindow` with a typed message channel. Schemas are required. Auto-injects the webview client script (disable with `{ injectClient: false }`).
247
+
248
+ #### `createWindow<S>(windowOptions, channelOptions): NativeWindowChannel<InferSchemaMap<S>>`
249
+
250
+ Convenience: creates a `NativeWindow` and wraps it with `createChannel`.
251
+
252
+ #### `getClientScript(): string`
253
+
254
+ Returns the webview-side client as a self-contained JS string for manual injection.
255
+
256
+ #### `createChannelClient<S>(options): TypedChannel<InferSchemaMap<S>>` (from `native-window-ipc/client`)
257
+
258
+ Create a typed channel client inside the webview. Schemas are required. For use in bundled webview apps.
259
+
260
+ #### `TypedChannel<T>`
261
+
262
+ ```ts
263
+ interface TypedChannel<T extends EventMap> {
264
+ send<K extends keyof T & string>(type: K, payload: T[K]): void;
265
+ on<K extends keyof T & string>(type: K, handler: (payload: T[K]) => void): void;
266
+ off<K extends keyof T & string>(type: K, handler: (payload: T[K]) => void): void;
267
+ }
268
+ ```
269
+
270
+ ## Security
271
+
272
+ All security hardening is compiled in by default on all supported platforms — no build-time feature flags required.
273
+
274
+ - **URL scheme blocking** — `javascript:`, `file:`, `data:`, and `blob:` navigations are blocked at the native layer
275
+ - **Content Security Policy** — inject a CSP via the `csp` option in `WindowOptions`
276
+ - **Trusted origin filtering** — restrict IPC messages and client injection to specific origins at the native and IPC layers
277
+ - **Webview surface hardening** — context menus, status bar, and built-in error page are disabled on Windows
278
+ - **IPC bridge hardening** — `window.ipc` and `window.__channel__` are frozen, non-writable objects
279
+ - **Message size limits** — 10 MB hard limit at the native layer, configurable 1 MB default at the IPC layer
280
+ - **Schema-based validation** — all incoming IPC payloads are validated at runtime against user-defined schemas
281
+
282
+ See the [Security documentation](https://native-window.dev/docs/security) for the full threat model and best practices.
283
+
284
+ ## Building
285
+
286
+ ### Prerequisites
287
+
288
+ - [Bun](https://bun.sh) (v1.3+), [Deno](https://deno.com) (v2+), or [Node.js](https://nodejs.org) (v18+)
289
+ - [Rust](https://rustup.rs) (stable)
290
+ - macOS, Windows, or Linux (for native compilation)
291
+ - On Linux: WebKitGTK development headers (e.g. `libwebkit2gtk-4.1-dev` on Ubuntu/Debian)
292
+
293
+ ### Install dependencies
294
+
295
+ ```bash
296
+ bun install
297
+ # or
298
+ deno install
299
+ ```
300
+
301
+ ### Build the native addon
302
+
303
+ ```bash
304
+ cd packages/webview
305
+ bun run build # release build
306
+ bun run build:debug # debug build
307
+ ```
308
+
309
+ The build targets the current platform. Cross-compilation targets are configured in `packages/webview/package.json` under `napi.triples`.
310
+
311
+ ## Samples
312
+
313
+ ```bash
314
+ # Raw IPC example
315
+ bun samples/basic.ts
316
+
317
+ # Typed IPC example
318
+ bun samples/typed-ipc.ts
319
+ ```
320
+
321
+ ## Testing
322
+
323
+ ```bash
324
+ # Run the IPC channel tests
325
+ cd packages/ipc
326
+ bun test
327
+ ```
328
+
329
+ ## Known Limitations
330
+
331
+ - **~16ms event latency** from the `pumpEvents()` polling interval
332
+ - **HTML null origin** — content loaded via `loadHtml()` has a null CORS origin; use a custom protocol or `loadUrl()` for fetch/XHR
333
+ - **Windows 10** may require the [WebView2 Runtime](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) — use `ensureRuntime()` to auto-install (included by default on Windows 11)
334
+ - **Linux** requires [WebKitGTK](https://webkitgtk.org/) to be installed (e.g. `libwebkit2gtk-4.1-dev` on Ubuntu/Debian)
335
+ - **No return values from `unsafe.evaluateJs()`** — use `postMessage`/`onMessage` to send results back
336
+ - **2 MB HTML limit on Windows** when using `loadHtml()`
337
+ - **Use `bun --watch`** instead of `bun --hot` for development (native addon reloading requires a process restart)
338
+
339
+ ## License
340
+
341
+ MIT
@@ -0,0 +1,268 @@
1
+ import { checkRuntime, ensureRuntime, loadHtmlOrigin } from '../native-window.js';
2
+ export { checkRuntime, ensureRuntime, loadHtmlOrigin };
3
+ export type { WindowOptions, RuntimeInfo } from '../native-window.js';
4
+ /**
5
+ * Operations that execute arbitrary code in the webview context.
6
+ * Grouped under {@link NativeWindow.unsafe} to signal injection risk.
7
+ *
8
+ * @security Never pass unsanitized user input to these methods.
9
+ * Use {@link sanitizeForJs} to escape strings before embedding them in
10
+ * script code.
11
+ */
12
+ export interface UnsafeNamespace {
13
+ /**
14
+ * Evaluate arbitrary JavaScript in the webview context.
15
+ * Fire-and-forget — there is no return value.
16
+ * Use `postMessage`/`onMessage` to send results back.
17
+ *
18
+ * @security **Injection risk.** Never pass unsanitized user input directly.
19
+ * Use {@link sanitizeForJs} to escape strings before embedding them in
20
+ * script code.
21
+ */
22
+ evaluateJs(script: string): void;
23
+ }
24
+ /**
25
+ * Control the browser devtools panel for this window's webview.
26
+ * Grouped under {@link NativeWindow.devtools} for discoverability.
27
+ *
28
+ * Requires `devtools: true` in {@link WindowOptions} at window creation.
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * const win = new NativeWindow({ devtools: true });
33
+ * win.devtools.open();
34
+ * console.log(win.devtools.isOpen()); // true
35
+ * win.devtools.close();
36
+ * ```
37
+ */
38
+ export interface DevtoolsNamespace {
39
+ /** Open the browser devtools panel. */
40
+ open(): void;
41
+ /** Close the browser devtools panel. */
42
+ close(): void;
43
+ /** Check whether the devtools panel is currently open. */
44
+ isOpen(): boolean;
45
+ }
46
+ /**
47
+ * Information about a cookie from the native cookie store.
48
+ * Includes `HttpOnly` cookies that are invisible to `document.cookie`.
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * win.onCookies((cookies) => {
53
+ * for (const c of cookies) {
54
+ * console.log(c.name, c.value, c.httpOnly);
55
+ * }
56
+ * });
57
+ * win.getCookies("https://example.com");
58
+ * ```
59
+ */
60
+ export interface CookieInfo {
61
+ /** Cookie name. */
62
+ name: string;
63
+ /** Cookie value. */
64
+ value: string;
65
+ /** Domain the cookie belongs to. */
66
+ domain: string;
67
+ /** Path the cookie is restricted to. */
68
+ path: string;
69
+ /** Whether the cookie is HttpOnly (inaccessible to JS). */
70
+ httpOnly: boolean;
71
+ /** Whether the cookie requires HTTPS. */
72
+ secure: boolean;
73
+ /** SameSite policy: "none", "lax", or "strict". */
74
+ sameSite: string;
75
+ /** Expiry as Unix timestamp (seconds). -1 for session cookies. */
76
+ expires: number;
77
+ }
78
+ type WindowOptions = import('../native-window.js').WindowOptions;
79
+ /**
80
+ * A native OS window with an embedded webview.
81
+ *
82
+ * Automatically initializes the native subsystem and starts pumping
83
+ * events on first construction. Stops the pump when all windows close.
84
+ */
85
+ export declare class NativeWindow {
86
+ /** @internal */
87
+ private _native;
88
+ /** @internal */
89
+ private _closed;
90
+ /** @internal */
91
+ private _unsafe?;
92
+ /** @internal */
93
+ private _devtools?;
94
+ constructor(options?: WindowOptions);
95
+ /** @internal */
96
+ private _handleClose;
97
+ /**
98
+ * Throws if the window has been closed.
99
+ * @internal
100
+ */
101
+ private _ensureOpen;
102
+ private _userCloseCallback?;
103
+ /**
104
+ * Register a handler for the window close event.
105
+ * The pump is automatically stopped when all windows are closed.
106
+ *
107
+ * Calling this multiple times replaces the previous handler.
108
+ */
109
+ onClose(callback: () => void): void;
110
+ /** Unique window ID */
111
+ get id(): number;
112
+ loadUrl(url: string): void;
113
+ /**
114
+ * Load raw HTML content into the webview.
115
+ *
116
+ * @security **Injection risk.** Never interpolate unsanitized user input
117
+ * into HTML strings. Use a dedicated sanitization library such as
118
+ * [DOMPurify](https://github.com/cure53/DOMPurify) or
119
+ * [sanitize-html](https://github.com/apostrophecms/sanitize-html) to
120
+ * sanitize untrusted content before embedding it.
121
+ */
122
+ loadHtml(html: string): void;
123
+ postMessage(message: string): void;
124
+ /**
125
+ * Namespace for operations that require extra care to avoid injection risks.
126
+ * Methods under `unsafe` execute arbitrary code in the webview context.
127
+ *
128
+ * @security Never pass unsanitized user input to these methods.
129
+ * Use {@link sanitizeForJs} to escape strings before embedding them in
130
+ * script code.
131
+ */
132
+ get unsafe(): UnsafeNamespace;
133
+ /**
134
+ * Namespace for controlling the browser devtools panel.
135
+ * Requires `devtools: true` in {@link WindowOptions} at window creation.
136
+ *
137
+ * @example
138
+ * ```ts
139
+ * const win = new NativeWindow({ devtools: true });
140
+ * win.devtools.open();
141
+ * console.log(win.devtools.isOpen()); // true
142
+ * win.devtools.close();
143
+ * ```
144
+ */
145
+ get devtools(): DevtoolsNamespace;
146
+ setTitle(title: string): void;
147
+ setSize(width: number, height: number): void;
148
+ setMinSize(width: number, height: number): void;
149
+ setMaxSize(width: number, height: number): void;
150
+ setPosition(x: number, y: number): void;
151
+ setResizable(resizable: boolean): void;
152
+ setDecorations(decorations: boolean): void;
153
+ setAlwaysOnTop(alwaysOnTop: boolean): void;
154
+ /**
155
+ * Set the window icon from a PNG or ICO file path.
156
+ * On macOS this is silently ignored (macOS doesn't support per-window icons).
157
+ * Relative paths resolve from the working directory.
158
+ */
159
+ setIcon(path: string): void;
160
+ show(): void;
161
+ hide(): void;
162
+ close(): void;
163
+ focus(): void;
164
+ maximize(): void;
165
+ minimize(): void;
166
+ unmaximize(): void;
167
+ reload(): void;
168
+ /**
169
+ * Register a handler for messages from the webview.
170
+ *
171
+ * @security **No origin filtering.** The raw `onMessage` API does not
172
+ * enforce origin restrictions. If your webview navigates to untrusted
173
+ * URLs, validate the `sourceUrl` parameter before processing messages.
174
+ * For automatic origin filtering, use `createChannel()` with the
175
+ * `trustedOrigins` option from `native-window-ipc`.
176
+ *
177
+ * @security **No rate limiting.** Messages from the webview are delivered
178
+ * without throttling. A malicious page can flood the host with messages.
179
+ * Consider implementing application-level rate limiting if loading
180
+ * untrusted content.
181
+ */
182
+ onMessage(callback: (message: string, sourceUrl: string) => void): void;
183
+ onResize(callback: (width: number, height: number) => void): void;
184
+ onMove(callback: (x: number, y: number) => void): void;
185
+ onFocus(callback: () => void): void;
186
+ onBlur(callback: () => void): void;
187
+ onPageLoad(callback: (event: "started" | "finished", url: string) => void): void;
188
+ onTitleChanged(callback: (title: string) => void): void;
189
+ onReload(callback: () => void): void;
190
+ /**
191
+ * Register a handler for blocked navigation events.
192
+ * Fired when a navigation is blocked by the {@link WindowOptions.allowedHosts}
193
+ * restriction. Receives the URL that was blocked.
194
+ *
195
+ * @example
196
+ * ```ts
197
+ * win.onNavigationBlocked((url) => {
198
+ * console.log("Blocked navigation to:", url);
199
+ * });
200
+ * ```
201
+ */
202
+ onNavigationBlocked(callback: (url: string) => void): void;
203
+ /**
204
+ * Validate and parse a raw cookies JSON array from the native layer.
205
+ * Returns a cleaned {@link CookieInfo} array or `null` if the payload
206
+ * is malformed.
207
+ *
208
+ * @internal
209
+ */
210
+ private _validateCookies;
211
+ /**
212
+ * Query cookies from the native cookie store.
213
+ *
214
+ * Returns a Promise that resolves with validated {@link CookieInfo} objects,
215
+ * including `HttpOnly` cookies that are invisible to `document.cookie`.
216
+ *
217
+ * - **macOS**: Uses `WKHTTPCookieStore.getAllCookies` with client-side
218
+ * URL filtering (domain + path match).
219
+ * - **Windows**: Uses `ICoreWebView2CookieManager.GetCookies` which
220
+ * filters by URI natively.
221
+ *
222
+ * @param url If provided, only cookies matching this URL are returned.
223
+ * If omitted, all cookies in the webview's cookie store are returned.
224
+ *
225
+ * @example
226
+ * ```ts
227
+ * const cookies = await win.getCookies("https://example.com");
228
+ * const session = cookies.find((c) => c.name === "session_id");
229
+ * if (session) console.log("Session:", session.value, "HttpOnly:", session.httpOnly);
230
+ * ```
231
+ */
232
+ getCookies(url?: string): Promise<CookieInfo[]>;
233
+ /**
234
+ * Clear cookies from the native cookie store.
235
+ *
236
+ * - If `host` is provided, only cookies whose domain matches that host
237
+ * are deleted (e.g. `"example.com"` deletes `.example.com` cookies).
238
+ * - If omitted, all cookies in the webview's cookie store are cleared.
239
+ *
240
+ * @example
241
+ * ```ts
242
+ * // Clear all cookies
243
+ * win.clearCookies();
244
+ *
245
+ * // Clear cookies for a specific host
246
+ * win.clearCookies("example.com");
247
+ * ```
248
+ */
249
+ clearCookies(host?: string): void;
250
+ }
251
+ /**
252
+ * Escape a string for safe embedding inside a JavaScript string literal.
253
+ * Handles backslashes, double quotes, newlines, carriage returns, null
254
+ * bytes, closing `</script>` tags, Unicode line/paragraph separators
255
+ * (U+2028, U+2029), backticks, and `${` template expressions.
256
+ *
257
+ * Safe for use in double-quoted, single-quoted, and template literal
258
+ * contexts.
259
+ *
260
+ * @example
261
+ * ```ts
262
+ * import { NativeWindow, sanitizeForJs } from "native-window";
263
+ *
264
+ * const userInput = 'He said "hello"\n<script>alert(1)</script>';
265
+ * win.unsafe.evaluateJs(`display("${sanitizeForJs(userInput)}")`);
266
+ * ```
267
+ */
268
+ export declare function sanitizeForJs(input: string): string;