winui-svelte 0.0.6 → 0.0.7

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.
Files changed (281) hide show
  1. package/API.md +390 -3
  2. package/README.md +4 -0
  3. package/dist/app/launch-command.d.ts +11 -6
  4. package/dist/app/launch-command.d.ts.map +1 -1
  5. package/dist/app/launch-command.js +16 -5
  6. package/dist/app/launch-command.js.map +1 -1
  7. package/dist/app/tray-instance.d.ts +4 -3
  8. package/dist/app/tray-instance.d.ts.map +1 -1
  9. package/dist/app/tray-instance.js +7 -5
  10. package/dist/app/tray-instance.js.map +1 -1
  11. package/dist/automation/backend.d.ts +51 -0
  12. package/dist/automation/backend.d.ts.map +1 -0
  13. package/dist/automation/backend.js +5 -0
  14. package/dist/automation/backend.js.map +1 -0
  15. package/dist/automation/client.d.ts +97 -0
  16. package/dist/automation/client.d.ts.map +1 -0
  17. package/dist/automation/client.js +203 -0
  18. package/dist/automation/client.js.map +1 -0
  19. package/dist/automation/ids.d.ts +90 -0
  20. package/dist/automation/ids.d.ts.map +1 -0
  21. package/dist/automation/ids.js +84 -0
  22. package/dist/automation/ids.js.map +1 -0
  23. package/dist/automation/index.d.ts +13 -0
  24. package/dist/automation/index.d.ts.map +1 -0
  25. package/dist/automation/index.js +8 -0
  26. package/dist/automation/index.js.map +1 -0
  27. package/dist/automation/native.d.ts +11 -0
  28. package/dist/automation/native.d.ts.map +1 -0
  29. package/dist/automation/native.js +595 -0
  30. package/dist/automation/native.js.map +1 -0
  31. package/dist/automation/text.d.ts +50 -0
  32. package/dist/automation/text.d.ts.map +1 -0
  33. package/dist/automation/text.js +110 -0
  34. package/dist/automation/text.js.map +1 -0
  35. package/dist/automation/with-client.d.ts +13 -0
  36. package/dist/automation/with-client.d.ts.map +1 -0
  37. package/dist/automation/with-client.js +19 -0
  38. package/dist/automation/with-client.js.map +1 -0
  39. package/dist/automation/worker-job.d.ts +32 -0
  40. package/dist/automation/worker-job.d.ts.map +1 -0
  41. package/dist/automation/worker-job.js +69 -0
  42. package/dist/automation/worker-job.js.map +1 -0
  43. package/dist/automation/worker.d.ts +44 -0
  44. package/dist/automation/worker.d.ts.map +1 -0
  45. package/dist/automation/worker.js +70 -0
  46. package/dist/automation/worker.js.map +1 -0
  47. package/dist/bindings/.dynwinrt-managed +1 -1
  48. package/dist/chrome/context-menus/context-menu-schema.d.ts +4 -4
  49. package/dist/chrome/notifications/notification-schema.d.ts +2 -2
  50. package/dist/components/hand-written/Window.svelte +2 -0
  51. package/dist/components/window-context.d.ts +14 -0
  52. package/dist/components/window-context.d.ts.map +1 -0
  53. package/dist/components/window-context.js +20 -0
  54. package/dist/components/window-context.js.map +1 -0
  55. package/dist/downloads/chrome-downloads.d.ts +8 -0
  56. package/dist/downloads/chrome-downloads.d.ts.map +1 -1
  57. package/dist/downloads/chrome-downloads.js +35 -6
  58. package/dist/downloads/chrome-downloads.js.map +1 -1
  59. package/dist/downloads/download-record.d.ts +3 -2
  60. package/dist/downloads/download-record.d.ts.map +1 -1
  61. package/dist/downloads/download-record.js.map +1 -1
  62. package/dist/downloads/download-transfer.d.ts.map +1 -1
  63. package/dist/downloads/download-transfer.js +3 -3
  64. package/dist/downloads/download-transfer.js.map +1 -1
  65. package/dist/downloads/download-types.d.ts +3 -1
  66. package/dist/downloads/download-types.d.ts.map +1 -1
  67. package/dist/downloads/download-types.js.map +1 -1
  68. package/dist/downloads/fetch-to-file.d.ts +11 -6
  69. package/dist/downloads/fetch-to-file.d.ts.map +1 -1
  70. package/dist/downloads/fetch-to-file.js +45 -16
  71. package/dist/downloads/fetch-to-file.js.map +1 -1
  72. package/dist/downloads/taskbar-progress.d.ts +3 -18
  73. package/dist/downloads/taskbar-progress.d.ts.map +1 -1
  74. package/dist/downloads/taskbar-progress.js +1 -38
  75. package/dist/downloads/taskbar-progress.js.map +1 -1
  76. package/dist/enums.d.ts +1 -0
  77. package/dist/enums.d.ts.map +1 -1
  78. package/dist/enums.js +1 -0
  79. package/dist/enums.js.map +1 -1
  80. package/dist/forms/form-field-props.d.ts +2 -2
  81. package/dist/progress/TaskbarProgress.d.svelte.ts +6 -0
  82. package/dist/progress/TaskbarProgress.svelte +32 -0
  83. package/dist/progress/aggregate.d.ts +23 -0
  84. package/dist/progress/aggregate.d.ts.map +1 -0
  85. package/dist/progress/aggregate.js +59 -0
  86. package/dist/progress/aggregate.js.map +1 -0
  87. package/dist/progress/core.d.ts +14 -0
  88. package/dist/progress/core.d.ts.map +1 -0
  89. package/dist/progress/core.js +8 -0
  90. package/dist/progress/core.js.map +1 -0
  91. package/dist/progress/index.d.ts +5 -0
  92. package/dist/progress/index.d.ts.map +1 -0
  93. package/dist/progress/index.js +4 -0
  94. package/dist/progress/index.js.map +1 -0
  95. package/dist/progress/progress-event.d.ts +18 -0
  96. package/dist/progress/progress-event.d.ts.map +1 -0
  97. package/dist/progress/progress-event.js +19 -0
  98. package/dist/progress/progress-event.js.map +1 -0
  99. package/dist/progress/progress-operation.d.ts +163 -0
  100. package/dist/progress/progress-operation.d.ts.map +1 -0
  101. package/dist/progress/progress-operation.js +356 -0
  102. package/dist/progress/progress-operation.js.map +1 -0
  103. package/dist/progress/progress-registry.d.ts +89 -0
  104. package/dist/progress/progress-registry.d.ts.map +1 -0
  105. package/dist/progress/progress-registry.js +187 -0
  106. package/dist/progress/progress-registry.js.map +1 -0
  107. package/dist/progress/progress-source.d.ts +46 -0
  108. package/dist/progress/progress-source.d.ts.map +1 -0
  109. package/dist/progress/progress-source.js +31 -0
  110. package/dist/progress/progress-source.js.map +1 -0
  111. package/dist/progress/progress-state.d.ts +54 -0
  112. package/dist/progress/progress-state.d.ts.map +1 -0
  113. package/dist/progress/progress-state.js +35 -0
  114. package/dist/progress/progress-state.js.map +1 -0
  115. package/dist/progress/progress-text.d.ts +10 -0
  116. package/dist/progress/progress-text.d.ts.map +1 -0
  117. package/dist/progress/progress-text.js +23 -0
  118. package/dist/progress/progress-text.js.map +1 -0
  119. package/dist/progress/scoped-source.d.ts +31 -0
  120. package/dist/progress/scoped-source.d.ts.map +1 -0
  121. package/dist/progress/scoped-source.js +46 -0
  122. package/dist/progress/scoped-source.js.map +1 -0
  123. package/dist/progress/taskbar-progress-props.d.ts +15 -0
  124. package/dist/progress/taskbar-progress-props.d.ts.map +1 -0
  125. package/dist/progress/taskbar-progress-props.js +2 -0
  126. package/dist/progress/taskbar-progress-props.js.map +1 -0
  127. package/dist/progress/taskbar-progress.d.ts +44 -0
  128. package/dist/progress/taskbar-progress.d.ts.map +1 -0
  129. package/dist/progress/taskbar-progress.js +62 -0
  130. package/dist/progress/taskbar-progress.js.map +1 -0
  131. package/dist/progress/track-operation.d.ts +36 -0
  132. package/dist/progress/track-operation.d.ts.map +1 -0
  133. package/dist/progress/track-operation.js +53 -0
  134. package/dist/progress/track-operation.js.map +1 -0
  135. package/dist/tray/menu-svelte/TrayMenuOperations.d.svelte.ts +6 -0
  136. package/dist/tray/menu-svelte/TrayMenuOperations.svelte +33 -0
  137. package/dist/tray/menu-svelte/TrayMenuProgress.d.svelte.ts +6 -0
  138. package/dist/tray/menu-svelte/TrayMenuProgress.svelte +28 -0
  139. package/dist/tray/menu-svelte/index.d.ts +3 -1
  140. package/dist/tray/menu-svelte/index.d.ts.map +1 -1
  141. package/dist/tray/menu-svelte/index.js +2 -0
  142. package/dist/tray/menu-svelte/index.js.map +1 -1
  143. package/dist/tray/menu-svelte/menu-node.d.ts +5 -5
  144. package/dist/tray/menu-svelte/menu-props.d.ts +16 -0
  145. package/dist/tray/menu-svelte/menu-props.d.ts.map +1 -1
  146. package/dist/tray/menu-svelte/operation-ids.d.ts +8 -0
  147. package/dist/tray/menu-svelte/operation-ids.d.ts.map +1 -0
  148. package/dist/tray/menu-svelte/operation-ids.js +20 -0
  149. package/dist/tray/menu-svelte/operation-ids.js.map +1 -0
  150. package/dist/tray/native.d.ts +6 -1
  151. package/dist/tray/native.d.ts.map +1 -1
  152. package/dist/tray/native.js +22 -32
  153. package/dist/tray/native.js.map +1 -1
  154. package/dist/tray/pointer-share.d.ts +27 -0
  155. package/dist/tray/pointer-share.d.ts.map +1 -0
  156. package/dist/tray/pointer-share.js +61 -0
  157. package/dist/tray/pointer-share.js.map +1 -0
  158. package/dist/tray/standalone/index.d.ts +1 -0
  159. package/dist/tray/standalone/index.d.ts.map +1 -1
  160. package/dist/tray/standalone/index.js +1 -0
  161. package/dist/tray/standalone/index.js.map +1 -1
  162. package/dist/tray/standalone/menu-theme.d.ts +38 -0
  163. package/dist/tray/standalone/menu-theme.d.ts.map +1 -0
  164. package/dist/tray/standalone/menu-theme.js +74 -0
  165. package/dist/tray/standalone/menu-theme.js.map +1 -0
  166. package/dist/tray/standalone/native.d.ts +5 -1
  167. package/dist/tray/standalone/native.d.ts.map +1 -1
  168. package/dist/tray/standalone/native.js +5 -1
  169. package/dist/tray/standalone/native.js.map +1 -1
  170. package/dist/tray/standalone/standalone-tray.d.ts +13 -0
  171. package/dist/tray/standalone/standalone-tray.d.ts.map +1 -1
  172. package/dist/tray/standalone/standalone-tray.js +23 -1
  173. package/dist/tray/standalone/standalone-tray.js.map +1 -1
  174. package/dist/tray/tray-core.d.ts.map +1 -1
  175. package/dist/tray/tray-core.js +1 -0
  176. package/dist/tray/tray-core.js.map +1 -1
  177. package/dist/tray/tray-manifest.d.ts +44 -4
  178. package/dist/tray/tray-manifest.d.ts.map +1 -1
  179. package/dist/tray/tray-manifest.js +48 -4
  180. package/dist/tray/tray-manifest.js.map +1 -1
  181. package/dist/vite/entrypoints/build-tray.d.ts +3 -1
  182. package/dist/vite/entrypoints/build-tray.d.ts.map +1 -1
  183. package/dist/vite/entrypoints/build-tray.js +22 -16
  184. package/dist/vite/entrypoints/build-tray.js.map +1 -1
  185. package/dist/vite/entrypoints/extract-tray.d.ts +7 -6
  186. package/dist/vite/entrypoints/extract-tray.d.ts.map +1 -1
  187. package/dist/vite/entrypoints/extract-tray.js +35 -15
  188. package/dist/vite/entrypoints/extract-tray.js.map +1 -1
  189. package/dist/vite/entrypoints/tray-module.d.ts +2 -1
  190. package/dist/vite/entrypoints/tray-module.d.ts.map +1 -1
  191. package/dist/vite/entrypoints/tray-module.js +8 -4
  192. package/dist/vite/entrypoints/tray-module.js.map +1 -1
  193. package/dist/web-apis/file-read.d.ts +14 -0
  194. package/dist/web-apis/file-read.d.ts.map +1 -0
  195. package/dist/web-apis/file-read.js +37 -0
  196. package/dist/web-apis/file-read.js.map +1 -0
  197. package/dist/web-apis/file-system.d.ts +9 -0
  198. package/dist/web-apis/file-system.d.ts.map +1 -1
  199. package/dist/web-apis/file-system.js +24 -0
  200. package/dist/web-apis/file-system.js.map +1 -1
  201. package/dist/win32-foreground.d.ts +14 -0
  202. package/dist/win32-foreground.d.ts.map +1 -0
  203. package/dist/win32-foreground.js +71 -0
  204. package/dist/win32-foreground.js.map +1 -0
  205. package/dist/window/create-window.d.ts +1 -1
  206. package/dist/window/create-window.d.ts.map +1 -1
  207. package/dist/window/create-window.js +1 -0
  208. package/dist/window/create-window.js.map +1 -1
  209. package/dist/window/foreground-filter.d.ts +71 -0
  210. package/dist/window/foreground-filter.d.ts.map +1 -0
  211. package/dist/window/foreground-filter.js +108 -0
  212. package/dist/window/foreground-filter.js.map +1 -0
  213. package/dist/window/foreground-native.d.ts +25 -0
  214. package/dist/window/foreground-native.d.ts.map +1 -0
  215. package/dist/window/foreground-native.js +88 -0
  216. package/dist/window/foreground-native.js.map +1 -0
  217. package/dist/window/foreground.d.ts +49 -0
  218. package/dist/window/foreground.d.ts.map +1 -0
  219. package/dist/window/foreground.js +78 -0
  220. package/dist/window/foreground.js.map +1 -0
  221. package/dist/window/window-host.svelte.d.ts +1 -1
  222. package/dist/window/window-host.svelte.d.ts.map +1 -1
  223. package/package.json +18 -1
  224. package/src/app/launch-command.ts +19 -5
  225. package/src/app/tray-instance.ts +7 -5
  226. package/src/automation/backend.ts +56 -0
  227. package/src/automation/client.ts +327 -0
  228. package/src/automation/ids.ts +97 -0
  229. package/src/automation/index.ts +23 -0
  230. package/src/automation/native.ts +689 -0
  231. package/src/automation/text.ts +174 -0
  232. package/src/automation/with-client.ts +20 -0
  233. package/src/automation/worker-job.ts +97 -0
  234. package/src/automation/worker.ts +116 -0
  235. package/src/components/window-context.ts +23 -0
  236. package/src/downloads/chrome-downloads.ts +46 -6
  237. package/src/downloads/download-record.ts +3 -2
  238. package/src/downloads/download-transfer.ts +3 -3
  239. package/src/downloads/download-types.ts +3 -0
  240. package/src/downloads/fetch-to-file.ts +47 -17
  241. package/src/downloads/taskbar-progress.ts +3 -49
  242. package/src/enums.ts +1 -0
  243. package/src/progress/TaskbarProgress.d.svelte.ts +6 -0
  244. package/src/progress/aggregate.ts +68 -0
  245. package/src/progress/core.ts +13 -0
  246. package/src/progress/index.ts +4 -0
  247. package/src/progress/progress-event.ts +25 -0
  248. package/src/progress/progress-operation.ts +469 -0
  249. package/src/progress/progress-registry.ts +224 -0
  250. package/src/progress/progress-source.ts +66 -0
  251. package/src/progress/progress-state.ts +72 -0
  252. package/src/progress/progress-text.ts +27 -0
  253. package/src/progress/scoped-source.ts +56 -0
  254. package/src/progress/taskbar-progress-props.ts +18 -0
  255. package/src/progress/taskbar-progress.ts +80 -0
  256. package/src/progress/track-operation.ts +81 -0
  257. package/src/tray/menu-svelte/TrayMenuOperations.d.svelte.ts +6 -0
  258. package/src/tray/menu-svelte/TrayMenuProgress.d.svelte.ts +6 -0
  259. package/src/tray/menu-svelte/index.ts +4 -0
  260. package/src/tray/menu-svelte/menu-props.ts +20 -0
  261. package/src/tray/menu-svelte/operation-ids.ts +21 -0
  262. package/src/tray/native.ts +29 -33
  263. package/src/tray/pointer-share.ts +71 -0
  264. package/src/tray/standalone/index.ts +1 -0
  265. package/src/tray/standalone/menu-theme.ts +90 -0
  266. package/src/tray/standalone/native.ts +5 -1
  267. package/src/tray/standalone/standalone-tray.ts +43 -1
  268. package/src/tray/tray-core.ts +1 -0
  269. package/src/tray/tray-manifest.ts +53 -4
  270. package/src/vite/entrypoints/build-tray.ts +23 -16
  271. package/src/vite/entrypoints/extract-tray.ts +41 -15
  272. package/src/vite/entrypoints/tray-module.ts +8 -4
  273. package/src/web-apis/file-read.ts +43 -0
  274. package/src/web-apis/file-system.ts +33 -0
  275. package/src/win32-foreground.ts +76 -0
  276. package/src/window/create-window.ts +2 -0
  277. package/src/window/foreground-filter.ts +167 -0
  278. package/src/window/foreground-native.ts +93 -0
  279. package/src/window/foreground.ts +106 -0
  280. package/src/window/window-host.svelte.ts +1 -1
  281. package/web-types.json +1 -1
