map-gl-offline 0.8.9 → 0.9.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 (71) hide show
  1. package/README.md +62 -192
  2. package/dist/idb-offline-sw.js +78 -11
  3. package/dist/index.d.ts +3 -3
  4. package/dist/index.esm.js +2032 -808
  5. package/dist/index.esm.js.map +1 -1
  6. package/dist/index.js +2039 -806
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.umd.js +2367 -933
  9. package/dist/index.umd.js.map +1 -1
  10. package/dist/main.d.ts +3 -0
  11. package/dist/managers/offlineMapManager/analyticsManagement.d.ts +1 -1
  12. package/dist/managers/offlineMapManager/base.d.ts +5 -5
  13. package/dist/managers/offlineMapManager/cleanupManagement.d.ts +6 -1
  14. package/dist/managers/offlineMapManager/importExportManagement.d.ts +1 -1
  15. package/dist/managers/offlineMapManager/maintenanceManagement.d.ts +1 -1
  16. package/dist/managers/offlineMapManager/regionManagement.d.ts +2 -2
  17. package/dist/managers/offlineMapManager/resourceManagement.d.ts +1 -1
  18. package/dist/managers/offlineMapManager/styleManagement.d.ts +1 -1
  19. package/dist/services/analyticsService.d.ts +1 -1
  20. package/dist/services/cleanupService.d.ts +15 -1
  21. package/dist/services/fontService.d.ts +1 -1
  22. package/dist/services/glyphService.d.ts +1 -1
  23. package/dist/services/importExportService.d.ts +1 -1
  24. package/dist/services/maintenanceService.d.ts +2 -2
  25. package/dist/services/modelService.d.ts +3 -1
  26. package/dist/services/regionService.d.ts +21 -11
  27. package/dist/services/resourceService.d.ts +2 -2
  28. package/dist/services/runtimeAssetService.d.ts +12 -0
  29. package/dist/services/spriteService.d.ts +1 -1
  30. package/dist/services/styleService.d.ts +14 -1
  31. package/dist/services/tileService.d.ts +1 -1
  32. package/dist/sheet/collar.d.ts +34 -0
  33. package/dist/storage/indexedDbManager.d.ts +1 -1
  34. package/dist/style.css +2 -2
  35. package/dist/sw/shared.d.ts +31 -3
  36. package/dist/types/import-export.d.ts +5 -0
  37. package/dist/types/maintenance.d.ts +3 -1
  38. package/dist/types/region.d.ts +29 -2
  39. package/dist/types/style.d.ts +4 -0
  40. package/dist/types/tile.d.ts +15 -0
  41. package/dist/ui/components/PanelActions.d.ts +1 -1
  42. package/dist/ui/components/PanelHeader.d.ts +1 -1
  43. package/dist/ui/components/RegionList.d.ts +1 -1
  44. package/dist/ui/components/shared/Button.d.ts +6 -0
  45. package/dist/ui/components/shared/LanguageSelector.d.ts +1 -1
  46. package/dist/ui/components/shared/MapControlButton.d.ts +1 -1
  47. package/dist/ui/components/shared/PanelContent.d.ts +3 -3
  48. package/dist/ui/components/shared/RegionDrawingTool.d.ts +2 -2
  49. package/dist/ui/controls/polygonControl.d.ts +7 -1
  50. package/dist/ui/controls/regionControl.d.ts +3 -3
  51. package/dist/ui/managers/ControlButtonManager.d.ts +1 -1
  52. package/dist/ui/managers/PanelManager.d.ts +16 -3
  53. package/dist/ui/managers/downloadManager.d.ts +7 -3
  54. package/dist/ui/modals/mbtilesModal.d.ts +1 -1
  55. package/dist/ui/modals/regionDetailsModal.d.ts +1 -1
  56. package/dist/ui/modals/regionFormModal.d.ts +11 -1
  57. package/dist/ui/offlineManagerControl.d.ts +4 -1
  58. package/dist/ui/translations/ar.d.ts +15 -1
  59. package/dist/ui/translations/en.d.ts +15 -1
  60. package/dist/ui/translations/index.d.ts +2 -0
  61. package/dist/utils/constants.d.ts +4 -2
  62. package/dist/utils/convertStyleForSW.d.ts +1 -1
  63. package/dist/utils/download.d.ts +1 -1
  64. package/dist/utils/formatting.d.ts +11 -0
  65. package/dist/utils/importResolver.d.ts +1 -1
  66. package/dist/utils/styleConfig.d.ts +39 -0
  67. package/dist/utils/styleProviderUtils.d.ts +21 -8
  68. package/dist/utils/styleUtils.d.ts +61 -10
  69. package/dist/utils/tileRange.d.ts +63 -0
  70. package/dist/utils/validation.d.ts +1 -1
  71. package/package.json +44 -39
