@legendapp/spark 0.0.1-next.2 → 0.0.1-next.4

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 (422) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +10 -4
  3. package/ai-codex.ts +1 -0
  4. package/ai.ts +1 -0
  5. package/app-documents.ts +1 -0
  6. package/camera.ts +13 -0
  7. package/config-plugin.d.cts +2 -0
  8. package/contracts.ts +2 -0
  9. package/diagnostics.ts +1 -0
  10. package/expo-config.d.cts +1 -0
  11. package/metro.cjs +4 -1
  12. package/metro.d.cts +12 -0
  13. package/native.cjs +3 -1
  14. package/native.d.cts +6 -0
  15. package/package.json +93 -15
  16. package/patches/camera/react-native-nitro-image.patch +320 -0
  17. package/patches/camera/react-native-nitro-modules.patch +50 -0
  18. package/patches/camera/react-native-vision-camera.patch +2662 -0
  19. package/patches/camera/upstream.json +22 -0
  20. package/patches/dependencies.json +8 -0
  21. package/patches/react-native-enriched-markdown@1.0.2.patch +8684 -0
  22. package/postinstall.cjs +1 -0
  23. package/schema.json +276 -58
  24. package/settings-observable.ts +1 -0
  25. package/settings-window.ts +1 -0
  26. package/shortcuts-commands.ts +1 -0
  27. package/shortcuts-keyboard.ts +3 -0
  28. package/ui-classnames.ts +1 -0
  29. package/ui-glass.ts +1 -0
  30. package/ui-search.ts +1 -0
  31. package/ui-sidebar.ts +1 -0
  32. package/ui-split-view.ts +1 -0
  33. package/ui-swipe.ts +1 -0
  34. package/ui-symbol.ts +1 -0
  35. package/vendor/node_modules/@legendapp/spark-ai/package.json +19 -0
  36. package/vendor/node_modules/@legendapp/spark-ai/src/availability.ts +17 -0
  37. package/vendor/node_modules/@legendapp/spark-ai/src/index.ts +15 -0
  38. package/vendor/node_modules/@legendapp/spark-ai/src/invocations.ts +34 -0
  39. package/vendor/node_modules/@legendapp/spark-ai/src/output.ts +62 -0
  40. package/vendor/node_modules/@legendapp/spark-ai/src/run.ts +12 -0
  41. package/vendor/node_modules/@legendapp/spark-ai/src/types.ts +16 -0
  42. package/vendor/node_modules/@legendapp/spark-audio/macos/RNSparkAudio.h +2 -1
  43. package/vendor/node_modules/@legendapp/spark-audio/macos/RNSparkAudio.mm +126 -24
  44. package/vendor/node_modules/@legendapp/spark-audio/package.json +5 -2
  45. package/vendor/node_modules/@legendapp/spark-audio/src/NativeSparkAudio.ts +5 -1
  46. package/vendor/node_modules/@legendapp/spark-audio/src/desktop.ts +36 -32
  47. package/vendor/node_modules/@legendapp/spark-audio/src/events.ts +11 -0
  48. package/vendor/node_modules/@legendapp/spark-audio/src/hooks.ts +65 -0
  49. package/vendor/node_modules/@legendapp/spark-audio/src/index.web.ts +92 -33
  50. package/vendor/node_modules/@legendapp/spark-audio/src/media-session-unavailable.ts +6 -4
  51. package/vendor/node_modules/@legendapp/spark-audio/src/media-session.ts +52 -19
  52. package/vendor/node_modules/@legendapp/spark-audio/src/media-session.web.ts +18 -10
  53. package/vendor/node_modules/@legendapp/spark-audio/src/media-types.ts +40 -13
  54. package/vendor/node_modules/@legendapp/spark-audio/src/mobile.ts +40 -32
  55. package/vendor/node_modules/@legendapp/spark-audio/src/player.ts +97 -0
  56. package/vendor/node_modules/@legendapp/spark-audio/src/status-listeners.ts +21 -15
  57. package/vendor/node_modules/@legendapp/spark-audio/src/types.ts +9 -4
  58. package/vendor/node_modules/@legendapp/spark-audio/windows/SparkAudio/SparkAudio.h +67 -20
  59. package/vendor/node_modules/@legendapp/spark-auth-session/package.json +4 -3
  60. package/vendor/node_modules/@legendapp/spark-auth-session/src/core.ts +60 -42
  61. package/vendor/node_modules/@legendapp/spark-auth-session/src/index.ts +28 -12
  62. package/vendor/node_modules/@legendapp/spark-auth-session/src/mobile.ts +97 -41
  63. package/vendor/node_modules/@legendapp/spark-auth-session/src/types.ts +20 -9
  64. package/vendor/node_modules/@legendapp/spark-cli/dist/add-desktop.js +50 -7
  65. package/vendor/node_modules/@legendapp/spark-cli/dist/build-mode.js +1 -1
  66. package/vendor/node_modules/@legendapp/spark-cli/dist/build.js +145 -59
  67. package/vendor/node_modules/@legendapp/spark-cli/dist/cli-arguments.js +61 -0
  68. package/vendor/node_modules/@legendapp/spark-cli/dist/commands.js +10 -4
  69. package/vendor/node_modules/@legendapp/spark-cli/dist/create.js +37 -8
  70. package/vendor/node_modules/@legendapp/spark-cli/dist/credentials.js +86 -25
  71. package/vendor/node_modules/@legendapp/spark-cli/dist/dependency-pins.js +132 -0
  72. package/vendor/node_modules/@legendapp/spark-cli/dist/dev-command.js +13 -4
  73. package/vendor/node_modules/@legendapp/spark-cli/dist/dev.js +13 -10
  74. package/vendor/node_modules/@legendapp/spark-cli/dist/errors.js +100 -0
  75. package/vendor/node_modules/@legendapp/spark-cli/dist/examples.js +2 -2
  76. package/vendor/node_modules/@legendapp/spark-cli/dist/expo-dev-patch.cjs +4 -2
  77. package/vendor/node_modules/@legendapp/spark-cli/dist/expo-metro.cjs +1 -1
  78. package/vendor/node_modules/@legendapp/spark-cli/dist/expo-native.cjs +5 -1
  79. package/vendor/node_modules/@legendapp/spark-cli/dist/expo-node.js +3 -3
  80. package/vendor/node_modules/@legendapp/spark-cli/dist/helpers.js +1 -1
  81. package/vendor/node_modules/@legendapp/spark-cli/dist/index.js +52 -44
  82. package/vendor/node_modules/@legendapp/spark-cli/dist/json.js +16 -0
  83. package/vendor/node_modules/@legendapp/spark-cli/dist/local.js +1 -1
  84. package/vendor/node_modules/@legendapp/spark-cli/dist/metro.cjs +26 -5
  85. package/vendor/node_modules/@legendapp/spark-cli/dist/native-metadata.js +26 -0
  86. package/vendor/node_modules/@legendapp/spark-cli/dist/native-patch-preflight.js +86 -0
  87. package/vendor/node_modules/@legendapp/spark-cli/dist/native-preparation.js +88 -0
  88. package/vendor/node_modules/@legendapp/spark-cli/dist/notary-profiles.js +75 -0
  89. package/vendor/node_modules/@legendapp/spark-cli/dist/package.js +4 -2
  90. package/vendor/node_modules/@legendapp/spark-cli/dist/platform.js +16 -2
  91. package/vendor/node_modules/@legendapp/spark-cli/dist/process.js +7 -0
  92. package/vendor/node_modules/@legendapp/spark-cli/dist/project.js +90 -32
  93. package/vendor/node_modules/@legendapp/spark-cli/dist/release.js +86 -5
  94. package/vendor/node_modules/@legendapp/spark-cli/dist/release.json +23 -18
  95. package/vendor/node_modules/@legendapp/spark-cli/dist/runner-install.js +145 -31
  96. package/vendor/node_modules/@legendapp/spark-cli/dist/signing.js +4 -3
  97. package/vendor/node_modules/@legendapp/spark-cli/dist/universal.cjs +2 -1
  98. package/vendor/node_modules/@legendapp/spark-cli/dist/updates.js +41 -4
  99. package/vendor/node_modules/@legendapp/spark-cli/dist/windows.js +5 -9
  100. package/vendor/node_modules/@legendapp/spark-cli/package.json +7 -6
  101. package/vendor/node_modules/@legendapp/spark-cli/templates/blank-typescript/App.tsx +6 -12
  102. package/vendor/node_modules/@legendapp/spark-cli/templates/blank-typescript/desktop.config.json +5 -3
  103. package/vendor/node_modules/@legendapp/spark-cli/templates/blank-typescript/package.json +12 -10
  104. package/vendor/node_modules/@legendapp/spark-cli/templates/diff-lite/Git.macos.tsx +2 -2
  105. package/vendor/node_modules/@legendapp/spark-cli/templates/document-editor/Integration.macos.tsx +23 -21
  106. package/vendor/node_modules/@legendapp/spark-cli/templates/document-editor/Integration.windows.tsx +23 -21
  107. package/vendor/node_modules/@legendapp/spark-cli/templates/document-editor/io.desktop.ts +11 -8
  108. package/vendor/node_modules/@legendapp/spark-cli/templates/document-editor/io.macos.ts +3 -3
  109. package/vendor/node_modules/@legendapp/spark-cli/templates/example-shared/Lifecycle.desktop.tsx +8 -14
  110. package/vendor/node_modules/@legendapp/spark-cli/templates/example-shared/OpenFiles.desktop.tsx +5 -10
  111. package/vendor/node_modules/@legendapp/spark-cli/templates/example-shared/io.desktop.ts +11 -8
  112. package/vendor/node_modules/@legendapp/spark-cli/templates/example-shared/io.macos.ts +3 -3
  113. package/vendor/node_modules/@legendapp/spark-cli/templates/music-lite/assets.desktop.ts +2 -2
  114. package/vendor/node_modules/@legendapp/spark-cli/templates/notes-lite/Activation.desktop.tsx +2 -2
  115. package/vendor/node_modules/@legendapp/spark-cli/templates/notes-lite/Desktop.desktop.ts +37 -15
  116. package/vendor/node_modules/@legendapp/spark-cli/templates/notes-lite/session.ts +5 -6
  117. package/vendor/node_modules/@legendapp/spark-cli/templates/notes-lite/window-session.ts +5 -4
  118. package/vendor/node_modules/@legendapp/spark-cli/templates/universal/desktop.config.json +5 -3
  119. package/vendor/node_modules/@legendapp/spark-cli/templates/universal/metro.config.js +1 -1
  120. package/vendor/node_modules/@legendapp/spark-cli/templates/universal/package.json +14 -12
  121. package/vendor/node_modules/@legendapp/spark-cli/templates/universal/react-native.config.js +1 -1
  122. package/vendor/node_modules/@legendapp/spark-cli/templates/windows/package.json +14 -12
  123. package/vendor/node_modules/@legendapp/spark-cli/templates/windows/react-native.config.js +1 -1
  124. package/vendor/node_modules/@legendapp/spark-clipboard/macos/RNDesktopClipboard.mm +10 -16
  125. package/vendor/node_modules/@legendapp/spark-clipboard/package.json +2 -2
  126. package/vendor/node_modules/@legendapp/spark-clipboard/src/NativeDesktopClipboard.ts +1 -1
  127. package/vendor/node_modules/@legendapp/spark-clipboard/src/desktop.ts +55 -31
  128. package/vendor/node_modules/@legendapp/spark-clipboard/src/expo.ts +21 -11
  129. package/vendor/node_modules/@legendapp/spark-clipboard/src/options.ts +8 -0
  130. package/vendor/node_modules/@legendapp/spark-clipboard/src/types.ts +10 -0
  131. package/vendor/node_modules/@legendapp/spark-clipboard/windows/SparkClipboard/SparkClipboard.h +38 -15
  132. package/vendor/node_modules/@legendapp/spark-clipboard/windows/SparkClipboard/SparkClipboard.vcxproj +2 -0
  133. package/vendor/node_modules/@legendapp/spark-codex/RNCodex.podspec +22 -0
  134. package/vendor/node_modules/@legendapp/spark-codex/cpp/HybridCodexAppServer.hpp +23 -0
  135. package/vendor/node_modules/@legendapp/spark-codex/cpp/HybridCodexAppServer.mm +1529 -0
  136. package/vendor/node_modules/@legendapp/spark-codex/nitro.json +21 -0
  137. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/.gitattributes +1 -0
  138. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/ios/RNCodex+autolinking.rb +62 -0
  139. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/ios/RNCodex-Swift-Cxx-Bridge.cpp +17 -0
  140. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/ios/RNCodex-Swift-Cxx-Bridge.hpp +27 -0
  141. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/ios/RNCodex-Swift-Cxx-Umbrella.hpp +38 -0
  142. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/ios/RNCodexAutolinking.mm +35 -0
  143. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/ios/RNCodexAutolinking.swift +16 -0
  144. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/shared/c++/CodexAvailability.hpp +95 -0
  145. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/shared/c++/CodexRunResult.hpp +99 -0
  146. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/shared/c++/HybridCodexAppServerSpec.cpp +24 -0
  147. package/vendor/node_modules/@legendapp/spark-codex/nitrogen/generated/shared/c++/HybridCodexAppServerSpec.hpp +71 -0
  148. package/vendor/node_modules/@legendapp/spark-codex/package.json +35 -0
  149. package/vendor/node_modules/@legendapp/spark-codex/react-native.config.js +11 -0
  150. package/vendor/node_modules/@legendapp/spark-codex/src/Codex.nitro.ts +30 -0
  151. package/vendor/node_modules/@legendapp/spark-codex/src/index.ts +65 -0
  152. package/vendor/node_modules/@legendapp/spark-codex/src/native.ts +6 -0
  153. package/vendor/node_modules/@legendapp/spark-commands/package.json +21 -0
  154. package/vendor/node_modules/@legendapp/spark-commands/src/bindings.ts +90 -0
  155. package/vendor/node_modules/@legendapp/spark-commands/src/index.tsx +400 -0
  156. package/vendor/node_modules/@legendapp/spark-commands/src/router.ts +138 -0
  157. package/vendor/node_modules/@legendapp/spark-commands/src/storage.ts +20 -0
  158. package/vendor/node_modules/@legendapp/spark-context-menu/macos/RNContextMenu.mm +7 -8
  159. package/vendor/node_modules/@legendapp/spark-context-menu/package.json +4 -3
  160. package/vendor/node_modules/@legendapp/spark-context-menu/src/NativeContextMenu.ts +1 -1
  161. package/vendor/node_modules/@legendapp/spark-context-menu/src/index.ts +26 -26
  162. package/vendor/node_modules/@legendapp/spark-context-menu/windows/SparkContextMenu/SparkContextMenu.h +3 -2
  163. package/vendor/node_modules/@legendapp/spark-desktop-app/RNDesktopApp.podspec +2 -1
  164. package/vendor/node_modules/@legendapp/spark-desktop-app/cpp/SparkBinaryJSI.hpp +89 -0
  165. package/vendor/node_modules/@legendapp/spark-desktop-app/cpp/SparkBinaryWindows.hpp +22 -0
  166. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/RNDesktopApp.mm +13 -7
  167. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkBinaryJSI.h +48 -0
  168. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkDesktop.h +4 -0
  169. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkDesktop.mm +33 -33
  170. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkDesktopError.h +20 -0
  171. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkLifecycle.h +26 -0
  172. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkLifecycle.mm +49 -0
  173. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkQuitCoordinator.h +9 -0
  174. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkQuitCoordinator.mm +70 -0
  175. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/SparkWindow.mm +9 -6
  176. package/vendor/node_modules/@legendapp/spark-desktop-app/macos/recent-documents/RNRecentDocumentController.mm +55 -0
  177. package/vendor/node_modules/@legendapp/spark-desktop-app/package.json +5 -3
  178. package/vendor/node_modules/@legendapp/spark-desktop-app/src/NativeDesktopApp.ts +1 -1
  179. package/vendor/node_modules/@legendapp/spark-desktop-app/src/api.ts +86 -40
  180. package/vendor/node_modules/@legendapp/spark-desktop-app/src/contracts/accelerator.ts +40 -0
  181. package/vendor/node_modules/@legendapp/spark-desktop-app/src/contracts/index.ts +56 -0
  182. package/vendor/node_modules/@legendapp/spark-desktop-app/src/contracts/menu.ts +116 -0
  183. package/vendor/node_modules/@legendapp/spark-desktop-app/src/contracts/native-buffer.ts +22 -0
  184. package/vendor/node_modules/@legendapp/spark-desktop-app/src/contracts/path.ts +24 -0
  185. package/vendor/node_modules/@legendapp/spark-desktop-app/src/events.ts +75 -0
  186. package/vendor/node_modules/@legendapp/spark-desktop-app/src/index.ts +2 -0
  187. package/vendor/node_modules/@legendapp/spark-desktop-app/src/index.windows.ts +2 -0
  188. package/vendor/node_modules/@legendapp/spark-desktop-app/src/open-requests.ts +43 -0
  189. package/vendor/node_modules/@legendapp/spark-desktop-app/src/restoration.ts +11 -0
  190. package/vendor/node_modules/@legendapp/spark-desktop-app/src/transport.ts +10 -0
  191. package/vendor/node_modules/@legendapp/spark-desktop-config/app.plugin.cjs +10 -5
  192. package/vendor/node_modules/@legendapp/spark-desktop-config/app.plugin.d.cts +3 -0
  193. package/vendor/node_modules/@legendapp/spark-desktop-config/autolinking.cjs +35 -0
  194. package/vendor/node_modules/@legendapp/spark-desktop-config/config.cjs +18 -3
  195. package/vendor/node_modules/@legendapp/spark-desktop-config/config.d.cts +89 -9
  196. package/vendor/node_modules/@legendapp/spark-desktop-config/expo.cjs +1 -0
  197. package/vendor/node_modules/@legendapp/spark-desktop-config/expo.d.cts +3 -0
  198. package/vendor/node_modules/@legendapp/spark-desktop-config/identity.cjs +3 -2
  199. package/vendor/node_modules/@legendapp/spark-desktop-config/lifecycle.cjs +20 -0
  200. package/vendor/node_modules/@legendapp/spark-desktop-config/native-patches.cjs +106 -0
  201. package/vendor/node_modules/@legendapp/spark-desktop-config/native-patches.d.cts +1 -0
  202. package/vendor/node_modules/@legendapp/spark-desktop-config/package.json +7 -5
  203. package/vendor/node_modules/@legendapp/spark-desktop-config/schema.json +276 -58
  204. package/vendor/node_modules/@legendapp/spark-desktop-config/updates.cjs +1 -0
  205. package/vendor/node_modules/@legendapp/spark-desktop-config/validation.cjs +35 -0
  206. package/vendor/node_modules/@legendapp/spark-desktop-config/windows.plugin.cjs +2 -1
  207. package/vendor/node_modules/@legendapp/spark-desktop-host/AppDelegate.mm +129 -11
  208. package/vendor/node_modules/@legendapp/spark-desktop-host/package.json +2 -2
  209. package/vendor/node_modules/@legendapp/spark-desktop-host/windows/application.inc +277 -121
  210. package/vendor/node_modules/@legendapp/spark-desktop-links/common/AuthLoopback.h +5 -7
  211. package/vendor/node_modules/@legendapp/spark-desktop-links/macos/RNDesktopLinks.mm +10 -9
  212. package/vendor/node_modules/@legendapp/spark-desktop-links/package.json +2 -2
  213. package/vendor/node_modules/@legendapp/spark-desktop-links/src/NativeDesktopLinks.ts +1 -1
  214. package/vendor/node_modules/@legendapp/spark-desktop-links/src/api.ts +27 -33
  215. package/vendor/node_modules/@legendapp/spark-desktop-links/src/expo.ts +3 -4
  216. package/vendor/node_modules/@legendapp/spark-desktop-links/src/native.ts +9 -0
  217. package/vendor/node_modules/@legendapp/spark-desktop-links/windows/SparkLinks/SparkLinks.h +22 -22
  218. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/RNDesktopShortcuts.podspec +1 -0
  219. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/macos/RNDesktopShortcuts.mm +1 -1
  220. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/macos/keyboard-manager/RNKeyboardManager.h +9 -0
  221. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/macos/keyboard-manager/RNKeyboardManager.mm +307 -0
  222. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/package.json +8 -5
  223. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/src/NativeDesktopShortcuts.ts +1 -1
  224. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/src/api.ts +39 -14
  225. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/src/keyboard-manager/NativeKeyboardManager.ts +12 -0
  226. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/src/keyboard-manager/codes.ts +108 -0
  227. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/src/keyboard-manager/index.ts +99 -0
  228. package/vendor/node_modules/@legendapp/spark-desktop-windows/RNDesktopWindows.podspec +2 -0
  229. package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/RNDesktopWindows.mm +229 -103
  230. package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/SparkWindowGeometry.h +63 -0
  231. package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/window-manager/LegendWindowRegistry.h +20 -0
  232. package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/window-manager/LegendWindowRegistry.mm +27 -0
  233. package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/window-manager/RNWindowManager.h +12 -0
  234. package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/window-manager/RNWindowManager.mm +3169 -0
  235. package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/window-manager/RNWindowManagerStartup.mm +31 -0
  236. package/vendor/node_modules/@legendapp/spark-desktop-windows/macos/window-manager/SidebarStartupFallbacks.mm +14 -0
  237. package/vendor/node_modules/@legendapp/spark-desktop-windows/package.json +10 -6
  238. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/NativeDesktopWindowManager.ts +1 -1
  239. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/api.ts +146 -70
  240. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/diagnostics.ts +17 -0
  241. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/index.ts +3 -1
  242. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/index.windows.ts +3 -1
  243. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/macos-adapter.ts +53 -0
  244. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/macos.ts +51 -0
  245. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/transport.ts +41 -0
  246. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/types.ts +140 -0
  247. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/validation.ts +162 -0
  248. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/window-manager/NativeWindowManager.ts +28 -0
  249. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/WindowProvider.tsx +20 -0
  250. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/createWindowsNavigator.tsx +78 -0
  251. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/index.ts +6 -0
  252. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/primaryWindowLifecycle.ts +34 -0
  253. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/types.ts +11 -0
  254. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/usePrimaryWindowLifecycle.ts +18 -0
  255. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows/useWindowFocusEffect.ts +17 -0
  256. package/vendor/node_modules/@legendapp/spark-documents/package.json +22 -0
  257. package/vendor/node_modules/@legendapp/spark-documents/src/controller.ts +97 -0
  258. package/vendor/node_modules/@legendapp/spark-documents/src/documentTransition.ts +13 -0
  259. package/vendor/node_modules/@legendapp/spark-documents/src/hooks.ts +139 -0
  260. package/vendor/node_modules/@legendapp/spark-documents/src/index.tsx +50 -0
  261. package/vendor/node_modules/@legendapp/spark-documents/src/reload.ts +39 -0
  262. package/vendor/node_modules/@legendapp/spark-documents/src/requests.ts +15 -0
  263. package/vendor/node_modules/@legendapp/spark-drag-drop/package.json +4 -3
  264. package/vendor/node_modules/@legendapp/spark-drag-drop/src/DesktopDragViewNativeComponent.ts +1 -1
  265. package/vendor/node_modules/@legendapp/spark-drag-drop/src/contracts.ts +73 -18
  266. package/vendor/node_modules/@legendapp/spark-drag-drop/src/index.tsx +58 -15
  267. package/vendor/node_modules/@legendapp/spark-drag-drop/windows/SparkDragDrop/SparkDragDrop.h +14 -8
  268. package/vendor/node_modules/@legendapp/spark-file-dialog/ios/RNFileDialog.mm +34 -121
  269. package/vendor/node_modules/@legendapp/spark-file-dialog/package.json +12 -5
  270. package/vendor/node_modules/@legendapp/spark-file-dialog/src/NativeFileDialog.ts +1 -5
  271. package/vendor/node_modules/@legendapp/spark-file-dialog/src/index.ts +19 -84
  272. package/vendor/node_modules/@legendapp/spark-file-dialog/src/native.ts +12 -0
  273. package/vendor/node_modules/@legendapp/spark-file-dialog/src/options.ts +34 -14
  274. package/vendor/node_modules/@legendapp/spark-file-dialog/src/types.ts +26 -0
  275. package/vendor/node_modules/@legendapp/spark-file-dialog/windows/SparkFileDialog/SparkFileDialog.h +42 -58
  276. package/vendor/node_modules/@legendapp/spark-file-system/RNDesktopFileSystem.podspec +1 -0
  277. package/vendor/node_modules/@legendapp/spark-file-system/macos/RNDesktopFileSystem.mm +32 -21
  278. package/vendor/node_modules/@legendapp/spark-file-system/macos/SparkFileMutations.h +24 -0
  279. package/vendor/node_modules/@legendapp/spark-file-system/macos/SparkFileMutations.mm +215 -0
  280. package/vendor/node_modules/@legendapp/spark-file-system/macos/file-scanner/RNFileScanner.h +9 -0
  281. package/vendor/node_modules/@legendapp/spark-file-system/macos/file-scanner/RNFileScanner.mm +82 -0
  282. package/vendor/node_modules/@legendapp/spark-file-system/macos/file-scanner/RNFileScannerCore.h +47 -0
  283. package/vendor/node_modules/@legendapp/spark-file-system/macos/file-scanner/RNFileScannerCore.mm +306 -0
  284. package/vendor/node_modules/@legendapp/spark-file-system/package.json +8 -6
  285. package/vendor/node_modules/@legendapp/spark-file-system/src/NativeDesktopFileSystem.ts +1 -1
  286. package/vendor/node_modules/@legendapp/spark-file-system/src/file-scanner/NativeFileScanner.ts +11 -0
  287. package/vendor/node_modules/@legendapp/spark-file-system/src/file-scanner/index.ts +93 -0
  288. package/vendor/node_modules/@legendapp/spark-file-system/src/handles.ts +48 -14
  289. package/vendor/node_modules/@legendapp/spark-file-system/src/index.ts +134 -45
  290. package/vendor/node_modules/@legendapp/spark-file-system/src/path.ts +1 -9
  291. package/vendor/node_modules/@legendapp/spark-file-system/windows/SparkFileSystem/SparkFileSystem.h +102 -26
  292. package/vendor/node_modules/@legendapp/spark-file-system/windows/SparkFileSystem/SparkFileSystem.vcxproj +2 -0
  293. package/vendor/node_modules/@legendapp/spark-global-shortcuts/RNDesktopGlobalShortcuts.podspec +1 -0
  294. package/vendor/node_modules/@legendapp/spark-global-shortcuts/macos/RNDesktopGlobalShortcuts.mm +7 -4
  295. package/vendor/node_modules/@legendapp/spark-global-shortcuts/package.json +4 -3
  296. package/vendor/node_modules/@legendapp/spark-global-shortcuts/src/NativeDesktopGlobalShortcuts.ts +1 -1
  297. package/vendor/node_modules/@legendapp/spark-global-shortcuts/src/index.ts +39 -10
  298. package/vendor/node_modules/@legendapp/spark-global-shortcuts/windows/SparkGlobalShortcuts/SparkGlobalShortcuts.h +5 -4
  299. package/vendor/node_modules/@legendapp/spark-message-dialog/macos/RNDesktopMessageDialog.mm +2 -2
  300. package/vendor/node_modules/@legendapp/spark-message-dialog/package.json +2 -2
  301. package/vendor/node_modules/@legendapp/spark-message-dialog/src/NativeDesktopMessageDialog.ts +1 -1
  302. package/vendor/node_modules/@legendapp/spark-message-dialog/src/index.ts +48 -11
  303. package/vendor/node_modules/@legendapp/spark-native-menu/ios/RNNativeMenu.mm +141 -609
  304. package/vendor/node_modules/@legendapp/spark-native-menu/package.json +9 -4
  305. package/vendor/node_modules/@legendapp/spark-native-menu/src/NativeMenu.ts +2 -7
  306. package/vendor/node_modules/@legendapp/spark-native-menu/src/api.ts +76 -121
  307. package/vendor/node_modules/@legendapp/spark-native-menu/src/hooks.ts +97 -0
  308. package/vendor/node_modules/@legendapp/spark-native-menu/src/windows-menus.ts +43 -37
  309. package/vendor/node_modules/@legendapp/spark-notifications/macos/RNDesktopNotifications.mm +75 -30
  310. package/vendor/node_modules/@legendapp/spark-notifications/package.json +2 -2
  311. package/vendor/node_modules/@legendapp/spark-notifications/src/NativeDesktopNotifications.ts +1 -1
  312. package/vendor/node_modules/@legendapp/spark-notifications/src/index.ts +130 -42
  313. package/vendor/node_modules/@legendapp/spark-notifications/windows/SparkNotifications/SparkNotifications.h +51 -8
  314. package/vendor/node_modules/@legendapp/spark-processes/macos/RNDesktopProcesses.mm +94 -21
  315. package/vendor/node_modules/@legendapp/spark-processes/package.json +4 -3
  316. package/vendor/node_modules/@legendapp/spark-processes/src/NativeDesktopProcesses.ts +1 -1
  317. package/vendor/node_modules/@legendapp/spark-processes/src/index.ts +124 -28
  318. package/vendor/node_modules/@legendapp/spark-processes/src/types.ts +34 -0
  319. package/vendor/node_modules/@legendapp/spark-processes/windows/SparkProcesses/SparkProcesses.h +83 -34
  320. package/vendor/node_modules/@legendapp/spark-processes/windows/SparkProcesses/SparkProcesses.vcxproj +2 -0
  321. package/vendor/node_modules/@legendapp/spark-secure-storage/macos/RNDesktopSecureStorage.mm +49 -40
  322. package/vendor/node_modules/@legendapp/spark-secure-storage/package.json +2 -2
  323. package/vendor/node_modules/@legendapp/spark-secure-storage/src/NativeDesktopSecureStorage.ts +1 -1
  324. package/vendor/node_modules/@legendapp/spark-secure-storage/src/desktop.ts +16 -14
  325. package/vendor/node_modules/@legendapp/spark-secure-storage/src/expo.ts +0 -1
  326. package/vendor/node_modules/@legendapp/spark-secure-storage/src/options.ts +3 -2
  327. package/vendor/node_modules/@legendapp/spark-secure-storage/src/unavailable.ts +6 -3
  328. package/vendor/node_modules/@legendapp/spark-settings/package.json +10 -3
  329. package/vendor/node_modules/@legendapp/spark-settings/src/fileStorage.ts +11 -0
  330. package/vendor/node_modules/@legendapp/spark-settings/src/index.ts +7 -9
  331. package/vendor/node_modules/@legendapp/spark-settings/src/storage/index.ts +142 -0
  332. package/vendor/node_modules/@legendapp/spark-settings/src/store.ts +63 -21
  333. package/vendor/node_modules/@legendapp/spark-settings-ui/package.json +20 -0
  334. package/vendor/node_modules/@legendapp/spark-settings-ui/src/index.tsx +436 -0
  335. package/vendor/node_modules/@legendapp/spark-settings-ui/src/options.ts +10 -0
  336. package/vendor/node_modules/@legendapp/spark-sqlite/package.json +3 -3
  337. package/vendor/node_modules/@legendapp/spark-sqlite/src/database.ts +182 -0
  338. package/vendor/node_modules/@legendapp/spark-sqlite/src/index.ts +19 -6
  339. package/vendor/node_modules/@legendapp/spark-sqlite/src/types.ts +22 -0
  340. package/vendor/node_modules/@legendapp/spark-system/macos/RNDesktopSystem.mm +36 -11
  341. package/vendor/node_modules/@legendapp/spark-system/package.json +2 -2
  342. package/vendor/node_modules/@legendapp/spark-system/src/NativeDesktopSystem.ts +1 -1
  343. package/vendor/node_modules/@legendapp/spark-system/src/index.ts +89 -32
  344. package/vendor/node_modules/@legendapp/spark-system/windows/SparkSystem/SparkSystem.h +8 -4
  345. package/vendor/node_modules/@legendapp/spark-tray/macos/RNDesktopTray.mm +20 -8
  346. package/vendor/node_modules/@legendapp/spark-tray/package.json +2 -2
  347. package/vendor/node_modules/@legendapp/spark-tray/src/NativeDesktopTray.ts +1 -1
  348. package/vendor/node_modules/@legendapp/spark-tray/src/index.ts +91 -34
  349. package/vendor/node_modules/@legendapp/spark-tray/windows/SparkTray/SparkTray.h +45 -15
  350. package/vendor/node_modules/@legendapp/spark-ui/macos/RNSparkButton.mm +2 -1
  351. package/vendor/node_modules/@legendapp/spark-ui/macos/RNSparkTextInput.mm +10 -2
  352. package/vendor/node_modules/@legendapp/spark-ui/macos/appkit-split-view/RNSidebarSplitViewComponent.h +15 -0
  353. package/vendor/node_modules/@legendapp/spark-ui/macos/appkit-split-view/RNSidebarSplitViewComponent.mm +1419 -0
  354. package/vendor/node_modules/@legendapp/spark-ui/macos/glass-effect-view/RNGlassEffectView.mm +72 -0
  355. package/vendor/node_modules/@legendapp/spark-ui/macos/native-select/RNNativeSegmentedControl.h +15 -0
  356. package/vendor/node_modules/@legendapp/spark-ui/macos/native-select/RNNativeSegmentedControl.mm +194 -0
  357. package/vendor/node_modules/@legendapp/spark-ui/macos/native-select/RNNativeSelect.h +15 -0
  358. package/vendor/node_modules/@legendapp/spark-ui/macos/native-select/RNNativeSelect.mm +180 -0
  359. package/vendor/node_modules/@legendapp/spark-ui/macos/sf-symbol/RNSFSymbol.h +15 -0
  360. package/vendor/node_modules/@legendapp/spark-ui/macos/sf-symbol/RNSFSymbol.mm +155 -0
  361. package/vendor/node_modules/@legendapp/spark-ui/macos/sidebar/RNSidebar.h +18 -0
  362. package/vendor/node_modules/@legendapp/spark-ui/macos/sidebar/RNSidebar.mm +645 -0
  363. package/vendor/node_modules/@legendapp/spark-ui/macos/swipe-actions/RNSwipeActions.h +10 -0
  364. package/vendor/node_modules/@legendapp/spark-ui/macos/swipe-actions/RNSwipeActions.mm +422 -0
  365. package/vendor/node_modules/@legendapp/spark-ui/macos/text-input-search/RNTextInputSearch.h +15 -0
  366. package/vendor/node_modules/@legendapp/spark-ui/macos/text-input-search/RNTextInputSearch.mm +164 -0
  367. package/vendor/node_modules/@legendapp/spark-ui/package.json +17 -4
  368. package/vendor/node_modules/@legendapp/spark-ui/src/SparkSelectNativeComponent.ts +3 -1
  369. package/vendor/node_modules/@legendapp/spark-ui/src/SparkTextInputNativeComponent.ts +6 -2
  370. package/vendor/node_modules/@legendapp/spark-ui/src/appkit-split-view/SidebarSplitViewNativeComponent.ts +37 -0
  371. package/vendor/node_modules/@legendapp/spark-ui/src/appkit-split-view/index.tsx +86 -0
  372. package/vendor/node_modules/@legendapp/spark-ui/src/availability.ts +10 -0
  373. package/vendor/node_modules/@legendapp/spark-ui/src/classnames/index.ts +8 -0
  374. package/vendor/node_modules/@legendapp/spark-ui/src/control.ts +42 -0
  375. package/vendor/node_modules/@legendapp/spark-ui/src/desktop.tsx +56 -0
  376. package/vendor/node_modules/@legendapp/spark-ui/src/glass-effect-view/index.tsx +15 -0
  377. package/vendor/node_modules/@legendapp/spark-ui/src/index.android.tsx +35 -21
  378. package/vendor/node_modules/@legendapp/spark-ui/src/index.ios.tsx +55 -26
  379. package/vendor/node_modules/@legendapp/spark-ui/src/index.tsx +1 -27
  380. package/vendor/node_modules/@legendapp/spark-ui/src/index.web.tsx +45 -14
  381. package/vendor/node_modules/@legendapp/spark-ui/src/index.windows.tsx +1 -42
  382. package/vendor/node_modules/@legendapp/spark-ui/src/mobile-input.tsx +11 -0
  383. package/vendor/node_modules/@legendapp/spark-ui/src/native-select/NativeSegmentedControlNativeComponent.ts +17 -0
  384. package/vendor/node_modules/@legendapp/spark-ui/src/native-select/NativeSelectNativeComponent.ts +17 -0
  385. package/vendor/node_modules/@legendapp/spark-ui/src/select.ts +5 -3
  386. package/vendor/node_modules/@legendapp/spark-ui/src/sf-symbol/SFSymbolNativeComponent.ts +13 -0
  387. package/vendor/node_modules/@legendapp/spark-ui/src/sf-symbol/index.tsx +27 -0
  388. package/vendor/node_modules/@legendapp/spark-ui/src/sidebar/SidebarItemNativeComponent.ts +25 -0
  389. package/vendor/node_modules/@legendapp/spark-ui/src/sidebar/SidebarNativeComponent.ts +24 -0
  390. package/vendor/node_modules/@legendapp/spark-ui/src/sidebar/index.tsx +104 -0
  391. package/vendor/node_modules/@legendapp/spark-ui/src/specialized.ts +22 -0
  392. package/vendor/node_modules/@legendapp/spark-ui/src/swipe-actions/SwipeActionsNativeComponent.ts +11 -0
  393. package/vendor/node_modules/@legendapp/spark-ui/src/swipe-actions/index.tsx +41 -0
  394. package/vendor/node_modules/@legendapp/spark-ui/src/text-input-search/TextInputSearchNativeComponent.ts +33 -0
  395. package/vendor/node_modules/@legendapp/spark-ui/src/text-input-search/index.tsx +34 -0
  396. package/vendor/node_modules/@legendapp/spark-ui/src/types.ts +30 -19
  397. package/vendor/node_modules/@legendapp/spark-ui/uniwind.ts +3 -1
  398. package/vendor/node_modules/@legendapp/spark-ui/uniwind.web.ts +3 -1
  399. package/vendor/node_modules/@legendapp/spark-ui/windows/SparkUI/SparkUI.h +16 -11
  400. package/vendor/node_modules/@legendapp/spark-updates/macos/RNDesktopUpdates.mm +21 -8
  401. package/vendor/node_modules/@legendapp/spark-updates/package.json +2 -2
  402. package/vendor/node_modules/@legendapp/spark-updates/src/NativeDesktopUpdates.ts +3 -2
  403. package/vendor/node_modules/@legendapp/spark-updates/src/index.ts +71 -15
  404. package/vendor/node_modules/@legendapp/spark-webview/package.json +2 -2
  405. package/vendor/node_modules/@legendapp/spark-webview/src/WebView.tsx +11 -0
  406. package/vendor/node_modules/@legendapp/spark-webview/src/adapter.ts +55 -0
  407. package/vendor/node_modules/@legendapp/spark-webview/src/index.ts +2 -2
  408. package/vendor/node_modules/@legendapp/spark-webview/src/types.ts +32 -0
  409. package/vendor/node_modules/@legendapp/spark-webview/src/view-props.ts +28 -0
  410. package/vendor/node_modules/@legendapp/spark-window-options/index.cjs +51 -14
  411. package/vendor/node_modules/@legendapp/spark-window-options/index.d.ts +21 -8
  412. package/vendor/node_modules/@legendapp/spark-window-options/package.json +1 -1
  413. package/windows-macos.ts +1 -0
  414. package/expo-metro.cjs +0 -1
  415. package/message-dialog.ts +0 -1
  416. package/universal.cjs +0 -1
  417. package/vendor/node_modules/@legendapp/spark-desktop-shortcuts/src/accelerator.ts +0 -22
  418. package/vendor/node_modules/@legendapp/spark-desktop-windows/src/windows-options.ts +0 -11
  419. package/vendor/node_modules/@legendapp/spark-file-dialog/src/index.windows.ts +0 -15
  420. package/vendor/node_modules/@legendapp/spark-global-shortcuts/src/accelerator.ts +0 -22
  421. package/vendor/node_modules/@legendapp/spark-ui/macos/RNSparkSelect.h +0 -4
  422. package/vendor/node_modules/@legendapp/spark-ui/macos/RNSparkSelect.mm +0 -53
