pythonnative 0.40.0__cp313-cp313-win_amd64.whl

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 (418) hide show
  1. pythonnative/__init__.py +411 -0
  2. pythonnative/_ios_log.py +92 -0
  3. pythonnative/_yoga.cp313-win_amd64.pyd +0 -0
  4. pythonnative/alerts.py +236 -0
  5. pythonnative/animated.py +1687 -0
  6. pythonnative/animation_graph.py +78 -0
  7. pythonnative/appearance.py +124 -0
  8. pythonnative/bootstrap.py +100 -0
  9. pythonnative/bridge/__init__.py +302 -0
  10. pythonnative/bridge/android.py +78 -0
  11. pythonnative/bridge/codec.py +170 -0
  12. pythonnative/bridge/commits.py +114 -0
  13. pythonnative/bridge/fake.py +243 -0
  14. pythonnative/bridge/ios.py +138 -0
  15. pythonnative/bridge/web.py +489 -0
  16. pythonnative/cli/__init__.py +7 -0
  17. pythonnative/cli/pn.py +1214 -0
  18. pythonnative/component.py +271 -0
  19. pythonnative/components/__init__.py +111 -0
  20. pythonnative/components/_base.py +166 -0
  21. pythonnative/components/controls.py +521 -0
  22. pythonnative/components/layout.py +518 -0
  23. pythonnative/components/lists.py +785 -0
  24. pythonnative/components/media.py +204 -0
  25. pythonnative/components/overlays.py +107 -0
  26. pythonnative/components/pressable.py +252 -0
  27. pythonnative/components/structural.py +167 -0
  28. pythonnative/components/text.py +291 -0
  29. pythonnative/devclient.py +824 -0
  30. pythonnative/devserver/__init__.py +34 -0
  31. pythonnative/devserver/server.py +718 -0
  32. pythonnative/devserver/static/animation_graph.js +82 -0
  33. pythonnative/devserver/static/bridge.js +147 -0
  34. pythonnative/devserver/static/colors.js +70 -0
  35. pythonnative/devserver/static/host.js +552 -0
  36. pythonnative/devserver/static/index.html +60 -0
  37. pythonnative/devserver/static/layout.js +85 -0
  38. pythonnative/devserver/static/preview.css +415 -0
  39. pythonnative/devserver/static/renderer.js +1994 -0
  40. pythonnative/devserver/static/shell.js +345 -0
  41. pythonnative/devserver/static/yoga/LICENSE +21 -0
  42. pythonnative/devserver/static/yoga/binaries/yoga-wasm-base64-esm.js +75 -0
  43. pythonnative/devserver/static/yoga/src/generated/YGEnums.d.ts +189 -0
  44. pythonnative/devserver/static/yoga/src/generated/YGEnums.js +211 -0
  45. pythonnative/devserver/static/yoga/src/generated/YGEnums.js.map +1 -0
  46. pythonnative/devserver/static/yoga/src/index.d.ts +12 -0
  47. pythonnative/devserver/static/yoga/src/index.js +16 -0
  48. pythonnative/devserver/static/yoga/src/index.js.map +1 -0
  49. pythonnative/devserver/static/yoga/src/load.d.ts +11 -0
  50. pythonnative/devserver/static/yoga/src/load.js +17 -0
  51. pythonnative/devserver/static/yoga/src/load.js.map +1 -0
  52. pythonnative/devserver/static/yoga/src/wrapAssembly.d.ts +155 -0
  53. pythonnative/devserver/static/yoga/src/wrapAssembly.js +125 -0
  54. pythonnative/devserver/static/yoga/src/wrapAssembly.js.map +1 -0
  55. pythonnative/devserver/watcher.py +267 -0
  56. pythonnative/devserver/ws.py +421 -0
  57. pythonnative/diagnostics.py +241 -0
  58. pythonnative/element.py +159 -0
  59. pythonnative/equality.py +19 -0
  60. pythonnative/events.py +231 -0
  61. pythonnative/gestures.py +1333 -0
  62. pythonnative/hooks.py +1621 -0
  63. pythonnative/hosts/__init__.py +63 -0
  64. pythonnative/hosts/base.py +596 -0
  65. pythonnative/hosts/native.py +302 -0
  66. pythonnative/hot_reload.py +585 -0
  67. pythonnative/layout.py +328 -0
  68. pythonnative/mutations.py +142 -0
  69. pythonnative/native/android/build.gradle +52 -0
  70. pythonnative/native/android/gradle.properties +3 -0
  71. pythonnative/native/android/settings.gradle +12 -0
  72. pythonnative/native/android/src/main/AndroidManifest.xml +11 -0
  73. pythonnative/native/android/src/main/cpp/CMakeLists.txt +9 -0
  74. pythonnative/native/android/src/main/cpp/yoga_jni.cpp +52 -0
  75. pythonnative/native/android/src/main/java/com/pythonnative/generated/NativeModules.kt +5 -0
  76. pythonnative/native/android/src/main/java/com/pythonnative/generated/NativeProps.kt +3705 -0
  77. pythonnative/native/android/src/main/java/com/pythonnative/generated/PNContracts.kt +129 -0
  78. pythonnative/native/android/src/main/java/com/pythonnative/runtime/PNBridge.kt +261 -0
  79. pythonnative/native/android/src/main/java/com/pythonnative/runtime/PythonHost.kt +20 -0
  80. pythonnative/native/android/src/main/java/com/pythonnative/runtime/animation/AnimationGraph.kt +108 -0
  81. pythonnative/native/android/src/main/java/com/pythonnative/runtime/animation/AnimationSpecs.kt +141 -0
  82. pythonnative/native/android/src/main/java/com/pythonnative/runtime/animation/PNAnimator.kt +257 -0
  83. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/CommitState.kt +106 -0
  84. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/JsonUtil.kt +175 -0
  85. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/MainThread.kt +40 -0
  86. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/PNLog.kt +33 -0
  87. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/PNRegistry.kt +82 -0
  88. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/PNTransaction.kt +80 -0
  89. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/TransactionApplier.kt +117 -0
  90. pythonnative/native/android/src/main/java/com/pythonnative/runtime/bridge/ViewRegistry.kt +74 -0
  91. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/BuiltinComponents.kt +37 -0
  92. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ButtonManager.kt +32 -0
  93. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ComponentManager.kt +213 -0
  94. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ContainerManagers.kt +69 -0
  95. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ControlManagers.kt +186 -0
  96. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/DatePickerManager.kt +123 -0
  97. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ImageLoader.kt +141 -0
  98. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ImageManager.kt +162 -0
  99. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ModalManager.kt +134 -0
  100. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PNColor.kt +201 -0
  101. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PickerManager.kt +86 -0
  102. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PortalManager.kt +55 -0
  103. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/PressableManager.kt +122 -0
  104. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ScreenStackManager.kt +110 -0
  105. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ScrollViewManager.kt +214 -0
  106. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/SegmentedControlManager.kt +113 -0
  107. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/StatusBarManager.kt +52 -0
  108. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/TabBarManager.kt +131 -0
  109. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/TextInputManager.kt +250 -0
  110. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/TextManager.kt +233 -0
  111. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/ViewStyler.kt +355 -0
  112. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/VirtualListManager.kt +159 -0
  113. pythonnative/native/android/src/main/java/com/pythonnative/runtime/components/WebViewManager.kt +149 -0
  114. pythonnative/native/android/src/main/java/com/pythonnative/runtime/gestures/GestureArbiter.kt +233 -0
  115. pythonnative/native/android/src/main/java/com/pythonnative/runtime/gestures/GestureCoordinator.kt +127 -0
  116. pythonnative/native/android/src/main/java/com/pythonnative/runtime/gestures/GestureRecognizers.kt +527 -0
  117. pythonnative/native/android/src/main/java/com/pythonnative/runtime/layout/NativeLayout.kt +145 -0
  118. pythonnative/native/android/src/main/java/com/pythonnative/runtime/layout/YogaNode.kt +29 -0
  119. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/BuiltinModules.kt +73 -0
  120. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/DeviceModules.kt +316 -0
  121. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/HostModule.kt +61 -0
  122. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/MediaModules.kt +200 -0
  123. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/NativeModule.kt +158 -0
  124. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/NotificationsModule.kt +100 -0
  125. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/PermissionsModule.kt +99 -0
  126. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/StorageModules.kt +89 -0
  127. pythonnative/native/android/src/main/java/com/pythonnative/runtime/modules/SystemModules.kt +178 -0
  128. pythonnative/native/android/src/main/java/com/pythonnative/runtime/plugins/GeneratedPlugins.kt +16 -0
  129. pythonnative/native/android/src/main/java/com/pythonnative/runtime/screens/PNScreenFragment.kt +188 -0
  130. pythonnative/native/android/src/main/java/com/pythonnative/runtime/screens/ScreenRegistry.kt +80 -0
  131. pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNAccessibilityDelegate.kt +48 -0
  132. pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNBorderDrawable.kt +76 -0
  133. pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNEditText.kt +18 -0
  134. pythonnative/native/android/src/main/java/com/pythonnative/runtime/views/PNFrameLayout.kt +49 -0
  135. pythonnative/native/android/src/test/java/com/pythonnative/runtime/AnimationSpecsTest.kt +75 -0
  136. pythonnative/native/android/src/test/java/com/pythonnative/runtime/GestureArbiterTest.kt +197 -0
  137. pythonnative/native/android/src/test/java/com/pythonnative/runtime/PNColorTest.kt +47 -0
  138. pythonnative/native/android/src/test/java/com/pythonnative/runtime/PNTransactionTest.kt +78 -0
  139. pythonnative/native/android/src/test/java/com/pythonnative/runtime/PromiseTest.kt +89 -0
  140. pythonnative/native/ios/Package.swift +23 -0
  141. pythonnative/native/ios/Sources/PythonNativeKit/Animation/PNAnimationGraph.swift +199 -0
  142. pythonnative/native/ios/Sources/PythonNativeKit/Animation/PNAnimator.swift +312 -0
  143. pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNBridge.swift +255 -0
  144. pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNCommit.swift +104 -0
  145. pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNRegistry.swift +142 -0
  146. pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNTransaction.swift +166 -0
  147. pythonnative/native/ios/Sources/PythonNativeKit/Bridge/PNViewRegistry.swift +53 -0
  148. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNButtonManagers.swift +207 -0
  149. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNColor.swift +173 -0
  150. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNComponentManager.swift +183 -0
  151. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNContainerView.swift +56 -0
  152. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNControlManagers.swift +281 -0
  153. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNImageManager.swift +222 -0
  154. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNOverlayManagers.swift +243 -0
  155. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNPressableManager.swift +114 -0
  156. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNScreenStackManager.swift +107 -0
  157. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNScrollViewManager.swift +197 -0
  158. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTabBarManager.swift +106 -0
  159. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTextInputManager.swift +297 -0
  160. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTextManager.swift +230 -0
  161. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNTransform.swift +82 -0
  162. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNViewManager.swift +86 -0
  163. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNViewState.swift +87 -0
  164. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNViewStyler.swift +340 -0
  165. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNVirtualListManager.swift +155 -0
  166. pythonnative/native/ios/Sources/PythonNativeKit/Components/PNWebViewManager.swift +124 -0
  167. pythonnative/native/ios/Sources/PythonNativeKit/Generated/NativeModules.swift +1 -0
  168. pythonnative/native/ios/Sources/PythonNativeKit/Generated/NativeProps.swift +3775 -0
  169. pythonnative/native/ios/Sources/PythonNativeKit/Generated/PNContracts.swift +46 -0
  170. pythonnative/native/ios/Sources/PythonNativeKit/Gestures/PNGestureCoordinator.swift +260 -0
  171. pythonnative/native/ios/Sources/PythonNativeKit/Layout/PNLayout.swift +173 -0
  172. pythonnative/native/ios/Sources/PythonNativeKit/Modules/AlertModule.swift +92 -0
  173. pythonnative/native/ios/Sources/PythonNativeKit/Modules/HostModule.swift +80 -0
  174. pythonnative/native/ios/Sources/PythonNativeKit/Modules/LifecycleModules.swift +174 -0
  175. pythonnative/native/ios/Sources/PythonNativeKit/Modules/MediaModules.swift +177 -0
  176. pythonnative/native/ios/Sources/PythonNativeKit/Modules/PNNativeModule.swift +168 -0
  177. pythonnative/native/ios/Sources/PythonNativeKit/Modules/PermissionModules.swift +266 -0
  178. pythonnative/native/ios/Sources/PythonNativeKit/Modules/SystemModules.swift +251 -0
  179. pythonnative/native/ios/Sources/PythonNativeKit/Plugins/PNPluginRegistration.swift +8 -0
  180. pythonnative/native/ios/Sources/PythonNativeKit/Screens/PNScreenRegistry.swift +46 -0
  181. pythonnative/native/ios/Sources/PythonNativeKit/Screens/PNViewController.swift +237 -0
  182. pythonnative/native/ios/Sources/PythonNativeKit/Support/PNCompat.swift +46 -0
  183. pythonnative/native/ios/Sources/PythonNativeKit/Support/PNJSON.swift +173 -0
  184. pythonnative/native/ios/Sources/PythonNativeKit/Support/PNLog.swift +47 -0
  185. pythonnative/native/ios/Sources/PythonNativeKit/Support/PNWindow.swift +51 -0
  186. pythonnative/native/ios/Tests/PythonNativeKitTests/PNAnimationGraphTests.swift +26 -0
  187. pythonnative/native/ios/Tests/PythonNativeKitTests/PNColorTests.swift +50 -0
  188. pythonnative/native/ios/Tests/PythonNativeKitTests/PNCommitTests.swift +86 -0
  189. pythonnative/native/ios/Tests/PythonNativeKitTests/PNGestureTests.swift +101 -0
  190. pythonnative/native/ios/Tests/PythonNativeKitTests/PNManagerTests.swift +126 -0
  191. pythonnative/native/ios/Tests/PythonNativeKitTests/PNModuleTests.swift +111 -0
  192. pythonnative/native/ios/Tests/PythonNativeKitTests/PNTransactionTests.swift +91 -0
  193. pythonnative/native/yoga/LICENSE +21 -0
  194. pythonnative/native/yoga/Package.swift +9 -0
  195. pythonnative/native/yoga/VENDORED.md +2 -0
  196. pythonnative/native/yoga/include/PNStyle.h +10 -0
  197. pythonnative/native/yoga/include/module.modulemap +5 -0
  198. pythonnative/native/yoga/include/yoga/YGConfig.h +158 -0
  199. pythonnative/native/yoga/include/yoga/YGEnums.h +142 -0
  200. pythonnative/native/yoga/include/yoga/YGMacros.h +99 -0
  201. pythonnative/native/yoga/include/yoga/YGNode.h +304 -0
  202. pythonnative/native/yoga/include/yoga/YGNodeLayout.h +35 -0
  203. pythonnative/native/yoga/include/yoga/YGNodeStyle.h +130 -0
  204. pythonnative/native/yoga/include/yoga/YGPixelGrid.h +29 -0
  205. pythonnative/native/yoga/include/yoga/YGValue.h +84 -0
  206. pythonnative/native/yoga/include/yoga/Yoga.h +21 -0
  207. pythonnative/native/yoga/python.cpp +16 -0
  208. pythonnative/native/yoga/style.cpp +272 -0
  209. pythonnative/native/yoga/yoga/CMakeLists.txt +41 -0
  210. pythonnative/native/yoga/yoga/YGConfig.cpp +92 -0
  211. pythonnative/native/yoga/yoga/YGConfig.h +158 -0
  212. pythonnative/native/yoga/yoga/YGEnums.cpp +262 -0
  213. pythonnative/native/yoga/yoga/YGEnums.h +142 -0
  214. pythonnative/native/yoga/yoga/YGMacros.h +99 -0
  215. pythonnative/native/yoga/yoga/YGNode.cpp +366 -0
  216. pythonnative/native/yoga/yoga/YGNode.h +304 -0
  217. pythonnative/native/yoga/yoga/YGNodeLayout.cpp +92 -0
  218. pythonnative/native/yoga/yoga/YGNodeLayout.h +35 -0
  219. pythonnative/native/yoga/yoga/YGNodeStyle.cpp +405 -0
  220. pythonnative/native/yoga/yoga/YGNodeStyle.h +130 -0
  221. pythonnative/native/yoga/yoga/YGPixelGrid.cpp +22 -0
  222. pythonnative/native/yoga/yoga/YGPixelGrid.h +29 -0
  223. pythonnative/native/yoga/yoga/YGValue.cpp +20 -0
  224. pythonnative/native/yoga/yoga/YGValue.h +84 -0
  225. pythonnative/native/yoga/yoga/Yoga.h +21 -0
  226. pythonnative/native/yoga/yoga/algorithm/AbsoluteLayout.cpp +563 -0
  227. pythonnative/native/yoga/yoga/algorithm/AbsoluteLayout.h +41 -0
  228. pythonnative/native/yoga/yoga/algorithm/Align.h +72 -0
  229. pythonnative/native/yoga/yoga/algorithm/Baseline.cpp +78 -0
  230. pythonnative/native/yoga/yoga/algorithm/Baseline.h +21 -0
  231. pythonnative/native/yoga/yoga/algorithm/BoundAxis.h +79 -0
  232. pythonnative/native/yoga/yoga/algorithm/Cache.cpp +121 -0
  233. pythonnative/native/yoga/yoga/algorithm/Cache.h +30 -0
  234. pythonnative/native/yoga/yoga/algorithm/CalculateLayout.cpp +2428 -0
  235. pythonnative/native/yoga/yoga/algorithm/CalculateLayout.h +38 -0
  236. pythonnative/native/yoga/yoga/algorithm/FlexDirection.h +120 -0
  237. pythonnative/native/yoga/yoga/algorithm/FlexLine.cpp +124 -0
  238. pythonnative/native/yoga/yoga/algorithm/FlexLine.h +75 -0
  239. pythonnative/native/yoga/yoga/algorithm/PixelGrid.cpp +132 -0
  240. pythonnative/native/yoga/yoga/algorithm/PixelGrid.h +29 -0
  241. pythonnative/native/yoga/yoga/algorithm/SizingMode.h +73 -0
  242. pythonnative/native/yoga/yoga/algorithm/TrailingPosition.h +44 -0
  243. pythonnative/native/yoga/yoga/config/Config.cpp +135 -0
  244. pythonnative/native/yoga/yoga/config/Config.h +92 -0
  245. pythonnative/native/yoga/yoga/debug/AssertFatal.cpp +53 -0
  246. pythonnative/native/yoga/yoga/debug/AssertFatal.h +29 -0
  247. pythonnative/native/yoga/yoga/debug/Log.cpp +107 -0
  248. pythonnative/native/yoga/yoga/debug/Log.h +34 -0
  249. pythonnative/native/yoga/yoga/enums/Align.h +47 -0
  250. pythonnative/native/yoga/yoga/enums/BoxSizing.h +40 -0
  251. pythonnative/native/yoga/yoga/enums/Dimension.h +40 -0
  252. pythonnative/native/yoga/yoga/enums/Direction.h +41 -0
  253. pythonnative/native/yoga/yoga/enums/Display.h +41 -0
  254. pythonnative/native/yoga/yoga/enums/Edge.h +47 -0
  255. pythonnative/native/yoga/yoga/enums/Errata.h +41 -0
  256. pythonnative/native/yoga/yoga/enums/ExperimentalFeature.h +39 -0
  257. pythonnative/native/yoga/yoga/enums/FlexDirection.h +42 -0
  258. pythonnative/native/yoga/yoga/enums/Gutter.h +41 -0
  259. pythonnative/native/yoga/yoga/enums/Justify.h +44 -0
  260. pythonnative/native/yoga/yoga/enums/LogLevel.h +44 -0
  261. pythonnative/native/yoga/yoga/enums/MeasureMode.h +41 -0
  262. pythonnative/native/yoga/yoga/enums/NodeType.h +40 -0
  263. pythonnative/native/yoga/yoga/enums/Overflow.h +41 -0
  264. pythonnative/native/yoga/yoga/enums/PhysicalEdge.h +21 -0
  265. pythonnative/native/yoga/yoga/enums/PositionType.h +41 -0
  266. pythonnative/native/yoga/yoga/enums/Unit.h +42 -0
  267. pythonnative/native/yoga/yoga/enums/Wrap.h +41 -0
  268. pythonnative/native/yoga/yoga/enums/YogaEnums.h +85 -0
  269. pythonnative/native/yoga/yoga/event/event.cpp +87 -0
  270. pythonnative/native/yoga/yoga/event/event.h +130 -0
  271. pythonnative/native/yoga/yoga/module.modulemap +21 -0
  272. pythonnative/native/yoga/yoga/node/CachedMeasurement.h +53 -0
  273. pythonnative/native/yoga/yoga/node/LayoutResults.cpp +48 -0
  274. pythonnative/native/yoga/yoga/node/LayoutResults.h +122 -0
  275. pythonnative/native/yoga/yoga/node/LayoutableChildren.h +148 -0
  276. pythonnative/native/yoga/yoga/node/Node.cpp +443 -0
  277. pythonnative/native/yoga/yoga/node/Node.h +337 -0
  278. pythonnative/native/yoga/yoga/numeric/Comparison.h +81 -0
  279. pythonnative/native/yoga/yoga/numeric/FloatOptional.h +93 -0
  280. pythonnative/native/yoga/yoga/style/SmallValueBuffer.h +133 -0
  281. pythonnative/native/yoga/yoga/style/Style.h +757 -0
  282. pythonnative/native/yoga/yoga/style/StyleLength.h +107 -0
  283. pythonnative/native/yoga/yoga/style/StyleValueHandle.h +98 -0
  284. pythonnative/native/yoga/yoga/style/StyleValuePool.h +127 -0
  285. pythonnative/native_modules/__init__.py +124 -0
  286. pythonnative/native_modules/app_state.py +99 -0
  287. pythonnative/native_modules/battery.py +75 -0
  288. pythonnative/native_modules/biometrics.py +42 -0
  289. pythonnative/native_modules/camera.py +65 -0
  290. pythonnative/native_modules/clipboard.py +46 -0
  291. pythonnative/native_modules/fallback.py +324 -0
  292. pythonnative/native_modules/file_system.py +145 -0
  293. pythonnative/native_modules/haptics.py +75 -0
  294. pythonnative/native_modules/linking.py +123 -0
  295. pythonnative/native_modules/location.py +75 -0
  296. pythonnative/native_modules/net_info.py +112 -0
  297. pythonnative/native_modules/notifications.py +129 -0
  298. pythonnative/native_modules/permissions.py +108 -0
  299. pythonnative/native_modules/registry.py +526 -0
  300. pythonnative/native_modules/secure_store.py +52 -0
  301. pythonnative/native_modules/share.py +51 -0
  302. pythonnative/native_views/__init__.py +375 -0
  303. pythonnative/native_views/base.py +316 -0
  304. pythonnative/native_views/bridge_backend.py +277 -0
  305. pythonnative/navigation/__init__.py +103 -0
  306. pythonnative/navigation/container.py +154 -0
  307. pythonnative/navigation/handle.py +540 -0
  308. pythonnative/navigation/hooks.py +133 -0
  309. pythonnative/navigation/host.py +58 -0
  310. pythonnative/navigation/linking.py +200 -0
  311. pythonnative/navigation/navigators.py +659 -0
  312. pythonnative/navigation/screen.py +149 -0
  313. pythonnative/navigation/state.py +269 -0
  314. pythonnative/net.py +248 -0
  315. pythonnative/platform.py +166 -0
  316. pythonnative/platform_metrics.py +252 -0
  317. pythonnative/preview.py +287 -0
  318. pythonnative/profiling.py +101 -0
  319. pythonnative/project/__init__.py +68 -0
  320. pythonnative/project/android.py +557 -0
  321. pythonnative/project/builder.py +817 -0
  322. pythonnative/project/config.py +773 -0
  323. pythonnative/project/deps.py +719 -0
  324. pythonnative/project/devices.py +304 -0
  325. pythonnative/project/doctor.py +283 -0
  326. pythonnative/project/fingerprint.py +171 -0
  327. pythonnative/project/icons.py +247 -0
  328. pythonnative/project/ios.py +325 -0
  329. pythonnative/project/lockfile.py +100 -0
  330. pythonnative/project/permissions.py +361 -0
  331. pythonnative/project/plugins.py +519 -0
  332. pythonnative/project/runtime_assets.py +183 -0
  333. pythonnative/py.typed +0 -0
  334. pythonnative/query.py +153 -0
  335. pythonnative/reconciler/__init__.py +29 -0
  336. pythonnative/reconciler/boundaries.py +375 -0
  337. pythonnative/reconciler/children.py +88 -0
  338. pythonnative/reconciler/core.py +1165 -0
  339. pythonnative/reconciler/layout_pass.py +393 -0
  340. pythonnative/reconciler/vnode.py +266 -0
  341. pythonnative/refresh.py +55 -0
  342. pythonnative/runtime.py +306 -0
  343. pythonnative/scheduler.py +159 -0
  344. pythonnative/sdk/__init__.py +153 -0
  345. pythonnative/sdk/_components.py +427 -0
  346. pythonnative/sdk/builtins.py +91 -0
  347. pythonnative/sdk/codegen.py +149 -0
  348. pythonnative/sdk/module_codegen.py +184 -0
  349. pythonnative/sdk/schema.py +224 -0
  350. pythonnative/sdk/templates/contracts.kt +46 -0
  351. pythonnative/sdk/templates/contracts.swift +46 -0
  352. pythonnative/storage.py +184 -0
  353. pythonnative/style.py +841 -0
  354. pythonnative/suspense.py +183 -0
  355. pythonnative/templates/android_template/app/build.gradle +75 -0
  356. pythonnative/templates/android_template/app/proguard-rules.pro +21 -0
  357. pythonnative/templates/android_template/app/src/androidTest/java/com/pythonnative/android_template/ExampleInstrumentedTest.kt +24 -0
  358. pythonnative/templates/android_template/app/src/debug/AndroidManifest.xml +7 -0
  359. pythonnative/templates/android_template/app/src/main/AndroidManifest.xml +32 -0
  360. pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/MainActivity.kt +130 -0
  361. pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/ScreenFragment.kt +13 -0
  362. pythonnative/templates/android_template/app/src/main/res/drawable/ic_launcher_background.xml +170 -0
  363. pythonnative/templates/android_template/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +30 -0
  364. pythonnative/templates/android_template/app/src/main/res/layout/activity_main.xml +10 -0
  365. pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +6 -0
  366. pythonnative/templates/android_template/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +6 -0
  367. pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher.webp +0 -0
  368. pythonnative/templates/android_template/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp +0 -0
  369. pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher.webp +0 -0
  370. pythonnative/templates/android_template/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp +0 -0
  371. pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher.webp +0 -0
  372. pythonnative/templates/android_template/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp +0 -0
  373. pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp +0 -0
  374. pythonnative/templates/android_template/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp +0 -0
  375. pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp +0 -0
  376. pythonnative/templates/android_template/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp +0 -0
  377. pythonnative/templates/android_template/app/src/main/res/navigation/nav_graph.xml +22 -0
  378. pythonnative/templates/android_template/app/src/main/res/values/colors.xml +5 -0
  379. pythonnative/templates/android_template/app/src/main/res/values/strings.xml +5 -0
  380. pythonnative/templates/android_template/app/src/main/res/values/themes.xml +9 -0
  381. pythonnative/templates/android_template/app/src/main/res/values-night/themes.xml +7 -0
  382. pythonnative/templates/android_template/app/src/main/res/xml/backup_rules.xml +13 -0
  383. pythonnative/templates/android_template/app/src/main/res/xml/data_extraction_rules.xml +19 -0
  384. pythonnative/templates/android_template/app/src/test/java/com/pythonnative/android_template/ExampleUnitTest.kt +17 -0
  385. pythonnative/templates/android_template/build.gradle +10 -0
  386. pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.jar +0 -0
  387. pythonnative/templates/android_template/gradle/wrapper/gradle-wrapper.properties +6 -0
  388. pythonnative/templates/android_template/gradle.properties +23 -0
  389. pythonnative/templates/android_template/gradlew +185 -0
  390. pythonnative/templates/android_template/gradlew.bat +89 -0
  391. pythonnative/templates/android_template/settings.gradle +17 -0
  392. pythonnative/templates/ios_template/ios_template/AppDelegate.swift +51 -0
  393. pythonnative/templates/ios_template/ios_template/Assets.xcassets/AccentColor.colorset/Contents.json +11 -0
  394. pythonnative/templates/ios_template/ios_template/Assets.xcassets/AppIcon.appiconset/Contents.json +13 -0
  395. pythonnative/templates/ios_template/ios_template/Assets.xcassets/Contents.json +6 -0
  396. pythonnative/templates/ios_template/ios_template/Base.lproj/LaunchScreen.storyboard +25 -0
  397. pythonnative/templates/ios_template/ios_template/BridgingHeader.h +14 -0
  398. pythonnative/templates/ios_template/ios_template/Info.plist +28 -0
  399. pythonnative/templates/ios_template/ios_template/PythonRuntime.swift +390 -0
  400. pythonnative/templates/ios_template/ios_template/SceneDelegate.swift +61 -0
  401. pythonnative/templates/ios_template/ios_template/ViewController.swift +23 -0
  402. pythonnative/templates/ios_template/ios_template.xcodeproj/project.pbxproj +745 -0
  403. pythonnative/templates/ios_template/ios_template.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  404. pythonnative/templates/ios_template/ios_templateTests/ios_templateTests.swift +36 -0
  405. pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITests.swift +41 -0
  406. pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITestsLaunchTests.swift +32 -0
  407. pythonnative/testing/__init__.py +53 -0
  408. pythonnative/testing/backend.py +276 -0
  409. pythonnative/testing/harness.py +369 -0
  410. pythonnative/utils.py +145 -0
  411. pythonnative-0.40.0.dist-info/DELVEWHEEL +2 -0
  412. pythonnative-0.40.0.dist-info/METADATA +150 -0
  413. pythonnative-0.40.0.dist-info/RECORD +418 -0
  414. pythonnative-0.40.0.dist-info/WHEEL +5 -0
  415. pythonnative-0.40.0.dist-info/entry_points.txt +2 -0
  416. pythonnative-0.40.0.dist-info/licenses/LICENSE +21 -0
  417. pythonnative-0.40.0.dist-info/top_level.txt +1 -0
  418. pythonnative.libs/msvcp140-a4c2229bdc2a2a630acdc095b4d86008.dll +0 -0
