mrkeyoor.com_
Sat 08 Aug 21:01 UTC
npmUtilsupdated 08 Aug 2026

@visx/point

@visx/point is a dependency-free two-dimensional coordinate container from the visx visualization monorepo. It exports a mutable Point class with public numeric x and y fields, methods that copy those coordinates into an object or array, and two standalone helpers that add or subtract points. Despite the visx name, the package contains no React, SVG, DOM, scale, or chart code. It is a tiny shared data shape used around visualization calculations, not a vector-math or geometry library.

Verdict

Useful as a shared visx coordinate type, but too small to justify a new dependency in most standalone applications. If two public numbers and addition are not enough, skip past it to a real vector or geometry library.

API stability5/5The public surface is only Point, value, toArray, sumPoints, and subtractPoints, with releases stretching back to the visx 1.x line in 2020. The v4 migration material calls out packaging fixes for @visx/point rather than a coordinate API rewrite, and the current source remains direct x/y arithmetic. There is little room for accidental behavior change, though suite-wide major versions still require reviewing package metadata.
Docs2/5The package README gives a correct installation command and one compact example for construction, value(), and toArray(). It does not mention two of the three root exports, sumPoints and subtractPoints, nor public mutability, zero defaults, the required options object, lack of validation, or return allocation. The broader visx site is strong for charts, but developers evaluating this utility need to read its four short source files for the full contract.
Maintenance5/5Version 4.0.0 was published on June 11, 2026, the airbnb/visx repository was pushed on June 22, and the project is not archived. The monorepo has CI, migration notes, visual regression testing, and coordinated package releases. GitHub reports 146 open issues and pull requests across the entire visx suite, not this tiny package specifically, so that count reflects a large visualization project rather than Point defects.
Ecosystem4/5The package recorded 4,077,417 downloads for July 31 through August 6, 2026 and belongs to the 20,999-star visx monorepo, making its Point type familiar inside that visualization stack. ESM, CommonJS, TypeScript, and zero dependencies make it easy to consume. Outside visx, the ecosystem value falls quickly because ordinary coordinate objects interoperate more freely and established vector libraries offer far more operations.

Use it if

  • You already use visx packages and want the same Point value type expected by nearby visualization code
  • You need a minimal mutable x/y class plus object and array conversion without any runtime dependencies
  • You want named sumPoints and subtractPoints helpers that always return a new Point
  • You publish code for both ESM and CommonJS consumers and value the package's explicit exports, TypeScript declarations, and sideEffects false marker
Skip it if

Setup reality

Installation is the whole build setup: @visx/point 4.0.0 has no dependencies, peer dependencies, native code, styles, configuration, React import, or browser requirement. The wider visx v4 suite requires React 18 or 19, but this package's own manifest does not, and its source is ordinary arithmetic, so it can be used in Node or non-React browser code. It publishes an ESM build, a CommonJS build, TypeScript declarations, a root exports map, and sideEffects: false. Import Point, sumPoints, and subtractPoints from the package root rather than reaching into lib or esm internals. The main first-run surprise is constructor shape: you must pass an object. new Point({}) creates (0, 0), new Point({ x: 4 }) creates (4, 0), but new Point() throws because the argument itself has no default. TypeScript prevents that call when checked, yet plain JavaScript will encounter it at runtime. Coordinates have no units, coordinate-system direction, precision policy, or finite-number validation. Public x and y fields are mutable. value() returns a fresh { x, y } snapshot and toArray() returns a fresh two-element array, so mutating either returned value does not update the Point. sumPoints(a, b) and subtractPoints(a, b) also allocate new Point objects and leave inputs alone. Their TypeScript signatures require Point instances, though the JavaScript implementation only reads x and y. If this crosses an API boundary, validate Number.isFinite yourself. If you are not already using visx, consider whether a local Point type is clearer than explaining why a three-method coordinate class is a production dependency.

Patterns

Create a two-dimensional pointcreate-point

import { Point } from '@visx/point';

const point = new Point({ x: 24, y: 80 });
console.log(point.x, point.y);

Coordinates are public mutable numbers. The class does not validate finiteness, units, or coordinate-system direction.

