@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,140 @@
1
+ import type { MenuAction } from "@legendapp/spark-desktop-app/src/contracts/menu";
2
+ export type { MenuAction } from "@legendapp/spark-desktop-app/src/contracts/menu";
3
+ export type WindowId = string;
4
+ export type DisplayId = string;
5
+ export interface Size { width: number; height: number }
6
+ /** Pointer position in logical units relative to the containing display's top-left corner. */
7
+ export interface CursorPoint { displayId: DisplayId; x: number; y: number }
8
+ /** Outer frame in logical units from the identified display's top-left corner. */
9
+ export interface WindowBounds extends Size { displayId: DisplayId; x: number; y: number }
10
+ export interface DisplayInfo {
11
+ id: DisplayId;
12
+ persistentId: string | null;
13
+ name: string;
14
+ primary: boolean;
15
+ size: Size;
16
+ workArea: { x: number; y: number; width: number; height: number };
17
+ scaleFactor: number;
18
+ }
19
+ export type WindowKind =
20
+ | { kind?: "window"; parentId?: WindowId; modal?: false }
21
+ | { kind: "window"; parentId: WindowId; modal: true }
22
+ | { kind: "overlay"; parentId?: WindowId; modal?: never };
23
+ export interface WindowAppearanceOptions {
24
+ title?: string;
25
+ appearance?: "system" | "light" | "dark";
26
+ titleBarStyle?: "default" | "overlay" | "hidden" | "borderless";
27
+ backgroundColor?: string;
28
+ transparent?: boolean;
29
+ hasShadow?: boolean;
30
+ alwaysOnTop?: boolean;
31
+ resizable?: boolean;
32
+ closable?: boolean;
33
+ minimizable?: boolean;
34
+ /** Null clears this constraint back to the supported 100–20000 logical-unit range. */
35
+ minSize?: Size | null;
36
+ maxSize?: Size | null;
37
+ }
38
+ export type WindowOpenOptions = WindowKind & WindowAppearanceOptions & {
39
+ id: WindowId;
40
+ component: string;
41
+ props?: Record<string, unknown>;
42
+ size?: Size;
43
+ position?: { displayId: DisplayId; x: number; y: number };
44
+ show?: boolean;
45
+ restoreBounds?: boolean;
46
+ macos?: MacOSWindowOptions;
47
+ };
48
+ export interface WindowUpdateOptions extends WindowAppearanceOptions { macos?: MacOSWindowUpdateOptions }
49
+ export interface WindowInfo {
50
+ id: WindowId;
51
+ kind: "window" | "overlay";
52
+ title: string;
53
+ parentId: WindowId | null;
54
+ modal: boolean;
55
+ visible: boolean;
56
+ focused: boolean;
57
+ minimized: boolean;
58
+ maximized: boolean;
59
+ fullscreen: boolean;
60
+ bounds: WindowBounds;
61
+ }
62
+ export type CloseResult = { closed: true } | { closed: false; reason: "vetoed" };
63
+ export interface ShowWindowOptions { focus?: boolean }
64
+ export interface CenterWindowOptions { displayId?: DisplayId }
65
+ export interface WindowEventMap {
66
+ focusChanged: { windowId: WindowId; focused: boolean };
67
+ boundsChanged: { windowId: WindowId; bounds: WindowBounds };
68
+ visibilityChanged: { windowId: WindowId; visible: boolean };
69
+ fullscreenChanged: { windowId: WindowId; fullscreen: boolean };
70
+ closed: { windowId: WindowId };
71
+ }
72
+ export interface MacOSTitleBarControl {
73
+ id: string;
74
+ label?: string;
75
+ placement?: "left" | "right";
76
+ disabled?: boolean;
77
+ selected?: boolean;
78
+ symbol?: string;
79
+ tooltip?: string;
80
+ }
81
+ export interface MacOSTitleBarOptions {
82
+ contentLayout?: "contentLayoutGuide" | "fullSize";
83
+ transparent?: boolean;
84
+ titleVisibility?: "visible" | "hidden";
85
+ separator?: "automatic" | "none" | "line" | "shadow";
86
+ material?: "none" | "glass" | "titlebar" | "headerView" | "hudWindow" | "sidebar" | "windowBackground";
87
+ blendingMode?: "behindWindow" | "withinWindow";
88
+ materialState?: "active" | "inactive" | "followsWindowActiveState";
89
+ trafficLights?: boolean;
90
+ controls?: readonly MacOSTitleBarControl[];
91
+ }
92
+ export interface MacOSToolbarSegment { value: string; label: string; symbol?: string }
93
+ interface ToolbarEntry { id: string; label?: string; placement?: "leading" | "trailing" }
94
+ type ToolbarMenuEntry = { id: string; label: string; disabled?: boolean; hidden?: boolean; icon?: { type: "symbol"; name: string } };
95
+ type ToolbarMenuItem =
96
+ | { type: "separator" }
97
+ | (ToolbarMenuEntry & { type: "action" })
98
+ | (ToolbarMenuEntry & { type: "checkbox"; checked: boolean })
99
+ | (ToolbarMenuEntry & { type: "slider"; min: number; max: number; value: number; suffix?: string });
100
+ export type MacOSToolbarItem =
101
+ | (ToolbarEntry & { type: "button"; disabled?: boolean; bordered?: boolean; symbol?: string; tooltip?: string; monospacedDigits?: boolean; width?: number })
102
+ | (ToolbarEntry & { type: "menu"; disabled?: boolean; bordered?: boolean; symbol?: string; tooltip?: string; width?: number; items: readonly ToolbarMenuItem[] })
103
+ | (ToolbarEntry & { type: "label"; text: string; width?: number })
104
+ | (ToolbarEntry & { type: "search"; disabled?: boolean; collapses?: boolean; placeholder?: string; value?: string; width?: number })
105
+ | (ToolbarEntry & { type: "segmented"; segments: readonly MacOSToolbarSegment[]; value: string | null });
106
+ export interface MacOSToolbarOptions {
107
+ visible?: boolean;
108
+ style?: "automatic" | "expanded" | "preference" | "unified" | "unifiedCompact";
109
+ items?: readonly MacOSToolbarItem[];
110
+ }
111
+ export interface MacOSStartupSplitViewOptions {
112
+ sidebarWidth: number;
113
+ sidebarMinWidth: number;
114
+ contentMinWidth: number;
115
+ sidebarCollapsed?: boolean;
116
+ appearance: "light" | "dark";
117
+ backgroundColor: string;
118
+ sidebarBackgroundColor: string;
119
+ contentTitlebarHeight?: number;
120
+ }
121
+ export interface MacOSWindowOptions {
122
+ panelStyle?: "utility" | "documentModal" | "nonactivating";
123
+ representedUri?: string | null;
124
+ level?: "normal" | "floating" | "modalPanel" | "mainMenu" | "status" | "screenSaver";
125
+ titleBar?: MacOSTitleBarOptions;
126
+ toolbar?: MacOSToolbarOptions;
127
+ startupSplitView?: MacOSStartupSplitViewOptions | null;
128
+ restoreOnLaunch?: boolean;
129
+ }
130
+ /** Panel class and startup shell are fixed when the native window is created. */
131
+ export type MacOSWindowUpdateOptions = Omit<MacOSWindowOptions, "panelStyle">;
132
+ export type MacOSWindowEvent =
133
+ | { type: "titleBarAction"; windowId: string; controlId: string }
134
+ | { type: "toolbarAction"; windowId: string; itemId: string }
135
+ | { type: "toolbarSelectionChanged"; windowId: string; itemId: string; value: string }
136
+ | { type: "toolbarSearchChanged" | "toolbarSearchSubmitted"; windowId: string; itemId: string; value: string; shiftKey: boolean }
137
+ | { type: "toolbarMenuAction"; windowId: string; itemId: string; action: MenuAction };
138
+ export interface MacOSWindowBoundsOptions { durationMs?: number }
139
+ export interface SetWindowBoundsOptions { macos?: MacOSWindowBoundsOptions }
140
+ export interface MacOSWindowBlurOptions { radius: number; durationMs?: number }
@@ -0,0 +1,162 @@
1
+ import { SparkError } from "@legendapp/spark-desktop-app/src/contracts";
2
+ import { menuItems } from "@legendapp/spark-desktop-app/src/contracts/menu";
3
+ import type { Size, WindowBounds, WindowOpenOptions, WindowUpdateOptions, MacOSWindowOptions } from "./types";
4
+
5
+ type ObjectValue = Record<string, unknown>;
6
+ export function object<T>(value: T, name: string): asserts value is T & ObjectValue {
7
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new SparkError("E_INVALID_ARGUMENT", `${name} must be an object`);
8
+ }
9
+ export function keys(value: object, allowed: readonly string[]) {
10
+ for (const key of Object.keys(value)) if (!allowed.includes(key)) throw new SparkError("E_UNSUPPORTED_OPTION", `Unsupported window option: ${key}`);
11
+ }
12
+ export function windowId(value: unknown): asserts value is string {
13
+ if (typeof value !== "string" || !/^[a-zA-Z0-9_-]{1,100}$/.test(value)) throw new SparkError("E_INVALID_ARGUMENT", "Window IDs require 1–100 letters, numbers, underscores or hyphens");
14
+ }
15
+ export function text(value: unknown, name: string, empty = true): asserts value is string {
16
+ if (typeof value !== "string" || value.includes("\0") || (!empty && !value.length)) throw new SparkError("E_INVALID_ARGUMENT", `Invalid ${name}`);
17
+ }
18
+ export function number(value: unknown, name: string, min: number, max: number): asserts value is number {
19
+ if (typeof value !== "number" || !Number.isFinite(value) || value < min || value > max) throw new SparkError("E_INVALID_ARGUMENT", `${name} must be between ${min} and ${max}`);
20
+ }
21
+ function enumValue(value: unknown, allowed: readonly string[], name: string) {
22
+ if (value !== undefined && !allowed.includes(value as string)) throw new SparkError("E_INVALID_ARGUMENT", `Invalid ${name}`);
23
+ }
24
+ function flags(value: ObjectValue, names: readonly string[]) {
25
+ for (const key of names) if (value[key] !== undefined && typeof value[key] !== "boolean") throw new SparkError("E_INVALID_ARGUMENT", `${key} must be boolean`);
26
+ }
27
+ export function size(value: unknown): asserts value is Size {
28
+ object(value, "size"); keys(value, ["width", "height"]);
29
+ number(value.width, "width", 100, 20000); number(value.height, "height", 100, 20000);
30
+ }
31
+ function position(value: unknown) {
32
+ object(value, "position"); keys(value, ["displayId", "x", "y"]);
33
+ text(value.displayId, "display ID", false); number(value.x, "x", -10000000, 10000000); number(value.y, "y", -10000000, 10000000);
34
+ }
35
+ export function bounds(value: unknown): asserts value is WindowBounds {
36
+ object(value, "bounds"); keys(value, ["displayId", "x", "y", "width", "height"]);
37
+ position({ displayId: value.displayId, x: value.x, y: value.y }); size({ width: value.width, height: value.height });
38
+ }
39
+ function color(value: unknown) {
40
+ if (typeof value !== "string" || !/^#[0-9a-f]{6}([0-9a-f]{2})?$/i.test(value)) throw new SparkError("E_INVALID_ARGUMENT", "Window colors must be #RRGGBB or #RRGGBBAA");
41
+ }
42
+ /** Snapshot JSON props before a queued native call; no silent coercion or omission. */
43
+ export function jsonSnapshot(value: unknown, active = new Set<object>()): unknown {
44
+ if (value === null || typeof value === "string" || typeof value === "boolean") return value;
45
+ if (typeof value === "number" && Number.isFinite(value)) return value;
46
+ if (!value || typeof value !== "object" || active.has(value)) throw new SparkError("E_INVALID_ARGUMENT", "Window props must be finite, acyclic JSON");
47
+ active.add(value);
48
+ try {
49
+ if (Array.isArray(value)) {
50
+ if (Object.getOwnPropertySymbols(value).length || Object.keys(value).length !== value.length || Array.from({ length: value.length }, (_, index) => index).some(index => !Object.hasOwn(value, index))) throw new SparkError("E_INVALID_ARGUMENT", "Window props cannot contain sparse arrays");
51
+ return value.map(entry => jsonSnapshot(entry, active));
52
+ }
53
+ if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) throw new SparkError("E_INVALID_ARGUMENT", "Window props require plain JSON objects");
54
+ if (Object.getOwnPropertySymbols(value).length) throw new SparkError("E_INVALID_ARGUMENT", "Window props cannot contain symbol properties");
55
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, jsonSnapshot(entry, active)]));
56
+ } finally { active.delete(value); }
57
+ }
58
+ const common = ["title", "appearance", "titleBarStyle", "backgroundColor", "transparent", "hasShadow", "alwaysOnTop", "resizable", "closable", "minimizable", "minSize", "maxSize", "macos"];
59
+ export function validateOptions(options: WindowOpenOptions | WindowUpdateOptions, platform: string, opening: boolean): void {
60
+ object(options, "window options"); keys(options, [...common, ...(opening ? ["id", "component", "props", "size", "position", "show", "restoreBounds", "kind", "parentId", "modal"] : [])]);
61
+ flags(options, ["transparent", "hasShadow", "alwaysOnTop", "resizable", "closable", "minimizable", "show", "restoreBounds", "modal"]);
62
+ if (options.title !== undefined) text(options.title, "title");
63
+ enumValue(options.appearance, ["system", "light", "dark"], "appearance");
64
+ enumValue(options.titleBarStyle, ["default", "overlay", "hidden", "borderless"], "titleBarStyle");
65
+ if (platform === "windows" && options.titleBarStyle === "overlay") throw new SparkError("E_UNSUPPORTED_OPTION", "Windows does not support overlay title bars");
66
+ if (options.backgroundColor !== undefined) color(options.backgroundColor);
67
+ for (const value of [options.minSize, options.maxSize]) if (value !== undefined && value !== null) size(value);
68
+ const min = options.minSize ?? { width: 100, height: 100 }, max = options.maxSize ?? { width: 20000, height: 20000 };
69
+ if (min.width > max.width || min.height > max.height) throw new SparkError("E_INVALID_ARGUMENT", "Minimum window size exceeds maximum");
70
+ if (options.macos !== undefined) {
71
+ if (platform !== "macos") throw new SparkError("E_UNSUPPORTED_OPTION", "macos window options require macOS");
72
+ validateMacOS(options.macos);
73
+ if (!opening && "panelStyle" in options.macos) throw new SparkError("E_UNSUPPORTED_OPTION", "panelStyle is fixed when opening a window");
74
+ if (options.alwaysOnTop !== undefined && options.macos.level !== undefined) throw new SparkError("E_INVALID_ARGUMENT", "Choose alwaysOnTop or a macOS window level");
75
+ }
76
+ if (opening) {
77
+ const value = options as WindowOpenOptions;
78
+ windowId(value.id); if (value.id === "main") throw new SparkError("E_INVALID_ARGUMENT", "The main window is created by the host");
79
+ text(value.component, "registered component", false);
80
+ enumValue(value.kind, ["window", "overlay"], "window kind");
81
+ if (value.parentId !== undefined) windowId(value.parentId);
82
+ if (value.parentId === value.id || (value.modal && (!value.parentId || String(value.kind) === "overlay"))) throw new SparkError("E_INVALID_ARGUMENT", "Modal windows require a distinct parent and cannot be overlays");
83
+ if (value.size !== undefined) {
84
+ size(value.size);
85
+ if (value.size.width < min.width || value.size.height < min.height || value.size.width > max.width || value.size.height > max.height) throw new SparkError("E_INVALID_ARGUMENT", "Window size is outside its constraints");
86
+ }
87
+ if (value.position !== undefined) position(value.position);
88
+ if (value.props !== undefined) { object(value.props, "props"); jsonSnapshot(value.props); }
89
+ }
90
+ }
91
+ function entries(value: unknown, name: string): ObjectValue[] {
92
+ if (!Array.isArray(value)) throw new SparkError("E_INVALID_ARGUMENT", `${name} must be an array`);
93
+ const ids = new Set<string>();
94
+ for (const item of value) {
95
+ object(item, name); text(item.id, `${name} ID`, false);
96
+ if (ids.has(item.id)) throw new SparkError("E_INVALID_ARGUMENT", `${name} IDs must be unique`);
97
+ ids.add(item.id);
98
+ }
99
+ return value;
100
+ }
101
+ export function validateMacOS(value: MacOSWindowOptions) {
102
+ object(value, "macos"); keys(value, ["panelStyle", "representedUri", "level", "titleBar", "toolbar", "startupSplitView", "restoreOnLaunch"]);
103
+ enumValue(value.panelStyle, ["utility", "documentModal", "nonactivating"], "panelStyle");
104
+ enumValue(value.level, ["normal", "floating", "modalPanel", "mainMenu", "status", "screenSaver"], "level");
105
+ flags(value, ["restoreOnLaunch"]);
106
+ if (value.representedUri !== undefined && value.representedUri !== null) {
107
+ text(value.representedUri, "represented URI", false);
108
+ try { new URL(value.representedUri); } catch { throw new SparkError("E_INVALID_ARGUMENT", "representedUri must be an absolute URI"); }
109
+ }
110
+ if (value.titleBar !== undefined) {
111
+ const title = value.titleBar; object(title, "titleBar");
112
+ keys(title, ["contentLayout", "transparent", "titleVisibility", "separator", "material", "blendingMode", "materialState", "trafficLights", "controls"]);
113
+ flags(title, ["transparent", "trafficLights"]);
114
+ enumValue(title.contentLayout, ["contentLayoutGuide", "fullSize"], "contentLayout");
115
+ enumValue(title.titleVisibility, ["visible", "hidden"], "titleVisibility");
116
+ enumValue(title.separator, ["automatic", "none", "line", "shadow"], "separator");
117
+ enumValue(title.material, ["none", "glass", "titlebar", "headerView", "hudWindow", "sidebar", "windowBackground"], "material");
118
+ enumValue(title.blendingMode, ["behindWindow", "withinWindow"], "blendingMode");
119
+ enumValue(title.materialState, ["active", "inactive", "followsWindowActiveState"], "materialState");
120
+ if (title.controls !== undefined) for (const control of entries(title.controls, "titlebar control")) {
121
+ keys(control, ["id", "label", "placement", "disabled", "selected", "symbol", "tooltip"]); flags(control, ["disabled", "selected"]);
122
+ enumValue(control.placement, ["left", "right"], "control placement");
123
+ for (const field of ["label", "symbol", "tooltip"]) if (control[field] !== undefined) text(control[field], field);
124
+ }
125
+ }
126
+ if (value.toolbar !== undefined) {
127
+ object(value.toolbar, "toolbar"); keys(value.toolbar, ["visible", "style", "items"]); flags(value.toolbar, ["visible"]);
128
+ enumValue(value.toolbar.style, ["automatic", "expanded", "preference", "unified", "unifiedCompact"], "toolbar style");
129
+ if (value.toolbar.items !== undefined) for (const item of entries(value.toolbar.items, "toolbar item")) {
130
+ const fields: Record<string, string[]> = { button: ["disabled", "bordered", "symbol", "tooltip", "monospacedDigits", "width"], menu: ["disabled", "bordered", "symbol", "tooltip", "width", "items"], label: ["text", "width"], search: ["disabled", "collapses", "placeholder", "value", "width"], segmented: ["segments", "value"] };
131
+ if (typeof item.type !== "string" || !Object.hasOwn(fields, item.type)) throw new SparkError("E_INVALID_ARGUMENT", "Unknown toolbar item type");
132
+ keys(item, ["id", "label", "placement", "type", ...fields[item.type]]);
133
+ flags(item, ["disabled", "bordered", "monospacedDigits", "collapses"]);
134
+ enumValue(item.placement, ["leading", "trailing"], "toolbar placement");
135
+ for (const field of ["label", "symbol", "tooltip", "text", "placeholder"]) if (item[field] !== undefined) text(item[field], field);
136
+ if (item.width !== undefined) number(item.width, "toolbar width", 1, 20000);
137
+ if (item.type === "label") text(item.text, "toolbar text");
138
+ if (item.type === "search" && item.value !== undefined) text(item.value, "search value");
139
+ if (item.type === "menu") menuItems(item.items as never, { types: ["action", "checkbox", "separator", "slider"], icons: ["symbol"] }, "macos");
140
+ if (item.type === "segmented") {
141
+ if (!Array.isArray(item.segments) || !item.segments.length) throw new SparkError("E_INVALID_ARGUMENT", "Toolbar segments must be nonempty");
142
+ const values = new Set<string>();
143
+ for (const segment of item.segments) {
144
+ object(segment, "segment"); keys(segment, ["value", "label", "symbol"]); text(segment.value, "segment value"); text(segment.label, "segment label", false);
145
+ if (segment.symbol !== undefined) text(segment.symbol, "segment symbol", false);
146
+ if (values.has(segment.value)) throw new SparkError("E_INVALID_ARGUMENT", "Segment values must be unique"); values.add(segment.value);
147
+ }
148
+ if (item.value !== null && !values.has(item.value as string)) throw new SparkError("E_INVALID_ARGUMENT", "Unknown toolbar segment value");
149
+ }
150
+ }
151
+ }
152
+ if (value.startupSplitView !== undefined && value.startupSplitView !== null) {
153
+ const split = value.startupSplitView; object(split, "startupSplitView");
154
+ keys(split, ["sidebarWidth", "sidebarMinWidth", "contentMinWidth", "sidebarCollapsed", "appearance", "backgroundColor", "sidebarBackgroundColor", "contentTitlebarHeight"]);
155
+ for (const field of ["sidebarWidth", "sidebarMinWidth", "contentMinWidth"] as const) number(split[field], field, 0, 20000);
156
+ if (split.sidebarWidth < split.sidebarMinWidth && !split.sidebarCollapsed) throw new SparkError("E_INVALID_ARGUMENT", "Sidebar width is below its minimum");
157
+ if (split.contentTitlebarHeight !== undefined) number(split.contentTitlebarHeight, "contentTitlebarHeight", 0, 20000);
158
+ flags(split, ["sidebarCollapsed"]);
159
+ if (!["light", "dark"].includes(split.appearance)) throw new SparkError("E_INVALID_ARGUMENT", "Startup split view requires light or dark appearance");
160
+ color(split.backgroundColor); color(split.sidebarBackgroundColor);
161
+ }
162
+ }
@@ -0,0 +1,28 @@
1
+ import type { TurboModule } from "react-native";
2
+ import { TurboModuleRegistry } from "react-native";
3
+
4
+ export interface Spec extends TurboModule {
5
+ getConstantsJson(): string;
6
+ getReactNativeStartupTimingJson(): string;
7
+ getDisplays(): Promise<string>;
8
+ openWindow(optionsJson: string): Promise<string>;
9
+ finishWindowRestoration(): Promise<string>;
10
+ closeWindow(identifier: string): Promise<string>;
11
+ closeFrontmostWindow(): Promise<string>;
12
+ hideMainWindow(): Promise<string>;
13
+ showWindow(identifier: string): Promise<string>;
14
+ showMainWindow(): Promise<string>;
15
+ setMainWindowOptions(optionsJson: string): Promise<string>;
16
+ setWindowOptions(identifier: string, optionsJson: string): Promise<string>;
17
+ getMainWindowFrame(): Promise<string>;
18
+ setMainWindowFrame(frameJson: string): Promise<string>;
19
+ setWindowBlur(identifier: string, radius: number, durationMs: number): Promise<string>;
20
+ setWindowTitle(identifier: string, title: string): Promise<string>;
21
+ setWindowToolbarItemText(identifier: string, itemId: string, text: string): Promise<string>;
22
+ setPreventDisplaySleep(enabled: boolean): Promise<string>;
23
+ focusToolbarSearchItem(identifier: string, itemId: string, value: string | null): Promise<string>;
24
+ addListener(eventName: string): void;
25
+ removeListeners(count: number): void;
26
+ }
27
+
28
+ export default TurboModuleRegistry.get<Spec>("NativeWindowManager");
@@ -0,0 +1,20 @@
1
+ import type { ComponentType, ReactNode } from "react";
2
+ import { createContext, useContext } from "react";
3
+ import { SparkError } from "@legendapp/spark-desktop-app/src/contracts";
4
+ import { windowId } from "../validation";
5
+ const WindowContext = createContext<string | null>(null);
6
+ export function useWindowId(): string {
7
+ const id = useContext(WindowContext);
8
+ if (id === null) throw new SparkError("E_UNAVAILABLE", "useWindowId requires a WindowProvider for this React root");
9
+ return id;
10
+ }
11
+ export interface WindowProviderProps { children: ReactNode; id: string }
12
+ export function WindowProvider({ children, id }: WindowProviderProps) {
13
+ windowId(id); return <WindowContext.Provider value={id}>{children}</WindowContext.Provider>;
14
+ }
15
+ export function withWindowProvider<P extends object>(Component: ComponentType<P>, id: string): ComponentType<P> {
16
+ windowId(id);
17
+ const Wrapped = (props: P) => <WindowProvider id={id}><Component {...props} /></WindowProvider>;
18
+ Wrapped.displayName = `Window(${id})`;
19
+ return Wrapped;
20
+ }
@@ -0,0 +1,78 @@
1
+ import type { ComponentType } from "react";
2
+ import { lazy, Suspense } from "react";
3
+ import { AppRegistry } from "react-native";
4
+ import { SparkError } from "@legendapp/spark-desktop-app/src/contracts";
5
+ import { openWindow, closeWindow, showWindow } from "../api";
6
+ import type { CloseResult, WindowInfo, WindowOpenOptions } from "../types";
7
+ import { keys, object, validateOptions, windowId } from "../validation";
8
+ import { Platform } from "react-native";
9
+ import type { NavigatorWindowOptions, WindowsConfig, WindowComponentProps } from "./types";
10
+ import { withWindowProvider } from "./WindowProvider";
11
+ export type NavigatorOpenOptions<P> = { props: P; options?: NavigatorWindowOptions };
12
+ type OpenArguments<P> = {} extends P ? [options?: { props?: P; options?: NavigatorWindowOptions }] : [options: NavigatorOpenOptions<P>];
13
+ export interface WindowsNavigator<T extends WindowsConfig> {
14
+ open<K extends keyof T>(name: K, ...args: OpenArguments<WindowComponentProps<T[K]>>): Promise<WindowInfo>;
15
+ close(name: keyof T): Promise<CloseResult>;
16
+ show(name: keyof T): Promise<void>;
17
+ getId(name: keyof T): string;
18
+ prefetch(name: keyof T): Promise<void>;
19
+ }
20
+ const registrations = new Set<string>();
21
+ function component(value: unknown): value is ComponentType<any> {
22
+ return typeof value === "function" || (!!value && typeof value === "object" && [Symbol.for("react.memo"), Symbol.for("react.forward_ref"), Symbol.for("react.lazy")].includes((value as any).$$typeof));
23
+ }
24
+ export function createWindowsNavigator<T extends WindowsConfig>(config: T): WindowsNavigator<T> {
25
+ object(config, "navigator configuration");
26
+ const ids = new Set<string>();
27
+ for (const entry of Object.values(config)) {
28
+ object(entry, "window registration"); keys(entry, ["id", "component", "loadComponent", "options"]); windowId(entry.id);
29
+ if (entry.id === "main" || ids.has(entry.id) || registrations.has(entry.id)) throw new SparkError("E_ALREADY_EXISTS", "Window ID is already registered or reserved");
30
+ ids.add(entry.id);
31
+ if ((entry.component !== undefined) === (entry.loadComponent !== undefined) || (entry.component !== undefined && !component(entry.component)) || (entry.loadComponent !== undefined && typeof entry.loadComponent !== "function")) throw new SparkError("E_INVALID_ARGUMENT", "Register exactly one component or loadComponent");
32
+ if (entry.options) {
33
+ object(entry.options, "registration options");
34
+ for (const key of ["id", "component", "props"]) if (key in entry.options) throw new SparkError("E_INVALID_ARGUMENT", "Navigator identity and props cannot be overridden in options");
35
+ validateOptions({ ...entry.options, id: entry.id, component: "registration" } as WindowOpenOptions, Platform.OS, true);
36
+ }
37
+ }
38
+ const registry = new Map<keyof T, { id: string; moduleName: string; options: NavigatorWindowOptions; load(): Promise<void> }>();
39
+ for (const name of Object.keys(config) as (keyof T)[]) {
40
+ const entry = config[name], id = entry.id, moduleName = `spark.window.${id}`;
41
+ let resolved: ComponentType<any> | undefined = entry.component ? withWindowProvider(entry.component, id) : undefined;
42
+ let pending: Promise<void> | undefined;
43
+ const load = async () => {
44
+ if (resolved) return;
45
+ if (!pending) pending = Promise.resolve().then(() => entry.loadComponent!()).then(value => {
46
+ const result = value && typeof value === "object" && "default" in value ? value.default : value;
47
+ if (!component(result)) throw new SparkError("E_INVALID_DATA", "Window loader did not return a React component");
48
+ resolved = withWindowProvider(result, id);
49
+ }).catch(cause => { pending = undefined; throw cause; });
50
+ await pending;
51
+ };
52
+ // Native surfaces restart on reload before the app can call open or prefetch.
53
+ const LoadedWindow = lazy(async () => { await load(); return { default: resolved! }; });
54
+ const RestartedWindow = (props: any) => <Suspense fallback={null}><LoadedWindow {...props} /></Suspense>;
55
+ AppRegistry.registerComponent(moduleName, () => resolved ?? RestartedWindow);
56
+ registrations.add(id);
57
+ registry.set(name, { id, moduleName, options: JSON.parse(JSON.stringify(entry.options ?? {})), load });
58
+ }
59
+ const get = (name: keyof T) => {
60
+ const value = registry.get(name); if (!value) throw new SparkError("E_NOT_FOUND", `Unknown window: ${String(name)}`); return value;
61
+ };
62
+ return {
63
+ async open(name, ...args) {
64
+ const registration = get(name), request = args[0] ?? {};
65
+ object(request, "open request"); keys(request, ["props", "options"]);
66
+ if (request.options) { object(request.options, "open options"); for (const key of ["id", "component", "props"]) if (key in request.options) throw new SparkError("E_INVALID_ARGUMENT", "Navigator identity and props cannot be overridden in options"); }
67
+ const options = { ...registration.options, ...request.options, id: registration.id, component: registration.moduleName, props: request.props } as WindowOpenOptions;
68
+ validateOptions(options, Platform.OS, true);
69
+ const snapshot = JSON.parse(JSON.stringify(options));
70
+ // Always load before native creation. Failed loaders remain retryable and leave no native shell.
71
+ await registration.load(); return openWindow(snapshot);
72
+ },
73
+ async close(name) { return closeWindow(get(name).id); },
74
+ async show(name) { await showWindow(get(name).id); },
75
+ getId(name) { return get(name).id; },
76
+ async prefetch(name) { await get(name).load(); },
77
+ };
78
+ }
@@ -0,0 +1,6 @@
1
+ export { createWindowsNavigator, type WindowsNavigator, type NavigatorOpenOptions } from "./createWindowsNavigator";
2
+ export type { WindowConfigEntry, WindowsConfig, WindowComponentLoader, NavigatorWindowOptions, WindowComponentProps } from "./types";
3
+ export { useWindowFocusEffect, type WindowHookOptions } from "./useWindowFocusEffect";
4
+ export { usePrimaryWindowLifecycle, type UsePrimaryWindowLifecycleOptions } from "./usePrimaryWindowLifecycle";
5
+ export { useWindowId, WindowProvider, withWindowProvider, type WindowProviderProps } from "./WindowProvider";
6
+ export { createPrimaryWindowLifecycle, type PrimaryWindowLifecycleOptions } from "./primaryWindowLifecycle";
@@ -0,0 +1,34 @@
1
+ import { addAppListener } from "@legendapp/spark-desktop-app";
2
+ import { SparkError, nativeError, type Subscription } from "@legendapp/spark-desktop-app/src/contracts";
3
+
4
+ export interface PrimaryWindowLifecycleOptions {
5
+ windowId: string;
6
+ onInitialOpen: () => void | Promise<void>;
7
+ onReopenRequested?: () => void | Promise<void>;
8
+ onWindowClosed?: () => void;
9
+ onError: (error: SparkError) => void;
10
+ }
11
+
12
+ /** Owns application events for one logical window, including reopened instances. */
13
+ export function createPrimaryWindowLifecycle(options: PrimaryWindowLifecycleOptions): Subscription {
14
+ const { windowId, onInitialOpen, onReopenRequested, onWindowClosed, onError } = options;
15
+ if (typeof windowId !== "string" || !/^[a-zA-Z0-9_-]{1,100}$/.test(windowId)) {
16
+ throw new SparkError("E_INVALID_ARGUMENT", "Expected a window ID");
17
+ }
18
+ let active = true;
19
+ const run = (action: (() => void | Promise<void>) | undefined) => {
20
+ if (active && action) void Promise.resolve().then(() => { if (active) return action(); })
21
+ .catch(cause => onError(nativeError(cause)));
22
+ };
23
+ const reopened = addAppListener("reopen", event => { if (!event.hasVisibleWindows) run(onReopenRequested); });
24
+ let closed: Subscription;
25
+ try {
26
+ closed = addAppListener("windowClosed", event => {
27
+ if (active && event.windowId === windowId && onWindowClosed) {
28
+ try { onWindowClosed(); } catch (cause) { onError(nativeError(cause)); }
29
+ }
30
+ });
31
+ } catch (error) { active = false; reopened.remove(); throw error; }
32
+ run(onInitialOpen);
33
+ return { remove() { active = false; reopened.remove(); closed.remove(); } };
34
+ }
@@ -0,0 +1,11 @@
1
+ import type { ComponentType } from "react";
2
+ import type { WindowOpenOptions } from "../types";
3
+ export type WindowComponentLoader<P = Record<string, never>> = () => ComponentType<P> | { default: ComponentType<P> } | Promise<ComponentType<P> | { default: ComponentType<P> }>;
4
+ type WithoutIdentity<T> = T extends unknown ? Omit<T, "id" | "component" | "props"> : never;
5
+ export type NavigatorWindowOptions = WithoutIdentity<WindowOpenOptions>;
6
+ export type WindowConfigEntry<P = any> = { id: string; options?: NavigatorWindowOptions } & (
7
+ | { component: ComponentType<P>; loadComponent?: never }
8
+ | { component?: never; loadComponent: WindowComponentLoader<P> }
9
+ );
10
+ export type WindowsConfig = Record<string, WindowConfigEntry>;
11
+ export type WindowComponentProps<T> = T extends { component: ComponentType<infer P> } ? P : T extends { loadComponent: WindowComponentLoader<infer P> } ? P : never;
@@ -0,0 +1,18 @@
1
+ import { useEffect, useLayoutEffect, useRef } from "react";
2
+ import { createPrimaryWindowLifecycle, type PrimaryWindowLifecycleOptions } from "./primaryWindowLifecycle";
3
+ export type UsePrimaryWindowLifecycleOptions = PrimaryWindowLifecycleOptions;
4
+
5
+ export function usePrimaryWindowLifecycle(options: UsePrimaryWindowLifecycleOptions): void {
6
+ const latest = useRef(options);
7
+ useLayoutEffect(() => { latest.current = options; });
8
+ useEffect(() => {
9
+ const registration = createPrimaryWindowLifecycle({
10
+ windowId: options.windowId,
11
+ onInitialOpen: () => latest.current.onInitialOpen(),
12
+ onReopenRequested: () => latest.current.onReopenRequested?.(),
13
+ onWindowClosed: () => latest.current.onWindowClosed?.(),
14
+ onError: error => latest.current.onError(error),
15
+ });
16
+ return () => registration.remove();
17
+ }, [options.windowId]);
18
+ }
@@ -0,0 +1,17 @@
1
+ import { useEffect, useLayoutEffect, useRef } from "react";
2
+ import { nativeError, type AsyncRegistration, type SparkError } from "@legendapp/spark-desktop-app/src/contracts";
3
+ import { addWindowListener } from "../api";
4
+ import { useWindowId } from "./WindowProvider";
5
+ export interface WindowHookOptions { onError?: (error: SparkError) => void }
6
+ export function useWindowFocusEffect(callback: () => void, options: WindowHookOptions = {}) {
7
+ const id = useWindowId(), latest = useRef({ callback, onError: options.onError });
8
+ useLayoutEffect(() => { latest.current = { callback, onError: options.onError }; }, [callback, options.onError]);
9
+ useEffect(() => {
10
+ let disposed = false, registration: AsyncRegistration | undefined;
11
+ const report = (cause: unknown) => { if (latest.current.onError) latest.current.onError(nativeError(cause)); else console.error(cause); };
12
+ void addWindowListener(id, "focusChanged", event => { if (!disposed && event.focused) latest.current.callback(); }, { onError: report }).then(value => {
13
+ if (disposed) void value.remove().catch(report); else registration = value;
14
+ }).catch(report);
15
+ return () => { disposed = true; void registration?.remove().catch(report); };
16
+ }, [id]);
17
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@legendapp/spark-documents",
3
+ "version": "0.0.1-next.4",
4
+ "private": true,
5
+ "license": "MIT",
6
+ "main": "src/index.tsx",
7
+ "files": [
8
+ "src"
9
+ ],
10
+ "dependencies": {
11
+ "@legendapp/spark-file-dialog": "0.0.1-next.4",
12
+ "@legendapp/spark-file-system": "0.0.1-next.4",
13
+ "@legendapp/spark-native-menu": "0.0.1-next.4",
14
+ "@legendapp/spark-desktop-app": "0.0.1-next.4",
15
+ "@legendapp/spark-desktop-windows": "0.0.1-next.4",
16
+ "@legendapp/spark-desktop-links": "0.0.1-next.4"
17
+ },
18
+ "peerDependencies": {
19
+ "react": "19.1.4",
20
+ "react-native": "0.81.6"
21
+ }
22
+ }