@matter-server/dashboard 0.6.2 → 0.6.3

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 (52) hide show
  1. package/dist/esm/pages/matter-network-view.d.ts +15 -0
  2. package/dist/esm/pages/matter-network-view.d.ts.map +1 -1
  3. package/dist/esm/pages/matter-network-view.js +171 -1
  4. package/dist/esm/pages/matter-network-view.js.map +1 -1
  5. package/dist/esm/pages/network/base-network-graph.d.ts +4 -0
  6. package/dist/esm/pages/network/base-network-graph.d.ts.map +1 -1
  7. package/dist/esm/pages/network/base-network-graph.js +9 -0
  8. package/dist/esm/pages/network/base-network-graph.js.map +1 -1
  9. package/dist/esm/pages/network/border-router-store.d.ts +20 -0
  10. package/dist/esm/pages/network/border-router-store.d.ts.map +1 -0
  11. package/dist/esm/pages/network/border-router-store.js +29 -0
  12. package/dist/esm/pages/network/border-router-store.js.map +6 -0
  13. package/dist/esm/pages/network/network-details.d.ts +40 -12
  14. package/dist/esm/pages/network/network-details.d.ts.map +1 -1
  15. package/dist/esm/pages/network/network-details.js +440 -112
  16. package/dist/esm/pages/network/network-details.js.map +1 -1
  17. package/dist/esm/pages/network/network-types.d.ts +76 -0
  18. package/dist/esm/pages/network/network-types.d.ts.map +1 -1
  19. package/dist/esm/pages/network/network-types.js.map +1 -1
  20. package/dist/esm/pages/network/network-utils.d.ts +89 -22
  21. package/dist/esm/pages/network/network-utils.d.ts.map +1 -1
  22. package/dist/esm/pages/network/network-utils.js +233 -95
  23. package/dist/esm/pages/network/network-utils.js.map +1 -1
  24. package/dist/esm/pages/network/thread-graph.d.ts +68 -9
  25. package/dist/esm/pages/network/thread-graph.d.ts.map +1 -1
  26. package/dist/esm/pages/network/thread-graph.js +388 -50
  27. package/dist/esm/pages/network/thread-graph.js.map +2 -2
  28. package/dist/esm/util/device-icons.d.ts +6 -0
  29. package/dist/esm/util/device-icons.d.ts.map +1 -1
  30. package/dist/esm/util/device-icons.js +6 -0
  31. package/dist/esm/util/device-icons.js.map +1 -1
  32. package/dist/web/js/{attribute-write-dialog-g4B6BoRt.js → attribute-write-dialog-DlMTUiLK.js} +1 -1
  33. package/dist/web/js/{command-invoke-dialog-D6G704VK.js → command-invoke-dialog-DO3IyFcm.js} +1 -1
  34. package/dist/web/js/{commission-node-dialog-Bg3oo5ub.js → commission-node-dialog-CMSvCm0i.js} +4 -4
  35. package/dist/web/js/{commission-node-existing-DO3g1aQJ.js → commission-node-existing-D08jghFu.js} +2 -2
  36. package/dist/web/js/{commission-node-thread-DM432aH1.js → commission-node-thread-D5waY758.js} +2 -2
  37. package/dist/web/js/{commission-node-wifi-Bx40FXij.js → commission-node-wifi-ClBlCFTZ.js} +2 -2
  38. package/dist/web/js/{dialog-box-DjyfULWB.js → dialog-box-D9vS2SmP.js} +1 -1
  39. package/dist/web/js/{fire_event-BstgNPuh.js → fire_event-BPhROjTC.js} +1 -1
  40. package/dist/web/js/main.js +1 -1
  41. package/dist/web/js/{matter-dashboard-app-Cj88TtbZ.js → matter-dashboard-app-C9zTE5uH.js} +1359 -302
  42. package/dist/web/js/{node-binding-dialog-9yy2LE3_.js → node-binding-dialog-B5p-gbim.js} +1 -1
  43. package/dist/web/js/{settings-dialog-Cs2xMsXb.js → settings-dialog-BMFhom0W.js} +1 -1
  44. package/package.json +4 -4
  45. package/src/pages/matter-network-view.ts +185 -1
  46. package/src/pages/network/base-network-graph.ts +10 -0
  47. package/src/pages/network/border-router-store.ts +38 -0
  48. package/src/pages/network/network-details.ts +535 -140
  49. package/src/pages/network/network-types.ts +76 -0
  50. package/src/pages/network/network-utils.ts +390 -171
  51. package/src/pages/network/thread-graph.ts +532 -73
  52. package/src/util/device-icons.ts +13 -0
