@sjvair/monitor-map 3.6.3 → 4.0.1

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 (156) hide show
  1. package/README.md +2 -2
  2. package/dist/lib/MonitorMapLayout.svelte +74 -36
  3. package/dist/lib/assets/icons/ozone/ozone-08-sunrise-haze.svg +1 -0
  4. package/dist/lib/assets/icons/pm25/pm25-02-particle-field.svg +1 -0
  5. package/dist/lib/collocation-sites/collocations-map-integration.svelte.d.ts +3 -0
  6. package/dist/lib/collocation-sites/collocations-map-integration.svelte.js +15 -1
  7. package/dist/lib/ev-stations/ev-stations-map-integration.svelte.js +27 -6
  8. package/dist/lib/hms/hms-fire-icon-manager.d.ts +8 -0
  9. package/dist/lib/hms/hms-fire-icon-manager.js +10 -1
  10. package/dist/lib/hms/hms-fire-map-integration.svelte.js +1 -1
  11. package/dist/lib/hms/hms-smoke-map-integration.svelte.d.ts +20 -0
  12. package/dist/lib/hms/hms-smoke-map-integration.svelte.js +22 -7
  13. package/dist/lib/index.d.ts +21 -7
  14. package/dist/lib/index.js +22 -7
  15. package/dist/lib/legend/Legend.svelte +40 -0
  16. package/dist/lib/legend/Legend.svelte.d.ts +7 -0
  17. package/dist/lib/legend/LegendBar.svelte +45 -0
  18. package/dist/lib/legend/LegendBar.svelte.d.ts +7 -0
  19. package/dist/lib/legend/legend-data.d.ts +40 -0
  20. package/dist/lib/legend/legend-data.js +65 -0
  21. package/dist/lib/map/MapShell.svelte +7 -6
  22. package/dist/lib/map/MapShell.svelte.d.ts +3 -1
  23. package/dist/lib/map/basemap.d.ts +14 -0
  24. package/dist/lib/map/basemap.js +10 -0
  25. package/dist/lib/map/integrations/map-geojson-integration.svelte.d.ts +6 -0
  26. package/dist/lib/map/integrations/map-geojson-integration.svelte.js +15 -2
  27. package/dist/lib/map/integrations/map-layer-integration.svelte.js +7 -3
  28. package/dist/lib/map/map-style-state.svelte.d.ts +13 -0
  29. package/dist/lib/map/map-style-state.svelte.js +35 -0
  30. package/dist/lib/map/map.svelte.d.ts +6 -0
  31. package/dist/lib/map/map.svelte.js +6 -0
  32. package/dist/lib/monitors/monitor-groups.d.ts +11 -0
  33. package/dist/lib/monitors/monitor-groups.js +7 -0
  34. package/dist/lib/monitors/monitor-utils.js +1 -3
  35. package/dist/lib/monitors/monitors-icon-manager.svelte.js +2 -5
  36. package/dist/lib/monitors/monitors-map-integration.svelte.d.ts +4 -4
  37. package/dist/lib/monitors/monitors-map-integration.svelte.js +45 -32
  38. package/dist/lib/monitors/monitors.svelte.d.ts +1 -0
  39. package/dist/lib/monitors/monitors.svelte.js +22 -0
  40. package/dist/lib/options/OptionsBar.svelte +96 -0
  41. package/dist/lib/options/OptionsBar.svelte.d.ts +10 -0
  42. package/dist/lib/options/OptionsGroup.svelte +12 -0
  43. package/dist/lib/options/OptionsGroup.svelte.d.ts +7 -0
  44. package/dist/lib/options/OptionsMenu.svelte +71 -0
  45. package/dist/lib/options/OptionsMenu.svelte.d.ts +15 -0
  46. package/dist/lib/options/group-state.d.ts +7 -0
  47. package/dist/lib/options/group-state.js +15 -0
  48. package/dist/lib/options/layout.d.ts +7 -0
  49. package/dist/lib/options/layout.js +9 -0
  50. package/dist/lib/options/map-option-defaults.d.ts +56 -0
  51. package/dist/lib/options/map-option-defaults.js +47 -0
  52. package/dist/lib/options/menus/LayersMenu.svelte +47 -0
  53. package/dist/lib/options/menus/LayersMenu.svelte.d.ts +3 -0
  54. package/dist/lib/options/menus/MonitorsMenu.svelte +68 -0
  55. package/dist/lib/options/menus/MonitorsMenu.svelte.d.ts +3 -0
  56. package/dist/lib/options/menus/OverlaysMenu.svelte +18 -0
  57. package/dist/lib/{MapLegend.svelte.d.ts → options/menus/OverlaysMenu.svelte.d.ts} +3 -3
  58. package/dist/lib/options/menus/PollutantMenu.svelte +89 -0
  59. package/dist/lib/options/menus/PollutantMenu.svelte.d.ts +3 -0
  60. package/dist/lib/options/menus/SettingsMenu.svelte +73 -0
  61. package/dist/lib/{hms/components/HMSFireLegend.svelte.d.ts → options/menus/SettingsMenu.svelte.d.ts} +3 -3
  62. package/dist/lib/options/options-state.svelte.d.ts +12 -0
  63. package/dist/lib/options/options-state.svelte.js +42 -0
  64. package/dist/lib/options/pollutant-param.d.ts +17 -0
  65. package/dist/lib/options/pollutant-param.js +14 -0
  66. package/dist/lib/options/reset-map-options.d.ts +2 -0
  67. package/dist/lib/options/reset-map-options.js +24 -0
  68. package/dist/lib/options/rows/CheckboxRow.svelte +51 -0
  69. package/dist/lib/options/rows/CheckboxRow.svelte.d.ts +13 -0
  70. package/dist/lib/options/rows/GroupRow.svelte +43 -0
  71. package/dist/lib/options/rows/GroupRow.svelte.d.ts +17 -0
  72. package/dist/lib/options/rows/MarkerIcon.svelte +10 -0
  73. package/dist/lib/options/rows/MarkerIcon.svelte.d.ts +8 -0
  74. package/dist/lib/options/rows/RadioRow.svelte +33 -0
  75. package/dist/lib/options/rows/RadioRow.svelte.d.ts +13 -0
  76. package/dist/lib/options/rows/SubmenuRow.svelte +22 -0
  77. package/dist/lib/options/rows/SubmenuRow.svelte.d.ts +11 -0
  78. package/dist/lib/search/Search.svelte +6 -6
  79. package/package.json +5 -3
  80. package/src/lib/MonitorMapLayout.svelte +74 -36
  81. package/src/lib/assets/icons/ozone/ozone-08-sunrise-haze.svg +1 -0
  82. package/src/lib/assets/icons/pm25/pm25-02-particle-field.svg +1 -0
  83. package/src/lib/collocation-sites/collocations-map-integration.svelte.ts +17 -1
  84. package/src/lib/ev-stations/ev-stations-map-integration.svelte.ts +26 -6
  85. package/src/lib/hms/hms-fire-icon-manager.ts +16 -2
  86. package/src/lib/hms/hms-fire-map-integration.svelte.ts +1 -1
  87. package/src/lib/hms/hms-smoke-map-integration.svelte.ts +25 -7
  88. package/src/lib/index.ts +31 -7
  89. package/src/lib/legend/Legend.svelte +40 -0
  90. package/src/lib/legend/LegendBar.svelte +45 -0
  91. package/src/lib/legend/legend-data.ts +101 -0
  92. package/src/lib/map/MapShell.svelte +7 -6
  93. package/src/lib/map/basemap.ts +24 -0
  94. package/src/lib/map/integrations/map-geojson-integration.svelte.ts +15 -2
  95. package/src/lib/map/integrations/map-layer-integration.svelte.ts +6 -3
  96. package/src/lib/map/map-style-state.svelte.ts +42 -0
  97. package/src/lib/map/map.svelte.ts +6 -0
  98. package/src/lib/monitors/monitor-groups.ts +20 -0
  99. package/src/lib/monitors/monitor-utils.ts +1 -5
  100. package/src/lib/monitors/monitors-icon-manager.svelte.ts +2 -8
  101. package/src/lib/monitors/monitors-map-integration.svelte.ts +39 -29
  102. package/src/lib/monitors/monitors.svelte.ts +22 -0
  103. package/src/lib/options/OptionsBar.svelte +96 -0
  104. package/src/lib/options/OptionsGroup.svelte +12 -0
  105. package/src/lib/options/OptionsMenu.svelte +71 -0
  106. package/src/lib/options/group-state.ts +16 -0
  107. package/src/lib/options/layout.ts +10 -0
  108. package/src/lib/options/map-option-defaults.ts +71 -0
  109. package/src/lib/options/menus/LayersMenu.svelte +47 -0
  110. package/src/lib/options/menus/MonitorsMenu.svelte +68 -0
  111. package/src/lib/options/menus/OverlaysMenu.svelte +18 -0
  112. package/src/lib/options/menus/PollutantMenu.svelte +89 -0
  113. package/src/lib/options/menus/SettingsMenu.svelte +73 -0
  114. package/src/lib/options/options-state.svelte.ts +48 -0
  115. package/src/lib/options/pollutant-param.ts +35 -0
  116. package/src/lib/options/reset-map-options.ts +28 -0
  117. package/src/lib/options/rows/CheckboxRow.svelte +51 -0
  118. package/src/lib/options/rows/GroupRow.svelte +43 -0
  119. package/src/lib/options/rows/MarkerIcon.svelte +10 -0
  120. package/src/lib/options/rows/RadioRow.svelte +33 -0
  121. package/src/lib/options/rows/SubmenuRow.svelte +22 -0
  122. package/src/lib/search/Search.svelte +6 -6
  123. package/dist/lib/MapLegend.svelte +0 -15
  124. package/dist/lib/collocation-sites/collocation-utils.d.ts +0 -3
  125. package/dist/lib/collocation-sites/collocation-utils.js +0 -30
  126. package/dist/lib/components/DisplayOption.svelte +0 -7
  127. package/dist/lib/components/DisplayOption.svelte.d.ts +0 -5
  128. package/dist/lib/components/MapLayersDisplayOptions.svelte +0 -42
  129. package/dist/lib/components/MapLayersDisplayOptions.svelte.d.ts +0 -18
  130. package/dist/lib/components/SegmentedControl.svelte +0 -52
  131. package/dist/lib/components/SegmentedControl.svelte.d.ts +0 -11
  132. package/dist/lib/components/ToggleSwitch.svelte +0 -93
  133. package/dist/lib/components/ToggleSwitch.svelte.d.ts +0 -9
  134. package/dist/lib/ev-stations/components/EvStationsDisplayOptions.svelte +0 -46
  135. package/dist/lib/ev-stations/components/EvStationsDisplayOptions.svelte.d.ts +0 -18
  136. package/dist/lib/hms/components/HMSFireLegend.svelte +0 -21
  137. package/dist/lib/map/MapStyleDisplayOptions.svelte +0 -61
  138. package/dist/lib/map/MapStyleDisplayOptions.svelte.d.ts +0 -3
  139. package/dist/lib/map/Menu.svelte +0 -65
  140. package/dist/lib/map/Menu.svelte.d.ts +0 -5
  141. package/dist/lib/monitors/components/MonitorMarkersLegend.svelte +0 -41
  142. package/dist/lib/monitors/components/MonitorMarkersLegend.svelte.d.ts +0 -3
  143. package/dist/lib/monitors/components/MonitorsDisplayOptions.svelte +0 -85
  144. package/dist/lib/monitors/components/MonitorsDisplayOptions.svelte.d.ts +0 -3
  145. package/src/lib/MapLegend.svelte +0 -15
  146. package/src/lib/collocation-sites/collocation-utils.ts +0 -41
  147. package/src/lib/components/DisplayOption.svelte +0 -7
  148. package/src/lib/components/MapLayersDisplayOptions.svelte +0 -42
  149. package/src/lib/components/SegmentedControl.svelte +0 -52
  150. package/src/lib/components/ToggleSwitch.svelte +0 -93
  151. package/src/lib/ev-stations/components/EvStationsDisplayOptions.svelte +0 -46
  152. package/src/lib/hms/components/HMSFireLegend.svelte +0 -21
  153. package/src/lib/map/MapStyleDisplayOptions.svelte +0 -61
  154. package/src/lib/map/Menu.svelte +0 -65
  155. package/src/lib/monitors/components/MonitorMarkersLegend.svelte +0 -41
  156. package/src/lib/monitors/components/MonitorsDisplayOptions.svelte +0 -85
