reflex-silverpoint-react 0.1.0__tar.gz → 0.3.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_silverpoint_react-0.3.0/PKG-INFO +379 -0
- reflex_silverpoint_react-0.3.0/README.md +353 -0
- {reflex_silverpoint_react-0.1.0 → reflex_silverpoint_react-0.3.0}/custom_components/reflex_silverpoint_react/__init__.py +125 -2
- {reflex_silverpoint_react-0.1.0 → reflex_silverpoint_react-0.3.0}/custom_components/reflex_silverpoint_react/base.py +16 -9
- {reflex_silverpoint_react-0.1.0 → reflex_silverpoint_react-0.3.0}/custom_components/reflex_silverpoint_react/base.pyi +86 -82
- {reflex_silverpoint_react-0.1.0 → reflex_silverpoint_react-0.3.0}/custom_components/reflex_silverpoint_react/catalog.py +12 -2
- {reflex_silverpoint_react-0.1.0 → reflex_silverpoint_react-0.3.0}/custom_components/reflex_silverpoint_react/charts.pyi +1000 -932
- reflex_silverpoint_react-0.3.0/custom_components/reflex_silverpoint_react/dashboard.py +240 -0
- reflex_silverpoint_react-0.3.0/custom_components/reflex_silverpoint_react/dashboard.pyi +314 -0
- reflex_silverpoint_react-0.3.0/custom_components/reflex_silverpoint_react/ui.py +573 -0
- reflex_silverpoint_react-0.3.0/custom_components/reflex_silverpoint_react/ui.pyi +1687 -0
- reflex_silverpoint_react-0.3.0/custom_components/reflex_silverpoint_react/ui_catalog.py +330 -0
- reflex_silverpoint_react-0.3.0/custom_components/reflex_silverpoint_react.egg-info/PKG-INFO +379 -0
- {reflex_silverpoint_react-0.1.0 → reflex_silverpoint_react-0.3.0}/custom_components/reflex_silverpoint_react.egg-info/SOURCES.txt +5 -0
- {reflex_silverpoint_react-0.1.0 → reflex_silverpoint_react-0.3.0}/pyproject.toml +3 -3
- reflex_silverpoint_react-0.3.0/tests/test_components.py +229 -0
- reflex_silverpoint_react-0.1.0/PKG-INFO +0 -224
- reflex_silverpoint_react-0.1.0/README.md +0 -198
- reflex_silverpoint_react-0.1.0/custom_components/reflex_silverpoint_react.egg-info/PKG-INFO +0 -224
- reflex_silverpoint_react-0.1.0/tests/test_components.py +0 -84
- {reflex_silverpoint_react-0.1.0 → reflex_silverpoint_react-0.3.0}/LICENSE +0 -0
- {reflex_silverpoint_react-0.1.0 → reflex_silverpoint_react-0.3.0}/custom_components/reflex_silverpoint_react/charts.py +0 -0
- {reflex_silverpoint_react-0.1.0 → reflex_silverpoint_react-0.3.0}/custom_components/reflex_silverpoint_react/helpers.py +0 -0
- {reflex_silverpoint_react-0.1.0 → reflex_silverpoint_react-0.3.0}/custom_components/reflex_silverpoint_react.egg-info/dependency_links.txt +0 -0
- {reflex_silverpoint_react-0.1.0 → reflex_silverpoint_react-0.3.0}/custom_components/reflex_silverpoint_react.egg-info/requires.txt +0 -0
- {reflex_silverpoint_react-0.1.0 → reflex_silverpoint_react-0.3.0}/custom_components/reflex_silverpoint_react.egg-info/top_level.txt +0 -0
- {reflex_silverpoint_react-0.1.0 → reflex_silverpoint_react-0.3.0}/setup.cfg +0 -0
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: reflex-silverpoint-react
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: The 33 silverpoint charts, the linked Dashboard and the 17 UI components (Renaissance silverpoint drawing style) for Reflex, wrapping @silverpoint/react
|
|
5
|
+
Author-email: Ernesto Crespo <ecrespo@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/ecrespo/reflex-silverpoint-react
|
|
8
|
+
Project-URL: Source, https://github.com/ecrespo/reflex-silverpoint-react
|
|
9
|
+
Project-URL: Issues, https://github.com/ecrespo/reflex-silverpoint-react/issues
|
|
10
|
+
Project-URL: Upstream, https://github.com/ecrespo/silverpoint
|
|
11
|
+
Keywords: reflex,reflex-custom-components,charts,silverpoint,data-visualization,svg,ui-components
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: reflex>=0.9.12
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: build; extra == "dev"
|
|
22
|
+
Requires-Dist: twine; extra == "dev"
|
|
23
|
+
Requires-Dist: pytest; extra == "dev"
|
|
24
|
+
Requires-Dist: ruff; extra == "dev"
|
|
25
|
+
Dynamic: license-file
|
|
26
|
+
|
|
27
|
+
# reflex-silverpoint-react
|
|
28
|
+
|
|
29
|
+
A [Reflex](https://reflex.dev) custom component for **[silverpoint](https://github.com/ecrespo/silverpoint)**:
|
|
30
|
+
charts drawn in the manner of a Renaissance silverpoint drawing, with a fine silver line on a
|
|
31
|
+
prepared ground, tone built from hatching, and white heightening on the live value.
|
|
32
|
+
|
|
33
|
+
The hand-drawn irregularity lives only in the ornament. The data geometry is exact, and every chart
|
|
34
|
+
has a `precision` mode that turns the inking off.
|
|
35
|
+
|
|
36
|
+
It wraps [`@silverpoint/react`](https://www.npmjs.com/package/@silverpoint/react) 0.3.0 and exposes
|
|
37
|
+
**all 33 charts**, the **`Dashboard`** (a laid-out, linkable grid of charts), the **17 UI
|
|
38
|
+
components** (buttons, inputs, tabs, cards, alerts…), the `SilverpointProvider`, both grounds
|
|
39
|
+
(`silverpoint` and `cyanotype`), the interaction events, custom readouts and the imperative handle
|
|
40
|
+
(SVG export and geometry) as Python.
|
|
41
|
+
|
|
42
|
+
### New in 0.3
|
|
43
|
+
|
|
44
|
+
- **17 UI components**, drawn as the charts are: `sp_button`, `sp_input`, `sp_checkbox`,
|
|
45
|
+
`sp_switch`, `sp_radio_group`, `sp_slider`, `sp_rate`, `sp_segmented`, `sp_tabs` (with
|
|
46
|
+
`sp_tab_panel`), `sp_steps`, `sp_card`, `sp_tag`, `sp_badge`, `sp_divider`, `sp_progress`,
|
|
47
|
+
`sp_alert` and `sp_skeleton`. Native controls underneath, controlled from Python. See
|
|
48
|
+
[UI components](#ui-components).
|
|
49
|
+
- `UI_COMPONENTS` and `UI_DEMOS`: the catalog's 17 components, their 45 reference states, and
|
|
50
|
+
`ui_demo(slug, state)` to render any of them.
|
|
51
|
+
- `substrate="prussian"` is accepted everywhere (the `cyanotype` ground's substrate).
|
|
52
|
+
|
|
53
|
+
### New in 0.2
|
|
54
|
+
|
|
55
|
+
- **`dashboard`**, **`dashboard_cell`** and **`dashboard_link`**: a titled grid of cards laid out from
|
|
56
|
+
a data-only layout, charts sized to their cells, and charts linked on a datum field.
|
|
57
|
+
- **The `cyanotype` ground**: a white line on Prussian blue. Tone is the weight of an exact line, so
|
|
58
|
+
nothing is hatched. Use `ground="cyanotype"` on a chart, the provider or a dashboard.
|
|
59
|
+
|
|
60
|
+

|
|
61
|
+
|
|
62
|
+
## Installation
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install reflex-silverpoint-react
|
|
66
|
+
# or
|
|
67
|
+
uv add reflex-silverpoint-react
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Nothing else to do on the JavaScript side: Reflex installs `@silverpoint/react`,
|
|
71
|
+
`@silverpoint/core`, `@silverpoint/grounds` and `@silverpoint/fonts`, and every chart imports the two
|
|
72
|
+
stylesheets it needs (`@silverpoint/grounds/styles.css` and the self-hosted EB Garamond of
|
|
73
|
+
`@silverpoint/fonts/fonts.css`); the UI components also import `@silverpoint/grounds/ui.css`. No
|
|
74
|
+
Tailwind, no CDN.
|
|
75
|
+
|
|
76
|
+
Requires Reflex 0.9.12 or later (React 19).
|
|
77
|
+
|
|
78
|
+
## Quickstart
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
import reflex as rx
|
|
82
|
+
from reflex_silverpoint_react import line_chart
|
|
83
|
+
|
|
84
|
+
DATA = [
|
|
85
|
+
{"hour": "00", "hits": 18},
|
|
86
|
+
{"hour": "04", "hits": 11},
|
|
87
|
+
{"hour": "08", "hits": 42},
|
|
88
|
+
{"hour": "12", "hits": 64},
|
|
89
|
+
{"hour": "16", "hits": 57},
|
|
90
|
+
{"hour": "20", "hits": 30},
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def index() -> rx.Component:
|
|
95
|
+
return rx.box(
|
|
96
|
+
line_chart(data=DATA, x_key="hour", value_key="hits", title="Hits per hour"),
|
|
97
|
+
width="480px",
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
app = rx.App()
|
|
102
|
+
app.add_page(index)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The chart takes the width of its container; `height` is the height of the drawing area (160 px by
|
|
106
|
+
default). Omit `data` and a chart draws its own demo dataset.
|
|
107
|
+
|
|
108
|
+
Props are the React props in `snake_case`: `xKey` → `x_key`, `hatchFill` → `hatch_fill`,
|
|
109
|
+
`footerRight` → `footer_right`, `centerLabel` → `center_label`, and so on. `data` and every prop can
|
|
110
|
+
be a Reflex state var.
|
|
111
|
+
|
|
112
|
+
## The 33 charts
|
|
113
|
+
|
|
114
|
+
| Family | Charts |
|
|
115
|
+
|---|---|
|
|
116
|
+
| Lines | `line_chart`, `step_chart`, `sparkline_rows`, `kpi_card` |
|
|
117
|
+
| Bars | `bar_chart`, `stacked_bar_chart`, `composed_chart`, `waterfall_chart`, `funnel_chart`, `bullet_chart`, `pyramid_chart`, `candlestick_chart` |
|
|
118
|
+
| Areas | `area_chart`, `range_band_chart`, `stream_chart` |
|
|
119
|
+
| Points & grids | `scatter_chart`, `bubble_chart`, `heatmap_chart`, `treemap_chart`, `activity_grid` |
|
|
120
|
+
| Flows | `sankey_chart`, `chord_ring` |
|
|
121
|
+
| Radial | `donut_chart`, `radar_chart`, `polar_bar_chart`, `radial_arc_group`, `radial_rings`, `gauge_arc`, `meter_chart`, `coxcomb_chart`, `wind_rose`, `volvelle_chart`, `orbit_chart` |
|
|
122
|
+
|
|
123
|
+
Every factory has a class of the same name in `PascalCase` (`LineChart`, `WindRose`…).
|
|
124
|
+
`reflex_silverpoint_react.CHARTS` is the whole catalog with each chart's family and the reference of
|
|
125
|
+
its own props (`COMMON_PROPS` holds the shared ones), handy for galleries and documentation.
|
|
126
|
+
|
|
127
|
+
## Props every chart shares
|
|
128
|
+
|
|
129
|
+
| Prop | Default | |
|
|
130
|
+
|---|---|---|
|
|
131
|
+
| `data` | demo dataset | The rows to draw: a list of dicts. Without it, the accessor props (`*_key`, `keys`, `names`) are ignored. |
|
|
132
|
+
| `ground` / `substrate` / `mode` | `"silverpoint"` / `"cream"` / `"ink"` | Style. Grounds: `silverpoint` and `cyanotype`. The `silverpoint` substrates are `cream`, `green`, `blue` and `ochre`; `cyanotype` has one, `prussian`, whatever substrate a chart names. `mode="precision"` turns the inking off. |
|
|
133
|
+
| `seed`, `id` | derived, stable | The hand drawing is deterministic: same props, same strokes. |
|
|
134
|
+
| `height`, `width` | `160`, container width | Size of the drawing area in px. |
|
|
135
|
+
| `chrome` | `"card"` | `"bare"` draws only the plot. |
|
|
136
|
+
| `title`, `badge`, `value`, `unit`, `footer_left`, `footer_right` | — | The card's text. |
|
|
137
|
+
| `label`, `description`, `data_table` | from `title`, —, `"hidden"` | Accessibility. |
|
|
138
|
+
| `locale`, `number_format` | environment | Number formatting (`number_format` is a dict of `Intl.NumberFormatOptions`). |
|
|
139
|
+
| `hatch_fill` | `"tile"` | `"per-shape"` gives richer hatching at a much greater weight. |
|
|
140
|
+
| `tooltip` | built-in readout | A custom readout; see `tooltip_template`. |
|
|
141
|
+
| `on_active_change`, `on_select` | — | Events; see below. |
|
|
142
|
+
|
|
143
|
+
## One ground for the whole app
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
from reflex_silverpoint_react import bar_chart, donut_chart, silverpoint_provider
|
|
147
|
+
|
|
148
|
+
silverpoint_provider(
|
|
149
|
+
bar_chart(data=sales, x_key="month", value_key="units", title="Units sold", unit="units"),
|
|
150
|
+
donut_chart(data=channels, name_key="channel", value_key="share", title="Sales by channel", center_label="%"),
|
|
151
|
+
ground="silverpoint",
|
|
152
|
+
substrate="green",
|
|
153
|
+
locale="en-GB",
|
|
154
|
+
)
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
A prop on a chart always wins over the provider. The provider's props can be state vars, so one
|
|
158
|
+
select can re-ground a whole dashboard.
|
|
159
|
+
|
|
160
|
+
## Dashboards
|
|
161
|
+
|
|
162
|
+
`dashboard` lays charts out in a titled grid. The layout is plain data: the number of columns, each
|
|
163
|
+
cell's column and row spans (per breakpoint if you like), the row height and the gap. The
|
|
164
|
+
breakpoints are the dashboard's own width: `sm` below 640 px, `md` up to 1024 px, and `lg` above.
|
|
165
|
+
The defaults are 1, 2 and 4 columns. Each chart is sized to its cell, and `ground`, `substrate`,
|
|
166
|
+
`mode` and `locale` pass to every chart inside.
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
from reflex_silverpoint_react import (
|
|
170
|
+
bar_chart,
|
|
171
|
+
dashboard,
|
|
172
|
+
dashboard_cell,
|
|
173
|
+
dashboard_cell_layout,
|
|
174
|
+
dashboard_layout,
|
|
175
|
+
kpi_card,
|
|
176
|
+
line_chart,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
dashboard(
|
|
180
|
+
dashboard_cell(kpi_card(title="Revenue", metric="thousands", delta=6.4), cell="revenue"),
|
|
181
|
+
dashboard_cell(line_chart(data=State.ops, x_key="hour", value_key="hits", title="Traffic"), cell="traffic"),
|
|
182
|
+
dashboard_cell(bar_chart(data=State.ops, x_key="hour", value_key="errors", title="Errors"), cell="errors"),
|
|
183
|
+
id="ops", # required
|
|
184
|
+
title="Operations", # or label=... for no visible heading
|
|
185
|
+
description="Service health over the last day.",
|
|
186
|
+
layout=dashboard_layout(
|
|
187
|
+
["revenue", dashboard_cell_layout("traffic", col_span={"md": 2, "lg": 3}, row_span=2), "errors"],
|
|
188
|
+
columns={"sm": 1, "md": 2, "lg": 4},
|
|
189
|
+
row_height=240,
|
|
190
|
+
gap=16,
|
|
191
|
+
),
|
|
192
|
+
link="hour", # link the charts on the rows' "hour" field
|
|
193
|
+
on_link_change=State.on_link, # {"key": "hour", "value": "18"}, or None when it clears
|
|
194
|
+
)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
- `dashboard_cell(chart, cell="id")` puts a chart in a named layout cell. Children without one follow
|
|
198
|
+
the named cells, in source order, with span 1.
|
|
199
|
+
- With `link`, pointing at or focusing an item in one chart marks every item in the other charts
|
|
200
|
+
that has the same value in that field. `dashboard_link(..., link="hour")` does the same for charts
|
|
201
|
+
you lay out yourself, outside a dashboard grid.
|
|
202
|
+
- `heading_level` (2-6) sets the title's heading level. `ssr_width` is the width the grid is laid
|
|
203
|
+
out for before the browser measures it.
|
|
204
|
+
- `dashboard_layout` and `dashboard_cell_layout` write the camelCase keys the component reads. You
|
|
205
|
+
can also pass a plain dict.
|
|
206
|
+
- The layout values and the charts' props can be state vars.
|
|
207
|
+
|
|
208
|
+
## UI components
|
|
209
|
+
|
|
210
|
+
New in silverpoint 0.3: seventeen interface components with frames hand-drawn by each ground's own
|
|
211
|
+
inker and tone laid as hatching (`silverpoint`) or as the weight of an exact white line
|
|
212
|
+
(`cyanotype`). Each is a native control underneath (a `<button>`, an `<input>`, a `<fieldset>` of
|
|
213
|
+
radios), so forms submit natively and the keyboard follows the WAI-ARIA patterns. They are imported
|
|
214
|
+
from `@silverpoint/react/ui`.
|
|
215
|
+
|
|
216
|
+

|
|
217
|
+
|
|
218
|
+
| Group | Components |
|
|
219
|
+
|---|---|
|
|
220
|
+
| Actions | `sp_button` |
|
|
221
|
+
| Data entry | `sp_input`, `sp_checkbox`, `sp_radio_group`, `sp_switch`, `sp_slider`, `sp_rate`, `sp_segmented` |
|
|
222
|
+
| Navigation | `sp_tabs` + `sp_tab_panel`, `sp_steps` |
|
|
223
|
+
| Data display | `sp_card`, `sp_tag`, `sp_badge`, `sp_divider` |
|
|
224
|
+
| Feedback | `sp_progress`, `sp_alert`, `sp_skeleton` |
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
from reflex_silverpoint_react import sp_button, sp_input, sp_switch, sp_tab_panel, sp_tabs, ui_item
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
class State(rx.State):
|
|
231
|
+
city: str = "Caracas"
|
|
232
|
+
precision: bool = False
|
|
233
|
+
view: str = "traffic"
|
|
234
|
+
|
|
235
|
+
@rx.event
|
|
236
|
+
def set_city(self, value: str): # on_change gets the value, not an event
|
|
237
|
+
self.city = value
|
|
238
|
+
|
|
239
|
+
@rx.event
|
|
240
|
+
def set_precision(self, value: bool):
|
|
241
|
+
self.precision = value
|
|
242
|
+
|
|
243
|
+
@rx.event
|
|
244
|
+
def set_view(self, value: str):
|
|
245
|
+
self.view = value
|
|
246
|
+
|
|
247
|
+
@rx.event
|
|
248
|
+
def save(self, form: dict):
|
|
249
|
+
print(form) # {"city": "Caracas", ...}: the native inputs submit under their name
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
rx.el.form(
|
|
253
|
+
sp_input(
|
|
254
|
+
label="City",
|
|
255
|
+
name="city",
|
|
256
|
+
value=State.city,
|
|
257
|
+
on_change=State.set_city,
|
|
258
|
+
invalid=State.city == "",
|
|
259
|
+
message="Required: pick a city",
|
|
260
|
+
),
|
|
261
|
+
sp_switch(label="Precision", checked=State.precision, on_change=State.set_precision),
|
|
262
|
+
sp_tabs(
|
|
263
|
+
sp_tab_panel(line_chart(...), value="traffic"),
|
|
264
|
+
sp_tab_panel(bar_chart(...), value="errors"),
|
|
265
|
+
items=[ui_item("traffic", "Traffic"), ui_item("errors", "Errors")],
|
|
266
|
+
value=State.view,
|
|
267
|
+
on_change=State.set_view,
|
|
268
|
+
),
|
|
269
|
+
sp_button("Save", type="submit", variant="primary"),
|
|
270
|
+
on_submit=State.save,
|
|
271
|
+
)
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
- **Shared props**: `id`, `ground`, `substrate`, `mode`, `seed`, `size` (`sm`/`md`/`lg`) and
|
|
275
|
+
`class_name`. Like charts, they fall back to the dashboard, then to `silverpoint_provider`.
|
|
276
|
+
- **Values**: value components are controlled (`value=` / `checked=` with `on_change`) or
|
|
277
|
+
uncontrolled (`default_value=` / `default_checked=`). `on_change` receives the new value itself (a
|
|
278
|
+
string, a bool or a number), never a DOM event.
|
|
279
|
+
- **Items**: `ui_item(key, label, disabled=False)` for tabs, segmented and radio groups;
|
|
280
|
+
`step_item(key, title, description=None, status=None)` for steps.
|
|
281
|
+
- **Slots**: children are a button's or tag's text, a card's or alert's body; `sp_card` also takes
|
|
282
|
+
`extra` and `footer`, and `sp_input` takes `prefix` and `suffix` (components or text).
|
|
283
|
+
- **Close events**: `sp_tag(closable=True, on_close=...)` and `sp_alert(closable=True, on_close=...)`.
|
|
284
|
+
- `UI_COMPONENTS` is the catalog (group, declared states, props reference) and `UI_DEMOS` the 45
|
|
285
|
+
reference states upstream ships; `ui_demo("radio-group", "selected", ground="cyanotype")` renders
|
|
286
|
+
one, uncontrolled.
|
|
287
|
+
- Text inputs controlled from state make a round trip per keystroke; for long text, prefer
|
|
288
|
+
`default_value` and read the value on submit.
|
|
289
|
+
|
|
290
|
+
## Interaction
|
|
291
|
+
|
|
292
|
+
```python
|
|
293
|
+
class State(rx.State):
|
|
294
|
+
active: str = "—"
|
|
295
|
+
|
|
296
|
+
@rx.event
|
|
297
|
+
def on_active(self, item: dict | None):
|
|
298
|
+
self.active = "—" if item is None else f"{item['datum']['hour']}: {item['value']}"
|
|
299
|
+
|
|
300
|
+
@rx.event
|
|
301
|
+
def on_select(self, item: dict):
|
|
302
|
+
print("selected", item["datum"])
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
line_chart(
|
|
306
|
+
data=DATA,
|
|
307
|
+
x_key="hour",
|
|
308
|
+
value_key="hits",
|
|
309
|
+
on_active_change=State.on_active,
|
|
310
|
+
on_select=State.on_select,
|
|
311
|
+
tooltip=tooltip_template("{datum.hour} h · {value} hits"),
|
|
312
|
+
)
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
- `on_active_change` receives the item under the pointer or keyboard focus, and `None` when it
|
|
316
|
+
leaves. `on_select` fires on click, `Enter` or `Space`. The item is
|
|
317
|
+
`{"seriesKey", "index", "datum", "value", "point": {"x", "y"}}`.
|
|
318
|
+
- `tooltip_template(text)` builds the `tooltip` render function from a format string. Placeholders:
|
|
319
|
+
`{heading}`, `{text}` (the built-in readout's two lines), `{announcement}`, `{value}`, `{index}`,
|
|
320
|
+
`{series}` and `{datum.<field>}`. `{{` and `}}` print literal braces.
|
|
321
|
+
|
|
322
|
+
## Export: the imperative handle
|
|
323
|
+
|
|
324
|
+
Give a chart an `id` and its `ChartHandle` is reachable from Python:
|
|
325
|
+
|
|
326
|
+
```python
|
|
327
|
+
from reflex_silverpoint_react import download_svg, get_geometry, get_svg
|
|
328
|
+
|
|
329
|
+
line_chart(id="hits", data=DATA, x_key="hour", value_key="hits")
|
|
330
|
+
|
|
331
|
+
rx.button("Download SVG", on_click=download_svg("hits", "hits.svg")) # in the browser
|
|
332
|
+
rx.button("SVG to Python", on_click=get_svg("hits", State.receive_svg)) # handler gets a str
|
|
333
|
+
rx.button("Geometry", on_click=get_geometry("hits", State.receive_geometry)) # handler gets a dict
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
The exported SVG carries its own ground colours, so it renders the same outside the app.
|
|
337
|
+
|
|
338
|
+
## Notes
|
|
339
|
+
|
|
340
|
+
- `volvelle_chart`: `index_ring` and `index_value` apply to your own rings, so pass `data` when you
|
|
341
|
+
use them (the demo dataset keeps its own index).
|
|
342
|
+
- `gauge_arc` and `meter_chart` take `percent` (0-100) instead of `data`.
|
|
343
|
+
- Charts switch to `precision` by themselves under `prefers-contrast: more` or
|
|
344
|
+
`forced-colors: active`; no prop overrides that.
|
|
345
|
+
- Accessors are field names (strings). The JavaScript API also accepts functions; from Python, shape
|
|
346
|
+
your rows instead.
|
|
347
|
+
|
|
348
|
+
## Demo app
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
uv venv && uv pip install -e .
|
|
352
|
+
cd silverpoint_react_demo
|
|
353
|
+
uv run reflex run
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Pages: **Start** (quickstart, provider, ink vs precision), **Gallery** (the 33 charts, ground
|
|
357
|
+
controls, demo datasets vs data from Python state with a re-roll), **Playground** (one chart, every
|
|
358
|
+
rendering choice and the Python that reproduces it), **Interaction** (events, custom readout, a
|
|
359
|
+
volvelle that turns on click, live KPI/gauge/meter, SVG and geometry export), **Dashboard** (a
|
|
360
|
+
linked operations dashboard fed from Python state with ground, substrate, mode and column controls, a
|
|
361
|
+
KPI strip, and `dashboard_link` on its own), **UI components** (`/ui`: the components controlled from
|
|
362
|
+
Python state with a native form submit, and the three reference panels of the upstream example apps
|
|
363
|
+
in silverpoint ink, precision and cyanotype), one **reference page per chart** (`/chart/<slug>`) and
|
|
364
|
+
one per UI component (`/ui/<slug>`: every declared state on both grounds, usage and props). The Gallery and Playground also get a ground control, for `cyanotype`.
|
|
365
|
+
|
|
366
|
+

|
|
367
|
+
|
|
368
|
+
## Development
|
|
369
|
+
|
|
370
|
+
```bash
|
|
371
|
+
uv venv && uv pip install -e ".[dev]"
|
|
372
|
+
uv run pytest
|
|
373
|
+
uv run ruff check .
|
|
374
|
+
uv run reflex component build # .pyi stubs + sdist and wheel in dist/
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
## License
|
|
378
|
+
|
|
379
|
+
MIT. silverpoint is MIT; the EB Garamond typeface is under the SIL Open Font License.
|