@@ -0,0 +1,31 @@
1
+ #import <TargetConditionals.h>
2
+ #if TARGET_OS_OSX && __has_include(<RNDesktopApp/SparkLifecycle.h>)
3
+ #import <RNDesktopApp/SparkLifecycle.h>
4
+ extern "C" void LegendPrecreateRestorableWindows(void);
5
+ extern "C" NSDictionary *LegendMainWindowStartupSplitViewConfiguration(void);
6
+ extern "C" void LegendPrepareSidebarSplitViewStartup(NSWindow *, NSDictionary *) __attribute__((weak_import));
7
+ extern "C" BOOL LegendAttachSidebarSplitViewStartupRoot(NSWindow *, NSView *, void (^)(void)) __attribute__((weak_import));
8
+
9
+ @interface RNWindowManagerStartup : NSObject <SparkStartupPlugin>
10
+ @end
11
+ @implementation RNWindowManagerStartup
12
+ - (void)prepareApplication { LegendPrecreateRestorableWindows(); }
13
+ - (void)prepareMainWindow:(NSWindow *)window {
14
+ if ([SparkLifecycleConfiguration()[@"mainWindow"][@"hidden"] boolValue]) return;
15
+ NSDictionary *configuration = LegendMainWindowStartupSplitViewConfiguration();
16
+ NSDictionary *initial = [NSBundle.mainBundle objectForInfoDictionaryKey:@"LegendInitialSplitView"];
17
+ if (!configuration && initial) {
18
+ // Unshown AppKit windows may still report Aqua; match the host startup theme.
19
+ NSAppearance *appearance = window.appearance ?: NSApp.appearance;
20
+ BOOL dark = appearance
21
+ ? [[appearance bestMatchFromAppearancesWithNames:@[NSAppearanceNameDarkAqua, NSAppearanceNameAqua]] isEqualToString:NSAppearanceNameDarkAqua]
22
+ : [[[NSUserDefaults.standardUserDefaults stringForKey:@"AppleInterfaceStyle"] lowercaseString] isEqualToString:@"dark"];
23
+ configuration = initial[dark ? @"dark" : @"light"];
24
+ }
25
+ if (LegendPrepareSidebarSplitViewStartup && configuration) LegendPrepareSidebarSplitViewStartup(window, configuration);
26
+ }
27
+ - (void)attachRootView:(NSView *)root toWindow:(NSWindow *)window installRoot:(void (^)(void))installRoot {
28
+ if (!LegendAttachSidebarSplitViewStartupRoot || !LegendAttachSidebarSplitViewStartupRoot(window, root, installRoot)) installRoot();
29
+ }
30
+ @end
31
+ #endif
@@ -0,0 +1,14 @@
1
+ #import <TargetConditionals.h>
2
+
3
+ #if TARGET_OS_OSX
4
+ #import <AppKit/AppKit.h>
5
+
6
+ // RNAppKitSplitView is optional. Supply linkable defaults for static release/LTO
7
+ // builds; its strong definitions replace these when that pod is included.
8
+ extern "C" __attribute__((weak)) void LegendPrepareSidebarSplitViewStartup(NSWindow *, NSDictionary *) {}
9
+ extern "C" __attribute__((weak)) BOOL LegendAttachSidebarSplitViewStartupRoot(NSWindow *, NSView *, void (^)(void))
10
+ {
11
+ return NO;
12
+ }
13
+ extern "C" __attribute__((weak)) void LegendFinishSidebarSplitViewStartup(NSWindow *) {}
14
+ #endif
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legendapp/spark-desktop-windows",
3
- "version": "0.0.1-next.2",
3
+ "version": "0.0.1-next.4",
4
4
  "license": "MIT",
