creation-framework 0.1.0a2__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.
- creation_framework-0.1.0a2/LICENSE +21 -0
- creation_framework-0.1.0a2/PKG-INFO +254 -0
- creation_framework-0.1.0a2/README.md +243 -0
- creation_framework-0.1.0a2/creation/__init__.py +97 -0
- creation_framework-0.1.0a2/creation/assets/__init__.py +0 -0
- creation_framework-0.1.0a2/creation/cli/__init__.py +0 -0
- creation_framework-0.1.0a2/creation/cli/cli.py +431 -0
- creation_framework-0.1.0a2/creation/components/__init__.py +0 -0
- creation_framework-0.1.0a2/creation/components/component.py +390 -0
- creation_framework-0.1.0a2/creation/context/__init__.py +0 -0
- creation_framework-0.1.0a2/creation/context/context.py +42 -0
- creation_framework-0.1.0a2/creation/core/__init__.py +0 -0
- creation_framework-0.1.0a2/creation/core/lifecycle.py +24 -0
- creation_framework-0.1.0a2/creation/diff/__init__.py +0 -0
- creation_framework-0.1.0a2/creation/diff/keyed.py +195 -0
- creation_framework-0.1.0a2/creation/dom/__init__.py +0 -0
- creation_framework-0.1.0a2/creation/dom/dom.py +218 -0
- creation_framework-0.1.0a2/creation/error/__init__.py +0 -0
- creation_framework-0.1.0a2/creation/error/error.py +50 -0
- creation_framework-0.1.0a2/creation/hooks/__init__.py +5 -0
- creation_framework-0.1.0a2/creation/hooks/hooks.py +228 -0
- creation_framework-0.1.0a2/creation/js/creation.js +165 -0
- creation_framework-0.1.0a2/creation/js/kernel.js +345 -0
- creation_framework-0.1.0a2/creation/kernel/__init__.py +0 -0
- creation_framework-0.1.0a2/creation/kernel/kernel.py +321 -0
- creation_framework-0.1.0a2/creation/kernel/timers.py +147 -0
- creation_framework-0.1.0a2/creation/reactive/__init__.py +0 -0
- creation_framework-0.1.0a2/creation/reactive/reactive.py +222 -0
- creation_framework-0.1.0a2/creation/router/__init__.py +0 -0
- creation_framework-0.1.0a2/creation/router/router.py +242 -0
- creation_framework-0.1.0a2/creation/src/__init__.py +0 -0
- creation_framework-0.1.0a2/creation/src/app.py +11 -0
- creation_framework-0.1.0a2/creation/src/html.py +428 -0
- creation_framework-0.1.0a2/creation/store/__init__.py +0 -0
- creation_framework-0.1.0a2/creation/store/store.py +135 -0
- creation_framework-0.1.0a2/creation_framework.egg-info/PKG-INFO +254 -0
- creation_framework-0.1.0a2/creation_framework.egg-info/SOURCES.txt +41 -0
- creation_framework-0.1.0a2/creation_framework.egg-info/dependency_links.txt +1 -0
- creation_framework-0.1.0a2/creation_framework.egg-info/entry_points.txt +2 -0
- creation_framework-0.1.0a2/creation_framework.egg-info/top_level.txt +1 -0
- creation_framework-0.1.0a2/pyproject.toml +31 -0
- creation_framework-0.1.0a2/setup.cfg +4 -0
- creation_framework-0.1.0a2/tests/test.py +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Parag Ghatage
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: creation-framework
|
|
3
|
+
Version: 0.1.0a2
|
|
4
|
+
Summary: A Python-first UI framework that runs in the browser using Pyodide. This is a fork of Evolve by Parag Ghatage.
|
|
5
|
+
Author-email: Alexander Matulionis <a.matulionis@usa.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Dynamic: license-file
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
<div align="center">
|
|
14
|
+
<h1>🌍 Creation</h1>
|
|
15
|
+
<p><strong>The Python-Native Frontend Framework</strong></p>
|
|
16
|
+
<p>
|
|
17
|
+
<a href="https://pypi.org/project/creation/">
|
|
18
|
+
<img src="https://img.shields.io/badge/pypi-v0.1.0-blue?style=flat-square&logo=pypi&logoColor=white" alt="PyPI Version" />
|
|
19
|
+
</a>
|
|
20
|
+
<a href="#">
|
|
21
|
+
<img src="https://img.shields.io/badge/python-3.11+-yellow?style=flat-square&logo=python&logoColor=white" alt="Python Version" />
|
|
22
|
+
</a>
|
|
23
|
+
<a href="LICENSE">
|
|
24
|
+
<img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License" />
|
|
25
|
+
</a>
|
|
26
|
+
</p>
|
|
27
|
+
|
|
28
|
+
<p>
|
|
29
|
+
Build high-performance, reactive web applications entirely in Python.<br/>
|
|
30
|
+
Powered by <strong>Pyodide (WASM)</strong> and a fine-grained <strong>Solid.js-style</strong> reactive engine.
|
|
31
|
+
</p>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
### Highlights
|
|
36
|
+
|
|
37
|
+
- **⚡ Zero Virtual DOM:** Uses fine-grained signals for direct DOM updates (O(1) complexity).
|
|
38
|
+
- **🐍 Python Native:** Write components, routing, and logic in pure Python.
|
|
39
|
+
- **📦 Tiny Bundle:** A minimal JS kernel coupled with an optimized Python environment.
|
|
40
|
+
- **🌐 Static Deployment:** Builds to pure HTML/CSS/WASM. Deploy to Vercel, Netlify, or GitHub Pages.
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
**Creation** is a paradigm shift for Python web development. Unlike traditional frameworks that render HTML on the server (Django, Flask) or wrap heavy JS runtimes, Creation runs **natively in the browser** via WebAssembly.
|
|
46
|
+
|
|
47
|
+
It features a **radical 2KB JavaScript micro-kernel** that handles DOM operations, while your application logic, state management, and component rendering happen entirely in Python.
|
|
48
|
+
|
|
49
|
+
This is a fork of Evolve by Parag Ghatage.
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
Requires Python 3.11+.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install creation
|
|
57
|
+
````
|
|
58
|
+
|
|
59
|
+
-----
|
|
60
|
+
|
|
61
|
+
## Quick Start
|
|
62
|
+
|
|
63
|
+
Get a reactive app running in seconds.
|
|
64
|
+
|
|
65
|
+
### 1\. Initialize a Project
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
creation init my-app
|
|
69
|
+
cd my-app
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
This creates a simple `app.py` with example routes.
|
|
73
|
+
|
|
74
|
+
### 2\. Run the Dev Server
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
creation run
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Visit `http://localhost:3000` to see your app.
|
|
81
|
+
|
|
82
|
+
### 3\. Build for Production
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
creation build
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
This compiles your app into `.creation/dist/`, ready for static hosting.
|
|
89
|
+
|
|
90
|
+
-----
|
|
91
|
+
|
|
92
|
+
## The "Hello World" Component
|
|
93
|
+
|
|
94
|
+
Creation uses a FastAPI-style decorator syntax. Create an `app.py` anywhere:
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from creation.router.router import page
|
|
98
|
+
from creation.src.html import div, h1, button, p
|
|
99
|
+
from creation.reactive.reactive import signal
|
|
100
|
+
|
|
101
|
+
@page("/")
|
|
102
|
+
def Home():
|
|
103
|
+
# Reactive state (Signals)
|
|
104
|
+
count = signal(0)
|
|
105
|
+
|
|
106
|
+
def increment(ev=None):
|
|
107
|
+
count(count() + 1)
|
|
108
|
+
|
|
109
|
+
return div(
|
|
110
|
+
h1("Welcome to Creation 🌍"),
|
|
111
|
+
p(lambda: f"Count: {count()}"), # Reactive text
|
|
112
|
+
button("Increment", on_click=increment),
|
|
113
|
+
style={"textAlign": "center", "fontFamily": "sans-serif"}
|
|
114
|
+
)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Run it:
|
|
118
|
+
```bash
|
|
119
|
+
creation run app.py
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
-----
|
|
123
|
+
|
|
124
|
+
## Key Features
|
|
125
|
+
|
|
126
|
+
### 1\. Fine-Grained Reactivity (Signals)
|
|
127
|
+
|
|
128
|
+
Creation doesn't re-render entire components. When a `signal` changes, only the specific text node or attribute bound to it updates.
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
from creation.reactive.reactive import signal, computed
|
|
132
|
+
|
|
133
|
+
count = signal(0)
|
|
134
|
+
double = computed(lambda: count() * 2)
|
|
135
|
+
|
|
136
|
+
# Use lambda for reactive text that updates automatically
|
|
137
|
+
span(lambda: f"Double is: {double()}")
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### 2\. Built-in Routing
|
|
141
|
+
|
|
142
|
+
A lightweight, history-mode router is included out of the box.
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
from creation.router.router import page, Link
|
|
146
|
+
|
|
147
|
+
@page("/about")
|
|
148
|
+
def About():
|
|
149
|
+
return div(
|
|
150
|
+
h1("About Us"),
|
|
151
|
+
Link("Go Home", to="/")
|
|
152
|
+
)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### 3\. Tailwind-Style Styling
|
|
156
|
+
|
|
157
|
+
Creation includes a `tw()` utility for rapid styling without leaving Python.
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
from creation.src.html import div, tw
|
|
161
|
+
|
|
162
|
+
div("Hello", **tw("text-white bg-blue-500 p-4 rounded-lg flex justify-center"))
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### 4\. Component Lifecycle
|
|
166
|
+
|
|
167
|
+
Hook into mount and unmount events for side effects (API calls, subscriptions).
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
from creation.components.component import component
|
|
171
|
+
from creation.core.lifecycle import on_mount, on_cleanup
|
|
172
|
+
|
|
173
|
+
@component
|
|
174
|
+
def Timer():
|
|
175
|
+
on_mount(lambda: print("Component mounted!"))
|
|
176
|
+
on_cleanup(lambda: print("Cleaned up!"))
|
|
177
|
+
return div("Timer Component")
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
-----
|
|
181
|
+
|
|
182
|
+
## Architecture
|
|
183
|
+
|
|
184
|
+
Creation bridges the gap between Python and the Browser DOM using a highly efficient architecture:
|
|
185
|
+
|
|
186
|
+
```mermaid
|
|
187
|
+
flowchart TD
|
|
188
|
+
subgraph Browser ["Browser (WASM Context)"]
|
|
189
|
+
direction TB
|
|
190
|
+
App[Your App.py] --> Reactive[Reactive Engine]
|
|
191
|
+
Reactive --> Diff[Diff Engine]
|
|
192
|
+
Diff --> Patch[Patch List]
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
subgraph Kernel ["JS Micro-Kernel"]
|
|
196
|
+
Bridge[Pyodide Bridge]
|
|
197
|
+
RealDOM[Real DOM]
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
Patch -- "Serialized Ops" --> Bridge
|
|
201
|
+
Bridge --> RealDOM
|
|
202
|
+
RealDOM -- "Events" --> App
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
1. **Python Layer:** Calculates changes using Signals.
|
|
207
|
+
2. **Diff Engine:** Generates a minimal list of DOM operations (patches).
|
|
208
|
+
3. **JS Kernel:** A tiny JavaScript layer receives patches and applies them to the real DOM.
|
|
209
|
+
|
|
210
|
+
-----
|
|
211
|
+
|
|
212
|
+
## Project Structure
|
|
213
|
+
|
|
214
|
+
When you run `creation init`, the following structure is created:
|
|
215
|
+
|
|
216
|
+
```text
|
|
217
|
+
my-app/
|
|
218
|
+
├── components/ # Reusable UI components
|
|
219
|
+
├── pages/ # Route handlers (@page)
|
|
220
|
+
├── public/ # Static assets (images, fonts)
|
|
221
|
+
├── creation.zip # Packed engine (generated on build)
|
|
222
|
+
└── app.py # Entry point (auto-generated)
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
-----
|
|
226
|
+
|
|
227
|
+
## Roadmap
|
|
228
|
+
|
|
229
|
+
- [x] **v0.1:** Core Reactive Engine & JS Kernel
|
|
230
|
+
- [x] **v0.1:** Component System & Routing
|
|
231
|
+
- [x] **v0.1:** CLI (`init`, `build`, `run`)
|
|
232
|
+
- [ ] **v0.2:** Global State Management (Store)
|
|
233
|
+
- [ ] **v0.3:** Form Handling & Validation
|
|
234
|
+
- [ ] **v0.4:** Server-Side Rendering (SSR) capabilities
|
|
235
|
+
- [ ] **v1.0:** Full WASM Component Model Support
|
|
236
|
+
|
|
237
|
+
-----
|
|
238
|
+
|
|
239
|
+
## Contributing
|
|
240
|
+
|
|
241
|
+
We welcome contributions\! Please see our [Contributing Guide](#) for details on how to set up the development environment.
|
|
242
|
+
|
|
243
|
+
1. Fork the Project
|
|
244
|
+
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
|
|
245
|
+
3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
|
|
246
|
+
4. Push to the Branch (`git push origin feature/AmazingFeature`)
|
|
247
|
+
5. Open a Pull Request
|
|
248
|
+
|
|
249
|
+
-----
|
|
250
|
+
|
|
251
|
+
## License
|
|
252
|
+
|
|
253
|
+
Distributed under the MIT License. See `LICENSE` for more information.
|
|
254
|
+
-----
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
|
|
2
|
+
<div align="center">
|
|
3
|
+
<h1>🌍 Creation</h1>
|
|
4
|
+
<p><strong>The Python-Native Frontend Framework</strong></p>
|
|
5
|
+
<p>
|
|
6
|
+
<a href="https://pypi.org/project/creation/">
|
|
7
|
+
<img src="https://img.shields.io/badge/pypi-v0.1.0-blue?style=flat-square&logo=pypi&logoColor=white" alt="PyPI Version" />
|
|
8
|
+
</a>
|
|
9
|
+
<a href="#">
|
|
10
|
+
<img src="https://img.shields.io/badge/python-3.11+-yellow?style=flat-square&logo=python&logoColor=white" alt="Python Version" />
|
|
11
|
+
</a>
|
|
12
|
+
<a href="LICENSE">
|
|
13
|
+
<img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License" />
|
|
14
|
+
</a>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p>
|
|
18
|
+
Build high-performance, reactive web applications entirely in Python.<br/>
|
|
19
|
+
Powered by <strong>Pyodide (WASM)</strong> and a fine-grained <strong>Solid.js-style</strong> reactive engine.
|
|
20
|
+
</p>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
### Highlights
|
|
25
|
+
|
|
26
|
+
- **⚡ Zero Virtual DOM:** Uses fine-grained signals for direct DOM updates (O(1) complexity).
|
|
27
|
+
- **🐍 Python Native:** Write components, routing, and logic in pure Python.
|
|
28
|
+
- **📦 Tiny Bundle:** A minimal JS kernel coupled with an optimized Python environment.
|
|
29
|
+
- **🌐 Static Deployment:** Builds to pure HTML/CSS/WASM. Deploy to Vercel, Netlify, or GitHub Pages.
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
**Creation** is a paradigm shift for Python web development. Unlike traditional frameworks that render HTML on the server (Django, Flask) or wrap heavy JS runtimes, Creation runs **natively in the browser** via WebAssembly.
|
|
35
|
+
|
|
36
|
+
It features a **radical 2KB JavaScript micro-kernel** that handles DOM operations, while your application logic, state management, and component rendering happen entirely in Python.
|
|
37
|
+
|
|
38
|
+
This is a fork of Evolve by Parag Ghatage.
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
Requires Python 3.11+.
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install creation
|
|
46
|
+
````
|
|
47
|
+
|
|
48
|
+
-----
|
|
49
|
+
|
|
50
|
+
## Quick Start
|
|
51
|
+
|
|
52
|
+
Get a reactive app running in seconds.
|
|
53
|
+
|
|
54
|
+
### 1\. Initialize a Project
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
creation init my-app
|
|
58
|
+
cd my-app
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
This creates a simple `app.py` with example routes.
|
|
62
|
+
|
|
63
|
+
### 2\. Run the Dev Server
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
creation run
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Visit `http://localhost:3000` to see your app.
|
|
70
|
+
|
|
71
|
+
### 3\. Build for Production
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
creation build
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
This compiles your app into `.creation/dist/`, ready for static hosting.
|
|
78
|
+
|
|
79
|
+
-----
|
|
80
|
+
|
|
81
|
+
## The "Hello World" Component
|
|
82
|
+
|
|
83
|
+
Creation uses a FastAPI-style decorator syntax. Create an `app.py` anywhere:
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from creation.router.router import page
|
|
87
|
+
from creation.src.html import div, h1, button, p
|
|
88
|
+
from creation.reactive.reactive import signal
|
|
89
|
+
|
|
90
|
+
@page("/")
|
|
91
|
+
def Home():
|
|
92
|
+
# Reactive state (Signals)
|
|
93
|
+
count = signal(0)
|
|
94
|
+
|
|
95
|
+
def increment(ev=None):
|
|
96
|
+
count(count() + 1)
|
|
97
|
+
|
|
98
|
+
return div(
|
|
99
|
+
h1("Welcome to Creation 🌍"),
|
|
100
|
+
p(lambda: f"Count: {count()}"), # Reactive text
|
|
101
|
+
button("Increment", on_click=increment),
|
|
102
|
+
style={"textAlign": "center", "fontFamily": "sans-serif"}
|
|
103
|
+
)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Run it:
|
|
107
|
+
```bash
|
|
108
|
+
creation run app.py
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
-----
|
|
112
|
+
|
|
113
|
+
## Key Features
|
|
114
|
+
|
|
115
|
+
### 1\. Fine-Grained Reactivity (Signals)
|
|
116
|
+
|
|
117
|
+
Creation doesn't re-render entire components. When a `signal` changes, only the specific text node or attribute bound to it updates.
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from creation.reactive.reactive import signal, computed
|
|
121
|
+
|
|
122
|
+
count = signal(0)
|
|
123
|
+
double = computed(lambda: count() * 2)
|
|
124
|
+
|
|
125
|
+
# Use lambda for reactive text that updates automatically
|
|
126
|
+
span(lambda: f"Double is: {double()}")
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 2\. Built-in Routing
|
|
130
|
+
|
|
131
|
+
A lightweight, history-mode router is included out of the box.
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
from creation.router.router import page, Link
|
|
135
|
+
|
|
136
|
+
@page("/about")
|
|
137
|
+
def About():
|
|
138
|
+
return div(
|
|
139
|
+
h1("About Us"),
|
|
140
|
+
Link("Go Home", to="/")
|
|
141
|
+
)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### 3\. Tailwind-Style Styling
|
|
145
|
+
|
|
146
|
+
Creation includes a `tw()` utility for rapid styling without leaving Python.
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
from creation.src.html import div, tw
|
|
150
|
+
|
|
151
|
+
div("Hello", **tw("text-white bg-blue-500 p-4 rounded-lg flex justify-center"))
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### 4\. Component Lifecycle
|
|
155
|
+
|
|
156
|
+
Hook into mount and unmount events for side effects (API calls, subscriptions).
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
from creation.components.component import component
|
|
160
|
+
from creation.core.lifecycle import on_mount, on_cleanup
|
|
161
|
+
|
|
162
|
+
@component
|
|
163
|
+
def Timer():
|
|
164
|
+
on_mount(lambda: print("Component mounted!"))
|
|
165
|
+
on_cleanup(lambda: print("Cleaned up!"))
|
|
166
|
+
return div("Timer Component")
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
-----
|
|
170
|
+
|
|
171
|
+
## Architecture
|
|
172
|
+
|
|
173
|
+
Creation bridges the gap between Python and the Browser DOM using a highly efficient architecture:
|
|
174
|
+
|
|
175
|
+
```mermaid
|
|
176
|
+
flowchart TD
|
|
177
|
+
subgraph Browser ["Browser (WASM Context)"]
|
|
178
|
+
direction TB
|
|
179
|
+
App[Your App.py] --> Reactive[Reactive Engine]
|
|
180
|
+
Reactive --> Diff[Diff Engine]
|
|
181
|
+
Diff --> Patch[Patch List]
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
subgraph Kernel ["JS Micro-Kernel"]
|
|
185
|
+
Bridge[Pyodide Bridge]
|
|
186
|
+
RealDOM[Real DOM]
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
Patch -- "Serialized Ops" --> Bridge
|
|
190
|
+
Bridge --> RealDOM
|
|
191
|
+
RealDOM -- "Events" --> App
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
1. **Python Layer:** Calculates changes using Signals.
|
|
196
|
+
2. **Diff Engine:** Generates a minimal list of DOM operations (patches).
|
|
197
|
+
3. **JS Kernel:** A tiny JavaScript layer receives patches and applies them to the real DOM.
|
|
198
|
+
|
|
199
|
+
-----
|
|
200
|
+
|
|
201
|
+
## Project Structure
|
|
202
|
+
|
|
203
|
+
When you run `creation init`, the following structure is created:
|
|
204
|
+
|
|
205
|
+
```text
|
|
206
|
+
my-app/
|
|
207
|
+
├── components/ # Reusable UI components
|
|
208
|
+
├── pages/ # Route handlers (@page)
|
|
209
|
+
├── public/ # Static assets (images, fonts)
|
|
210
|
+
├── creation.zip # Packed engine (generated on build)
|
|
211
|
+
└── app.py # Entry point (auto-generated)
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
-----
|
|
215
|
+
|
|
216
|
+
## Roadmap
|
|
217
|
+
|
|
218
|
+
- [x] **v0.1:** Core Reactive Engine & JS Kernel
|
|
219
|
+
- [x] **v0.1:** Component System & Routing
|
|
220
|
+
- [x] **v0.1:** CLI (`init`, `build`, `run`)
|
|
221
|
+
- [ ] **v0.2:** Global State Management (Store)
|
|
222
|
+
- [ ] **v0.3:** Form Handling & Validation
|
|
223
|
+
- [ ] **v0.4:** Server-Side Rendering (SSR) capabilities
|
|
224
|
+
- [ ] **v1.0:** Full WASM Component Model Support
|
|
225
|
+
|
|
226
|
+
-----
|
|
227
|
+
|
|
228
|
+
## Contributing
|
|
229
|
+
|
|
230
|
+
We welcome contributions\! Please see our [Contributing Guide](#) for details on how to set up the development environment.
|
|
231
|
+
|
|
232
|
+
1. Fork the Project
|
|
233
|
+
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
|
|
234
|
+
3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
|
|
235
|
+
4. Push to the Branch (`git push origin feature/AmazingFeature`)
|
|
236
|
+
5. Open a Pull Request
|
|
237
|
+
|
|
238
|
+
-----
|
|
239
|
+
|
|
240
|
+
## License
|
|
241
|
+
|
|
242
|
+
Distributed under the MIT License. See `LICENSE` for more information.
|
|
243
|
+
-----
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Creation - A Python web framework powered by Pyodide.
|
|
3
|
+
|
|
4
|
+
Core APIs:
|
|
5
|
+
- signal, computed, effect, batch - Reactive primitives
|
|
6
|
+
- component, @page, Link - Component and routing
|
|
7
|
+
- div, span, button, etc. - HTML elements with tw() styling
|
|
8
|
+
- set_timeout, set_interval - Browser timers
|
|
9
|
+
- create_store - Global state management
|
|
10
|
+
- use_effect, use_memo, use_ref - React-like hooks
|
|
11
|
+
|
|
12
|
+
Note: Browser-only modules (kernel, dom, timers) are only imported at runtime
|
|
13
|
+
in Pyodide, not at CLI time.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
__version__ = "0.1.0"
|
|
17
|
+
|
|
18
|
+
# Public API exports for IDE autocompletion and discoverability
|
|
19
|
+
__all__ = [
|
|
20
|
+
# Version
|
|
21
|
+
"__version__",
|
|
22
|
+
# Reactive primitives
|
|
23
|
+
"signal", "computed", "effect", "batch", "Signal", "Computed",
|
|
24
|
+
# Components
|
|
25
|
+
"component",
|
|
26
|
+
# Routing
|
|
27
|
+
"page", "Link", "navigate",
|
|
28
|
+
# Timers
|
|
29
|
+
"set_timeout", "set_interval", "clear_timeout", "clear_interval",
|
|
30
|
+
# Hooks
|
|
31
|
+
"use_effect", "use_memo", "use_ref", "use_callback",
|
|
32
|
+
# Lifecycle
|
|
33
|
+
"on_mount", "on_cleanup",
|
|
34
|
+
# HTML elements
|
|
35
|
+
"tw", "div", "span", "p", "button", "input", "a",
|
|
36
|
+
"h1", "h2", "h3", "h4", "h5", "h6",
|
|
37
|
+
# Store
|
|
38
|
+
"create_store", "init_store", "get_store",
|
|
39
|
+
# Context
|
|
40
|
+
"create_context", "use_context",
|
|
41
|
+
# Error handling
|
|
42
|
+
"ErrorBoundary",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def __getattr__(name):
|
|
47
|
+
"""
|
|
48
|
+
Lazy import to avoid loading browser-only modules at CLI time.
|
|
49
|
+
This allows the CLI to work while still providing convenient imports
|
|
50
|
+
when running in Pyodide.
|
|
51
|
+
"""
|
|
52
|
+
# Reactive (safe to import)
|
|
53
|
+
if name in ("signal", "computed", "effect", "batch", "Signal", "Computed"):
|
|
54
|
+
from .reactive.reactive import signal, computed, effect, batch, Signal, Computed
|
|
55
|
+
return locals()[name]
|
|
56
|
+
|
|
57
|
+
# Store (safe to import)
|
|
58
|
+
if name in ("create_store", "init_store", "get_store"):
|
|
59
|
+
from .store.store import create_store, init_store, get_store
|
|
60
|
+
return locals()[name]
|
|
61
|
+
|
|
62
|
+
# The following require browser environment (js module)
|
|
63
|
+
# They will fail at CLI time but work in Pyodide
|
|
64
|
+
|
|
65
|
+
if name == "component":
|
|
66
|
+
from .components.component import component
|
|
67
|
+
return component
|
|
68
|
+
|
|
69
|
+
if name in ("page", "Link", "navigate"):
|
|
70
|
+
from .router.router import page, Link, navigate
|
|
71
|
+
return locals()[name]
|
|
72
|
+
|
|
73
|
+
if name in ("set_timeout", "set_interval", "clear_timeout", "clear_interval"):
|
|
74
|
+
from .kernel.timers import set_timeout, set_interval, clear_timeout, clear_interval
|
|
75
|
+
return locals()[name]
|
|
76
|
+
|
|
77
|
+
if name in ("use_effect", "use_memo", "use_ref", "use_callback"):
|
|
78
|
+
from .hooks.hooks import use_effect, use_memo, use_ref, use_callback
|
|
79
|
+
return locals()[name]
|
|
80
|
+
|
|
81
|
+
if name in ("tw", "div", "span", "p", "button", "input", "a", "h1", "h2", "h3", "h4", "h5", "h6"):
|
|
82
|
+
from .src.html import tw, div, span, p, button, input, a, h1, h2, h3, h4, h5, h6
|
|
83
|
+
return locals()[name]
|
|
84
|
+
|
|
85
|
+
if name == "ErrorBoundary":
|
|
86
|
+
from .error.error import ErrorBoundary
|
|
87
|
+
return ErrorBoundary
|
|
88
|
+
|
|
89
|
+
if name in ("create_context", "use_context"):
|
|
90
|
+
from .context.context import create_context, use_context
|
|
91
|
+
return locals()[name]
|
|
92
|
+
|
|
93
|
+
if name in ("on_mount", "on_cleanup"):
|
|
94
|
+
from .core.lifecycle import on_mount, on_cleanup
|
|
95
|
+
return locals()[name]
|
|
96
|
+
|
|
97
|
+
raise AttributeError(f"module 'creation' has no attribute '{name}'")
|
|
File without changes
|
|
File without changes
|