@mp70/react-networks 0.1.9-beta → 0.2.0-rc.0
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.
- package/README.md +82 -33
- package/dist/index.css +75 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +700 -197
- package/dist/index.d.ts +700 -197
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# @mp70/react-networks
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/@mp70/react-networks)
|
|
4
|
+
[](https://www.npmjs.com/package/@mp70/react-networks)
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
6
6
|
|
|
7
|
-
A
|
|
7
|
+
A React library for creating interactive network diagrams with support for rack management, fiber networks, and power distribution. Built on React Flow with TypeScript support.
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
@@ -13,6 +13,7 @@ A production-ready React library for creating interactive network diagrams with
|
|
|
13
13
|
- **Fiber Networks**: Visual representation of fiber connections and patch panels
|
|
14
14
|
- **Power Distribution**: Vertical PDU support with power connections
|
|
15
15
|
- **View Switching**: Front/rear view switching for devices and racks
|
|
16
|
+
- **Device Images**: Front/rear device images supported (PNG, SVG, JPEG, etc.) via `frontImageUrl` / `rearImageUrl` (`https://`, `blob:`, `data:image/*`, or relative URLs)
|
|
16
17
|
- **Rack Alignment**: Align rack bottoms to the same horizontal plane
|
|
17
18
|
- **Inventory Integration**: Built-in helpers to import/export generic inventory/CMDB data
|
|
18
19
|
- **Customizable**: Extensive styling and theming options
|
|
@@ -89,23 +90,32 @@ export default App;
|
|
|
89
90
|
|
|
90
91
|
### Documentation Resources
|
|
91
92
|
|
|
92
|
-
-
|
|
93
|
-
-
|
|
94
|
-
- 🌐 [Documentation Site](../docs/) - Interactive documentation with live examples
|
|
95
|
-
- 📝 [Contributing Guide](CONTRIBUTING.md) - Development guidelines
|
|
93
|
+
- Main Project README: `../../README.md` - Project overview and quick start
|
|
94
|
+
- Contributing Guide: `CONTRIBUTING.md` - Development guidelines
|
|
96
95
|
|
|
97
96
|
### API Reference
|
|
98
97
|
|
|
99
98
|
#### Components
|
|
100
99
|
|
|
101
100
|
- [`NetworkDiagram`](#networkdiagram) - Main diagram component
|
|
101
|
+
- [`DiagramErrorBoundary`](#diagramerrorboundary) - Error boundary for diagram errors
|
|
102
102
|
- [`RackNode`](#racknode) - Rack visualization component
|
|
103
103
|
- [`DeviceNode`](#devicenode) - Device visualization component
|
|
104
104
|
- [`FiberNode`](#fibernode) - Fiber connection component
|
|
105
|
+
- [`FiberEdge`](#fiberedge) - Fiber edge component
|
|
106
|
+
- [`PowerEdge`](#poweredge) - Power edge component
|
|
105
107
|
- [`VerticalPDU`](#verticalpdu) - Power distribution component
|
|
106
108
|
- [`PatchPanelNode`](#patchpanelnode) - Patch panel component
|
|
109
|
+
- [`SpliceNode`](#splicenode) - Splice component
|
|
107
110
|
- [`SpliceTrayNode`](#splicetraynode) - Splice tray component
|
|
111
|
+
- [`TubeNode`](#tubenode) - Tube component
|
|
112
|
+
- [`CableNode`](#cablenode) - Cable component
|
|
113
|
+
- [`MultiTubeCableNode`](#multitubecablenode) - Multi-tube cable component
|
|
108
114
|
- [`CouplerNode`](#couplernode) - Coupler component
|
|
115
|
+
- [`ClosureNode`](#closurenode) - Closure component
|
|
116
|
+
- [`FibreSplitNode`](#fibresplitnode) - Fibre split component
|
|
117
|
+
- [`FibreFlowMap`](#fibreflowmap) - Fibre flow map component
|
|
118
|
+
- [`FibreCableWithTubesExpanded`](#fibrecablewithtubesexpanded) - Fibre cable with tubes expanded view
|
|
109
119
|
|
|
110
120
|
#### Utilities
|
|
111
121
|
|
|
@@ -125,31 +135,69 @@ export default App;
|
|
|
125
135
|
- [`validateSplicePlacements`](#validatespliceplacements) - Validate splice placements
|
|
126
136
|
- [`addSpliceToTray`](#addsplicetotray) - Add splice to tray schema
|
|
127
137
|
- [`removeSpliceFromTray`](#removesplicefromtray) - Remove splice from tray schema
|
|
138
|
+
- [`updateSpliceHolderPosition`](#updatespliceholderposition) - Update splice holder position in schema
|
|
128
139
|
|
|
129
140
|
**Data Integration:**
|
|
130
|
-
- [`netboxToNetworkDiagram`](#netboxtonetworkdiagram) - Convert NetBox data to diagram
|
|
131
141
|
- [`inventoryToNetworkDiagram`](#inventorytonetworkdiagram) - Convert inventory/CMDB data to diagram
|
|
142
|
+
- [`generateLayout`](#generatelayout) - Generate layout from inventory
|
|
132
143
|
|
|
133
144
|
**Dimension Calculations:**
|
|
134
145
|
- [`calculatePanelDimensions`](#calculatepaneldimensions) - Calculate panel dimensions from children
|
|
135
146
|
- [`calculateClosureDimensions`](#calculateclosuredimensions) - Calculate closure dimensions from children
|
|
136
147
|
- [`getCouplerDimensions`](#getcouplerdimensions) - Get coupler dimensions
|
|
137
148
|
- [`getTubeDimensions`](#gettubedimensions) - Get tube dimensions
|
|
149
|
+
- [`getTrayDimensions`](#gettraydimensions) - Get tray dimensions
|
|
150
|
+
|
|
151
|
+
**Other:**
|
|
152
|
+
- [`replaceEdge`](#replaceedge) - Replace an edge (e.g. when reconnecting)
|
|
153
|
+
- [`createNetworkDiagramStore`](#createnetworkdiagramstore) - Headless store for diagram state
|
|
154
|
+
- [`useNetworkDiagram`](#usenetworkdiagram) / [`useDiagramNodes`](#usediagramnodes) / [`useDiagramEdges`](#usediagramedges) - Headless hooks
|
|
155
|
+
- Power: `getPowerPortStyle`, `getConnectorConfig`, `getDeviceConnectorType`, `getPDUPortType`, `isHighPowerConnector`, `POWER_CONNECTORS`
|
|
156
|
+
- Fiber colors: `FIBER_COLORS_12`, `baseColorFor`, `isStriped`, `fiberSolidOrStriped`, `getFiberColor`
|
|
157
|
+
- Rack geometry: `getRackBounds`, `isPointInRack`, `findNearestRack`
|
|
158
|
+
- Constants: `U_HEIGHT_PX`, `RACK_HEADER_HEIGHT`, `RACK_WIDTH_PX`, `HANDLE_EXTENSION_PX`
|
|
159
|
+
- Status: `getStatusColor`
|
|
138
160
|
|
|
139
161
|
### NetworkDiagram Props
|
|
140
162
|
|
|
141
163
|
| Prop | Type | Default | Description |
|
|
142
164
|
|------|------|---------|-------------|
|
|
143
|
-
| `nodes` | `NetworkNode[]` | `[]` |
|
|
144
|
-
| `edges` | `NetworkEdge[]` | `[]` |
|
|
165
|
+
| `nodes` | `NetworkNode[]` | `[]` | Controlled nodes array |
|
|
166
|
+
| `edges` | `NetworkEdge[]` | `[]` | Controlled edges array |
|
|
167
|
+
| `onNodesChange` | `(nodes: NetworkNode[]) => void` | - | Callback when nodes change (controlled) |
|
|
168
|
+
| `onEdgesChange` | `(edges: NetworkEdge[]) => void` | - | Callback when edges change (controlled) |
|
|
169
|
+
| `initialNodes` | `NetworkNode[]` | - | Initial nodes (uncontrolled) |
|
|
170
|
+
| `initialEdges` | `NetworkEdge[]` | - | Initial edges (uncontrolled) |
|
|
171
|
+
| `store` | `NetworkDiagramStoreApi` | - | Headless store injection |
|
|
145
172
|
| `alignRacksToBottom` | `boolean` | `false` | Align rack bottoms to baseline |
|
|
146
|
-
| `onNodeClick` | `(node: NetworkNode) => void` | - | Node click handler |
|
|
173
|
+
| `onNodeClick` | `(node: NetworkNode \| null) => void` | - | Node click / selection handler |
|
|
147
174
|
| `onEdgeClick` | `(edge: NetworkEdge) => void` | - | Edge click handler |
|
|
148
175
|
| `onViewChange` | `(nodeId: string, view: 'front' \| 'rear') => void` | - | Device view change handler |
|
|
149
176
|
| `onRackFaceChange` | `(rackId: string, face: 'front' \| 'rear') => void` | - | Rack face change handler |
|
|
177
|
+
| `nodeTypes` | `NodeTypes` | - | Custom React Flow node types |
|
|
178
|
+
| `edgeTypes` | `EdgeTypes` | - | Custom React Flow edge types |
|
|
179
|
+
| `onConnect` | `(connection: Connection) => void` | - | Connection handler override |
|
|
180
|
+
| `onEdgeUpdate` | - | - | Edge update (reconnect) override |
|
|
181
|
+
| `isValidConnection` | `(connection: Connection) => boolean` | - | Connection validation override |
|
|
182
|
+
| `connectionMode` | `ConnectionMode` | - | React Flow connection mode |
|
|
183
|
+
| `reAssignable` | `boolean` | `true` | Allow devices to move between racks / ungroup on drag |
|
|
184
|
+
| `colorMode` | `'light' \| 'dark' \| 'system'` | - | Diagram color mode |
|
|
185
|
+
| `onInit` | `(instance: ReactFlowInstance) => void` | - | Called when React Flow is ready |
|
|
186
|
+
| `onFlowMethods` | `(methods: NetworkDiagramFlowMethods) => void` | - | Receive toObject/setViewport/toImage/fitView etc. |
|
|
187
|
+
| `showDownloadButton` | `boolean` | - | Show export image button |
|
|
188
|
+
| `downloadButtonPosition` | `'top-right' \| 'top-left' \| 'bottom-right' \| 'bottom-left'` | - | Download button position |
|
|
189
|
+
| `useSmoothstepEdgesForTubes` | `boolean` | `false` | Use smoothstep edges for tube connections |
|
|
150
190
|
| `className` | `string` | - | CSS class name |
|
|
151
191
|
| `style` | `React.CSSProperties` | - | Inline styles |
|
|
152
192
|
| `debug` | `boolean` | `false` | Enable debug mode |
|
|
193
|
+
| `readOnly` | `boolean` | `false` | Force lock diagram (no drag/connect/delete/reconnect/pan/zoom) |
|
|
194
|
+
| `interaction` | `NetworkDiagramInteractionOptions` | - | Fine-grained interaction (nodesDraggable, nodesConnectable, panOnDrag, etc.) |
|
|
195
|
+
| `actionPanel` | `NetworkDiagramActionPanelOptions` | - | Configure action panel (enabled, showRearToggle, showDeRack) |
|
|
196
|
+
| `connectOnClick` | `boolean` | `true` | Enable click-to-connect on handles |
|
|
197
|
+
| `panOnDrag` | `boolean` | - | Override pan on drag |
|
|
198
|
+
| `panOnScroll` | `boolean` | - | Override pan on scroll |
|
|
199
|
+
| `zoomOnScroll` | `boolean` | - | Override zoom on scroll |
|
|
200
|
+
| `fitViewOptions` | `FitViewOptions` | - | React Flow fitView options |
|
|
153
201
|
|
|
154
202
|
### NetworkNode Types
|
|
155
203
|
|
|
@@ -162,13 +210,23 @@ type NetworkNodeType =
|
|
|
162
210
|
| 'fiber'
|
|
163
211
|
| 'patch-panel'
|
|
164
212
|
| 'device'
|
|
165
|
-
| 'vertical-pdu'
|
|
213
|
+
| 'vertical-pdu'
|
|
214
|
+
| 'splice'
|
|
215
|
+
| 'splice-tray'
|
|
216
|
+
| 'tube'
|
|
217
|
+
| 'cable'
|
|
218
|
+
| 'multi-tube-cable'
|
|
219
|
+
| 'coupler'
|
|
220
|
+
| 'closure'
|
|
221
|
+
| 'fibre-split'
|
|
222
|
+
| 'fibre-flow-cable'
|
|
223
|
+
| 'fibre-flow-closure';
|
|
166
224
|
```
|
|
167
225
|
|
|
168
226
|
### NetworkEdge Types
|
|
169
227
|
|
|
170
228
|
```tsx
|
|
171
|
-
type NetworkEdgeType = 'fiber' | 'ethernet' | 'power';
|
|
229
|
+
type NetworkEdgeType = 'fiber' | 'ethernet' | 'power' | 'smoothstep' | 'step' | 'thick-cable' | 'fibre-flow' | 'fibre-flow-link';
|
|
172
230
|
```
|
|
173
231
|
|
|
174
232
|
## Advanced Usage
|
|
@@ -222,6 +280,8 @@ const rackSchema: RackConfig[] = [
|
|
|
222
280
|
const nodes = buildNodesFromRackConfig(rackSchema);
|
|
223
281
|
```
|
|
224
282
|
|
|
283
|
+
Device images (e.g. server front/rear photos or SVGs) use `frontImageUrl` and `rearImageUrl` on each device; supported formats include PNG, SVG, JPEG, GIF, and WebP.
|
|
284
|
+
|
|
225
285
|
### Inventory Integration
|
|
226
286
|
|
|
227
287
|
```tsx
|
|
@@ -285,13 +345,13 @@ The library supports extensive theming through CSS variables:
|
|
|
285
345
|
|
|
286
346
|
### Prerequisites
|
|
287
347
|
|
|
288
|
-
- Node.js
|
|
348
|
+
- Node.js 22+
|
|
289
349
|
- npm, yarn, or pnpm
|
|
290
350
|
|
|
291
351
|
### Setup
|
|
292
352
|
|
|
293
353
|
```bash
|
|
294
|
-
|
|
354
|
+
Clone the repository, then:
|
|
295
355
|
cd react-networks/packages/network-diagrams
|
|
296
356
|
npm install
|
|
297
357
|
```
|
|
@@ -331,7 +391,7 @@ The library is distributed as:
|
|
|
331
391
|
|
|
332
392
|
## Contributing
|
|
333
393
|
|
|
334
|
-
We welcome contributions!
|
|
394
|
+
We welcome contributions! See `CONTRIBUTING.md` for details.
|
|
335
395
|
|
|
336
396
|
### Development Workflow
|
|
337
397
|
|
|
@@ -346,26 +406,15 @@ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) f
|
|
|
346
406
|
|
|
347
407
|
Dual-licensed under:
|
|
348
408
|
|
|
349
|
-
- **AGPL-3.0** (Free) - For open source, personal, and educational use. Copyleft applies.
|
|
350
|
-
- **Commercial** (Paid) - For proprietary/commercial use without copyleft obligations.
|
|
351
|
-
|
|
352
|
-
See [LICENSE](../../LICENSE) for details. By installing, you agree to use under either license. Contact us for commercial use.
|
|
353
|
-
|
|
354
|
-
## Support
|
|
409
|
+
- **AGPL-3.0** (Free) - For open source, personal, and educational use. Copyleft applies.
|
|
410
|
+
- **Commercial** (Paid) - For proprietary/commercial use without copyleft obligations.
|
|
355
411
|
|
|
356
|
-
|
|
357
|
-
- 📚 [API Documentation](docs/API.md)
|
|
358
|
-
- 🌐 [Documentation Site](../docs/) - Interactive docs with examples
|
|
359
|
-
- 🐛 [Issue Tracker](https://github.com/MP70/react-networks/issues)
|
|
360
|
-
- 💬 [Discussions](https://github.com/MP70/react-networks/discussions)
|
|
361
|
-
- 📧 [Email Support](mailto:info@serversearcher.com)
|
|
412
|
+
See `../../LICENSE` for details. By installing, you agree to use under either license.
|
|
362
413
|
|
|
363
414
|
## Acknowledgments
|
|
364
415
|
|
|
365
|
-
-
|
|
366
|
-
- Network inventory/CMDB projects for inspiration
|
|
367
|
-
- The open source community for feedback and contributions
|
|
416
|
+
- React Flow for the diagram foundation
|
|
368
417
|
|
|
369
418
|
---
|
|
370
419
|
|
|
371
|
-
Made
|
|
420
|
+
Made by [matt](https://github.com/MP70) from [rackout.net](https://rackout.net).
|
package/dist/index.css
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* Library styles for @react-networks
|
|
1
|
+
/* Library styles for @mp70/react-networks */
|
|
2
2
|
|
|
3
3
|
/* Edge zIndex styles for dynamic prominence */
|
|
4
4
|
.edge-prominent {
|
|
@@ -356,6 +356,80 @@
|
|
|
356
356
|
border-color: #3b82f6 !important;
|
|
357
357
|
}
|
|
358
358
|
|
|
359
|
+
/* Device node styles */
|
|
360
|
+
.device-node {
|
|
361
|
+
background-color: #1f2937;
|
|
362
|
+
background-image: var(--rn-device-bg-image, none);
|
|
363
|
+
background-position: var(--rn-device-bg-position, center);
|
|
364
|
+
background-repeat: var(--rn-device-bg-repeat, no-repeat);
|
|
365
|
+
background-size: var(--rn-device-bg-size, cover);
|
|
366
|
+
border: 1px solid var(--rn-device-border-color, #10b981);
|
|
367
|
+
border-radius: 2px;
|
|
368
|
+
box-shadow: var(--rn-device-box-shadow, 0 1px 2px rgba(0, 0, 0, 0.1));
|
|
369
|
+
box-sizing: border-box;
|
|
370
|
+
color: white;
|
|
371
|
+
cursor: grab;
|
|
372
|
+
display: flex;
|
|
373
|
+
flex-direction: column;
|
|
374
|
+
font-family: monospace;
|
|
375
|
+
font-size: 8px;
|
|
376
|
+
height: var(--rn-device-height, 20px);
|
|
377
|
+
justify-content: center;
|
|
378
|
+
left: var(--rn-device-left, auto);
|
|
379
|
+
margin: 0;
|
|
380
|
+
padding: 0;
|
|
381
|
+
position: relative;
|
|
382
|
+
transform: translateY(var(--rn-device-translate-y, 0px));
|
|
383
|
+
width: var(--rn-device-width, 100%);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
.device-node__content {
|
|
387
|
+
display: flex;
|
|
388
|
+
flex: 1;
|
|
389
|
+
flex-direction: column;
|
|
390
|
+
justify-content: center;
|
|
391
|
+
overflow: hidden;
|
|
392
|
+
padding: 2px;
|
|
393
|
+
text-align: center;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
.device-node__label {
|
|
397
|
+
font-size: 7px;
|
|
398
|
+
font-weight: bold;
|
|
399
|
+
line-height: 1.1;
|
|
400
|
+
overflow: hidden;
|
|
401
|
+
text-overflow: ellipsis;
|
|
402
|
+
white-space: nowrap;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
.device-node__manufacturer {
|
|
406
|
+
color: #9ca3af;
|
|
407
|
+
font-size: 6px;
|
|
408
|
+
line-height: 1;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
.device-node__u-indicator {
|
|
412
|
+
background: #374151;
|
|
413
|
+
border-radius: 1px;
|
|
414
|
+
bottom: 1px;
|
|
415
|
+
color: #9ca3af;
|
|
416
|
+
font-size: 6px;
|
|
417
|
+
line-height: 1;
|
|
418
|
+
padding: 1px 2px;
|
|
419
|
+
position: absolute;
|
|
420
|
+
right: 1px;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
.device-node__status-indicator {
|
|
424
|
+
background: var(--rn-device-status-color, #6b7280);
|
|
425
|
+
border-radius: 50%;
|
|
426
|
+
bottom: 1px;
|
|
427
|
+
height: 4px;
|
|
428
|
+
left: 1px;
|
|
429
|
+
position: absolute;
|
|
430
|
+
width: 4px;
|
|
431
|
+
}
|
|
432
|
+
|
|
359
433
|
/* Light mode adjustments */
|
|
360
434
|
.react-flow-light .coupler-node {
|
|
361
435
|
background: #f9fafb;
|
package/dist/index.css.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/styles/index.css"],"sourcesContent":["/* Library styles for @react-networks/network-diagrams */\n\n/* Edge zIndex styles for dynamic prominence */\n.edge-prominent {\n z-index: 1000 !important;\n opacity: 1 !important;\n}\n\n.edge-dimmed {\n z-index: 500 !important;\n opacity: 0.3 !important;\n}\n\n/* Dynamic zIndex classes */\n.edge-z-1000 {\n z-index: 1000 !important;\n}\n\n.edge-z-500 {\n z-index: 500 !important;\n}\n\n/* React Flow theming */\n.react-flow-dark {\n --react-flow-background: #1a1a1a;\n --react-flow-text: #ffffff;\n --react-flow-border: #404040;\n --react-flow-controls-bg: #2d2d2d;\n --react-flow-controls-border: #404040;\n --react-flow-minimap-bg: #2d2d2d;\n --react-flow-minimap-border: #404040;\n}\n\n.react-flow-light {\n --react-flow-background: #f5f5f5;\n --react-flow-text: #1a1a1a;\n --react-flow-border: #e9ecef;\n --react-flow-controls-bg: #f8f9fa;\n --react-flow-controls-border: #e9ecef;\n --react-flow-minimap-bg: #f8f9fa;\n --react-flow-minimap-border: #e9ecef;\n}\n\n/* Apply ReactFlow theming */\n.react-flow-dark .react-flow__background {\n background-color: var(--react-flow-background);\n}\n\n.react-flow-light .react-flow__background {\n background-color: var(--react-flow-background);\n}\n\n/* Ensure canvas background is always off-white in light mode */\n.react-flow-light .react-flow__viewport {\n background-color: #f5f5f5 !important;\n}\n\n.react-flow-light .react-flow {\n background-color: #f5f5f5;\n}\n\n.react-flow-dark .react-flow__controls {\n background-color: var(--react-flow-controls-bg);\n border-color: var(--react-flow-controls-border);\n}\n\n.react-flow-light .react-flow__controls {\n background-color: var(--react-flow-controls-bg);\n border-color: var(--react-flow-controls-border);\n}\n\n.react-flow-dark .react-flow__minimap {\n background-color: var(--react-flow-minimap-bg);\n border-color: var(--react-flow-minimap-border);\n}\n\n.react-flow-light .react-flow__minimap {\n background-color: var(--react-flow-minimap-bg);\n border-color: var(--react-flow-minimap-border);\n}\n\n.react-flow-dark .react-flow__controls-button {\n background-color: var(--react-flow-controls-bg);\n color: var(--react-flow-text);\n border-color: var(--react-flow-controls-border);\n}\n\n.react-flow-light .react-flow__controls-button {\n background-color: var(--react-flow-controls-bg);\n color: var(--react-flow-text);\n border-color: var(--react-flow-controls-border);\n}\n\n.react-flow-dark .react-flow__controls-button:hover {\n background-color: #4b5563;\n}\n\n.react-flow-light .react-flow__controls-button:hover {\n background-color: #e9ecef;\n}\n\n/* Mobile-friendly control buttons - larger touch targets */\n@media (max-width: 768px) {\n .react-flow__controls-button {\n width: 44px !important;\n height: 44px !important;\n min-width: 44px !important;\n min-height: 44px !important;\n }\n}\n\n/* Override React Flow default handle styles for tube fiber handles */\n/* Use CSS variables set by inline styles to override React Flow defaults */\n.react-flow__handle.tube-fiber-handle {\n border: none !important;\n transform: none !important;\n background-clip: padding-box !important;\n opacity: 1 !important;\n /* Ensure no default React Flow styles interfere */\n box-shadow: none !important;\n /* Don't set background here - let inline styles or specific rules handle it */\n}\n\n/* Tube fiber handles - use fiber color */\n.react-flow__handle.tube-fiber-handle {\n background: var(--fiber-bg-image, var(--fiber-bg)) !important;\n background-color: var(--fiber-bg) !important;\n}\n\n/* Fibre flow map handles */\n.react-flow__handle.fibre-flow-handle {\n border: none !important;\n transform: none !important;\n background-clip: padding-box !important;\n opacity: 1 !important;\n box-shadow: none !important;\n}\n\n.react-flow__handle.fibre-flow-handle {\n background: var(--fiber-bg-image, var(--fiber-bg)) !important;\n background-color: var(--fiber-bg) !important;\n background-image: var(--fiber-bg-image, none) !important;\n}\n\n\n.react-flow__handle-right.tube-fiber-handle {\n right: auto !important;\n}\n\n/* More specific selector to ensure override - target all possible React Flow handle states */\n/* Only apply to non-ribbon handles */\n.react-flow__node .react-flow__handle.tube-fiber-handle:not(.ribbon-bundle-handle),\n.react-flow__node .react-flow__handle.tube-fiber-handle:not(.ribbon-bundle-handle)[data-handlepos],\n.react-flow__handle.tube-fiber-handle:not(.ribbon-bundle-handle)[data-handlepos],\n.react-flow__handle.tube-fiber-handle:not(.ribbon-bundle-handle)[data-fiber-idx] {\n background: var(--fiber-bg-image, var(--fiber-bg)) !important;\n background-color: var(--fiber-bg) !important;\n background-image: var(--fiber-bg-image, none) !important;\n}\n\n/* Ribbon bundle handles - simple solid color (removed gradient complexity) */\n\n/* Connection animation - pulse effect when edge is first created */\n@keyframes edgeConnectPulse {\n 0% {\n opacity: 0;\n stroke-width: 1;\n }\n 50% {\n opacity: 1;\n stroke-width: 4;\n }\n 100% {\n opacity: 1;\n stroke-width: 2;\n }\n}\n\n.react-flow__edge.edge-connecting path,\n.react-flow__edge.edge-connecting .react-flow__edge-path {\n animation: edgeConnectPulse 1s ease-out;\n}\n\n/* Highlighted edge pulse + dash motion (trace paths) */\n@keyframes rnEdgeHighlightPulse {\n 0%,\n 100% {\n opacity: 0.85;\n stroke-width: var(--rn-edge-highlight-from, 2px);\n }\n 50% {\n opacity: 1;\n stroke-width: var(--rn-edge-highlight-to, 6px);\n }\n}\n\n@keyframes rnEdgeHighlightDash {\n 0% {\n stroke-dashoffset: 0;\n }\n 100% {\n stroke-dashoffset: -48;\n }\n}\n\n.rn-edge-highlight {\n animation: rnEdgeHighlightPulse 2.4s ease-in-out infinite,\n rnEdgeHighlightDash 1.8s linear infinite;\n opacity: 0.9;\n stroke-linecap: round;\n}\n\n/* Splice glow animation - fade in when both handles are connected */\n@keyframes spliceGlowFadeIn {\n 0% {\n opacity: 0;\n transform: translateX(-50%) scaleY(0.3);\n }\n 100% {\n opacity: 1;\n transform: translateX(-50%) scaleY(1);\n }\n}\n\n.splice-glow {\n animation: spliceGlowFadeIn 0.5s ease-out;\n transform-origin: center;\n}\n\n/* Splice text animation - fade in when both handles are connected */\n@keyframes spliceTextFadeIn {\n 0% {\n opacity: 0;\n transform: scale(0.8);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n/* Splice text overlay - blur and opacity for text readability */\n.splice-text-overlay {\n backdrop-filter: blur(2px);\n -webkit-backdrop-filter: blur(2px);\n}\n\n/* Dark mode overlay */\n.react-flow-dark .splice-text-overlay {\n background: rgba(0, 0, 0, 0.6);\n}\n\n/* Light mode overlay */\n.react-flow-light .splice-text-overlay {\n background: rgba(255, 255, 255, 0.7);\n}\n\n/* Splice text label - theme-aware colors */\n.splice-text-label {\n color: #fff;\n text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8), 0 0 2px rgba(0, 0, 0, 0.6);\n}\n\n.splice-text-label.animate-in {\n animation: spliceTextFadeIn 0.5s ease-out;\n transform-origin: center;\n}\n\n/* Light mode text */\n.react-flow-light .splice-text-label {\n color: #1a1a1a;\n text-shadow: 0 1px 2px rgba(255, 255, 255, 0.9), 0 0 4px rgba(255, 255, 255, 0.7);\n}\n\n/* Remove all borders from splice nodes */\n.react-flow__node[data-type=\"splice\"],\n.react-flow__node[data-type=\"splice\"] > div {\n border: none !important;\n outline: none !important;\n}\n\n.splice-node {\n background: transparent !important;\n border: none !important;\n outline: none !important;\n}\n\n/* Only remove box-shadow when not selected */\n.react-flow__node[data-type=\"splice\"]:not(.selected) > div,\n.splice-node:not(.selected) {\n box-shadow: none !important;\n}\n\n/* React Networks Attribution */\n.react-networks-attribution {\n padding: 0;\n margin: 0;\n z-index: 1000;\n}\n\n.react-networks-attribution-link {\n font-size: 7px;\n color: #9ca3af;\n text-decoration: none;\n font-family: ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, \"Liberation Mono\", monospace;\n transition: color 0.2s ease;\n padding: 1px 4px;\n border-radius: 2px;\n display: inline-block;\n background: rgba(0, 0, 0, 0.3);\n backdrop-filter: blur(4px);\n}\n\n.react-networks-attribution-link:hover {\n color: #e5e7eb;\n background: rgba(0, 0, 0, 0.4);\n}\n\n/* Light mode attribution */\n.react-flow-light .react-networks-attribution-link {\n color: #6b7280;\n background: rgba(255, 255, 255, 0.6);\n}\n\n.react-flow-light .react-networks-attribution-link:hover {\n color: #1a1a1a;\n background: rgba(255, 255, 255, 0.8);\n}\n\n/* Coupler node styles */\n.coupler-node {\n transition: box-shadow 0.2s ease;\n}\n\n.coupler-node.selected {\n box-shadow: 0 0 0 2px #3b82f6 !important;\n}\n\n/* Patch panel node styles */\n.patch-panel-node {\n transition: box-shadow 0.2s ease, border-color 0.2s ease;\n}\n\n.patch-panel-node.selected {\n box-shadow: 0 0 0 2px #3b82f6 !important;\n border-color: #3b82f6 !important;\n}\n\n/* Closure node styles */\n.closure-node {\n transition: box-shadow 0.2s ease, border-color 0.2s ease;\n}\n\n.closure-node.selected {\n box-shadow: 0 0 0 2px #3b82f6 !important;\n border-color: #3b82f6 !important;\n}\n\n/* Light mode adjustments */\n.react-flow-light .coupler-node {\n background: #f9fafb;\n color: #1f2937;\n border-color: #d1d5db;\n}\n\n.react-flow-light .patch-panel-node {\n background: transparent !important;\n color: #1f2937;\n border-color: #d1d5db;\n}\n\n.react-flow-light .closure-node {\n background: transparent !important;\n color: #1f2937;\n border-color: #d1d5db;\n}\n\n/* Triangle node styles */\n.react-flow__node[data-type=\"fibre-split\"],\n.react-flow__node.react-flow__node-fibre-split {\n background: transparent !important;\n border: none !important;\n padding: 0 !important;\n}\n\n.react-flow__node[data-type=\"fibre-split\"] > div,\n.react-flow__node.react-flow__node-fibre-split > div {\n background: transparent !important;\n border: none !important;\n padding: 0 !important;\n box-shadow: none !important;\n overflow: visible !important;\n}\n\n.react-flow__node[data-type=\"fibre-split\"] svg,\n.react-flow__node.react-flow__node-fibre-split svg {\n display: block !important;\n visibility: visible !important;\n opacity: 1 !important;\n}\n\n.triangle-node {\n position: relative !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n background: transparent !important;\n border: none !important;\n padding: 0 !important;\n margin: 0 !important;\n box-shadow: none !important;\n overflow: visible !important;\n box-sizing: border-box !important;\n}\n\n\n.triangle-node-text {\n text-align: center;\n position: relative;\n z-index: 2;\n width: 46px;\n height: 46px;\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 0;\n color: #000000;\n font-weight: bold;\n font-size: 12px;\n}\n\n/* Cable node rotation */\n.cable-node-rotated {\n transform-origin: center center !important;\n}\n\n/* Ensure Fibre Flow edges render with full saturation and aren't affected by node overlays */\n.react-flow__edge[data-type=\"fibre-flow\"] path,\n.react-flow__edge[data-type=\"fibre-flow\"] .react-flow__edge-path {\n opacity: 1 !important;\n stroke-opacity: 1 !important;\n mix-blend-mode: normal !important;\n filter: none !important;\n}\n\n.react-flow__edge[data-type=\"fibre-flow-link\"] path,\n.react-flow__edge[data-type=\"fibre-flow-link\"] .react-flow__edge-path {\n opacity: 1 !important;\n stroke-opacity: 1 !important;\n mix-blend-mode: normal !important;\n filter: none !important;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/styles/index.css"],"sourcesContent":["/* Library styles for @mp70/react-networks */\n\n/* Edge zIndex styles for dynamic prominence */\n.edge-prominent {\n z-index: 1000 !important;\n opacity: 1 !important;\n}\n\n.edge-dimmed {\n z-index: 500 !important;\n opacity: 0.3 !important;\n}\n\n/* Dynamic zIndex classes */\n.edge-z-1000 {\n z-index: 1000 !important;\n}\n\n.edge-z-500 {\n z-index: 500 !important;\n}\n\n/* React Flow theming */\n.react-flow-dark {\n --react-flow-background: #1a1a1a;\n --react-flow-text: #ffffff;\n --react-flow-border: #404040;\n --react-flow-controls-bg: #2d2d2d;\n --react-flow-controls-border: #404040;\n --react-flow-minimap-bg: #2d2d2d;\n --react-flow-minimap-border: #404040;\n}\n\n.react-flow-light {\n --react-flow-background: #f5f5f5;\n --react-flow-text: #1a1a1a;\n --react-flow-border: #e9ecef;\n --react-flow-controls-bg: #f8f9fa;\n --react-flow-controls-border: #e9ecef;\n --react-flow-minimap-bg: #f8f9fa;\n --react-flow-minimap-border: #e9ecef;\n}\n\n/* Apply ReactFlow theming */\n.react-flow-dark .react-flow__background {\n background-color: var(--react-flow-background);\n}\n\n.react-flow-light .react-flow__background {\n background-color: var(--react-flow-background);\n}\n\n/* Ensure canvas background is always off-white in light mode */\n.react-flow-light .react-flow__viewport {\n background-color: #f5f5f5 !important;\n}\n\n.react-flow-light .react-flow {\n background-color: #f5f5f5;\n}\n\n.react-flow-dark .react-flow__controls {\n background-color: var(--react-flow-controls-bg);\n border-color: var(--react-flow-controls-border);\n}\n\n.react-flow-light .react-flow__controls {\n background-color: var(--react-flow-controls-bg);\n border-color: var(--react-flow-controls-border);\n}\n\n.react-flow-dark .react-flow__minimap {\n background-color: var(--react-flow-minimap-bg);\n border-color: var(--react-flow-minimap-border);\n}\n\n.react-flow-light .react-flow__minimap {\n background-color: var(--react-flow-minimap-bg);\n border-color: var(--react-flow-minimap-border);\n}\n\n.react-flow-dark .react-flow__controls-button {\n background-color: var(--react-flow-controls-bg);\n color: var(--react-flow-text);\n border-color: var(--react-flow-controls-border);\n}\n\n.react-flow-light .react-flow__controls-button {\n background-color: var(--react-flow-controls-bg);\n color: var(--react-flow-text);\n border-color: var(--react-flow-controls-border);\n}\n\n.react-flow-dark .react-flow__controls-button:hover {\n background-color: #4b5563;\n}\n\n.react-flow-light .react-flow__controls-button:hover {\n background-color: #e9ecef;\n}\n\n/* Mobile-friendly control buttons - larger touch targets */\n@media (max-width: 768px) {\n .react-flow__controls-button {\n width: 44px !important;\n height: 44px !important;\n min-width: 44px !important;\n min-height: 44px !important;\n }\n}\n\n/* Override React Flow default handle styles for tube fiber handles */\n/* Use CSS variables set by inline styles to override React Flow defaults */\n.react-flow__handle.tube-fiber-handle {\n border: none !important;\n transform: none !important;\n background-clip: padding-box !important;\n opacity: 1 !important;\n /* Ensure no default React Flow styles interfere */\n box-shadow: none !important;\n /* Don't set background here - let inline styles or specific rules handle it */\n}\n\n/* Tube fiber handles - use fiber color */\n.react-flow__handle.tube-fiber-handle {\n background: var(--fiber-bg-image, var(--fiber-bg)) !important;\n background-color: var(--fiber-bg) !important;\n}\n\n/* Fibre flow map handles */\n.react-flow__handle.fibre-flow-handle {\n border: none !important;\n transform: none !important;\n background-clip: padding-box !important;\n opacity: 1 !important;\n box-shadow: none !important;\n}\n\n.react-flow__handle.fibre-flow-handle {\n background: var(--fiber-bg-image, var(--fiber-bg)) !important;\n background-color: var(--fiber-bg) !important;\n background-image: var(--fiber-bg-image, none) !important;\n}\n\n\n.react-flow__handle-right.tube-fiber-handle {\n right: auto !important;\n}\n\n/* More specific selector to ensure override - target all possible React Flow handle states */\n/* Only apply to non-ribbon handles */\n.react-flow__node .react-flow__handle.tube-fiber-handle:not(.ribbon-bundle-handle),\n.react-flow__node .react-flow__handle.tube-fiber-handle:not(.ribbon-bundle-handle)[data-handlepos],\n.react-flow__handle.tube-fiber-handle:not(.ribbon-bundle-handle)[data-handlepos],\n.react-flow__handle.tube-fiber-handle:not(.ribbon-bundle-handle)[data-fiber-idx] {\n background: var(--fiber-bg-image, var(--fiber-bg)) !important;\n background-color: var(--fiber-bg) !important;\n background-image: var(--fiber-bg-image, none) !important;\n}\n\n/* Ribbon bundle handles - simple solid color (removed gradient complexity) */\n\n/* Connection animation - pulse effect when edge is first created */\n@keyframes edgeConnectPulse {\n 0% {\n opacity: 0;\n stroke-width: 1;\n }\n 50% {\n opacity: 1;\n stroke-width: 4;\n }\n 100% {\n opacity: 1;\n stroke-width: 2;\n }\n}\n\n.react-flow__edge.edge-connecting path,\n.react-flow__edge.edge-connecting .react-flow__edge-path {\n animation: edgeConnectPulse 1s ease-out;\n}\n\n/* Highlighted edge pulse + dash motion (trace paths) */\n@keyframes rnEdgeHighlightPulse {\n 0%,\n 100% {\n opacity: 0.85;\n stroke-width: var(--rn-edge-highlight-from, 2px);\n }\n 50% {\n opacity: 1;\n stroke-width: var(--rn-edge-highlight-to, 6px);\n }\n}\n\n@keyframes rnEdgeHighlightDash {\n 0% {\n stroke-dashoffset: 0;\n }\n 100% {\n stroke-dashoffset: -48;\n }\n}\n\n.rn-edge-highlight {\n animation: rnEdgeHighlightPulse 2.4s ease-in-out infinite,\n rnEdgeHighlightDash 1.8s linear infinite;\n opacity: 0.9;\n stroke-linecap: round;\n}\n\n/* Splice glow animation - fade in when both handles are connected */\n@keyframes spliceGlowFadeIn {\n 0% {\n opacity: 0;\n transform: translateX(-50%) scaleY(0.3);\n }\n 100% {\n opacity: 1;\n transform: translateX(-50%) scaleY(1);\n }\n}\n\n.splice-glow {\n animation: spliceGlowFadeIn 0.5s ease-out;\n transform-origin: center;\n}\n\n/* Splice text animation - fade in when both handles are connected */\n@keyframes spliceTextFadeIn {\n 0% {\n opacity: 0;\n transform: scale(0.8);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n/* Splice text overlay - blur and opacity for text readability */\n.splice-text-overlay {\n backdrop-filter: blur(2px);\n -webkit-backdrop-filter: blur(2px);\n}\n\n/* Dark mode overlay */\n.react-flow-dark .splice-text-overlay {\n background: rgba(0, 0, 0, 0.6);\n}\n\n/* Light mode overlay */\n.react-flow-light .splice-text-overlay {\n background: rgba(255, 255, 255, 0.7);\n}\n\n/* Splice text label - theme-aware colors */\n.splice-text-label {\n color: #fff;\n text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8), 0 0 2px rgba(0, 0, 0, 0.6);\n}\n\n.splice-text-label.animate-in {\n animation: spliceTextFadeIn 0.5s ease-out;\n transform-origin: center;\n}\n\n/* Light mode text */\n.react-flow-light .splice-text-label {\n color: #1a1a1a;\n text-shadow: 0 1px 2px rgba(255, 255, 255, 0.9), 0 0 4px rgba(255, 255, 255, 0.7);\n}\n\n/* Remove all borders from splice nodes */\n.react-flow__node[data-type=\"splice\"],\n.react-flow__node[data-type=\"splice\"] > div {\n border: none !important;\n outline: none !important;\n}\n\n.splice-node {\n background: transparent !important;\n border: none !important;\n outline: none !important;\n}\n\n/* Only remove box-shadow when not selected */\n.react-flow__node[data-type=\"splice\"]:not(.selected) > div,\n.splice-node:not(.selected) {\n box-shadow: none !important;\n}\n\n/* React Networks Attribution */\n.react-networks-attribution {\n padding: 0;\n margin: 0;\n z-index: 1000;\n}\n\n.react-networks-attribution-link {\n font-size: 7px;\n color: #9ca3af;\n text-decoration: none;\n font-family: ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, \"Liberation Mono\", monospace;\n transition: color 0.2s ease;\n padding: 1px 4px;\n border-radius: 2px;\n display: inline-block;\n background: rgba(0, 0, 0, 0.3);\n backdrop-filter: blur(4px);\n}\n\n.react-networks-attribution-link:hover {\n color: #e5e7eb;\n background: rgba(0, 0, 0, 0.4);\n}\n\n/* Light mode attribution */\n.react-flow-light .react-networks-attribution-link {\n color: #6b7280;\n background: rgba(255, 255, 255, 0.6);\n}\n\n.react-flow-light .react-networks-attribution-link:hover {\n color: #1a1a1a;\n background: rgba(255, 255, 255, 0.8);\n}\n\n/* Coupler node styles */\n.coupler-node {\n transition: box-shadow 0.2s ease;\n}\n\n.coupler-node.selected {\n box-shadow: 0 0 0 2px #3b82f6 !important;\n}\n\n/* Patch panel node styles */\n.patch-panel-node {\n transition: box-shadow 0.2s ease, border-color 0.2s ease;\n}\n\n.patch-panel-node.selected {\n box-shadow: 0 0 0 2px #3b82f6 !important;\n border-color: #3b82f6 !important;\n}\n\n/* Closure node styles */\n.closure-node {\n transition: box-shadow 0.2s ease, border-color 0.2s ease;\n}\n\n.closure-node.selected {\n box-shadow: 0 0 0 2px #3b82f6 !important;\n border-color: #3b82f6 !important;\n}\n\n/* Device node styles */\n.device-node {\n background-color: #1f2937;\n background-image: var(--rn-device-bg-image, none);\n background-position: var(--rn-device-bg-position, center);\n background-repeat: var(--rn-device-bg-repeat, no-repeat);\n background-size: var(--rn-device-bg-size, cover);\n border: 1px solid var(--rn-device-border-color, #10b981);\n border-radius: 2px;\n box-shadow: var(--rn-device-box-shadow, 0 1px 2px rgba(0, 0, 0, 0.1));\n box-sizing: border-box;\n color: white;\n cursor: grab;\n display: flex;\n flex-direction: column;\n font-family: monospace;\n font-size: 8px;\n height: var(--rn-device-height, 20px);\n justify-content: center;\n left: var(--rn-device-left, auto);\n margin: 0;\n padding: 0;\n position: relative;\n transform: translateY(var(--rn-device-translate-y, 0px));\n width: var(--rn-device-width, 100%);\n}\n\n.device-node__content {\n display: flex;\n flex: 1;\n flex-direction: column;\n justify-content: center;\n overflow: hidden;\n padding: 2px;\n text-align: center;\n}\n\n.device-node__label {\n font-size: 7px;\n font-weight: bold;\n line-height: 1.1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.device-node__manufacturer {\n color: #9ca3af;\n font-size: 6px;\n line-height: 1;\n}\n\n.device-node__u-indicator {\n background: #374151;\n border-radius: 1px;\n bottom: 1px;\n color: #9ca3af;\n font-size: 6px;\n line-height: 1;\n padding: 1px 2px;\n position: absolute;\n right: 1px;\n}\n\n.device-node__status-indicator {\n background: var(--rn-device-status-color, #6b7280);\n border-radius: 50%;\n bottom: 1px;\n height: 4px;\n left: 1px;\n position: absolute;\n width: 4px;\n}\n\n/* Light mode adjustments */\n.react-flow-light .coupler-node {\n background: #f9fafb;\n color: #1f2937;\n border-color: #d1d5db;\n}\n\n.react-flow-light .patch-panel-node {\n background: transparent !important;\n color: #1f2937;\n border-color: #d1d5db;\n}\n\n.react-flow-light .closure-node {\n background: transparent !important;\n color: #1f2937;\n border-color: #d1d5db;\n}\n\n/* Triangle node styles */\n.react-flow__node[data-type=\"fibre-split\"],\n.react-flow__node.react-flow__node-fibre-split {\n background: transparent !important;\n border: none !important;\n padding: 0 !important;\n}\n\n.react-flow__node[data-type=\"fibre-split\"] > div,\n.react-flow__node.react-flow__node-fibre-split > div {\n background: transparent !important;\n border: none !important;\n padding: 0 !important;\n box-shadow: none !important;\n overflow: visible !important;\n}\n\n.react-flow__node[data-type=\"fibre-split\"] svg,\n.react-flow__node.react-flow__node-fibre-split svg {\n display: block !important;\n visibility: visible !important;\n opacity: 1 !important;\n}\n\n.triangle-node {\n position: relative !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n background: transparent !important;\n border: none !important;\n padding: 0 !important;\n margin: 0 !important;\n box-shadow: none !important;\n overflow: visible !important;\n box-sizing: border-box !important;\n}\n\n\n.triangle-node-text {\n text-align: center;\n position: relative;\n z-index: 2;\n width: 46px;\n height: 46px;\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 0;\n color: #000000;\n font-weight: bold;\n font-size: 12px;\n}\n\n/* Cable node rotation */\n.cable-node-rotated {\n transform-origin: center center !important;\n}\n\n/* Ensure Fibre Flow edges render with full saturation and aren't affected by node overlays */\n.react-flow__edge[data-type=\"fibre-flow\"] path,\n.react-flow__edge[data-type=\"fibre-flow\"] .react-flow__edge-path {\n opacity: 1 !important;\n stroke-opacity: 1 !important;\n mix-blend-mode: normal !important;\n filter: none !important;\n}\n\n.react-flow__edge[data-type=\"fibre-flow-link\"] path,\n.react-flow__edge[data-type=\"fibre-flow-link\"] .react-flow__edge-path {\n opacity: 1 !important;\n stroke-opacity: 1 !important;\n mix-blend-mode: normal !important;\n filter: none !important;\n}\n"],"mappings":"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","names":[]}
|