@@ -3,7 +3,7 @@
3
3
  * Manages the main control button and progress badge states
4
4
  * Refactored to use modular Button component
5
5
  */
6
- import type { CssPrefix } from '../../utils/cssPrefix';
6
+ import type { CssPrefix } from '../../utils/cssPrefix.js';
7
7
  export interface ButtonManagerOptions {
8
8
  onTogglePanel: () => void;
9
9
  cssPrefix?: CssPrefix;
@@ -3,10 +3,10 @@
3
3
  * Handles rendering of the main offline manager panel
4
4
  * Refactored to use modular components
5
5
  */
6
- import { OfflineMapManager } from '../../managers/offlineMapManager';
6
+ import { OfflineMapManager } from '../../managers/offlineMapManager.js';
7
7
  import { DownloadManager } from './downloadManager';
8
- import { ModalManager } from '../../ui/modals/modalManager';
9
- import { BaseComponent } from '../../ui/components/shared/BaseComponent';
8
+ import { ModalManager } from '../modals/modalManager.js';
9
+ import { BaseComponent } from '../components/shared/BaseComponent.js';
10
10
  type MaplibreMap = unknown;
11
11
  export interface PanelRendererOptions {
12
12
  offlineManager: OfflineMapManager;
@@ -31,10 +31,12 @@ export declare class PanelRenderer extends BaseComponent {
31
31
  private headerContainer?;
32
32
  private actionButtonsContainer?;
33
33
  private regionsList?;
34
+ private awaitingProgressRender;
34
35
  private downloadProgressContainer?;
35
36
  private languageSelector?;
36
37
  private refreshTimeout?;
37
38
  private isRefreshing;
39
+ private refreshQueued;
38
40
  private unsubscribeLanguage?;
39
41
  private regionActionHandler?;
40
42
  constructor(options: PanelRendererOptions);
@@ -79,6 +81,13 @@ export declare class PanelRenderer extends BaseComponent {
79
81
  * Create orphaned regions header template
80
82
  */
81
83
  private createOrphanedRegionsHeaderTemplate;
84
+ /**
85
+ * Show the latest download progress. Called on every update, so it only
86
+ * redraws the progress section rather than the whole panel.
87
+ */
88
+ updateDownloadProgress(downloads: ReadonlyMap<string, unknown>): void;
89
+ /** What the current phase is doing, such as "Tiles: 64 of 128". */
90
+ private describeDownloadPhase;
82
91
  /**
83
92
  * Create download progress HTML
84
93
  */
@@ -158,6 +167,10 @@ export declare class PanelRenderer extends BaseComponent {
158
167
  /**
159
168
  * Handle loading a style to the map
160
169
  */
170
+ /** Whether the map is drawing this stored style, through `idb://` or the Service Worker. */
171
+ private isStyleShown;
172
+ /** After its stored copy is deleted, show a style from its original URL, not a blank map. */
173
+ private showOnlineStyle;
161
174
  private handleLoadStyle;
162
175
  /**
163
176
  * Handle deleting a style
@@ -44,8 +44,8 @@
44
44
  *
45
45
  * @module downloadManager
46
46
  */
47
- import { OfflineMapManager } from '../../managers/offlineMapManager';
48
- import { RegionFormData } from '../../ui/modals/regionFormModal';
47
+ import { OfflineMapManager } from '../../managers/offlineMapManager.js';
48
+ import { RegionFormData } from '../modals/regionFormModal.js';
49
49
  /**
50
50
  * Progress information for an active download.
51
51
  *
@@ -70,8 +70,10 @@ export interface DownloadProgress {
70
70
  completed: number;
71
71
  /** Total number of resources in current phase */
72
72
  total: number;
73
- /** Completion percentage (0-100) */
73
+ /** How far through the whole download (0-100). Only moves forward. */
74
74
  percentage: number;
75
+ /** How far through the current phase (0-100). */
76
+ phasePercentage?: number;
75
77
  /** Human-readable description of current activity */
76
78
  currentResource: string;
77
79
  /** Current download phase */
@@ -119,6 +121,8 @@ export declare class DownloadManager {
119
121
  private offlineManager;
120
122
  /** Map of region IDs to their download progress */
121
123
  private currentDownloads;
124
+ /** Aborts each running download, by region id. */
125
+ private controllers;
122
126
  private options;
123
127
  /**
124
128
  * Create a new DownloadManager instance.
@@ -4,7 +4,7 @@
4
4
  * Focused modal for exchanging regions as binary SQLite MBTiles archives.
5
5
  * Replaces the previous multi-format import/export modal.
6
6
  */
7
- import type { StoredRegion, ImportExportOptions, MBTilesExportOptions, ExportResult, ImportResult, RegionImportData } from '../../types';
7
+ import type { StoredRegion, ImportExportOptions, MBTilesExportOptions, ExportResult, ImportResult, RegionImportData } from '../../types/index.js';
8
8
  type MBTilesExportRequestOptions = ImportExportOptions & MBTilesExportOptions;
9
9
  export interface MBTilesModalOptions {
10
10
  region: StoredRegion;
@@ -3,7 +3,7 @@
3
3
  * Shows detailed information about a specific region
4
4
  * Refactored to use modular components
5
5
  */
6
- import { StoredRegion } from '../../types/region';
6
+ import { StoredRegion } from '../../types/region.js';
7
7
  export interface RegionDetailsOptions {
8
8
  region: StoredRegion;
9
9
  onClose: () => void;
@@ -12,7 +12,7 @@ export interface RegionFormData {
12
12
  provider?: 'mapbox' | 'maplibre' | 'auto';
13
13
  accessToken?: string | null;
14
14
  /** Additional tile sources to download alongside the style's own sources */
15
- extraSources?: import('../../types/region').ExtraSource[];
15
+ extraSources?: import('../../types/region.js').ExtraSource[];
16
16
  }
17
17
  /**
18
18
  * A tile source discovered on the live map, presented to the user for selection.
@@ -42,6 +42,11 @@ export interface RegionFormOptions {
42
42
  /** Tile sources discovered from the live map for user selection */
43
43
  mapSources?: MapTileSource[];
44
44
  }
45
+ /**
46
+ * True when a region of Mapbox Standard stops below the zoom where its buildings
47
+ * start. Standard Satellite has no buildings, so it doesn't count.
48
+ */
49
+ export declare function regionMissesBuildings(styleUrl: string, maxZoom: number): boolean;
45
50
  export declare class RegionFormModal {
46
51
  private options;
47
52
  private modal?;
@@ -49,6 +54,7 @@ export declare class RegionFormModal {
49
54
  private minZoomInput?;
50
55
  private maxZoomInput?;
51
56
  private styleUrlInput?;
57
+ private buildingsHint?;
52
58
  private providerSelect?;
53
59
  private accessTokenInput?;
54
60
  private accessTokenGroup?;
@@ -73,6 +79,8 @@ export declare class RegionFormModal {
73
79
  /**
74
80
  * Handle style URL changes to auto-detect provider
75
81
  */
82
+ /** Warn when a region would be saved without the style's buildings. */
83
+ private updateBuildingsHint;
76
84
  private handleStyleUrlChange;
77
85
  /**
78
86
  * Handle provider selection changes
@@ -90,6 +98,8 @@ export declare class RegionFormModal {
90
98
  * Create the footer with action buttons
91
99
  */
92
100
  private createFooter;
101
+ /** Check the zoom fields, showing the browser's message on the first bad one. */
102
+ private zoomRangeIsValid;
93
103
  /**
94
104
  * Handle form save
95
105
  */
@@ -35,7 +35,7 @@
35
35
  * @module offlineManagerControl
36
36
  */
37
37
  import type { IControl } from 'maplibre-gl';
38
- import { OfflineMapManager } from '../managers/offlineMapManager';
38
+ import { OfflineMapManager } from '../managers/offlineMapManager.js';
39
39
  /**
40
40
  * Request shape MapLibre passes to a protocol handler. `type` indicates how
41
41
  * the response will be consumed — `"json"` for sprite atlases / TileJSON,
@@ -127,6 +127,9 @@ export declare class OfflineManagerControl implements IControl {
127
127
  private regionControl;
128
128
  private downloadManager;
129
129
  private modalManager;
130
+ /** Percentages of this batch's downloads, finished ones at 100, for the badge. */
131
+ private badgeBatch;
132
+ private badgePercentage;
130
133
  /** Whether the bounding box visualization layer has been added to the map */
131
134
  private bboxLayerAdded;
132
135
  /** Map library module for protocol registration (null if not provided) */
@@ -24,7 +24,7 @@ export declare const ar: {
24
24
  readonly 'language.en': "الإنجليزية";
25
25
  readonly 'language.ar': "العربية";
26
26
  readonly 'header.title': "مدير الخرائط غير المتصلة";
27
- readonly 'header.subtitle': "{{count}} منطقة • {{size}} إجمالي";
27
+ readonly 'header.subtitle': "{{regions}} • {{size}} إجمالي";
28
28
  readonly 'actions.addRegion': "إضافة منطقة";
29
29
  readonly 'actions.refresh': "تحديث";
30
30
  readonly 'actions.loadStyle': "تحميل النمط";
@@ -38,6 +38,8 @@ export declare const ar: {
38
38
  readonly 'regionForm.namePlaceholder': "مثال: وسط المدينة";
39
39
  readonly 'regionForm.minZoom': "أدنى تكبير";
40
40
  readonly 'regionForm.maxZoom': "أقصى تكبير";
41
+ readonly 'regionForm.buildingsHint': "تبدأ مباني Mapbox Standard عند مستوى التكبير 15. اضبط أقصى تكبير على 15 أو أكثر لتضمينها.";
42
+ readonly 'regionForm.zoomRangeError': "يجب ألا يقل أقصى تكبير عن أدنى تكبير.";
41
43
  readonly 'regionForm.styleUrl': "رابط النمط";
42
44
  readonly 'regionForm.provider': "مزود النمط";
43
45
  readonly 'regionForm.providerAuto': "اكتشاف تلقائي";
@@ -66,7 +68,10 @@ export declare const ar: {
66
68
  readonly 'regionList.downloaded': "تم التحميل";
67
69
  readonly 'regionList.size': "الحجم";
68
70
  readonly 'regionList.tiles': "البلاطات";
71
+ readonly 'regionList.resources': "الخطوط والرموز والنماذج";
69
72
  readonly 'regionList.styleData': "النمط";
73
+ readonly 'regionList.regionCountOne': "منطقة واحدة";
74
+ readonly 'regionList.regionCount': "{{count}} منطقة";
70
75
  readonly 'regionList.totalSize': "الإجمالي";
71
76
  readonly 'regionList.styleId': "معرف النمط";
72
77
  readonly 'regionDetails.title': "تفاصيل المنطقة";
@@ -138,6 +143,13 @@ export declare const ar: {
138
143
  readonly 'mbtiles.importComplete': "اكتمل الاستيراد!";
139
144
  readonly 'mbtiles.importFailed': "فشل الاستيراد. يرجى المحاولة مرة أخرى.";
140
145
  readonly 'download.activeCount': "التحميلات النشطة ({{count}})";
146
+ readonly 'download.status.style': "جارٍ تجهيز النمط";
147
+ readonly 'download.status.sprites': "الرموز: {{completed}} من {{total}}";
148
+ readonly 'download.status.glyphs': "الخطوط: {{completed}} من {{total}}";
149
+ readonly 'download.status.models': "النماذج ثلاثية الأبعاد: {{completed}} من {{total}}";
150
+ readonly 'download.status.tiles': "البلاطات: {{completed}} من {{total}}";
151
+ readonly 'download.status.planning': "جارٍ تخطيط البلاطات";
152
+ readonly 'download.status.saving': "جارٍ حفظ المنطقة";
141
153
  readonly 'panel.downloadedRegions': "المناطق المحملة";
142
154
  readonly 'panel.noExpiry': "بدون انتهاء";
143
155
  readonly 'panel.noBounds': "بدون حدود";
@@ -153,6 +165,8 @@ export declare const ar: {
153
165
  readonly 'control.cancelSelection': "إلغاء التحديد";
154
166
  readonly 'control.saveSelectedRegion': "حفظ المنطقة المحددة";
155
167
  readonly 'alert.unknownError': "حدث خطأ غير معروف";
168
+ readonly 'alert.downloadFailed': "فشل التحميل";
169
+ readonly 'alert.needsMapboxGl': "يستخدم هذا النمط ميزات Mapbox GL JS، مثل النماذج ثلاثية الأبعاد أو إعدادات النمط، لذا لا يمكن عرضه إلا على خريطة Mapbox GL.";
156
170
  readonly 'alert.downloadNotImplemented': "ميزة التحميل غير مطبقة في هذه النسخة";
157
171
  readonly 'alert.mapNotAvailable': "الخريطة غير متاحة";
158
172
  readonly 'alert.invalidBounds': "حدود غير صالحة للمنطقة";
@@ -23,7 +23,7 @@ export declare const en: {
23
23
  readonly 'language.en': "English";
24
24
  readonly 'language.ar': "Arabic";
25
25
  readonly 'header.title': "Offline Manager";
26
- readonly 'header.subtitle': "{{count}} regions • {{size}} total";
26
+ readonly 'header.subtitle': "{{regions}} • {{size}} total";
27
27
  readonly 'actions.addRegion': "Add Region";
28
28
  readonly 'actions.refresh': "Refresh";
29
29
  readonly 'actions.loadStyle': "Load Style";
@@ -37,6 +37,8 @@ export declare const en: {
37
37
  readonly 'regionForm.namePlaceholder': "e.g., Downtown District";
38
38
  readonly 'regionForm.minZoom': "Min Zoom";
39
39
  readonly 'regionForm.maxZoom': "Max Zoom";
40
+ readonly 'regionForm.buildingsHint': "Mapbox Standard's buildings start at zoom 15. Set Max Zoom to 15 or more to include them.";
41
+ readonly 'regionForm.zoomRangeError': "Max Zoom must be at least Min Zoom.";
40
42
  readonly 'regionForm.styleUrl': "Style URL";
41
43
  readonly 'regionForm.provider': "Style Provider";
42
44
  readonly 'regionForm.providerAuto': "Auto-detect";
@@ -65,7 +67,10 @@ export declare const en: {
65
67
  readonly 'regionList.downloaded': "Downloaded";
66
68
  readonly 'regionList.size': "Size";
67
69
  readonly 'regionList.tiles': "Tiles";
70
+ readonly 'regionList.resources': "Fonts, icons and models";
68
71
  readonly 'regionList.styleData': "Style";
72
+ readonly 'regionList.regionCountOne': "1 region";
73
+ readonly 'regionList.regionCount': "{{count}} regions";
69
74
  readonly 'regionList.totalSize': "Total";
70
75
  readonly 'regionList.styleId': "Style ID";
71
76
  readonly 'regionDetails.title': "Region Details";
@@ -137,6 +142,13 @@ export declare const en: {
137
142
  readonly 'mbtiles.importComplete': "Import complete!";
138
143
  readonly 'mbtiles.importFailed': "Import failed. Please try again.";
139
144
  readonly 'download.activeCount': "Active Downloads ({{count}})";
145
+ readonly 'download.status.style': "Preparing style";
146
+ readonly 'download.status.sprites': "Sprites: {{completed}} of {{total}}";
147
+ readonly 'download.status.glyphs': "Fonts: {{completed}} of {{total}}";
148
+ readonly 'download.status.models': "3D models: {{completed}} of {{total}}";
149
+ readonly 'download.status.tiles': "Tiles: {{completed}} of {{total}}";
150
+ readonly 'download.status.planning': "Planning tiles";
151
+ readonly 'download.status.saving': "Saving region";
140
152
  readonly 'panel.downloadedRegions': "Downloaded Regions";
141
153
  readonly 'panel.noExpiry': "No expiry";
142
154
  readonly 'panel.noBounds': "No bounds";
@@ -152,6 +164,8 @@ export declare const en: {
152
164
  readonly 'control.cancelSelection': "Cancel Selection";
153
165
  readonly 'control.saveSelectedRegion': "Save Selected Region";
154
166
  readonly 'alert.unknownError': "Unknown error occurred";
167
+ readonly 'alert.downloadFailed': "Download failed";
168
+ readonly 'alert.needsMapboxGl': "This style uses Mapbox GL JS features, such as 3D models or style config, so only a Mapbox GL map can show it.";
155
169
  readonly 'alert.downloadNotImplemented': "Download feature not implemented in this refactored version";
156
170
  readonly 'alert.mapNotAvailable': "Map not available";
157
171
  readonly 'alert.invalidBounds': "Invalid bounds for region";
@@ -57,5 +57,7 @@ declare class I18nManager {
57
57
  }
58
58
  export declare const i18n: I18nManager;
59
59
  export declare const t: (key: TranslationKey, replacements?: Record<string, string | number>) => string;
60
+ /** "1 region" or "3 regions", in the current language. */
61
+ export declare const regionCountLabel: (count: number) => string;
60
62
  export { i18next };
61
63
  export { en, ar };
@@ -84,8 +84,10 @@ export declare const MAPBOX_API: {
84
84
  /**
85
85
  * Mapbox Standard sub-tilesets that are sparse-by-design across the planet.
86
86
  * These only have tiles where the underlying feature (indoor venues, landmark
87
- * POIs, 3D procedural buildings) actually exists, and return 404 for nearly
88
- * every other coordinate. The tile downloader pre-skips any source whose tile
87
+ * POIs, 3D procedural buildings) actually exists, and return 404 for every other
88
+ * coordinate, though they can be dense inside a major city. Unless the style's
89
+ * config has switched on a feature that needs one, the tile downloader pre-skips
90
+ * any source whose tile
89
91
  * URL templates reference one of these tileset IDs, so we never issue probe
90
92
  * or download requests for them — eliminating the 404 noise in devtools.
91
93
  *
@@ -1,4 +1,4 @@
1
- import type { MapboxStyle } from '../types/style';
1
+ import type { MapboxStyle } from '../types/style.js';
2
2
  /**
3
3
  * Convert a style with `idb://` URLs to use absolute `/__offline__/` HTTP URLs
4
4
  * so that a Service Worker can intercept the requests from web workers.
@@ -1,4 +1,4 @@
1
- import type { DownloadProgress } from '../types';
1
+ import type { DownloadProgress } from '../types/index.js';
2
2
  import { type ProxyType } from './proxyConfig';
3
3
  export type FetchResourceResult = {
4
4
  type: 'json';
@@ -5,6 +5,17 @@
5
5
  * Format bytes to human readable string
6
6
  */
7
7
  export declare function formatBytes(bytes: number): string;
8
+ /**
9
+ * A stored style's display name: its own `name`, or else the last meaningful
10
+ * part of its URL ("liberty" for `.../styles/liberty`), or else its key.
11
+ */
12
+ export declare function styleDisplayName(entry: {
13
+ key: string;
14
+ originalUrl?: string;
15
+ style?: {
16
+ name?: string;
17
+ };
18
+ }): string;
8
19
  /**
9
20
  * Format date to human readable string
10
21
  */
@@ -6,7 +6,7 @@
6
6
  * into the outer style. This allows the existing download pipeline to work
7
7
  * unchanged with import-based styles like Mapbox Standard.
8
8
  */
9
- import type { BaseStyle } from '../types/style';
9
+ import type { BaseStyle } from '../types/style.js';
10
10
  /** A single import entry in a style's `imports` array */
11
11
  export interface StyleImport {
12
12
  id: string;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Mapbox GL v3 style-config helpers.
3
+ *
4
+ * Mapbox Standard is one style with switchable features: most of its layers set
5
+ * `layout.visibility` from `["config", key]` expressions backed by `style.schema`
6
+ * defaults. These helpers work out which sources the style actually needs for
7
+ * the current config, so features that are switched off aren't downloaded and
8
+ * features that are switched on aren't skipped.
9
+ */
10
+ import type { BaseStyle } from '../types/style.js';
11
+ type ConfigValues = Record<string, unknown>;
12
+ /**
13
+ * True for styles whose feature set is config-driven: they declare a `schema`,
14
+ * or were flattened from `imports` (whose config is already resolved into the
15
+ * layers). Other styles are never filtered by config.
16
+ */
17
+ export declare function isConfigDrivenStyle(style: unknown): boolean;
18
+ /**
19
+ * Sources a config-driven style uses under its current config (`active`), and
20
+ * those it references but only from hidden layers or unused iconsets (`inactive`).
21
+ *
22
+ * Deliberately errs towards keeping sources: a visibility expression that can't
23
+ * be decided counts as visible. Sources nothing in the style references
24
+ * (`extraSources`, ones a caller adds at runtime) are in neither set.
25
+ */
26
+ export declare function classifySources(style: unknown): {
27
+ active: Set<string>;
28
+ inactive: Set<string>;
29
+ };
30
+ /** The sources {@link classifySources} found to be unneeded under the current config. */
31
+ export declare function findInactiveSources(style: unknown): Set<string>;
32
+ /**
33
+ * Write config values into a style's `schema` defaults. `["config", key]` reads
34
+ * those defaults at render time, so this one edit drives both what gets
35
+ * downloaded and what the stored style shows offline. Keys the schema doesn't
36
+ * declare are ignored with a warning.
37
+ */
38
+ export declare function applyStyleConfig(style: BaseStyle, config: ConfigValues): void;
39
+ export {};
@@ -2,7 +2,7 @@
2
2
  * Style Provider Detection and Handling Utilities
3
3
  * Supports both Mapbox GL and MapLibre GL styles
4
4
  */
5
- import type { BaseStyle, StyleProvider } from '../types/style';
5
+ import type { BaseStyle, StyleProvider } from '../types/style.js';
6
6
  /**
7
7
  * Check if a URL uses the mapbox:// protocol
8
8
  */
@@ -34,17 +34,30 @@ export declare function isMapboxHost(url: string, base?: string): boolean;
34
34
  */
35
35
  export declare function resolveMapboxUrl(mapboxUrl: string, accessToken: string): string;
36
36
  /**
37
- * Rewrite Mapbox CDN tile URLs to use the api.mapbox.com/v4 endpoint.
37
+ * Pick the TileJSON variant Mapbox GL renders from, the way its `mergeVariants`
38
+ * does: `meshopt-v2+lod`, then `meshopt`, then the base tileset.
38
39
  *
39
- * TileJSON responses from Mapbox return tile URLs on *.tiles.mapbox.com CDN
40
- * which may use paths like /raster/v1/ that require an SKU session token
41
- * generated by the Mapbox GL JS SDK at runtime. Since we fetch tiles directly
42
- * without the SDK, these 401. The /v4/ API endpoint on api.mapbox.com works
43
- * with just an access_token, so we rewrite CDN URLs to use it.
40
+ * These aren't just different encodings of one dataset. For
41
+ * `mapbox.mapbox-3dbuildings-v1`, the base tile over central Dubai is empty while
42
+ * the variants hold its 3D buildings, so downloading the base loses them offline.
43
+ * Variant tiles are `mapbox://3dtiles/...` URLs, resolved here using the base
44
+ * URL's query string, which carries the access token.
45
+ */
46
+ export declare function selectTileJsonVariant<T extends object>(tileJson: T): T;
47
+ /**
48
+ * Add the `sku` session token that Mapbox `/raster/v1/` tile URLs need.
49
+ *
50
+ * TileJSON returns these URLs without one, and without it they 401. Mapbox GL
51
+ * adds it at request time, but this library fetches tiles itself.
52
+ *
53
+ * Don't switch these to the `/v4/` endpoint, which needs no token: it serves a
54
+ * different tile. For `mapbox.mapbox-terrain-dem-v1`, `/v4/….png` is a 256px
55
+ * palette PNG with elevations off by up to ~200 m, while the renderer expects
56
+ * the 514px RGB tile (`tileSize: 514`) that `/raster/v1/` returns.
44
57
  *
45
58
  * Example:
46
59
  * https://a.tiles.mapbox.com/raster/v1/mapbox.mapbox-terrain-dem-v1/{z}/{x}/{y}.png?access_token=...
47
- * -> https://api.mapbox.com/v4/mapbox.mapbox-terrain-dem-v1/{z}/{x}/{y}.png?access_token=...
60
+ * -> https://a.tiles.mapbox.com/raster/v1/mapbox.mapbox-terrain-dem-v1/{z}/{x}/{y}.png?access_token=...&sku=101...
48
61
  */
49
62
  export declare function rewriteMapboxCdnTileUrl(tileUrl: string): string;
50
63
  /**
@@ -1,22 +1,72 @@
1
- import type { MapboxStyle } from '../types/style';
1
+ import type { MapboxStyle } from '../types/style.js';
2
2
  /**
3
- * Patches a MapboxStyle for offline use by replacing URLs with IndexedDB references
3
+ * Patches a MapboxStyle for offline use by replacing URLs with IndexedDB references.
4
+ *
5
+ * Safe to call repeatedly on the same stored style (every `addRegion` does):
6
+ * the first call stashes each source's upstream `tiles` / `maxzoom` under
7
+ * `__originalTiles` / `__originalMaxzoom`, and later calls patch from those,
8
+ * so the download pipeline can still reach the network and `maxzoom` can grow
9
+ * again when a deeper region is added.
10
+ *
4
11
  * @param style - The style to patch
5
- * @param downloadId - The download/region ID for tiles and other resources
6
- * @param maxZoom - Optional max zoom level for sources
12
+ * @param downloadId - Fallback ID for `idb://` URLs when `styleId` is omitted
13
+ * @param maxZoom - Max zoom downloaded for this style (the highest across its regions)
7
14
  * @param tileExtension - Optional tile extension
8
- * @param styleId - Optional style ID for sprites (if different from downloadId). Sprites are shared
9
- * across regions and stored with the style ID, so this parameter allows the sprite
10
- * URLs to correctly reference the style ID.
15
+ * @param styleId - Style ID used in all `idb://` URLs. Tiles, glyphs, sprites and
16
+ * models are stored per style, so URLs keyed by style keep working
17
+ * when any one region is deleted.
18
+ */
19
+ /**
20
+ * Add a region's extra tile sources to a style, unless one with that id is
21
+ * already there. Sources must be in the style before it's patched for offline use.
22
+ */
23
+ export declare function injectExtraSources(style: {
24
+ sources: Record<string, unknown>;
25
+ }, extraSources?: ReadonlyArray<{
26
+ id: string;
27
+ tiles: string[];
28
+ type?: string;
29
+ minzoom?: number;
30
+ maxzoom?: number;
31
+ attribution?: string;
32
+ }>): void;
33
+ /**
34
+ * Keep each model's upstream URL before the style is patched, the first time
35
+ * only. Patching points every model at `idb://`, so without this a model that
36
+ * failed to download couldn't be fetched again.
37
+ */
38
+ export declare function stashOriginalModels(entry: {
39
+ style: object;
40
+ originalModels?: Record<string, unknown>;
41
+ }): void;
42
+ /**
43
+ * Point models that aren't stored back at their upstream URLs. Run after
44
+ * patching, which points every model at `idb://`.
11
45
  */
46
+ export declare function restoreUnstoredModels(entry: {
47
+ style: object;
48
+ originalModels?: Record<string, unknown>;
49
+ }, storedNames: ReadonlySet<string>): void;
50
+ /**
51
+ * Whether a style uses parts of the spec only Mapbox GL JS v3 draws: config
52
+ * (`schema`), 3D `models`, `lights` or `imports`. MapLibre rejects these.
53
+ */
54
+ export declare function needsMapboxGl(style: object): boolean;
55
+ /** Whether a map instance is Mapbox GL JS v3, the only renderer with style config. */
56
+ export declare function isMapboxGlMap(map: unknown): boolean;
12
57
  export declare function patchStyleForOffline(style: MapboxStyle, downloadId: string, maxZoom?: number, tileExtension?: string, styleId?: string): MapboxStyle;
58
+ type FontSchema = Record<string, {
59
+ default?: unknown;
60
+ }>;
13
61
  /**
14
62
  * Extract individual font names from a `text-font` layout property value.
15
63
  *
16
- * Handles both simple arrays (`["Font A", "Font B"]`) and Mapbox GL expression
17
- * syntax (e.g. `["step", ["zoom"], ["literal", ["Font A"]], 10, ["literal", ["Font B"]]]`).
64
+ * Handles simple arrays (`["Font A", "Font B"]`), Mapbox GL expression syntax
65
+ * (e.g. `["step", ["zoom"], ["literal", ["Font A"]], 10, ["literal", ["Font B"]]]`),
66
+ * and Mapbox Standard's config-built stacks
67
+ * (`[["concat", ["config", "font"], " Medium"], "Arial Unicode MS Bold"]`).
18
68
  */
19
- export declare function extractFontNamesFromTextField(textFont: unknown): string[];
69
+ export declare function extractFontNamesFromTextField(textFont: unknown, schema?: FontSchema): string[];
20
70
  /**
21
71
  * Normalize a style's `sprite` property into a uniform array of {id, url} sources.
22
72
  * Handles string format, array format, and filters out already-patched idb:// URLs.
@@ -51,3 +101,4 @@ export declare function generateGlyphUrlsFromStyle(style: {
51
101
  };
52
102
  }>;
53
103
  }, glyphsUrlTemplate: string, ranges?: Array<[number, number]>): string[];
104
+ export {};
@@ -0,0 +1,63 @@
1
+ export interface TileRange {
2
+ minX: number;
3
+ maxX: number;
4
+ minY: number;
5
+ maxY: number;
6
+ }
7
+ /**
8
+ * XYZ tile range covering `bounds` at zoom `z`. Shared by the download
9
+ * pipeline (which fetches exactly this range) and region-scoped consumers
10
+ * like MBTiles export, so both agree on which tiles belong to a region.
11
+ */
12
+ export declare function getTileRangeAtZoom(bounds: [[number, number], [number, number]], z: number): TileRange;
13
+ /**
14
+ * Whether tile `z/x/y` falls inside `bounds` and `[minZoom, maxZoom]`.
15
+ */
16
+ export declare function isTileInRegion(z: number, x: number, y: number, region: {
17
+ bounds: [[number, number], [number, number]];
18
+ minZoom: number;
19
+ maxZoom: number;
20
+ }): boolean;
21
+ /**
22
+ * Zoom levels to download for one source in `region`: the overlap of the
23
+ * region's and the source's zoom ranges. When they don't overlap, the source
24
+ * still gets the zooms the map needs from it:
25
+ * - source ends below the region (`maxzoom` < region min) → its `maxzoom`,
26
+ * which the renderer overzooms for the region's zooms;
27
+ * - source starts above the region (`minzoom` > region max) → `minzoom`
28
+ * through `maxzoom` (or just `minzoom` if unbounded).
29
+ */
30
+ export declare function sourceZoomRange(region: {
31
+ minZoom: number;
32
+ maxZoom: number;
33
+ }, sourceMinZoom?: number, sourceMaxZoom?: number): {
34
+ min: number;
35
+ max: number;
36
+ };
37
+ /** Zoom fields of a stored style source (possibly patched by patchStyleForOffline). */
38
+ export interface SourceZoomConfig {
39
+ minzoom?: number;
40
+ maxzoom?: number;
41
+ __originalMaxzoom?: number | null;
42
+ }
43
+ /**
44
+ * A stored source's upstream `maxzoom`. Patched styles cap `maxzoom` for
45
+ * rendering and stash the upstream value under `__originalMaxzoom`.
46
+ */
47
+ export declare function upstreamMaxzoom(source: SourceZoomConfig | undefined): number | undefined;
48
+ /**
49
+ * Whether a stored tile was downloaded for `region`: inside its bounds, at a
50
+ * zoom the download pipeline fetches for the tile's source (which can fall
51
+ * outside the region's own range — see `sourceZoomRange`). `sources` is the
52
+ * stored style's `sources`. Regions with malformed bounds match nothing.
53
+ */
54
+ export declare function tileBelongsToRegion(tile: {
55
+ sourceId?: string;
56
+ z: number;
57
+ x: number;
58
+ y: number;
59
+ }, region: {
60
+ bounds: [[number, number], [number, number]];
61
+ minZoom: number;
62
+ maxZoom: number;
63
+ }, sources: Record<string, SourceZoomConfig | undefined>): boolean;
@@ -2,7 +2,7 @@
2
2
  * Validation utilities for common patterns
3
3
  * Provides reusable validation functions to ensure data integrity
4
4
  */
5
- import type { OfflineRegionOptions } from '../types';
5
+ import type { OfflineRegionOptions } from '../types/index.js';
6
6
  /**
7
7
  * Validate geographic bounds
8
8
  * @param bounds - Array of two [lng, lat] coordinate pairs