nextpy-framework 3.7.2__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.
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/__init__.py +1 -1
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/cli.py +104 -365
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/component_renderer.py +19 -11
- nextpy_framework-3.8.0/.nextpy_framework/nextpy/main.py +72 -0
- nextpy_framework-3.8.0/.nextpy_framework/nextpy/psx/compiler/actions.py +878 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/compiler/handler_compiler.py +52 -11
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/components/component.py +18 -6
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/core/parser.py +117 -30
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/core/runtime.py +15 -4
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/hydration/decorators.py +460 -136
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/hydration/engine.py +60 -1
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/hydration/integration.py +18 -4
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/runtime/actions_runtime.py +157 -11
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/runtime/js_actions_runtime.py +232 -52
- nextpy_framework-3.8.0/.nextpy_framework/nextpy_framework.egg-info/PKG-INFO +255 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/LICENSE +2 -2
- nextpy_framework-3.8.0/PKG-INFO +255 -0
- nextpy_framework-3.8.0/README.md +214 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/pyproject.toml +2 -2
- nextpy_framework-3.7.2/.nextpy_framework/nextpy/main.py +0 -81
- nextpy_framework-3.7.2/.nextpy_framework/nextpy/psx/compiler/actions.py +0 -431
- nextpy_framework-3.7.2/.nextpy_framework/nextpy_framework.egg-info/PKG-INFO +0 -906
- nextpy_framework-3.7.2/PKG-INFO +0 -906
- nextpy_framework-3.7.2/README.md +0 -865
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/ast_parser.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/auth.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/builder.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/__init__.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/debug/AutoDebug.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/debug/AutoDebug_v3.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/debug/DebugIcon.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/debug/DebugIconFixed.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/feedback.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/form.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/head.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/hooks_provider.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/image.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/layout.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/link.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/loader.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/navigation.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/toast.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/ui.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/visual.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/conf.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/config.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/__init__.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/builder.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/component_router.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/data_fetching.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/demo_pages_simple.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/demo_router.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/renderer.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/router.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/sync.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/db.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/debug/core.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/debug/performance.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/debug/ui.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/debug/websocket.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/dev_server.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/dev_tools.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/errors.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/hooks.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/hooks_provider.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/hooks_provider_new.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/jsx.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/jsx_preprocessor.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/jsx_transformer.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/performance.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/plugins/__init__.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/plugins/base.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/plugins/builtin.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/plugins/config.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/plugins.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/__init__.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/core/__init__.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/core/ast_nodes.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/core/evaluator.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/devtools/language_server.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/devtools/language_server_lsp.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/devtools/psx_formatter.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/devtools/server_client_components.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/devtools/setup.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/hydration/__init__.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/renderer/renderer.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/tests/test_full_integration.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/tests/test_html_attribute_support.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/utils/helpers.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/vdom/vnode.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/py.typed +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/runtime/events.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/security.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/server/__init__.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/server/app.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/server/debug.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/server/middleware.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/source/conf.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/HANDLER_REGISTRATION_SYSTEM.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/setup_complete.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_autodebug_enhanced.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_cli_scaffolding.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_colors.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_component_rendering.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_conversion.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_critical_fixes.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_demo_mode.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_demo_server.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_enhanced_handlers.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_extraction.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_final.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_fixes.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_handler_system.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_hydration_engine.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_integration.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_interactive_bug.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_jsx_edgecases.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_jsx_preprocessor.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_migration.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_modular_debug.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_routing.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_server.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_server_features.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_server_working.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_tailwind.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_tailwind_full.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_tailwind_integration.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_tailwind_up_to_date.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_websocket_complete.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/true_jsx.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/__init__.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/cache.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/email.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/file_upload.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/logging.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/search.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/seo.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/validators.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/websocket.py +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy_framework.egg-info/SOURCES.txt +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy_framework.egg-info/dependency_links.txt +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy_framework.egg-info/entry_points.txt +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy_framework.egg-info/requires.txt +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy_framework.egg-info/top_level.txt +0 -0
- {nextpy_framework-3.7.2 → nextpy_framework-3.8.0}/setup.cfg +0 -0
|
@@ -243,7 +243,7 @@ def cli():
|
|
|
243
243
|
|
|
244
244
|
|
|
245
245
|
@cli.command()
|
|
246
|
-
@click.option("--port", "-p", default=
|
|
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",
|
|
@@ -627,12 +628,8 @@ def create(name: str, psx: bool, template: str):
|
|
|
627
628
|
f" 💡 Check the error message above for more details", fg="yellow"
|
|
628
629
|
)
|
|
629
630
|
)
|
|
630
|
-
# Clean up partial creation
|
|
631
|
-
|
|
632
631
|
# Clean up partial creation
|
|
633
632
|
if project_dir.exists():
|
|
634
|
-
import shutil
|
|
635
|
-
|
|
636
633
|
shutil.rmtree(project_dir, ignore_errors=True)
|
|
637
634
|
|
|
638
635
|
click.echo(click.style(f" 🧹 Cleaned up partial files", fg="yellow"))
|
|
@@ -997,7 +994,10 @@ def _generate_page(name: str):
|
|
|
997
994
|
page_path.parent.mkdir(parents=True, exist_ok=True)
|
|
998
995
|
|
|
999
996
|
content = f'''"""Generated {name} page"""
|
|
997
|
+
|
|
998
|
+
from nextpy.psx import interactive_component as component
|
|
1000
999
|
|
|
1000
|
+
@component
|
|
1001
1001
|
def {name.title()}(props = None):
|
|
1002
1002
|
"""{name.title()} page component"""
|
|
1003
1003
|
props = props or {{}}
|
|
@@ -1105,13 +1105,16 @@ def _create_project_structure(
|
|
|
1105
1105
|
"components/ui",
|
|
1106
1106
|
"components/layout",
|
|
1107
1107
|
"docs",
|
|
1108
|
+
"hooks",
|
|
1108
1109
|
"styles",
|
|
1109
1110
|
"public",
|
|
1110
1111
|
"public/images",
|
|
1111
1112
|
"public/fonts",
|
|
1112
1113
|
"public/css",
|
|
1113
1114
|
"public/js",
|
|
1115
|
+
"middleware",
|
|
1114
1116
|
"templates",
|
|
1117
|
+
"tests",
|
|
1115
1118
|
"utils",
|
|
1116
1119
|
".nextpy",
|
|
1117
1120
|
".nextpy/plugins",
|
|
@@ -1329,213 +1332,132 @@ module.exports = {
|
|
|
1329
1332
|
_create_traditional_homepage(project_dir)
|
|
1330
1333
|
|
|
1331
1334
|
(project_dir / "pages" / "index.py").write_text('''"""Interactive Homepage """
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
+
from nextpy.psx import interactive_component as component
|
|
1336
|
+
|
|
1335
1337
|
|
|
1336
1338
|
@component
|
|
1337
1339
|
def Home(props=None):
|
|
1338
1340
|
props = props or {}
|
|
1339
1341
|
title = props.get("title", "Welcome to NextPy!")
|
|
1340
1342
|
message = props.get("message", "Build amazing web apps with Python and True JSX")
|
|
1341
|
-
|
|
1343
|
+
|
|
1342
1344
|
return (
|
|
1343
|
-
<div class="min-h-screen
|
|
1344
|
-
<div class="
|
|
1345
|
-
<
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
Docs
|
|
1359
|
-
</a>
|
|
1360
|
-
</div>
|
|
1361
|
-
</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>
|
|
1362
1360
|
</div>
|
|
1363
|
-
</div>
|
|
1364
1361
|
</div>
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
</div>
|
|
1369
|
-
)
|
|
1370
1362
|
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
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>
|
|
1382
1373
|
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
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
|
+
->
|
|
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>
|
|
1386
1389
|
|
|
1387
|
-
|
|
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
|
+
->
|
|
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>
|
|
1388
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
|
+
->
|
|
1413
|
+
</span>
|
|
1414
|
+
</h2>
|
|
1415
|
+
<p class="text-sm text-gray-400">
|
|
1416
|
+
Explore starter templates for NextPy.
|
|
1417
|
+
</p>
|
|
1418
|
+
</a>
|
|
1389
1419
|
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
{title}
|
|
1405
|
-
</h1>
|
|
1406
|
-
<p class="max-w-2xl mx-auto mt-6 text-xl text-blue-100">
|
|
1407
|
-
{description}
|
|
1408
|
-
</p>
|
|
1409
|
-
<div class="flex justify-center mt-10 space-x-4">
|
|
1410
|
-
<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">
|
|
1411
|
-
Explore Features
|
|
1412
|
-
</a>
|
|
1413
|
-
<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">
|
|
1414
|
-
Get Started
|
|
1415
|
-
</a>
|
|
1416
|
-
</div>
|
|
1417
|
-
</div>
|
|
1418
|
-
</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
|
+
->
|
|
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>
|
|
1419
1434
|
</div>
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
1435
|
</div>
|
|
1423
1436
|
)
|
|
1424
1437
|
|
|
1438
|
+
|
|
1425
1439
|
def getServerSideProps(context):
|
|
1426
1440
|
return {
|
|
1427
1441
|
"props": {
|
|
1428
|
-
"title": "
|
|
1429
|
-
"
|
|
1442
|
+
"title": "Welcome to NextPy!",
|
|
1443
|
+
"message": "Build amazing web apps with Python and True JSX"
|
|
1430
1444
|
}
|
|
1431
1445
|
}
|
|
1432
1446
|
|
|
1433
|
-
default = About
|
|
1434
|
-
'''
|
|
1435
|
-
)
|
|
1436
|
-
click.echo(" Created: pages/about.py (enhanced interactive page)")
|
|
1437
|
-
|
|
1438
|
-
# Create interactive demo pages
|
|
1439
|
-
(project_dir / "pages" / "interactive.py").write_text('''"""Interactive Demo Page"""
|
|
1440
1447
|
|
|
1441
|
-
|
|
1448
|
+
default = Home
|
|
1442
1449
|
|
|
1443
1450
|
|
|
1444
|
-
@component
|
|
1445
|
-
def InteractiveDemo(props=None):
|
|
1446
|
-
"""Interactive demo showcasing NextPy capabilities"""
|
|
1447
|
-
return (
|
|
1448
|
-
<div class="min-h-screen py-12 bg-gradient-to-br from-indigo-50 to-purple-100">
|
|
1449
|
-
<div class="px-4 mx-auto max-w-7xl sm:px-6 lg:px-8">
|
|
1450
|
-
<h1 class="mb-12 text-4xl font-extrabold text-center text-gray-900">
|
|
1451
|
-
Interactive NextPy Demos
|
|
1452
|
-
</h1>
|
|
1453
|
-
|
|
1454
|
-
<div class="grid grid-cols-1 gap-8 md:grid-cols-2 lg:grid-cols-3">
|
|
1455
|
-
|
|
1456
|
-
<div class="p-6 bg-white shadow-lg rounded-xl">
|
|
1457
|
-
<h2 class="mb-4 text-2xl font-bold text-gray-900">Live Counter</h2>
|
|
1458
|
-
<div class="text-center">
|
|
1459
|
-
<div class="mb-4 text-6xl font-bold text-blue-600" id="counter">0</div>
|
|
1460
|
-
<div class="space-x-4">
|
|
1461
|
-
<button onclick="updateCounter(-1)" class="px-6 py-3 text-white transition-colors bg-red-500 rounded-lg hover:bg-red-600">
|
|
1462
|
-
-
|
|
1463
|
-
</button>
|
|
1464
|
-
<button onclick="updateCounter(1)" class="px-6 py-3 text-white transition-colors bg-green-500 rounded-lg hover:bg-green-600">
|
|
1465
|
-
+
|
|
1466
|
-
</button>
|
|
1467
|
-
<button onclick="resetCounter()" class="px-6 py-3 text-white transition-colors bg-gray-500 rounded-lg hover:bg-gray-600">
|
|
1468
|
-
Reset
|
|
1469
|
-
</button>
|
|
1470
|
-
</div>
|
|
1471
|
-
</div>
|
|
1472
|
-
</div>
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
<div class="p-6 bg-white shadow-lg rounded-xl">
|
|
1476
|
-
<h2 class="mb-4 text-2xl font-bold text-gray-900">Todo List</h2>
|
|
1477
|
-
<div class="space-y-4">
|
|
1478
|
-
<div class="flex space-x-2">
|
|
1479
|
-
<input type="text" id="todoInput" placeholder="Add a new todo..." class="flex-1 px-4 py-2 border border-gray-300 rounded-lg" />
|
|
1480
|
-
<button onclick="addTodo()" class="px-6 py-2 text-white transition-colors bg-blue-500 rounded-lg hover:bg-blue-600">
|
|
1481
|
-
Add
|
|
1482
|
-
</button>
|
|
1483
|
-
</div>
|
|
1484
|
-
<ul id="todoList" class="space-y-2">
|
|
1485
|
-
|
|
1486
|
-
</ul>
|
|
1487
|
-
</div>
|
|
1488
|
-
</div>
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
<div class="p-6 bg-white shadow-lg rounded-xl">
|
|
1492
|
-
<h2 class="mb-4 text-2xl font-bold text-gray-900">Color Picker</h2>
|
|
1493
|
-
<div class="space-y-4">
|
|
1494
|
-
<input type="color" id="colorPicker" class="w-full h-20 rounded-lg cursor-pointer" />
|
|
1495
|
-
<div id="colorDisplay" class="p-4 font-mono text-lg text-center bg-gray-100 rounded-lg">
|
|
1496
|
-
Selected: #3B82F6
|
|
1497
|
-
</div>
|
|
1498
|
-
</div>
|
|
1499
|
-
</div>
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
<div class="p-6 bg-white shadow-lg rounded-xl">
|
|
1503
|
-
<h2 class="mb-4 text-2xl font-bold text-gray-900">Form Validation</h2>
|
|
1504
|
-
<form onsubmit="validateForm(event)" class="space-y-4">
|
|
1505
|
-
<div>
|
|
1506
|
-
<label class="block mb-2 text-sm font-medium text-gray-700">Email</label>
|
|
1507
|
-
<input type="email" id="email" required class="w-full px-4 py-2 border border-gray-300 rounded-lg" placeholder="you@example.com" />
|
|
1508
|
-
</div>
|
|
1509
|
-
<div>
|
|
1510
|
-
<label class="block mb-2 text-sm font-medium text-gray-700">Password</label>
|
|
1511
|
-
<input type="password" id="password" required minlength="6" class="w-full px-4 py-2 border border-gray-300 rounded-lg" placeholder="•••••••••" />
|
|
1512
|
-
</div>
|
|
1513
|
-
<button type="submit" class="w-full px-6 py-3 text-white transition-colors bg-blue-500 rounded-lg hover:bg-blue-600">
|
|
1514
|
-
Validate & Submit
|
|
1515
|
-
</button>
|
|
1516
|
-
</form>
|
|
1517
|
-
<div id="validationResult" class="hidden p-4 mt-4 rounded-lg">
|
|
1518
|
-
|
|
1519
|
-
</div>
|
|
1520
|
-
</div>
|
|
1521
|
-
</div>
|
|
1522
|
-
</div>
|
|
1523
|
-
</div>
|
|
1524
|
-
)
|
|
1525
|
-
|
|
1526
|
-
def getServerSideProps(context):
|
|
1527
|
-
return {"props": {}}
|
|
1528
|
-
|
|
1529
|
-
default = InteractiveDemo
|
|
1530
1451
|
''')
|
|
1531
|
-
click.echo(" Created: pages/
|
|
1452
|
+
click.echo(" Created: pages/index.py ")
|
|
1453
|
+
|
|
1532
1454
|
|
|
1533
1455
|
(project_dir / "components" / "ui" / "Button.py").write_text(
|
|
1534
1456
|
'''"""Button component"""
|
|
1535
|
-
from nextpy.psx import
|
|
1457
|
+
from nextpy.psx import psx
|
|
1458
|
+
|
|
1536
1459
|
|
|
1537
1460
|
|
|
1538
|
-
@component
|
|
1539
1461
|
def Button(props = None):
|
|
1540
1462
|
"""Reusable Button component"""
|
|
1541
1463
|
props = props or {}
|
|
@@ -1557,14 +1479,14 @@ def Button(props = None):
|
|
|
1557
1479
|
|
|
1558
1480
|
class_attr = f"px-6 py-3 rounded-lg font-medium transition-all duration-200 transform hover:scale-105 {variant_class} {className}"
|
|
1559
1481
|
|
|
1560
|
-
return (
|
|
1482
|
+
return psx(f"
|
|
1561
1483
|
<button class={class_attr}
|
|
1562
1484
|
id={props.get("id")}
|
|
1563
1485
|
disabled={props.get("disabled", False)}
|
|
1564
1486
|
onclick={props.get("onClick", "")}>
|
|
1565
1487
|
{children}
|
|
1566
1488
|
</button>
|
|
1567
|
-
)
|
|
1489
|
+
")
|
|
1568
1490
|
|
|
1569
1491
|
default = Button
|
|
1570
1492
|
'''
|
|
@@ -1614,119 +1536,7 @@ default = Layout
|
|
|
1614
1536
|
)
|
|
1615
1537
|
click.echo(" Created: components/layout/Layout.py")
|
|
1616
1538
|
|
|
1617
|
-
|
|
1618
|
-
(project_dir / ".vscode").mkdir(exist_ok=True)
|
|
1619
|
-
(project_dir / ".vscode" / "settings.json").write_text("""{
|
|
1620
|
-
"files.associations": {
|
|
1621
|
-
"*.py": "python",
|
|
1622
|
-
"*.py.jsx": "python",
|
|
1623
|
-
"*.jsx": "javascriptreact"
|
|
1624
|
-
},
|
|
1625
|
-
"emmet.includeLanguages": {
|
|
1626
|
-
"python": "html",
|
|
1627
|
-
"javascriptreact": "html",
|
|
1628
|
-
"typescriptreact": "html"
|
|
1629
|
-
},
|
|
1630
|
-
"emmet.triggerExpansionOnTab": true,
|
|
1631
|
-
"typescript.preferences.includePackageJsonAutoImports": "on",
|
|
1632
|
-
"editor.quickSuggestions": {
|
|
1633
|
-
"strings": true
|
|
1634
|
-
},
|
|
1635
|
-
"editor.suggestSelection": "first",
|
|
1636
|
-
"editor.wordBasedSuggestions": true,
|
|
1637
|
-
"editor.snippetSuggestions": "top",
|
|
1638
|
-
"editor.parameterHints": {
|
|
1639
|
-
"enabled": true
|
|
1640
|
-
},
|
|
1641
|
-
"editor.snippetSuggestions": "top",
|
|
1642
|
-
"html.autoClosingTags": true,
|
|
1643
|
-
"css.autoClosingTags": true,
|
|
1644
|
-
"javascript.autoClosingTags": true,
|
|
1645
|
-
"typescript.autoClosingTags": true,
|
|
1646
|
-
"editor.autoClosingBrackets": "always",
|
|
1647
|
-
"editor.autoClosingQuotes": "always",
|
|
1648
|
-
"editor.formatOnSave": true,
|
|
1649
|
-
"editor.codeActionsOnSave": {
|
|
1650
|
-
"source.fixAll.eslint": true,
|
|
1651
|
-
"source.organizeImports": true
|
|
1652
|
-
},
|
|
1653
|
-
"emmet.preferences": {
|
|
1654
|
-
"css.property.endWithSemicolon": true,
|
|
1655
|
-
"css.value.unit": "rem"
|
|
1656
|
-
},
|
|
1657
|
-
"files.exclude": {
|
|
1658
|
-
"*}__pycache__": true,
|
|
1659
|
-
"*}*.pyc": true,
|
|
1660
|
-
"*}node_modules": true,
|
|
1661
|
-
"*}out": true,
|
|
1662
|
-
"*}.next": true,
|
|
1663
|
-
"*}.pytest_cache": true,
|
|
1664
|
-
"*}.mypy_cache": true
|
|
1665
|
-
},
|
|
1666
|
-
"search.exclude": {
|
|
1667
|
-
"*}node_modules": true,
|
|
1668
|
-
"*}out": true,
|
|
1669
|
-
"*}.next": true,
|
|
1670
|
-
"*}__pycache__": true,
|
|
1671
|
-
"*}.pytest_cache": true,
|
|
1672
|
-
"*}.mypy_cache": true
|
|
1673
|
-
},
|
|
1674
|
-
"python.linting.enabled": true,
|
|
1675
|
-
"python.linting.pylintEnabled": false,
|
|
1676
|
-
"python.linting.flake8Enabled": false,
|
|
1677
|
-
"python.linting.pylintArgs": [
|
|
1678
|
-
"--disable=C0114,C0115,C0116,E1132,E1131,E1130"
|
|
1679
|
-
],
|
|
1680
|
-
"python.formatting.provider": "black",
|
|
1681
|
-
"[python]": {
|
|
1682
|
-
"editor.defaultFormatter": "ms-python.black-formatter",
|
|
1683
|
-
"editor.formatOnSave": true,
|
|
1684
|
-
"editor.rulers": [88],
|
|
1685
|
-
"editor.tabSize": 4,
|
|
1686
|
-
"editor.insertSpaces": true
|
|
1687
|
-
}
|
|
1688
|
-
}""")
|
|
1689
|
-
click.echo(" Created: .vscode/settings.json")
|
|
1690
|
-
|
|
1691
|
-
(project_dir / ".vscode" / "extensions.json").write_text("""{
|
|
1692
|
-
"recommendations": [
|
|
1693
|
-
"ms-python.python",
|
|
1694
|
-
"ms-python.vscode-pylance",
|
|
1695
|
-
"bradlc.vscode-tailwindcss",
|
|
1696
|
-
"esbenp.prettier-vscode",
|
|
1697
|
-
"ms-vscode.vscode-json",
|
|
1698
|
-
"formulahendry.auto-rename-tag",
|
|
1699
|
-
"christian-kohler.path-intellisense",
|
|
1700
|
-
"ms-vscode.vscode-html-css-class-completion",
|
|
1701
|
-
"ms-vscode.vscode-emmet",
|
|
1702
|
-
"ms-vscode.vscode-eslint",
|
|
1703
|
-
"dbaeumer.vscode-eslint",
|
|
1704
|
-
"ms-vscode.vscode-typescript-next",
|
|
1705
|
-
"ritwickdey.liveserver",
|
|
1706
|
-
"ms-vscode.vscode-jest",
|
|
1707
|
-
"esbenp.prettier-vscode",
|
|
1708
|
-
"streetsidesoftware.code-spell-checker",
|
|
1709
|
-
"gruntfuggly.todo-tree",
|
|
1710
|
-
"ms-vscode.vscode-git-graph",
|
|
1711
|
-
"eamodio.gitlens",
|
|
1712
|
-
"ms-vscode.vscode-docker",
|
|
1713
|
-
"ms-vscode.remote-explorer",
|
|
1714
|
-
"ms-vscode-remote.remote-containers",
|
|
1715
|
-
"ms-vscode.vscode-remote-wsl",
|
|
1716
|
-
"redhat.vscode-yaml",
|
|
1717
|
-
"ms-vscode.vscode-markdown",
|
|
1718
|
-
"yzhang.markdown-all-in-one",
|
|
1719
|
-
"shd101wyy.markdown-preview-enhanced",
|
|
1720
|
-
"ms-vscode.vscode-python",
|
|
1721
|
-
"kevinrose.vsc-python-indent",
|
|
1722
|
-
"ms-python.black-formatter",
|
|
1723
|
-
"ms-python.isort",
|
|
1724
|
-
"ms-python.flake8",
|
|
1725
|
-
"ms-python.mypy-type-checker"
|
|
1726
|
-
]
|
|
1727
|
-
}""")
|
|
1728
|
-
click.echo(" Created: .vscode/extensions.json")
|
|
1729
|
-
|
|
1539
|
+
|
|
1730
1540
|
# Create comprehensive API examples
|
|
1731
1541
|
(project_dir / "pages" / "api" / "hello.py").write_text(
|
|
1732
1542
|
'''"""API example - Hello endpoint"""
|
|
@@ -2209,77 +2019,6 @@ Thumbs.db
|
|
|
2209
2019
|
''')
|
|
2210
2020
|
click.echo(" Created: .gitignore")
|
|
2211
2021
|
|
|
2212
|
-
# Create main.py with Tailwind compilation (for pip-installed NextPy)
|
|
2213
|
-
(project_dir / "main.py").write_text('''"""NextPy ASGI Application Entry Point"""
|
|
2214
|
-
|
|
2215
|
-
import os
|
|
2216
|
-
import sys
|
|
2217
|
-
import subprocess
|
|
2218
|
-
from pathlib import Path
|
|
2219
|
-
|
|
2220
|
-
try:
|
|
2221
|
-
print("Compiling Tailwind CSS...")
|
|
2222
|
-
proj_root = Path.cwd()
|
|
2223
|
-
framework_dir = Path(__file__).parent
|
|
2224
|
-
# If the project root doesn't have a styles.css yet, warn the user and create a minimal one.
|
|
2225
|
-
styles_file = proj_root / "styles.css"
|
|
2226
|
-
if not styles_file.exists():
|
|
2227
|
-
print("Warning: styles.css not found, creating a minimal file.")
|
|
2228
|
-
styles_file.write_text("@tailwind base;\n@tailwind components;\n@tailwind utilities;\n")
|
|
2229
|
-
|
|
2230
|
-
import shutil
|
|
2231
|
-
npm_bin = shutil.which("npm")
|
|
2232
|
-
if not npm_bin:
|
|
2233
|
-
raise FileNotFoundError("npm not found on PATH")
|
|
2234
|
-
|
|
2235
|
-
lockfile = framework_dir / "package-lock.json"
|
|
2236
|
-
node_modules = framework_dir / "node_modules"
|
|
2237
|
-
if not node_modules.exists():
|
|
2238
|
-
if lockfile.exists():
|
|
2239
|
-
subprocess.run([npm_bin, "ci"], cwd=str(framework_dir), check=True)
|
|
2240
|
-
else:
|
|
2241
|
-
subprocess.run([npm_bin, "install"], cwd=str(framework_dir), check=True)
|
|
2242
|
-
|
|
2243
|
-
subprocess.run([npm_bin, "run", "build:tailwind"], cwd=str(framework_dir), check=True)
|
|
2244
|
-
print("Tailwind CSS compiled successfully.")
|
|
2245
|
-
except subprocess.CalledProcessError as e:
|
|
2246
|
-
print(f"Error compiling Tailwind CSS: {e}")
|
|
2247
|
-
print("You can also run `cd .nextpy_framework/nextpy && npm ci && npm run build:tailwind` manually.")
|
|
2248
|
-
except FileNotFoundError:
|
|
2249
|
-
print("Error: npm not found. Make sure Node.js is installed and available on PATH.")
|
|
2250
|
-
print("See https://nodejs.org/ for installation instructions.")
|
|
2251
|
-
|
|
2252
|
-
# Import NextPy modules (works when installed via pip)
|
|
2253
|
-
from nextpy.server.app import create_app
|
|
2254
|
-
from nextpy.db import init_db
|
|
2255
|
-
from nextpy.config import settings
|
|
2256
|
-
|
|
2257
|
-
# Initialize database
|
|
2258
|
-
try:
|
|
2259
|
-
init_db(settings["database_url"])
|
|
2260
|
-
print("Database initialized successfully.")
|
|
2261
|
-
except Exception as e:
|
|
2262
|
-
print(f"Warning: Database initialization failed: {e}")
|
|
2263
|
-
|
|
2264
|
-
# Create NextPy app with file-based routing
|
|
2265
|
-
app = create_app(
|
|
2266
|
-
pages_dir="pages",
|
|
2267
|
-
templates_dir="templates",
|
|
2268
|
-
public_dir="public",
|
|
2269
|
-
out_dir="out",
|
|
2270
|
-
debug=settings["debug"],
|
|
2271
|
-
)
|
|
2272
|
-
|
|
2273
|
-
# Note: Routes are automatically loaded from pages/ directory
|
|
2274
|
-
# - / -> pages/index.py
|
|
2275
|
-
# - /about -> pages/about.py
|
|
2276
|
-
# - /api/* -> pages/api/*.py
|
|
2277
|
-
|
|
2278
|
-
if __name__ == "__main__":
|
|
2279
|
-
import uvicorn
|
|
2280
|
-
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
|
|
2281
|
-
''')
|
|
2282
|
-
click.echo(" Created: main.py (pip-compatible)")
|
|
2283
2022
|
|
|
2284
2023
|
# Create .env file for development
|
|
2285
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
|
-
|
|
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
|
|