winui-svelte 0.0.5 → 0.0.6

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 (971) hide show
  1. package/API.md +1551 -20
  2. package/README.md +27 -4
  3. package/dist/app/activation/alarm-argument.d.ts +28 -0
  4. package/dist/app/activation/alarm-argument.d.ts.map +1 -0
  5. package/dist/app/activation/alarm-argument.js +44 -0
  6. package/dist/app/activation/alarm-argument.js.map +1 -0
  7. package/dist/app/activation/classify.d.ts +25 -8
  8. package/dist/app/activation/classify.d.ts.map +1 -1
  9. package/dist/app/activation/classify.js +34 -5
  10. package/dist/app/activation/classify.js.map +1 -1
  11. package/dist/app/activation/index.d.ts +1 -1
  12. package/dist/app/activation/index.d.ts.map +1 -1
  13. package/dist/app/activation/jump-list-argument.d.ts +20 -0
  14. package/dist/app/activation/jump-list-argument.d.ts.map +1 -0
  15. package/dist/app/activation/jump-list-argument.js +28 -0
  16. package/dist/app/activation/jump-list-argument.js.map +1 -0
  17. package/dist/app/activation/kinds.d.ts +16 -1
  18. package/dist/app/activation/kinds.d.ts.map +1 -1
  19. package/dist/app/activation/kinds.js +3 -1
  20. package/dist/app/activation/kinds.js.map +1 -1
  21. package/dist/app/activation/receive.d.ts +3 -1
  22. package/dist/app/activation/receive.d.ts.map +1 -1
  23. package/dist/app/activation/receive.js +13 -1
  24. package/dist/app/activation/receive.js.map +1 -1
  25. package/dist/app/activation/registration.d.ts +14 -0
  26. package/dist/app/activation/registration.d.ts.map +1 -1
  27. package/dist/app/activation/registration.js +11 -3
  28. package/dist/app/activation/registration.js.map +1 -1
  29. package/dist/app/activation/scheme.d.ts +7 -0
  30. package/dist/app/activation/scheme.d.ts.map +1 -1
  31. package/dist/app/activation/scheme.js +10 -1
  32. package/dist/app/activation/scheme.js.map +1 -1
  33. package/dist/app/index.d.ts +2 -0
  34. package/dist/app/index.d.ts.map +1 -1
  35. package/dist/app/index.js +1 -0
  36. package/dist/app/index.js.map +1 -1
  37. package/dist/app/instance-pipe.d.ts.map +1 -1
  38. package/dist/app/instance-pipe.js +1 -2
  39. package/dist/app/instance-pipe.js.map +1 -1
  40. package/dist/app/jump-list/index.d.ts +62 -0
  41. package/dist/app/jump-list/index.d.ts.map +1 -0
  42. package/dist/app/jump-list/index.js +51 -0
  43. package/dist/app/jump-list/index.js.map +1 -0
  44. package/dist/app/jump-list/native.d.ts +9 -0
  45. package/dist/app/jump-list/native.d.ts.map +1 -0
  46. package/dist/app/jump-list/native.js +284 -0
  47. package/dist/app/jump-list/native.js.map +1 -0
  48. package/dist/app/jump-list/tasks.d.ts +86 -0
  49. package/dist/app/jump-list/tasks.d.ts.map +1 -0
  50. package/dist/app/jump-list/tasks.js +89 -0
  51. package/dist/app/jump-list/tasks.js.map +1 -0
  52. package/dist/app/schedule/alarm.d.ts +10 -0
  53. package/dist/app/schedule/alarm.d.ts.map +1 -0
  54. package/dist/app/schedule/alarm.js +2 -0
  55. package/dist/app/schedule/alarm.js.map +1 -0
  56. package/dist/app/schedule/alarms.d.ts +78 -0
  57. package/dist/app/schedule/alarms.d.ts.map +1 -0
  58. package/dist/app/schedule/alarms.js +192 -0
  59. package/dist/app/schedule/alarms.js.map +1 -0
  60. package/dist/app/schedule/backend.d.ts +19 -0
  61. package/dist/app/schedule/backend.d.ts.map +1 -0
  62. package/dist/app/schedule/backend.js +3 -0
  63. package/dist/app/schedule/backend.js.map +1 -0
  64. package/dist/app/schedule/events.d.ts +30 -0
  65. package/dist/app/schedule/events.d.ts.map +1 -0
  66. package/dist/app/schedule/events.js +45 -0
  67. package/dist/app/schedule/events.js.map +1 -0
  68. package/dist/app/schedule/index.d.ts +7 -0
  69. package/dist/app/schedule/index.d.ts.map +1 -0
  70. package/dist/app/schedule/index.js +3 -0
  71. package/dist/app/schedule/index.js.map +1 -0
  72. package/dist/app/schedule/native.d.ts +19 -0
  73. package/dist/app/schedule/native.d.ts.map +1 -0
  74. package/dist/app/schedule/native.js +74 -0
  75. package/dist/app/schedule/native.js.map +1 -0
  76. package/dist/app/schedule/occurrence.d.ts +27 -0
  77. package/dist/app/schedule/occurrence.d.ts.map +1 -0
  78. package/dist/app/schedule/occurrence.js +34 -0
  79. package/dist/app/schedule/occurrence.js.map +1 -0
  80. package/dist/app/schedule/xml.d.ts +29 -0
  81. package/dist/app/schedule/xml.d.ts.map +1 -0
  82. package/dist/app/schedule/xml.js +93 -0
  83. package/dist/app/schedule/xml.js.map +1 -0
  84. package/dist/app/shell/app-paths.d.ts +46 -0
  85. package/dist/app/shell/app-paths.d.ts.map +1 -0
  86. package/dist/app/shell/app-paths.js +117 -0
  87. package/dist/app/shell/app-paths.js.map +1 -0
  88. package/dist/app/shell/backend.d.ts +26 -0
  89. package/dist/app/shell/backend.d.ts.map +1 -0
  90. package/dist/app/shell/backend.js +2 -0
  91. package/dist/app/shell/backend.js.map +1 -0
  92. package/dist/app/shell/index.d.ts +12 -0
  93. package/dist/app/shell/index.d.ts.map +1 -0
  94. package/dist/app/shell/index.js +6 -0
  95. package/dist/app/shell/index.js.map +1 -0
  96. package/dist/app/shell/kinds.d.ts +49 -0
  97. package/dist/app/shell/kinds.d.ts.map +1 -0
  98. package/dist/app/shell/kinds.js +37 -0
  99. package/dist/app/shell/kinds.js.map +1 -0
  100. package/dist/app/shell/native.d.ts +9 -0
  101. package/dist/app/shell/native.d.ts.map +1 -0
  102. package/dist/app/shell/native.js +280 -0
  103. package/dist/app/shell/native.js.map +1 -0
  104. package/dist/app/shell/open-with.d.ts +31 -0
  105. package/dist/app/shell/open-with.d.ts.map +1 -0
  106. package/dist/app/shell/open-with.js +45 -0
  107. package/dist/app/shell/open-with.js.map +1 -0
  108. package/dist/app/shell/paths.d.ts +17 -0
  109. package/dist/app/shell/paths.d.ts.map +1 -0
  110. package/dist/app/shell/paths.js +27 -0
  111. package/dist/app/shell/paths.js.map +1 -0
  112. package/dist/app/shell/shortcut.d.ts +77 -0
  113. package/dist/app/shell/shortcut.d.ts.map +1 -0
  114. package/dist/app/shell/shortcut.js +104 -0
  115. package/dist/app/shell/shortcut.js.map +1 -0
  116. package/dist/app/shell/trash.d.ts +20 -0
  117. package/dist/app/shell/trash.d.ts.map +1 -0
  118. package/dist/app/shell/trash.js +40 -0
  119. package/dist/app/shell/trash.js.map +1 -0
  120. package/dist/app/tray-instance.d.ts +38 -0
  121. package/dist/app/tray-instance.d.ts.map +1 -0
  122. package/dist/app/tray-instance.js +63 -0
  123. package/dist/app/tray-instance.js.map +1 -0
  124. package/dist/bindings/.dynwinrt-managed +1 -1
  125. package/dist/chrome/action/action-types.d.ts +48 -0
  126. package/dist/chrome/action/action-types.d.ts.map +1 -0
  127. package/dist/chrome/action/action-types.js +86 -0
  128. package/dist/chrome/action/action-types.js.map +1 -0
  129. package/dist/chrome/action/chrome-action.d.ts +117 -0
  130. package/dist/chrome/action/chrome-action.d.ts.map +1 -0
  131. package/dist/chrome/action/chrome-action.js +181 -0
  132. package/dist/chrome/action/chrome-action.js.map +1 -0
  133. package/dist/chrome/action/create-chrome-action.d.ts +23 -0
  134. package/dist/chrome/action/create-chrome-action.d.ts.map +1 -0
  135. package/dist/chrome/action/create-chrome-action.js +24 -0
  136. package/dist/chrome/action/create-chrome-action.js.map +1 -0
  137. package/dist/chrome/action/index.d.ts +7 -0
  138. package/dist/chrome/action/index.d.ts.map +1 -0
  139. package/dist/chrome/action/index.js +4 -0
  140. package/dist/chrome/action/index.js.map +1 -0
  141. package/dist/chrome/commands/chrome-commands.d.ts +62 -0
  142. package/dist/chrome/commands/chrome-commands.d.ts.map +1 -0
  143. package/dist/chrome/commands/chrome-commands.js +133 -0
  144. package/dist/chrome/commands/chrome-commands.js.map +1 -0
  145. package/dist/chrome/commands/command-types.d.ts +45 -0
  146. package/dist/chrome/commands/command-types.d.ts.map +1 -0
  147. package/dist/chrome/commands/command-types.js +27 -0
  148. package/dist/chrome/commands/command-types.js.map +1 -0
  149. package/dist/chrome/commands/index.d.ts +7 -0
  150. package/dist/chrome/commands/index.d.ts.map +1 -0
  151. package/dist/chrome/commands/index.js +4 -0
  152. package/dist/chrome/commands/index.js.map +1 -0
  153. package/dist/chrome/commands/shortcut.d.ts +24 -0
  154. package/dist/chrome/commands/shortcut.d.ts.map +1 -0
  155. package/dist/chrome/commands/shortcut.js +86 -0
  156. package/dist/chrome/commands/shortcut.js.map +1 -0
  157. package/dist/chrome/context-menus/build-menu.d.ts +26 -0
  158. package/dist/chrome/context-menus/build-menu.d.ts.map +1 -0
  159. package/dist/chrome/context-menus/build-menu.js +97 -0
  160. package/dist/chrome/context-menus/build-menu.js.map +1 -0
  161. package/dist/chrome/context-menus/chrome-context-menus.d.ts +61 -0
  162. package/dist/chrome/context-menus/chrome-context-menus.d.ts.map +1 -0
  163. package/dist/chrome/context-menus/chrome-context-menus.js +219 -0
  164. package/dist/chrome/context-menus/chrome-context-menus.js.map +1 -0
  165. package/dist/chrome/context-menus/context-menu-entry.d.ts +20 -0
  166. package/dist/chrome/context-menus/context-menu-entry.d.ts.map +1 -0
  167. package/dist/chrome/context-menus/context-menu-entry.js +16 -0
  168. package/dist/chrome/context-menus/context-menu-entry.js.map +1 -0
  169. package/dist/chrome/context-menus/context-menu-schema.d.ts +29 -0
  170. package/dist/chrome/context-menus/context-menu-schema.d.ts.map +1 -0
  171. package/dist/chrome/context-menus/context-menu-schema.js +38 -0
  172. package/dist/chrome/context-menus/context-menu-schema.js.map +1 -0
  173. package/dist/chrome/context-menus/context-menu-types.d.ts +74 -0
  174. package/dist/chrome/context-menus/context-menu-types.d.ts.map +1 -0
  175. package/dist/chrome/context-menus/context-menu-types.js +29 -0
  176. package/dist/chrome/context-menus/context-menu-types.js.map +1 -0
  177. package/dist/chrome/context-menus/index.d.ts +5 -0
  178. package/dist/chrome/context-menus/index.d.ts.map +1 -0
  179. package/dist/chrome/context-menus/index.js +4 -0
  180. package/dist/chrome/context-menus/index.js.map +1 -0
  181. package/dist/chrome/i18n/chrome-i18n.d.ts +78 -0
  182. package/dist/chrome/i18n/chrome-i18n.d.ts.map +1 -0
  183. package/dist/chrome/i18n/chrome-i18n.js +151 -0
  184. package/dist/chrome/i18n/chrome-i18n.js.map +1 -0
  185. package/dist/chrome/i18n/detect-language.d.ts +23 -0
  186. package/dist/chrome/i18n/detect-language.d.ts.map +1 -0
  187. package/dist/chrome/i18n/detect-language.js +55 -0
  188. package/dist/chrome/i18n/detect-language.js.map +1 -0
  189. package/dist/chrome/i18n/index.d.ts +6 -0
  190. package/dist/chrome/i18n/index.d.ts.map +1 -0
  191. package/dist/chrome/i18n/index.js +3 -0
  192. package/dist/chrome/i18n/index.js.map +1 -0
  193. package/dist/chrome/i18n/language-defaults.d.ts +17 -0
  194. package/dist/chrome/i18n/language-defaults.d.ts.map +1 -0
  195. package/dist/chrome/i18n/language-defaults.js +123 -0
  196. package/dist/chrome/i18n/language-defaults.js.map +1 -0
  197. package/dist/chrome/i18n/locale-chain.d.ts +26 -0
  198. package/dist/chrome/i18n/locale-chain.d.ts.map +1 -0
  199. package/dist/chrome/i18n/locale-chain.js +38 -0
  200. package/dist/chrome/i18n/locale-chain.js.map +1 -0
  201. package/dist/chrome/i18n/message-format.d.ts +14 -0
  202. package/dist/chrome/i18n/message-format.d.ts.map +1 -0
  203. package/dist/chrome/i18n/message-format.js +40 -0
  204. package/dist/chrome/i18n/message-format.js.map +1 -0
  205. package/dist/chrome/i18n/messages-schema.d.ts +22 -0
  206. package/dist/chrome/i18n/messages-schema.d.ts.map +1 -0
  207. package/dist/chrome/i18n/messages-schema.js +48 -0
  208. package/dist/chrome/i18n/messages-schema.js.map +1 -0
  209. package/dist/chrome/install.d.ts +47 -0
  210. package/dist/chrome/install.d.ts.map +1 -0
  211. package/dist/chrome/install.js +35 -0
  212. package/dist/chrome/install.js.map +1 -0
  213. package/dist/chrome/notifications/chrome-notifications.d.ts +69 -0
  214. package/dist/chrome/notifications/chrome-notifications.d.ts.map +1 -0
  215. package/dist/chrome/notifications/chrome-notifications.js +201 -0
  216. package/dist/chrome/notifications/chrome-notifications.js.map +1 -0
  217. package/dist/chrome/notifications/index.d.ts +5 -0
  218. package/dist/chrome/notifications/index.d.ts.map +1 -0
  219. package/dist/chrome/notifications/index.js +4 -0
  220. package/dist/chrome/notifications/index.js.map +1 -0
  221. package/dist/chrome/notifications/notification-mapping.d.ts +35 -0
  222. package/dist/chrome/notifications/notification-mapping.d.ts.map +1 -0
  223. package/dist/chrome/notifications/notification-mapping.js +47 -0
  224. package/dist/chrome/notifications/notification-mapping.js.map +1 -0
  225. package/dist/chrome/notifications/notification-schema.d.ts +50 -0
  226. package/dist/chrome/notifications/notification-schema.d.ts.map +1 -0
  227. package/dist/chrome/notifications/notification-schema.js +68 -0
  228. package/dist/chrome/notifications/notification-schema.js.map +1 -0
  229. package/dist/chrome/notifications/notification-types.d.ts +50 -0
  230. package/dist/chrome/notifications/notification-types.d.ts.map +1 -0
  231. package/dist/chrome/notifications/notification-types.js +13 -0
  232. package/dist/chrome/notifications/notification-types.js.map +1 -0
  233. package/dist/chrome/permissions/chrome-permissions.d.ts +82 -0
  234. package/dist/chrome/permissions/chrome-permissions.d.ts.map +1 -0
  235. package/dist/chrome/permissions/chrome-permissions.js +190 -0
  236. package/dist/chrome/permissions/chrome-permissions.js.map +1 -0
  237. package/dist/chrome/permissions/index.d.ts +6 -0
  238. package/dist/chrome/permissions/index.d.ts.map +1 -0
  239. package/dist/chrome/permissions/index.js +4 -0
  240. package/dist/chrome/permissions/index.js.map +1 -0
  241. package/dist/chrome/permissions/permission-schema.d.ts +19 -0
  242. package/dist/chrome/permissions/permission-schema.d.ts.map +1 -0
  243. package/dist/chrome/permissions/permission-schema.js +60 -0
  244. package/dist/chrome/permissions/permission-schema.js.map +1 -0
  245. package/dist/chrome/permissions/permission-table.d.ts +15 -0
  246. package/dist/chrome/permissions/permission-table.d.ts.map +1 -0
  247. package/dist/chrome/permissions/permission-table.js +49 -0
  248. package/dist/chrome/permissions/permission-table.js.map +1 -0
  249. package/dist/chrome/permissions/permission-types.d.ts +6 -0
  250. package/dist/chrome/permissions/permission-types.d.ts.map +1 -0
  251. package/dist/chrome/permissions/permission-types.js +2 -0
  252. package/dist/chrome/permissions/permission-types.js.map +1 -0
  253. package/dist/chrome/runtime/identity.d.ts +58 -0
  254. package/dist/chrome/runtime/identity.d.ts.map +1 -0
  255. package/dist/chrome/runtime/identity.js +79 -0
  256. package/dist/chrome/runtime/identity.js.map +1 -0
  257. package/dist/chrome/runtime/index.d.ts +11 -0
  258. package/dist/chrome/runtime/index.d.ts.map +1 -0
  259. package/dist/chrome/runtime/index.js +6 -0
  260. package/dist/chrome/runtime/index.js.map +1 -0
  261. package/dist/chrome/runtime/installed.d.ts +47 -0
  262. package/dist/chrome/runtime/installed.d.ts.map +1 -0
  263. package/dist/chrome/runtime/installed.js +61 -0
  264. package/dist/chrome/runtime/installed.js.map +1 -0
  265. package/dist/chrome/runtime/link.d.ts +62 -0
  266. package/dist/chrome/runtime/link.d.ts.map +1 -0
  267. package/dist/chrome/runtime/link.js +154 -0
  268. package/dist/chrome/runtime/link.js.map +1 -0
  269. package/dist/chrome/runtime/message-event.d.ts +44 -0
  270. package/dist/chrome/runtime/message-event.d.ts.map +1 -0
  271. package/dist/chrome/runtime/message-event.js +95 -0
  272. package/dist/chrome/runtime/message-event.js.map +1 -0
  273. package/dist/chrome/runtime/native-host.d.ts +65 -0
  274. package/dist/chrome/runtime/native-host.d.ts.map +1 -0
  275. package/dist/chrome/runtime/native-host.js +165 -0
  276. package/dist/chrome/runtime/native-host.js.map +1 -0
  277. package/dist/chrome/runtime/native-message.d.ts +35 -0
  278. package/dist/chrome/runtime/native-message.d.ts.map +1 -0
  279. package/dist/chrome/runtime/native-message.js +68 -0
  280. package/dist/chrome/runtime/native-message.js.map +1 -0
  281. package/dist/chrome/runtime/port.d.ts +59 -0
  282. package/dist/chrome/runtime/port.d.ts.map +1 -0
  283. package/dist/chrome/runtime/port.js +84 -0
  284. package/dist/chrome/runtime/port.js.map +1 -0
  285. package/dist/chrome/runtime/runtime.d.ts +165 -0
  286. package/dist/chrome/runtime/runtime.d.ts.map +1 -0
  287. package/dist/chrome/runtime/runtime.js +244 -0
  288. package/dist/chrome/runtime/runtime.js.map +1 -0
  289. package/dist/chrome/storage/chrome-storage.d.ts +43 -0
  290. package/dist/chrome/storage/chrome-storage.d.ts.map +1 -0
  291. package/dist/chrome/storage/chrome-storage.js +80 -0
  292. package/dist/chrome/storage/chrome-storage.js.map +1 -0
  293. package/dist/chrome/storage/index.d.ts +7 -0
  294. package/dist/chrome/storage/index.d.ts.map +1 -0
  295. package/dist/chrome/storage/index.js +4 -0
  296. package/dist/chrome/storage/index.js.map +1 -0
  297. package/dist/chrome/storage/storage-area.d.ts +98 -0
  298. package/dist/chrome/storage/storage-area.d.ts.map +1 -0
  299. package/dist/chrome/storage/storage-area.js +251 -0
  300. package/dist/chrome/storage/storage-area.js.map +1 -0
  301. package/dist/chrome/storage/storage-types.d.ts +91 -0
  302. package/dist/chrome/storage/storage-types.d.ts.map +1 -0
  303. package/dist/chrome/storage/storage-types.js +72 -0
  304. package/dist/chrome/storage/storage-types.js.map +1 -0
  305. package/dist/chrome/system/create-chrome-system.d.ts +27 -0
  306. package/dist/chrome/system/create-chrome-system.d.ts.map +1 -0
  307. package/dist/chrome/system/create-chrome-system.js +25 -0
  308. package/dist/chrome/system/create-chrome-system.js.map +1 -0
  309. package/dist/chrome/system/index.d.ts +11 -0
  310. package/dist/chrome/system/index.d.ts.map +1 -0
  311. package/dist/chrome/system/index.js +8 -0
  312. package/dist/chrome/system/index.js.map +1 -0
  313. package/dist/chrome/system/system-backend.d.ts +50 -0
  314. package/dist/chrome/system/system-backend.d.ts.map +1 -0
  315. package/dist/chrome/system/system-backend.js +60 -0
  316. package/dist/chrome/system/system-backend.js.map +1 -0
  317. package/dist/chrome/system/system-cpu.d.ts +29 -0
  318. package/dist/chrome/system/system-cpu.d.ts.map +1 -0
  319. package/dist/chrome/system/system-cpu.js +43 -0
  320. package/dist/chrome/system/system-cpu.js.map +1 -0
  321. package/dist/chrome/system/system-display.d.ts +40 -0
  322. package/dist/chrome/system/system-display.d.ts.map +1 -0
  323. package/dist/chrome/system/system-display.js +81 -0
  324. package/dist/chrome/system/system-display.js.map +1 -0
  325. package/dist/chrome/system/system-memory.d.ts +17 -0
  326. package/dist/chrome/system/system-memory.d.ts.map +1 -0
  327. package/dist/chrome/system/system-memory.js +20 -0
  328. package/dist/chrome/system/system-memory.js.map +1 -0
  329. package/dist/chrome/system/system-storage.d.ts +25 -0
  330. package/dist/chrome/system/system-storage.d.ts.map +1 -0
  331. package/dist/chrome/system/system-storage.js +29 -0
  332. package/dist/chrome/system/system-storage.js.map +1 -0
  333. package/dist/chrome/system/system-types.d.ts +94 -0
  334. package/dist/chrome/system/system-types.d.ts.map +1 -0
  335. package/dist/chrome/system/system-types.js +7 -0
  336. package/dist/chrome/system/system-types.js.map +1 -0
  337. package/dist/chrome/windows/chrome-windows.d.ts +190 -0
  338. package/dist/chrome/windows/chrome-windows.d.ts.map +1 -0
  339. package/dist/chrome/windows/chrome-windows.js +292 -0
  340. package/dist/chrome/windows/chrome-windows.js.map +1 -0
  341. package/dist/chrome/windows/create-chrome-windows.d.ts +11 -0
  342. package/dist/chrome/windows/create-chrome-windows.d.ts.map +1 -0
  343. package/dist/chrome/windows/create-chrome-windows.js +12 -0
  344. package/dist/chrome/windows/create-chrome-windows.js.map +1 -0
  345. package/dist/chrome/windows/index.d.ts +8 -0
  346. package/dist/chrome/windows/index.d.ts.map +1 -0
  347. package/dist/chrome/windows/index.js +5 -0
  348. package/dist/chrome/windows/index.js.map +1 -0
  349. package/dist/chrome/windows/window-schema.d.ts +54 -0
  350. package/dist/chrome/windows/window-schema.d.ts.map +1 -0
  351. package/dist/chrome/windows/window-schema.js +28 -0
  352. package/dist/chrome/windows/window-schema.js.map +1 -0
  353. package/dist/chrome/windows/window-surface.d.ts +23 -0
  354. package/dist/chrome/windows/window-surface.d.ts.map +1 -0
  355. package/dist/chrome/windows/window-surface.js +2 -0
  356. package/dist/chrome/windows/window-surface.js.map +1 -0
  357. package/dist/chrome/windows/window-types.d.ts +68 -0
  358. package/dist/chrome/windows/window-types.d.ts.map +1 -0
  359. package/dist/chrome/windows/window-types.js +21 -0
  360. package/dist/chrome/windows/window-types.js.map +1 -0
  361. package/dist/chrome/windows/windows-surface.d.ts +30 -0
  362. package/dist/chrome/windows/windows-surface.d.ts.map +1 -0
  363. package/dist/chrome/windows/windows-surface.js +105 -0
  364. package/dist/chrome/windows/windows-surface.js.map +1 -0
  365. package/dist/components/convert.d.ts +2 -1
  366. package/dist/components/convert.d.ts.map +1 -1
  367. package/dist/components/convert.js.map +1 -1
  368. package/dist/components/hand-written/items/item-rows.svelte.d.ts +11 -0
  369. package/dist/components/hand-written/items/item-rows.svelte.d.ts.map +1 -1
  370. package/dist/components/hand-written/items/item-rows.svelte.js +29 -0
  371. package/dist/components/hand-written/items/item-rows.svelte.js.map +1 -1
  372. package/dist/components/hand-written/items/items-host.svelte.d.ts.map +1 -1
  373. package/dist/components/hand-written/items/items-host.svelte.js +1 -0
  374. package/dist/components/hand-written/items/items-host.svelte.js.map +1 -1
  375. package/dist/components/hand-written/items/repeater-host.svelte.d.ts.map +1 -1
  376. package/dist/components/hand-written/items/repeater-host.svelte.js +1 -0
  377. package/dist/components/hand-written/items/repeater-host.svelte.js.map +1 -1
  378. package/dist/composition/expression.d.ts +1 -1
  379. package/dist/data-transfer/clipboard.d.ts +8 -0
  380. package/dist/data-transfer/clipboard.d.ts.map +1 -1
  381. package/dist/data-transfer/clipboard.js +6 -0
  382. package/dist/data-transfer/clipboard.js.map +1 -1
  383. package/dist/data-transfer/data-transfer.d.ts +17 -0
  384. package/dist/data-transfer/data-transfer.d.ts.map +1 -1
  385. package/dist/data-transfer/data-transfer.js +17 -1
  386. package/dist/data-transfer/data-transfer.js.map +1 -1
  387. package/dist/data-transfer/drag-effects.d.ts +2 -2
  388. package/dist/data-transfer/package-io.d.ts +20 -1
  389. package/dist/data-transfer/package-io.d.ts.map +1 -1
  390. package/dist/data-transfer/package-io.js +26 -1
  391. package/dist/data-transfer/package-io.js.map +1 -1
  392. package/dist/data-transfer/winrt-package.d.ts +5 -0
  393. package/dist/data-transfer/winrt-package.d.ts.map +1 -1
  394. package/dist/data-transfer/winrt-package.js +52 -1
  395. package/dist/data-transfer/winrt-package.js.map +1 -1
  396. package/dist/downloads/chrome-downloads.d.ts +112 -0
  397. package/dist/downloads/chrome-downloads.d.ts.map +1 -0
  398. package/dist/downloads/chrome-downloads.js +360 -0
  399. package/dist/downloads/chrome-downloads.js.map +1 -0
  400. package/dist/downloads/chrome-event.d.ts +20 -0
  401. package/dist/downloads/chrome-event.d.ts.map +1 -0
  402. package/dist/downloads/chrome-event.js +39 -0
  403. package/dist/downloads/chrome-event.js.map +1 -0
  404. package/dist/downloads/download-query.d.ts +14 -0
  405. package/dist/downloads/download-query.d.ts.map +1 -0
  406. package/dist/downloads/download-query.js +152 -0
  407. package/dist/downloads/download-query.js.map +1 -0
  408. package/dist/downloads/download-record.d.ts +148 -0
  409. package/dist/downloads/download-record.d.ts.map +1 -0
  410. package/dist/downloads/download-record.js +142 -0
  411. package/dist/downloads/download-record.js.map +1 -0
  412. package/dist/downloads/download-target.d.ts +29 -0
  413. package/dist/downloads/download-target.d.ts.map +1 -0
  414. package/dist/downloads/download-target.js +68 -0
  415. package/dist/downloads/download-target.js.map +1 -0
  416. package/dist/downloads/download-transfer.d.ts +30 -0
  417. package/dist/downloads/download-transfer.d.ts.map +1 -0
  418. package/dist/downloads/download-transfer.js +126 -0
  419. package/dist/downloads/download-transfer.js.map +1 -0
  420. package/dist/downloads/download-types.d.ts +212 -0
  421. package/dist/downloads/download-types.d.ts.map +1 -0
  422. package/dist/downloads/download-types.js +92 -0
  423. package/dist/downloads/download-types.js.map +1 -0
  424. package/dist/downloads/fetch-to-file.d.ts +94 -0
  425. package/dist/downloads/fetch-to-file.d.ts.map +1 -0
  426. package/dist/downloads/fetch-to-file.js +159 -0
  427. package/dist/downloads/fetch-to-file.js.map +1 -0
  428. package/dist/downloads/index.d.ts +10 -0
  429. package/dist/downloads/index.d.ts.map +1 -0
  430. package/dist/downloads/index.js +6 -0
  431. package/dist/downloads/index.js.map +1 -0
  432. package/dist/downloads/interrupt-reason.d.ts +12 -0
  433. package/dist/downloads/interrupt-reason.d.ts.map +1 -0
  434. package/dist/downloads/interrupt-reason.js +57 -0
  435. package/dist/downloads/interrupt-reason.js.map +1 -0
  436. package/dist/downloads/taskbar-progress.d.ts +19 -0
  437. package/dist/downloads/taskbar-progress.d.ts.map +1 -0
  438. package/dist/downloads/taskbar-progress.js +39 -0
  439. package/dist/downloads/taskbar-progress.js.map +1 -0
  440. package/dist/downloads/zone-identifier.d.ts +21 -0
  441. package/dist/downloads/zone-identifier.d.ts.map +1 -0
  442. package/dist/downloads/zone-identifier.js +38 -0
  443. package/dist/downloads/zone-identifier.js.map +1 -0
  444. package/dist/enums.d.ts +5 -0
  445. package/dist/enums.d.ts.map +1 -1
  446. package/dist/enums.js +5 -0
  447. package/dist/enums.js.map +1 -1
  448. package/dist/incremental/incremental-source.svelte.d.ts +71 -0
  449. package/dist/incremental/incremental-source.svelte.d.ts.map +1 -0
  450. package/dist/incremental/incremental-source.svelte.js +138 -0
  451. package/dist/incremental/incremental-source.svelte.js.map +1 -0
  452. package/dist/incremental/index.d.ts +5 -0
  453. package/dist/incremental/index.d.ts.map +1 -0
  454. package/dist/incremental/index.js +3 -0
  455. package/dist/incremental/index.js.map +1 -0
  456. package/dist/incremental/state.d.ts +35 -0
  457. package/dist/incremental/state.d.ts.map +1 -0
  458. package/dist/incremental/state.js +12 -0
  459. package/dist/incremental/state.js.map +1 -0
  460. package/dist/media/index.d.ts +1 -0
  461. package/dist/media/index.d.ts.map +1 -1
  462. package/dist/media/index.js.map +1 -1
  463. package/dist/picture-source.d.ts +25 -0
  464. package/dist/picture-source.d.ts.map +1 -0
  465. package/dist/picture-source.js +2 -0
  466. package/dist/picture-source.js.map +1 -0
  467. package/dist/renderer/host/host.d.ts.map +1 -1
  468. package/dist/renderer/host/host.js +11 -14
  469. package/dist/renderer/host/host.js.map +1 -1
  470. package/dist/store/states.d.ts +2 -2
  471. package/dist/store/windows-packages.d.ts +2 -2
  472. package/dist/store/windows-store.d.ts +2 -2
  473. package/dist/tray/TrayIcon.d.svelte.ts +14 -2
  474. package/dist/tray/TrayIcon.svelte +65 -18
  475. package/dist/tray/TrayMenuFlyout.d.svelte.ts +6 -0
  476. package/dist/tray/TrayMenuFlyout.svelte +108 -0
  477. package/dist/tray/balloons.d.ts +7 -0
  478. package/dist/tray/balloons.d.ts.map +1 -0
  479. package/dist/tray/balloons.js +53 -0
  480. package/dist/tray/balloons.js.map +1 -0
  481. package/dist/tray/bounds.d.ts +7 -0
  482. package/dist/tray/bounds.d.ts.map +1 -0
  483. package/dist/tray/bounds.js +15 -0
  484. package/dist/tray/bounds.js.map +1 -0
  485. package/dist/tray/flyout-model.d.ts +43 -0
  486. package/dist/tray/flyout-model.d.ts.map +1 -0
  487. package/dist/tray/flyout-model.js +55 -0
  488. package/dist/tray/flyout-model.js.map +1 -0
  489. package/dist/tray/flyout-picker.d.ts +24 -0
  490. package/dist/tray/flyout-picker.d.ts.map +1 -0
  491. package/dist/tray/flyout-picker.js +46 -0
  492. package/dist/tray/flyout-picker.js.map +1 -0
  493. package/dist/tray/index.d.ts +3 -0
  494. package/dist/tray/index.d.ts.map +1 -1
  495. package/dist/tray/index.js +1 -0
  496. package/dist/tray/index.js.map +1 -1
  497. package/dist/tray/menu/default-profile.d.ts +12 -0
  498. package/dist/tray/menu/default-profile.d.ts.map +1 -0
  499. package/dist/tray/menu/default-profile.js +17 -0
  500. package/dist/tray/menu/default-profile.js.map +1 -0
  501. package/dist/tray/menu/define.d.ts +10 -0
  502. package/dist/tray/menu/define.d.ts.map +1 -0
  503. package/dist/tray/menu/define.js +11 -0
  504. package/dist/tray/menu/define.js.map +1 -0
  505. package/dist/tray/menu/describe.d.ts +12 -0
  506. package/dist/tray/menu/describe.d.ts.map +1 -0
  507. package/dist/tray/menu/describe.js +31 -0
  508. package/dist/tray/menu/describe.js.map +1 -0
  509. package/dist/tray/menu/expand.d.ts +20 -0
  510. package/dist/tray/menu/expand.d.ts.map +1 -0
  511. package/dist/tray/menu/expand.js +56 -0
  512. package/dist/tray/menu/expand.js.map +1 -0
  513. package/dist/tray/menu/index.d.ts +10 -0
  514. package/dist/tray/menu/index.d.ts.map +1 -0
  515. package/dist/tray/menu/index.js +9 -0
  516. package/dist/tray/menu/index.js.map +1 -0
  517. package/dist/tray/menu/profile-file.d.ts +22 -0
  518. package/dist/tray/menu/profile-file.d.ts.map +1 -0
  519. package/dist/tray/menu/profile-file.js +35 -0
  520. package/dist/tray/menu/profile-file.js.map +1 -0
  521. package/dist/tray/menu/profile.d.ts +29 -0
  522. package/dist/tray/menu/profile.d.ts.map +1 -0
  523. package/dist/tray/menu/profile.js +32 -0
  524. package/dist/tray/menu/profile.js.map +1 -0
  525. package/dist/tray/menu/resolve-lite.d.ts +44 -0
  526. package/dist/tray/menu/resolve-lite.d.ts.map +1 -0
  527. package/dist/tray/menu/resolve-lite.js +169 -0
  528. package/dist/tray/menu/resolve-lite.js.map +1 -0
  529. package/dist/tray/menu/resolve.d.ts +21 -0
  530. package/dist/tray/menu/resolve.d.ts.map +1 -0
  531. package/dist/tray/menu/resolve.js +56 -0
  532. package/dist/tray/menu/resolve.js.map +1 -0
  533. package/dist/tray/menu/types.d.ts +208 -0
  534. package/dist/tray/menu/types.d.ts.map +1 -0
  535. package/dist/tray/menu/types.js +19 -0
  536. package/dist/tray/menu/types.js.map +1 -0
  537. package/dist/tray/menu/values.d.ts +14 -0
  538. package/dist/tray/menu/values.d.ts.map +1 -0
  539. package/dist/tray/menu/values.js +15 -0
  540. package/dist/tray/menu/values.js.map +1 -0
  541. package/dist/tray/menu-svelte/TrayMenu.d.svelte.ts +6 -0
  542. package/dist/tray/menu-svelte/TrayMenu.svelte +20 -0
  543. package/dist/tray/menu-svelte/TrayMenuEditor.d.svelte.ts +17 -0
  544. package/dist/tray/menu-svelte/TrayMenuEditor.svelte +322 -0
  545. package/dist/tray/menu-svelte/TrayMenuHeader.d.svelte.ts +6 -0
  546. package/dist/tray/menu-svelte/TrayMenuHeader.svelte +9 -0
  547. package/dist/tray/menu-svelte/TrayMenuItem.d.svelte.ts +6 -0
  548. package/dist/tray/menu-svelte/TrayMenuItem.svelte +10 -0
  549. package/dist/tray/menu-svelte/TrayMenuSeparator.d.svelte.ts +6 -0
  550. package/dist/tray/menu-svelte/TrayMenuSeparator.svelte +9 -0
  551. package/dist/tray/menu-svelte/TrayMenuSubmenu.d.svelte.ts +6 -0
  552. package/dist/tray/menu-svelte/TrayMenuSubmenu.svelte +11 -0
  553. package/dist/tray/menu-svelte/collect.d.ts +22 -0
  554. package/dist/tray/menu-svelte/collect.d.ts.map +1 -0
  555. package/dist/tray/menu-svelte/collect.js +53 -0
  556. package/dist/tray/menu-svelte/collect.js.map +1 -0
  557. package/dist/tray/menu-svelte/edit-profile.d.ts +100 -0
  558. package/dist/tray/menu-svelte/edit-profile.d.ts.map +1 -0
  559. package/dist/tray/menu-svelte/edit-profile.js +200 -0
  560. package/dist/tray/menu-svelte/edit-profile.js.map +1 -0
  561. package/dist/tray/menu-svelte/editor-labels.d.ts +33 -0
  562. package/dist/tray/menu-svelte/editor-labels.d.ts.map +1 -0
  563. package/dist/tray/menu-svelte/editor-labels.js +30 -0
  564. package/dist/tray/menu-svelte/editor-labels.js.map +1 -0
  565. package/dist/tray/menu-svelte/editor-props.d.ts +22 -0
  566. package/dist/tray/menu-svelte/editor-props.d.ts.map +1 -0
  567. package/dist/tray/menu-svelte/editor-props.js +2 -0
  568. package/dist/tray/menu-svelte/editor-props.js.map +1 -0
  569. package/dist/tray/menu-svelte/index.d.ts +12 -0
  570. package/dist/tray/menu-svelte/index.d.ts.map +1 -0
  571. package/dist/tray/menu-svelte/index.js +9 -0
  572. package/dist/tray/menu-svelte/index.js.map +1 -0
  573. package/dist/tray/menu-svelte/menu-node.d.ts +125 -0
  574. package/dist/tray/menu-svelte/menu-node.d.ts.map +1 -0
  575. package/dist/tray/menu-svelte/menu-node.js +82 -0
  576. package/dist/tray/menu-svelte/menu-node.js.map +1 -0
  577. package/dist/tray/menu-svelte/menu-props.d.ts +35 -0
  578. package/dist/tray/menu-svelte/menu-props.d.ts.map +1 -0
  579. package/dist/tray/menu-svelte/menu-props.js +2 -0
  580. package/dist/tray/menu-svelte/menu-props.js.map +1 -0
  581. package/dist/tray/menu-svelte/menu-source.d.ts +36 -0
  582. package/dist/tray/menu-svelte/menu-source.d.ts.map +1 -0
  583. package/dist/tray/menu-svelte/menu-source.js +54 -0
  584. package/dist/tray/menu-svelte/menu-source.js.map +1 -0
  585. package/dist/tray/menu-svelte/preview-lines.d.ts +20 -0
  586. package/dist/tray/menu-svelte/preview-lines.d.ts.map +1 -0
  587. package/dist/tray/menu-svelte/preview-lines.js +40 -0
  588. package/dist/tray/menu-svelte/preview-lines.js.map +1 -0
  589. package/dist/tray/native.d.ts +30 -7
  590. package/dist/tray/native.d.ts.map +1 -1
  591. package/dist/tray/native.js +100 -209
  592. package/dist/tray/native.js.map +1 -1
  593. package/dist/tray/standalone/define-tray.d.ts +26 -0
  594. package/dist/tray/standalone/define-tray.d.ts.map +1 -0
  595. package/dist/tray/standalone/define-tray.js +15 -0
  596. package/dist/tray/standalone/define-tray.js.map +1 -0
  597. package/dist/tray/standalone/index.d.ts +13 -4
  598. package/dist/tray/standalone/index.d.ts.map +1 -1
  599. package/dist/tray/standalone/index.js +6 -1
  600. package/dist/tray/standalone/index.js.map +1 -1
  601. package/dist/tray/standalone/native.d.ts +39 -23
  602. package/dist/tray/standalone/native.d.ts.map +1 -1
  603. package/dist/tray/standalone/native.js +144 -76
  604. package/dist/tray/standalone/native.js.map +1 -1
  605. package/dist/tray/standalone/standalone-tray.d.ts +43 -19
  606. package/dist/tray/standalone/standalone-tray.d.ts.map +1 -1
  607. package/dist/tray/standalone/standalone-tray.js +43 -41
  608. package/dist/tray/standalone/standalone-tray.js.map +1 -1
  609. package/dist/tray/themed-icon.d.ts +7 -0
  610. package/dist/tray/themed-icon.d.ts.map +1 -0
  611. package/dist/tray/themed-icon.js +39 -0
  612. package/dist/tray/themed-icon.js.map +1 -0
  613. package/dist/tray/tray-core.d.ts +11 -10
  614. package/dist/tray/tray-core.d.ts.map +1 -1
  615. package/dist/tray/tray-core.js +20 -31
  616. package/dist/tray/tray-core.js.map +1 -1
  617. package/dist/tray/tray-extras.d.ts +61 -0
  618. package/dist/tray/tray-extras.d.ts.map +1 -0
  619. package/dist/tray/tray-extras.js +2 -0
  620. package/dist/tray/tray-extras.js.map +1 -0
  621. package/dist/tray/tray-icon-props.d.ts +18 -5
  622. package/dist/tray/tray-icon-props.d.ts.map +1 -1
  623. package/dist/tray/tray-icon.d.ts +4 -2
  624. package/dist/tray/tray-icon.d.ts.map +1 -1
  625. package/dist/tray/tray-icon.js +13 -3
  626. package/dist/tray/tray-icon.js.map +1 -1
  627. package/dist/tray/tray-manifest.d.ts +18 -0
  628. package/dist/tray/tray-manifest.d.ts.map +1 -0
  629. package/dist/tray/tray-manifest.js +22 -0
  630. package/dist/tray/tray-manifest.js.map +1 -0
  631. package/dist/tray/tray-menu-flyout-props.d.ts +15 -0
  632. package/dist/tray/tray-menu-flyout-props.d.ts.map +1 -0
  633. package/dist/tray/tray-menu-flyout-props.js +2 -0
  634. package/dist/tray/tray-menu-flyout-props.js.map +1 -0
  635. package/dist/tray/tray-menu.d.ts +2 -2
  636. package/dist/tray/tray-menu.d.ts.map +1 -1
  637. package/dist/vite/build.d.ts +5 -1
  638. package/dist/vite/build.d.ts.map +1 -1
  639. package/dist/vite/build.js +26 -5
  640. package/dist/vite/build.js.map +1 -1
  641. package/dist/vite/entrypoints/build-tray.d.ts +27 -0
  642. package/dist/vite/entrypoints/build-tray.d.ts.map +1 -0
  643. package/dist/vite/entrypoints/build-tray.js +66 -0
  644. package/dist/vite/entrypoints/build-tray.js.map +1 -0
  645. package/dist/vite/entrypoints/discover.d.ts +30 -0
  646. package/dist/vite/entrypoints/discover.d.ts.map +1 -0
  647. package/dist/vite/entrypoints/discover.js +61 -0
  648. package/dist/vite/entrypoints/discover.js.map +1 -0
  649. package/dist/vite/entrypoints/extract-tray.d.ts +14 -0
  650. package/dist/vite/entrypoints/extract-tray.d.ts.map +1 -0
  651. package/dist/vite/entrypoints/extract-tray.js +83 -0
  652. package/dist/vite/entrypoints/extract-tray.js.map +1 -0
  653. package/dist/vite/entrypoints/lower-menu-markup.d.ts +40 -0
  654. package/dist/vite/entrypoints/lower-menu-markup.d.ts.map +1 -0
  655. package/dist/vite/entrypoints/lower-menu-markup.js +339 -0
  656. package/dist/vite/entrypoints/lower-menu-markup.js.map +1 -0
  657. package/dist/vite/entrypoints/lower-tray-svelte.d.ts +14 -0
  658. package/dist/vite/entrypoints/lower-tray-svelte.d.ts.map +1 -0
  659. package/dist/vite/entrypoints/lower-tray-svelte.js +259 -0
  660. package/dist/vite/entrypoints/lower-tray-svelte.js.map +1 -0
  661. package/dist/vite/entrypoints/node-span.d.ts +13 -0
  662. package/dist/vite/entrypoints/node-span.d.ts.map +1 -0
  663. package/dist/vite/entrypoints/node-span.js +32 -0
  664. package/dist/vite/entrypoints/node-span.js.map +1 -0
  665. package/dist/vite/entrypoints/tray-dev-plugin.d.ts +9 -0
  666. package/dist/vite/entrypoints/tray-dev-plugin.d.ts.map +1 -0
  667. package/dist/vite/entrypoints/tray-dev-plugin.js +102 -0
  668. package/dist/vite/entrypoints/tray-dev-plugin.js.map +1 -0
  669. package/dist/vite/entrypoints/tray-module.d.ts +22 -0
  670. package/dist/vite/entrypoints/tray-module.d.ts.map +1 -0
  671. package/dist/vite/entrypoints/tray-module.js +54 -0
  672. package/dist/vite/entrypoints/tray-module.js.map +1 -0
  673. package/dist/vite/entrypoints/tray-process.d.ts +39 -0
  674. package/dist/vite/entrypoints/tray-process.d.ts.map +1 -0
  675. package/dist/vite/entrypoints/tray-process.js +59 -0
  676. package/dist/vite/entrypoints/tray-process.js.map +1 -0
  677. package/dist/vite/entrypoints/tray-source.d.ts +11 -0
  678. package/dist/vite/entrypoints/tray-source.d.ts.map +1 -0
  679. package/dist/vite/entrypoints/tray-source.js +20 -0
  680. package/dist/vite/entrypoints/tray-source.js.map +1 -0
  681. package/dist/vite/entrypoints/tray-svelte-error.d.ts +14 -0
  682. package/dist/vite/entrypoints/tray-svelte-error.d.ts.map +1 -0
  683. package/dist/vite/entrypoints/tray-svelte-error.js +22 -0
  684. package/dist/vite/entrypoints/tray-svelte-error.js.map +1 -0
  685. package/dist/vite/externals.d.ts +7 -0
  686. package/dist/vite/externals.d.ts.map +1 -0
  687. package/dist/vite/externals.js +18 -0
  688. package/dist/vite/externals.js.map +1 -0
  689. package/dist/vite/plugin.d.ts.map +1 -1
  690. package/dist/vite/plugin.js +3 -12
  691. package/dist/vite/plugin.js.map +1 -1
  692. package/dist/web-apis/clipboard.d.ts.map +1 -1
  693. package/dist/web-apis/clipboard.js +48 -17
  694. package/dist/web-apis/clipboard.js.map +1 -1
  695. package/dist/web-apis/dialog-types.d.ts +81 -0
  696. package/dist/web-apis/dialog-types.d.ts.map +1 -0
  697. package/dist/web-apis/dialog-types.js +14 -0
  698. package/dist/web-apis/dialog-types.js.map +1 -0
  699. package/dist/web-apis/dialogs-windows.d.ts +25 -0
  700. package/dist/web-apis/dialogs-windows.d.ts.map +1 -0
  701. package/dist/web-apis/dialogs-windows.js +114 -0
  702. package/dist/web-apis/dialogs-windows.js.map +1 -0
  703. package/dist/web-apis/dialogs.d.ts +76 -0
  704. package/dist/web-apis/dialogs.d.ts.map +1 -0
  705. package/dist/web-apis/dialogs.js +250 -0
  706. package/dist/web-apis/dialogs.js.map +1 -0
  707. package/dist/web-apis/geolocation.d.ts.map +1 -1
  708. package/dist/web-apis/geolocation.js +14 -8
  709. package/dist/web-apis/geolocation.js.map +1 -1
  710. package/dist/web-apis/idle.d.ts +1 -1
  711. package/dist/web-apis/image-codec-windows.d.ts +24 -0
  712. package/dist/web-apis/image-codec-windows.d.ts.map +1 -0
  713. package/dist/web-apis/image-codec-windows.js +107 -0
  714. package/dist/web-apis/image-codec-windows.js.map +1 -0
  715. package/dist/web-apis/image-pixels.d.ts +27 -0
  716. package/dist/web-apis/image-pixels.d.ts.map +1 -0
  717. package/dist/web-apis/image-pixels.js +152 -0
  718. package/dist/web-apis/image-pixels.js.map +1 -0
  719. package/dist/web-apis/image-types.d.ts +64 -0
  720. package/dist/web-apis/image-types.d.ts.map +1 -0
  721. package/dist/web-apis/image-types.js +23 -0
  722. package/dist/web-apis/image-types.js.map +1 -0
  723. package/dist/web-apis/images.d.ts +199 -0
  724. package/dist/web-apis/images.d.ts.map +1 -0
  725. package/dist/web-apis/images.js +476 -0
  726. package/dist/web-apis/images.js.map +1 -0
  727. package/dist/web-apis/media-access.d.ts +1 -1
  728. package/dist/web-apis/notification.d.ts +6 -5
  729. package/dist/web-apis/notification.d.ts.map +1 -1
  730. package/dist/web-apis/notification.js.map +1 -1
  731. package/dist/web-apis/page.d.ts +1 -1
  732. package/dist/web-apis/permissions.d.ts +17 -0
  733. package/dist/web-apis/permissions.d.ts.map +1 -1
  734. package/dist/web-apis/permissions.js +25 -0
  735. package/dist/web-apis/permissions.js.map +1 -1
  736. package/dist/web-apis/png-writer.d.ts +9 -0
  737. package/dist/web-apis/png-writer.d.ts.map +1 -0
  738. package/dist/web-apis/png-writer.js +58 -0
  739. package/dist/web-apis/png-writer.js.map +1 -0
  740. package/dist/web-apis/push.d.ts +1 -1
  741. package/dist/web-apis/scroll-timeline.d.ts +1 -1
  742. package/dist/win32-calls.d.ts +32 -0
  743. package/dist/win32-calls.d.ts.map +1 -1
  744. package/dist/win32-calls.js +44 -0
  745. package/dist/win32-calls.js.map +1 -1
  746. package/dist/win32-icons.d.ts.map +1 -1
  747. package/dist/win32-icons.js +11 -31
  748. package/dist/win32-icons.js.map +1 -1
  749. package/dist/window/create-window.d.ts +3 -0
  750. package/dist/window/create-window.d.ts.map +1 -1
  751. package/dist/window/create-window.js +1 -0
  752. package/dist/window/create-window.js.map +1 -1
  753. package/dist/window/taskbar-calls.d.ts +28 -0
  754. package/dist/window/taskbar-calls.d.ts.map +1 -1
  755. package/dist/window/taskbar-calls.js +34 -0
  756. package/dist/window/taskbar-calls.js.map +1 -1
  757. package/dist/window/taskbar-native.d.ts.map +1 -1
  758. package/dist/window/taskbar-native.js +35 -1
  759. package/dist/window/taskbar-native.js.map +1 -1
  760. package/dist/window/taskbar.d.ts +34 -5
  761. package/dist/window/taskbar.d.ts.map +1 -1
  762. package/dist/window/taskbar.js +28 -3
  763. package/dist/window/taskbar.js.map +1 -1
  764. package/dist/window/window-host.svelte.d.ts +2 -1
  765. package/dist/window/window-host.svelte.d.ts.map +1 -1
  766. package/dist/window/window-host.svelte.js.map +1 -1
  767. package/dist/window/window-state.d.ts +1 -1
  768. package/dist/winui.d.ts +7 -0
  769. package/dist/winui.d.ts.map +1 -1
  770. package/dist/winui.js +7 -0
  771. package/dist/winui.js.map +1 -1
  772. package/package.json +83 -1
  773. package/src/app/activation/alarm-argument.ts +55 -0
  774. package/src/app/activation/classify.ts +36 -5
  775. package/src/app/activation/index.ts +1 -1
  776. package/src/app/activation/jump-list-argument.ts +30 -0
  777. package/src/app/activation/kinds.ts +24 -2
  778. package/src/app/activation/receive.ts +15 -1
  779. package/src/app/activation/registration.ts +11 -3
  780. package/src/app/activation/scheme.ts +11 -1
  781. package/src/app/index.ts +2 -0
  782. package/src/app/instance-pipe.ts +1 -3
  783. package/src/app/jump-list/index.ts +100 -0
  784. package/src/app/jump-list/native.ts +309 -0
  785. package/src/app/jump-list/tasks.ts +166 -0
  786. package/src/app/schedule/alarm.ts +11 -0
  787. package/src/app/schedule/alarms.ts +240 -0
  788. package/src/app/schedule/backend.ts +23 -0
  789. package/src/app/schedule/events.ts +67 -0
  790. package/src/app/schedule/index.ts +6 -0
  791. package/src/app/schedule/native.ts +78 -0
  792. package/src/app/schedule/occurrence.ts +45 -0
  793. package/src/app/schedule/xml.ts +115 -0
  794. package/src/app/shell/app-paths.ts +145 -0
  795. package/src/app/shell/backend.ts +30 -0
  796. package/src/app/shell/index.ts +11 -0
  797. package/src/app/shell/kinds.ts +52 -0
  798. package/src/app/shell/native.ts +336 -0
  799. package/src/app/shell/open-with.ts +62 -0
  800. package/src/app/shell/paths.ts +29 -0
  801. package/src/app/shell/shortcut.ts +163 -0
  802. package/src/app/shell/trash.ts +53 -0
  803. package/src/app/tray-instance.ts +75 -0
  804. package/src/chrome/action/action-types.ts +123 -0
  805. package/src/chrome/action/chrome-action.ts +234 -0
  806. package/src/chrome/action/create-chrome-action.ts +35 -0
  807. package/src/chrome/action/index.ts +13 -0
  808. package/src/chrome/commands/chrome-commands.ts +174 -0
  809. package/src/chrome/commands/command-types.ts +48 -0
  810. package/src/chrome/commands/index.ts +6 -0
  811. package/src/chrome/commands/shortcut.ts +107 -0
  812. package/src/chrome/context-menus/build-menu.ts +121 -0
  813. package/src/chrome/context-menus/chrome-context-menus.ts +255 -0
  814. package/src/chrome/context-menus/context-menu-entry.ts +34 -0
  815. package/src/chrome/context-menus/context-menu-schema.ts +48 -0
  816. package/src/chrome/context-menus/context-menu-types.ts +94 -0
  817. package/src/chrome/context-menus/index.ts +4 -0
  818. package/src/chrome/i18n/chrome-i18n.ts +197 -0
  819. package/src/chrome/i18n/detect-language.ts +67 -0
  820. package/src/chrome/i18n/index.ts +5 -0
  821. package/src/chrome/i18n/language-defaults.ts +167 -0
  822. package/src/chrome/i18n/locale-chain.ts +44 -0
  823. package/src/chrome/i18n/message-format.ts +60 -0
  824. package/src/chrome/i18n/messages-schema.ts +61 -0
  825. package/src/chrome/install.ts +75 -0
  826. package/src/chrome/notifications/chrome-notifications.ts +249 -0
  827. package/src/chrome/notifications/index.ts +8 -0
  828. package/src/chrome/notifications/notification-mapping.ts +63 -0
  829. package/src/chrome/notifications/notification-schema.ts +80 -0
  830. package/src/chrome/notifications/notification-types.ts +60 -0
  831. package/src/chrome/permissions/chrome-permissions.ts +259 -0
  832. package/src/chrome/permissions/index.ts +5 -0
  833. package/src/chrome/permissions/permission-schema.ts +75 -0
  834. package/src/chrome/permissions/permission-table.ts +54 -0
  835. package/src/chrome/permissions/permission-types.ts +5 -0
  836. package/src/chrome/runtime/identity.ts +115 -0
  837. package/src/chrome/runtime/index.ts +10 -0
  838. package/src/chrome/runtime/installed.ts +85 -0
  839. package/src/chrome/runtime/link.ts +211 -0
  840. package/src/chrome/runtime/message-event.ts +126 -0
  841. package/src/chrome/runtime/native-host.ts +220 -0
  842. package/src/chrome/runtime/native-message.ts +78 -0
  843. package/src/chrome/runtime/port.ts +117 -0
  844. package/src/chrome/runtime/runtime.ts +317 -0
  845. package/src/chrome/storage/chrome-storage.ts +120 -0
  846. package/src/chrome/storage/index.ts +13 -0
  847. package/src/chrome/storage/storage-area.ts +318 -0
  848. package/src/chrome/storage/storage-types.ts +115 -0
  849. package/src/chrome/system/create-chrome-system.ts +32 -0
  850. package/src/chrome/system/index.ts +21 -0
  851. package/src/chrome/system/system-backend.ts +88 -0
  852. package/src/chrome/system/system-cpu.ts +49 -0
  853. package/src/chrome/system/system-display.ts +94 -0
  854. package/src/chrome/system/system-memory.ts +24 -0
  855. package/src/chrome/system/system-storage.ts +33 -0
  856. package/src/chrome/system/system-types.ts +112 -0
  857. package/src/chrome/windows/chrome-windows.ts +372 -0
  858. package/src/chrome/windows/create-chrome-windows.ts +13 -0
  859. package/src/chrome/windows/index.ts +7 -0
  860. package/src/chrome/windows/window-schema.ts +32 -0
  861. package/src/chrome/windows/window-surface.ts +27 -0
  862. package/src/chrome/windows/window-types.ts +80 -0
  863. package/src/chrome/windows/windows-surface.ts +114 -0
  864. package/src/components/convert.ts +2 -1
  865. package/src/components/hand-written/items/item-rows.svelte.ts +37 -0
  866. package/src/components/hand-written/items/items-host.svelte.ts +2 -0
  867. package/src/components/hand-written/items/repeater-host.svelte.ts +1 -0
  868. package/src/data-transfer/clipboard.ts +15 -0
  869. package/src/data-transfer/data-transfer.ts +29 -1
  870. package/src/data-transfer/package-io.ts +36 -2
  871. package/src/data-transfer/winrt-package.ts +65 -1
  872. package/src/downloads/chrome-downloads.ts +434 -0
  873. package/src/downloads/chrome-event.ts +42 -0
  874. package/src/downloads/download-query.ts +204 -0
  875. package/src/downloads/download-record.ts +176 -0
  876. package/src/downloads/download-target.ts +79 -0
  877. package/src/downloads/download-transfer.ts +160 -0
  878. package/src/downloads/download-types.ts +173 -0
  879. package/src/downloads/fetch-to-file.ts +246 -0
  880. package/src/downloads/index.ts +22 -0
  881. package/src/downloads/interrupt-reason.ts +64 -0
  882. package/src/downloads/taskbar-progress.ts +50 -0
  883. package/src/downloads/zone-identifier.ts +42 -0
  884. package/src/enums.ts +5 -0
  885. package/src/incremental/incremental-source.svelte.ts +181 -0
  886. package/src/incremental/index.ts +4 -0
  887. package/src/incremental/state.ts +33 -0
  888. package/src/media/index.ts +1 -0
  889. package/src/picture-source.ts +26 -0
  890. package/src/renderer/host/host.ts +12 -15
  891. package/src/tray/TrayIcon.d.svelte.ts +14 -2
  892. package/src/tray/TrayMenuFlyout.d.svelte.ts +6 -0
  893. package/src/tray/balloons.ts +58 -0
  894. package/src/tray/bounds.ts +16 -0
  895. package/src/tray/flyout-model.ts +77 -0
  896. package/src/tray/flyout-picker.ts +56 -0
  897. package/src/tray/index.ts +3 -0
  898. package/src/tray/menu/default-profile.ts +20 -0
  899. package/src/tray/menu/define.ts +12 -0
  900. package/src/tray/menu/describe.ts +39 -0
  901. package/src/tray/menu/expand.ts +75 -0
  902. package/src/tray/menu/index.ts +30 -0
  903. package/src/tray/menu/profile-file.ts +44 -0
  904. package/src/tray/menu/profile.ts +39 -0
  905. package/src/tray/menu/resolve-lite.ts +226 -0
  906. package/src/tray/menu/resolve.ts +72 -0
  907. package/src/tray/menu/types.ts +270 -0
  908. package/src/tray/menu/values.ts +21 -0
  909. package/src/tray/menu-svelte/TrayMenu.d.svelte.ts +6 -0
  910. package/src/tray/menu-svelte/TrayMenuEditor.d.svelte.ts +17 -0
  911. package/src/tray/menu-svelte/TrayMenuHeader.d.svelte.ts +6 -0
  912. package/src/tray/menu-svelte/TrayMenuItem.d.svelte.ts +6 -0
  913. package/src/tray/menu-svelte/TrayMenuSeparator.d.svelte.ts +6 -0
  914. package/src/tray/menu-svelte/TrayMenuSubmenu.d.svelte.ts +6 -0
  915. package/src/tray/menu-svelte/collect.ts +58 -0
  916. package/src/tray/menu-svelte/edit-profile.ts +263 -0
  917. package/src/tray/menu-svelte/editor-labels.ts +54 -0
  918. package/src/tray/menu-svelte/editor-props.ts +27 -0
  919. package/src/tray/menu-svelte/index.ts +17 -0
  920. package/src/tray/menu-svelte/menu-node.ts +119 -0
  921. package/src/tray/menu-svelte/menu-props.ts +52 -0
  922. package/src/tray/menu-svelte/menu-source.ts +83 -0
  923. package/src/tray/menu-svelte/preview-lines.ts +58 -0
  924. package/src/tray/native.ts +121 -225
  925. package/src/tray/standalone/define-tray.ts +36 -0
  926. package/src/tray/standalone/index.ts +18 -6
  927. package/src/tray/standalone/native.ts +176 -106
  928. package/src/tray/standalone/standalone-tray.ts +103 -65
  929. package/src/tray/themed-icon.ts +48 -0
  930. package/src/tray/tray-core.ts +36 -43
  931. package/src/tray/tray-extras.ts +71 -0
  932. package/src/tray/tray-icon-props.ts +20 -5
  933. package/src/tray/tray-icon.ts +16 -4
  934. package/src/tray/tray-manifest.ts +25 -0
  935. package/src/tray/tray-menu-flyout-props.ts +17 -0
  936. package/src/tray/tray-menu.ts +2 -2
  937. package/src/vite/build.ts +35 -7
  938. package/src/vite/entrypoints/build-tray.ts +85 -0
  939. package/src/vite/entrypoints/discover.ts +75 -0
  940. package/src/vite/entrypoints/extract-tray.ts +99 -0
  941. package/src/vite/entrypoints/lower-menu-markup.ts +443 -0
  942. package/src/vite/entrypoints/lower-tray-svelte.ts +329 -0
  943. package/src/vite/entrypoints/node-span.ts +36 -0
  944. package/src/vite/entrypoints/tray-dev-plugin.ts +111 -0
  945. package/src/vite/entrypoints/tray-module.ts +59 -0
  946. package/src/vite/entrypoints/tray-process.ts +83 -0
  947. package/src/vite/entrypoints/tray-source.ts +21 -0
  948. package/src/vite/entrypoints/tray-svelte-error.ts +31 -0
  949. package/src/vite/externals.ts +19 -0
  950. package/src/vite/plugin.ts +3 -14
  951. package/src/web-apis/clipboard.ts +63 -16
  952. package/src/web-apis/dialog-types.ts +99 -0
  953. package/src/web-apis/dialogs-windows.ts +144 -0
  954. package/src/web-apis/dialogs.ts +312 -0
  955. package/src/web-apis/geolocation.ts +14 -8
  956. package/src/web-apis/image-codec-windows.ts +140 -0
  957. package/src/web-apis/image-pixels.ts +191 -0
  958. package/src/web-apis/image-types.ts +74 -0
  959. package/src/web-apis/images.ts +697 -0
  960. package/src/web-apis/notification.ts +5 -4
  961. package/src/web-apis/permissions.ts +31 -0
  962. package/src/web-apis/png-writer.ts +66 -0
  963. package/src/win32-calls.ts +86 -0
  964. package/src/win32-icons.ts +11 -31
  965. package/src/window/create-window.ts +5 -0
  966. package/src/window/taskbar-calls.ts +47 -0
  967. package/src/window/taskbar-native.ts +42 -0
  968. package/src/window/taskbar.ts +55 -6
  969. package/src/window/window-host.svelte.ts +2 -1
  970. package/src/winui.ts +7 -0
  971. package/web-types.json +421 -0
