npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

preact-places-autocomplete

v0.0.3

Published

[![travis build](https://img.shields.io/travis/kenny-hibino/preact-places-autocomplete.svg?style=flat-square)](https://travis-ci.org/kenny-hibino/preact-places-autocomplete) [![MIT-License](https://img.shields.io/npm/l/preact-places-autocomplete.svg?styl

Downloads

3

Readme

travis build MIT-License Gitter

Preact Places Autocomplete (forked from React Places Autocomplete)

A React component to build a customized UI for Google Maps Places Autocomplete

Demo

Live demo: kenny-hibino.github.io/preact-places-autocomplete/

Features

  1. Enable you to easily build a customized autocomplete dropdown powered by Google Maps Places Library
  2. Utility functions to geocode and get latitude and longitude using Google Maps Geocoder API
  3. Full control over rendering to integrate well with other libraries (e.g. Redux-Form)
  4. Mobile friendly UX
  5. WAI-ARIA compliant
  6. Support Asynchronous Google script loading

Installation

To install the stable version

npm install --save preact-places-autocomplete

React component is exported as a default export

import PlacesAutocomplete from 'preact-places-autocomplete'

utility functions are named exports

import { geocodeByAddress, geocodeByPlaceId, getLatLng } from 'preact-places-autocomplete'

Getting Started

To use this component, you are going to need to load Google Maps JavaScript API

Load the library in your project

<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places"></script>

Create your component

import React from 'react'
import PlacesAutocomplete, { geocodeByAddress, getLatLng } from 'preact-places-autocomplete'

class LocationSearchInput extends React.Component {
  constructor(props) {
    super(props);  
    this.state = { address: '' }
  }

  handleChange = (address) => {
    this.setState({ address })
  }

  handleSelect = (address) => {
    geocodeByAddress(address)
      .then(results => getLatLng(results[0]))
      .then(latLng => console.log('Success', latLng))
      .catch(error => console.error('Error', error))
  }

  render() {
    return (
      <PlacesAutocomplete
        value={this.state.address}
        onChange={this.handleChange}
        onSelect={this.handleSelect}
      >
        {({ getInputProps, suggestions, getSuggestionItemProps }) => (
          <div>
            <input
              {...getInputProps({
                placeholder: 'Search Places ...',
                className: 'location-search-input'
              })}
            />
            <div className="autocomplete-dropdown-container">
              {suggestions.map(suggestion => {
                const className = suggestion.active ? 'suggestion-item--active' : 'suggestion-item';
                // inline style for demonstration purpose
                const style = suggestion.active
                            ? { backgroundColor: '#fafafa', cursor: 'pointer' }
                            : { backgroundColor: '#ffffff', cursor: 'pointer' };
                return (
                  <div {...getSuggestionItemProps(suggestion, { className, style })}>
                    <span>{suggestion.description}</span>
                  </div>
                )
              })}
            </div>
          </div>
        )}
      </PlacesAutocomplete>
    );
  }
}

Props

PlacesAutocomplete is a Controlled Component with a Render Prop. Therefore, you MUST pass at least value and onChange callback to the input element, and render function via children.

| Prop | Type | Required | Description | | ------------- |:-------------:| :-----: |-------| | value | string | :white_check_mark: | value for the input element | | onChange | function | :white_check_mark: | onChange function for the input element | | children | function | :white_check_mark: | Render function to specify the rendering | | onSelect | function | | Event handler to handle user's select event | | onError | function | | Error handler function that gets called when Google Maps API responds with an error | | searchOptions | object | | Options to Google Maps API (i.e. bounds, radius) | |debounce | number | | Number of milliseconds to delay before making a call to Google Maps API | | highlightFirstSuggestion | boolean | | If set to true, first list item in the dropdown will be automatically highlighted | |shouldFetchSuggestions| boolean | | Component will hit Google Maps API only if this flag is set true | |googleCallbackName| string | | You can provide a callback name to initialize PlacesAutocomplete after google script is loaded |

value

Type: string, Required: true

onChange

Type: function, Required: true

Typically this event handler will update value state.

<PlacesAutocomplete
  value={this.state.value}
  onChange={value => this.setState({ value })}
>
  {/* custom render function */}
</PlacesAutocomplete>

children

Type: function Required: true

This is where you render whatever you want to based on the state of PlacesAutocomplete. The function will take an object with the following keys.

  • getInputProps : function
  • getSuggestionItemProps : function
  • suggestions : array

Simple example

const renderFunc = ({ getInputProps, getSuggestionItemProps, suggestions }) => (
  <div className="autocomplete-root">
    <input {...getInputProps()} />
    <div className="autocomplete-dropdown-container">
      {suggestions.map(suggestion => (
        <div {...getSuggestionItemProps(suggestion)}>
          <span>{suggestion.description}</span>
        </div>  
      ))}
    </div>
  </div>
);

// In render function
<PlacesAutocomplete
  value={this.state.value}
  onChange={this.handleChange}
>
  {renderFunc}
</PlacesAutocomplete>

getInputProps

This function will return the props that you can spread over the <input /> element. You can optionally call the function with an object to pass other props to the input.

// In render function
<input {...getInputProps({ className: 'my-input', autoFocus: true })} />

getSuggestionItemProps

This function will return the props that you can spread over each suggestion item in your autocomplete dropdown. You MUST call it with suggestion object as an argument, and optionally pass an object to pass other props to the element.

// Simple example
<div className="autocomplete-dropdown">
  {suggestions.map(suggestion => (
    <div {...getSuggestionItemProps(suggesions)}>
      {suggesion.description}
    </div>
  ))}
</div>

// Pass options as a second argument
<div className="autocomplete-dropdown">
  {suggestions.map(suggestion => {
    const className = suggestion.active ? 'suggestion-item--active' : 'suggesion-item';
    return (
      <div {...getSuggestionItemProps(suggestion, { className })}>
        {suggestion.description}
      </div>
    );
  })}
</div>

suggestions

This is an array of suggestion objects each containing all the data from Google Maps API and other metadata.

An example of a suggestion object.

{
  active: false,
  description: "San Francisco, CA, USA",
  formattedSuggestion: { mainText: "San Francisco", secondaryText: "CA, USA" },
  id: "1b9ea3c094d3ac23c9a3afa8cd4d8a41f05de50a",
  index: 0,
  matchedSubstrings: [ {length: 8, offset: 0} ],
  placeId: "ChIJIQBpAG2ahYAR_6128GcTUEo",
  terms: [
    { offset: 0, value: "San Francisco" },
    { offset: 15, value: "CA" },
    { offset: 19, value: "USA" }
  ],
  types: ["locality", "political", "geocode"]
}

onSelect

Type: function Required: false, Default: null

You can pass a function that gets called instead of onChange function when user hits the Enter key or clicks on a suggestion item.

The function takes two positional arguments. First argument is address, second is placeId.

// NOTE: `placeId` is null when user hits Enter key with no suggestion item selected.
const handleSelect = (address: string, placeId: ?string) => {
  // Do something with address and placeId
}

// Pass this function via onSelect prop.
<PlacesAutocomplete
  value={this.state.value}
  onChange={this.handleChange}
  onSelect={this.handleSelect}
>
  {/* Custom render function */}
</PlacesAutocomplete>

onError

Type: function Required: false

You can pass onError prop to customize the behavior when google.maps.places.PlacesServiceStatus is not OK (e.g., no predictions are found)

Function takes status (string) and clearSuggestions (function) as parameters

// Log error status and clear dropdown when Google Maps API returns an error.
const onError = (status, clearSuggestions) => {
  console.log('Google Maps API returned error with status: ', status)
  clearSuggestions()
}

<PlacesAutocomplete
  value={this.state.value}
  onChange={this.handleChange}
  onError={onError}
>
  {/* Custom render function */}
</PlacesAutocomplete>

searchOptions

Type: Object Required: false Default: {}

You can fine-tune the settings passed to the AutocompleteService class with searchOptions prop. This prop accepts an object following the same format as google.maps.places.AutocompletionRequest (except for input, which comes from the value of the input field).

// these options will bias the autocomplete predictions toward Sydney, Australia with a radius of 2000 meters,
// and limit the results to addresses only
const searchOptions = {
  location: new google.maps.LatLng(-34, 151),
  radius: 2000,
  types: ['address']
}

<PlacesAutocomplete
  value={this.state.value}
  onChange={this.handleChange}
  searchOptions={searchOptions}
>
  {/* Custom render function */}
</PlacesAutocomplete>

debounce

Type: number Required: false Default: 200

The number of milliseconds to delay before making a call to Google Maps API.

highlightFirstSuggestion

Type: boolean Required: false Default: false

If set to true, first suggestion in the dropdown will be automatically set to be active.

shouldFetchSuggestions

Type: boolean Required: false Default: true

// Only fetch suggestions when the input text is longer than 3 characters.
<PlacesAutocomplete
  value={this.state.address}
  onChange={this.handleChange}
  shouldFetchSuggestions={this.state.address.length > 3}
>
  {/* custom render function */}
</PlacesAutocomplete>

googleCallbackName

Type: string Required: false Default: undefined

If provided, component will initialize after the browser has finished downloading google script.

IMPORTANT: To enable this async mode, you need to provide the same callback name to google script via callback=[YOUR CALLBACK NAME].

Example:

<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=myCallbackFunc"></script>

Then, provide googleCallbackName prop to PlacesAutocomplete.

<PlacesAutocomplete
  value={this.state.value}
  onChange={this.handleChange}
  googleCallbackName="myCallbackFunc"
>
  {/* custom render function */}
</PlacesAutocomplete>

NOTE: If there are more than one PlacesAutocomplete components rendered in the page, set up a callback function that calls a callback function for each component.

Example:

<script>
window.myCallbackFunc = function() {
  window.initOne && window.initOne();
  window.initTwo && window.initTwo();
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=myCallbackFunc"></script>
<PlacesAutocomplete
  value={this.state.value}
  onChange={this.handleChange}
  googleCallbackName="initOne"
>
  {/* custom render function */}
</PlacesAutocomplete>

<PlacesAutocomplete
  value={this.state.value}
  onChange={this.handleChange}
  googleCallbackName="initTwo"
>
  {/* custom render function */}
</PlacesAutocomplete>

Utility Functions

geocodeByAddress API

/**
 * Returns a promise
 * @param {String} address
 * @return {Promise}
*/
geocodeByAddress(address)

address

Type: String, Required: true

String that gets passed to Google Maps Geocoder

import { geocodeByAddress } from 'preact-places-autocomplete'

// `results` is an entire payload from Google API.
geocodeByAddress('Los Angeles, CA')
  .then(results => console.log(results))
  .catch(error => console.error(error))

geocodeByPlaceId API

/**
 * Returns a promise
 * @param {String} placeId
 * @return {Promise}
*/
geocodeByPlaceId(placeId)

placeId

Type: String, Required: true

String that gets passed to Google Maps Geocoder

import { geocodeByPlaceId } from 'preact-places-autocomplete'

// `results` is an entire payload from Google API.
geocodeByPlaceId('ChIJE9on3F3HwoAR9AhGJW_fL-I')
  .then(results => console.log(results))
  .catch(error => console.error(error))

getLatLng API

/**
 * Returns a promise
 * @param {Object} result
 * @return {Promise}
*/
getLatLng(result)

result

Type: Object Required: true

One of the element from results (returned from Google Maps Geocoder)

import { geocodeByAddress, getLatLng } from 'preact-places-autocomplete'

geocodeByAddress('Tokyo, Japan')
  .then(results => getLatLng(results[0]))
  .then(({ lat, lng }) => console.log('Successfully got latitude and longitude', { lat, lng }))

Discussion

Join us on Gitter if you are interested in contributing!

License

MIT