unifi-network-maps 1.4.14__py3-none-any.whl → 1.5.0__py3-none-any.whl
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.
- unifi_network_maps/__init__.py +1 -1
- unifi_network_maps/adapters/unifi.py +83 -101
- unifi_network_maps/assets/icons/modern/ap.svg +9 -0
- unifi_network_maps/assets/icons/modern/camera.svg +9 -0
- unifi_network_maps/assets/icons/modern/client.svg +9 -0
- unifi_network_maps/assets/icons/modern/game_console.svg +10 -0
- unifi_network_maps/assets/icons/modern/gateway.svg +17 -0
- unifi_network_maps/assets/icons/modern/iot.svg +9 -0
- unifi_network_maps/assets/icons/modern/nas.svg +9 -0
- unifi_network_maps/assets/icons/modern/other.svg +10 -0
- unifi_network_maps/assets/icons/modern/phone.svg +10 -0
- unifi_network_maps/assets/icons/modern/printer.svg +9 -0
- unifi_network_maps/assets/icons/modern/speaker.svg +10 -0
- unifi_network_maps/assets/icons/modern/switch.svg +10 -0
- unifi_network_maps/assets/icons/modern/tv.svg +10 -0
- unifi_network_maps/assets/icons/modern-flat/ap.svg +5 -0
- unifi_network_maps/assets/icons/modern-flat/camera.svg +5 -0
- unifi_network_maps/assets/icons/modern-flat/client.svg +5 -0
- unifi_network_maps/assets/icons/modern-flat/game_console.svg +6 -0
- unifi_network_maps/assets/icons/modern-flat/gateway.svg +13 -0
- unifi_network_maps/assets/icons/modern-flat/iot.svg +5 -0
- unifi_network_maps/assets/icons/modern-flat/nas.svg +5 -0
- unifi_network_maps/assets/icons/modern-flat/other.svg +6 -0
- unifi_network_maps/assets/icons/modern-flat/phone.svg +6 -0
- unifi_network_maps/assets/icons/modern-flat/printer.svg +5 -0
- unifi_network_maps/assets/icons/modern-flat/speaker.svg +6 -0
- unifi_network_maps/assets/icons/modern-flat/switch.svg +6 -0
- unifi_network_maps/assets/icons/modern-flat/tv.svg +6 -0
- unifi_network_maps/assets/themes/dark.yaml +53 -10
- unifi_network_maps/assets/themes/default.yaml +34 -0
- unifi_network_maps/assets/themes/minimal-dark.yaml +98 -0
- unifi_network_maps/assets/themes/minimal.yaml +92 -0
- unifi_network_maps/assets/themes/unifi-dark.yaml +97 -0
- unifi_network_maps/assets/themes/unifi.yaml +92 -0
- unifi_network_maps/cli/args.py +54 -0
- unifi_network_maps/cli/main.py +18 -7
- unifi_network_maps/cli/render.py +79 -27
- unifi_network_maps/cli/runtime.py +29 -15
- unifi_network_maps/io/debug.py +2 -1
- unifi_network_maps/io/export.py +19 -13
- unifi_network_maps/io/mock_data.py +5 -3
- unifi_network_maps/io/paths.py +5 -3
- unifi_network_maps/model/classify.py +199 -0
- unifi_network_maps/model/clients.py +271 -0
- unifi_network_maps/model/connection.py +37 -0
- unifi_network_maps/model/diff.py +544 -0
- unifi_network_maps/model/edges.py +558 -0
- unifi_network_maps/model/helpers.py +64 -0
- unifi_network_maps/model/lldp.py +20 -25
- unifi_network_maps/model/mock.py +110 -23
- unifi_network_maps/model/snapshot.py +294 -0
- unifi_network_maps/model/topology.py +143 -931
- unifi_network_maps/model/topology_coerce.py +339 -0
- unifi_network_maps/model/vlans.py +32 -46
- unifi_network_maps/model/wan.py +132 -0
- unifi_network_maps/render/device_ports_md.py +39 -97
- unifi_network_maps/render/device_summary.py +53 -0
- unifi_network_maps/render/lldp_md.py +29 -219
- unifi_network_maps/render/markdown_tables.py +8 -0
- unifi_network_maps/render/mermaid.py +11 -2
- unifi_network_maps/render/mkdocs.py +2 -1
- unifi_network_maps/render/svg.py +566 -908
- unifi_network_maps/render/svg_icons.py +231 -0
- unifi_network_maps/render/svg_isometric.py +1196 -0
- unifi_network_maps/render/svg_labels.py +184 -0
- unifi_network_maps/render/svg_theme.py +166 -32
- unifi_network_maps/render/theme.py +86 -1
- {unifi_network_maps-1.4.14.dist-info → unifi_network_maps-1.5.0.dist-info}/METADATA +107 -31
- {unifi_network_maps-1.4.14.dist-info → unifi_network_maps-1.5.0.dist-info}/RECORD +73 -31
- unifi_network_maps/assets/icons/isometric/printer.svg +0 -122
- {unifi_network_maps-1.4.14.dist-info → unifi_network_maps-1.5.0.dist-info}/WHEEL +0 -0
- {unifi_network_maps-1.4.14.dist-info → unifi_network_maps-1.5.0.dist-info}/entry_points.txt +0 -0
- {unifi_network_maps-1.4.14.dist-info → unifi_network_maps-1.5.0.dist-info}/licenses/LICENSE +0 -0
- {unifi_network_maps-1.4.14.dist-info → unifi_network_maps-1.5.0.dist-info}/top_level.txt +0 -0
unifi_network_maps/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "1.
|
|
1
|
+
__version__ = "1.5.0"
|
|
@@ -17,6 +17,7 @@ from pathlib import Path
|
|
|
17
17
|
from typing import IO, TYPE_CHECKING
|
|
18
18
|
|
|
19
19
|
from ..io.paths import resolve_cache_dir
|
|
20
|
+
from ..model.helpers import as_list, first_attr, get_field
|
|
20
21
|
from ..model.vlans import build_vlan_info, normalize_networks
|
|
21
22
|
from .config import Config
|
|
22
23
|
|
|
@@ -38,47 +39,18 @@ def _cache_dir() -> Path:
|
|
|
38
39
|
return resolve_cache_dir(".cache/unifi_network_maps")
|
|
39
40
|
|
|
40
41
|
|
|
41
|
-
def _device_attr(device: object, name: str) -> object | None:
|
|
42
|
-
if isinstance(device, dict):
|
|
43
|
-
return device.get(name)
|
|
44
|
-
return getattr(device, name, None)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def _first_attr(device: object, *names: str) -> object | None:
|
|
48
|
-
for name in names:
|
|
49
|
-
value = _device_attr(device, name)
|
|
50
|
-
if value is not None:
|
|
51
|
-
return value
|
|
52
|
-
return None
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
def _as_list(value: object | None) -> list[object]:
|
|
56
|
-
if value is None:
|
|
57
|
-
return []
|
|
58
|
-
if isinstance(value, list):
|
|
59
|
-
return value
|
|
60
|
-
if isinstance(value, dict):
|
|
61
|
-
return [value]
|
|
62
|
-
if isinstance(value, str | bytes):
|
|
63
|
-
return []
|
|
64
|
-
try:
|
|
65
|
-
return list(value) # type: ignore[arg-type]
|
|
66
|
-
except TypeError:
|
|
67
|
-
return []
|
|
68
|
-
|
|
69
|
-
|
|
70
42
|
def _serialize_lldp_entry(entry: object) -> dict[str, object]:
|
|
71
43
|
return {
|
|
72
|
-
"chassis_id":
|
|
73
|
-
"port_id":
|
|
74
|
-
"port_desc":
|
|
75
|
-
"local_port_name":
|
|
76
|
-
"local_port_idx":
|
|
44
|
+
"chassis_id": first_attr(entry, "chassis_id", "chassisId"),
|
|
45
|
+
"port_id": first_attr(entry, "port_id", "portId"),
|
|
46
|
+
"port_desc": first_attr(entry, "port_desc", "portDesc", "port_descr", "portDescr"),
|
|
47
|
+
"local_port_name": first_attr(entry, "local_port_name", "localPortName"),
|
|
48
|
+
"local_port_idx": first_attr(entry, "local_port_idx", "localPortIdx"),
|
|
77
49
|
}
|
|
78
50
|
|
|
79
51
|
|
|
80
52
|
def _serialize_lldp_entries(value: object | None) -> list[dict[str, object]]:
|
|
81
|
-
entries =
|
|
53
|
+
entries = as_list(value)
|
|
82
54
|
serialized: list[dict[str, object]] = []
|
|
83
55
|
for entry in entries:
|
|
84
56
|
data = _serialize_lldp_entry(entry)
|
|
@@ -88,7 +60,7 @@ def _serialize_lldp_entries(value: object | None) -> list[dict[str, object]]:
|
|
|
88
60
|
|
|
89
61
|
|
|
90
62
|
def _serialize_port_entry(entry: object) -> dict[str, object]:
|
|
91
|
-
aggregation_group =
|
|
63
|
+
aggregation_group = first_attr(
|
|
92
64
|
entry,
|
|
93
65
|
"aggregation_group",
|
|
94
66
|
"aggregation_id",
|
|
@@ -101,30 +73,47 @@ def _serialize_port_entry(entry: object) -> dict[str, object]:
|
|
|
101
73
|
"aggregate",
|
|
102
74
|
"aggregated_by",
|
|
103
75
|
)
|
|
76
|
+
native_vlan = first_attr(
|
|
77
|
+
entry,
|
|
78
|
+
"native_networkconf_id",
|
|
79
|
+
"port_vlan",
|
|
80
|
+
"vlan",
|
|
81
|
+
"native_vlan",
|
|
82
|
+
"pvid",
|
|
83
|
+
)
|
|
84
|
+
tagged_vlans = first_attr(
|
|
85
|
+
entry,
|
|
86
|
+
"tagged_vlan_mgmt",
|
|
87
|
+
"tagged_vlans",
|
|
88
|
+
"vlan_trunk_mgmt",
|
|
89
|
+
"allowed_vlans",
|
|
90
|
+
)
|
|
104
91
|
return {
|
|
105
|
-
"port_idx":
|
|
106
|
-
"name":
|
|
107
|
-
"ifname":
|
|
108
|
-
"speed":
|
|
92
|
+
"port_idx": first_attr(entry, "port_idx", "portIdx"),
|
|
93
|
+
"name": first_attr(entry, "name"),
|
|
94
|
+
"ifname": first_attr(entry, "ifname"),
|
|
95
|
+
"speed": first_attr(entry, "speed"),
|
|
109
96
|
"aggregation_group": aggregation_group,
|
|
110
|
-
"port_poe":
|
|
111
|
-
"poe_enable":
|
|
112
|
-
"poe_good":
|
|
113
|
-
"poe_power":
|
|
97
|
+
"port_poe": first_attr(entry, "port_poe"),
|
|
98
|
+
"poe_enable": first_attr(entry, "poe_enable"),
|
|
99
|
+
"poe_good": first_attr(entry, "poe_good"),
|
|
100
|
+
"poe_power": first_attr(entry, "poe_power"),
|
|
101
|
+
"native_vlan": native_vlan,
|
|
102
|
+
"tagged_vlans": tagged_vlans,
|
|
114
103
|
}
|
|
115
104
|
|
|
116
105
|
|
|
117
106
|
def _serialize_port_table(value: object | None) -> list[dict[str, object]]:
|
|
118
|
-
return [_serialize_port_entry(entry) for entry in
|
|
107
|
+
return [_serialize_port_entry(entry) for entry in as_list(value)]
|
|
119
108
|
|
|
120
109
|
|
|
121
110
|
def _serialize_uplink(value: object | None) -> dict[str, object] | None:
|
|
122
111
|
if value is None:
|
|
123
112
|
return None
|
|
124
113
|
data = {
|
|
125
|
-
"uplink_mac":
|
|
126
|
-
"uplink_device_name":
|
|
127
|
-
"uplink_remote_port":
|
|
114
|
+
"uplink_mac": first_attr(value, "uplink_mac", "uplink_device_mac"),
|
|
115
|
+
"uplink_device_name": first_attr(value, "uplink_device_name", "uplink_name"),
|
|
116
|
+
"uplink_remote_port": first_attr(value, "uplink_remote_port", "port_idx"),
|
|
128
117
|
}
|
|
129
118
|
if any(item is not None for item in data.values()):
|
|
130
119
|
return data
|
|
@@ -132,36 +121,36 @@ def _serialize_uplink(value: object | None) -> dict[str, object] | None:
|
|
|
132
121
|
|
|
133
122
|
|
|
134
123
|
def _device_lldp_value(device: object) -> object | None:
|
|
135
|
-
lldp_info =
|
|
124
|
+
lldp_info = get_field(device, "lldp_info")
|
|
136
125
|
if lldp_info is None:
|
|
137
|
-
lldp_info =
|
|
126
|
+
lldp_info = get_field(device, "lldp")
|
|
138
127
|
if lldp_info is None:
|
|
139
|
-
lldp_info =
|
|
128
|
+
lldp_info = get_field(device, "lldp_table")
|
|
140
129
|
return lldp_info
|
|
141
130
|
|
|
142
131
|
|
|
143
132
|
def _device_uplink_fields(device: object) -> dict[str, object | None]:
|
|
144
133
|
return {
|
|
145
|
-
"uplink": _serialize_uplink(
|
|
146
|
-
"last_uplink": _serialize_uplink(
|
|
147
|
-
"uplink_mac":
|
|
148
|
-
"uplink_device_name":
|
|
149
|
-
"uplink_remote_port":
|
|
150
|
-
"last_uplink_mac":
|
|
134
|
+
"uplink": _serialize_uplink(get_field(device, "uplink")),
|
|
135
|
+
"last_uplink": _serialize_uplink(get_field(device, "last_uplink")),
|
|
136
|
+
"uplink_mac": first_attr(device, "uplink_mac", "uplink_device_mac"),
|
|
137
|
+
"uplink_device_name": get_field(device, "uplink_device_name"),
|
|
138
|
+
"uplink_remote_port": get_field(device, "uplink_remote_port"),
|
|
139
|
+
"last_uplink_mac": get_field(device, "last_uplink_mac"),
|
|
151
140
|
}
|
|
152
141
|
|
|
153
142
|
|
|
154
143
|
def _serialize_device_for_cache(device: object) -> dict[str, object]:
|
|
155
144
|
payload = {
|
|
156
|
-
"name":
|
|
157
|
-
"model_name":
|
|
158
|
-
"model":
|
|
159
|
-
"mac":
|
|
160
|
-
"ip":
|
|
161
|
-
"type":
|
|
162
|
-
"displayable_version":
|
|
145
|
+
"name": get_field(device, "name"),
|
|
146
|
+
"model_name": get_field(device, "model_name"),
|
|
147
|
+
"model": get_field(device, "model"),
|
|
148
|
+
"mac": get_field(device, "mac"),
|
|
149
|
+
"ip": first_attr(device, "ip", "ip_address"),
|
|
150
|
+
"type": first_attr(device, "type", "device_type"),
|
|
151
|
+
"displayable_version": first_attr(device, "displayable_version", "version"),
|
|
163
152
|
"lldp_info": _serialize_lldp_entries(_device_lldp_value(device)),
|
|
164
|
-
"port_table": _serialize_port_table(
|
|
153
|
+
"port_table": _serialize_port_table(get_field(device, "port_table")),
|
|
165
154
|
}
|
|
166
155
|
payload.update(_device_uplink_fields(device))
|
|
167
156
|
return payload
|
|
@@ -173,10 +162,11 @@ def _serialize_devices_for_cache(devices: Sequence[object]) -> list[dict[str, ob
|
|
|
173
162
|
|
|
174
163
|
def _serialize_network_for_cache(network: object) -> dict[str, object]:
|
|
175
164
|
return {
|
|
176
|
-
"
|
|
177
|
-
"
|
|
178
|
-
"
|
|
179
|
-
"
|
|
165
|
+
"_id": first_attr(network, "_id", "id", "network_id", "networkId"),
|
|
166
|
+
"name": first_attr(network, "name", "network_name", "networkName"),
|
|
167
|
+
"vlan": first_attr(network, "vlan", "vlan_id", "vlanId", "vlanid"),
|
|
168
|
+
"vlan_enabled": first_attr(network, "vlan_enabled", "vlanEnabled"),
|
|
169
|
+
"purpose": first_attr(network, "purpose"),
|
|
180
170
|
}
|
|
181
171
|
|
|
182
172
|
|
|
@@ -306,7 +296,7 @@ def _retry_attempts() -> int:
|
|
|
306
296
|
if not value:
|
|
307
297
|
return 2
|
|
308
298
|
if value.isdigit():
|
|
309
|
-
return max(1, int(value))
|
|
299
|
+
return min(max(1, int(value)), 20)
|
|
310
300
|
logger.warning("Invalid UNIFI_RETRY_ATTEMPTS value: %s", value)
|
|
311
301
|
return 2
|
|
312
302
|
|
|
@@ -316,7 +306,7 @@ def _retry_backoff_seconds() -> float:
|
|
|
316
306
|
if not value:
|
|
317
307
|
return 0.5
|
|
318
308
|
try:
|
|
319
|
-
return max(0.0, float(value))
|
|
309
|
+
return min(max(0.0, float(value)), 60.0)
|
|
320
310
|
except ValueError:
|
|
321
311
|
logger.warning("Invalid UNIFI_RETRY_BACKOFF_SECONDS value: %s", value)
|
|
322
312
|
return 0.5
|
|
@@ -327,7 +317,7 @@ def _request_timeout_seconds() -> float | None:
|
|
|
327
317
|
if not value:
|
|
328
318
|
return None
|
|
329
319
|
try:
|
|
330
|
-
return max(0.0, float(value))
|
|
320
|
+
return min(max(0.0, float(value)), 300.0)
|
|
331
321
|
except ValueError:
|
|
332
322
|
logger.warning("Invalid UNIFI_REQUEST_TIMEOUT_SECONDS value: %s", value)
|
|
333
323
|
return None
|
|
@@ -394,15 +384,12 @@ def fetch_devices(
|
|
|
394
384
|
site_name = site or config.site
|
|
395
385
|
ttl_seconds = _cache_ttl_seconds()
|
|
396
386
|
cache_path = _cache_dir() / f"devices_{_cache_key(config.url, site_name, str(detailed))}.json"
|
|
397
|
-
|
|
387
|
+
cache_safe = use_cache and _is_cache_dir_safe(cache_path.parent)
|
|
388
|
+
if cache_safe:
|
|
398
389
|
cached = _load_cache(cache_path, ttl_seconds)
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
stale_cached, cache_age = None, None
|
|
403
|
-
if cached is not None:
|
|
404
|
-
logger.debug("Using cached devices (%d)", len(cached))
|
|
405
|
-
return cached
|
|
390
|
+
if cached is not None:
|
|
391
|
+
logger.debug("Using cached devices (%d)", len(cached))
|
|
392
|
+
return cached
|
|
406
393
|
|
|
407
394
|
try:
|
|
408
395
|
controller = _init_controller(config, is_udm_pro=True)
|
|
@@ -416,6 +403,7 @@ def fetch_devices(
|
|
|
416
403
|
try:
|
|
417
404
|
devices = _call_with_retries("device fetch", _fetch)
|
|
418
405
|
except Exception as exc: # noqa: BLE001 - fallback to cache
|
|
406
|
+
stale_cached, cache_age = _load_cache_with_age(cache_path) if cache_safe else (None, None)
|
|
419
407
|
if stale_cached is not None:
|
|
420
408
|
logger.warning(
|
|
421
409
|
"Device fetch failed; using stale cache (%ds old): %s",
|
|
@@ -445,15 +433,12 @@ def fetch_clients(
|
|
|
445
433
|
site_name = site or config.site
|
|
446
434
|
ttl_seconds = _cache_ttl_seconds()
|
|
447
435
|
cache_path = _cache_dir() / f"clients_{_cache_key(config.url, site_name)}.json"
|
|
448
|
-
|
|
436
|
+
cache_safe = use_cache and _is_cache_dir_safe(cache_path.parent)
|
|
437
|
+
if cache_safe:
|
|
449
438
|
cached = _load_cache(cache_path, ttl_seconds)
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
stale_cached, cache_age = None, None
|
|
454
|
-
if cached is not None:
|
|
455
|
-
logger.debug("Using cached clients (%d)", len(cached))
|
|
456
|
-
return cached
|
|
439
|
+
if cached is not None:
|
|
440
|
+
logger.debug("Using cached clients (%d)", len(cached))
|
|
441
|
+
return cached
|
|
457
442
|
|
|
458
443
|
try:
|
|
459
444
|
controller = _init_controller(config, is_udm_pro=True)
|
|
@@ -467,6 +452,7 @@ def fetch_clients(
|
|
|
467
452
|
try:
|
|
468
453
|
clients = _call_with_retries("client fetch", _fetch)
|
|
469
454
|
except Exception as exc: # noqa: BLE001 - fallback to cache
|
|
455
|
+
stale_cached, cache_age = _load_cache_with_age(cache_path) if cache_safe else (None, None)
|
|
470
456
|
if stale_cached is not None:
|
|
471
457
|
logger.warning(
|
|
472
458
|
"Client fetch failed; using stale cache (%ds old): %s",
|
|
@@ -496,15 +482,12 @@ def fetch_networks(
|
|
|
496
482
|
site_name = site or config.site
|
|
497
483
|
ttl_seconds = _cache_ttl_seconds()
|
|
498
484
|
cache_path = _cache_dir() / f"networks_{_cache_key(config.url, site_name)}.json"
|
|
499
|
-
|
|
485
|
+
cache_safe = use_cache and _is_cache_dir_safe(cache_path.parent)
|
|
486
|
+
if cache_safe:
|
|
500
487
|
cached = _load_cache(cache_path, ttl_seconds)
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
stale_cached, cache_age = None, None
|
|
505
|
-
if cached is not None:
|
|
506
|
-
logger.debug("Using cached networks (%d)", len(cached))
|
|
507
|
-
return cached
|
|
488
|
+
if cached is not None:
|
|
489
|
+
logger.debug("Using cached networks (%d)", len(cached))
|
|
490
|
+
return cached
|
|
508
491
|
|
|
509
492
|
try:
|
|
510
493
|
controller = _init_controller(config, is_udm_pro=True)
|
|
@@ -513,15 +496,14 @@ def fetch_networks(
|
|
|
513
496
|
controller = _init_controller(config, is_udm_pro=False)
|
|
514
497
|
|
|
515
498
|
def _fetch() -> Sequence[object]:
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
logger.warning("Networkconf model parse failed; retrying raw fetch: %s", exc)
|
|
520
|
-
return controller.get_unifi_site_networkconf(site_name=site_name, raw=True)
|
|
499
|
+
# Always use raw=True to avoid model parsing issues with disabled WAN interfaces
|
|
500
|
+
# (the UnifiNetworkConf model requires an 'enabled' field that may be absent)
|
|
501
|
+
return controller.get_unifi_site_networkconf(site_name=site_name, raw=True)
|
|
521
502
|
|
|
522
503
|
try:
|
|
523
504
|
networks = _call_with_retries("network fetch", _fetch)
|
|
524
505
|
except Exception as exc: # noqa: BLE001 - fallback to cache
|
|
506
|
+
stale_cached, cache_age = _load_cache_with_age(cache_path) if cache_safe else (None, None)
|
|
525
507
|
if stale_cached is not None:
|
|
526
508
|
logger.warning(
|
|
527
509
|
"Network fetch failed; using stale cache (%ds old): %s",
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon wifi as isometric decal (30° perspective) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 90 160">
|
|
4
|
+
<g transform="matrix(0.866, 0.5, -0.866, 0.5, 45, 126)">
|
|
5
|
+
<g transform="translate(-12,-12) scale(2)">
|
|
6
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.37128 8.1434C7.22915 2.28553 16.7266 2.28553 22.5845 8.1434C22.8774 8.43628 22.8774 8.91114 22.5845 9.20404L22.0542 9.73441C21.9135 9.87507 21.7228 9.9541 21.5238 9.9541C21.3249 9.95411 21.1341 9.87509 20.9935 9.73443C16.0143 4.75525 7.94146 4.75525 2.96227 9.73443C2.82162 9.87509 2.63084 9.95411 2.43193 9.9541C2.23301 9.9541 2.04224 9.87507 1.90159 9.73441L1.37126 9.20404C1.07839 8.91114 1.0784 8.43628 1.37128 8.1434ZM4.55326 11.3254C8.65377 7.22493 15.302 7.22493 19.4025 11.3254C19.6954 11.6183 19.6954 12.0932 19.4025 12.3861L18.8722 12.9164C18.7316 13.0571 18.5408 13.1361 18.3419 13.1361C18.143 13.1361 17.9522 13.0571 17.8115 12.9164C14.5897 9.6946 9.3661 9.6946 6.14427 12.9164C5.85139 13.2093 5.37652 13.2093 5.08362 12.9164L4.55327 12.3861C4.41262 12.2455 4.33359 12.0547 4.33359 11.8558C4.33359 11.6569 4.41261 11.4661 4.55326 11.3254ZM7.75733 14.5074C10.1005 12.1642 13.8995 12.1642 16.2426 14.5074C16.5355 14.8003 16.5355 15.2751 16.2426 15.568L15.7123 16.0983C15.5716 16.239 15.3809 16.318 15.182 16.318C14.983 16.318 14.7923 16.239 14.6516 16.0983C13.1872 14.6339 10.8128 14.6339 9.34832 16.0983C9.05543 16.3912 8.58055 16.3912 8.28766 16.0983L7.75733 15.568C7.46444 15.2751 7.46444 14.8003 7.75733 14.5074ZM10.9393 17.6893C11.5251 17.1036 12.4748 17.1036 13.0606 17.6893C13.3535 17.9822 13.3535 18.4571 13.0606 18.75L12.5303 19.2803C12.3896 19.421 12.1989 19.5 12 19.5C11.8011 19.5 11.6103 19.421 11.4696 19.2803L10.9393 18.75C10.6464 18.4571 10.6464 17.9822 10.9393 17.6893Z" fill="#DECAL0"/>
|
|
7
|
+
</g>
|
|
8
|
+
</g>
|
|
9
|
+
</svg>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon video-camera as isometric decal (30° perspective) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 66">
|
|
4
|
+
<g transform="matrix(0.866, 0.5, -0.866, 0.5, 30, 38)">
|
|
5
|
+
<g transform="translate(-12,-12) scale(1)">
|
|
6
|
+
<path d="m15.75 10.5 4.72-4.72a.75.75 0 0 1 1.28.53v11.38a.75.75 0 0 1-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 0 0 2.25-2.25v-9a2.25 2.25 0 0 0-2.25-2.25h-9A2.25 2.25 0 0 0 2.25 7.5v9a2.25 2.25 0 0 0 2.25 2.25Z" fill="#DECAL0"/>
|
|
7
|
+
</g>
|
|
8
|
+
</g>
|
|
9
|
+
</svg>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon computer-desktop as isometric decal (30° perspective) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 66">
|
|
4
|
+
<g transform="matrix(0.866, 0.5, -0.866, 0.5, 30, 38)">
|
|
5
|
+
<g transform="translate(-12,-12) scale(1)">
|
|
6
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.25 5.25C2.25 3.59315 3.59315 2.25 5.25 2.25H18.75C20.4069 2.25 21.75 3.59315 21.75 5.25V15C21.75 16.6569 20.4069 18 18.75 18H15.75V18.2574C15.75 18.8541 15.9871 19.4264 16.409 19.8483L17.0303 20.4697C17.2448 20.6842 17.309 21.0068 17.1929 21.287C17.0768 21.5673 16.8033 21.75 16.5 21.75H7.5C7.19665 21.75 6.92318 21.5673 6.80709 21.287C6.691 21.0068 6.75517 20.6842 6.96967 20.4697L7.59099 19.8484C8.01295 19.4264 8.25 18.8541 8.25 18.2574V18H5.25C3.59315 18 2.25 16.6569 2.25 15V5.25ZM3.75 5.25V12.75C3.75 13.5784 4.42157 14.25 5.25 14.25H18.75C19.5784 14.25 20.25 13.5784 20.25 12.75V5.25C20.25 4.42157 19.5784 3.75 18.75 3.75H5.25C4.42157 3.75 3.75 4.42157 3.75 5.25Z" fill="#DECAL0"/>
|
|
7
|
+
</g>
|
|
8
|
+
</g>
|
|
9
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon puzzle-piece as isometric decal (30° perspective) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 66">
|
|
4
|
+
<g transform="matrix(0.866, 0.5, -0.866, 0.5, 30, 38)">
|
|
5
|
+
<g transform="translate(-12,-12) scale(1)">
|
|
6
|
+
<path d="M14.25 6.087c0-.355.186-.676.401-.959.221-.29.349-.634.349-1.003 0-1.036-1.007-1.875-2.25-1.875s-2.25.84-2.25 1.875c0 .369.128.713.349 1.003.215.283.401.604.401.959v0a.64.64 0 0 1-.657.643 48.39 48.39 0 0 0-4.163.3c-1.48.183-2.55 1.465-2.55 2.888v0c0 .426.084.84.248 1.216l3.553 8.088a2.25 2.25 0 0 0 2.062 1.348h4.514a2.25 2.25 0 0 0 2.062-1.348l3.553-8.088c.164-.376.248-.79.248-1.216v0c0-1.423-1.07-2.705-2.55-2.888a48.39 48.39 0 0 0-4.163-.3.64.64 0 0 1-.657-.643v0Z" fill="#DECAL0"/>
|
|
7
|
+
<path d="M9.375 15a.375.375 0 1 1 0-.75.375.375 0 0 1 0 .75Zm0-3a.375.375 0 1 1 0-.75.375.375 0 0 1 0 .75Zm1.5 1.5a.375.375 0 1 1 0-.75.375.375 0 0 1 0 .75Zm1.5-1.5a.375.375 0 1 1 0-.75.375.375 0 0 1 0 .75Zm1.5 0a.375.375 0 1 1 0-.75.375.375 0 0 1 0 .75Zm1.5 1.5a.375.375 0 1 1 0-.75.375.375 0 0 1 0 .75Zm0 1.5a.375.375 0 1 1 0-.75.375.375 0 0 1 0 .75Z" fill="#DECAL0"/>
|
|
8
|
+
</g>
|
|
9
|
+
</g>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon globe-alt as isometric decal (30° perspective) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 66">
|
|
4
|
+
<g transform="matrix(0.866, 0.5, -0.866, 0.5, 30, 38)">
|
|
5
|
+
<g transform="translate(-12,-12) scale(1)">
|
|
6
|
+
<path d="M21.7214 12.7517C21.7404 12.5036 21.75 12.2529 21.75 11.9999C21.75 10.4758 21.4003 9.03328 20.7767 7.74835C19.5396 8.92269 18.0671 9.85146 16.4374 10.4565C16.4789 10.9655 16.5 11.4803 16.5 11.9999C16.5 13.1011 16.4051 14.1802 16.2229 15.2293C18.2163 14.7277 20.0717 13.8792 21.7214 12.7517Z" fill="#DECAL0"/>
|
|
7
|
+
<path d="M14.6343 15.5501C14.874 14.4043 15 13.2168 15 11.9999C15 11.6315 14.9885 11.2659 14.9657 10.9032C14.0141 11.1299 13.021 11.2499 12 11.2499C10.979 11.2499 9.98594 11.1299 9.0343 10.9032C9.01155 11.2659 9 11.6315 9 11.9999C9 13.2168 9.12601 14.4043 9.3657 15.5501C10.2246 15.6817 11.1043 15.7499 12 15.7499C12.8957 15.7499 13.7754 15.6817 14.6343 15.5501Z" fill="#DECAL0"/>
|
|
8
|
+
<path d="M9.77224 17.119C10.5028 17.2054 11.2462 17.2499 12 17.2499C12.7538 17.2499 13.4972 17.2054 14.2278 17.119C13.714 18.7746 12.9575 20.3235 12 21.724C11.0425 20.3235 10.286 18.7746 9.77224 17.119Z" fill="#DECAL0"/>
|
|
9
|
+
<path d="M7.77705 15.2293C7.59493 14.1802 7.5 13.1011 7.5 11.9999C7.5 11.4803 7.52114 10.9655 7.56261 10.4565C5.93286 9.85146 4.46039 8.92269 3.22333 7.74835C2.59973 9.03328 2.25 10.4758 2.25 11.9999C2.25 12.2529 2.25964 12.5036 2.27856 12.7517C3.92826 13.8792 5.78374 14.7277 7.77705 15.2293Z" fill="#DECAL0"/>
|
|
10
|
+
<path d="M21.3561 14.7525C20.3404 18.2104 17.4597 20.8705 13.8776 21.5693C14.744 20.1123 15.4185 18.5278 15.8664 16.8508C17.8263 16.44 19.6736 15.7231 21.3561 14.7525Z" fill="#DECAL0"/>
|
|
11
|
+
<path d="M2.64395 14.7525C4.32642 15.7231 6.17372 16.44 8.13356 16.8508C8.58146 18.5278 9.25602 20.1123 10.1224 21.5693C6.54027 20.8705 3.65964 18.2104 2.64395 14.7525Z" fill="#DECAL0"/>
|
|
12
|
+
<path d="M13.8776 2.43055C16.3991 2.92245 18.5731 4.3862 19.9937 6.41599C18.9351 7.48484 17.6637 8.34251 16.2483 8.92017C15.862 6.58282 15.0435 4.39132 13.8776 2.43055Z" fill="#DECAL0"/>
|
|
13
|
+
<path d="M12 2.27588C13.4287 4.36548 14.4097 6.78537 14.805 9.39744C13.9083 9.62756 12.9684 9.74993 12 9.74993C11.0316 9.74993 10.0917 9.62756 9.19503 9.39744C9.5903 6.78537 10.5713 4.36548 12 2.27588Z" fill="#DECAL0"/>
|
|
14
|
+
<path d="M10.1224 2.43055C8.95648 4.39132 8.13795 6.58282 7.75171 8.92017C6.33629 8.34251 5.06489 7.48484 4.00635 6.41599C5.42689 4.3862 7.60085 2.92245 10.1224 2.43055Z" fill="#DECAL0"/>
|
|
15
|
+
</g>
|
|
16
|
+
</g>
|
|
17
|
+
</svg>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon signal as isometric decal (30° perspective) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 66">
|
|
4
|
+
<g transform="matrix(0.866, 0.5, -0.866, 0.5, 30, 38)">
|
|
5
|
+
<g transform="translate(-12,-12) scale(1)">
|
|
6
|
+
<path d="M9.348 14.652a3.75 3.75 0 0 1 0-5.304m5.304 0a3.75 3.75 0 0 1 0 5.304m-7.425 2.121a6.75 6.75 0 0 1 0-9.546m9.546 0a6.75 6.75 0 0 1 0 9.546M5.106 18.894c-3.808-3.807-3.808-9.98 0-13.788m13.788 0c3.808 3.807 3.808 9.98 0 13.788M12 12h.008v.008H12V12Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z" fill="#DECAL0"/>
|
|
7
|
+
</g>
|
|
8
|
+
</g>
|
|
9
|
+
</svg>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon server-stack as isometric decal (30° perspective) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 66">
|
|
4
|
+
<g transform="matrix(0.866, 0.5, -0.866, 0.5, 30, 38)">
|
|
5
|
+
<g transform="translate(-12,-12) scale(1)">
|
|
6
|
+
<path d="M5.25 14.25h13.5m-13.5 0a3 3 0 0 1-3-3m3 3a3 3 0 1 0 0 6h13.5a3 3 0 1 0 0-6m-16.5-3a3 3 0 0 1 3-3h13.5a3 3 0 0 1 3 3m-19.5 0a4.5 4.5 0 0 1 .9-2.7L5.737 5.1a3.375 3.375 0 0 1 2.7-1.35h7.126c1.062 0 2.062.5 2.7 1.35l2.587 3.45a4.5 4.5 0 0 1 .9 2.7m0 0a3 3 0 0 1-3 3m0 3h.008v.008h-.008v-.008Zm0-6h.008v.008h-.008v-.008Zm-3 6h.008v.008h-.008v-.008Zm0-6h.008v.008h-.008v-.008Z" fill="#DECAL0"/>
|
|
7
|
+
</g>
|
|
8
|
+
</g>
|
|
9
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon server as isometric decal (30° perspective) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 66">
|
|
4
|
+
<g transform="matrix(0.866, 0.5, -0.866, 0.5, 30, 38)">
|
|
5
|
+
<g transform="translate(-12,-12) scale(1)">
|
|
6
|
+
<path d="M4.07993 5.22701C4.43013 3.91375 5.61948 3 6.97863 3H17.0214C18.3805 3 19.5699 3.91375 19.9201 5.22701L22.0338 13.1535C21.1346 12.4318 19.9927 12 18.75 12H5.25C4.00727 12 2.86538 12.4318 1.96619 13.1535L4.07993 5.22701Z" fill="#DECAL0"/>
|
|
7
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.25 13.5C3.17893 13.5 1.5 15.1789 1.5 17.25C1.5 19.3211 3.17893 21 5.25 21H18.75C20.8211 21 22.5 19.3211 22.5 17.25C22.5 15.1789 20.8211 13.5 18.75 13.5H5.25ZM15.75 18C16.1642 18 16.5 17.6642 16.5 17.25C16.5 16.8358 16.1642 16.5 15.75 16.5C15.3358 16.5 15 16.8358 15 17.25C15 17.6642 15.3358 18 15.75 18ZM19.5 17.25C19.5 17.6642 19.1642 18 18.75 18C18.3358 18 18 17.6642 18 17.25C18 16.8358 18.3358 16.5 18.75 16.5C19.1642 16.5 19.5 16.8358 19.5 17.25Z" fill="#DECAL0"/>
|
|
8
|
+
</g>
|
|
9
|
+
</g>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon device-phone-mobile as isometric decal (30° perspective) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 66">
|
|
4
|
+
<g transform="matrix(0.866, 0.5, -0.866, 0.5, 30, 38)">
|
|
5
|
+
<g transform="translate(-12,-12) scale(1)">
|
|
6
|
+
<path d="M10.5 18.75a.75.75 0 0 0 0 1.5h3a.75.75 0 0 0 0-1.5h-3Z" fill="#DECAL0"/>
|
|
7
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.625.75A3.375 3.375 0 0 0 5.25 4.125v15.75a3.375 3.375 0 0 0 3.375 3.375h6.75a3.375 3.375 0 0 0 3.375-3.375V4.125A3.375 3.375 0 0 0 15.375.75h-6.75ZM7.5 4.125C7.5 3.504 8.004 3 8.625 3H9.75v.375c0 .621.504 1.125 1.125 1.125h2.25c.621 0 1.125-.504 1.125-1.125V3h1.125c.621 0 1.125.504 1.125 1.125v15.75c0 .621-.504 1.125-1.125 1.125h-6.75a1.125 1.125 0 0 1-1.125-1.125V4.125Z" fill="#DECAL0"/>
|
|
8
|
+
</g>
|
|
9
|
+
</g>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon printer as isometric decal (30° perspective) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 66">
|
|
4
|
+
<g transform="matrix(0.866, 0.5, -0.866, 0.5, 30, 38)">
|
|
5
|
+
<g transform="translate(-12,-12) scale(1)">
|
|
6
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.875 1.5C6.839 1.5 6 2.34 6 3.375v2.99c-.426.053-.851.11-1.274.174-1.454.218-2.476 1.483-2.476 2.917v6.294a3 3 0 0 0 3 3h.27l-.155 1.705A1.875 1.875 0 0 0 7.232 22.5h9.536a1.875 1.875 0 0 0 1.867-2.045l-.155-1.705h.27a3 3 0 0 0 3-3V9.456c0-1.434-1.022-2.7-2.476-2.917A48.716 48.716 0 0 0 18 6.366V3.375c0-1.036-.84-1.875-1.875-1.875h-8.25ZM16.5 6.205v-2.83a.375.375 0 0 0-.375-.375h-8.25a.375.375 0 0 0-.375.375v2.83a49.353 49.353 0 0 1 9 0Zm-.217 8.265c.178.018.317.16.333.337l.526 5.784a.375.375 0 0 1-.374.409H7.232a.375.375 0 0 1-.374-.409l.526-5.784a.373.373 0 0 1 .333-.337 41.741 41.741 0 0 1 8.566 0Zm.967-3.97a.75.75 0 0 1 .75-.75h.008a.75.75 0 0 1 .75.75v.008a.75.75 0 0 1-.75.75H18a.75.75 0 0 1-.75-.75V10.5Zm-3 0a.75.75 0 0 1 .75-.75h.008a.75.75 0 0 1 .75.75v.008a.75.75 0 0 1-.75.75H15a.75.75 0 0 1-.75-.75V10.5Z" fill="#DECAL0"/>
|
|
7
|
+
</g>
|
|
8
|
+
</g>
|
|
9
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon speaker-wave as isometric decal (30° perspective) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 66">
|
|
4
|
+
<g transform="matrix(0.866, 0.5, -0.866, 0.5, 30, 38)">
|
|
5
|
+
<g transform="translate(-12,-12) scale(1)">
|
|
6
|
+
<path d="M13.5 4.06c0-1.336-1.616-2.005-2.56-1.06l-4.5 4.5H4.508c-1.141 0-2.318.664-2.66 1.905A9.76 9.76 0 0 0 1.5 12c0 .898.121 1.768.35 2.595.341 1.24 1.518 1.905 2.659 1.905h1.93l4.5 4.5c.945.945 2.561.276 2.561-1.06V4.06ZM18.584 5.106a.75.75 0 0 1 1.06 0c3.808 3.807 3.808 9.98 0 13.788a.75.75 0 0 1-1.06-1.06 8.25 8.25 0 0 0 0-11.668.75.75 0 0 1 0-1.06Z" fill="#DECAL0"/>
|
|
7
|
+
<path d="M15.932 7.757a.75.75 0 0 1 1.061 0 6 6 0 0 1 0 8.486.75.75 0 0 1-1.06-1.061 4.5 4.5 0 0 0 0-6.364.75.75 0 0 1 0-1.06Z" fill="#DECAL0"/>
|
|
8
|
+
</g>
|
|
9
|
+
</g>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon server as isometric decal (30° perspective) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 66">
|
|
4
|
+
<g transform="matrix(0.866, 0.5, -0.866, 0.5, 30, 38)">
|
|
5
|
+
<g transform="translate(-12,-12) scale(1)">
|
|
6
|
+
<path d="M4.07993 5.22701C4.43013 3.91375 5.61948 3 6.97863 3H17.0214C18.3805 3 19.5699 3.91375 19.9201 5.22701L22.0338 13.1535C21.1346 12.4318 19.9927 12 18.75 12H5.25C4.00727 12 2.86538 12.4318 1.96619 13.1535L4.07993 5.22701Z" fill="#DECAL0"/>
|
|
7
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.25 13.5C3.17893 13.5 1.5 15.1789 1.5 17.25C1.5 19.3211 3.17893 21 5.25 21H18.75C20.8211 21 22.5 19.3211 22.5 17.25C22.5 15.1789 20.8211 13.5 18.75 13.5H5.25ZM15.75 18C16.1642 18 16.5 17.6642 16.5 17.25C16.5 16.8358 16.1642 16.5 15.75 16.5C15.3358 16.5 15 16.8358 15 17.25C15 17.6642 15.3358 18 15.75 18ZM19.5 17.25C19.5 17.6642 19.1642 18 18.75 18C18.3358 18 18 17.6642 18 17.25C18 16.8358 18.3358 16.5 18.75 16.5C19.1642 16.5 19.5 16.8358 19.5 17.25Z" fill="#DECAL0"/>
|
|
8
|
+
</g>
|
|
9
|
+
</g>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon tv as isometric decal (30° perspective) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 66">
|
|
4
|
+
<g transform="matrix(0.866, 0.5, -0.866, 0.5, 30, 38)">
|
|
5
|
+
<g transform="translate(-12,-12) scale(1)">
|
|
6
|
+
<path d="M19.5 6h-15v9h15V6Z" fill="#DECAL0"/>
|
|
7
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.375 3C2.339 3 1.5 3.84 1.5 4.875v11.25C1.5 17.16 2.34 18 3.375 18H9.75v1.5H6A.75.75 0 0 0 6 21h12a.75.75 0 0 0 0-1.5h-3.75V18h6.375c1.035 0 1.875-.84 1.875-1.875V4.875C22.5 3.839 21.66 3 20.625 3H3.375Zm0 13.5h17.25a.375.375 0 0 0 .375-.375V4.875a.375.375 0 0 0-.375-.375H3.375A.375.375 0 0 0 3 4.875v11.25c0 .207.168.375.375.375Z" fill="#DECAL0"/>
|
|
8
|
+
</g>
|
|
9
|
+
</g>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon wifi (flat) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#DECAL0">
|
|
4
|
+
<path fill-rule="evenodd" d="M1.371 8.143c5.858-5.857 15.356-5.857 21.213 0a.75.75 0 0 1 0 1.061.75.75 0 0 1-1.06 0 13.5 13.5 0 0 0-19.092 0 .75.75 0 0 1-1.06-1.06Zm3.182 3.182a10.5 10.5 0 0 1 14.85 0 .75.75 0 1 1-1.061 1.06 9 9 0 0 0-12.728 0 .75.75 0 1 1-1.06-1.06Zm3.182 3.182a6 6 0 0 1 8.486 0 .75.75 0 1 1-1.061 1.06 4.5 4.5 0 0 0-6.364 0 .75.75 0 0 1-1.06-1.06Zm3.182 3.182a1.5 1.5 0 0 1 2.121 0 .75.75 0 1 1-1.061 1.06.75.75 0 0 1 0-1.06Z" clip-rule="evenodd"/>
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon video-camera (mini) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#DECAL0">
|
|
4
|
+
<path d="m15.75 10.5 4.72-4.72a.75.75 0 0 1 1.28.53v11.38a.75.75 0 0 1-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 0 0 2.25-2.25v-9a2.25 2.25 0 0 0-2.25-2.25h-9A2.25 2.25 0 0 0 2.25 7.5v9a2.25 2.25 0 0 0 2.25 2.25Z" />
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon computer-desktop (flat) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#DECAL0">
|
|
4
|
+
<path fill-rule="evenodd" d="M2.25 5.25a3 3 0 0 1 3-3h13.5a3 3 0 0 1 3 3V15a3 3 0 0 1-3 3h-3v.257c0 .597.237 1.17.659 1.591l.621.622a.75.75 0 0 1-.53 1.28h-9a.75.75 0 0 1-.53-1.28l.621-.622a2.25 2.25 0 0 0 .659-1.59V18h-3a3 3 0 0 1-3-3V5.25Zm1.5 0v7.5a1.5 1.5 0 0 0 1.5 1.5h13.5a1.5 1.5 0 0 0 1.5-1.5v-7.5a1.5 1.5 0 0 0-1.5-1.5H5.25a1.5 1.5 0 0 0-1.5 1.5Z" clip-rule="evenodd"/>
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon puzzle-piece (mini) - representing game/entertainment -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#DECAL0">
|
|
4
|
+
<path d="M14.25 6.087c0-.355.186-.676.401-.959.221-.29.349-.634.349-1.003 0-1.036-1.007-1.875-2.25-1.875s-2.25.84-2.25 1.875c0 .369.128.713.349 1.003.215.283.401.604.401.959v0a.64.64 0 0 1-.657.643 48.39 48.39 0 0 0-4.163.3c-1.48.183-2.55 1.465-2.55 2.888v0c0 .426.084.84.248 1.216l3.553 8.088a2.25 2.25 0 0 0 2.062 1.348h4.514a2.25 2.25 0 0 0 2.062-1.348l3.553-8.088c.164-.376.248-.79.248-1.216v0c0-1.423-1.07-2.705-2.55-2.888a48.39 48.39 0 0 0-4.163-.3.64.64 0 0 1-.657-.643v0Z"/>
|
|
5
|
+
<path d="M9.375 15a.375.375 0 1 1 0-.75.375.375 0 0 1 0 .75Zm0-3a.375.375 0 1 1 0-.75.375.375 0 0 1 0 .75Zm1.5 1.5a.375.375 0 1 1 0-.75.375.375 0 0 1 0 .75Zm1.5-1.5a.375.375 0 1 1 0-.75.375.375 0 0 1 0 .75Zm1.5 0a.375.375 0 1 1 0-.75.375.375 0 0 1 0 .75Zm1.5 1.5a.375.375 0 1 1 0-.75.375.375 0 0 1 0 .75Zm0 1.5a.375.375 0 1 1 0-.75.375.375 0 0 1 0 .75Z"/>
|
|
6
|
+
</svg>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon globe-alt (flat) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#DECAL0">
|
|
4
|
+
<path d="M21.7214 12.7517C21.7404 12.5036 21.75 12.2529 21.75 11.9999C21.75 10.4758 21.4003 9.03328 20.7767 7.74835C19.5396 8.92269 18.0671 9.85146 16.4374 10.4565C16.4789 10.9655 16.5 11.4803 16.5 11.9999C16.5 13.1011 16.4051 14.1802 16.2229 15.2293C18.2163 14.7277 20.0717 13.8792 21.7214 12.7517Z"/>
|
|
5
|
+
<path d="M14.6343 15.5501C14.874 14.4043 15 13.2168 15 11.9999C15 11.6315 14.9885 11.2659 14.9657 10.9032C14.0141 11.1299 13.021 11.2499 12 11.2499C10.979 11.2499 9.98594 11.1299 9.0343 10.9032C9.01155 11.2659 9 11.6315 9 11.9999C9 13.2168 9.12601 14.4043 9.3657 15.5501C10.2246 15.6817 11.1043 15.7499 12 15.7499C12.8957 15.7499 13.7754 15.6817 14.6343 15.5501Z"/>
|
|
6
|
+
<path d="M9.77224 17.119C10.5028 17.2054 11.2462 17.2499 12 17.2499C12.7538 17.2499 13.4972 17.2054 14.2278 17.119C13.714 18.7746 12.9575 20.3235 12 21.724C11.0425 20.3235 10.286 18.7746 9.77224 17.119Z"/>
|
|
7
|
+
<path d="M7.77705 15.2293C7.59493 14.1802 7.5 13.1011 7.5 11.9999C7.5 11.4803 7.52114 10.9655 7.56261 10.4565C5.93286 9.85146 4.46039 8.92269 3.22333 7.74835C2.59973 9.03328 2.25 10.4758 2.25 11.9999C2.25 12.2529 2.25964 12.5036 2.27856 12.7517C3.92826 13.8792 5.78374 14.7277 7.77705 15.2293Z"/>
|
|
8
|
+
<path d="M21.3561 14.7525C20.3404 18.2104 17.4597 20.8705 13.8776 21.5693C14.744 20.1123 15.4185 18.5278 15.8664 16.8508C17.8263 16.44 19.6736 15.7231 21.3561 14.7525Z"/>
|
|
9
|
+
<path d="M2.64395 14.7525C4.32642 15.7231 6.17372 16.44 8.13356 16.8508C8.58146 18.5278 9.25602 20.1123 10.1224 21.5693C6.54027 20.8705 3.65964 18.2104 2.64395 14.7525Z"/>
|
|
10
|
+
<path d="M13.8776 2.43055C16.3991 2.92245 18.5731 4.3862 19.9937 6.41599C18.9351 7.48484 17.6637 8.34251 16.2483 8.92017C15.862 6.58282 15.0435 4.39132 13.8776 2.43055Z"/>
|
|
11
|
+
<path d="M12 2.27588C13.4287 4.36548 14.4097 6.78537 14.805 9.39744C13.9083 9.62756 12.9684 9.74993 12 9.74993C11.0316 9.74993 10.0917 9.62756 9.19503 9.39744C9.5903 6.78537 10.5713 4.36548 12 2.27588Z"/>
|
|
12
|
+
<path d="M10.1224 2.43055C8.95648 4.39132 8.13795 6.58282 7.75171 8.92017C6.33629 8.34251 5.06489 7.48484 4.00635 6.41599C5.42689 4.3862 7.60085 2.92245 10.1224 2.43055Z"/>
|
|
13
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon signal (mini) - representing IoT/connected devices -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#DECAL0">
|
|
4
|
+
<path d="M9.348 14.652a3.75 3.75 0 0 1 0-5.304m5.304 0a3.75 3.75 0 0 1 0 5.304m-7.425 2.121a6.75 6.75 0 0 1 0-9.546m9.546 0a6.75 6.75 0 0 1 0 9.546M5.106 18.894c-3.808-3.807-3.808-9.98 0-13.788m13.788 0c3.808 3.807 3.808 9.98 0 13.788M12 12h.008v.008H12V12Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z"/>
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon server-stack (mini) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#DECAL0">
|
|
4
|
+
<path d="M5.25 14.25h13.5m-13.5 0a3 3 0 0 1-3-3m3 3a3 3 0 1 0 0 6h13.5a3 3 0 1 0 0-6m-16.5-3a3 3 0 0 1 3-3h13.5a3 3 0 0 1 3 3m-19.5 0a4.5 4.5 0 0 1 .9-2.7L5.737 5.1a3.375 3.375 0 0 1 2.7-1.35h7.126c1.062 0 2.062.5 2.7 1.35l2.587 3.45a4.5 4.5 0 0 1 .9 2.7m0 0a3 3 0 0 1-3 3m0 3h.008v.008h-.008v-.008Zm0-6h.008v.008h-.008v-.008Zm-3 6h.008v.008h-.008v-.008Zm0-6h.008v.008h-.008v-.008Z"/>
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon server (flat) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#DECAL0">
|
|
4
|
+
<path d="M4.08 5.227A3 3 0 0 1 6.979 3H17.02a3 3 0 0 1 2.9 2.227l2.113 7.926A5.228 5.228 0 0 0 18.75 12H5.25a5.228 5.228 0 0 0-3.284 1.153L4.08 5.227Z"/>
|
|
5
|
+
<path fill-rule="evenodd" d="M5.25 13.5a3.75 3.75 0 1 0 0 7.5h13.5a3.75 3.75 0 1 0 0-7.5H5.25Zm10.5 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm3.75-.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Z" clip-rule="evenodd"/>
|
|
6
|
+
</svg>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon device-phone-mobile (mini) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#DECAL0">
|
|
4
|
+
<path d="M10.5 18.75a.75.75 0 0 0 0 1.5h3a.75.75 0 0 0 0-1.5h-3Z"/>
|
|
5
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.625.75A3.375 3.375 0 0 0 5.25 4.125v15.75a3.375 3.375 0 0 0 3.375 3.375h6.75a3.375 3.375 0 0 0 3.375-3.375V4.125A3.375 3.375 0 0 0 15.375.75h-6.75ZM7.5 4.125C7.5 3.504 8.004 3 8.625 3H9.75v.375c0 .621.504 1.125 1.125 1.125h2.25c.621 0 1.125-.504 1.125-1.125V3h1.125c.621 0 1.125.504 1.125 1.125v15.75c0 .621-.504 1.125-1.125 1.125h-6.75a1.125 1.125 0 0 1-1.125-1.125V4.125Z"/>
|
|
6
|
+
</svg>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon printer (mini) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#DECAL0">
|
|
4
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.875 1.5C6.839 1.5 6 2.34 6 3.375v2.99c-.426.053-.851.11-1.274.174-1.454.218-2.476 1.483-2.476 2.917v6.294a3 3 0 0 0 3 3h.27l-.155 1.705A1.875 1.875 0 0 0 7.232 22.5h9.536a1.875 1.875 0 0 0 1.867-2.045l-.155-1.705h.27a3 3 0 0 0 3-3V9.456c0-1.434-1.022-2.7-2.476-2.917A48.716 48.716 0 0 0 18 6.366V3.375c0-1.036-.84-1.875-1.875-1.875h-8.25ZM16.5 6.205v-2.83a.375.375 0 0 0-.375-.375h-8.25a.375.375 0 0 0-.375.375v2.83a49.353 49.353 0 0 1 9 0Zm-.217 8.265c.178.018.317.16.333.337l.526 5.784a.375.375 0 0 1-.374.409H7.232a.375.375 0 0 1-.374-.409l.526-5.784a.373.373 0 0 1 .333-.337 41.741 41.741 0 0 1 8.566 0Zm.967-3.97a.75.75 0 0 1 .75-.75h.008a.75.75 0 0 1 .75.75v.008a.75.75 0 0 1-.75.75H18a.75.75 0 0 1-.75-.75V10.5Zm-3 0a.75.75 0 0 1 .75-.75h.008a.75.75 0 0 1 .75.75v.008a.75.75 0 0 1-.75.75H15a.75.75 0 0 1-.75-.75V10.5Z"/>
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon speaker-wave (mini) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#DECAL0">
|
|
4
|
+
<path d="M13.5 4.06c0-1.336-1.616-2.005-2.56-1.06l-4.5 4.5H4.508c-1.141 0-2.318.664-2.66 1.905A9.76 9.76 0 0 0 1.5 12c0 .898.121 1.768.35 2.595.341 1.24 1.518 1.905 2.659 1.905h1.93l4.5 4.5c.945.945 2.561.276 2.561-1.06V4.06ZM18.584 5.106a.75.75 0 0 1 1.06 0c3.808 3.807 3.808 9.98 0 13.788a.75.75 0 0 1-1.06-1.06 8.25 8.25 0 0 0 0-11.668.75.75 0 0 1 0-1.06Z"/>
|
|
5
|
+
<path d="M15.932 7.757a.75.75 0 0 1 1.061 0 6 6 0 0 1 0 8.486.75.75 0 0 1-1.06-1.061 4.5 4.5 0 0 0 0-6.364.75.75 0 0 1 0-1.06Z"/>
|
|
6
|
+
</svg>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon server-stack (flat) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#DECAL0">
|
|
4
|
+
<path d="M5.25 2.25a3 3 0 0 0-3 3v4.5a3 3 0 0 0 3 3h13.5a3 3 0 0 0 3-3v-4.5a3 3 0 0 0-3-3H5.25Zm0 1.5h13.5a1.5 1.5 0 0 1 1.5 1.5v4.5a1.5 1.5 0 0 1-1.5 1.5H5.25a1.5 1.5 0 0 1-1.5-1.5v-4.5a1.5 1.5 0 0 1 1.5-1.5ZM5.25 11.25a3 3 0 0 0-3 3v4.5a3 3 0 0 0 3 3h13.5a3 3 0 0 0 3-3v-4.5a3 3 0 0 0-3-3H5.25Zm0 1.5h13.5a1.5 1.5 0 0 1 1.5 1.5v4.5a1.5 1.5 0 0 1-1.5 1.5H5.25a1.5 1.5 0 0 1-1.5-1.5v-4.5a1.5 1.5 0 0 1 1.5-1.5Z"/>
|
|
5
|
+
<path d="M6 6.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM6 15.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Z"/>
|
|
6
|
+
</svg>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Heroicon tv (mini) -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#DECAL0">
|
|
4
|
+
<path d="M19.5 6h-15v9h15V6Z"/>
|
|
5
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.375 3C2.339 3 1.5 3.84 1.5 4.875v11.25C1.5 17.16 2.34 18 3.375 18H9.75v1.5H6A.75.75 0 0 0 6 21h12a.75.75 0 0 0 0-1.5h-3.75V18h6.375c1.035 0 1.875-.84 1.875-1.875V4.875C22.5 3.839 21.66 3 20.625 3H3.375Zm0 13.5h17.25a.375.375 0 0 0 .375-.375V4.875a.375.375 0 0 0-.375-.375H3.375A.375.375 0 0 0 3 4.875v11.25c0 .207.168.375.375.375Z"/>
|
|
6
|
+
</svg>
|