package/API.md CHANGED
@@ -18,6 +18,7 @@ monorepo needs no build step (the repository is a pnpm workspace, see
18
18
  | `winui-svelte/host` | `src/renderer/host/host.ts` | `renderer`, the renderer WinUI controls are built through (`mountControl` makes it the active one), and the mount-target plumbing below; not for app code |
19
19
  | `winui-svelte/scroll-timeline` | `src/web-apis/scroll-timeline.ts` | `installScrollTimeline()`: `ScrollTimeline`, `ViewTimeline` and `element.animate(keyframes, { timeline })` over Composition (the CSS side is `winui-svelte/css/scroll-timeline`, which a sheet that uses `animation-timeline` imports) |
20
20
  | `winui-svelte/view-transitions` | `src/web-apis/view-transitions.ts` | `installViewTransitions()`: `document.startViewTransition` and `ViewTransition` over WinUI's connected animations (the CSS side is `winui-svelte/css/view-transition`, which a sheet or style attribute that sets `view-transition-name` imports) |
21
+ | `winui-svelte/dialogs` | `src/web-apis/dialogs.ts` | `installDialogs()`, `showDialog()`, `useDialogWindow()`, `DialogResult`, `DialogButton`: `alert`, `confirm` and `prompt` over `ContentDialog`, as promises (opt-in; see Dialogs) |
21
22
  | `winui-svelte/element-animation` | `src/renderer/host/element-animation.ts` | `enableElementAnimation()`: what Svelte's `transition:`, `in:`, `out:`, `animate:` and `svelte/motion` ask of an element, on WinUI controls (the Vite plugin calls it from a component that uses them; otherwise not bundled) |
22
23
  | `winui-svelte/attached-owners` | `src/components/attached-owners.ts` | `preloadAttachedOwners(names)`: loads the modules attached properties (`canvasLeft`, `gridRow`) are written through (the Vite plugin calls it from a component whose markup or script names one, so the property is set with the control; a prop named nowhere, built from a computed key, needs `await preloadAttachedOwners(["Canvas"])` first, or its control throws) |
23
24
  | `winui-svelte/settings` | `src/settings/index.ts` | `SettingsCard`, `SettingsExpander`: Fluent settings cards after the Community Toolkit's (opt-in) |
@@ -37,16 +38,27 @@ monorepo needs no build step (the repository is a pnpm workspace, see
37
38
  | `winui-svelte/bootstrap` | `src/window/bootstrap.ts` | `initWindowsAppSdk()`; imports nothing of WinRT, safe on the host's main thread |
38
39
  | `winui-svelte/thread` | `src/window/thread.ts` | `runOnUiThread()`; imports only dynwinrt, so the apartment comes first |
39
40
  | `winui-svelte/window` | `src/window/index.ts` | `runWindow()`, `exitApplication()`, `createWindow()`, `startTimer()`, `systemSettings()`, the picker options (see App services) |
40
- | `winui-svelte/app` | `src/app/index.ts` | `ensureSingleInstance()`, `notify()`, `activateInstance()`, `activateOrLaunch()`, `launchApp()`, `relaunch()`, `restartAfterCrash()` (opt-in; see App lifecycle) |
41
+ | `winui-svelte/app` | `src/app/index.ts` | `ensureSingleInstance()`, `notify()`, `activateInstance()`, `activateOrLaunch()`, `launchApp()`, `startTray()`, `relaunch()`, `restartAfterCrash()` (opt-in; see App lifecycle) |
42
+ | `winui-svelte/app/shell` | `src/app/shell/index.ts` | `trash()`, `openWith()`, `createShortcut()`, `readShortcut()`, `registerAppPath()`, `ShellFailure` (opt-in; see Shell verbs) |
41
43
  | `winui-svelte/app/activation` | `src/app/activation/index.ts` | `installProtocolHandlers()`, `registerFileTypes()`, `launchAtLogin()`, `startActivation()`, `ActivationKind` (opt-in; see Activation) |
44
+ | `winui-svelte/app/jump-list` | `src/app/jump-list/index.ts` | `setJumpListTasks()`, `clearJumpList()` (opt-in; see Jump list tasks) |
42
45
  | `winui-svelte/data-transfer` | `src/data-transfer/index.ts` | `enableDragEvents()`, `dropzone`, `draggable`, `filePicker`, `pickFiles`, `pickSaveFile`, `clipboard`, `launchUri` / `launchFile` / `openFolder` / `revealInExplorer`, `share`, `NativeFile`, `DataTransfer`, `DragEvent` (opt-in; see Data transfer) |
46
+ | `winui-svelte/incremental` | `src/incremental/index.ts` | `createIncrementalSource()`, `IncrementalSource`, `IncrementalStatus`, `IncrementalState` (opt-in; see Incremental loading) |
47
+ | `winui-svelte/downloads` | `src/downloads/index.ts` | `Downloads` (`chrome.downloads`), `fetchToFile()`, `markOfTheWeb()`, `DownloadError` (opt-in; see Downloads) |
48
+ | `winui-svelte/chrome/runtime` | `src/chrome/runtime/index.ts` | `Runtime` (`chrome.runtime`), `Port`, `InstallReason`, the native messaging codec (opt-in; see Chrome runtime) |
49
+ | `winui-svelte/chrome/notifications` | `src/chrome/notifications/index.ts` | `ChromeNotifications` (`chrome.notifications`), `NotificationTemplateType`, `NotificationPermissionLevel` (opt-in; see Chrome notifications) |
50
+
51
+ | `winui-svelte/chrome/commands` | `src/chrome/commands/index.ts` | `ChromeCommands` (`chrome.commands`), `parseShortcut()` (opt-in; see Chrome commands) |
52
+ | `winui-svelte/chrome/action` | `src/chrome/action/index.ts` | `ChromeAction` (`chrome.action`), `createChromeAction()` (opt-in; see Chrome action) |
53
+ | `winui-svelte/chrome/i18n` | `src/chrome/i18n/index.ts` | `ChromeI18n` (`chrome.i18n`), `installLanguageDefaults()` (opt-in; see Chrome i18n) |
54
+ | `winui-svelte/chrome/install` | `src/chrome/install.ts` | `installChromeApis()`, `ChromeGlobal`, `ChromeAlarms`, `ChromeSystem` (opt-in; see Chrome global) |
43
55
  | `winui-svelte/input` | `src/input/index.ts` | `enableInputEvents()`, `setPointerCapture` / `releasePointerCapture` / `hasPointerCapture`, `activeElement()`, `moveFocus()`, `trapFocus()`, `PointerType`, `PointerEvent` / `WheelEvent` / `KeyboardEvent` / `FocusEvent` (opt-in; see Input events and focus) |
44
56
  | `winui-svelte/media` | `src/media/index.ts` | `bitmapImageOf()`, `svgImageSourceOf()`, `decodeDataUri()`, `createMediaPlayer()`, `mediaSourceOfBytes()`, `observePlayback()`, `PlaybackState` (opt-in; see Media) |
45
57
  | `winui-svelte/win2d` | `src/win2d/index.ts` | `Canvas`, the Win2D controls, the drawing helpers and Win2D classes, `applyEffect` (opt-in; see Win2D) |
46
58
  | `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) |
47
59
  | `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) |
48
60
  | `winui-svelte/tray` | `src/tray/index.ts` | `TrayIcon` (with its `menu`), `createTrayIcon()`, `placeMenuWindow()`, `hideToTray()`, `restoreFromTray()`, `toggleInTray()`, `removeAllTrayIcons()`, `TrayGesture` (opt-in; see System tray) |
49
- | `winui-svelte/tray/standalone` | `src/tray/standalone/index.ts` | `createStandaloneTray()`, `NativeMenuEntryKind`, 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) |
61
+ | `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) |
50
62
  | `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) |
