@sjvair/monitor-map 3.0.3 → 3.0.5
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/dist/lib/LoadScreen.svelte +68 -0
- package/dist/lib/LoadScreen.svelte.d.ts +25 -0
- package/dist/lib/MainMapView.svelte +1 -0
- package/dist/lib/MainMapView.svelte.d.ts +26 -0
- package/dist/lib/MapLegend.svelte +15 -0
- package/dist/lib/MapLegend.svelte.d.ts +18 -0
- package/dist/lib/MonitorDetailPanel.svelte +152 -0
- package/dist/lib/MonitorDetailPanel.svelte.d.ts +3 -0
- package/dist/lib/MonitorMapLayout.svelte +193 -0
- package/dist/lib/MonitorMapLayout.svelte.d.ts +7 -0
- package/dist/lib/actions.d.ts +3 -0
- package/dist/lib/actions.js +12 -8
- package/dist/lib/assets/icons/adjustment-horizontal.svg +3 -0
- package/dist/lib/assets/logos/airgradient-blue.svg +63 -0
- package/dist/lib/assets/logos/airnow-compact.jpg +0 -0
- package/dist/lib/assets/logos/carb-compact.jpg +0 -0
- package/dist/lib/assets/logos/purpleair-compact.png +0 -0
- package/dist/lib/assets/logos/sjvair-parts/sjvair-air.webp +0 -0
- package/dist/lib/assets/logos/sjvair-parts/sjvair-icon.webp +0 -0
- package/dist/lib/assets/logos/sjvair-parts/sjvair-sjv.webp +0 -0
- package/dist/lib/assets/logos/sjvair-white.svg +115 -0
- package/dist/lib/assets/logos/sjvair.svg +96 -0
- package/dist/lib/collocation-sites/CollocationTooltip.svelte +98 -0
- package/dist/lib/collocation-sites/CollocationTooltip.svelte.d.ts +7 -0
- package/dist/lib/collocation-sites/collocation-utils.d.ts +3 -0
- package/dist/lib/collocation-sites/collocation-utils.js +30 -0
- package/dist/lib/collocation-sites/collocations-icon-manager.svelte.d.ts +7 -0
- package/dist/lib/collocation-sites/collocations-icon-manager.svelte.js +17 -20
- package/dist/lib/collocation-sites/collocations-map-integration.svelte.d.ts +18 -0
- package/dist/lib/collocation-sites/collocations-map-integration.svelte.js +98 -83
- package/dist/lib/collocation-sites/collocations.svelte.d.ts +9 -0
- package/dist/lib/collocation-sites/collocations.svelte.js +17 -26
- package/dist/lib/collocation-sites/types.d.ts +8 -0
- package/dist/lib/collocation-sites/types.js +1 -0
- package/dist/lib/colors.d.ts +17 -0
- package/dist/lib/colors.js +29 -23
- package/dist/lib/components/DataBox.svelte +29 -0
- package/dist/lib/components/DataBox.svelte.d.ts +9 -0
- package/dist/lib/components/DisplayOption.svelte +7 -0
- package/dist/lib/components/DisplayOption.svelte.d.ts +5 -0
- package/dist/lib/components/MapLayersDisplayOptions.svelte +42 -0
- package/dist/lib/components/MapLayersDisplayOptions.svelte.d.ts +18 -0
- package/dist/lib/components/SegmentedControl.svelte +61 -0
- package/dist/lib/components/SegmentedControl.svelte.d.ts +11 -0
- package/dist/lib/components/ToggleSwitch.svelte +93 -0
- package/dist/lib/components/ToggleSwitch.svelte.d.ts +9 -0
- package/dist/lib/components/ui/button/button.svelte +89 -0
- package/dist/lib/components/ui/button/button.svelte.d.ts +70 -0
- package/dist/lib/components/ui/button/index.d.ts +2 -0
- package/dist/lib/components/ui/button/index.js +4 -0
- package/dist/lib/components/ui/range-calendar/index.d.ts +19 -0
- package/dist/lib/components/ui/range-calendar/index.js +21 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-caption.svelte +76 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-caption.svelte.d.ts +19 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-cell.svelte +19 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-cell.svelte.d.ts +4 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-day.svelte +36 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-day.svelte.d.ts +4 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-grid-body.svelte +7 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-grid-body.svelte.d.ts +4 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-grid-head.svelte +7 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-grid-head.svelte.d.ts +4 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-grid-row.svelte +12 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-grid-row.svelte.d.ts +4 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-grid.svelte +16 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-grid.svelte.d.ts +4 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-head-cell.svelte +19 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-head-cell.svelte.d.ts +4 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-header.svelte +19 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-header.svelte.d.ts +4 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-heading.svelte +16 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-heading.svelte.d.ts +4 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-month-select.svelte +44 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-month-select.svelte.d.ts +4 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-month.svelte +15 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-month.svelte.d.ts +5 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-months.svelte +19 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-months.svelte.d.ts +5 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-nav.svelte +19 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-nav.svelte.d.ts +5 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-next-button.svelte +36 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-next-button.svelte.d.ts +8 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-prev-button.svelte +36 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-prev-button.svelte.d.ts +8 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-year-select.svelte +43 -0
- package/dist/lib/components/ui/range-calendar/range-calendar-year-select.svelte.d.ts +4 -0
- package/dist/lib/components/ui/range-calendar/range-calendar.svelte +112 -0
- package/dist/lib/components/ui/range-calendar/range-calendar.svelte.d.ts +21 -0
- package/dist/lib/data-chart/DataChart.svelte +303 -0
- package/dist/lib/data-chart/DataChart.svelte.d.ts +7 -0
- package/dist/lib/data-chart/DateRange.d.ts +6 -0
- package/dist/lib/data-chart/DateRange.js +15 -14
- package/dist/lib/data-chart/chart-utils.d.ts +3 -0
- package/dist/lib/data-chart/chart-utils.js +157 -93
- package/dist/lib/data-chart/data-chart.svelte.d.ts +7 -0
- package/dist/lib/data-chart/data-chart.svelte.js +7 -28
- package/dist/lib/data-chart/requests.d.ts +3 -0
- package/dist/lib/data-chart/requests.js +36 -28
- package/dist/lib/data-chart/tooltip.d.ts +10 -0
- package/dist/lib/data-chart/tooltip.js +160 -98
- package/dist/lib/ev-stations/components/EvStationClusterTooltip.svelte +16 -0
- package/dist/lib/ev-stations/components/EvStationClusterTooltip.svelte.d.ts +7 -0
- package/dist/lib/ev-stations/components/EvStationTooltip.svelte +127 -0
- package/dist/lib/ev-stations/components/EvStationTooltip.svelte.d.ts +7 -0
- package/dist/lib/ev-stations/components/EvStationsDisplayOptions.svelte +46 -0
- package/dist/lib/ev-stations/components/EvStationsDisplayOptions.svelte.d.ts +18 -0
- package/dist/lib/ev-stations/data-maps.d.ts +5 -0
- package/dist/lib/ev-stations/data-maps.js +152 -4
- package/dist/lib/ev-stations/ev-station-icons.d.ts +16 -0
- package/dist/lib/ev-stations/ev-station-icons.js +21 -27
- package/dist/lib/ev-stations/ev-stations-cluster-renderer.d.ts +19 -0
- package/dist/lib/ev-stations/ev-stations-cluster-renderer.js +130 -117
- package/dist/lib/ev-stations/ev-stations-map-integration.svelte.d.ts +31 -0
- package/dist/lib/ev-stations/ev-stations-map-integration.svelte.js +206 -180
- package/dist/lib/ev-stations/ev-stations.svelte.d.ts +9 -0
- package/dist/lib/ev-stations/ev-stations.svelte.js +54 -32
- package/dist/lib/ev-stations/types.d.ts +53 -0
- package/dist/lib/ev-stations/types.js +1 -0
- package/dist/lib/ev-stations/zip-codes.d.ts +13 -0
- package/dist/lib/ev-stations/zip-codes.js +457 -135
- package/dist/lib/hms/components/HMSFireLegend.svelte +21 -0
- package/dist/lib/hms/components/HMSFireLegend.svelte.d.ts +18 -0
- package/dist/lib/hms/hms-fire-icon-manager.d.ts +5 -0
- package/dist/lib/hms/hms-fire-icon-manager.js +28 -37
- package/dist/lib/hms/hms-fire-map-integration.svelte.d.ts +23 -0
- package/dist/lib/hms/hms-fire-map-integration.svelte.js +94 -97
- package/dist/lib/hms/hms-smoke-map-integration.svelte.d.ts +19 -0
- package/dist/lib/hms/hms-smoke-map-integration.svelte.js +68 -84
- package/dist/lib/hms/hms.svelte.d.ts +19 -0
- package/dist/lib/hms/hms.svelte.js +225 -76
- package/dist/lib/index.d.ts +68 -0
- package/dist/lib/index.js +56 -21
- package/dist/lib/map/Map.svelte +13 -0
- package/dist/lib/map/Map.svelte.d.ts +8 -0
- package/dist/lib/map/MapStyleDisplayOptions.svelte +61 -0
- package/dist/lib/map/MapStyleDisplayOptions.svelte.d.ts +3 -0
- package/dist/lib/map/Menu.svelte +64 -0
- package/dist/lib/map/Menu.svelte.d.ts +5 -0
- package/dist/lib/map/icons.d.ts +7 -0
- package/dist/lib/map/icons.js +24 -22
- package/dist/lib/map/integrations/base-layer-seperator.d.ts +9 -0
- package/dist/lib/map/integrations/base-layer-seperator.js +11 -12
- package/dist/lib/map/integrations/click-manager.d.ts +14 -0
- package/dist/lib/map/integrations/click-manager.js +52 -33
- package/dist/lib/map/integrations/integrations-manager.d.ts +8 -0
- package/dist/lib/map/integrations/integrations-manager.js +20 -12
- package/dist/lib/map/integrations/map-display-option.svelte.d.ts +7 -0
- package/dist/lib/map/integrations/map-display-option.svelte.js +10 -18
- package/dist/lib/map/integrations/map-geojson-integration.svelte.d.ts +13 -0
- package/dist/lib/map/integrations/map-geojson-integration.svelte.js +21 -17
- package/dist/lib/map/integrations/map-icon-manager.d.ts +15 -0
- package/dist/lib/map/integrations/map-icon-manager.js +52 -46
- package/dist/lib/map/integrations/map-integration.svelte.d.ts +6 -0
- package/dist/lib/map/integrations/map-integration.svelte.js +2 -5
- package/dist/lib/map/integrations/map-layer-integration.svelte.d.ts +11 -0
- package/dist/lib/map/integrations/map-layer-integration.svelte.js +36 -23
- package/dist/lib/map/integrations/tooltip.svelte.d.ts +28 -0
- package/dist/lib/map/integrations/tooltip.svelte.js +120 -78
- package/dist/lib/map/integrations/types.d.ts +14 -0
- package/dist/lib/map/integrations/types.js +1 -0
- package/dist/lib/map/map.svelte.d.ts +14 -0
- package/dist/lib/map/map.svelte.js +48 -50
- package/dist/lib/map/utils.d.ts +7 -0
- package/dist/lib/map/utils.js +32 -29
- package/dist/lib/monitors/components/MonitorClusterTooltip.svelte +112 -0
- package/dist/lib/monitors/components/MonitorClusterTooltip.svelte.d.ts +7 -0
- package/dist/lib/monitors/components/MonitorMarkersLegend.svelte +41 -0
- package/dist/lib/monitors/components/MonitorMarkersLegend.svelte.d.ts +3 -0
- package/dist/lib/monitors/components/MonitorSubscriptionManager.svelte +128 -0
- package/dist/lib/monitors/components/MonitorSubscriptionManager.svelte.d.ts +6 -0
- package/dist/lib/monitors/components/MonitorTooltip.svelte +61 -0
- package/dist/lib/monitors/components/MonitorTooltip.svelte.d.ts +7 -0
- package/dist/lib/monitors/components/MonitorWidgetModal.svelte +100 -0
- package/dist/lib/monitors/components/MonitorWidgetModal.svelte.d.ts +6 -0
- package/dist/lib/monitors/components/MonitorsDisplayOptions.svelte +79 -0
- package/dist/lib/monitors/components/MonitorsDisplayOptions.svelte.d.ts +3 -0
- package/dist/lib/monitors/monitor-utils.d.ts +4 -0
- package/dist/lib/monitors/monitor-utils.js +33 -23
- package/dist/lib/monitors/monitors-cluster-renderer.d.ts +33 -0
- package/dist/lib/monitors/monitors-cluster-renderer.js +218 -209
- package/dist/lib/monitors/monitors-icon-manager.svelte.d.ts +13 -0
- package/dist/lib/monitors/monitors-icon-manager.svelte.js +75 -70
- package/dist/lib/monitors/monitors-map-integration.svelte.d.ts +40 -0
- package/dist/lib/monitors/monitors-map-integration.svelte.js +278 -270
- package/dist/lib/monitors/monitors.svelte.d.ts +16 -0
- package/dist/lib/monitors/monitors.svelte.js +38 -63
- package/dist/lib/monitors/types.d.ts +26 -0
- package/dist/lib/monitors/types.js +1 -0
- package/dist/lib/reactivity.svelte.d.ts +0 -0
- package/dist/lib/reactivity.svelte.js +83 -0
- package/dist/lib/router-context.d.ts +27 -0
- package/dist/lib/router-context.js +11 -11
- package/dist/lib/routes.d.ts +2 -0
- package/dist/lib/routes.js +10 -9
- package/dist/lib/search/Search.svelte +189 -0
- package/dist/lib/search/Search.svelte.d.ts +3 -0
- package/dist/lib/search/service.d.ts +17 -0
- package/dist/lib/search/service.js +75 -85
- package/dist/lib/utils.d.ts +13 -0
- package/dist/lib/utils.js +10 -12
- package/dist/lib/weather.d.ts +1 -0
- package/dist/lib/weather.js +11 -7
- package/dist/lib/wind/wind.svelte.d.ts +10 -0
- package/dist/lib/wind/wind.svelte.js +13 -21
- package/package.json +9 -7
- package/src/lib/LoadScreen.svelte +3 -3
- package/src/lib/hms/components/HMSFireLegend.svelte +1 -1
- package/src/lib/hms/hms.svelte.ts +8 -9
- package/src/lib/index.ts +18 -0
- package/src/lib/routes.ts +6 -1
- package/src/lib/utils.ts +1 -1
- package/dist/lib/LoadScreen.js +0 -73
- package/dist/lib/MainMapView.js +0 -7
- package/dist/lib/MapLegend.js +0 -13
- package/dist/lib/MonitorDetailPanel.js +0 -169
- package/dist/lib/MonitorMapLayout.js +0 -91
- package/dist/lib/_virtual/_rolldown/runtime.js +0 -11
- package/dist/lib/assets/logos/airgradient-blue.js +0 -4
- package/dist/lib/assets/logos/airnow-compact.js +0 -4
- package/dist/lib/assets/logos/carb-compact.js +0 -4
- package/dist/lib/assets/logos/purpleair-compact.js +0 -4
- package/dist/lib/assets/logos/sjvair.js +0 -4
- package/dist/lib/collocation-sites/CollocationTooltip.js +0 -105
- package/dist/lib/components/DataBox.js +0 -30
- package/dist/lib/components/DisplayOption.js +0 -10
- package/dist/lib/components/MapLayersDisplayOptions.js +0 -87
- package/dist/lib/components/SegmentedControl.js +0 -37
- package/dist/lib/components/ToggleSwitch.js +0 -17
- package/dist/lib/components/ui/button/button.js +0 -34
- package/dist/lib/components/ui/range-calendar/range-calendar-caption.js +0 -82
- package/dist/lib/components/ui/range-calendar/range-calendar-cell.js +0 -35
- package/dist/lib/components/ui/range-calendar/range-calendar-day.js +0 -35
- package/dist/lib/components/ui/range-calendar/range-calendar-grid-body.js +0 -27
- package/dist/lib/components/ui/range-calendar/range-calendar-grid-head.js +0 -27
- package/dist/lib/components/ui/range-calendar/range-calendar-grid-row.js +0 -35
- package/dist/lib/components/ui/range-calendar/range-calendar-grid.js +0 -35
- package/dist/lib/components/ui/range-calendar/range-calendar-head-cell.js +0 -35
- package/dist/lib/components/ui/range-calendar/range-calendar-header.js +0 -35
- package/dist/lib/components/ui/range-calendar/range-calendar-month-select.js +0 -61
- package/dist/lib/components/ui/range-calendar/range-calendar-month.js +0 -25
- package/dist/lib/components/ui/range-calendar/range-calendar-months.js +0 -25
- package/dist/lib/components/ui/range-calendar/range-calendar-nav.js +0 -25
- package/dist/lib/components/ui/range-calendar/range-calendar-next-button.js +0 -58
- package/dist/lib/components/ui/range-calendar/range-calendar-prev-button.js +0 -58
- package/dist/lib/components/ui/range-calendar/range-calendar-year-select.js +0 -59
- package/dist/lib/components/ui/range-calendar/range-calendar.js +0 -272
- package/dist/lib/data-chart/DataChart.js +0 -142
- package/dist/lib/ev-stations/components/EvStationClusterTooltip.js +0 -16
- package/dist/lib/ev-stations/components/EvStationTooltip.js +0 -120
- package/dist/lib/ev-stations/components/EvStationsDisplayOptions.js +0 -41
- package/dist/lib/hms/components/HMSFireLegend.js +0 -35
- package/dist/lib/map/Map.js +0 -14
- package/dist/lib/map/MapStyleDisplayOptions.js +0 -43
- package/dist/lib/map/Menu.js +0 -44
- package/dist/lib/monitors/components/MonitorClusterTooltip.js +0 -83
- package/dist/lib/monitors/components/MonitorMarkersLegend.js +0 -35
- package/dist/lib/monitors/components/MonitorSubscriptionManager.js +0 -104
- package/dist/lib/monitors/components/MonitorTooltip.js +0 -59
- package/dist/lib/monitors/components/MonitorWidgetModal.js +0 -40
- package/dist/lib/monitors/components/MonitorsDisplayOptions.js +0 -76
- package/dist/lib/search/Search.js +0 -124
- package/dist/lib/sjvair-air.avif +0 -0
- package/dist/lib/sjvair-air.png +0 -0
- package/dist/lib/sjvair-air.webp +0 -0
- package/dist/lib/sjvair-air2.avif +0 -0
- package/dist/lib/sjvair-air2.png +0 -0
- package/dist/lib/sjvair-air2.webp +0 -0
- package/dist/lib/sjvair-icon.avif +0 -0
- package/dist/lib/sjvair-icon.png +0 -0
- package/dist/lib/sjvair-icon.webp +0 -0
- package/dist/lib/sjvair-icon2.avif +0 -0
- package/dist/lib/sjvair-icon2.png +0 -0
- package/dist/lib/sjvair-icon2.webp +0 -0
- package/dist/lib/sjvair-sjv.avif +0 -0
- package/dist/lib/sjvair-sjv.png +0 -0
- package/dist/lib/sjvair-sjv.webp +0 -0
- package/dist/lib/sjvair-sjv2.avif +0 -0
- package/dist/lib/sjvair-sjv2.png +0 -0
- package/dist/lib/sjvair-sjv2.webp +0 -0
|
@@ -1,64 +1,39 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { XMap
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
get meta() {
|
|
31
|
-
return e.get(this.#r);
|
|
32
|
-
}
|
|
33
|
-
set meta(t) {
|
|
34
|
-
e.set(this.#r, t, !0);
|
|
35
|
-
}
|
|
36
|
-
#i = e.state(null);
|
|
37
|
-
get pollutant() {
|
|
38
|
-
return e.get(this.#i);
|
|
39
|
-
}
|
|
40
|
-
set pollutant(t) {
|
|
41
|
-
e.set(this.#i, t, !0);
|
|
42
|
-
}
|
|
43
|
-
#a = e.derived(() => this.meta?.entryType(this.pollutant ?? this.meta.default_pollutant).asIter.levels || null);
|
|
44
|
-
get levels() {
|
|
45
|
-
return e.get(this.#a);
|
|
46
|
-
}
|
|
47
|
-
set levels(t) {
|
|
48
|
-
e.set(this.#a, t);
|
|
49
|
-
}
|
|
50
|
-
async init(e) {
|
|
51
|
-
this.initialized ||= ([this.list, this.meta] = await Promise.all([n(), i()]), this.pollutant = e === "pm25" || e === "o3" ? e : this.meta.default_pollutant, this.latest = await s(this.pollutant), this.autoUpdate.start(), !0);
|
|
52
|
-
}
|
|
53
|
-
async update() {
|
|
54
|
-
this.initialized && ([this.list, this.latest] = await Promise.all([n(), s(this.pollutant || this.meta?.default_pollutant || "pm25")]));
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
async function s(e) {
|
|
58
|
-
let n = await r(e), i = new t();
|
|
59
|
-
for (let e of n) i.set(e.id, e);
|
|
60
|
-
return i;
|
|
1
|
+
import { getMonitors, getMonitorsLatest, getMonitorsMeta } from "@sjvair/sdk";
|
|
2
|
+
import { XMap } from "@tstk/builtin-extensions";
|
|
3
|
+
import { Interval } from "@tstk/utils";
|
|
4
|
+
class MonitorsManager {
|
|
5
|
+
autoUpdate = new Interval(async () => await this.update(), 2 * 60 * 1000);
|
|
6
|
+
initialized = $state(false);
|
|
7
|
+
latest = $state(null);
|
|
8
|
+
list = $state(null);
|
|
9
|
+
meta = $state(null);
|
|
10
|
+
pollutant = $state(null);
|
|
11
|
+
levels = $derived(this.meta?.entryType(this.pollutant ?? this.meta.default_pollutant).asIter.levels || null);
|
|
12
|
+
async init(urlPollutant) {
|
|
13
|
+
if (this.initialized)
|
|
14
|
+
return;
|
|
15
|
+
[this.list, this.meta] = await Promise.all([getMonitors(), getMonitorsMeta()]);
|
|
16
|
+
this.pollutant =
|
|
17
|
+
urlPollutant === "pm25" || urlPollutant === "o3" ? urlPollutant : this.meta.default_pollutant;
|
|
18
|
+
this.latest = await getMonitorsLatestMap(this.pollutant);
|
|
19
|
+
this.autoUpdate.start();
|
|
20
|
+
this.initialized = true;
|
|
21
|
+
}
|
|
22
|
+
async update() {
|
|
23
|
+
if (!this.initialized)
|
|
24
|
+
return;
|
|
25
|
+
[this.list, this.latest] = await Promise.all([
|
|
26
|
+
getMonitors(),
|
|
27
|
+
getMonitorsLatestMap(this.pollutant || this.meta?.default_pollutant || "pm25")
|
|
28
|
+
]);
|
|
29
|
+
}
|
|
61
30
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
31
|
+
async function getMonitorsLatestMap(pollutant) {
|
|
32
|
+
const monitors = await getMonitorsLatest(pollutant);
|
|
33
|
+
const latest = new XMap();
|
|
34
|
+
for (const monitor of monitors) {
|
|
35
|
+
latest.set(monitor.id, monitor);
|
|
36
|
+
}
|
|
37
|
+
return latest;
|
|
38
|
+
}
|
|
39
|
+
export const monitorsManager = new MonitorsManager();
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Feature, Geometry } from "geojson";
|
|
2
|
+
import type { MonitorType } from "@sjvair/sdk";
|
|
3
|
+
import type { MapGeoJSONFeature } from "@maptiler/sdk";
|
|
4
|
+
export type MonitorMapFeature = Feature<Geometry, MonitorMarkerProperties>;
|
|
5
|
+
export interface MonitorClusterMapFeature extends MapGeoJSONFeature {
|
|
6
|
+
properties: MonitorClusterMarkerProperties;
|
|
7
|
+
}
|
|
8
|
+
export interface MonitorMarkerProperties {
|
|
9
|
+
icon: string;
|
|
10
|
+
id: string;
|
|
11
|
+
is_active: boolean;
|
|
12
|
+
is_sjvair?: boolean;
|
|
13
|
+
location: string;
|
|
14
|
+
name: string;
|
|
15
|
+
order: number;
|
|
16
|
+
type: MonitorType;
|
|
17
|
+
value: string;
|
|
18
|
+
}
|
|
19
|
+
export interface MonitorClusterMarkerProperties {
|
|
20
|
+
cluster: true;
|
|
21
|
+
cluster_id: number;
|
|
22
|
+
point_count: number;
|
|
23
|
+
point_count_abbreviated: string | number;
|
|
24
|
+
sumValues: number;
|
|
25
|
+
countValues: number;
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
File without changes
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
//class ReactiveState<T> {
|
|
3
|
+
// private internalValue?: T = $state();
|
|
4
|
+
//
|
|
5
|
+
// constructor(initialValue?: T) {
|
|
6
|
+
// this.internalValue = initialValue;
|
|
7
|
+
// }
|
|
8
|
+
// get value(): T | undefined {
|
|
9
|
+
// return this.internalValue;
|
|
10
|
+
// }
|
|
11
|
+
//
|
|
12
|
+
// set value(newValue: T) {
|
|
13
|
+
// // Perform any validation or side effects here
|
|
14
|
+
// this.internalValue = newValue; // Update the reactive state
|
|
15
|
+
// }
|
|
16
|
+
//}
|
|
17
|
+
//
|
|
18
|
+
//class ShallowReactiveState<T> {
|
|
19
|
+
// private internalValue?: T = $state.raw();
|
|
20
|
+
//
|
|
21
|
+
// constructor(initialValue?: T) {
|
|
22
|
+
// this.internalValue = initialValue;
|
|
23
|
+
// }
|
|
24
|
+
// get value(): T | undefined {
|
|
25
|
+
// return this.internalValue;
|
|
26
|
+
// }
|
|
27
|
+
//
|
|
28
|
+
// set value(newValue: T) {
|
|
29
|
+
// // Perform any validation or side effects here
|
|
30
|
+
// this.internalValue = newValue; // Update the reactive state
|
|
31
|
+
// }
|
|
32
|
+
//}
|
|
33
|
+
//
|
|
34
|
+
//
|
|
35
|
+
//class DerivedReactiveState<T> {
|
|
36
|
+
// private internalValue?: T;
|
|
37
|
+
//
|
|
38
|
+
// constructor(expression: () => T) {
|
|
39
|
+
// this.internalValue = $derived.by(expression);
|
|
40
|
+
// }
|
|
41
|
+
// get value(): T | undefined {
|
|
42
|
+
// return this.internalValue;
|
|
43
|
+
// }
|
|
44
|
+
// set value(newValue: T) {
|
|
45
|
+
// this.internalValue = newValue;
|
|
46
|
+
// }
|
|
47
|
+
//}
|
|
48
|
+
//
|
|
49
|
+
//export function Derived<V>(value: () => V) {
|
|
50
|
+
// let ref: DerivedReactiveState<V> = new DerivedReactiveState<V>(value);
|
|
51
|
+
// return function <V, T = unknown>(
|
|
52
|
+
// _target: ClassAccessorDecoratorTarget<T, V>,
|
|
53
|
+
// _ctx: ClassAccessorDecoratorContext,
|
|
54
|
+
// ): ClassAccessorDecoratorResult<T, V> {
|
|
55
|
+
//
|
|
56
|
+
// return {
|
|
57
|
+
// get() {
|
|
58
|
+
// return ref.value as V;
|
|
59
|
+
// },
|
|
60
|
+
// };
|
|
61
|
+
// }
|
|
62
|
+
//}
|
|
63
|
+
//export function Reactive(shallow?: boolean) {
|
|
64
|
+
// return function <V, T = unknown>(
|
|
65
|
+
// _target: ClassAccessorDecoratorTarget<T, V>,
|
|
66
|
+
// _ctx: ClassAccessorDecoratorContext,
|
|
67
|
+
// ): ClassAccessorDecoratorResult<T, V> {
|
|
68
|
+
// let ref = shallow ? new ShallowReactiveState<V>() : new ReactiveState<V>();
|
|
69
|
+
//
|
|
70
|
+
// return {
|
|
71
|
+
// get(): V {
|
|
72
|
+
// return ref.value as V;
|
|
73
|
+
// },
|
|
74
|
+
// set(newValue): void {
|
|
75
|
+
// ref.value = newValue;
|
|
76
|
+
// },
|
|
77
|
+
// init(initialValue: V): V {
|
|
78
|
+
// ref.value = initialValue;
|
|
79
|
+
// return ref.value as V;
|
|
80
|
+
// }
|
|
81
|
+
// };
|
|
82
|
+
// };
|
|
83
|
+
//}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ConstructUrlOptions, Navigation, NavigateOptions, RouterApi, Routes } from "sv-router";
|
|
2
|
+
export declare const ROUTER_KEY: unique symbol;
|
|
3
|
+
export interface MonitorMapRouterApi {
|
|
4
|
+
route: RouterApi<Routes>["route"];
|
|
5
|
+
/**
|
|
6
|
+
* Loosely typed against `string` rather than sv-router's literal-checked `Path<T>` union:
|
|
7
|
+
* internal calls prefix paths with `basePath` (a runtime string), which can't satisfy a
|
|
8
|
+
* template literal type checked against the host app's full route tree.
|
|
9
|
+
*/
|
|
10
|
+
navigate(path: string, options?: NavigateOptions & {
|
|
11
|
+
params?: Record<string, string>;
|
|
12
|
+
}): Promise<Navigation>;
|
|
13
|
+
p(path: string, options?: ConstructUrlOptions & {
|
|
14
|
+
params?: Record<string, string>;
|
|
15
|
+
}): string;
|
|
16
|
+
isActive: {
|
|
17
|
+
(path: string, params?: Record<string, string>): boolean;
|
|
18
|
+
startsWith(path: string, params?: Record<string, string>): boolean;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Prefix under which monitorMapRoutes is mounted in the host app's router,
|
|
22
|
+
* e.g. "" at the app root, or "/my-map" when nested under a host route.
|
|
23
|
+
*/
|
|
24
|
+
basePath: string;
|
|
25
|
+
}
|
|
26
|
+
export declare function provideMonitorMapRouter(api: MonitorMapRouterApi): void;
|
|
27
|
+
export declare function useMonitorMapRouter(): MonitorMapRouterApi;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { getContext
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
t(n, e);
|
|
1
|
+
import { getContext, setContext } from "svelte";
|
|
2
|
+
export const ROUTER_KEY = Symbol("monitor-map-router");
|
|
3
|
+
export function provideMonitorMapRouter(api) {
|
|
4
|
+
setContext(ROUTER_KEY, api);
|
|
6
5
|
}
|
|
7
|
-
function
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
export function useMonitorMapRouter() {
|
|
7
|
+
const api = getContext(ROUTER_KEY);
|
|
8
|
+
if (!api) {
|
|
9
|
+
throw new Error("monitor-map router context not found. Wrap your app root with " +
|
|
10
|
+
"provideMonitorMapRouter(...) before rendering monitor-map components.");
|
|
11
|
+
}
|
|
12
|
+
return api;
|
|
11
13
|
}
|
|
12
|
-
//#endregion
|
|
13
|
-
export { n as ROUTER_KEY, r as provideMonitorMapRouter, i as useMonitorMapRouter };
|
package/dist/lib/routes.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import MonitorMapLayout from "./MonitorMapLayout.svelte";
|
|
2
|
+
import MainMapView from "./MainMapView.svelte";
|
|
3
|
+
// Explicitly typed as sv-router's own `Routes` so declaration emission doesn't
|
|
4
|
+
// need to name svelte2tsx's internal per-component prop types (see
|
|
5
|
+
// MonitorMapLayout/MainMapView.svelte) and so this stays assignable to
|
|
6
|
+
// `createRouter`'s `Routes`-constrained parameter in a host app's router.ts.
|
|
7
|
+
export const monitorMapRoutes = {
|
|
8
|
+
layout: MonitorMapLayout,
|
|
9
|
+
"/": MainMapView,
|
|
10
|
+
"/monitor/:id": () => import("./MonitorDetailPanel.svelte")
|
|
8
11
|
};
|
|
9
|
-
//#endregion
|
|
10
|
-
export { n as monitorMapRoutes };
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onDestroy } from "svelte";
|
|
3
|
+
import { Marker } from "@maptiler/sdk";
|
|
4
|
+
import { SearchIcon } from "@lucide/svelte";
|
|
5
|
+
import { useMonitorMapRouter } from "../router-context";
|
|
6
|
+
import { mapManager } from "../map/map.svelte";
|
|
7
|
+
import { debounce } from "../utils";
|
|
8
|
+
import { monitorSearch, geocode, type SearchResult } from "./service";
|
|
9
|
+
import { monitorsMapIntegration } from "../monitors/monitors-map-integration.svelte";
|
|
10
|
+
|
|
11
|
+
const { navigate, basePath } = useMonitorMapRouter();
|
|
12
|
+
|
|
13
|
+
let collapsed = $state(true);
|
|
14
|
+
let searchText = $state("");
|
|
15
|
+
let results: SearchResult[] = $state([]);
|
|
16
|
+
let marker: Marker | null = $state.raw(null);
|
|
17
|
+
let inputEl: HTMLInputElement | null = $state(null);
|
|
18
|
+
|
|
19
|
+
function clickOutside(node: HTMLElement) {
|
|
20
|
+
function handler(e: MouseEvent) {
|
|
21
|
+
if (!collapsed && !node.contains(e.target as Node)) {
|
|
22
|
+
collapsed = true;
|
|
23
|
+
searchText = "";
|
|
24
|
+
results = [];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
document.addEventListener("click", handler, true);
|
|
28
|
+
return {
|
|
29
|
+
destroy() {
|
|
30
|
+
document.removeEventListener("click", handler, true);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function openSearch() {
|
|
36
|
+
if (collapsed) {
|
|
37
|
+
collapsed = false;
|
|
38
|
+
inputEl?.focus();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function clearSearch() {
|
|
43
|
+
searchText = "";
|
|
44
|
+
results = [];
|
|
45
|
+
marker?.remove();
|
|
46
|
+
marker = null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function handleInput() {
|
|
50
|
+
const query = searchText;
|
|
51
|
+
if (!query) {
|
|
52
|
+
results = [];
|
|
53
|
+
marker?.remove();
|
|
54
|
+
marker = null;
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const monitorResults = await monitorSearch(query);
|
|
58
|
+
if (searchText !== query) return;
|
|
59
|
+
if (monitorResults.length) {
|
|
60
|
+
results = monitorResults;
|
|
61
|
+
} else if (query.length > 4) {
|
|
62
|
+
const geo = await geocode(query);
|
|
63
|
+
if (searchText !== query) return;
|
|
64
|
+
results = geo;
|
|
65
|
+
} else {
|
|
66
|
+
results = [];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const debouncedSearch = debounce(handleInput, 500);
|
|
71
|
+
|
|
72
|
+
async function selectMonitor(result: Extract<SearchResult, { type: "monitor" }>) {
|
|
73
|
+
collapsed = true;
|
|
74
|
+
searchText = "";
|
|
75
|
+
results = [];
|
|
76
|
+
marker?.remove();
|
|
77
|
+
marker = null;
|
|
78
|
+
if (mapManager.map && result.monitor.position) {
|
|
79
|
+
const { coordinates } = result.monitor.position;
|
|
80
|
+
const center: [number, number] = [coordinates[0], coordinates[1]];
|
|
81
|
+
mapManager.map.flyTo({
|
|
82
|
+
center,
|
|
83
|
+
zoom: 12
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
await navigate(`${basePath}/monitor/:id`, { params: { id: result.monitor.id } });
|
|
87
|
+
monitorsMapIntegration.selectedMonitorId = result.monitor.id;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function selectGeocode(result: Extract<SearchResult, { type: "geocode" }>) {
|
|
91
|
+
const { feature } = result;
|
|
92
|
+
marker?.remove();
|
|
93
|
+
marker = null;
|
|
94
|
+
if (mapManager.map) {
|
|
95
|
+
const center: [number, number] = [feature.center[0], feature.center[1]];
|
|
96
|
+
marker = new Marker().setLngLat(center).addTo(mapManager.map);
|
|
97
|
+
const isAddress = feature.place_type?.[0] === "address";
|
|
98
|
+
mapManager.map.flyTo({
|
|
99
|
+
center,
|
|
100
|
+
...(isAddress && { zoom: 16 })
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
results = [];
|
|
104
|
+
collapsed = true;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
onDestroy(() => {
|
|
108
|
+
marker?.remove();
|
|
109
|
+
});
|
|
110
|
+
</script>
|
|
111
|
+
|
|
112
|
+
<div
|
|
113
|
+
class={[
|
|
114
|
+
"flex flex-col bg-white shadow-md overflow-hidden transition-all duration-300 select-none",
|
|
115
|
+
collapsed ? "w-12 h-12 rounded-full" : "w-90 rounded-3xl",
|
|
116
|
+
!collapsed && results.length ? "max-h-90" : "max-h-12"
|
|
117
|
+
]}
|
|
118
|
+
use:clickOutside
|
|
119
|
+
>
|
|
120
|
+
<div class="flex items-center w-full h-12 shrink-0">
|
|
121
|
+
<button
|
|
122
|
+
class="w-12 h-12 shrink-0 flex items-center justify-center rounded-full bg-brand border-4 border-white"
|
|
123
|
+
onclick={openSearch}
|
|
124
|
+
aria-label="Open search"
|
|
125
|
+
>
|
|
126
|
+
<SearchIcon size="24" color="#FFFFFF" />
|
|
127
|
+
</button>
|
|
128
|
+
<div class="overflow-hidden w-full h-full flex items-center">
|
|
129
|
+
<input
|
|
130
|
+
bind:this={inputEl}
|
|
131
|
+
bind:value={searchText}
|
|
132
|
+
oninput={debouncedSearch}
|
|
133
|
+
type="text"
|
|
134
|
+
placeholder="Search monitors or locations..."
|
|
135
|
+
class="h-full px-2 text-sm bg-transparent border-none outline-none w-full"
|
|
136
|
+
tabindex={collapsed ? -1 : 0}
|
|
137
|
+
/>
|
|
138
|
+
{#if searchText && !collapsed}
|
|
139
|
+
<button
|
|
140
|
+
onclick={clearSearch}
|
|
141
|
+
class="px-2 text-gray-400 hover:text-gray-600 text-xl leading-none cursor-pointer"
|
|
142
|
+
aria-label="Clear search">×</button
|
|
143
|
+
>
|
|
144
|
+
{/if}
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
<div
|
|
148
|
+
class={[
|
|
149
|
+
"overflow-y-auto transition-all duration-300 divide-y divide-gray-100",
|
|
150
|
+
!collapsed ? "max-h-80" : "max-h-0"
|
|
151
|
+
]}
|
|
152
|
+
>
|
|
153
|
+
{#each results as result (result.type === "monitor" ? result.monitor.id : result.feature.place_name)}
|
|
154
|
+
{#if result.type === "monitor"}
|
|
155
|
+
<button
|
|
156
|
+
onclick={() => selectMonitor(result)}
|
|
157
|
+
class="flex items-center w-full h-12 px-4 hover:brightness-95 bg-white text-left"
|
|
158
|
+
>
|
|
159
|
+
{#if result.logo.url}
|
|
160
|
+
<img
|
|
161
|
+
src={result.logo.url}
|
|
162
|
+
alt={result.logo.alt}
|
|
163
|
+
class="w-10 h-10 object-contain mr-3 shrink-0"
|
|
164
|
+
/>
|
|
165
|
+
{/if}
|
|
166
|
+
<span class="text-sm truncate">{result.monitor.name}</span>
|
|
167
|
+
</button>
|
|
168
|
+
{:else}
|
|
169
|
+
{@const comma = result.feature.place_name.indexOf(",")}
|
|
170
|
+
<button
|
|
171
|
+
onclick={() => selectGeocode(result)}
|
|
172
|
+
class="flex items-center w-full h-12 px-4 hover:brightness-95 bg-white text-left"
|
|
173
|
+
>
|
|
174
|
+
<span class="svg-icon location-on bg-brand w-6 h-6 shrink-0 mr-3"></span>
|
|
175
|
+
<div class="min-w-0">
|
|
176
|
+
<p class="text-sm font-medium truncate">
|
|
177
|
+
{result.feature.place_name.substring(0, comma < 0 ? undefined : comma)}
|
|
178
|
+
</p>
|
|
179
|
+
{#if comma >= 0}
|
|
180
|
+
<p class="text-xs text-muted-foreground truncate">
|
|
181
|
+
{result.feature.place_name.substring(comma + 1).trim()}
|
|
182
|
+
</p>
|
|
183
|
+
{/if}
|
|
184
|
+
</div>
|
|
185
|
+
</button>
|
|
186
|
+
{/if}
|
|
187
|
+
{/each}
|
|
188
|
+
</div>
|
|
189
|
+
</div>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type GeocodingFeature } from "@maptiler/sdk";
|
|
2
|
+
import type { MonitorLatestType } from "@sjvair/sdk";
|
|
3
|
+
export type MonitorResult = {
|
|
4
|
+
type: "monitor";
|
|
5
|
+
monitor: MonitorLatestType<"pm25" | "o3">;
|
|
6
|
+
logo: {
|
|
7
|
+
url: string;
|
|
8
|
+
alt: string;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
export type GeocodeResult = {
|
|
12
|
+
type: "geocode";
|
|
13
|
+
feature: GeocodingFeature;
|
|
14
|
+
};
|
|
15
|
+
export type SearchResult = MonitorResult | GeocodeResult;
|
|
16
|
+
export declare function monitorSearch(query: string): Promise<SearchResult[]>;
|
|
17
|
+
export declare function geocode(query: string): Promise<SearchResult[]>;
|