@mp70/react-networks 0.1.8-alpha → 0.1.8-beta

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 CHANGED
@@ -6,20 +6,20 @@
6
6
 
7
7
  A production-ready 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
- ## Features
9
+ ## Features
10
10
 
11
- - **🏗️ Rack Management**: Full support for 19" rack units with exact U positioning
12
- - **🔌 Device Placement**: Drag and drop devices with automatic U position snapping
13
- - **🌐 Fiber Networks**: Visual representation of fiber connections and patch panels
14
- - **⚡ Power Distribution**: Vertical PDU support with power connections
15
- - **👁️ View Switching**: Front/rear view switching for devices and racks
16
- - **📐 Rack Alignment**: Align rack bottoms to the same horizontal plane
17
- - **🔗 Inventory Integration**: Built-in helpers to import/export generic inventory/CMDB data
18
- - **🎨 Customizable**: Extensive styling and theming options
19
- - **📱 Responsive**: Works on desktop and mobile devices
20
- - **🔧 TypeScript**: Full TypeScript support with comprehensive type definitions
11
+ - **Rack Management**: Full support for 19" rack units with exact U positioning
12
+ - **Device Placement**: Drag and drop devices with automatic U position snapping
13
+ - **Fiber Networks**: Visual representation of fiber connections and patch panels
14
+ - **Power Distribution**: Vertical PDU support with power connections
15
+ - **View Switching**: Front/rear view switching for devices and racks
16
+ - **Rack Alignment**: Align rack bottoms to the same horizontal plane
17
+ - **Inventory Integration**: Built-in helpers to import/export generic inventory/CMDB data
18
+ - **Customizable**: Extensive styling and theming options
19
+ - **Responsive**: Works on desktop and mobile devices
20
+ - **TypeScript**: Full TypeScript support with comprehensive type definitions
21
21
 
22
- ## 🚀 Quick Start
22
+ ## Quick Start
23
23
 
24
24
  ### Installation
25
25
 
@@ -85,7 +85,7 @@ function App() {
85
85
  export default App;
86
86
  ```
87
87
 
88
- ## 📚 Documentation
88
+ ## Documentation
89
89
 
90
90
  ### API Reference
91
91
 
@@ -139,7 +139,7 @@ type NetworkNodeType =
139
139
  type NetworkEdgeType = 'fiber' | 'ethernet' | 'power';
140
140
  ```
141
141
 
142
- ## 🏗️ Advanced Usage
142
+ ## Advanced Usage
143
143
 
144
144
  ### Rack Configuration
145
145
 
@@ -218,7 +218,7 @@ import '@mp70/react-networks/index.css';
218
218
  }
219
219
  ```
220
220
 
221
- ## 🎨 Theming
221
+ ## Theming
222
222
 
223
223
  The library supports extensive theming through CSS variables:
224
224
 
@@ -249,7 +249,7 @@ The library supports extensive theming through CSS variables:
249
249
  }
250
250
  ```
251
251
 
252
- ## 🔧 Development
252
+ ## Development
253
253
 
254
254
  ### Prerequisites
255
255
 
@@ -288,7 +288,7 @@ npm test
288
288
  npm run lint
