map-gl-offline 0.1.0-alpha.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.
- package/LICENSE +21 -0
- package/README.md +590 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.esm.js +15863 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +16015 -0
- package/dist/index.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/managers/offlineMapManager/analyticsManagement.d.ts +7 -0
- package/dist/managers/offlineMapManager/base.d.ts +14 -0
- package/dist/managers/offlineMapManager/cleanupManagement.d.ts +16 -0
- package/dist/managers/offlineMapManager/importExportManagement.d.ts +10 -0
- package/dist/managers/offlineMapManager/index.d.ts +72 -0
- package/dist/managers/offlineMapManager/maintenanceManagement.d.ts +13 -0
- package/dist/managers/offlineMapManager/modules.d.ts +10 -0
- package/dist/managers/offlineMapManager/regionManagement.d.ts +11 -0
- package/dist/managers/offlineMapManager/resourceManagement.d.ts +24 -0
- package/dist/managers/offlineMapManager/styleManagement.d.ts +17 -0
- package/dist/managers/offlineMapManager.d.ts +2 -0
- package/dist/services/analyticsService.d.ts +10 -0
- package/dist/services/baseDownloadService.d.ts +96 -0
- package/dist/services/cleanupService.d.ts +34 -0
- package/dist/services/fontService.d.ts +26 -0
- package/dist/services/glyphService.d.ts +58 -0
- package/dist/services/importExportService.d.ts +57 -0
- package/dist/services/maintenanceService.d.ts +15 -0
- package/dist/services/regionService.d.ts +31 -0
- package/dist/services/resourceService.d.ts +42 -0
- package/dist/services/spriteService.d.ts +30 -0
- package/dist/services/styleService.d.ts +73 -0
- package/dist/services/tileService.d.ts +24 -0
- package/dist/storage/indexedDbManager.d.ts +2 -0
- package/dist/style.css +213 -0
- package/dist/types/cleanup.d.ts +49 -0
- package/dist/types/database.d.ts +33 -0
- package/dist/types/font.d.ts +115 -0
- package/dist/types/glyph.d.ts +127 -0
- package/dist/types/import-export.d.ts +96 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/maintenance.d.ts +49 -0
- package/dist/types/progress.d.ts +11 -0
- package/dist/types/region.d.ts +57 -0
- package/dist/types/sprite.d.ts +172 -0
- package/dist/types/style.d.ts +103 -0
- package/dist/types/tile.d.ts +112 -0
- package/dist/types/ui.d.ts +10 -0
- package/dist/ui/ThemeManager.d.ts +23 -0
- package/dist/ui/components/DownloadProgress.d.ts +14 -0
- package/dist/ui/components/PanelActions.d.ts +12 -0
- package/dist/ui/components/PanelHeader.d.ts +15 -0
- package/dist/ui/components/RegionList.d.ts +24 -0
- package/dist/ui/components/shared/BaseComponent.d.ts +86 -0
- package/dist/ui/components/shared/Button.d.ts +45 -0
- package/dist/ui/components/shared/List.d.ts +56 -0
- package/dist/ui/components/shared/MapControlButton.d.ts +37 -0
- package/dist/ui/components/shared/Modal.d.ts +49 -0
- package/dist/ui/components/shared/Panel.d.ts +53 -0
- package/dist/ui/components/shared/PanelContent.d.ts +39 -0
- package/dist/ui/components/shared/RegionDrawingTool.d.ts +54 -0
- package/dist/ui/components/shared/index.d.ts +12 -0
- package/dist/ui/controls/polygonControl.d.ts +83 -0
- package/dist/ui/controls/regionControl.d.ts +71 -0
- package/dist/ui/managers/ControlButtonManager.d.ts +42 -0
- package/dist/ui/managers/PanelManager.d.ts +160 -0
- package/dist/ui/managers/downloadManager.d.ts +63 -0
- package/dist/ui/modals/confirmationModal.d.ts +30 -0
- package/dist/ui/modals/importExportModal.d.ts +46 -0
- package/dist/ui/modals/importExportModal.old.d.ts +27 -0
- package/dist/ui/modals/modalManager.d.ts +23 -0
- package/dist/ui/modals/regionDetailsModal.d.ts +37 -0
- package/dist/ui/modals/regionFormModal.d.ts +86 -0
- package/dist/ui/offlineManagerControl.d.ts +120 -0
- package/dist/utils/asyncUtils.d.ts +24 -0
- package/dist/utils/cleanupCompressedTiles.d.ts +12 -0
- package/dist/utils/constants.d.ts +94 -0
- package/dist/utils/download.d.ts +52 -0
- package/dist/utils/errorHandling.d.ts +67 -0
- package/dist/utils/formatUtils.d.ts +24 -0
- package/dist/utils/formatting.d.ts +31 -0
- package/dist/utils/icons.d.ts +50 -0
- package/dist/utils/idbFetchHandler.d.ts +2 -0
- package/dist/utils/index.d.ts +13 -0
- package/dist/utils/logger.d.ts +52 -0
- package/dist/utils/performance.d.ts +164 -0
- package/dist/utils/styleProviderUtils.d.ts +42 -0
- package/dist/utils/styleUtils.d.ts +35 -0
- package/dist/utils/validation.d.ts +67 -0
- package/package.json +145 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Muhammad Imran Siddique
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,590 @@
|
|
|
1
|
+
# Map GL Offline 🗺️
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/js/map-gl-offline)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
6
|
+
|
|
7
|
+
> **⚠️ Development Notice**: This package is currently under active development and is optimized for **MapLibre GL JS**. Mapbox GL JS support is planned for future releases.
|
|
8
|
+
|
|
9
|
+
A comprehensive **TypeScript** library for **MapLibre GL JS** that enables complete offline map functionality with vector/raster tiles, styles, fonts, sprites, and glyphs stored in IndexedDB. Features include advanced analytics, import/export capabilities, intelligent cleanup, and a modern glassmorphic UI control.
|
|
10
|
+
|
|
11
|
+
## ✨ Features
|
|
12
|
+
|
|
13
|
+
### 🎯 Core Offline Capabilities
|
|
14
|
+
|
|
15
|
+
- 🗺️ **Complete Offline Maps**: Download and store entire map regions with polygon-based selection
|
|
16
|
+
- 🎯 **Smart Tile Management**: Efficient vector/raster tile downloading, caching, and retrieval with zoom-level optimization
|
|
17
|
+
- 🔤 **Font & Glyph Support**: Comprehensive font and glyph management with Unicode range support
|
|
18
|
+
- 🎨 **Sprite Management**: Handle map sprites and icons offline with multi-resolution support (@1x, @2x)
|
|
19
|
+
- 📊 **Real-time Analytics**: Detailed storage analytics, performance metrics, and optimization recommendations
|
|
20
|
+
- 📤 **Import/Export**: Export regions to JSON, PMTiles, and MBTiles formats for data portability
|
|
21
|
+
- 🔄 **Data Portability**: Seamless transfer of offline maps between devices and applications
|
|
22
|
+
|
|
23
|
+
### 🎨 Modern UI Control
|
|
24
|
+
|
|
25
|
+
- 🖼️ **Glassmorphic Design**: Beautiful modern interface with glassmorphism effects and smooth animations
|
|
26
|
+
- 🌓 **Dark/Light Theme**: Automatic theme switching with system preference detection
|
|
27
|
+
- 📍 **Polygon Drawing**: Interactive polygon tool for precise region selection
|
|
28
|
+
- 📊 **Live Progress**: Real-time download progress with detailed statistics
|
|
29
|
+
- 🎯 **Region Management**: Easy-to-use interface for managing multiple offline regions
|
|
30
|
+
- ⚡ **Responsive**: Mobile-friendly design that adapts to all screen sizes
|
|
31
|
+
|
|
32
|
+
### 🛠️ Technical Excellence
|
|
33
|
+
|
|
34
|
+
- 💾 **IndexedDB Storage**: Efficient browser storage with quota management and transaction safety
|
|
35
|
+
- 🔧 **Full TypeScript**: Complete type definitions, interfaces, and compile-time safety
|
|
36
|
+
- ⚡ **Performance Optimized**: Concurrent downloads, async/await patterns, and memory-efficient operations
|
|
37
|
+
- 🧹 **Intelligent Cleanup**: Smart cleanup of expired data with customizable policies
|
|
38
|
+
- 🔄 **Robust Error Handling**: Comprehensive error recovery, retry mechanisms, and graceful degradation
|
|
39
|
+
- 🗜️ **Multiple Formats**: Support for JSON, PMTiles, and MBTiles export/import
|
|
40
|
+
- 🔍 **Enhanced Logging**: Detailed debugging with zoom-level specific logging (Z12 tracking)
|
|
41
|
+
|
|
42
|
+
## 📦 Installation
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm install map-gl-offline
|
|
46
|
+
# or
|
|
47
|
+
yarn add map-gl-offline
|
|
48
|
+
# or
|
|
49
|
+
pnpm add map-gl-offline
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## 🔑 Environment Setup
|
|
53
|
+
|
|
54
|
+
For development or when using Maptiler styles, create a `.env` file:
|
|
55
|
+
|
|
56
|
+
```env
|
|
57
|
+
VITE_MAPTILER_API_KEY=your_api_key_here
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Get a free API key from [Maptiler](https://www.maptiler.com/).
|
|
61
|
+
|
|
62
|
+
## 🚀 Quick Start
|
|
63
|
+
|
|
64
|
+
### Basic Usage with UI Control
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
import maplibregl from 'maplibre-gl';
|
|
68
|
+
import { OfflineManagerControl } from 'map-gl-offline';
|
|
69
|
+
import 'maplibre-gl/dist/maplibre-gl.css';
|
|
70
|
+
import 'map-gl-offline/dist/style.css'; // Import UI styles
|
|
71
|
+
|
|
72
|
+
// Initialize map
|
|
73
|
+
const map = new maplibregl.Map({
|
|
74
|
+
container: 'map',
|
|
75
|
+
style: 'https://api.maptiler.com/maps/streets/style.json?key=YOUR_API_KEY',
|
|
76
|
+
center: [-74.006, 40.7128],
|
|
77
|
+
zoom: 12,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Add offline control to map
|
|
81
|
+
map.on('load', () => {
|
|
82
|
+
const offlineControl = new OfflineManagerControl({
|
|
83
|
+
position: 'top-right',
|
|
84
|
+
});
|
|
85
|
+
map.addControl(offlineControl);
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The UI control provides:
|
|
90
|
+
|
|
91
|
+
- 📍 **Polygon drawing** for region selection
|
|
92
|
+
- 📊 **Download progress** tracking
|
|
93
|
+
- 🗂️ **Region management** (view, delete, export)
|
|
94
|
+
- 🌓 **Theme toggle** (dark/light mode)
|
|
95
|
+
- 📈 **Storage analytics**
|
|
96
|
+
|
|
97
|
+
### Programmatic Usage
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
import { OfflineMapManager } from 'map-gl-offline';
|
|
101
|
+
|
|
102
|
+
// Initialize the offline manager
|
|
103
|
+
const offlineManager = new OfflineMapManager();
|
|
104
|
+
|
|
105
|
+
// Download a map region for offline use
|
|
106
|
+
await offlineManager.addRegion({
|
|
107
|
+
id: 'downtown',
|
|
108
|
+
name: 'Downtown Area',
|
|
109
|
+
bounds: [
|
|
110
|
+
[-74.0559, 40.7128], // Southwest [lng, lat]
|
|
111
|
+
[-74.0059, 40.7628], // Northeast [lng, lat]
|
|
112
|
+
],
|
|
113
|
+
minZoom: 10,
|
|
114
|
+
maxZoom: 16,
|
|
115
|
+
styleUrl: 'https://api.maptiler.com/maps/streets/style.json?key=YOUR_KEY',
|
|
116
|
+
onProgress: progress => {
|
|
117
|
+
console.log(`Progress: ${progress.percentage}%`);
|
|
118
|
+
console.log(`Current: ${progress.message}`);
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// Retrieve and use stored region
|
|
123
|
+
const region = await offlineManager.getRegion('downtown');
|
|
124
|
+
if (region) {
|
|
125
|
+
map.setStyle(region.offlineStyle); // Apply offline style
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// List all regions
|
|
129
|
+
const regions = await offlineManager.listStoredRegions();
|
|
130
|
+
console.log(`Stored regions:`, regions);
|
|
131
|
+
|
|
132
|
+
// Delete a region
|
|
133
|
+
await offlineManager.deleteRegion('downtown');
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Import/Export Functionality
|
|
137
|
+
|
|
138
|
+
Export and import offline regions for backup, sharing, or cross-device usage:
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
// Export region to JSON
|
|
142
|
+
const jsonExport = await offlineManager.exportRegionAsJSON('downtown', {
|
|
143
|
+
includeStyle: true,
|
|
144
|
+
includeTiles: true,
|
|
145
|
+
includeSprites: true,
|
|
146
|
+
includeFonts: true,
|
|
147
|
+
onProgress: progress => {
|
|
148
|
+
console.log(`Export: ${progress.percentage}% - ${progress.stage}`);
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Download exported file
|
|
153
|
+
const url = URL.createObjectURL(jsonExport.blob);
|
|
154
|
+
const a = document.createElement('a');
|
|
155
|
+
a.href = url;
|
|
156
|
+
a.download = jsonExport.filename;
|
|
157
|
+
a.click();
|
|
158
|
+
URL.revokeObjectURL(url);
|
|
159
|
+
|
|
160
|
+
// Export to PMTiles (web-optimized format)
|
|
161
|
+
const pmtilesExport = await offlineManager.exportRegionAsPMTiles('downtown', {
|
|
162
|
+
compression: 'gzip',
|
|
163
|
+
metadata: { attribution: 'Custom map data', version: '1.0' },
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// Export to MBTiles (SQLite-based, industry standard)
|
|
167
|
+
const mbtilesExport = await offlineManager.exportRegionAsMBTiles('downtown', {
|
|
168
|
+
format: 'pbf',
|
|
169
|
+
compression: 'gzip',
|
|
170
|
+
metadata: { description: 'Offline map for mobile app' },
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// Import region from file
|
|
174
|
+
const fileInput = document.querySelector('#fileInput');
|
|
175
|
+
fileInput.addEventListener('change', async event => {
|
|
176
|
+
const file = event.target.files?.[0];
|
|
177
|
+
if (file) {
|
|
178
|
+
const result = await offlineManager.importRegion({
|
|
179
|
+
file,
|
|
180
|
+
format: 'json', // or 'pmtiles', 'mbtiles'
|
|
181
|
+
overwrite: true,
|
|
182
|
+
newRegionId: 'imported-downtown',
|
|
183
|
+
newRegionName: 'Imported Downtown',
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
if (result.success) {
|
|
187
|
+
console.log(`Imported: ${result.regionId}`);
|
|
188
|
+
console.log(`Stats:`, result.statistics);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Export Format Comparison:**
|
|
195
|
+
|
|
196
|
+
| Format | Best For | Pros | Cons |
|
|
197
|
+
| ------- | ----------------------------- | ---------------------------------------- | ---------------------- |
|
|
198
|
+
| JSON | Development, debugging | Human-readable, easy to inspect | Larger file size |
|
|
199
|
+
| PMTiles | Web deployment, CDN | Efficient HTTP range requests, optimized | Specialized format |
|
|
200
|
+
| MBTiles | GIS tools, cross-platform use | SQLite-based, widely supported, mature | Requires SQLite parser |
|
|
201
|
+
|
|
202
|
+
### Analytics & Monitoring
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
// Get comprehensive storage analytics
|
|
206
|
+
const analytics = await offlineManager.getComprehensiveStorageAnalytics();
|
|
207
|
+
console.log(`Total storage: ${analytics.totalStorageSize} bytes`);
|
|
208
|
+
console.log(`Tiles: ${analytics.tiles.count} (${analytics.tiles.totalSize} bytes)`);
|
|
209
|
+
console.log(`Fonts: ${analytics.fonts.count} (${analytics.fonts.totalSize} bytes)`);
|
|
210
|
+
console.log(`Sprites: ${analytics.sprites.count} (${analytics.sprites.totalSize} bytes)`);
|
|
211
|
+
console.log(`Recommendations:`, analytics.recommendations);
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Cleanup & Maintenance
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
// Clean up old tiles (7 days)
|
|
218
|
+
const tileCleanup = await offlineManager.cleanupOldTiles(7 * 24 * 60 * 60 * 1000);
|
|
219
|
+
console.log(`Cleaned ${tileCleanup} old tiles`);
|
|
220
|
+
|
|
221
|
+
// Verify and repair tiles
|
|
222
|
+
const verification = await offlineManager.verifyAndRepairTiles();
|
|
223
|
+
console.log(`Valid: ${verification.validTiles}, Corrupted: ${verification.corruptedTiles}`);
|
|
224
|
+
|
|
225
|
+
// Start automatic cleanup
|
|
226
|
+
offlineManager.startAutoCleanup({
|
|
227
|
+
interval: 24 * 60 * 60 * 1000, // Daily
|
|
228
|
+
maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## 📚 API Reference
|
|
233
|
+
|
|
234
|
+
### OfflineMapManager
|
|
235
|
+
|
|
236
|
+
Main class for managing offline maps.
|
|
237
|
+
|
|
238
|
+
**Constructor:**
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
const manager = new OfflineMapManager(options?: {
|
|
242
|
+
autoCleanup?: boolean;
|
|
243
|
+
cleanupInterval?: number;
|
|
244
|
+
});
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**Core Methods:**
|
|
248
|
+
|
|
249
|
+
- `addRegion(options: OfflineRegionOptions)` - Download and store a map region
|
|
250
|
+
- `getRegion(id: string)` - Retrieve a stored region by ID
|
|
251
|
+
- `deleteRegion(id: string)` - Delete a specific region and its resources
|
|
252
|
+
- `listStoredRegions()` - List all stored regions with metadata
|
|
253
|
+
- `updateRegion(id: string, updates: Partial<OfflineRegionOptions>)` - Update region settings
|
|
254
|
+
|
|
255
|
+
**Analytics Methods:**
|
|
256
|
+
|
|
257
|
+
- `getComprehensiveStorageAnalytics()` - Get detailed storage statistics
|
|
258
|
+
- `getRegionAnalytics(regionId: string)` - Get analytics for specific region
|
|
259
|
+
- `getTileStats()` - Get tile-specific statistics
|
|
260
|
+
- `getFontStats()` - Get font statistics
|
|
261
|
+
- `getSpriteStats()` - Get sprite statistics
|
|
262
|
+
|
|
263
|
+
**Import/Export Methods:**
|
|
264
|
+
|
|
265
|
+
- `exportRegionAsJSON(regionId: string, options?)` - Export to JSON format
|
|
266
|
+
- `exportRegionAsPMTiles(regionId: string, options?)` - Export to PMTiles format
|
|
267
|
+
- `exportRegionAsMBTiles(regionId: string, options?)` - Export to MBTiles format
|
|
268
|
+
- `importRegion(data: RegionImportData)` - Import from file (JSON/PMTiles/MBTiles)
|
|
269
|
+
|
|
270
|
+
**Maintenance Methods:**
|
|
271
|
+
|
|
272
|
+
- `cleanupOldTiles(maxAge: number)` - Remove tiles older than specified age
|
|
273
|
+
- `cleanupOldFonts(maxAge: number)` - Remove old font data
|
|
274
|
+
- `cleanupExpiredRegions()` - Remove regions past expiration date
|
|
275
|
+
- `verifyAndRepairTiles()` - Verify tile integrity and repair if possible
|
|
276
|
+
- `startAutoCleanup(options)` - Enable automatic cleanup
|
|
277
|
+
- `stopAutoCleanup()` - Disable automatic cleanup
|
|
278
|
+
|
|
279
|
+
### OfflineManagerControl
|
|
280
|
+
|
|
281
|
+
UI control for MapLibre GL with glassmorphic design.
|
|
282
|
+
|
|
283
|
+
**Constructor:**
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
const control = new OfflineManagerControl({
|
|
287
|
+
position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';
|
|
288
|
+
theme?: 'light' | 'dark' | 'auto';
|
|
289
|
+
});
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
**Features:**
|
|
293
|
+
|
|
294
|
+
- Interactive polygon drawing for region selection
|
|
295
|
+
- Real-time download progress tracking
|
|
296
|
+
- Region management (view, delete, export)
|
|
297
|
+
- Theme toggle (dark/light mode)
|
|
298
|
+
- Storage analytics display
|
|
299
|
+
- Responsive mobile-friendly design
|
|
300
|
+
|
|
301
|
+
## 🔧 Configuration Options
|
|
302
|
+
|
|
303
|
+
### OfflineRegionOptions
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
interface OfflineRegionOptions {
|
|
307
|
+
id: string; // Unique region identifier
|
|
308
|
+
name?: string; // Human-readable name
|
|
309
|
+
bounds: [[number, number], [number, number]]; // [[lng, lat], [lng, lat]]
|
|
310
|
+
minZoom: number; // Minimum zoom level (e.g., 10)
|
|
311
|
+
maxZoom: number; // Maximum zoom level (e.g., 16)
|
|
312
|
+
styleUrl: string; // Map style URL
|
|
313
|
+
onProgress?: (progress: ProgressInfo) => void; // Progress callback
|
|
314
|
+
expiresAt?: number; // Expiration timestamp (ms)
|
|
315
|
+
autoDelete?: boolean; // Auto-delete on expiration
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Import/Export Options
|
|
320
|
+
|
|
321
|
+
```typescript
|
|
322
|
+
interface ExportOptions {
|
|
323
|
+
includeStyle?: boolean; // Include style data (default: true)
|
|
324
|
+
includeTiles?: boolean; // Include tiles (default: true)
|
|
325
|
+
includeSprites?: boolean; // Include sprites (default: true)
|
|
326
|
+
includeFonts?: boolean; // Include fonts (default: true)
|
|
327
|
+
onProgress?: (progress: ExportProgress) => void;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
interface PMTilesExportOptions extends ExportOptions {
|
|
331
|
+
compression?: 'gzip' | 'brotli' | 'none';
|
|
332
|
+
clustered?: boolean;
|
|
333
|
+
metadata?: Record<string, any>;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
interface MBTilesExportOptions extends ExportOptions {
|
|
337
|
+
format?: 'pbf' | 'png' | 'jpg';
|
|
338
|
+
compression?: 'gzip' | 'none';
|
|
339
|
+
metadata?: Record<string, any>;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
interface RegionImportData {
|
|
343
|
+
file: File;
|
|
344
|
+
format: 'json' | 'pmtiles' | 'mbtiles';
|
|
345
|
+
overwrite?: boolean;
|
|
346
|
+
newRegionId?: string;
|
|
347
|
+
newRegionName?: string;
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
## 🎯 Use Cases
|
|
352
|
+
|
|
353
|
+
- 🏔️ **Outdoor & Recreation Apps**: Hiking, camping, and adventure apps with offline trail maps
|
|
354
|
+
- 📱 **Field Data Collection**: Survey and data collection in remote areas
|
|
355
|
+
- 🚨 **Emergency Response**: Critical map access during network outages
|
|
356
|
+
- ✈️ **Travel Apps**: Tourist apps with offline city maps
|
|
357
|
+
- 🚗 **Fleet Management**: Vehicle tracking with offline map fallback
|
|
358
|
+
- 📊 **Asset Management**: Field service apps with offline capability
|
|
359
|
+
- 🎓 **Educational Apps**: Geography and learning apps with downloadable maps
|
|
360
|
+
- 🏗️ **Construction & Engineering**: Site management with offline blueprints
|
|
361
|
+
- 💾 **Bandwidth Optimization**: Reduce data costs by pre-downloading maps
|
|
362
|
+
- 🔄 **Multi-Device Sync**: Share offline maps across devices and platforms
|
|
363
|
+
|
|
364
|
+
## 💡 Best Practices
|
|
365
|
+
|
|
366
|
+
### Performance Optimization
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
// Balance quality vs storage with appropriate zoom levels
|
|
370
|
+
const region = {
|
|
371
|
+
minZoom: 10, // Don't go too low (tile count grows exponentially)
|
|
372
|
+
maxZoom: 16, // Don't go too high (diminishing returns)
|
|
373
|
+
bounds: [
|
|
374
|
+
/* ... */
|
|
375
|
+
],
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
// Monitor storage usage
|
|
379
|
+
const analytics = await manager.getComprehensiveStorageAnalytics();
|
|
380
|
+
if (analytics.totalStorageSize > 500 * 1024 * 1024) {
|
|
381
|
+
// 500MB
|
|
382
|
+
console.warn('High storage usage detected');
|
|
383
|
+
await manager.cleanupExpiredRegions();
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Use progressive loading for better UX
|
|
387
|
+
const progressiveDownload = {
|
|
388
|
+
priorityZoomLevels: [12, 13, 11, 14, 10, 15, 16],
|
|
389
|
+
onProgress: p => updateUI(p),
|
|
390
|
+
};
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Error Handling
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
try {
|
|
397
|
+
await manager.addRegion(regionOptions);
|
|
398
|
+
} catch (error) {
|
|
399
|
+
if (error.message.includes('quota')) {
|
|
400
|
+
console.error('Storage quota exceeded');
|
|
401
|
+
await manager.cleanupExpiredRegions();
|
|
402
|
+
} else if (error.message.includes('network')) {
|
|
403
|
+
console.error('Network error. Retrying...');
|
|
404
|
+
} else {
|
|
405
|
+
console.error('Unexpected error:', error);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### Storage Management
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
// Check available storage
|
|
414
|
+
if ('storage' in navigator && 'estimate' in navigator.storage) {
|
|
415
|
+
const { usage, quota } = await navigator.storage.estimate();
|
|
416
|
+
console.log(`Used: ${usage} / ${quota} bytes`);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// Regular cleanup
|
|
420
|
+
await manager.cleanupOldTiles(7 * 24 * 60 * 60 * 1000); // 7 days
|
|
421
|
+
|
|
422
|
+
// Auto-cleanup on startup
|
|
423
|
+
manager.startAutoCleanup({
|
|
424
|
+
interval: 24 * 60 * 60 * 1000, // Daily
|
|
425
|
+
maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days
|
|
426
|
+
});
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
## 🔍 Troubleshooting
|
|
430
|
+
|
|
431
|
+
### Storage Quota Issues
|
|
432
|
+
|
|
433
|
+
```typescript
|
|
434
|
+
// Check quota
|
|
435
|
+
const { usage, quota } = await navigator.storage.estimate();
|
|
436
|
+
if (usage / quota > 0.9) {
|
|
437
|
+
await manager.cleanupExpiredRegions();
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Request persistent storage
|
|
441
|
+
if (navigator.storage?.persist) {
|
|
442
|
+
const isPersisted = await navigator.storage.persist();
|
|
443
|
+
console.log(`Persistent storage: ${isPersisted}`);
|
|
444
|
+
}
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### Import/Export Issues
|
|
448
|
+
|
|
449
|
+
```typescript
|
|
450
|
+
// Validate file before import
|
|
451
|
+
const validFormats = ['json', 'pmtiles', 'mbtiles'];
|
|
452
|
+
const ext = file.name.split('.').pop();
|
|
453
|
+
if (!validFormats.includes(ext)) {
|
|
454
|
+
throw new Error(`Unsupported format: ${ext}`);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// Handle large files
|
|
458
|
+
if (file.size > 100 * 1024 * 1024) {
|
|
459
|
+
// 100MB
|
|
460
|
+
console.warn('Large file - import may take time');
|
|
461
|
+
}
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### Performance Issues
|
|
465
|
+
|
|
466
|
+
```typescript
|
|
467
|
+
// Reduce concurrency for slower devices
|
|
468
|
+
const lightOptions = {
|
|
469
|
+
maxConcurrency: 2,
|
|
470
|
+
batchSize: 10,
|
|
471
|
+
timeout: 30000,
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
// Use smaller regions
|
|
475
|
+
const smallerRegion = {
|
|
476
|
+
minZoom: 11, // Start at higher zoom
|
|
477
|
+
maxZoom: 15, // End at lower zoom
|
|
478
|
+
};
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
## 🌐 Browser Compatibility
|
|
482
|
+
|
|
483
|
+
| Browser | Version | Support |
|
|
484
|
+
| ------- | ------- | ------- |
|
|
485
|
+
| Chrome | 51+ | ✅ |
|
|
486
|
+
| Firefox | 45+ | ✅ |
|
|
487
|
+
| Safari | 10+ | ✅ |
|
|
488
|
+
| Edge | 79+ | ✅ |
|
|
489
|
+
| Mobile | Modern | ✅ |
|
|
490
|
+
|
|
491
|
+
**Requirements:**
|
|
492
|
+
|
|
493
|
+
- IndexedDB support
|
|
494
|
+
- ES2015+ JavaScript
|
|
495
|
+
- Async/await support
|
|
496
|
+
- Web Workers (optional, for background tasks)
|
|
497
|
+
|
|
498
|
+
## 📄 License
|
|
499
|
+
|
|
500
|
+
MIT © [Muhammad Imran Siddique](https://github.com/muimsd)
|
|
501
|
+
|
|
502
|
+
## 🤝 Contributing
|
|
503
|
+
|
|
504
|
+
Contributions are welcome! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
|
505
|
+
|
|
506
|
+
### Development Setup
|
|
507
|
+
|
|
508
|
+
```bash
|
|
509
|
+
# Clone repository
|
|
510
|
+
git clone https://github.com/muimsd/map-gl-offline.git
|
|
511
|
+
cd map-gl-offline
|
|
512
|
+
|
|
513
|
+
# Install dependencies
|
|
514
|
+
pnpm install
|
|
515
|
+
|
|
516
|
+
# Run development server
|
|
517
|
+
pnpm dev
|
|
518
|
+
|
|
519
|
+
# Run tests
|
|
520
|
+
pnpm test
|
|
521
|
+
|
|
522
|
+
# Build library
|
|
523
|
+
pnpm build
|
|
524
|
+
|
|
525
|
+
# Run example app
|
|
526
|
+
cd examples/maplibre
|
|
527
|
+
pnpm install
|
|
528
|
+
pnpm dev
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### Project Structure
|
|
532
|
+
|
|
533
|
+
```
|
|
534
|
+
map-gl-offline/
|
|
535
|
+
├── src/
|
|
536
|
+
│ ├── managers/ # Core offline manager
|
|
537
|
+
│ ├── services/ # Tile, font, sprite services
|
|
538
|
+
│ ├── storage/ # IndexedDB management
|
|
539
|
+
│ ├── ui/ # UI components & controls
|
|
540
|
+
│ ├── utils/ # Utilities & helpers
|
|
541
|
+
│ └── types/ # TypeScript definitions
|
|
542
|
+
├── examples/
|
|
543
|
+
│ └── maplibre/ # Live example app
|
|
544
|
+
└── tests/ # Test suites
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
## 📞 Support & Links
|
|
548
|
+
|
|
549
|
+
- 🐛 [Report Issues](https://github.com/muimsd/map-gl-offline/issues)
|
|
550
|
+
- 💬 [Discussions](https://github.com/muimsd/map-gl-offline/discussions)
|
|
551
|
+
- 📚 [Documentation](https://github.com/muimsd/map-gl-offline)
|
|
552
|
+
- ⭐ [Feature Requests](https://github.com/muimsd/map-gl-offline/issues/new)
|
|
553
|
+
- 🌟 [Star on GitHub](https://github.com/muimsd/map-gl-offline)
|
|
554
|
+
|
|
555
|
+
## 🔄 Recent Updates
|
|
556
|
+
|
|
557
|
+
### v0.1.0 (Latest)
|
|
558
|
+
|
|
559
|
+
- ✅ **Fractional Zoom Fix**: Fixed tile loading at fractional zoom levels
|
|
560
|
+
- ✅ **Modern UI**: Glassmorphic design with dark/light theme
|
|
561
|
+
- ✅ **Polygon Drawing**: Interactive region selection tool
|
|
562
|
+
- ✅ **Import/Export**: JSON, PMTiles, and MBTiles support
|
|
563
|
+
- ✅ **Enhanced Analytics**: Comprehensive storage insights
|
|
564
|
+
- ✅ **Performance**: Optimized downloads and memory usage
|
|
565
|
+
- ✅ **TypeScript**: Full type safety throughout
|
|
566
|
+
|
|
567
|
+
See [CHANGELOG.md](CHANGELOG.md) for complete version history.
|
|
568
|
+
|
|
569
|
+
## 🙏 Acknowledgments
|
|
570
|
+
|
|
571
|
+
- [MapLibre GL JS](https://github.com/maplibre/maplibre-gl-js) - Open-source map rendering engine
|
|
572
|
+
- [PMTiles](https://github.com/protomaps/PMTiles) - Cloud-optimized map tile format
|
|
573
|
+
- [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) - Browser storage API
|
|
574
|
+
- [Tilebelt](https://github.com/mapbox/tilebelt) - Tile coordinate utilities
|
|
575
|
+
|
|
576
|
+
- [Tailwind CSS](https://tailwindcss.com/) - Utility-first CSS framework
|
|
577
|
+
|
|
578
|
+
## 📄 License
|
|
579
|
+
|
|
580
|
+
MIT © [Muhammad Imran Siddique](https://github.com/muimsd)
|
|
581
|
+
|
|
582
|
+
---
|
|
583
|
+
|
|
584
|
+
<div align="center">
|
|
585
|
+
|
|
586
|
+
**Made with ❤️ for the mapping community**
|
|
587
|
+
|
|
588
|
+
[⭐ Star on GitHub](https://github.com/muimsd/map-gl-offline) • [📖 Documentation](https://github.com/muimsd/map-gl-offline) • [🐛 Report Bug](https://github.com/muimsd/map-gl-offline/issues)
|
|
589
|
+
|
|
590
|
+
</div>
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export { OfflineMapManager } from './managers/offlineMapManager';
|
|
2
|
+
export * from './services/tileService';
|
|
3
|
+
export * from './services/fontService';
|
|
4
|
+
export * from './services/glyphService';
|
|
5
|
+
export * from './services/spriteService';
|
|
6
|
+
export * from './services/cleanupService';
|
|
7
|
+
export * from './services/styleService';
|
|
8
|
+
export * from './services/regionService';
|
|
9
|
+
export * from './services/resourceService';
|
|
10
|
+
export * from './services/analyticsService';
|
|
11
|
+
export * from './services/maintenanceService';
|
|
12
|
+
export * from './services/importExportService';
|
|
13
|
+
export * from './storage/indexedDbManager';
|
|
14
|
+
export * from './types';
|
|
15
|
+
export * from './utils';
|
|
16
|
+
export { OfflineMapManager as default } from './managers/offlineMapManager';
|
|
17
|
+
export { OfflineManagerControl } from './ui/offlineManagerControl';
|