@mailwoman/react 9.4.0 → 10.1.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.
Files changed (370) hide show
  1. package/README.md +17 -16
  2. package/fonts.css +97 -22
  3. package/lib/common/About.tsx +87 -71
  4. package/lib/common/ClientOnly.tsx +2 -14
  5. package/lib/common/CopyButton.tsx +3 -1
  6. package/lib/common/LoadingIndicator.tsx +4 -2
  7. package/lib/common/PresetChips.tsx +9 -8
  8. package/lib/common/confidence-tiers.ts +7 -6
  9. package/lib/common/cx.ts +3 -1
  10. package/lib/common/text-tokens.ts +7 -4
  11. package/lib/common/useBuildInfo.ts +54 -0
  12. package/lib/common/useClipboard.ts +2 -11
  13. package/lib/common.ts +22 -0
  14. package/lib/index.ts +27 -112
  15. package/lib/map/AppIdentity.tsx +85 -0
  16. package/lib/map/BackendControl.tsx +16 -13
  17. package/lib/map/CompareToggle.tsx +11 -33
  18. package/lib/map/DebugInfo.tsx +88 -0
  19. package/lib/map/Geocoder.tsx +92 -58
  20. package/lib/map/GeocoderControls.tsx +582 -127
  21. package/lib/map/GraticuleLayer.tsx +54 -0
  22. package/lib/map/MapCanvas.tsx +23 -12
  23. package/lib/map/MapChipRow.tsx +73 -0
  24. package/lib/map/MapCompass.tsx +68 -0
  25. package/lib/map/MapControlStack.tsx +97 -0
  26. package/lib/map/MapFooter.tsx +101 -0
  27. package/lib/map/MapProgressBar.tsx +55 -0
  28. package/lib/map/MapSearchBar.tsx +82 -0
  29. package/lib/map/MapSheet.tsx +71 -0
  30. package/lib/map/OverlayLayers.tsx +1 -1
  31. package/lib/map/PlaceAutocomplete.tsx +10 -21
  32. package/lib/map/PlaceMarker.tsx +4 -2
  33. package/lib/map/ResolvedPlaceLayers.tsx +5 -14
  34. package/lib/map/ResultCamera.tsx +8 -31
  35. package/lib/map/ResultOverlay.tsx +2 -12
  36. package/lib/map/ResultPanel.tsx +1 -20
  37. package/lib/map/VersionPicker.tsx +10 -19
  38. package/lib/map/fake-runtime.ts +10 -12
  39. package/lib/map/geometry.ts +14 -47
  40. package/lib/map/graticule.ts +80 -0
  41. package/lib/map/map-debug.ts +1 -1
  42. package/lib/map/place-render.ts +28 -60
  43. package/lib/map/types.ts +65 -97
  44. package/lib/map/useCompareState.ts +5 -4
  45. package/lib/map/useGeocode.ts +7 -5
  46. package/lib/map/useMapBearing.ts +56 -0
  47. package/lib/map/useMapLabelPick.ts +114 -0
  48. package/lib/map/useMapPlaceRender.ts +2 -6
  49. package/lib/map/usePlaceAutocomplete.ts +44 -50
  50. package/lib/map.ts +95 -0
  51. package/lib/pipeline/CandidatePicker.tsx +13 -5
  52. package/lib/pipeline/ConfidenceCell.tsx +1 -1
  53. package/lib/pipeline/FailureDiagnostic.tsx +8 -2
  54. package/lib/pipeline/QueryForm.tsx +5 -2
  55. package/lib/pipeline/ResolvedPlace.tsx +1 -1
  56. package/lib/pipeline/SpanHighlight.tsx +7 -5
  57. package/lib/pipeline/TimingPanel.tsx +1 -1
  58. package/lib/pipeline/TreeView.tsx +1 -1
  59. package/lib/pipeline/copy.ts +22 -25
  60. package/lib/pipeline/presets.ts +15 -13
  61. package/lib/pipeline/types.ts +21 -14
  62. package/lib/pipeline/useParsePipeline.ts +38 -24
  63. package/lib/pipeline.ts +36 -0
  64. package/lib/poi/AbstainPanel.tsx +1 -1
  65. package/lib/poi/LiveResultsBlock.tsx +2 -1
  66. package/lib/poi/POIExplorer.tsx +24 -15
  67. package/lib/poi/QueryInput.tsx +1 -1
  68. package/lib/poi/SubjectPanel.tsx +4 -3
  69. package/lib/poi/runtime.ts +5 -16
  70. package/lib/poi/types.ts +39 -27
  71. package/lib/poi/usePOISearch.ts +39 -44
  72. package/lib/poi.ts +39 -0
  73. package/lib/runtime/useReleaseRuntime.ts +125 -74
  74. package/lib/runtime.ts +16 -0
  75. package/lib/search/SearchModal.tsx +317 -0
  76. package/lib/search/search.css +144 -0
  77. package/lib/search/types.ts +67 -0
  78. package/lib/search.ts +11 -0
  79. package/out/common/About.d.ts +13 -4
  80. package/out/common/About.d.ts.map +1 -1
  81. package/out/common/About.js +5 -2
  82. package/out/common/About.js.map +1 -1
  83. package/out/common/ClientOnly.d.ts +2 -11
  84. package/out/common/ClientOnly.d.ts.map +1 -1
  85. package/out/common/ClientOnly.js +1 -13
  86. package/out/common/ClientOnly.js.map +1 -1
  87. package/out/common/CopyButton.d.ts +3 -1
  88. package/out/common/CopyButton.d.ts.map +1 -1
  89. package/out/common/CopyButton.js.map +1 -1
  90. package/out/common/LoadingIndicator.d.ts +4 -2
  91. package/out/common/LoadingIndicator.d.ts.map +1 -1
  92. package/out/common/LoadingIndicator.js.map +1 -1
  93. package/out/common/PresetChips.d.ts +9 -8
  94. package/out/common/PresetChips.d.ts.map +1 -1
  95. package/out/common/PresetChips.js.map +1 -1
  96. package/out/common/confidence-tiers.d.ts +7 -6
  97. package/out/common/confidence-tiers.d.ts.map +1 -1
  98. package/out/common/confidence-tiers.js +7 -6
  99. package/out/common/confidence-tiers.js.map +1 -1
  100. package/out/common/cx.d.ts +3 -1
  101. package/out/common/cx.d.ts.map +1 -1
  102. package/out/common/cx.js +3 -1
  103. package/out/common/cx.js.map +1 -1
  104. package/out/common/text-tokens.d.ts +4 -3
  105. package/out/common/text-tokens.d.ts.map +1 -1
  106. package/out/common/text-tokens.js +6 -3
  107. package/out/common/text-tokens.js.map +1 -1
  108. package/out/common/useBuildInfo.d.ts +27 -0
  109. package/out/common/useBuildInfo.d.ts.map +1 -0
  110. package/out/common/useBuildInfo.js +32 -0
  111. package/out/common/useBuildInfo.js.map +1 -0
  112. package/out/common/useClipboard.d.ts +1 -3
  113. package/out/common/useClipboard.d.ts.map +1 -1
  114. package/out/common/useClipboard.js +2 -11
  115. package/out/common/useClipboard.js.map +1 -1
  116. package/out/common.d.ts +22 -0
  117. package/out/common.d.ts.map +1 -0
  118. package/out/common.js +15 -0
  119. package/out/common.js.map +1 -0
  120. package/out/index.d.ts +26 -71
  121. package/out/index.d.ts.map +1 -1
  122. package/out/index.js +21 -47
  123. package/out/index.js.map +1 -1
  124. package/out/map/AppIdentity.d.ts +42 -0
  125. package/out/map/AppIdentity.d.ts.map +1 -0
  126. package/out/map/AppIdentity.js +16 -0
  127. package/out/map/AppIdentity.js.map +1 -0
  128. package/out/map/BackendControl.d.ts +9 -10
  129. package/out/map/BackendControl.d.ts.map +1 -1
  130. package/out/map/BackendControl.js +2 -2
  131. package/out/map/BackendControl.js.map +1 -1
  132. package/out/map/CompareToggle.d.ts +8 -31
  133. package/out/map/CompareToggle.d.ts.map +1 -1
  134. package/out/map/CompareToggle.js +5 -2
  135. package/out/map/CompareToggle.js.map +1 -1
  136. package/out/map/DebugInfo.d.ts +34 -0
  137. package/out/map/DebugInfo.d.ts.map +1 -0
  138. package/out/map/DebugInfo.js +39 -0
  139. package/out/map/DebugInfo.js.map +1 -0
  140. package/out/map/Geocoder.d.ts +47 -26
  141. package/out/map/Geocoder.d.ts.map +1 -1
  142. package/out/map/Geocoder.js +34 -50
  143. package/out/map/Geocoder.js.map +1 -1
  144. package/out/map/GeocoderControls.d.ts +23 -33
  145. package/out/map/GeocoderControls.d.ts.map +1 -1
  146. package/out/map/GeocoderControls.js +277 -16
  147. package/out/map/GeocoderControls.js.map +1 -1
  148. package/out/map/GraticuleLayer.d.ts +28 -0
  149. package/out/map/GraticuleLayer.d.ts.map +1 -0
  150. package/out/map/GraticuleLayer.js +25 -0
  151. package/out/map/GraticuleLayer.js.map +1 -0
  152. package/out/map/MapCanvas.d.ts +23 -12
  153. package/out/map/MapCanvas.d.ts.map +1 -1
  154. package/out/map/MapCanvas.js +5 -2
  155. package/out/map/MapCanvas.js.map +1 -1
  156. package/out/map/MapChipRow.d.ts +43 -0
  157. package/out/map/MapChipRow.d.ts.map +1 -0
  158. package/out/map/MapChipRow.js +12 -0
  159. package/out/map/MapChipRow.js.map +1 -0
  160. package/out/map/MapCompass.d.ts +33 -0
  161. package/out/map/MapCompass.d.ts.map +1 -0
  162. package/out/map/MapCompass.js +15 -0
  163. package/out/map/MapCompass.js.map +1 -0
  164. package/out/map/MapControlStack.d.ts +56 -0
  165. package/out/map/MapControlStack.d.ts.map +1 -0
  166. package/out/map/MapControlStack.js +18 -0
  167. package/out/map/MapControlStack.js.map +1 -0
  168. package/out/map/MapFooter.d.ts +27 -0
  169. package/out/map/MapFooter.d.ts.map +1 -0
  170. package/out/map/MapFooter.js +37 -0
  171. package/out/map/MapFooter.js.map +1 -0
  172. package/out/map/MapProgressBar.d.ts +31 -0
  173. package/out/map/MapProgressBar.d.ts.map +1 -0
  174. package/out/map/MapProgressBar.js +8 -0
  175. package/out/map/MapProgressBar.js.map +1 -0
  176. package/out/map/MapSearchBar.d.ts +48 -0
  177. package/out/map/MapSearchBar.d.ts.map +1 -0
  178. package/out/map/MapSearchBar.js +12 -0
  179. package/out/map/MapSearchBar.js.map +1 -0
  180. package/out/map/MapSheet.d.ts +35 -0
  181. package/out/map/MapSheet.d.ts.map +1 -0
  182. package/out/map/MapSheet.js +29 -0
  183. package/out/map/MapSheet.js.map +1 -0
  184. package/out/map/OverlayLayers.d.ts +1 -1
  185. package/out/map/OverlayLayers.js +2 -2
  186. package/out/map/PlaceAutocomplete.d.ts +10 -21
  187. package/out/map/PlaceAutocomplete.d.ts.map +1 -1
  188. package/out/map/PlaceAutocomplete.js +2 -1
  189. package/out/map/PlaceAutocomplete.js.map +1 -1
  190. package/out/map/PlaceMarker.d.ts +4 -2
  191. package/out/map/PlaceMarker.d.ts.map +1 -1
  192. package/out/map/PlaceMarker.js +3 -1
  193. package/out/map/PlaceMarker.js.map +1 -1
  194. package/out/map/ResolvedPlaceLayers.d.ts +5 -14
  195. package/out/map/ResolvedPlaceLayers.d.ts.map +1 -1
  196. package/out/map/ResolvedPlaceLayers.js +2 -2
  197. package/out/map/ResolvedPlaceLayers.js.map +1 -1
  198. package/out/map/ResultCamera.d.ts +8 -31
  199. package/out/map/ResultCamera.d.ts.map +1 -1
  200. package/out/map/ResultCamera.js +3 -28
  201. package/out/map/ResultCamera.js.map +1 -1
  202. package/out/map/ResultOverlay.d.ts +2 -12
  203. package/out/map/ResultOverlay.d.ts.map +1 -1
  204. package/out/map/ResultOverlay.js +1 -2
  205. package/out/map/ResultOverlay.js.map +1 -1
  206. package/out/map/ResultPanel.d.ts +1 -20
  207. package/out/map/ResultPanel.d.ts.map +1 -1
  208. package/out/map/ResultPanel.js +1 -1
  209. package/out/map/ResultPanel.js.map +1 -1
  210. package/out/map/VersionPicker.d.ts +7 -19
  211. package/out/map/VersionPicker.d.ts.map +1 -1
  212. package/out/map/VersionPicker.js +5 -2
  213. package/out/map/VersionPicker.js.map +1 -1
  214. package/out/map/fake-runtime.d.ts +9 -11
  215. package/out/map/fake-runtime.d.ts.map +1 -1
  216. package/out/map/fake-runtime.js +9 -12
  217. package/out/map/fake-runtime.js.map +1 -1
  218. package/out/map/geometry.d.ts +13 -34
  219. package/out/map/geometry.d.ts.map +1 -1
  220. package/out/map/geometry.js +9 -34
  221. package/out/map/geometry.js.map +1 -1
  222. package/out/map/graticule.d.ts +17 -0
  223. package/out/map/graticule.d.ts.map +1 -0
  224. package/out/map/graticule.js +67 -0
  225. package/out/map/graticule.js.map +1 -0
  226. package/out/map/map-debug.d.ts +1 -1
  227. package/out/map/map-debug.d.ts.map +1 -1
  228. package/out/map/map-debug.js +1 -1
  229. package/out/map/map-debug.js.map +1 -1
  230. package/out/map/place-render.d.ts +23 -43
  231. package/out/map/place-render.d.ts.map +1 -1
  232. package/out/map/place-render.js +4 -39
  233. package/out/map/place-render.js.map +1 -1
  234. package/out/map/types.d.ts +67 -95
  235. package/out/map/types.d.ts.map +1 -1
  236. package/out/map/types.js +1 -10
  237. package/out/map/types.js.map +1 -1
  238. package/out/map/useCompareState.d.ts +5 -4
  239. package/out/map/useCompareState.d.ts.map +1 -1
  240. package/out/map/useCompareState.js +3 -3
  241. package/out/map/useCompareState.js.map +1 -1
  242. package/out/map/useGeocode.d.ts +5 -3
  243. package/out/map/useGeocode.d.ts.map +1 -1
  244. package/out/map/useGeocode.js +4 -4
  245. package/out/map/useGeocode.js.map +1 -1
  246. package/out/map/useMapBearing.d.ts +28 -0
  247. package/out/map/useMapBearing.d.ts.map +1 -0
  248. package/out/map/useMapBearing.js +30 -0
  249. package/out/map/useMapBearing.js.map +1 -0
  250. package/out/map/useMapLabelPick.d.ts +13 -0
  251. package/out/map/useMapLabelPick.d.ts.map +1 -0
  252. package/out/map/useMapLabelPick.js +95 -0
  253. package/out/map/useMapLabelPick.js.map +1 -0
  254. package/out/map/useMapPlaceRender.d.ts +2 -6
  255. package/out/map/useMapPlaceRender.d.ts.map +1 -1
  256. package/out/map/useMapPlaceRender.js +2 -6
  257. package/out/map/useMapPlaceRender.js.map +1 -1
  258. package/out/map/usePlaceAutocomplete.d.ts +30 -28
  259. package/out/map/usePlaceAutocomplete.d.ts.map +1 -1
  260. package/out/map/usePlaceAutocomplete.js +6 -33
  261. package/out/map/usePlaceAutocomplete.js.map +1 -1
  262. package/out/map.d.ts +69 -0
  263. package/out/map.d.ts.map +1 -0
  264. package/out/map.js +46 -0
  265. package/out/map.js.map +1 -0
  266. package/out/pipeline/CandidatePicker.d.ts +12 -2
  267. package/out/pipeline/CandidatePicker.d.ts.map +1 -1
  268. package/out/pipeline/CandidatePicker.js +2 -2
  269. package/out/pipeline/CandidatePicker.js.map +1 -1
  270. package/out/pipeline/ConfidenceCell.d.ts +1 -1
  271. package/out/pipeline/ConfidenceCell.js +1 -1
  272. package/out/pipeline/FailureDiagnostic.d.ts +8 -2
  273. package/out/pipeline/FailureDiagnostic.d.ts.map +1 -1
  274. package/out/pipeline/FailureDiagnostic.js +3 -0
  275. package/out/pipeline/FailureDiagnostic.js.map +1 -1
  276. package/out/pipeline/PipelineExplorer.js +1 -1
  277. package/out/pipeline/QueryForm.d.ts +5 -2
  278. package/out/pipeline/QueryForm.d.ts.map +1 -1
  279. package/out/pipeline/QueryForm.js +1 -1
  280. package/out/pipeline/QueryForm.js.map +1 -1
  281. package/out/pipeline/ResolvedPlace.js +1 -1
  282. package/out/pipeline/SpanHighlight.d.ts +4 -3
  283. package/out/pipeline/SpanHighlight.d.ts.map +1 -1
  284. package/out/pipeline/SpanHighlight.js +3 -2
  285. package/out/pipeline/SpanHighlight.js.map +1 -1
  286. package/out/pipeline/TimingPanel.d.ts +1 -1
  287. package/out/pipeline/TimingPanel.js +1 -1
  288. package/out/pipeline/TreeView.d.ts +1 -1
  289. package/out/pipeline/copy.d.ts +1 -1
  290. package/out/pipeline/copy.d.ts.map +1 -1
  291. package/out/pipeline/copy.js +4 -3
  292. package/out/pipeline/copy.js.map +1 -1
  293. package/out/pipeline/presets.d.ts +5 -4
  294. package/out/pipeline/presets.d.ts.map +1 -1
  295. package/out/pipeline/presets.js +15 -13
  296. package/out/pipeline/presets.js.map +1 -1
  297. package/out/pipeline/types.d.ts +21 -14
  298. package/out/pipeline/types.d.ts.map +1 -1
  299. package/out/pipeline/types.js +2 -4
  300. package/out/pipeline/types.js.map +1 -1
  301. package/out/pipeline/useParsePipeline.d.ts +15 -7
  302. package/out/pipeline/useParsePipeline.d.ts.map +1 -1
  303. package/out/pipeline/useParsePipeline.js +10 -7
  304. package/out/pipeline/useParsePipeline.js.map +1 -1
  305. package/out/pipeline.d.ts +33 -0
  306. package/out/pipeline.d.ts.map +1 -0
  307. package/out/pipeline.js +21 -0
  308. package/out/pipeline.js.map +1 -0
  309. package/out/poi/AbstainPanel.d.ts +1 -1
  310. package/out/poi/LiveResultsBlock.d.ts +2 -1
  311. package/out/poi/LiveResultsBlock.d.ts.map +1 -1
  312. package/out/poi/LiveResultsBlock.js +1 -1
  313. package/out/poi/LiveResultsBlock.js.map +1 -1
  314. package/out/poi/POIExplorer.d.ts +22 -12
  315. package/out/poi/POIExplorer.d.ts.map +1 -1
  316. package/out/poi/POIExplorer.js +10 -9
  317. package/out/poi/POIExplorer.js.map +1 -1
  318. package/out/poi/QueryInput.d.ts +1 -1
  319. package/out/poi/SubjectPanel.d.ts +2 -2
  320. package/out/poi/SubjectPanel.d.ts.map +1 -1
  321. package/out/poi/SubjectPanel.js +3 -2
  322. package/out/poi/SubjectPanel.js.map +1 -1
  323. package/out/poi/runtime.d.ts +5 -14
  324. package/out/poi/runtime.d.ts.map +1 -1
  325. package/out/poi/runtime.js +5 -16
  326. package/out/poi/runtime.js.map +1 -1
  327. package/out/poi/types.d.ts +39 -27
  328. package/out/poi/types.d.ts.map +1 -1
  329. package/out/poi/types.js +2 -4
  330. package/out/poi/types.js.map +1 -1
  331. package/out/poi/usePOISearch.d.ts +28 -17
  332. package/out/poi/usePOISearch.d.ts.map +1 -1
  333. package/out/poi/usePOISearch.js +6 -32
  334. package/out/poi/usePOISearch.js.map +1 -1
  335. package/out/poi.d.ts +23 -0
  336. package/out/poi.d.ts.map +1 -0
  337. package/out/poi.js +15 -0
  338. package/out/poi.js.map +1 -0
  339. package/out/runtime/useReleaseRuntime.d.ts +64 -65
  340. package/out/runtime/useReleaseRuntime.d.ts.map +1 -1
  341. package/out/runtime/useReleaseRuntime.js +31 -26
  342. package/out/runtime/useReleaseRuntime.js.map +1 -1
  343. package/out/runtime.d.ts +9 -0
  344. package/out/runtime.d.ts.map +1 -0
  345. package/out/runtime.js +8 -0
  346. package/out/runtime.js.map +1 -0
  347. package/out/search/SearchModal.d.ts +33 -0
  348. package/out/search/SearchModal.d.ts.map +1 -0
  349. package/out/search/SearchModal.js +187 -0
  350. package/out/search/SearchModal.js.map +1 -0
  351. package/out/search/types.d.ts +64 -0
  352. package/out/search/types.d.ts.map +1 -0
  353. package/out/search/types.js +13 -0
  354. package/out/search/types.js.map +1 -0
  355. package/out/search.d.ts +11 -0
  356. package/out/search.d.ts.map +1 -0
  357. package/out/search.js +9 -0
  358. package/out/search.js.map +1 -0
  359. package/package.json +132 -133
  360. package/styles.css +1340 -202
  361. package/tokens/index.css +26 -7
  362. package/tokens/tokens.json +121 -6
  363. package/tokens/tokens.resolver.json +1 -1
  364. package/lib/map/index.ts +0 -76
  365. package/out/map/index.d.ts +0 -52
  366. package/out/map/index.d.ts.map +0 -1
  367. package/out/map/index.js +0 -36
  368. package/out/map/index.js.map +0 -1
  369. package/styleframe.config.ts +0 -321
  370. package/vitest.node.config.ts +0 -20