5
5
  "main": "src/index",
6
6
  "react-native": "src/index",
@@ -19,14 +19,17 @@
19
19
  "jsSrcsDir": "src",
20
20
  "ios": {
21
21
  "modulesProvider": {
22
- "NativeDesktopWindowManager": "RNDesktopWindows"
23
- }
22
+ "NativeDesktopWindowManager": "RNDesktopWindows",
23
+ "NativeWindowManager": "RNWindowManager"
24
+ },
25
+ "componentProvider": {}
24
26
  }
25
27
  },
26
28
  "spark": {
27
29
  "sdk": true,
28
30
  "nativeModules": [
29
- "NativeDesktopWindowManager"
31
+ "NativeDesktopWindowManager",
32
+ "NativeWindowManager"
30
33
  ],
31
34
  "pod": "RNDesktopWindows",
32
35
  "platforms": [
@@ -37,8 +40,9 @@
37
40
  ]
38
41
  },
39
42
  "dependencies": {
40
- "@legendapp/spark-desktop-app": "0.0.1-next.2",
41
- "@legendapp/spark-window-options": "0.0.1-next.2"
43
+ "@legendapp/spark-desktop-app": "0.0.1-next.4",
44
+ "@legendapp/spark-window-options": "0.0.1-next.4",
45
+ "@legendapp/state": "^3.0.0-beta.42"
42
46
  },
