@mailwoman/react 8.6.0 → 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -133,8 +133,8 @@ export function DemoControls({
133
133
  activeIndex={autocomplete.activeIndex}
134
134
  onPick={autocomplete.pick}
135
135
  onHover={autocomplete.setActiveIndex}
136
- listboxId={autocomplete.listboxId}
137
- optionId={autocomplete.optionId}
136
+ listboxID={autocomplete.listboxID}
137
+ optionID={autocomplete.optionID}
138
138
  />
139
139
 
140
140
  <PresetChips
@@ -35,13 +35,13 @@ export interface PlaceAutocompleteProps {
35
35
  */
36
36
  onHover?: (index: number) => void
37
37
  /**
38
- * The listbox element id — pass `listboxId` from the hook (matches the input's `aria-controls`).
38
+ * The listbox element id — pass `listboxID` from the hook (matches the input's `aria-controls`).
39
39
  */
40
- listboxId: string
40
+ listboxID: string
41
41
  /**
42
- * Build the option element id — pass `optionId` from the hook.
42
+ * Build the option element id — pass `optionID` from the hook.
43
43
  */
44
- optionId: (index: number) => string
44
+ optionID: (index: number) => string
45
45
  /**
46
46
  * Leading label. @default "Did you mean:"
47
47
  */
@@ -56,19 +56,19 @@ export function PlaceAutocomplete({
56
56
  activeIndex,
57
57
  onPick,
58
58
  onHover,
59
- listboxId,
60
- optionId,
59
+ listboxID,
60
+ optionID,
61
61
  caption = "Did you mean:",
62
62
  }: PlaceAutocompleteProps): ReactNode {
63
63
  if (!suggestions.length) return null
64
64
 
65
65
  return (
66
- <div className="mw-demo-suggest" id={listboxId} role="listbox" aria-label="Place suggestions">
66
+ <div className="mw-demo-suggest" id={listboxID} role="listbox" aria-label="Place suggestions">
67
67
  <span className="mw-demo-suggest__label">{caption}</span>
68
68
  {suggestions.map((s, i) => (
69
69
  <button
70
70
  key={`${s.value}-${i}`}
71
- id={optionId(i)}
71
+ id={optionID(i)}
72
72
  type="button"
73
73
  role="option"
74
74
  aria-selected={i === activeIndex}
@@ -37,7 +37,7 @@ export interface ResolvedPlaceLayersProps {
37
37
  /**
38
38
  * Source/layer id prefix for the outline. @default "mw-result"
39
39
  */
40
- outlineId?: string
40
+ outlineID?: string
41
41
  /**
42
42
  * Marker color. @default the house pink.
43
43
  */
@@ -51,7 +51,7 @@ export function ResolvedPlaceLayers({
51
51
  spec,
52
52
  applyCamera = true,
53
53
  animateCamera = true,
54
- outlineId,
54
+ outlineID,
55
55
  markerColor,
56
56
  }: ResolvedPlaceLayersProps): ReactNode {
57
57
  if (!spec) return null
@@ -66,7 +66,7 @@ export function ResolvedPlaceLayers({
66
66
  color={markerColor}
67
67
  />
68
68
  ))}
69
- <ResultOverlay outline={spec.outline} id={outlineId} color={markerColor} />
69
+ <ResultOverlay outline={spec.outline} id={outlineID} color={markerColor} />
70
70
  {applyCamera ? <ResultCamera target={spec.camera} animate={animateCamera} /> : null}
71
71
  </>
72
72
  )
@@ -19,11 +19,31 @@
19
19
  * value-key dance, no dependency-lint suppression.
20
20
  */
21
21
 
22
+ import type { FitBoundsOptions } from "maplibre-gl"
22
23
  import { type ReactNode, useEffect } from "react"
23
24
  import { useMap } from "react-map-gl/maplibre"
24
25
 
25
26
  import type { MapCameraTarget } from "./place-render.ts"
26
27
 
28
+ /**
29
+ * The `fitBounds` options for a `bounds` target — and the reason this is a named function rather than an object literal
30
+ * at the call site.
31
+ *
32
+ * `duration` is present ONLY on the non-animated path, and its ABSENCE on the animated one is load-bearing. maplibre's
33
+ * `Camera.flyTo` (which `fitBounds` funnels into via `_fitInternal`) branches on `'duration' in options`, not on the
34
+ * value: an explicitly-passed `duration: undefined` therefore survives the key test and is coerced with `+undefined` →
35
+ * `NaN`. Every ease frame then computes `k = easing(elapsed / NaN)` → `NaN`, the flight-path math yields a `NaN` world
36
+ * coordinate, and the FIRST frame throws `Invalid LngLat object: (NaN, NaN)` out of the RAF loop — before the map has
37
+ * moved at all, and with no `move` event to notice it by.
38
+ *
39
+ * Measured 2026-08-05 against maplibre-gl 5.24.0, same bounds and same map: `{padding: 40, duration: undefined}` →
40
+ * `map._easeOptions.duration = NaN` + the throw; `{padding: 40}` → `3937.7 ms` + a normal flight. So pass the key or
41
+ * don't — never pass it holding `undefined`.
42
+ */
43
+ export function fitBoundsOptionsFor(padding: number, animate: boolean): FitBoundsOptions {
44
+ return animate ? { padding } : { padding, duration: 0 }
45
+ }
46
+
27
47
  export interface ResultCameraProps {
28
48
  /**
29
49
  * The camera target to animate to. `null` leaves the camera untouched (no result yet).
@@ -57,7 +77,7 @@ export function ResultCamera({ target, animate = true }: ResultCameraProps): Rea
57
77
  return
58
78
  }
59
79
 
60
- instance.fitBounds(target.bounds, { padding: target.padding, duration: animate ? undefined : 0 })
80
+ instance.fitBounds(target.bounds, fitBoundsOptionsFor(target.padding, animate))
61
81
  }, [map, target, animate])
62
82
 
63
83
  return null
@@ -87,15 +87,15 @@ export interface UsePlaceAutocomplete {
87
87
  /**
88
88
  * The listbox element id (matches `inputProps["aria-controls"]`).
89
89
  */
90
- listboxId: string
90
+ listboxID: string
91
91
  /**
92
92
  * Build the option element id for suggestion `index`.
93
93
  */
94
- optionId: (index: number) => string
94
+ optionID: (index: number) => string
95
95
  }
96
96
 
97
97
  const LISTBOX_ID = "mw-demo-suggest-list"
98
- const optionId = (index: number) => `mw-demo-suggest-${index}`
98
+ const optionID = (index: number) => `mw-demo-suggest-${index}`
99
99
 
100
100
  /**
101
101
  * Extract the locality segment being typed — the text after the last comma, trimmed.
@@ -220,10 +220,10 @@ export function usePlaceAutocomplete({
220
220
  "aria-expanded": suggestions.length > 0,
221
221
  "aria-controls": LISTBOX_ID,
222
222
  "aria-autocomplete": "list",
223
- "aria-activedescendant": activeIndex >= 0 ? optionId(activeIndex) : undefined,
223
+ "aria-activedescendant": activeIndex >= 0 ? optionID(activeIndex) : undefined,
224
224
  autoComplete: "off",
225
225
  },
226
- listboxId: LISTBOX_ID,
227
- optionId,
226
+ listboxID: LISTBOX_ID,
227
+ optionID,
228
228
  }
229
229
  }
@@ -15,7 +15,7 @@ export function DemoControls({ runtime, geocode, autocomplete, compare, panels,
15
15
  const { busy, result, selectedCandidate } = geocode;
16
16
  const loading = runtime.loading;
17
17
  const errorMessage = geocode.parseError ?? runtime.errorMessage ?? null;
18
- return (_jsxs("section", { className: "mw-demo-controls", children: [panels.header, panels.releaseInfo, _jsx(VersionPicker, { versions: versions, selected: runtime.selectedVersion ?? null, onSelect: onSelectVersion, disabled: busy }), _jsx(BackendControl, { activeBackend: runtime.activeBackend, forceWASM: runtime.forceWASM ?? false, onForceWASMChange: onForceWASMChange }), _jsx(CompareToggle, { versions: versions, primaryVersion: runtime.selectedVersion ?? null, compareMode: compare.compareMode, onCompareModeChange: compare.setCompareMode, compareVersion: compare.compareVersion, onCompareVersionChange: compare.setCompareVersion, disabled: busy }), _jsx(QueryForm, { value: geocode.text, onChange: geocode.setText, onSubmit: geocode.submit, disabled: !runtime.ready, busy: busy, placeholder: placeholder, onKeyDown: autocomplete.onInputKeyDown, inputProps: autocomplete.inputProps }), panels.bias, _jsx(PlaceAutocomplete, { suggestions: autocomplete.suggestions, activeIndex: autocomplete.activeIndex, onPick: autocomplete.pick, onHover: autocomplete.setActiveIndex, listboxId: autocomplete.listboxId, optionId: autocomplete.optionId }), _jsx(PresetChips, { presets: presets, disabled: !runtime.ready || busy, onPick: (value) => {
18
+ return (_jsxs("section", { className: "mw-demo-controls", children: [panels.header, panels.releaseInfo, _jsx(VersionPicker, { versions: versions, selected: runtime.selectedVersion ?? null, onSelect: onSelectVersion, disabled: busy }), _jsx(BackendControl, { activeBackend: runtime.activeBackend, forceWASM: runtime.forceWASM ?? false, onForceWASMChange: onForceWASMChange }), _jsx(CompareToggle, { versions: versions, primaryVersion: runtime.selectedVersion ?? null, compareMode: compare.compareMode, onCompareModeChange: compare.setCompareMode, compareVersion: compare.compareVersion, onCompareVersionChange: compare.setCompareVersion, disabled: busy }), _jsx(QueryForm, { value: geocode.text, onChange: geocode.setText, onSubmit: geocode.submit, disabled: !runtime.ready, busy: busy, placeholder: placeholder, onKeyDown: autocomplete.onInputKeyDown, inputProps: autocomplete.inputProps }), panels.bias, _jsx(PlaceAutocomplete, { suggestions: autocomplete.suggestions, activeIndex: autocomplete.activeIndex, onPick: autocomplete.pick, onHover: autocomplete.setActiveIndex, listboxID: autocomplete.listboxID, optionID: autocomplete.optionID }), _jsx(PresetChips, { presets: presets, disabled: !runtime.ready || busy, onPick: (value) => {
19
19
  geocode.setText(value);
20
20
  geocode.reset();
21
21
  }, trailing: panels.permalink ? panels.permalink(geocode.text) : null }), loading && !runtime.ready ? (_jsx(LoadingIndicator, { mode: "staged", steps: loading.stepLabels.length ? loading.stepLabels : undefined, activeStep: loading.stepIndex, label: loading.progress })) : null, errorMessage ? _jsx("p", { className: "mw-error", children: errorMessage }) : null, panels.aboveResult ? panels.aboveResult({ result }) : null, busy ? (_jsx("div", { className: "mw-result", children: _jsx(LoadingIndicator, { mode: "staged", steps: runtime.parseStageLabels, activeStep: geocode.parseStage }) })) : result ? (panels.result ? (panels.result({
@@ -31,13 +31,13 @@ export interface PlaceAutocompleteProps {
31
31
  */
32
32
  onHover?: (index: number) => void;
33
33
  /**
34
- * The listbox element id — pass `listboxId` from the hook (matches the input's `aria-controls`).
34
+ * The listbox element id — pass `listboxID` from the hook (matches the input's `aria-controls`).
35
35
  */
36
- listboxId: string;
36
+ listboxID: string;
37
37
  /**
38
- * Build the option element id — pass `optionId` from the hook.
38
+ * Build the option element id — pass `optionID` from the hook.
39
39
  */
40
- optionId: (index: number) => string;
40
+ optionID: (index: number) => string;
41
41
  /**
42
42
  * Leading label. @default "Did you mean:"
43
43
  */
@@ -46,5 +46,5 @@ export interface PlaceAutocompleteProps {
46
46
  /**
47
47
  * The suggestion listbox.
48
48
  */
49
- export declare function PlaceAutocomplete({ suggestions, activeIndex, onPick, onHover, listboxId, optionId, caption, }: PlaceAutocompleteProps): ReactNode;
49
+ export declare function PlaceAutocomplete({ suggestions, activeIndex, onPick, onHover, listboxID, optionID, caption, }: PlaceAutocompleteProps): ReactNode;
50
50
  //# sourceMappingURL=PlaceAutocomplete.d.ts.map
@@ -3,9 +3,9 @@ import { cx } from "../common/cx.js";
3
3
  /**
4
4
  * The suggestion listbox.
5
5
  */
6
- export function PlaceAutocomplete({ suggestions, activeIndex, onPick, onHover, listboxId, optionId, caption = "Did you mean:", }) {
6
+ export function PlaceAutocomplete({ suggestions, activeIndex, onPick, onHover, listboxID, optionID, caption = "Did you mean:", }) {
7
7
  if (!suggestions.length)
8
8
  return null;
9
- return (_jsxs("div", { className: "mw-demo-suggest", id: listboxId, role: "listbox", "aria-label": "Place suggestions", children: [_jsx("span", { className: "mw-demo-suggest__label", children: caption }), suggestions.map((s, i) => (_jsx("button", { id: optionId(i), type: "button", role: "option", "aria-selected": i === activeIndex, className: cx("mw-chip", { "mw-chip--active": i === activeIndex }), onMouseEnter: () => onHover?.(i), onClick: () => onPick(s.value), title: s.placetype, children: s.label ?? s.value }, `${s.value}-${i}`)))] }));
9
+ return (_jsxs("div", { className: "mw-demo-suggest", id: listboxID, role: "listbox", "aria-label": "Place suggestions", children: [_jsx("span", { className: "mw-demo-suggest__label", children: caption }), suggestions.map((s, i) => (_jsx("button", { id: optionID(i), type: "button", role: "option", "aria-selected": i === activeIndex, className: cx("mw-chip", { "mw-chip--active": i === activeIndex }), onMouseEnter: () => onHover?.(i), onClick: () => onPick(s.value), title: s.placetype, children: s.label ?? s.value }, `${s.value}-${i}`)))] }));
10
10
  }
11
11
  //# sourceMappingURL=PlaceAutocomplete.js.map
@@ -31,7 +31,7 @@ export interface ResolvedPlaceLayersProps {
31
31
  /**
32
32
  * Source/layer id prefix for the outline. @default "mw-result"
33
33
  */
34
- outlineId?: string;
34
+ outlineID?: string;
35
35
  /**
36
36
  * Marker color. @default the house pink.
37
37
  */
@@ -40,5 +40,5 @@ export interface ResolvedPlaceLayersProps {
40
40
  /**
41
41
  * Render the marker(s), outline, and (optional) camera move for one resolved place.
42
42
  */
43
- export declare function ResolvedPlaceLayers({ spec, applyCamera, animateCamera, outlineId, markerColor, }: ResolvedPlaceLayersProps): ReactNode;
43
+ export declare function ResolvedPlaceLayers({ spec, applyCamera, animateCamera, outlineID, markerColor, }: ResolvedPlaceLayersProps): ReactNode;
44
44
  //# sourceMappingURL=ResolvedPlaceLayers.d.ts.map
@@ -5,9 +5,9 @@ import { ResultOverlay } from "./ResultOverlay.js";
5
5
  /**
6
6
  * Render the marker(s), outline, and (optional) camera move for one resolved place.
7
7
  */
8
- export function ResolvedPlaceLayers({ spec, applyCamera = true, animateCamera = true, outlineId, markerColor, }) {
8
+ export function ResolvedPlaceLayers({ spec, applyCamera = true, animateCamera = true, outlineID, markerColor, }) {
9
9
  if (!spec)
10
10
  return null;
11
- return (_jsxs(_Fragment, { children: [spec.markers.map(([longitude, latitude], index) => (_jsx(PlaceMarker, { longitude: longitude, latitude: latitude, color: markerColor }, `${longitude},${latitude},${index}`))), _jsx(ResultOverlay, { outline: spec.outline, id: outlineId, color: markerColor }), applyCamera ? _jsx(ResultCamera, { target: spec.camera, animate: animateCamera }) : null] }));
11
+ return (_jsxs(_Fragment, { children: [spec.markers.map(([longitude, latitude], index) => (_jsx(PlaceMarker, { longitude: longitude, latitude: latitude, color: markerColor }, `${longitude},${latitude},${index}`))), _jsx(ResultOverlay, { outline: spec.outline, id: outlineID, color: markerColor }), applyCamera ? _jsx(ResultCamera, { target: spec.camera, animate: animateCamera }) : null] }));
12
12
  }
13
13
  //# sourceMappingURL=ResolvedPlaceLayers.js.map
@@ -18,8 +18,25 @@
18
18
  * as the effect dependency re-runs the camera move exactly when the resolved place changes — no
19
19
  * value-key dance, no dependency-lint suppression.
20
20
  */
21
+ import type { FitBoundsOptions } from "maplibre-gl";
21
22
  import { type ReactNode } from "react";
22
23
  import type { MapCameraTarget } from "./place-render.ts";
24
+ /**
25
+ * The `fitBounds` options for a `bounds` target — and the reason this is a named function rather than an object literal
26
+ * at the call site.
27
+ *
28
+ * `duration` is present ONLY on the non-animated path, and its ABSENCE on the animated one is load-bearing. maplibre's
29
+ * `Camera.flyTo` (which `fitBounds` funnels into via `_fitInternal`) branches on `'duration' in options`, not on the
30
+ * value: an explicitly-passed `duration: undefined` therefore survives the key test and is coerced with `+undefined` →
31
+ * `NaN`. Every ease frame then computes `k = easing(elapsed / NaN)` → `NaN`, the flight-path math yields a `NaN` world
32
+ * coordinate, and the FIRST frame throws `Invalid LngLat object: (NaN, NaN)` out of the RAF loop — before the map has
33
+ * moved at all, and with no `move` event to notice it by.
34
+ *
35
+ * Measured 2026-08-05 against maplibre-gl 5.24.0, same bounds and same map: `{padding: 40, duration: undefined}` →
36
+ * `map._easeOptions.duration = NaN` + the throw; `{padding: 40}` → `3937.7 ms` + a normal flight. So pass the key or
37
+ * don't — never pass it holding `undefined`.
38
+ */
39
+ export declare function fitBoundsOptionsFor(padding: number, animate: boolean): FitBoundsOptions;
23
40
  export interface ResultCameraProps {
24
41
  /**
25
42
  * The camera target to animate to. `null` leaves the camera untouched (no result yet).
@@ -1 +1 @@
1
- {"version":3,"file":"ResultCamera.d.ts","sourceRoot":"","sources":["../../map/ResultCamera.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,KAAK,SAAS,EAAa,MAAM,OAAO,CAAA;AAGjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAExD,MAAM,WAAW,iBAAiB;IACjC;;OAEG;IACH,MAAM,EAAE,eAAe,GAAG,IAAI,CAAA;IAC9B;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CACjB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,OAAc,EAAE,EAAE,iBAAiB,GAAG,SAAS,CAsBrF"}
1
+ {"version":3,"file":"ResultCamera.d.ts","sourceRoot":"","sources":["../../map/ResultCamera.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,EAAE,KAAK,SAAS,EAAa,MAAM,OAAO,CAAA;AAGjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAExD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,gBAAgB,CAEvF;AAED,MAAM,WAAW,iBAAiB;IACjC;;OAEG;IACH,MAAM,EAAE,eAAe,GAAG,IAAI,CAAA;IAC9B;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CACjB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,OAAc,EAAE,EAAE,iBAAiB,GAAG,SAAS,CAsBrF"}
@@ -20,6 +20,24 @@
20
20
  */
21
21
  import { useEffect } from "react";
22
22
  import { useMap } from "react-map-gl/maplibre";
23
+ /**
24
+ * The `fitBounds` options for a `bounds` target — and the reason this is a named function rather than an object literal
25
+ * at the call site.
26
+ *
27
+ * `duration` is present ONLY on the non-animated path, and its ABSENCE on the animated one is load-bearing. maplibre's
28
+ * `Camera.flyTo` (which `fitBounds` funnels into via `_fitInternal`) branches on `'duration' in options`, not on the
29
+ * value: an explicitly-passed `duration: undefined` therefore survives the key test and is coerced with `+undefined` →
30
+ * `NaN`. Every ease frame then computes `k = easing(elapsed / NaN)` → `NaN`, the flight-path math yields a `NaN` world
31
+ * coordinate, and the FIRST frame throws `Invalid LngLat object: (NaN, NaN)` out of the RAF loop — before the map has
32
+ * moved at all, and with no `move` event to notice it by.
33
+ *
34
+ * Measured 2026-08-05 against maplibre-gl 5.24.0, same bounds and same map: `{padding: 40, duration: undefined}` →
35
+ * `map._easeOptions.duration = NaN` + the throw; `{padding: 40}` → `3937.7 ms` + a normal flight. So pass the key or
36
+ * don't — never pass it holding `undefined`.
37
+ */
38
+ export function fitBoundsOptionsFor(padding, animate) {
39
+ return animate ? { padding } : { padding, duration: 0 };
40
+ }
23
41
  /**
24
42
  * Drive the live map to `target`. No DOM of its own — it is a behavior mounted as a `<Map>` child.
25
43
  */
@@ -38,7 +56,7 @@ export function ResultCamera({ target, animate = true }) {
38
56
  }
39
57
  return;
40
58
  }
41
- instance.fitBounds(target.bounds, { padding: target.padding, duration: animate ? undefined : 0 });
59
+ instance.fitBounds(target.bounds, fitBoundsOptionsFor(target.padding, animate));
42
60
  }, [map, target, animate]);
43
61
  return null;
44
62
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ResultCamera.js","sourceRoot":"","sources":["../../map/ResultCamera.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAkB,SAAS,EAAE,MAAM,OAAO,CAAA;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAgB9C;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,EAAqB;IACzE,MAAM,GAAG,GAAG,MAAM,EAAE,CAAA;IAEpB,SAAS,CAAC,GAAG,EAAE;QACd,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,CAAA;QAEtC,IAAI,CAAC,QAAQ,IAAI,CAAC,MAAM;YAAE,OAAM;QAEhC,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC9B,IAAI,OAAO,EAAE,CAAC;gBACb,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;YAC7D,CAAC;iBAAM,CAAC;gBACP,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;YAC9D,CAAC;YAED,OAAM;QACP,CAAC;QAED,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IAClG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IAE1B,OAAO,IAAI,CAAA;AACZ,CAAC"}
1
+ {"version":3,"file":"ResultCamera.js","sourceRoot":"","sources":["../../map/ResultCamera.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,EAAkB,SAAS,EAAE,MAAM,OAAO,CAAA;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAI9C;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAe,EAAE,OAAgB;IACpE,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAA;AACxD,CAAC;AAcD;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,EAAqB;IACzE,MAAM,GAAG,GAAG,MAAM,EAAE,CAAA;IAEpB,SAAS,CAAC,GAAG,EAAE;QACd,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,CAAA;QAEtC,IAAI,CAAC,QAAQ,IAAI,CAAC,MAAM;YAAE,OAAM;QAEhC,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC9B,IAAI,OAAO,EAAE,CAAC;gBACb,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;YAC7D,CAAC;iBAAM,CAAC;gBACP,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;YAC9D,CAAC;YAED,OAAM;QACP,CAAC;QAED,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;IAChF,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IAE1B,OAAO,IAAI,CAAA;AACZ,CAAC"}
@@ -81,11 +81,11 @@ export interface UsePlaceAutocomplete {
81
81
  /**
82
82
  * The listbox element id (matches `inputProps["aria-controls"]`).
83
83
  */
84
- listboxId: string;
84
+ listboxID: string;
85
85
  /**
86
86
  * Build the option element id for suggestion `index`.
87
87
  */
88
- optionId: (index: number) => string;
88
+ optionID: (index: number) => string;
89
89
  }
90
90
  export declare function usePlaceAutocomplete({ text, setText, autocomplete, minChars, debounceMs, }: UsePlaceAutocompleteOptions): UsePlaceAutocomplete;
91
91
  //# sourceMappingURL=usePlaceAutocomplete.d.ts.map
@@ -17,7 +17,7 @@
17
17
  import { useCallback, useEffect, useRef, useState } from "react";
18
18
  import { useDebouncedValue } from "../common/useDebouncedValue.js";
19
19
  const LISTBOX_ID = "mw-demo-suggest-list";
20
- const optionId = (index) => `mw-demo-suggest-${index}`;
20
+ const optionID = (index) => `mw-demo-suggest-${index}`;
21
21
  /**
22
22
  * Extract the locality segment being typed — the text after the last comma, trimmed.
23
23
  */
@@ -116,11 +116,11 @@ export function usePlaceAutocomplete({ text, setText, autocomplete, minChars = 2
116
116
  "aria-expanded": suggestions.length > 0,
117
117
  "aria-controls": LISTBOX_ID,
118
118
  "aria-autocomplete": "list",
119
- "aria-activedescendant": activeIndex >= 0 ? optionId(activeIndex) : undefined,
119
+ "aria-activedescendant": activeIndex >= 0 ? optionID(activeIndex) : undefined,
120
120
  autoComplete: "off",
121
121
  },
122
- listboxId: LISTBOX_ID,
123
- optionId,
122
+ listboxID: LISTBOX_ID,
123
+ optionID,
124
124
  };
125
125
  }
126
126
  //# sourceMappingURL=usePlaceAutocomplete.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mailwoman/react",
3
- "version": "8.6.0",
3
+ "version": "9.0.0",
4
4
  "description": "React components + headless hooks for mailwoman — parse/geocode/POI explorers, Storybook-tested, Docusaurus-independent.",
5
5
  "license": "AGPL-3.0-only OR LicenseRef-Commercial",
6
6
  "repository": {
@@ -67,26 +67,26 @@
67
67
  "test:node": "vitest run --config vitest.node.config.ts"
68
68
  },
69
69
  "dependencies": {
70
- "@mailwoman/kind-classifier": "8.6.0",
71
- "@mailwoman/poi-taxonomy": "8.6.0",
72
- "@mailwoman/query-shape": "8.6.0"
70
+ "@mailwoman/kind-classifier": "9.0.0",
71
+ "@mailwoman/poi-taxonomy": "9.0.0",
72
+ "@mailwoman/query-shape": "9.0.0"
73
73
  },
74
74
  "devDependencies": {
75
- "@storybook/addon-docs": "^10.5.4",
76
- "@storybook/react-vite": "^10.5.4",
75
+ "@storybook/addon-docs": "^10.5.5",
76
+ "@storybook/react-vite": "^10.5.5",
77
77
  "@types/react": "^19.2.17",
78
78
  "@types/react-dom": "^19.2.3",
79
- "@vitejs/plugin-react": "^6.0.4",
79
+ "@vitejs/plugin-react": "^6.0.5",
80
80
  "@vitest/browser": "4.1.10",
81
81
  "@vitest/browser-playwright": "4.1.10",
82
82
  "maplibre-gl": "^5.24.0",
83
- "playwright": "^1.62.0",
83
+ "playwright": "^1.62.1",
84
84
  "react": "^19.2.8",
85
85
  "react-dom": "^19.2.8",
86
- "react-map-gl": "^8.1.1",
87
- "storybook": "^10.5.4",
86
+ "react-map-gl": "^8.1.2",
87
+ "storybook": "^10.5.5",
88
88
  "typescript": "^6.0.3",
89
- "vite": "^8.1.5",
89
+ "vite": "^8.2.0",
90
90
  "vitest": "4.1.10"
91
91
  },
92
92
  "peerDependencies": {