Skip to content
This repository has been archived by the owner on Dec 20, 2024. It is now read-only.

chore(lint): use impargo eslint configs #27

Merged
merged 1 commit into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
extends: ['@impargo/eslint-config'],
plugins: ['react-hooks'],
rules: {
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
},
env: {
browser: true,
},
}
16 changes: 8 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- uses: actions/setup-node@v4
with:
node-version: 14
node-version: 20
- name: Cache
uses: actions/cache@v1.0.3
with:
Expand All @@ -24,9 +24,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- uses: actions/setup-node@v4
with:
node-version: 14
node-version: 20
- name: Restore cache
uses: actions/cache@v1.0.3
with:
Expand All @@ -40,9 +40,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- uses: actions/setup-node@v4
with:
node-version: 14
node-version: 20
- name: Restore cache
uses: actions/cache@v1.0.3
with:
Expand All @@ -55,9 +55,9 @@ jobs:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v2
# - uses: actions/setup-node@v1
# - uses: actions/setup-node@v4
# with:
# node-version: 14
# node-version: 20
# - name: Restore cache
# uses: actions/cache@v1.0.3
# with:
Expand Down
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"typescript.tsdk": "node_modules/typescript/lib"
}
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"coverage:post": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js",
"prepublishOnly": "gulp",
"transpile": "gulp transpile",
"lint": "tslint --config tslint.json --project tsconfig.json --type-check",
"lint": "eslint 'src/**/*.{js,ts,tsx}' 'test/**/*.{js,ts,tsx}' 'testbench/**/*.{js,ts,tsx}'",
"dev": "parcel testbench/index.html"
},
"repository": {
Expand Down Expand Up @@ -46,6 +46,7 @@
"homepage": "https://github.com/impargo/react-here-maps#readme",
"devDependencies": {
"@babel/core": "^7.12.0",
"@impargo/eslint-config": "^1.4.0",
"@types/chai": "^4.0.1",
"@types/enzyme": "^3.10.8",
"@types/heremaps": "^3.1.5",
Expand All @@ -67,6 +68,7 @@
"coveralls": "^2.11.12",
"css-loader": "^0.28.4",
"enzyme": "^3.11.0",
"eslint-plugin-react-hooks": "^4.6.0",
"gulp": "^4.0.2",
"gulp-sass": "^5.1.0",
"gulp-typescript": "^5.0.1",
Expand Down Expand Up @@ -105,8 +107,6 @@
"source-map-loader": "^0.2.1",
"style-loader": "^0.18.2",
"ts-loader": "^2.2.2",
"tslint": "^5.5.0",
"tslint-react": "^3.0.0",
"typescript": "^4.0.5",
"vinyl-source-stream": "^1.1.0",
"watchify": "^3.7.0"
Expand Down
99 changes: 50 additions & 49 deletions src/Cluster.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,48 @@
import { useCallback, useContext, useEffect, useMemo, useRef } from "react";
import { HEREMapContext } from "./context";
import getMarkerIcon from "./utils/get-marker-icon";
import { useCallback, useContext, useEffect, useMemo, useRef } from 'react'

import { HEREMapContext } from './context'
import getMarkerIcon from './utils/get-marker-icon'

export interface Datapoint<T> {
lat: number;
lon: number;
lat: number,
lon: number,
/**
* Any generic data that can be stored in the datapoint.
*/
data: T;
data: T,
}

export interface ClusterProps<T> {
/**
* The datapoints that should be clustered. They should contain coordinates, a bitmap, and any generic type of data.
* Note: a change in this array will force a reclustering of the entire cluster.
*/
points: Array<Datapoint<T>>;
points: Array<Datapoint<T>>,
/**
* Clustering options used by HERE maps clustering provider.
* Note: a change in these options will recreate the clustering provider.
*/
clusteringOptions?: H.clustering.Provider.ClusteringOptions;
clusteringOptions?: H.clustering.Provider.ClusteringOptions,
/**
* A function that should return the marker bitmap to be used for a specific set of cluster points.
* Note: a change in this function will trigger a redraw for all the datapoints in the cluster.
* So make sure to wrap it in a `useCallback` and only change its reference when necessary.
*/
getBitmapForCluster: (points: T[]) => string;
getBitmapForCluster: (points: T[]) => string,
/**
* A function that should return the marker bitmap for a single point.
* Note: a change in this function will trigger a redraw for all the datapoints in the cluster.
* So make sure to wrap it in a `useCallback` and only change its reference when necessary.
*/
getBitmapForPoint: (point: T) => string;
getBitmapForPoint: (point: T) => string,
/**
* A callback for when a cluster of points are clicked.
*/
onClusterClick: (data: T[], e: H.mapevents.Event) => void;
onClusterClick: (data: T[], e: H.mapevents.Event) => void,
/**
* A callback for when a single point in the cluster is clicked.
*/
onPointClick: (data: T, e: H.mapevents.Event) => void;
onPointClick: (data: T, e: H.mapevents.Event) => void,
}

export const defaultClusteringOptions: H.clustering.Provider.ClusteringOptions = {
Expand All @@ -53,98 +54,98 @@
* Minimum weight of points required to form a cluster (default weight for a cluster point is 1).
*/
minWeight: 2,
};
}

function createTheme<T>(
function createTheme<T> (
getBitmapForCluster: (points: T[]) => string,
getBitmapForPoint: (point: T) => string,
): H.clustering.ITheme {
return {
getClusterPresentation: (cluster) => {
const clusterPoints: T[] = [];
cluster.forEachDataPoint((point) => clusterPoints.push(point.getData()));
const clusterPoints: T[] = []
cluster.forEachDataPoint((point) => clusterPoints.push(point.getData()))
return new H.map.Marker(cluster.getPosition(), {
data: clusterPoints,
icon: getMarkerIcon(getBitmapForCluster(clusterPoints)),
max: cluster.getMaxZoom(),
min: cluster.getMinZoom(),
});
})
},
getNoisePresentation: (point) => {
const data: T = point.getData();
const data: T = point.getData()
return new H.map.Marker(point.getPosition(), {
data,
icon: getMarkerIcon(getBitmapForPoint(data)),
min: point.getMinZoom(),
});
})
},
};
}
}

