@sjvair/monitor-map 3.2.2 → 3.3.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.
@@ -1,13 +1,10 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from "svelte";
3
3
  import { onDestroy } from "svelte";
4
- import LoadScreen, { disable as disableLoadScreen } from "./LoadScreen.svelte";
5
- import Map from "./map/Map.svelte";
6
- import Menu from "./map/Menu.svelte";
4
+ import MapShell from "./map/MapShell.svelte";
7
5
  import MonitorsDisplayOptions from "./monitors/components/MonitorsDisplayOptions.svelte";
8
6
  import MapLayersDisplayOptions from "./components/MapLayersDisplayOptions.svelte";
9
7
  import MapStyleDisplayOptions from "./map/MapStyleDisplayOptions.svelte";
10
- import { mapManager } from "./map/map.svelte";
11
8
  import { monitorsManager } from "./monitors/monitors.svelte";
12
9
  import { monitorsMapIntegration } from "./monitors/monitors-map-integration.svelte";
13
10
  import { windMapIntegration } from "./wind/wind.svelte";
@@ -33,8 +30,6 @@
33
30
 
34
31
  const { route, navigate, basePath } = useMonitorMapRouter();
35
32
 
36
- const TRANSITION_MS = 300;
37
-
38
33
  const integrations: Array<SomeMapIntegration> = [
39
34
  baseLayerSeperator,
40
35
  collocationSitesMapIntegration,
@@ -76,22 +71,6 @@
76
71
  }
77
72
  });
78
73
 
79
- $effect(() => {
80
- if (mapManager.map && monitorsManager.initialized) {
81
- mapManager.map.once("idle", () => disableLoadScreen());
82
- }
83
- });
84
-
85
- $effect(() => {
86
- if (panelOpen) {
87
- // Container width snapped to open; resize after layout settles
88
- requestAnimationFrame(() => mapManager.map?.resize());
89
- } else {
90
- // Container width snaps back after the transform transition ends
91
- setTimeout(() => mapManager.map?.resize(), TRANSITION_MS);
92
- }
93
- });
94
-
95
74
  // Clear selected icon scale when the detail panel closes
