feat(dees-geo-map): Add dark/light theme support for UI and map tiles, subscribe to theme changes and add traffic toggle in navigation

This commit is contained in:
2026-02-05 16:50:51 +00:00
parent 32454a7d19
commit 54999a52b7
6 changed files with 275 additions and 133 deletions

View File

@@ -8,6 +8,7 @@ import {
type TemplateResult,
cssManager,
css,
domtools,
} from '@design.estate/dees-element';
import { DeesContextmenu } from '@design.estate/dees-catalog';
import { geoComponentStyles, mapContainerStyles, toolbarStyles, searchStyles, navigationStyles, trafficStyles, headerToolbarStyles } from '../../00componentstyles.js';
@@ -175,41 +176,63 @@ export class DeesGeoMap extends DeesElement {
.maplibregl-ctrl-attrib {
font-size: 11px;
background: rgba(0, 0, 0, 0.5);
color: rgba(255, 255, 255, 0.8);
background: ${cssManager.bdTheme('rgba(255, 255, 255, 0.8)', 'rgba(0, 0, 0, 0.5)')};
color: ${cssManager.bdTheme('rgba(0, 0, 0, 0.7)', 'rgba(255, 255, 255, 0.8)')};
padding: 2px 6px;
border-radius: 4px;
}
.maplibregl-ctrl-attrib a {
color: rgba(255, 255, 255, 0.8);
color: ${cssManager.bdTheme('rgba(0, 0, 0, 0.7)', 'rgba(255, 255, 255, 0.8)')};
}
.feature-count {
padding: 6px 12px;
background: rgba(30, 30, 30, 0.9);
border: 1px solid rgba(255, 255, 255, 0.1);
background: ${cssManager.bdTheme('rgba(255, 255, 255, 0.95)', 'rgba(30, 30, 30, 0.9)')};
border: 1px solid ${cssManager.bdTheme('rgba(0, 0, 0, 0.1)', 'rgba(255, 255, 255, 0.1)')};
border-radius: 6px;
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
font-size: 12px;
color: rgba(255, 255, 255, 0.7);
color: ${cssManager.bdTheme('rgba(0, 0, 0, 0.6)', 'rgba(255, 255, 255, 0.7)')};
}
`,
];
// Map theme subscription for cleanup
private mapThemeSubscription: { unsubscribe: () => void } | null = null;
// ─── Lifecycle ──────────────────────────────────────────────────────────────
public async firstUpdated() {
this.initializeControllers();
await this.initializeMap();
// Subscribe to theme changes to update map style
this.subscribeToThemeChanges();
}
public async disconnectedCallback() {
await super.disconnectedCallback();
if (this.mapThemeSubscription) {
this.mapThemeSubscription.unsubscribe();
this.mapThemeSubscription = null;
}
this.cleanup();
}
/**
* Subscribe to theme changes via domtools
*/
private async subscribeToThemeChanges(): Promise<void> {
const domtoolsInstance = await domtools.DomTools.setupDomTools();
this.mapThemeSubscription = domtoolsInstance.themeManager.themeObservable.subscribe(
(_goBright: boolean) => {
this.updateMapStyleForTheme();
}
);
}
public updated(changedProperties: Map<string, unknown>) {
super.updated(changedProperties);
if (changedProperties.has('dragToDraw') && this.draw && this.map) {
@@ -293,11 +316,21 @@ export class DeesGeoMap extends DeesElement {
getMap: () => this.map,
// Connect traffic controller for traffic-aware routing
getTrafficRoute: async (start, end, mode) => {
if (this.trafficController?.supportsTrafficRouting()) {
if (this.showTraffic && this.trafficController?.supportsTrafficRouting()) {
return this.trafficController.fetchRouteWithTraffic(start, end, mode);
}
return null;
},
// Traffic toggle callbacks
onTrafficToggle: (enabled) => {
if (enabled) {
this.trafficController?.enable();
} else {
this.trafficController?.disable();
}
this.showTraffic = enabled;
},
getTrafficEnabled: () => this.showTraffic,
});
this.navigationController.navigationMode = this.navigationMode;
@@ -377,30 +410,30 @@ export class DeesGeoMap extends DeesElement {
private getMapStyle(): maplibregl.StyleSpecification | string {
if (this.mapStyle === 'osm') {
return {
version: 8,
sources: {
'osm-tiles': {
type: 'raster',
tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
tileSize: 256,
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
},
},
layers: [
{
id: 'osm-tiles',
type: 'raster',
source: 'osm-tiles',
minzoom: 0,
maxzoom: 19,
},
],
};
// Check current theme and use appropriate tiles
const isDarkTheme = !cssManager.goBright;
if (isDarkTheme) {
// CartoDB Dark Matter GL vector style - high quality dark theme
return 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json';
} else {
// CartoDB Voyager GL vector style - high quality light theme
return 'https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json';
}
}
return this.mapStyle;
}
/**
* Update the map style when theme changes
*/
private updateMapStyleForTheme(): void {
if (!this.map || !this.isMapReady || this.mapStyle !== 'osm') return;
const newStyle = this.getMapStyle();
this.map.setStyle(newStyle as maplibregl.StyleSpecification);
}
// ─── Terra Draw Initialization ──────────────────────────────────────────────
private initializeTerraDraw() {
@@ -934,9 +967,7 @@ export class DeesGeoMap extends DeesElement {
${renderIcon('polygon')}
</button>
` : ''}
${showTrafficControls && this.trafficController
? this.trafficController.render()
: ''}
${this.trafficController?.render()}
<div class="toolbar-divider"></div>
<button
class="tool-button"

View File

@@ -65,6 +65,10 @@ export interface INavigationControllerCallbacks {
end: [number, number],
mode: TNavigationMode
) => Promise<ITrafficAwareRoute | null>;
/** Optional callback when traffic toggle is changed */
onTrafficToggle?: (enabled: boolean) => void;
/** Optional callback to get current traffic state */
getTrafficEnabled?: () => boolean;
}
/**
@@ -832,6 +836,7 @@ export class NavigationController {
private renderPlanningView(extraClass?: string): TemplateResult {
const { isLoading, error, startPoint, endPoint } = this.navigationState;
const canCalculate = startPoint && endPoint && !isLoading;
const trafficEnabled = this.callbacks.getTrafficEnabled?.() ?? false;
return html`
<div class="navigation-panel ${extraClass || ''}">
@@ -864,6 +869,22 @@ export class NavigationController {
</button>
</div>
<div class="nav-traffic-toggle">
<div class="nav-traffic-toggle-label">
${renderIcon('traffic')}
<span>Traffic-aware routing</span>
</div>
<button
class="nav-traffic-toggle-btn ${trafficEnabled ? 'active' : ''}"
@click=${() => this.callbacks.onTrafficToggle?.(!trafficEnabled)}
title="${trafficEnabled ? 'Disable traffic' : 'Enable traffic'}"
>
<span class="toggle-track">
<span class="toggle-thumb"></span>
</span>
</button>
</div>
<div class="nav-inputs">
${this.renderNavInput('start', 'Start point', this.navStartSearchQuery, this.navStartSearchResults)}
${this.renderNavInput('end', 'End point', this.navEndSearchQuery, this.navEndSearchResults)}