@mailwoman/react 9.0.0 → 9.2.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/README.md +1 -1
- package/common/ClientOnly.tsx +18 -6
- package/map/GeocoderDemo.tsx +24 -1
- package/map/geometry.ts +7 -7
- package/map/usePlaceAutocomplete.ts +37 -25
- package/out/common/ClientOnly.d.ts +5 -2
- package/out/common/ClientOnly.d.ts.map +1 -1
- package/out/common/ClientOnly.js +13 -5
- package/out/common/ClientOnly.js.map +1 -1
- package/out/map/GeocoderDemo.d.ts.map +1 -1
- package/out/map/GeocoderDemo.js +20 -1
- package/out/map/GeocoderDemo.js.map +1 -1
- package/out/map/geometry.js +7 -7
- package/out/map/usePlaceAutocomplete.d.ts.map +1 -1
- package/out/map/usePlaceAutocomplete.js +33 -22
- package/out/map/usePlaceAutocomplete.js.map +1 -1
- package/out/poi/usePOISearch.d.ts.map +1 -1
- package/out/poi/usePOISearch.js +71 -44
- package/out/poi/usePOISearch.js.map +1 -1
- package/out/runtime/useDemoRuntime.d.ts.map +1 -1
- package/out/runtime/useDemoRuntime.js +5 -3
- package/out/runtime/useDemoRuntime.js.map +1 -1
- package/package.json +249 -6
- package/poi/usePOISearch.ts +72 -46
- package/runtime/useDemoRuntime.ts +6 -3
- package/styles.css +49 -19
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @mailwoman/react
|
|
2
2
|
|
|
3
|
-
React components + headless hooks for [mailwoman](https://mailwoman.
|
|
3
|
+
React components + headless hooks for [mailwoman](https://mailwoman.ai) — the
|
|
4
4
|
parse/geocode/POI explorers from the docs site, decomposed and packaged for use in any React app.
|
|
5
5
|
|
|
6
6
|
## What's in the box
|
package/common/ClientOnly.tsx
CHANGED
|
@@ -8,11 +8,21 @@
|
|
|
8
8
|
* Remix, Docusaurus). It renders `fallback` on the server and the first client paint, then swaps to
|
|
9
9
|
* `children()` once mounted — keeping timers, clipboard, and dynamic imports off the server render.
|
|
10
10
|
*
|
|
11
|
-
* The mount flag
|
|
12
|
-
*
|
|
11
|
+
* The mount flag comes from `useSyncExternalStore` with a constant snapshot pair — `false` on the
|
|
12
|
+
* server, `true` in the browser — which is the store-shaped statement of exactly this boundary. The
|
|
13
|
+
* earlier `useState(false)` + `useEffect(() => setMounted(true))` said the same thing with a
|
|
14
|
+
* render-cascade the react(set-state-in-effect) rule rightly flags: the second render was the
|
|
15
|
+
* mechanism, not an accident, and the store form gets the same second paint without a set-state.
|
|
13
16
|
*/
|
|
14
17
|
|
|
15
|
-
import { type ReactNode,
|
|
18
|
+
import { type ReactNode, useSyncExternalStore } from "react"
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The boundary never changes after mount, so nothing ever notifies.
|
|
22
|
+
*/
|
|
23
|
+
function subscribeNever(): () => void {
|
|
24
|
+
return () => {}
|
|
25
|
+
}
|
|
16
26
|
|
|
17
27
|
export interface ClientOnlyProps {
|
|
18
28
|
/**
|
|
@@ -26,9 +36,11 @@ export interface ClientOnlyProps {
|
|
|
26
36
|
}
|
|
27
37
|
|
|
28
38
|
export function ClientOnly({ children, fallback = null }: ClientOnlyProps): ReactNode {
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
39
|
+
const mounted = useSyncExternalStore(
|
|
40
|
+
subscribeNever,
|
|
41
|
+
() => true,
|
|
42
|
+
() => false
|
|
43
|
+
)
|
|
32
44
|
|
|
33
45
|
return mounted ? children() : fallback
|
|
34
46
|
}
|
package/map/GeocoderDemo.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, useRef } from "react"
|
|
22
|
+
import { type ReactNode, useCallback, useEffect, useRef } from "react"
|
|
23
23
|
import type { MapRef } from "react-map-gl/maplibre"
|
|
24
24
|
|
|
25
25
|
import { ClientOnly } from "../common/ClientOnly.tsx"
|
|
@@ -81,6 +81,29 @@ function GeocoderDemoInner({
|
|
|
81
81
|
}: GeocoderDemoInnerProps): ReactNode {
|
|
82
82
|
const mapRef = useRef<MapRef>(null)
|
|
83
83
|
|
|
84
|
+
// TEST SEAM: the e2e viewport-bias suite drives the REAL map (pan + zoom past the bias gate)
|
|
85
|
+
// before submitting, and a browser test cannot reach a React ref — so the live map handle is
|
|
86
|
+
// republished on `globalThis.__mailwomanDemoMap`, the same seam the pre-port demo carried. The
|
|
87
|
+
// ref fills only after react-map-gl instantiates the map, hence the short poll; cleared on
|
|
88
|
+
// unmount so a torn-down demo never leaves a stale handle behind.
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
const seam = globalThis as { __mailwomanDemoMap?: ReturnType<MapRef["getMap"]> }
|
|
91
|
+
|
|
92
|
+
const timer = setInterval(() => {
|
|
93
|
+
const map = mapRef.current?.getMap()
|
|
94
|
+
|
|
95
|
+
if (map) {
|
|
96
|
+
seam.__mailwomanDemoMap = map
|
|
97
|
+
clearInterval(timer)
|
|
98
|
+
}
|
|
99
|
+
}, 250)
|
|
100
|
+
|
|
101
|
+
return () => {
|
|
102
|
+
clearInterval(timer)
|
|
103
|
+
delete seam.__mailwomanDemoMap
|
|
104
|
+
}
|
|
105
|
+
}, [])
|
|
106
|
+
|
|
84
107
|
// Read the viewport bias at submit time — through the map handle, never a threaded state value, so granting/zooming
|
|
85
108
|
// mid-session doesn't re-create the parse callback. Below the min-bias zoom, a whole-globe center is noise → null.
|
|
86
109
|
const getBias = useCallback((): MapBias | null => {
|
package/map/geometry.ts
CHANGED
|
@@ -56,16 +56,16 @@ function kmPerDegLon(lat: number): number {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
/**
|
|
59
|
-
* A closed 64-segment (65-point) GeoJSON ring of `
|
|
59
|
+
* A closed 64-segment (65-point) GeoJSON ring of `radiusKM` around `[lon, lat]`, with latitude correction.
|
|
60
60
|
*/
|
|
61
|
-
function circleRing(lat: number, lon: number,
|
|
61
|
+
function circleRing(lat: number, lon: number, radiusKM: number): number[][] {
|
|
62
62
|
const perLon = kmPerDegLon(lat)
|
|
63
63
|
const ring: number[][] = []
|
|
64
64
|
|
|
65
65
|
for (let i = 0; i <= CIRCLE_SEGMENTS; i++) {
|
|
66
66
|
const theta = (2 * Math.PI * i) / 64
|
|
67
67
|
|
|
68
|
-
ring.push([lon + (
|
|
68
|
+
ring.push([lon + (radiusKM * Math.cos(theta)) / perLon, lat + (radiusKM * Math.sin(theta)) / KM_PER_DEG_LAT])
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
return ring
|
|
@@ -81,9 +81,9 @@ export function approxCircleGeometry(lat: number, lon: number, bbox?: PlaceBBox)
|
|
|
81
81
|
? Math.hypot((bbox.maxLat - bbox.minLat) * KM_PER_DEG_LAT, (bbox.maxLon - bbox.minLon) * kmPerDegLon(lat)) / 2
|
|
82
82
|
: 3
|
|
83
83
|
|
|
84
|
-
const
|
|
84
|
+
const radiusKM = Math.min(50, Math.max(0.5, halfDiagKm))
|
|
85
85
|
|
|
86
|
-
return { type: "Polygon", coordinates: [circleRing(lat, lon,
|
|
86
|
+
return { type: "Polygon", coordinates: [circleRing(lat, lon, radiusKM)] }
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
/**
|
|
@@ -92,9 +92,9 @@ export function approxCircleGeometry(lat: number, lon: number, bbox?: PlaceBBox)
|
|
|
92
92
|
* honors small radii so an exact building reads as a tight dot (an ~8 m floor keeps a 10 m situs circle visible).
|
|
93
93
|
*/
|
|
94
94
|
export function radiusCircleGeometry(lat: number, lon: number, radiusM: number): PlaceGeometry {
|
|
95
|
-
const
|
|
95
|
+
const radiusKM = Math.max(0.008, radiusM / 1000)
|
|
96
96
|
|
|
97
|
-
return { type: "Polygon", coordinates: [circleRing(lat, lon,
|
|
97
|
+
return { type: "Polygon", coordinates: [circleRing(lat, lon, radiusKM)] }
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
/**
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* the presentational {@link PlaceAutocomplete} listbox renders `suggestions` / `activeIndex`.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import { type KeyboardEvent, useCallback, useEffect,
|
|
18
|
+
import { type KeyboardEvent, useCallback, useEffect, useState } from "react"
|
|
19
19
|
|
|
20
20
|
import { useDebouncedValue } from "../common/useDebouncedValue.ts"
|
|
21
21
|
import type { Suggestion } from "./types.ts"
|
|
@@ -95,6 +95,12 @@ export interface UsePlaceAutocomplete {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
const LISTBOX_ID = "mw-demo-suggest-list"
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Stable empty list for the derived no-suggestions state — a fresh `[]` per render would churn the identity every
|
|
101
|
+
* consumer and every useCallback dependency list sees.
|
|
102
|
+
*/
|
|
103
|
+
const NO_SUGGESTIONS: Suggestion[] = []
|
|
98
104
|
const optionID = (index: number) => `mw-demo-suggest-${index}`
|
|
99
105
|
|
|
100
106
|
/**
|
|
@@ -118,30 +124,33 @@ export function usePlaceAutocomplete({
|
|
|
118
124
|
minChars = 2,
|
|
119
125
|
debounceMs = 150,
|
|
120
126
|
}: UsePlaceAutocompleteOptions): UsePlaceAutocomplete {
|
|
121
|
-
|
|
127
|
+
/**
|
|
128
|
+
* The last COMPLETED fetch, keyed by the query that produced it. Visibility is DERIVED from this during render rather
|
|
129
|
+
* than pushed through sync setStates in the effect — the effect's only job is the async fetch, so every state write
|
|
130
|
+
* in it happens after an await and the react(set-state-in-effect) rule is satisfied by structure, not by exception.
|
|
131
|
+
*/
|
|
132
|
+
const [fetched, setFetched] = useState<{ query: string; suggestions: Suggestion[] } | null>(null)
|
|
133
|
+
/**
|
|
134
|
+
* The query whose list was dismissed or picked. Suppression as DATA, replacing the one-shot ref flag: a pick stores
|
|
135
|
+
* the query the rewritten text will produce, so the post-pick fetch is skipped and the place just chosen is never
|
|
136
|
+
* re-suggested. One divergence from the ref version, accepted and small: after Esc, retyping the exact same string
|
|
137
|
+
* keeps the list hidden until the query changes.
|
|
138
|
+
*/
|
|
139
|
+
const [dismissed, setDismissed] = useState<string | null>(null)
|
|
122
140
|
const [activeIndex, setActiveIndex] = useState(-1)
|
|
123
|
-
// One-shot guard: a pick rewrites `text` to the chosen name, which would otherwise re-trigger the fetch and
|
|
124
|
-
// immediately re-suggest the place just chosen. Set on pick, consumed by the next effect run.
|
|
125
|
-
const suppressRef = useRef(false)
|
|
126
141
|
|
|
127
142
|
const query = localitySegment(text)
|
|
128
143
|
const debouncedQuery = useDebouncedValue(query, debounceMs)
|
|
129
144
|
|
|
130
|
-
|
|
131
|
-
if (suppressRef.current) {
|
|
132
|
-
suppressRef.current = false
|
|
133
|
-
setSuggestions([])
|
|
134
|
-
setActiveIndex(-1)
|
|
145
|
+
const eligible = Boolean(autocomplete) && debouncedQuery.length >= minChars && !/^\d/.test(debouncedQuery)
|
|
135
146
|
|
|
136
|
-
|
|
137
|
-
|
|
147
|
+
const suggestions =
|
|
148
|
+
eligible && fetched?.query === debouncedQuery && dismissed !== debouncedQuery ? fetched.suggestions : NO_SUGGESTIONS
|
|
138
149
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
setActiveIndex(-1)
|
|
150
|
+
useEffect(() => {
|
|
151
|
+
if (!autocomplete || debouncedQuery.length < minChars || /^\d/.test(debouncedQuery)) return
|
|
142
152
|
|
|
143
|
-
|
|
144
|
-
}
|
|
153
|
+
if (dismissed === debouncedQuery) return
|
|
145
154
|
|
|
146
155
|
let cancelled = false
|
|
147
156
|
|
|
@@ -150,11 +159,11 @@ export function usePlaceAutocomplete({
|
|
|
150
159
|
const next = await autocomplete(debouncedQuery)
|
|
151
160
|
|
|
152
161
|
if (cancelled) return
|
|
153
|
-
|
|
162
|
+
setFetched({ query: debouncedQuery, suggestions: next })
|
|
154
163
|
setActiveIndex(-1)
|
|
155
164
|
} catch {
|
|
156
165
|
if (cancelled) return
|
|
157
|
-
|
|
166
|
+
setFetched({ query: debouncedQuery, suggestions: [] })
|
|
158
167
|
setActiveIndex(-1)
|
|
159
168
|
}
|
|
160
169
|
})()
|
|
@@ -162,22 +171,25 @@ export function usePlaceAutocomplete({
|
|
|
162
171
|
return () => {
|
|
163
172
|
cancelled = true
|
|
164
173
|
}
|
|
165
|
-
}, [debouncedQuery, autocomplete, minChars])
|
|
174
|
+
}, [debouncedQuery, autocomplete, minChars, dismissed])
|
|
166
175
|
|
|
167
176
|
const pick = useCallback(
|
|
168
177
|
(value: string) => {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
178
|
+
const next = replaceSegment(text, value)
|
|
179
|
+
|
|
180
|
+
setText(next)
|
|
181
|
+
// Suppress the fetch the rewritten text would trigger — the segment being typed IS the picked name.
|
|
182
|
+
setDismissed(localitySegment(next))
|
|
183
|
+
setFetched(null)
|
|
172
184
|
setActiveIndex(-1)
|
|
173
185
|
},
|
|
174
186
|
[text, setText]
|
|
175
187
|
)
|
|
176
188
|
|
|
177
189
|
const dismiss = useCallback(() => {
|
|
178
|
-
|
|
190
|
+
setDismissed(debouncedQuery)
|
|
179
191
|
setActiveIndex(-1)
|
|
180
|
-
}, [])
|
|
192
|
+
}, [debouncedQuery])
|
|
181
193
|
|
|
182
194
|
const onInputKeyDown = useCallback(
|
|
183
195
|
(event: KeyboardEvent<HTMLInputElement>) => {
|
|
@@ -8,8 +8,11 @@
|
|
|
8
8
|
* Remix, Docusaurus). It renders `fallback` on the server and the first client paint, then swaps to
|
|
9
9
|
* `children()` once mounted — keeping timers, clipboard, and dynamic imports off the server render.
|
|
10
10
|
*
|
|
11
|
-
* The mount flag
|
|
12
|
-
*
|
|
11
|
+
* The mount flag comes from `useSyncExternalStore` with a constant snapshot pair — `false` on the
|
|
12
|
+
* server, `true` in the browser — which is the store-shaped statement of exactly this boundary. The
|
|
13
|
+
* earlier `useState(false)` + `useEffect(() => setMounted(true))` said the same thing with a
|
|
14
|
+
* render-cascade the react(set-state-in-effect) rule rightly flags: the second render was the
|
|
15
|
+
* mechanism, not an accident, and the store form gets the same second paint without a set-state.
|
|
13
16
|
*/
|
|
14
17
|
import { type ReactNode } from "react";
|
|
15
18
|
export interface ClientOnlyProps {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClientOnly.d.ts","sourceRoot":"","sources":["../../common/ClientOnly.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ClientOnly.d.ts","sourceRoot":"","sources":["../../common/ClientOnly.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,KAAK,SAAS,EAAwB,MAAM,OAAO,CAAA;AAS5D,MAAM,WAAW,eAAe;IAC/B;;OAEG;IACH,QAAQ,EAAE,MAAM,SAAS,CAAA;IACzB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAA;CACpB;AAED,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,QAAe,EAAE,EAAE,eAAe,GAAG,SAAS,CAQpF"}
|
package/out/common/ClientOnly.js
CHANGED
|
@@ -8,13 +8,21 @@
|
|
|
8
8
|
* Remix, Docusaurus). It renders `fallback` on the server and the first client paint, then swaps to
|
|
9
9
|
* `children()` once mounted — keeping timers, clipboard, and dynamic imports off the server render.
|
|
10
10
|
*
|
|
11
|
-
* The mount flag
|
|
12
|
-
*
|
|
11
|
+
* The mount flag comes from `useSyncExternalStore` with a constant snapshot pair — `false` on the
|
|
12
|
+
* server, `true` in the browser — which is the store-shaped statement of exactly this boundary. The
|
|
13
|
+
* earlier `useState(false)` + `useEffect(() => setMounted(true))` said the same thing with a
|
|
14
|
+
* render-cascade the react(set-state-in-effect) rule rightly flags: the second render was the
|
|
15
|
+
* mechanism, not an accident, and the store form gets the same second paint without a set-state.
|
|
13
16
|
*/
|
|
14
|
-
import {
|
|
17
|
+
import { useSyncExternalStore } from "react";
|
|
18
|
+
/**
|
|
19
|
+
* The boundary never changes after mount, so nothing ever notifies.
|
|
20
|
+
*/
|
|
21
|
+
function subscribeNever() {
|
|
22
|
+
return () => { };
|
|
23
|
+
}
|
|
15
24
|
export function ClientOnly({ children, fallback = null }) {
|
|
16
|
-
const
|
|
17
|
-
useEffect(() => setMounted(true), []);
|
|
25
|
+
const mounted = useSyncExternalStore(subscribeNever, () => true, () => false);
|
|
18
26
|
return mounted ? children() : fallback;
|
|
19
27
|
}
|
|
20
28
|
//# sourceMappingURL=ClientOnly.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClientOnly.js","sourceRoot":"","sources":["../../common/ClientOnly.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ClientOnly.js","sourceRoot":"","sources":["../../common/ClientOnly.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAkB,oBAAoB,EAAE,MAAM,OAAO,CAAA;AAE5D;;GAEG;AACH,SAAS,cAAc;IACtB,OAAO,GAAG,EAAE,GAAE,CAAC,CAAA;AAChB,CAAC;AAaD,MAAM,UAAU,UAAU,CAAC,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI,EAAmB;IACxE,MAAM,OAAO,GAAG,oBAAoB,CACnC,cAAc,EACd,GAAG,EAAE,CAAC,IAAI,EACV,GAAG,EAAE,CAAC,KAAK,CACX,CAAA;IAED,OAAO,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAA;AACvC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GeocoderDemo.d.ts","sourceRoot":"","sources":["../../map/GeocoderDemo.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,KAAK,SAAS,
|
|
1
|
+
{"version":3,"file":"GeocoderDemo.d.ts","sourceRoot":"","sources":["../../map/GeocoderDemo.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,KAAK,SAAS,EAAkC,MAAM,OAAO,CAAA;AAItE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAA;AAKvD,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAW,MAAM,YAAY,CAAA;AAMlE,MAAM,WAAW,iBAAiB;IACjC;;OAEG;IACH,OAAO,EAAE,WAAW,CAAA;IACpB;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;OAEG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IAC/B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAC3B;AA0HD;;GAEG;AACH,wBAAgB,YAAY,CAAC,EAC5B,OAAO,EACP,MAAkB,EAClB,cAAmB,EACnB,OAAoB,EACpB,WAAe,EACf,iBAAwB,GACxB,EAAE,iBAAiB,GAAG,SAAS,CAqB/B"}
|
package/out/map/GeocoderDemo.js
CHANGED
|
@@ -19,7 +19,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
19
19
|
* the `@mailwoman/react/map` subpath ONLY — never the package root. The whole thing renders in Storybook
|
|
20
20
|
* over a fake runtime (offline stub style + canned geocode) with no network, no ONNX, no gazetteer.
|
|
21
21
|
*/
|
|
22
|
-
import { useCallback, useRef } from "react";
|
|
22
|
+
import { useCallback, useEffect, useRef } from "react";
|
|
23
23
|
import { ClientOnly } from "../common/ClientOnly.js";
|
|
24
24
|
import { DemoControls } from "./DemoControls.js";
|
|
25
25
|
import { DemoMap } from "./DemoMap.js";
|
|
@@ -31,6 +31,25 @@ import { useMapPlaceRender } from "./useMapPlaceRender.js";
|
|
|
31
31
|
import { usePlaceAutocomplete } from "./usePlaceAutocomplete.js";
|
|
32
32
|
function GeocoderDemoInner({ runtime, panels, defaultAddress, presets, minBiasZoom, applyResultCamera, }) {
|
|
33
33
|
const mapRef = useRef(null);
|
|
34
|
+
// TEST SEAM: the e2e viewport-bias suite drives the REAL map (pan + zoom past the bias gate)
|
|
35
|
+
// before submitting, and a browser test cannot reach a React ref — so the live map handle is
|
|
36
|
+
// republished on `globalThis.__mailwomanDemoMap`, the same seam the pre-port demo carried. The
|
|
37
|
+
// ref fills only after react-map-gl instantiates the map, hence the short poll; cleared on
|
|
38
|
+
// unmount so a torn-down demo never leaves a stale handle behind.
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
const seam = globalThis;
|
|
41
|
+
const timer = setInterval(() => {
|
|
42
|
+
const map = mapRef.current?.getMap();
|
|
43
|
+
if (map) {
|
|
44
|
+
seam.__mailwomanDemoMap = map;
|
|
45
|
+
clearInterval(timer);
|
|
46
|
+
}
|
|
47
|
+
}, 250);
|
|
48
|
+
return () => {
|
|
49
|
+
clearInterval(timer);
|
|
50
|
+
delete seam.__mailwomanDemoMap;
|
|
51
|
+
};
|
|
52
|
+
}, []);
|
|
34
53
|
// Read the viewport bias at submit time — through the map handle, never a threaded state value, so granting/zooming
|
|
35
54
|
// mid-session doesn't re-create the parse callback. Below the min-bias zoom, a whole-globe center is noise → null.
|
|
36
55
|
const getBias = useCallback(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GeocoderDemo.js","sourceRoot":"","sources":["../../map/GeocoderDemo.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAkB,WAAW,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"GeocoderDemo.js","sourceRoot":"","sources":["../../map/GeocoderDemo.tsx"],"names":[],"mappings":"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"}
|
package/out/map/geometry.js
CHANGED
|
@@ -30,14 +30,14 @@ function kmPerDegLon(lat) {
|
|
|
30
30
|
return KM_PER_DEG_LAT * Math.cos((lat * Math.PI) / 180);
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
-
* A closed 64-segment (65-point) GeoJSON ring of `
|
|
33
|
+
* A closed 64-segment (65-point) GeoJSON ring of `radiusKM` around `[lon, lat]`, with latitude correction.
|
|
34
34
|
*/
|
|
35
|
-
function circleRing(lat, lon,
|
|
35
|
+
function circleRing(lat, lon, radiusKM) {
|
|
36
36
|
const perLon = kmPerDegLon(lat);
|
|
37
37
|
const ring = [];
|
|
38
38
|
for (let i = 0; i <= CIRCLE_SEGMENTS; i++) {
|
|
39
39
|
const theta = (2 * Math.PI * i) / 64;
|
|
40
|
-
ring.push([lon + (
|
|
40
|
+
ring.push([lon + (radiusKM * Math.cos(theta)) / perLon, lat + (radiusKM * Math.sin(theta)) / KM_PER_DEG_LAT]);
|
|
41
41
|
}
|
|
42
42
|
return ring;
|
|
43
43
|
}
|
|
@@ -50,8 +50,8 @@ export function approxCircleGeometry(lat, lon, bbox) {
|
|
|
50
50
|
const halfDiagKm = bbox
|
|
51
51
|
? Math.hypot((bbox.maxLat - bbox.minLat) * KM_PER_DEG_LAT, (bbox.maxLon - bbox.minLon) * kmPerDegLon(lat)) / 2
|
|
52
52
|
: 3;
|
|
53
|
-
const
|
|
54
|
-
return { type: "Polygon", coordinates: [circleRing(lat, lon,
|
|
53
|
+
const radiusKM = Math.min(50, Math.max(0.5, halfDiagKm));
|
|
54
|
+
return { type: "Polygon", coordinates: [circleRing(lat, lon, radiusKM)] };
|
|
55
55
|
}
|
|
56
56
|
/**
|
|
57
57
|
* A circle of an EXACT radius in meters — for the street-level uncertainty (#377): a 10 m situs floor or a calibrated
|
|
@@ -59,8 +59,8 @@ export function approxCircleGeometry(lat, lon, bbox) {
|
|
|
59
59
|
* honors small radii so an exact building reads as a tight dot (an ~8 m floor keeps a 10 m situs circle visible).
|
|
60
60
|
*/
|
|
61
61
|
export function radiusCircleGeometry(lat, lon, radiusM) {
|
|
62
|
-
const
|
|
63
|
-
return { type: "Polygon", coordinates: [circleRing(lat, lon,
|
|
62
|
+
const radiusKM = Math.max(0.008, radiusM / 1000);
|
|
63
|
+
return { type: "Polygon", coordinates: [circleRing(lat, lon, radiusKM)] };
|
|
64
64
|
}
|
|
65
65
|
/**
|
|
66
66
|
* Bounding box of a Polygon / MultiPolygon, for `fitBounds`. Walks the nested coordinate arrays, so it handles both a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePlaceAutocomplete.d.ts","sourceRoot":"","sources":["../../map/usePlaceAutocomplete.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,KAAK,aAAa,
|
|
1
|
+
{"version":3,"file":"usePlaceAutocomplete.d.ts","sourceRoot":"","sources":["../../map/usePlaceAutocomplete.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,KAAK,aAAa,EAAoC,MAAM,OAAO,CAAA;AAG5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,MAAM,WAAW,2BAA2B;IAC3C;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,EAAE,CAAC,CAAA;IACvD;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACtC,IAAI,EAAE,UAAU,CAAA;IAChB,eAAe,EAAE,OAAO,CAAA;IACxB,eAAe,EAAE,MAAM,CAAA;IACvB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,uBAAuB,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3C,YAAY,EAAE,KAAK,CAAA;CACnB;AAED,MAAM,WAAW,oBAAoB;IACpC;;OAEG;IACH,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB;;OAEG;IACH,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC;;OAEG;IACH,cAAc,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAA;IAChE;;OAEG;IACH,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7B;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB;;OAEG;IACH,UAAU,EAAE,sBAAsB,CAAA;IAClC;;OAEG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB;;OAEG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;CACnC;AAyBD,wBAAgB,oBAAoB,CAAC,EACpC,IAAI,EACJ,OAAO,EACP,YAAY,EACZ,QAAY,EACZ,UAAgB,GAChB,EAAE,2BAA2B,GAAG,oBAAoB,CAmHpD"}
|
|
@@ -14,9 +14,14 @@
|
|
|
14
14
|
* `onInputKeyDown` (↑/↓ move the highlight, Enter accepts it AND suppresses submit, Esc dismisses), and
|
|
15
15
|
* the presentational {@link PlaceAutocomplete} listbox renders `suggestions` / `activeIndex`.
|
|
16
16
|
*/
|
|
17
|
-
import { useCallback, useEffect,
|
|
17
|
+
import { useCallback, useEffect, useState } from "react";
|
|
18
18
|
import { useDebouncedValue } from "../common/useDebouncedValue.js";
|
|
19
19
|
const LISTBOX_ID = "mw-demo-suggest-list";
|
|
20
|
+
/**
|
|
21
|
+
* Stable empty list for the derived no-suggestions state — a fresh `[]` per render would churn the identity every
|
|
22
|
+
* consumer and every useCallback dependency list sees.
|
|
23
|
+
*/
|
|
24
|
+
const NO_SUGGESTIONS = [];
|
|
20
25
|
const optionID = (index) => `mw-demo-suggest-${index}`;
|
|
21
26
|
/**
|
|
22
27
|
* Extract the locality segment being typed — the text after the last comma, trimmed.
|
|
@@ -31,55 +36,61 @@ function replaceSegment(current, name) {
|
|
|
31
36
|
return current.includes(",") ? `${current.slice(0, current.lastIndexOf(",") + 1)} ${name}` : name;
|
|
32
37
|
}
|
|
33
38
|
export function usePlaceAutocomplete({ text, setText, autocomplete, minChars = 2, debounceMs = 150, }) {
|
|
34
|
-
|
|
39
|
+
/**
|
|
40
|
+
* The last COMPLETED fetch, keyed by the query that produced it. Visibility is DERIVED from this during render rather
|
|
41
|
+
* than pushed through sync setStates in the effect — the effect's only job is the async fetch, so every state write
|
|
42
|
+
* in it happens after an await and the react(set-state-in-effect) rule is satisfied by structure, not by exception.
|
|
43
|
+
*/
|
|
44
|
+
const [fetched, setFetched] = useState(null);
|
|
45
|
+
/**
|
|
46
|
+
* The query whose list was dismissed or picked. Suppression as DATA, replacing the one-shot ref flag: a pick stores
|
|
47
|
+
* the query the rewritten text will produce, so the post-pick fetch is skipped and the place just chosen is never
|
|
48
|
+
* re-suggested. One divergence from the ref version, accepted and small: after Esc, retyping the exact same string
|
|
49
|
+
* keeps the list hidden until the query changes.
|
|
50
|
+
*/
|
|
51
|
+
const [dismissed, setDismissed] = useState(null);
|
|
35
52
|
const [activeIndex, setActiveIndex] = useState(-1);
|
|
36
|
-
// One-shot guard: a pick rewrites `text` to the chosen name, which would otherwise re-trigger the fetch and
|
|
37
|
-
// immediately re-suggest the place just chosen. Set on pick, consumed by the next effect run.
|
|
38
|
-
const suppressRef = useRef(false);
|
|
39
53
|
const query = localitySegment(text);
|
|
40
54
|
const debouncedQuery = useDebouncedValue(query, debounceMs);
|
|
55
|
+
const eligible = Boolean(autocomplete) && debouncedQuery.length >= minChars && !/^\d/.test(debouncedQuery);
|
|
56
|
+
const suggestions = eligible && fetched?.query === debouncedQuery && dismissed !== debouncedQuery ? fetched.suggestions : NO_SUGGESTIONS;
|
|
41
57
|
useEffect(() => {
|
|
42
|
-
if (
|
|
43
|
-
suppressRef.current = false;
|
|
44
|
-
setSuggestions([]);
|
|
45
|
-
setActiveIndex(-1);
|
|
58
|
+
if (!autocomplete || debouncedQuery.length < minChars || /^\d/.test(debouncedQuery))
|
|
46
59
|
return;
|
|
47
|
-
|
|
48
|
-
if (!autocomplete || debouncedQuery.length < minChars || /^\d/.test(debouncedQuery)) {
|
|
49
|
-
setSuggestions([]);
|
|
50
|
-
setActiveIndex(-1);
|
|
60
|
+
if (dismissed === debouncedQuery)
|
|
51
61
|
return;
|
|
52
|
-
}
|
|
53
62
|
let cancelled = false;
|
|
54
63
|
void (async () => {
|
|
55
64
|
try {
|
|
56
65
|
const next = await autocomplete(debouncedQuery);
|
|
57
66
|
if (cancelled)
|
|
58
67
|
return;
|
|
59
|
-
|
|
68
|
+
setFetched({ query: debouncedQuery, suggestions: next });
|
|
60
69
|
setActiveIndex(-1);
|
|
61
70
|
}
|
|
62
71
|
catch {
|
|
63
72
|
if (cancelled)
|
|
64
73
|
return;
|
|
65
|
-
|
|
74
|
+
setFetched({ query: debouncedQuery, suggestions: [] });
|
|
66
75
|
setActiveIndex(-1);
|
|
67
76
|
}
|
|
68
77
|
})();
|
|
69
78
|
return () => {
|
|
70
79
|
cancelled = true;
|
|
71
80
|
};
|
|
72
|
-
}, [debouncedQuery, autocomplete, minChars]);
|
|
81
|
+
}, [debouncedQuery, autocomplete, minChars, dismissed]);
|
|
73
82
|
const pick = useCallback((value) => {
|
|
74
|
-
|
|
75
|
-
setText(
|
|
76
|
-
|
|
83
|
+
const next = replaceSegment(text, value);
|
|
84
|
+
setText(next);
|
|
85
|
+
// Suppress the fetch the rewritten text would trigger — the segment being typed IS the picked name.
|
|
86
|
+
setDismissed(localitySegment(next));
|
|
87
|
+
setFetched(null);
|
|
77
88
|
setActiveIndex(-1);
|
|
78
89
|
}, [text, setText]);
|
|
79
90
|
const dismiss = useCallback(() => {
|
|
80
|
-
|
|
91
|
+
setDismissed(debouncedQuery);
|
|
81
92
|
setActiveIndex(-1);
|
|
82
|
-
}, []);
|
|
93
|
+
}, [debouncedQuery]);
|
|
83
94
|
const onInputKeyDown = useCallback((event) => {
|
|
84
95
|
if (!suggestions.length)
|
|
85
96
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePlaceAutocomplete.js","sourceRoot":"","sources":["../../map/usePlaceAutocomplete.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAsB,WAAW,EAAE,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"usePlaceAutocomplete.js","sourceRoot":"","sources":["../../map/usePlaceAutocomplete.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePOISearch.d.ts","sourceRoot":"","sources":["../../poi/usePOISearch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAUH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,iBAAiB,EAAE,aAAa,EAAc,MAAM,YAAY,CAAA;AAE/G,MAAM,WAAW,mBAAmB;IACnC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,WAAW,CAAC,EAAE,cAAc,CAAA;IAC5B;;OAEG;IACH,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,YAAY;IAC5B;;OAEG;IACH,YAAY,EAAE,OAAO,CAAA;IACrB;;OAEG;IACH,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAA;IAChC;;OAEG;IACH,UAAU,EAAE,eAAe,CAAA;IAC3B;;OAEG;IACH,aAAa,EAAE,OAAO,CAAA;IACtB;;OAEG;IACH,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/B;AA6BD,wBAAgB,YAAY,CAAC,EAC5B,IAAI,EACJ,WAA4B,EAC5B,aAAa,EACb,eAAuB,EACvB,UAAgB,GAChB,EAAE,mBAAmB,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"usePOISearch.d.ts","sourceRoot":"","sources":["../../poi/usePOISearch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAUH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,iBAAiB,EAAE,aAAa,EAAc,MAAM,YAAY,CAAA;AAE/G,MAAM,WAAW,mBAAmB;IACnC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,WAAW,CAAC,EAAE,cAAc,CAAA;IAC5B;;OAEG;IACH,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,YAAY;IAC5B;;OAEG;IACH,YAAY,EAAE,OAAO,CAAA;IACrB;;OAEG;IACH,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAA;IAChC;;OAEG;IACH,UAAU,EAAE,eAAe,CAAA;IAC3B;;OAEG;IACH,aAAa,EAAE,OAAO,CAAA;IACtB;;OAEG;IACH,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/B;AA6BD,wBAAgB,YAAY,CAAC,EAC5B,IAAI,EACJ,WAA4B,EAC5B,aAAa,EACb,eAAuB,EACvB,UAAgB,GAChB,EAAE,mBAAmB,GAAG,YAAY,CAkLpC"}
|