Create the origin with an empty options objectcreate-origin

import { Point } from '@visx/point';

const origin = new Point({});
console.log(origin.value()); // { x: 0, y: 0 }

Pass the object. new Point() throws at runtime because the constructor destructures its argument before applying x and y defaults.

Default a missing coordinate to zerodefault-one-coordinate

const xOnly = new Point({ x: 12 });
const yOnly = new Point({ y: -4 });

console.log(xOnly.toArray()); // [12, 0]
console.log(yOnly.toArray()); // [0, -4]

Only omitted x or y receives zero. Explicit NaN, Infinity, null, or a runtime string is not cleaned or rejected.

Validate external coordinates before constructionvalidate-coordinates

function pointFromJson(input) {
  if (!input || !Number.isFinite(input.x) || !Number.isFinite(input.y)) {
    throw new TypeError('finite x and y required');
  }
  return new Point({ x: input.x, y: input.y });
}

TypeScript declarations help at compile time, but Point performs no runtime validation for parsed JSON or other untyped inputs.

Copy coordinates into a plain objectcopy-point-value

const point = new Point({ x: 3, y: 5 });
const snapshot = point.value();

snapshot.x = 99;
console.log(point.x); // 3

value() allocates a new object. Mutating that snapshot does not mutate the Point instance.

Convert coordinates to an arrayconvert-to-tuple

const point = new Point({ x: 3, y: 5 });
const [x, y] = point.toArray();
const svgTranslate = `translate(${x} ${y})`;

toArray() returns a number array, not a readonly fixed-length TypeScript tuple, and allocates a fresh array on every call.

Update a point in placemutate-point

const cursor = new Point({ x: 0, y: 0 });

cursor.x = pointerEvent.clientX;
cursor.y = pointerEvent.clientY;

The fields are intentionally writable. Avoid sharing a mutable Point where consumers assume coordinate values are stable.

Translate a point by an offsetadd-points

import { Point, sumPoints } from '@visx/point';

const position = new Point({ x: 40, y: 20 });
const margin = new Point({ x: 16, y: 12 });
const screenPosition = sumPoints(position, margin);

sumPoints returns a new Point and does not mutate either input.

Compute a drag deltasubtract-points

import { Point, subtractPoints } from '@visx/point';

const start = new Point({ x: 100, y: 80 });
const current = new Point({ x: 128, y: 65 });
const delta = subtractPoints(current, start);
console.log(delta.value()); // { x: 28, y: -15 }

Order matters: subtractPoints(a, b) computes a minus b for both coordinates.

Calculate a midpointfind-midpoint

import { Point, sumPoints } from '@visx/point';

function midpoint(a, b) {
  const total = sumPoints(a, b);
  return new Point({ x: total.x / 2, y: total.y / 2 });
}

Scaling and division are not built in. If manual vector operations spread across the codebase, use a fuller vector library.

Average a list of pointsfind-centroid

import { Point, sumPoints } from '@visx/point';

function centroid(points) {
  if (points.length === 0) return undefined;
  const total = points.reduce(
    (sum, point) => sumPoints(sum, point),
    new Point({}),
  );
  return new Point({ x: total.x / points.length, y: total.y / points.length });
}

Each sumPoints call allocates. For large arrays or animation loops, accumulate numeric x and y totals directly.

Serialize points for an SVG polylinebuild-svg-polyline

const points = [
  new Point({ x: 0, y: 10 }),
  new Point({ x: 20, y: 4 }),
  new Point({ x: 40, y: 18 }),
];

const attribute = points.map((point) => point.toArray().join(',')).join(' ');
// <polyline points={attribute} />

This package does not render SVG. It only supplies coordinates; React or DOM code owns the element, keys, scales, and clipping.

Alternatives

PackageRegistryPick it when
gl-matrixnpmChoose it for allocation-conscious vec2, vec3, matrices, quaternions, transforms, and numeric rendering work
victornpmChoose it for a fluent two-dimensional vector class with length, angle, normalize, rotate, dot, distance, and interpolation operations
@flatten-js/corenpmChoose it when points are only the start and you also need lines, circles, arcs, polygons, intersections, and spatial relations