@visx/vendor
@visx/vendor is visx's compatibility layer for selected D3 modules and InternMap. Imports such as @visx/vendor/d3-scale resolve to the upstream ESM package, while CommonJS require calls resolve to fully transpiled vendored copies whose internal imports remain consistent. It also publishes matching root declaration files and pins exact runtime and @types versions. This is release infrastructure for visx and similar library-author situations, not a chart component, a unified D3 API, or a general recommendation to replace direct D3 dependencies.
Do not add @visx/vendor to a normal application just to reach D3 functions. It is a purposeful publishing shim for visx and dual ESM/CommonJS library work; direct D3 submodules are the simpler dependency everywhere else.
Use it if
- You are maintaining a visx package and need the exact vendored D3 versions used across the visx 4 monorepo
- You publish a library with both ESM and CommonJS consumers and need a transpiled CommonJS route for D3 modules that ship ESM
- Your existing visx integration already imports @visx/vendor subpaths and you need to understand or preserve that compatibility contract
- You need identical conditional import and require subpaths for the specific D3 modules this package exposes
- You are writing an application and can import D3 normally: the package README says this consists of vendored dependencies for other visx packages, so direct d3-array, d3-scale, or d3-shape dependencies are clearer
- You expect import statements from @visx/vendor itself: there is no root export, only ./d3-* and ./internmap subpaths, so a top-level import is intentionally unsupported
- You use only one D3 module: this package declares twelve runtime dependencies plus eleven @types packages at fixed versions, creating a much wider install footprint than one direct submodule
- You need D3 modules outside its list, such as d3-axis, d3-selection, d3-zoom, or d3-transition: the export map cannot resolve them and the package is not the full d3 bundle
- You plan to import vendor-cjs internals or generated files directly: those are implementation details; only documented @visx/vendor/d3-* and @visx/vendor/internmap subpaths have an export-map contract
Setup reality
There are no peer dependencies, native builds, credentials, or configuration files. The surprise is the package boundary: import @visx/vendor/d3-array or another documented subpath, never @visx/vendor. Under ESM, that subpath re-exports the unmodified installed upstream module. Under require(), it selects a transpiled CommonJS copy generated inside the package, including rewritten references to any other vendored dependencies. The export map covers d3-array, d3-color, d3-delaunay, d3-format, d3-geo, d3-interpolate, d3-path, d3-scale, d3-shape, d3-time, d3-time-format, and internmap. Root .js compatibility files exist for older tools that ignore package exports, but new code should use the extensionless documented subpath. Type declarations are copied from fixed @types packages, while runtime packages are also pinned to exact versions. That keeps visx builds reproducible but means upgrades follow the visx release line, not your application's preferred D3 cadence. Version 4 moved d3-shape and d3-path to v3 and targets modern browsers; CommonJS transpilation does not promise IE11 polyfills. The package is marked side-effect-free for bundling, but its installed dependency tree is still broad. If you are not solving dual-format library publishing or matching visx internals, install the individual upstream D3 module instead.
Patterns
Compute a numeric extentcompute-array-extent
import { extent } from '@visx/vendor/d3-array';
const [min, max] = extent(rows, (row) => row.value);The result can contain undefined for empty or non-numeric input; narrow or default both values before creating a scale.
Parse and darken a coloradjust-color
import { color } from '@visx/vendor/d3-color';
const parsed = color('#4f46e5');
const darker = parsed?.darker(0.8).formatHex() ?? '#000000';color() returns null for invalid input, so do not call methods without checking the parse result.
Find the nearest point with Delaunayfind-nearest-point
import { Delaunay } from '@visx/vendor/d3-delaunay';
const delaunay = Delaunay.from(
points,
(point) => point.x,
(point) => point.y,
);
const nearest = points[delaunay.find(pointerX, pointerY)];Build the triangulation in the same coordinate system as the pointer, usually screen-scaled x and y rather than raw data values.
Create a reusable number formatterformat-number
import { format } from '@visx/vendor/d3-format';
const dollars = format('$,.2f');
console.log(dollars(12345.6)); // $12,345.60The formatter uses D3's default locale; configure an explicit locale if separators and currency rules vary by audience.
Fit GeoJSON to an SVG viewportproject-geojson
import { geoMercator, geoPath } from '@visx/vendor/d3-geo';
const projection = geoMercator().fitSize([width, height], featureCollection);
const makePath = geoPath(projection);
const pathData = makePath(featureCollection);Mercator distorts area toward the poles; choose a projection that matches the geographic question rather than using this default blindly.
Interpolate between two colorsinterpolate-color
import { interpolateRgb } from '@visx/vendor/d3-interpolate';
const colorAt = interpolateRgb('#2563eb', '#dc2626');
const midpoint = colorAt(0.5);RGB interpolation is not perceptually uniform; use a color-space-specific interpolator when equal visual steps matter.
Construct SVG path data imperativelybuild-svg-path
import { path } from '@visx/vendor/d3-path';
const p = path();
p.moveTo(10, 10);
p.lineTo(90, 10);
p.lineTo(50, 70);
p.closePath();
const d = p.toString();path() stores commands in memory and returns SVG path text; it does not render or manage a DOM element.
Map data values to pixelscreate-linear-scale
import { scaleLinear } from '@visx/vendor/d3-scale';
const x = scaleLinear()
.domain([0, 100])
.range([0, 640])
.clamp(true);
const pixel = x(42);A scale performs numeric mapping only; axes and marks come from other D3 or visx packages.
Generate a smoothed line pathgenerate-line-path
import { line, curveMonotoneX } from '@visx/vendor/d3-shape';
const makeLine = line()
.x((point) => point.x)
.y((point) => point.y)
.curve(curveMonotoneX);
const d = makeLine(points);Sort points by x before curveMonotoneX; the generator can return null when no drawable points are present.
Generate calendar-day boundariesgenerate-day-range
import { timeDay } from '@visx/vendor/d3-time';
const days = timeDay.range(
new Date('2026-08-01T00:00:00'),
new Date('2026-08-08T00:00:00'),
);timeDay uses local calendar time and can cross daylight-saving changes; use utcDay when the domain is explicitly UTC.
Parse a date with a fixed formatparse-date-string
import { timeParse } from '@visx/vendor/d3-time-format';
const parseDate = timeParse('%Y-%m-%d');
const date = parseDate('2026-08-08');timeParse returns null when the text does not match and creates local-time Dates; utcParse avoids local-zone interpretation.
Treat equivalent Date objects as one map keyintern-date-keys
import { InternMap } from '@visx/vendor/internmap';
const labels = new InternMap();
labels.set(new Date('2026-08-08T00:00:00Z'), 'release');
const label = labels.get(new Date('2026-08-08T00:00:00Z'));
// 'release'InternMap uses each key's primitive value by default, so distinct Date objects for the same instant resolve together unlike a native Map.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| d3-array | npm | Install the specific upstream D3 submodule directly when your application only needs array statistics, grouping, bins, or ticks. |
| d3 | npm | Use the official aggregate package when a data-visualization application intentionally needs many D3 modules and uses ESM. |
| victory-vendor | npm | Use it only when working inside Victory's corresponding vendoring model rather than visx; it inspired this package but tracks Victory's needs. |