import { type GeoJsonFeature, type GeoJsonFeatureCollection, type GeoJsonPosition } from "@trackunit/geo-json-utils"; import type { CategoryKey, ControlConfig } from "../../controls/types"; import type { FitParticipation, ShapeInteractiveMode, ShapeLayerHandle, ShapeOverlapConfig, ShapeStyle, ShapesUnderCursorHit } from "../types"; import type { ShapeDecoration } from "./shapeDecorations"; import type { ShapeLabelResolutionContext } from "./shapeLabelResolution"; export type UseShapesOptions = Readonly<{ /** Unique ID for this layer */ id: string; /** Human-readable name */ name: string; /** GeoJSON FeatureCollection containing polygon, multipolygon, and/or line features */ features: GeoJsonFeatureCollection; /** Resolves the style for each shape. Called without context for the static pre-pass. */ resolveStyle: (feature: GeoJsonFeature, ctx?: ShapeLabelResolutionContext) => ShapeStyle; /** Which parts of the shape respond to interaction. Default: `"stroke"` */ interactive?: ShapeInteractiveMode; /** * Opt-in fill tiling for overlapping polygons (ADR-0021). When set to * `{ mode: "tile" }`, overlapping fills are clipped so every pixel is painted * by exactly one feature and ownership follows the cursor. Strokes stay full. * Orthogonal to `interactive` — neither implies the other. */ overlap?: ShapeOverlapConfig; /** * Controls to contribute to the map UI, keyed by semantic area. * Omit entirely (or omit a key) to contribute nothing to that area. */ controls?: Partial>>; /** * Produce custom decorations for each feature. Called per-feature during the * decoration rendering pass. These are merged with auto-generated decorations * (e.g. multi-geometry "+" badges) unless `skipAutoDecorations` is true. */ getDecorations?: (feature: GeoJsonFeature) => ReadonlyArray; /** When true, suppress all auto-generated decorations (e.g. multi-geometry "+" badges). Default: false */ skipAutoDecorations?: boolean; /** Whether the layer is currently loading its initial data. Omit for static (non-loading) layers. */ loading?: boolean; /** Controls whether this layer's bounds are included in fit-to-content operations. Default: `"all"` */ fitParticipation?: FitParticipation; /** * Called by `` after the pointer settle debounce fires and the * stroke hit-test completes for this layer. Receives the full hit list * (fill + stroke flags) sorted by feature id. Useful for custom * hover-promotion, tooltips, or analytics. * * Only fires for layers with `overlap: { mode: "tile" }`. */ onShapesUnderCursor?: (hits: ReadonlyArray, ctx: Readonly<{ position: GeoJsonPosition; }>) => void; }>; export type UseShapesReturn = ShapeLayerHandle; /** * `useShapes` -- creates a shape layer handle from a GeoJSON FeatureCollection. * * Input is GeoJSON. Polygons that cross the antimeridian as a single * seam-jumping ring (the form site APIs return) are split into RFC 7946 * MultiPolygon halves so fill tiling and hit-testing clip per hemisphere. * Adapters merge those halves back into one outline at render time. * * @example * ```tsx * const zones = useShapes({ * id: "zones", * name: "Zones", * features: zoneFeatureCollection, * resolveStyle: () => ({ fill: "rgba(0,0,255,0.1)", stroke: "blue", strokeWidth: 2 }), * interactive: "stroke", * }); * ``` */ export declare const useShapes: (options: UseShapesOptions) => UseShapesReturn;