package/API.md CHANGED
@@ -38,6 +38,7 @@ monorepo needs no build step (the repository is a pnpm workspace, see
38
38
  | `winui-svelte/bootstrap` | `src/window/bootstrap.ts` | `initWindowsAppSdk()`; imports nothing of WinRT, safe on the host's main thread |
39
39
  | `winui-svelte/thread` | `src/window/thread.ts` | `runOnUiThread()`; imports only dynwinrt, so the apartment comes first |
40
40
  | `winui-svelte/window` | `src/window/index.ts` | `runWindow()`, `exitApplication()`, `createWindow()`, `startTimer()`, `systemSettings()`, the picker options (see App services) |
41
+ | `winui-svelte/window/foreground` | `src/window/foreground.ts` | `trackForeground()`, `bringWindowToFront()`, `shouldRestore()` (opt-in; see Following the foreground app) |
41
42
  | `winui-svelte/app` | `src/app/index.ts` | `ensureSingleInstance()`, `notify()`, `activateInstance()`, `activateOrLaunch()`, `launchApp()`, `startTray()`, `relaunch()`, `restartAfterCrash()` (opt-in; see App lifecycle) |
42
43
  | `winui-svelte/app/shell` | `src/app/shell/index.ts` | `trash()`, `openWith()`, `createShortcut()`, `readShortcut()`, `registerAppPath()`, `ShellFailure` (opt-in; see Shell verbs) |
43
44
  | `winui-svelte/app/activation` | `src/app/activation/index.ts` | `installProtocolHandlers()`, `registerFileTypes()`, `launchAtLogin()`, `startActivation()`, `ActivationKind` (opt-in; see Activation) |
@@ -58,11 +59,13 @@ monorepo needs no build step (the repository is a pnpm workspace, see
58
59
  | `winui-svelte/enums` | `src/enums.ts` | every closed set a prop or option takes: WinUI's enums, `ThemeBrush`, `ColorKeyword`, `Backdrop`, `WindowTheme`, `TrayBalloonIcon` and the rest (see Closed sets) |
59
60
  | `winui-svelte/win2d/context-2d` | `src/win2d/context-2d/index.ts` | `Canvas2D`, `createCanvas2D`, `CanvasElement`, `Context2D`, `Path2D` and the rest of the HTML Canvas 2D API over Win2D (opt-in; see Canvas 2D) |
60
61
  | `winui-svelte/tray` | `src/tray/index.ts` | `TrayIcon` (with its `menu`), `createTrayIcon()`, `placeMenuWindow()`, `hideToTray()`, `restoreFromTray()`, `toggleInTray()`, `removeAllTrayIcons()`, `TrayGesture` (opt-in; see System tray) |
62
+ | `winui-svelte/progress/core` | `src/progress/core.ts` | `ProgressRegistry`, `defaultProgressRegistry()`, `ProgressOperation`, `trackOperation()`, `progressText()` and the types, with no Svelte component and no taskbar code, for a process with no window (opt-in; see Progress) |
61
63
  | `winui-svelte/tray/standalone` | `src/tray/standalone/index.ts` | `createStandaloneTray()`, `defineTray()`, its opt-in parts `balloons`, `bounds` and `themedIcon`, `MenuItemKind`, `MenuLevel`, and the `winui-svelte/app` calls that start or signal the app: a tray with no window, no WinUI and no components (opt-in; see Tray with no window) |
62
64
  | `winui-svelte/notice` | `src/notice/index.ts` | `showNotice()`, `NoticeIcon`, `NoticeButtons`, `NoticeButton`: a message box with no window or app (opt-in; see Notice with no app) |
63
65
  | `winui-svelte/forms` | `src/forms/index.ts` | `Form`, `FormField`, `textField`, `numberField`, `selectField` and the other field attachments, `formButton`, `FormValues`, `validityOf` (opt-in; see Forms) |
64
66
  | `winui-svelte/store` | `src/store/index.ts` | `getAppLicense`, `watchLicense`, `checkForUpdates`, `watchPackages`, `getStartupTask`, `getPackageInfo`: the Store and package APIs, answering `hasPackage: false` outside a package (opt-in) |
65
67
  | `winui-svelte/accessibility`, `/accessibility/audit` | `src/accessibility/index.ts`, `src/accessibility/audit/index.ts` | `announce`, `liveRegion`, `LivePriority`; `auditAccessibility`, `accessibilityRules` (opt-in; see Accessibility) |
68
+ | `winui-svelte/automation` | `src/automation/index.ts` | `withUiaClient`, `createUiaWorker`, `readWindowText`, `UiaControlType`: a UI Automation client that reads the text of another window (opt-in; see UI Automation client) |
66
69
  | `winui-svelte/devices` | `src/devices/index.ts` | device enumeration, input devices, Bluetooth, printers, power, network, display, audio, gamepads and sensors, each also at `winui-svelte/devices/<area>` (opt-in; see Windows devices) |
67
70
 
68
71
  The table is the source layout: `exports` point at `.ts` files so the monorepo
@@ -752,6 +755,7 @@ type WindowOptions<Props> = {
752
755
  size?: { width: number; height: number }; // device pixels
753
756
  backdrop?: Backdrop; // "acrylic" | "acrylicBase" | "acrylicThin" | "mica" | "micaAlt" | "none" | "transparent"
754
757
  extendsIntoTitleBar?: boolean;
758
+ onclosing?: () => boolean | void; // AppWindow.Closing: return true to keep the window open
755
759
  isBackground?: boolean; // shown without activating (tests, captures)
756
760
  } & ({ component: Component<Props>; props: Props } | { control: FrameworkElement });
757
761
 
@@ -2571,9 +2575,13 @@ An opt-in subpath: an app that does not import it does not bundle it
2571
2575
  redirects to it
2572
2576
  An app whose windows run in a worker thread passes `entryScript`, the script
2573
2577
  that starts the process, because `process.argv[1]` there is the worker's
2578
+ A single executable application (a Node `node:sea` build, where
2579
+ `process.execPath` is the app's own exe) is relaunched as the exe and
2580
+ `arguments`, with no script and no Node flags
2574
2581
  - `restartAfterCrash({ arguments, conditions })` is
2575
2582
  `RegisterApplicationRestart`: Windows starts the same Node and entry
2576
- script with `arguments` after a crash, a hang, an update that closes the
2583
+ script (a single executable: its own exe) with `arguments` after a crash,
2584
+ a hang, an update that closes the
2577
2585
  app or a reboot for one; `conditions` is a subset of `RestartCondition`
2578
2586
  (`crash`, `hang`, `update`, `reboot`; all by default)
2579
2587
  Limits: no callback (a crashed Node cannot run code, so
@@ -2926,6 +2934,65 @@ const hotkey = registerHotkey({
2926
2934
  posts `WM_HOTKEY` to the thread itself with `PostThreadMessageW`; no key is
2927
2935
  pressed
2928
2936
 
2937
+ ### Following the foreground app (`winui-svelte/window/foreground`)
2938
+
2939
+ Opt-in; nothing runs at import
2940
+
2941
+ ```ts
2942
+ import {
2943
+ bringWindowToFront,
2944
+ shouldRestore,
2945
+ trackForeground
2946
+ } from "winui-svelte/window/foreground";
2947
+
2948
+ const tracker = trackForeground({
2949
+ ownWindows: () => [pillHwnd],
2950
+ onChanged: ({ hwnd, isRealApp }) => {}
2951
+ });
2952
+ tracker.lastRealApp; // bigint | null, the last real app that was in front
2953
+ tracker.current; // bigint | null
2954
+ tracker.stop(); // idempotent
2955
+
2956
+ const isBack = shouldRestore({
2957
+ lastRealApp: tracker.lastRealApp,
2958
+ foreground: tracker.foreground
2959
+ });
2960
+ if (isBack && tracker.lastRealApp !== null) {
2961
+ bringWindowToFront(tracker.lastRealApp); // true when Windows took it
2962
+ }
2963
+ ```
2964
+
2965
+ - `trackForeground({ onChanged, ownWindows, ignoredClasses, tracking,
2966
+ intervalMilliseconds })` runs on the UI thread of a `runWindow` app
2967
+ - `tracking: "events"` (default, `ForegroundTracking.events`): the shell posts
2968
+ a message to a hidden window of the app on each change
2969
+ (`RegisterShellHookWindow` and `SHELLHOOK`), the message pump reads it, and
2970
+ `GetForegroundWindow` is read once; an idle foreground costs nothing
2971
+ dynwinrt delivers no native callbacks, so `SetWinEventHook` cannot be used
2972
+ If Windows refuses the registration, use `tracking: "polling"`
2973
+ - `tracking: "polling"`: one `GetForegroundWindow` per `intervalMilliseconds`
2974
+ (100 by default, 16 at least); latency is one tick
2975
+ The class and the process of a window are read once, when it is first seen
2976
+ - The filter: a real app is not the desktop, not a shell class
2977
+ (`ForegroundShellClass`: `Progman`, `WorkerW`, `Shell_TrayWnd`,
2978
+ `Shell_SecondaryTrayWnd`, `CopilotKeyPressFocusFrame`), not a window of
2979
+ this process, and not in `ownWindows()` or `ignoredClasses`
2980
+ `lastRealApp` changes only on a real app
2981
+ - `bringWindowToFront(hwnd)` joins this thread to the foreground thread's
2982
+ input for `BringWindowToTop` and `SetForegroundWindow`, then detaches,
2983
+ because a hotkey's key releases went to the app in front and Windows'
2984
+ foreground lock refuses a plain call; it restores a minimized window first,
2985
+ sends no input and returns whether the window ended in front
2986
+ It is best effort: a foreground window of a higher integrity level or a hung
2987
+ one still refuses; the tray menu window takes the foreground through it
2988
+ - Not measured yet: the idle cost of each mode (the tray's 30 Hz timer costs
2989
+ about 2 percent of a core in an idle window)
2990
+
2991
+ Manual checklist: press the app's hotkey from Notepad, then from the desktop,
2992
+ then from a browser on a second monitor; each time the key goes back to where
2993
+ it was; then Alt+Tab to another app while the overlay is up and confirm it is
2994
+ not pulled back
2995
+
2929
2996
  ### System tray (`winui-svelte/tray`)
2930
2997
 
2931
2998
  WinUI and the Windows App SDK have no notification-area API (apps call
@@ -3324,6 +3391,12 @@ createStandaloneTray({
3324
3391
  `bounds` when their extras are passed
3325
3392
  The icon keeps the process alive; `remove()` or the process ending takes it
3326
3393
  out of the tray
3394
+ - `colorScheme` is the menu's `color-scheme` as the web says it: `"light dark"`
3395
+ (the default) makes the popup dark when Windows' app theme is, `"light"` and
3396
+ `"dark"` force one; `MenuColorScheme` names the three values
3397
+ It uses uxtheme's `SetPreferredAppMode` and `FlushMenuThemes` (ordinals 135
3398
+ and 136), applied before each menu opens, so it affects the process's other
3399
+ native menus too
3327
3400
  - The default is the smallest tray: an icon from one `.ico` path, clicks,
3328
3401
  `update`, `remove` and the menu
3329
3402
  Three parts are opt-in, each one import from the same entry, passed in
@@ -3373,8 +3446,8 @@ tray.notify({ title: "Ready" });
3373
3446
  here: Windows opens a submenu row without reporting a pick, and no pixel
3374
3447
  or file icon is drawn
3375
3448
  The menu is modal: the thread runs its own message loop until it closes
3376
- It does not follow a dark system theme, which a native popup menu does not
3377
- without an undocumented call; a menu that must match the theme belongs in
3449
+ `colorScheme` makes it follow the system theme through an undocumented
3450
+ uxtheme call; a menu that must be drawn in WinUI belongs in
3378
3451
  `winui-svelte/tray` with `TrayIcon`'s `menu` snippet
3379
3452
  - The same entry re-exports `activateInstance`, `activateOrLaunch` and
3380
3453
  `launchApp` from `winui-svelte/app` (App lifecycle), so a tray imports from
@@ -3385,6 +3458,76 @@ tray.notify({ title: "Ready" });
3385
3458
  component, window or renderer module, or a component's name, is in the
3386
3459
  output, or if it grows past its budget
3387
3460
 
3461
+ ### Trays and windows are independent
3462
+
3463
+ Neither needs the other
3464
+ A process can have zero windows and several tray icons, or windows and
3465
+ taskbar buttons and no tray; nothing is created for the part you leave out
3466
+
3467
+ ```ts
3468
+ // Zero windows, two icons, one Node process
3469
+ import { createStandaloneTray, MenuColorScheme, MenuItemKind } from "winui-svelte/tray/standalone";
3470
+ import { defaultProgressRegistry, progressText } from "winui-svelte/progress/core";
3471
+
3472
+ createStandaloneTray({
3473
+ icon: "recorder.ico",
3474
+ tooltip: "Recorder",
3475
+ colorScheme: MenuColorScheme.DARK,
3476
+ menu: () => [{
3477
+ kind: MenuItemKind.COMMAND,
3478
+ id: "status",
3479
+ label: progressText(defaultProgressRegistry().snapshot),
3480
+ onselect() {}
3481
+ }]
3482
+ });
3483
+
3484
+ createStandaloneTray({
3485
+ icon: "uploads.ico",
3486
+ tooltip: "Uploads",
3487
+ colorScheme: MenuColorScheme.LIGHT,
3488
+ menu: [{ kind: MenuItemKind.COMMAND, id: "quit", label: "Quit", onselect: () => process.exit(0) }]
3489
+ });
3490
+ ```
3491
+
3492
+ ```svelte
3493
+ <!-- Windows and a taskbar button, no tray -->
3494
+ <script lang="ts">
3495
+ import { Window } from "winui-svelte/components";
3496
+ import { TaskbarProgress } from "winui-svelte/progress";
3497
+ </script>
3498
+
3499
+ <Window>
3500
+ <TaskbarProgress />
3501
+ </Window>
3502
+ ```
3503
+
3504
+ - Each `createStandaloneTray` has an identity of its own (its own hidden owner
3505
+ window and a unique id, and its own `guid` when you pass one), its own
3506
+ timer, its own menu and its own state; `remove()` takes out that icon only
3507
+ and the exit hook takes out all of them
3508
+ - Clicks are polled, and Windows keeps one "pressed since the last read"
3509
+ flag for the whole process, which the first read clears; the trays of a
3510
+ process share that read, so each icon hears a click shorter than its
3511
+ polling interval (the flag can still be cleared by another process or by
3512
+ other code of yours that calls `GetAsyncKeyState`)
3513
+ - The menu theme is one setting per process (uxtheme's preferred app mode);
3514
+ a tray sets its own `colorScheme` right before each of its menus opens, so
3515
+ two trays with different schemes each get theirs, because only one menu is
3516
+ open at a time
3517
+ The setting then stays until the next menu opens, so another popup menu in
3518
+ the same process (a window's) shows in the scheme of the tray that spoke
3519
+ last
3520
+ - `winui-svelte/progress/core` is the progress registry, operations and
3521
+ `progressText` with no Svelte component and no taskbar code, so a
3522
+ tray-only process can show progress; `winui-svelte/progress` adds
3523
+ `TaskbarProgress` and `bindTaskbarProgress`, which are the only part that
3524
+ needs a window
3525
+ - `scripts/pack/independence.test.ts` walks the imports and fails if the
3526
+ standalone tray reaches a component, the renderer, the window runtime or
3527
+ taskbar code, if the taskbar progress reaches a tray, or if a window
3528
+ reaches a tray; `scripts/pack/tray-only.test.ts` bundles two trays with the
3529
+ registry and fails on the same, or on a growing size
3530
+
3388
3531
  ### Tray as an entrypoint (`entrypoints/tray.ts`)
3389
3532
 
3390
3533
  The app does not have to know it has a tray; the tray is its own file, found
@@ -3425,6 +3568,14 @@ export default defineTray({
3425
3568
  - `guid` is required: it keeps the icon's place in the tray and names the one
3426
3569
  tray process, so a second `tray.js` exits at once
3427
3570
  - `onactivate` runs on a left click when `onclick` is not given
3571
+ - `export default [defineTray({ ... }), defineTray({ ... })]` defines several
3572
+ trays in one entrypoint: one `tray.js`, one process, each tray with its own
3573
+ `guid`, icon, tooltip, menu and `colorScheme` (every `guid` must differ)
3574
+ The first tray's `guid` names the process, so keep the order; `tray.json` is
3575
+ the single manifest for one tray and `{ "trays": [ ... ] }` for several, and
3576
+ `startTray()` reads the first `guid` from either
3577
+ The markup form (`tray.svelte`) is one tray; use `tray.ts` for several
3578
+ `examples/tray-multiple` is a two-icon entrypoint with no window
3428
3579
  - The build reads `icon`, `tooltip` and `guid` from the syntax tree, never by
3429
3580
  running the file, so a top-level import of WinRT in `tray.ts` does not
3430
3581
  execute at build; `icon` and `guid` must be string literals, and the icon a
@@ -4556,6 +4707,170 @@ takes drops, through the handlers a real drop reaches, and resolves with the
4556
4707
  operation the control accepted (`0` when it refused); it sends no input, so an
4557
4708
  app can test its drop handling in a real window
4558
4709
 
4710
+ ## Progress (`winui-svelte/progress`)
4711
+
4712
+ One progress object for any long work: a download, a file read, a copy, an OCR
4713
+ pass; it is a promise, an `EventTarget` with the platform events, and
4714
+ reactive state, in one value
4715
+ Operations list themselves in an app-wide registry, so the taskbar button and
4716
+ the tray show them with no setup
4717
+ Opt-in: nothing is bundled until an app imports it, and importing does no work
4718
+
4719
+ ### Five call sites
4720
+
4721
+ ```svelte
4722
+ <script lang="ts">
4723
+ import { Button, ProgressBar, TextBlock, Window } from "winui-svelte/components";
4724
+ import { fetchToFile } from "winui-svelte/downloads";
4725
+ import { TaskbarProgress } from "winui-svelte/progress";
4726
+
4727
+ // 1. A download with a bar: fetchToFile returns the operation at once
4728
+ const download = fetchToFile({ url, handle });
4729
+ download.then(size => console.log("saved", size)); // or: await download
4730
+ </script>
4731
+
4732
+ <Window>
4733
+ <TaskbarProgress /> <!-- 4. the taskbar shows every running operation -->
4734
+ <ProgressBar {...download.barProps} /> <!-- value, isIndeterminate, showPaused, showError -->
4735
+ <TextBlock>{download.loaded} of {download.total ?? "?"}</TextBlock>
4736
+ <Button onclick={() => download.cancel()}>Cancel</Button>
4737
+ </Window>
4738
+ ```
4739
+
4740
+ ```ts
4741
+ // 2. Reading a file from disk, with progress and cancel
4742
+ const read = handle.read({ onprogress: event => console.log(event.loaded, event.total) });
4743
+ const file = await read; // a File, like getFile()
4744
+ read.cancel(); // or abort the signal given in the options
4745
+
4746
+ // 3. Any other long work: one call, no lifecycle code
4747
+ const copy = trackOperation({
4748
+ label: "Copying photos",
4749
+ group: "sync",
4750
+ async run(operation) {
4751
+ for await (const chunk of source) {
4752
+ await write(chunk);
4753
+ operation.update({ loaded: (written += chunk.byteLength), total });
4754
+ operation.signal.throwIfAborted();
4755
+ }
4756
+ }
4757
+ });
4758
+
4759
+ // 5. Retry: a failed fetchToFile continues where it stopped
4760
+ await fetchToFile({ url, handle, resume: true });
4761
+ ```
4762
+
4763
+ ```svelte
4764
+ <!-- Tray menu, in tray.svelte markup -->
4765
+ <TrayMenu>
4766
+ <TrayMenuProgress id="progress" /> <!-- "setup.exe - 45%", hidden when idle -->
4767
+ <TrayMenuOperations id="operations" label="Running" emptyLabel="Nothing running" />
4768
+ </TrayMenu>
4769
+ ```
4770
+
4771
+ `{...download.barProps}` spreads onto a `ProgressBar`; Svelte then cannot tell
4772
+ at build time whether a scoped class selector matches that bar, so write the
4773
+ five props out when the same component has a `<style>` rule for its siblings
4774
+
4775
+ ### Several windows and tray icons
4776
+
4777
+ The registry is app-wide; what a taskbar button or a tray line shows is scoped
4778
+ by `group` (a name an operation is given) or by an operation or registry given
4779
+ as `of`
4780
+ A `<TaskbarProgress />` drives the taskbar button of the window it sits in;
4781
+ `window={handle}` picks another
4782
+
4783
+ ```svelte
4784
+ <script lang="ts">
4785
+ const upload = trackOperation({ group: "uploads", run });
4786
+ const download = fetchToFile({ url, handle, group: "downloads" });
4787
+ </script>
4788
+
4789
+ <!-- Window A: its taskbar button shows the downloads only -->
4790
+ <Window bind:handle={windowA}>
4791
+ <TaskbarProgress group="downloads" />
4792
+ </Window>
4793
+
4794
+ <!-- Window B: its own button shows one upload; window A is not touched -->
4795
+ <Window>
4796
+ <TaskbarProgress of={upload} />
4797
+ </Window>
4798
+
4799
+ <!-- The main window drives window A from outside -->
4800
+ <TaskbarProgress window={windowA} group="downloads" />
4801
+
4802
+ <!-- Two tray icons, each with its own menu and its own scope -->
4803
+ <TrayIcon>
4804
+ <TrayMenu>
4805
+ <TrayMenuProgress id="downloads" group="downloads" />
4806
+ </TrayMenu>
4807
+ </TrayIcon>
4808
+ <TrayIcon>
4809
+ <TrayMenu>
4810
+ <TrayMenuOperations id="uploads" label="Uploads" group="uploads" />
4811
+ </TrayMenu>
4812
+ </TrayIcon>
4813
+ ```
4814
+
4815
+ ### `ProgressOperation`
4816
+
4817
+ - It is `PromiseLike`: `await operation` gives the value passed to `complete`
4818
+ and throws the reason of `fail` or `cancel` (an `AbortError` by default); an
4819
+ operation nobody awaits raises no unhandled rejection
4820
+ - It is an `EventTarget` that fires `loadstart`, `progress`, `load`, `error`,
4821
+ `abort` and `loadend` as `OperationProgressEvent` (`lengthComputable`,
4822
+ `loaded`, `total`), in the order `XMLHttpRequest` and `FileReader` use, plus
4823
+ `pause`, `resume` and `change`; `onprogress` and its kin work as properties
4824
+ and as options
4825
+ - `value` (0 to 1), `loaded`, `total`, `state`, `isIndeterminate`,
4826
+ `showPaused`, `showError`, `label` and `barProps` are reactive in markup and
4827
+ in `$effect`, with the meaning `ProgressBar` gives them: a total that is
4828
+ unknown is indeterminate
4829
+ - `$operation` works too: it has `subscribe` and so is a Svelte store
4830
+ - `signal` is an `AbortSignal` that aborts on `cancel()`; a `signal` given to
4831
+ the constructor cancels the operation when it aborts
4832
+ - `start`, `update({ loaded, total })`, `pause`, `resume`, `complete(value)`
4833
+ and `fail(reason)` are for the code doing the work; `resume` also retries an
4834
+ errored operation (the other final states are final)
4835
+ - `ProgressState` is the closed set of states: `idle`, `running`, `paused`,
4836
+ `complete`, `error`, `canceled`
4837
+
4838
+ ### Registry and scopes
4839
+
4840
+ - `defaultProgressRegistry()` is the app-wide registry; an operation lists
4841
+ itself there unless it gets `registry: otherRegistry` or `registry: false`
4842
+ - A finished or canceled operation leaves; a failed one stays so a red bar
4843
+ is not lost, until `clearFailed()` or `remove(operation)`
4844
+ - `registry.where("sync")` or `registry.where(operation => ...)` is a scoped
4845
+ registry that follows the first (call `dispose()` when done);
4846
+ `<TaskbarProgress group>` and the tray components do this for you
4847
+ - `snapshot`, `value`, `count`, `state`, `isIndeterminate`, `showPaused` and
4848
+ `showError` are the aggregate: the bar covers the operations that know their
4849
+ total, and is indeterminate only when none does; `paused` when all that are
4850
+ left are paused; `error` when only failed ones are left; `count` is the
4851
+ number unfinished
4852
+ - `aggregateSnapshots` is that rule as a pure function
4853
+
4854
+ ### Taskbar and tray
4855
+
4856
+ - `<TaskbarProgress of group window taskbar />` draws nothing and keeps the
4857
+ taskbar button in step: a bar, a marquee when the total is unknown, paused
4858
+ yellow, error red, gone when nothing is left; the shell is told only when the
4859
+ bar moves by a thousandth
4860
+ - `bindTaskbarProgress({ source, taskbar })` is the same without markup (the
4861
+ `taskbar` option of `Downloads.download` uses it); `taskbarOptionsOf` is the
4862
+ mapping
4863
+ - `<TrayMenuProgress id of group />` is a command line with the text of
4864
+ `progressText(snapshot)`, hidden while nothing runs; `onselect` is yours
4865
+ - `<TrayMenuOperations id label of group />` is a submenu with a line per
4866
+ running operation; picking a line cancels it
4867
+ - `Downloads` gives each download an operation (`progress: registry` in its
4868
+ options picks the registry, `group` in `download({ ... })` the group), and
4869
+ `fetchToFile` returns one; `FileSystemFileHandle.read` is the extra (WinUI
4870
+ only) that reads a file in 1 MiB chunks
4871
+ - `trackStream({ stream, operation })` passes a `ReadableStream` through and
4872
+ reports the bytes; `trackOperation` is the whole lifecycle for any async work
4873
+
4559
4874
  ## Incremental loading (`winui-svelte/incremental`)
4560
4875
 
4561
4876
  A list that loads its next batch as the user scrolls near the end, for
@@ -6331,6 +6646,78 @@ The working example is `examples/win2d` (`test/win2d.test.ts` runs it in a real
6331
6646
  window and checks the redraw; `src/win2d/win2d.test.ts` draws on a render
6332
6647
  target and checks the pixels)
6333
6648
 
6649
+ ## UI Automation client (`winui-svelte/automation`)
6650
+
6651
+ Read the exact text and headings of another window, instead of OCR; the
6652
+ counterpart of the Accessibility section, which provides automation to
6653
+ others, while this one consumes it; no web API reads another application's
6654
+ window, so this mirrors none; it is opt-in and bundles COM only when imported
6655
+
6656
+ ```ts
6657
+ import { createUiaWorker } from "winui-svelte/automation";
6658
+
6659
+ const worker = createUiaWorker();
6660
+ const text = await worker.readText({
6661
+ target: "foreground",
6662
+ excludeProcessId: process.pid,
6663
+ hardMilliseconds: 1500
6664
+ });
6665
+ // { title, blocks: [{ kind: "heading", level: 1, text }, ...], version, end }
6666
+ ```
6667
+
6668
+ `readText` runs in a worker thread in the multithreaded COM apartment; a target
6669
+ that hangs makes the call reject with `UiaTimeout` after `hardMilliseconds`,
6670
+ the worker is ended and the next call starts a new one (a blocked COM call
6671
+ cannot be cancelled); it resolves null when there is no window to read, the
6672
+ window is the excluded process's or an elevated one
6673
+
6674
+ For the lower level, `withUiaClient` gives a client on the calling thread
6675
+ (call it from a thread that joined a COM apartment) and releases every COM
6676
+ pointer it made when the callback ends:
6677
+
6678
+ ```ts
6679
+ import { UiaControlType, withUiaClient } from "winui-svelte/automation";
6680
+
6681
+ const lines = await withUiaClient(client => {
6682
+ const root = client.elementFromHandle(hwnd);
6683
+ if (root === null) {
6684
+ return [];
6685
+ }
6686
+
6687
+ const found: string[] = [];
6688
+ const walk = client.walk({
6689
+ root,
6690
+ maxElements: 400,
6691
+ maxMilliseconds: 400,
6692
+ shouldVisit: ({ controlType, isOffscreen }) => !isOffscreen && controlType !== UiaControlType.button
6693
+ });
6694
+ for (const node of walk) {
6695
+ const ranges = node.pattern("text")?.visibleRanges() ?? [];
6696
+ found.push(...ranges.map(range => range.getText(1000)));
6697
+ }
6698
+
6699
+ return found;
6700
+ });
6701
+ ```
6702
+
6703
+ | Call | What |
6704
+ |---|---|
6705
+ | `withUiaClient(use)` | creates `CUIAutomation`, runs `use(client)`, releases everything; an element used after that throws `UiaScopeEndedError` |
6706
+ | `client.elementFromHandle(hwnd)`, `client.focusedElement()` | an element, or null when it is gone or cannot be read |
6707
+ | `element.properties()` | `name`, `className`, `automationId`, `controlType`, `processId`, `isOffscreen`, `boundingRectangle`, `headingLevel` (0 for none, 1 to 9), `hasTextPattern`, `hasValuePattern` |
6708
+ | `client.walk({ root, maxElements, maxMilliseconds, shouldVisit })` | breadth first over the control view, one cached call per parent (`FindAllBuildCache`); `walk.end` is `complete`, `maxElements` or `deadline`; an element that went away is skipped; `node.skipSubtree()` prunes |
6709
+ | `element.pattern("text")` | `visibleRanges()`, `documentRange()`, and `range.getText(maxLength)` |
6710
+ | `element.pattern("value")` | `value` |
6711
+ | `readWindowText({ client, root })` | the headings and text of a window, skipping chrome and off screen elements (`UIA_CHROME_CONTROL_TYPES`); `version` changes when the text does |
6712
+ | `createUiaWorker()` | `readText({ target, excludeProcessId, hardMilliseconds, ... })` with the hard deadline; `close()` |
6713
+ | `UiaControlType`, `UiaPropertyId`, `UiaPatternName`, `HEADING_LEVEL_NONE`, `HEADING_LEVEL_FIRST` | the header's ids as `as const` sets and constants (the sets also under `winui-svelte/enums`) |
6714
+ | `UiaWalkEnd`, `TextBlockKind`, `UiaTarget` | the closed sets of a walk's end, a block's kind and a worker target (`foreground`, `focused`, or `{ hwnd }`) |
6715
+ | `UiaElementUnavailableError`, `UiaScopeEndedError`, `UiaTimeout` | the errors: an element went away, a client was used after its scope, a target did not answer in time |
6716
+
6717
+ Elements an app cannot read (elevated windows) come back as null, never an
6718
+ exception; browsers and Electron build their tree when the first client asks,
6719
+ so the first walk of such a window can be slower
6720
+
6334
6721
  ## Windows devices (`winui-svelte/devices`)
6335
6722
 
6336
6723
  Windows' own device APIs (`Windows.Devices.*`, `Windows.System.Power`,
package/README.md CHANGED
@@ -882,6 +882,8 @@ conditions on `exports`), which your Vite compiles (`winuiSvelte()`)
882
882
  | `winui-svelte/chrome/permissions` | `ChromePermissions`: `chrome.permissions` (`getAll`, `contains`, `request`, `remove`, `onAdded`, `onRemoved`) over the Permissions API providers and the OS consent; the grants are saved in the app's data folder (opt-in; [`API.md`](https://github.com/avi12/winui-svelte/blob/main/API.md#chromepermissions-winui-sveltechromepermissions)) |
883
883
  | `winui-svelte/chrome/context-menus` | `ChromeContextMenus`: `chrome.contextMenus` (`create`, `update`, `remove`, `removeAll`, `onClicked`; normal, checkbox, radio and separator items, `contexts`, `parentId`) drawn by the tray menu model, for the tray icon and a window's context flyout (opt-in; [`API.md`](https://github.com/avi12/winui-svelte/blob/main/API.md#chromecontextmenus-winui-sveltechromecontext-menus)) |
884
884
  | `winui-svelte/downloads` | `Downloads`: `chrome.downloads` with the same names and shapes, and `fetchToFile` for `showSaveFilePicker` handles; streamed, resumable, with the Mark of the Web and optional taskbar progress (opt-in; [`API.md`](https://github.com/avi12/winui-svelte/blob/main/API.md#downloads-winui-sveltedownloads)) |
885
+ | `winui-svelte/progress/core` | The registry, `ProgressOperation`, `trackOperation` and `progressText` of `winui-svelte/progress` without `<TaskbarProgress />`: no Svelte component and no window code, for a tray-only process (opt-in; [`API.md`](https://github.com/avi12/winui-svelte/blob/main/API.md#trays-and-windows-are-independent)) |
886
+ | `winui-svelte/progress` | `ProgressOperation` (a promise, an `EventTarget` with `progress` and `loadend`, and reactive `value`), `ProgressRegistry`, `<TaskbarProgress />`, `trackOperation`; downloads, file reads and your own work report through it, scoped by group per window or tray icon (opt-in; [`API.md`](https://github.com/avi12/winui-svelte/blob/main/API.md#progress-winui-svelteprogress)) |
885
887
  | `winui-svelte/chrome/runtime` | `Runtime`: `chrome.runtime` for a native app (manifest, messages and ports between the app's contexts, native messaging hosts, `onInstalled`, `onStartup`, `onSuspend`) (opt-in; [`API.md`](https://github.com/avi12/winui-svelte/blob/main/API.md#chrome-runtime-winui-sveltechromeruntime)) |
886
888
  | `winui-svelte/chrome/notifications` | `ChromeNotifications`: `chrome.notifications` (`create`, `update`, `clear`, `getAll`, `getPermissionLevel`, `onClicked`, `onButtonClicked`, `onClosed`; basic, image, list and progress templates, buttons) over the web `Notification`, one notification pipeline (opt-in; [`API.md`](https://github.com/avi12/winui-svelte/blob/main/API.md#chrome-notifications-winui-sveltechromenotifications)) |
887
889
  | `winui-svelte/chrome/commands` | `ChromeCommands`: `chrome.commands` (`getAll`, `onCommand`) with `suggested_key` shortcuts as global hotkeys (opt-in; [`API.md`](https://github.com/avi12/winui-svelte/blob/main/API.md#chrome-commands-winui-sveltechromecommands)) |
@@ -900,9 +902,11 @@ conditions on `exports`), which your Vite compiles (`winuiSvelte()`)
900
902
  | `winui-svelte/tray/standalone` | `createStandaloneTray`: a notification-area icon and a native popup menu, the model of `winui-svelte/tray/menu` (levels and a user profile when you pass `resolve: resolveMenu`; balloons, `bounds` and a light and dark icon pair when you pass `balloons`, `bounds` and `themedIcon` in `extras`), in a plain Node process, with no window, no WinUI and no components, that starts or signals the full app; `defineTray` for `entrypoints/tray.ts`, or the menu as markup in `entrypoints/tray.svelte`, lowered at build with no Svelte runtime: a tray the build bundles apart so the app never imports it (opt-in; [`API.md`](https://github.com/avi12/winui-svelte/blob/main/API.md#tray-with-no-window-winui-sveltetraystandalone), [entrypoint](https://github.com/avi12/winui-svelte/blob/main/API.md#tray-as-an-entrypoint-entrypointstrayts)) |
901
903
  | `winui-svelte/notice` | `showNotice`: a message box with no window or app, for a check that ends a run before it starts (opt-in; [`API.md`](https://github.com/avi12/winui-svelte/blob/main/API.md#notice-with-no-app-winui-sveltenotice)) |
902
904
  | `winui-svelte/window/taskbar` | `handle.taskbar`: a progress bar, an overlay icon or badge, flashing and the thumbnail's tooltip and clip on the window's taskbar button, and the unpackaged `setAppBadge` fallback (opt-in; [`API.md`](https://github.com/avi12/winui-svelte/blob/main/API.md#taskbar-button-winui-sveltewindowtaskbar)) |
905
+ | `winui-svelte/window/foreground` | `trackForeground`: which app is in front, event driven, ignoring the shell and the app's own windows, and `bringWindowToFront` for another app's window (opt-in; [`API.md`](https://github.com/avi12/winui-svelte/blob/main/API.md#following-the-foreground-app-winui-sveltewindowforeground)) |
903
906
  | `winui-svelte/forms` | `Form`, `FormField` and the attachments that join a control to a form by name, with HTML's constraint validation and zod (opt-in; [`API.md`](https://github.com/avi12/winui-svelte/blob/main/API.md#forms-winui-svelteforms)) |
904
907
  | `winui-svelte/store` | `getAppLicense`, `watchLicense`, `checkForUpdates`, `watchPackages`, `getStartupTask`: the Store licence, updates, package events and startup task, answering `hasPackage: false` outside a package (opt-in; [`API.md`](https://github.com/avi12/winui-svelte/blob/main/API.md#store-and-package-winui-sveltestore)) |
905
908
  | `winui-svelte/accessibility`, `/accessibility/audit` | `announce` and `liveRegion` say a change to a screen reader (`aria-live`, `role="alert"`) over UI Automation notifications; `auditAccessibility` checks a window for unnamed buttons, unlabeled inputs, duplicate access keys and low contrast (opt-in; [`API.md`](https://github.com/avi12/winui-svelte/blob/main/API.md#accessibility-winui-svelteaccessibility)) |
909
+ | `winui-svelte/automation` | `createUiaWorker` and `withUiaClient` read the exact text and headings of another window over UI Automation (a worker with a hard deadline, so a hung app cannot stall yours); [`API.md`](https://github.com/avi12/winui-svelte/blob/main/API.md#ui-automation-client-winui-svelteautomation) |
906
910
  | `winui-svelte/devices`, `/devices/enumeration`, `/devices/input`, `/devices/bluetooth`, `/devices/printers`, `/devices/power`, `/devices/network`, `/devices/audio`, `/devices/display`, `/devices/gamepad`, `/devices/sensors` | device enumeration, input devices, Bluetooth, printers, power, network, displays, audio, gamepads, sensors: Windows' own device APIs as runes (opt-in; [`API.md`](https://github.com/avi12/winui-svelte/blob/main/API.md#windows-devices-winui-sveltedevices)) |
907
911
  | `winui-svelte/implicit-layout-animation` | `implicitLayoutAnimation`, `LayoutEasing`: the children of a panel slide to their new places when the layout moves them |
908
912
  | `winui-svelte/settings` | `SettingsCard`, `SettingsExpander`: Fluent settings cards after the Community Toolkit's |
@@ -29,18 +29,23 @@ export declare function commandOf({ executable, nodeFlags, script, appArguments
29
29
  };
30
30
  /**
31
31
  * The command that starts this app again, copied from the running process.
32
+ * A single executable application (a Node `node:sea` build) is its own
33
+ * program: `process.execPath` is the exe, it has no entry script and takes no
34
+ * Node flags, so the command is the exe and the app's arguments.
32
35
  *
33
- * @param options - The arguments the new copy gets, and the entry script when
34
- * it is not `process.argv[1]`.
36
+ * @param options - The arguments the new copy gets, the entry script when it
37
+ * is not `process.argv[1]`, and `isSingleExecutable` (the running process's
38
+ * answer by default; a test stands in).
35
39
  * @returns The program and its arguments.
36
- * @throws {Error} When the process has no entry script (an interactive
37
- * session).
40
+ * @throws {Error} When the process has no entry script and is not a single
41
+ * executable (an interactive session).
38
42
  */
39
- export declare function launchCommand({ appArguments, entryScript }: {
43
+ export declare function launchCommand({ appArguments, entryScript, isSingleExecutable }: {
40
44
  appArguments: readonly string[];
41
45
  entryScript?: string | undefined;
46
+ isSingleExecutable?: boolean;
42
47
  }): {
43
48
  executable: string;
44
- arguments: string[];
49
+ arguments: readonly string[];
45
50
  };
46
51
  //# sourceMappingURL=launch-command.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"launch-command.d.ts","sourceRoot":"","sources":["../../src/app/launch-command.ts"],"names":[],"mappings":"AAOA,+DAA+D;AAC/D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAcD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,UAE9D;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE;IACzE,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CACjC;;;EAKA;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,EAAE,YAAY,EAAE,WAA6B,EAAE,EAAE;IAC7E,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;;;EAYA"}
1
+ {"version":3,"file":"launch-command.d.ts","sourceRoot":"","sources":["../../src/app/launch-command.ts"],"names":[],"mappings":"AASA,+DAA+D;AAC/D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAcD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,UAE9D;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE;IACzE,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CACjC;;;EAKA;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,EAAE,YAAY,EAAE,WAA6B,EAAE,kBAA4B,EAAE,EAAE;IAC3G,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;;;EAmBA"}
@@ -1,3 +1,4 @@
1
+ import { isSea } from "node:sea";
1
2
  const SPACE = " ";
2
3
  const QUOTE = "\"";
3
4
  const BACKSLASH = "\\";
@@ -39,14 +40,24 @@ export function commandOf({ executable, nodeFlags, script, appArguments }) {
39
40
  }
40
41
  /**
41
42
  * The command that starts this app again, copied from the running process.
43
+ * A single executable application (a Node `node:sea` build) is its own
44
+ * program: `process.execPath` is the exe, it has no entry script and takes no
45
+ * Node flags, so the command is the exe and the app's arguments.
42
46
  *
43
- * @param options - The arguments the new copy gets, and the entry script when
44
- * it is not `process.argv[1]`.
47
+ * @param options - The arguments the new copy gets, the entry script when it
48
+ * is not `process.argv[1]`, and `isSingleExecutable` (the running process's
49
+ * answer by default; a test stands in).
45
50
  * @returns The program and its arguments.
46
- * @throws {Error} When the process has no entry script (an interactive
47
- * session).
51
+ * @throws {Error} When the process has no entry script and is not a single
52
+ * executable (an interactive session).
48
53
  */
49
- export function launchCommand({ appArguments, entryScript = process.argv[1] }) {
54
+ export function launchCommand({ appArguments, entryScript = process.argv[1], isSingleExecutable = isSea() }) {
55
+ if (isSingleExecutable) {
56
+ return {
57
+ executable: process.execPath,
58
+ arguments: appArguments
59
+ };
60
+ }
50
61
  const isScriptMissing = entryScript === undefined;
51
62
  if (isScriptMissing) {
52
63
  throw new Error("relaunch and restartAfterCrash need a process started from a script");
@@ -1 +1 @@
1
- {"version":3,"file":"launch-command.js","sourceRoot":"","sources":["../../src/app/launch-command.ts"],"names":[],"mappings":"AAAA,MAAM,KAAK,GAAG,GAAG,CAAC;AAClB,MAAM,KAAK,GAAG,IAAI,CAAC;AACnB,MAAM,SAAS,GAAG,IAAI,CAAC;AACvB,MAAM,YAAY,GAAG,QAAQ,CAAC;AAC9B,MAAM,oBAAoB,GAAG,SAAS,CAAC;AACvC,MAAM,wBAAwB,GAAG,UAAU,CAAC;AAQ5C,SAAS,aAAa,CAAC,QAAgB;IACrC,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpE,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ;SACrB,OAAO,CAAC,wBAAwB,EAAE,CAAC,MAAM,EAAE,WAAmB,EAAE,EAAE,CAAC,GAAG,WAAW,GAAG,WAAW,GAAG,SAAS,GAAG,KAAK,EAAE,CAAC;SACtH,OAAO,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,WAAmB,EAAE,EAAE,CAAC,GAAG,WAAW,GAAG,WAAW,EAAE,CAAC,CAAC;IAClG,OAAO,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK,EAAE,CAAC;AACtC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,YAA+B;IAC7D,OAAO,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACrD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAKtE;IACC,OAAO;QACL,UAAU;QACV,SAAS,EAAE,CAAC,GAAG,SAAS,EAAE,MAAM,EAAE,GAAG,YAAY,CAAC;KAC3B,CAAC;AAC5B,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,EAAE,YAAY,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAG1E;IACC,MAAM,eAAe,GAAG,WAAW,KAAK,SAAS,CAAC;IAClD,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;IACzF,CAAC;IAED,OAAO,SAAS,CAAC;QACf,UAAU,EAAE,OAAO,CAAC,QAAQ;QAC5B,SAAS,EAAE,OAAO,CAAC,QAAQ;QAC3B,MAAM,EAAE,WAAW;QACnB,YAAY;KACb,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"launch-command.js","sourceRoot":"","sources":["../../src/app/launch-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC,MAAM,KAAK,GAAG,GAAG,CAAC;AAClB,MAAM,KAAK,GAAG,IAAI,CAAC;AACnB,MAAM,SAAS,GAAG,IAAI,CAAC;AACvB,MAAM,YAAY,GAAG,QAAQ,CAAC;AAC9B,MAAM,oBAAoB,GAAG,SAAS,CAAC;AACvC,MAAM,wBAAwB,GAAG,UAAU,CAAC;AAQ5C,SAAS,aAAa,CAAC,QAAgB;IACrC,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpE,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ;SACrB,OAAO,CAAC,wBAAwB,EAAE,CAAC,MAAM,EAAE,WAAmB,EAAE,EAAE,CAAC,GAAG,WAAW,GAAG,WAAW,GAAG,SAAS,GAAG,KAAK,EAAE,CAAC;SACtH,OAAO,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,WAAmB,EAAE,EAAE,CAAC,GAAG,WAAW,GAAG,WAAW,EAAE,CAAC,CAAC;IAClG,OAAO,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK,EAAE,CAAC;AACtC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,YAA+B;IAC7D,OAAO,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACrD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAKtE;IACC,OAAO;QACL,UAAU;QACV,SAAS,EAAE,CAAC,GAAG,SAAS,EAAE,MAAM,EAAE,GAAG,YAAY,CAAC;KAC3B,CAAC;AAC5B,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,aAAa,CAAC,EAAE,YAAY,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,kBAAkB,GAAG,KAAK,EAAE,EAIxG;IACC,IAAI,kBAAkB,EAAE,CAAC;QACvB,OAAO;YACL,UAAU,EAAE,OAAO,CAAC,QAAQ;YAC5B,SAAS,EAAE,YAAY;SACA,CAAC;IAC5B,CAAC;IAED,MAAM,eAAe,GAAG,WAAW,KAAK,SAAS,CAAC;IAClD,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;IACzF,CAAC;IAED,OAAO,SAAS,CAAC;QACf,UAAU,EAAE,OAAO,CAAC,QAAQ;QAC5B,SAAS,EAAE,OAAO,CAAC,QAAQ;QAC3B,MAAM,EAAE,WAAW;QACnB,YAAY;KACb,CAAC,CAAC;AACL,CAAC"}
@@ -8,8 +8,9 @@ import { activateOrLaunch } from "./activate.js";
8
8
  */
9
9
  export declare function trayInstanceKey(guid: string): string;
10
10
  /**
11
- * Claims the right to be the one tray process for `guid`: the built `tray.js`
12
- * calls it first. A second copy finds the first and gets false, and exits.
11
+ * Claims the right to be the one tray process for `guid` (the first tray's,
12
+ * when the entrypoint defines several): the built `tray.js` calls it first.
13
+ * A second copy finds the first and gets false, and exits.
13
14
  * Needs no window or UI thread.
14
15
  *
15
16
  * @param options - The tray's guid.
@@ -27,7 +28,7 @@ export interface StartTrayOptions {
27
28
  }
28
29
  /**
29
30
  * Starts the built `tray.js` as a process of its own, once: when one runs for
30
- * the same `guid` nothing starts. Optional, and never needed by the app's
31
+ * the same process guid nothing starts. Optional, and never needed by the app's
31
32
  * code: an installer, a launcher or the app's own `main` may call it.
32
33
  *
33
34
  * @param options - The folder of the build.
@@ -1 +1 @@
1
- {"version":3,"file":"tray-instance.d.ts","sourceRoot":"","sources":["../../src/app/tray-instance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AASjD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,UAE3C;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,WAY3D;AAED,8BAA8B;AAC9B,MAAM,WAAW,gBAAgB;IAC/B,+FAA+F;IAC/F,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE5B,+FAA+F;IAC/F,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,gBAAgB,CAAC;CAC7C;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,EAAE,SAAyB,EAAE,QAA2B,EAAE,GAAE,gBAAqB,oBAc1G"}
1
+ {"version":3,"file":"tray-instance.d.ts","sourceRoot":"","sources":["../../src/app/tray-instance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AASjD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,UAE3C;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,WAY3D;AAED,8BAA8B;AAC9B,MAAM,WAAW,gBAAgB;IAC/B,+FAA+F;IAC/F,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE5B,+FAA+F;IAC/F,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,gBAAgB,CAAC;CAC7C;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,EAAE,SAAyB,EAAE,QAA2B,EAAE,GAAE,gBAAqB,oBAe1G"}