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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@salla.sa/ui-google-map-render

v1.2.1

Published

Framework-agnostic Google Maps web components using Lit - lightweight with runtime library loading

Readme

@salla.sa/ui-google-map-render

Framework-agnostic Google Maps web components built with Lit. Modern, accessible, and easy to use in any web project.

Features

  • Lightweight: Only ~17KB gzipped - Google Maps loaded at runtime from CDN
  • Framework Agnostic: Works with React, Vue, Angular, or vanilla JavaScript
  • Modern API: Uses Google Maps JavaScript API v3 with AdvancedMarkerElement
  • TypeScript: Full TypeScript support with type definitions
  • 14 Languages: Built-in translations for English, Arabic, Spanish, French, German, and more
  • RTL Support: Automatic right-to-left layout for Arabic, Hebrew, Farsi, and Urdu
  • Geolocation: Built-in geolocation button with smart error handling
  • Comprehensive Components: Map, Markers, Info Windows, Shapes, Clustering, Street View
  • Accessible: ARIA labels and keyboard navigation support
  • Zero Dependencies: Only Lit framework (~50KB)

Installation

npm install @salla.sa/ui-google-map-render

Bundle Size: ~17KB gzipped (only Lit + component code)

Lightweight Design Philosophy

This library is designed to be extremely lightweight:

  • ✅ Only core component logic is bundled (~67KB uncompressed, ~17KB gzipped)
  • ✅ Google Maps libraries loaded dynamically at runtime from Google CDN
  • ✅ Marker clustering is completely optional (not bundled)
  • ✅ Zero dependencies except Lit framework

Optional: Marker Clustering Support

The <gmap-cluster> component requires the @googlemaps/markerclusterer package:

npm install @googlemaps/markerclusterer

This is only needed if you use <gmap-cluster>. All other components work without any additional dependencies.

Interactive Builder

🎨 Try the interactive builder to customize your map and generate code!

Open builder.html in your browser for a visual interface that lets you:

  • Adjust map properties in real-time
  • Customize marker styling and colors
  • Enable/disable features like geolocation and autocomplete
  • See available events with live monitoring
  • Generate ready-to-use code for Vanilla JS, Vue.js, or React

Simply open the file in your browser to start building!

Quick Start

1. Load the Google Maps API

import { load } from '@salla.sa/ui-google-map-render';

load({
  key: 'YOUR_API_KEY',
  version: 'quarterly',
  libraries: ['marker', 'places'],
  language: 'en',
  region: 'US',
  mapIds: ['YOUR_MAP_ID'], // Required for AdvancedMarkerElement
});

2. Use the Components

<gmap-map
  center='{"lat": 24.7136, "lng": 46.6753}'
  zoom="12"
  enable-geolocation
  language="en"
>
  <gmap-marker
    position='{"lat": 24.7136, "lng": 46.6753}'
    background="#EA4335"
    title="My Location"
  >
    <gmap-info-window opened>
      <div>
        <h3>Hello World!</h3>
        <p>This is an info window</p>
      </div>
    </gmap-info-window>
  </gmap-marker>
</gmap-map>

3. Custom Map Styling (Optional)

Customize your map appearance using cloud-based Map Styles in Google Cloud Console.

Steps:

  1. Go to Google Cloud Console → Map Styles
  2. Create a new style or import JSON
  3. Save and copy your Map ID
  4. Use the Map ID in your component
<gmap-map
  center='{"lat": 24.7136, "lng": 46.6753}'
  zoom="12"
  map-id="YOUR_CUSTOM_STYLED_MAP_ID"
>
</gmap-map>

📖 Guides:

Components

<gmap-map> - Main Map Component

The core map component that renders a Google Map.

Properties:

| Property | Type | Default | Description | |----------|------|---------|-------------| | center | {lat, lng} | Required | Map center coordinates | | zoom | number | 10 | Zoom level (0-22) | | mapId | string | - | Google Cloud Map ID (required for markers, also controls styling) | | mapTypeId | string | 'roadmap' | Map type: roadmap, hybrid, satellite, terrain | | gestureHandling | string | 'cooperative' | Gesture handling mode | | enableGeolocation | boolean | false | Show geolocation button | | showLocationMarker | boolean | true | Show marker at user's location (when using geolocation) | | locationMarkerPosition | {lat, lng, accuracy?} | - | Initial location marker position | | locationMarkerBackground | string | '#4285F4' | Location marker background color | | locationMarkerBorderColor | string | '#1967D2' | Location marker border color | | locationMarkerGlyphColor | string | '#FFFFFF' | Location marker glyph color | | locationMarkerScale | number | 1.2 | Location marker size scale | | locationCircleOptions | object | - | Custom circle options (fillColor, strokeColor, etc.) | | language | string | 'en' | UI language code | | geolocationButtonLabel | string | - | Custom geolocation button text | | geolocationErrorTitle | string | - | Custom error title text | | geolocation* | string | - | See Translation Overrides | | minZoom | number | 2 | Minimum zoom level | | maxZoom | number | 21 | Maximum zoom level | | mapTypeControl | boolean | false | Show/hide map type control (satellite/terrain switcher) | | streetViewControl | boolean | false | Show/hide street view control |

Events:

Native Google Maps events (keep original names):

  • click, dblclick, drag, dragend, dragstart, idle, mousemove, mouseout, mouseover

Standardized custom events (kebab-case with gmap- prefix):

  • gmap-ready - Map is initialized and ready
  • gmap-center-changed - Map center has changed
  • gmap-zoom-changed - Map zoom level has changed
  • gmap-bounds-changed - Map bounds have changed
  • gmap-geolocation-success - Geolocation successful
  • gmap-geolocation-error - Geolocation error
  • gmap-geolocation-loading - Geolocation in progress
  • gmap-location-changed - Unified event for both initial location and marker drag (recommended)
  • gmap-location-marker-dragend - User dragged the location marker (specific event)

Methods:

  • panBy(x, y) - Pan map by pixels
  • panTo(latLng) - Pan to coordinates
  • fitBounds(bounds) - Fit map to bounds
  • resize() - Trigger map resize
  • getCurrentLocation() - Get user's location via browser geolocation
  • setLocation(lat, lng, accuracy?, panTo?) - Programmatically set location marker

UI Controls:

By default, the map has a clean minimal UI with only zoom controls visible. The map type control (satellite/terrain switcher) and street view controls are hidden by default for a cleaner interface.

To enable them:

<!-- Show map type control (satellite/terrain) -->
<gmap-map map-type-control></gmap-map>

<!-- Show street view control -->
<gmap-map street-view-control></gmap-map>

<!-- Show all controls -->
<gmap-map map-type-control street-view-control></gmap-map>

<gmap-marker> - Advanced Marker

Modern marker using Google Maps AdvancedMarkerElement API.

Important: Requires mapId to be set on the parent <gmap-map>.

Properties:

| Property | Type | Default | Description | |----------|------|---------|-------------| | position | {lat, lng} | Required | Marker position | | title | string | - | Hover tooltip | | gmpDraggable | boolean | false | Enable dragging | | gmpClickable | boolean | true | Enable clicking | | background | string | - | Pin background color | | borderColor | string | - | Pin border color | | glyphColor | string | - | Pin icon color | | scale | number | 1 | Pin size multiplier | | icon | string | - | Custom icon URL (legacy) |

Events:

Native Google Maps events:

  • click, drag, dragstart, dragend

Custom events (with gmap- prefix):

  • gmap-marker-ready - Marker is initialized and ready
  • gmap-position-changed - Marker position has changed (e.g., after drag)

<gmap-info-window> - Info Window

Popup windows that display content on the map.

Properties:

| Property | Type | Default | Description | |----------|------|---------|-------------| | opened | boolean | true | Window visibility | | position | {lat, lng} | - | Position (for standalone windows) | | zIndex | number | - | Stacking order |

Usage:

<!-- Attached to marker -->
<gmap-marker position='{"lat": 24.7136, "lng": 46.6753}'>
  <gmap-info-window opened>
    <div>Content here</div>
  </gmap-info-window>
</gmap-marker>

<!-- Standalone -->
<gmap-info-window position='{"lat": 24.7136, "lng": 46.6753}' opened>
  <div>Floating content</div>
</gmap-info-window>

Shape Components

<gmap-polyline> - Connected Lines