@@ -2,24 +2,9 @@
2
2
  * @copyright Sister Software
3
3
  * @license AGPL-3.0
4
4
  * @author Teffen Ellis, et al.
5
- *
6
- * `<Geocoder>` — the WHOLE geocoder, composed. It is the map analogue of `PipelineExplorer`
7
- * and takes the SAME DI shape: an injected {@link GeocoderRuntime} (the host owns ONNX / httpvfs / R2 /
8
- * the composed map style) plus a {@link GeocoderPanels} bag (the host's ModelVisualizer / VersionCompare /
9
- * About / Permalink). Everything here is composition + a `ClientOnly` boundary:
10
- *
11
- * - the floating {@link GeocoderControls} panel (version / compare / backend / query+autocomplete / result),
12
- * - the declarative {@link MapCanvas} with the phase-2 overlays ({@link OverlayLayers}) and the
13
- * resolved-place marker/outline/camera ({@link ResolvedPlaceLayers}) driven by the parse state,
14
- * - the hooks that wire them: {@link useGeocode} (parse + viewport bias + map place),
15
- * {@link usePlaceAutocomplete}, {@link useCompareState}.
16
- *
17
- * Because it pulls {@link MapCanvas} (→ `react-map-gl` → `maplibre-gl`, WebGL + DOM at import), it lives on
18
- * the `@mailwoman/react/map` subpath ONLY — never the package root. The whole thing renders in Storybook
19
- * over a fake runtime (offline stub style + canned geocode) with no network, no ONNX, no gazetteer.
20
5
  */
