@swan-io/shared-business 3.4.0 → 4.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swan-io/shared-business",
3
- "version": "3.4.0",
3
+ "version": "4.0.0",
4
4
  "engines": {
5
5
  "node": ">=18.0.0",
6
6
  "yarn": "^1.22.0"
@@ -31,6 +31,7 @@
31
31
  "dependencies": {
32
32
  "@formatjs/intl": "^2.9.6",
33
33
  "@googlemaps/js-api-loader": "1.16.2",
34
+ "@placekit/client-js": "^2.0.0",
34
35
  "@swan-io/boxed": "^1.2.0",
35
36
  "dayjs": "^1.11.10",
36
37
  "react": "^18.2.0",
@@ -6,7 +6,7 @@ import { Space } from "@swan-io/lake/src/components/Space";
6
6
  import { useBoolean } from "@swan-io/lake/src/hooks/useBoolean";
7
7
  import { useCallback, useEffect } from "react";
8
8
  import { locale, t } from "../utils/i18n";
9
- import { GMapAddressSearchInput } from "./GMapAddressSearchInput";
9
+ import { PlacekitAddressSearchInput } from "./PlacekitAddressSearchInput";
10
10
  export const AddressFormPart = ({ initialAddress, initialCity, initialPostalCode, country, label, optionalLabel, placeholder, Field, setFieldValue, listenFields, isLarge, apiKey, }) => {
11
11
  const [manualModeEnabled, setManualMode] = useBoolean(initialAddress !== "" || initialCity !== "" || initialPostalCode !== "");
12
12
  useEffect(() => {
@@ -19,8 +19,10 @@ export const AddressFormPart = ({ initialAddress, initialCity, initialPostalCode
19
19
  const onSuggestion = useCallback((place) => {
20
20
  setFieldValue("address", place.completeAddress);
21
21
  setFieldValue("city", place.city);
22
- setFieldValue("postalCode", place.postalCode);
22
+ if (place.postalCode != null) {
23
+ setFieldValue("postalCode", place.postalCode);
24
+ }
23
25
  setManualMode.on();
24
26
  }, [setManualMode, setFieldValue]);
25
- return (_jsxs(_Fragment, { children: [_jsx(Field, { name: "address", children: ({ ref, value, onChange, error }) => (_jsx(LakeLabel, { label: label ?? t("addressFormPart.addressLabel"), optionalLabel: optionalLabel, render: id => (_jsx(GMapAddressSearchInput, { inputRef: ref, apiKey: apiKey, emptyResultText: t("common.noResult"), placeholder: placeholder ?? t("addressFormPart.placeholder"), language: locale.language, id: id, country: country, value: value, error: error, onValueChange: onChange, onSuggestion: onSuggestion })), actions: !manualModeEnabled && isLarge ? (_jsx(LakeButton, { mode: "secondary", size: "small", onPress: setManualMode.on, children: t("addressFormPart.setManual") })) : null })) }), !manualModeEnabled && !isLarge ? (_jsx(LakeButton, { mode: "secondary", size: "small", onPress: setManualMode.on, children: t("addressFormPart.setManual") })) : null, manualModeEnabled ? (_jsxs(_Fragment, { children: [_jsx(Space, { height: 12 }), _jsx(Field, { name: "city", children: ({ ref, value, valid, error, onChange }) => (_jsx(LakeLabel, { label: t("addressFormPart.cityLabel"), render: id => (_jsx(LakeTextInput, { ref: ref, id: id, value: value, valid: valid, error: error, onChangeText: onChange })) })) }), _jsx(Space, { height: 12 }), _jsx(Field, { name: "postalCode", children: ({ ref, value, valid, error, onChange }) => (_jsx(LakeLabel, { label: t("addressFormPart.postCodeLabel"), render: id => (_jsx(LakeTextInput, { ref: ref, id: id, value: value, valid: valid, error: error, onChangeText: onChange })) })) })] })) : null] }));
27
+ return (_jsxs(_Fragment, { children: [_jsx(Field, { name: "address", children: ({ ref, value, onChange, error }) => (_jsx(LakeLabel, { label: label ?? t("addressFormPart.addressLabel"), optionalLabel: optionalLabel, render: id => (_jsx(PlacekitAddressSearchInput, { inputRef: ref, apiKey: apiKey, emptyResultText: t("common.noResult"), placeholder: placeholder ?? t("addressFormPart.placeholder"), language: locale.language, id: id, country: country, value: value, error: error, onValueChange: onChange, onSuggestion: onSuggestion })), actions: !manualModeEnabled && isLarge ? (_jsx(LakeButton, { mode: "secondary", size: "small", onPress: setManualMode.on, children: t("addressFormPart.setManual") })) : null })) }), !manualModeEnabled && !isLarge ? (_jsx(LakeButton, { mode: "secondary", size: "small", onPress: setManualMode.on, children: t("addressFormPart.setManual") })) : null, manualModeEnabled ? (_jsxs(_Fragment, { children: [_jsx(Space, { height: 12 }), _jsx(Field, { name: "city", children: ({ ref, value, valid, error, onChange }) => (_jsx(LakeLabel, { label: t("addressFormPart.cityLabel"), render: id => (_jsx(LakeTextInput, { ref: ref, id: id, value: value, valid: valid, error: error, onChangeText: onChange })) })) }), _jsx(Space, { height: 12 }), _jsx(Field, { name: "postalCode", children: ({ ref, value, valid, error, onChange }) => (_jsx(LakeLabel, { label: t("addressFormPart.postCodeLabel"), render: id => (_jsx(LakeTextInput, { ref: ref, id: id, value: value, valid: valid, error: error, onChangeText: onChange })) })) })] })) : null] }));
26
28
  };
@@ -25,7 +25,7 @@ type Props = {
25
25
  initialState?: EditorState;
26
26
  accountCountry: AccountCountry;
27
27
  step: BeneficiaryFormStep;
28
- googleMapApiKey: string;
28
+ placekitApiKey: string;
29
29
  onStepChange: (step: BeneficiaryFormStep) => void;
30
30
  onSave: (editorState: EditorState) => void | Promise<void>;
31
31
  onClose: () => void;
@@ -23,7 +23,7 @@ import { locale, rifmDateProps, t } from "../utils/i18n";
23
23
  import { validateBooleanRequired, validateIndividualTaxNumber, validateNullableRequired, validateRequired, } from "../utils/validation";
24
24
  import { AddressFormPart } from "./AddressFormPart";
25
25
  import { CountryPicker } from "./CountryPicker";
26
- import { GMapCityInput } from "./GMapCityInput";
26
+ import { PlacekitCityInput } from "./PlacekitCityInput";
27
27
  import { TaxIdentificationNumberInput } from "./TaxIdentificationNumberInput";
28
28
  const styles = StyleSheet.create({
29
29
  inputContainer: {
@@ -154,7 +154,7 @@ const requiredStepFields = [
154
154
  "birthCityPostalCode",
155
155
  "type",
156
156
  ];
157
- export const BeneficiaryForm = forwardRef(({ initialState, accountCountry, step, googleMapApiKey, onStepChange, onClose, onSave, onCityLoadError, }, ref) => {
157
+ export const BeneficiaryForm = forwardRef(({ initialState, accountCountry, step, placekitApiKey, onStepChange, onClose, onSave, onCityLoadError, }, ref) => {
158
158
  const [reference] = useState(() => initialState?.reference ?? uuid());
159
159
  const isAddressRequired = match(accountCountry)
160
160
  .with("DEU", "ESP", () => true)
@@ -329,15 +329,17 @@ export const BeneficiaryForm = forwardRef(({ initialState, accountCountry, step,
329
329
  };
330
330
  });
331
331
  return (_jsx(ResponsiveContainer, { breakpoint: breakpoints.tiny, children: ({ small, large }) => (_jsxs(_Fragment, { children: [match(step)
332
- .with("common", () => (_jsxs(View, { role: "form", children: [_jsxs(Box, { direction: small ? "column" : "row", children: [_jsx(Field, { name: "firstName", children: ({ value, onChange, error }) => (_jsx(LakeLabel, { label: t("beneficiaryForm.beneficiary.firstName"), style: styles.inputContainer, render: id => (_jsx(LakeTextInput, { error: error, placeholder: t("beneficiaryForm.beneficiary.firstNamePlaceholder"), id: id, value: value, onChangeText: onChange })) })) }), _jsx(Space, { width: 12 }), _jsx(Field, { name: "lastName", children: ({ value, onChange, error }) => (_jsx(LakeLabel, { label: t("beneficiaryForm.beneficiary.lastName"), style: styles.inputContainer, render: id => (_jsx(LakeTextInput, { error: error, placeholder: t("beneficiaryForm.beneficiary.lastNamePlaceholder"), id: id, value: value, onChangeText: onChange })) })) })] }), _jsxs(Box, { direction: small ? "column" : "row", children: [_jsx(Field, { name: "birthDate", children: ({ value, onChange, error }) => (_jsx(LakeLabel, { label: t("beneficiaryForm.beneficiary.birthDate"), optionalLabel: isBirthInfoRequired ? undefined : t("common.optional"), style: styles.inputContainer, render: id => (_jsx(Rifm, { value: value ?? "", onChange: onChange, ...rifmDateProps, children: ({ value, onChange }) => (_jsx(LakeTextInput, { error: error, placeholder: locale.datePlaceholder, id: id, value: value, onChange: onChange })) })) })) }), _jsx(Space, { width: 12 }), _jsx(Field, { name: "birthCountryCode", children: ({ value, onChange, error }) => (_jsx(LakeLabel, { label: t("beneficiaryForm.beneficiary.birthCountry"), style: styles.inputContainer, render: id => (_jsx(CountryPicker, { id: id, error: error, value: value, placeholder: t("beneficiaryForm.beneficiary.birthCountryPlaceholder"), countries: allCountries, onValueChange: onChange })) })) })] }), _jsx(Box, { direction: small ? "column" : "row", children: _jsx(FieldsListener, { names: ["birthCountryCode"], children: ({ birthCountryCode }) => (_jsxs(_Fragment, { children: [_jsx(Field, { name: "birthCity", children: ({ value, onChange, error }) => (_jsx(LakeLabel, { label: t("beneficiaryForm.beneficiary.birthCity"), optionalLabel: isBirthInfoRequired ? undefined : t("common.optional"), style: styles.inputContainer, render: id => (_jsx(GMapCityInput, { id: id, apiKey: googleMapApiKey, error: error, country: birthCountryCode.value, value: value ?? "", onValueChange: onChange, placeholder: birthCountryCode.value == null
332
+ .with("common", () => (_jsxs(View, { role: "form", children: [_jsxs(Box, { direction: small ? "column" : "row", children: [_jsx(Field, { name: "firstName", children: ({ value, onChange, error }) => (_jsx(LakeLabel, { label: t("beneficiaryForm.beneficiary.firstName"), style: styles.inputContainer, render: id => (_jsx(LakeTextInput, { error: error, placeholder: t("beneficiaryForm.beneficiary.firstNamePlaceholder"), id: id, value: value, onChangeText: onChange })) })) }), _jsx(Space, { width: 12 }), _jsx(Field, { name: "lastName", children: ({ value, onChange, error }) => (_jsx(LakeLabel, { label: t("beneficiaryForm.beneficiary.lastName"), style: styles.inputContainer, render: id => (_jsx(LakeTextInput, { error: error, placeholder: t("beneficiaryForm.beneficiary.lastNamePlaceholder"), id: id, value: value, onChangeText: onChange })) })) })] }), _jsxs(Box, { direction: small ? "column" : "row", children: [_jsx(Field, { name: "birthDate", children: ({ value, onChange, error }) => (_jsx(LakeLabel, { label: t("beneficiaryForm.beneficiary.birthDate"), optionalLabel: isBirthInfoRequired ? undefined : t("common.optional"), style: styles.inputContainer, render: id => (_jsx(Rifm, { value: value ?? "", onChange: onChange, ...rifmDateProps, children: ({ value, onChange }) => (_jsx(LakeTextInput, { error: error, placeholder: locale.datePlaceholder, id: id, value: value, onChange: onChange })) })) })) }), _jsx(Space, { width: 12 }), _jsx(Field, { name: "birthCountryCode", children: ({ value, onChange, error }) => (_jsx(LakeLabel, { label: t("beneficiaryForm.beneficiary.birthCountry"), style: styles.inputContainer, render: id => (_jsx(CountryPicker, { id: id, error: error, value: value, placeholder: t("beneficiaryForm.beneficiary.birthCountryPlaceholder"), countries: allCountries, onValueChange: onChange })) })) })] }), _jsx(Box, { direction: small ? "column" : "row", children: _jsx(FieldsListener, { names: ["birthCountryCode"], children: ({ birthCountryCode }) => (_jsxs(_Fragment, { children: [_jsx(Field, { name: "birthCity", children: ({ value, onChange, error }) => (_jsx(LakeLabel, { label: t("beneficiaryForm.beneficiary.birthCity"), optionalLabel: isBirthInfoRequired ? undefined : t("common.optional"), style: styles.inputContainer, render: id => (_jsx(PlacekitCityInput, { id: id, apiKey: placekitApiKey, error: error, country: birthCountryCode.value, value: value ?? "", onValueChange: onChange, placeholder: birthCountryCode.value == null
333
333
  ? t("beneficiaryForm.beneficiary.fillBirthCountry")
334
334
  : t("beneficiaryForm.beneficiary.birthCityPlaceholder"), onSuggestion: place => {
335
335
  onChange(place.city);
336
- setFieldValue("birthCityPostalCode", place.postalCode);
336
+ if (place.postalCode != null) {
337
+ setFieldValue("birthCityPostalCode", place.postalCode);
338
+ }
337
339
  }, onLoadError: onCityLoadError })) })) }), _jsx(Space, { width: 12 }), _jsx(Field, { name: "birthCityPostalCode", children: ({ value, onChange, error }) => (_jsx(LakeLabel, { label: t("beneficiaryForm.beneficiary.birthPostalCode"), optionalLabel: isBirthInfoRequired ? undefined : t("common.optional"), style: styles.inputContainer, render: id => (_jsx(LakeTextInput, { error: error, placeholder: birthCountryCode.value == null
338
340
  ? t("beneficiaryForm.beneficiary.fillBirthCountry")
339
341
  : t("beneficiaryForm.beneficiary.birthPostalCodePlaceholder"), id: id, disabled: birthCountryCode.value === undefined, value: value, onChangeText: onChange })) })) })] })) }) }), _jsx(Field, { name: "type", children: ({ value, onChange }) => (_jsx(LakeLabel, { label: t("beneficiaryForm.beneficiary.type"), type: "radioGroup", render: () => (_jsx(RadioGroup, { direction: "row", value: value, onValueChange: onChange, items: beneficiaryTypes })) })) }), _jsx(FieldsListener, { names: ["type"], children: ({ type }) => type.value === "HasCapital" ? (_jsxs(_Fragment, { children: [_jsx(Field, { name: "totalCapitalPercentage", children: ({ value, onChange, error }) => (_jsx(LakeLabel, { label: t("beneficiaryForm.beneficiary.totalCapitalPercentage"), render: id => (_jsx(LakeTextInput, { error: error, unit: "%", inputMode: "decimal", "aria-valuemin": 0, "aria-valuemax": 100, id: id, value: value, onChangeText: onChange })) })) }), _jsx(Space, { height: 12 }), _jsx(Field, { name: "capitalType", children: ({ value, error, onChange }) => (_jsx(CapitalTypeCheckboxes, { value: value ?? "none", error: error, onChange: onChange })) })] })) : null })] })))
340
- .with("address", () => (_jsxs(View, { role: "form", children: [_jsx(Field, { name: "country", children: ({ value, onChange }) => (_jsx(LakeLabel, { label: t("beneficiaryForm.beneficiary.country"), render: id => (_jsx(CountryPicker, { id: id, value: value, countries: allCountries, onValueChange: onChange })) })) }), _jsx(Space, { height: 12 }), _jsx(FieldsListener, { names: ["country"], children: ({ country }) => (_jsxs(_Fragment, { children: [_jsx(AddressFormPart, { apiKey: googleMapApiKey, initialAddress: initialAddress.current.residencyAddressLine1 ?? "", initialCity: initialAddress.current.residencyAddressCity ?? "", initialPostalCode: initialAddress.current.residencyAddressPostalCode ?? "", country: country?.value ?? accountCountry, label: t("beneficiaryForm.beneficiary.address"), Field: Field, setFieldValue: setFieldValue, listenFields: listenFields, isLarge: large }), ((accountCountry === "DEU" && country?.value === "DEU") ||
342
+ .with("address", () => (_jsxs(View, { role: "form", children: [_jsx(Field, { name: "country", children: ({ value, onChange }) => (_jsx(LakeLabel, { label: t("beneficiaryForm.beneficiary.country"), render: id => (_jsx(CountryPicker, { id: id, value: value, countries: allCountries, onValueChange: onChange })) })) }), _jsx(Space, { height: 12 }), _jsx(FieldsListener, { names: ["country"], children: ({ country }) => (_jsxs(_Fragment, { children: [_jsx(AddressFormPart, { apiKey: placekitApiKey, initialAddress: initialAddress.current.residencyAddressLine1 ?? "", initialCity: initialAddress.current.residencyAddressCity ?? "", initialPostalCode: initialAddress.current.residencyAddressPostalCode ?? "", country: country?.value ?? accountCountry, label: t("beneficiaryForm.beneficiary.address"), Field: Field, setFieldValue: setFieldValue, listenFields: listenFields, isLarge: large }), ((accountCountry === "DEU" && country?.value === "DEU") ||
341
343
  accountCountry === "ESP") && (_jsxs(_Fragment, { children: [_jsx(Space, { height: 12 }), _jsx(Field, { name: "taxIdentificationNumber", children: ({ value, error, valid, onChange }) => (_jsx(TaxIdentificationNumberInput, { value: value ?? "", error: error, valid: valid, onChange: onChange, accountCountry: accountCountry, isCompany: false,
342
344
  // is mandatory for German accounts with UBO living in Germany
343
345
  required: accountCountry === "DEU" && country?.value === "DEU" })) })] }))] })) })] })))
@@ -1,14 +1,18 @@
1
1
  import { CountryCCA3 } from "@swan-io/shared-business/src/constants/countries";
2
2
  import { MutableRefObject } from "react";
3
3
  import { StyleProp, ViewStyle } from "react-native";
4
- import { PlaceDetail } from "../hooks/useGoogleMapSDK";
4
+ export type AddressDetail = {
5
+ completeAddress: string;
6
+ city: string;
7
+ postalCode?: string;
8
+ };
5
9
  type Props = {
6
10
  inputRef?: MutableRefObject<unknown>;
7
11
  id?: string;
8
12
  country: CountryCCA3;
9
13
  disabled?: boolean;
10
14
  error?: string;
11
- onSuggestion?: (suggestion: PlaceDetail) => void;
15
+ onSuggestion?: (suggestion: AddressDetail) => void;
12
16
  onValueChange: (value: string) => void;
13
17
  style?: StyleProp<ViewStyle>;
14
18
  value?: string;
@@ -16,7 +20,7 @@ type Props = {
16
20
  placeholder: string;
17
21
  shouldDisplaySuggestions?: boolean;
18
22
  emptyResultText: string;
19
- apiKey: string;
23
+ apiKey?: string;
20
24
  };
21
- export declare const GMapAddressSearchInput: ({ inputRef, id, country, disabled, error, value, onValueChange, onSuggestion, language, placeholder, shouldDisplaySuggestions, emptyResultText, apiKey, }: Props) => import("react/jsx-runtime").JSX.Element;
25
+ export declare const PlacekitAddressSearchInput: ({ inputRef, id, country, disabled, error, value, onValueChange, onSuggestion, language, placeholder, shouldDisplaySuggestions, emptyResultText, apiKey, }: Props) => import("react/jsx-runtime").JSX.Element;
22
26
  export {};
@@ -0,0 +1,33 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Array, Future, Option, Result } from "@swan-io/boxed";
3
+ import { AutocompleteSearchInput } from "@swan-io/lake/src/components/AutocompleteSearchInput";
4
+ import { countriesWithMultipleCCA3, getCCA2forCCA3, } from "@swan-io/shared-business/src/constants/countries";
5
+ import { useCallback } from "react";
6
+ import { usePlacekit } from "../hooks/usePlacekit";
7
+ export const PlacekitAddressSearchInput = ({ inputRef, id, country, disabled, error, value, onValueChange, onSuggestion, language, placeholder, shouldDisplaySuggestions = true, emptyResultText, apiKey, }) => {
8
+ const placekit = usePlacekit({ apiKey });
9
+ const loadSuggestions = useCallback((value) => {
10
+ if (placekit != null) {
11
+ const countries = Array.filterMap(countriesWithMultipleCCA3[country] ?? [country], cca3 => Option.fromNullable(getCCA2forCCA3(cca3)));
12
+ const cca2Countries = countries.length === 0 ? Option.None() : Option.Some(countries);
13
+ return Future.fromPromise(placekit.search(value, {
14
+ types: ["street"],
15
+ language,
16
+ countries: cca2Countries.toUndefined(),
17
+ })).mapOk(({ results }) => results.map(result => ({
18
+ title: result.name,
19
+ subtitle: result.city,
20
+ value: result,
21
+ })), true);
22
+ }
23
+ return Future.value(Result.Ok([]));
24
+ }, [placekit, country, language]);
25
+ const onSuggestionSelected = useCallback((suggestion) => {
26
+ onSuggestion?.({
27
+ completeAddress: suggestion.value.name,
28
+ postalCode: suggestion.value.zipcode[0],
29
+ city: suggestion.value.city,
30
+ });
31
+ }, [onSuggestion]);
32
+ return (_jsx(AutocompleteSearchInput, { inputRef: inputRef, value: value, onValueChange: onValueChange, disabled: disabled, id: id, placeholder: placeholder, error: error, emptyResultText: emptyResultText, shouldDisplaySuggestions: shouldDisplaySuggestions, loadSuggestions: placekit != null ? loadSuggestions : undefined, onSuggestion: onSuggestionSelected }));
33
+ };
@@ -0,0 +1,19 @@
1
+ import { CountryCCA3 } from "../constants/countries";
2
+ export type CityDetail = {
3
+ city: string;
4
+ postalCode?: string;
5
+ };
6
+ type Props = {
7
+ value: string;
8
+ onValueChange: (value: string) => void;
9
+ country?: CountryCCA3;
10
+ disabled?: boolean;
11
+ error?: string;
12
+ id?: string;
13
+ placeholder?: string;
14
+ onSuggestion?: (place: CityDetail) => void;
15
+ onLoadError: (error: unknown) => void;
16
+ apiKey?: string;
17
+ };
18
+ export declare const PlacekitCityInput: ({ value, onValueChange, country, disabled, placeholder, id, error, onSuggestion, onLoadError, apiKey, }: Props) => import("react/jsx-runtime").JSX.Element;
19
+ export {};
@@ -0,0 +1,34 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Array, Future, Option, Result } from "@swan-io/boxed";
3
+ import { AutocompleteSearchInput } from "@swan-io/lake/src/components/AutocompleteSearchInput";
4
+ import { useCallback } from "react";
5
+ import { countriesWithMultipleCCA3, getCCA2forCCA3 } from "../constants/countries";
6
+ import { usePlacekit } from "../hooks/usePlacekit";
7
+ import { t } from "../utils/i18n";
8
+ export const PlacekitCityInput = ({ value, onValueChange, country, disabled, placeholder, id, error, onSuggestion, onLoadError, apiKey, }) => {
9
+ const placekit = usePlacekit({ apiKey });
10
+ const loadSuggestions = useCallback((value) => {
11
+ if (placekit != null) {
12
+ const countries = Option.fromNullable(country)
13
+ .map(country => countriesWithMultipleCCA3[country] ?? [country])
14
+ .map(cca3Codes => Array.filterMap(cca3Codes, cca3 => Option.fromNullable(getCCA2forCCA3(cca3))))
15
+ .flatMap(array => (array.length === 0 ? Option.None() : Option.Some(array)));
16
+ return Future.fromPromise(placekit.search(value, {
17
+ types: ["city"],
18
+ countries: countries.toUndefined(),
19
+ })).mapOk(({ results }) => results.map(result => ({
20
+ title: result.name,
21
+ subtitle: result.city,
22
+ value: result,
23
+ })), true);
24
+ }
25
+ return Future.value(Result.Ok([]));
26
+ }, [placekit, country]);
27
+ const onSuggestionSelected = useCallback((suggestion) => {
28
+ onSuggestion?.({
29
+ city: suggestion.value.city,
30
+ postalCode: suggestion.value.zipcode[0],
31
+ });
32
+ }, [onSuggestion]);
33
+ return (_jsx(AutocompleteSearchInput, { value: value, onValueChange: onValueChange, disabled: disabled, id: id, placeholder: placeholder, error: error, emptyResultText: t("common.noResult"), loadSuggestions: placekit != null ? loadSuggestions : undefined, onSuggestion: onSuggestionSelected, onLoadError: onLoadError }));
34
+ };
@@ -1979,8 +1979,8 @@ export declare const countries: ({
1979
1979
  export type Country = (typeof countries)[number];
1980
1980
  export type CountryCCA2 = (typeof countries)[number]["cca2"];
1981
1981
  export type CountryCCA3 = (typeof countries)[number]["cca3"];
1982
- export declare const getCCA2forCCA3: (cca3: CountryCCA3) => "FR" | "AX" | "AS" | "AD" | "AO" | "AI" | "AQ" | "AG" | "AR" | "AW" | "AU" | "AZ" | "BS" | "BD" | "BB" | "BE" | "BZ" | "BJ" | "BM" | "BO" | "BQ" | "BA" | "BW" | "BV" | "BR" | "VG" | "BF" | "BI" | "CV" | "CM" | "CA" | "KY" | "CZ" | "CL" | "CX" | "CC" | "CO" | "CK" | "CR" | "CI" | "CU" | "CW" | "DK" | "DE" | "DJ" | "DM" | "EC" | "EE" | "IE" | "SV" | "ES" | "FK" | "FJ" | "FO" | "GA" | "GM" | "GH" | "GI" | "GD" | "GP" | "GU" | "GT" | "GG" | "GW" | "GQ" | "GN" | "GY" | "GF" | "HT" | "HM" | "HN" | "HR" | "ID" | "IS" | "IM" | "IT" | "JM" | "JE" | "GL" | "KH" | "KZ" | "KE" | "KI" | "CF" | "KM" | "RE" | "LV" | "LS" | "LR" | "LI" | "LT" | "LU" | "MG" | "HU" | "MH" | "MW" | "MY" | "MV" | "ML" | "MT" | "MQ" | "MU" | "YT" | "MX" | "FM" | "MZ" | "MD" | "MC" | "MS" | "NA" | "NL" | "BN" | "NZ" | "NI" | "NE" | "NG" | "NU" | "NF" | "NO" | "MP" | "NC" | "AT" | "UZ" | "PK" | "PW" | "PA" | "PG" | "PY" | "PE" | "PH" | "PN" | "PL" | "PF" | "PT" | "PR" | "DO" | "XK" | "CD" | "CG" | "RO" | "RW" | "KN" | "LC" | "VC" | "BL" | "MF" | "PM" | "WS" | "SM" | "ST" | "CH" | "SN" | "SC" | "AL" | "SL" | "SG" | "SI" | "SK" | "SB" | "SO" | "ZA" | "GS" | "SS" | "LK" | "FI" | "SR" | "SE" | "SZ" | "TZ" | "TD" | "TF" | "TL" | "TG" | "TO" | "TT" | "TR" | "TM" | "TC" | "TV" | "UG" | "GB" | "US" | "UM" | "VI" | "UY" | "VU" | "VA" | "VE" | "VN" | "WF" | "ZM" | "ZW" | "BT" | "GR" | "CY" | "BY" | "BG" | "KG" | "MK" | "MN" | "RU" | "RS" | "TJ" | "UA" | "ME" | "AM" | "IL" | "AF" | "JO" | "DZ" | "SD" | "EH" | "IQ" | "SA" | "KW" | "MA" | "YE" | "IR" | "TN" | "AE" | "SY" | "OM" | "PS" | "QA" | "LB" | "EG" | "MR" | "NP" | "IN" | "TH" | "LA" | "MM" | "GE" | "ET" | "ER" | "BH" | "LY" | "CN" | "JP" | "MO" | "TW" | "HK" | "KR" | "KP" | undefined;
1983
- export declare const getCCA3forCCA2: (cca2: CountryCCA2) => "FRA" | "ALA" | "ASM" | "AND" | "AGO" | "AIA" | "ATA" | "ATG" | "ARG" | "ABW" | "AUS" | "AZE" | "BHS" | "BGD" | "BRB" | "BEL" | "BLZ" | "BEN" | "BMU" | "BOL" | "BES" | "BIH" | "BWA" | "BVT" | "BRA" | "VGB" | "BFA" | "BDI" | "CPV" | "CMR" | "CAN" | "CYM" | "CZE" | "CHL" | "CXR" | "CCK" | "COL" | "COK" | "CRI" | "CIV" | "CUB" | "CUW" | "DNK" | "DEU" | "DJI" | "DMA" | "ECU" | "EST" | "IRL" | "SLV" | "ESP" | "FLK" | "FJI" | "FRO" | "GAB" | "GMB" | "GHA" | "GIB" | "GRD" | "GLP" | "GUM" | "GTM" | "GGY" | "GNB" | "GNQ" | "GIN" | "GUY" | "GUF" | "HTI" | "HMD" | "HND" | "HRV" | "IDN" | "ISL" | "IMN" | "ITA" | "JAM" | "JEY" | "GRL" | "KHM" | "KAZ" | "KEN" | "KIR" | "CAF" | "COM" | "REU" | "LVA" | "LSO" | "LBR" | "LIE" | "LTU" | "LUX" | "MDG" | "HUN" | "MHL" | "MWI" | "MYS" | "MDV" | "MLI" | "MLT" | "MTQ" | "MUS" | "MYT" | "MEX" | "FSM" | "MOZ" | "MDA" | "MCO" | "MSR" | "NAM" | "NLD" | "BRN" | "NZL" | "NIC" | "NER" | "NGA" | "NIU" | "NFK" | "NOR" | "MNP" | "NCL" | "AUT" | "UZB" | "PAK" | "PLW" | "PAN" | "PNG" | "PRY" | "PER" | "PHL" | "PCN" | "POL" | "PYF" | "PRT" | "PRI" | "DOM" | "UNK" | "COD" | "COG" | "ROU" | "RWA" | "KNA" | "LCA" | "VCT" | "BLM" | "MAF" | "SPM" | "WSM" | "SMR" | "STP" | "CHE" | "SEN" | "SYC" | "ALB" | "SLE" | "SGP" | "SVN" | "SVK" | "SLB" | "SOM" | "ZAF" | "SGS" | "SSD" | "LKA" | "FIN" | "SUR" | "SWE" | "SWZ" | "TZA" | "TCD" | "ATF" | "TLS" | "TGO" | "TON" | "TTO" | "TUR" | "TKM" | "TCA" | "TUV" | "UGA" | "GBR" | "USA" | "UMI" | "VIR" | "URY" | "VUT" | "VAT" | "VEN" | "VNM" | "WLF" | "ZMB" | "ZWE" | "BTN" | "GRC" | "CYP" | "BLR" | "BGR" | "KGZ" | "MKD" | "MNG" | "RUS" | "SRB" | "TJK" | "UKR" | "MNE" | "ARM" | "ISR" | "AFG" | "JOR" | "DZA" | "SDN" | "ESH" | "IRQ" | "SAU" | "KWT" | "MAR" | "YEM" | "IRN" | "TUN" | "ARE" | "SYR" | "OMN" | "PSE" | "QAT" | "LBN" | "EGY" | "MRT" | "NPL" | "IND" | "THA" | "LAO" | "MMR" | "GEO" | "ETH" | "ERI" | "BHR" | "LBY" | "CHN" | "JPN" | "MAC" | "TWN" | "HKG" | "KOR" | "PRK" | undefined;
1982
+ export declare const getCCA2forCCA3: (cca3: CountryCCA3) => CountryCCA2 | undefined;
1983
+ export declare const getCCA3forCCA2: (cca2: CountryCCA2) => CountryCCA3 | undefined;
1984
1984
  export declare const companyWithUboCountries: readonly ["BEL", "DEU", "FRA", "ITA", "LTU", "LUX", "NLD"];
1985
1985
  export type CompanyWithUboCountryCCA3 = (typeof companyWithUboCountries)[number];
1986
1986
  export declare const allCountries: ("FRA" | "ALA" | "ASM" | "AND" | "AGO" | "AIA" | "ATA" | "ATG" | "ARG" | "ABW" | "AUS" | "AZE" | "BHS" | "BGD" | "BRB" | "BEL" | "BLZ" | "BEN" | "BMU" | "BOL" | "BES" | "BIH" | "BWA" | "BVT" | "BRA" | "VGB" | "BFA" | "BDI" | "CPV" | "CMR" | "CAN" | "CYM" | "CZE" | "CHL" | "CXR" | "CCK" | "COL" | "COK" | "CRI" | "CIV" | "CUB" | "CUW" | "DNK" | "DEU" | "DJI" | "DMA" | "ECU" | "EST" | "IRL" | "SLV" | "ESP" | "FLK" | "FJI" | "FRO" | "GAB" | "GMB" | "GHA" | "GIB" | "GRD" | "GLP" | "GUM" | "GTM" | "GGY" | "GNB" | "GNQ" | "GIN" | "GUY" | "GUF" | "HTI" | "HMD" | "HND" | "HRV" | "IDN" | "ISL" | "IMN" | "ITA" | "JAM" | "JEY" | "GRL" | "KHM" | "KAZ" | "KEN" | "KIR" | "CAF" | "COM" | "REU" | "LVA" | "LSO" | "LBR" | "LIE" | "LTU" | "LUX" | "MDG" | "HUN" | "MHL" | "MWI" | "MYS" | "MDV" | "MLI" | "MLT" | "MTQ" | "MUS" | "MYT" | "MEX" | "FSM" | "MOZ" | "MDA" | "MCO" | "MSR" | "NAM" | "NLD" | "BRN" | "NZL" | "NIC" | "NER" | "NGA" | "NIU" | "NFK" | "NOR" | "MNP" | "NCL" | "AUT" | "UZB" | "PAK" | "PLW" | "PAN" | "PNG" | "PRY" | "PER" | "PHL" | "PCN" | "POL" | "PYF" | "PRT" | "PRI" | "DOM" | "UNK" | "COD" | "COG" | "ROU" | "RWA" | "KNA" | "LCA" | "VCT" | "BLM" | "MAF" | "SPM" | "WSM" | "SMR" | "STP" | "CHE" | "SEN" | "SYC" | "ALB" | "SLE" | "SGP" | "SVN" | "SVK" | "SLB" | "SOM" | "ZAF" | "SGS" | "SSD" | "LKA" | "FIN" | "SUR" | "SWE" | "SWZ" | "TZA" | "TCD" | "ATF" | "TLS" | "TGO" | "TON" | "TTO" | "TUR" | "TKM" | "TCA" | "TUV" | "UGA" | "GBR" | "USA" | "UMI" | "VIR" | "URY" | "VUT" | "VAT" | "VEN" | "VNM" | "WLF" | "ZMB" | "ZWE" | "BTN" | "GRC" | "CYP" | "BLR" | "BGR" | "KGZ" | "MKD" | "MNG" | "RUS" | "SRB" | "TJK" | "UKR" | "MNE" | "ARM" | "ISR" | "AFG" | "JOR" | "DZA" | "SDN" | "ESH" | "IRQ" | "SAU" | "KWT" | "MAR" | "YEM" | "IRN" | "TUN" | "ARE" | "SYR" | "OMN" | "PSE" | "QAT" | "LBN" | "EGY" | "MRT" | "NPL" | "IND" | "THA" | "LAO" | "MMR" | "GEO" | "ETH" | "ERI" | "BHR" | "LBY" | "CHN" | "JPN" | "MAC" | "TWN" | "HKG" | "KOR" | "PRK")[];
@@ -1988,7 +1988,7 @@ export declare const individualCountries: ("FRA" | "BEL" | "CZE" | "DNK" | "DEU"
1988
1988
  export type IndividualCountryCCA3 = (typeof individualCountries)[number];
1989
1989
  export declare const companyCountries: ("FRA" | "BEL" | "CZE" | "DNK" | "DEU" | "EST" | "IRL" | "ESP" | "HRV" | "ISL" | "ITA" | "LVA" | "LIE" | "LTU" | "LUX" | "HUN" | "MLT" | "MCO" | "NLD" | "NOR" | "AUT" | "POL" | "PRT" | "ROU" | "SVN" | "SVK" | "FIN" | "SWE" | "GRC" | "CYP" | "BGR")[];
1990
1990
  export type CompanyCountryCCA3 = (typeof companyCountries)[number];
1991
- export declare const countriesWithMultipleCCA3: Partial<Record<CountryCCA3, string[]>>;
1991
+ export declare const countriesWithMultipleCCA3: Partial<Record<CountryCCA3, CountryCCA3[]>>;
1992
1992
  export declare const isCountryCCA3: (value: unknown) => value is "FRA" | "ALA" | "ASM" | "AND" | "AGO" | "AIA" | "ATA" | "ATG" | "ARG" | "ABW" | "AUS" | "AZE" | "BHS" | "BGD" | "BRB" | "BEL" | "BLZ" | "BEN" | "BMU" | "BOL" | "BES" | "BIH" | "BWA" | "BVT" | "BRA" | "VGB" | "BFA" | "BDI" | "CPV" | "CMR" | "CAN" | "CYM" | "CZE" | "CHL" | "CXR" | "CCK" | "COL" | "COK" | "CRI" | "CIV" | "CUB" | "CUW" | "DNK" | "DEU" | "DJI" | "DMA" | "ECU" | "EST" | "IRL" | "SLV" | "ESP" | "FLK" | "FJI" | "FRO" | "GAB" | "GMB" | "GHA" | "GIB" | "GRD" | "GLP" | "GUM" | "GTM" | "GGY" | "GNB" | "GNQ" | "GIN" | "GUY" | "GUF" | "HTI" | "HMD" | "HND" | "HRV" | "IDN" | "ISL" | "IMN" | "ITA" | "JAM" | "JEY" | "GRL" | "KHM" | "KAZ" | "KEN" | "KIR" | "CAF" | "COM" | "REU" | "LVA" | "LSO" | "LBR" | "LIE" | "LTU" | "LUX" | "MDG" | "HUN" | "MHL" | "MWI" | "MYS" | "MDV" | "MLI" | "MLT" | "MTQ" | "MUS" | "MYT" | "MEX" | "FSM" | "MOZ" | "MDA" | "MCO" | "MSR" | "NAM" | "NLD" | "BRN" | "NZL" | "NIC" | "NER" | "NGA" | "NIU" | "NFK" | "NOR" | "MNP" | "NCL" | "AUT" | "UZB" | "PAK" | "PLW" | "PAN" | "PNG" | "PRY" | "PER" | "PHL" | "PCN" | "POL" | "PYF" | "PRT" | "PRI" | "DOM" | "UNK" | "COD" | "COG" | "ROU" | "RWA" | "KNA" | "LCA" | "VCT" | "BLM" | "MAF" | "SPM" | "WSM" | "SMR" | "STP" | "CHE" | "SEN" | "SYC" | "ALB" | "SLE" | "SGP" | "SVN" | "SVK" | "SLB" | "SOM" | "ZAF" | "SGS" | "SSD" | "LKA" | "FIN" | "SUR" | "SWE" | "SWZ" | "TZA" | "TCD" | "ATF" | "TLS" | "TGO" | "TON" | "TTO" | "TUR" | "TKM" | "TCA" | "TUV" | "UGA" | "GBR" | "USA" | "UMI" | "VIR" | "URY" | "VUT" | "VAT" | "VEN" | "VNM" | "WLF" | "ZMB" | "ZWE" | "BTN" | "GRC" | "CYP" | "BLR" | "BGR" | "KGZ" | "MKD" | "MNG" | "RUS" | "SRB" | "TJK" | "UKR" | "MNE" | "ARM" | "ISR" | "AFG" | "JOR" | "DZA" | "SDN" | "ESH" | "IRQ" | "SAU" | "KWT" | "MAR" | "YEM" | "IRN" | "TUN" | "ARE" | "SYR" | "OMN" | "PSE" | "QAT" | "LBN" | "EGY" | "MRT" | "NPL" | "IND" | "THA" | "LAO" | "MMR" | "GEO" | "ETH" | "ERI" | "BHR" | "LBY" | "CHN" | "JPN" | "MAC" | "TWN" | "HKG" | "KOR" | "PRK";
1993
1993
  export declare const isCountryCCA2: (value: unknown) => value is "FR" | "AX" | "AS" | "AD" | "AO" | "AI" | "AQ" | "AG" | "AR" | "AW" | "AU" | "AZ" | "BS" | "BD" | "BB" | "BE" | "BZ" | "BJ" | "BM" | "BO" | "BQ" | "BA" | "BW" | "BV" | "BR" | "VG" | "BF" | "BI" | "CV" | "CM" | "CA" | "KY" | "CZ" | "CL" | "CX" | "CC" | "CO" | "CK" | "CR" | "CI" | "CU" | "CW" | "DK" | "DE" | "DJ" | "DM" | "EC" | "EE" | "IE" | "SV" | "ES" | "FK" | "FJ" | "FO" | "GA" | "GM" | "GH" | "GI" | "GD" | "GP" | "GU" | "GT" | "GG" | "GW" | "GQ" | "GN" | "GY" | "GF" | "HT" | "HM" | "HN" | "HR" | "ID" | "IS" | "IM" | "IT" | "JM" | "JE" | "GL" | "KH" | "KZ" | "KE" | "KI" | "CF" | "KM" | "RE" | "LV" | "LS" | "LR" | "LI" | "LT" | "LU" | "MG" | "HU" | "MH" | "MW" | "MY" | "MV" | "ML" | "MT" | "MQ" | "MU" | "YT" | "MX" | "FM" | "MZ" | "MD" | "MC" | "MS" | "NA" | "NL" | "BN" | "NZ" | "NI" | "NE" | "NG" | "NU" | "NF" | "NO" | "MP" | "NC" | "AT" | "UZ" | "PK" | "PW" | "PA" | "PG" | "PY" | "PE" | "PH" | "PN" | "PL" | "PF" | "PT" | "PR" | "DO" | "XK" | "CD" | "CG" | "RO" | "RW" | "KN" | "LC" | "VC" | "BL" | "MF" | "PM" | "WS" | "SM" | "ST" | "CH" | "SN" | "SC" | "AL" | "SL" | "SG" | "SI" | "SK" | "SB" | "SO" | "ZA" | "GS" | "SS" | "LK" | "FI" | "SR" | "SE" | "SZ" | "TZ" | "TD" | "TF" | "TL" | "TG" | "TO" | "TT" | "TR" | "TM" | "TC" | "TV" | "UG" | "GB" | "US" | "UM" | "VI" | "UY" | "VU" | "VA" | "VE" | "VN" | "WF" | "ZM" | "ZW" | "BT" | "GR" | "CY" | "BY" | "BG" | "KG" | "MK" | "MN" | "RU" | "RS" | "TJ" | "UA" | "ME" | "AM" | "IL" | "AF" | "JO" | "DZ" | "SD" | "EH" | "IQ" | "SA" | "KW" | "MA" | "YE" | "IR" | "TN" | "AE" | "SY" | "OM" | "PS" | "QA" | "LB" | "EG" | "MR" | "NP" | "IN" | "TH" | "LA" | "MM" | "GE" | "ET" | "ER" | "BH" | "LY" | "CN" | "JP" | "MO" | "TW" | "HK" | "KR" | "KP";
1994
1994
  export declare const isIndividualCountryCCA3: (value: unknown) => value is "FRA" | "BEL" | "CZE" | "DNK" | "DEU" | "EST" | "IRL" | "ESP" | "HRV" | "ISL" | "ITA" | "LVA" | "LIE" | "LTU" | "LUX" | "HUN" | "MLT" | "MCO" | "NLD" | "NOR" | "AUT" | "POL" | "PRT" | "ROU" | "SVN" | "SVK" | "FIN" | "SWE" | "GRC" | "CYP" | "BGR";
@@ -0,0 +1,4 @@
1
+ import { PKClient } from "@placekit/client-js";
2
+ export declare const usePlacekit: ({ apiKey }: {
3
+ apiKey?: string | undefined;
4
+ }) => PKClient | undefined;
@@ -0,0 +1,12 @@
1
+ import { useEffect, useState } from "react";
2
+ export const usePlacekit = ({ apiKey }) => {
3
+ const [placekit, setPlacekit] = useState(undefined);
4
+ useEffect(() => {
5
+ if (apiKey != null) {
6
+ void import("@placekit/client-js").then(({ default: placekit }) => {
7
+ setPlacekit(placekit(apiKey));
8
+ });
9
+ }
10
+ }, [apiKey]);
11
+ return placekit;
12
+ };
@@ -1,50 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Future, Result } from "@swan-io/boxed";
3
- import { AutoWidthImage } from "@swan-io/lake/src/components/AutoWidthImage";
4
- import { AutocompleteSearchInput } from "@swan-io/lake/src/components/AutocompleteSearchInput";
5
- import { Box } from "@swan-io/lake/src/components/Box";
6
- import { countriesWithMultipleCCA3, } from "@swan-io/shared-business/src/constants/countries";
7
- import { useCallback, useMemo } from "react";
8
- import { StyleSheet } from "react-native";
9
- import poweredByGoogle from "../assets/images/powered_by_google_on_white_hdpi.png";
10
- import { getPlaceDetails, useGoogleMapSDK } from "../hooks/useGoogleMapSDK";
11
- const styles = StyleSheet.create({
12
- footer: {
13
- padding: 12,
14
- paddingBottom: 4,
15
- },
16
- });
17
- export const GMapAddressSearchInput = ({ inputRef, id, country, disabled, error, value, onValueChange, onSuggestion, language, placeholder, shouldDisplaySuggestions = true, emptyResultText, apiKey, }) => {
18
- const sdk = useGoogleMapSDK({
19
- language,
20
- apiKey,
21
- });
22
- const autocomplete = useMemo(() => sdk.map(google => new google.maps.places.AutocompleteService()), [sdk]);
23
- const loadSuggestions = useCallback((value) => {
24
- if (autocomplete.isDone()) {
25
- return Future.fromPromise(autocomplete.get().getPlacePredictions({
26
- input: value,
27
- componentRestrictions: { country: countriesWithMultipleCCA3[country] ?? [country] },
28
- types: ["address"],
29
- })).mapOk(({ predictions }) => predictions.map(p => ({
30
- id: p.place_id,
31
- title: p.structured_formatting.main_text,
32
- subtitle: p.structured_formatting.secondary_text,
33
- value: null,
34
- })), true);
35
- }
36
- return Future.value(Result.Ok([]));
37
- }, [autocomplete, country]);
38
- const onSuggestionSelected = useCallback((suggestion) => {
39
- getPlaceDetails(suggestion.id).onResolve(result => {
40
- if (result.isOk()) {
41
- const dependsOnCountriesWithMultipleCCA3 = countriesWithMultipleCCA3[country]?.includes(result.value.country);
42
- onSuggestion?.({
43
- ...result.value,
44
- country: dependsOnCountriesWithMultipleCCA3 === true ? country : result.value.country,
45
- });
46
- }
47
- });
48
- }, [country, onSuggestion]);
49
- return (_jsx(AutocompleteSearchInput, { inputRef: inputRef, value: value, onValueChange: onValueChange, disabled: disabled, id: id, placeholder: placeholder, error: error, emptyResultText: emptyResultText, ListFooterComponent: _jsx(Box, { direction: "row", justifyContent: "end", style: styles.footer, children: _jsx(AutoWidthImage, { height: 14, sourceUri: poweredByGoogle }) }), shouldDisplaySuggestions: shouldDisplaySuggestions, loadSuggestions: loadSuggestions, onSuggestion: onSuggestionSelected }));
50
- };
@@ -1,16 +0,0 @@
1
- import { CountryCCA3 } from "../constants/countries";
2
- import { PlaceDetail } from "../hooks/useGoogleMapSDK";
3
- type Props = {
4
- value: string;
5
- onValueChange: (value: string) => void;
6
- country?: CountryCCA3;
7
- disabled?: boolean;
8
- error?: string;
9
- id?: string;
10
- placeholder?: string;
11
- onSuggestion?: (place: Pick<PlaceDetail, "city" | "postalCode">) => void;
12
- onLoadError: (error: unknown) => void;
13
- apiKey: string;
14
- };
15
- export declare const GMapCityInput: ({ value, onValueChange, country, disabled, placeholder, id, error, onSuggestion, onLoadError, apiKey, }: Props) => import("react/jsx-runtime").JSX.Element;
16
- export {};
@@ -1,48 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Future, Result } from "@swan-io/boxed";
3
- import { AutoWidthImage } from "@swan-io/lake/src/components/AutoWidthImage";
4
- import { AutocompleteSearchInput } from "@swan-io/lake/src/components/AutocompleteSearchInput";
5
- import { Box } from "@swan-io/lake/src/components/Box";
6
- import { isNotNullish } from "@swan-io/lake/src/utils/nullish";
7
- import { useCallback, useMemo } from "react";
8
- import { StyleSheet } from "react-native";
9
- import poweredByGoogle from "../assets/images/powered_by_google_on_white_hdpi.png";
10
- import { countriesWithMultipleCCA3 } from "../constants/countries";
11
- import { getPlaceDetails, useGoogleMapSDK } from "../hooks/useGoogleMapSDK";
12
- import { t } from "../utils/i18n";
13
- const styles = StyleSheet.create({
14
- poweredByGoogle: {
15
- paddingVertical: 8,
16
- paddingHorizontal: 16,
17
- },
18
- });
19
- export const GMapCityInput = ({ value, onValueChange, country, disabled, placeholder, id, error, onSuggestion, onLoadError, apiKey, }) => {
20
- const sdk = useGoogleMapSDK({ apiKey });
21
- const autocomplete = useMemo(() => sdk.map(google => new google.maps.places.AutocompleteService()), [sdk]);
22
- const loadSuggestions = useCallback((value) => {
23
- if (autocomplete.isDone() && isNotNullish(country)) {
24
- return Future.fromPromise(autocomplete.get().getPlacePredictions({
25
- input: value,
26
- componentRestrictions: {
27
- country: [...(countriesWithMultipleCCA3[country] ?? "")],
28
- },
29
- types: ["(cities)"],
30
- })).mapOk(({ predictions }) => predictions.map(p => ({
31
- id: p.place_id,
32
- title: p.structured_formatting.main_text,
33
- subtitle: p.structured_formatting.secondary_text,
34
- value: null,
35
- })), true);
36
- }
37
- return Future.value(Result.Ok([]));
38
- }, [autocomplete, country]);
39
- const onSuggestionSelected = useCallback((suggestion) => {
40
- getPlaceDetails(suggestion.id).onResolve(result => {
41
- if (result.isOk()) {
42
- console.log("result.value", result.value);
43
- onSuggestion?.(result.value);
44
- }
45
- });
46
- }, [onSuggestion]);
47
- return (_jsx(AutocompleteSearchInput, { value: value, onValueChange: onValueChange, disabled: disabled, id: id, placeholder: placeholder, error: error, emptyResultText: t("common.noResult"), ListFooterComponent: _jsx(Box, { direction: "row", justifyContent: "end", style: styles.poweredByGoogle, children: _jsx(AutoWidthImage, { height: 14, sourceUri: poweredByGoogle }) }), loadSuggestions: loadSuggestions, onSuggestion: onSuggestionSelected, onLoadError: onLoadError }));
48
- };
@@ -1,16 +0,0 @@
1
- /// <reference types="google.maps" />
2
- import { AsyncData, Future, Result } from "@swan-io/boxed";
3
- type Props = {
4
- language?: string;
5
- apiKey: string;
6
- };
7
- export declare const useGoogleMapSDK: ({ language, apiKey }: Props) => AsyncData<typeof google>;
8
- export type PlaceDetail = {
9
- completeAddress: string;
10
- streetNumber: string;
11
- city: string;
12
- country: string;
13
- postalCode: string;
14
- };
15
- export declare const getPlaceDetails: (placeId: string) => Future<Result<PlaceDetail, unknown>>;
16
- export {};
@@ -1,63 +0,0 @@
1
- import { Loader } from "@googlemaps/js-api-loader";
2
- import { AsyncData, Future, Result } from "@swan-io/boxed";
3
- import { useEffect } from "react";
4
- import { atom, useAtom } from "react-atomic-state";
5
- import { match } from "ts-pattern";
6
- import { getCCA3forCCA2 } from "../constants/countries";
7
- const sdk = atom(AsyncData.NotAsked());
8
- export const useGoogleMapSDK = ({ language, apiKey }) => {
9
- const googleSdk = useAtom(sdk);
10
- useEffect(() => {
11
- if (googleSdk.isNotAsked()) {
12
- if (apiKey != undefined) {
13
- sdk.set(AsyncData.Loading());
14
- void new Loader({
15
- apiKey,
16
- language,
17
- libraries: ["places"],
18
- authReferrerPolicy: "origin",
19
- })
20
- .load()
21
- .then(google => sdk.set(AsyncData.Done(google)));
22
- }
23
- }
24
- }, [language, googleSdk, apiKey]);
25
- return googleSdk;
26
- };
27
- export const getPlaceDetails = (placeId) => {
28
- return Future.make(resolve => {
29
- const place = new google.maps.places.PlacesService(document.createElement("div"));
30
- place.getDetails({ placeId }, placeDetail => {
31
- if (placeDetail?.address_components == null) {
32
- resolve(Result.Error("No place detail found"));
33
- return;
34
- }
35
- const result = {
36
- completeAddress: "",
37
- streetNumber: "",
38
- postalCode: "",
39
- country: "",
40
- city: "",
41
- };
42
- placeDetail.address_components.forEach(({ types, short_name, long_name }) => {
43
- const type = types[0];
44
- match(type)
45
- .with("street_number", () => (result.streetNumber = long_name))
46
- .with("route", () => (result.completeAddress = long_name))
47
- .with("postal_code", () => (result.postalCode = short_name))
48
- .with("country", () => (result.country = getCCA3forCCA2(short_name) ?? short_name))
49
- .with("locality", () => (result.city = long_name))
50
- .otherwise(() => { });
51
- });
52
- if (result.streetNumber != "") {
53
- if (placeDetail?.name === `${result.completeAddress} ${result.streetNumber}`) {
54
- result.completeAddress = `${result.completeAddress} ${result.streetNumber}`;
55
- }
56
- else {
57
- result.completeAddress = `${result.streetNumber} ${result.completeAddress}`;
58
- }
59
- }
60
- resolve(Result.Ok(result));
61
- });
62
- });
63
- };