MapView
MoleculeLeaflet-based interactive map. Tooltip-enabled markers, predefined zones (polygon), route lines (polyline), and click-to-add marker mode.
<%- include('modules/ui/MapView/MapView', {
center: [41.015, 28.979],
zoom: 6,
height: 400,
markers: CITIES,
zones: ZONES,
routes: ROUTES,
}) %>
<%- include('modules/ui/MapView/MapView', {
center: [39.5, 35.0],
zoom: 5,
height: 360,
}) %>
<%- include('modules/ui/MapView/MapView', {
center: [39.5, 35.0],
zoom: 5,
height: 360,
zones: ZONES,
routes: ROUTES,
}) %>
<%
// MapView — provider-agnostic interactive map (EJS).
// Mirror of NextJS modules/ui/MapView/index.tsx.
//
// M1: leaflet provider, token-aware CartoDB tiles (Voyager / Dark Matter),
// IntersectionObserver-driven lazy load, fit-to-bounds.
//
// Locals:
// id — DOM id base (auto-generated when omitted)
// provider — 'leaflet' | 'mapbox' | 'google' (default 'leaflet')
// center, zoom — view start
// markers, zones, routes
// fitBoundsPadding — number → enables fit-to-bounds
// height — px or CSS string
// className — extra root classes
//
// TODO M1+: providers/mapbox + google adapters.
// TODO M2: cluster, hover popup, activeMarkerId, custom marker icons.
// TODO M3: search, geocode, route.
// TODO M4: draw, locate, layer toggle.
// TODO M5: a11y polish, i18n messages, telemetry.
var _id = locals.id || ('map-' + Math.random().toString(36).substr(2, 9));
var _provider = locals.provider || 'leaflet';
var _center = locals.center || [39.9334, 32.8597];
var _zoom = locals.zoom || 6;
var _height = locals.height || 480;
var _markers = locals.markers || [];
var _zones = locals.zones || [];
var _routes = locals.routes || [];
var _fitBoundsPadding = locals.fitBoundsPadding;
var _cls = locals.className || '';
if (_provider !== 'leaflet') {
throw new Error('MapView provider "' + _provider + '" is not yet implemented — TODO M1+');
}
// Button base classes — kept in sync with Button.ejs `xs` size + primary/outline variants.
var btnBase = 'inline-flex items-center justify-center gap-2 rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus disabled:opacity-50 disabled:cursor-not-allowed px-2 py-1 text-xs';
var btnPrimary = 'bg-primary text-primary-fg hover:bg-primary-hover';
var btnOutline = 'border border-border text-text-primary hover:bg-surface-overlay';
// CSS height
var _cssHeight = (typeof _height === 'number') ? (_height + 'px') : _height;
%>
<%/*
Inline Card(variant="raised") wrapper with -mx-6 -my-4 cancel-padding inner
so toolbar + map render edge-to-edge inside Card's rounded border.
*/%>
<%- include('./partials/_controls', {
_id: _id,
_zones: _zones,
_routes: _routes,
btnBase: btnBase,
btnPrimary: btnPrimary,
btnOutline: btnOutline
}) %>