| Property | Type | Description | |----------|------|-------------| | path | Array<{lat, lng}> | Array of coordinates | | editable | boolean | Allow editing | | draggable | boolean | Allow dragging | | options | object | Polyline options (strokeColor, etc.) |

Events:

  • gmap-path-changed - Path has been modified

<gmap-polygon> - Closed Shape

| Property | Type | Description | |----------|------|-------------| | path | Array<{lat, lng}> | Single polygon path | | paths | Array<Array<{lat, lng}>> | Multiple paths (with holes) | | editable | boolean | Allow editing | | draggable | boolean | Allow dragging | | options | object | Polygon options (fillColor, etc.) |

Events:

  • gmap-path-changed - Path has been modified (single path)
  • gmap-paths-changed - Paths have been modified (multiple paths with holes)

<gmap-circle> - Circular Overlay

| Property | Type | Description | |----------|------|-------------| | center | {lat, lng} | Circle center | | radius | number | Radius in meters | | editable | boolean | Allow resize/move | | draggable | boolean | Allow dragging | | options | object | Circle options |

<gmap-rectangle> - Rectangular Overlay

| Property | Type | Description | |----------|------|-------------| | bounds | {north, south, east, west} | Rectangle bounds | | editable | boolean | Allow resize/move | | draggable | boolean | Allow dragging | | options | object | Rectangle options |

<gmap-cluster> - Marker Clustering

Groups nearby markers into clusters for better performance.

Requirements: Install @googlemaps/markerclusterer

<gmap-cluster grid-size="60">
  <gmap-marker position='{"lat": 24.71, "lng": 46.67}'></gmap-marker>
  <gmap-marker position='{"lat": 24.72, "lng": 46.68}'></gmap-marker>
  <!-- More markers -->
</gmap-cluster>

<gmap-street-view-panorama> - Street View

Display Google Street View panorama.

| Property | Type | Description | |----------|------|-------------| | position | {lat, lng} | Panorama location | | pano | string | Specific panorama ID | | zoom | number | Zoom level (0-5) | | pov | {heading, pitch} | Point of view |

Event Naming Convention

All custom events follow a standardized naming convention for consistency:

  • Native Google Maps events: Keep their original names (click, dblclick, drag, etc.)
  • Custom events: Use kebab-case with gmap- prefix (gmap-ready, gmap-center-changed, etc.)

This ensures:

  • ✅ Clear distinction between native and custom events
  • ✅ No naming conflicts with other libraries
  • ✅ Consistent, professional naming across all components
  • ✅ Better compatibility with HTML attributes
// Native Google Maps events (no prefix)
map.addEventListener('click', (e) => { ... });
map.addEventListener('dragend', (e) => { ... });

// Custom events (gmap- prefix, kebab-case)
map.addEventListener('gmap-ready', (e) => { ... });
map.addEventListener('gmap-center-changed', (e) => { ... });
map.addEventListener('gmap-geolocation-success', (e) => { ... });

Geolocation

The map component includes a built-in geolocation feature with smart error handling and a draggable marker.

Basic Usage

<!-- With marker (default) -->
<gmap-map
  enable-geolocation
  map-id="YOUR_MAP_ID"
  language="ar"
  geolocation-button-label="استخدم موقعي"
>
</gmap-map>

<!-- Without marker (just get coordinates) -->
<gmap-map
  enable-geolocation
  show-location-marker="false"
>
</gmap-map>

Initial Location Marker

Set an initial location marker when the map loads:

<gmap-map
  map-id="YOUR_MAP_ID"
  location-marker-position='{"lat": 24.7136, "lng": 46.6753, "accuracy": 50}'
>
</gmap-map>

Customize Marker Style

Customize the location marker colors and size:

<gmap-map
  enable-geolocation
  map-id="YOUR_MAP_ID"
  location-marker-background="#EA4335"
  location-marker-border-color="#C5221F"
  location-marker-glyph-color="#FFFFFF"
  location-marker-scale="1.5"
>
</gmap-map>

Programmatic Location Setting

Set the location marker programmatically using JavaScript:

const map = document.querySelector('gmap-map');

// Wait for map to be ready
map.addEventListener('gmap-ready', () => {
  // Set location marker (with pan)
  map.setLocation(24.7136, 46.6753, 100);
  
  // Set location without panning
  map.setLocation(24.7136, 46.6753, 100, false);
});

