sql-dag-flow 0.3.0__tar.gz → 0.4.1__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 (24) hide show
  1. {sql_dag_flow-0.3.0/src/sql_dag_flow.egg-info → sql_dag_flow-0.4.1}/PKG-INFO +22 -12
  2. {sql_dag_flow-0.3.0 → sql_dag_flow-0.4.1}/README.md +21 -11
  3. {sql_dag_flow-0.3.0 → sql_dag_flow-0.4.1}/pyproject.toml +1 -1
  4. sql_dag_flow-0.4.1/src/sql_dag_flow/static/assets/index-DqU54Zg2.css +1 -0
  5. sql_dag_flow-0.4.1/src/sql_dag_flow/static/assets/index-FP7nXXa6.js +84 -0
  6. {sql_dag_flow-0.3.0 → sql_dag_flow-0.4.1}/src/sql_dag_flow/static/index.html +2 -2
  7. {sql_dag_flow-0.3.0 → sql_dag_flow-0.4.1/src/sql_dag_flow.egg-info}/PKG-INFO +22 -12
  8. {sql_dag_flow-0.3.0 → sql_dag_flow-0.4.1}/src/sql_dag_flow.egg-info/SOURCES.txt +2 -2
  9. sql_dag_flow-0.3.0/src/sql_dag_flow/static/assets/index-B6fMDnZ3.js +0 -84
  10. sql_dag_flow-0.3.0/src/sql_dag_flow/static/assets/index-h7gxR8yA.css +0 -1
  11. {sql_dag_flow-0.3.0 → sql_dag_flow-0.4.1}/LICENSE +0 -0
  12. {sql_dag_flow-0.3.0 → sql_dag_flow-0.4.1}/MANIFEST.in +0 -0
  13. {sql_dag_flow-0.3.0 → sql_dag_flow-0.4.1}/setup.cfg +0 -0
  14. {sql_dag_flow-0.3.0 → sql_dag_flow-0.4.1}/src/sql_dag_flow/__init__.py +0 -0
  15. {sql_dag_flow-0.3.0 → sql_dag_flow-0.4.1}/src/sql_dag_flow/main.py +0 -0
  16. {sql_dag_flow-0.3.0 → sql_dag_flow-0.4.1}/src/sql_dag_flow/parser.py +0 -0
  17. {sql_dag_flow-0.3.0 → sql_dag_flow-0.4.1}/src/sql_dag_flow/static/vite.svg +0 -0
  18. {sql_dag_flow-0.3.0 → sql_dag_flow-0.4.1}/src/sql_dag_flow/test_api_endpoints.py +0 -0
  19. {sql_dag_flow-0.3.0 → sql_dag_flow-0.4.1}/src/sql_dag_flow/test_parser.py +0 -0
  20. {sql_dag_flow-0.3.0 → sql_dag_flow-0.4.1}/src/sql_dag_flow/verify_counts.py +0 -0
  21. {sql_dag_flow-0.3.0 → sql_dag_flow-0.4.1}/src/sql_dag_flow.egg-info/dependency_links.txt +0 -0
  22. {sql_dag_flow-0.3.0 → sql_dag_flow-0.4.1}/src/sql_dag_flow.egg-info/entry_points.txt +0 -0
  23. {sql_dag_flow-0.3.0 → sql_dag_flow-0.4.1}/src/sql_dag_flow.egg-info/requires.txt +0 -0
  24. {sql_dag_flow-0.3.0 → sql_dag_flow-0.4.1}/src/sql_dag_flow.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sql-dag-flow
3
- Version: 0.3.0
3
+ Version: 0.4.1
4
4
  Summary: A sophisticated SQL lineage visualization tool for Medallion Architectures.
5
5
  Author-email: Flavio Sandoval <dsandovalflavio@gmail.com>
6
6
  License: MIT
@@ -83,16 +83,26 @@ Specially optimized for the **Medallion Architecture** (Bronze, Silver, Gold) an
83
83
  * **Transparent & Borderless**:Create clean, floating text labels without boxes.
84
84
  * **Groups**: Create visual containers to group related nodes.
85
85
 
86
- ### 📊 Discovery & Analysis Tools (New ✨)
86
+ ### 📊 Discovery & Analysis Tools
87
87
  * **Business Rule Extraction**: Automatically detects and displays WHERE filters, CASE logic, HAVING clauses, and aggregations from each SQL model.
88
88
  * **Complexity Scoring**: Weighted metric per node (JOINs×3, CTEs×2, Subqueries×3, Filters×1, CASE×2, Aggregations×1, UNIONs×2) with color-coded badges (🟢 Low, 🟡 Medium, 🟠 High, 🔴 Very High). Toggleable via ⚡ button.
