UNPKG

wix-style-react

Version:
166 lines 8.4 kB
import React, { useCallback, useMemo, useRef, useImperativeHandle, } from 'react'; import PropTypes from 'prop-types'; import AddressInput from '../AddressInput'; import { addressInputItemBuilder } from '../AddressInputItem'; import usePlacesAutocomplete from '../providers/usePlacesAutocomplete'; import useAtlasClient from '../providers/useAtlasClient'; import { dataHooks } from './constants'; const AtlasAddressInput = React.forwardRef(({ baseUrl, token, language = 'en', locale = 'en-us', debounceMs, debounceFn, onChange, onClear, onSelect, onError, selectOnSubmit, optionLayout, optionPrefix, optionSuffix, status: statusProp, ...props }, ref) => { const client = useAtlasClient({ baseUrl, token, language, locale }); const { predictions, updatePredictions, clearPredictions, loading } = usePlacesAutocomplete({ client, debounceMs, debounceFn, onError }); // If not loading, show the status passed from props const status = loading ? 'loading' : statusProp; const options = useMemo(() => predictions.map(prediction => addressInputItemBuilder({ id: prediction.searchId, mainLabel: prediction.textStructure.mainText, secondaryLabel: prediction.textStructure.secondaryText, displayLabel: prediction.description, optionLayout, prefix: optionPrefix, suffix: optionSuffix, dataHook: dataHooks.item, })), [predictions, optionLayout, optionPrefix, optionSuffix]); const innerRef = useRef(); useImperativeHandle(ref, () => ({ focus: () => innerRef.current && innerRef.current.focus(), })); const _onChange = useCallback(event => { updatePredictions(event.target.value); onChange && onChange(event); }, [updatePredictions, onChange]); const _onClear = useCallback(() => { clearPredictions(); onClear && onClear(); }, [clearPredictions, onClear]); const _onSelect = useCallback(option => { const getAddress = () => client.getAddress(option.id); onSelect && onSelect(option, getAddress); }, [client, onSelect]); // A callback which is called when the user performs a Submit-Action const _onManualSubmit = useCallback(inputValue => { if (selectOnSubmit && onSelect && inputValue) { const option = addressInputItemBuilder({ id: inputValue, mainLabel: inputValue, displayLabel: inputValue, }); const getAddress = async () => { // search for address matching input value const addresses = await client.searchAddresses(inputValue); // Return first address result return addresses[0]; }; onSelect(option, getAddress); } }, [selectOnSubmit, onSelect, client]); return (React.createElement(AddressInput, { ...props, options: options, onChange: _onChange, onClear: _onClear, onSelect: _onSelect, onManuallyInput: _onManualSubmit, status: status, ref: innerRef })); }); AtlasAddressInput.displayName = 'AtlasAddressInput'; AtlasAddressInput.propTypes = { /** Accept a custom domain for WixAtlasServiceWeb to retrieve predictions from */ baseUrl: PropTypes.string, /** Sets an authorization token to pass to the Atlas Service */ token: PropTypes.string, /** Sets the `language` to pass to the Atlas Service. * Use the language code e.g. `'en'`. */ language: PropTypes.string, /** Sets the `locale` to pass to the Atlas Service. * Locale consists of language code and country code separated by a dash e.g. `'en-us'`. */ locale: PropTypes.string, /** Fetch predictions debounce in milliseconds (default: 200) */ debounceMs: PropTypes.number, /** Allows passing a custom debounce function (default: lodash debounce). * Usage: * (callback: Function, debounceMs: number) => Function */ debounceFn: PropTypes.func, /** Applies a data-hook HTML attribute that can be used in the tests */ dataHook: PropTypes.string, /** Specifies a CSS class name to be appended to the component’s root element */ className: PropTypes.string, /** Displays clear button (X) on a non-empty input */ clearButton: PropTypes.bool, /** Sets the initial input value */ initialValue: PropTypes.string, /** Sets a value to display (controlled mode) */ value: PropTypes.string, /** Specifies whether input is disabled */ disabled: PropTypes.bool, /** Defines a callback function which is called whenever a user selects a different option in the list. * @param {DropdownLayoutOption} option selected option * @param {() => Promise<Address>} getAddress function for retrieving additional place details */ onSelect: PropTypes.func, /** Defines a callback function which is called every time input value is changed */ onChange: PropTypes.func, /** Defines a handler for getting notified upon a clear event. When passed, it displays a clear button in the input. */ onClear: PropTypes.func, /** Defines a standard input onFocus callback */ onFocus: PropTypes.func, /** Defines a standard input onBlur callback */ onBlur: PropTypes.func, /** Specifies whether input is auto selected on focus */ autoSelect: PropTypes.bool, /** Specifies whether to trigger `onSelect` handler when performing a Submit-Action (Enter or Tab key down). * If set to true, `onSelect` will be called with the following params: * * `option`: an option with a label set to the input value. * * `getAddress`: function for retrieving additional place details * uses Atlas's search function to return the closest result to the input value * * This is useful when looking for locations for which Atlas does not give suggestions - for example: Apartment/Apt. */ selectOnSubmit: PropTypes.bool, /** Defines a handler for prediction fetching errors. Returns an error object. * you can read these [guidelines](https://bo.wix.com/wix-docs/rnd/platformization-guidelines/errors#platformization-guidelines_errors_errors) * to learn about the meaning of each error status. */ onError: PropTypes.func, /** Specify the status of a field. Mostly used for a “loading” indication upon async request calls. */ status: PropTypes.oneOf(['loading', 'error', 'warning']), /** Defines the message to display on status icon hover. If not given or empty there will be no tooltip */ statusMessage: PropTypes.node, /** Control the border style of an input */ border: PropTypes.oneOf(['standard', 'round', 'bottomLine', 'none']), /** Controls the size of the input */ size: PropTypes.oneOf(['small', 'medium', 'large']), /** Sets a placeholder message to display */ placeholder: PropTypes.string, /** Sets the message to show in a dropdown when no results are found */ noResultsText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), /** Sets the layout of `mainLabel` and `secondaryLabel`. The possible options can be either side by side or vertically stacked. */ optionLayout: PropTypes.oneOf(['single-line', 'double-line']), /** Pass any component to show as the prefix of the option, e.g., text, icon. */ optionPrefix: PropTypes.node, /** Pass any component to show as the suffix of the option, e.g., text, icon, button. */ optionSuffix: PropTypes.node, /** Allows to pass common popover props */ popoverProps: PropTypes.shape({ appendTo: PropTypes.oneOf(['window', 'scrollParent', 'parent', 'viewport']), maxWidth: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), minWidth: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), flip: PropTypes.bool, fixed: PropTypes.bool, placement: PropTypes.oneOf([ 'auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start', ]), dynamicWidth: PropTypes.bool, }), }; export default AtlasAddressInput; //# sourceMappingURL=AtlasAddressInput.js.map