51
63
  | `winui-svelte/forms` | `src/forms/index.ts` | `Form`, `FormField`, `textField`, `numberField`, `selectField` and the other field attachments, `formButton`, `FormValues`, `validityOf` (opt-in; see Forms) |
52
64
  | `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) |
@@ -745,6 +757,7 @@ type WindowOptions<Props> = {
745
757
 
746
758
  interface AppWindow<Props> {
747
759
  readonly window: Window;
760
+ readonly handle: WindowHandle; // what chromeWindowSurface and the rest of the window API take
748
761
  readonly mounted: Mounted<Props> | null; // null for a control
749
762
  close(): void;
750
763
  onClosed(listener: () => void): void;
@@ -1354,7 +1367,7 @@ const vertical: Orientation = 1;
1354
1367
  | A path geometry (`GeometryInput`, on `PathIcon` and `Path`) | Path Markup Syntax text or a `Geometry` | `data="M0,0 L10,10"` |
1355
1368
  | A font family (`FontFamilyInput`) | a family name or a `FontFamily` | `"Segoe UI Variable"` |
1356
1369
  | A grid length (`GridLengthInput`) | pixels, or `GridLengthText` as XAML writes it | `"Auto"`, `"2*"`, `"120"` |
1357
- | The package's own | `Backdrop`, `WindowTheme`, `TitleBarHeight`, `WindowPresentation`, `PickerLocation`, `NavigationCacheMode`, `NavigationMode`, `MoveDirection`, `XamlKind`, `FocusKind`, `TrayGesture`, `TrayBalloonIcon`, `ConnectedAnimationKind` | `backdrop={Backdrop.mica}` |
1370
+ | The package's own | `Backdrop`, `WindowTheme`, `TitleBarHeight`, `WindowPresentation`, `PickerLocation`, `NavigationCacheMode`, `NavigationMode`, `MoveDirection`, `XamlKind`, `FocusKind`, `TrayGesture`, `TrayBalloonIcon`, `ConnectedAnimationKind`, `DialogResult`, `DialogButton` | `backdrop={Backdrop.mica}` |
1358
1371
 
1359
1372
  A WinUI enum's members keep WinUI's names and case (`"Minimal"`, not
1360
1373
  `"minimal"`), as the metadata and the docs have them; the package's own sets
@@ -2618,10 +2631,13 @@ if (!single.isPrimary) {
2618
2631
  - `ActivationEvent` is a union on `kind` (`ActivationKind`, also from
2619
2632
  `winui-svelte/enums`): `launch` (started by hand), `file` (`files`, absolute
2620
2633
  paths of existing files), `protocol` (`uri`, `scheme`), `startup` (started
2621
- at sign-in) and `redirect` (a later copy with nothing to open)
2634
+ at sign-in), `redirect` (a later copy with nothing to open) and `jumpList`
2635
+ (`taskId`, a task of the jump list was chosen; see Jump list tasks) and
2636
+ `alarm` (`alarm`, an alarm of `winui-svelte/app/schedule` went off; it also
2637
+ reaches `onAlarm`)
2622
2638
  Every event has `isRedirect`, `arguments` and `workingDirectory`; a link
2623
2639
  sent by a later copy is `protocol` with `isRedirect: true`
2624
- - A link wins over files, files win over the startup marker; an argument
2640
+ - An alarm wins over a jump list task, a jump list task wins over a link, a link wins over files, files win over the startup marker; an argument
2625
2641
  that fits none stays in `arguments`
2626
2642
  Arguments are checked with a schema (up to 1024 of them, up to 32767
2627
2643
  characters each, no NUL); a failure goes to `onError`, the rest go on
@@ -2661,6 +2677,190 @@ if (!single.isPrimary) {
2661
2677
  `test/activation.test.ts` starts real second copies with a link, a file and
2662
2678
  nothing, and checks the first hears each as one event
2663
2679
 
2680
+ ### Jump list tasks (`winui-svelte/app/jump-list`)
2681
+
2682
+ Entries in the Tasks section of the taskbar button's right-click menu
2683
+ (`ICustomDestinationList`, `IObjectCollection` and `IShellLink`)
2684
+ No package identity is needed; an opt-in subpath
2685
+ Thumbnail toolbar buttons cannot be built from Node (their click is a sent
2686
+ message that no hook receives), so a task is the way to put a command there
2687
+
2688
+ ```ts
2689
+ import { startActivation } from "winui-svelte/app/activation";
2690
+ import { setJumpListTasks } from "winui-svelte/app/jump-list";
2691
+
2692
+ const list = setJumpListTasks({
2693
+ tasks: [
2694
+ { id: "new-note", title: "New note", arguments: ["--new"] },
2695
+ { id: "inbox", title: "Open inbox", arguments: ["--inbox"], icon: "inbox.ico" },
2696
+ ],
2697
+ });
2698
+
2699
+ startActivation({
2700
+ key: "com.example.notes",
2701
+ window: mainWindow,
2702
+ onActivation(event) {
2703
+ const task = list.taskOf(event);
2704
+ if (task?.id === "new-note") newNote();
2705
+ },
2706
+ });
2707
+ ```
2708
+
2709
+ - `setJumpListTasks({ tasks, appUserModelId, command })` replaces the Tasks
2710
+ of the list and returns `{ tasks, taskOf(event) }`; `tasks` is a `const`
2711
+ generic, so `task.id` is the union of your ids
2712
+ - `clearJumpList({ appUserModelId })` deletes the whole list
2713
+ - A `JumpListTask` is `{ id, title, arguments, description, icon, iconIndex,
2714
+ workingDirectory }`; `id` is letters, digits, `_`, `.` and `-`, 64 at most,
2715
+ and unique; `icon` is a file path (`PictureSource`, but a `data:`, `http(s)`
2716
+ or `ms-appx` URI is a `TypeError`): an .ico, or an .exe or .dll with
2717
+ `iconIndex`
2718
+ - A click starts `command` (this process's Node and entry script by default,
2719
+ as `registerFileTypes` does; a bundled executable passes its own) with the
2720
+ marker `--winui-svelte-jump-list=<id>` and then the task's `arguments`,
2721
+ quoted for `CommandLineToArgvW`
2722
+ `startActivation` hands that to the running copy through the single
2723
+ instance redirect as a `jumpList` event: `taskId` is the id and `arguments`
2724
+ are the task's own; a first start gets the same event with `isRedirect:
2725
+ false`
2726
+ - The list belongs to the process's AppUserModelID and Windows shows nothing,
2727
+ without an error, when a window has another; so the call throws when the
2728
+ process has none (give `<Window>` an `appUserModelId`, or call
2729
+ `joinAppUserModel`) or when `appUserModelId` differs from it
2730
+ - Keep the tasks static, as Microsoft advises: set them once at start
2731
+ - Call it on a thread with COM (the UI thread of a window has it)
2732
+ - `src/app/jump-list/native.test.ts` commits a list under a unique
2733
+ AppUserModelID in the test process, checks that Windows wrote its
2734
+ custom destinations file, and deletes the list, even when it fails
2735
+
2736
+ ### Shell verbs (`winui-svelte/app/shell`)
2737
+
2738
+ What Explorer's context menu does, from code
2739
+ There is no web API for these; the names follow the launcher helpers of
2740
+ `winui-svelte/data-transfer`, which stay the home of `launchUri`,
2741
+ `launchFile`, `openFolder` and `revealInExplorer`
2742
+ An opt-in subpath: an app that does not import it does not bundle it
2743
+
2744
+ ```ts
2745
+ import { createShortcut, openWith, readShortcut, registerAppPath, trash } from "winui-svelte/app/shell";
2746
+
2747
+ const result = trash({ paths: ["C:\\Users\\me\\old.txt"] });
2748
+ if (!result.ok) console.warn(result.reason, result.message);
2749
+
2750
+ createShortcut({
2751
+ path: "C:\\Users\\me\\Desktop\\Notes.lnk",
2752
+ target: "C:\\Apps\\notes.exe",
2753
+ arguments: ["--open", "my notes.txt"],
2754
+ workingDirectory: "C:\\Apps",
2755
+ icon: { path: "C:\\Apps\\notes.exe", index: 0 },
2756
+ description: "Open my notes",
2757
+ });
2758
+ const link = readShortcut({ path: "C:\\Users\\me\\Desktop\\Notes.lnk" });
2759
+ await openWith({ path: "C:\\Users\\me\\photo.png" });
2760
+ registerAppPath({ name: "notes", program: "C:\\Apps\\notes.exe" });
2761
+ ```
2762
+
2763
+ - Every verb returns `{ ok: true }` or `{ ok: false, reason, message }`;
2764
+ `reason` is a `ShellFailure` (`invalid`, `not-found`, `exists`,
2765
+ `owned-by-another`, `aborted`, `failed`)
2766
+ - These act on the user's own files; they check and then act, and none
2767
+ asks the user first
2768
+ - Paths are data: each must be a full path with no control character and not a
2769
+ device path; none is built into a command line
2770
+ - `trash` sends to the Recycle Bin (`SHFileOperationW` with
2771
+ `FOF_ALLOWUNDO`) and never deletes for good; when Windows would have to
2772
+ (a drive without a bin, a file too big for it) it asks, and nothing goes
2773
+ unless the user agrees; all the paths are checked before any is touched
2774
+ - `openWith` shows the Windows "Open with" list for a file
2775
+ (`LauncherOptions.DisplayApplicationPicker`), so it takes a file and never a
2776
+ program; it opens a dialog and is only unit-tested with a fake
2777
+ - `createShortcut` writes only the `.lnk` file (`IShellLink` and
2778
+ `IPersistFile`); each argument is quoted by the same rule as the
2779
+ activation registrations, and an existing file is kept unless
2780
+ `shouldOverwrite` is set; the target is not required to exist
2781
+ - `readShortcut` gives the target as stored, without searching for a moved
2782
+ one and without running anything
2783
+ - `registerAppPath` writes a key under `HKEY_CURRENT_USER` (App Paths) with a
2784
+ marker value, only when the key is free or the package made it;
2785
+ `unregisterAppPath` removes only a key with the marker; the name is an
2786
+ identifier that is not a name Windows or a common tool answers to, and the
2787
+ program is a full path ending in `.exe`; the machine-wide hive is out of reach
2788
+ - A shortcut that carries an AUMID (for toast identity) is not offered yet
2789
+ - `src/app/shell/native.test.ts` recycles a file, writes and reads a
2790
+ shortcut in a folder it creates under the temp directory and removes, and
2791
+ registers and removes an App Paths alias with a unique name
2792
+
2793
+ ### Alarms (`winui-svelte/app/schedule`)
2794
+
2795
+ Starts the app at a time, once or on a repeat, through Task Scheduler, and
2796
+ tells it which alarm went off
2797
+ The shape is `chrome.alarms` (`create`, `get`, `getAll`, `clear`, `clearAll`,
2798
+ `onAlarm`, the `Alarm` type) with promises instead of callbacks, and
2799
+ `chrome.runtime.onStartup` for the start at sign-in
2800
+ An opt-in subpath: an app that does not import it does not bundle it
2801
+
2802
+ ```ts
2803
+ import { ActivationKind, startActivation } from "winui-svelte/app/activation";
2804
+ import * as alarms from "winui-svelte/app/schedule";
2805
+
2806
+ alarms.onAlarm.addListener(alarm => sync(alarm.name));
2807
+ alarms.onStartup.addListener(() => restoreSession());
2808
+ startActivation({ key: "my-app", onActivation: () => {} });
2809
+
2810
+ await alarms.create("nightly-sync", { when: Date.now() + 3_600_000, periodInMinutes: 1440 });
2811
+ await alarms.get("nightly-sync"); // { name, scheduledTime, periodInMinutes: 1440 }
2812
+ await alarms.getAll(); // every alarm this package made
2813
+ await alarms.clear("nightly-sync"); // true
2814
+ await alarms.clearAll(); // false
2815
+ ```
2816
+
2817
+ - `create(name, { when, delayInMinutes, periodInMinutes })` is Chrome's:
2818
+ `when` is milliseconds since 1970, `delayInMinutes` counts from now, and
2819
+ with only `periodInMinutes` the first run is one period away; `when` and
2820
+ `delayInMinutes` together, or none of the three, throw; creating a name again
2821
+ replaces its alarm
2822
+ - `name` is letters, digits, `.`, `_` and `-` (a task name, not free text)
2823
+ - Chrome's one-minute minimum for `delayInMinutes` is not applied: a delay
2824
+ can be seconds, and a time in the past runs at once
2825
+ - `periodInMinutes` is 1 to 44640 (Task Scheduler cannot repeat faster than
2826
+ a minute, nor slower than 31 days)
2827
+ - Extras, optional members of the same object: `arguments` (reach the
2828
+ started copy after the entry script), `runWhenOnBattery` (true by
2829
+ default), `command` (a bundled executable instead of Node) and `backend`
2830
+ (a test)
2831
+ - `get`, `getAll`, `clear` and `clearAll` read and remove only the tasks in the
2832
+ `winui-svelte` folder of Task Scheduler, so a task of another program can
2833
+ neither be listed nor removed from here; `scheduledTime` is the next run
2834
+ - `onAlarm` and `onStartup` have `addListener`, `removeListener` and
2835
+ `hasListener`; they are called by `startActivation`, so call it for the
2836
+ alarms to arrive
2837
+ - A task runs the app again with a marker argument, which becomes an `alarm`
2838
+ activation (`event.alarm`) and also reaches `onAlarm`; if the app is open,
2839
+ the new copy hands the activation to it and exits, so the listener of the
2840
+ running app hears it, and if it is closed, the started copy hears it
2841
+ - `onStartup` is called for a `startup` activation, that is when Windows
2842
+ starts the app at sign-in; turning that start on or off is `launchAtLogin`
2843
+ of `winui-svelte/app/activation` (the Run key listed in Settings, Apps,
2844
+ Startup), which this module does not repeat
2845
+ - How it works: the package writes a Task Scheduler 1.2 XML definition to a
2846
+ private temporary file and runs `schtasks.exe /Create /XML` (found by
2847
+ `SystemRoot`), so no COM is involved; the task runs as the signed-in user
2848
+ with normal rights (no administrator), with no time limit, and a start
2849
+ missed while the PC was off is made up when it is next on; the alarm's first
2850
+ time and period are kept in the task's description, which is how `get`
2851
+ reads them back
2852
+ - A one-shot alarm's task deletes itself a day after its time
2853
+ - Limits:
2854
+ - The task runs only while the user is signed in
2855
+ - `schtasks` is the only gate: Group Policy can forbid task creation, and
2856
+ then `create` rejects with its message
2857
+ - Moving or reinstalling the app leaves a task that points at the old path
2858
+ until the alarm is created again
2859
+ - `src/app/schedule/schedule.test.ts` checks the generated XML, the quoting
2860
+ and escaping of arguments, the marker argument and the activation it
2861
+ becomes, and an alarm's round trip to a task and back over a fake backend; no
2862
+ real task is made
2863
+
2664
2864
  ### Global hotkeys (`winui-svelte/app/hotkeys`)
2665
2865
 
2666
2866
  A system-wide key combination, heard whichever app has the focus
@@ -2847,6 +3047,239 @@ window's content
2847
3047
  A Tauri or Electron host that already has a tray should keep it: two icons
2848
3048
  would show, and this one lives and dies with the WinUI window's process
2849
3049
 
3050
+ ### One tray menu for every renderer (`winui-svelte/tray/menu`)
3051
+
3052
+ A pure model of a tray menu: no WinUI, no Win32, so it runs under
3053
+ `node --test` and in a tray-only bundle
3054
+ You declare items once; the user picks how much of the menu to see, from the
3055
+ simple menu of a dictation app to the long one of a screenshot tool, and then
3056
+ hides, shows and reorders single items; a renderer draws what `resolveMenu`
3057
+ returns
3058
+ An opt-in subpath: an app that does not import it does not bundle it
3059
+
3060
+ ```ts
3061
+ import { defineMenu, MenuItemKind, MenuLevel, resolveMenu } from "winui-svelte/tray/menu";
3062
+
3063
+ // The simple style: three commands and a separator, no levels set
3064
+ const simple = defineMenu([
3065
+ { kind: MenuItemKind.COMMAND, id: "toggle", label: "Start dictation" },
3066
+ { kind: MenuItemKind.COMMAND, id: "settings", label: "Settings" },
3067
+ { kind: MenuItemKind.SEPARATOR, id: "line" },
3068
+ { kind: MenuItemKind.COMMAND, id: "quit", label: "Quit", isRequired: true }
3069
+ ]);
3070
+
3071
+ // The complex style: the same model with levels
3072
+ const complex = defineMenu([
3073
+ { kind: MenuItemKind.HEADER, id: "capture-header", label: "Capture" },
3074
+ {
3075
+ kind: MenuItemKind.SUBMENU,
3076
+ id: "capture",
3077
+ label: "Capture",
3078
+ items: [
3079
+ { kind: MenuItemKind.COMMAND, id: "region", label: "Region", shortcut: "Ctrl+Shift+4" },
3080
+ { kind: MenuItemKind.COMMAND, id: "scroll", label: "Scrolling", level: MenuLevel.FULL }
3081
+ ]
3082
+ },
3083
+ {
3084
+ kind: MenuItemKind.SUBMENU,
3085
+ id: "recent",
3086
+ label: "Recent uploads",
3087
+ level: MenuLevel.STANDARD,
3088
+ emptyLabel: "Nothing uploaded yet",
3089
+ maxItems: 10,
3090
+ items: () => recentUploads().map(({ name }) => ({ kind: MenuItemKind.COMMAND, id: `recent-${name}`, label: name }))
3091
+ },
3092
+ {
3093
+ kind: MenuItemKind.CHECK,
3094
+ id: "autostart",
3095
+ label: "Start with Windows",
3096
+ level: MenuLevel.STANDARD,
3097
+ isChecked: () => isAutostart(),
3098
+ staysOpen: true
3099
+ },
3100
+ { kind: MenuItemKind.COMMAND, id: "quit", label: "Quit", isRequired: true }
3101
+ ]);
3102
+
3103
+ // Call it each time the menu opens: functions are read now
3104
+ const lines = resolveMenu({
3105
+ items: complex,
3106
+ profile: { level: MenuLevel.STANDARD, hidden: ["region"], shown: [], order: {} }
3107
+ });
3108
+ ```
3109
+
3110
+ - `MenuItem` is a union on `kind`: `command`, `check`, `radio`, `submenu`,
3111
+ `separator` and `header` (`MenuItemKind`); a field belongs to the kinds that
3112
+ have it, so a command with `isChecked` or a radio with no `group` fails to
3113
+ compile
3114
+ - Every item has a unique, stable `id`; the profile of the user is keyed by it
3115
+ `defineMenu` keeps the ids as literal types, and `MenuProfile` typed with
3116
+ `MenuIds` of the menu (and the `profile` of `resolveMenu`) rejects an id
3117
+ that is not in the menu
3118
+ - `level` is the lowest detail level that shows the item (`MenuLevel`:
3119
+ `simple`, `standard`, `full`; `simple` when left out); `isRequired` cannot
3120
+ be hidden by the user
3121
+ - `label`, `isEnabled`, `isVisible`, `isChecked`, `isBold` and `badge` may be
3122
+ a value or a function, read each time `resolveMenu` runs
3123
+ - `items` of a submenu may be a function that makes the children each time;
3124
+ `sort` and `maxItems` order and cap such a list, and `emptyLabel` shows a
3125
+ disabled line when it is empty instead of dropping the submenu
3126
+ - `staysOpen` keeps the menu open after the pick (the renderer then refreshes
3127
+ labels and ticks only); `closeThenRun` (true unless set to false) runs
3128
+ `onselect` after the menu has closed, so that a dialog can open
3129
+ - A submenu may have its own `onselect` and `autoExpand`
3130
+ - `icon` is a path, a glyph or `IconPixels`; `shortcut` is display text only,
3131
+ the menu does not bind the key
3132
+ - `MenuProfile` is plain JSON: `level`, `hidden` (ids the level shows that
3133
+ the user hid), `shown` (ids above the level that the user turned on) and
3134
+ `order` (child ids in the user order, keyed by parent id, `""` for the root)
3135
+ - `resolveMenu({ items, profile })` returns `ResolvedMenuItem[]`: final text,
3136
+ booleans and a `select()` per line, with separators collapsed, headers with
3137
+ nothing under them dropped and empty submenus dropped; it throws
3138
+ `MenuModelError` for a repeated id or a radio with no group
3139
+ - `describeMenu({ items })` lists every item with its id, kind, label, level,
3140
+ parent id and `isRequired`, for an editor
3141
+ - `defaultProfile({ level })`, `parseProfile({ value })` and `profileSchema`
3142
+ (a field that is wrong falls back to its default, nothing throws),
3143
+ `loadProfile({ file })` and `saveProfile({ file, profile })` (the file is
3144
+ replaced atomically)
3145
+ - Not in the model: the actions of the icon itself (left, double and middle
3146
+ click) stay on the tray icon options
3147
+
3148
+ ### The tray menu in a window (`winui-svelte/tray/menu/svelte`)
3149
+
3150
+ The model of `winui-svelte/tray/menu` drawn by `<TrayIcon>` as a WinUI
3151
+ `MenuFlyout`, from an array or from markup
3152
+ An opt-in subpath; a consumer that imports only `winui-svelte/tray/menu`
3153
+ bundles no Svelte and no component
3154
+
3155
+ ```svelte
3156
+ <script lang="ts">
3157
+ import { MenuLevel } from "winui-svelte/enums";
3158
+ import { TrayIcon } from "winui-svelte/tray";
3159
+ import { TrayMenu, TrayMenuItem, TrayMenuSeparator, TrayMenuSubmenu } from "winui-svelte/tray/menu/svelte";
3160
+
3161
+ let isAutostart = $state(false);
3162
+ let recent = $state(["a.png", "b.png"]);
3163
+ </script>
3164
+
3165
+ <TrayIcon icon="app.ico" tooltip="My app">
3166
+ <TrayMenu profile={savedProfile}>
3167
+ <TrayMenuItem id="open" label="Open" onselect={showWindow} />
3168
+ <TrayMenuItem id="autostart" kind="check" label="Start with Windows"
3169
+ isChecked={isAutostart} level={MenuLevel.STANDARD} staysOpen
3170
+ onselect={() => (isAutostart = !isAutostart)} />
3171
+ <TrayMenuSubmenu id="recent" label="Recent" emptyLabel="Nothing yet">
3172
+ {#each recent as name (name)}
3173
+ <TrayMenuItem id={`recent.${name}`} label={name} />
3174
+ {/each}
3175
+ </TrayMenuSubmenu>
3176
+ <TrayMenuSeparator id="line" />
3177
+ <TrayMenuItem id="quit" label="Quit" isRequired onselect={quit} />
3178
+ </TrayMenu>
3179
+ </TrayIcon>
3180
+ ```
3181
+
3182
+ - `<TrayIcon menu={items} profile={profile}>` takes the array of
3183
+ `defineMenu` instead of markup, or the `menu` snippet of a hand-written
3184
+ flyout as before; the three never mix
3185
+ The ids of the array stay literal, so `profile` rejects an id the menu does
3186
+ not have
3187
+ - `<TrayMenu>` and its children are inert elements: they draw nothing, the
3188
+ tray walks the tree each time the menu opens, so order, nesting, `{#if}`,
3189
+ keyed `{#each}` and reactive props all work, with no second renderer
3190
+ - The props are the fields of the model's own items (`TrayMenuItem` takes a
3191
+ `kind` of `command`, `check` or `radio`; a tick on a command or a radio with
3192
+ no `group` fails `svelte-check`), and an unknown attribute fails too
3193
+ - Markup cannot carry a literal union, so ids written in markup are plain
3194
+ `string`; the exported `collectMenu` reads a `TrayMenu` element into the same
3195
+ `MenuItem[]`
3196
+ - A `TrayMenu` has a `profile` of its own, used for its lines
3197
+ `profile` on `TrayIcon` applies to `menu={items}`
3198
+ - The flyout is built from `resolveMenu` each time the menu opens: a command is
3199
+ a `MenuFlyoutItem`, a check a `ToggleMenuFlyoutItem`, a radio a
3200
+ `RadioMenuFlyoutItem` (its `group` is the `GroupName`), a submenu a
3201
+ `MenuFlyoutSubItem`, a header a disabled bold item
3202
+ `isBold` is the font weight; `icon` is drawn as a glyph (`FontIcon`) or, for
3203
+ a path to an `.ico` or `.png`, an `ImageIcon`; `IconPixels` is not drawn
3204
+ A flyout has one trailing column, the keyboard accelerator's, so it shows
3205
+ the `badge` and then the `shortcut` as text
3206
+ - `onselect` runs after the flyout has closed, on the next turn
3207
+ (`closeThenRun`, true unless set to false)
3208
+ - `staysOpen`: WinUI closes a flyout when an item is invoked, and offers no
3209
+ property to keep it open, so the item runs after the close and the flyout is
3210
+ built again from the model, at the same point, with the new labels and ticks
3211
+ The menu blinks once; every other pick closes the menu
3212
+ - `TrayMenuFlyout` (from `winui-svelte/tray`) is that flyout on its own: put
3213
+ it in a `menu` snippet with `resolve={() => resolveMenu({ items })}` and
3214
+ `onclose={close}`; `onflyout` hands over the native `MenuFlyout` to read
3215
+ - Not drawn by WinUI: a submenu row's own `onselect` (a `MenuFlyoutSubItem` has
3216
+ no click) and `autoExpand` (it has no member to open it from code)
3217
+
3218
+ ### Letting the user customize the tray menu (`winui-svelte/tray/menu/svelte`)
3219
+
3220
+ `<TrayMenuEditor>` is the settings control for a tray menu: the user picks how
3221
+ much of it shows, from three lines to a ShareX-like menu "and everything in
3222
+ between"
3223
+ It edits a `MenuProfile` and says so; it never reads or writes a file
3224
+
3225
+ The three levels are the `level` of each item (`simple` when left out):
3226
+
3227
+ | Level | The user gets | Shown items |
3228
+ |---|---|---|
3229
+ | Simple | The few lines every user needs | Items of level `simple` |
3230
+ | Standard | The usual set | `simple` and `standard` |
3231
+ | Full | Everything the app can do | All |
3232
+
3233
+ ```svelte
3234
+ <script lang="ts">
3235
+ import { TrayIcon } from "winui-svelte/tray";
3236
+ import { loadProfile, saveProfile } from "winui-svelte/tray/menu";
3237
+ import { TrayMenuEditor } from "winui-svelte/tray/menu/svelte";
3238
+ import { items } from "./menu.ts";
3239
+
3240
+ const FILE = "tray-menu.json";
3241
+ let profile = $state(loadProfile({ file: FILE }));
3242
+ </script>
3243
+
3244
+ <TrayMenuEditor {items} isPreviewShown bind:profile
3245
+ onchange={next => saveProfile({ file: FILE, profile: next })} />
3246
+
3247
+ <TrayIcon icon="app.ico" menu={items} {profile} />
3248
+ ```
3249
+
3250
+ | Prop | Meaning |
3251
+ |---|---|
3252
+ | `items` | The menu `defineMenu` declares; the ids stay literal |
3253
+ | `profile` | The user's choice, bindable; the default profile when left out |
3254
+ | `onchange(profile)` | Runs with the new profile after every edit; save it here |
3255
+ | `onsave(profile)` | Adds a Save button that runs this, for an app that saves on request |
3256
+ | `labels` | The strings of the editor, each optional and English by default (`DEFAULT_EDITOR_LABELS`); `{name}` stands for an item's label |
3257
+ | `isPreviewShown` | Lists the menu as it resolves under the profile, as plain rows |
3258
+
3259
+ - The detail level is three radio buttons: Simple, Standard, Full
3260
+ Changing it keeps the user's tweaks: an item the user hid stays hidden at
3261
+ every level, and one the user turned on above the level stays on
3262
+ The word "Custom" appears beside the level while the profile has any tweak
3263
+ (a hidden or shown item, or a menu in another order); the level alone is not
3264
+ a tweak
3265
+ - Below it is a tree of every item (`describeMenu`), submenus with their
3266
+ children indented
3267
+ Each row has a check for "shown" (what the level, `hidden` and `shown` make
3268
+ of it), the lowest level that includes the item as text, and Up and Down
3269
+ buttons that move it within its own menu (the whole tree is reachable with
3270
+ Tab, Space and Enter, and no operation needs a drag)
3271
+ - An item with `isRequired` is locked on and says "Always shown"
3272
+ - "Reset to default" returns to `defaultProfile()` and is disabled while the
3273
+ profile already is that
3274
+ - Every control has an `automationName`, the title and sections are headings,
3275
+ and no state is told by color alone
3276
+ - The functions behind it are pure and tested without a window:
3277
+ `src/tray/menu-svelte/edit-profile.ts` (`setLevel`, `setItemShown`,
3278
+ `moveItem`, `editorRows`, `hasTweaks`)
3279
+ - `examples/tray-menu-editor` puts the editor beside the tray icon it edits, on
3280
+ a ShareX-like menu with Capture, Upload and Tools submenus, a dynamic recent
3281
+ list, a check item and a required Exit; its simple level is a three-line menu
3282
+
2850
3283
  ### Tray with no window (`winui-svelte/tray/standalone`)