89
89
  * **Statistics Panel**: Centered popup with layer distribution bars, edge/source/sink/orphan counts, project/dataset tree, and architecture health validation.
90
90
  * **Schema Preview**: Extracts columns from DDL, CTAS (`CREATE TABLE AS SELECT`), and `CREATE VIEW` statements.
91
91
 
92
+ ### 🎨 Linear-Inspired UI (New in v0.4.0 ✨)
93
+ * **Design Token System**: ~80 CSS custom properties for consistent theming across all components.
94
+ * **Premium Dark Theme**: Deep `#0d0d0d` canvas with warm white text (`#e8e8e6`), never pure white.
95
+ * **Refined Light Theme**: Warm off-white `#f7f6f3` backgrounds — never harsh pure white.
96
+ * **Glassmorphism Toolbars**: `backdrop-filter: blur(16px)` on all floating panels.
97
+ * **Violet-Indigo Accent**: Premium `#7c6aef` accent color replacing generic blues/greens.
98
+ * **Smooth Animations**: `fadeIn` and `slideUp` micro-animations on popovers and modals.
99
+ * **Custom Scrollbars**: Subtle, styled scrollbars matching the theme.
100
+ * **Focus Rings**: Accessible focus indicators using the accent color.
101
+
92
102
  ### ⚙️ Customization
93
103
  * **Premium UI**:
94
104
  * **Themes**: Toggle between Light and Dark modes.
95
- * **Palettes**: Choose from Standard, Vivid, or Pastel color schemes to match your presentation style.
105
+ * **Palettes**: Choose from **Standard**, **Vivid**, **Pastel**, or **Linear** (new — muted, LCH-inspired tones) color schemes.
96
106
  * **Styles**: Switch between "Full" (colored body) and "Minimal" (colored border) node styles.
97
107
  * **Export**: Save high-resolution **PNG** or vector **SVG** diagrams for documentation.
98
108
 
@@ -102,14 +112,14 @@ Specially optimized for the **Medallion Architecture** (Bronze, Silver, Gold) an
102
112
 
103
113
  SQL DAG Flow uses distinct colors to identify node types. You can switch between these palettes in the Settings.
104
114
 
105
- | Node Type | Layer / Meaning | Standard | Vivid | Pastel |
106
- | :--- | :--- | :--- | :--- | :--- |
107
- | **Bronze** | Raw Ingestion | 🟤 Brown (`#8B4513`) | 🟠 Orange (`#FF5722`) | 🟤 Pale Brown (`#D7CCC8`) |
108
- | **Silver** | Cleaned / Conformed | ⚪ Gray (`#708090`) | 🔵 Blue (`#29B6F6`) | ⚪ Blue Grey (`#CFD8DC`) |
109
- | **Gold** | Business Aggregates | 🟡 Gold (`#DAA520`) | 🟡 Yellow (`#FFEB3B`) | 🟡 Pale Yellow (`#FFF9C4`) |
110
- | **External** | Missing / Ghost Node | 🟠 Dark Orange (`#D35400`) | 🟠 Neon Orange (`#FF9800`) | 🟠 Peach (`#FFE0B2`) |
111
- | **CTE** | Internal Common Table Expression | 💖 Pink (`#E91E63`) | 💗 Deep Pink (`#F50057`) | 🌸 Light Pink (`#F8BBD0`) |
112
- | **Other** | Uncategorized | 🔵 Teal (`#4CA1AF`) | 💠 Cyan (`#00BCD4`) | 🧊 Pale Cyan (`#B2EBF2`) |
115
+ | Node Type | Layer / Meaning | Standard | Vivid | Pastel | Linear |
116
+ | :--- | :--- | :--- | :--- | :--- | :--- |
117
+ | **Bronze** | Raw Ingestion | 🟤 Brown (`#8B4513`) | 🟠 Orange (`#FF5722`) | 🟤 Pale Brown (`#D7CCC8`) | 🟤 Muted (`#B08968`) |
118
+ | **Silver** | Cleaned / Conformed | ⚪ Gray (`#708090`) | 🔵 Blue (`#29B6F6`) | ⚪ Blue Grey (`#CFD8DC`) | ⚪ Slate (`#8E99A4`) |
119
+ | **Gold** | Business Aggregates | 🟡 Gold (`#DAA520`) | 🟡 Yellow (`#FFEB3B`) | 🟡 Pale Yellow (`#FFF9C4`) | 🟡 Warm (`#D4A843`) |
120
+ | **External** | Missing / Ghost Node | 🟠 Dark Orange (`#D35400`) | 🟠 Neon Orange (`#FF9800`) | 🟠 Peach (`#FFE0B2`) | 🟠 Sand (`#CC8B5E`) |
121
+ | **CTE** | Internal Common Table Expression | 💖 Pink (`#E91E63`) | 💗 Deep Pink (`#F50057`) | 🌸 Light Pink (`#F8BBD0`) | 💜 Mauve (`#C77092`) |
122
+ | **Other** | Uncategorized | 🔵 Teal (`#4CA1AF`) | 💠 Cyan (`#00BCD4`) | 🧊 Pale Cyan (`#B2EBF2`) | 🔵 Ocean (`#6B9DAD`) |
113
123
 