96
75
  $effect(() => {
97
76
  if (panelOpen) return;
@@ -101,75 +80,28 @@
101
80
  onDestroy(() => {
102
81
  monitorsManager.autoUpdate.stop();
103
82
  });
104
-
105
- /**
106
- * HACK: Fix for escaping sv-router and allowing navigation to other pages,
107
- * as well as navigating back
108
- */
109
- const rootPath = basePath || "/";
110
- const knownRoutes = [`${basePath}/monitor/`];
111
-
112
- window.addEventListener("pageshow", (e) => {
113
- if (e.persisted) window.location.reload();
114
- });
115
-
116
- document.addEventListener(
117
- "click",
118
- (e) => {
119
- const anchor = e
120
- .composedPath()
121
- .find((el) => el instanceof HTMLAnchorElement) as HTMLAnchorElement;
122
- if (!anchor) return;
123
- const { pathname } = new URL(anchor.href);
124
- const isKnown = pathname === rootPath || knownRoutes.some((r) => pathname.startsWith(r));
125
- if (!isKnown) {
126
- e.stopImmediatePropagation();
127
- window.location.href = anchor.href;
128
- }
129
- },
130
- { capture: true }
131
- );
132
83
  </script>
133
84
 
134
- <!--
135
- <div class="shell" class:panel-open={panelOpen}>
136
- -->
137
- <div class="relative flex h-full w-full flex-col md:flex-row">
138
- <LoadScreen />
139
- <div class="relative flex-1 overflow-hidden">
140
- <Map {integrations} />
85
+ <MapShell
86
+ {integrations}
87
+ ready={monitorsManager.initialized}
88
+ {panelOpen}
89
+ knownRoutes={[`${basePath}/monitor/`]}
90
+ {basePath}
91
+ >
92
+ {#snippet menu()}
93
+ <MonitorsDisplayOptions />
94
+ <EvStationsDisplayOptions />
95
+ <MapLayersDisplayOptions />
96
+ <MapStyleDisplayOptions />
97
+ {/snippet}
98
+ {#snippet overlays()}
141
99
  <div class="pointer-events-none absolute bottom-0 left-0 z-10">
142
100
  <MapLegend />
143
101
  </div>
144
- <div class="absolute top-4 left-4 z-10">
145
- <div class="absolute z-10">
146
- <Menu>
147
- <MonitorsDisplayOptions />
148
- <EvStationsDisplayOptions />
149
- <MapLayersDisplayOptions />
150
- <MapStyleDisplayOptions />
151
- </Menu>
152
- </div>
153
- <div class="absolute left-16">
154
- <Search />
155
- </div>
156
- </div>
157
- </div>
158
- <div
159
- class={[
160
- "panel-containr w-full shrink-0 overflow-hidden",
161
- panelOpen ? "h-1/2 md:h-full md:w-1/3" : "md:w-0"
162
- ]}
163
- >
164
- <div
165
- class={[
166
- "panel-contet h-full duration-300 ease-in-out",
167
- panelOpen
168
- ? "translate-y-0 md:translate-x-0"
169
- : "translate-y-full md:translate-x-full md:translate-y-0"
170
- ]}
171
- >
172
- {@render children()}
102
+ <div class="absolute top-4 left-20 z-10">
103
+ <Search />
173
104
  </div>
174
- </div>
175
- </div>
105
+ {/snippet}
106
+ {@render children()}
107
+ </MapShell>
@@ -44,6 +44,7 @@ export { baseLayerSeperator } from "./map/integrations/base-layer-seperator";
44
44
  export { hmsFireMapIntegration } from "./hms/hms-fire-map-integration.svelte";
45
45
  export { hmsSmokeMapIntegration } from "./hms/hms-smoke-map-integration.svelte";
46
46
  export { default as Map } from "./map/Map.svelte";
47
+ export { default as MapShell, type MapShellProps } from "./map/MapShell.svelte";
47
48
  export { default as Menu } from "./map/Menu.svelte";
48
49
  export { default as LoadScreen, loadScreenState, enable as enableLoadScreen, disable as disableLoadScreen } from "./LoadScreen.svelte";
49
50
  export type { LoadScreenState } from "./LoadScreen.svelte";
package/dist/lib/index.js CHANGED
@@ -42,6 +42,7 @@ export { hmsFireMapIntegration } from "./hms/hms-fire-map-integration.svelte";
42
42
  export { hmsSmokeMapIntegration } from "./hms/hms-smoke-map-integration.svelte";
43
43
  // Components
44
44
  export { default as Map } from "./map/Map.svelte";
45
+ export { default as MapShell } from "./map/MapShell.svelte";
45
46
  export { default as Menu } from "./map/Menu.svelte";
46
47
  export { default as LoadScreen, loadScreenState, enable as enableLoadScreen, disable as disableLoadScreen } from "./LoadScreen.svelte";
47
48
  export { default as MonitorsDisplayOptions } from "./monitors/components/MonitorsDisplayOptions.svelte";
@@ -0,0 +1,146 @@
1
+ <script lang="ts" module>
2
+ import type { Snippet } from "svelte";
3
+ import type { SomeMapIntegration } from "./integrations/types";
4
+
5
+ export interface MapShellProps {
6
+ /** Map integrations to register, e.g. [monitorsMapIntegration] */
7
+ integrations: Array<SomeMapIntegration>;
8
+ /**
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
11
+ * is true.
12
+ */
13
+ ready: boolean;
14
+ /** True when the routed detail panel (`children`) should be visible */
15
+ panelOpen: boolean;
16
+ /**
17
+ * Path prefixes that are part of this map's own routed panel (e.g.
18
+ * [`${basePath}/monitor/`]) — internal navigation to these should not
19
+ * trigger the escape-hatch full-page navigation below.
20
+ */
21
+ knownRoutes?: Array<string>;
22
+ /** Rendered inside the display-options menu toggle */
23
+ menu?: Snippet;
24
+ /** Freeform absolutely-positioned content over the map (legend, search, etc.) */
25
+ overlays?: Snippet;
26
+ /** The routed detail panel content */
27
+ children?: Snippet;
28
+ /**
29
+ * Base path to use for the sv-router escape-hatch's "known" root route.
30
+ * If provided, used directly instead of reading `basePath` from
31
+ * `useMonitorMapRouter()`. Only relevant when `routerEscapeHatch` is
32
+ * enabled.
33
+ */
34
+ basePath?: string;
35
+ /**
36
+ * Whether to install the sv-router escape-hatch (`pageshow`/`click`
37
+ * listeners that force a full-page navigation for links outside this
38
+ * map's own routes). Defaults to `true`, preserving the existing
39
+ * full-page-map behavior. When `true` and no `basePath` prop is given,
40
+ * `MapShell` falls back to reading `basePath` from
41
+ * `useMonitorMapRouter()`. Set to `false` to embed `MapShell` inside a
42
+ * host app with its own routing — this also skips calling
43
+ * `useMonitorMapRouter()` entirely, so no `provideMonitorMapRouter(...)`
44
+ * ancestor is required.
45
+ */
46
+ routerEscapeHatch?: boolean;
47
+ }
48
+ </script>
49
+
50
+ <script lang="ts">
51
+ import LoadScreen, { disable as disableLoadScreen } from "../LoadScreen.svelte";
52
+ import Map from "./Map.svelte";
53
+ import Menu from "./Menu.svelte";
54
+ import { mapManager } from "./map.svelte";
55
+ import { useMonitorMapRouter } from "../router-context";
56
+
57
+ let {
58
+ integrations,
59
+ ready,
60
+ panelOpen,
61
+ knownRoutes = [],
62
+ menu,
63
+ overlays,
64
+ children,
65
+ basePath: providedBasePath,
66
+ routerEscapeHatch = true
67
+ }: MapShellProps = $props();
68
+
69
+ const basePath = providedBasePath ?? (routerEscapeHatch ? useMonitorMapRouter().basePath : "");
70
+ const TRANSITION_MS = 300;
71
+
72
+ $effect(() => {
73
+ if (mapManager.map && ready) {
74
+ mapManager.map.once("idle", () => disableLoadScreen());
75
+ }
76
+ });
77
+
78
+ $effect(() => {
79
+ if (panelOpen) {
80
+ // Container width snapped to open; resize after layout settles
81
+ requestAnimationFrame(() => mapManager.map?.resize());
82
+ } else {
83
+ // Container width snaps back after the transform transition ends
84
+ setTimeout(() => mapManager.map?.resize(), TRANSITION_MS);
85
+ }
86
+ });
87
+
88
+ /**
89
+ * HACK: Fix for escaping sv-router and allowing navigation to other pages,
90
+ * as well as navigating back
91
+ */
92
+ if (routerEscapeHatch) {
93
+ const rootPath = basePath || "/";
94
+
95
+ window.addEventListener("pageshow", (e) => {
96
+ if (e.persisted) window.location.reload();
97
+ });
98
+
99
+ document.addEventListener(
100
+ "click",
101
+ (e) => {
102
+ const anchor = e
103
+ .composedPath()
104
+ .find((el) => el instanceof HTMLAnchorElement) as HTMLAnchorElement;
105
+ if (!anchor) return;
106
+ const { pathname } = new URL(anchor.href);
107
+ const isKnown = pathname === rootPath || knownRoutes.some((r) => pathname.startsWith(r));
108
+ if (!isKnown) {
109
+ e.stopImmediatePropagation();
110
+ window.location.href = anchor.href;
111
+ }
112
+ },
113
+ { capture: true }
114
+ );
115
+ }
116
+ </script>
117
+
118
+ <div class="relative flex h-full w-full flex-col md:flex-row">
119
+ <LoadScreen />
120
+ <div class="relative flex-1 overflow-hidden">
121
+ <Map {integrations} />
122
+ {@render overlays?.()}
123
+ {#if menu}
124
+ <div class="absolute top-4 left-4 z-10">
125
+ <Menu>{@render menu()}</Menu>
126
+ </div>
127
+ {/if}
128
+ </div>
129
+ <div
130
+ class={[
131
+ "panel-containr w-full shrink-0 overflow-hidden",
132
+ panelOpen ? "h-1/2 md:h-full md:w-1/3" : "md:w-0"
133
+ ]}
134
+ >
135
+ <div
136
+ class={[
137
+ "panel-contet h-full duration-300 ease-in-out",
138
+ panelOpen
139
+ ? "translate-y-0 md:translate-x-0"
140
+ : "translate-y-full md:translate-x-full md:translate-y-0"
141
+ ]}
142
+ >
143
+ {@render children?.()}
144
+ </div>
145
+ </div>
146
+ </div>
@@ -0,0 +1,48 @@
1
+ import type { Snippet } from "svelte";
2
+ import type { SomeMapIntegration } from "./integrations/types";
3
+ export interface MapShellProps {
4
+ /** Map integrations to register, e.g. [monitorsMapIntegration] */
5
+ integrations: Array<SomeMapIntegration>;
6
+ /**
7
+ * True once the caller's own data managers have finished their initial
8
+ * load. The shell hides the load screen once the map is idle AND this
9
+ * is true.
10
+ */
11
+ ready: boolean;
12
+ /** True when the routed detail panel (`children`) should be visible */
13
+ panelOpen: boolean;
14
+ /**
15
+ * Path prefixes that are part of this map's own routed panel (e.g.
16
+ * [`${basePath}/monitor/`]) — internal navigation to these should not
17
+ * trigger the escape-hatch full-page navigation below.
18
+ */
19
+ knownRoutes?: Array<string>;
20
+ /** Rendered inside the display-options menu toggle */
21
+ menu?: Snippet;
22
+ /** Freeform absolutely-positioned content over the map (legend, search, etc.) */
23
+ overlays?: Snippet;
24
+ /** The routed detail panel content */
25
+ children?: Snippet;
26
+ /**
27
+ * Base path to use for the sv-router escape-hatch's "known" root route.
28
+ * If provided, used directly instead of reading `basePath` from
29
+ * `useMonitorMapRouter()`. Only relevant when `routerEscapeHatch` is
30
+ * enabled.
31
+ */
32
+ basePath?: string;
33
+ /**
34
+ * Whether to install the sv-router escape-hatch (`pageshow`/`click`
35
+ * listeners that force a full-page navigation for links outside this
36
+ * map's own routes). Defaults to `true`, preserving the existing
37
+ * full-page-map behavior. When `true` and no `basePath` prop is given,
38
+ * `MapShell` falls back to reading `basePath` from
39
+ * `useMonitorMapRouter()`. Set to `false` to embed `MapShell` inside a
40
+ * host app with its own routing — this also skips calling
41
+ * `useMonitorMapRouter()` entirely, so no `provideMonitorMapRouter(...)`
42
+ * ancestor is required.
43
+ */
44
+ routerEscapeHatch?: boolean;
45
+ }
46
+ declare const MapShell: import("svelte").Component<MapShellProps, {}, "">;
47
+ type MapShell = ReturnType<typeof MapShell>;
48
+ export default MapShell;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sjvair/monitor-map",
3
3
  "description": "SJVAir's interactive monitor map",
4
- "version": "3.2.2",
4
+ "version": "3.3.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/SJVAir/monitor-map"
@@ -1,13 +1,10 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from "svelte";
3
3
  import { onDestroy } from "svelte";
4
- import LoadScreen, { disable as disableLoadScreen } from "$lib/LoadScreen.svelte";
5
- import Map from "$lib/map/Map.svelte";
6
- import Menu from "$lib/map/Menu.svelte";
4
+ import MapShell from "$lib/map/MapShell.svelte";
7
5
  import MonitorsDisplayOptions from "$lib/monitors/components/MonitorsDisplayOptions.svelte";
8
6
  import MapLayersDisplayOptions from "$lib/components/MapLayersDisplayOptions.svelte";
9
7
  import MapStyleDisplayOptions from "$lib/map/MapStyleDisplayOptions.svelte";
10
- import { mapManager } from "$lib/map/map.svelte";
11
8
  import { monitorsManager } from "$lib/monitors/monitors.svelte";
12
9
  import { monitorsMapIntegration } from "$lib/monitors/monitors-map-integration.svelte";
13
10
  import { windMapIntegration } from "$lib/wind/wind.svelte";
@@ -33,8 +30,6 @@
33
30
 
34
31
  const { route, navigate, basePath } = useMonitorMapRouter();
35
32
 
36
- const TRANSITION_MS = 300;
37
-
38
33
  const integrations: Array<SomeMapIntegration> = [
39
34
  baseLayerSeperator,
40
35
  collocationSitesMapIntegration,
@@ -76,22 +71,6 @@
76
71
  }
77
72
  });
78
73
 
79
- $effect(() => {
80
- if (mapManager.map && monitorsManager.initialized) {
81
- mapManager.map.once("idle", () => disableLoadScreen());
82
- }
83
- });
84
-
85
- $effect(() => {
86
- if (panelOpen) {
87
- // Container width snapped to open; resize after layout settles
88
- requestAnimationFrame(() => mapManager.map?.resize());
89
- } else {
90
- // Container width snaps back after the transform transition ends
91
- setTimeout(() => mapManager.map?.resize(), TRANSITION_MS);
92
- }
93
- });
94
-
95
74
  // Clear selected icon scale when the detail panel closes
96
75
  $effect(() => {
97
76
  if (panelOpen) return;
@@ -101,75 +80,28 @@
101
80
  onDestroy(() => {
102
81
  monitorsManager.autoUpdate.stop();
103
82
  });
104
-
105
- /**
106
- * HACK: Fix for escaping sv-router and allowing navigation to other pages,
107
- * as well as navigating back
108
- */
109
- const rootPath = basePath || "/";
110
- const knownRoutes = [`${basePath}/monitor/`];
111
-
112
- window.addEventListener("pageshow", (e) => {
113
- if (e.persisted) window.location.reload();
114
- });
115
-
116
- document.addEventListener(
117
- "click",
118
- (e) => {
119
- const anchor = e
120
- .composedPath()
121
- .find((el) => el instanceof HTMLAnchorElement) as HTMLAnchorElement;
122
- if (!anchor) return;
123
- const { pathname } = new URL(anchor.href);
124
- const isKnown = pathname === rootPath || knownRoutes.some((r) => pathname.startsWith(r));
125
- if (!isKnown) {
126
- e.stopImmediatePropagation();
127
- window.location.href = anchor.href;
128
- }
129
- },
130
- { capture: true }
131
- );
132
83
  </script>
133
84
 
134
- <!--
135
- <div class="shell" class:panel-open={panelOpen}>
136
- -->
137
- <div class="relative flex h-full w-full flex-col md:flex-row">
138
- <LoadScreen />
139
- <div class="relative flex-1 overflow-hidden">
140
- <Map {integrations} />
85
+ <MapShell
86
+ {integrations}
87
+ ready={monitorsManager.initialized}
88
+ {panelOpen}
89
+ knownRoutes={[`${basePath}/monitor/`]}
90
+ {basePath}
91
+ >
92
+ {#snippet menu()}
93
+ <MonitorsDisplayOptions />
94
+ <EvStationsDisplayOptions />
95
+ <MapLayersDisplayOptions />
96
+ <MapStyleDisplayOptions />
97
+ {/snippet}
98
+ {#snippet overlays()}
141
99
  <div class="pointer-events-none absolute bottom-0 left-0 z-10">
142
100
  <MapLegend />
143
101
  </div>
144
- <div class="absolute top-4 left-4 z-10">
145
- <div class="absolute z-10">
146
- <Menu>
147
- <MonitorsDisplayOptions />
148
- <EvStationsDisplayOptions />
149
- <MapLayersDisplayOptions />
150
- <MapStyleDisplayOptions />
151
- </Menu>
152
- </div>
153
- <div class="absolute left-16">
154
- <Search />
155
- </div>
156
- </div>
157
- </div>
158
- <div
159
- class={[
160
- "panel-containr w-full shrink-0 overflow-hidden",
161
- panelOpen ? "h-1/2 md:h-full md:w-1/3" : "md:w-0"
162
- ]}
163
- >
164
- <div
165
- class={[
166
- "panel-contet h-full duration-300 ease-in-out",
167
- panelOpen
168
- ? "translate-y-0 md:translate-x-0"
169
- : "translate-y-full md:translate-x-full md:translate-y-0"
170
- ]}
171
- >
172
- {@render children()}
102
+ <div class="absolute top-4 left-20 z-10">
103
+ <Search />
173
104
  </div>
174
- </div>
175
- </div>
105
+ {/snippet}
106
+ {@render children()}
107
+ </MapShell>
package/src/lib/index.ts CHANGED
@@ -55,6 +55,7 @@ export { hmsSmokeMapIntegration } from "./hms/hms-smoke-map-integration.svelte";
55
55
 
56
56
  // Components
57
57
  export { default as Map } from "./map/Map.svelte";
58
+ export { default as MapShell, type MapShellProps } from "./map/MapShell.svelte";
58
59
  export { default as Menu } from "./map/Menu.svelte";
59
60
  export {
60
61
  default as LoadScreen,
@@ -0,0 +1,146 @@
1
+ <script lang="ts" module>
2
+ import type { Snippet } from "svelte";
3
+ import type { SomeMapIntegration } from "$lib/map/integrations/types";
4
+
5
+ export interface MapShellProps {
6
+ /** Map integrations to register, e.g. [monitorsMapIntegration] */
7
+ integrations: Array<SomeMapIntegration>;
8
+ /**
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
11
+ * is true.
12
+ */
13
+ ready: boolean;
14
+ /** True when the routed detail panel (`children`) should be visible */
15
+ panelOpen: boolean;
16
+ /**
17
+ * Path prefixes that are part of this map's own routed panel (e.g.
18
+ * [`${basePath}/monitor/`]) — internal navigation to these should not
19
+ * trigger the escape-hatch full-page navigation below.
20
+ */
21
+ knownRoutes?: Array<string>;
22
+ /** Rendered inside the display-options menu toggle */
23
+ menu?: Snippet;
24
+ /** Freeform absolutely-positioned content over the map (legend, search, etc.) */
25
+ overlays?: Snippet;
26
+ /** The routed detail panel content */
27
+ children?: Snippet;
28
+ /**
29
+ * Base path to use for the sv-router escape-hatch's "known" root route.
30
+ * If provided, used directly instead of reading `basePath` from
31
+ * `useMonitorMapRouter()`. Only relevant when `routerEscapeHatch` is
32
+ * enabled.
33
+ */
34
+ basePath?: string;
35
+ /**
36
+ * Whether to install the sv-router escape-hatch (`pageshow`/`click`
37
+ * listeners that force a full-page navigation for links outside this
38
+ * map's own routes). Defaults to `true`, preserving the existing
39
+ * full-page-map behavior. When `true` and no `basePath` prop is given,
40
+ * `MapShell` falls back to reading `basePath` from
41
+ * `useMonitorMapRouter()`. Set to `false` to embed `MapShell` inside a
42
+ * host app with its own routing — this also skips calling
43
+ * `useMonitorMapRouter()` entirely, so no `provideMonitorMapRouter(...)`
44
+ * ancestor is required.
45
+ */
46
+ routerEscapeHatch?: boolean;
47
+ }
48
+ </script>
49
+
50
+ <script lang="ts">
51
+ import LoadScreen, { disable as disableLoadScreen } from "$lib/LoadScreen.svelte";
52
+ import Map from "$lib/map/Map.svelte";
53
+ import Menu from "$lib/map/Menu.svelte";
54
+ import { mapManager } from "$lib/map/map.svelte";
55
+ import { useMonitorMapRouter } from "$lib/router-context";
56
+
57
+ let {
58
+ integrations,
59
+ ready,
60
+ panelOpen,
61
+ knownRoutes = [],
62
+ menu,
63
+ overlays,
64
+ children,
65
+ basePath: providedBasePath,
66
+ routerEscapeHatch = true
67
+ }: MapShellProps = $props();
68
+
69
+ const basePath = providedBasePath ?? (routerEscapeHatch ? useMonitorMapRouter().basePath : "");
70
+ const TRANSITION_MS = 300;
71
+
72
+ $effect(() => {
73
+ if (mapManager.map && ready) {
74
+ mapManager.map.once("idle", () => disableLoadScreen());
75
+ }
76
+ });
77
+
78
+ $effect(() => {
79
+ if (panelOpen) {
80
+ // Container width snapped to open; resize after layout settles
81
+ requestAnimationFrame(() => mapManager.map?.resize());
82
+ } else {
83
+ // Container width snaps back after the transform transition ends
84
+ setTimeout(() => mapManager.map?.resize(), TRANSITION_MS);
85
+ }
86
+ });
87
+
88
+ /**
89
+ * HACK: Fix for escaping sv-router and allowing navigation to other pages,
90
+ * as well as navigating back
91
+ */
92
+ if (routerEscapeHatch) {
93
+ const rootPath = basePath || "/";
94
+
95
+ window.addEventListener("pageshow", (e) => {
96
+ if (e.persisted) window.location.reload();
97
+ });
98
+
99
+ document.addEventListener(
100
+ "click",
101
+ (e) => {
102
+ const anchor = e
103
+ .composedPath()
104
+ .find((el) => el instanceof HTMLAnchorElement) as HTMLAnchorElement;
105
+ if (!anchor) return;
106
+ const { pathname } = new URL(anchor.href);
107
+ const isKnown = pathname === rootPath || knownRoutes.some((r) => pathname.startsWith(r));
108
+ if (!isKnown) {
109
+ e.stopImmediatePropagation();
110
+ window.location.href = anchor.href;
111
+ }
112
+ },
113
+ { capture: true }
114
+ );
115
+ }
116
+ </script>
117
+
118
+ <div class="relative flex h-full w-full flex-col md:flex-row">
119
+ <LoadScreen />
120
+ <div class="relative flex-1 overflow-hidden">
121
+ <Map {integrations} />
122
+ {@render overlays?.()}
123
+ {#if menu}
124
+ <div class="absolute top-4 left-4 z-10">
125
+ <Menu>{@render menu()}</Menu>
126
+ </div>
127
+ {/if}
128
+ </div>
129
+ <div
130
+ class={[
131
+ "panel-containr w-full shrink-0 overflow-hidden",
132
+ panelOpen ? "h-1/2 md:h-full md:w-1/3" : "md:w-0"
133
+ ]}
134
+ >
135
+ <div
136
+ class={[
137
+ "panel-contet h-full duration-300 ease-in-out",
138
+ panelOpen
139
+ ? "translate-y-0 md:translate-x-0"
140
+ : "translate-y-full md:translate-x-full md:translate-y-0"
141
+ ]}
142
+ >
143
+ {@render children?.()}
144
+ </div>
145
+ </div>
146
+ </div>