@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.
Files changed (254) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +59 -138
  3. package/dist/lib/MonitorDetailPanel.svelte +23 -20
  4. package/dist/lib/MonitorMapLayout.svelte +147 -77
  5. package/dist/lib/components/DataBox.svelte +4 -1
  6. package/dist/lib/components/ui/range-calendar/range-calendar.svelte.d.ts +1 -1
  7. package/dist/lib/config.svelte.d.ts +7 -0
  8. package/dist/lib/config.svelte.js +10 -0
  9. package/dist/lib/core.d.ts +2 -2
  10. package/dist/lib/core.js +2 -1
  11. package/dist/lib/data-chart/DataChart.svelte +40 -25
  12. package/dist/lib/data-chart/DateRange.d.ts +13 -4
  13. package/dist/lib/data-chart/DateRange.js +50 -14
  14. package/dist/lib/data-chart/chart-utils.js +5 -7
  15. package/dist/lib/data-chart/level-colors.d.ts +3 -4
  16. package/dist/lib/data-chart/level-colors.js +7 -4
  17. package/dist/lib/data-chart/pacific-time.d.ts +9 -0
  18. package/dist/lib/data-chart/pacific-time.js +25 -0
  19. package/dist/lib/data-chart/tooltip.js +2 -2
  20. package/{src/lib/ev-stations/components/EvStationTooltip.svelte → dist/lib/ev-stations/EvPopup.svelte} +6 -5
  21. package/dist/lib/ev-stations/EvPopup.svelte.d.ts +7 -0
  22. package/dist/lib/ev-stations/ev-plugin.svelte.d.ts +14 -0
  23. package/dist/lib/ev-stations/ev-plugin.svelte.js +71 -0
  24. package/dist/lib/ev-stations/ev-station-icons.d.ts +1 -4
  25. package/dist/lib/ev-stations/ev-station-icons.js +1 -13
  26. package/dist/lib/ev-stations/ev-stations.d.ts +7 -0
  27. package/dist/lib/ev-stations/ev-stations.js +53 -0
  28. package/dist/lib/ev-stations/ev-store.svelte.d.ts +21 -0
  29. package/dist/lib/ev-stations/ev-store.svelte.js +83 -0
  30. package/dist/lib/ev-stations/station-popup.svelte.d.ts +14 -0
  31. package/dist/lib/ev-stations/station-popup.svelte.js +54 -0
  32. package/dist/lib/ev-stations/types.d.ts +0 -29
  33. package/dist/lib/ev-stations/zip-codes.d.ts +11 -0
  34. package/dist/lib/ev-stations/zip-codes.js +28 -16
  35. package/dist/lib/index.d.ts +8 -56
  36. package/dist/lib/index.js +7 -46
  37. package/dist/lib/legend/Legend.svelte +18 -19
  38. package/dist/lib/legend/Legend.svelte.d.ts +2 -2
  39. package/dist/lib/levels.d.ts +7 -0
  40. package/dist/lib/levels.js +19 -0
  41. package/dist/lib/map/MapShell.svelte +17 -24
  42. package/dist/lib/map/MapShell.svelte.d.ts +4 -4
  43. package/dist/lib/map/basemaps.d.ts +25 -0
  44. package/dist/lib/map/basemaps.js +66 -0
  45. package/dist/lib/map/live-map.svelte.d.ts +3 -0
  46. package/dist/lib/map/live-map.svelte.js +22 -0
  47. package/dist/lib/map/sync-plugins.svelte.d.ts +19 -0
  48. package/dist/lib/map/sync-plugins.svelte.js +52 -0
  49. package/dist/lib/monitors/components/MonitorSubscriptionManager.svelte +66 -61
  50. package/dist/lib/monitors/filtered-source.svelte.d.ts +9 -0
  51. package/dist/lib/monitors/filtered-source.svelte.js +28 -0
  52. package/dist/lib/monitors/monitors.svelte.d.ts +25 -35
  53. package/dist/lib/monitors/monitors.svelte.js +35 -218
  54. package/dist/lib/monitors/retry-load.d.ts +8 -0
  55. package/dist/lib/monitors/retry-load.js +11 -0
  56. package/dist/lib/monitors/types.d.ts +1 -41
  57. package/dist/lib/options/map-option-defaults.d.ts +25 -36
  58. package/dist/lib/options/map-option-defaults.js +12 -30
  59. package/dist/lib/options/map-options.svelte.d.ts +13 -0
  60. package/dist/lib/options/map-options.svelte.js +26 -0
  61. package/dist/lib/options/menus/LayersMenu.svelte +8 -20
  62. package/dist/lib/options/menus/LayersMenu.svelte.d.ts +17 -2
  63. package/dist/lib/options/menus/MonitorsMenu.svelte +34 -18
  64. package/dist/lib/options/menus/OverlaysMenu.svelte +2 -2
  65. package/dist/lib/options/menus/PollutantMenu.svelte +4 -9
  66. package/dist/lib/options/menus/SettingsMenu.svelte +32 -25
  67. package/dist/lib/options/menus/SettingsMenu.svelte.d.ts +5 -16
  68. package/dist/lib/options/plugin-order.d.ts +8 -0
  69. package/dist/lib/options/plugin-order.js +36 -0
  70. package/dist/lib/options/pollutant-param.d.ts +7 -5
  71. package/dist/lib/options/pollutant-param.js +9 -5
  72. package/dist/lib/options/row-icons.d.ts +8 -0
  73. package/dist/lib/options/row-icons.js +15 -0
  74. package/dist/lib/options/rows/MarkerIcon.svelte +5 -5
  75. package/dist/lib/options/rows/MarkerIcon.svelte.d.ts +1 -2
  76. package/dist/lib/search/Search.svelte +20 -33
  77. package/dist/lib/search/Search.svelte.d.ts +5 -1
  78. package/dist/lib/search/search-pin.svelte.d.ts +11 -0
  79. package/dist/lib/search/search-pin.svelte.js +28 -0
  80. package/dist/lib/search/service.d.ts +7 -2
  81. package/dist/lib/search/service.js +17 -10
  82. package/dist/lib/stores.svelte.d.ts +8 -0
  83. package/dist/lib/stores.svelte.js +9 -0
  84. package/dist/lib/wind/wind-plugin.d.ts +11 -0
  85. package/dist/lib/wind/wind-plugin.js +25 -0
  86. package/package.json +12 -10
  87. package/src/lib/MonitorDetailPanel.svelte +23 -20
  88. package/src/lib/MonitorMapLayout.svelte +147 -77
  89. package/src/lib/components/DataBox.svelte +4 -1
  90. package/src/lib/config.svelte.ts +16 -0
  91. package/src/lib/core.ts +2 -2
  92. package/src/lib/data-chart/DataChart.svelte +40 -25
  93. package/src/lib/data-chart/DateRange.ts +58 -15
  94. package/src/lib/data-chart/chart-utils.ts +6 -7
  95. package/src/lib/data-chart/level-colors.ts +8 -9
  96. package/src/lib/data-chart/pacific-time.ts +31 -0
  97. package/src/lib/data-chart/tooltip.ts +2 -2
  98. package/{dist/lib/ev-stations/components/EvStationTooltip.svelte → src/lib/ev-stations/EvPopup.svelte} +6 -5
  99. package/src/lib/ev-stations/ev-plugin.svelte.ts +86 -0
  100. package/src/lib/ev-stations/ev-station-icons.ts +1 -17
  101. package/src/lib/ev-stations/ev-stations.ts +72 -0
  102. package/src/lib/ev-stations/ev-store.svelte.ts +117 -0
  103. package/src/lib/ev-stations/station-popup.svelte.ts +64 -0
  104. package/src/lib/ev-stations/types.ts +0 -34
  105. package/src/lib/ev-stations/zip-codes.ts +29 -16
  106. package/src/lib/index.ts +8 -99
  107. package/src/lib/legend/Legend.svelte +18 -19
  108. package/src/lib/levels.ts +24 -0
  109. package/src/lib/map/MapShell.svelte +17 -24
  110. package/src/lib/map/basemaps.ts +76 -0
  111. package/src/lib/map/live-map.svelte.ts +24 -0
  112. package/src/lib/map/sync-plugins.svelte.ts +69 -0
  113. package/src/lib/monitors/components/MonitorSubscriptionManager.svelte +66 -61
  114. package/src/lib/monitors/filtered-source.svelte.ts +38 -0
  115. package/src/lib/monitors/monitors.svelte.ts +58 -261
  116. package/src/lib/monitors/retry-load.ts +14 -0
  117. package/src/lib/monitors/types.ts +1 -47
  118. package/src/lib/options/map-option-defaults.ts +30 -53
  119. package/src/lib/options/map-options.svelte.ts +30 -0
  120. package/src/lib/options/menus/LayersMenu.svelte +8 -20
  121. package/src/lib/options/menus/MonitorsMenu.svelte +34 -18
  122. package/src/lib/options/menus/OverlaysMenu.svelte +2 -2
  123. package/src/lib/options/menus/PollutantMenu.svelte +4 -9
  124. package/src/lib/options/menus/SettingsMenu.svelte +32 -25
  125. package/src/lib/options/plugin-order.ts +38 -0
  126. package/src/lib/options/pollutant-param.ts +14 -9
  127. package/src/lib/options/row-icons.ts +17 -0
  128. package/src/lib/options/rows/MarkerIcon.svelte +5 -5
  129. package/src/lib/search/Search.svelte +20 -33
  130. package/src/lib/search/search-pin.svelte.ts +35 -0
  131. package/src/lib/search/service.ts +34 -15
  132. package/src/lib/stores.svelte.ts +15 -0
  133. package/src/lib/wind/wind-plugin.ts +33 -0
  134. package/dist/lib/collocation-sites/CollocationTooltip.svelte +0 -98
  135. package/dist/lib/collocation-sites/CollocationTooltip.svelte.d.ts +0 -7
  136. package/dist/lib/collocation-sites/collocations-icon-manager.svelte.d.ts +0 -7
  137. package/dist/lib/collocation-sites/collocations-icon-manager.svelte.js +0 -18
  138. package/dist/lib/collocation-sites/collocations-map-integration.svelte.d.ts +0 -21
  139. package/dist/lib/collocation-sites/collocations-map-integration.svelte.js +0 -113
  140. package/dist/lib/collocation-sites/collocations.svelte.d.ts +0 -10
  141. package/dist/lib/collocation-sites/collocations.svelte.js +0 -21
  142. package/dist/lib/collocation-sites/types.d.ts +0 -8
  143. package/dist/lib/collocation-sites/types.js +0 -1
  144. package/dist/lib/ev-stations/components/EvStationClusterTooltip.svelte +0 -16
  145. package/dist/lib/ev-stations/components/EvStationClusterTooltip.svelte.d.ts +0 -7
  146. package/dist/lib/ev-stations/components/EvStationTooltip.svelte.d.ts +0 -7
  147. package/dist/lib/ev-stations/ev-stations-cluster-renderer.d.ts +0 -19
  148. package/dist/lib/ev-stations/ev-stations-cluster-renderer.js +0 -131
  149. package/dist/lib/ev-stations/ev-stations-map-integration.svelte.d.ts +0 -31
  150. package/dist/lib/ev-stations/ev-stations-map-integration.svelte.js +0 -226
  151. package/dist/lib/ev-stations/ev-stations.svelte.d.ts +0 -10
  152. package/dist/lib/ev-stations/ev-stations.svelte.js +0 -57
  153. package/dist/lib/hms/hms-fire-icon-manager.d.ts +0 -13
  154. package/dist/lib/hms/hms-fire-icon-manager.js +0 -39
  155. package/dist/lib/hms/hms-fire-map-integration.svelte.d.ts +0 -23
  156. package/dist/lib/hms/hms-fire-map-integration.svelte.js +0 -94
  157. package/dist/lib/hms/hms-smoke-map-integration.svelte.d.ts +0 -39
  158. package/dist/lib/hms/hms-smoke-map-integration.svelte.js +0 -87
  159. package/dist/lib/hms/hms.svelte.d.ts +0 -20
  160. package/dist/lib/hms/hms.svelte.js +0 -237
  161. package/dist/lib/legend/LegendBar.svelte +0 -45
  162. package/dist/lib/legend/LegendBar.svelte.d.ts +0 -7
  163. package/dist/lib/legend/legend-data.d.ts +0 -40
  164. package/dist/lib/legend/legend-data.js +0 -65
  165. package/dist/lib/map/Map.svelte +0 -13
  166. package/dist/lib/map/Map.svelte.d.ts +0 -8
  167. package/dist/lib/map/basemap.d.ts +0 -14
  168. package/dist/lib/map/basemap.js +0 -10
  169. package/dist/lib/map/icons.d.ts +0 -7
  170. package/dist/lib/map/icons.js +0 -33
  171. package/dist/lib/map/integrations/base-layer-seperator.d.ts +0 -9
  172. package/dist/lib/map/integrations/base-layer-seperator.js +0 -11
  173. package/dist/lib/map/integrations/click-manager.d.ts +0 -14
  174. package/dist/lib/map/integrations/click-manager.js +0 -52
  175. package/dist/lib/map/integrations/integrations-manager.d.ts +0 -8
  176. package/dist/lib/map/integrations/integrations-manager.js +0 -20
  177. package/dist/lib/map/integrations/map-display-option.svelte.d.ts +0 -7
  178. package/dist/lib/map/integrations/map-display-option.svelte.js +0 -10
  179. package/dist/lib/map/integrations/map-geojson-integration.svelte.d.ts +0 -32
  180. package/dist/lib/map/integrations/map-geojson-integration.svelte.js +0 -60
  181. package/dist/lib/map/integrations/map-icon-manager.d.ts +0 -15
  182. package/dist/lib/map/integrations/map-icon-manager.js +0 -52
  183. package/dist/lib/map/integrations/map-integration.svelte.d.ts +0 -6
  184. package/dist/lib/map/integrations/map-integration.svelte.js +0 -2
  185. package/dist/lib/map/integrations/map-layer-integration.svelte.d.ts +0 -11
  186. package/dist/lib/map/integrations/map-layer-integration.svelte.js +0 -40
  187. package/dist/lib/map/integrations/tooltip.svelte.d.ts +0 -36
  188. package/dist/lib/map/integrations/tooltip.svelte.js +0 -131
  189. package/dist/lib/map/integrations/types.d.ts +0 -14
  190. package/dist/lib/map/integrations/types.js +0 -1
  191. package/dist/lib/map/map-manager.svelte.d.ts +0 -20
  192. package/dist/lib/map/map-manager.svelte.js +0 -63
  193. package/dist/lib/map/map-style-state.svelte.d.ts +0 -23
  194. package/dist/lib/map/map-style-state.svelte.js +0 -86
  195. package/dist/lib/map/utils.d.ts +0 -7
  196. package/dist/lib/map/utils.js +0 -36
  197. package/dist/lib/monitors/components/MonitorClusterTooltip.svelte +0 -112
  198. package/dist/lib/monitors/components/MonitorClusterTooltip.svelte.d.ts +0 -7
  199. package/dist/lib/monitors/components/MonitorTooltip.svelte +0 -61
  200. package/dist/lib/monitors/components/MonitorTooltip.svelte.d.ts +0 -7
  201. package/dist/lib/monitors/monitor-utils.d.ts +0 -4
  202. package/dist/lib/monitors/monitor-utils.js +0 -41
  203. package/dist/lib/monitors/monitors-cluster-renderer.d.ts +0 -33
  204. package/dist/lib/monitors/monitors-cluster-renderer.js +0 -221
  205. package/dist/lib/monitors/monitors-icon-manager.svelte.d.ts +0 -15
  206. package/dist/lib/monitors/monitors-icon-manager.svelte.js +0 -78
  207. package/dist/lib/monitors/monitors-map-integration.svelte.d.ts +0 -43
  208. package/dist/lib/monitors/monitors-map-integration.svelte.js +0 -301
  209. package/dist/lib/options/reset-map-options.d.ts +0 -2
  210. package/dist/lib/options/reset-map-options.js +0 -24
  211. package/dist/lib/reactivity.svelte.d.ts +0 -0
  212. package/dist/lib/reactivity.svelte.js +0 -83
  213. package/dist/lib/wind/wind.svelte.d.ts +0 -10
  214. package/dist/lib/wind/wind.svelte.js +0 -13
  215. package/src/lib/collocation-sites/CollocationTooltip.svelte +0 -98
  216. package/src/lib/collocation-sites/collocations-icon-manager.svelte.ts +0 -21
  217. package/src/lib/collocation-sites/collocations-map-integration.svelte.ts +0 -136
  218. package/src/lib/collocation-sites/collocations.svelte.ts +0 -27
  219. package/src/lib/collocation-sites/types.ts +0 -10
  220. package/src/lib/ev-stations/components/EvStationClusterTooltip.svelte +0 -16
  221. package/src/lib/ev-stations/ev-stations-cluster-renderer.ts +0 -162
  222. package/src/lib/ev-stations/ev-stations-map-integration.svelte.ts +0 -248
  223. package/src/lib/ev-stations/ev-stations.svelte.ts +0 -84
  224. package/src/lib/hms/hms-fire-icon-manager.ts +0 -48
  225. package/src/lib/hms/hms-fire-map-integration.svelte.ts +0 -109
  226. package/src/lib/hms/hms-smoke-map-integration.svelte.ts +0 -105
  227. package/src/lib/hms/hms.svelte.ts +0 -270
  228. package/src/lib/legend/LegendBar.svelte +0 -45
  229. package/src/lib/legend/legend-data.ts +0 -101
  230. package/src/lib/map/Map.svelte +0 -13
  231. package/src/lib/map/basemap.ts +0 -24
  232. package/src/lib/map/icons.ts +0 -42
  233. package/src/lib/map/integrations/base-layer-seperator.ts +0 -17
  234. package/src/lib/map/integrations/click-manager.ts +0 -64
  235. package/src/lib/map/integrations/integrations-manager.ts +0 -25
  236. package/src/lib/map/integrations/map-display-option.svelte.ts +0 -13
  237. package/src/lib/map/integrations/map-geojson-integration.svelte.ts +0 -77
  238. package/src/lib/map/integrations/map-icon-manager.ts +0 -67
  239. package/src/lib/map/integrations/map-integration.svelte.ts +0 -8
  240. package/src/lib/map/integrations/map-layer-integration.svelte.ts +0 -49
  241. package/src/lib/map/integrations/tooltip.svelte.ts +0 -153
  242. package/src/lib/map/integrations/types.ts +0 -24
  243. package/src/lib/map/map-manager.svelte.ts +0 -83
  244. package/src/lib/map/map-style-state.svelte.ts +0 -94
  245. package/src/lib/map/utils.ts +0 -53
  246. package/src/lib/monitors/components/MonitorClusterTooltip.svelte +0 -112
  247. package/src/lib/monitors/components/MonitorTooltip.svelte +0 -61
  248. package/src/lib/monitors/monitor-utils.ts +0 -57
  249. package/src/lib/monitors/monitors-cluster-renderer.ts +0 -285
  250. package/src/lib/monitors/monitors-icon-manager.svelte.ts +0 -98
  251. package/src/lib/monitors/monitors-map-integration.svelte.ts +0 -318
  252. package/src/lib/options/reset-map-options.ts +0 -28
  253. package/src/lib/reactivity.svelte.ts +0 -82
  254. 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 "@sjvair/monitor-map/core" (no map), and
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
- // State managers
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 LegendBar from "./LegendBar.svelte";
4
- import type { LegendSection } from "./legend-data";
3
+ import { Legend, legendSection, type MapContext } from "@sjvair/map-sdk";
5
4
 
