reflex-rosencharts 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.
- reflex_rosencharts-0.1.0/.gitignore +19 -0
- reflex_rosencharts-0.1.0/CONTRIBUTING.md +84 -0
- reflex_rosencharts-0.1.0/LICENSE +22 -0
- reflex_rosencharts-0.1.0/NOTICE +9 -0
- reflex_rosencharts-0.1.0/PKG-INFO +100 -0
- reflex_rosencharts-0.1.0/README.md +73 -0
- reflex_rosencharts-0.1.0/pyproject.toml +57 -0
- reflex_rosencharts-0.1.0/reference/rosencharts/README.md +31 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/__init__.py +30 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/__init__.py +5 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/area/__init__.py +13 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/area/area_chart.py +110 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/area/area_chart.tsx +242 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/area/area_chart_full.py +106 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/area/area_chart_full.tsx +213 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/area/area_chart_gradient.py +112 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/area/area_chart_gradient.tsx +222 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/area/area_chart_semi_filled.py +113 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/area/area_chart_semi_filled.tsx +224 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/area/gallery.py +63 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/__init__.py +29 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_benchmark.py +65 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_benchmark.tsx +75 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_breakdown.py +81 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_breakdown.tsx +129 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_flags_horizontal.py +64 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_flags_horizontal.tsx +146 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_gradient.py +70 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_gradient.tsx +141 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_horizontal.py +69 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_horizontal.tsx +146 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_horizontal_logo.py +70 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_horizontal_logo.tsx +252 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_line.py +73 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_line.tsx +227 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_multi_vertical.py +80 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_multi_vertical.tsx +189 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_thin_breakdown.py +81 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_thin_breakdown.tsx +109 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_thin_horizontal.py +79 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_thin_horizontal.tsx +201 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_triple_flags_horizontal.py +70 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_triple_flags_horizontal.tsx +181 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_vertical.py +71 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/bar_chart_vertical.tsx +160 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/bar/gallery.py +168 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/helpers/ClientTooltip.tsx +167 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/helpers/__init__.py +1 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/helpers/client_tooltip.py +17 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/line/__init__.py +21 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/line/gallery.py +113 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/line/line_chart.py +78 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/line/line_chart.tsx +226 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/line/line_chart_curved.py +74 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/line/line_chart_curved.tsx +226 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/line/line_chart_full.py +81 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/line/line_chart_full.tsx +155 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/line/line_chart_labels_curved.py +71 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/line/line_chart_labels_curved.tsx +162 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/line/line_chart_multiple.py +91 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/line/line_chart_multiple.tsx +268 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/line/line_chart_pulse.py +71 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/line/line_chart_pulse.tsx +231 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/line/line_chart_step.py +70 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/line/line_chart_step.tsx +220 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/line/line_chart_stocks_curved.py +72 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/line/line_chart_stocks_curved.tsx +291 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/other/__init__.py +6 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/other/bubble_chart.py +93 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/other/bubble_chart.tsx +125 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/other/funnel_chart.py +81 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/other/funnel_chart.tsx +108 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/other/gallery.py +33 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/pie/__init__.py +21 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/pie/donut_chart.py +70 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/pie/donut_chart.tsx +122 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/pie/donut_chart_center_text.py +77 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/pie/donut_chart_center_text.tsx +135 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/pie/donut_chart_fillable.py +43 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/pie/donut_chart_fillable.tsx +83 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/pie/donut_chart_fillable_half.py +43 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/pie/donut_chart_fillable_half.tsx +95 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/pie/donut_chart_half.py +67 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/pie/donut_chart_half.tsx +115 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/pie/gallery.py +121 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/pie/pie_chart.py +77 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/pie/pie_chart.tsx +88 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/pie/pie_chart_labels.py +76 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/pie/pie_chart_labels.tsx +135 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/pie/pie_chart_stocks.py +101 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/pie/pie_chart_stocks.tsx +166 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/radar/__init__.py +6 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/radar/gallery.py +32 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/radar/radar_chart.py +65 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/radar/radar_chart.tsx +91 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/radar/radar_chart_rounded.py +66 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/radar/radar_chart_rounded.tsx +116 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/scatter/__init__.py +13 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/scatter/gallery.py +61 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/scatter/scatter_chart.py +84 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/scatter/scatter_chart.tsx +227 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/scatter/scatter_chart_interactive.py +87 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/scatter/scatter_chart_interactive.tsx +208 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/scatter/scatter_chart_multiclass.py +89 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/scatter/scatter_chart_multiclass.tsx +206 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/scatter/scatter_chart_stocks.py +73 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/scatter/scatter_chart_stocks.tsx +295 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/treemap/__init__.py +7 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/treemap/gallery.py +48 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/treemap/treemap_chart.py +80 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/treemap/treemap_chart.tsx +110 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/treemap/treemap_chart_gradient.py +108 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/treemap/treemap_chart_gradient.tsx +157 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/treemap/treemap_chart_images.py +111 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/components/treemap/treemap_chart_images.tsx +200 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/gallery/__init__.py +5 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/gallery/registry.py +55 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/py.typed +0 -0
- reflex_rosencharts-0.1.0/reflex_rosencharts/reflex_rosencharts.py +125 -0
- reflex_rosencharts-0.1.0/specs/README.md +33 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Contribuir — Receta de port (rosencharts → Reflex)
|
|
2
|
+
|
|
3
|
+
Patrón **probado** (validado end-to-end con el piloto `line_chart`, compila con
|
|
4
|
+
`reflex export`). Detalle de diseño en
|
|
5
|
+
[`specs/technical/architecture.md`](specs/technical/architecture.md) §5.2.
|
|
6
|
+
|
|
7
|
+
## Layout de assets (importante)
|
|
8
|
+
|
|
9
|
+
`rx.asset("x.tsx", shared=True)` copia el archivo a
|
|
10
|
+
`public/external/<módulo_python_punteado_como_dirs>/x.tsx`. Es decir, el módulo
|
|
11
|
+
`reflex_rosencharts.components.line.line_chart` deja su TSX en
|
|
12
|
+
`external/reflex_rosencharts/components/line/line_chart/line_chart.tsx`.
|
|
13
|
+
|
|
14
|
+
Como **toda** gráfica vive en `components/<familia>/<name>.py` (asset = `<name>.tsx`),
|
|
15
|
+
su TSX queda en `.../components/<familia>/<name>/<name>.tsx`, y el helper compartido
|
|
16
|
+
en `.../components/helpers/client_tooltip/ClientTooltip.tsx`. Por eso la ruta relativa
|
|
17
|
+
al helper es **constante para todas las gráficas**:
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import { ClientTooltip, TooltipTrigger, TooltipContent } from "../../helpers/client_tooltip/ClientTooltip";
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Pasos por gráfica (TDD)
|
|
24
|
+
|
|
25
|
+
1. **RED** — `tests/test_<familia>.py`: la función existe, es importable, `.create(data=...)`
|
|
26
|
+
construye un `rx.Component`, y el default reproduce el ejemplo. Corre el test y velo fallar.
|
|
27
|
+
2. **Copiar** `reference/rosencharts/<familia>-charts/<n>_<Name>.tsx`
|
|
28
|
+
→ `reflex_rosencharts/components/<familia>/<name>.tsx`.
|
|
29
|
+
3. **Parametrizar datos**: sustituir el array hardcodeado por una prop con default = ejemplo:
|
|
30
|
+
```tsx
|
|
31
|
+
const defaultData = [ ...ejemplo original... ];
|
|
32
|
+
export function ChartName({ data = defaultData, color = "..." }: {...}) {
|
|
33
|
+
if (data.length === 0) return <div className="relative h-72 w-full" />;
|
|
34
|
+
// ... mapear/escalas a partir de `data`
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
4. **Ajustar import del helper** (sólo si usa tooltip) a la ruta constante de arriba.
|
|
38
|
+
5. **Wrapper Python** (`<name>.py`):
|
|
39
|
+
```python
|
|
40
|
+
from typing import TypedDict
|
|
41
|
+
import reflex as rx
|
|
42
|
+
from ..helpers.client_tooltip import client_tooltip_asset # sólo si usa tooltip
|
|
43
|
+
|
|
44
|
+
class LinePoint(TypedDict):
|
|
45
|
+
date: str
|
|
46
|
+
value: float
|
|
47
|
+
|
|
48
|
+
_DEFAULT_DATA: list[LinePoint] = [ ...ejemplo... ]
|
|
49
|
+
|
|
50
|
+
client_tooltip_asset() # sólo si usa tooltip (lo hace viajar)
|
|
51
|
+
_PATH = rx.asset("line_chart.tsx", shared=True)
|
|
52
|
+
|
|
53
|
+
class LineChart(rx.NoSSRComponent): # NoSSRComponent si usa portal/tooltip; rx.Component si no
|
|
54
|
+
library = f"$/public{_PATH}"
|
|
55
|
+
tag = "LineChart" # == nombre exportado en el TSX
|
|
56
|
+
is_default = False
|
|
57
|
+
lib_dependencies: list[str] = ["d3"] # si el TSX importa de "d3"
|
|
58
|
+
data: rx.Var[list[LinePoint]] = rx.Var.create(_DEFAULT_DATA)
|
|
59
|
+
color: rx.Var[str] = rx.Var.create("stroke-fuchsia-400")
|
|
60
|
+
|
|
61
|
+
def line_chart(**props) -> rx.Component:
|
|
62
|
+
return LineChart.create(**props)
|
|
63
|
+
```
|
|
64
|
+
6. **Re-exportar** en `components/<familia>/__init__.py` y en `reflex_rosencharts/__init__.py`.
|
|
65
|
+
7. **Entrada de galería** en `components/<familia>/gallery.py` (lista `GALLERY_ENTRIES`); el
|
|
66
|
+
registry central la recoge sin tocar archivos compartidos.
|
|
67
|
+
8. **GREEN** — corre el test y velo pasar. Refactor manteniendo verde. Commit.
|
|
68
|
+
|
|
69
|
+
## Reglas
|
|
70
|
+
|
|
71
|
+
- Nombre Python en `snake_case`; quitar sufijo `_DIV` (técnica de render, va en el docstring).
|
|
72
|
+
- `tag` debe coincidir EXACTAMENTE con el nombre `export function <Tag>` del TSX.
|
|
73
|
+
- `data` vacío ⇒ render de contenedor vacío, nunca lanzar excepción.
|
|
74
|
+
- Conservar variantes `dark:` de Tailwind.
|
|
75
|
+
- Cada variante con campos extra define su propio `TypedDict` (ver Data Model §4).
|
|
76
|
+
- Gráficas SIN tooltip: usar `rx.Component` (no NoSSR) y omitir `client_tooltip_asset()`.
|
|
77
|
+
|
|
78
|
+
## Definición de Done (por gráfica)
|
|
79
|
+
|
|
80
|
+
- [ ] Test TDD verde (import + render + default)
|
|
81
|
+
- [ ] Wrapper + TSX parametrizado + re-export en ambos `__init__`
|
|
82
|
+
- [ ] Entrada en `components/<familia>/gallery.py`
|
|
83
|
+
- [ ] Compila en `reflex export`
|
|
84
|
+
- [ ] Docstring con esquema de datos y snippet
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Filipe Sommer (original rosencharts)
|
|
4
|
+
Copyright (c) 2026 Ernesto Crespo (reflex-rosencharts port)
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
reflex-rosencharts
|
|
2
|
+
==================
|
|
3
|
+
|
|
4
|
+
Este proyecto es un port a Reflex de "rosencharts":
|
|
5
|
+
https://github.com/Filsommer/rosenCharts
|
|
6
|
+
Copyright (c) Filsommer — Licencia MIT
|
|
7
|
+
|
|
8
|
+
El código original (TSX) se conserva como referencia en reference/rosencharts/
|
|
9
|
+
bajo su licencia MIT original. Las adaptaciones a Reflex se distribuyen bajo MIT.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: reflex-rosencharts
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: rosencharts charts (D3 + Tailwind) ported to Reflex as Python components — 43 charts, no JS required.
|
|
5
|
+
Project-URL: Homepage, https://github.com/ecrespo/reflex-rosencharts
|
|
6
|
+
Project-URL: Source, https://github.com/ecrespo/reflex-rosencharts
|
|
7
|
+
Project-URL: Issues, https://github.com/ecrespo/reflex-rosencharts/issues
|
|
8
|
+
Author-email: Ernesto Crespo <ecrespo@gmail.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
License-File: NOTICE
|
|
12
|
+
Keywords: charts,components,d3,dataviz,reflex,rosencharts,tailwind,visualization
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Requires-Dist: reflex>=0.9.5.post2
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# reflex-rosencharts
|
|
29
|
+
|
|
30
|
+
Port de la librería de gráficas [**rosencharts**](https://github.com/Filsommer/rosenCharts)
|
|
31
|
+
(43 componentes React/TSX con D3.js + Tailwind) a un **custom component de
|
|
32
|
+
[Reflex](https://reflex.dev/)**, para usar las gráficas desde Python puro.
|
|
33
|
+
|
|
34
|
+
> Estado: **43/43 gráficas implementadas** ✅ — todas con wrapper Python, TSX parametrizado,
|
|
35
|
+
> ejemplo en la galería y tests. La app demo (`reflex run`) muestra las 43 con su snippet de uso.
|
|
36
|
+
> Capturas en [`docs/screenshots/`](docs/screenshots/).
|
|
37
|
+
|
|
38
|
+
## ¿Por qué?
|
|
39
|
+
|
|
40
|
+
rosencharts no es un paquete npm: son componentes `.tsx` para copiar y pegar, con datos
|
|
41
|
+
hardcodeados y estilo Tailwind. Este proyecto los envuelve como **componentes locales de Reflex**
|
|
42
|
+
(`rx.asset` + `library="$/public..."`), los parametriza para recibir datos desde `rx.State`, y los
|
|
43
|
+
expone como funciones Python:
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
import reflex as rx
|
|
47
|
+
import reflex_rosencharts as rxc
|
|
48
|
+
|
|
49
|
+
class State(rx.State):
|
|
50
|
+
sales: list[dict] = [{"date": "2023-05-01", "value": 6}, {"date": "2023-05-02", "value": 8}]
|
|
51
|
+
|
|
52
|
+
def index() -> rx.Component:
|
|
53
|
+
return rxc.line_chart(data=State.sales)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Gráficas (43 en 8 familias)
|
|
57
|
+
|
|
58
|
+
| Familia | Nº | Ejemplos |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| Area | 4 | `area_chart`, `area_chart_gradient` |
|
|
61
|
+
| Bar | 12 | `bar_chart_horizontal`, `bar_chart_benchmark` |
|
|
62
|
+
| Line | 8 | `line_chart`, `line_chart_multiple` |
|
|
63
|
+
| Pie/Donut | 8 | `pie_chart`, `donut_chart_center_text` |
|
|
64
|
+
| Scatter | 4 | `scatter_chart`, `scatter_chart_interactive` |
|
|
65
|
+
| Treemap | 3 | `treemap_chart`, `treemap_chart_images` |
|
|
66
|
+
| Radar | 2 | `radar_chart`, `radar_chart_rounded` |
|
|
67
|
+
| Other | 2 | `bubble_chart`, `funnel_chart` |
|
|
68
|
+
|
|
69
|
+
Catálogo completo y props: [`specs/api/component-api-v1.md`](specs/api/component-api-v1.md).
|
|
70
|
+
|
|
71
|
+
## Desarrollo
|
|
72
|
+
|
|
73
|
+
Gestionado con [uv](https://docs.astral.sh/uv/):
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
uv sync # instalar dependencias
|
|
77
|
+
uv run reflex run # arrancar la demo app / galería (las 43 gráficas)
|
|
78
|
+
uv run pytest # tests de los wrappers (TDD)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
La **galería demo** vive en `reflex_rosencharts/reflex_rosencharts.py`: barra lateral por familia
|
|
82
|
+
y una tarjeta por gráfica (gráfica renderizada con datos de ejemplo + snippet Python). Es el banco
|
|
83
|
+
de pruebas visual del port.
|
|
84
|
+
|
|
85
|
+
## Especificaciones (SDD)
|
|
86
|
+
|
|
87
|
+
El proyecto sigue **Spec-Driven Design**. Las specs son el artefacto primario:
|
|
88
|
+
|
|
89
|
+
- [PRD](specs/prd/reflex-rosencharts-prd.md) — el qué y el para quién
|
|
90
|
+
- [API Spec](specs/api/component-api-v1.md) — API pública Python (funciones, props)
|
|
91
|
+
- [Technical Design](specs/technical/architecture.md) — patrón de wrapping y arquitectura
|
|
92
|
+
- [Data Model](specs/data-model/chart-data-schemas.md) — esquemas de datos por gráfica
|
|
93
|
+
- [Implementation Plan](specs/plans/implementation-plan.md) — fases por familia
|
|
94
|
+
|
|
95
|
+
El código original (referencia, solo lectura) está en [`reference/rosencharts/`](reference/rosencharts/).
|
|
96
|
+
|
|
97
|
+
## Licencia y atribución
|
|
98
|
+
|
|
99
|
+
MIT. Este proyecto es un port de [rosencharts](https://github.com/Filsommer/rosenCharts)
|
|
100
|
+
de Filsommer (MIT). Ver [`LICENSE`](LICENSE) y [`NOTICE`](NOTICE).
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# reflex-rosencharts
|
|
2
|
+
|
|
3
|
+
Port de la librería de gráficas [**rosencharts**](https://github.com/Filsommer/rosenCharts)
|
|
4
|
+
(43 componentes React/TSX con D3.js + Tailwind) a un **custom component de
|
|
5
|
+
[Reflex](https://reflex.dev/)**, para usar las gráficas desde Python puro.
|
|
6
|
+
|
|
7
|
+
> Estado: **43/43 gráficas implementadas** ✅ — todas con wrapper Python, TSX parametrizado,
|
|
8
|
+
> ejemplo en la galería y tests. La app demo (`reflex run`) muestra las 43 con su snippet de uso.
|
|
9
|
+
> Capturas en [`docs/screenshots/`](docs/screenshots/).
|
|
10
|
+
|
|
11
|
+
## ¿Por qué?
|
|
12
|
+
|
|
13
|
+
rosencharts no es un paquete npm: son componentes `.tsx` para copiar y pegar, con datos
|
|
14
|
+
hardcodeados y estilo Tailwind. Este proyecto los envuelve como **componentes locales de Reflex**
|
|
15
|
+
(`rx.asset` + `library="$/public..."`), los parametriza para recibir datos desde `rx.State`, y los
|
|
16
|
+
expone como funciones Python:
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
import reflex as rx
|
|
20
|
+
import reflex_rosencharts as rxc
|
|
21
|
+
|
|
22
|
+
class State(rx.State):
|
|
23
|
+
sales: list[dict] = [{"date": "2023-05-01", "value": 6}, {"date": "2023-05-02", "value": 8}]
|
|
24
|
+
|
|
25
|
+
def index() -> rx.Component:
|
|
26
|
+
return rxc.line_chart(data=State.sales)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Gráficas (43 en 8 familias)
|
|
30
|
+
|
|
31
|
+
| Familia | Nº | Ejemplos |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| Area | 4 | `area_chart`, `area_chart_gradient` |
|
|
34
|
+
| Bar | 12 | `bar_chart_horizontal`, `bar_chart_benchmark` |
|
|
35
|
+
| Line | 8 | `line_chart`, `line_chart_multiple` |
|
|
36
|
+
| Pie/Donut | 8 | `pie_chart`, `donut_chart_center_text` |
|
|
37
|
+
| Scatter | 4 | `scatter_chart`, `scatter_chart_interactive` |
|
|
38
|
+
| Treemap | 3 | `treemap_chart`, `treemap_chart_images` |
|
|
39
|
+
| Radar | 2 | `radar_chart`, `radar_chart_rounded` |
|
|
40
|
+
| Other | 2 | `bubble_chart`, `funnel_chart` |
|
|
41
|
+
|
|
42
|
+
Catálogo completo y props: [`specs/api/component-api-v1.md`](specs/api/component-api-v1.md).
|
|
43
|
+
|
|
44
|
+
## Desarrollo
|
|
45
|
+
|
|
46
|
+
Gestionado con [uv](https://docs.astral.sh/uv/):
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
uv sync # instalar dependencias
|
|
50
|
+
uv run reflex run # arrancar la demo app / galería (las 43 gráficas)
|
|
51
|
+
uv run pytest # tests de los wrappers (TDD)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
La **galería demo** vive en `reflex_rosencharts/reflex_rosencharts.py`: barra lateral por familia
|
|
55
|
+
y una tarjeta por gráfica (gráfica renderizada con datos de ejemplo + snippet Python). Es el banco
|
|
56
|
+
de pruebas visual del port.
|
|
57
|
+
|
|
58
|
+
## Especificaciones (SDD)
|
|
59
|
+
|
|
60
|
+
El proyecto sigue **Spec-Driven Design**. Las specs son el artefacto primario:
|
|
61
|
+
|
|
62
|
+
- [PRD](specs/prd/reflex-rosencharts-prd.md) — el qué y el para quién
|
|
63
|
+
- [API Spec](specs/api/component-api-v1.md) — API pública Python (funciones, props)
|
|
64
|
+
- [Technical Design](specs/technical/architecture.md) — patrón de wrapping y arquitectura
|
|
65
|
+
- [Data Model](specs/data-model/chart-data-schemas.md) — esquemas de datos por gráfica
|
|
66
|
+
- [Implementation Plan](specs/plans/implementation-plan.md) — fases por familia
|
|
67
|
+
|
|
68
|
+
El código original (referencia, solo lectura) está en [`reference/rosencharts/`](reference/rosencharts/).
|
|
69
|
+
|
|
70
|
+
## Licencia y atribución
|
|
71
|
+
|
|
72
|
+
MIT. Este proyecto es un port de [rosencharts](https://github.com/Filsommer/rosenCharts)
|
|
73
|
+
de Filsommer (MIT). Ver [`LICENSE`](LICENSE) y [`NOTICE`](NOTICE).
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "reflex-rosencharts"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "rosencharts charts (D3 + Tailwind) ported to Reflex as Python components — 43 charts, no JS required."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE", "NOTICE"]
|
|
8
|
+
requires-python = ">=3.10"
|
|
9
|
+
authors = [{ name = "Ernesto Crespo", email = "ecrespo@gmail.com" }]
|
|
10
|
+
keywords = ["reflex", "charts", "d3", "tailwind", "dataviz", "visualization", "rosencharts", "components"]
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Development Status :: 4 - Beta",
|
|
13
|
+
"Intended Audience :: Developers",
|
|
14
|
+
"Operating System :: OS Independent",
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Programming Language :: Python :: 3.10",
|
|
17
|
+
"Programming Language :: Python :: 3.11",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
20
|
+
"Topic :: Scientific/Engineering :: Visualization",
|
|
21
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
22
|
+
"Typing :: Typed",
|
|
23
|
+
]
|
|
24
|
+
dependencies = [
|
|
25
|
+
"reflex>=0.9.5.post2",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://github.com/ecrespo/reflex-rosencharts"
|
|
30
|
+
Source = "https://github.com/ecrespo/reflex-rosencharts"
|
|
31
|
+
Issues = "https://github.com/ecrespo/reflex-rosencharts/issues"
|
|
32
|
+
|
|
33
|
+
[dependency-groups]
|
|
34
|
+
dev = [
|
|
35
|
+
"playwright>=1.60.0",
|
|
36
|
+
"pytest>=9.1.0",
|
|
37
|
+
"pytest-cov>=7.1.0",
|
|
38
|
+
"twine>=5.0.0",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[build-system]
|
|
42
|
+
requires = ["hatchling"]
|
|
43
|
+
build-backend = "hatchling.build"
|
|
44
|
+
|
|
45
|
+
[tool.hatch.build.targets.wheel]
|
|
46
|
+
# Ship the Python wrappers AND the parametrized .tsx assets they wrap.
|
|
47
|
+
packages = ["reflex_rosencharts"]
|
|
48
|
+
artifacts = ["*.tsx"]
|
|
49
|
+
|
|
50
|
+
[tool.hatch.build.targets.sdist]
|
|
51
|
+
include = [
|
|
52
|
+
"reflex_rosencharts",
|
|
53
|
+
"README.md",
|
|
54
|
+
"LICENSE",
|
|
55
|
+
"NOTICE",
|
|
56
|
+
"CONTRIBUTING.md",
|
|
57
|
+
]
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Rosen - A React Charting Library
|
|
2
|
+
|
|
3
|
+
A lightweight and easy-to-use charting library built with D3.js and Tailwind. Just copy-paste the code and install the required dependencies to get started!
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
First, install D3.js by running:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install d3
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
If you're using TypeScript, install the D3 types as well:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm install --save-dev @types/d3
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
Simply copy and paste the provided charting code into your project and ensure that D3.js is installed.
|
|
22
|
+
|
|
23
|
+
## Features
|
|
24
|
+
|
|
25
|
+
- Simple copy-paste integration
|
|
26
|
+
- Uses D3.js for powerful and flexible charting
|
|
27
|
+
- Works with JavaScript and TypeScript
|
|
28
|
+
|
|
29
|
+
## License
|
|
30
|
+
|
|
31
|
+
MIT
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""reflex-rosencharts: port de rosencharts a componentes de Reflex.
|
|
2
|
+
|
|
3
|
+
API pública (a poblar durante la implementación, ver specs/api/component-api-v1.md):
|
|
4
|
+
import reflex_rosencharts as rxc
|
|
5
|
+
rxc.line_chart(data=...)
|
|
6
|
+
|
|
7
|
+
Por ahora el paquete expone el scaffold y la demo app. Las funciones de gráfica
|
|
8
|
+
se irán re-exportando aquí a medida que se porten (fases F1-F7 del plan).
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
__version__ = "0.1.0"
|
|
12
|
+
|
|
13
|
+
# Public API — aggregated dynamically from each family package so that charts can be
|
|
14
|
+
# ported in parallel without ever editing this shared file. Each family's __init__
|
|
15
|
+
# declares __all__; we lift those names into the package namespace.
|
|
16
|
+
import importlib as _importlib # noqa: E402
|
|
17
|
+
|
|
18
|
+
_FAMILIES = ["line", "area", "bar", "pie", "scatter", "treemap", "radar", "other"]
|
|
19
|
+
__all__: list[str] = []
|
|
20
|
+
|
|
21
|
+
for _family in _FAMILIES:
|
|
22
|
+
try:
|
|
23
|
+
_mod = _importlib.import_module(f".components.{_family}", __name__)
|
|
24
|
+
except ModuleNotFoundError:
|
|
25
|
+
continue
|
|
26
|
+
for _name in getattr(_mod, "__all__", []):
|
|
27
|
+
globals()[_name] = getattr(_mod, _name)
|
|
28
|
+
__all__.append(_name)
|
|
29
|
+
|
|
30
|
+
del _importlib, _family, _FAMILIES
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Componentes rosencharts: familia area."""
|
|
2
|
+
|
|
3
|
+
from .area_chart import area_chart
|
|
4
|
+
from .area_chart_full import area_chart_full
|
|
5
|
+
from .area_chart_gradient import area_chart_gradient
|
|
6
|
+
from .area_chart_semi_filled import area_chart_semi_filled
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"area_chart",
|
|
10
|
+
"area_chart_full",
|
|
11
|
+
"area_chart_gradient",
|
|
12
|
+
"area_chart_semi_filled",
|
|
13
|
+
]
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""area_chart — port of rosencharts area-charts/1_AreaChart.tsx to Reflex.
|
|
2
|
+
|
|
3
|
+
Render technique: D3 ``scaleTime``/``scaleLinear`` with ``d3.area`` + ``d3.line``
|
|
4
|
+
(curveMonotoneX), styled with Tailwind. Uses the shared ClientTooltip helper
|
|
5
|
+
(createPortal), so the component renders client-side only (NoSSRComponent).
|
|
6
|
+
|
|
7
|
+
Data schema (``AreaPoint``)::
|
|
8
|
+
|
|
9
|
+
{"date": "YYYY-MM-DD", "value": float}
|
|
10
|
+
|
|
11
|
+
Example::
|
|
12
|
+
|
|
13
|
+
import reflex_rosencharts as rxc
|
|
14
|
+
rxc.area_chart(data=State.sales, color="text-purple-200 dark:text-purple-400")
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from typing import TypedDict
|
|
18
|
+
|
|
19
|
+
import reflex as rx
|
|
20
|
+
|
|
21
|
+
from ..helpers.client_tooltip import client_tooltip_asset
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class AreaPoint(TypedDict):
|
|
25
|
+
"""A single point of a time series."""
|
|
26
|
+
|
|
27
|
+
date: str # ISO date 'YYYY-MM-DD'
|
|
28
|
+
value: float
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# Default dataset == the original rosencharts example, so ``area_chart()`` with no
|
|
32
|
+
# args reproduces the reference chart (Tech Design DD-002).
|
|
33
|
+
_DEFAULT_DATA: list[AreaPoint] = [
|
|
34
|
+
{"date": "2023-04-30", "value": 4},
|
|
35
|
+
{"date": "2023-05-01", "value": 6},
|
|
36
|
+
{"date": "2023-05-02", "value": 8},
|
|
37
|
+
{"date": "2023-05-03", "value": 7},
|
|
38
|
+
{"date": "2023-05-04", "value": 10},
|
|
39
|
+
{"date": "2023-05-05", "value": 12},
|
|
40
|
+
{"date": "2023-05-06", "value": 10.5},
|
|
41
|
+
{"date": "2023-05-07", "value": 6},
|
|
42
|
+
{"date": "2023-05-08", "value": 8},
|
|
43
|
+
{"date": "2023-05-09", "value": 7.5},
|
|
44
|
+
{"date": "2023-05-10", "value": 6},
|
|
45
|
+
{"date": "2023-05-11", "value": 8},
|
|
46
|
+
{"date": "2023-05-12", "value": 9},
|
|
47
|
+
{"date": "2023-05-13", "value": 10},
|
|
48
|
+
{"date": "2023-05-14", "value": 17},
|
|
49
|
+
{"date": "2023-05-15", "value": 14},
|
|
50
|
+
{"date": "2023-05-16", "value": 15},
|
|
51
|
+
{"date": "2023-05-17", "value": 20},
|
|
52
|
+
{"date": "2023-05-18", "value": 18},
|
|
53
|
+
{"date": "2023-05-19", "value": 16},
|
|
54
|
+
{"date": "2023-05-20", "value": 15},
|
|
55
|
+
{"date": "2023-05-21", "value": 16},
|
|
56
|
+
{"date": "2023-05-22", "value": 13},
|
|
57
|
+
{"date": "2023-05-23", "value": 11},
|
|
58
|
+
{"date": "2023-05-24", "value": 11},
|
|
59
|
+
{"date": "2023-05-25", "value": 13},
|
|
60
|
+
{"date": "2023-05-26", "value": 12},
|
|
61
|
+
{"date": "2023-05-27", "value": 9},
|
|
62
|
+
{"date": "2023-05-28", "value": 8},
|
|
63
|
+
{"date": "2023-05-29", "value": 10},
|
|
64
|
+
{"date": "2023-05-30", "value": 11},
|
|
65
|
+
{"date": "2023-05-31", "value": 8},
|
|
66
|
+
{"date": "2023-06-01", "value": 9},
|
|
67
|
+
{"date": "2023-06-02", "value": 10},
|
|
68
|
+
{"date": "2023-06-03", "value": 12},
|
|
69
|
+
{"date": "2023-06-04", "value": 13},
|
|
70
|
+
{"date": "2023-06-05", "value": 15},
|
|
71
|
+
{"date": "2023-06-06", "value": 13.5},
|
|
72
|
+
{"date": "2023-06-07", "value": 13},
|
|
73
|
+
{"date": "2023-06-08", "value": 13},
|
|
74
|
+
{"date": "2023-06-09", "value": 14},
|
|
75
|
+
{"date": "2023-06-10", "value": 13},
|
|
76
|
+
{"date": "2023-06-11", "value": 12.5},
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
# Ship the shared helper next to this chart so the TSX's relative import resolves.
|
|
80
|
+
client_tooltip_asset()
|
|
81
|
+
_PATH = rx.asset("area_chart.tsx", shared=True)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class AreaChart(rx.NoSSRComponent):
|
|
85
|
+
"""Reflex wrapper around the parametrized AreaChart TSX."""
|
|
86
|
+
|
|
87
|
+
library = f"$/public{_PATH}"
|
|
88
|
+
tag = "AreaChart"
|
|
89
|
+
is_default = False
|
|
90
|
+
|
|
91
|
+
lib_dependencies: list[str] = ["d3"]
|
|
92
|
+
|
|
93
|
+
# Props
|
|
94
|
+
data: rx.Var[list[AreaPoint]] = rx.Var.create(_DEFAULT_DATA)
|
|
95
|
+
color: rx.Var[str] = rx.Var.create("text-purple-200 dark:text-purple-400")
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def area_chart(**props) -> rx.Component:
|
|
99
|
+
"""Filled area chart over a time series, with a per-point tooltip.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
data: list of ``{"date": "YYYY-MM-DD", "value": float}``. Defaults to the
|
|
103
|
+
original rosencharts example.
|
|
104
|
+
color: Tailwind ``text-*`` class for the filled area. Defaults to
|
|
105
|
+
``"text-purple-200 dark:text-purple-400"``.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
A Reflex component rendering the area chart.
|
|
109
|
+
"""
|
|
110
|
+
return AreaChart.create(**props)
|