UNPKG

@navinc/base-react-components

Version:
110 lines (99 loc) 3.37 kB
import React, { useEffect, useRef } from 'react' import styled from 'styled-components' import { Copy } from './copy' import { Input, Label, FieldWrapper, Field, Errors, Err } from './form-elements/shared.js' import { loadScript } from '@navinc/utils' import noop from '@navinc/utils/noop.js' const handlePreventSubmitOnEnter = (keyDownEvent) => { if (keyDownEvent.keyCode === 13) keyDownEvent.preventDefault() } export const AddressInput = ({ className, label, hasSpaceForErrors, isInvalid, value, required, type, errors = [], lede = '', onAddressSelected = noop, touched, placeholder = 'Enter a location', ...props }) => { const inputRef = useRef(null) useEffect(() => { Promise.resolve( global?.google?.maps?.places?.Autocomplete ?? loadScript( 'https://maps.googleapis.com/maps/api/js?key=AIzaSyAvfE0mS4qeMdHm2fsIfE2XowJj6XG2pW8&libraries=places' ).then( () => global?.google?.maps?.places?.Autocomplete ?? Promise.reject(new Error('Error loading GoogleMaps script')) ) ) .then((Autocomplete) => { const autocomplete = new Autocomplete(inputRef.current, { types: ['address'], componentRestrictions: { country: 'us' }, }) autocomplete.addListener('place_changed', () => { const place = autocomplete.getPlace() // bail if there is a problem getting data from the api if (!place || !Array.isArray(place.address_components)) return const { locality: city = '', administrative_area_level_1: state = '', postal_code: zip = '', street_number: streetNumber = '', route: street = '', street1 = `${streetNumber} ${street}`.trim(), } = Object.assign( ...place.address_components .filter(({ types: [type] }) => ['street_number', 'route', 'locality', 'administrative_area_level_1', 'postal_code'].includes(type) ) .map(({ types: [type], long_name: longName, short_name: shortName }) => ({ [type]: ['route', 'locality'].includes(type) ? longName : shortName, })) ) onAddressSelected({ city, state, street1, zip }) }) }) .catch((err) => console.error(err)) // eslint-disable-next-line react-hooks/exhaustive-deps }, []) return ( <FieldWrapper className={className}> {lede && <Copy bold>{lede}</Copy>} <Field className="js-private" isInvalid={isInvalid} isVisited={touched || value || placeholder} onKeyDown={handlePreventSubmitOnEnter} required={required} type={type} value={value} > <Input ref={inputRef} type={type} required={required} value={value} isInvalid={isInvalid} placeholder={placeholder} {...props} /> <Label required={required} value={value}> {label} </Label> </Field> <Errors hasSpaceForErrors={hasSpaceForErrors}> {!!errors.length && errors.map((err, i) => <Err key={`err-${i}`}>{err}</Err>)} </Errors> </FieldWrapper> ) } const StyledAddressInput = styled(AddressInput)`` export default StyledAddressInput