@mailwoman/react 9.4.0 → 10.0.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/lib/common/About.tsx +87 -71
- package/lib/common/index.ts +22 -0
- package/lib/index.ts +4 -99
- package/lib/map/BackendControl.tsx +7 -3
- package/lib/map/CompareToggle.tsx +3 -2
- package/lib/map/Geocoder.tsx +48 -28
- package/lib/map/GeocoderControls.tsx +258 -99
- package/lib/map/MapChipRow.tsx +77 -0
- package/lib/map/MapCompass.tsx +77 -0
- package/lib/map/MapControlStack.tsx +98 -0
- package/lib/map/MapFooter.tsx +115 -0
- package/lib/map/MapProgressBar.tsx +58 -0
- package/lib/map/MapSearchBar.tsx +68 -0
- package/lib/map/MapSheet.tsx +62 -0
- package/lib/map/index.ts +19 -0
- package/lib/map/types.ts +18 -4
- package/lib/map/useMapBearing.ts +56 -0
- package/lib/map/useMapLabelPick.ts +123 -0
- package/lib/pipeline/index.ts +36 -0
- package/lib/pipeline/useParsePipeline.ts +29 -18
- package/lib/poi/index.ts +39 -0
- package/lib/runtime/index.ts +16 -0
- package/out/common/About.d.ts +13 -4
- package/out/common/About.d.ts.map +1 -1
- package/out/common/About.js +5 -2
- package/out/common/About.js.map +1 -1
- package/out/common/index.d.ts +22 -0
- package/out/common/index.d.ts.map +1 -0
- package/out/common/index.js +15 -0
- package/out/common/index.js.map +1 -0
- package/out/index.d.ts +4 -59
- package/out/index.d.ts.map +1 -1
- package/out/index.js +4 -36
- package/out/index.js.map +1 -1
- package/out/map/BackendControl.d.ts.map +1 -1
- package/out/map/BackendControl.js +1 -1
- package/out/map/BackendControl.js.map +1 -1
- package/out/map/CompareToggle.d.ts.map +1 -1
- package/out/map/CompareToggle.js +1 -1
- package/out/map/CompareToggle.js.map +1 -1
- package/out/map/Geocoder.d.ts +11 -1
- package/out/map/Geocoder.d.ts.map +1 -1
- package/out/map/Geocoder.js +26 -26
- package/out/map/Geocoder.js.map +1 -1
- package/out/map/GeocoderControls.d.ts +29 -11
- package/out/map/GeocoderControls.d.ts.map +1 -1
- package/out/map/GeocoderControls.js +65 -16
- package/out/map/GeocoderControls.js.map +1 -1
- package/out/map/MapChipRow.d.ts +47 -0
- package/out/map/MapChipRow.d.ts.map +1 -0
- package/out/map/MapChipRow.js +12 -0
- package/out/map/MapChipRow.js.map +1 -0
- package/out/map/MapCompass.d.ts +42 -0
- package/out/map/MapCompass.d.ts.map +1 -0
- package/out/map/MapCompass.js +11 -0
- package/out/map/MapCompass.js.map +1 -0
- package/out/map/MapControlStack.d.ts +57 -0
- package/out/map/MapControlStack.d.ts.map +1 -0
- package/out/map/MapControlStack.js +15 -0
- package/out/map/MapControlStack.js.map +1 -0
- package/out/map/MapFooter.d.ts +40 -0
- package/out/map/MapFooter.d.ts.map +1 -0
- package/out/map/MapFooter.js +51 -0
- package/out/map/MapFooter.js.map +1 -0
- package/out/map/MapProgressBar.d.ts +34 -0
- package/out/map/MapProgressBar.d.ts.map +1 -0
- package/out/map/MapProgressBar.js +8 -0
- package/out/map/MapProgressBar.js.map +1 -0
- package/out/map/MapSearchBar.d.ts +49 -0
- package/out/map/MapSearchBar.d.ts.map +1 -0
- package/out/map/MapSearchBar.js +6 -0
- package/out/map/MapSearchBar.js.map +1 -0
- package/out/map/MapSheet.d.ts +32 -0
- package/out/map/MapSheet.d.ts.map +1 -0
- package/out/map/MapSheet.js +33 -0
- package/out/map/MapSheet.js.map +1 -0
- package/out/map/OverlayLayers.js +1 -1
- package/out/map/ResolvedPlaceLayers.js +1 -1
- package/out/map/ResultPanel.js +1 -1
- package/out/map/fake-runtime.js.map +1 -1
- package/out/map/index.d.ts +17 -0
- package/out/map/index.d.ts.map +1 -1
- package/out/map/index.js +10 -0
- package/out/map/index.js.map +1 -1
- package/out/map/map-debug.d.ts.map +1 -1
- package/out/map/map-debug.js.map +1 -1
- package/out/map/types.d.ts +20 -4
- package/out/map/types.d.ts.map +1 -1
- package/out/map/useMapBearing.d.ts +28 -0
- package/out/map/useMapBearing.d.ts.map +1 -0
- package/out/map/useMapBearing.js +35 -0
- package/out/map/useMapBearing.js.map +1 -0
- package/out/map/useMapLabelPick.d.ts +23 -0
- package/out/map/useMapLabelPick.d.ts.map +1 -0
- package/out/map/useMapLabelPick.js +104 -0
- package/out/map/useMapLabelPick.js.map +1 -0
- package/out/pipeline/CandidatePicker.js +1 -1
- package/out/pipeline/PipelineExplorer.js +1 -1
- package/out/pipeline/QueryForm.js +1 -1
- package/out/pipeline/ResolvedPlace.js +1 -1
- package/out/pipeline/TimingPanel.js +1 -1
- package/out/pipeline/index.d.ts +33 -0
- package/out/pipeline/index.d.ts.map +1 -0
- package/out/pipeline/index.js +21 -0
- package/out/pipeline/index.js.map +1 -0
- package/out/pipeline/useParsePipeline.d.ts +5 -2
- package/out/pipeline/useParsePipeline.d.ts.map +1 -1
- package/out/pipeline/useParsePipeline.js +6 -2
- package/out/pipeline/useParsePipeline.js.map +1 -1
- package/out/poi/LiveResultsBlock.js +1 -1
- package/out/poi/POIExplorer.js +1 -1
- package/out/poi/SubjectPanel.js +1 -1
- package/out/poi/index.d.ts +23 -0
- package/out/poi/index.d.ts.map +1 -0
- package/out/poi/index.js +15 -0
- package/out/poi/index.js.map +1 -0
- package/out/poi/runtime.d.ts.map +1 -1
- package/out/runtime/index.d.ts +9 -0
- package/out/runtime/index.d.ts.map +1 -0
- package/out/runtime/index.js +8 -0
- package/out/runtime/index.js.map +1 -0
- package/package.json +87 -6
- package/styleframe.config.ts +9 -1
- package/styles.css +948 -26
- package/tokens/index.css +2 -1
- package/tokens/tokens.json +7 -0
- package/tokens/tokens.resolver.json +1 -1
package/lib/common/About.tsx
CHANGED
|
@@ -3,87 +3,103 @@
|
|
|
3
3
|
* @license AGPL-3.0
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
5
|
*
|
|
6
|
-
* `About` — the
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* `About` — the explainer for the browser geocoder: the neural model, the confidence colours, the gazetteer
|
|
7
|
+
* resolver, the byte-range database and the FST prior. Prose about the product a host places above or beside the
|
|
8
|
+
* geocoder; it renders nothing live.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import type { ReactNode } from "react"
|
|
12
12
|
|
|
13
|
-
export
|
|
13
|
+
export interface AboutProps {
|
|
14
|
+
/**
|
|
15
|
+
* Wrap the prose in its own `<details>` disclosure. Set false where the host is already the disclosure — inside a
|
|
16
|
+
* sheet opened by an About button, a summary repeating that button's words is one control too many.
|
|
17
|
+
*
|
|
18
|
+
* @default true
|
|
19
|
+
*/
|
|
20
|
+
collapsible?: boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function About({ collapsible = true }: AboutProps = {}): ReactNode {
|
|
24
|
+
const body = (
|
|
25
|
+
<div className="mw-about__body">
|
|
26
|
+
<section className="mw-about__section">
|
|
27
|
+
<h3 className="mw-about__heading">Neural model</h3>
|
|
28
|
+
<p>
|
|
29
|
+
A ~29M-parameter BERT-style encoder classifies each token into one of 33 BIO labels covering 16 address
|
|
30
|
+
components (street, house number, unit, locality, region, postcode, venue, country, intersection, etc.). It
|
|
31
|
+
runs entirely in your browser via <strong>onnxruntime-web</strong> (WebGPU with WASM SIMD fallback). The model
|
|
32
|
+
ships as a 37.6 MB int8-quantized ONNX bundle; fp32 weights are also available for higher accuracy.
|
|
33
|
+
</p>
|
|
34
|
+
</section>
|
|
35
|
+
|
|
36
|
+
<section className="mw-about__section">
|
|
37
|
+
<h3 className="mw-about__heading">Confidence colors</h3>
|
|
38
|
+
<p>
|
|
39
|
+
Every classified span carries a confidence score between 0 and 1. The colors in the results table give you a
|
|
40
|
+
quick visual read:
|
|
41
|
+
</p>
|
|
42
|
+
<ul className="mw-about__legend">
|
|
43
|
+
<li className="mw-about__item">
|
|
44
|
+
<span className="mw-about__swatch mw-about__swatch--high" />
|
|
45
|
+
<strong>Green</strong> (≥ 0.8) — high confidence. The model is nearly certain.
|
|
46
|
+
</li>
|
|
47
|
+
<li className="mw-about__item">
|
|
48
|
+
<span className="mw-about__swatch mw-about__swatch--mid" />
|
|
49
|
+
<strong>Amber</strong> (0.5–0.8) — moderate confidence. Worth verifying.
|
|
50
|
+
</li>
|
|
51
|
+
<li className="mw-about__item">
|
|
52
|
+
<span className="mw-about__swatch mw-about__swatch--low" />
|
|
53
|
+
<strong>Red</strong> (< 0.5) — low confidence. The model is unsure — likely wrong.
|
|
54
|
+
</li>
|
|
55
|
+
</ul>
|
|
56
|
+
<p>
|
|
57
|
+
These are raw model scores. For calibrated probabilities, the library ships a per-locale isotonic calibrator (
|
|
58
|
+
<code>calibration.json</code>) that maps the raw scores to well-calibrated probability estimates.
|
|
59
|
+
</p>
|
|
60
|
+
</section>
|
|
61
|
+
|
|
62
|
+
<section className="mw-about__section">
|
|
63
|
+
<h3 className="mw-about__heading">WOF resolver</h3>
|
|
64
|
+
<p>
|
|
65
|
+
After classification, the resolver queries a <strong>Who's On First</strong> (WOF) SQLite gazetteer to
|
|
66
|
+
match the parsed components — locality, region, and postcode — against real-world places with coordinates. The
|
|
67
|
+
cascade tries postcode first (most precise), then locality, then the raw input text. The result is a sorted
|
|
68
|
+
list of candidate places with WOF IDs, placetypes, lat/lon, and bounding boxes.
|
|
69
|
+
</p>
|
|
70
|
+
</section>
|
|
71
|
+
|
|
72
|
+
<section className="mw-about__section">
|
|
73
|
+
<h3 className="mw-about__heading">Byte-range gazetteer</h3>
|
|
74
|
+
<p>
|
|
75
|
+
The gazetteer is a multi-gigabyte SQLite file served from a public bucket. It loads via{" "}
|
|
76
|
+
<strong>sql.js-httpvfs</strong>, which range-requests only the pages a lookup touches, so your browser fetches
|
|
77
|
+
a few hundred kilobytes per session instead of the whole file.
|
|
78
|
+
</p>
|
|
79
|
+
</section>
|
|
80
|
+
|
|
81
|
+
<section className="mw-about__section">
|
|
82
|
+
<h3 className="mw-about__heading">FST prior</h3>
|
|
83
|
+
<p>
|
|
84
|
+
A <strong>finite-state transducer</strong> (FST) built from ~94K US place names runs before the neural
|
|
85
|
+
classifier. It pre-annotates known locality, region, and postcode spans in the input — places like
|
|
86
|
+
"Springfield" or "Cook County" that the FST can match exactly. These "FST prior"
|
|
87
|
+
hits feed the classifier as strong hints, improving locality and region recall on addresses where the neural
|
|
88
|
+
model alone might miss them. The FST is active whenever the selected release includes it.
|
|
89
|
+
</p>
|
|
90
|
+
</section>
|
|
91
|
+
</div>
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
if (!collapsible) return body
|
|
95
|
+
|
|
14
96
|
return (
|
|
15
97
|
<details className="mw-about">
|
|
16
98
|
<summary className="mw-about__summary">
|
|
17
99
|
<span className="mw-about__icon">ℹ️</span>
|
|
18
100
|
About this geocoder
|
|
19
101
|
</summary>
|
|
20
|
-
|
|
21
|
-
<section className="mw-about__section">
|
|
22
|
-
<h3 className="mw-about__heading">Neural model</h3>
|
|
23
|
-
<p>
|
|
24
|
-
A ~29M-parameter BERT-style encoder classifies each token into one of 33 BIO labels covering 16 address
|
|
25
|
-
components (street, house number, unit, locality, region, postcode, venue, country, intersection, etc.). It
|
|
26
|
-
runs entirely in your browser via <strong>onnxruntime-web</strong> (WebGPU with WASM SIMD fallback). The
|
|
27
|
-
model ships as a 37.6 MB int8-quantized ONNX bundle; fp32 weights are also available for higher accuracy.
|
|
28
|
-
</p>
|
|
29
|
-
</section>
|
|
30
|
-
|
|
31
|
-
<section className="mw-about__section">
|
|
32
|
-
<h3 className="mw-about__heading">Confidence colors</h3>
|
|
33
|
-
<p>
|
|
34
|
-
Every classified span carries a confidence score between 0 and 1. The colors in the results table give you a
|
|
35
|
-
quick visual read:
|
|
36
|
-
</p>
|
|
37
|
-
<ul className="mw-about__legend">
|
|
38
|
-
<li className="mw-about__item">
|
|
39
|
-
<span className="mw-about__swatch mw-about__swatch--high" />
|
|
40
|
-
<strong>Green</strong> (≥ 0.8) — high confidence. The model is nearly certain.
|
|
41
|
-
</li>
|
|
42
|
-
<li className="mw-about__item">
|
|
43
|
-
<span className="mw-about__swatch mw-about__swatch--mid" />
|
|
44
|
-
<strong>Amber</strong> (0.5–0.8) — moderate confidence. Worth verifying.
|
|
45
|
-
</li>
|
|
46
|
-
<li className="mw-about__item">
|
|
47
|
-
<span className="mw-about__swatch mw-about__swatch--low" />
|
|
48
|
-
<strong>Red</strong> (< 0.5) — low confidence. The model is unsure — likely wrong.
|
|
49
|
-
</li>
|
|
50
|
-
</ul>
|
|
51
|
-
<p>
|
|
52
|
-
These are raw model scores. For calibrated probabilities, the library ships a per-locale isotonic calibrator
|
|
53
|
-
(<code>calibration.json</code>) that maps the raw scores to well-calibrated probability estimates.
|
|
54
|
-
</p>
|
|
55
|
-
</section>
|
|
56
|
-
|
|
57
|
-
<section className="mw-about__section">
|
|
58
|
-
<h3 className="mw-about__heading">WOF resolver</h3>
|
|
59
|
-
<p>
|
|
60
|
-
After classification, the resolver queries a <strong>Who's On First</strong> (WOF) SQLite gazetteer to
|
|
61
|
-
match the parsed components — locality, region, and postcode — against real-world places with coordinates.
|
|
62
|
-
The cascade tries postcode first (most precise), then locality, then the raw input text. The result is a
|
|
63
|
-
sorted list of candidate places with WOF IDs, placetypes, lat/lon, and bounding boxes.
|
|
64
|
-
</p>
|
|
65
|
-
</section>
|
|
66
|
-
|
|
67
|
-
<section className="mw-about__section">
|
|
68
|
-
<h3 className="mw-about__heading">Byte-range gazetteer</h3>
|
|
69
|
-
<p>
|
|
70
|
-
The gazetteer is a multi-gigabyte SQLite file served from a public bucket. It loads via{" "}
|
|
71
|
-
<strong>sql.js-httpvfs</strong>, which range-requests only the pages a lookup touches, so your browser
|
|
72
|
-
fetches a few hundred kilobytes per session instead of the whole file.
|
|
73
|
-
</p>
|
|
74
|
-
</section>
|
|
75
|
-
|
|
76
|
-
<section className="mw-about__section">
|
|
77
|
-
<h3 className="mw-about__heading">FST prior</h3>
|
|
78
|
-
<p>
|
|
79
|
-
A <strong>finite-state transducer</strong> (FST) built from ~94K US place names runs before the neural
|
|
80
|
-
classifier. It pre-annotates known locality, region, and postcode spans in the input — places like
|
|
81
|
-
"Springfield" or "Cook County" that the FST can match exactly. These "FST
|
|
82
|
-
prior" hits feed the classifier as strong hints, improving locality and region recall on addresses
|
|
83
|
-
where the neural model alone might miss them. The FST is active whenever the selected release includes it.
|
|
84
|
-
</p>
|
|
85
|
-
</section>
|
|
86
|
-
</div>
|
|
102
|
+
{body}
|
|
87
103
|
</details>
|
|
88
104
|
)
|
|
89
105
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
* @file Common React primitives.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export { ClientOnly } from "./ClientOnly.tsx"
|
|
9
|
+
export type { ClientOnlyProps } from "./ClientOnly.tsx"
|
|
10
|
+
export { CopyButton } from "./CopyButton.tsx"
|
|
11
|
+
export type { CopyButtonProps } from "./CopyButton.tsx"
|
|
12
|
+
export { cx } from "#common/cx"
|
|
13
|
+
export type { ClassValue } from "#common/cx"
|
|
14
|
+
export { KindBadge } from "./KindBadge.tsx"
|
|
15
|
+
export type { KindBadgeProps } from "./KindBadge.tsx"
|
|
16
|
+
export { LoadingIndicator } from "./LoadingIndicator.tsx"
|
|
17
|
+
export type { LoadingIndicatorProps, LoadingMode } from "./LoadingIndicator.tsx"
|
|
18
|
+
export { PresetChips } from "./PresetChips.tsx"
|
|
19
|
+
export type { Preset, PresetChipsProps } from "./PresetChips.tsx"
|
|
20
|
+
export { useClipboard } from "#common/useClipboard"
|
|
21
|
+
export type { UseClipboard } from "#common/useClipboard"
|
|
22
|
+
export { useDebouncedValue } from "#common/useDebouncedValue"
|
package/lib/index.ts
CHANGED
|
@@ -16,106 +16,11 @@
|
|
|
16
16
|
* aware) — no CSS is imported by the component modules, so the bare package import is node-safe.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
export
|
|
21
|
-
export
|
|
22
|
-
export
|
|
23
|
-
export type { CopyButtonProps } from "./common/CopyButton.tsx"
|
|
24
|
-
export { cx } from "#common/cx"
|
|
25
|
-
export type { ClassValue } from "#common/cx"
|
|
26
|
-
export { KindBadge } from "./common/KindBadge.tsx"
|
|
27
|
-
export type { KindBadgeProps } from "./common/KindBadge.tsx"
|
|
28
|
-
export { LoadingIndicator } from "./common/LoadingIndicator.tsx"
|
|
29
|
-
export type { LoadingIndicatorProps, LoadingMode } from "./common/LoadingIndicator.tsx"
|
|
30
|
-
export { PresetChips } from "./common/PresetChips.tsx"
|
|
31
|
-
export type { Preset, PresetChipsProps } from "./common/PresetChips.tsx"
|
|
32
|
-
export { useClipboard } from "#common/useClipboard"
|
|
33
|
-
export type { UseClipboard } from "#common/useClipboard"
|
|
34
|
-
export { useDebouncedValue } from "#common/useDebouncedValue"
|
|
19
|
+
export * from "#common/index"
|
|
20
|
+
export * from "#poi/index"
|
|
21
|
+
export * from "#pipeline/index"
|
|
22
|
+
export * from "#runtime/index"
|
|
35
23
|
|
|
36
|
-
// ── POI explorer ───────────────────────────────────────────────────────────
|
|
37
|
-
export { AbstainPanel } from "./poi/AbstainPanel.tsx"
|
|
38
|
-
export type { AbstainPanelProps } from "./poi/AbstainPanel.tsx"
|
|
39
|
-
export { LiveResultsBlock } from "./poi/LiveResultsBlock.tsx"
|
|
40
|
-
export type { LiveResultsBlockProps } from "./poi/LiveResultsBlock.tsx"
|
|
41
|
-
export { OverpassBlock } from "./poi/OverpassBlock.tsx"
|
|
42
|
-
export type { OverpassBlockProps } from "./poi/OverpassBlock.tsx"
|
|
43
|
-
export { POIExplorer } from "./poi/POIExplorer.tsx"
|
|
44
|
-
export type { POIExplorerProps } from "./poi/POIExplorer.tsx"
|
|
45
|
-
export { QueryInput } from "./poi/QueryInput.tsx"
|
|
46
|
-
export type { QueryInputProps } from "./poi/QueryInput.tsx"
|
|
47
|
-
export { formatDistance, loadPOIRuntime, POI_DEFAULT_TEXT, POI_PRESETS } from "#poi/runtime"
|
|
48
|
-
export { SubjectPanel } from "./poi/SubjectPanel.tsx"
|
|
49
|
-
export type { SubjectPanelProps } from "./poi/SubjectPanel.tsx"
|
|
50
|
-
|
|
51
|
-
export type {
|
|
52
|
-
CategoryRecord,
|
|
53
|
-
LiveSearchState,
|
|
54
|
-
LoadPOIRuntime,
|
|
55
|
-
POIBrandSubject,
|
|
56
|
-
POICategorySubject,
|
|
57
|
-
POIExplorerResult,
|
|
58
|
-
POILiveSearch,
|
|
59
|
-
POILiveSearchResult,
|
|
60
|
-
POIRuntime,
|
|
61
|
-
POISearchHit,
|
|
62
|
-
POISubject,
|
|
63
|
-
POISubjectBase,
|
|
64
|
-
TaxonomyLookup,
|
|
65
|
-
} from "#poi/types"
|
|
66
|
-
|
|
67
|
-
export { usePOISearch } from "#poi/usePOISearch"
|
|
68
|
-
export type { UsePOISearch, UsePOISearchOptions } from "#poi/usePOISearch"
|
|
69
|
-
|
|
70
|
-
// ── Result visualizers ─────────────────────────────────────────────────────
|
|
71
|
-
|
|
72
|
-
export { About } from "./common/About.tsx"
|
|
73
|
-
export { FailureDiagnostic } from "./pipeline/FailureDiagnostic.tsx"
|
|
74
|
-
export type { FailureDiagnosticProps } from "./pipeline/FailureDiagnostic.tsx"
|
|
75
|
-
export { SpanHighlight } from "./pipeline/SpanHighlight.tsx"
|
|
76
|
-
export type { SpanHighlightProps } from "./pipeline/SpanHighlight.tsx"
|
|
77
|
-
export { TimingPanel } from "./pipeline/TimingPanel.tsx"
|
|
78
|
-
export type { TimingPanelProps } from "./pipeline/TimingPanel.tsx"
|
|
79
|
-
export { TreeView } from "./pipeline/TreeView.tsx"
|
|
80
|
-
export type { TreeViewProps } from "./pipeline/TreeView.tsx"
|
|
81
|
-
|
|
82
|
-
// ── Pipeline explorer ──────────────────────────────────────────────────────
|
|
83
|
-
export { CandidatePicker } from "./pipeline/CandidatePicker.tsx"
|
|
84
|
-
export type { CandidatePickerProps } from "./pipeline/CandidatePicker.tsx"
|
|
85
|
-
export { ComponentTable } from "./pipeline/ComponentTable.tsx"
|
|
86
|
-
export type { ComponentTableProps } from "./pipeline/ComponentTable.tsx"
|
|
87
|
-
export { ConfidenceCell } from "./pipeline/ConfidenceCell.tsx"
|
|
88
|
-
export type { ConfidenceCellProps } from "./pipeline/ConfidenceCell.tsx"
|
|
89
|
-
export { buildParsePayload } from "#pipeline/copy"
|
|
90
|
-
export { PIPELINE_DEFAULT_ADDRESS, PIPELINE_PRESETS } from "#pipeline/presets"
|
|
91
|
-
export { PipelineExplorer } from "./pipeline/PipelineExplorer.tsx"
|
|
92
|
-
export type { PipelineExplorerProps } from "./pipeline/PipelineExplorer.tsx"
|
|
93
|
-
export { QueryForm } from "./pipeline/QueryForm.tsx"
|
|
94
|
-
export type { QueryFormProps } from "./pipeline/QueryForm.tsx"
|
|
95
|
-
export { ResolvedPlace } from "./pipeline/ResolvedPlace.tsx"
|
|
96
|
-
export type { ResolvedPlaceProps } from "./pipeline/ResolvedPlace.tsx"
|
|
97
|
-
|
|
98
|
-
export type { PipelineLoadingState, PipelinePanels, PipelineRuntime } from "#pipeline/types"
|
|
99
|
-
|
|
100
|
-
export { useParsePipeline } from "#pipeline/useParsePipeline"
|
|
101
|
-
export type { UseParsePipeline, UseParsePipelineOptions } from "#pipeline/useParsePipeline"
|
|
102
|
-
|
|
103
|
-
// ── Release runtime (shared load orchestration; node-safe — no onnx/httpvfs/maplibre) ──
|
|
104
|
-
export { useReleaseRuntime } from "#runtime/useReleaseRuntime"
|
|
105
|
-
|
|
106
|
-
export type {
|
|
107
|
-
AssetsLoadContext,
|
|
108
|
-
ReleaseBase,
|
|
109
|
-
ReleaseLoaderState,
|
|
110
|
-
ReleaseManifest,
|
|
111
|
-
ReleaseRuntimeConfig,
|
|
112
|
-
} from "#runtime/useReleaseRuntime"
|
|
113
|
-
|
|
114
|
-
// ── Map (types only from root) ──────────────────────────────────────────────
|
|
115
|
-
// The map SURFACE lives behind the `@mailwoman/react/map` subpath so `maplibre-gl` / `react-map-gl`
|
|
116
|
-
// (WebGL + DOM at import) never enter the package-root graph — a bare `import("@mailwoman/react")` in node
|
|
117
|
-
// must not pull them. Only the CONTRACT types are re-exported here (fully erased at compile time, so no
|
|
118
|
-
// runtime linkage): the `MapCanvas` component + hooks are import-able solely via `@mailwoman/react/map`.
|
|
119
24
|
export type {
|
|
120
25
|
GeocoderRuntime,
|
|
121
26
|
InferenceBackend,
|
|
@@ -34,13 +34,17 @@ export interface BackendControlProps {
|
|
|
34
34
|
export function BackendControl({ activeBackend, forceWASM, onForceWASMChange }: BackendControlProps): ReactNode {
|
|
35
35
|
return (
|
|
36
36
|
<div className="mw-demo-backend">
|
|
37
|
+
<span className="mw-map-sheet__label">Inference backend</span>
|
|
38
|
+
|
|
37
39
|
{activeBackend ? (
|
|
38
40
|
<span className="mw-demo-backend__active">
|
|
39
|
-
|
|
41
|
+
Running on <code>{activeBackend}</code>
|
|
40
42
|
</span>
|
|
41
43
|
) : null}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
|
|
45
|
+
<label className="mw-map-sheet__check mw-demo-backend__toggle">
|
|
46
|
+
<input type="checkbox" checked={forceWASM} onChange={(event) => onForceWASMChange(event.target.checked)} />
|
|
47
|
+
Force WASM
|
|
44
48
|
</label>
|
|
45
49
|
</div>
|
|
46
50
|
)
|
|
@@ -69,8 +69,9 @@ export function CompareToggle({
|
|
|
69
69
|
|
|
70
70
|
return (
|
|
71
71
|
<div className="mw-demo-compare">
|
|
72
|
-
<label className="mw-demo-compare__toggle">
|
|
73
|
-
<input type="checkbox" checked={compareMode} onChange={(
|
|
72
|
+
<label className="mw-map-sheet__check mw-demo-compare__toggle">
|
|
73
|
+
<input type="checkbox" checked={compareMode} onChange={(event) => onCompareModeChange(event.target.checked)} />
|
|
74
|
+
Compare two model versions
|
|
74
75
|
</label>
|
|
75
76
|
{compareMode ? (
|
|
76
77
|
<div className="mw-demo-control">
|
package/lib/map/Geocoder.tsx
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* over a fake runtime (offline stub style + canned geocode) with no network, no ONNX, no gazetteer.
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import { type ReactNode, useCallback, useEffect, useRef } from "react"
|
|
22
|
+
import { type ReactNode, useCallback, useEffect, useRef, useState } from "react"
|
|
23
23
|
import type { MapRef } from "react-map-gl/maplibre"
|
|
24
24
|
|
|
25
25
|
import type { GeocoderPanels, GeocoderRuntime, MapBias } from "#map/types"
|
|
@@ -52,6 +52,16 @@ export interface GeocoderProps {
|
|
|
52
52
|
* Example chips. @default the empty set (host supplies its own).
|
|
53
53
|
*/
|
|
54
54
|
presets?: ReadonlyArray<Preset>
|
|
55
|
+
/**
|
|
56
|
+
* Open the developer disclosure on mount — the model version, the backend readout and compare. Collapsed by default
|
|
57
|
+
* so the address field is the first thing a visitor meets. @default false
|
|
58
|
+
*/
|
|
59
|
+
developer?: boolean
|
|
60
|
+
/**
|
|
61
|
+
* Fired with the query each time one is submitted. The host writes it into its own URL — this package never touches
|
|
62
|
+
* `location`, because which parameter carries a query is the app's decision.
|
|
63
|
+
*/
|
|
64
|
+
onSubmitQuery?: (query: string) => void
|
|
55
65
|
/**
|
|
56
66
|
* Only hint the viewport bias once the visitor has zoomed past the global view — a whole-globe center is noise.
|
|
57
67
|
* Matches the `map.getZoom() >= 4` threshold. @default 4
|
|
@@ -66,10 +76,11 @@ export interface GeocoderProps {
|
|
|
66
76
|
}
|
|
67
77
|
|
|
68
78
|
interface GeocoderInnerProps extends Required<
|
|
69
|
-
Pick<GeocoderProps, "runtime" | "defaultAddress" | "minBiasZoom" | "applyResultCamera">
|
|
79
|
+
Pick<GeocoderProps, "runtime" | "defaultAddress" | "minBiasZoom" | "applyResultCamera" | "developer">
|
|
70
80
|
> {
|
|
71
81
|
panels: GeocoderPanels
|
|
72
82
|
presets: ReadonlyArray<Preset>
|
|
83
|
+
onSubmitQuery?: (query: string) => void
|
|
73
84
|
}
|
|
74
85
|
|
|
75
86
|
function GeocoderInner({
|
|
@@ -79,42 +90,44 @@ function GeocoderInner({
|
|
|
79
90
|
presets,
|
|
80
91
|
minBiasZoom,
|
|
81
92
|
applyResultCamera,
|
|
93
|
+
developer,
|
|
94
|
+
onSubmitQuery,
|
|
82
95
|
}: GeocoderInnerProps): ReactNode {
|
|
83
96
|
const mapRef = useRef<MapRef>(null)
|
|
84
|
-
|
|
97
|
+
// The chrome sits OUTSIDE `<MapCanvas>`, so it cannot take the handle from `useMap()`. A ref alone does not
|
|
98
|
+
// re-render the compass or the layer control when the map arrives, so the same poll that publishes the test
|
|
99
|
+
// handle also puts it in state — one poll, two consumers.
|
|
100
|
+
const [map, setMap] = useState<ReturnType<MapRef["getMap"]> | null>(null)
|
|
101
|
+
|
|
102
|
+
// The map announces itself; nothing polls for it. `onLoad` carries the instance, so the compass and the layer
|
|
103
|
+
// control render on the frame the map is ready rather than up to an interval later.
|
|
104
|
+
//
|
|
85
105
|
// TEST INJECTION POINT: the e2e viewport-bias suite drives the REAL map (pan + zoom past the bias threshold)
|
|
86
|
-
// before submitting, and a browser test cannot reach a React ref — so the
|
|
87
|
-
//
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const host = globalThis as { __mailwomanMapCanvas?: ReturnType<MapRef["getMap"]> }
|
|
92
|
-
|
|
93
|
-
const timer = setInterval(() => {
|
|
94
|
-
const map = mapRef.current?.getMap()
|
|
95
|
-
|
|
96
|
-
if (map) {
|
|
97
|
-
host.__mailwomanMapCanvas = map
|
|
98
|
-
clearInterval(timer)
|
|
99
|
-
}
|
|
100
|
-
}, 250)
|
|
101
|
-
|
|
102
|
-
return () => {
|
|
103
|
-
clearInterval(timer)
|
|
104
|
-
delete host.__mailwomanMapCanvas
|
|
105
|
-
}
|
|
106
|
+
// before submitting, and a browser test cannot reach a React ref — so the same handle is republished on
|
|
107
|
+
// `globalThis.__mailwomanMapCanvas`, and cleared on unmount so a torn-down geocoder leaves no stale handle.
|
|
108
|
+
const onMapLoad = useCallback((event: { target: ReturnType<MapRef["getMap"]> }) => {
|
|
109
|
+
;(globalThis as { __mailwomanMapCanvas?: ReturnType<MapRef["getMap"]> }).__mailwomanMapCanvas = event.target
|
|
110
|
+
setMap(event.target)
|
|
106
111
|
}, [])
|
|
107
112
|
|
|
113
|
+
useEffect(
|
|
114
|
+
() => () => {
|
|
115
|
+
setMap(null)
|
|
116
|
+
delete (globalThis as { __mailwomanMapCanvas?: ReturnType<MapRef["getMap"]> }).__mailwomanMapCanvas
|
|
117
|
+
},
|
|
118
|
+
[]
|
|
119
|
+
)
|
|
120
|
+
|
|
108
121
|
// Read the viewport bias at submit time — through the map handle, never a threaded state value, so granting/zooming
|
|
109
122
|
// mid-session doesn't re-create the parse callback. Below the min-bias zoom, a whole-globe center is noise → null.
|
|
110
123
|
const getBias = useCallback((): MapBias | null => {
|
|
111
|
-
const
|
|
124
|
+
const live = mapRef.current?.getMap()
|
|
112
125
|
|
|
113
|
-
if (!
|
|
114
|
-
const zoom =
|
|
126
|
+
if (!live) return null
|
|
127
|
+
const zoom = live.getZoom()
|
|
115
128
|
|
|
116
129
|
if (zoom < minBiasZoom) return null
|
|
117
|
-
const center =
|
|
130
|
+
const center = live.getCenter()
|
|
118
131
|
|
|
119
132
|
return { center: [center.lng, center.lat], zoom }
|
|
120
133
|
}, [minBiasZoom])
|
|
@@ -154,7 +167,7 @@ function GeocoderInner({
|
|
|
154
167
|
style={{ width: "100%", height: "100%" }}
|
|
155
168
|
// One compact attribution pill (the map's own default is a wide, always-open "MapLibre | © …" bar), no
|
|
156
169
|
// maplibre wordmark logo.
|
|
157
|
-
mapProps={{ attributionControl: { compact: true }, maplibreLogo: false }}
|
|
170
|
+
mapProps={{ attributionControl: { compact: true }, maplibreLogo: false, onLoad: onMapLoad }}
|
|
158
171
|
>
|
|
159
172
|
<OverlayLayers overlays={runtime.overlays} />
|
|
160
173
|
<ResolvedPlaceLayers spec={spec} applyCamera={applyResultCamera} />
|
|
@@ -170,8 +183,11 @@ function GeocoderInner({
|
|
|
170
183
|
panels={panels}
|
|
171
184
|
presets={presets}
|
|
172
185
|
placeholder={defaultAddress}
|
|
186
|
+
map={map}
|
|
187
|
+
onSubmitQuery={onSubmitQuery}
|
|
173
188
|
onSelectVersion={onSelectVersion}
|
|
174
189
|
onForceWASMChange={onForceWASMChange}
|
|
190
|
+
developer={developer}
|
|
175
191
|
/>
|
|
176
192
|
|
|
177
193
|
{panels.debugDrawer ? panels.debugDrawer({ result: geocode.result }) : null}
|
|
@@ -195,6 +211,8 @@ export function Geocoder({
|
|
|
195
211
|
presets = NO_PRESETS,
|
|
196
212
|
minBiasZoom = 4,
|
|
197
213
|
applyResultCamera = true,
|
|
214
|
+
developer = false,
|
|
215
|
+
onSubmitQuery,
|
|
198
216
|
}: GeocoderProps): ReactNode {
|
|
199
217
|
return (
|
|
200
218
|
<ClientOnly
|
|
@@ -212,6 +230,8 @@ export function Geocoder({
|
|
|
212
230
|
presets={presets}
|
|
213
231
|
minBiasZoom={minBiasZoom}
|
|
214
232
|
applyResultCamera={applyResultCamera}
|
|
233
|
+
developer={developer}
|
|
234
|
+
onSubmitQuery={onSubmitQuery}
|
|
215
235
|
/>
|
|
216
236
|
)}
|
|
217
237
|
</ClientOnly>
|