114
124
  ---
115
125
 
@@ -121,7 +131,7 @@ Install easily via `pip`:
121
131
  pip install sql-dag-flow
122
132
  ```
123
133
 
124
- To update to the latest version (**v0.3.0**):
134
+ To update to the latest version (**v0.4.0**):
125
135
 
126
136
  ```bash
127
137
  pip install --upgrade sql-dag-flow
@@ -58,16 +58,26 @@ Specially optimized for the **Medallion Architecture** (Bronze, Silver, Gold) an
58
58
  * **Transparent & Borderless**:Create clean, floating text labels without boxes.
59
59
  * **Groups**: Create visual containers to group related nodes.
60
60
 
61
- ### 📊 Discovery & Analysis Tools (New ✨)
61
+ ### 📊 Discovery & Analysis Tools
62
62
  * **Business Rule Extraction**: Automatically detects and displays WHERE filters, CASE logic, HAVING clauses, and aggregations from each SQL model.
63
63
  * **Complexity Scoring**: Weighted metric per node (JOINs×3, CTEs×2, Subqueries×3, Filters×1, CASE×2, Aggregations×1, UNIONs×2) with color-coded badges (🟢 Low, 🟡 Medium, 🟠 High, 🔴 Very High). Toggleable via ⚡ button.
64
64
  * **Statistics Panel**: Centered popup with layer distribution bars, edge/source/sink/orphan counts, project/dataset tree, and architecture health validation.
65
65
  * **Schema Preview**: Extracts columns from DDL, CTAS (`CREATE TABLE AS SELECT`), and `CREATE VIEW` statements.
66
66
 
67
+ ### 🎨 Linear-Inspired UI (New in v0.4.0 ✨)
68
+ * **Design Token System**: ~80 CSS custom properties for consistent theming across all components.
69
+ * **Premium Dark Theme**: Deep `#0d0d0d` canvas with warm white text (`#e8e8e6`), never pure white.
70
+ * **Refined Light Theme**: Warm off-white `#f7f6f3` backgrounds — never harsh pure white.
71
+ * **Glassmorphism Toolbars**: `backdrop-filter: blur(16px)` on all floating panels.
72
+ * **Violet-Indigo Accent**: Premium `#7c6aef` accent color replacing generic blues/greens.
73
+ * **Smooth Animations**: `fadeIn` and `slideUp` micro-animations on popovers and modals.
74
+ * **Custom Scrollbars**: Subtle, styled scrollbars matching the theme.
75
+ * **Focus Rings**: Accessible focus indicators using the accent color.
76
+
67
77
  ### ⚙️ Customization
68
78
  * **Premium UI**:
69
79
  * **Themes**: Toggle between Light and Dark modes.
70
- * **Palettes**: Choose from Standard, Vivid, or Pastel color schemes to match your presentation style.
80
+ * **Palettes**: Choose from **Standard**, **Vivid**, **Pastel**, or **Linear** (new — muted, LCH-inspired tones) color schemes.
71
81
  * **Styles**: Switch between "Full" (colored body) and "Minimal" (colored border) node styles.
72
82
  * **Export**: Save high-resolution **PNG** or vector **SVG** diagrams for documentation.
73
83
 
@@ -77,14 +87,14 @@ Specially optimized for the **Medallion Architecture** (Bronze, Silver, Gold) an
77
87
 
78
88
  SQL DAG Flow uses distinct colors to identify node types. You can switch between these palettes in the Settings.
79
89
 
