streamlit-schema-editor 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 (38) hide show
  1. streamlit_schema_editor-0.1.0/LICENSE +1 -0
  2. streamlit_schema_editor-0.1.0/PKG-INFO +433 -0
  3. streamlit_schema_editor-0.1.0/README.md +417 -0
  4. streamlit_schema_editor-0.1.0/examples/databricks_mapping.py +197 -0
  5. streamlit_schema_editor-0.1.0/examples/er_diagram.py +74 -0
  6. streamlit_schema_editor-0.1.0/examples/playground.py +369 -0
  7. streamlit_schema_editor-0.1.0/examples/schema_viewer.py +98 -0
  8. streamlit_schema_editor-0.1.0/pyproject.toml +58 -0
  9. streamlit_schema_editor-0.1.0/streamlit_schema_editor/__init__.py +37 -0
  10. streamlit_schema_editor-0.1.0/streamlit_schema_editor/_component.py +50 -0
  11. streamlit_schema_editor-0.1.0/streamlit_schema_editor/api.py +232 -0
  12. streamlit_schema_editor-0.1.0/streamlit_schema_editor/frontend/build/index-DfzQj94y.js +16536 -0
  13. streamlit_schema_editor-0.1.0/streamlit_schema_editor/frontend/build/index-_hash_.css +1 -0
  14. streamlit_schema_editor-0.1.0/streamlit_schema_editor/frontend/package-lock.json +3039 -0
  15. streamlit_schema_editor-0.1.0/streamlit_schema_editor/frontend/package.json +46 -0
  16. streamlit_schema_editor-0.1.0/streamlit_schema_editor/frontend/preview.html +12 -0
  17. streamlit_schema_editor-0.1.0/streamlit_schema_editor/frontend/src/SchemaEditorCanvas.tsx +2638 -0
  18. streamlit_schema_editor-0.1.0/streamlit_schema_editor/frontend/src/components/base-handle.tsx +28 -0
  19. streamlit_schema_editor-0.1.0/streamlit_schema_editor/frontend/src/components/base-node.tsx +47 -0
  20. streamlit_schema_editor-0.1.0/streamlit_schema_editor/frontend/src/components/button-edge.tsx +46 -0
  21. streamlit_schema_editor-0.1.0/streamlit_schema_editor/frontend/src/components/database-schema-node.tsx +83 -0
  22. streamlit_schema_editor-0.1.0/streamlit_schema_editor/frontend/src/components/labeled-handle.tsx +51 -0
  23. streamlit_schema_editor-0.1.0/streamlit_schema_editor/frontend/src/components/ui/button.tsx +52 -0
  24. streamlit_schema_editor-0.1.0/streamlit_schema_editor/frontend/src/components/ui/table.tsx +56 -0
  25. streamlit_schema_editor-0.1.0/streamlit_schema_editor/frontend/src/global.css +198 -0
  26. streamlit_schema_editor-0.1.0/streamlit_schema_editor/frontend/src/index.tsx +63 -0
  27. streamlit_schema_editor-0.1.0/streamlit_schema_editor/frontend/src/lib/utils.ts +6 -0
  28. streamlit_schema_editor-0.1.0/streamlit_schema_editor/frontend/src/preview.tsx +126 -0
  29. streamlit_schema_editor-0.1.0/streamlit_schema_editor/frontend/src/vite-env.d.ts +1 -0
  30. streamlit_schema_editor-0.1.0/streamlit_schema_editor/frontend/tsconfig.json +21 -0
  31. streamlit_schema_editor-0.1.0/streamlit_schema_editor/frontend/vite.config.ts +43 -0
  32. streamlit_schema_editor-0.1.0/streamlit_schema_editor/py.typed +1 -0
  33. streamlit_schema_editor-0.1.0/streamlit_schema_editor/pyproject.toml +8 -0
  34. streamlit_schema_editor-0.1.0/streamlit_schema_editor/types.py +110 -0
  35. streamlit_schema_editor-0.1.0/tests/fixtures/e2e_app.py +66 -0
  36. streamlit_schema_editor-0.1.0/tests/smoke_test.py +35 -0
  37. streamlit_schema_editor-0.1.0/tests/test_api.py +238 -0
  38. streamlit_schema_editor-0.1.0/tests/test_component_e2e.py +162 -0
