streamlit-drawable-konva 0.1.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.
- streamlit_drawable_konva-0.1.0/LICENSE +21 -0
- streamlit_drawable_konva-0.1.0/MANIFEST.in +2 -0
- streamlit_drawable_konva-0.1.0/PKG-INFO +180 -0
- streamlit_drawable_konva-0.1.0/README.md +157 -0
- streamlit_drawable_konva-0.1.0/pyproject.toml +51 -0
- streamlit_drawable_konva-0.1.0/setup.cfg +4 -0
- streamlit_drawable_konva-0.1.0/streamlit_drawable_konva/__init__.py +163 -0
- streamlit_drawable_konva-0.1.0/streamlit_drawable_konva/frontend/build/index.js +17926 -0
- streamlit_drawable_konva-0.1.0/streamlit_drawable_konva/pyproject.toml +8 -0
- streamlit_drawable_konva-0.1.0/streamlit_drawable_konva.egg-info/PKG-INFO +180 -0
- streamlit_drawable_konva-0.1.0/streamlit_drawable_konva.egg-info/SOURCES.txt +12 -0
- streamlit_drawable_konva-0.1.0/streamlit_drawable_konva.egg-info/dependency_links.txt +1 -0
- streamlit_drawable_konva-0.1.0/streamlit_drawable_konva.egg-info/requires.txt +10 -0
- streamlit_drawable_konva-0.1.0/streamlit_drawable_konva.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Streamlit Drawable Konva Contributors
|
|
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,180 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: streamlit-drawable-konva
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Streamlit drawable canvas component using Konva.js (Components v2)
|
|
5
|
+
Author-email: George Siogkas <gsiogkas@cvrlab.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/gsiogkas/streamlit-drawable-konva
|
|
8
|
+
Project-URL: Documentation, https://github.com/gsiogkas/streamlit-drawable-konva#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/gsiogkas/streamlit-drawable-konva
|
|
10
|
+
Project-URL: Issues, https://github.com/gsiogkas/streamlit-drawable-konva/issues
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: streamlit>=1.51
|
|
15
|
+
Requires-Dist: numpy
|
|
16
|
+
Requires-Dist: pillow
|
|
17
|
+
Provides-Extra: demo
|
|
18
|
+
Requires-Dist: pandas; extra == "demo"
|
|
19
|
+
Provides-Extra: devel
|
|
20
|
+
Requires-Dist: wheel; extra == "devel"
|
|
21
|
+
Requires-Dist: pandas; extra == "devel"
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
|
|
24
|
+
# Streamlit Drawable Konva
|
|
25
|
+
|
|
26
|
+
Streamlit custom component (Components **v2**) that provides a sketching canvas
|
|
27
|
+
using [Konva.js](https://konvajs.org/) / `react-konva`.
|
|
28
|
+
|
|
29
|
+
The public Python API is intentionally compatible with
|
|
30
|
+
[`streamlit-drawable-canvas-fix`](https://pypi.org/project/streamlit-drawable-canvas-fix/)
|
|
31
|
+
(`st_canvas` → `CanvasResult(image_data, json_data)`). Object JSON uses
|
|
32
|
+
Konva-oriented fields (`x`/`y`/`points`/…), not Fabric.js schemas.
|
|
33
|
+
|
|
34
|
+
## Features
|
|
35
|
+
|
|
36
|
+
- Freehand, line, rect, circle, point, polygon drawing
|
|
37
|
+
- Transform mode (move / scale / rotate); double-click to delete
|
|
38
|
+
- Background color or image
|
|
39
|
+
- Realtime or on-demand updates to Streamlit
|
|
40
|
+
- Undo / redo / clear toolbar
|
|
41
|
+
- Returns RGBA `image_data` and scene `json_data`
|
|
42
|
+
|
|
43
|
+
## Why Konva.js (vs Fabric.js)?
|
|
44
|
+
|
|
45
|
+
Konva is not universally “better” than Fabric — both are mature 2D canvas
|
|
46
|
+
libraries. For **this** Streamlit component, Konva is the better fit.
|
|
47
|
+
|
|
48
|
+
| Concern | Konva | Fabric |
|
|
49
|
+
| --- | --- | --- |
|
|
50
|
+
| React integration | First-class via `react-konva` (declarative scene tree) | Imperative `fabric.Canvas`; React wrappers are thinner / more brittle |
|
|
51
|
+
| Mental model | Stage → Layer → Shape (clear export boundaries) | Single canvas object model; background vs drawing export needs extra care |
|
|
52
|
+
| Bundle / focus | Leaner, scene-graph oriented | Heavier; strong textile/image-editing heritage |
|
|
53
|
+
| Transforms | Built-in `Transformer` for select / scale / rotate | Excellent selection UX; historically the gold standard for editors |
|
|
54
|
+
| Ecosystem | Strong for interactive UIs and annotation tools | Huge installed base; many Fabric JSON examples in the wild |
|
|
55
|
+
|
|
56
|
+
**Why we chose Konva here**
|
|
57
|
+
|
|
58
|
+
1. **React + Streamlit Components v2** — the official CCv2 React template maps
|
|
59
|
+
cleanly onto `react-konva`. Drawing state stays in React; updates go out via
|
|
60
|
+
`setStateValue` without fighting an imperative canvas singleton.
|
|
61
|
+
2. **Layered export** — background images can live on a non-exported layer while
|
|
62
|
+
strokes/shapes export cleanly to `image_data`, matching the upstream
|
|
63
|
+
“background is not round-tripped” behavior with less glue code.
|
|
64
|
+
3. **Maintainability** — freerdraw / shapes / polygon / transform are ordinary
|
|
65
|
+
React event handlers and Konva nodes, which is easier to evolve next to a
|
|
66
|
+
modern Vite + TypeScript frontend than a Fabric-centric CRA-era stack.
|
|
67
|
+
4. **Performance for annotation UIs** — Konva’s layer/stage model scales well for
|
|
68
|
+
ROI / sketching workloads typical in Streamlit apps.
|
|
69
|
+
|
|
70
|
+
**When Fabric may still win**
|
|
71
|
+
|
|
72
|
+
- You need **byte-compatible Fabric JSON** (existing pipelines, demos, or
|
|
73
|
+
tutorials that assume `left`/`top`/`path` Fabric schemas).
|
|
74
|
+
- You want Fabric’s mature free-transform / skew / complex text editing out of
|
|
75
|
+
the box without reimplementing edge cases.
|
|
76
|
+
|
|
77
|
+
This package keeps a **compatible Python API** (`st_canvas` → `CanvasResult`) so
|
|
78
|
+
apps can migrate from `streamlit-drawable-canvas-fix`, while accepting that
|
|
79
|
+
`json_data` is Konva-oriented rather than a Fabric dump.
|
|
80
|
+
|
|
81
|
+
## Install (uv)
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
uv sync
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Build the frontend once (required before first Streamlit run):
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
cd streamlit_drawable_konva/frontend
|
|
91
|
+
npm install
|
|
92
|
+
npm run build
|
|
93
|
+
cd ../../
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Editable install is handled by `uv sync` via the local `pyproject.toml`.
|
|
97
|
+
|
|
98
|
+
## Demo
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
uv run streamlit run app.py
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Development
|
|
105
|
+
|
|
106
|
+
CCv2 watches a production-style build into `frontend/build` (no separate webpack
|
|
107
|
+
dev server URL). Use two terminals:
|
|
108
|
+
|
|
109
|
+
**Terminal A — frontend watch build**
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
cd streamlit_drawable_konva/frontend
|
|
113
|
+
npm install
|
|
114
|
+
npm run dev
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Terminal B — Streamlit**
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
uv sync
|
|
121
|
+
uv run streamlit run app.py
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Refresh the browser after frontend rebuilds.
|
|
125
|
+
|
|
126
|
+
## API
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
from streamlit_drawable_konva import st_canvas
|
|
130
|
+
|
|
131
|
+
result = st_canvas(
|
|
132
|
+
fill_color="rgba(255, 165, 0, 0.3)",
|
|
133
|
+
stroke_width=3,
|
|
134
|
+
stroke_color="#000000",
|
|
135
|
+
background_color="#eee",
|
|
136
|
+
background_image=None,
|
|
137
|
+
update_streamlit=True,
|
|
138
|
+
height=400,
|
|
139
|
+
width=600,
|
|
140
|
+
drawing_mode="freedraw", # freedraw|line|rect|circle|point|polygon|transform
|
|
141
|
+
initial_drawing=None,
|
|
142
|
+
display_toolbar=True,
|
|
143
|
+
point_display_radius=3,
|
|
144
|
+
key="canvas",
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
# result.image_data -> np.ndarray | None
|
|
148
|
+
# result.json_data -> dict | None
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Polygon controls
|
|
152
|
+
|
|
153
|
+
- Left-click: add point
|
|
154
|
+
- Right-click: close polygon
|
|
155
|
+
- Double-click: remove latest point
|
|
156
|
+
|
|
157
|
+
### Transform controls
|
|
158
|
+
|
|
159
|
+
- Click object to select
|
|
160
|
+
- Drag / resize / rotate with the transformer
|
|
161
|
+
- Double-click selected object to delete
|
|
162
|
+
|
|
163
|
+
## Packaging notes
|
|
164
|
+
|
|
165
|
+
- Registered as `streamlit-drawable-konva.st_canvas` via the in-package
|
|
166
|
+
`streamlit_drawable_konva/pyproject.toml` manifest (`asset_dir = frontend/build`).
|
|
167
|
+
- Requires Streamlit `>= 1.51` (Components v2).
|
|
168
|
+
- Frontend toolchain targets Node `>= 18` (Vite 5).
|
|
169
|
+
|
|
170
|
+
## Publishing (GitHub / PyPI / Streamlit Cloud / gallery)
|
|
171
|
+
|
|
172
|
+
Step-by-step instructions: [`PUBLISHING.md`](PUBLISHING.md).
|
|
173
|
+
|
|
174
|
+
Order: push to GitHub → publish to PyPI → deploy `app.py` on Community Cloud →
|
|
175
|
+
submit [`gallery/streamlit-drawable-konva.json`](gallery/streamlit-drawable-konva.json)
|
|
176
|
+
as a PR to [streamlit/gallery](https://github.com/streamlit/gallery/tree/main/components/registry).
|
|
177
|
+
|
|
178
|
+
## License
|
|
179
|
+
|
|
180
|
+
MIT
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Streamlit Drawable Konva
|
|
2
|
+
|
|
3
|
+
Streamlit custom component (Components **v2**) that provides a sketching canvas
|
|
4
|
+
using [Konva.js](https://konvajs.org/) / `react-konva`.
|
|
5
|
+
|
|
6
|
+
The public Python API is intentionally compatible with
|
|
7
|
+
[`streamlit-drawable-canvas-fix`](https://pypi.org/project/streamlit-drawable-canvas-fix/)
|
|
8
|
+
(`st_canvas` → `CanvasResult(image_data, json_data)`). Object JSON uses
|
|
9
|
+
Konva-oriented fields (`x`/`y`/`points`/…), not Fabric.js schemas.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- Freehand, line, rect, circle, point, polygon drawing
|
|
14
|
+
- Transform mode (move / scale / rotate); double-click to delete
|
|
15
|
+
- Background color or image
|
|
16
|
+
- Realtime or on-demand updates to Streamlit
|
|
17
|
+
- Undo / redo / clear toolbar
|
|
18
|
+
- Returns RGBA `image_data` and scene `json_data`
|
|
19
|
+
|
|
20
|
+
## Why Konva.js (vs Fabric.js)?
|
|
21
|
+
|
|
22
|
+
Konva is not universally “better” than Fabric — both are mature 2D canvas
|
|
23
|
+
libraries. For **this** Streamlit component, Konva is the better fit.
|
|
24
|
+
|
|
25
|
+
| Concern | Konva | Fabric |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| React integration | First-class via `react-konva` (declarative scene tree) | Imperative `fabric.Canvas`; React wrappers are thinner / more brittle |
|
|
28
|
+
| Mental model | Stage → Layer → Shape (clear export boundaries) | Single canvas object model; background vs drawing export needs extra care |
|
|
29
|
+
| Bundle / focus | Leaner, scene-graph oriented | Heavier; strong textile/image-editing heritage |
|
|
30
|
+
| Transforms | Built-in `Transformer` for select / scale / rotate | Excellent selection UX; historically the gold standard for editors |
|
|
31
|
+
| Ecosystem | Strong for interactive UIs and annotation tools | Huge installed base; many Fabric JSON examples in the wild |
|
|
32
|
+
|
|
33
|
+
**Why we chose Konva here**
|
|
34
|
+
|
|
35
|
+
1. **React + Streamlit Components v2** — the official CCv2 React template maps
|
|
36
|
+
cleanly onto `react-konva`. Drawing state stays in React; updates go out via
|
|
37
|
+
`setStateValue` without fighting an imperative canvas singleton.
|
|
38
|
+
2. **Layered export** — background images can live on a non-exported layer while
|
|
39
|
+
strokes/shapes export cleanly to `image_data`, matching the upstream
|
|
40
|
+
“background is not round-tripped” behavior with less glue code.
|
|
41
|
+
3. **Maintainability** — freerdraw / shapes / polygon / transform are ordinary
|
|
42
|
+
React event handlers and Konva nodes, which is easier to evolve next to a
|
|
43
|
+
modern Vite + TypeScript frontend than a Fabric-centric CRA-era stack.
|
|
44
|
+
4. **Performance for annotation UIs** — Konva’s layer/stage model scales well for
|
|
45
|
+
ROI / sketching workloads typical in Streamlit apps.
|
|
46
|
+
|
|
47
|
+
**When Fabric may still win**
|
|
48
|
+
|
|
49
|
+
- You need **byte-compatible Fabric JSON** (existing pipelines, demos, or
|
|
50
|
+
tutorials that assume `left`/`top`/`path` Fabric schemas).
|
|
51
|
+
- You want Fabric’s mature free-transform / skew / complex text editing out of
|
|
52
|
+
the box without reimplementing edge cases.
|
|
53
|
+
|
|
54
|
+
This package keeps a **compatible Python API** (`st_canvas` → `CanvasResult`) so
|
|
55
|
+
apps can migrate from `streamlit-drawable-canvas-fix`, while accepting that
|
|
56
|
+
`json_data` is Konva-oriented rather than a Fabric dump.
|
|
57
|
+
|
|
58
|
+
## Install (uv)
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
uv sync
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Build the frontend once (required before first Streamlit run):
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
cd streamlit_drawable_konva/frontend
|
|
68
|
+
npm install
|
|
69
|
+
npm run build
|
|
70
|
+
cd ../../
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Editable install is handled by `uv sync` via the local `pyproject.toml`.
|
|
74
|
+
|
|
75
|
+
## Demo
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
uv run streamlit run app.py
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Development
|
|
82
|
+
|
|
83
|
+
CCv2 watches a production-style build into `frontend/build` (no separate webpack
|
|
84
|
+
dev server URL). Use two terminals:
|
|
85
|
+
|
|
86
|
+
**Terminal A — frontend watch build**
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
cd streamlit_drawable_konva/frontend
|
|
90
|
+
npm install
|
|
91
|
+
npm run dev
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Terminal B — Streamlit**
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
uv sync
|
|
98
|
+
uv run streamlit run app.py
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Refresh the browser after frontend rebuilds.
|
|
102
|
+
|
|
103
|
+
## API
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from streamlit_drawable_konva import st_canvas
|
|
107
|
+
|
|
108
|
+
result = st_canvas(
|
|
109
|
+
fill_color="rgba(255, 165, 0, 0.3)",
|
|
110
|
+
stroke_width=3,
|
|
111
|
+
stroke_color="#000000",
|
|
112
|
+
background_color="#eee",
|
|
113
|
+
background_image=None,
|
|
114
|
+
update_streamlit=True,
|
|
115
|
+
height=400,
|
|
116
|
+
width=600,
|
|
117
|
+
drawing_mode="freedraw", # freedraw|line|rect|circle|point|polygon|transform
|
|
118
|
+
initial_drawing=None,
|
|
119
|
+
display_toolbar=True,
|
|
120
|
+
point_display_radius=3,
|
|
121
|
+
key="canvas",
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
# result.image_data -> np.ndarray | None
|
|
125
|
+
# result.json_data -> dict | None
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Polygon controls
|
|
129
|
+
|
|
130
|
+
- Left-click: add point
|
|
131
|
+
- Right-click: close polygon
|
|
132
|
+
- Double-click: remove latest point
|
|
133
|
+
|
|
134
|
+
### Transform controls
|
|
135
|
+
|
|
136
|
+
- Click object to select
|
|
137
|
+
- Drag / resize / rotate with the transformer
|
|
138
|
+
- Double-click selected object to delete
|
|
139
|
+
|
|
140
|
+
## Packaging notes
|
|
141
|
+
|
|
142
|
+
- Registered as `streamlit-drawable-konva.st_canvas` via the in-package
|
|
143
|
+
`streamlit_drawable_konva/pyproject.toml` manifest (`asset_dir = frontend/build`).
|
|
144
|
+
- Requires Streamlit `>= 1.51` (Components v2).
|
|
145
|
+
- Frontend toolchain targets Node `>= 18` (Vite 5).
|
|
146
|
+
|
|
147
|
+
## Publishing (GitHub / PyPI / Streamlit Cloud / gallery)
|
|
148
|
+
|
|
149
|
+
Step-by-step instructions: [`PUBLISHING.md`](PUBLISHING.md).
|
|
150
|
+
|
|
151
|
+
Order: push to GitHub → publish to PyPI → deploy `app.py` on Community Cloud →
|
|
152
|
+
submit [`gallery/streamlit-drawable-konva.json`](gallery/streamlit-drawable-konva.json)
|
|
153
|
+
as a PR to [streamlit/gallery](https://github.com/streamlit/gallery/tree/main/components/registry).
|
|
154
|
+
|
|
155
|
+
## License
|
|
156
|
+
|
|
157
|
+
MIT
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77.0.3", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "streamlit-drawable-konva"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Streamlit drawable canvas component using Konva.js (Components v2)"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
requires-python = ">=3.10"
|
|
13
|
+
authors = [
|
|
14
|
+
{ name = "George Siogkas", email = "gsiogkas@cvrlab.com" },
|
|
15
|
+
]
|
|
16
|
+
dependencies = [
|
|
17
|
+
"streamlit>=1.51",
|
|
18
|
+
"numpy",
|
|
19
|
+
"pillow",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
[project.urls]
|
|
23
|
+
Homepage = "https://github.com/gsiogkas/streamlit-drawable-konva"
|
|
24
|
+
Documentation = "https://github.com/gsiogkas/streamlit-drawable-konva#readme"
|
|
25
|
+
Repository = "https://github.com/gsiogkas/streamlit-drawable-konva"
|
|
26
|
+
Issues = "https://github.com/gsiogkas/streamlit-drawable-konva/issues"
|
|
27
|
+
# Demo = "https://YOUR_APP_SLUG.streamlit.app" # uncomment after Cloud deploy
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
[project.optional-dependencies]
|
|
31
|
+
demo = ["pandas"]
|
|
32
|
+
devel = [
|
|
33
|
+
"wheel",
|
|
34
|
+
"pandas",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[dependency-groups]
|
|
38
|
+
demo = ["pandas"]
|
|
39
|
+
dev = ["pandas", "wheel"]
|
|
40
|
+
|
|
41
|
+
[tool.setuptools.packages.find]
|
|
42
|
+
include = ["streamlit_drawable_konva*"]
|
|
43
|
+
|
|
44
|
+
[tool.setuptools]
|
|
45
|
+
include-package-data = true
|
|
46
|
+
|
|
47
|
+
[tool.setuptools.package-data]
|
|
48
|
+
streamlit_drawable_konva = ["frontend/build/**/*", "pyproject.toml"]
|
|
49
|
+
|
|
50
|
+
[tool.uv]
|
|
51
|
+
default-groups = ["demo"]
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"""Streamlit Drawable Konva — Components v2 canvas with a compatible st_canvas API."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import base64
|
|
6
|
+
import io
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from typing import Any, Optional
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
import streamlit as st
|
|
12
|
+
from PIL import Image
|
|
13
|
+
|
|
14
|
+
_COMPONENT = st.components.v2.component(
|
|
15
|
+
"streamlit-drawable-konva.st_canvas",
|
|
16
|
+
js="index.js",
|
|
17
|
+
html='<div class="react-root"></div>',
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class CanvasResult:
|
|
23
|
+
"""Output of the drawable canvas component.
|
|
24
|
+
|
|
25
|
+
Attributes
|
|
26
|
+
----------
|
|
27
|
+
image_data:
|
|
28
|
+
RGBA image as a NumPy array, or None before the first update.
|
|
29
|
+
json_data:
|
|
30
|
+
JSON scene dict (Konva-oriented objects), or None before the first update.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
image_data: Optional[np.ndarray] = None
|
|
34
|
+
json_data: Optional[dict] = None
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _data_url_to_image(data_url: str) -> Image.Image:
|
|
38
|
+
_, encoded = data_url.split(";base64,", 1)
|
|
39
|
+
return Image.open(io.BytesIO(base64.b64decode(encoded)))
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _image_to_data_url(img: Image.Image) -> str:
|
|
43
|
+
buf = io.BytesIO()
|
|
44
|
+
img.convert("RGBA").save(buf, format="PNG")
|
|
45
|
+
b64 = base64.b64encode(buf.getvalue()).decode("ascii")
|
|
46
|
+
return f"data:image/png;base64,{b64}"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _resize_img(img: Image.Image, new_height: int, new_width: int) -> Image.Image:
|
|
50
|
+
return img.resize((new_width, new_height))
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _noop() -> None:
|
|
54
|
+
"""Required CCv2 on_change stub so default state keys are always present."""
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def st_canvas(
|
|
58
|
+
fill_color: str = "#eee",
|
|
59
|
+
stroke_width: int = 20,
|
|
60
|
+
stroke_color: str = "black",
|
|
61
|
+
background_color: str = "",
|
|
62
|
+
background_image: Optional[Image.Image] = None,
|
|
63
|
+
update_streamlit: bool = True,
|
|
64
|
+
height: int = 400,
|
|
65
|
+
width: int = 600,
|
|
66
|
+
drawing_mode: str = "freedraw",
|
|
67
|
+
initial_drawing: Optional[dict] = None,
|
|
68
|
+
display_toolbar: bool = True,
|
|
69
|
+
point_display_radius: int = 3,
|
|
70
|
+
key: Optional[str] = None,
|
|
71
|
+
) -> CanvasResult:
|
|
72
|
+
"""Create a Konva drawing canvas in a Streamlit app.
|
|
73
|
+
|
|
74
|
+
Compatible with the core API of ``streamlit-drawable-canvas`` /
|
|
75
|
+
``streamlit-drawable-canvas-fix``, implemented on Streamlit Components v2.
|
|
76
|
+
|
|
77
|
+
Parameters
|
|
78
|
+
----------
|
|
79
|
+
fill_color:
|
|
80
|
+
Fill color for shapes (CSS color). Defaults to ``"#eee"``.
|
|
81
|
+
stroke_width:
|
|
82
|
+
Stroke / brush width in pixels. Defaults to ``20``.
|
|
83
|
+
stroke_color:
|
|
84
|
+
Stroke color. Defaults to ``"black"``.
|
|
85
|
+
background_color:
|
|
86
|
+
Canvas background color. Empty string means transparent.
|
|
87
|
+
Overridden by ``background_image``. Changing this resets the drawing.
|
|
88
|
+
background_image:
|
|
89
|
+
Pillow image displayed behind drawings (resized to canvas size).
|
|
90
|
+
Not included in returned ``image_data``.
|
|
91
|
+
update_streamlit:
|
|
92
|
+
When True, send canvas data to Streamlit on mouse-up / object updates.
|
|
93
|
+
height:
|
|
94
|
+
Canvas height in pixels. Defaults to ``400``.
|
|
95
|
+
width:
|
|
96
|
+
Canvas width in pixels. Defaults to ``600``.
|
|
97
|
+
drawing_mode:
|
|
98
|
+
One of ``freedraw``, ``transform``, ``line``, ``rect``, ``circle``,
|
|
99
|
+
``point``, ``polygon``. Defaults to ``freedraw``.
|
|
100
|
+
initial_drawing:
|
|
101
|
+
JSON scene to load (typically a previous ``json_data``).
|
|
102
|
+
display_toolbar:
|
|
103
|
+
Show undo / redo / clear toolbar.
|
|
104
|
+
point_display_radius:
|
|
105
|
+
Radius used when drawing points as circles.
|
|
106
|
+
key:
|
|
107
|
+
Optional Streamlit widget key.
|
|
108
|
+
|
|
109
|
+
Returns
|
|
110
|
+
-------
|
|
111
|
+
CanvasResult
|
|
112
|
+
``image_data`` is an RGBA NumPy array; ``json_data`` is the scene dict.
|
|
113
|
+
"""
|
|
114
|
+
background_image_url: Optional[str] = None
|
|
115
|
+
bg_color = background_color
|
|
116
|
+
if background_image is not None:
|
|
117
|
+
resized = _resize_img(background_image, height, width)
|
|
118
|
+
background_image_url = _image_to_data_url(resized)
|
|
119
|
+
bg_color = ""
|
|
120
|
+
|
|
121
|
+
scene: dict[str, Any] = (
|
|
122
|
+
{"version": "konva-1", "objects": []}
|
|
123
|
+
if initial_drawing is None
|
|
124
|
+
else dict(initial_drawing)
|
|
125
|
+
)
|
|
126
|
+
scene["background"] = bg_color
|
|
127
|
+
|
|
128
|
+
toolbar_h = 40 if display_toolbar else 0
|
|
129
|
+
component_height = height + toolbar_h + 8
|
|
130
|
+
|
|
131
|
+
raw = _COMPONENT(
|
|
132
|
+
key=key,
|
|
133
|
+
data={
|
|
134
|
+
"fillColor": fill_color,
|
|
135
|
+
"strokeWidth": stroke_width,
|
|
136
|
+
"strokeColor": stroke_color,
|
|
137
|
+
"backgroundColor": bg_color,
|
|
138
|
+
"backgroundImageURL": background_image_url,
|
|
139
|
+
"realtimeUpdateStreamlit": update_streamlit
|
|
140
|
+
and (drawing_mode != "polygon"),
|
|
141
|
+
"canvasHeight": height,
|
|
142
|
+
"canvasWidth": width,
|
|
143
|
+
"drawingMode": drawing_mode,
|
|
144
|
+
"initialDrawing": scene,
|
|
145
|
+
"displayToolbar": display_toolbar,
|
|
146
|
+
"displayRadius": point_display_radius,
|
|
147
|
+
},
|
|
148
|
+
default={"image_data_url": None, "json_data": None},
|
|
149
|
+
on_image_data_url_change=_noop,
|
|
150
|
+
on_json_data_change=_noop,
|
|
151
|
+
height=component_height,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
image_data_url = getattr(raw, "image_data_url", None)
|
|
155
|
+
json_data = getattr(raw, "json_data", None)
|
|
156
|
+
|
|
157
|
+
if image_data_url is None:
|
|
158
|
+
return CanvasResult(image_data=None, json_data=json_data)
|
|
159
|
+
|
|
160
|
+
return CanvasResult(
|
|
161
|
+
image_data=np.asarray(_data_url_to_image(image_data_url)),
|
|
162
|
+
json_data=json_data,
|
|
163
|
+
)
|