80
- | Node Type | Layer / Meaning | Standard | Vivid | Pastel |
81
- | :--- | :--- | :--- | :--- | :--- |
82
- | **Bronze** | Raw Ingestion | 🟤 Brown (`#8B4513`) | 🟠 Orange (`#FF5722`) | 🟤 Pale Brown (`#D7CCC8`) |
83
- | **Silver** | Cleaned / Conformed | ⚪ Gray (`#708090`) | 🔵 Blue (`#29B6F6`) | ⚪ Blue Grey (`#CFD8DC`) |
84
- | **Gold** | Business Aggregates | 🟡 Gold (`#DAA520`) | 🟡 Yellow (`#FFEB3B`) | 🟡 Pale Yellow (`#FFF9C4`) |
85
- | **External** | Missing / Ghost Node | 🟠 Dark Orange (`#D35400`) | 🟠 Neon Orange (`#FF9800`) | 🟠 Peach (`#FFE0B2`) |
86
- | **CTE** | Internal Common Table Expression | 💖 Pink (`#E91E63`) | 💗 Deep Pink (`#F50057`) | 🌸 Light Pink (`#F8BBD0`) |
87
- | **Other** | Uncategorized | 🔵 Teal (`#4CA1AF`) | 💠 Cyan (`#00BCD4`) | 🧊 Pale Cyan (`#B2EBF2`) |
90
+ | Node Type | Layer / Meaning | Standard | Vivid | Pastel | Linear |
91
+ | :--- | :--- | :--- | :--- | :--- | :--- |
92
+ | **Bronze** | Raw Ingestion | 🟤 Brown (`#8B4513`) | 🟠 Orange (`#FF5722`) | 🟤 Pale Brown (`#D7CCC8`) | 🟤 Muted (`#B08968`) |
93
+ | **Silver** | Cleaned / Conformed | ⚪ Gray (`#708090`) | 🔵 Blue (`#29B6F6`) | ⚪ Blue Grey (`#CFD8DC`) | ⚪ Slate (`#8E99A4`) |
94
+ | **Gold** | Business Aggregates | 🟡 Gold (`#DAA520`) | 🟡 Yellow (`#FFEB3B`) | 🟡 Pale Yellow (`#FFF9C4`) | 🟡 Warm (`#D4A843`) |
95
+ | **External** | Missing / Ghost Node | 🟠 Dark Orange (`#D35400`) | 🟠 Neon Orange (`#FF9800`) | 🟠 Peach (`#FFE0B2`) | 🟠 Sand (`#CC8B5E`) |
96
+ | **CTE** | Internal Common Table Expression | 💖 Pink (`#E91E63`) | 💗 Deep Pink (`#F50057`) | 🌸 Light Pink (`#F8BBD0`) | 💜 Mauve (`#C77092`) |
97
+ | **Other** | Uncategorized | 🔵 Teal (`#4CA1AF`) | 💠 Cyan (`#00BCD4`) | 🧊 Pale Cyan (`#B2EBF2`) | 🔵 Ocean (`#6B9DAD`) |
88
98
 
89
99
  ---
90
100
 
@@ -96,7 +106,7 @@ Install easily via `pip`:
96
106
  pip install sql-dag-flow
97
107
  ```
98
108
 
99
- To update to the latest version (**v0.3.0**):
109
+ To update to the latest version (**v0.4.0**):
100
110
 
101
111
  ```bash
102
112
  pip install --upgrade sql-dag-flow
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "sql-dag-flow"
7
- version = "0.3.0"
7
+ version = "0.4.1"
8
8
  description = "A sophisticated SQL lineage visualization tool for Medallion Architectures."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -0,0 +1 @@