2851
3284
 
2852
3285
  A tray that runs in a process of its own, plain Node, with no `Window`, no
@@ -2861,7 +3294,7 @@ for the menu and its timers run on the dispatcher queue
2861
3294
  import {
2862
3295
  activateOrLaunch,
2863
3296
  createStandaloneTray,
2864
- NativeMenuEntryKind
3297
+ MenuItemKind
2865
3298
  } from "winui-svelte/tray/standalone";
2866
3299
 
2867
3300
  function openPanel() {
@@ -2877,23 +3310,68 @@ createStandaloneTray({
2877
3310
  tooltip: "Panel",
2878
3311
  onclick: openPanel,
2879
3312
  menu: [
2880
- { kind: NativeMenuEntryKind.COMMAND, label: "Open", onselect: openPanel },
2881
- { kind: NativeMenuEntryKind.SEPARATOR },
2882
- { kind: NativeMenuEntryKind.COMMAND, label: "Quit", onselect: () => process.exit(0) }
3313
+ { kind: MenuItemKind.COMMAND, id: "open", label: "Open", onselect: openPanel },
3314
+ { kind: MenuItemKind.SEPARATOR, id: "line" },
3315
+ { kind: MenuItemKind.COMMAND, id: "quit", label: "Quit", onselect: () => process.exit(0) }
2883
3316
  ]
2884
3317
  });
2885
3318
  ```
2886
3319
 
2887
3320
  - `createStandaloneTray(options)` takes the icon's options (`icon`,
2888
3321
  `tooltip`, `isVisible`, `guid`, `onclick`, `ondoubleclick`,
2889
- `onmiddleclick`) and `menu`, and returns the same handle as
2890
- `createTrayIcon` (`update`, `notify`, `bounds`, `isRegistered`, `remove`)
3322
+ `onmiddleclick`), `menu`, `extras`, and `resolve` with `profile`, and returns
3323
+ a handle with `update`, `isRegistered` and `remove`, plus `notify` and
3324
+ `bounds` when their extras are passed
2891
3325
  The icon keeps the process alive; `remove()` or the process ending takes it
2892
3326
  out of the tray
3327
+ - The default is the smallest tray: an icon from one `.ico` path, clicks,
3328
+ `update`, `remove` and the menu
3329
+ Three parts are opt-in, each one import from the same entry, passed in
3330
+ `extras`, and none of their code is in the bundle unless passed:
3331
+ `balloons` adds `notify`, `bounds` adds `bounds()`, and `themedIcon` lets
3332
+ `icon` be `{ forLightTaskbar, forDarkTaskbar }`, swapped as the taskbar theme
3333
+ changes
3334
+ The handle has `notify` or `bounds` only when its extra is passed, and a
3335
+ theme pair is accepted only with `themedIcon`; otherwise it fails to compile
3336
+ `createTrayIcon` and `TrayIcon` of `winui-svelte/tray` include all three
3337
+
3338
+ ```ts
3339
+ import { balloons, bounds, createStandaloneTray, themedIcon } from "winui-svelte/tray/standalone";
3340
+
3341
+ const tray = createStandaloneTray({
3342
+ icon: { forLightTaskbar: "dark.ico", forDarkTaskbar: "light.ico" },
3343
+ extras: [balloons, bounds, themedIcon]
3344
+ });
3345
+ tray.notify({ title: "Ready" });
3346
+ ```
3347
+
2893
3348
  - The menu is Windows' own popup menu (`TrackPopupMenuEx`), made on a right
2894
3349
  click and destroyed when it closes; nothing of it exists while idle
2895
- A command is `{ kind, label, onselect, isEnabled }`, a line is
2896
- `{ kind: NativeMenuEntryKind.SEPARATOR }`
3350
+ `menu` is the same model as the windowed tray's (`winui-svelte/tray/menu`):
3351
+ commands, checks, radios, submenus to any depth, separators and headers,
3352
+ each with an `id` (a separator too), and values that are functions are read
3353
+ each time the menu opens, as are lazy submenu `items`
3354
+ The menu is drawn by the lite resolver by default: every item is shown in
3355
+ declared order, with dynamic values, `isVisible`, `emptyLabel`, `sort` and
3356
+ `maxItems` applied, and `level` and `isRequired` ignored; it leaves the
3357
+ level and profile code out of the bundle
3358
+ For levels, a user profile and ordering, opt in with one import:
3359
+ `resolve: resolveMenu` from the same entry, and then `profile`, the user's
3360
+ choice of level, hidden, shown and order (a `MenuProfile` with a
3361
+ `MenuLevel`, or a function that gives one, for example from
3362
+ `loadProfile`)
3363
+ The ids are literal types: `profile` accepts only ids of `menu`, and a
3364
+ wrong one fails to compile; a `profile` without `resolve: resolveMenu` also
3365
+ fails to compile, so a profile is never ignored in silence
3366
+ Windows draws a check as a tick, a radio as a dot, a header as a disabled
3367
+ bold line, a shortcut right-aligned and a badge after the label
3368
+ `staysOpen` closes and reopens the menu at the same point, with fresh
3369
+ labels and ticks, right after the line runs; `onselect` otherwise runs on
3370
+ the next turn after the menu is gone (`closeThenRun: false` runs it as the
3371
+ menu closes)
3372
+ A submenu's own `onselect` and `autoExpand`, and every `icon`, do nothing
3373
+ here: Windows opens a submenu row without reporting a pick, and no pixel
3374
+ or file icon is drawn
2897
3375
  The menu is modal: the thread runs its own message loop until it closes
2898
3376
  It does not follow a dark system theme, which a native popup menu does not
2899
3377
  without an undocumented call; a menu that must match the theme belongs in
@@ -2907,6 +3385,156 @@ createStandaloneTray({
2907
3385
  component, window or renderer module, or a component's name, is in the
2908
3386
  output, or if it grows past its budget
2909
3387
 
3388
+ ### Tray as an entrypoint (`entrypoints/tray.ts`)
3389
+
3390
+ The app does not have to know it has a tray; the tray is its own file, found
3391
+ by its name and built into a small bundle for a process of its own
3392
+
3393
+ ```text
3394
+ my-app/
3395
+ entrypoints/
3396
+ main.ts -> dist/main.js
3397
+ window.ts -> dist/window.js
3398
+ tray.ts -> dist/tray.js, dist/tray.json, dist/tray.ico
3399
+ ```
3400
+
3401
+ `main.ts` and `window.ts` never import `tray.ts`; `buildApp` (and the dev
3402
+ server of `winuiSvelte()`) discover the folder, so `entries` is optional, and a
3403
+ name given in `entries` wins over the file found
3404
+
3405
+ ```ts
3406
+ import { activateOrLaunch, defineTray, MenuItemKind, MenuLevel, resolveMenu } from "winui-svelte/tray/standalone";
3407
+
3408
+ export default defineTray({
3409
+ icon: "tray.ico",
3410
+ tooltip: "My app",
3411
+ guid: "7d1c5a52-3f1b-4a63-9f5e-2f4d6b0c8a11",
3412
+ onactivate: openApp,
3413
+ resolve: resolveMenu,
3414
+ menu: [
3415
+ { kind: MenuItemKind.COMMAND, id: "open", label: "Open", isRequired: true, onselect: openApp },
3416
+ { kind: MenuItemKind.COMMAND, id: "capture", label: "Capture", level: MenuLevel.STANDARD }
3417
+ ]
3418
+ });
3419
+ ```
3420
+
3421
+ - `defineTray` returns its argument; it takes the options of
3422
+ `createStandaloneTray` (`menu`, `resolve`, `profile`, `extras`, the click
3423
+ handlers) with the ids of `menu` as a literal union, so a `profile` that names
3424
+ an id the menu lacks is a type error, and `profile` needs `resolve`
3425
+ - `guid` is required: it keeps the icon's place in the tray and names the one
3426
+ tray process, so a second `tray.js` exits at once
3427
+ - `onactivate` runs on a left click when `onclick` is not given
3428
+ - The build reads `icon`, `tooltip` and `guid` from the syntax tree, never by
3429
+ running the file, so a top-level import of WinRT in `tray.ts` does not
3430
+ execute at build; `icon` and `guid` must be string literals, and the icon a
3431
+ file inside the folder of `tray.ts` (written there as `icon: "tray.ico"`,
3432
+ copied to the same relative path in the output)
3433
+ - `tray.js` is the wrapper the build writes (a virtual module, like WXT's
3434
+ background): it imports the default export, calls `claimTrayInstance({ guid })`
3435
+ (the right to be the one tray for the `guid`; false in a second copy) and then
3436
+ `createStandaloneTray`; `tray.json` holds what was read
3437
+ - `startTray()` from `winui-svelte/app` starts `tray.js` detached once; it is
3438
+ optional, for an installer, a launcher or the app's own start; it reads
3439
+ `tray.json` for the `guid`, so the key is derived in one place
3440
+ (`trayInstanceKey(guid)`); `activateOrLaunch` is how the tray reaches the app
3441
+ - Under the dev server the tray is built into `.winui/tray` and started; a
3442
+ change to it rebuilds and restarts the process (no HMR, as WXT's background)
3443
+ after stopping the Node process whose pid `.winui/tray.pid` holds
3444
+ - The icon of a stopped process stays in the notification area until the
3445
+ pointer passes over it; that is how Windows handles an icon whose process
3446
+ was ended
3447
+ - The bundle holds no component and no window runtime; most of its size is
3448
+ zod, which a bundle for Node carries (`scripts/pack/tray-entrypoint.test.ts`
3449
+ keeps its budget)
3450
+ - `tray.svelte` is the same entrypoint written as markup (next section); a
3451
+ folder with both `tray.ts` and `tray.svelte` is an error
3452
+
3453
+ The working example is `examples/tray-entrypoint`
3454
+
3455
+ #### The tray written as markup (`entrypoints/tray.svelte`)
3456
+
3457
+ The menu can be written with the components of
3458
+ `winui-svelte/tray/menu/svelte`; the build reads the file with Svelte's parser
3459
+ and lowers the markup to the plain model of `tray.ts`, so none of Svelte's
3460
+ runtime is in `tray.js` (about 40 KB that a tray-only process cannot carry)
3461
+
3462
+ ```svelte
3463
+ <script module lang="ts">
3464
+ import { activateOrLaunch, resolveMenu } from "winui-svelte/tray/standalone";
3465
+
3466
+ let isAutostart = false;
3467
+
3468
+ function openApp() {
3469
+ void activateOrLaunch({ key: "my-app", activation: { arguments: [], workingDirectory: "." }, launch: { command: process.execPath, arguments: ["main.js"] } });
3470
+ }
3471
+
3472
+ function recentCaptures() {
3473
+ return ["a.png", "b.png"];
3474
+ }
3475
+
3476
+ export const options = {
3477
+ icon: "tray.ico",
3478
+ tooltip: "My app",
3479
+ guid: "7d1c5a52-3f1b-4a63-9f5e-2f4d6b0c8a11",
3480
+ onactivate: openApp,
3481
+ resolve: resolveMenu
3482
+ };
3483
+ </script>
3484
+
3485
+ <script lang="ts">
3486
+ import { TrayMenu, TrayMenuItem, TrayMenuSubmenu } from "winui-svelte/tray/menu/svelte";
3487
+ </script>
3488
+
3489
+ <TrayMenu>
3490
+ <TrayMenuItem id="open" label="Open" isRequired onselect={openApp} />
3491
+ <TrayMenuSubmenu id="recent" label="Recent" emptyLabel="Nothing yet">
3492
+ {#each recentCaptures() as name, iCapture (name)}
3493
+ <TrayMenuItem id={`recent.${iCapture}`} label={name} />
3494
+ {/each}
3495
+ </TrayMenuSubmenu>
3496
+ {#if isAutostart}
3497
+ <TrayMenuItem id="delay" label="Delay at sign-in" />
3498
+ {/if}
3499
+ </TrayMenu>
3500
+ ```
3501
+
3502
+ - `<script module>` holds `export const options = { ... }`, the options of
3503
+ `defineTray` except `menu` (the markup is the menu); the build reads `icon`,
3504
+ `tooltip` and `guid` from its literals as it does for `tray.ts`, and
3505
+ everything `options` uses (functions, imports) lives in the same script,
3506
+ because Svelte keeps a module script apart from the instance script; a
3507
+ `satisfies` on the object is read through
3508
+ - The menu is read each time it opens, like the dynamic values of the model, so
3509
+ a plain `let` and a plain function are always current; there is no `$state`,
3510
+ `$derived`, `$effect`, `$props`, `$bindable`, `$inspect` or `$host` (the build
3511
+ refuses them, since nothing would re-run)
3512
+ - Supported: `TrayMenu` (once, the root, no attributes), `TrayMenuItem` (a
3513
+ command, or `kind="check"` or `kind="radio"`), `TrayMenuSubmenu`,
3514
+ `TrayMenuSeparator` and `TrayMenuHeader`, imported by name; attributes as
3515
+ `label="text"`, `label="x {y}"`, `label={expression}`, `{shorthand}`, a bare
3516
+ boolean (`isRequired`), `{...spread}` and `onselect={handler}`; `{#if}`,
3517
+ `{:else if}` and `{:else}`; `{#each list as item, index (key)}` over an array
3518
+ (the key is not used, the `id` is the identity); `{@const}`; the children of
3519
+ a submenu become its `items` function
3520
+ - Refused with an error that names the file, the line and the construct:
3521
+ components of your own, other elements, `{#await}`, `{#key}`, `{#snippet}`,
3522
+ `{@render}`, `{@html}`, `{@debug}`, `bind:`, `use:`, `on:`, `class:`,
3523
+ `style:`, `let:`, transitions, `animate:`, `{@attach}`, `<svelte:*>`, text
3524
+ between the lines, `{:else}` of an `{#each}` (give the submenu an
3525
+ `emptyLabel`), a `<style>` block and importing a `.svelte` file
3526
+ - Each line becomes an object literal and `menu` the function that returns
3527
+ them: `{#if}` spreads a conditional array, `{#each}` spreads `flatMap`, so
3528
+ `defineTray` receives `menu: () => [ ... ]` (a function is accepted wherever
3529
+ an array is, by `createStandaloneTray` too)
3530
+ - `svelte-check` and the editor check the markup against the props of the
3531
+ components, so a wrong attribute or value is an error there; the build
3532
+ checks nothing, as for any `.svelte` file
3533
+ - A `tray.svelte` built to `tray.js` is within a few dozen bytes of the same
3534
+ tray written in `tray.ts` (`scripts/pack/tray-svelte-entrypoint.test.ts`)
3535
+
3536
+ The working example is `examples/tray-entrypoint-svelte`
3537
+
2910
3538
  ### Notice with no app (`winui-svelte/notice`)
2911
3539
 
2912
3540
  `showNotice` shows a message box before there is a window or an app: the
@@ -2952,7 +3580,8 @@ const isConfirmed = pressed === NoticeButton.YES;
2952
3580
  ### Taskbar button (`winui-svelte/window/taskbar`)
2953
3581
 
2954
3582
  `handle.taskbar` is the window's button on the taskbar: a progress bar, an
2955
- overlay icon and flashing, over `ITaskbarList3` and `FlashWindowEx`
3583
+ overlay icon, flashing and the thumbnail's tooltip and clip, over
3584
+ `ITaskbarList3` and `FlashWindowEx`
2956
3585
  No package identity is needed; call it on the UI thread
2957
3586
  The shell calls need the real desktop shell, so a window on a desktop of its
2958
3587
  own gets `E_NOTIMPL`; a window that has no taskbar button (a background or
@@ -2978,6 +3607,15 @@ handle.taskbar.flash({ count: 2 });
2978
3607
  - `flash({ count, until })`: `until` is a `TaskbarFlashUntil` (`count`, the
2979
3608
  default, flashes `count` times, 3 by default; `foreground` until the window is
2980
3609
  brought forward; `stopped` until `stopFlashing()`)
3610
+ - `setThumbnailTooltip(text)`: the text above the window's thumbnail on hover
3611
+ (259 characters at most, else a `RangeError`; empty shows the title again)
3612
+ - `setThumbnailClip({ x, y, width, height })`: shows only that part of the
3613
+ window in the thumbnail, in pixels of the client area, inside it; `null`
3614
+ shows all of it; whole numbers with a positive size, else a `TypeError`
3615
+ `SetThumbnailClip` gets `E_NOTIMPL` on a desktop of its own, so only a fake
3616
+ tests it
3617
+ - Thumbnail toolbar buttons are not offered: their click is a sent message
3618
+ that Node cannot receive; use jump list tasks (`winui-svelte/app/jump-list`)
2981
3619
  - `createTaskbarButton(hwnd)` and `TaskbarButton` take a window handle
2982
3620
  (`appWindow.id.value`) directly; `taskbarBadgeBackend(button)` is the
2983
3621
  `fallback` for `installBadging`
@@ -3020,6 +3658,708 @@ handle.taskbar.flash({ count: 2 });
3020
3658
  The working example is `examples/services` (`test/services.test.ts` runs it in
3021
3659
  a real window; the dialogs themselves need a person and are not opened there)
3022
3660
 
3661
+ ## ChromePermissions (`winui-svelte/chrome/permissions`)
3662
+
3663
+ `chrome.permissions` for a native app, with Chrome's names and shapes:
3664
+ `getAll()`, `contains(permissions)`, `request(permissions)`,
3665
+ `remove(permissions)`, `onAdded` and `onRemoved` (a `ChromeEvent`), and
3666
+ `Permissions { permissions, origins }`
3667
+ Opt-in: nothing is bundled until an app imports it, importing does no work,
3668
+ and no global is installed
3669
+
3670
+ ```ts
3671
+ import { ChromePermissions } from "winui-svelte/chrome/permissions";
3672
+
3673
+ const permissions = new ChromePermissions();
3674
+ permissions.onAdded.addListener(({ permissions: names }) => console.log(names));
3675
+ const isAllowed = await permissions.request({
3676
+ permissions: ["geolocation"],
3677
+ openSettings: true
3678
+ });
3679
+ ```
3680
+
3681
+ There is no per-site prompt in a native app; a permission is the OS consent
3682
+ the Permissions API already reports (`registerPermission` providers, so the
3683
+ Web APIs stay the single source of truth)
3684
+ The app holds a native permission when it asked for it and Windows allows it
3685
+ now; if either side takes it back, `contains` turns false
3686
+ The names the app asked for are saved in `chrome-permissions.json` in the
3687
+ app's data folder (`appDataFolder`, the folder `localStorage` uses), kept
3688
+ by an atomic write
3689
+
3690
+ | Chrome name | Held when | Backed by |
3691
+ | --- | --- | --- |
3692
+ | `audioCapture` | allowed | `microphone` |
3693
+ | `videoCapture` | allowed | `camera` |
3694
+ | `geolocation` | allowed | `geolocation` |
3695
+ | `notifications` | allowed | `notifications` |
3696
+ | `clipboardRead`, `clipboardWrite` | allowed | `clipboard-read`, `clipboard-write` |
3697
+ | `idle` | allowed | `idle-detection` |
3698
+ | `bluetooth` | allowed | `bluetooth` |
3699
+ | `gcm` | allowed | `push` |
3700
+ | `power` | allowed | `screen-wake-lock` |
3701
+ | `unlimitedStorage` | allowed | `persistent-storage` |
3702
+ | `activeTab`, `alarms`, `background`, `contextMenus`, `cookies`, `declarativeNetRequest`, `downloads`, `offscreen`, `scripting`, `storage`, `tabs`, `webRequest`, `windows` | always | nothing; no native meaning, and `remove` answers false |
3703
+ | any other name | never | `contains` and `request` reject with an `Error` |
3704
+ | origins (`<all_urls>` and match patterns) | always | nothing; a native app has no host permissions, a bad pattern rejects, `remove` answers false |
3705
+
3706
+ - The table is data you can read: `NATIVE_PERMISSIONS` (a `Map` from a Chrome
3707
+ name to the Web permissions behind it), `GRANTED_BY_DEFAULT` (a `Set` of the
3708
+ always-held names) and `ALL_URLS` (`<all_urls>`)
3709
+ - `request` checks each missing native permission: a state of `prompt` calls
3710
+ the provider's `request` (location shows the Windows prompt through
3711
+ `Geolocator.RequestAccessAsync`); camera and microphone are asked by the
3712
+ first device open, so they stay refused until Windows allows them
3713
+ - All requested permissions must be allowed, or `request` answers false and
3714
+ saves nothing; `onAdded` fires with the new ones
3715
+ - WinUI-only extra: `openSettings: true` in the object of `request` opens the
3716
+ Settings page with the switch (`ms-settings:privacy-webcam`,
3717
+ `privacy-microphone`, `privacy-location`, `notifications`, `bluetooth`,
3718
+ else `privacy`) when a permission stays refused; the answer is still false
3719
+ - `remove` forgets the saved grant and fires `onRemoved`; Windows keeps its own
3720
+ switch
3721
+ - Options of the constructor: `file`, `appName`, `location`, `environment`
3722
+ and `openSettings`, the stand-ins for tests
3723
+
3724
+ ## ChromeContextMenus (`winui-svelte/chrome/context-menus`)
3725
+
3726
+ `chrome.contextMenus` for a native app, with Chrome's names and shapes:
3727
+ `create(properties)` (answers the id), `update(id, properties)`,
3728
+ `remove(id)`, `removeAll()` and `onClicked` (a `ChromeEvent`); the item
3729
+ types `normal`, `checkbox`, `radio` and `separator`, and `title`, `id`,
3730
+ `checked`, `enabled`, `visible`, `contexts`, `parentId` and `onclick`
3731
+ Opt-in: nothing is bundled until an app imports it, importing does no work,
3732
+ and no global is installed
3733
+
3734
+ The items live in one list and are drawn by the tray menu model
3735
+ (`winui-svelte/tray/menu`), not by a second menu implementation:
3736
+ `menu(surface)` answers the lines for `TrayIcon` (`menu={...}`) or for a
3737
+ window's context flyout, in the same `MenuItem` shape
3738
+ The array is the same object each time and is rewritten in place when an item
3739
+ changes, so a menu that reads it when it opens shows the current items
3740
+
3741
+ ```ts
3742
+ import { ChromeContextMenus, ContextMenuSurface } from "winui-svelte/chrome/context-menus";
3743
+
3744
+ const menus = new ChromeContextMenus();
3745
+ menus.create({ id: "pause", title: "Pause", type: "checkbox", contexts: ["action"] });
3746
+ menus.onClicked.addListener(({ menuItemId, checked }) => console.log(menuItemId, checked));
3747
+ const lines = menus.menu(ContextMenuSurface.TRAY);
3748
+ ```
3749
+
3750
+ | Context | Surface | Shown |
3751
+ | --- | --- | --- |
3752
+ | `action`, `browser_action`, `page_action` | `tray` | in the tray icon's menu |
3753
+ | `page` | `window` | in the context flyout of a window |
3754
+ | `all` | both | in both |
3755
+ | `frame`, `selection`, `link`, `editable`, `image`, `video`, `audio`, `launcher` | none | accepted and ignored; there is no page under a native menu |
3756
+
3757
+ - `contexts` is `["page"]` when left out, as in Chrome
3758
+ - `documentUrlPatterns` and `targetUrlPatterns` are accepted and ignored
3759
+ - A radio belongs to the run of radios next to it among its siblings; a pick
3760
+ ticks it and unticks the others of the run
3761
+ - A pick of a checkbox flips it; `onclick` runs first, then `onClicked`
3762
+ fires with `menuItemId`, `parentMenuItemId`, `checked`, `wasChecked` and
3763
+ `editable` (always false); there is no `pageUrl`, `selectionText` or tab
3764
+ - An item with children is drawn as a submenu; a hidden item leaves out its
3765
+ children
3766
+ - `create` throws, and `update` and `remove` reject, with an `Error` for a
3767
+ duplicate id, an unknown id or parent, a parent under the item, a missing
3768
+ title, or a key Chrome does not know
3769
+ - Not mirrored: the callback arguments (use the promises), Chrome's grouping of
3770
+ several top-level items under the extension's name, and the limit of six
3771
+ top-level `action` items
3772
+ - Public exports: `ChromeContextMenus`, `ContextItemType`,
3773
+ `ContextMenuSurface`, `ContextType`, `ChromeEvent`, and the types
3774
+ `CreateProperties`, `OnClickData` and `UpdateProperties`
3775
+
3776
+ ## Downloads (`winui-svelte/downloads`)
3777
+
3778
+ Downloads on the two APIs an app already knows: the web's `fetch` with the File
3779
+ System Access API, and `chrome.downloads`
3780
+ Opt-in: nothing is bundled until an app imports it, and importing does no work
3781
+
3782
+ ### Web layer: `fetchToFile`
3783
+
3784
+ `fetchToFile` streams a URL into the file handle `showSaveFilePicker` gave
3785
+ (`installFileSystem` defines it), resumes with a Range request and marks the
3786
+ finished file as downloaded from the Internet
3787
+
3788
+ ```ts
3789
+ import { fetchToFile } from "winui-svelte/downloads";
3790
+
3791
+ const handle = await showSaveFilePicker({ suggestedName: "setup.exe" });
3792
+ await fetchToFile({
3793
+ url: "https://example.com/setup.exe",
3794
+ handle,
3795
+ onprogress: ({ loaded, total }) => console.log(loaded, total)
3796
+ });
3797
+ ```
3798
+
3799
+ - The body goes through `FileSystemWritableFileStream`; when it is whole the
3800
+ file gets a `Zone.Identifier` alternate data stream with `ZoneId=3` and
3801
+ `HostUrl` (the final address, without credentials), as a browser's download
3802
+ would, so Explorer and SmartScreen warn before it runs; a volume with no
3803
+ streams (FAT, a share) stays unmarked
3804
+ - A failed or cancelled (`signal`) read keeps the bytes that arrived;
3805
+ `resume: true` sends `Range: bytes=<size of the file>-` and appends to it
3806
+ when the server answers 206 with the matching `Content-Range`; a server that
3807
+ ignores the range (200) or refuses it (416) makes the download start over
3808
+ - `onprogress({ loaded, total })` runs after every chunk; `total` is undefined
3809
+ when the server sends no length or compresses the body
3810
+ - A non-2xx answer throws `DownloadError` with the `status`; `headers`,
3811
+ `method` and `body` shape the request and `fetch` stands in for the global
3812
+ one (the tests do)
3813
+ - `requestDownload` and `streamToFile` are the two halves of `fetchToFile`, for
3814
+ an app that decides the file after the headers arrive;
3815
+ `markOfTheWeb({ path, hostUrl })` marks a file saved another way and
3816
+ `zoneIdentifierText(hostUrl)` is the stream's text
3817
+
3818
+ ### Chrome layer: `Downloads`
3819
+
3820
+ `Downloads` is `chrome.downloads` with the same names and shapes; where Chrome
3821
+ takes a callback, a method returns a promise
3822
+
3823
+ ```ts
3824
+ import { Downloads } from "winui-svelte/downloads";
3825
+
3826
+ const downloads = new Downloads();
3827
+ downloads.onChanged.addListener(({ id, state }) => {
3828
+ if (state?.current === "complete") {
3829
+ console.log(`download ${id} is done`);
3830
+ }
3831
+ });
3832
+ const id = await downloads.download({
3833
+ url: "https://example.com/setup.exe",
3834
+ filename: "installers/setup.exe",
3835
+ conflictAction: "uniquify",
3836
+ taskbar: handle.taskbar
3837
+ });
3838
+ await downloads.pause(id);
3839
+ await downloads.resume(id);
3840
+ const [item] = await downloads.search({ id });
3841
+ ```
3842
+
3843
+ - `download({ url, filename, saveAs, conflictAction, headers, method, body })`
3844
+ returns the id once the download has started; the options are checked with
3845
+ zod, so a bad `url`, `method` or an unknown key rejects; `filename` is
3846
+ relative to the downloads folder (`directory` of the constructor, the user's
3847
+ Downloads folder by default) and may not leave it
3848
+ - The file name is `filename`, else the server's `Content-Disposition`, else
3849
+ the last part of the address; `conflictAction` is `uniquify` (the default,
3850
+ `name (1).ext`), `overwrite` or `prompt`; `saveAs` and `prompt` ask with the
3851
+ global `showSaveFilePicker` (or `pickSaveFile` of the constructor)
3852
+ - The bytes arrive in the file's name plus `.part`, renamed when whole, with
3853
+ the Mark of the Web
3854
+ - `pause(id)` keeps the bytes (`paused: true`, `canResume: true`) and
3855
+ `resume(id)` asks for the rest with a Range request; a dropped connection
3856
+ ends `interrupted` with `NETWORK_FAILED` and can resume too; `cancel(id)`
3857
+ deletes the bytes and ends `interrupted` with `USER_CANCELED`
3858
+ - `search(query)` takes Chrome's `DownloadQuery` (`query` terms, with a leading
3859
+ `-` to exclude, `filenameRegex`, `urlRegex`, `startedBefore` and the other
3860
+ time bounds, `totalBytesGreater`, `limit`, `orderBy` and every field as an
3861
+ exact match); `erase(query)` removes the ones that are not running from the
3862
+ list and returns their ids, the files stay; `removeFile(id)` deletes the file
3863
+ - `show(id)` and `showDefaultFolder()` open Explorer through `revealInExplorer`
3864
+ - `onCreated` gets the `DownloadItem`, `onChanged` a `DownloadDelta` with only
3865
+ what changed (`state`, `paused`, `bytesReceived`, `totalBytes`, `error`,
3866
+ `canResume`, `filename`, and so on) and `onErased` the id; they have
3867
+ `addListener`, `removeListener`, `hasListener` and `hasListeners`
3868
+ - The closed sets are `DownloadState` (`in_progress`, `interrupted`,
3869
+ `complete`), `FilenameConflictAction`, `HttpMethod` and `InterruptReason`,
3870
+ and `ChromeEvent` is the class of the three events
3871
+ - `DownloadItem.totalBytes` and `fileSize` are -1 while unknown, as in Chrome;
3872
+ the `error` values are `InterruptReason`'s, and an HTTP status maps to
3873
+ `SERVER_UNAUTHORIZED`, `SERVER_FORBIDDEN`, `SERVER_BAD_CONTENT` or
3874
+ `SERVER_FAILED`
3875
+ - `taskbar` is the one extra member of the options object: `handle.taskbar`
3876
+ shows a bar that fills as the download goes (a marquee when the size is
3877
+ unknown), yellow while paused, removed when it ends and red when it fails
3878
+ - Not mirrored: `open`, `getFileIcon`, `acceptDanger`, `setShelfEnabled`,
3879
+ `onDeterminingFilename` and the danger types, a download here is always safe
3880
+ - `src/downloads/fetch-to-file.test.ts` and `chrome-downloads.test.ts` run
3881
+ against a local HTTP server with Range support
3882
+
3883
+ ## Chrome storage (`winui-svelte/chrome/storage`)
3884
+
3885
+ `chrome.storage` with the same areas, names and shapes; where Chrome takes a
3886
+ callback, a method returns a promise
3887
+ Opt-in: nothing is bundled until an app imports it, and importing does no work
3888
+
3889
+ ```ts
3890
+ import { ChromeStorage } from "winui-svelte/chrome/storage";
3891
+
3892
+ const storage = new ChromeStorage();
3893
+ storage.onChanged.addListener((changes, areaName) => {
3894
+ console.log(areaName, changes);
3895
+ });
3896
+ await storage.local.set({ theme: "dark", volume: 0.8 });
3897
+ const { theme } = await storage.local.get({ theme: "light" });
3898
+ await storage.session.set({ token: "abc" });
3899
+ await storage.local.remove(["volume"]);
3900
+ const bytes = await storage.local.getBytesInUse();
3901
+ ```
3902
+
3903
+ - Areas: `local`, `sync`, `session` and `managed`, each a `StorageArea` with
3904
+ `get`, `getKeys`, `getBytesInUse`, `set`, `remove`, `clear`,
3905
+ `setAccessLevel` and `onChanged`; `ChromeStorage.onChanged` fires for every
3906
+ area with `(changes, areaName)`
3907
+ - `get(keys)` takes a key, an array of keys, an object of defaults, or null or
3908
+ nothing for every item; arguments are checked with zod and a wrong one
3909
+ rejects
3910
+ - Values are JSON, as in Chrome: a value JSON cannot hold (a function,
3911
+ `undefined`) is left out, `NaN` becomes `null` and a `Date` becomes its
3912
+ string; the stored files are checked with zod and a corrupt one reads as
3913
+ empty
3914
+ - `local` is a JSON file in the app's local data folder, next to
3915
+ `localStorage` (`chrome-storage-local.json`, written atomically after every
3916
+ change); `session` is in memory and ends with the process; the file is read
3917
+ on the first call to the area
3918
+ - `sync` is a local fallback: Windows has no sync service an unpackaged app
3919
+ can use (roaming settings are deprecated), so `chrome-storage-sync.json`
3920
+ lives beside the local file and values never reach another PC; Chrome's
3921
+ `sync` limits apply (`QUOTA_BYTES` 102400, `QUOTA_BYTES_PER_ITEM` 8192,
3922
+ `MAX_ITEMS` 512) so code meets the same errors; the write-rate constants are
3923
+ published and not enforced
3924
+ - `managed` is read-only and always empty: `set`, `remove` and `clear` reject
3925
+ with `This is a read-only store.`, and `get` answers the defaults
3926
+ - `QUOTA_BYTES` is 10485760 for `local` and `session`, and a write that would
3927
+ pass a quota rejects and stores nothing; `getBytesInUse` counts each key's
3928
+ length plus its JSON text, as Chrome does
3929
+ - `onChanged` gets `{ key: { oldValue, newValue } }` only for keys that
3930
+ changed (`oldValue` is missing for a new key, `newValue` for a removed one);
3931
+ a write that changes nothing fires nothing
3932
+ - `setAccessLevel({ accessLevel })` takes `AccessLevel`'s values and keeps
3933
+ them; every context of a native app is trusted, so it changes nothing
3934
+ - A change made by another process is not seen, and `ChromeStorage` takes
3935
+ `appName`, `environment`, `localFile` and `syncFile` (the tests give an
3936
+ in-memory file); the closed sets are `StorageAreaName` and `AccessLevel`
3937
+ - `LOCAL_QUOTA`, `SESSION_QUOTA` and `SYNC_QUOTA` hold the numbers each area
3938
+ publishes, for code that wants them without making a `ChromeStorage`
3939
+ - `src/chrome/storage/chrome-storage.test.ts` runs against an in-memory file
3940
+
3941
+ ## Chrome runtime (`winui-svelte/chrome/runtime`)
3942
+
3943
+ `chrome.runtime` for a native app: the manifest, messages and ports between the
3944
+ app's own contexts, native messaging hosts, and the install and exit events
3945
+ Opt-in: nothing is bundled until an app imports it, importing does no work, and
3946
+ no global `chrome` is installed; make one `Runtime` in each context that wants
3947
+ one
3948
+
3949
+ ```ts
3950
+ import { Runtime } from "winui-svelte/chrome/runtime";
3951
+
3952
+ const runtime = new Runtime();
3953
+ runtime.addLink(transport);
3954
+ runtime.onMessage.addListener((message, sender, sendResponse) => {
3955
+ sendResponse({ echo: message });
3956
+ });
3957
+ const answer = await runtime.sendMessage({ hello: "world" });
3958
+ ```
3959
+
3960
+ - Where Chrome sets `chrome.runtime.lastError`, a promise rejects or a `Port`
3961
+ has an `error`; there is no `lastError`
3962
+ - `getManifest()` gives `{ manifest_version: 3, name, version, description }`
3963
+ from the package identity when the app has one, else from the nearest
3964
+ `package.json` above the entry script; `id` is the package family name, or
3965
+ the `package.json` name; `getURL(path)` is `ms-appx:///path` in a package and
3966
+ a `file:` URL under the folder of `package.json` otherwise;
3967
+ `getPlatformInfo()` is `{ os: "win", arch }` with Chrome's architecture names
3968
+ - Contexts are joined by `addLink(transport)`, with any transport of
3969
+ `winui-svelte/state` (a worker's message port, stdio, memory); the call
3970
+ returns how to leave; messages are `defineMessaging` requests, so framing,
3971
+ timeouts (`timeoutMilliseconds`) and a closed link are the messaging layer's
3972
+ own, and every frame is checked with zod
3973
+ - `sendMessage(message)` reaches every other linked context and resolves with
3974
+ the first answer; a listener answers with `sendResponse`, by returning `true`
3975
+ and calling it later, or by returning a promise; it resolves `undefined` when
3976
+ listeners heard it and none answered, and rejects with Chrome's own "Receiving end does not exist" error when no
3977
+ context is linked or none listens; a listener that throws or rejects rejects the sender
3978
+ - `connect({ name })` opens a `Port` to every other linked context, which hears
3979
+ it in `onConnect`; `Port` has `postMessage`, `onMessage`, `onDisconnect`,
3980
+ `disconnect()`, `name` and `sender`; a port ends when the link closes, and
3981
+ `error` says why when something failed
3982
+ - `connectNative(application)` and `sendNativeMessage({ application, message })`
3983
+ start a registered host and speak the native messaging protocol on its stdio
3984
+ (four bytes of length, then JSON; a host's message is limited to 1 MiB)
3985
+ - A host is registered as in Chrome: a key
3986
+ `Software\winui-svelte\NativeMessagingHosts\<name>` below
3987
+ `HKEY_CURRENT_USER` whose default value is the path of the manifest (`name`,
3988
+ `path`, `type: "stdio"`, `allowed_origins`); the host gets the app's origin,
3989
+ `winui-svelte://<id>/`, as its first argument, and an `allowed_origins` that
3990
+ omits it refuses the host; a host is an executable, not a script;
3991
+ `resolveHost`, `registry` and `spawnHost` stand in for the lookup and the
3992
+ start in a test
3993
+ - `onInstalled` fires from `detectInstalled()`, which an app calls once at
3994
+ start: `{ reason: "install" }` on a first run, `{ reason: "update",
3995
+ previousVersion }` when the version changed, nothing when it is the same; the
3996
+ last version is kept in `%LOCALAPPDATA%\winui-svelte\runtime\<id>.json`, or
3997
+ in the `versionStore` you give
3998
+ - `onStartup` is the `onStartup` of `winui-svelte/app/schedule`, fired by
3999
+ `startActivation` for a `startup` activation (see `launchAtLogin`), not a
4000
+ second source
4001
+ - `onSuspend` fires when the process exits, the only suspend a desktop app
4002
+ has; `suspendSource` changes what it listens to; `dispose()` stops it and
4003
+ closes the links
4004
+ - `reload()` is `relaunch` of `winui-svelte/app`
4005
+ - The protocol's pieces are exported for a host written in Node:
4006
+ `encodeNativeMessage(message)`, `NativeMessageDecoder` (`push(chunk)` returns
4007
+ the messages a chunk completed), `NativeMessageError`, `MAX_HOST_MESSAGE_BYTES`
4008
+ and `NATIVE_HOST_REGISTRY_KEY`, the registry key below `HKEY_CURRENT_USER`
4009
+ that holds the hosts
4010
+ - Not mirrored: `onMessageExternal`, `onConnectExternal`, `onSuspendCanceled`,
4011
+ `onUpdateAvailable`, `requestUpdateCheck`, `restart`, `setUninstallURL`,
4012
+ `openOptionsPage`, `getContexts`, `getPackageDirectoryEntry`
4013
+ - The single-instance pipe stays the way a second copy of the app reaches the
4014
+ first (`startActivation`); contexts of one copy talk over their transports
4015
+ - `src/chrome/runtime/runtime.test.ts` runs it over in-memory links and a child
4016
+ process that echoes in the native messaging protocol
4017
+
4018
+ ## Chrome notifications (`winui-svelte/chrome/notifications`)
4019
+
4020
+ `chrome.notifications` for a native app, with Chrome's names and shapes; where
4021
+ Chrome takes a callback, a method returns a promise
4022
+ It delegates to the web `Notification` (`winui-svelte/web-apis/notification`),
4023
+ so there is one notification pipeline: the same permission, the same Windows
4024
+ app notifications and the same progress bar
4025
+ Opt-in: nothing is bundled until an app imports it, importing does no work, and
4026
+ no global is installed
4027
+ `installNotification()` must have run, as for the web `Notification`
4028
+
4029
+ ```ts
4030
+ import { ChromeNotifications } from "winui-svelte/chrome/notifications";
4031
+
4032
+ const notifications = new ChromeNotifications();
4033
+ notifications.onButtonClicked.addListener((id, index) => console.log(id, index));
4034
+ await notifications.create("sync", {
4035
+ type: "progress",
4036
+ title: "Syncing",
4037
+ message: "Uploading photos",
4038
+ progress: 10,
4039
+ buttons: [{ title: "Pause" }]
4040
+ });
4041
+ await notifications.update("sync", { progress: 60 });
4042
+ ```
4043
+
4044
+ - Exports: `ChromeNotifications`, `ChromeEvent`, `NotificationTemplateType`
4045
+ (`basic`, `image`, `list`, `progress`) and `NotificationPermissionLevel`
4046
+ (`granted`, `denied`), and the option types
4047
+ - `create(id, options)` resolves with the id (made up for a missing or empty
4048
+ one); the same id replaces the notification that is up, without `onClosed`
4049
+ The first call asks Windows for the permission and rejects with an `Error`
4050
+ when it is refused
4051
+ - `type`, `title` and `message` are required, and so is `imageUrl` for `image`,
4052
+ `items` for `list` and `progress` (0 to 100) for `progress`; `iconUrl` is
4053
+ optional, since an unpackaged app may have none; options are checked with a
4054
+ schema and a bad one rejects with an `Error`
4055
+ - `update(id, options)` merges into the notification and answers false when
4056
+ there is none; a change of `progress` alone moves the bar in place
4057
+ (`Notification.update`), anything else shows it again under its id
4058
+ - `clear(id)` removes it and answers false when there is none; `getAll()`
4059
+ answers an object with each id as a key and `true` as the value, for the
4060
+ notifications this run holds
4061
+ - `getPermissionLevel()` reads `Notification.permission`: `granted`, else
4062
+ `denied` (including "not asked yet", which the first `create` settles)
4063
+ - `onClicked(id)`, `onButtonClicked(id, buttonIndex)` and `onClosed(id, byUser)`
4064
+ are `ChromeEvent`s; Windows removes a clicked toast, so a click is followed
4065
+ by `onClosed(id, true)`, `clear` fires `onClosed(id, false)`, and a swipe away
4066
+ is not reported
4067
+ - `isClickable: false` silences `onClicked` for the body, not the buttons
4068
+ - Mapping: `message` is the body, `list` adds one `title: message` line per
4069
+ item, `image` uses `imageUrl`, `contextMessage` is the attribution,
4070
+ `eventTime` the timestamp, `buttons` (at most 2) become actions named by
4071
+ their index, `priority` below 0 is silent and 2 requires interaction, and
4072
+ `requireInteraction` and `silent` pass through
4073
+ - Not mirrored: `onPermissionLevelChanged` and `onShowSettings`
4074
+ - `src/chrome/notifications/chrome-notifications.test.ts` runs the web
4075
+ `Notification` over a stand-in for the Windows App SDK; no toast is shown
4076
+
4077
+ ## Chrome commands (`winui-svelte/chrome/commands`)
4078
+
4079
+ `chrome.commands` for a native app: the manifest's `commands` key as global
4080
+ hotkeys, over `registerHotkey` of `winui-svelte/app/hotkeys`
4081
+ Opt-in: nothing is bundled until an app imports it, importing does no work, and
4082
+ no global `chrome` is installed
4083
+
4084
+ ```ts
4085
+ import { ChromeCommands } from "winui-svelte/chrome/commands";
4086
+
4087
+ const commands = new ChromeCommands({
4088
+ commands: {
4089
+ toggle: {
4090
+ suggested_key: { default: "Ctrl+Shift+Y", mac: "Command+Shift+Y" },
4091
+ description: "Toggle the panel"
4092
+ }
4093
+ }
4094
+ });
4095
+ commands.onCommand.addListener(name => console.log(name));
4096
+ const failures = commands.start();
4097
+ const all = await commands.getAll();
4098
+ ```
4099
+
4100
+ - `start()` registers every shortcut (call it on the UI thread, where
4101
+ `registerHotkey` belongs) and returns the commands whose shortcut was
4102
+ refused, as `{ name, error }`; a clash with another app leaves that command
4103
+ unassigned, so its `getAll` shortcut is empty, as in Chrome; `stop()` gives
4104
+ the shortcuts back
4105
+ - `getAll()` resolves with `{ name, description, shortcut }` for each command
4106
+ in the manifest's order, the shortcut spelled `"Ctrl+Shift+Y"`
4107
+ - `suggested_key` is a string or one per platform; `windows` then `default`
4108
+ is used, and `mac`, `linux` and `chromeos` are ignored
4109
+ - `Ctrl`, `Alt` and `Shift` are as in Chrome; `Command` and `MacCtrl` mean
4110
+ Ctrl; keys are `A` to `Z`, `0` to `9`, `F1` to `F12`, `Comma`, `Period`,
4111
+ `Home`, `End`, `PageUp`, `PageDown`, `Space`, `Insert`, `Delete`, `Up`,
4112
+ `Down`, `Left`, `Right` and the four media keys; `parseShortcut(text)`
4113
+ reads one into the `HotkeyChord` and the display spelling, and throws for
4114
+ anything else
4115
+ - A bad manifest (a shortcut Chrome would not take, or a wrong shape, checked
4116
+ with zod) throws from the constructor
4117
+ - Chrome keeps most shortcuts inside the browser; a native app has no such
4118
+ scope, so every shortcut with a key is system-wide and `global` changes
4119
+ nothing
4120
+ - `_execute_action` (and `_execute_browser_action`, `_execute_page_action`)
4121
+ call `onExecuteAction` when you give it, as Chrome treats them as a click on
4122
+ the action (pass `() => action.click()` of `winui-svelte/chrome/action`),
4123
+ and fire `onCommand` otherwise
4124
+ - `onCommand` is a `ChromeEvent` and is called with the name only, there is no
4125
+ tab; `register` stands in for `registerHotkey` in a test
4126
+ - Not mirrored: `onChanged`, and the shortcut customisation page
4127
+ - `src/chrome/commands/chrome-commands.test.ts` runs it over a fake registrar,
4128
+ so no real hotkey is registered
4129
+
4130
+ ## Chrome i18n (`winui-svelte/chrome/i18n`)
4131
+
4132
+ `chrome.i18n` for a native app: `getMessage` is synchronous, over the
4133
+ standard `_locales/<locale>/messages.json` files, so an unmodified
4134
+ extension's locale folder works
4135
+ Opt-in: nothing is bundled until an app imports it, importing does no work, and
4136
+ no global `chrome` is installed
4137
+
4138
+ ```ts
4139
+ import { ChromeI18n, installLanguageDefaults } from "winui-svelte/chrome/i18n";
4140
+
4141
+ const i18n = new ChromeI18n();
4142
+ i18n.getMessage("greeting", ["Ann", "3"]);
4143
+ installLanguageDefaults(i18n);
4144
+ ```
4145
+
4146
+ - `getMessage(name, substitutions)` takes a string or up to nine strings;
4147
+ `$1` to `$9` are the substitutions, `$NAME$` is the content of the
4148
+ message's `placeholders` entry of that name (which may hold `$1`), and `$$`
4149
+ is a dollar sign; names are matched without case; an unknown name gives an
4150
+ empty string, as in Chrome
4151
+ - Lookup is per message: the exact locale (`pt-BR` is the folder `pt_BR`),
4152
+ then its language (`pt`), then the `default_locale` of `manifest.json`
4153
+ beside the folder; `localesFolder`, `root`, `defaultLocale`, `uiLanguage` and
4154
+ `acceptLanguages` override the defaults (the app's root, `_locales` in it,
4155
+ the system language)
4156
+ - The predefined messages are `@@extension_id`, `@@ui_locale` (`en_US`),
4157
+ `@@bidi_dir`, `@@bidi_reversed_dir`, `@@bidi_start_edge` and
4158
+ `@@bidi_end_edge`
4159
+ - `getUILanguage()` is a BCP 47 tag; `getAcceptLanguages()` resolves with the
4160
+ list; `detectLanguage(text)` tells scripts apart (Arabic, Hebrew, Cyrillic,
4161
+ Greek, Thai, Devanagari, Hangul, kana and Han) and answers `und` for
4162
+ Latin-script text, where Chrome uses a trained model
4163
+ - Every `messages.json` is checked with zod; a malformed one throws from
4164
+ `getMessage`
4165
+ - `installLanguageDefaults(source)` makes `navigator.language`,
4166
+ `navigator.languages`, the default locale of the `Intl` formats and of
4167
+ `toLocaleString` (and its date and time forms) follow the same source, so
4168
+ they agree with `chrome.i18n`; a locale a caller passes still wins; it
4169
+ returns the function that undoes it
4170
+ - `src/chrome/i18n/chrome-i18n.test.ts` runs it over in-memory files
4171
+
4172
+ ## Chrome global (`winui-svelte/chrome/install`)
4173
+
4174
+ `installChromeApis` defines `globalThis.chrome` for code written for a Chrome
4175
+ extension
4176
+ Opt-in: importing does no work, and the global holds exactly the namespaces the
4177
+ app passes, so the bundle holds only what the app imported to make them
4178
+
4179
+ ```ts
4180
+ import { installChromeApis } from "winui-svelte/chrome/install";
4181
+ import { ChromeI18n } from "winui-svelte/chrome/i18n";
4182
+ import { ChromeStorage } from "winui-svelte/chrome/storage";
4183
+ import * as alarms from "winui-svelte/app/schedule";
4184
+
4185
+ const uninstall = installChromeApis({
4186
+ storage: new ChromeStorage(),
4187
+ i18n: new ChromeI18n(),
4188
+ alarms
4189
+ });
4190
+ await chrome.storage.local.set({ theme: "dark" });
4191
+ ```
4192
+
4193
+ - `ChromeGlobal` is the options object and the type of `globalThis.chrome`; its
4194
+ members are `storage`, `runtime`, `permissions`, `contextMenus`, `commands`,
4195
+ `action`, `notifications`, `i18n`, `alarms`, `downloads`, `system` and `windows`, each optional,
4196
+ each an instance (or, for `alarms`, the `ChromeAlarms` calls and events of
4197
+ `winui-svelte/app/schedule`); the object is open to more namespaces as they
4198
+ are mirrored
4199
+ - The package declares no global type; to type `chrome` in your app, declare
4200
+ `var chrome: ChromeGlobal` in your own `declare global`
4201
+ - A `chrome` object that is already there keeps its other members; the
4202
+ returned function puts the previous one back
4203
+ - It does not call `installLanguageDefaults`; do that where you want
4204
+ `navigator.language` and `Intl` to follow `chrome.i18n`
4205
+ - `src/chrome/install.test.ts` covers it
4206
+
4207
+ ## Chrome action (`winui-svelte/chrome/action`)
4208
+
4209
+ `chrome.action` for a native app, over the tray icon (`winui-svelte/tray`)
4210
+ Opt-in: nothing is bundled until an app imports it, importing does no work, and
4211
+ no global `chrome` is installed
4212
+
4213
+ ```ts
4214
+ import { createChromeAction } from "winui-svelte/chrome/action";
4215
+
4216
+ const { action, tray } = createChromeAction({
4217
+ icon: "app.ico",
4218
+ title: "Inbox",
4219
+ guid: "0b3c0a53-2a8f-4a5e-9d57-1c2f7c1a9f10"
4220
+ });
4221
+ action.onClicked.addListener(() => console.log("clicked"));
4222
+ await action.setBadgeText({ text: "3" });
4223
+ ```
4224
+
4225
+ - `createChromeAction(options)` takes the options of `createTrayIcon` (except
4226
+ `onclick`) and `title`, makes the tray icon and returns `{ action, tray }`;
4227
+ call it on the UI thread; the left click is `onClicked`, the other gestures
4228
+ go to the tray as given; `createTray` stands in for `createTrayIcon` in a test
4229
+ - `new ChromeAction({ title, tray })` is the same without making the tray: give
4230
+ the tray's `onclick` to `action.click()`, then `attach(tray)` (a tray from
4231
+ `defineTray` fits), through the `ActionTray` shape
4232
+ - `setTitle({ title })` and `getTitle()` are the tooltip, kept to what the shell
4233
+ holds (127 characters)
4234
+ - `setIcon({ path })` swaps the icon file; `path` is a string or
4235
+ `{ forLightTaskbar, forDarkTaskbar }`; Chrome's `imageData` and size maps
4236
+ are rejected
4237
+ - `setBadgeText({ text })` and `getBadgeText()`: the tray cannot paint on an
4238
+ icon (icons are files loaded by path, and drawing needs a new icon file on
4239
+ every change), so the badge is a tooltip suffix, `"Inbox (3)"`; empty text
4240
+ clears it
4241
+ - `setBadgeBackgroundColor({ color })` and `getBadgeBackgroundColor()` keep the
4242
+ color (four channels, or `#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`; Chrome's
4243
+ red until set) and nothing draws it
4244
+ - `enable()`, `disable()` and `isEnabled()`: a disabled action still shows
4245
+ (the tray cannot grey an icon) but a click on it is ignored
4246
+ - Every method returns a promise and rejects on a bad argument (zod); `tabId`
4247
+ is accepted and ignored, there are no tabs, so everything is global
4248
+ - `onClicked` is a `ChromeEvent` and is called with no argument
4249
+ - Not mirrored: `setPopup`, `getPopup`, `openPopup`, `getUserSettings`,
4250
+ `setBadgeTextColor`, `onUserSettingsChanged`
4251
+ - `src/chrome/action/chrome-action.test.ts` runs it over a fake tray
4252
+
4253
+ ## Chrome system (`winui-svelte/chrome/system`)
4254
+
4255
+ `chrome.system` for a native app: `cpu`, `memory`, `storage` and `display`
4256
+ with Chrome's names and promises, over Node's `os` and the display areas
4257
+ that `winui-svelte/devices/display` and the web `screen` read
4258
+ Opt-in: nothing is bundled until an app imports it, importing does no work, and
4259
+ no global `chrome` is installed
4260
+
4261
+ ```ts
4262
+ import { createChromeSystem } from "winui-svelte/chrome/system";
4263
+
4264
+ const system = createChromeSystem();
4265
+ const cpu = await system.cpu.getInfo();
4266
+ const memory = await system.memory.getInfo();
4267
+ const drives = await system.storage.getInfo();
4268
+ const displays = await system.display.getInfo();
4269
+ system.display.onDisplayChanged.addListener(() => console.log("changed"));
4270
+ ```
4271
+
4272
+ - `createChromeSystem(options)` returns `{ cpu, memory, storage, display }`
4273
+ (`SystemCpu`, `SystemMemory`, `SystemStorage`, `SystemDisplay`); nothing is
4274
+ read until a method is called; `backend` stands in for the machine in a
4275
+ test, and `windowsSystemBackend()` is the default (`SystemBackend` is its
4276
+ shape)
4277
+ - `cpu.getInfo()` resolves with `numOfProcessors`, `archName` (`x86-64`,
4278
+ `arm64`, `x86-32`, `arm`), `modelName`, `features`, `processors` (the
4279
+ `kernel`, `user`, `idle` and `total` milliseconds of each) and an empty
4280
+ `temperatures`; `features` is `mmx`, `sse` and `sse2` on x64 and empty
4281
+ elsewhere, as Node reports no others
4282
+ - `memory.getInfo()` resolves with `capacity` and `availableCapacity` in bytes
4283
+ - `storage.getInfo()` resolves with `{ id, name, type, capacity }` for each
4284
+ drive letter, `type` one of `StorageUnitType` (`fixed`, `removable`,
4285
+ `unknown`), read with `GetDriveTypeW`
4286
+ - `storage.onAttached` and `storage.onDetached` are not mirrored: Windows
4287
+ tells an app about a drive coming or going only through a hidden window's
4288
+ `WM_DEVICECHANGE` or a `DeviceWatcher` that needs a package identity; call
4289
+ `getInfo` again
4290
+ - `display.getInfo(flags)` resolves with one record per display area, the
4291
+ primary first: `id`, `name` (`Display 1` and so on), `isPrimary`,
4292
+ `isEnabled`, `dpiX`, `dpiY` (the system scale times 96), `bounds` and
4293
+ `workArea` as `{ left, top, width, height }` in screen pixels;
4294
+ `mirroringSourceId` is empty and `rotation` 0, as Windows tells an app
4295
+ neither; `singleUnified` is accepted and ignored; a flag of the wrong
4296
+ type rejects (zod)
4297
+ - `display.onDisplayChanged` is a `ChromeEvent` called with no argument; the
4298
+ display watcher runs only while a listener is added
4299
+ - Not here on purpose: `chrome.idle` is the web `IdleDetector` and
4300
+ `chrome.desktopCapture` the web `getDisplayMedia`, both already covered
4301
+ - `src/chrome/system/chrome-system.test.ts` runs it over a fake backend
4302
+
4303
+ ## Chrome windows (`winui-svelte/chrome/windows`)
4304
+
4305
+ `chrome.windows` for the windows of a native app, over `WindowHandle`
4306
+ Opt-in: nothing is bundled until an app imports it, importing does no work, and
4307
+ no global `chrome` is installed
4308
+
4309
+ ```ts
4310
+ import { createWindow } from "winui-svelte/window";
4311
+ import { chromeWindowSurface, createChromeWindows, WindowState } from "winui-svelte/chrome/windows";
4312
+
4313
+ const windows = createChromeWindows({
4314
+ open: () => chromeWindowSurface(createWindow({ component: Panel, props: {} }).handle)
4315
+ });
4316
+ windows.track({
4317
+ surface: chromeWindowSurface(mainHandle),
4318
+ isCurrent: true
4319
+ });
4320
+ windows.onFocusChanged.addListener(windowId => console.log(windowId));
4321
+ const panel = await windows.create({ width: 400, height: 300 });
4322
+ await windows.update(panel.id, { state: WindowState.maximized });
4323
+ await windows.remove(panel.id);
4324
+ ```
4325
+
4326
+ - `createChromeWindows(options)` makes a `ChromeWindows`; make one and share
4327
+ it, since the windows it knows and their ids live in it; no process-wide
4328
+ list of windows exists, so the app hands it the windows
4329
+ - `track({ surface, isCurrent })` starts reporting a window, gives it an id
4330
+ from 1 and fires `onCreated`; `chromeWindowSurface(handle)` makes a
4331
+ `ChromeWindowSurface` of a `WindowHandle` (`bind:handle` on `<Window>`, or
4332
+ the `handle` of what `createWindow` returns); a window leaves when it
4333
+ closes, firing `onRemoved`
4334
+ - `create(createData)` calls the `open` option, which makes the content,
4335
+ tracks what it returns and then applies `left`, `top`, `width`, `height`,
4336
+ `state` and `focused`; without `open` it rejects; `url`, `tabId`, `type`,
4337
+ `incognito` and `setSelfAsOpener` reach `open` and nothing else
4338
+ - `get(windowId)`, `getCurrent()`, `getLastFocused()` and `getAll()` resolve
4339
+ with a `ChromeWindow`: `id`, `focused`, `top`, `left`, `width`, `height`,
4340
+ `state`, `alwaysOnTop`, `incognito` (always false) and `type` (always
4341
+ `normal`); places and sizes are in device pixels, as `AppWindow` has them;
4342
+ `populate` and `windowTypes` are accepted and ignored, there are no tabs
4343
+ - `WINDOW_ID_CURRENT` (-2) names the window `track` marked current, else the
4344
+ last focused; `WINDOW_ID_NONE` (-1) is what `onFocusChanged` reports when
4345
+ focus leaves the app's windows
4346
+ - `update(windowId, updateInfo)` takes `left`, `top`, `width`, `height`,
4347
+ `state` (`WindowState`: `normal`, `minimized`, `maximized`, `fullscreen`,
4348
+ `locked-fullscreen`, the last as full screen), `focused` (true brings the
4349
+ window forward; false changes nothing) and `drawAttention` (flashes the
4350
+ taskbar button until the window is brought forward); as in Chrome a place
4351
+ or size cannot go with a state other than `normal`, and `focused` cannot go
4352
+ with `minimized`
4353
+ - `remove(windowId)` closes the window; `onRemoved` fires once it has closed,
4354
+ so a close guard on the window keeps it
4355
+ - Every method returns a promise and rejects on a bad argument (zod) or an
4356
+ unknown id; `WindowType` lists Chrome's types, and every window is `normal`
4357
+ - `onCreated`, `onRemoved`, `onFocusChanged` and `onBoundsChanged` are
4358
+ `ChromeEvent`s; `onBoundsChanged` fires after a move or a resize
4359
+ - Not mirrored: `tabs` in a window, `create`'s `focused: false` and `incognito`
4360
+ effects, and `onBoundsChanged`'s separate move and resize
4361
+ - `src/chrome/windows/chrome-windows.test.ts` runs it over fake windows
4362
+
3023
4363
  ## Data transfer (`winui-svelte/data-transfer`)
3024
4364
 
3025
4365
  Drag and drop, file dialogs, the clipboard and the launcher, in the web's
@@ -3169,8 +4509,17 @@ picker code in `src/window/pickers.ts` is the one used)
3169
4509
 
3170
4510
  `clipboard.readText()`, `readHtml()`, `read({ formats })` (a `DataTransfer`),
3171
4511
  `types()`, `writeText(text)`, `write({ text, html, uri, files, bitmap, custom,
3172
- shouldPersist })`, `clear()` and `onChange(callback)` (returns what stops it)
4512
+ shouldPersist, deferred })`, `clear()` and `onChange(callback)` (returns what
4513
+ stops it)
3173
4514
  `write` replaces the clipboard's whole content
4515
+ `deferred` maps a type to a provider (`() => Promise<string | NativeFile>`) that
4516
+ Windows runs when something pastes, through `DataPackage.SetDataProvider`; a
4517
+ source does the same for a drag with `event.dataTransfer.setDeferredData({
4518
+ type, provider })` in `dragstart`, and the data is made at the drop
4519
+ A type starting with `image/` is a picture, so its provider gives a `NativeFile`
4520
+ A provider that rejects leaves its format empty
4521
+ Windows runs a provider on the UI thread, and `shouldPersist` runs them at
4522
+ once, before the app exits
3174
4523
 
3175
4524
  ### Launcher and share
3176
4525
 
@@ -3207,6 +4556,78 @@ takes drops, through the handlers a real drop reaches, and resolves with the
3207
4556
  operation the control accepted (`0` when it refused); it sends no input, so an
3208
4557
  app can test its drop handling in a real window
3209
4558
 
4559
+ ## Incremental loading (`winui-svelte/incremental`)
4560
+
4561
+ A list that loads its next batch as the user scrolls near the end, for
4562
+ `ListView`, `GridView`, `ItemsRepeater`, `ItemsView` and `BreadcrumbBar`
4563
+ Opt-in: nothing is bundled until an app imports it, and importing does no work
4564
+
4565
+ ```svelte
4566
+ <script lang="ts">
4567
+ import { ListView } from "winui-svelte/components";
4568
+ import { createIncrementalSource, IncrementalStatus } from "winui-svelte/incremental";
4569
+
4570
+ const source = createIncrementalSource<Post>({
4571
+ batchSize: 25,
4572
+ load: ({ offset, count, signal }) => fetchPosts({ offset, count, signal })
4573
+ });
4574
+ </script>
4575
+
4576
+ <ListView incremental={source} item={postRow} items={source.items} key={post => post.id} />
4577
+ {#if source.state.status === IncrementalStatus.ERROR}
4578
+ <button onclick={() => source.retry()}>Try again</button>
4579
+ {/if}
4580
+ ```
4581
+
4582
+ `createIncrementalSource({ load, batchSize, threshold, isLast })` (options:
4583
+ `IncrementalSourceOptions`) returns an `IncrementalSource`, generic over the item;
4584
+ `IncrementalLoading` is what a list asks of its `incremental` prop
4585
+ `load({ offset, count, signal })` resolves with the next items; fewer than
4586
+ `count` (or none) is the last batch, and `isLast({ batch, items })` decides when
4587
+ the size cannot (a server that sends a cursor)
4588
+ `batchSize` is 20 and `threshold` is 5 by default: the next batch loads when
4589
+ the control realizes an item within `threshold` of the end
4590
+ The source holds `items` and `state`, both reactive
4591
+ `state` is `{ status: "idle" | "loading" | "done" }` or
4592
+ `{ status: "error", error }`; `IncrementalStatus` names the four (also in
4593
+ `winui-svelte/enums`)
4594
+
4595
+ - `loadMore()` loads now; while a load is in flight it returns that load's
4596
+ promise, so a load never runs twice, and it never rejects
4597
+ - A failure is the `error` state and stays until `retry()`; the list does not
4598
+ retry by itself
4599
+ - `cancel()` aborts the load in flight through its `AbortSignal` and drops its
4600
+ result; `reset()` also clears the items, and a bound list loads the first
4601
+ batch again; `dispose()` aborts for good
4602
+ - A list bound to a source starts it, so the first batch needs no call
4603
+
4604
+ ### The mechanism, and why
4605
+
4606
+ WinUI's own is `ISupportIncrementalLoading` on the items source, which the
4607
+ list calls when it nears its end (`IncrementalLoadingTrigger`)
4608
+ winui-svelte does not use it: the items of these lists are a native vector of
4609
+ keys (see Items), and the interface belongs on the collection itself, which
4610
+ would have to be a JavaScript-made `IBindableVector`,
4611
+ `INotifyCollectionChanged` and `ISupportIncrementalLoading` returning an
4612
+ `IAsyncOperation`
4613
+ dynwinrt (0.1.0-preview.23) can make a COM object from a callback
4614
+ (`createComObject`), but nothing in this package has proved that WinUI binds it
4615
+ as an items source, and the same table would have to answer a bindable vector's
4616
+ every call, so it was not built
4617
+ Instead the control's own realization tells the source: ListView and GridView
4618
+ report each container's index through `ContainerContentChanging`, the repeaters
4619
+ through `ElementPrepared`, and the source loads when that index is within
4620
+ `threshold` of the end
4621
+ The report is made after the layout pass (a timer of zero, the furthest index of
4622
+ the pass), because a source that changes `state` during it changes the app's
4623
+ markup (a footer) while WinUI measures, which WinUI refuses
4624
+ `ScrollViewer.ChangeView` and a real scroll reach the source the same way
4625
+ (`test/incremental-list.test.ts`)
4626
+
4627
+ A loading footer, an error row or a "no more" line is markup of the app, beside
4628
+ the list, from `source.state`; the list has no footer snippet of its own
4629
+ The example is `examples/incremental-list`
4630
+
3210
4631
  ## Input events and focus (`winui-svelte/input`)
3211
4632
 
3212
4633
  The web's pointer, wheel, keyboard and focus events on any element, and focus
@@ -3361,6 +4782,7 @@ needs
3361
4782
  | `element.animate()`, `Animation`, `KeyframeEffect` | `winui-svelte/web-apis/animations` | web plus extras | none | done |
3362
4783
  | `ScrollTimeline`, `ViewTimeline`, `element.animate(keyframes, { timeline })` | `winui-svelte/scroll-timeline` | web | none | done |
3363
4784
  | `document.startViewTransition`, `ViewTransition`, `view-transition-name` | `winui-svelte/view-transitions` | web plus extras | none | done |
4785
+ | `alert`, `confirm`, `prompt` | `winui-svelte/dialogs` | web (as promises) plus extras | none | done |
3364
4786
  | `navigator.mediaDevices` (`getUserMedia`, `getDisplayMedia`, `enumerateDevices`), `MediaStream`, `MediaRecorder` | `winui-svelte/web-apis/media-devices` | web plus extras | none (a camera or microphone needs the Windows privacy switch on) | done |
3365
4787
  | `speechSynthesis`, `SpeechSynthesisUtterance`, `SpeechRecognition` (SSML, silences, scenario, phrases) | `winui-svelte/web-apis/speech` | web plus extras | none | done |
3366
4788
  | `navigator.mediaSession`, `MediaMetadata` | `winui-svelte/web-apis/media-session` | web plus extras | none | done |
@@ -3373,6 +4795,7 @@ needs
3373
4795
  | `navigator.credentials`, `PasswordCredential`, `PublicKeyCredential` (Windows Hello) | `winui-svelte/web-apis/credentials` | web plus extras | none | done |
3374
4796
  | `EyeDropper` | `winui-svelte/web-apis/eye-dropper` | web plus extras | none | done |
3375
4797
  | `FontFace`, `document.fonts` (font files of the app) | `winui-svelte/web-apis/fonts` | web plus extras | none | done |
4798
+ | `createImageBitmap`, `ImageBitmap`, `ImageDecoder`, canvas `toBlob`, `convertToBlob`, `toDataURL` (PNG, JPEG, GIF, BMP, TIFF) | `winui-svelte/web-apis/images` | web plus extras | none | done |
3376
4799
  | `navigator.contacts` (Contact Picker) | `winui-svelte/web-apis/contacts` | web plus extras | for most apps, package identity | done |
3377
4800
 
3378
4801
  Every row is built and tested; the timers (`setTimeout`, `setInterval`,
@@ -3406,7 +4829,9 @@ names the APIs register: `geolocation`, `accelerometer`, `screen-wake-lock`
3406
4829
  and so on) and `PermissionStateName` (`granted`, `denied`, `prompt`) are the
3407
4830
  spec's; an API registers its permission
3408
4831
  with `registerPermission({ name, provider })` and calls
3409
- `announcePermissionChange(name)` when it moves, so open statuses fire `change`
4832
+ `announcePermissionChange(name)` when it moves, so open statuses fire `change`; a provider may add `request()` (the system
4833
+ prompt), which `requestPermission(name)` calls and `readPermission(name)` reads
4834
+ back, as `chrome.permissions` does
3410
4835
 
3411
4836
  ### The three kinds and the extras convention
3412
4837
 
@@ -3664,8 +5089,11 @@ Each is `install<Name>()` from its own subpath and takes an optional `backend`
3664
5089
  the always granted `clipboard-read` and `clipboard-write` permissions
3665
5090
  More than one item, or a type the clipboard cannot take, rejects with
3666
5091
  `NotAllowedError`
5092
+ A type whose value is a promise (`new ClipboardItem({ "text/html": promise })`)
5093
+ is delayed-rendered: `write` resolves at once and the promise is awaited
5094
+ when something pastes
3667
5095
  Extras: `readContent({ formats })` (copied files in `files`, custom formats
3668
- as text), `writeContent({ files, custom, bitmap, shouldPersist })`,
5096
+ as text), `writeContent({ files, custom, bitmap, deferred, shouldPersist })`,
3669
5097
  `formats()` and `history()` (Win+V, empty when history is off)
3670
5098
  `windowsClipboardBackend()` is the real backend, for a test to wrap
3671
5099
  - `winui-svelte/web-apis/share`: `installShare()` defines `navigator.share`
@@ -3904,6 +5332,73 @@ old element to the new one
3904
5332
  `:active-view-transition-type()` have no counterpart, and `types` is carried
3905
5333
  but read by nothing
3906
5334
 
5335
+ #### Dialogs (`winui-svelte/dialogs`)
5336
+
5337
+ `installDialogs()` defines `alert`, `confirm` and `prompt` on the global scope
5338
+ over WinUI's `ContentDialog`
5339
+
5340
+ ```svelte
5341
+ <script lang="ts">
5342
+ import { installDialogs, useDialogWindow } from "winui-svelte/dialogs";
5343
+ import type { WindowHandle } from "winui-svelte/components";
5344
+
5345
+ installDialogs();
5346
+ let handle = $state<WindowHandle>();
5347
+
5348
+ $effect(() => {
5349
+ if (!handle) {
5350
+ return;
5351
+ }
5352
+
5353
+ return useDialogWindow(handle);
5354
+ });
5355
+
5356
+ async function remove() {
5357
+ const isSure = await confirm("Delete this file?");
5358
+ if (isSure) {
5359
+ await alert("Deleted");
5360
+ }
5361
+ }
5362
+ </script>
5363
+ ```
5364
+
5365
+ - Decision: they return promises, where the browser's block, because a
5366
+ `ContentDialog` is asynchronous and the thread that would block is the one
5367
+ that pumps the window, so a blocking version would freeze the dialog it
5368
+ waits for; the web names are kept, so that a library written for a browser still calls them,
5369
+ and the result is awaited: `await confirm(text)`. The other way (new names
5370
+ and no globals) would make every such library need a patch; the cost of this
5371
+ way is that `if (confirm(text))` is always true, because a promise is
5372
+ truthy, and `lib.dom` still types the globals as synchronous; in your own
5373
+ code call `showAlert`, `showConfirm` and `showPrompt` (the same functions,
5374
+ typed as promises) and leave the globals to libraries
5375
+ - `alert(message)` resolves when the dialog closes, `confirm(message)`
5376
+ resolves `true` for OK, `prompt(message, default)` resolves with the text or
5377
+ `null` for Cancel, Escape or the close button; a message that is not a
5378
+ string is shown as `String(message)`
5379
+ - `showDialog({ content, title, primaryButtonText, secondaryButtonText,
5380
+ closeButtonText, defaultButton, input, signal })` is the WinUI form: three
5381
+ buttons, the button Enter presses (`DialogButton`), a text box
5382
+ (`{ value, placeholder, isMultiline }`) and an `AbortSignal` that closes the
5383
+ dialog like Escape; it resolves with `{ result, text }`, where `result` is a
5384
+ `DialogResult` (`primary`, `secondary` or `none`) and `text` is the box when
5385
+ the primary button closed a dialog that had one
5386
+ - Which window: `useDialogWindow(handle)` takes the handle `bind:handle`
5387
+ gives, for each window; the dialog opens in the one activated last, and the
5388
+ function it returns stops following the window
5389
+ - One at a time: WinUI shows one `ContentDialog` per window, so a dialog asked
5390
+ for while another is open waits, in order, in the same line the
5391
+ `ContentDialog` components use; a dialog that fails does not hold the line,
5392
+ and an aborted one that still waits is rejected with an `AbortError`
5393
+ - No window: `alert` and `confirm` show a message box (`showNotice`, with the
5394
+ installed `title`), and `prompt` and `showDialog` reject with an
5395
+ `InvalidStateError`, because a message box has no text box and no third
5396
+ button
5397
+ - `installDialogs({ title, okText, cancelText })` sets the title and the
5398
+ button texts (English by default; WinUI does not translate them)
5399
+ - Not covered: a dialog that blocks the caller, and the prompt of
5400
+ `beforeunload`
5401
+
3907
5402
  ### Media devices (`winui-svelte/web-apis/media-devices`)
3908
5403
 
3909
5404
  `installMediaDevices()` defines `navigator.mediaDevices` (`enumerateDevices`,
@@ -4250,6 +5745,42 @@ anywhere on the screen
4250
5745
  - `ScreenPicker` is the one interface the polling picker (`windowsScreenPicker`)
4251
5746
  and the tests implement
4252
5747
 
5748
+ #### Images (`winui-svelte/web-apis/images`)
5749
+
5750
+ `installImageCodecs()` defines `createImageBitmap`, `ImageBitmap` and
5751
+ `ImageDecoder`, and adds `toBlob`, `convertToBlob` and `toDataURL` to
5752
+ `CanvasElement`; all of it runs on `Windows.Graphics.Imaging`, which needs no
5753
+ window and no package identity
5754
+
5755
+ - `createImageBitmap(source, options?)` and `createImageBitmap(source, sx, sy,
5756
+ sw, sh, options?)` take a `Blob`, `File` or `NativeFile` of an image file,
5757
+ `ImageData`, an `ImageBitmap` or a canvas; `imageOrientation` (`from-image`,
5758
+ `none`, `flipY`), `resizeWidth`, `resizeHeight` and `resizeQuality` work;
5759
+ `premultiplyAlpha` and `colorSpaceConversion` are read and ignored (images are
5760
+ color managed to sRGB); a file Windows cannot decode rejects with
5761
+ `InvalidStateError`
5762
+ - `ImageBitmap` has `width`, `height` and `close()`; `drawImage` and
5763
+ `createPattern` take it; extra: `toImageData()` (RGBA, not premultiplied)
5764
+ - `new ImageDecoder({ data, type })` takes bytes or a stream; `tracks` (an
5765
+ `ImageTrackList` of one `ImageTrack`), `complete`, `completed`, `decode({ frameIndex })`, `reset()`,
5766
+ `close()` and `ImageDecoder.isTypeSupported(type)`; `image` is an
5767
+ `ImageBitmap`, not a `VideoFrame`, and `duration` is not reported; a GIF
5768
+ frame is what the file stores, so an optimized GIF gives the changed area
5769
+ - Decoders: BMP, GIF, ICO, JPEG, PNG, TIFF, JPEG XR, and WebP, AVIF and HEIC
5770
+ where Windows has the codec; `isTypeSupported` asks Windows' own list
5771
+ - Encoders: PNG, JPEG (`quality` 0 to 1 is `ImageQuality`, 0.92 by default;
5772
+ transparency is drawn over black), GIF, BMP and TIFF; WebP has no Windows
5773
+ encoder, so `toBlob`, `convertToBlob` and `toDataURLAsync` give a PNG for
5774
+ `image/webp` and for any type Windows cannot write, as the platform does
5775
+ - `toDataURL(type, quality)` is synchronous and every Windows encoder is
5776
+ asynchronous, so it always returns a PNG; extra: `toDataURLAsync(type,
5777
+ quality)` encodes any type above
5778
+ - A canvas with no pixels gives `data:,`, `null` from `toBlob` and rejects
5779
+ `convertToBlob`
5780
+ - `ImageCodec` is the one interface the Windows codec (`windowsImageCodec`)
5781
+ and the tests implement; `ImageMimeType`, `ImageOrientation` and
5782
+ `ResizeQuality` are in `winui-svelte/enums`
5783
+
4253
5784
  #### Contacts (`winui-svelte/web-apis/contacts`)
4254
5785
 
4255
5786
  `installContacts()` defines `navigator.contacts` (a `ContactsManager`) with
@@ -4714,7 +6245,7 @@ and resets the context, as in a browser), `getContext("2d")` (the same
4714
6245
  `display` and any other property, with `setProperty`), `getBoundingClientRect()`,
4715
6246
  `clientWidth`, `clientHeight`, `offsetWidth`, `offsetHeight`, `addEventListener`,
4716
6247
  `removeEventListener` and `dispatchEvent`
4717
- It has no document: there is no `ownerDocument` and no `toDataURL`, and
6248
+ It has no document: there is no `ownerDocument`, and `toDataURL` and `toBlob` exist only after `installImageCodecs()`, and
4718
6249
  `parentNode` is `null`
4719
6250
 
4720
6251
  Pointer events of the control reach the canvas as DOM events: `pointerdown`,
@@ -4785,8 +6316,8 @@ Not tried: the events need a real pointer, which a test must not inject
4785
6316
  | `globalCompositeOperation` of `multiply`, `screen`, `overlay`, `darken`, `lighten`, `color-dodge`, `color-burn`, `hard-light`, `soft-light`, `difference`, `exclusion`, `hue`, `saturation`, `color`, `luminosity` | Win2D blends an effect's inputs, not a shape with the canvas; the value is ignored |
4786
6317
  | `filter` | it is always `none`; use a Win2D effect on the image |
4787
6318
  | `letterSpacing`, `wordSpacing`, `fontKerning`, `fontStretch`, `fontVariantCaps`, `textRendering` | No Win2D equivalent set per draw call |
4788
- | `drawImage` of an `HTMLImageElement`, `ImageBitmap`, `HTMLVideoElement` or `OffscreenCanvas` | There is no DOM; decode with `loadBitmap`, or draw another `CanvasElement` |
4789
- | `toDataURL`, `toBlob`, `transferControlToOffscreen`, `captureStream` | No encoder is exposed on the canvas; `canvas.target.saveAsync` writes a PNG or JPEG file |
6319
+ | `drawImage` of an `HTMLImageElement`, `HTMLVideoElement` or `OffscreenCanvas` | There is no DOM; decode with `loadBitmap`, or draw another `CanvasElement`; an `ImageBitmap` from `winui-svelte/web-apis/images` draws |
6320
+ | `transferControlToOffscreen`, `captureStream` | There is no `OffscreenCanvas` or media stream; `toBlob`, `convertToBlob` and `toDataURL` come with `winui-svelte/web-apis/images` |
4790
6321
  | `getContext` of `webgl`, `webgl2`, `bitmaprenderer`; the `alpha`, `desynchronized` and `willReadFrequently` options | One 2D context, always with an alpha channel |
4791
6322
  | `scrollPathIntoView` | There is no element tree to scroll; the method is absent |
4792
6323
  | `requestAnimationFrame`, `devicePixelRatio`, `document`, `window` | Globals of a browser, defined by the opt-in `winui-svelte/web-apis/timing`, `/screen` and `/page`; `getComputedStyle` has no counterpart |