wix-style-react
Version:
wix-style-react
166 lines • 8.4 kB
JavaScript
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