affineui 0.4.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 (34) hide show
  1. affineui-0.4.0/CMakeLists.txt +65 -0
  2. affineui-0.4.0/PKG-INFO +204 -0
  3. affineui-0.4.0/README.md +190 -0
  4. affineui-0.4.0/dist/affineui-0.0.3-cp311-cp311-win_amd64.whl +0 -0
  5. affineui-0.4.0/examples/component_gallery.py +840 -0
  6. affineui-0.4.0/examples/hello.py +24 -0
  7. affineui-0.4.0/examples/hello_panel.py +11 -0
  8. affineui-0.4.0/examples/photo_edit.py +72 -0
  9. affineui-0.4.0/examples/photo_edit_app/WEB_REFERENCE.md +356 -0
  10. affineui-0.4.0/examples/photo_edit_app/__init__.py +94 -0
  11. affineui-0.4.0/examples/photo_edit_app/app.py +1463 -0
  12. affineui-0.4.0/examples/photo_edit_app/colors.py +55 -0
  13. affineui-0.4.0/examples/photo_edit_app/dialogs.py +511 -0
  14. affineui-0.4.0/examples/photo_edit_app/options.py +150 -0
  15. affineui-0.4.0/examples/photo_edit_app/panels.py +578 -0
  16. affineui-0.4.0/examples/photo_edit_app/specs.py +372 -0
  17. affineui-0.4.0/examples/photo_edit_app/stage.py +139 -0
  18. affineui-0.4.0/examples/photo_edit_app/styles.py +352 -0
  19. affineui-0.4.0/examples/test_panels/__init__.py +1 -0
  20. affineui-0.4.0/examples/test_panels/collections.py +50 -0
  21. affineui-0.4.0/examples/test_panels/controls.py +66 -0
  22. affineui-0.4.0/examples/test_panels/decius_reference.py +586 -0
  23. affineui-0.4.0/examples/test_panels/forms.py +73 -0
  24. affineui-0.4.0/examples/test_panels/photo.py +130 -0
  25. affineui-0.4.0/pyproject.toml +43 -0
  26. affineui-0.4.0/python/affineui/__init__.py +309 -0
  27. affineui-0.4.0/python/affineui/__init__.pyi +581 -0
  28. affineui-0.4.0/python/affineui/py.typed +0 -0
  29. affineui-0.4.0/src/affineui_py.cpp +2042 -0
  30. affineui-0.4.0/tests/conftest.py +63 -0
  31. affineui-0.4.0/tests/test_ime.py +250 -0
  32. affineui-0.4.0/tests/test_photo_app.py +306 -0
  33. affineui-0.4.0/tests/test_photo_core.py +501 -0
  34. affineui-0.4.0/tests/test_smoke.py +502 -0
