create-honua-app 0.1.6 → 0.1.8
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/README.md +6 -7
- package/package.json +1 -1
- package/templates/react-ts/README.md +4 -0
- package/templates/react-ts/package.json +1 -1
- package/templates/react-ts/src/App.tsx +8 -1
- package/templates/react-ts/src/online-basemap.ts +84 -0
- package/templates/vanilla-ts/README.md +4 -0
- package/templates/vanilla-ts/package.json +1 -1
- package/templates/vanilla-ts/src/main.ts +17 -1
- package/templates/vanilla-ts/src/online-basemap.ts +84 -0
- package/templates.manifest.json +1 -1
package/README.md
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# create-honua-app
|
|
2
2
|
|
|
3
3
|
Scaffold a [Honua JavaScript SDK](https://github.com/honua-io/honua-sdk-js) map application — Vite + TypeScript,
|
|
4
|
-
|
|
4
|
+
running a map on the first `npm run dev`. These commands explicitly pin the SDK version documented here;
|
|
5
|
+
omit `--sdk-version` to follow the promoted release channel or this scaffold's certified fallback.
|
|
5
6
|
|
|
6
|
-
<!-- doc-run:
|
|
7
|
+
<!-- doc-run: run ready-url="http://localhost:5173/" -->
|
|
7
8
|
```bash
|
|
8
|
-
npm create honua-app@latest my-map
|
|
9
|
+
npm create honua-app@latest my-map -- --sdk-version 0.1.15 # x-release-please-version
|
|
9
10
|
cd my-map
|
|
10
11
|
npm install
|
|
11
12
|
npm run dev
|
|
@@ -27,9 +28,8 @@ create-honua-app [directory] [options]
|
|
|
27
28
|
|
|
28
29
|
With `npm create`, pass CLI options after `--`:
|
|
29
30
|
|
|
30
|
-
<!-- doc-run: blocked https://github.com/honua-io/honua-release/issues/423 -->
|
|
31
31
|
```bash
|
|
32
|
-
npm create honua-app@latest my-react-map -- --template react-ts
|
|
32
|
+
npm create honua-app@latest my-react-map -- --template react-ts --sdk-version 0.1.15 # x-release-please-version
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
## Which SDK version a scaffold pins
|
|
@@ -43,9 +43,8 @@ or if it names a prerelease or another line, or if the registry cannot be read,
|
|
|
43
43
|
version this release of `create-honua-app` ships with. The default path never pins a prerelease. To choose a version
|
|
44
44
|
yourself, pass `--sdk-version`:
|
|
45
45
|
|
|
46
|
-
<!-- doc-run: blocked https://github.com/honua-io/honua-release/issues/423 -->
|
|
47
46
|
```bash
|
|
48
|
-
npm create honua-app@latest my-pinned-map -- --sdk-version 0.1.
|
|
47
|
+
npm create honua-app@latest my-pinned-map -- --sdk-version 0.1.15 # x-release-please-version
|
|
49
48
|
```
|
|
50
49
|
|
|
51
50
|
## Templates
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-honua-app",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "Scaffold a Honua JavaScript SDK map application: Vite + TypeScript + MapLibre starters that connect and mount a source without hand-assembling peers",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Honua",
|
|
@@ -62,3 +62,7 @@ npm run build
|
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
The fixture data is synthetic demonstration data from the Honua SDK sample fixtures (Apache-2.0).
|
|
65
|
+
|
|
66
|
+
## Live basemap
|
|
67
|
+
|
|
68
|
+
The default fixture lane stays offline. When `VITE_HONUA_ENDPOINT` selects a live endpoint, the map uses keyless OpenFreeMap Positron (or Dark for the system theme) and keeps source attribution visible. Set `VITE_HONUA_BASEMAP_STYLE` to a custom/self-hosted style URL. A basemap asset failure leaves operational data and controls available with an actionable status. Keep the expanded source credits in screenshots and exports.
|
|
@@ -4,6 +4,7 @@ import { maplibreRenderer } from "@honua/sdk-js/runtime";
|
|
|
4
4
|
import * as maplibregl from "maplibre-gl";
|
|
5
5
|
import type { RefObject } from "react";
|
|
6
6
|
import { useEffect, useRef, useState } from "react";
|
|
7
|
+
import { mountSampleOnlineBasemap } from "./online-basemap.js";
|
|
7
8
|
|
|
8
9
|
import { FIXTURE_LAYER_PATH } from "./fixture-endpoint.js";
|
|
9
10
|
|
|
@@ -54,11 +55,17 @@ function useExternalMap(): { containerRef: RefObject<HTMLDivElement | null>; map
|
|
|
54
55
|
style: BASEMAP_STYLE,
|
|
55
56
|
center: INITIAL_VIEW.center,
|
|
56
57
|
zoom: INITIAL_VIEW.zoom,
|
|
57
|
-
attributionControl:
|
|
58
|
+
attributionControl: { compact: true },
|
|
58
59
|
});
|
|
60
|
+
const disposeBasemap = configuredEndpoint
|
|
61
|
+
? mountSampleOnlineBasemap(created, {
|
|
62
|
+
styleUrl: import.meta.env.VITE_HONUA_BASEMAP_STYLE?.trim() || undefined,
|
|
63
|
+
})
|
|
64
|
+
: () => {};
|
|
59
65
|
setMap(created);
|
|
60
66
|
return () => {
|
|
61
67
|
setMap(null);
|
|
68
|
+
disposeBasemap();
|
|
62
69
|
created.remove();
|
|
63
70
|
};
|
|
64
71
|
}, []);
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import * as runtime from "@honua/sdk-js/runtime";
|
|
2
|
+
|
|
3
|
+
type HonuaOnlineBasemapTheme = "positron" | "liberty" | "dark";
|
|
4
|
+
interface OnlineBasemapBinding {
|
|
5
|
+
activate(options: { theme: HonuaOnlineBasemapTheme; styleUrl?: string }): Promise<boolean>;
|
|
6
|
+
dispose(): void;
|
|
7
|
+
}
|
|
8
|
+
type OnlineBasemapConstructor = new (
|
|
9
|
+
map: MapLibreMap,
|
|
10
|
+
options: { onError: (message: string) => void; onReady: () => void },
|
|
11
|
+
) => OnlineBasemapBinding;
|
|
12
|
+
import type { Map as MapLibreMap } from "maplibre-gl";
|
|
13
|
+
|
|
14
|
+
/** Explicit live-lane enhancement. Local fixture lanes never call this helper. */
|
|
15
|
+
export function mountSampleOnlineBasemap(
|
|
16
|
+
map: MapLibreMap,
|
|
17
|
+
options: {
|
|
18
|
+
readonly styleUrl?: string;
|
|
19
|
+
readonly lightTheme?: Exclude<HonuaOnlineBasemapTheme, "dark">;
|
|
20
|
+
readonly styleEnvironmentVariable?: string;
|
|
21
|
+
} = {},
|
|
22
|
+
): () => void {
|
|
23
|
+
const notice = document.createElement("div");
|
|
24
|
+
notice.setAttribute("role", "status");
|
|
25
|
+
notice.dataset.basemapStatus = "loading";
|
|
26
|
+
notice.style.cssText =
|
|
27
|
+
"position:absolute;left:12px;right:12px;bottom:40px;z-index:5;padding:8px 12px;background:Canvas;color:CanvasText;border:1px solid currentColor;border-radius:6px;font:13px system-ui;pointer-events:none;display:none";
|
|
28
|
+
map.getContainer().append(notice);
|
|
29
|
+
// Older published SDKs can still run the local fixture lane. A live map
|
|
30
|
+
// explicitly reports the required upgrade instead of failing module loading.
|
|
31
|
+
const Binding = (runtime as unknown as { readonly HonuaOnlineBasemapBinding?: OnlineBasemapConstructor })
|
|
32
|
+
.HonuaOnlineBasemapBinding;
|
|
33
|
+
if (typeof Binding !== "function") {
|
|
34
|
+
notice.textContent =
|
|
35
|
+
"Online basemaps require a newer @honua/sdk-js release with HonuaOnlineBasemapBinding. Upgrade @honua/sdk-js after the basemap SDK release is published, then reload. Operational data remains usable.";
|
|
36
|
+
notice.dataset.basemapStatus = "error";
|
|
37
|
+
notice.style.display = "block";
|
|
38
|
+
return () => notice.remove();
|
|
39
|
+
}
|
|
40
|
+
const binding = new Binding(map, {
|
|
41
|
+
onError: (message) => {
|
|
42
|
+
notice.textContent = `${message} Set ${options.styleEnvironmentVariable ?? "VITE_HONUA_BASEMAP_STYLE"} to your custom/self-hosted style URL.`;
|
|
43
|
+
notice.dataset.basemapStatus = "error";
|
|
44
|
+
notice.style.display = "block";
|
|
45
|
+
},
|
|
46
|
+
onReady: () => {
|
|
47
|
+
notice.textContent = "";
|
|
48
|
+
notice.dataset.basemapStatus = "ready";
|
|
49
|
+
notice.style.display = "none";
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
const preferred = matchMedia("(prefers-color-scheme: dark)");
|
|
53
|
+
let pendingTheme: HonuaOnlineBasemapTheme | undefined;
|
|
54
|
+
const flush = () => {
|
|
55
|
+
if (!pendingTheme || !map.isStyleLoaded()) return;
|
|
56
|
+
const theme = pendingTheme;
|
|
57
|
+
pendingTheme = undefined;
|
|
58
|
+
void binding.activate({ theme, styleUrl: options.styleUrl });
|
|
59
|
+
};
|
|
60
|
+
const update = () => {
|
|
61
|
+
const selected = document.documentElement.dataset.theme;
|
|
62
|
+
const dark = selected === "dark" || (!selected && preferred.matches);
|
|
63
|
+
pendingTheme = dark ? "dark" : (options.lightTheme ?? "positron");
|
|
64
|
+
flush();
|
|
65
|
+
};
|
|
66
|
+
const observer = new MutationObserver(update);
|
|
67
|
+
observer.observe(document.documentElement, { attributes: true, attributeFilter: ["data-theme"] });
|
|
68
|
+
preferred.addEventListener("change", update);
|
|
69
|
+
// Theme changes during tile/sprite loading must survive until the renderer
|
|
70
|
+
// is ready again. Consume only the latest pending theme, once per update.
|
|
71
|
+
map.on("idle", flush);
|
|
72
|
+
map.once("load", flush);
|
|
73
|
+
update();
|
|
74
|
+
const dispose = () => {
|
|
75
|
+
map.off("load", flush);
|
|
76
|
+
map.off("idle", flush);
|
|
77
|
+
observer.disconnect();
|
|
78
|
+
preferred.removeEventListener("change", update);
|
|
79
|
+
binding.dispose();
|
|
80
|
+
notice.remove();
|
|
81
|
+
};
|
|
82
|
+
// Dispose before remove(), while the renderer's style resources still exist.
|
|
83
|
+
return dispose;
|
|
84
|
+
}
|
|
@@ -59,3 +59,7 @@ npm run build
|
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
The fixture data is synthetic demonstration data from the Honua SDK sample fixtures (Apache-2.0).
|
|
62
|
+
|
|
63
|
+
## Live basemap
|
|
64
|
+
|
|
65
|
+
The default fixture lane stays offline. When `VITE_HONUA_ENDPOINT` selects a live endpoint, the map uses keyless OpenFreeMap Positron (or Dark for the system theme) and keeps source attribution visible. Set `VITE_HONUA_BASEMAP_STYLE` to a custom/self-hosted style URL. A basemap asset failure leaves operational data and controls available with an actionable status. Keep the expanded source credits in screenshots and exports.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { mountSampleOnlineBasemap } from "./online-basemap.js";
|
|
1
2
|
import "./maplibre-worker.js";
|
|
2
3
|
import "maplibre-gl/dist/maplibre-gl.css";
|
|
3
4
|
|
|
@@ -16,7 +17,7 @@ const BASEMAP_STYLE = {
|
|
|
16
17
|
layers: [{ id: "background", type: "background", paint: { "background-color": "#0e1a17" } }],
|
|
17
18
|
};
|
|
18
19
|
|
|
19
|
-
const MAP_OPTIONS = { center: [-157.873, 21.2985], zoom: 11.4, attributionControl:
|
|
20
|
+
const MAP_OPTIONS = { center: [-157.873, 21.2985], zoom: 11.4, attributionControl: { compact: true } };
|
|
20
21
|
|
|
21
22
|
/** Bounded row budget. Honua never mounts a truncated result silently. */
|
|
22
23
|
const MAX_FEATURES = 250;
|
|
@@ -99,6 +100,21 @@ async function run(): Promise<void> {
|
|
|
99
100
|
rendererOptions: { mapOptions: MAP_OPTIONS },
|
|
100
101
|
});
|
|
101
102
|
await mounted.ready;
|
|
103
|
+
const rawMap = mounted.raw("maplibre");
|
|
104
|
+
const disposeBasemap =
|
|
105
|
+
configuredEndpoint && rawMap
|
|
106
|
+
? mountSampleOnlineBasemap(rawMap as maplibregl.Map, {
|
|
107
|
+
styleUrl: import.meta.env.VITE_HONUA_BASEMAP_STYLE?.trim() || undefined,
|
|
108
|
+
})
|
|
109
|
+
: () => {};
|
|
110
|
+
window.addEventListener(
|
|
111
|
+
"pagehide",
|
|
112
|
+
() => {
|
|
113
|
+
disposeBasemap();
|
|
114
|
+
void honua.dispose();
|
|
115
|
+
},
|
|
116
|
+
{ once: true },
|
|
117
|
+
);
|
|
102
118
|
stage("mount", "done", "mounted");
|
|
103
119
|
element("status").textContent = "The accepted plan is mounted. Every stage above ran through the public SDK API.";
|
|
104
120
|
} catch (error) {
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import * as runtime from "@honua/sdk-js/runtime";
|
|
2
|
+
|
|
3
|
+
type HonuaOnlineBasemapTheme = "positron" | "liberty" | "dark";
|
|
4
|
+
interface OnlineBasemapBinding {
|
|
5
|
+
activate(options: { theme: HonuaOnlineBasemapTheme; styleUrl?: string }): Promise<boolean>;
|
|
6
|
+
dispose(): void;
|
|
7
|
+
}
|
|
8
|
+
type OnlineBasemapConstructor = new (
|
|
9
|
+
map: MapLibreMap,
|
|
10
|
+
options: { onError: (message: string) => void; onReady: () => void },
|
|
11
|
+
) => OnlineBasemapBinding;
|
|
12
|
+
import type { Map as MapLibreMap } from "maplibre-gl";
|
|
13
|
+
|
|
14
|
+
/** Explicit live-lane enhancement. Local fixture lanes never call this helper. */
|
|
15
|
+
export function mountSampleOnlineBasemap(
|
|
16
|
+
map: MapLibreMap,
|
|
17
|
+
options: {
|
|
18
|
+
readonly styleUrl?: string;
|
|
19
|
+
readonly lightTheme?: Exclude<HonuaOnlineBasemapTheme, "dark">;
|
|
20
|
+
readonly styleEnvironmentVariable?: string;
|
|
21
|
+
} = {},
|
|
22
|
+
): () => void {
|
|
23
|
+
const notice = document.createElement("div");
|
|
24
|
+
notice.setAttribute("role", "status");
|
|
25
|
+
notice.dataset.basemapStatus = "loading";
|
|
26
|
+
notice.style.cssText =
|
|
27
|
+
"position:absolute;left:12px;right:12px;bottom:40px;z-index:5;padding:8px 12px;background:Canvas;color:CanvasText;border:1px solid currentColor;border-radius:6px;font:13px system-ui;pointer-events:none;display:none";
|
|
28
|
+
map.getContainer().append(notice);
|
|
29
|
+
// Older published SDKs can still run the local fixture lane. A live map
|
|
30
|
+
// explicitly reports the required upgrade instead of failing module loading.
|
|
31
|
+
const Binding = (runtime as unknown as { readonly HonuaOnlineBasemapBinding?: OnlineBasemapConstructor })
|
|
32
|
+
.HonuaOnlineBasemapBinding;
|
|
33
|
+
if (typeof Binding !== "function") {
|
|
34
|
+
notice.textContent =
|
|
35
|
+
"Online basemaps require a newer @honua/sdk-js release with HonuaOnlineBasemapBinding. Upgrade @honua/sdk-js after the basemap SDK release is published, then reload. Operational data remains usable.";
|
|
36
|
+
notice.dataset.basemapStatus = "error";
|
|
37
|
+
notice.style.display = "block";
|
|
38
|
+
return () => notice.remove();
|
|
39
|
+
}
|
|
40
|
+
const binding = new Binding(map, {
|
|
41
|
+
onError: (message) => {
|
|
42
|
+
notice.textContent = `${message} Set ${options.styleEnvironmentVariable ?? "VITE_HONUA_BASEMAP_STYLE"} to your custom/self-hosted style URL.`;
|
|
43
|
+
notice.dataset.basemapStatus = "error";
|
|
44
|
+
notice.style.display = "block";
|
|
45
|
+
},
|
|
46
|
+
onReady: () => {
|
|
47
|
+
notice.textContent = "";
|
|
48
|
+
notice.dataset.basemapStatus = "ready";
|
|
49
|
+
notice.style.display = "none";
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
const preferred = matchMedia("(prefers-color-scheme: dark)");
|
|
53
|
+
let pendingTheme: HonuaOnlineBasemapTheme | undefined;
|
|
54
|
+
const flush = () => {
|
|
55
|
+
if (!pendingTheme || !map.isStyleLoaded()) return;
|
|
56
|
+
const theme = pendingTheme;
|
|
57
|
+
pendingTheme = undefined;
|
|
58
|
+
void binding.activate({ theme, styleUrl: options.styleUrl });
|
|
59
|
+
};
|
|
60
|
+
const update = () => {
|
|
61
|
+
const selected = document.documentElement.dataset.theme;
|
|
62
|
+
const dark = selected === "dark" || (!selected && preferred.matches);
|
|
63
|
+
pendingTheme = dark ? "dark" : (options.lightTheme ?? "positron");
|
|
64
|
+
flush();
|
|
65
|
+
};
|
|
66
|
+
const observer = new MutationObserver(update);
|
|
67
|
+
observer.observe(document.documentElement, { attributes: true, attributeFilter: ["data-theme"] });
|
|
68
|
+
preferred.addEventListener("change", update);
|
|
69
|
+
// Theme changes during tile/sprite loading must survive until the renderer
|
|
70
|
+
// is ready again. Consume only the latest pending theme, once per update.
|
|
71
|
+
map.on("idle", flush);
|
|
72
|
+
map.once("load", flush);
|
|
73
|
+
update();
|
|
74
|
+
const dispose = () => {
|
|
75
|
+
map.off("load", flush);
|
|
76
|
+
map.off("idle", flush);
|
|
77
|
+
observer.disconnect();
|
|
78
|
+
preferred.removeEventListener("change", update);
|
|
79
|
+
binding.dispose();
|
|
80
|
+
notice.remove();
|
|
81
|
+
};
|
|
82
|
+
// Dispose before remove(), while the renderer's style resources still exist.
|
|
83
|
+
return dispose;
|
|
84
|
+
}
|