reflex-silverpoint-react 0.7.0__tar.gz → 0.8.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 (48) hide show
  1. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/PKG-INFO +95 -36
  2. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/README.md +93 -32
  3. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/custom_components/reflex_silverpoint_react/__init__.py +54 -3
  4. reflex_silverpoint_react-0.8.0/custom_components/reflex_silverpoint_react/assets/trigger.jsx +63 -0
  5. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/custom_components/reflex_silverpoint_react/base.py +40 -12
  6. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/custom_components/reflex_silverpoint_react/base.pyi +6 -3
  7. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/custom_components/reflex_silverpoint_react/catalog.py +12 -0
  8. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/custom_components/reflex_silverpoint_react/charts.pyi +1 -1
  9. reflex_silverpoint_react-0.8.0/custom_components/reflex_silverpoint_react/composed.py +633 -0
  10. reflex_silverpoint_react-0.8.0/custom_components/reflex_silverpoint_react/composed.pyi +684 -0
  11. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/custom_components/reflex_silverpoint_react/dashboard.py +5 -3
  12. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/custom_components/reflex_silverpoint_react/dashboard.pyi +1 -1
  13. reflex_silverpoint_react-0.8.0/custom_components/reflex_silverpoint_react/overlays.py +784 -0
  14. reflex_silverpoint_react-0.8.0/custom_components/reflex_silverpoint_react/overlays.pyi +674 -0
  15. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/custom_components/reflex_silverpoint_react/palette.py +85 -70
  16. reflex_silverpoint_react-0.8.0/custom_components/reflex_silverpoint_react/surfaces.py +235 -0
  17. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/custom_components/reflex_silverpoint_react/surfaces.pyi +30 -106
  18. reflex_silverpoint_react-0.8.0/custom_components/reflex_silverpoint_react/timeline.py +172 -0
  19. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/custom_components/reflex_silverpoint_react/timeline.pyi +43 -15
  20. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/custom_components/reflex_silverpoint_react/ui.py +3 -0
  21. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/custom_components/reflex_silverpoint_react/ui.pyi +1 -1
  22. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/custom_components/reflex_silverpoint_react.egg-info/PKG-INFO +95 -36
  23. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/custom_components/reflex_silverpoint_react.egg-info/SOURCES.txt +6 -4
  24. reflex_silverpoint_react-0.8.0/custom_components/reflex_silverpoint_react.egg-info/requires.txt +9 -0
  25. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/pyproject.toml +8 -7
  26. reflex_silverpoint_react-0.8.0/tests/test_agent_catalog.py +162 -0
  27. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/tests/test_components.py +4 -4
  28. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/tests/test_demo_data.py +23 -0
  29. reflex_silverpoint_react-0.8.0/tests/test_plugin.py +42 -0
  30. reflex_silverpoint_react-0.8.0/tests/test_skill.py +170 -0
  31. reflex_silverpoint_react-0.8.0/tests/test_v07.py +324 -0
  32. reflex_silverpoint_react-0.7.0/custom_components/reflex_silverpoint_react/assets/surface.jsx +0 -219
  33. reflex_silverpoint_react-0.7.0/custom_components/reflex_silverpoint_react/assets/surfaces.css +0 -375
  34. reflex_silverpoint_react-0.7.0/custom_components/reflex_silverpoint_react/assets/timeline.css +0 -225
  35. reflex_silverpoint_react-0.7.0/custom_components/reflex_silverpoint_react/assets/timeline.jsx +0 -64
  36. reflex_silverpoint_react-0.7.0/custom_components/reflex_silverpoint_react/composed.py +0 -702
  37. reflex_silverpoint_react-0.7.0/custom_components/reflex_silverpoint_react/overlays.py +0 -835
  38. reflex_silverpoint_react-0.7.0/custom_components/reflex_silverpoint_react/surfaces.py +0 -329
  39. reflex_silverpoint_react-0.7.0/custom_components/reflex_silverpoint_react/timeline.py +0 -157
  40. reflex_silverpoint_react-0.7.0/custom_components/reflex_silverpoint_react.egg-info/requires.txt +0 -11
  41. reflex_silverpoint_react-0.7.0/tests/test_v07.py +0 -234
  42. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/LICENSE +0 -0
  43. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/custom_components/reflex_silverpoint_react/charts.py +0 -0
  44. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/custom_components/reflex_silverpoint_react/helpers.py +0 -0
  45. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/custom_components/reflex_silverpoint_react/ui_catalog.py +0 -0
  46. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/custom_components/reflex_silverpoint_react.egg-info/dependency_links.txt +0 -0
  47. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/custom_components/reflex_silverpoint_react.egg-info/top_level.txt +0 -0
  48. {reflex_silverpoint_react-0.7.0 → reflex_silverpoint_react-0.8.0}/setup.cfg +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reflex-silverpoint-react
3
- Version: 0.7.0
4
- Summary: The 60 silverpoint charts, the Dashboard, 17 UI components, palettes, 20 composed components and a Knight Lab timeline (Renaissance silverpoint drawing style) for Reflex, wrapping @silverpoint/react
3
+ Version: 0.8.0
4
+ Summary: The 60 silverpoint charts, the Dashboard, 38 UI, composed and overlay components, palettes and a Knight Lab timeline (Renaissance silverpoint drawing style) for Reflex, wrapping @silverpoint/react 0.8
5
5
  Author-email: Ernesto Crespo <ecrespo@gmail.com>
6
6
  License: MIT
