@wherabouts/react-ui 0.1.0 → 0.3.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/LICENSE +21 -0
- package/README.md +27 -9
- package/dist/index.cjs +246 -257
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +97 -45
- package/dist/index.d.ts +97 -45
- package/dist/index.js +246 -257
- package/dist/index.js.map +1 -1
- package/dist/styles.css +52 -40
- package/docs/README.md +16 -0
- package/docs/address-autocomplete.md +208 -0
- package/docs/address-field-group.md +152 -0
- package/docs/address-form-field.md +198 -0
- package/docs/forward-geocode-input.md +115 -0
- package/docs/reverse-geocode-input.md +124 -0
- package/package.json +26 -19
package/dist/index.js
CHANGED
|
@@ -1,24 +1,45 @@
|
|
|
1
1
|
import { useAutocomplete, useCombobox, useReverseGeocode } from '@wherabouts/react';
|
|
2
2
|
import { useMemo, useRef, useState, useEffect } from 'react';
|
|
3
3
|
import { createPortal } from 'react-dom';
|
|
4
|
+
import { countryName } from '@wherabouts/sdk';
|
|
4
5
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
6
|
|
|
6
|
-
// src/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
7
|
+
// src/components/address-autocomplete.tsx
|
|
8
|
+
function useAddressGeolocation(enabled) {
|
|
9
|
+
const [lat, setLat] = useState(void 0);
|
|
10
|
+
const [lng, setLng] = useState(void 0);
|
|
11
|
+
const [loading, setLoading] = useState(false);
|
|
12
|
+
const [error, setError] = useState(null);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (!enabled) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (typeof navigator === "undefined" || !("geolocation" in navigator)) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
setLoading(true);
|
|
21
|
+
const controller = new AbortController();
|
|
22
|
+
navigator.geolocation.getCurrentPosition(
|
|
23
|
+
(position) => {
|
|
24
|
+
if (!controller.signal.aborted) {
|
|
25
|
+
setLat(position.coords.latitude);
|
|
26
|
+
setLng(position.coords.longitude);
|
|
27
|
+
setError(null);
|
|
28
|
+
setLoading(false);
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
(err) => {
|
|
32
|
+
if (!controller.signal.aborted) {
|
|
33
|
+
setError(err);
|
|
34
|
+
setLoading(false);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
return () => {
|
|
39
|
+
controller.abort();
|
|
40
|
+
};
|
|
41
|
+
}, [enabled]);
|
|
42
|
+
return { lat, lng, loading, error };
|
|
22
43
|
}
|
|
23
44
|
|
|
24
45
|
// ../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
|
|
@@ -2500,41 +2521,18 @@ var twMerge = /* @__PURE__ */ createTailwindMerge(getDefaultConfig);
|
|
|
2500
2521
|
function cn(...inputs) {
|
|
2501
2522
|
return twMerge(clsx(inputs));
|
|
2502
2523
|
}
|
|
2503
|
-
function
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
setLoading(true);
|
|
2516
|
-
const controller = new AbortController();
|
|
2517
|
-
navigator.geolocation.getCurrentPosition(
|
|
2518
|
-
(position) => {
|
|
2519
|
-
if (!controller.signal.aborted) {
|
|
2520
|
-
setLat(position.coords.latitude);
|
|
2521
|
-
setLng(position.coords.longitude);
|
|
2522
|
-
setError(null);
|
|
2523
|
-
setLoading(false);
|
|
2524
|
-
}
|
|
2525
|
-
},
|
|
2526
|
-
(err) => {
|
|
2527
|
-
if (!controller.signal.aborted) {
|
|
2528
|
-
setError(err);
|
|
2529
|
-
setLoading(false);
|
|
2530
|
-
}
|
|
2531
|
-
}
|
|
2532
|
-
);
|
|
2533
|
-
return () => {
|
|
2534
|
-
controller.abort();
|
|
2535
|
-
};
|
|
2536
|
-
}, [enabled]);
|
|
2537
|
-
return { lat, lng, loading, error };
|
|
2524
|
+
function toAddressWithParsed(suggestion) {
|
|
2525
|
+
return {
|
|
2526
|
+
id: suggestion.id,
|
|
2527
|
+
formattedAddress: suggestion.formattedAddress,
|
|
2528
|
+
latitude: suggestion.latitude,
|
|
2529
|
+
longitude: suggestion.longitude,
|
|
2530
|
+
streetAddress: suggestion.streetAddress,
|
|
2531
|
+
suburb: suggestion.locality,
|
|
2532
|
+
state: suggestion.state,
|
|
2533
|
+
postcode: suggestion.postcode,
|
|
2534
|
+
country: countryName(suggestion.country)
|
|
2535
|
+
};
|
|
2538
2536
|
}
|
|
2539
2537
|
var DEFAULT_I18N = {
|
|
2540
2538
|
noResults: "No addresses found",
|
|
@@ -2778,186 +2776,6 @@ function AddressAutocomplete({
|
|
|
2778
2776
|
}
|
|
2779
2777
|
);
|
|
2780
2778
|
}
|
|
2781
|
-
function AddressFormField({
|
|
2782
|
-
label,
|
|
2783
|
-
labelClassName,
|
|
2784
|
-
errorClassName,
|
|
2785
|
-
error,
|
|
2786
|
-
required,
|
|
2787
|
-
disabled,
|
|
2788
|
-
id: customId,
|
|
2789
|
-
className,
|
|
2790
|
-
...autocompleteProps
|
|
2791
|
-
}) {
|
|
2792
|
-
const id = customId ?? "wherabouts-field";
|
|
2793
|
-
return /* @__PURE__ */ jsxs(
|
|
2794
|
-
"div",
|
|
2795
|
-
{
|
|
2796
|
-
"data-slot": "address-form-field",
|
|
2797
|
-
className: "flex flex-col gap-2",
|
|
2798
|
-
children: [
|
|
2799
|
-
/* @__PURE__ */ jsxs(
|
|
2800
|
-
"label",
|
|
2801
|
-
{
|
|
2802
|
-
htmlFor: id,
|
|
2803
|
-
className: cn(
|
|
2804
|
-
"block text-sm font-medium text-gray-900",
|
|
2805
|
-
labelClassName
|
|
2806
|
-
),
|
|
2807
|
-
children: [
|
|
2808
|
-
label,
|
|
2809
|
-
required && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "ml-1 text-red-600", children: "*" })
|
|
2810
|
-
]
|
|
2811
|
-
}
|
|
2812
|
-
),
|
|
2813
|
-
/* @__PURE__ */ jsx(
|
|
2814
|
-
AddressAutocomplete,
|
|
2815
|
-
{
|
|
2816
|
-
...autocompleteProps,
|
|
2817
|
-
id,
|
|
2818
|
-
required,
|
|
2819
|
-
disabled,
|
|
2820
|
-
error,
|
|
2821
|
-
className
|
|
2822
|
-
}
|
|
2823
|
-
),
|
|
2824
|
-
error && /* @__PURE__ */ jsx(
|
|
2825
|
-
"p",
|
|
2826
|
-
{
|
|
2827
|
-
role: "alert",
|
|
2828
|
-
"aria-live": "polite",
|
|
2829
|
-
className: cn(
|
|
2830
|
-
"text-sm text-red-600",
|
|
2831
|
-
errorClassName
|
|
2832
|
-
),
|
|
2833
|
-
children: error
|
|
2834
|
-
}
|
|
2835
|
-
)
|
|
2836
|
-
]
|
|
2837
|
-
}
|
|
2838
|
-
);
|
|
2839
|
-
}
|
|
2840
|
-
function ReverseGeocodeInput({
|
|
2841
|
-
client,
|
|
2842
|
-
latitude,
|
|
2843
|
-
longitude,
|
|
2844
|
-
onResult,
|
|
2845
|
-
className,
|
|
2846
|
-
disabled,
|
|
2847
|
-
placeholder = "Address will appear here",
|
|
2848
|
-
id
|
|
2849
|
-
}) {
|
|
2850
|
-
const { address, distance } = useReverseGeocode(
|
|
2851
|
-
client,
|
|
2852
|
-
latitude != null && longitude != null ? { lat: latitude, lng: longitude } : null
|
|
2853
|
-
);
|
|
2854
|
-
useEffect(() => {
|
|
2855
|
-
onResult?.({
|
|
2856
|
-
address: address?.formattedAddress ?? null,
|
|
2857
|
-
distance: distance ?? null
|
|
2858
|
-
});
|
|
2859
|
-
}, [address, distance, onResult]);
|
|
2860
|
-
const displayText = address?.formattedAddress ?? "";
|
|
2861
|
-
return /* @__PURE__ */ jsx(
|
|
2862
|
-
"input",
|
|
2863
|
-
{
|
|
2864
|
-
id,
|
|
2865
|
-
"data-slot": "geocode-input",
|
|
2866
|
-
type: "text",
|
|
2867
|
-
readOnly: true,
|
|
2868
|
-
disabled,
|
|
2869
|
-
value: displayText,
|
|
2870
|
-
placeholder,
|
|
2871
|
-
className: cn(
|
|
2872
|
-
"block h-8 w-full cursor-default rounded-none border border-input bg-muted/40 px-2.5 py-1 text-foreground text-xs",
|
|
2873
|
-
className
|
|
2874
|
-
)
|
|
2875
|
-
}
|
|
2876
|
-
);
|
|
2877
|
-
}
|
|
2878
|
-
var toGeocodeAddress = (address) => address ? {
|
|
2879
|
-
id: address.id,
|
|
2880
|
-
formattedAddress: address.formattedAddress,
|
|
2881
|
-
latitude: address.latitude,
|
|
2882
|
-
longitude: address.longitude
|
|
2883
|
-
} : null;
|
|
2884
|
-
function useForwardGeocode(client, query) {
|
|
2885
|
-
const [data, setData] = useState(null);
|
|
2886
|
-
const [loading, setLoading] = useState(false);
|
|
2887
|
-
const [error, setError] = useState(null);
|
|
2888
|
-
useEffect(() => {
|
|
2889
|
-
if (!query) {
|
|
2890
|
-
setData(null);
|
|
2891
|
-
setError(null);
|
|
2892
|
-
return;
|
|
2893
|
-
}
|
|
2894
|
-
const controller = new AbortController();
|
|
2895
|
-
async function fetch() {
|
|
2896
|
-
setLoading(true);
|
|
2897
|
-
setError(null);
|
|
2898
|
-
try {
|
|
2899
|
-
const response = await client.geocode.forward(
|
|
2900
|
-
{ q: query },
|
|
2901
|
-
{ signal: controller.signal }
|
|
2902
|
-
);
|
|
2903
|
-
if (controller.signal.aborted) {
|
|
2904
|
-
return;
|
|
2905
|
-
}
|
|
2906
|
-
setData(toGeocodeAddress(response.address));
|
|
2907
|
-
} catch (err) {
|
|
2908
|
-
if (controller.signal.aborted) {
|
|
2909
|
-
return;
|
|
2910
|
-
}
|
|
2911
|
-
setError(err instanceof Error ? err : new Error(String(err)));
|
|
2912
|
-
setData(null);
|
|
2913
|
-
} finally {
|
|
2914
|
-
if (!controller.signal.aborted) {
|
|
2915
|
-
setLoading(false);
|
|
2916
|
-
}
|
|
2917
|
-
}
|
|
2918
|
-
}
|
|
2919
|
-
fetch();
|
|
2920
|
-
return () => {
|
|
2921
|
-
controller.abort();
|
|
2922
|
-
};
|
|
2923
|
-
}, [client, query]);
|
|
2924
|
-
return { data, loading, error };
|
|
2925
|
-
}
|
|
2926
|
-
function ForwardGeocodeInput({
|
|
2927
|
-
client,
|
|
2928
|
-
query,
|
|
2929
|
-
onResult,
|
|
2930
|
-
className,
|
|
2931
|
-
disabled,
|
|
2932
|
-
placeholder = "Coordinates will appear here",
|
|
2933
|
-
id
|
|
2934
|
-
}) {
|
|
2935
|
-
const { data } = useForwardGeocode(client, query);
|
|
2936
|
-
useEffect(() => {
|
|
2937
|
-
onResult?.({
|
|
2938
|
-
latitude: data?.latitude ?? null,
|
|
2939
|
-
longitude: data?.longitude ?? null,
|
|
2940
|
-
formattedAddress: data?.formattedAddress ?? null
|
|
2941
|
-
});
|
|
2942
|
-
}, [data, onResult]);
|
|
2943
|
-
const displayText = data ? `${data.latitude.toFixed(4)}, ${data.longitude.toFixed(4)}` : "";
|
|
2944
|
-
return /* @__PURE__ */ jsx(
|
|
2945
|
-
"input",
|
|
2946
|
-
{
|
|
2947
|
-
id,
|
|
2948
|
-
"data-slot": "geocode-input",
|
|
2949
|
-
type: "text",
|
|
2950
|
-
readOnly: true,
|
|
2951
|
-
disabled,
|
|
2952
|
-
value: displayText,
|
|
2953
|
-
placeholder,
|
|
2954
|
-
className: cn(
|
|
2955
|
-
"block h-8 w-full cursor-default rounded-none border border-input bg-muted/40 px-2.5 py-1 text-foreground text-xs",
|
|
2956
|
-
className
|
|
2957
|
-
)
|
|
2958
|
-
}
|
|
2959
|
-
);
|
|
2960
|
-
}
|
|
2961
2779
|
function AddressFieldGroup({
|
|
2962
2780
|
client,
|
|
2963
2781
|
value,
|
|
@@ -2986,8 +2804,8 @@ function AddressFieldGroup({
|
|
|
2986
2804
|
return /* @__PURE__ */ jsxs(
|
|
2987
2805
|
"div",
|
|
2988
2806
|
{
|
|
2989
|
-
"data-slot": "address-field-group",
|
|
2990
2807
|
className: cn("flex flex-col gap-4", className),
|
|
2808
|
+
"data-slot": "address-field-group",
|
|
2991
2809
|
children: [
|
|
2992
2810
|
/* @__PURE__ */ jsx(
|
|
2993
2811
|
AddressAutocomplete,
|
|
@@ -3001,28 +2819,28 @@ function AddressFieldGroup({
|
|
|
3001
2819
|
/* @__PURE__ */ jsxs(
|
|
3002
2820
|
"div",
|
|
3003
2821
|
{
|
|
3004
|
-
"data-slot": "address-field-group-inputs",
|
|
3005
2822
|
className: "grid grid-cols-2 gap-4",
|
|
2823
|
+
"data-slot": "address-field-group-inputs",
|
|
3006
2824
|
children: [
|
|
3007
2825
|
/* @__PURE__ */ jsxs("div", { className: "col-span-2", children: [
|
|
3008
2826
|
/* @__PURE__ */ jsx(
|
|
3009
2827
|
"label",
|
|
3010
2828
|
{
|
|
3011
|
-
htmlFor: "field-street",
|
|
3012
2829
|
className: "mb-1 block font-medium text-foreground text-sm",
|
|
2830
|
+
htmlFor: "field-street",
|
|
3013
2831
|
children: streetLabel
|
|
3014
2832
|
}
|
|
3015
2833
|
),
|
|
3016
2834
|
/* @__PURE__ */ jsx(
|
|
3017
2835
|
"input",
|
|
3018
2836
|
{
|
|
3019
|
-
|
|
3020
|
-
type: "text",
|
|
2837
|
+
className: "block h-8 w-full rounded-none border border-input bg-transparent px-2.5 py-1 text-foreground text-xs outline-none transition-colors placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-1 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-input/30",
|
|
3021
2838
|
disabled,
|
|
3022
|
-
|
|
2839
|
+
id: "field-street",
|
|
3023
2840
|
onChange: (e) => handleFieldChange("street", e.target.value),
|
|
3024
|
-
|
|
3025
|
-
|
|
2841
|
+
placeholder: "Street address",
|
|
2842
|
+
type: "text",
|
|
2843
|
+
value: value.street
|
|
3026
2844
|
}
|
|
3027
2845
|
)
|
|
3028
2846
|
] }),
|
|
@@ -3030,21 +2848,21 @@ function AddressFieldGroup({
|
|
|
3030
2848
|
/* @__PURE__ */ jsx(
|
|
3031
2849
|
"label",
|
|
3032
2850
|
{
|
|
3033
|
-
htmlFor: "field-suburb",
|
|
3034
2851
|
className: "mb-1 block font-medium text-foreground text-sm",
|
|
2852
|
+
htmlFor: "field-suburb",
|
|
3035
2853
|
children: suburbLabel
|
|
3036
2854
|
}
|
|
3037
2855
|
),
|
|
3038
2856
|
/* @__PURE__ */ jsx(
|
|
3039
2857
|
"input",
|
|
3040
2858
|
{
|
|
3041
|
-
|
|
3042
|
-
type: "text",
|
|
2859
|
+
className: "block h-8 w-full rounded-none border border-input bg-transparent px-2.5 py-1 text-foreground text-xs outline-none transition-colors placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-1 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-input/30",
|
|
3043
2860
|
disabled,
|
|
3044
|
-
|
|
2861
|
+
id: "field-suburb",
|
|
3045
2862
|
onChange: (e) => handleFieldChange("suburb", e.target.value),
|
|
3046
|
-
|
|
3047
|
-
|
|
2863
|
+
placeholder: "Suburb",
|
|
2864
|
+
type: "text",
|
|
2865
|
+
value: value.suburb
|
|
3048
2866
|
}
|
|
3049
2867
|
)
|
|
3050
2868
|
] }),
|
|
@@ -3052,21 +2870,21 @@ function AddressFieldGroup({
|
|
|
3052
2870
|
/* @__PURE__ */ jsx(
|
|
3053
2871
|
"label",
|
|
3054
2872
|
{
|
|
3055
|
-
htmlFor: "field-state",
|
|
3056
2873
|
className: "mb-1 block font-medium text-foreground text-sm",
|
|
2874
|
+
htmlFor: "field-state",
|
|
3057
2875
|
children: stateLabel
|
|
3058
2876
|
}
|
|
3059
2877
|
),
|
|
3060
2878
|
/* @__PURE__ */ jsx(
|
|
3061
2879
|
"input",
|
|
3062
2880
|
{
|
|
3063
|
-
|
|
3064
|
-
type: "text",
|
|
2881
|
+
className: "block h-8 w-full rounded-none border border-input bg-transparent px-2.5 py-1 text-foreground text-xs outline-none transition-colors placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-1 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-input/30",
|
|
3065
2882
|
disabled,
|
|
3066
|
-
|
|
2883
|
+
id: "field-state",
|
|
3067
2884
|
onChange: (e) => handleFieldChange("state", e.target.value),
|
|
3068
|
-
|
|
3069
|
-
|
|
2885
|
+
placeholder: "State",
|
|
2886
|
+
type: "text",
|
|
2887
|
+
value: value.state
|
|
3070
2888
|
}
|
|
3071
2889
|
)
|
|
3072
2890
|
] }),
|
|
@@ -3074,21 +2892,21 @@ function AddressFieldGroup({
|
|
|
3074
2892
|
/* @__PURE__ */ jsx(
|
|
3075
2893
|
"label",
|
|
3076
2894
|
{
|
|
3077
|
-
htmlFor: "field-postcode",
|
|
3078
2895
|
className: "mb-1 block font-medium text-foreground text-sm",
|
|
2896
|
+
htmlFor: "field-postcode",
|
|
3079
2897
|
children: postcodeLabel
|
|
3080
2898
|
}
|
|
3081
2899
|
),
|
|
3082
2900
|
/* @__PURE__ */ jsx(
|
|
3083
2901
|
"input",
|
|
3084
2902
|
{
|
|
3085
|
-
|
|
3086
|
-
type: "text",
|
|
2903
|
+
className: "block h-8 w-full rounded-none border border-input bg-transparent px-2.5 py-1 text-foreground text-xs outline-none transition-colors placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-1 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-input/30",
|
|
3087
2904
|
disabled,
|
|
3088
|
-
|
|
2905
|
+
id: "field-postcode",
|
|
3089
2906
|
onChange: (e) => handleFieldChange("postcode", e.target.value),
|
|
3090
|
-
|
|
3091
|
-
|
|
2907
|
+
placeholder: "Postcode",
|
|
2908
|
+
type: "text",
|
|
2909
|
+
value: value.postcode
|
|
3092
2910
|
}
|
|
3093
2911
|
)
|
|
3094
2912
|
] })
|
|
@@ -3099,6 +2917,177 @@ function AddressFieldGroup({
|
|
|
3099
2917
|
}
|
|
3100
2918
|
);
|
|
3101
2919
|
}
|
|
2920
|
+
function AddressFormField({
|
|
2921
|
+
label,
|
|
2922
|
+
labelClassName,
|
|
2923
|
+
errorClassName,
|
|
2924
|
+
error,
|
|
2925
|
+
required,
|
|
2926
|
+
disabled,
|
|
2927
|
+
id: customId,
|
|
2928
|
+
className,
|
|
2929
|
+
...autocompleteProps
|
|
2930
|
+
}) {
|
|
2931
|
+
const id = customId ?? "wherabouts-field";
|
|
2932
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", "data-slot": "address-form-field", children: [
|
|
2933
|
+
/* @__PURE__ */ jsxs(
|
|
2934
|
+
"label",
|
|
2935
|
+
{
|
|
2936
|
+
className: cn(
|
|
2937
|
+
"block font-medium text-gray-900 text-sm",
|
|
2938
|
+
labelClassName
|
|
2939
|
+
),
|
|
2940
|
+
htmlFor: id,
|
|
2941
|
+
children: [
|
|
2942
|
+
label,
|
|
2943
|
+
required && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "ml-1 text-red-600", children: "*" })
|
|
2944
|
+
]
|
|
2945
|
+
}
|
|
2946
|
+
),
|
|
2947
|
+
/* @__PURE__ */ jsx(
|
|
2948
|
+
AddressAutocomplete,
|
|
2949
|
+
{
|
|
2950
|
+
...autocompleteProps,
|
|
2951
|
+
className,
|
|
2952
|
+
disabled,
|
|
2953
|
+
error,
|
|
2954
|
+
id,
|
|
2955
|
+
required
|
|
2956
|
+
}
|
|
2957
|
+
),
|
|
2958
|
+
error && /* @__PURE__ */ jsx(
|
|
2959
|
+
"p",
|
|
2960
|
+
{
|
|
2961
|
+
"aria-live": "polite",
|
|
2962
|
+
className: cn("text-red-600 text-sm", errorClassName),
|
|
2963
|
+
role: "alert",
|
|
2964
|
+
children: error
|
|
2965
|
+
}
|
|
2966
|
+
)
|
|
2967
|
+
] });
|
|
2968
|
+
}
|
|
2969
|
+
var toGeocodeAddress = (address) => address ? {
|
|
2970
|
+
id: address.id,
|
|
2971
|
+
formattedAddress: address.formattedAddress,
|
|
2972
|
+
latitude: address.latitude,
|
|
2973
|
+
longitude: address.longitude
|
|
2974
|
+
} : null;
|
|
2975
|
+
function useForwardGeocode(client, query) {
|
|
2976
|
+
const [data, setData] = useState(null);
|
|
2977
|
+
const [loading, setLoading] = useState(false);
|
|
2978
|
+
const [error, setError] = useState(null);
|
|
2979
|
+
useEffect(() => {
|
|
2980
|
+
if (!query) {
|
|
2981
|
+
setData(null);
|
|
2982
|
+
setError(null);
|
|
2983
|
+
return;
|
|
2984
|
+
}
|
|
2985
|
+
const activeQuery = query;
|
|
2986
|
+
const controller = new AbortController();
|
|
2987
|
+
async function fetch() {
|
|
2988
|
+
setLoading(true);
|
|
2989
|
+
setError(null);
|
|
2990
|
+
try {
|
|
2991
|
+
const response = await client.geocode.forward(
|
|
2992
|
+
{ q: activeQuery },
|
|
2993
|
+
{ signal: controller.signal }
|
|
2994
|
+
);
|
|
2995
|
+
if (controller.signal.aborted) {
|
|
2996
|
+
return;
|
|
2997
|
+
}
|
|
2998
|
+
setData(toGeocodeAddress(response.address));
|
|
2999
|
+
} catch (err) {
|
|
3000
|
+
if (controller.signal.aborted) {
|
|
3001
|
+
return;
|
|
3002
|
+
}
|
|
3003
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
3004
|
+
setData(null);
|
|
3005
|
+
} finally {
|
|
3006
|
+
if (!controller.signal.aborted) {
|
|
3007
|
+
setLoading(false);
|
|
3008
|
+
}
|
|
3009
|
+
}
|
|
3010
|
+
}
|
|
3011
|
+
fetch();
|
|
3012
|
+
return () => {
|
|
3013
|
+
controller.abort();
|
|
3014
|
+
};
|
|
3015
|
+
}, [client, query]);
|
|
3016
|
+
return { data, loading, error };
|
|
3017
|
+
}
|
|
3018
|
+
function ForwardGeocodeInput({
|
|
3019
|
+
client,
|
|
3020
|
+
query,
|
|
3021
|
+
onResult,
|
|
3022
|
+
className,
|
|
3023
|
+
disabled,
|
|
3024
|
+
placeholder = "Coordinates will appear here",
|
|
3025
|
+
id
|
|
3026
|
+
}) {
|
|
3027
|
+
const { data } = useForwardGeocode(client, query);
|
|
3028
|
+
useEffect(() => {
|
|
3029
|
+
onResult?.({
|
|
3030
|
+
latitude: data?.latitude ?? null,
|
|
3031
|
+
longitude: data?.longitude ?? null,
|
|
3032
|
+
formattedAddress: data?.formattedAddress ?? null
|
|
3033
|
+
});
|
|
3034
|
+
}, [data, onResult]);
|
|
3035
|
+
const displayText = data ? `${data.latitude.toFixed(4)}, ${data.longitude.toFixed(4)}` : "";
|
|
3036
|
+
return /* @__PURE__ */ jsx(
|
|
3037
|
+
"input",
|
|
3038
|
+
{
|
|
3039
|
+
className: cn(
|
|
3040
|
+
"block h-8 w-full cursor-default rounded-none border border-input bg-muted/40 px-2.5 py-1 text-foreground text-xs",
|
|
3041
|
+
className
|
|
3042
|
+
),
|
|
3043
|
+
"data-slot": "geocode-input",
|
|
3044
|
+
disabled,
|
|
3045
|
+
id,
|
|
3046
|
+
placeholder,
|
|
3047
|
+
readOnly: true,
|
|
3048
|
+
type: "text",
|
|
3049
|
+
value: displayText
|
|
3050
|
+
}
|
|
3051
|
+
);
|
|
3052
|
+
}
|
|
3053
|
+
function ReverseGeocodeInput({
|
|
3054
|
+
client,
|
|
3055
|
+
latitude,
|
|
3056
|
+
longitude,
|
|
3057
|
+
onResult,
|
|
3058
|
+
className,
|
|
3059
|
+
disabled,
|
|
3060
|
+
placeholder = "Address will appear here",
|
|
3061
|
+
id
|
|
3062
|
+
}) {
|
|
3063
|
+
const { address, distance } = useReverseGeocode(
|
|
3064
|
+
client,
|
|
3065
|
+
latitude != null && longitude != null ? { lat: latitude, lng: longitude } : null
|
|
3066
|
+
);
|
|
3067
|
+
useEffect(() => {
|
|
3068
|
+
onResult?.({
|
|
3069
|
+
address: address?.formattedAddress ?? null,
|
|
3070
|
+
distance: distance ?? null
|
|
3071
|
+
});
|
|
3072
|
+
}, [address, distance, onResult]);
|
|
3073
|
+
const displayText = address?.formattedAddress ?? "";
|
|
3074
|
+
return /* @__PURE__ */ jsx(
|
|
3075
|
+
"input",
|
|
3076
|
+
{
|
|
3077
|
+
className: cn(
|
|
3078
|
+
"block h-8 w-full cursor-default rounded-none border border-input bg-muted/40 px-2.5 py-1 text-foreground text-xs",
|
|
3079
|
+
className
|
|
3080
|
+
),
|
|
3081
|
+
"data-slot": "geocode-input",
|
|
3082
|
+
disabled,
|
|
3083
|
+
id,
|
|
3084
|
+
placeholder,
|
|
3085
|
+
readOnly: true,
|
|
3086
|
+
type: "text",
|
|
3087
|
+
value: displayText
|
|
3088
|
+
}
|
|
3089
|
+
);
|
|
3090
|
+
}
|
|
3102
3091
|
|
|
3103
3092
|
export { AddressAutocomplete, AddressFieldGroup, AddressFormField, ForwardGeocodeInput, ReverseGeocodeInput, cn, toAddressWithParsed };
|
|
3104
3093
|
//# sourceMappingURL=index.js.map
|