react-map-gl-supercluster
Version:
> The easiest way to get `react-map-gl` and `supercluster` to work together
138 lines • 5.43 kB
TypeScript
import Supercluster, { ClusterFeature, PointFeature } from "supercluster";
//#region src/types.d.ts
/** Plain GeoJSON properties object used by points and clusters. */
type GeoJsonProperties = Record<string, unknown>;
/**
* Point properties accepted by `useSupercluster`.
*
* The `cluster` key is reserved: generated clusters use it as a discriminator,
* so input points must not define it. Use `isCluster` to tell features apart.
*
* @example
* ```ts
* type CityPoint = { name: string; population: number } // satisfies PointFeatureProperties
* ```
*/
type PointFeatureProperties = GeoJsonProperties & {
cluster?: never;
};
/** A feature returned from `useSupercluster`: either an original point or a generated cluster. */
type Cluster<TFeatureProperties extends GeoJsonProperties, TClusterProperties extends GeoJsonProperties> = PointFeature<TFeatureProperties> | ClusterFeature<TClusterProperties>;
/**
* Loaded `supercluster` instance returned by the hook.
*
* Use it for advanced reads such as leaves, children, and expansion zoom.
*
* @example
* ```ts
* const zoom = supercluster.getClusterExpansionZoom(clusterId)
* ```
*/
type SuperclusterInstance<TFeatureProperties extends GeoJsonProperties, TClusterProperties extends GeoJsonProperties> = Omit<Supercluster<TFeatureProperties, TClusterProperties>, 'load'>;
/**
* Maps point properties to the aggregate properties used by clusters.
*
* Mirrors `supercluster`'s `map` option.
*
* @example
* ```ts
* type City = { name: string; population: number }
* type CityCluster = { population: number }
*
* const map: MapFeatureToCluster<City, CityCluster> = (point) => ({
* population: point.population,
* })
* ```
*/
type MapFeatureToCluster<TFeatureProperties extends GeoJsonProperties, TClusterProperties extends GeoJsonProperties> = (feature: TFeatureProperties) => TClusterProperties;
/**
* Merges aggregate properties while building clusters.
*
* Mirrors `supercluster`'s `reduce` option.
*
* @example
* ```ts
* const reduce: ReduceCluster<CityCluster> = (memo, point) => {
* memo.population += point.population
* }
* ```
*/
type ReduceCluster<TClusterProperties extends GeoJsonProperties> = (memo: TClusterProperties, feature: Readonly<TClusterProperties>) => void;
/**
* Options passed to the underlying `supercluster` index.
*
* Function options should be stable between renders.
*
* @example
* ```ts
* const options = {
* radius: 60,
* maxZoom: 18,
* map,
* reduce,
* }
* ```
*/
type SuperclusterOptions<TFeatureProperties extends GeoJsonProperties, TClusterProperties extends GeoJsonProperties> = {
minZoom?: number | undefined;
maxZoom?: number | undefined;
radius?: number | undefined;
minPoints?: number | undefined;
extent?: number | undefined;
nodeSize?: number | undefined;
generateId?: boolean | undefined;
map?: MapFeatureToCluster<TFeatureProperties, TClusterProperties> | undefined;
reduce?: ReduceCluster<TClusterProperties> | undefined;
};
type LngLatBounds = {
toArray(): number[][];
};
type MapEventListener = (...args: unknown[]) => void;
/** Minimal structural contract satisfied by every `react-map-gl` `MapRef` flavor. */
type MapLike = {
getBounds(): LngLatBounds | null;
getZoom(): number;
on(type: string, listener: MapEventListener): void;
off(type: string, listener?: MapEventListener): void;
};
//#endregion
//#region src/use-supercluster.d.ts
/** Values returned by `useSupercluster`. */
type UseSuperclusterReturnValue<TFeatureProperties extends GeoJsonProperties, TClusterProperties extends GeoJsonProperties> = {
/** Clusters for the current — optionally padded — map bounds and rounded zoom. */
clusters: Array<Cluster<TFeatureProperties, TClusterProperties>>;
/** Loaded index for advanced `supercluster` queries. */
supercluster: SuperclusterInstance<TFeatureProperties, TClusterProperties>;
};
/**
* Hook options.
*
* Pass `mapRef` when the map is outside `react-map-gl` context or when several maps are mounted.
*/
type UseSuperclusterOptions<MapRef extends MapLike, TFeatureProperties extends GeoJsonProperties, TClusterProperties extends GeoJsonProperties> = SuperclusterOptions<TFeatureProperties, TClusterProperties> & {
mapRef?: MapRef | undefined | null;
/**
* Extra viewport fraction (per side) included when querying clusters.
*
* Markers near the edges don't pop in and out, and pans inside the padded
* area at the same rounded zoom skip recomputation entirely. The queried
* area grows as `(1 + 2 * padding)²`, so large values render more
* off-screen markers. Non-positive values disable padding.
*
* @default 0
*/
boundsPadding?: number | undefined;
};
//#endregion
//#region src/is-cluster.d.ts
/**
* Narrows a feature returned from `useSupercluster` to a generated cluster.
*
* @example
* ```tsx
* clusters.map((feature) => (isCluster(feature) ? renderCluster(feature) : renderPoint(feature)))
* ```
*/
declare function isCluster<TFeatureProperties extends PointFeatureProperties, TClusterProperties extends GeoJsonProperties>(feature: Cluster<TFeatureProperties, TClusterProperties>): feature is ClusterFeature<TClusterProperties>;
//#endregion
export { ClusterFeature as a, PointFeatureProperties as c, Cluster as i, SuperclusterInstance as l, UseSuperclusterOptions as n, GeoJsonProperties as o, UseSuperclusterReturnValue as r, PointFeature as s, isCluster as t };