nextpy-framework 3.7.3__tar.gz → 3.8.0__tar.gz

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 (143) hide show
  1. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/__init__.py +1 -1
  2. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/cli.py +101 -361
  3. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/component_renderer.py +19 -11
  4. nextpy_framework-3.8.0/.nextpy_framework/nextpy/main.py +72 -0
  5. nextpy_framework-3.8.0/.nextpy_framework/nextpy/psx/compiler/actions.py +878 -0
  6. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/compiler/handler_compiler.py +52 -11
  7. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/components/component.py +18 -6
  8. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/core/parser.py +117 -30
  9. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/core/runtime.py +15 -4
  10. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/hydration/decorators.py +460 -136
  11. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/hydration/engine.py +60 -1
  12. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/hydration/integration.py +18 -4
  13. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/runtime/actions_runtime.py +157 -11
  14. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/runtime/js_actions_runtime.py +232 -52
  15. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0/.nextpy_framework/nextpy_framework.egg-info}/PKG-INFO +1 -1
  16. {nextpy_framework-3.7.3/.nextpy_framework/nextpy_framework.egg-info → nextpy_framework-3.8.0}/PKG-INFO +1 -1
  17. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/pyproject.toml +1 -1
  18. nextpy_framework-3.7.3/.nextpy_framework/nextpy/main.py +0 -81
  19. nextpy_framework-3.7.3/.nextpy_framework/nextpy/psx/compiler/actions.py +0 -431
  20. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/ast_parser.py +0 -0
  21. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/auth.py +0 -0
  22. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/builder.py +0 -0
  23. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/__init__.py +0 -0
  24. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/debug/AutoDebug.py +0 -0
  25. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/debug/AutoDebug_v3.py +0 -0
  26. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/debug/DebugIcon.py +0 -0
  27. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/debug/DebugIconFixed.py +0 -0
  28. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/feedback.py +0 -0
  29. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/form.py +0 -0
  30. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/head.py +0 -0
  31. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/hooks_provider.py +0 -0
  32. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/image.py +0 -0
  33. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/layout.py +0 -0
  34. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/link.py +0 -0
  35. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/loader.py +0 -0
  36. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/navigation.py +0 -0
  37. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/toast.py +0 -0
  38. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/ui.py +0 -0
  39. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/visual.py +0 -0
  40. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components.py +0 -0
  41. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/conf.py +0 -0
  42. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/config.py +0 -0
  43. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/__init__.py +0 -0
  44. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/builder.py +0 -0
  45. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/component_router.py +0 -0
  46. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/data_fetching.py +0 -0
  47. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/demo_pages_simple.py +0 -0
  48. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/demo_router.py +0 -0
  49. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/renderer.py +0 -0
  50. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/router.py +0 -0
  51. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/sync.py +0 -0
  52. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/db.py +0 -0
  53. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/debug/core.py +0 -0
  54. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/debug/performance.py +0 -0
  55. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/debug/ui.py +0 -0
  56. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/debug/websocket.py +0 -0
  57. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/dev_server.py +0 -0
  58. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/dev_tools.py +0 -0
  59. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/errors.py +0 -0
  60. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/hooks.py +0 -0
  61. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/hooks_provider.py +0 -0
  62. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/hooks_provider_new.py +0 -0
  63. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/jsx.py +0 -0
  64. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/jsx_preprocessor.py +0 -0
  65. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/jsx_transformer.py +0 -0
  66. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/performance.py +0 -0
  67. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/plugins/__init__.py +0 -0
  68. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/plugins/base.py +0 -0
  69. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/plugins/builtin.py +0 -0
  70. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/plugins/config.py +0 -0
  71. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/plugins.py +0 -0
  72. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/__init__.py +0 -0
  73. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/core/__init__.py +0 -0
  74. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/core/ast_nodes.py +0 -0
  75. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/core/evaluator.py +0 -0
  76. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/devtools/language_server.py +0 -0
  77. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/devtools/language_server_lsp.py +0 -0
  78. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/devtools/psx_formatter.py +0 -0
  79. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/devtools/server_client_components.py +0 -0
  80. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/devtools/setup.py +0 -0
  81. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/hydration/__init__.py +0 -0
  82. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/renderer/renderer.py +0 -0
  83. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/tests/test_full_integration.py +0 -0
  84. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/tests/test_html_attribute_support.py +0 -0
  85. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/utils/helpers.py +0 -0
  86. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/vdom/vnode.py +0 -0
  87. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/py.typed +0 -0
  88. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/runtime/events.py +0 -0
  89. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/security.py +0 -0
  90. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/server/__init__.py +0 -0
  91. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/server/app.py +0 -0
  92. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/server/debug.py +0 -0
  93. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/server/middleware.py +0 -0
  94. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/source/conf.py +0 -0
  95. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/HANDLER_REGISTRATION_SYSTEM.py +0 -0
  96. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/setup_complete.py +0 -0
  97. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_autodebug_enhanced.py +0 -0
  98. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_cli_scaffolding.py +0 -0
  99. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_colors.py +0 -0
  100. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_component_rendering.py +0 -0
  101. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_conversion.py +0 -0
  102. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_critical_fixes.py +0 -0
  103. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_demo_mode.py +0 -0
  104. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_demo_server.py +0 -0
  105. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_enhanced_handlers.py +0 -0
  106. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_extraction.py +0 -0
  107. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_final.py +0 -0
  108. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_fixes.py +0 -0
  109. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_handler_system.py +0 -0
  110. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_hydration_engine.py +0 -0
  111. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_integration.py +0 -0
  112. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_interactive_bug.py +0 -0
  113. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_jsx_edgecases.py +0 -0
  114. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_jsx_preprocessor.py +0 -0
  115. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_migration.py +0 -0
  116. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_modular_debug.py +0 -0
  117. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_routing.py +0 -0
  118. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_server.py +0 -0
  119. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_server_features.py +0 -0
  120. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_server_working.py +0 -0
  121. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_tailwind.py +0 -0
  122. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_tailwind_full.py +0 -0
  123. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_tailwind_integration.py +0 -0
  124. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_tailwind_up_to_date.py +0 -0
  125. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_websocket_complete.py +0 -0
  126. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/true_jsx.py +0 -0
  127. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/__init__.py +0 -0
  128. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/cache.py +0 -0
  129. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/email.py +0 -0
  130. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/file_upload.py +0 -0
  131. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/logging.py +0 -0
  132. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/search.py +0 -0
  133. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/seo.py +0 -0
  134. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/validators.py +0 -0
  135. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/websocket.py +0 -0
  136. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy_framework.egg-info/SOURCES.txt +0 -0
  137. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy_framework.egg-info/dependency_links.txt +0 -0
  138. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy_framework.egg-info/entry_points.txt +0 -0
  139. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy_framework.egg-info/requires.txt +0 -0
  140. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy_framework.egg-info/top_level.txt +0 -0
  141. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/LICENSE +0 -0
  142. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/README.md +0 -0
  143. {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/setup.cfg +0 -0
@@ -3,7 +3,7 @@ NextPy - The Python Web Framdwork
3
3
  File-based routing, SSR, SSG, and more with FastAPI + PSX (True JSX)
4
4
  """
5
5
 
6
- __version__ = "3.7.2"
6
+ __version__ = "3.8.0"
7
7
 
8
8
  from nextpy.core.router import Router, Route, DynamicRoute
9
9
  from nextpy.core.renderer import Renderer
@@ -243,7 +243,7 @@ def cli():
243
243
 
244
244
 
245
245
  @cli.command()
246
- @click.option("--port", "-p", default=5000, help="Port to run the server on")
246
+ @click.option("--port", "-p", default=8000, help="Port to run the server on")
247
247
  @click.option("--host", "-h", default="0.0.0.0", help="Host to bind to")
248
248
  @click.option("--reload/--no-reload", default=True, help="Enable hot reload")
249
249
  @click.option("--debug/--no-debug", default=True, help="Enable debug mode")
@@ -322,6 +322,7 @@ def dev(port: int, host: str, reload: bool, debug: bool):
322
322
  # Enhanced reload patterns for JSX files
323
323
  reload_includes = [
324
324
  "*.py",
325
+ "*.psx",
325
326
  "*.py.jsx",
326
327
  "*.jsx",
327
328
  "*.html",
@@ -993,7 +994,10 @@ def _generate_page(name: str):
993
994
  page_path.parent.mkdir(parents=True, exist_ok=True)
994
995
 
995
996
  content = f'''"""Generated {name} page"""
997
+
998
+ from nextpy.psx import interactive_component as component
996
999
 
1000
+ @component
997
1001
  def {name.title()}(props = None):
998
1002
  """{name.title()} page component"""
999
1003
  props = props or {{}}
@@ -1328,213 +1332,132 @@ module.exports = {
1328
1332
  _create_traditional_homepage(project_dir)
1329
1333
 
1330
1334
  (project_dir / "pages" / "index.py").write_text('''"""Interactive Homepage """
1331
-
1332
- from nextpy.psx import component
1333
-
1335
+ from nextpy.psx import interactive_component as component
1336
+
1334
1337
 
1335
1338
  @component
1336
1339
  def Home(props=None):
1337
1340
  props = props or {}
1338
1341
  title = props.get("title", "Welcome to NextPy!")
1339
1342
  message = props.get("message", "Build amazing web apps with Python and True JSX")
1340
-
1343
+
1341
1344
  return (
1342
- <div class="min-h-screen bg-gradient-to-br from-blue-600 via-purple-600 to-pink-600">
1343
- <div class="bg-white border-b border-white bg-opacity-10 backdrop-blur-md border-opacity-20">
1344
- <div class="px-4 mx-auto max-w-7xl sm:px-6 lg:px-8">
1345
- <div class="flex items-center justify-between h-16">
1346
- <div class="flex items-center">
1347
- <h1 class="text-xl font-bold text-white">NextPy</h1>
1348
- </div>
1349
- <div class="flex space-x-4">
1350
- <a href="/about" class="px-3 py-2 text-sm font-medium text-white transition-colors rounded-md hover:text-blue-200">
1351
- About
1352
- </a>
1353
- <a href="/features" class="px-3 py-2 text-sm font-medium text-white transition-colors rounded-md hover:text-blue-200">
1354
- Features
1355
- </a>
1356
- <a href="/docs" class="px-3 py-2 text-sm font-medium text-white transition-colors rounded-md hover:text-blue-200">
1357
- Docs
1358
- </a>
1359
- </div>
1360
- </div>
1345
+ <div class="flex flex-col items-center justify-between min-h-screen p-24 font-sans text-white bg-black">
1346
+ <div class="flex items-center justify-between w-full max-w-5xl text-sm">
1347
+ <p>
1348
+ Get started by editing index.py in the
1349
+ <code class="font-mono font-bold">/pages</code>
1350
+ directory.
1351
+ </p>
1352
+ <div>
1353
+ <a
1354
+ href="https://rahimstudios.dev"
1355
+ class="flex items-center gap-2 hover:underline"
1356
+ >
1357
+ By
1358
+ <span class="font-bold">RahimStudios</span>
1359
+ </a>
1361
1360
  </div>
1362
- </div>
1363
1361
  </div>
1364
-
1365
-
1366
-
1367
- </div>
1368
- )
1369
1362
 
1370
- def getServerSideProps(context):
1371
- return {
1372
- "props": {
1373
- "title": "Welcome to NextPy!",
1374
- "message": "Build amazing web apps with Python and True JSX"
1375
- }
1376
- }
1377
-
1378
- default = Home
1379
- ''')
1380
- click.echo(" Created: pages/index.py ")
1363
+ <div class="flex flex-col items-center gap-8">
1364
+ <div class="flex items-center gap-4">
1365
+ <h1 class="text-6xl font-bold text-transparent bg-gradient-to-r from-blue-400 to-purple-600 bg-clip-text">
1366
+ NextPy
1367
+ </h1>
1368
+ <span class="inline-flex items-center justify-center w-12 h-12 text-lg font-bold bg-gray-800 rounded-full">
1369
+ 3.7.3
1370
+ </span>
1371
+ </div>
1372
+ </div>
1381
1373
 
1382
- # Create enhanced about page with interactive features
1383
- (project_dir / "pages" / "about.py").write_text(
1384
- '''"""Enhanced About page with True JSX"""
1374
+ <div class="grid w-full max-w-5xl grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
1375
+ <a
1376
+ href="https://nextpy-framework.onrender.com/"
1377
+ class="p-6 transition-colors border border-gray-700 rounded-lg hover:border-gray-400 group"
1378
+ >
1379
+ <h2 class="mb-3 text-2xl font-semibold">
1380
+ Docs
1381
+ <span class="inline-block transition-transform group-hover:translate-x-1">
1382
+ -&gt;
1383
+ </span>
1384
+ </h2>
1385
+ <p class="text-sm text-gray-400">
1386
+ Find in-depth information about NextPy features and API.
1387
+ </p>
1388
+ </a>
1385
1389
 
1386
- from nextpy.psx import component
1390
+ <a
1391
+ href="https://nextpy-framework.onrender.com/learn"
1392
+ class="p-6 transition-colors border border-gray-700 rounded-lg hover:border-gray-400 group"
1393
+ >
1394
+ <h2 class="mb-3 text-2xl font-semibold">
1395
+ Learn
1396
+ <span class="inline-block transition-transform group-hover:translate-x-1">
1397
+ -&gt;
1398
+ </span>
1399
+ </h2>
1400
+ <p class="text-sm text-gray-400">
1401
+ Learn about NextPy in an interactive course with quizzes!
1402
+ </p>
1403
+ </a>
1387
1404
 
1405
+ <a
1406
+ href="https://nextpy-framework.onrender.com/templates"
1407
+ class="p-6 transition-colors border border-gray-700 rounded-lg hover:border-gray-400 group"
1408
+ >
1409
+ <h2 class="mb-3 text-2xl font-semibold">
1410
+ Templates
1411
+ <span class="inline-block transition-transform group-hover:translate-x-1">
1412
+ -&gt;
1413
+ </span>
1414
+ </h2>
1415
+ <p class="text-sm text-gray-400">
1416
+ Explore starter templates for NextPy.
1417
+ </p>
1418
+ </a>
1388
1419
 
1389
- @component
1390
- def About(props=None):
1391
- """About page component with interactive features"""
1392
- props = props or {}
1393
-
1394
- title = props.get("title", "About NextPy")
1395
- description = props.get("description", "The Python web framework that brings React-like development to Python")
1396
-
1397
- return (
1398
- <div class="min-h-screen bg-gray-50">
1399
- <div class="text-white bg-gradient-to-r from-blue-600 to-purple-600">
1400
- <div class="px-4 py-16 mx-auto max-w-7xl sm:py-24 sm:px-6 lg:px-8">
1401
- <div class="text-center">
1402
- <h1 class="text-4xl font-extrabold tracking-tight sm:text-5xl lg:text-6xl">
1403
- {title}
1404
- </h1>
1405
- <p class="max-w-2xl mx-auto mt-6 text-xl text-blue-100">
1406
- {description}
1407
- </p>
1408
- <div class="flex justify-center mt-10 space-x-4">
1409
- <a href="/features" class="inline-flex items-center justify-center px-8 py-3 text-base font-medium text-blue-600 bg-white border border-transparent rounded-md hover:bg-blue-50 md:py-4 md:text-lg md:px-10">
1410
- Explore Features
1411
- </a>
1412
- <a href="/getting-started" class="inline-flex items-center justify-center px-8 py-3 text-base font-medium text-white bg-blue-500 border border-transparent rounded-md hover:bg-blue-600 md:py-4 md:text-lg md:px-10">
1413
- Get Started
1414
- </a>
1415
- </div>
1416
- </div>
1417
- </div>
1420
+ <a
1421
+ href="https://nextpy-framework.onrender.com/deploy"
1422
+ class="p-6 transition-colors border border-gray-700 rounded-lg hover:border-gray-400 group"
1423
+ >
1424
+ <h2 class="mb-3 text-2xl font-semibold">
1425
+ Deploy
1426
+ <span class="inline-block transition-transform group-hover:translate-x-1">
1427
+ -&gt;
1428
+ </span>
1429
+ </h2>
1430
+ <p class="text-sm text-gray-400">
1431
+ Instantly deploy your NextPy site to a shareable URL with RahimStudios.
1432
+ </p>
1433
+ </a>
1418
1434
  </div>
1419
-
1420
-
1421
1435
  </div>
1422
1436
  )
1423
1437
 
1438
+
1424
1439
  def getServerSideProps(context):
1425
1440
  return {
1426
1441
  "props": {
1427
- "title": "About NextPy",
1428
- "description": "The Python web framework that brings React-like development to Python"
1442
+ "title": "Welcome to NextPy!",
1443
+ "message": "Build amazing web apps with Python and True JSX"
1429
1444
  }
1430
1445
  }
1431
1446
 
1432
- default = About
1433
- '''
1434
- )
1435
- click.echo(" Created: pages/about.py (enhanced interactive page)")
1436
-
1437
- # Create interactive demo pages
1438
- (project_dir / "pages" / "interactive.py").write_text('''"""Interactive Demo Page"""
1439
1447
 
1440
- from nextpy.psx import component
1441
-
1442
-
1443
- @component
1444
- def InteractiveDemo(props=None):
1445
- """Interactive demo showcasing NextPy capabilities"""
1446
- return (
1447
- <div class="min-h-screen py-12 bg-gradient-to-br from-indigo-50 to-purple-100">
1448
- <div class="px-4 mx-auto max-w-7xl sm:px-6 lg:px-8">
1449
- <h1 class="mb-12 text-4xl font-extrabold text-center text-gray-900">
1450
- Interactive NextPy Demos
1451
- </h1>
1452
-
1453
- <div class="grid grid-cols-1 gap-8 md:grid-cols-2 lg:grid-cols-3">
1454
-
1455
- <div class="p-6 bg-white shadow-lg rounded-xl">
1456
- <h2 class="mb-4 text-2xl font-bold text-gray-900">Live Counter</h2>
1457
- <div class="text-center">
1458
- <div class="mb-4 text-6xl font-bold text-blue-600" id="counter">0</div>
1459
- <div class="space-x-4">
1460
- <button onclick="updateCounter(-1)" class="px-6 py-3 text-white transition-colors bg-red-500 rounded-lg hover:bg-red-600">
1461
- -
1462
- </button>
1463
- <button onclick="updateCounter(1)" class="px-6 py-3 text-white transition-colors bg-green-500 rounded-lg hover:bg-green-600">
1464
- +
1465
- </button>
1466
- <button onclick="resetCounter()" class="px-6 py-3 text-white transition-colors bg-gray-500 rounded-lg hover:bg-gray-600">
1467
- Reset
1468
- </button>
1469
- </div>
1470
- </div>
1471
- </div>
1472
-
1473
-
1474
- <div class="p-6 bg-white shadow-lg rounded-xl">
1475
- <h2 class="mb-4 text-2xl font-bold text-gray-900">Todo List</h2>
1476
- <div class="space-y-4">
1477
- <div class="flex space-x-2">
1478
- <input type="text" id="todoInput" placeholder="Add a new todo..." class="flex-1 px-4 py-2 border border-gray-300 rounded-lg" />
1479
- <button onclick="addTodo()" class="px-6 py-2 text-white transition-colors bg-blue-500 rounded-lg hover:bg-blue-600">
1480
- Add
1481
- </button>
1482
- </div>
1483
- <ul id="todoList" class="space-y-2">
1484
-
1485
- </ul>
1486
- </div>
1487
- </div>
1488
-
1489
-
1490
- <div class="p-6 bg-white shadow-lg rounded-xl">
1491
- <h2 class="mb-4 text-2xl font-bold text-gray-900">Color Picker</h2>
1492
- <div class="space-y-4">
1493
- <input type="color" id="colorPicker" class="w-full h-20 rounded-lg cursor-pointer" />
1494
- <div id="colorDisplay" class="p-4 font-mono text-lg text-center bg-gray-100 rounded-lg">
1495
- Selected: #3B82F6
1496
- </div>
1497
- </div>
1498
- </div>
1499
-
1500
-
1501
- <div class="p-6 bg-white shadow-lg rounded-xl">
1502
- <h2 class="mb-4 text-2xl font-bold text-gray-900">Form Validation</h2>
1503
- <form onsubmit="validateForm(event)" class="space-y-4">
1504
- <div>
1505
- <label class="block mb-2 text-sm font-medium text-gray-700">Email</label>
1506
- <input type="email" id="email" required class="w-full px-4 py-2 border border-gray-300 rounded-lg" placeholder="you@example.com" />
1507
- </div>
1508
- <div>
1509
- <label class="block mb-2 text-sm font-medium text-gray-700">Password</label>
1510
- <input type="password" id="password" required minlength="6" class="w-full px-4 py-2 border border-gray-300 rounded-lg" placeholder="•••••••••" />
1511
- </div>
1512
- <button type="submit" class="w-full px-6 py-3 text-white transition-colors bg-blue-500 rounded-lg hover:bg-blue-600">
1513
- Validate & Submit
1514
- </button>
1515
- </form>
1516
- <div id="validationResult" class="hidden p-4 mt-4 rounded-lg">
1517
-
1518
- </div>
1519
- </div>
1520
- </div>
1521
- </div>
1522
- </div>
1523
- )
1448
+ default = Home
1524
1449
 
1525
- def getServerSideProps(context):
1526
- return {"props": {}}
1527
1450
 
1528
- default = InteractiveDemo
1529
1451
  ''')
1530
- click.echo(" Created: pages/interactive.py (interactive demos)")
1452
+ click.echo(" Created: pages/index.py ")
1453
+
1531
1454
 
1532
1455
  (project_dir / "components" / "ui" / "Button.py").write_text(
1533
1456
  '''"""Button component"""
1534
- from nextpy.psx import component
1457
+ from nextpy.psx import psx
1458
+
1535
1459
 
1536
1460
 
1537
- @component
1538
1461
  def Button(props = None):
1539
1462
  """Reusable Button component"""
1540
1463
  props = props or {}
@@ -1556,14 +1479,14 @@ def Button(props = None):
1556
1479
 
1557
1480
  class_attr = f"px-6 py-3 rounded-lg font-medium transition-all duration-200 transform hover:scale-105 {variant_class} {className}"
1558
1481
 
1559
- return (
1482
+ return psx(f"
1560
1483
  <button class={class_attr}
1561
1484
  id={props.get("id")}
1562
1485
  disabled={props.get("disabled", False)}
1563
1486
  onclick={props.get("onClick", "")}>
1564
1487
  {children}
1565
1488
  </button>
1566
- )
1489
+ ")
1567
1490
 
1568
1491
  default = Button
1569
1492
  '''
@@ -1613,119 +1536,7 @@ default = Layout
1613
1536
  )
1614
1537
  click.echo(" Created: components/layout/Layout.py")
1615
1538
 
1616
- # Create VS Code configuration for PSX support
1617
- (project_dir / ".vscode").mkdir(exist_ok=True)
1618
- (project_dir / ".vscode" / "settings.json").write_text("""{
1619
- "files.associations": {
1620
- "*.py": "python",
1621
- "*.py.jsx": "python",
1622
- "*.jsx": "javascriptreact"
1623
- },
1624
- "emmet.includeLanguages": {
1625
- "python": "html",
1626
- "javascriptreact": "html",
1627
- "typescriptreact": "html"
1628
- },
1629
- "emmet.triggerExpansionOnTab": true,
1630
- "typescript.preferences.includePackageJsonAutoImports": "on",
1631
- "editor.quickSuggestions": {
1632
- "strings": true
1633
- },
1634
- "editor.suggestSelection": "first",
1635
- "editor.wordBasedSuggestions": true,
1636
- "editor.snippetSuggestions": "top",
1637
- "editor.parameterHints": {
1638
- "enabled": true
1639
- },
1640
- "editor.snippetSuggestions": "top",
1641
- "html.autoClosingTags": true,
1642
- "css.autoClosingTags": true,
1643
- "javascript.autoClosingTags": true,
1644
- "typescript.autoClosingTags": true,
1645
- "editor.autoClosingBrackets": "always",
1646
- "editor.autoClosingQuotes": "always",
1647
- "editor.formatOnSave": true,
1648
- "editor.codeActionsOnSave": {
1649
- "source.fixAll.eslint": true,
1650
- "source.organizeImports": true
1651
- },
1652
- "emmet.preferences": {
1653
- "css.property.endWithSemicolon": true,
1654
- "css.value.unit": "rem"
1655
- },
1656
- "files.exclude": {
1657
- "*}__pycache__": true,
1658
- "*}*.pyc": true,
1659
- "*}node_modules": true,
1660
- "*}out": true,
1661
- "*}.next": true,
1662
- "*}.pytest_cache": true,
1663
- "*}.mypy_cache": true
1664
- },
1665
- "search.exclude": {
1666
- "*}node_modules": true,
1667
- "*}out": true,
1668
- "*}.next": true,
1669
- "*}__pycache__": true,
1670
- "*}.pytest_cache": true,
1671
- "*}.mypy_cache": true
1672
- },
1673
- "python.linting.enabled": true,
1674
- "python.linting.pylintEnabled": false,
1675
- "python.linting.flake8Enabled": false,
1676
- "python.linting.pylintArgs": [
1677
- "--disable=C0114,C0115,C0116,E1132,E1131,E1130"
1678
- ],
1679
- "python.formatting.provider": "black",
1680
- "[python]": {
1681
- "editor.defaultFormatter": "ms-python.black-formatter",
1682
- "editor.formatOnSave": true,
1683
- "editor.rulers": [88],
1684
- "editor.tabSize": 4,
1685
- "editor.insertSpaces": true
1686
- }
1687
- }""")
1688
- click.echo(" Created: .vscode/settings.json")
1689
-
1690
- (project_dir / ".vscode" / "extensions.json").write_text("""{
1691
- "recommendations": [
1692
- "ms-python.python",
1693
- "ms-python.vscode-pylance",
1694
- "bradlc.vscode-tailwindcss",
1695
- "esbenp.prettier-vscode",
1696
- "ms-vscode.vscode-json",
1697
- "formulahendry.auto-rename-tag",
1698
- "christian-kohler.path-intellisense",
1699
- "ms-vscode.vscode-html-css-class-completion",
1700
- "ms-vscode.vscode-emmet",
1701
- "ms-vscode.vscode-eslint",
1702
- "dbaeumer.vscode-eslint",
1703
- "ms-vscode.vscode-typescript-next",
1704
- "ritwickdey.liveserver",
1705
- "ms-vscode.vscode-jest",
1706
- "esbenp.prettier-vscode",
1707
- "streetsidesoftware.code-spell-checker",
1708
- "gruntfuggly.todo-tree",
1709
- "ms-vscode.vscode-git-graph",
1710
- "eamodio.gitlens",
1711
- "ms-vscode.vscode-docker",
1712
- "ms-vscode.remote-explorer",
1713
- "ms-vscode-remote.remote-containers",
1714
- "ms-vscode.vscode-remote-wsl",
1715
- "redhat.vscode-yaml",
1716
- "ms-vscode.vscode-markdown",
1717
- "yzhang.markdown-all-in-one",
1718
- "shd101wyy.markdown-preview-enhanced",
1719
- "ms-vscode.vscode-python",
1720
- "kevinrose.vsc-python-indent",
1721
- "ms-python.black-formatter",
1722
- "ms-python.isort",
1723
- "ms-python.flake8",
1724
- "ms-python.mypy-type-checker"
1725
- ]
1726
- }""")
1727
- click.echo(" Created: .vscode/extensions.json")
1728
-
1539
+
1729
1540
  # Create comprehensive API examples
1730
1541
  (project_dir / "pages" / "api" / "hello.py").write_text(
1731
1542
  '''"""API example - Hello endpoint"""
@@ -2208,77 +2019,6 @@ Thumbs.db
2208
2019
  ''')
2209
2020
  click.echo(" Created: .gitignore")
2210
2021
 
2211
- # Create main.py with Tailwind compilation (for pip-installed NextPy)
2212
- (project_dir / "main.py").write_text('''"""NextPy ASGI Application Entry Point"""
2213
-
2214
- import os
2215
- import sys
2216
- import subprocess
2217
- from pathlib import Path
2218
-
2219
- try:
2220
- print("Compiling Tailwind CSS...")
2221
- proj_root = Path.cwd()
2222
- framework_dir = Path(__file__).parent
2223
- # If the project root doesn't have a styles.css yet, warn the user and create a minimal one.
2224
- styles_file = proj_root / "styles.css"
2225
- if not styles_file.exists():
2226
- print("Warning: styles.css not found, creating a minimal file.")
2227
- styles_file.write_text("@tailwind base;\n@tailwind components;\n@tailwind utilities;\n")
2228
-
2229
- import shutil
2230
- npm_bin = shutil.which("npm")
2231
- if not npm_bin:
2232
- raise FileNotFoundError("npm not found on PATH")
2233
-
2234
- lockfile = framework_dir / "package-lock.json"
2235
- node_modules = framework_dir / "node_modules"
2236
- if not node_modules.exists():
2237
- if lockfile.exists():
2238
- subprocess.run([npm_bin, "ci"], cwd=str(framework_dir), check=True)
2239
- else:
2240
- subprocess.run([npm_bin, "install"], cwd=str(framework_dir), check=True)
2241
-
2242
- subprocess.run([npm_bin, "run", "build:tailwind"], cwd=str(framework_dir), check=True)
2243
- print("Tailwind CSS compiled successfully.")
2244
- except subprocess.CalledProcessError as e:
2245
- print(f"Error compiling Tailwind CSS: {e}")
2246
- print("You can also run `cd .nextpy_framework/nextpy && npm ci && npm run build:tailwind` manually.")
2247
- except FileNotFoundError:
2248
- print("Error: npm not found. Make sure Node.js is installed and available on PATH.")
2249
- print("See https://nodejs.org/ for installation instructions.")
2250
-
2251
- # Import NextPy modules (works when installed via pip)
2252
- from nextpy.server.app import create_app
2253
- from nextpy.db import init_db
2254
- from nextpy.config import settings
2255
-
2256
- # Initialize database
2257
- try:
2258
- init_db(settings["database_url"])
2259
- print("Database initialized successfully.")
2260
- except Exception as e:
2261
- print(f"Warning: Database initialization failed: {e}")
2262
-
2263
- # Create NextPy app with file-based routing
2264
- app = create_app(
2265
- pages_dir="pages",
2266
- templates_dir="templates",
2267
- public_dir="public",
2268
- out_dir="out",
2269
- debug=settings["debug"],
2270
- )
2271
-
2272
- # Note: Routes are automatically loaded from pages/ directory
2273
- # - / -> pages/index.py
2274
- # - /about -> pages/about.py
2275
- # - /api/* -> pages/api/*.py
2276
-
2277
- if __name__ == "__main__":
2278
- import uvicorn
2279
- uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
2280
- ''')
2281
- click.echo(" Created: main.py (pip-compatible)")
2282
2022
 
2283
2023
  # Create .env file for development
2284
2024
  (project_dir / ".env").write_text("""# NextPy Development Environment
@@ -243,7 +243,7 @@ class ComponentRenderer:
243
243
  elif has_interactive_decorator and not hasattr(component, '__wrapped__'):
244
244
  # The original file had @interactive_component but the decorator wasn't applied
245
245
  # This means we need to apply the decorator to the rendered HTML
246
- html = self._apply_interactive_component_to_rendered_html(rendered, original_content, page_props)
246
+ html = self._apply_interactive_component_to_rendered_html(file_path, rendered, original_content, page_props)
247
247
  else:
248
248
  # Convert to HTML, passing page props as context for {expressions}
249
249
  # Check if this is a PSX component and handle Server/Client components
@@ -320,9 +320,20 @@ class ComponentRenderer:
320
320
 
321
321
  # 🔥 Inject Dev Tools (only in dev mode)
322
322
  dev_scripts = ""
323
+
324
+ # Ensure the Action runtime is always available on the page.
325
+ # Your button onclick handlers expect window.NextPyActionRuntime.
326
+ action_runtime_script = ""
327
+ try:
328
+ from ..psx.runtime.js_actions_runtime import JS_ACTION_RUNTIME_SCRIPT
329
+ action_runtime_script = f"<script>{JS_ACTION_RUNTIME_SCRIPT}</script>\n"
330
+ except ImportError:
331
+ action_runtime_script = ""
332
+
323
333
  if dev_mode:
324
334
  dev_scripts = """
325
335
  <script>
336
+
326
337
  /* ===============================
327
338
  NextPy Live Error Overlay
328
339
  ================================ */
@@ -581,14 +592,7 @@ class ComponentRenderer:
581
592
 
582
593
  <link rel="stylesheet" href="./public/tailwind.css">
583
594
 
584
- <style>
585
- * {{ margin: 0; padding: 0; box-sizing: border-box; }}
586
-
587
- body {{
588
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
589
-
590
- }}
591
- </style>
595
+
592
596
 
593
597
  </head>
594
598
 
@@ -598,11 +602,12 @@ class ComponentRenderer:
598
602
  {content}
599
603
  </div>
600
604
 
601
- {dev_scripts}
605
+ {action_runtime_script}{dev_scripts}
602
606
 
603
607
  </body>
604
608
  </html>
605
609
  """
610
+
606
611
 
607
612
 
608
613
 
@@ -895,6 +900,8 @@ class ComponentRenderer:
895
900
  # Extract handlers from the original content
896
901
  handlers = extract_handler_functions(lambda: None) # We'll parse the content directly
897
902
 
903
+ print(f"new keys {handlers}")
904
+
898
905
  # Parse the original content to find handler functions
899
906
  import re
900
907
  handler_pattern = r'def\s+(\w+)\s*\([^)]*\)\s*:'
@@ -933,6 +940,7 @@ class ComponentRenderer:
933
940
  # Extract state keys
934
941
  state_pattern = r'\[(\w+),\s*set\w+\]\s*=\s*useState'
935
942
  state_keys = re.findall(state_pattern, original_content)
943
+ print(f"here new keys {state_keys}")
936
944
 
937
945
  # Convert handler attributes in HTML
938
946
  html_with_handlers = convert_handler_attributes_in_html(rendered_html, handlers, state_keys)
@@ -957,7 +965,7 @@ class ComponentRenderer:
957
965
 
958
966
  # Generate scripts
959
967
  full_script = engine.generate_hydration_script()
960
- handler_script = generate_handler_registration_script(handlers, component_id, state_keys=state_keys)
968
+ handler_script = generate_handler_registration_script(handlers, component_id, state_keys=state_keys, html=html_with_handlers)
961
969
  hydrator = get_component_hydrator()
962
970
  hydration_script = hydrator.generate_hydration_script()
963
971