import { EventEmitter } from '../../stencil-public-runtime'; import type { LngLatBoundsLike } from 'maplibre-gl'; import { type PreviewError } from '../../lib/errors'; import LocationPreviewer from '../../lib/previewers/location'; import type OgmRecord from '../../lib/record'; /** * Where several records are: one numbered marker apiece, and optionally a way to search the map for * more of them. * * Nothing of a record is drawn but its number. A page of boxes says less than a page of numbers a * reader can find again in the list beside the map, and the only two boxes worth drawing are the ones * that answer a question: which area is being searched, and where the one result something outside has * pointed at actually is. For a single record on a map of its own, see . */ export declare class OgmOverview { el: HTMLElement; theme: 'light' | 'dark'; darkBasemap?: string; lightBasemap?: string; records?: OgmRecord[]; previewers?: (LocationPreviewer | undefined)[]; /** * Which result to bring forward, as either its place in the list counted from one or the id of the * record - or of the resource a previewer draws - that it came from. An attribute hands over a * string for either, since an attribute is always one. * * The marker changes color and comes to the front, and the result's own extent is drawn around it. * The camera doesn't move: something on the page has said which result matters, not where to look. * * A reader's pointer over a number does the same thing without being asked, so both can be true at * once - of two different results, if a page names one while the pointer is over another. Each is a * way of saying the same thing about a row, so each gets the same drawing; see draw. */ highlighted?: number | string; /** * Whether a reader can search the map by holding shift and dragging a box over it. The area they * drew is reported through `boundsChange`; nothing here answers it, because what a new area means * is the embedding page's to say. The help text is a prop because GeoBlacklight runs the strings * for the control this replaces through Rails I18n. */ geosearch: boolean; searchHelpText: string; /** * The area a search is currently filtered to, drawn as a box and framed by the camera. Given as the * west, south, east, north degrees `boundsChange` reports, as an ENVELOPE string in the form * `dcat_bbox` holds one, or as anything else MapLibre reads as bounds. A string is read from an * attribute, so a page rendered by a server can say what its map is filtered to without any * JavaScript at all. * * It goes on holding: whenever what is drawn changes, the camera returns here rather than * re-framing itself around the new set of results. Wins over `viewBounds` when both are given, * an active filter being the stronger statement - though in practice a page states one or the * other, never both. Leave it unset for a map that should look at whatever it has been given; see * `viewBounds` for a default to open on instead of the whole world. */ searchBounds?: LngLatBoundsLike | string; /** * Where to point the camera when there is nothing else to look at - no active search, no results - * in place of the whole world. Given in the same form as `searchBounds` and read the same way, but * nothing about it is drawn: no box, no marker, nothing on the map says it is there. * * Framed exactly, with no padding and no ceiling on how far in the camera can zoom - unlike * `searchBounds` and the extent of a set of results, which both keep the theme's gap because * neither one is a promise about what should fill the frame. This one is: a page that sets it has * already chosen the exact box the map should show, so nothing here second-guesses that choice. */ viewBounds?: LngLatBoundsLike | string; /** * Whether a wheel needs the command key, and a touch drag needs a second finger, before either * reaches the map - see MapLibre's CooperativeGesturesHandler. On by default, since a small map * embedded in a page must not eat the scroll a reader meant for the page around it. A page that * gives the map the whole screen, or has its own way of keeping the two apart, can turn it off. */ cooperativeGestures: boolean; error?: PreviewError; boundsChange: EventEmitter<[number, number, number, number]>; /** * Which result the reader's pointer is over: its place in the list counted from one, and the id of * the record - or of the resource a previewer draws - it came from. Null once the pointer has left * every number. * * Both terms, because a page holds its results in one or the other, and either is enough to light up * the row the reader is pointing at - which is the whole of what this is for: * * overview.addEventListener('highlightChange', event => mark(event.detail?.id)); * * The reader's own pointer only. Setting `highlighted` doesn't come back out: a page that has said * which result matters already knows, and reporting it would be a loop waiting to be wired. */ highlightChange: EventEmitter<{ place: number; id: string; } | null>; private map; private mapTheme; private geosearchControl?; private mapStyleLoaded; private projection; private extents; private ids; private searchFilter?; private viewFilter?; private hovered?; componentWillLoad(): void; componentDidLoad(): Promise; /** * Clean up the map, unless this disconnect turns out to be a relocation rather than a removal. * * A page can preserve this element across a Turbo visit - data-turbo-permanent - by detaching it * from the old document and reattaching it to the new one, and the two happen close enough together * that nothing else runs in between: no repaint, no other timer, nothing but the microtasks Turbo's * own rendering steps through. Waiting a macrotask is enough to stand on the far side of all of * that and ask what actually happened - isConnected is true again if a reattach was coming, and * still false if this really was the end of it - without holding up anything that depends on * disconnectedCallback happening promptly. Checked instead of assumed: guessing "permanent" from * the attribute would be a second thing to keep in sync with Turbo's own timing, for no less code. */ disconnectedCallback(): void; /** * Highlight whichever number the reader's pointer is over. * * Bound to the layer rather than to the map, so MapLibre does the hit testing against the symbols it * actually placed - and bound once, before any of them exist, because a layer listener is the map's * own and goes on answering for every style document that follows. Nothing here moves the camera or * tells the page: a pointer resting on a number is a question about that number, not a click. * * mousemove rather than mouseenter, because the pointer can cross from one marker straight onto the * next without ever leaving the layer, and mouseenter is only offered the first of those. */ private followPointer; private handlePointerOver; private handlePointerOut; private setHovered; private hoveredResult; private addControls; private handleStyleLoad; /** * The projection changing under the camera, which is worth a fresh one: what a globe can be pointed * at is not what a flat map can - see frameLocation - so flattening one is how a reader sees the * whole of something too wide to fit on a sphere. * * Nothing is remembered here, because this event can't say who caused it. A reader pressing the * globe button and a style document naming its own projection on the way in arrive as the same * thing, and no flag holds them apart: a swap asked for while the map is still loading the document * before it lands that reset squarely inside any window this could call the reader's. What to put * back after a swap is read off the map instead, at the point the swap starts - see onThemeChange. */ private handleProjectionTransition; protected onGeosearchChange(): void; protected onSearchHelpTextChange(): void; private applyGeosearch; /** * What the reader drew, as an area a query can state. * * The two corners arrive as pixels on the canvas, so which is west is decided on screen rather than * by longitude. With rotation disabled the left edge is always the west one, and it has to be read * that way round: a box dragged across the antimeridian unprojects to 175 and -175, and taking the * smaller of those for west would describe the other 350 degrees. Screen y grows downward, so the * top of the box is its north edge. * * On a globe those two corners aren't the corners of a rectangle at all - the top edge of a screen * box isn't a line of latitude - but they are what the reader enclosed, and they are the same two * points MapLibre's own box zoom would have fitted. * * The latitudes are sorted afterwards, unlike the longitudes. Screen y and latitude only run * together while the pole is off screen: pan one into view on a globe and a line of pixels crosses * it, so the higher pixel can be the lower latitude, and a box dragged over the pole would come out * with its south edge north of its north edge. Nothing rejects that - LngLatBounds holds whichever * corners it is given - so it would leave here as a bbox no query can answer. */ private search; protected onRecordsChange(): Promise; protected onSearchBoundsChange(): Promise; protected onViewBoundsChange(): Promise; protected onHighlightedChange(): void; protected onThemeChange(): Promise; protected onCooperativeGesturesChange(): void; private load; private readSearchFilter; private readViewFilter; private measure; private declaredExtents; private draw; private frame; private target; private globe; private camera; private highlightedPositions; /** * Which result the highlight names, counted from one. * * A number is a place in the list, and a string is an id - unless it is a place written down, which * is what an attribute hands over for either, since an attribute is always a string. An id is tried * first, because an id we hold is a match and a place is only a count: a page whose records are * named "1", "2", "3" means the record rather than the row. * * Counted over every result, including the ones nobody could place. The number is the row a reader * sees beside the map, so closing the gap a record with no bounding box leaves would point every * result after it at the wrong row - and a highlight that lands on one of those gaps draws nothing, * which is the truth. Nothing at all for a value naming neither an id nor a row, which is a map with * no highlight rather than one with the wrong highlight. */ private highlightedPosition; private position; render(): any; }