@mailwoman/react 8.0.0 → 8.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.
Files changed (192) hide show
  1. package/common/ClientOnly.tsx +6 -2
  2. package/common/CopyButton.tsx +9 -3
  3. package/common/KindBadge.tsx +1 -1
  4. package/common/LoadingIndicator.tsx +22 -7
  5. package/common/PresetChips.tsx +6 -2
  6. package/common/cx.ts +3 -1
  7. package/common/useClipboard.ts +7 -2
  8. package/index.ts +5 -0
  9. package/map/BackendControl.tsx +12 -4
  10. package/map/CompareToggle.tsx +27 -9
  11. package/map/DemoControls.tsx +31 -11
  12. package/map/DemoMap.tsx +33 -11
  13. package/map/GeocoderDemo.tsx +25 -8
  14. package/map/OverlayLayers.tsx +7 -3
  15. package/map/PlaceAutocomplete.tsx +25 -9
  16. package/map/PlaceMarker.tsx +18 -6
  17. package/map/ResolvedPlaceLayers.tsx +15 -5
  18. package/map/ResultCamera.tsx +6 -2
  19. package/map/ResultOverlay.tsx +18 -6
  20. package/map/ResultPanel.tsx +21 -7
  21. package/map/VersionPicker.tsx +18 -6
  22. package/map/geometry.ts +28 -8
  23. package/map/index.ts +3 -0
  24. package/map/place-render.ts +36 -12
  25. package/map/types.ts +132 -44
  26. package/map/useCompareState.ts +15 -5
  27. package/map/useDemoGeocode.ts +12 -4
  28. package/map/useMapPlaceRender.ts +3 -1
  29. package/map/usePlaceAutocomplete.ts +52 -18
  30. package/out/common/ClientOnly.d.ts +6 -2
  31. package/out/common/ClientOnly.d.ts.map +1 -1
  32. package/out/common/ClientOnly.js.map +1 -1
  33. package/out/common/CopyButton.d.ts +9 -3
  34. package/out/common/CopyButton.d.ts.map +1 -1
  35. package/out/common/CopyButton.js.map +1 -1
  36. package/out/common/KindBadge.js +1 -1
  37. package/out/common/KindBadge.js.map +1 -1
  38. package/out/common/LoadingIndicator.d.ts +21 -6
  39. package/out/common/LoadingIndicator.d.ts.map +1 -1
  40. package/out/common/LoadingIndicator.js +4 -1
  41. package/out/common/LoadingIndicator.js.map +1 -1
  42. package/out/common/PresetChips.d.ts +6 -2
  43. package/out/common/PresetChips.d.ts.map +1 -1
  44. package/out/common/PresetChips.js.map +1 -1
  45. package/out/common/cx.d.ts +3 -1
  46. package/out/common/cx.d.ts.map +1 -1
  47. package/out/common/cx.js +3 -1
  48. package/out/common/cx.js.map +1 -1
  49. package/out/common/useClipboard.d.ts +3 -1
  50. package/out/common/useClipboard.d.ts.map +1 -1
  51. package/out/common/useClipboard.js +6 -2
  52. package/out/common/useClipboard.js.map +1 -1
  53. package/out/index.d.ts.map +1 -1
  54. package/out/index.js.map +1 -1
  55. package/out/map/BackendControl.d.ts +12 -4
  56. package/out/map/BackendControl.d.ts.map +1 -1
  57. package/out/map/BackendControl.js +3 -1
  58. package/out/map/BackendControl.js.map +1 -1
  59. package/out/map/CompareToggle.d.ts +27 -9
  60. package/out/map/CompareToggle.d.ts.map +1 -1
  61. package/out/map/CompareToggle.js +3 -1
  62. package/out/map/CompareToggle.js.map +1 -1
  63. package/out/map/DemoControls.d.ts +30 -10
  64. package/out/map/DemoControls.d.ts.map +1 -1
  65. package/out/map/DemoControls.js +4 -2
  66. package/out/map/DemoControls.js.map +1 -1
  67. package/out/map/DemoMap.d.ts +33 -11
  68. package/out/map/DemoMap.d.ts.map +1 -1
  69. package/out/map/DemoMap.js.map +1 -1
  70. package/out/map/GeocoderDemo.d.ts +16 -6
  71. package/out/map/GeocoderDemo.d.ts.map +1 -1
  72. package/out/map/GeocoderDemo.js +9 -3
  73. package/out/map/GeocoderDemo.js.map +1 -1
  74. package/out/map/OverlayLayers.d.ts +6 -2
  75. package/out/map/OverlayLayers.d.ts.map +1 -1
  76. package/out/map/OverlayLayers.js +4 -2
  77. package/out/map/OverlayLayers.js.map +1 -1
  78. package/out/map/PlaceAutocomplete.d.ts +24 -8
  79. package/out/map/PlaceAutocomplete.d.ts.map +1 -1
  80. package/out/map/PlaceAutocomplete.js +4 -2
  81. package/out/map/PlaceAutocomplete.js.map +1 -1
  82. package/out/map/PlaceMarker.d.ts +15 -5
  83. package/out/map/PlaceMarker.d.ts.map +1 -1
  84. package/out/map/PlaceMarker.js +6 -2
  85. package/out/map/PlaceMarker.js.map +1 -1
  86. package/out/map/ResolvedPlaceLayers.d.ts +15 -5
  87. package/out/map/ResolvedPlaceLayers.d.ts.map +1 -1
  88. package/out/map/ResolvedPlaceLayers.js +3 -1
  89. package/out/map/ResolvedPlaceLayers.js.map +1 -1
  90. package/out/map/ResultCamera.d.ts +6 -2
  91. package/out/map/ResultCamera.d.ts.map +1 -1
  92. package/out/map/ResultCamera.js +3 -1
  93. package/out/map/ResultCamera.js.map +1 -1
  94. package/out/map/ResultOverlay.d.ts +15 -5
  95. package/out/map/ResultOverlay.d.ts.map +1 -1
  96. package/out/map/ResultOverlay.js +3 -1
  97. package/out/map/ResultOverlay.js.map +1 -1
  98. package/out/map/ResultPanel.d.ts +21 -7
  99. package/out/map/ResultPanel.d.ts.map +1 -1
  100. package/out/map/ResultPanel.js +3 -1
  101. package/out/map/ResultPanel.js.map +1 -1
  102. package/out/map/VersionPicker.d.ts +18 -6
  103. package/out/map/VersionPicker.d.ts.map +1 -1
  104. package/out/map/VersionPicker.js +3 -1
  105. package/out/map/VersionPicker.js.map +1 -1
  106. package/out/map/geometry.d.ts +12 -4
  107. package/out/map/geometry.d.ts.map +1 -1
  108. package/out/map/geometry.js +17 -5
  109. package/out/map/geometry.js.map +1 -1
  110. package/out/map/index.d.ts.map +1 -1
  111. package/out/map/index.js.map +1 -1
  112. package/out/map/place-render.d.ts +27 -9
  113. package/out/map/place-render.d.ts.map +1 -1
  114. package/out/map/place-render.js +9 -3
  115. package/out/map/place-render.js.map +1 -1
  116. package/out/map/types.d.ts +132 -44
  117. package/out/map/types.d.ts.map +1 -1
  118. package/out/map/useCompareState.d.ts +15 -5
  119. package/out/map/useCompareState.d.ts.map +1 -1
  120. package/out/map/useCompareState.js.map +1 -1
  121. package/out/map/useDemoGeocode.d.ts +12 -4
  122. package/out/map/useDemoGeocode.d.ts.map +1 -1
  123. package/out/map/useDemoGeocode.js.map +1 -1
  124. package/out/map/useMapPlaceRender.d.ts +3 -1
  125. package/out/map/useMapPlaceRender.d.ts.map +1 -1
  126. package/out/map/useMapPlaceRender.js +3 -1
  127. package/out/map/useMapPlaceRender.js.map +1 -1
  128. package/out/map/usePlaceAutocomplete.d.ts +45 -15
  129. package/out/map/usePlaceAutocomplete.d.ts.map +1 -1
  130. package/out/map/usePlaceAutocomplete.js +7 -3
  131. package/out/map/usePlaceAutocomplete.js.map +1 -1
  132. package/out/pipeline/ConfidenceCell.d.ts.map +1 -1
  133. package/out/pipeline/ConfidenceCell.js +9 -1
  134. package/out/pipeline/ConfidenceCell.js.map +1 -1
  135. package/out/pipeline/PipelineExplorer.d.ts +12 -4
  136. package/out/pipeline/PipelineExplorer.d.ts.map +1 -1
  137. package/out/pipeline/PipelineExplorer.js +6 -2
  138. package/out/pipeline/PipelineExplorer.js.map +1 -1
  139. package/out/pipeline/QueryForm.d.ts +6 -2
  140. package/out/pipeline/QueryForm.d.ts.map +1 -1
  141. package/out/pipeline/QueryForm.js +1 -1
  142. package/out/pipeline/QueryForm.js.map +1 -1
  143. package/out/pipeline/ResolvedPlace.js +1 -1
  144. package/out/pipeline/ResolvedPlace.js.map +1 -1
  145. package/out/pipeline/presets.d.ts +7 -0
  146. package/out/pipeline/presets.d.ts.map +1 -1
  147. package/out/pipeline/presets.js +7 -0
  148. package/out/pipeline/presets.js.map +1 -1
  149. package/out/pipeline/types.d.ts +60 -20
  150. package/out/pipeline/types.d.ts.map +1 -1
  151. package/out/pipeline/useParsePipeline.d.ts +12 -4
  152. package/out/pipeline/useParsePipeline.d.ts.map +1 -1
  153. package/out/pipeline/useParsePipeline.js +2 -2
  154. package/out/pipeline/useParsePipeline.js.map +1 -1
  155. package/out/poi/LiveResultsBlock.d.ts +6 -2
  156. package/out/poi/LiveResultsBlock.d.ts.map +1 -1
  157. package/out/poi/LiveResultsBlock.js +1 -1
  158. package/out/poi/LiveResultsBlock.js.map +1 -1
  159. package/out/poi/POIExplorer.d.ts +12 -4
  160. package/out/poi/POIExplorer.d.ts.map +1 -1
  161. package/out/poi/POIExplorer.js.map +1 -1
  162. package/out/poi/SubjectPanel.d.ts.map +1 -1
  163. package/out/poi/SubjectPanel.js +4 -2
  164. package/out/poi/SubjectPanel.js.map +1 -1
  165. package/out/poi/runtime.d.ts +9 -2
  166. package/out/poi/runtime.d.ts.map +1 -1
  167. package/out/poi/runtime.js +10 -3
  168. package/out/poi/runtime.js.map +1 -1
  169. package/out/poi/types.d.ts +40 -15
  170. package/out/poi/types.d.ts.map +1 -1
  171. package/out/poi/usePOISearch.d.ts +27 -9
  172. package/out/poi/usePOISearch.d.ts.map +1 -1
  173. package/out/poi/usePOISearch.js +5 -3
  174. package/out/poi/usePOISearch.js.map +1 -1
  175. package/out/runtime/useDemoRuntime.d.ts +81 -27
  176. package/out/runtime/useDemoRuntime.d.ts.map +1 -1
  177. package/out/runtime/useDemoRuntime.js.map +1 -1
  178. package/package.json +4 -4
  179. package/pipeline/ConfidenceCell.tsx +11 -1
  180. package/pipeline/PipelineExplorer.tsx +19 -6
  181. package/pipeline/QueryForm.tsx +7 -3
  182. package/pipeline/ResolvedPlace.tsx +2 -2
  183. package/pipeline/presets.ts +7 -0
  184. package/pipeline/types.ts +60 -20
  185. package/pipeline/useParsePipeline.ts +14 -6
  186. package/poi/LiveResultsBlock.tsx +7 -3
  187. package/poi/POIExplorer.tsx +14 -4
  188. package/poi/SubjectPanel.tsx +4 -2
  189. package/poi/runtime.ts +11 -3
  190. package/poi/types.ts +41 -15
  191. package/poi/usePOISearch.ts +34 -12
  192. package/runtime/useDemoRuntime.ts +82 -27
