opentray 0.5.2 → 0.7.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
@@ -31,10 +31,18 @@ The top-level SDK now exposes the mainline broker-backed path directly:
31
31
  import { createSpace, createTray, resolveDefaultSpace } from "opentray";
32
32
 
33
33
  const space = await createSpace({ id: "com.example.status", default: true });
34
- await space.createTray({
34
+ const tray = await space.createTray({
35
35
  trayId: "status",
36
36
  title: "Status",
37
37
  icon: { type: "file", path: "./assets/tray-icon.png" },
38
+ menu: { items: [{ type: "item", id: 1, title: "Open", primaryEvent: true }] },
39
+ });
40
+
41
+ await tray.setTitle("Status: ready");
42
+ tray.onMenuClick(({ itemId }) => {
43
+ if (itemId === 1) {
44
+ // Open a native menu action or a WebView surface.
45
+ }
38
46
  });
39
47
 
40
48
  const defaultSpace = await resolveDefaultSpace();
@@ -60,9 +68,11 @@ Run the direct webview control demo:
60
68
 
61
69
  ```bash
62
70
  pnpm --filter opentray example:webview-control
71
+ pnpm --filter opentray example:webview-control -- --overlay
72
+ pnpm --filter opentray example:webview-control -- --no-overlay
63
73
  ```
64
74
 
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.
75
+ 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
76
  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
77
 
68
78
  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:
@@ -86,6 +96,26 @@ const panel = tray.createWebviewWindow({
86
96
  await panel.show();
87
97
  ```
88
98
 
99
+ For tray-anchored or screen-aware surfaces, use `WebviewPlacementKit` from `@opentray/ext-webview` instead of hand-authoring raw broker frames or creating a one-off panel abstraction.
100
+
101
+ Run the placement demo when you want to review tray, screen, and edge-aware placement:
102
+
103
+ ```bash
104
+ cargo build -p opentray-bin -p opentray-ext-webview
105
+ pnpm --filter opentray example:placement
106
+ ```
107
+
108
+ This demo follows the `skills/opentray` placement law: extension-owned WebView mounting, continuous `WebviewPlacementKit.watch()`, `applyOnce()`, tray/screen/edge anchors, and a page-owned frameless drag region.
109
+
110
+ Run the media query demo when you want to review responsive native window style and constraints:
111
+
112
+ ```bash
113
+ cargo build -p opentray-bin -p opentray-ext-webview
114
+ pnpm --filter opentray example:mediaQuery
115
+ ```
116
+
117
+ This demo focuses on `styleKit.apply(...)` and `mediaQueryKit.match(...)`. Keep it separate from placement debugging so size/style callbacks do not obscure placement behavior.
118
+
89
119
  Run the dedicated tray-panel demo:
90
120
 
91
121
  ```bash
@@ -94,8 +124,8 @@ pnpm --filter opentray example:tray-panel
94
124
  ```
95
125
 
96
126
  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`.
97
- It also follows the native-glass rule strictly: transparent native window background, no root HTML shell styling, and content padding only inside the page.
98
- 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.
127
+ 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.
128
+ 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.
99
129
  For a step-by-step walkthrough of the examples and expected behavior, read [examples/EXAMPLE.md](./examples/EXAMPLE.md).
100
130
 
101
131
  ## Release Channels And Maturity
@@ -108,20 +138,23 @@ OpenTray uses release channels and capability maturity together. Do not read a p
108
138
  Current WebView truth:
109
139
 
110
140
  - macOS is the current `stable` human-visible acceptance path
111
- - Windows and Linux are currently `alpha` for WebView runtime behavior, even though their platform packages are published
141
+ - Windows is the current `stable` WebView2-backed human-visible acceptance path for common bridge/window controls, background material/corner preferences, and native icon projection
142
+ - Linux remains supported by the OpenTray core daemon/packages, but `@opentray/ext-webview` does not publish Linux native WebView packages
112
143
  - some requests are `unsupported by design`, such as asking the macOS runtime to apply a Windows-only style family
113
144
  - some results are `unavailable by context`, such as tray-bounds projection when the current session has no authoritative tray anchor
114
145
 
115
146
  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.
116
147
 
117
- After installing from npm, use the published CLI smoke path instead of workspace scripts:
148
+ The published CLI is intentionally small and only owns daemon lifecycle and health:
118
149
 
119
150
  ```bash
120
- opentray smoke daemon-tray
121
- opentray smoke daemon-lynx
151
+ opentray daemon health
152
+ opentray daemon start
153
+ opentray daemon stop
154
+ opentray daemon restart
122
155
  ```
123
156
 
124
- `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.
157
+ 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.
125
158
 
126
159
  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:
127
160
 
@@ -139,7 +172,7 @@ The host side of that example can call `await tray.getBounds()` to read the curr
139
172
 
140
173
  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.
141
174
 
142
- 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.
175
+ 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.
143
176
 
144
177
  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.
145
178
 
@@ -151,9 +184,9 @@ pnpm run smoke:lynx -- --run <github-actions-run-id> --bundle packages/cli/asset
151
184
  pnpm run smoke:lynx -- --run <github-actions-run-id> --bundle packages/cli/assets/lynx-review/main.lynx.bundle --features "*,!nativeScreenApi"
152
185
  ```
153
186
 
154
- 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.
187
+ 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.
155
188
 
156
- 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.
189
+ 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.
157
190
 
158
191
  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:
159
192
 
@@ -161,7 +194,7 @@ If you are validating the current prerelease branch before stable publication, i
161
194
  npm i opentray@alpha
162
195
  ```
163
196
 
164
- For local native smoke before npm publish, stage the current platform artifacts first:
197
+ For local native smoke before npm publish, stage the current platform artifacts first and run source-tree examples:
165
198
 
166
199
  ```bash
167
200
  cargo build -p opentray-bin -p opentray-ext-webview -p opentray-ext-lynx
@@ -170,8 +203,8 @@ bun run scripts/binaries/stage-local.ts --kind webview --source target/debug/lib
170
203
  bun run scripts/binaries/stage-local.ts --kind lynx --source target/debug/libopentray_ext_lynx.dylib
171
204
  bash scripts/release/build-lynx-runtime.sh /tmp/OpenTrayLynxRuntime.app.zip
172
205
  bun run scripts/binaries/stage-local.ts --kind lynx-runtime --source /tmp/OpenTrayLynxRuntime.app.zip
173
- OPENTRAY_EXAMPLE_WEBVIEW_SMOKE=1 pnpm --filter opentray cli -- smoke daemon-tray
174
- pnpm --filter opentray cli -- smoke daemon-lynx
206
+ OPENTRAY_EXAMPLE_WEBVIEW_SMOKE=1 pnpm --filter opentray example:daemon-tray
207
+ pnpm --filter opentray example:daemon-lynx -- --bundle packages/cli/assets/lynx-review/main.lynx.bundle
175
208
  ```
176
209
 
177
210
  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:
@@ -179,7 +212,7 @@ During source-level daemon work, restart the daemon with the freshly built broke
179
212
  ```bash
180
213
  cargo build -p opentray-bin
181
214
  OPENTRAY_BROKER_BIN="$PWD/target/debug/opentray" pnpm --filter opentray cli -- daemon restart
182
- OPENTRAY_BROKER_BIN="$PWD/target/debug/opentray" pnpm --filter opentray cli -- smoke daemon-tray
215
+ OPENTRAY_BROKER_BIN="$PWD/target/debug/opentray" OPENTRAY_EXAMPLE_WEBVIEW_SMOKE=1 pnpm --filter opentray example:daemon-tray
183
216
  ```
184
217
 
185
218
  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.
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"}