From a835b924932f8c21fe97248fc6e70edbecb67aaa Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Wed, 2 Oct 2019 09:04:14 -0700 Subject: [PATCH 01/11] typescript(vx-geo): add types deps, add types to package.json --- packages/vx-geo/package.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/vx-geo/package.json b/packages/vx-geo/package.json index 01f32c724..642c154ca 100644 --- a/packages/vx-geo/package.json +++ b/packages/vx-geo/package.json @@ -5,6 +5,7 @@ "sideEffects": false, "main": "lib/index.js", "module": "esm/index.js", + "types": "lib/index.d.ts", "files": [ "lib", "esm" @@ -31,6 +32,9 @@ }, "homepage": "https://github.com/hshoff/vx#readme", "dependencies": { + "@types/classnames": "^2.2.9", + "@types/d3-geo": "^1.11.1", + "@types/react": "*", "@vx/group": "0.0.192", "classnames": "^2.2.5", "d3-geo": "^1.11.3", From 37834c373ae728795ef84d336363231a744a20f3 Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Wed, 2 Oct 2019 09:05:59 -0700 Subject: [PATCH 02/11] typescript(vx-geo): rename files .js/.jsx => .ts/.tsx --- packages/vx-geo/src/graticule/{Graticule.jsx => Graticule.tsx} | 0 packages/vx-geo/src/{index.js => index.ts} | 0 packages/vx-geo/src/projections/{Albers.jsx => Albers.tsx} | 0 packages/vx-geo/src/projections/{AlbersUsa.jsx => AlbersUsa.tsx} | 0 .../projections/{CustomProjection.jsx => CustomProjection.tsx} | 0 .../vx-geo/src/projections/{EqualEarth.jsx => EqualEarth.tsx} | 0 packages/vx-geo/src/projections/{Mercator.jsx => Mercator.tsx} | 0 .../vx-geo/src/projections/{NaturalEarth.jsx => NaturalEarth.tsx} | 0 .../vx-geo/src/projections/{Orthographic.jsx => Orthographic.tsx} | 0 .../vx-geo/src/projections/{Projection.jsx => Projection.tsx} | 0 packages/vx-geo/test/{Albers.test.jsx => Albers.test.tsx} | 0 packages/vx-geo/test/{AlbersUsa.test.jsx => AlbersUsa.test.tsx} | 0 .../test/{CustomProjection.test.jsx => CustomProjection.test.tsx} | 0 packages/vx-geo/test/{EqualEarth.test.jsx => EqualEarth.test.tsx} | 0 packages/vx-geo/test/{Mercator.test.jsx => Mercator.test.tsx} | 0 .../vx-geo/test/{Orthographic.test.jsx => Orthographic.test.tsx} | 0 packages/vx-geo/test/{Projection.test.jsx => Projection.test.tsx} | 0 17 files changed, 0 insertions(+), 0 deletions(-) rename packages/vx-geo/src/graticule/{Graticule.jsx => Graticule.tsx} (100%) rename packages/vx-geo/src/{index.js => index.ts} (100%) rename packages/vx-geo/src/projections/{Albers.jsx => Albers.tsx} (100%) rename packages/vx-geo/src/projections/{AlbersUsa.jsx => AlbersUsa.tsx} (100%) rename packages/vx-geo/src/projections/{CustomProjection.jsx => CustomProjection.tsx} (100%) rename packages/vx-geo/src/projections/{EqualEarth.jsx => EqualEarth.tsx} (100%) rename packages/vx-geo/src/projections/{Mercator.jsx => Mercator.tsx} (100%) rename packages/vx-geo/src/projections/{NaturalEarth.jsx => NaturalEarth.tsx} (100%) rename packages/vx-geo/src/projections/{Orthographic.jsx => Orthographic.tsx} (100%) rename packages/vx-geo/src/projections/{Projection.jsx => Projection.tsx} (100%) rename packages/vx-geo/test/{Albers.test.jsx => Albers.test.tsx} (100%) rename packages/vx-geo/test/{AlbersUsa.test.jsx => AlbersUsa.test.tsx} (100%) rename packages/vx-geo/test/{CustomProjection.test.jsx => CustomProjection.test.tsx} (100%) rename packages/vx-geo/test/{EqualEarth.test.jsx => EqualEarth.test.tsx} (100%) rename packages/vx-geo/test/{Mercator.test.jsx => Mercator.test.tsx} (100%) rename packages/vx-geo/test/{Orthographic.test.jsx => Orthographic.test.tsx} (100%) rename packages/vx-geo/test/{Projection.test.jsx => Projection.test.tsx} (100%) diff --git a/packages/vx-geo/src/graticule/Graticule.jsx b/packages/vx-geo/src/graticule/Graticule.tsx similarity index 100% rename from packages/vx-geo/src/graticule/Graticule.jsx rename to packages/vx-geo/src/graticule/Graticule.tsx diff --git a/packages/vx-geo/src/index.js b/packages/vx-geo/src/index.ts similarity index 100% rename from packages/vx-geo/src/index.js rename to packages/vx-geo/src/index.ts diff --git a/packages/vx-geo/src/projections/Albers.jsx b/packages/vx-geo/src/projections/Albers.tsx similarity index 100% rename from packages/vx-geo/src/projections/Albers.jsx rename to packages/vx-geo/src/projections/Albers.tsx diff --git a/packages/vx-geo/src/projections/AlbersUsa.jsx b/packages/vx-geo/src/projections/AlbersUsa.tsx similarity index 100% rename from packages/vx-geo/src/projections/AlbersUsa.jsx rename to packages/vx-geo/src/projections/AlbersUsa.tsx diff --git a/packages/vx-geo/src/projections/CustomProjection.jsx b/packages/vx-geo/src/projections/CustomProjection.tsx similarity index 100% rename from packages/vx-geo/src/projections/CustomProjection.jsx rename to packages/vx-geo/src/projections/CustomProjection.tsx diff --git a/packages/vx-geo/src/projections/EqualEarth.jsx b/packages/vx-geo/src/projections/EqualEarth.tsx similarity index 100% rename from packages/vx-geo/src/projections/EqualEarth.jsx rename to packages/vx-geo/src/projections/EqualEarth.tsx diff --git a/packages/vx-geo/src/projections/Mercator.jsx b/packages/vx-geo/src/projections/Mercator.tsx similarity index 100% rename from packages/vx-geo/src/projections/Mercator.jsx rename to packages/vx-geo/src/projections/Mercator.tsx diff --git a/packages/vx-geo/src/projections/NaturalEarth.jsx b/packages/vx-geo/src/projections/NaturalEarth.tsx similarity index 100% rename from packages/vx-geo/src/projections/NaturalEarth.jsx rename to packages/vx-geo/src/projections/NaturalEarth.tsx diff --git a/packages/vx-geo/src/projections/Orthographic.jsx b/packages/vx-geo/src/projections/Orthographic.tsx similarity index 100% rename from packages/vx-geo/src/projections/Orthographic.jsx rename to packages/vx-geo/src/projections/Orthographic.tsx diff --git a/packages/vx-geo/src/projections/Projection.jsx b/packages/vx-geo/src/projections/Projection.tsx similarity index 100% rename from packages/vx-geo/src/projections/Projection.jsx rename to packages/vx-geo/src/projections/Projection.tsx diff --git a/packages/vx-geo/test/Albers.test.jsx b/packages/vx-geo/test/Albers.test.tsx similarity index 100% rename from packages/vx-geo/test/Albers.test.jsx rename to packages/vx-geo/test/Albers.test.tsx diff --git a/packages/vx-geo/test/AlbersUsa.test.jsx b/packages/vx-geo/test/AlbersUsa.test.tsx similarity index 100% rename from packages/vx-geo/test/AlbersUsa.test.jsx rename to packages/vx-geo/test/AlbersUsa.test.tsx diff --git a/packages/vx-geo/test/CustomProjection.test.jsx b/packages/vx-geo/test/CustomProjection.test.tsx similarity index 100% rename from packages/vx-geo/test/CustomProjection.test.jsx rename to packages/vx-geo/test/CustomProjection.test.tsx diff --git a/packages/vx-geo/test/EqualEarth.test.jsx b/packages/vx-geo/test/EqualEarth.test.tsx similarity index 100% rename from packages/vx-geo/test/EqualEarth.test.jsx rename to packages/vx-geo/test/EqualEarth.test.tsx diff --git a/packages/vx-geo/test/Mercator.test.jsx b/packages/vx-geo/test/Mercator.test.tsx similarity index 100% rename from packages/vx-geo/test/Mercator.test.jsx rename to packages/vx-geo/test/Mercator.test.tsx diff --git a/packages/vx-geo/test/Orthographic.test.jsx b/packages/vx-geo/test/Orthographic.test.tsx similarity index 100% rename from packages/vx-geo/test/Orthographic.test.jsx rename to packages/vx-geo/test/Orthographic.test.tsx diff --git a/packages/vx-geo/test/Projection.test.jsx b/packages/vx-geo/test/Projection.test.tsx similarity index 100% rename from packages/vx-geo/test/Projection.test.jsx rename to packages/vx-geo/test/Projection.test.tsx From cadcbb74c0d66ddff0749d36eb7a6a0bc3fd9e09 Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Wed, 2 Oct 2019 12:29:19 -0700 Subject: [PATCH 03/11] typescript(vx-geo): add @types/geojson, require react@^16.3.0 peerDep --- packages/vx-geo/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/vx-geo/package.json b/packages/vx-geo/package.json index 642c154ca..bbae63cc5 100644 --- a/packages/vx-geo/package.json +++ b/packages/vx-geo/package.json @@ -34,6 +34,7 @@ "dependencies": { "@types/classnames": "^2.2.9", "@types/d3-geo": "^1.11.1", + "@types/geojson": "*", "@types/react": "*", "@vx/group": "0.0.192", "classnames": "^2.2.5", @@ -44,7 +45,7 @@ "topojson-client": "^3.0.0" }, "peerDependencies": { - "react": "^15.0.0-0 || ^16.0.0-0" + "react": "^16.3.0-0" }, "publishConfig": { "access": "public" From 52d67d962a6ceb58d60c10615c962fee93c35965 Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Wed, 2 Oct 2019 12:29:40 -0700 Subject: [PATCH 04/11] typescript(vx-geo): re-write packages in TypeScript --- packages/vx-geo/src/graticule/Graticule.tsx | 54 +++++-- packages/vx-geo/src/projections/Albers.tsx | 6 +- packages/vx-geo/src/projections/AlbersUsa.tsx | 8 +- .../src/projections/CustomProjection.tsx | 8 +- .../vx-geo/src/projections/EqualEarth.tsx | 9 +- packages/vx-geo/src/projections/Mercator.tsx | 8 +- .../vx-geo/src/projections/NaturalEarth.tsx | 9 +- .../vx-geo/src/projections/Orthographic.tsx | 8 +- .../vx-geo/src/projections/Projection.tsx | 148 +++++++++++++----- 9 files changed, 184 insertions(+), 74 deletions(-) diff --git a/packages/vx-geo/src/graticule/Graticule.tsx b/packages/vx-geo/src/graticule/Graticule.tsx index 11f1c382a..2aa7626f0 100644 --- a/packages/vx-geo/src/graticule/Graticule.tsx +++ b/packages/vx-geo/src/graticule/Graticule.tsx @@ -1,20 +1,40 @@ import React from 'react'; -import PropTypes from 'prop-types'; import { Group } from '@vx/group'; -import { geoGraticule } from 'd3-geo'; +import { geoGraticule, GeoGraticuleGenerator } from 'd3-geo'; +import { LineString, MultiLineString, Polygon } from 'geojson'; -Graticule.propTypes = { - graticule: PropTypes.func, - lines: PropTypes.func, - outline: PropTypes.func, - children: PropTypes.func, - extent: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.number)), - extentMajor: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.number)), - extentMinor: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.number)), - step: PropTypes.arrayOf(PropTypes.number), - stepMajor: PropTypes.arrayOf(PropTypes.number), - stepMinor: PropTypes.arrayOf(PropTypes.number), - precision: PropTypes.number, +export type GraticuleProps = { + /** + * Render function for graticules which is passed a GeoJSON MultiLineString geometry object + * representing all meridians and parallels for the graticule. + */ + graticule?: (multiLineString: MultiLineString) => string; + /** + * Render function for graticule lines, which is invoked once for each meridian or parallel for the graticule, + * and is passed the GeoJSON LineString object representing said meridian or parallel. + */ + lines?: (lineString: LineString) => string; + /** + * Render function for the outline of the graticule (i.e. along the meridians and parallels defining its extent). + * It is passed a GeoJSON Polygon geometry object representing the outline. + */ + outline?: (polygon: Polygon) => string; + /** Override render function, which is passed the configured graticule generator. */ + children?: ({ graticule }: { graticule: GeoGraticuleGenerator }) => React.ReactNode; + /** Sets the major and minor extents of the graticule generator, which defaults to ⟨⟨-180°, -80° - ε⟩, ⟨180°, 80° + ε⟩⟩. */ + extent?: [[number, number], [number, number]]; + /** Sets the major extent of the graticule generator, which defaults to ⟨⟨-180°, -90° + ε⟩, ⟨180°, 90° - ε⟩⟩. */ + extentMajor?: [[number, number], [number, number]]; + /** Sets the major extent of the graticule generator, which defaults to ⟨⟨-180°, -80° - ε⟩, ⟨180°, 80° + ε⟩⟩. */ + extentMinor?: [[number, number], [number, number]]; + /** Sets both the major and minor step of the graticule generator. */ + step?: [number, number]; + /** Sets the major step of the graticule generator, which defaults to ⟨90°, 360°⟩. */ + stepMajor?: [number, number]; + /** Sets the major step of the graticule generator, which defaults to ⟨10°, 10°⟩. */ + stepMinor?: [number, number]; + /** Sets the precision of the graticule generator, which defaults to 2.5°. */ + precision?: number; }; export default function Graticule({ @@ -30,7 +50,7 @@ export default function Graticule({ precision, children, ...restProps -}) { +}: GraticuleProps & Omit, keyof GraticuleProps>) { const currGraticule = geoGraticule(); if (extent) currGraticule.extent(extent); @@ -39,9 +59,9 @@ export default function Graticule({ if (step) currGraticule.step(step); if (stepMajor) currGraticule.stepMajor(stepMajor); if (stepMinor) currGraticule.stepMinor(stepMinor); - if (precision) currGraticule.stepMinor(precision); + if (precision) currGraticule.precision(precision); - if (children) return children({ graticule: currGraticule }); + if (children) return <>{children({ graticule: currGraticule })}; return ( diff --git a/packages/vx-geo/src/projections/Albers.tsx b/packages/vx-geo/src/projections/Albers.tsx index 0b340d4d2..82f21ed9e 100644 --- a/packages/vx-geo/src/projections/Albers.tsx +++ b/packages/vx-geo/src/projections/Albers.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import Projection from './Projection'; +import Projection, { ProjectionProps, GeoPermissibleObjects } from './Projection'; /** * All props pass through to `` */ -export default function Albers(props) { - return ; +export default function Albers(props: ProjectionProps) { + return projection="albers" {...props} />; } diff --git a/packages/vx-geo/src/projections/AlbersUsa.tsx b/packages/vx-geo/src/projections/AlbersUsa.tsx index 4fbee6c7e..f2ecd4245 100644 --- a/packages/vx-geo/src/projections/AlbersUsa.tsx +++ b/packages/vx-geo/src/projections/AlbersUsa.tsx @@ -1,9 +1,11 @@ import React from 'react'; -import Projection from './Projection'; +import Projection, { ProjectionProps, GeoPermissibleObjects } from './Projection'; /** * All props pass through to `` */ -export default function AlbersUsa(props) { - return ; +export default function AlbersUsa( + props: ProjectionProps, +) { + return projection="albersUsa" {...props} />; } diff --git a/packages/vx-geo/src/projections/CustomProjection.tsx b/packages/vx-geo/src/projections/CustomProjection.tsx index 7c5bca637..ca6b6e283 100644 --- a/packages/vx-geo/src/projections/CustomProjection.tsx +++ b/packages/vx-geo/src/projections/CustomProjection.tsx @@ -1,9 +1,11 @@ import React from 'react'; -import Projection from './Projection'; +import Projection, { ProjectionProps, GeoPermissibleObjects } from './Projection'; /** * All props pass through to `` */ -export default function CustomProjection(props) { - return ; +export default function CustomProjection( + props: ProjectionProps, +) { + return {...props} />; } diff --git a/packages/vx-geo/src/projections/EqualEarth.tsx b/packages/vx-geo/src/projections/EqualEarth.tsx index 34bd50c39..6ca1f9d5c 100644 --- a/packages/vx-geo/src/projections/EqualEarth.tsx +++ b/packages/vx-geo/src/projections/EqualEarth.tsx @@ -1,9 +1,12 @@ import React from 'react'; -import Projection from './Projection'; +import Projection, { ProjectionProps, GeoPermissibleObjects } from './Projection'; /** * All props pass through to `` */ -export default function EqualEarth(props) { - return ; +// @ts-ignore ts-migrate(2304) FIXME: Cannot find name '$TSFixMe'. +export default function EqualEarth( + props: ProjectionProps, +) { + return projection="equalEarth" {...props} />; } diff --git a/packages/vx-geo/src/projections/Mercator.tsx b/packages/vx-geo/src/projections/Mercator.tsx index b513476da..333e0b8c6 100644 --- a/packages/vx-geo/src/projections/Mercator.tsx +++ b/packages/vx-geo/src/projections/Mercator.tsx @@ -1,9 +1,11 @@ import React from 'react'; -import Projection from './Projection'; +import Projection, { ProjectionProps, GeoPermissibleObjects } from './Projection'; /** * All props pass through to `` */ -export default function Mercator(props) { - return ; +export default function Mercator( + props: ProjectionProps, +) { + return projection="mercator" {...props} />; } diff --git a/packages/vx-geo/src/projections/NaturalEarth.tsx b/packages/vx-geo/src/projections/NaturalEarth.tsx index 9069f69f6..e788a4284 100644 --- a/packages/vx-geo/src/projections/NaturalEarth.tsx +++ b/packages/vx-geo/src/projections/NaturalEarth.tsx @@ -1,9 +1,12 @@ import React from 'react'; -import Projection from './Projection'; +import Projection, { ProjectionProps, GeoPermissibleObjects } from './Projection'; /** * All props pass through to `` */ -export default function NaturalEarth(props) { - return ; +// @ts-ignore ts-migrate(2304) FIXME: Cannot find name '$TSFixMe'. +export default function NaturalEarth( + props: ProjectionProps, +) { + return projection="naturalEarth" {...props} />; } diff --git a/packages/vx-geo/src/projections/Orthographic.tsx b/packages/vx-geo/src/projections/Orthographic.tsx index 0edbc8e92..f0185f6bf 100644 --- a/packages/vx-geo/src/projections/Orthographic.tsx +++ b/packages/vx-geo/src/projections/Orthographic.tsx @@ -1,9 +1,11 @@ import React from 'react'; -import Projection from './Projection'; +import Projection, { ProjectionProps, GeoPermissibleObjects } from './Projection'; /** * All props pass through to `` */ -export default function Orthographic(props) { - return ; +export default function Orthographic( + props: ProjectionProps, +) { + return projection="orthographic" {...props} />; } diff --git a/packages/vx-geo/src/projections/Projection.tsx b/packages/vx-geo/src/projections/Projection.tsx index 10de034e7..f7892bb93 100644 --- a/packages/vx-geo/src/projections/Projection.tsx +++ b/packages/vx-geo/src/projections/Projection.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import PropTypes from 'prop-types'; import cx from 'classnames'; import { Group } from '@vx/group'; import { @@ -10,11 +9,25 @@ import { geoNaturalEarth1, geoEqualEarth, geoPath, + GeoPath, + GeoProjection, + GeoPermissibleObjects, } from 'd3-geo'; -import Graticule from '../graticule/Graticule'; +import Graticule, { GraticuleProps } from '../graticule/Graticule'; +import { LineString, Polygon, MultiLineString } from 'geojson'; + +export type GeoPermissibleObjects = GeoPermissibleObjects; // TODO: Implement all projections of d3-geo -const projectionMapping = { +type ProjectionPreset = + | 'orthographic' + | 'albers' + | 'albersUsa' + | 'mercator' + | 'naturalEarth' + | 'equalEarth'; + +const projectionMapping: { [projection in ProjectionPreset]: () => GeoProjection } = { orthographic: () => geoOrthographic(), albers: () => geoAlbers(), albersUsa: () => geoAlbersUsa(), @@ -23,33 +36,88 @@ const projectionMapping = { equalEarth: () => geoEqualEarth(), }; -Projection.propTypes = { - data: PropTypes.array.isRequired, - projection: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), - projectionFunc: PropTypes.func, - clipAngle: PropTypes.number, - clipExtent: PropTypes.array, - scale: PropTypes.number, - translate: PropTypes.array, - center: PropTypes.array, - rotate: PropTypes.array, - precision: PropTypes.number, - fitExtent: PropTypes.array, - fitSize: PropTypes.array, - centroid: PropTypes.func, - className: PropTypes.string, - children: PropTypes.func, - innerRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), - graticule: PropTypes.object, - graticuleLines: PropTypes.object, - graticuleOutline: PropTypes.object, - pointRadius: PropTypes.number, +type Projection = ProjectionPreset | (() => GeoProjection); + +export type ProjectionProps = { + /** Array of features to project. */ + data: Datum[]; + /** Preset projection name, or custom projection function which returns a GeoProjection. */ + projection?: Projection; + /** Hook to render above features, passed the configured projectionFunc. */ + projectionFunc?: (projection: GeoProjection) => React.ReactNode; + /** Sets the projection’s clipping circle radius to the specified angle in degree. */ + clipAngle?: number; + /** + * Sets the projection’s viewport clip extent to the specified bounds in pixels. extent bounds + * are specified as an array [[x₀, y₀], [x₁, y₁]], where x₀ is the left-side of the viewport, + * y₀ is the top, x₁ is the right and y₁ is the bottom. + */ + clipExtent?: [[number, number], [number, number]]; + /** + * Sets the projection’s scale factor to the specified value. The scale factor corresponds linearly + * to the distance between projected points; however, absolute scale factors are not equivalent + * across projections. + */ + scale?: number; + /** + * Sets the projection’s translation offset, which determines the pixel coordinates of the + * projection’s center, to the specified two-element array [tx, ty]. + */ + translate?: [number, number]; + /** Sets the projection’s center to the specified two-element array of longitude and latitude in degrees. */ + center?: [number, number]; + /** Sets the projection’s three-axis spherical rotation to the specified angles [lambda, phi [, gamma]], corresponding to yaw, pitch, and roll. */ + rotate?: [number, number] | [number, number, number]; + /** Sets the threshold for the projection’s adaptive resampling to the specified value in pixels. */ + precision?: number; + /** + * Sets the projection’s scale and translate to fit the specified GeoJSON object in the center of the given extent. + * The extent is specified as an array [[x₀, y₀], [x₁, y₁]], where x₀ is the left side of the bounding box, + * y₀ is the top, x₁ is the right and y₁ is the bottom. + */ + fitExtent?: [ + [[number, number], [number, number]], + any, // ExtendedFeature | ExtendedFeatureCollection | GeoGeometryObjects, + ]; + /** Convenience prop for props.fitExtent where the top-left corner of the extent is [0, 0]. */ + fitSize?: [ + [number, number], + any, // ExtendedFeature | ExtendedFeatureCollection | GeoGeometryObjects + ]; + /** Hook to render anything at the centroid of a feature. */ + centroid?: (centroid: [number, number], feature: ParsedFeature) => React.ReactNode; + /** className to apply to feature path elements. */ + className?: string; + /** Override render function which is passed the */ + children?: (args: { + path: GeoPath; + features: ParsedFeature[]; + }) => React.ReactNode; + /** Function invoked for each feature which returns a React.Ref to the projection path element for that feature. */ + innerRef?: (feature: ParsedFeature, index: number) => React.Ref; + /** If specified, renders a Graticule with the specified props. Specify `graticule.foreground = true` to be rendered on top of features. */ + graticule?: Omit & { foreground: boolean }; + /** If specified, renders a Graticule lines with the specified props. Specify `graticuleLines.foreground = true` to be rendered on top of features. */ + graticuleLines?: Omit & { foreground: boolean }; + /** If specified, renders a Graticule outline with the specified props. Specify `graticuleOutline.foreground = true` to be rendered on top of features. */ + graticuleOutline?: Omit & { foreground: boolean }; + /** Sets the radius used to display Point and MultiPoint geometries to the specified number. */ + pointRadius?: number; }; +export interface ParsedFeature { + feature: Datum; + type: Projection; + projection: GeoProjection; + index: number; + centroid: [number, number]; + path: string | null; +} + /** * Component for all projections. */ -export default function Projection({ +export default function Projection({ data, projection = 'mercator', projectionFunc, @@ -71,8 +139,10 @@ export default function Projection({ pointRadius, children, ...restProps -}) { - const maybeCustomProjection = projectionMapping[projection] || projection; +}: ProjectionProps & Omit, keyof ProjectionProps>) { + const maybeCustomProjection = + typeof projection === 'string' ? projectionMapping[projection] : projection; + const currProjection = maybeCustomProjection(); if (clipAngle) currProjection.clipAngle(clipAngle); @@ -81,7 +151,7 @@ export default function Projection({ if (translate) currProjection.translate(translate); if (center) currProjection.center(center); if (rotate) currProjection.rotate(rotate); - if (precision) currProjection.rotate(precision); + if (precision) currProjection.precision(precision); if (fitExtent) currProjection.fitExtent(...fitExtent); if (fitSize) currProjection.fitSize(...fitSize); @@ -89,7 +159,7 @@ export default function Projection({ if (pointRadius) path.pointRadius(pointRadius); - const features = data.map((feature, i) => { + const features: ParsedFeature[] = data.map((feature, i) => { return { feature, type: projection, @@ -100,16 +170,18 @@ export default function Projection({ }; }); - if (children) return children({ path, features }); + if (children) return <>{children({ path, features })}; return ( - {graticule && !graticule.foreground && path(g)} {...graticule} />} + {graticule && !graticule.foreground && ( + path(ml) || ''} {...graticule} /> + )} {graticuleLines && !graticuleLines.foreground && ( - path(g)} {...graticuleLines} /> + path(l) || ''} {...graticuleLines} /> )} {graticuleOutline && !graticuleOutline.foreground && ( - path(g)} {...graticuleOutline} /> + path(p) || ''} {...graticuleOutline} /> )} {features.map((feature, i) => { @@ -125,15 +197,19 @@ export default function Projection({ ); })} + {/* TODO: Maybe find a different way to pass projection function to use for example invert */} {projectionFunc && projectionFunc(currProjection)} - {graticule && graticule.foreground && path(g)} {...graticule} />} + {graticule && graticule.foreground && ( + path(ml) || ''} {...graticule} /> + )} + {graticuleLines && graticuleLines.foreground && ( - path(g)} {...graticuleLines} /> + path(l) || ''} {...graticuleLines} /> )} {graticuleOutline && graticuleOutline.foreground && ( - path(g)} {...graticuleOutline} /> + path(p) || ''} {...graticuleOutline} /> )} ); From 4e7e14ef01a2560cea9c275b802d55a7388dcbb4 Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Wed, 2 Oct 2019 12:33:46 -0700 Subject: [PATCH 05/11] typescript(vx-geo): fix type in Projection --- packages/vx-geo/src/projections/Projection.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vx-geo/src/projections/Projection.tsx b/packages/vx-geo/src/projections/Projection.tsx index f7892bb93..2b690a8e7 100644 --- a/packages/vx-geo/src/projections/Projection.tsx +++ b/packages/vx-geo/src/projections/Projection.tsx @@ -189,7 +189,7 @@ export default function Projection({ From d303f66a5819326c45c6ad45418b6bbeeed82092 Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Wed, 2 Oct 2019 12:37:33 -0700 Subject: [PATCH 06/11] typescript(vx-geo): annotate types in tests --- packages/vx-geo/test/Projection.test.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/vx-geo/test/Projection.test.tsx b/packages/vx-geo/test/Projection.test.tsx index 46eba2b3f..a28fe7edc 100644 --- a/packages/vx-geo/test/Projection.test.tsx +++ b/packages/vx-geo/test/Projection.test.tsx @@ -1,13 +1,14 @@ import React from 'react'; import { shallow } from 'enzyme'; import { feature } from 'topojson-client'; +import { GeometryCollection } from 'geojson'; import Projection from '../src/projections/Projection'; import topology from './topo.json'; describe('', () => { // TopoJSON with two polygons - const data = feature(topology, topology.objects.collection).features; + const data: GeometryCollection[] = feature(topology, topology.objects.collection).features; const props = { data }; test('it should be defined', () => { From c7121a151613abaca3b9b5c120e7adef91ceadec Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Fri, 4 Oct 2019 13:21:48 -0700 Subject: [PATCH 07/11] typescript(vx-geo): add @types/topojson-client dev dep --- packages/vx-geo/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/vx-geo/package.json b/packages/vx-geo/package.json index bbae63cc5..10d079ce6 100644 --- a/packages/vx-geo/package.json +++ b/packages/vx-geo/package.json @@ -42,6 +42,7 @@ "prop-types": "^15.5.10" }, "devDependencies": { + "@types/topojson-client": "^3.0.0", "topojson-client": "^3.0.0" }, "peerDependencies": { From f51e7bd9ed60d132c2314792e4e409a1627f70a5 Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Wed, 9 Oct 2019 13:19:04 -0700 Subject: [PATCH 08/11] typescript(vx-geo): remove @ts-ignores --- packages/vx-geo/src/projections/EqualEarth.tsx | 1 - packages/vx-geo/src/projections/NaturalEarth.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/vx-geo/src/projections/EqualEarth.tsx b/packages/vx-geo/src/projections/EqualEarth.tsx index 6ca1f9d5c..9feabac32 100644 --- a/packages/vx-geo/src/projections/EqualEarth.tsx +++ b/packages/vx-geo/src/projections/EqualEarth.tsx @@ -4,7 +4,6 @@ import Projection, { ProjectionProps, GeoPermissibleObjects } from './Projection /** * All props pass through to `` */ -// @ts-ignore ts-migrate(2304) FIXME: Cannot find name '$TSFixMe'. export default function EqualEarth( props: ProjectionProps, ) { diff --git a/packages/vx-geo/src/projections/NaturalEarth.tsx b/packages/vx-geo/src/projections/NaturalEarth.tsx index e788a4284..3ece06e11 100644 --- a/packages/vx-geo/src/projections/NaturalEarth.tsx +++ b/packages/vx-geo/src/projections/NaturalEarth.tsx @@ -4,7 +4,6 @@ import Projection, { ProjectionProps, GeoPermissibleObjects } from './Projection /** * All props pass through to `` */ -// @ts-ignore ts-migrate(2304) FIXME: Cannot find name '$TSFixMe'. export default function NaturalEarth( props: ProjectionProps, ) { From 5723ef4ed7d5155e97036e7fa978b6c34441143e Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Wed, 9 Oct 2019 13:54:33 -0700 Subject: [PATCH 09/11] typescript(vx-geo): fix types in test/Projection --- packages/vx-geo/test/Projection.test.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/vx-geo/test/Projection.test.tsx b/packages/vx-geo/test/Projection.test.tsx index a28fe7edc..27bc7fa74 100644 --- a/packages/vx-geo/test/Projection.test.tsx +++ b/packages/vx-geo/test/Projection.test.tsx @@ -4,10 +4,12 @@ import { feature } from 'topojson-client'; import { GeometryCollection } from 'geojson'; import Projection from '../src/projections/Projection'; +// @ts-ignore import topology from './topo.json'; describe('', () => { // TopoJSON with two polygons + // @ts-ignore @TODO get this to method overload properly const data: GeometryCollection[] = feature(topology, topology.objects.collection).features; const props = { data }; From c4ba7d411f2387222ffcefd699964809426260b0 Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Wed, 9 Oct 2019 14:58:35 -0700 Subject: [PATCH 10/11] lint(vx-geo): disable import/no-unresolved for @types/geojson --- packages/vx-geo/src/projections/Projection.tsx | 4 +++- packages/vx-geo/test/Projection.test.tsx | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/vx-geo/src/projections/Projection.tsx b/packages/vx-geo/src/projections/Projection.tsx index 2b690a8e7..316f1a445 100644 --- a/packages/vx-geo/src/projections/Projection.tsx +++ b/packages/vx-geo/src/projections/Projection.tsx @@ -13,9 +13,11 @@ import { GeoProjection, GeoPermissibleObjects, } from 'd3-geo'; -import Graticule, { GraticuleProps } from '../graticule/Graticule'; +// eslint-disable-next-line import/no-unresolved import { LineString, Polygon, MultiLineString } from 'geojson'; +import Graticule, { GraticuleProps } from '../graticule/Graticule'; + export type GeoPermissibleObjects = GeoPermissibleObjects; // TODO: Implement all projections of d3-geo diff --git a/packages/vx-geo/test/Projection.test.tsx b/packages/vx-geo/test/Projection.test.tsx index 27bc7fa74..28a8ff8a3 100644 --- a/packages/vx-geo/test/Projection.test.tsx +++ b/packages/vx-geo/test/Projection.test.tsx @@ -1,10 +1,11 @@ import React from 'react'; import { shallow } from 'enzyme'; import { feature } from 'topojson-client'; +// eslint-disable-next-line import/no-unresolved import { GeometryCollection } from 'geojson'; import Projection from '../src/projections/Projection'; -// @ts-ignore +// @ts-ignore doesn't like .json import topology from './topo.json'; describe('', () => { From 575f6660bc97d55e6600f798366d4c5c503a9c43 Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Wed, 9 Oct 2019 15:09:07 -0700 Subject: [PATCH 11/11] lint(vx-geo): disable import/no-unresolved for @types/geojson again --- packages/vx-geo/src/graticule/Graticule.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/vx-geo/src/graticule/Graticule.tsx b/packages/vx-geo/src/graticule/Graticule.tsx index 2aa7626f0..24fe746c7 100644 --- a/packages/vx-geo/src/graticule/Graticule.tsx +++ b/packages/vx-geo/src/graticule/Graticule.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { Group } from '@vx/group'; import { geoGraticule, GeoGraticuleGenerator } from 'd3-geo'; +// eslint-disable-next-line import/no-unresolved import { LineString, MultiLineString, Polygon } from 'geojson'; export type GraticuleProps = {