1
+ @import"https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,400;14..32,500;14..32,600;14..32,700;14..32,800&display=swap";:root,[data-theme=dark]{--surface-primary: #0d0d0d;--surface-secondary: #141414;--surface-elevated: #1c1c1c;--surface-inset: #0a0a0a;--surface-overlay: rgba(0, 0, 0, .6);--surface-tooltip: rgba(22, 22, 22, .95);--text-primary: #e8e8e6;--text-secondary: #8b8b8b;--text-tertiary: #5a5a5a;--text-inverse: #0d0d0d;--text-accent: #8d9eff;--border-default: rgba(255, 255, 255, .06);--border-emphasis: rgba(255, 255, 255, .12);--border-strong: rgba(255, 255, 255, .2);--interactive-hover: rgba(255, 255, 255, .04);--interactive-active: rgba(255, 255, 255, .08);--interactive-selected: rgba(255, 255, 255, .06);--accent-primary: #7c6aef;--accent-hover: #8d7df5;--accent-muted: rgba(124, 106, 239, .15);--accent-text: #a99eff;--shadow-sm: 0 1px 2px rgba(0, 0, 0, .3), 0 1px 3px rgba(0, 0, 0, .15);--shadow-md: 0 4px 12px rgba(0, 0, 0, .4), 0 2px 4px rgba(0, 0, 0, .2);--shadow-lg: 0 12px 40px rgba(0, 0, 0, .5), 0 4px 12px rgba(0, 0, 0, .3);--shadow-xl: 0 20px 60px rgba(0, 0, 0, .6), 0 8px 20px rgba(0, 0, 0, .35);--canvas-bg: #0d0d0d;--canvas-dots: #1a1a1a;--edge-default: #444;--edge-incoming: #4dc9f6;--edge-outgoing: #f67280;--edge-lineage: #9d7aff;--edge-dimmed: #333;--status-success: #34d399;--status-warning: #fbbf24;--status-error: #f87171;--status-info: #60a5fa;--minimap-bg: #141414;--scrollbar-thumb: rgba(255, 255, 255, .1);--scrollbar-track: transparent}[data-theme=light]{--surface-primary: #f7f6f3;--surface-secondary: #efeeeb;--surface-elevated: #ffffff;--surface-inset: #eae9e6;--surface-overlay: rgba(0, 0, 0, .4);--surface-tooltip: rgba(255, 255, 255, .97);--text-primary: #1a1a1a;--text-secondary: #5c5c5c;--text-tertiary: #8a8a8a;--text-inverse: #f7f6f3;--text-accent: #5b4cc4;--border-default: rgba(0, 0, 0, .06);--border-emphasis: rgba(0, 0, 0, .1);--border-strong: rgba(0, 0, 0, .18);--interactive-hover: rgba(0, 0, 0, .03);--interactive-active: rgba(0, 0, 0, .06);--interactive-selected: rgba(0, 0, 0, .04);--accent-primary: #6c5ce7;--accent-hover: #5a4bd6;--accent-muted: rgba(108, 92, 231, .1);--accent-text: #5b4cc4;--shadow-sm: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--shadow-md: 0 4px 12px rgba(0, 0, 0, .06), 0 2px 4px rgba(0, 0, 0, .04);--shadow-lg: 0 12px 40px rgba(0, 0, 0, .08), 0 4px 12px rgba(0, 0, 0, .04);--shadow-xl: 0 20px 60px rgba(0, 0, 0, .1), 0 8px 20px rgba(0, 0, 0, .05);--canvas-bg: #f7f6f3;--canvas-dots: #ddd;--edge-default: #b0b0b0;--edge-incoming: #0077b6;--edge-outgoing: #c9184a;--edge-lineage: #7b2cbf;--edge-dimmed: #ccc;--status-success: #059669;--status-warning: #d97706;--status-error: #dc2626;--status-info: #2563eb;--minimap-bg: #efeeeb;--scrollbar-thumb: rgba(0, 0, 0, .12);--scrollbar-track: transparent}:root{--layer-bronze-standard: #8B4513;--layer-silver-standard: #708090;--layer-gold-standard: #DAA520;--layer-external-standard: #D35400;--layer-cte-standard: #E91E63;--layer-other-standard: #4CA1AF;--layer-bronze-vivid: #FF5722;--layer-silver-vivid: #29B6F6;--layer-gold-vivid: #FFEB3B;--layer-external-vivid: #FF9800;--layer-cte-vivid: #F50057;--layer-other-vivid: #00BCD4;--layer-bronze-pastel: #D7CCC8;--layer-silver-pastel: #CFD8DC;--layer-gold-pastel: #FFF9C4;--layer-external-pastel: #FFE0B2;--layer-cte-pastel: #F8BBD0;--layer-other-pastel: #B2EBF2;--layer-bronze-linear: #B08968;--layer-silver-linear: #8E99A4;--layer-gold-linear: #D4A843;--layer-external-linear: #CC8B5E;--layer-cte-linear: #C77092;--layer-other-linear: #6B9DAD;--layer-dot-bronze: #cd7f32;--layer-dot-silver: #708090;--layer-dot-gold: #FFD700;--layer-dot-external: #ff9f1c;--layer-dot-cte: #E91E63;--layer-dot-other: #4CA1AF}body{margin:0;font-family:Inter,system-ui,-apple-system,BlinkMacSystemFont,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;width:100vw;height:100vh;overflow:hidden;background:var(--surface-primary);color:var(--text-primary);transition:background .3s ease,color .3s ease}code{font-family:SF Mono,Fira Code,Cascadia Code,Menlo,Monaco,Consolas,Courier New,monospace}.react-flow__attribution{display:none!important}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:var(--scrollbar-track)}::-webkit-scrollbar-thumb{background:var(--scrollbar-thumb);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--border-emphasis)}.heading-display{font-variation-settings:"opsz" 32;letter-spacing:-.02em}.transition-colors{transition:background-color .2s cubic-bezier(.25,.1,.25,1),color .2s cubic-bezier(.25,.1,.25,1),border-color .2s cubic-bezier(.25,.1,.25,1),box-shadow .2s cubic-bezier(.25,.1,.25,1)}.sidebar-item:hover{background:var(--interactive-hover)!important}@keyframes fadeIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}@keyframes slideUp{0%{opacity:0;transform:translate(-50%,8px)}to{opacity:1;transform:translate(-50%)}}.react-flow{direction:ltr;--xy-edge-stroke-default: #b1b1b7;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #555;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(255, 255, 255, .5);--xy-minimap-background-color-default: #fff;--xy-minimap-mask-background-color-default: rgba(240, 240, 240, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #e2e2e2;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: transparent;--xy-background-pattern-dots-color-default: #91919a;--xy-background-pattern-lines-color-default: #eee;--xy-background-pattern-cross-color-default: #e2e2e2;background-color:var(--xy-background-color, var(--xy-background-color-default));--xy-node-color-default: inherit;--xy-node-border-default: 1px solid #1a192b;--xy-node-background-color-default: #fff;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(0, 0, 0, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #1a192b;--xy-node-border-radius-default: 3px;--xy-handle-background-color-default: #1a192b;--xy-handle-border-color-default: #fff;--xy-selection-background-color-default: rgba(0, 89, 220, .08);--xy-selection-border-default: 1px dotted rgba(0, 89, 220, .8);--xy-controls-button-background-color-default: #fefefe;--xy-controls-button-background-color-hover-default: #f4f4f4;--xy-controls-button-color-default: inherit;--xy-controls-button-color-hover-default: inherit;--xy-controls-button-border-color-default: #eee;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #ffffff;--xy-edge-label-color-default: inherit;--xy-resize-background-color-default: #3367d9}.react-flow.dark{--xy-edge-stroke-default: #3e3e3e;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #727272;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(150, 150, 150, .25);--xy-minimap-background-color-default: #141414;--xy-minimap-mask-background-color-default: rgba(60, 60, 60, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #2b2b2b;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: #141414;--xy-background-pattern-dots-color-default: #777;--xy-background-pattern-lines-color-default: #777;--xy-background-pattern-cross-color-default: #777;--xy-node-color-default: #f8f8f8;--xy-node-border-default: 1px solid #3c3c3c;--xy-node-background-color-default: #1e1e1e;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(255, 255, 255, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #999;--xy-handle-background-color-default: #bebebe;--xy-handle-border-color-default: #1e1e1e;--xy-selection-background-color-default: rgba(200, 200, 220, .08);--xy-selection-border-default: 1px dotted rgba(200, 200, 220, .8);--xy-controls-button-background-color-default: #2b2b2b;--xy-controls-button-background-color-hover-default: #3e3e3e;--xy-controls-button-color-default: #f8f8f8;--xy-controls-button-color-hover-default: #fff;--xy-controls-button-border-color-default: #5b5b5b;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #141414;--xy-edge-label-color-default: #f8f8f8}.react-flow__background{background-color:var(--xy-background-color-props, var(--xy-background-color, var(--xy-background-color-default)));pointer-events:none;z-index:-1}.react-flow__container{position:absolute;width:100%;height:100%;top:0;left:0}.react-flow__pane{z-index:1}.react-flow__pane.draggable{cursor:grab}.react-flow__pane.dragging{cursor:grabbing}.react-flow__pane.selection{cursor:pointer}.react-flow__viewport{transform-origin:0 0;z-index:2;pointer-events:none}.react-flow__renderer{z-index:4}.react-flow__selection{z-index:6}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible{outline:none}.react-flow__edge-path{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default));stroke-width:var(--xy-edge-stroke-width, var(--xy-edge-stroke-width-default));fill:none}.react-flow__connection-path{stroke:var(--xy-connectionline-stroke, var(--xy-connectionline-stroke-default));stroke-width:var(--xy-connectionline-stroke-width, var(--xy-connectionline-stroke-width-default));fill:none}.react-flow .react-flow__edges{position:absolute}.react-flow .react-flow__edges svg{overflow:visible;position:absolute;pointer-events:none}.react-flow__edge{pointer-events:visibleStroke}.react-flow__edge.selectable{cursor:pointer}.react-flow__edge.animated path{stroke-dasharray:5;animation:dashdraw .5s linear infinite}.react-flow__edge.animated path.react-flow__edge-interaction{stroke-dasharray:none;animation:none}.react-flow__edge.inactive{pointer-events:none}.react-flow__edge.selected,.react-flow__edge:focus,.react-flow__edge:focus-visible{outline:none}.react-flow__edge.selected .react-flow__edge-path,.react-flow__edge.selectable:focus .react-flow__edge-path,.react-flow__edge.selectable:focus-visible .react-flow__edge-path{stroke:var(--xy-edge-stroke-selected, var(--xy-edge-stroke-selected-default))}.react-flow__edge-textwrapper{pointer-events:all}.react-flow__edge .react-flow__edge-text{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__arrowhead polyline{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.react-flow__arrowhead polyline.arrowclosed{fill:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.react-flow__connection{pointer-events:none}.react-flow__connection .animated{stroke-dasharray:5;animation:dashdraw .5s linear infinite}svg.react-flow__connectionline{z-index:1001;overflow:visible;position:absolute}.react-flow__nodes{pointer-events:none;transform-origin:0 0}.react-flow__node{position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none;pointer-events:all;transform-origin:0 0;box-sizing:border-box;cursor:default}.react-flow__node.selectable{cursor:pointer}.react-flow__node.draggable{cursor:grab;pointer-events:all}.react-flow__node.draggable.dragging{cursor:grabbing}.react-flow__nodesselection{z-index:3;transform-origin:left top;pointer-events:none}.react-flow__nodesselection-rect{position:absolute;pointer-events:all;cursor:grab}.react-flow__handle{position:absolute;pointer-events:none;min-width:5px;min-height:5px;width:6px;height:6px;background-color:var(--xy-handle-background-color, var(--xy-handle-background-color-default));border:1px solid var(--xy-handle-border-color, var(--xy-handle-border-color-default));border-radius:100%}.react-flow__handle.connectingfrom{pointer-events:all}.react-flow__handle.connectionindicator{pointer-events:all;cursor:crosshair}.react-flow__handle-bottom{top:auto;left:50%;bottom:0;transform:translate(-50%,50%)}.react-flow__handle-top{top:0;left:50%;transform:translate(-50%,-50%)}.react-flow__handle-left{top:50%;left:0;transform:translate(-50%,-50%)}.react-flow__handle-right{top:50%;right:0;transform:translate(50%,-50%)}.react-flow__edgeupdater{cursor:move;pointer-events:all}.react-flow__pane.selection .react-flow__panel{pointer-events:none}.react-flow__panel{position:absolute;z-index:5;margin:15px}.react-flow__panel.top{top:0}.react-flow__panel.bottom{bottom:0}.react-flow__panel.top.center,.react-flow__panel.bottom.center{left:50%;transform:translate(-15px) translate(-50%)}.react-flow__panel.left{left:0}.react-flow__panel.right{right:0}.react-flow__panel.left.center,.react-flow__panel.right.center{top:50%;transform:translateY(-15px) translateY(-50%)}.react-flow__attribution{font-size:10px;background:var(--xy-attribution-background-color, var(--xy-attribution-background-color-default));padding:2px 3px;margin:0}.react-flow__attribution a{text-decoration:none;color:#999}@keyframes dashdraw{0%{stroke-dashoffset:10}}.react-flow__edgelabel-renderer{position:absolute;width:100%;height:100%;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;left:0;top:0}.react-flow__viewport-portal{position:absolute;width:100%;height:100%;left:0;top:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__minimap{background:var( --xy-minimap-background-color-props, var(--xy-minimap-background-color, var(--xy-minimap-background-color-default)) )}.react-flow__minimap-svg{display:block}.react-flow__minimap-mask{fill:var( --xy-minimap-mask-background-color-props, var(--xy-minimap-mask-background-color, var(--xy-minimap-mask-background-color-default)) );stroke:var( --xy-minimap-mask-stroke-color-props, var(--xy-minimap-mask-stroke-color, var(--xy-minimap-mask-stroke-color-default)) );stroke-width:var( --xy-minimap-mask-stroke-width-props, var(--xy-minimap-mask-stroke-width, var(--xy-minimap-mask-stroke-width-default)) )}.react-flow__minimap-node{fill:var( --xy-minimap-node-background-color-props, var(--xy-minimap-node-background-color, var(--xy-minimap-node-background-color-default)) );stroke:var( --xy-minimap-node-stroke-color-props, var(--xy-minimap-node-stroke-color, var(--xy-minimap-node-stroke-color-default)) );stroke-width:var( --xy-minimap-node-stroke-width-props, var(--xy-minimap-node-stroke-width, var(--xy-minimap-node-stroke-width-default)) )}.react-flow__background-pattern.dots{fill:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-dots-color-default)) )}.react-flow__background-pattern.lines{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-lines-color-default)) )}.react-flow__background-pattern.cross{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-cross-color-default)) )}.react-flow__controls{display:flex;flex-direction:column;box-shadow:var(--xy-controls-box-shadow, var(--xy-controls-box-shadow-default))}.react-flow__controls.horizontal{flex-direction:row}.react-flow__controls-button{display:flex;justify-content:center;align-items:center;height:26px;width:26px;padding:4px;border:none;background:var(--xy-controls-button-background-color, var(--xy-controls-button-background-color-default));border-bottom:1px solid var( --xy-controls-button-border-color-props, var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) );color:var( --xy-controls-button-color-props, var(--xy-controls-button-color, var(--xy-controls-button-color-default)) );cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__controls-button svg{width:100%;max-width:12px;max-height:12px;fill:currentColor}.react-flow__edge.updating .react-flow__edge-path{stroke:#777}.react-flow__edge-text{font-size:10px}.react-flow__node.selectable:focus,.react-flow__node.selectable:focus-visible{outline:none}.react-flow__node-input,.react-flow__node-default,.react-flow__node-output,.react-flow__node-group{padding:10px;border-radius:var(--xy-node-border-radius, var(--xy-node-border-radius-default));width:150px;font-size:12px;color:var(--xy-node-color, var(--xy-node-color-default));text-align:center;border:var(--xy-node-border, var(--xy-node-border-default));background-color:var(--xy-node-background-color, var(--xy-node-background-color-default))}.react-flow__node-input.selectable:hover,.react-flow__node-default.selectable:hover,.react-flow__node-output.selectable:hover,.react-flow__node-group.selectable:hover{box-shadow:var(--xy-node-boxshadow-hover, var(--xy-node-boxshadow-hover-default))}.react-flow__node-input.selectable.selected,.react-flow__node-input.selectable:focus,.react-flow__node-input.selectable:focus-visible,.react-flow__node-default.selectable.selected,.react-flow__node-default.selectable:focus,.react-flow__node-default.selectable:focus-visible,.react-flow__node-output.selectable.selected,.react-flow__node-output.selectable:focus,.react-flow__node-output.selectable:focus-visible,.react-flow__node-group.selectable.selected,.react-flow__node-group.selectable:focus,.react-flow__node-group.selectable:focus-visible{box-shadow:var(--xy-node-boxshadow-selected, var(--xy-node-boxshadow-selected-default))}.react-flow__node-group{background-color:var(--xy-node-group-background-color, var(--xy-node-group-background-color-default))}.react-flow__nodesselection-rect,.react-flow__selection{background:var(--xy-selection-background-color, var(--xy-selection-background-color-default));border:var(--xy-selection-border, var(--xy-selection-border-default))}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible,.react-flow__selection:focus,.react-flow__selection:focus-visible{outline:none}.react-flow__controls-button:hover{background:var( --xy-controls-button-background-color-hover-props, var(--xy-controls-button-background-color-hover, var(--xy-controls-button-background-color-hover-default)) );color:var( --xy-controls-button-color-hover-props, var(--xy-controls-button-color-hover, var(--xy-controls-button-color-hover-default)) )}.react-flow__controls-button:disabled{pointer-events:none}.react-flow__controls-button:disabled svg{fill-opacity:.4}.react-flow__controls-button:last-child{border-bottom:none}.react-flow__controls.horizontal .react-flow__controls-button{border-bottom:none;border-right:1px solid var( --xy-controls-button-border-color-props, var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) )}.react-flow__controls.horizontal .react-flow__controls-button:last-child{border-right:none}.react-flow__resize-control{position:absolute}.react-flow__resize-control.left,.react-flow__resize-control.right{cursor:ew-resize}.react-flow__resize-control.top,.react-flow__resize-control.bottom{cursor:ns-resize}.react-flow__resize-control.top.left,.react-flow__resize-control.bottom.right{cursor:nwse-resize}.react-flow__resize-control.bottom.left,.react-flow__resize-control.top.right{cursor:nesw-resize}.react-flow__resize-control.handle{width:5px;height:5px;border:1px solid #fff;border-radius:1px;background-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));translate:-50% -50%}.react-flow__resize-control.handle.left{left:0;top:50%}.react-flow__resize-control.handle.right{left:100%;top:50%}.react-flow__resize-control.handle.top{left:50%;top:0}.react-flow__resize-control.handle.bottom{left:50%;top:100%}.react-flow__resize-control.handle.top.left,.react-flow__resize-control.handle.bottom.left{left:0}.react-flow__resize-control.handle.top.right,.react-flow__resize-control.handle.bottom.right{left:100%}.react-flow__resize-control.line{border-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));border-width:0;border-style:solid}.react-flow__resize-control.line.left,.react-flow__resize-control.line.right{width:1px;transform:translate(-50%);top:0;height:100%}.react-flow__resize-control.line.left{left:0;border-left-width:1px}.react-flow__resize-control.line.right{left:100%;border-right-width:1px}.react-flow__resize-control.line.top,.react-flow__resize-control.line.bottom{height:1px;transform:translateY(-50%);left:0;width:100%}.react-flow__resize-control.line.top{top:0;border-top-width:1px}.react-flow__resize-control.line.bottom{border-bottom-width:1px;top:100%}.react-flow__edge-textbg{fill:var(--xy-edge-label-background-color, var(--xy-edge-label-background-color-default))}.react-flow__edge-text{fill:var(--xy-edge-label-color, var(--xy-edge-label-color-default))}