reflex-mermaidjs 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.
Files changed (23) hide show
  1. reflex_mermaidjs-0.1.0/LICENSE +21 -0
  2. reflex_mermaidjs-0.1.0/PKG-INFO +261 -0
  3. reflex_mermaidjs-0.1.0/README.md +233 -0
  4. reflex_mermaidjs-0.1.0/custom_components/reflex_mermaidjs/__init__.py +95 -0
  5. reflex_mermaidjs-0.1.0/custom_components/reflex_mermaidjs/actions.py +88 -0
  6. reflex_mermaidjs-0.1.0/custom_components/reflex_mermaidjs/constants.py +114 -0
  7. reflex_mermaidjs-0.1.0/custom_components/reflex_mermaidjs/examples.json +634 -0
  8. reflex_mermaidjs-0.1.0/custom_components/reflex_mermaidjs/examples.py +48 -0
  9. reflex_mermaidjs-0.1.0/custom_components/reflex_mermaidjs/markdown.py +55 -0
  10. reflex_mermaidjs-0.1.0/custom_components/reflex_mermaidjs/mermaid_diagram.jsx +842 -0
  11. reflex_mermaidjs-0.1.0/custom_components/reflex_mermaidjs/mermaidjs.py +265 -0
  12. reflex_mermaidjs-0.1.0/custom_components/reflex_mermaidjs/mermaidjs.pyi +237 -0
  13. reflex_mermaidjs-0.1.0/custom_components/reflex_mermaidjs/py.typed +0 -0
  14. reflex_mermaidjs-0.1.0/custom_components/reflex_mermaidjs/urls.py +164 -0
  15. reflex_mermaidjs-0.1.0/custom_components/reflex_mermaidjs.egg-info/PKG-INFO +261 -0
  16. reflex_mermaidjs-0.1.0/custom_components/reflex_mermaidjs.egg-info/SOURCES.txt +21 -0
  17. reflex_mermaidjs-0.1.0/custom_components/reflex_mermaidjs.egg-info/dependency_links.txt +1 -0
  18. reflex_mermaidjs-0.1.0/custom_components/reflex_mermaidjs.egg-info/requires.txt +1 -0
  19. reflex_mermaidjs-0.1.0/custom_components/reflex_mermaidjs.egg-info/top_level.txt +1 -0
  20. reflex_mermaidjs-0.1.0/pyproject.toml +87 -0
  21. reflex_mermaidjs-0.1.0/setup.cfg +4 -0
  22. reflex_mermaidjs-0.1.0/tests/test_component.py +134 -0
  23. reflex_mermaidjs-0.1.0/tests/test_urls.py +79 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ernesto Crespo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,261 @@