function pointToDatapoint<T>(point: Datapoint<T>): H.clustering.DataPoint {
return new H.clustering.DataPoint(point.lat, point.lon, null, point.data);
function pointToDatapoint<T> (point: Datapoint<T>): H.clustering.DataPoint {
return new H.clustering.DataPoint(point.lat, point.lon, null, point.data)
}

/**
* A component that can automatically cluster a group of datapoints.
*/
export default function Cluster<T>({
export default function Cluster<T> ({
points,
clusteringOptions = defaultClusteringOptions,
getBitmapForCluster,
getBitmapForPoint,
onClusterClick,
onPointClick,
}: ClusterProps<T>): null {
const { map } = useContext(HEREMapContext);
const { map } = useContext(HEREMapContext)

const onClusterClickRef = useRef(onClusterClick);
onClusterClickRef.current = onClusterClick;
const onClusterClickRef = useRef(onClusterClick)
onClusterClickRef.current = onClusterClick

const onPointClickRef = useRef(onPointClick);
onPointClickRef.current = onPointClick;
const onPointClickRef = useRef(onPointClick)
onPointClickRef.current = onPointClick

const theme: H.clustering.ITheme = useMemo(() => createTheme(
getBitmapForCluster,
getBitmapForPoint,
), [getBitmapForCluster, getBitmapForPoint]);
), [getBitmapForCluster, getBitmapForPoint])

const datapoints = useMemo(() => points.map(pointToDatapoint), [points]);
const datapoints = useMemo(() => points.map(pointToDatapoint), [points])

const onClick = useCallback((evt: Event) => {
const e = evt as unknown as H.mapevents.Event;
const data: T | T[] = (e.target as H.map.Object).getData();
const e = evt as unknown as H.mapevents.Event
const data: T | T[] = (e.target as H.map.Object).getData()
if (Array.isArray(data)) {
onClusterClickRef.current(data, e);
onClusterClickRef.current(data, e)
} else {
onPointClickRef.current(data, e);
onPointClickRef.current(data, e)
}
}, []);
}, [])

const clusteredDataProvider = useMemo(() => {
const provider = new H.clustering.Provider(datapoints, {
clusteringOptions,
theme,
});
provider.addEventListener("tap", onClick);
return provider;
}, [clusteringOptions, onClick /* theme, datapoints */]);
})
provider.addEventListener('tap', onClick)
return provider
}, [clusteringOptions, onClick])

Check warning on line 132 in src/Cluster.tsx

View workflow job for this annotation

GitHub Actions / lint

React Hook useMemo has missing dependencies: 'datapoints' and 'theme'. Either include them or remove the dependency array

useEffect(() => {
clusteredDataProvider.setTheme(theme);
}, [theme, clusteredDataProvider]);
clusteredDataProvider.setTheme(theme)
}, [theme, clusteredDataProvider])

useEffect(() => {
clusteredDataProvider.setDataPoints(datapoints);
}, [datapoints, clusteredDataProvider]);
clusteredDataProvider.setDataPoints(datapoints)
}, [datapoints, clusteredDataProvider])

useEffect(() => {
const layer = new H.map.layer.ObjectLayer(clusteredDataProvider);
map?.addLayer(layer);
const layer = new H.map.layer.ObjectLayer(clusteredDataProvider)
map?.addLayer(layer)
return () => {
map?.removeLayer(layer);
};
}, [map, clusteredDataProvider]);
map?.removeLayer(layer)
}
}, [map, clusteredDataProvider])

return null;
return null
}
Loading
Loading