21
6
 
22
- import { type ReactNode, useCallback, useEffect, useRef } from "react"
7
+ import { type ReactNode, useCallback, useEffect, useRef, useState } from "react"
23
8
  import type { MapRef } from "react-map-gl/maplibre"
24
9
 
25
10
  import type { GeocoderPanels, GeocoderRuntime, MapBias } from "#map/types"
@@ -31,45 +16,80 @@ import { usePlaceAutocomplete } from "#map/usePlaceAutocomplete"
31
16
  import { ClientOnly } from "../common/ClientOnly.tsx"
32
17
  import type { Preset } from "../common/PresetChips.tsx"
33
18
  import { GeocoderControls } from "./GeocoderControls.tsx"
19
+ import { GraticuleLayer } from "./GraticuleLayer.tsx"
34
20
  import { MapCanvas } from "./MapCanvas.tsx"
35
21
  import { OverlayLayers } from "./OverlayLayers.tsx"
36
22
  import { ResolvedPlaceLayers } from "./ResolvedPlaceLayers.tsx"
37
23
 
24
+ /**
25
+ * Props for {@linkcode Geocoder}.
26
+ */
38
27
  export interface GeocoderProps {
39
28
  /**
40
- * The injected geocoder runtime (map style + overlays + parse + version/backend).
29
+ * The geocoder runtime supplies the map style and overlays.
30
+ *
31
+ * It also supplies the parser and version and backend controls.
41
32
  */
42
33
  runtime: GeocoderRuntime
43
34
  /**
44
- * Host-injected panels (about, release blurb, compare, permalink, debug drawer, map controls, …).
35
+ * Panels supplied by the host.
45
36
  */
46
37
  panels?: GeocoderPanels
47
38
  /**
48
- * Address to pre-fill.
39
+ * The address that pre-fills the search field.
40
+ * It is not run automatically.
49
41
  */
50
42
  defaultAddress?: string
51
43
  /**
52
- * Example chips. @default the empty set (host supplies its own).
44
+ * A query to run once when the runtime is ready, such as a permalink's `?q=` value.
45
+ *
46
+ * Unlike {@link GeocoderProps.defaultAddress}, this query is submitted,
47
+ * so a shared link reproduces its result.
48
+ */
49
+ initialQuery?: string | null
50
+ /**
51
+ * The example chips.
52
+ *
53
+ * @default []
53
54
  */
54
55
  presets?: ReadonlyArray<Preset>
55
56
  /**
56
- * Only hint the viewport bias once the visitor has zoomed past the global view — a whole-globe center is noise.
57
- * Matches the `map.getZoom() >= 4` threshold. @default 4
57
+ * Whether the developer panel starts open.
58
+ *
59
+ * @default false
60
+ */
61
+ developer?: boolean
62
+ /**
63
+ * Called with each user-submitted query.
64
+ *
65
+ * The host decides how to write the query to its URL.
66
+ * This package never touches `location`.
67
+ */
68
+ onSubmitQuery?: (query: string) => void
69
+ /**
70
+ * The minimum map zoom at which the viewport is sent as a location bias.
71
+ *
72
+ * @default 4
58
73
  */
59
74
  minBiasZoom?: number
60
75
  /**
61
- * Fly/fit the map to the resolved place on each result (via {@link ResolvedPlaceLayers}). @default true. Set false
62
- * for a host that drives the camera itself (a controlled `<MapCanvas viewState>`), or to keep a headless test
63
- * deterministic — the marker + outline still render, only the animated camera move is skipped.
76
+ * Whether the map moves to each resolved place.
77
+ *
78
+ * Set it to false when the host controls the camera or a test needs a fixed view.
79
+ * The marker and outline render either way.
80
+ *
81
+ * @default true
64
82
  */
65
83
  applyResultCamera?: boolean
66
84
  }
