Dotted Map
magicui/dotted-mapFreeComponent
A component with a dotted map.
Live preview
live · rendered by the registry
Rendered by magicui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://magicui.design/r/dotted-map.jsonSource
1import * as React from "react"2import { createMap } from "svg-dotted-map"34import { cn } from "@/lib/utils"56export interface Marker {7 lat: number8 lng: number9 size?: number10 pulse?: boolean11}1213/** addMarkers returns markers with lat/lng removed; only x, y and other props (e.g. size) remain */14type MapMarker<M extends Marker> = Omit<M, "lat" | "lng"> & {15 x: number16 y: number17}1819export interface DottedMapProps<20 M extends Marker = Marker,21> extends React.SVGProps<SVGSVGElement> {22 width?: number23 height?: number24 mapSamples?: number25 markers?: M[]26 dotColor?: string27 markerColor?: string28 dotRadius?: number29 stagger?: boolean30 pulse?: boolean3132 renderMarkerOverlay?: (args: {33 marker: MapMarker<M>34 index: number35 x: number36 y: number37 r: number38 }) => React.ReactNode39}4041export function DottedMap<M extends Marker = Marker>({42 width = 150,43 height = 75,44 mapSamples = 5000,45 markers = [],46 dotColor = "currentColor",47 markerColor = "#FF6900",48 dotRadius = 0.2,49 stagger = true,50 pulse = false,51 renderMarkerOverlay,52 className,53 style,54 ...svgProps55}: DottedMapProps<M>) {56 const { points, addMarkers } = createMap({57 width,58 height,59 mapSamples,60 })61 const processedMarkers = addMarkers(markers)6263 // Compute stagger helpers in a single, simple pass64 const { xStep, yToRowIndex } = React.useMemo(() => {65 const sorted = [...points].sort((a, b) => a.y - b.y || a.x - b.x)66 const rowMap = new Map<number, number>()67 let step = 068 let prevY = Number.NaN69 let prevXInRow = Number.NaN7071 for (const p of sorted) {72 if (p.y !== prevY) {73 // new row74 prevY = p.y75 prevXInRow = Number.NaN76 if (!rowMap.has(p.y)) rowMap.set(p.y, rowMap.size)77 }78 if (!Number.isNaN(prevXInRow)) {79 const delta = p.x - prevXInRow80 if (delta > 0) step = step === 0 ? delta : Math.min(step, delta)81 }82 prevXInRow = p.x83 }8485 return { xStep: step || 1, yToRowIndex: rowMap }86 }, [points])8788 return (89 <svg90 viewBox={`0 0 ${width} ${height}`}91 className={cn("text-gray-500 dark:text-gray-500", className)}92 style={{ width: "100%", height: "100%", ...style }}93 {...svgProps}94 >95 {points.map((point, index) => {96 const rowIndex = yToRowIndex.get(point.y) ?? 097 const offsetX = stagger && rowIndex % 2 === 1 ? xStep / 2 : 098 return (99 <circle100 cx={point.x + offsetX}101 cy={point.y}102// … truncated
What it pulls in
npm packages
Files it writes
More from magicui
All 247 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Androidandroid | magicui | Components | Free | no deps | |
| Animated Beamanimated-beam | magicui | Components | Free | 1 dep | |
| Animated Circular Progress Baranimated-circular-progress-bar | magicui | Components | Free | no deps | |
| Animated Gradient Textanimated-gradient-text | magicui | Components | Free | no deps | |
| Animated Grid Patternanimated-grid-pattern | magicui | Components | Free | 1 dep | |
| Animated Listanimated-list | magicui | Components | Free | 1 dep | |
| Animated Shiny Textanimated-shiny-text | magicui | Components | Free | no deps | |
| Theme Toggleranimated-theme-toggler | magicui | Components | Free | 1 dep |
