maplibre-gl-components 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +283 -4
  2. package/dist/{Terrain-1bxohZJX.cjs → InspectControl-BLalXkaR.cjs} +2254 -11
  3. package/dist/InspectControl-BLalXkaR.cjs.map +1 -0
  4. package/dist/{Terrain-BbC-hVIs.js → InspectControl-DXc8bOjy.js} +2239 -17
  5. package/dist/InspectControl-DXc8bOjy.js.map +1 -0
  6. package/dist/index.cjs +48 -45
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.mjs +10 -7
  9. package/dist/maplibre-gl-components.css +447 -0
  10. package/dist/react.cjs +530 -21
  11. package/dist/react.cjs.map +1 -1
  12. package/dist/react.mjs +526 -17
  13. package/dist/react.mjs.map +1 -1
  14. package/dist/types/index.d.ts +4 -1
  15. package/dist/types/index.d.ts.map +1 -1
  16. package/dist/types/lib/core/InspectControl.d.ts +202 -0
  17. package/dist/types/lib/core/InspectControl.d.ts.map +1 -0
  18. package/dist/types/lib/core/InspectControlReact.d.ts +32 -0
  19. package/dist/types/lib/core/InspectControlReact.d.ts.map +1 -0
  20. package/dist/types/lib/core/SearchControl.d.ts +172 -0
  21. package/dist/types/lib/core/SearchControl.d.ts.map +1 -0
  22. package/dist/types/lib/core/SearchControlReact.d.ts +32 -0
  23. package/dist/types/lib/core/SearchControlReact.d.ts.map +1 -0
  24. package/dist/types/lib/core/VectorDataset.d.ts +197 -0
  25. package/dist/types/lib/core/VectorDataset.d.ts.map +1 -0
  26. package/dist/types/lib/core/VectorDatasetReact.d.ts +31 -0
  27. package/dist/types/lib/core/VectorDatasetReact.d.ts.map +1 -0
  28. package/dist/types/lib/core/types.d.ts +355 -0
  29. package/dist/types/lib/core/types.d.ts.map +1 -1
  30. package/dist/types/lib/hooks/index.d.ts +3 -0
  31. package/dist/types/lib/hooks/index.d.ts.map +1 -1
  32. package/dist/types/lib/hooks/useInspectControl.d.ts +49 -0
  33. package/dist/types/lib/hooks/useInspectControl.d.ts.map +1 -0
  34. package/dist/types/lib/hooks/useSearchControl.d.ts +43 -0
  35. package/dist/types/lib/hooks/useSearchControl.d.ts.map +1 -0
  36. package/dist/types/lib/hooks/useVectorDataset.d.ts +35 -0
  37. package/dist/types/lib/hooks/useVectorDataset.d.ts.map +1 -0
  38. package/dist/types/react.d.ts +5 -2
  39. package/dist/types/react.d.ts.map +1 -1
  40. package/package.json +4 -1
  41. package/dist/Terrain-1bxohZJX.cjs.map +0 -1
  42. package/dist/Terrain-BbC-hVIs.js.map +0 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # maplibre-gl-components
2
2
 
3
- Legend, colorbar, basemap switcher, terrain toggle, and HTML control components for MapLibre GL JS maps.
3
+ Legend, colorbar, basemap switcher, terrain toggle, search, vector data loader, feature inspector, and HTML control components for MapLibre GL JS maps.
4
4
 
