@wherabouts/react 0.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.
- package/dist/index.cjs +149 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +37 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +145 -0
- package/dist/index.js.map +1 -0
- package/package.json +51 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
|
|
5
|
+
// src/use-autocomplete.ts
|
|
6
|
+
function useAutocomplete(client, options = {}) {
|
|
7
|
+
const { debounceMs = 300, limit, country, state } = options;
|
|
8
|
+
const [query, setQuery] = react.useState("");
|
|
9
|
+
const [results, setResults] = react.useState([]);
|
|
10
|
+
const [loading, setLoading] = react.useState(false);
|
|
11
|
+
const [error, setError] = react.useState(null);
|
|
12
|
+
const abortRef = react.useRef(null);
|
|
13
|
+
const timerRef = react.useRef(null);
|
|
14
|
+
const handleSetQuery = react.useCallback((q) => {
|
|
15
|
+
setQuery(q);
|
|
16
|
+
}, []);
|
|
17
|
+
react.useEffect(() => {
|
|
18
|
+
if (timerRef.current) {
|
|
19
|
+
clearTimeout(timerRef.current);
|
|
20
|
+
}
|
|
21
|
+
if (abortRef.current) {
|
|
22
|
+
abortRef.current.abort();
|
|
23
|
+
}
|
|
24
|
+
if (!query.trim()) {
|
|
25
|
+
setResults([]);
|
|
26
|
+
setLoading(false);
|
|
27
|
+
setError(null);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
setLoading(true);
|
|
31
|
+
timerRef.current = setTimeout(async () => {
|
|
32
|
+
const controller = new AbortController();
|
|
33
|
+
abortRef.current = controller;
|
|
34
|
+
setError(null);
|
|
35
|
+
try {
|
|
36
|
+
const res = await client.addresses.autocomplete(
|
|
37
|
+
{ q: query, limit, country, state },
|
|
38
|
+
{ signal: controller.signal }
|
|
39
|
+
);
|
|
40
|
+
if (!controller.signal.aborted) {
|
|
41
|
+
setResults(res.results);
|
|
42
|
+
}
|
|
43
|
+
} catch (e) {
|
|
44
|
+
if (!controller.signal.aborted) {
|
|
45
|
+
setError(e instanceof Error ? e : new Error(String(e)));
|
|
46
|
+
setResults([]);
|
|
47
|
+
}
|
|
48
|
+
} finally {
|
|
49
|
+
if (!controller.signal.aborted) {
|
|
50
|
+
setLoading(false);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}, debounceMs);
|
|
54
|
+
return () => {
|
|
55
|
+
if (timerRef.current) {
|
|
56
|
+
clearTimeout(timerRef.current);
|
|
57
|
+
}
|
|
58
|
+
if (abortRef.current) {
|
|
59
|
+
abortRef.current.abort();
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}, [query, debounceMs, limit, country, state, client]);
|
|
63
|
+
return { query, setQuery: handleSetQuery, results, loading, error };
|
|
64
|
+
}
|
|
65
|
+
function useReverseGeocode(client, coords) {
|
|
66
|
+
const [address, setAddress] = react.useState(null);
|
|
67
|
+
const [distance, setDistance] = react.useState(null);
|
|
68
|
+
const [loading, setLoading] = react.useState(false);
|
|
69
|
+
const [error, setError] = react.useState(null);
|
|
70
|
+
const abortRef = react.useRef(null);
|
|
71
|
+
react.useEffect(() => {
|
|
72
|
+
if (abortRef.current) {
|
|
73
|
+
abortRef.current.abort();
|
|
74
|
+
}
|
|
75
|
+
if (!coords) {
|
|
76
|
+
setAddress(null);
|
|
77
|
+
setDistance(null);
|
|
78
|
+
setLoading(false);
|
|
79
|
+
setError(null);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const controller = new AbortController();
|
|
83
|
+
abortRef.current = controller;
|
|
84
|
+
setLoading(true);
|
|
85
|
+
setError(null);
|
|
86
|
+
client.addresses.reverse(coords, { signal: controller.signal }).then((res) => {
|
|
87
|
+
if (!controller.signal.aborted) {
|
|
88
|
+
setAddress(res.address);
|
|
89
|
+
setDistance(res.distance);
|
|
90
|
+
}
|
|
91
|
+
}).catch((e) => {
|
|
92
|
+
if (!controller.signal.aborted) {
|
|
93
|
+
setError(e instanceof Error ? e : new Error(String(e)));
|
|
94
|
+
}
|
|
95
|
+
}).finally(() => {
|
|
96
|
+
if (!controller.signal.aborted) {
|
|
97
|
+
setLoading(false);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
return () => {
|
|
101
|
+
controller.abort();
|
|
102
|
+
};
|
|
103
|
+
}, [coords?.lat, coords?.lng, client]);
|
|
104
|
+
return { address, distance, loading, error };
|
|
105
|
+
}
|
|
106
|
+
function useZoneContains(client, coords) {
|
|
107
|
+
const [zones, setZones] = react.useState([]);
|
|
108
|
+
const [loading, setLoading] = react.useState(false);
|
|
109
|
+
const [error, setError] = react.useState(null);
|
|
110
|
+
const abortRef = react.useRef(null);
|
|
111
|
+
react.useEffect(() => {
|
|
112
|
+
if (abortRef.current) {
|
|
113
|
+
abortRef.current.abort();
|
|
114
|
+
}
|
|
115
|
+
if (!coords) {
|
|
116
|
+
setZones([]);
|
|
117
|
+
setLoading(false);
|
|
118
|
+
setError(null);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const controller = new AbortController();
|
|
122
|
+
abortRef.current = controller;
|
|
123
|
+
setLoading(true);
|
|
124
|
+
setError(null);
|
|
125
|
+
client.zones.contains(coords, { signal: controller.signal }).then((res) => {
|
|
126
|
+
if (!controller.signal.aborted) {
|
|
127
|
+
setZones(res.zones);
|
|
128
|
+
}
|
|
129
|
+
}).catch((e) => {
|
|
130
|
+
if (!controller.signal.aborted) {
|
|
131
|
+
setError(e instanceof Error ? e : new Error(String(e)));
|
|
132
|
+
}
|
|
133
|
+
}).finally(() => {
|
|
134
|
+
if (!controller.signal.aborted) {
|
|
135
|
+
setLoading(false);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
return () => {
|
|
139
|
+
controller.abort();
|
|
140
|
+
};
|
|
141
|
+
}, [coords?.lat, coords?.lng, client]);
|
|
142
|
+
return { zones, loading, error };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
exports.useAutocomplete = useAutocomplete;
|
|
146
|
+
exports.useReverseGeocode = useReverseGeocode;
|
|
147
|
+
exports.useZoneContains = useZoneContains;
|
|
148
|
+
//# sourceMappingURL=index.cjs.map
|
|
149
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/use-autocomplete.ts","../src/use-reverse-geocode.ts","../src/use-zone-contains.ts"],"names":["useState","useRef","useCallback","useEffect"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { AddressSuggestion, WheraboutsClient } from \"@wherabouts/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\nexport interface UseAutocompleteOptions {\n\tcountry?: string;\n\tdebounceMs?: number;\n\tlimit?: number;\n\tstate?: string;\n}\n\nexport interface UseAutocompleteResult {\n\terror: Error | null;\n\tloading: boolean;\n\tquery: string;\n\tresults: AddressSuggestion[];\n\tsetQuery: (q: string) => void;\n}\n\nexport function useAutocomplete(\n\tclient: WheraboutsClient,\n\toptions: UseAutocompleteOptions = {}\n): UseAutocompleteResult {\n\tconst { debounceMs = 300, limit, country, state } = options;\n\n\tconst [query, setQuery] = useState(\"\");\n\tconst [results, setResults] = useState<AddressSuggestion[]>([]);\n\tconst [loading, setLoading] = useState(false);\n\tconst [error, setError] = useState<Error | null>(null);\n\n\tconst abortRef = useRef<AbortController | null>(null);\n\tconst timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n\t// Stable setter — consumers can safely pass this to input onChange\n\tconst handleSetQuery = useCallback((q: string) => {\n\t\tsetQuery(q);\n\t}, []);\n\n\tuseEffect(() => {\n\t\tif (timerRef.current) {\n\t\t\tclearTimeout(timerRef.current);\n\t\t}\n\t\tif (abortRef.current) {\n\t\t\tabortRef.current.abort();\n\t\t}\n\n\t\tif (!query.trim()) {\n\t\t\tsetResults([]);\n\t\t\tsetLoading(false);\n\t\t\tsetError(null);\n\t\t\treturn;\n\t\t}\n\n\t\tsetLoading(true);\n\n\t\ttimerRef.current = setTimeout(async () => {\n\t\t\tconst controller = new AbortController();\n\t\t\tabortRef.current = controller;\n\t\t\tsetError(null);\n\n\t\t\ttry {\n\t\t\t\tconst res = await client.addresses.autocomplete(\n\t\t\t\t\t{ q: query, limit, country, state },\n\t\t\t\t\t{ signal: controller.signal }\n\t\t\t\t);\n\t\t\t\tif (!controller.signal.aborted) {\n\t\t\t\t\tsetResults(res.results);\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tif (!controller.signal.aborted) {\n\t\t\t\t\tsetError(e instanceof Error ? e : new Error(String(e)));\n\t\t\t\t\tsetResults([]);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tif (!controller.signal.aborted) {\n\t\t\t\t\tsetLoading(false);\n\t\t\t\t}\n\t\t\t}\n\t\t}, debounceMs);\n\n\t\treturn () => {\n\t\t\tif (timerRef.current) {\n\t\t\t\tclearTimeout(timerRef.current);\n\t\t\t}\n\t\t\tif (abortRef.current) {\n\t\t\t\tabortRef.current.abort();\n\t\t\t}\n\t\t};\n\t}, [query, debounceMs, limit, country, state, client]);\n\n\treturn { query, setQuery: handleSetQuery, results, loading, error };\n}\n","import type { ReverseGeocodeAddress, WheraboutsClient } from \"@wherabouts/sdk\";\nimport { useEffect, useRef, useState } from \"react\";\n\nexport interface LatLng {\n\tlat: number;\n\tlng: number;\n}\n\nexport interface UseReverseGeocodeResult {\n\taddress: ReverseGeocodeAddress | null;\n\tdistance: number | null;\n\terror: Error | null;\n\tloading: boolean;\n}\n\nexport function useReverseGeocode(\n\tclient: WheraboutsClient,\n\tcoords: LatLng | null\n): UseReverseGeocodeResult {\n\tconst [address, setAddress] = useState<ReverseGeocodeAddress | null>(null);\n\tconst [distance, setDistance] = useState<number | null>(null);\n\tconst [loading, setLoading] = useState(false);\n\tconst [error, setError] = useState<Error | null>(null);\n\tconst abortRef = useRef<AbortController | null>(null);\n\n\tuseEffect(() => {\n\t\tif (abortRef.current) {\n\t\t\tabortRef.current.abort();\n\t\t}\n\n\t\tif (!coords) {\n\t\t\tsetAddress(null);\n\t\t\tsetDistance(null);\n\t\t\tsetLoading(false);\n\t\t\tsetError(null);\n\t\t\treturn;\n\t\t}\n\n\t\tconst controller = new AbortController();\n\t\tabortRef.current = controller;\n\t\tsetLoading(true);\n\t\tsetError(null);\n\n\t\tclient.addresses\n\t\t\t.reverse(coords, { signal: controller.signal })\n\t\t\t.then((res) => {\n\t\t\t\tif (!controller.signal.aborted) {\n\t\t\t\t\tsetAddress(res.address);\n\t\t\t\t\tsetDistance(res.distance);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch((e: unknown) => {\n\t\t\t\tif (!controller.signal.aborted) {\n\t\t\t\t\tsetError(e instanceof Error ? e : new Error(String(e)));\n\t\t\t\t}\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tif (!controller.signal.aborted) {\n\t\t\t\t\tsetLoading(false);\n\t\t\t\t}\n\t\t\t});\n\n\t\treturn () => {\n\t\t\tcontroller.abort();\n\t\t};\n\t}, [coords?.lat, coords?.lng, client]);\n\n\treturn { address, distance, loading, error };\n}\n","import type { WheraboutsClient, ZoneRecord } from \"@wherabouts/sdk\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport type { LatLng } from \"./use-reverse-geocode.ts\";\n\nexport interface UseZoneContainsResult {\n\terror: Error | null;\n\tloading: boolean;\n\tzones: ZoneRecord[];\n}\n\nexport function useZoneContains(\n\tclient: WheraboutsClient,\n\tcoords: LatLng | null\n): UseZoneContainsResult {\n\tconst [zones, setZones] = useState<ZoneRecord[]>([]);\n\tconst [loading, setLoading] = useState(false);\n\tconst [error, setError] = useState<Error | null>(null);\n\tconst abortRef = useRef<AbortController | null>(null);\n\n\tuseEffect(() => {\n\t\tif (abortRef.current) {\n\t\t\tabortRef.current.abort();\n\t\t}\n\n\t\tif (!coords) {\n\t\t\tsetZones([]);\n\t\t\tsetLoading(false);\n\t\t\tsetError(null);\n\t\t\treturn;\n\t\t}\n\n\t\tconst controller = new AbortController();\n\t\tabortRef.current = controller;\n\t\tsetLoading(true);\n\t\tsetError(null);\n\n\t\tclient.zones\n\t\t\t.contains(coords, { signal: controller.signal })\n\t\t\t.then((res) => {\n\t\t\t\tif (!controller.signal.aborted) {\n\t\t\t\t\tsetZones(res.zones);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch((e: unknown) => {\n\t\t\t\tif (!controller.signal.aborted) {\n\t\t\t\t\tsetError(e instanceof Error ? e : new Error(String(e)));\n\t\t\t\t}\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tif (!controller.signal.aborted) {\n\t\t\t\t\tsetLoading(false);\n\t\t\t\t}\n\t\t\t});\n\n\t\treturn () => {\n\t\t\tcontroller.abort();\n\t\t};\n\t}, [coords?.lat, coords?.lng, client]);\n\n\treturn { zones, loading, error };\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { AddressSuggestion, WheraboutsClient, ReverseGeocodeAddress, ZoneRecord } from '@wherabouts/sdk';
|
|
2
|
+
|
|
3
|
+
interface UseAutocompleteOptions {
|
|
4
|
+
country?: string;
|
|
5
|
+
debounceMs?: number;
|
|
6
|
+
limit?: number;
|
|
7
|
+
state?: string;
|
|
8
|
+
}
|
|
9
|
+
interface UseAutocompleteResult {
|
|
10
|
+
error: Error | null;
|
|
11
|
+
loading: boolean;
|
|
12
|
+
query: string;
|
|
13
|
+
results: AddressSuggestion[];
|
|
14
|
+
setQuery: (q: string) => void;
|
|
15
|
+
}
|
|
16
|
+
declare function useAutocomplete(client: WheraboutsClient, options?: UseAutocompleteOptions): UseAutocompleteResult;
|
|
17
|
+
|
|
18
|
+
interface LatLng {
|
|
19
|
+
lat: number;
|
|
20
|
+
lng: number;
|
|
21
|
+
}
|
|
22
|
+
interface UseReverseGeocodeResult {
|
|
23
|
+
address: ReverseGeocodeAddress | null;
|
|
24
|
+
distance: number | null;
|
|
25
|
+
error: Error | null;
|
|
26
|
+
loading: boolean;
|
|
27
|
+
}
|
|
28
|
+
declare function useReverseGeocode(client: WheraboutsClient, coords: LatLng | null): UseReverseGeocodeResult;
|
|
29
|
+
|
|
30
|
+
interface UseZoneContainsResult {
|
|
31
|
+
error: Error | null;
|
|
32
|
+
loading: boolean;
|
|
33
|
+
zones: ZoneRecord[];
|
|
34
|
+
}
|
|
35
|
+
declare function useZoneContains(client: WheraboutsClient, coords: LatLng | null): UseZoneContainsResult;
|
|
36
|
+
|
|
37
|
+
export { type LatLng, type UseAutocompleteOptions, type UseAutocompleteResult, type UseReverseGeocodeResult, type UseZoneContainsResult, useAutocomplete, useReverseGeocode, useZoneContains };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { AddressSuggestion, WheraboutsClient, ReverseGeocodeAddress, ZoneRecord } from '@wherabouts/sdk';
|
|
2
|
+
|
|
3
|
+
interface UseAutocompleteOptions {
|
|
4
|
+
country?: string;
|
|
5
|
+
debounceMs?: number;
|
|
6
|
+
limit?: number;
|
|
7
|
+
state?: string;
|
|
8
|
+
}
|
|
9
|
+
interface UseAutocompleteResult {
|
|
10
|
+
error: Error | null;
|
|
11
|
+
loading: boolean;
|
|
12
|
+
query: string;
|
|
13
|
+
results: AddressSuggestion[];
|
|
14
|
+
setQuery: (q: string) => void;
|
|
15
|
+
}
|
|
16
|
+
declare function useAutocomplete(client: WheraboutsClient, options?: UseAutocompleteOptions): UseAutocompleteResult;
|
|
17
|
+
|
|
18
|
+
interface LatLng {
|
|
19
|
+
lat: number;
|
|
20
|
+
lng: number;
|
|
21
|
+
}
|
|
22
|
+
interface UseReverseGeocodeResult {
|
|
23
|
+
address: ReverseGeocodeAddress | null;
|
|
24
|
+
distance: number | null;
|
|
25
|
+
error: Error | null;
|
|
26
|
+
loading: boolean;
|
|
27
|
+
}
|
|
28
|
+
declare function useReverseGeocode(client: WheraboutsClient, coords: LatLng | null): UseReverseGeocodeResult;
|
|
29
|
+
|
|
30
|
+
interface UseZoneContainsResult {
|
|
31
|
+
error: Error | null;
|
|
32
|
+
loading: boolean;
|
|
33
|
+
zones: ZoneRecord[];
|
|
34
|
+
}
|
|
35
|
+
declare function useZoneContains(client: WheraboutsClient, coords: LatLng | null): UseZoneContainsResult;
|
|
36
|
+
|
|
37
|
+
export { type LatLng, type UseAutocompleteOptions, type UseAutocompleteResult, type UseReverseGeocodeResult, type UseZoneContainsResult, useAutocomplete, useReverseGeocode, useZoneContains };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { useState, useRef, useCallback, useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
// src/use-autocomplete.ts
|
|
4
|
+
function useAutocomplete(client, options = {}) {
|
|
5
|
+
const { debounceMs = 300, limit, country, state } = options;
|
|
6
|
+
const [query, setQuery] = useState("");
|
|
7
|
+
const [results, setResults] = useState([]);
|
|
8
|
+
const [loading, setLoading] = useState(false);
|
|
9
|
+
const [error, setError] = useState(null);
|
|
10
|
+
const abortRef = useRef(null);
|
|
11
|
+
const timerRef = useRef(null);
|
|
12
|
+
const handleSetQuery = useCallback((q) => {
|
|
13
|
+
setQuery(q);
|
|
14
|
+
}, []);
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
if (timerRef.current) {
|
|
17
|
+
clearTimeout(timerRef.current);
|
|
18
|
+
}
|
|
19
|
+
if (abortRef.current) {
|
|
20
|
+
abortRef.current.abort();
|
|
21
|
+
}
|
|
22
|
+
if (!query.trim()) {
|
|
23
|
+
setResults([]);
|
|
24
|
+
setLoading(false);
|
|
25
|
+
setError(null);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
setLoading(true);
|
|
29
|
+
timerRef.current = setTimeout(async () => {
|
|
30
|
+
const controller = new AbortController();
|
|
31
|
+
abortRef.current = controller;
|
|
32
|
+
setError(null);
|
|
33
|
+
try {
|
|
34
|
+
const res = await client.addresses.autocomplete(
|
|
35
|
+
{ q: query, limit, country, state },
|
|
36
|
+
{ signal: controller.signal }
|
|
37
|
+
);
|
|
38
|
+
if (!controller.signal.aborted) {
|
|
39
|
+
setResults(res.results);
|
|
40
|
+
}
|
|
41
|
+
} catch (e) {
|
|
42
|
+
if (!controller.signal.aborted) {
|
|
43
|
+
setError(e instanceof Error ? e : new Error(String(e)));
|
|
44
|
+
setResults([]);
|
|
45
|
+
}
|
|
46
|
+
} finally {
|
|
47
|
+
if (!controller.signal.aborted) {
|
|
48
|
+
setLoading(false);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}, debounceMs);
|
|
52
|
+
return () => {
|
|
53
|
+
if (timerRef.current) {
|
|
54
|
+
clearTimeout(timerRef.current);
|
|
55
|
+
}
|
|
56
|
+
if (abortRef.current) {
|
|
57
|
+
abortRef.current.abort();
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}, [query, debounceMs, limit, country, state, client]);
|
|
61
|
+
return { query, setQuery: handleSetQuery, results, loading, error };
|
|
62
|
+
}
|
|
63
|
+
function useReverseGeocode(client, coords) {
|
|
64
|
+
const [address, setAddress] = useState(null);
|
|
65
|
+
const [distance, setDistance] = useState(null);
|
|
66
|
+
const [loading, setLoading] = useState(false);
|
|
67
|
+
const [error, setError] = useState(null);
|
|
68
|
+
const abortRef = useRef(null);
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
if (abortRef.current) {
|
|
71
|
+
abortRef.current.abort();
|
|
72
|
+
}
|
|
73
|
+
if (!coords) {
|
|
74
|
+
setAddress(null);
|
|
75
|
+
setDistance(null);
|
|
76
|
+
setLoading(false);
|
|
77
|
+
setError(null);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const controller = new AbortController();
|
|
81
|
+
abortRef.current = controller;
|
|
82
|
+
setLoading(true);
|
|
83
|
+
setError(null);
|
|
84
|
+
client.addresses.reverse(coords, { signal: controller.signal }).then((res) => {
|
|
85
|
+
if (!controller.signal.aborted) {
|
|
86
|
+
setAddress(res.address);
|
|
87
|
+
setDistance(res.distance);
|
|
88
|
+
}
|
|
89
|
+
}).catch((e) => {
|
|
90
|
+
if (!controller.signal.aborted) {
|
|
91
|
+
setError(e instanceof Error ? e : new Error(String(e)));
|
|
92
|
+
}
|
|
93
|
+
}).finally(() => {
|
|
94
|
+
if (!controller.signal.aborted) {
|
|
95
|
+
setLoading(false);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
return () => {
|
|
99
|
+
controller.abort();
|
|
100
|
+
};
|
|
101
|
+
}, [coords?.lat, coords?.lng, client]);
|
|
102
|
+
return { address, distance, loading, error };
|
|
103
|
+
}
|
|
104
|
+
function useZoneContains(client, coords) {
|
|
105
|
+
const [zones, setZones] = useState([]);
|
|
106
|
+
const [loading, setLoading] = useState(false);
|
|
107
|
+
const [error, setError] = useState(null);
|
|
108
|
+
const abortRef = useRef(null);
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
if (abortRef.current) {
|
|
111
|
+
abortRef.current.abort();
|
|
112
|
+
}
|
|
113
|
+
if (!coords) {
|
|
114
|
+
setZones([]);
|
|
115
|
+
setLoading(false);
|
|
116
|
+
setError(null);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const controller = new AbortController();
|
|
120
|
+
abortRef.current = controller;
|
|
121
|
+
setLoading(true);
|
|
122
|
+
setError(null);
|
|
123
|
+
client.zones.contains(coords, { signal: controller.signal }).then((res) => {
|
|
124
|
+
if (!controller.signal.aborted) {
|
|
125
|
+
setZones(res.zones);
|
|
126
|
+
}
|
|
127
|
+
}).catch((e) => {
|
|
128
|
+
if (!controller.signal.aborted) {
|
|
129
|
+
setError(e instanceof Error ? e : new Error(String(e)));
|
|
130
|
+
}
|
|
131
|
+
}).finally(() => {
|
|
132
|
+
if (!controller.signal.aborted) {
|
|
133
|
+
setLoading(false);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
return () => {
|
|
137
|
+
controller.abort();
|
|
138
|
+
};
|
|
139
|
+
}, [coords?.lat, coords?.lng, client]);
|
|
140
|
+
return { zones, loading, error };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export { useAutocomplete, useReverseGeocode, useZoneContains };
|
|
144
|
+
//# sourceMappingURL=index.js.map
|
|
145
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/use-autocomplete.ts","../src/use-reverse-geocode.ts","../src/use-zone-contains.ts"],"names":["useState","useRef","useEffect"],"mappings":"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","file":"index.js","sourcesContent":["import type { AddressSuggestion, WheraboutsClient } from \"@wherabouts/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\nexport interface UseAutocompleteOptions {\n\tcountry?: string;\n\tdebounceMs?: number;\n\tlimit?: number;\n\tstate?: string;\n}\n\nexport interface UseAutocompleteResult {\n\terror: Error | null;\n\tloading: boolean;\n\tquery: string;\n\tresults: AddressSuggestion[];\n\tsetQuery: (q: string) => void;\n}\n\nexport function useAutocomplete(\n\tclient: WheraboutsClient,\n\toptions: UseAutocompleteOptions = {}\n): UseAutocompleteResult {\n\tconst { debounceMs = 300, limit, country, state } = options;\n\n\tconst [query, setQuery] = useState(\"\");\n\tconst [results, setResults] = useState<AddressSuggestion[]>([]);\n\tconst [loading, setLoading] = useState(false);\n\tconst [error, setError] = useState<Error | null>(null);\n\n\tconst abortRef = useRef<AbortController | null>(null);\n\tconst timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n\t// Stable setter — consumers can safely pass this to input onChange\n\tconst handleSetQuery = useCallback((q: string) => {\n\t\tsetQuery(q);\n\t}, []);\n\n\tuseEffect(() => {\n\t\tif (timerRef.current) {\n\t\t\tclearTimeout(timerRef.current);\n\t\t}\n\t\tif (abortRef.current) {\n\t\t\tabortRef.current.abort();\n\t\t}\n\n\t\tif (!query.trim()) {\n\t\t\tsetResults([]);\n\t\t\tsetLoading(false);\n\t\t\tsetError(null);\n\t\t\treturn;\n\t\t}\n\n\t\tsetLoading(true);\n\n\t\ttimerRef.current = setTimeout(async () => {\n\t\t\tconst controller = new AbortController();\n\t\t\tabortRef.current = controller;\n\t\t\tsetError(null);\n\n\t\t\ttry {\n\t\t\t\tconst res = await client.addresses.autocomplete(\n\t\t\t\t\t{ q: query, limit, country, state },\n\t\t\t\t\t{ signal: controller.signal }\n\t\t\t\t);\n\t\t\t\tif (!controller.signal.aborted) {\n\t\t\t\t\tsetResults(res.results);\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tif (!controller.signal.aborted) {\n\t\t\t\t\tsetError(e instanceof Error ? e : new Error(String(e)));\n\t\t\t\t\tsetResults([]);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tif (!controller.signal.aborted) {\n\t\t\t\t\tsetLoading(false);\n\t\t\t\t}\n\t\t\t}\n\t\t}, debounceMs);\n\n\t\treturn () => {\n\t\t\tif (timerRef.current) {\n\t\t\t\tclearTimeout(timerRef.current);\n\t\t\t}\n\t\t\tif (abortRef.current) {\n\t\t\t\tabortRef.current.abort();\n\t\t\t}\n\t\t};\n\t}, [query, debounceMs, limit, country, state, client]);\n\n\treturn { query, setQuery: handleSetQuery, results, loading, error };\n}\n","import type { ReverseGeocodeAddress, WheraboutsClient } from \"@wherabouts/sdk\";\nimport { useEffect, useRef, useState } from \"react\";\n\nexport interface LatLng {\n\tlat: number;\n\tlng: number;\n}\n\nexport interface UseReverseGeocodeResult {\n\taddress: ReverseGeocodeAddress | null;\n\tdistance: number | null;\n\terror: Error | null;\n\tloading: boolean;\n}\n\nexport function useReverseGeocode(\n\tclient: WheraboutsClient,\n\tcoords: LatLng | null\n): UseReverseGeocodeResult {\n\tconst [address, setAddress] = useState<ReverseGeocodeAddress | null>(null);\n\tconst [distance, setDistance] = useState<number | null>(null);\n\tconst [loading, setLoading] = useState(false);\n\tconst [error, setError] = useState<Error | null>(null);\n\tconst abortRef = useRef<AbortController | null>(null);\n\n\tuseEffect(() => {\n\t\tif (abortRef.current) {\n\t\t\tabortRef.current.abort();\n\t\t}\n\n\t\tif (!coords) {\n\t\t\tsetAddress(null);\n\t\t\tsetDistance(null);\n\t\t\tsetLoading(false);\n\t\t\tsetError(null);\n\t\t\treturn;\n\t\t}\n\n\t\tconst controller = new AbortController();\n\t\tabortRef.current = controller;\n\t\tsetLoading(true);\n\t\tsetError(null);\n\n\t\tclient.addresses\n\t\t\t.reverse(coords, { signal: controller.signal })\n\t\t\t.then((res) => {\n\t\t\t\tif (!controller.signal.aborted) {\n\t\t\t\t\tsetAddress(res.address);\n\t\t\t\t\tsetDistance(res.distance);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch((e: unknown) => {\n\t\t\t\tif (!controller.signal.aborted) {\n\t\t\t\t\tsetError(e instanceof Error ? e : new Error(String(e)));\n\t\t\t\t}\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tif (!controller.signal.aborted) {\n\t\t\t\t\tsetLoading(false);\n\t\t\t\t}\n\t\t\t});\n\n\t\treturn () => {\n\t\t\tcontroller.abort();\n\t\t};\n\t}, [coords?.lat, coords?.lng, client]);\n\n\treturn { address, distance, loading, error };\n}\n","import type { WheraboutsClient, ZoneRecord } from \"@wherabouts/sdk\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport type { LatLng } from \"./use-reverse-geocode.ts\";\n\nexport interface UseZoneContainsResult {\n\terror: Error | null;\n\tloading: boolean;\n\tzones: ZoneRecord[];\n}\n\nexport function useZoneContains(\n\tclient: WheraboutsClient,\n\tcoords: LatLng | null\n): UseZoneContainsResult {\n\tconst [zones, setZones] = useState<ZoneRecord[]>([]);\n\tconst [loading, setLoading] = useState(false);\n\tconst [error, setError] = useState<Error | null>(null);\n\tconst abortRef = useRef<AbortController | null>(null);\n\n\tuseEffect(() => {\n\t\tif (abortRef.current) {\n\t\t\tabortRef.current.abort();\n\t\t}\n\n\t\tif (!coords) {\n\t\t\tsetZones([]);\n\t\t\tsetLoading(false);\n\t\t\tsetError(null);\n\t\t\treturn;\n\t\t}\n\n\t\tconst controller = new AbortController();\n\t\tabortRef.current = controller;\n\t\tsetLoading(true);\n\t\tsetError(null);\n\n\t\tclient.zones\n\t\t\t.contains(coords, { signal: controller.signal })\n\t\t\t.then((res) => {\n\t\t\t\tif (!controller.signal.aborted) {\n\t\t\t\t\tsetZones(res.zones);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch((e: unknown) => {\n\t\t\t\tif (!controller.signal.aborted) {\n\t\t\t\t\tsetError(e instanceof Error ? e : new Error(String(e)));\n\t\t\t\t}\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tif (!controller.signal.aborted) {\n\t\t\t\t\tsetLoading(false);\n\t\t\t\t}\n\t\t\t});\n\n\t\treturn () => {\n\t\t\tcontroller.abort();\n\t\t};\n\t}, [coords?.lat, coords?.lng, client]);\n\n\treturn { zones, loading, error };\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wherabouts/react",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "React hooks for the Wherabouts location API",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": ">=18"
|
|
10
|
+
},
|
|
11
|
+
"main": "./dist/index.cjs",
|
|
12
|
+
"module": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"import": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"default": "./dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"require": {
|
|
21
|
+
"types": "./dist/index.d.cts",
|
|
22
|
+
"default": "./dist/index.cjs"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"README.md"
|
|
32
|
+
],
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"react": ">=18",
|
|
35
|
+
"@wherabouts/sdk": ">=0.4.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/react": "^19",
|
|
39
|
+
"react": "^19.2.3",
|
|
40
|
+
"tsup": "^8.5.1",
|
|
41
|
+
"typescript": "^5",
|
|
42
|
+
"vitest": "^4.1.4",
|
|
43
|
+
"@wherabouts/sdk": "0.4.0",
|
|
44
|
+
"@wherabouts.com/config": "0.0.0"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "tsup",
|
|
48
|
+
"check-types": "tsc --noEmit",
|
|
49
|
+
"test": "vitest run"
|
|
50
|
+
}
|
|
51
|
+
}
|