// Update location dynamically (e.g., from a form or API)
function updateLocation(lat, lng) {
  map.setLocation(lat, lng, 50);
}

Features:

  • 📍 Optional draggable marker - users can adjust their location by dragging
  • 🎯 Accuracy circle that follows the marker
  • 🔔 Unified gmap-location-changed event for simplified DX
  • ⚙️ Control marker visibility with show-location-marker property
  • 🎨 Fully customizable marker colors and style
  • 🚀 Programmatic location setting via setLocation() method
  • 📌 Initial location support via location-marker-position property

Events:

// Recommended: Use the unified event for simplified DX
map.addEventListener('gmap-location-changed', (e) => {
  const { position, accuracy, source } = e.detail;
  console.log('Location:', position); // { lat, lng }
  console.log('Accuracy:', accuracy); // meters
  console.log('Source:', source); // 'geolocation', 'marker-drag', or 'programmatic'
  
  // Handle all location changes with one event!
  // Sources:
  // - 'geolocation': Browser geolocation API
  // - 'marker-drag': User dragged the marker
  // - 'programmatic': Set via setLocation() method
  
  // Perfect for updating forms or triggering geocoding
});

// Alternative: Listen to specific events
map.addEventListener('gmap-geolocation-success', (e) => {
  console.log('Location:', e.detail.position);
  console.log('Accuracy:', e.detail.accuracy);
});

map.addEventListener('gmap-geolocation-error', (e) => {
  console.error('Error:', e.detail.code, e.detail.message);
});

map.addEventListener('gmap-geolocation-loading', (e) => {
  console.log('Getting location...', e.detail.message);
});

// Specific event for marker drag (if you need to distinguish)
map.addEventListener('gmap-location-marker-dragend', (e) => {
  console.log('Marker dragged to:', e.detail.position);
  console.log('Accuracy:', e.detail.accuracy);
});

Translations

Built-in support for 14 languages:

  • English (en)
  • Arabic (ar) - RTL
  • Spanish (es)
  • French (fr)
  • German (de)
  • Chinese (zh)
  • Japanese (ja)
  • Portuguese (pt)
  • Russian (ru)
  • Italian (it)
  • Dutch (nl)
  • Turkish (tr)
  • Korean (ko)
  • Hindi (hi)
<gmap-map language="ar"></gmap-map>

Override translations:

<gmap-map
  language="en"
  geolocation-button-label="Find Me"
  geolocation-loading-title="Finding your location..."
  geolocation-error-title="Location Error"
  geolocation-error-button-text="OK"
  geolocation-click-to-select-message="You can also click on the map to select a location"
  geolocation-permission-denied-message="Please allow location access in your browser settings"
  geolocation-position-unavailable-message="Unable to determine your location"
  geolocation-timeout-message="Location request timed out"
  geolocation-general-error-message="An error occurred while getting your location"
>
</gmap-map>

All Available Geolocation Override Attributes:

| Attribute | Purpose | Default (English) | |-----------|---------|-------------------| | geolocation-button-label | Button text | "" (icon only) | | geolocation-loading-title | Loading overlay title | "Getting Your Location" | | geolocation-loading-instructions | Loading overlay instructions | "Please allow location access..." | | geolocation-error-title | Error overlay title | "Location Error" | | geolocation-error-button-text | Error close button text | "Continue" | | geolocation-error-timer-message | Error auto-hide message | "This message will auto-hide..." | | geolocation-click-to-select-message | Hint in error overlay | "You can click on the map..." | | geolocation-permission-denied-message | Permission denied error | "Location permission denied..." | | geolocation-position-unavailable-message | Position unavailable error | "Your location is unavailable..." | | geolocation-timeout-message | Timeout error | "Location request timed out..." | | geolocation-general-error-message | General error fallback | "Unable to get your location..." |

Framework Integration

React

import '@salla.sa/ui-google-map-render';
import { load } from '@salla.sa/ui-google-map-render';

// Load API once
load({ key: 'YOUR_API_KEY', mapIds: ['YOUR_MAP_ID'] });