289
289
  ```
290
290
 
291
- ## 📦 Distribution
291
+ ## Distribution
292
292
 
293
293
  The library is distributed as:
294
294
 
@@ -297,7 +297,7 @@ The library is distributed as:
297
297
  - **TypeScript**: `dist/index.d.ts`
298
298
  - **CSS**: `dist/index.css`
299
299
 
300
- ## 🤝 Contributing
300
+ ## Contributing
301
301
 
302
302
  We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
303
303
 
@@ -310,7 +310,7 @@ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) f
310
310
  5. Run the test suite
311
311
  6. Submit a pull request
312
312
 
313
- ## 📄 License
313
+ ## License
314
314
 
315
315
  Dual-licensed under:
316
316
 
@@ -319,15 +319,15 @@ Dual-licensed under:
319
319
 
320
320
  See [LICENSE](../../LICENSE) for details. By installing, you agree to use under either license. Contact us for commercial use.
321
321
 
322
- ## 🆘 Support
322
+ ## Support
323
323
 
324
- - 📖 [Documentation](../../README.md)
325
- - 📚 [API Documentation](docs/API.md)
326
- - 🐛 [Issue Tracker](https://github.com/MP70/react-networks/issues)
327
- - 💬 [Discussions](https://github.com/MP70/react-networks/discussions)
328
- - 📧 [Email Support](mailto:info@serversearcher.com)
324
+ - [Documentation](../../README.md)
325
+ - [API Documentation](docs/API.md)
326
+ - [Issue Tracker](https://github.com/MP70)
327
+ - [Discussions](https://github.com/MP70)
328
+ - [Email Support](mailto:info@serversearcher.com)
329
329
 
330
- ## 🙏 Acknowledgments
330
+ ## Acknowledgments
331
331
 
332
332
  - [React Flow](https://reactflow.dev) for the excellent diagram foundation
333
333
  - Network inventory/CMDB projects for inspiration
@@ -335,4 +335,4 @@ See [LICENSE](../../LICENSE) for details. By installing, you agree to use under
335
335
 
336
336
  ---
337
337
 
338
- Made with ❤️ by [Matt Pickering](https://github.com/MP70)
338
+ Made with love by [Matt Pickering](https://github.com/MP70)
package/dist/index.css CHANGED
@@ -99,6 +99,16 @@
99
99
  background-color: #e9ecef;
100
100
  }
101
101
 
102
+ /* Mobile-friendly control buttons - larger touch targets */
103
+ @media (max-width: 768px) {
104
+ .react-flow__controls-button {
105
+ width: 44px !important;
106
+ height: 44px !important;
107
+ min-width: 44px !important;
108
+ min-height: 44px !important;
109
+ }
110
+ }
111
+
102
112
  /* Override React Flow default handle styles for tube fiber handles */
103
113
  /* Use CSS variables set by inline styles to override React Flow defaults */
104
114
  .react-flow__handle.tube-fiber-handle {
@@ -106,27 +116,35 @@
106
116
  transform: none !important;
107
117
  background-clip: padding-box !important;
108
118
  opacity: 1 !important;
109
- /* Remove React Flow's default background completely */
110
- background: var(--fiber-bg-image, var(--fiber-bg)) !important;
111
- background-color: var(--fiber-bg) !important;
112
119
  /* Ensure no default React Flow styles interfere */
113
120
  box-shadow: none !important;
121
+ /* Don't set background here - let inline styles or specific rules handle it */
114
122
  }
115
123
 
124
+ /* Tube fiber handles - use fiber color */
125
+ .react-flow__handle.tube-fiber-handle {
126
+ background: var(--fiber-bg-image, var(--fiber-bg)) !important;
127
+ background-color: var(--fiber-bg) !important;
128
+ }
129
+
130
+
116
131
  .react-flow__handle-right.tube-fiber-handle {
117
132
  right: auto !important;
118
133
  }
119
134
 
120
135
  /* More specific selector to ensure override - target all possible React Flow handle states */
121
- .react-flow__node .react-flow__handle.tube-fiber-handle,
122
- .react-flow__node .react-flow__handle.tube-fiber-handle[data-handlepos],
123
- .react-flow__handle.tube-fiber-handle[data-handlepos],
124
- .react-flow__handle.tube-fiber-handle[data-fiber-idx] {
136
+ /* Only apply to non-ribbon handles */
137
+ .react-flow__node .react-flow__handle.tube-fiber-handle:not(.ribbon-bundle-handle),
138
+ .react-flow__node .react-flow__handle.tube-fiber-handle:not(.ribbon-bundle-handle)[data-handlepos],
139
+ .react-flow__handle.tube-fiber-handle:not(.ribbon-bundle-handle)[data-handlepos],
140
+ .react-flow__handle.tube-fiber-handle:not(.ribbon-bundle-handle)[data-fiber-idx] {
125
141
  background: var(--fiber-bg-image, var(--fiber-bg)) !important;
126
142
  background-color: var(--fiber-bg) !important;
127
143
  background-image: var(--fiber-bg-image, none) !important;
128
144
  }
129
145
 
146
+ /* Ribbon bundle handles - simple solid color (removed gradient complexity) */
147
+
130
148
  /* Connection animation - pulse effect when edge is first created */
131
149
  @keyframes edgeConnectPulse {
132
150
  0% {
@@ -148,6 +166,35 @@
148
166
  animation: edgeConnectPulse 1s ease-out;
149
167
  }
150
168
 
169
+ /* Highlighted edge pulse + dash motion (trace paths) */
170
+ @keyframes rnEdgeHighlightPulse {
171
+ 0%,
172
+ 100% {
173
+ opacity: 0.85;
174
+ stroke-width: var(--rn-edge-highlight-from, 2px);
175
+ }
176
+ 50% {
177
+ opacity: 1;
178
+ stroke-width: var(--rn-edge-highlight-to, 6px);
179
+ }
180
+ }
181
+
182
+ @keyframes rnEdgeHighlightDash {
183
+ 0% {
184
+ stroke-dashoffset: 0;
185
+ }
186
+ 100% {
187
+ stroke-dashoffset: -48;
188
+ }
189
+ }
190
+
191
+ .rn-edge-highlight {
192
+ animation: rnEdgeHighlightPulse 2.4s ease-in-out infinite,
193
+ rnEdgeHighlightDash 1.8s linear infinite;
194
+ opacity: 0.9;
195
+ stroke-linecap: round;
196
+ }
197
+
151
198
  /* Splice glow animation - fade in when both handles are connected */
152
199
  @keyframes spliceGlowFadeIn {
153
200
  0% {
@@ -218,6 +265,7 @@
218
265
  }
219
266
 
220
267
  .splice-node {
268
+ background: transparent !important;
221
269
  border: none !important;
222
270
  outline: none !important;
223
271
  }
@@ -239,7 +287,7 @@
239
287
  font-size: 7px;
240
288
  color: #9ca3af;
241
289
  text-decoration: none;
242
- font-family: Inter, system-ui, -apple-system, sans-serif;
290
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
243
291
  transition: color 0.2s ease;
244
292
  padding: 1px 4px;
245
293
  border-radius: 2px;
@@ -312,3 +360,61 @@
312
360
  border-color: #d1d5db;
313
361
  }
314
362
 
363
+ /* Triangle node styles */
364
+ .react-flow__node[data-type="fibre-split"],
365
+ .react-flow__node.react-flow__node-fibre-split {
366
+ background: transparent !important;
367
+ border: none !important;
368
+ padding: 0 !important;
369
+ }
370
+
371
+ .react-flow__node[data-type="fibre-split"] > div,
372
+ .react-flow__node.react-flow__node-fibre-split > div {
373
+ background: transparent !important;
374
+ border: none !important;
375
+ padding: 0 !important;
376
+ box-shadow: none !important;
377
+ overflow: visible !important;
378
+ }
379
+
380
+ .react-flow__node[data-type="fibre-split"] svg,
381
+ .react-flow__node.react-flow__node-fibre-split svg {
382
+ display: block !important;
383
+ visibility: visible !important;
384
+ opacity: 1 !important;
385
+ }
386
+
387
+ .triangle-node {
388
+ position: relative !important;
389
+ display: flex !important;
390
+ align-items: center !important;
391
+ justify-content: center !important;
392
+ background: transparent !important;
393
+ border: none !important;
394
+ padding: 0 !important;
395
+ margin: 0 !important;
396
+ box-shadow: none !important;
397
+ overflow: visible !important;
398
+ box-sizing: border-box !important;
399
+ }
400
+
401
+
402
+ .triangle-node-text {
403
+ text-align: center;
404
+ position: relative;
405
+ z-index: 2;
406
+ width: 46px;
407
+ height: 46px;
408
+ display: flex;
409
+ align-items: center;
410
+ justify-content: center;
411
+ margin: 0;
412
+ color: #000000;
413
+ font-weight: bold;
414
+ font-size: 12px;
415
+ }
416
+
417
+ /* Cable node rotation */
418
+ .cable-node-rotated {
419
+ transform-origin: center center !important;
420
+ }
@@ -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/* 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 /* Remove React Flow's default background completely */\n background: var(--fiber-bg-image, var(--fiber-bg)) !important;\n background-color: var(--fiber-bg) !important;\n /* Ensure no default React Flow styles interfere */\n box-shadow: none !important;\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.react-flow__node .react-flow__handle.tube-fiber-handle,\n.react-flow__node .react-flow__handle.tube-fiber-handle[data-handlepos],\n.react-flow__handle.tube-fiber-handle[data-handlepos],\n.react-flow__handle.tube-fiber-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/* 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/* 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 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: Inter, system-ui, -apple-system, sans-serif;\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"],"mappings":"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","names":[]}
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\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"],"mappings":"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","names":[]}
package/dist/index.d.mts CHANGED
@@ -15,13 +15,18 @@ declare enum Width {
15
15
  * Port configuration for network devices
16
16
  * @public
17
17
  */
18
+ /**
19
+ * Port type enumeration
20
+ * @public
21
+ */
22
+ type PortType = 'ethernet' | 'fiber' | 'console' | 'mgmt' | 'usb' | 'power_ac' | 'power_c13' | 'power_c19';
18
23
  interface Port {
19
24
  /** Display label for the port */
20
25
  label: string;
21
26
  /** Whether the port is currently connected */
22
27
  connected: boolean;
23
28
  /** Type of port for styling and validation */
24
- type?: 'ethernet' | 'fiber' | 'console' | 'mgmt' | 'usb' | 'power_ac' | 'power_c13' | 'power_c19';
29
+ type?: PortType;
25
30
  /** Cable type for connection validation */
26
31
  cableType?: 'smf' | 'cat6' | 'om3' | 'om4' | 'om5' | 'cat5e' | 'cat6a' | 'cat7' | 'fiber' | 'ethernet';
27
32
  }
@@ -39,7 +44,7 @@ interface PortBlock {
39
44
  * Network node types supported by the diagram
40
45
  * @public
41
46
  */
42
- type NetworkNodeType = 'rack' | 'switch' | 'router' | 'server' | 'fiber' | 'patch-panel' | 'device' | 'vertical-pdu' | 'splice' | 'splice-tray' | 'tube' | 'cable' | 'coupler' | 'closure';
47
+ type NetworkNodeType = 'rack' | 'switch' | 'router' | 'server' | 'fiber' | 'patch-panel' | 'device' | 'vertical-pdu' | 'splice' | 'splice-tray' | 'tube' | 'cable' | 'multi-tube-cable' | 'coupler' | 'closure' | 'fibre-split';
43
48
  /**
44
49
  * Device status states
45
50
  * @public
@@ -136,12 +141,20 @@ interface NetworkNode {
136
141
  panelWidth?: number;
137
142
  /** Height override for container nodes (patch-panel, closure) */
138
143
  panelHeight?: number;
144
+ /** Optional rack width in pixels (for rack nodes, default: 300px) */
145
+ rackWidthPx?: number;
139
146
  /** Number of rows for container nodes (patch-panel, closure) */
140
147
  rows?: number;
141
148
  /** Number of columns for container nodes (patch-panel, closure) */
142
149
  cols?: number;
143
150
  /** Header text for container nodes */
144
151
  header?: string;
152
+ /** Type of fibre splitter: 'splitter' or 'WDM' (default: 'splitter') */
153
+ splitterType?: 'splitter' | 'WDM';
154
+ /** Number of input fibers on the left (1 or 2, default: 1) */
155
+ inputCount?: number;
156
+ /** Number of output fibers on the right (1-64, default: 8) */
157
+ outputCount?: number;
145
158
  /** Additional custom properties */
146
159
  [key: string]: any;
147
160
  };
@@ -178,6 +191,18 @@ interface NetworkEdge {
178
191
  color?: string;
179
192
  /** Edge kind for styling/validation */
180
193
  kind?: 'fiber' | 'power' | 'network';
194
+ /** Whether this edge represents a ribbon fiber connection */
195
+ isRibbon?: boolean;
196
+ /** Array of fiber IDs for ribbon mode (6-12 fibers) */
197
+ ribbonFiberIds?: number[];
198
+ /** Highlight edge with a pulsing stroke */
199
+ highlight?: boolean;
200
+ /** Override highlight color (defaults to edge color) */
201
+ highlightColor?: string;
202
+ /** Override highlight max stroke width */
203
+ highlightWidth?: number;
204
+ /** Optional tag for grouping edges in demos */
205
+ traceTag?: string;
181
206
  /** Additional custom properties */
182
207
  [key: string]: any;
183
208
  };
@@ -209,6 +234,8 @@ interface RackConfig {
209
234
  customHeaderText?: string;
210
235
  /** Devices mounted in the rack */
211
236
  devices: RackDevice[];
237
+ /** Optional rack width in pixels (default: 300px which represents standard 48.26cm/19" rack) */
238
+ rackWidthPx?: number;
212
239
  }
213
240
  /**
214
241
  * Device mounted in a rack
@@ -279,6 +306,10 @@ interface SpliceConfig {
279
306
  holder: number;
280
307
  /** Loss value in dB */
281
308
  lossDb?: number;
309
+ /** Splice mode: 'single' for individual fiber, 'ribbon' for ribbon splices */
310
+ mode?: 'single' | 'ribbon';
311
+ /** For ribbon mode: array of fiber IDs (6-12) in the ribbon */
312
+ ribbonFiberIds?: number[];
282
313
  }
283
314
  /**
284
315
  * Splice tray configuration structure
@@ -343,6 +374,9 @@ interface NetworkDiagramProps {
343
374
  setNodes: (nodes: any[]) => void;
344
375
  setEdges: (edges: any[]) => void;
345
376
  toImage: (options?: any) => Promise<string>;
377
+ getNodes: () => any[];
378
+ getEdges: () => any[];
379
+ fitView: (options?: any) => void;
346
380
  }) => void;
347
381
  /** Show download button */
348
382
  showDownloadButton?: boolean;
@@ -352,12 +386,16 @@ interface NetworkDiagramProps {
352
386
  downloadButtonText?: string;
353
387
  /** Download button styling options */
354
388
  downloadButtonStyle?: React.CSSProperties;
355
- /** Allow reconnecting existing edges from either end */
356
- allowReconnectExisting?: boolean;
357
389
  /** Use smoothstep edges for tube connections (both tube-to-cable and cable-to-tube). Default is fiber. */
358
390
  useSmoothstepEdgesForTubes?: boolean;
359
391
  /** Enable connecting edges by clicking on handles. When true, increases handle sizes for better touch targets. Default is true. */
360
392
  connectOnClick?: boolean;
393
+ /** Disable panning on drag. Default is false. */
394
+ panOnDrag?: boolean;
395
+ /** Disable panning on scroll. Default is true. */
396
+ panOnScroll?: boolean;
397
+ /** Disable zooming on scroll. Default is true. */
398
+ zoomOnScroll?: boolean;
361
399
  }
362
400
 
363
401
  declare const NetworkDiagram: React$1.FC<NetworkDiagramProps>;
@@ -399,18 +437,34 @@ declare const TubeNode: React$1.FC<NodeProps<NetworkNode['data']>>;
399
437
 
400
438
  /**
401
439
  * CableNode
402
- * - Visually mirrors TubeNode but represents an entire cable
403
- * - Each colored handle corresponds to a tube within the cable
440
+ * - Represents a multi-fiber cable (1-24 fibers)
441
+ * - Each colored handle corresponds to a single fiber
404
442
  * - Displays cable summary text (fiber count + cable identifier)
405
443
  */
406
444
  declare const CableNode: React$1.FC<NodeProps<NetworkNode['data']>>;
407
445
 
446
+ /**
447
+ * MultiTubeCableNode
448
+ * - Represents a multi-tube cable (1-24 tubes)
449
+ * - Each colored handle corresponds to a tube within the cable
450
+ * - Displays cable summary text (fiber count + cable identifier)
451
+ */
452
+ declare const MultiTubeCableNode: React$1.FC<NodeProps<NetworkNode['data']>>;
453
+
408
454
  declare const CouplerNode: React$1.FC<NodeProps<NetworkNode['data']>>;
409
455
 
410
456
  declare const PatchPanelNode: React$1.FC<NodeProps<NetworkNode['data']>>;
411
457
 
412
458
  declare const ClosureNode: React$1.FC<NodeProps<NetworkNode['data']>>;
413
459
 
460
+ /**
461
+ * FibreSplitNode component for rendering fiber splitters and WDM devices
462
+ * Uses a trapezoid shape pointing right (narrow input on left, wider outputs on right)
463
+ *
464
+ * @public
465
+ */
466
+ declare const FibreSplitNode: React$1.FC<NodeProps<NetworkNode['data']>>;
467
+
414
468
  interface InventoryRackDTO {
415
469
  id: string | number;
416
470
  name: string;
@@ -571,6 +625,8 @@ declare const snapToSplicePosition: (splice: NetworkNode, tray: NetworkNode, new
571
625
  declare const findNextAvailableHolderPosition: (tray: NetworkNode, splice: NetworkNode, allNodes: NetworkNode[], startFrom?: number) => number;
572
626
  /**
573
627
  * Calculate splice position based on holder number within a tray
628
+ * Note: This function doesn't have access to splice data, so it uses single mode spacing
629
+ * For ribbon splices, use calculateSplicePositionFromNumberWithData instead
574
630
  */
575
631
  declare const calculateSplicePositionFromNumber: (tray: NetworkNode, holderPosition: number) => {
576
632
  x: number;
@@ -998,4 +1054,4 @@ declare function useNetworkDiagram(store: NetworkDiagramStore): NetworkDiagramSt
998
1054
  declare function useNodes(store: NetworkDiagramStore): NetworkNode[];
999
1055
  declare function useEdges(store: NetworkDiagramStore): NetworkEdge[];
1000
1056
 
1001
- export { COUPLERS_PER_PANEL, COUPLER_SLOT_HEIGHT_PX, COUPLER_WIDTH_PX, CableNode, ClosureNode, CouplerNode, DeviceNode, DevicePlacementError, type DevicePlacementValidation, FIBER_COLORS_12, type FiberCable, type FiberColorId, FiberEdge, FiberNode, NetworkDiagram, type NetworkDiagramProps, type NetworkEdge, type NetworkNode, PANEL_BORDER_WIDTH, PANEL_HEADER_HEIGHT, PANEL_HEIGHT_PX, PANEL_PADDING, PANEL_TUBE_TRAY_SPACING, PANEL_WIDTH_PX, POWER_CONNECTORS, PatchPanelNode, type Port, type PortBlock, PowerEdge, type RackConfig, type RackDevice, RackNode, type RackSchemaOptions, type ReplaceEdgeOptions, type SpliceConfig, SpliceNode, SplicePlacementError, type SplicePlacementValidation, type SpliceSchemaOptions, type SpliceTrayConfig, SpliceTrayNode, TubeNode, VerticalPDU, Width, addDeviceToRack, addSpliceToTray, baseColorFor, buildNodesFromRackConfig, buildNodesFromSpliceConfig, calculateCouplerRightX, calculateCouplerSlotSpacing, calculateCouplerSpacing, calculateDevicePositionFromU, calculatePanelDimensions, calculateSlotPositionFromY, calculateSplicePositionFromNumber, calculateYFromSlotPosition, createNetworkDiagramStore, createRackConfigFromNodes, createSpliceConfigFromNodes, fiberSolidOrStriped, findNearestRack, findNextAvailableHolderPosition, findNextAvailableUPosition, generateLayout, getConnectorConfig, getCouplerDimensions, getDeviceConnectorType, getFiberColor, getInnerContentWidth, getPDUPortType, getPanelHeight, getPanelWidth, getPowerPortStyle, getRackBounds, getStatusColor, getTrayDimensions, getTubeDimensions, inventoryCableToNetworkEdge, inventoryDeviceToNetworkNode, inventoryRackToNetworkNode, inventoryToNetworkDiagram, isHighPowerConnector, isPointInRack, isStriped, isUPositionAvailable, removeDeviceFromRack, removeSpliceFromTray, replaceEdge, snapToCouplerPosition, snapToSplicePosition, snapToUPosition, updateDeviceUPosition$1 as updateDeviceUPosition, updateDeviceUPosition as updateDeviceUPositionInSchema, updateSpliceHolderPosition, useEdges as useDiagramEdges, useNodes as useDiagramNodes, useNetworkDiagram, validateAndSnapDevice, validateRackDevicePlacements, validateSplicePlacements };
1057
+ export { COUPLERS_PER_PANEL, COUPLER_SLOT_HEIGHT_PX, COUPLER_WIDTH_PX, CableNode, ClosureNode, CouplerNode, DeviceNode, DevicePlacementError, type DevicePlacementValidation, FIBER_COLORS_12, type FiberCable, type FiberColorId, FiberEdge, FiberNode, FibreSplitNode, MultiTubeCableNode, NetworkDiagram, type NetworkDiagramProps, type NetworkEdge, type NetworkNode, PANEL_BORDER_WIDTH, PANEL_HEADER_HEIGHT, PANEL_HEIGHT_PX, PANEL_PADDING, PANEL_TUBE_TRAY_SPACING, PANEL_WIDTH_PX, POWER_CONNECTORS, PatchPanelNode, type Port, type PortBlock, type PortType, PowerEdge, type RackConfig, type RackDevice, RackNode, type RackSchemaOptions, type ReplaceEdgeOptions, type SpliceConfig, SpliceNode, SplicePlacementError, type SplicePlacementValidation, type SpliceSchemaOptions, type SpliceTrayConfig, SpliceTrayNode, TubeNode, VerticalPDU, Width, addDeviceToRack, addSpliceToTray, baseColorFor, buildNodesFromRackConfig, buildNodesFromSpliceConfig, calculateCouplerRightX, calculateCouplerSlotSpacing, calculateCouplerSpacing, calculateDevicePositionFromU, calculatePanelDimensions, calculateSlotPositionFromY, calculateSplicePositionFromNumber, calculateYFromSlotPosition, createNetworkDiagramStore, createRackConfigFromNodes, createSpliceConfigFromNodes, fiberSolidOrStriped, findNearestRack, findNextAvailableHolderPosition, findNextAvailableUPosition, generateLayout, getConnectorConfig, getCouplerDimensions, getDeviceConnectorType, getFiberColor, getInnerContentWidth, getPDUPortType, getPanelHeight, getPanelWidth, getPowerPortStyle, getRackBounds, getStatusColor, getTrayDimensions, getTubeDimensions, inventoryCableToNetworkEdge, inventoryDeviceToNetworkNode, inventoryRackToNetworkNode, inventoryToNetworkDiagram, isHighPowerConnector, isPointInRack, isStriped, isUPositionAvailable, removeDeviceFromRack, removeSpliceFromTray, replaceEdge, snapToCouplerPosition, snapToSplicePosition, snapToUPosition, updateDeviceUPosition$1 as updateDeviceUPosition, updateDeviceUPosition as updateDeviceUPositionInSchema, updateSpliceHolderPosition, useEdges as useDiagramEdges, useNodes as useDiagramNodes, useNetworkDiagram, validateAndSnapDevice, validateRackDevicePlacements, validateSplicePlacements };