@@ -234,7 +234,7 @@ function c$4({
234
234
  }
235
235
 
236
236
  // Material Design Icons v7.4.47
237
- var mdiAccessPoint="M4.93,4.93C3.12,6.74 2,9.24 2,12C2,14.76 3.12,17.26 4.93,19.07L6.34,17.66C4.89,16.22 4,14.22 4,12C4,9.79 4.89,7.78 6.34,6.34L4.93,4.93M19.07,4.93L17.66,6.34C19.11,7.78 20,9.79 20,12C20,14.22 19.11,16.22 17.66,17.66L19.07,19.07C20.88,17.26 22,14.76 22,12C22,9.24 20.88,6.74 19.07,4.93M7.76,7.76C6.67,8.85 6,10.35 6,12C6,13.65 6.67,15.15 7.76,16.24L9.17,14.83C8.45,14.11 8,13.11 8,12C8,10.89 8.45,9.89 9.17,9.17L7.76,7.76M16.24,7.76L14.83,9.17C15.55,9.89 16,10.89 16,12C16,13.11 15.55,14.11 14.83,14.83L16.24,16.24C17.33,15.15 18,13.65 18,12C18,10.35 17.33,8.85 16.24,7.76M12,10A2,2 0 0,0 10,12A2,2 0 0,0 12,14A2,2 0 0,0 14,12A2,2 0 0,0 12,10Z";var mdiAirConditioner="M6.59,0.66C8.93,-1.15 11.47,1.06 12.04,4.5C12.47,4.5 12.89,4.62 13.27,4.84C13.79,4.24 14.25,3.42 14.07,2.5C13.65,0.35 16.06,-1.39 18.35,1.58C20.16,3.92 17.95,6.46 14.5,7.03C14.5,7.46 14.39,7.89 14.16,8.27C14.76,8.78 15.58,9.24 16.5,9.06C18.63,8.64 20.38,11.04 17.41,13.34C15.07,15.15 12.53,12.94 11.96,9.5C11.53,9.5 11.11,9.37 10.74,9.15C10.22,9.75 9.75,10.58 9.93,11.5C10.35,13.64 7.94,15.39 5.65,12.42C3.83,10.07 6.05,7.53 9.5,6.97C9.5,6.54 9.63,6.12 9.85,5.74C9.25,5.23 8.43,4.76 7.5,4.94C5.37,5.36 3.62,2.96 6.59,0.66M5,16H7A2,2 0 0,1 9,18V24H7V22H5V24H3V18A2,2 0 0,1 5,16M5,18V20H7V18H5M12.93,16H15L12.07,24H10L12.93,16M18,16H21V18H18V22H21V24H18A2,2 0 0,1 16,22V18A2,2 0 0,1 18,16Z";var mdiAirFilter="M19,18.31V20A2,2 0 0,1 17,22H7A2,2 0 0,1 5,20V16.3C4.54,16.12 3.95,16 3,16A1,1 0 0,1 2,15A1,1 0 0,1 3,14C3.82,14 4.47,14.08 5,14.21V12.3C4.54,12.12 3.95,12 3,12A1,1 0 0,1 2,11A1,1 0 0,1 3,10C3.82,10 4.47,10.08 5,10.21V8.3C4.54,8.12 3.95,8 3,8A1,1 0 0,1 2,7A1,1 0 0,1 3,6C3.82,6 4.47,6.08 5,6.21V4A2,2 0 0,1 7,2H17A2,2 0 0,1 19,4V6.16C20.78,6.47 21.54,7.13 21.71,7.29C22.1,7.68 22.1,8.32 21.71,8.71C21.32,9.1 20.8,9.09 20.29,8.71V8.71C20.29,8.71 19.25,8 17,8C15.74,8 14.91,8.41 13.95,8.9C12.91,9.41 11.74,10 10,10C9.64,10 9.31,10 9,9.96V7.95C9.3,8 9.63,8 10,8C11.26,8 12.09,7.59 13.05,7.11C14.09,6.59 15.27,6 17,6V4H7V20H17V18C18.5,18 18.97,18.29 19,18.31M17,10C15.27,10 14.09,10.59 13.05,11.11C12.09,11.59 11.26,12 10,12C9.63,12 9.3,12 9,11.95V13.96C9.31,14 9.64,14 10,14C11.74,14 12.91,13.41 13.95,12.9C14.91,12.42 15.74,12 17,12C19.25,12 20.29,12.71 20.29,12.71V12.71C20.8,13.1 21.32,13.1 21.71,12.71C22.1,12.32 22.1,11.69 21.71,11.29C21.5,11.08 20.25,10 17,10M17,14C15.27,14 14.09,14.59 13.05,15.11C12.09,15.59 11.26,16 10,16C9.63,16 9.3,16 9,15.95V17.96C9.31,18 9.64,18 10,18C11.74,18 12.91,17.41 13.95,16.9C14.91,16.42 15.74,16 17,16C19.25,16 20.29,16.71 20.29,16.71V16.71C20.8,17.1 21.32,17.1 21.71,16.71C22.1,16.32 22.1,15.69 21.71,15.29C21.5,15.08 20.25,14 17,14Z";var mdiAirPurifier="M11,9A4,4 0 0,1 15,13A4,4 0 0,1 11,17A4,4 0 0,1 7,13A4,4 0 0,1 11,9M11,11A2,2 0 0,0 9,13A2,2 0 0,0 11,15A2,2 0 0,0 13,13A2,2 0 0,0 11,11M7,4H14A4,4 0 0,1 18,8V9H16V8A2,2 0 0,0 14,6H7A2,2 0 0,0 5,8V20H16V18H18V22H3V8A4,4 0 0,1 7,4M16,11C18.5,11 18.5,9 21,9V11C18.5,11 18.5,13 16,13V11M16,15C18.5,15 18.5,13 21,13V15C18.5,15 18.5,17 16,17V15Z";var mdiAlertCircleOutline="M11,15H13V17H11V15M11,7H13V13H11V7M12,2C6.47,2 2,6.5 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,20A8,8 0 0,1 4,12A8,8 0 0,1 12,4A8,8 0 0,1 20,12A8,8 0 0,1 12,20Z";var mdiArrowLeft="M20,11V13H8L13.5,18.5L12.08,19.92L4.16,12L12.08,4.08L13.5,5.5L8,11H20Z";var mdiBell="M21,19V20H3V19L5,17V11C5,7.9 7.03,5.17 10,4.29C10,4.19 10,4.1 10,4A2,2 0 0,1 12,2A2,2 0 0,1 14,4C14,4.1 14,4.19 14,4.29C16.97,5.17 19,7.9 19,11V17L21,19M14,21A2,2 0 0,1 12,23A2,2 0 0,1 10,21";var mdiBlindsHorizontal="M20 19V3H4V19H2V21H22V19H20M16 9H18V11H16V9M14 11H6V9H14V11M18 7H16V5H18V7M14 5V7H6V5H14M6 19V13H14V14.82C13.55 15.14 13.25 15.66 13.25 16.25C13.25 17.22 14.03 18 15 18S16.75 17.22 16.75 16.25C16.75 15.66 16.45 15.13 16 14.82V13H18V19H6Z";var mdiBrightnessAuto="M14.3,16L13.6,14H10.4L9.7,16H7.8L11,7H13L16.2,16H14.3M20,8.69V4H15.31L12,0.69L8.69,4H4V8.69L0.69,12L4,15.31V20H8.69L12,23.31L15.31,20H20V15.31L23.31,12L20,8.69M10.85,12.65H13.15L12,9L10.85,12.65Z";var mdiBrightnessPercent="M20.04,8.71V4H15.34L12,0.69L8.71,4H4V8.71L0.69,12L4,15.34V20.04H8.71L12,23.35L15.34,20.04H20.04V15.34L23.35,12L20.04,8.71M8.83,7.05C9.81,7.05 10.6,7.84 10.6,8.83A1.77,1.77 0 0,1 8.83,10.6C7.84,10.6 7.05,9.81 7.05,8.83C7.05,7.84 7.84,7.05 8.83,7.05M15.22,17C14.24,17 13.45,16.2 13.45,15.22A1.77,1.77 0 0,1 15.22,13.45C16.2,13.45 17,14.24 17,15.22A1.78,1.78 0 0,1 15.22,17M8.5,17.03L7,15.53L15.53,7L17.03,8.5L8.5,17.03Z";var mdiCamera="M4,4H7L9,2H15L17,4H20A2,2 0 0,1 22,6V18A2,2 0 0,1 20,20H4A2,2 0 0,1 2,18V6A2,2 0 0,1 4,4M12,7A5,5 0 0,0 7,12A5,5 0 0,0 12,17A5,5 0 0,0 17,12A5,5 0 0,0 12,7M12,9A3,3 0 0,1 15,12A3,3 0 0,1 12,15A3,3 0 0,1 9,12A3,3 0 0,1 12,9Z";var mdiCast="M1,10V12A9,9 0 0,1 10,21H12C12,14.92 7.07,10 1,10M1,14V16A5,5 0 0,1 6,21H8A7,7 0 0,0 1,14M1,18V21H4A3,3 0 0,0 1,18M21,3H3C1.89,3 1,3.89 1,5V8H3V5H21V19H14V21H21A2,2 0 0,0 23,19V5C23,3.89 22.1,3 21,3Z";var mdiCctv="M6.03 12.03L8.03 15.5L5.5 18.68L2 12.62L6.03 12.03M17 18V15.29C17.88 14.9 18.5 14.03 18.5 13C18.5 12.43 18.3 11.9 17.97 11.5L19.94 10.35C20.95 9.76 21.3 8.47 20.71 7.46L19.33 5.06C18.74 4.05 17.45 3.7 16.44 4.28L8.31 9C7.36 9.53 7.03 10.75 7.58 11.71L9.08 14.31C9.63 15.26 10.86 15.59 11.81 15.04L13.69 13.96C13.94 14.55 14.41 15.03 15 15.29V18C15 19.1 15.9 20 17 20H22V18H17Z";var mdiChatProcessing="M12,3C17.5,3 22,6.58 22,11C22,15.42 17.5,19 12,19C10.76,19 9.57,18.82 8.47,18.5C5.55,21 2,21 2,21C4.33,18.67 4.7,17.1 4.75,16.5C3.05,15.07 2,13.13 2,11C2,6.58 6.5,3 12,3M17,12V10H15V12H17M13,12V10H11V12H13M9,12V10H7V12H9Z";var mdiChevronDown="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z";var mdiChevronRight="M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z";var mdiChip="M6,4H18V5H21V7H18V9H21V11H18V13H21V15H18V17H21V19H18V20H6V19H3V17H6V15H3V13H6V11H3V9H6V7H3V5H6V4M11,15V18H12V15H11M13,15V18H14V15H13M15,15V18H16V15H15Z";var mdiClose="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z";var mdiCog="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z";var mdiDishwasher="M18,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V4A2,2 0 0,0 18,2M10,4A1,1 0 0,1 11,5A1,1 0 0,1 10,6A1,1 0 0,1 9,5A1,1 0 0,1 10,4M7,4A1,1 0 0,1 8,5A1,1 0 0,1 7,6A1,1 0 0,1 6,5A1,1 0 0,1 7,4M18,20H6V8H18V20M14.67,15.33C14.69,16.03 14.41,16.71 13.91,17.21C12.86,18.26 11.15,18.27 10.09,17.21C9.59,16.71 9.31,16.03 9.33,15.33C9.4,14.62 9.63,13.94 10,13.33C10.37,12.5 10.81,11.73 11.33,11L12,10C13.79,12.59 14.67,14.36 14.67,15.33";var mdiDoorOpen="M12,3C10.89,3 10,3.89 10,5H3V19H2V21H22V19H21V5C21,3.89 20.11,3 19,3H12M12,5H19V19H12V5M5,11H7V13H5V11Z";var mdiDoorbell="M12 10C10.9 10 10 10.9 10 12S10.9 14 12 14 14 13.1 14 12 13.1 10 12 10M16 2H8C6.9 2 6 2.9 6 4V20C6 21.1 6.9 22 8 22H16C17.1 22 18 21.1 18 20V4C18 2.9 17.1 2 16 2M16 20H8V4H16V20Z";var mdiDoorbellVideo="M14 15C14 16.11 13.11 17 12 17S10 16.11 10 15 10.9 13 12 13 14 13.9 14 15M18 4V20C18 21.1 17.11 22 16 22H8C6.9 22 6 21.11 6 20V4C6 2.9 6.9 2 8 2H16C17.11 2 18 2.9 18 4M10.5 7C10.5 7.83 11.17 8.5 12 8.5S13.5 7.83 13.5 7 12.83 5.5 12 5.5 10.5 6.17 10.5 7M16 10H8V20H16V10Z";var mdiEthernet="M7,15H9V18H11V15H13V18H15V15H17V18H19V9H15V6H9V9H5V18H7V15M4.38,3H19.63C20.94,3 22,4.06 22,5.38V19.63A2.37,2.37 0 0,1 19.63,22H4.38C3.06,22 2,20.94 2,19.63V5.38C2,4.06 3.06,3 4.38,3Z";var mdiEvStation="M19.77,7.23L19.78,7.22L16.06,3.5L15,4.56L17.11,6.67C16.17,7.03 15.5,7.93 15.5,9A2.5,2.5 0 0,0 18,11.5C18.36,11.5 18.69,11.42 19,11.29V18.5A1,1 0 0,1 18,19.5A1,1 0 0,1 17,18.5V14A2,2 0 0,0 15,12H14V5A2,2 0 0,0 12,3H6A2,2 0 0,0 4,5V21H14V13.5H15.5V18.5A2.5,2.5 0 0,0 18,21A2.5,2.5 0 0,0 20.5,18.5V9C20.5,8.31 20.22,7.68 19.77,7.23M18,10A1,1 0 0,1 17,9A1,1 0 0,1 18,8A1,1 0 0,1 19,9A1,1 0 0,1 18,10M8,18V13.5H6L10,6V11H12L8,18Z";var mdiFan="M12,11A1,1 0 0,0 11,12A1,1 0 0,0 12,13A1,1 0 0,0 13,12A1,1 0 0,0 12,11M12.5,2C17,2 17.11,5.57 14.75,6.75C13.76,7.24 13.32,8.29 13.13,9.22C13.61,9.42 14.03,9.73 14.35,10.13C18.05,8.13 22.03,8.92 22.03,12.5C22.03,17 18.46,17.1 17.28,14.73C16.78,13.74 15.72,13.3 14.79,13.11C14.59,13.59 14.28,14 13.88,14.34C15.87,18.03 15.08,22 11.5,22C7,22 6.91,18.42 9.27,17.24C10.25,16.75 10.69,15.71 10.89,14.79C10.4,14.59 9.97,14.27 9.65,13.87C5.96,15.85 2,15.07 2,11.5C2,7 5.56,6.89 6.74,9.26C7.24,10.25 8.29,10.68 9.22,10.87C9.41,10.39 9.73,9.97 10.14,9.65C8.15,5.96 8.94,2 12.5,2Z";var mdiFile="M13,9V3.5L18.5,9M6,2C4.89,2 4,2.89 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6Z";var mdiFitToScreen="M17 4H20C21.1 4 22 4.9 22 6V8H20V6H17V4M4 8V6H7V4H4C2.9 4 2 4.9 2 6V8H4M20 16V18H17V20H20C21.1 20 22 19.1 22 18V16H20M7 18H4V16H2V18C2 19.1 2.9 20 4 20H7V18M18 8H6V16H18V8Z";var mdiFridge="M7,2H17A2,2 0 0,1 19,4V9H5V4A2,2 0 0,1 7,2M19,19A2,2 0 0,1 17,21V22H15V21H9V22H7V21A2,2 0 0,1 5,19V10H19V19M8,5V7H10V5H8M8,12V15H10V12H8Z";var mdiGauge="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,4A8,8 0 0,1 20,12C20,14.4 19,16.5 17.3,18C15.9,16.7 14,16 12,16C10,16 8.2,16.7 6.7,18C5,16.5 4,14.4 4,12A8,8 0 0,1 12,4M14,5.89C13.62,5.9 13.26,6.15 13.1,6.54L11.81,9.77L11.71,10C11,10.13 10.41,10.6 10.14,11.26C9.73,12.29 10.23,13.45 11.26,13.86C12.29,14.27 13.45,13.77 13.86,12.74C14.12,12.08 14,11.32 13.57,10.76L13.67,10.5L14.96,7.29L14.97,7.26C15.17,6.75 14.92,6.17 14.41,5.96C14.28,5.91 14.15,5.89 14,5.89M10,6A1,1 0 0,0 9,7A1,1 0 0,0 10,8A1,1 0 0,0 11,7A1,1 0 0,0 10,6M7,9A1,1 0 0,0 6,10A1,1 0 0,0 7,11A1,1 0 0,0 8,10A1,1 0 0,0 7,9M17,9A1,1 0 0,0 16,10A1,1 0 0,0 17,11A1,1 0 0,0 18,10A1,1 0 0,0 17,9Z";var mdiGraphOutline="M19.5 17C19.36 17 19.24 17 19.11 17.04L17.5 13.8C17.95 13.35 18.25 12.71 18.25 12C18.25 10.62 17.13 9.5 15.75 9.5C15.61 9.5 15.5 9.5 15.35 9.54L13.74 6.3C14.21 5.84 14.5 5.21 14.5 4.5C14.5 3.12 13.38 2 12 2S9.5 3.12 9.5 4.5C9.5 5.2 9.79 5.84 10.26 6.29L8.65 9.54C8.5 9.5 8.39 9.5 8.25 9.5C6.87 9.5 5.75 10.62 5.75 12C5.75 12.71 6.04 13.34 6.5 13.79L4.89 17.04C4.76 17 4.64 17 4.5 17C3.12 17 2 18.12 2 19.5C2 20.88 3.12 22 4.5 22S7 20.88 7 19.5C7 18.8 6.71 18.16 6.24 17.71L7.86 14.46C8 14.5 8.12 14.5 8.25 14.5C8.38 14.5 8.5 14.5 8.63 14.46L10.26 17.71C9.79 18.16 9.5 18.8 9.5 19.5C9.5 20.88 10.62 22 12 22S14.5 20.88 14.5 19.5C14.5 18.12 13.38 17 12 17C11.87 17 11.74 17 11.61 17.04L10 13.8C10.45 13.35 10.75 12.71 10.75 12C10.75 11.3 10.46 10.67 10 10.21L11.61 6.96C11.74 7 11.87 7 12 7C12.13 7 12.26 7 12.39 6.96L14 10.21C13.54 10.66 13.25 11.3 13.25 12C13.25 13.38 14.37 14.5 15.75 14.5C15.88 14.5 16 14.5 16.13 14.46L17.76 17.71C17.29 18.16 17 18.8 17 19.5C17 20.88 18.12 22 19.5 22S22 20.88 22 19.5C22 18.12 20.88 17 19.5 17M4.5 20.5C3.95 20.5 3.5 20.05 3.5 19.5S3.95 18.5 4.5 18.5 5.5 18.95 5.5 19.5 5.05 20.5 4.5 20.5M13 19.5C13 20.05 12.55 20.5 12 20.5S11 20.05 11 19.5 11.45 18.5 12 18.5 13 18.95 13 19.5M7.25 12C7.25 11.45 7.7 11 8.25 11S9.25 11.45 9.25 12 8.8 13 8.25 13 7.25 12.55 7.25 12M11 4.5C11 3.95 11.45 3.5 12 3.5S13 3.95 13 4.5 12.55 5.5 12 5.5 11 5.05 11 4.5M14.75 12C14.75 11.45 15.2 11 15.75 11S16.75 11.45 16.75 12 16.3 13 15.75 13 14.75 12.55 14.75 12M19.5 20.5C18.95 20.5 18.5 20.05 18.5 19.5S18.95 18.5 19.5 18.5 20.5 18.95 20.5 19.5 20.05 20.5 19.5 20.5Z";var mdiHeatPump="M19 3H5C3.9 3 3 3.9 3 5V19C3 20.1 3.9 21 5 21H19C20.1 21 21 20.1 21 19V5C21 3.9 20.1 3 19 3M12.75 7.08C13.57 7.2 14.32 7.5 14.95 8L12.75 10.19V7.08M11.25 7.08V10.19L9.05 8C9.68 7.5 10.43 7.2 11.25 7.08M8 9.05L10.19 11.25H7.08C7.2 10.43 7.5 9.68 8 9.05M7.08 12.75H10.19L8 14.95C7.5 14.32 7.2 13.57 7.08 12.75M11.25 16.92C10.43 16.8 9.68 16.5 9.05 16L11.25 13.81V16.92M12 13C11.45 13 11 12.55 11 12S11.45 11 12 11 13 11.45 13 12 12.55 13 12 13M12.75 16.92V13.81L14.95 16C14.32 16.5 13.57 16.8 12.75 16.92M16 14.95L13.81 12.75H16.92C16.8 13.57 16.5 14.32 16 14.95M13.81 11.25L16 9.05C16.5 9.69 16.8 10.44 16.92 11.25H13.81Z";var mdiHelp="M10,19H13V22H10V19M12,2C17.35,2.22 19.68,7.62 16.5,11.67C15.67,12.67 14.33,13.33 13.67,14.17C13,15 13,16 13,17H10C10,15.33 10,13.92 10.67,12.92C11.33,11.92 12.67,11.33 13.5,10.67C15.92,8.43 15.32,5.26 12,5A3,3 0 0,0 9,8H6A6,6 0 0,1 12,2Z";var mdiHome="M10,20V14H14V20H19V12H22L12,3L2,12H5V20H10Z";var mdiLeaf="M17,8C8,10 5.9,16.17 3.82,21.34L5.71,22L6.66,19.7C7.14,19.87 7.64,20 8,20C19,20 22,3 22,3C21,5 14,5.25 9,6.25C4,7.25 2,11.5 2,13.5C2,15.5 3.75,17.25 3.75,17.25C7,8 17,8 17,8Z";var mdiLightbulb="M12,2A7,7 0 0,0 5,9C5,11.38 6.19,13.47 8,14.74V17A1,1 0 0,0 9,18H15A1,1 0 0,0 16,17V14.74C17.81,13.47 19,11.38 19,9A7,7 0 0,0 12,2M9,21A1,1 0 0,0 10,22H14A1,1 0 0,0 15,21V20H9V21Z";var mdiLink="M3.9,12C3.9,10.29 5.29,8.9 7,8.9H11V7H7A5,5 0 0,0 2,12A5,5 0 0,0 7,17H11V15.1H7C5.29,15.1 3.9,13.71 3.9,12M8,13H16V11H8V13M17,7H13V8.9H17C18.71,8.9 20.1,10.29 20.1,12C20.1,13.71 18.71,15.1 17,15.1H13V17H17A5,5 0 0,0 22,12A5,5 0 0,0 17,7Z";var mdiLoading="M12,4V2A10,10 0 0,0 2,12H4A8,8 0 0,1 12,4Z";var mdiLock="M12,17A2,2 0 0,0 14,15C14,13.89 13.1,13 12,13A2,2 0 0,0 10,15A2,2 0 0,0 12,17M18,8A2,2 0 0,1 20,10V20A2,2 0 0,1 18,22H6A2,2 0 0,1 4,20V10C4,8.89 4.9,8 6,8H7V6A5,5 0 0,1 12,1A5,5 0 0,1 17,6V8H18M12,3A3,3 0 0,0 9,6V8H15V6A3,3 0 0,0 12,3Z";var mdiLogout="M17 7L15.59 8.41L18.17 11H8V13H18.17L15.59 15.58L17 17L22 12M4 5H12V3H4C2.9 3 2 3.9 2 5V19C2 20.1 2.9 21 4 21H12V19H4V5Z";var mdiMagnifyMinus="M9,2A7,7 0 0,1 16,9C16,10.57 15.5,12 14.61,13.19L15.41,14H16L22,20L20,22L14,16V15.41L13.19,14.61C12,15.5 10.57,16 9,16A7,7 0 0,1 2,9A7,7 0 0,1 9,2M5,8V10H13V8H5Z";var mdiMagnifyPlus="M9,2A7,7 0 0,1 16,9C16,10.57 15.5,12 14.61,13.19L15.41,14H16L22,20L20,22L14,16V15.41L13.19,14.61C12,15.5 10.57,16 9,16A7,7 0 0,1 2,9A7,7 0 0,1 9,2M8,5V8H5V10H8V13H10V10H13V8H10V5H8Z";var mdiMeterElectric="M12 2C7.04 2 3 6.04 3 11C3 14.91 5.5 18.24 9 19.47V22H11V19.94C11.33 20 11.66 20 12 20S12.67 20 13 19.94V22H15V19.47C18.5 18.23 21 14.9 21 11C21 6.04 16.96 2 12 2M14.25 14L11.25 17L9.75 15.5L11 14.25L9.75 13L12.75 10L14.25 11.5L13 12.75L14.25 14M16 9H8V7H16V9Z";var mdiMicrowave="M4,5A2,2 0 0,0 2,7V17A2,2 0 0,0 4,19H20A2,2 0 0,0 22,17V7A2,2 0 0,0 20,5H4M4,7H16V17H4V7M19,7A1,1 0 0,1 20,8A1,1 0 0,1 19,9A1,1 0 0,1 18,8A1,1 0 0,1 19,7M13,9V15H15V9H13M19,11A1,1 0 0,1 20,12A1,1 0 0,1 19,13A1,1 0 0,1 18,12A1,1 0 0,1 19,11Z";var mdiMotionSensor="M10,0.2C9,0.2 8.2,1 8.2,2C8.2,3 9,3.8 10,3.8C11,3.8 11.8,3 11.8,2C11.8,1 11,0.2 10,0.2M15.67,1A7.33,7.33 0 0,0 23,8.33V7A6,6 0 0,1 17,1H15.67M18.33,1C18.33,3.58 20.42,5.67 23,5.67V4.33C21.16,4.33 19.67,2.84 19.67,1H18.33M21,1A2,2 0 0,0 23,3V1H21M7.92,4.03C7.75,4.03 7.58,4.06 7.42,4.11L2,5.8V11H3.8V7.33L5.91,6.67L2,22H3.8L6.67,13.89L9,17V22H10.8V15.59L8.31,11.05L9.04,8.18L10.12,10H15V8.2H11.38L9.38,4.87C9.08,4.37 8.54,4.03 7.92,4.03Z";var mdiPause="M14,19H18V5H14M6,19H10V5H6V19Z";var mdiPencil="M20.71,7.04C21.1,6.65 21.1,6 20.71,5.63L18.37,3.29C18,2.9 17.35,2.9 16.96,3.29L15.12,5.12L18.87,8.87M3,17.25V21H6.75L17.81,9.93L14.06,6.18L3,17.25Z";var mdiPlay="M8,5.14V19.14L19,12.14L8,5.14Z";var mdiPlus="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z";var mdiPowerPlug="M16,7V3H14V7H10V3H8V7H8C7,7 6,8 6,9V14.5L9.5,18V21H14.5V18L18,14.5V9C18,8 17,7 16,7Z";var mdiPump="M2 21V15H3.5C3.18 14.06 3 13.05 3 12C3 7.03 7.03 3 12 3H22V9H20.5C20.82 9.94 21 10.95 21 12C21 16.97 16.97 21 12 21H2M5 12C5 13.28 5.34 14.47 5.94 15.5L9.4 13.5C9.15 13.06 9 12.55 9 12C9 11.35 9.21 10.75 9.56 10.26L6.3 7.93C5.5 9.08 5 10.5 5 12M12 19C14.59 19 16.85 17.59 18.06 15.5L14.6 13.5C14.08 14.4 13.11 15 12 15L11.71 15L11.33 18.97L12 19M12 9C13.21 9 14.26 9.72 14.73 10.76L18.37 9.1C17.27 6.68 14.83 5 12 5V9M12 11C11.45 11 11 11.45 11 12C11 12.55 11.45 13 12 13C12.55 13 13 12.55 13 12C13 11.45 12.55 11 12 11Z";var mdiRefresh="M17.65,6.35C16.2,4.9 14.21,4 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20C15.73,20 18.84,17.45 19.73,14H17.65C16.83,16.33 14.61,18 12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6C13.66,6 15.14,6.69 16.22,7.78L13,11H20V4L17.65,6.35Z";var mdiRemote="M12,0C8.96,0 6.21,1.23 4.22,3.22L5.63,4.63C7.26,3 9.5,2 12,2C14.5,2 16.74,3 18.36,4.64L19.77,3.23C17.79,1.23 15.04,0 12,0M7.05,6.05L8.46,7.46C9.37,6.56 10.62,6 12,6C13.38,6 14.63,6.56 15.54,7.46L16.95,6.05C15.68,4.78 13.93,4 12,4C10.07,4 8.32,4.78 7.05,6.05M12,15A2,2 0 0,1 10,13A2,2 0 0,1 12,11A2,2 0 0,1 14,13A2,2 0 0,1 12,15M15,9H9A1,1 0 0,0 8,10V22A1,1 0 0,0 9,23H15A1,1 0 0,0 16,22V10A1,1 0 0,0 15,9Z";var mdiRobotVacuum="M12,2C14.65,2 17.19,3.06 19.07,4.93L17.65,6.35C16.15,4.85 14.12,4 12,4C9.88,4 7.84,4.84 6.35,6.35L4.93,4.93C6.81,3.06 9.35,2 12,2M3.66,6.5L5.11,7.94C4.39,9.17 4,10.57 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12C20,10.57 19.61,9.17 18.88,7.94L20.34,6.5C21.42,8.12 22,10.04 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12C2,10.04 2.58,8.12 3.66,6.5M12,6A6,6 0 0,1 18,12C18,13.59 17.37,15.12 16.24,16.24L14.83,14.83C14.08,15.58 13.06,16 12,16C10.94,16 9.92,15.58 9.17,14.83L7.76,16.24C6.63,15.12 6,13.59 6,12A6,6 0 0,1 12,6M12,8A1,1 0 0,0 11,9A1,1 0 0,0 12,10A1,1 0 0,0 13,9A1,1 0 0,0 12,8Z";var mdiRouter="M12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C17.5 22 22 17.5 22 12C22 6.5 17.5 2 12 2M12 20C7.58 20 4 16.42 4 12C4 7.58 7.58 4 12 4C16.42 4 20 7.58 20 12C20 16.42 16.42 20 12 20M13 13V16H15L12 19L9 16H11V13M5 13H8V15L11 12L8 9V11H5M11 11V8H9L12 5L15 8H13V11M19 11H16V9L13 12L16 15V13H19";var mdiShareVariant="M18,16.08C17.24,16.08 16.56,16.38 16.04,16.85L8.91,12.7C8.96,12.47 9,12.24 9,12C9,11.76 8.96,11.53 8.91,11.3L15.96,7.19C16.5,7.69 17.21,8 18,8A3,3 0 0,0 21,5A3,3 0 0,0 18,2A3,3 0 0,0 15,5C15,5.24 15.04,5.47 15.09,5.7L8.04,9.81C7.5,9.31 6.79,9 6,9A3,3 0 0,0 3,12A3,3 0 0,0 6,15C6.79,15 7.5,14.69 8.04,14.19L15.16,18.34C15.11,18.55 15.08,18.77 15.08,19C15.08,20.61 16.39,21.91 18,21.91C19.61,21.91 20.92,20.61 20.92,19A2.92,2.92 0 0,0 18,16.08Z";var mdiSignalCellular1="M19.5,5.5V18.5H17.5V5.5H19.5M12.5,10.5V18.5H10.5V10.5H12.5M21,4H16V20H21V4M14,9H9V20H14V9M7,14H2V20H7V14Z";var mdiSignalCellular2="M19.5,5.5V18.5H17.5V5.5H19.5M21,4H16V20H21V4M14,9H9V20H14V9M7,14H2V20H7V14Z";var mdiSignalCellular3="M21,4H16V20H21V4M14,9H9V20H14V9M7,14H2V20H7V14Z";var mdiSmokeDetector="M12,18A6,6 0 0,0 18,12C18,8.68 15.31,6 12,6C8.68,6 6,8.68 6,12A6,6 0 0,0 12,18M19,3A2,2 0 0,1 21,5V19A2,2 0 0,1 19,21H5C3.89,21 3,20.1 3,19V5C3,3.89 3.89,3 5,3H19M8,12A4,4 0 0,1 12,8A4,4 0 0,1 16,12A4,4 0 0,1 12,16A4,4 0 0,1 8,12Z";var mdiSnowflakeAlert="M16.46,9.41L13,7.38V5.12L14.71,3.41L13.29,2L12,3.29L10.71,2L9.29,3.41L11,5.12V7.38L8.5,8.82L6.5,7.69L5.92,5.36L4,5.88L4.47,7.65L2.7,8.12L3.22,10.05L5.55,9.43L7.55,10.56V13.45L5.55,14.58L3.22,13.96L2.7,15.89L4.47,16.36L4,18.12L5.93,18.64L6.55,16.31L8.55,15.18L11,16.62V18.88L9.29,20.59L10.71,22L12,20.71L13.29,22L14.7,20.59L13,18.88V16.62L16.46,14.61M9.5,10.56L12,9.11L14.5,10.56V13.44L12,14.89L9.5,13.44M19,13V7H21V13H19M19,17V15H21V17H19Z";var mdiSolarPower="M11.45,2V5.55L15,3.77L11.45,2M10.45,8L8,10.46L11.75,11.71L10.45,8M2,11.45L3.77,15L5.55,11.45H2M10,2H2V10C2.57,10.17 3.17,10.25 3.77,10.25C7.35,10.26 10.26,7.35 10.27,3.75C10.26,3.16 10.17,2.57 10,2M17,22V16H14L19,7V13H22L17,22Z";var mdiSpeaker="M12,12A3,3 0 0,0 9,15A3,3 0 0,0 12,18A3,3 0 0,0 15,15A3,3 0 0,0 12,12M12,20A5,5 0 0,1 7,15A5,5 0 0,1 12,10A5,5 0 0,1 17,15A5,5 0 0,1 12,20M12,4A2,2 0 0,1 14,6A2,2 0 0,1 12,8C10.89,8 10,7.1 10,6C10,4.89 10.89,4 12,4M17,2H7C5.89,2 5,2.89 5,4V20A2,2 0 0,0 7,22H17A2,2 0 0,0 19,20V4C19,2.89 18.1,2 17,2Z";var mdiSprinkler="M11 7H13V9H11V7M5 22H9V10H5V22M14 11H16V9H14V11M17 10H19V8H17V10M17 5V7H19V5H17M14 8H16V6H14V8M17 13H19V11H17V13M5 7H5.33L6 9H8L8.67 7H9V6H5V7Z";var mdiStove="M6,14H8L11,17H9L6,14M4,4H5V3A1,1 0 0,1 6,2H10A1,1 0 0,1 11,3V4H13V3A1,1 0 0,1 14,2H18A1,1 0 0,1 19,3V4H20A2,2 0 0,1 22,6V19A2,2 0 0,1 20,21V22H17V21H7V22H4V21A2,2 0 0,1 2,19V6A2,2 0 0,1 4,4M18,7A1,1 0 0,1 19,8A1,1 0 0,1 18,9A1,1 0 0,1 17,8A1,1 0 0,1 18,7M14,7A1,1 0 0,1 15,8A1,1 0 0,1 14,9A1,1 0 0,1 13,8A1,1 0 0,1 14,7M20,6H4V10H20V6M4,19H20V12H4V19M6,7A1,1 0 0,1 7,8A1,1 0 0,1 6,9A1,1 0 0,1 5,8A1,1 0 0,1 6,7M13,14H15L18,17H16L13,14Z";var mdiTelevision="M21,17H3V5H21M21,3H3A2,2 0 0,0 1,5V17A2,2 0 0,0 3,19H8V21H16V19H21A2,2 0 0,0 23,17V5A2,2 0 0,0 21,3Z";var mdiThermometer="M15 13V5A3 3 0 0 0 9 5V13A5 5 0 1 0 15 13M12 4A1 1 0 0 1 13 5V8H11V5A1 1 0 0 1 12 4Z";var mdiToggleSwitch="M17,7H7A5,5 0 0,0 2,12A5,5 0 0,0 7,17H17A5,5 0 0,0 22,12A5,5 0 0,0 17,7M17,15A3,3 0 0,1 14,12A3,3 0 0,1 17,9A3,3 0 0,1 20,12A3,3 0 0,1 17,15Z";var mdiTrashCan="M9,3V4H4V6H5V19A2,2 0 0,0 7,21H17A2,2 0 0,0 19,19V6H20V4H15V3H9M9,8H11V17H9V8M13,8H15V17H13V8Z";var mdiTumbleDryer="M6,2H18A2,2 0 0,1 20,4V20A2,2 0 0,1 18,22H6A2,2 0 0,1 4,20V4A2,2 0 0,1 6,2M7,4A1,1 0 0,0 6,5A1,1 0 0,0 7,6A1,1 0 0,0 8,5A1,1 0 0,0 7,4M10,4A1,1 0 0,0 9,5A1,1 0 0,0 10,6A1,1 0 0,0 11,5A1,1 0 0,0 10,4M12,8A6,6 0 0,0 6,14A6,6 0 0,0 12,20A6,6 0 0,0 18,14A6,6 0 0,0 12,8M8.11,10.5H10C9.76,11.88 10,12.67 10.58,13.29C11.68,14.36 12.16,15.71 11.89,17.5H10C10.24,16.12 10,15.33 9.42,14.71C8.32,13.64 7.85,12.29 8.11,10.5M12.11,10.5H14C13.76,11.88 14,12.67 14.58,13.29C15.68,14.36 16.16,15.71 15.89,17.5H14C14.24,16.12 14,15.33 13.42,14.71C12.32,13.64 11.85,12.29 12.11,10.5Z";var mdiUpdate="M21,10.12H14.22L16.96,7.3C14.23,4.6 9.81,4.5 7.08,7.2C4.35,9.91 4.35,14.28 7.08,17C9.81,19.7 14.23,19.7 16.96,17C18.32,15.65 19,14.08 19,12.1H21C21,14.08 20.12,16.65 18.36,18.39C14.85,21.87 9.15,21.87 5.64,18.39C2.14,14.92 2.11,9.28 5.62,5.81C9.13,2.34 14.76,2.34 18.27,5.81L21,3V10.12M12.5,8V12.25L16,14.33L15.28,15.54L11,13V8H12.5Z";var mdiWashingMachine="M14.83,11.17C16.39,12.73 16.39,15.27 14.83,16.83C13.27,18.39 10.73,18.39 9.17,16.83L14.83,11.17M6,2H18A2,2 0 0,1 20,4V20A2,2 0 0,1 18,22H6A2,2 0 0,1 4,20V4A2,2 0 0,1 6,2M7,4A1,1 0 0,0 6,5A1,1 0 0,0 7,6A1,1 0 0,0 8,5A1,1 0 0,0 7,4M10,4A1,1 0 0,0 9,5A1,1 0 0,0 10,6A1,1 0 0,0 11,5A1,1 0 0,0 10,4M12,8A6,6 0 0,0 6,14A6,6 0 0,0 12,20A6,6 0 0,0 18,14A6,6 0 0,0 12,8Z";var mdiWater="M12,20A6,6 0 0,1 6,14C6,10 12,3.25 12,3.25C12,3.25 18,10 18,14A6,6 0 0,1 12,20Z";var mdiWaterBoiler="M8 2C6.89 2 6 2.89 6 4V16C6 17.11 6.89 18 8 18H9V20H6V22H9C10.11 22 11 21.11 11 20V18H13V20C13 21.11 13.89 22 15 22H18V20H15V18H16C17.11 18 18 17.11 18 16V4C18 2.89 17.11 2 16 2H8M12 4.97A2 2 0 0 1 14 6.97A2 2 0 0 1 12 8.97A2 2 0 0 1 10 6.97A2 2 0 0 1 12 4.97M10 14.5H14V16H10V14.5Z";var mdiWaterPercent="M12,3.25C12,3.25 6,10 6,14C6,17.32 8.69,20 12,20A6,6 0 0,0 18,14C18,10 12,3.25 12,3.25M14.47,9.97L15.53,11.03L9.53,17.03L8.47,15.97M9.75,10A1.25,1.25 0 0,1 11,11.25A1.25,1.25 0 0,1 9.75,12.5A1.25,1.25 0 0,1 8.5,11.25A1.25,1.25 0 0,1 9.75,10M14.25,14.5A1.25,1.25 0 0,1 15.5,15.75A1.25,1.25 0 0,1 14.25,17A1.25,1.25 0 0,1 13,15.75A1.25,1.25 0 0,1 14.25,14.5Z";var mdiWeatherNight="M17.75,4.09L15.22,6.03L16.13,9.09L13.5,7.28L10.87,9.09L11.78,6.03L9.25,4.09L12.44,4L13.5,1L14.56,4L17.75,4.09M21.25,11L19.61,12.25L20.2,14.23L18.5,13.06L16.8,14.23L17.39,12.25L15.75,11L17.81,10.95L18.5,9L19.19,10.95L21.25,11M18.97,15.95C19.8,15.87 20.69,17.05 20.16,17.8C19.84,18.25 19.5,18.67 19.08,19.07C15.17,23 8.84,23 4.94,19.07C1.03,15.17 1.03,8.83 4.94,4.93C5.34,4.53 5.76,4.17 6.21,3.85C6.96,3.32 8.14,4.21 8.06,5.04C7.79,7.9 8.75,10.87 10.95,13.06C13.14,15.26 16.1,16.22 18.97,15.95M17.33,17.97C14.5,17.81 11.7,16.64 9.53,14.5C7.36,12.31 6.2,9.5 6.04,6.68C3.23,9.82 3.34,14.64 6.35,17.66C9.37,20.67 14.19,20.78 17.33,17.97Z";var mdiWeatherRainy="M6,14.03A1,1 0 0,1 7,15.03C7,15.58 6.55,16.03 6,16.03C3.24,16.03 1,13.79 1,11.03C1,8.27 3.24,6.03 6,6.03C7,3.68 9.3,2.03 12,2.03C15.43,2.03 18.24,4.69 18.5,8.06L19,8.03A4,4 0 0,1 23,12.03C23,14.23 21.21,16.03 19,16.03H18C17.45,16.03 17,15.58 17,15.03C17,14.47 17.45,14.03 18,14.03H19A2,2 0 0,0 21,12.03A2,2 0 0,0 19,10.03H17V9.03C17,6.27 14.76,4.03 12,4.03C9.5,4.03 7.45,5.84 7.06,8.21C6.73,8.09 6.37,8.03 6,8.03A3,3 0 0,0 3,11.03A3,3 0 0,0 6,14.03M12,14.15C12.18,14.39 12.37,14.66 12.56,14.94C13,15.56 14,17.03 14,18C14,19.11 13.1,20 12,20A2,2 0 0,1 10,18C10,17.03 11,15.56 11.44,14.94C11.63,14.66 11.82,14.4 12,14.15M12,11.03L11.5,11.59C11.5,11.59 10.65,12.55 9.79,13.81C8.93,15.06 8,16.56 8,18A4,4 0 0,0 12,22A4,4 0 0,0 16,18C16,16.56 15.07,15.06 14.21,13.81C13.35,12.55 12.5,11.59 12.5,11.59";var mdiWeatherSunny="M12,7A5,5 0 0,1 17,12A5,5 0 0,1 12,17A5,5 0 0,1 7,12A5,5 0 0,1 12,7M12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15A3,3 0 0,0 15,12A3,3 0 0,0 12,9M12,2L14.39,5.42C13.65,5.15 12.84,5 12,5C11.16,5 10.35,5.15 9.61,5.42L12,2M3.34,7L7.5,6.65C6.9,7.16 6.36,7.78 5.94,8.5C5.5,9.24 5.25,10 5.11,10.79L3.34,7M3.36,17L5.12,13.23C5.26,14 5.53,14.78 5.95,15.5C6.37,16.24 6.91,16.86 7.5,17.37L3.36,17M20.65,7L18.88,10.79C18.74,10 18.47,9.23 18.05,8.5C17.63,7.78 17.1,7.15 16.5,6.64L20.65,7M20.64,17L16.5,17.36C17.09,16.85 17.62,16.22 18.04,15.5C18.46,14.77 18.73,14 18.87,13.21L20.64,17M12,22L9.59,18.56C10.33,18.83 11.14,19 12,19C12.82,19 13.63,18.83 14.37,18.56L12,22Z";var mdiWifi="M12,21L15.6,16.2C14.6,15.45 13.35,15 12,15C10.65,15 9.4,15.45 8.4,16.2L12,21M12,3C7.95,3 4.21,4.34 1.2,6.6L3,9C5.5,7.12 8.62,6 12,6C15.38,6 18.5,7.12 21,9L22.8,6.6C19.79,4.34 16.05,3 12,3M12,9C9.3,9 6.81,9.89 4.8,11.4L6.6,13.8C8.1,12.67 9.97,12 12,12C14.03,12 15.9,12.67 17.4,13.8L19.2,11.4C17.19,9.89 14.7,9 12,9Z";
237
+ var mdiAccessPoint="M4.93,4.93C3.12,6.74 2,9.24 2,12C2,14.76 3.12,17.26 4.93,19.07L6.34,17.66C4.89,16.22 4,14.22 4,12C4,9.79 4.89,7.78 6.34,6.34L4.93,4.93M19.07,4.93L17.66,6.34C19.11,7.78 20,9.79 20,12C20,14.22 19.11,16.22 17.66,17.66L19.07,19.07C20.88,17.26 22,14.76 22,12C22,9.24 20.88,6.74 19.07,4.93M7.76,7.76C6.67,8.85 6,10.35 6,12C6,13.65 6.67,15.15 7.76,16.24L9.17,14.83C8.45,14.11 8,13.11 8,12C8,10.89 8.45,9.89 9.17,9.17L7.76,7.76M16.24,7.76L14.83,9.17C15.55,9.89 16,10.89 16,12C16,13.11 15.55,14.11 14.83,14.83L16.24,16.24C17.33,15.15 18,13.65 18,12C18,10.35 17.33,8.85 16.24,7.76M12,10A2,2 0 0,0 10,12A2,2 0 0,0 12,14A2,2 0 0,0 14,12A2,2 0 0,0 12,10Z";var mdiAirConditioner="M6.59,0.66C8.93,-1.15 11.47,1.06 12.04,4.5C12.47,4.5 12.89,4.62 13.27,4.84C13.79,4.24 14.25,3.42 14.07,2.5C13.65,0.35 16.06,-1.39 18.35,1.58C20.16,3.92 17.95,6.46 14.5,7.03C14.5,7.46 14.39,7.89 14.16,8.27C14.76,8.78 15.58,9.24 16.5,9.06C18.63,8.64 20.38,11.04 17.41,13.34C15.07,15.15 12.53,12.94 11.96,9.5C11.53,9.5 11.11,9.37 10.74,9.15C10.22,9.75 9.75,10.58 9.93,11.5C10.35,13.64 7.94,15.39 5.65,12.42C3.83,10.07 6.05,7.53 9.5,6.97C9.5,6.54 9.63,6.12 9.85,5.74C9.25,5.23 8.43,4.76 7.5,4.94C5.37,5.36 3.62,2.96 6.59,0.66M5,16H7A2,2 0 0,1 9,18V24H7V22H5V24H3V18A2,2 0 0,1 5,16M5,18V20H7V18H5M12.93,16H15L12.07,24H10L12.93,16M18,16H21V18H18V22H21V24H18A2,2 0 0,1 16,22V18A2,2 0 0,1 18,16Z";var mdiAirFilter="M19,18.31V20A2,2 0 0,1 17,22H7A2,2 0 0,1 5,20V16.3C4.54,16.12 3.95,16 3,16A1,1 0 0,1 2,15A1,1 0 0,1 3,14C3.82,14 4.47,14.08 5,14.21V12.3C4.54,12.12 3.95,12 3,12A1,1 0 0,1 2,11A1,1 0 0,1 3,10C3.82,10 4.47,10.08 5,10.21V8.3C4.54,8.12 3.95,8 3,8A1,1 0 0,1 2,7A1,1 0 0,1 3,6C3.82,6 4.47,6.08 5,6.21V4A2,2 0 0,1 7,2H17A2,2 0 0,1 19,4V6.16C20.78,6.47 21.54,7.13 21.71,7.29C22.1,7.68 22.1,8.32 21.71,8.71C21.32,9.1 20.8,9.09 20.29,8.71V8.71C20.29,8.71 19.25,8 17,8C15.74,8 14.91,8.41 13.95,8.9C12.91,9.41 11.74,10 10,10C9.64,10 9.31,10 9,9.96V7.95C9.3,8 9.63,8 10,8C11.26,8 12.09,7.59 13.05,7.11C14.09,6.59 15.27,6 17,6V4H7V20H17V18C18.5,18 18.97,18.29 19,18.31M17,10C15.27,10 14.09,10.59 13.05,11.11C12.09,11.59 11.26,12 10,12C9.63,12 9.3,12 9,11.95V13.96C9.31,14 9.64,14 10,14C11.74,14 12.91,13.41 13.95,12.9C14.91,12.42 15.74,12 17,12C19.25,12 20.29,12.71 20.29,12.71V12.71C20.8,13.1 21.32,13.1 21.71,12.71C22.1,12.32 22.1,11.69 21.71,11.29C21.5,11.08 20.25,10 17,10M17,14C15.27,14 14.09,14.59 13.05,15.11C12.09,15.59 11.26,16 10,16C9.63,16 9.3,16 9,15.95V17.96C9.31,18 9.64,18 10,18C11.74,18 12.91,17.41 13.95,16.9C14.91,16.42 15.74,16 17,16C19.25,16 20.29,16.71 20.29,16.71V16.71C20.8,17.1 21.32,17.1 21.71,16.71C22.1,16.32 22.1,15.69 21.71,15.29C21.5,15.08 20.25,14 17,14Z";var mdiAirPurifier="M11,9A4,4 0 0,1 15,13A4,4 0 0,1 11,17A4,4 0 0,1 7,13A4,4 0 0,1 11,9M11,11A2,2 0 0,0 9,13A2,2 0 0,0 11,15A2,2 0 0,0 13,13A2,2 0 0,0 11,11M7,4H14A4,4 0 0,1 18,8V9H16V8A2,2 0 0,0 14,6H7A2,2 0 0,0 5,8V20H16V18H18V22H3V8A4,4 0 0,1 7,4M16,11C18.5,11 18.5,9 21,9V11C18.5,11 18.5,13 16,13V11M16,15C18.5,15 18.5,13 21,13V15C18.5,15 18.5,17 16,17V15Z";var mdiAlertCircleOutline="M11,15H13V17H11V15M11,7H13V13H11V7M12,2C6.47,2 2,6.5 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,20A8,8 0 0,1 4,12A8,8 0 0,1 12,4A8,8 0 0,1 20,12A8,8 0 0,1 12,20Z";var mdiArrowLeft="M20,11V13H8L13.5,18.5L12.08,19.92L4.16,12L12.08,4.08L13.5,5.5L8,11H20Z";var mdiBell="M21,19V20H3V19L5,17V11C5,7.9 7.03,5.17 10,4.29C10,4.19 10,4.1 10,4A2,2 0 0,1 12,2A2,2 0 0,1 14,4C14,4.1 14,4.19 14,4.29C16.97,5.17 19,7.9 19,11V17L21,19M14,21A2,2 0 0,1 12,23A2,2 0 0,1 10,21";var mdiBlindsHorizontal="M20 19V3H4V19H2V21H22V19H20M16 9H18V11H16V9M14 11H6V9H14V11M18 7H16V5H18V7M14 5V7H6V5H14M6 19V13H14V14.82C13.55 15.14 13.25 15.66 13.25 16.25C13.25 17.22 14.03 18 15 18S16.75 17.22 16.75 16.25C16.75 15.66 16.45 15.13 16 14.82V13H18V19H6Z";var mdiBrightnessAuto="M14.3,16L13.6,14H10.4L9.7,16H7.8L11,7H13L16.2,16H14.3M20,8.69V4H15.31L12,0.69L8.69,4H4V8.69L0.69,12L4,15.31V20H8.69L12,23.31L15.31,20H20V15.31L23.31,12L20,8.69M10.85,12.65H13.15L12,9L10.85,12.65Z";var mdiBrightnessPercent="M20.04,8.71V4H15.34L12,0.69L8.71,4H4V8.71L0.69,12L4,15.34V20.04H8.71L12,23.35L15.34,20.04H20.04V15.34L23.35,12L20.04,8.71M8.83,7.05C9.81,7.05 10.6,7.84 10.6,8.83A1.77,1.77 0 0,1 8.83,10.6C7.84,10.6 7.05,9.81 7.05,8.83C7.05,7.84 7.84,7.05 8.83,7.05M15.22,17C14.24,17 13.45,16.2 13.45,15.22A1.77,1.77 0 0,1 15.22,13.45C16.2,13.45 17,14.24 17,15.22A1.78,1.78 0 0,1 15.22,17M8.5,17.03L7,15.53L15.53,7L17.03,8.5L8.5,17.03Z";var mdiCamera="M4,4H7L9,2H15L17,4H20A2,2 0 0,1 22,6V18A2,2 0 0,1 20,20H4A2,2 0 0,1 2,18V6A2,2 0 0,1 4,4M12,7A5,5 0 0,0 7,12A5,5 0 0,0 12,17A5,5 0 0,0 17,12A5,5 0 0,0 12,7M12,9A3,3 0 0,1 15,12A3,3 0 0,1 12,15A3,3 0 0,1 9,12A3,3 0 0,1 12,9Z";var mdiCast="M1,10V12A9,9 0 0,1 10,21H12C12,14.92 7.07,10 1,10M1,14V16A5,5 0 0,1 6,21H8A7,7 0 0,0 1,14M1,18V21H4A3,3 0 0,0 1,18M21,3H3C1.89,3 1,3.89 1,5V8H3V5H21V19H14V21H21A2,2 0 0,0 23,19V5C23,3.89 22.1,3 21,3Z";var mdiCctv="M6.03 12.03L8.03 15.5L5.5 18.68L2 12.62L6.03 12.03M17 18V15.29C17.88 14.9 18.5 14.03 18.5 13C18.5 12.43 18.3 11.9 17.97 11.5L19.94 10.35C20.95 9.76 21.3 8.47 20.71 7.46L19.33 5.06C18.74 4.05 17.45 3.7 16.44 4.28L8.31 9C7.36 9.53 7.03 10.75 7.58 11.71L9.08 14.31C9.63 15.26 10.86 15.59 11.81 15.04L13.69 13.96C13.94 14.55 14.41 15.03 15 15.29V18C15 19.1 15.9 20 17 20H22V18H17Z";var mdiChatProcessing="M12,3C17.5,3 22,6.58 22,11C22,15.42 17.5,19 12,19C10.76,19 9.57,18.82 8.47,18.5C5.55,21 2,21 2,21C4.33,18.67 4.7,17.1 4.75,16.5C3.05,15.07 2,13.13 2,11C2,6.58 6.5,3 12,3M17,12V10H15V12H17M13,12V10H11V12H13M9,12V10H7V12H9Z";var mdiChevronDown="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z";var mdiChevronRight="M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z";var mdiChip="M6,4H18V5H21V7H18V9H21V11H18V13H21V15H18V17H21V19H18V20H6V19H3V17H6V15H3V13H6V11H3V9H6V7H3V5H6V4M11,15V18H12V15H11M13,15V18H14V15H13M15,15V18H16V15H15Z";var mdiClose="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z";var mdiCog="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z";var mdiDishwasher="M18,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V4A2,2 0 0,0 18,2M10,4A1,1 0 0,1 11,5A1,1 0 0,1 10,6A1,1 0 0,1 9,5A1,1 0 0,1 10,4M7,4A1,1 0 0,1 8,5A1,1 0 0,1 7,6A1,1 0 0,1 6,5A1,1 0 0,1 7,4M18,20H6V8H18V20M14.67,15.33C14.69,16.03 14.41,16.71 13.91,17.21C12.86,18.26 11.15,18.27 10.09,17.21C9.59,16.71 9.31,16.03 9.33,15.33C9.4,14.62 9.63,13.94 10,13.33C10.37,12.5 10.81,11.73 11.33,11L12,10C13.79,12.59 14.67,14.36 14.67,15.33";var mdiDoorOpen="M12,3C10.89,3 10,3.89 10,5H3V19H2V21H22V19H21V5C21,3.89 20.11,3 19,3H12M12,5H19V19H12V5M5,11H7V13H5V11Z";var mdiDoorbell="M12 10C10.9 10 10 10.9 10 12S10.9 14 12 14 14 13.1 14 12 13.1 10 12 10M16 2H8C6.9 2 6 2.9 6 4V20C6 21.1 6.9 22 8 22H16C17.1 22 18 21.1 18 20V4C18 2.9 17.1 2 16 2M16 20H8V4H16V20Z";var mdiDoorbellVideo="M14 15C14 16.11 13.11 17 12 17S10 16.11 10 15 10.9 13 12 13 14 13.9 14 15M18 4V20C18 21.1 17.11 22 16 22H8C6.9 22 6 21.11 6 20V4C6 2.9 6.9 2 8 2H16C17.11 2 18 2.9 18 4M10.5 7C10.5 7.83 11.17 8.5 12 8.5S13.5 7.83 13.5 7 12.83 5.5 12 5.5 10.5 6.17 10.5 7M16 10H8V20H16V10Z";var mdiEthernet="M7,15H9V18H11V15H13V18H15V15H17V18H19V9H15V6H9V9H5V18H7V15M4.38,3H19.63C20.94,3 22,4.06 22,5.38V19.63A2.37,2.37 0 0,1 19.63,22H4.38C3.06,22 2,20.94 2,19.63V5.38C2,4.06 3.06,3 4.38,3Z";var mdiEvStation="M19.77,7.23L19.78,7.22L16.06,3.5L15,4.56L17.11,6.67C16.17,7.03 15.5,7.93 15.5,9A2.5,2.5 0 0,0 18,11.5C18.36,11.5 18.69,11.42 19,11.29V18.5A1,1 0 0,1 18,19.5A1,1 0 0,1 17,18.5V14A2,2 0 0,0 15,12H14V5A2,2 0 0,0 12,3H6A2,2 0 0,0 4,5V21H14V13.5H15.5V18.5A2.5,2.5 0 0,0 18,21A2.5,2.5 0 0,0 20.5,18.5V9C20.5,8.31 20.22,7.68 19.77,7.23M18,10A1,1 0 0,1 17,9A1,1 0 0,1 18,8A1,1 0 0,1 19,9A1,1 0 0,1 18,10M8,18V13.5H6L10,6V11H12L8,18Z";var mdiEyeOff="M11.83,9L15,12.16C15,12.11 15,12.05 15,12A3,3 0 0,0 12,9C11.94,9 11.89,9 11.83,9M7.53,9.8L9.08,11.35C9.03,11.56 9,11.77 9,12A3,3 0 0,0 12,15C12.22,15 12.44,14.97 12.65,14.92L14.2,16.47C13.53,16.8 12.79,17 12,17A5,5 0 0,1 7,12C7,11.21 7.2,10.47 7.53,9.8M2,4.27L4.28,6.55L4.73,7C3.08,8.3 1.78,10 1,12C2.73,16.39 7,19.5 12,19.5C13.55,19.5 15.03,19.2 16.38,18.66L16.81,19.08L19.73,22L21,20.73L3.27,3M12,7A5,5 0 0,1 17,12C17,12.64 16.87,13.26 16.64,13.82L19.57,16.75C21.07,15.5 22.27,13.86 23,12C21.27,7.61 17,4.5 12,4.5C10.6,4.5 9.26,4.75 8,5.2L10.17,7.35C10.74,7.13 11.35,7 12,7Z";var mdiFan="M12,11A1,1 0 0,0 11,12A1,1 0 0,0 12,13A1,1 0 0,0 13,12A1,1 0 0,0 12,11M12.5,2C17,2 17.11,5.57 14.75,6.75C13.76,7.24 13.32,8.29 13.13,9.22C13.61,9.42 14.03,9.73 14.35,10.13C18.05,8.13 22.03,8.92 22.03,12.5C22.03,17 18.46,17.1 17.28,14.73C16.78,13.74 15.72,13.3 14.79,13.11C14.59,13.59 14.28,14 13.88,14.34C15.87,18.03 15.08,22 11.5,22C7,22 6.91,18.42 9.27,17.24C10.25,16.75 10.69,15.71 10.89,14.79C10.4,14.59 9.97,14.27 9.65,13.87C5.96,15.85 2,15.07 2,11.5C2,7 5.56,6.89 6.74,9.26C7.24,10.25 8.29,10.68 9.22,10.87C9.41,10.39 9.73,9.97 10.14,9.65C8.15,5.96 8.94,2 12.5,2Z";var mdiFile="M13,9V3.5L18.5,9M6,2C4.89,2 4,2.89 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6Z";var mdiFitToScreen="M17 4H20C21.1 4 22 4.9 22 6V8H20V6H17V4M4 8V6H7V4H4C2.9 4 2 4.9 2 6V8H4M20 16V18H17V20H20C21.1 20 22 19.1 22 18V16H20M7 18H4V16H2V18C2 19.1 2.9 20 4 20H7V18M18 8H6V16H18V8Z";var mdiFridge="M7,2H17A2,2 0 0,1 19,4V9H5V4A2,2 0 0,1 7,2M19,19A2,2 0 0,1 17,21V22H15V21H9V22H7V21A2,2 0 0,1 5,19V10H19V19M8,5V7H10V5H8M8,12V15H10V12H8Z";var mdiGauge="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,4A8,8 0 0,1 20,12C20,14.4 19,16.5 17.3,18C15.9,16.7 14,16 12,16C10,16 8.2,16.7 6.7,18C5,16.5 4,14.4 4,12A8,8 0 0,1 12,4M14,5.89C13.62,5.9 13.26,6.15 13.1,6.54L11.81,9.77L11.71,10C11,10.13 10.41,10.6 10.14,11.26C9.73,12.29 10.23,13.45 11.26,13.86C12.29,14.27 13.45,13.77 13.86,12.74C14.12,12.08 14,11.32 13.57,10.76L13.67,10.5L14.96,7.29L14.97,7.26C15.17,6.75 14.92,6.17 14.41,5.96C14.28,5.91 14.15,5.89 14,5.89M10,6A1,1 0 0,0 9,7A1,1 0 0,0 10,8A1,1 0 0,0 11,7A1,1 0 0,0 10,6M7,9A1,1 0 0,0 6,10A1,1 0 0,0 7,11A1,1 0 0,0 8,10A1,1 0 0,0 7,9M17,9A1,1 0 0,0 16,10A1,1 0 0,0 17,11A1,1 0 0,0 18,10A1,1 0 0,0 17,9Z";var mdiGraphOutline="M19.5 17C19.36 17 19.24 17 19.11 17.04L17.5 13.8C17.95 13.35 18.25 12.71 18.25 12C18.25 10.62 17.13 9.5 15.75 9.5C15.61 9.5 15.5 9.5 15.35 9.54L13.74 6.3C14.21 5.84 14.5 5.21 14.5 4.5C14.5 3.12 13.38 2 12 2S9.5 3.12 9.5 4.5C9.5 5.2 9.79 5.84 10.26 6.29L8.65 9.54C8.5 9.5 8.39 9.5 8.25 9.5C6.87 9.5 5.75 10.62 5.75 12C5.75 12.71 6.04 13.34 6.5 13.79L4.89 17.04C4.76 17 4.64 17 4.5 17C3.12 17 2 18.12 2 19.5C2 20.88 3.12 22 4.5 22S7 20.88 7 19.5C7 18.8 6.71 18.16 6.24 17.71L7.86 14.46C8 14.5 8.12 14.5 8.25 14.5C8.38 14.5 8.5 14.5 8.63 14.46L10.26 17.71C9.79 18.16 9.5 18.8 9.5 19.5C9.5 20.88 10.62 22 12 22S14.5 20.88 14.5 19.5C14.5 18.12 13.38 17 12 17C11.87 17 11.74 17 11.61 17.04L10 13.8C10.45 13.35 10.75 12.71 10.75 12C10.75 11.3 10.46 10.67 10 10.21L11.61 6.96C11.74 7 11.87 7 12 7C12.13 7 12.26 7 12.39 6.96L14 10.21C13.54 10.66 13.25 11.3 13.25 12C13.25 13.38 14.37 14.5 15.75 14.5C15.88 14.5 16 14.5 16.13 14.46L17.76 17.71C17.29 18.16 17 18.8 17 19.5C17 20.88 18.12 22 19.5 22S22 20.88 22 19.5C22 18.12 20.88 17 19.5 17M4.5 20.5C3.95 20.5 3.5 20.05 3.5 19.5S3.95 18.5 4.5 18.5 5.5 18.95 5.5 19.5 5.05 20.5 4.5 20.5M13 19.5C13 20.05 12.55 20.5 12 20.5S11 20.05 11 19.5 11.45 18.5 12 18.5 13 18.95 13 19.5M7.25 12C7.25 11.45 7.7 11 8.25 11S9.25 11.45 9.25 12 8.8 13 8.25 13 7.25 12.55 7.25 12M11 4.5C11 3.95 11.45 3.5 12 3.5S13 3.95 13 4.5 12.55 5.5 12 5.5 11 5.05 11 4.5M14.75 12C14.75 11.45 15.2 11 15.75 11S16.75 11.45 16.75 12 16.3 13 15.75 13 14.75 12.55 14.75 12M19.5 20.5C18.95 20.5 18.5 20.05 18.5 19.5S18.95 18.5 19.5 18.5 20.5 18.95 20.5 19.5 20.05 20.5 19.5 20.5Z";var mdiHeatPump="M19 3H5C3.9 3 3 3.9 3 5V19C3 20.1 3.9 21 5 21H19C20.1 21 21 20.1 21 19V5C21 3.9 20.1 3 19 3M12.75 7.08C13.57 7.2 14.32 7.5 14.95 8L12.75 10.19V7.08M11.25 7.08V10.19L9.05 8C9.68 7.5 10.43 7.2 11.25 7.08M8 9.05L10.19 11.25H7.08C7.2 10.43 7.5 9.68 8 9.05M7.08 12.75H10.19L8 14.95C7.5 14.32 7.2 13.57 7.08 12.75M11.25 16.92C10.43 16.8 9.68 16.5 9.05 16L11.25 13.81V16.92M12 13C11.45 13 11 12.55 11 12S11.45 11 12 11 13 11.45 13 12 12.55 13 12 13M12.75 16.92V13.81L14.95 16C14.32 16.5 13.57 16.8 12.75 16.92M16 14.95L13.81 12.75H16.92C16.8 13.57 16.5 14.32 16 14.95M13.81 11.25L16 9.05C16.5 9.69 16.8 10.44 16.92 11.25H13.81Z";var mdiHelp="M10,19H13V22H10V19M12,2C17.35,2.22 19.68,7.62 16.5,11.67C15.67,12.67 14.33,13.33 13.67,14.17C13,15 13,16 13,17H10C10,15.33 10,13.92 10.67,12.92C11.33,11.92 12.67,11.33 13.5,10.67C15.92,8.43 15.32,5.26 12,5A3,3 0 0,0 9,8H6A6,6 0 0,1 12,2Z";var mdiHome="M10,20V14H14V20H19V12H22L12,3L2,12H5V20H10Z";var mdiLeaf="M17,8C8,10 5.9,16.17 3.82,21.34L5.71,22L6.66,19.7C7.14,19.87 7.64,20 8,20C19,20 22,3 22,3C21,5 14,5.25 9,6.25C4,7.25 2,11.5 2,13.5C2,15.5 3.75,17.25 3.75,17.25C7,8 17,8 17,8Z";var mdiLightbulb="M12,2A7,7 0 0,0 5,9C5,11.38 6.19,13.47 8,14.74V17A1,1 0 0,0 9,18H15A1,1 0 0,0 16,17V14.74C17.81,13.47 19,11.38 19,9A7,7 0 0,0 12,2M9,21A1,1 0 0,0 10,22H14A1,1 0 0,0 15,21V20H9V21Z";var mdiLink="M3.9,12C3.9,10.29 5.29,8.9 7,8.9H11V7H7A5,5 0 0,0 2,12A5,5 0 0,0 7,17H11V15.1H7C5.29,15.1 3.9,13.71 3.9,12M8,13H16V11H8V13M17,7H13V8.9H17C18.71,8.9 20.1,10.29 20.1,12C20.1,13.71 18.71,15.1 17,15.1H13V17H17A5,5 0 0,0 22,12A5,5 0 0,0 17,7Z";var mdiLoading="M12,4V2A10,10 0 0,0 2,12H4A8,8 0 0,1 12,4Z";var mdiLock="M12,17A2,2 0 0,0 14,15C14,13.89 13.1,13 12,13A2,2 0 0,0 10,15A2,2 0 0,0 12,17M18,8A2,2 0 0,1 20,10V20A2,2 0 0,1 18,22H6A2,2 0 0,1 4,20V10C4,8.89 4.9,8 6,8H7V6A5,5 0 0,1 12,1A5,5 0 0,1 17,6V8H18M12,3A3,3 0 0,0 9,6V8H15V6A3,3 0 0,0 12,3Z";var mdiLogout="M17 7L15.59 8.41L18.17 11H8V13H18.17L15.59 15.58L17 17L22 12M4 5H12V3H4C2.9 3 2 3.9 2 5V19C2 20.1 2.9 21 4 21H12V19H4V5Z";var mdiMagnifyMinus="M9,2A7,7 0 0,1 16,9C16,10.57 15.5,12 14.61,13.19L15.41,14H16L22,20L20,22L14,16V15.41L13.19,14.61C12,15.5 10.57,16 9,16A7,7 0 0,1 2,9A7,7 0 0,1 9,2M5,8V10H13V8H5Z";var mdiMagnifyPlus="M9,2A7,7 0 0,1 16,9C16,10.57 15.5,12 14.61,13.19L15.41,14H16L22,20L20,22L14,16V15.41L13.19,14.61C12,15.5 10.57,16 9,16A7,7 0 0,1 2,9A7,7 0 0,1 9,2M8,5V8H5V10H8V13H10V10H13V8H10V5H8Z";var mdiMeterElectric="M12 2C7.04 2 3 6.04 3 11C3 14.91 5.5 18.24 9 19.47V22H11V19.94C11.33 20 11.66 20 12 20S12.67 20 13 19.94V22H15V19.47C18.5 18.23 21 14.9 21 11C21 6.04 16.96 2 12 2M14.25 14L11.25 17L9.75 15.5L11 14.25L9.75 13L12.75 10L14.25 11.5L13 12.75L14.25 14M16 9H8V7H16V9Z";var mdiMicrowave="M4,5A2,2 0 0,0 2,7V17A2,2 0 0,0 4,19H20A2,2 0 0,0 22,17V7A2,2 0 0,0 20,5H4M4,7H16V17H4V7M19,7A1,1 0 0,1 20,8A1,1 0 0,1 19,9A1,1 0 0,1 18,8A1,1 0 0,1 19,7M13,9V15H15V9H13M19,11A1,1 0 0,1 20,12A1,1 0 0,1 19,13A1,1 0 0,1 18,12A1,1 0 0,1 19,11Z";var mdiMotionSensor="M10,0.2C9,0.2 8.2,1 8.2,2C8.2,3 9,3.8 10,3.8C11,3.8 11.8,3 11.8,2C11.8,1 11,0.2 10,0.2M15.67,1A7.33,7.33 0 0,0 23,8.33V7A6,6 0 0,1 17,1H15.67M18.33,1C18.33,3.58 20.42,5.67 23,5.67V4.33C21.16,4.33 19.67,2.84 19.67,1H18.33M21,1A2,2 0 0,0 23,3V1H21M7.92,4.03C7.75,4.03 7.58,4.06 7.42,4.11L2,5.8V11H3.8V7.33L5.91,6.67L2,22H3.8L6.67,13.89L9,17V22H10.8V15.59L8.31,11.05L9.04,8.18L10.12,10H15V8.2H11.38L9.38,4.87C9.08,4.37 8.54,4.03 7.92,4.03Z";var mdiPause="M14,19H18V5H14M6,19H10V5H6V19Z";var mdiPencil="M20.71,7.04C21.1,6.65 21.1,6 20.71,5.63L18.37,3.29C18,2.9 17.35,2.9 16.96,3.29L15.12,5.12L18.87,8.87M3,17.25V21H6.75L17.81,9.93L14.06,6.18L3,17.25Z";var mdiPlay="M8,5.14V19.14L19,12.14L8,5.14Z";var mdiPlus="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z";var mdiPowerPlug="M16,7V3H14V7H10V3H8V7H8C7,7 6,8 6,9V14.5L9.5,18V21H14.5V18L18,14.5V9C18,8 17,7 16,7Z";var mdiPump="M2 21V15H3.5C3.18 14.06 3 13.05 3 12C3 7.03 7.03 3 12 3H22V9H20.5C20.82 9.94 21 10.95 21 12C21 16.97 16.97 21 12 21H2M5 12C5 13.28 5.34 14.47 5.94 15.5L9.4 13.5C9.15 13.06 9 12.55 9 12C9 11.35 9.21 10.75 9.56 10.26L6.3 7.93C5.5 9.08 5 10.5 5 12M12 19C14.59 19 16.85 17.59 18.06 15.5L14.6 13.5C14.08 14.4 13.11 15 12 15L11.71 15L11.33 18.97L12 19M12 9C13.21 9 14.26 9.72 14.73 10.76L18.37 9.1C17.27 6.68 14.83 5 12 5V9M12 11C11.45 11 11 11.45 11 12C11 12.55 11.45 13 12 13C12.55 13 13 12.55 13 12C13 11.45 12.55 11 12 11Z";var mdiRefresh="M17.65,6.35C16.2,4.9 14.21,4 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20C15.73,20 18.84,17.45 19.73,14H17.65C16.83,16.33 14.61,18 12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6C13.66,6 15.14,6.69 16.22,7.78L13,11H20V4L17.65,6.35Z";var mdiRemote="M12,0C8.96,0 6.21,1.23 4.22,3.22L5.63,4.63C7.26,3 9.5,2 12,2C14.5,2 16.74,3 18.36,4.64L19.77,3.23C17.79,1.23 15.04,0 12,0M7.05,6.05L8.46,7.46C9.37,6.56 10.62,6 12,6C13.38,6 14.63,6.56 15.54,7.46L16.95,6.05C15.68,4.78 13.93,4 12,4C10.07,4 8.32,4.78 7.05,6.05M12,15A2,2 0 0,1 10,13A2,2 0 0,1 12,11A2,2 0 0,1 14,13A2,2 0 0,1 12,15M15,9H9A1,1 0 0,0 8,10V22A1,1 0 0,0 9,23H15A1,1 0 0,0 16,22V10A1,1 0 0,0 15,9Z";var mdiRobotVacuum="M12,2C14.65,2 17.19,3.06 19.07,4.93L17.65,6.35C16.15,4.85 14.12,4 12,4C9.88,4 7.84,4.84 6.35,6.35L4.93,4.93C6.81,3.06 9.35,2 12,2M3.66,6.5L5.11,7.94C4.39,9.17 4,10.57 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12C20,10.57 19.61,9.17 18.88,7.94L20.34,6.5C21.42,8.12 22,10.04 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12C2,10.04 2.58,8.12 3.66,6.5M12,6A6,6 0 0,1 18,12C18,13.59 17.37,15.12 16.24,16.24L14.83,14.83C14.08,15.58 13.06,16 12,16C10.94,16 9.92,15.58 9.17,14.83L7.76,16.24C6.63,15.12 6,13.59 6,12A6,6 0 0,1 12,6M12,8A1,1 0 0,0 11,9A1,1 0 0,0 12,10A1,1 0 0,0 13,9A1,1 0 0,0 12,8Z";var mdiRouter="M12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C17.5 22 22 17.5 22 12C22 6.5 17.5 2 12 2M12 20C7.58 20 4 16.42 4 12C4 7.58 7.58 4 12 4C16.42 4 20 7.58 20 12C20 16.42 16.42 20 12 20M13 13V16H15L12 19L9 16H11V13M5 13H8V15L11 12L8 9V11H5M11 11V8H9L12 5L15 8H13V11M19 11H16V9L13 12L16 15V13H19";var mdiRouterWireless="M20.2,5.9L21,5.1C19.6,3.7 17.8,3 16,3C14.2,3 12.4,3.7 11,5.1L11.8,5.9C13,4.8 14.5,4.2 16,4.2C17.5,4.2 19,4.8 20.2,5.9M19.3,6.7C18.4,5.8 17.2,5.3 16,5.3C14.8,5.3 13.6,5.8 12.7,6.7L13.5,7.5C14.2,6.8 15.1,6.5 16,6.5C16.9,6.5 17.8,6.8 18.5,7.5L19.3,6.7M19,13H17V9H15V13H5A2,2 0 0,0 3,15V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V15A2,2 0 0,0 19,13M8,18H6V16H8V18M11.5,18H9.5V16H11.5V18M15,18H13V16H15V18Z";var mdiShareVariant="M18,16.08C17.24,16.08 16.56,16.38 16.04,16.85L8.91,12.7C8.96,12.47 9,12.24 9,12C9,11.76 8.96,11.53 8.91,11.3L15.96,7.19C16.5,7.69 17.21,8 18,8A3,3 0 0,0 21,5A3,3 0 0,0 18,2A3,3 0 0,0 15,5C15,5.24 15.04,5.47 15.09,5.7L8.04,9.81C7.5,9.31 6.79,9 6,9A3,3 0 0,0 3,12A3,3 0 0,0 6,15C6.79,15 7.5,14.69 8.04,14.19L15.16,18.34C15.11,18.55 15.08,18.77 15.08,19C15.08,20.61 16.39,21.91 18,21.91C19.61,21.91 20.92,20.61 20.92,19A2.92,2.92 0 0,0 18,16.08Z";var mdiSignalCellular1="M19.5,5.5V18.5H17.5V5.5H19.5M12.5,10.5V18.5H10.5V10.5H12.5M21,4H16V20H21V4M14,9H9V20H14V9M7,14H2V20H7V14Z";var mdiSignalCellular2="M19.5,5.5V18.5H17.5V5.5H19.5M21,4H16V20H21V4M14,9H9V20H14V9M7,14H2V20H7V14Z";var mdiSignalCellular3="M21,4H16V20H21V4M14,9H9V20H14V9M7,14H2V20H7V14Z";var mdiSmokeDetector="M12,18A6,6 0 0,0 18,12C18,8.68 15.31,6 12,6C8.68,6 6,8.68 6,12A6,6 0 0,0 12,18M19,3A2,2 0 0,1 21,5V19A2,2 0 0,1 19,21H5C3.89,21 3,20.1 3,19V5C3,3.89 3.89,3 5,3H19M8,12A4,4 0 0,1 12,8A4,4 0 0,1 16,12A4,4 0 0,1 12,16A4,4 0 0,1 8,12Z";var mdiSnowflakeAlert="M16.46,9.41L13,7.38V5.12L14.71,3.41L13.29,2L12,3.29L10.71,2L9.29,3.41L11,5.12V7.38L8.5,8.82L6.5,7.69L5.92,5.36L4,5.88L4.47,7.65L2.7,8.12L3.22,10.05L5.55,9.43L7.55,10.56V13.45L5.55,14.58L3.22,13.96L2.7,15.89L4.47,16.36L4,18.12L5.93,18.64L6.55,16.31L8.55,15.18L11,16.62V18.88L9.29,20.59L10.71,22L12,20.71L13.29,22L14.7,20.59L13,18.88V16.62L16.46,14.61M9.5,10.56L12,9.11L14.5,10.56V13.44L12,14.89L9.5,13.44M19,13V7H21V13H19M19,17V15H21V17H19Z";var mdiSolarPower="M11.45,2V5.55L15,3.77L11.45,2M10.45,8L8,10.46L11.75,11.71L10.45,8M2,11.45L3.77,15L5.55,11.45H2M10,2H2V10C2.57,10.17 3.17,10.25 3.77,10.25C7.35,10.26 10.26,7.35 10.27,3.75C10.26,3.16 10.17,2.57 10,2M17,22V16H14L19,7V13H22L17,22Z";var mdiSpeaker="M12,12A3,3 0 0,0 9,15A3,3 0 0,0 12,18A3,3 0 0,0 15,15A3,3 0 0,0 12,12M12,20A5,5 0 0,1 7,15A5,5 0 0,1 12,10A5,5 0 0,1 17,15A5,5 0 0,1 12,20M12,4A2,2 0 0,1 14,6A2,2 0 0,1 12,8C10.89,8 10,7.1 10,6C10,4.89 10.89,4 12,4M17,2H7C5.89,2 5,2.89 5,4V20A2,2 0 0,0 7,22H17A2,2 0 0,0 19,20V4C19,2.89 18.1,2 17,2Z";var mdiSprinkler="M11 7H13V9H11V7M5 22H9V10H5V22M14 11H16V9H14V11M17 10H19V8H17V10M17 5V7H19V5H17M14 8H16V6H14V8M17 13H19V11H17V13M5 7H5.33L6 9H8L8.67 7H9V6H5V7Z";var mdiStove="M6,14H8L11,17H9L6,14M4,4H5V3A1,1 0 0,1 6,2H10A1,1 0 0,1 11,3V4H13V3A1,1 0 0,1 14,2H18A1,1 0 0,1 19,3V4H20A2,2 0 0,1 22,6V19A2,2 0 0,1 20,21V22H17V21H7V22H4V21A2,2 0 0,1 2,19V6A2,2 0 0,1 4,4M18,7A1,1 0 0,1 19,8A1,1 0 0,1 18,9A1,1 0 0,1 17,8A1,1 0 0,1 18,7M14,7A1,1 0 0,1 15,8A1,1 0 0,1 14,9A1,1 0 0,1 13,8A1,1 0 0,1 14,7M20,6H4V10H20V6M4,19H20V12H4V19M6,7A1,1 0 0,1 7,8A1,1 0 0,1 6,9A1,1 0 0,1 5,8A1,1 0 0,1 6,7M13,14H15L18,17H16L13,14Z";var mdiTelevision="M21,17H3V5H21M21,3H3A2,2 0 0,0 1,5V17A2,2 0 0,0 3,19H8V21H16V19H21A2,2 0 0,0 23,17V5A2,2 0 0,0 21,3Z";var mdiThermometer="M15 13V5A3 3 0 0 0 9 5V13A5 5 0 1 0 15 13M12 4A1 1 0 0 1 13 5V8H11V5A1 1 0 0 1 12 4Z";var mdiToggleSwitch="M17,7H7A5,5 0 0,0 2,12A5,5 0 0,0 7,17H17A5,5 0 0,0 22,12A5,5 0 0,0 17,7M17,15A3,3 0 0,1 14,12A3,3 0 0,1 17,9A3,3 0 0,1 20,12A3,3 0 0,1 17,15Z";var mdiTrashCan="M9,3V4H4V6H5V19A2,2 0 0,0 7,21H17A2,2 0 0,0 19,19V6H20V4H15V3H9M9,8H11V17H9V8M13,8H15V17H13V8Z";var mdiTumbleDryer="M6,2H18A2,2 0 0,1 20,4V20A2,2 0 0,1 18,22H6A2,2 0 0,1 4,20V4A2,2 0 0,1 6,2M7,4A1,1 0 0,0 6,5A1,1 0 0,0 7,6A1,1 0 0,0 8,5A1,1 0 0,0 7,4M10,4A1,1 0 0,0 9,5A1,1 0 0,0 10,6A1,1 0 0,0 11,5A1,1 0 0,0 10,4M12,8A6,6 0 0,0 6,14A6,6 0 0,0 12,20A6,6 0 0,0 18,14A6,6 0 0,0 12,8M8.11,10.5H10C9.76,11.88 10,12.67 10.58,13.29C11.68,14.36 12.16,15.71 11.89,17.5H10C10.24,16.12 10,15.33 9.42,14.71C8.32,13.64 7.85,12.29 8.11,10.5M12.11,10.5H14C13.76,11.88 14,12.67 14.58,13.29C15.68,14.36 16.16,15.71 15.89,17.5H14C14.24,16.12 14,15.33 13.42,14.71C12.32,13.64 11.85,12.29 12.11,10.5Z";var mdiUpdate="M21,10.12H14.22L16.96,7.3C14.23,4.6 9.81,4.5 7.08,7.2C4.35,9.91 4.35,14.28 7.08,17C9.81,19.7 14.23,19.7 16.96,17C18.32,15.65 19,14.08 19,12.1H21C21,14.08 20.12,16.65 18.36,18.39C14.85,21.87 9.15,21.87 5.64,18.39C2.14,14.92 2.11,9.28 5.62,5.81C9.13,2.34 14.76,2.34 18.27,5.81L21,3V10.12M12.5,8V12.25L16,14.33L15.28,15.54L11,13V8H12.5Z";var mdiWashingMachine="M14.83,11.17C16.39,12.73 16.39,15.27 14.83,16.83C13.27,18.39 10.73,18.39 9.17,16.83L14.83,11.17M6,2H18A2,2 0 0,1 20,4V20A2,2 0 0,1 18,22H6A2,2 0 0,1 4,20V4A2,2 0 0,1 6,2M7,4A1,1 0 0,0 6,5A1,1 0 0,0 7,6A1,1 0 0,0 8,5A1,1 0 0,0 7,4M10,4A1,1 0 0,0 9,5A1,1 0 0,0 10,6A1,1 0 0,0 11,5A1,1 0 0,0 10,4M12,8A6,6 0 0,0 6,14A6,6 0 0,0 12,20A6,6 0 0,0 18,14A6,6 0 0,0 12,8Z";var mdiWater="M12,20A6,6 0 0,1 6,14C6,10 12,3.25 12,3.25C12,3.25 18,10 18,14A6,6 0 0,1 12,20Z";var mdiWaterBoiler="M8 2C6.89 2 6 2.89 6 4V16C6 17.11 6.89 18 8 18H9V20H6V22H9C10.11 22 11 21.11 11 20V18H13V20C13 21.11 13.89 22 15 22H18V20H15V18H16C17.11 18 18 17.11 18 16V4C18 2.89 17.11 2 16 2H8M12 4.97A2 2 0 0 1 14 6.97A2 2 0 0 1 12 8.97A2 2 0 0 1 10 6.97A2 2 0 0 1 12 4.97M10 14.5H14V16H10V14.5Z";var mdiWaterPercent="M12,3.25C12,3.25 6,10 6,14C6,17.32 8.69,20 12,20A6,6 0 0,0 18,14C18,10 12,3.25 12,3.25M14.47,9.97L15.53,11.03L9.53,17.03L8.47,15.97M9.75,10A1.25,1.25 0 0,1 11,11.25A1.25,1.25 0 0,1 9.75,12.5A1.25,1.25 0 0,1 8.5,11.25A1.25,1.25 0 0,1 9.75,10M14.25,14.5A1.25,1.25 0 0,1 15.5,15.75A1.25,1.25 0 0,1 14.25,17A1.25,1.25 0 0,1 13,15.75A1.25,1.25 0 0,1 14.25,14.5Z";var mdiWeatherNight="M17.75,4.09L15.22,6.03L16.13,9.09L13.5,7.28L10.87,9.09L11.78,6.03L9.25,4.09L12.44,4L13.5,1L14.56,4L17.75,4.09M21.25,11L19.61,12.25L20.2,14.23L18.5,13.06L16.8,14.23L17.39,12.25L15.75,11L17.81,10.95L18.5,9L19.19,10.95L21.25,11M18.97,15.95C19.8,15.87 20.69,17.05 20.16,17.8C19.84,18.25 19.5,18.67 19.08,19.07C15.17,23 8.84,23 4.94,19.07C1.03,15.17 1.03,8.83 4.94,4.93C5.34,4.53 5.76,4.17 6.21,3.85C6.96,3.32 8.14,4.21 8.06,5.04C7.79,7.9 8.75,10.87 10.95,13.06C13.14,15.26 16.1,16.22 18.97,15.95M17.33,17.97C14.5,17.81 11.7,16.64 9.53,14.5C7.36,12.31 6.2,9.5 6.04,6.68C3.23,9.82 3.34,14.64 6.35,17.66C9.37,20.67 14.19,20.78 17.33,17.97Z";var mdiWeatherRainy="M6,14.03A1,1 0 0,1 7,15.03C7,15.58 6.55,16.03 6,16.03C3.24,16.03 1,13.79 1,11.03C1,8.27 3.24,6.03 6,6.03C7,3.68 9.3,2.03 12,2.03C15.43,2.03 18.24,4.69 18.5,8.06L19,8.03A4,4 0 0,1 23,12.03C23,14.23 21.21,16.03 19,16.03H18C17.45,16.03 17,15.58 17,15.03C17,14.47 17.45,14.03 18,14.03H19A2,2 0 0,0 21,12.03A2,2 0 0,0 19,10.03H17V9.03C17,6.27 14.76,4.03 12,4.03C9.5,4.03 7.45,5.84 7.06,8.21C6.73,8.09 6.37,8.03 6,8.03A3,3 0 0,0 3,11.03A3,3 0 0,0 6,14.03M12,14.15C12.18,14.39 12.37,14.66 12.56,14.94C13,15.56 14,17.03 14,18C14,19.11 13.1,20 12,20A2,2 0 0,1 10,18C10,17.03 11,15.56 11.44,14.94C11.63,14.66 11.82,14.4 12,14.15M12,11.03L11.5,11.59C11.5,11.59 10.65,12.55 9.79,13.81C8.93,15.06 8,16.56 8,18A4,4 0 0,0 12,22A4,4 0 0,0 16,18C16,16.56 15.07,15.06 14.21,13.81C13.35,12.55 12.5,11.59 12.5,11.59";var mdiWeatherSunny="M12,7A5,5 0 0,1 17,12A5,5 0 0,1 12,17A5,5 0 0,1 7,12A5,5 0 0,1 12,7M12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15A3,3 0 0,0 15,12A3,3 0 0,0 12,9M12,2L14.39,5.42C13.65,5.15 12.84,5 12,5C11.16,5 10.35,5.15 9.61,5.42L12,2M3.34,7L7.5,6.65C6.9,7.16 6.36,7.78 5.94,8.5C5.5,9.24 5.25,10 5.11,10.79L3.34,7M3.36,17L5.12,13.23C5.26,14 5.53,14.78 5.95,15.5C6.37,16.24 6.91,16.86 7.5,17.37L3.36,17M20.65,7L18.88,10.79C18.74,10 18.47,9.23 18.05,8.5C17.63,7.78 17.1,7.15 16.5,6.64L20.65,7M20.64,17L16.5,17.36C17.09,16.85 17.62,16.22 18.04,15.5C18.46,14.77 18.73,14 18.87,13.21L20.64,17M12,22L9.59,18.56C10.33,18.83 11.14,19 12,19C12.82,19 13.63,18.83 14.37,18.56L12,22Z";var mdiWifi="M12,21L15.6,16.2C14.6,15.45 13.35,15 12,15C10.65,15 9.4,15.45 8.4,16.2L12,21M12,3C7.95,3 4.21,4.34 1.2,6.6L3,9C5.5,7.12 8.62,6 12,6C15.38,6 18.5,7.12 21,9L22.8,6.6C19.79,4.34 16.05,3 12,3M12,9C9.3,9 6.81,9.89 4.8,11.4L6.6,13.8C8.1,12.67 9.97,12 12,12C14.03,12 15.9,12.67 17.4,13.8L19.2,11.4C17.19,9.89 14.7,9 12,9Z";
238
238
 
239
239
  /**
240
240
  * @license
@@ -1080,12 +1080,12 @@ function o$3(o) {
1080
1080
  */
1081
1081
  const clientContext = n$6("client");
1082
1082
 
1083
- var __defProp$f = Object.defineProperty;
1083
+ var __defProp$g = Object.defineProperty;
1084
1084
  var __getOwnPropDesc$i = Object.getOwnPropertyDescriptor;
1085
1085
  var __decorateClass$k = (decorators, target, key, kind) => {
1086
1086
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$i(target, key) : target;
1087
1087
  for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
1088
- if (kind && result) __defProp$f(target, key, result);
1088
+ if (kind && result) __defProp$g(target, key, result);
1089
1089
  return result;
1090
1090
  };
1091
1091
  let HaSvgIcon = class extends i$4 {
@@ -4025,7 +4025,7 @@ MdListItem = __decorate([t$1('md-list-item')], MdListItem);
4025
4025
  */
4026
4026
  const showSettingsDialog = async client => {
4027
4027
  var _document$querySelect;
4028
- await import('./settings-dialog-Cs2xMsXb.js');
4028
+ await import('./settings-dialog-BMFhom0W.js');
4029
4029
  const dialog = document.createElement("settings-dialog");
4030
4030
  dialog.client = client;
4031
4031
  (_document$querySelect = document.querySelector("matter-dashboard-app")) === null || _document$querySelect === void 0 || _document$querySelect.renderRoot.appendChild(dialog);
@@ -4114,12 +4114,12 @@ const notFoundStyles = i$7`
4114
4114
  }
4115
4115
  `;
4116
4116
 
4117
- var __defProp$e = Object.defineProperty;
4117
+ var __defProp$f = Object.defineProperty;
4118
4118
  var __getOwnPropDesc$h = Object.getOwnPropertyDescriptor;
4119
4119
  var __decorateClass$j = (decorators, target, key, kind) => {
4120
4120
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$h(target, key) : target;
4121
4121
  for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
4122
- if (kind && result) __defProp$e(target, key, result);
4122
+ if (kind && result) __defProp$f(target, key, result);
4123
4123
  return result;
4124
4124
  };
4125
4125
  let DashboardHeader = class extends i$4 {
@@ -19697,7 +19697,7 @@ const clusters = {
19697
19697
  * SPDX-License-Identifier: Apache-2.0
19698
19698
  */
19699
19699
  const showDialogBox = async (type, dialogParams) => {
19700
- await import('./dialog-box-DjyfULWB.js');
19700
+ await import('./dialog-box-D9vS2SmP.js');
19701
19701
  return new Promise(resolve => {
19702
19702
  const dialog = document.createElement("dialog-box");
19703
19703
  dialog.params = dialogParams;
@@ -19716,7 +19716,7 @@ const showPromptDialog = dialogParams => showDialogBox("prompt", dialogParams);
19716
19716
  */
19717
19717
  const showAttributeWriteDialog = async options => {
19718
19718
  var _document$querySelect;
19719
- await import('./attribute-write-dialog-g4B6BoRt.js');
19719
+ await import('./attribute-write-dialog-DlMTUiLK.js');
19720
19720
  const dialog = document.createElement("attribute-write-dialog");
19721
19721
  dialog.client = options.client;
19722
19722
  dialog.nodeId = options.nodeId;
@@ -19735,7 +19735,7 @@ const showAttributeWriteDialog = async options => {
19735
19735
  */
19736
19736
  const showCommandInvokeDialog = async options => {
19737
19737
  var _document$querySelect;
19738
- await import('./command-invoke-dialog-D6G704VK.js');
19738
+ await import('./command-invoke-dialog-DO3IyFcm.js');
19739
19739
  const dialog = document.createElement("command-invoke-dialog");
19740
19740
  dialog.client = options.client;
19741
19741
  dialog.nodeId = options.nodeId;
@@ -19908,7 +19908,7 @@ MdTextButton = __decorate([t$1('md-text-button')], MdTextButton);
19908
19908
  */
19909
19909
  const showNodeBindingDialog = async (client, node, endpoint) => {
19910
19910
  var _document$querySelect;
19911
- await import('./node-binding-dialog-9yy2LE3_.js');
19911
+ await import('./node-binding-dialog-B5p-gbim.js');
19912
19912
  const dialog = document.createElement("node-binding-dialog");
19913
19913
  dialog.client = client;
19914
19914
  dialog.node = node;
@@ -20232,6 +20232,10 @@ function createUnknownDeviceIconDataUrl(isRouter = false, isSelected = false) {
20232
20232
  const color = isSelected ? getCssVar("--node-color-selected", "#1976d2") : getCssVar("--node-color-unknown", "#ff9800");
20233
20233
  return createIconDataUrl(iconPath, color);
20234
20234
  }
20235
+ function createBorderRouterIconDataUrl(isSelected = false) {
20236
+ const color = isSelected ? getCssVar("--node-color-selected", "#1976d2") : getCssVar("--md-sys-color-primary", "#03a9f4");
20237
+ return createIconDataUrl(mdiRouterWireless, color);
20238
+ }
20235
20239
  function createWiFiRouterIconDataUrl(isSelected = false) {
20236
20240
  const color = isSelected ? getCssVar("--node-color-selected", "#1976d2") : getCssVar("--node-color-unknown", "#ff9800");
20237
20241
  return createIconDataUrl(mdiWifi, color);
@@ -20295,12 +20299,12 @@ function formatNodeAddressFromAny(fabricIndex, nodeId) {
20295
20299
  return formatNodeAddress(fabricIndex, numericId);
20296
20300
  }
20297
20301
 
20298
- var __defProp$d = Object.defineProperty;
20302
+ var __defProp$e = Object.defineProperty;
20299
20303
  var __getOwnPropDesc$g = Object.getOwnPropertyDescriptor;
20300
20304
  var __decorateClass$i = (decorators, target, key, kind) => {
20301
20305
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$g(target, key) : target;
20302
20306
  for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
20303
- if (kind && result) __defProp$d(target, key, result);
20307
+ if (kind && result) __defProp$e(target, key, result);
20304
20308
  return result;
20305
20309
  };
20306
20310
  function getUniqueClusters(node, endpoint) {
@@ -20430,12 +20434,12 @@ MatterEndpointView = __decorateClass$i([t$1("matter-endpoint-view")], MatterEndp
20430
20434
  */
20431
20435
  const bindingContext = n$6("binding");
20432
20436
 
20433
- var __defProp$c = Object.defineProperty;
20437
+ var __defProp$d = Object.defineProperty;
20434
20438
  var __getOwnPropDesc$f = Object.getOwnPropertyDescriptor;
20435
20439
  var __decorateClass$h = (decorators, target, key, kind) => {
20436
20440
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$f(target, key) : target;
20437
20441
  for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
20438
- if (kind && result) __defProp$c(target, key, result);
20442
+ if (kind && result) __defProp$d(target, key, result);
20439
20443
  return result;
20440
20444
  };
20441
20445
  const UPDATE_STATE_LABELS = {
@@ -20714,11 +20718,11 @@ function getClusterCommandsTag(clusterId) {
20714
20718
  }
20715
20719
 
20716
20720
  var _staticBlock$1;
20717
- var __defProp$b = Object.defineProperty;
20721
+ var __defProp$c = Object.defineProperty;
20718
20722
  var __decorateClass$g = (decorators, target, key, kind) => {
20719
20723
  var result = void 0 ;
20720
20724
  for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (decorator(target, key, result) ) || result;
20721
- if (result) __defProp$b(target, key, result);
20725
+ if (result) __defProp$c(target, key, result);
20722
20726
  return result;
20723
20727
  };
20724
20728
  class BaseClusterCommands extends i$4 {
@@ -22953,12 +22957,12 @@ let MdOutlinedTextField = class MdOutlinedTextField extends OutlinedTextField {
22953
22957
  MdOutlinedTextField.styles = [styles$2, styles$3];
22954
22958
  MdOutlinedTextField = __decorate([t$1('md-outlined-text-field')], MdOutlinedTextField);
22955
22959
 
22956
- var __defProp$a = Object.defineProperty;
22960
+ var __defProp$b = Object.defineProperty;
22957
22961
  var __getOwnPropDesc$e = Object.getOwnPropertyDescriptor;
22958
22962
  var __decorateClass$f = (decorators, target, key, kind) => {
22959
22963
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$e(target, key) : target;
22960
22964
  for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
22961
- if (kind && result) __defProp$a(target, key, result);
22965
+ if (kind && result) __defProp$b(target, key, result);
22962
22966
  return result;
22963
22967
  };
22964
22968
  const CLUSTER_ID$2 = 40;
@@ -23085,12 +23089,12 @@ __decorateClass$f([r$2()], BasicInformationClusterCommands.prototype, "_saving",
23085
23089
  BasicInformationClusterCommands = __decorateClass$f([t$1("basic-information-cluster-commands")], BasicInformationClusterCommands);
23086
23090
  registerClusterCommands(CLUSTER_ID$2, "basic-information-cluster-commands");
23087
23091
 
23088
- var __defProp$9 = Object.defineProperty;
23092
+ var __defProp$a = Object.defineProperty;
23089
23093
  var __getOwnPropDesc$d = Object.getOwnPropertyDescriptor;
23090
23094
  var __decorateClass$e = (decorators, target, key, kind) => {
23091
23095
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$d(target, key) : target;
23092
23096
  for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
23093
- if (kind && result) __defProp$9(target, key, result);
23097
+ if (kind && result) __defProp$a(target, key, result);
23094
23098
  return result;
23095
23099
  };
23096
23100
  const CLUSTER_ID$1 = 8;
@@ -23237,12 +23241,12 @@ let OnOffClusterCommands = class extends BaseClusterCommands {
23237
23241
  OnOffClusterCommands = __decorateClass$d([t$1("on-off-cluster-commands")], OnOffClusterCommands);
23238
23242
  registerClusterCommands(CLUSTER_ID, "on-off-cluster-commands");
23239
23243
 
23240
- var __defProp$8 = Object.defineProperty;
23244
+ var __defProp$9 = Object.defineProperty;
23241
23245
  var __getOwnPropDesc$b = Object.getOwnPropertyDescriptor;
23242
23246
  var __decorateClass$c = (decorators, target, key, kind) => {
23243
23247
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$b(target, key) : target;
23244
23248
  for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
23245
- if (kind && result) __defProp$8(target, key, result);
23249
+ if (kind && result) __defProp$9(target, key, result);
23246
23250
  return result;
23247
23251
  };
23248
23252
  const GLOBAL_ATTRIBUTE_MIN = 65520;
@@ -23807,6 +23811,32 @@ DashboardFooter.styles = i$7`
23807
23811
  `;
23808
23812
  DashboardFooter = __decorateClass$b([t$1("dashboard-footer")], DashboardFooter);
23809
23813
 
23814
+ /**
23815
+ * @license
23816
+ * Copyright 2025-2026 Open Home Foundation
23817
+ * SPDX-License-Identifier: Apache-2.0
23818
+ */
23819
+ class BorderRouterStore {
23820
+ // Replaced (not mutated) on every refresh so Lit consumers passing this map as a
23821
+ // @property() detect the snapshot change via the default `===` identity compare and
23822
+ // re-render. Mutating in place would keep the same reference and silently skip updates.
23823
+ #entries = /* @__PURE__ */new Map();
23824
+ get entries() {
23825
+ return this.#entries;
23826
+ }
23827
+ async refresh(client) {
23828
+ const list = await client.sendCommand("get_thread_border_routers", 0, {});
23829
+ const next = /* @__PURE__ */new Map();
23830
+ for (const entry of list) {
23831
+ next.set(entry.extAddressHex.toUpperCase(), entry);
23832
+ }
23833
+ this.#entries = next;
23834
+ }
23835
+ reset() {
23836
+ this.#entries = /* @__PURE__ */new Map();
23837
+ }
23838
+ }
23839
+
23810
23840
  /**
23811
23841
  * @license
23812
23842
  * Copyright 2025-2026 Open Home Foundation
@@ -23889,6 +23919,9 @@ function getThreadRole(node) {
23889
23919
  function getThreadChannel(node) {
23890
23920
  return node.attributes["0/53/0"];
23891
23921
  }
23922
+ function getThreadExtendedPanId(node) {
23923
+ return node.attributes["0/53/4"];
23924
+ }
23892
23925
  function getThreadExtendedAddress(node) {
23893
23926
  const networkInterfaces = node.attributes["0/51/0"];
23894
23927
  if (!Array.isArray(networkInterfaces) || networkInterfaces.length === 0) {
@@ -24027,11 +24060,13 @@ function buildRloc16Map(nodes) {
24027
24060
  }
24028
24061
  return rloc16Map;
24029
24062
  }
24030
- function findUnknownDevices(nodes, extAddrMap, rloc16Map) {
24031
- const unknownMap = /* @__PURE__ */new Map();
24063
+ function findUnknownDevices(nodes, extAddrMap, rloc16Map, borderRouters) {
24064
+ const aggregates = /* @__PURE__ */new Map();
24032
24065
  for (const node of Object.values(nodes)) {
24033
24066
  const nodeId = String(node.node_id);
24034
24067
  const neighbors = parseNeighborTable(node);
24068
+ const observerXp = getThreadExtendedPanId(node);
24069
+ const observerXpHex = observerXp !== void 0 ? observerXp.toString(16).padStart(16, "0").toUpperCase() : void 0;
24035
24070
  for (const neighbor of neighbors) {
24036
24071
  if (extAddrMap.has(neighbor.extAddress)) {
24037
24072
  continue;
@@ -24040,31 +24075,141 @@ function findUnknownDevices(nodes, extAddrMap, rloc16Map) {
24040
24075
  continue;
24041
24076
  }
24042
24077
  const extAddressHex = neighbor.extAddress.toString(16).padStart(16, "0").toUpperCase();
24043
- const id = `unknown_${extAddressHex}`;
24044
- if (!unknownMap.has(id)) {
24045
- unknownMap.set(id, {
24046
- id,
24078
+ let agg = aggregates.get(extAddressHex);
24079
+ if (agg === void 0) {
24080
+ agg = {
24047
24081
  extAddressHex,
24048
24082
  extAddress: neighbor.extAddress,
24049
24083
  seenBy: [],
24050
24084
  isRouter: false,
24051
- bestRssi: null
24052
- });
24085
+ bestRssi: null,
24086
+ extendedPanIdHex: observerXpHex
24087
+ };
24088
+ aggregates.set(extAddressHex, agg);
24089
+ } else if (agg.extendedPanIdHex === void 0 && observerXpHex !== void 0) {
24090
+ agg.extendedPanIdHex = observerXpHex;
24053
24091
  }
24054
- const unknown = unknownMap.get(id);
24055
- if (!unknown.seenBy.includes(nodeId)) {
24056
- unknown.seenBy.push(nodeId);
24092
+ if (!agg.seenBy.includes(nodeId)) {
24093
+ agg.seenBy.push(nodeId);
24057
24094
  }
24058
24095
  if (neighbor.rxOnWhenIdle) {
24059
- unknown.isRouter = true;
24096
+ agg.isRouter = true;
24060
24097
  }
24061
24098
  const rssi = neighbor.avgRssi ?? neighbor.lastRssi;
24062
- if (rssi !== null && (unknown.bestRssi === null || rssi > unknown.bestRssi)) {
24063
- unknown.bestRssi = rssi;
24099
+ if (rssi !== null && (agg.bestRssi === null || rssi > agg.bestRssi)) {
24100
+ agg.bestRssi = rssi;
24064
24101
  }
24065
24102
  }
24066
24103
  }
24067
- return Array.from(unknownMap.values());
24104
+ const networkNameByXp = /* @__PURE__ */new Map();
24105
+ if (borderRouters !== void 0) {
24106
+ for (const br of borderRouters.values()) {
24107
+ if (br.extendedPanIdHex !== void 0 && br.networkName !== void 0) {
24108
+ networkNameByXp.set(br.extendedPanIdHex, br.networkName);
24109
+ }
24110
+ }
24111
+ }
24112
+ const out = new Array();
24113
+ for (const agg of aggregates.values()) {
24114
+ const br = borderRouters === null || borderRouters === void 0 ? void 0 : borderRouters.get(agg.extAddressHex);
24115
+ if (br !== void 0) {
24116
+ out.push({
24117
+ kind: "br",
24118
+ ...br,
24119
+ id: `br_${agg.extAddressHex}`,
24120
+ extAddressHex: agg.extAddressHex,
24121
+ extAddress: agg.extAddress,
24122
+ seenBy: agg.seenBy,
24123
+ isRouter: agg.isRouter,
24124
+ bestRssi: agg.bestRssi
24125
+ });
24126
+ } else {
24127
+ const networkName = agg.extendedPanIdHex !== void 0 ? networkNameByXp.get(agg.extendedPanIdHex) : void 0;
24128
+ out.push({
24129
+ kind: "unknown",
24130
+ id: `unknown_${agg.extAddressHex}`,
24131
+ extAddressHex: agg.extAddressHex,
24132
+ extAddress: agg.extAddress,
24133
+ seenBy: agg.seenBy,
24134
+ isRouter: agg.isRouter,
24135
+ bestRssi: agg.bestRssi,
24136
+ extendedPanIdHex: agg.extendedPanIdHex,
24137
+ networkName
24138
+ });
24139
+ }
24140
+ }
24141
+ return out;
24142
+ }
24143
+ const CONNECTION_MODE_LABELS = {
24144
+ 0: "disabled",
24145
+ 1: "PSKc / DTLS",
24146
+ 2: "PSKd / DTLS",
24147
+ 3: "vendor-defined",
24148
+ 4: "X.509"
24149
+ };
24150
+ const THREAD_INTERFACE_STATUS_LABELS = {
24151
+ 0: "not initialized",
24152
+ 1: "initialized, inactive",
24153
+ 2: "initialized, active"
24154
+ };
24155
+ const AVAILABILITY_LABELS = {
24156
+ 0: "infrequent",
24157
+ 1: "high"
24158
+ };
24159
+ const THREAD_ROLE_LABELS = {
24160
+ 0: "detached",
24161
+ 1: "child",
24162
+ 2: "router",
24163
+ 3: "leader"
24164
+ };
24165
+ const MULTI_AIL_STATE_LABELS = {
24166
+ 0: "disabled",
24167
+ 1: "not detected",
24168
+ 2: "detected"
24169
+ };
24170
+ function decodeMeshcopStateBitmap(hex) {
24171
+ if (hex === void 0 || !/^[0-9a-fA-F]{1,8}$/.test(hex)) return void 0;
24172
+ const value = parseInt(hex, 16);
24173
+ if (!Number.isFinite(value)) return void 0;
24174
+ const connectionModeValue = value & 7;
24175
+ const threadInterfaceStatusValue = value >> 3 & 3;
24176
+ const availabilityValue = value >> 5 & 3;
24177
+ const bbr = (value >> 7 & 1) === 1;
24178
+ const bbrIsPrimary = (value >> 8 & 1) === 1;
24179
+ const threadRoleValue = value >> 9 & 3;
24180
+ const epskcSupported = (value >> 11 & 1) === 1;
24181
+ const multiAilStateValue = value >> 12 & 3;
24182
+ const reserved = value >>> 14 >>> 0;
24183
+ return {
24184
+ connectionModeValue,
24185
+ connectionMode: CONNECTION_MODE_LABELS[connectionModeValue],
24186
+ threadInterfaceStatusValue,
24187
+ threadInterfaceStatus: THREAD_INTERFACE_STATUS_LABELS[threadInterfaceStatusValue],
24188
+ availabilityValue,
24189
+ availability: AVAILABILITY_LABELS[availabilityValue],
24190
+ bbr,
24191
+ bbrFunction: bbr ? bbrIsPrimary ? "primary" : "secondary" : void 0,
24192
+ threadRoleValue,
24193
+ threadRole: THREAD_ROLE_LABELS[threadRoleValue],
24194
+ epskcSupported,
24195
+ multiAilStateValue,
24196
+ multiAilState: MULTI_AIL_STATE_LABELS[multiAilStateValue],
24197
+ reservedHex: reserved !== 0 ? reserved.toString(16).toUpperCase() : void 0
24198
+ };
24199
+ }
24200
+ function getSignalLevel(neighbor) {
24201
+ const rssi = neighbor.avgRssi ?? neighbor.lastRssi;
24202
+ if (rssi !== null) {
24203
+ if (rssi > SIGNAL_STRONG_THRESHOLD) return "strong";
24204
+ if (rssi > SIGNAL_MEDIUM_THRESHOLD) return "medium";
24205
+ return "weak";
24206
+ }
24207
+ return getSignalLevelFromLqi(neighbor.lqi);
24208
+ }
24209
+ function getSignalLevelFromLqi(lqi) {
24210
+ if (lqi > LQI_STRONG_THRESHOLD) return "strong";
24211
+ if (lqi > LQI_MEDIUM_THRESHOLD) return "medium";
24212
+ return "weak";
24068
24213
  }
24069
24214
  function getSignalColor(neighbor) {
24070
24215
  const rssi = neighbor.avgRssi ?? neighbor.lastRssi;
@@ -24198,9 +24343,16 @@ function getWiFiVersionName(version) {
24198
24343
  return "Unknown";
24199
24344
  }
24200
24345
  }
24201
- function buildThreadConnections(nodes, extAddrMap, rloc16Map, unknownDevices) {
24202
- const connections = [];
24203
- const seenConnections = /* @__PURE__ */new Set();
24346
+ function makePairKey(a, b) {
24347
+ return a < b ? `${a}|${b}` : `${b}|${a}`;
24348
+ }
24349
+ function getEdgeSignalScore(conn) {
24350
+ const levelScore = conn.signalLevel === "strong" ? 3e3 : conn.signalLevel === "medium" ? 2e3 : conn.signalLevel === "weak" ? 1e3 : 0;
24351
+ const detail = conn.rssi !== null ? conn.rssi + 200 : conn.lqi;
24352
+ return levelScore + detail;
24353
+ }
24354
+ function buildThreadEdgePairs(nodes, extAddrMap, rloc16Map, unknownDevices) {
24355
+ const pairs = /* @__PURE__ */new Map();
24204
24356
  const unknownExtAddrMap = /* @__PURE__ */new Map();
24205
24357
  for (const unknown of unknownDevices) {
24206
24358
  unknownExtAddrMap.set(unknown.extAddress, unknown.id);
@@ -24216,29 +24368,37 @@ function buildThreadConnections(nodes, extAddrMap, rloc16Map, unknownDevices) {
24216
24368
  if (toNodeId === void 0) {
24217
24369
  toNodeId = unknownExtAddrMap.get(neighbor.extAddress);
24218
24370
  }
24219
- if (toNodeId === void 0) {
24220
- continue;
24221
- }
24222
- if (fromNodeId === toNodeId) {
24223
- continue;
24224
- }
24225
- const connectionKey = `${fromNodeId}-${toNodeId}`;
24226
- const reverseKey = `${toNodeId}-${fromNodeId}`;
24227
- if (seenConnections.has(connectionKey) || seenConnections.has(reverseKey)) {
24228
- continue;
24371
+ if (toNodeId === void 0 || fromNodeId === toNodeId) continue;
24372
+ const pairKey = makePairKey(fromNodeId, toNodeId);
24373
+ if (!pairs.has(pairKey)) {
24374
+ const [nodeA, nodeB] = fromNodeId < toNodeId ? [fromNodeId, toNodeId] : [toNodeId, fromNodeId];
24375
+ pairs.set(pairKey, {
24376
+ pairKey,
24377
+ nodeA,
24378
+ nodeB
24379
+ });
24229
24380
  }
24230
- seenConnections.add(connectionKey);
24381
+ const pair = pairs.get(pairKey);
24382
+ const isFromA = fromNodeId === pair.nodeA;
24383
+ if (isFromA && pair.edgeAB) continue;
24384
+ if (!isFromA && pair.edgeBA) continue;
24231
24385
  const routeEntry = findRouteByExtAddress(node, neighbor.extAddress);
24232
24386
  const bidirectionalLqi = routeEntry ? getRouteBidirectionalLqi(routeEntry) : void 0;
24233
- connections.push({
24387
+ const edge = {
24234
24388
  fromNodeId,
24235
24389
  toNodeId,
24236
24390
  signalColor: getSignalColor(neighbor),
24391
+ signalLevel: getSignalLevel(neighbor),
24237
24392
  lqi: neighbor.lqi,
24238
24393
  rssi: neighbor.avgRssi ?? neighbor.lastRssi,
24239
24394
  pathCost: routeEntry === null || routeEntry === void 0 ? void 0 : routeEntry.pathCost,
24240
24395
  bidirectionalLqi
24241
- });
24396
+ };
24397
+ if (isFromA) {
24398
+ pair.edgeAB = edge;
24399
+ } else {
24400
+ pair.edgeBA = edge;
24401
+ }
24242
24402
  }
24243
24403
  const routes = parseRouteTable(node);
24244
24404
  for (const route of routes) {
@@ -24251,95 +24411,121 @@ function buildThreadConnections(nodes, extAddrMap, rloc16Map, unknownDevices) {
24251
24411
  toNodeId = unknownExtAddrMap.get(route.extAddress);
24252
24412
  }
24253
24413
  if (toNodeId === void 0 || toNodeId === fromNodeId) continue;
24254
- const connectionKey = `${fromNodeId}-${toNodeId}`;
24255
- const reverseKey = `${toNodeId}-${fromNodeId}`;
24256
- if (seenConnections.has(connectionKey) || seenConnections.has(reverseKey)) {
24257
- continue;
24414
+ const pairKey = makePairKey(fromNodeId, toNodeId);
24415
+ if (!pairs.has(pairKey)) {
24416
+ const [nodeA, nodeB] = fromNodeId < toNodeId ? [fromNodeId, toNodeId] : [toNodeId, fromNodeId];
24417
+ pairs.set(pairKey, {
24418
+ pairKey,
24419
+ nodeA,
24420
+ nodeB
24421
+ });
24258
24422
  }
24259
- seenConnections.add(connectionKey);
24423
+ const pair = pairs.get(pairKey);
24424
+ const isFromA = fromNodeId === pair.nodeA;
24425
+ if (isFromA && pair.edgeAB) continue;
24426
+ if (!isFromA && pair.edgeBA) continue;
24260
24427
  const bidirectionalLqi = getRouteBidirectionalLqi(route);
24261
24428
  const signalColor = bidirectionalLqi !== void 0 ? getSignalColorFromLqi(bidirectionalLqi) : "var(--md-sys-color-outline, grey)";
24262
- connections.push({
24429
+ const edge = {
24263
24430
  fromNodeId,
24264
24431
  toNodeId,
24265
24432
  signalColor,
24433
+ signalLevel: bidirectionalLqi !== void 0 ? getSignalLevelFromLqi(bidirectionalLqi) : void 0,
24266
24434
  lqi: bidirectionalLqi ?? 0,
24267
24435
  rssi: null,
24268
24436
  pathCost: route.pathCost,
24269
24437
  bidirectionalLqi,
24270
24438
  fromRouteTable: true
24271
- });
24439
+ };
24440
+ if (isFromA) {
24441
+ pair.edgeAB = edge;
24442
+ } else {
24443
+ pair.edgeBA = edge;
24444
+ }
24272
24445
  }
24273
24446
  }
24274
- return connections;
24447
+ return pairs;
24275
24448
  }
24276
- function getNodeConnections(nodeId, nodes, extAddrMap, rloc16Map) {
24449
+ function getNodeConnectionsFromPairs(nodeId, edgePairs, nodes, filters) {
24277
24450
  const connections = [];
24278
- const seenConnectedIds = /* @__PURE__ */new Set();
24279
- const node = nodes[nodeId];
24280
- if (!node) return connections;
24281
- const thisExtAddr = getThreadExtendedAddress(node);
24282
- const neighbors = parseNeighborTable(node);
24283
- for (const neighbor of neighbors) {
24284
- let connectedNodeId = extAddrMap.get(neighbor.extAddress);
24285
- if (connectedNodeId === void 0 && rloc16Map && neighbor.rloc16 !== 0) {
24286
- connectedNodeId = rloc16Map.get(neighbor.rloc16);
24287
- }
24288
- const connectedNode = connectedNodeId ? nodes[connectedNodeId] : void 0;
24289
- const isUnknown = connectedNodeId === void 0;
24290
- const displayId = connectedNodeId ?? `unknown_${neighbor.extAddress.toString(16).toUpperCase().padStart(16, "0")}`;
24291
- seenConnectedIds.add(displayId);
24292
- const routeEntry = findRouteByExtAddress(node, neighbor.extAddress);
24293
- const bidirectionalLqi = routeEntry ? getRouteBidirectionalLqi(routeEntry) : void 0;
24451
+ const hiddenNodeIds = /* @__PURE__ */new Set();
24452
+ if (filters !== null && filters !== void 0 && filters.hideOfflineNodes) {
24453
+ for (const node of Object.values(nodes)) {
24454
+ if (node.available === false) {
24455
+ hiddenNodeIds.add(String(node.node_id));
24456
+ }
24457
+ }
24458
+ }
24459
+ for (const pair of edgePairs.values()) {
24460
+ const isA = pair.nodeA === nodeId;
24461
+ const isB = pair.nodeB === nodeId;
24462
+ if (!isA && !isB) continue;
24463
+ const remoteId = isA ? pair.nodeB : pair.nodeA;
24464
+ const outgoing = isA ? pair.edgeAB : pair.edgeBA;
24465
+ const incoming = isA ? pair.edgeBA : pair.edgeAB;
24466
+ const survivors = [];
24467
+ for (const [conn, isOut] of [[outgoing, true], [incoming, false]]) {
24468
+ if (!conn) continue;
24469
+ if (filters) {
24470
+ const fromId = String(conn.fromNodeId);
24471
+ const toId = String(conn.toNodeId);
24472
+ if (hiddenNodeIds.has(fromId) || hiddenNodeIds.has(toId)) continue;
24473
+ if (filters.hideWeakSignalEdges && conn.signalLevel === "weak") continue;
24474
+ if (filters.hideMediumSignalEdges && conn.signalLevel === "medium") continue;
24475
+ if (filters.hideStrongSignalEdges && conn.signalLevel === "strong") continue;
24476
+ }
24477
+ survivors.push({
24478
+ conn,
24479
+ isOutgoing: isOut
24480
+ });
24481
+ }
24482
+ if (survivors.length === 0) continue;
24483
+ let winner;
24484
+ const outgoingSurvivor = survivors.find(s => s.isOutgoing);
24485
+ if (outgoingSurvivor) {
24486
+ winner = outgoingSurvivor;
24487
+ } else {
24488
+ survivors.sort((a, b) => getEdgeSignalScore(a.conn) - getEdgeSignalScore(b.conn));
24489
+ winner = survivors[0];
24490
+ }
24491
+ const remoteNode = nodes[remoteId];
24492
+ const isExternalUnknown = remoteId.startsWith("unknown_");
24493
+ const isExternalBr = remoteId.startsWith("br_");
24494
+ const isUnknown = isExternalUnknown || isExternalBr;
24495
+ let extAddressHex;
24496
+ if (isExternalUnknown) {
24497
+ extAddressHex = remoteId.slice("unknown_".length);
24498
+ } else if (isExternalBr) {
24499
+ extAddressHex = remoteId.slice("br_".length);
24500
+ } else if (remoteNode) {
24501
+ extAddressHex = getThreadExtendedAddressHex(remoteNode) ?? "Unknown";
24502
+ } else {
24503
+ extAddressHex = "Unknown";
24504
+ }
24294
24505
  connections.push({
24295
- connectedNodeId: displayId,
24296
- connectedNode,
24297
- extAddressHex: neighbor.extAddress.toString(16).toUpperCase().padStart(16, "0"),
24298
- signalColor: getSignalColor(neighbor),
24299
- lqi: neighbor.lqi,
24300
- rssi: neighbor.avgRssi ?? neighbor.lastRssi,
24301
- isOutgoing: true,
24506
+ connectedNodeId: remoteId,
24507
+ connectedNode: remoteNode,
24508
+ extAddressHex,
24509
+ signalColor: winner.conn.signalColor,
24510
+ signalLevel: winner.conn.signalLevel,
24511
+ lqi: winner.conn.lqi,
24512
+ rssi: winner.conn.rssi,
24513
+ isOutgoing: winner.isOutgoing,
24514
+ isReverseOnly: !outgoing,
24302
24515
  isUnknown,
24303
- pathCost: routeEntry === null || routeEntry === void 0 ? void 0 : routeEntry.pathCost,
24304
- bidirectionalLqi
24516
+ pathCost: winner.conn.pathCost,
24517
+ bidirectionalLqi: winner.conn.bidirectionalLqi
24305
24518
  });
24306
24519
  }
24307
- if (thisExtAddr !== void 0) {
24308
- for (const otherNode of Object.values(nodes)) {
24309
- const otherNodeId = String(otherNode.node_id);
24310
- if (otherNodeId === nodeId) continue;
24311
- if (seenConnectedIds.has(otherNodeId)) continue;
24312
- const otherNeighbors = parseNeighborTable(otherNode);
24313
- const reverseEntry = otherNeighbors.find(n => n.extAddress === thisExtAddr);
24314
- if (reverseEntry) {
24315
- const otherExtAddr = getThreadExtendedAddress(otherNode);
24316
- const extAddrHex = otherExtAddr ? otherExtAddr.toString(16).toUpperCase().padStart(16, "0") : "Unknown";
24317
- const routeEntry = findRouteByExtAddress(otherNode, thisExtAddr);
24318
- const bidirectionalLqi = routeEntry ? getRouteBidirectionalLqi(routeEntry) : void 0;
24319
- connections.push({
24320
- connectedNodeId: otherNodeId,
24321
- connectedNode: otherNode,
24322
- extAddressHex: extAddrHex,
24323
- signalColor: getSignalColor(reverseEntry),
24324
- lqi: reverseEntry.lqi,
24325
- rssi: reverseEntry.avgRssi ?? reverseEntry.lastRssi,
24326
- isOutgoing: false,
24327
- isUnknown: false,
24328
- pathCost: routeEntry === null || routeEntry === void 0 ? void 0 : routeEntry.pathCost,
24329
- bidirectionalLqi
24330
- });
24331
- }
24332
- }
24333
- }
24334
24520
  return connections;
24335
24521
  }
24336
24522
 
24337
- var __defProp$7 = Object.defineProperty;
24523
+ var __defProp$8 = Object.defineProperty;
24338
24524
  var __getOwnPropDesc$9 = Object.getOwnPropertyDescriptor;
24339
24525
  var __decorateClass$a = (decorators, target, key, kind) => {
24340
24526
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$9(target, key) : target;
24341
24527
  for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
24342
- if (kind && result) __defProp$7(target, key, result);
24528
+ if (kind && result) __defProp$8(target, key, result);
24343
24529
  return result;
24344
24530
  };
24345
24531
  let DevicePanel = class extends i$4 {
@@ -25509,12 +25695,12 @@ let MdDialog = class MdDialog extends Dialog {};
25509
25695
  MdDialog.styles = [styles];
25510
25696
  MdDialog = __decorate([t$1('md-dialog')], MdDialog);
25511
25697
 
25512
- var __defProp$6 = Object.defineProperty;
25698
+ var __defProp$7 = Object.defineProperty;
25513
25699
  var __getOwnPropDesc$8 = Object.getOwnPropertyDescriptor;
25514
25700
  var __decorateClass$9 = (decorators, target, key, kind) => {
25515
25701
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$8(target, key) : target;
25516
25702
  for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
25517
- if (kind && result) __defProp$6(target, key, result);
25703
+ if (kind && result) __defProp$7(target, key, result);
25518
25704
  return result;
25519
25705
  };
25520
25706
  const THREAD_ATTRIBUTE_PATHS = ["0/53/7", "0/53/8", "0/51/0"];
@@ -25772,21 +25958,27 @@ __decorateClass$9([r$2()], UpdateConnectionsDialog.prototype, "_includeNeighbors
25772
25958
  __decorateClass$9([r$2()], UpdateConnectionsDialog.prototype, "_isUpdating", 2);
25773
25959
  UpdateConnectionsDialog = __decorateClass$9([t$1("update-connections-dialog")], UpdateConnectionsDialog);
25774
25960
 
25775
- var __defProp$5 = Object.defineProperty;
25961
+ var __defProp$6 = Object.defineProperty;
25776
25962
  var __getOwnPropDesc$7 = Object.getOwnPropertyDescriptor;
25777
25963
  var __decorateClass$8 = (decorators, target, key, kind) => {
25778
25964
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$7(target, key) : target;
25779
25965
  for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
25780
- if (kind && result) __defProp$5(target, key, result);
25966
+ if (kind && result) __defProp$6(target, key, result);
25781
25967
  return result;
25782
25968
  };
25783
25969
  let NetworkDetails = class extends i$4 {
25784
25970
  constructor() {
25785
25971
  super(...arguments);
25786
25972
  this.selectedNodeId = null;
25973
+ this.hideOfflineNodes = false;
25974
+ this.hideWeakSignalEdges = false;
25975
+ this.hideMediumSignalEdges = false;
25976
+ this.hideStrongSignalEdges = false;
25787
25977
  this.nodes = {};
25788
25978
  this.unknownDevices = /* @__PURE__ */new Map();
25979
+ this.borderRouters = /* @__PURE__ */new Map();
25789
25980
  this.wifiAccessPoints = /* @__PURE__ */new Map();
25981
+ this.threadEdgePairs = /* @__PURE__ */new Map();
25790
25982
  this._showUpdateDialog = false;
25791
25983
  }
25792
25984
  _handleClose() {
@@ -25811,16 +26003,6 @@ let NetworkDetails = class extends i$4 {
25811
26003
  this._handleSelectNode(nodeId);
25812
26004
  }
25813
26005
  }
25814
- _formatExtAddress(extAddr) {
25815
- if (extAddr === void 0 || extAddr === "") return "Unknown";
25816
- if (typeof extAddr === "bigint") {
25817
- return extAddr.toString(16).toUpperCase().padStart(16, "0");
25818
- }
25819
- return extAddr;
25820
- }
25821
- _getSignalIcon(neighbor) {
25822
- return this._getSignalIconFromColor(getSignalColor(neighbor));
25823
- }
25824
26006
  _getSignalIconFromColor(color) {
25825
26007
  const strongColor = getCssVar("--signal-color-strong", "#4caf50");
25826
26008
  const mediumColor = getCssVar("--signal-color-medium", "#ff9800");
@@ -25885,10 +26067,13 @@ let NetworkDetails = class extends i$4 {
25885
26067
  const threadRole = getThreadRole(node);
25886
26068
  const channel = getThreadChannel(node);
25887
26069
  const extAddressHex = getThreadExtendedAddressHex(node);
25888
- const extAddrMap = buildExtAddrMap(this.nodes);
25889
- const rloc16Map = buildRloc16Map(this.nodes);
25890
26070
  const nodeId = String(node.node_id);
25891
- const connections = getNodeConnections(nodeId, this.nodes, extAddrMap, rloc16Map);
26071
+ const connections = getNodeConnectionsFromPairs(nodeId, this.threadEdgePairs, this.nodes, {
26072
+ hideOfflineNodes: this.hideOfflineNodes,
26073
+ hideWeakSignalEdges: this.hideWeakSignalEdges,
26074
+ hideMediumSignalEdges: this.hideMediumSignalEdges,
26075
+ hideStrongSignalEdges: this.hideStrongSignalEdges
26076
+ });
25892
26077
  return b`
25893
26078
  <div class="section">
25894
26079
  <h4>Thread Network</h4>
@@ -25966,7 +26151,13 @@ let NetworkDetails = class extends i$4 {
25966
26151
  >` : A}${conn.pathCost !== void 0 ? b`<span class="route-info"
25967
26152
  >, Cost: ${conn.pathCost}</span
25968
26153
  >` : A}
25969
- ${!conn.isOutgoing ? b` <span class="direction-hint">(reverse)</span> ` : A}
26154
+ ${conn.isReverseOnly ? b`
26155
+ <span
26156
+ class="direction-hint reverse-only"
26157
+ title="Peer reports this node but this node has no matching neighbor-table entry. Possible one-way visibility (range, TX power, or stale neighbor table)."
26158
+ >← one-way</span
26159
+ >
26160
+ ` : !conn.isOutgoing ? b` <span class="direction-hint">(reverse)</span> ` : A}
25970
26161
  </div>
25971
26162
  </div>
25972
26163
  </div>
@@ -26022,24 +26213,12 @@ let NetworkDetails = class extends i$4 {
26022
26213
  ` : A}
26023
26214
  `;
26024
26215
  }
26025
- /**
26026
- * Find the neighbor entry for an unknown device from a node's neighbor table.
26027
- */
26028
- _findNeighborEntry(node, unknownExtAddrHex) {
26029
- const neighbors = parseNeighborTable(node);
26030
- for (const neighbor of neighbors) {
26031
- const neighborHex = this._formatExtAddress(neighbor.extAddress);
26032
- if (neighborHex === unknownExtAddrHex) {
26033
- return neighbor;
26034
- }
26035
- }
26036
- return null;
26037
- }
26038
26216
  _renderUnknownDeviceInfo(deviceId) {
26039
- const unknown = this.unknownDevices.get(deviceId);
26040
- if (!unknown) {
26217
+ const device = this.unknownDevices.get(deviceId);
26218
+ if (!device || device.kind !== "unknown") {
26041
26219
  return b` <p>Unknown device data not available</p> `;
26042
26220
  }
26221
+ const unknown = device;
26043
26222
  return b`
26044
26223
  <div class="section">
26045
26224
  <h4>Unknown Device</h4>
@@ -26051,6 +26230,18 @@ let NetworkDetails = class extends i$4 {
26051
26230
  <span class="label">Extended Address:</span>
26052
26231
  <span class="value mono">${unknown.extAddressHex}</span>
26053
26232
  </div>
26233
+ ${unknown.networkName !== void 0 ? b`
26234
+ <div class="info-row">
26235
+ <span class="label">Thread Network:</span>
26236
+ <span class="value">${unknown.networkName}</span>
26237
+ </div>
26238
+ ` : A}
26239
+ ${unknown.extendedPanIdHex !== void 0 ? b`
26240
+ <div class="info-row">
26241
+ <span class="label">Extended PAN ID:</span>
26242
+ <span class="value mono">${unknown.extendedPanIdHex}</span>
26243
+ </div>
26244
+ ` : A}
26054
26245
  ${unknown.bestRssi !== null ? b`
26055
26246
  <div class="info-row">
26056
26247
  <span class="label">Best RSSI:</span>
@@ -26059,71 +26250,284 @@ let NetworkDetails = class extends i$4 {
26059
26250
  ` : A}
26060
26251
  </div>
26061
26252
 
26062
- ${unknown.seenBy.length > 0 ? b`
26063
- <md-divider></md-divider>
26064
- <div class="section">
26065
- <h4>Neighbors (${unknown.seenBy.length})</h4>
26066
- <div class="neighbors-list">
26067
- ${unknown.seenBy.toSorted((a, b) => {
26068
- const score = nodeId => {
26069
- const n = this.nodes[nodeId.toString()];
26070
- if (!n) return -Infinity;
26071
- const entry = this._findNeighborEntry(n, unknown.extAddressHex);
26072
- if (!entry) return -Infinity;
26073
- const rssi = entry.avgRssi ?? entry.lastRssi;
26074
- if (rssi !== null && rssi !== void 0) return rssi;
26075
- if (entry.lqi !== null && entry.lqi !== void 0) return entry.lqi;
26253
+ ${this._renderExternalDeviceNeighbors(deviceId)}
26254
+
26255
+ <md-divider></md-divider>
26256
+ <div class="section">
26257
+ <p class="hint-text">
26258
+ This device appears in Thread neighbor tables but is not commissioned to this fabric. It may be a
26259
+ Thread Border Router whose Thread radio MAC differs from its MeshCoP border-agent ID (common with
26260
+ Apple and Aqara), or a device from another Matter ecosystem.
26261
+ </p>
26262
+ </div>
26263
+ `;
26264
+ }
26265
+ /**
26266
+ * Neighbor list shared by external-device panels (unknown + BR). Uses the
26267
+ * same edge pairs as the graph so panel and graph agree on which links
26268
+ * survive filtering. Sorted by best RSSI/LQI signal, descending.
26269
+ */
26270
+ _renderExternalDeviceNeighbors(deviceId) {
26271
+ const connections = getNodeConnectionsFromPairs(deviceId, this.threadEdgePairs, this.nodes, {
26272
+ hideOfflineNodes: this.hideOfflineNodes,
26273
+ hideWeakSignalEdges: this.hideWeakSignalEdges,
26274
+ hideMediumSignalEdges: this.hideMediumSignalEdges,
26275
+ hideStrongSignalEdges: this.hideStrongSignalEdges
26276
+ });
26277
+ if (connections.length === 0) return A;
26278
+ return b`
26279
+ <md-divider></md-divider>
26280
+ <div class="section">
26281
+ <h4>Neighbors (${connections.length})</h4>
26282
+ <div class="neighbors-list">
26283
+ ${connections.toSorted((a, b) => {
26284
+ const score = conn => {
26285
+ if (conn.rssi !== null && conn.rssi !== void 0) return conn.rssi;
26286
+ if (conn.lqi !== null && conn.lqi !== void 0) return conn.lqi;
26076
26287
  return -Infinity;
26077
26288
  };
26078
26289
  return score(b) - score(a);
26079
- }).map(nodeId => {
26080
- const node = this.nodes[nodeId.toString()];
26081
- if (!node) return A;
26082
- const neighborEntry = this._findNeighborEntry(node, unknown.extAddressHex);
26083
- const signalColor = neighborEntry ? getSignalColor(neighborEntry) : getCssVar("--graph-node-fallback", "#999");
26084
- const rssi = (neighborEntry === null || neighborEntry === void 0 ? void 0 : neighborEntry.avgRssi) ?? (neighborEntry === null || neighborEntry === void 0 ? void 0 : neighborEntry.lastRssi) ?? null;
26085
- const lqi = neighborEntry === null || neighborEntry === void 0 ? void 0 : neighborEntry.lqi;
26290
+ }).map(conn => {
26291
+ if (!conn.connectedNode) return A;
26086
26292
  return b`
26087
- <div
26088
- class="neighbor-item clickable"
26089
- role="button"
26090
- tabindex="0"
26091
- @click=${() => this._handleSelectNode(nodeId)}
26092
- @keydown=${e => this._handleKeyDown(e, nodeId)}
26093
- >
26094
- ${neighborEntry ? b`
26095
- <ha-svg-icon
26096
- .path=${this._getSignalIcon(neighborEntry)}
26097
- style="--icon-primary-color: ${signalColor}"
26098
- ></ha-svg-icon>
26099
- ` : A}
26100
- <div class="neighbor-info">
26101
- <div class="neighbor-name">
26102
- Node ${nodeId}
26103
- <span class="node-id-hex">${this._formatNodeIdHex(nodeId)}</span>:
26104
- ${getDeviceName(node)}
26105
- </div>
26106
- ${neighborEntry ? b`
26107
- <div class="neighbor-signal">
26108
- ${rssi !== null ? b`RSSI: ${rssi} dBm, ` : A}
26109
- ${lqi !== void 0 ? b`LQI: ${lqi}` : A}
26110
- </div>
26111
- ` : A}
26112
- </div>
26113
- </div>
26114
- `;
26293
+ <div
26294
+ class="neighbor-item clickable"
26295
+ role="button"
26296
+ tabindex="0"
26297
+ @click=${() => this._handleSelectNode(conn.connectedNodeId)}
26298
+ @keydown=${e => this._handleKeyDown(e, conn.connectedNodeId)}
26299
+ >
26300
+ <ha-svg-icon
26301
+ .path=${this._getSignalIconFromColor(conn.signalColor)}
26302
+ style="--icon-primary-color: ${conn.signalColor}"
26303
+ ></ha-svg-icon>
26304
+ <div class="neighbor-info">
26305
+ <div class="neighbor-name">
26306
+ Node ${conn.connectedNodeId}
26307
+ <span class="node-id-hex"
26308
+ >${this._formatNodeIdHex(conn.connectedNodeId)}</span
26309
+ >: ${getDeviceName(conn.connectedNode)}
26310
+ </div>
26311
+ <div class="neighbor-signal">
26312
+ ${conn.rssi !== null ? b`RSSI: ${conn.rssi} dBm, ` : A}
26313
+ ${conn.lqi !== null ? b`LQI: ${conn.lqi}` : A}
26314
+ </div>
26315
+ </div>
26316
+ </div>
26317
+ `;
26115
26318
  })}
26116
- </div>
26319
+ </div>
26320
+ </div>
26321
+ `;
26322
+ }
26323
+ /**
26324
+ * Identity rows for a Border Router (network name, vendor, model, Thread version, ext address).
26325
+ * Caller controls the surrounding <div class="section"> + heading.
26326
+ */
26327
+ _renderBorderRouterIdentityRows(br, includeExtAddr) {
26328
+ return b`
26329
+ ${br.networkName ? b`
26330
+ <div class="info-row">
26331
+ <span class="label">Network name:</span>
26332
+ <span class="value">${br.networkName}</span>
26117
26333
  </div>
26118
26334
  ` : A}
26119
-
26120
- <md-divider></md-divider>
26335
+ ${br.vendorName ? b`
26336
+ <div class="info-row">
26337
+ <span class="label">Vendor:</span>
26338
+ <span class="value">${br.vendorName}</span>
26339
+ </div>
26340
+ ` : A}
26341
+ ${br.modelName ? b`
26342
+ <div class="info-row">
26343
+ <span class="label">Model:</span>
26344
+ <span class="value">${br.modelName}</span>
26345
+ </div>
26346
+ ` : A}
26347
+ ${br.threadVersion ? b`
26348
+ <div class="info-row">
26349
+ <span class="label">Thread version:</span>
26350
+ <span class="value">${br.threadVersion}</span>
26351
+ </div>
26352
+ ` : A}
26353
+ ${includeExtAddr ? b`
26354
+ <div class="info-row">
26355
+ <span class="label">Extended Address:</span>
26356
+ <span class="value mono">${br.extAddressHex}</span>
26357
+ </div>
26358
+ ` : A}
26359
+ `;
26360
+ }
26361
+ /**
26362
+ * Render the MeshCoP state bitmap as decoded fields (BBR role, connection mode, Thread
26363
+ * interface status, availability, ePSKc) plus the raw hex underneath. Reserved values are
26364
+ * rendered as numeric so a future spec extension stays visible.
26365
+ */
26366
+ _renderStateBitmap(hex) {
26367
+ if (hex === void 0) return A;
26368
+ const decoded = decodeMeshcopStateBitmap(hex);
26369
+ if (decoded === void 0) {
26370
+ return b`
26371
+ <div class="info-row">
26372
+ <span class="label">State bitmap:</span>
26373
+ <span class="value mono">${hex}</span>
26374
+ </div>
26375
+ `;
26376
+ }
26377
+ const stateParts = new Array();
26378
+ stateParts.push(decoded.bbr ? `BBR (${decoded.bbrFunction ?? "?"})` : "not BBR");
26379
+ if (decoded.threadRole !== void 0) {
26380
+ stateParts.push(`Thread ${decoded.threadRole}`);
26381
+ }
26382
+ if (decoded.threadInterfaceStatus !== void 0) {
26383
+ stateParts.push(decoded.threadInterfaceStatus);
26384
+ }
26385
+ return b`
26386
+ <div class="info-row">
26387
+ <span class="label">State:</span>
26388
+ <span class="value">${stateParts.join(", ")}</span>
26389
+ </div>
26390
+ <div class="info-row">
26391
+ <span class="label">Connection:</span>
26392
+ <span class="value">${decoded.connectionMode ?? `reserved (${decoded.connectionModeValue})`}</span>
26393
+ </div>
26394
+ <div class="info-row">
26395
+ <span class="label">Availability:</span>
26396
+ <span class="value">${decoded.availability ?? `reserved (${decoded.availabilityValue})`}</span>
26397
+ </div>
26398
+ <div class="info-row">
26399
+ <span class="label">ePSKc:</span>
26400
+ <span class="value">${decoded.epskcSupported ? "supported" : "not supported"}</span>
26401
+ </div>
26402
+ ${decoded.multiAilStateValue !== 0 ? b`
26403
+ <div class="info-row">
26404
+ <span class="label">Multi-AIL:</span>
26405
+ <span class="value">
26406
+ ${decoded.multiAilState ?? `reserved (${decoded.multiAilStateValue})`}
26407
+ </span>
26408
+ </div>
26409
+ ` : A}
26410
+ <div class="info-row">
26411
+ <span class="label">State bitmap (raw):</span>
26412
+ <span class="value mono">${hex}</span>
26413
+ </div>
26414
+ `;
26415
+ }
26416
+ /**
26417
+ * Network-info rows for a Border Router (extended PAN ID, partition, timestamps, state, domain, agent ID).
26418
+ * Returns nothing if no fields are populated, so the caller can skip the surrounding section.
26419
+ */
26420
+ _renderBorderRouterNetworkRows(br) {
26421
+ const hasAny = br.extendedPanIdHex !== void 0 || br.partitionIdHex !== void 0 || br.activeTimestampHex !== void 0 || br.stateBitmapHex !== void 0 || br.domainName !== void 0 || br.borderAgentIdHex !== void 0;
26422
+ if (!hasAny) return A;
26423
+ return b`
26424
+ ${br.extendedPanIdHex ? b`
26425
+ <div class="info-row">
26426
+ <span class="label">Extended PAN ID:</span>
26427
+ <span class="value mono">${br.extendedPanIdHex}</span>
26428
+ </div>
26429
+ ` : A}
26430
+ ${br.partitionIdHex ? b`
26431
+ <div class="info-row">
26432
+ <span class="label">Partition ID:</span>
26433
+ <span class="value mono">${br.partitionIdHex}</span>
26434
+ </div>
26435
+ ` : A}
26436
+ ${br.activeTimestampHex ? b`
26437
+ <div class="info-row">
26438
+ <span class="label">Active timestamp:</span>
26439
+ <span class="value mono">${br.activeTimestampHex}</span>
26440
+ </div>
26441
+ ` : A}
26442
+ ${this._renderStateBitmap(br.stateBitmapHex)}
26443
+ ${br.domainName ? b`
26444
+ <div class="info-row">
26445
+ <span class="label">Domain:</span>
26446
+ <span class="value">${br.domainName}</span>
26447
+ </div>
26448
+ ` : A}
26449
+ ${br.borderAgentIdHex ? b`
26450
+ <div class="info-row">
26451
+ <span class="label">Border agent ID:</span>
26452
+ <span class="value mono">${br.borderAgentIdHex}</span>
26453
+ </div>
26454
+ ` : A}
26455
+ `;
26456
+ }
26457
+ /**
26458
+ * Address rows for a Border Router (hostname, IPs, ports, sources).
26459
+ */
26460
+ _renderBorderRouterAddressRows(br) {
26461
+ const hasAny = br.hostname !== void 0 || br.addresses.length > 0 || br.meshcopPort !== void 0 || br.trelPort !== void 0 || br.sources.length > 0;
26462
+ if (!hasAny) return A;
26463
+ return b`
26464
+ ${br.hostname ? b`
26465
+ <div class="info-row">
26466
+ <span class="label">Hostname:</span>
26467
+ <span class="value mono">${br.hostname}</span>
26468
+ </div>
26469
+ ` : A}
26470
+ ${br.addresses.map(addr => b`
26471
+ <div class="info-row">
26472
+ <span class="label">Address:</span>
26473
+ <span class="value mono">${addr}</span>
26474
+ </div>
26475
+ `)}
26476
+ ${br.meshcopPort !== void 0 ? b`
26477
+ <div class="info-row">
26478
+ <span class="label">meshcop port:</span>
26479
+ <span class="value">${br.meshcopPort}</span>
26480
+ </div>
26481
+ ` : A}
26482
+ ${br.trelPort !== void 0 ? b`
26483
+ <div class="info-row">
26484
+ <span class="label">trel port:</span>
26485
+ <span class="value">${br.trelPort}</span>
26486
+ </div>
26487
+ ` : A}
26488
+ ${br.sources.length > 0 ? b`
26489
+ <div class="info-row">
26490
+ <span class="label">Sources:</span>
26491
+ <span class="value">${br.sources.join(", ")}</span>
26492
+ </div>
26493
+ ` : A}
26494
+ `;
26495
+ }
26496
+ _renderBorderRouterInfo(deviceId) {
26497
+ const device = this.unknownDevices.get(deviceId);
26498
+ if (!device || device.kind !== "br") {
26499
+ return b` <p>Border router data not available</p> `;
26500
+ }
26501
+ const br = device;
26502
+ const networkRows = this._renderBorderRouterNetworkRows(br);
26503
+ const addressRows = this._renderBorderRouterAddressRows(br);
26504
+ return b`
26121
26505
  <div class="section">
26122
- <p class="hint-text">
26123
- This device appears in Thread neighbor tables but is not commissioned to this fabric. It may be a
26124
- Thread Border Router or a device from another Matter ecosystem.
26125
- </p>
26506
+ <h4>Border Router</h4>
26507
+ ${this._renderBorderRouterIdentityRows(br, true)}
26508
+ ${br.bestRssi !== null ? b`
26509
+ <div class="info-row">
26510
+ <span class="label">Best RSSI:</span>
26511
+ <span class="value">${br.bestRssi} dBm</span>
26512
+ </div>
26513
+ ` : A}
26126
26514
  </div>
26515
+
26516
+ ${networkRows !== A ? b`
26517
+ <md-divider></md-divider>
26518
+ <div class="section">
26519
+ <h4>Thread Network</h4>
26520
+ ${networkRows}
26521
+ </div>
26522
+ ` : A}
26523
+ ${addressRows !== A ? b`
26524
+ <md-divider></md-divider>
26525
+ <div class="section">
26526
+ <h4>Addresses</h4>
26527
+ ${addressRows}
26528
+ </div>
26529
+ ` : A}
26530
+ ${this._renderExternalDeviceNeighbors(deviceId)}
26127
26531
  `;
26128
26532
  }
26129
26533
  /**
@@ -26133,8 +26537,8 @@ let NetworkDetails = class extends i$4 {
26133
26537
  if (this.selectedNodeId === null) return false;
26134
26538
  const isAccessPoint = typeof this.selectedNodeId === "string" && this.selectedNodeId.startsWith("ap_");
26135
26539
  if (isAccessPoint) return false;
26136
- const isUnknown = typeof this.selectedNodeId === "string" && this.selectedNodeId.startsWith("unknown_");
26137
- if (isUnknown) {
26540
+ const isExternal = typeof this.selectedNodeId === "string" && (this.selectedNodeId.startsWith("unknown_") || this.selectedNodeId.startsWith("br_"));
26541
+ if (isExternal) {
26138
26542
  return this._getOnlineSeenByNodes().length > 0;
26139
26543
  }
26140
26544
  const node = this.nodes[this.selectedNodeId.toString()];
@@ -26147,7 +26551,7 @@ let NetworkDetails = class extends i$4 {
26147
26551
  * Get the type of the currently selected node for dialog variant.
26148
26552
  */
26149
26553
  _getSelectedNodeType() {
26150
- if (typeof this.selectedNodeId === "string" && this.selectedNodeId.startsWith("unknown_")) {
26554
+ if (typeof this.selectedNodeId === "string" && (this.selectedNodeId.startsWith("unknown_") || this.selectedNodeId.startsWith("br_"))) {
26151
26555
  return "unknown";
26152
26556
  }
26153
26557
  const node = this.nodes[this.selectedNodeId.toString()];
@@ -26164,15 +26568,11 @@ let NetworkDetails = class extends i$4 {
26164
26568
  if (!node) return [];
26165
26569
  const networkType = getNetworkType(node);
26166
26570
  if (networkType === "thread") {
26167
- const extAddrMap = buildExtAddrMap(this.nodes);
26168
- const rloc16Map = buildRloc16Map(this.nodes);
26169
- const connections = getNodeConnections(nodeId, this.nodes, extAddrMap, rloc16Map);
26571
+ const connections = getNodeConnectionsFromPairs(nodeId, this.threadEdgePairs, this.nodes);
26170
26572
  return connections.filter(conn => {
26171
- if (typeof conn.connectedNodeId === "string" && conn.connectedNodeId.startsWith("unknown_")) {
26172
- return false;
26173
- }
26174
- const connectedNode = this.nodes[String(conn.connectedNodeId)];
26175
- return (connectedNode === null || connectedNode === void 0 ? void 0 : connectedNode.available) === true;
26573
+ var _conn$connectedNode;
26574
+ if (conn.isUnknown) return false;
26575
+ return ((_conn$connectedNode = conn.connectedNode) === null || _conn$connectedNode === void 0 ? void 0 : _conn$connectedNode.available) === true;
26176
26576
  }).map(conn => String(conn.connectedNodeId));
26177
26577
  }
26178
26578
  return [];
@@ -26181,12 +26581,12 @@ let NetworkDetails = class extends i$4 {
26181
26581
  * Get online nodes that see an unknown device.
26182
26582
  */
26183
26583
  _getOnlineSeenByNodes() {
26184
- if (typeof this.selectedNodeId !== "string" || !this.selectedNodeId.startsWith("unknown_")) {
26584
+ if (typeof this.selectedNodeId !== "string" || !this.selectedNodeId.startsWith("unknown_") && !this.selectedNodeId.startsWith("br_")) {
26185
26585
  return [];
26186
26586
  }
26187
- const unknown = this.unknownDevices.get(this.selectedNodeId);
26188
- if (!unknown) return [];
26189
- return unknown.seenBy.filter(nodeId => {
26587
+ const device = this.unknownDevices.get(this.selectedNodeId);
26588
+ if (!device) return [];
26589
+ return device.seenBy.filter(nodeId => {
26190
26590
  const node = this.nodes[nodeId.toString()];
26191
26591
  return (node === null || node === void 0 ? void 0 : node.available) === true;
26192
26592
  });
@@ -26195,11 +26595,19 @@ let NetworkDetails = class extends i$4 {
26195
26595
  * Get the name of the selected node for display in dialog.
26196
26596
  */
26197
26597
  _getSelectedNodeName() {
26198
- if (typeof this.selectedNodeId === "string" && this.selectedNodeId.startsWith("unknown_")) {
26199
- const unknown = this.unknownDevices.get(this.selectedNodeId);
26200
- if (!unknown) return "External Device";
26201
- const typeLabel = unknown.isRouter ? "External Router" : "External Device";
26202
- return `${typeLabel} (${unknown.extAddressHex.slice(-8)})`;
26598
+ if (typeof this.selectedNodeId === "string") {
26599
+ if (this.selectedNodeId.startsWith("br_")) {
26600
+ const device = this.unknownDevices.get(this.selectedNodeId);
26601
+ if (!device || device.kind !== "br") return "Border Router";
26602
+ const label = device.networkName ?? device.vendorName ?? "Border Router";
26603
+ return `${label} (${device.extAddressHex.slice(-8)})`;
26604
+ }
26605
+ if (this.selectedNodeId.startsWith("unknown_")) {
26606
+ const device = this.unknownDevices.get(this.selectedNodeId);
26607
+ if (!device || device.kind !== "unknown") return "External Device";
26608
+ const typeLabel = device.isRouter ? "External Router" : "External Device";
26609
+ return `${typeLabel} (${device.extAddressHex.slice(-8)})`;
26610
+ }
26203
26611
  }
26204
26612
  const node = this.nodes[this.selectedNodeId.toString()];
26205
26613
  return node ? getDeviceName(node) : "Unknown";
@@ -26209,6 +26617,10 @@ let NetworkDetails = class extends i$4 {
26209
26617
  }
26210
26618
  _handleDialogClose() {
26211
26619
  this._showUpdateDialog = false;
26620
+ this.dispatchEvent(new CustomEvent("connections-updated", {
26621
+ bubbles: true,
26622
+ composed: true
26623
+ }));
26212
26624
  }
26213
26625
  _renderWiFiAccessPointInfo(apId) {
26214
26626
  const ap = this.wifiAccessPoints.get(apId);
@@ -26274,6 +26686,33 @@ let NetworkDetails = class extends i$4 {
26274
26686
  </div>
26275
26687
  `;
26276
26688
  }
26689
+ /**
26690
+ * Annotation shown on a commissioned Thread node that is also a discovered Border Router.
26691
+ * Mirrors the BR Identity/Network/Addresses sections, sans the redundant ext-address row.
26692
+ */
26693
+ _renderCommissionedNodeBorderRouterAnnotation(node) {
26694
+ const xaHex = getThreadExtendedAddressHex(node);
26695
+ if (!xaHex) return A;
26696
+ const br = this.borderRouters.get(xaHex);
26697
+ if (!br) return A;
26698
+ const networkRows = this._renderBorderRouterNetworkRows(br);
26699
+ const addressRows = this._renderBorderRouterAddressRows(br);
26700
+ return b`
26701
+ <md-divider></md-divider>
26702
+ <div class="section">
26703
+ <h4>Also a Border Router</h4>
26704
+ ${this._renderBorderRouterIdentityRows(br, false)}
26705
+ ${networkRows !== A ? b`
26706
+ <div class="subsection-label">Thread Network</div>
26707
+ ${networkRows}
26708
+ ` : A}
26709
+ ${addressRows !== A ? b`
26710
+ <div class="subsection-label">Addresses</div>
26711
+ ${addressRows}
26712
+ ` : A}
26713
+ </div>
26714
+ `;
26715
+ }
26277
26716
  render() {
26278
26717
  if (this.selectedNodeId === null) {
26279
26718
  return b`
@@ -26320,6 +26759,44 @@ let NetworkDetails = class extends i$4 {
26320
26759
  ` : A}
26321
26760
  `;
26322
26761
  }
26762
+ const borderRouterId = typeof this.selectedNodeId === "string" && this.selectedNodeId.startsWith("br_") ? this.selectedNodeId : null;
26763
+ if (borderRouterId !== null) {
26764
+ const onlineSeenByNodes = this._getOnlineSeenByNodes();
26765
+ return b`
26766
+ <div class="details-panel">
26767
+ <div class="header">
26768
+ <h3>Border Router</h3>
26769
+ <div class="header-actions">
26770
+ ${onlineSeenByNodes.length > 0 ? b`
26771
+ <button
26772
+ class="action-button"
26773
+ @click=${this._handleUpdateConnections}
26774
+ aria-label="Update connection data"
26775
+ title="Update connection data"
26776
+ >
26777
+ <ha-svg-icon .path=${mdiRefresh}></ha-svg-icon>
26778
+ </button>
26779
+ ` : A}
26780
+ <button class="close-button" @click=${this._handleClose} aria-label="Close details panel">
26781
+ <ha-svg-icon .path=${mdiClose}></ha-svg-icon>
26782
+ </button>
26783
+ </div>
26784
+ </div>
26785
+ <div class="content">${this._renderBorderRouterInfo(borderRouterId)}</div>
26786
+ </div>
26787
+ ${this._showUpdateDialog ? b`
26788
+ <update-connections-dialog
26789
+ .client=${this.client}
26790
+ .nodes=${this.nodes}
26791
+ selectedNodeType="unknown"
26792
+ .selectedNodeName=${this._getSelectedNodeName()}
26793
+ .selectedNodeId=${this.selectedNodeId}
26794
+ .onlineNeighborIds=${onlineSeenByNodes}
26795
+ @dialog-closed=${this._handleDialogClose}
26796
+ ></update-connections-dialog>
26797
+ ` : A}
26798
+ `;
26799
+ }
26323
26800
  const isAccessPoint = typeof this.selectedNodeId === "string" && this.selectedNodeId.startsWith("ap_");
26324
26801
  if (isAccessPoint) {
26325
26802
  return b`
@@ -26368,7 +26845,9 @@ let NetworkDetails = class extends i$4 {
26368
26845
  </button>
26369
26846
  </div>
26370
26847
  </div>
26371
- <div class="content">${this._renderNodeInfo(node)}</div>
26848
+ <div class="content">
26849
+ ${this._renderNodeInfo(node)}${this._renderCommissionedNodeBorderRouterAnnotation(node)}
26850
+ </div>
26372
26851
  <div class="footer">
26373
26852
  <a href="#node/${this.selectedNodeId}" class="view-link">View node details</a>
26374
26853
  </div>
@@ -26499,6 +26978,15 @@ NetworkDetails.styles = [reducedMotionStyles, i$7`
26499
26978
  letter-spacing: 0.5px;
26500
26979
  }
26501
26980
 
26981
+ .subsection-label {
26982
+ margin: 12px 0 4px 0;
26983
+ font-size: 0.75rem;
26984
+ font-weight: 500;
26985
+ color: var(--md-sys-color-on-surface-variant, #666);
26986
+ text-transform: uppercase;
26987
+ letter-spacing: 0.4px;
26988
+ }
26989
+
26502
26990
  .info-row {
26503
26991
  display: flex;
26504
26992
  justify-content: space-between;
@@ -26582,6 +27070,14 @@ NetworkDetails.styles = [reducedMotionStyles, i$7`
26582
27070
  opacity: 0.8;
26583
27071
  }
26584
27072
 
27073
+ .direction-hint.reverse-only {
27074
+ font-style: normal;
27075
+ font-weight: 500;
27076
+ opacity: 1;
27077
+ color: var(--md-sys-color-error, #b3261e);
27078
+ cursor: help;
27079
+ }
27080
+
26585
27081
  .route-info {
26586
27082
  color: var(--md-sys-color-tertiary, #7d5260);
26587
27083
  font-size: 0.85em;
@@ -26653,15 +27149,33 @@ NetworkDetails.styles = [reducedMotionStyles, i$7`
26653
27149
  }
26654
27150
  `];
26655
27151
  __decorateClass$8([n$2()], NetworkDetails.prototype, "selectedNodeId", 2);
27152
+ __decorateClass$8([n$2({
27153
+ type: Boolean
27154
+ })], NetworkDetails.prototype, "hideOfflineNodes", 2);
27155
+ __decorateClass$8([n$2({
27156
+ type: Boolean
27157
+ })], NetworkDetails.prototype, "hideWeakSignalEdges", 2);
27158
+ __decorateClass$8([n$2({
27159
+ type: Boolean
27160
+ })], NetworkDetails.prototype, "hideMediumSignalEdges", 2);
27161
+ __decorateClass$8([n$2({
27162
+ type: Boolean
27163
+ })], NetworkDetails.prototype, "hideStrongSignalEdges", 2);
26656
27164
  __decorateClass$8([n$2({
26657
27165
  type: Object
26658
27166
  })], NetworkDetails.prototype, "nodes", 2);
26659
27167
  __decorateClass$8([n$2({
26660
27168
  type: Object
26661
27169
  })], NetworkDetails.prototype, "unknownDevices", 2);
27170
+ __decorateClass$8([n$2({
27171
+ attribute: false
27172
+ })], NetworkDetails.prototype, "borderRouters", 2);
26662
27173
  __decorateClass$8([n$2({
26663
27174
  type: Object
26664
27175
  })], NetworkDetails.prototype, "wifiAccessPoints", 2);
27176
+ __decorateClass$8([n$2({
27177
+ type: Object
27178
+ })], NetworkDetails.prototype, "threadEdgePairs", 2);
26665
27179
  __decorateClass$8([c$4({
26666
27180
  context: clientContext
26667
27181
  })], NetworkDetails.prototype, "client", 2);
@@ -34573,11 +35087,11 @@ if(valueMin!==undefined&&valueMax!==undefined){for(id in obj){if(Object.prototyp
34573
35087
  */Network.prototype.clusterOutliers=function(){return this.clustering.clusterOutliers.apply(this.clustering,arguments);};Network.prototype.getSeed=function(){return this.layoutEngine.getSeed.apply(this.layoutEngine,arguments);};Network.prototype.enableEditMode=function(){return this.manipulation.enableEditMode.apply(this.manipulation,arguments);};Network.prototype.disableEditMode=function(){return this.manipulation.disableEditMode.apply(this.manipulation,arguments);};Network.prototype.addNodeMode=function(){return this.manipulation.addNodeMode.apply(this.manipulation,arguments);};Network.prototype.editNode=function(){return this.manipulation.editNode.apply(this.manipulation,arguments);};Network.prototype.editNodeMode=function(){console.warn("Deprecated: Please use editNode instead of editNodeMode.");return this.manipulation.editNode.apply(this.manipulation,arguments);};Network.prototype.addEdgeMode=function(){return this.manipulation.addEdgeMode.apply(this.manipulation,arguments);};Network.prototype.editEdgeMode=function(){return this.manipulation.editEdgeMode.apply(this.manipulation,arguments);};Network.prototype.deleteSelected=function(){return this.manipulation.deleteSelected.apply(this.manipulation,arguments);};Network.prototype.getPositions=function(){return this.nodesHandler.getPositions.apply(this.nodesHandler,arguments);};Network.prototype.getPosition=function(){return this.nodesHandler.getPosition.apply(this.nodesHandler,arguments);};Network.prototype.storePositions=function(){return this.nodesHandler.storePositions.apply(this.nodesHandler,arguments);};Network.prototype.moveNode=function(){return this.nodesHandler.moveNode.apply(this.nodesHandler,arguments);};Network.prototype.getBoundingBox=function(){return this.nodesHandler.getBoundingBox.apply(this.nodesHandler,arguments);};Network.prototype.getConnectedNodes=function(objectId){if(this.body.nodes[objectId]!==undefined){return this.nodesHandler.getConnectedNodes.apply(this.nodesHandler,arguments);}else {return this.edgesHandler.getConnectedNodes.apply(this.edgesHandler,arguments);}};Network.prototype.getConnectedEdges=function(){return this.nodesHandler.getConnectedEdges.apply(this.nodesHandler,arguments);};Network.prototype.startSimulation=function(){return this.physics.startSimulation.apply(this.physics,arguments);};Network.prototype.stopSimulation=function(){return this.physics.stopSimulation.apply(this.physics,arguments);};Network.prototype.stabilize=function(){return this.physics.stabilize.apply(this.physics,arguments);};Network.prototype.getSelection=function(){return this.selectionHandler.getSelection.apply(this.selectionHandler,arguments);};Network.prototype.setSelection=function(){return this.selectionHandler.setSelection.apply(this.selectionHandler,arguments);};Network.prototype.getSelectedNodes=function(){return this.selectionHandler.getSelectedNodeIds.apply(this.selectionHandler,arguments);};Network.prototype.getSelectedEdges=function(){return this.selectionHandler.getSelectedEdgeIds.apply(this.selectionHandler,arguments);};Network.prototype.getNodeAt=function(){const node=this.selectionHandler.getNodeAt.apply(this.selectionHandler,arguments);if(node!==undefined&&node.id!==undefined){return node.id;}return node;};Network.prototype.getEdgeAt=function(){const edge=this.selectionHandler.getEdgeAt.apply(this.selectionHandler,arguments);if(edge!==undefined&&edge.id!==undefined){return edge.id;}return edge;};Network.prototype.selectNodes=function(){return this.selectionHandler.selectNodes.apply(this.selectionHandler,arguments);};Network.prototype.selectEdges=function(){return this.selectionHandler.selectEdges.apply(this.selectionHandler,arguments);};Network.prototype.unselectAll=function(){this.selectionHandler.unselectAll.apply(this.selectionHandler,arguments);this.selectionHandler.commitWithoutEmitting.apply(this.selectionHandler);this.redraw();};Network.prototype.redraw=function(){return this.renderer.redraw.apply(this.renderer,arguments);};Network.prototype.getScale=function(){return this.view.getScale.apply(this.view,arguments);};Network.prototype.getViewPosition=function(){return this.view.getViewPosition.apply(this.view,arguments);};Network.prototype.fit=function(){return this.view.fit.apply(this.view,arguments);};Network.prototype.moveTo=function(){return this.view.moveTo.apply(this.view,arguments);};Network.prototype.focus=function(){return this.view.focus.apply(this.view,arguments);};Network.prototype.releaseNode=function(){return this.view.releaseNode.apply(this.view,arguments);};Network.prototype.getOptionsFromConfigurator=function(){let options={};if(this.configurator){options=this.configurator.getOptions.apply(this.configurator);}return options;};
34574
35088
 
34575
35089
  var _staticBlock;
34576
- var __defProp$4 = Object.defineProperty;
35090
+ var __defProp$5 = Object.defineProperty;
34577
35091
  var __decorateClass$7 = (decorators, target, key, kind) => {
34578
35092
  var result = void 0 ;
34579
35093
  for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (decorator(target, key, result) ) || result;
34580
- if (result) __defProp$4(target, key, result);
35094
+ if (result) __defProp$5(target, key, result);
34581
35095
  return result;
34582
35096
  };
34583
35097
  class BaseNetworkGraph extends i$4 {
@@ -34908,6 +35422,15 @@ class BaseNetworkGraph extends i$4 {
34908
35422
  }
34909
35423
  });
34910
35424
  }
35425
+ /**
35426
+ * Deselects all nodes, clears highlights, and restores default styling.
35427
+ */
35428
+ deselectAll() {
35429
+ if (!this._network) return;
35430
+ this._selectedNodeId = null;
35431
+ this._network.unselectAll();
35432
+ this._clearHighlights();
35433
+ }
34911
35434
  _dispatchNodeSelected(nodeId) {
34912
35435
  this.dispatchEvent(new CustomEvent("node-selected", {
34913
35436
  detail: {
@@ -35071,24 +35594,49 @@ __decorateClass$7([n$2({
35071
35594
  __decorateClass$7([r$2()], BaseNetworkGraph.prototype, "_selectedNodeId");
35072
35595
  __decorateClass$7([r$2()], BaseNetworkGraph.prototype, "_physicsEnabled");
35073
35596
 
35597
+ var __defProp$4 = Object.defineProperty;
35074
35598
  var __getOwnPropDesc$6 = Object.getOwnPropertyDescriptor;
35075
35599
  var __decorateClass$6 = (decorators, target, key, kind) => {
35076
35600
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$6(target, key) : target;
35077
- for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (decorator(result)) || result;
35601
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
35602
+ if (kind && result) __defProp$4(target, key, result);
35078
35603
  return result;
35079
35604
  };
35080
35605
  let ThreadGraph = class extends BaseNetworkGraph {
35081
35606
  constructor() {
35082
35607
  super(...arguments);
35083
- /** Cache of unknown devices for the current render */
35608
+ this.borderRouters = /* @__PURE__ */new Map();
35609
+ this.hideOfflineNodes = false;
35610
+ this.hideWeakSignalEdges = false;
35611
+ this.hideMediumSignalEdges = false;
35612
+ this.hideStrongSignalEdges = false;
35613
+ /** Cache of external Thread devices (Border Routers and unknown) for the current render */
35084
35614
  this._unknownDevices = [];
35085
- /** Cached map of unknown devices (rebuilt in _updateGraph) */
35615
+ /** Cached map of external Thread devices (rebuilt in _updateGraph) */
35086
35616
  this._unknownDevicesMapCache = /* @__PURE__ */new Map();
35087
- }
35088
- /** Get unknown devices as a map for use by details panel */
35617
+ /** All computed edge pairs (rebuilt in _updateGraph) */
35618
+ this._edgePairs = /* @__PURE__ */new Map();
35619
+ /** Base state of each edge after filter+dedup, before highlight */
35620
+ this._edgeBaseState = /* @__PURE__ */new Map();
35621
+ /** Whether highlight is currently active */
35622
+ this._isHighlighted = false;
35623
+ /** Node ID currently highlighted (for icon restoration on clear) */
35624
+ this._highlightedNodeId = null;
35625
+ }
35626
+ /** Get external Thread devices as a map for use by details panel */
35089
35627
  get unknownDevicesMap() {
35090
35628
  return this._unknownDevicesMapCache;
35091
35629
  }
35630
+ /** Get computed edge pairs (for potential use by other components) */
35631
+ get edgePairs() {
35632
+ return this._edgePairs;
35633
+ }
35634
+ updated(changedProperties) {
35635
+ super.updated(changedProperties);
35636
+ if (changedProperties.has("hideOfflineNodes") || changedProperties.has("hideWeakSignalEdges") || changedProperties.has("hideMediumSignalEdges") || changedProperties.has("hideStrongSignalEdges") || changedProperties.has("borderRouters")) {
35637
+ this._debouncedUpdateGraph();
35638
+ }
35639
+ }
35092
35640
  /**
35093
35641
  * Searches for a Thread node (known or unknown) by extended address and selects it.
35094
35642
  * Accepts formats like:
@@ -35123,73 +35671,160 @@ let ThreadGraph = class extends BaseNetworkGraph {
35123
35671
  _updateGraph() {
35124
35672
  if (!this._nodesDataSet || !this._edgesDataSet) return;
35125
35673
  this._clearOriginalEdgeColors();
35674
+ this._edgeBaseState.clear();
35675
+ this._isHighlighted = false;
35126
35676
  const threadNodes = Object.values(this.nodes).filter(node => getNetworkType(node) === "thread");
35127
35677
  if (threadNodes.length === 0) {
35128
35678
  this._nodesDataSet.clear();
35129
35679
  this._edgesDataSet.clear();
35130
35680
  this._unknownDevices = [];
35131
35681
  this._unknownDevicesMapCache.clear();
35682
+ this._edgePairs.clear();
35132
35683
  return;
35133
35684
  }
35134
35685
  const extAddrMap = buildExtAddrMap(this.nodes);
35135
35686
  const rloc16Map = buildRloc16Map(this.nodes);
35136
- this._unknownDevices = findUnknownDevices(this.nodes, extAddrMap, rloc16Map);
35687
+ this._unknownDevices = findUnknownDevices(this.nodes, extAddrMap, rloc16Map, this.borderRouters);
35137
35688
  this._unknownDevicesMapCache.clear();
35138
35689
  for (const device of this._unknownDevices) {
35139
- this._unknownDevicesMapCache.set(device.id, {
35140
- extAddressHex: device.extAddressHex,
35141
- isRouter: device.isRouter,
35142
- seenBy: device.seenBy,
35143
- bestRssi: device.bestRssi
35144
- });
35690
+ this._unknownDevicesMapCache.set(device.id, device);
35145
35691
  }
35146
- const connections = buildThreadConnections(this.nodes, extAddrMap, rloc16Map, this._unknownDevices);
35692
+ this._edgePairs = buildThreadEdgePairs(this.nodes, extAddrMap, rloc16Map, this._unknownDevices);
35693
+ const hiddenNodeIds = /* @__PURE__ */new Set();
35147
35694
  const graphNodes = threadNodes.map(node => {
35148
35695
  const nodeId = String(node.node_id);
35149
35696
  const threadRole = getThreadRole(node);
35150
- const isSelected = nodeId === String(this._selectedNodeId);
35151
35697
  const isOffline = node.available === false;
35698
+ const shouldHide = this.hideOfflineNodes && isOffline;
35699
+ if (shouldHide) {
35700
+ hiddenNodeIds.add(nodeId);
35701
+ }
35152
35702
  return {
35153
35703
  id: nodeId,
35154
35704
  label: getDeviceName(node),
35155
- image: createNodeIconDataUrl(node, threadRole, isSelected, isOffline),
35705
+ image: createNodeIconDataUrl(node, threadRole, false, isOffline),
35156
35706
  shape: "image",
35157
35707
  networkType: "thread",
35158
35708
  threadRole,
35159
- offline: isOffline
35709
+ offline: isOffline,
35710
+ hidden: shouldHide
35160
35711
  };
35161
35712
  });
35162
- for (const unknown of this._unknownDevices) {
35163
- const isSelected = unknown.id === this._selectedNodeId;
35164
- const typeLabel = unknown.isRouter ? "External Router" : "External Device";
35165
- graphNodes.push({
35166
- id: unknown.id,
35167
- label: `${typeLabel} (${unknown.extAddressHex.slice(-8)})`,
35168
- image: createUnknownDeviceIconDataUrl(unknown.isRouter, isSelected),
35169
- shape: "image",
35170
- networkType: "thread",
35171
- isUnknown: true
35172
- });
35713
+ for (const device of this._unknownDevices) {
35714
+ const isSelected = device.id === this._selectedNodeId;
35715
+ let shouldHide = false;
35716
+ if (this.hideOfflineNodes) {
35717
+ const hasOnlineSeenBy = device.seenBy.some(nodeId => {
35718
+ const node = this.nodes[nodeId];
35719
+ return node && node.available !== false;
35720
+ });
35721
+ shouldHide = !hasOnlineSeenBy;
35722
+ }
35723
+ if (shouldHide) {
35724
+ hiddenNodeIds.add(device.id);
35725
+ }
35726
+ if (device.kind === "br") {
35727
+ var _device$hostname;
35728
+ const hostname = (_device$hostname = device.hostname) === null || _device$hostname === void 0 ? void 0 : _device$hostname.replace(/\.$/, "").replace(/\.local$/i, "");
35729
+ const top = (hostname ?? device.networkName ?? "Border Router").slice(0, 24);
35730
+ const suffix = hostname !== void 0 && device.networkName !== void 0 && device.networkName !== top ? `
35731
+ ${device.networkName}` : "";
35732
+ const label = `${top}${suffix}`;
35733
+ graphNodes.push({
35734
+ id: device.id,
35735
+ label,
35736
+ image: createBorderRouterIconDataUrl(isSelected),
35737
+ shape: "image",
35738
+ networkType: "thread",
35739
+ isUnknown: false,
35740
+ hidden: shouldHide
35741
+ });
35742
+ } else {
35743
+ const typeLabel = device.isRouter ? "External Router" : "External Device";
35744
+ const suffix = device.networkName !== void 0 ? `
35745
+ ${device.networkName}` : "";
35746
+ graphNodes.push({
35747
+ id: device.id,
35748
+ label: `${typeLabel} (${device.extAddressHex.slice(-8)})${suffix}`,
35749
+ image: createUnknownDeviceIconDataUrl(device.isRouter, isSelected),
35750
+ shape: "image",
35751
+ networkType: "thread",
35752
+ isUnknown: true,
35753
+ hidden: shouldHide
35754
+ });
35755
+ }
35756
+ }
35757
+ const graphEdges = [];
35758
+ for (const pair of this._edgePairs.values()) {
35759
+ const edgesInPair = [];
35760
+ for (const conn of [pair.edgeAB, pair.edgeBA]) {
35761
+ if (!conn) continue;
35762
+ const fromId = String(conn.fromNodeId);
35763
+ const toId = String(conn.toNodeId);
35764
+ const isToUnknown = toId.startsWith("unknown_") || toId.startsWith("br_");
35765
+ const fromNode = this.nodes[fromId];
35766
+ const toNode = this.nodes[toId];
35767
+ const hasOfflineEndpoint = (fromNode === null || fromNode === void 0 ? void 0 : fromNode.available) === false || (toNode === null || toNode === void 0 ? void 0 : toNode.available) === false;
35768
+ let filterHidden = false;
35769
+ if (hiddenNodeIds.has(fromId) || hiddenNodeIds.has(toId)) {
35770
+ filterHidden = true;
35771
+ }
35772
+ if (!filterHidden && this.hideWeakSignalEdges && conn.signalLevel === "weak") {
35773
+ filterHidden = true;
35774
+ }
35775
+ if (!filterHidden && this.hideMediumSignalEdges && conn.signalLevel === "medium") {
35776
+ filterHidden = true;
35777
+ }
35778
+ if (!filterHidden && this.hideStrongSignalEdges && conn.signalLevel === "strong") {
35779
+ filterHidden = true;
35780
+ }
35781
+ const edgeId = `edge_${fromId}_${toId}`;
35782
+ const visEdge = {
35783
+ id: edgeId,
35784
+ from: fromId,
35785
+ to: toId,
35786
+ color: {
35787
+ color: conn.signalColor,
35788
+ highlight: conn.signalColor
35789
+ },
35790
+ width: 2,
35791
+ title: conn.rssi !== null ? `RSSI: ${conn.rssi} dBm, LQI: ${conn.lqi}` : `LQI: ${conn.lqi}`,
35792
+ dashes: isToUnknown || hasOfflineEndpoint,
35793
+ hidden: filterHidden,
35794
+ pairKey: pair.pairKey,
35795
+ reportingNodeId: fromId
35796
+ };
35797
+ edgesInPair.push({
35798
+ conn,
35799
+ visEdge,
35800
+ filterHidden
35801
+ });
35802
+ }
35803
+ const visibleInPair = edgesInPair.filter(e => !e.visEdge.hidden);
35804
+ if (visibleInPair.length > 1) {
35805
+ visibleInPair.sort((a, b) => getEdgeSignalScore(a.conn) - getEdgeSignalScore(b.conn));
35806
+ for (let i = 1; i < visibleInPair.length; i++) {
35807
+ visibleInPair[i].visEdge.hidden = true;
35808
+ }
35809
+ }
35810
+ for (const e of edgesInPair) {
35811
+ const isHidden = e.visEdge.hidden ?? false;
35812
+ let hiddenReason = "visible";
35813
+ if (isHidden) {
35814
+ hiddenReason = e.filterHidden ? "filter" : "dedup";
35815
+ }
35816
+ this._edgeBaseState.set(e.visEdge.id, {
35817
+ hiddenReason,
35818
+ width: e.visEdge.width,
35819
+ color: {
35820
+ color: e.visEdge.color.color,
35821
+ highlight: e.visEdge.color.highlight
35822
+ },
35823
+ dashes: e.visEdge.dashes ?? false
35824
+ });
35825
+ graphEdges.push(e.visEdge);
35826
+ }
35173
35827
  }
35174
- const graphEdges = connections.map((conn, index) => {
35175
- const isToUnknown = typeof conn.toNodeId === "string" && conn.toNodeId.startsWith("unknown_");
35176
- const fromNode = this.nodes[String(conn.fromNodeId)];
35177
- const toNode = this.nodes[String(conn.toNodeId)];
35178
- const hasOfflineEndpoint = (fromNode === null || fromNode === void 0 ? void 0 : fromNode.available) === false || (toNode === null || toNode === void 0 ? void 0 : toNode.available) === false;
35179
- return {
35180
- id: `edge_${index}`,
35181
- from: conn.fromNodeId,
35182
- to: conn.toNodeId,
35183
- color: {
35184
- color: conn.signalColor,
35185
- highlight: conn.signalColor
35186
- },
35187
- width: 2,
35188
- title: conn.rssi !== null ? `RSSI: ${conn.rssi} dBm, LQI: ${conn.lqi}` : `LQI: ${conn.lqi}`,
35189
- dashes: isToUnknown || hasOfflineEndpoint
35190
- // Dashed lines to unknown or offline devices
35191
- };
35192
- });
35193
35828
  const existingNodeIds = this._nodesDataSet.getIds();
35194
35829
  const newNodeIds = new Set(graphNodes.map(n => n.id));
35195
35830
  const nodesToRemove = existingNodeIds.filter(id => !newNodeIds.has(id));
@@ -35199,20 +35834,278 @@ let ThreadGraph = class extends BaseNetworkGraph {
35199
35834
  this._nodesDataSet.update(graphNodes);
35200
35835
  this._edgesDataSet.clear();
35201
35836
  this._edgesDataSet.add(graphEdges);
35837
+ if (this._selectedNodeId !== null) {
35838
+ this._highlightConnections(this._selectedNodeId);
35839
+ }
35840
+ }
35841
+ /**
35842
+ * Highlights edges connected to the selected node with swap/arrow logic.
35843
+ *
35844
+ * For each visible edge connected to the highlighted node:
35845
+ * - If the visible edge comes from the remote node AND there is a
35846
+ * dedup-hidden edge from the highlighted node → SWAP: show the
35847
+ * highlighted node's edge instead (its signal is better or equal,
35848
+ * but we prefer the highlighted node's perspective).
35849
+ * - Otherwise → thicken the edge. If the pair is truly one-way (only
35850
+ * one of edgeAB/edgeBA exists), also draw an arrow in the data
35851
+ * direction so asymmetric visibility is visible at a glance.
35852
+ */
35853
+ _highlightConnections(nodeId) {
35854
+ if (!this._edgesDataSet || !this._nodesDataSet) return;
35855
+ const nodeIdStr = String(nodeId);
35856
+ if (this._isHighlighted && this._highlightedNodeId === nodeIdStr) return;
35857
+ if (this._isHighlighted) {
35858
+ this._restoreEdgeBaseState();
35859
+ }
35860
+ const allEdges = this._edgesDataSet.get();
35861
+ const dimmedColor = this._getDimmedEdgeColor();
35862
+ const edgesByPair = /* @__PURE__ */new Map();
35863
+ for (const edge of allEdges) {
35864
+ if (edge.pairKey) {
35865
+ const list = edgesByPair.get(edge.pairKey) ?? [];
35866
+ list.push(edge);
35867
+ edgesByPair.set(edge.pairKey, list);
35868
+ }
35869
+ }
35870
+ const connectedNodeIds = /* @__PURE__ */new Set();
35871
+ const edgeUpdates = {};
35872
+ for (const edge of allEdges) {
35873
+ const fromStr = String(edge.from);
35874
+ const toStr = String(edge.to);
35875
+ const isConnected = fromStr === nodeIdStr || toStr === nodeIdStr;
35876
+ if (!isConnected) {
35877
+ const baseState2 = this._edgeBaseState.get(edge.id);
35878
+ if (baseState2 && baseState2.hiddenReason === "visible") {
35879
+ edgeUpdates[String(edge.id)] = {
35880
+ id: edge.id,
35881
+ width: 1,
35882
+ color: {
35883
+ color: dimmedColor,
35884
+ highlight: dimmedColor
35885
+ }
35886
+ };
35887
+ }
35888
+ continue;
35889
+ }
35890
+ const baseState = this._edgeBaseState.get(edge.id);
35891
+ if (!baseState || baseState.hiddenReason !== "visible") {
35892
+ continue;
35893
+ }
35894
+ const remoteId = fromStr === nodeIdStr ? toStr : fromStr;
35895
+ const reportingId = String(edge.reportingNodeId ?? edge.from);
35896
+ connectedNodeIds.add(remoteId);
35897
+ if (reportingId !== nodeIdStr) {
35898
+ const pairEdges = edge.pairKey ? edgesByPair.get(edge.pairKey) : void 0;
35899
+ const swapCandidate = pairEdges === null || pairEdges === void 0 ? void 0 : pairEdges.find(e => {
35900
+ const rid = String(e.reportingNodeId ?? e.from);
35901
+ if (rid !== nodeIdStr) return false;
35902
+ const bs = this._edgeBaseState.get(e.id);
35903
+ return (bs === null || bs === void 0 ? void 0 : bs.hiddenReason) === "dedup";
35904
+ });
35905
+ if (swapCandidate) {
35906
+ const swapBaseState = this._edgeBaseState.get(swapCandidate.id);
35907
+ edgeUpdates[String(edge.id)] = {
35908
+ id: edge.id,
35909
+ hidden: true
35910
+ };
35911
+ edgeUpdates[String(swapCandidate.id)] = {
35912
+ id: swapCandidate.id,
35913
+ hidden: false,
35914
+ width: 3,
35915
+ color: swapBaseState ? {
35916
+ color: swapBaseState.color.color,
35917
+ highlight: swapBaseState.color.highlight
35918
+ } : {
35919
+ color: "#999999",
35920
+ highlight: "#999999"
35921
+ }
35922
+ };
35923
+ } else {
35924
+ edgeUpdates[String(edge.id)] = this._reverseEdgeUpdate(edge);
35925
+ }
35926
+ } else {
35927
+ edgeUpdates[String(edge.id)] = this._asymmetricEdgeUpdate(edge);
35928
+ }
35929
+ }
35930
+ this._edgesDataSet.update(Object.values(edgeUpdates));
35931
+ const allNodes = this._nodesDataSet.get();
35932
+ const nodeUpdates = allNodes.map(node => {
35933
+ const isNeighbor = connectedNodeIds.has(node.id);
35934
+ const isSelected = node.id === nodeId;
35935
+ return {
35936
+ id: node.id,
35937
+ size: isSelected ? 40 : isNeighbor ? 35 : 25,
35938
+ font: {
35939
+ size: isSelected ? 14 : isNeighbor ? 13 : 11,
35940
+ color: this._getFontColor(),
35941
+ bold: isSelected || isNeighbor ? {
35942
+ color: this._getFontColor()
35943
+ } : void 0
35944
+ },
35945
+ opacity: isSelected || isNeighbor ? 1 : 0.5
35946
+ };
35947
+ });
35948
+ this._nodesDataSet.update(nodeUpdates);
35949
+ if (this._highlightedNodeId && this._highlightedNodeId !== nodeIdStr) {
35950
+ this._setNodeIconHighlight(this._highlightedNodeId, false);
35951
+ }
35952
+ this._highlightedNodeId = nodeIdStr;
35953
+ this._setNodeIconHighlight(nodeIdStr, true);
35954
+ this._isHighlighted = true;
35955
+ }
35956
+ /**
35957
+ * Thicken a connected edge and add a directional arrow when the pair is
35958
+ * truly one-way in data (only one of edgeAB/edgeBA exists). Used for the
35959
+ * highlighted-reports-peer branch where filter-hidden peer directions
35960
+ * should not draw an arrow on the user's own perspective.
35961
+ *
35962
+ * Explicit arrow object (vs the shorthand "to") keeps the head visible
35963
+ * on dashed offline edges where some vis.js builds skip the shorthand.
35964
+ */
35965
+ _asymmetricEdgeUpdate(edge) {
35966
+ const pair = edge.pairKey ? this._edgePairs.get(edge.pairKey) : void 0;
35967
+ const isAsymmetric = pair ? !pair.edgeAB || !pair.edgeBA : false;
35968
+ const update = {
35969
+ id: edge.id,
35970
+ width: 3
35971
+ };
35972
+ if (isAsymmetric) {
35973
+ update.arrows = {
35974
+ to: {
35975
+ enabled: true,
35976
+ scaleFactor: 1
35977
+ }
35978
+ };
35979
+ }
35980
+ return update;
35981
+ }
35982
+ /**
35983
+ * Thicken a connected edge and always add a directional arrow. Used for
35984
+ * the remote-reports-highlighted branch where the displayed edge is the
35985
+ * peer's direction (no swap target available); the user sees the same
35986
+ * single line whether the outgoing direction is filter-hidden or absent.
35987
+ */
35988
+ _reverseEdgeUpdate(edge) {
35989
+ return {
35990
+ id: edge.id,
35991
+ width: 3,
35992
+ arrows: {
35993
+ to: {
35994
+ enabled: true,
35995
+ scaleFactor: 1
35996
+ }
35997
+ }
35998
+ };
35999
+ }
36000
+ /**
36001
+ * Swap a node's icon between the default and highlighted variants.
36002
+ * Kept separate so both `_highlightConnections` (switching target) and
36003
+ * `_clearHighlights` (fully unselecting) reach the same end state.
36004
+ */
36005
+ _setNodeIconHighlight(nodeId, isHighlighted) {
36006
+ if (!this._nodesDataSet) return;
36007
+ const nodeData = this.nodes[nodeId];
36008
+ if (nodeData) {
36009
+ const threadRole = getThreadRole(nodeData);
36010
+ const isOffline = nodeData.available === false;
36011
+ this._nodesDataSet.update({
36012
+ id: nodeId,
36013
+ image: createNodeIconDataUrl(nodeData, threadRole, isHighlighted, isOffline)
36014
+ });
36015
+ return;
36016
+ }
36017
+ const external = this._unknownDevicesMapCache.get(nodeId);
36018
+ if ((external === null || external === void 0 ? void 0 : external.kind) === "br") {
36019
+ this._nodesDataSet.update({
36020
+ id: nodeId,
36021
+ image: createBorderRouterIconDataUrl(isHighlighted)
36022
+ });
36023
+ } else if (nodeId.startsWith("unknown_") || nodeId.startsWith("br_")) {
36024
+ this._nodesDataSet.update({
36025
+ id: nodeId,
36026
+ image: createUnknownDeviceIconDataUrl((external === null || external === void 0 ? void 0 : external.isRouter) ?? false, isHighlighted)
36027
+ });
36028
+ }
36029
+ }
36030
+ /**
36031
+ * Clears all highlights and restores the graph to its base state
36032
+ * (after filter+dedup, before highlight modifications).
36033
+ */
36034
+ _clearHighlights() {
36035
+ if (!this._edgesDataSet || !this._nodesDataSet) return;
36036
+ this._restoreEdgeBaseState();
36037
+ if (this._highlightedNodeId) {
36038
+ this._setNodeIconHighlight(this._highlightedNodeId, false);
36039
+ this._highlightedNodeId = null;
36040
+ }
36041
+ const allNodes = this._nodesDataSet.get();
36042
+ const nodeUpdates = allNodes.map(node => ({
36043
+ id: node.id,
36044
+ size: 30,
36045
+ font: {
36046
+ size: 12,
36047
+ color: this._getFontColor(),
36048
+ bold: void 0
36049
+ },
36050
+ opacity: 1
36051
+ }));
36052
+ this._nodesDataSet.update(nodeUpdates);
36053
+ this._isHighlighted = false;
36054
+ }
36055
+ /**
36056
+ * Restores all edges to their base state (undoes highlight modifications).
36057
+ * This resets hidden/visible state, width, color, and dashes.
36058
+ */
36059
+ _restoreEdgeBaseState() {
36060
+ if (!this._edgesDataSet) return;
36061
+ const edgeUpdates = [];
36062
+ for (const [id, baseState] of this._edgeBaseState) {
36063
+ edgeUpdates.push({
36064
+ id,
36065
+ hidden: baseState.hiddenReason !== "visible",
36066
+ width: baseState.width,
36067
+ color: {
36068
+ color: baseState.color.color,
36069
+ highlight: baseState.color.highlight
36070
+ },
36071
+ dashes: baseState.dashes,
36072
+ arrows: ""
36073
+ });
36074
+ }
36075
+ this._edgesDataSet.update(edgeUpdates);
35202
36076
  }
35203
36077
  render() {
35204
36078
  const threadNodes = Object.values(this.nodes).filter(node => getNetworkType(node) === "thread");
35205
- if (threadNodes.length === 0) {
36079
+ const visibleThreadNodes = this.hideOfflineNodes ? threadNodes.filter(node => node.available !== false) : threadNodes;
36080
+ if (visibleThreadNodes.length === 0) {
36081
+ const allOfflineFiltered = threadNodes.length > 0 && this.hideOfflineNodes;
35206
36082
  return b`
35207
36083
  <div class="empty-state">
35208
- <p>No Thread devices found</p>
35209
- <p class="hint">Thread devices will appear here once commissioned</p>
36084
+ <p>${allOfflineFiltered ? "No online Thread devices" : "No Thread devices found"}</p>
36085
+ <p class="hint">
36086
+ ${allOfflineFiltered ? 'Disable the "Offline nodes" filter to show offline devices' : "Thread devices will appear here once commissioned"}
36087
+ </p>
35210
36088
  </div>
35211
36089
  `;
35212
36090
  }
35213
36091
  return b` <div class="graph-container"></div> `;
35214
36092
  }
35215
36093
  };
36094
+ __decorateClass$6([n$2({
36095
+ attribute: false
36096
+ })], ThreadGraph.prototype, "borderRouters", 2);
36097
+ __decorateClass$6([n$2({
36098
+ type: Boolean
36099
+ })], ThreadGraph.prototype, "hideOfflineNodes", 2);
36100
+ __decorateClass$6([n$2({
36101
+ type: Boolean
36102
+ })], ThreadGraph.prototype, "hideWeakSignalEdges", 2);
36103
+ __decorateClass$6([n$2({
36104
+ type: Boolean
36105
+ })], ThreadGraph.prototype, "hideMediumSignalEdges", 2);
36106
+ __decorateClass$6([n$2({
36107
+ type: Boolean
36108
+ })], ThreadGraph.prototype, "hideStrongSignalEdges", 2);
35216
36109
  ThreadGraph = __decorateClass$6([t$1("thread-graph")], ThreadGraph);
35217
36110
  function normalizeExtendedAddressInput(address) {
35218
36111
  const trimmed = address.trim();
@@ -35379,6 +36272,19 @@ var __decorateClass$4 = (decorators, target, key, kind) => {
35379
36272
  if (kind && result) __defProp$3(target, key, result);
35380
36273
  return result;
35381
36274
  };
36275
+ const HIDE_OPTIONS = [{
36276
+ key: "_hideOfflineNodes",
36277
+ label: "Offline nodes"
36278
+ }, {
36279
+ key: "_hideWeakSignalEdges",
36280
+ label: "Weak signal edges"
36281
+ }, {
36282
+ key: "_hideMediumSignalEdges",
36283
+ label: "Medium signal edges"
36284
+ }, {
36285
+ key: "_hideStrongSignalEdges",
36286
+ label: "Strong signal edges"
36287
+ }];
35382
36288
  let MatterNetworkView = class extends i$4 {
35383
36289
  constructor() {
35384
36290
  super(...arguments);
@@ -35389,7 +36295,24 @@ let MatterNetworkView = class extends i$4 {
35389
36295
  this._physicsEnabled = true;
35390
36296
  this._threadAddressSearch = "";
35391
36297
  this._threadAddressSearchStatus = "idle";
36298
+ this._borderRouterStore = new BorderRouterStore();
36299
+ this._showHideMenu = false;
36300
+ this._hideOfflineNodes = false;
36301
+ this._hideWeakSignalEdges = false;
36302
+ this._hideMediumSignalEdges = false;
36303
+ this._hideStrongSignalEdges = false;
35392
36304
  this._initialSelectionApplied = false;
36305
+ this._documentClickHandler = event => {
36306
+ const path = event.composedPath();
36307
+ if (!path.some(el => el instanceof HTMLElement && el.classList.contains("hide-menu-container"))) {
36308
+ this._showHideMenu = false;
36309
+ }
36310
+ };
36311
+ this._documentKeyHandler = event => {
36312
+ if (event.key === "Escape" && this._showHideMenu) {
36313
+ this._showHideMenu = false;
36314
+ }
36315
+ };
35393
36316
  }
35394
36317
  willUpdate(changedProperties) {
35395
36318
  if (changedProperties.has("initialSelectedNodeId") && this.initialSelectedNodeId !== null) {
@@ -35397,15 +36320,42 @@ let MatterNetworkView = class extends i$4 {
35397
36320
  this._initialSelectionApplied = false;
35398
36321
  }
35399
36322
  }
36323
+ firstUpdated() {
36324
+ if (this.networkType === "thread") {
36325
+ void this._refreshBorderRouters();
36326
+ }
36327
+ }
36328
+ async _refreshBorderRouters() {
36329
+ try {
36330
+ await this._borderRouterStore.refresh(this.client);
36331
+ this.requestUpdate();
36332
+ } catch (err) {
36333
+ console.warn("Failed to refresh border router store:", err);
36334
+ }
36335
+ }
36336
+ _handleConnectionsUpdated() {
36337
+ if (this.networkType !== "thread") return;
36338
+ void this._refreshBorderRouters();
36339
+ }
35400
36340
  updated(changedProperties) {
35401
36341
  super.updated(changedProperties);
36342
+ if (changedProperties.has("networkType") && this.networkType === "thread") {
36343
+ void this._refreshBorderRouters();
36344
+ }
35402
36345
  if (!this._initialSelectionApplied && this.initialSelectedNodeId !== null) {
35403
36346
  this._initialSelectionApplied = true;
35404
36347
  this._selectNodeWhenReady(this.initialSelectedNodeId);
35405
36348
  }
35406
36349
  }
36350
+ connectedCallback() {
36351
+ super.connectedCallback();
36352
+ document.addEventListener("click", this._documentClickHandler);
36353
+ document.addEventListener("keydown", this._documentKeyHandler);
36354
+ }
35407
36355
  disconnectedCallback() {
35408
36356
  super.disconnectedCallback();
36357
+ document.removeEventListener("click", this._documentClickHandler);
36358
+ document.removeEventListener("keydown", this._documentKeyHandler);
35409
36359
  if (this._selectRetryTimer) {
35410
36360
  clearTimeout(this._selectRetryTimer);
35411
36361
  }
@@ -35426,57 +36376,73 @@ let MatterNetworkView = class extends i$4 {
35426
36376
  }
35427
36377
  _handleDetailsClose() {
35428
36378
  this._selectedNodeId = null;
35429
- }
35430
- _handleSelectNode(event) {
35431
- const nodeId = event.detail.nodeId;
35432
- this._selectedNodeId = nodeId;
35433
36379
  if (this.networkType === "thread") {
35434
36380
  var _this$_threadGraph;
35435
- (_this$_threadGraph = this._threadGraph) === null || _this$_threadGraph === void 0 || _this$_threadGraph.selectNode(nodeId);
36381
+ (_this$_threadGraph = this._threadGraph) === null || _this$_threadGraph === void 0 || _this$_threadGraph.deselectAll();
35436
36382
  } else {
35437
36383
  var _this$_wifiGraph;
35438
- (_this$_wifiGraph = this._wifiGraph) === null || _this$_wifiGraph === void 0 || _this$_wifiGraph.selectNode(nodeId);
36384
+ (_this$_wifiGraph = this._wifiGraph) === null || _this$_wifiGraph === void 0 || _this$_wifiGraph.deselectAll();
35439
36385
  }
35440
36386
  }
35441
- _handleFitToScreen() {
36387
+ _handleSelectNode(event) {
36388
+ const nodeId = event.detail.nodeId;
36389
+ this._selectedNodeId = nodeId;
35442
36390
  if (this.networkType === "thread") {
35443
36391
  var _this$_threadGraph2;
35444
- (_this$_threadGraph2 = this._threadGraph) === null || _this$_threadGraph2 === void 0 || _this$_threadGraph2.fit();
36392
+ (_this$_threadGraph2 = this._threadGraph) === null || _this$_threadGraph2 === void 0 || _this$_threadGraph2.selectNode(nodeId);
35445
36393
  } else {
35446
36394
  var _this$_wifiGraph2;
35447
- (_this$_wifiGraph2 = this._wifiGraph) === null || _this$_wifiGraph2 === void 0 || _this$_wifiGraph2.fit();
36395
+ (_this$_wifiGraph2 = this._wifiGraph) === null || _this$_wifiGraph2 === void 0 || _this$_wifiGraph2.selectNode(nodeId);
35448
36396
  }
35449
36397
  }
35450
- _handleZoomIn() {
36398
+ _handleFitToScreen() {
35451
36399
  if (this.networkType === "thread") {
35452
36400
  var _this$_threadGraph3;
35453
- (_this$_threadGraph3 = this._threadGraph) === null || _this$_threadGraph3 === void 0 || _this$_threadGraph3.zoomIn();
36401
+ (_this$_threadGraph3 = this._threadGraph) === null || _this$_threadGraph3 === void 0 || _this$_threadGraph3.fit();
35454
36402
  } else {
35455
36403
  var _this$_wifiGraph3;
35456
- (_this$_wifiGraph3 = this._wifiGraph) === null || _this$_wifiGraph3 === void 0 || _this$_wifiGraph3.zoomIn();
36404
+ (_this$_wifiGraph3 = this._wifiGraph) === null || _this$_wifiGraph3 === void 0 || _this$_wifiGraph3.fit();
35457
36405
  }
35458
36406
  }
35459
- _handleZoomOut() {
36407
+ _handleZoomIn() {
35460
36408
  if (this.networkType === "thread") {
35461
36409
  var _this$_threadGraph4;
35462
- (_this$_threadGraph4 = this._threadGraph) === null || _this$_threadGraph4 === void 0 || _this$_threadGraph4.zoomOut();
36410
+ (_this$_threadGraph4 = this._threadGraph) === null || _this$_threadGraph4 === void 0 || _this$_threadGraph4.zoomIn();
35463
36411
  } else {
35464
36412
  var _this$_wifiGraph4;
35465
- (_this$_wifiGraph4 = this._wifiGraph) === null || _this$_wifiGraph4 === void 0 || _this$_wifiGraph4.zoomOut();
36413
+ (_this$_wifiGraph4 = this._wifiGraph) === null || _this$_wifiGraph4 === void 0 || _this$_wifiGraph4.zoomIn();
36414
+ }
36415
+ }
36416
+ _handleZoomOut() {
36417
+ if (this.networkType === "thread") {
36418
+ var _this$_threadGraph5;
36419
+ (_this$_threadGraph5 = this._threadGraph) === null || _this$_threadGraph5 === void 0 || _this$_threadGraph5.zoomOut();
36420
+ } else {
36421
+ var _this$_wifiGraph5;
36422
+ (_this$_wifiGraph5 = this._wifiGraph) === null || _this$_wifiGraph5 === void 0 || _this$_wifiGraph5.zoomOut();
35466
36423
  }
35467
36424
  }
36425
+ _handleToggleHideMenu() {
36426
+ this._showHideMenu = !this._showHideMenu;
36427
+ }
36428
+ _handleToggleHideOption(option) {
36429
+ this[option] = !this[option];
36430
+ }
36431
+ _isAnyHideOptionActive() {
36432
+ return HIDE_OPTIONS.some(option => this[option.key]);
36433
+ }
35468
36434
  _handleTogglePhysics() {
35469
- var _this$_threadGraph5, _this$_wifiGraph5;
36435
+ var _this$_threadGraph6, _this$_wifiGraph6;
35470
36436
  const newState = !this._physicsEnabled;
35471
36437
  this._physicsEnabled = newState;
35472
- (_this$_threadGraph5 = this._threadGraph) === null || _this$_threadGraph5 === void 0 || _this$_threadGraph5.setPhysicsEnabled(newState);
35473
- (_this$_wifiGraph5 = this._wifiGraph) === null || _this$_wifiGraph5 === void 0 || _this$_wifiGraph5.setPhysicsEnabled(newState);
36438
+ (_this$_threadGraph6 = this._threadGraph) === null || _this$_threadGraph6 === void 0 || _this$_threadGraph6.setPhysicsEnabled(newState);
36439
+ (_this$_wifiGraph6 = this._wifiGraph) === null || _this$_wifiGraph6 === void 0 || _this$_wifiGraph6.setPhysicsEnabled(newState);
35474
36440
  }
35475
36441
  _handlePhysicsChanged(event) {
35476
- var _this$_threadGraph6, _this$_wifiGraph6;
36442
+ var _this$_threadGraph7, _this$_wifiGraph7;
35477
36443
  this._physicsEnabled = event.detail.enabled;
35478
- (_this$_threadGraph6 = this._threadGraph) === null || _this$_threadGraph6 === void 0 || _this$_threadGraph6.setPhysicsEnabled(event.detail.enabled);
35479
- (_this$_wifiGraph6 = this._wifiGraph) === null || _this$_wifiGraph6 === void 0 || _this$_wifiGraph6.setPhysicsEnabled(event.detail.enabled);
36444
+ (_this$_threadGraph7 = this._threadGraph) === null || _this$_threadGraph7 === void 0 || _this$_threadGraph7.setPhysicsEnabled(event.detail.enabled);
36445
+ (_this$_wifiGraph7 = this._wifiGraph) === null || _this$_wifiGraph7 === void 0 || _this$_wifiGraph7.setPhysicsEnabled(event.detail.enabled);
35480
36446
  }
35481
36447
  _handleThreadAddressSearchInput(event) {
35482
36448
  this._threadAddressSearch = event.target.value;
@@ -35530,6 +36496,37 @@ let MatterNetworkView = class extends i$4 {
35530
36496
  <button class="control-button" @click=${this._handleFitToScreen} title="Fit to screen">
35531
36497
  <ha-svg-icon .path=${mdiFitToScreen}></ha-svg-icon>
35532
36498
  </button>
36499
+ <div class="hide-menu-container">
36500
+ <button
36501
+ class="control-button ${this._isAnyHideOptionActive() ? "active" : ""}"
36502
+ @click=${this._handleToggleHideMenu}
36503
+ title="Hide options"
36504
+ aria-haspopup="true"
36505
+ aria-expanded=${this._showHideMenu}
36506
+ aria-controls="hide-options-menu"
36507
+ >
36508
+ <ha-svg-icon .path=${mdiEyeOff}></ha-svg-icon>
36509
+ </button>
36510
+ ${this._showHideMenu ? b`
36511
+ <div
36512
+ id="hide-options-menu"
36513
+ class="hide-dropdown"
36514
+ role="group"
36515
+ aria-label="Hide options"
36516
+ >
36517
+ ${HIDE_OPTIONS.map(option => b`
36518
+ <label class="hide-option">
36519
+ <input
36520
+ type="checkbox"
36521
+ .checked=${this[option.key]}
36522
+ @change=${() => this._handleToggleHideOption(option.key)}
36523
+ />
36524
+ <span>${option.label}</span>
36525
+ </label>
36526
+ `)}
36527
+ </div>
36528
+ ` : ""}
36529
+ </div>
35533
36530
  <button
35534
36531
  class="control-button ${this._physicsEnabled ? "" : "active"}"
35535
36532
  @click=${this._handleTogglePhysics}
@@ -35545,6 +36542,11 @@ let MatterNetworkView = class extends i$4 {
35545
36542
  </div>`}
35546
36543
  <thread-graph
35547
36544
  .nodes=${this.nodes}
36545
+ .borderRouters=${this._borderRouterStore.entries}
36546
+ .hideOfflineNodes=${this._hideOfflineNodes}
36547
+ .hideWeakSignalEdges=${this._hideWeakSignalEdges}
36548
+ .hideMediumSignalEdges=${this._hideMediumSignalEdges}
36549
+ .hideStrongSignalEdges=${this._hideStrongSignalEdges}
35548
36550
  @node-selected=${this._handleNodeSelected}
35549
36551
  @physics-changed=${this._handlePhysicsChanged}
35550
36552
  ></thread-graph>
@@ -35584,10 +36586,11 @@ let MatterNetworkView = class extends i$4 {
35584
36586
  `;
35585
36587
  }
35586
36588
  render() {
35587
- var _this$_threadGraph7, _this$_wifiGraph7;
36589
+ var _this$_threadGraph8, _this$_wifiGraph8, _this$_threadGraph9;
35588
36590
  const showSidebar = this._selectedNodeId !== null;
35589
- const unknownDevices = ((_this$_threadGraph7 = this._threadGraph) === null || _this$_threadGraph7 === void 0 ? void 0 : _this$_threadGraph7.unknownDevicesMap) ?? /* @__PURE__ */new Map();
35590
- const wifiAccessPoints = ((_this$_wifiGraph7 = this._wifiGraph) === null || _this$_wifiGraph7 === void 0 ? void 0 : _this$_wifiGraph7.wifiAccessPointsMap) ?? /* @__PURE__ */new Map();
36591
+ const unknownDevices = ((_this$_threadGraph8 = this._threadGraph) === null || _this$_threadGraph8 === void 0 ? void 0 : _this$_threadGraph8.unknownDevicesMap) ?? /* @__PURE__ */new Map();
36592
+ const wifiAccessPoints = ((_this$_wifiGraph8 = this._wifiGraph) === null || _this$_wifiGraph8 === void 0 ? void 0 : _this$_wifiGraph8.wifiAccessPointsMap) ?? /* @__PURE__ */new Map();
36593
+ const threadEdgePairs = ((_this$_threadGraph9 = this._threadGraph) === null || _this$_threadGraph9 === void 0 ? void 0 : _this$_threadGraph9.edgePairs) ?? /* @__PURE__ */new Map();
35591
36594
  return b`
35592
36595
  <dashboard-header
35593
36596
  title="Open Home Foundation Matter Server"
@@ -35607,9 +36610,16 @@ let MatterNetworkView = class extends i$4 {
35607
36610
  .selectedNodeId=${this._selectedNodeId}
35608
36611
  .nodes=${this.nodes}
35609
36612
  .unknownDevices=${unknownDevices}
36613
+ .borderRouters=${this._borderRouterStore.entries}
35610
36614
  .wifiAccessPoints=${wifiAccessPoints}
36615
+ .threadEdgePairs=${threadEdgePairs}
36616
+ .hideOfflineNodes=${this._hideOfflineNodes}
36617
+ .hideWeakSignalEdges=${this._hideWeakSignalEdges}
36618
+ .hideMediumSignalEdges=${this._hideMediumSignalEdges}
36619
+ .hideStrongSignalEdges=${this._hideStrongSignalEdges}
35611
36620
  @close=${this._handleDetailsClose}
35612
36621
  @select-node=${this._handleSelectNode}
36622
+ @connections-updated=${this._handleConnectionsUpdated}
35613
36623
  ></network-details>
35614
36624
  </aside>
35615
36625
  </div>
@@ -35771,6 +36781,47 @@ MatterNetworkView.styles = [reducedMotionStyles, i$7`
35771
36781
  --icon-primary-color: var(--md-sys-color-on-primary-container, #21005d);
35772
36782
  }
35773
36783
 
36784
+ .hide-menu-container {
36785
+ position: relative;
36786
+ }
36787
+
36788
+ .hide-dropdown {
36789
+ position: absolute;
36790
+ top: calc(100% + 4px);
36791
+ right: 0;
36792
+ background: var(--md-sys-color-surface-container, #fff);
36793
+ border: 1px solid var(--md-sys-color-outline-variant, #ccc);
36794
+ border-radius: 4px;
36795
+ box-shadow: var(--md-sys-elevation-level2, 0 2px 6px var(--md-sys-color-shadow, rgba(0, 0, 0, 0.15)));
36796
+ min-width: 150px;
36797
+ z-index: 100;
36798
+ padding: 4px 0;
36799
+ }
36800
+
36801
+ .hide-option {
36802
+ display: flex;
36803
+ align-items: center;
36804
+ gap: 8px;
36805
+ padding: 8px 12px;
36806
+ cursor: pointer;
36807
+ color: var(--md-sys-color-on-surface, #1c1b1f);
36808
+ font-size: 0.9rem;
36809
+ user-select: none;
36810
+ }
36811
+
36812
+ .hide-option:hover {
36813
+ background-color: var(--md-sys-color-surface-container-high, #e8e8e8);
36814
+ }
36815
+
36816
+ .hide-option input[type="checkbox"] {
36817
+ cursor: pointer;
36818
+ margin: 0;
36819
+ }
36820
+
36821
+ .hide-option span {
36822
+ flex: 1;
36823
+ }
36824
+
35774
36825
  .graph-section thread-graph,
35775
36826
  .graph-section wifi-graph {
35776
36827
  flex: 1 1 0;
@@ -35869,6 +36920,12 @@ __decorateClass$4([r$2()], MatterNetworkView.prototype, "_selectedNodeId", 2);
35869
36920
  __decorateClass$4([r$2()], MatterNetworkView.prototype, "_physicsEnabled", 2);
35870
36921
  __decorateClass$4([r$2()], MatterNetworkView.prototype, "_threadAddressSearch", 2);
35871
36922
  __decorateClass$4([r$2()], MatterNetworkView.prototype, "_threadAddressSearchStatus", 2);
36923
+ __decorateClass$4([r$2()], MatterNetworkView.prototype, "_borderRouterStore", 2);
36924
+ __decorateClass$4([r$2()], MatterNetworkView.prototype, "_showHideMenu", 2);
36925
+ __decorateClass$4([r$2()], MatterNetworkView.prototype, "_hideOfflineNodes", 2);
36926
+ __decorateClass$4([r$2()], MatterNetworkView.prototype, "_hideWeakSignalEdges", 2);
36927
+ __decorateClass$4([r$2()], MatterNetworkView.prototype, "_hideMediumSignalEdges", 2);
36928
+ __decorateClass$4([r$2()], MatterNetworkView.prototype, "_hideStrongSignalEdges", 2);
35872
36929
  __decorateClass$4([e$5("thread-graph")], MatterNetworkView.prototype, "_threadGraph", 2);
35873
36930
  __decorateClass$4([e$5("wifi-graph")], MatterNetworkView.prototype, "_wifiGraph", 2);
35874
36931
  MatterNetworkView = __decorateClass$4([t$1("matter-network-view")], MatterNetworkView);
@@ -36073,7 +37130,7 @@ MatterNodeView = __decorateClass$3([t$1("matter-node-view")], MatterNodeView);
36073
37130
  */
36074
37131
  const showCommissionNodeDialog = async client => {
36075
37132
  var _document$querySelect;
36076
- await import('./commission-node-dialog-Bg3oo5ub.js');
37133
+ await import('./commission-node-dialog-CMSvCm0i.js');
36077
37134
  const dialog = document.createElement("commission-node-dialog");
36078
37135
  dialog.client = client;
36079
37136
  (_document$querySelect = document.querySelector("matter-dashboard-app")) === null || _document$querySelect === void 0 || _document$querySelect.renderRoot.appendChild(dialog);