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,142 @@
1
+ import UIKit
2
+
3
+ /// A native plugin bundled into the app by `pn build`. The generated
4
+ /// `PNGeneratedPlugins.registerAll(into:)` calls each entry's `register`.
5
+ public protocol PNPlugin {
6
+ /// Register component managers and native modules.
7
+ static func register(into registry: PNRegistry)
8
+ }
9
+
10
+ /// Component-manager and native-module registry.
11
+ ///
12
+ /// Built-ins register lazily on first use; plugins register through
13
+ /// `PNPlugin.register(into:)`. Component factories are invoked once per
14
+ /// element type and the resulting manager is shared by every view of
15
+ /// that type (managers are stateless; per-view state lives in
16
+ /// `PNViewState`).
17
+ public final class PNRegistry {
18
+ public static let shared = PNRegistry()
19
+
20
+ private var componentFactories: [String: () -> PNComponentManager] = [:]
21
+ private var componentManagers: [String: PNComponentManager] = [:]
22
+ private var moduleTypes: [String: PNNativeModule.Type] = [:]
23
+ private var moduleInstances: [String: PNNativeModule] = [:]
24
+ private var builtinsRegistered = false
25
+ private let placeholder = PNPlaceholderManager()
26
+
27
+ private init() {}
28
+
29
+ // MARK: - Registration
30
+
31
+ /// Register (or replace) the manager factory for element type `name`.
32
+ public func registerComponent(_ name: String, factory: @escaping () -> PNComponentManager) {
33
+ componentFactories[name] = factory
34
+ componentManagers.removeValue(forKey: name)
35
+ }
36
+
37
+ /// Register (or replace) a native module by its `name`.
38
+ public func registerModule(_ type: PNNativeModule.Type) {
39
+ moduleTypes[type.name] = type
40
+ moduleInstances.removeValue(forKey: type.name)
41
+ }
42
+
43
+ /// Element type names currently registered.
44
+ public var componentNames: [String] {
45
+ ensureBuiltins()
46
+ return Array(componentFactories.keys).sorted()
47
+ }
48
+
49
+ /// Module names currently registered.
50
+ public var moduleNames: [String] {
51
+ ensureBuiltins()
52
+ return Array(moduleTypes.keys).sorted()
53
+ }
54
+
55
+ // MARK: - Lookup
56
+
57
+ /// The shared manager for `type`, or a placeholder manager for unknown types.
58
+ public func manager(for type: String) -> PNComponentManager {
59
+ ensureBuiltins()
60
+ if let existing = componentManagers[type] { return existing }
61
+ if let factory = componentFactories[type] {
62
+ let manager = factory()
63
+ componentManagers[type] = manager
64
+ return manager
65
+ }
66
+ PNLog.once(PNLog.components, key: "unknown-type:\(type)", "unknown element type '\(type)'; using a placeholder UIView")
67
+ return placeholder
68
+ }
69
+
70
+ /// The module instance registered under `name`, created on first use.
71
+ public func module(named name: String) -> PNNativeModule? {
72
+ ensureBuiltins()
73
+ if let existing = moduleInstances[name] { return existing }
74
+ guard let type = moduleTypes[name] else { return nil }
75
+ let instance = type.init()
76
+ moduleInstances[name] = instance
77
+ return instance
78
+ }
79
+
80
+ // MARK: - Built-ins
81
+
82
+ /// Register every built-in manager and module, then the generated plugins.
83
+ public func ensureBuiltins() {
84
+ if builtinsRegistered { return }
85
+ builtinsRegistered = true
86
+ PNBuiltins.register(into: self)
87
+ PNGeneratedPlugins.registerAll(into: self)
88
+ }
89
+ }
90
+
91
+ /// Registration of the components and modules that ship with PythonNativeKit.
92
+ enum PNBuiltins {
93
+ static func register(into registry: PNRegistry) {
94
+ let flex: () -> PNComponentManager = { PNViewManager() }
95
+ registry.registerComponent("View", factory: flex)
96
+ registry.registerComponent("Screen") { PNScreenManager() }
97
+ registry.registerComponent("ScreenStack") { PNScreenStackManager() }
98
+ registry.registerComponent("Column", factory: flex)
99
+ registry.registerComponent("Row", factory: flex)
100
+ registry.registerComponent("Text") { PNTextManager() }
101
+ registry.registerComponent("Button") { PNButtonManager() }
102
+ registry.registerComponent("TextInput") { PNTextInputManager() }
103
+ registry.registerComponent("Image") { PNImageManager() }
104
+ registry.registerComponent("Switch") { PNSwitchManager() }
105
+ registry.registerComponent("ProgressBar") { PNProgressBarManager() }
106
+ registry.registerComponent("ActivityIndicator") { PNActivityIndicatorManager() }
107
+ registry.registerComponent("WebView") { PNWebViewManager() }
108
+ registry.registerComponent("Spacer") { PNSpacerManager() }
109
+ registry.registerComponent("ScrollView") { PNScrollViewManager() }
110
+ registry.registerComponent("SafeAreaView") { PNSafeAreaViewManager() }
111
+ registry.registerComponent("Modal") { PNModalManager() }
112
+ registry.registerComponent("Portal") { PNPortalManager() }
113
+ registry.registerComponent("Slider") { PNSliderManager() }
114
+ registry.registerComponent("TabBar") { PNTabBarManager() }
115
+ registry.registerComponent("Pressable") { PNPressableManager() }
116
+ registry.registerComponent("StatusBar") { PNStatusBarManager() }
117
+ registry.registerComponent("KeyboardAvoidingView") { PNKeyboardAvoidingViewManager() }
118
+ registry.registerComponent("Picker") { PNPickerManager() }
119
+ registry.registerComponent("Checkbox") { PNCheckboxManager() }
120
+ registry.registerComponent("SegmentedControl") { PNSegmentedControlManager() }
121
+ registry.registerComponent("DatePicker") { PNDatePickerManager() }
122
+ registry.registerComponent("VirtualList") { PNVirtualListManager() }
123
+
124
+ registry.registerModule(HostModule.self)
125
+ registry.registerModule(DeviceModule.self)
126
+ registry.registerModule(AlertModule.self)
127
+ registry.registerModule(StorageModule.self)
128
+ registry.registerModule(SecureStoreModule.self)
129
+ registry.registerModule(ClipboardModule.self)
130
+ registry.registerModule(ShareModule.self)
131
+ registry.registerModule(LinkingModule.self)
132
+ registry.registerModule(HapticsModule.self)
133
+ registry.registerModule(BatteryModule.self)
134
+ registry.registerModule(NetInfoModule.self)
135
+ registry.registerModule(AppStateModule.self)
136
+ registry.registerModule(PermissionsModule.self)
137
+ registry.registerModule(NotificationsModule.self)
138
+ registry.registerModule(CameraModule.self)
139
+ registry.registerModule(LocationModule.self)
140
+ registry.registerModule(BiometricsModule.self)
141
+ }
142
+ }
@@ -0,0 +1,166 @@
1
+ import UIKit
2
+
3
+ /// Decodes and applies reconciler transactions.
4
+ ///
5
+ /// A transaction is a JSON array of ops:
6
+ ///
7
+ /// - `["c", tag, "Type", {props}]` create a view
8
+ /// - `["u", tag, {changed}]` apply changed props (`null` removes a prop)
9
+ /// - `["i", parent, child, index]` ensure `child` is at `index` under `parent`
10
+ /// - `["d", tag]` destroy the view
11
+ /// - `["f", tag, x, y, w, h]` set the frame in points
12
+ ///
13
+ /// Ops are applied strictly in order; a failing op is logged and skipped
14
+ /// so one bad prop can't desync the rest of the tree.
15
+ public enum PNTransaction {
16
+ /// A decoded op.
17
+ public enum Op: Equatable {
18
+ case create(tag: Int64, type: String, props: [String: Any])
19
+ case update(tag: Int64, changed: [String: Any])
20
+ case insert(parent: Int64, child: Int64, index: Int)
21
+ case destroy(tag: Int64)
22
+ case frame(tag: Int64, x: Double, y: Double, w: Double, h: Double)
23
+
24
+ public static func == (lhs: Op, rhs: Op) -> Bool {
25
+ switch (lhs, rhs) {
26
+ case let (.create(t1, ty1, p1), .create(t2, ty2, p2)):
27
+ return t1 == t2 && ty1 == ty2 && NSDictionary(dictionary: p1).isEqual(to: p2)
28
+ case let (.update(t1, p1), .update(t2, p2)):
29
+ return t1 == t2 && NSDictionary(dictionary: p1).isEqual(to: p2)
30
+ case let (.insert(p1, c1, i1), .insert(p2, c2, i2)):
31
+ return p1 == p2 && c1 == c2 && i1 == i2
32
+ case let (.destroy(t1), .destroy(t2)):
33
+ return t1 == t2
34
+ case let (.frame(t1, x1, y1, w1, h1), .frame(t2, x2, y2, w2, h2)):
35
+ return t1 == t2 && x1 == x2 && y1 == y2 && w1 == w2 && h1 == h2
36
+ default:
37
+ return false
38
+ }
39
+ }
40
+ }
41
+
42
+ /// Errors raised while decoding a single op.
43
+ public enum DecodeError: Error, Equatable {
44
+ case notAnArray
45
+ case malformedOp(index: Int)
46
+ case unknownOpcode(String)
47
+ }
48
+
49
+ // MARK: - Decoding
50
+
51
+ /// Decode a transaction document into ops. Malformed ops are skipped
52
+ /// (and logged) rather than failing the whole batch.
53
+ public static func decode(_ json: String) throws -> [Op] {
54
+ guard let root = PNJSON.decode(json) as? [Any] else { throw DecodeError.notAnArray }
55
+ var ops: [Op] = []
56
+ ops.reserveCapacity(root.count)
57
+ for (index, raw) in root.enumerated() {
58
+ do {
59
+ ops.append(try decodeOp(raw, index: index))
60
+ } catch {
61
+ PNLog.rateLimited(PNLog.bridge, key: "decode-op", "skipping malformed op #\(index): \(error)")
62
+ }
63
+ }
64
+ return ops
65
+ }
66
+
67
+ static func decodeOp(_ raw: Any, index: Int) throws -> Op {
68
+ guard let parts = raw as? [Any], let code = parts.first as? String else {
69
+ throw DecodeError.malformedOp(index: index)
70
+ }
71
+ func tag(_ i: Int) throws -> Int64 {
72
+ guard i < parts.count, let value = PNProps.double(parts[i]), value.isFinite else {
73
+ throw DecodeError.malformedOp(index: index)
74
+ }
75
+ return Int64(value)
76
+ }
77
+ func number(_ i: Int) throws -> Double {
78
+ guard i < parts.count, let value = PNProps.double(parts[i]) else {
79
+ throw DecodeError.malformedOp(index: index)
80
+ }
81
+ return value
82
+ }
83
+ switch code {
84
+ case "c":
85
+ guard parts.count >= 4, let type = parts[2] as? String else { throw DecodeError.malformedOp(index: index) }
86
+ let props = (PNJSON.resolveInfinity(parts[3]) as? [String: Any]) ?? [:]
87
+ return .create(tag: try tag(1), type: type, props: props)
88
+ case "u":
89
+ guard parts.count >= 3 else { throw DecodeError.malformedOp(index: index) }
90
+ let changed = (PNJSON.resolveInfinity(parts[2]) as? [String: Any]) ?? [:]
91
+ return .update(tag: try tag(1), changed: changed)
92
+ case "i":
93
+ guard parts.count >= 4 else { throw DecodeError.malformedOp(index: index) }
94
+ return .insert(parent: try tag(1), child: try tag(2), index: Int(try number(3)))
95
+ case "d":
96
+ return .destroy(tag: try tag(1))
97
+ case "f":
98
+ guard parts.count >= 6 else { throw DecodeError.malformedOp(index: index) }
99
+ return .frame(tag: try tag(1), x: try number(2), y: try number(3), w: try number(4), h: try number(5))
100
+ default:
101
+ throw DecodeError.unknownOpcode(code)
102
+ }
103
+ }
104
+
105
+ // MARK: - Applying
106
+
107
+ /// Decode and apply a transaction document.
108
+ public static func apply(_ json: String) {
109
+ let ops: [Op]
110
+ do {
111
+ ops = try decode(json)
112
+ } catch {
113
+ PNLog.bridge.error("transaction rejected: \(String(describing: error))")
114
+ return
115
+ }
116
+ apply(ops)
117
+ }
118
+
119
+ /// Apply already-decoded ops in order with per-op error isolation.
120
+ public static func apply(_ ops: [Op]) {
121
+ let registry = PNViewRegistry.shared
122
+ for op in ops {
123
+ switch op {
124
+ case let .create(tag, type, props):
125
+ if registry.resolve(tag) != nil {
126
+ PNLog.rateLimited(PNLog.bridge, key: "dup-create", "create for tag \(tag) ignored: already exists")
127
+ continue
128
+ }
129
+ let manager = PNRegistry.shared.manager(for: type)
130
+ let view = manager.createView(tag: tag, props: props)
131
+ registry.register(PNViewRecord(tag: tag, typeName: type, view: view, manager: manager))
132
+ manager.didCreate(view: view, tag: tag, props: props)
133
+
134
+ case let .update(tag, changed):
135
+ guard let record = registry.resolve(tag) else {
136
+ PNLog.rateLimited(PNLog.bridge, key: "missing-update", "update for unknown tag \(tag)")
137
+ continue
138
+ }
139
+ record.manager.update(view: record.view, changed: changed)
140
+
141
+ case let .insert(parent, child, index):
142
+ guard let parentRecord = registry.resolve(parent), let childRecord = registry.resolve(child) else {
143
+ PNLog.rateLimited(PNLog.bridge, key: "missing-insert", "insert \(child) into \(parent): unknown tag")
144
+ continue
145
+ }
146
+ parentRecord.manager.insertChild(parent: parentRecord.view, child: childRecord.view, index: index)
147
+
148
+ case let .destroy(tag):
149
+ PNAnimationGraph.forget(tag)
150
+ guard let record = registry.unregister(tag) else { continue }
151
+ if let parentTag = PNLayout.nodes[tag]?.parent, let parentRecord = registry.resolve(parentTag) {
152
+ parentRecord.manager.removeChild(parent: parentRecord.view, child: record.view)
153
+ } else if let parent = record.view.superview,
154
+ let state = PNViewState.existing(for: parent), let parentRecord = registry.resolve(state.tag) {
155
+ parentRecord.manager.removeChild(parent: parent, child: record.view)
156
+ }
157
+ record.manager.destroy(view: record.view)
158
+ PNViewState.detach(record.view)
159
+
160
+ case let .frame(tag, x, y, w, h):
161
+ guard let record = registry.resolve(tag) else { continue }
162
+ record.manager.setFrame(view: record.view, x: x, y: y, w: w, h: h)
163
+ }
164
+ }
165
+ }
166
+ }
@@ -0,0 +1,53 @@
1
+ import UIKit
2
+
3
+ /// One live native view addressed by its reconciler tag.
4
+ public final class PNViewRecord {
5
+ public let tag: Int64
6
+ public let typeName: String
7
+ public let view: UIView
8
+ public let manager: PNComponentManager
9
+
10
+ init(tag: Int64, typeName: String, view: UIView, manager: PNComponentManager) {
11
+ self.tag = tag
12
+ self.typeName = typeName
13
+ self.view = view
14
+ self.manager = manager
15
+ }
16
+ }
17
+
18
+ /// Tag -> view table. Every view created through a transaction is
19
+ /// registered here until its `d` op arrives.
20
+ public final class PNViewRegistry {
21
+ public static let shared = PNViewRegistry()
22
+
23
+ private var records: [Int64: PNViewRecord] = [:]
24
+
25
+ private init() {}
26
+
27
+ /// The record for `tag`, or `nil` when no such view exists.
28
+ public func resolve(_ tag: Int64) -> PNViewRecord? {
29
+ records[tag]
30
+ }
31
+
32
+ /// The registered view for `tag`.
33
+ public func view(for tag: Int64) -> UIView? {
34
+ records[tag]?.view
35
+ }
36
+
37
+ /// Number of live records (used by tests and diagnostics).
38
+ public var count: Int { records.count }
39
+
40
+ func register(_ record: PNViewRecord) {
41
+ records[record.tag] = record
42
+ }
43
+
44
+ @discardableResult
45
+ func unregister(_ tag: Int64) -> PNViewRecord? {
46
+ records.removeValue(forKey: tag)
47
+ }
48
+
49
+ /// Drop every record. Intended for tests.
50
+ public func removeAll() {
51
+ records.removeAll()
52
+ }
53
+ }
@@ -0,0 +1,207 @@
1
+ import UIKit
2
+
3
+ /// A closure-backed `UIControl` target with the duplicate-send filter the
4
+ /// simulator's event injection needs (one `UIEvent`, two action sends).
5
+ public final class PNActionTarget: NSObject {
6
+ private let handler: () -> Void
7
+ private var lastTimestamp: TimeInterval?
8
+
9
+ public init(_ handler: @escaping () -> Void) {
10
+ self.handler = handler
11
+ }
12
+
13
+ /// Attach `handler` to `control` for `events`, retained by the view's state.
14
+ @discardableResult
15
+ public static func attach(_ control: UIControl, events: UIControl.Event, _ handler: @escaping () -> Void) -> PNActionTarget {
16
+ let target = PNActionTarget(handler)
17
+ control.addTarget(target, action: #selector(fire(_:forEvent:)), for: events)
18
+ PNViewState.existing(for: control)?.retained.append(target)
19
+ return target
20
+ }
21
+
22
+ @objc func fire(_ sender: Any?, forEvent event: UIEvent?) {
23
+ if let timestamp = event?.timestamp {
24
+ if lastTimestamp == timestamp {
25
+ PNLog.once(PNLog.components, key: "control-dedupe", "dropped a duplicated control action (one UIEvent, two sends)")
26
+ return
27
+ }
28
+ lastTimestamp = timestamp
29
+ }
30
+ handler()
31
+ }
32
+ }
33
+
34
+ /// `Button`: a system `UIButton` emitting `on_press`.
35
+ public final class PNButtonManager: PNComponentManager {
36
+ public override func makeView(props: [String: Any]) -> UIView {
37
+ UIButton(type: .system)
38
+ }
39
+
40
+ public override func createView(tag: Int64, props: [String: Any]) -> UIView {
41
+ let view = super.createView(tag: tag, props: props)
42
+ if let button = view as? UIButton {
43
+ PNActionTarget.attach(button, events: .touchUpInside) { [weak button] in
44
+ guard let button = button else { return }
45
+ PNEvents.emit(button, "on_press")
46
+ }
47
+ }
48
+ return view
49
+ }
50
+
51
+ public override func apply(view: UIView, props: [String: Any], initial: Bool) {
52
+ guard let button = view as? UIButton else { return }
53
+ if PNProps.has(props, "title") {
54
+ button.setTitle(PNProps.string(PNProps.value(props, "title")) ?? "", for: .normal)
55
+ }
56
+ if let size = PNProps.double(PNProps.value(props, "font_size")) {
57
+ button.titleLabel?.font = UIFont.systemFont(ofSize: CGFloat(size))
58
+ }
59
+ if let color = PNColor.parse(PNProps.value(props, "background_color")) {
60
+ button.backgroundColor = color
61
+ if !PNProps.has(props, "color") {
62
+ button.setTitleColor(.white, for: .normal)
63
+ }
64
+ }
65
+ if let color = PNColor.parse(PNProps.value(props, "color")) {
66
+ button.setTitleColor(color, for: .normal)
67
+ }
68
+ if PNProps.has(props, "disabled") {
69
+ button.isEnabled = !(PNProps.bool(PNProps.value(props, "disabled")) ?? false)
70
+ }
71
+ PNViewStyler.applyDecoration(button, props)
72
+ }
73
+
74
+ public override func measure(view: UIView, maxW: CGFloat, maxH: CGFloat) -> CGSize {
75
+ let intrinsic = view.intrinsicContentSize
76
+ var w = intrinsic.width + 24
77
+ var h = intrinsic.height + 12
78
+ if maxW.isFinite { w = min(w, maxW) }
79
+ if maxH.isFinite { h = min(h, maxH) }
80
+ return CGSize(width: max(w, 44), height: max(h, 32))
81
+ }
82
+ }
83
+
84
+ /// `Checkbox`: an SF Symbol button toggling checked / unchecked.
85
+ public final class PNCheckboxManager: PNComponentManager {
86
+ public override func makeView(props: [String: Any]) -> UIView {
87
+ UIButton(type: .custom)
88
+ }
89
+
90
+ public override func createView(tag: Int64, props: [String: Any]) -> UIView {
91
+ let view = super.createView(tag: tag, props: props)
92
+ if let button = view as? UIButton {
93
+ PNActionTarget.attach(button, events: .touchUpInside) { [weak self, weak button] in
94
+ guard let self = self, let button = button else { return }
95
+ self.toggle(button)
96
+ }
97
+ }
98
+ return view
99
+ }
100
+
101
+ public override func apply(view: UIView, props: [String: Any], initial: Bool) {
102
+ guard let button = view as? UIButton, let state = PNViewState.existing(for: button) else { return }
103
+ if initial {
104
+ let ink = PNColor.parse("#111111") ?? .label
105
+ button.setTitleColor(ink, for: .normal)
106
+ button.tintColor = ink
107
+ }
108
+ if PNProps.has(props, "value") {
109
+ state.extras["value"] = PNProps.bool(PNProps.value(props, "value")) ?? false
110
+ }
111
+ if PNProps.has(props, "label") {
112
+ let label = PNProps.string(PNProps.value(props, "label")) ?? ""
113
+ button.setTitle(label, for: .normal)
114
+ button.accessibilityLabel = label
115
+ }
116
+ if PNProps.has(props, "disabled") {
117
+ button.isEnabled = !(PNProps.bool(PNProps.value(props, "disabled")) ?? false)
118
+ }
119
+ updateImage(button)
120
+ PNViewStyler.applyAccessibility(button, props)
121
+ }
122
+
123
+ private func toggle(_ button: UIButton) {
124
+ guard let state = PNViewState.existing(for: button) else { return }
125
+ if PNProps.bool(PNProps.value(state.props, "disabled")) == true { return }
126
+ let newValue = !state.flag("value")
127
+ // Optimistic flip so the box feels instant; the `value` prop re-syncs it.
128
+ state.extras["value"] = newValue
129
+ updateImage(button)
130
+ PNEvents.emit(button, "on_change", [newValue])
131
+ }
132
+
133
+ private func updateImage(_ button: UIButton) {
134
+ guard let state = PNViewState.existing(for: button) else { return }
135
+ let checked = state.flag("value")
136
+ guard var image = UIImage(systemName: checked ? "checkmark.square.fill" : "square") else { return }
137
+ if checked, let color = PNColor.parse(PNProps.value(state.props, "color")) {
138
+ image = image.withTintColor(color, renderingMode: .alwaysOriginal)
139
+ }
140
+ button.setImage(image, for: .normal)
141
+ }
142
+
143
+ public override func measure(view: UIView, maxW: CGFloat, maxH: CGFloat) -> CGSize {
144
+ let size = view.sizeThatFits(CGSize(width: PNComponentManager.clampConstraint(maxW), height: PNComponentManager.clampConstraint(maxH)))
145
+ var w = max(size.width + 8, 28)
146
+ if maxW.isFinite { w = min(w, maxW) }
147
+ return CGSize(width: w, height: max(size.height, 28))
148
+ }
149
+ }
150
+
151
+ /// `Picker`: a button that presents an action sheet listing the options.
152
+ public final class PNPickerManager: PNComponentManager {
153
+ public override func makeView(props: [String: Any]) -> UIView {
154
+ UIButton(type: .system)
155
+ }
156
+
157
+ public override func createView(tag: Int64, props: [String: Any]) -> UIView {
158
+ let view = super.createView(tag: tag, props: props)
159
+ if let button = view as? UIButton {
160
+ PNActionTarget.attach(button, events: .touchUpInside) { [weak self, weak button] in
161
+ guard let self = self, let button = button else { return }
162
+ self.presentSheet(button)
163
+ }
164
+ }
165
+ return view
166
+ }
167
+
168
+ public override func apply(view: UIView, props: [String: Any], initial: Bool) {
169
+ guard let button = view as? UIButton else { return }
170
+ button.setTitle(PNPickerManager.title(for: mergedProps(button)), for: .normal)
171
+ if PNProps.has(props, "disabled") { button.isEnabled = !(PNProps.bool(PNProps.value(props, "disabled")) ?? false) }
172
+ PNViewStyler.applyAccessibility(button, props)
173
+ }
174
+
175
+ static func items(_ props: [String: Any]) -> [[String: Any]] {
176
+ ((PNProps.value(props, "items") as? [Any]) ?? []).compactMap { $0 as? [String: Any] }
177
+ }
178
+
179
+ static func title(for props: [String: Any]) -> String {
180
+ let selected = PNProps.value(props, "value")
181
+ for item in items(props) {
182
+ if let value = PNProps.value(item, "value"), PNJSON.encode(value) == PNJSON.encode(selected) {
183
+ return PNProps.string(item["label"]) ?? PNProps.string(item["value"]) ?? ""
184
+ }
185
+ }
186
+ return PNProps.string(PNProps.value(props, "placeholder")) ?? "Select…"
187
+ }
188
+
189
+ private func presentSheet(_ button: UIButton) {
190
+ let merged = mergedProps(button)
191
+ let items = PNPickerManager.items(merged)
192
+ var buttons: [[String: Any]] = items.map { ["label": PNProps.string($0["label"]) ?? PNProps.string($0["value"]) ?? ""] }
193
+ buttons.append(["label": "Cancel", "style": "cancel"])
194
+ PNAlertPresenter.present(
195
+ title: PNProps.string(PNProps.value(merged, "placeholder")) ?? "Select…",
196
+ message: nil, buttons: buttons, style: "action_sheet"
197
+ ) { index in
198
+ guard index >= 0, index < items.count else { return }
199
+ PNEvents.emit(button, "on_change", [PNProps.value(items[index], "value")])
200
+ }
201
+ }
202
+
203
+ public override func measure(view: UIView, maxW: CGFloat, maxH: CGFloat) -> CGSize {
204
+ let size = view.sizeThatFits(CGSize(width: PNComponentManager.clampConstraint(maxW), height: PNComponentManager.clampConstraint(maxH)))
205
+ return CGSize(width: size.width + 16, height: size.height + 8)
206
+ }
207
+ }