7
7
  Project-URL: Homepage, https://github.com/ecrespo/reflex-silverpoint-react
@@ -18,13 +18,11 @@ Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
19
  Requires-Dist: reflex>=0.10.0
20
20
  Provides-Extra: timeline
21
- Requires-Dist: reflex-knightlab-timeline>=0.1.2; extra == "timeline"
22
21
  Provides-Extra: dev
23
22
  Requires-Dist: build; extra == "dev"
24
23
  Requires-Dist: twine; extra == "dev"
25
24
  Requires-Dist: pytest; extra == "dev"
26
25
  Requires-Dist: ruff; extra == "dev"
27
- Requires-Dist: reflex-knightlab-timeline>=0.1.2; extra == "dev"
28
26
  Dynamic: license-file
29
27
 
30
28
  # reflex-silverpoint-react
@@ -36,17 +34,48 @@ prepared ground, tone built from hatching, and white heightening on the live val
36
34
  The hand-drawn irregularity lives only in the ornament. The data geometry is exact, and every chart
37
35
  has a `precision` mode that turns the inking off.
38
36
 
39
- It wraps [`@silverpoint/react`](https://www.npmjs.com/package/@silverpoint/react) 0.6.0 and exposes
37
+ It wraps [`@silverpoint/react`](https://www.npmjs.com/package/@silverpoint/react) **0.8.0** and exposes
40
38
  **all 60 charts**, the **`Dashboard`** (a laid-out, linkable grid of charts), the **17 UI
41
- components** (buttons, inputs, tabs, cards, alerts…), the `SilverpointProvider`, both grounds
42
- (`silverpoint` and `cyanotype`), the interaction events, custom readouts and the imperative handle
43
- (SVG export and geometry) as Python.
44
-
45
- On top of that it adds, in Reflex: **palettes** for every chart and component, **20 composed
46
- components** built on silverpoint's own frames and tones (tables, overlays, toasts…), and the
47
- **Knight Lab timeline** drawn in silverpoint.
48
-
49
- ### New in 0.7
39
+ components** (buttons, inputs, tabs, cards, alerts…), the **12 composed components** (table,
40
+ pagination, breadcrumb, avatar…), the **7 overlays** and the toaster (modal, drawer, popover,
41
+ tooltip, select, dropdown menu, toast), the **palettes**, the **Knight Lab timeline**, the
42
+ `SilverpointProvider`, both grounds (`silverpoint` and `cyanotype`), the interaction events, custom
43
+ readouts and the imperative handle (SVG export and geometry) as Python.
44
+
45
+ Everything it renders is an npm component of silverpoint, under its parity contract: the same
46
+ markup React, Vue and Angular render.
47
+
48
+ ### New in 0.8.0
49
+
50
+ - Wraps **`@silverpoint/react` 0.8.0**. silverpoint 0.8 adds agent access and changes no API this
51
+ package wraps, so the Python builders are unchanged.
52
+ - **Agent access:** the `reflex-silverpoint` skill, a Claude plugin with the hosted silverpoint MCP
53
+ server, and `reflex-catalog.json`, the Reflex catalog silverpoint's agent catalog joins. See
54
+ [Use with AI](#use-with-ai).
55
+
56
+ ### New in 0.7.1
57
+
58
+ - Wraps **`@silverpoint/react` 0.7.0** (0.7.0 wrapped 0.6.0). silverpoint 0.7 took this package's
59
+ palettes, composed components, overlays and timeline into the library itself, so they are now the
60
+ npm components, not Reflex-composed copies: same Python builders, the library's markup.
61
+ - **Palettes** are the npm `palette` prop: they merge element → dashboard → provider field by field,
62
+ `silverpoint_provider(palette=...)` works, and `silverpoint_palette(...)` is a provider with a
63
+ palette. `check_palette()` measures the core's nine contrast pairs (the focus ring and the white
64
+ heightening included); `"ironGall"` names the `iron_gall` preset too.
65
+ - **Composed components and overlays read `silverpoint_provider`**, as the `Sp` components do.
66
+ Overlays are a native `<dialog>` and the Popover API (no Radix); they render in place, so a
67
+ section's palette reaches them.
68
+ - **Logical sides**: `side="start"`/`"end"` and `position="bottom-end"`…; `left`/`right` still work
69
+ with a `DeprecationWarning`. `sp_drawer(size=)` is `extent=`, `sp_popover(side_offset=)` is
70
+ `offset=`; `sp_modal` gains `label` and `dismissible`, `sp_result`/`sp_descriptions`
71
+ `heading_level`.
72
+ - `sp_textarea(textarea_id=)` and `sp_input_number(input_id=)` are `id=` (deprecated aliases kept);
73
+ `sp_textarea` has no `on_blur`. `sp_collapse_item(on_toggle=)` receives the new open state (a bool).
74
+ - **`sp_timeline`** is the npm `SpTimeline`: TimelineJS is an npm dependency of that component, so the
75
+ `[timeline]` extra pulls in nothing any more (it is kept so existing installs keep working).
76
+ - `sort_rows()` follows the core's `uiSortRows` order (numbers first, then text by code point).
77
+
78
+ ### New in 0.7.0
50
79
 
51
80
  - **Reflex 0.10.0**, and therefore **Python 3.11 or later** (Python 3.10 is no longer supported).
52
81
  Reflex 0.10 removed `reflex component build`: stubs are regenerated with `scripts/make_stubs.py`.
@@ -63,7 +92,7 @@ components** built on silverpoint's own frames and tones (tables, overlays, toas
63
92
  `sp_trigger` as their drawn button. See [Composed components](#composed-components).
64
93
  - **`sp_timeline`** — Knight Lab TimelineJS drawn in silverpoint: a skin on the ground's colours and
65
94
  type, plus the ground's own hand-inked frames and tone tiles on its markers, eras and buttons.
66
- Optional extra: `pip install "reflex-silverpoint-react[timeline]"`. See [Timeline](#timeline).
95
+ Optional extra (until 0.7.1): `pip install "reflex-silverpoint-react[timeline]"`. See [Timeline](#timeline).
67
96
  - `sp_surface`, `sp_glyph`: the building blocks, for components of your own.
68
97
 
69
98
  ### New in 0.6
@@ -396,19 +425,19 @@ silverpoint_palette(dashboard(...), sp_card(...), palette="indigo") # a whole s
396
425
  ```
397
426
 
398
427
  Fields: `substrate`, `ink`, `ink_secondary`, `heighten`, `rule`, `grid`, `text`, `text_muted` and
399
- `focus` (the UI focus ring). Unset fields keep the ground's own. An element's own `palette` always
400
- wins over its section's. A palette is **monochrome by design**: tone is built from hatch density
401
- (Art. 6), so a chart has two inks (`ink` for the main series, `ink_secondary` for the second), never
402
- a colour per series. `precision` mode and the system's high-contrast modes still apply on top.
403
- `silverpoint_provider` takes no palette (it renders no element): use `silverpoint_palette`.
428
+ `focus` (the UI focus ring). Unset fields keep the ground's own. Palettes merge field by field,
429
+ element → dashboard → provider, so an element's own `palette` wins over its section's. A palette is
430
+ **monochrome by design**: tone is built from hatch density (Art. 6), so a chart has two inks (`ink`
431
+ for the main series, `ink_secondary` for the second), never a colour per series. `precision` mode and
432
+ the system's high-contrast modes still apply on top. `silverpoint_palette(...)` is
433
+ `silverpoint_provider(palette=...)` around the section.
404
434
 
405
435
  ## Composed components
406
436
 
407
- Components built in Reflex on silverpoint's markup contract: `@silverpoint/grounds/ui.css` draws its
408
- hand-inked frames, hatched tones and heightening on any element that follows it, so these are drawn
409
- with exactly the same pieces as the `Sp` components. They are **Reflex-only** (silverpoint's React,
410
- Vue and Angular adapters do not have them) and, unlike the `Sp` components, they do not read
411
- `silverpoint_provider`: pass `ground`, `substrate`, `mode` and `palette` explicitly.
437
+ silverpoint 0.7's composed components and overlays, the npm components of `@silverpoint/react/ui`:
438
+ native markup drawn by the core with the ground's hand-inked frames, hatched tones and
439
+ heightening, exactly as the `Sp` components are. Like them they read `silverpoint_provider` (and
440
+ the dashboard they sit in); a prop on the component always wins.
412
441
 
413
442
  ```python
414
443
  from reflex_silverpoint_react import sort_rows, sp_pagination, sp_table
@@ -428,7 +457,7 @@ sp_table(
428
457
  sp_pagination(total=240, current=State.page, on_change=State.set_page, show_total=True)
429
458
  ```
430
459
 
431
- | Level A (native) | |
460
+ | Composed (native markup) | |
432
461
  |---|---|
433
462
  | `sp_table` | Card-framed table: small-caps header, tabular figures, hatched striping, sortable headers with `aria-sort` |
434
463
  | `sp_pagination` | Previous/next, first/last, a window around the current page (heightened); `on_change(page)` |
@@ -441,7 +470,7 @@ sp_pagination(total=240, current=State.page, on_change=State.set_page, show_tota
441
470
  | `sp_empty`, `sp_result` | Empty state; outcome with a drawn round mark |
442
471
  | `sp_textarea`, `sp_input_number` | On the `SpInput` contract; `on_change` receives the value (text or number) |
443
472
 
444
- | Level B (Radix primitives) | |
473
+ | Overlays (`<dialog>`, Popover API) | |
445
474
  |---|---|
446
475
  | `sp_modal`, `sp_drawer` | Dialog on a card frame over a hatched backdrop; drawer from any edge |
447
476
  | `sp_popover`, `sp_tooltip` | Anchored content; tooltip on hover or keyboard focus |
@@ -449,10 +478,15 @@ sp_pagination(total=240, current=State.page, on_change=State.set_page, show_tota
449
478
  | `sp_dropdown_menu` | Commands with shortcuts, separators and labels; `on_select(key)` |
450
479
  | `sp_toast`, `sp_toaster` | Notices that stack in a corner; `error`/`warning` are announced assertively |
451
480
 
452
- Behaviour (focus trapping, keyboard, dismissal, positioning, ARIA) is Radix's, at the versions
453
- Reflex already installs. Overlays render in a portal at the end of `<body>`, outside any
454
- `silverpoint_palette` section, so give them `palette` directly. A string `trigger` becomes
455
- `sp_trigger(...)`, the drawn button that can forward Radix's props (`sp_button` cannot).
481
+ Behaviour is the platform's: `showModal()` for the modal and the drawer (focus stays inside, Escape
482
+ and the backdrop close it unless `dismissible=False`), the Popover API for the rest (light
483
+ dismiss), keyboard and placement from `@silverpoint/core` (APG listbox and menu, typeahead, flip and
484
+ shift). Overlays render in place (the top layer, no portal), so a section's palette reaches them.
485
+ Sides are logical (`start`/`end`) and mirror in right-to-left text. An overlay clones its `trigger`
486
+ with its ARIA and a toggling click, so the trigger must keep the props it is given: a native
487
+ `rx.el.button`, or `sp_trigger(...)`, the drawn button strings become (`sp_button` drops them in
488
+ silverpoint 0.7.0). `sp_trigger` does not read the provider: give it `ground`, `substrate`, `mode`
489
+ and `palette`.
456
490
 
457
491
  ```python
458
492
  sp_modal(
@@ -471,15 +505,15 @@ sp_toaster(sp_toast("Saved", State.text, kind="success", open=State.toast_open,
471
505
 
472
506
  ## Timeline
473
507
 
474
- ```bash
475
- pip install "reflex-silverpoint-react[timeline]" # adds reflex-knightlab-timeline
476
- ```
508
+ The npm `SpTimeline` of `@silverpoint/react/timeline`. TimelineJS (`@knight-lab/timelinejs` 3.9.13)
509
+ is an npm dependency of this component: Reflex installs it when a page uses `sp_timeline`, and no
510
+ Python extra is needed. If it cannot be loaded, the component warns `SP025` and renders `fallback`.
477
511
 
478
512
  ```python
479
513
  from reflex_silverpoint_react import sp_timeline
480
514
 
481
515
  sp_timeline(
482
- DATA, # TimelineJS data: title, events, eras (or a TimelineData)
516
+ DATA, # TimelineJS data: title, events, eras (or any object with to_dict())
483
517
  height=560,
484
518
  ground="silverpoint",
485
519
  substrate="cream",
@@ -561,10 +595,35 @@ The exported SVG carries its own ground colours, so it renders the same outside
561
595
  - Accessors are field names (strings). The JavaScript API also accepts functions; from Python, shape
562
596
  your rows instead.
563
597
 
598
+ ## Use with AI
599
+
600
+ An assistant writes better `reflex-silverpoint-react` code with the **`reflex-silverpoint` skill**
601
+ ([`skills/reflex-silverpoint/`](skills/reflex-silverpoint/SKILL.md)): the builders and their
602
+ snake_case props, State patterns, event payloads, the provider and palettes, composed components and
603
+ overlays, the dashboard and the timeline. Its tables are generated from the package, and every Python
604
+ example in it is imported and rendered by the tests.
605
+
606
+ In Claude Code, the plugin installs the skill together with the hosted silverpoint MCP server
607
+ (`https://silverpointweb.vercel.app/mcp`), which recommends charts, checks props and draws a chart
608
+ as SVG before you write the code:
609
+
610
+ ```text
611
+ /plugin marketplace add ecrespo/reflex-silverpoint-react
612
+ /plugin install reflex-silverpoint@reflex-silverpoint
613
+ ```
614
+
615
+ The MCP server alone: `claude mcp add --transport http silverpoint https://silverpointweb.vercel.app/mcp`.
616
+
617
+ [`reflex-catalog.json`](reflex-catalog.json) is this package's catalog for agents: every chart and
618
+ component builder with its props (Python name, JS name and type), the deprecated arguments it still
619
+ accepts, the helpers, the package version and the silverpoint version it wraps. silverpoint's agent
620
+ catalog joins it, so its MCP tools answer with the Reflex names too. `scripts/export_catalog.py`
621
+ writes it, CI fails when it is stale, and each GitHub release carries it.
622
+
564
623
  ## Demo app
565
624
 
566
625
  ```bash
567
- uv venv && uv pip install -e ".[timeline]"
626
+ uv venv && uv pip install -e .
568
627
  cd silverpoint_react_demo
569
628
  uv run reflex run
570
629
  ```
@@ -7,17 +7,48 @@ prepared ground, tone built from hatching, and white heightening on the live val
7
7
  The hand-drawn irregularity lives only in the ornament. The data geometry is exact, and every chart
8
8
  has a `precision` mode that turns the inking off.
9
9
 
10
- It wraps [`@silverpoint/react`](https://www.npmjs.com/package/@silverpoint/react) 0.6.0 and exposes
10
+ It wraps [`@silverpoint/react`](https://www.npmjs.com/package/@silverpoint/react) **0.8.0** and exposes
11
11
  **all 60 charts**, the **`Dashboard`** (a laid-out, linkable grid of charts), the **17 UI
12
- components** (buttons, inputs, tabs, cards, alerts…), the `SilverpointProvider`, both grounds
13
- (`silverpoint` and `cyanotype`), the interaction events, custom readouts and the imperative handle
14
- (SVG export and geometry) as Python.
15
-
16
- On top of that it adds, in Reflex: **palettes** for every chart and component, **20 composed
17
- components** built on silverpoint's own frames and tones (tables, overlays, toasts…), and the
18
- **Knight Lab timeline** drawn in silverpoint.
19
-
20
- ### New in 0.7
12
+ components** (buttons, inputs, tabs, cards, alerts…), the **12 composed components** (table,
13
+ pagination, breadcrumb, avatar…), the **7 overlays** and the toaster (modal, drawer, popover,
14
+ tooltip, select, dropdown menu, toast), the **palettes**, the **Knight Lab timeline**, the
15
+ `SilverpointProvider`, both grounds (`silverpoint` and `cyanotype`), the interaction events, custom
16
+ readouts and the imperative handle (SVG export and geometry) as Python.
17
+
18
+ Everything it renders is an npm component of silverpoint, under its parity contract: the same
19
+ markup React, Vue and Angular render.
20
+
21
+ ### New in 0.8.0
22
+
23
+ - Wraps **`@silverpoint/react` 0.8.0**. silverpoint 0.8 adds agent access and changes no API this
24
+ package wraps, so the Python builders are unchanged.
25
+ - **Agent access:** the `reflex-silverpoint` skill, a Claude plugin with the hosted silverpoint MCP
26
+ server, and `reflex-catalog.json`, the Reflex catalog silverpoint's agent catalog joins. See
27
+ [Use with AI](#use-with-ai).
28
+
29
+ ### New in 0.7.1
30
+
31
+ - Wraps **`@silverpoint/react` 0.7.0** (0.7.0 wrapped 0.6.0). silverpoint 0.7 took this package's
32
+ palettes, composed components, overlays and timeline into the library itself, so they are now the
33
+ npm components, not Reflex-composed copies: same Python builders, the library's markup.
34
+ - **Palettes** are the npm `palette` prop: they merge element → dashboard → provider field by field,
35
+ `silverpoint_provider(palette=...)` works, and `silverpoint_palette(...)` is a provider with a
36
+ palette. `check_palette()` measures the core's nine contrast pairs (the focus ring and the white
37
+ heightening included); `"ironGall"` names the `iron_gall` preset too.
38
+ - **Composed components and overlays read `silverpoint_provider`**, as the `Sp` components do.
39
+ Overlays are a native `<dialog>` and the Popover API (no Radix); they render in place, so a
40
+ section's palette reaches them.
41
+ - **Logical sides**: `side="start"`/`"end"` and `position="bottom-end"`…; `left`/`right` still work
42
+ with a `DeprecationWarning`. `sp_drawer(size=)` is `extent=`, `sp_popover(side_offset=)` is
43
+ `offset=`; `sp_modal` gains `label` and `dismissible`, `sp_result`/`sp_descriptions`
44
+ `heading_level`.
45
+ - `sp_textarea(textarea_id=)` and `sp_input_number(input_id=)` are `id=` (deprecated aliases kept);
46
+ `sp_textarea` has no `on_blur`. `sp_collapse_item(on_toggle=)` receives the new open state (a bool).
47
+ - **`sp_timeline`** is the npm `SpTimeline`: TimelineJS is an npm dependency of that component, so the
48
+ `[timeline]` extra pulls in nothing any more (it is kept so existing installs keep working).
49
+ - `sort_rows()` follows the core's `uiSortRows` order (numbers first, then text by code point).
50
+
51
+ ### New in 0.7.0
21
52
 
22
53
  - **Reflex 0.10.0**, and therefore **Python 3.11 or later** (Python 3.10 is no longer supported).
23
54
  Reflex 0.10 removed `reflex component build`: stubs are regenerated with `scripts/make_stubs.py`.
@@ -34,7 +65,7 @@ components** built on silverpoint's own frames and tones (tables, overlays, toas
34
65
  `sp_trigger` as their drawn button. See [Composed components](#composed-components).
35
66
  - **`sp_timeline`** — Knight Lab TimelineJS drawn in silverpoint: a skin on the ground's colours and
36
67
  type, plus the ground's own hand-inked frames and tone tiles on its markers, eras and buttons.
37
- Optional extra: `pip install "reflex-silverpoint-react[timeline]"`. See [Timeline](#timeline).
68
+ Optional extra (until 0.7.1): `pip install "reflex-silverpoint-react[timeline]"`. See [Timeline](#timeline).
38
69
  - `sp_surface`, `sp_glyph`: the building blocks, for components of your own.
39
70
 
40
71
  ### New in 0.6
@@ -367,19 +398,19 @@ silverpoint_palette(dashboard(...), sp_card(...), palette="indigo") # a whole s
367
398
  ```
368
399
 
369
400
  Fields: `substrate`, `ink`, `ink_secondary`, `heighten`, `rule`, `grid`, `text`, `text_muted` and
370
- `focus` (the UI focus ring). Unset fields keep the ground's own. An element's own `palette` always
371
- wins over its section's. A palette is **monochrome by design**: tone is built from hatch density
372
- (Art. 6), so a chart has two inks (`ink` for the main series, `ink_secondary` for the second), never
373
- a colour per series. `precision` mode and the system's high-contrast modes still apply on top.
374
- `silverpoint_provider` takes no palette (it renders no element): use `silverpoint_palette`.
401
+ `focus` (the UI focus ring). Unset fields keep the ground's own. Palettes merge field by field,
402
+ element → dashboard → provider, so an element's own `palette` wins over its section's. A palette is
403
+ **monochrome by design**: tone is built from hatch density (Art. 6), so a chart has two inks (`ink`
404
+ for the main series, `ink_secondary` for the second), never a colour per series. `precision` mode and
405
+ the system's high-contrast modes still apply on top. `silverpoint_palette(...)` is
406
+ `silverpoint_provider(palette=...)` around the section.
375
407
 
376
408
  ## Composed components
377
409
 
378
- Components built in Reflex on silverpoint's markup contract: `@silverpoint/grounds/ui.css` draws its
379
- hand-inked frames, hatched tones and heightening on any element that follows it, so these are drawn
380
- with exactly the same pieces as the `Sp` components. They are **Reflex-only** (silverpoint's React,
381
- Vue and Angular adapters do not have them) and, unlike the `Sp` components, they do not read
382
- `silverpoint_provider`: pass `ground`, `substrate`, `mode` and `palette` explicitly.
410
+ silverpoint 0.7's composed components and overlays, the npm components of `@silverpoint/react/ui`:
411
+ native markup drawn by the core with the ground's hand-inked frames, hatched tones and
412
+ heightening, exactly as the `Sp` components are. Like them they read `silverpoint_provider` (and
413
+ the dashboard they sit in); a prop on the component always wins.
383
414
 
384
415
  ```python
385
416
  from reflex_silverpoint_react import sort_rows, sp_pagination, sp_table
@@ -399,7 +430,7 @@ sp_table(
399
430
  sp_pagination(total=240, current=State.page, on_change=State.set_page, show_total=True)
400
431
  ```
401
432
 
402
- | Level A (native) | |
433
+ | Composed (native markup) | |
403
434
  |---|---|
404
435
  | `sp_table` | Card-framed table: small-caps header, tabular figures, hatched striping, sortable headers with `aria-sort` |
405
436
  | `sp_pagination` | Previous/next, first/last, a window around the current page (heightened); `on_change(page)` |
@@ -412,7 +443,7 @@ sp_pagination(total=240, current=State.page, on_change=State.set_page, show_tota
412
443
  | `sp_empty`, `sp_result` | Empty state; outcome with a drawn round mark |
413
444
  | `sp_textarea`, `sp_input_number` | On the `SpInput` contract; `on_change` receives the value (text or number) |
414
445
 
415
- | Level B (Radix primitives) | |
446
+ | Overlays (`<dialog>`, Popover API) | |
416
447
  |---|---|
417
448
  | `sp_modal`, `sp_drawer` | Dialog on a card frame over a hatched backdrop; drawer from any edge |
418
449
  | `sp_popover`, `sp_tooltip` | Anchored content; tooltip on hover or keyboard focus |
@@ -420,10 +451,15 @@ sp_pagination(total=240, current=State.page, on_change=State.set_page, show_tota
420
451
  | `sp_dropdown_menu` | Commands with shortcuts, separators and labels; `on_select(key)` |
421
452
  | `sp_toast`, `sp_toaster` | Notices that stack in a corner; `error`/`warning` are announced assertively |
422
453
 
423
- Behaviour (focus trapping, keyboard, dismissal, positioning, ARIA) is Radix's, at the versions
424
- Reflex already installs. Overlays render in a portal at the end of `<body>`, outside any
425
- `silverpoint_palette` section, so give them `palette` directly. A string `trigger` becomes
426
- `sp_trigger(...)`, the drawn button that can forward Radix's props (`sp_button` cannot).
454
+ Behaviour is the platform's: `showModal()` for the modal and the drawer (focus stays inside, Escape
455
+ and the backdrop close it unless `dismissible=False`), the Popover API for the rest (light
456
+ dismiss), keyboard and placement from `@silverpoint/core` (APG listbox and menu, typeahead, flip and
457
+ shift). Overlays render in place (the top layer, no portal), so a section's palette reaches them.
458
+ Sides are logical (`start`/`end`) and mirror in right-to-left text. An overlay clones its `trigger`
459
+ with its ARIA and a toggling click, so the trigger must keep the props it is given: a native
460
+ `rx.el.button`, or `sp_trigger(...)`, the drawn button strings become (`sp_button` drops them in
461
+ silverpoint 0.7.0). `sp_trigger` does not read the provider: give it `ground`, `substrate`, `mode`
462
+ and `palette`.
427
463
 
428
464
  ```python
429
465
  sp_modal(
@@ -442,15 +478,15 @@ sp_toaster(sp_toast("Saved", State.text, kind="success", open=State.toast_open,
442
478
 
443
479
  ## Timeline
444
480
 
445
- ```bash
446
- pip install "reflex-silverpoint-react[timeline]" # adds reflex-knightlab-timeline
447
- ```
481
+ The npm `SpTimeline` of `@silverpoint/react/timeline`. TimelineJS (`@knight-lab/timelinejs` 3.9.13)
482
+ is an npm dependency of this component: Reflex installs it when a page uses `sp_timeline`, and no
483
+ Python extra is needed. If it cannot be loaded, the component warns `SP025` and renders `fallback`.
448
484
 
449
485
  ```python
450
486
  from reflex_silverpoint_react import sp_timeline
451
487
 
452
488
  sp_timeline(
453
- DATA, # TimelineJS data: title, events, eras (or a TimelineData)
489
+ DATA, # TimelineJS data: title, events, eras (or any object with to_dict())
454
490
  height=560,
455
491
  ground="silverpoint",
456
492
  substrate="cream",
@@ -532,10 +568,35 @@ The exported SVG carries its own ground colours, so it renders the same outside
532
568
  - Accessors are field names (strings). The JavaScript API also accepts functions; from Python, shape
533
569
  your rows instead.
534
570
 
571
+ ## Use with AI
572
+
573
+ An assistant writes better `reflex-silverpoint-react` code with the **`reflex-silverpoint` skill**
574
+ ([`skills/reflex-silverpoint/`](skills/reflex-silverpoint/SKILL.md)): the builders and their
575
+ snake_case props, State patterns, event payloads, the provider and palettes, composed components and
576
+ overlays, the dashboard and the timeline. Its tables are generated from the package, and every Python
577
+ example in it is imported and rendered by the tests.
578
+
579
+ In Claude Code, the plugin installs the skill together with the hosted silverpoint MCP server
580
+ (`https://silverpointweb.vercel.app/mcp`), which recommends charts, checks props and draws a chart
581
+ as SVG before you write the code:
582
+
583
+ ```text
584
+ /plugin marketplace add ecrespo/reflex-silverpoint-react
585
+ /plugin install reflex-silverpoint@reflex-silverpoint
586
+ ```
587
+
588
+ The MCP server alone: `claude mcp add --transport http silverpoint https://silverpointweb.vercel.app/mcp`.
589
+
590
+ [`reflex-catalog.json`](reflex-catalog.json) is this package's catalog for agents: every chart and
591
+ component builder with its props (Python name, JS name and type), the deprecated arguments it still
592
+ accepts, the helpers, the package version and the silverpoint version it wraps. silverpoint's agent
593
+ catalog joins it, so its MCP tools answer with the Reflex names too. `scripts/export_catalog.py`
594
+ writes it, CI fails when it is stale, and each GitHub release carries it.
595
+
535
596
  ## Demo app
536
597
 
537
598
  ```bash
538
- uv venv && uv pip install -e ".[timeline]"
599
+ uv venv && uv pip install -e .
539
600
  cd silverpoint_react_demo
540
601
  uv run reflex run
541
602
  ```
@@ -1,7 +1,8 @@
1
1
  """reflex-silverpoint-react: silverpoint charts and UI components for Reflex.
2
2
 
3
3
  Charts and interface components drawn in the manner of a Renaissance silverpoint drawing,
4
- wrapping ``@silverpoint/react``.
4
+ wrapping ``@silverpoint/react`` 0.8.0: the 60 charts, the dashboard, the 38 UI, composed and overlay
5
+ components, the palettes and the Knight Lab timeline.
5
6
  """
6
7
 
7
8
  from .base import (
@@ -11,6 +12,7 @@ from .base import (
11
12
  GroundName,
12
13
  SilverpointChart,
13
14
  SilverpointProvider,
15
+ silverpoint_palette,
14
16
  silverpoint_provider,
15
17
  )
16
18
  from .catalog import CHARTS, COMMON_PROPS, FAMILIES, ChartInfo, PropDoc, chart_by_name, chart_by_slug
@@ -138,6 +140,18 @@ from .charts import (
138
140
  wind_rose,
139
141
  )
140
142
  from .composed import (
143
+ SpAvatar,
144
+ SpAvatarGroup,
145
+ SpBreadcrumb,
146
+ SpCollapse,
147
+ SpCollapseItem,
148
+ SpDescriptions,
149
+ SpEmpty,
150
+ SpResult,
151
+ SpStatistic,
152
+ SpTable,
153
+ SpTextarea,
154
+ SpTimelineList,
141
155
  sort_rows,
142
156
  sp_avatar,
143
157
  sp_avatar_group,
@@ -165,6 +179,15 @@ from .dashboard import (
165
179
  )
166
180
  from .helpers import chart_ref, download_svg, get_geometry, get_svg, tooltip_template
167
181
  from .overlays import (
182
+ SpDrawer,
183
+ SpDropdownMenu,
184
+ SpModal,
185
+ SpPopover,
186
+ SpSelect,
187
+ SpToast,
188
+ SpToaster,
189
+ SpTooltip,
190
+ SpTrigger,
168
191
  sp_drawer,
169
192
  sp_dropdown_menu,
170
193
  sp_modal,
@@ -176,13 +199,15 @@ from .overlays import (
176
199
  sp_trigger,
177
200
  )
178
201
  from .palette import (
202
+ PALETTE_JS_FIELDS,
203
+ PALETTE_PAIRS,
179
204
  PALETTE_PROPERTIES,
180
205
  PALETTES,
181
206
  Palette,
182
207
  check_palette,
183
208
  contrast_ratio,
184
209
  palette_css,
185
- silverpoint_palette,
210
+ palette_prop,
186
211
  )
187
212
  from .surfaces import (
188
213
  SpGlyph,
@@ -194,7 +219,7 @@ from .surfaces import (
194
219
  sp_pagination,
195
220
  sp_surface,
196
221
  )
197
- from .timeline import sp_timeline, timeline_available
222
+ from .timeline import TIMELINEJS_VERSION, SpTimeline, sp_timeline, timeline_available
198
223
  from .ui import (
199
224
  SILVERPOINT_UI_STYLESHEET,
200
225
  SilverpointUi,
@@ -254,11 +279,14 @@ __all__ = [
254
279
  "DASHBOARD_DEFAULTS",
255
280
  "FAMILIES",
256
281
  "PALETTES",
282
+ "PALETTE_JS_FIELDS",
283
+ "PALETTE_PAIRS",
257
284
  "PALETTE_PROPERTIES",
258
285
  "SILVERPOINT_LIBRARY",
259
286
  "SILVERPOINT_STYLESHEETS",
260
287
  "SILVERPOINT_UI_STYLESHEET",
261
288
  "SILVERPOINT_VERSION",
289
+ "TIMELINEJS_VERSION",
262
290
  "UI_COMMON_PROPS",
263
291
  "UI_COMPONENTS",
264
292
  "UI_DEMOS",
@@ -321,27 +349,49 @@ __all__ = [
321
349
  "SilverpointUi",
322
350
  "SlopeChart",
323
351
  "SpAlert",
352
+ "SpAvatar",
353
+ "SpAvatarGroup",
324
354
  "SpBadge",
355
+ "SpBreadcrumb",
325
356
  "SpButton",
326
357
  "SpCard",
327
358
  "SpCheckbox",
359
+ "SpCollapse",
360
+ "SpCollapseItem",
361
+ "SpDescriptions",
328
362
  "SpDivider",
363
+ "SpDrawer",
364
+ "SpDropdownMenu",
365
+ "SpEmpty",
329
366
  "SpGlyph",
330
367
  "SpInput",
331
368
  "SpInputNumber",
369
+ "SpModal",
332
370
  "SpPagination",
371
+ "SpPopover",
333
372
  "SpProgress",
334
373
  "SpRadioGroup",
335
374
  "SpRate",
375
+ "SpResult",
336
376
  "SpSegmented",
377
+ "SpSelect",
337
378
  "SpSkeleton",
338
379
  "SpSlider",
380
+ "SpStatistic",
339
381
  "SpSteps",
340
382
  "SpSurface",
341
383
  "SpSwitch",
342
384
  "SpTabPanel",
385
+ "SpTable",
343
386
  "SpTabs",
344
387
  "SpTag",
388
+ "SpTextarea",
389
+ "SpTimeline",
390
+ "SpTimelineList",
391
+ "SpToast",
392
+ "SpToaster",
393
+ "SpTooltip",
394
+ "SpTrigger",
345
395
  "SparklineRows",
346
396
  "SquarifiedTreemap",
347
397
  "StackedBarChart",
@@ -405,6 +455,7 @@ __all__ = [
405
455
  "network_node",
406
456
  "orbit_chart",
407
457
  "palette_css",
458
+ "palette_prop",
408
459
  "parallel_coordinates_chart",
409
460
  "polar_bar_chart",
410
461
  "polar_line_chart",
@@ -0,0 +1,63 @@
1
+ /* reflex-silverpoint-react — sp_trigger: a native <button> drawn as SpButton, that keeps every prop.
2
+ *
3
+ * An overlay of @silverpoint/react clones its trigger with aria-haspopup, aria-expanded,
4
+ * aria-controls, onPointerDown and onClick (useTrigger, REQ-500). SpButton 0.7.0 keeps only its own
5
+ * props, so those would be lost on it; this button renders the very tree @silverpoint/core's
6
+ * uiButtonView builds (resolveUi resolves ground, substrate, mode, size, frame variant and palette)
7
+ * and adds everything else it is given to the native element.
8
+ */
9
+ const SP_TRIGGER_ATTRS = { class: "className", for: "htmlFor", readonly: "readOnly", tabindex: "tabIndex" };
10
+
11
+ function spTriggerStyle(text) {
12
+ const out = {};
13
+ for (const declaration of (text || "").split(";")) {
14
+ const colon = declaration.indexOf(":");
15
+ if (colon > 0) out[declaration.slice(0, colon).trim()] = declaration.slice(colon + 1).trim();
16
+ }
17
+ return out;
18
+ }
19
+
20
+ function spTriggerNode(node, content, extra) {
21
+ if ("text" in node) return node.text;
22
+ if ("slot" in node) return node.slot === "content" ? content : null;
23
+ const props = {};
24
+ for (const [name, value] of Object.entries(node.attrs)) {
25
+ if (value === undefined) continue;
26
+ props[SP_TRIGGER_ATTRS[name] || name] = name === "style" ? spTriggerStyle(value) : value;
27
+ }
28
+ if (extra) {
29
+ const { style, ...rest } = extra;
30
+ Object.assign(props, rest);
31
+ if (style) props.style = { ...(props.style || {}), ...style };
32
+ }
33
+ return createElement(node.tag, props, ...node.children.map((child) => spTriggerNode(child, content)));
34
+ }
35
+
36
+ function useSpTriggerForced() {
37
+ const [forced, setForced] = useState(false);
38
+ useEffect(() => {
39
+ if (typeof matchMedia !== "function") return undefined;
40
+ const query = matchMedia(FORCED_PRECISION_QUERY);
41
+ const update = () => setForced(query.matches);
42
+ update();
43
+ query.addEventListener?.("change", update);
44
+ return () => query.removeEventListener?.("change", update);
45
+ }, []);
46
+ return forced;
47
+ }
48
+
49
+ const SilverpointTrigger = forwardRef(function SilverpointTrigger(
50
+ { ground, substrate, mode, size, seed, palette, variant, chevron, disabled, label, children, className, id, ...rest },
51
+ ref,
52
+ ) {
53
+ const forcedPrecision = useSpTriggerForced();
54
+ const props = { ground, substrate, mode, size, seed, palette, variant, disabled, label, className, id, type: "button" };
55
+ const resolved = resolveUi(props, { forcedPrecision });
56
+ const text = typeof children === "string" || typeof children === "number" ? String(children) : children == null ? undefined : "·";
57
+ const view = uiButtonView(props, resolved, { text });
58
+ // The chevron sits beside the label, as SpButton's own danger cross does.
59
+ const tree = chevron
60
+ ? { ...view, children: [...view.children, { tag: "svg", attrs: { part: "sp-mark", "data-glyph": "chevronDown", viewBox: "0 0 16 16", "aria-hidden": "true" }, children: [{ tag: "path", attrs: { d: UI_GLYPHS.chevronDown }, children: [] }] }] }
61
+ : view;
62
+ return spTriggerNode(tree, children, { ...rest, ref });
63
+ });