opentray 0.5.1 → 0.6.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.
package/README.md CHANGED
@@ -34,7 +34,7 @@ const space = await createSpace({ id: "com.example.status", default: true });
34
34
  await space.createTray({
35
35
  trayId: "status",
36
36
  title: "Status",
37
- icon: { type: "rgba", data: [0, 0, 0, 0], width: 1, height: 1 },
37
+ icon: { type: "file", path: "./assets/tray-icon.png" },
38
38
  });
39
39
 
40
40
  const defaultSpace = await resolveDefaultSpace();
@@ -42,7 +42,7 @@ await createTray(
42
42
  {
43
43
  trayId: "secondary",
44
44
  title: "Secondary",
45
- icon: { type: "rgba", data: [0, 0, 0, 0], width: 1, height: 1 },
45
+ icon: { type: "file", path: "./assets/tray-icon.png" },
46
46
  },
47
47
  { space: defaultSpace.space }
48
48
  );
@@ -60,11 +60,34 @@ Run the direct webview control demo:
60
60
 
61
61
  ```bash
62
62
  pnpm --filter opentray example:webview-control
63
+ pnpm --filter opentray example:webview-control -- --overlay
64
+ pnpm --filter opentray example:webview-control -- --no-overlay
63
65
  ```
64
66
 
65
- That demo opens a native WebView window immediately and puts the controls inside the page itself, so you can exercise frameless, transparent, keep-on-top, title, icon, screen, and navigation behavior without going through the tray menu first.
67
+ That demo opens a native WebView window immediately and puts the controls inside the page itself, so you can exercise frameless, background modes, keep-on-top, title, icon, screen, overlay, and navigation behavior without going through the tray menu first. The control demo enables the show-time `windowControlsOverlay` capability by default; use `-- --no-overlay` when you want to test the disabled path.
66
68
  Treat `example:webview-control` as the API exercise surface. It is useful for probing capabilities and events, but it is not the canonical recipe for a tray-anchored glass shell.
67
69
 
70
+ Application code mounts WebView as a tray capability. The first WebView command loads the native extension automatically; ordinary code does not need to send `load-ext` manually:
71
+
72
+ ```ts
73
+ import { WebviewExt } from "@opentray/ext-webview";
74
+ import { createTray } from "opentray";
75
+
76
+ const tray = (await createTray({
77
+ trayId: "status",
78
+ title: "Status",
79
+ icon: { type: "file", path: "./tray-icon.png" },
80
+ })).extend(WebviewExt);
81
+
82
+ const panel = tray.createWebviewWindow({
83
+ html: "<main>Status</main>",
84
+ width: 360,
85
+ height: 240,
86
+ });
87
+
88
+ await panel.show();
89
+ ```
90
+
68
91
  Run the dedicated tray-panel demo:
69
92
 
70
93
  ```bash
@@ -73,8 +96,8 @@ pnpm --filter opentray example:tray-panel
73
96
  ```
74
97
 
75
98
  This demo is the canonical custom TrayPanel case: one `primaryEvent` tray item, backend `tray.getBounds()`, page `navigator.opentray.tray.getBounds()`, screen-aware repositioning, and a frameless glass panel with `keepOnTop`.
76
- It also follows the native-glass rule strictly: transparent native window background, no root HTML shell styling, and content padding only inside the page.
77
- It now also pins `style.platform.macos.materialState: "active"` so the tray-launched material surface does not immediately fall back to the inactive grey AppKit appearance.
99
+ It also follows the native-glass rule strictly: material background through `style.background`, no root HTML shell styling, and content padding only inside the page.
100
+ On macOS it requests `{ kind: "platformMaterial", material: "hudWindow", state: "active" }` so the tray-launched material surface does not immediately fall back to the inactive grey AppKit appearance. On Windows it uses `background: "mica"` and `cornerPreference: "round"` instead of sending macOS-only style.
78
101
  For a step-by-step walkthrough of the examples and expected behavior, read [examples/EXAMPLE.md](./examples/EXAMPLE.md).
79
102
 
80
103
  ## Release Channels And Maturity
@@ -87,20 +110,23 @@ OpenTray uses release channels and capability maturity together. Do not read a p
87
110
  Current WebView truth:
88
111
 
89
112
  - macOS is the current `stable` human-visible acceptance path
90
- - Windows and Linux are currently `alpha` for WebView runtime behavior, even though their platform packages are published
113
+ - Windows is the current `stable` WebView2-backed human-visible acceptance path for common bridge/window controls, background material/corner preferences, and native icon projection
114
+ - Linux remains supported by the OpenTray core daemon/packages, but `@opentray/ext-webview` does not publish Linux native WebView packages
91
115
  - some requests are `unsupported by design`, such as asking the macOS runtime to apply a Windows-only style family
92
116
  - some results are `unavailable by context`, such as tray-bounds projection when the current session has no authoritative tray anchor
93
117
 
94
- When run from the repo worktree, the example automatically discovers `target/debug` or `target/release` `libopentray_ext_webview` and wires it through `OPENTRAY_EXT_PATH` before starting the daemon. That keeps the example on the real `load-ext` path without requiring a manual staging step for routine source-level testing.
118
+ When run from the repo worktree, the example automatically discovers `target/debug` or `target/release` `libopentray_ext_webview` and wires it through `OPENTRAY_EXT_PATH` before starting the daemon. The WebView mount still exercises the real generic extension loader, but example users do not author a manual `load-ext` request.
95
119
 
96
- After installing from npm, use the published CLI smoke path instead of workspace scripts:
120
+ The published CLI is intentionally small and only owns daemon lifecycle and health:
97
121
 
98
122
  ```bash
99
- opentray smoke daemon-tray
100
- opentray smoke daemon-lynx
123
+ opentray daemon health
124
+ opentray daemon start
125
+ opentray daemon stop
126
+ opentray daemon restart
101
127
  ```
102
128
 
103
- `opentray smoke daemon-lynx` now uses the package-owned review bundle by default so a fresh npm install can perform the final visual audit without a workspace checkout. Keep `--bundle <path-to-main.lynx.bundle>` only when you want to override that official audit asset with a custom bundle.
129
+ Visual smoke is a real runtime activity, not a daemon CLI subcommand. It may auto-start or reuse the same-version daemon, write runtime coordination files under `$OPENTRAY_HOME/.opentray/<package-version>/runtime` or the user's home directory when `OPENTRAY_HOME` is unset, create a visible tray item, load native extension packages, and open real WebView/Lynx windows. Use the `opentray` skill or source-tree examples to orchestrate those checks, and run `opentray daemon stop` if you want immediate daemon cleanup or if a smoke process was interrupted.
104
130
 
105
131
  This example starts or reuses the same-version daemon automatically, creates a real tray through the public SDK, and prints broker-routed menu events. Use manual lifecycle commands only for operator/debug control:
106
132
 
@@ -118,7 +144,7 @@ The host side of that example can call `await tray.getBounds()` to read the curr
118
144
 
119
145
  The opened WebView also enables the injected page bridge so the rendered page can call `navigator.window` / `navigator.opentrayWindow` and, for the demo only, opt into `window.close()` / `window.moveTo()` / `window.resizeTo()` overrides. Use the in-page buttons to verify `getCapabilities`, `getStyle`, `setStyle({ frameless })`, move, resize, close, and tray-bounds behavior visually instead of relying only on terminal logs.
120
146
 
121
- The Lynx smoke path uses the same generic extension loader but launches a real `OpenTrayLynxRuntime.app.zip` sidecar from `@opentray/ext-lynx-darwin-*`. It starts the requested `.lynx.bundle` in a fixed host shell, sets an initial title and icon, applies an explicit startup feature expression, and exposes `Show Window`, `Hide Window`, and `Quit Smoke` through tray-routed events. Inside the Lynx window, use the rendered controls to verify `getCapabilities`, `getStyle`, `getTitle`, `setTitle`, `getIcon`, `setIcon`, `navigator.screen.getScreenDetails()`, `resizeTo`, `moveTo`, frameless toggling, `window.resizeTo()`, `window.getScreenDetails()`, and close behavior visually. On macOS, the runtime Dock icon should no longer appear blank.
147
+ The Lynx example path uses the same generic extension loader but launches a real `OpenTrayLynxRuntime.app.zip` sidecar from `@opentray/ext-lynx-darwin-*`. It starts the requested `.lynx.bundle` in a fixed host shell, sets an initial title and icon, applies an explicit startup feature expression, and exposes `Show Window`, `Hide Window`, and `Quit Smoke` through tray-routed events. Inside the Lynx window, use the rendered controls to verify `getCapabilities`, `getStyle`, `getTitle`, `setTitle`, `getIcon`, `setIcon`, `navigator.screen.getScreenDetails()`, `resizeTo`, `moveTo`, frameless toggling, `window.resizeTo()`, `window.getScreenDetails()`, and close behavior visually. On macOS, the runtime Dock icon should no longer appear blank.
122
148
 