@@ -15,9 +15,13 @@
15
15
  import { type ReactNode, useEffect, useState } from "react"
16
16
 
17
17
  export interface ClientOnlyProps {
18
- /** Rendered once mounted in the browser. A thunk so its (browser-only) imports never run on the server. */
18
+ /**
19
+ * Rendered once mounted in the browser. A thunk so its (browser-only) imports never run on the server.
20
+ */
19
21
  children: () => ReactNode
20
- /** Rendered on the server and until the first client mount. */
22
+ /**
23
+ * Rendered on the server and until the first client mount.
24
+ */
21
25
  fallback?: ReactNode
22
26
  }
23
27
 
@@ -12,11 +12,17 @@ import type { ReactNode } from "react"
12
12
  import { useClipboard } from "./useClipboard.ts"
13
13
 
14
14
  export interface CopyButtonProps {
15
- /** The text to copy. If a thunk, it's evaluated at click time (so callers can copy the latest value). */
15
+ /**
16
+ * The text to copy. If a thunk, it's evaluated at click time (so callers can copy the latest value).
17
+ */
16
18
  value: string | (() => string)
17
- /** Label in the idle state. @default "Copy" */
19
+ /**
20
+ * Label in the idle state. @default "Copy"
21
+ */
18
22
  label?: ReactNode
19
- /** Label shown briefly after a successful copy. @default "✓ Copied" */
23
+ /**
24
+ * Label shown briefly after a successful copy. @default "✓ Copied"
25
+ */
20
26
  copiedLabel?: ReactNode
21
27
  className?: string
22
28
  disabled?: boolean
@@ -30,7 +30,7 @@ export function KindBadge({ kindResult }: KindBadgeProps): ReactNode {
30
30
  <strong>Kind:</strong> <code>{kindResult.kind}</code>{" "}
31
31
  <span className="mw-kind__confidence">({formatPct(kindResult.confidence)})</span>
32
32
  </summary>
33
- {kindResult.alternatives.length > 0 ? (
33
+ {kindResult.alternatives.length ? (
34
34
  <ul className="mw-kind__alternatives">
35
35
  {kindResult.alternatives.map((alt) => (
36
36
  <li key={alt.kind}>
@@ -16,17 +16,29 @@ import { cx } from "./cx.ts"
16
16
  export type LoadingMode = "pulse" | "spinner" | "staged"
17
17
 
18
18
  export interface LoadingIndicatorProps extends React.HTMLAttributes<HTMLDivElement> {
19
- /** @default "spinner" */
19
+ /**
20
+ * @default "spinner"
21
+ */
20
22
  mode?: LoadingMode
21
- /** Optional label; in staged mode it renders above the step list. */
23
+ /**
24
+ * Optional label; in staged mode it renders above the step list.
25
+ */
22
26
  label?: string
23
- /** Number of skeleton bars (pulse mode). @default 3 */
27
+ /**
28
+ * Number of skeleton bars (pulse mode). @default 3
29
+ */
24
30
  barCount?: number
25
- /** Spinner ring size. @default "medium" */
31
+ /**
32
+ * Spinner ring size. @default "medium"
33
+ */
26
34
  size?: "small" | "medium" | "large"
27
- /** Step labels (staged mode) — one row each. */
35
+ /**
36
+ * Step labels (staged mode) — one row each.
37
+ */
28
38
  steps?: string[]
29
- /** 0-based index of the active step; earlier steps are complete, later ones pending. @default -1 */
39
+ /**
40
+ * 0-based index of the active step; earlier steps are complete, later ones pending. @default -1
41
+ */
30
42
  activeStep?: number
31
43
  }
32
44
 
@@ -36,6 +48,9 @@ const SIZE_CLASS: Record<NonNullable<LoadingIndicatorProps["size"]>, string> = {
36
48
  large: "mw-spinner--large",
37
49
  }
38
50
 
51
+ /**
52
+ * Spinner, pulse or staged progress, depending on how long the caller expects to wait.
53
+ */
39
54
  export const LoadingIndicator = memo<LoadingIndicatorProps>(function LoadingIndicator({
40
55
  mode = "spinner",
41
56
  label,
@@ -71,7 +86,7 @@ const SpinnerRing = memo<{ size: NonNullable<LoadingIndicatorProps["size"]> }>(f
71
86
  })
72
87
 
73
88
  const StagedProgress = memo<{ steps?: string[]; activeStep: number }>(function StagedProgress({ steps, activeStep }) {
74
- if (!steps || steps.length === 0) return null
89
+ if (!steps || !steps.length) return null
75
90
 
76
91
  return (
77
92
  <ul className="mw-staged">
@@ -25,9 +25,13 @@ export interface PresetChipsProps {
25
25
  presets: ReadonlyArray<Preset>
26
26
  onPick: (value: string) => void
27
27
  disabled?: boolean
28
- /** Leading label. @default "Try:" */
28
+ /**
29
+ * Leading label. @default "Try:"
30
+ */
29
31
  caption?: string
30
- /** Optional trailing content rendered inside the chip row after the presets (e.g. an inline permalink button). */
32
+ /**
33
+ * Optional trailing content rendered inside the chip row after the presets (e.g. an inline permalink button).
34
+ */
31
35
  trailing?: ReactNode
32
36
  }
33
37
 
package/common/cx.ts CHANGED
@@ -10,7 +10,9 @@
10
10
 
11
11
  export type ClassValue = string | number | false | null | undefined | Record<string, boolean>
12
12
 
13
- /** Join truthy class tokens; object entries contribute their key when the value is truthy. */
13
+ /**
14
+ * Join truthy class tokens; object entries contribute their key when the value is truthy.
15
+ */
14
16
  export function cx(...values: ClassValue[]): string {
15
17
  const out: string[] = []
16
18
 
@@ -10,7 +10,9 @@
10
10
 
11
11
  import { useCallback, useEffect, useRef, useState } from "react"
12
12
 
13
- /** Best-effort clipboard write: async Clipboard API first, hidden-textarea `execCommand` fallback. */
13
+ /**
14
+ * Best-effort clipboard write: async Clipboard API first, hidden-textarea `execCommand` fallback.
15
+ */
14
16
  async function writeToClipboard(value: string): Promise<void> {
15
17
  try {
16
18
  await navigator.clipboard.writeText(value)
@@ -41,7 +43,9 @@ export interface UseClipboard {
41
43
  copy: (value: string) => Promise<void>
42
44
  }
43
45
 
44
- /** @param resetMs - How long the `copied` flag stays true after a successful copy. */
46
+ /**
47
+ * @param resetMs - How long the `copied` flag stays true after a successful copy.
48
+ */
45
49
  export function useClipboard(resetMs = 1500): UseClipboard {
46
50
  const [copied, setCopied] = useState(false)
47
51
  const timer = useRef<ReturnType<typeof setTimeout> | null>(null)
@@ -64,6 +68,7 @@ export function useClipboard(resetMs = 1500): UseClipboard {
64
68
  if (timer.current) {
65
69
  clearTimeout(timer.current)
66
70
  }
71
+
67
72
  timer.current = setTimeout(() => setCopied(false), resetMs)
68
73
  },
69
74
  [resetMs]
package/index.ts CHANGED
@@ -47,6 +47,7 @@ export type { QueryInputProps } from "./poi/QueryInput.tsx"
47
47
  export { formatDistance, loadPOIRuntime, POI_DEFAULT_TEXT, POI_PRESETS } from "./poi/runtime.ts"
48
48
  export { SubjectPanel } from "./poi/SubjectPanel.tsx"
49
49
  export type { SubjectPanelProps } from "./poi/SubjectPanel.tsx"
50
+
50
51
  export type {
51
52
  CategoryRecord,
52
53
  LiveSearchState,
@@ -62,6 +63,7 @@ export type {
62
63
  POISubjectBase,
63
64
  TaxonomyLookup,
64
65
  } from "./poi/types.ts"
66
+
65
67
  export { usePOISearch } from "./poi/usePOISearch.ts"
66
68
  export type { UsePOISearch, UsePOISearchOptions } from "./poi/usePOISearch.ts"
67
69
 
@@ -80,6 +82,7 @@ export { QueryForm } from "./pipeline/QueryForm.tsx"
80
82
  export type { QueryFormProps } from "./pipeline/QueryForm.tsx"
81
83
  export { ResolvedPlace } from "./pipeline/ResolvedPlace.tsx"
82
84
  export type { ResolvedPlaceProps } from "./pipeline/ResolvedPlace.tsx"
85
+
83
86
  export type {
84
87
  DualRoleView,
85
88
  FSTProvenance,
@@ -91,11 +94,13 @@ export type {
91
94
  ResolvedPlaceView,
92
95
  StageTiming,
93
96
  } from "./pipeline/types.ts"
97
+
94
98
  export { useParsePipeline } from "./pipeline/useParsePipeline.ts"
95
99
  export type { UseParsePipeline, UseParsePipelineOptions } from "./pipeline/useParsePipeline.ts"
96
100
 
97
101
  // ── Demo runtime (shared load orchestration; node-safe — no onnx/httpvfs/maplibre) ──
98
102
  export { useDemoRuntime } from "./runtime/useDemoRuntime.ts"
103
+
99
104
  export type {
100
105
  DemoAssetsLoadContext,
101
106
  DemoLoaderState,
@@ -14,15 +14,23 @@
14
14
  import type { ReactNode } from "react"
15
15
 
16
16
  export interface BackendControlProps {
17
- /** The backend the runtime resolved to (e.g. `webgpu (28 MB int8)`); empty before it is known. */
17
+ /**
18
+ * The backend the runtime resolved to (e.g. `webgpu (28 MB int8)`); empty before it is known.
19
+ */
18
20
  activeBackend?: string
19
- /** Whether the CPU/WASM backend is currently forced. */
21
+ /**
22
+ * Whether the CPU/WASM backend is currently forced.
23
+ */
20
24
  forceWASM: boolean
21
- /** Fired when the visitor toggles the "Force WASM" checkbox. */
25
+ /**
26
+ * Fired when the visitor toggles the "Force WASM" checkbox.
27
+ */
22
28
  onForceWASMChange: (forceWASM: boolean) => void
23
29
  }
24
30
 
25
- /** The backend indicator + WASM opt-out. */
31
+ /**
32
+ * The backend indicator + WASM opt-out.
33
+ */
26
34
  export function BackendControl({ activeBackend, forceWASM, onForceWASMChange }: BackendControlProps): ReactNode {
27
35
  return (
28
36
  <div className="mw-demo-backend">
@@ -16,25 +16,43 @@ import type { ReactNode } from "react"
16
16
  import type { DemoVersionOption } from "./types.ts"
17
17
 
18
18
  export interface CompareToggleProps {
19
- /** The selectable model bundles (the primary version is filtered out of the compare list). */
19
+ /**
20
+ * The selectable model bundles (the primary version is filtered out of the compare list).
21
+ */
20
22
  versions: ReadonlyArray<DemoVersionOption>
21
- /** The primary version, excluded from the compare options. */
23
+ /**
24
+ * The primary version, excluded from the compare options.
25
+ */
22
26
  primaryVersion: string | null
23
- /** Whether compare mode is on. */
27
+ /**
28
+ * Whether compare mode is on.
29
+ */
24
30
  compareMode: boolean
25
- /** Fired when the visitor flips compare mode. */
31
+ /**
32
+ * Fired when the visitor flips compare mode.
33
+ */
26
34
  onCompareModeChange: (compareMode: boolean) => void
27
- /** The version chosen to compare against, or `null` when none is chosen. */
35
+ /**
36
+ * The version chosen to compare against, or `null` when none is chosen.
37
+ */
28
38
  compareVersion: string | null
29
- /** Fired with the chosen compare version (or `null` when the empty option is picked). */
39
+ /**
40
+ * Fired with the chosen compare version (or `null` when the empty option is picked).
41
+ */
30
42
  onCompareVersionChange: (version: string | null) => void
31
- /** Disable the compare-version select (e.g. while a parse or compare load runs). */
43
+ /**
44
+ * Disable the compare-version select (e.g. while a parse or compare load runs).
45
+ */
32
46
  disabled?: boolean
33
- /** A status line rendered under the select (e.g. the compare backend, or a "Loading…" line). */
47
+ /**
48
+ * A status line rendered under the select (e.g. the compare backend, or a "Loading…" line).
49
+ */
34
50
  status?: ReactNode
35
51
  }
36
52
 
37
- /** The compare toggle + (when on) the compare-version selector. Renders `null` with fewer than two versions. */
53
+ /**
54
+ * The compare toggle + (when on) the compare-version selector. Renders `null` with fewer than two versions.
55
+ */
38
56
  export function CompareToggle({
39
57
  versions,
40
58
  primaryVersion,
@@ -30,27 +30,47 @@ import type { UsePlaceAutocomplete } from "./usePlaceAutocomplete.ts"
30
30
  import { VersionPicker } from "./VersionPicker.tsx"
31
31
 
32
32
  export interface DemoControlsProps {
33
- /** The injected demo runtime. */
33
+ /**
34
+ * The injected demo runtime.
35
+ */
34
36
  runtime: DemoRuntime
35
- /** The parse+resolve state machine. */
37
+ /**
38
+ * The parse+resolve state machine.
39
+ */
36
40
  geocode: UseDemoGeocode
37
- /** The place-autocomplete combobox state. */
41
+ /**
42
+ * The place-autocomplete combobox state.
43
+ */
38
44
  autocomplete: UsePlaceAutocomplete
39
- /** The compare-mode state. */
45
+ /**
46
+ * The compare-mode state.
47
+ */
40
48
  compare: UseCompareState
41
- /** Host-injected panels (about, release blurb, compare, permalink, extras, failure). */
49
+ /**
50
+ * Host-injected panels (about, release blurb, compare, permalink, extras, failure).
51
+ */
42
52
  panels: DemoPanels
43
- /** Example chips. */
53
+ /**
54
+ * Example chips.
55
+ */
44
56
  presets: ReadonlyArray<Preset>
45
- /** Input placeholder. */
57
+ /**
58
+ * Input placeholder.
59
+ */
46
60
  placeholder: string
47
- /** Select a model version (the composed demo also clears a now-colliding compare selection). */
61
+ /**
62
+ * Select a model version (the composed demo also clears a now-colliding compare selection).
63
+ */
48
64
  onSelectVersion: (version: string) => void
49
- /** Toggle the forced WASM backend. */
65
+ /**
66
+ * Toggle the forced WASM backend.
67
+ */
50
68
  onForceWASMChange: (forceWASM: boolean) => void
51
69
  }
52
70
 
53
- /** The floating control panel. */
71
+ /**
72
+ * The floating control panel.
73
+ */
54
74
  export function DemoControls({
55
75
  runtime,
56
76
  geocode,
@@ -130,7 +150,7 @@ export function DemoControls({
130
150
  {loading && !runtime.ready ? (
131
151
  <LoadingIndicator
132
152
  mode="staged"
133
- steps={loading.stepLabels.length > 0 ? loading.stepLabels : undefined}
153
+ steps={loading.stepLabels.length ? loading.stepLabels : undefined}
134
154
  activeStep={loading.stepIndex}
135
155
  label={loading.progress}
136
156
  />
package/map/DemoMap.tsx CHANGED
@@ -25,7 +25,9 @@ import type { CSSProperties, ReactNode, Ref } from "react"
25
25
  import { Map } from "react-map-gl/maplibre"
26
26
  import type { MapProps, MapRef, ViewStateChangeEvent } from "react-map-gl/maplibre"
27
27
 
28
- /** The style a `<DemoMap>` renders — a style URL or an inline/composed `StyleSpecification`. */
28
+ /**
29
+ * The style a `<DemoMap>` renders — a style URL or an inline/composed `StyleSpecification`.
30
+ */
29
31
  export type DemoMapStyle = NonNullable<MapProps["mapStyle"]>
30
32
 
31
33
  /**
@@ -37,25 +39,45 @@ export type DemoMapExtraProps = Partial<
37
39
  >
38
40
 
39
41
  export interface DemoMapProps {
40
- /** The map style — host-composed `StyleSpecification` or a style URL. */
42
+ /**
43
+ * The map style — host-composed `StyleSpecification` or a style URL.
44
+ */
41
45
  mapStyle: DemoMapStyle
42
- /** Uncontrolled initial camera. Use this OR `viewState`, not both. */
46
+ /**
47
+ * Uncontrolled initial camera. Use this OR `viewState`, not both.
48
+ */
43
49
  initialViewState?: MapProps["initialViewState"]
44
- /** Controlled camera. Pair with `onMove` to persist it. */
50
+ /**
51
+ * Controlled camera. Pair with `onMove` to persist it.
52
+ */
45
53
  viewState?: MapProps["viewState"]
46
- /** Fired on every camera change (drag/zoom/rotate) — the seam for viewport-bias persistence. */
54
+ /**
55
+ * Fired on every camera change (drag/zoom/rotate) — the seam for viewport-bias persistence.
56
+ */
47
57
  onMove?: (event: ViewStateChangeEvent) => void
48
- /** Map projection. @default "globe" (matches the docs `DashboardMap`). */
58
+ /**
59
+ * Map projection. @default "globe" (matches the docs `DashboardMap`).
60
+ */
49
61
  projection?: MapProps["projection"]
50
- /** Forwarded to the underlying `<Map>` for imperative access (`useMap`/`flyTo` in later phases). */
62
+ /**
63
+ * Forwarded to the underlying `<Map>` for imperative access (`useMap`/`flyTo` in later phases).
64
+ */
51
65
  mapRef?: Ref<MapRef>
52
- /** Overlays, markers, and controls — rendered as `<Map>` children. Empty in phase 1. */
66
+ /**
67
+ * Overlays, markers, and controls — rendered as `<Map>` children. Empty in phase 1.
68
+ */
53
69
  children?: ReactNode
54
- /** Class on the wrapper element. */
70
+ /**
71
+ * Class on the wrapper element.
72
+ */
55
73
  className?: string
56
- /** Inline style on the wrapper element (sizing lives here or on `.mw-demo-map`). */
74
+ /**
75
+ * Inline style on the wrapper element (sizing lives here or on `.mw-demo-map`).
76
+ */
57
77
  style?: CSSProperties
58
- /** Remaining `<Map>` props DemoMap does not surface explicitly. */
78
+ /**
79
+ * Remaining `<Map>` props DemoMap does not surface explicitly.
80
+ */
59
81
  mapProps?: DemoMapExtraProps
60
82
  }
61
83
 
@@ -23,7 +23,7 @@ import { type ReactNode, useCallback, useRef } from "react"
23
23
  import type { MapRef } from "react-map-gl/maplibre"
24
24
 
25
25
  import { ClientOnly } from "../common/ClientOnly.tsx"
26
- import { type Preset } from "../common/PresetChips.tsx"
26
+ import type { Preset } from "../common/PresetChips.tsx"
27
27
  import { DemoControls } from "./DemoControls.tsx"
28
28
  import { DemoMap } from "./DemoMap.tsx"
29
29
  import { OverlayLayers } from "./OverlayLayers.tsx"
@@ -35,13 +35,21 @@ import { useMapPlaceRender } from "./useMapPlaceRender.ts"
35
35
  import { usePlaceAutocomplete } from "./usePlaceAutocomplete.ts"
36
36
 
37
37
  export interface GeocoderDemoProps {
38
- /** The injected demo runtime (map style + overlays + parse + version/backend). */
38
+ /**
39
+ * The injected demo runtime (map style + overlays + parse + version/backend).
40
+ */
39
41
  runtime: DemoRuntime
40
- /** Host-injected panels (about, release blurb, compare, permalink, debug drawer, map controls, …). */
42
+ /**
43
+ * Host-injected panels (about, release blurb, compare, permalink, debug drawer, map controls, …).
44
+ */
41
45
  panels?: DemoPanels
42
- /** Address to pre-fill. */
46
+ /**
47
+ * Address to pre-fill.
48
+ */
43
49
  defaultAddress?: string
44
- /** Example chips. @default the empty set (host supplies its own). */
50
+ /**
51
+ * Example chips. @default the empty set (host supplies its own).
52
+ */
45
53
  presets?: ReadonlyArray<Preset>
46
54
  /**
47
55
  * Only hint the viewport bias once the visitor has zoomed past the global view — a whole-globe center is noise.
@@ -89,6 +97,7 @@ function GeocoderDemoInner({
89
97
 
90
98
  const geocode = useDemoGeocode({ runtime, defaultText: defaultAddress, getBias })
91
99
  const compare = useCompareState()
100
+
92
101
  const autocomplete = usePlaceAutocomplete({
93
102
  text: geocode.text,
94
103
  setText: geocode.setText,
@@ -146,12 +155,20 @@ function GeocoderDemoInner({
146
155
  )
147
156
  }
148
157
 
149
- /** The composed geocoder demo, behind a `ClientOnly` SSR boundary (the map is intrinsically a client component). */
158
+ /**
159
+ * Stable empty defaults — a fresh `{}`/`[]` per render would churn every downstream memo dep.
160
+ */
161
+ const NO_PANELS: DemoPanels = {}
162
+ const NO_PRESETS: ReadonlyArray<Preset> = []
163
+
164
+ /**
165
+ * The composed geocoder demo, behind a `ClientOnly` SSR boundary (the map is intrinsically a client component).
166
+ */
150
167
  export function GeocoderDemo({
151
168
  runtime,
152
- panels = {},
169
+ panels = NO_PANELS,
153
170
  defaultAddress = "",
154
- presets = [],
171
+ presets = NO_PRESETS,
155
172
  minBiasZoom = 4,
156
173
  applyResultCamera = true,
157
174
  }: GeocoderDemoProps): ReactNode {
@@ -19,13 +19,17 @@ import { Layer, Source } from "react-map-gl/maplibre"
19
19
  import type { OverlaySpec } from "./types.ts"
20
20
 
21
21
  export interface OverlayLayersProps {
22
- /** The overlays to render, in draw order (first is drawn first / lowest). */
22
+ /**
23
+ * The overlays to render, in draw order (first is drawn first / lowest).
24
+ */
23
25
  overlays?: OverlaySpec[]
24
26
  }
25
27
 
26
- /** Render each overlay as one `<Source>` and its `<Layer>`s, honoring the `visible` flag via `visibility`. */
28
+ /**
29
+ * Render each overlay as one `<Source>` and its `<Layer>`s, honoring the `visible` flag via `visibility`.
30
+ */
27
31
  export function OverlayLayers({ overlays }: OverlayLayersProps): ReactNode {
28
- if (!overlays || overlays.length === 0) return null
32
+ if (!overlays || !overlays.length) return null
29
33
 
30
34
  return (
31
35
  <>
@@ -18,23 +18,39 @@ import { cx } from "../common/cx.ts"
18
18
  import type { Suggestion } from "./types.ts"
19
19
 
20
20
  export interface PlaceAutocompleteProps {
21
- /** The suggestions to render (from {@link usePlaceAutocomplete}). */
21
+ /**
22
+ * The suggestions to render (from {@link usePlaceAutocomplete}).
23
+ */
22
24
  suggestions: Suggestion[]
23
- /** The keyboard-highlighted index; `-1` for none. */
25
+ /**
26
+ * The keyboard-highlighted index; `-1` for none.
27
+ */
24
28
  activeIndex: number
25
- /** Fired (with the suggestion `value`) when one is clicked. */
29
+ /**
30
+ * Fired (with the suggestion `value`) when one is clicked.
31
+ */
26
32
  onPick: (value: string) => void
27
- /** Fired with the index a pointer entered, so hover matches keyboard highlight. */
33
+ /**
34
+ * Fired with the index a pointer entered, so hover matches keyboard highlight.
35
+ */
28
36
  onHover?: (index: number) => void
29
- /** The listbox element id — pass `listboxId` from the hook (matches the input's `aria-controls`). */
37
+ /**
38
+ * The listbox element id — pass `listboxId` from the hook (matches the input's `aria-controls`).
39
+ */
30
40
  listboxId: string
31
- /** Build the option element id — pass `optionId` from the hook. */
41
+ /**
42
+ * Build the option element id — pass `optionId` from the hook.
43
+ */
32
44
  optionId: (index: number) => string
33
- /** Leading label. @default "Did you mean:" */
45
+ /**
46
+ * Leading label. @default "Did you mean:"
47
+ */
34
48
  caption?: string
35
49
  }
36
50
 
37
- /** The suggestion listbox. */
51
+ /**
52
+ * The suggestion listbox.
53
+ */
38
54
  export function PlaceAutocomplete({
39
55
  suggestions,
40
56
  activeIndex,
@@ -44,7 +60,7 @@ export function PlaceAutocomplete({
44
60
  optionId,
45
61
  caption = "Did you mean:",
46
62
  }: PlaceAutocompleteProps): ReactNode {
47
- if (suggestions.length === 0) return null
63
+ if (!suggestions.length) return null
48
64
 
49
65
  return (
50
66
  <div className="mw-demo-suggest" id={listboxId} role="listbox" aria-label="Place suggestions">
@@ -15,21 +15,33 @@
15
15
  import type { ReactNode } from "react"
16
16
  import { Marker } from "react-map-gl/maplibre"
17
17
 
18
- /** The house pink the demo has always drawn the resolved-place marker in. */
18
+ /**
19
+ * The house pink the demo has always drawn the resolved-place marker in.
20
+ */
19
21
  const MARKER_COLOR = "#e0367c"
20
22
 
21
23
  export interface PlaceMarkerProps {
22
- /** Marker longitude. */
24
+ /**
25
+ * Marker longitude.
26
+ */
23
27
  longitude: number
24
- /** Marker latitude. */
28
+ /**
29
+ * Marker latitude.
30
+ */
25
31
  latitude: number
26
- /** Pin color. @default the house pink. */
32
+ /**
33
+ * Pin color. @default the house pink.
34
+ */
27
35
  color?: string
28
- /** Which part of the marker sits on the coordinate. @default "center" (a symmetric dot). */
36
+ /**
37
+ * Which part of the marker sits on the coordinate. @default "center" (a symmetric dot).
38
+ */
29
39
  anchor?: "center" | "top" | "bottom" | "left" | "right"
30
40
  }
31
41
 
32
- /** A single resolved-place marker. Wraps `react-map-gl`'s `<Marker>` with the demo's default color. */
42
+ /**
43
+ * A single resolved-place marker. Wraps `react-map-gl`'s `<Marker>` with the demo's default color.
44
+ */
33
45
  export function PlaceMarker({
34
46
  longitude,
35
47
  latitude,
@@ -21,22 +21,32 @@ import { ResultCamera } from "./ResultCamera.tsx"
21
21
  import { ResultOverlay } from "./ResultOverlay.tsx"
22
22
 
23
23
  export interface ResolvedPlaceLayersProps {
24
- /** The render spec (from {@link useMapPlaceRender}); `null` renders nothing. */
24
+ /**
25
+ * The render spec (from {@link useMapPlaceRender}); `null` renders nothing.
26
+ */
25
27
  spec: MapPlaceRenderSpec | null
26
28
  /**
27
29
  * Apply the computed camera target via {@link ResultCamera}. @default true. Set false when the consumer drives the
28
30
  * camera itself (e.g. a controlled `<DemoMap viewState>` fed by {@link cameraToViewState}).
29
31
  */
30
32
  applyCamera?: boolean
31
- /** Animate the camera move. Forwarded to {@link ResultCamera}. @default true */
33
+ /**
34
+ * Animate the camera move. Forwarded to {@link ResultCamera}. @default true
35
+ */
32
36
  animateCamera?: boolean
33
- /** Source/layer id prefix for the outline. @default "mw-result" */
37
+ /**
38
+ * Source/layer id prefix for the outline. @default "mw-result"
39
+ */
34
40
  outlineId?: string
35
- /** Marker color. @default the house pink. */
41
+ /**
42
+ * Marker color. @default the house pink.
43
+ */
36
44
  markerColor?: string
37
45
  }
38
46
 
39
- /** Render the marker(s), outline, and (optional) camera move for one resolved place. */
47
+ /**
48
+ * Render the marker(s), outline, and (optional) camera move for one resolved place.
49
+ */
40
50
  export function ResolvedPlaceLayers({
41
51
  spec,
42
52
  applyCamera = true,
@@ -25,7 +25,9 @@ import { useMap } from "react-map-gl/maplibre"
25
25
  import type { MapCameraTarget } from "./place-render.ts"
26
26
 
27
27
  export interface ResultCameraProps {
28
- /** The camera target to animate to. `null` leaves the camera untouched (no result yet). */
28
+ /**
29
+ * The camera target to animate to. `null` leaves the camera untouched (no result yet).
30
+ */
29
31
  target: MapCameraTarget | null
30
32
  /**
31
33
  * Animate (`flyTo`/`fitBounds`) vs jump. @default true. When false, a `center` target jumps with `jumpTo`; a `bounds`
@@ -34,7 +36,9 @@ export interface ResultCameraProps {
34
36
  animate?: boolean
35
37
  }
36
38
 
37
- /** Drive the live map to `target`. No DOM of its own — it is a behavior mounted as a `<Map>` child. */
39
+ /**
40
+ * Drive the live map to `target`. No DOM of its own — it is a behavior mounted as a `<Map>` child.
41
+ */
38
42
  export function ResultCamera({ target, animate = true }: ResultCameraProps): ReactNode {
39
43
  const map = useMap()
40
44