6
- let { sections }: { sections: Array<LegendSection> } = $props();
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 sections.length}
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
- {#if !collapsed}
25
- <div class="flex flex-col gap-3 border-t border-gray-200 px-4 py-3">
26
- {#each sections as section (section.id)}
27
- <div>
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 { SomeMapIntegration } from "$lib/map/integrations/types";
3
+ import type { MapContext } from "@sjvair/map-sdk";
4
4
 
5
5
  export interface MapShellProps {
6
- /** Map integrations to register, e.g. [monitorsMapIntegration] */
7
- integrations: Array<SomeMapIntegration>;
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 idle AND this
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 Map from "$lib/map/Map.svelte";
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
- integrations,
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
- // mapManager.map is only ever assigned once its own initial "load" has
83
- // already fired (see initializeMap in map-manager.svelte.ts), so by the time this
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
- <Map {integrations} />
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 { monitorsManager } from "$lib";
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
- if (!monitorsManager.meta) return [];
27
- try {
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 (!signal.aborted) throw error;
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
- <div class="relative select-none">
82
- <button
83
- class={[
84
- "flex w-full cursor-pointer items-center justify-center gap-2 rounded border px-3 py-1.5 text-sm font-semibold text-white",
85
- subscribedLevel
86
- ? "border-green-700 bg-green-600 hover:bg-green-700"
87
- : "border-blue-600 bg-blue-500 hover:bg-blue-600"
88
- ]}
89
- disabled={loading}
90
- onclick={() => (open = !open)}
91
- >
92
- {subscribedLevel ? "Manage Subscription" : "Subscribe to Alerts"}
93
- <ChevronDownIcon
94
- size={16}
95
- class={["transition-transform duration-300", open ? "rotate-180" : ""]}
96
- />
97
- </button>
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
- {#if open}
100
- <button aria-label="Close" class="fixed inset-0 z-10" onclick={() => (open = false)}></button>
101
- <div class="absolute top-full left-0 z-20 mt-1 w-full overflow-hidden rounded shadow-lg">
102
- {#if subscribedLevel}
103
- <button
104
- 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]"
105
- onclick={() => handleLevelClick(subscribedLevel)}
106
- >
107
- Unsubscribe
108
- <BellOffIcon size={14} />
109
- </button>
110
- {/if}
111
- {#each alertLevels as level (level.name)}
112
- {@const isSubscribed = level.name === subscribedLevel}
113
- <button
114
- class={[
115
- "flex w-full items-center justify-between px-4 py-2 text-sm text-white last:rounded-b",
116
- !isSubscribed ? "cursor-pointer first:rounded-t hover:brightness-90" : ""
117
- ]}
118
- style="background-color: {level.color}"
119
- disabled={saving}
120
- onclick={!isSubscribed ? () => handleLevelClick(level.name) : null}
121
- >
122
- <span>{level.label}</span>
123
- {#if isSubscribed}
124
- <BellCheckIcon size={14} />
125
- {/if}
126
- </button>
127
- {/each}
128
- </div>
129
- {/if}
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
+ }