@@ -0,0 +1,65 @@
1
+ cmake_minimum_required(VERSION 3.20)
2
+
3
+ project(affineui_python
4
+ VERSION 0.0.1
5
+ DESCRIPTION "Python bindings for AffineUI"
6
+ LANGUAGES CXX
7
+ )
8
+
9
+ find_package(Python COMPONENTS Interpreter Development.Module REQUIRED)
10
+ find_package(pybind11 CONFIG REQUIRED)
11
+
12
+ if(NOT TARGET affineui)
13
+ set(AFFINEUI_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
14
+ set(AFFINEUI_BUILD_TESTS OFF CACHE BOOL "" FORCE)
15
+ set(AFFINEUI_BUILD_TOOLS OFF CACHE BOOL "" FORCE)
16
+ set(AFFINEUI_BUILD_PYTHON_BINDINGS OFF CACHE BOOL "" FORCE)
17
+ set(AFFINEUI_INSTALL OFF CACHE BOOL "" FORCE)
18
+ add_subdirectory(
19
+ "${CMAKE_CURRENT_LIST_DIR}/../.."
20
+ "${CMAKE_CURRENT_BINARY_DIR}/affineui-core"
21
+ )
22
+ endif()
23
+
24
+ pybind11_add_module(_affineui MODULE
25
+ src/affineui_py.cpp
26
+ )
27
+
28
+ target_link_libraries(_affineui PRIVATE affineui::affineui)
29
+ target_compile_features(_affineui PRIVATE cxx_std_20)
30
+ target_compile_definitions(_affineui PRIVATE
31
+ AFFINEUI_PY_VERSION="${PROJECT_VERSION}"
32
+ )
33
+
34
+ install(TARGETS _affineui
35
+ LIBRARY DESTINATION affineui
36
+ RUNTIME DESTINATION affineui
37
+ )
38
+
39
+ # ── photo_core: example-support extension module (NOT part of affineui) ──────
40
+ # The Decius Photo Edit sample's raster core lives with the other C++ example
41
+ # sidecars in examples/core/. Building it here (where pybind11 is already in
42
+ # scope) yields a standalone `photo_core` module the sample imports alongside
43
+ # `affineui`. It is not shipped inside the affineui package.
44
+ add_subdirectory(
45
+ "${CMAKE_CURRENT_LIST_DIR}/../../examples/core/photoedit"
46
+ "${CMAKE_CURRENT_BINARY_DIR}/photoedit"
47
+ )
48
+ affineui_photoedit_python_module()
49
+
50
+ # photo_core installs as a top-level module at the wheel root so both the
51
+ # sample (`import photo_core`) and the test suite import it the normal way.
52
+ # It shares process-global pybind11 internals with affineui's _affineui, so
53
+ # the two MUST come from the same build — a clean editable reinstall keeps
54
+ # them in lockstep; the sample additionally carries a self-locator fallback
55
+ # that loads an ABI-matched photo_core from _affineui's own directory if the
56
+ # top-level import ever misses (partial/edited trees).
57
+ install(TARGETS photo_core
58
+ LIBRARY DESTINATION .
59
+ RUNTIME DESTINATION .
60
+ )
61
+
62
+ install(FILES
63
+ "${CMAKE_CURRENT_LIST_DIR}/../../extras/browser_server/affineui_browser_server.h"
64
+ DESTINATION affineui/include
65
+ )
@@ -0,0 +1,204 @@
1
+ Metadata-Version: 2.2
2
+ Name: affineui
3
+ Version: 0.4.0
4
+ Summary: Python bindings for AffineUI — GPU-accelerated HTML/CSS UI for tools and game engines. EXPERIMENTAL preview; APIs will change.
5
+ Author: AffineUI contributors
6
+ License: MIT
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: C++
10
+ Classifier: Topic :: Software Development :: User Interfaces
11
+ Project-URL: Repository, https://github.com/affineui/affineui
12
+ Requires-Python: >=3.9
13
+ Description-Content-Type: text/markdown
14
+
15
+ # AffineUI for Python
16
+
17
+ <img src="https://raw.githubusercontent.com/affineui/affineui/main/images/affineui_dender.png" width="720" alt="AffineUI running the Dender 3D-print slicer — the default Decius CSS look">
18
+
19
+ <img src="https://raw.githubusercontent.com/affineui/affineui/main/images/affineui_bootstrap.png" width="720" alt="AffineUI rendering a Bootstrap dashboard">
20
+
21
+ **A small, HTML5-compliant, GPU-accelerated UI renderer with an integrated
22
+ component framework — a native replacement for Electron and Qt, for Python.**
23
+
24
+ Think Gradio, but native: describe your UI as a tree of typed components,
25
+ get a real HTML/CSS renderer with a browser-quality cascade, animations,
26
+ hit-testing, and 120 Hz paint — all in one binary, no browser embedded, no
27
+ JavaScript runtime, no Electron. Bootstrap and Tailwind-style stylesheets
28
+ render out of the box; the bundled default is
29
+ [Decius CSS](https://deciuscss.com).
30
+
31
+ **Status:** alpha. Broad standards coverage, real UIs run today, but
32
+ expect bugs and expect APIs to move.
33
+
34
+ > **Note:** this release carries no `-alpha` suffix in its version number,
35
+ > but AffineUI is alpha and pre-1.0. Features, APIs, and the set of supported
36
+ > platforms are all still in flux.
37
+ >
38
+ > Verified on: **Linux (Ubuntu, x86-64)**, **macOS (Apple Silicon)**, and
39
+ > **Windows (x86-64)** — the full suite (600+ tests) passes on each. Other
40
+ > platforms and architectures are not yet supported.
41
+
42
+ ---
43
+
44
+ ## Install
45
+
46
+ ```bash
47
+ pip install affineui
48
+ ```
49
+
50
+ Prebuilt wheels ship for CPython 3.9 – 3.13 on Linux (`manylinux_2_28`
51
+ x86_64), macOS (universal2 — Intel + Apple Silicon), and Windows AMD64.
52
+
53
+ For a source install from a clone of the [main repo](https://github.com/affineui/affineui):
54
+
55
+ ```bash
56
+ pip install ./bindings/python # regular install
57
+ pip install -e ./bindings/python # editable / dev
58
+ ```
59
+
60
+ ---
61
+
62
+ ## Hello, world
63
+
64
+ ### Component API (recommended)
65
+
66
+ ```python
67
+ import affineui as ui
68
+
69
+ view = ui.View(ui.ViewTheme.Decius)
70
+ view.begin()
71
+ view.heading(1, "Hello from Python")
72
+ view.paragraph("AffineUI — native HTML/CSS, no browser, no JS.")
73
+ view.button("Click me", primary=True, key="go").on_click(lambda: print("clicked!"))
74
+ view.end()
75
+
76
+ app = ui.App(title="Hello", width=720, height=480)
77
+ app.load_view(view)
78
+ raise SystemExit(app.run())
79
+ ```
80
+
81
+ ### Raw HTML
82
+
83
+ ```python
84
+ import affineui as ui
85
+
86
+ app = ui.App(title="Hello", width=720, height=480)
87
+ app.load_html("""
88
+ <main style="padding: 24px; font-family: sans-serif;">
89
+ <h1>Hello from Python</h1>
90
+ <p>AffineUI is alive.</p>
91
+ <button>Click me</button>
92
+ </main>
93
+ """)
94
+ raise SystemExit(app.run())
95
+ ```
96
+
97
+ ### Headless (no window — for CI and tests)
98
+
99
+ ```python
100
+ import affineui as ui
101
+
102
+ doc = ui.document(
103
+ "<main><h1>Hello</h1><p>Layout without a window.</p></main>",
104
+ "main { padding: 16px; } h1 { font-size: 32px; }",
105
+ width=640, height=360,
106
+ )
107
+ print(ui.version(), doc.content_size())
108
+ ```
109
+
110
+ ---
111
+
112
+ ## A modest app
113
+
114
+ A live-updating counter — state lives in Python; the reconciler diffs
115
+ your view and patches the DOM in place. CSS hover/focus/animation keeps
116
+ running between updates.
117
+
118
+ ```python
119
+ import affineui as ui
120
+
121
+ count = 0
122
+ app = ui.App(title="Counter", width=480, height=240)
123
+
124
+ def build_view() -> ui.View:
125
+ view = ui.View(ui.ViewTheme.Decius)
126
+ view.begin()
127
+ view.heading(1, f"Count: {count}")
128
+ view.button("Increment", primary=True, key="inc").on_click(bump)
129
+ view.button("Reset", key="reset").on_click(reset)
130
+ view.end()
131
+ return view
132
+
133
+ def bump():
134
+ global count
135
+ count += 1
136
+ app.load_view(build_view())
137
+
138
+ def reset():
139
+ global count
140
+ count = 0
141
+ app.load_view(build_view())
142
+
143
+ app.load_view(build_view())
144
+ raise SystemExit(app.run())
145
+ ```
146
+
147
+ The main repo's [`bindings/python/examples/`](https://github.com/affineui/affineui/tree/main/bindings/python/examples)
148
+ ships larger runnable programs — a component gallery, a photo editor,
149
+ and a full Bootstrap-styled panel demo.
150
+
151
+ ---
152
+
153
+ ## Loading design-system CSS
154
+
155
+ Decius CSS is the default when you use the component API. To render your
156
+ own HTML with a framework stylesheet, tell the app where its asset
157
+ folder is:
158
+
159
+ ```python
160
+ app = ui.App(
161
+ title="Bootstrap demo",
162
+ width=1280,
163
+ height=720,
164
+ asset_folders=["examples"], # so href="frameworks/..." resolves
165
+ )
166
+ app.load_html("""
167
+ <link rel="stylesheet" href="frameworks/css/bootstrap-5.3.8.min.css">
168
+ <div class="container py-4">
169
+ <button class="btn btn-primary">Native Bootstrap</button>
170
+ </div>
171
+ """)
172
+ raise SystemExit(app.run())
173
+ ```
174
+
175
+ Bootstrap 4.6 / 5.3, Tailwind-style utility classes, and Ant-style
176
+ component markup all render — this is a real CSS engine, not an
177
+ HTML-shaped layout solver.
178
+
179
+ ---
180
+
181
+ ## What AffineUI is *not*
182
+
183
+ - **Not a browser.** No navigation, no `fetch`, no cookies.
184
+ - **Not a nerfed HTML5.** Missing non-esoteric features are bugs.
185
+ - **Not a security sandbox.** Never feed it untrusted HTML/CSS/JS.
186
+ - **Not an everything-included framework.** No video decode, no audio,
187
+ no 3D — those are your app's job.
188
+ - **Not (yet) a JS runtime.** JS + React support is on the roadmap as
189
+ an opt-in extension.
190
+
191
+ See the [main README](https://github.com/affineui/affineui) for the
192
+ full picture, embedding notes, C++ / Rust / C# APIs, and the demo
193
+ gallery.
194
+
195
+ ---
196
+
197
+ ## Links
198
+
199
+ - **Repository:** <https://github.com/affineui/affineui>
200
+ - **Docs:** <https://github.com/affineui/affineui/tree/main/docs>
201
+ - **Issues:** <https://github.com/affineui/affineui/issues>
202
+ - **Discussion:** [r/affineui](https://www.reddit.com/r/affineui/) — questions,
203
+ show-and-tell, and general chat
204
+ - **License:** MIT
@@ -0,0 +1,190 @@
1
+ # AffineUI for Python
2
+
3
+ <img src="https://raw.githubusercontent.com/affineui/affineui/main/images/affineui_dender.png" width="720" alt="AffineUI running the Dender 3D-print slicer — the default Decius CSS look">
4
+
5
+ <img src="https://raw.githubusercontent.com/affineui/affineui/main/images/affineui_bootstrap.png" width="720" alt="AffineUI rendering a Bootstrap dashboard">
6
+
7
+ **A small, HTML5-compliant, GPU-accelerated UI renderer with an integrated
8
+ component framework — a native replacement for Electron and Qt, for Python.**
9
+
10
+ Think Gradio, but native: describe your UI as a tree of typed components,
11
+ get a real HTML/CSS renderer with a browser-quality cascade, animations,
12
+ hit-testing, and 120 Hz paint — all in one binary, no browser embedded, no
13
+ JavaScript runtime, no Electron. Bootstrap and Tailwind-style stylesheets
14
+ render out of the box; the bundled default is
15
+ [Decius CSS](https://deciuscss.com).
16
+
17
+ **Status:** alpha. Broad standards coverage, real UIs run today, but
18
+ expect bugs and expect APIs to move.
19
+
20
+ > **Note:** this release carries no `-alpha` suffix in its version number,
21
+ > but AffineUI is alpha and pre-1.0. Features, APIs, and the set of supported
22
+ > platforms are all still in flux.
23
+ >
24
+ > Verified on: **Linux (Ubuntu, x86-64)**, **macOS (Apple Silicon)**, and
25
+ > **Windows (x86-64)** — the full suite (600+ tests) passes on each. Other
26
+ > platforms and architectures are not yet supported.
27
+
28
+ ---
29
+
30
+ ## Install
31
+
32
+ ```bash
33
+ pip install affineui
34
+ ```
35
+
36
+ Prebuilt wheels ship for CPython 3.9 – 3.13 on Linux (`manylinux_2_28`
37
+ x86_64), macOS (universal2 — Intel + Apple Silicon), and Windows AMD64.
38
+
39
+ For a source install from a clone of the [main repo](https://github.com/affineui/affineui):
40
+
41
+ ```bash
42
+ pip install ./bindings/python # regular install
43
+ pip install -e ./bindings/python # editable / dev
44
+ ```
45
+
46
+ ---
47
+
48
+ ## Hello, world
49
+
50
+ ### Component API (recommended)
51
+
52
+ ```python
53
+ import affineui as ui
54
+
55
+ view = ui.View(ui.ViewTheme.Decius)
56
+ view.begin()
57
+ view.heading(1, "Hello from Python")
58
+ view.paragraph("AffineUI — native HTML/CSS, no browser, no JS.")
59
+ view.button("Click me", primary=True, key="go").on_click(lambda: print("clicked!"))
60
+ view.end()
61
+
62
+ app = ui.App(title="Hello", width=720, height=480)
63
+ app.load_view(view)
64
+ raise SystemExit(app.run())
65
+ ```
66
+
67
+ ### Raw HTML
68
+
69
+ ```python
70
+ import affineui as ui
71
+
72
+ app = ui.App(title="Hello", width=720, height=480)
73
+ app.load_html("""
74
+ <main style="padding: 24px; font-family: sans-serif;">
75
+ <h1>Hello from Python</h1>
76
+ <p>AffineUI is alive.</p>
77
+ <button>Click me</button>
78
+ </main>
79
+ """)
80
+ raise SystemExit(app.run())
81
+ ```
82
+
83
+ ### Headless (no window — for CI and tests)
84
+
85
+ ```python
86
+ import affineui as ui
87
+
88
+ doc = ui.document(
89
+ "<main><h1>Hello</h1><p>Layout without a window.</p></main>",
90
+ "main { padding: 16px; } h1 { font-size: 32px; }",
91
+ width=640, height=360,
92
+ )
93
+ print(ui.version(), doc.content_size())
94
+ ```
95
+
96
+ ---
97
+
98
+ ## A modest app
99
+
100
+ A live-updating counter — state lives in Python; the reconciler diffs
101
+ your view and patches the DOM in place. CSS hover/focus/animation keeps
102
+ running between updates.
103
+
104
+ ```python
105
+ import affineui as ui
106
+
107
+ count = 0
108
+ app = ui.App(title="Counter", width=480, height=240)
109
+
110
+ def build_view() -> ui.View:
111
+ view = ui.View(ui.ViewTheme.Decius)
112
+ view.begin()
113
+ view.heading(1, f"Count: {count}")
114
+ view.button("Increment", primary=True, key="inc").on_click(bump)
115
+ view.button("Reset", key="reset").on_click(reset)
116
+ view.end()
117
+ return view
118
+
119
+ def bump():
120
+ global count
121
+ count += 1
122
+ app.load_view(build_view())
123
+
124
+ def reset():
125
+ global count
126
+ count = 0
127
+ app.load_view(build_view())
128
+
129
+ app.load_view(build_view())
130
+ raise SystemExit(app.run())
131
+ ```
132
+
133
+ The main repo's [`bindings/python/examples/`](https://github.com/affineui/affineui/tree/main/bindings/python/examples)
134
+ ships larger runnable programs — a component gallery, a photo editor,
135
+ and a full Bootstrap-styled panel demo.
136
+
137
+ ---
138
+
139
+ ## Loading design-system CSS
140
+
141
+ Decius CSS is the default when you use the component API. To render your
142
+ own HTML with a framework stylesheet, tell the app where its asset
143
+ folder is:
144
+
145
+ ```python
146
+ app = ui.App(
147
+ title="Bootstrap demo",
148
+ width=1280,
149
+ height=720,
150
+ asset_folders=["examples"], # so href="frameworks/..." resolves
151
+ )
152
+ app.load_html("""
153
+ <link rel="stylesheet" href="frameworks/css/bootstrap-5.3.8.min.css">
154
+ <div class="container py-4">
155
+ <button class="btn btn-primary">Native Bootstrap</button>
156
+ </div>
157
+ """)
158
+ raise SystemExit(app.run())
159
+ ```
160
+
161
+ Bootstrap 4.6 / 5.3, Tailwind-style utility classes, and Ant-style
162
+ component markup all render — this is a real CSS engine, not an
163
+ HTML-shaped layout solver.
164
+
165
+ ---
166
+
167
+ ## What AffineUI is *not*
168
+
169
+ - **Not a browser.** No navigation, no `fetch`, no cookies.
170
+ - **Not a nerfed HTML5.** Missing non-esoteric features are bugs.
171
+ - **Not a security sandbox.** Never feed it untrusted HTML/CSS/JS.
172
+ - **Not an everything-included framework.** No video decode, no audio,
173
+ no 3D — those are your app's job.
174
+ - **Not (yet) a JS runtime.** JS + React support is on the roadmap as
175
+ an opt-in extension.
176
+
177
+ See the [main README](https://github.com/affineui/affineui) for the
178
+ full picture, embedding notes, C++ / Rust / C# APIs, and the demo
179
+ gallery.
180
+
181
+ ---
182
+
183
+ ## Links
184
+
185
+ - **Repository:** <https://github.com/affineui/affineui>
186
+ - **Docs:** <https://github.com/affineui/affineui/tree/main/docs>
187
+ - **Issues:** <https://github.com/affineui/affineui/issues>
188
+ - **Discussion:** [r/affineui](https://www.reddit.com/r/affineui/) — questions,
189
+ show-and-tell, and general chat
190
+ - **License:** MIT