react-route-profile 0.1.29 → 0.1.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/hooks/useOrientation.ts","../src/theme.ts","../src/theme-provider.tsx","../src/components/Loader.tsx","../src/components/RouteMap/ElevationChart/DistanceTick.tsx","../src/components/RouteMap/HoverContext.tsx","../src/components/RouteMap/ElevationChart/ElevationDot.tsx","../src/components/RouteMap/ElevationChart/ElevationTick.tsx","../src/types.ts","../src/components/RouteMap/ElevationChart/SurfaceStrip.tsx","../src/components/RouteMap/ElevationChart/ElevationTooltip.tsx","../src/assets/icons/marker.svg","../src/components/icons/buildMarkerIcon.ts","../src/components/RouteMap/ElevationChart/MarkerShape.tsx","../src/components/RouteMap/ElevationChart/RouteStrip.tsx","../src/components/RouteMap/ElevationChart/useTriggerByXValue.tsx","../src/components/RouteMap/ElevationChart/utils.ts","../src/components/RouteMap/ElevationChart/ElevationChart.tsx","../src/constants.ts","../src/components/RouteMap/GoogleMapCanvas.tsx","../src/components/RouteMap/RouteMap.tsx","../node_modules/@uidotdev/usehooks/index.js","../src/hooks/useMapHeader.ts"],"names":["getIsLandscape","useOrientation","isHorizontal","setIsHorizontal","useState","useEffect","handleResize","theme","ThemeContext","createContext","mergeTheme","override","ThemeProvider","children","mergedTheme","useMemo","jsx","useTheme","useContext","Loader","message","height","style","styles","Loader_default","DistanceTick","props","x","y","payload","km","jsxs","HoverContext","HoverProvider","hover","setHoverState","setHover","useCallback","state","clearHover","value","useHover","ctx","Dot","cx","cy","fill","ElevationDot","MapDot","ElevationTick","m","SurfaceType","SURFACE_STRIP_WIDTH","SURFACE_STRIP_HEIGHT","SURFACE_TEXTURES","surfaceAsphalt","surfaceCompacted","surfaceConcrete","surfaceNatural","surfacePenetrated","SurfaceStrip","route","maxDistance","xAxisMap","offset","surfaces","xAxis","scale","chartLeft","chartWidth","axisY","stripY","Fragment","surfaceType","file","width","surface","index","rawStart","rawEnd","clampedStart","clampedEnd","segStart","segEnd","startX","endX","MARKER_DISTANCE_TOLERANCE_MATCH","getSurfaceForDistance","distance","start","end","getRouteForDistance","routes","formatSurfaceLabel","formatSegmentLabel","segment","formatKm","rounded","ElevationTooltip","active","label","accent","primary","markers","tooltip","point","marker","surfaceTexture","routeSegment","marker_default","svgTemplate","base","outer","inner","fillIndex","match","buildMarkerIcon","svg","MarkerShape","name","layout","size","iconHref","words","w","Text","text","word","Word","id","useId","RouteStrip","belowHeight","useTriggerByXValue","data","activeIndex","setActiveIndex","activePoint","clearActiveIndex","triggerByXValue","lo","hi","mid","bestIndex","prev","curr","getMaxDistance","points","getTicksForDistance","step","ticks","d","getPointsWithElevation","f","a","b","getAllPoints","computeMinMax","elevations","p","min","max","pad","computeRoundedDomainAndTicks","minMax","shouldOffset","paddedRange","graphMin","graphMax","v","computeMarkerPoints","elevationPoints","geoJson","pointFeatures","coords","lng","lat","nearest","acc","findNearestPointByCoordinates","target","closest","minDist","findNearestPoint","isCloseCheck","marker1","marker2","threshold","ElevationChart","minY","maxY","tickVals","nearestPoint","ResponsiveContainer","ComposedChart","activePayload","activePayloadItem","CartesianGrid","Customized","XAxis","YAxis","Tooltip","Line","idx","tooClose","ReferenceDot","ReferenceLine","DEFAULT_CENTER","DEFAULT_ZOOM_HORIZONTAL","DEFAULT_ZOOM_VERTICAL","GoogleMapCanvas","ref","useRef","highlightMarkerRef","mapRef","markerIcons","zoom","map","feature","isFirst","isLast","moveListener","e","latLng","mapInstance","icon","messages","Status","RenderLoader","type","render","status","RouteMap","apiKey","className","containerStyle","Wrapper","useMeasure","dimensions","setDimensions","previousObserver","node","observer","entry","useMapHeader","refHeader","headerHeight","isHeaderReady","mapHeight"],"mappings":"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","file":"index.js","sourcesContent":["import { useEffect, useState } from \"react\";\n\nconst getIsLandscape = () => {\n if (typeof window === \"undefined\") return true;\n return window.innerWidth >= window.innerHeight;\n};\n\nexport const useOrientation = () => {\n const [isHorizontal, setIsHorizontal] = useState<boolean>(getIsLandscape);\n\n useEffect(() => {\n const handleResize = () => setIsHorizontal(getIsLandscape());\n\n window.addEventListener(\"resize\", handleResize);\n return () => window.removeEventListener(\"resize\", handleResize);\n }, []);\n\n return { isHorizontal, isVertical: !isHorizontal };\n};\n","export interface ThemeColors {\n primary: string;\n primaryMuted: string;\n accent: string;\n surface: string;\n}\n\nexport interface ThemeMarker {\n outer: string;\n inner: string;\n startInner: string;\n finishInner: string;\n}\n\nexport interface ThemeDots {\n mapActive: string;\n chart: string;\n chartActive: string;\n}\n\nexport interface ThemeMap {\n strokeWeight: number;\n markerSize: number;\n markerLabelFontSize: number;\n markerLabelFontWeight: string;\n hoverMarkerScale: number;\n}\n\nexport interface ThemeChart {\n margin: { top: number; right: number; bottom: number; left: number };\n gridStroke: string;\n gridDasharray: string;\n axisStroke: string;\n cursorStroke: string;\n cursorStrokeWidth: number;\n yAxisWidth: number;\n lineStrokeWidth: number;\n dotRadius: number;\n dotOpacity: number;\n activeDotRadius: number;\n referenceDotRadius: number;\n referenceLineOpacity: number;\n gradientStartOpacity: number;\n gradientEndOpacity: number;\n xTickFontSize: number;\n xTickDy: number;\n xTickUnitFontSize: number;\n xTickUnitDx: number;\n yTickFontSize: number;\n yTickDy: number;\n yTickUnitFontSize: number;\n yTickUnitDx: number;\n}\n\nexport interface ThemeTooltip {\n background: string;\n textColor: string;\n padding: string;\n borderRadius: number;\n}\n\nexport interface ThemeMarkerShape {\n size: number;\n lift: number;\n text: {\n fontSize: number;\n fontWeight: number;\n letterSpacing: number;\n xOffset: number;\n lineHeight: number;\n startLiftPerWord: number;\n };\n}\n\nexport interface ThemeShadows {\n map: string;\n}\n\nexport interface Theme {\n colors: ThemeColors;\n marker: ThemeMarker;\n dots: ThemeDots;\n map: ThemeMap;\n chart: ThemeChart;\n tooltip: ThemeTooltip;\n markerShape: ThemeMarkerShape & {\n text: ThemeMarkerShape[\"text\"];\n };\n}\n\nexport interface PartialTheme {\n colors?: Partial<ThemeColors>;\n marker?: Partial<ThemeMarker>;\n dots?: Partial<ThemeDots>;\n map?: Partial<ThemeMap>;\n chart?: Partial<ThemeChart>;\n tooltip?: Partial<ThemeTooltip>;\n markerShape?: Partial<ThemeMarkerShape> & {\n text?: Partial<ThemeMarkerShape[\"text\"]>;\n };\n}\n\nexport const theme: Theme = {\n colors: {\n primary: \"rgba(14, 165, 233, 1)\",\n primaryMuted: \"rgba(14, 165, 233, 0.7)\",\n accent: \"rgba(132, 204, 22, 1)\",\n surface: \"rgba(248, 250, 252, 1)\",\n },\n marker: {\n outer: \"rgba(132, 204, 22, 1)\",\n inner: \"rgba(248, 250, 252, 1)\",\n startInner: \"rgba(34, 197, 94, 1)\",\n finishInner: \"rgba(239, 68, 68, 1)\",\n },\n dots: {\n mapActive: \"rgba(132, 204, 22, 1)\",\n chart: \"rgba(132, 204, 22, 1)\",\n chartActive: \"rgba(132, 204, 22, 1)\",\n },\n map: {\n strokeWeight: 10,\n markerSize: 50,\n markerLabelFontSize: 20,\n markerLabelFontWeight: \"bold\",\n hoverMarkerScale: 6,\n },\n chart: {\n margin: { top: 4, right: 8, bottom: 4, left: 8 },\n gridStroke: \"rgba(255,255,255,0.08)\",\n gridDasharray: \"3 3\",\n axisStroke: \"rgba(226, 232, 240, 0.7)\",\n cursorStroke: \"rgba(226,232,240,0.4)\",\n cursorStrokeWidth: 1,\n yAxisWidth: 60,\n lineStrokeWidth: 1,\n dotRadius: 3,\n dotOpacity: 0.9,\n activeDotRadius: 3,\n referenceDotRadius: 7,\n referenceLineOpacity: 0.5,\n gradientStartOpacity: 0.6,\n gradientEndOpacity: 0.1,\n xTickFontSize: 12,\n xTickDy: 12,\n xTickUnitFontSize: 10,\n xTickUnitDx: 2,\n yTickFontSize: 12,\n yTickDy: 4,\n yTickUnitFontSize: 10,\n yTickUnitDx: 2,\n },\n tooltip: {\n background: \"rgba(15,23,42,0.9)\",\n textColor: \"#e2e8f0\",\n padding: \"6px 8px\",\n borderRadius: 6,\n },\n markerShape: {\n size: 33,\n lift: 20,\n text: {\n fontSize: 12,\n fontWeight: 300,\n letterSpacing: 2,\n xOffset: 15,\n lineHeight: 12,\n startLiftPerWord: 10,\n },\n },\n};\n","import { createContext, type ReactNode, useContext, useMemo } from \"react\";\nimport { theme as defaultTheme, PartialTheme, type Theme } from \"./theme\";\n\nconst ThemeContext = createContext<Theme>(defaultTheme);\n\nconst mergeTheme = (override?: PartialTheme): Theme => ({\n colors: {\n ...defaultTheme.colors,\n ...(override?.colors ?? {}),\n },\n marker: {\n ...defaultTheme.marker,\n ...(override?.marker ?? {}),\n },\n dots: {\n ...defaultTheme.dots,\n ...(override?.dots ?? {}),\n },\n map: {\n ...defaultTheme.map,\n ...(override?.map ?? {}),\n },\n chart: {\n ...defaultTheme.chart,\n ...(override?.chart ?? {}),\n },\n tooltip: {\n ...defaultTheme.tooltip,\n ...(override?.tooltip ?? {}),\n },\n markerShape: {\n ...defaultTheme.markerShape,\n ...(override?.markerShape ?? {}),\n text: {\n ...defaultTheme.markerShape.text,\n ...(override?.markerShape?.text ?? {}),\n },\n },\n});\n\nexport const ThemeProvider = ({\n theme,\n children,\n}: {\n theme?: PartialTheme;\n children: ReactNode;\n}) => {\n const mergedTheme = useMemo(() => mergeTheme(theme), [theme]);\n return (\n <ThemeContext.Provider value={mergedTheme}>\n {children}\n </ThemeContext.Provider>\n );\n};\n\nexport const useTheme = () => useContext(ThemeContext);\n","import type { CSSProperties } from \"react\";\nimport { useTheme } from \"../theme-provider\";\nimport styles from \"./Loader.module.css\";\n\ninterface LoaderProps {\n message?: string;\n height?: number | string;\n}\n\nconst Loader = ({\n message = \"Loading map...\",\n height = \"100dvh\",\n}: LoaderProps) => {\n const theme = useTheme();\n\n const style: CSSProperties = {\n height,\n background: theme.colors.surface,\n color: theme.colors.primary,\n };\n\n return (\n <div className={styles.rrpLoader} style={style}>\n {message}\n </div>\n );\n};\n\nexport default Loader;\n","import { useTheme } from \"../../../theme-provider\";\n\nexport const DistanceTick = (props: any) => {\n const { x, y, payload } = props;\n const theme = useTheme();\n const km = Math.round((payload?.value ?? 0) / 1000);\n return (\n <text\n x={x}\n y={y}\n fill={theme.chart.axisStroke}\n fontSize={theme.chart.xTickFontSize}\n textAnchor=\"middle\"\n dy={theme.chart.xTickDy}\n >\n <tspan>{km}</tspan>\n <tspan\n fontSize={theme.chart.xTickUnitFontSize}\n dx={theme.chart.xTickUnitDx}\n >\n km\n </tspan>\n </text>\n );\n};\n","import {\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useMemo,\n useState,\n} from \"react\";\n\nexport enum HoverStateChangeSource {\n Chart = \"chart\",\n Map = \"map\",\n}\nexport interface HoverState {\n lat?: number;\n lng?: number;\n source?: HoverStateChangeSource;\n}\n\ninterface HoverContextValue {\n hover: HoverState;\n setHover: (state: HoverState) => void;\n clearHover: () => void;\n}\n\nconst HoverContext = createContext<HoverContextValue | undefined>(undefined);\n\nexport const HoverProvider = ({ children }: { children: ReactNode }) => {\n const [hover, setHoverState] = useState<HoverState>({});\n\n const setHover = useCallback((state: HoverState) => setHoverState(state), []);\n const clearHover = useCallback(() => setHoverState({}), []);\n\n const value = useMemo(\n () => ({\n hover,\n setHover,\n clearHover,\n }),\n [hover, setHover, clearHover]\n );\n\n return (\n <HoverContext.Provider value={value}>{children}</HoverContext.Provider>\n );\n};\n\nexport const useHover = () => {\n const ctx = useContext(HoverContext);\n if (!ctx) {\n throw new Error(\"useHover must be used within HoverProvider\");\n }\n return ctx;\n};\n","import { useTheme } from \"../../../theme-provider\";\n\nconst Dot = (props: any) => {\n const { cx, cy, fill } = props;\n const theme = useTheme();\n if (cx === undefined || cy === undefined) return null;\n return (\n <circle\n cx={cx}\n cy={cy}\n r={theme.chart.dotRadius}\n fill={fill}\n opacity={theme.chart.dotOpacity}\n />\n );\n};\n\nexport const ElevationDot = (props: any) => {\n const theme = useTheme();\n return <Dot {...props} fill={theme.dots.chart} />;\n};\n\nexport const MapDot = (props: any) => {\n const theme = useTheme();\n return <Dot {...props} fill={theme.dots.mapActive} />;\n};\n","import { useTheme } from \"../../../theme-provider\";\n\nexport const ElevationTick = (props: any) => {\n const { x, y, payload } = props;\n const theme = useTheme();\n const m = Math.round(payload?.value ?? 0);\n return (\n <text\n x={x}\n y={y}\n fill={theme.chart.axisStroke}\n fontSize={theme.chart.yTickFontSize}\n textAnchor=\"end\"\n dy={theme.chart.yTickDy}\n >\n <tspan>{m}</tspan>\n <tspan\n fontSize={theme.chart.yTickUnitFontSize}\n dx={theme.chart.yTickUnitDx}\n >\n m\n </tspan>\n </text>\n );\n};\n","export interface RouteConfig {\n id: string;\n name: string;\n center: { lat: number; lng: number };\n zoomHorizontal?: number;\n zoomVertical?: number;\n geoJson: object;\n surface?: Array<{segment: [number, number], type: SurfaceType}>;\n routes?: Array<{id: string; color: string; segment: [number, number]}>;\n}\n\nexport enum SurfaceType {\n Asphalt = \"asphalt\",\n Compacted = \"compacted\",\n Concrete = \"concrete\",\n Natural = \"natural\",\n Penetrated = \"penetrated\",\n}\n","import surfaceAsphalt from \"../../../assets/surface/surface_asphalt.png\";\nimport surfaceCompacted from \"../../../assets/surface/surface_compacted.png\";\nimport surfaceConcrete from \"../../../assets/surface/surface_concrete.png\";\nimport surfaceNatural from \"../../../assets/surface/surface_natural.png\";\nimport surfacePenetrated from \"../../../assets/surface/surface_penetrated.png\";\nimport type { RouteConfig } from \"../../../types\";\nimport { SurfaceType } from \"../../../types\";\n\n// const surfaceAsphalt = new URL(\n// \"../../../assets/surface/surface_asphalt.png\",\n// import.meta.url\n// ).href;\n// const surfaceCompacted = new URL(\n// \"../../../assets/surface/surface_compacted.png\",\n// import.meta.url\n// ).href;\n// const surfaceConcrete = new URL(\n// \"../../../assets/surface/surface_concrete.png\",\n// import.meta.url\n// ).href;\n// const surfaceNatural = new URL(\n// \"../../../assets/surface/surface_natural.png\",\n// import.meta.url\n// ).href;\n// const surfacePenetrated = new URL(\n// \"../../../assets/surface/surface_penetrated.png\",\n// import.meta.url\n// ).href;\n\nconst SURFACE_STRIP_WIDTH = 30;\nexport const SURFACE_STRIP_HEIGHT = 16;\n\nexport const SURFACE_TEXTURES: Record<\n SurfaceType,\n { file: string; width?: number; height?: number }\n> = {\n [SurfaceType.Asphalt]: {\n file: surfaceAsphalt,\n width: 30,\n height: 22,\n },\n [SurfaceType.Compacted]: {\n file: surfaceCompacted,\n width: 200,\n height: 16,\n },\n [SurfaceType.Concrete]: {\n file: surfaceConcrete,\n },\n [SurfaceType.Natural]: {\n file: surfaceNatural,\n width: 30,\n height: 22,\n },\n [SurfaceType.Penetrated]: {\n file: surfacePenetrated,\n width: 30,\n height: 22,\n },\n};\n\ntype SurfaceStripProps = {\n route: RouteConfig;\n maxDistance: number;\n height?: number;\n xAxisMap?: Record<\n string,\n {\n scale?: (value: number) => number;\n x?: number;\n y?: number;\n width?: number;\n }\n >;\n offset?: { left?: number; top?: number; width?: number; height?: number };\n};\n\nexport const SurfaceStrip = ({\n route,\n maxDistance,\n xAxisMap,\n offset,\n}: SurfaceStripProps) => {\n const surfaces = route.surface ?? [];\n if (!surfaces.length) {\n return null;\n }\n\n const xAxis = xAxisMap ? Object.values(xAxisMap)[0] : undefined;\n const scale = xAxis?.scale;\n const chartLeft = xAxis?.x ?? offset?.left ?? 0;\n const chartWidth = xAxis?.width ?? offset?.width ?? 0;\n const axisY = xAxis?.y ?? (offset?.top ?? 0) + (offset?.height ?? 0);\n const height = SURFACE_STRIP_HEIGHT;\n const stripY = axisY - height;\n\n if (!scale || chartWidth <= 0) {\n return null;\n }\n\n return (\n <>\n <defs>\n {Object.entries(SURFACE_TEXTURES).map(\n ([surfaceType, { file, width, height }]) => (\n <pattern\n key={surfaceType}\n id={`surface-${surfaceType}`}\n patternUnits={\n surfaceType === SurfaceType.Compacted\n ? undefined\n : \"userSpaceOnUse\"\n }\n width={width ?? SURFACE_STRIP_WIDTH}\n height={height ?? SURFACE_STRIP_HEIGHT}\n >\n <image\n href={file}\n x=\"0\"\n y=\"0\"\n width={width ?? SURFACE_STRIP_WIDTH}\n height={height ?? SURFACE_STRIP_HEIGHT}\n />\n </pattern>\n )\n )}\n </defs>\n <g>\n <rect\n x={chartLeft}\n y={stripY}\n width={chartWidth}\n height={height}\n fill=\"none\"\n />\n {surfaces.map((surface, index) => {\n const [rawStart, rawEnd] = surface.segment;\n const clampedStart = Math.max(0, Math.min(rawStart, maxDistance));\n const clampedEnd = Math.max(0, Math.min(rawEnd, maxDistance));\n const segStart = Math.min(clampedStart, clampedEnd);\n const segEnd = Math.max(clampedStart, clampedEnd);\n if (segEnd <= segStart) {\n return null;\n }\n\n const startX = scale(segStart);\n const endX = scale(segEnd);\n const x = Math.min(startX, endX);\n const width = Math.max(0, Math.abs(endX - startX));\n if (width <= 0) {\n return null;\n }\n\n return (\n <rect\n key={`${surface.type}-${index}`}\n x={x}\n y={stripY}\n width={width}\n height={height}\n fill={`url(#surface-${surface.type})`}\n />\n );\n })}\n </g>\n </>\n );\n};\n","import type { TooltipProps } from \"recharts\";\nimport { useTheme } from \"../../../theme-provider\";\nimport type { RouteConfig, SurfaceType } from \"../../../types\";\nimport { SURFACE_TEXTURES } from \"./SurfaceStrip\";\n\ninterface ElevationTooltipProps extends TooltipProps<number, string> {\n accent: string;\n primary: string;\n markers: Array<{ distance: number; name?: string }>;\n surfaces?: RouteConfig[\"surface\"];\n routes?: RouteConfig[\"routes\"];\n}\n\nconst MARKER_DISTANCE_TOLERANCE_MATCH = 300; // meters\n\nconst getSurfaceForDistance = (\n surfaces: RouteConfig[\"surface\"],\n distance: number\n) => {\n if (!surfaces?.length) return null;\n return (\n surfaces.find((surface) => {\n const [start, end] = surface.segment;\n const segStart = Math.min(start, end);\n const segEnd = Math.max(start, end);\n return distance >= segStart && distance <= segEnd;\n }) ?? null\n );\n};\n\nconst getRouteForDistance = (\n routes: RouteConfig[\"routes\"],\n distance: number\n) => {\n if (!routes?.length) return null;\n return (\n routes.find((route) => {\n const [start, end] = route.segment;\n const segStart = Math.min(start, end);\n const segEnd = Math.max(start, end);\n return distance >= segStart && distance <= segEnd;\n }) ?? null\n );\n};\n\nconst formatSurfaceLabel = (surface: SurfaceType) =>\n surface.charAt(0).toUpperCase() + surface.slice(1);\n\nconst formatSegmentLabel = (segment: [number, number]) => {\n const [start, end] = segment;\n const segStart = Math.min(start, end);\n const segEnd = Math.max(start, end);\n const formatKm = (value: number) => {\n const km = value / 1000;\n const rounded = km.toFixed(1);\n return rounded.endsWith(\".0\") ? rounded.slice(0, -2) : rounded;\n };\n return `(${formatKm(segStart)} km - ${formatKm(segEnd)} km)`;\n};\n\nexport const ElevationTooltip = ({\n active,\n payload,\n label,\n accent,\n primary,\n markers,\n surfaces,\n routes,\n}: ElevationTooltipProps) => {\n const { tooltip } = useTheme();\n\n if (!active || !payload?.length) return null;\n\n const point = payload[0]?.payload;\n const distance = (point?.distance as number | undefined) ?? (label as number);\n const marker = markers.find(\n (m) =>\n Math.abs((m?.distance ?? -1) - (point?.distance ?? 0)) <=\n MARKER_DISTANCE_TOLERANCE_MATCH\n );\n const surface = getSurfaceForDistance(surfaces, distance);\n const surfaceTexture = surface?.type ? SURFACE_TEXTURES[surface.type] : null;\n const routeSegment = getRouteForDistance(routes, distance);\n\n const km = Math.trunc((label as number) / 1000);\n const m = Math.round((label as number) % 1000);\n\n return (\n <div\n style={{\n background: tooltip.background,\n border: \"none\",\n color: tooltip.textColor,\n padding: \"4px 6px\",\n borderRadius: tooltip.borderRadius,\n fontSize: 13,\n lineHeight: 1.2,\n }}\n >\n <div style={{ fontWeight: 600, color: primary }}>\n {km} km {m} m\n </div>\n <div>\n Elevation: <strong>{Math.round(point?.elevation ?? 0)} m</strong>\n </div>\n {surface?.type ? (\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 4 }}>\n <svg\n width=\"20\"\n height=\"14\"\n aria-hidden=\"true\"\n style={{ display: \"block\" }}\n >\n {surfaceTexture ? (\n <image\n href={surfaceTexture.file}\n x=\"0\"\n y=\"0\"\n width=\"20\"\n height=\"14\"\n preserveAspectRatio=\"xMidYMid slice\"\n />\n ) : (\n <rect width=\"20\" height=\"14\" fill={tooltip.textColor} />\n )}\n </svg>\n <span>{formatSurfaceLabel(surface.type)}</span>\n <span>{formatSegmentLabel(surface.segment)}</span>\n </div>\n ) : null}\n {routeSegment ? (\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 4 }}>\n <svg\n width=\"20\"\n height=\"14\"\n aria-hidden=\"true\"\n style={{ display: \"block\" }}\n >\n <rect width=\"20\" height=\"14\" fill={routeSegment.color} />\n </svg>\n <span>{routeSegment.id}</span>\n <span>{formatSegmentLabel(routeSegment.segment)}</span>\n </div>\n ) : null}\n {marker?.name ? (\n <div style={{ color: accent, fontWeight: 600 }}>{marker.name}</div>\n ) : null}\n </div>\n );\n};\n","<svg stroke=\"currentColor\" fill=\"#84CC16\" stroke-width=\"2\" viewBox=\"0 0 24 24\" aria-hidden=\"true\" height=\"200px\" width=\"200px\" xmlns=\"http://www.w3.org/2000/svg\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z\"></path>\n <path fill=\"white\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M15 11a3 3 0 11-6 0 3 3 0 016 0z\"></path>\n</svg>\n","import markerSvg from \"../../assets/icons/marker.svg?raw\";\nimport markerFinishSvg from \"../../assets/icons/markerFinish.svg?raw\";\nimport markerStartSvg from \"../../assets/icons/markerStart.svg?raw\";\n\nconst svgTemplate = (base: string, outer: string, inner: string) => {\n let fillIndex = 0;\n return base.replace(/fill=\"[^\"]*\"/g, (match) => {\n fillIndex += 1;\n if (fillIndex === 1) return `fill=\"${outer}\"`;\n if (fillIndex === 2) return `fill=\"${inner}\"`;\n return match;\n });\n};\n\nexport const buildMarkerIcon = (outer: string, inner: string) => {\n const svg = svgTemplate(markerSvg, outer, inner).trim();\n const encoded = encodeURIComponent(svg)\n .replace(/'/g, \"%27\")\n .replace(/\"/g, \"%22\");\n return `data:image/svg+xml,${encoded}`;\n};\n\nexport const markers = {\n default: markerSvg,\n start: markerStartSvg,\n finish: markerFinishSvg,\n};","import { useId, useMemo } from \"react\";\nimport { useTheme } from \"../../../theme-provider\";\nimport { buildMarkerIcon } from \"../../icons/buildMarkerIcon\";\nimport { MapDot } from \"./ElevationDot\";\n\nexport const MarkerShape = (props: any) => {\n const { cx, cy, fill, name } = props;\n const theme = useTheme();\n const layout = theme.markerShape;\n const size = layout.size;\n\n const iconHref = useMemo(\n () => buildMarkerIcon(theme.marker.outer, theme.marker.inner),\n [theme.marker.inner, theme.marker.outer]\n );\n\n if (cx === undefined || cy === undefined) return null;\n\n const words =\n typeof name === \"string\"\n ? name\n .split(/\\s+/)\n .map((w) => w.trim())\n .filter(Boolean)\n : [];\n return (\n <g>\n <MapDot cx={cx} cy={cy} />\n <image\n x={cx - size / 2}\n y={cy - size / 2 - layout.lift}\n width={size}\n height={size}\n href={iconHref}\n />\n {name ? <Text words={words} cx={cx} cy={cy} fill={fill} /> : null}\n </g>\n );\n};\n\nconst Text = ({\n words,\n cx,\n cy,\n fill,\n}: {\n words: string[];\n cx: number;\n cy: number;\n fill?: string;\n}) => {\n const theme = useTheme();\n const text = theme.markerShape.text;\n\n return (\n <text\n y={cy - words.length * text.startLiftPerWord}\n fill={fill || \"#fff\"}\n fontSize={text.fontSize}\n fontWeight={text.fontWeight}\n letterSpacing={text.letterSpacing}\n style={{ userSelect: \"none\" }}\n >\n {words.map((word, index) => (\n <Word key={word} word={word} index={index} cx={cx} />\n ))}\n </text>\n );\n};\n\nconst Word = ({\n word,\n index,\n cx,\n}: {\n word: string;\n index: number;\n cx: number;\n}) => {\n const theme = useTheme();\n const text = theme.markerShape.text;\n const id = useId();\n return (\n <tspan\n key={id}\n x={cx + text.xOffset}\n dy={index === 0 ? 0 : text.lineHeight}\n >\n {word}\n </tspan>\n );\n};\n","import type { RouteConfig } from \"../../../types\";\n\nexport const ROUTE_STRIP_HEIGHT = 16;\n\ntype RouteStripProps = {\n route: RouteConfig;\n maxDistance: number;\n belowHeight?: number;\n xAxisMap?: Record<\n string,\n {\n scale?: (value: number) => number;\n x?: number;\n y?: number;\n width?: number;\n }\n >;\n offset?: { left?: number; top?: number; width?: number; height?: number };\n};\n\nexport const RouteStrip = ({\n route,\n maxDistance,\n belowHeight = 0,\n xAxisMap,\n offset,\n}: RouteStripProps) => {\n const routes = route.routes ?? [];\n if (!routes.length) {\n return null;\n }\n\n const xAxis = xAxisMap ? Object.values(xAxisMap)[0] : undefined;\n const scale = xAxis?.scale;\n const chartLeft = xAxis?.x ?? offset?.left ?? 0;\n const chartWidth = xAxis?.width ?? offset?.width ?? 0;\n const axisY = xAxis?.y ?? (offset?.top ?? 0) + (offset?.height ?? 0);\n const height = ROUTE_STRIP_HEIGHT;\n const stripY = axisY - belowHeight - height;\n\n if (!scale || chartWidth <= 0) {\n return null;\n }\n\n return (\n <g>\n <rect\n x={chartLeft}\n y={stripY}\n width={chartWidth}\n height={height}\n fill=\"none\"\n />\n {routes.map((routeSegment, index) => {\n const [rawStart, rawEnd] = routeSegment.segment;\n const clampedStart = Math.max(0, Math.min(rawStart, maxDistance));\n const clampedEnd = Math.max(0, Math.min(rawEnd, maxDistance));\n const segStart = Math.min(clampedStart, clampedEnd);\n const segEnd = Math.max(clampedStart, clampedEnd);\n if (segEnd <= segStart) {\n return null;\n }\n\n const startX = scale(segStart);\n const endX = scale(segEnd);\n const x = Math.min(startX, endX);\n const width = Math.max(0, Math.abs(endX - startX));\n if (width <= 0) {\n return null;\n }\n\n return (\n <g key={`${routeSegment.id}-${index}`}>\n <rect\n x={x}\n y={stripY}\n width={width}\n height={height}\n fill={routeSegment.color}\n />\n <text\n x={x + width / 2}\n y={stripY + height / 2}\n fill=\"#000000\"\n fontSize={10}\n fontWeight={600}\n textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n >\n {routeSegment.id}\n </text>\n </g>\n );\n })}\n </g>\n );\n};\n","import { useCallback, useMemo, useState } from \"react\";\n\nexport function useTriggerByXValue<\n T extends { distance: number; elevation: number }\n>(data: T[]) {\n const [activeIndex, setActiveIndex] = useState<number | null>(null);\n\n const activePoint = useMemo(\n () => (activeIndex != null ? data[activeIndex] : null),\n [activeIndex, data]\n );\n\n const clearActiveIndex = useCallback(() => {\n setActiveIndex(null);\n }, []);\n\n const triggerByXValue = useCallback(\n (distance: number) => {\n if (!data.length) return;\n\n // assume data sorted by distance ascending\n let lo = 0;\n let hi = data.length - 1;\n\n // binary search for closest distance\n while (lo < hi) {\n const mid = Math.floor((lo + hi) / 2);\n if (data[mid].distance < distance) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n\n // lo is first >= distance; pick closer of lo and lo-1\n let bestIndex = lo;\n if (lo > 0) {\n const prev = data[lo - 1];\n const curr = data[lo];\n if (\n Math.abs(prev.distance - distance) <\n Math.abs(curr.distance - distance)\n ) {\n bestIndex = lo - 1;\n }\n }\n\n setActiveIndex(bestIndex);\n },\n [data]\n );\n\n return {\n activeIndex,\n activePoint,\n triggerByXValue,\n clearActiveIndex,\n };\n}\n","import type { ElevationPoint, Marker } from \"./types\";\n\nexport const getMaxDistance = (points: ElevationPoint[]) =>\n points.length ? points[points.length - 1].distance : 0;\n\nexport const getTicksForDistance = (maxDistance: number, step: number = 2000) => {\n const ticks: number[] = [];\n for (let d = 0; d <= maxDistance; d += step) {\n ticks.push(d);\n }\n if (ticks[ticks.length - 1] < maxDistance) {\n ticks.push(maxDistance);\n }\n return ticks;\n}\n\nexport const getPointsWithElevation = (route: any): ElevationPoint[] => {\n const geo = route.geoJson as any;\n const line = geo?.features?.find(\n (f: any) =>\n f?.geometry?.type === \"LineString\" &&\n f?.properties?.elevationProfile?.points\n );\n const raw = line?.properties?.elevationProfile?.points || [];\n return [...raw].sort(\n (a: ElevationPoint, b: ElevationPoint) => (a?.distance ?? 0) - (b?.distance ?? 0)\n );\n};\n\nexport const getAllPoints = (route: any): [number, number][] => {\n const geo = route.geoJson as any;\n const points = geo?.features?.find(\n (f: any) =>\n f?.geometry?.type === \"LineString\" &&\n f?.geometry?.coordinates\n );\n return points.geometry.coordinates\n}\n\nexport const computeMinMax = (points: Array<{ elevation: number }>) => {\n if (!points.length) return [0, 0] as const;\n const elevations = points.map((p) => p.elevation);\n const min = Math.min(...elevations);\n const max = Math.max(...elevations);\n const pad = Math.max(10, (max - min) * 0.05);\n return [Math.floor(min - pad), Math.ceil(max + pad)];\n};\n\nexport const computeRoundedDomainAndTicks = (\n minMax: [number, number],\n shouldOffset: boolean = false\n) => {\n const [min, max] = minMax;\n const paddedRange = (max - min) * 1.2;\n const step = Math.max(10, Math.round(paddedRange / 6 / 10) * 10 || 50);\n const offset = shouldOffset ? -20 : 0;\n const graphMin =\n Math.floor((min - (paddedRange - (max - min)) / 2) / step) * step +\n offset;\n const graphMax =\n Math.ceil((max + (paddedRange - (max - min)) / 2) / step) * step +\n offset;\n const ticks: number[] = [];\n for (let v = graphMin; v <= graphMax + step / 2; v += step) {\n ticks.push(v);\n }\n\n return [graphMin, graphMax, ticks] as const;\n};\n\nexport const computeMarkerPoints = (\n elevationPoints: ElevationPoint[],\n geoJson: any\n) => {\n if (!elevationPoints?.length) return [];\n const features = geoJson?.features ?? [];\n const pointFeatures = features.filter(\n (f: any) => f?.geometry?.type === \"Point\"\n );\n\n const markers: Array<Marker> = [];\n\n pointFeatures.forEach((f: any) => {\n const coords = f?.geometry?.coordinates;\n if (!Array.isArray(coords) || coords.length < 2) return;\n const [lng, lat] = coords;\n if (!Number.isFinite(lat) || !Number.isFinite(lng)) return;\n const nearest = elevationPoints.reduce<{\n point: ElevationPoint | null;\n dist: number;\n }>(\n (acc, p) => {\n const d = Math.pow(p.lat - lat, 2) + Math.pow(p.lng - lng, 2);\n if (d < acc.dist) {\n return { point: p, dist: d };\n }\n return acc;\n },\n { point: null, dist: Number.POSITIVE_INFINITY }\n );\n if (nearest.point) {\n // Skip if this marker matches the very first elevation point (start of route)\n if (nearest.point.distance === 0) {\n return;\n }\n markers.push({\n distance: nearest.point.distance,\n elevation: nearest.point.elevation,\n name: f?.properties?.name,\n });\n }\n });\n\n return markers.sort((a, b) => (a.distance ?? 0) - (b.distance ?? 0));\n};\n\nexport const findNearestPointByCoordinates = (\n points: [number, number][],\n target: { lat: number; lng: number }\n): ElevationPoint | null => {\n if (!points.length) return null;\n let closest: ElevationPoint | null = null;\n let minDist = Number.POSITIVE_INFINITY;\n points.forEach(([lng, lat]) => {\n const d = ((lat - target.lat) ** 2) + ((lng - target.lng) ** 2);\n if (d < minDist) {\n minDist = d;\n closest = { lat, lng } as ElevationPoint;\n }\n });\n return closest;\n};\n\nexport const findNearestPoint = (\n points: ElevationPoint[],\n target: [number, number]\n): ElevationPoint | null => {\n if (!points.length) return null;\n let closest: ElevationPoint | null = null;\n let minDist = Number.POSITIVE_INFINITY;\n points.forEach((p) => {\n const d = ((p.lat - target[0]) ** 2) + ((p.lng - target[1]) ** 2);\n if (d < minDist) {\n minDist = d;\n closest = p;\n }\n });\n return closest;\n};\n\nconst DISTANCE_THRESHOLD = 1000; // meters\n\nexport const isCloseCheck = (\n marker1: Marker,\n marker2?: Marker,\n threshold: number = DISTANCE_THRESHOLD\n) => {\n return (\n marker2 &&\n Math.abs((marker2.distance ?? 0) - (marker1.distance ?? 0)) < threshold\n );\n};\n","import { useEffect, useMemo } from \"react\";\nimport {\n CartesianGrid,\n ComposedChart,\n Customized,\n Line,\n ReferenceDot,\n ReferenceLine,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from \"recharts\";\nimport { useTheme } from \"../../../theme-provider\";\nimport type { RouteConfig } from \"../../../types\";\nimport { HoverStateChangeSource, useHover } from \"../HoverContext\";\nimport { DistanceTick } from \"./DistanceTick\";\nimport { ElevationDot } from \"./ElevationDot\";\nimport { ElevationTick } from \"./ElevationTick\";\nimport { ElevationTooltip } from \"./ElevationTooltip\";\nimport { MarkerShape } from \"./MarkerShape\";\nimport { RouteStrip } from \"./RouteStrip\";\nimport { SURFACE_STRIP_HEIGHT, SurfaceStrip } from \"./SurfaceStrip\";\nimport { useTriggerByXValue } from \"./useTriggerByXValue\";\nimport {\n computeMarkerPoints,\n computeMinMax,\n computeRoundedDomainAndTicks,\n findNearestPoint,\n getMaxDistance,\n getPointsWithElevation,\n getTicksForDistance,\n isCloseCheck,\n} from \"./utils\";\n\ninterface ElevationChartProps {\n route: RouteConfig;\n}\n\nexport const ElevationChart = ({ route }: ElevationChartProps) => {\n const { hover, setHover } = useHover();\n const theme = useTheme();\n const points = useMemo(() => getPointsWithElevation(route), [route]);\n const markers = useMemo(\n () => computeMarkerPoints(points, route.geoJson),\n [points, route.geoJson]\n );\n const maxDistance = getMaxDistance(points);\n const ticks = getTicksForDistance(maxDistance);\n const [min, max] = computeMinMax(points);\n const [minY, maxY, tickVals] = useMemo(\n () => computeRoundedDomainAndTicks([min, max], !!route.surface?.length),\n [min, max, route.surface?.length]\n );\n\n const { activeIndex, activePoint, triggerByXValue, clearActiveIndex } =\n useTriggerByXValue(points);\n\n useEffect(() => {\n if (\n hover.source === HoverStateChangeSource.Chart ||\n !hover.lat ||\n !hover.lng\n )\n return;\n const nearestPoint = findNearestPoint(points, [hover.lat, hover.lng]);\n if (nearestPoint) {\n triggerByXValue(nearestPoint.distance);\n }\n }, [hover, points, triggerByXValue]);\n\n if (!points.length) {\n return null;\n }\n\n return (\n <ResponsiveContainer\n width=\"100%\"\n height=\"100%\"\n style={{ userSelect: \"none\" }}\n >\n <ComposedChart\n data={points}\n margin={theme.chart.margin}\n onMouseMove={({ activePayload }) => {\n activeIndex && clearActiveIndex();\n const activePayloadItem = activePayload?.[0];\n if (!activePayloadItem) {\n return;\n }\n const { lat, lng } = activePayloadItem.payload;\n setHover({ lat, lng, source: HoverStateChangeSource.Chart });\n }}\n onMouseEnter={() => clearActiveIndex()}\n >\n <defs>\n <linearGradient id=\"elevationGradient\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop\n offset=\"0%\"\n stopColor={theme.colors.primary}\n stopOpacity={theme.chart.gradientStartOpacity}\n />\n <stop\n offset=\"100%\"\n stopColor={theme.colors.primaryMuted}\n stopOpacity={theme.chart.gradientEndOpacity}\n />\n </linearGradient>\n </defs>\n\n <CartesianGrid\n stroke={theme.chart.gridStroke}\n strokeDasharray={theme.chart.gridDasharray}\n />\n <Customized\n component={\n <RouteStrip\n route={route}\n maxDistance={maxDistance}\n belowHeight={SURFACE_STRIP_HEIGHT}\n />\n }\n />\n <Customized\n component={<SurfaceStrip route={route} maxDistance={maxDistance} />}\n />\n <XAxis\n dataKey=\"distance\"\n type=\"number\"\n domain={[0, maxDistance]}\n ticks={ticks}\n tick={<DistanceTick />}\n stroke={theme.chart.axisStroke}\n />\n <YAxis\n dataKey=\"elevation\"\n tick={<ElevationTick />}\n domain={[minY, maxY]}\n ticks={tickVals}\n stroke={theme.chart.axisStroke}\n width={theme.chart.yAxisWidth}\n />\n\n <Tooltip\n cursor={{\n stroke: theme.chart.cursorStroke,\n strokeWidth: theme.chart.cursorStrokeWidth,\n }}\n content={\n <ElevationTooltip\n accent={theme.colors.accent}\n primary={theme.colors.primary}\n markers={markers}\n surfaces={route.surface}\n routes={route.routes}\n />\n }\n />\n\n <Line\n type=\"monotone\"\n dataKey=\"elevation\"\n stroke={theme.colors.primary}\n strokeWidth={theme.chart.lineStrokeWidth}\n // @ts-ignore\n dot={(props) => {\n const { cx, cy, index } = props;\n const isActive = index === activeIndex;\n\n if (isActive && activePoint) {\n return <ElevationDot cx={cx} cy={cy} key={`dot-${cx}-${cy}`} />;\n }\n }}\n activeDot={{\n r: theme.chart.activeDotRadius,\n fill: theme.dots.chartActive,\n strokeWidth: 0,\n }}\n fill=\"url(#elevationGradient)\"\n isAnimationActive={false}\n />\n\n {markers.length > 0 &&\n markers.map((m, idx) => {\n const tooClose = isCloseCheck(markers[idx], markers[idx + 1]);\n return (\n <ReferenceDot\n key={`${m.distance}-${idx}`}\n x={m.distance}\n y={m.elevation}\n r={theme.chart.referenceDotRadius}\n shape={(props) => (\n <MarkerShape\n {...props}\n name={tooClose ? undefined : m.name}\n fill={theme.colors.accent}\n />\n )}\n />\n );\n })}\n\n {/* Vertical line at active X (same as hover cursor) */}\n {activePoint && (\n <ReferenceLine\n x={activePoint.distance}\n opacity={theme.chart.referenceLineOpacity}\n />\n )}\n </ComposedChart>\n </ResponsiveContainer>\n );\n};\n","import markerSvg from \"./assets/icons/marker.svg\";\nimport markerFinishSvg from \"./assets/icons/markerFinish.svg\";\nimport markerStartSvg from \"./assets/icons/markerStart.svg\";\n\nexport const DEFAULT_CENTER = { lat: 48.9325937, lng: 20.3452306 };\nexport const DEFAULT_ZOOM_HORIZONTAL = 13;\nexport const DEFAULT_ZOOM_VERTICAL = 12;\n\nexport const markers = {\n default: markerSvg,\n start: markerStartSvg,\n finish: markerFinishSvg,\n}\n","import { useEffect, useMemo, useRef } from \"react\";\nimport {\n DEFAULT_CENTER,\n DEFAULT_ZOOM_HORIZONTAL,\n DEFAULT_ZOOM_VERTICAL,\n} from \"../../constants\";\nimport { useTheme } from \"../../theme-provider\";\nimport type { RouteConfig } from \"../../types\";\nimport { buildMarkerIcon } from \"../icons/buildMarkerIcon\";\nimport {\n findNearestPointByCoordinates,\n getAllPoints,\n} from \"./ElevationChart/utils\";\nimport styles from \"./GoogleMapCanvas.module.css\";\nimport { HoverStateChangeSource, useHover } from \"./HoverContext\";\n\ninterface GoogleMapCanvasProps {\n route: RouteConfig;\n height: number | string;\n isHorizontal: boolean;\n}\n\nexport const GoogleMapCanvas = ({\n route,\n height,\n isHorizontal,\n}: GoogleMapCanvasProps) => {\n const theme = useTheme();\n const { hover, setHover } = useHover();\n const ref = useRef<HTMLDivElement | null>(null);\n const highlightMarkerRef = useRef<google.maps.Marker | null>(null);\n const mapRef = useRef<google.maps.Map | null>(null);\n const points = useMemo(() => getAllPoints(route), [route]);\n const markerIcons = useMemo(\n () => ({\n default: buildMarkerIcon(theme.marker.outer, theme.marker.inner),\n start: buildMarkerIcon(theme.marker.outer, theme.marker.startInner),\n finish: buildMarkerIcon(theme.marker.outer, theme.marker.finishInner),\n }),\n [theme.marker]\n );\n\n useEffect(() => {\n if (!ref.current || !window.google?.maps) {\n return;\n }\n\n const zoom =\n (isHorizontal && (route.zoomHorizontal || DEFAULT_ZOOM_HORIZONTAL)) ||\n route.zoomVertical ||\n DEFAULT_ZOOM_VERTICAL;\n\n const map = new window.google.maps.Map(ref.current, {\n center: route.center || DEFAULT_CENTER,\n zoom,\n mapTypeId: window.google.maps.MapTypeId.SATELLITE,\n streetViewControl: false,\n });\n mapRef.current = map;\n\n map.data.setStyle((feature: google.maps.Data.Feature) => {\n const name = feature.getProperty(\"name\") as string;\n const isFirst = feature.getProperty(\"first\") as boolean;\n const isLast = feature.getProperty(\"last\") as boolean;\n\n return {\n strokeColor: theme.colors.primaryMuted,\n strokeWeight: theme.map.strokeWeight,\n icon: {\n url: isFirst\n ? markerIcons.start\n : isLast\n ? markerIcons.finish\n : markerIcons.default,\n scaledSize: new window.google.maps.Size(\n theme.map.markerSize,\n theme.map.markerSize\n ),\n optimized: false,\n zIndex: isFirst || isLast ? 100 : 10,\n collisionBehavior:\n window.google?.maps?.CollisionBehavior?.REQUIRED_AND_HIDES_OPTIONAL,\n },\n label: {\n className: \"rrpMarkerLabel\",\n fontSize: `${theme.map.markerLabelFontSize}px`,\n fontWeight: theme.map.markerLabelFontWeight,\n color: theme.colors.accent,\n text: name,\n },\n };\n });\n\n map.data.addGeoJson(route.geoJson);\n\n const moveListener = map.addListener(\n \"mousemove\",\n (e: google.maps.MapMouseEvent) => {\n const latLng = e.latLng;\n if (!latLng) return;\n const nearest = findNearestPointByCoordinates(points, {\n lat: latLng.lat(),\n lng: latLng.lng(),\n });\n if (nearest) {\n setHover({\n lat: nearest.lat,\n lng: nearest.lng,\n source: HoverStateChangeSource.Map,\n });\n }\n }\n );\n\n return () => {\n moveListener.remove();\n map.data.forEach((feature: google.maps.Data.Feature) => {\n map.data.remove(feature);\n });\n mapRef.current = null;\n };\n }, [route, isHorizontal, theme, points, setHover, markerIcons]);\n\n useEffect(() => {\n if (!ref.current || !window.google?.maps) return;\n const mapInstance = mapRef.current;\n if (!mapInstance) return;\n if (!hover.lat || !hover.lng) {\n if (highlightMarkerRef.current) {\n highlightMarkerRef.current.setMap(null);\n highlightMarkerRef.current = null;\n }\n return;\n }\n const icon = {\n path: window.google.maps.SymbolPath.CIRCLE,\n scale: theme.map.hoverMarkerScale,\n fillColor: theme.dots.mapActive,\n fillOpacity: 1,\n strokeWeight: 0,\n };\n if (!highlightMarkerRef.current) {\n highlightMarkerRef.current = new window.google.maps.Marker({\n map: mapInstance,\n icon,\n });\n } else {\n highlightMarkerRef.current.setIcon(icon);\n }\n highlightMarkerRef.current.setPosition({ lat: hover.lat, lng: hover.lng });\n highlightMarkerRef.current.setMap(mapInstance);\n }, [hover, theme]);\n\n return (\n <div\n ref={ref}\n className={styles.rrpMapCanvas}\n style={{\n height,\n }}\n />\n );\n};\n","import { Status, Wrapper } from \"@googlemaps/react-wrapper\";\nimport type { CSSProperties } from \"react\";\nimport { useOrientation } from \"../../hooks/useOrientation\";\nimport { theme as defaultTheme, type PartialTheme } from \"../../theme\";\nimport { ThemeProvider } from \"../../theme-provider\";\nimport type { RouteConfig } from \"../../types\";\nimport Loader from \"../Loader\";\nimport { ElevationChart } from \"./ElevationChart\";\nimport { GoogleMapCanvas } from \"./GoogleMapCanvas\";\nimport { HoverProvider } from \"./HoverContext\";\nimport styles from \"./RouteMap.module.css\";\n\nexport interface RouteMapProps {\n apiKey: string;\n route: RouteConfig;\n height?: number | string;\n className?: string;\n style?: CSSProperties;\n theme?: PartialTheme;\n}\n\nconst messages = {\n apiKey: \"Oops! Cannot display the map: Google Maps API key missing\",\n [Status.FAILURE]:\n \"Unable to load Google Maps API. Check your API key or network.\",\n [Status.LOADING]: undefined,\n [Status.SUCCESS]: undefined,\n};\n\nconst RenderLoader = ({\n type,\n height,\n}: {\n type: keyof typeof messages;\n height?: number | string;\n}) => (\n <div style={{ height }}>\n <Loader message={messages[type]} height={height} />\n </div>\n);\n\nconst render = (status: Status, height?: number | string) => (\n <RenderLoader type={status} height={height} />\n);\n\nexport const RouteMap = ({\n apiKey,\n route,\n height = \"100dvh\",\n className,\n style,\n theme = defaultTheme,\n}: RouteMapProps) => {\n const { isHorizontal } = useOrientation();\n\n if (!apiKey) {\n return (\n <ThemeProvider theme={theme}>\n <RenderLoader type=\"apiKey\" height={height} />\n </ThemeProvider>\n );\n }\n\n const containerStyle: CSSProperties = {\n height,\n width: \"100%\",\n ...style,\n };\n\n return (\n <ThemeProvider theme={theme}>\n <HoverProvider>\n <div className={className} style={containerStyle}>\n <Wrapper apiKey={apiKey} render={(status) => render(status, height)}>\n <GoogleMapCanvas\n route={route}\n height={height}\n isHorizontal={isHorizontal}\n />\n </Wrapper>\n <div className={styles.rrpChartLayer}>\n <div className={styles.rrpChartBody}>\n <ElevationChart route={route} />\n </div>\n </div>\n </div>\n </HoverProvider>\n </ThemeProvider>\n );\n};\n","import * as React from \"react\";\n\nfunction isShallowEqual(object1, object2) {\n const keys1 = Object.keys(object1);\n const keys2 = Object.keys(object2);\n\n if (keys1.length !== keys2.length) {\n return false;\n }\n\n for (let key of keys1) {\n if (object1[key] !== object2[key]) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction isTouchEvent({ nativeEvent }) {\n return window.TouchEvent\n ? nativeEvent instanceof TouchEvent\n : \"touches\" in nativeEvent;\n}\n\nfunction isMouseEvent(event) {\n return event.nativeEvent instanceof MouseEvent;\n}\n\nfunction throttle(cb, ms) {\n let lastTime = 0;\n return () => {\n const now = Date.now();\n if (now - lastTime >= ms) {\n cb();\n lastTime = now;\n }\n };\n}\n\nfunction isPlainObject(value) {\n return Object.prototype.toString.call(value) === \"[object Object]\";\n}\n\nfunction dispatchStorageEvent(key, newValue) {\n window.dispatchEvent(new StorageEvent(\"storage\", { key, newValue }));\n}\n\nexport function useBattery() {\n const [state, setState] = React.useState({\n supported: true,\n loading: true,\n level: null,\n charging: null,\n chargingTime: null,\n dischargingTime: null,\n });\n\n React.useEffect(() => {\n if (!navigator.getBattery) {\n setState((s) => ({\n ...s,\n supported: false,\n loading: false,\n }));\n return;\n }\n\n let battery = null;\n\n const handleChange = () => {\n setState({\n supported: true,\n loading: false,\n level: battery.level,\n charging: battery.charging,\n chargingTime: battery.chargingTime,\n dischargingTime: battery.dischargingTime,\n });\n };\n\n navigator.getBattery().then((b) => {\n battery = b;\n handleChange();\n\n b.addEventListener(\"levelchange\", handleChange);\n b.addEventListener(\"chargingchange\", handleChange);\n b.addEventListener(\"chargingtimechange\", handleChange);\n b.addEventListener(\"dischargingtimechange\", handleChange);\n });\n\n return () => {\n if (battery) {\n battery.removeEventListener(\"levelchange\", handleChange);\n battery.removeEventListener(\"chargingchange\", handleChange);\n battery.removeEventListener(\"chargingtimechange\", handleChange);\n battery.removeEventListener(\"dischargingtimechange\", handleChange);\n }\n };\n }, []);\n\n return state;\n}\n\nexport function useClickAway(cb) {\n const ref = React.useRef(null);\n const refCb = React.useRef(cb);\n\n React.useLayoutEffect(() => {\n refCb.current = cb;\n });\n\n React.useEffect(() => {\n const handler = (e) => {\n const element = ref.current;\n if (element && !element.contains(e.target)) {\n refCb.current(e);\n }\n };\n\n document.addEventListener(\"mousedown\", handler);\n document.addEventListener(\"touchstart\", handler);\n\n return () => {\n document.removeEventListener(\"mousedown\", handler);\n document.removeEventListener(\"touchstart\", handler);\n };\n }, []);\n\n return ref;\n}\n\nfunction oldSchoolCopy(text) {\n const tempTextArea = document.createElement(\"textarea\");\n tempTextArea.value = text;\n document.body.appendChild(tempTextArea);\n tempTextArea.select();\n document.execCommand(\"copy\");\n document.body.removeChild(tempTextArea);\n}\n\nexport function useCopyToClipboard() {\n const [state, setState] = React.useState(null);\n\n const copyToClipboard = React.useCallback((value) => {\n const handleCopy = async () => {\n try {\n if (navigator?.clipboard?.writeText) {\n await navigator.clipboard.writeText(value);\n setState(value);\n } else {\n throw new Error(\"writeText not supported\");\n }\n } catch (e) {\n oldSchoolCopy(value);\n setState(value);\n }\n };\n\n handleCopy();\n }, []);\n\n return [state, copyToClipboard];\n}\n\nexport function useCounter(startingValue = 0, options = {}) {\n const { min, max } = options;\n\n if (typeof min === \"number\" && startingValue < min) {\n throw new Error(\n `Your starting value of ${startingValue} is less than your min of ${min}.`\n );\n }\n\n if (typeof max === \"number\" && startingValue > max) {\n throw new Error(\n `Your starting value of ${startingValue} is greater than your max of ${max}.`\n );\n }\n\n const [count, setCount] = React.useState(startingValue);\n\n const increment = React.useCallback(() => {\n setCount((c) => {\n const nextCount = c + 1;\n\n if (typeof max === \"number\" && nextCount > max) {\n return c;\n }\n\n return nextCount;\n });\n }, [max]);\n\n const decrement = React.useCallback(() => {\n setCount((c) => {\n const nextCount = c - 1;\n\n if (typeof min === \"number\" && nextCount < min) {\n return c;\n }\n\n return nextCount;\n });\n }, [min]);\n\n const set = React.useCallback(\n (nextCount) => {\n setCount((c) => {\n if (typeof max === \"number\" && nextCount > max) {\n return c;\n }\n\n if (typeof min === \"number\" && nextCount < min) {\n return c;\n }\n\n return nextCount;\n });\n },\n [max, min]\n );\n\n const reset = React.useCallback(() => {\n setCount(startingValue);\n }, [startingValue]);\n\n return [\n count,\n {\n increment,\n decrement,\n set,\n reset,\n },\n ];\n}\n\nexport function useDebounce(value, delay) {\n const [debouncedValue, setDebouncedValue] = React.useState(value);\n\n React.useEffect(() => {\n const handler = setTimeout(() => {\n setDebouncedValue(value);\n }, delay);\n\n return () => {\n clearTimeout(handler);\n };\n }, [value, delay]);\n\n return debouncedValue;\n}\n\nexport function useDefault(initialValue, defaultValue) {\n const [state, setState] = React.useState(initialValue);\n\n if (typeof state === \"undefined\" || state === null) {\n return [defaultValue, setState];\n }\n\n return [state, setState];\n}\n\nexport function useDocumentTitle(title) {\n React.useEffect(() => {\n document.title = title;\n }, [title]);\n}\n\nexport function useFavicon(url) {\n React.useEffect(() => {\n let link = document.querySelector(`link[rel~=\"icon\"]`);\n\n if (!link) {\n link = document.createElement(\"link\");\n link.type = \"image/x-icon\";\n link.rel = \"icon\";\n link.href = url;\n document.head.appendChild(link);\n } else {\n link.href = url;\n }\n }, [url]);\n}\n\nexport function useGeolocation(options = {}) {\n const [state, setState] = React.useState({\n loading: true,\n accuracy: null,\n altitude: null,\n altitudeAccuracy: null,\n heading: null,\n latitude: null,\n longitude: null,\n speed: null,\n timestamp: null,\n error: null,\n });\n\n const optionsRef = React.useRef(options);\n\n React.useEffect(() => {\n const onEvent = ({ coords, timestamp }) => {\n setState({\n loading: false,\n timestamp,\n latitude: coords.latitude,\n longitude: coords.longitude,\n altitude: coords.altitude,\n accuracy: coords.accuracy,\n altitudeAccuracy: coords.altitudeAccuracy,\n heading: coords.heading,\n speed: coords.speed,\n });\n };\n\n const onEventError = (error) => {\n setState((s) => ({\n ...s,\n loading: false,\n error,\n }));\n };\n\n navigator.geolocation.getCurrentPosition(\n onEvent,\n onEventError,\n optionsRef.current\n );\n\n const watchId = navigator.geolocation.watchPosition(\n onEvent,\n onEventError,\n optionsRef.current\n );\n\n return () => {\n navigator.geolocation.clearWatch(watchId);\n };\n }, []);\n\n return state;\n}\n\nconst initialUseHistoryStateState = {\n past: [],\n present: null,\n future: [],\n};\n\nconst useHistoryStateReducer = (state, action) => {\n const { past, present, future } = state;\n\n if (action.type === \"UNDO\") {\n return {\n past: past.slice(0, past.length - 1),\n present: past[past.length - 1],\n future: [present, ...future],\n };\n } else if (action.type === \"REDO\") {\n return {\n past: [...past, present],\n present: future[0],\n future: future.slice(1),\n };\n } else if (action.type === \"SET\") {\n const { newPresent } = action;\n\n if (action.newPresent === present) {\n return state;\n }\n\n return {\n past: [...past, present],\n present: newPresent,\n future: [],\n };\n } else if (action.type === \"CLEAR\") {\n return {\n ...initialUseHistoryStateState,\n present: action.initialPresent,\n };\n } else {\n throw new Error(\"Unsupported action type\");\n }\n};\n\nexport function useHistoryState(initialPresent = {}) {\n const initialPresentRef = React.useRef(initialPresent);\n\n const [state, dispatch] = React.useReducer(useHistoryStateReducer, {\n ...initialUseHistoryStateState,\n present: initialPresentRef.current,\n });\n\n const canUndo = state.past.length !== 0;\n const canRedo = state.future.length !== 0;\n\n const undo = React.useCallback(() => {\n if (canUndo) {\n dispatch({ type: \"UNDO\" });\n }\n }, [canUndo]);\n\n const redo = React.useCallback(() => {\n if (canRedo) {\n dispatch({ type: \"REDO\" });\n }\n }, [canRedo]);\n\n const set = React.useCallback(\n (newPresent) => dispatch({ type: \"SET\", newPresent }),\n []\n );\n\n const clear = React.useCallback(\n () =>\n dispatch({ type: \"CLEAR\", initialPresent: initialPresentRef.current }),\n []\n );\n\n return { state: state.present, set, undo, redo, clear, canUndo, canRedo };\n}\n\nexport function useHover() {\n const [hovering, setHovering] = React.useState(false);\n const previousNode = React.useRef(null);\n\n const handleMouseEnter = React.useCallback(() => {\n setHovering(true);\n }, []);\n\n const handleMouseLeave = React.useCallback(() => {\n setHovering(false);\n }, []);\n\n const customRef = React.useCallback(\n (node) => {\n if (previousNode.current?.nodeType === Node.ELEMENT_NODE) {\n previousNode.current.removeEventListener(\n \"mouseenter\",\n handleMouseEnter\n );\n previousNode.current.removeEventListener(\n \"mouseleave\",\n handleMouseLeave\n );\n }\n\n if (node?.nodeType === Node.ELEMENT_NODE) {\n node.addEventListener(\"mouseenter\", handleMouseEnter);\n node.addEventListener(\"mouseleave\", handleMouseLeave);\n }\n\n previousNode.current = node;\n },\n [handleMouseEnter, handleMouseLeave]\n );\n\n return [customRef, hovering];\n}\n\nexport function useIdle(ms = 1000 * 60) {\n const [idle, setIdle] = React.useState(false);\n\n React.useEffect(() => {\n let timeoutId;\n\n const handleTimeout = () => {\n setIdle(true);\n };\n\n const handleEvent = throttle((e) => {\n setIdle(false);\n\n window.clearTimeout(timeoutId);\n timeoutId = window.setTimeout(handleTimeout, ms);\n }, 500);\n\n const handleVisibilityChange = () => {\n if (!document.hidden) {\n handleEvent();\n }\n };\n\n timeoutId = window.setTimeout(handleTimeout, ms);\n\n window.addEventListener(\"mousemove\", handleEvent);\n window.addEventListener(\"mousedown\", handleEvent);\n window.addEventListener(\"resize\", handleEvent);\n window.addEventListener(\"keydown\", handleEvent);\n window.addEventListener(\"touchstart\", handleEvent);\n window.addEventListener(\"wheel\", handleEvent);\n document.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n return () => {\n window.removeEventListener(\"mousemove\", handleEvent);\n window.removeEventListener(\"mousedown\", handleEvent);\n window.removeEventListener(\"resize\", handleEvent);\n window.removeEventListener(\"keydown\", handleEvent);\n window.removeEventListener(\"touchstart\", handleEvent);\n window.removeEventListener(\"wheel\", handleEvent);\n document.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n window.clearTimeout(timeoutId);\n };\n }, [ms]);\n\n return idle;\n}\n\nexport function useIntersectionObserver(options = {}) {\n const { threshold = 1, root = null, rootMargin = \"0px\" } = options;\n const [entry, setEntry] = React.useState(null);\n\n const previousObserver = React.useRef(null);\n\n const customRef = React.useCallback(\n (node) => {\n if (previousObserver.current) {\n previousObserver.current.disconnect();\n previousObserver.current = null;\n }\n\n if (node?.nodeType === Node.ELEMENT_NODE) {\n const observer = new IntersectionObserver(\n ([entry]) => {\n setEntry(entry);\n },\n { threshold, root, rootMargin }\n );\n\n observer.observe(node);\n previousObserver.current = observer;\n }\n },\n [threshold, root, rootMargin]\n );\n\n return [customRef, entry];\n}\n\nexport function useIsClient() {\n const [isClient, setIsClient] = React.useState(false);\n\n React.useEffect(() => {\n setIsClient(true);\n }, []);\n\n return isClient;\n}\n\nexport function useIsFirstRender() {\n const renderRef = React.useRef(true);\n\n if (renderRef.current === true) {\n renderRef.current = false;\n return true;\n }\n\n return renderRef.current;\n}\n\nexport function useList(defaultList = []) {\n const [list, setList] = React.useState(defaultList);\n\n const set = React.useCallback((l) => {\n setList(l);\n }, []);\n\n const push = React.useCallback((element) => {\n setList((l) => [...l, element]);\n }, []);\n\n const removeAt = React.useCallback((index) => {\n setList((l) => [...l.slice(0, index), ...l.slice(index + 1)]);\n }, []);\n\n const insertAt = React.useCallback((index, element) => {\n setList((l) => [...l.slice(0, index), element, ...l.slice(index)]);\n }, []);\n\n const updateAt = React.useCallback((index, element) => {\n setList((l) => l.map((e, i) => (i === index ? element : e)));\n }, []);\n\n const clear = React.useCallback(() => setList([]), []);\n\n return [list, { set, push, removeAt, insertAt, updateAt, clear }];\n}\n\nconst setLocalStorageItem = (key, value) => {\n const stringifiedValue = JSON.stringify(value);\n window.localStorage.setItem(key, stringifiedValue);\n dispatchStorageEvent(key, stringifiedValue);\n};\n\nconst removeLocalStorageItem = (key) => {\n window.localStorage.removeItem(key);\n dispatchStorageEvent(key, null);\n};\n\nconst getLocalStorageItem = (key) => {\n return window.localStorage.getItem(key);\n};\n\nconst useLocalStorageSubscribe = (callback) => {\n window.addEventListener(\"storage\", callback);\n return () => window.removeEventListener(\"storage\", callback);\n};\n\nconst getLocalStorageServerSnapshot = () => {\n throw Error(\"useLocalStorage is a client-only hook\");\n};\n\nexport function useLocalStorage(key, initialValue) {\n const getSnapshot = () => getLocalStorageItem(key);\n\n const store = React.useSyncExternalStore(\n useLocalStorageSubscribe,\n getSnapshot,\n getLocalStorageServerSnapshot\n );\n\n const setState = React.useCallback(\n (v) => {\n try {\n const nextState = typeof v === \"function\" ? v(JSON.parse(store)) : v;\n\n if (nextState === undefined || nextState === null) {\n removeLocalStorageItem(key);\n } else {\n setLocalStorageItem(key, nextState);\n }\n } catch (e) {\n console.warn(e);\n }\n },\n [key, store]\n );\n\n React.useEffect(() => {\n if (\n getLocalStorageItem(key) === null &&\n typeof initialValue !== \"undefined\"\n ) {\n setLocalStorageItem(key, initialValue);\n }\n }, [key, initialValue]);\n\n return [store ? JSON.parse(store) : initialValue, setState];\n}\n\nexport function useLockBodyScroll() {\n React.useLayoutEffect(() => {\n const originalStyle = window.getComputedStyle(document.body).overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = originalStyle;\n };\n }, []);\n}\n\nexport function useLongPress(callback, options = {}) {\n const { threshold = 400, onStart, onFinish, onCancel } = options;\n const isLongPressActive = React.useRef(false);\n const isPressed = React.useRef(false);\n const timerId = React.useRef();\n\n return React.useMemo(() => {\n if (typeof callback !== \"function\") {\n return {};\n }\n\n const start = (event) => {\n if (!isMouseEvent(event) && !isTouchEvent(event)) return;\n\n if (onStart) {\n onStart(event);\n }\n\n isPressed.current = true;\n timerId.current = setTimeout(() => {\n callback(event);\n isLongPressActive.current = true;\n }, threshold);\n };\n\n const cancel = (event) => {\n if (!isMouseEvent(event) && !isTouchEvent(event)) return;\n\n if (isLongPressActive.current) {\n if (onFinish) {\n onFinish(event);\n }\n } else if (isPressed.current) {\n if (onCancel) {\n onCancel(event);\n }\n }\n\n isLongPressActive.current = false;\n isPressed.current = false;\n\n if (timerId.current) {\n window.clearTimeout(timerId.current);\n }\n };\n\n const mouseHandlers = {\n onMouseDown: start,\n onMouseUp: cancel,\n onMouseLeave: cancel,\n };\n\n const touchHandlers = {\n onTouchStart: start,\n onTouchEnd: cancel,\n };\n\n return {\n ...mouseHandlers,\n ...touchHandlers,\n };\n }, [callback, threshold, onCancel, onFinish, onStart]);\n}\n\nexport function useMap(initialState) {\n const mapRef = React.useRef(new Map(initialState));\n const [, reRender] = React.useReducer((x) => x + 1, 0);\n\n mapRef.current.set = (...args) => {\n Map.prototype.set.apply(mapRef.current, args);\n reRender();\n return mapRef.current;\n };\n\n mapRef.current.clear = (...args) => {\n Map.prototype.clear.apply(mapRef.current, args);\n reRender();\n };\n\n mapRef.current.delete = (...args) => {\n const res = Map.prototype.delete.apply(mapRef.current, args);\n reRender();\n\n return res;\n };\n\n return mapRef.current;\n}\n\nexport function useMeasure() {\n const [dimensions, setDimensions] = React.useState({\n width: null,\n height: null,\n });\n\n const previousObserver = React.useRef(null);\n\n const customRef = React.useCallback((node) => {\n if (previousObserver.current) {\n previousObserver.current.disconnect();\n previousObserver.current = null;\n }\n\n if (node?.nodeType === Node.ELEMENT_NODE) {\n const observer = new ResizeObserver(([entry]) => {\n if (entry && entry.borderBoxSize) {\n const { inlineSize: width, blockSize: height } =\n entry.borderBoxSize[0];\n\n setDimensions({ width, height });\n }\n });\n\n observer.observe(node);\n previousObserver.current = observer;\n }\n }, []);\n\n return [customRef, dimensions];\n}\n\nexport function useMediaQuery(query) {\n const subscribe = React.useCallback(\n (callback) => {\n const matchMedia = window.matchMedia(query);\n\n matchMedia.addEventListener(\"change\", callback);\n return () => {\n matchMedia.removeEventListener(\"change\", callback);\n };\n },\n [query]\n );\n\n const getSnapshot = () => {\n return window.matchMedia(query).matches;\n };\n\n const getServerSnapshot = () => {\n throw Error(\"useMediaQuery is a client-only hook\");\n };\n\n return React.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n}\n\nexport function useMouse() {\n const [state, setState] = React.useState({\n x: 0,\n y: 0,\n elementX: 0,\n elementY: 0,\n elementPositionX: 0,\n elementPositionY: 0,\n });\n\n const ref = React.useRef(null);\n\n React.useLayoutEffect(() => {\n const handleMouseMove = (event) => {\n let newState = {\n x: event.pageX,\n y: event.pageY,\n };\n\n if (ref.current?.nodeType === Node.ELEMENT_NODE) {\n const { left, top } = ref.current.getBoundingClientRect();\n const elementPositionX = left + window.scrollX;\n const elementPositionY = top + window.scrollY;\n const elementX = event.pageX - elementPositionX;\n const elementY = event.pageY - elementPositionY;\n\n newState.elementX = elementX;\n newState.elementY = elementY;\n newState.elementPositionX = elementPositionX;\n newState.elementPositionY = elementPositionY;\n }\n\n setState((s) => {\n return {\n ...s,\n ...newState,\n };\n });\n };\n\n document.addEventListener(\"mousemove\", handleMouseMove);\n\n return () => {\n document.removeEventListener(\"mousemove\", handleMouseMove);\n };\n }, []);\n\n return [state, ref];\n}\n\nconst getConnection = () => {\n return (\n navigator?.connection ||\n navigator?.mozConnection ||\n navigator?.webkitConnection\n );\n};\n\nconst useNetworkStateSubscribe = (callback) => {\n window.addEventListener(\"online\", callback, { passive: true });\n window.addEventListener(\"offline\", callback, { passive: true });\n\n const connection = getConnection();\n\n if (connection) {\n connection.addEventListener(\"change\", callback, { passive: true });\n }\n\n return () => {\n window.removeEventListener(\"online\", callback);\n window.removeEventListener(\"offline\", callback);\n\n if (connection) {\n connection.removeEventListener(\"change\", callback);\n }\n };\n};\n\nconst getNetworkStateServerSnapshot = () => {\n throw Error(\"useNetworkState is a client-only hook\");\n};\n\nexport function useNetworkState() {\n const cache = React.useRef({});\n\n const getSnapshot = () => {\n const online = navigator.onLine;\n const connection = getConnection();\n\n const nextState = {\n online,\n downlink: connection?.downlink,\n downlinkMax: connection?.downlinkMax,\n effectiveType: connection?.effectiveType,\n rtt: connection?.rtt,\n saveData: connection?.saveData,\n type: connection?.type,\n };\n\n if (isShallowEqual(cache.current, nextState)) {\n return cache.current;\n } else {\n cache.current = nextState;\n return nextState;\n }\n };\n\n return React.useSyncExternalStore(\n useNetworkStateSubscribe,\n getSnapshot,\n getNetworkStateServerSnapshot\n );\n}\n\nexport function useObjectState(initialValue) {\n const [state, setState] = React.useState(initialValue);\n\n const handleUpdate = React.useCallback((arg) => {\n if (typeof arg === \"function\") {\n setState((s) => {\n const newState = arg(s);\n\n if (isPlainObject(newState)) {\n return {\n ...s,\n ...newState,\n };\n }\n });\n }\n\n if (isPlainObject(arg)) {\n setState((s) => ({\n ...s,\n ...arg,\n }));\n }\n }, []);\n\n return [state, handleUpdate];\n}\n\nexport function useOrientation() {\n const [orientation, setOrientation] = React.useState({\n angle: 0,\n type: \"landscape-primary\",\n });\n\n React.useLayoutEffect(() => {\n const handleChange = () => {\n const { angle, type } = window.screen.orientation;\n setOrientation({\n angle,\n type,\n });\n };\n\n const handle_orientationchange = () => {\n setOrientation({\n type: \"UNKNOWN\",\n angle: window.orientation,\n });\n };\n\n if (window.screen?.orientation) {\n handleChange();\n window.screen.orientation.addEventListener(\"change\", handleChange);\n } else {\n handle_orientationchange();\n window.addEventListener(\"orientationchange\", handle_orientationchange);\n }\n\n return () => {\n if (window.screen?.orientation) {\n window.screen.orientation.removeEventListener(\"change\", handleChange);\n } else {\n window.removeEventListener(\n \"orientationchange\",\n handle_orientationchange\n );\n }\n };\n }, []);\n\n return orientation;\n}\n\nconst usePreferredLanguageSubscribe = (cb) => {\n window.addEventListener(\"languagechange\", cb);\n return () => window.removeEventListener(\"languagechange\", cb);\n};\n\nconst getPreferredLanguageSnapshot = () => {\n return navigator.language;\n};\n\nconst getPreferredLanguageServerSnapshot = () => {\n throw Error(\"usePreferredLanguage is a client-only hook\");\n};\n\nexport function usePreferredLanguage() {\n return React.useSyncExternalStore(\n usePreferredLanguageSubscribe,\n getPreferredLanguageSnapshot,\n getPreferredLanguageServerSnapshot\n );\n}\n\nexport function usePrevious(value) {\n const [current, setCurrent] = React.useState(value);\n const [previous, setPrevious] = React.useState(null);\n\n if (value !== current) {\n setPrevious(current);\n setCurrent(value);\n }\n\n return previous;\n}\n\nexport function useQueue(initialValue = []) {\n const [queue, setQueue] = React.useState(initialValue);\n\n const add = React.useCallback((element) => {\n setQueue((q) => [...q, element]);\n }, []);\n\n const remove = React.useCallback(() => {\n let removedElement;\n\n setQueue(([first, ...q]) => {\n removedElement = first;\n return q;\n });\n\n return removedElement;\n }, []);\n\n const clear = React.useCallback(() => {\n setQueue([]);\n }, []);\n\n return {\n add,\n remove,\n clear,\n first: queue[0],\n last: queue[queue.length - 1],\n size: queue.length,\n queue,\n };\n}\n\nexport function useRenderCount() {\n const count = React.useRef(0);\n\n count.current++;\n\n return count.current;\n}\n\nexport function useRenderInfo(name = \"Unknown\") {\n const count = React.useRef(0);\n const lastRender = React.useRef();\n const now = Date.now();\n\n count.current++;\n\n React.useEffect(() => {\n lastRender.current = Date.now();\n });\n\n const sinceLastRender = lastRender.current ? now - lastRender.current : 0;\n\n if (process.env.NODE_ENV !== \"production\") {\n const info = {\n name,\n renders: count.current,\n sinceLastRender,\n timestamp: now,\n };\n\n console.log(info);\n\n return info;\n }\n}\n\nexport function useScript(src, options = {}) {\n const [status, setStatus] = React.useState(\"loading\");\n const optionsRef = React.useRef(options);\n\n React.useEffect(() => {\n let script = document.querySelector(`script[src=\"${src}\"]`);\n\n const domStatus = script?.getAttribute(\"data-status\");\n if (domStatus) {\n setStatus(domStatus);\n return;\n }\n\n if (script === null) {\n script = document.createElement(\"script\");\n script.src = src;\n script.async = true;\n script.setAttribute(\"data-status\", \"loading\");\n document.body.appendChild(script);\n\n const handleScriptLoad = () => {\n script.setAttribute(\"data-status\", \"ready\");\n setStatus(\"ready\");\n removeEventListeners();\n };\n\n const handleScriptError = () => {\n script.setAttribute(\"data-status\", \"error\");\n setStatus(\"error\");\n removeEventListeners();\n };\n\n const removeEventListeners = () => {\n script.removeEventListener(\"load\", handleScriptLoad);\n script.removeEventListener(\"error\", handleScriptError);\n };\n\n script.addEventListener(\"load\", handleScriptLoad);\n script.addEventListener(\"error\", handleScriptError);\n\n const removeOnUnmount = optionsRef.current.removeOnUnmount;\n\n return () => {\n if (removeOnUnmount === true) {\n script.remove();\n removeEventListeners();\n }\n };\n } else {\n setStatus(\"unknown\");\n }\n }, [src]);\n\n return status;\n}\n\nconst setSessionStorageItem = (key, value) => {\n const stringifiedValue = JSON.stringify(value);\n window.sessionStorage.setItem(key, stringifiedValue);\n dispatchStorageEvent(key, stringifiedValue);\n};\n\nconst removeSessionStorageItem = (key) => {\n window.sessionStorage.removeItem(key);\n dispatchStorageEvent(key, null);\n};\n\nconst getSessionStorageItem = (key) => {\n return window.sessionStorage.getItem(key);\n};\n\nconst useSessionStorageSubscribe = (callback) => {\n window.addEventListener(\"storage\", callback);\n return () => window.removeEventListener(\"storage\", callback);\n};\n\nconst getSessionStorageServerSnapshot = () => {\n throw Error(\"useSessionStorage is a client-only hook\");\n};\n\nexport function useSessionStorage(key, initialValue) {\n const getSnapshot = () => getSessionStorageItem(key);\n\n const store = React.useSyncExternalStore(\n useSessionStorageSubscribe,\n getSnapshot,\n getSessionStorageServerSnapshot\n );\n\n const setState = React.useCallback(\n (v) => {\n try {\n const nextState = typeof v === \"function\" ? v(JSON.parse(store)) : v;\n\n if (nextState === undefined || nextState === null) {\n removeSessionStorageItem(key);\n } else {\n setSessionStorageItem(key, nextState);\n }\n } catch (e) {\n console.warn(e);\n }\n },\n [key, store]\n );\n\n React.useEffect(() => {\n if (\n getSessionStorageItem(key) === null &&\n typeof initialValue !== \"undefined\"\n ) {\n setSessionStorageItem(key, initialValue);\n }\n }, [key, initialValue]);\n\n return [store ? JSON.parse(store) : initialValue, setState];\n}\n\nexport function useSet(values) {\n const setRef = React.useRef(new Set(values));\n const [, reRender] = React.useReducer((x) => x + 1, 0);\n\n setRef.current.add = (...args) => {\n const res = Set.prototype.add.apply(setRef.current, args);\n reRender();\n\n return res;\n };\n\n setRef.current.clear = (...args) => {\n Set.prototype.clear.apply(setRef.current, args);\n reRender();\n };\n\n setRef.current.delete = (...args) => {\n const res = Set.prototype.delete.apply(setRef.current, args);\n reRender();\n\n return res;\n };\n\n return setRef.current;\n}\n\nexport function useThrottle(value, interval = 500) {\n const [throttledValue, setThrottledValue] = React.useState(value);\n const lastUpdated = React.useRef(null);\n\n React.useEffect(() => {\n const now = Date.now();\n\n if (lastUpdated.current && now >= lastUpdated.current + interval) {\n lastUpdated.current = now;\n setThrottledValue(value);\n } else {\n const id = window.setTimeout(() => {\n lastUpdated.current = now;\n setThrottledValue(value);\n }, interval);\n\n return () => window.clearTimeout(id);\n }\n }, [value, interval]);\n\n return throttledValue;\n}\n\nexport function useToggle(initialValue) {\n const [on, setOn] = React.useState(() => {\n if (typeof initialValue === \"boolean\") {\n return initialValue;\n }\n\n return Boolean(initialValue);\n });\n\n const handleToggle = React.useCallback((value) => {\n if (typeof value === \"boolean\") {\n return setOn(value);\n }\n\n return setOn((v) => !v);\n }, []);\n\n return [on, handleToggle];\n}\n\nconst useVisibilityChangeSubscribe = (callback) => {\n document.addEventListener(\"visibilitychange\", callback);\n\n return () => {\n document.removeEventListener(\"visibilitychange\", callback);\n };\n};\n\nconst getVisibilityChangeSnapshot = () => {\n return document.visibilityState;\n};\n\nconst getVisibilityChangeServerSnapshot = () => {\n throw Error(\"useVisibilityChange is a client-only hook\");\n};\n\nexport function useVisibilityChange() {\n const visibilityState = React.useSyncExternalStore(\n useVisibilityChangeSubscribe,\n getVisibilityChangeSnapshot,\n getVisibilityChangeServerSnapshot\n );\n\n return visibilityState === \"visible\";\n}\n\nexport function useWindowScroll() {\n const [state, setState] = React.useState({\n x: null,\n y: null,\n });\n\n const scrollTo = React.useCallback((...args) => {\n if (typeof args[0] === \"object\") {\n window.scrollTo(args[0]);\n } else if (typeof args[0] === \"number\" && typeof args[1] === \"number\") {\n window.scrollTo(args[0], args[1]);\n } else {\n throw new Error(\n `Invalid arguments passed to scrollTo. See here for more info. https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo`\n );\n }\n }, []);\n\n React.useLayoutEffect(() => {\n const handleScroll = () => {\n setState({ x: window.scrollX, y: window.scrollY });\n };\n\n handleScroll();\n window.addEventListener(\"scroll\", handleScroll);\n\n return () => {\n window.removeEventListener(\"scroll\", handleScroll);\n };\n }, []);\n\n return [state, scrollTo];\n}\n\nexport function useWindowSize() {\n const [size, setSize] = React.useState({\n width: null,\n height: null,\n });\n\n React.useLayoutEffect(() => {\n const handleResize = () => {\n setSize({\n width: window.innerWidth,\n height: window.innerHeight,\n });\n };\n\n handleResize();\n window.addEventListener(\"resize\", handleResize);\n\n return () => {\n window.removeEventListener(\"resize\", handleResize);\n };\n }, []);\n\n return size;\n}\n","import { useMeasure } from \"@uidotdev/usehooks\";\n\nexport const useMapHeader = () => {\n const [refHeader, { height: headerHeight }] = useMeasure();\n\n const isHeaderReady = Boolean(headerHeight);\n const mapHeight = isHeaderReady\n ? `calc(100dvh - ${headerHeight}px)`\n : \"0px\";\n\n return {\n refHeader,\n isHeaderReady,\n headerHeight,\n mapHeight,\n };\n};\n"]}
1
+ {"version":3,"sources":["../src/hooks/useOrientation.ts","../src/theme.ts","../src/theme-provider.tsx","../src/components/Loader.tsx","../src/components/RouteMap/ElevationChart/DistanceTick.tsx","../src/components/RouteMap/HoverContext.tsx","../src/components/RouteMap/ElevationChart/ElevationDot.tsx","../src/components/RouteMap/ElevationChart/ElevationTick.tsx","../src/types.ts","../src/components/RouteMap/ElevationChart/SurfaceStrip.tsx","../src/components/RouteMap/ElevationChart/ElevationTooltip.tsx","../src/assets/icons/marker.svg","../src/components/icons/buildMarkerIcon.ts","../src/components/RouteMap/ElevationChart/MarkerShape.tsx","../src/components/RouteMap/ElevationChart/RouteStrip.tsx","../src/components/RouteMap/ElevationChart/useTriggerByXValue.tsx","../src/components/RouteMap/ElevationChart/utils.ts","../src/components/RouteMap/ElevationChart/ElevationChart.tsx","../src/constants.ts","../src/components/RouteMap/GoogleMapCanvas.tsx","../src/components/RouteMap/RouteMap.tsx","../node_modules/@uidotdev/usehooks/index.js","../src/hooks/useMapHeader.ts"],"names":["getIsLandscape","useOrientation","isHorizontal","setIsHorizontal","useState","useEffect","handleResize","theme","ThemeContext","createContext","mergeTheme","override","ThemeProvider","children","mergedTheme","useMemo","jsx","useTheme","useContext","Loader","message","height","style","styles","Loader_default","DistanceTick","props","x","y","payload","km","jsxs","HoverContext","HoverProvider","hover","setHoverState","setHover","useCallback","state","clearHover","value","useHover","ctx","Dot","cx","cy","fill","ElevationDot","MapDot","ElevationTick","m","SurfaceType","SURFACE_STRIP_WIDTH","SURFACE_STRIP_HEIGHT","SURFACE_TEXTURES","surface_asphalt_default","surface_compacted_default","surface_concrete_default","surface_natural_default","surface_penetrated_default","SurfaceStrip","route","maxDistance","xAxisMap","offset","surfaces","xAxis","scale","chartLeft","chartWidth","axisY","stripY","Fragment","surfaceType","file","width","surface","index","rawStart","rawEnd","clampedStart","clampedEnd","segStart","segEnd","startX","endX","MARKER_DISTANCE_TOLERANCE_MATCH","getSurfaceForDistance","distance","start","end","getRouteForDistance","routes","formatSurfaceLabel","formatSegmentLabel","segment","formatKm","rounded","ElevationTooltip","active","label","accent","primary","markers","tooltip","point","marker","surfaceTexture","routeSegment","marker_default","svgTemplate","base","outer","inner","fillIndex","match","buildMarkerIcon","svg","MarkerShape","name","layout","size","iconHref","words","w","Text","text","word","Word","id","useId","RouteStrip","belowHeight","useTriggerByXValue","data","activeIndex","setActiveIndex","activePoint","clearActiveIndex","triggerByXValue","lo","hi","mid","bestIndex","prev","curr","getMaxDistance","points","getTicksForDistance","step","ticks","d","getPointsWithElevation","f","a","b","getAllPoints","computeMinMax","elevations","p","min","max","pad","computeRoundedDomainAndTicks","minMax","shouldOffset","paddedRange","graphMin","graphMax","v","computeMarkerPoints","elevationPoints","geoJson","pointFeatures","coords","lng","lat","nearest","acc","findNearestPointByCoordinates","target","closest","minDist","findNearestPoint","isCloseCheck","marker1","marker2","threshold","ElevationChart","minY","maxY","tickVals","nearestPoint","ResponsiveContainer","ComposedChart","activePayload","activePayloadItem","CartesianGrid","Customized","XAxis","YAxis","Tooltip","Line","idx","tooClose","ReferenceDot","ReferenceLine","DEFAULT_CENTER","DEFAULT_ZOOM_HORIZONTAL","DEFAULT_ZOOM_VERTICAL","GoogleMapCanvas","ref","useRef","highlightMarkerRef","mapRef","markerIcons","zoom","map","feature","isFirst","isLast","moveListener","e","latLng","mapInstance","icon","messages","Status","RenderLoader","type","render","status","RouteMap","apiKey","className","containerStyle","Wrapper","useMeasure","dimensions","setDimensions","previousObserver","node","observer","entry","useMapHeader","refHeader","headerHeight","isHeaderReady","mapHeight"],"mappings":"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","file":"index.js","sourcesContent":["import { useEffect, useState } from \"react\";\n\nconst getIsLandscape = () => {\n if (typeof window === \"undefined\") return true;\n return window.innerWidth >= window.innerHeight;\n};\n\nexport const useOrientation = () => {\n const [isHorizontal, setIsHorizontal] = useState<boolean>(getIsLandscape);\n\n useEffect(() => {\n const handleResize = () => setIsHorizontal(getIsLandscape());\n\n window.addEventListener(\"resize\", handleResize);\n return () => window.removeEventListener(\"resize\", handleResize);\n }, []);\n\n return { isHorizontal, isVertical: !isHorizontal };\n};\n","export interface ThemeColors {\n primary: string;\n primaryMuted: string;\n accent: string;\n surface: string;\n}\n\nexport interface ThemeMarker {\n outer: string;\n inner: string;\n startInner: string;\n finishInner: string;\n}\n\nexport interface ThemeDots {\n mapActive: string;\n chart: string;\n chartActive: string;\n}\n\nexport interface ThemeMap {\n strokeWeight: number;\n markerSize: number;\n markerLabelFontSize: number;\n markerLabelFontWeight: string;\n hoverMarkerScale: number;\n}\n\nexport interface ThemeChart {\n margin: { top: number; right: number; bottom: number; left: number };\n gridStroke: string;\n gridDasharray: string;\n axisStroke: string;\n cursorStroke: string;\n cursorStrokeWidth: number;\n yAxisWidth: number;\n lineStrokeWidth: number;\n dotRadius: number;\n dotOpacity: number;\n activeDotRadius: number;\n referenceDotRadius: number;\n referenceLineOpacity: number;\n gradientStartOpacity: number;\n gradientEndOpacity: number;\n xTickFontSize: number;\n xTickDy: number;\n xTickUnitFontSize: number;\n xTickUnitDx: number;\n yTickFontSize: number;\n yTickDy: number;\n yTickUnitFontSize: number;\n yTickUnitDx: number;\n}\n\nexport interface ThemeTooltip {\n background: string;\n textColor: string;\n padding: string;\n borderRadius: number;\n}\n\nexport interface ThemeMarkerShape {\n size: number;\n lift: number;\n text: {\n fontSize: number;\n fontWeight: number;\n letterSpacing: number;\n xOffset: number;\n lineHeight: number;\n startLiftPerWord: number;\n };\n}\n\nexport interface ThemeShadows {\n map: string;\n}\n\nexport interface Theme {\n colors: ThemeColors;\n marker: ThemeMarker;\n dots: ThemeDots;\n map: ThemeMap;\n chart: ThemeChart;\n tooltip: ThemeTooltip;\n markerShape: ThemeMarkerShape & {\n text: ThemeMarkerShape[\"text\"];\n };\n}\n\nexport interface PartialTheme {\n colors?: Partial<ThemeColors>;\n marker?: Partial<ThemeMarker>;\n dots?: Partial<ThemeDots>;\n map?: Partial<ThemeMap>;\n chart?: Partial<ThemeChart>;\n tooltip?: Partial<ThemeTooltip>;\n markerShape?: Partial<ThemeMarkerShape> & {\n text?: Partial<ThemeMarkerShape[\"text\"]>;\n };\n}\n\nexport const theme: Theme = {\n colors: {\n primary: \"rgba(14, 165, 233, 1)\",\n primaryMuted: \"rgba(14, 165, 233, 0.7)\",\n accent: \"rgba(132, 204, 22, 1)\",\n surface: \"rgba(248, 250, 252, 1)\",\n },\n marker: {\n outer: \"rgba(132, 204, 22, 1)\",\n inner: \"rgba(248, 250, 252, 1)\",\n startInner: \"rgba(34, 197, 94, 1)\",\n finishInner: \"rgba(239, 68, 68, 1)\",\n },\n dots: {\n mapActive: \"rgba(132, 204, 22, 1)\",\n chart: \"rgba(132, 204, 22, 1)\",\n chartActive: \"rgba(132, 204, 22, 1)\",\n },\n map: {\n strokeWeight: 10,\n markerSize: 50,\n markerLabelFontSize: 20,\n markerLabelFontWeight: \"bold\",\n hoverMarkerScale: 6,\n },\n chart: {\n margin: { top: 4, right: 8, bottom: 4, left: 8 },\n gridStroke: \"rgba(255,255,255,0.08)\",\n gridDasharray: \"3 3\",\n axisStroke: \"rgba(226, 232, 240, 0.7)\",\n cursorStroke: \"rgba(226,232,240,0.4)\",\n cursorStrokeWidth: 1,\n yAxisWidth: 60,\n lineStrokeWidth: 1,\n dotRadius: 3,\n dotOpacity: 0.9,\n activeDotRadius: 3,\n referenceDotRadius: 7,\n referenceLineOpacity: 0.5,\n gradientStartOpacity: 0.6,\n gradientEndOpacity: 0.1,\n xTickFontSize: 12,\n xTickDy: 12,\n xTickUnitFontSize: 10,\n xTickUnitDx: 2,\n yTickFontSize: 12,\n yTickDy: 4,\n yTickUnitFontSize: 10,\n yTickUnitDx: 2,\n },\n tooltip: {\n background: \"rgba(15,23,42,0.9)\",\n textColor: \"#e2e8f0\",\n padding: \"6px 8px\",\n borderRadius: 6,\n },\n markerShape: {\n size: 33,\n lift: 20,\n text: {\n fontSize: 12,\n fontWeight: 300,\n letterSpacing: 2,\n xOffset: 15,\n lineHeight: 12,\n startLiftPerWord: 10,\n },\n },\n};\n","import { createContext, type ReactNode, useContext, useMemo } from \"react\";\nimport { theme as defaultTheme, PartialTheme, type Theme } from \"./theme\";\n\nconst ThemeContext = createContext<Theme>(defaultTheme);\n\nconst mergeTheme = (override?: PartialTheme): Theme => ({\n colors: {\n ...defaultTheme.colors,\n ...(override?.colors ?? {}),\n },\n marker: {\n ...defaultTheme.marker,\n ...(override?.marker ?? {}),\n },\n dots: {\n ...defaultTheme.dots,\n ...(override?.dots ?? {}),\n },\n map: {\n ...defaultTheme.map,\n ...(override?.map ?? {}),\n },\n chart: {\n ...defaultTheme.chart,\n ...(override?.chart ?? {}),\n },\n tooltip: {\n ...defaultTheme.tooltip,\n ...(override?.tooltip ?? {}),\n },\n markerShape: {\n ...defaultTheme.markerShape,\n ...(override?.markerShape ?? {}),\n text: {\n ...defaultTheme.markerShape.text,\n ...(override?.markerShape?.text ?? {}),\n },\n },\n});\n\nexport const ThemeProvider = ({\n theme,\n children,\n}: {\n theme?: PartialTheme;\n children: ReactNode;\n}) => {\n const mergedTheme = useMemo(() => mergeTheme(theme), [theme]);\n return (\n <ThemeContext.Provider value={mergedTheme}>\n {children}\n </ThemeContext.Provider>\n );\n};\n\nexport const useTheme = () => useContext(ThemeContext);\n","import type { CSSProperties } from \"react\";\nimport { useTheme } from \"../theme-provider\";\nimport styles from \"./Loader.module.css\";\n\ninterface LoaderProps {\n message?: string;\n height?: number | string;\n}\n\nconst Loader = ({\n message = \"Loading map...\",\n height = \"100dvh\",\n}: LoaderProps) => {\n const theme = useTheme();\n\n const style: CSSProperties = {\n height,\n background: theme.colors.surface,\n color: theme.colors.primary,\n };\n\n return (\n <div className={styles.rrpLoader} style={style}>\n {message}\n </div>\n );\n};\n\nexport default Loader;\n","import { useTheme } from \"../../../theme-provider\";\n\nexport const DistanceTick = (props: any) => {\n const { x, y, payload } = props;\n const theme = useTheme();\n const km = Math.round((payload?.value ?? 0) / 1000);\n return (\n <text\n x={x}\n y={y}\n fill={theme.chart.axisStroke}\n fontSize={theme.chart.xTickFontSize}\n textAnchor=\"middle\"\n dy={theme.chart.xTickDy}\n >\n <tspan>{km}</tspan>\n <tspan\n fontSize={theme.chart.xTickUnitFontSize}\n dx={theme.chart.xTickUnitDx}\n >\n km\n </tspan>\n </text>\n );\n};\n","import {\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useMemo,\n useState,\n} from \"react\";\n\nexport enum HoverStateChangeSource {\n Chart = \"chart\",\n Map = \"map\",\n}\nexport interface HoverState {\n lat?: number;\n lng?: number;\n source?: HoverStateChangeSource;\n}\n\ninterface HoverContextValue {\n hover: HoverState;\n setHover: (state: HoverState) => void;\n clearHover: () => void;\n}\n\nconst HoverContext = createContext<HoverContextValue | undefined>(undefined);\n\nexport const HoverProvider = ({ children }: { children: ReactNode }) => {\n const [hover, setHoverState] = useState<HoverState>({});\n\n const setHover = useCallback((state: HoverState) => setHoverState(state), []);\n const clearHover = useCallback(() => setHoverState({}), []);\n\n const value = useMemo(\n () => ({\n hover,\n setHover,\n clearHover,\n }),\n [hover, setHover, clearHover]\n );\n\n return (\n <HoverContext.Provider value={value}>{children}</HoverContext.Provider>\n );\n};\n\nexport const useHover = () => {\n const ctx = useContext(HoverContext);\n if (!ctx) {\n throw new Error(\"useHover must be used within HoverProvider\");\n }\n return ctx;\n};\n","import { useTheme } from \"../../../theme-provider\";\n\nconst Dot = (props: any) => {\n const { cx, cy, fill } = props;\n const theme = useTheme();\n if (cx === undefined || cy === undefined) return null;\n return (\n <circle\n cx={cx}\n cy={cy}\n r={theme.chart.dotRadius}\n fill={fill}\n opacity={theme.chart.dotOpacity}\n />\n );\n};\n\nexport const ElevationDot = (props: any) => {\n const theme = useTheme();\n return <Dot {...props} fill={theme.dots.chart} />;\n};\n\nexport const MapDot = (props: any) => {\n const theme = useTheme();\n return <Dot {...props} fill={theme.dots.mapActive} />;\n};\n","import { useTheme } from \"../../../theme-provider\";\n\nexport const ElevationTick = (props: any) => {\n const { x, y, payload } = props;\n const theme = useTheme();\n const m = Math.round(payload?.value ?? 0);\n return (\n <text\n x={x}\n y={y}\n fill={theme.chart.axisStroke}\n fontSize={theme.chart.yTickFontSize}\n textAnchor=\"end\"\n dy={theme.chart.yTickDy}\n >\n <tspan>{m}</tspan>\n <tspan\n fontSize={theme.chart.yTickUnitFontSize}\n dx={theme.chart.yTickUnitDx}\n >\n m\n </tspan>\n </text>\n );\n};\n","export interface RouteConfig {\n id: string;\n name: string;\n center: { lat: number; lng: number };\n zoomHorizontal?: number;\n zoomVertical?: number;\n geoJson: object;\n surface?: Array<{segment: [number, number], type: SurfaceType}>;\n routes?: Array<{id: string; color: string; segment: [number, number]}>;\n}\n\nexport enum SurfaceType {\n Asphalt = \"asphalt\",\n Compacted = \"compacted\",\n Concrete = \"concrete\",\n Natural = \"natural\",\n Penetrated = \"penetrated\",\n}\n","import surfaceAsphalt from \"../../../assets/surface/surface_asphalt.png\";\nimport surfaceCompacted from \"../../../assets/surface/surface_compacted.png\";\nimport surfaceConcrete from \"../../../assets/surface/surface_concrete.png\";\nimport surfaceNatural from \"../../../assets/surface/surface_natural.png\";\nimport surfacePenetrated from \"../../../assets/surface/surface_penetrated.png\";\nimport type { RouteConfig } from \"../../../types\";\nimport { SurfaceType } from \"../../../types\";\n\n// const surfaceAsphalt = new URL(\n// \"../../../assets/surface/surface_asphalt.png\",\n// import.meta.url\n// ).href;\n// const surfaceCompacted = new URL(\n// \"../../../assets/surface/surface_compacted.png\",\n// import.meta.url\n// ).href;\n// const surfaceConcrete = new URL(\n// \"../../../assets/surface/surface_concrete.png\",\n// import.meta.url\n// ).href;\n// const surfaceNatural = new URL(\n// \"../../../assets/surface/surface_natural.png\",\n// import.meta.url\n// ).href;\n// const surfacePenetrated = new URL(\n// \"../../../assets/surface/surface_penetrated.png\",\n// import.meta.url\n// ).href;\n\nconst SURFACE_STRIP_WIDTH = 30;\nexport const SURFACE_STRIP_HEIGHT = 16;\n\nexport const SURFACE_TEXTURES: Record<\n SurfaceType,\n { file: string; width?: number; height?: number }\n> = {\n [SurfaceType.Asphalt]: {\n file: surfaceAsphalt,\n width: 30,\n height: 22,\n },\n [SurfaceType.Compacted]: {\n file: surfaceCompacted,\n width: 200,\n height: 16,\n },\n [SurfaceType.Concrete]: {\n file: surfaceConcrete,\n },\n [SurfaceType.Natural]: {\n file: surfaceNatural,\n width: 30,\n height: 22,\n },\n [SurfaceType.Penetrated]: {\n file: surfacePenetrated,\n width: 30,\n height: 22,\n },\n};\n\ntype SurfaceStripProps = {\n route: RouteConfig;\n maxDistance: number;\n height?: number;\n xAxisMap?: Record<\n string,\n {\n scale?: (value: number) => number;\n x?: number;\n y?: number;\n width?: number;\n }\n >;\n offset?: { left?: number; top?: number; width?: number; height?: number };\n};\n\nexport const SurfaceStrip = ({\n route,\n maxDistance,\n xAxisMap,\n offset,\n}: SurfaceStripProps) => {\n const surfaces = route.surface ?? [];\n if (!surfaces.length) {\n return null;\n }\n\n const xAxis = xAxisMap ? Object.values(xAxisMap)[0] : undefined;\n const scale = xAxis?.scale;\n const chartLeft = xAxis?.x ?? offset?.left ?? 0;\n const chartWidth = xAxis?.width ?? offset?.width ?? 0;\n const axisY = xAxis?.y ?? (offset?.top ?? 0) + (offset?.height ?? 0);\n const height = SURFACE_STRIP_HEIGHT;\n const stripY = axisY - height;\n\n if (!scale || chartWidth <= 0) {\n return null;\n }\n\n return (\n <>\n <defs>\n {Object.entries(SURFACE_TEXTURES).map(\n ([surfaceType, { file, width, height }]) => (\n <pattern\n key={surfaceType}\n id={`surface-${surfaceType}`}\n patternUnits={\n surfaceType === SurfaceType.Compacted\n ? undefined\n : \"userSpaceOnUse\"\n }\n width={width ?? SURFACE_STRIP_WIDTH}\n height={height ?? SURFACE_STRIP_HEIGHT}\n >\n <image\n href={file}\n x=\"0\"\n y=\"0\"\n width={width ?? SURFACE_STRIP_WIDTH}\n height={height ?? SURFACE_STRIP_HEIGHT}\n />\n </pattern>\n )\n )}\n </defs>\n <g>\n <rect\n x={chartLeft}\n y={stripY}\n width={chartWidth}\n height={height}\n fill=\"none\"\n />\n {surfaces.map((surface, index) => {\n const [rawStart, rawEnd] = surface.segment;\n const clampedStart = Math.max(0, Math.min(rawStart, maxDistance));\n const clampedEnd = Math.max(0, Math.min(rawEnd, maxDistance));\n const segStart = Math.min(clampedStart, clampedEnd);\n const segEnd = Math.max(clampedStart, clampedEnd);\n if (segEnd <= segStart) {\n return null;\n }\n\n const startX = scale(segStart);\n const endX = scale(segEnd);\n const x = Math.min(startX, endX);\n const width = Math.max(0, Math.abs(endX - startX));\n if (width <= 0) {\n return null;\n }\n\n return (\n <rect\n key={`${surface.type}-${index}`}\n x={x}\n y={stripY}\n width={width}\n height={height}\n fill={`url(#surface-${surface.type})`}\n />\n );\n })}\n </g>\n </>\n );\n};\n","import type { TooltipProps } from \"recharts\";\nimport { useTheme } from \"../../../theme-provider\";\nimport type { RouteConfig, SurfaceType } from \"../../../types\";\nimport { SURFACE_TEXTURES } from \"./SurfaceStrip\";\n\ninterface ElevationTooltipProps extends TooltipProps<number, string> {\n accent: string;\n primary: string;\n markers: Array<{ distance: number; name?: string }>;\n surfaces?: RouteConfig[\"surface\"];\n routes?: RouteConfig[\"routes\"];\n}\n\nconst MARKER_DISTANCE_TOLERANCE_MATCH = 300; // meters\n\nconst getSurfaceForDistance = (\n surfaces: RouteConfig[\"surface\"],\n distance: number\n) => {\n if (!surfaces?.length) return null;\n return (\n surfaces.find((surface) => {\n const [start, end] = surface.segment;\n const segStart = Math.min(start, end);\n const segEnd = Math.max(start, end);\n return distance >= segStart && distance <= segEnd;\n }) ?? null\n );\n};\n\nconst getRouteForDistance = (\n routes: RouteConfig[\"routes\"],\n distance: number\n) => {\n if (!routes?.length) return null;\n return (\n routes.find((route) => {\n const [start, end] = route.segment;\n const segStart = Math.min(start, end);\n const segEnd = Math.max(start, end);\n return distance >= segStart && distance <= segEnd;\n }) ?? null\n );\n};\n\nconst formatSurfaceLabel = (surface: SurfaceType) =>\n surface.charAt(0).toUpperCase() + surface.slice(1);\n\nconst formatSegmentLabel = (segment: [number, number]) => {\n const [start, end] = segment;\n const segStart = Math.min(start, end);\n const segEnd = Math.max(start, end);\n const formatKm = (value: number) => {\n const km = value / 1000;\n const rounded = km.toFixed(1);\n return rounded.endsWith(\".0\") ? rounded.slice(0, -2) : rounded;\n };\n return `(${formatKm(segStart)} km - ${formatKm(segEnd)} km)`;\n};\n\nexport const ElevationTooltip = ({\n active,\n payload,\n label,\n accent,\n primary,\n markers,\n surfaces,\n routes,\n}: ElevationTooltipProps) => {\n const { tooltip } = useTheme();\n\n if (!active || !payload?.length) return null;\n\n const point = payload[0]?.payload;\n const distance = (point?.distance as number | undefined) ?? (label as number);\n const marker = markers.find(\n (m) =>\n Math.abs((m?.distance ?? -1) - (point?.distance ?? 0)) <=\n MARKER_DISTANCE_TOLERANCE_MATCH\n );\n const surface = getSurfaceForDistance(surfaces, distance);\n const surfaceTexture = surface?.type ? SURFACE_TEXTURES[surface.type] : null;\n const routeSegment = getRouteForDistance(routes, distance);\n\n const km = Math.trunc((label as number) / 1000);\n const m = Math.round((label as number) % 1000);\n\n return (\n <div\n style={{\n background: tooltip.background,\n border: \"none\",\n color: tooltip.textColor,\n padding: \"4px 6px\",\n borderRadius: tooltip.borderRadius,\n fontSize: 13,\n lineHeight: 1.2,\n }}\n >\n <div style={{ fontWeight: 600, color: primary }}>\n {km} km {m} m\n </div>\n <div>\n Elevation: <strong>{Math.round(point?.elevation ?? 0)} m</strong>\n </div>\n {surface?.type ? (\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 4 }}>\n <svg\n width=\"20\"\n height=\"14\"\n aria-hidden=\"true\"\n style={{ display: \"block\" }}\n >\n {surfaceTexture ? (\n <image\n href={surfaceTexture.file}\n x=\"0\"\n y=\"0\"\n width=\"20\"\n height=\"14\"\n preserveAspectRatio=\"xMidYMid slice\"\n />\n ) : (\n <rect width=\"20\" height=\"14\" fill={tooltip.textColor} />\n )}\n </svg>\n <span>{formatSurfaceLabel(surface.type)}</span>\n <span>{formatSegmentLabel(surface.segment)}</span>\n </div>\n ) : null}\n {routeSegment ? (\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 4 }}>\n <svg\n width=\"20\"\n height=\"14\"\n aria-hidden=\"true\"\n style={{ display: \"block\" }}\n >\n <rect width=\"20\" height=\"14\" fill={routeSegment.color} />\n </svg>\n <span>{routeSegment.id}</span>\n <span>{formatSegmentLabel(routeSegment.segment)}</span>\n </div>\n ) : null}\n {marker?.name ? (\n <div style={{ color: accent, fontWeight: 600 }}>{marker.name}</div>\n ) : null}\n </div>\n );\n};\n","<svg stroke=\"currentColor\" fill=\"#84CC16\" stroke-width=\"2\" viewBox=\"0 0 24 24\" aria-hidden=\"true\" height=\"200px\" width=\"200px\" xmlns=\"http://www.w3.org/2000/svg\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z\"></path>\n <path fill=\"white\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M15 11a3 3 0 11-6 0 3 3 0 016 0z\"></path>\n</svg>\n","import markerSvg from \"../../assets/icons/marker.svg?raw\";\nimport markerFinishSvg from \"../../assets/icons/markerFinish.svg?raw\";\nimport markerStartSvg from \"../../assets/icons/markerStart.svg?raw\";\n\nconst svgTemplate = (base: string, outer: string, inner: string) => {\n let fillIndex = 0;\n return base.replace(/fill=\"[^\"]*\"/g, (match) => {\n fillIndex += 1;\n if (fillIndex === 1) return `fill=\"${outer}\"`;\n if (fillIndex === 2) return `fill=\"${inner}\"`;\n return match;\n });\n};\n\nexport const buildMarkerIcon = (outer: string, inner: string) => {\n const svg = svgTemplate(markerSvg, outer, inner).trim();\n const encoded = encodeURIComponent(svg)\n .replace(/'/g, \"%27\")\n .replace(/\"/g, \"%22\");\n return `data:image/svg+xml,${encoded}`;\n};\n\nexport const markers = {\n default: markerSvg,\n start: markerStartSvg,\n finish: markerFinishSvg,\n};","import { useId, useMemo } from \"react\";\nimport { useTheme } from \"../../../theme-provider\";\nimport { buildMarkerIcon } from \"../../icons/buildMarkerIcon\";\nimport { MapDot } from \"./ElevationDot\";\n\nexport const MarkerShape = (props: any) => {\n const { cx, cy, fill, name } = props;\n const theme = useTheme();\n const layout = theme.markerShape;\n const size = layout.size;\n\n const iconHref = useMemo(\n () => buildMarkerIcon(theme.marker.outer, theme.marker.inner),\n [theme.marker.inner, theme.marker.outer]\n );\n\n if (cx === undefined || cy === undefined) return null;\n\n const words =\n typeof name === \"string\"\n ? name\n .split(/\\s+/)\n .map((w) => w.trim())\n .filter(Boolean)\n : [];\n return (\n <g>\n <MapDot cx={cx} cy={cy} />\n <image\n x={cx - size / 2}\n y={cy - size / 2 - layout.lift}\n width={size}\n height={size}\n href={iconHref}\n />\n {name ? <Text words={words} cx={cx} cy={cy} fill={fill} /> : null}\n </g>\n );\n};\n\nconst Text = ({\n words,\n cx,\n cy,\n fill,\n}: {\n words: string[];\n cx: number;\n cy: number;\n fill?: string;\n}) => {\n const theme = useTheme();\n const text = theme.markerShape.text;\n\n return (\n <text\n y={cy - words.length * text.startLiftPerWord}\n fill={fill || \"#fff\"}\n fontSize={text.fontSize}\n fontWeight={text.fontWeight}\n letterSpacing={text.letterSpacing}\n style={{ userSelect: \"none\" }}\n >\n {words.map((word, index) => (\n <Word key={word} word={word} index={index} cx={cx} />\n ))}\n </text>\n );\n};\n\nconst Word = ({\n word,\n index,\n cx,\n}: {\n word: string;\n index: number;\n cx: number;\n}) => {\n const theme = useTheme();\n const text = theme.markerShape.text;\n const id = useId();\n return (\n <tspan\n key={id}\n x={cx + text.xOffset}\n dy={index === 0 ? 0 : text.lineHeight}\n >\n {word}\n </tspan>\n );\n};\n","import type { RouteConfig } from \"../../../types\";\n\nexport const ROUTE_STRIP_HEIGHT = 16;\n\ntype RouteStripProps = {\n route: RouteConfig;\n maxDistance: number;\n belowHeight?: number;\n xAxisMap?: Record<\n string,\n {\n scale?: (value: number) => number;\n x?: number;\n y?: number;\n width?: number;\n }\n >;\n offset?: { left?: number; top?: number; width?: number; height?: number };\n};\n\nexport const RouteStrip = ({\n route,\n maxDistance,\n belowHeight = 0,\n xAxisMap,\n offset,\n}: RouteStripProps) => {\n const routes = route.routes ?? [];\n if (!routes.length) {\n return null;\n }\n\n const xAxis = xAxisMap ? Object.values(xAxisMap)[0] : undefined;\n const scale = xAxis?.scale;\n const chartLeft = xAxis?.x ?? offset?.left ?? 0;\n const chartWidth = xAxis?.width ?? offset?.width ?? 0;\n const axisY = xAxis?.y ?? (offset?.top ?? 0) + (offset?.height ?? 0);\n const height = ROUTE_STRIP_HEIGHT;\n const stripY = axisY - belowHeight - height;\n\n if (!scale || chartWidth <= 0) {\n return null;\n }\n\n return (\n <g>\n <rect\n x={chartLeft}\n y={stripY}\n width={chartWidth}\n height={height}\n fill=\"none\"\n />\n {routes.map((routeSegment, index) => {\n const [rawStart, rawEnd] = routeSegment.segment;\n const clampedStart = Math.max(0, Math.min(rawStart, maxDistance));\n const clampedEnd = Math.max(0, Math.min(rawEnd, maxDistance));\n const segStart = Math.min(clampedStart, clampedEnd);\n const segEnd = Math.max(clampedStart, clampedEnd);\n if (segEnd <= segStart) {\n return null;\n }\n\n const startX = scale(segStart);\n const endX = scale(segEnd);\n const x = Math.min(startX, endX);\n const width = Math.max(0, Math.abs(endX - startX));\n if (width <= 0) {\n return null;\n }\n\n return (\n <g key={`${routeSegment.id}-${index}`}>\n <rect\n x={x}\n y={stripY}\n width={width}\n height={height}\n fill={routeSegment.color}\n />\n <text\n x={x + width / 2}\n y={stripY + height / 2}\n fill=\"#000000\"\n fontSize={10}\n fontWeight={600}\n textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n >\n {routeSegment.id}\n </text>\n </g>\n );\n })}\n </g>\n );\n};\n","import { useCallback, useMemo, useState } from \"react\";\n\nexport function useTriggerByXValue<\n T extends { distance: number; elevation: number }\n>(data: T[]) {\n const [activeIndex, setActiveIndex] = useState<number | null>(null);\n\n const activePoint = useMemo(\n () => (activeIndex != null ? data[activeIndex] : null),\n [activeIndex, data]\n );\n\n const clearActiveIndex = useCallback(() => {\n setActiveIndex(null);\n }, []);\n\n const triggerByXValue = useCallback(\n (distance: number) => {\n if (!data.length) return;\n\n // assume data sorted by distance ascending\n let lo = 0;\n let hi = data.length - 1;\n\n // binary search for closest distance\n while (lo < hi) {\n const mid = Math.floor((lo + hi) / 2);\n if (data[mid].distance < distance) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n\n // lo is first >= distance; pick closer of lo and lo-1\n let bestIndex = lo;\n if (lo > 0) {\n const prev = data[lo - 1];\n const curr = data[lo];\n if (\n Math.abs(prev.distance - distance) <\n Math.abs(curr.distance - distance)\n ) {\n bestIndex = lo - 1;\n }\n }\n\n setActiveIndex(bestIndex);\n },\n [data]\n );\n\n return {\n activeIndex,\n activePoint,\n triggerByXValue,\n clearActiveIndex,\n };\n}\n","import type { ElevationPoint, Marker } from \"./types\";\n\nexport const getMaxDistance = (points: ElevationPoint[]) =>\n points.length ? points[points.length - 1].distance : 0;\n\nexport const getTicksForDistance = (maxDistance: number, step: number = 2000) => {\n const ticks: number[] = [];\n for (let d = 0; d <= maxDistance; d += step) {\n ticks.push(d);\n }\n if (ticks[ticks.length - 1] < maxDistance) {\n ticks.push(maxDistance);\n }\n return ticks;\n}\n\nexport const getPointsWithElevation = (route: any): ElevationPoint[] => {\n const geo = route.geoJson as any;\n const line = geo?.features?.find(\n (f: any) =>\n f?.geometry?.type === \"LineString\" &&\n f?.properties?.elevationProfile?.points\n );\n const raw = line?.properties?.elevationProfile?.points || [];\n return [...raw].sort(\n (a: ElevationPoint, b: ElevationPoint) => (a?.distance ?? 0) - (b?.distance ?? 0)\n );\n};\n\nexport const getAllPoints = (route: any): [number, number][] => {\n const geo = route.geoJson as any;\n const points = geo?.features?.find(\n (f: any) =>\n f?.geometry?.type === \"LineString\" &&\n f?.geometry?.coordinates\n );\n return points.geometry.coordinates\n}\n\nexport const computeMinMax = (points: Array<{ elevation: number }>) => {\n if (!points.length) return [0, 0] as const;\n const elevations = points.map((p) => p.elevation);\n const min = Math.min(...elevations);\n const max = Math.max(...elevations);\n const pad = Math.max(10, (max - min) * 0.05);\n return [Math.floor(min - pad), Math.ceil(max + pad)];\n};\n\nexport const computeRoundedDomainAndTicks = (\n minMax: [number, number],\n shouldOffset: boolean = false\n) => {\n const [min, max] = minMax;\n const paddedRange = (max - min) * 1.2;\n const step = Math.max(10, Math.round(paddedRange / 6 / 10) * 10 || 50);\n const offset = shouldOffset ? -20 : 0;\n const graphMin =\n Math.floor((min - (paddedRange - (max - min)) / 2) / step) * step +\n offset;\n const graphMax =\n Math.ceil((max + (paddedRange - (max - min)) / 2) / step) * step +\n offset;\n const ticks: number[] = [];\n for (let v = graphMin; v <= graphMax + step / 2; v += step) {\n ticks.push(v);\n }\n\n return [graphMin, graphMax, ticks] as const;\n};\n\nexport const computeMarkerPoints = (\n elevationPoints: ElevationPoint[],\n geoJson: any\n) => {\n if (!elevationPoints?.length) return [];\n const features = geoJson?.features ?? [];\n const pointFeatures = features.filter(\n (f: any) => f?.geometry?.type === \"Point\"\n );\n\n const markers: Array<Marker> = [];\n\n pointFeatures.forEach((f: any) => {\n const coords = f?.geometry?.coordinates;\n if (!Array.isArray(coords) || coords.length < 2) return;\n const [lng, lat] = coords;\n if (!Number.isFinite(lat) || !Number.isFinite(lng)) return;\n const nearest = elevationPoints.reduce<{\n point: ElevationPoint | null;\n dist: number;\n }>(\n (acc, p) => {\n const d = Math.pow(p.lat - lat, 2) + Math.pow(p.lng - lng, 2);\n if (d < acc.dist) {\n return { point: p, dist: d };\n }\n return acc;\n },\n { point: null, dist: Number.POSITIVE_INFINITY }\n );\n if (nearest.point) {\n // Skip if this marker matches the very first elevation point (start of route)\n if (nearest.point.distance === 0) {\n return;\n }\n markers.push({\n distance: nearest.point.distance,\n elevation: nearest.point.elevation,\n name: f?.properties?.name,\n });\n }\n });\n\n return markers.sort((a, b) => (a.distance ?? 0) - (b.distance ?? 0));\n};\n\nexport const findNearestPointByCoordinates = (\n points: [number, number][],\n target: { lat: number; lng: number }\n): ElevationPoint | null => {\n if (!points.length) return null;\n let closest: ElevationPoint | null = null;\n let minDist = Number.POSITIVE_INFINITY;\n points.forEach(([lng, lat]) => {\n const d = ((lat - target.lat) ** 2) + ((lng - target.lng) ** 2);\n if (d < minDist) {\n minDist = d;\n closest = { lat, lng } as ElevationPoint;\n }\n });\n return closest;\n};\n\nexport const findNearestPoint = (\n points: ElevationPoint[],\n target: [number, number]\n): ElevationPoint | null => {\n if (!points.length) return null;\n let closest: ElevationPoint | null = null;\n let minDist = Number.POSITIVE_INFINITY;\n points.forEach((p) => {\n const d = ((p.lat - target[0]) ** 2) + ((p.lng - target[1]) ** 2);\n if (d < minDist) {\n minDist = d;\n closest = p;\n }\n });\n return closest;\n};\n\nconst DISTANCE_THRESHOLD = 1000; // meters\n\nexport const isCloseCheck = (\n marker1: Marker,\n marker2?: Marker,\n threshold: number = DISTANCE_THRESHOLD\n) => {\n return (\n marker2 &&\n Math.abs((marker2.distance ?? 0) - (marker1.distance ?? 0)) < threshold\n );\n};\n","import { useEffect, useMemo } from \"react\";\nimport {\n CartesianGrid,\n ComposedChart,\n Customized,\n Line,\n ReferenceDot,\n ReferenceLine,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from \"recharts\";\nimport { useTheme } from \"../../../theme-provider\";\nimport type { RouteConfig } from \"../../../types\";\nimport { HoverStateChangeSource, useHover } from \"../HoverContext\";\nimport { DistanceTick } from \"./DistanceTick\";\nimport { ElevationDot } from \"./ElevationDot\";\nimport { ElevationTick } from \"./ElevationTick\";\nimport { ElevationTooltip } from \"./ElevationTooltip\";\nimport { MarkerShape } from \"./MarkerShape\";\nimport { RouteStrip } from \"./RouteStrip\";\nimport { SURFACE_STRIP_HEIGHT, SurfaceStrip } from \"./SurfaceStrip\";\nimport { useTriggerByXValue } from \"./useTriggerByXValue\";\nimport {\n computeMarkerPoints,\n computeMinMax,\n computeRoundedDomainAndTicks,\n findNearestPoint,\n getMaxDistance,\n getPointsWithElevation,\n getTicksForDistance,\n isCloseCheck,\n} from \"./utils\";\n\ninterface ElevationChartProps {\n route: RouteConfig;\n}\n\nexport const ElevationChart = ({ route }: ElevationChartProps) => {\n const { hover, setHover } = useHover();\n const theme = useTheme();\n const points = useMemo(() => getPointsWithElevation(route), [route]);\n const markers = useMemo(\n () => computeMarkerPoints(points, route.geoJson),\n [points, route.geoJson]\n );\n const maxDistance = getMaxDistance(points);\n const ticks = getTicksForDistance(maxDistance);\n const [min, max] = computeMinMax(points);\n const [minY, maxY, tickVals] = useMemo(\n () => computeRoundedDomainAndTicks([min, max], !!route.surface?.length),\n [min, max, route.surface?.length]\n );\n\n const { activeIndex, activePoint, triggerByXValue, clearActiveIndex } =\n useTriggerByXValue(points);\n\n useEffect(() => {\n if (\n hover.source === HoverStateChangeSource.Chart ||\n !hover.lat ||\n !hover.lng\n )\n return;\n const nearestPoint = findNearestPoint(points, [hover.lat, hover.lng]);\n if (nearestPoint) {\n triggerByXValue(nearestPoint.distance);\n }\n }, [hover, points, triggerByXValue]);\n\n if (!points.length) {\n return null;\n }\n\n return (\n <ResponsiveContainer\n width=\"100%\"\n height=\"100%\"\n style={{ userSelect: \"none\" }}\n >\n <ComposedChart\n data={points}\n margin={theme.chart.margin}\n onMouseMove={({ activePayload }) => {\n activeIndex && clearActiveIndex();\n const activePayloadItem = activePayload?.[0];\n if (!activePayloadItem) {\n return;\n }\n const { lat, lng } = activePayloadItem.payload;\n setHover({ lat, lng, source: HoverStateChangeSource.Chart });\n }}\n onMouseEnter={() => clearActiveIndex()}\n >\n <defs>\n <linearGradient id=\"elevationGradient\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop\n offset=\"0%\"\n stopColor={theme.colors.primary}\n stopOpacity={theme.chart.gradientStartOpacity}\n />\n <stop\n offset=\"100%\"\n stopColor={theme.colors.primaryMuted}\n stopOpacity={theme.chart.gradientEndOpacity}\n />\n </linearGradient>\n </defs>\n\n <CartesianGrid\n stroke={theme.chart.gridStroke}\n strokeDasharray={theme.chart.gridDasharray}\n />\n <Customized\n component={\n <RouteStrip\n route={route}\n maxDistance={maxDistance}\n belowHeight={SURFACE_STRIP_HEIGHT}\n />\n }\n />\n <Customized\n component={<SurfaceStrip route={route} maxDistance={maxDistance} />}\n />\n <XAxis\n dataKey=\"distance\"\n type=\"number\"\n domain={[0, maxDistance]}\n ticks={ticks}\n tick={<DistanceTick />}\n stroke={theme.chart.axisStroke}\n />\n <YAxis\n dataKey=\"elevation\"\n tick={<ElevationTick />}\n domain={[minY, maxY]}\n ticks={tickVals}\n stroke={theme.chart.axisStroke}\n width={theme.chart.yAxisWidth}\n />\n\n <Tooltip\n cursor={{\n stroke: theme.chart.cursorStroke,\n strokeWidth: theme.chart.cursorStrokeWidth,\n }}\n content={\n <ElevationTooltip\n accent={theme.colors.accent}\n primary={theme.colors.primary}\n markers={markers}\n surfaces={route.surface}\n routes={route.routes}\n />\n }\n />\n\n <Line\n type=\"monotone\"\n dataKey=\"elevation\"\n stroke={theme.colors.primary}\n strokeWidth={theme.chart.lineStrokeWidth}\n // @ts-ignore\n dot={(props) => {\n const { cx, cy, index } = props;\n const isActive = index === activeIndex;\n\n if (isActive && activePoint) {\n return <ElevationDot cx={cx} cy={cy} key={`dot-${cx}-${cy}`} />;\n }\n }}\n activeDot={{\n r: theme.chart.activeDotRadius,\n fill: theme.dots.chartActive,\n strokeWidth: 0,\n }}\n fill=\"url(#elevationGradient)\"\n isAnimationActive={false}\n />\n\n {markers.length > 0 &&\n markers.map((m, idx) => {\n const tooClose = isCloseCheck(markers[idx], markers[idx + 1]);\n return (\n <ReferenceDot\n key={`${m.distance}-${idx}`}\n x={m.distance}\n y={m.elevation}\n r={theme.chart.referenceDotRadius}\n shape={(props) => (\n <MarkerShape\n {...props}\n name={tooClose ? undefined : m.name}\n fill={theme.colors.accent}\n />\n )}\n />\n );\n })}\n\n {/* Vertical line at active X (same as hover cursor) */}\n {activePoint && (\n <ReferenceLine\n x={activePoint.distance}\n opacity={theme.chart.referenceLineOpacity}\n />\n )}\n </ComposedChart>\n </ResponsiveContainer>\n );\n};\n","import markerSvg from \"./assets/icons/marker.svg\";\nimport markerFinishSvg from \"./assets/icons/markerFinish.svg\";\nimport markerStartSvg from \"./assets/icons/markerStart.svg\";\n\nexport const DEFAULT_CENTER = { lat: 48.9325937, lng: 20.3452306 };\nexport const DEFAULT_ZOOM_HORIZONTAL = 13;\nexport const DEFAULT_ZOOM_VERTICAL = 12;\n\nexport const markers = {\n default: markerSvg,\n start: markerStartSvg,\n finish: markerFinishSvg,\n}\n","import { useEffect, useMemo, useRef } from \"react\";\nimport {\n DEFAULT_CENTER,\n DEFAULT_ZOOM_HORIZONTAL,\n DEFAULT_ZOOM_VERTICAL,\n} from \"../../constants\";\nimport { useTheme } from \"../../theme-provider\";\nimport type { RouteConfig } from \"../../types\";\nimport { buildMarkerIcon } from \"../icons/buildMarkerIcon\";\nimport {\n findNearestPointByCoordinates,\n getAllPoints,\n} from \"./ElevationChart/utils\";\nimport styles from \"./GoogleMapCanvas.module.css\";\nimport { HoverStateChangeSource, useHover } from \"./HoverContext\";\n\ninterface GoogleMapCanvasProps {\n route: RouteConfig;\n height: number | string;\n isHorizontal: boolean;\n}\n\nexport const GoogleMapCanvas = ({\n route,\n height,\n isHorizontal,\n}: GoogleMapCanvasProps) => {\n const theme = useTheme();\n const { hover, setHover } = useHover();\n const ref = useRef<HTMLDivElement | null>(null);\n const highlightMarkerRef = useRef<google.maps.Marker | null>(null);\n const mapRef = useRef<google.maps.Map | null>(null);\n const points = useMemo(() => getAllPoints(route), [route]);\n const markerIcons = useMemo(\n () => ({\n default: buildMarkerIcon(theme.marker.outer, theme.marker.inner),\n start: buildMarkerIcon(theme.marker.outer, theme.marker.startInner),\n finish: buildMarkerIcon(theme.marker.outer, theme.marker.finishInner),\n }),\n [theme.marker]\n );\n\n useEffect(() => {\n if (!ref.current || !window.google?.maps) {\n return;\n }\n\n const zoom =\n (isHorizontal && (route.zoomHorizontal || DEFAULT_ZOOM_HORIZONTAL)) ||\n route.zoomVertical ||\n DEFAULT_ZOOM_VERTICAL;\n\n const map = new window.google.maps.Map(ref.current, {\n center: route.center || DEFAULT_CENTER,\n zoom,\n mapTypeId: window.google.maps.MapTypeId.SATELLITE,\n streetViewControl: false,\n });\n mapRef.current = map;\n\n map.data.setStyle((feature: google.maps.Data.Feature) => {\n const name = feature.getProperty(\"name\") as string;\n const isFirst = feature.getProperty(\"first\") as boolean;\n const isLast = feature.getProperty(\"last\") as boolean;\n\n return {\n strokeColor: theme.colors.primaryMuted,\n strokeWeight: theme.map.strokeWeight,\n icon: {\n url: isFirst\n ? markerIcons.start\n : isLast\n ? markerIcons.finish\n : markerIcons.default,\n scaledSize: new window.google.maps.Size(\n theme.map.markerSize,\n theme.map.markerSize\n ),\n optimized: false,\n zIndex: isFirst || isLast ? 100 : 10,\n collisionBehavior:\n window.google?.maps?.CollisionBehavior?.REQUIRED_AND_HIDES_OPTIONAL,\n },\n label: {\n className: \"rrpMarkerLabel\",\n fontSize: `${theme.map.markerLabelFontSize}px`,\n fontWeight: theme.map.markerLabelFontWeight,\n color: theme.colors.accent,\n text: name,\n },\n };\n });\n\n map.data.addGeoJson(route.geoJson);\n\n const moveListener = map.addListener(\n \"mousemove\",\n (e: google.maps.MapMouseEvent) => {\n const latLng = e.latLng;\n if (!latLng) return;\n const nearest = findNearestPointByCoordinates(points, {\n lat: latLng.lat(),\n lng: latLng.lng(),\n });\n if (nearest) {\n setHover({\n lat: nearest.lat,\n lng: nearest.lng,\n source: HoverStateChangeSource.Map,\n });\n }\n }\n );\n\n return () => {\n moveListener.remove();\n map.data.forEach((feature: google.maps.Data.Feature) => {\n map.data.remove(feature);\n });\n mapRef.current = null;\n };\n }, [route, isHorizontal, theme, points, setHover, markerIcons]);\n\n useEffect(() => {\n if (!ref.current || !window.google?.maps) return;\n const mapInstance = mapRef.current;\n if (!mapInstance) return;\n if (!hover.lat || !hover.lng) {\n if (highlightMarkerRef.current) {\n highlightMarkerRef.current.setMap(null);\n highlightMarkerRef.current = null;\n }\n return;\n }\n const icon = {\n path: window.google.maps.SymbolPath.CIRCLE,\n scale: theme.map.hoverMarkerScale,\n fillColor: theme.dots.mapActive,\n fillOpacity: 1,\n strokeWeight: 0,\n };\n if (!highlightMarkerRef.current) {\n highlightMarkerRef.current = new window.google.maps.Marker({\n map: mapInstance,\n icon,\n });\n } else {\n highlightMarkerRef.current.setIcon(icon);\n }\n highlightMarkerRef.current.setPosition({ lat: hover.lat, lng: hover.lng });\n highlightMarkerRef.current.setMap(mapInstance);\n }, [hover, theme]);\n\n return (\n <div\n ref={ref}\n className={styles.rrpMapCanvas}\n style={{\n height,\n }}\n />\n );\n};\n","import { Status, Wrapper } from \"@googlemaps/react-wrapper\";\nimport type { CSSProperties } from \"react\";\nimport { useOrientation } from \"../../hooks/useOrientation\";\nimport { theme as defaultTheme, type PartialTheme } from \"../../theme\";\nimport { ThemeProvider } from \"../../theme-provider\";\nimport type { RouteConfig } from \"../../types\";\nimport Loader from \"../Loader\";\nimport { ElevationChart } from \"./ElevationChart\";\nimport { GoogleMapCanvas } from \"./GoogleMapCanvas\";\nimport { HoverProvider } from \"./HoverContext\";\nimport styles from \"./RouteMap.module.css\";\n\nexport interface RouteMapProps {\n apiKey: string;\n route: RouteConfig;\n height?: number | string;\n className?: string;\n style?: CSSProperties;\n theme?: PartialTheme;\n}\n\nconst messages = {\n apiKey: \"Oops! Cannot display the map: Google Maps API key missing\",\n [Status.FAILURE]:\n \"Unable to load Google Maps API. Check your API key or network.\",\n [Status.LOADING]: undefined,\n [Status.SUCCESS]: undefined,\n};\n\nconst RenderLoader = ({\n type,\n height,\n}: {\n type: keyof typeof messages;\n height?: number | string;\n}) => (\n <div style={{ height }}>\n <Loader message={messages[type]} height={height} />\n </div>\n);\n\nconst render = (status: Status, height?: number | string) => (\n <RenderLoader type={status} height={height} />\n);\n\nexport const RouteMap = ({\n apiKey,\n route,\n height = \"100dvh\",\n className,\n style,\n theme = defaultTheme,\n}: RouteMapProps) => {\n const { isHorizontal } = useOrientation();\n\n if (!apiKey) {\n return (\n <ThemeProvider theme={theme}>\n <RenderLoader type=\"apiKey\" height={height} />\n </ThemeProvider>\n );\n }\n\n const containerStyle: CSSProperties = {\n height,\n width: \"100%\",\n ...style,\n };\n\n return (\n <ThemeProvider theme={theme}>\n <HoverProvider>\n <div className={className} style={containerStyle}>\n <Wrapper apiKey={apiKey} render={(status) => render(status, height)}>\n <GoogleMapCanvas\n route={route}\n height={height}\n isHorizontal={isHorizontal}\n />\n </Wrapper>\n <div className={styles.rrpChartLayer}>\n <div className={styles.rrpChartBody}>\n <ElevationChart route={route} />\n </div>\n </div>\n </div>\n </HoverProvider>\n </ThemeProvider>\n );\n};\n","import * as React from \"react\";\n\nfunction isShallowEqual(object1, object2) {\n const keys1 = Object.keys(object1);\n const keys2 = Object.keys(object2);\n\n if (keys1.length !== keys2.length) {\n return false;\n }\n\n for (let key of keys1) {\n if (object1[key] !== object2[key]) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction isTouchEvent({ nativeEvent }) {\n return window.TouchEvent\n ? nativeEvent instanceof TouchEvent\n : \"touches\" in nativeEvent;\n}\n\nfunction isMouseEvent(event) {\n return event.nativeEvent instanceof MouseEvent;\n}\n\nfunction throttle(cb, ms) {\n let lastTime = 0;\n return () => {\n const now = Date.now();\n if (now - lastTime >= ms) {\n cb();\n lastTime = now;\n }\n };\n}\n\nfunction isPlainObject(value) {\n return Object.prototype.toString.call(value) === \"[object Object]\";\n}\n\nfunction dispatchStorageEvent(key, newValue) {\n window.dispatchEvent(new StorageEvent(\"storage\", { key, newValue }));\n}\n\nexport function useBattery() {\n const [state, setState] = React.useState({\n supported: true,\n loading: true,\n level: null,\n charging: null,\n chargingTime: null,\n dischargingTime: null,\n });\n\n React.useEffect(() => {\n if (!navigator.getBattery) {\n setState((s) => ({\n ...s,\n supported: false,\n loading: false,\n }));\n return;\n }\n\n let battery = null;\n\n const handleChange = () => {\n setState({\n supported: true,\n loading: false,\n level: battery.level,\n charging: battery.charging,\n chargingTime: battery.chargingTime,\n dischargingTime: battery.dischargingTime,\n });\n };\n\n navigator.getBattery().then((b) => {\n battery = b;\n handleChange();\n\n b.addEventListener(\"levelchange\", handleChange);\n b.addEventListener(\"chargingchange\", handleChange);\n b.addEventListener(\"chargingtimechange\", handleChange);\n b.addEventListener(\"dischargingtimechange\", handleChange);\n });\n\n return () => {\n if (battery) {\n battery.removeEventListener(\"levelchange\", handleChange);\n battery.removeEventListener(\"chargingchange\", handleChange);\n battery.removeEventListener(\"chargingtimechange\", handleChange);\n battery.removeEventListener(\"dischargingtimechange\", handleChange);\n }\n };\n }, []);\n\n return state;\n}\n\nexport function useClickAway(cb) {\n const ref = React.useRef(null);\n const refCb = React.useRef(cb);\n\n React.useLayoutEffect(() => {\n refCb.current = cb;\n });\n\n React.useEffect(() => {\n const handler = (e) => {\n const element = ref.current;\n if (element && !element.contains(e.target)) {\n refCb.current(e);\n }\n };\n\n document.addEventListener(\"mousedown\", handler);\n document.addEventListener(\"touchstart\", handler);\n\n return () => {\n document.removeEventListener(\"mousedown\", handler);\n document.removeEventListener(\"touchstart\", handler);\n };\n }, []);\n\n return ref;\n}\n\nfunction oldSchoolCopy(text) {\n const tempTextArea = document.createElement(\"textarea\");\n tempTextArea.value = text;\n document.body.appendChild(tempTextArea);\n tempTextArea.select();\n document.execCommand(\"copy\");\n document.body.removeChild(tempTextArea);\n}\n\nexport function useCopyToClipboard() {\n const [state, setState] = React.useState(null);\n\n const copyToClipboard = React.useCallback((value) => {\n const handleCopy = async () => {\n try {\n if (navigator?.clipboard?.writeText) {\n await navigator.clipboard.writeText(value);\n setState(value);\n } else {\n throw new Error(\"writeText not supported\");\n }\n } catch (e) {\n oldSchoolCopy(value);\n setState(value);\n }\n };\n\n handleCopy();\n }, []);\n\n return [state, copyToClipboard];\n}\n\nexport function useCounter(startingValue = 0, options = {}) {\n const { min, max } = options;\n\n if (typeof min === \"number\" && startingValue < min) {\n throw new Error(\n `Your starting value of ${startingValue} is less than your min of ${min}.`\n );\n }\n\n if (typeof max === \"number\" && startingValue > max) {\n throw new Error(\n `Your starting value of ${startingValue} is greater than your max of ${max}.`\n );\n }\n\n const [count, setCount] = React.useState(startingValue);\n\n const increment = React.useCallback(() => {\n setCount((c) => {\n const nextCount = c + 1;\n\n if (typeof max === \"number\" && nextCount > max) {\n return c;\n }\n\n return nextCount;\n });\n }, [max]);\n\n const decrement = React.useCallback(() => {\n setCount((c) => {\n const nextCount = c - 1;\n\n if (typeof min === \"number\" && nextCount < min) {\n return c;\n }\n\n return nextCount;\n });\n }, [min]);\n\n const set = React.useCallback(\n (nextCount) => {\n setCount((c) => {\n if (typeof max === \"number\" && nextCount > max) {\n return c;\n }\n\n if (typeof min === \"number\" && nextCount < min) {\n return c;\n }\n\n return nextCount;\n });\n },\n [max, min]\n );\n\n const reset = React.useCallback(() => {\n setCount(startingValue);\n }, [startingValue]);\n\n return [\n count,\n {\n increment,\n decrement,\n set,\n reset,\n },\n ];\n}\n\nexport function useDebounce(value, delay) {\n const [debouncedValue, setDebouncedValue] = React.useState(value);\n\n React.useEffect(() => {\n const handler = setTimeout(() => {\n setDebouncedValue(value);\n }, delay);\n\n return () => {\n clearTimeout(handler);\n };\n }, [value, delay]);\n\n return debouncedValue;\n}\n\nexport function useDefault(initialValue, defaultValue) {\n const [state, setState] = React.useState(initialValue);\n\n if (typeof state === \"undefined\" || state === null) {\n return [defaultValue, setState];\n }\n\n return [state, setState];\n}\n\nexport function useDocumentTitle(title) {\n React.useEffect(() => {\n document.title = title;\n }, [title]);\n}\n\nexport function useFavicon(url) {\n React.useEffect(() => {\n let link = document.querySelector(`link[rel~=\"icon\"]`);\n\n if (!link) {\n link = document.createElement(\"link\");\n link.type = \"image/x-icon\";\n link.rel = \"icon\";\n link.href = url;\n document.head.appendChild(link);\n } else {\n link.href = url;\n }\n }, [url]);\n}\n\nexport function useGeolocation(options = {}) {\n const [state, setState] = React.useState({\n loading: true,\n accuracy: null,\n altitude: null,\n altitudeAccuracy: null,\n heading: null,\n latitude: null,\n longitude: null,\n speed: null,\n timestamp: null,\n error: null,\n });\n\n const optionsRef = React.useRef(options);\n\n React.useEffect(() => {\n const onEvent = ({ coords, timestamp }) => {\n setState({\n loading: false,\n timestamp,\n latitude: coords.latitude,\n longitude: coords.longitude,\n altitude: coords.altitude,\n accuracy: coords.accuracy,\n altitudeAccuracy: coords.altitudeAccuracy,\n heading: coords.heading,\n speed: coords.speed,\n });\n };\n\n const onEventError = (error) => {\n setState((s) => ({\n ...s,\n loading: false,\n error,\n }));\n };\n\n navigator.geolocation.getCurrentPosition(\n onEvent,\n onEventError,\n optionsRef.current\n );\n\n const watchId = navigator.geolocation.watchPosition(\n onEvent,\n onEventError,\n optionsRef.current\n );\n\n return () => {\n navigator.geolocation.clearWatch(watchId);\n };\n }, []);\n\n return state;\n}\n\nconst initialUseHistoryStateState = {\n past: [],\n present: null,\n future: [],\n};\n\nconst useHistoryStateReducer = (state, action) => {\n const { past, present, future } = state;\n\n if (action.type === \"UNDO\") {\n return {\n past: past.slice(0, past.length - 1),\n present: past[past.length - 1],\n future: [present, ...future],\n };\n } else if (action.type === \"REDO\") {\n return {\n past: [...past, present],\n present: future[0],\n future: future.slice(1),\n };\n } else if (action.type === \"SET\") {\n const { newPresent } = action;\n\n if (action.newPresent === present) {\n return state;\n }\n\n return {\n past: [...past, present],\n present: newPresent,\n future: [],\n };\n } else if (action.type === \"CLEAR\") {\n return {\n ...initialUseHistoryStateState,\n present: action.initialPresent,\n };\n } else {\n throw new Error(\"Unsupported action type\");\n }\n};\n\nexport function useHistoryState(initialPresent = {}) {\n const initialPresentRef = React.useRef(initialPresent);\n\n const [state, dispatch] = React.useReducer(useHistoryStateReducer, {\n ...initialUseHistoryStateState,\n present: initialPresentRef.current,\n });\n\n const canUndo = state.past.length !== 0;\n const canRedo = state.future.length !== 0;\n\n const undo = React.useCallback(() => {\n if (canUndo) {\n dispatch({ type: \"UNDO\" });\n }\n }, [canUndo]);\n\n const redo = React.useCallback(() => {\n if (canRedo) {\n dispatch({ type: \"REDO\" });\n }\n }, [canRedo]);\n\n const set = React.useCallback(\n (newPresent) => dispatch({ type: \"SET\", newPresent }),\n []\n );\n\n const clear = React.useCallback(\n () =>\n dispatch({ type: \"CLEAR\", initialPresent: initialPresentRef.current }),\n []\n );\n\n return { state: state.present, set, undo, redo, clear, canUndo, canRedo };\n}\n\nexport function useHover() {\n const [hovering, setHovering] = React.useState(false);\n const previousNode = React.useRef(null);\n\n const handleMouseEnter = React.useCallback(() => {\n setHovering(true);\n }, []);\n\n const handleMouseLeave = React.useCallback(() => {\n setHovering(false);\n }, []);\n\n const customRef = React.useCallback(\n (node) => {\n if (previousNode.current?.nodeType === Node.ELEMENT_NODE) {\n previousNode.current.removeEventListener(\n \"mouseenter\",\n handleMouseEnter\n );\n previousNode.current.removeEventListener(\n \"mouseleave\",\n handleMouseLeave\n );\n }\n\n if (node?.nodeType === Node.ELEMENT_NODE) {\n node.addEventListener(\"mouseenter\", handleMouseEnter);\n node.addEventListener(\"mouseleave\", handleMouseLeave);\n }\n\n previousNode.current = node;\n },\n [handleMouseEnter, handleMouseLeave]\n );\n\n return [customRef, hovering];\n}\n\nexport function useIdle(ms = 1000 * 60) {\n const [idle, setIdle] = React.useState(false);\n\n React.useEffect(() => {\n let timeoutId;\n\n const handleTimeout = () => {\n setIdle(true);\n };\n\n const handleEvent = throttle((e) => {\n setIdle(false);\n\n window.clearTimeout(timeoutId);\n timeoutId = window.setTimeout(handleTimeout, ms);\n }, 500);\n\n const handleVisibilityChange = () => {\n if (!document.hidden) {\n handleEvent();\n }\n };\n\n timeoutId = window.setTimeout(handleTimeout, ms);\n\n window.addEventListener(\"mousemove\", handleEvent);\n window.addEventListener(\"mousedown\", handleEvent);\n window.addEventListener(\"resize\", handleEvent);\n window.addEventListener(\"keydown\", handleEvent);\n window.addEventListener(\"touchstart\", handleEvent);\n window.addEventListener(\"wheel\", handleEvent);\n document.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n return () => {\n window.removeEventListener(\"mousemove\", handleEvent);\n window.removeEventListener(\"mousedown\", handleEvent);\n window.removeEventListener(\"resize\", handleEvent);\n window.removeEventListener(\"keydown\", handleEvent);\n window.removeEventListener(\"touchstart\", handleEvent);\n window.removeEventListener(\"wheel\", handleEvent);\n document.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n window.clearTimeout(timeoutId);\n };\n }, [ms]);\n\n return idle;\n}\n\nexport function useIntersectionObserver(options = {}) {\n const { threshold = 1, root = null, rootMargin = \"0px\" } = options;\n const [entry, setEntry] = React.useState(null);\n\n const previousObserver = React.useRef(null);\n\n const customRef = React.useCallback(\n (node) => {\n if (previousObserver.current) {\n previousObserver.current.disconnect();\n previousObserver.current = null;\n }\n\n if (node?.nodeType === Node.ELEMENT_NODE) {\n const observer = new IntersectionObserver(\n ([entry]) => {\n setEntry(entry);\n },\n { threshold, root, rootMargin }\n );\n\n observer.observe(node);\n previousObserver.current = observer;\n }\n },\n [threshold, root, rootMargin]\n );\n\n return [customRef, entry];\n}\n\nexport function useIsClient() {\n const [isClient, setIsClient] = React.useState(false);\n\n React.useEffect(() => {\n setIsClient(true);\n }, []);\n\n return isClient;\n}\n\nexport function useIsFirstRender() {\n const renderRef = React.useRef(true);\n\n if (renderRef.current === true) {\n renderRef.current = false;\n return true;\n }\n\n return renderRef.current;\n}\n\nexport function useList(defaultList = []) {\n const [list, setList] = React.useState(defaultList);\n\n const set = React.useCallback((l) => {\n setList(l);\n }, []);\n\n const push = React.useCallback((element) => {\n setList((l) => [...l, element]);\n }, []);\n\n const removeAt = React.useCallback((index) => {\n setList((l) => [...l.slice(0, index), ...l.slice(index + 1)]);\n }, []);\n\n const insertAt = React.useCallback((index, element) => {\n setList((l) => [...l.slice(0, index), element, ...l.slice(index)]);\n }, []);\n\n const updateAt = React.useCallback((index, element) => {\n setList((l) => l.map((e, i) => (i === index ? element : e)));\n }, []);\n\n const clear = React.useCallback(() => setList([]), []);\n\n return [list, { set, push, removeAt, insertAt, updateAt, clear }];\n}\n\nconst setLocalStorageItem = (key, value) => {\n const stringifiedValue = JSON.stringify(value);\n window.localStorage.setItem(key, stringifiedValue);\n dispatchStorageEvent(key, stringifiedValue);\n};\n\nconst removeLocalStorageItem = (key) => {\n window.localStorage.removeItem(key);\n dispatchStorageEvent(key, null);\n};\n\nconst getLocalStorageItem = (key) => {\n return window.localStorage.getItem(key);\n};\n\nconst useLocalStorageSubscribe = (callback) => {\n window.addEventListener(\"storage\", callback);\n return () => window.removeEventListener(\"storage\", callback);\n};\n\nconst getLocalStorageServerSnapshot = () => {\n throw Error(\"useLocalStorage is a client-only hook\");\n};\n\nexport function useLocalStorage(key, initialValue) {\n const getSnapshot = () => getLocalStorageItem(key);\n\n const store = React.useSyncExternalStore(\n useLocalStorageSubscribe,\n getSnapshot,\n getLocalStorageServerSnapshot\n );\n\n const setState = React.useCallback(\n (v) => {\n try {\n const nextState = typeof v === \"function\" ? v(JSON.parse(store)) : v;\n\n if (nextState === undefined || nextState === null) {\n removeLocalStorageItem(key);\n } else {\n setLocalStorageItem(key, nextState);\n }\n } catch (e) {\n console.warn(e);\n }\n },\n [key, store]\n );\n\n React.useEffect(() => {\n if (\n getLocalStorageItem(key) === null &&\n typeof initialValue !== \"undefined\"\n ) {\n setLocalStorageItem(key, initialValue);\n }\n }, [key, initialValue]);\n\n return [store ? JSON.parse(store) : initialValue, setState];\n}\n\nexport function useLockBodyScroll() {\n React.useLayoutEffect(() => {\n const originalStyle = window.getComputedStyle(document.body).overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = originalStyle;\n };\n }, []);\n}\n\nexport function useLongPress(callback, options = {}) {\n const { threshold = 400, onStart, onFinish, onCancel } = options;\n const isLongPressActive = React.useRef(false);\n const isPressed = React.useRef(false);\n const timerId = React.useRef();\n\n return React.useMemo(() => {\n if (typeof callback !== \"function\") {\n return {};\n }\n\n const start = (event) => {\n if (!isMouseEvent(event) && !isTouchEvent(event)) return;\n\n if (onStart) {\n onStart(event);\n }\n\n isPressed.current = true;\n timerId.current = setTimeout(() => {\n callback(event);\n isLongPressActive.current = true;\n }, threshold);\n };\n\n const cancel = (event) => {\n if (!isMouseEvent(event) && !isTouchEvent(event)) return;\n\n if (isLongPressActive.current) {\n if (onFinish) {\n onFinish(event);\n }\n } else if (isPressed.current) {\n if (onCancel) {\n onCancel(event);\n }\n }\n\n isLongPressActive.current = false;\n isPressed.current = false;\n\n if (timerId.current) {\n window.clearTimeout(timerId.current);\n }\n };\n\n const mouseHandlers = {\n onMouseDown: start,\n onMouseUp: cancel,\n onMouseLeave: cancel,\n };\n\n const touchHandlers = {\n onTouchStart: start,\n onTouchEnd: cancel,\n };\n\n return {\n ...mouseHandlers,\n ...touchHandlers,\n };\n }, [callback, threshold, onCancel, onFinish, onStart]);\n}\n\nexport function useMap(initialState) {\n const mapRef = React.useRef(new Map(initialState));\n const [, reRender] = React.useReducer((x) => x + 1, 0);\n\n mapRef.current.set = (...args) => {\n Map.prototype.set.apply(mapRef.current, args);\n reRender();\n return mapRef.current;\n };\n\n mapRef.current.clear = (...args) => {\n Map.prototype.clear.apply(mapRef.current, args);\n reRender();\n };\n\n mapRef.current.delete = (...args) => {\n const res = Map.prototype.delete.apply(mapRef.current, args);\n reRender();\n\n return res;\n };\n\n return mapRef.current;\n}\n\nexport function useMeasure() {\n const [dimensions, setDimensions] = React.useState({\n width: null,\n height: null,\n });\n\n const previousObserver = React.useRef(null);\n\n const customRef = React.useCallback((node) => {\n if (previousObserver.current) {\n previousObserver.current.disconnect();\n previousObserver.current = null;\n }\n\n if (node?.nodeType === Node.ELEMENT_NODE) {\n const observer = new ResizeObserver(([entry]) => {\n if (entry && entry.borderBoxSize) {\n const { inlineSize: width, blockSize: height } =\n entry.borderBoxSize[0];\n\n setDimensions({ width, height });\n }\n });\n\n observer.observe(node);\n previousObserver.current = observer;\n }\n }, []);\n\n return [customRef, dimensions];\n}\n\nexport function useMediaQuery(query) {\n const subscribe = React.useCallback(\n (callback) => {\n const matchMedia = window.matchMedia(query);\n\n matchMedia.addEventListener(\"change\", callback);\n return () => {\n matchMedia.removeEventListener(\"change\", callback);\n };\n },\n [query]\n );\n\n const getSnapshot = () => {\n return window.matchMedia(query).matches;\n };\n\n const getServerSnapshot = () => {\n throw Error(\"useMediaQuery is a client-only hook\");\n };\n\n return React.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n}\n\nexport function useMouse() {\n const [state, setState] = React.useState({\n x: 0,\n y: 0,\n elementX: 0,\n elementY: 0,\n elementPositionX: 0,\n elementPositionY: 0,\n });\n\n const ref = React.useRef(null);\n\n React.useLayoutEffect(() => {\n const handleMouseMove = (event) => {\n let newState = {\n x: event.pageX,\n y: event.pageY,\n };\n\n if (ref.current?.nodeType === Node.ELEMENT_NODE) {\n const { left, top } = ref.current.getBoundingClientRect();\n const elementPositionX = left + window.scrollX;\n const elementPositionY = top + window.scrollY;\n const elementX = event.pageX - elementPositionX;\n const elementY = event.pageY - elementPositionY;\n\n newState.elementX = elementX;\n newState.elementY = elementY;\n newState.elementPositionX = elementPositionX;\n newState.elementPositionY = elementPositionY;\n }\n\n setState((s) => {\n return {\n ...s,\n ...newState,\n };\n });\n };\n\n document.addEventListener(\"mousemove\", handleMouseMove);\n\n return () => {\n document.removeEventListener(\"mousemove\", handleMouseMove);\n };\n }, []);\n\n return [state, ref];\n}\n\nconst getConnection = () => {\n return (\n navigator?.connection ||\n navigator?.mozConnection ||\n navigator?.webkitConnection\n );\n};\n\nconst useNetworkStateSubscribe = (callback) => {\n window.addEventListener(\"online\", callback, { passive: true });\n window.addEventListener(\"offline\", callback, { passive: true });\n\n const connection = getConnection();\n\n if (connection) {\n connection.addEventListener(\"change\", callback, { passive: true });\n }\n\n return () => {\n window.removeEventListener(\"online\", callback);\n window.removeEventListener(\"offline\", callback);\n\n if (connection) {\n connection.removeEventListener(\"change\", callback);\n }\n };\n};\n\nconst getNetworkStateServerSnapshot = () => {\n throw Error(\"useNetworkState is a client-only hook\");\n};\n\nexport function useNetworkState() {\n const cache = React.useRef({});\n\n const getSnapshot = () => {\n const online = navigator.onLine;\n const connection = getConnection();\n\n const nextState = {\n online,\n downlink: connection?.downlink,\n downlinkMax: connection?.downlinkMax,\n effectiveType: connection?.effectiveType,\n rtt: connection?.rtt,\n saveData: connection?.saveData,\n type: connection?.type,\n };\n\n if (isShallowEqual(cache.current, nextState)) {\n return cache.current;\n } else {\n cache.current = nextState;\n return nextState;\n }\n };\n\n return React.useSyncExternalStore(\n useNetworkStateSubscribe,\n getSnapshot,\n getNetworkStateServerSnapshot\n );\n}\n\nexport function useObjectState(initialValue) {\n const [state, setState] = React.useState(initialValue);\n\n const handleUpdate = React.useCallback((arg) => {\n if (typeof arg === \"function\") {\n setState((s) => {\n const newState = arg(s);\n\n if (isPlainObject(newState)) {\n return {\n ...s,\n ...newState,\n };\n }\n });\n }\n\n if (isPlainObject(arg)) {\n setState((s) => ({\n ...s,\n ...arg,\n }));\n }\n }, []);\n\n return [state, handleUpdate];\n}\n\nexport function useOrientation() {\n const [orientation, setOrientation] = React.useState({\n angle: 0,\n type: \"landscape-primary\",\n });\n\n React.useLayoutEffect(() => {\n const handleChange = () => {\n const { angle, type } = window.screen.orientation;\n setOrientation({\n angle,\n type,\n });\n };\n\n const handle_orientationchange = () => {\n setOrientation({\n type: \"UNKNOWN\",\n angle: window.orientation,\n });\n };\n\n if (window.screen?.orientation) {\n handleChange();\n window.screen.orientation.addEventListener(\"change\", handleChange);\n } else {\n handle_orientationchange();\n window.addEventListener(\"orientationchange\", handle_orientationchange);\n }\n\n return () => {\n if (window.screen?.orientation) {\n window.screen.orientation.removeEventListener(\"change\", handleChange);\n } else {\n window.removeEventListener(\n \"orientationchange\",\n handle_orientationchange\n );\n }\n };\n }, []);\n\n return orientation;\n}\n\nconst usePreferredLanguageSubscribe = (cb) => {\n window.addEventListener(\"languagechange\", cb);\n return () => window.removeEventListener(\"languagechange\", cb);\n};\n\nconst getPreferredLanguageSnapshot = () => {\n return navigator.language;\n};\n\nconst getPreferredLanguageServerSnapshot = () => {\n throw Error(\"usePreferredLanguage is a client-only hook\");\n};\n\nexport function usePreferredLanguage() {\n return React.useSyncExternalStore(\n usePreferredLanguageSubscribe,\n getPreferredLanguageSnapshot,\n getPreferredLanguageServerSnapshot\n );\n}\n\nexport function usePrevious(value) {\n const [current, setCurrent] = React.useState(value);\n const [previous, setPrevious] = React.useState(null);\n\n if (value !== current) {\n setPrevious(current);\n setCurrent(value);\n }\n\n return previous;\n}\n\nexport function useQueue(initialValue = []) {\n const [queue, setQueue] = React.useState(initialValue);\n\n const add = React.useCallback((element) => {\n setQueue((q) => [...q, element]);\n }, []);\n\n const remove = React.useCallback(() => {\n let removedElement;\n\n setQueue(([first, ...q]) => {\n removedElement = first;\n return q;\n });\n\n return removedElement;\n }, []);\n\n const clear = React.useCallback(() => {\n setQueue([]);\n }, []);\n\n return {\n add,\n remove,\n clear,\n first: queue[0],\n last: queue[queue.length - 1],\n size: queue.length,\n queue,\n };\n}\n\nexport function useRenderCount() {\n const count = React.useRef(0);\n\n count.current++;\n\n return count.current;\n}\n\nexport function useRenderInfo(name = \"Unknown\") {\n const count = React.useRef(0);\n const lastRender = React.useRef();\n const now = Date.now();\n\n count.current++;\n\n React.useEffect(() => {\n lastRender.current = Date.now();\n });\n\n const sinceLastRender = lastRender.current ? now - lastRender.current : 0;\n\n if (process.env.NODE_ENV !== \"production\") {\n const info = {\n name,\n renders: count.current,\n sinceLastRender,\n timestamp: now,\n };\n\n console.log(info);\n\n return info;\n }\n}\n\nexport function useScript(src, options = {}) {\n const [status, setStatus] = React.useState(\"loading\");\n const optionsRef = React.useRef(options);\n\n React.useEffect(() => {\n let script = document.querySelector(`script[src=\"${src}\"]`);\n\n const domStatus = script?.getAttribute(\"data-status\");\n if (domStatus) {\n setStatus(domStatus);\n return;\n }\n\n if (script === null) {\n script = document.createElement(\"script\");\n script.src = src;\n script.async = true;\n script.setAttribute(\"data-status\", \"loading\");\n document.body.appendChild(script);\n\n const handleScriptLoad = () => {\n script.setAttribute(\"data-status\", \"ready\");\n setStatus(\"ready\");\n removeEventListeners();\n };\n\n const handleScriptError = () => {\n script.setAttribute(\"data-status\", \"error\");\n setStatus(\"error\");\n removeEventListeners();\n };\n\n const removeEventListeners = () => {\n script.removeEventListener(\"load\", handleScriptLoad);\n script.removeEventListener(\"error\", handleScriptError);\n };\n\n script.addEventListener(\"load\", handleScriptLoad);\n script.addEventListener(\"error\", handleScriptError);\n\n const removeOnUnmount = optionsRef.current.removeOnUnmount;\n\n return () => {\n if (removeOnUnmount === true) {\n script.remove();\n removeEventListeners();\n }\n };\n } else {\n setStatus(\"unknown\");\n }\n }, [src]);\n\n return status;\n}\n\nconst setSessionStorageItem = (key, value) => {\n const stringifiedValue = JSON.stringify(value);\n window.sessionStorage.setItem(key, stringifiedValue);\n dispatchStorageEvent(key, stringifiedValue);\n};\n\nconst removeSessionStorageItem = (key) => {\n window.sessionStorage.removeItem(key);\n dispatchStorageEvent(key, null);\n};\n\nconst getSessionStorageItem = (key) => {\n return window.sessionStorage.getItem(key);\n};\n\nconst useSessionStorageSubscribe = (callback) => {\n window.addEventListener(\"storage\", callback);\n return () => window.removeEventListener(\"storage\", callback);\n};\n\nconst getSessionStorageServerSnapshot = () => {\n throw Error(\"useSessionStorage is a client-only hook\");\n};\n\nexport function useSessionStorage(key, initialValue) {\n const getSnapshot = () => getSessionStorageItem(key);\n\n const store = React.useSyncExternalStore(\n useSessionStorageSubscribe,\n getSnapshot,\n getSessionStorageServerSnapshot\n );\n\n const setState = React.useCallback(\n (v) => {\n try {\n const nextState = typeof v === \"function\" ? v(JSON.parse(store)) : v;\n\n if (nextState === undefined || nextState === null) {\n removeSessionStorageItem(key);\n } else {\n setSessionStorageItem(key, nextState);\n }\n } catch (e) {\n console.warn(e);\n }\n },\n [key, store]\n );\n\n React.useEffect(() => {\n if (\n getSessionStorageItem(key) === null &&\n typeof initialValue !== \"undefined\"\n ) {\n setSessionStorageItem(key, initialValue);\n }\n }, [key, initialValue]);\n\n return [store ? JSON.parse(store) : initialValue, setState];\n}\n\nexport function useSet(values) {\n const setRef = React.useRef(new Set(values));\n const [, reRender] = React.useReducer((x) => x + 1, 0);\n\n setRef.current.add = (...args) => {\n const res = Set.prototype.add.apply(setRef.current, args);\n reRender();\n\n return res;\n };\n\n setRef.current.clear = (...args) => {\n Set.prototype.clear.apply(setRef.current, args);\n reRender();\n };\n\n setRef.current.delete = (...args) => {\n const res = Set.prototype.delete.apply(setRef.current, args);\n reRender();\n\n return res;\n };\n\n return setRef.current;\n}\n\nexport function useThrottle(value, interval = 500) {\n const [throttledValue, setThrottledValue] = React.useState(value);\n const lastUpdated = React.useRef(null);\n\n React.useEffect(() => {\n const now = Date.now();\n\n if (lastUpdated.current && now >= lastUpdated.current + interval) {\n lastUpdated.current = now;\n setThrottledValue(value);\n } else {\n const id = window.setTimeout(() => {\n lastUpdated.current = now;\n setThrottledValue(value);\n }, interval);\n\n return () => window.clearTimeout(id);\n }\n }, [value, interval]);\n\n return throttledValue;\n}\n\nexport function useToggle(initialValue) {\n const [on, setOn] = React.useState(() => {\n if (typeof initialValue === \"boolean\") {\n return initialValue;\n }\n\n return Boolean(initialValue);\n });\n\n const handleToggle = React.useCallback((value) => {\n if (typeof value === \"boolean\") {\n return setOn(value);\n }\n\n return setOn((v) => !v);\n }, []);\n\n return [on, handleToggle];\n}\n\nconst useVisibilityChangeSubscribe = (callback) => {\n document.addEventListener(\"visibilitychange\", callback);\n\n return () => {\n document.removeEventListener(\"visibilitychange\", callback);\n };\n};\n\nconst getVisibilityChangeSnapshot = () => {\n return document.visibilityState;\n};\n\nconst getVisibilityChangeServerSnapshot = () => {\n throw Error(\"useVisibilityChange is a client-only hook\");\n};\n\nexport function useVisibilityChange() {\n const visibilityState = React.useSyncExternalStore(\n useVisibilityChangeSubscribe,\n getVisibilityChangeSnapshot,\n getVisibilityChangeServerSnapshot\n );\n\n return visibilityState === \"visible\";\n}\n\nexport function useWindowScroll() {\n const [state, setState] = React.useState({\n x: null,\n y: null,\n });\n\n const scrollTo = React.useCallback((...args) => {\n if (typeof args[0] === \"object\") {\n window.scrollTo(args[0]);\n } else if (typeof args[0] === \"number\" && typeof args[1] === \"number\") {\n window.scrollTo(args[0], args[1]);\n } else {\n throw new Error(\n `Invalid arguments passed to scrollTo. See here for more info. https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo`\n );\n }\n }, []);\n\n React.useLayoutEffect(() => {\n const handleScroll = () => {\n setState({ x: window.scrollX, y: window.scrollY });\n };\n\n handleScroll();\n window.addEventListener(\"scroll\", handleScroll);\n\n return () => {\n window.removeEventListener(\"scroll\", handleScroll);\n };\n }, []);\n\n return [state, scrollTo];\n}\n\nexport function useWindowSize() {\n const [size, setSize] = React.useState({\n width: null,\n height: null,\n });\n\n React.useLayoutEffect(() => {\n const handleResize = () => {\n setSize({\n width: window.innerWidth,\n height: window.innerHeight,\n });\n };\n\n handleResize();\n window.addEventListener(\"resize\", handleResize);\n\n return () => {\n window.removeEventListener(\"resize\", handleResize);\n };\n }, []);\n\n return size;\n}\n","import { useMeasure } from \"@uidotdev/usehooks\";\n\nexport const useMapHeader = () => {\n const [refHeader, { height: headerHeight }] = useMeasure();\n\n const isHeaderReady = Boolean(headerHeight);\n const mapHeight = isHeaderReady\n ? `calc(100dvh - ${headerHeight}px)`\n : \"0px\";\n\n return {\n refHeader,\n isHeaderReady,\n headerHeight,\n mapHeight,\n };\n};\n"]}