@mailwoman/react 7.5.0 → 7.6.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/common/PresetChips.tsx +4 -1
- package/index.ts +28 -0
- package/map/BackendControl.tsx +39 -0
- package/map/CompareToggle.tsx +81 -0
- package/map/DemoControls.tsx +173 -0
- package/map/DemoMap.tsx +98 -0
- package/map/GeocoderDemo.tsx +178 -0
- package/map/OverlayLayers.tsx +46 -0
- package/map/PlaceAutocomplete.tsx +69 -0
- package/map/PlaceMarker.tsx +40 -0
- package/map/ResolvedPlaceLayers.tsx +63 -0
- package/map/ResultCamera.tsx +60 -0
- package/map/ResultOverlay.tsx +61 -0
- package/map/ResultPanel.tsx +84 -0
- package/map/VersionPicker.tsx +62 -0
- package/map/geometry.ts +135 -0
- package/map/index.ts +73 -0
- package/map/place-render.ts +157 -0
- package/map/types.ts +207 -0
- package/map/useCompareState.ts +45 -0
- package/map/useDemoGeocode.ts +67 -0
- package/map/useMapPlaceRender.ts +21 -0
- package/map/usePlaceAutocomplete.ts +195 -0
- package/out/common/PresetChips.d.ts +3 -1
- package/out/common/PresetChips.d.ts.map +1 -1
- package/out/common/PresetChips.js +2 -2
- package/out/common/PresetChips.js.map +1 -1
- package/out/index.d.ts +3 -0
- package/out/index.d.ts.map +1 -1
- package/out/index.js +2 -0
- package/out/index.js.map +1 -1
- package/out/map/BackendControl.d.ts +24 -0
- package/out/map/BackendControl.d.ts.map +1 -0
- package/out/map/BackendControl.js +6 -0
- package/out/map/BackendControl.js.map +1 -0
- package/out/map/CompareToggle.d.ts +35 -0
- package/out/map/CompareToggle.d.ts.map +1 -0
- package/out/map/CompareToggle.js +9 -0
- package/out/map/CompareToggle.js.map +1 -0
- package/out/map/DemoControls.d.ts +44 -0
- package/out/map/DemoControls.d.ts.map +1 -0
- package/out/map/DemoControls.js +28 -0
- package/out/map/DemoControls.js.map +1 -0
- package/out/map/DemoMap.d.ts +59 -0
- package/out/map/DemoMap.d.ts.map +1 -0
- package/out/map/DemoMap.js +12 -0
- package/out/map/DemoMap.js.map +1 -0
- package/out/map/GeocoderDemo.d.ts +47 -0
- package/out/map/GeocoderDemo.d.ts.map +1 -0
- package/out/map/GeocoderDemo.js +73 -0
- package/out/map/GeocoderDemo.js.map +1 -0
- package/out/map/OverlayLayers.d.ts +23 -0
- package/out/map/OverlayLayers.d.ts.map +1 -0
- package/out/map/OverlayLayers.js +27 -0
- package/out/map/OverlayLayers.js.map +1 -0
- package/out/map/PlaceAutocomplete.d.ts +34 -0
- package/out/map/PlaceAutocomplete.d.ts.map +1 -0
- package/out/map/PlaceAutocomplete.js +9 -0
- package/out/map/PlaceAutocomplete.js.map +1 -0
- package/out/map/PlaceMarker.d.ts +27 -0
- package/out/map/PlaceMarker.d.ts.map +1 -0
- package/out/map/PlaceMarker.js +9 -0
- package/out/map/PlaceMarker.js.map +1 -0
- package/out/map/ResolvedPlaceLayers.d.ts +34 -0
- package/out/map/ResolvedPlaceLayers.d.ts.map +1 -0
- package/out/map/ResolvedPlaceLayers.js +11 -0
- package/out/map/ResolvedPlaceLayers.js.map +1 -0
- package/out/map/ResultCamera.d.ts +34 -0
- package/out/map/ResultCamera.d.ts.map +1 -0
- package/out/map/ResultCamera.js +43 -0
- package/out/map/ResultCamera.js.map +1 -0
- package/out/map/ResultOverlay.d.ts +34 -0
- package/out/map/ResultOverlay.d.ts.map +1 -0
- package/out/map/ResultOverlay.js +18 -0
- package/out/map/ResultOverlay.js.map +1 -0
- package/out/map/ResultPanel.d.ts +34 -0
- package/out/map/ResultPanel.d.ts.map +1 -0
- package/out/map/ResultPanel.js +12 -0
- package/out/map/ResultPanel.js.map +1 -0
- package/out/map/VersionPicker.d.ts +30 -0
- package/out/map/VersionPicker.d.ts.map +1 -0
- package/out/map/VersionPicker.js +8 -0
- package/out/map/VersionPicker.js.map +1 -0
- package/out/map/geometry.d.ts +55 -0
- package/out/map/geometry.d.ts.map +1 -0
- package/out/map/geometry.js +99 -0
- package/out/map/geometry.js.map +1 -0
- package/out/map/index.d.ts +52 -0
- package/out/map/index.d.ts.map +1 -0
- package/out/map/index.js +36 -0
- package/out/map/index.js.map +1 -0
- package/out/map/place-render.d.ts +85 -0
- package/out/map/place-render.d.ts.map +1 -0
- package/out/map/place-render.js +98 -0
- package/out/map/place-render.js.map +1 -0
- package/out/map/types.d.ts +193 -0
- package/out/map/types.d.ts.map +1 -0
- package/out/map/types.js +18 -0
- package/out/map/types.js.map +1 -0
- package/out/map/useCompareState.d.ts +25 -0
- package/out/map/useCompareState.d.ts.map +1 -0
- package/out/map/useCompareState.js +27 -0
- package/out/map/useCompareState.js.map +1 -0
- package/out/map/useDemoGeocode.d.ts +36 -0
- package/out/map/useDemoGeocode.d.ts.map +1 -0
- package/out/map/useDemoGeocode.js +44 -0
- package/out/map/useDemoGeocode.js.map +1 -0
- package/out/map/useMapPlaceRender.d.ts +15 -0
- package/out/map/useMapPlaceRender.d.ts.map +1 -0
- package/out/map/useMapPlaceRender.js +18 -0
- package/out/map/useMapPlaceRender.js.map +1 -0
- package/out/map/usePlaceAutocomplete.d.ts +61 -0
- package/out/map/usePlaceAutocomplete.d.ts.map +1 -0
- package/out/map/usePlaceAutocomplete.js +122 -0
- package/out/map/usePlaceAutocomplete.js.map +1 -0
- package/out/pipeline/QueryForm.d.ts +6 -2
- package/out/pipeline/QueryForm.d.ts.map +1 -1
- package/out/pipeline/QueryForm.js +2 -2
- package/out/pipeline/QueryForm.js.map +1 -1
- package/out/runtime/useDemoRuntime.d.ts +113 -0
- package/out/runtime/useDemoRuntime.d.ts.map +1 -0
- package/out/runtime/useDemoRuntime.js +135 -0
- package/out/runtime/useDemoRuntime.js.map +1 -0
- package/package.json +27 -6
- package/pipeline/QueryForm.tsx +17 -2
- package/runtime/useDemoRuntime.ts +245 -0
- package/styles.css +145 -0
- package/vitest.node.config.ts +20 -0
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* `QueryForm` — the address input + submit button for the pipeline explorer. Shows a spinner while
|
|
7
7
|
* parsing. Presentational; `onSubmit` fires on form submission.
|
|
8
8
|
*/
|
|
9
|
-
import type { ReactNode } from "react";
|
|
9
|
+
import type { InputHTMLAttributes, KeyboardEvent, ReactNode } from "react";
|
|
10
10
|
export interface QueryFormProps {
|
|
11
11
|
value: string;
|
|
12
12
|
onChange: (value: string) => void;
|
|
@@ -14,6 +14,10 @@ export interface QueryFormProps {
|
|
|
14
14
|
disabled?: boolean;
|
|
15
15
|
busy?: boolean;
|
|
16
16
|
placeholder?: string;
|
|
17
|
+
/** Keydown on the input — the seam a combobox (the demo's place-autocomplete) needs for arrow/Enter/Esc nav. */
|
|
18
|
+
onKeyDown?: (event: KeyboardEvent<HTMLInputElement>) => void;
|
|
19
|
+
/** Escape hatch for extra `<input>` attributes (aria-combobox props, `autoComplete`, …). Merged last. */
|
|
20
|
+
inputProps?: InputHTMLAttributes<HTMLInputElement>;
|
|
17
21
|
}
|
|
18
|
-
export declare function QueryForm({ value, onChange, onSubmit, disabled, busy, placeholder }: QueryFormProps): ReactNode;
|
|
22
|
+
export declare function QueryForm({ value, onChange, onSubmit, disabled, busy, placeholder, onKeyDown, inputProps, }: QueryFormProps): ReactNode;
|
|
19
23
|
//# sourceMappingURL=QueryForm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryForm.d.ts","sourceRoot":"","sources":["../../pipeline/QueryForm.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"QueryForm.d.ts","sourceRoot":"","sources":["../../pipeline/QueryForm.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAI1E,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gHAAgH;IAChH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAA;IAC5D,yGAAyG;IACzG,UAAU,CAAC,EAAE,mBAAmB,CAAC,gBAAgB,CAAC,CAAA;CAClD;AAED,wBAAgB,SAAS,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,WAAW,EACX,SAAS,EACT,UAAU,GACV,EAAE,cAAc,GAAG,SAAS,CA+B5B"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { LoadingIndicator } from "../common/LoadingIndicator.js";
|
|
3
|
-
export function QueryForm({ value, onChange, onSubmit, disabled, busy, placeholder }) {
|
|
3
|
+
export function QueryForm({ value, onChange, onSubmit, disabled, busy, placeholder, onKeyDown, inputProps, }) {
|
|
4
4
|
return (_jsxs("form", { className: "mw-field", onSubmit: (e) => {
|
|
5
5
|
e.preventDefault();
|
|
6
6
|
onSubmit();
|
|
7
|
-
}, children: [_jsx("label", { htmlFor: "mw-pipeline-input", children: "Address" }), _jsx("input", { id: "mw-pipeline-input", type: "text", value: value, onChange: (e) => onChange(e.target.value), disabled: disabled, placeholder: placeholder }), _jsx("button", { type: "submit", disabled: disabled || busy, children: busy ? (_jsxs(_Fragment, { children: [_jsx(LoadingIndicator, { mode: "spinner", size: "small" }), " Parsing\u2026"] })) : ("Parse + resolve") })] }));
|
|
7
|
+
}, children: [_jsx("label", { htmlFor: "mw-pipeline-input", children: "Address" }), _jsx("input", { id: "mw-pipeline-input", type: "text", value: value, onChange: (e) => onChange(e.target.value), disabled: disabled, placeholder: placeholder, onKeyDown: onKeyDown, ...inputProps }), _jsx("button", { type: "submit", disabled: disabled || busy, children: busy ? (_jsxs(_Fragment, { children: [_jsx(LoadingIndicator, { mode: "spinner", size: "small" }), " Parsing\u2026"] })) : ("Parse + resolve") })] }));
|
|
8
8
|
}
|
|
9
9
|
//# sourceMappingURL=QueryForm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QueryForm.js","sourceRoot":"","sources":["../../pipeline/QueryForm.tsx"],"names":[],"mappings":";AAWA,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAAgC,CAAA;
|
|
1
|
+
{"version":3,"file":"QueryForm.js","sourceRoot":"","sources":["../../pipeline/QueryForm.tsx"],"names":[],"mappings":";AAWA,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAAgC,CAAA;AAejE,MAAM,UAAU,SAAS,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,WAAW,EACX,SAAS,EACT,UAAU,GACM;IAChB,OAAO,CACN,gBACC,SAAS,EAAC,UAAU,EACpB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;YACf,CAAC,CAAC,cAAc,EAAE,CAAA;YAClB,QAAQ,EAAE,CAAA;QACX,CAAC,aAED,gBAAO,OAAO,EAAC,mBAAmB,wBAAgB,EAClD,gBACC,EAAE,EAAC,mBAAmB,EACtB,IAAI,EAAC,MAAM,EACX,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACzC,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,SAAS,KAChB,UAAU,GACb,EACF,iBAAQ,IAAI,EAAC,QAAQ,EAAC,QAAQ,EAAE,QAAQ,IAAI,IAAI,YAC9C,IAAI,CAAC,CAAC,CAAC,CACP,8BACC,KAAC,gBAAgB,IAAC,IAAI,EAAC,SAAS,EAAC,IAAI,EAAC,OAAO,GAAG,sBAC9C,CACH,CAAC,CAAC,CAAC,CACH,iBAAiB,CACjB,GACO,IACH,CACP,CAAA;AACF,CAAC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* `useDemoRuntime` — the headless load-orchestration hook shared by every mailwoman demo surface (the
|
|
7
|
+
* inline doc-embeds via `DemoEmbed`, and the geocoder map page). It owns the version-selection state
|
|
8
|
+
* machine, the per-version load SEQUENCING, cancellation, and the ready / loading / error state — but
|
|
9
|
+
* NOTHING model- or map-specific. The actual asset fetchers (the ONNX classifier factory, the httpvfs
|
|
10
|
+
* WOF opener, the FST fetch, the releases.json fetch) are INJECTED by the host as async functions, so
|
|
11
|
+
* this module imports only React: no `onnxruntime-web`, no `sql.js-httpvfs`, no `maplibre-gl`, no
|
|
12
|
+
* `fetch`-specific plumbing. That keeps it node-import-safe and root-exportable from
|
|
13
|
+
* `@mailwoman/react` — the exact seam `PipelineRuntime` established, generalized to the loader itself.
|
|
14
|
+
*
|
|
15
|
+
* The hook is generic over `TAssets` (the opaque bundle the host's `loadAssets` returns — classifier,
|
|
16
|
+
* FST, WOF lookup, calibrator, …) and `TRelease` (the host's release-manifest entry). The package
|
|
17
|
+
* never inspects either; it just holds, reveals, and re-loads them across version/backend switches.
|
|
18
|
+
*/
|
|
19
|
+
/** The minimal contract a release-manifest entry must satisfy. Hosts extend this with their own fields. */
|
|
20
|
+
export interface DemoReleaseBase {
|
|
21
|
+
/** The version tag this entry describes (matched against `selectedVersion`). */
|
|
22
|
+
version: string;
|
|
23
|
+
/** Optional display label a version picker shows; falls back to `version`. */
|
|
24
|
+
label?: string;
|
|
25
|
+
}
|
|
26
|
+
/** The releases manifest the host fetches — the default version plus the selectable release entries. */
|
|
27
|
+
export interface DemoManifest<TRelease extends DemoReleaseBase = DemoReleaseBase> {
|
|
28
|
+
/** The version selected on first load (before the user picks another). */
|
|
29
|
+
defaultVersion: string;
|
|
30
|
+
/** Every selectable release. */
|
|
31
|
+
releases: TRelease[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The progress channel handed to the host's `loadAssets`. The host reports load progress + the resolved backend + the
|
|
35
|
+
* staged step labels/index THROUGH these setters (all no-op once the load is superseded/aborted), while the hook owns
|
|
36
|
+
* the terminal state (revealing the assets + clearing progress on success, surfacing the error on failure).
|
|
37
|
+
*/
|
|
38
|
+
export interface DemoAssetsLoadContext {
|
|
39
|
+
/** Aborts when this load is superseded (version/backend switch) or the provider unmounts. */
|
|
40
|
+
signal: AbortSignal;
|
|
41
|
+
/** Whether the host should force the CPU/WASM backend (opt out of WebGPU) for this load. */
|
|
42
|
+
forceWASM: boolean;
|
|
43
|
+
/** Set the human-readable progress line (e.g. `Loading v7 model (~28 MB)…`). */
|
|
44
|
+
setProgress: (progress: string) => void;
|
|
45
|
+
/** Set the staged-loader step labels (e.g. `["Loading classifier", "Loading FST gazetteer"]`). */
|
|
46
|
+
setStepLabels: (labels: string[]) => void;
|
|
47
|
+
/** Advance the staged-loader step index (0-based). */
|
|
48
|
+
setStepIndex: (index: number) => void;
|
|
49
|
+
/** Report the backend the neural runtime resolved to (e.g. `webgpu (27 MB int8)`). */
|
|
50
|
+
setBackend: (backend: string) => void;
|
|
51
|
+
}
|
|
52
|
+
/** The injected loaders the hook orchestrates. Nothing here is model- or map-aware — the host owns all that. */
|
|
53
|
+
export interface DemoRuntimeConfig<TAssets, TRelease extends DemoReleaseBase = DemoReleaseBase> {
|
|
54
|
+
/**
|
|
55
|
+
* Fetch + normalize the releases manifest. Returns `null` when no manifest is available (the demo then shows nothing
|
|
56
|
+
* selectable). Rejecting surfaces `errorMessage`. Runs once on mount.
|
|
57
|
+
*/
|
|
58
|
+
loadManifest: (signal: AbortSignal) => Promise<DemoManifest<TRelease> | null>;
|
|
59
|
+
/**
|
|
60
|
+
* Load the full asset bundle for one release — the classifier, FST, WOF lookup, calibrator, whatever the host needs.
|
|
61
|
+
* Runs on every version or `forceWASM` change. Report progress via `ctx`; return the bundle. Rejecting surfaces
|
|
62
|
+
* `errorMessage`. Bail early when `ctx.signal.aborted` — the hook discards a superseded result regardless.
|
|
63
|
+
*/
|
|
64
|
+
loadAssets: (release: TRelease, ctx: DemoAssetsLoadContext) => Promise<TAssets>;
|
|
65
|
+
/** The progress line shown before the manifest arrives. @default "Loading releases…" */
|
|
66
|
+
initialProgress?: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The state `useDemoRuntime` produces — the load-orchestration state a demo surface renders + re-projects.
|
|
70
|
+
*
|
|
71
|
+
* NAMING (phase 4): this is the LOADER STATE, deliberately distinct from {@link DemoRuntime} (the injected runtime
|
|
72
|
+
* contract `<GeocoderDemo>` consumes). The two were same-stem before (`UseDemoRuntime` vs `DemoRuntime`); phase 4
|
|
73
|
+
* disambiguates by renaming the loader-state type to `DemoLoaderState`. A host builds a {@link DemoRuntime} by pairing
|
|
74
|
+
* this loader state (assets + backend + version) with the map surface (style, overlays, bias, parse) — see the map
|
|
75
|
+
* subpath's `DemoRuntime`.
|
|
76
|
+
*/
|
|
77
|
+
export interface DemoLoaderState<TAssets, TRelease extends DemoReleaseBase = DemoReleaseBase> {
|
|
78
|
+
/** The releases manifest, once fetched. */
|
|
79
|
+
manifest: DemoManifest<TRelease> | null;
|
|
80
|
+
/** The currently-selected version, or `null` before the manifest resolves. */
|
|
81
|
+
selectedVersion: string | null;
|
|
82
|
+
/** The release entry matching `selectedVersion` (convenience over `manifest.releases.find`). */
|
|
83
|
+
selectedRelease: TRelease | null;
|
|
84
|
+
/** The loaded asset bundle for the selected version, or `null` while (re)loading. */
|
|
85
|
+
assets: TAssets | null;
|
|
86
|
+
/** Whether the asset bundle is loaded and ready to use. */
|
|
87
|
+
ready: boolean;
|
|
88
|
+
/** Human-readable load progress (`""` when idle/ready). */
|
|
89
|
+
loadingProgress: string;
|
|
90
|
+
/** Staged-loader step index (0-based; `-1` before the first step). */
|
|
91
|
+
loadingStepIndex: number;
|
|
92
|
+
/** Staged-loader step labels. */
|
|
93
|
+
loadingStepLabels: string[];
|
|
94
|
+
/** A load error (manifest or asset), distinct from any per-parse error a consumer tracks separately. */
|
|
95
|
+
errorMessage: string | null;
|
|
96
|
+
/** The backend the neural runtime resolved to (e.g. `webgpu (27 MB int8)`), or `""` before it's known. */
|
|
97
|
+
activeBackend: string;
|
|
98
|
+
/** Whether the CPU/WASM backend is currently forced. */
|
|
99
|
+
forceWASM: boolean;
|
|
100
|
+
/** Switch to a different version (clears any error, then reloads the asset bundle). */
|
|
101
|
+
selectVersion: (version: string) => void;
|
|
102
|
+
/** Force (or unforce) the CPU/WASM backend — reloads the asset bundle. */
|
|
103
|
+
setForceWASM: (forceWASM: boolean) => void;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Drive the shared version → asset-bundle load state machine over a host-injected loader.
|
|
107
|
+
*
|
|
108
|
+
* Sequence: on mount `loadManifest` runs and its `defaultVersion` becomes the selection; each version (or `forceWASM`)
|
|
109
|
+
* change reloads the bundle via `loadAssets`, the previous load aborted first. The assets are revealed ATOMICALLY when
|
|
110
|
+
* `loadAssets` resolves (so `ready` flips exactly once per load), and consumers gate on `ready`.
|
|
111
|
+
*/
|
|
112
|
+
export declare function useDemoRuntime<TAssets, TRelease extends DemoReleaseBase = DemoReleaseBase>(config: DemoRuntimeConfig<TAssets, TRelease>): DemoLoaderState<TAssets, TRelease>;
|
|
113
|
+
//# sourceMappingURL=useDemoRuntime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDemoRuntime.d.ts","sourceRoot":"","sources":["../../runtime/useDemoRuntime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,2GAA2G;AAC3G,MAAM,WAAW,eAAe;IAC/B,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAA;IACf,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAA;CACd;AAED,wGAAwG;AACxG,MAAM,WAAW,YAAY,CAAC,QAAQ,SAAS,eAAe,GAAG,eAAe;IAC/E,0EAA0E;IAC1E,cAAc,EAAE,MAAM,CAAA;IACtB,gCAAgC;IAChC,QAAQ,EAAE,QAAQ,EAAE,CAAA;CACpB;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACrC,6FAA6F;IAC7F,MAAM,EAAE,WAAW,CAAA;IACnB,4FAA4F;IAC5F,SAAS,EAAE,OAAO,CAAA;IAClB,gFAAgF;IAChF,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,kGAAkG;IAClG,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;IACzC,sDAAsD;IACtD,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,sFAAsF;IACtF,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CACrC;AAED,gHAAgH;AAChH,MAAM,WAAW,iBAAiB,CAAC,OAAO,EAAE,QAAQ,SAAS,eAAe,GAAG,eAAe;IAC7F;;;OAGG;IACH,YAAY,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAA;IAC7E;;;;OAIG;IACH,UAAU,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,qBAAqB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAC/E,wFAAwF;IACxF,eAAe,CAAC,EAAE,MAAM,CAAA;CACxB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,eAAe,CAAC,OAAO,EAAE,QAAQ,SAAS,eAAe,GAAG,eAAe;IAC3F,2CAA2C;IAC3C,QAAQ,EAAE,YAAY,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAA;IACvC,8EAA8E;IAC9E,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,gGAAgG;IAChG,eAAe,EAAE,QAAQ,GAAG,IAAI,CAAA;IAChC,qFAAqF;IACrF,MAAM,EAAE,OAAO,GAAG,IAAI,CAAA;IACtB,2DAA2D;IAC3D,KAAK,EAAE,OAAO,CAAA;IACd,2DAA2D;IAC3D,eAAe,EAAE,MAAM,CAAA;IACvB,sEAAsE;IACtE,gBAAgB,EAAE,MAAM,CAAA;IACxB,iCAAiC;IACjC,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,wGAAwG;IACxG,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,0GAA0G;IAC1G,aAAa,EAAE,MAAM,CAAA;IACrB,wDAAwD;IACxD,SAAS,EAAE,OAAO,CAAA;IAClB,uFAAuF;IACvF,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACxC,0EAA0E;IAC1E,YAAY,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAA;CAC1C;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,QAAQ,SAAS,eAAe,GAAG,eAAe,EACzF,MAAM,EAAE,iBAAiB,CAAC,OAAO,EAAE,QAAQ,CAAC,GAC1C,eAAe,CAAC,OAAO,EAAE,QAAQ,CAAC,CA2HpC"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* `useDemoRuntime` — the headless load-orchestration hook shared by every mailwoman demo surface (the
|
|
7
|
+
* inline doc-embeds via `DemoEmbed`, and the geocoder map page). It owns the version-selection state
|
|
8
|
+
* machine, the per-version load SEQUENCING, cancellation, and the ready / loading / error state — but
|
|
9
|
+
* NOTHING model- or map-specific. The actual asset fetchers (the ONNX classifier factory, the httpvfs
|
|
10
|
+
* WOF opener, the FST fetch, the releases.json fetch) are INJECTED by the host as async functions, so
|
|
11
|
+
* this module imports only React: no `onnxruntime-web`, no `sql.js-httpvfs`, no `maplibre-gl`, no
|
|
12
|
+
* `fetch`-specific plumbing. That keeps it node-import-safe and root-exportable from
|
|
13
|
+
* `@mailwoman/react` — the exact seam `PipelineRuntime` established, generalized to the loader itself.
|
|
14
|
+
*
|
|
15
|
+
* The hook is generic over `TAssets` (the opaque bundle the host's `loadAssets` returns — classifier,
|
|
16
|
+
* FST, WOF lookup, calibrator, …) and `TRelease` (the host's release-manifest entry). The package
|
|
17
|
+
* never inspects either; it just holds, reveals, and re-loads them across version/backend switches.
|
|
18
|
+
*/
|
|
19
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
20
|
+
/**
|
|
21
|
+
* Drive the shared version → asset-bundle load state machine over a host-injected loader.
|
|
22
|
+
*
|
|
23
|
+
* Sequence: on mount `loadManifest` runs and its `defaultVersion` becomes the selection; each version (or `forceWASM`)
|
|
24
|
+
* change reloads the bundle via `loadAssets`, the previous load aborted first. The assets are revealed ATOMICALLY when
|
|
25
|
+
* `loadAssets` resolves (so `ready` flips exactly once per load), and consumers gate on `ready`.
|
|
26
|
+
*/
|
|
27
|
+
export function useDemoRuntime(config) {
|
|
28
|
+
const { initialProgress = "Loading releases…" } = config;
|
|
29
|
+
const [manifest, setManifest] = useState(null);
|
|
30
|
+
const [selectedVersion, setSelectedVersion] = useState(null);
|
|
31
|
+
const [assets, setAssets] = useState(null);
|
|
32
|
+
const [loadingProgress, setLoadingProgress] = useState(initialProgress);
|
|
33
|
+
const [loadingStepIndex, setLoadingStepIndex] = useState(-1);
|
|
34
|
+
const [loadingStepLabels, setLoadingStepLabels] = useState([]);
|
|
35
|
+
const [errorMessage, setErrorMessage] = useState(null);
|
|
36
|
+
const [activeBackend, setActiveBackend] = useState("");
|
|
37
|
+
const [forceWASM, setForceWASMState] = useState(false);
|
|
38
|
+
// Latest-ref the injected loaders: a host that re-creates them each render (an inline arrow) must NOT retrigger the
|
|
39
|
+
// load effects, which key ONLY on version/backend. The effects read `.current` at run time.
|
|
40
|
+
const loadManifestRef = useRef(config.loadManifest);
|
|
41
|
+
loadManifestRef.current = config.loadManifest;
|
|
42
|
+
const loadAssetsRef = useRef(config.loadAssets);
|
|
43
|
+
loadAssetsRef.current = config.loadAssets;
|
|
44
|
+
// Latest manifest for the version-load effect, so it can resolve the release WITHOUT depending on `manifest`
|
|
45
|
+
// identity — which would double-fire the load the instant the manifest first arrives (the selection transition
|
|
46
|
+
// null → defaultVersion already fires it once).
|
|
47
|
+
const manifestRef = useRef(null);
|
|
48
|
+
manifestRef.current = manifest;
|
|
49
|
+
// Mount: fetch the manifest, then select the default version.
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
const controller = new AbortController();
|
|
52
|
+
void (async () => {
|
|
53
|
+
try {
|
|
54
|
+
const data = await loadManifestRef.current(controller.signal);
|
|
55
|
+
if (controller.signal.aborted)
|
|
56
|
+
return;
|
|
57
|
+
if (data) {
|
|
58
|
+
setManifest(data);
|
|
59
|
+
setSelectedVersion(data.defaultVersion);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (controller.signal.aborted)
|
|
64
|
+
return;
|
|
65
|
+
setErrorMessage(error instanceof Error ? error.message : String(error));
|
|
66
|
+
}
|
|
67
|
+
})();
|
|
68
|
+
return () => controller.abort();
|
|
69
|
+
}, []);
|
|
70
|
+
// Load the per-version asset bundle when the version (or the backend force) changes.
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
if (!selectedVersion)
|
|
73
|
+
return;
|
|
74
|
+
const release = manifestRef.current?.releases.find((r) => r.version === selectedVersion) ?? null;
|
|
75
|
+
if (!release)
|
|
76
|
+
return;
|
|
77
|
+
const controller = new AbortController();
|
|
78
|
+
const { signal } = controller;
|
|
79
|
+
const guard = (fn) => {
|
|
80
|
+
if (!signal.aborted) {
|
|
81
|
+
fn();
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
void (async () => {
|
|
85
|
+
try {
|
|
86
|
+
setAssets(null);
|
|
87
|
+
setLoadingStepIndex(-1);
|
|
88
|
+
setLoadingStepLabels([]);
|
|
89
|
+
setActiveBackend("");
|
|
90
|
+
const ctx = {
|
|
91
|
+
signal,
|
|
92
|
+
forceWASM,
|
|
93
|
+
setProgress: (progress) => guard(() => setLoadingProgress(progress)),
|
|
94
|
+
setStepLabels: (labels) => guard(() => setLoadingStepLabels(labels)),
|
|
95
|
+
setStepIndex: (index) => guard(() => setLoadingStepIndex(index)),
|
|
96
|
+
setBackend: (backend) => guard(() => setActiveBackend(backend)),
|
|
97
|
+
};
|
|
98
|
+
const loaded = await loadAssetsRef.current(release, ctx);
|
|
99
|
+
if (signal.aborted)
|
|
100
|
+
return;
|
|
101
|
+
setAssets(loaded);
|
|
102
|
+
setLoadingProgress("");
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
if (signal.aborted)
|
|
106
|
+
return;
|
|
107
|
+
setErrorMessage(error instanceof Error ? error.message : String(error));
|
|
108
|
+
setLoadingProgress("");
|
|
109
|
+
}
|
|
110
|
+
})();
|
|
111
|
+
return () => controller.abort();
|
|
112
|
+
}, [selectedVersion, forceWASM]);
|
|
113
|
+
const selectVersion = useCallback((version) => {
|
|
114
|
+
setSelectedVersion(version);
|
|
115
|
+
setErrorMessage(null);
|
|
116
|
+
}, []);
|
|
117
|
+
const setForceWASM = useCallback((next) => setForceWASMState(next), []);
|
|
118
|
+
const selectedRelease = useMemo(() => manifest?.releases.find((r) => r.version === selectedVersion) ?? null, [manifest, selectedVersion]);
|
|
119
|
+
return {
|
|
120
|
+
manifest,
|
|
121
|
+
selectedVersion,
|
|
122
|
+
selectedRelease,
|
|
123
|
+
assets,
|
|
124
|
+
ready: assets !== null,
|
|
125
|
+
loadingProgress,
|
|
126
|
+
loadingStepIndex,
|
|
127
|
+
loadingStepLabels,
|
|
128
|
+
errorMessage,
|
|
129
|
+
activeBackend,
|
|
130
|
+
forceWASM,
|
|
131
|
+
selectVersion,
|
|
132
|
+
setForceWASM,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=useDemoRuntime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDemoRuntime.js","sourceRoot":"","sources":["../../runtime/useDemoRuntime.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mailwoman/react",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.6.0",
|
|
4
4
|
"description": "React components + headless hooks for mailwoman — parse/geocode/POI explorers, Storybook-tested, Docusaurus-independent.",
|
|
5
5
|
"license": "AGPL-3.0-only OR LicenseRef-Commercial",
|
|
6
6
|
"repository": {
|
|
@@ -39,6 +39,10 @@
|
|
|
39
39
|
".": {
|
|
40
40
|
"types": "./out/index.d.ts",
|
|
41
41
|
"default": "./out/index.js"
|
|
42
|
+
},
|
|
43
|
+
"./map": {
|
|
44
|
+
"types": "./out/map/index.d.ts",
|
|
45
|
+
"default": "./out/map/index.js"
|
|
42
46
|
}
|
|
43
47
|
},
|
|
44
48
|
"publishConfig": {
|
|
@@ -49,18 +53,23 @@
|
|
|
49
53
|
".": {
|
|
50
54
|
"types": "./out/index.d.ts",
|
|
51
55
|
"default": "./out/index.js"
|
|
56
|
+
},
|
|
57
|
+
"./map": {
|
|
58
|
+
"types": "./out/map/index.d.ts",
|
|
59
|
+
"default": "./out/map/index.js"
|
|
52
60
|
}
|
|
53
61
|
}
|
|
54
62
|
},
|
|
55
63
|
"scripts": {
|
|
56
64
|
"storybook": "storybook dev -p 6007 --no-open",
|
|
57
65
|
"build-storybook": "storybook build",
|
|
58
|
-
"test:browser": "vitest run --config vitest.config.ts"
|
|
66
|
+
"test:browser": "vitest run --config vitest.config.ts",
|
|
67
|
+
"test:node": "vitest run --config vitest.node.config.ts"
|
|
59
68
|
},
|
|
60
69
|
"dependencies": {
|
|
61
|
-
"@mailwoman/kind-classifier": "7.
|
|
62
|
-
"@mailwoman/poi-taxonomy": "7.
|
|
63
|
-
"@mailwoman/query-shape": "7.
|
|
70
|
+
"@mailwoman/kind-classifier": "7.6.0",
|
|
71
|
+
"@mailwoman/poi-taxonomy": "7.6.0",
|
|
72
|
+
"@mailwoman/query-shape": "7.6.0"
|
|
64
73
|
},
|
|
65
74
|
"devDependencies": {
|
|
66
75
|
"@storybook/addon-docs": "^10.5.2",
|
|
@@ -70,15 +79,27 @@
|
|
|
70
79
|
"@vitejs/plugin-react": "^6.0.3",
|
|
71
80
|
"@vitest/browser": "4.1.10",
|
|
72
81
|
"@vitest/browser-playwright": "4.1.10",
|
|
82
|
+
"maplibre-gl": "^5.24.0",
|
|
73
83
|
"playwright": "^1.61.1",
|
|
74
84
|
"react": "^19.2.7",
|
|
75
85
|
"react-dom": "^19.2.7",
|
|
86
|
+
"react-map-gl": "^8.1.1",
|
|
76
87
|
"storybook": "^10.5.2",
|
|
77
88
|
"vite": "^8.1.5",
|
|
78
89
|
"vitest": "4.1.10"
|
|
79
90
|
},
|
|
80
91
|
"peerDependencies": {
|
|
92
|
+
"maplibre-gl": ">=5",
|
|
81
93
|
"react": ">=18",
|
|
82
|
-
"react-dom": ">=18"
|
|
94
|
+
"react-dom": ">=18",
|
|
95
|
+
"react-map-gl": ">=8"
|
|
96
|
+
},
|
|
97
|
+
"peerDependenciesMeta": {
|
|
98
|
+
"maplibre-gl": {
|
|
99
|
+
"optional": true
|
|
100
|
+
},
|
|
101
|
+
"react-map-gl": {
|
|
102
|
+
"optional": true
|
|
103
|
+
}
|
|
83
104
|
}
|
|
84
105
|
}
|
package/pipeline/QueryForm.tsx
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* parsing. Presentational; `onSubmit` fires on form submission.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import type { ReactNode } from "react"
|
|
10
|
+
import type { InputHTMLAttributes, KeyboardEvent, ReactNode } from "react"
|
|
11
11
|
|
|
12
12
|
import { LoadingIndicator } from "../common/LoadingIndicator.tsx"
|
|
13
13
|
|
|
@@ -18,9 +18,22 @@ export interface QueryFormProps {
|
|
|
18
18
|
disabled?: boolean
|
|
19
19
|
busy?: boolean
|
|
20
20
|
placeholder?: string
|
|
21
|
+
/** Keydown on the input — the seam a combobox (the demo's place-autocomplete) needs for arrow/Enter/Esc nav. */
|
|
22
|
+
onKeyDown?: (event: KeyboardEvent<HTMLInputElement>) => void
|
|
23
|
+
/** Escape hatch for extra `<input>` attributes (aria-combobox props, `autoComplete`, …). Merged last. */
|
|
24
|
+
inputProps?: InputHTMLAttributes<HTMLInputElement>
|
|
21
25
|
}
|
|
22
26
|
|
|
23
|
-
export function QueryForm({
|
|
27
|
+
export function QueryForm({
|
|
28
|
+
value,
|
|
29
|
+
onChange,
|
|
30
|
+
onSubmit,
|
|
31
|
+
disabled,
|
|
32
|
+
busy,
|
|
33
|
+
placeholder,
|
|
34
|
+
onKeyDown,
|
|
35
|
+
inputProps,
|
|
36
|
+
}: QueryFormProps): ReactNode {
|
|
24
37
|
return (
|
|
25
38
|
<form
|
|
26
39
|
className="mw-field"
|
|
@@ -37,6 +50,8 @@ export function QueryForm({ value, onChange, onSubmit, disabled, busy, placehold
|
|
|
37
50
|
onChange={(e) => onChange(e.target.value)}
|
|
38
51
|
disabled={disabled}
|
|
39
52
|
placeholder={placeholder}
|
|
53
|
+
onKeyDown={onKeyDown}
|
|
54
|
+
{...inputProps}
|
|
40
55
|
/>
|
|
41
56
|
<button type="submit" disabled={disabled || busy}>
|
|
42
57
|
{busy ? (
|