pythonnative 0.40.0__cp314-cp314-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.cp314-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,785 @@
1
+ """Keyed virtualized lists with one logical component tree."""
2
+
3
+ import bisect
4
+ from typing import Any, Callable, Dict, List, Optional, Tuple
5
+
6
+ from ..component import component
7
+ from ..element import Element
8
+ from ..hooks import Ref, use_imperative_handle, use_memo, use_ref, use_state
9
+ from ..style import StyleProp, resolve_style
10
+ from .layout import Column, Row, ScrollView, View
11
+ from .text import Text
12
+
13
+ _DEFAULT_ROW_EXTENT = 44.0
14
+
15
+
16
+ class _RowSpec:
17
+ """One virtualized row: a stable key, a lazy renderer, and an extent hint."""
18
+
19
+ __slots__ = ("key", "make", "extent", "item", "index")
20
+
21
+ def __init__(
22
+ self,
23
+ key: str,
24
+ make: Callable[[], Element],
25
+ extent: Optional[float],
26
+ item: Any = None,
27
+ index: int = 0,
28
+ ) -> None:
29
+ self.key = key
30
+ self.make = make
31
+ self.extent = extent
32
+ self.item = item
33
+ self.index = index
34
+
35
+
36
+ def _dispatch_scroll_command(scroll_ref: Any, name: str, args: Dict[str, Any]) -> Any:
37
+ """Send an imperative command to the ScrollView under ``scroll_ref``."""
38
+ tag = getattr(scroll_ref, "_pn_tag", None)
39
+ if tag is None:
40
+ return None
41
+ from ..native_views import get_registry
42
+
43
+ try:
44
+ return get_registry().command(tag, name, args)
45
+ except Exception:
46
+ return None
47
+
48
+
49
+ class ListController:
50
+ """Imperative scroll handle published on a list's ``ref``.
51
+
52
+ [`FlatList`][pythonnative.FlatList] and
53
+ [`SectionList`][pythonnative.SectionList] install a
54
+ ``ListController`` on ``ref.current`` (via
55
+ [`use_imperative_handle`][pythonnative.use_imperative_handle])
56
+ after mount and clear it back to ``None`` on unmount.
57
+
58
+ Example:
59
+ ```python
60
+ import pythonnative as pn
61
+
62
+ @pn.component
63
+ def Chat(messages):
64
+ list_ref = pn.use_ref()
65
+ pn.use_layout_effect(
66
+ lambda: list_ref.current and list_ref.current.scroll_to_end(animated=False),
67
+ [len(messages)],
68
+ )
69
+ return pn.FlatList(data=messages, render_item=Bubble, ref=list_ref)
70
+ ```
71
+ """
72
+
73
+ __slots__ = ("_scroll_to_offset", "_scroll_to_index", "_scroll_to_end")
74
+
75
+ def __init__(
76
+ self,
77
+ scroll_to_offset: Callable[[float, bool], None],
78
+ scroll_to_index: Callable[[int, bool], None],
79
+ scroll_to_end: Callable[[bool], None],
80
+ ) -> None:
81
+ self._scroll_to_offset = scroll_to_offset
82
+ self._scroll_to_index = scroll_to_index
83
+ self._scroll_to_end = scroll_to_end
84
+
85
+ def scroll_to_offset(self, offset: float, animated: bool = True) -> None:
86
+ """Scroll to an absolute content offset in points."""
87
+ self._scroll_to_offset(offset, animated)
88
+
89
+ def scroll_to_index(self, index: int, animated: bool = True) -> None:
90
+ """Scroll so the row at ``index`` sits at the top of the viewport."""
91
+ self._scroll_to_index(index, animated)
92
+
93
+ def scroll_to_end(self, animated: bool = True) -> None:
94
+ """Scroll to the end of the content."""
95
+ self._scroll_to_end(animated)
96
+
97
+
98
+ @component
99
+ def _VirtualizedList(
100
+ rows: Optional[List[_RowSpec]] = None,
101
+ horizontal: bool = False,
102
+ estimated_row_extent: Optional[float] = None,
103
+ overscan_extent: Optional[float] = None,
104
+ initial_window_extent: Optional[float] = None,
105
+ header: Optional[Element] = None,
106
+ footer: Optional[Element] = None,
107
+ empty: Optional[Element] = None,
108
+ refresh_control: Optional[Element] = None,
109
+ on_end_reached: Optional[Callable[[], Any]] = None,
110
+ on_end_reached_threshold: Optional[float] = None,
111
+ on_viewable_items_changed: Optional[Callable[[List[Dict[str, Any]]], None]] = None,
112
+ on_scroll: Optional[Callable[[Any], Any]] = None,
113
+ shows_scroll_indicator: bool = True,
114
+ content_container_style: Optional[Dict[str, Any]] = None,
115
+ list_style: Optional[Dict[str, Any]] = None,
116
+ controller_ref: Optional[Ref] = None,
117
+ ) -> Element:
118
+ """Shared windowing engine behind FlatList and SectionList."""
119
+ rows = rows or []
120
+ n = len(rows)
121
+ horizontal = bool(horizontal)
122
+ estimated: float = float(estimated_row_extent or _DEFAULT_ROW_EXTENT)
123
+ overscan: float = float(overscan_extent or 0.0)
124
+ initial_extent: float = float(initial_window_extent or 800.0)
125
+
126
+ window, set_window = use_state((0, -1))
127
+ measured: Ref[Dict[str, float]] = use_ref({}) # row key -> measured extent (points)
128
+ row_refs: Ref[Dict[str, Ref]] = use_ref({}) # row key -> Ref for live rows
129
+ end_latch = use_ref({"fired_for": -1})
130
+ viewable_ref: Ref[Dict[str, Tuple[str, ...]]] = use_ref({"keys": ()})
131
+ scroll_pos = use_ref({"offset": 0.0})
132
+ sv_ref: Ref = use_ref(None)
133
+
134
+ # ------------------------------------------------------------------
135
+ # Extent model: measured > per-row hint > estimate. ``starts`` are
136
+ # prefix sums; ``starts[n]`` is the total content extent.
137
+ # ------------------------------------------------------------------
138
+ measured_map: Dict[str, float] = measured.current
139
+ starts: List[float] = [0.0] * (n + 1)
140
+ acc = 0.0
141
+ for i, spec in enumerate(rows):
142
+ starts[i] = acc
143
+ extent = measured_map.get(spec.key)
144
+ if extent is None:
145
+ extent = spec.extent if spec.extent is not None else estimated
146
+ acc += max(0.0, float(extent))
147
+ starts[n] = acc
148
+ total_extent = acc
149
+
150
+ def _viewport_extent() -> float:
151
+ frame = sv_ref._pn_frame
152
+ if frame:
153
+ extent = frame[2] if horizontal else frame[3]
154
+ if extent and extent > 0:
155
+ return float(extent)
156
+ return initial_extent
157
+
158
+ def _window_for(offset: float, viewport: float) -> Tuple[int, int]:
159
+ if n == 0:
160
+ return (0, -1)
161
+ pad = overscan if overscan > 0 else viewport
162
+ lo = max(0.0, offset - pad)
163
+ hi = offset + viewport + pad
164
+ first = max(0, bisect.bisect_right(starts, lo, 0, n) - 1)
165
+ last = min(n - 1, bisect.bisect_left(starts, hi, 0, n))
166
+ return (first, last)
167
+
168
+ first, last = window
169
+ if last < 0 or first >= n:
170
+ first, last = _window_for(scroll_pos.current["offset"], _viewport_extent())
171
+ last = min(last, n - 1)
172
+ first = max(0, min(first, max(0, n - 1)))
173
+
174
+ # ------------------------------------------------------------------
175
+ # Scroll handling: sweep measured extents, shift the window, fire
176
+ # end-reached / viewability callbacks. State only changes when the
177
+ # window actually moves, so steady scrolling inside the overscan
178
+ # region costs no re-render.
179
+ # ------------------------------------------------------------------
180
+ end_threshold = float(on_end_reached_threshold or 0.5)
181
+ on_viewable = on_viewable_items_changed
182
+ user_on_scroll = on_scroll
183
+
184
+ def _sweep_measured() -> None:
185
+ for row_key, row_ref in row_refs.current.items():
186
+ frame = getattr(row_ref, "_pn_frame", None)
187
+ if frame:
188
+ extent = frame[2] if horizontal else frame[3]
189
+ if extent and extent > 0:
190
+ measured_map[row_key] = float(extent)
191
+
192
+ def _handle_scroll(payload: Any) -> None:
193
+ if isinstance(payload, dict):
194
+ offset = float(payload.get("x" if horizontal else "y", 0.0) or 0.0)
195
+ else:
196
+ offset = float(payload or 0.0)
197
+ scroll_pos.current["offset"] = offset
198
+ _sweep_measured()
199
+ viewport = _viewport_extent()
200
+
201
+ new_window = _window_for(offset, viewport)
202
+ if new_window != (first, last):
203
+ set_window(new_window)
204
+
205
+ if on_end_reached is not None and total_extent > 0:
206
+ remaining = total_extent - (offset + viewport)
207
+ if remaining <= end_threshold * viewport:
208
+ if end_latch.current["fired_for"] != n:
209
+ end_latch.current["fired_for"] = n
210
+ on_end_reached()
211
+ elif remaining > end_threshold * viewport + viewport:
212
+ end_latch.current["fired_for"] = -1
213
+
214
+ if on_viewable is not None and n > 0:
215
+ v_first = max(0, bisect.bisect_right(starts, offset, 0, n) - 1)
216
+ v_last = min(n - 1, bisect.bisect_left(starts, offset + viewport, 0, n))
217
+ keys = tuple(rows[i].key for i in range(v_first, v_last + 1))
218
+ if keys != viewable_ref.current["keys"]:
219
+ viewable_ref.current["keys"] = keys
220
+ on_viewable(
221
+ [
222
+ {"index": rows[i].index, "key": rows[i].key, "item": rows[i].item}
223
+ for i in range(v_first, v_last + 1)
224
+ ]
225
+ )
226
+
227
+ if user_on_scroll is not None:
228
+ user_on_scroll(payload)
229
+
230
+ # ------------------------------------------------------------------
231
+ # Imperative controller (scroll_to_index / offset / end) published
232
+ # on the user's ref. Rebuilt every render (deps=None) so the
233
+ # closures see fresh extents.
234
+ # ------------------------------------------------------------------
235
+ def _scroll_to_offset(offset: float, animated: bool = True) -> None:
236
+ axis = "x" if horizontal else "y"
237
+ _dispatch_scroll_command(sv_ref, "scroll_to_offset", {axis: float(offset), "animated": animated})
238
+
239
+ def _scroll_to_index(index: int, animated: bool = True) -> None:
240
+ idx = max(0, min(int(index), n - 1)) if n else 0
241
+ _scroll_to_offset(starts[idx], animated)
242
+
243
+ def _scroll_to_end(animated: bool = True) -> None:
244
+ _scroll_to_offset(max(0.0, total_extent - _viewport_extent()), animated)
245
+
246
+ use_imperative_handle(
247
+ controller_ref,
248
+ lambda: ListController(_scroll_to_offset, _scroll_to_index, _scroll_to_end),
249
+ None,
250
+ )
251
+
252
+ # ------------------------------------------------------------------
253
+ # Children: header, leading spacer, windowed rows, trailing spacer,
254
+ # footer. Rows keep per-key refs so their measured extents survive
255
+ # recycling.
256
+ # ------------------------------------------------------------------
257
+ spacer_key = "width" if horizontal else "height"
258
+ children: List[Element] = []
259
+ if header is not None:
260
+ children.append(View(header, key="__pn_header__"))
261
+
262
+ if n == 0:
263
+ if empty is not None:
264
+ children.append(View(empty, key="__pn_empty__"))
265
+ else:
266
+ live_refs: Dict[str, Ref] = {}
267
+ lead = starts[first]
268
+ if lead > 0:
269
+ lead_style: Dict[str, Any] = {spacer_key: lead}
270
+ children.append(View(style=lead_style, key="__pn_lead__"))
271
+ for i in range(first, last + 1):
272
+ spec = rows[i]
273
+ row_ref = row_refs.current.get(spec.key) or Ref()
274
+ live_refs[spec.key] = row_ref
275
+ children.append(View(spec.make(), ref=row_ref, key=spec.key))
276
+ row_refs.current = live_refs
277
+ trail = total_extent - starts[last + 1]
278
+ if trail > 0:
279
+ trail_style: Dict[str, Any] = {spacer_key: trail}
280
+ children.append(View(style=trail_style, key="__pn_trail__"))
281
+
282
+ if footer is not None:
283
+ children.append(View(footer, key="__pn_footer__"))
284
+
285
+ wrapper = Row if horizontal else Column
286
+ inner = wrapper(*children, style=content_container_style)
287
+ return ScrollView(
288
+ inner,
289
+ scroll_axis="horizontal" if horizontal else "vertical",
290
+ on_scroll=_handle_scroll,
291
+ refresh_control=refresh_control,
292
+ shows_scroll_indicator=shows_scroll_indicator,
293
+ style=list_style,
294
+ ref=sv_ref,
295
+ )
296
+
297
+
298
+ def _native_lists_supported() -> bool:
299
+ """Whether the natively virtualized list path is available.
300
+
301
+ Android (RecyclerView) and iOS (UICollectionView) have native handlers;
302
+ the browser preview and off-device tests use the Python-windowed
303
+ engine. Patchable in tests to exercise the native routing.
304
+ """
305
+ from ..native_views import get_registry
306
+ from ..utils import IS_ANDROID, IS_IOS
307
+
308
+ return IS_ANDROID or IS_IOS or getattr(get_registry(), "native_layout", False)
309
+
310
+
311
+ def _use_native_lists() -> bool:
312
+ """Resolve ``_native_lists_supported`` through the package at call time.
313
+
314
+ Looking the function up on ``pythonnative.components`` (rather than
315
+ this module's globals) keeps
316
+ ``monkeypatch.setattr(pythonnative.components, "_native_lists_supported", ...)``
317
+ effective now that the implementation lives in a submodule.
318
+ """
319
+ from . import _native_lists_supported as supported
320
+
321
+ return supported()
322
+
323
+
324
+ @component
325
+ def _NativeList(
326
+ rows: Optional[List[_RowSpec]] = None,
327
+ on_end_reached: Optional[Callable[[], Any]] = None,
328
+ on_end_reached_threshold: Optional[float] = None,
329
+ on_viewable_items_changed: Optional[Callable[[List[Dict[str, Any]]], None]] = None,
330
+ on_scroll: Optional[Callable[[Dict[str, float]], None]] = None,
331
+ shows_scroll_indicator: Optional[bool] = None,
332
+ list_style: Optional[Dict[str, Any]] = None,
333
+ controller_ref: Optional[Ref] = None,
334
+ horizontal: bool = False,
335
+ estimated_row_extent: float = 44,
336
+ header: Optional[Element] = None,
337
+ footer: Optional[Element] = None,
338
+ empty: Optional[Element] = None,
339
+ refresh_control: Optional[Element] = None,
340
+ content_container_style: Optional[Dict[str, Any]] = None,
341
+ ) -> Element:
342
+ """Prepare a bounded set of logical rows for native recycled containers.
343
+
344
+ Keys own hooks. Native container identities never enter the component
345
+ tree. Every data snapshot has a revision, including same-length edits.
346
+ """
347
+ source = rows or []
348
+ rows = list(source)
349
+ if not rows and empty is not None:
350
+ rows.append(_RowSpec("__empty__", lambda: empty, None))
351
+ if header is not None:
352
+ rows.insert(0, _RowSpec("__header__", lambda: header, None))
353
+ if footer is not None:
354
+ rows.append(_RowSpec("__footer__", lambda: footer, None))
355
+ keys = [row.key for row in rows]
356
+ if len(set(keys)) != len(keys):
357
+ raise ValueError("List keys must be unique")
358
+ generation = use_ref(0)
359
+
360
+ def next_revision() -> int:
361
+ generation.current += 1
362
+ return generation.current
363
+
364
+ revision = use_memo(next_revision, [source, header, footer, empty])
365
+ center, set_center = use_state(0)
366
+ first, last = max(0, center - 16), min(len(rows), center + 40)
367
+ internal_ref: Ref = use_ref()
368
+ end_revision = use_ref(-1)
369
+
370
+ def bind(info: Dict[str, Any]) -> None:
371
+ if info.get("revision") != revision:
372
+ return
373
+ index = int(info.get("index", -1))
374
+ if not 0 <= index < len(rows) or info.get("key") != keys[index]:
375
+ return
376
+ if index < first + 8 or index >= last - 8:
377
+ set_center(index)
378
+
379
+ def scroll(info: Dict[str, Any]) -> Any:
380
+ if on_end_reached is not None:
381
+ remaining = info.get("range", 0) - info.get("x" if horizontal else "y", 0) - info.get("extent", 0)
382
+ if (
383
+ remaining <= (on_end_reached_threshold or 0.5) * info.get("extent", 0)
384
+ and end_revision.current != revision
385
+ ):
386
+ end_revision.current = revision
387
+ from ..runtime import invoke
388
+
389
+ invoke(on_end_reached)
390
+ if on_viewable_items_changed is not None:
391
+ start, end = int(info.get("first", 0)), int(info.get("last", -1))
392
+ from ..runtime import invoke
393
+
394
+ invoke(
395
+ on_viewable_items_changed,
396
+ [
397
+ {"key": rows[i].key, "index": rows[i].index, "item": rows[i].item}
398
+ for i in range(max(0, start), min(len(rows), end + 1))
399
+ ],
400
+ )
401
+ return on_scroll(info) if on_scroll is not None else None
402
+
403
+ use_imperative_handle(
404
+ controller_ref,
405
+ lambda: ListController(
406
+ lambda offset, animated: _dispatch_scroll_command(
407
+ internal_ref, "scroll_to_offset", {"x" if horizontal else "y": offset, "animated": animated}
408
+ ),
409
+ lambda index, animated: _dispatch_scroll_command(
410
+ internal_ref, "scroll_to_index", {"index": index, "animated": animated}
411
+ ),
412
+ lambda animated: _dispatch_scroll_command(internal_ref, "scroll_to_end", {"animated": animated}),
413
+ ),
414
+ [horizontal],
415
+ )
416
+ props = {
417
+ "flex_grow": 1,
418
+ **(list_style or {}),
419
+ "keys": keys,
420
+ "revision": revision,
421
+ "count": len(rows),
422
+ "row_heights": [r.extent or estimated_row_extent for r in rows],
423
+ "horizontal": horizontal,
424
+ "on_bind_row": bind,
425
+ "on_scroll": scroll,
426
+ "shows_scroll_indicator": shows_scroll_indicator is not False,
427
+ "ref": internal_ref,
428
+ }
429
+ if refresh_control is not None:
430
+ props["refresh_control"] = dict(refresh_control.props)
431
+ children = []
432
+ for row in rows[first:last]:
433
+ style = dict(content_container_style or {})
434
+ if row.extent is not None:
435
+ style["width" if horizontal else "height"] = row.extent
436
+ if not horizontal:
437
+ style["width"] = "100%"
438
+ child = View(row.make(), style=style, key=row.key)
439
+ child.props["_pn_list_key"] = row.key
440
+ children.append(child)
441
+ return Element("VirtualList", props, children)
442
+
443
+
444
+ def FlatList(
445
+ *,
446
+ data: Optional[List[Any]] = None,
447
+ render_item: Optional[Callable[[Any, int], Element]] = None,
448
+ key_extractor: Optional[Callable[[Any, int], str]] = None,
449
+ item_height: Optional[float] = None,
450
+ get_item_height: Optional[Callable[[Any, int], float]] = None,
451
+ estimated_item_height: Optional[float] = None,
452
+ separator_height: float = 0,
453
+ refresh_control: Optional[Element] = None,
454
+ horizontal: bool = False,
455
+ num_columns: int = 1,
456
+ list_header: Optional[Element] = None,
457
+ list_footer: Optional[Element] = None,
458
+ list_empty: Optional[Element] = None,
459
+ on_end_reached: Optional[Callable[[], Any]] = None,
460
+ on_end_reached_threshold: float = 0.5,
461
+ on_viewable_items_changed: Optional[Callable[[List[Dict[str, Any]]], None]] = None,
462
+ on_scroll: Optional[Callable[[Dict[str, float]], None]] = None,
463
+ shows_scroll_indicator: bool = True,
464
+ content_container_style: StyleProp = None,
465
+ style: StyleProp = None,
466
+ ref: Optional[Ref] = None,
467
+ key: Optional[str] = None,
468
+ ) -> Element:
469
+ """Virtualized scrollable list that renders items from ``data`` lazily.
470
+
471
+ Only the rows inside (and just beyond) the viewport are mounted;
472
+ leading and trailing spacers stand in for everything else, and the
473
+ window shifts as the user scrolls. Rows may have **variable
474
+ heights**: pass ``item_height`` when rows are uniform,
475
+ ``get_item_height`` for exact per-item extents, or nothing at all;
476
+ unknown rows start at ``estimated_item_height`` and are corrected
477
+ with their measured extent once they've been on screen.
478
+
479
+ Pass a [`Ref`][pythonnative.Ref] (from
480
+ [`use_ref`][pythonnative.use_ref]) to receive a
481
+ [`ListController`][pythonnative.ListController] on ``ref.current``:
482
+ ``ref.current.scroll_to_index(i)``,
483
+ ``ref.current.scroll_to_offset(pts)``, and
484
+ ``ref.current.scroll_to_end()``.
485
+
486
+ Args:
487
+ data: List of arbitrary item values.
488
+ render_item: ``render_item(item, index) -> Element``. Defaults
489
+ to wrapping each item in a [`Text`][pythonnative.Text].
490
+ key_extractor: Function returning a stable key per item
491
+ (recommended whenever ``data`` can reorder).
492
+ item_height: Uniform row extent in points, when known.
493
+ get_item_height: ``get_item_height(item, index) -> float`` for
494
+ exact variable extents without measurement.
495
+ estimated_item_height: Starting extent estimate for rows whose
496
+ true size isn't known yet (default 44).
497
+ separator_height: Gap below each row, in points.
498
+ refresh_control: Optional [`RefreshControl`][pythonnative.RefreshControl]
499
+ element for pull-to-refresh.
500
+ horizontal: Scroll horizontally (extents become widths).
501
+ num_columns: Render items in a grid of this many columns.
502
+ list_header: Element rendered once before all rows.
503
+ list_footer: Element rendered once after all rows.
504
+ list_empty: Element rendered when ``data`` is empty.
505
+ on_end_reached: Called when the user scrolls within
506
+ ``on_end_reached_threshold`` viewports of the end (fires
507
+ once per data length).
508
+ on_end_reached_threshold: Distance from the end, in viewport
509
+ multiples, at which ``on_end_reached`` fires.
510
+ on_viewable_items_changed: Called with a list of
511
+ ``{"index", "key", "item"}`` dicts whenever the set of
512
+ visible rows changes.
513
+ on_scroll: Called with the raw scroll payload
514
+ (``{"x": …, "y": …}``).
515
+ shows_scroll_indicator: When ``False``, hides the scroll bar.
516
+ content_container_style: Style applied to the inner content
517
+ wrapper.
518
+ style: Style for the outer scroll container.
519
+ ref: Optional [`Ref`][pythonnative.Ref]; receives a
520
+ [`ListController`][pythonnative.ListController] on
521
+ ``ref.current`` after mount.
522
+ key: Stable identity for keyed reconciliation of the list.
523
+
524
+ Returns:
525
+ A virtualized list element (a function component instance).
526
+
527
+ Example:
528
+ ```python
529
+ import pythonnative as pn
530
+
531
+ items = [{"id": i, "name": f"Item {i}"} for i in range(10000)]
532
+
533
+ pn.FlatList(
534
+ data=items,
535
+ item_height=44,
536
+ render_item=lambda item, _: pn.Text(item["name"]),
537
+ key_extractor=lambda item, _: str(item["id"]),
538
+ )
539
+ ```
540
+ """
541
+ items_list = list(data or [])
542
+ sep = float(separator_height or 0.0)
543
+
544
+ def _row_key(item: Any, index: int) -> str:
545
+ if key_extractor is not None:
546
+ try:
547
+ return str(key_extractor(item, index))
548
+ except Exception:
549
+ pass
550
+ return f"__pn_row_{index}__"
551
+
552
+ def _row_extent(item: Any, index: int) -> Optional[float]:
553
+ if get_item_height is not None:
554
+ try:
555
+ return float(get_item_height(item, index)) + sep
556
+ except Exception:
557
+ return None
558
+ if item_height is not None:
559
+ return float(item_height) + sep
560
+ return None
561
+
562
+ def _make_row(item: Any, index: int) -> Callable[[], Element]:
563
+ def _make() -> Element:
564
+ el = render_item(item, index) if render_item else Text(str(item))
565
+ if sep > 0:
566
+ pad_style: Dict[str, Any] = {"padding_end" if horizontal else "padding_bottom": sep}
567
+ return View(el, style=pad_style)
568
+ return el
569
+
570
+ return _make
571
+
572
+ rows: List[_RowSpec] = []
573
+ if num_columns > 1 and not horizontal:
574
+ for start in range(0, len(items_list), num_columns):
575
+ chunk = items_list[start : start + num_columns]
576
+
577
+ def _make_group(group: List[Any] = chunk, base: int = start) -> Element:
578
+ cells = [
579
+ View(
580
+ render_item(it, base + j) if render_item else Text(str(it)),
581
+ style={"flex": 1},
582
+ key=_row_key(it, base + j),
583
+ )
584
+ for j, it in enumerate(group)
585
+ ]
586
+ row = Row(*cells)
587
+ if sep > 0:
588
+ return View(row, style={"padding_bottom": sep})
589
+ return row
590
+
591
+ group_key = "__pn_grp_" + "|".join(_row_key(it, start + j) for j, it in enumerate(chunk))
592
+ extent = (float(item_height) + sep) if item_height is not None else None
593
+ rows.append(_RowSpec(group_key, _make_group, extent, item=chunk, index=start))
594
+ else:
595
+ for i, item in enumerate(items_list):
596
+ rows.append(_RowSpec(_row_key(item, i), _make_row(item, i), _row_extent(item, i), item=item, index=i))
597
+
598
+ estimated = estimated_item_height if estimated_item_height is not None else (item_height or _DEFAULT_ROW_EXTENT)
599
+
600
+ if _use_native_lists():
601
+ return _NativeList(
602
+ rows=rows,
603
+ on_end_reached=on_end_reached,
604
+ on_end_reached_threshold=on_end_reached_threshold,
605
+ on_viewable_items_changed=on_viewable_items_changed,
606
+ on_scroll=on_scroll,
607
+ shows_scroll_indicator=shows_scroll_indicator,
608
+ list_style=resolve_style(style) or None,
609
+ controller_ref=ref,
610
+ horizontal=horizontal,
611
+ estimated_row_extent=float(estimated) + sep,
612
+ header=list_header,
613
+ footer=list_footer,
614
+ empty=list_empty,
615
+ refresh_control=refresh_control,
616
+ content_container_style=resolve_style(content_container_style) or None,
617
+ ).with_key(key)
618
+
619
+ return _VirtualizedList(
620
+ rows=rows,
621
+ horizontal=horizontal,
622
+ estimated_row_extent=float(estimated) + sep,
623
+ header=list_header,
624
+ footer=list_footer,
625
+ empty=list_empty,
626
+ refresh_control=refresh_control,
627
+ on_end_reached=on_end_reached,
628
+ on_end_reached_threshold=on_end_reached_threshold,
629
+ on_viewable_items_changed=on_viewable_items_changed,
630
+ on_scroll=on_scroll,
631
+ shows_scroll_indicator=shows_scroll_indicator,
632
+ content_container_style=resolve_style(content_container_style) or None,
633
+ list_style=resolve_style(style) or None,
634
+ controller_ref=ref,
635
+ ).with_key(key)
636
+
637
+
638
+ def SectionList(
639
+ *,
640
+ sections: Optional[List[Dict[str, Any]]] = None,
641
+ render_item: Optional[Callable[[Any, int, int], Element]] = None,
642
+ render_section_header: Optional[Callable[[Dict[str, Any], int], Element]] = None,
643
+ key_extractor: Optional[Callable[[Any, int], str]] = None,
644
+ item_height: Optional[float] = None,
645
+ get_item_height: Optional[Callable[[Any, int, int], float]] = None,
646
+ estimated_item_height: Optional[float] = None,
647
+ section_header_height: Optional[float] = None,
648
+ separator_height: float = 0,
649
+ refresh_control: Optional[Element] = None,
650
+ list_header: Optional[Element] = None,
651
+ list_footer: Optional[Element] = None,
652
+ list_empty: Optional[Element] = None,
653
+ on_end_reached: Optional[Callable[[], Any]] = None,
654
+ on_end_reached_threshold: float = 0.5,
655
+ on_scroll: Optional[Callable[[Dict[str, float]], None]] = None,
656
+ style: StyleProp = None,
657
+ ref: Optional[Ref] = None,
658
+ key: Optional[str] = None,
659
+ ) -> Element:
660
+ """Virtualized list with section headers interleaved between row groups.
661
+
662
+ Flattens ``sections`` into a single virtualized sequence where each
663
+ entry is either a header or an item, then reuses the same windowing
664
+ engine as [`FlatList`][pythonnative.FlatList]; headers and items
665
+ may have different (and variable) heights.
666
+
667
+ Args:
668
+ sections: Each section is ``{"title": ..., "data": [...]}``.
669
+ render_item: ``render_item(item, item_index, section_index) ->
670
+ Element``.
671
+ render_section_header: ``render_section_header(section,
672
+ section_index) -> Element``. Defaults to a bold
673
+ [`Text`][pythonnative.Text] of the section title.
674
+ key_extractor: Stable key per item: ``key_extractor(item,
675
+ item_index) -> str``.
676
+ item_height: Uniform item extent in points, when known.
677
+ get_item_height: ``get_item_height(item, item_index,
678
+ section_index) -> float`` for exact variable extents.
679
+ estimated_item_height: Starting estimate for unmeasured rows.
680
+ section_header_height: Header extent in points, when known.
681
+ separator_height: Gap below each item, in points.
682
+ refresh_control: Optional [`RefreshControl`][pythonnative.RefreshControl] element.
683
+ list_header: Element rendered once before everything.
684
+ list_footer: Element rendered once after everything.
685
+ list_empty: Element rendered when there are no sections.
686
+ on_end_reached: Called near the end of the content.
687
+ on_end_reached_threshold: Distance from the end, in viewport
688
+ multiples, at which ``on_end_reached`` fires.
689
+ on_scroll: Called with the raw scroll payload.
690
+ style: Style for the outer scroll container.
691
+ ref: Optional [`Ref`][pythonnative.Ref]; receives a
692
+ [`ListController`][pythonnative.ListController] on
693
+ ``ref.current`` after mount.
694
+ key: Stable identity for keyed reconciliation of the list.
695
+
696
+ Returns:
697
+ A virtualized list element (a function component instance).
698
+ """
699
+ sections_list = list(sections or [])
700
+ sep = float(separator_height or 0.0)
701
+
702
+ def _header_el(section: Dict[str, Any], s_idx: int) -> Element:
703
+ if render_section_header is not None:
704
+ return render_section_header(section, s_idx)
705
+ return Text(str(section.get("title", "")), style={"bold": True, "padding": 8})
706
+
707
+ def _item_el(item: Any, i_idx: int, s_idx: int) -> Element:
708
+ if render_item is not None:
709
+ return render_item(item, i_idx, s_idx)
710
+ return Text(str(item))
711
+
712
+ rows: List[_RowSpec] = []
713
+ flat_index = 0
714
+ for s_idx, section in enumerate(sections_list):
715
+
716
+ def _make_header(sec: Dict[str, Any] = section, si: int = s_idx) -> Element:
717
+ return _header_el(sec, si)
718
+
719
+ rows.append(
720
+ _RowSpec(
721
+ f"__pn_sec_{s_idx}__",
722
+ _make_header,
723
+ float(section_header_height) if section_header_height is not None else None,
724
+ item=section,
725
+ index=flat_index,
726
+ )
727
+ )
728
+ flat_index += 1
729
+ for i_idx, item in enumerate(section.get("data", []) or []):
730
+ if key_extractor is not None:
731
+ try:
732
+ row_key = f"s{s_idx}:" + str(key_extractor(item, i_idx))
733
+ except Exception:
734
+ row_key = f"__pn_row_{s_idx}_{i_idx}__"
735
+ else:
736
+ row_key = f"__pn_row_{s_idx}_{i_idx}__"
737
+
738
+ def _make_item(it: Any = item, ii: int = i_idx, si: int = s_idx) -> Element:
739
+ el = _item_el(it, ii, si)
740
+ if sep > 0:
741
+ return View(el, style={"padding_bottom": sep})
742
+ return el
743
+
744
+ extent: Optional[float] = None
745
+ if get_item_height is not None:
746
+ try:
747
+ extent = float(get_item_height(item, i_idx, s_idx)) + sep
748
+ except Exception:
749
+ extent = None
750
+ elif item_height is not None:
751
+ extent = float(item_height) + sep
752
+ rows.append(_RowSpec(row_key, _make_item, extent, item=item, index=flat_index))
753
+ flat_index += 1
754
+
755
+ estimated = estimated_item_height if estimated_item_height is not None else (item_height or _DEFAULT_ROW_EXTENT)
756
+
757
+ if _use_native_lists():
758
+ return _NativeList(
759
+ rows=rows,
760
+ on_end_reached=on_end_reached,
761
+ on_end_reached_threshold=on_end_reached_threshold,
762
+ on_scroll=on_scroll,
763
+ list_style=resolve_style(style) or None,
764
+ controller_ref=ref,
765
+ estimated_row_extent=float(estimated) + sep,
766
+ header=list_header,
767
+ footer=list_footer,
768
+ empty=list_empty,
769
+ refresh_control=refresh_control,
770
+ ).with_key(key)
771
+
772
+ return _VirtualizedList(
773
+ rows=rows,
774
+ horizontal=False,
775
+ estimated_row_extent=float(estimated) + sep,
776
+ header=list_header,
777
+ footer=list_footer,
778
+ empty=list_empty,
779
+ refresh_control=refresh_control,
780
+ on_end_reached=on_end_reached,
781
+ on_end_reached_threshold=on_end_reached_threshold,
782
+ on_scroll=on_scroll,
783
+ list_style=resolve_style(style) or None,
784
+ controller_ref=ref,
785
+ ).with_key(key)