import type { Marker, MarkerIcon } from '@edgepdf/types'; /** Options for focusing the map on a specific marker. */ export interface FocusMarkerOptions { /** Target zoom level after focusing. */ zoom?: number; /** Whether to animate the pan. */ animate?: boolean; /** Pixel offset from the left edge of the viewport. */ offsetLeft?: number; /** Pixel offset from the right edge of the viewport. */ offsetRight?: number; /** Pixel offset from the top edge of the viewport. */ offsetTop?: number; /** Pixel offset from the bottom edge of the viewport. */ offsetBottom?: number; } export interface UseMarkersReturn { /** Markers currently tracked by the viewer. */ markers: Marker[]; /** * Replace all markers in the viewer. * Updates both the local context and the web runtime. */ setMarkers: (markers: Marker[]) => void; /** * Add a single marker. * The marker object should follow the Marker shape from @edgepdf/types. * The web runtime confirms the creation via a MARKER_CREATED event which * then syncs back to context. */ addMarker: (marker: Marker) => void; /** * Remove a marker by its ID. * Removal is confirmed via a MARKER_DELETED event from the web runtime. */ removeMarker: (markerId: string) => void; /** * Update an existing marker with new data. * The update is confirmed via a MARKER_UPDATED event from the web runtime. */ updateMarker: (marker: Marker) => void; focusMarker: (markerId: string, options?: FocusMarkerOptions) => void; /** * Set the active/selected marker programmatically. * Draws a selection border overlay on the marker and clears any other selection. * Pass null to clear the active selection. */ setActiveMarker: (markerId: string | null) => void; /** * Dynamically enable or disable annotation (marker creation on map tap). * * Useful for single-pin flows — call `setAnnotationEnabled(false)` inside * `onMarkerAdd` to prevent additional pins after the first one: * * @example * ```tsx * const { setAnnotationEnabled } = useMarkers(); * * setAnnotationEnabled(false)} * /> * ``` */ setAnnotationEnabled: (enabled: boolean) => void; /** * Set the icon given to markers created by tapping the map. Pass `null` to * go back to the legacy PNG pin. * * Without this, a tap-created marker is always a PNG pin and the only way to * give it a dynamic icon is to catch `onMarkerAdd` and send an update back, * which renders the pin first and then swaps it. */ setDefaultMarkerIcon: (icon: MarkerIcon | null) => void; /** * Marker icon names the loaded viewer build can render. * * The icon set is frozen inside `viewer.html` at build time, so this is the * only way native code can know what is renderable. Empty until the map is * ready, and empty against a viewer build predating the feature — treat * empty as "unknown", not as "nothing is renderable". */ availableMarkerIcons: string[]; } /** * Hook to manage markers in the PDF viewer. * * Commands (`addMarker`, `removeMarker`, `updateMarker`, `setMarkers`) send messages into the * web runtime. The context `markers` array is updated when the web runtime * confirms changes via outbound bridge events. * * @example * ```tsx * function AnnotationBar() { * const { markers, addMarker, removeMarker, updateMarker } = useMarkers(); * * return ( * * {markers.map((m) => ( * removeMarker(m.id)} * onUpdate={(data) => updateMarker({ ...m, ...data })} * /> * ))} *