@@ -0,0 +1,552 @@
1
+ // The page's `Host` module and screen stack, plus the other native
2
+ // modules the browser can honor (Alert, Clipboard, Linking, Share,
3
+ // Haptics, NetInfo, AppState, Device).
4
+ //
5
+ // A "screen" here is what PNViewController is on iOS: it owns one
6
+ // Python screen id, sends host lifecycle events (`create`, `start`,
7
+ // `layout`, `resume`, `pause`, `stop`, `destroy`), and hosts the root
8
+ // view Python attaches with `Host.attach_root`. Screens stack inside the
9
+ // phone frame with a slide transition; a header with a back button
10
+ // stands in for UINavigationBar.
11
+
12
+ const STATUS_BAR = 47;
13
+ const HEADER = 44;
14
+
15
+ export class Screen {
16
+ constructor(host, id, path, argsJson, options) {
17
+ this.host = host;
18
+ this.id = id;
19
+ this.path = path;
20
+ this.argsJson = argsJson;
21
+ this.options = { header_shown: true, ...(options || {}) };
22
+ this.root = null;
23
+ this.created = false;
24
+ this.lastLayout = "";
25
+
26
+ this.el = document.createElement("section");
27
+ this.el.className = "pn-screen";
28
+ this.el.dataset.screen = String(id);
29
+ this.header = document.createElement("div");
30
+ this.header.className = "pn-header";
31
+ this.back = document.createElement("button");
32
+ this.back.className = "pn-back";
33
+ this.back.textContent = "Back";
34
+ this.back.addEventListener("click", () => host.backPressed());
35
+ this.title = document.createElement("span");
36
+ this.title.className = "pn-title";
37
+ this.header.appendChild(this.back);
38
+ this.header.appendChild(this.title);
39
+ this.content = document.createElement("div");
40
+ this.content.className = "pn-content";
41
+ this.el.appendChild(this.header);
42
+ this.el.appendChild(this.content);
43
+ }
44
+
45
+ applyOptions(options) {
46
+ Object.assign(this.options, options || {});
47
+ const o = this.options;
48
+ this.title.textContent = o.title == null ? "" : String(o.title);
49
+ this.header.style.display = o.header_shown === false ? "none" : "";
50
+ this.back.style.visibility = this.host.stack.indexOf(this) > 0 && !o.hide_back_button ? "" : "hidden";
51
+ const tint = this.host.color(o.header_tint_color);
52
+ this.back.style.color = tint ?? "";
53
+ const bg = this.host.color(o.header_background_color);
54
+ this.header.style.background = bg ?? "";
55
+ this.layout();
56
+ }
57
+
58
+ /** Top offset of the content area (status bar + header when shown). */
59
+ contentTop() {
60
+ const bar = this.host.statusBarHidden ? 0 : STATUS_BAR;
61
+ return bar + (this.options.header_shown === false ? 0 : HEADER);
62
+ }
63
+
64
+ viewport() {
65
+ const { width, height, bottomInset } = this.host.frameMetrics();
66
+ const top = this.contentTop();
67
+ return {
68
+ width,
69
+ height: Math.max(0, height - top),
70
+ insets: { top: 0, left: 0, bottom: bottomInset, right: 0 },
71
+ keyboard_height: 0,
72
+ color_scheme: this.host.scheme(),
73
+ };
74
+ }
75
+
76
+ layout() {
77
+ const top = this.contentTop();
78
+ this.header.style.top = `${this.host.statusBarHidden ? 0 : STATUS_BAR}px`;
79
+ this.content.style.top = `${top}px`;
80
+ if (!this.created) return;
81
+ const payload = JSON.stringify(this.viewport());
82
+ if (payload !== this.lastLayout) {
83
+ this.lastLayout = payload;
84
+ this.host.hostEvent(this.id, "layout", payload);
85
+ }
86
+ }
87
+
88
+ attachRoot(view) {
89
+ this.root = view;
90
+ this.content.appendChild(view.el);
91
+ view.el.classList.add("pn-root");
92
+ }
93
+
94
+ detachRoot(view) {
95
+ if (this.root === view) this.root = null;
96
+ if (view.el.parentNode === this.content) this.content.removeChild(view.el);
97
+ }
98
+ }
99
+
100
+ export class PreviewHost {
101
+ /**
102
+ * @param opts {{
103
+ * bridge, renderer, screensEl, overlaysEl, frameMetrics(), scheme(),
104
+ * color(value), statusBar(opts), log(level, text)
105
+ * }}
106
+ */
107
+ constructor(opts) {
108
+ Object.assign(this, opts);
109
+ this.stack = [];
110
+ this.nextScreenId = 1;
111
+ this.statusBarHidden = false;
112
+ this.appState = "active";
113
+ this.entry = null;
114
+ this.installVisibilityTracking();
115
+ this.installNetworkTracking();
116
+ }
117
+
118
+ // -- lifecycle ---------------------------------------------------------
119
+
120
+ /** Mount the entry screen (or remount after a reset). */
121
+ async start(entry) {
122
+ this.entry = entry || this.entry;
123
+ await this.clear();
124
+ await this.pushScreen(this.entry, null, {}, { animated: false });
125
+ }
126
+
127
+ async clear() {
128
+ for (const screen of [...this.stack].reverse()) {
129
+ this.hostEvent(screen.id, "pause", "{}");
130
+ this.hostEvent(screen.id, "stop", "{}");
131
+ this.hostEvent(screen.id, "destroy", "{}");
132
+ screen.el.remove();
133
+ }
134
+ this.stack = [];
135
+ this.overlaysEl.textContent = "";
136
+ }
137
+
138
+ async pushScreen(path, argsJson, options, { animated = true } = {}) {
139
+ const screen = new Screen(this, this.nextScreenId++, path, argsJson, options);
140
+ const previous = this.top();
141
+ if (previous) this.hostEvent(previous.id, "pause", "{}");
142
+ this.stack.push(screen);
143
+ this.screensEl.appendChild(screen.el);
144
+ if (animated) screen.el.classList.add("pn-enter");
145
+ screen.applyOptions({});
146
+ const payload = { path: path || null, args: argsJson ?? null, ...screen.viewport() };
147
+ const reply = await this.bridge.request("host", screen.id, "create", JSON.stringify(payload));
148
+ screen.created = true;
149
+ screen.lastLayout = JSON.stringify(screen.viewport());
150
+ this.attachFromReply(screen, reply);
151
+ this.hostEvent(screen.id, "start", "{}");
152
+ if (animated) {
153
+ requestAnimationFrame(() => screen.el.classList.remove("pn-enter"));
154
+ if (previous) previous.el.classList.add("pn-under");
155
+ }
156
+ this.hostEvent(screen.id, "resume", JSON.stringify(screen.viewport()));
157
+ if (previous) this.hostEvent(previous.id, "stop", "{}");
158
+ return screen;
159
+ }
160
+
161
+ attachFromReply(screen, reply) {
162
+ let root = null;
163
+ try {
164
+ const parsed = typeof reply === "string" ? JSON.parse(reply) : reply;
165
+ root = parsed && parsed.root != null ? Number(parsed.root) : null;
166
+ } catch (err) {
167
+ root = null;
168
+ }
169
+ if (root == null || screen.root) return;
170
+ const view = this.renderer.views.get(root);
171
+ if (view) screen.attachRoot(view);
172
+ }
173
+
174
+ popScreens(count = 1) {
175
+ if (this.stack.length <= 1) return false;
176
+ const removed = [];
177
+ for (let i = 0; i < count && this.stack.length > 1; i++) removed.push(this.stack.pop());
178
+ const revealed = this.top();
179
+ for (const screen of removed) {
180
+ this.hostEvent(screen.id, "pause", "{}");
181
+ screen.el.classList.add("pn-enter");
182
+ setTimeout(() => {
183
+ screen.el.remove();
184
+ this.hostEvent(screen.id, "stop", "{}");
185
+ this.hostEvent(screen.id, "destroy", "{}");
186
+ }, 280);
187
+ }
188
+ revealed.el.classList.remove("pn-under");
189
+ revealed.applyOptions({});
190
+ this.hostEvent(revealed.id, "start", "{}");
191
+ this.hostEvent(revealed.id, "resume", JSON.stringify(revealed.viewport()));
192
+ return true;
193
+ }
194
+
195
+ async replaceScreen(target, path, argsJson, options) {
196
+ const index = this.stack.indexOf(target);
197
+ if (index < 0) return false;
198
+ if (index === this.stack.length - 1) {
199
+ // Replace the visible screen: push the new one, then drop the old one under it.
200
+ const next = await this.pushScreen(path, argsJson, options, { animated: true });
201
+ this.stack.splice(index, 1);
202
+ target.el.remove();
203
+ this.hostEvent(target.id, "stop", "{}");
204
+ this.hostEvent(target.id, "destroy", "{}");
205
+ next.applyOptions({});
206
+ return true;
207
+ }
208
+ const screen = new Screen(this, this.nextScreenId++, path, argsJson, options);
209
+ this.stack[index] = screen;
210
+ this.screensEl.insertBefore(screen.el, target.el);
211
+ screen.el.classList.add("pn-under");
212
+ target.el.remove();
213
+ this.hostEvent(target.id, "destroy", "{}");
214
+ const payload = { path: path || null, args: argsJson ?? null, ...screen.viewport() };
215
+ const reply = await this.bridge.request("host", screen.id, "create", JSON.stringify(payload));
216
+ screen.created = true;
217
+ this.attachFromReply(screen, reply);
218
+ return true;
219
+ }
220
+
221
+ top() {
222
+ return this.stack[this.stack.length - 1] || null;
223
+ }
224
+
225
+ async backPressed() {
226
+ const screen = this.top();
227
+ if (!screen) return;
228
+ const reply = await this.bridge.request("host", screen.id, "back_pressed", "{}");
229
+ if (reply === "true" || reply === true) return;
230
+ this.popScreens(1);
231
+ }
232
+
233
+ hostEvent(screenId, name, payload) {
234
+ this.bridge.callback("host", screenId, name, payload);
235
+ }
236
+
237
+ /** Re-run layout for every screen (rotation, device change, scheme change). */
238
+ relayout() {
239
+ for (const screen of this.stack) screen.layout();
240
+ }
241
+
242
+ appearanceChanged() {
243
+ this.bridge.callback("host", 0, "appearance", JSON.stringify({ color_scheme: this.scheme() }));
244
+ this.relayout();
245
+ }
246
+
247
+ screenById(id) {
248
+ return this.stack.find((s) => s.id === Number(id)) || null;
249
+ }
250
+
251
+ // -- native modules ----------------------------------------------------
252
+
253
+ /** Handle `["call", id, module, method, envelopeJson]`; returns the JSON result text. */
254
+ async call(module, method, envelopeJson) {
255
+ let envelope = {};
256
+ try {
257
+ envelope = envelopeJson ? JSON.parse(envelopeJson) || {} : {};
258
+ } catch (err) {
259
+ envelope = {};
260
+ }
261
+ const args = envelope.args || {};
262
+ const callId = Number(envelope.call_id) || 0;
263
+ const impl = this.modules()[module];
264
+ if (!impl) return JSON.stringify({ ok: false, error: `no browser module named ${module}`, code: "unknown_module" });
265
+ const fn = impl[method];
266
+ if (typeof fn !== "function") {
267
+ return JSON.stringify({ ok: false, error: `${module} has no method '${method}'`, code: "unknown_method" });
268
+ }
269
+ let result;
270
+ try {
271
+ result = fn.call(impl, args);
272
+ } catch (err) {
273
+ return JSON.stringify({ ok: false, error: String(err && err.message ? err.message : err) });
274
+ }
275
+ if (result && typeof result.then === "function") {
276
+ if (callId === 0) {
277
+ // Synchronous call of an async method: wait for it (the request
278
+ // path is already asynchronous on this side).
279
+ try {
280
+ return JSON.stringify({ ok: true, value: nullish(await result) });
281
+ } catch (err) {
282
+ return JSON.stringify({ ok: false, error: String(err && err.message ? err.message : err) });
283
+ }
284
+ }
285
+ result
286
+ .then((value) => this.moduleMessage(module, { call_id: callId, ok: true, value: nullish(value) }))
287
+ .catch((err) => this.moduleMessage(module, { call_id: callId, ok: false, error: String(err && err.message ? err.message : err) }));
288
+ return JSON.stringify({ pending: true });
289
+ }
290
+ return JSON.stringify({ ok: true, value: nullish(result) });
291
+ }
292
+
293
+ moduleMessage(module, message) {
294
+ this.bridge.callback("module", 0, module, JSON.stringify(message));
295
+ }
296
+
297
+ moduleEvent(module, event, payload) {
298
+ this.moduleMessage(module, { event, payload });
299
+ }
300
+
301
+ modules() {
302
+ if (this._modules) return this._modules;
303
+ const host = this;
304
+ this._modules = {
305
+ Host: {
306
+ cache_state({ screen, state }) {
307
+ const s = host.screenById(screen);
308
+ if (s) s.cachedState = state;
309
+ return null;
310
+ },
311
+ attach_root({ screen, tag }) {
312
+ const s = host.screenById(screen);
313
+ const view = host.renderer.views.get(Number(tag));
314
+ if (!s || !view) throw new Error("attach_root: unknown screen or view");
315
+ s.attachRoot(view);
316
+ return s.viewport();
317
+ },
318
+ detach_root({ screen, tag }) {
319
+ const s = host.screenById(screen);
320
+ const view = host.renderer.views.get(Number(tag));
321
+ if (s && view) s.detachRoot(view);
322
+ return null;
323
+ },
324
+ viewport({ screen }) {
325
+ const s = host.screenById(screen);
326
+ return s ? s.viewport() : new Screen(host, 0, null, null, {}).viewport();
327
+ },
328
+ set_options({ screen, options }) {
329
+ const s = host.screenById(screen);
330
+ if (s) s.applyOptions(options || {});
331
+ return null;
332
+ },
333
+ finish() { return null; },
334
+ },
335
+ Alert: {
336
+ show(args) {
337
+ host.presentAlert(args);
338
+ return null;
339
+ },
340
+ present(args) {
341
+ return host.presentAlert(args);
342
+ },
343
+ },
344
+ Clipboard: {
345
+ async set_string({ text }) {
346
+ host.clipboardText = text == null ? "" : String(text);
347
+ try {
348
+ await navigator.clipboard.writeText(host.clipboardText);
349
+ } catch (err) {
350
+ /* permission denied; keep the in-page copy */
351
+ }
352
+ return null;
353
+ },
354
+ async get_string() {
355
+ try {
356
+ return await navigator.clipboard.readText();
357
+ } catch (err) {
358
+ return host.clipboardText || "";
359
+ }
360
+ },
361
+ has_string() {
362
+ return !!host.clipboardText;
363
+ },
364
+ },
365
+ Linking: {
366
+ open_url({ url }) {
367
+ const text = String(url || "");
368
+ if (!text) return false;
369
+ window.open(text, "_blank", "noopener");
370
+ host.log("info", `Linking.open_url(${text})`);
371
+ return true;
372
+ },
373
+ can_open_url({ url }) {
374
+ return /^(https?|mailto|tel|sms):/i.test(String(url || ""));
375
+ },
376
+ get_initial_url() {
377
+ return null;
378
+ },
379
+ open_settings() {
380
+ host.log("info", "Linking.open_settings() has no browser equivalent");
381
+ return false;
382
+ },
383
+ },
384
+ Share: {
385
+ async share({ message, url, title }) {
386
+ if (navigator.share) {
387
+ try {
388
+ await navigator.share({ text: message || undefined, url: url || undefined, title: title || undefined });
389
+ return true;
390
+ } catch (err) {
391
+ return false;
392
+ }
393
+ }
394
+ host.log("info", `Share.share(${JSON.stringify({ message, url, title })})`);
395
+ host.toast("Shared (see console)");
396
+ return true;
397
+ },
398
+ },
399
+ Haptics: {
400
+ impact({ style }) {
401
+ host.vibrate(style === "heavy" ? 30 : style === "light" ? 8 : 15);
402
+ return null;
403
+ },
404
+ notification({ type_, type }) {
405
+ host.vibrate((type_ || type) === "error" ? [30, 40, 30] : [12, 30, 12]);
406
+ return null;
407
+ },
408
+ selection() {
409
+ host.vibrate(5);
410
+ return null;
411
+ },
412
+ vibrate({ duration_ms }) {
413
+ host.vibrate(Number(duration_ms) || 50);
414
+ return null;
415
+ },
416
+ },
417
+ NetInfo: {
418
+ fetch() {
419
+ return host.netInfoSnapshot();
420
+ },
421
+ },
422
+ AppState: {
423
+ current_state() {
424
+ return host.appState;
425
+ },
426
+ },
427
+ Device: {
428
+ info() {
429
+ const [browser, version] = browserFamily(navigator.userAgent);
430
+ return {
431
+ platform: "web",
432
+ os: browser,
433
+ os_version: version,
434
+ model: `${browser} on ${navigator.platform || "web"}`,
435
+ app_dir: "~/.pythonnative_data",
436
+ cache_dir: "~/.pythonnative_data/cache",
437
+ temp_dir: "~/.pythonnative_data/tmp",
438
+ locale: (navigator.language || "en-US").replace("-", "_"),
439
+ app_version: "0.0.0",
440
+ build_number: "0",
441
+ bundle_id: "com.pythonnative.preview",
442
+ screen_width: host.frameMetrics().width,
443
+ screen_height: host.frameMetrics().height,
444
+ scale: window.devicePixelRatio || 1,
445
+ user_agent: navigator.userAgent,
446
+ };
447
+ },
448
+ },
449
+ };
450
+ return this._modules;
451
+ }
452
+
453
+ // -- helpers -----------------------------------------------------------
454
+
455
+ vibrate(pattern) {
456
+ if (navigator.vibrate) navigator.vibrate(pattern);
457
+ }
458
+
459
+ netInfoSnapshot() {
460
+ const online = navigator.onLine !== false;
461
+ const conn = navigator.connection || {};
462
+ return {
463
+ is_connected: online,
464
+ is_internet_reachable: online,
465
+ type: online ? conn.type || "wifi" : "none",
466
+ details: { effective_type: conn.effectiveType || null, downlink: conn.downlink || null },
467
+ };
468
+ }
469
+
470
+ installNetworkTracking() {
471
+ const emit = () => this.moduleEvent("NetInfo", "change", this.netInfoSnapshot());
472
+ window.addEventListener("online", emit);
473
+ window.addEventListener("offline", emit);
474
+ }
475
+
476
+ installVisibilityTracking() {
477
+ document.addEventListener("visibilitychange", () => {
478
+ const next = document.visibilityState === "hidden" ? "background" : "active";
479
+ if (next === this.appState) return;
480
+ this.appState = next;
481
+ this.moduleEvent("AppState", "change", next);
482
+ });
483
+ }
484
+
485
+ /** Present an iOS-style alert or action sheet; resolves with the chosen index (-1 on dismiss). */
486
+ presentAlert({ title, message, buttons, style }) {
487
+ return new Promise((resolve) => {
488
+ const list = Array.isArray(buttons) && buttons.length ? buttons : [{ label: "OK", style: "default" }];
489
+ const sheet = style === "action_sheet" || style === "sheet";
490
+ const backdrop = document.createElement("div");
491
+ backdrop.className = "pn-alert-backdrop" + (sheet ? " pn-sheet" : "");
492
+ const box = document.createElement("div");
493
+ box.className = "pn-alert" + (sheet ? " pn-sheet" : "");
494
+ const body = document.createElement("div");
495
+ body.className = "pn-alert-body";
496
+ if (title) {
497
+ const h = document.createElement("h2");
498
+ h.textContent = String(title);
499
+ body.appendChild(h);
500
+ }
501
+ if (message) {
502
+ const p = document.createElement("p");
503
+ p.textContent = String(message);
504
+ body.appendChild(p);
505
+ }
506
+ box.appendChild(body);
507
+ const row = document.createElement("div");
508
+ row.className = "pn-alert-buttons" + (list.length > 2 || sheet ? " pn-vertical" : "");
509
+ const finish = (index) => {
510
+ backdrop.remove();
511
+ resolve(index);
512
+ };
513
+ list.forEach((button, index) => {
514
+ const b = document.createElement("button");
515
+ b.type = "button";
516
+ b.textContent = String(button.label ?? button.title ?? "OK");
517
+ if (button.style === "cancel") b.classList.add("pn-cancel");
518
+ if (button.style === "destructive") b.classList.add("pn-destructive");
519
+ b.addEventListener("click", () => finish(index));
520
+ row.appendChild(b);
521
+ });
522
+ box.appendChild(row);
523
+ backdrop.appendChild(box);
524
+ backdrop.addEventListener("click", (event) => {
525
+ if (event.target !== backdrop) return;
526
+ const cancel = list.findIndex((b) => b.style === "cancel");
527
+ finish(cancel >= 0 ? cancel : sheet ? -1 : -1);
528
+ });
529
+ this.overlaysEl.appendChild(backdrop);
530
+ });
531
+ }
532
+ }
533
+
534
+ function nullish(value) {
535
+ return value === undefined ? null : value;
536
+ }
537
+
538
+ /** `["Chrome", "144.0"]`-style browser name and version from a user agent string. */
539
+ export function browserFamily(userAgent) {
540
+ const ua = userAgent || "";
541
+ const probes = [
542
+ ["Firefox", /Firefox\/([\d.]+)/],
543
+ ["Edge", /Edg\/([\d.]+)/],
544
+ ["Chrome", /Chrome\/([\d.]+)/],
545
+ ["Safari", /Version\/([\d.]+).*Safari/],
546
+ ];
547
+ for (const [name, re] of probes) {
548
+ const m = re.exec(ua);
549
+ if (m) return [name, m[1].split(".").slice(0, 2).join(".")];
550
+ }
551
+ return ["Browser", "0"];
552
+ }
@@ -0,0 +1,60 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <meta name="color-scheme" content="light dark" />
7
+ <title>PythonNative preview</title>
8
+ <link rel="stylesheet" href="/static/preview.css" />
9
+ </head>
10
+ <body>
11
+ <header id="pn-toolbar">
12
+ <div class="pn-brand">
13
+ <span class="pn-dot" id="pn-status-dot" title="Disconnected"></span>
14
+ <strong>PythonNative</strong>
15
+ <span id="pn-project-name" class="pn-muted"></span>
16
+ </div>
17
+ <div class="pn-controls">
18
+ <label>Device
19
+ <select id="pn-device"></select>
20
+ </label>
21
+ <button id="pn-rotate" title="Rotate (r)">Rotate</button>
22
+ <button id="pn-scheme" title="Toggle light/dark (d)">Dark</button>
23
+ <button id="pn-back" title="Back (Esc)">Back</button>
24
+ <button id="pn-reload" title="Remount the app (shift+r)">Reload app</button>
25
+ <button id="pn-console-toggle" title="Show/hide console (`)">Console</button>
26
+ </div>
27
+ </header>
28
+
29
+ <main id="pn-stage">
30
+ <div id="pn-device-frame" class="pn-frame">
31
+ <div id="pn-statusbar" class="pn-statusbar">
32
+ <span class="pn-time" id="pn-clock">9:41</span>
33
+ <span class="pn-status-icons">●●● ⌒ ▮</span>
34
+ </div>
35
+ <div id="pn-screens" class="pn-screens"></div>
36
+ <div id="pn-overlays" class="pn-overlays"></div>
37
+ <div id="pn-home" class="pn-home"></div>
38
+ </div>
39
+ <div id="pn-connect" class="pn-connect">
40
+ <div class="pn-connect-card">
41
+ <h1>Waiting for <code>pn start</code></h1>
42
+ <p id="pn-connect-detail">Connecting to the dev server...</p>
43
+ </div>
44
+ </div>
45
+ </main>
46
+
47
+ <section id="pn-console" class="pn-console pn-hidden">
48
+ <div class="pn-console-bar">
49
+ <span>Console</span>
50
+ <button id="pn-console-clear">Clear</button>
51
+ </div>
52
+ <div id="pn-console-lines" class="pn-console-lines"></div>
53
+ </section>
54
+
55
+ <div id="pn-toasts" class="pn-toasts"></div>
56
+ <div id="pn-measure" class="pn-measure" aria-hidden="true"></div>
57
+
58
+ <script type="module" src="/static/shell.js"></script>
59
+ </body>
60
+ </html>
@@ -0,0 +1,85 @@
1
+ import Yoga from "./yoga/src/index.js";
2
+
3
+ const detached = new Set(["VirtualList", "Modal", "Portal", "ScreenStack"]);
4
+ const containers = new Set([...detached, "View", "Row", "Column", "ScrollView", "Screen"]);
5
+ const edges = {left:0, top:1, right:2, bottom:3, start:4, end:5, horizontal:6, vertical:7, all:8};
6
+ const enums = {
7
+ direction: ["Direction", ["inherit", "ltr", "rtl"]],
8
+ flex_direction: ["FlexDirection", ["column", "column_reverse", "row", "row_reverse"]],
9
+ justify_content: ["JustifyContent", ["flex_start", "center", "flex_end", "space_between", "space_around", "space_evenly"]],
10
+ align_items: ["AlignItems", ["auto", "flex_start", "center", "flex_end", "stretch", "baseline", "space_between", "space_around", "space_evenly"]],
11
+ align_self: ["AlignSelf", ["auto", "flex_start", "center", "flex_end", "stretch", "baseline", "space_between", "space_around", "space_evenly"]],
12
+ align_content: ["AlignContent", ["auto", "flex_start", "center", "flex_end", "stretch", "baseline", "space_between", "space_around", "space_evenly"]],
13
+ position: ["PositionType", ["static", "relative", "absolute"]],
14
+ flex_wrap: ["FlexWrap", ["nowrap", "wrap", "wrap_reverse"]],
15
+ display: ["Display", ["flex", "none", "contents"]],
16
+ };
17
+ function style(node, props) {
18
+ const fresh = Yoga.Node.create();
19
+ for (const [key, value] of Object.entries(props)) {
20
+ if (value == null) continue;
21
+ if (enums[key]) {
22
+ const [name, values] = enums[key];
23
+ const index = values.indexOf(value);
24
+ if (index < 0) throw Error(`Invalid ${key}: ${value}`);
25
+ fresh[`set${name}`](index);
26
+ } else if (["width", "height", "min_width", "min_height", "max_width", "max_height", "flex", "flex_grow", "flex_shrink", "flex_basis", "aspect_ratio"].includes(key)) {
27
+ fresh["set" + key.split("_").map(p => p[0].toUpperCase() + p.slice(1)).join("")](value);
28
+ } else if (["gap", "spacing", "row_gap", "column_gap"].includes(key)) {
29
+ fresh.setGap({row_gap:1, column_gap:0}[key] ?? 2, value);
30
+ } else if (["left", "right", "top", "bottom", "start", "end"].includes(key)) fresh.setPosition(edges[key], value);
31
+ else if (key.startsWith("padding") || key.startsWith("margin")) {
32
+ const [group, edge] = key.split("_");
33
+ const name = group === "padding" ? "setPadding" : "setMargin";
34
+ if (typeof value === "object") for (const [side, amount] of Object.entries(value)) fresh[name](edges[side], amount);
35
+ else fresh[name](edges[edge || "all"], value);
36
+ } else if (key.startsWith("border_") && key.endsWith("width")) fresh.setBorder(edges[key.split("_")[1]] ?? 8, value);
37
+ }
38
+ node.copyStyle(fresh);
39
+ fresh.free();
40
+ }
41
+ export function disposeLayout(view) {
42
+ if (!view.yoga) return;
43
+ const parent = view.yoga.getParent();
44
+ if (parent) parent.removeChild(view.yoga);
45
+ view.yoga.free(); view.yoga = null;
46
+ }
47
+ export function computeLayout(renderer, {roots = [], width, height}) {
48
+ const views = [...renderer.views.values()];
49
+ for (const view of views) {
50
+ view.yoga ||= Yoga.Node.create();
51
+ const props = JSON.stringify(view.props);
52
+ if (props !== view.yogaProps) {
53
+ style(view.yoga, view.props); view.yogaProps = props;
54
+ if (["ScrollView", "VirtualList", "ScreenStack"].includes(view.type)) { view.yoga.setOverflow(1); view.yoga.setFlexShrink(1); }
55
+ }
56
+ while (view.yoga.getChildCount()) view.yoga.removeChild(view.yoga.getChild(0));
57
+ view.yoga.unsetMeasureFunc();
58
+ }
59
+ for (const view of views) {
60
+ if (!detached.has(view.type)) for (const child of view.children) view.yoga.insertChild(child.yoga, view.yoga.getChildCount());
61
+ if (!view.yoga.getChildCount() && !containers.has(view.type)) view.yoga.setMeasureFunc((w, wm, h, hm) => {
62
+ const [width, height] = view.manager.measure(view, wm ? w : 1e6, hm ? h : 1e6);
63
+ return {width, height};
64
+ });
65
+ }
66
+ for (const tag of roots) renderer.views.get(tag)?.yoga.calculateLayout(width, height, 1);
67
+ for (const view of views) if (view.parent && !view.yoga.getParent()) {
68
+ const parent = view.parent;
69
+ const isList = parent.type === "VirtualList", horizontal = parent.props.horizontal;
70
+ view.yoga.calculateLayout(isList && horizontal ? NaN : parent.frame?.w || width,
71
+ isList && !horizontal ? NaN : parent.frame?.h || height, 1);
72
+ }
73
+ const frames = [];
74
+ for (const view of views) {
75
+ const layout = view.yoga.getComputedLayout();
76
+ const frame = [layout.left, layout.top, layout.width, layout.height];
77
+ if (JSON.stringify(frame) === view.layoutFrame) continue;
78
+ view.layoutFrame = JSON.stringify(frame);
79
+ view.frame = {x:frame[0], y:frame[1], w:frame[2], h:frame[3]};
80
+ if (!roots.includes(view.tag)) view.manager.frame(view, ...frame);
81
+ frames.push([view.tag, ...frame]);
82
+ }
83
+ for (const view of views) if (view.children.length) view.manager.childrenChanged(view);
84
+ return frames;
85
+ }