@@ -0,0 +1 @@
1
+ YOUR LICENSE HERE
@@ -0,0 +1,433 @@
1
+ Metadata-Version: 2.4
2
+ Name: streamlit-schema-editor
3
+ Version: 0.1.0
4
+ Summary: Streamlit custom component for rendering and editing schema graphs
5
+ Keywords: streamlit,schema,er-diagram,lineage,metadata
6
+ Author: Parth Mishra
7
+ Author-email: Parth Mishra <pmishraworld@mac.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Requires-Dist: streamlit>=1.51
11
+ Requires-Python: >=3.11
12
+ Project-URL: Homepage, https://github.com/parthmishra/streamlit-schema-editor
13
+ Project-URL: Repository, https://github.com/parthmishra/streamlit-schema-editor
14
+ Project-URL: Issues, https://github.com/parthmishra/streamlit-schema-editor/issues
15
+ Description-Content-Type: text/markdown
16
+
17
+ # streamlit-schema-editor
18
+
19
+ Streamlit custom component for viewing and editing schema, ER, and source-to-target
20
+ mapping graphs with React Flow and Streamlit Custom Components v2.
21
+
22
+ ## Installation
23
+
24
+ ```sh
25
+ uv pip install streamlit-schema-editor
26
+ ```
27
+
28
+ ## What It Supports
29
+
30
+ - schema viewing with table and column metadata
31
+ - source-to-target mapping with interactive relationship creation and deletion
32
+ - inline column editing for `name` and `data_type`
33
+ - optional edge action button for relationship inspection or custom workflows
34
+ - read-only or editable canvases
35
+ - validation styling for tables, columns, and relationships
36
+ - metadata passthrough on tables, columns, and relationships
37
+ - structured `event` + `event_context` payloads for Streamlit-side workflows
38
+
39
+ ## Usage
40
+
41
+ ```python
42
+ import streamlit as st
43
+
44
+ from streamlit_schema_editor import streamlit_schema_editor
45
+
46
+
47
+ if "tables" not in st.session_state:
48
+ st.session_state.tables = [
49
+ {
50
+ "id": "crm_customer",
51
+ "label": "crm_customer",
52
+ "metadata": {"system": "crm"},
53
+ "columns": [
54
+ {"id": "customer_id", "name": "customer_id", "data_type": "uuid"},
55
+ {"id": "cust_name", "name": "cust_name", "data_type": "varchar"},
56
+ ],
57
+ },
58
+ {
59
+ "id": "dim_customer",
60
+ "label": "dim_customer",
61
+ "metadata": {"system": "warehouse"},
62
+ "columns": [
63
+ {"id": "customer_key", "name": "customer_key", "data_type": "bigint"},
64
+ {"id": "customer_name", "name": "customer_name", "data_type": "varchar"},
65
+ ],
66
+ },
67
+ ]
68
+
69
+ if "relationships" not in st.session_state:
70
+ st.session_state.relationships = [
71
+ {
72
+ "id": "rel::crm_customer::cust_name::dim_customer::customer_name",
73
+ "source_table": "crm_customer",
74
+ "source_column": "cust_name",
75
+ "target_table": "dim_customer",
76
+ "target_column": "customer_name",
77
+ "validation": {
78
+ "status": "loading",
79
+ "summary": "Awaiting warehouse validation for this mapping.",
80
+ },
81
+ "metadata": {
82
+ "rule_id": "MAP-1024",
83
+ "sql_expression": "UPPER(TRIM(cust_name))",
84
+ },
85
+ }
86
+ ]
87
+
88
+ value = streamlit_schema_editor(
89
+ st.session_state.tables,
90
+ st.session_state.relationships,
91
+ height=700,
92
+ show_controls=True,
93
+ max_connections_per_handle=2,
94
+ key="schema-editor",
95
+ )
96
+
97
+ st.session_state.tables = value["tables"]
98
+ st.session_state.relationships = value["relationships"]
99
+
100
+ st.write(value["event"])
101
+ st.json(value["event_context"])
102
+ ```
103
+
104
+ ## API
105
+
106
+ ```python
107
+ streamlit_schema_editor(
108
+ tables,
109
+ relationships,
110
+ *,
111
+ groups=None,
112
+ height=600,
113
+ fit_view=True,
114
+ editable=True,
115
+ connectable=None,
116
+ draggable=None,
117
+ deletable=None,
118
+ show_controls=False,
119
+ show_arrowheads=True,
120
+ show_edge_button=False,
121
+ show_column_count_badge=True,
122
+ show_groups=True,
123
+ group_layout="manual",
124
+ group_order=None,
125
+ table_layout_within_group="manual",
126
+ show_validation=True,
127
+ validation_refresh_key=None,
128
+ column_type_options=None,
129
+ allow_zoom=True,
130
+ allow_duplicate_edges=False,
131
+ max_connections_per_handle=None,
132
+ max_incoming_connections_per_handle=None,
133
+ max_outgoing_connections_per_handle=None,
134
+ key=None,
135
+ )
136
+ ```
137
+
138
+ `editable` acts as the default for `connectable` and `deletable`. Dragging is
139
+ enabled by default even for read-only canvases, and `editable` also enables
140
+ inline column editing, row add/remove controls, and column edit events. Override
141
+ the interaction flags individually when you need a mixed mode.
142
+
143
+ Use `show_arrowheads=False` for ER-style views where you want the canvas to read
144
+ more like an undirected diagram, and `show_column_count_badge=False` when long
145
+ table names need the extra header space. The legacy aliases
146
+ `max_incoming_per_target` and `max_outgoing_per_source` are still accepted for
147
+ backward compatibility, but the generic connection-limit parameters are the
148
+ preferred public API.
149
+
150
+ `show_edge_button` is optional and defaults to `False`. Turn it on only when you
151
+ want a per-relationship action affordance in the middle of the edge.
152
+
153
+ Use `groups` plus per-table `group_id` when you want optional labeled containers
154
+ such as `Source` / `Target`, database lanes, or bronze/silver/gold layers.
155
+ `show_groups` controls whether those containers are currently rendered without
156
+ requiring you to change the underlying table or relationship payload.
157
+
158
+ Use `group_layout="columns"` or `group_layout="rows"` when you want the
159
+ component to place groups automatically without manually setting every group
160
+ `position`. Use `group_order` to control that automatic order, and
161
+ `table_layout_within_group="stack"` to vertically arrange grouped tables for
162
+ lane-style views. Automatic layout modes intentionally own placement, so they
163
+ are best paired with read-only or lightly interactive canvases.
164
+
165
+ `show_validation` controls whether validation-derived colors, badges, and
166
+ summaries are rendered. If you want to force those visuals to refresh without
167
+ changing the schema payload, change `validation_refresh_key` between reruns.
168
+
169
+ ### Edge Button
170
+
171
+ Enable the button when you want relationship inspection or a custom workflow
172
+ trigger from the canvas:
173
+
174
+ ```python
175
+ value = streamlit_schema_editor(
176
+ tables,
177
+ relationships,
178
+ show_edge_button=True,
179
+ key="schema-editor-with-edge-actions",
180
+ )
181
+
182
+ if value["event"] == "edge_details_requested":
183
+ relationship_id = (value["event_context"] or {}).get("relationship_id")
184
+ st.write(f"Inspect relationship: {relationship_id}")
185
+ ```
186
+
187
+ When enabled, the edge button can show:
188
+
189
+ - `relationship["label"]` when present
190
+ - `i` as a compact fallback for inspection
191
+
192
+ This button is useful for cases like opening a details panel, surfacing lineage
193
+ metadata, showing validation context, or launching a relationship editor. For
194
+ pure ER or schema-viewing use cases, leave it disabled.
195
+
196
+ ### Return Value
197
+
198
+ - `tables`: current table list with updated positions
199
+ - `groups`: current group list with updated positions and sizes
200
+ - `relationships`: current relationships after connect/delete actions
201
+ - `selection`: current selected table, column, and relationship ids
202
+ - `event`: semantic event name or `None`
203
+ - `event_context`: structured payload for the last event
204
+
205
+ ### Event Names
206
+
207
+ - `selection_changed`
208
+ - `node_moved`
209
+ - `table_deleted`
210
+ - `column_created`
211
+ - `column_updated`
212
+ - `column_deleted`
213
+ - `relationship_created`
214
+ - `relationship_deleted`
215
+ - `relationship_rejected`
216
+ - `edge_details_requested`
217
+
218
+ `edge_details_requested` is only emitted when `show_edge_button=True`.
219
+
220
+ ### Schema Fields
221
+
222
+ Tables, columns, and relationships support generic `metadata` passthrough. Tables,
223
+ columns, and relationships can also opt into a top-level `validation` object.
224
+ Tables can optionally declare a single `group_id`, and groups are defined
225
+ separately with `id`, `label`, `position`, `width`, `height`, and `metadata`:
226
+
227
+ ```python
228
+ {
229
+ "validation": {
230
+ "status": "error",
231
+ "code": "missing_column",
232
+ "summary": "Column not found in upstream schema.",
233
+ "detail": "Latest introspection did not return crm_customer.region_code.",
234
+ }
235
+ }
236
+ ```
237
+
238
+ Use `validation` for generic UI state that the component understands, and keep
239
+ app-specific semantics in `metadata`. For example, SQL expressions, lineage
240
+ attributes, ownership, or workflow IDs should live in `metadata`, not as
241
+ first-class component fields.
242
+
243
+ ### Inline Column Editing
244
+
245
+ When `editable=True`, table nodes support lightweight inline schema editing:
246
+
247
+ - click a column name to edit `column["name"]`
248
+ - click a data type to edit `column["data_type"]`
249
+ - use the placeholder row at the bottom of a table to add a column row
250
+ - use the `×` control on a row to remove that column
251
+
252
+ Column ids remain stable and are not edited inline. If you delete a column, any
253
+ attached relationships are removed from the graph at the same time.
254
+
255
+ If you pass `column_type_options`, the inline data-type editor uses an in-node
256
+ combobox with suggested values while still allowing custom typed entries such as
257
+ `varchar(255)`.
258
+
259
+ ### Common Recipes
260
+
261
+ Viewer-style canvas with dragging enabled but editing disabled:
262
+
263
+ ```python
264
+ value = streamlit_schema_editor(
265
+ tables,
266
+ relationships,
267
+ editable=False,
268
+ draggable=True,
269
+ connectable=False,
270
+ deletable=False,
271
+ show_controls=True,
272
+ key="schema-viewer",
273
+ )
274
+ ```
275
+
276
+ Mapping editor with inline column editing and relationship inspection:
277
+
278
+ ```python
279
+ value = streamlit_schema_editor(
280
+ tables,
281
+ relationships,
282
+ editable=True,
283
+ show_edge_button=True,
284
+ show_controls=True,
285
+ key="mapping-editor",
286
+ )
287
+ ```
288
+
289
+ Toggle labeled source / target lanes on and off at runtime:
290
+
291
+ ```python
292
+ groups = [
293
+ {"id": "source", "label": "Source", "width": 420, "height": 640},
294
+ {"id": "target", "label": "Target", "width": 380, "height": 640},
295
+ ]
296
+
297
+ tables = [
298
+ {**source_table, "group_id": "source"},
299
+ {**target_table, "group_id": "target"},
300
+ ]
301
+
302
+ show_groups = st.toggle("Show groups", value=True)
303
+
304
+ value = streamlit_schema_editor(
305
+ tables,
306
+ relationships,
307
+ groups=groups,
308
+ show_groups=show_groups,
309
+ group_layout="columns",
310
+ group_order=["source", "target"],
311
+ table_layout_within_group="stack",
312
+ key="schema-editor-groups",
313
+ )
314
+ ```
315
+
316
+ Hide validation visuals until the user opts in:
317
+
318
+ ```python
319
+ show_validation = st.toggle("Show validation", value=True)
320
+
321
+ value = streamlit_schema_editor(
322
+ tables,
323
+ relationships,
324
+ show_validation=show_validation,
325
+ key="schema-editor-validation-toggle",
326
+ )
327
+ ```
328
+
329
+ Force validation visuals to refresh on demand:
330
+
331
+ ```python
332
+ if "validation_refresh_nonce" not in st.session_state:
333
+ st.session_state.validation_refresh_nonce = 0
334
+
335
+ if st.button("Refresh validation visuals"):
336
+ st.session_state.validation_refresh_nonce += 1
337
+
338
+ value = streamlit_schema_editor(
339
+ tables,
340
+ relationships,
341
+ show_validation=True,
342
+ validation_refresh_key=st.session_state.validation_refresh_nonce,
343
+ key="schema-editor-validation-refresh",
344
+ )
345
+ ```
346
+
347
+ Use known type options while still allowing custom values:
348
+
349
+ ```python
350
+ value = streamlit_schema_editor(
351
+ tables,
352
+ relationships,
353
+ editable=True,
354
+ column_type_options=[
355
+ "uuid",
356
+ "bigint",
357
+ "integer",
358
+ "varchar",
359
+ "text",
360
+ "timestamp",
361
+ "json",
362
+ ],
363
+ key="schema-editor-type-options",
364
+ )
365
+ ```
366
+
367
+ Handle inline column edit events in Streamlit:
368
+
369
+ ```python
370
+ value = streamlit_schema_editor(
371
+ tables,
372
+ relationships,
373
+ editable=True,
374
+ key="schema-editor-events",
375
+ )
376
+
377
+ if value["event"] == "column_created":
378
+ st.success(f"Added column: {(value['event_context'] or {}).get('column_id')}")
379
+
380
+ if value["event"] == "column_updated":
381
+ context = value["event_context"] or {}
382
+ st.info(
383
+ "Updated "
384
+ f"{context.get('table_id')}.{context.get('column_id')} "
385
+ f"fields={context.get('fields')}"
386
+ )
387
+
388
+ if value["event"] == "column_deleted":
389
+ context = value["event_context"] or {}
390
+ st.warning(
391
+ "Deleted "
392
+ f"{context.get('table_id')}.{context.get('column_id')} "
393
+ f"and removed relationships={context.get('deleted_relationship_ids')}"
394
+ )
395
+ ```
396
+
397
+ ## Examples
398
+
399
+ Run the examples from the project root:
400
+
401
+ ```sh
402
+ uv run streamlit run example.py
403
+ uv run streamlit run examples/playground.py
404
+ uv run streamlit run examples/schema_viewer.py
405
+ uv run streamlit run examples/er_diagram.py
406
+ uv run streamlit run examples/databricks_mapping.py
407
+ ```
408
+
409
+ - `example.py`: full source-to-target mapping demo
410
+ - `examples/playground.py`: interactive playground for toggling runtime options, grouping visibility, and validation live
411
+ - `examples/schema_viewer.py`: read-only schema browser
412
+ - `examples/er_diagram.py`: ER-style relationship view with arrowheads hidden
413
+ - `examples/databricks_mapping.py`: Databricks-inspired source-to-target mapping demo with labeled group lanes
414
+
415
+ ## Development
416
+
417
+ Build the frontend first, then build the Python package:
418
+
419
+ ```sh
420
+ cd streamlit_schema_editor/frontend
421
+ npm install
422
+ npm run build
423
+ cd ../..
424
+ uv build
425
+ ```
426
+
427
+ ## Testing
428
+
429
+ Run the Python tests:
430
+
431
+ ```sh
432
+ uv run pytest
433
+ ```