1
+ Metadata-Version: 2.4
2
+ Name: reflex-mermaidjs
3
+ Version: 0.1.0
4
+ Summary: Reflex custom component for mermaid-js: flowcharts, sequence, class, ER, gantt, mindmap and 30+ diagram types from text, with pan & zoom, themes, export and events
5
+ Author-email: Ernesto Crespo <ecrespo@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/ecrespo/reflex-mermaidjs
8
+ Project-URL: Source, https://github.com/ecrespo/reflex-mermaidjs
9
+ Project-URL: Issues, https://github.com/ecrespo/reflex-mermaidjs/issues
10
+ Keywords: reflex,reflex-custom-components,mermaid,mermaid-js,diagrams,flowchart,uml
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Web Environment
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Multimedia :: Graphics
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: reflex>=0.9.11
27
+ Dynamic: license-file
28
+
29
+ # reflex-mermaidjs
30
+
31
+ [mermaid-js](https://mermaid.js.org) diagrams for [Reflex](https://reflex.dev): flowcharts, sequence, class, state, ER, gantt, mindmap, architecture, C4, sankey, kanban, venn, wardley, railroad and 30+ other diagram types, generated from text the way markdown is.
32
+
33
+ - Wraps **mermaid 12.0.0** (ELK layout bundled), plus the **tidy-tree** layout and **ZenUML** plugins
34
+ - Every mermaid option as a typed prop: `theme`, `look` (`classic` / `handDrawn` / `neo`), `layout`, `security_level`, `theme_variables`, raw `config`...
35
+ - `appearance="dark"` automatic dark themes (same behaviour as mermaid.live)
36
+ - **Pan & zoom** (wheel, drag, double-click to fit) with a floating toolbar and optional dotted grid
37
+ - Events: `on_render`, `on_error`, `on_node_click`, `on_zoom_change`
38
+ - Python actions: `zoom_in`, `zoom_out`, `set_zoom`, `fit_view`, `reset_view`, `fullscreen`, `export_png`, `export_svg`, `copy_svg`, `get_svg`
39
+ - Icons: Iconify `logos` and `mdi` bundled, any other Iconify pack by name, Font Awesome `fa:` icons
40
+ - KaTeX math (`$$...$$`) in labels
41
+ - `rx.markdown` integration: ```` ```mermaid ```` fences become diagrams
42
+ - Share helpers in pure Python: `mermaid_live_url`, `deserialize_state` (mermaid.live `pako:` links), `mermaid_ink_url`, `kroki_url`
43
+ - 36 diagram types of sample diagrams (`get_diagram_examples()`), the same set mermaid.live offers
44
+
45
+ ## Installation
46
+
47
+ ```bash
48
+ pip install reflex-mermaidjs
49
+ # or
50
+ uv add reflex-mermaidjs
51
+ ```
52
+
53
+ Requires `reflex>=0.9.11`. npm dependencies (mermaid, plugins, icons) are installed automatically by Reflex.
54
+
55
+ ## Quick start
56
+
57
+ ```python
58
+ import reflex as rx
59
+ from reflex_mermaidjs import mermaid
60
+
61
+
62
+ def index() -> rx.Component:
63
+ return mermaid(
64
+ """flowchart TD
65
+ A[Christmas] -->|Get money| B(Go shopping)
66
+ B --> C{Let me think}
67
+ C -->|One| D[Laptop]
68
+ C -->|Two| E[iPhone]
69
+ C -->|Three| F[fa:fa-car Car]""",
70
+ theme="forest",
71
+ )
72
+
73
+
74
+ app = rx.App()
75
+ app.add_page(index)
76
+ ```
77
+
78
+ The diagram text can be passed positionally or as `chart=`, and can be a state var — the diagram re-renders when it changes.
79
+
80
+ ## Live editing with state, pan & zoom and events
81
+
82
+ ```python
83
+ import reflex as rx
84
+ from reflex_mermaidjs import mermaid, export_png, fit_view
85
+
86
+
87
+ class State(rx.State):
88
+ code: str = "sequenceDiagram\n Alice->>Bob: Hi Bob\n Bob-->>Alice: Hi Alice"
89
+ diagram_type: str = ""
90
+ error: str = ""
91
+
92
+ @rx.event
93
+ def set_code(self, value: str):
94
+ self.code = value
95
+
96
+ @rx.event
97
+ def rendered(self, event: dict):
98
+ self.diagram_type = event["diagram_type"]
99
+ self.error = ""
100
+
101
+ @rx.event
102
+ def failed(self, event: dict):
103
+ self.error = event["message"]
104
+
105
+ @rx.event
106
+ def clicked(self, event: dict):
107
+ return rx.toast.info(f"Clicked {event['node_id']}")
108
+
109
+
110
+ def index() -> rx.Component:
111
+ return rx.hstack(
112
+ rx.text_area(value=State.code, on_change=State.set_code.debounce(250), width="40%", rows="20"),
113
+ rx.vstack(
114
+ mermaid(
115
+ State.code,
116
+ id="diagram",
117
+ appearance=rx.color_mode_cond("light", "dark"),
118
+ pan_zoom=True,
119
+ grid=True,
120
+ node_click=True,
121
+ error_mode="keep-last",
122
+ on_render=State.rendered,
123
+ on_error=State.failed,
124
+ on_node_click=State.clicked,
125
+ height="600px",
126
+ width="100%",
127
+ ),
128
+ rx.hstack(
129
+ rx.button("Fit", on_click=fit_view("diagram")),
130
+ rx.button("PNG", on_click=export_png("diagram", "diagram.png")),
131
+ rx.text(State.diagram_type),
132
+ ),
133
+ width="60%",
134
+ ),
135
+ )
136
+ ```
137
+
138
+ ## Props
139
+
140
+ | Prop | Type | Description |
141
+ | --- | --- | --- |
142
+ | `chart` | `str` | Diagram definition (front matter and `%%{init}%%` directives are supported) |
143
+ | `config` | `dict` | Raw [MermaidConfig](https://mermaid.js.org/config/schema-docs/config.html) passed to `mermaid.initialize` |
144
+ | `theme` | `default`, `base`, `dark`, `forest`, `neutral`, `neo`, `neo-dark`, `redux`, `redux-dark`, `redux-color`, `redux-dark-color`, `null` | Theme |
145
+ | `look` | `classic`, `handDrawn`, `neo` | Visual look |
146
+ | `layout` | `str` | `dagre`, `elk`, `elk.stress`, `elk.force`, `elk.mrtree`, `elk.radial`, `elk.box`, `elk.rectpacking`, `tidy-tree`... |
147
+ | `security_level` | `strict`, `loose`, `antiscript`, `sandbox` | `loose` enables `click` callbacks and HTML labels |
148
+ | `theme_variables` / `theme_css` | `dict` / `str` | Theme customisation (most useful with `theme="base"`) |
149
+ | `font_family`, `font_size`, `hand_drawn_seed`, `dark_mode`, `html_labels`, `wrap`, `max_text_size`, `max_edges`, `deterministic_ids`, `log_level` | | Same as the mermaid options |
150
+ | `appearance` | `light`, `dark` | With no explicit theme, `dark` uses the dark variant of each diagram type's default theme |
151
+ | `tidy_tree` | `bool` | Register the tidy-tree layout (default `True`) |
152
+ | `zenuml` | `bool` | Register ZenUML eagerly (it is auto-registered when the text starts with `zenuml`) |
153
+ | `font_awesome` | `bool` | Load Font Awesome CSS for `fa:` icons (default `True`) |
154
+ | `icon_packs` | `list[str \| dict]` | Iconify packs. `logos` and `mdi` are bundled; other names load from jsDelivr; or `{"name": ..., "url": ...}` |
155
+ | `pan_zoom` | `bool` | Wheel zoom + drag pan. The component fills its box, so give it a height (defaults to 480px) |
156
+ | `show_controls`, `controls_position` | `bool`, `top-right`... | Floating toolbar (fit, zoom out, zoom in, 100%, fullscreen) |
157
+ | `min_zoom`, `max_zoom`, `zoom_step`, `max_fit_zoom` | `float` | Zoom limits |
158
+ | `fit_on_render` | `bool \| "auto"` | `auto` fits on first render and when the diagram type/size changes a lot |
159
+ | `grid` | `bool` | Dotted background grid (color via the `--mermaid-grid-color` CSS variable) |
160
+ | `center` | `bool` | Center the SVG in static mode |
161
+ | `debounce` | `int` | Debounce re-renders in ms |
162
+ | `error_mode` | `inline`, `keep-last`, `none` | How parse errors are shown |
163
+ | `click_callbacks` | `list[str]` | Callback names used in `click node callback` directives, routed to `on_node_click` |
164
+ | `node_click` | `bool` | Emit `on_node_click` for any node click |
165
+
166
+ ### Events
167
+
168
+ | Event | Payload |
169
+ | --- | --- |
170
+ | `on_render` | `{svg, diagram_type, render_id, render_ms}` |
171
+ | `on_error` | `{message, line, expected}` |
172
+ | `on_node_click` | `{node_id, callback, label, args}` |
173
+ | `on_zoom_change` | `{zoom, x, y}` (debounced) |
174
+
175
+ ## Python actions
176
+
177
+ Any diagram with an `id` can be driven from event handlers or triggers. They return `rx.call_script` events:
178
+
179
+ ```python
180
+ from reflex_mermaidjs import zoom_in, zoom_out, set_zoom, fit_view, reset_view, fullscreen
181
+ from reflex_mermaidjs import export_png, export_svg, copy_svg, get_svg, get_png_data_url
182
+
183
+ rx.button("PNG", on_click=export_png("diagram", "diagram.png", scale=2, background="transparent"))
184
+ rx.button("Send SVG to Python", on_click=get_svg("diagram", State.receive_svg))
185
+ ```
186
+
187
+ ## Markdown
188
+
189
+ ```python
190
+ from reflex_mermaidjs import markdown_with_mermaid, mermaid_component_map
191
+
192
+ markdown_with_mermaid(State.text, mermaid_props={"theme": "neutral"})
193
+ # or merge with your own map
194
+ rx.markdown(State.text, component_map={**mermaid_component_map(), "h1": my_h1})
195
+ ```
196
+
197
+ Non-mermaid code fences keep the regular `rx.code_block` highlighting.
198
+
199
+ ## Sharing helpers
200
+
201
+ ```python
202
+ from reflex_mermaidjs import mermaid_live_url, mermaid_ink_url, kroki_url, deserialize_state
203
+
204
+ mermaid_live_url(code, {"theme": "dark"}) # https://mermaid.live/edit#pako:...
205
+ mermaid_ink_url(code, fmt="img", image_type="png") # server-rendered image
206
+ kroki_url(code, "svg")
207
+ state = deserialize_state("https://mermaid.live/edit#pako:eNp...") # {"code": ..., "mermaid": ...}
208
+ ```
209
+
210
+ ## Icons
211
+
212
+ ```python
213
+ mermaid("""architecture-beta
214
+ group api(logos:aws-lambda)[API]
215
+ service db(logos:postgresql)[Database] in api
216
+ service server(logos:python)[Server] in api
217
+ db:L -- R:server""")
218
+
219
+ mermaid(
220
+ chart,
221
+ icon_packs=["logos", "mdi", "fa7-brands", {"name": "custom", "url": "https://example.com/icons.json"}],
222
+ )
223
+ ```
224
+
225
+ ## Demo app
226
+
227
+ The `mermaidjs_demo/` app is a mermaid.live-style editor built with this component:
228
+
229
+ - **Live editor** — code editor with line numbers, config tab (theme/look/layout/security selectors + JSON), all sample diagrams, history, share dialog (mermaid.live / mermaid.ink / kroki links, import a mermaid.live link, Python and Markdown snippets), PNG/SVG export, hand-drawn/grid/pan-zoom toggles, dark mode
230
+ - **Gallery** — every diagram type rendered live
231
+ - **Features** — themes, looks, layouts, theme variables from state, data-driven charts, events and actions, markdown, icons, math, ZenUML, error handling
232
+ - **API** — props table generated from the source
233
+
234
+ ```bash
235
+ uv sync --all-groups
236
+ cd mermaidjs_demo
237
+ uv run reflex run
238
+ ```
239
+
240
+ ## Development
241
+
242
+ ```bash
243
+ uv sync --all-groups
244
+
245
+ uv run pytest # tests
246
+ uv run ruff check . # lint
247
+ uv run ruff format . # format
248
+ uv run bandit -c pyproject.toml -r . -ll # SAST
249
+
250
+ uv run reflex component build # generates .pyi stubs and builds dist/
251
+ ```
252
+
253
+ The same checks run in CI on every push and pull request — see the
254
+ [Quality](.github/workflows/quality.yml) and
255
+ [Security](.github/workflows/security.yml) workflows. Releases are tag-driven
256
+ and documented in [RELEASING.md](RELEASING.md); the security posture of the
257
+ component is documented in [SECURITY.md](SECURITY.md).
258
+
259
+ ## License
260
+
261
+ MIT © Ernesto Crespo
@@ -0,0 +1,233 @@
1
+ # reflex-mermaidjs
2
+
3
+ [mermaid-js](https://mermaid.js.org) diagrams for [Reflex](https://reflex.dev): flowcharts, sequence, class, state, ER, gantt, mindmap, architecture, C4, sankey, kanban, venn, wardley, railroad and 30+ other diagram types, generated from text the way markdown is.
4
+
5
+ - Wraps **mermaid 12.0.0** (ELK layout bundled), plus the **tidy-tree** layout and **ZenUML** plugins
6
+ - Every mermaid option as a typed prop: `theme`, `look` (`classic` / `handDrawn` / `neo`), `layout`, `security_level`, `theme_variables`, raw `config`...
7
+ - `appearance="dark"` automatic dark themes (same behaviour as mermaid.live)
8
+ - **Pan & zoom** (wheel, drag, double-click to fit) with a floating toolbar and optional dotted grid
9
+ - Events: `on_render`, `on_error`, `on_node_click`, `on_zoom_change`
10
+ - Python actions: `zoom_in`, `zoom_out`, `set_zoom`, `fit_view`, `reset_view`, `fullscreen`, `export_png`, `export_svg`, `copy_svg`, `get_svg`
11
+ - Icons: Iconify `logos` and `mdi` bundled, any other Iconify pack by name, Font Awesome `fa:` icons
12
+ - KaTeX math (`$$...$$`) in labels
13
+ - `rx.markdown` integration: ```` ```mermaid ```` fences become diagrams
14
+ - Share helpers in pure Python: `mermaid_live_url`, `deserialize_state` (mermaid.live `pako:` links), `mermaid_ink_url`, `kroki_url`
15
+ - 36 diagram types of sample diagrams (`get_diagram_examples()`), the same set mermaid.live offers
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ pip install reflex-mermaidjs
21
+ # or
22
+ uv add reflex-mermaidjs
23
+ ```
24
+
25
+ Requires `reflex>=0.9.11`. npm dependencies (mermaid, plugins, icons) are installed automatically by Reflex.
26
+
27
+ ## Quick start
28
+
29
+ ```python
30
+ import reflex as rx
31
+ from reflex_mermaidjs import mermaid
32
+
33
+
34
+ def index() -> rx.Component:
35
+ return mermaid(
36
+ """flowchart TD
37
+ A[Christmas] -->|Get money| B(Go shopping)
38
+ B --> C{Let me think}
39
+ C -->|One| D[Laptop]
40
+ C -->|Two| E[iPhone]
41
+ C -->|Three| F[fa:fa-car Car]""",
42
+ theme="forest",
43
+ )
44
+
45
+
46
+ app = rx.App()
47
+ app.add_page(index)
48
+ ```
49
+
50
+ The diagram text can be passed positionally or as `chart=`, and can be a state var — the diagram re-renders when it changes.
51
+
52
+ ## Live editing with state, pan & zoom and events
53
+
54
+ ```python
55
+ import reflex as rx
56
+ from reflex_mermaidjs import mermaid, export_png, fit_view
57
+
58
+
59
+ class State(rx.State):
60
+ code: str = "sequenceDiagram\n Alice->>Bob: Hi Bob\n Bob-->>Alice: Hi Alice"
61
+ diagram_type: str = ""
62
+ error: str = ""
63
+
64
+ @rx.event
65
+ def set_code(self, value: str):
66
+ self.code = value
67
+
68
+ @rx.event
69
+ def rendered(self, event: dict):
70
+ self.diagram_type = event["diagram_type"]
71
+ self.error = ""
72
+
73
+ @rx.event
74
+ def failed(self, event: dict):
75
+ self.error = event["message"]
76
+
77
+ @rx.event
78
+ def clicked(self, event: dict):
79
+ return rx.toast.info(f"Clicked {event['node_id']}")
80
+
81
+
82
+ def index() -> rx.Component:
83
+ return rx.hstack(
84
+ rx.text_area(value=State.code, on_change=State.set_code.debounce(250), width="40%", rows="20"),
85
+ rx.vstack(
86
+ mermaid(
87
+ State.code,
88
+ id="diagram",
89
+ appearance=rx.color_mode_cond("light", "dark"),
90
+ pan_zoom=True,
91
+ grid=True,
92
+ node_click=True,
93
+ error_mode="keep-last",
94
+ on_render=State.rendered,
95
+ on_error=State.failed,
96
+ on_node_click=State.clicked,
97
+ height="600px",
98
+ width="100%",
99
+ ),
100
+ rx.hstack(
101
+ rx.button("Fit", on_click=fit_view("diagram")),
102
+ rx.button("PNG", on_click=export_png("diagram", "diagram.png")),
103
+ rx.text(State.diagram_type),
104
+ ),
105
+ width="60%",
106
+ ),
107
+ )
108
+ ```
109
+
110
+ ## Props
111
+
112
+ | Prop | Type | Description |
113
+ | --- | --- | --- |
114
+ | `chart` | `str` | Diagram definition (front matter and `%%{init}%%` directives are supported) |
115
+ | `config` | `dict` | Raw [MermaidConfig](https://mermaid.js.org/config/schema-docs/config.html) passed to `mermaid.initialize` |
116
+ | `theme` | `default`, `base`, `dark`, `forest`, `neutral`, `neo`, `neo-dark`, `redux`, `redux-dark`, `redux-color`, `redux-dark-color`, `null` | Theme |
117
+ | `look` | `classic`, `handDrawn`, `neo` | Visual look |
118
+ | `layout` | `str` | `dagre`, `elk`, `elk.stress`, `elk.force`, `elk.mrtree`, `elk.radial`, `elk.box`, `elk.rectpacking`, `tidy-tree`... |
119
+ | `security_level` | `strict`, `loose`, `antiscript`, `sandbox` | `loose` enables `click` callbacks and HTML labels |
120
+ | `theme_variables` / `theme_css` | `dict` / `str` | Theme customisation (most useful with `theme="base"`) |
121
+ | `font_family`, `font_size`, `hand_drawn_seed`, `dark_mode`, `html_labels`, `wrap`, `max_text_size`, `max_edges`, `deterministic_ids`, `log_level` | | Same as the mermaid options |
122
+ | `appearance` | `light`, `dark` | With no explicit theme, `dark` uses the dark variant of each diagram type's default theme |
123
+ | `tidy_tree` | `bool` | Register the tidy-tree layout (default `True`) |
124
+ | `zenuml` | `bool` | Register ZenUML eagerly (it is auto-registered when the text starts with `zenuml`) |
125
+ | `font_awesome` | `bool` | Load Font Awesome CSS for `fa:` icons (default `True`) |
126
+ | `icon_packs` | `list[str \| dict]` | Iconify packs. `logos` and `mdi` are bundled; other names load from jsDelivr; or `{"name": ..., "url": ...}` |
127
+ | `pan_zoom` | `bool` | Wheel zoom + drag pan. The component fills its box, so give it a height (defaults to 480px) |
128
+ | `show_controls`, `controls_position` | `bool`, `top-right`... | Floating toolbar (fit, zoom out, zoom in, 100%, fullscreen) |
129
+ | `min_zoom`, `max_zoom`, `zoom_step`, `max_fit_zoom` | `float` | Zoom limits |
130
+ | `fit_on_render` | `bool \| "auto"` | `auto` fits on first render and when the diagram type/size changes a lot |
131
+ | `grid` | `bool` | Dotted background grid (color via the `--mermaid-grid-color` CSS variable) |
132
+ | `center` | `bool` | Center the SVG in static mode |
133
+ | `debounce` | `int` | Debounce re-renders in ms |
134
+ | `error_mode` | `inline`, `keep-last`, `none` | How parse errors are shown |
135
+ | `click_callbacks` | `list[str]` | Callback names used in `click node callback` directives, routed to `on_node_click` |
136
+ | `node_click` | `bool` | Emit `on_node_click` for any node click |
137
+
138
+ ### Events
139
+
140
+ | Event | Payload |
141
+ | --- | --- |
142
+ | `on_render` | `{svg, diagram_type, render_id, render_ms}` |
143
+ | `on_error` | `{message, line, expected}` |
144
+ | `on_node_click` | `{node_id, callback, label, args}` |
145
+ | `on_zoom_change` | `{zoom, x, y}` (debounced) |
146
+
147
+ ## Python actions
148
+
149
+ Any diagram with an `id` can be driven from event handlers or triggers. They return `rx.call_script` events:
150
+
151
+ ```python
152
+ from reflex_mermaidjs import zoom_in, zoom_out, set_zoom, fit_view, reset_view, fullscreen
153
+ from reflex_mermaidjs import export_png, export_svg, copy_svg, get_svg, get_png_data_url
154
+
155
+ rx.button("PNG", on_click=export_png("diagram", "diagram.png", scale=2, background="transparent"))
156
+ rx.button("Send SVG to Python", on_click=get_svg("diagram", State.receive_svg))
157
+ ```
158
+
159
+ ## Markdown
160
+
161
+ ```python
162
+ from reflex_mermaidjs import markdown_with_mermaid, mermaid_component_map
163
+
164
+ markdown_with_mermaid(State.text, mermaid_props={"theme": "neutral"})
165
+ # or merge with your own map
166
+ rx.markdown(State.text, component_map={**mermaid_component_map(), "h1": my_h1})
167
+ ```
168
+
169
+ Non-mermaid code fences keep the regular `rx.code_block` highlighting.
170
+
171
+ ## Sharing helpers
172
+
173
+ ```python
174
+ from reflex_mermaidjs import mermaid_live_url, mermaid_ink_url, kroki_url, deserialize_state
175
+
176
+ mermaid_live_url(code, {"theme": "dark"}) # https://mermaid.live/edit#pako:...
177
+ mermaid_ink_url(code, fmt="img", image_type="png") # server-rendered image
178
+ kroki_url(code, "svg")
179
+ state = deserialize_state("https://mermaid.live/edit#pako:eNp...") # {"code": ..., "mermaid": ...}
180
+ ```
181
+
182
+ ## Icons
183
+
184
+ ```python
185
+ mermaid("""architecture-beta
186
+ group api(logos:aws-lambda)[API]
187
+ service db(logos:postgresql)[Database] in api
188
+ service server(logos:python)[Server] in api
189
+ db:L -- R:server""")
190
+
191
+ mermaid(
192
+ chart,
193
+ icon_packs=["logos", "mdi", "fa7-brands", {"name": "custom", "url": "https://example.com/icons.json"}],
194
+ )
195
+ ```
196
+
197
+ ## Demo app
198
+
199
+ The `mermaidjs_demo/` app is a mermaid.live-style editor built with this component:
200
+
201
+ - **Live editor** — code editor with line numbers, config tab (theme/look/layout/security selectors + JSON), all sample diagrams, history, share dialog (mermaid.live / mermaid.ink / kroki links, import a mermaid.live link, Python and Markdown snippets), PNG/SVG export, hand-drawn/grid/pan-zoom toggles, dark mode
202
+ - **Gallery** — every diagram type rendered live
203
+ - **Features** — themes, looks, layouts, theme variables from state, data-driven charts, events and actions, markdown, icons, math, ZenUML, error handling
204
+ - **API** — props table generated from the source
205
+
206
+ ```bash
207
+ uv sync --all-groups
208
+ cd mermaidjs_demo
209
+ uv run reflex run
210
+ ```
211
+
212
+ ## Development
213
+
214
+ ```bash
215
+ uv sync --all-groups
216
+
217
+ uv run pytest # tests
218
+ uv run ruff check . # lint
219
+ uv run ruff format . # format
220
+ uv run bandit -c pyproject.toml -r . -ll # SAST
221
+
222
+ uv run reflex component build # generates .pyi stubs and builds dist/
223
+ ```
224
+
225
+ The same checks run in CI on every push and pull request — see the
226
+ [Quality](.github/workflows/quality.yml) and
227
+ [Security](.github/workflows/security.yml) workflows. Releases are tag-driven
228
+ and documented in [RELEASING.md](RELEASING.md); the security posture of the
229
+ component is documented in [SECURITY.md](SECURITY.md).
230
+
231
+ ## License
232
+
233
+ MIT © Ernesto Crespo
@@ -0,0 +1,95 @@
1
+ """reflex-mermaidjs: mermaid-js diagrams for Reflex."""
2
+
3
+ from importlib.metadata import PackageNotFoundError
4
+ from importlib.metadata import version as _package_version
5
+
6
+ from . import actions
7
+ from .actions import (
8
+ copy_svg,
9
+ export_png,
10
+ export_svg,
11
+ fit_view,
12
+ fullscreen,
13
+ get_png_data_url,
14
+ get_svg,
15
+ reset_view,
16
+ set_zoom,
17
+ zoom_in,
18
+ zoom_out,
19
+ )
20
+ from .constants import (
21
+ DIAGRAM_KEYWORDS,
22
+ LAYOUTS,
23
+ LOOKS,
24
+ MERMAID_VERSION,
25
+ SECURITY_LEVELS,
26
+ THEMES,
27
+ )
28
+ from .examples import get_default_example, get_diagram_examples
29
+ from .markdown import markdown_with_mermaid, mermaid_component_map
30
+ from .mermaidjs import (
31
+ ErrorEvent,
32
+ IconPack,
33
+ Mermaid,
34
+ NodeClickEvent,
35
+ RenderEvent,
36
+ ZoomEvent,
37
+ mermaid,
38
+ )
39
+ from .urls import (
40
+ build_state,
41
+ deserialize_state,
42
+ kroki_url,
43
+ mermaid_ink_url,
44
+ mermaid_live_url,
45
+ pako_decode,
46
+ pako_encode,
47
+ serialize_state,
48
+ )
49
+
50
+ # pyproject.toml is the single source of truth for the version; read it back
51
+ # from the installed metadata so the two can never drift.
52
+ try:
53
+ __version__ = _package_version("reflex-mermaidjs")
54
+ except PackageNotFoundError: # pragma: no cover - source tree without an install
55
+ __version__ = "0.0.0.dev0"
56
+
57
+ __all__ = [
58
+ "DIAGRAM_KEYWORDS",
59
+ "LAYOUTS",
60
+ "LOOKS",
61
+ "MERMAID_VERSION",
62
+ "SECURITY_LEVELS",
63
+ "THEMES",
64
+ "ErrorEvent",
65
+ "IconPack",
66
+ "Mermaid",
67
+ "NodeClickEvent",
68
+ "RenderEvent",
69
+ "ZoomEvent",
70
+ "actions",
71
+ "build_state",
72
+ "copy_svg",
73
+ "deserialize_state",
74
+ "export_png",
75
+ "export_svg",
76
+ "fit_view",
77
+ "fullscreen",
78
+ "get_default_example",
79
+ "get_diagram_examples",
80
+ "get_png_data_url",
81
+ "get_svg",
82
+ "kroki_url",
83
+ "markdown_with_mermaid",
84
+ "mermaid",
85
+ "mermaid_component_map",
86
+ "mermaid_ink_url",
87
+ "mermaid_live_url",
88
+ "pako_decode",
89
+ "pako_encode",
90
+ "reset_view",
91
+ "serialize_state",
92
+ "set_zoom",
93
+ "zoom_in",
94
+ "zoom_out",
95
+ ]