67
85
 
68
86
  interface GeocoderInnerProps extends Required<
69
- Pick<GeocoderProps, "runtime" | "defaultAddress" | "minBiasZoom" | "applyResultCamera">
87
+ Pick<GeocoderProps, "runtime" | "defaultAddress" | "minBiasZoom" | "applyResultCamera" | "developer">
70
88
  > {
71
89
  panels: GeocoderPanels
72
90
  presets: ReadonlyArray<Preset>
91
+ initialQuery: string | null
92
+ onSubmitQuery?: (query: string) => void
73
93
  }
74
94
 
75
95
  function GeocoderInner({
@@ -79,42 +99,44 @@ function GeocoderInner({
79
99
  presets,
80
100
  minBiasZoom,
81
101
  applyResultCamera,
102
+ developer,
103
+ initialQuery,
104
+ onSubmitQuery,
82
105
  }: GeocoderInnerProps): ReactNode {
83
106
  const mapRef = useRef<MapRef>(null)
107
+ // The controls render outside `<MapCanvas>` and cannot call `useMap()`.
108
+ // The map is kept in state so they re-render when it loads.
109
+ const [map, setMap] = useState<ReturnType<MapRef["getMap"]> | null>(null)
84
110
 
85
- // 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 live map handle is
87
- // republished on `globalThis.__mailwomanMapCanvas`. The ref fills only after react-map-gl instantiates
88
- // the map, hence the short poll; cleared on unmount so a torn-down geocoder never leaves a stale
89
- // handle behind.
90
- useEffect(() => {
91
- const host = globalThis as { __mailwomanMapCanvas?: ReturnType<MapRef["getMap"]> }
111
+ // The graticule is inserted before the first non-background layer, so it draws under the data layers.
112
+ const [baseLayerID, setBaseLayerID] = useState<string | undefined>(undefined)
92
113
 
93
- const timer = setInterval(() => {
94
- const map = mapRef.current?.getMap()
114
+ const onMapLoad = useCallback((event: { target: ReturnType<MapRef["getMap"]> }) => {
115
+ // Browser tests read the map from this global.
116
+ ;(globalThis as { __mailwomanMapCanvas?: ReturnType<MapRef["getMap"]> }).__mailwomanMapCanvas = event.target
117
+ setMap(event.target)
95
118
 
96
- if (map) {
97
- host.__mailwomanMapCanvas = map
98
- clearInterval(timer)
99
- }
100
- }, 250)
119
+ const layers = event.target.getStyle()?.layers ?? []
101
120
 
102
- return () => {
103
- clearInterval(timer)
104
- delete host.__mailwomanMapCanvas
105
- }
121
+ setBaseLayerID(layers.find((layer) => layer.type !== "background")?.id)
106
122
  }, [])
107
123
 
108
- // Read the viewport bias at submit time — through the map handle, never a threaded state value, so granting/zooming
109
- // mid-session doesn't re-create the parse callback. Below the min-bias zoom, a whole-globe center is noise → null.
124
+ useEffect(
125
+ () => () => {
126
+ setMap(null)
127
+ delete (globalThis as { __mailwomanMapCanvas?: ReturnType<MapRef["getMap"]> }).__mailwomanMapCanvas
128
+ },
129
+ []
130
+ )
131
+
110
132
  const getBias = useCallback((): MapBias | null => {
111
- const map = mapRef.current?.getMap()
133
+ const live = mapRef.current?.getMap()
112
134
 
113
- if (!map) return null
114
- const zoom = map.getZoom()
135
+ if (!live) return null
136
+ const zoom = live.getZoom()
115
137
 
116
138
  if (zoom < minBiasZoom) return null
117
- const center = map.getCenter()
139
+ const center = live.getCenter()
118
140
 
119
141
  return { center: [center.lng, center.lat], zoom }
120
142
  }, [minBiasZoom])
@@ -152,10 +174,11 @@ function GeocoderInner({
152
174
  zoom: runtime.initialZoom ?? 3,
153
175
  }}
154
176
  style={{ width: "100%", height: "100%" }}
155
- // One compact attribution pill (the map's own default is a wide, always-open "MapLibre | © …" bar), no
156
- // maplibre wordmark logo.
157
- mapProps={{ attributionControl: { compact: true }, maplibreLogo: false }}
177
+ // The attribution is compact.
178
+ // The MapLibre logo is hidden.
179
+ mapProps={{ attributionControl: { compact: true }, maplibreLogo: false, onLoad: onMapLoad }}
158
180
  >
181
+ <GraticuleLayer beforeID={baseLayerID} />
159
182
  <OverlayLayers overlays={runtime.overlays} />
160
183
  <ResolvedPlaceLayers spec={spec} applyCamera={applyResultCamera} />
161
184
  {panels.mapControls}
@@ -170,23 +193,28 @@ function GeocoderInner({
170
193
  panels={panels}
171
194
  presets={presets}
172
195
  placeholder={defaultAddress}
196
+ initialQuery={initialQuery}
197
+ map={map}
198
+ onSubmitQuery={onSubmitQuery}
173
199
  onSelectVersion={onSelectVersion}
174
200
  onForceWASMChange={onForceWASMChange}
201
+ developer={developer}
175
202
  />
176
-
177
203
  {panels.debugDrawer ? panels.debugDrawer({ result: geocode.result }) : null}
178
204
  </div>
179
205
  )
180
206
  }
181
207
 
182
- /**
183
- * Stable empty defaults — a fresh `{}`/`[]` per render would churn every downstream memo dep.
184
- */
208
+ // These defaults are module constants so each render sees the same reference and memo dependencies stay stable.
185
209
  const NO_PANELS: GeocoderPanels = {}
186
210
  const NO_PRESETS: ReadonlyArray<Preset> = []
187
211
 
188
212
  /**
189
- * The composed geocoder, behind a `ClientOnly` SSR boundary (the map is intrinsically a client component).
213
+ * Renders the map and search controls as one geocoder.
214
+ * It also renders host panels.
215
+ *
216
+ * It renders only on the client because MapLibre needs browser APIs.
217
+ * Import it from `@mailwoman/react/map`.
190
218
  */
191
219
  export function Geocoder({
192
220
  runtime,
@@ -195,6 +223,9 @@ export function Geocoder({
195
223
  presets = NO_PRESETS,
196
224
  minBiasZoom = 4,
197
225
  applyResultCamera = true,
226
+ developer = false,
227
+ initialQuery = null,
228
+ onSubmitQuery,
198
229
  }: GeocoderProps): ReactNode {
199
230
  return (
200
231
  <ClientOnly
@@ -212,6 +243,9 @@ export function Geocoder({
212
243
  presets={presets}
213
244
  minBiasZoom={minBiasZoom}
214
245
  applyResultCamera={applyResultCamera}
246
+ developer={developer}
247
+ initialQuery={initialQuery}
248
+ onSubmitQuery={onSubmitQuery}
215
249
  />
216
250
  )}
217
251
  </ClientOnly>