function MapComponent() {
  const handleCenterChange = (e) => {
    console.log('Center:', e.detail);
  };

  return (
    <gmap-map
      center={{ lat: 24.7136, lng: 46.6753 }}
      zoom={12}
      onCenter_changed={handleCenterChange}
    >
      <gmap-marker position={{ lat: 24.7136, lng: 46.6753 }} />
    </gmap-map>
  );
}

Vue

<template>
  <gmap-map
    :center="center"
    :zoom="12"
    @center_changed="handleCenterChange"
  >
    <gmap-marker :position="center" />
  </gmap-map>
</template>

<script setup>
import '@salla.sa/ui-google-map-render';
import { load } from '@salla.sa/ui-google-map-render';
import { ref } from 'vue';

load({ key: 'YOUR_API_KEY', mapIds: ['YOUR_MAP_ID'] });

const center = ref({ lat: 24.7136, lng: 46.6753 });

const handleCenterChange = (e) => {
  console.log('Center:', e.detail);
};
</script>

Angular

import '@salla.sa/ui-google-map-render';
import { load } from '@salla.sa/ui-google-map-render';

// In app module or component
load({ key: 'YOUR_API_KEY', mapIds: ['YOUR_MAP_ID'] });
<gmap-map
  [center]="center"
  [zoom]="12"
  (center_changed)="handleCenterChange($event)"
>
  <gmap-marker [position]="center"></gmap-marker>
</gmap-map>

Performance & Bundle Size

Runtime Library Loading

All Google Maps libraries are loaded dynamically at runtime:

// These are loaded from Google CDN when needed, NOT bundled:
// - marker library (AdvancedMarkerElement, PinElement)
// - places library (if you add autocomplete features)
// - Any other Google Maps libraries

// Example: Marker library is automatically loaded when first marker is created

What's in the Bundle?

  • ✅ Component logic (~50KB)
  • ✅ Lit framework (~50KB)
  • ✅ Translation strings for 14 languages (~10KB)
  • ✅ TypeScript types (0KB at runtime)

Total: ~17KB gzipped

What's NOT in the Bundle?

  • ❌ Google Maps API (loaded from CDN)
  • ❌ Marker library (loaded at runtime)
  • ❌ Clustering library (optional peer dependency)
  • ❌ Any Google Maps code

Best Practices

1. API Key Security

Restrict your API key by HTTP referrer in Google Cloud Console:

https://yourdomain.com/*

2. Map ID Setup

Create a Map ID in Google Cloud Console for AdvancedMarkerElement: https://console.cloud.google.com/google/maps-apis/studio/maps

3. Version Pinning

Use quarterly version for production stability:

load({
  key: 'YOUR_API_KEY',
  version: 'quarterly', // Recommended for production
});

4. Lazy Loading

Load the map API only when needed:

// Load API when user interacts
button.addEventListener('click', async () => {
  await import('@salla.sa/ui-google-map-render');
  load({ key: 'YOUR_API_KEY' });
});

5. Performance

  • Use clustering for >50 markers
  • Limit the number of info windows open simultaneously
  • Use appropriate zoom levels for your use case

TypeScript

Full TypeScript support included:

import type {
  LoadOptions,
  GeolocationResult,
  GeolocationError,
} from '@salla.sa/ui-google-map-render';

const options: LoadOptions = {
  key: 'YOUR_API_KEY',
  version: 'quarterly',
  libraries: ['marker'],
  mapIds: ['YOUR_MAP_ID'],
};

Browser Support

  • Chrome 90+
  • Firefox 88+
  • Safari 14+
  • Edge 90+

Requires ES2020 support and Web Components v1.

Documentation

License

MIT

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

Support

For issues and questions:

  • GitHub Issues: [Link to repo]
  • Documentation: [Link to docs]

Why This Library?

  1. Smallest Bundle: At ~17KB gzipped, we're 50-75% smaller than alternatives
  2. Runtime Loading: Google Maps loaded from CDN, not bundled
  3. Modern Standards: Built with Web Components, works everywhere
  4. Zero Lock-in: Pure web components, use with any framework
  5. Production Ready: Based on battle-tested vue2-google-maps design

Acknowledgments

Built with Lit - Simple. Fast. Web Components.

Based on the feature set of vue2-google-maps but completely rewritten for modern web standards with a focus on bundle size and performance.