@nativedesktop/react 0.1.1 → 0.2.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.
@@ -1,5 +1,5 @@
1
1
  export declare const NDP_VERSION = 1;
2
- export type WidgetName = "Window" | "Box" | "Label" | "Button" | "TextInput" | "TextArea" | "Checkbox" | "Radio" | "Select" | "Slider" | "ProgressBar" | "Image" | "ScrollView" | "Separator" | "Spinner" | "TabView" | "Grid" | "ListView" | "WebView" | "NativeView" | "SplitView" | "HeaderBar" | "ToolbarView" | "SearchInput" | "SourceList" | "SourceTree" | "Menubar" | "Menu" | "MenuItem" | "SettingsGroup" | "Row" | "SwitchRow" | "Clamp" | "Switch" | "ToggleButton" | "SegmentedControl" | "NumberInput" | "LinkButton" | "LevelIndicator" | "ColorPicker" | "Banner" | "MenuButton" | "SplitButton" | "Popover" | "Expander" | "StatusPage" | "ToastOverlay" | "DatePicker" | "Table" | "TreeView" | "FontPicker" | "Video" | "TrayItem" | "ShareButton" | "Terminal" | "Paned" | "CommandPalette";
2
+ export type WidgetName = "Window" | "Box" | "Label" | "Button" | "TextInput" | "TextArea" | "Checkbox" | "Radio" | "Select" | "Slider" | "ProgressBar" | "Image" | "ScrollView" | "Separator" | "Spinner" | "TabView" | "Grid" | "ListView" | "WebView" | "NativeView" | "SplitView" | "HeaderBar" | "ToolbarView" | "SearchInput" | "SourceList" | "SourceTree" | "Menubar" | "Menu" | "MenuItem" | "SettingsGroup" | "Row" | "SwitchRow" | "Clamp" | "Switch" | "ToggleButton" | "SegmentedControl" | "NumberInput" | "LinkButton" | "LevelIndicator" | "ColorPicker" | "Banner" | "MenuButton" | "SplitButton" | "Popover" | "Expander" | "StatusPage" | "ToastOverlay" | "DatePicker" | "Table" | "TreeView" | "FontPicker" | "Video" | "TrayItem" | "ShareButton" | "Terminal" | "Paned" | "CommandPalette" | "Avatar" | "Badge" | "Tag" | "Kbd" | "ComboBox" | "Breadcrumb" | "Dialog" | "Sheet" | "RichText" | "ProgressCircle" | "Skeleton" | "Chart" | "CodeEditor";
3
3
  /** Child runtime identity, carried inside the hello frame. */