123
149
  For Lynx, `frameless` currently means borderless only. It does not imply a full-window drag region, because that would steal clicks from the page content. When isolating host-feature regressions, `--features "*,!frameless"` is the fastest way to keep the bridge on while removing the borderless shell from the test.
124
150
 
@@ -130,9 +156,9 @@ pnpm run smoke:lynx -- --run <github-actions-run-id> --bundle packages/cli/asset
130
156
  pnpm run smoke:lynx -- --run <github-actions-run-id> --bundle packages/cli/assets/lynx-review/main.lynx.bundle --features "*,!nativeScreenApi"
131
157
  ```
132
158
 
133
- The package-owned review bundle is the full human acceptance surface. The separate `input-probe.lynx.bundle` is only a low-level diagnostic asset for isolating raw click/scroll/input delivery. The empty feature set is the baseline carrier check. Use it to validate the physical window baseline: click, scroll, input, red/yellow/green controls, and resize/move. Only after that baseline is healthy should you validate explicit startup feature sets on top of the same carrier.
159
+ The workspace review bundle is the full human acceptance surface. The separate `input-probe.lynx.bundle` is only a low-level diagnostic asset for isolating raw click/scroll/input delivery. The empty feature set is the baseline carrier check. Use it to validate the physical window baseline: click, scroll, input, red/yellow/green controls, and resize/move. Only after that baseline is healthy should you validate explicit startup feature sets on top of the same carrier.
134
160
 
135
- First-stage platform packages are published for macOS, Linux, and Windows. macOS is the current human-visual acceptance path. Linux and Windows artifacts are present for package topology validation, but unsupported broker/WebView capability must fail explicitly rather than pretending a visible UI exists. Lynx is intentionally macOS-first for now and should fail honestly on other platforms instead of pretending the runtime exists.
161
+ First-stage core daemon platform packages are published for macOS, Linux, and Windows. macOS and Windows are stable WebView human-visual acceptance paths for common window and bridge commands plus native material projection. Linux is not an official `@opentray/ext-webview` runtime target. Lynx is intentionally macOS-first for now and should fail honestly on other platforms instead of pretending the runtime exists.
136
162
 
137
163
  If you are validating the current prerelease branch before stable publication, install from the alpha channel and treat that as alpha evidence rather than stable evidence:
138
164
 
@@ -140,7 +166,7 @@ If you are validating the current prerelease branch before stable publication, i
140
166
  npm i opentray@alpha
141
167
  ```
142
168
 
143
- For local native smoke before npm publish, stage the current platform artifacts first:
169
+ For local native smoke before npm publish, stage the current platform artifacts first and run source-tree examples:
144
170
 
145
171
  ```bash
146
172
  cargo build -p opentray-bin -p opentray-ext-webview -p opentray-ext-lynx
@@ -149,8 +175,8 @@ bun run scripts/binaries/stage-local.ts --kind webview --source target/debug/lib
149
175
  bun run scripts/binaries/stage-local.ts --kind lynx --source target/debug/libopentray_ext_lynx.dylib
150
176
  bash scripts/release/build-lynx-runtime.sh /tmp/OpenTrayLynxRuntime.app.zip
151
177
  bun run scripts/binaries/stage-local.ts --kind lynx-runtime --source /tmp/OpenTrayLynxRuntime.app.zip
152
- OPENTRAY_EXAMPLE_WEBVIEW_SMOKE=1 pnpm --filter opentray cli -- smoke daemon-tray
153
- pnpm --filter opentray cli -- smoke daemon-lynx
178
+ OPENTRAY_EXAMPLE_WEBVIEW_SMOKE=1 pnpm --filter opentray example:daemon-tray
179
+ pnpm --filter opentray example:daemon-lynx -- --bundle packages/cli/assets/lynx-review/main.lynx.bundle
154
180
  ```
