stuff like that
This commit is contained in:
parent
0c0bb53915
commit
990475bcf3
@ -83,11 +83,14 @@ if (enablePlaygrounds) {
|
||||
I18nPlayground = React.lazy(() => import("./components/playground/I18nPlayground"));
|
||||
PlaygroundChat = React.lazy(() => import("./pages/PlaygroundChat"));
|
||||
|
||||
Tetris = React.lazy(() => import("./apps/tetris/Tetris"));
|
||||
FileBrowser = React.lazy(() => import("./apps/filebrowser/FileBrowser"));
|
||||
SupportChat = React.lazy(() => import("./pages/SupportChat"));
|
||||
}
|
||||
|
||||
|
||||
Tetris = React.lazy(() => import("./apps/tetris/Tetris"));
|
||||
FileBrowser = React.lazy(() => import("./apps/filebrowser/FileBrowser"));
|
||||
|
||||
|
||||
const VersionMap = React.lazy(() => import("./pages/VersionMap"));
|
||||
const UserCollections = React.lazy(() => import("./pages/UserCollections"));
|
||||
const Collections = React.lazy(() => import("./pages/Collections"));
|
||||
@ -202,8 +205,9 @@ const AppWrapper = () => {
|
||||
<Route path="/logs" element={<React.Suspense fallback={<div>Loading...</div>}><LogsPage /></React.Suspense>} />
|
||||
|
||||
{/* Apps */}
|
||||
{enablePlaygrounds && <Route path="/app/tetris" element={<React.Suspense fallback={<div>Loading...</div>}><Tetris /></React.Suspense>} />}
|
||||
{enablePlaygrounds && <Route path="/app/filebrowser/*" element={<React.Suspense fallback={<div>Loading...</div>}><FileBrowser /></React.Suspense>} />}
|
||||
<Route path="/app/tetris" element={<React.Suspense fallback={<div>Loading...</div>}><Tetris /></React.Suspense>} />
|
||||
<Route path="/app/filebrowser/*" element={<React.Suspense fallback={<div>Loading...</div>}><FileBrowser /></React.Suspense>} />
|
||||
{enablePlaygrounds && <Route path="/support-chat" element={<React.Suspense fallback={<div>Loading...</div>}><SupportChat /></React.Suspense>} />}
|
||||
|
||||
{/* Ecommerce Routes */}
|
||||
{(ecommerce) && (
|
||||
|
||||
@ -624,8 +624,8 @@ export const CompetitorsMapView: React.FC<CompetitorsMapViewProps> = ({ competit
|
||||
|
||||
{/* Map Viewport */}
|
||||
<div className="relative flex-1 min-h-0 w-full overflow-hidden">
|
||||
<div
|
||||
ref={mapContainer}
|
||||
<div
|
||||
ref={mapContainer}
|
||||
className="w-full h-full relative"
|
||||
/>
|
||||
|
||||
@ -660,7 +660,7 @@ export const CompetitorsMapView: React.FC<CompetitorsMapViewProps> = ({ competit
|
||||
pickerPolygons={pickerPolygons}
|
||||
posterTheme={posterTheme}
|
||||
setPosterTheme={setPosterTheme}
|
||||
onClose={onClosePosterMode || (() => {})}
|
||||
onClose={onClosePosterMode || (() => { })}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
|
||||
@ -39,7 +39,7 @@ export const InfoPanel: React.FC<InfoPanelProps> = ({ isOpen, onClose, lat, lng,
|
||||
setLoadingWiki(true);
|
||||
setErrorWiki(null);
|
||||
try {
|
||||
const apiUrl = import.meta.env.VITE_API_URL || 'http://localhost:3333';
|
||||
const apiUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL || '';
|
||||
const res = await fetch(`${apiUrl}/api/locations/wiki?lat=${lat}&lon=${lng}&limit=20`);
|
||||
if (res.ok) {
|
||||
const json = await res.json();
|
||||
@ -67,7 +67,7 @@ export const InfoPanel: React.FC<InfoPanelProps> = ({ isOpen, onClose, lat, lng,
|
||||
setLoadingLlm(true);
|
||||
setLlmInfo(null);
|
||||
try {
|
||||
const apiUrl = import.meta.env.VITE_API_URL || 'http://localhost:3333';
|
||||
const apiUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL || '';
|
||||
const res = await fetch(`${apiUrl}/api/locations/llm-info?location=${encodeURIComponent(locationName)}`);
|
||||
if (res.ok) {
|
||||
const json = await res.json();
|
||||
|
||||
@ -399,7 +399,7 @@ export const fetchReverseGeocode = async (lat: number, lon: number): Promise<any
|
||||
|
||||
export const fetchIpLocation = async (): Promise<any> => {
|
||||
return fetchWithDeduplication('ip-api-location', async () => {
|
||||
const res = await fetch('http://ip-api.com/json/');
|
||||
const res = await fetch('https://ipapi.co/json/');
|
||||
if (!res.ok) throw new Error(`Failed to fetch IP location: ${res.statusText}`);
|
||||
return await res.json();
|
||||
}, 600000); // 10 minutes cache
|
||||
|
||||
@ -7,7 +7,7 @@ const XIcon = ({ className }: { className?: string }) => (
|
||||
<svg className={className} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
|
||||
);
|
||||
const PaletteIcon = ({ className }: { className?: string }) => (
|
||||
<svg className={className} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="13.5" cy="6.5" r=".5" fill="currentColor"/><circle cx="17.5" cy="10.5" r=".5" fill="currentColor"/><circle cx="8.5" cy="7.5" r=".5" fill="currentColor"/><circle cx="6.5" cy="12.5" r=".5" fill="currentColor"/><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z"/></svg>
|
||||
<svg className={className} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="13.5" cy="6.5" r=".5" fill="currentColor" /><circle cx="17.5" cy="10.5" r=".5" fill="currentColor" /><circle cx="8.5" cy="7.5" r=".5" fill="currentColor" /><circle cx="6.5" cy="12.5" r=".5" fill="currentColor" /><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z" /></svg>
|
||||
);
|
||||
|
||||
interface MapPosterOverlayProps {
|
||||
@ -36,25 +36,25 @@ export function MapPosterOverlay({ map, pickerRegions, pickerPolygons, posterThe
|
||||
const c = map.getCenter();
|
||||
setCenter({ lat: c.lat, lng: c.lng });
|
||||
};
|
||||
|
||||
|
||||
const fetchGeo = async () => {
|
||||
const c = map.getCenter();
|
||||
try {
|
||||
const apiUrl = import.meta.env.VITE_API_URL || 'http://localhost:3333';
|
||||
const apiUrl = import.meta.env.VITE_SERVER_IMAGE_API_URL || '';
|
||||
const res = await fetch(`${apiUrl}/api/regions/reverse?lat=${c.lat}&lon=${c.lng}`);
|
||||
if (res.ok) {
|
||||
const json = await res.json();
|
||||
if (json.data) {
|
||||
const geo = json.data;
|
||||
let cty = geo.city && geo.city !== 'unknown' ? geo.city :
|
||||
geo.locality && geo.locality !== 'unknown' ? geo.locality :
|
||||
geo.principalSubdivision && geo.principalSubdivision !== 'unknown' ? geo.principalSubdivision : null;
|
||||
let cty = geo.city && geo.city !== 'unknown' ? geo.city :
|
||||
geo.locality && geo.locality !== 'unknown' ? geo.locality :
|
||||
geo.principalSubdivision && geo.principalSubdivision !== 'unknown' ? geo.principalSubdivision : null;
|
||||
let ctry = geo.countryName || null;
|
||||
if (cty && cty !== "unknown") setInferredCity(cty);
|
||||
if (ctry && ctry !== "unknown") setInferredCountry(ctry);
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
} catch (e) { }
|
||||
};
|
||||
|
||||
updateCenter();
|
||||
@ -62,8 +62,8 @@ export function MapPosterOverlay({ map, pickerRegions, pickerPolygons, posterThe
|
||||
|
||||
map.on('move', updateCenter);
|
||||
map.on('moveend', fetchGeo);
|
||||
|
||||
return () => {
|
||||
|
||||
return () => {
|
||||
map.off('move', updateCenter);
|
||||
map.off('moveend', fetchGeo);
|
||||
}
|
||||
@ -71,7 +71,7 @@ export function MapPosterOverlay({ map, pickerRegions, pickerPolygons, posterThe
|
||||
|
||||
let city = "CITY NAME";
|
||||
let country = "COUNTRY";
|
||||
|
||||
|
||||
if (pickerRegions && pickerRegions.length > 0) {
|
||||
const countryRegion = pickerRegions.find(r => r.level === 0);
|
||||
const cityRegion = pickerRegions.slice().reverse().find(r => r.level > 0);
|
||||
@ -90,7 +90,7 @@ export function MapPosterOverlay({ map, pickerRegions, pickerPolygons, posterThe
|
||||
};
|
||||
|
||||
const displayCity = city.toUpperCase().split('').join(' ');
|
||||
|
||||
|
||||
const gradientTop = `linear-gradient(to bottom, ${theme.gradient_color}FF 0%, ${theme.gradient_color}00 100%)`;
|
||||
const gradientBottom = `linear-gradient(to top, ${theme.gradient_color}FF 30%, ${theme.gradient_color}00 100%)`;
|
||||
|
||||
@ -103,12 +103,12 @@ export function MapPosterOverlay({ map, pickerRegions, pickerPolygons, posterThe
|
||||
const isDark = document.documentElement.classList.contains('dark');
|
||||
applyPosterTheme(map, theme, isDark);
|
||||
};
|
||||
|
||||
|
||||
if (map.isStyleLoaded()) _apply();
|
||||
|
||||
|
||||
map.on('style.load', _apply);
|
||||
map.on('styledata', _apply);
|
||||
|
||||
|
||||
return () => {
|
||||
map.off('style.load', _apply);
|
||||
map.off('styledata', _apply);
|
||||
@ -117,10 +117,10 @@ export function MapPosterOverlay({ map, pickerRegions, pickerPolygons, posterThe
|
||||
|
||||
useEffect(() => {
|
||||
if (!map || !pickerPolygons || pickerPolygons.length === 0) return;
|
||||
|
||||
|
||||
const combinedFeatures = pickerPolygons.flatMap(fc => fc.features || []);
|
||||
const fc = { type: 'FeatureCollection', features: combinedFeatures };
|
||||
|
||||
|
||||
if (!map.getSource('poster-gadm')) {
|
||||
map.addSource('poster-gadm', { type: 'geojson', data: fc as any });
|
||||
map.addLayer({
|
||||
@ -134,7 +134,7 @@ export function MapPosterOverlay({ map, pickerRegions, pickerPolygons, posterThe
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (showGadmBorders) {
|
||||
map.setLayoutProperty('poster-gadm-borders', 'visibility', 'visible');
|
||||
map.setPaintProperty('poster-gadm-borders', 'line-color', theme.text);
|
||||
@ -152,21 +152,21 @@ export function MapPosterOverlay({ map, pickerRegions, pickerPolygons, posterThe
|
||||
<div className="absolute inset-0 z-40 pointer-events-none flex flex-col justify-between overflow-hidden mix-blend-normal">
|
||||
{/* Top Gradient */}
|
||||
<div className="w-full h-32 absolute top-0 left-0" style={{ background: gradientTop }} />
|
||||
|
||||
|
||||
{/* Controls (pointer events auto) */}
|
||||
<div id="poster-controls" className="absolute top-4 left-4 flex gap-2 pointer-events-auto z-50">
|
||||
|
||||
{pickerPolygons && pickerPolygons.length > 0 && (
|
||||
<button
|
||||
onClick={() => setShowGadmBorders(!showGadmBorders)}
|
||||
<button
|
||||
onClick={() => setShowGadmBorders(!showGadmBorders)}
|
||||
className={`flex items-center px-3 py-1.5 ${showGadmBorders ? 'bg-indigo-100 text-indigo-700 dark:bg-indigo-900/40 dark:text-indigo-300' : 'bg-gray-100 hover:bg-gray-200 dark:bg-gray-700 dark:hover:bg-gray-600 text-gray-800 dark:text-gray-100'} rounded text-sm font-medium transition-colors shadow-sm`}
|
||||
title="Toggle GADM Borders"
|
||||
>
|
||||
<MapIcon className="w-4 h-4" />
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
onClick={onClose}
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="flex items-center px-3 py-1.5 bg-red-100 hover:bg-red-200 dark:bg-red-900/40 dark:hover:bg-red-900/60 text-red-700 dark:text-red-300 rounded text-sm font-medium transition-colors shadow-sm"
|
||||
>
|
||||
<XIcon className="w-4 h-4 mr-1.5" /> Exit Poster Mode
|
||||
@ -175,27 +175,27 @@ export function MapPosterOverlay({ map, pickerRegions, pickerPolygons, posterThe
|
||||
|
||||
{/* Bottom Content Area */}
|
||||
<div className="w-full h-72 absolute bottom-0 left-0 flex flex-col justify-end items-center pb-12" style={{ background: gradientBottom }}>
|
||||
<div
|
||||
<div
|
||||
className="text-center transition-colors duration-500"
|
||||
style={{ color: theme.text }}
|
||||
>
|
||||
<div className="font-bold tracking-[0.2em] text-5xl mb-6 font-mono leading-none drop-shadow-sm">
|
||||
{displayCity}
|
||||
</div>
|
||||
|
||||
|
||||
<div className="w-20 h-[2px] mx-auto opacity-70 mb-5 drop-shadow-sm" style={{ backgroundColor: theme.text }} />
|
||||
|
||||
|
||||
<div className="text-2xl tracking-[0.3em] font-light mb-3 drop-shadow-sm">
|
||||
{country.toUpperCase()}
|
||||
</div>
|
||||
|
||||
|
||||
<div className="text-sm opacity-80 font-mono tracking-wider drop-shadow-sm">
|
||||
{center ? formatCoords(center) : 'Loading...'}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Attribution */}
|
||||
<div
|
||||
<div
|
||||
className="absolute bottom-4 right-4 text-xs opacity-50 font-mono"
|
||||
style={{ color: theme.text }}
|
||||
>
|
||||
@ -204,4 +204,4 @@ export function MapPosterOverlay({ map, pickerRegions, pickerPolygons, posterThe
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -92,8 +92,8 @@ export function GadmRegionCollector({
|
||||
setIsLocating(true);
|
||||
try {
|
||||
const data = await fetchIpLocation();
|
||||
if (data && data.status === 'success' && data.lat && data.lon) {
|
||||
const hierarchy = await fetchRegionHierarchy(data.lat, data.lon);
|
||||
if (data && !data.error && data.latitude && data.longitude) {
|
||||
const hierarchy = await fetchRegionHierarchy(data.latitude, data.longitude);
|
||||
if (hierarchy && hierarchy.length > 0) {
|
||||
const pathGids = hierarchy.map((d: any) => d.gid);
|
||||
const l0 = hierarchy[0];
|
||||
|
||||
@ -146,7 +146,7 @@ function applyEventToState(
|
||||
|
||||
const stats = parsed.stats || data?.stats;
|
||||
if (stats) next.stats = { ...next.stats, ...stats };
|
||||
// console.log(`SSE ${type}`, parsed);
|
||||
console.log(`SSE ${type}`, parsed);
|
||||
switch (type) {
|
||||
case 'grid-ready':
|
||||
next.stats = { ...next.stats, totalWaypoints: data?.totalWaypoints || data?.waypoints?.length || 0, phase: 'searching' };
|
||||
|
||||
@ -201,7 +201,7 @@ export function JobViewer({ jobId }: { jobId: string }) {
|
||||
const allResults = jobData?.result?.searchResult?.results || competitors;
|
||||
const foundTypes = Array.from(new Set(allResults.flatMap((r: any) => r.types || []).filter(Boolean))).sort() as string[];
|
||||
return (
|
||||
<div className="flex flex-col flex-1 w-full overflow-hidden min-h-0 mt-2">
|
||||
<div className="flex flex-col flex-1 w-full overflow-hidden min-h-0 mt-2 dark:bg-gray-800/70 p-1">
|
||||
<div className="w-full flex-1 min-h-0 flex flex-col rounded-2xl shadow-xl transition-all duration-300">
|
||||
<div className="flex flex-col md:flex-row md:items-start justify-between">
|
||||
<div className="w-full">
|
||||
|
||||
@ -74,19 +74,19 @@ export function useMapControls(onMapCenterUpdate?: (loc: string, zoom?: number)
|
||||
setIsLocating(true);
|
||||
try {
|
||||
const data = await fetchIpLocation();
|
||||
if (data.status === 'success' && data.lat && data.lon) {
|
||||
if (!data.error && data.latitude && data.longitude) {
|
||||
if (userLocationMarkerRef.current) {
|
||||
userLocationMarkerRef.current.remove();
|
||||
}
|
||||
const marker = new maplibregl.Marker({ color: '#ef4444' })
|
||||
.setLngLat([data.lon, data.lat])
|
||||
.setLngLat([data.longitude, data.latitude])
|
||||
.setPopup(new maplibregl.Popup({ closeButton: false }).setText('Your Location (IP)'))
|
||||
.addTo(map);
|
||||
|
||||
userLocationMarkerRef.current = marker;
|
||||
|
||||
map.flyTo({
|
||||
center: [data.lon, data.lat],
|
||||
center: [data.longitude, data.latitude],
|
||||
zoom: 12
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,280 +1,280 @@
|
||||
export interface PosterTheme {
|
||||
name: string;
|
||||
description?: string;
|
||||
bg: string;
|
||||
text: string;
|
||||
gradient_color: string;
|
||||
water: string;
|
||||
parks: string;
|
||||
road_motorway: string;
|
||||
road_primary: string;
|
||||
road_secondary: string;
|
||||
road_tertiary: string;
|
||||
road_residential: string;
|
||||
road_default: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
bg: string;
|
||||
text: string;
|
||||
gradient_color: string;
|
||||
water: string;
|
||||
parks: string;
|
||||
road_motorway: string;
|
||||
road_primary: string;
|
||||
road_secondary: string;
|
||||
road_tertiary: string;
|
||||
road_residential: string;
|
||||
road_default: string;
|
||||
}
|
||||
|
||||
export const POSTER_THEMES: Record<string, PosterTheme> = {
|
||||
"autumn": {
|
||||
"name": "Autumn",
|
||||
"description": "Burnt oranges, deep reds, golden yellows - seasonal warmth",
|
||||
"bg": "#FBF7F0",
|
||||
"text": "#8B4513",
|
||||
"gradient_color": "#FBF7F0",
|
||||
"water": "#D8CFC0",
|
||||
"parks": "#E8E0D0",
|
||||
"road_motorway": "#8B2500",
|
||||
"road_primary": "#B8450A",
|
||||
"road_secondary": "#CC7A30",
|
||||
"road_tertiary": "#D9A050",
|
||||
"road_residential": "#E8C888",
|
||||
"road_default": "#CC7A30"
|
||||
},
|
||||
"blueprint": {
|
||||
"name": "Blueprint",
|
||||
"description": "Classic architectural blueprint - technical drawing aesthetic",
|
||||
"bg": "#1A3A5C",
|
||||
"text": "#E8F4FF",
|
||||
"gradient_color": "#1A3A5C",
|
||||
"water": "#0F2840",
|
||||
"parks": "#1E4570",
|
||||
"road_motorway": "#E8F4FF",
|
||||
"road_primary": "#C5DCF0",
|
||||
"road_secondary": "#9FC5E8",
|
||||
"road_tertiary": "#7BAED4",
|
||||
"road_residential": "#5A96C0",
|
||||
"road_default": "#7BAED4"
|
||||
},
|
||||
"contrast_zones": {
|
||||
"name": "Contrast Zones",
|
||||
"description": "Strong contrast showing urban density - darker in center, lighter at edges",
|
||||
"bg": "#FFFFFF",
|
||||
"text": "#000000",
|
||||
"gradient_color": "#FFFFFF",
|
||||
"water": "#B0B0B0",
|
||||
"parks": "#ECECEC",
|
||||
"road_motorway": "#000000",
|
||||
"road_primary": "#0F0F0F",
|
||||
"road_secondary": "#252525",
|
||||
"road_tertiary": "#404040",
|
||||
"road_residential": "#5A5A5A",
|
||||
"road_default": "#404040"
|
||||
},
|
||||
"copper_patina": {
|
||||
"name": "Copper Patina",
|
||||
"description": "Oxidized copper aesthetic - teal-green patina with copper accents",
|
||||
"bg": "#E8F0F0",
|
||||
"text": "#2A5A5A",
|
||||
"gradient_color": "#E8F0F0",
|
||||
"water": "#C0D8D8",
|
||||
"parks": "#D8E8E0",
|
||||
"road_motorway": "#B87333",
|
||||
"road_primary": "#5A8A8A",
|
||||
"road_secondary": "#6B9E9E",
|
||||
"road_tertiary": "#88B4B4",
|
||||
"road_residential": "#A8CCCC",
|
||||
"road_default": "#88B4B4"
|
||||
},
|
||||
"emerald": {
|
||||
"name": "Emerald City",
|
||||
"description": "Lush dark green aesthetic with mint accents",
|
||||
"bg": "#062C22",
|
||||
"text": "#E3F9F1",
|
||||
"gradient_color": "#062C22",
|
||||
"water": "#0D4536",
|
||||
"parks": "#0F523E",
|
||||
"road_motorway": "#4ADEB0",
|
||||
"road_primary": "#2DB88F",
|
||||
"road_secondary": "#249673",
|
||||
"road_tertiary": "#1B7559",
|
||||
"road_residential": "#155C46",
|
||||
"road_default": "#155C46"
|
||||
},
|
||||
"forest": {
|
||||
"name": "Forest",
|
||||
"description": "Deep greens and sage tones - organic botanical aesthetic",
|
||||
"bg": "#F0F4F0",
|
||||
"text": "#2D4A3E",
|
||||
"gradient_color": "#F0F4F0",
|
||||
"water": "#B8D4D4",
|
||||
"parks": "#D4E8D4",
|
||||
"road_motorway": "#2D4A3E",
|
||||
"road_primary": "#3D6B55",
|
||||
"road_secondary": "#5A8A70",
|
||||
"road_tertiary": "#7AAA90",
|
||||
"road_residential": "#A0C8B0",
|
||||
"road_default": "#7AAA90"
|
||||
},
|
||||
"gradient_roads": {
|
||||
"name": "Gradient Roads",
|
||||
"description": "Smooth gradient from dark center to light edges with subtle features",
|
||||
"bg": "#FFFFFF",
|
||||
"text": "#000000",
|
||||
"gradient_color": "#FFFFFF",
|
||||
"water": "#D5D5D5",
|
||||
"parks": "#EFEFEF",
|
||||
"road_motorway": "#050505",
|
||||
"road_primary": "#151515",
|
||||
"road_secondary": "#2A2A2A",
|
||||
"road_tertiary": "#404040",
|
||||
"road_residential": "#555555",
|
||||
"road_default": "#404040"
|
||||
},
|
||||
"japanese_ink": {
|
||||
"name": "Japanese Ink",
|
||||
"description": "Traditional ink wash inspired - minimalist with subtle red accent",
|
||||
"bg": "#FAF8F5",
|
||||
"text": "#2C2C2C",
|
||||
"gradient_color": "#FAF8F5",
|
||||
"water": "#E8E4E0",
|
||||
"parks": "#F0EDE8",
|
||||
"road_motorway": "#8B2500",
|
||||
"road_primary": "#4A4A4A",
|
||||
"road_secondary": "#6A6A6A",
|
||||
"road_tertiary": "#909090",
|
||||
"road_residential": "#B8B8B8",
|
||||
"road_default": "#909090"
|
||||
},
|
||||
"midnight_blue": {
|
||||
"name": "Midnight Blue",
|
||||
"description": "Deep navy background with gold/copper roads - luxury atlas aesthetic",
|
||||
"bg": "#0A1628",
|
||||
"text": "#D4AF37",
|
||||
"gradient_color": "#0A1628",
|
||||
"water": "#061020",
|
||||
"parks": "#0F2235",
|
||||
"road_motorway": "#D4AF37",
|
||||
"road_primary": "#C9A227",
|
||||
"road_secondary": "#A8893A",
|
||||
"road_tertiary": "#8B7355",
|
||||
"road_residential": "#6B5B4F",
|
||||
"road_default": "#8B7355"
|
||||
},
|
||||
"monochrome_blue": {
|
||||
"name": "Monochrome Blue",
|
||||
"description": "Single blue color family with varying saturation - clean and cohesive",
|
||||
"bg": "#F5F8FA",
|
||||
"text": "#1A3A5C",
|
||||
"gradient_color": "#F5F8FA",
|
||||
"water": "#D0E0F0",
|
||||
"parks": "#E0EAF2",
|
||||
"road_motorway": "#1A3A5C",
|
||||
"road_primary": "#2A5580",
|
||||
"road_secondary": "#4A7AA8",
|
||||
"road_tertiary": "#7AA0C8",
|
||||
"road_residential": "#A8C4E0",
|
||||
"road_default": "#4A7AA8"
|
||||
},
|
||||
"neon_cyberpunk": {
|
||||
"name": "Neon Cyberpunk",
|
||||
"description": "Dark background with electric pink/cyan - bold night city vibes",
|
||||
"bg": "#0D0D1A",
|
||||
"text": "#00FFFF",
|
||||
"gradient_color": "#0D0D1A",
|
||||
"water": "#0A0A15",
|
||||
"parks": "#151525",
|
||||
"road_motorway": "#FF00FF",
|
||||
"road_primary": "#00FFFF",
|
||||
"road_secondary": "#00C8C8",
|
||||
"road_tertiary": "#0098A0",
|
||||
"road_residential": "#006870",
|
||||
"road_default": "#0098A0"
|
||||
},
|
||||
"noir": {
|
||||
"name": "Noir",
|
||||
"description": "Pure black background with white/gray roads - modern gallery aesthetic",
|
||||
"bg": "#000000",
|
||||
"text": "#FFFFFF",
|
||||
"gradient_color": "#000000",
|
||||
"water": "#0A0A0A",
|
||||
"parks": "#111111",
|
||||
"road_motorway": "#FFFFFF",
|
||||
"road_primary": "#E0E0E0",
|
||||
"road_secondary": "#B0B0B0",
|
||||
"road_tertiary": "#808080",
|
||||
"road_residential": "#505050",
|
||||
"road_default": "#808080"
|
||||
},
|
||||
"ocean": {
|
||||
"name": "Ocean",
|
||||
"description": "Various blues and teals - perfect for coastal cities",
|
||||
"bg": "#F0F8FA",
|
||||
"text": "#1A5F7A",
|
||||
"gradient_color": "#F0F8FA",
|
||||
"water": "#B8D8E8",
|
||||
"parks": "#D8EAE8",
|
||||
"road_motorway": "#1A5F7A",
|
||||
"road_primary": "#2A7A9A",
|
||||
"road_secondary": "#4A9AB8",
|
||||
"road_tertiary": "#70B8D0",
|
||||
"road_residential": "#A0D0E0",
|
||||
"road_default": "#4A9AB8"
|
||||
},
|
||||
"pastel_dream": {
|
||||
"name": "Pastel Dream",
|
||||
"description": "Soft muted pastels with dusty blues and mauves - dreamy artistic aesthetic",
|
||||
"bg": "#FAF7F2",
|
||||
"text": "#5D5A6D",
|
||||
"gradient_color": "#FAF7F2",
|
||||
"water": "#D4E4ED",
|
||||
"parks": "#E8EDE4",
|
||||
"road_motorway": "#7B8794",
|
||||
"road_primary": "#9BA4B0",
|
||||
"road_secondary": "#B5AEBB",
|
||||
"road_tertiary": "#C9C0C9",
|
||||
"road_residential": "#D8D2D8",
|
||||
"road_default": "#C9C0C9"
|
||||
},
|
||||
"sunset": {
|
||||
"name": "Sunset",
|
||||
"description": "Warm oranges and pinks on soft peach - dreamy golden hour aesthetic",
|
||||
"bg": "#FDF5F0",
|
||||
"text": "#C45C3E",
|
||||
"gradient_color": "#FDF5F0",
|
||||
"water": "#F0D8D0",
|
||||
"parks": "#F8E8E0",
|
||||
"road_motorway": "#C45C3E",
|
||||
"road_primary": "#D87A5A",
|
||||
"road_secondary": "#E8A088",
|
||||
"road_tertiary": "#F0B8A8",
|
||||
"road_residential": "#F5D0C8",
|
||||
"road_default": "#E8A088"
|
||||
},
|
||||
"terracotta": {
|
||||
"name": "Terracotta",
|
||||
"description": "Mediterranean warmth - burnt orange and clay tones on cream",
|
||||
"bg": "#F5EDE4",
|
||||
"text": "#8B4513",
|
||||
"gradient_color": "#F5EDE4",
|
||||
"water": "#A8C4C4",
|
||||
"parks": "#E8E0D0",
|
||||
"road_motorway": "#A0522D",
|
||||
"road_primary": "#B8653A",
|
||||
"road_secondary": "#C9846A",
|
||||
"road_tertiary": "#D9A08A",
|
||||
"road_residential": "#E5C4B0",
|
||||
"road_default": "#D9A08A"
|
||||
},
|
||||
"warm_beige": {
|
||||
"name": "Warm Beige",
|
||||
"description": "Earthy warm neutrals with sepia tones - vintage map aesthetic",
|
||||
"bg": "#F5F0E8",
|
||||
"text": "#6B5B4F",
|
||||
"gradient_color": "#F5F0E8",
|
||||
"water": "#DDD5C8",
|
||||
"parks": "#E8E4D8",
|
||||
"road_motorway": "#8B7355",
|
||||
"road_primary": "#A08B70",
|
||||
"road_secondary": "#B5A48E",
|
||||
"road_tertiary": "#C9BBAA",
|
||||
"road_residential": "#D9CFC2",
|
||||
"road_default": "#C9BBAA"
|
||||
},
|
||||
"autumn": {
|
||||
"name": "Autumn",
|
||||
"description": "Burnt oranges, deep reds, golden yellows - seasonal warmth",
|
||||
"bg": "#FBF7F0",
|
||||
"text": "#8B4513",
|
||||
"gradient_color": "#FBF7F0",
|
||||
"water": "#D8CFC0",
|
||||
"parks": "#E8E0D0",
|
||||
"road_motorway": "#8B2500",
|
||||
"road_primary": "#B8450A",
|
||||
"road_secondary": "#CC7A30",
|
||||
"road_tertiary": "#D9A050",
|
||||
"road_residential": "#E8C888",
|
||||
"road_default": "#CC7A30"
|
||||
},
|
||||
"blueprint": {
|
||||
"name": "Blueprint",
|
||||
"description": "Classic architectural blueprint - technical drawing aesthetic",
|
||||
"bg": "#1A3A5C",
|
||||
"text": "#E8F4FF",
|
||||
"gradient_color": "#1A3A5C",
|
||||
"water": "#0F2840",
|
||||
"parks": "#1E4570",
|
||||
"road_motorway": "#E8F4FF",
|
||||
"road_primary": "#C5DCF0",
|
||||
"road_secondary": "#9FC5E8",
|
||||
"road_tertiary": "#7BAED4",
|
||||
"road_residential": "#5A96C0",
|
||||
"road_default": "#7BAED4"
|
||||
},
|
||||
"contrast_zones": {
|
||||
"name": "Contrast Zones",
|
||||
"description": "Strong contrast showing urban density - darker in center, lighter at edges",
|
||||
"bg": "#FFFFFF",
|
||||
"text": "#000000",
|
||||
"gradient_color": "#FFFFFF",
|
||||
"water": "#B0B0B0",
|
||||
"parks": "#ECECEC",
|
||||
"road_motorway": "#000000",
|
||||
"road_primary": "#0F0F0F",
|
||||
"road_secondary": "#252525",
|
||||
"road_tertiary": "#404040",
|
||||
"road_residential": "#5A5A5A",
|
||||
"road_default": "#404040"
|
||||
},
|
||||
"copper_patina": {
|
||||
"name": "Copper Patina",
|
||||
"description": "Oxidized copper aesthetic - teal-green patina with copper accents",
|
||||
"bg": "#E8F0F0",
|
||||
"text": "#2A5A5A",
|
||||
"gradient_color": "#E8F0F0",
|
||||
"water": "#C0D8D8",
|
||||
"parks": "#D8E8E0",
|
||||
"road_motorway": "#B87333",
|
||||
"road_primary": "#5A8A8A",
|
||||
"road_secondary": "#6B9E9E",
|
||||
"road_tertiary": "#88B4B4",
|
||||
"road_residential": "#A8CCCC",
|
||||
"road_default": "#88B4B4"
|
||||
},
|
||||
"emerald": {
|
||||
"name": "Emerald City",
|
||||
"description": "Lush dark green aesthetic with mint accents",
|
||||
"bg": "#062C22",
|
||||
"text": "#E3F9F1",
|
||||
"gradient_color": "#062C22",
|
||||
"water": "#0D4536",
|
||||
"parks": "#0F523E",
|
||||
"road_motorway": "#4ADEB0",
|
||||
"road_primary": "#2DB88F",
|
||||
"road_secondary": "#249673",
|
||||
"road_tertiary": "#1B7559",
|
||||
"road_residential": "#155C46",
|
||||
"road_default": "#155C46"
|
||||
},
|
||||
"forest": {
|
||||
"name": "Forest",
|
||||
"description": "Deep greens and sage tones - organic botanical aesthetic",
|
||||
"bg": "#F0F4F0",
|
||||
"text": "#2D4A3E",
|
||||
"gradient_color": "#F0F4F0",
|
||||
"water": "#B8D4D4",
|
||||
"parks": "#D4E8D4",
|
||||
"road_motorway": "#2D4A3E",
|
||||
"road_primary": "#3D6B55",
|
||||
"road_secondary": "#5A8A70",
|
||||
"road_tertiary": "#7AAA90",
|
||||
"road_residential": "#A0C8B0",
|
||||
"road_default": "#7AAA90"
|
||||
},
|
||||
"gradient_roads": {
|
||||
"name": "Gradient Roads",
|
||||
"description": "Smooth gradient from dark center to light edges with subtle features",
|
||||
"bg": "#FFFFFF",
|
||||
"text": "#000000",
|
||||
"gradient_color": "#FFFFFF",
|
||||
"water": "#D5D5D5",
|
||||
"parks": "#EFEFEF",
|
||||
"road_motorway": "#050505",
|
||||
"road_primary": "#151515",
|
||||
"road_secondary": "#2A2A2A",
|
||||
"road_tertiary": "#404040",
|
||||
"road_residential": "#555555",
|
||||
"road_default": "#404040"
|
||||
},
|
||||
"japanese_ink": {
|
||||
"name": "Japanese Ink",
|
||||
"description": "Traditional ink wash inspired - minimalist with subtle red accent",
|
||||
"bg": "#FAF8F5",
|
||||
"text": "#2C2C2C",
|
||||
"gradient_color": "#FAF8F5",
|
||||
"water": "#E8E4E0",
|
||||
"parks": "#F0EDE8",
|
||||
"road_motorway": "#8B2500",
|
||||
"road_primary": "#4A4A4A",
|
||||
"road_secondary": "#6A6A6A",
|
||||
"road_tertiary": "#909090",
|
||||
"road_residential": "#B8B8B8",
|
||||
"road_default": "#909090"
|
||||
},
|
||||
"midnight_blue": {
|
||||
"name": "Midnight Blue",
|
||||
"description": "Deep navy background with gold/copper roads - luxury atlas aesthetic",
|
||||
"bg": "#0A1628",
|
||||
"text": "#D4AF37",
|
||||
"gradient_color": "#0A1628",
|
||||
"water": "#061020",
|
||||
"parks": "#0F2235",
|
||||
"road_motorway": "#D4AF37",
|
||||
"road_primary": "#C9A227",
|
||||
"road_secondary": "#A8893A",
|
||||
"road_tertiary": "#8B7355",
|
||||
"road_residential": "#6B5B4F",
|
||||
"road_default": "#8B7355"
|
||||
},
|
||||
"monochrome_blue": {
|
||||
"name": "Monochrome Blue",
|
||||
"description": "Single blue color family with varying saturation - clean and cohesive",
|
||||
"bg": "#F5F8FA",
|
||||
"text": "#1A3A5C",
|
||||
"gradient_color": "#F5F8FA",
|
||||
"water": "#D0E0F0",
|
||||
"parks": "#E0EAF2",
|
||||
"road_motorway": "#1A3A5C",
|
||||
"road_primary": "#2A5580",
|
||||
"road_secondary": "#4A7AA8",
|
||||
"road_tertiary": "#7AA0C8",
|
||||
"road_residential": "#A8C4E0",
|
||||
"road_default": "#4A7AA8"
|
||||
},
|
||||
"neon_cyberpunk": {
|
||||
"name": "Neon Cyberpunk",
|
||||
"description": "Dark background with electric pink/cyan - bold night city vibes",
|
||||
"bg": "#0D0D1A",
|
||||
"text": "#00FFFF",
|
||||
"gradient_color": "#0D0D1A",
|
||||
"water": "#0A0A15",
|
||||
"parks": "#151525",
|
||||
"road_motorway": "#FF00FF",
|
||||
"road_primary": "#00FFFF",
|
||||
"road_secondary": "#00C8C8",
|
||||
"road_tertiary": "#0098A0",
|
||||
"road_residential": "#006870",
|
||||
"road_default": "#0098A0"
|
||||
},
|
||||
"noir": {
|
||||
"name": "Noir",
|
||||
"description": "Pure black background with white/gray roads - modern gallery aesthetic",
|
||||
"bg": "#000000",
|
||||
"text": "#FFFFFF",
|
||||
"gradient_color": "#000000",
|
||||
"water": "#0A0A0A",
|
||||
"parks": "#111111",
|
||||
"road_motorway": "#FFFFFF",
|
||||
"road_primary": "#E0E0E0",
|
||||
"road_secondary": "#B0B0B0",
|
||||
"road_tertiary": "#808080",
|
||||
"road_residential": "#505050",
|
||||
"road_default": "#808080"
|
||||
},
|
||||
"ocean": {
|
||||
"name": "Ocean",
|
||||
"description": "Various blues and teals - perfect for coastal cities",
|
||||
"bg": "#F0F8FA",
|
||||
"text": "#1A5F7A",
|
||||
"gradient_color": "#F0F8FA",
|
||||
"water": "#B8D8E8",
|
||||
"parks": "#D8EAE8",
|
||||
"road_motorway": "#1A5F7A",
|
||||
"road_primary": "#2A7A9A",
|
||||
"road_secondary": "#4A9AB8",
|
||||
"road_tertiary": "#70B8D0",
|
||||
"road_residential": "#A0D0E0",
|
||||
"road_default": "#4A9AB8"
|
||||
},
|
||||
"pastel_dream": {
|
||||
"name": "Pastel Dream",
|
||||
"description": "Soft muted pastels with dusty blues and mauves - dreamy artistic aesthetic",
|
||||
"bg": "#FAF7F2",
|
||||
"text": "#5D5A6D",
|
||||
"gradient_color": "#FAF7F2",
|
||||
"water": "#D4E4ED",
|
||||
"parks": "#E8EDE4",
|
||||
"road_motorway": "#7B8794",
|
||||
"road_primary": "#9BA4B0",
|
||||
"road_secondary": "#B5AEBB",
|
||||
"road_tertiary": "#C9C0C9",
|
||||
"road_residential": "#D8D2D8",
|
||||
"road_default": "#C9C0C9"
|
||||
},
|
||||
"sunset": {
|
||||
"name": "Sunset",
|
||||
"description": "Warm oranges and pinks on soft peach - dreamy golden hour aesthetic",
|
||||
"bg": "#FDF5F0",
|
||||
"text": "#C45C3E",
|
||||
"gradient_color": "#FDF5F0",
|
||||
"water": "#F0D8D0",
|
||||
"parks": "#F8E8E0",
|
||||
"road_motorway": "#C45C3E",
|
||||
"road_primary": "#D87A5A",
|
||||
"road_secondary": "#E8A088",
|
||||
"road_tertiary": "#F0B8A8",
|
||||
"road_residential": "#F5D0C8",
|
||||
"road_default": "#E8A088"
|
||||
},
|
||||
"terracotta": {
|
||||
"name": "Terracotta",
|
||||
"description": "Mediterranean warmth - burnt orange and clay tones on cream",
|
||||
"bg": "#F5EDE4",
|
||||
"text": "#8B4513",
|
||||
"gradient_color": "#F5EDE4",
|
||||
"water": "#A8C4C4",
|
||||
"parks": "#E8E0D0",
|
||||
"road_motorway": "#A0522D",
|
||||
"road_primary": "#B8653A",
|
||||
"road_secondary": "#C9846A",
|
||||
"road_tertiary": "#D9A08A",
|
||||
"road_residential": "#E5C4B0",
|
||||
"road_default": "#D9A08A"
|
||||
},
|
||||
"warm_beige": {
|
||||
"name": "Warm Beige",
|
||||
"description": "Earthy warm neutrals with sepia tones - vintage map aesthetic",
|
||||
"bg": "#F5F0E8",
|
||||
"text": "#6B5B4F",
|
||||
"gradient_color": "#F5F0E8",
|
||||
"water": "#DDD5C8",
|
||||
"parks": "#E8E4D8",
|
||||
"road_motorway": "#8B7355",
|
||||
"road_primary": "#A08B70",
|
||||
"road_secondary": "#B5A48E",
|
||||
"road_tertiary": "#C9BBAA",
|
||||
"road_residential": "#D9CFC2",
|
||||
"road_default": "#C9BBAA"
|
||||
},
|
||||
};
|
||||
|
||||
export function applyPosterTheme(map: maplibregl.Map | any, theme: PosterTheme, isDark: boolean = false) {
|
||||
if (!map || !map.getStyle()) return;
|
||||
|
||||
|
||||
const setPaintSafe = (layer: string, prop: string, val: string | number) => {
|
||||
if (map.getLayer(layer)) {
|
||||
try {
|
||||
@ -286,10 +286,10 @@ export function applyPosterTheme(map: maplibregl.Map | any, theme: PosterTheme,
|
||||
};
|
||||
|
||||
const layers = map.getStyle().layers || [];
|
||||
|
||||
|
||||
layers.forEach((layer: any) => {
|
||||
const id = layer.id.toLowerCase();
|
||||
|
||||
|
||||
// Hide all symbols (labels, POIs, etc)
|
||||
if (layer.type === 'symbol') {
|
||||
map.setLayoutProperty(id, 'visibility', 'none');
|
||||
@ -323,10 +323,10 @@ export function applyPosterTheme(map: maplibregl.Map | any, theme: PosterTheme,
|
||||
if (id.includes('building')) {
|
||||
setPaintSafe(id, 'fill-color', theme.road_residential || theme.road_default);
|
||||
setPaintSafe(id, 'line-color', theme.road_residential || theme.road_default);
|
||||
|
||||
|
||||
// Try wrapping opacity changes safely
|
||||
try { map.setPaintProperty(id, 'fill-opacity', 0.2); } catch(e){}
|
||||
try { map.setPaintProperty(id, 'line-opacity', 0.1); } catch(e){}
|
||||
try { map.setPaintProperty(id, 'fill-opacity', 0.2); } catch (e) { }
|
||||
try { map.setPaintProperty(id, 'line-opacity', 0.1); } catch (e) { }
|
||||
return;
|
||||
}
|
||||
|
||||
@ -334,16 +334,16 @@ export function applyPosterTheme(map: maplibregl.Map | any, theme: PosterTheme,
|
||||
if (id.includes('road') || id.includes('highway') || id.includes('tunnel') || id.includes('bridge') || id.includes('aeroway')) {
|
||||
if (id.includes('mot') || id.includes('motorway') || id.includes('trunk') || id.includes('runway')) {
|
||||
setPaintSafe(id, 'line-color', theme.road_motorway);
|
||||
}
|
||||
}
|
||||
else if (id.includes('pri') || id.includes('primary') || id.includes('major')) {
|
||||
setPaintSafe(id, 'line-color', theme.road_primary);
|
||||
}
|
||||
}
|
||||
else if (id.includes('sec') || id.includes('secondary')) {
|
||||
setPaintSafe(id, 'line-color', theme.road_secondary);
|
||||
}
|
||||
}
|
||||
else if (id.includes('ter') || id.includes('tertiary')) {
|
||||
setPaintSafe(id, 'line-color', theme.road_tertiary);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Minor / Residential / Path / Track / Service / Taxiway
|
||||
setPaintSafe(id, 'line-color', theme.road_residential || theme.road_default);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user