4
4
  export interface Runtime {
5
5
  name: string;
@@ -5,12 +5,14 @@ export interface Geometry {
5
5
  w: number;
6
6
  h: number;
7
7
  }
8
- /** SourceList's per-row shape on the wire (M11 SourceList Wave 1) — camelCase iconName, matching the schema prop shape. testID carries SourceTree's per-node testID (null for SourceList rows, which have none). */
8
+ /** The per-row shape on the wire, shared by every row-driven widget (SourceList `items`, SourceTree `nodes`, CommandPalette `items`) — camelCase iconName, matching the schema prop shape. testID carries SourceTree's per-node testID (null for SourceList rows, which have none); id and subtitle carry the row's own identity and secondary line where the widget's item type has them (CommandPaletteItem, SourceTreeNode), so a drive can name a row instead of counting to it. */
9
9
  export interface RowJson {
10
10
  title: string;
11
11
  badge: string | null;
12
12
  iconName: string | null;
13
13
  testID: string | null;
14
+ id: string | null;
15
+ subtitle: string | null;
14
16
  }
15
17
  /** One tree-snapshot node. itemCount is ListView's row count (M5c-D4), null for every widget that isn't data-driven; rows is SourceList's ordered row data, null for every widget that isn't row-driven. role/enabled/focused/value are the accessibility-tree fields (M16): role is the widget's schema-declared automation role (null when the type declares none); enabled/focused/value come from a live per-node backend probe and default to true/false/null on backends without the probe. */
16
18
  export interface JsonNode {
@@ -62,7 +64,7 @@ export interface ScrollResult {
62
64
  x: number;
63
65
  y: number;
64
66
  }
65
- /** Exactly one selector: textContains | refVisible | testId. With testId, `state` (default "present", one of present|gone|visible|enabled|disabled|focused) picks the predicate and countAtLeast/valueEquals/valueContains refine it. valueEquals/valueContains compare against the node's a11y value STRING RENDERING (numbers stringified, bools "true"/"false") so one predicate works for TextInput and Slider alike. Every predicate is evaluated host-side on the retained tree plus the live a11y probe, once per ~50ms tick — never a getTree round trip. */
67
+ /** Exactly one selector: textContains | refVisible | testId. With testId, `state` (default "present", one of present|gone|visible|enabled|disabled|focused) picks the predicate and countAtLeast/valueEquals/valueContains refine it. valueEquals/valueContains compare against the node's a11y value STRING RENDERING (numbers stringified, bools "true"/"false") so one predicate works for TextInput and Slider alike. urlContains/pageTitleContains/pageTextContains are PAGE predicates and refine a testId selector the same way; the node they name must be a WebView. url and title come from the engine directly, but pageTextContains INJECTS JAVASCRIPT (document.body.innerText) into the page world, re-probed at most once per 250ms and matched against the last answer — so a match can lag the page by one probe. Every predicate is evaluated host-side on the retained tree plus the live probes, once per ~50ms tick — never a getTree round trip. */
66
68
  export interface WaitCondition {
67
69
  textContains?: string;
68
70
  refVisible?: number;
@@ -71,6 +73,9 @@ export interface WaitCondition {
71
73
  countAtLeast?: number;
72
74
  valueEquals?: string;
73
75
  valueContains?: string;
76
+ urlContains?: string;
77
+ pageTitleContains?: string;
78
+ pageTextContains?: string;
74
79
  }
75
80
  export interface ResolveResult {
76
81
  ref: number | null;
@@ -104,6 +109,22 @@ export interface DragResult {
104
109
  export interface KeysResult {
105
110
  dispatched: boolean;
106
111
  }
112
+ /** Live page state read off the engine on the UI thread (WebKitGTK's uri/title/is-loading/can-go-back/can-go-forward, WKWebView's url/title/isLoading/canGoBack/canGoForward) — no page JavaScript, no app cooperation. url/title are null before the first commit. */
113
+ export interface WebViewInfo {
114
+ ref: number;
115
+ url: string | null;
116
+ title: string | null;
117
+ loading: boolean;
118
+ canGoBack: boolean;
119
+ canGoForward: boolean;
120
+ }
121
+ /** `value` is the result's STRING rendering (the engine's own JSValue-to-string), the same shape the javaScriptResult event carries — never a typed JSON value. On a thrown exception `ok` is false and `error` carries the engine's message. */
122
+ export interface WebViewEvalResult {
123
+ ref: number;
124
+ ok: boolean;
125
+ value: string | null;
126
+ error: string | null;
127
+ }
107
128
  /** Full tree snapshot with stable refs, testIDs, text, logical geometry, and accessibility state (role/enabled/focused/value). window (if given) must be a Window node ref and scopes the snapshot to that window's subtree; absent, the root/first window is used and other windows' nodes attach as orphans. */
108
129
  export interface GetTreeParams {
109
130
  window?: number;
@@ -181,6 +202,21 @@ export interface PointerParams {
181
202
  clickCount?: number;
182
203
  window?: number;
183
204
  }
205
+ /** Live page state for a WebView node: {url, title, loading, canGoBack, canGoForward}. Read straight off the engine, so a drive can assert what a page did without the app forwarding its navigate/titleChanged events. Target by exactly one of ref / testId (window optionally scopes testId resolution); a target that is not a WebView answers -32602. */
206
+ export interface WebviewInfoParams {
207
+ ref?: number;
208
+ testId?: string;
209
+ window?: number;
210
+ }
211
+ /** Evaluates `code` in a WebView node's page and answers the result's string rendering. `world` picks an isolated content world by name (absent/empty = the page's own world), matching the executeJavaScript command. The engine's evaluation is asynchronous: the host starts it, then polls its own UI thread until it settles or timeoutMs elapses (-32002). A thrown exception is a RESULT with ok:false, not an RPC error. Target by exactly one of ref / testId; a target that is not a WebView answers -32602. */
212
+ export interface WebviewEvalParams {
213
+ ref?: number;
214
+ testId?: string;
215
+ window?: number;
216
+ code: string;
217
+ world?: string;
218
+ timeoutMs?: number;
219
+ }
184
220
  /** Press-move-release gesture. Endpoints are widget refs (their centers; fromRef/toRef must share a window) or explicit coordinates (fromX/fromY/toX/toY in the target window, default root). The full down/dragged.../up sequence is posted as one batch so native mouse-tracking loops (slider thumbs, split dividers) consume it like a real drag. Unsupported on GTK (-32003). */
185
221
  export interface DragParams {
186
222
  fromRef?: number;
@@ -252,6 +288,14 @@ export interface RpcMethods {
252
288
  params: PointerParams;
253
289
  result: PointerResult;
254
290
  };
291
+ webviewInfo: {
292
+ params: WebviewInfoParams;
293
+ result: WebViewInfo;
294
+ };
295
+ webviewEval: {
296
+ params: WebviewEvalParams;
297
+ result: WebViewEvalResult;
298
+ };
255
299
  drag: {
256
300
  params: DragParams;
257
301
  result: DragResult;
@@ -8,7 +8,7 @@ export declare const intrinsicToName: Record<string, string>;
8
8
  export interface WidgetEvent {
9
9
  name: string;
10
10
  handler: string;
11
- payload: "none" | "text" | "checked" | "value" | "index" | "data";
11
+ payload: "none" | "text" | "checked" | "value" | "index" | "indexes" | "data" | "position" | "dragPoint";
12
12
  }
13
13
  export declare const widgetEvents: Record<string, WidgetEvent[]>;
14
14
  export declare const handlerPropNames: Record<string, string[]>;
@@ -18,9 +18,20 @@ export declare const widgetCommands: Record<string, readonly string[]>;
18
18
  /** Compile-time command-name map (only widgets with commands appear). */
19
19
  export type WidgetCommandNames = {
20
20
  "window": "showAlert" | "openFile" | "saveFile" | "showAbout" | "showTabOverview" | "present";
21
- "webview": "goBack" | "goForward" | "reload" | "stop" | "executeJavaScript" | "setZoom" | "setUserAgent" | "openDevTools";
21
+ "button": "focus";
22
+ "textinput": "focus";
23
+ "textarea": "focus";
24
+ "checkbox": "focus";
25
+ "radio": "focus";
26
+ "select": "focus";
27
+ "webview": "goBack" | "goForward" | "reload" | "stop" | "executeJavaScript" | "setZoom" | "setUserAgent" | "openDevTools" | "addUserScript" | "removeUserScript" | "clearUserScripts" | "registerScriptMessage" | "unregisterScriptMessage" | "respondScheme" | "getCookies" | "setCookie" | "deleteCookie" | "findStart" | "findNext" | "findPrevious" | "findStop" | "saveSession" | "restoreSession" | "setMuted" | "setContextMenuItems" | "focus";
28
+ "searchinput": "focus";
29
+ "switch": "focus";
30
+ "numberinput": "focus";
22
31
  "toastoverlay": "showToast" | "dismissToast";
23
32
  "terminal": "copy" | "paste" | "selectAll" | "clearSelection" | "focus";
33
+ "combobox": "focus";
34
+ "codeeditor": "focus";
24
35
  };
25
36
  /** Platform availability (schema `platforms`): null = every platform. A
26
37
  * widget listing only some platforms renders natively there and is an
@@ -7,16 +7,17 @@ export type { SpacingScale } from "./metrics.ts";
7
7
  export { getAppDataDir, ensureAppDataDir } from "./paths.ts";
8
8
  export { defineNativeComponent } from "./native-component.ts";
9
9
  export type { NativeComponentOptions, NativeComponentProps, NativeComponentRef } from "./native-component.ts";
10
- export { executeJavaScript, onJavaScriptResult } from "./webview.ts";
10
+ export { executeJavaScript, onJavaScriptResult, getCookies, onCookiesResult, saveSession, onSessionSaved, setContextMenuItems, } from "./webview.ts";
11
+ export type { Cookie, ContextMenuContext, ContextMenuItem, ContextMenuItemClick } from "./webview.ts";
11
12
  export { showAlert, openFile, saveFile, showAbout, showTabOverview, onAlertResult, onOpenFileResult, onSaveFileResult, } from "./dialogs.ts";
12
13
  export type { DialogButton, ShowAlertOptions, AlertResult, OpenFileOptions as WindowOpenFileOptions, OpenFileResult as WindowOpenFileResult, SaveFileOptions as WindowSaveFileOptions, SaveFileResult as WindowSaveFileResult, ShowAboutOptions, } from "./dialogs.ts";
13
14
  export { showToast, dismissToast, onToastButtonClicked, onToastDismissed } from "./toast.ts";
14
15
  export type { ToastPriority, ShowToastOptions, ToastResult } from "./toast.ts";
15
16
  export type { Instance } from "./host-config.ts";
16
- export type { NdNodeRef, WidgetType, TableColumn, TableRow, TreeNode, SourceTreeAction, SourceTreeNode } from "./generated/intrinsics.ts";
17
+ export type { NdNodeRef, WidgetType, TableColumn, TableRow, TreeNode, SourceTreeAction, SourceTreeNode, CommandPaletteItem, ChartPoint, ChartSeries, CodeDiagnostic, } from "./generated/intrinsics.ts";
17
18
  export { performRefresh, registerExports, fullReload } from "./hmr.ts";
18
- export { useState, useEffect, useLayoutEffect, useMemo, useCallback, useRef, useContext, useReducer, useTransition, useDeferredValue, useSyncExternalStore, useId, use, startTransition, memo, forwardRef, createContext, Suspense, Fragment, } from "./dev-react.ts";
19
- export { dialog, clipboard, notifications, recentDocuments, credentials, app, system, audio } from "./system.ts";
19
+ export { useState, useEffect, useLayoutEffect, useMemo, useCallback, useRef, useContext, useReducer, useTransition, useDeferredValue, useSyncExternalStore, useId, use, startTransition, memo, forwardRef, createContext, Suspense, Fragment, Activity, } from "./dev-react.ts";
20
+ export { dialog, clipboard, notifications, recentDocuments, credentials, app, system, audio, webviewEngine } from "./system.ts";
20
21
  export type { FileFilter, OpenFileOptions, SaveFileOptions, MessageLevel, MessageOptions, NotificationOptions, Appearance, AppearanceInfo, AudioPlayOptions, AudioState, AudioStateEvent, AudioSpectrumEvent, } from "./system.ts";
21
22
  export { openExternal, openPath, revealPath } from "./shell.ts";
22
23
  export { onUnhandledError, setUnhandledErrorPolicy } from "./errors.ts";
@@ -126,6 +126,42 @@ export declare const system: {
126
126
  /** Subscribes to system appearance/accent changes. Returns an unsubscribe function. */
127
127
  onAppearanceChange(handler: (info: AppearanceInfo) => void): () => void;
128
128
  };
129
+ export interface RegisterSchemeOptions {
130
+ /**
131
+ * Lets pages read the scheme cross-origin. GTK marks the scheme CORS-enabled
132
+ * on the WebKitSecurityManager; without it a `fetch()` from another origin is
133
+ * refused before any response header is consulted. **AppKit ignores this**
134
+ * (see the asymmetry note on `registerScheme`).
135
+ */
136
+ corsEnabled?: boolean;
137
+ /**
138
+ * Makes the scheme's origins secure contexts, which is what `crypto.subtle`,
139
+ * IndexedDB and service workers require. **GTK only** — WebKit's Cocoa API
140
+ * has no public equivalent.
141
+ */
142
+ secure?: boolean;
143
+ }
144
+ /** Engine-level `<webview>` configuration. `core:webview` is default-granted. */
145
+ export declare const webviewEngine: {
146
+ /**
147
+ * Registers a custom URI scheme (`crx`, `app`, …) with the web engine.
148
+ * Requests for it arrive as the `schemeRequest` event on the `<webview>`
149
+ * that made them, and the app answers with the `respondScheme` command.
150
+ *
151
+ * MUST be called before the first `<webview>` mounts: WebKit binds scheme
152
+ * handlers to a configuration/context that is frozen once a view exists.
153
+ * Calling it later rejects with "registerScheme must be called before the
154
+ * first <webview> mounts".
155
+ *
156
+ * Backend asymmetry: `corsEnabled` and `secure` take effect on GTK only.
157
+ * WebKitGTK exposes a WebKitSecurityManager for both; WebKit's Cocoa API
158
+ * keeps that registry as SPI, so on AppKit the options are accepted and
159
+ * ignored. Cross-origin reads still work there through `respondScheme`'s
160
+ * `Access-Control-Allow-Origin` header — a secure context cannot be granted
161
+ * at all.
162
+ */
163
+ registerScheme(scheme: string, options?: RegisterSchemeOptions): Promise<void>;
164
+ };
129
165
  export interface AudioPlayOptions {
130
166
  path?: string;
131
167
  url?: string;
@@ -1,5 +1,46 @@
1
1
  import type { NdNodeRef } from "./generated/intrinsics.ts";
2
- export declare function executeJavaScript(node: NdNodeRef<"webview">, code: string): Promise<string>;
2
+ export declare function executeJavaScript(node: NdNodeRef<"webview">, code: string, world?: string): Promise<string>;
3
3
  export declare function onJavaScriptResult(e: {
4
4
  data: unknown;
5
5
  }): void;
6
+ export interface Cookie {
7
+ name: string;
8
+ value: string;
9
+ domain: string;
10
+ path: string;
11
+ secure: boolean;
12
+ httpOnly: boolean;
13
+ /** Unix seconds, or null for a session cookie. */
14
+ expires: number | null;
15
+ sameSite: "None" | "Lax" | "Strict";
16
+ }
17
+ export declare function getCookies(node: NdNodeRef<"webview">, url?: string): Promise<Cookie[]>;
18
+ export declare function onCookiesResult(e: {
19
+ data: unknown;
20
+ }): void;
21
+ export declare function saveSession(node: NdNodeRef<"webview">): Promise<string>;
22
+ export declare function onSessionSaved(e: {
23
+ data: unknown;
24
+ }): void;
25
+ export type ContextMenuContext = "all" | "page" | "link" | "image" | "selection" | "editable";
26
+ export interface ContextMenuItem {
27
+ id?: string;
28
+ label?: string;
29
+ type?: "normal" | "checkbox" | "radio" | "separator";
30
+ checked?: boolean;
31
+ enabled?: boolean;
32
+ contexts?: ContextMenuContext[];
33
+ targetUrlGlobs?: string[];
34
+ children?: ContextMenuItem[];
35
+ }
36
+ export interface ContextMenuItemClick {
37
+ id: string;
38
+ pageUrl: string;
39
+ linkUrl?: string;
40
+ imageUrl?: string;
41
+ selectionText?: string;
42
+ editable: boolean;
43
+ checked?: boolean;
44
+ wasChecked?: boolean;
45
+ }
46
+ export declare function setContextMenuItems(node: NdNodeRef<"webview">, items: ContextMenuItem[]): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nativedesktop/react",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/FormalSnake/NativeDesktop#readme",
@@ -11,46 +11,48 @@
11
11
  "directory": "packages/react"
12
12
  },
13
13
  "publishConfig": {
14
- "access": "public"
15
- },
16
- "files": ["dist"],
17
- "main": "./dist/index.js",
18
- "types": "./dist/packages/react/src/index.d.ts",
19
- "exports": {
20
- ".": {
21
- "types": "./dist/packages/react/src/index.d.ts",
22
- "default": "./dist/index.js"
14
+ "access": "public"
23
15
  },
24
- "./jsx-runtime": {
25
- "types": "./dist/packages/react/src/jsx-runtime.d.ts",
26
- "default": "./dist/jsx-runtime.js"
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "main": "./dist/index.js",
20
+ "types": "./dist/packages/react/src/index.d.ts",
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/packages/react/src/index.d.ts",
24
+ "default": "./dist/index.js"
25
+ },
26
+ "./jsx-runtime": {
27
+ "types": "./dist/packages/react/src/jsx-runtime.d.ts",
28
+ "default": "./dist/jsx-runtime.js"
29
+ },
30
+ "./jsx-dev-runtime": {
31
+ "types": "./dist/packages/react/src/jsx-dev-runtime.d.ts",
32
+ "default": "./dist/jsx-dev-runtime.js"
33
+ },
34
+ "./rpc": {
35
+ "types": "./dist/packages/react/src/generated/rpc.d.ts",
36
+ "default": "./dist/generated/rpc.js"
37
+ }
27
38
  },
28
- "./jsx-dev-runtime": {
29
- "types": "./dist/packages/react/src/jsx-dev-runtime.d.ts",
30
- "default": "./dist/jsx-dev-runtime.js"
39
+ "scripts": {
40
+ "build": "rm -rf dist && tsc -p tsconfig.build.json && bun build ./src/index.ts ./src/jsx-runtime.ts ./src/jsx-dev-runtime.ts ./src/generated/rpc.ts --outdir dist --target node --format esm --external react --external react-reconciler --external react-refresh",
41
+ "prepack": "bun run build",
42
+ "prepare": "bun run build"
31
43
  },
32
- "./rpc": {
33
- "types": "./dist/packages/react/src/generated/rpc.d.ts",
34
- "default": "./dist/generated/rpc.js"
44
+ "peerDependencies": {
45
+ "react": "^19.2.7"
46
+ },
47
+ "dependencies": {
48
+ "react-reconciler": "0.33.0",
49
+ "react-refresh": "0.17.0"
50
+ },
51
+ "devDependencies": {
52
+ "@types/react": "19.2.17",
53
+ "@types/react-reconciler": "0.33.0",
54
+ "@types/react-refresh": "0.14.7",
55
+ "react": "19.2.7",
56
+ "typescript": "7.0.2"
35
57
  }
36
- },
37
- "scripts": {
38
- "build": "rm -rf dist && tsc -p tsconfig.build.json && bun build ./src/index.ts ./src/jsx-runtime.ts ./src/jsx-dev-runtime.ts ./src/generated/rpc.ts --outdir dist --target node --format esm --external react --external react-reconciler --external react-refresh",
39
- "prepack": "bun run build",
40
- "prepare": "bun run build"
41
- },
42
- "peerDependencies": {
43
- "react": "^19.2.7"
44
- },
45
- "dependencies": {
46
- "react-reconciler": "0.33.0",
47
- "react-refresh": "0.17.0"
48
- },
49
- "devDependencies": {
50
- "@types/react": "19.2.17",
51
- "@types/react-reconciler": "0.33.0",
52
- "@types/react-refresh": "0.14.7",
53
- "react": "19.2.7",
54
- "typescript": "7.0.2"
55
- }
56
58
  }