# Project Hints - dees-catalog-geo ## Overview Geospatial web components library using MapLibre GL JS for map rendering and terra-draw for drawing capabilities. ## Key Dependencies - **maplibre-gl** (v5.x): WebGL-based vector map library - **terra-draw** (v1.24.0): Modern drawing library with support for multiple map libraries - **terra-draw-maplibre-gl-adapter** (v1.x): Adapter connecting terra-draw with MapLibre ## Component: dees-geo-map ### Properties | Property | Type | Default | Description | |----------|------|---------|-------------| | `center` | `[number, number]` | `[0, 0]` | Map center as [lng, lat] | | `zoom` | `number` | `2` | Initial zoom level | | `mapStyle` | `string` | `'osm'` | Map style ('osm' or custom URL) | | `activeTool` | `TDrawTool` | `'static'` | Active drawing tool | | `geoJson` | `GeoJSON.FeatureCollection` | `{...}` | Initial features | | `showToolbar` | `boolean` | `true` | Show/hide drawing toolbar | | `projection` | `'mercator' \| 'globe'` | `'mercator'` | Map projection type | | `showSearch` | `boolean` | `false` | Show address search input | | `showNavigation` | `boolean` | `false` | Show A-to-B navigation panel | | `navigationMode` | `'driving' \| 'walking' \| 'cycling'` | `'driving'` | Transport mode for routing | ### Drawing Tools (TDrawTool) - `point` - Draw points - `linestring` - Draw lines - `polygon` - Draw polygons - `rectangle` - Draw rectangles - `circle` - Draw circles - `freehand` - Freehand drawing - `select` - Select and edit features - `static` - Pan/zoom only (no drawing) ### Events - `map-ready` - Fired when map is initialized - `map-move` - Fired on pan/zoom with center and zoom - `draw-change` - Fired on any feature change - `draw-finish` - Fired when a shape is completed - `address-selected` - Fired when a search result is selected - `route-calculated` - Fired when a navigation route is calculated (includes route, startPoint, endPoint, mode) ### Public Methods - `getFeatures()` - Get all drawn features - `getGeoJson()` - Get features as FeatureCollection - `loadGeoJson(geojson)` - Load features from GeoJSON - `clearAllFeatures()` - Remove all features - `setTool(tool)` - Set active drawing tool - `flyTo(center, zoom?)` - Animate to location - `fitToFeatures(padding?)` - Fit view to all features - `setProjection(projection)` - Set map projection ('mercator' or 'globe') - `getMap()` - Get underlying MapLibre instance - `getTerraDraw()` - Get TerraDraw instance - `calculateRoute()` - Calculate route between start and end points - `setNavigationStart(coords, address?)` - Set navigation start point - `setNavigationEnd(coords, address?)` - Set navigation end point - `clearNavigation()` - Clear all navigation state ### Context Menu Right-click on the map to access a context menu with the following options: - **Drag to Draw** - Toggle between drag mode (click-drag for circles/rectangles) and two-click mode - **Globe View** - Toggle between globe (3D sphere) and Mercator (flat) projection - **Clear All Features** - Remove all drawn features from the map - **Fit to Features** - Zoom and pan to show all drawn features ### Navigation Feature The navigation panel (`showNavigation={true}`) provides A-to-B routing using OSRM (Open Source Routing Machine): - **Transport modes**: Driving, Walking, Cycling - **Point selection**: Type an address or click on the map - **Route display**: Blue line overlay with turn-by-turn directions - **API**: Uses free OSRM API (https://router.project-osrm.org) with fair-use rate limit ## Development - `pnpm install` - Install dependencies - `pnpm watch` - Start development server (port 3002) - `pnpm build` - Build for production ## File Structure ``` ts_web/ ├── index.ts # Main exports ├── 00_commitinfo_data.ts # Auto-generated └── elements/ ├── index.ts # Elements barrel ├── 00colors.ts # Color definitions ├── 00componentstyles.ts # Shared styles └── 00group-map/ ├── index.ts └── dees-geo-map/ ├── index.ts # Exports main + modules ├── dees-geo-map.ts # Main component (~550 lines) ├── dees-geo-map.demo.ts # Demo function ├── geo-map.icons.ts # Icon SVG definitions (~60 lines) ├── geo-map.search.ts # SearchController class (~180 lines) └── geo-map.navigation.ts # NavigationController class (~530 lines) ``` ## Modular Architecture The component was refactored for better maintainability: ### geo-map.icons.ts Contains all SVG icon definitions as a `GEO_MAP_ICONS` record and a `renderIcon(name)` helper function. ### geo-map.search.ts `SearchController` class encapsulating Nominatim geocoding search: - Reusable for standalone search or within navigation - Debounced API calls - Keyboard navigation support - Customizable via `ISearchControllerConfig` ### geo-map.navigation.ts `NavigationController` class for A-to-B routing: - OSRM routing API integration - Start/end point management with markers - Map click mode for point selection - Turn-by-turn directions rendering - Route overlay on map ### Usage of Controllers ```typescript // SearchController is reusable const search = new SearchController( { placeholder: 'Search...' }, { onResultSelected: (result, coords, zoom) => { /* handle */ }, onRequestUpdate: () => this.requestUpdate(), } ); // NavigationController manages all navigation state const nav = new NavigationController({ onRouteCalculated: (event) => { /* dispatch */ }, onRequestUpdate: () => this.requestUpdate(), getMap: () => this.map, }); ``` ## Notes - MapLibre CSS is loaded dynamically from CDN - Terra-draw requires the separate maplibre-gl-adapter package - The component uses Shadow DOM for style encapsulation ### Shadow DOM & Terra-Draw Drawing Fix Terra-draw's event listeners normally intercept map events through MapLibre's canvas element. In Shadow DOM contexts, these events are scoped locally and don't propagate correctly, causing terra-draw handlers to fail while MapLibre's drag handlers continue working. **Solution**: Manual drag coordination in `setTool()`: - When a drawing tool is active (`polygon`, `rectangle`, `point`, `linestring`, `circle`, `freehand`), MapLibre's `dragPan` and `dragRotate` are disabled - When `static` or `select` mode is active, dragging is re-enabled - The `TerraDrawMapLibreGLAdapter` does NOT accept a `lib` parameter - only `map` is required