map-gl-style-switcher 0.7.0 → 0.7.5
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/README.md +170 -33
- package/dist/map-gl-style-switcher.css +195 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,21 +4,23 @@
|
|
|
4
4
|
[](https://github.com/muimsd/map-gl-style-switcher/actions/workflows/ci.yml)
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
6
|
[](https://app.netlify.com/projects/map-gl-style-switcher/deploys)
|
|
7
|
+
|
|
7
8
|
<!-- [](https://codecov.io/gh/muimsd/map-gl-style-switcher) -->
|
|
8
9
|
|
|
9
|
-
A TypeScript control for switching Mapbox GL / MapLibre GL map styles. Easily add a floating style switcher to your map app, with support for multiple styles, images, dark/light themes, and before/after change callbacks.
|
|
10
|
+
A TypeScript control for switching Mapbox GL / MapLibre GL map styles. Easily add a floating style switcher to your map app, with support for multiple styles, images, dark/light themes, and before/after change callbacks.
|
|
10
11
|
|
|
11
12
|
**Available as:**
|
|
13
|
+
|
|
12
14
|
- `StyleSwitcherControl` - Direct IControl implementation for Mapbox/MapLibre GL
|
|
13
15
|
- `MapGLStyleSwitcher` - React component for react-map-gl integration
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
**<a href="https://map-gl-style-switcher.netlify.app/" target="_blank">🌐 Live Demo</a>**
|
|
16
18
|
|
|
17
19
|
## Demo
|
|
18
20
|
|
|
19
21
|

|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
_Live demo of the style switcher control in action_
|
|
22
24
|
|
|
23
25
|
## Features
|
|
24
26
|
|
|
@@ -49,6 +51,130 @@ yarn add map-gl-style-switcher
|
|
|
49
51
|
pnpm add map-gl-style-switcher
|
|
50
52
|
```
|
|
51
53
|
|
|
54
|
+
## CDN Usage
|
|
55
|
+
|
|
56
|
+
For quick prototyping or when you don't want to use a build system, you can include the package directly from a CDN:
|
|
57
|
+
|
|
58
|
+
### unpkg CDN
|
|
59
|
+
|
|
60
|
+
```html
|
|
61
|
+
<!DOCTYPE html>
|
|
62
|
+
<html>
|
|
63
|
+
<head>
|
|
64
|
+
<!-- MapLibre GL CSS -->
|
|
65
|
+
<link href="https://unpkg.com/maplibre-gl@4/dist/maplibre-gl.css" rel="stylesheet" />
|
|
66
|
+
|
|
67
|
+
<!-- Style Switcher CSS -->
|
|
68
|
+
<link rel="stylesheet" href="https://unpkg.com/map-gl-style-switcher@latest/dist/map-gl-style-switcher.css">
|
|
69
|
+
</head>
|
|
70
|
+
<body>
|
|
71
|
+
<div id="map" style="width: 100%; height: 100vh;"></div>
|
|
72
|
+
|
|
73
|
+
<!-- MapLibre GL JS -->
|
|
74
|
+
<script src="https://unpkg.com/maplibre-gl@4/dist/maplibre-gl.js"></script>
|
|
75
|
+
|
|
76
|
+
<!-- Style Switcher UMD -->
|
|
77
|
+
<script src="https://unpkg.com/map-gl-style-switcher@latest/dist/index.umd.js"></script>
|
|
78
|
+
|
|
79
|
+
<script>
|
|
80
|
+
// StyleSwitcherControl is available globally as MapGLStyleSwitcher.StyleSwitcherControl
|
|
81
|
+
const { StyleSwitcherControl } = MapGLStyleSwitcher;
|
|
82
|
+
|
|
83
|
+
const styles = [
|
|
84
|
+
{
|
|
85
|
+
id: 'voyager',
|
|
86
|
+
name: 'Voyager',
|
|
87
|
+
image: 'https://unpkg.com/map-gl-style-switcher@latest/public/voyager.png',
|
|
88
|
+
styleUrl: 'https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json',
|
|
89
|
+
description: 'Voyager style from Carto',
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
id: 'positron',
|
|
93
|
+
name: 'Positron',
|
|
94
|
+
image: 'https://unpkg.com/map-gl-style-switcher@latest/public/positron.png',
|
|
95
|
+
styleUrl: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
|
|
96
|
+
description: 'Positron style from Carto',
|
|
97
|
+
}
|
|
98
|
+
];
|
|
99
|
+
|
|
100
|
+
const map = new maplibregl.Map({
|
|
101
|
+
container: 'map',
|
|
102
|
+
style: styles[0].styleUrl,
|
|
103
|
+
center: [0, 0],
|
|
104
|
+
zoom: 2
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const styleSwitcher = new StyleSwitcherControl({
|
|
108
|
+
styles: styles,
|
|
109
|
+
theme: 'auto',
|
|
110
|
+
activeStyleId: styles[0].id,
|
|
111
|
+
onAfterStyleChange: (from, to) => {
|
|
112
|
+
map.setStyle(to.styleUrl);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
map.addControl(styleSwitcher, 'bottom-left');
|
|
117
|
+
</script>
|
|
118
|
+
</body>
|
|
119
|
+
</html>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### jsDelivr CDN
|
|
123
|
+
|
|
124
|
+
```html
|
|
125
|
+
<!DOCTYPE html>
|
|
126
|
+
<html>
|
|
127
|
+
<head>
|
|
128
|
+
<!-- MapLibre GL CSS -->
|
|
129
|
+
<link href="https://cdn.jsdelivr.net/npm/maplibre-gl@4/dist/maplibre-gl.css" rel="stylesheet" />
|
|
130
|
+
|
|
131
|
+
<!-- Style Switcher CSS -->
|
|
132
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/map-gl-style-switcher@latest/dist/map-gl-style-switcher.css">
|
|
133
|
+
</head>
|
|
134
|
+
<body>
|
|
135
|
+
<div id="map" style="width: 100%; height: 100vh;"></div>
|
|
136
|
+
|
|
137
|
+
<!-- MapLibre GL JS -->
|
|
138
|
+
<script src="https://cdn.jsdelivr.net/npm/maplibre-gl@4/dist/maplibre-gl.js"></script>
|
|
139
|
+
|
|
140
|
+
<!-- Style Switcher UMD -->
|
|
141
|
+
<script src="https://cdn.jsdelivr.net/npm/map-gl-style-switcher@latest/dist/index.umd.js"></script>
|
|
142
|
+
|
|
143
|
+
<script>
|
|
144
|
+
// Same JavaScript code as above
|
|
145
|
+
const { StyleSwitcherControl } = MapGLStyleSwitcher;
|
|
146
|
+
// ... rest of the code
|
|
147
|
+
</script>
|
|
148
|
+
</body>
|
|
149
|
+
</html>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### ES Modules from CDN
|
|
153
|
+
|
|
154
|
+
For modern browsers that support ES modules:
|
|
155
|
+
|
|
156
|
+
```html
|
|
157
|
+
<script type="module">
|
|
158
|
+
import { StyleSwitcherControl } from 'https://unpkg.com/map-gl-style-switcher@latest/dist/index.js';
|
|
159
|
+
|
|
160
|
+
// Your code here
|
|
161
|
+
const styleSwitcher = new StyleSwitcherControl({
|
|
162
|
+
styles: styles,
|
|
163
|
+
theme: 'auto'
|
|
164
|
+
});
|
|
165
|
+
</script>
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Specific Version
|
|
169
|
+
|
|
170
|
+
To use a specific version instead of `@latest`:
|
|
171
|
+
|
|
172
|
+
```html
|
|
173
|
+
<!-- Replace @latest with specific version, e.g., @0.7.2 -->
|
|
174
|
+
<link rel="stylesheet" href="https://unpkg.com/map-gl-style-switcher@0.7.2/dist/map-gl-style-switcher.css">
|
|
175
|
+
<script src="https://unpkg.com/map-gl-style-switcher@0.7.2/dist/index.umd.js"></script>
|
|
176
|
+
```
|
|
177
|
+
|
|
52
178
|
## Usage
|
|
53
179
|
|
|
54
180
|
### Basic MapLibre GL Integration
|
|
@@ -85,14 +211,16 @@ const styles = [
|
|
|
85
211
|
id: 'arcgis-hybrid',
|
|
86
212
|
name: 'ArcGIS Hybrid',
|
|
87
213
|
image: './arcgis-hybrid.png',
|
|
88
|
-
styleUrl:
|
|
214
|
+
styleUrl:
|
|
215
|
+
'https://raw.githubusercontent.com/go2garret/maps/main/src/assets/json/arcgis_hybrid.json',
|
|
89
216
|
description: 'Hybrid Satellite style from ESRI',
|
|
90
217
|
},
|
|
91
218
|
{
|
|
92
219
|
id: 'osm',
|
|
93
220
|
name: 'OSM',
|
|
94
221
|
image: './osm.png',
|
|
95
|
-
styleUrl:
|
|
222
|
+
styleUrl:
|
|
223
|
+
'https://raw.githubusercontent.com/go2garret/maps/main/src/assets/json/openStreetMap.json',
|
|
96
224
|
description: 'OSM style',
|
|
97
225
|
},
|
|
98
226
|
];
|
|
@@ -125,11 +253,7 @@ map.addControl(styleSwitcher, 'bottom-left');
|
|
|
125
253
|
|
|
126
254
|
### React Integration with react-map-gl
|
|
127
255
|
|
|
128
|
-
For React applications using `react-map-gl`,
|
|
129
|
-
|
|
130
|
-
#### Using the Built-in MapGLStyleSwitcher Component (Recommended)
|
|
131
|
-
|
|
132
|
-
This package provides a ready-to-use `MapGLStyleSwitcher` component:
|
|
256
|
+
For React applications using `react-map-gl`, This package provides a ready-to-use `MapGLStyleSwitcher` component:
|
|
133
257
|
|
|
134
258
|
```tsx
|
|
135
259
|
import React, { useState } from 'react';
|
|
@@ -163,14 +287,16 @@ const styles = [
|
|
|
163
287
|
id: 'arcgis-hybrid',
|
|
164
288
|
name: 'ArcGIS Hybrid',
|
|
165
289
|
image: './arcgis-hybrid.png',
|
|
166
|
-
styleUrl:
|
|
290
|
+
styleUrl:
|
|
291
|
+
'https://raw.githubusercontent.com/go2garret/maps/main/src/assets/json/arcgis_hybrid.json',
|
|
167
292
|
description: 'Hybrid Satellite style from ESRI',
|
|
168
293
|
},
|
|
169
294
|
{
|
|
170
295
|
id: 'osm',
|
|
171
296
|
name: 'OSM',
|
|
172
297
|
image: './osm.png',
|
|
173
|
-
styleUrl:
|
|
298
|
+
styleUrl:
|
|
299
|
+
'https://raw.githubusercontent.com/go2garret/maps/main/src/assets/json/openStreetMap.json',
|
|
174
300
|
description: 'OSM style',
|
|
175
301
|
},
|
|
176
302
|
];
|
|
@@ -184,7 +310,7 @@ export const MapComponent = () => {
|
|
|
184
310
|
initialViewState={{
|
|
185
311
|
longitude: 0,
|
|
186
312
|
latitude: 0,
|
|
187
|
-
zoom: 2
|
|
313
|
+
zoom: 2,
|
|
188
314
|
}}
|
|
189
315
|
style={{ width: '100%', height: '100vh' }}
|
|
190
316
|
mapStyle={mapStyle}
|
|
@@ -213,17 +339,21 @@ npm install react-map-gl maplibre-gl map-gl-style-switcher
|
|
|
213
339
|
|
|
214
340
|
```tsx
|
|
215
341
|
interface MapGLStyleSwitcherProps {
|
|
216
|
-
styles: StyleItem[];
|
|
217
|
-
activeStyleId?: string;
|
|
218
|
-
theme?: 'light' | 'dark' | 'auto';
|
|
219
|
-
showLabels?: boolean;
|
|
220
|
-
showImages?: boolean;
|
|
221
|
-
position?:
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
342
|
+
styles: StyleItem[]; // Array of map styles (required)
|
|
343
|
+
activeStyleId?: string; // Currently active style ID
|
|
344
|
+
theme?: 'light' | 'dark' | 'auto'; // UI theme (default: 'light')
|
|
345
|
+
showLabels?: boolean; // Show style names (default: true)
|
|
346
|
+
showImages?: boolean; // Show style thumbnails (default: true)
|
|
347
|
+
position?:
|
|
348
|
+
| 'top-left'
|
|
349
|
+
| 'top-right' // Control position (default: 'bottom-left')
|
|
350
|
+
| 'bottom-left'
|
|
351
|
+
| 'bottom-right';
|
|
352
|
+
animationDuration?: number; // Animation duration in ms (default: 200)
|
|
353
|
+
maxHeight?: number; // Max height of expanded list (default: 300)
|
|
354
|
+
rtl?: boolean; // Enable RTL layout (default: false)
|
|
355
|
+
classNames?: Partial<{
|
|
356
|
+
// Custom CSS classes
|
|
227
357
|
container: string;
|
|
228
358
|
list: string;
|
|
229
359
|
item: string;
|
|
@@ -232,9 +362,9 @@ interface MapGLStyleSwitcherProps {
|
|
|
232
362
|
dark: string;
|
|
233
363
|
light: string;
|
|
234
364
|
}>;
|
|
235
|
-
onBeforeStyleChange?: (from: StyleItem, to: StyleItem) => void;
|
|
236
|
-
onAfterStyleChange?: (from: StyleItem, to: StyleItem) => void;
|
|
237
|
-
onStyleChange?: (styleUrl: string) => void;
|
|
365
|
+
onBeforeStyleChange?: (from: StyleItem, to: StyleItem) => void; // Callback before style change
|
|
366
|
+
onAfterStyleChange?: (from: StyleItem, to: StyleItem) => void; // Callback after style change
|
|
367
|
+
onStyleChange?: (styleUrl: string) => void; // Simplified callback for style URL
|
|
238
368
|
}
|
|
239
369
|
```
|
|
240
370
|
|
|
@@ -291,8 +421,9 @@ npm run dev
|
|
|
291
421
|
```
|
|
292
422
|
|
|
293
423
|
This example demonstrates:
|
|
424
|
+
|
|
294
425
|
- React 19 with TypeScript and Vite 7
|
|
295
|
-
- MapLibre GL integration with react-map-gl
|
|
426
|
+
- MapLibre GL integration with react-map-gl
|
|
296
427
|
- MapGLStyleSwitcher component usage
|
|
297
428
|
- Multiple basemap styles with thumbnails
|
|
298
429
|
- Responsive design with auto theme detection
|
|
@@ -310,10 +441,12 @@ npm run dev
|
|
|
310
441
|
```
|
|
311
442
|
|
|
312
443
|
This example shows:
|
|
444
|
+
|
|
313
445
|
- Pure TypeScript/JavaScript implementation
|
|
314
446
|
- MapLibre GL integration
|
|
315
447
|
- StyleSwitcherControl direct usage
|
|
316
448
|
- Multiple themes and configuration options
|
|
449
|
+
|
|
317
450
|
## Available Styles
|
|
318
451
|
|
|
319
452
|

|
|
@@ -321,15 +454,18 @@ This example shows:
|
|
|
321
454
|
The style switcher supports various map styles. Here are some popular options you can use:
|
|
322
455
|
|
|
323
456
|
### Carto Basemaps
|
|
457
|
+
|
|
324
458
|
- **Voyager** - A balanced, colorful style perfect for data visualization and general mapping applications
|
|
325
459
|
- **Positron** - A clean, minimal light basemap ideal for overlaying data with maximum contrast
|
|
326
460
|
- **Dark Matter** - A dark theme basemap excellent for creating striking data visualizations and night mode interfaces
|
|
327
461
|
|
|
328
462
|
### Satellite & Hybrid
|
|
463
|
+
|
|
329
464
|
- **ArcGIS Hybrid** - Combines satellite imagery with street labels, perfect for geographic context and navigation
|
|
330
465
|
- **Satellite** - High-resolution satellite imagery for detailed geographic analysis
|
|
331
466
|
|
|
332
467
|
### OpenStreetMap
|
|
468
|
+
|
|
333
469
|
- **OSM (OpenStreetMap)** - Community-driven open-source mapping with detailed street-level information
|
|
334
470
|
|
|
335
471
|
### Example Styles Configuration
|
|
@@ -345,7 +481,7 @@ const styles = [
|
|
|
345
481
|
},
|
|
346
482
|
{
|
|
347
483
|
id: 'positron',
|
|
348
|
-
name: 'Positron',
|
|
484
|
+
name: 'Positron',
|
|
349
485
|
image: './positron.png',
|
|
350
486
|
styleUrl: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
|
|
351
487
|
description: 'Positron style from Carto',
|
|
@@ -361,14 +497,16 @@ const styles = [
|
|
|
361
497
|
id: 'arcgis-hybrid',
|
|
362
498
|
name: 'ArcGIS Hybrid',
|
|
363
499
|
image: './arcgis-hybrid.png',
|
|
364
|
-
styleUrl:
|
|
500
|
+
styleUrl:
|
|
501
|
+
'https://raw.githubusercontent.com/go2garret/maps/main/src/assets/json/arcgis_hybrid.json',
|
|
365
502
|
description: 'Hybrid Satellite style from ESRI',
|
|
366
503
|
},
|
|
367
504
|
{
|
|
368
505
|
id: 'osm',
|
|
369
506
|
name: 'OSM',
|
|
370
507
|
image: './osm.png',
|
|
371
|
-
styleUrl:
|
|
508
|
+
styleUrl:
|
|
509
|
+
'https://raw.githubusercontent.com/go2garret/maps/main/src/assets/json/openStreetMap.json',
|
|
372
510
|
description: 'OSM style',
|
|
373
511
|
},
|
|
374
512
|
];
|
|
@@ -412,7 +550,7 @@ interface StyleSwitcherClassNames {
|
|
|
412
550
|
}
|
|
413
551
|
```
|
|
414
552
|
|
|
415
|
-
|
|
553
|
+
_Example of different map styles that can be used with the style switcher_
|
|
416
554
|
|
|
417
555
|
### Option Details
|
|
418
556
|
|
|
@@ -569,7 +707,6 @@ We welcome contributions! Please feel free to submit a Pull Request. For major c
|
|
|
569
707
|
```
|
|
570
708
|
|
|
571
709
|
4. **Make your changes**
|
|
572
|
-
|
|
573
710
|
- Follow TypeScript best practices
|
|
574
711
|
- Maintain backward compatibility when possible
|
|
575
712
|
- Add tests for new features
|
|
@@ -1 +1,195 @@
|
|
|
1
|
-
|
|
1
|
+
/* Override MapLibre GL and Mapbox GL control styles for style switcher */
|
|
2
|
+
.maplibregl-ctrl.style-switcher,
|
|
3
|
+
.mapboxgl-ctrl.style-switcher {
|
|
4
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
|
|
5
|
+
background: #fff;
|
|
6
|
+
border-radius: 6px;
|
|
7
|
+
padding: 4px;
|
|
8
|
+
margin: 8px;
|
|
9
|
+
transition: box-shadow 0.2s;
|
|
10
|
+
min-width: unset;
|
|
11
|
+
width: auto;
|
|
12
|
+
user-select: none;
|
|
13
|
+
cursor: pointer;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/* RTL support */
|
|
17
|
+
[dir='rtl'] .maplibregl-ctrl.style-switcher,
|
|
18
|
+
[dir='rtl'] .mapboxgl-ctrl.style-switcher,
|
|
19
|
+
.maplibregl-ctrl.style-switcher[dir='rtl'],
|
|
20
|
+
.mapboxgl-ctrl.style-switcher[dir='rtl'] {
|
|
21
|
+
direction: rtl;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* Theme variants */
|
|
25
|
+
.maplibregl-ctrl.style-switcher.style-switcher-dark,
|
|
26
|
+
.mapboxgl-ctrl.style-switcher.style-switcher-dark {
|
|
27
|
+
background: #2a2a2a;
|
|
28
|
+
color: #fff;
|
|
29
|
+
border: 1px solid #444;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.maplibregl-ctrl.style-switcher.style-switcher-light,
|
|
33
|
+
.mapboxgl-ctrl.style-switcher.style-switcher-light {
|
|
34
|
+
background: #ffffff;
|
|
35
|
+
color: #333;
|
|
36
|
+
border: 1px solid #ddd;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* List container */
|
|
40
|
+
.style-switcher-list {
|
|
41
|
+
display: flex;
|
|
42
|
+
flex-direction: column;
|
|
43
|
+
gap: 4px;
|
|
44
|
+
padding: 4px 0px;
|
|
45
|
+
max-height: 300px;
|
|
46
|
+
overflow-y: auto;
|
|
47
|
+
overflow-x: hidden;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* RTL support for list */
|
|
51
|
+
[dir='rtl'] .style-switcher-list,
|
|
52
|
+
.style-switcher-list[dir='rtl'] {
|
|
53
|
+
direction: rtl;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* Individual style items */
|
|
57
|
+
.style-switcher-item {
|
|
58
|
+
display: flex;
|
|
59
|
+
align-items: center;
|
|
60
|
+
gap: 6px;
|
|
61
|
+
cursor: pointer;
|
|
62
|
+
padding: 2px 4px;
|
|
63
|
+
border-radius: 4px;
|
|
64
|
+
transition: all 0.2s ease;
|
|
65
|
+
border: 2px solid transparent;
|
|
66
|
+
position: relative;
|
|
67
|
+
overflow: hidden;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.style-switcher-item:hover {
|
|
71
|
+
background: #f0f8ff;
|
|
72
|
+
transform: translateY(-1px);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.style-switcher-item.selected {
|
|
76
|
+
background: #e6f0ff;
|
|
77
|
+
font-weight: 600;
|
|
78
|
+
border: 1px solid #0066cc;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* When labels are hidden, shrink items to image size only */
|
|
82
|
+
.style-switcher-item:not(:has(span)) {
|
|
83
|
+
min-width: unset;
|
|
84
|
+
width: 40px;
|
|
85
|
+
justify-content: center;
|
|
86
|
+
padding-left: 0;
|
|
87
|
+
padding-right: 0;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* Hide label span if showLabels is false (for safety) */
|
|
91
|
+
.style-switcher-item.hide-label span {
|
|
92
|
+
display: none !important;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/* Dark theme item styles */
|
|
96
|
+
.maplibregl-ctrl.style-switcher.style-switcher-dark .style-switcher-item:hover,
|
|
97
|
+
.mapboxgl-ctrl.style-switcher.style-switcher-dark .style-switcher-item:hover {
|
|
98
|
+
background: #333;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.maplibregl-ctrl.style-switcher.style-switcher-dark
|
|
102
|
+
.style-switcher-item.selected,
|
|
103
|
+
.mapboxgl-ctrl.style-switcher.style-switcher-dark
|
|
104
|
+
.style-switcher-item.selected {
|
|
105
|
+
background: #404040;
|
|
106
|
+
border-color: #666;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* Image styles */
|
|
110
|
+
.style-switcher-item img {
|
|
111
|
+
width: 32px;
|
|
112
|
+
height: 32px;
|
|
113
|
+
object-fit: cover;
|
|
114
|
+
border-radius: 2px;
|
|
115
|
+
background: #f0f0f0;
|
|
116
|
+
border: 1px solid #ddd;
|
|
117
|
+
flex-shrink: 0;
|
|
118
|
+
transition: all 0.2s ease;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* Image styles - dark theme */
|
|
122
|
+
.maplibregl-ctrl.style-switcher.style-switcher-dark .style-switcher-item img,
|
|
123
|
+
.mapboxgl-ctrl.style-switcher.style-switcher-dark .style-switcher-item img {
|
|
124
|
+
background: #555;
|
|
125
|
+
border-color: #666;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* Text styles */
|
|
129
|
+
.style-switcher-item span {
|
|
130
|
+
font-size: 14px;
|
|
131
|
+
line-height: 1.2;
|
|
132
|
+
white-space: nowrap;
|
|
133
|
+
overflow: hidden;
|
|
134
|
+
text-overflow: ellipsis;
|
|
135
|
+
flex: 1;
|
|
136
|
+
min-width: 0;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* Accessibility improvements */
|
|
140
|
+
.maplibregl-ctrl.style-switcher:focus,
|
|
141
|
+
.mapboxgl-ctrl.style-switcher:focus {
|
|
142
|
+
outline: 2px solid #0066cc;
|
|
143
|
+
outline-offset: 1px;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.style-switcher-item:focus {
|
|
147
|
+
outline: 2px solid #0066cc;
|
|
148
|
+
outline-offset: 1px;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/* Animation for expand/collapse */
|
|
152
|
+
.style-switcher-list {
|
|
153
|
+
animation: fadeIn 0.2s ease-in-out;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
@keyframes fadeIn {
|
|
157
|
+
from {
|
|
158
|
+
opacity: 0;
|
|
159
|
+
transform: translateY(-10px);
|
|
160
|
+
}
|
|
161
|
+
to {
|
|
162
|
+
opacity: 1;
|
|
163
|
+
transform: translateY(0);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* Scrollbar styling */
|
|
168
|
+
.style-switcher-list::-webkit-scrollbar {
|
|
169
|
+
width: 4px;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.style-switcher-list::-webkit-scrollbar-track {
|
|
173
|
+
background: #f0f0f0;
|
|
174
|
+
border-radius: 2px;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.style-switcher-list::-webkit-scrollbar-thumb {
|
|
178
|
+
background: #ccc;
|
|
179
|
+
border-radius: 2px;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* Scrollbar styling - dark theme */
|
|
183
|
+
.maplibregl-ctrl.style-switcher.style-switcher-dark
|
|
184
|
+
.style-switcher-list::-webkit-scrollbar-track,
|
|
185
|
+
.mapboxgl-ctrl.style-switcher.style-switcher-dark
|
|
186
|
+
.style-switcher-list::-webkit-scrollbar-track {
|
|
187
|
+
background: #2a2a2a;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.maplibregl-ctrl.style-switcher.style-switcher-dark
|
|
191
|
+
.style-switcher-list::-webkit-scrollbar-thumb,
|
|
192
|
+
.mapboxgl-ctrl.style-switcher.style-switcher-dark
|
|
193
|
+
.style-switcher-list::-webkit-scrollbar-thumb {
|
|
194
|
+
background: #555;
|
|
195
|
+
}
|