maplibre-gl-plugin-template
v0.2.2
Published
A template for creating MapLibre GL JS plugins with TypeScript and React support
Downloads
347
Maintainers
Readme
MapLibre GL Plugin Template
A template for creating MapLibre GL JS plugins with TypeScript and React support.
Features
- TypeScript Support - Full TypeScript support with type definitions
- React Integration - React wrapper component and custom hooks
- IControl Implementation - Implements MapLibre's IControl interface
- Modern Build Setup - Vite-based build with dual ESM/CJS output
- Testing - Vitest setup with React Testing Library
- CI/CD Ready - GitHub Actions for npm publishing and GitHub Pages
Installation
npm install maplibre-gl-plugin-templateQuick Start
Vanilla JavaScript/TypeScript
import maplibregl from 'maplibre-gl';
import { PluginControl } from 'maplibre-gl-plugin-template';
import 'maplibre-gl-plugin-template/style.css';
const map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json',
center: [0, 0],
zoom: 2,
});
map.on('load', () => {
const control = new PluginControl({
title: 'My Plugin',
collapsed: false,
panelWidth: 300,
});
map.addControl(control, 'top-right');
});React
import { useEffect, useRef, useState } from 'react';
import maplibregl, { Map } from 'maplibre-gl';
import { PluginControlReact, usePluginState } from 'maplibre-gl-plugin-template/react';
import 'maplibre-gl-plugin-template/style.css';
function App() {
const mapContainer = useRef<HTMLDivElement>(null);
const [map, setMap] = useState<Map | null>(null);
const { state, toggle } = usePluginState();
useEffect(() => {
if (!mapContainer.current) return;
const mapInstance = new maplibregl.Map({
container: mapContainer.current,
style: 'https://demotiles.maplibre.org/style.json',
center: [0, 0],
zoom: 2,
});
mapInstance.on('load', () => setMap(mapInstance));
return () => mapInstance.remove();
}, []);
return (
<div style={{ width: '100%', height: '100vh' }}>
<div ref={mapContainer} style={{ width: '100%', height: '100%' }} />
{map && (
<PluginControlReact
map={map}
title="My Plugin"
collapsed={state.collapsed}
onStateChange={(newState) => console.log(newState)}
/>
)}
</div>
);
}API
PluginControl
The main control class implementing MapLibre's IControl interface.
Constructor Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| collapsed | boolean | true | Whether the panel starts collapsed (showing only the 29x29 toggle button) |
| position | string | 'top-right' | Control position on the map |
| title | string | 'Plugin Control' | Title displayed in the header |
| panelWidth | number | 300 | Width of the dropdown panel in pixels |
| className | string | '' | Custom CSS class name |
Methods
toggle()- Toggle the collapsed stateexpand()- Expand the panelcollapse()- Collapse the panelgetState()- Get the current statesetState(state)- Update the stateon(event, handler)- Register an event handleroff(event, handler)- Remove an event handlergetMap()- Get the map instancegetContainer()- Get the container element
Events
collapse- Fired when the panel is collapsedexpand- Fired when the panel is expandedstatechange- Fired when the state changes
PluginControlReact
React wrapper component for PluginControl.
Props
All PluginControl options plus:
| Prop | Type | Description |
|------|------|-------------|
| map | Map | MapLibre GL map instance (required) |
| onStateChange | function | Callback fired when state changes |
usePluginState
Custom React hook for managing plugin state.
const {
state, // Current state
setState, // Update entire state
setCollapsed, // Set collapsed state
setPanelWidth,// Set panel width
setData, // Set custom data
reset, // Reset to initial state
toggle, // Toggle collapsed state
} = usePluginState(initialState);Utilities
The package exports several utility functions:
clamp(value, min, max)- Clamp a value between min and maxformatNumericValue(value, step)- Format a number with appropriate decimalsgenerateId(prefix?)- Generate a unique IDdebounce(fn, delay)- Debounce a functionthrottle(fn, limit)- Throttle a functionclassNames(classes)- Build a class string from an object
Development
Setup
# Clone the repository
git clone https://github.com/your-username/maplibre-gl-plugin-template.git
cd maplibre-gl-plugin-template
# Install dependencies
npm install
# Start development server
npm run devScripts
| Script | Description |
|--------|-------------|
| npm run dev | Start development server |
| npm run build | Build the library |
| npm run build:examples | Build examples for deployment |
| npm run test | Run tests |
| npm run test:ui | Run tests with UI |
| npm run test:coverage | Run tests with coverage |
| npm run lint | Lint the code |
| npm run format | Format the code |
Project Structure
maplibre-gl-plugin-template/
├── src/
│ ├── index.ts # Main entry point
│ ├── react.ts # React entry point
│ ├── index.css # Root styles
│ └── lib/
│ ├── core/ # Core classes and types
│ ├── hooks/ # React hooks
│ ├── utils/ # Utility functions
│ └── styles/ # Component styles
├── tests/ # Test files
├── examples/ # Example applications
│ ├── basic/ # Vanilla JS example
│ └── react/ # React example
└── .github/workflows/ # CI/CD workflowsDocker
The examples can be run using Docker. The image is automatically built and published to GitHub Container Registry.
Pull and Run
# Pull the latest image
docker pull ghcr.io/opengeos/maplibre-gl-plugin-template:latest
# Run the container
docker run -p 8080:80 ghcr.io/opengeos/maplibre-gl-plugin-template:latestThen open http://localhost:8080/maplibre-gl-plugin-template/ in your browser to view the examples.
Build Locally
# Build the image
docker build -t maplibre-gl-plugin-template .
# Run the container
docker run -p 8080:80 maplibre-gl-plugin-templateAvailable Tags
| Tag | Description |
|-----|-------------|
| latest | Latest release |
| x.y.z | Specific version (e.g., 1.0.0) |
| x.y | Minor version (e.g., 1.0) |
Customization
To use this template for your own plugin:
- Clone or fork this repository
- Update
package.jsonwith your plugin name and details - Modify
src/lib/core/PluginControl.tsto implement your plugin logic - Update the styles in
src/lib/styles/plugin-control.css - Add custom utilities, hooks, or components as needed
- Update the README with your plugin's documentation
License
MIT License - see LICENSE for details.
