@skyvexsoftware/stratos-sdk 0.22.1 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useTheme.d.ts +7 -0
- package/dist/hooks/useTheme.js +23 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/ui/index.d.ts +2 -0
- package/dist/ui/index.js +1 -0
- package/dist/ui/stratos-map-labels.d.ts +8 -0
- package/dist/ui/stratos-map-labels.js +35 -0
- package/dist/ui/stratos-map.d.ts +19 -0
- package/dist/ui/stratos-map.js +81 -0
- package/package.json +13 -1
package/dist/hooks/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export { useVaApi } from "./useVaApi";
|
|
|
11
11
|
export { useShellConfig } from "./useShellConfig";
|
|
12
12
|
export { useShellNavigation } from "./useShellNavigation";
|
|
13
13
|
export { useShellToast } from "./useShellToast";
|
|
14
|
+
export { useTheme } from "./useTheme";
|
|
14
15
|
export { useSocket, useSimulatorData, useProtocolUrl, useNotifications, useSystemMetrics, } from "./useSimulatorData";
|
|
15
16
|
export { SOCKET_EVENTS } from "../shared-types/socket-events";
|
|
16
17
|
export type { ConnectionState, NotificationPayload, ProtocolUrlPayload, SimulatorDataPayload, SimulatorStatusPayload, SocketEventName, SystemMetricsPayload, } from "../shared-types/socket-events";
|
package/dist/hooks/index.js
CHANGED
|
@@ -11,6 +11,7 @@ export { useVaApi } from "./useVaApi";
|
|
|
11
11
|
export { useShellConfig } from "./useShellConfig";
|
|
12
12
|
export { useShellNavigation } from "./useShellNavigation";
|
|
13
13
|
export { useShellToast } from "./useShellToast";
|
|
14
|
+
export { useTheme } from "./useTheme";
|
|
14
15
|
export { useSocket, useSimulatorData, useProtocolUrl, useNotifications, useSystemMetrics, } from "./useSimulatorData";
|
|
15
16
|
// Socket.io event catalog — re-exported from shared-types for convenience
|
|
16
17
|
export { SOCKET_EVENTS } from "../shared-types/socket-events";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The theme Stratos is showing, `"light"` or `"dark"` (with "system" already
|
|
3
|
+
* resolved), and a re-render whenever it changes. Use it for anything the
|
|
4
|
+
* CSS theme variables can't reach, such as a map style or a logo.
|
|
5
|
+
*/
|
|
6
|
+
export declare function useTheme(): "light" | "dark";
|
|
7
|
+
//# sourceMappingURL=useTheme.d.ts.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useSyncExternalStore } from "react";
|
|
2
|
+
// The shell marks dark mode with the "dark" class on <html>, so watching that
|
|
3
|
+
// one attribute follows every way the theme changes (Settings, "system" mode
|
|
4
|
+
// following the OS, the dev footer).
|
|
5
|
+
function subscribe(onChange) {
|
|
6
|
+
const observer = new MutationObserver(onChange);
|
|
7
|
+
observer.observe(document.documentElement, {
|
|
8
|
+
attributes: true,
|
|
9
|
+
attributeFilter: ["class"],
|
|
10
|
+
});
|
|
11
|
+
return () => observer.disconnect();
|
|
12
|
+
}
|
|
13
|
+
function getSnapshot() {
|
|
14
|
+
return document.documentElement.classList.contains("dark") ? "dark" : "light";
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The theme Stratos is showing, `"light"` or `"dark"` (with "system" already
|
|
18
|
+
* resolved), and a re-render whenever it changes. Use it for anything the
|
|
19
|
+
* CSS theme variables can't reach, such as a map style or a logo.
|
|
20
|
+
*/
|
|
21
|
+
export function useTheme() {
|
|
22
|
+
return useSyncExternalStore(subscribe, getSnapshot);
|
|
23
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -33,11 +33,14 @@ export { useVaApi } from "./hooks/useVaApi";
|
|
|
33
33
|
export { useShellConfig } from "./hooks/useShellConfig";
|
|
34
34
|
export { useShellNavigation } from "./hooks/useShellNavigation";
|
|
35
35
|
export { useShellToast } from "./hooks/useShellToast";
|
|
36
|
+
export { useTheme } from "./hooks/useTheme";
|
|
36
37
|
export { useSocket, useSimulatorData, useProtocolUrl, useNotifications, useSystemMetrics, } from "./hooks/useSimulatorData";
|
|
37
38
|
export { SOCKET_EVENTS } from "./shared-types/socket-events";
|
|
38
39
|
export type { AutoStartConfirmPayload, ConnectionState, LogEntryPayload, NotificationPayload, ProtocolUrlPayload, SimulatorDataPayload, SimulatorStatusPayload, SocketEventName, SoundPayload, SystemMetricsPayload, } from "./shared-types/socket-events";
|
|
39
40
|
export type { PluginDialogKind, PluginDialogSelectOption, PluginDialogSpec, PluginDialogResult, PluginDialogClosePayload, } from "./shared-types/plugin-dialogs";
|
|
40
41
|
export { AlertDialog, AlertDialogPortal, AlertDialogOverlay, AlertDialogTrigger, AlertDialogContent, AlertDialogHeader, AlertDialogFooter, AlertDialogTitle, AlertDialogDescription, AlertDialogAction, AlertDialogCancel, Badge, badgeVariants, Button, buttonVariants, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Combobox, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Input, Label, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, RadioGroup, RadioGroupItem, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Slider, Switch, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "./ui";
|
|
41
42
|
export type { BadgeProps, ButtonProps, ComboboxOption, ComboboxProps, } from "./ui";
|
|
43
|
+
export { StratosMap } from "./ui/stratos-map";
|
|
44
|
+
export type { StratosMapProps } from "./ui/stratos-map";
|
|
42
45
|
export { cn } from "./utils/cn";
|
|
43
46
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -23,11 +23,13 @@ export { useVaApi } from "./hooks/useVaApi";
|
|
|
23
23
|
export { useShellConfig } from "./hooks/useShellConfig";
|
|
24
24
|
export { useShellNavigation } from "./hooks/useShellNavigation";
|
|
25
25
|
export { useShellToast } from "./hooks/useShellToast";
|
|
26
|
+
export { useTheme } from "./hooks/useTheme";
|
|
26
27
|
export { useSocket, useSimulatorData, useProtocolUrl, useNotifications, useSystemMetrics, } from "./hooks/useSimulatorData";
|
|
27
28
|
// ── Socket.io Event Catalog ──────────────────────────────────────────────
|
|
28
29
|
export { SOCKET_EVENTS } from "./shared-types/socket-events";
|
|
29
30
|
// ── UI Primitives ──────────────────────────────────────────────────────
|
|
30
31
|
export { AlertDialog, AlertDialogPortal, AlertDialogOverlay, AlertDialogTrigger, AlertDialogContent, AlertDialogHeader, AlertDialogFooter, AlertDialogTitle, AlertDialogDescription, AlertDialogAction, AlertDialogCancel, Badge, badgeVariants, Button, buttonVariants, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Combobox, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Input, Label, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, RadioGroup, RadioGroupItem, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Slider, Switch, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "./ui";
|
|
32
|
+
export { StratosMap } from "./ui/stratos-map";
|
|
31
33
|
// ── Icons (internal) ──────────────────────────────────────────────────
|
|
32
34
|
// Kept at runtime for plugin bundles that still read them; out of the
|
|
33
35
|
// published types. Plugins import from lucide-react or use DynamicIcon.
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ export { Switch } from "./switch";
|
|
|
16
16
|
export { Textarea } from "./textarea";
|
|
17
17
|
export { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, } from "./select";
|
|
18
18
|
export { Separator } from "./separator";
|
|
19
|
+
export { StratosMap } from "./stratos-map";
|
|
20
|
+
export type { StratosMapProps } from "./stratos-map";
|
|
19
21
|
export { Tabs, TabsContent, TabsList, TabsTrigger } from "./tabs";
|
|
20
22
|
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "./tooltip";
|
|
21
23
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/ui/index.js
CHANGED
|
@@ -13,5 +13,6 @@ export { Switch } from "./switch";
|
|
|
13
13
|
export { Textarea } from "./textarea";
|
|
14
14
|
export { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, } from "./select";
|
|
15
15
|
export { Separator } from "./separator";
|
|
16
|
+
export { StratosMap } from "./stratos-map";
|
|
16
17
|
export { Tabs, TabsContent, TabsList, TabsTrigger } from "./tabs";
|
|
17
18
|
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "./tooltip";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type maplibregl from "maplibre-gl";
|
|
2
|
+
/**
|
|
3
|
+
* The Stratos look on top of the base style: English place names (else the
|
|
4
|
+
* local name), no village, hamlet, highway shield or minor road labels, and
|
|
5
|
+
* softer halos.
|
|
6
|
+
*/
|
|
7
|
+
export declare function applyStratosLabels(map: maplibregl.Map): void;
|
|
8
|
+
//# sourceMappingURL=stratos-map-labels.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Stratos look on top of the base style: English place names (else the
|
|
3
|
+
* local name), no village, hamlet, highway shield or minor road labels, and
|
|
4
|
+
* softer halos.
|
|
5
|
+
*/
|
|
6
|
+
export function applyStratosLabels(map) {
|
|
7
|
+
const layers = map.getStyle()?.layers;
|
|
8
|
+
if (!layers)
|
|
9
|
+
return;
|
|
10
|
+
for (const layer of layers) {
|
|
11
|
+
if (layer.type === "symbol" && layer.layout?.["text-field"] !== undefined) {
|
|
12
|
+
map.setLayoutProperty(layer.id, "text-field", [
|
|
13
|
+
"coalesce",
|
|
14
|
+
["get", "name:en"],
|
|
15
|
+
["get", "name"],
|
|
16
|
+
]);
|
|
17
|
+
}
|
|
18
|
+
const id = layer.id.toLowerCase();
|
|
19
|
+
if (id.includes("place-village") ||
|
|
20
|
+
id.includes("place-hamlet") ||
|
|
21
|
+
id.includes("highway-shield") ||
|
|
22
|
+
id.includes("road_label_minor")) {
|
|
23
|
+
map.setLayoutProperty(layer.id, "visibility", "none");
|
|
24
|
+
}
|
|
25
|
+
if (layer.type === "symbol") {
|
|
26
|
+
try {
|
|
27
|
+
map.setPaintProperty(layer.id, "text-halo-width", 1.5);
|
|
28
|
+
map.setPaintProperty(layer.id, "text-halo-blur", 1);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// Some symbol layers don't take these.
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Ref } from "react";
|
|
2
|
+
import type { MapProps, MapRef } from "react-map-gl/maplibre";
|
|
3
|
+
export type StratosMapProps = Omit<MapProps, "mapStyle" | "attributionControl"> & {
|
|
4
|
+
/** Your own style in the light theme (URL or object). Defaults to Stratos's. */
|
|
5
|
+
lightStyle?: MapProps["mapStyle"];
|
|
6
|
+
/** Your own style in the dark theme (URL or object). Defaults to Stratos's. */
|
|
7
|
+
darkStyle?: MapProps["mapStyle"];
|
|
8
|
+
ref?: Ref<MapRef>;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* react-map-gl's `Map` (every prop and child passes through) in Stratos's
|
|
12
|
+
* map style, light or dark to match the theme, with English labels and the
|
|
13
|
+
* attribution tucked behind its info button. It switches style when the theme changes, and
|
|
14
|
+
* carries `data-stratos-map-drawing` until it has drawn the style showing:
|
|
15
|
+
* the dev footer's Screenshot waits for that, so both shots show the right
|
|
16
|
+
* map.
|
|
17
|
+
*/
|
|
18
|
+
export declare function StratosMap({ lightStyle, darkStyle, onLoad, ref, ...props }: StratosMapProps): import("react").JSX.Element;
|
|
19
|
+
//# sourceMappingURL=stratos-map.d.ts.map
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useLayoutEffect, useRef, useState } from "react";
|
|
3
|
+
import { Map } from "react-map-gl/maplibre";
|
|
4
|
+
import { useTheme } from "../hooks/useTheme";
|
|
5
|
+
import { applyStratosLabels } from "./stratos-map-labels";
|
|
6
|
+
const LIGHT_STYLE = "https://tiles.openfreemap.org/styles/positron";
|
|
7
|
+
const DARK_STYLE = "https://tiles.openfreemap.org/styles/dark";
|
|
8
|
+
// MapLibre draws the attribution open the moment the map is made and only
|
|
9
|
+
// tucks it away later, so keep it hidden until the map has loaded and it's
|
|
10
|
+
// tucked away, then fade it in.
|
|
11
|
+
const STYLES = `
|
|
12
|
+
[data-stratos-map]:not([data-attribution-ready]) .maplibregl-ctrl-attrib {
|
|
13
|
+
opacity: 0;
|
|
14
|
+
pointer-events: none;
|
|
15
|
+
}
|
|
16
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
17
|
+
[data-stratos-map] .maplibregl-ctrl-attrib {
|
|
18
|
+
transition: opacity 200ms ease-out;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
`;
|
|
22
|
+
const ATTRIBUTION = { compact: true };
|
|
23
|
+
const isStratosStyle = (style) => style === LIGHT_STYLE || style === DARK_STYLE;
|
|
24
|
+
/**
|
|
25
|
+
* react-map-gl's `Map` (every prop and child passes through) in Stratos's
|
|
26
|
+
* map style, light or dark to match the theme, with English labels and the
|
|
27
|
+
* attribution tucked behind its info button. It switches style when the theme changes, and
|
|
28
|
+
* carries `data-stratos-map-drawing` until it has drawn the style showing:
|
|
29
|
+
* the dev footer's Screenshot waits for that, so both shots show the right
|
|
30
|
+
* map.
|
|
31
|
+
*/
|
|
32
|
+
export function StratosMap({ lightStyle = LIGHT_STYLE, darkStyle = DARK_STYLE, onLoad, ref, ...props }) {
|
|
33
|
+
const mapStyle = useTheme() === "dark" ? darkStyle : lightStyle;
|
|
34
|
+
const [loaded, setLoaded] = useState(false);
|
|
35
|
+
const [drawing, setDrawing] = useState(true);
|
|
36
|
+
// "style" while a style URL loads (a diffed switch reports idle on the old
|
|
37
|
+
// style meanwhile), "draw" until the map is next idle, null when drawn.
|
|
38
|
+
const phase = useRef("draw");
|
|
39
|
+
const shownStyle = useRef(mapStyle);
|
|
40
|
+
useLayoutEffect(() => {
|
|
41
|
+
if (shownStyle.current === mapStyle)
|
|
42
|
+
return;
|
|
43
|
+
shownStyle.current = mapStyle;
|
|
44
|
+
phase.current = typeof mapStyle === "string" ? "style" : "draw";
|
|
45
|
+
setDrawing(true);
|
|
46
|
+
}, [mapStyle]);
|
|
47
|
+
const handleLoad = (event) => {
|
|
48
|
+
const map = event.target;
|
|
49
|
+
// Tucked away behind its info button, not open until the first drag.
|
|
50
|
+
map
|
|
51
|
+
.getContainer()
|
|
52
|
+
.querySelector(".maplibregl-ctrl-attrib.maplibregl-compact-show")
|
|
53
|
+
?.classList.remove("maplibregl-compact-show");
|
|
54
|
+
setLoaded(true);
|
|
55
|
+
// Stratos's label tweaks, again after each theme switch reloads the style.
|
|
56
|
+
if (isStratosStyle(shownStyle.current))
|
|
57
|
+
applyStratosLabels(map);
|
|
58
|
+
map.on("style.load", () => {
|
|
59
|
+
if (isStratosStyle(shownStyle.current))
|
|
60
|
+
applyStratosLabels(map);
|
|
61
|
+
});
|
|
62
|
+
map.on("styledata", () => {
|
|
63
|
+
if (phase.current === "style")
|
|
64
|
+
phase.current = "draw";
|
|
65
|
+
});
|
|
66
|
+
map.on("idle", () => {
|
|
67
|
+
if (phase.current !== "draw")
|
|
68
|
+
return;
|
|
69
|
+
phase.current = null;
|
|
70
|
+
setDrawing(false);
|
|
71
|
+
});
|
|
72
|
+
// Then the plugin's own onLoad, if it passed one.
|
|
73
|
+
onLoad?.(event);
|
|
74
|
+
};
|
|
75
|
+
return (
|
|
76
|
+
// No box of its own: the map sizes against the parent as it would bare.
|
|
77
|
+
_jsxs("div", { "data-stratos-map": "", "data-attribution-ready": loaded ? "" : undefined, "data-stratos-map-drawing": drawing ? "" : undefined, style: { display: "contents" }, children: [_jsx("style", { href: "stratos-map", precedence: "default", children: STYLES }), _jsx(Map, { ...props, ref: ref, mapStyle: mapStyle,
|
|
78
|
+
// Reload Stratos's style from scratch on a theme switch, so style.load
|
|
79
|
+
// fires and the label tweaks go back on (a diff would undo them).
|
|
80
|
+
styleDiffing: isStratosStyle(mapStyle) ? false : props.styleDiffing, attributionControl: ATTRIBUTION, onLoad: handleLoad })] }));
|
|
81
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skyvexsoftware/stratos-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "Plugin SDK for Stratos — types, hooks, and UI components",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Skyvex Software Pty Ltd",
|
|
@@ -107,10 +107,20 @@
|
|
|
107
107
|
"class-variance-authority": "^0.7.0",
|
|
108
108
|
"cmdk": "^1.0.0",
|
|
109
109
|
"lucide-react": ">=0.300.0",
|
|
110
|
+
"maplibre-gl": "^5.0.0",
|
|
110
111
|
"react": "^19.0.0",
|
|
112
|
+
"react-map-gl": "^8.0.0",
|
|
111
113
|
"socket.io-client": "^4.0.0",
|
|
112
114
|
"vite": "^7.0.0"
|
|
113
115
|
},
|
|
116
|
+
"peerDependenciesMeta": {
|
|
117
|
+
"maplibre-gl": {
|
|
118
|
+
"optional": true
|
|
119
|
+
},
|
|
120
|
+
"react-map-gl": {
|
|
121
|
+
"optional": true
|
|
122
|
+
}
|
|
123
|
+
},
|
|
114
124
|
"dependencies": {
|
|
115
125
|
"axios": "^1.17.0",
|
|
116
126
|
"clsx": "^2.1.1",
|
|
@@ -135,7 +145,9 @@
|
|
|
135
145
|
"class-variance-authority": "^0.7.1",
|
|
136
146
|
"cmdk": "^1.1.1",
|
|
137
147
|
"lucide-react": "^0.577.0",
|
|
148
|
+
"maplibre-gl": "5.19.0",
|
|
138
149
|
"react-dom": "^19.0.0",
|
|
150
|
+
"react-map-gl": "8.1.1",
|
|
139
151
|
"socket.io-client": "^4.8.3",
|
|
140
152
|
"typescript": "^5.8.3",
|
|
141
153
|
"vite": "^7.3.1"
|