43
47
  "private": true
44
48
  }
@@ -3,4 +3,4 @@ import { TurboModuleRegistry } from "react-native";
3
3
  export interface Spec extends TurboModule {
4
4
  call(method: string, args: string): Promise<string>;
5
5
  }
6
- export default TurboModuleRegistry.getEnforcing<Spec>("NativeDesktopWindowManager");
6
+ export default TurboModuleRegistry.get<Spec>("NativeDesktopWindowManager");
@@ -1,79 +1,155 @@
1
- import { validateWindow, type WindowStyle } from "@legendapp/spark-window-options";
2
- export type { WindowStyle } from "@legendapp/spark-window-options";
3
- import Native from "./NativeDesktopWindowManager";
4
1
  import { Platform } from "react-native";
5
- import { validateWindowsWindowOptions } from "./windows-options";
6
- import { onDesktopEvent } from "@legendapp/spark-desktop-app";
7
- export type Frame = { x: number; y: number; width: number; height: number };
8
- export type WindowInfo = { id: string; kind: "window" | "overlay"; title: string; visible: boolean; focused: boolean; resizable: boolean; alwaysOnTop: boolean; minWidth: number; maxWidth: number; minimized: boolean; fullscreen: boolean; frame: Frame };
9
- export type Display = { id: string; name: string; frame: Frame; workArea: Frame; scale: number };
10
- export type WindowOptions = WindowStyle & { id: string; kind?: "window" | "overlay"; parentId?: string; modal?: boolean; props?: Record<string, unknown> };
11
- export type WindowEvent = { type: string; windowId: string; requestId?: number };
12
- async function call<T = void>(method: string, args: object = {}): Promise<T> {
13
- return JSON.parse(await Native.call(method, JSON.stringify(args))) as T;
2
+ import { SparkError, asyncRegistration, nativeError, type AsyncRegistration, type Availability } from "@legendapp/spark-desktop-app/src/contracts";
3
+ export type { AsyncRegistration } from "@legendapp/spark-desktop-app/src/contracts";
4
+ import { onDesktopEvent } from "@legendapp/spark-desktop-app/src/events";
5
+ import Native from "./NativeDesktopWindowManager";
6
+ import { createMacOSWindow, macosNative, updateMacOSWindow } from "./macos-adapter";
7
+ import { bounds, keys, number, object, text, validateOptions, windowId } from "./validation";
8
+ import { getNativeDisplays, isBounds, isInfo, record, subscribeToWindowInstance, windowCall, windowCommand, type NativeWindowInfo } from "./transport";
9
+ import type { CenterWindowOptions, CloseResult, CursorPoint, DisplayInfo, SetWindowBoundsOptions, ShowWindowOptions, WindowBounds, WindowEventMap, WindowInfo, WindowOpenOptions, WindowUpdateOptions } from "./types";
10
+ export type * from "./types";
11
+
12
+ export function getWindowAvailability(): Availability {
13
+ if (Platform.OS !== "macos" && Platform.OS !== "windows") return { available: false, reason: "unsupported-platform" };
14
+ if (!Native) return { available: false, reason: "missing-module" };
15
+ if (Platform.OS === "macos") try { macosNative(); } catch { return { available: false, reason: "missing-module" }; }
16
+ return { available: true };
17
+ }
18
+ function publicInfo(value: NativeWindowInfo): WindowInfo {
19
+ const { id, kind, title, parentId, modal, visible, focused, minimized, maximized, fullscreen, bounds: { displayId, x, y, width, height } } = value;
20
+ return { id, kind, title, parentId, modal, visible, focused, minimized, maximized, fullscreen, bounds: { displayId, x, y, width, height } };
21
+ }
22
+ export async function openWindow(options: WindowOpenOptions): Promise<WindowInfo> {
23
+ validateOptions(options, Platform.OS, true);
24
+ // Optional undefined fields may be omitted; props have already undergone strict JSON validation.
25
+ const snapshot = JSON.parse(JSON.stringify(options)) as WindowOpenOptions;
26
+ if (snapshot.kind === "overlay") Object.assign(snapshot, { titleBarStyle: "borderless", transparent: true, hasShadow: false, alwaysOnTop: true, resizable: false, minimizable: false, ...snapshot });
27
+ if (Platform.OS === "macos") {
28
+ if (snapshot.kind === "overlay" && options.alwaysOnTop === undefined && options.macos?.level === undefined) {
29
+ snapshot.macos = { ...snapshot.macos, level: "status" };
30
+ delete snapshot.alwaysOnTop;
31
+ }
32
+ await createMacOSWindow(snapshot);
33
+ try {
34
+ const info = await windowCall("completeOpen", snapshot, isInfo);
35
+ // Common chrome is applied first; explicit AppKit groups own their corresponding fields.
36
+ if (!snapshot.macos) return publicInfo(info);
37
+ await updateMacOSWindow(snapshot.id, snapshot.macos);
38
+ // The window now exists: reflect the applied chrome, but a transient read-back
39
+ // failure must not discard a window that opened successfully, so fall back to info.
40
+ try { return await getWindow(snapshot.id); } catch { return publicInfo(info); }
41
+ } catch (cause) {
42
+ try { await windowCommand("discard", { id: snapshot.id }); }
43
+ catch (cleanup) { throw new SparkError("E_NATIVE", "Window opening and cleanup both failed", { cause: new AggregateError([cause, cleanup]) }); }
44
+ throw cause;
45
+ }
46
+ }
47
+ return publicInfo(await windowCall("open", snapshot, isInfo));
14
48
  }
15
- function id(value: string) { if (!/^[a-zA-Z0-9_-]{1,100}$/.test(value)) throw new Error("Window id must contain 1–100 letters, numbers, underscores or hyphens"); return value; }
16
- function dimension(value: number) { if (!Number.isFinite(value) || value < 100 || value > 20000) throw new Error("Window dimensions must be between 100 and 20000 points"); }
17
- export function openWindow(options: WindowOptions) {
18
- id(options.id); if (options.id === "main") throw new Error("Use showWindow for the main window");
19
- if (options.kind !== undefined && !["window", "overlay"].includes(options.kind)) throw new Error("Invalid window kind");
20
- if (options.kind === "overlay" && options.modal) throw new Error("An overlay cannot be modal");
21
- options = options.kind === "overlay" ? { titleBarStyle: "borderless", transparent: true, hasShadow: false, alwaysOnTop: true, resizable: false, minimizable: false, ...options } : options;
22
- const { id: _id, kind, parentId, modal, props, ...style } = options;
23
- validateWindow(style);
24
- if (Platform.OS === "windows") {
25
- validateWindowsWindowOptions(style);
49
+ export async function getWindow(id: string): Promise<WindowInfo> { windowId(id); return publicInfo(await windowCall("info", { id }, isInfo)); }
50
+ export async function listWindows(): Promise<WindowInfo[]> { return (await windowCall("list", {}, (value): value is NativeWindowInfo[] => Array.isArray(value) && value.every(isInfo))).map(publicInfo); }
51
+ export async function getDisplays(): Promise<DisplayInfo[]> { return getNativeDisplays(); }
52
+ /** Pointer position in Spark's coordinate vocabulary: logical units relative to the containing display's top-left corner. */
53
+ export async function getCursorPoint(): Promise<CursorPoint> { return windowCall("cursorPoint", {}, (value): value is CursorPoint => record(value) && typeof value.displayId === "string" && Number.isFinite(value.x) && Number.isFinite(value.y)); }
54
+ export async function setWindowOptions(id: string, options: WindowUpdateOptions): Promise<void> {
55
+ windowId(id); validateOptions(options, Platform.OS, false);
56
+ const snapshot = JSON.parse(JSON.stringify(options)) as WindowUpdateOptions;
57
+ if (!snapshot.macos || Object.keys(snapshot).some(key => key !== "macos")) {
58
+ await windowCommand("options", { id, options: snapshot });
26
59
  }
27
- if (parentId !== undefined) id(parentId);
28
- if (parentId === options.id || (modal && !parentId)) throw new Error("Modal windows need a distinct parent");
29
- return call<WindowInfo>("open", options);
60
+ if (snapshot.macos) await updateMacOSWindow(id, snapshot.macos);
30
61
  }
31
- export function setWindowOptions(windowId: string, options: WindowStyle) {
32
- validateWindow(options);
33
- if (Platform.OS === "windows") validateWindowsWindowOptions(options);
34
- return call("options", { id: id(windowId), options });
62
+ /** Portable frame change. Animated moves are macOS-only: pass `macos.durationMs` and the call rejects on Windows rather than ignoring the request. */
63
+ export async function setWindowBounds(id: string, value: WindowBounds, options: SetWindowBoundsOptions = {}): Promise<void> {
64
+ windowId(id); bounds(value); object(options, "bounds options"); keys(options, ["macos"]);
65
+ if (options.macos !== undefined) {
66
+ if (Platform.OS !== "macos") throw new SparkError("E_UNSUPPORTED_OPTION", "macos bounds options require macOS");
67
+ const macos = options.macos; object(macos, "macos"); keys(macos, ["durationMs"]);
68
+ if (macos.durationMs !== undefined) number(macos.durationMs, "durationMs", 0, 60000);
69
+ await windowCommand("bounds", { id, bounds: value, durationMs: macos.durationMs ?? 0 });
70
+ return;
71
+ }
72
+ await windowCommand("bounds", { id, bounds: value });
73
+ }
74
+ export async function showWindow(id: string, options: ShowWindowOptions = {}): Promise<void> {
75
+ windowId(id); object(options, "show options"); keys(options, ["focus"]);
76
+ if (options.focus !== undefined && typeof options.focus !== "boolean") throw new SparkError("E_INVALID_ARGUMENT", "focus must be boolean");
77
+ await windowCommand("show", { id, focus: options.focus ?? true });
78
+ }
79
+ export async function centerWindow(id: string, options: CenterWindowOptions = {}): Promise<void> {
80
+ windowId(id); object(options, "center options"); keys(options, ["displayId"]);
81
+ if (options.displayId !== undefined) text(options.displayId, "display ID", false);
82
+ await windowCommand("center", { id, ...options });
35
83
  }
36
- export const maximizeWindow = (windowId = "main") => call("maximize", { id: id(windowId) });
37
- export const unmaximizeWindow = (windowId = "main") => call("unmaximize", { id: id(windowId) });
38
- export const centerWindow = (windowId = "main") => call("center", { id: id(windowId) });
39
- export const listWindows = () => call<WindowInfo[]>("list");
40
- export const getDisplays = () => call<Display[]>("displays");
41
- export const getWindow = (windowId = "main") => call<WindowInfo>("info", { id: id(windowId) });
42
- export const closeWindow = (windowId = "main") => call("close", { id: id(windowId) });
43
- export const showWindow = (windowId = "main") => call("show", { id: id(windowId) });
44
- export const hideWindow = (windowId = "main") => call("hide", { id: id(windowId) });
45
- export const minimizeWindow = (windowId = "main") => call("minimize", { id: id(windowId) });
46
- export const setFullscreen = (windowId: string, enabled: boolean) => call("fullscreen", { id: id(windowId), enabled });
47
- export const setWindowTitle = (windowId: string, title: string) => call("title", { id: id(windowId), title });
48
- /** macOS uses screen points with a bottom-left origin; Windows uses virtual-screen pixels with a top-left origin. */
49
- export function setWindowFrame(windowId: string, frame: Frame) {
50
- dimension(frame.width); dimension(frame.height);
51
- if (!Number.isFinite(frame.x) || !Number.isFinite(frame.y)) throw new Error("Frame origin must be finite");
52
- return call("frame", { id: id(windowId), frame });
84
+ export async function hideWindow(id: string): Promise<void> { windowId(id); await windowCommand("hide", { id }); }
85
+ export async function minimizeWindow(id: string): Promise<void> { windowId(id); await windowCommand("minimize", { id }); }
86
+ export async function maximizeWindow(id: string): Promise<void> { windowId(id); await windowCommand("maximize", { id }); }
87
+ export async function unmaximizeWindow(id: string): Promise<void> { windowId(id); await windowCommand("unmaximize", { id }); }
88
+ export async function setWindowFullscreen(id: string, enabled: boolean): Promise<void> {
89
+ windowId(id); if (typeof enabled !== "boolean") throw new SparkError("E_INVALID_ARGUMENT", "fullscreen must be boolean");
90
+ await windowCommand("fullscreen", { id, enabled });
91
+ }
92
+ const closing = new Map<string, Promise<CloseResult>>();
93
+ export async function closeWindow(id: string): Promise<CloseResult> {
94
+ windowId(id);
95
+ let pending = closing.get(id);
96
+ if (!pending) {
97
+ pending = windowCall("close", { id }, (value): value is CloseResult => record(value) && (value.closed === true || (value.closed === false && value.reason === "vetoed"))).finally(() => closing.delete(id));
98
+ closing.set(id, pending);
99
+ }
100
+ return pending;
53
101
  }
54
- export function onWindowEvent(listener: (event: WindowEvent) => void) {
55
- return onDesktopEvent(event => { if (typeof event.windowId === "string") listener(event as WindowEvent); });
102
+ export interface WindowListenerOptions { onError?: (error: SparkError) => void }
103
+ function report(options: WindowListenerOptions, cause: unknown) { try { (options.onError ?? console.error)(nativeError(cause)); } catch (error) { console.error(error); } }
104
+ /** Registration acknowledges the live native instance. Removal stops callbacks immediately. */
105
+ export async function addWindowListener<K extends keyof WindowEventMap>(id: string, type: K, listener: (event: WindowEventMap[K]) => void, options: WindowListenerOptions = {}): Promise<AsyncRegistration> {
106
+ windowId(id); object(options, "listener options"); keys(options, ["onError"]);
107
+ if (!["focusChanged", "boundsChanged", "visibilityChanged", "fullscreenChanged", "closed"].includes(type) || typeof listener !== "function" || (options.onError !== undefined && typeof options.onError !== "function")) throw new SparkError("E_INVALID_ARGUMENT", "Invalid window listener");
108
+ return subscribeToWindowInstance(id, event => {
109
+ if (event.type !== type) return;
110
+ const valid = type === "closed" || (type === "boundsChanged" ? isBounds(event.bounds) : typeof event[type === "focusChanged" ? "focused" : type === "visibilityChanged" ? "visible" : "fullscreen"] === "boolean");
111
+ if (!valid) { report(options, new SparkError("E_INVALID_DATA", "Malformed window event")); return; }
112
+ const payload = { windowId: id, ...(type === "boundsChanged" ? { bounds: event.bounds } : type === "focusChanged" ? { focused: event.focused } : type === "visibilityChanged" ? { visible: event.visible } : type === "fullscreenChanged" ? { fullscreen: event.fullscreen } : {}) };
113
+ try { listener(payload as WindowEventMap[K]); } catch (cause) { report(options, cause); }
114
+ }, [type]);
56
115
  }
57
- const guards = new Set<string>();
58
- export async function beforeWindowClose(windowId: string, handler: () => boolean | Promise<boolean>) {
59
- id(windowId);
60
- if (guards.has(windowId)) throw new Error("This window already has a close handler");
61
- guards.add(windowId); let removed = false; let pending: number | undefined;
62
- const subscription = onWindowEvent(event => {
63
- if (event.windowId !== windowId || event.type !== "beforeClose" || pending === event.requestId) return;
64
- pending = event.requestId;
65
- void Promise.resolve().then(handler).then(
66
- allow => call("replyClose", { id: windowId, requestId: event.requestId, allow: !removed && allow === true }),
67
- () => call("replyClose", { id: windowId, requestId: event.requestId, allow: false }),
68
- ).catch(console.error).finally(() => { if (pending === event.requestId) pending = undefined; });
116
+ const guards = new Map<string, AsyncRegistration>();
117
+ const creatingGuards = new Set<string>();
118
+ const orphanGuards = new Map<string, AsyncRegistration>();
119
+ let guardSequence = 0;
120
+ /** Each window accepts one close guard; a second registration rejects E_BUSY until the first is removed. Removal is idempotent. */
121
+ export async function beforeWindowClose(id: string, handler: () => boolean | Promise<boolean>, options: WindowListenerOptions = {}): Promise<AsyncRegistration> {
122
+ windowId(id); object(options, "guard options"); keys(options, ["onError"]);
123
+ if (typeof handler !== "function" || (options.onError !== undefined && typeof options.onError !== "function")) throw new SparkError("E_INVALID_ARGUMENT", "Expected window close callbacks");
124
+ if (orphanGuards.has(id)) { await orphanGuards.get(id)!.remove(); orphanGuards.delete(id); }
125
+ if (guards.has(id) || creatingGuards.has(id)) throw new SparkError("E_BUSY", "Window already has a close guard");
126
+ creatingGuards.add(id);
127
+ const guardId = `close-${Date.now()}-${++guardSequence}`;
128
+ let stopped = false, instance: string | undefined, request: number | undefined, latestRequest = 0;
129
+ let subscription: ReturnType<typeof onDesktopEvent>;
130
+ try { subscription = onDesktopEvent(event => {
131
+ if (stopped || event.windowId !== id || event.instanceId !== instance) return;
132
+ if (event.type === "closed") { stopped = true; subscription.remove(); guards.delete(id); return; }
133
+ if (event.guardId !== guardId) return;
134
+ if (event.type === "closeGuardTimeout") { request = undefined; report(options, new SparkError("E_TIMEOUT", "Window close guard exceeded 30 seconds")); return; }
135
+ if (event.type !== "beforeClose" || !Number.isSafeInteger(event.requestId) || (event.requestId as number) <= latestRequest) return;
136
+ const current = latestRequest = request = event.requestId as number;
137
+ void Promise.resolve().then(() => stopped ? false : handler()).catch(cause => { report(options, cause); return false; }).then(async allow => {
138
+ if (stopped || request !== current) return;
139
+ await windowCommand("replyClose", { id, instanceId: instance, guardId, requestId: current, allow: allow === true });
140
+ }).catch(cause => report(options, cause)).finally(() => { if (request === current) request = undefined; });
141
+ }, { types: ["closed", "beforeClose", "closeGuardTimeout"], target: { field: "windowId", value: id } }); } catch (cause) { creatingGuards.delete(id); throw cause; }
142
+ const registration = asyncRegistration(() => { stopped = true; subscription.remove(); }, async () => {
143
+ try { if (instance) await windowCommand("closeGuard", { id, instanceId: instance, guardId, enabled: false }); }
144
+ catch (cause) { if (nativeError(cause).code !== "E_NOT_FOUND") throw cause; }
145
+ if (guards.get(id) === registration) guards.delete(id);
69
146
  });
70
- try { await call("closeGuard", { id: windowId, enabled: true }); }
71
- catch (error) { subscription.remove(); guards.delete(windowId); throw error; }
72
- return { async remove() {
73
- if (removed) return;
74
- removed = true; subscription.remove(); guards.delete(windowId);
75
- // Closed secondary windows no longer have a native guard to remove.
76
- try { await call("closeGuard", { id: windowId, enabled: false }); }
77
- catch (error) { if ((error as { code?: string }).code !== "E_NOT_FOUND") throw error; }
78
- } };
147
+ try {
148
+ instance = (await windowCall("observe", { id }, isInfo)).instanceId;
149
+ await windowCommand("closeGuard", { id, instanceId: instance, guardId, enabled: true });
150
+ if (!stopped) guards.set(id, registration); return registration;
151
+ } catch (cause) {
152
+ try { await registration.remove(); } catch (cleanup) { orphanGuards.set(id, registration); report(options, cleanup); }
153
+ throw cause;
154
+ } finally { creatingGuards.delete(id); }
79
155
  }
@@ -0,0 +1,17 @@
1
+ import { parseNativeResult } from "@legendapp/spark-desktop-app/src/contracts";
2
+ import { macosNative } from "./macos-adapter";
3
+ export interface StartupTiming {
4
+ clockOffsetMs?: number;
5
+ startTime?: number;
6
+ endTime?: number;
7
+ initializeRuntimeStart?: number;
8
+ initializeRuntimeEnd?: number;
9
+ executeJavaScriptBundleEntryPointStart?: number;
10
+ executeJavaScriptBundleEntryPointEnd?: number;
11
+ mainWindowFirstVisibleTime?: number;
12
+ mainWindowReactRootAttachedTime?: number;
13
+ }
14
+ /** Native monotonic millisecond markers; clockOffsetMs maps them to wall-clock time. */
15
+ export function getStartupTiming(): StartupTiming {
16
+ return parseNativeResult(macosNative().getReactNativeStartupTimingJson(), (value): value is StartupTiming => !!value && typeof value === "object" && !Array.isArray(value) && Object.values(value).every(marker => typeof marker === "number" && Number.isFinite(marker)));
17
+ }
@@ -1 +1,3 @@
1
- export * from "./api";
1
+ export { getWindowAvailability, openWindow, getWindow, listWindows, getDisplays, getCursorPoint, setWindowOptions, setWindowBounds, showWindow, hideWindow, closeWindow, minimizeWindow, maximizeWindow, unmaximizeWindow, setWindowFullscreen, centerWindow, addWindowListener, beforeWindowClose, type WindowListenerOptions, type AsyncRegistration } from "./api";
2
+ export type * from "./types";
3
+ export * from "./windows";
@@ -1 +1,3 @@
1
- export * from "./api";
1
+ export { getWindowAvailability, openWindow, getWindow, listWindows, getDisplays, setWindowOptions, setWindowBounds, showWindow, hideWindow, closeWindow, minimizeWindow, maximizeWindow, unmaximizeWindow, setWindowFullscreen, centerWindow, addWindowListener, beforeWindowClose, type WindowListenerOptions, type AsyncRegistration } from "./api";
2
+ export type * from "./types";
3
+ export * from "./windows";
@@ -0,0 +1,53 @@
1
+ import { Platform } from "react-native";
2
+ import { SparkError, invokeNative, parseNativeResult } from "@legendapp/spark-desktop-app/src/contracts";
3
+ import { menuItems } from "@legendapp/spark-desktop-app/src/contracts/menu";
4
+ import Native from "./window-manager/NativeWindowManager";
5
+ import type { MacOSWindowOptions, WindowOpenOptions } from "./types";
6
+ export function macosNative() {
7
+ if (Platform.OS !== "macos") throw new SparkError("E_UNSUPPORTED_PLATFORM", "This operation requires macOS");
8
+ if (!Native) throw new SparkError("E_MODULE_UNAVAILABLE", "The macOS window module is unavailable");
9
+ return Native;
10
+ }
11
+ export async function macosCommand(operation: () => Promise<string>): Promise<void> {
12
+ const result = parseNativeResult(await invokeNative(operation), (value): value is { success: boolean; message?: string } => !!value && typeof value === "object" && typeof (value as any).success === "boolean");
13
+ if (!result.success) throw new SparkError("E_NATIVE", result.message ?? "macOS window operation failed");
14
+ }
15
+ export function macosOptions(options: MacOSWindowOptions | undefined): Record<string, unknown> {
16
+ if (!options) return {};
17
+ const result: Record<string, unknown> = {}, style: Record<string, unknown> = {};
18
+ if (options.representedUri !== undefined) result.representedURL = options.representedUri;
19
+ if (options.restoreOnLaunch !== undefined) result.restoreOnLaunch = options.restoreOnLaunch;
20
+ if (options.startupSplitView !== undefined) style.startupSplitView = options.startupSplitView;
21
+ if (options.level !== undefined) {
22
+ const names = { normal: "NORMAL", floating: "FLOATING", modalPanel: "MODAL_PANEL", mainMenu: "MAIN_MENU", status: "STATUS", screenSaver: "SCREEN_SAVER" };
23
+ const constants = parseNativeResult(macosNative().getConstantsJson(), (value): value is Record<string, number> => !!value && typeof value === "object");
24
+ const value = constants[`WINDOW_LEVEL_${names[options.level]}`];
25
+ if (!Number.isFinite(value)) throw new SparkError("E_INVALID_DATA", "Missing native window level constant");
26
+ result.level = value;
27
+ }
28
+ if (options.panelStyle !== undefined) style.panelStyle = options.panelStyle;
29
+ const title = options.titleBar;
30
+ if (title) {
31
+ const fields = { contentLayout: "contentLayoutMode", transparent: "titlebarAppearsTransparent", titleVisibility: "titleVisibility", separator: "titlebarSeparatorStyle", material: "titlebarMaterial", blendingMode: "titlebarMaterialBlendingMode", materialState: "titlebarMaterialState", trafficLights: "trafficLights" } as const;
32
+ for (const [key, target] of Object.entries(fields)) if (title[key as keyof typeof fields] !== undefined) style[target] = title[key as keyof typeof fields];
33
+ if (title.controls) style.titlebarControls = title.controls.map(({ symbol, disabled, ...control }) => ({ ...control, type: "button", enabled: !disabled, systemImageName: symbol }));
34
+ }
35
+ if (options.toolbar) {
36
+ if (options.toolbar.visible !== undefined) style.hasToolbar = options.toolbar.visible;
37
+ if (options.toolbar.style !== undefined) style.toolbarStyle = options.toolbar.style;
38
+ if (options.toolbar.items) style.toolbarItems = options.toolbar.items.map(item => {
39
+ const { type, ...common } = item;
40
+ if (type === "segmented") { const value = item as Extract<typeof item, { type: "segmented" }>; return { ...common, type, selectedValue: value.value, segments: value.segments.map(({ symbol, ...segment }) => ({ ...segment, systemImageName: symbol })) }; }
41
+ if (type === "menu") { const { items, ...value } = item as Extract<typeof item, { type: "menu" }>; return { ...value, type: "menuButton", enabled: !value.disabled, systemImageName: value.symbol, menuItems: menuItems(items, { types: ["action", "checkbox", "separator", "slider"], icons: ["symbol"] }, "macos") }; }
42
+ return { ...common, type, ...("disabled" in item ? { enabled: !item.disabled } : {}), ...("symbol" in item ? { systemImageName: item.symbol } : {}) };
43
+ });
44
+ }
45
+ result.windowStyle = style;
46
+ return result;
47
+ }
48
+ export async function createMacOSWindow(options: WindowOpenOptions): Promise<void> {
49
+ await macosCommand(() => macosNative().openWindow(JSON.stringify({ ...macosOptions(options.macos), identifier: options.id, moduleName: options.component, initialProperties: options.props ?? {}, title: options.title, deferOrderFront: true, sparkOverlay: options.kind === "overlay" })));
50
+ }
51
+ export async function updateMacOSWindow(id: string, options: MacOSWindowOptions): Promise<void> {
52
+ await macosCommand(() => macosNative().setWindowOptions(id, JSON.stringify(macosOptions(options))));
53
+ }
@@ -0,0 +1,51 @@
1
+ import { SparkError, nativeError, type AsyncRegistration } from "@legendapp/spark-desktop-app/src/contracts";
2
+ export type { AsyncRegistration } from "@legendapp/spark-desktop-app/src/contracts";
3
+ import { macosCommand, macosNative } from "./macos-adapter";
4
+ import { subscribeToWindowInstance } from "./transport";
5
+ import { type WindowListenerOptions } from "./api";
6
+ import { keys, number, object, text, windowId } from "./validation";
7
+ import type { MacOSWindowBlurOptions, MacOSWindowEvent } from "./types";
8
+ export type { MacOSWindowBlurOptions, MacOSWindowEvent, MacOSToolbarItem, MacOSToolbarOptions, MenuAction } from "./types";
9
+ /** Animated frame changes go through `setWindowBounds` from `/windows` with a `macos.durationMs` group, which rejects on Windows. */
10
+ export async function setWindowBlur(id: string, options: MacOSWindowBlurOptions): Promise<void> {
11
+ const native = macosNative(); windowId(id); object(options, "blur options"); keys(options, ["radius", "durationMs"]);
12
+ number(options.radius, "radius", 0, 1000); if (options.durationMs !== undefined) number(options.durationMs, "durationMs", 0, 60000);
13
+ await macosCommand(() => native.setWindowBlur(id, options.radius, options.durationMs ?? 0));
14
+ }
15
+ export interface FocusToolbarSearchOptions { value?: string }
16
+ export async function focusToolbarSearch(id: string, itemId: string, options: FocusToolbarSearchOptions = {}): Promise<void> {
17
+ const native = macosNative(); windowId(id); text(itemId, "toolbar item ID", false); object(options, "search options"); keys(options, ["value"]);
18
+ if (options.value !== undefined) text(options.value, "search value");
19
+ await macosCommand(() => native.focusToolbarSearchItem(id, itemId, options.value ?? null));
20
+ }
21
+ export async function setToolbarItemText(id: string, itemId: string, value: string): Promise<void> {
22
+ const native = macosNative(); windowId(id); text(itemId, "toolbar item ID", false); text(value, "toolbar text");
23
+ await macosCommand(() => native.setWindowToolbarItemText(id, itemId, value));
24
+ }
25
+ export async function addMacOSWindowListener(id: string, listener: (event: MacOSWindowEvent) => void, options: WindowListenerOptions = {}): Promise<AsyncRegistration> {
26
+ macosNative(); windowId(id); object(options, "listener options"); keys(options, ["onError"]);
27
+ if (typeof listener !== "function" || (options.onError !== undefined && typeof options.onError !== "function")) throw new SparkError("E_INVALID_ARGUMENT", "Expected window event callbacks");
28
+ return subscribeToWindowInstance(id, event => {
29
+ if (!["titleBarAction", "toolbarAction", "toolbarSelectionChanged", "toolbarSearchChanged", "toolbarSearchSubmitted", "toolbarMenuAction"].includes(event.type)) return;
30
+ const report = (cause: unknown) => { if (options.onError) options.onError(nativeError(cause)); else console.error(cause); };
31
+ const error = () => report(new SparkError("E_INVALID_DATA", "Malformed macOS window event"));
32
+ const base = { windowId: id, type: event.type };
33
+ let payload: unknown;
34
+ if (event.type === "titleBarAction") {
35
+ if (typeof event.controlId !== "string" || !event.controlId) return error();
36
+ payload = { ...base, controlId: event.controlId };
37
+ } else {
38
+ if (typeof event.itemId !== "string" || !event.itemId) return error();
39
+ if (event.type === "toolbarAction") payload = { ...base, itemId: event.itemId };
40
+ else if (event.type === "toolbarMenuAction") {
41
+ const action = event.action as any;
42
+ if (!action || typeof action.itemId !== "string" || !action.itemId || (action.type !== "action" && !(action.type === "valueChanged" && typeof action.value === "number" && Number.isFinite(action.value)))) return error();
43
+ payload = { ...base, itemId: event.itemId, action: action.type === "action" ? { type: "action", itemId: action.itemId } : { type: "valueChanged", itemId: action.itemId, value: action.value } };
44
+ } else {
45
+ if (typeof event.value !== "string" || (event.type !== "toolbarSelectionChanged" && typeof event.shiftKey !== "boolean")) return error();
46
+ payload = { ...base, itemId: event.itemId, value: event.value, ...(event.type !== "toolbarSelectionChanged" ? { shiftKey: event.shiftKey } : {}) };
47
+ }
48
+ }
49
+ try { listener(payload as MacOSWindowEvent); } catch (cause) { report(cause); }
50
+ }, ["titleBarAction", "toolbarAction", "toolbarSelectionChanged", "toolbarSearchChanged", "toolbarSearchSubmitted", "toolbarMenuAction"]);
51
+ }
@@ -0,0 +1,41 @@
1
+ import { Platform } from "react-native";
2
+ import { SparkError, asyncRegistration, invokeNative, parseNativeResult, type AsyncRegistration } from "@legendapp/spark-desktop-app/src/contracts";
3
+ import { onDesktopEvent, type DesktopEvent } from "@legendapp/spark-desktop-app/src/events";
4
+ import Native from "./NativeDesktopWindowManager";
5
+ import { windowId } from "./validation";
6
+ import type { DisplayInfo, WindowBounds, WindowInfo } from "./types";
7
+
8
+ /** Internal native transport shared by the public window API and the macOS adapter. Not part of any public entry point. */
9
+ export const record = (value: unknown): value is Record<string, any> => !!value && typeof value === "object" && !Array.isArray(value);
10
+ export const finite = (value: unknown): value is number => typeof value === "number" && Number.isFinite(value);
11
+ export const isSize = (value: unknown) => record(value) && finite(value.width) && value.width > 0 && finite(value.height) && value.height > 0;
12
+ export const isBounds = (value: unknown): value is WindowBounds => record(value) && isSize(value) && finite(value.x) && finite(value.y) && typeof value.displayId === "string" && !!value.displayId;
13
+ export interface NativeWindowInfo extends WindowInfo { instanceId: string }
14
+ export const isInfo = (value: unknown): value is NativeWindowInfo => record(value) && typeof value.id === "string" && typeof value.instanceId === "string" && !!value.instanceId && ["window", "overlay"].includes(value.kind) && typeof value.title === "string" && (value.parentId === null || typeof value.parentId === "string") && [value.modal, value.visible, value.focused, value.minimized, value.maximized, value.fullscreen].every(flag => typeof flag === "boolean") && isBounds(value.bounds);
15
+
16
+ export async function windowCall<T>(method: string, args: object, validate: (value: unknown) => value is T): Promise<T> {
17
+ if (Platform.OS !== "macos" && Platform.OS !== "windows") throw new SparkError("E_UNSUPPORTED_PLATFORM", "Windows require a desktop host");
18
+ if (!Native) throw new SparkError("E_MODULE_UNAVAILABLE", "The window module is unavailable");
19
+ const native = Native;
20
+ return parseNativeResult(await invokeNative(() => native.call(method, JSON.stringify(args))), validate);
21
+ }
22
+ export async function windowCommand(method: string, args: object): Promise<void> { await windowCall(method, args, (value): value is null => value === null); }
23
+ /** Internal lifetime binding shared by ordinary and AppKit event subscriptions. */
24
+ export async function subscribeToWindowInstance(id: string, listener: (event: DesktopEvent) => void, types: readonly string[] = ["focusChanged", "boundsChanged", "visibilityChanged", "fullscreenChanged"]): Promise<AsyncRegistration> {
25
+ windowId(id);
26
+ let instance: string | undefined, stopped = false;
27
+ const buffered: DesktopEvent[] = [];
28
+ const consume = (event: DesktopEvent) => {
29
+ if (stopped || event.windowId !== id) return;
30
+ if (!instance) { buffered.push(event); return; }
31
+ if (event.instanceId !== instance) return;
32
+ try { listener(event); } finally { if (event.type === "closed") { stopped = true; subscription.remove(); } }
33
+ };
34
+ const subscription = onDesktopEvent(consume, { types: [...types, "closed"], target: { field: "windowId", value: id } });
35
+ try { instance = (await windowCall("observe", { id }, isInfo)).instanceId; buffered.splice(0).forEach(consume); }
36
+ catch (cause) { stopped = true; subscription.remove(); throw cause; }
37
+ return asyncRegistration(() => { stopped = true; subscription.remove(); }, async () => {});
38
+ }
39
+ export async function getNativeDisplays(): Promise<DisplayInfo[]> {
40
+ return windowCall("displays", {}, (value): value is DisplayInfo[] => Array.isArray(value) && value.length > 0 && value.every(item => record(item) && typeof item.id === "string" && !!item.id && (item.persistentId === null || typeof item.persistentId === "string") && typeof item.name === "string" && typeof item.primary === "boolean" && isSize(item.size) && isSize(item.workArea) && finite(item.workArea.x) && finite(item.workArea.y) && finite(item.scaleFactor) && item.scaleFactor > 0) && value.filter(item => item.primary).length === 1 && new Set(value.map(item => item.id)).size === value.length);
41
+ }