@sjvair/monitor-map 4.3.0 → 5.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +59 -138
- package/dist/lib/MonitorDetailPanel.svelte +23 -20
- package/dist/lib/MonitorMapLayout.svelte +147 -77
- package/dist/lib/components/DataBox.svelte +4 -1
- package/dist/lib/components/ui/range-calendar/range-calendar.svelte.d.ts +1 -1
- package/dist/lib/config.svelte.d.ts +7 -0
- package/dist/lib/config.svelte.js +10 -0
- package/dist/lib/core.d.ts +2 -2
- package/dist/lib/core.js +2 -1
- package/dist/lib/data-chart/DataChart.svelte +40 -25
- package/dist/lib/data-chart/DateRange.d.ts +13 -4
- package/dist/lib/data-chart/DateRange.js +50 -14
- package/dist/lib/data-chart/chart-utils.js +5 -7
- package/dist/lib/data-chart/level-colors.d.ts +3 -4
- package/dist/lib/data-chart/level-colors.js +7 -4
- package/dist/lib/data-chart/pacific-time.d.ts +9 -0
- package/dist/lib/data-chart/pacific-time.js +25 -0
- package/dist/lib/data-chart/tooltip.js +2 -2
- package/{src/lib/ev-stations/components/EvStationTooltip.svelte → dist/lib/ev-stations/EvPopup.svelte} +6 -5
- package/dist/lib/ev-stations/EvPopup.svelte.d.ts +7 -0
- package/dist/lib/ev-stations/ev-plugin.svelte.d.ts +14 -0
- package/dist/lib/ev-stations/ev-plugin.svelte.js +71 -0
- package/dist/lib/ev-stations/ev-station-icons.d.ts +1 -4
- package/dist/lib/ev-stations/ev-station-icons.js +1 -13
- package/dist/lib/ev-stations/ev-stations.d.ts +7 -0
- package/dist/lib/ev-stations/ev-stations.js +53 -0
- package/dist/lib/ev-stations/ev-store.svelte.d.ts +21 -0
- package/dist/lib/ev-stations/ev-store.svelte.js +83 -0
- package/dist/lib/ev-stations/station-popup.svelte.d.ts +14 -0
- package/dist/lib/ev-stations/station-popup.svelte.js +54 -0
- package/dist/lib/ev-stations/types.d.ts +0 -29
- package/dist/lib/ev-stations/zip-codes.d.ts +11 -0
- package/dist/lib/ev-stations/zip-codes.js +28 -16
- package/dist/lib/index.d.ts +8 -56
- package/dist/lib/index.js +7 -46
- package/dist/lib/legend/Legend.svelte +18 -19
- package/dist/lib/legend/Legend.svelte.d.ts +2 -2
- package/dist/lib/levels.d.ts +7 -0
- package/dist/lib/levels.js +19 -0
- package/dist/lib/map/MapShell.svelte +17 -24
- package/dist/lib/map/MapShell.svelte.d.ts +4 -4
- package/dist/lib/map/basemaps.d.ts +25 -0
- package/dist/lib/map/basemaps.js +66 -0
- package/dist/lib/map/live-map.svelte.d.ts +3 -0
- package/dist/lib/map/live-map.svelte.js +22 -0
- package/dist/lib/map/sync-plugins.svelte.d.ts +19 -0
- package/dist/lib/map/sync-plugins.svelte.js +52 -0
- package/dist/lib/monitors/components/MonitorSubscriptionManager.svelte +66 -61
- package/dist/lib/monitors/filtered-source.svelte.d.ts +9 -0
- package/dist/lib/monitors/filtered-source.svelte.js +28 -0
- package/dist/lib/monitors/monitors.svelte.d.ts +25 -35
- package/dist/lib/monitors/monitors.svelte.js +35 -218
- package/dist/lib/monitors/retry-load.d.ts +8 -0
- package/dist/lib/monitors/retry-load.js +11 -0
- package/dist/lib/monitors/types.d.ts +1 -41
- package/dist/lib/options/map-option-defaults.d.ts +25 -36
- package/dist/lib/options/map-option-defaults.js +12 -30
- package/dist/lib/options/map-options.svelte.d.ts +13 -0
- package/dist/lib/options/map-options.svelte.js +26 -0
- package/dist/lib/options/menus/LayersMenu.svelte +8 -20
- package/dist/lib/options/menus/LayersMenu.svelte.d.ts +17 -2
- package/dist/lib/options/menus/MonitorsMenu.svelte +34 -18
- package/dist/lib/options/menus/OverlaysMenu.svelte +2 -2
- package/dist/lib/options/menus/PollutantMenu.svelte +4 -9
- package/dist/lib/options/menus/SettingsMenu.svelte +32 -25
- package/dist/lib/options/menus/SettingsMenu.svelte.d.ts +5 -16
- package/dist/lib/options/plugin-order.d.ts +8 -0
- package/dist/lib/options/plugin-order.js +36 -0
- package/dist/lib/options/pollutant-param.d.ts +7 -5
- package/dist/lib/options/pollutant-param.js +9 -5
- package/dist/lib/options/row-icons.d.ts +8 -0
- package/dist/lib/options/row-icons.js +15 -0
- package/dist/lib/options/rows/MarkerIcon.svelte +5 -5
- package/dist/lib/options/rows/MarkerIcon.svelte.d.ts +1 -2
- package/dist/lib/search/Search.svelte +20 -33
- package/dist/lib/search/Search.svelte.d.ts +5 -1
- package/dist/lib/search/search-pin.svelte.d.ts +11 -0
- package/dist/lib/search/search-pin.svelte.js +28 -0
- package/dist/lib/search/service.d.ts +7 -2
- package/dist/lib/search/service.js +17 -10
- package/dist/lib/stores.svelte.d.ts +8 -0
- package/dist/lib/stores.svelte.js +9 -0
- package/dist/lib/wind/wind-plugin.d.ts +11 -0
- package/dist/lib/wind/wind-plugin.js +25 -0
- package/package.json +12 -10
- package/src/lib/MonitorDetailPanel.svelte +23 -20
- package/src/lib/MonitorMapLayout.svelte +147 -77
- package/src/lib/components/DataBox.svelte +4 -1
- package/src/lib/config.svelte.ts +16 -0
- package/src/lib/core.ts +2 -2
- package/src/lib/data-chart/DataChart.svelte +40 -25
- package/src/lib/data-chart/DateRange.ts +58 -15
- package/src/lib/data-chart/chart-utils.ts +6 -7
- package/src/lib/data-chart/level-colors.ts +8 -9
- package/src/lib/data-chart/pacific-time.ts +31 -0
- package/src/lib/data-chart/tooltip.ts +2 -2
- package/{dist/lib/ev-stations/components/EvStationTooltip.svelte → src/lib/ev-stations/EvPopup.svelte} +6 -5
- package/src/lib/ev-stations/ev-plugin.svelte.ts +86 -0
- package/src/lib/ev-stations/ev-station-icons.ts +1 -17
- package/src/lib/ev-stations/ev-stations.ts +72 -0
- package/src/lib/ev-stations/ev-store.svelte.ts +117 -0
- package/src/lib/ev-stations/station-popup.svelte.ts +64 -0
- package/src/lib/ev-stations/types.ts +0 -34
- package/src/lib/ev-stations/zip-codes.ts +29 -16
- package/src/lib/index.ts +8 -99
- package/src/lib/legend/Legend.svelte +18 -19
- package/src/lib/levels.ts +24 -0
- package/src/lib/map/MapShell.svelte +17 -24
- package/src/lib/map/basemaps.ts +76 -0
- package/src/lib/map/live-map.svelte.ts +24 -0
- package/src/lib/map/sync-plugins.svelte.ts +69 -0
- package/src/lib/monitors/components/MonitorSubscriptionManager.svelte +66 -61
- package/src/lib/monitors/filtered-source.svelte.ts +38 -0
- package/src/lib/monitors/monitors.svelte.ts +58 -261
- package/src/lib/monitors/retry-load.ts +14 -0
- package/src/lib/monitors/types.ts +1 -47
- package/src/lib/options/map-option-defaults.ts +30 -53
- package/src/lib/options/map-options.svelte.ts +30 -0
- package/src/lib/options/menus/LayersMenu.svelte +8 -20
- package/src/lib/options/menus/MonitorsMenu.svelte +34 -18
- package/src/lib/options/menus/OverlaysMenu.svelte +2 -2
- package/src/lib/options/menus/PollutantMenu.svelte +4 -9
- package/src/lib/options/menus/SettingsMenu.svelte +32 -25
- package/src/lib/options/plugin-order.ts +38 -0
- package/src/lib/options/pollutant-param.ts +14 -9
- package/src/lib/options/row-icons.ts +17 -0
- package/src/lib/options/rows/MarkerIcon.svelte +5 -5
- package/src/lib/search/Search.svelte +20 -33
- package/src/lib/search/search-pin.svelte.ts +35 -0
- package/src/lib/search/service.ts +34 -15
- package/src/lib/stores.svelte.ts +15 -0
- package/src/lib/wind/wind-plugin.ts +33 -0
- package/dist/lib/collocation-sites/CollocationTooltip.svelte +0 -98
- package/dist/lib/collocation-sites/CollocationTooltip.svelte.d.ts +0 -7
- package/dist/lib/collocation-sites/collocations-icon-manager.svelte.d.ts +0 -7
- package/dist/lib/collocation-sites/collocations-icon-manager.svelte.js +0 -18
- package/dist/lib/collocation-sites/collocations-map-integration.svelte.d.ts +0 -21
- package/dist/lib/collocation-sites/collocations-map-integration.svelte.js +0 -113
- package/dist/lib/collocation-sites/collocations.svelte.d.ts +0 -10
- package/dist/lib/collocation-sites/collocations.svelte.js +0 -21
- package/dist/lib/collocation-sites/types.d.ts +0 -8
- package/dist/lib/collocation-sites/types.js +0 -1
- package/dist/lib/ev-stations/components/EvStationClusterTooltip.svelte +0 -16
- package/dist/lib/ev-stations/components/EvStationClusterTooltip.svelte.d.ts +0 -7
- package/dist/lib/ev-stations/components/EvStationTooltip.svelte.d.ts +0 -7
- package/dist/lib/ev-stations/ev-stations-cluster-renderer.d.ts +0 -19
- package/dist/lib/ev-stations/ev-stations-cluster-renderer.js +0 -131
- package/dist/lib/ev-stations/ev-stations-map-integration.svelte.d.ts +0 -31
- package/dist/lib/ev-stations/ev-stations-map-integration.svelte.js +0 -226
- package/dist/lib/ev-stations/ev-stations.svelte.d.ts +0 -10
- package/dist/lib/ev-stations/ev-stations.svelte.js +0 -57
- package/dist/lib/hms/hms-fire-icon-manager.d.ts +0 -13
- package/dist/lib/hms/hms-fire-icon-manager.js +0 -39
- package/dist/lib/hms/hms-fire-map-integration.svelte.d.ts +0 -23
- package/dist/lib/hms/hms-fire-map-integration.svelte.js +0 -94
- package/dist/lib/hms/hms-smoke-map-integration.svelte.d.ts +0 -39
- package/dist/lib/hms/hms-smoke-map-integration.svelte.js +0 -87
- package/dist/lib/hms/hms.svelte.d.ts +0 -20
- package/dist/lib/hms/hms.svelte.js +0 -237
- package/dist/lib/legend/LegendBar.svelte +0 -45
- package/dist/lib/legend/LegendBar.svelte.d.ts +0 -7
- package/dist/lib/legend/legend-data.d.ts +0 -40
- package/dist/lib/legend/legend-data.js +0 -65
- package/dist/lib/map/Map.svelte +0 -13
- package/dist/lib/map/Map.svelte.d.ts +0 -8
- package/dist/lib/map/basemap.d.ts +0 -14
- package/dist/lib/map/basemap.js +0 -10
- package/dist/lib/map/icons.d.ts +0 -7
- package/dist/lib/map/icons.js +0 -33
- package/dist/lib/map/integrations/base-layer-seperator.d.ts +0 -9
- package/dist/lib/map/integrations/base-layer-seperator.js +0 -11
- package/dist/lib/map/integrations/click-manager.d.ts +0 -14
- package/dist/lib/map/integrations/click-manager.js +0 -52
- package/dist/lib/map/integrations/integrations-manager.d.ts +0 -8
- package/dist/lib/map/integrations/integrations-manager.js +0 -20
- package/dist/lib/map/integrations/map-display-option.svelte.d.ts +0 -7
- package/dist/lib/map/integrations/map-display-option.svelte.js +0 -10
- package/dist/lib/map/integrations/map-geojson-integration.svelte.d.ts +0 -32
- package/dist/lib/map/integrations/map-geojson-integration.svelte.js +0 -60
- package/dist/lib/map/integrations/map-icon-manager.d.ts +0 -15
- package/dist/lib/map/integrations/map-icon-manager.js +0 -52
- package/dist/lib/map/integrations/map-integration.svelte.d.ts +0 -6
- package/dist/lib/map/integrations/map-integration.svelte.js +0 -2
- package/dist/lib/map/integrations/map-layer-integration.svelte.d.ts +0 -11
- package/dist/lib/map/integrations/map-layer-integration.svelte.js +0 -40
- package/dist/lib/map/integrations/tooltip.svelte.d.ts +0 -36
- package/dist/lib/map/integrations/tooltip.svelte.js +0 -131
- package/dist/lib/map/integrations/types.d.ts +0 -14
- package/dist/lib/map/integrations/types.js +0 -1
- package/dist/lib/map/map-manager.svelte.d.ts +0 -20
- package/dist/lib/map/map-manager.svelte.js +0 -63
- package/dist/lib/map/map-style-state.svelte.d.ts +0 -23
- package/dist/lib/map/map-style-state.svelte.js +0 -86
- package/dist/lib/map/utils.d.ts +0 -7
- package/dist/lib/map/utils.js +0 -36
- package/dist/lib/monitors/components/MonitorClusterTooltip.svelte +0 -112
- package/dist/lib/monitors/components/MonitorClusterTooltip.svelte.d.ts +0 -7
- package/dist/lib/monitors/components/MonitorTooltip.svelte +0 -61
- package/dist/lib/monitors/components/MonitorTooltip.svelte.d.ts +0 -7
- package/dist/lib/monitors/monitor-utils.d.ts +0 -4
- package/dist/lib/monitors/monitor-utils.js +0 -41
- package/dist/lib/monitors/monitors-cluster-renderer.d.ts +0 -33
- package/dist/lib/monitors/monitors-cluster-renderer.js +0 -221
- package/dist/lib/monitors/monitors-icon-manager.svelte.d.ts +0 -15
- package/dist/lib/monitors/monitors-icon-manager.svelte.js +0 -78
- package/dist/lib/monitors/monitors-map-integration.svelte.d.ts +0 -43
- package/dist/lib/monitors/monitors-map-integration.svelte.js +0 -301
- package/dist/lib/options/reset-map-options.d.ts +0 -2
- package/dist/lib/options/reset-map-options.js +0 -24
- package/dist/lib/reactivity.svelte.d.ts +0 -0
- package/dist/lib/reactivity.svelte.js +0 -83
- package/dist/lib/wind/wind.svelte.d.ts +0 -10
- package/dist/lib/wind/wind.svelte.js +0 -13
- package/src/lib/collocation-sites/CollocationTooltip.svelte +0 -98
- package/src/lib/collocation-sites/collocations-icon-manager.svelte.ts +0 -21
- package/src/lib/collocation-sites/collocations-map-integration.svelte.ts +0 -136
- package/src/lib/collocation-sites/collocations.svelte.ts +0 -27
- package/src/lib/collocation-sites/types.ts +0 -10
- package/src/lib/ev-stations/components/EvStationClusterTooltip.svelte +0 -16
- package/src/lib/ev-stations/ev-stations-cluster-renderer.ts +0 -162
- package/src/lib/ev-stations/ev-stations-map-integration.svelte.ts +0 -248
- package/src/lib/ev-stations/ev-stations.svelte.ts +0 -84
- package/src/lib/hms/hms-fire-icon-manager.ts +0 -48
- package/src/lib/hms/hms-fire-map-integration.svelte.ts +0 -109
- package/src/lib/hms/hms-smoke-map-integration.svelte.ts +0 -105
- package/src/lib/hms/hms.svelte.ts +0 -270
- package/src/lib/legend/LegendBar.svelte +0 -45
- package/src/lib/legend/legend-data.ts +0 -101
- package/src/lib/map/Map.svelte +0 -13
- package/src/lib/map/basemap.ts +0 -24
- package/src/lib/map/icons.ts +0 -42
- package/src/lib/map/integrations/base-layer-seperator.ts +0 -17
- package/src/lib/map/integrations/click-manager.ts +0 -64
- package/src/lib/map/integrations/integrations-manager.ts +0 -25
- package/src/lib/map/integrations/map-display-option.svelte.ts +0 -13
- package/src/lib/map/integrations/map-geojson-integration.svelte.ts +0 -77
- package/src/lib/map/integrations/map-icon-manager.ts +0 -67
- package/src/lib/map/integrations/map-integration.svelte.ts +0 -8
- package/src/lib/map/integrations/map-layer-integration.svelte.ts +0 -49
- package/src/lib/map/integrations/tooltip.svelte.ts +0 -153
- package/src/lib/map/integrations/types.ts +0 -24
- package/src/lib/map/map-manager.svelte.ts +0 -83
- package/src/lib/map/map-style-state.svelte.ts +0 -94
- package/src/lib/map/utils.ts +0 -53
- package/src/lib/monitors/components/MonitorClusterTooltip.svelte +0 -112
- package/src/lib/monitors/components/MonitorTooltip.svelte +0 -61
- package/src/lib/monitors/monitor-utils.ts +0 -57
- package/src/lib/monitors/monitors-cluster-renderer.ts +0 -285
- package/src/lib/monitors/monitors-icon-manager.svelte.ts +0 -98
- package/src/lib/monitors/monitors-map-integration.svelte.ts +0 -318
- package/src/lib/options/reset-map-options.ts +0 -28
- package/src/lib/reactivity.svelte.ts +0 -82
- package/src/lib/wind/wind.svelte.ts +0 -20
package/src/lib/index.ts
CHANGED
|
@@ -15,9 +15,11 @@
|
|
|
15
15
|
* ```svelte
|
|
16
16
|
* <!-- app root -->
|
|
17
17
|
* <script>
|
|
18
|
-
* import { provideMonitorMapRouter } from "@sjvair/monitor-map";
|
|
18
|
+
* import { configureMonitorMap, provideMonitorMapRouter } from "@sjvair/monitor-map";
|
|
19
19
|
* import { route, navigate, p, isActive, Router } from "./router";
|
|
20
20
|
*
|
|
21
|
+
* // Once at startup, before the map or the EV layer is used. The library reads no keys itself.
|
|
22
|
+
* configureMonitorMap({ maptilerKey, nrelKey });
|
|
21
23
|
* provideMonitorMapRouter({ route, navigate, p, isActive, basePath: "/my-map" });
|
|
22
24
|
* </script>
|
|
23
25
|
*
|
|
@@ -25,111 +27,18 @@
|
|
|
25
27
|
* ```
|
|
26
28
|
*
|
|
27
29
|
* A host that must stay light at startup imports from the subpath entries instead:
|
|
28
|
-
* `provideMonitorMapRouter`/`monitorsManager` from
|
|
30
|
+
* `configureMonitorMap`/`provideMonitorMapRouter`/`monitorsManager` from
|
|
31
|
+
* "@sjvair/monitor-map/core" (no map), and
|
|
29
32
|
* `monitorMapRoutes` from "@sjvair/monitor-map/routes" (same tree, lazy layout and routes).
|
|
30
33
|
* `monitorMapRoutes` from this entry stays eager.
|
|
31
34
|
*/
|
|
32
35
|
export { monitorMapRoutes } from "./routes";
|
|
36
|
+
export { configureMonitorMap, monitorMapConfig, type MonitorMapConfig } from "./config.svelte.js";
|
|
33
37
|
export {
|
|
34
38
|
ROUTER_KEY,
|
|
35
39
|
provideMonitorMapRouter,
|
|
36
40
|
useMonitorMapRouter,
|
|
37
41
|
type MonitorMapRouterApi
|
|
38
42
|
} from "./router-context";
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
export { monitorsManager } from "./monitors/monitors.svelte";
|
|
42
|
-
export type { MonitorsManager, MonitorsInitOptions } from "./monitors/monitors.svelte";
|
|
43
|
-
export { collocationSitesManager } from "./collocation-sites/collocations.svelte";
|
|
44
|
-
export type { CollocationSitesManager } from "./collocation-sites/collocations.svelte";
|
|
45
|
-
export { evStationsManager } from "./ev-stations/ev-stations.svelte";
|
|
46
|
-
export type { EvStationsManager } from "./ev-stations/ev-stations.svelte";
|
|
47
|
-
export { hmsManager } from "./hms/hms.svelte";
|
|
48
|
-
export type { HMSManager } from "./hms/hms.svelte";
|
|
49
|
-
export { mapManager, DefaultMapStyle, initializeMap } from "./map/map-manager.svelte.js";
|
|
50
|
-
export type { MapManager } from "./map/map-manager.svelte.js";
|
|
51
|
-
|
|
52
|
-
// Map integrations
|
|
53
|
-
export {
|
|
54
|
-
monitorsMapIntegration,
|
|
55
|
-
MonitorsMapIntegration
|
|
56
|
-
} from "./monitors/monitors-map-integration.svelte";
|
|
57
|
-
export { collocationSitesMapIntegration } from "./collocation-sites/collocations-map-integration.svelte";
|
|
58
|
-
export { evStationsMapIntegration } from "./ev-stations/ev-stations-map-integration.svelte";
|
|
59
|
-
export { windMapIntegration } from "./wind/wind.svelte";
|
|
60
|
-
export { baseLayerSeperator } from "./map/integrations/base-layer-seperator";
|
|
61
|
-
export { hmsFireMapIntegration } from "./hms/hms-fire-map-integration.svelte";
|
|
62
|
-
export { hmsSmokeMapIntegration } from "./hms/hms-smoke-map-integration.svelte";
|
|
63
|
-
|
|
64
|
-
// Components
|
|
65
|
-
export { default as Map } from "./map/Map.svelte";
|
|
66
|
-
export { default as MapShell, type MapShellProps } from "./map/MapShell.svelte";
|
|
67
|
-
export {
|
|
68
|
-
default as LoadScreen,
|
|
69
|
-
loadScreenState,
|
|
70
|
-
enable as enableLoadScreen,
|
|
71
|
-
disable as disableLoadScreen
|
|
72
|
-
} from "./LoadScreen.svelte";
|
|
73
|
-
export type { LoadScreenState } from "./LoadScreen.svelte";
|
|
74
|
-
|
|
75
|
-
// Options toolbar / panel (compose these inside MapShell's `menu` snippet)
|
|
76
|
-
export { default as OptionsBar } from "./options/OptionsBar.svelte";
|
|
77
|
-
export { default as OptionsGroup } from "./options/OptionsGroup.svelte";
|
|
78
|
-
export { default as OptionsMenu } from "./options/OptionsMenu.svelte";
|
|
79
|
-
export { default as CheckboxRow } from "./options/rows/CheckboxRow.svelte";
|
|
80
|
-
export { default as RadioRow } from "./options/rows/RadioRow.svelte";
|
|
81
|
-
export { default as SubmenuRow } from "./options/rows/SubmenuRow.svelte";
|
|
82
|
-
export { default as GroupRow } from "./options/rows/GroupRow.svelte";
|
|
83
|
-
export { default as MarkerIcon } from "./options/rows/MarkerIcon.svelte";
|
|
84
|
-
export { default as PollutantMenu } from "./options/menus/PollutantMenu.svelte";
|
|
85
|
-
export { default as MonitorsMenu } from "./options/menus/MonitorsMenu.svelte";
|
|
86
|
-
export { default as LayersMenu } from "./options/menus/LayersMenu.svelte";
|
|
87
|
-
export { default as OverlaysMenu } from "./options/menus/OverlaysMenu.svelte";
|
|
88
|
-
export { default as SettingsMenu } from "./options/menus/SettingsMenu.svelte";
|
|
89
|
-
export { resetMapOptions } from "./options/reset-map-options";
|
|
90
|
-
export { mapStyleState } from "./map/map-style-state.svelte.js";
|
|
91
|
-
export type { MapStyleState } from "./map/map-style-state.svelte.js";
|
|
92
|
-
|
|
93
|
-
// Legend
|
|
94
|
-
export { default as Legend } from "./legend/Legend.svelte";
|
|
95
|
-
export { default as LegendBar } from "./legend/LegendBar.svelte";
|
|
96
|
-
export {
|
|
97
|
-
pollutantLegendSection,
|
|
98
|
-
fireSmokeLegendSections,
|
|
99
|
-
type LegendSection,
|
|
100
|
-
type LegendBarData,
|
|
101
|
-
type LegendCategory
|
|
102
|
-
} from "./legend/legend-data";
|
|
103
|
-
export { FIRE_LEGEND_CATEGORIES } from "./hms/hms-fire-icon-manager";
|
|
104
|
-
export { SMOKE_LEGEND } from "./hms/hms-smoke-map-integration.svelte";
|
|
105
|
-
|
|
106
|
-
// Integration base classes (extend these to add custom map features)
|
|
107
|
-
export { MapIntegration } from "./map/integrations/map-integration.svelte";
|
|
108
|
-
export { MapLayerIntegration } from "./map/integrations/map-layer-integration.svelte";
|
|
109
|
-
export { MapIconLayerIntegration as MapGeoJSONIntegration } from "./map/integrations/map-geojson-integration.svelte";
|
|
110
|
-
|
|
111
|
-
// Types
|
|
112
|
-
export type { SomeMapIntegration } from "./map/integrations/types";
|
|
113
|
-
export type { WindMapIntegration } from "./wind/wind.svelte";
|
|
114
|
-
export type { EvStationsMapIntegration } from "./ev-stations/ev-stations-map-integration.svelte";
|
|
115
|
-
export type { HMSFireMapIntegration } from "./hms/hms-fire-map-integration.svelte";
|
|
116
|
-
export type { HMSSmokeMapIntegration } from "./hms/hms-smoke-map-integration.svelte";
|
|
117
|
-
export type { HMSFireGroup } from "./hms/hms.svelte";
|
|
118
|
-
export type {
|
|
119
|
-
MonitorMapFeature,
|
|
120
|
-
MonitorMarkerProperties,
|
|
121
|
-
MonitorClusterMapFeature,
|
|
122
|
-
MonitorClusterMarkerProperties,
|
|
123
|
-
MonitorsDataSource,
|
|
124
|
-
MonitorsPollutant
|
|
125
|
-
} from "./monitors/types";
|
|
126
|
-
export type {
|
|
127
|
-
CollocationSiteMapFeature,
|
|
128
|
-
CollocationSiteMarkerProperties
|
|
129
|
-
} from "./collocation-sites/types";
|
|
130
|
-
export type {
|
|
131
|
-
EvStation,
|
|
132
|
-
EvStationMarkerProperties,
|
|
133
|
-
EvStationMapFeature,
|
|
134
|
-
EvStationClusterMapFeature
|
|
135
|
-
} from "./ev-stations/types";
|
|
43
|
+
export { monitorsManager } from "./monitors/monitors.svelte.js";
|
|
44
|
+
export type { MonitorsManager, MonitorsInitOptions } from "./monitors/monitors.svelte.js";
|
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { ChevronDownIcon, InfoIcon } from "@lucide/svelte";
|
|
3
|
-
import
|
|
4
|
-
import type { LegendSection } from "./legend-data";
|
|
3
|
+
import { Legend, legendSection, type MapContext } from "@sjvair/map-sdk";
|
|
5
4
|
|
|
6
|
-
let {
|
|
5
|
+
let { map }: { map: MapContext } = $props();
|
|
7
6
|
|
|
8
7
|
// Independent of which sections are active, so toggling a layer doesn't reset it.
|
|
9
8
|
let collapsed = $state(false);
|
|
9
|
+
|
|
10
|
+
// What map-sdk's Legend would list: a scale with levels, or a status line for a plugin that is
|
|
11
|
+
// loading or failing. The card is hidden while there is none.
|
|
12
|
+
const hasSections = $derived(
|
|
13
|
+
map.plugins.some((plugin) => {
|
|
14
|
+
const data = plugin.legend?.();
|
|
15
|
+
if (!data) return false;
|
|
16
|
+
if ("status" in data) return data.status.state !== "ready";
|
|
17
|
+
return legendSection(data, map.format) !== null;
|
|
18
|
+
})
|
|
19
|
+
);
|
|
10
20
|
</script>
|
|
11
21
|
|
|
12
|
-
{#if
|
|
22
|
+
{#if hasSections}
|
|
13
23
|
<div class="pointer-events-auto w-84 max-w-[calc(100vw-2rem)] rounded-md bg-white shadow">
|
|
14
24
|
<button
|
|
15
25
|
type="button"
|
|
@@ -21,20 +31,9 @@
|
|
|
21
31
|
<span class="flex-1 text-left">Legend</span>
|
|
22
32
|
<ChevronDownIcon size={18} class="transition-transform {collapsed ? '-rotate-90' : ''}" />
|
|
23
33
|
</button>
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
<p class="mb-2 text-center text-sm font-semibold">
|
|
29
|
-
{section.title}
|
|
30
|
-
{#if section.unit}
|
|
31
|
-
<span class="text-xs font-normal text-gray-500">({section.unit})</span>
|
|
32
|
-
{/if}
|
|
33
|
-
</p>
|
|
34
|
-
<LegendBar bar={section.bar} />
|
|
35
|
-
</div>
|
|
36
|
-
{/each}
|
|
37
|
-
</div>
|
|
38
|
-
{/if}
|
|
34
|
+
<!-- Kept mounted (hidden) when collapsed so the legend doesn't re-read the theme on expand. -->
|
|
35
|
+
<div class="border-t border-gray-200 px-4 py-3 {collapsed ? 'hidden' : ''}">
|
|
36
|
+
<Legend {map} order="top-first" framed={false} />
|
|
37
|
+
</div>
|
|
39
38
|
</div>
|
|
40
39
|
{/if}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { levelFor, NO_LEVEL, type Level, type Scale } from "@sjvair/map-sdk/data";
|
|
2
|
+
|
|
3
|
+
/** The color for a reading no level covers, as map-sdk draws an inactive monitor. */
|
|
4
|
+
export const NEUTRAL_LEVEL_COLOR = "#969696";
|
|
5
|
+
|
|
6
|
+
/** The scale level a reading falls in, or null when there is no scale or no level covers it. */
|
|
7
|
+
export function readingLevel(
|
|
8
|
+
value: string | number | null | undefined,
|
|
9
|
+
scale: Scale | null
|
|
10
|
+
): Level | null {
|
|
11
|
+
if (!scale) return null;
|
|
12
|
+
const level = levelFor(value, scale);
|
|
13
|
+
return level === NO_LEVEL ? null : level;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** A reading as the panel shows it: cut off to a whole number, or "–" when not a number. */
|
|
17
|
+
export function readingDisplay(value: string | number | null | undefined): string {
|
|
18
|
+
// Number("") and Number(null) are 0, not a reading.
|
|
19
|
+
if (value === null || value === undefined || (typeof value === "string" && !value.trim())) {
|
|
20
|
+
return "–";
|
|
21
|
+
}
|
|
22
|
+
const number = Math.trunc(Number(value));
|
|
23
|
+
return Number.isFinite(number) ? number.toString() : "–";
|
|
24
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<script lang="ts" module>
|
|
2
2
|
import type { Snippet } from "svelte";
|
|
3
|
-
import type {
|
|
3
|
+
import type { MapContext } from "@sjvair/map-sdk";
|
|
4
4
|
|
|
5
5
|
export interface MapShellProps {
|
|
6
|
-
/**
|
|
7
|
-
|
|
6
|
+
/** The map to show, from `createMap()` (the monitor map uses `createLiveMap()`). */
|
|
7
|
+
map: MapContext;
|
|
8
8
|
/**
|
|
9
9
|
* True once the caller's own data managers have finished their initial
|
|
10
|
-
* load. The shell hides the load screen once the map is
|
|
10
|
+
* load. The shell hides the load screen once the map is ready AND this
|
|
11
11
|
* is true.
|
|
12
12
|
*/
|
|
13
13
|
ready: boolean;
|
|
@@ -56,13 +56,12 @@
|
|
|
56
56
|
|
|
57
57
|
<script lang="ts">
|
|
58
58
|
import LoadScreen, { disable as disableLoadScreen } from "$lib/LoadScreen.svelte";
|
|
59
|
-
import
|
|
59
|
+
import { MapView } from "@sjvair/map-sdk";
|
|
60
60
|
import OptionsBar from "$lib/options/OptionsBar.svelte";
|
|
61
|
-
import { mapManager } from "$lib/map/map-manager.svelte.js";
|
|
62
61
|
import { useMonitorMapRouter } from "$lib/router-context";
|
|
63
62
|
|
|
64
63
|
let {
|
|
65
|
-
|
|
64
|
+
map,
|
|
66
65
|
ready,
|
|
67
66
|
loadError,
|
|
68
67
|
panelOpen,
|
|
@@ -76,28 +75,14 @@
|
|
|
76
75
|
}: MapShellProps = $props();
|
|
77
76
|
|
|
78
77
|
const basePath = providedBasePath ?? (routerEscapeHatch ? useMonitorMapRouter().basePath : "");
|
|
79
|
-
const TRANSITION_MS = 300;
|
|
80
78
|
|
|
81
79
|
$effect(() => {
|
|
82
|
-
//
|
|
83
|
-
|
|
84
|
-
// effect sees a non-null map, it's already safe to reveal — waiting for a
|
|
85
|
-
// further "idle" event here is unreliable since one may never fire again.
|
|
86
|
-
if (mapManager.map && ready) {
|
|
80
|
+
// `map.ready` is map-sdk's signal that the style loaded and the map went idle.
|
|
81
|
+
if (map.ready && ready) {
|
|
87
82
|
disableLoadScreen();
|
|
88
83
|
}
|
|
89
84
|
});
|
|
90
85
|
|
|
91
|
-
$effect(() => {
|
|
92
|
-
if (panelOpen) {
|
|
93
|
-
// Container width snapped to open; resize after layout settles
|
|
94
|
-
requestAnimationFrame(() => mapManager.map?.resize());
|
|
95
|
-
} else {
|
|
96
|
-
// Container width snaps back after the transform transition ends
|
|
97
|
-
setTimeout(() => mapManager.map?.resize(), TRANSITION_MS);
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
|
|
101
86
|
/**
|
|
102
87
|
* HACK: Fix for escaping sv-router and allowing navigation to other pages,
|
|
103
88
|
* as well as navigating back
|
|
@@ -131,7 +116,15 @@
|
|
|
131
116
|
<div class="relative flex h-full w-full flex-col md:flex-row">
|
|
132
117
|
<LoadScreen error={loadError} />
|
|
133
118
|
<div class="relative flex-1 overflow-hidden">
|
|
134
|
-
<
|
|
119
|
+
<MapView
|
|
120
|
+
{map}
|
|
121
|
+
label="Air quality monitor map"
|
|
122
|
+
controls="engine"
|
|
123
|
+
featureList={{ position: "top-right", reveal: "focus" }}
|
|
124
|
+
selectionBar={false}
|
|
125
|
+
tooltip="pointer"
|
|
126
|
+
class="h-full w-full"
|
|
127
|
+
/>
|
|
135
128
|
{@render overlays?.()}
|
|
136
129
|
{#if menu || search}
|
|
137
130
|
<OptionsBar {search}>{@render menu?.()}</OptionsBar>
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { MapStyle } from "@maptiler/sdk";
|
|
2
|
+
import type { ReferenceMapStyle } from "@maptiler/sdk";
|
|
3
|
+
import type { BasemapConfig } from "@sjvair/map-sdk";
|
|
4
|
+
|
|
5
|
+
/** Every MapTiler style at its highest `_V<n>` version, sorted by name. */
|
|
6
|
+
const BASEMAP_STYLES: ReferenceMapStyle[] = (() => {
|
|
7
|
+
const latest = new Map<string, { version: number; style: ReferenceMapStyle }>();
|
|
8
|
+
for (const style of Object.values(MapStyle) as ReferenceMapStyle[]) {
|
|
9
|
+
const id = style.getId();
|
|
10
|
+
const match = id.match(/^(.+?)_V(\d+)$/i);
|
|
11
|
+
const baseName = match ? match[1] : id;
|
|
12
|
+
const version = match ? parseInt(match[2], 10) : 0;
|
|
13
|
+
const existing = latest.get(baseName);
|
|
14
|
+
if (!existing || version > existing.version) {
|
|
15
|
+
latest.set(baseName, { version, style });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return Array.from(latest.values())
|
|
19
|
+
.map((e) => e.style)
|
|
20
|
+
.sort((a, b) => a.getName().localeCompare(b.getName()));
|
|
21
|
+
})();
|
|
22
|
+
|
|
23
|
+
/** The basemap the map opens on, and Reset selects: Streets v4's default variant. */
|
|
24
|
+
export function defaultBasemapId(): string {
|
|
25
|
+
return MapStyle.STREETS_V4.getDefaultVariant().getId();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The monitor map's basemaps: every MapTiler style's variants (style URLs, so map-sdk's fallback
|
|
30
|
+
* can match a failed style by URL), opening on Streets v4, with no layers removed.
|
|
31
|
+
*/
|
|
32
|
+
export function monitorMapBasemaps(): BasemapConfig {
|
|
33
|
+
const seen = new Set<string>();
|
|
34
|
+
const styles: BasemapConfig["styles"] = [];
|
|
35
|
+
for (const style of BASEMAP_STYLES) {
|
|
36
|
+
for (const variant of style.getVariants()) {
|
|
37
|
+
const id = variant.getId();
|
|
38
|
+
if (seen.has(id)) continue;
|
|
39
|
+
seen.add(id);
|
|
40
|
+
styles.push({ id, style: variant.getExpandedStyleURL() });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return { styles, defaultId: defaultBasemapId(), excludedLayers: [] };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface BasemapChoice {
|
|
47
|
+
name: string;
|
|
48
|
+
variants: Array<{ id: string; type: string; name: string }>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** The Basemap select's options (one per style name) and each one's Theme radios. */
|
|
52
|
+
export function basemapChoices(): BasemapChoice[] {
|
|
53
|
+
return BASEMAP_STYLES.map((style) => ({
|
|
54
|
+
name: style.getName(),
|
|
55
|
+
variants: style
|
|
56
|
+
.getVariants()
|
|
57
|
+
.map((variant) => ({ id: variant.getId(), type: variant.getType(), name: variant.getName() }))
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** The choice that has a variant with this id. */
|
|
62
|
+
export function choiceForId(id: string): BasemapChoice | undefined {
|
|
63
|
+
return basemapChoices().find((choice) => choice.variants.some((v) => v.id === id));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The variant to show after switching to the basemap named `toBaseName`: the same variant type
|
|
68
|
+
* (e.g. "DARK") as `currentId` when the new basemap offers it, otherwise its default.
|
|
69
|
+
*/
|
|
70
|
+
export function switchBasemap(currentId: string, toBaseName: string): string {
|
|
71
|
+
const target = BASEMAP_STYLES.find((style) => style.getName() === toBaseName);
|
|
72
|
+
if (!target) return currentId;
|
|
73
|
+
const type = choiceForId(currentId)?.variants.find((v) => v.id === currentId)?.type;
|
|
74
|
+
if (type && target.hasVariant(type)) return target.getVariant(type).getId();
|
|
75
|
+
return target.getDefaultVariant().getId();
|
|
76
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createMap, type MapContext } from "@sjvair/map-sdk";
|
|
2
|
+
import { monitorMapBasemaps } from "./basemaps";
|
|
3
|
+
import { monitorMapConfig } from "../config.svelte.js";
|
|
4
|
+
|
|
5
|
+
/** The San Joaquin Valley view the map opens on. */
|
|
6
|
+
const INITIAL_VIEW = {
|
|
7
|
+
center: [-119.7987626619462, 36.76272050981146] as [number, number],
|
|
8
|
+
zoom: 7,
|
|
9
|
+
bearing: 0,
|
|
10
|
+
pitch: 0
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/** The monitor map's map context: a globe over space on Streets v4, with every basemap to choose. */
|
|
14
|
+
export function createLiveMap(): MapContext {
|
|
15
|
+
return createMap({
|
|
16
|
+
config: {
|
|
17
|
+
maptilerKey: monitorMapConfig().maptilerKey,
|
|
18
|
+
initialView: INITIAL_VIEW,
|
|
19
|
+
projection: "globe",
|
|
20
|
+
space: { preset: "milkyway" },
|
|
21
|
+
basemaps: monitorMapBasemaps()
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { untrack } from "svelte";
|
|
2
|
+
import type { MapContext, MapPlugin, PluginOptions } from "@sjvair/map-sdk";
|
|
3
|
+
import { beforeId, DRAW_ORDER, type PluginKey } from "../options/plugin-order";
|
|
4
|
+
|
|
5
|
+
/** A plugin, or a plugin with the add options it needs (e.g. its selection mode). */
|
|
6
|
+
export type PluginEntry =
|
|
7
|
+
MapPlugin | { plugin: MapPlugin; options?: Omit<PluginOptions, "before"> };
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Builds a fresh plugin for each key (plugin objects are single-use). Called untracked. A key
|
|
11
|
+
* with no factory is never added, and never removed either: another `syncPlugins` call may own it.
|
|
12
|
+
*/
|
|
13
|
+
export type PluginFactories = Partial<Record<PluginKey, () => PluginEntry>>;
|
|
14
|
+
|
|
15
|
+
function entryOf(entry: PluginEntry): { plugin: MapPlugin; options?: PluginOptions } {
|
|
16
|
+
return "plugin" in entry ? entry : { plugin: entry };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Keeps `map`'s plugins in step with `wanted()`, in `DRAW_ORDER`: adds a wanted plugin below the
|
|
21
|
+
* first present plugin above it and removes one that is no longer wanted. A change to anything
|
|
22
|
+
* `deps()` reads removes and re-adds every present plugin of `factories` (e.g. `clustered`,
|
|
23
|
+
* which a plugin only takes when it is built). Call it during component setup.
|
|
24
|
+
*/
|
|
25
|
+
export function syncPlugins(
|
|
26
|
+
map: MapContext,
|
|
27
|
+
wanted: () => Set<PluginKey>,
|
|
28
|
+
factories: PluginFactories,
|
|
29
|
+
deps?: () => unknown
|
|
30
|
+
): void {
|
|
31
|
+
const keys = DRAW_ORDER.filter((key) => factories[key]);
|
|
32
|
+
// Bumped when a dep changes; separate from `wanted` so an option change that leaves the
|
|
33
|
+
// wanted set as it is never rebuilds anything.
|
|
34
|
+
let generation = $state(0);
|
|
35
|
+
let built = 0;
|
|
36
|
+
|
|
37
|
+
if (deps) {
|
|
38
|
+
let first = true;
|
|
39
|
+
$effect(() => {
|
|
40
|
+
deps();
|
|
41
|
+
if (first) first = false;
|
|
42
|
+
else untrack(() => generation++);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
$effect(() => {
|
|
47
|
+
const want = wanted();
|
|
48
|
+
const current = generation;
|
|
49
|
+
untrack(() => {
|
|
50
|
+
const rebuild = current !== built;
|
|
51
|
+
built = current;
|
|
52
|
+
// A scratch copy of the ids for this pass; nothing reads it reactively.
|
|
53
|
+
// eslint-disable-next-line svelte/prefer-svelte-reactivity
|
|
54
|
+
const present = new Set(map.plugins.map((p) => p.id));
|
|
55
|
+
for (const key of keys) {
|
|
56
|
+
if (present.has(key) && (rebuild || !want.has(key))) {
|
|
57
|
+
map.removePlugin(key);
|
|
58
|
+
present.delete(key);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
for (const key of keys) {
|
|
62
|
+
if (!want.has(key) || present.has(key)) continue;
|
|
63
|
+
const { plugin, options } = entryOf(factories[key]!());
|
|
64
|
+
map.addPlugin(plugin, { ...options, before: beforeId(key, present) });
|
|
65
|
+
present.add(key);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { BellCheckIcon, BellOffIcon, ChevronDownIcon } from "@lucide/svelte";
|
|
3
3
|
import { subscribe, unsubscribe } from "@sjvair/sdk/account";
|
|
4
|
-
import
|
|
4
|
+
import LoadError from "$lib/LoadError.svelte";
|
|
5
|
+
import { monitorsManager } from "$lib/monitors/monitors.svelte.js";
|
|
5
6
|
import { getApiToken, loadSubscriptionLevel } from "$lib/monitors/subscriptions";
|
|
6
7
|
|
|
7
8
|
interface MonitorSubscriptionManagerProps {
|
|
@@ -22,23 +23,21 @@
|
|
|
22
23
|
let saving = $state(false);
|
|
23
24
|
let subscribedLevel: string | null = $state(null);
|
|
24
25
|
|
|
26
|
+
// The alert rows, in this order, from the PM2.5 scale; a key the scale lacks is skipped.
|
|
25
27
|
const alertLevels = $derived.by(() => {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return monitorsManager.meta
|
|
29
|
-
.entryType("pm25")
|
|
30
|
-
.asIter.levels!.filter((level) =>
|
|
31
|
-
ALERT_LEVEL_NAMES.includes(level.name as (typeof ALERT_LEVEL_NAMES)[number])
|
|
32
|
-
);
|
|
33
|
-
} catch {
|
|
34
|
-
return [];
|
|
35
|
-
}
|
|
28
|
+
const levels = monitorsManager.meta?.entryType("pm25").scale?.levels ?? [];
|
|
29
|
+
return ALERT_LEVEL_NAMES.flatMap((key) => levels.find((level) => level.key === key) ?? []);
|
|
36
30
|
});
|
|
37
31
|
|
|
32
|
+
let loadError = $state(false);
|
|
33
|
+
let attempt = $state(0);
|
|
34
|
+
|
|
38
35
|
$effect(() => {
|
|
39
36
|
const id = monitorId;
|
|
37
|
+
void attempt;
|
|
40
38
|
open = false;
|
|
41
39
|
subscribedLevel = null;
|
|
40
|
+
loadError = false;
|
|
42
41
|
const controller = new AbortController();
|
|
43
42
|
const { signal } = controller;
|
|
44
43
|
loading = true;
|
|
@@ -47,7 +46,9 @@
|
|
|
47
46
|
if (!signal.aborted) subscribedLevel = level;
|
|
48
47
|
})
|
|
49
48
|
.catch((error) => {
|
|
50
|
-
if (
|
|
49
|
+
if (signal.aborted) return;
|
|
50
|
+
console.error("Could not load subscription status", error);
|
|
51
|
+
loadError = true;
|
|
51
52
|
})
|
|
52
53
|
.finally(() => {
|
|
53
54
|
if (!signal.aborted) loading = false;
|
|
@@ -78,53 +79,57 @@
|
|
|
78
79
|
}
|
|
79
80
|
</script>
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
<
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
82
|
+
{#if loadError}
|
|
83
|
+
<LoadError message="Couldn't load your alert settings." onretry={() => attempt++} />
|
|
84
|
+
{:else}
|
|
85
|
+
<div class="relative select-none">
|
|
86
|
+
<button
|
|
87
|
+
class={[
|
|
88
|
+
"flex w-full cursor-pointer items-center justify-center gap-2 rounded border px-3 py-1.5 text-sm font-semibold text-white",
|
|
89
|
+
subscribedLevel
|
|
90
|
+
? "border-green-700 bg-green-600 hover:bg-green-700"
|
|
91
|
+
: "border-blue-600 bg-blue-500 hover:bg-blue-600"
|
|
92
|
+
]}
|
|
93
|
+
disabled={loading}
|
|
94
|
+
onclick={() => (open = !open)}
|
|
95
|
+
>
|
|
96
|
+
{subscribedLevel ? "Manage Subscription" : "Subscribe to Alerts"}
|
|
97
|
+
<ChevronDownIcon
|
|
98
|
+
size={16}
|
|
99
|
+
class={["transition-transform duration-300", open ? "rotate-180" : ""]}
|
|
100
|
+
/>
|
|
101
|
+
</button>
|
|
98
102
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
</div>
|
|
103
|
+
{#if open}
|
|
104
|
+
<button aria-label="Close" class="fixed inset-0 z-10" onclick={() => (open = false)}></button>
|
|
105
|
+
<div class="absolute top-full left-0 z-20 mt-1 w-full overflow-hidden rounded shadow-lg">
|
|
106
|
+
{#if subscribedLevel}
|
|
107
|
+
<button
|
|
108
|
+
class="flex w-full cursor-pointer items-center justify-between rounded-t border border-black/30 px-4 py-2 text-sm hover:bg-[#F5F5F3]"
|
|
109
|
+
onclick={() => handleLevelClick(subscribedLevel)}
|
|
110
|
+
>
|
|
111
|
+
Unsubscribe
|
|
112
|
+
<BellOffIcon size={14} />
|
|
113
|
+
</button>
|
|
114
|
+
{/if}
|
|
115
|
+
{#each alertLevels as level (level.key)}
|
|
116
|
+
{@const isSubscribed = level.key === subscribedLevel}
|
|
117
|
+
<button
|
|
118
|
+
class={[
|
|
119
|
+
"flex w-full items-center justify-between px-4 py-2 text-sm text-white last:rounded-b",
|
|
120
|
+
!isSubscribed ? "cursor-pointer first:rounded-t hover:brightness-90" : ""
|
|
121
|
+
]}
|
|
122
|
+
style="background-color: {level.color}"
|
|
123
|
+
disabled={saving}
|
|
124
|
+
onclick={!isSubscribed ? () => handleLevelClick(level.key) : null}
|
|
125
|
+
>
|
|
126
|
+
<span>{level.label}</span>
|
|
127
|
+
{#if isSubscribed}
|
|
128
|
+
<BellCheckIcon size={14} />
|
|
129
|
+
{/if}
|
|
130
|
+
</button>
|
|
131
|
+
{/each}
|
|
132
|
+
</div>
|
|
133
|
+
{/if}
|
|
134
|
+
</div>
|
|
135
|
+
{/if}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { DataSource, MonitorFeatureProperties } from "@sjvair/map-sdk/data";
|
|
2
|
+
import type { MapOptions } from "../options/map-option-defaults";
|
|
3
|
+
|
|
4
|
+
type Options = Pick<MapOptions, "monitorTypes" | "inactive" | "inside">;
|
|
5
|
+
|
|
6
|
+
function shown(props: MonitorFeatureProperties, options: Options): boolean {
|
|
7
|
+
return (
|
|
8
|
+
options.monitorTypes[props.type] === true &&
|
|
9
|
+
(props.isActive || options.inactive) &&
|
|
10
|
+
(props.location !== "inside" || options.inside)
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* `source` with only the monitors the Monitors menu shows: types that are on, inactive and
|
|
16
|
+
* inside ones only when those are on. Clusters are built from these, so their averages follow.
|
|
17
|
+
*/
|
|
18
|
+
export function filteredMonitors(
|
|
19
|
+
source: DataSource<MonitorFeatureProperties>,
|
|
20
|
+
options: Options
|
|
21
|
+
): DataSource<MonitorFeatureProperties> {
|
|
22
|
+
const features = $derived.by(() => {
|
|
23
|
+
const all = source.features;
|
|
24
|
+
if (!all) return null;
|
|
25
|
+
return { ...all, features: all.features.filter((f) => shown(f.properties, options)) };
|
|
26
|
+
});
|
|
27
|
+
return {
|
|
28
|
+
get status() {
|
|
29
|
+
return source.status;
|
|
30
|
+
},
|
|
31
|
+
get features() {
|
|
32
|
+
return features;
|
|
33
|
+
},
|
|
34
|
+
get scale() {
|
|
35
|
+
return source.scale;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|