@@ -1,93 +0,0 @@
1
- <script lang="ts">
2
- interface ToggleSwitchProps {
3
- id: string;
4
- label: string;
5
- reverse?: boolean;
6
- value: boolean;
7
- }
8
-
9
- let { id, label, reverse, value = $bindable() }: ToggleSwitchProps = $props();
10
- </script>
11
-
12
- <label
13
- for={id}
14
- class={[
15
- "flex cursor-pointer items-center justify-center gap-x-[0.25em] whitespace-nowrap select-none",
16
- { "flex-row-reverse": reverse }
17
- ]}
18
- >
19
- {label}
20
- <div class="switch">
21
- <input class="switch-input" type="checkbox" {id} name={id} bind:checked={value} />
22
- <span class="slider round"></span>
23
- </div>
24
- </label>
25
-
26
- <style>
27
- .switch {
28
- --animation-duration: 100ms;
29
- --switch-diameter: 1.625em;
30
- --switch-offset: 0.25em;
31
- --track-width: 3.75em;
32
- --track-height: 2.125em;
33
-
34
- font-size: 0.5em;
35
- position: relative;
36
- display: inline-block;
37
- width: var(--track-width);
38
- height: var(--track-height);
39
- transform: scale(0.8);
40
-
41
- .switch-input {
42
- opacity: 0;
43
- width: 0;
44
- height: 0;
45
-
46
- &:checked + .slider {
47
- background-color: #2196f3;
48
- }
49
-
50
- &:focus + .slider {
51
- box-shadow: 0 0 1px #2196f3;
52
- }
53
-
54
- &:checked + .slider:before {
55
- -webkit-transform: translateX(var(--switch-diameter));
56
- -ms-transform: translateX(var(--switch-diameter));
57
- transform: translateX(var(--switch-diameter));
58
- }
59
- }
60
-
61
- .slider {
62
- position: absolute;
63
- cursor: pointer;
64
- top: 0;
65
- left: 0;
66
- right: 0;
67
- bottom: 0;
68
- background-color: #ccc;
69
- -webkit-transition: var(--animation-duration);
70
- transition: var(--animation-duration);
71
-
72
- &:before {
73
- position: absolute;
74
- content: "";
75
- height: var(--switch-diameter);
76
- width: var(--switch-diameter);
77
- left: var(--switch-offset);
78
- bottom: var(--switch-offset);
79
- background-color: white;
80
- -webkit-transition: var(--animation-duration);
81
- transition: var(--animation-duration);
82
- }
83
- /* Rounded sliders */
84
- &.round {
85
- border-radius: var(--track-height);
86
- }
87
-
88
- &.round:before {
89
- border-radius: 50%;
90
- }
91
- }
92
- }
93
- </style>
@@ -1,46 +0,0 @@
1
- <script lang="ts">
2
- import DisplayOption from "$lib/components/DisplayOption.svelte";
3
- import ToggleSwitch from "$lib/components/ToggleSwitch.svelte";
4
- import { evStationsMapIntegration } from "../ev-stations-map-integration.svelte";
5
-
6
- const { displayOptions } = evStationsMapIntegration;
7
- </script>
8
-
9
- <DisplayOption>
10
- <p class="text-lg font-bold whitespace-nowrap underline">EV Stations</p>
11
- <div class="mb-2 w-full text-xs">
12
- <div class="w-fit">
13
- <ToggleSwitch
14
- id="ev-clusters"
15
- label="Marker Clusters"
16
- bind:value={evStationsMapIntegration.clustered}
17
- />
18
- </div>
19
- </div>
20
- <label for="ev-lvl2" class="flex cursor-pointer gap-1 whitespace-nowrap select-none">
21
- <input
22
- type="checkbox"
23
- id="ev-lvl2"
24
- bind:checked={evStationsMapIntegration.displayOptions.lvl2.value}
25
- />
26
- <img
27
- class="w-5"
28
- src={displayOptions.lvl2.icon!.image.src}
29
- alt={displayOptions.lvl2.icon!.image.alt}
30
- />
31
- Level 2
32
- </label>
33
- <label for="ev-lvl3" class="flex cursor-pointer gap-1 whitespace-nowrap select-none">
34
- <input
35
- type="checkbox"
36
- id="ev-lvl3"
37
- bind:checked={evStationsMapIntegration.displayOptions.lvl3.value}
38
- />
39
- <img
40
- class="w-5"
41
- src={displayOptions.lvl3.icon!.image.src}
42
- alt={displayOptions.lvl3.icon!.image.alt}
43
- />
44
- Level 3
45
- </label>
46
- </DisplayOption>
@@ -1,21 +0,0 @@
1
- <script lang="ts">
2
- import { hmsFireMapIntegration } from "../hms-fire-map-integration.svelte";
3
-
4
- const levels = ["<10", "10-49", "50-149", "150-349", "≥350"];
5
- </script>
6
-
7
- {#if hmsFireMapIntegration.enabled && hmsFireMapIntegration.features.length > 0}
8
- <div class="flex w-fit flex-col rounded bg-white p-1 shadow">
9
- <p class="text-center font-semibold whitespace-nowrap">Fire Points</p>
10
- <div class="flex flex-col">
11
- {#each hmsFireMapIntegration.icons.iter as [, icon], idx (idx)}
12
- <div class="flex items-center gap-1">
13
- <div class="flex size-9 items-center justify-center">
14
- <img src={icon.image.src} alt={icon.image.alt} />
15
- </div>
16
- <span>{levels[idx]} MW</span>
17
- </div>
18
- {/each}
19
- </div>
20
- </div>
21
- {/if}
@@ -1,61 +0,0 @@
1
- <script lang="ts">
2
- import { MapStyleVariant, ReferenceMapStyle } from "@maptiler/sdk";
3
- import { mapManager, DefaultMapStyle } from "./map.svelte";
4
- import { MAP_STYLE_OPTIONS } from "./utils";
5
- import { integrationsManager } from "./integrations/integrations-manager";
6
- import DisplayOption from "$lib/components/DisplayOption.svelte";
7
-
8
- let currentMapStyle: MapStyleVariant = DefaultMapStyle;
9
-
10
- let selectedReferenceStyle: ReferenceMapStyle = $state(DefaultMapStyle.getReferenceStyle());
11
- let selectedVariant: MapStyleVariant = $state(DefaultMapStyle);
12
-
13
- const selectedStyleVariants: Array<MapStyleVariant> = $derived(
14
- selectedReferenceStyle.getVariants()
15
- );
16
-
17
- $effect(() => {
18
- const referenceStyleChanged: boolean =
19
- selectedReferenceStyle !== currentMapStyle.getReferenceStyle();
20
- const variantChanged: boolean = selectedVariant !== currentMapStyle;
21
-
22
- if (mapManager.map !== null) {
23
- if (referenceStyleChanged && !variantChanged) {
24
- selectedVariant = selectedReferenceStyle.getDefaultVariant();
25
- } else if (variantChanged) {
26
- mapManager.map.once("style.load", async () => {
27
- currentMapStyle = selectedVariant;
28
- integrationsManager.refresh();
29
- });
30
-
31
- mapManager.map.setStyle(selectedVariant);
32
- }
33
- }
34
- });
35
- </script>
36
-
37
- <DisplayOption>
38
- <p class="text-lg font-bold underline">Map Styles</p>
39
- <label for="mapStyleType">Style</label>
40
- <select
41
- id="mapStyleType"
42
- name="selectedOption"
43
- bind:value={selectedReferenceStyle}
44
- class="rounded border p-1"
45
- >
46
- {#each MAP_STYLE_OPTIONS as mapStyle, idx (idx)}
47
- <option value={mapStyle}>{mapStyle.getName()}</option>
48
- {/each}
49
- </select>
50
- <label for="mapStyleVariant">Variant</label>
51
- <select
52
- id="mapStyleType"
53
- name="selectedOption"
54
- bind:value={selectedVariant}
55
- class="rounded border p-1"
56
- >
57
- {#each selectedStyleVariants as variant, idx (idx)}
58
- <option value={variant}>{variant.getName()}</option>
59
- {/each}
60
- </select>
61
- </DisplayOption>
@@ -1,65 +0,0 @@
1
- <script lang="ts">
2
- import type { Attachment } from "svelte/attachments";
3
- import { SlidersHorizontalIcon } from "@lucide/svelte";
4
-
5
- let { children } = $props();
6
- let isOpen: boolean = $state(false);
7
-
8
- function open() {
9
- if (!isOpen) {
10
- isOpen = true;
11
- }
12
- }
13
-
14
- function close() {
15
- if (isOpen) {
16
- isOpen = false;
17
- }
18
- }
19
-
20
- const hasTarget = (target: EventTarget | null): target is HTMLElement => target !== null;
21
-
22
- const displayOptionsToggle: Attachment<HTMLDivElement> = (target: HTMLDivElement) => {
23
- function toggle(e: PointerEvent) {
24
- if (hasTarget(e.target) && target.contains(e.target)) {
25
- return "trigger" in e.target.dataset ? close() : open();
26
- } else {
27
- close();
28
- }
29
- }
30
- document.body.addEventListener("click", toggle);
31
-
32
- return () => document.body.removeEventListener("click", toggle);
33
- };
34
- </script>
35
-
36
- <div
37
- {@attach displayOptionsToggle}
38
- data-trigger
39
- class:rounded-full={!isOpen}
40
- class:delay-100={!isOpen}
41
- class="relative top-0 left-0 flex items-center justify-center overflow-hidden rounded bg-white p-1 shadow transition-all duration-0 select-none"
42
- >
43
- <button
44
- class:w-0={isOpen}
45
- class:h-0={isOpen}
46
- class:opacity-0={isOpen}
47
- class="relative flex size-10 items-center justify-center transition-all"
48
- aria-label="Display Options"
49
- >
50
- <SlidersHorizontalIcon size="24" />
51
- </button>
52
- <div
53
- class={[
54
- "relative flex max-w-[90vw] items-center justify-center overflow-x-hidden overflow-y-scroll transition-all duration-250",
55
- isOpen ? "h-55 w-135" : "h-0 w-0"
56
- ]}
57
- >
58
- <div
59
- data-trigger
60
- class="xs:justify-between absolute top-0 left-0 flex h-fit w-full flex-wrap items-start gap-2 p-2 sm:justify-evenly md:justify-between md:gap-4"
61
- >
62
- {@render children?.()}
63
- </div>
64
- </div>
65
- </div>
@@ -1,41 +0,0 @@
1
- <script lang="ts">
2
- import { monitorsManager } from "../monitors.svelte";
3
-
4
- const label = $derived(monitorsManager.pollutant === "pm25" ? "PM 2.5" : "Ozone");
5
- const values = $derived(
6
- monitorsManager.pollutant === "pm25" ? [12, 35, 55, 150, 250] : [55, 71, 86, 106, 201]
7
- );
8
- </script>
9
-
10
- <div class="flex min-w-50 flex-col rounded bg-white px-[1.5em] py-[0.5em] shadow">
11
- <p class="text-center font-semibold whitespace-nowrap">
12
- {label} Concentration
13
- </p>
14
- <div class="map-legend-bar inline-block h-[1.5em]">&nbsp;</div>
15
- <div class="mb-[1.5em] flex">
16
- <div class="h-[0.5em] w-1/5 shrink-0 border-l border-black">
17
- <span class="relative top-[0.5em] right-[0.3em]">0</span>
18
- </div>
19
- {#each values as value, idx (idx)}
20
- <div class="h-[0.5em] w-1/5 shrink-0 border-l border-black last:relative last:right-px">
21
- <span class="relative top-[0.5em] {idx >= 3 ? 'right-[0.8em]' : 'right-[0.5em]'}"
22
- >{value}</span
23
- >
24
- </div>
25
- {/each}
26
- </div>
27
- </div>
28
-
29
- <style>
30
- .map-legend-bar {
31
- background: linear-gradient(
32
- 90deg,
33
- #00e400 0%,
34
- #ffff00 20%,
35
- #ff7e00 40%,
36
- #ff0000 60%,
37
- #8f3f97 80%,
38
- #7e0023 100%
39
- );
40
- }
41
- </style>
@@ -1,85 +0,0 @@
1
- <script lang="ts">
2
- import type { MonitorsMeta } from "@sjvair/sdk";
3
- import DisplayOption from "$lib/components/DisplayOption.svelte";
4
- import SegmentedControl from "$lib/components/SegmentedControl.svelte";
5
- import ToggleSwitch from "$lib/components/ToggleSwitch.svelte";
6
- import { monitorsManager } from "../monitors.svelte";
7
- import { monitorsMapIntegration } from "../monitors-map-integration.svelte";
8
-
9
- interface PollutantDisplayOptions {
10
- label: string;
11
- value: MonitorsMeta["default_pollutant"];
12
- }
13
-
14
- const pollutants: Array<PollutantDisplayOptions> = [
15
- {
16
- label: "PM 2.5",
17
- value: "pm25"
18
- },
19
- {
20
- label: "Ozone",
21
- value: "o3"
22
- }
23
- ];
24
-
25
- // "inside" is a location filter (indoor vs outdoor), not tied to a monitor type or
26
- // pollutant, so it's always shown, like "inactive".
27
- const uiOnlyDisplayOptions = new Set(["inactive", "inside"]);
28
-
29
- // "sjvair" (SJVAir non-FEM) isn't its own backend monitor type — it groups is_sjvair-flagged
30
- // purpleair devices with airgradient devices (see monitorsMapIntegration.filters/featuresByType),
31
- // so its visibility follows whichever of those two types supports the current pollutant.
32
- const sjvairUnderlyingTypes = ["purpleair", "airgradient"];
33
-
34
- function pollutantSupportedByType(type: string): boolean {
35
- const deviceMeta = monitorsManager.meta?.monitors[type];
36
- return (
37
- !!deviceMeta && !!monitorsManager.pollutant && monitorsManager.pollutant in deviceMeta.entries
38
- );
39
- }
40
-
41
- const monitorDisplayOptions = $derived.by(() => {
42
- return Object.entries(monitorsMapIntegration.displayOptions).filter(([key]) => {
43
- if (uiOnlyDisplayOptions.has(key)) return true;
44
- if (key === "sjvair") return sjvairUnderlyingTypes.some(pollutantSupportedByType);
45
- return pollutantSupportedByType(key);
46
- });
47
- });
48
-
49
- $effect(() => {
50
- monitorsManager.list = [];
51
- monitorsManager.latest = null;
52
- monitorsManager.update();
53
- });
54
- </script>
55
-
56
- <DisplayOption>
57
- <p class="text-lg font-bold underline">Air Monitors</p>
58
- <div class="mb-2 w-full text-xs">
59
- <div class="w-fit">
60
- <ToggleSwitch
61
- id="monitor-clusters"
62
- label="Marker Clusters"
63
- bind:value={monitorsMapIntegration.clustered}
64
- ></ToggleSwitch>
65
- </div>
66
- {#if monitorsManager.pollutant}
67
- <SegmentedControl
68
- segmentLabel="Pollutant:"
69
- options={pollutants}
70
- bind:group={monitorsManager.pollutant}
71
- />
72
- {/if}
73
- </div>
74
-
75
- {#each monitorDisplayOptions as [id, option] (option.label)}
76
- {@const inputId = `${id}-monitor-display-option`}
77
- <label for={inputId} class="flex cursor-pointer gap-1 whitespace-nowrap select-none">
78
- <input type="checkbox" id={inputId} name={option.label} bind:checked={option.value} />
79
- {#if option.icon}
80
- <img class="w-3" src={option.icon.image.src} alt={option.icon.image.alt} />
81
- {/if}
82
- {option.label}
83
- </label>
84
- {/each}
85
- </DisplayOption>