155
181
 
156
182
  During source-level daemon work, restart the daemon with the freshly built broker binary before testing tray behavior. Otherwise the CLI may reuse the already staged same-version daemon:
@@ -158,7 +184,7 @@ During source-level daemon work, restart the daemon with the freshly built broke
158
184
  ```bash
159
185
  cargo build -p opentray-bin
160
186
  OPENTRAY_BROKER_BIN="$PWD/target/debug/opentray" pnpm --filter opentray cli -- daemon restart
161
- OPENTRAY_BROKER_BIN="$PWD/target/debug/opentray" pnpm --filter opentray cli -- smoke daemon-tray
187
+ OPENTRAY_BROKER_BIN="$PWD/target/debug/opentray" OPENTRAY_EXAMPLE_WEBVIEW_SMOKE=1 pnpm --filter opentray example:daemon-tray
162
188
  ```
163
189
 
164
190
  The daemon exits automatically after 30 seconds with no connected clients. Set `OPENTRAY_DAEMON_IDLE_TIMEOUT_MS=0` to keep it alive during debugging, or provide another millisecond value for a custom idle release window.
@@ -175,4 +201,4 @@ otool -L target/release/libopentray_ext_webview.dylib
175
201
  otool -L target/release/libopentray_ext_lynx.dylib
176
202
  ```
177
203
 
178
- Current native icon support is `rgba`. `encoded` and `file` are typed protocol shapes, but the native `tray-icon` backend reports them as unsupported until decoding and file loading policy are implemented.
204
+ The native `tray-icon` backend now normalizes `encoded` and `file` icon inputs into RGBA before native tray materialization. `rgba` still works when you already have pixel data, but ordinary app code can point at a PNG file instead of hand-building pixels.
package/dist/cli.d.mts CHANGED
@@ -4,14 +4,6 @@ import { DaemonHealth } from "@opentray/spec";
4
4
  type CliCommand = {
5
5
  type: "daemon";
6
6
  action: "start" | "stop" | "restart" | "health";
7
- } | {
8
- type: "smoke";
9
- name: "daemon-tray";
10
- } | {
11
- type: "smoke";
12
- name: "daemon-lynx";
13
- bundlePath?: string;
14
- featureExpression?: string;
15
7
  } | {
16
8
  type: "help";
17
9
  };
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.mts","names":[],"sources":["../src/cli.ts"],"mappings":";;;KAuBK,UAAA;EACC,IAAA;EAAgB,MAAA;AAAA;EAChB,IAAA;EAAe,IAAA;AAAA;EAEf,IAAA;EACA,IAAA;EACA,UAAA;EACA,iBAAA;AAAA;EAEA,IAAA;AAAA;AAAA,cAEO,eAAA,GAAmB,IAAA,eAAiB,UA+BhD;AAAA,cAEY,MAAA,GAAgB,IAAA,eAAiB,OAAO;AAAA,cAwGxC,wBAAA,GAA4B,MAAoB,EAAZ,YAAY;AAAA,cAoBhD,eAAA,GACX,aAAA,sBACA,UAAkB"}
1
+ {"version":3,"file":"cli.d.mts","names":[],"sources":["../src/cli.ts"],"mappings":";;;KAqBK,UAAA;EACC,IAAA;EAAgB,MAAA;AAAA;EAChB,IAAA;AAAA;AAAA,cAEO,eAAA,GAAmB,IAAA,eAAiB,UAehD;AAAA,cAEY,MAAA,GAAgB,IAAA,eAAiB,OAAO;AAAA,cAiFxC,wBAAA,GAA4B,MAAoB,EAAZ,YAAY;AAAA,cAoBhD,eAAA,GACX,aAAA,sBACA,UAAkB"}