5
5
  [![npm version](https://badge.fury.io/js/maplibre-gl-components.svg)](https://badge.fury.io/js/maplibre-gl-components)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
@@ -11,6 +11,9 @@ Legend, colorbar, basemap switcher, terrain toggle, and HTML control components
11
11
  - **Legend** - Categorical legends with color swatches and labels
12
12
  - **BasemapControl** - Interactive basemap switcher with 100+ providers from xyzservices
13
13
  - **TerrainControl** - Toggle 3D terrain on/off using free AWS Terrarium elevation tiles
14
+ - **SearchControl** - Collapsible place search with geocoding and fly-to functionality
15
+ - **VectorDatasetControl** - Load GeoJSON files via file upload or drag-and-drop
16
+ - **InspectControl** - Click on features to view their properties/attributes
14
17
  - **HtmlControl** - Flexible HTML content control for custom info panels
15
18
  - **Zoom-based Visibility** - Show/hide components at specific zoom levels with `minzoom`/`maxzoom`
16
19
  - **React Support** - First-class React components and hooks
@@ -29,7 +32,7 @@ npm install maplibre-gl-components
29
32
 
30
33
  ```typescript
31
34
  import maplibregl from 'maplibre-gl';
32
- import { Colorbar, Legend, HtmlControl, BasemapControl, TerrainControl } from 'maplibre-gl-components';
35
+ import { Colorbar, Legend, HtmlControl, BasemapControl, TerrainControl, SearchControl, VectorDatasetControl } from 'maplibre-gl-components';
33
36
  import 'maplibre-gl-components/style.css';
34
37
 
35
38
  const map = new maplibregl.Map({
@@ -46,6 +49,24 @@ const terrainControl = new TerrainControl({
46
49
  });
47
50
  map.addControl(terrainControl, 'top-right');
48
51
 
52
+ // Add a search control
53
+ const searchControl = new SearchControl({
54
+ placeholder: 'Search for a place...',
55
+ flyToZoom: 14,
56
+ showMarker: true,
57
+ });
58
+ map.addControl(searchControl, 'top-right');
59
+
60
+ // Add a vector dataset loader (file upload and drag-drop)
61
+ const vectorControl = new VectorDatasetControl({
62
+ fitBounds: true,
63
+ });
64
+ map.addControl(vectorControl, 'top-left');
65
+
66
+ vectorControl.on('load', (event) => {
67
+ console.log('Loaded:', event.dataset?.filename);
68
+ });
69
+
49
70
  // Add a basemap switcher
50
71
  const basemapControl = new BasemapControl({
51
72
  defaultBasemap: 'OpenStreetMap.Mapnik',
@@ -92,7 +113,7 @@ htmlControl.setHtml('<div><strong>Stats:</strong> 5,678 features</div>');
92
113
  ```tsx
93
114
  import { useState, useEffect, useRef } from 'react';
94
115
  import maplibregl from 'maplibre-gl';
95
- import { ColorbarReact, LegendReact, HtmlControlReact, BasemapReact, TerrainReact } from 'maplibre-gl-components/react';
116
+ import { ColorbarReact, LegendReact, HtmlControlReact, BasemapReact, TerrainReact, SearchControlReact, VectorDatasetReact } from 'maplibre-gl-components/react';
96
117
  import 'maplibre-gl-components/style.css';
97
118
 
98
119
  function MyMap() {
@@ -121,6 +142,22 @@ function MyMap() {
121
142
 
122
143
  {map && (
123
144
  <>
145
+ <VectorDatasetReact
146
+ map={map}
147
+ fitBounds
148
+ position="top-left"
149
+ onDatasetLoad={(dataset) => console.log('Loaded:', dataset.filename)}
150
+ />
151
+
152
+ <SearchControlReact
153
+ map={map}
154
+ placeholder="Search for a place..."
155
+ flyToZoom={14}
156
+ showMarker
157
+ position="top-right"
158
+ onResultSelect={(result) => console.log('Selected:', result.name)}
159
+ />
160
+
124
161
  <TerrainReact
125
162
  map={map}
126
163
  exaggeration={1.5}
@@ -344,6 +381,147 @@ basemapControl.on('basemapchange', handler) // Listen for basemap changes
344
381
  - Thunderforest, MapBox, MapTiler (require API keys)
345
382
  - NASAGIBS, OpenSeaMap, and 20+ more
346
383
 
384
+ ### SearchControl
385
+
386
+ A collapsible place search control with geocoding support.
387
+
388
+ ```typescript
389
+ interface SearchControlOptions {
390
+ position?: ControlPosition;
391
+ visible?: boolean; // Default: true
392
+ collapsed?: boolean; // Start collapsed (icon only). Default: true
393
+ placeholder?: string; // Search input placeholder. Default: 'Search places...'
394
+ geocoderUrl?: string; // Geocoding API URL. Default: Nominatim
395
+ maxResults?: number; // Max results to show. Default: 5
396
+ debounceMs?: number; // Debounce delay in ms. Default: 300
397
+ flyToZoom?: number; // Zoom level when selecting result. Default: 14
398
+ showMarker?: boolean; // Show marker at selected location. Default: true
399
+ markerColor?: string; // Marker color. Default: '#4264fb'
400
+ collapseOnSelect?: boolean; // Collapse after selecting. Default: true
401
+ clearOnSelect?: boolean; // Clear results after selecting. Default: true
402
+ geocoder?: (query: string) => Promise<SearchResult[]>; // Custom geocoder function
403
+ backgroundColor?: string;
404
+ borderRadius?: number;
405
+ opacity?: number;
406
+ width?: number; // Expanded width in pixels. Default: 280
407
+ fontSize?: number;
408
+ fontColor?: string;
409
+ minzoom?: number;
410
+ maxzoom?: number;
411
+ }
412
+
413
+ interface SearchResult {
414
+ id: string; // Unique identifier
415
+ name: string; // Place name
416
+ displayName: string; // Full display name with address
417
+ lng: number; // Longitude
418
+ lat: number; // Latitude
419
+ bbox?: [number, number, number, number]; // Bounding box [west, south, east, north]
420
+ type?: string; // Place type (city, street, etc.)
421
+ importance?: number; // Relevance score
422
+ }
423
+
424
+ // Methods
425
+ searchControl.show()
426
+ searchControl.hide()
427
+ searchControl.expand() // Expand to show input
428
+ searchControl.collapse() // Collapse to icon only
429
+ searchControl.toggle() // Toggle expanded/collapsed
430
+ searchControl.search(query) // Perform a search
431
+ searchControl.selectResult(result) // Select a result and fly to it
432
+ searchControl.clear() // Clear search and marker
433
+ searchControl.update(options)
434
+ searchControl.getState()
435
+ searchControl.on('resultselect', handler) // Listen for result selection
436
+ searchControl.on('search', handler) // Listen for search completion
437
+ searchControl.on('clear', handler) // Listen for clear events
438
+ ```
439
+
440
+ **Geocoding:**
441
+ By default, SearchControl uses [Nominatim](https://nominatim.openstreetmap.org/) (OpenStreetMap) for geocoding, which is free and requires no API key. You can also provide a custom geocoder function for other services.
442
+
443
+ ```typescript
444
+ // Using custom geocoder
445
+ const searchControl = new SearchControl({
446
+ geocoder: async (query) => {
447
+ const response = await fetch(`https://my-geocoder.com/search?q=${query}`);
448
+ const data = await response.json();
449
+ return data.map(item => ({
450
+ id: item.id,
451
+ name: item.name,
452
+ displayName: item.address,
453
+ lng: item.longitude,
454
+ lat: item.latitude,
455
+ }));
456
+ },
457
+ });
458
+ ```
459
+
460
+ ### VectorDatasetControl
461
+
462
+ A control for loading GeoJSON files via file upload button or drag-and-drop.
463
+
464
+ ```typescript
465
+ interface VectorDatasetControlOptions {
466
+ position?: ControlPosition;
467
+ visible?: boolean; // Default: true
468
+ showDropZone?: boolean; // Show overlay when dragging. Default: true
469
+ acceptedExtensions?: string[]; // File extensions. Default: ['.geojson', '.json']
470
+ multiple?: boolean; // Allow multiple files. Default: true
471
+ defaultStyle?: VectorLayerStyle; // Default styling for loaded layers
472
+ fitBounds?: boolean; // Fit map to loaded data. Default: true
473
+ fitBoundsPadding?: number; // Padding for fitBounds. Default: 50
474
+ maxFileSize?: number; // Max file size in bytes. Default: 50MB
475
+ backgroundColor?: string;
476
+ borderRadius?: number;
477
+ opacity?: number;
478
+ minzoom?: number;
479
+ maxzoom?: number;
480
+ }
481
+
482
+ interface VectorLayerStyle {
483
+ fillColor?: string; // Polygon fill. Default: '#3388ff'
484
+ fillOpacity?: number; // Polygon fill opacity. Default: 0.3
485
+ strokeColor?: string; // Line/outline color. Default: '#3388ff'
486
+ strokeWidth?: number; // Line width. Default: 2
487
+ strokeOpacity?: number; // Line opacity. Default: 1
488
+ circleRadius?: number; // Point radius. Default: 6
489
+ circleColor?: string; // Point color. Default: '#3388ff'
490
+ circleStrokeColor?: string; // Point outline. Default: '#ffffff'
491
+ circleStrokeWidth?: number; // Point outline width. Default: 2
492
+ }
493
+
494
+ interface LoadedDataset {
495
+ id: string; // Unique ID
496
+ filename: string; // Original filename
497
+ sourceId: string; // MapLibre source ID
498
+ layerIds: string[]; // MapLibre layer IDs
499
+ featureCount: number; // Number of features
500
+ geometryTypes: string[]; // Geometry types present
501
+ loadedAt: Date; // When loaded
502
+ }
503
+
504
+ // Methods
505
+ vectorControl.show()
506
+ vectorControl.hide()
507
+ vectorControl.getLoadedDatasets() // Get all loaded datasets
508
+ vectorControl.removeDataset(id) // Remove a dataset by ID
509
+ vectorControl.removeAllDatasets() // Remove all datasets
510
+ vectorControl.loadGeoJSON(geojson, filename) // Programmatically load GeoJSON
511
+ vectorControl.update(options)
512
+ vectorControl.getState()
513
+ vectorControl.on('load', handler) // Fired when a dataset is loaded
514
+ vectorControl.on('error', handler) // Fired when an error occurs
515
+ ```
516
+
517
+ **Loading Methods:**
518
+ - Click the upload button to open a file picker
519
+ - Drag and drop GeoJSON files directly onto the map
520
+
521
+ **Supported Formats:**
522
+ - GeoJSON (.geojson, .json)
523
+ - FeatureCollection, Feature, or raw Geometry objects
524
+
347
525
  ### TerrainControl
348
526
 
349
527
  A toggle control for 3D terrain rendering using free AWS Terrarium elevation tiles.
@@ -388,6 +566,78 @@ The control uses free terrain tiles from AWS:
388
566
  - Encoding: Terrarium RGB-encoded elevation data
389
567
  - No API key required
390
568
 
569
+ ### InspectControl
570
+
571
+ A control for inspecting vector features on the map. Click on features to view their properties/attributes in a popup.
572
+
573
+ ```typescript
574
+ interface InspectControlOptions {
575
+ position?: ControlPosition;
576
+ visible?: boolean; // Default: true
577
+ enabled?: boolean; // Start with inspect mode on. Default: false
578
+ maxFeatures?: number; // Max features at click point. Default: 10
579
+ includeLayers?: string[]; // Only inspect these layers
580
+ excludeLayers?: string[]; // Skip these layers
581
+ highlightStyle?: InspectHighlightStyle; // Style for selected feature
582
+ excludeProperties?: string[]; // Properties to hide (e.g., internal IDs)
583
+ showGeometryType?: boolean; // Show geometry type badge. Default: true
584
+ showLayerName?: boolean; // Show layer name. Default: true
585
+ maxWidth?: number; // Popup max width. Default: 320
586
+ maxHeight?: number; // Popup content max height. Default: 300
587
+ backgroundColor?: string;
588
+ borderRadius?: number;
589
+ opacity?: number;
590
+ fontSize?: number;
591
+ fontColor?: string;
592
+ minzoom?: number;
593
+ maxzoom?: number;
594
+ }
595
+
596
+ interface InspectHighlightStyle {
597
+ fillColor?: string; // Polygon fill. Default: '#ffff00'
598
+ fillOpacity?: number; // Polygon fill opacity. Default: 0.3
599
+ strokeColor?: string; // Line/outline color. Default: '#ffff00'
600
+ strokeWidth?: number; // Line width. Default: 3
601
+ circleRadius?: number; // Point radius. Default: 10
602
+ circleStrokeWidth?: number; // Point outline. Default: 3
603
+ }
604
+
605
+ interface InspectedFeature {
606
+ id: string; // Unique inspection ID
607
+ feature: GeoJSON.Feature; // The GeoJSON feature
608
+ layerId: string; // MapLibre layer ID
609
+ sourceId: string; // MapLibre source ID
610
+ lngLat: [number, number]; // Click coordinates
611
+ }
612
+
613
+ // Methods
614
+ inspectControl.show()
615
+ inspectControl.hide()
616
+ inspectControl.enable() // Enable inspect mode
617
+ inspectControl.disable() // Disable inspect mode
618
+ inspectControl.toggle() // Toggle inspect mode on/off
619
+ inspectControl.isEnabled() // Check if inspect mode is enabled
620
+ inspectControl.clear() // Clear current inspection
621
+ inspectControl.getInspectedFeatures() // Get all features at click point
622
+ inspectControl.getSelectedFeature() // Get currently selected feature
623
+ inspectControl.selectFeature(index) // Select feature by index
624
+ inspectControl.nextFeature() // Navigate to next feature
625
+ inspectControl.previousFeature() // Navigate to previous feature
626
+ inspectControl.update(options)
627
+ inspectControl.getState()
628
+ inspectControl.on('enable', handler) // Fired when inspect mode is enabled
629
+ inspectControl.on('disable', handler) // Fired when inspect mode is disabled
630
+ inspectControl.on('featureselect', handler) // Fired when a feature is selected
631
+ inspectControl.on('clear', handler) // Fired when inspection is cleared
632
+ ```
633
+
634
+ **Usage:**
635
+ 1. Click the info button to enable inspect mode
636
+ 2. Click on any vector feature on the map
637
+ 3. View properties in the popup
638
+ 4. Use < > buttons to navigate when multiple features are at the same location
639
+ 5. Click elsewhere or the button again to disable
640
+
391
641
  ## Built-in Colormaps
392
642
 
393
643
  ### Sequential
@@ -493,7 +743,7 @@ const colorbar = new Colorbar({
493
743
  ## React Hooks
494
744
 
495
745
  ```typescript
496
- import { useColorbar, useLegend, useHtmlControl, useBasemap, useTerrain } from 'maplibre-gl-components/react';
746
+ import { useColorbar, useLegend, useHtmlControl, useBasemap, useTerrain, useSearchControl, useVectorDataset } from 'maplibre-gl-components/react';
497
747
 
498
748
  function MyComponent() {
499
749
  const colorbar = useColorbar({ colormap: 'viridis', vmin: 0, vmax: 100 });
@@ -501,6 +751,8 @@ function MyComponent() {
501
751
  const htmlControl = useHtmlControl({ html: '...' });
502
752
  const basemap = useBasemap({ selectedBasemap: 'OpenStreetMap.Mapnik' });
503
753
  const terrain = useTerrain({ enabled: false, exaggeration: 1.5 });
754
+ const search = useSearchControl({ collapsed: true });
755
+ const vectorDataset = useVectorDataset();
504
756
 
505
757
  return (
506
758
  <>
@@ -516,6 +768,15 @@ function MyComponent() {
516
768
  <button onClick={() => terrain.toggle()}>
517
769
  Toggle Terrain
518
770
  </button>
771
+ <button onClick={() => search.toggle()}>
772
+ Toggle Search
773
+ </button>
774
+
775
+ <SearchControlReact
776
+ map={map}
777
+ collapsed={search.state.collapsed}
778
+ onResultSelect={(result) => search.selectResult(result)}
779
+ />
519
780
 
520
781
  <TerrainReact
521
782
  map={map}
@@ -572,6 +833,24 @@ The default styles can be customized using CSS:
572
833
  .maplibre-gl-terrain-button {
573
834
  color: #0078d7;
574
835
  }
836
+
837
+ /* Override search control styles */
838
+ .maplibre-gl-search {
839
+ background: rgba(255, 255, 255, 0.95);
840
+ }
841
+
842
+ .maplibre-gl-search-toggle:hover {
843
+ color: #0078d7;
844
+ }
845
+
846
+ /* Override vector dataset control styles */
847
+ .maplibre-gl-vector-dataset-button:hover {
848
+ color: #0078d7;
849
+ }
850
+
851
+ .maplibre-gl-vector-dataset-dropzone {
852
+ background: rgba(0, 120, 215, 0.2);
853
+ }
575
854
  ```
576
855
 
577
856
  ## Examples