import type { GeoJsonGeometry, GeoJsonPosition } from "@trackunit/geo-json-utils"; import type { MapApi } from "../../core/types"; import type { LayerHandle, ShapesUnderCursorHit } from "../types"; /** * Per-handle, per-feature clipped fill geometries (ADR-0021), keyed * `handleId → (featureId → geometry)`. Mirrors the style-overrides channel in * `useShapeDecorations`. */ export type FillGeometryOverrides = ReadonlyMap>; /** * Per-handle, per-feature z-index overrides for fill promotion (ADR-0021 Path B), * keyed `handleId → (featureId → zIndex)`. Higher value = visually on top. * Only features in an overlap group receive an entry. */ export type ZIndexOverrides = ReadonlyMap>; type UseShapeFillTilingConfig = Readonly<{ api: MapApi | undefined; handles: ReadonlyArray; onFillGeometriesChange: (overrides: FillGeometryOverrides) => void; onZIndexOverridesChange: (overrides: ZIndexOverrides) => void; /** * Called once per pointer-settle with the overall top hit (smallest area * across all handles/groups). Fires only when at least one candidate hit * exists and decoration hover is not active. */ onSettledHover?: (handleId: string, featureId: string) => void; /** * Currently selected feature id. Routed through the selection promotion * channel (Path B) — not the resting `computeFillTiling` baseline. */ selectedFeatureId?: string | null; /** Handle id of the selected shape entity (required when `selectedFeatureId` is set). */ selectedHandleId?: string | null; /** * Per-handle set of feature ids whose fill is suppressed (`fillOpacity === 0` * on the resolved context-aware style). Suppressed features are excluded from * tiling stack computation and return no fill hit during settle / queryAt. * Derived from `viewportStyleOverrides` in `` via `isFillSuppressed`. */ suppressedFillIdsByHandle?: ReadonlyMap>; }>; /** Return type of `useShapeFillTiling`. */ export type UseShapeFillTilingReturn = Readonly<{ /** * Imperative hit-test for a given handle and position. Uses the current * viewport snapshot captured by the last render. Returns an empty array * when the handle id is unknown or has no polygonal features. */ queryAt: (handleId: string, position: GeoJsonPosition) => ReadonlyArray; /** * Promote a feature to the front of its overlap group (sticky until the next * hover or selection). Used when the pointer is over a shape decoration * (e.g. edge label) that is not on the fill/stroke geometry — same * promotion channel as stroke/fill settle promotion. */ promoteFeature: (handleId: string, featureId: string) => void; /** * Symmetric counterpart to `promoteFeature`. Clears the promotion for * `featureId` in its overlap group only when it is the current group winner; * no-op otherwise. */ clearPromotion: (handleId: string, featureId: string) => void; /** * Suppress pointer-settle fill promotion while a shape decoration (edge label, * etc.) is hovered — the cursor may sit over another polygon's fill visually. */ setDecorationHoverActive: (active: boolean) => void; }>; /** * `useShapeFillTiling` — clips overlapping polygon fills for shape handles that * opted in via `overlap: { mode: "tile" }`, and promotes shapes on stroke-hover * settle (sticky, ~120ms debounce), decoration hover (edge labels, etc.), or when * a shape is selected (selection always forces front). Emits the result through * `onFillGeometriesChange` and `onZIndexOverridesChange`; `` merges them * into each shape handle's `featureFillGeometries` and `featureZIndexOverrides`. * * **Path B (ADR-0021):** `computeFillTiling` is promotion-unaware — it only runs on * viewport / feature-set / selection changes and produces stable resting fills and * resting z-indices. Hover promotion removes the resting clip for each group's * current sticky winner (so covered area can paint on top) and raises its z-index. * Non-winners in an active group are re-clipped against the winner's full outline * only (exclusive rings stay painted). Promotion clears when the pointer leaves * all sites on the handle. * * Resting tiling (viewport + feature set) is deferred while the map is moving * and coalesced on `idle` so pan/zoom does not run `computeFillTiling` every frame. * * @internal */ export declare const useShapeFillTiling: ({ api, handles, onFillGeometriesChange, onZIndexOverridesChange, onSettledHover, selectedFeatureId, selectedHandleId, suppressedFillIdsByHandle, }: UseShapeFillTilingConfig) => UseShapeFillTilingReturn; export {};