feature: Set up contact info block and map
Deploy to Dreamhost (dev) / build (push) Successful in 34s
Sync TODOs with Issues / sync_todos (push) Successful in 7s

This commit is contained in:
Keith Solomon
2026-07-04 19:22:26 -05:00
parent 23ef7388eb
commit 01c6fb7831
12 changed files with 3853 additions and 3423 deletions
+2346 -3384
View File
File diff suppressed because it is too large Load Diff
+98
View File
@@ -0,0 +1,98 @@
/**
* Contact Info map module.
*/
const MAP_SELECTOR = '.contact-info__map[data-lat][data-lng]';
const DEFAULT_ZOOM = 14;
const MARKER_SIZE = [62, 68];
let leafletModulePromise;
function loadLeaflet() {
if (!leafletModulePromise) {
leafletModulePromise = import('https://unpkg.com/leaflet@1.9.4/dist/leaflet-src.esm.js');
}
return leafletModulePromise;
}
function toFloat(value) {
const parsed = Number.parseFloat(value);
return Number.isFinite(parsed) ? parsed : null;
}
export async function initContactInfoMap() {
const mapContainers = document.querySelectorAll(MAP_SELECTOR);
if (!mapContainers.length) {
return;
}
let Leaflet;
try {
const module = await loadLeaflet();
Leaflet = module.default || module;
} catch (error) {
console.error('Leaflet failed to load for contact map.', error);
return;
}
mapContainers.forEach((container) => {
if (container.dataset.mapReady === 'true') {
return;
}
const latitude = toFloat(container.dataset.lat);
const longitude = toFloat(container.dataset.lng);
const zoom = toFloat(container.dataset.zoom) || DEFAULT_ZOOM;
if (latitude === null || longitude === null) {
return;
}
const map = Leaflet.map(container, {
zoomControl: false,
scrollWheelZoom: false,
dragging: false,
doubleClickZoom: false,
boxZoom: false,
keyboard: false,
tap: false,
attributionControl: true,
}).setView([latitude, longitude], zoom);
Leaflet.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
maxZoom: 19,
subdomains: 'abcd',
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>'
}).addTo(map);
const markerSvg = container.dataset.markerSvg;
const markerIcon = markerSvg
? Leaflet.divIcon({
className: 'contact-info__leaflet-pin',
html: markerSvg,
iconSize: MARKER_SIZE,
iconAnchor: [MARKER_SIZE[0] / 2, MARKER_SIZE[1]],
})
: Leaflet.icon({
iconUrl: container.dataset.marker || '',
iconSize: MARKER_SIZE,
iconAnchor: [MARKER_SIZE[0] / 2, MARKER_SIZE[1]],
popupAnchor: [0, -MARKER_SIZE[1] + 8],
className: 'contact-info__leaflet-pin'
});
const marker = Leaflet.marker([latitude, longitude], { icon: markerIcon }).addTo(map);
const popupText = container.dataset.popup;
if (popupText) {
marker.bindPopup(popupText);
}
container.dataset.mapReady = 'true';
});
}
+4
View File
@@ -8,6 +8,7 @@ import GetHeaderHeight from './modules/GetHeaderHeight.js';
import tagExternalLinks from './modules/TagExternalLinks.js';
import Navigation from './modules/Navigation.js';
import initRecentPostsCarousels from './modules/RecentPostsCarousel.js';
import { initContactInfoMap } from './modules/ContactInfoMap.js';
// Add passive event listeners
! function (e) {
@@ -72,6 +73,9 @@ document.addEventListener('DOMContentLoaded', () => {
// Initialize mobile Recent Insights carousels.
initRecentPostsCarousels();
// Initialize Contact Info Leaflet maps.
initContactInfoMap();
// Add Back to Top button to body
// const backToTop = document.createElement('x-back-to-top');
// document.body.appendChild(backToTop);