@isothrum/editor 0.0.0-stage → 0.1.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.
Files changed (293) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +8 -0
  3. package/PUBLISHING.md +93 -0
  4. package/README.md +106 -2
  5. package/desktop-editor/editor.css +11 -0
  6. package/desktop-editor/index.html +14 -0
  7. package/desktop-editor/main.tsx +26 -0
  8. package/dist/desktop/editor.css +1 -0
  9. package/dist/desktop/editor.js +181 -0
  10. package/dist/desktop/fonts/geist-cyrillic-ext-wght-normal-RO72NYA2.woff2 +0 -0
  11. package/dist/desktop/fonts/geist-cyrillic-wght-normal-CK2XY27K.woff2 +0 -0
  12. package/dist/desktop/fonts/geist-latin-ext-wght-normal-XEQ56JUF.woff2 +0 -0
  13. package/dist/desktop/fonts/geist-latin-wght-normal-T72VVCUW.woff2 +0 -0
  14. package/dist/desktop/fonts/geist-mono-cyrillic-ext-wght-normal-QXKVIKFD.woff2 +0 -0
  15. package/dist/desktop/fonts/geist-mono-cyrillic-wght-normal-GOIAQAGU.woff2 +0 -0
  16. package/dist/desktop/fonts/geist-mono-latin-ext-wght-normal-HU3ZAWN6.woff2 +0 -0
  17. package/dist/desktop/fonts/geist-mono-latin-wght-normal-CJNQKXUG.woff2 +0 -0
  18. package/dist/desktop/fonts/geist-mono-symbols2-wght-normal-WZJJVLQO.woff2 +0 -0
  19. package/dist/desktop/fonts/geist-mono-vietnamese-wght-normal-KW5NM6YV.woff2 +0 -0
  20. package/dist/desktop/fonts/geist-vietnamese-wght-normal-Y2R7JZKV.woff2 +0 -0
  21. package/dist/desktop/fonts/shantell-sans-cyrillic-ext-wght-normal-ILPQWRJJ.woff2 +0 -0
  22. package/dist/desktop/fonts/shantell-sans-cyrillic-wght-normal-RKC6NDPM.woff2 +0 -0
  23. package/dist/desktop/fonts/shantell-sans-latin-ext-wght-normal-SNKHG3LM.woff2 +0 -0
  24. package/dist/desktop/fonts/shantell-sans-latin-wght-normal-7CHHGC3N.woff2 +0 -0
  25. package/dist/desktop/fonts/shantell-sans-vietnamese-wght-normal-IPFAQSBA.woff2 +0 -0
  26. package/dist/desktop/index.html +14 -0
  27. package/dist/desktop/styles.css +2 -0
  28. package/dist/desktop/wasm/isothrum_wasm.d.ts +60 -0
  29. package/dist/desktop/wasm/isothrum_wasm.js +312 -0
  30. package/dist/desktop/wasm/isothrum_wasm_bg.wasm +0 -0
  31. package/dist/index.js +7059 -0
  32. package/dist/index.js.map +7 -0
  33. package/dist/model.js +745 -0
  34. package/dist/model.js.map +7 -0
  35. package/dist/types/components/tool/canvas/cable-edge.d.ts +4 -0
  36. package/dist/types/components/tool/canvas/contexts.d.ts +12 -0
  37. package/dist/types/components/tool/canvas/device-icon.d.ts +17 -0
  38. package/dist/types/components/tool/canvas/inline-text.d.ts +15 -0
  39. package/dist/types/components/tool/canvas/lan-node.d.ts +8 -0
  40. package/dist/types/components/tool/canvas/machine-addresses.d.ts +14 -0
  41. package/dist/types/components/tool/canvas/machine-node.d.ts +4 -0
  42. package/dist/types/components/tool/canvas/note-node.d.ts +7 -0
  43. package/dist/types/components/tool/canvas/port-led.d.ts +10 -0
  44. package/dist/types/components/tool/canvas/router-node.d.ts +8 -0
  45. package/dist/types/components/tool/canvas/sketch.d.ts +50 -0
  46. package/dist/types/components/tool/canvas/status-dot.d.ts +5 -0
  47. package/dist/types/components/tool/canvas/switch-node.d.ts +8 -0
  48. package/dist/types/components/tool/canvas/use-measured-ports.d.ts +7 -0
  49. package/dist/types/components/tool/context-menus.d.ts +5 -0
  50. package/dist/types/components/tool/device-block.d.ts +12 -0
  51. package/dist/types/components/tool/editor-menu.d.ts +28 -0
  52. package/dist/types/components/tool/export/copy-button.d.ts +9 -0
  53. package/dist/types/components/tool/export/export-panel.d.ts +17 -0
  54. package/dist/types/components/tool/export/target-list.d.ts +15 -0
  55. package/dist/types/components/tool/floating-window.d.ts +13 -0
  56. package/dist/types/components/tool/flow-canvas.d.ts +6 -0
  57. package/dist/types/components/tool/hooks/use-cabling.d.ts +23 -0
  58. package/dist/types/components/tool/hooks/use-captures.d.ts +9 -0
  59. package/dist/types/components/tool/hooks/use-clipboard.d.ts +12 -0
  60. package/dist/types/components/tool/hooks/use-context-menus.d.ts +25 -0
  61. package/dist/types/components/tool/hooks/use-design.d.ts +10 -0
  62. package/dist/types/components/tool/hooks/use-desktop.d.ts +50 -0
  63. package/dist/types/components/tool/hooks/use-devices.d.ts +17 -0
  64. package/dist/types/components/tool/hooks/use-downloads.d.ts +9 -0
  65. package/dist/types/components/tool/hooks/use-editor.d.ts +609 -0
  66. package/dist/types/components/tool/hooks/use-engine.d.ts +9 -0
  67. package/dist/types/components/tool/hooks/use-history.d.ts +9 -0
  68. package/dist/types/components/tool/hooks/use-lab-actions.d.ts +25 -0
  69. package/dist/types/components/tool/hooks/use-lab-run.d.ts +25 -0
  70. package/dist/types/components/tool/hooks/use-lab.d.ts +18 -0
  71. package/dist/types/components/tool/hooks/use-lan-carry.d.ts +8 -0
  72. package/dist/types/components/tool/hooks/use-machine-actions.d.ts +26 -0
  73. package/dist/types/components/tool/hooks/use-placement.d.ts +27 -0
  74. package/dist/types/components/tool/hooks/use-project.d.ts +25 -0
  75. package/dist/types/components/tool/hooks/use-projects.d.ts +34 -0
  76. package/dist/types/components/tool/hooks/use-shared-link.d.ts +23 -0
  77. package/dist/types/components/tool/hooks/use-toast.d.ts +2 -0
  78. package/dist/types/components/tool/hooks/use-tools.d.ts +17 -0
  79. package/dist/types/components/tool/lab-canvas.d.ts +18 -0
  80. package/dist/types/components/tool/overlays.d.ts +5 -0
  81. package/dist/types/components/tool/projects-list.d.ts +9 -0
  82. package/dist/types/components/tool/text.d.ts +418 -0
  83. package/dist/types/components/tool/toolbar.d.ts +5 -0
  84. package/dist/types/components/tool/top-bars.d.ts +10 -0
  85. package/dist/types/components/tool/windows/conditions-fields.d.ts +6 -0
  86. package/dist/types/components/tool/windows/editor-windows.d.ts +5 -0
  87. package/dist/types/components/tool/windows/fields.d.ts +4 -0
  88. package/dist/types/components/tool/windows/lab-status.d.ts +6 -0
  89. package/dist/types/components/tool/windows/lab-windows.d.ts +13 -0
  90. package/dist/types/components/tool/windows/link-controls.d.ts +21 -0
  91. package/dist/types/components/tool/windows/machine-controls.d.ts +16 -0
  92. package/dist/types/components/tool/windows/machine-inspector.d.ts +11 -0
  93. package/dist/types/components/tool/windows/runs-fields.d.ts +18 -0
  94. package/dist/types/components/tool/windows/selected-windows.d.ts +21 -0
  95. package/dist/types/components/ui/button.d.ts +8 -0
  96. package/dist/types/components/ui/dropdown-menu.d.ts +21 -0
  97. package/dist/types/index.d.ts +7 -0
  98. package/dist/types/lib/auth.d.ts +38 -0
  99. package/dist/types/lib/brand.d.ts +19 -0
  100. package/dist/types/lib/i18n.d.ts +19 -0
  101. package/dist/types/lib/tool/blocks.d.ts +35 -0
  102. package/dist/types/lib/tool/cables.d.ts +48 -0
  103. package/dist/types/lib/tool/clone.d.ts +12 -0
  104. package/dist/types/lib/tool/conditions.d.ts +31 -0
  105. package/dist/types/lib/tool/create.d.ts +22 -0
  106. package/dist/types/lib/tool/desktop.d.ts +63 -0
  107. package/dist/types/lib/tool/draft.d.ts +20 -0
  108. package/dist/types/lib/tool/engine.d.ts +33 -0
  109. package/dist/types/lib/tool/examples.d.ts +11 -0
  110. package/dist/types/lib/tool/export-targets.d.ts +21 -0
  111. package/dist/types/lib/tool/facing.d.ts +9 -0
  112. package/dist/types/lib/tool/geometry.d.ts +36 -0
  113. package/dist/types/lib/tool/gns3-cables.d.ts +17 -0
  114. package/dist/types/lib/tool/gns3-import.d.ts +15 -0
  115. package/dist/types/lib/tool/gns3-parts.d.ts +25 -0
  116. package/dist/types/lib/tool/issues.d.ts +12 -0
  117. package/dist/types/lib/tool/layout.d.ts +52 -0
  118. package/dist/types/lib/tool/live.d.ts +21 -0
  119. package/dist/types/lib/tool/logos.d.ts +7 -0
  120. package/dist/types/lib/tool/model.d.ts +173 -0
  121. package/dist/types/lib/tool/os.d.ts +20 -0
  122. package/dist/types/lib/tool/pins.d.ts +5 -0
  123. package/dist/types/lib/tool/placement.d.ts +21 -0
  124. package/dist/types/lib/tool/ports.d.ts +21 -0
  125. package/dist/types/lib/tool/presets.d.ts +21 -0
  126. package/dist/types/lib/tool/projects-api.d.ts +37 -0
  127. package/dist/types/lib/tool/router-ports.d.ts +22 -0
  128. package/dist/types/lib/tool/selection.d.ts +19 -0
  129. package/dist/types/lib/tool/storage.d.ts +25 -0
  130. package/dist/types/lib/tool/switch-edit.d.ts +17 -0
  131. package/dist/types/lib/tool/text/de.d.ts +2 -0
  132. package/dist/types/lib/tool/text/en.d.ts +429 -0
  133. package/dist/types/lib/tool/text/es.d.ts +2 -0
  134. package/dist/types/lib/tool/text/fr.d.ts +2 -0
  135. package/dist/types/lib/tool/text/index.d.ts +419 -0
  136. package/dist/types/lib/tool/topology.d.ts +2 -0
  137. package/dist/types/lib/tool/vlans.d.ts +24 -0
  138. package/dist/types/lib/utils.d.ts +2 -0
  139. package/dist/types/model.d.ts +13 -0
  140. package/package.json +88 -4
  141. package/scripts/build-desktop-editor.mjs +43 -0
  142. package/scripts/build-lib.mjs +38 -0
  143. package/src/components/tool/canvas/cable-edge.tsx +112 -0
  144. package/src/components/tool/canvas/contexts.ts +18 -0
  145. package/src/components/tool/canvas/device-icon.tsx +105 -0
  146. package/src/components/tool/canvas/inline-text.tsx +69 -0
  147. package/src/components/tool/canvas/lan-node.tsx +148 -0
  148. package/src/components/tool/canvas/machine-addresses.tsx +117 -0
  149. package/src/components/tool/canvas/machine-node.tsx +114 -0
  150. package/src/components/tool/canvas/note-node.tsx +109 -0
  151. package/src/components/tool/canvas/port-led.tsx +21 -0
  152. package/src/components/tool/canvas/router-node.tsx +114 -0
  153. package/src/components/tool/canvas/sketch.tsx +130 -0
  154. package/src/components/tool/canvas/status-dot.tsx +29 -0
  155. package/src/components/tool/canvas/switch-node.tsx +143 -0
  156. package/src/components/tool/canvas/use-measured-ports.ts +25 -0
  157. package/src/components/tool/context-menus.tsx +142 -0
  158. package/src/components/tool/device-block.tsx +107 -0
  159. package/src/components/tool/editor-menu.tsx +191 -0
  160. package/src/components/tool/export/copy-button.tsx +45 -0
  161. package/src/components/tool/export/export-panel.tsx +127 -0
  162. package/src/components/tool/export/target-list.tsx +87 -0
  163. package/src/components/tool/floating-window.tsx +69 -0
  164. package/src/components/tool/flow-canvas.tsx +138 -0
  165. package/src/components/tool/hooks/use-cabling.ts +66 -0
  166. package/src/components/tool/hooks/use-captures.ts +24 -0
  167. package/src/components/tool/hooks/use-clipboard.ts +54 -0
  168. package/src/components/tool/hooks/use-context-menus.ts +37 -0
  169. package/src/components/tool/hooks/use-design.ts +24 -0
  170. package/src/components/tool/hooks/use-desktop.ts +100 -0
  171. package/src/components/tool/hooks/use-devices.ts +58 -0
  172. package/src/components/tool/hooks/use-downloads.ts +42 -0
  173. package/src/components/tool/hooks/use-editor.ts +114 -0
  174. package/src/components/tool/hooks/use-engine.ts +29 -0
  175. package/src/components/tool/hooks/use-history.ts +107 -0
  176. package/src/components/tool/hooks/use-lab-actions.ts +57 -0
  177. package/src/components/tool/hooks/use-lab-run.ts +61 -0
  178. package/src/components/tool/hooks/use-lab.ts +32 -0
  179. package/src/components/tool/hooks/use-lan-carry.ts +43 -0
  180. package/src/components/tool/hooks/use-machine-actions.ts +57 -0
  181. package/src/components/tool/hooks/use-placement.ts +80 -0
  182. package/src/components/tool/hooks/use-project.ts +112 -0
  183. package/src/components/tool/hooks/use-projects.ts +85 -0
  184. package/src/components/tool/hooks/use-shared-link.ts +64 -0
  185. package/src/components/tool/hooks/use-toast.ts +16 -0
  186. package/src/components/tool/hooks/use-tools.ts +60 -0
  187. package/src/components/tool/lab-canvas.tsx +96 -0
  188. package/src/components/tool/overlays.tsx +104 -0
  189. package/src/components/tool/projects-list.tsx +96 -0
  190. package/src/components/tool/text.ts +9 -0
  191. package/src/components/tool/toolbar.tsx +106 -0
  192. package/src/components/tool/top-bars.tsx +90 -0
  193. package/src/components/tool/windows/conditions-fields.tsx +43 -0
  194. package/src/components/tool/windows/editor-windows.tsx +73 -0
  195. package/src/components/tool/windows/fields.ts +6 -0
  196. package/src/components/tool/windows/lab-status.tsx +68 -0
  197. package/src/components/tool/windows/lab-windows.tsx +130 -0
  198. package/src/components/tool/windows/link-controls.tsx +69 -0
  199. package/src/components/tool/windows/machine-controls.tsx +116 -0
  200. package/src/components/tool/windows/machine-inspector.tsx +83 -0
  201. package/src/components/tool/windows/runs-fields.tsx +127 -0
  202. package/src/components/tool/windows/selected-windows.tsx +147 -0
  203. package/src/components/ui/button.tsx +59 -0
  204. package/src/components/ui/dropdown-menu.tsx +185 -0
  205. package/src/index.ts +21 -0
  206. package/src/lib/auth.tsx +43 -0
  207. package/src/lib/brand.tsx +46 -0
  208. package/src/lib/i18n.ts +53 -0
  209. package/src/lib/tool/blocks.test.ts +64 -0
  210. package/src/lib/tool/blocks.ts +78 -0
  211. package/src/lib/tool/cable-wiring.test.ts +74 -0
  212. package/src/lib/tool/cables.test.ts +75 -0
  213. package/src/lib/tool/cables.ts +215 -0
  214. package/src/lib/tool/clone.test.ts +54 -0
  215. package/src/lib/tool/clone.ts +48 -0
  216. package/src/lib/tool/conditions.test.ts +170 -0
  217. package/src/lib/tool/conditions.ts +132 -0
  218. package/src/lib/tool/create.test.ts +67 -0
  219. package/src/lib/tool/create.ts +83 -0
  220. package/src/lib/tool/desktop.test.ts +59 -0
  221. package/src/lib/tool/desktop.ts +99 -0
  222. package/src/lib/tool/draft.test.ts +150 -0
  223. package/src/lib/tool/draft.ts +109 -0
  224. package/src/lib/tool/engine.test.ts +39 -0
  225. package/src/lib/tool/engine.ts +58 -0
  226. package/src/lib/tool/examples.test.ts +35 -0
  227. package/src/lib/tool/examples.ts +71 -0
  228. package/src/lib/tool/export-targets.test.ts +47 -0
  229. package/src/lib/tool/export-targets.ts +84 -0
  230. package/src/lib/tool/facing.test.ts +72 -0
  231. package/src/lib/tool/facing.ts +100 -0
  232. package/src/lib/tool/geometry.test.ts +80 -0
  233. package/src/lib/tool/geometry.ts +109 -0
  234. package/src/lib/tool/gns3-cables.test.ts +47 -0
  235. package/src/lib/tool/gns3-cables.ts +81 -0
  236. package/src/lib/tool/gns3-import.test.ts +102 -0
  237. package/src/lib/tool/gns3-import.ts +198 -0
  238. package/src/lib/tool/gns3-layout.test.ts +62 -0
  239. package/src/lib/tool/gns3-parts.test.ts +47 -0
  240. package/src/lib/tool/gns3-parts.ts +68 -0
  241. package/src/lib/tool/issues.test.ts +35 -0
  242. package/src/lib/tool/issues.ts +60 -0
  243. package/src/lib/tool/layout.test.ts +128 -0
  244. package/src/lib/tool/layout.ts +229 -0
  245. package/src/lib/tool/live.test.ts +46 -0
  246. package/src/lib/tool/live.ts +49 -0
  247. package/src/lib/tool/logos.test.ts +30 -0
  248. package/src/lib/tool/logos.ts +99 -0
  249. package/src/lib/tool/model.test.ts +128 -0
  250. package/src/lib/tool/model.ts +238 -0
  251. package/src/lib/tool/os.test.ts +45 -0
  252. package/src/lib/tool/os.ts +57 -0
  253. package/src/lib/tool/parity.test.ts +145 -0
  254. package/src/lib/tool/pins.test.ts +24 -0
  255. package/src/lib/tool/pins.ts +11 -0
  256. package/src/lib/tool/placement.test.ts +79 -0
  257. package/src/lib/tool/placement.ts +60 -0
  258. package/src/lib/tool/ports.test.ts +39 -0
  259. package/src/lib/tool/ports.ts +48 -0
  260. package/src/lib/tool/presets.test.ts +50 -0
  261. package/src/lib/tool/presets.ts +77 -0
  262. package/src/lib/tool/projects-api.test.ts +59 -0
  263. package/src/lib/tool/projects-api.ts +47 -0
  264. package/src/lib/tool/router-ports.test.ts +63 -0
  265. package/src/lib/tool/router-ports.ts +88 -0
  266. package/src/lib/tool/selection.test.ts +44 -0
  267. package/src/lib/tool/selection.ts +34 -0
  268. package/src/lib/tool/storage.test.ts +123 -0
  269. package/src/lib/tool/storage.ts +127 -0
  270. package/src/lib/tool/switch-edit.test.ts +49 -0
  271. package/src/lib/tool/switch-edit.ts +38 -0
  272. package/src/lib/tool/text/de.ts +358 -0
  273. package/src/lib/tool/text/en.ts +371 -0
  274. package/src/lib/tool/text/es.ts +358 -0
  275. package/src/lib/tool/text/fr.ts +358 -0
  276. package/src/lib/tool/text/index.ts +21 -0
  277. package/src/lib/tool/text/text.test.ts +33 -0
  278. package/src/lib/tool/topology.test.ts +108 -0
  279. package/src/lib/tool/topology.ts +116 -0
  280. package/src/lib/tool/vlans.test.ts +64 -0
  281. package/src/lib/tool/vlans.ts +79 -0
  282. package/src/lib/utils.ts +6 -0
  283. package/src/model.ts +13 -0
  284. package/src/test/arbitrary.ts +41 -0
  285. package/src/test/engine.ts +48 -0
  286. package/src/test/lab.ts +101 -0
  287. package/styles/globals.css +258 -0
  288. package/styles/theme.css +192 -0
  289. package/tsconfig.build.json +12 -0
  290. package/tsconfig.json +22 -0
  291. package/wasm/isothrum_wasm.d.ts +60 -0
  292. package/wasm/isothrum_wasm.js +312 -0
  293. package/wasm/isothrum_wasm_bg.wasm +0 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/components/tool/lab-canvas.tsx", "../src/lib/i18n.ts", "../src/lib/tool/text/de.ts", "../src/lib/tool/text/en.ts", "../src/lib/tool/text/es.ts", "../src/lib/tool/text/fr.ts", "../src/lib/tool/text/index.ts", "../src/lib/auth.tsx", "../src/lib/brand.tsx", "../src/lib/utils.ts", "../src/components/tool/context-menus.tsx", "../src/components/tool/text.ts", "../src/components/tool/editor-menu.tsx", "../src/lib/tool/model.ts", "../src/components/ui/dropdown-menu.tsx", "../src/components/tool/flow-canvas.tsx", "../src/lib/tool/geometry.ts", "../src/lib/tool/vlans.ts", "../src/lib/tool/cables.ts", "../src/lib/tool/ports.ts", "../src/lib/tool/issues.ts", "../src/lib/tool/selection.ts", "../src/components/tool/canvas/cable-edge.tsx", "../src/lib/tool/conditions.ts", "../src/components/tool/canvas/contexts.ts", "../src/components/tool/canvas/sketch.tsx", "../src/components/tool/canvas/lan-node.tsx", "../src/components/tool/canvas/inline-text.tsx", "../src/components/tool/canvas/machine-node.tsx", "../src/components/tool/canvas/device-icon.tsx", "../src/lib/tool/logos.ts", "../src/components/tool/canvas/machine-addresses.tsx", "../src/lib/tool/pins.ts", "../src/components/tool/canvas/router-node.tsx", "../src/components/tool/canvas/port-led.tsx", "../src/components/tool/canvas/status-dot.tsx", "../src/components/tool/canvas/use-measured-ports.ts", "../src/components/tool/canvas/note-node.tsx", "../src/components/tool/canvas/switch-node.tsx", "../src/lib/tool/switch-edit.ts", "../src/components/tool/hooks/use-editor.ts", "../src/lib/tool/os.ts", "../src/lib/tool/presets.ts", "../src/lib/tool/blocks.ts", "../src/lib/tool/desktop.ts", "../src/lib/tool/facing.ts", "../src/lib/tool/live.ts", "../src/lib/tool/router-ports.ts", "../src/lib/tool/topology.ts", "../src/components/tool/hooks/use-cabling.ts", "../src/lib/tool/create.ts", "../src/lib/tool/placement.ts", "../src/components/tool/hooks/use-captures.ts", "../src/components/tool/hooks/use-clipboard.ts", "../src/lib/tool/clone.ts", "../src/components/tool/hooks/use-history.ts", "../src/components/tool/hooks/use-context-menus.ts", "../src/components/tool/hooks/use-desktop.ts", "../src/lib/tool/draft.ts", "../src/lib/tool/storage.ts", "../src/components/tool/hooks/use-design.ts", "../src/components/tool/hooks/use-devices.ts", "../src/components/tool/hooks/use-downloads.ts", "../src/components/tool/hooks/use-engine.ts", "../src/lib/tool/engine.ts", "../src/components/tool/hooks/use-lab.ts", "../src/components/tool/hooks/use-lab-actions.ts", "../src/lib/tool/examples.ts", "../src/lib/tool/gns3-cables.ts", "../src/lib/tool/gns3-parts.ts", "../src/lib/tool/gns3-import.ts", "../src/components/tool/hooks/use-lab-run.ts", "../src/components/tool/hooks/use-lan-carry.ts", "../src/components/tool/hooks/use-machine-actions.ts", "../src/components/tool/hooks/use-placement.ts", "../src/components/tool/hooks/use-projects.ts", "../src/lib/tool/projects-api.ts", "../src/components/tool/hooks/use-project.ts", "../src/components/tool/hooks/use-shared-link.ts", "../src/components/tool/hooks/use-toast.ts", "../src/components/tool/hooks/use-tools.ts", "../src/components/tool/overlays.tsx", "../src/components/ui/button.tsx", "../src/components/tool/toolbar.tsx", "../src/components/tool/device-block.tsx", "../src/components/tool/top-bars.tsx", "../src/components/tool/export/export-panel.tsx", "../src/lib/tool/export-targets.ts", "../src/components/tool/export/copy-button.tsx", "../src/components/tool/export/target-list.tsx", "../src/components/tool/floating-window.tsx", "../src/components/tool/projects-list.tsx", "../src/components/tool/windows/lab-windows.tsx", "../src/components/tool/windows/lab-status.tsx", "../src/components/tool/windows/selected-windows.tsx", "../src/components/tool/windows/fields.ts", "../src/components/tool/windows/conditions-fields.tsx", "../src/components/tool/windows/link-controls.tsx", "../src/components/tool/windows/machine-controls.tsx", "../src/components/tool/windows/machine-inspector.tsx", "../src/components/tool/windows/runs-fields.tsx", "../src/components/tool/windows/editor-windows.tsx"],
4
+ "sourcesContent": ["\"use client\";\n\nimport { useRef } from \"react\";\nimport { ReactFlowProvider } from \"@xyflow/react\";\nimport { editorText } from \"@/lib/tool/text\";\nimport { AuthClientProvider, type AuthClient } from \"@/lib/auth\";\nimport { BrandMarkProvider, type BrandMark } from \"@/lib/brand\";\nimport { cn } from \"@/lib/utils\";\nimport { RunningLabMenus } from \"./context-menus\";\nimport { SessionWatch } from \"./editor-menu\";\nimport { FlowCanvas } from \"./flow-canvas\";\nimport { useEditor, type EditorModel } from \"./hooks/use-editor\";\nimport { Overlays } from \"./overlays\";\nimport { EditorTextContext } from \"./text\";\nimport { Toolbar } from \"./toolbar\";\nimport { TopLeft, TopRight } from \"./top-bars\";\nimport { EditorWindows } from \"./windows/editor-windows\";\n\n/** The hidden file input a GNS3 project is picked with (the menu opens it). */\nfunction Gns3Input({ e, input }: { e: EditorModel; input: React.RefObject<HTMLInputElement | null> }) {\n return (\n <input\n ref={input}\n type=\"file\"\n accept=\".gns3,application/json\"\n hidden\n aria-label={e.t.menu.gns3File}\n onChange={(ev) => {\n const file = ev.target.files?.[0];\n if (file) void e.actions.importGns3(file);\n ev.target.value = \"\";\n }}\n />\n );\n}\n\nfunction Editor({ lang, accounts }: { lang: string; accounts: boolean }) {\n const canvasRef = useRef<HTMLDivElement>(null);\n const gns3Input = useRef<HTMLInputElement>(null);\n const e = useEditor(lang, accounts, canvasRef);\n const { tools } = e;\n return (\n <div\n ref={canvasRef}\n className={cn(\n \"fixed inset-0 bg-background\",\n e.tool && \"[&_.react-flow__pane]:!cursor-crosshair\",\n tools.mode === \"hand\" && \"[&_.react-flow__pane]:!cursor-grab [&_.react-flow__pane.dragging]:!cursor-grabbing\",\n )}\n onDragOver={(ev) => {\n ev.preventDefault();\n }}\n onDrop={e.placement.onDrop}\n data-design={e.design.design}\n >\n <Gns3Input e={e} input={gns3Input} />\n {accounts && <SessionWatch onChange={e.projects.setSignedInNow} />}\n <FlowCanvas e={e} />\n <TopLeft e={e} onImportGns3={() => gns3Input.current?.click()} />\n <Toolbar e={e} />\n <TopRight e={e} />\n <Overlays e={e} />\n <RunningLabMenus e={e} />\n <EditorWindows e={e} />\n </div>\n );\n}\n\n/** The props of the lab editor. */\nexport interface LabCanvasProps {\n /** The editor's language (one of the editor's locales); anything else falls back to English. */\n lang: string;\n /**\n * Whether the accounts UI (sign in, save to projects) is shown. When `true`, pass `auth`.\n * Defaults to `false`, for hosts without accounts (the desktop app, a standalone embed).\n */\n accounts?: boolean;\n /** The host's auth client, required when `accounts` is `true`; ignored otherwise. */\n auth?: AuthClient | null;\n /** A product mark for the empty canvas; defaults to the Isothrum mark. */\n brandMark?: BrandMark;\n}\n\n/** The lab editor: the editor's words in the page's language, for every part of it (windows, canvas, export). */\nexport function LabCanvas({ lang, accounts = false, auth = null, brandMark }: LabCanvasProps) {\n const text = editorText(lang);\n const inner = (\n <EditorTextContext.Provider value={text}>\n <ReactFlowProvider>\n <Editor lang={lang} accounts={accounts} />\n </ReactFlowProvider>\n </EditorTextContext.Provider>\n );\n const withAuth = <AuthClientProvider client={auth}>{inner}</AuthClientProvider>;\n return brandMark ? <BrandMarkProvider mark={brandMark}>{withAuth}</BrandMarkProvider> : withAuth;\n}\n", "export const LOCALES = [\"en\", \"fr\", \"es\", \"de\"] as const;\nexport const DEFAULT_LOCALE = \"en\" as const;\n\nexport type Locale = (typeof LOCALES)[number];\n\n/** Whether `value` names one of the site's locales. */\nexport function hasLocale(value: string): value is Locale {\n return (LOCALES as readonly string[]).includes(value);\n}\n\n/** Every locale but `locale`. */\nexport function otherLocales(locale: string): Locale[] {\n return LOCALES.filter((l) => l !== locale);\n}\n\nexport const localeNames: Record<Locale, string> = {\n en: \"English\",\n fr: \"Fran\u00E7ais\",\n es: \"Espa\u00F1ol\",\n de: \"Deutsch\",\n};\n\n/**\n * Replace (or insert) the locale segment in a pathname.\n * \"/en/blog/foo\" + \"fr\" \u2192 \"/fr/blog/foo\"\n * \"/blog/foo\" + \"fr\" \u2192 \"/fr/blog/foo\"\n */\nexport function withLocale(pathname: string, locale: Locale): string {\n const segments = pathname.split(\"/\").filter(Boolean);\n if (segments.length && hasLocale(segments[0])) {\n segments[0] = locale;\n } else {\n segments.unshift(locale);\n }\n return \"/\" + segments.join(\"/\");\n}\n\n/**\n * Build the absolute-URL hreflang map for a path that exists in every locale.\n * Useful for static pages (homepage, /blog index, etc).\n */\nexport function hreflangFor(siteUrl: string, pathWithoutLocale: string) {\n const base = siteUrl.replace(/\\/$/, \"\");\n const path = pathWithoutLocale.startsWith(\"/\")\n ? pathWithoutLocale\n : \"/\" + pathWithoutLocale;\n const map: Record<string, string> = {};\n for (const l of LOCALES) {\n map[l] = `${base}/${l}${path === \"/\" ? \"\" : path}`;\n }\n map[\"x-default\"] = `${base}/${DEFAULT_LOCALE}${path === \"/\" ? \"\" : path}`;\n return map;\n}\n", "import type { EditorText } from \"./en\";\n\nexport const de: EditorText = {\n toolbar: {\n blocks: { switch: \"Switch\", router: \"Router\", firewall: \"Firewall\", container: \"Container\", vm: \"Virtuelle Maschine\", mine: \"Meine Ger\u00E4te\" },\n kindsOf: (block) => `Arten: ${block}`,\n devices: \"Ger\u00E4te\",\n hand: \"Hand: Arbeitsfl\u00E4che verschieben\",\n select: \"Auswahl: ausw\u00E4hlen, verschieben, l\u00F6schen\",\n lan: \"LAN\",\n lanTitle: \"LAN / VLAN: ein Bereich; Maschinen darin erhalten dort eine Adresse\",\n switch: \"Switch\",\n switchTitle: \"Switch: Ports in VLANs und ein Trunk\",\n note: \"Notiz\",\n noteTitle: \"Notiz: Text, Kasten oder Ellipse, um das Lab zu erkl\u00E4ren\",\n forget: (device) => `${device} vergessen`,\n forgetLabel: (device) => `Ger\u00E4t ${device} vergessen`,\n undo: \"R\u00FCckg\u00E4ngig\",\n undoTitle: \"R\u00FCckg\u00E4ngig \u00B7 Strg/\u2318 Z\",\n redo: \"Wiederholen\",\n redoTitle: \"Wiederholen \u00B7 Strg/\u2318 Umschalt Z\",\n },\n hints: {\n lan: \"Auf die Arbeitsfl\u00E4che klicken, um ein LAN zu platzieren; Maschinen darin erhalten dort eine Adresse. Name oder Bereich doppelklicken, um sie zu bearbeiten.\",\n note: \"Auf die Arbeitsfl\u00E4che klicken, um eine Notiz zu platzieren, dann doppelklicken, um zu schreiben. Notizen bleiben im Editor, nicht in der isoloom.yml.\",\n place: (device) => `${device}: zum Platzieren auf die Arbeitsfl\u00E4che klicken. Esc zum Abbrechen.`,\n hand: \"Ziehen, um die Arbeitsfl\u00E4che zu verschieben. V dr\u00FCcken, um wieder auszuw\u00E4hlen.\",\n cable: \"Von einem Punkt einer Maschine zu einer anderen ziehen, um sie zu verkabeln.\",\n select: \"Auf der Arbeitsfl\u00E4che ziehen, um mehrere Maschinen auszuw\u00E4hlen: Entf oder Strg/\u2318 C, V, D. Leertaste halten, um die Arbeitsfl\u00E4che zu verschieben.\",\n },\n devices: {\n router: { label: \"Router\", hint: \"automatisch: seine Netze erreichen einander\" },\n \"router-frr\": { label: \"Router (FRR)\", hint: \"FRRouting-Container zum Selbstkonfigurieren\" },\n firewall: { label: \"Firewall\", hint: \"nftables auf Alpine\" },\n container: { label: \"Linux-Container\" },\n web: { label: \"Webserver\", hint: \"nginx, Port 80\" },\n database: { label: \"Datenbank\", hint: \"PostgreSQL, Port 5432\" },\n desktop: { label: \"Linux-Desktop\", hint: \"Xfce mit VNC: Rechtsklick, Bildschirm; Passwort vncpassword\" },\n \"linux-vm\": { label: \"Linux-VM\" },\n \"ubuntu-vm\": { label: \"Ubuntu-VM\" },\n \"kali-vm\": { label: \"Kali-VM\" },\n \"windows-vm\": { label: \"Windows-VM\" },\n workstation: { label: \"Workstation\", hint: \"hier landet der Benutzer\" },\n \"cisco-iol\": { label: \"Cisco-IOL-Router\", hint: \"IOS unter Linux, dein vrnetlab-Image\" },\n \"cisco-iol-l2\": { label: \"Cisco-IOL-Switch\", hint: \"IOL-L2, dein vrnetlab-Image\" },\n },\n myDevice: (what) => `eigenes Ger\u00E4t: ${what}`,\n myDeviceRouter: \"automatischer Router\",\n status: {\n loading: \"L\u00E4dt\u2026\",\n toFix: (count) => `${String(count)} zu beheben`,\n valid: \"G\u00FCltig\",\n },\n run: {\n autoStart: \"Dieses Lab beim \u00D6ffnen der App starten\",\n autoStartNote: \"Auf diesem Computer, wenn die App mit diesem Lab \u00F6ffnet und es nicht schon l\u00E4uft.\",\n statusTitle: (up, total) => `${String(up)} von ${String(total)} Maschinen laufen`,\n probed: \"Ports von den Maschinen gelesen\",\n inferred: \"Ports nach dem Zustand der Maschinen (VMs werden nicht abgefragt)\",\n run: \"Starten\",\n starting: \"Startet\u2026\",\n stop: \"Stoppen\",\n stopping: \"Stoppt\u2026\",\n vmsTitle: \"Ein Lab mit VMs l\u00E4uft mit Vagrant (und VirtualBox oder libvirt): installiere es von vagrantup.com oder exportiere das Lab\",\n runVmsTitle: \"Das Lab auf diesem Rechner ausf\u00FChren (VMs mit Vagrant)\",\n startingVmsLog: \"VMs werden mit vagrant up gestartet (beim ersten Mal werden ihre Boxen geladen: Minuten)\u2026\",\n runTitle: \"Das Lab auf diesem Rechner starten (Docker)\",\n startingLog: \"Lab wird mit docker compose gestartet\u2026\",\n window: \"Auf diesem Rechner ausf\u00FChren\",\n running: \"Das Lab l\u00E4uft. Ein LAN oder ein Kabel ausw\u00E4hlen, um seinen Verkehr mitzuschneiden.\",\n stopped: \"Das Lab ist gestoppt.\",\n noDocker:\n \"Docker antwortet nicht. Docker installieren und starten; unter Linux au\u00DFerdem das eigene Konto zur Gruppe docker hinzuf\u00FCgen (sudo usermod -aG docker $USER, dann neu anmelden).\",\n noLiveCapture: (wireshark, dir) =>\n `${\n wireshark\n ? \"Wireshark kann mit diesem Konto nicht live mitschneiden: sudo usermod -aG wireshark $USER ausf\u00FChren, dann neu anmelden. Bis dahin werden Mitschnitte\"\n : \"Wireshark ist nicht installiert: Mitschnitte werden\"\n } als .pcap-Dateien unter ${dir} gespeichert.`,\n },\n capture: {\n capturing: (network) => `Mitschnitt von ${network}`,\n writingTo: \"Schreibt nach\",\n live: \"Live in Wireshark.\",\n stop: \"Mitschnitt stoppen\",\n start: \"Verkehr mitschneiden\",\n runFirst: \"Das Lab starten, um seinen Verkehr mitzuschneiden.\",\n },\n link: {\n suspend: \"Verbindung trennen\",\n resume: \"Verbindung wiederherstellen\",\n suspendAll: \"Alle Verbindungen trennen\",\n resumeAll: \"Alle Verbindungen wiederherstellen\",\n cableSuspended: \"Verbindung getrennt: nichts kommt durch.\",\n lanSuspended: (ports) => (ports === 1 ? \"1 Verbindung getrennt.\" : `${String(ports)} Verbindungen getrennt.`),\n runFirst: \"Das Lab starten, um seine Verbindungen zu trennen.\",\n },\n export: \"Exportieren\",\n engineDidntLoad: (error) => `Die Engine wurde nicht geladen: ${error}`,\n engineFailed: (error) => `Die Engine ist an diesem Lab gescheitert: ${error}`,\n toasts: {\n brokenLink: \"Dieser Freigabelink ist besch\u00E4digt: Das Lab konnte nicht gelesen werden.\",\n openedShared: (lab) => `Geteiltes Lab \u201E${lab}\u201C ge\u00F6ffnet. R\u00FCckg\u00E4ngig holt das vorherige zur\u00FCck.`,\n linkCopied: \"Freigabelink kopiert: Wer ihn \u00F6ffnet, erh\u00E4lt eine Kopie dieses Labs.\",\n copyPrompt: \"Diesen Link kopieren, um das Lab zu teilen:\",\n savedDevice: (device) => `\u201E${device}\u201C gespeichert: Es steht am Ende der Werkzeugleiste.`,\n gns3Opened: (lab, machines, lans) =>\n `\u201E${lab}\u201C aus GNS3 ge\u00F6ffnet: ${String(machines)} ${machines === 1 ? \"Maschine\" : \"Maschinen\"}, ${String(lans)} ${lans === 1 ? \"LAN\" : \"LANs\"}.`,\n undoBringsBack: \"R\u00FCckg\u00E4ngig holt das vorherige Lab zur\u00FCck.\",\n gns3Unreadable: \"Dieses GNS3-Projekt konnte nicht gelesen werden.\",\n },\n windows: {\n machine: \"Maschine\",\n lan: (lan) => `LAN ${lan}`,\n cable: (a, b) => `Kabel ${a} \u2194 ${b}`,\n portOn: (machine) => `Port an ${machine}`,\n cableNote: \"Jedes Kabel ist ein eigenes kleines Netz (ein /29); die beiden Enden erhalten seine ersten zwei Adressen.\",\n removeCable: \"Kabel entfernen\",\n conditions: {\n title: \"Leitungsbedingungen\",\n delay: \"Verz\u00F6gerung (ms, je Richtung)\",\n jitter: \"Jitter (ms)\",\n loss: \"Verlust (%)\",\n rate: \"Bandbreite (Mbit/s)\",\n hint: \"Eine langsame oder verlustbehaftete Leitung, mit tc netem an jedem Ende. Leer: keine.\",\n onLan: \"Dieses Kabel bringt die Maschine ins LAN: Bedingungen am LAN einstellen.\",\n onVlan: \"Bedingungen gelten f\u00FCr ein Kabel oder ein einfaches LAN, noch nicht f\u00FCr das VLAN eines Switches.\",\n },\n selected: (count) => `${String(count)} ausgew\u00E4hlt`,\n selection: (items, cables) =>\n `${String(items)} ${items === 1 ? \"Element\" : \"Elemente\"}, ${String(cables)} Kabel. Eines davon ziehen, um alle zusammen zu verschieben.`,\n deleteSelection: (count) => `${String(count)} l\u00F6schen (Entf-Taste)`,\n close: \"Schlie\u00DFen\",\n },\n lab: {\n title: \"Lab\",\n containers: \"Container\",\n vms: \"VMs\",\n lans: \"LANs\",\n cables: \"Kabel\",\n toFix: \"Zu beheben\",\n valid: \"Das Lab ist g\u00FCltig: bereit zum Export.\",\n routing:\n \"Ein Router braucht seine eigene Weiterleitungskonfiguration: Jedes Kabel ist ein eigenes Netz, und nichts routet von selbst zwischen ihnen.\",\n },\n menu: {\n menu: \"Men\u00FC\",\n example: \"Beispiel-Lab laden\",\n vlanExample: \"VLAN-Beispiel laden\",\n gns3: \"GNS3-Projekt \u00F6ffnen\u2026\",\n gns3File: \"GNS3-Projekt\",\n share: \"Freigabelink kopieren\",\n fit: \"An Bildschirm anpassen\",\n clear: \"Arbeitsfl\u00E4che leeren\",\n light: \"Helles Design\",\n dark: \"Dunkles Design\",\n style: \"Stil\",\n styles: { sketch: \"Skizze: handgezeichnet\", business: \"Business: klar und n\u00FCchtern\" },\n language: \"Sprache\",\n about: \"\u00DCber Isothrum\",\n blog: \"Blog\",\n },\n welcome: {\n menuHint: \"Beispiel, Design, Sprache\u2026\",\n toolbarHint: \"Ein Ger\u00E4t w\u00E4hlen, dann auf die Arbeitsfl\u00E4che klicken\",\n pitch: \"Ein Netzwerk-Lab aus Containern und VMs zeichnen. Herunterladen, fertig zum Start mit Docker, Vagrant oder Terraform.\",\n example: \"Beispiel-Lab laden\",\n how: \"So funktioniert's\",\n },\n inspector: {\n name: \"Name\",\n runsAs: \"L\u00E4uft als\",\n automaticRouter: \"Automatischer Router\",\n container: \"Container (Docker)\",\n vm: \"Virtuelle Maschine\",\n routerNote:\n \"Nichts zu konfigurieren: Die Netze, an denen er h\u00E4ngt (seine LANs, VLANs und Kabel), erreichen einander \u00FCber den eigenen Router von Isoloom. Um das Routing selbst zu konfigurieren, ihn als Container (FRR) oder als VM betreiben.\",\n image: \"Image\",\n keepRunning: \"Laufen lassen\",\n applianceNote: \"Cisco IOL l\u00E4uft aus deinem eigenen Image: baue es mit\",\n ciscoOs: \"Cisco-OS\",\n needsKvm: \"L\u00E4uft in QEMU: der Docker-Host braucht /dev/kvm.\",\n dynamipsFirmware: (name: string) => `Dein 7200-IOS-Image in den Download legen: images/${name}.bin.`,\n iosConfig: \"IOS-Konfiguration\",\n iosConfigHint: \"Erg\u00E4nzt die Konfiguration, die Isothrum schreibt (Name, admin/admin \u00FCber SSH, die Adresse jeder Schnittstelle). Gilt beim ersten Start.\",\n keepRunningHint: \"F\u00FCr ein Image ohne eigenen Dienst (Alpine, Ubuntu, Kali\u2026): eine Maschine zum Arbeiten.\",\n os: \"Betriebssystem\",\n provision: \"Provisionierungsschritte (einer pro Zeile)\",\n ports: \"Dienst-Ports\",\n access: \"Der Benutzer landet auf dieser Maschine\",\n cables: \"Kabel\",\n noCables: \"Noch keine: von einem ihrer Punkte zu einer anderen Maschine ziehen.\",\n saveTitle: \"Die Einrichtung dieser Maschine als Ger\u00E4t in der Werkzeugleiste behalten, um sie erneut zu platzieren\",\n save: \"Als Ger\u00E4t speichern\",\n remove: \"Maschine entfernen\",\n },\n canvas: {\n imageShort: \"Image\",\n hosts: (n) => (n === 1 ? \"1 Host\" : `${String(n)} Hosts`),\n roles: { router: \"Router\", firewall: \"Firewall\", workstation: \"Arbeitsplatz\", server: \"Server\", desktop: \"Desktop\", host: \"Host\" },\n switchModel: (ports) => `Switch \u00B7 ${String(ports)} Ports`,\n live: {\n up: \"L\u00E4uft\",\n starting: \"Startet\",\n unhealthy: \"Fehlerhaft\",\n down: \"Gestoppt\",\n portUp: \"Verbindung aktiv\",\n portDown: \"Verbindung unterbrochen\",\n portUnknown: \"Unbekannt (gestoppt, oder der Port geh\u00F6rt zum Betriebssystem des Ger\u00E4ts)\",\n lanPorts: (up, total) => `${String(up)} von ${String(total)} Ports in diesem LAN aktiv`,\n cable: { up: \"\u00DCbertr\u00E4gt Verkehr\", cut: \"Getrennt: nichts kommt durch\", down: \"Unterbrochen: ein Ende ist gestoppt oder sein Port unterbrochen\" },\n cableShort: { cut: \"getrennt\", down: \"unterbrochen\" },\n },\n editTitle: (what) => `${what}: zum Bearbeiten doppelklicken`,\n unnamed: \"unbenannt\",\n machineName: \"Maschinenname\",\n vm: \"VM\",\n automatic: \"Automatisch\",\n container: \"Container\",\n access: \"Zugang\",\n addressTitle: (network, fixed) => `${network}: doppelklicken, um diese Adresse festzulegen${fixed ? \" (festgelegt)\" : \"\"}`,\n fixed: \"festgelegt\",\n addressOn: (network) => `Adresse in ${network}`,\n lanName: \"LAN-Name\",\n addressBlock: \"Adressbereich\",\n internetOnTitle: \"Erreicht das Internet (klicken, um es zu sperren)\",\n internetOffTitle: \"Kein Internet (klicken, um es zu erlauben)\",\n internetOn: \"Internetzugang: an\",\n internetOff: \"Internetzugang: aus\",\n showAreaTitle: \"Bereich des LANs anzeigen\",\n hideAreaTitle: \"Bereich des LANs ausblenden (das LAN bleibt: nur sein Rechteck verschwindet)\",\n showArea: \"Bereich anzeigen\",\n hideArea: \"Bereich ausblenden\",\n switchName: \"Switch-Name\",\n port: (n) => `Port ${String(n)}`,\n trunkPort: \"Trunk-Port\",\n trunkCarries: (vlans) => `Trunk, tr\u00E4gt ${vlans}`,\n noVlan: \"kein VLAN\",\n clickToChange: \"(klicken zum \u00C4ndern)\",\n vlanNumber: \"VLAN-Nummer\",\n vlanBlock: \"Adressbereich des VLANs\",\n remove: (what) => `${what} entfernen`,\n routerName: \"Router-Name\",\n portFree: (port) => `${port}: frei`,\n textOnly: \"Nur Text\",\n box: \"Kasten\",\n ellipse: \"Ellipse\",\n colors: { yellow: \"gelb\", red: \"rot\", blue: \"blau\", green: \"gr\u00FCn\", violet: \"violett\" },\n color: (color) => `Farbe ${color}`,\n write: \"Zum Schreiben doppelklicken\",\n note: \"Notiz\",\n noteName: \"Notiz\",\n },\n exportPanel: {\n copy: \"Kopieren\",\n copied: \"Kopiert\",\n labName: \"Lab-Name (der Name des Zips)\",\n fixFirst: \"Vor dem Export das Lab korrigieren\",\n download: (lab) => `${lab}.zip herunterladen`,\n onlySpec: \"Nur isoloom.yml\",\n where: \"Wo es l\u00E4uft\",\n whereIntro: \"Das Zip enth\u00E4lt einen Ordner pro Ziel. Entpacken und das passende starten.\",\n mixed:\n \"Dieses Lab mischt Container und VMs und l\u00E4uft daher mit Vagrant. Nur Container (Docker, Kubernetes, eine Cloud-VM) oder nur VMs (Proxmox, Cloud-VMs) schalten weitere Ziele frei.\",\n install: \"Isoloom startet jedes davon mit einem Befehl. Einmal installieren:\",\n files: (count) => `${String(count)} ${count === 1 ? \"Datei\" : \"Dateien\"}`,\n downloadOnly: (target) => `Nur ${target} herunterladen (mit isoloom.yml)`,\n downloadTarget: (target) => `${target} herunterladen`,\n withIsoloom: \"Mit Isoloom (stoppen mit isoloom down)\",\n withTool: \"Oder direkt mit dem Werkzeug\",\n run: \"Ausf\u00FChren\",\n specIntro: \"Das Lab als eine lesbare Datei, zum Ablegen in Git oder zum Bearbeiten von Hand.\",\n showSpec: \"Datei anzeigen\",\n hideSpec: \"Datei ausblenden\",\n containersAndVms: \"Container und VMs\",\n dockerOnOneVm: \"Docker auf einer VM\",\n oneVmPerMachine: \"eine VM pro Maschine\",\n },\n issues: {\n vlanBlocks: (vlan, block, other, sw) => `${vlan} ist ${block} auf einem Switch und ${other} auf ${sw}.`,\n areaBlock: (lan, block, switches) => `Der Bereich ${lan} ist ${block}, seine Switches sagen ${switches}.`,\n noName: { machine: \"Eine Maschine hat keinen Namen.\", lan: \"Ein LAN hat keinen Namen.\", switch: \"Ein Switch hat keinen Namen.\" },\n sameName: {\n machine: (name) => `Zwei Maschinen hei\u00DFen \u201E${name}\u201C.`,\n lan: (name) => `Zwei LANs hei\u00DFen \u201E${name}\u201C.`,\n switch: (name) => `Zwei Switches hei\u00DFen \u201E${name}\u201C.`,\n },\n badPort: (machine, entry) => `\u201E${entry}\u201C in den Ports von ${machine} ist kein Port: eine Zahl von 1 bis 65535, dann /udp, /http, /https oder /tls, wenn es nicht einfaches TCP ist.`,\n },\n gns3: {\n notGns3: \"Das ist kein GNS3-Projekt: die .gns3-Datei \u00F6ffnen (in einem .gns3project ist es die oberste).\",\n noTopology: \"Diese Datei enth\u00E4lt keine GNS3-Topologie.\",\n cisco: (node, kind) =>\n `${node}: Ein Cisco-${kind}-Router wurde zu einem automatischen Router; seine IOS-Konfiguration wird nicht \u00FCbernommen.`,\n firewall: (node) => `${node}: Eine Firewall wurde zu einem automatischen Router (ihre Regeln werden nicht \u00FCbernommen).`,\n noEquivalent: (node, type) => `${node}: Der GNS3-Knoten \u201E${type}\u201C hat keine Entsprechung; \u00FCbersprungen.`,\n noNodes: \"Das Projekt hat keine Knoten.\",\n },\n account: {\n signIn: \"Mit Cyber Auth anmelden\",\n signOut: \"Abmelden\",\n signedInAs: (name: string) => `Angemeldet als ${name}`,\n },\n projects: {\n save: \"In meinen Projekten speichern\",\n saveAs: \"Als neues Projekt speichern\u2026\",\n openList: \"Projekt \u00F6ffnen\u2026\",\n saveAsPrompt: \"Name des neuen Projekts:\",\n windowTitle: \"Meine Projekte\",\n loading: \"Projekte werden geladen\u2026\",\n none: \"Noch kein Projekt: dieses Lab speichern, um eines anzulegen.\",\n open: \"ge\u00F6ffnet\",\n openButton: \"\u00D6ffnen\",\n delete: (name: string) => `${name} l\u00F6schen`,\n confirmDelete: (name: string) => `Das Projekt \u201E${name}\u201C und seinen Verlauf l\u00F6schen?`,\n failed: (error: string) => `Projekte konnten nicht geladen werden: ${error}`,\n history: (name: string) => `Fr\u00FChere Versionen von ${name}`,\n noVersions: \"Noch keine fr\u00FChere Version.\",\n restore: \"\u00D6ffnen\",\n historyHint: \"Eine Version zu \u00F6ffnen legt sie auf die Arbeitsfl\u00E4che: R\u00FCckg\u00E4ngig holt die aktuelle zur\u00FCck, das n\u00E4chste Speichern beh\u00E4lt sie.\",\n opened: (name: string) => `\u201E${name}\u201C ge\u00F6ffnet. R\u00FCckg\u00E4ngig holt das vorherige Lab zur\u00FCck.`,\n status: {\n idle: (name: string) => `Projekt \u201E${name}\u201C`,\n saving: (name: string) => `\u201E${name}\u201C wird gespeichert\u2026`,\n saved: (name: string) => `In \u201E${name}\u201C gespeichert`,\n error: (name: string) => `\u201E${name}\u201C konnte nicht gespeichert werden`,\n },\n },\n machineRun: {\n display: \"Bildschirm (VNC)\",\n displayTitle: \"Der Bildschirm der Maschine: ihr VNC-Server oder die Anzeige der VM\",\n displayOpened: (what) => `Ge\u00F6ffnet: ${what}`,\n consoleHint: \"Doppelklick auf eine Maschine \u00F6ffnet ihre Konsole; Rechtsklick f\u00FCr Bildschirm und mehr.\",\n runFirst: \"Das Lab starten, um seine Konsolen zu \u00F6ffnen.\",\n running: \"L\u00E4uft im Lab.\",\n stopped: \"Gestoppt (der Rest des Labs l\u00E4uft).\",\n unknown: \"Nicht im laufenden Lab: das Lab neu starten, um sie hinzuzuf\u00FCgen.\",\n console: \"Konsole\",\n restart: \"Neu starten\",\n stop: \"Stoppen\",\n start: \"Starten\",\n snapshots: \"Snapshots\",\n takeSnapshot: \"Erstellen\",\n snapshotHint: \"Die Maschine so speichern, wie sie ist (ihre Dateien, die gespeicherte Konfiguration eines Routers); nicht ihre Volumes\",\n snapshotPrompt: \"Name des Snapshots (optional):\",\n noSnapshots: \"Noch keine.\",\n restore: \"Wiederherstellen\",\n inUse: \"aktiv\",\n ownImage: \"Zur\u00FCck zum eigenen Image\",\n deleteSnapshot: (label: string) => `Snapshot ${label} l\u00F6schen`,\n },\n update: {\n available: (version: string) => `Isothrum ${version} ist verf\u00FCgbar.`,\n restart: \"Neu starten zum Aktualisieren\",\n installing: \"Wird aktualisiert\u2026\",\n later: \"Sp\u00E4ter\",\n },\n};\n", "/**\n * The editor's words, in English: the source the other languages follow. `EditorText` is this\n * object's type, so a translation that misses a key (or a function's arguments) doesn't compile.\n * Not translated: machine, LAN and port names, images, OS ids, commands, file names, key letters,\n * and the engine's own messages (they come from Isoloom).\n */\nexport const en = {\n toolbar: {\n blocks: { switch: \"Switch\", router: \"Router\", firewall: \"Firewall\", container: \"Container\", vm: \"Virtual machine\", mine: \"My devices\" },\n kindsOf: (block: string) => `Kinds of ${block.toLowerCase()}`,\n devices: \"Devices\",\n hand: \"Hand: move the canvas\",\n select: \"Selection: select, move, delete\",\n lan: \"LAN\",\n lanTitle: \"LAN / VLAN: an area; machines inside it get an address on it\",\n switch: \"Switch\",\n switchTitle: \"Switch: ports in VLANs, and a trunk\",\n note: \"Note\",\n noteTitle: \"Note: text, a box or an ellipse, to explain the lab\",\n forget: (device: string) => `Forget ${device}`,\n forgetLabel: (device: string) => `Forget the device ${device}`,\n undo: \"Undo\",\n undoTitle: \"Undo \u00B7 Ctrl/\u2318 Z\",\n redo: \"Redo\",\n redoTitle: \"Redo \u00B7 Ctrl/\u2318 Shift Z\",\n },\n /** The line under the toolbar. */\n hints: {\n lan: \"Click on the canvas to place a LAN; machines inside it get an address on it. Double-click its name or range to edit it.\",\n note: \"Click on the canvas to place a note, then double-click it to write. Notes stay in the editor, not in isoloom.yml.\",\n place: (device: string) => `Click on the canvas to place a ${device.toLowerCase()}. Esc to cancel.`,\n hand: \"Drag to move the canvas. Press V to select again.\",\n cable: \"Drag from a dot on one machine to another to cable them.\",\n select: \"Drag on the canvas to select several machines: Delete, or Ctrl/\u2318 C, V, D. Hold Space to move the canvas.\",\n },\n /** The built-in devices of the toolbar, by preset id. Without a hint, the hint is what the device runs (its OS or image). */\n devices: {\n router: { label: \"Router\", hint: \"automatic: its networks reach each other\" },\n \"router-frr\": { label: \"Router (FRR)\", hint: \"FRRouting container you configure\" },\n firewall: { label: \"Firewall\", hint: \"nftables on Alpine\" },\n container: { label: \"Linux container\" },\n web: { label: \"Web server\", hint: \"nginx, port 80\" },\n database: { label: \"Database\", hint: \"PostgreSQL, port 5432\" },\n desktop: { label: \"Linux desktop\", hint: \"Xfce with VNC: right-click it, Screen; password vncpassword\" },\n \"linux-vm\": { label: \"Linux VM\" },\n \"ubuntu-vm\": { label: \"Ubuntu VM\" },\n \"kali-vm\": { label: \"Kali VM\" },\n \"windows-vm\": { label: \"Windows VM\" },\n workstation: { label: \"Workstation\", hint: \"where the user lands\" },\n \"cisco-iol\": { label: \"Cisco IOL router\", hint: \"IOS on Linux, your vrnetlab build\" },\n \"cisco-iol-l2\": { label: \"Cisco IOL switch\", hint: \"IOL-L2, your vrnetlab build\" },\n },\n /** A device saved from the canvas: what it runs (an image, an OS, or this). */\n myDevice: (what: string) => `your device: ${what}`,\n myDeviceRouter: \"automatic router\",\n status: {\n loading: \"Loading\u2026\",\n toFix: (count: number) => `${String(count)} to fix`,\n valid: \"Valid\",\n },\n run: {\n autoStart: \"Start this lab when the app opens\",\n autoStartNote: \"On this computer, when the app opens on this lab and it isn't running already.\",\n statusTitle: (up: number, total: number) => `${String(up)} of ${String(total)} machines up`,\n probed: \"ports read from the machines\",\n inferred: \"ports from the machines' states (VMs aren't probed)\",\n run: \"Run\",\n starting: \"Starting\u2026\",\n stop: \"Stop\",\n stopping: \"Stopping\u2026\",\n vmsTitle: \"A lab with VMs runs with Vagrant (and VirtualBox or libvirt): install it from vagrantup.com, or export the lab\",\n runVmsTitle: \"Run the lab on this machine (VMs with Vagrant)\",\n startingVmsLog: \"Starting the VMs with vagrant up (the first time downloads their boxes: minutes)\u2026\",\n runTitle: \"Run the lab on this machine (Docker)\",\n startingLog: \"Starting the lab with docker compose\u2026\",\n window: \"Run on this machine\",\n running: \"The lab is running. Select a LAN or a cable to capture its traffic.\",\n stopped: \"The lab is stopped.\",\n noDocker:\n \"Docker doesn't answer. Install and start it; on Linux, also add yourself to the docker group (sudo usermod -aG docker $USER, then log in again).\",\n noLiveCapture: (wireshark: boolean, dir: string) =>\n `${\n wireshark\n ? \"Wireshark can't capture live from this account: run sudo usermod -aG wireshark $USER, then log in again. Until then, captures\"\n : \"Wireshark isn't installed: captures\"\n } are saved as .pcap files under ${dir}.`,\n },\n capture: {\n capturing: (network: string) => `Capturing ${network}`,\n writingTo: \"Writing to\",\n live: \"Live in Wireshark.\",\n stop: \"Stop the capture\",\n start: \"Capture traffic\",\n runFirst: \"Run the lab to capture its traffic.\",\n },\n link: {\n suspend: \"Suspend the link\",\n resume: \"Resume the link\",\n suspendAll: \"Suspend every link\",\n resumeAll: \"Resume every link\",\n cableSuspended: \"Link suspended: nothing gets through.\",\n lanSuspended: (ports: number) => (ports === 1 ? \"1 link suspended.\" : `${String(ports)} links suspended.`),\n runFirst: \"Run the lab to suspend its links.\",\n },\n export: \"Export\",\n engineDidntLoad: (error: string) => `The engine didn't load: ${error}`,\n engineFailed: (error: string) => `The engine failed on this lab: ${error}`,\n toasts: {\n brokenLink: \"This share link is damaged: the lab couldn't be read.\",\n openedShared: (lab: string) => `Opened the shared lab \u201C${lab}\u201D. Undo brings back yours.`,\n linkCopied: \"Share link copied: anyone who opens it gets a copy of this lab.\",\n copyPrompt: \"Copy this link to share the lab:\",\n savedDevice: (device: string) => `Saved \u201C${device}\u201D: it's at the end of the toolbar.`,\n gns3Opened: (lab: string, machines: number, lans: number) =>\n `Opened \u201C${lab}\u201D from GNS3: ${String(machines)} machine${machines === 1 ? \"\" : \"s\"}, ${String(lans)} LAN${lans === 1 ? \"\" : \"s\"}.`,\n undoBringsBack: \"Undo brings back your lab.\",\n gns3Unreadable: \"This GNS3 project couldn't be read.\",\n },\n windows: {\n machine: \"Machine\",\n lan: (lan: string) => `LAN ${lan}`,\n cable: (a: string, b: string) => `Cable ${a} \u2194 ${b}`,\n portOn: (machine: string) => `Port on ${machine}`,\n cableNote: \"Each cable is its own small network (a /29); the two ends get its first two addresses.\",\n removeCable: \"Remove cable\",\n conditions: {\n title: \"Link conditions\",\n delay: \"Delay (ms, each way)\",\n jitter: \"Jitter (ms)\",\n loss: \"Loss (%)\",\n rate: \"Bandwidth (Mbit/s)\",\n hint: \"A slow or lossy link, applied with tc netem on each end. Empty means none.\",\n onLan: \"This cable puts the machine on the LAN: set conditions on the LAN.\",\n onVlan: \"Conditions go on a cable or a plain LAN; not on a switch's VLAN yet.\",\n },\n selected: (count: number) => `${String(count)} selected`,\n selection: (items: number, cables: number) =>\n `${String(items)} ${items === 1 ? \"item\" : \"items\"}, ${String(cables)} ${cables === 1 ? \"cable\" : \"cables\"}. Drag one of them to move them together.`,\n deleteSelection: (count: number) => `Delete ${String(count)} (Delete key)`,\n close: \"Close\",\n },\n lab: {\n title: \"Lab\",\n containers: \"Containers\",\n vms: \"VMs\",\n lans: \"LANs\",\n cables: \"Cables\",\n toFix: \"To fix\",\n valid: \"The lab is valid: ready to export.\",\n routing:\n \"A router needs its own forwarding configuration: each cable is its own network, and nothing routes between them for you.\",\n },\n menu: {\n menu: \"Menu\",\n example: \"Load the example lab\",\n vlanExample: \"Load the VLAN example\",\n gns3: \"Open a GNS3 project\u2026\",\n gns3File: \"GNS3 project\",\n share: \"Copy a share link\",\n fit: \"Fit to screen\",\n clear: \"Clear the canvas\",\n light: \"Light theme\",\n dark: \"Dark theme\",\n style: \"Style\",\n styles: { sketch: \"Sketch: hand-drawn\", business: \"Business: crisp and sober\" },\n language: \"Language\",\n about: \"About Isothrum\",\n blog: \"Blog\",\n },\n welcome: {\n menuHint: \"Example, theme, language\u2026\",\n toolbarHint: \"Pick a device, then click on the canvas\",\n pitch: \"Draw a network lab of containers and VMs. Download it, ready to run with Docker, Vagrant or Terraform.\",\n example: \"Load the example lab\",\n how: \"How it works\",\n },\n inspector: {\n name: \"Name\",\n runsAs: \"Runs as\",\n automaticRouter: \"Automatic router\",\n container: \"Container (Docker)\",\n vm: \"Virtual machine\",\n routerNote:\n \"Nothing to configure: the networks it is on (its LANs, VLANs and cables) reach each other through Isoloom's own router. To configure routing yourself, run it as a container (FRR) or a VM.\",\n image: \"Image\",\n keepRunning: \"Keep it running\",\n applianceNote: \"Cisco IOL runs from your own image: build it with\",\n ciscoOs: \"Cisco OS\",\n needsKvm: \"Runs in QEMU: the Docker host needs /dev/kvm.\",\n dynamipsFirmware: (name: string) => `Put your 7200 IOS image in the download as images/${name}.bin.`,\n iosConfig: \"IOS configuration\",\n iosConfigHint: \"Added to the one Isothrum writes (hostname, admin/admin over SSH, each interface\u2019s address). Applied on first boot.\",\n keepRunningHint: \"For an image with no service of its own (Alpine, Ubuntu, Kali\u2026): a machine to work from.\",\n os: \"Operating system\",\n provision: \"Provisioning steps (one per line)\",\n ports: \"Service ports\",\n access: \"The user lands on this machine\",\n cables: \"Cables\",\n noCables: \"None yet: drag from one of its dots to another machine.\",\n saveTitle: \"Keep this machine's setup as a device in the toolbar, to place it again\",\n save: \"Save as a device\",\n remove: \"Remove machine\",\n },\n /** On the canvas: machines, LANs, switches, routers, notes. */\n canvas: {\n imageShort: \"Image\",\n hosts: (n: number) => (n === 1 ? \"1 host\" : `${String(n)} hosts`),\n roles: { router: \"Router\", firewall: \"Firewall\", workstation: \"Workstation\", server: \"Server\", desktop: \"Desktop\", host: \"Host\" },\n switchModel: (ports: number) => `Switch \u00B7 ${String(ports)} ports`,\n live: {\n up: \"Running\",\n starting: \"Starting\",\n unhealthy: \"Unhealthy\",\n down: \"Stopped\",\n portUp: \"Link up\",\n portDown: \"Link down\",\n portUnknown: \"Unknown (stopped, or the port belongs to the device's OS)\",\n lanPorts: (up: number, total: number) => `${String(up)} of ${String(total)} ports on this LAN are up`,\n cable: { up: \"Carries traffic\", cut: \"Suspended: nothing gets through\", down: \"Down: an end is stopped or its port is down\" },\n cableShort: { cut: \"suspended\", down: \"down\" },\n },\n editTitle: (what: string) => `${what}: double-click to edit`,\n unnamed: \"unnamed\",\n machineName: \"Machine name\",\n vm: \"VM\",\n automatic: \"Automatic\",\n container: \"Container\",\n access: \"access\",\n addressTitle: (network: string, fixed: boolean) => `${network}: double-click to fix this address${fixed ? \" (fixed)\" : \"\"}`,\n fixed: \"fixed\",\n addressOn: (network: string) => `Address on ${network}`,\n lanName: \"LAN name\",\n addressBlock: \"Address block\",\n internetOnTitle: \"Reaches the internet (click to cut it off)\",\n internetOffTitle: \"No internet (click to allow it)\",\n internetOn: \"Internet access: on\",\n internetOff: \"Internet access: off\",\n showAreaTitle: \"Show the LAN's area\",\n hideAreaTitle: \"Hide the LAN's area (the LAN stays: only its rectangle goes)\",\n showArea: \"Show the area\",\n hideArea: \"Hide the area\",\n switchName: \"Switch name\",\n port: (n: number) => `Port ${String(n)}`,\n trunkPort: \"Trunk port\",\n trunkCarries: (vlans: string) => `trunk, carries ${vlans}`,\n noVlan: \"no VLAN\",\n clickToChange: \"(click to change)\",\n vlanNumber: \"VLAN number\",\n vlanBlock: \"VLAN address block\",\n remove: (what: string) => `Remove ${what}`,\n routerName: \"Router name\",\n portFree: (port: string) => `${port}: free`,\n textOnly: \"Text only\",\n box: \"Box\",\n ellipse: \"Ellipse\",\n colors: { yellow: \"yellow\", red: \"red\", blue: \"blue\", green: \"green\", violet: \"violet\" },\n color: (color: string) => `Color ${color}`,\n write: \"Double-click to write\",\n note: \"Note\",\n /** A note in lists (it has no name of its own). */\n noteName: \"note\",\n },\n exportPanel: {\n copy: \"Copy\",\n copied: \"Copied\",\n labName: \"Lab name (the zip's name)\",\n fixFirst: \"Fix the lab before exporting\",\n download: (lab: string) => `Download ${lab}.zip`,\n onlySpec: \"Only isoloom.yml\",\n where: \"Where it runs\",\n whereIntro: \"The zip holds one folder per target. Unzip it, then start the one that suits you.\",\n mixed:\n \"This lab mixes containers and VMs, so it runs with Vagrant. Make it all containers (Docker, Kubernetes, a cloud VM) or all VMs (Proxmox, cloud VMs) to unlock more targets.\",\n install: \"Isoloom starts any of them with one command. Install it once:\",\n files: (count: number) => `${String(count)} ${count === 1 ? \"file\" : \"files\"}`,\n downloadOnly: (target: string) => `Download ${target} only (with isoloom.yml)`,\n downloadTarget: (target: string) => `Download ${target}`,\n withIsoloom: \"With Isoloom (stop it with isoloom down)\",\n withTool: \"Or with the tool directly\",\n run: \"Run\",\n specIntro: \"The lab as one readable file, to keep in Git or edit by hand.\",\n showSpec: \"Show the file\",\n hideSpec: \"Hide the file\",\n /** Target names: \"Vagrant (containers and VMs)\", \"AWS (one VM per machine)\"\u2026 */\n containersAndVms: \"containers and VMs\",\n dockerOnOneVm: \"Docker on one VM\",\n oneVmPerMachine: \"one VM per machine\",\n },\n /** What the canvas checks before the engine runs. */\n issues: {\n vlanBlocks: (vlan: string, block: string, other: string, sw: string) => `${vlan} is ${block} on one switch and ${other} on ${sw}.`,\n areaBlock: (lan: string, block: string, switches: string) => `The ${lan} area is ${block}, its switches say ${switches}.`,\n noName: { machine: \"A machine has no name.\", lan: \"A LAN has no name.\", switch: \"A switch has no name.\" },\n sameName: {\n machine: (name: string) => `Two machines are named \u201C${name}\u201D.`,\n lan: (name: string) => `Two LANs are named \u201C${name}\u201D.`,\n switch: (name: string) => `Two switches are named \u201C${name}\u201D.`,\n },\n badPort: (machine: string, entry: string) => `\u201C${entry}\u201D in ${machine}'s ports isn't a port: a number from 1 to 65535, then /udp, /http, /https or /tls if it isn't plain TCP.`,\n },\n gns3: {\n notGns3: \"This isn't a GNS3 project: open the .gns3 file (inside a .gns3project, it's the one at the top).\",\n noTopology: \"This file has no GNS3 topology in it.\",\n cisco: (node: string, kind: string) =>\n `${node}: a Cisco ${kind} router became an automatic router; its IOS configuration isn't carried over.`,\n firewall: (node: string) => `${node}: a firewall became an automatic router (its rules aren't carried over).`,\n noEquivalent: (node: string, type: string) => `${node}: GNS3's \u201C${type}\u201D node has no equivalent; skipped.`,\n noNodes: \"The project has no nodes.\",\n },\n account: {\n signIn: \"Sign in with Cyber Auth\",\n signOut: \"Sign out\",\n signedInAs: (name: string) => `Signed in as ${name}`,\n },\n projects: {\n save: \"Save to my projects\",\n saveAs: \"Save as a new project\u2026\",\n openList: \"Open a project\u2026\",\n saveAsPrompt: \"Name of the new project:\",\n windowTitle: \"My projects\",\n loading: \"Loading your projects\u2026\",\n none: \"No project yet: save this lab to start one.\",\n open: \"open\",\n openButton: \"Open\",\n delete: (name: string) => `Delete ${name}`,\n confirmDelete: (name: string) => `Delete the project \u201C${name}\u201D and its history?`,\n failed: (error: string) => `Couldn't load your projects: ${error}`,\n history: (name: string) => `Earlier versions of ${name}`,\n noVersions: \"No earlier version yet.\",\n restore: \"Open\",\n historyHint: \"Opening a version puts it on the canvas: Undo brings back the current one, and the next save keeps it.\",\n opened: (name: string) => `Opened \u201C${name}\u201D. Undo brings back the lab that was there.`,\n status: {\n idle: (name: string) => `Project \u201C${name}\u201D`,\n saving: (name: string) => `Saving \u201C${name}\u201D\u2026`,\n saved: (name: string) => `Saved to \u201C${name}\u201D`,\n error: (name: string) => `Couldn't save \u201C${name}\u201D`,\n },\n },\n machineRun: {\n display: \"Screen (VNC)\",\n displayTitle: \"The machine's screen: its VNC server, or the VM's display\",\n displayOpened: (what: string) => `Opened ${what}`,\n consoleHint: \"Double-click a machine for its console; right-click it for its screen and more.\",\n runFirst: \"Run the lab to open its consoles.\",\n running: \"Running in the lab.\",\n stopped: \"Stopped (the rest of the lab runs).\",\n unknown: \"Not in the running lab: start the lab again to add it.\",\n console: \"Console\",\n restart: \"Restart\",\n stop: \"Stop\",\n start: \"Start\",\n snapshots: \"Snapshots\",\n takeSnapshot: \"Take one\",\n snapshotHint: \"Save the machine as it is now (its files, a router's saved configuration); not its volumes\",\n snapshotPrompt: \"Name of the snapshot (optional):\",\n noSnapshots: \"None yet.\",\n restore: \"Restore\",\n inUse: \"in use\",\n ownImage: \"Back to its own image\",\n deleteSnapshot: (label: string) => `Delete the snapshot ${label}`,\n },\n update: {\n available: (version: string) => `Isothrum ${version} is available.`,\n restart: \"Restart to update\",\n installing: \"Updating\u2026\",\n later: \"Later\",\n },\n};\n\nexport type EditorText = typeof en;\n", "import type { EditorText } from \"./en\";\n\nexport const es: EditorText = {\n toolbar: {\n blocks: { switch: \"Switch\", router: \"Router\", firewall: \"Cortafuegos\", container: \"Contenedor\", vm: \"M\u00E1quina virtual\", mine: \"Mis equipos\" },\n kindsOf: (block) => `Tipos: ${block.toLowerCase()}`,\n devices: \"Dispositivos\",\n hand: \"Mano: mover el lienzo\",\n select: \"Selecci\u00F3n: seleccionar, mover, eliminar\",\n lan: \"LAN\",\n lanTitle: \"LAN / VLAN: un \u00E1rea; las m\u00E1quinas que est\u00E1n dentro reciben una direcci\u00F3n en ella\",\n switch: \"Switch\",\n switchTitle: \"Switch: puertos en VLAN y un trunk\",\n note: \"Nota\",\n noteTitle: \"Nota: texto, un recuadro o una elipse, para explicar el laboratorio\",\n forget: (device) => `Olvidar ${device}`,\n forgetLabel: (device) => `Olvidar el dispositivo ${device}`,\n undo: \"Deshacer\",\n undoTitle: \"Deshacer \u00B7 Ctrl/\u2318 Z\",\n redo: \"Rehacer\",\n redoTitle: \"Rehacer \u00B7 Ctrl/\u2318 May\u00FAs Z\",\n },\n hints: {\n lan: \"Haz clic en el lienzo para colocar una LAN; las m\u00E1quinas que est\u00E1n dentro reciben una direcci\u00F3n en ella. Haz doble clic en su nombre o rango para editarlo.\",\n note: \"Haz clic en el lienzo para colocar una nota y luego doble clic para escribir. Las notas se quedan en el editor, no en isoloom.yml.\",\n place: (device) => `${device}: haz clic en un punto del lienzo para colocar. Esc para cancelar.`,\n hand: \"Arrastra para mover el lienzo. Pulsa V para volver a seleccionar.\",\n cable: \"Arrastra desde un punto de una m\u00E1quina hasta otra para conectarlas.\",\n select: \"Arrastra en el lienzo para seleccionar varias m\u00E1quinas: Supr, o Ctrl/\u2318 C, V, D. Mant\u00E9n Espacio para mover el lienzo.\",\n },\n devices: {\n router: { label: \"Router\", hint: \"autom\u00E1tico: sus redes se comunican entre s\u00ED\" },\n \"router-frr\": { label: \"Router (FRR)\", hint: \"contenedor FRRouting que configuras t\u00FA\" },\n firewall: { label: \"Cortafuegos\", hint: \"nftables en Alpine\" },\n container: { label: \"Contenedor Linux\" },\n web: { label: \"Servidor web\", hint: \"nginx, puerto 80\" },\n database: { label: \"Base de datos\", hint: \"PostgreSQL, puerto 5432\" },\n desktop: { label: \"Escritorio Linux\", hint: \"Xfce con VNC: clic derecho, Pantalla; contrase\u00F1a vncpassword\" },\n \"linux-vm\": { label: \"VM Linux\" },\n \"ubuntu-vm\": { label: \"VM Ubuntu\" },\n \"kali-vm\": { label: \"VM Kali\" },\n \"windows-vm\": { label: \"VM Windows\" },\n workstation: { label: \"Estaci\u00F3n de trabajo\", hint: \"donde entra el usuario\" },\n \"cisco-iol\": { label: \"Router Cisco IOL\", hint: \"IOS en Linux, tu imagen vrnetlab\" },\n \"cisco-iol-l2\": { label: \"Switch Cisco IOL\", hint: \"IOL-L2, tu imagen vrnetlab\" },\n },\n myDevice: (what) => `tu dispositivo: ${what}`,\n myDeviceRouter: \"router autom\u00E1tico\",\n status: {\n loading: \"Cargando\u2026\",\n toFix: (count) => `${String(count)} por corregir`,\n valid: \"V\u00E1lido\",\n },\n run: {\n autoStart: \"Iniciar este laboratorio al abrir la aplicaci\u00F3n\",\n autoStartNote: \"En este ordenador, cuando la aplicaci\u00F3n se abre en este laboratorio y no est\u00E1 ya en marcha.\",\n statusTitle: (up, total) => `${String(up)} de ${String(total)} m\u00E1quinas en marcha`,\n probed: \"puertos le\u00EDdos de las m\u00E1quinas\",\n inferred: \"puertos seg\u00FAn el estado de las m\u00E1quinas (las VM no se sondean)\",\n run: \"Ejecutar\",\n starting: \"Iniciando\u2026\",\n stop: \"Detener\",\n stopping: \"Deteniendo\u2026\",\n vmsTitle: \"Un laboratorio con VM se ejecuta con Vagrant (y VirtualBox o libvirt): inst\u00E1lalo desde vagrantup.com, o exporta el laboratorio\",\n runVmsTitle: \"Ejecutar el laboratorio en esta m\u00E1quina (VM con Vagrant)\",\n startingVmsLog: \"Iniciando las VM con vagrant up (la primera vez descarga sus boxes: minutos)\u2026\",\n runTitle: \"Ejecutar el laboratorio en esta m\u00E1quina (Docker)\",\n startingLog: \"Iniciando el laboratorio con docker compose\u2026\",\n window: \"Ejecutar en esta m\u00E1quina\",\n running: \"El laboratorio est\u00E1 en marcha. Selecciona una LAN o un cable para capturar su tr\u00E1fico.\",\n stopped: \"El laboratorio est\u00E1 detenido.\",\n noDocker:\n \"Docker no responde. Inst\u00E1lalo e in\u00EDcialo; en Linux, a\u00F1\u00E1dete tambi\u00E9n al grupo docker (sudo usermod -aG docker $USER y vuelve a iniciar sesi\u00F3n).\",\n noLiveCapture: (wireshark, dir) =>\n `${\n wireshark\n ? \"Wireshark no puede capturar en directo desde esta cuenta: ejecuta sudo usermod -aG wireshark $USER y vuelve a iniciar sesi\u00F3n. Mientras tanto, las capturas\"\n : \"Wireshark no est\u00E1 instalado: las capturas\"\n } se guardan como archivos .pcap en ${dir}.`,\n },\n capture: {\n capturing: (network) => `Capturando ${network}`,\n writingTo: \"Escribiendo en\",\n live: \"En directo en Wireshark.\",\n stop: \"Detener la captura\",\n start: \"Capturar tr\u00E1fico\",\n runFirst: \"Ejecuta el laboratorio para capturar su tr\u00E1fico.\",\n },\n link: {\n suspend: \"Suspender el enlace\",\n resume: \"Reanudar el enlace\",\n suspendAll: \"Suspender todos los enlaces\",\n resumeAll: \"Reanudar todos los enlaces\",\n cableSuspended: \"Enlace suspendido: no pasa nada.\",\n lanSuspended: (ports) => (ports === 1 ? \"1 enlace suspendido.\" : `${String(ports)} enlaces suspendidos.`),\n runFirst: \"Ejecuta el laboratorio para suspender sus enlaces.\",\n },\n export: \"Exportar\",\n engineDidntLoad: (error) => `El motor no se carg\u00F3: ${error}`,\n engineFailed: (error) => `El motor fall\u00F3 con este laboratorio: ${error}`,\n toasts: {\n brokenLink: \"Este enlace para compartir est\u00E1 da\u00F1ado: no se pudo leer el laboratorio.\",\n openedShared: (lab) => `Se abri\u00F3 el laboratorio compartido \u201C${lab}\u201D. Deshacer recupera el tuyo.`,\n linkCopied: \"Enlace copiado: quien lo abra obtendr\u00E1 una copia de este laboratorio.\",\n copyPrompt: \"Copia este enlace para compartir el laboratorio:\",\n savedDevice: (device) => `\u201C${device}\u201D guardado: est\u00E1 al final de la barra de herramientas.`,\n gns3Opened: (lab, machines, lans) =>\n `Se abri\u00F3 \u201C${lab}\u201D desde GNS3: ${String(machines)} m\u00E1quina${machines === 1 ? \"\" : \"s\"}, ${String(lans)} LAN.`,\n undoBringsBack: \"Deshacer recupera tu laboratorio.\",\n gns3Unreadable: \"No se pudo leer este proyecto GNS3.\",\n },\n windows: {\n machine: \"M\u00E1quina\",\n lan: (lan) => `LAN ${lan}`,\n cable: (a, b) => `Cable ${a} \u2194 ${b}`,\n portOn: (machine) => `Puerto en ${machine}`,\n cableNote: \"Cada cable es su propia red peque\u00F1a (una /29); sus dos extremos reciben sus dos primeras direcciones.\",\n removeCable: \"Quitar el cable\",\n conditions: {\n title: \"Condiciones del enlace\",\n delay: \"Latencia (ms, en cada sentido)\",\n jitter: \"Jitter (ms)\",\n loss: \"P\u00E9rdida (%)\",\n rate: \"Ancho de banda (Mbit/s)\",\n hint: \"Un enlace lento o con p\u00E9rdidas, aplicado con tc netem en cada extremo. Vac\u00EDo: ninguna.\",\n onLan: \"Este cable pone la m\u00E1quina en la LAN: ajusta las condiciones en la LAN.\",\n onVlan: \"Las condiciones van en un cable o una LAN normal; todav\u00EDa no en la VLAN de un switch.\",\n },\n selected: (count) => `${String(count)} seleccionados`,\n selection: (items, cables) =>\n `${String(items)} elemento${items === 1 ? \"\" : \"s\"}, ${String(cables)} cable${cables === 1 ? \"\" : \"s\"}. Arrastra uno de ellos para moverlos juntos.`,\n deleteSelection: (count) => `Eliminar ${String(count)} (tecla Supr)`,\n close: \"Cerrar\",\n },\n lab: {\n title: \"Laboratorio\",\n containers: \"Contenedores\",\n vms: \"VM\",\n lans: \"LAN\",\n cables: \"Cables\",\n toFix: \"Por corregir\",\n valid: \"El laboratorio es v\u00E1lido: listo para exportar.\",\n routing:\n \"Un router necesita su propia configuraci\u00F3n de reenv\u00EDo: cada cable es su propia red y nada enruta entre ellas por ti.\",\n },\n menu: {\n menu: \"Men\u00FA\",\n example: \"Cargar el laboratorio de ejemplo\",\n vlanExample: \"Cargar el ejemplo de VLAN\",\n gns3: \"Abrir un proyecto GNS3\u2026\",\n gns3File: \"Proyecto GNS3\",\n share: \"Copiar un enlace para compartir\",\n fit: \"Ajustar a la pantalla\",\n clear: \"Vaciar el lienzo\",\n light: \"Tema claro\",\n dark: \"Tema oscuro\",\n style: \"Estilo\",\n styles: { sketch: \"Boceto: a mano alzada\", business: \"Business: limpio y sobrio\" },\n language: \"Idioma\",\n about: \"Acerca de Isothrum\",\n blog: \"Blog\",\n },\n welcome: {\n menuHint: \"Ejemplo, tema, idioma\u2026\",\n toolbarHint: \"Elige un dispositivo y haz clic en el lienzo\",\n pitch: \"Dibuja un laboratorio de red con contenedores y m\u00E1quinas virtuales. Desc\u00E1rgalo, listo para ejecutar con Docker, Vagrant o Terraform.\",\n example: \"Cargar el laboratorio de ejemplo\",\n how: \"C\u00F3mo funciona\",\n },\n inspector: {\n name: \"Nombre\",\n runsAs: \"Se ejecuta como\",\n automaticRouter: \"Router autom\u00E1tico\",\n container: \"Contenedor (Docker)\",\n vm: \"M\u00E1quina virtual\",\n routerNote:\n \"Nada que configurar: las redes a las que est\u00E1 conectado (sus LAN, VLAN y cables) se comunican a trav\u00E9s del router propio de Isoloom. Para configurar el enrutamiento t\u00FA mismo, ejec\u00FAtalo como contenedor (FRR) o como VM.\",\n image: \"Imagen\",\n keepRunning: \"Mantenerlo en marcha\",\n applianceNote: \"Cisco IOL se ejecuta desde tu propia imagen: cr\u00E9ala con\",\n ciscoOs: \"SO de Cisco\",\n needsKvm: \"Se ejecuta en QEMU: el host Docker necesita /dev/kvm.\",\n dynamipsFirmware: (name: string) => `Pon tu imagen IOS de 7200 en la descarga como images/${name}.bin.`,\n iosConfig: \"Configuraci\u00F3n IOS\",\n iosConfigHint: \"Se a\u00F1ade a la que escribe Isothrum (nombre, admin/admin por SSH, la direcci\u00F3n de cada interfaz). Se aplica en el primer arranque.\",\n keepRunningHint: \"Para una imagen sin servicio propio (Alpine, Ubuntu, Kali\u2026): una m\u00E1quina desde la que trabajar.\",\n os: \"Sistema operativo\",\n provision: \"Pasos de aprovisionamiento (uno por l\u00EDnea)\",\n ports: \"Puertos de servicio\",\n access: \"El usuario entra en esta m\u00E1quina\",\n cables: \"Cables\",\n noCables: \"Ninguno a\u00FAn: arrastra desde uno de sus puntos hasta otra m\u00E1quina.\",\n saveTitle: \"Guardar la configuraci\u00F3n de esta m\u00E1quina como dispositivo en la barra de herramientas, para volver a colocarla\",\n save: \"Guardar como dispositivo\",\n remove: \"Quitar la m\u00E1quina\",\n },\n canvas: {\n imageShort: \"Imagen\",\n hosts: (n) => (n === 1 ? \"1 equipo\" : `${String(n)} equipos`),\n roles: { router: \"Router\", firewall: \"Cortafuegos\", workstation: \"Puesto de trabajo\", server: \"Servidor\", desktop: \"Escritorio\", host: \"Equipo\" },\n switchModel: (ports) => `Switch \u00B7 ${String(ports)} puertos`,\n live: {\n up: \"En marcha\",\n starting: \"Arrancando\",\n unhealthy: \"Con problemas\",\n down: \"Detenida\",\n portUp: \"Enlace activo\",\n portDown: \"Enlace ca\u00EDdo\",\n portUnknown: \"Desconocido (detenida, o el puerto pertenece al SO del equipo)\",\n lanPorts: (up, total) => `${String(up)} de ${String(total)} puertos activos en esta LAN`,\n cable: { up: \"Pasa tr\u00E1fico\", cut: \"Suspendido: no pasa nada\", down: \"Ca\u00EDdo: un extremo est\u00E1 detenido o su puerto ca\u00EDdo\" },\n cableShort: { cut: \"suspendido\", down: \"ca\u00EDdo\" },\n },\n editTitle: (what) => `${what}: doble clic para editar`,\n unnamed: \"sin nombre\",\n machineName: \"Nombre de la m\u00E1quina\",\n vm: \"VM\",\n automatic: \"Autom\u00E1tico\",\n container: \"Contenedor\",\n access: \"acceso\",\n addressTitle: (network, fixed) => `${network}: doble clic para fijar esta direcci\u00F3n${fixed ? \" (fija)\" : \"\"}`,\n fixed: \"fija\",\n addressOn: (network) => `Direcci\u00F3n en ${network}`,\n lanName: \"Nombre de la LAN\",\n addressBlock: \"Bloque de direcciones\",\n internetOnTitle: \"Llega a internet (haz clic para cortarlo)\",\n internetOffTitle: \"Sin internet (haz clic para permitirlo)\",\n internetOn: \"Acceso a internet: s\u00ED\",\n internetOff: \"Acceso a internet: no\",\n showAreaTitle: \"Mostrar el \u00E1rea de la LAN\",\n hideAreaTitle: \"Ocultar el \u00E1rea de la LAN (la LAN se queda: solo desaparece su rect\u00E1ngulo)\",\n showArea: \"Mostrar el \u00E1rea\",\n hideArea: \"Ocultar el \u00E1rea\",\n switchName: \"Nombre del switch\",\n port: (n) => `Puerto ${String(n)}`,\n trunkPort: \"Puerto trunk\",\n trunkCarries: (vlans) => `trunk, lleva ${vlans}`,\n noVlan: \"ninguna VLAN\",\n clickToChange: \"(haz clic para cambiar)\",\n vlanNumber: \"N\u00FAmero de VLAN\",\n vlanBlock: \"Bloque de direcciones de la VLAN\",\n remove: (what) => `Quitar ${what}`,\n routerName: \"Nombre del router\",\n portFree: (port) => `${port}: libre`,\n textOnly: \"Solo texto\",\n box: \"Recuadro\",\n ellipse: \"Elipse\",\n colors: { yellow: \"amarillo\", red: \"rojo\", blue: \"azul\", green: \"verde\", violet: \"violeta\" },\n color: (color) => `Color ${color}`,\n write: \"Doble clic para escribir\",\n note: \"Nota\",\n noteName: \"nota\",\n },\n exportPanel: {\n copy: \"Copiar\",\n copied: \"Copiado\",\n labName: \"Nombre del laboratorio (el del zip)\",\n fixFirst: \"Corrige el laboratorio antes de exportar\",\n download: (lab) => `Descargar ${lab}.zip`,\n onlySpec: \"Solo isoloom.yml\",\n where: \"D\u00F3nde se ejecuta\",\n whereIntro: \"El zip contiene una carpeta por destino. Descompr\u00EDmelo y arranca el que te convenga.\",\n mixed:\n \"Este laboratorio mezcla contenedores y m\u00E1quinas virtuales, as\u00ED que funciona con Vagrant. Hazlo todo de contenedores (Docker, Kubernetes, una VM en la nube) o todo de VM (Proxmox, VM en la nube) para desbloquear m\u00E1s destinos.\",\n install: \"Isoloom arranca cualquiera de ellos con un solo comando. Inst\u00E1lalo una vez:\",\n files: (count) => `${String(count)} archivo${count === 1 ? \"\" : \"s\"}`,\n downloadOnly: (target) => `Descargar solo ${target} (con isoloom.yml)`,\n downloadTarget: (target) => `Descargar ${target}`,\n withIsoloom: \"Con Isoloom (detenlo con isoloom down)\",\n withTool: \"O directamente con la herramienta\",\n run: \"Ejecutar\",\n specIntro: \"El laboratorio en un \u00FAnico archivo legible, para guardarlo en Git o editarlo a mano.\",\n showSpec: \"Mostrar el archivo\",\n hideSpec: \"Ocultar el archivo\",\n containersAndVms: \"contenedores y VM\",\n dockerOnOneVm: \"Docker en una VM\",\n oneVmPerMachine: \"una VM por m\u00E1quina\",\n },\n issues: {\n vlanBlocks: (vlan, block, other, sw) => `${vlan} es ${block} en un switch y ${other} en ${sw}.`,\n areaBlock: (lan, block, switches) => `El \u00E1rea ${lan} es ${block}, sus switches dicen ${switches}.`,\n noName: { machine: \"Una m\u00E1quina no tiene nombre.\", lan: \"Una LAN no tiene nombre.\", switch: \"Un switch no tiene nombre.\" },\n sameName: {\n machine: (name) => `Dos m\u00E1quinas se llaman \u201C${name}\u201D.`,\n lan: (name) => `Dos LAN se llaman \u201C${name}\u201D.`,\n switch: (name) => `Dos switches se llaman \u201C${name}\u201D.`,\n },\n badPort: (machine, entry) => `\u00AB${entry}\u00BB en los puertos de ${machine} no es un puerto: un n\u00FAmero de 1 a 65535 y, si no es TCP simple, /udp, /http, /https o /tls.`,\n },\n gns3: {\n notGns3: \"Esto no es un proyecto GNS3: abre el archivo .gns3 (dentro de un .gns3project, es el que est\u00E1 en la ra\u00EDz).\",\n noTopology: \"Este archivo no contiene ninguna topolog\u00EDa GNS3.\",\n cisco: (node, kind) =>\n `${node}: un router Cisco ${kind} se convirti\u00F3 en un router autom\u00E1tico; su configuraci\u00F3n IOS no se conserva.`,\n firewall: (node) => `${node}: un cortafuegos se convirti\u00F3 en un router autom\u00E1tico (sus reglas no se conservan).`,\n noEquivalent: (node, type) => `${node}: el nodo \u201C${type}\u201D de GNS3 no tiene equivalente; se omiti\u00F3.`,\n noNodes: \"El proyecto no tiene nodos.\",\n },\n account: {\n signIn: \"Iniciar sesi\u00F3n con Cyber Auth\",\n signOut: \"Cerrar sesi\u00F3n\",\n signedInAs: (name: string) => `Sesi\u00F3n iniciada: ${name}`,\n },\n projects: {\n save: \"Guardar en mis proyectos\",\n saveAs: \"Guardar como nuevo proyecto\u2026\",\n openList: \"Abrir un proyecto\u2026\",\n saveAsPrompt: \"Nombre del nuevo proyecto:\",\n windowTitle: \"Mis proyectos\",\n loading: \"Cargando tus proyectos\u2026\",\n none: \"A\u00FAn no hay proyectos: guarda este lab para crear uno.\",\n open: \"abierto\",\n openButton: \"Abrir\",\n delete: (name: string) => `Eliminar ${name}`,\n confirmDelete: (name: string) => `\u00BFEliminar el proyecto \u00AB${name}\u00BB y su historial?`,\n failed: (error: string) => `No se pudieron cargar tus proyectos: ${error}`,\n history: (name: string) => `Versiones anteriores de ${name}`,\n noVersions: \"A\u00FAn no hay versiones anteriores.\",\n restore: \"Abrir\",\n historyHint: \"Abrir una versi\u00F3n la pone en el lienzo: Deshacer recupera la actual, y el pr\u00F3ximo guardado la conserva.\",\n opened: (name: string) => `\u00AB${name}\u00BB abierto. Deshacer recupera el lab que hab\u00EDa.`,\n status: {\n idle: (name: string) => `Proyecto \u00AB${name}\u00BB`,\n saving: (name: string) => `Guardando \u00AB${name}\u00BB\u2026`,\n saved: (name: string) => `Guardado en \u00AB${name}\u00BB`,\n error: (name: string) => `No se pudo guardar \u00AB${name}\u00BB`,\n },\n },\n machineRun: {\n display: \"Pantalla (VNC)\",\n displayTitle: \"La pantalla de la m\u00E1quina: su servidor VNC, o la pantalla de la VM\",\n displayOpened: (what) => `Abierto: ${what}`,\n consoleHint: \"Doble clic en una m\u00E1quina para su consola; clic derecho para su pantalla y m\u00E1s.\",\n runFirst: \"Ejecuta el laboratorio para abrir sus consolas.\",\n running: \"En marcha en el lab.\",\n stopped: \"Detenida (el resto del lab sigue).\",\n unknown: \"No est\u00E1 en el lab en marcha: vuelve a iniciar el lab para a\u00F1adirla.\",\n console: \"Consola\",\n restart: \"Reiniciar\",\n stop: \"Detener\",\n start: \"Iniciar\",\n snapshots: \"Instant\u00E1neas\",\n takeSnapshot: \"Tomar una\",\n snapshotHint: \"Guardar la m\u00E1quina tal como est\u00E1 (sus archivos, la configuraci\u00F3n guardada de un router); no sus vol\u00FAmenes\",\n snapshotPrompt: \"Nombre de la instant\u00E1nea (opcional):\",\n noSnapshots: \"Ninguna todav\u00EDa.\",\n restore: \"Restaurar\",\n inUse: \"en uso\",\n ownImage: \"Volver a su imagen\",\n deleteSnapshot: (label: string) => `Eliminar la instant\u00E1nea ${label}`,\n },\n update: {\n available: (version: string) => `Isothrum ${version} est\u00E1 disponible.`,\n restart: \"Reiniciar para actualizar\",\n installing: \"Actualizando\u2026\",\n later: \"M\u00E1s tarde\",\n },\n};\n", "import type { EditorText } from \"./en\";\n\nexport const fr: EditorText = {\n toolbar: {\n blocks: { switch: \"Switch\", router: \"Routeur\", firewall: \"Pare-feu\", container: \"Conteneur\", vm: \"Machine virtuelle\", mine: \"Mes \u00E9quipements\" },\n kindsOf: (block) => `Types : ${block.toLowerCase()}`,\n devices: \"Appareils\",\n hand: \"Main : d\u00E9placer le canevas\",\n select: \"S\u00E9lection : s\u00E9lectionner, d\u00E9placer, supprimer\",\n lan: \"LAN\",\n lanTitle: \"LAN / VLAN : une zone ; les machines \u00E0 l'int\u00E9rieur y re\u00E7oivent une adresse\",\n switch: \"Switch\",\n switchTitle: \"Switch : des ports dans des VLAN, et un trunk\",\n note: \"Note\",\n noteTitle: \"Note : du texte, un cadre ou une ellipse, pour expliquer le lab\",\n forget: (device) => `Oublier ${device}`,\n forgetLabel: (device) => `Oublier l'appareil ${device}`,\n undo: \"Annuler\",\n undoTitle: \"Annuler \u00B7 Ctrl/\u2318 Z\",\n redo: \"R\u00E9tablir\",\n redoTitle: \"R\u00E9tablir \u00B7 Ctrl/\u2318 Maj Z\",\n },\n hints: {\n lan: \"Cliquez sur le canevas pour placer un LAN ; les machines \u00E0 l'int\u00E9rieur y re\u00E7oivent une adresse. Double-cliquez sur son nom ou sa plage pour les modifier.\",\n note: \"Cliquez sur le canevas pour placer une note, puis double-cliquez dessus pour \u00E9crire. Les notes restent dans l'\u00E9diteur, pas dans isoloom.yml.\",\n place: (device) => `${device} : cliquez sur le canevas pour l'ajouter. \u00C9chap pour annuler.`,\n hand: \"Faites glisser pour d\u00E9placer le canevas. Appuyez sur V pour revenir \u00E0 la s\u00E9lection.\",\n cable: \"Tirez d'un point d'une machine vers une autre pour les c\u00E2bler.\",\n select: \"Faites glisser sur le canevas pour s\u00E9lectionner plusieurs machines : Suppr, ou Ctrl/\u2318 C, V, D. Maintenez Espace pour d\u00E9placer le canevas.\",\n },\n devices: {\n router: { label: \"Routeur\", hint: \"automatique : ses r\u00E9seaux communiquent entre eux\" },\n \"router-frr\": { label: \"Routeur (FRR)\", hint: \"conteneur FRRouting que vous configurez\" },\n firewall: { label: \"Pare-feu\", hint: \"nftables sur Alpine\" },\n container: { label: \"Conteneur Linux\" },\n web: { label: \"Serveur web\", hint: \"nginx, port 80\" },\n database: { label: \"Base de donn\u00E9es\", hint: \"PostgreSQL, port 5432\" },\n desktop: { label: \"Bureau Linux\", hint: \"Xfce avec VNC : clic droit, \u00C9cran ; mot de passe vncpassword\" },\n \"linux-vm\": { label: \"VM Linux\" },\n \"ubuntu-vm\": { label: \"VM Ubuntu\" },\n \"kali-vm\": { label: \"VM Kali\" },\n \"windows-vm\": { label: \"VM Windows\" },\n workstation: { label: \"Poste de travail\", hint: \"l\u00E0 o\u00F9 arrive l'utilisateur\" },\n \"cisco-iol\": { label: \"Routeur Cisco IOL\", hint: \"IOS sur Linux, votre image vrnetlab\" },\n \"cisco-iol-l2\": { label: \"Switch Cisco IOL\", hint: \"IOL-L2, votre image vrnetlab\" },\n },\n myDevice: (what) => `votre appareil : ${what}`,\n myDeviceRouter: \"routeur automatique\",\n status: {\n loading: \"Chargement\u2026\",\n toFix: (count) => `${String(count)} \u00E0 corriger`,\n valid: \"Valide\",\n },\n run: {\n autoStart: \"Lancer ce lab \u00E0 l\u2019ouverture de l\u2019application\",\n autoStartNote: \"Sur cet ordinateur, quand l\u2019application s\u2019ouvre sur ce lab et qu\u2019il ne tourne pas d\u00E9j\u00E0.\",\n statusTitle: (up, total) => `${String(up)} machines sur ${String(total)} en marche`,\n probed: \"ports lus sur les machines\",\n inferred: \"ports d\u2019apr\u00E8s l\u2019\u00E9tat des machines (les VM ne sont pas sond\u00E9es)\",\n run: \"Lancer\",\n starting: \"D\u00E9marrage\u2026\",\n stop: \"Arr\u00EAter\",\n stopping: \"Arr\u00EAt\u2026\",\n vmsTitle: \"Un lab avec des VM tourne avec Vagrant (et VirtualBox ou libvirt) : installez-le depuis vagrantup.com, ou exportez le lab\",\n runVmsTitle: \"Lancer le lab sur cette machine (VM avec Vagrant)\",\n startingVmsLog: \"D\u00E9marrage des VM avec vagrant up (la premi\u00E8re fois t\u00E9l\u00E9charge leurs box : quelques minutes)\u2026\",\n runTitle: \"Lancer le lab sur cette machine (Docker)\",\n startingLog: \"D\u00E9marrage du lab avec docker compose\u2026\",\n window: \"Lancer sur cette machine\",\n running: \"Le lab tourne. S\u00E9lectionnez un LAN ou un c\u00E2ble pour capturer son trafic.\",\n stopped: \"Le lab est arr\u00EAt\u00E9.\",\n noDocker:\n \"Docker ne r\u00E9pond pas. Installez-le et d\u00E9marrez-le ; sous Linux, ajoutez-vous aussi au groupe docker (sudo usermod -aG docker $USER, puis reconnectez-vous).\",\n noLiveCapture: (wireshark, dir) =>\n `${\n wireshark\n ? \"Wireshark ne peut pas capturer en direct depuis ce compte : lancez sudo usermod -aG wireshark $USER, puis reconnectez-vous. En attendant, les captures\"\n : \"Wireshark n'est pas install\u00E9 : les captures\"\n } sont enregistr\u00E9es en fichiers .pcap dans ${dir}.`,\n },\n capture: {\n capturing: (network) => `Capture de ${network}`,\n writingTo: \"\u00C9criture dans\",\n live: \"En direct dans Wireshark.\",\n stop: \"Arr\u00EAter la capture\",\n start: \"Capturer le trafic\",\n runFirst: \"Lancez le lab pour capturer son trafic.\",\n },\n link: {\n suspend: \"Suspendre le lien\",\n resume: \"R\u00E9tablir le lien\",\n suspendAll: \"Suspendre tous les liens\",\n resumeAll: \"R\u00E9tablir tous les liens\",\n cableSuspended: \"Lien suspendu : rien ne passe.\",\n lanSuspended: (ports) => (ports === 1 ? \"1 lien suspendu.\" : `${String(ports)} liens suspendus.`),\n runFirst: \"Lancez le lab pour suspendre ses liens.\",\n },\n export: \"Exporter\",\n engineDidntLoad: (error) => `Le moteur ne s'est pas charg\u00E9 : ${error}`,\n engineFailed: (error) => `Le moteur a \u00E9chou\u00E9 sur ce lab : ${error}`,\n toasts: {\n brokenLink: \"Ce lien de partage est ab\u00EEm\u00E9 : le lab n'a pas pu \u00EAtre lu.\",\n openedShared: (lab) => `Lab partag\u00E9 \u00AB ${lab} \u00BB ouvert. Annuler ram\u00E8ne le v\u00F4tre.`,\n linkCopied: \"Lien de partage copi\u00E9 : toute personne qui l'ouvre re\u00E7oit une copie de ce lab.\",\n copyPrompt: \"Copiez ce lien pour partager le lab :\",\n savedDevice: (device) => `\u00AB ${device} \u00BB enregistr\u00E9 : il est au bout de la barre d'outils.`,\n gns3Opened: (lab, machines, lans) =>\n `\u00AB ${lab} \u00BB ouvert depuis GNS3 : ${String(machines)} machine${machines > 1 ? \"s\" : \"\"}, ${String(lans)} LAN.`,\n undoBringsBack: \"Annuler ram\u00E8ne votre lab.\",\n gns3Unreadable: \"Ce projet GNS3 n'a pas pu \u00EAtre lu.\",\n },\n windows: {\n machine: \"Machine\",\n lan: (lan) => `LAN ${lan}`,\n cable: (a, b) => `C\u00E2ble ${a} \u2194 ${b}`,\n portOn: (machine) => `Port sur ${machine}`,\n cableNote: \"Chaque c\u00E2ble est son propre petit r\u00E9seau (un /29) ; ses deux extr\u00E9mit\u00E9s en re\u00E7oivent les deux premi\u00E8res adresses.\",\n removeCable: \"Supprimer le c\u00E2ble\",\n conditions: {\n title: \"Conditions du lien\",\n delay: \"Latence (ms, dans chaque sens)\",\n jitter: \"Gigue (ms)\",\n loss: \"Perte (%)\",\n rate: \"D\u00E9bit (Mbit/s)\",\n hint: \"Un lien lent ou qui perd des paquets, appliqu\u00E9 avec tc netem \u00E0 chaque extr\u00E9mit\u00E9. Vide : aucune.\",\n onLan: \"Ce c\u00E2ble place la machine sur le LAN : r\u00E9glez les conditions sur le LAN.\",\n onVlan: \"Les conditions se r\u00E8glent sur un c\u00E2ble ou un LAN simple, pas encore sur le VLAN d'un switch.\",\n },\n selected: (count) => `${String(count)} s\u00E9lectionn\u00E9s`,\n selection: (items, cables) =>\n `${String(items)} \u00E9l\u00E9ment${items > 1 ? \"s\" : \"\"}, ${String(cables)} c\u00E2ble${cables > 1 ? \"s\" : \"\"}. Faites glisser l'un d'eux pour les d\u00E9placer ensemble.`,\n deleteSelection: (count) => `Supprimer ${String(count)} (touche Suppr)`,\n close: \"Fermer\",\n },\n lab: {\n title: \"Lab\",\n containers: \"Conteneurs\",\n vms: \"VM\",\n lans: \"LAN\",\n cables: \"C\u00E2bles\",\n toFix: \"\u00C0 corriger\",\n valid: \"Le lab est valide : pr\u00EAt \u00E0 exporter.\",\n routing:\n \"Un routeur a besoin de sa propre configuration de transfert : chaque c\u00E2ble est son propre r\u00E9seau, et rien ne route entre eux \u00E0 votre place.\",\n },\n menu: {\n menu: \"Menu\",\n example: \"Charger le lab d'exemple\",\n vlanExample: \"Charger l'exemple VLAN\",\n gns3: \"Ouvrir un projet GNS3\u2026\",\n gns3File: \"Projet GNS3\",\n share: \"Copier un lien de partage\",\n fit: \"Ajuster \u00E0 l'\u00E9cran\",\n clear: \"Vider le canevas\",\n light: \"Th\u00E8me clair\",\n dark: \"Th\u00E8me sombre\",\n style: \"Style\",\n styles: { sketch: \"Croquis : dessin\u00E9 \u00E0 la main\", business: \"Business : net et sobre\" },\n language: \"Langue\",\n about: \"\u00C0 propos d'Isothrum\",\n blog: \"Blog\",\n },\n welcome: {\n menuHint: \"Exemple, th\u00E8me, langue\u2026\",\n toolbarHint: \"Choisissez un appareil, puis cliquez sur le canevas\",\n pitch: \"Dessinez un lab r\u00E9seau de conteneurs et de VM. T\u00E9l\u00E9chargez-le, pr\u00EAt \u00E0 lancer avec Docker, Vagrant ou Terraform.\",\n example: \"Charger le lab d'exemple\",\n how: \"Comment \u00E7a marche\",\n },\n inspector: {\n name: \"Nom\",\n runsAs: \"Ex\u00E9cut\u00E9 comme\",\n automaticRouter: \"Routeur automatique\",\n container: \"Conteneur (Docker)\",\n vm: \"Machine virtuelle\",\n routerNote:\n \"Rien \u00E0 configurer : les r\u00E9seaux auxquels il est reli\u00E9 (ses LAN, VLAN et c\u00E2bles) communiquent par le routeur d'Isoloom. Pour configurer le routage vous-m\u00EAme, ex\u00E9cutez-le comme conteneur (FRR) ou comme VM.\",\n image: \"Image\",\n keepRunning: \"Le garder allum\u00E9\",\n applianceNote: \"Cisco IOL tourne depuis votre propre image : construisez-la avec\",\n ciscoOs: \"OS Cisco\",\n needsKvm: \"Tourne dans QEMU : l\u2019h\u00F4te Docker doit avoir /dev/kvm.\",\n dynamipsFirmware: (name: string) => `Placez votre image IOS de 7200 dans le t\u00E9l\u00E9chargement : images/${name}.bin.`,\n iosConfig: \"Configuration IOS\",\n iosConfigHint: \"Ajout\u00E9e \u00E0 celle qu\u2019Isothrum \u00E9crit (nom, admin/admin en SSH, l\u2019adresse de chaque interface). Appliqu\u00E9e au premier d\u00E9marrage.\",\n keepRunningHint: \"Pour une image sans service propre (Alpine, Ubuntu, Kali\u2026) : une machine depuis laquelle travailler.\",\n os: \"Syst\u00E8me d'exploitation\",\n provision: \"\u00C9tapes de provisionnement (une par ligne)\",\n ports: \"Ports de service\",\n access: \"L'utilisateur arrive sur cette machine\",\n cables: \"C\u00E2bles\",\n noCables: \"Aucun pour l'instant : tirez depuis l'un de ses points vers une autre machine.\",\n saveTitle: \"Garder la configuration de cette machine comme appareil dans la barre d'outils, pour la placer \u00E0 nouveau\",\n save: \"Enregistrer comme appareil\",\n remove: \"Supprimer la machine\",\n },\n canvas: {\n imageShort: \"Image\",\n hosts: (n) => (n === 1 ? \"1 h\u00F4te\" : `${String(n)} h\u00F4tes`),\n roles: { router: \"Routeur\", firewall: \"Pare-feu\", workstation: \"Poste de travail\", server: \"Serveur\", desktop: \"Bureau\", host: \"H\u00F4te\" },\n switchModel: (ports) => `Switch \u00B7 ${String(ports)} ports`,\n live: {\n up: \"En marche\",\n starting: \"D\u00E9marrage\",\n unhealthy: \"En mauvaise sant\u00E9\",\n down: \"Arr\u00EAt\u00E9e\",\n portUp: \"Lien actif\",\n portDown: \"Lien coup\u00E9\",\n portUnknown: \"Inconnu (arr\u00EAt\u00E9e, ou le port appartient \u00E0 l\u2019OS de l\u2019\u00E9quipement)\",\n lanPorts: (up, total) => `${String(up)} ports sur ${String(total)} actifs sur ce LAN`,\n cable: { up: \"Le trafic passe\", cut: \"Suspendu : rien ne passe\", down: \"Coup\u00E9 : une extr\u00E9mit\u00E9 est arr\u00EAt\u00E9e ou son port est coup\u00E9\" },\n cableShort: { cut: \"suspendu\", down: \"coup\u00E9\" },\n },\n editTitle: (what) => `${what} : double-cliquez pour modifier`,\n unnamed: \"sans nom\",\n machineName: \"Nom de la machine\",\n vm: \"VM\",\n automatic: \"Automatique\",\n container: \"Conteneur\",\n access: \"acc\u00E8s\",\n addressTitle: (network, fixed) => `${network} : double-cliquez pour fixer cette adresse${fixed ? \" (fix\u00E9e)\" : \"\"}`,\n fixed: \"fix\u00E9e\",\n addressOn: (network) => `Adresse sur ${network}`,\n lanName: \"Nom du LAN\",\n addressBlock: \"Plage d'adresses\",\n internetOnTitle: \"Acc\u00E8de \u00E0 internet (cliquez pour le couper)\",\n internetOffTitle: \"Pas d'internet (cliquez pour l'autoriser)\",\n internetOn: \"Acc\u00E8s \u00E0 internet : activ\u00E9\",\n internetOff: \"Acc\u00E8s \u00E0 internet : d\u00E9sactiv\u00E9\",\n showAreaTitle: \"Afficher la zone du LAN\",\n hideAreaTitle: \"Masquer la zone du LAN (le LAN reste : seul son rectangle dispara\u00EEt)\",\n showArea: \"Afficher la zone\",\n hideArea: \"Masquer la zone\",\n switchName: \"Nom du switch\",\n port: (n) => `Port ${String(n)}`,\n trunkPort: \"Port trunk\",\n trunkCarries: (vlans) => `trunk, transporte ${vlans}`,\n noVlan: \"aucun VLAN\",\n clickToChange: \"(cliquez pour changer)\",\n vlanNumber: \"Num\u00E9ro de VLAN\",\n vlanBlock: \"Plage d'adresses du VLAN\",\n remove: (what) => `Supprimer ${what}`,\n routerName: \"Nom du routeur\",\n portFree: (port) => `${port} : libre`,\n textOnly: \"Texte seul\",\n box: \"Cadre\",\n ellipse: \"Ellipse\",\n colors: { yellow: \"jaune\", red: \"rouge\", blue: \"bleu\", green: \"vert\", violet: \"violet\" },\n color: (color) => `Couleur ${color}`,\n write: \"Double-cliquez pour \u00E9crire\",\n note: \"Note\",\n noteName: \"note\",\n },\n exportPanel: {\n copy: \"Copier\",\n copied: \"Copi\u00E9\",\n labName: \"Nom du lab (celui du zip)\",\n fixFirst: \"Corrigez le lab avant d'exporter\",\n download: (lab) => `T\u00E9l\u00E9charger ${lab}.zip`,\n onlySpec: \"Seulement isoloom.yml\",\n where: \"O\u00F9 le lancer\",\n whereIntro: \"Le zip contient un dossier par cible. D\u00E9compressez-le, puis lancez celle qui vous convient.\",\n mixed:\n \"Ce lab m\u00E9lange conteneurs et VM : il tourne donc avec Vagrant. Passez tout en conteneurs (Docker, Kubernetes, une VM cloud) ou tout en VM (Proxmox, VM cloud) pour d\u00E9bloquer d'autres cibles.\",\n install: \"Isoloom lance n'importe laquelle en une commande. Installez-le une fois :\",\n files: (count) => `${String(count)} fichier${count > 1 ? \"s\" : \"\"}`,\n downloadOnly: (target) => `T\u00E9l\u00E9charger seulement ${target} (avec isoloom.yml)`,\n downloadTarget: (target) => `T\u00E9l\u00E9charger ${target}`,\n withIsoloom: \"Avec Isoloom (arr\u00EAtez-le avec isoloom down)\",\n withTool: \"Ou directement avec l'outil\",\n run: \"Lancer\",\n specIntro: \"Le lab en un seul fichier lisible, \u00E0 garder dans Git ou \u00E0 modifier \u00E0 la main.\",\n showSpec: \"Afficher le fichier\",\n hideSpec: \"Masquer le fichier\",\n containersAndVms: \"conteneurs et VM\",\n dockerOnOneVm: \"Docker sur une VM\",\n oneVmPerMachine: \"une VM par machine\",\n },\n issues: {\n vlanBlocks: (vlan, block, other, sw) => `${vlan} est en ${block} sur un switch et en ${other} sur ${sw}.`,\n areaBlock: (lan, block, switches) => `La zone ${lan} est en ${block}, ses switchs disent ${switches}.`,\n noName: { machine: \"Une machine n'a pas de nom.\", lan: \"Un LAN n'a pas de nom.\", switch: \"Un switch n'a pas de nom.\" },\n sameName: {\n machine: (name) => `Deux machines s'appellent \u00AB ${name} \u00BB.`,\n lan: (name) => `Deux LAN s'appellent \u00AB ${name} \u00BB.`,\n switch: (name) => `Deux switchs s'appellent \u00AB ${name} \u00BB.`,\n },\n badPort: (machine, entry) => `\u00AB ${entry} \u00BB dans les ports de ${machine} n'est pas un port : un nombre de 1 \u00E0 65535, puis /udp, /http, /https ou /tls s'il n'est pas en TCP simple.`,\n },\n gns3: {\n notGns3: \"Ce n'est pas un projet GNS3 : ouvrez le fichier .gns3 (dans un .gns3project, c'est celui \u00E0 la racine).\",\n noTopology: \"Ce fichier ne contient aucune topologie GNS3.\",\n cisco: (node, kind) =>\n `${node} : un routeur Cisco ${kind} est devenu un routeur automatique ; sa configuration IOS n'est pas reprise.`,\n firewall: (node) => `${node} : un pare-feu est devenu un routeur automatique (ses r\u00E8gles ne sont pas reprises).`,\n noEquivalent: (node, type) => `${node} : le n\u0153ud \u00AB ${type} \u00BB de GNS3 n'a pas d'\u00E9quivalent ; ignor\u00E9.`,\n noNodes: \"Le projet n'a aucun n\u0153ud.\",\n },\n account: {\n signIn: \"Se connecter avec Cyber Auth\",\n signOut: \"Se d\u00E9connecter\",\n signedInAs: (name: string) => `Connect\u00E9 : ${name}`,\n },\n projects: {\n save: \"Enregistrer dans mes projets\",\n saveAs: \"Enregistrer comme nouveau projet\u2026\",\n openList: \"Ouvrir un projet\u2026\",\n saveAsPrompt: \"Nom du nouveau projet :\",\n windowTitle: \"Mes projets\",\n loading: \"Chargement de vos projets\u2026\",\n none: \"Aucun projet pour l'instant : enregistrez ce lab pour en cr\u00E9er un.\",\n open: \"ouvert\",\n openButton: \"Ouvrir\",\n delete: (name: string) => `Supprimer ${name}`,\n confirmDelete: (name: string) => `Supprimer le projet \u00AB ${name} \u00BB et son historique ?`,\n failed: (error: string) => `Impossible de charger vos projets : ${error}`,\n history: (name: string) => `Versions pr\u00E9c\u00E9dentes de ${name}`,\n noVersions: \"Pas encore de version pr\u00E9c\u00E9dente.\",\n restore: \"Ouvrir\",\n historyHint: \"Ouvrir une version la place sur le canevas : Annuler ram\u00E8ne la version actuelle, et le prochain enregistrement la conserve.\",\n opened: (name: string) => `\u00AB ${name} \u00BB ouvert. Annuler ram\u00E8ne le lab qui \u00E9tait l\u00E0.`,\n status: {\n idle: (name: string) => `Projet \u00AB ${name} \u00BB`,\n saving: (name: string) => `Enregistrement de \u00AB ${name} \u00BB\u2026`,\n saved: (name: string) => `Enregistr\u00E9 dans \u00AB ${name} \u00BB`,\n error: (name: string) => `\u00C9chec de l'enregistrement de \u00AB ${name} \u00BB`,\n },\n },\n machineRun: {\n display: \"\u00C9cran (VNC)\",\n displayTitle: \"L\u2019\u00E9cran de la machine : son serveur VNC, ou l\u2019affichage de la VM\",\n displayOpened: (what) => `Ouvert : ${what}`,\n consoleHint: \"Double-cliquez sur une machine pour sa console ; clic droit pour son \u00E9cran et le reste.\",\n runFirst: \"Lancez le lab pour ouvrir ses consoles.\",\n running: \"En marche dans le lab.\",\n stopped: \"Arr\u00EAt\u00E9e (le reste du lab tourne).\",\n unknown: \"Absente du lab en marche : relancez le lab pour l\u2019ajouter.\",\n console: \"Console\",\n restart: \"Red\u00E9marrer\",\n stop: \"Arr\u00EAter\",\n start: \"D\u00E9marrer\",\n snapshots: \"Instantan\u00E9s\",\n takeSnapshot: \"En prendre un\",\n snapshotHint: \"Enregistrer la machine telle qu\u2019elle est (ses fichiers, la configuration enregistr\u00E9e d\u2019un routeur) ; pas ses volumes\",\n snapshotPrompt: \"Nom de l\u2019instantan\u00E9 (facultatif) :\",\n noSnapshots: \"Aucun pour l\u2019instant.\",\n restore: \"Restaurer\",\n inUse: \"utilis\u00E9\",\n ownImage: \"Revenir \u00E0 son image\",\n deleteSnapshot: (label: string) => `Supprimer l\u2019instantan\u00E9 ${label}`,\n },\n update: {\n available: (version: string) => `Isothrum ${version} est disponible.`,\n restart: \"Red\u00E9marrer pour mettre \u00E0 jour\",\n installing: \"Mise \u00E0 jour\u2026\",\n later: \"Plus tard\",\n },\n};\n", "import { hasLocale, type Locale } from \"@/lib/i18n\";\nimport { de } from \"./de\";\nimport { en, type EditorText } from \"./en\";\nimport { es } from \"./es\";\nimport { fr } from \"./fr\";\n\nexport type { EditorText };\n\n/**\n * The editor's own words in each language. They live here, typed, rather than in the site's\n * JSON dictionaries: the editor only renders in the browser, and many of its strings take\n * values (names, counts), which functions say better than templates.\n */\nconst TEXTS: Record<Locale, EditorText> = { en, fr, es, de };\n\nexport function editorText(lang: string): EditorText {\n return hasLocale(lang) ? TEXTS[lang] : en;\n}\n\n/** English: the source the other languages follow. */\nexport const defaultText = en;\n", "\"use client\";\n\nimport { createContext, useContext, type ReactNode } from \"react\";\n\n/**\n * The accounts surface the editor uses, injected by the host (the website wires Better Auth; the\n * desktop app and the standalone editor leave it out and run with `accounts={false}`). Keeping it\n * an injected port is what lets this package stay free of any auth implementation.\n */\nexport interface AuthSessionUser {\n name?: string | null;\n email: string;\n}\n\nexport interface AuthSession {\n user: AuthSessionUser;\n}\n\nexport interface AuthClient {\n /** React hook: the current session (or `null`), and whether it is still loading. */\n useSession: () => { data: AuthSession | null; isPending: boolean };\n signOut: () => Promise<unknown> | void;\n signIn: {\n oauth2: (options: { providerId: string; callbackURL: string; errorCallbackURL: string }) => Promise<unknown> | void;\n };\n}\n\nconst AuthClientContext = createContext<AuthClient | null>(null);\n\n/** Provides the host's auth client to the editor. Omit it (or pass `null`) to run without accounts. */\nexport function AuthClientProvider({ client, children }: { client: AuthClient | null; children: ReactNode }) {\n return <AuthClientContext.Provider value={client}>{children}</AuthClientContext.Provider>;\n}\n\n/**\n * The injected auth client. It is present only where accounts are enabled; the editor reads it\n * solely inside `accounts`-gated UI, so a missing client there is a wiring error, not a normal path.\n */\nexport function useAuthClient(): AuthClient {\n const client = useContext(AuthClientContext);\n if (!client) throw new Error(\"Accounts are enabled but no AuthClient was provided to the editor.\");\n return client;\n}\n", "\"use client\";\n\nimport { createContext, useContext, type ReactNode } from \"react\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * The product mark the empty canvas shows. It is a port so a host can inject its own mark while the\n * package stays brand-neutral; the default below is the Isothrum mark (the geometry is shared with\n * the website's favicon and OG images), themed by the host's `--primary` tokens.\n */\nexport interface BrandMarkProps {\n className?: string;\n}\n\nexport type BrandMark = (props: BrandMarkProps) => ReactNode;\n\nconst logoMark = {\n viewBox: \"0 0 32 32\",\n radius: 9,\n fill: \"M7.2 8.1 14.6 7.8 14.4 15.3 7 15.5Z M17.6 16.6 25.1 16.3 24.9 24 17.4 23.8Z\",\n stroke: \"M14.6 11.6C16.8 11.3 19.4 11.9 21.2 11.7 21.5 13.2 21.1 14.8 21.3 16.4\",\n strokeWidth: 2.25,\n} as const;\n\n/** The default Isothrum mark, themed by `--primary`/`--primary-foreground`. */\nexport function DefaultBrandMark({ className }: BrandMarkProps) {\n return (\n <svg viewBox={logoMark.viewBox} aria-hidden className={cn(\"size-7 shrink-0\", className)}>\n <rect width=\"32\" height=\"32\" rx={logoMark.radius} className=\"fill-primary\" />\n <path d={logoMark.fill} strokeWidth={1} strokeLinejoin=\"round\" className=\"fill-primary-foreground stroke-primary-foreground\" />\n <path d={logoMark.stroke} fill=\"none\" strokeWidth={logoMark.strokeWidth} strokeLinecap=\"round\" strokeLinejoin=\"round\" className=\"stroke-primary-foreground\" />\n </svg>\n );\n}\n\nconst BrandMarkContext = createContext<BrandMark>(DefaultBrandMark);\n\n/** Lets a host replace the editor's product mark. Omit it to keep the default Isothrum mark. */\nexport function BrandMarkProvider({ mark, children }: { mark: BrandMark; children: ReactNode }) {\n return <BrandMarkContext.Provider value={mark}>{children}</BrandMarkContext.Provider>;\n}\n\n/** The product mark in use (the injected one, or the default). */\nexport function useBrandMark(): BrandMark {\n return useContext(BrandMarkContext);\n}\n", "import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n", "\"use client\";\n\nimport { useEffect, type ReactNode } from \"react\";\nimport { Monitor, Play, Plug, Radio, RotateCw, Square, SquareTerminal, Unplug, type LucideIcon } from \"lucide-react\";\nimport type { EditorModel } from \"./hooks/use-editor\";\nimport type { LinkMenuAt, MachineMenuAt } from \"./hooks/use-context-menus\";\nimport type { LinkAction, MachineAction } from \"./hooks/use-machine-actions\";\nimport { useText } from \"./text\";\n\n/** A menu at the pointer (a right-click): Escape or a click elsewhere closes it. */\nfunction ContextMenu({ at, title, onClose, children }: { at: { x: number; y: number }; title: string; onClose: () => void; children: ReactNode }) {\n useEffect(() => {\n const esc = (e: globalThis.KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n window.addEventListener(\"keydown\", esc);\n return () => {\n window.removeEventListener(\"keydown\", esc);\n };\n }, [onClose]);\n return (\n <>\n <div\n className=\"fixed inset-0 z-40\"\n onClick={onClose}\n onContextMenu={(e) => {\n e.preventDefault();\n onClose();\n }}\n />\n <div\n role=\"menu\"\n aria-label={title}\n style={{ left: Math.min(at.x, window.innerWidth - 248), top: Math.min(at.y, window.innerHeight - 260) }}\n className=\"fixed z-50 w-60 rounded-lg border bg-popover p-1 text-popover-foreground shadow-[0_8px_30px_-8px_rgb(0_0_0/0.25)]\"\n onClick={onClose}\n >\n <p className=\"truncate px-2 pt-1 pb-1.5 font-mono text-xs text-muted-foreground\">{title}</p>\n {children}\n </div>\n </>\n );\n}\n\nfunction MenuItem({ icon: Icon, label, enabled = true, onClick }: { icon: LucideIcon; label: string; enabled?: boolean; onClick: () => void }) {\n return (\n <button\n type=\"button\"\n role=\"menuitem\"\n disabled={!enabled}\n onClick={onClick}\n className=\"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm hover:bg-muted disabled:pointer-events-none disabled:opacity-40\"\n >\n <Icon className=\"size-4 text-muted-foreground\" aria-hidden /> {label}\n </button>\n );\n}\n\nconst Divider = () => <div className=\"my-1 h-px bg-border\" />;\n\n/** Desktop only: a machine's menu, on a right-click, as in GNS3. */\nfunction MachineMenu({ at, running, state, onClose, onConsole, onDisplay, onAction }: { at: MachineMenuAt; running: boolean; state: string | undefined; onClose: () => void; onConsole: () => void; onDisplay: () => void; onAction: (action: MachineAction) => void }) {\n const t = useText().machineRun;\n const up = running && state === \"running\";\n return (\n <ContextMenu at={at} title={at.machine} onClose={onClose}>\n <MenuItem icon={SquareTerminal} label={t.console} enabled={up} onClick={onConsole} />\n <MenuItem icon={Monitor} label={t.display} enabled={up} onClick={onDisplay} />\n <Divider />\n {up ? (\n <>\n <MenuItem icon={RotateCw} label={t.restart} onClick={() => { onAction(\"restart\"); }} />\n <MenuItem icon={Square} label={t.stop} onClick={() => { onAction(\"stop\"); }} />\n </>\n ) : (\n <MenuItem icon={Play} label={t.start} enabled={running && !!state} onClick={() => { onAction(\"start\"); }} />\n )}\n {!running && <p className=\"px-2 pt-1 pb-1 text-xs text-muted-foreground\">{t.runFirst}</p>}\n </ContextMenu>\n );\n}\n\n/**\n * Desktop only: a cable's or a LAN's menu, on a right-click, as in GNS3: capture its traffic,\n * suspend or resume it (a cable's ends, or every link of a LAN).\n */\nfunction LinkMenu({ at, running, capturing, suspended, onClose, onCapture, onLink }: { at: LinkMenuAt; running: boolean; capturing: boolean; suspended: boolean; onClose: () => void; onCapture: () => void; onLink: (action: LinkAction) => void }) {\n const t = useText();\n const ends = at.machines;\n const all = !ends;\n return (\n <ContextMenu at={at} title={at.title} onClose={onClose}>\n {capturing ? <MenuItem icon={Square} label={t.capture.stop} onClick={onCapture} /> : <MenuItem icon={Radio} label={t.capture.start} enabled={running} onClick={onCapture} />}\n {(!ends || ends.length > 0) && (\n <>\n <Divider />\n {suspended ? (\n <MenuItem icon={Plug} label={all ? t.link.resumeAll : t.link.resume} enabled={running} onClick={() => { onLink(\"resume\"); }} />\n ) : (\n <MenuItem icon={Unplug} label={all ? t.link.suspendAll : t.link.suspend} enabled={running} onClick={() => { onLink(\"suspend\"); }} />\n )}\n </>\n )}\n {!running && <p className=\"px-2 pt-1 pb-1 text-xs text-muted-foreground\">{t.capture.runFirst}</p>}\n </ContextMenu>\n );\n}\n\n/** The right-click menus of the running lab (desktop app only). */\nexport function RunningLabMenus({ e }: { e: EditorModel }) {\n const { invoke, desk } = e;\n const { machineMenu, linkMenu, setMachineMenu, setLinkMenu } = desk.menus;\n const running = desk.state.run === \"running\";\n const { captures, capture, stopCapture } = desk.captures;\n if (!invoke) return null;\n return (\n <>\n {machineMenu && (\n <MachineMenu\n at={machineMenu}\n running={running}\n state={desk.live.machineStates[machineMenu.machine]}\n onClose={() => { setMachineMenu(null); }}\n onConsole={() => void desk.actions.machineConsole(machineMenu.machine)}\n onDisplay={() => void desk.actions.machineDisplay(machineMenu.machine)}\n onAction={(action) => void desk.actions.machineAct(machineMenu.machine, action)}\n />\n )}\n {linkMenu && (\n <LinkMenu\n at={linkMenu}\n running={running}\n capturing={linkMenu.network in captures}\n suspended={desk.live.links.some((l) => l.network === linkMenu.network && (!linkMenu.machines || linkMenu.machines.includes(l.machine)))}\n onClose={() => { setLinkMenu(null); }}\n onCapture={() => void (linkMenu.network in captures ? stopCapture(linkMenu.network) : capture(linkMenu.network))}\n onLink={(action) => void desk.actions.linkAct(linkMenu.network, linkMenu.machines, action)}\n />\n )}\n </>\n );\n}\n", "import { createContext, useContext } from \"react\";\nimport { defaultText, type EditorText } from \"@/lib/tool/text\";\n\n/** The editor's words, set once by the editor from the page's language; English outside it. */\nexport const EditorTextContext = createContext<EditorText>(defaultText);\n\nexport function useText(): EditorText {\n return useContext(EditorTextContext);\n}\n", "\"use client\";\n\nimport { useEffect } from \"react\";\nimport { useTheme } from \"next-themes\";\nimport { Check, CopyPlus, FileUp, FolderOpen, Info, Languages, LayoutTemplate, Link2, LogIn, LogOut, Maximize, Menu, Moon, Newspaper, Palette, Save, Sun, Trash2 } from \"lucide-react\";\nimport { useAuthClient } from \"@/lib/auth\";\nimport { LOCALES, localeNames } from \"@/lib/i18n\";\nimport { DESIGNS, type Design } from \"@/lib/tool/model\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\";\nimport { useText } from \"./text\";\n\n/** Signed in: saving to and opening from the user's projects. */\ninterface ProjectActions {\n onSave: () => void;\n onSaveAs: () => void;\n onOpen: () => void;\n}\n\ninterface EditorMenuProps {\n lang: string;\n onExample: () => void;\n onVlanExample: () => void;\n onShare: () => void;\n onImportGns3: () => void;\n design: Design;\n onDesign: (d: Design) => void;\n accounts: boolean;\n projects: ProjectActions | null;\n onClear: () => void;\n onFit: () => void;\n canClear: boolean;\n}\n\n/** Reports whether someone is signed in (mounted only where accounts exist). */\nexport function SessionWatch({ onChange }: { onChange: (signedIn: boolean) => void }) {\n const authClient = useAuthClient();\n const { data } = authClient.useSession();\n useEffect(() => {\n onChange(!!data);\n }, [data, onChange]);\n return null;\n}\n\n/** Signed in through Cyber Auth, or the way to sign in (the editor works without an account). */\nfunction AccountItems() {\n const t = useText().account;\n const authClient = useAuthClient();\n const { data, isPending } = authClient.useSession();\n if (isPending) return null;\n const back = window.location.pathname;\n return (\n <>\n <DropdownMenuSeparator />\n {data ? (\n <DropdownMenuGroup>\n <DropdownMenuLabel className=\"font-normal text-muted-foreground\">{t.signedInAs(data.user.name || data.user.email)}</DropdownMenuLabel>\n <DropdownMenuItem onClick={() => void authClient.signOut()}>\n <LogOut /> {t.signOut}\n </DropdownMenuItem>\n </DropdownMenuGroup>\n ) : (\n <DropdownMenuItem onClick={() => void authClient.signIn.oauth2({ providerId: \"cyber-auth\", callbackURL: back, errorCallbackURL: back })}>\n <LogIn /> {t.signIn}\n </DropdownMenuItem>\n )}\n </>\n );\n}\n\n/** Saving to and opening from the user's projects. */\nfunction ProjectItems({ projects }: { projects: ProjectActions }) {\n const tp = useText().projects;\n return (\n <>\n <DropdownMenuItem onClick={projects.onSave}>\n <Save /> {tp.save}\n <DropdownMenuShortcut>\u2318S</DropdownMenuShortcut>\n </DropdownMenuItem>\n <DropdownMenuItem onClick={projects.onSaveAs}>\n <CopyPlus /> {tp.saveAs}\n </DropdownMenuItem>\n <DropdownMenuItem onClick={projects.onOpen}>\n <FolderOpen /> {tp.openList}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n </>\n );\n}\n\n/** The light or dark theme, and the canvas's look. */\nfunction LookItems({ design, onDesign }: Pick<EditorMenuProps, \"design\" | \"onDesign\">) {\n const t = useText().menu;\n const { resolvedTheme, setTheme } = useTheme();\n const dark = resolvedTheme === \"dark\";\n return (\n <>\n <DropdownMenuItem onClick={() => { setTheme(dark ? \"light\" : \"dark\"); }}>\n {dark ? <Sun /> : <Moon />} {dark ? t.light : t.dark}\n </DropdownMenuItem>\n <DropdownMenuSub>\n <DropdownMenuSubTrigger>\n <Palette /> {t.style}\n </DropdownMenuSubTrigger>\n <DropdownMenuSubContent>\n {DESIGNS.map((d) => (\n <DropdownMenuItem key={d} onClick={() => { onDesign(d); }}>\n {d === design ? <Check /> : <span className=\"size-4\" />} {t.styles[d]}\n </DropdownMenuItem>\n ))}\n </DropdownMenuSubContent>\n </DropdownMenuSub>\n </>\n );\n}\n\n/** The editor in another language, and the site's pages about it. */\nfunction SiteItems({ lang, accounts }: Pick<EditorMenuProps, \"lang\" | \"accounts\">) {\n const t = useText().menu;\n return (\n <>\n <DropdownMenuSub>\n <DropdownMenuSubTrigger>\n <Languages /> {t.language}\n </DropdownMenuSubTrigger>\n <DropdownMenuSubContent>\n {LOCALES.map((l) => (\n <DropdownMenuItem key={l} disabled={l === lang} render={<a href={`/${l}`} />}>\n {localeNames[l]}\n </DropdownMenuItem>\n ))}\n </DropdownMenuSubContent>\n </DropdownMenuSub>\n {accounts && <AccountItems />}\n <DropdownMenuSeparator />\n <DropdownMenuItem render={<a href={`/${lang}/about`} />}>\n <Info /> {t.about}\n </DropdownMenuItem>\n <DropdownMenuItem render={<a href={`/${lang}/blog`} />}>\n <Newspaper /> {t.blog}\n </DropdownMenuItem>\n </>\n );\n}\n\n/** The editor's menu (top left): examples, projects, files, the look, the language. */\nexport function EditorMenu(p: EditorMenuProps) {\n const t = useText().menu;\n return (\n <DropdownMenu>\n <DropdownMenuTrigger aria-label={t.menu} className=\"grid size-9 place-items-center rounded-lg border bg-popover shadow-sm hover:bg-muted\">\n <Menu className=\"size-4\" />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-56\">\n <DropdownMenuItem onClick={p.onExample}>\n <LayoutTemplate /> {t.example}\n </DropdownMenuItem>\n <DropdownMenuItem onClick={p.onVlanExample}>\n <LayoutTemplate /> {t.vlanExample}\n </DropdownMenuItem>\n {p.projects && <ProjectItems projects={p.projects} />}\n <DropdownMenuItem onClick={p.onImportGns3}>\n <FileUp /> {t.gns3}\n </DropdownMenuItem>\n <DropdownMenuItem onClick={p.onShare} disabled={!p.canClear}>\n <Link2 /> {t.share}\n </DropdownMenuItem>\n <DropdownMenuItem onClick={p.onFit}>\n <Maximize /> {t.fit}\n </DropdownMenuItem>\n <DropdownMenuItem onClick={p.onClear} disabled={!p.canClear}>\n <Trash2 /> {t.clear}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <LookItems design={p.design} onDesign={p.onDesign} />\n <SiteItems lang={p.lang} accounts={p.accounts} />\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n", "import type { Edge, Node, XYPosition } from \"@xyflow/react\";\n\n/**\n * The lab as drawn on the canvas: machines, LANs, switches and notes are nodes, cables are edges\n * between two ports. `toTopology` translates it into the topology JSON the engine reads\n * (`isothrum_compiler::Topology`), which it compiles to Isoloom's isoloom.yml.\n */\n\nexport type IconId = \"container\" | \"server\" | \"router\" | \"shield\" | \"monitor\" | \"laptop\";\n\n/** The Cisco OSes a container node can be (Isoloom's `app.appliance`). */\nexport type Appliance = \"cisco-iol\" | \"cisco-iol-l2\" | \"cisco-vios\" | \"cisco-vios-l2\" | \"cisco-csr1000v\" | \"cisco-c8000v\" | \"cisco-dynamips\";\n\n/** Each Cisco OS: its usual vrnetlab image (none for Dynamips: Isoloom builds the emulator). */\nexport const APPLIANCES: { id: Appliance; label: string; image: string; switch?: boolean; kvm?: boolean }[] = [\n { id: \"cisco-iol\", label: \"IOL (IOS on Linux)\", image: \"vrnetlab/cisco_iol:17.12.01\" },\n { id: \"cisco-iol-l2\", label: \"IOL-L2 (switch)\", image: \"vrnetlab/cisco_iol:L2-17.12.01\", switch: true },\n { id: \"cisco-vios\", label: \"IOSv\", image: \"vrnetlab/cisco_vios:15.9.3M6\", kvm: true },\n { id: \"cisco-vios-l2\", label: \"IOSvL2 (switch)\", image: \"vrnetlab/cisco_viosl2:15.2\", switch: true, kvm: true },\n { id: \"cisco-csr1000v\", label: \"CSR1000v (IOS XE)\", image: \"vrnetlab/cisco_csr1000v:17.03.08\", kvm: true },\n { id: \"cisco-c8000v\", label: \"Catalyst 8000v (IOS XE)\", image: \"vrnetlab/cisco_c8000v:17.15.01a\", kvm: true },\n { id: \"cisco-dynamips\", label: \"Dynamips 7200 (classic IOS)\", image: \"\" },\n];\n\n/** The OS's name for the `k`th data interface (from 1), as Isoloom numbers them. */\nexport function applianceInterface(kind: Appliance, k: number): string {\n switch (kind) {\n case \"cisco-iol\":\n case \"cisco-iol-l2\":\n return `Ethernet${String(Math.floor(k / 4))}/${String(k % 4)}`;\n case \"cisco-vios\":\n case \"cisco-vios-l2\":\n return `GigabitEthernet0/${String(k)}`;\n case \"cisco-csr1000v\":\n case \"cisco-c8000v\":\n return `GigabitEthernet${String(k + 1)}`;\n case \"cisco-dynamips\":\n return k === 1 ? \"FastEthernet0/0\" : `FastEthernet${String(Math.floor(k / 2))}/${String(k % 2)}`;\n }\n}\n\nexport type MachineData = {\n name: string;\n /** \"router\": an automatic router, not a machine (its networks reach each other). */\n kind: \"container\" | \"vm\" | \"router\";\n icon: IconId;\n /** Container image (`kind: container`): Isoloom's `app.image`. */\n image: string;\n /** The OS, as Isoloom writes it (`debian@12`, see `OS_CHOICES`) (`kind: vm`): Isoloom's `os`. */\n os: string;\n /** Provisioning steps, one per line (`kind: vm`): Isoloom's `app.steps`. */\n provision: string;\n /** Service ports, comma-separated, each a port and what it speaks when it isn't TCP (`80, 53/udp`): see `readPorts`. */\n ports: string;\n /** The machine the user lands on. */\n access: boolean;\n /**\n * A container with no service of its own (a stock Linux image), kept running idle as a\n * machine to work from. Unset: guessed from the image (see `idleByDefault`).\n */\n idle?: boolean;\n /** A network OS in its container, wired as its image expects (Cisco IOL, built with vrnetlab). */\n appliance?: Appliance;\n /** The appliance's own configuration (IOS commands), added to the one Isoloom generates. */\n config?: string;\n /** Addresses fixed by hand: LAN name -> last octet. Others take the next free one. */\n pins?: Record<string, number>;\n};\n\n/** Stock Linux images: a shell that exits at once, so they need to be kept running idle. */\nconst STOCK_IMAGES = [\"alpine\", \"ubuntu\", \"debian\", \"kali-rolling\", \"fedora\", \"rockylinux\", \"almalinux\", \"centos\", \"busybox\", \"archlinux\", \"netshoot\"];\n\n/** An image's name: its last path segment, without the tag, in lowercase. */\nexport function imageName(image: string): string {\n return image.trim().split(\":\")[0].split(\"/\").pop()?.toLowerCase() ?? \"\";\n}\n\nexport function idleByDefault(image: string): boolean {\n return STOCK_IMAGES.includes(imageName(image));\n}\n\n/** How a cable or a LAN behaves, as a slow or lossy link: one-way delay and its jitter (ms),\n * loss (%), bandwidth (Mbit/s). Isoloom applies it with `tc netem` (its `tc`). */\nexport type LinkConditions = {\n delay?: number;\n jitter?: number;\n loss?: number;\n rate?: number;\n};\n\n/** The two ends of a cable: `aPort` on the source machine, `bPort` on the target. */\nexport type CableData = {\n aPort: string;\n bPort: string;\n /** How the cable behaves (between two machines; a cable to a LAN takes the LAN's). */\n tc?: LinkConditions;\n /** Drawing only, worked out from what the cable is plugged into (never saved). */\n color?: string;\n};\n\n/** A LAN (or VLAN) drawn as an area: machines inside it are on it. */\nexport type LanData = {\n name: string;\n cidr: string;\n internet: boolean;\n /** How the LAN behaves (not on a switch's VLAN yet). */\n tc?: LinkConditions;\n /** Only its label is drawn: the LAN, its machines and their addresses are unchanged. */\n hidden?: boolean;\n};\n\n/** A VLAN on a switch: `vlan<id>`, with its block. VLANs are lab-wide: `vlan10` is the same\n * network on every switch, and a LAN area named `vlan10` is that VLAN too. */\ntype Vlan = {\n id: number;\n cidr: string;\n};\n\n/** A switch port: a VLAN (access), \"trunk\" (every VLAN of the switch), or nothing. */\nexport type PortMode = number | \"trunk\" | null;\n\n/**\n * A switch: access ports, each in a VLAN (or none), and one trunk port that carries every VLAN\n * of the switch. Not a machine: it is the network fabric, so it never appears in isoloom.yml;\n * its VLANs do, as networks, and a machine cabled to a port joins the port's VLAN.\n */\ntype SwitchData = {\n name: string;\n vlans: Vlan[];\n ports: PortMode[];\n};\n\n/** A note on the canvas: text, a box or an ellipse. Drawing only: never in isoloom.yml. */\nexport type NoteShape = \"text\" | \"rect\" | \"ellipse\";\nexport const NOTE_COLORS = [\"yellow\", \"red\", \"blue\", \"green\", \"violet\"] as const;\ntype NoteData = {\n text: string;\n shape: NoteShape;\n color: (typeof NOTE_COLORS)[number];\n};\n\nexport type MachineNode = Node<MachineData, \"machine\">;\nexport type LanNode = Node<LanData, \"lan\">;\nexport type SwitchNode = Node<SwitchData, \"switch\">;\nexport type NoteNode = Node<NoteData, \"note\">;\nexport type LabNode = MachineNode | LanNode | SwitchNode | NoteNode;\nexport type CableEdge = Edge<CableData, \"cable\">;\n\nexport const isMachine = (n: LabNode): n is MachineNode => n.type === \"machine\";\n/**\n * A router you configure (FRR as a container, or a VM): drawn as a faceplate with interfaces,\n * like a switch. The automatic router (kind \"router\") has no interfaces to show.\n */\nexport const isRealRouter = (n: LabNode): n is MachineNode => isMachine(n) && n.data.icon === \"router\" && n.data.kind !== \"router\";\nexport const ROUTER_PORTS = 4;\nexport const ROUTER_W = 168;\nexport const ROUTER_H = 74;\nexport const routerPort = (i: number) => `eth${String(i)}`;\n\n/** Routers and firewalls: one connection point, and they snap onto a LAN's edge. */\nexport const isAppliance = (n: LabNode): n is MachineNode => isMachine(n) && (n.data.icon === \"router\" || n.data.icon === \"shield\");\nexport const isLan = (n: LabNode): n is LanNode => n.type === \"lan\";\nexport const isSwitch = (n: LabNode): n is SwitchNode => n.type === \"switch\";\nexport const isNote = (n: LabNode): n is NoteNode => n.type === \"note\";\n/** A node's name as lists show it (a note has none). */\nexport const nodeName = (n: LabNode): string => (isNote(n) ? \"note\" : n.data.name);\n\nexport const SWITCH_PORTS = 8;\n/** A switch's faceplate on the canvas (see `SwitchNodeView`). */\nexport const SWITCH_W = 306;\nexport const SWITCH_H = 74;\nexport const TRUNK = \"trunk\";\n\n/** A machine's box on the canvas (see `MachineNodeView`). */\nexport const MACHINE_W = 120;\nexport const MACHINE_H = 116;\nexport const LAN_W = 420;\nexport const LAN_H = 300;\n\n/** How big a node is drawn: what snapping and \"is it inside the LAN\" go by. */\nexport function sizeOf(n: LabNode): { w: number; h: number } {\n if (n.type === \"lan\") return { w: n.width ?? LAN_W, h: n.height ?? LAN_H };\n if (n.type === \"switch\") return { w: SWITCH_W, h: SWITCH_H };\n if (n.type === \"note\") return { w: n.width ?? 200, h: n.height ?? 90 };\n if (n.data.icon === \"router\" && n.data.kind !== \"router\") return { w: ROUTER_W, h: ROUTER_H };\n return { w: MACHINE_W, h: MACHINE_H };\n}\n\n/** A node's center on the canvas, by its drawn size (measured by React Flow, or `fallback`). */\nexport function centerOf(n: LabNode, fallback: { w: number; h: number } = { w: MACHINE_W, h: MACHINE_H }): XYPosition {\n return {\n x: n.position.x + (n.width ?? n.measured?.width ?? fallback.w) / 2,\n y: n.position.y + (n.height ?? n.measured?.height ?? fallback.h) / 2,\n };\n}\n\n/**\n * How a LAN behaves on the canvas, as an Excalidraw frame: it is moved and selected by its label\n * only, so a click or a drag inside it reaches the canvas (placing a device, drawing a selection\n * box). Not saved: applied to every LAN when it is created or loaded.\n */\nexport const LAN_BEHAVIOR = { dragHandle: \".lan-handle\", className: \"pointer-events-none\" } as const;\n\n/** Which side of a LAN an appliance sits on, when it is snapped onto one. */\nexport type Side = \"top\" | \"bottom\" | \"left\" | \"right\";\n\n/** The canvas's look (see `DesignContext`): hand-drawn, or crisp for a report. */\nexport type Design = \"sketch\" | \"business\";\nexport const DESIGNS: Design[] = [\"sketch\", \"business\"];\n\nexport type Draft = {\n name: string;\n nodes: LabNode[];\n edges: CableEdge[];\n design?: Design;\n};\n\n/** Machine names are Isoloom keys: lowercase letters, digits and dashes. */\nexport function cleanName(name: string): string {\n return name.toLowerCase().replace(/[^a-z0-9-]/g, \"\");\n}\n\nexport function uid(prefix: string): string {\n return `${prefix}-${Date.now().toString(36)}${Math.random().toString(36).slice(2, 7)}`;\n}\n\n/** The first `<prefix><n>` no machine or LAN uses yet. */\nexport function freeName(prefix: string, nodes: LabNode[]): string {\n const taken = new Set(nodes.map(nodeName));\n for (let i = 1; ; i++) {\n if (!taken.has(`${prefix}${String(i)}`)) return `${prefix}${String(i)}`;\n }\n}\n\n/** Every node unselected: what placing or pasting something does to the rest. */\nexport function unselected<T extends LabNode | CableEdge>(items: T[]): T[] {\n return items.map((n) => ({ ...n, selected: false }));\n}\n", "\"use client\"\n\nimport * as React from \"react\"\nimport { Menu as MenuPrimitive } from \"@base-ui/react/menu\"\n\nimport { cn } from \"@/lib/utils\"\nimport { ChevronRightIcon } from \"lucide-react\"\n\nfunction DropdownMenu({ ...props }: MenuPrimitive.Root.Props) {\n return <MenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />\n}\n\nfunction DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {\n return <MenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />\n}\n\nfunction DropdownMenuContent({\n align = \"start\",\n alignOffset = 0,\n side = \"bottom\",\n sideOffset = 4,\n className,\n ...props\n}: MenuPrimitive.Popup.Props &\n Pick<\n MenuPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <MenuPrimitive.Portal>\n <MenuPrimitive.Positioner\n className=\"isolate z-50 outline-none\"\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n >\n <MenuPrimitive.Popup\n data-slot=\"dropdown-menu-content\"\n className={cn(\"z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:overflow-hidden data-closed:fade-out-0 data-closed:zoom-out-95\", className )}\n {...props}\n />\n </MenuPrimitive.Positioner>\n </MenuPrimitive.Portal>\n )\n}\n\nfunction DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {\n return <MenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />\n}\n\nfunction DropdownMenuLabel({\n className,\n inset,\n ...props\n}: MenuPrimitive.GroupLabel.Props & {\n inset?: boolean\n}) {\n return (\n <MenuPrimitive.GroupLabel\n data-slot=\"dropdown-menu-label\"\n data-inset={inset}\n className={cn(\n \"px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:pl-7\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuItem({\n className,\n inset,\n variant = \"default\",\n ...props\n}: MenuPrimitive.Item.Props & {\n inset?: boolean\n variant?: \"default\" | \"destructive\"\n}) {\n return (\n <MenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n data-inset={inset}\n data-variant={variant}\n className={cn(\n \"group/dropdown-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) {\n return <MenuPrimitive.SubmenuRoot data-slot=\"dropdown-menu-sub\" {...props} />\n}\n\nfunction DropdownMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: MenuPrimitive.SubmenuTrigger.Props & {\n inset?: boolean\n}) {\n return (\n <MenuPrimitive.SubmenuTrigger\n data-slot=\"dropdown-menu-sub-trigger\"\n data-inset={inset}\n className={cn(\n \"flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-popup-open:bg-accent data-popup-open:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto\" />\n </MenuPrimitive.SubmenuTrigger>\n )\n}\n\nfunction DropdownMenuSubContent({\n align = \"start\",\n alignOffset = -3,\n side = \"right\",\n sideOffset = 0,\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuContent>) {\n return (\n <DropdownMenuContent\n data-slot=\"dropdown-menu-sub-content\"\n className={cn(\"w-auto min-w-[96px] rounded-lg bg-popover p-1 text-popover-foreground shadow-lg ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\", className )}\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuSeparator({\n className,\n ...props\n}: MenuPrimitive.Separator.Props) {\n return (\n <MenuPrimitive.Separator\n data-slot=\"dropdown-menu-separator\"\n className={cn(\"-mx-1 my-1 h-px bg-border\", className)}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuShortcut({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n className={cn(\n \"ml-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuLabel,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubTrigger,\n DropdownMenuSubContent,\n}\n", "\"use client\";\n\nimport type { MouseEvent, ReactNode } from \"react\";\nimport { Background, BackgroundVariant, ConnectionMode, Controls, Panel, ReactFlow, SelectionMode, type EdgeTypes, type NodeTypes } from \"@xyflow/react\";\nimport \"@xyflow/react/dist/style.css\";\nimport { Redo2, Undo2 } from \"lucide-react\";\nimport { machineEnds, networkOfCable } from \"@/lib/tool/cables\";\nimport { isLan, isMachine, type CableEdge, type LabNode } from \"@/lib/tool/model\";\nimport { nameById } from \"@/lib/tool/selection\";\nimport { CableEdgeView } from \"./canvas/cable-edge\";\nimport { AddressesContext, LiveContext, PortsContext, SidesContext } from \"./canvas/contexts\";\nimport { LanNodeView } from \"./canvas/lan-node\";\nimport { MachineNodeView } from \"./canvas/machine-node\";\nimport { NoteNodeView } from \"./canvas/note-node\";\nimport { DesignContext } from \"./canvas/sketch\";\nimport { SwitchNodeView } from \"./canvas/switch-node\";\nimport type { EditorModel } from \"./hooks/use-editor\";\n\nconst nodeTypes: NodeTypes = { machine: MachineNodeView, lan: LanNodeView, switch: SwitchNodeView, note: NoteNodeView };\nconst edgeTypes: EdgeTypes = { cable: CableEdgeView };\n\n/** What the canvas's nodes and cables read: the look, addresses, port sides and the running lab. */\nfunction CanvasContexts({ e, children }: { e: EditorModel; children: ReactNode }) {\n return (\n <DesignContext.Provider value={e.design.design}>\n <AddressesContext.Provider value={e.addresses}>\n <SidesContext.Provider value={e.views.sides}>\n <PortsContext.Provider value={e.views.routerPorts}>\n <LiveContext.Provider value={e.liveView}>{children}</LiveContext.Provider>\n </PortsContext.Provider>\n </SidesContext.Provider>\n </AddressesContext.Provider>\n </DesignContext.Provider>\n );\n}\n\n/** As in GNS3: double-click a running machine for its console, right-click for the rest (desktop app only). */\nfunction runningLabMenus(e: EditorModel) {\n const { invoke, desk, lab } = e;\n const running = desk.state.run === \"running\";\n return {\n onNodeDoubleClick: (_: MouseEvent, node: LabNode) => {\n if (invoke && running && isMachine(node)) void desk.actions.machineConsole(node.data.name);\n },\n onNodeContextMenu: (ev: MouseEvent, node: LabNode) => {\n if (!invoke) return;\n if (isMachine(node)) {\n ev.preventDefault();\n desk.menus.setMachineMenu({ x: ev.clientX, y: ev.clientY, machine: node.data.name });\n } else if (isLan(node)) {\n ev.preventDefault();\n desk.menus.setLinkMenu({ x: ev.clientX, y: ev.clientY, network: node.data.name, title: node.data.name });\n }\n },\n onEdgeContextMenu: (ev: MouseEvent, edge: CableEdge) => {\n const network = invoke ? networkOfCable(edge.id, lab.nodes, lab.edges) : null;\n if (!network) return;\n ev.preventDefault();\n const title = `${nameById(lab.nodes, edge.source)} \u2194 ${nameById(lab.nodes, edge.target)}`;\n desk.menus.setLinkMenu({ x: ev.clientX, y: ev.clientY, network, title, machines: machineEnds(edge, lab.nodes) });\n },\n };\n}\n\n/** Undo and redo, beside the zoom controls. */\nfunction HistoryButtons({ e }: { e: EditorModel }) {\n const { step, canUndo, canRedo } = e.history;\n const t = e.t.toolbar;\n return (\n <Panel position=\"bottom-left\" className=\"!mb-4 !ml-16 flex overflow-hidden rounded-lg border bg-popover shadow-sm\">\n <button type=\"button\" onClick={() => { step(true); }} disabled={!canUndo} title={t.undoTitle} aria-label={t.undo} className=\"grid size-8 place-items-center text-foreground hover:bg-muted disabled:opacity-35\">\n <Undo2 className=\"size-4\" />\n </button>\n <button type=\"button\" onClick={() => { step(false); }} disabled={!canRedo} title={t.redoTitle} aria-label={t.redo} className=\"grid size-8 place-items-center border-l text-foreground hover:bg-muted disabled:opacity-35\">\n <Redo2 className=\"size-4\" />\n </button>\n </Panel>\n );\n}\n\n/** The canvas: React Flow with the lab's nodes and cables, in Excalidraw's two modes. */\nexport function FlowCanvas({ e }: { e: EditorModel }) {\n const { lab, tools, cabling, carry, placement } = e;\n const select = tools.mode === \"select\";\n const menus = runningLabMenus(e);\n return (\n <CanvasContexts e={e}>\n <ReactFlow<LabNode, CableEdge>\n nodes={lab.nodes}\n edges={e.views.shownEdges}\n nodeTypes={nodeTypes}\n edgeTypes={edgeTypes}\n onNodesChange={cabling.onNodesChange}\n onNodeDragStart={carry.onNodeDragStart}\n onNodeDrag={carry.onNodeDrag}\n onNodeDragStop={carry.onNodeDragStop}\n // A selected LAN must stay under its machines.\n elevateNodesOnSelect={false}\n onEdgesChange={lab.onEdgesChange}\n onConnect={cabling.onConnect}\n onPaneClick={placement.onPaneClick}\n onNodeClick={placement.onNodeClick}\n onNodeDoubleClick={menus.onNodeDoubleClick}\n onNodeContextMenu={menus.onNodeContextMenu}\n onEdgeContextMenu={menus.onEdgeContextMenu}\n onMoveStart={e.desk.menus.closeMenus}\n connectionMode={ConnectionMode.Loose}\n // Select: dragging the canvas draws a selection box; the middle button or Space pans.\n // Hand: dragging pans, and nothing on the canvas can be changed.\n panOnDrag={select ? [1] : true}\n selectionOnDrag={select}\n // Only what is wholly inside the box, so selecting a LAN's machines leaves the LAN alone.\n selectionMode={SelectionMode.Full}\n multiSelectionKeyCode={[\"Shift\", \"Meta\", \"Control\"]}\n panActivationKeyCode=\"Space\"\n nodesDraggable={select}\n nodesConnectable={select}\n elementsSelectable={select}\n panOnScroll\n zoomActivationKeyCode={[\"Meta\", \"Control\"]}\n isValidConnection={cabling.isValid}\n edgesReconnectable\n onReconnectStart={cabling.onReconnectStart}\n onReconnect={cabling.onReconnect}\n onReconnectEnd={cabling.onReconnectEnd}\n colorMode={e.resolvedTheme === \"dark\" ? \"dark\" : \"light\"}\n deleteKeyCode={[\"Backspace\", \"Delete\"]}\n fitView\n fitViewOptions={{ padding: 0.4, maxZoom: 1.1 }}\n proOptions={{ hideAttribution: true }}\n >\n {e.design.design === \"business\" && <Background variant={BackgroundVariant.Dots} gap={20} size={1.2} color=\"var(--border)\" />}\n <Controls position=\"bottom-left\" showInteractive={false} className=\"!m-4 overflow-hidden !rounded-lg !border !shadow-sm\" />\n <HistoryButtons e={e} />\n </ReactFlow>\n </CanvasContexts>\n );\n}\n", "import type { XYPosition } from \"@xyflow/react\";\nimport { LAN_H, LAN_W, MACHINE_H, MACHINE_W, isAppliance, isLan, sizeOf, type LabNode, type LanNode, type MachineNode, type Side } from \"./model\";\n\n/** Where things sit on the canvas: LAN areas, their borders, and what snaps onto them. */\n\n/** How close (canvas units) an appliance's center must come to a LAN's border to snap onto it. */\nconst SNAP = 36;\n/** Exactly on the border, give or take rounding. */\nconst ON = 0.5;\n\ninterface Rect {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\n/** The area a LAN covers on the canvas. */\nexport function lanRect(l: LanNode): Rect {\n return { x: l.position.x, y: l.position.y, w: l.width ?? LAN_W, h: l.height ?? LAN_H };\n}\n\n/** Whether `p` lies within `r`, borders included, give or take `slack`. */\nexport function within(r: Rect, p: XYPosition, slack = 0): boolean {\n return p.x >= r.x - slack && p.x <= r.x + r.w + slack && p.y >= r.y - slack && p.y <= r.y + r.h + slack;\n}\n\n/** A point on one of a rectangle's borders, and how far `p` is from it. */\ninterface BorderPoint {\n d: number;\n x: number;\n y: number;\n}\n\n/** The points of `r`'s borders facing `p` (top, bottom, left, right), where `p` is level with them. */\nfunction borderPoints(r: Rect, p: XYPosition): BorderPoint[] {\n const alongX = p.x >= r.x && p.x <= r.x + r.w;\n const alongY = p.y >= r.y && p.y <= r.y + r.h;\n const out: BorderPoint[] = [];\n if (alongX) out.push({ d: Math.abs(p.y - r.y), x: p.x, y: r.y }, { d: Math.abs(p.y - (r.y + r.h)), x: p.x, y: r.y + r.h });\n if (alongY) out.push({ d: Math.abs(p.x - r.x), x: r.x, y: p.y }, { d: Math.abs(p.x - (r.x + r.w)), x: r.x + r.w, y: p.y });\n return out;\n}\n\n/**\n * Where an appliance at `position` should go: centered on the nearest LAN border within reach\n * (half inside, half outside), or where it is when no border is near.\n */\nexport function snapToLanEdge(position: XYPosition, lans: LanNode[], size: { w: number; h: number } = { w: MACHINE_W, h: MACHINE_H }): XYPosition {\n const center = { x: position.x + size.w / 2, y: position.y + size.h / 2 };\n let best: BorderPoint | null = null;\n for (const l of lans) {\n for (const c of borderPoints(lanRect(l), center)) if (c.d <= SNAP && (!best || c.d < best.d)) best = c;\n }\n return best ? { x: best.x - size.w / 2, y: best.y - size.h / 2 } : position;\n}\n\n/** The side of `r` that `p` lies on, if any (top, bottom, left, right, in that order). */\nfunction sideOf(r: Rect, p: XYPosition): Side | null {\n const alongX = p.x >= r.x && p.x <= r.x + r.w;\n const alongY = p.y >= r.y && p.y <= r.y + r.h;\n if (alongX && Math.abs(p.y - r.y) < ON) return \"top\";\n if (alongX && Math.abs(p.y - (r.y + r.h)) < ON) return \"bottom\";\n if (alongY && Math.abs(p.x - r.x) < ON) return \"left\";\n if (alongY && Math.abs(p.x - (r.x + r.w)) < ON) return \"right\";\n return null;\n}\n\n/** A node's center, by the size it is drawn at (see `sizeOf`). */\nfunction drawnCenter(m: LabNode): XYPosition {\n const { w, h } = sizeOf(m);\n return { x: m.position.x + w / 2, y: m.position.y + h / 2 };\n}\n\n/** The LAN border an appliance sits on, if any: the side of the LAN, so its port faces out. */\nexport function sideOnLan(m: MachineNode, lans: LanNode[]): Side | null {\n const c = drawnCenter(m);\n for (const l of lans) {\n const side = sideOf(lanRect(l), c);\n if (side) return side;\n }\n return null;\n}\n\n/** The LAN an appliance sits on the border of, and which border: its inside and outside. */\nexport function lanUnder(m: MachineNode, lans: LanNode[]): { lan: LanNode; side: Side } | null {\n for (const l of lans) {\n const side = sideOnLan(m, [l]);\n if (side) return { lan: l, side };\n }\n return null;\n}\n\n/** Whether a point is inside a LAN's area (not on its border). */\nexport function insideLan(p: XYPosition, l: LanNode): boolean {\n const r = lanRect(l);\n return p.x > r.x + ON && p.x < r.x + r.w - ON && p.y > r.y + ON && p.y < r.y + r.h - ON;\n}\n\n/**\n * The LANs a machine sits in: its center is inside the area (or on its border). A hidden LAN's\n * area isn't drawn, so it doesn't take machines by position, except routers and firewalls on\n * its edge; machines join it through its switch's ports or a cable.\n */\nexport function lansAround(m: MachineNode, nodes: LabNode[]): LanNode[] {\n const c = drawnCenter(m);\n const onEdge = isAppliance(m) ? lanUnder(m, nodes.filter(isLan))?.lan.id : undefined;\n return nodes.filter(isLan).filter((l) => (!l.data.hidden || l.id === onEdge) && within(lanRect(l), c));\n}\n", "import { TRUNK, isSwitch, type CableEdge, type LabNode, type SwitchNode } from \"./model\";\n\n/** VLANs and switch ports. VLANs are lab-wide: `vlan10` is the same network on every switch. */\n\nexport const vlanName = (id: number) => `vlan${String(id)}`;\n\n/** A VLAN's color, from its number, so `vlan10` has the same color on every switch and area. */\nconst VLAN_COLORS = [\"#7048e8\", \"#2f9e44\", \"#1971c2\", \"#e8590c\", \"#e03131\", \"#0c8599\", \"#c2255c\", \"#5c940d\"];\nexport function vlanColor(id: number): string {\n return VLAN_COLORS[Math.abs(Math.round(id / 10)) % VLAN_COLORS.length];\n}\n\n/** A trunk port's look: striped with the colors of the VLANs it carries (muted when none). */\nexport function trunkStripes(vlans: { id: number }[]): string {\n if (!vlans.length) return \"var(--muted)\";\n const stripes = vlans.map((v, i) => `${vlanColor(v.id)} ${String(i * 5)}px ${String((i + 1) * 5)}px`).join(\", \");\n return `repeating-linear-gradient(135deg, ${stripes})`;\n}\n\n/** The VLAN number in a LAN's name (`vlan10` -> 10), when the LAN is a VLAN. */\nexport function vlanOf(lanName: string): number | null {\n const m = /^vlan(\\d{1,4})$/.exec(lanName);\n return m ? Number(m[1]) : null;\n}\n\n/** The port a switch handle stands for: `p3` -> its index, `trunk` -> the trunk. */\nfunction switchPort(handle: string | null | undefined): number | typeof TRUNK | null {\n if (handle === TRUNK) return TRUNK;\n const m = handle ? /^p(\\d+)$/.exec(handle) : null;\n return m ? Number(m[1]) - 1 : null;\n}\n\n/** Whether a switch handle is a trunk: the T port, or any port set to \"trunk\". */\nexport function isTrunkPort(sw: SwitchNode, handle: string | null | undefined): boolean {\n const port = switchPort(handle);\n return port === TRUNK || (typeof port === \"number\" && sw.data.ports[port] === TRUNK);\n}\n\n/** The VLAN of an access port, or null (a trunk, an unassigned port, not a port). */\nexport function accessVlan(sw: SwitchNode, handle: string | null | undefined): number | null {\n const port = switchPort(handle);\n const mode = typeof port === \"number\" ? sw.data.ports[port] : null;\n return typeof mode === \"number\" ? mode : null;\n}\n\n/** A port's label next to its cable: 1, 2\u2026 or T. */\nexport function switchPortLabel(handle: string | null | undefined): string {\n const p = switchPort(handle);\n if (p === TRUNK) return \"T\";\n return p === null ? \"\" : String(p + 1);\n}\n\n/**\n * The LAN each switch's VLANs belong to in isoloom.yml: switches joined by a cable, or sharing a\n * VLAN number (VLANs are lab-wide here), are one LAN, named after the first. Returns a switch's\n * LAN name by its id.\n */\nexport function switchLans(nodes: LabNode[], edges: CableEdge[]): (switchId: string) => string {\n const switches = nodes.filter(isSwitch);\n const group = new Map(switches.map((s) => [s.id, s.id]));\n const root = (id: string): string => {\n const up = group.get(id);\n return up === undefined || up === id ? id : root(up);\n };\n const unite = (a: string, b: string) => group.set(root(a), root(b));\n for (const e of edges) if (group.has(e.source) && group.has(e.target)) unite(e.source, e.target);\n const firstWith = new Map<number, string>();\n for (const sw of switches) {\n for (const v of sw.data.vlans) {\n const other = firstWith.get(v.id);\n if (other) unite(sw.id, other);\n else firstWith.set(v.id, sw.id);\n }\n }\n return (id: string) => switches.find((s) => root(s.id) === root(id))?.data.name ?? \"\";\n}\n\n/** The name Isoloom gives a trunk's interface: its LAN's, within Linux's limit (`sw1`, then `sw1.10`). */\nexport const trunkInterface = (lan: string) => lan.slice(0, 10).replace(/-+$/, \"\");\n", "import type { Connection } from \"@xyflow/react\";\nimport { sideOnLan } from \"./geometry\";\nimport { isAppliance, isLan, isMachine, isRealRouter, isSwitch, routerPort, uid, type CableEdge, type LabNode, type LanNode, type MachineNode } from \"./model\";\nimport { accessVlan, switchPortLabel, vlanName } from \"./vlans\";\n\n/** Cables: where they plug in, what their ends are called, and which network each one is. */\n\n/** The handle a cable uses on a machine: an appliance's single port, or a machine's top/bottom. */\nfunction machineHandle(m: MachineNode, old: string | null | undefined): string {\n if (isAppliance(m)) return \"port\";\n return old === \"bottom\" ? \"bottom\" : \"top\";\n}\n\nconst isPort = (h: string | null | undefined): h is string => !!h && /^eth\\d+$/.test(h);\n\n/** The ports each real router's cables already plug into. */\nfunction takenPorts(edges: CableEdge[], byId: Map<string, LabNode>): Map<string, Set<string>> {\n const taken = new Map<string, Set<string>>();\n for (const e of edges) {\n for (const [id, h] of [\n [e.source, e.sourceHandle],\n [e.target, e.targetHandle],\n ] as const) {\n const n = byId.get(id);\n if (n && isRealRouter(n) && isPort(h)) taken.set(id, (taken.get(id) ?? new Set()).add(h));\n }\n }\n return taken;\n}\n\n/**\n * Cables saved with the old handles (one on each side of every machine) move onto the current\n * ones: an appliance's single port, the top or bottom of other machines. LAN handles stay.\n */\nexport function migrateEdges(edges: CableEdge[], nodes: LabNode[]): CableEdge[] {\n const byId = new Map(nodes.map((n) => [n.id, n]));\n // A real router's cables plug into its ports: one that isn't on a port yet takes a free one.\n const taken = takenPorts(edges, byId);\n const freePort = (id: string) => {\n const used = taken.get(id) ?? new Set<string>();\n for (let i = 0; i < 64; i++) {\n if (!used.has(routerPort(i))) {\n used.add(routerPort(i));\n taken.set(id, used);\n return routerPort(i);\n }\n }\n return routerPort(0);\n };\n const fix = (id: string, h: string | null | undefined) => {\n const n = byId.get(id);\n if (n && isRealRouter(n)) return isPort(h) ? h : freePort(id);\n return n && isMachine(n) ? machineHandle(n, h) : h;\n };\n return edges.map((e) => ({ ...e, sourceHandle: fix(e.source, e.sourceHandle), targetHandle: fix(e.target, e.targetHandle) }));\n}\n\n/** The ports a machine's cables already use. */\nfunction usedPorts(nodeId: string, edges: CableEdge[]): string[] {\n return edges.flatMap((e) => [...(e.source === nodeId && e.data ? [e.data.aPort] : []), ...(e.target === nodeId && e.data ? [e.data.bPort] : [])]);\n}\n\n/**\n * The first free `eth<n>` on a machine, from `first`: an appliance on a LAN's edge uses eth0 on\n * that LAN, so its cables start at eth1.\n */\nexport function nextPort(nodeId: string, edges: CableEdge[], first = 0): string {\n const used = new Set(usedPorts(nodeId, edges));\n for (let i = first; ; i++) {\n if (!used.has(`eth${String(i)}`)) return `eth${String(i)}`;\n }\n}\n\n/** Whether a cable runs between two named machines: a link of its own in isoloom.yml. */\nfunction isLink(e: CableEdge, byId: Map<string, LabNode>): boolean {\n const x = byId.get(e.source);\n const y = byId.get(e.target);\n return !!x && !!y && isMachine(x) && isMachine(y) && !!x.data.name && !!y.data.name && !!e.data;\n}\n\n/** The network a cable on a switch port carries: the access port's VLAN (a trunk carries several). */\nfunction switchNetwork(edge: CableEdge, byId: Map<string, LabNode>): string | null | undefined {\n for (const [sw, handle] of [\n [byId.get(edge.source), edge.sourceHandle],\n [byId.get(edge.target), edge.targetHandle],\n ] as const) {\n if (!sw || !isSwitch(sw)) continue;\n const vlan = accessVlan(sw, handle);\n return vlan !== null ? vlanName(vlan) : null;\n }\n return undefined;\n}\n\n/**\n * The Isoloom network a cable became (`link-<n>`): cables between two machines are numbered in\n * the order `toTopology` lists them. A cable to a LAN is that LAN.\n */\nexport function networkOfCable(edgeId: string, nodes: LabNode[], edges: CableEdge[]): string | null {\n const byId = new Map(nodes.map((n) => [n.id, n]));\n const edge = edges.find((e) => e.id === edgeId);\n if (!edge) return null;\n const a = byId.get(edge.source);\n const b = byId.get(edge.target);\n if (a && isLan(a)) return a.data.name;\n if (b && isLan(b)) return b.data.name;\n const onSwitch = switchNetwork(edge, byId);\n if (onSwitch !== undefined) return onSwitch;\n const i = edges.filter((e) => isLink(e, byId)).findIndex((e) => e.id === edgeId);\n return i < 0 ? null : `link-${String(i)}`;\n}\n\n/** The names of a cable's ends that are machines (a LAN or a switch has no port to cut). */\nexport function machineEnds(edge: CableEdge, nodes: LabNode[]): string[] {\n return [edge.source, edge.target].flatMap((id) => {\n const n = nodes.find((x) => x.id === id);\n return n && isMachine(n) ? [n.data.name] : [];\n });\n}\n\n/** What a cable's ends can plug into, by node id. */\nexport interface LabIndex {\n lanIds: Set<string>;\n switchIds: Set<string>;\n routerIds: Set<string>;\n}\n\n/** Whether a cable end on `node` takes a port: a switch's or a real router's. */\nconst ported = (index: LabIndex, node: string) => index.switchIds.has(node) || index.routerIds.has(node);\n\n/** Whether a switch or router port already has a cable (other than `ignore`, the one moving). */\nfunction portTaken(index: LabIndex, edges: CableEdge[], ignore: string | undefined, node: string, handle: string | null | undefined): boolean {\n return (\n ported(index, node) &&\n edges.some((e) => e.id !== ignore && ((e.source === node && e.sourceHandle === handle) || (e.target === node && e.targetHandle === handle)))\n );\n}\n\n/** A cable's two ends, as React Flow gives them (a connection being drawn, or a cable). */\ninterface Ends {\n source: string;\n target: string;\n sourceHandle?: string | null;\n targetHandle?: string | null;\n}\n\n/**\n * Machine to machine, LAN or port. Never LAN to LAN or switch to LAN, and a switch or router\n * port takes one cable, as on real gear. `ignore`: the cable being moved, whose ends don't count.\n */\nexport function canConnect(c: Ends, index: LabIndex, edges: CableEdge[], ignore?: string): boolean {\n if (c.source === c.target) return false;\n const area = (id: string) => index.lanIds.has(id) || index.switchIds.has(id);\n const bothSwitches = index.switchIds.has(c.source) && index.switchIds.has(c.target);\n if (area(c.source) && area(c.target) && !bothSwitches) return false;\n return !portTaken(index, edges, ignore, c.source, c.sourceHandle) && !portTaken(index, edges, ignore, c.target, c.targetHandle);\n}\n\n/** An appliance on a LAN's edge already uses eth0 there. */\nexport function onLanEdge(id: string, nodes: LabNode[], lans: LanNode[]): boolean {\n const n = nodes.find((x) => x.id === id);\n return !!n && isAppliance(n) && sideOnLan(n, lans) !== null;\n}\n\n/**\n * The label of a cable's end on `node`: the switch port, the router's port, nothing on a LAN,\n * or else `machinePort()` (the machine's next free port, or the one it keeps).\n */\nfunction endLabel(index: LabIndex, node: string, handle: string | null | undefined, machinePort: () => string): string {\n if (index.lanIds.has(node)) return \"\";\n if (index.switchIds.has(node)) return switchPortLabel(handle);\n if (index.routerIds.has(node)) return handle ?? \"\";\n return machinePort();\n}\n\n/** A new cable for a connection, its ends labelled (`first(node)`: the first port to give). */\nexport function newCable(c: Connection, index: LabIndex, edges: CableEdge[], first: (node: string) => number): CableEdge {\n return {\n id: uid(\"c\"),\n type: \"cable\",\n source: c.source,\n sourceHandle: c.sourceHandle,\n target: c.target,\n targetHandle: c.targetHandle,\n // A LAN has no ports: the cable's end on it stays unnamed.\n data: {\n aPort: endLabel(index, c.source, c.sourceHandle, () => nextPort(c.source, edges, first(c.source))),\n bPort: endLabel(index, c.target, c.targetHandle, () => nextPort(c.target, edges, first(c.target))),\n },\n };\n}\n\n/**\n * The cables after `old` moved to `c`. A moved end gets the label of where it lands: the switch\n * port, nothing on a LAN, or the machine's next free port. An end that stays put keeps its label\n * (same machine: same port; where on its box the cable attaches is only drawing).\n */\nexport function reconnected(edges: CableEdge[], old: CableEdge, c: Connection, index: LabIndex, first: (node: string) => number): CableEdge[] {\n const others = edges.filter((e) => e.id !== old.id);\n const label = (node: string, handle: string | null, keep: string, same: boolean) => endLabel(index, node, handle, () => (same ? keep : nextPort(node, others, first(node))));\n return edges.map((e) =>\n e.id !== old.id || !e.data\n ? e\n : {\n ...e,\n source: c.source,\n sourceHandle: c.sourceHandle,\n target: c.target,\n targetHandle: c.targetHandle,\n data: {\n aPort: label(c.source, c.sourceHandle, e.data.aPort, c.source === e.source),\n bPort: label(c.target, c.targetHandle, e.data.bPort, c.target === e.target),\n },\n },\n );\n}\n", "/**\n * A machine's ports field (`80, 443/https, 53/udp`): each entry a port, 1 to 65535, and what it\n * speaks when it isn't plain TCP: Isoloom's port `protocol`. An entry Isoloom couldn't take is\n * kept out of the topology and reported (see `canvasIssues`), never guessed.\n */\n\n/** What a port speaks: TCP (the default), UDP, or TCP that speaks HTTP, HTTPS or TLS. */\nexport const PORT_PROTOCOLS = [\"tcp\", \"udp\", \"http\", \"https\", \"tls\"] as const;\ntype PortProtocol = (typeof PORT_PROTOCOLS)[number];\n\n/** A port as the engine's topology takes it (`protocol` left out for TCP). */\nexport interface Service {\n port: number;\n protocol?: PortProtocol;\n}\n\nconst ENTRY = /^(\\d{1,5})(?:\\/([a-z]+))?$/;\n\nconst isProtocol = (p: string): p is PortProtocol => PORT_PROTOCOLS.some((x) => x === p);\n\n/** One entry as a port, or null when Isoloom couldn't take it. */\nfunction service(entry: string): Service | null {\n const m = ENTRY.exec(entry);\n if (!m) return null;\n // An entry without its protocol is TCP.\n const [, digits, protocol = \"tcp\"] = m;\n const port = Number(digits);\n if (port < 1 || port > 65535) return null;\n if (protocol === \"tcp\") return { port };\n return isProtocol(protocol) ? { port, protocol } : null;\n}\n\n/** The ports field read: its ports, and each entry it couldn't read. */\nexport function readPorts(text: string): { services: Service[]; bad: string[] } {\n const services: Service[] = [];\n const bad: string[] = [];\n for (const entry of text.split(\",\").map((e) => e.trim()).filter(Boolean)) {\n const s = service(entry);\n if (s) services.push(s);\n else bad.push(entry);\n }\n return { services, bad };\n}\n\n/** Ports as the field writes them: `80, 53/udp`. */\nexport function portsText(services: readonly Service[]): string {\n return services.map((s) => (s.protocol && s.protocol !== \"tcp\" ? `${String(s.port)}/${s.protocol}` : String(s.port))).join(\", \");\n}\n", "import { isLan, isMachine, isSwitch, type LabNode } from \"./model\";\nimport { readPorts } from \"./ports\";\nimport { vlanName } from \"./vlans\";\n\n/** The editor's words for what the canvas finds wrong (see the editor's text). */\nexport interface IssueText {\n vlanBlocks: (vlan: string, block: string, other: string, sw: string) => string;\n areaBlock: (lan: string, block: string, switches: string) => string;\n noName: Record<\"machine\" | \"lan\" | \"switch\", string>;\n sameName: Record<\"machine\" | \"lan\" | \"switch\", (name: string) => string>;\n /** A ports field entry Isoloom couldn't take: the machine and the entry. */\n badPort: (machine: string, entry: string) => string;\n}\n\n/** One VLAN, one block: every switch (and a LAN area of that name) must agree on it. */\nfunction blockIssues(nodes: LabNode[], text: IssueText): string[] {\n const issues: string[] = [];\n const blocks = new Map<string, string>();\n for (const sw of nodes.filter(isSwitch)) {\n for (const v of sw.data.vlans) {\n const name = vlanName(v.id);\n const seen = blocks.get(name);\n if (seen && seen !== v.cidr) issues.push(text.vlanBlocks(name, seen, v.cidr, sw.data.name));\n blocks.set(name, v.cidr);\n }\n }\n for (const l of nodes.filter(isLan)) {\n const seen = blocks.get(l.data.name);\n if (seen && seen !== l.data.cidr) issues.push(text.areaBlock(l.data.name, l.data.cidr, seen));\n }\n return issues;\n}\n\n/** Names Isoloom would reject (none) or merge (the same twice), per kind of node. */\nfunction nameIssues(nodes: LabNode[], text: IssueText): string[] {\n const issues: string[] = [];\n for (const [what, list] of [\n [\"machine\", nodes.filter(isMachine)],\n [\"lan\", nodes.filter(isLan)],\n [\"switch\", nodes.filter(isSwitch)],\n ] as const) {\n const seen = new Set<string>();\n for (const n of list) {\n if (!n.data.name) issues.push(text.noName[what]);\n else if (seen.has(n.data.name)) issues.push(text.sameName[what](n.data.name));\n seen.add(n.data.name);\n }\n }\n return issues;\n}\n\n/** Port entries Isoloom couldn't take (not a port, or not one of its protocols): left out of the topology, so said here. */\nfunction portIssues(nodes: LabNode[], text: IssueText): string[] {\n return nodes.filter(isMachine).flatMap((m) => readPorts(m.data.ports).bad.map((entry) => text.badPort(m.data.name, entry)));\n}\n\n/** What the canvas can tell before the engine runs: names Isoloom would reject or merge, ports it couldn't take. */\nexport function canvasIssues(nodes: LabNode[], text: IssueText): string[] {\n return [...blockIssues(nodes, text), ...nameIssues(nodes, text), ...portIssues(nodes, text)];\n}\n", "import { canvasIssues, type IssueText } from \"./issues\";\nimport type { Plan } from \"./engine\";\nimport { isLan, isMachine, nodeName, type CableEdge, type LabNode } from \"./model\";\n\n/** What is selected: one thing opens its window; several open the \"selection\" window instead. */\nexport function selectionOf(nodes: LabNode[], edges: CableEdge[]) {\n const selectedNodes = nodes.filter((n) => n.selected);\n const selectedEdges = edges.filter((e) => e.selected);\n const count = selectedNodes.length + selectedEdges.length;\n const only = count === 1 ? selectedNodes.at(0) : undefined;\n return {\n selectedNodes,\n selectedEdges,\n count,\n machine: only && isMachine(only) ? only : undefined,\n lan: only && isLan(only) ? only : undefined,\n edge: count === 1 ? selectedEdges.at(0) : undefined,\n };\n}\n\n/**\n * What to fix before the lab runs: the canvas's own findings, then the engine's. An empty canvas\n * isn't a lab with problems yet: nothing until there is something to check.\n */\nexport function labIssues(nodes: LabNode[], plan: Plan | null, text: IssueText): string[] {\n if (nodes.length === 0) return [];\n return [...canvasIssues(nodes, text), ...(plan && !plan.ok && plan.error ? [plan.error] : []), ...(plan?.problems ?? [])];\n}\n\n/** A node's name by its id, as the windows show it (\"?\" for one that is gone). */\nexport function nameById(nodes: LabNode[], id: string): string {\n const n = nodes.find((x) => x.id === id);\n return n ? nodeName(n) : \"?\";\n}\n", "\"use client\";\n\nimport { useContext, useMemo } from \"react\";\nimport { BaseEdge, EdgeLabelRenderer, Position, getSmoothStepPath, getStraightPath, type EdgeProps } from \"@xyflow/react\";\nimport { Unplug } from \"lucide-react\";\nimport { conditionsLabel } from \"@/lib/tool/conditions\";\nimport type { CableStatus } from \"@/lib/tool/live\";\nimport type { CableEdge } from \"@/lib/tool/model\";\nimport { cn } from \"@/lib/utils\";\nimport { useText } from \"../text\";\nimport { LiveContext } from \"./contexts\";\nimport { Sketch, gen, seedOf, useBusiness, useSketch } from \"./sketch\";\n\ninterface Point {\n x: number;\n y: number;\n}\n\nconst translate = (p: Point) => `translate(-50%, -50%) translate(${String(p.x)}px, ${String(p.y)}px)`;\n\nfunction PortLabel({ at, text }: { at: Point; text?: string }) {\n if (!text) return null;\n return (\n <div style={{ transform: translate(at) }} className=\"nodrag nopan pointer-events-none absolute rounded-sm border bg-card px-1 py-px font-mono text-[10px] leading-none text-muted-foreground\">\n {text}\n </div>\n );\n}\n\n/**\n * Where a cable runs and where its labels sit. Business: right angles with rounded corners, as in\n * a diagramming tool, a port's name just off its port in the direction the cable leaves; sketch:\n * straight, the names along the line.\n */\nfunction cableGeometry(p: EdgeProps<CableEdge>, business: boolean) {\n const { sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition } = p;\n const [path, midX, midY] = business\n ? getSmoothStepPath({ sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition, borderRadius: 10, offset: 18 })\n : getStraightPath({ sourceX, sourceY, targetX, targetY });\n const along = (f: number) => ({ x: sourceX + (targetX - sourceX) * f, y: sourceY + (targetY - sourceY) * f });\n const off = (x: number, y: number, side: Position) => ({\n x: x + (side === Position.Left ? -18 : side === Position.Right ? 18 : 0),\n y: y + (side === Position.Top ? -14 : side === Position.Bottom ? 14 : 0),\n });\n return {\n path,\n middle: business ? { x: midX, y: midY } : along(0.5),\n a: business ? off(sourceX, sourceY, sourcePosition) : along(0.18),\n b: business ? off(targetX, targetY, targetPosition) : along(0.82),\n };\n}\n\n/** The running lab: a cable says whether it carries traffic. */\nfunction LiveBadge({ live, at }: { live: Exclude<CableStatus, \"unknown\">; at: Point }) {\n const t = useText().canvas.live;\n return (\n <div title={t.cable[live]} style={{ transform: translate(at) }} className=\"nodrag nopan pointer-events-auto absolute\">\n {live === \"up\" ? (\n <span className=\"block size-2 rounded-full bg-success ring-2 ring-background\" aria-label={t.cable.up} />\n ) : (\n <span className={cn(\"flex items-center gap-1 rounded-sm border bg-card px-1 py-px text-[10px] leading-none whitespace-nowrap\", live === \"cut\" ? \"border-destructive/50 text-destructive\" : \"text-muted-foreground\")}>\n <Unplug className=\"size-2.5\" aria-hidden /> {t.cableShort[live]}\n </span>\n )}\n </div>\n );\n}\n\n/** The line itself, in the color of the VLAN or network on the port it's plugged into. */\nfunction CableLine({ p, path, live, stroke }: { p: EdgeProps<CableEdge>; path: string; live: CableStatus | undefined; stroke: string }) {\n const business = useBusiness();\n const sketch = useSketch();\n const { id, sourceX, sourceY, targetX, targetY, selected } = p;\n const line = useMemo(\n () => gen.line(sourceX, sourceY, targetX, targetY, { ...sketch, seed: seedOf(id), stroke: \"S\", strokeWidth: selected ? 2.5 : 1.5 }),\n [id, sourceX, sourceY, targetX, targetY, selected, sketch],\n );\n const broken = live === \"cut\" || live === \"down\";\n if (business) {\n return <path d={path} fill=\"none\" style={{ stroke, strokeWidth: selected ? 2.25 : 1.5, strokeLinejoin: \"round\", strokeDasharray: broken ? \"6 5\" : undefined, opacity: live === \"down\" ? 0.4 : 1 }} />;\n }\n const opacity = live === \"down\" ? 0.35 : selected ? 1 : p.data?.color ? 0.95 : 0.7;\n return <Sketch drawable={line} stroke={stroke} opacity={opacity} dash={broken ? \"7 6\" : undefined} />;\n}\n\n/** A cable: a hand-drawn line with the port name next to each end, as in GNS3. */\nexport function CableEdgeView(p: EdgeProps<CableEdge>) {\n const { id, data, selected } = p;\n const business = useBusiness();\n const { path, middle, a, b } = cableGeometry(p, business);\n const live = useContext(LiveContext)?.cables[id];\n const stroke = selected ? \"var(--signal)\" : live === \"cut\" ? \"var(--destructive)\" : (data?.color ?? (business ? \"#64748b\" : \"var(--foreground)\"));\n const conditions = conditionsLabel(data?.tc);\n return (\n <>\n {/* The straight path is invisible: it only gives the cable a wide, easy target to click. */}\n <BaseEdge id={id} path={path} interactionWidth={18} style={{ stroke: \"transparent\" }} />\n <CableLine p={p} path={path} live={live} stroke={stroke} />\n <EdgeLabelRenderer>\n {live && live !== \"unknown\" && <LiveBadge live={live} at={{ x: middle.x, y: middle.y + (conditions ? 14 : 0) }} />}\n <PortLabel at={a} text={data?.aPort} />\n <PortLabel at={b} text={data?.bPort} />\n {/* A slow or lossy cable says so in its middle. */}\n {conditions && (\n <div style={{ transform: translate(middle) }} className=\"nodrag nopan pointer-events-none absolute rounded-sm border bg-pastel-yellow px-1 py-px font-mono text-[10px] leading-none whitespace-nowrap text-foreground\">\n {conditions}\n </div>\n )}\n </EdgeLabelRenderer>\n </>\n );\n}\n", "import type { LinkConditions } from \"./model\";\n\n/** Isoloom's `tc` for a slow or lossy link, as the engine's topology takes it. */\nexport interface Tc {\n delay?: string;\n jitter?: string;\n loss?: number;\n rate?: string;\n}\n\n/** Whether a field holds a number: every finite one is written, for Isoloom to judge (it reports a loss above 100%, or a jitter without a delay). */\nconst isSet = (n: number | undefined): n is number => typeof n === \"number\" && Number.isFinite(n);\n\n/** Whether `n` is a whole number, give or take what floating point loses in a multiplication. */\nconst whole = (n: number) => Math.abs(n - Math.round(n)) < 1e-9;\n\n/** A rate (Mbit/s) as `tc` writes one: whole Mbit/s, else whole kbit/s, else bits. */\nfunction rateText(rate: number): string {\n if (Number.isInteger(rate)) return `${String(rate)}mbit`;\n if (whole(rate * 1000)) return `${String(Math.round(rate * 1000))}kbit`;\n return `${String(rate * 1_000_000)}bit`;\n}\n\n/** The conditions as Isoloom's `tc` takes them, or `undefined` when none is set. */\nexport function tcOf(c: LinkConditions | undefined): Tc | undefined {\n if (!c) return undefined;\n const tc = {\n ...(isSet(c.delay) ? { delay: `${String(c.delay)}ms` } : {}),\n ...(isSet(c.jitter) ? { jitter: `${String(c.jitter)}ms` } : {}),\n ...(isSet(c.loss) ? { loss: c.loss } : {}),\n ...(isSet(c.rate) ? { rate: rateText(c.rate) } : {}),\n };\n return Object.keys(tc).length ? tc : undefined;\n}\n\n/** A short summary for the canvas: `40 ms \u00B15 \u00B7 0.5% \u00B7 10 Mbit/s`. */\nexport function conditionsLabel(c: LinkConditions | undefined): string {\n if (!tcOf(c) || !c) return \"\";\n const parts: string[] = [];\n const jitter = isSet(c.jitter) ? ` \u00B1${String(c.jitter)}` : \"\";\n if (isSet(c.delay)) parts.push(`${String(c.delay)} ms${jitter}`);\n else if (jitter) parts.push(`${jitter.trim()} ms`);\n if (isSet(c.loss)) parts.push(`${String(c.loss)}%`);\n if (isSet(c.rate)) parts.push(`${String(c.rate)} Mbit/s`);\n return parts.join(\" \u00B7 \");\n}\n\n/** The `tc` fields written as a number and a unit: two times and a rate. */\ntype MeasuredField = \"delay\" | \"jitter\" | \"rate\";\n\n/** A `tc` value the editor can't read: left out of the drawing and reported, never guessed. */\nexport interface TcProblem {\n field: MeasuredField;\n value: string;\n}\n\n/** A `tc` read back: the editor's numbers (none when nothing is set), and each value it couldn't read. */\nexport interface ReadConditions {\n conditions: LinkConditions | undefined;\n problems: TcProblem[];\n}\n\n/** A unit as `[times, per]`: a value in it is `value * times / per` in the editor's unit. */\ntype Scale = readonly [times: number, per: number];\n\n/** The time units Isoloom's `tc` takes, to milliseconds. */\nconst TIME: ReadonlyMap<string, Scale> = new Map([\n [\"us\", [1, 1000]],\n [\"ms\", [1, 1]],\n [\"s\", [1000, 1]],\n]);\n\n/** The rate units Isoloom's `tc` takes, to Mbit/s: `bps` counts bytes. A rate has its unit: Isoloom refuses a bare number. */\nconst RATE: ReadonlyMap<string, Scale> = new Map([\n [\"bit\", [1, 1_000_000]],\n [\"kbit\", [1, 1000]],\n [\"mbit\", [1, 1]],\n [\"gbit\", [1000, 1]],\n [\"bps\", [8, 1_000_000]],\n [\"kbps\", [8, 1000]],\n [\"mbps\", [8, 1]],\n [\"gbps\", [8000, 1]],\n]);\n\nconst UNITS: Record<MeasuredField, ReadonlyMap<string, Scale>> = { delay: TIME, jitter: TIME, rate: RATE };\n\n/**\n * A number and the letters after it, split as Isoloom splits a `tc` value: the letters at the end\n * are the unit, and what comes before is a number as Rust reads one (a sign, digits with or\n * without a point, an exponent: `40`, `-0.5`, `.5`, `5.`, `1E-3`).\n */\nconst MEASURE = /^([+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][+-]?\\d+)?)([A-Za-z]*)$/;\n\n/** `40ms` -> 40, `500us` -> 0.5, `1gbit` -> 1000: in the editor's unit, or undefined when `v` isn't a number and one of `units` (Isoloom's, case and all), or too large to be one. */\nfunction measure(v: string, units: ReadonlyMap<string, Scale>): number | undefined {\n const m = MEASURE.exec(v);\n const scale = m ? units.get(m[2]) : undefined;\n if (!m || !scale) return undefined;\n const n = (Number(m[1]) * scale[0]) / scale[1];\n return Number.isFinite(n) ? n : undefined;\n}\n\n/** Isoloom's `tc` back to the editor's numbers: the inverse of `tcOf`, every value it can't read reported. */\nexport function conditionsOf(tc: Tc | undefined): ReadConditions {\n const conditions: LinkConditions = {};\n const problems: TcProblem[] = [];\n for (const field of [\"delay\", \"jitter\", \"rate\"] as const) {\n const value = tc?.[field];\n if (value === undefined) continue;\n const n = measure(value, UNITS[field]);\n if (n === undefined) problems.push({ field, value });\n else conditions[field] = n;\n }\n if (tc?.loss !== undefined) conditions.loss = tc.loss;\n return { conditions: Object.keys(conditions).length ? conditions : undefined, problems };\n}\n\n/** What each field takes, as the fix a problem names. */\nconst EXPECTED: Record<MeasuredField, string> = { delay: \"a time like 40ms, 500us or 1s\", jitter: \"a time like 40ms, 500us or 1s\", rate: \"a rate like 10mbit or 512kbit\" };\n\n/** A problem in words, for the `tc` at path `at` in the topology: where, the value, the form it takes. */\nexport function tcProblemText(at: string, p: TcProblem): string {\n return `${at}.${p.field}: \\`${p.value}\\` isn't ${EXPECTED[p.field]}; the drawing leaves it out`;\n}\n\n/** The conditions a field edit leaves: a positive number, or the field cleared (none when all are). */\nexport function withCondition(value: LinkConditions | undefined, key: keyof LinkConditions, raw: string): LinkConditions | undefined {\n const n = raw === \"\" ? undefined : Number(raw);\n const next = { ...value, [key]: n !== undefined && Number.isFinite(n) && n > 0 ? n : undefined };\n // Every field it has, even one a stored lab carries that the editor doesn't know.\n return Object.values(next as Record<string, number | undefined>).some((v) => v !== undefined) ? next : undefined;\n}\n", "import { createContext } from \"react\";\nimport type { LiveView } from \"@/lib/tool/live\";\nimport type { Side } from \"@/lib/tool/model\";\nimport type { Addresses, RouterPorts } from \"@/lib/tool/router-ports\";\n\n/** What the canvas's nodes and cables read from the editor, without props through React Flow. */\n\n/** Each machine's addresses (from the engine), by machine name: [network, IPv4][]. */\nexport const AddressesContext = createContext<Addresses>({});\n\n/** Each real router's interfaces, by node id. */\nexport const PortsContext = createContext<Partial<Record<string, RouterPorts>>>({});\n\n/** The running lab as the desktop app reads it (null: not running, or in a browser). */\nexport const LiveContext = createContext<LiveView | null>(null);\n\n/** The LAN border each appliance sits on, by node id (so its port can face out), and the side each switch or router port faces, by `<id>:<port>`. */\nexport const SidesContext = createContext<Partial<Record<string, Side>>>({});\n", "\"use client\";\n\nimport { createContext, useContext } from \"react\";\nimport rough from \"roughjs\";\nimport { cn } from \"@/lib/utils\";\nimport type { Design } from \"@/lib/tool/model\";\n\n/**\n * The whiteboard look: boxes and cables drawn by rough.js (the library behind Excalidraw), kept\n * gentle so the diagram stays clear. Each shape has a fixed seed, so its wobble doesn't change\n * from one render to the next.\n */\nexport const gen = rough.generator();\nexport const SKETCH = { roughness: 1.15, bowing: 1 };\n\n/**\n * The canvas's look: the hand-drawn sketch (default), or business: crisp single lines, the plain\n * sans, muted fills, for a diagram that goes into a report. The fonts and colors switch through\n * CSS (`data-design` on the canvas); the strokes switch here.\n */\nexport const DesignContext = createContext<Design>(\"sketch\");\nconst CRISP = { roughness: 0, bowing: 0, disableMultiStroke: true, disableMultiStrokeFill: true, preserveVertices: true };\n\n/** The stroke options for this design (rough.js draws both: at roughness 0 a line is straight). */\nexport function useSketch() {\n return useContext(DesignContext) === \"business\" ? CRISP : SKETCH;\n}\n\n/** Whether the canvas is in the business look. */\nexport function useBusiness(): boolean {\n return useContext(DesignContext) === \"business\";\n}\n\nexport function seedOf(id: string): number {\n let h = 7;\n for (const ch of id) h = (h * 31 + ch.charCodeAt(0)) % 2147483647;\n return h || 1;\n}\n\nexport type Drawable = ReturnType<typeof gen.rectangle>;\n\n/** rough.js output as SVG paths; \"F\" and \"S\" stand for the fill and stroke we style with CSS. */\nexport function Sketch({\n drawable,\n fill,\n stroke,\n opacity = 1,\n dash,\n}: {\n drawable: Drawable;\n fill?: string;\n stroke: string;\n opacity?: number;\n /** rough.js returns the path only: a dash pattern has to be applied here. */\n dash?: string;\n}) {\n return (\n <>\n {gen.toPaths(drawable).map((p, i) => (\n <path\n key={i}\n d={p.d}\n style={{\n fill: p.fill === \"F\" && fill ? fill : \"none\",\n stroke: p.stroke === \"S\" ? stroke : \"none\",\n strokeWidth: p.strokeWidth,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeDasharray: p.stroke === \"S\" ? dash : undefined,\n opacity,\n }}\n />\n ))}\n </>\n );\n}\n\ninterface FrameProps {\n drawable: Drawable;\n fill: string;\n selected: boolean;\n dim?: boolean;\n /** Business: network equipment, drawn as a dark faceplate instead of a card. */\n hardware?: boolean;\n}\n\n/** Business, network equipment: a dark faceplate with a screw at each end (its rack ears). */\nfunction Faceplate({ selected, dim }: { selected: boolean; dim: boolean }) {\n return (\n <div\n aria-hidden\n className={cn(\n \"pointer-events-none absolute inset-0 rounded-md border border-black/70 shadow-[inset_0_1px_0_rgb(255_255_255/0.09),0_1px_2px_rgb(15_23_42/0.25),0_10px_24px_-12px_rgb(15_23_42/0.55)]\",\n selected && \"ring-2 ring-signal ring-offset-2 ring-offset-background\",\n dim && \"opacity-55 saturate-0\",\n )}\n style={{ background: \"linear-gradient(180deg, #2c3646 0%, #1b2230 100%)\" }}\n >\n {[\"left-1.5\", \"right-1.5\"].map((side) => (\n <span key={side} className={cn(\"absolute top-1/2 size-[7px] -translate-y-1/2 rounded-full bg-[#0e131b] ring-1 ring-white/15\", side)} />\n ))}\n </div>\n );\n}\n\n/**\n * A node's frame. Sketch: the hand-drawn shape in its pastel. Business: a card, as in a network\n * diagram tool: rounded corners, a hairline border, a soft shadow (or, for network equipment, a\n * dark faceplate).\n */\nexport function Frame({ drawable, fill, selected, dim = false, hardware = false }: FrameProps) {\n if (!useBusiness()) {\n return (\n <svg aria-hidden className={cn(\"pointer-events-none absolute inset-0 overflow-visible\", dim && \"opacity-40\")} width=\"100%\" height=\"100%\">\n <Sketch drawable={drawable} fill={fill} stroke={selected ? \"var(--signal)\" : \"var(--foreground)\"} opacity={selected ? 1 : 0.8} />\n </svg>\n );\n }\n if (hardware) return <Faceplate selected={selected} dim={dim} />;\n return (\n <div\n aria-hidden\n className={cn(\n \"pointer-events-none absolute inset-0 overflow-hidden rounded-lg border bg-card shadow-[0_1px_2px_rgb(15_23_42/0.06),0_4px_12px_-6px_rgb(15_23_42/0.12)] transition-shadow\",\n selected ? \"border-signal ring-2 ring-signal/25\" : \"border-border group-hover:border-foreground/25\",\n dim && \"border-dashed bg-muted/60 shadow-none\",\n )}\n ></div>\n );\n}\n", "\"use client\";\n\nimport { useContext, useMemo } from \"react\";\nimport { Handle, NodeResizer, Position, useReactFlow, type NodeProps } from \"@xyflow/react\";\nimport { Eye, EyeOff, Globe, GlobeLock } from \"lucide-react\";\nimport { conditionsLabel } from \"@/lib/tool/conditions\";\nimport { LAN_H, LAN_W, cleanName, type LanData, type LanNode } from \"@/lib/tool/model\";\nimport { vlanColor, vlanOf } from \"@/lib/tool/vlans\";\nimport { cn } from \"@/lib/utils\";\nimport { useText } from \"../text\";\nimport { AddressesContext, LiveContext } from \"./contexts\";\nimport { InlineText } from \"./inline-text\";\nimport { SKETCH, Sketch, gen, seedOf, useSketch, type Drawable } from \"./sketch\";\n\nconst SIDES = [\n [\"top\", Position.Top],\n [\"right\", Position.Right],\n [\"bottom\", Position.Bottom],\n [\"left\", Position.Left],\n] as const;\n\n/** Business: a panel, its header a band in the LAN's color. */\nfunction LanPanel({ tint, selected }: { tint: string | null; selected: boolean }) {\n const color = tint ?? \"#2563eb\";\n return (\n <div\n aria-hidden\n className={cn(\"pointer-events-none absolute inset-0 rounded-xl border\", selected && \"ring-2 ring-signal/25\")}\n style={{ background: `color-mix(in oklab, ${color} 4%, var(--background))`, borderColor: selected ? \"var(--signal)\" : `color-mix(in oklab, ${color} 30%, var(--border))` }}\n >\n <div className=\"h-10 rounded-t-xl border-b\" style={{ background: `color-mix(in oklab, ${color} 9%, var(--background))`, borderColor: `color-mix(in oklab, ${color} 18%, var(--border))` }} />\n </div>\n );\n}\n\n/** Sketch: a dashed area in the LAN's tint (a VLAN's color), or a pale blue. */\nfunction LanSketch({ frame, tint, selected, w, h }: { frame: Drawable; tint: string | null; selected: boolean; w: number; h: number }) {\n return (\n <svg aria-hidden className=\"pointer-events-none absolute inset-0 overflow-visible\" width={w} height={h}>\n <Sketch\n drawable={frame}\n fill={tint ? `color-mix(in oklab, ${tint} 9%, transparent)` : \"color-mix(in oklab, var(--pastel-blue) 45%, transparent)\"}\n stroke={selected ? \"var(--signal)\" : (tint ?? \"var(--muted-foreground)\")}\n dash=\"10 7\"\n />\n </svg>\n );\n}\n\n/** Where cables plug in (kept while the area is hidden, cables may hang on them), and the border: the LAN's grip, to move it and everything in it. */\nfunction LanGrips({ hidden }: { hidden: boolean }) {\n const grips = [\"top-0 inset-x-0 h-3 -translate-y-1/2\", \"bottom-0 inset-x-0 h-3 translate-y-1/2\", \"left-0 inset-y-0 w-3 -translate-x-1/2\", \"right-0 inset-y-0 w-3 translate-x-1/2\"] as const;\n return (\n <>\n {SIDES.map(([side, position]) => (\n <Handle\n key={side}\n id={side}\n type=\"source\"\n position={position}\n style={hidden ? { opacity: 0 } : undefined}\n className=\"pointer-events-auto !z-10 !size-3 !border-2 !border-background !bg-muted-foreground/40 transition-colors hover:!bg-signal\"\n />\n ))}\n {!hidden && grips.map((place) => <div key={place} aria-hidden className={cn(\"lan-handle pointer-events-auto absolute cursor-move\", place)} />)}\n </>\n );\n}\n\n/** Business: how many machines a LAN has. */\nfunction LanHosts({ name }: { name: string }) {\n const t = useText().canvas;\n const n = Object.values(useContext(AddressesContext)).filter((ips) => ips?.some(([net]) => net === name)).length;\n return <span className=\"rounded-sm px-1 text-[10px] whitespace-nowrap text-muted-foreground\">{t.hosts(n)}</span>;\n}\n\n/** A running LAN's ports up, out of all: green when all are, amber when some aren't. */\nfunction LanLive({ name }: { name: string }) {\n const t = useText().canvas.live;\n const lan = useContext(LiveContext)?.lans[name];\n if (!lan?.total) return null;\n const all = lan.up === lan.total;\n return (\n <span title={t.lanPorts(lan.up, lan.total)} className={cn(\"flex items-center gap-1 rounded-sm px-1 font-mono text-[10px] whitespace-nowrap\", all ? \"bg-success/15 text-success\" : \"bg-warning/20 text-foreground\")}>\n <span className={cn(\"size-1.5 rounded-full\", all ? \"bg-success\" : \"bg-warning\")} aria-hidden />\n {lan.up}/{lan.total}\n </span>\n );\n}\n\n/** The label: also a grip; double-click the name or the block to edit them in place. */\nfunction LanLabel({ id, data, crisp }: { id: string; data: LanData; crisp: boolean }) {\n const t = useText().canvas;\n const { updateNodeData } = useReactFlow();\n const hidden = !!data.hidden;\n const conditions = conditionsLabel(data.tc);\n const toggle = \"nodrag grid size-5 place-items-center rounded text-muted-foreground hover:bg-muted hover:text-foreground\";\n return (\n <div className=\"lan-handle pointer-events-auto absolute top-1.5 left-2 flex cursor-move items-center gap-2 rounded-md px-1.5 py-1 hover:bg-background/70\">\n <InlineText label={t.lanName} value={data.name} clean={cleanName} onCommit={(name) => { updateNodeData(id, { name }); }} className=\"font-heading text-base font-semibold\" />\n <InlineText\n label={t.addressBlock}\n value={data.cidr}\n clean={(v) => v.replace(/[^0-9./]/g, \"\")}\n onCommit={(cidr) => { updateNodeData(id, { cidr }); }}\n className=\"font-mono text-[11px] text-muted-foreground in-data-[design=business]:rounded in-data-[design=business]:border in-data-[design=business]:bg-background in-data-[design=business]:px-1.5 in-data-[design=business]:py-px\"\n />\n {conditions && <span className=\"rounded-sm bg-pastel-yellow/70 px-1 font-mono text-[10px] whitespace-nowrap text-foreground\">{conditions}</span>}\n {crisp && <LanHosts name={data.name} />}\n <LanLive name={data.name} />\n <button type=\"button\" onClick={() => { updateNodeData(id, { internet: !data.internet }); }} title={data.internet ? t.internetOnTitle : t.internetOffTitle} aria-label={data.internet ? t.internetOn : t.internetOff} className={toggle}>\n {data.internet ? <Globe className=\"size-3.5\" /> : <GlobeLock className=\"size-3.5 text-warning\" />}\n </button>\n <button type=\"button\" onClick={() => { updateNodeData(id, { hidden: !hidden }); }} title={hidden ? t.showAreaTitle : t.hideAreaTitle} aria-label={hidden ? t.showArea : t.hideArea} className={toggle}>\n {hidden ? <EyeOff className=\"size-3.5\" /> : <Eye className=\"size-3.5\" />}\n </button>\n </div>\n );\n}\n\n/**\n * A LAN on the canvas: a sketched, dashed area behind the machines, with its name and block.\n * Machines inside it are on it; a cable from a machine to its edge puts that machine on it too\n * (how a router joins several LANs). Resizable from its corners when selected.\n */\nexport function LanNodeView({ id, data, selected, width, height }: NodeProps<LanNode>) {\n const hidden = !!data.hidden;\n // A LAN named vlan<n> is that VLAN: it takes the VLAN's color, as on the switches.\n const vlan = vlanOf(data.name);\n const tint = vlan === null ? null : vlanColor(vlan);\n const w = width ?? LAN_W;\n const h = height ?? LAN_H;\n const sketch = useSketch();\n const frame = useMemo(\n () => gen.rectangle(2, 2, w - 4, h - 4, { ...sketch, roughness: sketch.roughness && 0.8, seed: seedOf(id), fill: \"F\", fillStyle: \"solid\", stroke: \"S\", strokeWidth: selected ? 2 : 1.4 }),\n [id, w, h, selected, sketch],\n );\n return (\n <div style={{ width: w, height: h }} className=\"group relative\">\n <NodeResizer isVisible={selected} minWidth={200} minHeight={160} lineClassName=\"!border-transparent\" handleClassName=\"pointer-events-auto !z-10 !size-2.5 !rounded-sm !border-signal !bg-background\" />\n {/* Hidden: no rectangle, no grips; the label stays, to edit the LAN or show it again. */}\n {!hidden && sketch === SKETCH && <LanSketch frame={frame} tint={tint} selected={selected} w={w} h={h} />}\n {!hidden && sketch !== SKETCH && <LanPanel tint={tint} selected={selected} />}\n <LanGrips hidden={hidden} />\n <LanLabel id={id} data={data} crisp={sketch !== SKETCH} />\n </div>\n );\n}\n", "\"use client\";\n\nimport { useState, type KeyboardEvent } from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { useText } from \"../text\";\n\ninterface InlineTextProps {\n value: string;\n onCommit: (v: string) => void;\n clean?: (v: string) => string;\n className?: string;\n label: string;\n /** Clearing the field means something (e.g. \"back to automatic\"), so an empty value counts. */\n allowEmpty?: boolean;\n}\n\n/** The field while editing: as wide as the text, not the box around it. */\nfunction InlineField({ draft, setDraft, done, clean, className, label }: { draft: string; setDraft: (v: string) => void; done: (keep: boolean) => void } & Pick<InlineTextProps, \"clean\" | \"className\" | \"label\">) {\n return (\n <input\n autoFocus\n aria-label={label}\n value={draft}\n // As wide as the text, not the box around it: the width follows what is typed.\n size={1}\n style={{ width: `${String(Math.max(3, draft.length) + 1.5)}ch`, fieldSizing: \"content\", minWidth: \"3ch\" }}\n onChange={(e) => {\n setDraft(clean ? clean(e.target.value) : e.target.value);\n }}\n onBlur={() => {\n done(true);\n }}\n onKeyDown={(e: KeyboardEvent) => {\n e.stopPropagation();\n if (e.key === \"Enter\") done(true);\n if (e.key === \"Escape\") done(false);\n }}\n className={cn(\"nodrag nopan w-auto max-w-[260px] rounded-sm bg-background px-0.5 outline-none ring-2 ring-signal\", className)}\n />\n );\n}\n\n/**\n * Text edited in place, as in Excalidraw: double-click to edit, Enter or a click elsewhere to\n * keep, Escape to drop. `nodrag` so typing never moves the node.\n */\nexport function InlineText({ value, onCommit, clean, className, label, allowEmpty = false }: InlineTextProps) {\n const t = useText().canvas;\n const [draft, setDraft] = useState<string | null>(null);\n if (draft === null) {\n return (\n <span\n title={t.editTitle(label)}\n onDoubleClick={(e) => {\n e.stopPropagation();\n setDraft(value);\n }}\n className={cn(\"cursor-text\", className)}\n >\n {value || t.unnamed}\n </span>\n );\n }\n const done = (keep: boolean) => {\n if (keep && (draft.trim() || allowEmpty)) onCommit(draft.trim());\n setDraft(null);\n };\n return <InlineField draft={draft} setDraft={setDraft} done={done} clean={clean} className={className} label={label} />;\n}\n", "\"use client\";\n\nimport { useContext, useMemo } from \"react\";\nimport { Handle, Position, useReactFlow, type NodeProps } from \"@xyflow/react\";\nimport { MACHINE_H, MACHINE_W, cleanName, type MachineData, type MachineNode, type Side } from \"@/lib/tool/model\";\nimport { cn } from \"@/lib/utils\";\nimport { useText } from \"../text\";\nimport { LiveContext, SidesContext } from \"./contexts\";\nimport { DeviceIcon, accentFor, pastelFor, roleOf } from \"./device-icon\";\nimport { InlineText } from \"./inline-text\";\nimport { MachineAddresses, MachineFacts } from \"./machine-addresses\";\nimport { RouterFaceplate } from \"./router-node\";\nimport { Frame, gen, seedOf, useBusiness, useSketch } from \"./sketch\";\nimport { StatusDot } from \"./status-dot\";\nimport { useRemeasure } from \"./use-measured-ports\";\n\n/** A machine on the canvas: a hand-drawn box in its pastel, its logo and name, a socket per side. */\nexport function MachineNodeView(props: NodeProps<MachineNode>) {\n // A router you configure is drawn as its faceplate; the automatic one stays a box.\n if (props.data.icon === \"router\" && props.data.kind !== \"router\") return <RouterFaceplate {...props} />;\n return <MachineBox {...props} />;\n}\n\nconst HANDLE = \"!size-3 !border-2 !border-background !bg-foreground/50 transition-colors group-hover:!bg-signal\";\n\n/**\n * Where cables plug in. An appliance: its outside port (every cable when it stands alone; on a\n * LAN's edge, the cables to the other network), facing out of the LAN, and on a LAN's edge its\n * inside port. Another machine: its top and bottom.\n */\nfunction MachineHandles({ appliance, side }: { appliance: boolean; side: Side | undefined }) {\n if (!appliance) {\n return ([\"top\", \"bottom\"] as const).map((h) => (\n <Handle key={h} id={h} type=\"source\" position={h === \"top\" ? Position.Top : Position.Bottom} className=\"!size-2.5 !border-2 !border-background !bg-foreground/40 transition-colors group-hover:!bg-signal\" />\n ));\n }\n return (\n <>\n <Handle id=\"port\" type=\"source\" position={side === \"bottom\" ? Position.Bottom : Position.Top} className={HANDLE} />\n {side && <Handle id=\"lan\" type=\"source\" position={side === \"bottom\" ? Position.Top : Position.Bottom} className={HANDLE} />}\n </>\n );\n}\n\n/** What the machine runs as, and whether it is the access machine (two pieces of text, as drawn). */\nfunction KindLine({ data }: { data: MachineData }) {\n const t = useText().canvas;\n return (\n <>\n {data.kind === \"vm\" ? t.vm : data.kind === \"router\" ? t.automatic : t.container}\n {data.access ? ` \u00B7 ${t.access}` : \"\"}\n </>\n );\n}\n\n/** Business: an asset card, its icon tinted, its name and role, then its facts. */\nfunction BusinessBody({ id, data, down }: { id: string; data: MachineData; down: boolean }) {\n const t = useText().canvas;\n const { updateNodeData } = useReactFlow();\n return (\n <div className={cn(\"relative flex w-full flex-col items-start self-stretch px-2.5 pt-2.5\", down && \"opacity-50\")}>\n <div className=\"flex w-full min-w-0 items-center gap-2\">\n <DeviceIcon data={data} size=\"sm\" accent={accentFor(data)} />\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-[12.5px] leading-tight font-semibold tracking-tight\">\n <InlineText label={t.machineName} value={data.name} clean={cleanName} onCommit={(name) => { updateNodeData(id, { name }); }} />\n </div>\n <div className=\"mt-0.5 truncate text-[10px] leading-tight text-muted-foreground\">{t.roles[roleOf(data)]}</div>\n </div>\n </div>\n <div className=\"mt-1.5 text-[8.5px] leading-none font-semibold tracking-wider text-muted-foreground/80 uppercase\"><KindLine data={data} /></div>\n <MachineFacts id={id} data={data} />\n </div>\n );\n}\n\n/** Sketch: the logo, the name, what it runs as. */\nfunction SketchBody({ id, data, down }: { id: string; data: MachineData; down: boolean }) {\n const t = useText().canvas;\n const { updateNodeData } = useReactFlow();\n return (\n <div className={cn(\"relative flex flex-col items-center gap-1\", down && \"opacity-50\")}>\n <DeviceIcon data={data} />\n <div className=\"max-w-[104px] truncate font-heading text-sm leading-tight font-semibold\">\n <InlineText label={t.machineName} value={data.name} clean={cleanName} onCommit={(name) => { updateNodeData(id, { name }); }} />\n </div>\n <div className=\"text-[10px] leading-none text-muted-foreground in-data-[design=business]:text-[9px] in-data-[design=business]:font-medium in-data-[design=business]:tracking-wider in-data-[design=business]:uppercase\">\n <KindLine data={data} />\n </div>\n </div>\n );\n}\n\nfunction MachineBox({ id, data, selected }: NodeProps<MachineNode>) {\n const side = useContext(SidesContext)[id];\n // React Flow caches where handles are: re-measure when the port flips.\n useRemeasure(id, side);\n const sketch = useSketch();\n const box = useMemo(\n () => gen.rectangle(3, 3, MACHINE_W - 6, MACHINE_H - 6, { ...sketch, seed: seedOf(id), fill: \"F\", fillStyle: \"solid\", stroke: \"S\", strokeWidth: selected ? 2.25 : 1.4 }),\n [id, selected, sketch],\n );\n const down = useContext(LiveContext)?.machines[data.name]?.status === \"down\";\n const business = useBusiness();\n return (\n <div style={{ width: MACHINE_W, height: MACHINE_H }} className={cn(\"group relative flex flex-col items-center gap-1\", business ? \"justify-start\" : \"justify-center px-2\")}>\n <Frame drawable={box} fill={pastelFor(data)} selected={selected} dim={down} />\n <StatusDot name={data.name} className=\"-top-1 -right-1\" />\n <MachineHandles appliance={data.icon === \"router\" || data.icon === \"shield\"} side={side} />\n {business ? <BusinessBody id={id} data={data} down={down} /> : <SketchBody id={id} data={data} down={down} />}\n {!business && <MachineAddresses id={id} data={data} />}\n </div>\n );\n}\n", "\"use client\";\n\nimport type { CSSProperties } from \"react\";\nimport { Container, Laptop, Monitor, Router, Server, Shield, type LucideIcon } from \"lucide-react\";\nimport type { SimpleIcon } from \"simple-icons\";\nimport { dockerLogo, isDark, logoFor } from \"@/lib/tool/logos\";\nimport type { IconId, MachineData } from \"@/lib/tool/model\";\nimport { cn } from \"@/lib/utils\";\n\n/** By icon id; a node from a link or an old draft may name one we don't have: a container then. */\nconst ICONS: Partial<Record<string, LucideIcon>> = {\n container: Container,\n server: Server,\n router: Router,\n shield: Shield,\n monitor: Monitor,\n laptop: Laptop,\n};\n\n/** What a machine is for, as people say it: its role in the lab. */\nexport function roleOf(m: Pick<MachineData, \"kind\" | \"icon\" | \"image\">): \"router\" | \"firewall\" | \"workstation\" | \"server\" | \"desktop\" | \"host\" {\n if (m.icon === \"router\") return \"router\";\n if (m.icon === \"shield\") return \"firewall\";\n if (m.icon === \"laptop\") return \"workstation\";\n if (m.icon === \"server\") return \"server\";\n if (m.icon === \"monitor\") return m.kind === \"vm\" ? \"host\" : \"desktop\";\n return \"host\";\n}\n\n/** Business: a device's accent, by what it is (the pastels' strong counterparts). */\nexport function accentFor(m: Pick<MachineData, \"kind\" | \"icon\">): string {\n if (m.icon === \"router\") return \"#d97706\";\n if (m.icon === \"shield\") return \"#dc2626\";\n if (m.icon === \"laptop\") return \"#7c3aed\";\n return m.kind === \"vm\" ? \"#0d9488\" : \"#2563eb\";\n}\n\n/** Each kind of device has its pastel, as on a whiteboard. */\nexport function pastelFor(m: Pick<MachineData, \"kind\" | \"icon\">): string {\n if (m.icon === \"router\") return \"var(--pastel-yellow)\";\n if (m.icon === \"shield\") return \"var(--pastel-red)\";\n if (m.icon === \"laptop\") return \"var(--pastel-violet)\";\n return m.kind === \"vm\" ? \"var(--pastel-green)\" : \"var(--pastel-blue)\";\n}\n\n/** Roles whose icon says more than the OS logo would: the logo becomes a small badge. */\nconst ROLE_ICONS: IconId[] = [\"router\", \"laptop\", \"shield\"];\n\n/**\n * A brand logo in its own color. On the dark theme the color is lifted toward white, so deep\n * brand colors (Alpine, Kali, PostgreSQL) stay readable while keeping their hue.\n */\nfunction BrandLogo({ icon, className }: { icon: SimpleIcon; className?: string }) {\n const dark = isDark(icon.hex);\n return (\n <svg\n viewBox=\"0 0 24 24\"\n role=\"img\"\n aria-label={icon.title}\n className={cn(className, !dark && \"fill-[var(--logo)] dark:fill-[color-mix(in_oklab,var(--logo)_60%,white)]\")}\n style={{ \"--logo\": `#${icon.hex}` } as CSSProperties}\n >\n <path d={icon.path} fill={dark ? \"currentColor\" : undefined} />\n </svg>\n );\n}\n\n/** The tile's look: tinted with the accent (business), the pastel (a small one), or plain. */\nfunction tileStyle(data: Pick<MachineData, \"kind\" | \"icon\">, size: \"sm\" | \"md\", accent: string | undefined): CSSProperties | undefined {\n if (accent) return { backgroundColor: `color-mix(in oklab, ${accent} 11%, var(--card))`, boxShadow: `inset 0 0 0 1px color-mix(in oklab, ${accent} 22%, transparent)` };\n return size === \"sm\" ? { backgroundColor: pastelFor(data) } : undefined;\n}\n\n/**\n * A device's picture: the logo of what it runs (its OS or image) when we know one, otherwise\n * a generic icon. Routers and workstations keep their role icon, with the OS logo as a badge.\n */\nexport function DeviceIcon({\n data,\n size = \"md\",\n accent,\n}: {\n data: Pick<MachineData, \"kind\" | \"image\" | \"os\" | \"icon\">;\n size?: \"sm\" | \"md\";\n /** Business: the tile takes this tint, its glyph this color. */\n accent?: string;\n}) {\n const logo = logoFor(data) ?? (data.kind === \"container\" ? dockerLogo : null);\n const role = ROLE_ICONS.includes(data.icon);\n const Icon = ICONS[data.icon] ?? Container;\n const glyph = size === \"md\" ? \"size-6\" : \"size-4\";\n return (\n <span\n className={cn(\"relative grid shrink-0 place-items-center bg-background text-foreground ring-1 ring-foreground/10\", size === \"md\" ? \"size-11 rounded-lg\" : \"size-8 rounded-md\")}\n style={tileStyle(data, size, accent)}\n >\n {logo && !role ? <BrandLogo icon={logo} className={cn(glyph, \"text-foreground\")} /> : <Icon className={glyph} style={accent ? { color: accent } : undefined} aria-hidden />}\n {logo && role && (\n <span className=\"absolute -right-1.5 -bottom-1.5 grid size-5 place-items-center rounded-full border bg-card shadow-sm\">\n <BrandLogo icon={logo} className=\"size-3 text-foreground\" />\n </span>\n )}\n </span>\n );\n}\n", "import {\n siAlmalinux,\n siAlpinelinux,\n siApache,\n siCentos,\n siDebian,\n siDocker,\n siElasticsearch,\n siFedora,\n siGitlab,\n siGrafana,\n siJenkins,\n siKalilinux,\n siKibana,\n siLinux,\n siMariadb,\n siMongodb,\n siMysql,\n siNginx,\n siNodedotjs,\n siPostgresql,\n siPrometheus,\n siPython,\n siRedis,\n siRockylinux,\n siTraefikproxy,\n siUbuntu,\n siWireshark,\n type SimpleIcon,\n} from \"simple-icons\";\nimport { imageName, type MachineData } from \"./model\";\n\n/**\n * A machine's logo, from what it runs: the VM's OS, or the container's image. Logos are from\n * Simple Icons (there is none for Windows: Microsoft had theirs removed), so a Windows VM, a\n * router or an image we don't recognise keeps its generic icon.\n */\n\nconst BY_OS: [prefix: string, icon: SimpleIcon][] = [\n [\"debian\", siDebian],\n [\"ubuntu\", siUbuntu],\n [\"kali\", siKalilinux],\n [\"rocky\", siRockylinux],\n [\"alma\", siAlmalinux],\n [\"centos\", siCentos],\n [\"fedora\", siFedora],\n];\n\n/** Image name (its last path segment, without the tag) \u2192 logo. */\nconst BY_IMAGE: [name: string, icon: SimpleIcon][] = [\n [\"nginx\", siNginx],\n [\"alpine\", siAlpinelinux],\n [\"postgres\", siPostgresql],\n [\"mysql\", siMysql],\n [\"mariadb\", siMariadb],\n [\"redis\", siRedis],\n [\"mongo\", siMongodb],\n [\"httpd\", siApache],\n [\"node\", siNodedotjs],\n [\"python\", siPython],\n [\"grafana\", siGrafana],\n [\"prometheus\", siPrometheus],\n [\"elasticsearch\", siElasticsearch],\n [\"kibana\", siKibana],\n [\"jenkins\", siJenkins],\n [\"gitlab-ce\", siGitlab],\n [\"gitlab-ee\", siGitlab],\n [\"traefik\", siTraefikproxy],\n [\"wireshark\", siWireshark],\n [\"kali-rolling\", siKalilinux],\n [\"debian\", siDebian],\n [\"ubuntu\", siUbuntu],\n [\"rockylinux\", siRockylinux],\n [\"alma\", siAlmalinux],\n [\"centos\", siCentos],\n [\"fedora\", siFedora],\n];\n\nexport function logoFor(m: Pick<MachineData, \"kind\" | \"image\" | \"os\">): SimpleIcon | null {\n if (m.kind === \"vm\") {\n if (m.os.startsWith(\"windows\")) return null;\n return BY_OS.find(([prefix]) => m.os.startsWith(prefix))?.[1] ?? siLinux;\n }\n const name = imageName(m.image);\n return BY_IMAGE.find(([n]) => name === n)?.[1] ?? null;\n}\n\n/** The fallback for a container whose image we don't know: Docker's whale. */\nexport const dockerLogo = siDocker;\n\n/** Brand colors too dark to read on a dark background (AlmaLinux and others use black). */\nexport function isDark(hex: string): boolean {\n const n = parseInt(hex, 16);\n const [r, g, b] = [(n >> 16) & 255, (n >> 8) & 255, n & 255].map((c) => {\n const s = c / 255;\n return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;\n });\n return 0.2126 * r + 0.7152 * g + 0.0722 * b < 0.05;\n}\n", "\"use client\";\n\nimport { useContext } from \"react\";\nimport { useReactFlow } from \"@xyflow/react\";\nimport { Disc3, Package, Pin } from \"lucide-react\";\nimport type { MachineData } from \"@/lib/tool/model\";\nimport { pinned } from \"@/lib/tool/pins\";\nimport { cn } from \"@/lib/utils\";\nimport { useText } from \"../text\";\nimport { AddressesContext, LiveContext } from \"./contexts\";\nimport { InlineText } from \"./inline-text\";\n\n/** A machine's LAN addresses ([network, IPv4]; cables' /29 left out), whether each port is down, and fixing one by hand. */\nfunction useAddresses(id: string, data: MachineData) {\n const { updateNodeData } = useReactFlow();\n const ips = (useContext(AddressesContext)[data.name] ?? []).filter(([net]) => !net.startsWith(\"link-\"));\n const ports = useContext(LiveContext)?.ports;\n // Double-click an address to fix it by hand (same block, a new last number); clear it to go\n // back to the next free one.\n const pin = (net: string, ip: string, typed: string) => {\n const pins = pinned(data.pins, net, ip, typed);\n if (pins) updateNodeData(id, { pins });\n };\n const down = (net: string) => ports?.[`${data.name}/${net}`] === false;\n return { ips, pin, down };\n}\n\n/** An address's tooltip: the network, whether it is fixed, and whether its port is down. */\nfunction useAddressTitle(data: MachineData) {\n const t = useText().canvas;\n return (net: string, down: boolean) => {\n const title = t.addressTitle(net, !!data.pins?.[net]);\n return down ? `${t.live.portDown} \u00B7 ${title}` : title;\n };\n}\n\nconst onlyAddressChars = (v: string) => v.replace(/[^0-9.]/g, \"\");\n\n/** An address, edited in place. */\nfunction Address({ id, data, net, ip, className }: { id: string; data: MachineData; net: string; ip: string; className?: string }) {\n const t = useText().canvas;\n const { pin } = useAddresses(id, data);\n return <InlineText allowEmpty label={t.addressOn(net)} value={ip} clean={onlyAddressChars} onCommit={(v) => { pin(net, ip, v); }} className={className} />;\n}\n\n/** What a machine runs, in a short form: its OS, or its image's last part. */\nfunction runsOf(data: MachineData): string | undefined {\n if (data.kind === \"vm\") return data.os;\n return data.kind === \"container\" ? data.image.split(\"/\").pop() : \"\";\n}\n\n/**\n * Business: what an asset card says about a machine, in labelled rows: its addresses (two at\n * most, then how many more), and what it runs (its image or OS).\n */\nexport function MachineFacts({ id, data }: { id: string; data: MachineData }) {\n const t = useText().canvas;\n const { ips, down } = useAddresses(id, data);\n const title = useAddressTitle(data);\n const runs = runsOf(data);\n const shown = ips.slice(0, 2);\n // The automatic router has no address of its own: nothing to list.\n if (!shown.length && !runs) return null;\n return (\n <dl className=\"mt-2 grid w-full grid-cols-[12px_minmax(0,1fr)] items-center gap-x-1.5 gap-y-[3px] border-t pt-1.5 text-[10px] leading-tight\">\n {shown.map(([net, ip], i) => (\n <div key={net} className=\"contents\">\n <dt className=\"text-[8.5px] font-semibold text-muted-foreground/80\">{i === 0 ? \"IP\" : \"\"}</dt>\n <dd title={title(net, down(net))} className={cn(\"nodrag flex min-w-0 items-center gap-0.5 font-mono\", down(net) && \"text-destructive line-through\")}>\n <Address id={id} data={data} net={net} ip={ip} className=\"truncate\" />\n {data.pins?.[net] !== undefined && <Pin className=\"size-2.5 shrink-0 text-signal\" aria-label={t.fixed} />}\n {i === 1 && ips.length > 2 && (\n <span className=\"shrink-0 font-sans text-muted-foreground\" title={ips.slice(2).map(([n, a]) => `${n}: ${a}`).join(\"\\n\")}>\n +{ips.length - 2}\n </span>\n )}\n </dd>\n </div>\n ))}\n {runs && (\n <>\n <dt className=\"text-muted-foreground/80\" title={data.kind === \"vm\" ? \"OS\" : t.imageShort}>\n {data.kind === \"vm\" ? <Disc3 className=\"size-3\" aria-label=\"OS\" /> : <Package className=\"size-3\" aria-label={t.imageShort} />}\n </dt>\n <dd className=\"truncate font-mono text-muted-foreground\" title={data.kind === \"vm\" ? data.os : data.image}>\n {runs}\n </dd>\n </>\n )}\n </dl>\n );\n}\n\n/** The machine's IPs, under its box, as on a network diagram. */\nexport function MachineAddresses({ id, data }: { id: string; data: MachineData }) {\n const t = useText().canvas;\n const { ips, down } = useAddresses(id, data);\n const title = useAddressTitle(data);\n if (!ips.length) return null;\n return (\n <div className=\"pointer-events-none absolute top-full left-1/2 mt-1.5 flex -translate-x-1/2 flex-col items-center gap-0.5\">\n {ips.map(([net, ip]) => (\n <span\n key={net}\n title={title(net, down(net))}\n className={cn(\n \"nodrag pointer-events-auto flex items-center gap-0.5 rounded-sm bg-background/90 px-1 font-mono text-[10px] leading-tight whitespace-nowrap text-foreground\",\n down(net) && \"text-destructive line-through\",\n )}\n >\n {data.pins?.[net] !== undefined && <Pin className=\"size-2.5 text-signal\" aria-label={t.fixed} />}\n <Address id={id} data={data} net={net} ip={ip} />\n </span>\n ))}\n </div>\n );\n}\n", "/**\n * Fixing a machine's address on a LAN by hand: same block, a new last number (typed alone, or\n * as a whole address); clearing it goes back to the next free one. Null: not a valid address.\n */\nexport function pinned(pins: Record<string, number> | undefined, net: string, ip: string, typed: string): Record<string, number> | null {\n const text = typed.trim();\n if (text === \"\") return Object.fromEntries(Object.entries(pins ?? {}).filter(([n]) => n !== net));\n const base = ip.slice(0, ip.lastIndexOf(\".\") + 1);\n const last = Number(text.startsWith(base) ? text.slice(base.length) : text.split(\".\").pop());\n return Number.isInteger(last) && last > 0 && last < 255 ? { ...pins, [net]: last } : null;\n}\n", "\"use client\";\n\nimport { useContext, useMemo } from \"react\";\nimport { Handle, Position, useReactFlow, type NodeProps } from \"@xyflow/react\";\nimport { Router } from \"lucide-react\";\nimport { APPLIANCES, ROUTER_H, ROUTER_PORTS, ROUTER_W, cleanName, routerPort, type MachineData, type MachineNode } from \"@/lib/tool/model\";\nimport type { RouterPorts } from \"@/lib/tool/router-ports\";\nimport { cn } from \"@/lib/utils\";\nimport { useText } from \"../text\";\nimport { LiveContext, PortsContext, SidesContext } from \"./contexts\";\nimport { InlineText } from \"./inline-text\";\nimport { BUSINESS_SOCKET, PORT_BOX, PortLed } from \"./port-led\";\nimport { Frame, gen, seedOf, useBusiness, useSketch } from \"./sketch\";\nimport { StatusDot } from \"./status-dot\";\nimport { usePortSides } from \"./use-measured-ports\";\n\nconst RPORT = 24;\nconst RPORT_GAP = 8;\nconst RPAD = 14;\n\n/** The router's model under its name: a VM, a Cisco OS, or FRR. */\nfunction modelOf(data: MachineData, vm: string): string {\n if (data.kind === \"vm\") return vm;\n return data.appliance ? `Cisco ${APPLIANCES.find((x) => x.id === data.appliance)?.label.split(\" (\")[0] ?? \"\"}` : \"FRR\";\n}\n\ntype Interface = RouterPorts[\"interfaces\"][number];\n\n/** One port of the faceplate: its name, its square in its network's color, its handle. */\nfunction RouterPort({ id, data, port, i, view }: { id: string; data: MachineData; port: string; i: number; view: RouterPorts }) {\n const t = useText().canvas;\n const tl = useText().canvas.live;\n const sides = useContext(SidesContext);\n const live = useContext(LiveContext);\n const business = useBusiness();\n const x = RPAD + i * (RPORT + RPORT_GAP);\n const color = view.colors[port];\n const nets = view.interfaces.filter((f) => f.name === port || f.name.startsWith(`${port}.`));\n // A port is down when one of its networks' ports is (unknown counts as up).\n const down = nets.some((f) => live?.ports[`${data.name}/${f.network}`] === false);\n const lines = nets.map((f: Interface) => `${f.name}: ${f.network}${f.ip ? ` \u00B7 ${f.ip}` : \"\"}`).join(\"\\n\");\n return (\n <div>\n <span className={cn(\"absolute top-[26px] w-6 text-center font-mono text-[9px] text-muted-foreground\", business && \"text-slate-400\")} style={{ left: x }}>\n {port}\n </span>\n <span\n title={(down ? `${tl.portDown}\\n` : \"\") + (nets.length ? lines : t.portFree(port))}\n className={cn(\"absolute top-[38px]\", PORT_BOX, business && BUSINESS_SOCKET, !business && down && \"border-dashed border-destructive opacity-40\")}\n style={{ left: x, width: RPORT, height: 20, background: business ? \"#0b1017\" : (color ?? \"var(--muted)\") }}\n >\n {business && <PortLed color={down ? \"#ef4444\" : (color ?? null)} />}\n </span>\n <Handle\n id={port}\n type=\"source\"\n position={sides[`${id}:${port}`] === \"top\" ? Position.Top : Position.Bottom}\n style={{ left: x + RPORT / 2 }}\n className=\"!size-2.5 !border-2 !border-background !bg-foreground/50 transition-colors group-hover:!bg-signal\"\n />\n </div>\n );\n}\n\n/** Its interfaces, beside the faceplate: port, address, network. */\nfunction InterfaceList({ data, view }: { data: MachineData; view: RouterPorts }) {\n const live = useContext(LiveContext);\n return (\n <ul className=\"pointer-events-none absolute top-0 left-full ml-3 flex w-max flex-col gap-0.5 font-mono text-[10px]\">\n {view.interfaces.map((f) => (\n <li key={f.name} className={cn(\"flex items-center gap-1.5 rounded-sm bg-background/90 px-1\", live?.ports[`${data.name}/${f.network}`] === false && \"text-destructive line-through\")}>\n <span className=\"size-2 rounded-[2px]\" style={{ background: f.color }} aria-hidden />\n <span className=\"text-muted-foreground\">{f.name}</span>\n <span>{f.ip ?? \"\u2014\"}</span>\n <span className=\"text-muted-foreground\">{f.network}</span>\n </li>\n ))}\n </ul>\n );\n}\n\n/**\n * A router you configure, drawn like a switch: its interfaces eth0\u2013eth3, each in the color of the\n * network plugged into it, and beside it the list of interfaces with their addresses. A cable\n * plugs into one port; on a LAN's edge, eth0 is that LAN.\n */\nexport function RouterFaceplate({ id, data, selected }: NodeProps<MachineNode>) {\n const t = useText().canvas;\n const { updateNodeData } = useReactFlow();\n usePortSides(id);\n const view = useContext(PortsContext)[id] ?? { colors: {}, interfaces: [] };\n const sketch = useSketch();\n const box = useMemo(\n () => gen.rectangle(2, 2, ROUTER_W - 4, ROUTER_H - 4, { ...sketch, seed: seedOf(id), fill: \"F\", fillStyle: \"solid\", stroke: \"S\", strokeWidth: selected ? 2.25 : 1.4 }),\n [id, selected, sketch],\n );\n const live = useContext(LiveContext);\n const business = useBusiness();\n return (\n <div style={{ width: ROUTER_W, height: ROUTER_H }} className=\"group relative\">\n <StatusDot name={data.name} className=\"-top-1 -right-1\" />\n <Frame drawable={box} fill=\"var(--pastel-yellow)\" selected={selected} dim={live?.machines[data.name]?.status === \"down\"} hardware={business} />\n <div className={cn(\"absolute top-1.5 left-3.5 flex items-center gap-1.5 font-heading text-sm font-semibold\", business && \"left-5 text-[13px] text-white\")}>\n <Router className={cn(\"size-3.5\", business && \"text-amber-400\")} aria-hidden />\n <InlineText label={t.routerName} value={data.name} clean={cleanName} onCommit={(name) => { updateNodeData(id, { name }); }} />\n <span className={cn(\"font-sans text-[10px] font-normal text-muted-foreground\", business && \"text-[9px] font-semibold tracking-wider text-slate-400 uppercase\")}>{modelOf(data, t.vm)}</span>\n </div>\n {Array.from({ length: ROUTER_PORTS }, (_, i) => routerPort(i)).map((port, i) => (\n <RouterPort key={port} id={id} data={data} port={port} i={i} view={view} />\n ))}\n <InterfaceList data={data} view={view} />\n </div>\n );\n}\n", "/**\n * Business: a socket's status light, in its VLAN's or network's color (a trunk's stripes), lit\n * when something is assigned to the port; dark when nothing is.\n */\nexport function PortLed({ color }: { color: string | null }) {\n return (\n <>\n {/* The socket's latch. */}\n <span aria-hidden className=\"pointer-events-none absolute inset-x-[6px] top-[3px] h-[4px] rounded-t-[1px] border border-b-0 border-white/12\" />\n <span\n aria-hidden\n className=\"pointer-events-none absolute bottom-[3px] left-1/2 h-[3px] w-3 -translate-x-1/2 rounded-full\"\n style={color ? { background: color, boxShadow: color.startsWith(\"repeating\") ? undefined : `0 0 5px ${color}` } : { background: \"#2a3341\" }}\n />\n </>\n );\n}\n\n/** The look of a port's square: business sockets are dark and recessed. */\nexport const PORT_BOX = \"rounded-[3px] border border-foreground/40\";\nexport const BUSINESS_SOCKET = \"rounded-[2px] border-black/80 shadow-[inset_0_1px_3px_rgb(0_0_0/0.7)]\";\n", "\"use client\";\n\nimport { useContext } from \"react\";\nimport type { Status } from \"@/lib/tool/desktop\";\nimport { cn } from \"@/lib/utils\";\nimport { useText } from \"../text\";\nimport { LiveContext } from \"./contexts\";\n\nconst STATUS_DOT: Record<Status, string> = {\n up: \"bg-success\",\n starting: \"bg-warning animate-pulse\",\n unhealthy: \"bg-destructive\",\n down: \"bg-muted-foreground/50\",\n};\n\n/** A machine's status as a dot in its corner, its state in the tooltip. */\nexport function StatusDot({ name, className }: { name: string; className?: string }) {\n const t = useText().canvas.live;\n const m = useContext(LiveContext)?.machines[name];\n if (!m) return null;\n return (\n <span\n role=\"img\"\n title={`${t[m.status]} \u00B7 ${m.detail}`}\n aria-label={t[m.status]}\n className={cn(\"pointer-events-auto absolute z-10 size-3 rounded-full ring-2 ring-background\", STATUS_DOT[m.status], className)}\n />\n );\n}\n", "import { useContext, useEffect } from \"react\";\nimport { useUpdateNodeInternals } from \"@xyflow/react\";\nimport { SidesContext } from \"./contexts\";\n\n/**\n * Which way each port of node `id` faces (`<id>:<port>` in the sides), as one key; React Flow\n * caches where handles are, so they are measured again when it changes.\n */\nexport function usePortSides(id: string) {\n const sides = useContext(SidesContext);\n const facing = Object.keys(sides)\n .filter((k) => k.startsWith(`${id}:`))\n .sort()\n .join(\",\");\n useRemeasure(id, facing);\n return sides;\n}\n\n/** Measures node `id`'s handles again whenever `key` changes. */\nexport function useRemeasure(id: string, key: string | undefined): void {\n const updateNodeInternals = useUpdateNodeInternals();\n useEffect(() => {\n updateNodeInternals(id);\n }, [id, key, updateNodeInternals]);\n}\n", "\"use client\";\n\nimport { useMemo, useState } from \"react\";\nimport { NodeResizer, NodeToolbar, Position, useReactFlow, type NodeProps } from \"@xyflow/react\";\nimport { Circle, Square, Type, type LucideIcon } from \"lucide-react\";\nimport { NOTE_COLORS, type NoteNode, type NoteShape } from \"@/lib/tool/model\";\nimport { cn } from \"@/lib/utils\";\nimport { useText } from \"../text\";\nimport { Sketch, gen, seedOf, useSketch } from \"./sketch\";\n\n/** When selected, a small bar picks the note's shape and color. */\nfunction NoteBar({ id, data, visible }: { id: string; data: NoteNode[\"data\"]; visible: boolean }) {\n const t = useText().canvas;\n const { updateNodeData } = useReactFlow();\n const shapes: [NoteShape, LucideIcon, string][] = [\n [\"text\", Type, t.textOnly],\n [\"rect\", Square, t.box],\n [\"ellipse\", Circle, t.ellipse],\n ];\n return (\n <NodeToolbar isVisible={visible} position={Position.Top} className=\"flex items-center gap-1 rounded-lg border bg-popover p-1 shadow-sm\">\n {shapes.map(([shape, Icon, label]) => (\n <button key={shape} type=\"button\" title={label} aria-label={label} aria-pressed={data.shape === shape} onClick={() => { updateNodeData(id, { shape }); }} className={cn(\"grid size-7 place-items-center rounded-md hover:bg-muted\", data.shape === shape && \"bg-signal/15 text-signal\")}>\n <Icon className=\"size-4\" />\n </button>\n ))}\n <span className=\"mx-0.5 h-5 w-px bg-border\" />\n {NOTE_COLORS.map((color) => (\n <button\n key={color}\n type=\"button\"\n title={t.colors[color]}\n aria-label={t.color(t.colors[color])}\n aria-pressed={data.color === color}\n onClick={() => { updateNodeData(id, { color }); }}\n className={cn(\"size-5 rounded-full border\", data.color === color && \"ring-2 ring-signal ring-offset-1 ring-offset-popover\")}\n style={{ background: `var(--pastel-${color})` }}\n />\n ))}\n </NodeToolbar>\n );\n}\n\n/** The note's text; double-click to write (Enter a new line; Escape or Ctrl/\u2318 Enter is done). */\nfunction NoteText({ id, data, selected, draft, setDraft }: { id: string; data: NoteNode[\"data\"]; selected: boolean; draft: string | null; setDraft: (d: string | null) => void }) {\n const t = useText().canvas;\n const { updateNodeData } = useReactFlow();\n return (\n <div\n className={cn(\n \"absolute inset-0 flex items-center justify-center overflow-hidden p-3 font-heading text-base leading-snug text-foreground\",\n data.shape === \"ellipse\" && \"px-[15%]\",\n data.shape === \"text\" && selected && \"rounded-md outline-1 outline-signal/50 outline-dashed\",\n )}\n onDoubleClick={(e) => {\n e.stopPropagation();\n setDraft(data.text);\n }}\n >\n {draft === null ? (\n <p className={cn(\"w-full text-center break-words whitespace-pre-wrap\", !data.text && \"text-muted-foreground\")}>{data.text || t.write}</p>\n ) : (\n <textarea\n autoFocus\n aria-label={t.note}\n value={draft}\n onChange={(e) => { setDraft(e.target.value); }}\n onBlur={() => {\n updateNodeData(id, { text: draft });\n setDraft(null);\n }}\n onKeyDown={(e) => {\n if (e.key === \"Escape\" || (e.key === \"Enter\" && (e.metaKey || e.ctrlKey))) e.currentTarget.blur();\n }}\n className=\"nodrag nowheel size-full resize-none bg-transparent text-center outline-none\"\n />\n )}\n </div>\n );\n}\n\n/**\n * A note: text on the canvas, bare or in a sketched box or ellipse, to explain the lab. It stays\n * in the editor (the draft, share links) and never reaches isoloom.yml.\n */\nexport function NoteNodeView({ id, data, selected, width, height }: NodeProps<NoteNode>) {\n const [draft, setDraft] = useState<string | null>(null);\n const w = width ?? 200;\n const h = height ?? 90;\n const sketch = useSketch();\n const outline = useMemo(() => {\n const o = { ...sketch, seed: seedOf(id), fill: \"F\", fillStyle: \"solid\", stroke: \"S\", strokeWidth: selected ? 2 : 1.3 };\n if (data.shape === \"rect\") return gen.rectangle(2, 2, w - 4, h - 4, o);\n if (data.shape === \"ellipse\") return gen.ellipse(w / 2, h / 2, w - 4, h - 4, o);\n return null;\n }, [id, w, h, selected, data.shape, sketch]);\n return (\n <div style={{ width: w, height: h }} className=\"relative\">\n <NodeResizer isVisible={selected} minWidth={80} minHeight={40} lineClassName=\"!border-transparent\" handleClassName=\"pointer-events-auto !z-10 !size-2.5 !rounded-sm !border-signal !bg-background\" />\n <NoteBar id={id} data={data} visible={selected && draft === null} />\n {outline && (\n <svg aria-hidden className=\"pointer-events-none absolute inset-0 overflow-visible\" width={w} height={h}>\n <Sketch drawable={outline} fill={`var(--pastel-${data.color})`} stroke={selected ? \"var(--signal)\" : \"var(--foreground)\"} />\n </svg>\n )}\n <NoteText id={id} data={data} selected={selected} draft={draft} setDraft={setDraft} />\n </div>\n );\n}\n", "\"use client\";\n\nimport { useContext, useMemo } from \"react\";\nimport { Handle, Position, useReactFlow, type NodeProps } from \"@xyflow/react\";\nimport { Plus, X } from \"lucide-react\";\nimport { SWITCH_H, SWITCH_PORTS, SWITCH_W, TRUNK, cleanName, type SwitchNode } from \"@/lib/tool/model\";\nimport { addVlan, changeVlan, cyclePort, removeVlan, vlanNumber } from \"@/lib/tool/switch-edit\";\nimport { trunkStripes, vlanColor, vlanName } from \"@/lib/tool/vlans\";\nimport { cn } from \"@/lib/utils\";\nimport { useText } from \"../text\";\nimport { SidesContext } from \"./contexts\";\nimport { InlineText } from \"./inline-text\";\nimport { BUSINESS_SOCKET, PORT_BOX, PortLed } from \"./port-led\";\nimport { Frame, gen, seedOf, useBusiness, useSketch } from \"./sketch\";\nimport { usePortSides } from \"./use-measured-ports\";\n\nconst PORT = 24;\nconst PORT_GAP = 6;\nconst SW_PAD = 14;\n\n/** Where a port's square starts, from the switch's left. The trunk sits apart, after a gap. */\nfunction portX(i: number | typeof TRUNK): number {\n return i === TRUNK ? SW_PAD + SWITCH_PORTS * (PORT + PORT_GAP) + 14 : SW_PAD + i * (PORT + PORT_GAP);\n}\n\ntype SwitchData = SwitchNode[\"data\"];\n\n/** A port's tooltip: what it carries, and that a click changes it (not on the T port). */\nfunction usePortTitle(data: SwitchData) {\n const t = useText().canvas;\n return (i: number | typeof TRUNK) => {\n const mode = i === TRUNK ? TRUNK : data.ports[i];\n const name = i === TRUNK ? \"T\" : t.port(i + 1);\n if (mode === TRUNK) return `${name}: ${t.trunkCarries(data.vlans.map((v) => vlanName(v.id)).join(\", \") || t.noVlan)}${i === TRUNK ? \"\" : ` ${t.clickToChange}`}`;\n return `${name}: ${mode === null ? t.noVlan : vlanName(mode)} ${t.clickToChange}`;\n };\n}\n\n/** One port: its number, its square in its VLAN's color (striped for a trunk), its handle. */\nfunction SwitchPort({ id, data, i, onCycle }: { id: string; data: SwitchData; i: number | typeof TRUNK; onCycle: (i: number) => void }) {\n const t = useText().canvas;\n const sides = useContext(SidesContext);\n const business = useBusiness();\n const title = usePortTitle(data);\n const trunk = i === TRUNK;\n const mode = trunk ? TRUNK : data.ports[i];\n const vlan = typeof mode === \"number\" ? mode : null;\n const color = mode === TRUNK ? trunkStripes(data.vlans) : vlan === null ? null : vlanColor(vlan);\n const handle = trunk ? TRUNK : `p${String(i + 1)}`;\n const x = portX(i);\n return (\n <div>\n <span className={cn(\"absolute top-[26px] w-6 text-center font-mono text-[9px] text-muted-foreground\", business && \"text-slate-400\")} style={{ left: x }}>\n {trunk ? \"T\" : i + 1}\n </span>\n <button\n type=\"button\"\n onClick={() => {\n if (!trunk) onCycle(i);\n }}\n title={title(i)}\n aria-label={trunk ? t.trunkPort : t.port(i + 1)}\n className={cn(\"nodrag absolute top-[38px]\", PORT_BOX, trunk ? \"cursor-default\" : \"cursor-pointer hover:ring-2 hover:ring-signal\", business && BUSINESS_SOCKET)}\n style={{ left: x, width: PORT, height: 20, background: business ? \"#0b1017\" : (color ?? \"var(--muted)\") }}\n >\n {business && <PortLed color={color} />}\n </button>\n <Handle\n id={handle}\n type=\"source\"\n position={sides[`${id}:${handle}`] === \"top\" ? Position.Top : Position.Bottom}\n style={{ left: x + PORT / 2 }}\n className=\"!size-2.5 !border-2 !border-background !bg-foreground/50 transition-colors group-hover:!bg-signal\"\n />\n </div>\n );\n}\n\n/** The VLANs, beside the faceplate (cables leave from above and below it): double-click to edit, + to add, \u00D7 to remove. */\nfunction VlanList({ id, data }: { id: string; data: SwitchData }) {\n const t = useText().canvas;\n const { updateNodeData } = useReactFlow();\n return (\n <div className=\"nodrag absolute top-0 left-full ml-3 flex w-max flex-col items-start gap-1 text-[11px]\">\n {data.vlans.map((v) => (\n <span key={v.id} className=\"flex items-center gap-1 rounded-md bg-background/90 pr-1\">\n <span className=\"size-2.5 rounded-[2px]\" style={{ background: vlanColor(v.id) }} aria-hidden />\n <span className=\"font-heading font-semibold\">\n vlan\n <InlineText\n label={t.vlanNumber}\n value={String(v.id)}\n clean={(x) => x.replace(/\\D/g, \"\").slice(0, 4)}\n onCommit={(x) => {\n const n = vlanNumber(data, x);\n if (n !== null) updateNodeData(id, changeVlan(data, v.id, { id: n }));\n }}\n />\n </span>\n <InlineText label={t.vlanBlock} value={v.cidr} clean={(x) => x.replace(/[^0-9./]/g, \"\")} onCommit={(cidr) => { updateNodeData(id, changeVlan(data, v.id, { cidr })); }} className=\"font-mono text-muted-foreground\" />\n <button type=\"button\" onClick={() => { updateNodeData(id, removeVlan(data, v.id)); }} aria-label={t.remove(vlanName(v.id))} className=\"text-muted-foreground hover:text-foreground\">\n <X className=\"size-3\" />\n </button>\n </span>\n ))}\n <button type=\"button\" onClick={() => { updateNodeData(id, addVlan(data)); }} className=\"flex items-center gap-0.5 rounded-md px-1 text-muted-foreground hover:bg-muted hover:text-foreground\">\n <Plus className=\"size-3\" /> VLAN\n </button>\n </div>\n );\n}\n\n/**\n * A switch, drawn as its faceplate: numbered access ports in their VLAN's color (click one to\n * change its VLAN), and a trunk striped with every VLAN it carries. A cable plugs into a port.\n * Its VLANs are listed under it: double-click to edit, + to add, \u00D7 to remove.\n */\nexport function SwitchNodeView({ id, data, selected }: NodeProps<SwitchNode>) {\n const t = useText().canvas;\n const { updateNodeData } = useReactFlow();\n // Each port faces the device plugged into it: up when that device is above the switch.\n usePortSides(id);\n const sketch = useSketch();\n const box = useMemo(\n () => gen.rectangle(2, 2, SWITCH_W - 4, SWITCH_H - 4, { ...sketch, seed: seedOf(id), fill: \"F\", fillStyle: \"solid\", stroke: \"S\", strokeWidth: selected ? 2.25 : 1.4 }),\n [id, selected, sketch],\n );\n const business = useBusiness();\n const ports: (number | typeof TRUNK)[] = [...data.ports.map((_, i) => i), TRUNK];\n return (\n <div style={{ width: SWITCH_W, height: SWITCH_H }} className=\"group relative\">\n <Frame drawable={box} fill=\"var(--card)\" selected={selected} hardware={business} />\n <div className={cn(\"absolute top-1.5 left-3.5 flex items-baseline gap-2 font-heading text-sm font-semibold\", business && \"left-5 text-[13px] text-white\")}>\n <InlineText label={t.switchName} value={data.name} clean={cleanName} onCommit={(name) => { updateNodeData(id, { name }); }} />\n {business && <span className=\"font-sans text-[9px] font-semibold tracking-wider text-slate-400 uppercase\">{t.switchModel(data.ports.length)}</span>}\n </div>\n {ports.map((i) => (\n <SwitchPort key={String(i)} id={id} data={data} i={i} onCycle={(port) => { updateNodeData(id, cyclePort(data, port)); }} />\n ))}\n <VlanList id={id} data={data} />\n </div>\n );\n}\n", "import { TRUNK, type PortMode, type SwitchNode } from \"./model\";\n\n/** Editing a switch on the canvas: each change returns the switch's fields that change. */\n\ntype SwitchData = SwitchNode[\"data\"];\n\n/** A click steps a port through each VLAN, then trunk, then unassigned. */\nexport function cyclePort(data: SwitchData, i: number): Pick<SwitchData, \"ports\"> {\n const order: PortMode[] = [...data.vlans.map((v) => v.id), TRUNK, null];\n const next = order[(order.indexOf(data.ports[i]) + 1) % order.length];\n return { ports: data.ports.map((p, j) => (j === i ? next : p)) };\n}\n\n/** A VLAN's number or block changed; a new number moves its ports along. */\nexport function changeVlan(data: SwitchData, old: number, patch: { id?: number; cidr?: string }): Pick<SwitchData, \"vlans\" | \"ports\"> {\n const renumbered = patch.id;\n return {\n vlans: data.vlans.map((v) => (v.id === old ? { ...v, ...patch } : v)),\n ports: renumbered === undefined ? data.ports : data.ports.map((p) => (p === old ? renumbered : p)),\n };\n}\n\n/** A VLAN removed: its ports are left unassigned. */\nexport function removeVlan(data: SwitchData, vid: number): Pick<SwitchData, \"vlans\" | \"ports\"> {\n return { vlans: data.vlans.filter((v) => v.id !== vid), ports: data.ports.map((p) => (p === vid ? null : p)) };\n}\n\n/** A new VLAN, numbered 10 after the highest, with its own block. */\nexport function addVlan(data: SwitchData): Pick<SwitchData, \"vlans\"> {\n const next = Math.max(0, ...data.vlans.map((v) => v.id)) + 10;\n return { vlans: [...data.vlans, { id: next, cidr: next <= 255 ? `10.10.${String(next)}.0/24` : \"10.11.0.0/24\" }] };\n}\n\n/** A typed VLAN number, if it can be one: 1\u20134094, and not one the switch has already. */\nexport function vlanNumber(data: SwitchData, typed: string): number | null {\n const n = Number(typed);\n return n > 0 && n < 4095 && !data.vlans.some((v) => v.id === n) ? n : null;\n}\n", "import { useMemo, useState, type RefObject } from \"react\";\nimport { useReactFlow } from \"@xyflow/react\";\nimport { useTheme } from \"next-themes\";\nimport { toolLabel } from \"@/lib/tool/blocks\";\nimport { runsOnVms } from \"@/lib/tool/desktop\";\nimport { facingSides, shownCables } from \"@/lib/tool/facing\";\nimport { liveViewOf } from \"@/lib/tool/live\";\nimport { isMachine, type CableEdge, type LabNode } from \"@/lib/tool/model\";\nimport { routerPortsOf, type Addresses } from \"@/lib/tool/router-ports\";\nimport { labIssues, selectionOf } from \"@/lib/tool/selection\";\nimport { toTopology } from \"@/lib/tool/topology\";\nimport type { Plan } from \"@/lib/tool/engine\";\nimport { useText } from \"../text\";\nimport { useCabling, useLabIndex } from \"./use-cabling\";\nimport { useCaptures } from \"./use-captures\";\nimport { useClipboard } from \"./use-clipboard\";\nimport { useContextMenus } from \"./use-context-menus\";\nimport { useAutoStart, useDesktopStartup, useDesktopState, useLiveLab, useRunPanel } from \"./use-desktop\";\nimport { useDesign } from \"./use-design\";\nimport { useDevices } from \"./use-devices\";\nimport { useDownloads } from \"./use-downloads\";\nimport { useEngine, usePlan } from \"./use-engine\";\nimport { useHistory } from \"./use-history\";\nimport { useDraftSaving, useLab } from \"./use-lab\";\nimport { useFitWhenDrawn, useLabActions } from \"./use-lab-actions\";\nimport { useLabRun } from \"./use-lab-run\";\nimport { useLanCarry } from \"./use-lan-carry\";\nimport { useMachineActions } from \"./use-machine-actions\";\nimport { usePlacement } from \"./use-placement\";\nimport { useProjects } from \"./use-projects\";\nimport { useSharedLink } from \"./use-shared-link\";\nimport { useToast } from \"./use-toast\";\nimport { useToolKeys, useTools } from \"./use-tools\";\n\n/** The desktop app's side: running the lab, its machines, captures (all inert in a browser). */\nfunction useDesktopSide(labName: string, initialName: string, setToast: (message: string) => void) {\n const t = useText();\n const state = useDesktopState();\n const live = useLiveLab(state.invoke, labName, state.run);\n const actions = useMachineActions({ invoke: state.invoke, labName, live, setToast, t });\n const menus = useContextMenus();\n const panel = useRunPanel();\n const autoStart = useAutoStart(state.invoke, labName);\n const captures = useCaptures(state.invoke, labName, (error) => {\n panel.setRunLog(error);\n panel.setRunOpen(true);\n });\n useDesktopStartup(state, initialName, autoStart.setAutoStartPending);\n return { state, live, actions, menus, panel, autoStart, captures };\n}\n\n/** While the lab has an error the engine gives no addresses; the canvas keeps showing the last good ones, so the address in conflict can still be edited where it is. */\nfunction useAddresses(plan: Plan | null): Addresses {\n const [last, setLast] = useState<Addresses>({});\n const good = plan?.ok && Object.keys(plan.addresses).length ? plan.addresses : null;\n if (good && good !== last) setLast(good);\n return plan?.ok ? plan.addresses : last;\n}\n\n/** What the canvas draws from the lab: port sides, cables as attached now, router ports. */\nfunction useCanvasViews(nodes: LabNode[], edges: CableEdge[], lans: ReturnType<typeof useLabIndex>[\"lans\"], addresses: Addresses) {\n const sides = useMemo(() => facingSides(nodes, edges, lans), [nodes, edges, lans]);\n const shownEdges = useMemo(() => shownCables(nodes, edges, lans), [nodes, edges, lans]);\n const routerPorts = useMemo(() => routerPortsOf(nodes, edges, lans, addresses), [nodes, edges, lans, addresses]);\n return { sides, shownEdges, routerPorts };\n}\n\n/** The lab editor's state and behaviour: what the canvas, the toolbar and the windows show and do. */\nexport function useEditor(lang: string, accounts: boolean, canvasRef: RefObject<HTMLDivElement | null>) {\n const t = useText();\n const { engine, error: engineError } = useEngine();\n const { resolvedTheme } = useTheme();\n const flow = useReactFlow<LabNode, CableEdge>();\n const lab = useLab();\n const [exportOpen, setExportOpen] = useState(false);\n const [statusOpen, setStatusOpen] = useState(false);\n const tools = useTools();\n const [toast, setToast] = useToast();\n const desk = useDesktopSide(lab.labName, lab.initial.name, setToast);\n const history = useHistory(lab);\n const design = useDesign();\n const fitWhenDrawn = useFitWhenDrawn(flow.fitView);\n useSharedLink({ lab, setDesign: design.setDesign, setToast, fitWhenDrawn, t });\n useClipboard(lab, flow.deleteElements);\n useDraftSaving(lab);\n const topology = useMemo(() => toTopology(lab.labName, lab.nodes, lab.edges), [lab.labName, lab.nodes, lab.edges]);\n const plan = usePlan(engine, topology, t);\n const projects = useProjects({ accounts, lab, design: design.design, setDesign: design.setDesign, plan, setToast, fitWhenDrawn, t });\n const addresses = useAddresses(plan);\n const index = useLabIndex(lab.nodes);\n const views = useCanvasViews(lab.nodes, lab.edges, index.lans, addresses);\n const carry = useLanCarry(lab);\n const cabling = useCabling(lab, index);\n const devices = useDevices(tools, setToast, t);\n useToolKeys(tools);\n const actions = useLabActions(lab, fitWhenDrawn, setToast, t);\n const machines = lab.nodes.filter(isMachine);\n const hasVms = runsOnVms(machines.some((n) => n.data.kind === \"vm\"), plan);\n const run = useLabRun({ ...desk, state: desk.state, lab: { labName: lab.labName, topology, plan, engine, hasVms }, t });\n const { invoke, run: runState } = desk.state;\n const { live, links } = desk.live;\n const liveView = useMemo(() => (runState === \"running\" && live ? liveViewOf(live, links, lab.nodes, lab.edges) : null), [runState, live, links, lab.nodes, lab.edges]);\n const placement = usePlacement({ lab, lans: index.lans, tools, presets: devices.presets, canvasRef, screenToFlowPosition: flow.screenToFlowPosition, closeMenus: desk.menus.closeMenus, importGns3: (f) => void actions.importGns3(f) });\n const downloads = useDownloads(engine, plan, topology, lab.labName);\n const tool = toolLabel(tools.activeTool, devices.presets, t);\n const issues = labIssues(lab.nodes, plan, t.issues);\n const selection = selectionOf(lab.nodes, lab.edges);\n return {\n lang, accounts, t, engine, engineError, plan, resolvedTheme, flow, lab, tools, toast, setToast, desk, history, design, projects, addresses, index, views, carry, cabling, devices, actions, run, liveView, placement, downloads, tool, issues, selection, invoke,\n exportOpen, setExportOpen, statusOpen, setStatusOpen, machines, hasVms, mixed: hasVms && machines.some((n) => n.data.kind === \"container\"), empty: lab.nodes.length === 0, fitWhenDrawn,\n };\n}\n\nexport type EditorModel = ReturnType<typeof useEditor>;\n", "import type { Appliance } from \"./model\";\n\n/**\n * The OSes a machine can be, as Isoloom writes them (`<family>@<version>`): exactly Isoloom's list,\n * which its engine gives (`choices_json`, checked by the tests). A machine of one of them is its\n * OS, set up by its provisioning steps; each target decides whether it runs as a VM or as a\n * container built from the OS's image.\n */\nexport const OS_CHOICES = [\n \"debian@11\",\n \"debian@12\",\n \"debian@13\",\n \"ubuntu@14.04\",\n \"ubuntu@16.04\",\n \"ubuntu@18.04\",\n \"ubuntu@20.04\",\n \"ubuntu@22.04\",\n \"ubuntu@24.04\",\n \"rocky@9\",\n \"alma@9\",\n \"alpine@3.19\",\n \"kali@rolling\",\n \"fedora@42\",\n \"centos@7\",\n \"windows@10\",\n \"windows@11\",\n \"windows-server@2008r2\",\n \"windows-server@2012r2\",\n \"windows-server@2016\",\n \"windows-server@2019\",\n \"windows-server@2022\",\n \"windows-server@2025\",\n];\n\n/** The OS a new VM gets. */\nexport const DEFAULT_OS = \"debian@12\";\n\n/**\n * An OS as a lab stored before Isoloom's new format named it (its image-table name: `debian-12`,\n * `almalinux-9`, `kali`, `windows-server-2022`), in today's spelling; any other value as it is.\n */\nexport function currentOs(os: string): string {\n if (os === \"kali\") return \"kali@rolling\";\n const m = /^([a-z-]+?)-(\\d[\\da-z.]*)$/.exec(os);\n if (!m || os.includes(\"@\")) return os;\n const family = m[1] === \"almalinux\" ? \"alma\" : m[1];\n return `${family}@${m[2]}`;\n}\n\n/** The Cisco OSes stored under the id the editor gave them before Isoloom's (`cisco-viosl2`). */\nconst OLD_APPLIANCES: ReadonlyMap<string, Appliance> = new Map([[\"cisco-viosl2\", \"cisco-vios-l2\"]]);\n\n/** A machine as a stored lab or device holds it, in today's spelling: its OS and its Cisco OS. */\nexport function currentMachine<M extends { os: string; appliance?: Appliance }>(m: M): M {\n const appliance = m.appliance === undefined ? undefined : (OLD_APPLIANCES.get(m.appliance) ?? m.appliance);\n return { ...m, os: currentOs(m.os), ...(appliance === undefined ? {} : { appliance }) };\n}\n", "import { uid, type MachineData } from \"./model\";\nimport { DEFAULT_OS } from \"./os\";\n\n/** The devices the toolbar places, and the ones saved from the canvas. */\n\nexport interface Preset {\n id: string;\n /** Toolbar groups: network appliances first, then containers, then VMs, then saved devices. */\n group: \"network\" | \"container\" | \"vm\" | \"mine\";\n /** A saved device's name. The built-in devices are named in the editor's text, by their id. */\n label?: string;\n /** Prefix of the generated machine name (`router1`, `router2`...). */\n prefix: string;\n data: Omit<MachineData, \"name\">;\n}\n\nconst base = { image: \"\", os: \"\", provision: \"\", ports: \"\", access: false };\n\n/** A built-in device: `id` in `group`, named `<prefix><n>`, with `data` over the defaults. */\nconst preset = (id: string, group: Preset[\"group\"], prefix: string, data: Pick<MachineData, \"kind\" | \"icon\"> & Partial<MachineData>): Preset => ({\n id,\n group,\n prefix,\n data: { ...base, ...data },\n});\n\nexport const PRESETS: Preset[] = [\n preset(\"router\", \"network\", \"router\", { kind: \"router\", icon: \"router\" }),\n preset(\"router-frr\", \"network\", \"frr\", { kind: \"container\", icon: \"router\", image: \"frrouting/frr:v8.5.2\" }),\n preset(\"firewall\", \"network\", \"fw\", { kind: \"container\", icon: \"shield\", image: \"alpine:3.20\" }),\n preset(\"container\", \"container\", \"box\", { kind: \"container\", icon: \"container\", image: \"alpine:3.20\" }),\n preset(\"web\", \"container\", \"web\", { kind: \"container\", icon: \"server\", image: \"nginx:1.27-alpine\", ports: \"80\" }),\n preset(\"database\", \"container\", \"db\", { kind: \"container\", icon: \"server\", image: \"postgres:16-alpine\", ports: \"5432\" }),\n preset(\"linux-vm\", \"vm\", \"vm\", { kind: \"vm\", icon: \"monitor\", os: DEFAULT_OS }),\n preset(\"ubuntu-vm\", \"vm\", \"ubuntu\", { kind: \"vm\", icon: \"monitor\", os: \"ubuntu@24.04\" }),\n preset(\"kali-vm\", \"vm\", \"kali\", { kind: \"vm\", icon: \"monitor\", os: \"kali@rolling\" }),\n preset(\"windows-vm\", \"vm\", \"win\", { kind: \"vm\", icon: \"monitor\", os: \"windows-server@2022\" }),\n preset(\"workstation\", \"vm\", \"user\", { kind: \"vm\", icon: \"laptop\", os: DEFAULT_OS, access: true }),\n // Last, so the number keys above keep their devices.\n preset(\"cisco-iol\", \"network\", \"r\", { kind: \"container\", icon: \"router\", image: \"vrnetlab/cisco_iol:17.12.01\", appliance: \"cisco-iol\" }),\n preset(\"cisco-iol-l2\", \"network\", \"sw\", { kind: \"container\", icon: \"router\", image: \"vrnetlab/cisco_iol:L2-17.12.01\", appliance: \"cisco-iol-l2\" }),\n // A Linux desktop with a VNC server (GNS3's desktop appliances): its screen opens from the\n // desktop app (right-click, Screen). VNC password: vncpassword.\n preset(\"desktop\", \"container\", \"desk\", { kind: \"container\", icon: \"monitor\", image: \"consol/debian-xfce-vnc:latest\" }),\n];\n\n/** Keys 1\u20139 then 0 pick the devices, in toolbar order. */\nexport function shortcutOf(presetId: string): string | null {\n const i = PRESETS.findIndex((p) => p.id === presetId);\n return i < 0 || i > 9 ? null : String((i + 1) % 10);\n}\n\n/** The device a number key picks: 1\u20139 the first nine, 0 the tenth. */\nexport function presetForKey(key: string): Preset | undefined {\n return /^[0-9]$/.test(key) ? PRESETS[(Number(key) + 9) % 10] : undefined;\n}\n\n/** A device from a machine on the canvas: everything but its name and fixed addresses. */\nexport function deviceFrom(m: MachineData): Preset {\n const { name, ...rest } = m;\n const data: Omit<MachineData, \"name\"> = { ...rest, pins: undefined };\n return {\n id: uid(\"my\"),\n group: \"mine\",\n label: name,\n prefix: name.replace(/\\d+$/, \"\") || \"device\",\n data,\n };\n}\n\n/** What changes when a machine is set to run as `kind`: a VM keeps its OS (Debian 12 by default), a container its image (FRR for a router, Alpine otherwise). */\nexport function runAs(m: MachineData, kind: string): Partial<MachineData> | null {\n if (kind === \"vm\") return { kind, os: m.os || DEFAULT_OS };\n if (kind === \"router\") return { kind };\n if (kind === \"container\") return { kind, image: m.image || (m.icon === \"router\" ? \"frrouting/frr:v8.5.2\" : \"alpine:3.20\") };\n return null;\n}\n", "import { PRESETS, shortcutOf, type Preset } from \"./presets\";\nimport type { EditorText } from \"./text\";\n\n/** The toolbar's blocks: a switch, a router, a firewall, a container, a VM, and the saved devices. */\n\n/** The switch tool's id in the toolbar (devices use their preset ids). */\nexport const SWITCH_TOOL = \"switch\";\n/** The LAN tool's id in the toolbar. */\nexport const LAN_TOOL = \"lan\";\nexport const NOTE_TOOL = \"note\";\n\n/** One kind a block places: a preset (a device), or the switch tool. */\nexport interface BlockOption {\n tool: string;\n label: string;\n hint: string;\n preset?: Preset;\n key?: string | null;\n}\nexport interface Block {\n id: string;\n label: string;\n options: BlockOption[];\n}\n\n/** What a device runs: its OS (a VM), or its image. */\nconst runs = (p: Preset) => (p.data.kind === \"vm\" ? p.data.os : p.data.image);\n\n/** A device's name and hint in the toolbar: the built-in ones by id (the hint, unless the text gives one, is what it runs), a saved one by its name. */\nfunction presetText(p: Preset, t: EditorText): { label: string; hint: string } {\n if (p.group !== \"mine\") {\n const d = (t.devices as Partial<Record<string, { label: string; hint?: string }>>)[p.id];\n return d ? { label: d.label, hint: d.hint ?? runs(p) } : { label: p.id, hint: \"\" };\n }\n const what = p.data.kind === \"vm\" ? p.data.os : p.data.kind === \"router\" ? t.myDeviceRouter : p.data.image;\n return { label: p.label ?? p.prefix, hint: t.myDevice(what) };\n}\n\n/** The blocks of the toolbar, each listing the kinds it places (the switch block starts with the switch tool). */\nexport function deviceBlocks(presets: Preset[], mine: Preset[], t: EditorText): Block[] {\n const kinds = (ids: string[]) =>\n ids.flatMap((id): BlockOption[] => {\n const p = presets.find((x) => x.id === id);\n return p ? [{ tool: p.id, ...presetText(p, t), preset: p, key: shortcutOf(p.id) }] : [];\n });\n const switchTool: BlockOption = { tool: SWITCH_TOOL, label: t.toolbar.switch, hint: t.toolbar.switchTitle, key: \"S\" };\n const blocks: Block[] = [\n { id: \"switch\", label: t.toolbar.blocks.switch, options: [switchTool, ...kinds([\"cisco-iol-l2\"])] },\n { id: \"router\", label: t.toolbar.blocks.router, options: kinds([\"router\", \"router-frr\", \"cisco-iol\"]) },\n { id: \"firewall\", label: t.toolbar.blocks.firewall, options: kinds([\"firewall\"]) },\n { id: \"container\", label: t.toolbar.blocks.container, options: kinds([\"container\", \"web\", \"database\", \"desktop\"]) },\n { id: \"vm\", label: t.toolbar.blocks.vm, options: kinds([\"linux-vm\", \"ubuntu-vm\", \"kali-vm\", \"windows-vm\", \"workstation\"]) },\n ];\n if (mine.length) blocks.push({ id: \"mine\", label: t.toolbar.blocks.mine, options: kinds(mine.map((d) => d.id)) });\n return blocks;\n}\n\n/** What the tool being placed is called, if any (a LAN, a switch, a note, or a device). */\nexport function toolLabel(tool: string | null, presets: Preset[], t: EditorText): { label: string } | undefined {\n if (tool === LAN_TOOL) return { label: t.toolbar.lan };\n if (tool === SWITCH_TOOL) return { label: t.toolbar.switch };\n if (tool === NOTE_TOOL) return { label: t.toolbar.note };\n const picked = presets.find((p) => p.id === tool);\n return picked && presetText(picked, t);\n}\n\n/** Every device the toolbar can place: the built-in ones, then the saved ones. */\nexport const allPresets = (mine: Preset[]): Preset[] => [...PRESETS, ...mine];\n\n/** The line under the toolbar: what a click does now. */\nexport function hintFor(tool: string | null, label: string | undefined, state: { hand: boolean; nodes: number; edges: number }, t: EditorText): string {\n if (label !== undefined) {\n if (tool === LAN_TOOL) return t.hints.lan;\n return tool === NOTE_TOOL ? t.hints.note : t.hints.place(label);\n }\n if (state.hand) return t.hints.hand;\n return state.nodes >= 2 && state.edges === 0 ? t.hints.cable : t.hints.select;\n}\n", "/**\n * The desktop app's commands (Isothrum desktop loads this editor in its window and exposes them\n * on `window.__TAURI__`). In a browser there is no such object, and the desktop-only controls\n * (Run, Stop, Capture) stay hidden.\n */\nexport type Invoke = <T>(command: string, args?: Record<string, unknown>) => Promise<T>;\n\ninterface TauriWindow {\n __TAURI__?: { core?: { invoke?: Invoke } };\n}\n\nexport function desktop(): Invoke | null {\n if (typeof window === \"undefined\") return null;\n const tauri = (window as unknown as TauriWindow).__TAURI__;\n return tauri?.core?.invoke ?? null;\n}\n\n/**\n * Whether the desktop app runs the lab on VMs (with Vagrant): it runs it on Docker whenever Isoloom\n * generates its Docker files, which a machine drawn as a Linux VM has (its OS and steps build a\n * container); only a lab with a machine that is a VM only (Windows, a playbook step) needs VMs.\n */\nexport function runsOnVms(hasVmNodes: boolean, plan: { files: { path: string }[] } | null): boolean {\n return hasVmNodes && !(plan?.files.some((f) => f.path === \".isoloom/docker/compose.yml\") ?? false);\n}\n\n/** One machine now (desktop: `lab_live`): Docker's state, and its health when it has a check. */\nexport interface MachineLive {\n state: string;\n health: string;\n}\n/** One machine's port on one network now: up, down, or unknown (stopped, or a Cisco OS's). */\ninterface PortLive {\n machine: string;\n network: string;\n up: boolean | null;\n interface: string | null;\n}\n/** The running lab now. `probed`: the ports were read from the machines (not inferred). */\nexport interface LabLive {\n machines: Record<string, MachineLive>;\n ports: PortLive[];\n probed: boolean;\n}\n\n/** A machine at a glance: up, on its way (starting, restarting), unhealthy, or down. */\nexport type Status = \"up\" | \"starting\" | \"unhealthy\" | \"down\";\n\nexport function machineStatus(m: MachineLive | undefined): Status {\n if (!m) return \"down\";\n if (m.state === \"restarting\" || m.state === \"created\") return \"starting\";\n if (m.state !== \"running\") return \"down\";\n if (m.health === \"unhealthy\") return \"unhealthy\";\n return m.health === \"starting\" ? \"starting\" : \"up\";\n}\n\n/** A link cut while the lab runs: `machine`'s port on `network`, down. */\nexport interface SuspendedLink {\n network: string;\n machine: string;\n}\n\n/** A machine saved as an image (desktop: `docker commit`). */\nexport interface Snapshot {\n id: string;\n machine: string;\n image: string;\n label: string;\n created: number;\n in_use: boolean;\n}\n\nexport interface DesktopInfo {\n version: string;\n docker: boolean;\n vagrant?: boolean;\n wireshark: boolean;\n live_capture: boolean;\n labs: string;\n}\n\n/** A line of `docker compose ps --format json` (nothing in particular when it isn't one). */\nfunction serviceLine(line: string): { State?: string } {\n try {\n return JSON.parse(line) as { State?: string };\n } catch {\n return {};\n }\n}\n\n/** `docker compose ps --format json`: one JSON object per line. */\nexport function runningServices(ps: string): number {\n return ps\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter(Boolean)\n .map(serviceLine)\n .filter((s) => s.State === \"running\").length;\n}\n", "import { networkOfCable } from \"./cables\";\nimport { insideLan, lanUnder, sideOnLan } from \"./geometry\";\nimport { centerOf, isAppliance, isMachine, isRealRouter, isSwitch, type CableEdge, type LabNode, type LanNode, type Side } from \"./model\";\nimport { vlanColor, vlanOf } from \"./vlans\";\n\n/** Which way ports face and where cables attach: worked out from where things are on the canvas. */\n\n/** A node's vertical middle, by its measured height (its top when it hasn't been measured). */\nconst middleY = (n: LabNode) => n.position.y + (n.height ?? n.measured?.height ?? 0) / 2;\n\n/** The nodes at the other end of `n`'s cables. */\nfunction peersOf(n: LabNode, nodes: LabNode[], edges: CableEdge[]): LabNode[] {\n return edges\n .filter((e) => e.source === n.id || e.target === n.id)\n .flatMap((e) => nodes.find((x) => x.id === (e.source === n.id ? e.target : e.source)) ?? []);\n}\n\n/**\n * Which way each appliance's single port faces, by node id. On a LAN's edge: out of the LAN.\n * Elsewhere: toward its cables (down when they mostly lead below it), so they don't cross the box.\n */\nfunction applianceSides(nodes: LabNode[], edges: CableEdge[], lans: LanNode[], out: Record<string, Side>): void {\n for (const n of nodes) {\n if (!isAppliance(n)) continue;\n const side = sideOnLan(n, lans);\n if (side) {\n out[n.id] = side;\n continue;\n }\n const peers = peersOf(n, nodes, edges);\n const below = peers.filter((x) => middleY(x) > n.position.y + 58).length;\n if (peers.length && below > peers.length / 2) out[n.id] = \"bottom\";\n }\n}\n\n/** A switch's (or a real router's) port faces up, `<id>:<port>`, when the device on it is above. */\nfunction portSides(nodes: LabNode[], edges: CableEdge[], out: Record<string, Side>): void {\n for (const e of edges) {\n for (const [end, handle, other] of [\n [e.source, e.sourceHandle, e.target],\n [e.target, e.targetHandle, e.source],\n ] as const) {\n const sw = nodes.find((x) => x.id === end);\n const peer = nodes.find((x) => x.id === other);\n if (sw && peer && (isSwitch(sw) || isRealRouter(sw)) && handle && middleY(peer) < sw.position.y) out[`${sw.id}:${handle}`] = \"top\";\n }\n }\n}\n\n/** The sides ports face: an appliance's by its id, a switch's or router's ports by `<id>:<port>`. */\nexport function facingSides(nodes: LabNode[], edges: CableEdge[], lans: LanNode[]): Record<string, Side> {\n const out: Record<string, Side> = {};\n applianceSides(nodes, edges, lans, out);\n portSides(nodes, edges, out);\n return out;\n}\n\n/** The side of a LAN another node lies toward, relative to the LAN's own proportions. */\nfunction lanSideToward(lan: LabNode, other: LabNode): Side {\n const a = centerOf(lan);\n const b = centerOf(other);\n const dx = (b.x - a.x) / (lan.width ?? lan.measured?.width ?? 1);\n const dy = (b.y - a.y) / (lan.height ?? lan.measured?.height ?? 1);\n if (Math.abs(dx) > Math.abs(dy)) return dx > 0 ? \"right\" : \"left\";\n return dy > 0 ? \"bottom\" : \"top\";\n}\n\n/**\n * Where a cable attaches to `n`, going to `other`. A switch keeps the port the cable is plugged\n * into, and a real router its port. An appliance on a LAN's edge: its inside port toward machines\n * in that LAN, the outside one otherwise. A machine: its top or bottom, whichever faces the\n * other end. A LAN: its side facing the other end.\n */\nfunction handleFor(n: LabNode, handle: string | null | undefined, other: LabNode, lans: LanNode[]): string | null | undefined {\n if (isSwitch(n) || isRealRouter(n)) return handle;\n if (isAppliance(n)) {\n const under = lanUnder(n, lans);\n return under && insideLan(centerOf(other), under.lan) ? \"lan\" : \"port\";\n }\n if (isMachine(n)) return centerOf(other).y < centerOf(n).y ? \"top\" : \"bottom\";\n return lanSideToward(n, other);\n}\n\n/**\n * The cables as drawn: each end attached where things are now (not where the cable was first\n * drawn), and a cable on a VLAN (a switch access port, a VLAN area, a router port on it) in its\n * color.\n */\nexport function shownCables(nodes: LabNode[], edges: CableEdge[], lans: LanNode[]): CableEdge[] {\n const byId = new Map(nodes.map((n) => [n.id, n]));\n return edges.map((e) => {\n const a = byId.get(e.source);\n const b = byId.get(e.target);\n if (!a || !b) return e;\n const net = networkOfCable(e.id, nodes, edges);\n const vlan = net ? vlanOf(net) : null;\n const data = e.data && vlan !== null ? { ...e.data, color: vlanColor(vlan) } : e.data;\n return { ...e, data, sourceHandle: handleFor(a, e.sourceHandle, b, lans), targetHandle: handleFor(b, e.targetHandle, a, lans) };\n });\n}\n", "import { machineEnds, networkOfCable } from \"./cables\";\nimport { machineStatus, type LabLive, type Status, type SuspendedLink } from \"./desktop\";\nimport type { CableEdge, LabNode } from \"./model\";\n\n/**\n * The running lab as the canvas shows it (desktop app; null: not running, or in a browser).\n * Machines by name; ports by `machine/network` (up, down, or null: unknown); cables by edge id;\n * LANs by name, with how many of their ports are up.\n */\nexport type CableStatus = \"up\" | \"cut\" | \"down\" | \"unknown\";\nexport interface LiveView {\n machines: Partial<Record<string, { status: Status; detail: string }>>;\n ports: Partial<Record<string, boolean | null>>;\n cables: Partial<Record<string, CableStatus>>;\n lans: Partial<Record<string, { up: number; total: number }>>;\n}\n\n/** A cable now: cut (suspended), down (a port or a machine is), up (both ports are), or unknown. */\nfunction cableStatus(view: Pick<LiveView, \"machines\" | \"ports\">, network: string, ends: string[], links: SuspendedLink[]): CableStatus {\n if (links.some((l) => l.network === network && ends.includes(l.machine))) return \"cut\";\n const states = ends.map((m) => view.ports[`${m}/${network}`]);\n if (states.some((s) => s === false) || ends.some((m) => view.machines[m]?.status === \"down\")) return \"down\";\n return states.length && states.every((s) => s === true) ? \"up\" : \"unknown\";\n}\n\n/** Each LAN's ports up, out of all. */\nfunction lansLive(live: LabLive): LiveView[\"lans\"] {\n const lans: Record<string, { up: number; total: number }> = {};\n for (const p of live.ports) {\n const l = (lans[p.network] ??= { up: 0, total: 0 });\n l.total += 1;\n if (p.up === true) l.up += 1;\n }\n return lans;\n}\n\nexport function liveViewOf(live: LabLive, links: SuspendedLink[], nodes: LabNode[], edges: CableEdge[]): LiveView {\n const ports: Record<string, boolean | null> = {};\n for (const p of live.ports) ports[`${p.machine}/${p.network}`] = p.up;\n const machines = Object.fromEntries(\n Object.entries(live.machines).map(([m, l]) => [m, { status: machineStatus(l), detail: l.health ? `${l.state}, ${l.health}` : l.state }]),\n );\n const cables: Record<string, CableStatus> = {};\n for (const e of edges) {\n const network = networkOfCable(e.id, nodes, edges);\n if (network) cables[e.id] = cableStatus({ machines, ports }, network, machineEnds(e, nodes), links);\n }\n return { machines, ports, cables, lans: lansLive(live) };\n}\n", "import { networkOfCable } from \"./cables\";\nimport { lanUnder } from \"./geometry\";\nimport { applianceInterface, isRealRouter, isSwitch, routerPort, type CableEdge, type LabNode, type LanNode, type MachineNode } from \"./model\";\nimport { isTrunkPort, switchLans, trunkInterface, trunkStripes, vlanColor, vlanName, vlanOf } from \"./vlans\";\n\n/**\n * A real router's interfaces: each port's color (striped when it is a trunk), and the list of\n * interfaces with the network and address on each; a trunk port has one sub-interface per VLAN\n * (eth0.10, eth0.20), as router-on-a-stick.\n */\nexport interface RouterPorts {\n colors: Partial<Record<string, string>>;\n interfaces: { name: string; network: string; ip?: string; color: string }[];\n}\n\n/** Each machine's addresses (from the engine), by machine name: [network, IPv4][]. */\nexport type Addresses = Partial<Record<string, [string, string][]>>;\n\ninterface Wiring {\n nodes: LabNode[];\n edges: CableEdge[];\n lans: LanNode[];\n /** A network's color: a VLAN's own, a LAN's blue, gray for a point-to-point cable. */\n colorOf: (net: string) => string;\n /** A switch's LAN name, by its id. */\n lanOfSwitch: (id: string) => string;\n}\n\n/** One router's interfaces: its cabled ports, an appliance's own names, the LAN it sits on. */\nfunction portsOf(w: Wiring, r: MachineNode, ips: [string, string][]): RouterPorts {\n const ipOn = (net: string) => ips.find(([n]) => n === net)?.[1];\n const view: RouterPorts = { colors: {}, interfaces: [] };\n const add = (name: string, net: string) => view.interfaces.push({ name, network: net, ip: ipOn(net), color: w.colorOf(net) });\n for (const e of w.edges) cabledPort(w, r, e, view, add);\n // Cisco IOL: Isoloom numbers its interfaces in the order of its networks (Ethernet0/0 is\n // management), which is the order of its addresses.\n const kind = r.data.appliance;\n if (kind) view.interfaces = ips.map(([net, ip], k) => ({ name: applianceInterface(kind, k + 1), network: net, ip, color: w.colorOf(net) }));\n // On a LAN's edge, the LAN is on the first port no cable uses.\n const under = lanUnder(r, w.lans);\n if (under) {\n let i = 0;\n while (view.colors[routerPort(i)] && i < 63) i++;\n add(routerPort(i), under.lan.data.name);\n view.colors[routerPort(i)] = w.colorOf(under.lan.data.name);\n }\n view.interfaces.sort((x, y) => x.name.localeCompare(y.name, undefined, { numeric: true }));\n return view;\n}\n\n/**\n * The port cable `e` plugs into on router `r`, if it does: on a switch's trunk, one sub-interface\n * per VLAN, named as Isoloom names them (after the switch's LAN: `sw1.10`), and the port striped\n * with their colors; otherwise the cable's network.\n */\nfunction cabledPort(w: Wiring, r: MachineNode, e: CableEdge, view: RouterPorts, add: (name: string, net: string) => void): void {\n const mine = e.source === r.id ? e.sourceHandle : e.target === r.id ? e.targetHandle : null;\n if (!mine) return;\n const other = w.nodes.find((n) => n.id === (e.source === r.id ? e.target : e.source));\n const otherHandle = e.source === r.id ? e.targetHandle : e.sourceHandle;\n if (other && isSwitch(other) && isTrunkPort(other, otherHandle)) {\n const trunk = trunkInterface(w.lanOfSwitch(other.id));\n other.data.vlans.forEach((v) => {\n add(`${trunk}.${String(v.id)}`, vlanName(v.id));\n });\n view.colors[mine] = trunkStripes(other.data.vlans);\n return;\n }\n const net = networkOfCable(e.id, w.nodes, w.edges);\n if (!net) return;\n add(mine, net);\n view.colors[mine] = w.colorOf(net);\n}\n\n/**\n * Each real router's interfaces, by node id: the network on each port, its address there, and a\n * color. On a LAN's edge, the LAN is on eth0 (or the first port no cable uses).\n */\nexport function routerPortsOf(nodes: LabNode[], edges: CableEdge[], lans: LanNode[], addresses: Addresses): Record<string, RouterPorts> {\n const lanNames = new Set(lans.map((l) => l.data.name));\n const colorOf = (net: string) => {\n const v = vlanOf(net);\n if (v !== null) return vlanColor(v);\n return lanNames.has(net) ? \"#74c0fc\" : \"#adb5bd\";\n };\n const w: Wiring = { nodes, edges, lans, colorOf, lanOfSwitch: switchLans(nodes, edges) };\n return Object.fromEntries(nodes.filter(isRealRouter).map((r) => [r.id, portsOf(w, r, addresses[r.data.name] ?? [])]));\n}\n", "import { tcOf, type Tc } from \"./conditions\";\nimport { lansAround } from \"./geometry\";\nimport { idleByDefault, isLan, isMachine, isSwitch, type CableEdge, type LabNode, type MachineData } from \"./model\";\nimport { readPorts, type Service } from \"./ports\";\nimport { accessVlan, isTrunkPort, switchLans, vlanName } from \"./vlans\";\n\n/** The lab as the engine's topology JSON (`isothrum_compiler::Topology`). */\n\n/** Machine id -> the LANs it is on. */\ntype Membership = Map<string, Set<string>>;\n\nfunction join(membership: Membership, machine: string, lan: string): void {\n membership.set(machine, (membership.get(machine) ?? new Set()).add(lan));\n}\n\n/** A machine on a switch port joins the port's VLAN; on the trunk, every VLAN of the switch. */\nfunction joinSwitchPorts(membership: Membership, e: CableEdge, byId: Map<string, LabNode>): void {\n const a = byId.get(e.source);\n const b = byId.get(e.target);\n for (const [m, sw, handle] of [\n [a, b, e.targetHandle],\n [b, a, e.sourceHandle],\n ] as const) {\n if (!m || !sw || !isMachine(m) || !isSwitch(sw)) continue;\n if (isTrunkPort(sw, handle)) {\n for (const v of sw.data.vlans) join(membership, m.id, vlanName(v.id));\n } else {\n const vlan = accessVlan(sw, handle);\n if (vlan !== null) join(membership, m.id, vlanName(vlan));\n }\n }\n}\n\n/** A machine is on a LAN when it sits inside its area, or when a cable runs from it to the area. */\nfunction membershipOf(nodes: LabNode[], edges: CableEdge[], byId: Map<string, LabNode>): Membership {\n const membership: Membership = new Map();\n for (const n of nodes.filter(isMachine)) for (const l of lansAround(n, nodes)) join(membership, n.id, l.data.name);\n for (const e of edges) {\n const a = byId.get(e.source);\n const b = byId.get(e.target);\n if (a && b && isMachine(a) && isLan(b)) join(membership, a.id, b.data.name);\n if (a && b && isLan(a) && isMachine(b)) join(membership, b.id, a.data.name);\n joinSwitchPorts(membership, e, byId);\n }\n return membership;\n}\n\n/** What a machine runs, as the engine's `kind`. */\nfunction kindOf(m: MachineData) {\n if (m.kind === \"router\") return { router: {} };\n if (m.kind === \"container\") {\n return {\n container: m.appliance\n ? { image: m.image.trim(), appliance: m.appliance, ...(m.config?.trim() ? { config: m.config } : {}) }\n : { image: m.image.trim(), idle: m.idle ?? idleByDefault(m.image) },\n };\n }\n const provision = m.provision\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter(Boolean);\n return { vm: { os: m.os, provision } };\n}\n\n/** The ports in a machine's field that Isoloom takes (the others are reported: `canvasIssues`). */\nconst servicesOf = (m: MachineData): Service[] => readPorts(m.ports).services;\n\n/** Cables between two machines; a cable to a LAN is a membership, not a link. */\nfunction linksOf(edges: CableEdge[], byId: Map<string, LabNode>) {\n return edges.flatMap((e) => {\n const a = byId.get(e.source);\n const b = byId.get(e.target);\n if (!a || !b || !isMachine(a) || !isMachine(b) || !a.data.name || !b.data.name || !e.data) return [];\n return [{ a: { node: a.data.name, port: e.data.aPort.trim() }, b: { node: b.data.name, port: e.data.bPort.trim() }, tc: tcOf(e.data.tc) }];\n });\n}\n\ninterface Net {\n cidr: string;\n internet: boolean;\n tc?: Tc;\n switch?: string;\n vlan?: number;\n}\n\n/** The LAN areas, and each switch's VLANs, which nest under it in isoloom.yml (`sw1.vlan10`). */\nfunction networksOf(nodes: LabNode[], edges: CableEdge[]): Record<string, Net> {\n const lans = nodes.filter(isLan).filter((l) => l.data.name);\n const networks: Record<string, Net> = Object.fromEntries(\n lans.map((l) => [l.data.name, { cidr: l.data.cidr.trim(), internet: l.data.internet, tc: tcOf(l.data.tc) }]),\n );\n const nameOfGroup = switchLans(nodes, edges);\n for (const sw of nodes.filter(isSwitch)) {\n for (const v of sw.data.vlans) {\n const net = (networks[vlanName(v.id)] as Net | undefined) ?? { cidr: v.cidr.trim(), internet: true };\n networks[vlanName(v.id)] = { ...net, tc: undefined, switch: nameOfGroup(sw.id), vlan: v.id };\n }\n }\n return networks;\n}\n\nexport function toTopology(name: string, nodes: LabNode[], edges: CableEdge[]): string {\n const byId = new Map(nodes.map((n) => [n.id, n]));\n const membership = membershipOf(nodes, edges, byId);\n const machines = Object.fromEntries(\n nodes\n .filter(isMachine)\n .filter((n) => n.data.name)\n .map(({ id, data: m }) => {\n const networks = Object.fromEntries([...(membership.get(id) ?? [])].map((lan) => [lan, m.pins?.[lan] ?? null]));\n return [m.name, { kind: kindOf(m), access: m.access, services: servicesOf(m), networks }];\n }),\n );\n const links = linksOf(edges, byId);\n return JSON.stringify({ name, nodes: machines, networks: networksOf(nodes, edges), links });\n}\n", "import { useCallback, useMemo, useRef } from \"react\";\nimport { addEdge, type Connection, type NodeChange } from \"@xyflow/react\";\nimport { canConnect, newCable, onLanEdge, reconnected, type LabIndex } from \"@/lib/tool/cables\";\nimport { isLan, isRealRouter, isSwitch, type CableEdge, type LabNode, type LanNode } from \"@/lib/tool/model\";\nimport { snapMoves } from \"@/lib/tool/placement\";\nimport type { Lab } from \"./use-lab\";\n\n/** The ids of the LANs, switches and real routers, and the LANs themselves. */\nexport function useLabIndex(nodes: LabNode[]): LabIndex & { lans: LanNode[] } {\n const lanIds = useMemo(() => new Set(nodes.filter(isLan).map((n) => n.id)), [nodes]);\n const lans = useMemo(() => nodes.filter(isLan), [nodes]);\n const switchIds = useMemo(() => new Set(nodes.filter(isSwitch).map((n) => n.id)), [nodes]);\n const routerIds = useMemo(() => new Set(nodes.filter(isRealRouter).map((n) => n.id)), [nodes]);\n return useMemo(() => ({ lanIds, lans, switchIds, routerIds }), [lanIds, lans, switchIds, routerIds]);\n}\n\n/**\n * Drawing and moving cables. Machine to machine, LAN or port; never LAN to LAN or switch to LAN;\n * a switch or router port takes one cable. Cables can be moved: drag either end onto another\n * machine, LAN or port, or onto the canvas to unplug it.\n */\nexport function useCabling(lab: Lab, index: LabIndex & { lans: LanNode[] }) {\n const { nodes, edges, setEdges, onNodesChange } = lab;\n // Routers, firewalls and switches are magnetic: dragged near a LAN's border, they land on it.\n const onSnappingChange = useCallback(\n (changes: NodeChange<LabNode>[]) => {\n onNodesChange(snapMoves(changes, nodes, index.lans));\n },\n [onNodesChange, nodes, index.lans],\n );\n // The cable being moved, if any: its own ends don't count as taken while it moves.\n const moving = useRef<{ id: string; done: boolean } | null>(null);\n // An appliance on a LAN's edge already uses eth0 there: its cables start at eth1.\n const first = useCallback((id: string) => (onLanEdge(id, nodes, index.lans) ? 1 : 0), [nodes, index.lans]);\n const isValid = useCallback((c: Parameters<typeof canConnect>[0]) => canConnect(c, index, edges, moving.current?.id), [index, edges]);\n const onReconnect = useCallback(\n (old: CableEdge, c: Connection) => {\n if (!c.source || !c.target || !canConnect(c, index, edges, moving.current?.id)) return;\n if (moving.current) moving.current.done = true;\n setEdges((es) => reconnected(es, old, c, index, first));\n },\n [index, edges, setEdges, first],\n );\n const onConnect = useCallback(\n (c: Connection) => {\n if (!c.source || !c.target || c.source === c.target) return;\n setEdges((es) => addEdge<CableEdge>(newCable(c, index, es, first), es));\n },\n [setEdges, index, first],\n );\n return {\n onNodesChange: onSnappingChange,\n isValid,\n onConnect,\n onReconnect,\n onReconnectStart: (_: unknown, edge: CableEdge) => {\n moving.current = { id: edge.id, done: false };\n },\n // Dropped nowhere: the cable is unplugged.\n onReconnectEnd: () => {\n const m = moving.current;\n if (m && !m.done) setEdges((es) => es.filter((e) => e.id !== m.id));\n moving.current = null;\n },\n };\n}\n", "import type { XYPosition } from \"@xyflow/react\";\nimport { LAN_BEHAVIOR, LAN_H, LAN_W, freeName, isLan, uid, type LabNode, type LanData, type LanNode, type MachineData, type MachineNode, type NoteNode, type SwitchNode } from \"./model\";\nimport type { Preset } from \"./presets\";\n\n/** New nodes, as the toolbar places them. */\n\nexport function newNote(position: XYPosition): NoteNode {\n return { id: uid(\"n\"), type: \"note\", position, width: 200, height: 90, selected: true, data: { text: \"\", shape: \"text\", color: \"yellow\" } };\n}\n\n/** vlan10 and vlan20: a new switch's VLANs (ports 1\u20134 and 5\u20138, both on the trunk). */\nexport function twoVlans(): SwitchNode[\"data\"] {\n return {\n name: \"\",\n vlans: [\n { id: 10, cidr: \"10.10.10.0/24\" },\n { id: 20, cidr: \"10.10.20.0/24\" },\n ],\n ports: [10, 10, 10, 10, 20, 20, 20, 20],\n };\n}\n\n/** A new switch with vlan10 on ports 1\u20134, vlan20 on ports 5\u20138, both on the trunk. */\nexport function newSwitch(center: XYPosition, nodes: LabNode[]): SwitchNode {\n return {\n id: uid(\"s\"),\n type: \"switch\",\n position: { x: center.x - 170, y: center.y - 40 },\n data: { ...twoVlans(), name: freeName(\"sw\", nodes) },\n };\n}\n\nexport function newMachine(preset: Preset, position: XYPosition, nodes: LabNode[]): MachineNode {\n const name = freeName(preset.prefix, nodes);\n const data: MachineData = { ...preset.data, name };\n // Isoloom needs a VM's provisioning steps, except on the access machine (the runner supplies it).\n if (data.kind === \"vm\" && !data.access && !data.provision) {\n data.provision = `provision/${name}.${data.os.startsWith(\"windows\") ? \"ps1\" : \"sh\"}`;\n }\n return { id: uid(\"m\"), type: \"machine\", position, data };\n}\n\n/** The third number of each LAN's 10.10.<n>.0/24 block. */\nexport function usedThirds(nodes: LabNode[]): Set<number> {\n return new Set(\n nodes\n .filter(isLan)\n .map((n) => /^10\\.10\\.(\\d+)\\./.exec(n.data.cidr)?.[1])\n .filter(Boolean)\n .map(Number),\n );\n}\n\n/** A new LAN centered on `center`, with the next free 10.10.<n>.0/24. */\nexport function newLan(center: XYPosition, nodes: LabNode[]): LanNode {\n const used = usedThirds(nodes);\n let third = 1;\n while (used.has(third)) third++;\n return {\n ...LAN_BEHAVIOR,\n id: uid(\"l\"),\n type: \"lan\",\n position: { x: center.x - LAN_W / 2, y: center.y - LAN_H / 2 },\n width: LAN_W,\n height: LAN_H,\n data: { name: freeName(\"lan\", nodes), cidr: `10.10.${String(third)}.0/24`, internet: true },\n };\n}\n\n/**\n * A LAN that hangs under a device placed at `center` (a router or a switch): the device sits on\n * its top edge, toward the right, so the LAN's label (top left) stays clear and clickable.\n */\nexport function lanBelow(center: XYPosition, nodes: LabNode[], data?: Partial<LanData>, size = { w: LAN_W, h: LAN_H }): LanNode {\n const lan = newLan({ x: center.x, y: center.y + size.h / 2 }, nodes);\n return {\n ...lan,\n width: size.w,\n height: size.h,\n position: { x: center.x - size.w * 0.74, y: center.y },\n data: { ...lan.data, ...data },\n };\n}\n", "import type { NodeChange, XYPosition } from \"@xyflow/react\";\nimport { lanBelow, newMachine, newSwitch } from \"./create\";\nimport { snapToLanEdge } from \"./geometry\";\nimport { MACHINE_H, MACHINE_W, ROUTER_H, ROUTER_W, SWITCH_H, SWITCH_W, isAppliance, isRealRouter, isSwitch, sizeOf, unselected, type LabNode, type LanNode } from \"./model\";\nimport type { Preset } from \"./presets\";\nimport { vlanName } from \"./vlans\";\n\n/** Placing devices: where they land, and what comes with them. */\n\n/** A device placed from the palette (no point given): in the middle of the view, staggered so machines added in a row don't stack exactly. */\nexport function paletteSpot(viewCenter: XYPosition, nodes: LabNode[]): XYPosition {\n const step = (nodes.length % 5) * 24;\n return { x: viewCenter.x - 56 + step, y: viewCenter.y - 40 + step };\n}\n\n/**\n * The nodes after placing a router or firewall at `position`: near a LAN's border it lands on\n * it, as when dragged; away from any LAN it comes with its own LAN under it (it is that LAN's\n * gateway). `dropped`: placed at a point (a click, a drop), centered there like a machine.\n */\nexport function placeAppliance(preset: Preset, position: XYPosition, dropped: boolean, nodes: LabNode[], lans: LanNode[]): LabNode[] {\n const real = isRealRouter({ id: \"\", type: \"machine\", position, data: { ...preset.data, name: \"\" } });\n const size = real ? { w: ROUTER_W, h: ROUTER_H } : { w: MACHINE_W, h: MACHINE_H };\n const at = dropped ? { x: position.x + MACHINE_W / 2 - size.w / 2, y: position.y + MACHINE_H / 2 - size.h / 2 } : position;\n const snapped = snapToLanEdge(at, lans, size);\n const m = { ...newMachine(preset, snapped, nodes), selected: true };\n if (snapped !== at) return [...unselected(nodes), m];\n const lan = lanBelow({ x: snapped.x + size.w / 2, y: snapped.y + size.h / 2 }, [...nodes, m]);\n return [lan, ...unselected(nodes), m];\n}\n\n/** The nodes after placing a machine at `position`, selected. */\nexport function placeMachine(preset: Preset, position: XYPosition, nodes: LabNode[]): LabNode[] {\n return [...unselected(nodes), { ...newMachine(preset, position, nodes), selected: true }];\n}\n\n/**\n * The nodes after placing a switch at `at`: on a LAN's edge when near one; away from any LAN it\n * comes with its LAN, its first VLAN, hanging under it.\n */\nexport function placeSwitch(at: XYPosition, nodes: LabNode[], lans: LanNode[]): LabNode[] {\n const sw = newSwitch(at, nodes);\n const snapped = snapToLanEdge(sw.position, lans, { w: SWITCH_W, h: SWITCH_H });\n const placed = { ...sw, position: snapped, selected: true };\n if (snapped !== sw.position) return [...unselected(nodes), placed];\n const first = sw.data.vlans[0];\n const lan = lanBelow({ x: sw.position.x + SWITCH_W / 2, y: sw.position.y + SWITCH_H / 2 }, nodes, { name: vlanName(first.id), cidr: first.cidr }, { w: 600, h: 300 });\n return [lan, ...unselected(nodes), placed];\n}\n\n/** Routers, firewalls and switches are magnetic: dragged near a LAN's border, they land on it. */\nexport function snapMoves(changes: NodeChange<LabNode>[], nodes: LabNode[], lans: LanNode[]): NodeChange<LabNode>[] {\n return changes.map((c) => {\n if (c.type !== \"position\" || !c.position) return c;\n const n = nodes.find((x) => x.id === c.id);\n if (n && isAppliance(n)) return { ...c, position: snapToLanEdge(c.position, lans, sizeOf(n)) };\n if (n && isSwitch(n)) return { ...c, position: snapToLanEdge(c.position, lans, { w: SWITCH_W, h: SWITCH_H }) };\n return c;\n });\n}\n", "import { useState } from \"react\";\nimport type { Invoke } from \"@/lib/tool/desktop\";\n\n/** Captures in progress (desktop): network -> the .pcap file, or null when Wireshark shows it live. */\nexport function useCaptures(invoke: Invoke | null, labName: string, onError: (error: string) => void) {\n const [captures, setCaptures] = useState<Record<string, string | null>>({});\n async function capture(network: string) {\n if (!invoke) return;\n try {\n const res = await invoke<{ file: string | null }>(\"capture_start\", { name: labName, network });\n setCaptures((c) => ({ ...c, [network]: res.file }));\n } catch (e) {\n onError(String(e));\n }\n }\n async function stopCapture(network: string) {\n if (!invoke) return;\n await invoke(\"capture_stop\", { name: labName, network }).catch(() => undefined);\n setCaptures((c) => Object.fromEntries(Object.entries(c).filter(([n]) => n !== network)));\n }\n return { captures, capture, stopCapture, clearCaptures: () => { setCaptures({}); } };\n}\n\nexport type Captures = ReturnType<typeof useCaptures>;\n", "import { useCallback, useEffect, useRef } from \"react\";\nimport type { XYPosition } from \"@xyflow/react\";\nimport { cloneLab } from \"@/lib/tool/clone\";\nimport { isLan, unselected, type CableEdge, type LabNode } from \"@/lib/tool/model\";\nimport { inTextField } from \"./use-history\";\nimport type { Lab } from \"./use-lab\";\n\ntype DeleteNodes = (elements: { nodes: { id: string }[] }) => unknown;\n\n/** The cables between `picked` nodes: what goes with them when they are copied. */\nfunction cablesWithin(picked: LabNode[], edges: CableEdge[]): CableEdge[] {\n const ids = new Set(picked.map((n) => n.id));\n return edges.filter((c) => ids.has(c.source) && ids.has(c.target));\n}\n\n/**\n * Copy, cut, paste and duplicate (Ctrl/\u2318 C, X, V, D). Copies get new names and ids, a LAN its own\n * block; LANs go first in the list so they stay under the machines.\n */\nexport function useClipboard(lab: Lab, deleteElements: DeleteNodes): void {\n const { nodes, edges, setNodes, setEdges } = lab;\n const clipboard = useRef<{ nodes: LabNode[]; edges: CableEdge[]; pastes: number } | null>(null);\n const addCopies = useCallback(\n (picked: LabNode[], from: CableEdge[], offset: XYPosition) => {\n const copies = cloneLab(picked, from, nodes, offset);\n setNodes([...copies.nodes.filter(isLan), ...unselected(nodes), ...copies.nodes.filter((n) => !isLan(n))]);\n setEdges((es) => [...unselected(es), ...copies.edges]);\n },\n [nodes, setNodes, setEdges],\n );\n useEffect(() => {\n function onKey(e: KeyboardEvent) {\n if (inTextField(e)) return;\n if (!(e.metaKey || e.ctrlKey) || e.shiftKey) return;\n const key = e.key.toLowerCase();\n const picked = nodes.filter((n) => n.selected);\n const pasted = clipboard.current;\n if ((key === \"c\" || key === \"x\") && picked.length) {\n clipboard.current = { nodes: picked, edges: cablesWithin(picked, edges), pastes: 0 };\n if (key === \"x\") void deleteElements({ nodes: picked.map((n) => ({ id: n.id })) });\n } else if (key === \"v\" && pasted) {\n pasted.pastes += 1;\n addCopies(pasted.nodes, pasted.edges, { x: 40 * pasted.pastes, y: 40 * pasted.pastes });\n } else if (key === \"d\" && picked.length) {\n addCopies(picked, cablesWithin(picked, edges), { x: 40, y: 40 });\n } else return;\n e.preventDefault();\n }\n window.addEventListener(\"keydown\", onKey);\n return () => {\n window.removeEventListener(\"keydown\", onKey);\n };\n }, [nodes, edges, addCopies, deleteElements]);\n}\n", "import type { XYPosition } from \"@xyflow/react\";\nimport { usedThirds } from \"./create\";\nimport { freeName, uid, type CableEdge, type LabNode } from \"./model\";\n\nconst idPrefix: Record<LabNode[\"type\"], string> = { lan: \"l\", switch: \"s\", note: \"n\", machine: \"m\" };\n\n/** The next free 10.10.<n>.0/24 for a copied LAN (and taken from then on). */\nfunction takeThird(used: Set<number>): number {\n let third = 1;\n while (used.has(third)) third++;\n used.add(third);\n return third;\n}\n\n/** A copy of `n` with a fresh name (web1 -> web3) at `position`, its LAN block taken from `used`. */\nfunction copyOf(n: Exclude<LabNode, { type: \"note\" }>, id: string, position: XYPosition, all: LabNode[], used: Set<number>): LabNode {\n const name = freeName(n.data.name.replace(/\\d+$/, \"\") || \"copy\", all);\n if (n.type === \"lan\") return { ...n, id, position, selected: true, data: { ...n.data, name, cidr: `10.10.${String(takeThird(used))}.0/24` } };\n if (n.type === \"machine\") return { ...n, id, position, selected: true, data: { ...n.data, name, pins: undefined } };\n return { ...n, id, position, selected: true, data: { ...n.data, name, vlans: n.data.vlans.map((v) => ({ ...v })), ports: [...n.data.ports] } };\n}\n\n/**\n * Copies of `picked` (and of the cables between them) ready to add to `existing`: new ids,\n * moved by `offset`, fresh names (web1 -> web3), a LAN with its own free block, no fixed\n * addresses (they would collide with the originals). VLANs keep their numbers: they are\n * lab-wide.\n */\nexport function cloneLab(picked: LabNode[], edges: CableEdge[], existing: LabNode[], offset: XYPosition): { nodes: LabNode[]; edges: CableEdge[] } {\n const ids = new Map<string, string>();\n const all: LabNode[] = [...existing];\n const used = usedThirds(all);\n const nodes = picked.map((n) => {\n const id = uid(idPrefix[n.type]);\n ids.set(n.id, id);\n const position = { x: n.position.x + offset.x, y: n.position.y + offset.y };\n const copy: LabNode = n.type === \"note\" ? { ...n, id, position, selected: true, data: { ...n.data } } : copyOf(n, id, position, all, used);\n all.push(copy);\n return copy;\n });\n const copies = edges.flatMap((e) => {\n const source = ids.get(e.source);\n const target = ids.get(e.target);\n if (source === undefined || target === undefined) return [];\n return [{ ...e, id: uid(\"c\"), source, target, selected: false, data: e.data ? { ...e.data } : e.data }];\n });\n return { nodes, edges: copies };\n}\n", "import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { CableEdge, LabNode } from \"@/lib/tool/model\";\nimport type { Lab } from \"./use-lab\";\n\n/** A lab as the history keeps it: nothing selected or being dragged. */\ninterface Snapshot {\n nodes: LabNode[];\n edges: CableEdge[];\n}\n\nfunction snapshot(nodes: LabNode[], edges: CableEdge[]): Snapshot {\n return {\n nodes: nodes.map((n) => ({ ...n, selected: false, dragging: false })),\n edges: edges.map((e) => ({ ...e, selected: false })),\n };\n}\n\n/** What a change to the lab is (not selection, not the sizes React Flow measures). */\nfunction signature(nodes: LabNode[], edges: CableEdge[]): string {\n return JSON.stringify([\n nodes.map((n) => [n.id, n.type, n.position.x, n.position.y, n.width, n.height, n.data]),\n edges.map((e) => [e.id, e.source, e.sourceHandle, e.target, e.targetHandle, e.data?.aPort, e.data?.bPort]),\n ]);\n}\n\ninterface History {\n past: Snapshot[];\n future: Snapshot[];\n current: Snapshot;\n sig: string;\n last: number;\n applying: boolean;\n}\n\n/** Records a change: changes in quick succession (a drag, typing a name) count as one. */\nfunction record(h: History, nodes: LabNode[], edges: CableEdge[], sig: string): void {\n const now = Date.now();\n if (!h.applying) {\n if (now - h.last > 700) {\n h.past.push(h.current);\n if (h.past.length > 200) h.past.shift();\n }\n h.future = [];\n h.last = now;\n }\n h.applying = false;\n h.current = snapshot(nodes, edges);\n h.sig = sig;\n}\n\n/** Undo and redo. Every change to the lab goes into the history. */\nexport function useHistory(lab: Lab) {\n const { initial, nodes, edges, setNodes, setEdges } = lab;\n const history = useRef<History>({ past: [], future: [], current: snapshot(initial.nodes, initial.edges), sig: signature(initial.nodes, initial.edges), last: 0, applying: false });\n const [canUndo, setCanUndo] = useState(false);\n const [canRedo, setCanRedo] = useState(false);\n useEffect(() => {\n const h = history.current;\n const sig = signature(nodes, edges);\n if (sig === h.sig) return;\n record(h, nodes, edges, sig);\n queueMicrotask(() => {\n setCanUndo(h.past.length > 0);\n setCanRedo(h.future.length > 0);\n });\n }, [nodes, edges]);\n const step = useCallback(\n (back: boolean) => {\n const h = history.current;\n const target = (back ? h.past : h.future).pop();\n if (!target) return;\n (back ? h.future : h.past).push(h.current);\n h.applying = true;\n h.last = 0;\n setNodes(target.nodes);\n setEdges(target.edges);\n },\n [setNodes, setEdges],\n );\n useUndoKeys(step);\n return { step, canUndo, canRedo };\n}\n\n/** Whether a key event happens in a text field (where the keys edit the text, as everywhere else). */\nexport function inTextField(e: KeyboardEvent): boolean {\n return e.target instanceof Element && e.target.closest(\"input, textarea, select, [contenteditable]\") !== null;\n}\n\n/** Ctrl/\u2318 Z undoes, Ctrl/\u2318 Shift Z or Y redoes. */\nfunction useUndoKeys(step: (back: boolean) => void): void {\n useEffect(() => {\n function onKey(e: KeyboardEvent) {\n // In a text field, the keys undo the typing, as everywhere else.\n if (inTextField(e)) return;\n if (!(e.metaKey || e.ctrlKey)) return;\n const key = e.key.toLowerCase();\n if (key === \"z\" && !e.shiftKey) step(true);\n else if ((key === \"z\" && e.shiftKey) || key === \"y\") step(false);\n else return;\n e.preventDefault();\n }\n window.addEventListener(\"keydown\", onKey);\n return () => {\n window.removeEventListener(\"keydown\", onKey);\n };\n }, [step]);\n}\n", "import { useState } from \"react\";\n\n/** A right-click on a machine (desktop): its console, its screen, starting or stopping it. */\nexport interface MachineMenuAt {\n x: number;\n y: number;\n machine: string;\n}\n\n/**\n * A right-click on a cable or a LAN (desktop): capture its traffic, suspend or resume it.\n * `machines`: a cable's ends that are machines (their ports); none for a whole LAN.\n */\nexport interface LinkMenuAt {\n x: number;\n y: number;\n network: string;\n title: string;\n machines?: string[];\n}\n\n/** The right-click menus open on the canvas (desktop app only). */\nexport function useContextMenus() {\n const [machineMenu, setMachineMenu] = useState<MachineMenuAt | null>(null);\n const [linkMenu, setLinkMenu] = useState<LinkMenuAt | null>(null);\n return {\n machineMenu,\n setMachineMenu,\n linkMenu,\n setLinkMenu,\n closeMenus: () => {\n setMachineMenu(null);\n setLinkMenu(null);\n },\n };\n}\n\n", "import { useCallback, useEffect, useState } from \"react\";\nimport { desktop, runningServices, type DesktopInfo, type Invoke, type LabLive, type Snapshot, type SuspendedLink } from \"@/lib/tool/desktop\";\nimport { autoStarts } from \"@/lib/tool/storage\";\n\n/** The desktop app's side of the editor: running the lab on this machine (none in a browser). */\n\nexport type RunState = \"stopped\" | \"starting\" | \"running\" | \"stopping\";\n\n/** The app's commands (null in a browser), what the app says about itself, and the lab's run state. */\nexport function useDesktopState() {\n const [invoke] = useState(desktop);\n const [info, setInfo] = useState<DesktopInfo | null>(null);\n const [run, setRun] = useState<RunState>(\"stopped\");\n const [update, setUpdate] = useState<string | null>(null);\n const [updating, setUpdating] = useState(false);\n return { invoke, info, setInfo, run, setRun, update, setUpdate, updating, setUpdating };\n}\n\nexport type DesktopState = ReturnType<typeof useDesktopState>;\n\n/**\n * The running lab now (desktop): its machines' states and their ports, read from them, its\n * machines' snapshots, and the links cut. Read again every 3 seconds while it runs.\n */\nexport function useLiveLab(invoke: Invoke | null, labName: string, run: RunState) {\n const [machineStates, setMachineStates] = useState<Record<string, string>>({});\n const [snapshots, setSnapshots] = useState<Snapshot[]>([]);\n const [links, setLinks] = useState<SuspendedLink[]>([]);\n const [live, setLive] = useState<LabLive | null>(null);\n const refreshStates = useCallback(async () => {\n if (!invoke) return;\n try {\n const now = await invoke<LabLive | null>(\"lab_live\", { name: labName });\n setLive(now);\n setMachineStates(Object.fromEntries(Object.entries(now?.machines ?? {}).map(([m, l]) => [m, l.state])));\n setSnapshots(await invoke<Snapshot[]>(\"snapshot_list\", { name: labName }));\n setLinks(await invoke<SuspendedLink[]>(\"link_list\", { name: labName }));\n } catch {\n setMachineStates({});\n setLive(null);\n }\n }, [invoke, labName]);\n useEffect(() => {\n if (run !== \"running\") return;\n queueMicrotask(() => void refreshStates());\n const timer = setInterval(() => void refreshStates(), 3000);\n return () => {\n clearInterval(timer);\n };\n }, [run, refreshStates]);\n return { machineStates, snapshots, links, setLinks, live, setLive, refreshStates };\n}\n\nexport type LiveLab = ReturnType<typeof useLiveLab>;\n\n/** The Run window's state and its log. */\nexport function useRunPanel() {\n const [runOpen, setRunOpen] = useState(false);\n const [runLog, setRunLog] = useState(\"\");\n return { runOpen, setRunOpen, runLog, setRunLog };\n}\n\n/** Auto-start (desktop): this lab starts when the app opens on it, once the engine has its spec. */\nexport function useAutoStart(invoke: Invoke | null, labName: string) {\n const [autoStart, setAutoStart] = useState(false);\n const [autoStartPending, setAutoStartPending] = useState(false);\n useEffect(() => {\n if (invoke)\n queueMicrotask(() => {\n setAutoStart(autoStarts(labName));\n });\n }, [invoke, labName]);\n return { autoStart, setAutoStart, autoStartPending, setAutoStartPending };\n}\n\n/**\n * On opening: what the app says about itself, whether a newer release is out (signed; from\n * GitHub's latest release), and whether the lab still runs from before the app was reopened. If\n * not, and it is set to, it starts.\n */\nexport function useDesktopStartup(state: DesktopState, initialName: string, setAutoStartPending: (pending: boolean) => void): void {\n const { invoke, setInfo, setUpdate, setRun } = state;\n useEffect(() => {\n if (!invoke) return;\n invoke<DesktopInfo>(\"desktop_info\").then(setInfo, () => undefined);\n invoke<{ version: string } | null>(\"update_check\").then(\n (u) => {\n if (u) setUpdate(u.version);\n },\n () => undefined,\n );\n invoke<string>(\"lab_status\", { name: initialName }).then(\n (ps) => {\n if (runningServices(ps) > 0) setRun(\"running\");\n else if (autoStarts(initialName)) setAutoStartPending(true);\n },\n () => undefined,\n );\n }, [invoke, initialName, setInfo, setUpdate, setRun, setAutoStartPending]);\n}\n", "import { migrateEdges } from \"./cables\";\nimport { DESIGNS, LAN_BEHAVIOR, cleanName, type CableEdge, type Design, type Draft, type LabNode } from \"./model\";\nimport { currentMachine } from \"./os\";\n\n/** A lab as it is kept: in storage, in a saved project, or in a share link. */\n\n/** Whether `v` is one of the canvas's looks. */\nexport const isDesign = (v: unknown): v is Design => DESIGNS.some((d) => d === v);\n\n/** A lab's nodes and cables as stored: the lab only, no UI state. */\nexport function storedNodes(nodes: LabNode[]): Pick<LabNode, \"id\" | \"type\" | \"position\" | \"data\" | \"width\" | \"height\">[] {\n return nodes.map(({ id, type, position, data, width, height }) => ({ id, type, position, data, width, height }));\n}\n\nexport function storedEdges(edges: CableEdge[], data: (e: CableEdge) => CableEdge[\"data\"] = (e) => e.data): CableEdge[] {\n return edges.map((e) => ({ id: e.id, type: e.type, source: e.source, sourceHandle: e.sourceHandle, target: e.target, targetHandle: e.targetHandle, data: data(e) }));\n}\n\n/** LANs behave as frames again, machines name their OS as Isoloom does, and cables move onto today's handles. */\nfunction current(nodes: LabNode[], edges: CableEdge[]): { nodes: LabNode[]; edges: CableEdge[] } {\n const withBehavior = nodes.map((n): LabNode => {\n if (n.type === \"lan\") return { ...n, ...LAN_BEHAVIOR };\n return n.type === \"machine\" ? { ...n, data: currentMachine(n.data) } : n;\n });\n return { nodes: withBehavior, edges: migrateEdges(edges, withBehavior) };\n}\n\n/** Whether `v` is a JSON object: not null, not a list. */\nconst isRecord = (v: unknown): v is Record<string, unknown> => typeof v === \"object\" && v !== null && !Array.isArray(v);\n\n/** Whether a stored node has what the editor reads of every node: an id, a position and its data. */\nconst isNode = (v: unknown): v is LabNode => isRecord(v) && typeof v.id === \"string\" && isRecord(v.position) && isRecord(v.data);\n\n/** Whether a stored cable has what the editor reads of every cable: an id and its two ends. */\nconst isCable = (v: unknown): v is CableEdge => isRecord(v) && typeof v.id === \"string\" && typeof v.source === \"string\" && typeof v.target === \"string\";\n\n/** Whether a parsed value has the shape of a draft: a name (if any) in text, lists of nodes and cables. */\nfunction hasLists(d: unknown): d is { name?: string; nodes: LabNode[]; edges: CableEdge[]; design?: unknown } {\n if (!isRecord(d)) return false;\n const { name, nodes, edges } = d;\n if (name !== undefined && typeof name !== \"string\") return false;\n return Array.isArray(nodes) && Array.isArray(edges) && nodes.every(isNode) && edges.every(isCable);\n}\n\n/**\n * A draft from storage or a saved project, made current: LAN behavior, machines' OS names, today's cable handles.\n * Null when it isn't a lab's shape (a node or a cable that isn't one, as a damaged store holds).\n */\nexport function normalizeDraft(d: unknown): Draft | null {\n if (!hasLists(d)) return null;\n return { ...(d as Draft), ...current(d.nodes, d.edges) };\n}\n\n/** A draft without what is only UI state (selection, drag, measured sizes): what a save keeps. */\nexport function plainDraft(d: Draft): Draft {\n return {\n ...d,\n nodes: d.nodes.map((n) => {\n const c = { ...n };\n delete c.selected;\n delete c.dragging;\n delete c.measured;\n return c;\n }),\n edges: d.edges.map((e) => {\n const c = { ...e };\n delete c.selected;\n return c;\n }),\n };\n}\n\n/** Base64url without padding, as a link carries it. */\nfunction toBase64Url(bytes: Uint8Array): string {\n let bin = \"\";\n for (const b of bytes) bin += String.fromCharCode(b);\n return btoa(bin).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n/**\n * A lab in a link: its JSON, deflated, in base64url, after `#lab=`. The part after `#` never\n * reaches a server, so a shared lab stays as private as the editor (the link is the only copy).\n */\nexport async function encodeLab(draft: Draft): Promise<string> {\n const plain = {\n name: draft.name,\n // The look goes with the link, so the reader sees the diagram as it was drawn.\n ...(draft.design && draft.design !== \"sketch\" ? { design: draft.design } : {}),\n nodes: storedNodes(draft.nodes),\n // A cable keeps its ports and conditions; its color is only drawing, worked out again.\n edges: storedEdges(draft.edges, (e) => (e.data ? { aPort: e.data.aPort, bPort: e.data.bPort, tc: e.data.tc } : e.data)),\n };\n const stream = new Blob([JSON.stringify(plain)]).stream().pipeThrough(new CompressionStream(\"deflate-raw\"));\n return toBase64Url(new Uint8Array(await new Response(stream).arrayBuffer()));\n}\n\nexport async function decodeLab(code: string): Promise<Draft | null> {\n try {\n const bin = atob(code.replace(/-/g, \"+\").replace(/_/g, \"/\"));\n const bytes = Uint8Array.from(bin, (c) => c.charCodeAt(0));\n const stream = new Blob([bytes]).stream().pipeThrough(new DecompressionStream(\"deflate-raw\"));\n const d: unknown = JSON.parse(await new Response(stream).text());\n if (!hasLists(d)) return null;\n const design = isDesign(d.design) ? d.design : undefined;\n return { name: cleanName(d.name ?? \"\") || \"shared-lab\", ...current(d.nodes, d.edges), design };\n } catch {\n return null;\n }\n}\n", "import { isDesign, normalizeDraft, storedEdges, storedNodes } from \"./draft\";\nimport type { Design, Draft } from \"./model\";\nimport { currentMachine } from \"./os\";\nimport type { Preset } from \"./presets\";\n\n/**\n * What the editor keeps in this browser (localStorage). Storage can be blocked (a private\n * window) or full: then reading gives nothing and writing keeps nothing, and the editor works on.\n */\n\nconst DRAFT_KEY = \"isothrum-canvas-v1\";\nconst DEVICES_KEY = \"isothrum-devices-v1\";\nconst DESIGN_KEY = \"isothrum-design\";\nconst BLOCKS_KEY = \"isothrum-toolbar-blocks\";\nconst AUTO_START_KEY = \"isothrum-auto-start\";\nconst PROJECT_KEY = \"isothrum-project\";\n\n/** The stored value at `key`, parsed; null when there is none or it can't be read. */\nfunction read(key: string): unknown {\n try {\n const raw = localStorage.getItem(key);\n return raw === null ? null : (JSON.parse(raw) as unknown);\n } catch {\n return null;\n }\n}\n\n/** Stores `value` at `key` as JSON, or removes it when null. */\nfunction write(key: string, value: unknown): void {\n try {\n if (value === null) localStorage.removeItem(key);\n else localStorage.setItem(key, JSON.stringify(value));\n } catch {\n // Not kept: it lasts as long as the page.\n }\n}\n\n/** The last lab drawn in this browser; none (a blank canvas) when what is kept hasn't a lab's shape. */\nexport function loadDraft(): Draft | null {\n return normalizeDraft(read(DRAFT_KEY));\n}\n\n/** Keeps the lab, without its UI state (selection is not part of the lab). */\nexport function saveDraft(draft: Draft): void {\n write(DRAFT_KEY, { name: draft.name, nodes: storedNodes(draft.nodes), edges: storedEdges(draft.edges) });\n}\n\n/** Whether a stored device has what placing it needs: an id, its machine, a name prefix. */\nfunction isPreset(p: unknown): p is Preset {\n if (typeof p !== \"object\" || p === null) return false;\n const { id, data, prefix } = p as Partial<Record<keyof Preset, unknown>>;\n return Boolean(id) && Boolean(data) && Boolean(prefix);\n}\n\n/** Devices saved from the canvas (GNS3's appliances), placed from the toolbar like the built-in ones. */\nexport function loadDevices(): Preset[] {\n const list = read(DEVICES_KEY);\n // Saved before Isoloom's new format: OS names as it writes them now.\n return Array.isArray(list) ? list.filter(isPreset).map((p) => ({ ...p, data: currentMachine(p.data) })) : [];\n}\n\nexport function saveDevices(list: Preset[]): void {\n write(DEVICES_KEY, list);\n}\n\n/** The canvas's look picked in this browser, if any. */\nexport function loadDesign(): Design | null {\n try {\n const saved = localStorage.getItem(DESIGN_KEY);\n return isDesign(saved) ? saved : null;\n } catch {\n return null;\n }\n}\n\nexport function saveDesign(design: Design): void {\n try {\n localStorage.setItem(DESIGN_KEY, design);\n } catch {\n // The choice lasts as long as the page.\n }\n}\n\n/** The kind each toolbar block places, by block id, as picked last. */\nexport function loadBlockChoices(): Record<string, string> | null {\n try {\n const saved: unknown = JSON.parse(localStorage.getItem(BLOCKS_KEY) ?? \"{}\");\n return saved && typeof saved === \"object\" ? (saved as Record<string, string>) : null;\n } catch {\n // The first kind of each block.\n return null;\n }\n}\n\nexport function saveBlockChoices(choices: Record<string, string>): void {\n write(BLOCKS_KEY, choices);\n}\n\n/** The labs that start when the desktop app opens on them (GNS3's auto-start). */\nfunction autoStartLabs(): string[] {\n const list = read(AUTO_START_KEY);\n return Array.isArray(list) ? list.filter((x): x is string => typeof x === \"string\") : [];\n}\n\n/** Whether `lab` starts when the app opens on it. */\nexport function autoStarts(lab: string): boolean {\n return autoStartLabs().includes(lab);\n}\n\nexport function setAutoStarts(lab: string, on: boolean): void {\n const others = autoStartLabs().filter((l) => l !== lab);\n write(AUTO_START_KEY, on ? [...others, lab] : others);\n}\n\n/** The saved project the editor is attached to. */\nexport interface ProjectRef {\n id: string;\n name: string;\n}\n\nexport function loadProject(): ProjectRef | null {\n return read(PROJECT_KEY) as ProjectRef | null;\n}\n\nexport function saveProject(p: ProjectRef | null): void {\n write(PROJECT_KEY, p);\n}\n", "import { useEffect, useState } from \"react\";\nimport { desktop } from \"@/lib/tool/desktop\";\nimport type { Design } from \"@/lib/tool/model\";\nimport { loadDesign, saveDesign } from \"@/lib/tool/storage\";\n\n/**\n * The canvas's look: a preference of this browser (a share link brings its own). The desktop\n * app opens in business, the site in the sketch.\n */\nexport function useDesign() {\n const [design, setDesign] = useState<Design>(() => (desktop() ? \"business\" : \"sketch\"));\n useEffect(() => {\n const saved = loadDesign();\n if (saved)\n queueMicrotask(() => {\n setDesign(saved);\n });\n }, []);\n const chooseDesign = (d: Design) => {\n setDesign(d);\n saveDesign(d);\n };\n return { design, setDesign, chooseDesign };\n}\n", "import { useEffect, useMemo, useState } from \"react\";\nimport { allPresets, deviceBlocks } from \"@/lib/tool/blocks\";\nimport type { MachineData } from \"@/lib/tool/model\";\nimport { deviceFrom, type Preset } from \"@/lib/tool/presets\";\nimport { loadBlockChoices, loadDevices, saveBlockChoices, saveDevices } from \"@/lib/tool/storage\";\nimport type { EditorText } from \"@/lib/tool/text\";\nimport type { Tools } from \"./use-tools\";\n\n/**\n * Devices saved from the canvas, in this browser (loaded after mount: no localStorage on the\n * server), and the toolbar's blocks, each placing the kind picked last.\n */\nexport function useDevices(tools: Tools, setToast: (message: string) => void, t: EditorText) {\n const [myDevices, setMyDevices] = useState<Preset[]>([]);\n useEffect(() => {\n queueMicrotask(() => {\n setMyDevices(loadDevices());\n });\n }, []);\n const presets = useMemo(() => allPresets(myDevices), [myDevices]);\n const blocks = useMemo(() => deviceBlocks(presets, myDevices, t), [presets, myDevices, t]);\n const [blockChoice, setBlockChoice] = useState<Record<string, string>>({});\n useEffect(() => {\n const saved = loadBlockChoices();\n if (saved)\n queueMicrotask(() => {\n setBlockChoice(saved);\n });\n }, []);\n const keep = (list: Preset[]) => {\n setMyDevices(list);\n saveDevices(list);\n };\n return {\n presets,\n blocks,\n blockChoice,\n pickFromBlock: (block: string, tool: string) => {\n tools.pick(tool);\n setBlockChoice((c) => {\n const next = { ...c, [block]: tool };\n saveBlockChoices(next);\n return next;\n });\n },\n /** Saving a machine again under the same name replaces that device. */\n saveDevice: (m: MachineData) => {\n const device = deviceFrom(m);\n const name = device.label ?? \"\";\n keep([...myDevices.filter((d) => d.label !== name), device]);\n setToast(t.toasts.savedDevice(name));\n },\n forgetDevice: (id: string) => {\n keep(myDevices.filter((d) => d.id !== id));\n if (tools.activeTool === id) tools.setActiveTool(null);\n },\n };\n}\n", "import { useState } from \"react\";\nimport type { Engine, Plan } from \"@/lib/tool/engine\";\n\n/** Saves `blob` as `filename`, through a link the browser follows. */\nfunction download(blob: Blob, filename: string) {\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = filename;\n a.click();\n URL.revokeObjectURL(url);\n}\n\nconst zip = (bytes: Uint8Array) => new Blob([bytes as BlobPart], { type: \"application/zip\" });\n\n/** The Export window's downloads: the whole lab, one target, or isoloom.yml alone. */\nexport function useDownloads(engine: Engine | null, plan: Plan | null, topology: string, labName: string) {\n const [downloadError, setDownloadError] = useState<string | null>(null);\n /** Builds a zip with the engine and saves it, or says why it couldn't. */\n function save(build: (engine: Engine) => Uint8Array, filename: string) {\n if (!engine) return;\n setDownloadError(null);\n try {\n download(zip(build(engine)), filename);\n } catch (e) {\n setDownloadError(String(e));\n }\n }\n return {\n downloadError,\n downloadAll: () => {\n save((e) => e.bundle(topology), `${labName || \"lab\"}.zip`);\n },\n /** One target's zip: isoloom.yml and that target's folder. */\n downloadTarget: (dir: string) => {\n save((e) => e.bundle_target(topology, dir), `${labName || \"lab\"}-${dir.replace(/\\//g, \"-\")}.zip`);\n },\n downloadSpec: () => {\n if (plan?.isoloom_yml) download(new Blob([plan.isoloom_yml], { type: \"text/yaml\" }), \"isoloom.yml\");\n },\n };\n}\n", "import { useEffect, useMemo, useState } from \"react\";\nimport { loadEngine, planOf, type Engine, type Plan } from \"@/lib/tool/engine\";\nimport type { EditorText } from \"@/lib/tool/text\";\n\n/** The engine, once loaded (or why it didn't load). */\nexport function useEngine(): { engine: Engine | null; error: string | null } {\n const [engine, setEngine] = useState<Engine | null>(null);\n const [error, setError] = useState<string | null>(null);\n useEffect(() => {\n let alive = true;\n loadEngine().then(\n (m) => {\n if (alive) setEngine(m);\n },\n (e: unknown) => {\n if (alive) setError(String(e));\n },\n );\n return () => {\n alive = false;\n };\n }, []);\n return { engine, error };\n}\n\n/** The engine's plan for the lab (null until the engine has loaded). An engine crash must not take the canvas down with it. */\nexport function usePlan(engine: Engine | null, topology: string, t: EditorText): Plan | null {\n return useMemo(() => (engine ? planOf(engine, topology, t.engineFailed) : null), [engine, topology, t]);\n}\n", "import type { Addresses } from \"./router-ports\";\n\n/**\n * The engine's JavaScript surface, from `public/wasm/isothrum_wasm.js` (built from\n * `crates/isothrum-wasm`). Everything runs in the browser: nothing is sent to a server.\n */\nexport interface Engine {\n default: () => Promise<unknown>;\n plan_json: (topology: string) => string;\n bundle: (topology: string) => Uint8Array;\n /** The lab's own files (provisioning starters, appliance configurations), as JSON. */\n own_files_json: (topology: string) => string;\n bundle_target: (topology: string, targetDir: string) => Uint8Array;\n}\n\nexport interface GeneratedFile {\n path: string;\n contents: string;\n}\n\n/** What the engine makes of a lab: isoloom.yml and every target's files, or what is wrong. */\nexport interface Plan {\n ok: boolean;\n error: string | null;\n isoloom_yml: string | null;\n problems: string[];\n files: GeneratedFile[];\n skipped: string[];\n addresses: Addresses;\n}\n\n/** Served from `public/wasm/`; loaded at runtime, not bundled. */\nconst ENGINE_URL: string = \"/wasm/isothrum_wasm.js\";\n\n/** Loads and starts the engine. */\nexport async function loadEngine(): Promise<Engine> {\n const m = (await import(/* webpackIgnore: true */ /* turbopackIgnore: true */ ENGINE_URL)) as Engine;\n await m.default();\n return m;\n}\n\n/** The plan as the engine writes it: isoloom.yml may be left out when there is none. */\ntype RawPlan = Omit<Plan, \"isoloom_yml\"> & { isoloom_yml?: string | null };\n\n/** The engine's plan for a topology; an engine crash becomes a plan with `error` (from `failed`). */\nexport function planOf(engine: Engine, topology: string, failed: (error: string) => string): Plan {\n try {\n const raw = JSON.parse(engine.plan_json(topology)) as RawPlan;\n return { ...raw, isoloom_yml: raw.isoloom_yml ?? null };\n } catch (e) {\n return { ok: false, error: failed(String(e)), isoloom_yml: null, problems: [], files: [], skipped: [], addresses: {} };\n }\n}\n\n/** The lab's own files (provisioning starters, appliance configurations). */\nexport function ownFiles(engine: Engine, topology: string): GeneratedFile[] {\n return JSON.parse(engine.own_files_json(topology)) as GeneratedFile[];\n}\n", "import { useEffect, useState } from \"react\";\nimport { useEdgesState, useNodesState } from \"@xyflow/react\";\nimport type { CableEdge, Draft, LabNode } from \"@/lib/tool/model\";\nimport { loadDraft, saveDraft } from \"@/lib/tool/storage\";\n\n/** The lab on the canvas: its name, nodes and cables, kept in this browser as it changes. */\nexport function useLab() {\n // The last lab drawn in this browser, or a blank canvas (the example is one click away). The\n // editor renders on the client only, so reading storage here can't mismatch the server's HTML.\n const [initial] = useState<Draft>(() => loadDraft() ?? { name: \"my-lab\", nodes: [], edges: [] });\n const [labName, setLabName] = useState(initial.name);\n const [nodes, setNodes, onNodesChange] = useNodesState<LabNode>(initial.nodes);\n const [edges, setEdges, onEdgesChange] = useEdgesState<CableEdge>(initial.edges);\n return { initial, labName, setLabName, nodes, setNodes, onNodesChange, edges, setEdges, onEdgesChange };\n}\n\nexport type Lab = ReturnType<typeof useLab>;\n\n/** Saves the lab as it changes. */\nexport function useDraftSaving(lab: Lab): void {\n const { labName, nodes, edges } = lab;\n useEffect(() => {\n saveDraft({ name: labName, nodes, edges });\n }, [labName, nodes, edges]);\n}\n\n/** Replaces the whole lab (an example, a shared link, a project, a GNS3 import). */\nexport function replaceLab(lab: Lab, next: Draft): void {\n lab.setLabName(next.name);\n lab.setNodes(next.nodes);\n lab.setEdges(next.edges);\n}\n", "import { useCallback } from \"react\";\nimport { migrateEdges } from \"@/lib/tool/cables\";\nimport { exampleLab } from \"@/lib/tool/examples\";\nimport { fromGns3 } from \"@/lib/tool/gns3-import\";\nimport { isLan, isMachine, type CableData, type Draft, type MachineData } from \"@/lib/tool/model\";\nimport type { EditorText } from \"@/lib/tool/text\";\nimport { replaceLab, type Lab } from \"./use-lab\";\n\ntype FitView = (options: { padding: number; maxZoom: number }) => unknown;\n\n/** After replacing the whole lab: fits once React Flow has measured the new nodes. */\nexport function useFitWhenDrawn(fitView: FitView) {\n return useCallback(\n (options = { padding: 0.4, maxZoom: 1 }) => {\n setTimeout(() => void fitView(options), 120);\n },\n [fitView],\n );\n}\n\n/** Editing the lab from its windows and menus: a machine's or a cable's fields, examples, a GNS3 project. */\nexport function useLabActions(lab: Lab, fitWhenDrawn: (options?: { padding: number; maxZoom: number }) => void, setToast: (message: string) => void, t: EditorText) {\n const { nodes, setNodes, setEdges } = lab;\n return {\n updateMachine: (id: string, patch: Partial<MachineData>) => {\n const next = nodes.map((n) => (n.id === id && isMachine(n) ? { ...n, data: { ...n.data, ...patch } } : n));\n setNodes(next);\n // Turning a router into a real one (or back) changes its connection points: its cables move\n // onto free ports, or back onto its single port.\n if (\"kind\" in patch) setEdges((es) => migrateEdges(es, next));\n },\n updateCable: (id: string, patch: Partial<CableData>) => {\n setEdges((es) => es.map((e) => (e.id === id && e.data ? { ...e, data: { ...e.data, ...patch } } : e)));\n },\n loadExample: (make: () => Draft = exampleLab) => {\n replaceLab(lab, make());\n fitWhenDrawn();\n },\n clearLab: () => {\n setNodes([]);\n setEdges([]);\n },\n /** A GNS3 project opens as a lab (Undo brings back the one that was there). */\n importGns3: async (file: File) => {\n try {\n const { lab: opened, warnings } = fromGns3(await file.text(), t.gns3);\n replaceLab(lab, opened);\n fitWhenDrawn({ padding: 0.3, maxZoom: 1 });\n const machines = opened.nodes.filter(isMachine).length;\n const lans = opened.nodes.filter(isLan).length;\n setToast(`${t.toasts.gns3Opened(opened.name, machines, lans)}${warnings.length ? ` ${warnings.join(\" \")}` : \"\"} ${t.toasts.undoBringsBack}`);\n } catch (err) {\n setToast(err instanceof Error ? err.message : t.toasts.gns3Unreadable);\n }\n },\n };\n}\n", "import { twoVlans } from \"./create\";\nimport { DEFAULT_OS } from \"./os\";\nimport { LAN_BEHAVIOR, MACHINE_H, MACHINE_W, type CableEdge, type Draft, type LabNode, type LanData, type LanNode, type MachineData, type MachineNode } from \"./model\";\n\n/** The labs the menu loads: one to start from, and one with VLANs. */\n\nconst base = { image: \"\", os: \"\", provision: \"\", ports: \"\", access: false };\n\nconst machine = (id: string, position: { x: number; y: number }, data: MachineData): MachineNode => ({ id, type: \"machine\", position, data });\n\nconst lan = (id: string, area: { x: number; y: number; w: number; h: number }, data: LanData): LanNode => ({\n ...LAN_BEHAVIOR,\n id,\n type: \"lan\",\n position: { x: area.x, y: area.y },\n width: area.w,\n height: area.h,\n data,\n});\n\n/** A cable from `source` to `target`, its handles and port labels as [source's, target's]. */\nconst cable = (id: string, [source, target]: [string, string], [sh, th]: [string, string], [aPort, bPort]: [string, string]): CableEdge => ({\n id,\n type: \"cable\",\n source,\n sourceHandle: sh,\n target,\n targetHandle: th,\n data: { aPort, bPort },\n});\n\n/**\n * A starting lab: an office LAN with a workstation, a servers LAN with a web server and a\n * database, and a router cabled to both LANs.\n */\nexport function exampleLab(): Draft {\n const nodes: LabNode[] = [\n // LANs first, so they are drawn under the machines.\n lan(\"l-office\", { x: -40, y: 40, w: 280, h: 260 }, { name: \"office\", cidr: \"10.10.1.0/24\", internet: true }),\n lan(\"l-servers\", { x: 560, y: -80, w: 300, h: 500 }, { name: \"servers\", cidr: \"10.10.2.0/24\", internet: true }),\n machine(\"m-user\", { x: 40, y: 110 }, { ...base, name: \"user\", kind: \"vm\", icon: \"laptop\", os: DEFAULT_OS, access: true }),\n // On the office LAN's right edge: a two-network appliance, office on one side, its port out.\n machine(\"m-router\", { x: 240 - MACHINE_W / 2, y: 170 - MACHINE_H / 2 }, { ...base, name: \"router\", kind: \"router\", icon: \"router\" }),\n machine(\"m-web\", { x: 650, y: 0 }, { ...base, name: \"web\", kind: \"container\", icon: \"server\", image: \"nginx:1.27-alpine\", ports: \"80\" }),\n machine(\"m-db\", { x: 650, y: 240 }, { ...base, name: \"db\", kind: \"vm\", icon: \"monitor\", os: DEFAULT_OS, provision: \"provision/db.sh\", ports: \"5432\" }),\n ];\n const edges = [cable(\"c-1\", [\"m-router\", \"l-servers\"], [\"port\", \"left\"], [\"eth1\", \"\"])];\n return { name: \"office-lab\", nodes, edges };\n}\n\n/**\n * The VLAN example: a switch with vlan10 and vlan20, two PCs on vlan10, a server on vlan20, and a\n * router on the trunk (router-on-a-stick: one address on each VLAN).\n */\nexport function vlanExample(): Draft {\n const nodes: LabNode[] = [\n { id: \"s-sw1\", type: \"switch\", position: { x: 40, y: 0 }, data: { ...twoVlans(), name: \"sw1\" } },\n machine(\"m-router\", { x: 180, y: -230 }, { ...base, name: \"router\", kind: \"router\", icon: \"router\" }),\n machine(\"m-pc1\", { x: -140, y: 220 }, { ...base, name: \"pc1\", kind: \"vm\", icon: \"laptop\", os: DEFAULT_OS, access: true }),\n machine(\"m-pc2\", { x: 40, y: 220 }, { ...base, name: \"pc2\", kind: \"container\", icon: \"container\", image: \"alpine:3.20\" }),\n machine(\"m-srv\", { x: 300, y: 220 }, { ...base, name: \"srv\", kind: \"container\", icon: \"server\", image: \"nginx:1.27-alpine\", ports: \"80\" }),\n ];\n const onSwitch = (id: string, m: string, mh: string, port: string, labels: [string, string]) => cable(id, [m, \"s-sw1\"], [mh, port], labels);\n const edges = [\n onSwitch(\"c-1\", \"m-router\", \"port\", \"trunk\", [\"eth0\", \"T\"]),\n onSwitch(\"c-2\", \"m-pc1\", \"top\", \"p1\", [\"eth0\", \"1\"]),\n onSwitch(\"c-3\", \"m-pc2\", \"top\", \"p2\", [\"eth0\", \"2\"]),\n onSwitch(\"c-4\", \"m-srv\", \"top\", \"p5\", [\"eth0\", \"5\"]),\n ];\n return { name: \"vlan-lab\", nodes, edges };\n}\n", "import { nextPort } from \"./cables\";\nimport { lanRect, within } from \"./geometry\";\nimport { centerOf, isLan, uid, type CableEdge, type LabNode, type LanNode, type MachineNode, type Side } from \"./model\";\n\n/** A GNS3 project's links as cables: machine to machine, or machine to the LAN its switch became. */\n\nexport interface Gns3Wiring {\n links: [string, string][];\n /** The machines and the LANs, by GNS3 node id. */\n machines: Map<string, MachineNode>;\n lanOf: Map<string, LanNode>;\n /** Every node of the lab so far (the LANs among them). */\n nodes: LabNode[];\n /** A GNS3 LAN's size: which side of it faces a machine goes by its proportions. */\n lanSize: { w: number; h: number };\n}\n\nconst machineSide = (m: MachineNode, other: LabNode) => {\n if (m.data.icon === \"router\" || m.data.icon === \"shield\") return \"port\";\n return centerOf(other).y < centerOf(m).y ? \"top\" : \"bottom\";\n};\n\nfunction lanSide(w: Gns3Wiring, lan: LanNode, m: MachineNode): Side {\n const d = { x: centerOf(m).x - centerOf(lan).x, y: centerOf(m).y - centerOf(lan).y };\n if (Math.abs(d.x) / w.lanSize.w > Math.abs(d.y) / w.lanSize.h) return d.x < 0 ? \"left\" : \"right\";\n return d.y < 0 ? \"top\" : \"bottom\";\n}\n\nfunction machineCable(a: MachineNode, b: MachineNode, edges: CableEdge[]): CableEdge {\n return {\n id: uid(\"c\"),\n type: \"cable\",\n source: a.id,\n sourceHandle: machineSide(a, b),\n target: b.id,\n targetHandle: machineSide(b, a),\n data: { aPort: nextPort(a.id, edges), bPort: nextPort(b.id, edges) },\n };\n}\n\nfunction lanCable(w: Gns3Wiring, m: MachineNode, lan: LanNode, edges: CableEdge[]): CableEdge {\n return {\n id: uid(\"c\"),\n type: \"cable\",\n source: m.id,\n sourceHandle: machineSide(m, lan),\n target: lan.id,\n targetHandle: lanSide(w, lan, m),\n data: { aPort: nextPort(m.id, edges), bPort: \"\" },\n };\n}\n\n/**\n * A LAN drawn over a machine it isn't cabled to would put that machine on it: its area is hidden\n * (its label and cables stay).\n */\nfunction hideCovering(w: Gns3Wiring, linked: Set<string>): void {\n for (const lan of w.nodes.filter(isLan)) {\n const covers = [...w.machines.values()].some((m) => within(lanRect(lan), centerOf(m)) && !linked.has(`${m.id}/${lan.id}`));\n if (covers) lan.data = { ...lan.data, hidden: true };\n }\n}\n\n/** The cables of the project's links (each machine\u2013LAN pair once); hides the LANs that would mislead. */\nexport function gns3Cables(w: Gns3Wiring): CableEdge[] {\n const edges: CableEdge[] = [];\n const linked = new Set<string>();\n for (const [a, b] of w.links) {\n const ma = w.machines.get(a);\n const mb = w.machines.get(b);\n const lan = w.lanOf.get(b) ?? w.lanOf.get(a);\n const m = ma ?? mb;\n if (ma && mb) edges.push(machineCable(ma, mb, edges));\n else if (m && lan && !linked.has(`${m.id}/${lan.id}`)) {\n linked.add(`${m.id}/${lan.id}`);\n edges.push(lanCable(w, m, lan, edges));\n }\n }\n hideCovering(w, linked);\n return edges;\n}\n", "import type { NoteShape } from \"./model\";\nimport { DEFAULT_OS } from \"./os\";\n\n/** Pieces of a GNS3 import that read one thing: an OS from an image name, a note from a drawing. */\n\n/** The editor's words for what a GNS3 import can't carry over (see the editor's text). */\nexport interface Gns3Text {\n notGns3: string;\n noTopology: string;\n cisco: (node: string, kind: string) => string;\n firewall: (node: string) => string;\n noEquivalent: (node: string, type: string) => string;\n noNodes: string;\n}\n\nexport interface G3Drawing {\n x?: number;\n y?: number;\n svg?: string;\n}\n\nfunction windowsOs(t: string): string {\n if (t.includes(\"11\")) return \"windows@11\";\n if (t.includes(\"10\") && !t.includes(\"server\")) return \"windows@10\";\n if (t.includes(\"2016\")) return \"windows-server@2016\";\n if (t.includes(\"2019\")) return \"windows-server@2019\";\n if (t.includes(\"2025\")) return \"windows-server@2025\";\n return \"windows-server@2022\";\n}\n\n/** Linux distributions by a word in the image's name, each with its version guess. */\nconst DISTROS: [word: string, os: (t: string) => string][] = [\n [\"kali\", () => \"kali@rolling\"],\n [\"ubuntu\", (t) => (t.includes(\"20.04\") ? \"ubuntu@20.04\" : t.includes(\"24\") ? \"ubuntu@24.04\" : \"ubuntu@22.04\")],\n [\"rocky\", () => \"rocky@9\"],\n [\"alma\", () => \"alma@9\"],\n [\"centos\", () => \"centos@7\"],\n [\"fedora\", () => \"fedora@42\"],\n [\"alpine\", () => \"alpine@3.19\"],\n [\"debian\", (t) => (t.includes(\"11\") ? \"debian@11\" : t.includes(\"13\") ? \"debian@13\" : DEFAULT_OS)],\n];\n\n/** The Isoloom OS a VM's image or name suggests (Debian 12 when nothing does). */\nexport function guessOs(text: string): string {\n const t = text.toLowerCase();\n if (t.includes(\"win\")) return windowsOs(t);\n const distro = DISTROS.find(([word]) => t.includes(word));\n return distro ? distro[1](t) : DEFAULT_OS;\n}\n\n/** The text in an SVG drawing's <text> elements, one line each. */\nfunction svgText(svg: string): string {\n return [...svg.matchAll(/<text[^>]*>([\\s\\S]*?)<\\/text>/g)]\n .map((m) => m[1].replace(/<[^>]+>/g, \"\").replace(/&lt;/g, \"<\").replace(/&gt;/g, \">\").replace(/&amp;/g, \"&\").trim())\n .filter(Boolean)\n .join(\"\\n\");\n}\n\n/** The text of an SVG drawing, and its shape and size (scaled by `scale`). */\nexport function drawingNote(d: G3Drawing, scale: number): { text: string; shape: NoteShape; w: number; h: number } | null {\n const svg = d.svg ?? \"\";\n const text = svgText(svg);\n const shape: NoteShape = svg.includes(\"<ellipse\") ? \"ellipse\" : svg.includes(\"<rect\") ? \"rect\" : \"text\";\n if (!text && shape === \"text\") return null;\n const w = Number(/width=\"([\\d.]+)\"/.exec(svg)?.[1] ?? 0);\n const h = Number(/height=\"([\\d.]+)\"/.exec(svg)?.[1] ?? 0);\n return { text, shape, w: Math.max(120, Math.min(600, w * scale)) || 200, h: Math.max(50, Math.min(400, h * scale)) || 90 };\n}\n", "/**\n * Opening a GNS3 project (.gns3, the JSON GNS3 saves) as a lab. GNS3 draws switches as boxes\n * that machines plug into; here they become LANs, the machines cabled to their edge. Docker\n * nodes keep their image, QEMU/VirtualBox/VMware nodes become VMs (the OS guessed from the\n * image), VPCS becomes a small container, Cisco routers (Dynamips, IOU) automatic routers, a NAT\n * or cloud gives its LAN the internet, and text drawings become notes. What can't come across\n * (an IOS configuration, a node type with no equivalent) is reported, not silently dropped.\n */\n\nimport { migrateEdges } from \"./cables\";\nimport { gns3Cables } from \"./gns3-cables\";\nimport { drawingNote, guessOs, type G3Drawing, type Gns3Text } from \"./gns3-parts\";\nimport { LAN_BEHAVIOR, MACHINE_H, MACHINE_W, cleanName, uid, type Draft, type LabNode, type LanNode, type MachineData, type MachineNode, type NoteNode } from \"./model\";\n\ninterface G3Node {\n node_id: string;\n name?: string;\n node_type?: string;\n x?: number;\n y?: number;\n properties?: Record<string, unknown>;\n}\ninterface G3Link {\n nodes?: { node_id: string }[];\n}\ninterface G3Project {\n name?: string;\n type?: string;\n topology?: { nodes?: G3Node[]; links?: G3Link[]; drawings?: G3Drawing[] };\n}\n\n/** GNS3 places small icons; Isothrum's machines are about twice as big, so positions spread out. */\nconst SCALE = 2;\nconst LAN_W = 260;\nconst LAN_H = 160;\n\nconst SWITCHES = new Set([\"ethernet_switch\", \"ethernet_hub\", \"atm_switch\", \"frame_relay_switch\"]);\nconst INTERNET = new Set([\"nat\", \"cloud\"]);\nconst CISCO = new Set([\"dynamips\", \"iou\"]);\nconst VMS = new Set([\"qemu\", \"virtualbox\", \"vmware\"]);\n\n/** Appliances recognised by their image or name: network devices rather than hosts. */\nconst ROUTER_HINT = /vyos|csr|vios|xrv|routeros|mikrotik|frr|cisco|juniper|vsrx|vmx|veos|arista|nokia|sros|openwrt/i;\nconst FIREWALL_HINT = /fortigate|pfsense|opnsense|asav|paloalto|pan-os|checkpoint|sophos/i;\nconst SWITCH_HINT = /openvswitch|ovs|cumulus|nxos|iosvl2|vios_l2/i;\n\nconst str = (v: unknown) => (typeof v === \"string\" ? v : \"\");\n\n/** What a GNS3 node becomes: part of a LAN (a switch, or the internet), or a machine. */\nfunction kindOf(n: G3Node): \"switch\" | \"internet\" | \"machine\" {\n const t = n.node_type ?? \"\";\n const look = `${n.name ?? \"\"} ${str(n.properties?.image)} ${str(n.properties?.hda_disk_image)}`;\n if (SWITCHES.has(t) || ((t === \"docker\" || VMS.has(t)) && SWITCH_HINT.test(look))) return \"switch\";\n if (INTERNET.has(t)) return \"internet\";\n return \"machine\";\n}\n\n/** An import in progress: the project's nodes, the lab's nodes so far, the names taken. */\ninterface Import {\n g3nodes: G3Node[];\n links: [string, string][];\n nodes: LabNode[];\n names: Set<string>;\n warnings: string[];\n text: Gns3Text;\n}\n\n/** The project's nodes and its two-ended links, or why the file isn't a GNS3 project. */\nfunction parse(source: string, text: Gns3Text): { project: G3Project; g3nodes: G3Node[]; links: [string, string][] } {\n let project: G3Project;\n try {\n project = JSON.parse(source) as G3Project;\n } catch {\n throw new Error(text.notGns3);\n }\n const g3nodes = project.topology?.nodes;\n if (!Array.isArray(g3nodes)) throw new Error(text.noTopology);\n const links = (project.topology?.links ?? [])\n .map((l) => (l.nodes ?? []).map((e) => e.node_id))\n .flatMap((ends): [string, string][] => (ends.length === 2 ? [[ends[0], ends[1]]] : []));\n return { project, g3nodes, links };\n}\n\n/** A free name from GNS3's (spaces and underscores as dashes), `-2`, `-3`\u2026 when it is taken. */\nfunction nameFor(imp: Import, raw: string, fallback: string): string {\n const base = cleanName(raw.replace(/[\\s_]+/g, \"-\")).replace(/^-+|-+$/g, \"\") || fallback;\n let name = base;\n for (let i = 2; imp.names.has(name); i++) name = `${base}-${String(i)}`;\n imp.names.add(name);\n return name;\n}\n\nconst center = (n: G3Node) => ({ x: (n.x ?? 0) * SCALE + 30, y: (n.y ?? 0) * SCALE + 30 });\n\n/** Switches cabled together are one LAN; a NAT or cloud cabled to a switch gives it the internet. */\nfunction switchGroups(imp: Import): (id: string) => string | null {\n const parent = new Map<string, string>();\n const find = (id: string): string => {\n const up = parent.get(id);\n return up === undefined || up === id ? id : find(up);\n };\n for (const n of imp.g3nodes) if (kindOf(n) !== \"machine\") parent.set(n.node_id, n.node_id);\n for (const [a, b] of imp.links) if (parent.has(a) && parent.has(b)) parent.set(find(a), find(b));\n return (id) => (parent.has(id) ? find(id) : null);\n}\n\n/** One LAN per group of switches (and NAT/cloud), where its first member was. */\nfunction importLans(imp: Import): Map<string, LanNode> {\n const groupOf = switchGroups(imp);\n const lanOf = new Map<string, LanNode>();\n let third = 1;\n for (const n of imp.g3nodes) {\n const root = groupOf(n.node_id);\n if (root === null) continue;\n let lan = lanOf.get(root);\n if (!lan) {\n const members = imp.g3nodes.filter((m) => groupOf(m.node_id) === root);\n const first = members.find((m) => kindOf(m) === \"switch\") ?? members[0];\n const c = center(first);\n const data = { name: nameFor(imp, first.name ?? \"\", \"lan\"), cidr: `10.10.${String(third++)}.0/24`, internet: members.some((m) => kindOf(m) === \"internet\") };\n lan = { ...LAN_BEHAVIOR, id: uid(\"l\"), type: \"lan\", position: { x: c.x - LAN_W / 2, y: c.y - LAN_H / 2 }, width: LAN_W, height: LAN_H, data };\n imp.nodes.push(lan);\n }\n lanOf.set(n.node_id, lan);\n lanOf.set(root, lan);\n }\n return lanOf;\n}\n\n/** What a GNS3 machine becomes, or null (with a warning) when nothing here matches it. */\nfunction machineData(imp: Import, n: G3Node): Omit<MachineData, \"name\"> | null {\n const t = n.node_type ?? \"\";\n const p = n.properties ?? {};\n const look = `${n.name ?? \"\"} ${str(p.image)} ${str(p.hda_disk_image)} ${str(p.vmname)}`;\n const base = { image: \"\", os: \"\", provision: \"\", ports: \"\", access: false };\n if (CISCO.has(t) || ROUTER_HINT.test(look)) {\n if (CISCO.has(t)) imp.warnings.push(imp.text.cisco(n.name ?? n.node_id, t === \"iou\" ? \"IOU\" : \"Dynamips\"));\n return { ...base, kind: \"router\", icon: \"router\" };\n }\n if (FIREWALL_HINT.test(look)) {\n imp.warnings.push(imp.text.firewall(n.name ?? n.node_id));\n return { ...base, kind: \"router\", icon: \"shield\" };\n }\n if (t === \"docker\") return { ...base, kind: \"container\", icon: \"container\", image: str(p.image) || \"alpine:3.20\" };\n if (t === \"vpcs\" || t === \"traceng\") return { ...base, kind: \"container\", icon: \"laptop\", image: \"alpine:3.20\" };\n if (VMS.has(t)) return { ...base, kind: \"vm\", icon: \"monitor\", os: guessOs(look) };\n imp.warnings.push(imp.text.noEquivalent(n.name ?? n.node_id, t));\n return null;\n}\n\n/** The machines, where GNS3 had them, by GNS3 node id. */\nfunction importMachines(imp: Import): Map<string, MachineNode> {\n const machines = new Map<string, MachineNode>();\n for (const n of imp.g3nodes) {\n if (kindOf(n) !== \"machine\") continue;\n let data = machineData(imp, n);\n if (!data) continue;\n const name = nameFor(imp, n.name ?? \"\", data.kind === \"router\" ? \"router\" : \"machine\");\n if (data.kind === \"vm\") data = { ...data, provision: `provision/${name}.${data.os.startsWith(\"windows\") ? \"ps1\" : \"sh\"}` };\n const c = center(n);\n const m: MachineNode = { id: uid(\"m\"), type: \"machine\", position: { x: c.x - MACHINE_W / 2, y: c.y - MACHINE_H / 2 }, data: { ...data, name } };\n machines.set(n.node_id, m);\n imp.nodes.push(m);\n }\n return machines;\n}\n\n/** The project's text drawings, as notes. */\nfunction importNotes(imp: Import, drawings: G3Drawing[]): void {\n for (const d of drawings) {\n const note = drawingNote(d, SCALE);\n if (!note) continue;\n const n: NoteNode = {\n id: uid(\"n\"),\n type: \"note\",\n position: { x: (d.x ?? 0) * SCALE, y: (d.y ?? 0) * SCALE },\n width: note.w,\n height: note.h,\n data: { text: note.text, shape: note.shape, color: \"yellow\" },\n };\n imp.nodes.push(n);\n }\n}\n\n/** `text`: the editor's words for what goes wrong (warnings and errors are shown as they are). */\nexport function fromGns3(source: string, text: Gns3Text): { lab: Draft; warnings: string[] } {\n const { project, g3nodes, links } = parse(source, text);\n const imp: Import = { g3nodes, links, nodes: [], names: new Set(), warnings: [], text };\n const lanOf = importLans(imp);\n const machines = importMachines(imp);\n const edges = gns3Cables({ links, machines, lanOf, nodes: imp.nodes, lanSize: { w: LAN_W, h: LAN_H } });\n importNotes(imp, project.topology?.drawings ?? []);\n // LANs first, so they stay under the machines.\n const ordered = [...imp.nodes.filter((n) => n.type === \"lan\"), ...imp.nodes.filter((n) => n.type !== \"lan\")];\n const lab: Draft = { name: cleanName((project.name ?? \"\").replace(/[\\s_]+/g, \"-\")) || \"gns3-lab\", nodes: ordered, edges: migrateEdges(edges, ordered) };\n if (!g3nodes.length) imp.warnings.push(text.noNodes);\n return { lab, warnings: imp.warnings };\n}\n", "import { useEffect, useEffectEvent } from \"react\";\nimport { ownFiles, type Engine, type Plan } from \"@/lib/tool/engine\";\nimport type { EditorText } from \"@/lib/tool/text\";\nimport type { DesktopState, LiveLab, RunState, useAutoStart, useRunPanel } from \"./use-desktop\";\nimport type { Captures } from \"./use-captures\";\n\ninterface Deps {\n state: DesktopState;\n panel: ReturnType<typeof useRunPanel>;\n autoStart: ReturnType<typeof useAutoStart>;\n live: LiveLab;\n captures: Captures;\n lab: { labName: string; topology: string; plan: Plan | null; engine: Engine | null; hasVms: boolean };\n t: EditorText;\n}\n\n/** Running the lab on this machine (desktop): `lab_up` from the engine's spec, and `lab_down`. */\nexport function useLabRun({ state, panel, autoStart, live, captures, lab, t }: Deps) {\n const { invoke, run, setRun } = state;\n async function runLab() {\n if (!invoke || !lab.plan?.isoloom_yml) return;\n setRun(\"starting\");\n panel.setRunOpen(true);\n panel.setRunLog(lab.hasVms ? t.run.startingVmsLog : t.run.startingLog);\n try {\n const files = lab.engine ? ownFiles(lab.engine, lab.topology) : [];\n panel.setRunLog(await invoke<string>(\"lab_up\", { name: lab.labName, yaml: lab.plan.isoloom_yml, files }));\n setRun(\"running\");\n } catch (e) {\n panel.setRunLog(String(e));\n setRun(\"stopped\");\n }\n }\n async function stopLab() {\n if (!invoke) return;\n setRun(\"stopping\");\n try {\n panel.setRunLog(await invoke<string>(\"lab_down\", { name: lab.labName }));\n } catch (e) {\n panel.setRunLog(String(e));\n }\n captures.clearCaptures();\n live.setLinks([]);\n live.setLive(null);\n setRun(\"stopped\");\n }\n // The auto-start waits for the engine: the lab runs from the spec it makes.\n const spec = lab.plan?.isoloom_yml;\n const { autoStartPending, setAutoStartPending } = autoStart;\n const startPending = useEffectEvent((current: RunState) => {\n setAutoStartPending(false);\n if (current === \"stopped\") void runLab();\n });\n useEffect(() => {\n if (!autoStartPending || !spec) return;\n queueMicrotask(() => {\n startPending(run);\n });\n }, [autoStartPending, spec, run]);\n return { runLab, stopLab };\n}\n", "import { useRef } from \"react\";\nimport type { XYPosition } from \"@xyflow/react\";\nimport { lansAround, within } from \"@/lib/tool/geometry\";\nimport { SWITCH_H, SWITCH_W, isLan, isMachine, isNote, isSwitch, type LabNode, type LanNode } from \"@/lib/tool/model\";\nimport type { Lab } from \"./use-lab\";\n\n/** What moves with a LAN: machines inside (or on the edge, routers), switches on its edge or inside it, notes in it. */\nfunction lanMembers(lan: LanNode, nodes: LabNode[]): Map<string, XYPosition> {\n const r = { x: lan.position.x, y: lan.position.y, w: lan.width ?? 420, h: lan.height ?? 300 };\n const inside = (cx: number, cy: number) => within(r, { x: cx, y: cy }, 0.5);\n const carried = (n: LabNode) =>\n (isMachine(n) && lansAround(n, nodes).some((l) => l.id === lan.id)) ||\n (isSwitch(n) && inside(n.position.x + SWITCH_W / 2, n.position.y + SWITCH_H / 2)) ||\n (isNote(n) && inside(n.position.x + (n.width ?? 200) / 2, n.position.y + (n.height ?? 90) / 2));\n return new Map(nodes.filter(carried).map((m) => [m.id, { ...m.position }]));\n}\n\n/** Moving a LAN carries the machines inside it, as Excalidraw frames do. */\nexport function useLanCarry(lab: Lab) {\n const { nodes, setNodes } = lab;\n const carried = useRef<{ lan: string; start: XYPosition; members: Map<string, XYPosition> } | null>(null);\n return {\n onNodeDragStart: (_: unknown, node: LabNode) => {\n if (!isLan(node)) return;\n carried.current = { lan: node.id, start: { ...node.position }, members: lanMembers(node, nodes) };\n },\n onNodeDrag: (_: unknown, node: LabNode) => {\n const c = carried.current;\n if (!c || c.lan !== node.id) return;\n const dx = node.position.x - c.start.x;\n const dy = node.position.y - c.start.y;\n setNodes((ns) =>\n ns.map((n) => {\n const from = c.members.get(n.id);\n return from ? { ...n, position: { x: from.x + dx, y: from.y + dy } } : n;\n }),\n );\n },\n onNodeDragStop: () => {\n carried.current = null;\n },\n };\n}\n", "import { useState } from \"react\";\nimport type { Invoke, SuspendedLink } from \"@/lib/tool/desktop\";\nimport type { EditorText } from \"@/lib/tool/text\";\nimport type { LiveLab } from \"./use-desktop\";\n\nexport type MachineAction = \"start\" | \"stop\" | \"restart\";\nexport type LinkAction = \"suspend\" | \"resume\";\n\ninterface Deps {\n invoke: Invoke | null;\n labName: string;\n live: LiveLab;\n setToast: (message: string) => void;\n t: EditorText;\n}\n\n/**\n * One machine of the running lab (desktop): a console, its screen, starting or stopping it, its\n * snapshots, and cutting or reconnecting its links. A failure shows as a toast.\n */\nexport function useMachineActions({ invoke, labName, live, setToast, t }: Deps) {\n const [busy, setBusy] = useState(false);\n /** Runs a command for this lab while the machine controls wait, then reads the lab again. */\n async function act(run: (invoke: Invoke) => Promise<unknown>) {\n if (!invoke) return;\n setBusy(true);\n try {\n await run(invoke);\n } catch (e) {\n setToast(String(e));\n }\n setBusy(false);\n void live.refreshStates();\n }\n /** Opens a console on the machine, or its screen (GNS3's VNC console: its VNC server, or a VM's display). */\n async function open(command: \"machine_console\" | \"machine_display\", machine: string) {\n if (!invoke) return;\n try {\n const shown = await invoke<string>(command, { name: labName, machine });\n if (command === \"machine_display\") setToast(t.machineRun.displayOpened(shown));\n } catch (e) {\n setToast(String(e));\n }\n }\n return {\n busy,\n snapshotDo: (command: string, args: Record<string, unknown>) => act((run) => run(command, { name: labName, ...args })),\n machineAct: (machine: string, action: MachineAction) => act((run) => run(\"machine_action\", { name: labName, machine, action })),\n /** Cuts or reconnects the ports of `machines` on `network` (every machine's, when not named). */\n linkAct: (network: string, machines: string[] | undefined, action: LinkAction) =>\n act(async (run) => {\n live.setLinks(await run<SuspendedLink[]>(\"link_action\", { name: labName, network, machines, action }));\n }),\n machineConsole: (machine: string) => open(\"machine_console\", machine),\n machineDisplay: (machine: string) => open(\"machine_display\", machine),\n };\n}\n", "import type { DragEvent, MouseEvent, RefObject } from \"react\";\nimport type { XYPosition } from \"@xyflow/react\";\nimport { LAN_TOOL, NOTE_TOOL, SWITCH_TOOL } from \"@/lib/tool/blocks\";\nimport { newLan, newNote } from \"@/lib/tool/create\";\nimport { isLan, unselected, type LabNode, type LanNode } from \"@/lib/tool/model\";\nimport { paletteSpot, placeAppliance, placeMachine, placeSwitch } from \"@/lib/tool/placement\";\nimport type { Preset } from \"@/lib/tool/presets\";\nimport type { Lab } from \"./use-lab\";\nimport type { Tools } from \"./use-tools\";\n\n/** The drag-and-drop type of a device dragged from the toolbar. */\nexport const PRESET_MIME = \"application/x-isothrum-preset\";\n\ninterface Deps {\n lab: Lab;\n lans: LanNode[];\n tools: Tools;\n presets: Preset[];\n canvasRef: RefObject<HTMLDivElement | null>;\n screenToFlowPosition: (p: XYPosition) => XYPosition;\n /** Closes the right-click menus (a click on the canvas does). */\n closeMenus: () => void;\n /** Opens a dropped GNS3 project. */\n importGns3: (file: File) => void;\n}\n\n/** Placing devices, LANs, switches and notes: by a click on the canvas with a tool, or a drop. */\nexport function usePlacement({ lab, lans, tools, presets, canvasRef, screenToFlowPosition, closeMenus, importGns3 }: Deps) {\n const { setNodes } = lab;\n function addPreset(presetId: string, at?: XYPosition) {\n const preset = presets.find((p) => p.id === presetId);\n if (!preset) return;\n // A click in the palette drops the machine in the middle of the view.\n const viewCenter = () => {\n const r = canvasRef.current?.getBoundingClientRect();\n return r ? screenToFlowPosition({ x: r.left + r.width / 2, y: r.top + r.height / 2 }) : { x: 0, y: 0 };\n };\n const position = at ?? paletteSpot(viewCenter(), lab.nodes);\n if (preset.data.icon === \"router\" || preset.data.icon === \"shield\") setNodes((ns) => placeAppliance(preset, position, !!at, ns, lans));\n else setNodes((ns) => placeMachine(preset, position, ns));\n }\n /** Places the active tool, centered on the pointer; then back to selecting, as Excalidraw does after a shape. */\n function place(tool: string, e: MouseEvent) {\n const at = () => screenToFlowPosition({ x: e.clientX, y: e.clientY });\n // LANs go first in the list, so they are drawn under the machines; notes on top of everything, so they can sit over a LAN.\n if (tool === LAN_TOOL) {\n const center = at();\n setNodes((ns) => [{ ...newLan(center, ns), selected: true }, ...unselected(ns)]);\n } else if (tool === NOTE_TOOL) {\n const { x, y } = at();\n setNodes((ns) => [...unselected(ns), newNote({ x: x - 100, y: y - 45 })]);\n } else if (tool === SWITCH_TOOL) {\n const center = at();\n setNodes((ns) => placeSwitch(center, ns, lans));\n } else addPreset(tool, screenToFlowPosition({ x: e.clientX - 60, y: e.clientY - 58 }));\n }\n function onPaneClick(e: MouseEvent) {\n closeMenus();\n if (!tools.activeTool) return;\n place(tools.activeTool, e);\n tools.setActiveTool(null);\n }\n return {\n onPaneClick,\n // Inside a LAN the click lands on the area, not the canvas: placing there is the common case.\n onNodeClick: (e: MouseEvent, node: LabNode) => {\n if (tools.activeTool && isLan(node)) onPaneClick(e);\n },\n onDrop: (e: DragEvent) => {\n e.preventDefault();\n const file = [...e.dataTransfer.files].find((f) => f.name.endsWith(\".gns3\"));\n if (file) {\n importGns3(file);\n return;\n }\n const id = e.dataTransfer.getData(PRESET_MIME);\n if (id) addPreset(id, screenToFlowPosition({ x: e.clientX - 60, y: e.clientY - 58 }));\n },\n };\n}\n", "import { useEffect, useEffectEvent, useMemo, useState } from \"react\";\nimport { normalizeDraft, plainDraft } from \"@/lib/tool/draft\";\nimport type { Design, Draft } from \"@/lib/tool/model\";\nimport type { Plan } from \"@/lib/tool/engine\";\nimport { projectFromLink } from \"@/lib/tool/projects-api\";\nimport type { ProjectRef } from \"@/lib/tool/storage\";\nimport type { EditorText } from \"@/lib/tool/text\";\nimport { useProject } from \"./use-project\";\nimport { clearHash } from \"./use-shared-link\";\nimport { replaceLab, type Lab } from \"./use-lab\";\n\ninterface Deps {\n /** Accounts are on (the desktop's bundled editor has no site to ask). */\n accounts: boolean;\n lab: Lab;\n design: Design;\n setDesign: (d: Design) => void;\n plan: Plan | null;\n setToast: (message: string) => void;\n fitWhenDrawn: () => void;\n t: EditorText;\n}\n\n/** Saved projects, for a signed-in user (see `useProject`): opening, saving, Ctrl/\u2318 S. */\nexport function useProjects({ accounts, lab, design, setDesign, plan, setToast, fitWhenDrawn, t }: Deps) {\n const [signedInNow, setSignedInNow] = useState(false);\n const signedIn = accounts && signedInNow;\n const { labName, nodes, edges } = lab;\n const savedDraft = useMemo(() => plainDraft({ name: labName, nodes, edges, design }), [labName, nodes, edges, design]);\n const proj = useProject({ signedIn, draft: savedDraft, yml: plan?.ok ? plan.isoloom_yml : null });\n const [projectsOpen, setProjectsOpen] = useState(false);\n function openDraft(d: Draft) {\n const opened = normalizeDraft(d);\n if (!opened) return;\n replaceLab(lab, opened);\n if (opened.design) setDesign(opened.design);\n fitWhenDrawn();\n }\n /** Opens a project, attached to it from now on. */\n function openProject(p: ProjectRef, d: Draft) {\n const opened = normalizeDraft(d);\n if (!opened) return;\n openDraft(opened);\n proj.opened(p, plainDraft({ name: opened.name, nodes: opened.nodes, edges: opened.edges, design: opened.design ?? design }));\n setToast(t.projects.opened(p.name));\n }\n useProjectLink(signedIn, openProject);\n async function saveAs() {\n const name = window.prompt(t.projects.saveAsPrompt, proj.project ? `${proj.project.name} (2)` : labName);\n if (name?.trim()) await proj.save(true, name.trim());\n }\n useSaveKeys(signedIn, () => void proj.save(), () => void saveAs());\n return { signedIn, setSignedInNow, proj, projectsOpen, setProjectsOpen, openDraft, openProject, saveAs };\n}\n\n/** A link to a project (#project=<id>, as the MCP server gives): opens it once signed in. */\nfunction useProjectLink(signedIn: boolean, openProject: (p: ProjectRef, d: Draft) => void): void {\n const open = useEffectEvent((id: string) => {\n void projectFromLink(id).then((p) => {\n if (p) openProject({ id: p.id, name: p.name }, p.draft as Draft);\n });\n });\n useEffect(() => {\n const m = /^#project=([\\w-]+)$/.exec(window.location.hash);\n if (!m || !signedIn) return;\n clearHash();\n open(m[1]);\n }, [signedIn]);\n}\n\n/** Ctrl/\u2318 S saves the project, Ctrl/\u2318 Shift S saves it as a new one (signed in only). */\nfunction useSaveKeys(signedIn: boolean, save: () => void, saveAs: () => void): void {\n useEffect(() => {\n function onKey(e: KeyboardEvent) {\n if (!signedIn || !(e.metaKey || e.ctrlKey) || e.key.toLowerCase() !== \"s\") return;\n e.preventDefault();\n if (e.shiftKey) saveAs();\n else save();\n }\n window.addEventListener(\"keydown\", onKey);\n return () => {\n window.removeEventListener(\"keydown\", onKey);\n };\n });\n}\n", "import type { Draft } from \"./model\";\n\n/**\n * The site's project store (`/api/projects`), for a signed-in user: their projects, each with\n * its earlier versions. Errors carry the server's message, or the HTTP status.\n */\n\nexport interface ProjectSummary {\n id: string;\n name: string;\n updatedAt: string;\n}\nexport interface ProjectVersion {\n id: number;\n savedAt: string;\n}\n\n/** The server's reason in an error response (`{ error }`), or the status when it gives none. */\nasync function failure(r: Response): Promise<Error> {\n const body = (await r.json().catch(() => null)) as { error?: unknown } | null;\n const reason = body?.error;\n return new Error(typeof reason === \"string\" ? reason : String(r.status));\n}\n\nasync function api<T>(method: string, path: string, body?: unknown): Promise<T> {\n const r = await fetch(path, { method, headers: { \"content-type\": \"application/json\" }, body: body ? JSON.stringify(body) : undefined });\n if (!r.ok) throw await failure(r);\n return (r.status === 204 ? null : await r.json()) as T;\n}\n\nexport const listProjects = () => api<ProjectSummary[]>(\"GET\", \"/api/projects\");\nexport const getProject = (id: string) => api<{ id: string; name: string; draft: Draft }>(\"GET\", `/api/projects/${id}`);\nexport const deleteProject = (id: string) => api(\"DELETE\", `/api/projects/${id}`);\nexport const listVersions = (id: string) => api<ProjectVersion[]>(`GET`, `/api/projects/${id}/versions`);\nexport const getVersion = (id: string, version: number) => api<{ draft: Draft }>(\"GET\", `/api/projects/${id}/versions/${String(version)}`);\n\n/** Saves the lab as a new project (POST), or as the next version of `id` (PUT). */\nexport function saveProject(id: string | null, body: { name?: string; draft: Draft; isoloomYml: string | null }): Promise<ProjectSummary> {\n if (id) return api<ProjectSummary>(\"PUT\", `/api/projects/${id}`, body);\n return api<ProjectSummary>(\"POST\", \"/api/projects\", body);\n}\n\n/** A project by the id in a link (#project=\u2026), or null when it can't be read. */\nexport async function projectFromLink(id: string): Promise<{ id: string; name: string; draft: unknown } | null> {\n const r = await fetch(`/api/projects/${id}`);\n return r.ok ? ((await r.json()) as { id: string; name: string; draft: unknown }) : null;\n}\n", "import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { Draft } from \"@/lib/tool/model\";\nimport { saveProject as store } from \"@/lib/tool/projects-api\";\nimport { loadProject, saveProject as remember, type ProjectRef } from \"@/lib/tool/storage\";\n\n/**\n * Saved projects (isoloom/isothrum#31): the lab on the signed-in user's account. Once a lab is\n * saved as a project, every change saves itself (a moment after the last one); each save keeps\n * the previous version. The browser draft stays the working copy, signed in or not.\n */\n\nexport type SaveState = \"idle\" | \"saving\" | \"saved\" | \"error\";\n\nconst AUTOSAVE_MS = 2500;\n\ninterface Deps {\n signedIn: boolean;\n /** The lab as it is now (its identity changes on every edit). */\n draft: Draft;\n /** The isoloom.yml the engine generated for it. */\n yml: string | null;\n}\n\n/** The lab as last saved (its JSON; empty before the first save), to tell when it changed. */\nfunction useLastSaved() {\n const lastSaved = useRef(\"\");\n return useMemo(\n () => ({\n get: () => lastSaved.current,\n set: (json: string) => {\n lastSaved.current = json;\n },\n }),\n [],\n );\n}\n\ntype LastSaved = ReturnType<typeof useLastSaved>;\n\n/** Autosave: a moment after the last change, when the lab is a project. */\nfunction useAutosave(enabled: boolean, draft: Draft, lastSaved: LastSaved, save: () => unknown): void {\n useEffect(() => {\n if (!enabled) return;\n const now = JSON.stringify(draft);\n if (now === lastSaved.get()) return;\n if (!lastSaved.get()) {\n // Just attached (a reload): what's here is what was saved, or newer; save it next change.\n lastSaved.set(now);\n return;\n }\n const timer = setTimeout(() => void save(), AUTOSAVE_MS);\n return () => {\n clearTimeout(timer);\n };\n }, [enabled, draft, lastSaved, save]);\n}\n\n/** The project the editor is attached to, and saving it. */\nexport function useProject({ signedIn, draft, yml }: Deps) {\n const [project, setProject] = useState<ProjectRef | null>(null);\n const [state, setState] = useState<SaveState>(\"idle\");\n useEffect(() => {\n if (signedIn) queueMicrotask(() => { setProject(loadProject()); });\n }, [signedIn]);\n const attach = useCallback((p: ProjectRef | null) => {\n setProject(p);\n remember(p);\n }, []);\n // What a save sends: the lab as it is after the last render.\n const latest = useRef({ draft, yml });\n useEffect(() => {\n latest.current = { draft, yml };\n }, [draft, yml]);\n const lastSaved = useLastSaved();\n const save = useCallback(\n async (asNew = false, name?: string): Promise<ProjectRef | null> => {\n const now = latest.current;\n setState(\"saving\");\n try {\n const saved =\n project && !asNew\n ? await store(project.id, { draft: now.draft, isoloomYml: now.yml, ...(name ? { name } : {}) })\n : await store(null, { name: name ?? project?.name ?? now.draft.name, draft: now.draft, isoloomYml: now.yml });\n lastSaved.set(JSON.stringify(now.draft));\n attach({ id: saved.id, name: saved.name });\n setState(\"saved\");\n return saved;\n } catch {\n setState(\"error\");\n return null;\n }\n },\n [project, attach, lastSaved],\n );\n useAutosave(signedIn && !!project, draft, lastSaved, save);\n return {\n project,\n state,\n save,\n detach: () => {\n attach(null);\n lastSaved.set(\"\");\n setState(\"idle\");\n },\n /** After opening a project: attached to it, nothing to save yet. */\n opened: (p: ProjectRef, d: Draft) => {\n lastSaved.set(JSON.stringify(d));\n attach(p);\n setState(\"saved\");\n },\n };\n}\n", "import { useEffect, useEffectEvent } from \"react\";\nimport { decodeLab, encodeLab } from \"@/lib/tool/draft\";\nimport type { Design } from \"@/lib/tool/model\";\nimport type { EditorText } from \"@/lib/tool/text\";\nimport { replaceLab, type Lab } from \"./use-lab\";\n\n/** Removes the `#\u2026` part of the address once it has been read. */\nexport function clearHash(): void {\n window.history.replaceState(null, \"\", window.location.pathname + window.location.search);\n}\n\ninterface Deps {\n lab: Lab;\n setDesign: (d: Design) => void;\n setToast: (message: string) => void;\n /** Fits the view once React Flow has measured the new lab. */\n fitWhenDrawn: () => void;\n t: EditorText;\n}\n\n/**\n * A shared lab (#lab=\u2026 in the address) opens on arrival, and when a link is pasted into a tab\n * already on the editor (only the part after # changes then, and the browser doesn't reload).\n * Undo brings back what was there.\n */\nexport function useSharedLink({ lab, setDesign, setToast, fitWhenDrawn, t }: Deps): void {\n const open = useEffectEvent(() => {\n const m = /^#lab=([A-Za-z0-9_-]+)$/.exec(window.location.hash);\n if (!m) return;\n void decodeLab(m[1]).then((shared) => {\n clearHash();\n if (!shared) {\n setToast(t.toasts.brokenLink);\n return;\n }\n replaceLab(lab, shared);\n if (shared.design) setDesign(shared.design);\n setToast(t.toasts.openedShared(shared.name));\n fitWhenDrawn();\n });\n });\n useEffect(() => {\n const onHash = () => {\n open();\n };\n onHash();\n window.addEventListener(\"hashchange\", onHash);\n return () => {\n window.removeEventListener(\"hashchange\", onHash);\n };\n }, []);\n}\n\n/** Copies a link that opens this lab (its JSON, deflated, after `#lab=`). */\nexport async function copyShareLink(draft: Parameters<typeof encodeLab>[0], lang: string, setToast: (message: string) => void, t: EditorText) {\n const code = await encodeLab(draft);\n const url = `${window.location.origin}/${lang}#lab=${code}`;\n try {\n await navigator.clipboard.writeText(url);\n setToast(t.toasts.linkCopied);\n } catch {\n window.prompt(t.toasts.copyPrompt, url);\n }\n}\n", "import { useEffect, useState } from \"react\";\n\n/** A message at the bottom of the canvas, for a few seconds (longer when it is long). */\nexport function useToast(): [string | null, (message: string | null) => void] {\n const [toast, setToast] = useState<string | null>(null);\n useEffect(() => {\n if (!toast) return;\n const timer = setTimeout(() => {\n setToast(null);\n }, Math.max(4000, toast.length * 60));\n return () => {\n clearTimeout(timer);\n };\n }, [toast]);\n return [toast, setToast];\n}\n", "import { useEffect, useState } from \"react\";\nimport { LAN_TOOL, NOTE_TOOL, SWITCH_TOOL } from \"@/lib/tool/blocks\";\nimport { presetForKey } from \"@/lib/tool/presets\";\nimport { inTextField } from \"./use-history\";\n\n/** Excalidraw's two modes: select (drag a box, Shift-click, Delete) or hand (drag moves the canvas). */\nexport type Mode = \"select\" | \"hand\";\n\n/**\n * The device being placed (Excalidraw-style tool): the next click on the canvas drops it there.\n * Picking a tool selects again; picking the same one twice puts it down.\n */\nexport function useTools() {\n const [activeTool, setActiveTool] = useState<string | null>(null);\n const [mode, setMode] = useState<Mode>(\"select\");\n const pick = (tool: string) => {\n setMode(\"select\");\n setActiveTool(activeTool === tool ? null : tool);\n };\n const setModeOnly = (m: Mode) => {\n setMode(m);\n setActiveTool(null);\n };\n return { activeTool, setActiveTool, mode, setMode, pick, setModeOnly };\n}\n\nexport type Tools = ReturnType<typeof useTools>;\n\n/** The tool a key toggles: S a switch, L a LAN, T a note, 1\u20139 and 0 a device. */\nfunction toolForKey(key: string): string | undefined {\n const lower = key.toLowerCase();\n if (lower === \"s\" && key.length === 1) return SWITCH_TOOL;\n if (lower === \"l\" && key.length === 1) return LAN_TOOL;\n if (lower === \"t\" && key.length === 1) return NOTE_TOOL;\n return presetForKey(key)?.id;\n}\n\n/** Keyboard: 1\u20139 and 0 pick a device, S, L, T a switch, LAN or note, V selects, H the hand, Escape puts it down. Not while typing in a field. */\nexport function useToolKeys(tools: Tools): void {\n const { setMode, setActiveTool } = tools;\n useEffect(() => {\n function onKey(e: KeyboardEvent) {\n if (e.metaKey || e.ctrlKey || e.altKey || inTextField(e)) return;\n if (e.key === \"Escape\") setActiveTool(null);\n if (e.key === \"v\" || e.key === \"V\" || e.key === \"h\" || e.key === \"H\") {\n setMode(e.key === \"h\" || e.key === \"H\" ? \"hand\" : \"select\");\n setActiveTool(null);\n }\n const tool = toolForKey(e.key);\n if (tool) {\n setMode(\"select\");\n setActiveTool((cur) => (cur === tool ? null : tool));\n }\n }\n window.addEventListener(\"keydown\", onKey);\n return () => {\n window.removeEventListener(\"keydown\", onKey);\n };\n }, [setMode, setActiveTool]);\n}\n", "\"use client\";\n\nimport { LayoutTemplate, X } from \"lucide-react\";\nimport { useBrandMark } from \"@/lib/brand\";\nimport { Button, buttonVariants } from \"@/components/ui/button\";\nimport type { EditorModel } from \"./hooks/use-editor\";\nimport { useText } from \"./text\";\n\n/** Handwritten hints, pointing at the menu and the toolbar. */\nfunction WelcomeHints() {\n const t = useText().welcome;\n return (\n <>\n <div aria-hidden className=\"pointer-events-none absolute top-14 left-6 z-0 hidden items-start gap-1 font-heading text-sm text-muted-foreground md:flex\">\n <svg viewBox=\"0 0 40 40\" className=\"size-9 -scale-x-100\" fill=\"none\">\n <path d=\"M34 36C30 22 22 12 8 6m0 0 2 8M8 6l8 0\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" />\n </svg>\n <span className=\"mt-6\">{t.menuHint}</span>\n </div>\n <div aria-hidden className=\"pointer-events-none absolute top-24 left-1/2 z-0 hidden -translate-x-[calc(100%+40px)] items-start gap-1 font-heading text-sm text-muted-foreground md:flex\">\n <span className=\"mt-6\">{t.toolbarHint}</span>\n <svg viewBox=\"0 0 40 40\" className=\"size-9\" fill=\"none\">\n <path d=\"M6 36C12 24 22 14 34 8m0 0-8 0m8 0-2 8\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" />\n </svg>\n </div>\n </>\n );\n}\n\n/** The empty canvas: who we are, where to start, and handwritten pointers to the controls. */\nfunction Welcome({ onExample, lang }: { onExample: () => void; lang: string }) {\n const t = useText().welcome;\n const LogoMark = useBrandMark();\n return (\n <>\n <WelcomeHints />\n <div className=\"pointer-events-none absolute inset-0 z-0 grid place-items-center p-6\">\n {/* Only the buttons take clicks: a drop or a click elsewhere goes to the canvas below. */}\n <div className=\"flex max-w-md flex-col items-center text-center\">\n <LogoMark className=\"size-14\" />\n <p className=\"mt-4 font-heading text-4xl font-semibold lowercase\">isothrum</p>\n <p className=\"mt-3 text-muted-foreground text-pretty\">{t.pitch}</p>\n <div className=\"pointer-events-auto mt-6 flex flex-wrap justify-center gap-2\">\n <Button onClick={onExample}>\n <LayoutTemplate data-icon=\"inline-start\" /> {t.example}\n </Button>\n <a href={`/${lang}/about`} className={buttonVariants({ variant: \"outline\" })}>\n {t.how}\n </a>\n </div>\n </div>\n </div>\n </>\n );\n}\n\n/** Desktop app: a newer release is out; restarting installs it. */\nfunction UpdateBanner({ e, version }: { e: EditorModel; version: string }) {\n const t = e.t.update;\n const { invoke, updating, setUpdating, setUpdate } = e.desk.state;\n async function install() {\n if (!invoke) return;\n setUpdating(true);\n try {\n await invoke(\"update_install\");\n } catch (err) {\n e.setToast(String(err));\n setUpdating(false);\n }\n }\n return (\n <div role=\"status\" className=\"absolute right-4 bottom-4 z-30 flex items-center gap-3 rounded-lg border bg-popover px-3 py-2 text-sm shadow-sm\">\n <span>{t.available(version)}</span>\n <Button size=\"sm\" disabled={updating} onClick={() => void install()}>\n {updating ? t.installing : t.restart}\n </Button>\n <button type=\"button\" className=\"text-muted-foreground hover:text-foreground\" aria-label={t.later} title={t.later} onClick={() => { setUpdate(null); }}>\n <X className=\"size-4\" />\n </button>\n </div>\n );\n}\n\n/** What floats over the canvas's bottom: the welcome, an update, a toast, an engine that didn't load. */\nexport function Overlays({ e }: { e: EditorModel }) {\n const { update } = e.desk.state;\n return (\n <>\n {/* The empty canvas welcomes, as Excalidraw does. Hidden while a device is picked, so the whole canvas is free to click. */}\n {e.empty && !e.tools.activeTool && <Welcome onExample={() => { e.actions.loadExample(); }} lang={e.lang} />}\n {update && <UpdateBanner e={e} version={update} />}\n {e.toast && (\n <p role=\"status\" className=\"absolute bottom-4 left-1/2 z-30 w-max max-w-[min(36rem,calc(100vw-2rem))] -translate-x-1/2 rounded-lg border bg-popover px-3 py-2 text-sm shadow-sm\">\n {e.toast}\n </p>\n )}\n {e.engineError && (\n <p role=\"alert\" className=\"absolute bottom-4 left-1/2 z-10 -translate-x-1/2 rounded-lg border bg-popover px-3 py-2 text-sm text-destructive shadow-sm\">\n {e.t.engineDidntLoad(e.engineError)}\n </p>\n )}\n </>\n );\n}\n", "import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-link underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-10 gap-2 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n icon: \"size-8\",\n \"icon-xs\":\n \"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\":\n \"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg\",\n \"icon-lg\": \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n", "\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport { Hand, MousePointer2, Network, StickyNote } from \"lucide-react\";\nimport { LAN_TOOL, NOTE_TOOL, hintFor } from \"@/lib/tool/blocks\";\nimport { cn } from \"@/lib/utils\";\nimport { DeviceBlock } from \"./device-block\";\nimport type { EditorModel } from \"./hooks/use-editor\";\nimport type { Mode } from \"./hooks/use-tools\";\n\nconst KEY = \"absolute bottom-0 left-0.5 font-mono text-[9px] text-muted-foreground\";\nconst TOOL = \"relative grid size-10 shrink-0 place-items-center rounded-lg transition-colors hover:bg-muted\";\nconst PICKED = \"bg-brand-100 ring-1 ring-signal hover:bg-brand-100 dark:bg-brand-950\";\n\nconst Separator = () => <span className=\"mx-1 h-6 w-px shrink-0 bg-border\" aria-hidden />;\n\n/** Hand and selection, Excalidraw's two modes. */\nfunction ModeButtons({ e }: { e: EditorModel }) {\n const t = e.t.toolbar;\n const { tools } = e;\n const modes: [Mode, typeof Hand, string, string][] = [\n [\"hand\", Hand, t.hand, \"H\"],\n [\"select\", MousePointer2, t.select, \"V\"],\n ];\n return modes.map(([m, Icon, label, key]) => {\n const on = tools.mode === m && !tools.activeTool;\n return (\n <button\n key={m}\n type=\"button\"\n onClick={() => { tools.setModeOnly(m); }}\n aria-pressed={on}\n aria-label={label}\n title={`${label} \u00B7 ${key}`}\n className={cn(TOOL, on && \"bg-brand-100 text-brand-700 hover:bg-brand-100 dark:bg-brand-950 dark:text-brand-300\")}\n >\n <Icon className=\"size-[18px]\" aria-hidden />\n <span className={KEY}>{key}</span>\n </button>\n );\n });\n}\n\n/** A tool of its own (a LAN, a note): picked, it is the next thing a click places. */\nfunction ToolButton({ e, tool, label, title, letter, children }: { e: EditorModel; tool: string; label: string; title: string; letter: string; children: ReactNode }) {\n const { tools } = e;\n return (\n <button\n type=\"button\"\n onClick={() => { tools.pick(tool); }}\n aria-pressed={tools.activeTool === tool}\n aria-label={label}\n title={`${title} \u00B7 ${letter}`}\n className={cn(TOOL, tools.activeTool === tool && PICKED)}\n >\n {children}\n <span className={KEY}>{letter}</span>\n </button>\n );\n}\n\n/** The blocks from `from` to `to` (the network ones, then the machines). */\nfunction Blocks({ e, from, to }: { e: EditorModel; from: number; to?: number }) {\n const { devices, tools } = e;\n return devices.blocks.slice(from, to).map((b) => (\n <DeviceBlock key={b.id} block={b} choice={devices.blockChoice[b.id]} active={tools.activeTool} onPick={(tool) => { devices.pickFromBlock(b.id, tool); }} onForget={devices.forgetDevice} />\n ));\n}\n\n/** Top center: the devices, grouped as network, containers, VMs; the line under it says what a click does. */\nexport function Toolbar({ e }: { e: EditorModel }) {\n const t = e.t;\n const { tools, lab } = e;\n const hint = hintFor(tools.activeTool, e.tool?.label, { hand: tools.mode === \"hand\", nodes: lab.nodes.length, edges: lab.edges.length }, t);\n return (\n <div className=\"pointer-events-none absolute inset-x-0 top-3 z-10 flex flex-col items-center gap-2 px-16 max-sm:items-start max-sm:pl-16\">\n <div role=\"toolbar\" aria-label={t.toolbar.devices} className=\"pointer-events-auto flex max-w-full items-center gap-0.5 overflow-x-auto rounded-xl border bg-popover p-1 shadow-[0_4px_20px_-6px_rgb(0_0_0/0.15)]\">\n <ModeButtons e={e} />\n <Separator />\n {/* The devices as elementary blocks: a LAN, a switch, a router, a firewall, a\n container, a VM (and the devices saved from the canvas). A block places the kind\n picked last; its arrow lists the kinds. */}\n <div className=\"flex items-center gap-0.5\">\n <ToolButton e={e} tool={LAN_TOOL} label={t.toolbar.lan} title={t.toolbar.lanTitle} letter=\"L\">\n <span className=\"grid size-8 place-items-center rounded-md border border-dashed border-foreground/40 bg-pastel-blue\">\n <Network className=\"size-4\" aria-hidden />\n </span>\n </ToolButton>\n <Blocks e={e} from={0} to={3} />\n </div>\n <Separator />\n <div className=\"flex items-center gap-0.5\">\n <Blocks e={e} from={3} />\n </div>\n <div className=\"flex items-center gap-0.5\">\n <Separator />\n <ToolButton e={e} tool={NOTE_TOOL} label={t.toolbar.note} title={t.toolbar.noteTitle} letter=\"T\">\n <StickyNote className=\"size-5\" />\n </ToolButton>\n </div>\n </div>\n {/* On the empty canvas the welcome's handwritten hints say it instead. */}\n {(!e.empty || tools.activeTool) && <p className=\"pointer-events-none hidden text-center text-xs text-muted-foreground sm:block\">{hint}</p>}\n </div>\n );\n}\n", "\"use client\";\n\nimport { Check, ChevronDown, X } from \"lucide-react\";\nimport type { Block, BlockOption } from \"@/lib/tool/blocks\";\nimport { cn } from \"@/lib/utils\";\nimport { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuShortcut, DropdownMenuTrigger } from \"@/components/ui/dropdown-menu\";\nimport { DeviceIcon } from \"./canvas/device-icon\";\nimport { PRESET_MIME } from \"./hooks/use-placement\";\nimport { useText } from \"./text\";\n\n/** A kind's picture: the device's, or the switch's ports. */\nfunction BlockIcon({ option }: { option: BlockOption }) {\n if (option.preset) return <DeviceIcon data={option.preset.data} size=\"sm\" />;\n return (\n <span className=\"flex size-8 shrink-0 items-center justify-center gap-[2px] rounded-md bg-background ring-1 ring-foreground/10\" aria-hidden>\n {[\"#7048e8\", \"#7048e8\", \"#2f9e44\", \"#2f9e44\"].map((c, i) => (\n <span key={i} className=\"h-3 w-1 rounded-[1px]\" style={{ background: c }} />\n ))}\n </span>\n );\n}\n\n/** One kind in a block's list: what it is, its key, and (a saved device) a way to forget it. */\nfunction KindItem({ o, current, onPick, onForget }: { o: BlockOption; current: string; onPick: (tool: string) => void; onForget: (id: string) => void }) {\n const t = useText().toolbar;\n return (\n <DropdownMenuItem onClick={() => { onPick(o.tool); }} className=\"gap-2.5\">\n <BlockIcon option={o} />\n <span className=\"flex min-w-0 flex-1 flex-col\">\n <span className=\"truncate\">{o.label}</span>\n <span className=\"truncate text-xs text-muted-foreground\">{o.hint}</span>\n </span>\n {o.tool === current && <Check className=\"size-4 text-muted-foreground\" />}\n {o.key && <DropdownMenuShortcut>{o.key}</DropdownMenuShortcut>}\n {o.preset?.group === \"mine\" && (\n <span\n role=\"button\"\n tabIndex={-1}\n aria-label={t.forgetLabel(o.label)}\n title={t.forget(o.label)}\n onClick={(e) => {\n e.stopPropagation();\n onForget(o.tool);\n }}\n className=\"grid size-5 place-items-center rounded text-muted-foreground hover:bg-muted hover:text-foreground\"\n >\n <X className=\"size-3\" />\n </span>\n )}\n </DropdownMenuItem>\n );\n}\n\n/** A block's arrow: every kind it places, with what it is and its key. */\nfunction KindsMenu({ block, current, onPick, onForget }: { block: Block; current: string; onPick: (tool: string) => void; onForget: (id: string) => void }) {\n const t = useText().toolbar;\n return (\n <DropdownMenu>\n <DropdownMenuTrigger\n aria-label={t.kindsOf(block.label)}\n title={t.kindsOf(block.label)}\n className=\"absolute -right-0.5 -bottom-0.5 grid size-4 place-items-center rounded-full border bg-popover text-muted-foreground shadow-sm hover:text-foreground\"\n >\n <ChevronDown className=\"size-2.5\" />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-72\">\n <DropdownMenuGroup>\n <DropdownMenuLabel>{block.label}</DropdownMenuLabel>\n </DropdownMenuGroup>\n {block.options.map((o) => (\n <KindItem key={o.tool} o={o} current={current} onPick={onPick} onForget={onForget} />\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\n/**\n * A toolbar block: one button that places the kind picked last (drag it, or click then click\n * the canvas), and an arrow listing every kind with what it is and its key.\n */\nexport function DeviceBlock({ block, choice, active, onPick, onForget }: { block: Block; choice: string | undefined; active: string | null; onPick: (tool: string) => void; onForget: (id: string) => void }) {\n const current = block.options.find((o) => o.tool === choice) ?? block.options.at(0);\n if (!current) return null;\n const on = block.options.some((o) => o.tool === active);\n return (\n <div className={cn(\"relative flex shrink-0 items-center rounded-lg\", on && \"bg-brand-100 ring-1 ring-signal dark:bg-brand-950\")}>\n <button\n type=\"button\"\n draggable={!!current.preset}\n onDragStart={(e) => {\n if (!current.preset) return;\n e.dataTransfer.setData(PRESET_MIME, current.preset.id);\n e.dataTransfer.effectAllowed = \"move\";\n }}\n onClick={() => { onPick(current.tool); }}\n aria-pressed={on}\n aria-label={`${block.label}: ${current.label}`}\n title={`${block.label}: ${current.label} (${current.hint})${current.key ? ` \u00B7 ${current.key}` : \"\"}`}\n className={cn(\"grid size-10 place-items-center rounded-lg transition-colors hover:bg-muted\", on && \"hover:bg-transparent\")}\n >\n <BlockIcon option={current} />\n </button>\n {block.options.length > 1 && <KindsMenu block={block} current={current.tool} onPick={onPick} onForget={onForget} />}\n </div>\n );\n}\n", "\"use client\";\n\nimport { CircleAlert, CircleCheck, Download, Play, Square } from \"lucide-react\";\nimport { vlanExample } from \"@/lib/tool/examples\";\nimport { cn } from \"@/lib/utils\";\nimport { Button } from \"@/components/ui/button\";\nimport { EditorMenu } from \"./editor-menu\";\nimport { copyShareLink } from \"./hooks/use-shared-link\";\nimport type { EditorModel } from \"./hooks/use-editor\";\n\n/** Top left: the menu, and where the lab is saved. */\nexport function TopLeft({ e, onImportGns3 }: { e: EditorModel; onImportGns3: () => void }) {\n const { projects, actions, lab, design, t } = e;\n const { proj } = projects;\n const share = () => copyShareLink({ name: lab.labName, nodes: lab.nodes, edges: lab.edges, design: design.design }, e.lang, e.setToast, t);\n const projectActions = projects.signedIn ? { onSave: () => void proj.save(), onSaveAs: () => void projects.saveAs(), onOpen: () => { projects.setProjectsOpen(true); } } : null;\n return (\n <div className=\"absolute top-3 left-3 z-10 flex items-center gap-2\">\n <EditorMenu\n lang={e.lang}\n onExample={() => { actions.loadExample(); }}\n onVlanExample={() => { actions.loadExample(vlanExample); }}\n onShare={() => void share()}\n onImportGns3={onImportGns3}\n onClear={actions.clearLab}\n onFit={() => void e.flow.fitView({ padding: 0.4, duration: 300 })}\n canClear={!e.empty}\n design={design.design}\n onDesign={design.chooseDesign}\n accounts={e.accounts}\n projects={projectActions}\n />\n {projects.signedIn && proj.project && (\n <span role=\"status\" className={cn(\"pointer-events-none max-w-56 truncate rounded-md px-1.5 text-xs text-muted-foreground max-sm:hidden\", proj.state === \"error\" && \"text-destructive\")}>\n {t.projects.status[proj.state](proj.project.name)}\n </span>\n )}\n </div>\n );\n}\n\n/** The lab's status: valid, or how many things to fix (the engine still loading). */\nfunction StatusButton({ e }: { e: EditorModel }) {\n const { issues, t } = e;\n const label = !e.engine ? t.status.loading : issues.length ? t.status.toFix(issues.length) : t.status.valid;\n return (\n <button type=\"button\" onClick={() => { e.setStatusOpen((o) => !o); }} className={cn(\"flex h-9 items-center gap-1.5 rounded-lg border bg-popover px-3 text-xs font-medium shadow-sm\", issues.length ? \"text-warning\" : \"text-success\")}>\n {issues.length ? <CircleAlert className=\"size-4\" /> : <CircleCheck className=\"size-4\" />}\n <span className=\"max-sm:sr-only\">{label}</span>\n </button>\n );\n}\n\n/** Desktop app: run the lab on this machine, or stop it. */\nfunction RunButton({ e }: { e: EditorModel }) {\n const { t, hasVms } = e;\n const { run, info } = e.desk.state;\n if (run === \"running\" || run === \"stopping\") {\n return (\n <Button variant=\"outline\" onClick={() => void e.run.stopLab()} disabled={run === \"stopping\"} className=\"h-9 bg-popover shadow-sm\">\n <Square data-icon=\"inline-start\" /> {run === \"stopping\" ? t.run.stopping : t.run.stop}\n </Button>\n );\n }\n const vagrant = !!info?.vagrant;\n return (\n <Button\n variant=\"outline\"\n onClick={() => void e.run.runLab()}\n disabled={run === \"starting\" || !e.plan?.ok || e.issues.length > 0 || e.empty || (hasVms && !vagrant)}\n title={hasVms ? (vagrant ? t.run.runVmsTitle : t.run.vmsTitle) : t.run.runTitle}\n className=\"h-9 bg-popover shadow-sm\"\n >\n <Play data-icon=\"inline-start\" /> {run === \"starting\" ? t.run.starting : t.run.run}\n </Button>\n );\n}\n\n/** Top right: the lab's status, Run (desktop app), and Export. */\nexport function TopRight({ e }: { e: EditorModel }) {\n return (\n <div className=\"absolute top-3 right-3 z-10 flex items-center gap-2\">\n {!e.empty && <StatusButton e={e} />}\n {e.invoke && <RunButton e={e} />}\n <Button onClick={() => { e.setExportOpen((o) => !o); }} disabled={!e.engine || e.empty} className=\"h-9 shadow-sm\">\n <Download data-icon=\"inline-start\" /> {e.t.export}\n </Button>\n </div>\n );\n}\n", "\"use client\";\n\nimport { useState } from \"react\";\nimport { CircleAlert, Download, FileCode } from \"lucide-react\";\nimport type { GeneratedFile } from \"@/lib/tool/engine\";\nimport { groupByTarget } from \"@/lib/tool/export-targets\";\nimport { Button } from \"@/components/ui/button\";\nimport { useText } from \"../text\";\nimport { CopyButton } from \"./copy-button\";\nimport { TargetList, type Opened } from \"./target-list\";\n\n/** One line to install the Isoloom command line (macOS, Linux; Windows binaries are on its releases page). */\nconst INSTALL = \"curl -fsSL https://raw.githubusercontent.com/isoloom/isoloom/main/install.sh | sh\";\n\ninterface ExportPanelProps {\n labName: string;\n onLabNameChange: (name: string) => void;\n /** Containers and VMs together: only Vagrant can run it. */\n mixed: boolean;\n spec: string | null;\n files: GeneratedFile[];\n issues: string[];\n onDownloadAll: () => void;\n onDownloadSpec: () => void;\n /** One target's zip: isoloom.yml and that target's folder. */\n onDownloadTarget: (dir: string) => void;\n}\n\n/** What to fix before the lab can be downloaded. */\nfunction FixFirst({ issues }: { issues: string[] }) {\n const t = useText().exportPanel;\n return (\n <div className=\"rounded-lg border border-warning/40 bg-warning/5 p-4 text-sm\">\n <p className=\"flex items-center gap-2 font-medium\">\n <CircleAlert className=\"size-4 text-warning\" aria-hidden /> {t.fixFirst}\n </p>\n <ul className=\"mt-2 list-disc space-y-1 pl-6 text-muted-foreground\">\n {issues.map((p, i) => (\n <li key={i}>{p}</li>\n ))}\n </ul>\n </div>\n );\n}\n\n/** Where it runs: one folder per target in the zip, how to install Isoloom, each target's commands. */\nfunction WhereItRuns({ p, opened }: { p: ExportPanelProps; opened: Opened }) {\n const t = useText().exportPanel;\n return (\n <section className=\"flex flex-col gap-3\">\n <div>\n <h3 className=\"font-semibold\">{t.where}</h3>\n <p className=\"text-sm text-muted-foreground\">{t.whereIntro}</p>\n {p.mixed && <p className=\"mt-2 rounded-md bg-pastel-yellow p-2.5 text-sm\">{t.mixed}</p>}\n </div>\n <div className=\"flex flex-col gap-1.5 rounded-md bg-pastel-violet p-3 text-xs\">\n <span>{t.install}</span>\n <div className=\"flex items-center gap-2\">\n <code className=\"min-w-0 flex-1 truncate font-mono\">{INSTALL}</code>\n <CopyButton text={INSTALL} />\n </div>\n </div>\n <TargetList targets={groupByTarget(p.files, t)} ready opened={opened} onDownloadTarget={p.onDownloadTarget} />\n </section>\n );\n}\n\n/** isoloom.yml: the lab as one readable file, to keep in Git or edit by hand. */\nfunction SpecSection({ spec, show, onToggle }: { spec: string; show: boolean; onToggle: () => void }) {\n const t = useText().exportPanel;\n return (\n <section className=\"flex flex-col gap-3\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h3 className=\"font-semibold\">isoloom.yml</h3>\n <p className=\"text-sm text-muted-foreground\">{t.specIntro}</p>\n </div>\n </div>\n <div className=\"rounded-lg border bg-surface\">\n <div className=\"flex items-center justify-between border-b px-3 py-1\">\n <button type=\"button\" className=\"text-xs text-muted-foreground hover:text-foreground\" onClick={onToggle}>\n {show ? t.hideSpec : t.showSpec}\n </button>\n <CopyButton text={spec} />\n </div>\n {show && (\n <pre className=\"max-h-96 overflow-auto p-3 font-mono text-xs\">\n <code>{spec}</code>\n </pre>\n )}\n </div>\n </section>\n );\n}\n\n/** What the Export window shows: the lab's name, the downloads, where it runs and how. */\nexport function ExportPanel(p: ExportPanelProps) {\n const t = useText().exportPanel;\n const [openTarget, setOpenTarget] = useState<string | null>(null);\n const [openFile, setOpenFile] = useState<string | null>(null);\n const [showSpec, setShowSpec] = useState(false);\n const ready = p.spec !== null && p.issues.length === 0;\n const opened: Opened = { target: openTarget, setTarget: setOpenTarget, file: openFile, setFile: setOpenFile };\n return (\n <div className=\"flex flex-col gap-6 p-4\">\n <label className=\"flex flex-col gap-1 text-sm\">\n <span className=\"text-muted-foreground\">{t.labName}</span>\n <input\n className=\"h-9 w-full rounded-md border border-input bg-background px-2.5 font-mono text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n value={p.labName}\n onChange={(e) => { p.onLabNameChange(e.target.value); }}\n />\n </label>\n {!ready && <FixFirst issues={p.issues} />}\n <div className=\"flex flex-col gap-2\">\n <Button size=\"lg\" onClick={p.onDownloadAll} disabled={!ready}>\n <Download data-icon=\"inline-start\" /> {t.download(p.labName || \"lab\")}\n </Button>\n <Button size=\"lg\" variant=\"outline\" onClick={p.onDownloadSpec} disabled={p.spec === null}>\n <FileCode data-icon=\"inline-start\" /> {t.onlySpec}\n </Button>\n </div>\n {ready && <WhereItRuns p={p} opened={opened} />}\n {p.spec && <SpecSection spec={p.spec} show={showSpec} onToggle={() => { setShowSpec((s) => !s); }} />}\n </div>\n );\n}\n", "import type { GeneratedFile } from \"./engine\";\n\n/**\n * The Isoloom outputs in a lab's zip, as the Export window lists them: how each is named for\n * people, the one Isoloom command that starts it (from the unzipped folder), and the same thing\n * with the tool itself.\n */\n\n/** The words the names take (the editor's text). */\nexport interface TargetText {\n containersAndVms: string;\n oneVmPerMachine: string;\n dockerOnOneVm: string;\n}\n\nexport interface Target {\n dir: string;\n files: GeneratedFile[];\n name: string;\n isoloom: string | null;\n run: string;\n}\n\nconst CLOUDS: Partial<Record<string, string>> = {\n aws: \"AWS\",\n azure: \"Azure\",\n gcp: \"Google Cloud\",\n digitalocean: \"DigitalOcean\",\n linode: \"Linode\",\n oci: \"Oracle Cloud\",\n};\n\ntype Described = Pick<Target, \"name\" | \"isoloom\" | \"run\">;\n\n/** A cloud output (one folder per cloud): Docker on one VM, or one VM per machine. */\nfunction cloudTarget(target: string, cloud: string | undefined, terraform: string, t: TargetText): Described {\n const where = CLOUDS[cloud ?? \"\"] ?? String(cloud);\n if (target === \"cloud-docker\") return { name: `${where} (${t.dockerOnOneVm})`, isoloom: `isoloom run cloud-docker --cloud ${String(cloud)}`, run: terraform };\n return { name: `${where} (${t.oneVmPerMachine})`, isoloom: `isoloom run cloud-vm --cloud ${String(cloud)}`, run: terraform };\n}\n\nfunction describe(dir: string, t: TargetText): Described {\n const [target, cloud] = dir.split(\"/\") as [string, string | undefined];\n const terraform = `cd .isoloom/${dir} && terraform init && terraform apply`;\n switch (target) {\n case \"docker\":\n return { name: \"Docker Compose\", isoloom: \"isoloom run docker\", run: \"docker compose -f .isoloom/docker/compose.yml up -d\" };\n case \"hybrid\":\n return { name: `Vagrant (${t.containersAndVms})`, isoloom: \"isoloom run hybrid\", run: \"cd .isoloom/hybrid && vagrant up\" };\n case \"vagrant\":\n return { name: `Vagrant (${t.oneVmPerMachine})`, isoloom: \"isoloom run vagrant\", run: \"cd .isoloom/vagrant && vagrant up\" };\n case \"docker-vm\":\n return cloud === \"proxmox\"\n ? { name: `Proxmox (${t.dockerOnOneVm})`, isoloom: null, run: terraform }\n : { name: `Vagrant (${t.dockerOnOneVm})`, isoloom: \"isoloom run docker-vm\", run: \"cd .isoloom/docker-vm && vagrant up\" };\n case \"proxmox\":\n return { name: `Proxmox (${t.oneVmPerMachine})`, isoloom: \"isoloom run proxmox\", run: terraform };\n case \"kubernetes\":\n return { name: \"Kubernetes\", isoloom: \"isoloom run kubernetes\", run: \"kubectl kustomize --load-restrictor LoadRestrictionsNone .isoloom/kubernetes | kubectl apply -f -\" };\n case \"cloud-docker\":\n case \"cloud-vm\":\n return cloudTarget(target, cloud, terraform, t);\n default:\n return { name: dir, isoloom: null, run: \"\" };\n }\n}\n\n/** The folder a generated file belongs to: `<target>`, or `<target>/<cloud>` for a cloud output and docker-vm's Proxmox module. */\nfunction folderOf(path: string): string {\n const parts = path.replace(/^\\.isoloom\\//, \"\").split(\"/\");\n // Every other subfolder (checks/, \u2026) belongs to its target.\n const deeper = parts.length > 2 && (parts[0] === \"cloud-docker\" || parts[0] === \"cloud-vm\" || (parts[0] === \"docker-vm\" && parts[1] === \"proxmox\"));\n return deeper ? `${parts[0]}/${parts[1]}` : parts[0];\n}\n\n/** Generated files grouped by where they run: `.isoloom/<target>[/<cloud>]/\u2026`. */\nexport function groupByTarget(files: GeneratedFile[], t: TargetText): Target[] {\n const groups = new Map<string, GeneratedFile[]>();\n for (const f of files) {\n const dir = folderOf(f.path);\n groups.set(dir, [...(groups.get(dir) ?? []), f]);\n }\n return [...groups.entries()].map(([dir, fs]) => ({ dir, files: fs, ...describe(dir, t) }));\n}\n", "\"use client\";\n\nimport { useState } from \"react\";\nimport { Check, Copy } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport { useText } from \"../text\";\n\nexport function CopyButton({ text, label }: { text: string; label?: string }) {\n const t = useText().exportPanel;\n const [copied, setCopied] = useState(false);\n return (\n <Button\n size=\"xs\"\n variant=\"ghost\"\n onClick={() => {\n // There is no clipboard outside a secure context (plain http): then nothing happens.\n const clipboard = navigator.clipboard as Clipboard | undefined;\n void clipboard?.writeText(text).then(() => {\n setCopied(true);\n setTimeout(() => {\n setCopied(false);\n }, 1500);\n });\n }}\n >\n {copied ? <Check data-icon=\"inline-start\" /> : <Copy data-icon=\"inline-start\" />}\n {copied ? t.copied : (label ?? t.copy)}\n </Button>\n );\n}\n\n/** A command to copy, under its label. */\nexport function Command({ label, text }: { label: string; text: string }) {\n return (\n <div className=\"rounded-md border bg-surface\">\n <div className=\"flex items-center justify-between border-b px-3 py-1\">\n <span className=\"text-xs text-muted-foreground\">{label}</span>\n <CopyButton text={text} />\n </div>\n <pre className=\"overflow-x-auto p-3 font-mono text-xs\">\n <code>{text}</code>\n </pre>\n </div>\n );\n}\n", "\"use client\";\n\nimport { ChevronRight, Download } from \"lucide-react\";\nimport type { Target } from \"@/lib/tool/export-targets\";\nimport { cn } from \"@/lib/utils\";\nimport { useText } from \"../text\";\nimport { Command } from \"./copy-button\";\n\n/** Which target and which file are open: kept by the Export window, so they stay open while it is. */\nexport interface Opened {\n target: string | null;\n setTarget: (dir: string | null) => void;\n file: string | null;\n setFile: (path: string | null) => void;\n}\n\n/** A target's commands and files; a click on a file shows it. */\nfunction TargetDetails({ target, opened }: { target: Target; opened: Opened }) {\n const t = useText().exportPanel;\n const { file: openFile, setFile: setOpenFile } = opened;\n return (\n <div className=\"flex flex-col gap-3 px-4 pb-4\">\n {target.isoloom && <Command label={t.withIsoloom} text={target.isoloom} />}\n {target.run && <Command label={target.isoloom ? t.withTool : t.run} text={target.run} />}\n <ul className=\"font-mono text-xs\">\n {target.files.map((f) => (\n <li key={f.path}>\n <button\n type=\"button\"\n onClick={() => { setOpenFile(openFile === f.path ? null : f.path); }}\n className={cn(\"w-full truncate rounded px-2 py-1 text-left text-muted-foreground hover:bg-muted hover:text-foreground\", openFile === f.path && \"bg-muted text-foreground\")}\n >\n {f.path}\n </button>\n {openFile === f.path && (\n <pre className=\"mt-1 max-h-80 overflow-auto rounded-md border bg-surface p-3\">\n <code>{f.contents}</code>\n </pre>\n )}\n </li>\n ))}\n </ul>\n </div>\n );\n}\n\n/** One target: its name and file count (a click opens it), and its own zip. */\nfunction TargetRow({ target, opened, onDownload, ready }: { target: Target; opened: Opened; onDownload: () => void; ready: boolean }) {\n const t = useText().exportPanel;\n const expanded = opened.target === target.dir;\n const onToggle = () => {\n opened.setTarget(expanded ? null : target.dir);\n };\n return (\n <li>\n <div className=\"flex items-center hover:bg-muted/50\">\n <button type=\"button\" aria-expanded={expanded} onClick={onToggle} className=\"flex min-w-0 flex-1 items-center gap-2 py-3 pl-4 text-left text-sm\">\n <ChevronRight className={cn(\"size-4 text-muted-foreground transition-transform\", expanded && \"rotate-90\")} aria-hidden />\n <span className=\"flex-1 font-medium\">{target.name}</span>\n <span className=\"text-xs text-muted-foreground\">{t.files(target.files.length)}</span>\n </button>\n <button\n type=\"button\"\n onClick={onDownload}\n disabled={!ready}\n title={t.downloadOnly(target.name)}\n aria-label={t.downloadTarget(target.name)}\n className=\"mr-2 grid size-8 shrink-0 place-items-center rounded-md text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-40\"\n >\n <Download className=\"size-4\" />\n </button>\n </div>\n {expanded && <TargetDetails target={target} opened={opened} />}\n </li>\n );\n}\n\n/** Every target the zip holds, one open at a time. */\nexport function TargetList({ targets, ready, opened, onDownloadTarget }: { targets: Target[]; ready: boolean; opened: Opened; onDownloadTarget: (dir: string) => void }) {\n return (\n <ul className=\"divide-y rounded-lg border\">\n {targets.map((g) => (\n <TargetRow key={g.dir} target={g} opened={opened} onDownload={() => { onDownloadTarget(g.dir); }} ready={ready} />\n ))}\n </ul>\n );\n}\n", "\"use client\";\n\nimport { useRef, useState, type PointerEvent, type ReactNode } from \"react\";\nimport { GripHorizontal, X } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport { useText } from \"./text\";\n\nconst MARGIN = 12;\n/** Room left under the top bar (menu, toolbar, export). */\nconst TOP = 72;\n\n/** Dragging a window by its title bar, kept inside the screen. */\nfunction useWindowDrag(width: number, side: \"left\" | \"right\") {\n const ref = useRef<HTMLDivElement>(null);\n // The editor only renders in the browser, so the screen size is known from the start.\n const [pos, setPos] = useState(() => {\n const w = Math.min(width, window.innerWidth - 2 * MARGIN);\n return { x: side === \"left\" ? MARGIN : window.innerWidth - w - MARGIN, y: TOP };\n });\n const drag = useRef<{ dx: number; dy: number } | null>(null);\n const clamp = (x: number, y: number) => {\n const w = ref.current?.offsetWidth ?? width;\n return { x: Math.min(Math.max(MARGIN, x), window.innerWidth - w - MARGIN), y: Math.min(Math.max(MARGIN, y), window.innerHeight - 48) };\n };\n const handlers = {\n onPointerDown: (e: PointerEvent<HTMLDivElement>) => {\n if (e.target instanceof Element && e.target.closest(\"button\")) return;\n drag.current = { dx: e.clientX - pos.x, dy: e.clientY - pos.y };\n e.currentTarget.setPointerCapture(e.pointerId);\n },\n onPointerMove: (e: PointerEvent<HTMLDivElement>) => {\n if (drag.current) setPos(clamp(e.clientX - drag.current.dx, e.clientY - drag.current.dy));\n },\n onPointerUp: () => {\n drag.current = null;\n },\n };\n return { ref, pos, handlers };\n}\n\n/**\n * A window floating over the canvas: drag it by its title bar, close it with the cross. It opens\n * against the left or right edge and stays inside the screen while dragged.\n */\nexport function FloatingWindow({ title, side, width, onClose, children, className }: { title: ReactNode; side: \"left\" | \"right\"; width: number; onClose: () => void; children: ReactNode; className?: string }) {\n const t = useText();\n const { ref, pos, handlers } = useWindowDrag(width, side);\n return (\n <div\n ref={ref}\n role=\"dialog\"\n aria-label={typeof title === \"string\" ? title : undefined}\n style={{ left: pos.x, top: pos.y, width: `min(${String(width)}px, calc(100vw - ${String(2 * MARGIN)}px))` }}\n className={cn(\n \"absolute z-20 flex max-h-[calc(100dvh-96px)] flex-col overflow-hidden rounded-xl border bg-popover text-popover-foreground shadow-[0_8px_30px_-8px_rgb(0_0_0/0.18)]\",\n className,\n )}\n >\n <div {...handlers} className=\"flex cursor-grab touch-none items-center gap-2 border-b px-3 py-2 select-none active:cursor-grabbing\">\n <GripHorizontal className=\"size-4 text-muted-foreground/60\" aria-hidden />\n <span className=\"flex-1 truncate font-heading text-sm font-semibold\">{title}</span>\n <button type=\"button\" onClick={onClose} aria-label={t.windows.close} className=\"grid size-6 place-items-center rounded-md text-muted-foreground hover:bg-muted hover:text-foreground\">\n <X className=\"size-4\" />\n </button>\n </div>\n <div className=\"min-h-0 flex-1 overflow-y-auto\">{children}</div>\n </div>\n );\n}\n", "\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { FolderOpen, History, Trash2 } from \"lucide-react\";\nimport type { Draft } from \"@/lib/tool/model\";\nimport { deleteProject, getProject, getVersion, listProjects, listVersions, type ProjectSummary, type ProjectVersion } from \"@/lib/tool/projects-api\";\nimport type { ProjectRef } from \"@/lib/tool/storage\";\nimport { Button } from \"@/components/ui/button\";\nimport { useText } from \"./text\";\n\nconst when = (iso: string) => new Date(iso).toLocaleString(undefined, { dateStyle: \"medium\", timeStyle: \"short\" });\n\n/** A project: its name (and whether it is the one open), when it was saved, opening and deleting it. */\nfunction ProjectRow({ p, current, onOpen, onDelete }: { p: ProjectSummary; current: ProjectRef | null; onOpen: () => void; onDelete: () => void }) {\n const t = useText().projects;\n return (\n <li className=\"flex items-center gap-2 px-3 py-2\">\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate font-medium\">\n {p.name}\n {current?.id === p.id && <span className=\"ml-1.5 text-xs font-normal text-signal\">{t.open}</span>}\n </p>\n <p className=\"text-xs text-muted-foreground\">{when(p.updatedAt)}</p>\n </div>\n <Button size=\"sm\" variant=\"outline\" onClick={onOpen}>\n <FolderOpen data-icon=\"inline-start\" /> {t.openButton}\n </Button>\n <Button size=\"icon-sm\" variant=\"ghost\" aria-label={t.delete(p.name)} title={t.delete(p.name)} onClick={onDelete}>\n <Trash2 />\n </Button>\n </li>\n );\n}\n\n/** The open project's earlier versions: listing them, and opening one. */\nfunction VersionHistory({ current, versions, setVersions, onOpenVersion }: { current: ProjectRef; versions: ProjectVersion[] | null; setVersions: (v: ProjectVersion[]) => void; onOpenVersion: (draft: Draft) => void }) {\n const t = useText().projects;\n return (\n <div className=\"flex flex-col gap-2\">\n <Button size=\"sm\" variant=\"ghost\" className=\"self-start\" onClick={() => void listVersions(current.id).then(setVersions)}>\n <History data-icon=\"inline-start\" /> {t.history(current.name)}\n </Button>\n {versions &&\n (versions.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">{t.noVersions}</p>\n ) : (\n <ul className=\"flex flex-col gap-1\">\n {versions.map((v) => (\n <li key={v.id} className=\"flex items-center justify-between gap-2 text-xs\">\n <span className=\"text-muted-foreground\">{when(v.savedAt)}</span>\n <Button size=\"xs\" variant=\"outline\" onClick={() => void getVersion(current.id, v.id).then((r) => { onOpenVersion(r.draft); })}>\n {t.restore}\n </Button>\n </li>\n ))}\n </ul>\n ))}\n <p className=\"text-xs text-muted-foreground\">{t.historyHint}</p>\n </div>\n );\n}\n\n/** The user's projects, to open or delete one; and the open project's earlier versions. */\nexport function ProjectsList({ current, onOpen, onOpenVersion, onDeleted }: { current: ProjectRef | null; onOpen: (p: ProjectRef, draft: Draft) => void; onOpenVersion: (draft: Draft) => void; onDeleted: (id: string) => void }) {\n const t = useText().projects;\n const [list, setList] = useState<ProjectSummary[] | null>(null);\n const [versions, setVersions] = useState<ProjectVersion[] | null>(null);\n const [error, setError] = useState<string | null>(null);\n useEffect(() => {\n listProjects().then(setList, (e: unknown) => {\n setError((e as Error).message);\n });\n }, []);\n async function remove(p: ProjectSummary) {\n if (!window.confirm(t.confirmDelete(p.name))) return;\n await deleteProject(p.id);\n setList((l) => l?.filter((x) => x.id !== p.id) ?? null);\n onDeleted(p.id);\n }\n if (error) return <p className=\"text-sm text-destructive\">{t.failed(error)}</p>;\n if (!list) return <p className=\"text-sm text-muted-foreground\">{t.loading}</p>;\n return (\n <div className=\"flex flex-col gap-4 text-sm\">\n {list.length === 0 ? (\n <p className=\"text-muted-foreground\">{t.none}</p>\n ) : (\n <ul className=\"flex flex-col divide-y rounded-lg border\">\n {list.map((p) => (\n <ProjectRow key={p.id} p={p} current={current} onOpen={() => void getProject(p.id).then((full) => { onOpen({ id: full.id, name: full.name }, full.draft); })} onDelete={() => void remove(p)} />\n ))}\n </ul>\n )}\n {current && <VersionHistory current={current} versions={versions} setVersions={setVersions} onOpenVersion={onOpenVersion} />}\n </div>\n );\n}\n", "\"use client\";\n\nimport { Trash2 } from \"lucide-react\";\nimport { isLan, isNote, isSwitch, nodeName, unselected } from \"@/lib/tool/model\";\nimport { setAutoStarts } from \"@/lib/tool/storage\";\nimport { Button } from \"@/components/ui/button\";\nimport { FloatingWindow } from \"../floating-window\";\nimport type { EditorModel } from \"../hooks/use-editor\";\nimport { LabStatus } from \"./lab-status\";\n\n/** Several things selected: what they are, and deleting them all. */\nexport function SelectionWindow({ e }: { e: EditorModel }) {\n const { t, lab } = e;\n const { selectedNodes, selectedEdges, count } = e.selection;\n return (\n <FloatingWindow\n title={t.windows.selected(count)}\n side=\"left\"\n width={280}\n onClose={() => {\n lab.setNodes((ns) => unselected(ns));\n lab.setEdges((es) => unselected(es));\n }}\n >\n <div className=\"flex flex-col gap-3 p-4 text-sm\">\n <p className=\"text-muted-foreground\">{t.windows.selection(selectedNodes.length, selectedEdges.length)}</p>\n {selectedNodes.length > 0 && (\n <ul className=\"flex flex-wrap gap-1.5 font-mono text-xs\">\n {selectedNodes.map((n) => (\n <li key={n.id} className=\"rounded-md border px-1.5 py-0.5\">\n {isNote(n) ? t.canvas.noteName : nodeName(n)}\n </li>\n ))}\n </ul>\n )}\n <Button variant=\"outline\" size=\"sm\" onClick={() => void e.flow.deleteElements({ nodes: selectedNodes.map((n) => ({ id: n.id })), edges: selectedEdges.map((c) => ({ id: c.id })) })}>\n <Trash2 data-icon=\"inline-start\" /> {t.windows.deleteSelection(count)}\n </Button>\n </div>\n </FloatingWindow>\n );\n}\n\n/** The lab at a glance: how many containers, VMs, LANs and cables, and what to fix. */\nexport function StatusWindow({ e }: { e: EditorModel }) {\n const { t, lab, machines, issues } = e;\n const vlans = new Set(lab.nodes.filter(isSwitch).flatMap((sw) => sw.data.vlans.map((v) => v.id)));\n const counts = [\n [t.lab.containers, machines.filter((n) => n.data.kind === \"container\").length],\n [t.lab.vms, machines.filter((n) => n.data.kind === \"vm\").length],\n [t.lab.lans, lab.nodes.filter(isLan).length + vlans.size],\n [t.lab.cables, lab.edges.length],\n ] as const;\n return (\n <FloatingWindow title={t.lab.title} side=\"right\" width={320} onClose={() => { e.setStatusOpen(false); }}>\n <div className=\"flex flex-col gap-4 p-4 text-sm\">\n {/* Equal columns, unless a label (Contenedores) needs more: then it widens, unbroken. */}\n <div className=\"grid grid-cols-[repeat(4,minmax(min-content,1fr))] gap-2 text-center\">\n {counts.map(([label, count]) => (\n <div key={label} className=\"rounded-lg border p-2\">\n <div className=\"font-heading text-lg font-semibold\">{count}</div>\n <div className=\"text-xs text-muted-foreground\">{label}</div>\n </div>\n ))}\n </div>\n {issues.length > 0 ? (\n <div>\n <h3 className=\"mb-2 font-medium\">{t.lab.toFix}</h3>\n <ul className=\"list-disc space-y-1 pl-5 text-muted-foreground\">\n {issues.map((p, i) => (\n <li key={i}>{p}</li>\n ))}\n </ul>\n </div>\n ) : (\n <p className=\"text-success\">{t.lab.valid}</p>\n )}\n <p className=\"text-xs text-muted-foreground\">{t.lab.routing}</p>\n </div>\n </FloatingWindow>\n );\n}\n\n/** What the Run window says the lab is doing. */\nfunction runLine(e: EditorModel): string {\n const t = e.t;\n switch (e.desk.state.run) {\n case \"running\":\n return `${t.run.running} ${t.machineRun.consoleHint}`;\n case \"starting\":\n return t.run.starting;\n case \"stopping\":\n return t.run.stopping;\n case \"stopped\":\n return t.run.stopped;\n }\n}\n\n/** Desktop app: the lab running on this machine, its log, and starting it with the app. */\nexport function RunWindow({ e }: { e: EditorModel }) {\n const { t, desk, lab } = e;\n const { info, run } = desk.state;\n const { autoStart, setAutoStart } = desk.autoStart;\n return (\n <FloatingWindow title={t.run.window} side=\"right\" width={420} onClose={() => { desk.panel.setRunOpen(false); }}>\n <div className=\"flex flex-col gap-3 p-4 text-sm\">\n <p>{runLine(e)}</p>\n {info && !info.docker && <p className=\"rounded-md bg-pastel-yellow p-2.5 text-xs\">{t.run.noDocker}</p>}\n {info && !info.live_capture && <p className=\"text-xs text-muted-foreground\">{t.run.noLiveCapture(info.wireshark, info.labs.replace(/labs$/, \"captures\"))}</p>}\n <label className=\"flex items-start gap-2 text-xs\">\n <input\n type=\"checkbox\"\n className=\"mt-0.5\"\n checked={autoStart}\n onChange={(ev) => {\n setAutoStarts(lab.labName, ev.target.checked);\n setAutoStart(ev.target.checked);\n }}\n />\n <span>\n {t.run.autoStart}\n <span className=\"block text-muted-foreground\">{t.run.autoStartNote}</span>\n </span>\n </label>\n {run === \"running\" && desk.live.live && <LabStatus live={desk.live.live} cut={desk.live.links} />}\n {desk.panel.runLog && <pre className=\"max-h-72 overflow-auto rounded-md border bg-surface p-3 font-mono text-xs whitespace-pre-wrap\">{desk.panel.runLog}</pre>}\n </div>\n </FloatingWindow>\n );\n}\n", "\"use client\";\n\nimport { machineStatus, type LabLive, type MachineLive, type Status, type SuspendedLink } from \"@/lib/tool/desktop\";\nimport { cn } from \"@/lib/utils\";\nimport { useText } from \"../text\";\n\nconst DOT: Record<Status, string> = { up: \"bg-success\", starting: \"bg-warning\", unhealthy: \"bg-destructive\", down: \"bg-muted-foreground/50\" };\n\ntype Port = LabLive[\"ports\"][number];\n\n/** A port of a running machine: its network (and interface), green when up, struck through when down. */\nfunction PortChip({ p, cut }: { p: Port; cut: boolean }) {\n const t = useText().canvas.live;\n const title = p.up === null ? t.portUnknown : p.up ? t.portUp : cut ? t.cable.cut : t.portDown;\n return (\n <span\n title={title}\n className={cn(\"rounded-sm border px-1 font-mono text-[10px]\", p.up === true && \"border-success/40 text-success\", p.up === false && \"border-destructive/40 text-destructive line-through\", p.up === null && \"text-muted-foreground\")}\n >\n {p.network}\n {p.interface ? ` ${p.interface}` : \"\"}\n </span>\n );\n}\n\n/** One machine now: its state (and health), then its ports. */\nfunction MachineLine({ name, l, live, cut }: { name: string; l: MachineLive; live: LabLive; cut: SuspendedLink[] }) {\n const t = useText();\n const status = machineStatus(l);\n return (\n <li className=\"flex flex-col gap-0.5\">\n <span className=\"flex items-center gap-1.5\">\n <span className={cn(\"size-2 shrink-0 rounded-full\", DOT[status])} aria-hidden />\n <span className=\"font-mono font-medium\">{name}</span>\n <span className=\"text-muted-foreground\">\n {t.canvas.live[status]}\n {l.health && status !== \"unhealthy\" ? ` \u00B7 ${l.health}` : \"\"}\n </span>\n </span>\n <span className=\"flex flex-wrap gap-1 pl-3.5\">\n {live.ports\n .filter((p) => p.machine === name)\n .map((p) => (\n <PortChip key={p.network} p={p} cut={cut.some((c) => c.machine === name && c.network === p.network)} />\n ))}\n </span>\n </li>\n );\n}\n\n/** Desktop only: the running lab now, machine by machine, with each one's ports. */\nexport function LabStatus({ live, cut }: { live: LabLive; cut: SuspendedLink[] }) {\n const t = useText();\n const machines = Object.entries(live.machines);\n const up = machines.filter(([, l]) => machineStatus(l) === \"up\").length;\n return (\n <section className=\"flex flex-col gap-2\">\n <h3 className=\"text-xs font-medium text-muted-foreground\">\n {t.run.statusTitle(up, machines.length)} \u00B7 {live.probed ? t.run.probed : t.run.inferred}\n </h3>\n <ul className=\"flex max-h-64 flex-col gap-1 overflow-auto rounded-md border bg-surface p-2 text-xs\">\n {machines.map(([name, l]) => (\n <MachineLine key={name} name={name} l={l} live={live} cut={cut} />\n ))}\n </ul>\n </section>\n );\n}\n", "\"use client\";\n\nimport { Trash2 } from \"lucide-react\";\nimport { machineEnds, networkOfCable } from \"@/lib/tool/cables\";\nimport { isSwitch, unselected, type CableEdge, type LanNode, type MachineNode } from \"@/lib/tool/model\";\nimport { nameById } from \"@/lib/tool/selection\";\nimport { vlanName } from \"@/lib/tool/vlans\";\nimport { cn } from \"@/lib/utils\";\nimport { Button } from \"@/components/ui/button\";\nimport { FloatingWindow } from \"../floating-window\";\nimport type { EditorModel } from \"../hooks/use-editor\";\nimport { ConditionsFields } from \"./conditions-fields\";\nimport { field } from \"./fields\";\nimport { CaptureControl, LinkControl } from \"./link-controls\";\nimport { MachineControls } from \"./machine-controls\";\nimport { MachineInspector } from \"./machine-inspector\";\n\n/** The cables of a machine, as its window lists them: `its port \u2192 the other end's name and port`. */\nfunction cablesOf(e: EditorModel, id: string): string[] {\n const nameOf = (other: string) => nameById(e.lab.nodes, other);\n return e.lab.edges\n .filter((c) => c.source === id || c.target === id)\n .map((c) => (c.source === id ? `${String(c.data?.aPort)} \u2192 ${nameOf(c.target)} ${String(c.data?.bPort)}` : `${String(c.data?.bPort)} \u2192 ${nameOf(c.source)} ${String(c.data?.aPort)}`));\n}\n\n/** A machine's window: the inspector, and (desktop app, lab running) its controls. */\nexport function MachineWindow({ e, node }: { e: EditorModel; node: MachineNode }) {\n const { lab, desk, actions } = e;\n const name = node.data.name;\n const act = desk.actions;\n return (\n <FloatingWindow title={name || e.t.windows.machine} side=\"left\" width={280} onClose={() => { lab.setNodes((ns) => unselected(ns)); }}>\n <div className=\"p-4\">\n <MachineInspector\n node={node}\n cables={cablesOf(e, node.id)}\n onChange={(patch) => { actions.updateMachine(node.id, patch); }}\n onDelete={() => void e.flow.deleteElements({ nodes: [{ id: node.id }] })}\n onSaveDevice={() => { e.devices.saveDevice(node.data); }}\n />\n {e.invoke && desk.state.run === \"running\" && (\n <MachineControls\n state={desk.live.machineStates[name]}\n busy={act.busy}\n onConsole={() => void act.machineConsole(name)}\n onDisplay={() => void act.machineDisplay(name)}\n onAction={(action) => void act.machineAct(name, action)}\n snapshots={desk.live.snapshots.filter((x) => x.machine === name)}\n onSnapshot={(label) => void act.snapshotDo(\"snapshot_take\", { machine: name, label })}\n onUse={(id) => void act.snapshotDo(\"snapshot_use\", { machine: name, id })}\n onDeleteSnapshot={(id) => void act.snapshotDo(\"snapshot_delete\", { id })}\n />\n )}\n </div>\n </FloatingWindow>\n );\n}\n\n/**\n * A LAN's window: how it behaves (its name and block are edited on the canvas itself), and in the\n * desktop app capturing its traffic and suspending its links.\n */\nexport function LanWindow({ e, lan }: { e: EditorModel; lan: LanNode }) {\n const { lab, desk } = e;\n const name = lan.data.name;\n const running = desk.state.run === \"running\";\n const { captures, capture, stopCapture } = desk.captures;\n const cut = desk.live.links.filter((l) => l.network === name).length;\n const onVlan = lab.nodes.some((n) => isSwitch(n) && n.data.vlans.some((v) => vlanName(v.id) === name));\n return (\n <FloatingWindow title={e.t.windows.lan(name)} side=\"left\" width={280} onClose={() => { lab.setNodes((ns) => unselected(ns)); }}>\n <div className=\"flex flex-col gap-4 p-4 text-sm\">\n {onVlan ? <p className=\"text-xs text-muted-foreground\">{e.t.windows.conditions.onVlan}</p> : <ConditionsFields value={lan.data.tc} onChange={(tc) => { e.flow.updateNodeData(lan.id, { tc }); }} />}\n {e.invoke && (\n <>\n <CaptureControl network={name} running={running} capturing={name in captures} file={captures[name]} onStart={() => void capture(name)} onStop={() => void stopCapture(name)} />\n <LinkControl\n running={running}\n busy={desk.actions.busy}\n all\n suspended={cut ? e.t.link.lanSuspended(cut) : null}\n onSuspend={() => void desk.actions.linkAct(name, undefined, \"suspend\")}\n onResume={() => void desk.actions.linkAct(name, undefined, \"resume\")}\n />\n </>\n )}\n </div>\n </FloatingWindow>\n );\n}\n\n/** Desktop app: capturing a cable's traffic, and suspending it (when it has a machine at an end). */\nfunction CableRunControls({ e, edge }: { e: EditorModel; edge: CableEdge }) {\n const { desk, lab } = e;\n const network = networkOfCable(edge.id, lab.nodes, lab.edges);\n if (!network) return null;\n const running = desk.state.run === \"running\";\n const { captures, capture, stopCapture } = desk.captures;\n const ends = machineEnds(edge, lab.nodes);\n const cut = desk.live.links.some((l) => l.network === network && ends.includes(l.machine));\n return (\n <>\n <CaptureControl network={network} running={running} capturing={network in captures} file={captures[network]} onStart={() => void capture(network)} onStop={() => void stopCapture(network)} />\n {ends.length > 0 && (\n <LinkControl\n running={running}\n busy={desk.actions.busy}\n suspended={cut ? e.t.link.cableSuspended : null}\n onSuspend={() => void desk.actions.linkAct(network, ends, \"suspend\")}\n onResume={() => void desk.actions.linkAct(network, ends, \"resume\")}\n />\n )}\n </>\n );\n}\n\n/** A cable's window: the port at each end, how it behaves, and removing it. */\nexport function CableWindow({ e, edge, data }: { e: EditorModel; edge: CableEdge; data: NonNullable<CableEdge[\"data\"]> }) {\n const { lab, index, t } = e;\n const nameOf = (id: string) => nameById(lab.nodes, id);\n const ends = [\n [\"aPort\", edge.source],\n [\"bPort\", edge.target],\n ] as const;\n return (\n <FloatingWindow title={t.windows.cable(nameOf(edge.source), nameOf(edge.target))} side=\"left\" width={280} onClose={() => { lab.setEdges((es) => unselected(es)); }}>\n <div className=\"flex flex-col gap-4 p-4 text-sm\">\n {ends.map(([key, nodeId]) => (\n <label key={key} className=\"flex flex-col gap-1\">\n <span className=\"text-muted-foreground\">{t.windows.portOn(nameOf(nodeId))}</span>\n <input className={cn(field, \"font-mono\")} value={data[key]} onChange={(ev) => { e.actions.updateCable(edge.id, { [key]: ev.target.value }); }} />\n </label>\n ))}\n <p className=\"text-xs text-muted-foreground\">{t.windows.cableNote}</p>\n {[edge.source, edge.target].some((id) => index.lanIds.has(id) || index.switchIds.has(id)) ? (\n <p className=\"text-xs text-muted-foreground\">{t.windows.conditions.onLan}</p>\n ) : (\n <ConditionsFields value={data.tc} onChange={(tc) => { e.actions.updateCable(edge.id, { tc }); }} />\n )}\n {e.invoke && <CableRunControls e={e} edge={edge} />}\n <Button variant=\"outline\" size=\"sm\" onClick={() => void e.flow.deleteElements({ edges: [{ id: edge.id }] })}>\n <Trash2 data-icon=\"inline-start\" /> {t.windows.removeCable}\n </Button>\n </div>\n </FloatingWindow>\n );\n}\n", "/** A text field in the editor's windows. */\nexport const field =\n \"h-8 w-full rounded-md border border-input bg-background px-2 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring\";\n\n/** A multi-line field (provisioning steps, an appliance's configuration). */\nexport const area = \"w-full rounded-md border border-input bg-background px-2 py-1.5 font-mono text-xs outline-none focus-visible:ring-2 focus-visible:ring-ring\";\n", "\"use client\";\n\nimport { withCondition } from \"@/lib/tool/conditions\";\nimport type { LinkConditions } from \"@/lib/tool/model\";\nimport { cn } from \"@/lib/utils\";\nimport { useText } from \"../text\";\nimport { field } from \"./fields\";\n\n/** How a cable or a LAN behaves: four optional numbers (empty: none). */\nexport function ConditionsFields({ value, onChange }: { value: LinkConditions | undefined; onChange: (tc: LinkConditions | undefined) => void }) {\n const t = useText().windows.conditions;\n const fields: [keyof LinkConditions, string, number][] = [\n [\"delay\", t.delay, 1],\n [\"jitter\", t.jitter, 1],\n [\"loss\", t.loss, 0.1],\n [\"rate\", t.rate, 1],\n ];\n return (\n <fieldset className=\"flex flex-col gap-2\">\n <legend className=\"mb-1 text-muted-foreground\">{t.title}</legend>\n <div className=\"grid grid-cols-2 gap-2\">\n {fields.map(([key, label, step]) => (\n <label key={key} className=\"flex flex-col gap-1\">\n <span className=\"text-xs text-muted-foreground\">{label}</span>\n <input\n type=\"number\"\n min={0}\n step={step}\n inputMode=\"decimal\"\n className={cn(field, \"font-mono\")}\n value={value?.[key] ?? \"\"}\n disabled={key === \"jitter\" && !value?.delay}\n onChange={(e) => {\n onChange(withCondition(value, key, e.target.value));\n }}\n />\n </label>\n ))}\n </div>\n <p className=\"text-xs text-muted-foreground\">{t.hint}</p>\n </fieldset>\n );\n}\n", "\"use client\";\n\nimport { Plug, Radio, Square, Unplug } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport { useText } from \"../text\";\n\n/** Desktop only: capture a LAN's or a cable's traffic while the lab runs. */\nexport function CaptureControl({ network, running, file, capturing, onStart, onStop }: { network: string; running: boolean; file: string | null | undefined; capturing: boolean; onStart: () => void; onStop: () => void }) {\n const t = useText().capture;\n return (\n <div className=\"flex flex-col gap-1.5 rounded-lg bg-pastel-violet p-3\">\n {capturing ? (\n <>\n <p className=\"flex items-center gap-1.5 font-medium\">\n <span className=\"size-2 animate-pulse rounded-full bg-destructive\" aria-hidden /> {t.capturing(network)}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {file ? (\n <>\n {t.writingTo} <span className=\"font-mono break-all\">{file}</span>\n </>\n ) : (\n t.live\n )}\n </p>\n <Button size=\"sm\" variant=\"outline\" onClick={onStop}>\n <Square data-icon=\"inline-start\" /> {t.stop}\n </Button>\n </>\n ) : (\n <>\n <Button size=\"sm\" onClick={onStart} disabled={!running}>\n <Radio data-icon=\"inline-start\" /> {t.start}\n </Button>\n {!running && <p className=\"text-xs text-muted-foreground\">{t.runFirst}</p>}\n </>\n )}\n </div>\n );\n}\n\n/**\n * Desktop only: suspend a link while the lab runs, as GNS3 does: a cable's ends (their ports,\n * down) or, with `all`, every link of a LAN. `suspended` says so when it is.\n */\nexport function LinkControl({ running, busy, all = false, suspended, onSuspend, onResume }: { running: boolean; busy: boolean; all?: boolean; suspended: string | null; onSuspend: () => void; onResume: () => void }) {\n const t = useText().link;\n return (\n <div className=\"flex flex-col gap-1.5 rounded-lg bg-pastel-violet p-3\">\n {suspended ? (\n <>\n <p className=\"flex items-center gap-1.5 font-medium\">\n <Unplug className=\"size-4\" aria-hidden /> {suspended}\n </p>\n <Button size=\"sm\" variant=\"outline\" onClick={onResume} disabled={busy}>\n <Plug data-icon=\"inline-start\" /> {all ? t.resumeAll : t.resume}\n </Button>\n </>\n ) : (\n <>\n <Button size=\"sm\" variant=\"outline\" onClick={onSuspend} disabled={!running || busy}>\n <Unplug data-icon=\"inline-start\" /> {all ? t.suspendAll : t.suspend}\n </Button>\n {!running && <p className=\"text-xs text-muted-foreground\">{t.runFirst}</p>}\n </>\n )}\n </div>\n );\n}\n", "\"use client\";\n\nimport { Camera, Monitor, Play, RotateCw, Square, SquareTerminal, Trash2 } from \"lucide-react\";\nimport type { Snapshot } from \"@/lib/tool/desktop\";\nimport { Button } from \"@/components/ui/button\";\nimport type { MachineAction } from \"../hooks/use-machine-actions\";\nimport { useText } from \"../text\";\n\ninterface Props {\n state: string | undefined;\n busy: boolean;\n onConsole: () => void;\n onDisplay: () => void;\n onAction: (action: MachineAction) => void;\n snapshots: Snapshot[];\n onSnapshot: (label: string) => void;\n onUse: (id: string | null) => void;\n onDeleteSnapshot: (id: string) => void;\n}\n\n/** A console, its screen, and starting, restarting or stopping it. */\nfunction RunButtons({ state, busy, onConsole, onDisplay, onAction }: Pick<Props, \"state\" | \"busy\" | \"onConsole\" | \"onDisplay\" | \"onAction\">) {\n const t = useText().machineRun;\n const running = state === \"running\";\n return (\n <div className=\"flex flex-wrap gap-2\">\n <Button size=\"sm\" variant=\"outline\" disabled={!running} onClick={onConsole}>\n <SquareTerminal data-icon=\"inline-start\" /> {t.console}\n </Button>\n <Button size=\"sm\" variant=\"outline\" disabled={!running} onClick={onDisplay} title={t.displayTitle}>\n <Monitor data-icon=\"inline-start\" /> {t.display}\n </Button>\n {running ? (\n <>\n <Button size=\"sm\" variant=\"outline\" disabled={busy} onClick={() => { onAction(\"restart\"); }}>\n <RotateCw data-icon=\"inline-start\" /> {t.restart}\n </Button>\n <Button size=\"sm\" variant=\"outline\" disabled={busy} onClick={() => { onAction(\"stop\"); }}>\n <Square data-icon=\"inline-start\" /> {t.stop}\n </Button>\n </>\n ) : (\n <Button size=\"sm\" variant=\"outline\" disabled={busy || !state} onClick={() => { onAction(\"start\"); }}>\n <Play data-icon=\"inline-start\" /> {t.start}\n </Button>\n )}\n </div>\n );\n}\n\nconst when = (created: number) => new Date(created * 1000).toLocaleString(undefined, { dateStyle: \"short\", timeStyle: \"short\" });\n\n/** The machine's snapshots, newest first: restore one, delete one, or go back to its own image. */\nfunction SnapshotList({ snapshots, busy, onUse, onDeleteSnapshot }: Pick<Props, \"snapshots\" | \"busy\" | \"onUse\" | \"onDeleteSnapshot\">) {\n const t = useText().machineRun;\n if (snapshots.length === 0) return <p className=\"text-xs text-muted-foreground\">{t.noSnapshots}</p>;\n return (\n <ul className=\"flex flex-col gap-1 text-xs\">\n {snapshots\n .slice()\n .reverse()\n .map((x) => (\n <li key={x.id} className=\"flex items-center gap-1.5\">\n <span className=\"min-w-0 flex-1 truncate\" title={x.image}>\n {x.label} <span className=\"text-muted-foreground\">\u00B7 {when(x.created)}</span>\n </span>\n {x.in_use ? (\n <span className=\"text-signal\">{t.inUse}</span>\n ) : (\n <Button size=\"xs\" variant=\"ghost\" disabled={busy} onClick={() => { onUse(x.id); }}>\n {t.restore}\n </Button>\n )}\n <Button size=\"icon-xs\" variant=\"ghost\" disabled={busy || x.in_use} aria-label={t.deleteSnapshot(x.label)} title={t.deleteSnapshot(x.label)} onClick={() => { onDeleteSnapshot(x.id); }}>\n <Trash2 />\n </Button>\n </li>\n ))}\n </ul>\n );\n}\n\n/** In the desktop app, for a machine of the running lab: its state, its controls, its snapshots. */\nexport function MachineControls(p: Props) {\n const t = useText().machineRun;\n const running = p.state === \"running\";\n return (\n <div className=\"mt-4 flex flex-col gap-2 border-t pt-3 text-sm\">\n <p className=\"text-xs text-muted-foreground\">{running ? t.running : p.state ? t.stopped : t.unknown}</p>\n <RunButtons state={p.state} busy={p.busy} onConsole={p.onConsole} onDisplay={p.onDisplay} onAction={p.onAction} />\n <div className=\"mt-2 flex flex-col gap-1.5\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-muted-foreground\">{t.snapshots}</span>\n <Button\n size=\"xs\"\n variant=\"outline\"\n disabled={p.busy || !running}\n title={t.snapshotHint}\n onClick={() => {\n const label = window.prompt(t.snapshotPrompt, \"\");\n if (label !== null) p.onSnapshot(label);\n }}\n >\n <Camera data-icon=\"inline-start\" /> {t.takeSnapshot}\n </Button>\n </div>\n <SnapshotList snapshots={p.snapshots} busy={p.busy} onUse={p.onUse} onDeleteSnapshot={p.onDeleteSnapshot} />\n {p.snapshots.some((x) => x.in_use) && (\n <Button size=\"xs\" variant=\"ghost\" className=\"self-start\" disabled={p.busy} onClick={() => { p.onUse(null); }}>\n {t.ownImage}\n </Button>\n )}\n </div>\n </div>\n );\n}\n", "\"use client\";\n\nimport { BookmarkPlus, Trash2 } from \"lucide-react\";\nimport { cleanName, type MachineData, type MachineNode } from \"@/lib/tool/model\";\nimport { runAs } from \"@/lib/tool/presets\";\nimport { Button } from \"@/components/ui/button\";\nimport { useText } from \"../text\";\nimport { field } from \"./fields\";\nimport { ContainerFields, ServiceFields, VmFields } from \"./runs-fields\";\n\ntype Change = (patch: Partial<MachineData>) => void;\n\n/** Its name, and what it runs as: an automatic router (a router's only), a container or a VM. */\nfunction NameAndKind({ m, onChange }: { m: MachineData; onChange: Change }) {\n const t = useText().inspector;\n return (\n <>\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-muted-foreground\">{t.name}</span>\n <input className={field} value={m.name} onChange={(e) => { onChange({ name: cleanName(e.target.value) }); }} />\n </label>\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-muted-foreground\">{t.runsAs}</span>\n <select\n className={field}\n value={m.kind}\n onChange={(e) => {\n const patch = runAs(m, e.target.value);\n if (patch) onChange(patch);\n }}\n >\n {m.icon === \"router\" && <option value=\"router\">{t.automaticRouter}</option>}\n <option value=\"container\">{t.container}</option>\n <option value=\"vm\">{t.vm}</option>\n </select>\n </label>\n </>\n );\n}\n\n/** The machine's cables, as `its port \u2192 the other end's name and port`. */\nfunction CableList({ cables }: { cables: string[] }) {\n const t = useText().inspector;\n return (\n <div>\n <span className=\"text-muted-foreground\">{t.cables}</span>\n {cables.length ? (\n <ul className=\"mt-1 space-y-0.5 font-mono text-xs\">\n {cables.map((c, i) => (\n <li key={i}>{c}</li>\n ))}\n </ul>\n ) : (\n <p className=\"mt-1 text-xs text-muted-foreground\">{t.noCables}</p>\n )}\n </div>\n );\n}\n\n/** A machine's window: its name and kind, what it runs, its services, its cables. */\nexport function MachineInspector({ node, cables, onChange, onDelete, onSaveDevice }: { node: MachineNode; cables: string[]; onChange: Change; onDelete: () => void; onSaveDevice: () => void }) {\n const t = useText().inspector;\n const m = node.data;\n return (\n <div className=\"flex flex-col gap-4 text-sm\">\n <NameAndKind m={m} onChange={onChange} />\n {m.kind === \"router\" && <p className=\"text-xs text-muted-foreground\">{t.routerNote}</p>}\n {m.kind === \"container\" && <ContainerFields m={m} onChange={onChange} />}\n {m.kind !== \"router\" && m.kind !== \"container\" && <VmFields m={m} onChange={onChange} />}\n {/* An automatic router is not a machine, nor is an appliance one to land on: no services. */}\n {m.kind !== \"router\" && !m.appliance && <ServiceFields m={m} onChange={onChange} />}\n <CableList cables={cables} />\n <div className=\"flex flex-wrap gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={onSaveDevice} title={t.saveTitle}>\n <BookmarkPlus data-icon=\"inline-start\" /> {t.save}\n </Button>\n <Button variant=\"outline\" size=\"sm\" onClick={onDelete}>\n <Trash2 data-icon=\"inline-start\" /> {t.remove}\n </Button>\n </div>\n </div>\n );\n}\n", "\"use client\";\n\nimport { APPLIANCES, idleByDefault, type MachineData } from \"@/lib/tool/model\";\nimport { OS_CHOICES } from \"@/lib/tool/os\";\nimport { cn } from \"@/lib/utils\";\nimport { useText } from \"../text\";\nimport { area, field } from \"./fields\";\n\ntype Change = (patch: Partial<MachineData>) => void;\n\n/** A Cisco OS in its container: which one, what it needs, and its own IOS configuration. */\nfunction ApplianceFields({ m, onChange }: { m: MachineData; onChange: Change }) {\n const t = useText().inspector;\n return (\n <>\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-muted-foreground\">{t.ciscoOs}</span>\n <select\n className={field}\n value={m.appliance}\n onChange={(e) => {\n const a = APPLIANCES.find((x) => x.id === e.target.value);\n if (a) onChange({ appliance: a.id, image: a.image });\n }}\n >\n {APPLIANCES.map((a) => (\n <option key={a.id} value={a.id}>\n {a.label}\n </option>\n ))}\n </select>\n {APPLIANCES.find((a) => a.id === m.appliance)?.kvm && <span className=\"text-xs text-muted-foreground\">{t.needsKvm}</span>}\n {m.appliance === \"cisco-dynamips\" && <span className=\"text-xs text-muted-foreground\">{t.dynamipsFirmware(m.name)}</span>}\n </label>\n <p className=\"text-xs text-muted-foreground\">\n {t.applianceNote}{\" \"}\n <a className=\"underline\" href=\"https://github.com/srl-labs/vrnetlab/tree/master/cisco/iol\" target=\"_blank\" rel=\"noreferrer\">\n vrnetlab\n </a>\n </p>\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-muted-foreground\">{t.iosConfig}</span>\n <textarea\n className={`min-h-28 ${area}`}\n placeholder={\"router ospf 1\\n network 10.0.0.0 0.255.255.255 area 0\"}\n value={m.config ?? \"\"}\n onChange={(e) => {\n onChange({ config: e.target.value });\n }}\n spellCheck={false}\n />\n <span className=\"text-xs text-muted-foreground\">{t.iosConfigHint}</span>\n </label>\n </>\n );\n}\n\n/** A container: its image (none to type for Dynamips), and a Cisco OS's fields or whether it idles. */\nexport function ContainerFields({ m, onChange }: { m: MachineData; onChange: Change }) {\n const t = useText().inspector;\n return (\n <>\n {m.appliance !== \"cisco-dynamips\" && (\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-muted-foreground\">{t.image}</span>\n <input className={cn(field, \"font-mono\")} value={m.image} onChange={(e) => { onChange({ image: e.target.value }); }} />\n </label>\n )}\n {m.appliance ? (\n <ApplianceFields m={m} onChange={onChange} />\n ) : (\n <label className=\"flex items-start gap-2\">\n <input type=\"checkbox\" className=\"mt-0.5\" checked={m.idle ?? idleByDefault(m.image)} onChange={(e) => { onChange({ idle: e.target.checked }); }} />\n <span>\n {t.keepRunning}\n <span className=\"block text-xs text-muted-foreground\">{t.keepRunningHint}</span>\n </span>\n </label>\n )}\n </>\n );\n}\n\n/** A VM: its OS and its provisioning steps. */\nexport function VmFields({ m, onChange }: { m: MachineData; onChange: Change }) {\n const t = useText().inspector;\n return (\n <>\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-muted-foreground\">{t.os}</span>\n <select className={field} value={m.os} onChange={(e) => { onChange({ os: e.target.value }); }}>\n {OS_CHOICES.map((os) => (\n <option key={os} value={os}>\n {os}\n </option>\n ))}\n </select>\n </label>\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-muted-foreground\">{t.provision}</span>\n <textarea\n className={`min-h-16 ${area}`}\n placeholder={m.os.startsWith(\"windows\") ? `provision/${m.name}.ps1` : `provision/${m.name}.sh`}\n value={m.provision}\n onChange={(e) => { onChange({ provision: e.target.value }); }}\n />\n </label>\n </>\n );\n}\n\n/** A machine's services and whether the user lands on it (not an automatic router, nor an appliance). */\nexport function ServiceFields({ m, onChange }: { m: MachineData; onChange: Change }) {\n const t = useText().inspector;\n return (\n <>\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-muted-foreground\">{t.ports}</span>\n <input className={field} placeholder=\"80, 443/https, 53/udp\" value={m.ports} onChange={(e) => { onChange({ ports: e.target.value }); }} />\n </label>\n <label className=\"flex items-center gap-2\">\n <input type=\"checkbox\" checked={m.access} onChange={(e) => { onChange({ access: e.target.checked }); }} />\n {t.access}\n </label>\n </>\n );\n}\n", "\"use client\";\n\nimport { cleanName } from \"@/lib/tool/model\";\nimport { ExportPanel } from \"../export/export-panel\";\nimport { FloatingWindow } from \"../floating-window\";\nimport type { EditorModel } from \"../hooks/use-editor\";\nimport { ProjectsList } from \"../projects-list\";\nimport { RunWindow, SelectionWindow, StatusWindow } from \"./lab-windows\";\nimport { CableWindow, LanWindow, MachineWindow } from \"./selected-windows\";\n\n/** The user's projects (signed in): open one, or one of its earlier versions. */\nfunction ProjectsWindow({ e }: { e: EditorModel }) {\n const { projects } = e;\n return (\n <FloatingWindow title={e.t.projects.windowTitle} side=\"left\" width={340} onClose={() => { projects.setProjectsOpen(false); }}>\n <div className=\"p-4\">\n <ProjectsList\n current={projects.proj.project}\n onOpen={(p, d) => {\n projects.openProject(p, d);\n projects.setProjectsOpen(false);\n }}\n onOpenVersion={(d) => { projects.openDraft(d); }}\n onDeleted={(id) => {\n if (projects.proj.project?.id === id) projects.proj.detach();\n }}\n />\n </div>\n </FloatingWindow>\n );\n}\n\n/** Export: the lab's name, its zip and isoloom.yml, and where it runs. */\nfunction ExportWindow({ e }: { e: EditorModel }) {\n const { plan, downloads, lab } = e;\n return (\n <FloatingWindow title={e.t.export} side=\"right\" width={420} onClose={() => { e.setExportOpen(false); }}>\n {downloads.downloadError && (\n <p role=\"alert\" className=\"px-4 pt-4 text-sm text-destructive\">\n {downloads.downloadError}\n </p>\n )}\n <ExportPanel\n labName={lab.labName}\n onLabNameChange={(n) => { lab.setLabName(cleanName(n)); }}\n mixed={e.mixed}\n spec={plan?.isoloom_yml ?? null}\n files={plan?.ok ? plan.files : []}\n issues={e.issues}\n onDownloadAll={downloads.downloadAll}\n onDownloadSpec={downloads.downloadSpec}\n onDownloadTarget={downloads.downloadTarget}\n />\n </FloatingWindow>\n );\n}\n\n/** The windows floating over the canvas: what is selected, projects, the lab's status, Run, Export. */\nexport function EditorWindows({ e }: { e: EditorModel }) {\n const { selection, empty } = e;\n return (\n <>\n {selection.machine && <MachineWindow key={`m-${selection.machine.id}`} e={e} node={selection.machine} />}\n {selection.lan && <LanWindow key={`l-${selection.lan.id}`} e={e} lan={selection.lan} />}\n {selection.edge?.data && <CableWindow key={`c-${selection.edge.id}`} e={e} edge={selection.edge} data={selection.edge.data} />}\n {e.projects.projectsOpen && <ProjectsWindow e={e} />}\n {selection.count > 1 && <SelectionWindow e={e} />}\n {e.statusOpen && !empty && <StatusWindow e={e} />}\n {e.invoke && e.desk.panel.runOpen && <RunWindow e={e} />}\n {e.exportOpen && !empty && <ExportWindow e={e} />}\n </>\n );\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["useRef", "lan", "machine", "lan", "machine", "lan", "machine", "lan", "machine", "createContext", "useContext", "jsx", "createContext", "useContext", "createContext", "useContext", "createContext", "useContext", "jsx", "jsxs", "useEffect", "jsx", "jsxs", "Fragment", "jsx", "jsxs", "useEffect", "center", "lan", "area", "useContext", "Unplug", "createContext", "createContext", "useContext", "Fragment", "jsx", "createContext", "useContext", "Fragment", "jsx", "jsxs", "Unplug", "useContext", "useContext", "useMemo", "Position", "jsx", "Fragment", "jsx", "jsxs", "Position", "useContext", "lan", "useMemo", "useContext", "useMemo", "Handle", "Position", "useReactFlow", "Monitor", "jsx", "jsxs", "Monitor", "useContext", "useReactFlow", "base", "Fragment", "jsx", "jsxs", "useReactFlow", "useContext", "runs", "useContext", "useMemo", "Handle", "Position", "useReactFlow", "Router", "Fragment", "jsx", "jsxs", "useContext", "jsx", "useContext", "useContext", "useEffect", "useContext", "useEffect", "jsx", "jsxs", "useContext", "Handle", "Position", "useReactFlow", "useMemo", "Router", "Fragment", "jsx", "jsxs", "Handle", "Position", "useReactFlow", "useContext", "useMemo", "useMemo", "useState", "NodeResizer", "Position", "useReactFlow", "Square", "jsx", "jsxs", "useReactFlow", "Square", "Position", "useState", "useMemo", "NodeResizer", "useContext", "useMemo", "Handle", "Position", "useReactFlow", "jsx", "jsxs", "useContext", "Handle", "Position", "useReactFlow", "useMemo", "jsx", "jsxs", "useMemo", "useState", "useReactFlow", "useTheme", "lan", "machine", "lan", "useMemo", "center", "preset", "lan", "preset", "lan", "useMemo", "es", "useState", "useCallback", "useEffect", "useRef", "useCallback", "useEffect", "useRef", "useState", "useRef", "useCallback", "es", "useEffect", "useState", "useCallback", "useEffect", "useState", "useState", "useCallback", "useEffect", "useEffect", "useState", "useState", "useEffect", "useEffect", "useMemo", "useState", "useState", "useEffect", "useMemo", "useState", "useEffect", "useMemo", "useState", "useState", "useEffect", "useMemo", "useEffect", "useState", "useState", "useEffect", "useCallback", "base", "area", "lan", "LAN_W", "LAN_H", "kindOf", "base", "lan", "useCallback", "es", "useEffect", "current", "useEffect", "useRef", "lan", "useRef", "useState", "machine", "preset", "center", "useEffect", "useEffectEvent", "useMemo", "useState", "saveProject", "useCallback", "useEffect", "useMemo", "useRef", "useState", "useRef", "useMemo", "useEffect", "useState", "useCallback", "saveProject", "useEffect", "useEffectEvent", "useEffectEvent", "useEffect", "useState", "useMemo", "useEffectEvent", "useEffect", "useEffect", "useState", "useEffect", "useState", "useState", "useEffect", "useAddresses", "useState", "useMemo", "useTheme", "useReactFlow", "LayoutTemplate", "X", "jsx", "Fragment", "jsx", "jsxs", "LayoutTemplate", "X", "Check", "X", "jsx", "jsxs", "current", "Check", "X", "jsx", "jsxs", "Play", "Square", "jsx", "jsxs", "Square", "Play", "useState", "CircleAlert", "Download", "useState", "Check", "jsx", "jsxs", "useState", "Check", "Download", "jsx", "jsxs", "Download", "jsx", "jsxs", "CircleAlert", "useState", "Download", "useRef", "useState", "X", "jsx", "jsxs", "useRef", "useState", "X", "useEffect", "useState", "FolderOpen", "Trash2", "jsx", "jsxs", "current", "FolderOpen", "Trash2", "useState", "useEffect", "Trash2", "jsx", "jsxs", "jsx", "jsxs", "es", "Trash2", "Trash2", "jsx", "jsxs", "Plug", "Radio", "Square", "Unplug", "Fragment", "jsx", "jsxs", "Square", "Radio", "Unplug", "Plug", "Monitor", "Play", "RotateCw", "Square", "SquareTerminal", "Trash2", "Fragment", "jsx", "jsxs", "SquareTerminal", "Monitor", "RotateCw", "Square", "Play", "when", "Trash2", "Trash2", "Fragment", "jsx", "jsxs", "Fragment", "jsx", "jsxs", "Trash2", "Fragment", "jsx", "jsxs", "lan", "es", "Trash2", "Fragment", "jsx", "jsxs", "jsx", "jsxs", "useRef"]
7
+ }