{"version":3,"sources":["jsdelivr-header.js","/npm/@mapbox/search-js-web@1.5.0/src/index.ts","/npm/@mapbox/search-js-web@1.5.0/src/utils/dom.ts","/npm/@mapbox/search-js-web@1.5.0/src/utils/class_name_transformers.ts","/npm/@mapbox/search-js-web@1.5.0/src/utils/index.ts","/npm/@mapbox/search-js-web@1.5.0/src/utils/map.ts","/npm/@mapbox/search-js-web@1.5.0/src/constants.ts","/npm/@mapbox/search-js-web@1.5.0/src/components/HTMLScopedElement.ts","/npm/@mapbox/search-js-web@1.5.0/src/theme.ts","/npm/@mapbox/search-js-web@1.5.0/src/utils/popover.ts","/npm/@mapbox/search-js-web@1.5.0/src/MapboxHTMLEvent.ts","/npm/@mapbox/search-js-web@1.5.0/src/utils/aria/messages.ts","/npm/@mapbox/search-js-web@1.5.0/src/utils/aria/index.ts","/npm/@mapbox/search-js-web@1.5.0/src/utils/listbox.ts","/npm/@mapbox/search-js-web@1.5.0/src/components/MapboxSearchListbox.ts","/npm/@mapbox/search-js-web@1.5.0/src/utils/autofill.ts","/npm/@mapbox/search-js-web@1.5.0/src/confirmAddress.ts","/npm/@mapbox/search-js-web@1.5.0/src/components/MapboxAddressConfirmation.ts","/npm/@mapbox/search-js-web@1.5.0/src/config.ts","/npm/@mapbox/search-js-web@1.5.0/src/utils/confirmation.ts","/npm/@mapbox/search-js-web@1.5.0/src/utils/contribute.ts","/npm/@mapbox/search-js-web@1.5.0/src/components/MapboxAddressConfirmationFeature.ts","/npm/@mapbox/search-js-web@1.5.0/src/components/MapboxAddressConfirmationNoFeature.ts","/npm/@mapbox/search-js-web@1.5.0/src/components/MapboxAddressAutofill.ts","/npm/@mapbox/search-js-web@1.5.0/src/utils/detect_browser_autofill.ts","/npm/@mapbox/search-js-web@1.5.0/src/events/utils.ts","/npm/@mapbox/search-js-web@1.5.0/src/events/MapboxEventManager.ts","/npm/@mapbox/search-js-web@1.5.0/src/components/MapboxSearchBox.ts","/npm/@mapbox/search-js-web@1.5.0/src/utils/localization.ts","/npm/@mapbox/search-js-web@1.5.0/src/components/MapboxGeocoder.ts","/npm/@mapbox/search-js-web@1.5.0/src/components/MapboxAddressMinimap.ts","/npm/@mapbox/search-js-web@1.5.0/src/utils/minimap.ts","/npm/@mapbox/search-js-web@1.5.0/src/autofill.ts"],"names":[],"mappings":"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","file":"/npm/@mapbox/search-js-web@1.5.0/dist/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/@mapbox/search-js-web@1.5.0/dist/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","/* eslint-disable @typescript-eslint/triple-slash-reference */\n/* eslint-disable spaced-comment */\n\n/// <reference path=\"./types/custom_elements.d.ts\" />\n/// <reference path=\"./types/typehead.d.ts\" />\n\nimport './components/MapboxSearchListbox';\nimport './components/MapboxAddressConfirmationFeature';\nimport './components/MapboxAddressConfirmationNoFeature';\n\nexport {\n  MapboxAddressConfirmation,\n  AddressConfirmOptions,\n  ConfirmationMinimapOptions\n} from './components/MapboxAddressConfirmation';\n\nexport { MapboxAddressAutofill } from './components/MapboxAddressAutofill';\nexport {\n  MapboxSearchBox,\n  MapboxSearchBoxComponentOptions\n} from './components/MapboxSearchBox';\nexport {\n  MapboxGeocoder,\n  MapboxGeocoderComponentOptions\n} from './components/MapboxGeocoder';\n\nexport { MapboxAddressMinimap } from './components/MapboxAddressMinimap';\n\nexport { MapboxHTMLEvent } from './MapboxHTMLEvent';\nexport { Theme } from './theme';\n\nexport {\n  autofill,\n  AddressAutofillCollectionOptions,\n  AddressAutofillCollectionOptions as AutofillCollectionOptions // alias for backward compatibility\n} from './autofill';\nexport { confirmAddress } from './confirmAddress';\n\nexport { MapStyleMode, Anchor } from './utils/minimap';\nexport { AddressConfirmShowResult } from './utils/confirmation';\nexport {\n  getFormAutofillValues,\n  getAutofillSearchText,\n  AutofillValueMap\n} from './utils/autofill';\nexport { PopoverOptions } from './utils/popover';\n\nexport { config } from './config';\n","/**\n * Used below in {@link createCSSStyleSheet}.\n */\nconst subdoc = document.implementation.createHTMLDocument();\n\nexport function bindElements<\n  Binding extends { [key: string | symbol | number]: Element }\n>(root: Element, elements: { [key in keyof Binding]: string }): Binding {\n  const binding: Binding = {} as Binding;\n  for (const [key, selector] of Object.entries(elements)) {\n    binding[key as keyof Binding] = root.querySelector(selector);\n  }\n\n  return binding;\n}\n\n/**\n * Gets all child elements for a given node.\n */\nexport function getChildElements(node: Node): HTMLElement[] {\n  return Array.from(node.childNodes || []).filter(\n    (el) => el.nodeType === Node.ELEMENT_NODE\n  ) as HTMLElement[];\n}\n\n/**\n * Creates an HTML element from a string and returns it.\n */\nexport function createElementFromString<T extends Element>(\n  innerHTML: string\n): T {\n  const template = document.createElement('template');\n  template.innerHTML = innerHTML;\n  return template.content.firstElementChild as T;\n}\n\n/**\n * Returns a {@link CSSStyleSheet} that can be used to traverse a\n * CSS file.\n *\n * NOTE: We need to use a sub-document to avoid the styles being\n * applied to the current page.\n */\nexport function createCSSStyleSheet(text: string): CSSStyleSheet {\n  const style = subdoc.createElement('style');\n  style.textContent = text;\n  subdoc.head.appendChild(style);\n  return style.sheet;\n}\n\n/**\n * Returns if the property has \"display: none\" set on itself.\n *\n * Reference: https://stackoverflow.com/questions/19669786/check-if-element-is-visible-in-dom\n */\nexport function isVisible(element: HTMLElement): boolean {\n  const style = window.getComputedStyle(element);\n  return style.display !== 'none';\n}\n\nexport type InputFormElement =\n  | HTMLInputElement\n  | HTMLSelectElement\n  | HTMLTextAreaElement;\n\ntype ReactInputEvent = Event & {\n  simulated: boolean;\n};\n\ntype ReactInputWrapperState = InputFormElement & {\n  _valueTracker?: {\n    getValue: () => string;\n    setValue: (value: string) => void;\n    stopTracking: () => void;\n  };\n};\n\n/**\n * Sets the value of the given input element and triggers an `input` event.\n *\n * This should also work for React, which overrides the `value` setter with\n * a custom tracker. Due to this, a naive `input.value = value` will not\n * work correctly in React.\n *\n * Reference: https://github.com/facebook/react/blob/c88fb49d37fd01024e0a254a37b7810d107bdd1d/packages/react-dom/src/client/inputValueTracking.js#L53\n * Reference: https://github.com/facebook/react/issues/11488\n */\nexport function setValue(\n  input: InputFormElement | undefined,\n  value: string\n): void {\n  if (!input) {\n    return;\n  }\n\n  const set = Object.getOwnPropertyDescriptor(\n    input.constructor.prototype,\n    'value'\n  ).set;\n  set.call(input, value);\n\n  // Make this work in React 16+.\n  const wrapperState = input as ReactInputWrapperState;\n  if (wrapperState._valueTracker) {\n    wrapperState._valueTracker.setValue('');\n  }\n\n  const onInputEvent = new Event('input', {\n    bubbles: true\n  }) as ReactInputEvent;\n  onInputEvent.simulated = true;\n\n  input.dispatchEvent(onInputEvent);\n\n  const onChangeEvent = new Event('change', {\n    bubbles: true\n  }) as ReactInputEvent;\n  onChangeEvent.simulated = true;\n\n  input.dispatchEvent(onChangeEvent);\n}\n\n/**\n * Pre-calculate the size of an element, handling cases where the element is not yet rendered\n * @param element - The element to measure\n * @param deep - If true, include node's descendents in calculation. Defaults to false.\n * @returns Object with height and width properties as numbers\n */\nexport function getElementSize(\n  element: HTMLElement,\n  deep = false\n): {\n  height: number;\n  width: number;\n} {\n  let width: number;\n  let height: number;\n  const elementRect = element.getBoundingClientRect();\n  if (\n    element.style.display === 'none' ||\n    (elementRect.height === 0 && elementRect.width === 0)\n  ) {\n    const clone = element.cloneNode(deep) as HTMLElement;\n    element.parentElement.appendChild(clone);\n    clone.style.setProperty('display', 'block', 'important');\n    const cloneRect = clone.getBoundingClientRect();\n    width = cloneRect.width;\n    height = cloneRect.height;\n    clone.style.setProperty('display', 'none');\n    clone.remove();\n  } else {\n    width = elementRect.width;\n    height = elementRect.height;\n  }\n  return {\n    height: Math.floor(height),\n    width: Math.floor(width)\n  };\n}\n\n/**\n * Adds a style to the current page document for the root CSS from the Mapbox search-js-web package.\n */\nexport function addDocumentStyle(css: string): void {\n  const style = document.createElement('style');\n  style.innerHTML = css;\n  document.head.appendChild(style);\n}\n","import { createCSSStyleSheet } from './dom';\n\n/**\n * W3C spec:\n *\n * In CSS, identifiers (including element names, classes, and IDs in selectors)\n * can contain only the characters [a-z0-9] and ISO 10646 characters U+00A0 and\n * higher, plus the hyphen (-) and the underscore (_); they cannot start with a\n * digit, or a hyphen followed by a digit. Identifiers can also contain escaped\n * characters and any ISO 10646 character as a numeric code (see next item).\n *\n * For instance, the identifier \"B&W?\" may be written as \"B&W?\" or \"B\\26 W\\3F\".\n *\n * Reference: https://stackoverflow.com/questions/448981/which-characters-are-valid-in-css-class-names-selectors\n */\nconst IDENTIFIER_REGEX = new RegExp('[_a-zA-Z]+[_a-zA-Z0-9-]*', 'g');\nconst CLASS_NAME_REGEX = new RegExp(`\\\\.${IDENTIFIER_REGEX.source}`, 'g');\n\n/**\n * Of the format @IDENFIFIER (RULE) { }\n *\n * Only catches the media and supports identifiers.\n *\n * Reference: https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule\n */\nconst CONDITION_RULE_REGEX = new RegExp(\n  `^\\\\s*(@(?:media|supports)[^{]*){(.*)}\\\\s*$`\n);\n\nexport function transformClassSelectors(\n  css: string,\n  transform: (className: string) => string\n): string {\n  return css.replace(CLASS_NAME_REGEX, (className: string) => {\n    return '.' + transform(className.slice(1));\n  });\n}\n\n/**\n * Returns a version of the CSS string with each class name transformed\n * by {@link transform}.\n *\n * The main reason why this function exists is to allow for CSS class\n * encapsulation without Shadow DOM.\n */\nexport function transformCSSClassRules(\n  text: string,\n  transform: (className: string) => string\n): string {\n  // Create a CSSStyleSheet so we can traverse the CSS rules,\n  // without having to parse ourselves.\n  const sheet = createCSSStyleSheet(text);\n  const rules = sheet.cssRules;\n\n  /**\n   * No guarantees of in-place mutation.\n   */\n  function transformCSSRule(rule: CSSRule): string {\n    /**\n     * [CSSStyleRule](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleRule)\n     * represents a single CSS declaration block, like `h1 { color: red; }`.\n     *\n     * Make sure to transform the \"selector\", which in the example above is \"h1\".\n     */\n    if (rule instanceof CSSStyleRule) {\n      const selector = transformClassSelectors(rule.selectorText, transform);\n      return `${selector} { ${rule.style.cssText} }`;\n    }\n\n    /**\n     * Condition-rules are like `@media print { ... }`, or `@supports (display: grid) { ... }`.\n     *\n     * This should be covered by [CSSConditionRule](https://developer.mozilla.org/en-US/docs/Web/API/CSSConditionRule)\n     * however browser support for CSSConditionRule is not great: namely, Safari\n     * versions earlier than 14.1 (early 2021) do not support it.\n     *\n     * Because of this, we need to traverse the text of the at-rule with\n     * a regular expression.\n     *\n     * Useful helper: https://regexr.com/\n     */\n    const atRule = CONDITION_RULE_REGEX.exec(rule.cssText.split('\\n').join(''));\n    if (atRule && atRule.length > 2) {\n      const rule = atRule[1];\n      const contents = atRule[2];\n\n      // Recursively transform the contents of the at-rule.\n      return `${rule} { ${transformCSSClassRules(contents, transform)} }`;\n    }\n\n    /**\n     * Otherwise, just pass through fonts, animations, etc...\n     */\n    return rule.cssText;\n  }\n\n  // Construct a new CSS string by traversing the rules and serializing\n  // them to a string.\n  let style = '';\n  for (const rule of Array.from(rules)) {\n    style += transformCSSRule(rule) + '\\n\\n';\n  }\n\n  return style.trim();\n}\n\n/**\n * Manipulates {@param content} in place, with each class attribute transformed\n * by {@link transform}.\n *\n * The main reason why this function exists is to allow for CSS class\n * encapsulation without Shadow DOM.\n */\nexport function transformDOMClassAttributes(\n  content: HTMLElement,\n  transform: (className: string) => string\n): HTMLElement {\n  // Perform the transformation on each class attribute in-place,\n  // on the clone.\n  const elements = Array.from(content.querySelectorAll('[class]'));\n  // Add the current node!\n  elements.push(content);\n\n  for (const element of elements) {\n    const { classList } = element;\n    for (const className of Array.from(classList)) {\n      classList.remove(className);\n      classList.add(transform(className));\n    }\n  }\n\n  // Return the element.\n  return content;\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { SessionToken } from '@mapbox/search-js-core';\nimport { MAPBOX_DOMAINS } from '../constants';\n\n/**\n * Returns a random ID that is valid as a CSS identifier.\n *\n * CSS identifiers cannot start with a number, so we prefix the ID with `mbx`.\n */\nexport function randomValidID(): string {\n  return `mbx` + new SessionToken().id.slice(0, 8);\n}\n\n/**\n * Try to parse as a JSON object, returning `null` if it fails.\n */\nexport function tryParseJSON<T>(json: string): T | null {\n  try {\n    return JSON.parse(json);\n  } catch (e) {\n    return null;\n  }\n}\n\nexport function deepEquals<T>(a: T, b: T): boolean {\n  if (a == null || b == null) {\n    return a === b;\n  }\n\n  if (typeof a !== 'object' || typeof b !== 'object') {\n    return a === b;\n  }\n\n  const aKeys = Object.keys(a);\n  const bKeys = Object.keys(b);\n\n  if (aKeys.length !== bKeys.length) {\n    return false;\n  }\n\n  for (const key of aKeys) {\n    if (!deepEquals(a[key], b[key])) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\n/**\n * Round a number to a given number of digits after the decimal\n * @param num - Number to round\n * @param decimalPlaces - Number of places after the decimal to round to\n * @returns Rounded decimal number\n */\nexport function round(num: number, decimalPlaces: number): number {\n  const factorOfTen = Math.pow(10, decimalPlaces);\n  return Math.round(num * factorOfTen) / factorOfTen;\n}\n\n/**\n * Returns true if a hostname matches a local server protocol\n * @param hostname - A string representing window.location.hostname\n * @returns A boolean value\n */\nexport function isLocalServer(hostname: string): boolean {\n  return Boolean(\n    hostname.match(\n      /localhost|[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}|::1|\\.local|^$/gi\n    )\n  );\n}\n\n/**\n * Returns true if a hostname matches a Mapbox domain\n * @param hostname - A string representing window.location.hostname\n * @returns A boolean value\n */\nexport function isMapboxDomain(hostname: string): boolean {\n  return Boolean(MAPBOX_DOMAINS.some((domain) => hostname.includes(domain)));\n}\n","import mapboxgl from 'mapbox-gl';\n\n/**\n * This is slightly higher than the default value of 1.2.\n * https://docs.mapbox.com/mapbox-gl-js/api/map/#map#flyto\n * We use a high speed value for cypress tests to increase test speed and improve test stability.\n */\nexport const FLY_TO_SPEED = 1.4;\n\n/**\n * Gets the center/zoom for a given bounding box.\n *\n * @param delta - Subtracted from the zoom level so users can fully see\n * the bounding box. This is a hack to add padding.\n */\nexport function bboxViewport(\n  map: mapboxgl.Map,\n  bounds: mapboxgl.LngLatBoundsLike,\n  delta = 0.5\n): mapboxgl.FlyToOptions {\n  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n  const { center, zoom } = map.cameraForBounds(bounds)!;\n  const transformedZoom = Math.max(zoom - delta, 0);\n\n  return {\n    center,\n    zoom: transformedZoom,\n    speed: FLY_TO_SPEED\n  };\n}\n\n/**\n * Gets the maximum zoom level for a [Mapbox Search Box API](https://docs.mapbox.com/api/search/search-box/)\n * or [Mapbox Geocoding API](https://docs.mapbox.com/api/search/geocoding-v6/) place type.\n *\n * @returns The maximum zoom level for the given place type, `16` if the type is not supported.\n */\nexport function getMaxZoom(placeType: string): number {\n  switch (placeType) {\n    case 'street':\n      return 15;\n    case 'neighborhood':\n    case 'postcode':\n    case 'locality':\n    case 'oaza':\n      return 14;\n    case 'place':\n    case 'city':\n      return 13;\n    case 'district':\n      return 9;\n    case 'region':\n    case 'prefecture':\n      return 6;\n    case 'country':\n      return 4;\n    default:\n      return 16;\n  }\n}\n\n/**\n * Gets the base URL for the Static Images API for a given user style\n * {@link https://docs.mapbox.com/api/maps/static-images/}\n * @param username The username of the account to which the style belongs\n * @param styleId The ID of the style from which to create a static map\n * @returns\n */\nexport function getStaticBaseUrl(username: string, styleId: string): string {\n  return `https://api.mapbox.com/styles/v1/${username}/${styleId}/static/`;\n}\n","import { createElementFromString } from './utils/dom';\nimport { getStaticBaseUrl } from './utils/map';\nimport closeIcon from './icons/close.svg';\nimport loadingIcon from './icons/loading.svg';\n\nexport const STATIC_BASE_URL_SATELLITE = getStaticBaseUrl(\n  'mapbox',\n  'satellite-streets-v11'\n);\n\nexport const AUTOFILL_SKU_TOKEN_PREFIX = '20d01';\n\nexport const MAPBOX_DOMAINS = ['mapbox.com', 'mapbox.cn', 'tilestream.net'];\n\nexport const LISTBOX_TEMPLATE =\n  createElementFromString<HTMLTemplateElement>(/* html */ `\n<template>\n  <div class=\"MapboxSearch\">\n    <div class=\"Label\" role=\"label\" aria-live=\"polite\" aria-atomic=\"true\">\n    </div>\n    <div class=\"Results\" aria-hidden=\"true\">\n      <div class=\"ResultsList\" role=\"listbox\">\n      </div>\n      <div class=\"ResultsAttribution\" aria-hidden=\"true\">\n        <a href=\"https://www.mapbox.com/search-service\" target=\"_blank\" tabindex=\"-1\">\n          Powered by Mapbox\n        </a>\n      </div>\n    </div>\n  </div>\n</template>\n`);\n\nexport const LISTBOX_SUGGESTION_TEMPLATE =\n  createElementFromString<HTMLTemplateElement>(/* html */ `\n<template>\n  <div class=\"Suggestion\" role=\"option\" tabindex=\"-1\">\n    <div class=\"SuggestionIcon\" aria-hidden=\"true\"></div>\n    <div class=\"SuggestionText\">\n      <div class=\"SuggestionName\"></div>\n      <div class=\"SuggestionDesc\"></div>\n    </div>\n  </div>\n</template>\n`);\n\nexport const SEARCHBOX_TEMPLATE =\n  createElementFromString<HTMLTemplateElement>(/* html */ `\n<template>\n  <div class=\"SearchBox\">\n    <div class=\"SearchIcon\"></div>\n    <input class=\"Input\" type=\"text\" />\n    <div class=\"ActionIcon\">\n      <button aria-label=\"Clear\" class=\"ClearBtn\" type=\"button\">${closeIcon}</button>\n      <div class=\"LoadingIcon\">${loadingIcon}</div>\n    </div>\n  </div>\n</template>\n`);\n\nexport const GEOCODER_TEMPLATE =\n  createElementFromString<HTMLTemplateElement>(/* html */ `\n<template>\n  <div class=\"Geocoder\">\n    <div class=\"SearchIcon\"></div>\n    <input class=\"Input\" type=\"text\" />\n    <div class=\"ActionIcon\">\n      <button aria-label=\"Clear\" class=\"ClearBtn\" type=\"button\">${closeIcon}</button>\n      <div class=\"LoadingIcon\">${loadingIcon}</div>\n    </div>\n  </div>\n</template>\n`);\n","/* eslint-disable custom-elements/expose-class-on-global */\n/* eslint-disable custom-elements/define-tag-after-class-definition */\nimport {\n  transformClassSelectors,\n  transformCSSClassRules,\n  transformDOMClassAttributes\n} from '../utils/class_name_transformers';\n\nimport { randomValidID } from '../utils';\n\n/**\n * Custom HTML element that uses the \"Scoped DOM\" approach,\n * which is not really Shadow DOM, but a way to encapsulate CSS classes\n * without Shadow DOM.\n *\n * This is a workaround for the fact that ARIA attributes are identified by\n * IDs, and cannot be shared between Shadow DOM and non-Shadow DOM (Light DOM)\n * elements due to encapsulation.\n *\n * Examples are an <input> element and its corresponding popover.\n *\n * The \"Scoped DOM\" approach is to encapsulate CSS classes by transforming\n * the class attribute of each element, prefixing each class with a\n * random UUID.\n *\n * Goals of the \"Scoped DOM\":\n *\n * - Once the [Accessibility Object Model (AOM)](https://wicg.github.io/aom/explainer.html) is finalized,\n *   replace all uses of {@link MapboxHTMLScopedElement} with {@link MapboxHTMLShadowElement}, and use\n *   AOM instead of IDREFs for ARIA attributes.\n *\n * - The Scoped DOM should be self-contained and work well enough that we don't\n *   need to constantly work around it.\n *\n * - The Scoped DOM should have extensive testing.\n */\nexport class HTMLScopedElement<\n  Events extends { [key: number | string | symbol]: Event } = Record<\n    string,\n    Event\n  >\n> extends HTMLElement {\n  // Seed to use for class name prefixing.\n  #seed = randomValidID();\n\n  protected get template(): HTMLTemplateElement {\n    return null;\n  }\n\n  protected get templateStyle(): string {\n    return null;\n  }\n\n  protected get templateUserStyle(): string {\n    return null;\n  }\n\n  #templateUserStyleElement: HTMLStyleElement;\n\n  /**\n   * `clonedCallback` should be a part of the Web Components spec, but sadly\n   * it is not.\n   *\n   * This is detected in {@link connectedCallback} below if the seed has changed.\n   */\n  clonedCallback(oldSeed: string, newSeed: string): void {\n    // New transform function that replaces any instances of the old\n    // seed with the new one.\n    const seedTransform = (className: string) =>\n      className.replace(oldSeed, newSeed);\n\n    transformDOMClassAttributes(this, seedTransform);\n\n    const styles = Array.from(this.querySelectorAll<HTMLStyleElement>('style'));\n    for (const style of styles) {\n      style.textContent = transformClassSelectors(\n        style.textContent,\n        seedTransform\n      );\n    }\n\n    // Find and repopulate #templateUserStyleElement.\n    if (styles.length) {\n      this.#templateUserStyleElement = styles[styles.length - 1];\n    }\n\n    // Replace id prefix for all sub-nodes\n    const nodesWithId = Array.from(this.querySelectorAll(`[id^=\"${oldSeed}\"]`));\n    for (const node of nodesWithId) {\n      node.id = node.id.replace(oldSeed, newSeed);\n    }\n  }\n\n  connectedCallback(): void {\n    // Return if we already have children.\n    if (this.childElementCount > 0) {\n      const oldSeed = this.dataset.seed;\n      const newSeed = this.#seed;\n\n      // If we have a different seed than before, say from a clone,\n      // then we need to update any templates and styles.\n      if (oldSeed && oldSeed !== newSeed) {\n        this.clonedCallback(oldSeed, newSeed);\n\n        // Finally, make sure the dataset has the new seed.\n        this.dataset.seed = newSeed;\n      }\n\n      return;\n    }\n\n    this.dataset.seed = this.#seed;\n\n    // Use the Light DOM to contain our inner elements,\n    // and do CSS class obfuscation in the \"Scoped DOM.\"\n    const template = this.template;\n    if (template) {\n      const element = this.prepareTemplate(template);\n      this.appendChild(element);\n    }\n\n    const templateStyle = this.templateStyle;\n    if (templateStyle) {\n      const style = document.createElement('style');\n      style.textContent = this.prepareCSS(templateStyle);\n      this.appendChild(style);\n    }\n\n    const userStyle = document.createElement('style');\n    if (this.templateUserStyle) {\n      userStyle.textContent = this.prepareCSS(this.templateUserStyle);\n    }\n    this.appendChild(userStyle);\n    this.#templateUserStyleElement = userStyle;\n  }\n\n  /**\n   * Transform function for {@link transformCSSClassRules} and\n   * {@link transformDOMClassAttributes}.\n   */\n  #transform = (className: string): string => {\n    return `${this.#seed}--${className}`;\n  };\n\n  prepareTemplate(template: HTMLTemplateElement): HTMLElement {\n    const element = template.content.firstElementChild;\n    return transformDOMClassAttributes(\n      element.cloneNode(true) as HTMLElement,\n      this.#transform\n    );\n  }\n\n  prepareCSS(css: string): string {\n    return transformCSSClassRules(css, this.#transform);\n  }\n\n  updateTemplateUserStyle(style: string): void {\n    if (!this.#templateUserStyleElement) {\n      return;\n    }\n    this.#templateUserStyleElement.textContent = this.prepareCSS(style);\n  }\n\n  querySelector<E extends Element = Element>(selectors: string): E {\n    return super.querySelector(\n      transformClassSelectors(selectors, this.#transform)\n    );\n  }\n\n  querySelectorAll<E extends Element = Element>(\n    selectors: string\n  ): NodeListOf<E> {\n    return super.querySelectorAll(\n      transformClassSelectors(selectors, this.#transform)\n    );\n  }\n\n  addEventListener<K extends keyof Events>(\n    type: K,\n    listener: (this: HTMLFormElement, ev: Events[K]) => unknown,\n    options?: boolean | AddEventListenerOptions\n  ): void;\n  addEventListener(\n    type: string,\n    listener: EventListenerOrEventListenerObject,\n    options?: boolean | AddEventListenerOptions\n  ): void {\n    super.addEventListener(type, listener, options);\n  }\n\n  removeEventListener<K extends keyof Events>(\n    type: K,\n    listener: (this: HTMLFormElement, ev: Events[K]) => unknown,\n    options?: boolean | EventListenerOptions\n  ): void;\n  removeEventListener(\n    type: string,\n    listener: EventListenerOrEventListenerObject,\n    options?: boolean | EventListenerOptions\n  ): void {\n    super.removeEventListener(type, listener, options);\n  }\n\n  dispatchEvent<K extends keyof Events>(event: Events[K]): boolean {\n    return super.dispatchEvent(event);\n  }\n}\n","import closeIcon from './icons/close.svg';\nimport questionIcon from './icons/question.svg';\nimport markerIcon from './icons/marker.svg';\nimport streetIcon from './icons/street.svg';\nimport addressMarkerIcon from './icons/addressMarker.svg';\nimport searchIcon from './icons/search.svg';\n\nimport { version } from '../package.json';\nconst styleToggleSatelliteImg = `https://api.mapbox.com/search-js/v${version}/img/style-toggle-satellite.jpg`;\nconst styleToggleDefaultImg = `https://api.mapbox.com/search-js/v${version}/img/style-toggle-default.jpg`;\n\n/**\n * Reference:\n * https://getbootstrap.com/docs/5.0/layout/breakpoints/\n */\nexport const MOBILE_BREAKPOINT = 768 - 1;\nconst MOBILE_MEDIA_QUERY = `@media only screen and (max-width: ${MOBILE_BREAKPOINT}px)`;\n\n/**\n * Currently, the only expression supported is\n * `['mobile', mobile_value, tablet_and_desktop_value]`.\n *\n * @typedef Expression\n */\ntype Expression = ['mobile', string, string];\n\n/**\n * `ThemeVariables` are a collection of CSS variables that style Control Theme API\n * elements.\n *\n * @typedef ThemeVariables\n */\nexport interface ThemeVariables {\n  /** @section {Sizing} */\n\n  /**\n   * Unit is the base font size and can be referenced in other variables as multiples of `1em`.\n   *\n   * Analogous to [`font-size`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-size).\n   */\n  unit?: string | Expression;\n  /**\n   * Unit header is a derivative of `unit` and is used for modal headers.\n   *\n   * Analogous to [`font-size`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-size).\n   */\n  unitHeader?: string | Expression;\n\n  /**\n   * Minimum width of elements such as modals and listboxes.\n   *\n   * Analogous to CSS [`<length>`](https://developer.mozilla.org/en-US/docs/Web/CSS/length).\n   */\n  minWidth?: string;\n  /**\n   * Spacing between items in an element.\n   *\n   * Analogous to CSS [`<length>`](https://developer.mozilla.org/en-US/docs/Web/CSS/length).\n   */\n  spacing?: string;\n  /**\n   * Padding of items in an element.\n   *\n   * Analogous to CSS [`<length>`](https://developer.mozilla.org/en-US/docs/Web/CSS/length).\n   */\n  padding?: string;\n  /**\n   * Padding of powered by mapbox label in footer of search listbox.\n   *\n   * Analogous to CSS [`<length>`](https://developer.mozilla.org/en-US/docs/Web/CSS/length).\n   */\n  paddingFooterLabel?: string;\n  /**\n   * Padding for contents of modal elements.\n   *\n   * Analogous to CSS [`<length>`](https://developer.mozilla.org/en-US/docs/Web/CSS/length).\n   */\n  paddingModal?: string;\n\n  /** @section {Colors} */\n\n  /**\n   * Color of the primary text.\n   *\n   * Analogous to CSS [`color`](https://developer.mozilla.org/en-US/docs/Web/CSS/color).\n   * **Default**: dark gray\n   */\n  colorText?: string;\n  /**\n   * Color of the primary accent color.\n   *\n   * Analogous to CSS [`color`](https://developer.mozilla.org/en-US/docs/Web/CSS/color).\n   * **Default**: variant of blue\n   */\n  colorPrimary?: string;\n  /**\n   * Color of the secondary accent color.\n   *\n   * Analogous to CSS [`color`](https://developer.mozilla.org/en-US/docs/Web/CSS/color).\n   * **Default**: blue-gray\n   */\n  colorSecondary?: string;\n\n  /**\n   * Background color for elements such as modals and listboxes.\n   *\n   * Analogous to CSS [`color`](https://developer.mozilla.org/en-US/docs/Web/CSS/color).\n   * **Default**: white\n   */\n  colorBackground?: string;\n  /**\n   * Background color for items on hover.\n   *\n   * Analogous to CSS [`color`](https://developer.mozilla.org/en-US/docs/Web/CSS/color).\n   * **Default**: light gray\n   */\n  colorBackgroundHover?: string;\n  /**\n   * Background color for items on press.\n   *\n   * Analogous to CSS [`color`](https://developer.mozilla.org/en-US/docs/Web/CSS/color).\n   * **Default**: dark gray\n   */\n  colorBackgroundActive?: string;\n\n  /**\n   * Backdrop color of body content behind modals.\n   *\n   * Analogous to CSS [`color`](https://developer.mozilla.org/en-US/docs/Web/CSS/color).\n   * **Default**: black with alpha value\n   */\n  colorBackdrop?: string;\n\n  /** @section {Borders and box shadows} */\n\n  /**\n   * Border color of elements such as modals and listboxes.\n   *\n   * Analogous to CSS [`border`](https://developer.mozilla.org/en-US/docs/Web/CSS/border).\n   */\n  border?: string;\n  /**\n   * Border radius of elements such as modals and listboxes.\n   *\n   * Analogous to CSS [`border-radius`](https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius).\n   */\n  borderRadius?: string;\n  /**\n   * Box shadow of elements such as modals and listboxes.\n   *\n   * Analogous to CSS [`box-shadow`](https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow).\n   */\n  boxShadow?: string;\n\n  /** @section {Typography} */\n\n  /**\n   * Line height.\n   *\n   * Analogous to CSS [`line-height`](https://developer.mozilla.org/en-US/docs/Web/CSS/line-height).\n   * **Default**: 1.2\n   */\n  lineHeight?: string;\n  /**\n   * Font family.\n   *\n   * Analogous to CSS [`font-family`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-family).\n   * **Default**: Sans-serif [system font stack](https://systemfontstack.com/)\n   */\n  fontFamily?: string;\n  /**\n   * Font weight for body text.\n   *\n   * Analogous to CSS [`font-weight`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight).\n   * **Default**: normal\n   */\n  fontWeight?: string;\n  /**\n   * Font weight for subheadings.\n   *\n   * Analogous to CSS [`font-weight`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight).\n   * **Default**: 600\n   */\n  fontWeightSemibold?: string;\n  /**\n   * Font weight for headings and item titles.\n   *\n   * Analogous to CSS [`font-weight`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight).\n   * **Default**: bold\n   */\n  fontWeightBold?: string;\n\n  /** @section {Transitions} */\n\n  /**\n   * The duration to use for listbox animations.\n   *\n   * Analogous to CSS [`<time>`](https://developer.mozilla.org/en-US/docs/Web/CSS/time).\n   * **Default**: `150ms`\n   */\n  duration?: string;\n  /**\n   * The timing function to use for listbox animations.\n   *\n   * Analogous to CSS [`<easing-function>`](https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function).\n   * **Default**: `ease-out`\n   */\n  curve?: string;\n}\n\n/**\n * `ThemeIcons` are [SVG icons](https://developer.mozilla.org/en-US/docs/Web/SVG)\n * that are used in Control Theme API elements.\n *\n * Roughly, icon names and their defaults are the same as\n * [Mapbox's Assembly](https://labs.mapbox.com/assembly/icons/).\n *\n * Values must be valid SVG plain-text. Unless otherwise noted,\n * icons should be 18px in size and have appropriate dimensions set.\n *\n * Icons can also be filled with 'currentColor'.\n *\n * @typedef ThemeIcons\n * @example\n * ```typescript\n * const icons = {\n *   close: `\n * <?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n * <svg viewBox=\"0 0 18 18\" xmlns=\"http://www.w3.org/2000/svg\">\n *   <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M3.79289 3.79289C4.18342 3.40237 4.81658 3.40237 5.20711 3.79289L9 7.58579L12.7929 3.79289C13.1834 3.40237 13.8166 3.40237 14.2071 3.79289C14.5976 4.18342 14.5976 4.81658 14.2071 5.20711L10.4142 9L14.2071 12.7929C14.5976 13.1834 14.5976 13.8166 14.2071 14.2071C13.8166 14.5976 13.1834 14.5976 12.7929 14.2071L9 10.4142L5.20711 14.2071C4.81658 14.5976 4.18342 14.5976 3.79289 14.2071C3.40237 13.8166 3.40237 13.1834 3.79289 12.7929L7.58579 9L3.79289 5.20711C3.40237 4.81658 3.40237 4.18342 3.79289 3.79289Z\" fill=\"currentColor\"/>\n * </svg>\n * `\n * }\n * ```\n */\nexport interface ThemeIcons {\n  /**\n   * Close icon.\n   */\n  close?: string;\n  /**\n   * Question mark icon.\n   */\n  question?: string;\n\n  /**\n   * Icon for map markers. Can be any size.\n   */\n  marker?: string;\n\n  /**\n   * Icon for streets results in search list box.\n   */\n  street?: string;\n\n  /**\n   * Icon for address results in search list box.\n   */\n  addressMarker?: string;\n\n  /**\n   * Icon for Search Box input.\n   */\n  search?: string;\n}\n\n/**\n * `ThemeImages` are raster images that are used in Control Theme API elements.\n *\n * There are currently only two images, \"toggle default\" and \"toggle satellite,\"\n * which specify images for a Map/Satellite toggle button.\n *\n * Values must be valid URLs accessible by the expected browser environment. [Data URLs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs)\n * and [Blob URLs](https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL) are also supported.\n *\n * @typedef ThemeImages\n */\nexport interface ThemeImages {\n  /**\n   * Image for the \"Map\" of the Map/Satellite toggle button.\n   */\n  styleToggleDefault?: string;\n  /**\n   * Image for the \"Satellite\" of the Map/Satellite toggle button.\n   */\n  styleToggleSatellite?: string;\n}\n\n/**\n * The Control Theme API is a way to apply your own design system to\n * Mapbox Search JS Web elements.\n *\n * Control themes use a combination of CSS variables, custom scoped CSS, and\n * SVG icons.\n *\n * @typedef Theme\n * @example\n * ```typescript\n * const theme = {\n *   variables: {\n *     fontFamily: 'Avenir, sans-serif',\n *     unit: '14px',\n *     padding: '0.5em',\n *     borderRadius: '0',\n *     boxShadow: '0 0 0 1px silver',\n *   }\n * };\n *\n * autofill({ theme });\n * ```\n */\nexport interface Theme {\n  /**\n   * CSS variables to be applied to the control.\n   */\n  variables?: ThemeVariables;\n  /**\n   * SVG icon overrides to be applied to the control.\n   */\n  icons?: ThemeIcons;\n  /**\n   * Raster image URLs to be applied to the control.\n   */\n  images?: ThemeImages;\n  /**\n   * Optional CSS text to be inserted into Scoped CSS elements. As such, any\n   * CSS will not interact with the rest of the page.\n   *\n   * TODO: Class names are element-specific and have yet to be standardized. Breaking\n   * changes are likely and will be flagged in CHANGELOG.md.\n   */\n  cssText?: string;\n}\n\nconst DEFAULT_THEME: Theme = {\n  variables: {\n    // Added as font size on container, so em references this value.\n    unit: ['mobile', '16px', '14px'],\n    unitHeader: ['mobile', '24px', '18px'],\n\n    minWidth: 'min(300px, 100vw)',\n    spacing: '0.75em',\n    padding: '0.5em 0.75em',\n    paddingFooterLabel: '0.5em 0.75em',\n    paddingModal: '1.25em',\n\n    colorText: 'rgba(0, 0, 0, 0.75)',\n    colorPrimary: '#4264FB',\n    colorSecondary: '#667F91',\n\n    colorBackground: '#fff',\n    colorBackgroundHover: '#f5f5f5',\n    colorBackgroundActive: '#f0f0f0',\n\n    colorBackdrop: 'rgba(102, 127, 145, 0.3)',\n\n    border: 'none',\n\n    borderRadius: '4px',\n    boxShadow: `\n      0 0 10px 2px rgba(0, 0, 0, 0.05),\n      0 0 6px 1px rgba(0, 0, 0, 0.1),\n      0 0 0 1px rgba(0, 0, 0, 0.1)\n    `,\n\n    lineHeight: '1.2em',\n    /**\n     * Reference:\n     * https://systemfontstack.com/\n     */\n    fontFamily: `\n      -apple-system, BlinkMacSystemFont,\n      avenir next, avenir,\n      segoe ui,\n      helvetica neue, helvetica,\n      Ubuntu, roboto, noto, arial, sans-serif\n    `,\n    fontWeight: 'normal',\n    fontWeightSemibold: '600',\n    fontWeightBold: 'bold',\n\n    duration: '150ms',\n    curve: 'ease-out'\n  },\n  icons: {\n    close: closeIcon,\n    question: questionIcon,\n    marker: markerIcon,\n    street: streetIcon,\n    addressMarker: addressMarkerIcon,\n    search: searchIcon\n  },\n  images: {\n    styleToggleDefault: styleToggleDefaultImg,\n    styleToggleSatellite: styleToggleSatelliteImg\n  }\n};\n\ntype CSSText = string;\n\n/**\n * Applies {@link Theme} to the given HTML element as CSS variables\n * in the style attribute.\n */\nexport function getThemeCSS(rootSelector: string, theme: Theme = {}): CSSText {\n  const variables = {\n    // Make sure to shallow apply default variables.\n    ...DEFAULT_THEME.variables,\n    ...(theme.variables || {})\n  };\n\n  let cssText = theme.cssText || '';\n  let rootVariables = '';\n\n  for (const [key, value] of Object.entries(variables)) {\n    // Is a literal, not an expression.\n    if (!Array.isArray(value)) {\n      rootVariables += `--${key}: ${value};`;\n      continue;\n    }\n\n    // Is an expression; only support \"mobile\" for now.\n    if (value[0] !== 'mobile') {\n      const valueStr = JSON.stringify(value);\n      throw new Error(\n        `Unsupported expression in theme variables: ${key} ${valueStr}`\n      );\n    }\n\n    const [, mobileValue, desktopValue] = value;\n\n    // On mobile, force the mobile value.\n    cssText += `${MOBILE_MEDIA_QUERY} { ${rootSelector} { --${key}: ${mobileValue} !important; } }`;\n    // Our default is still the desktop value.\n    rootVariables += `--${key}: ${desktopValue};`;\n  }\n\n  return cssText + `${rootSelector} { ${rootVariables} }`;\n}\n\nexport function getIcon<I extends keyof Theme['icons']>(\n  iconName: I,\n  theme: Theme = {}\n): string | undefined {\n  const icons = {\n    ...DEFAULT_THEME.icons,\n    ...(theme.icons || {})\n  };\n\n  const svgString = icons[iconName];\n  return svgString;\n}\n\nexport function getImage<I extends keyof Theme['images']>(\n  imageName: I,\n  theme: Theme = {}\n): string | undefined {\n  const images = {\n    ...DEFAULT_THEME.images,\n    ...(theme.images || {})\n  };\n\n  const imgString = images[imageName];\n  return imgString;\n}\n","import {\n  computePosition,\n  autoUpdate,\n  ComputePositionConfig,\n  flip,\n  offset\n} from '@floating-ui/dom';\n\n/**\n * Options controlling the display of the Popover used in {@link AddressAutofill}, {@link MapboxSearchBox}, and {@link MapboxGeocoder}.\n * @typedef PopoverOptions\n */\nexport interface PopoverOptions {\n  /**\n   * Positions the popover above or below the reference element. Defaults to 'bottom-start'.\n   */\n  placement: 'top-start' | 'bottom-start';\n  /**\n   * If true, the popover will flip to the opposite side of the reference element to try to keep it in view when scrolling out of frame. Defaults to false.\n   */\n  flip: boolean;\n  /**\n   * The distance gap between the popover and the reference element. Defaults to 5px.\n   */\n  offset: number;\n}\n\n/**\n * Wrapper around floating-ui controls to manage popover positioning and lifecycle.\n */\nexport class Popover {\n  /**\n   * The element around which the popover is positioned, e.g. the `<input>` search box\n   */\n  referenceEl: HTMLElement;\n  /**\n   * The floating popover element, e.g. the results box\n   */\n  floatingEl: HTMLElement;\n\n  #options: PopoverOptions;\n\n  /**\n   * Cleans up the popover instance and any side effects\n   */\n  destroy: () => void;\n\n  #defaultOptions: PopoverOptions = {\n    placement: 'bottom-start',\n    flip: false,\n    offset: 10\n  };\n\n  constructor(\n    referenceEl: HTMLElement,\n    floatingEl: HTMLElement,\n    options?: Partial<PopoverOptions>\n  ) {\n    this.referenceEl = referenceEl;\n    this.floatingEl = floatingEl;\n    this.#options = { ...this.#defaultOptions, ...options };\n    this.destroy = autoUpdate(this.referenceEl, this.floatingEl, this.update);\n  }\n\n  /**\n   * Positioning options for the popover element.\n   */\n  get options(): PopoverOptions {\n    return this.#options;\n  }\n  set options(newOptions: Partial<PopoverOptions>) {\n    this.#options = { ...this.#options, ...newOptions };\n  }\n\n  /**\n   * Recomputes the popover position one time\n   */\n  update = async (): Promise<void> => {\n    const config: Partial<ComputePositionConfig> = {\n      placement: this.options.placement,\n      middleware: [\n        offset(this.options.offset),\n        this.options.flip && flip()\n      ].filter(Boolean)\n    };\n    const { x, y } = await computePosition(\n      this.referenceEl,\n      this.floatingEl,\n      config\n    );\n    Object.assign(this.floatingEl.style, {\n      left: `${x}px`,\n      top: `${y}px`\n    });\n  };\n}\n","/**\n * `MapboxHTMLEvent` is an event dispatched by the Search Box and Address Autofill\n * components.\n *\n * @example\n * ```\n * const search = new MapboxSearchBox();\n * search.addEventListener('retrieve', (event: MapboxHTMLEvent<Suggestion>) => {\n *  console.log(event.detail);\n * });\n */\nexport class MapboxHTMLEvent<T> extends CustomEvent<T> {\n  constructor(type: string, detail?: T) {\n    super(type, {\n      composed: true,\n      detail\n    });\n  }\n\n  /**\n   * Returns a shallow copy of the event. This method is useful for\n   * manually bubbling events from a connected component.\n   *\n   * @param newTarget - Optional event target to assign to the clone\n   *\n   * @example\n   * `MapboxSearchBox` will call `event.clone()` on the `retrieve`\n   * event from `MapboxSearchListbox`, and then dispatch the cloned event.\n   */\n  clone(newTarget?: EventTarget): MapboxHTMLEvent<T> {\n    const eventClone = new MapboxHTMLEvent(this.type, this.detail);\n    if (newTarget) {\n      Object.defineProperty(eventClone, 'target', { value: newTarget });\n    }\n    return eventClone;\n  }\n}\n","export const LENGTH_MESSAGE = 'Type in 2 or more characters for results.';\n\nexport const KEYBOARD_NAVIGATION_GUIDE_MESSAGE =\n  'When autocomplete results are available use up and down arrows to review and enter to select. Touch device users, explore by touch or with swipe gestures.';\n\nexport const NO_SEARCH_RESULTS_MESSAGE = 'No search results.';\n\nexport const getSuggestionSelectedMessage = (\n  address: string,\n  numberOfResults: number,\n  currentIndex: number\n): string =>\n  `${numberOfResults} ${\n    numberOfResults === 1 ? 'result is' : 'results are'\n  } available. ${address}. ${currentIndex} of ${numberOfResults} is selected.`;\n\nexport const getSuggestionsReadyMessage = (numberOfResults: number): string =>\n  `${numberOfResults} ${\n    numberOfResults === 1 ? 'result is' : 'results are'\n  } available. Use up and down arrows to review and enter to select. Touch device users, explore by touch or with swipe gestures.`;\n","import {\n  AddressAutofillSuggestion,\n  GeocodingFeature,\n  SearchBoxSuggestion\n} from '@mapbox/search-js-core';\nimport {\n  getSuggestionSelectedMessage,\n  getSuggestionsReadyMessage,\n  KEYBOARD_NAVIGATION_GUIDE_MESSAGE,\n  LENGTH_MESSAGE,\n  NO_SEARCH_RESULTS_MESSAGE\n} from './messages';\n/**\n * This is to make sure our custom \"buttons\" have appropriate\n * keyboard controls for WAI-ARIA.\n *\n * Reference: https://www.w3.org/TR/wai-aria-practices-1.1/#keyboard-interaction-3\n */\nexport function ariaButtonKeyDown(e: KeyboardEvent): void {\n  const el = e.currentTarget as HTMLElement;\n\n  if (e.key === ' ' || e.key === 'Enter') {\n    e.preventDefault();\n    e.stopPropagation();\n\n    // Simulate a click event.\n    el.dispatchEvent(\n      new MouseEvent('click', {\n        bubbles: true,\n        composed: true\n      })\n    );\n  }\n}\n\nconst ARIA_DESCRIPTION_ID = 'search-listbox__description';\n\n/**\n * Builds element that may contain different messages for VoiceOver utilities.\n * The element has necessary aria-* specific attributes and visually hidden.\n */\nexport const createAriaLiveElement = (seed: string): HTMLDivElement => {\n  const container = document.createElement('div');\n  container.setAttribute('aria-live', 'polite');\n  container.setAttribute('aria-atomic', 'true');\n  container.setAttribute('role', 'status');\n  container.setAttribute(\n    'style',\n    'border: 0px;clip: rect(0px, 0px, 0px, 0px);height: 1px;margin-bottom: -1px;margin-right: -1px;overflow: hidden;padding: 0px;position: absolute;white-space: nowrap;width: 1px;'\n  );\n\n  const description = document.createElement('div');\n  description.setAttribute('id', `${seed}--${ARIA_DESCRIPTION_ID}`);\n\n  container.appendChild(description);\n\n  return container;\n};\n\nexport const setLiveRegionMessage = (message: string, seed: string): void => {\n  const description: HTMLInputElement =\n    document.body.querySelector(`[id=\"${seed}--${ARIA_DESCRIPTION_ID}\"]`) ??\n    null;\n  if (description) {\n    description.textContent = message;\n  }\n};\n\n/**\n * Adds special parameters to form input to avoid password managers from trigger it's autocompletion on our field.\n * @param input\n */\nexport const suppressExtensionsAutocomplete = (\n  input: HTMLInputElement\n): void => {\n  // 1Password password manager fix https://1password.community/discussion/comment/606453/#Comment_606453\n  input.name = input.name + ' address-search';\n  // LastPass password manager fix https://support.lastpass.com/help/how-do-i-prevent-fields-from-being-filled-automatically\n  input.setAttribute('data-lpignore', 'true');\n};\n\n/**\n * Calculates the message for autofill component to be announced by VoiceOver utilities depending on its state.\n * @example\n * \"Type in 2 or more characters for results.\" (When input text length is less than 2 characters)\n */\nexport const getAriaMessage = (\n  searchValue: string,\n  suggestions: (\n    | SearchBoxSuggestion\n    | AddressAutofillSuggestion\n    | GeocodingFeature\n  )[],\n  selectedIndex: number | undefined\n): string => {\n  let ariaMessage = null;\n\n  const noResults = !suggestions || suggestions.length === 0;\n\n  if (searchValue?.length < 2) {\n    ariaMessage = LENGTH_MESSAGE + ' ' + KEYBOARD_NAVIGATION_GUIDE_MESSAGE;\n  } else if (noResults) {\n    ariaMessage = NO_SEARCH_RESULTS_MESSAGE;\n  } else if (selectedIndex !== undefined) {\n    const suggestion = suggestions[selectedIndex];\n    const placeName =\n      (suggestion as SearchBoxSuggestion).name ||\n      (suggestion as AddressAutofillSuggestion).feature_name ||\n      (suggestion as GeocodingFeature).properties.name;\n\n    ariaMessage = getSuggestionSelectedMessage(\n      placeName,\n      suggestions.length,\n      selectedIndex + 1\n    );\n  } else {\n    ariaMessage = getSuggestionsReadyMessage(suggestions.length);\n  }\n\n  return ariaMessage;\n};\n","import {\n  AddressAutofillSuggestion,\n  GeocodingFeature,\n  SearchBoxSuggestion\n} from '@mapbox/search-js-core';\nimport { SEARCH_SERVICE } from './services';\n\n/**\n * Returns the string from suggestions that meant to be used as first stroke\n * title in search results list for that particular suggestion.\n */\nexport const getSuggestionTitle = (\n  item: SearchBoxSuggestion | AddressAutofillSuggestion | GeocodingFeature,\n  service: SEARCH_SERVICE\n): string => {\n  switch (service) {\n    case SEARCH_SERVICE.AddressAutofill:\n      return (\n        (item as AddressAutofillSuggestion).matching_name ||\n        (item as AddressAutofillSuggestion).feature_name ||\n        (item as AddressAutofillSuggestion).address_line1\n      );\n    case SEARCH_SERVICE.SearchBox:\n      return (item as SearchBoxSuggestion).name;\n    case SEARCH_SERVICE.Geocoding:\n      return (item as GeocodingFeature).properties.name;\n    default:\n      return '';\n  }\n};\n\n/**\n * Returns parsed/formatted description text to show in the second line of an autofill suggestion element\n */\nexport const buildSuggestionDescription = (\n  item: SearchBoxSuggestion | AddressAutofillSuggestion | GeocodingFeature,\n  service: SEARCH_SERVICE\n): string => {\n  switch (service) {\n    case SEARCH_SERVICE.AddressAutofill:\n      return (item as AddressAutofillSuggestion).description;\n    case SEARCH_SERVICE.SearchBox:\n      if ((item as SearchBoxSuggestion).feature_type === 'poi') {\n        // TODO: update this to be street name + place_formatted, once API response is updated\n        return (item as SearchBoxSuggestion).full_address;\n      }\n      return (item as SearchBoxSuggestion).place_formatted;\n    case SEARCH_SERVICE.Geocoding:\n      return (item as GeocodingFeature).properties.place_formatted;\n    default:\n      return '';\n  }\n};\n\n/**\n * Event detail object for the 'input' event.\n */\nexport interface InputEventDetail {\n  /**\n   * The last character (or characters if pasted) that was inputted into the input field.\n   */\n  lastInput: string;\n  /**\n   * The current value of the input field.\n   */\n  inputText: string;\n}\n","import {\n  SearchBoxSuggestion,\n  AddressAutofillSuggestion,\n  GeocodingFeature\n} from '@mapbox/search-js-core';\n\nimport { HTMLScopedElement } from './HTMLScopedElement';\n\nimport { Theme, getThemeCSS, getIcon } from '../theme';\nimport { bindElements, getChildElements } from '../utils/dom';\nimport { Popover, PopoverOptions } from '../utils/popover';\n\nimport style from '../style.css';\nimport { MapboxHTMLEvent } from '../MapboxHTMLEvent';\nimport { MapboxAddressAutofill } from './MapboxAddressAutofill';\nimport { AddressAutofillInstance } from '../autofill';\nimport { getAriaMessage, setLiveRegionMessage } from '../utils/aria';\nimport { LISTBOX_TEMPLATE, LISTBOX_SUGGESTION_TEMPLATE } from '../constants';\nimport {\n  InputEventDetail,\n  buildSuggestionDescription,\n  getSuggestionTitle\n} from '../utils/listbox';\nimport { SEARCH_SERVICE } from '../utils/services';\n\nfunction getAriaIdForSuggestion(resultListId: string, i: number): string {\n  return `${resultListId}-${i}`;\n}\n\ntype Binding = {\n  /**\n   * Wrapper around the entire component.\n   */\n  MapboxSearch: HTMLElement;\n  /**\n   * Results container, which contains:\n   * - {@link ResultsList}\n   * - {@link Label}\n   * - Attribution.\n   */\n  Results: HTMLDivElement;\n  /**\n   * Exposed as a listbox to assistive technologies.\n   */\n  ResultsList: HTMLUListElement;\n  /**\n   * Exposed as a label.\n   *\n   * Visually hidden but can \"announce\" the current selection to\n   * assistive technologies.\n   */\n  Label: HTMLDivElement;\n};\n\n/**\n * Event detail object for the `select` event.\n */\nexport type SelectionEventDetail<Suggestion> = {\n  suggestion: Suggestion;\n  selectedIndex: number;\n};\n\ntype ListboxEventTypes<Suggestion> = {\n  /**\n   * Triggered on `input` events, i.e. typing  in the `<input>` element.\n   */\n  input: MapboxHTMLEvent<InputEventDetail>;\n  /**\n   * Triggered on selection events, i.e. clicking on an item in the results list\n   * or hitting `Enter` with an item highlighted.\n   */\n  select: MapboxHTMLEvent<SelectionEventDetail<Suggestion>>;\n  /**\n   * Triggered on `blur` event, i.e. focus moves away from the `<input>` element.\n   */\n  blur: MapboxHTMLEvent<unknown>;\n  /**\n   * Triggered on `focus` evenet, i.e. focus moves onto the `<input>` element.\n   */\n  focus: MapboxHTMLEvent<unknown>;\n};\n\nexport class MapboxSearchListbox<\n  Suggestion extends\n    | SearchBoxSuggestion\n    | AddressAutofillSuggestion\n    | GeocodingFeature\n> extends HTMLScopedElement<ListboxEventTypes<Suggestion>> {\n  protected override get template(): HTMLTemplateElement {\n    return LISTBOX_TEMPLATE;\n  }\n\n  protected override get templateStyle(): string {\n    return style;\n  }\n\n  protected get templateUserStyle(): string {\n    return getThemeCSS('.MapboxSearch', this.theme);\n  }\n\n  /**\n   * The current list of suggestions to be rendered in the results box.\n   */\n  suggestions: Suggestion[] | null = null;\n\n  /**\n   * The Address Autofill instance driving the listbox.\n   * Can be either the custom element or function.\n   */\n  autofillHost?: MapboxAddressAutofill | AddressAutofillInstance;\n\n  #popover: Popover | null = null;\n\n  #binding: Binding;\n\n  #labelID: string;\n  #resultListID: string;\n\n  #inputInternal: HTMLInputElement | null;\n\n  dataSeed: string;\n\n  get input(): HTMLInputElement | null {\n    return this.#inputInternal;\n  }\n\n  set input(newInput: HTMLInputElement | null) {\n    const oldInput = this.#inputInternal;\n\n    if (oldInput) {\n      oldInput.removeEventListener('input', this.#handleInput);\n      oldInput.removeEventListener('focus', this.#handleFocus);\n      oldInput.removeEventListener('blur', this.#handleBlur);\n      oldInput.removeEventListener('keydown', this.#handleKeyDown);\n\n      if (this.#popover) {\n        this.#popover.destroy();\n      }\n    }\n\n    if (newInput) {\n      newInput.addEventListener('input', this.#handleInput);\n      newInput.addEventListener('focus', this.#handleFocus);\n      newInput.addEventListener('blur', this.#handleBlur);\n      newInput.addEventListener('keydown', this.#handleKeyDown);\n\n      // Set ARIA role and attributes.\n      newInput.setAttribute('role', 'combobox');\n      newInput.setAttribute('aria-autocomplete', 'list');\n      newInput.setAttribute('aria-controls', this.#resultListID);\n\n      if (this.isConnected) {\n        this.#popover = new Popover(\n          newInput,\n          this.#binding.Results,\n          this.popoverOptions\n        );\n      }\n    }\n\n    this.#inputInternal = newInput;\n  }\n\n  #searchService = null;\n\n  get searchService(): SEARCH_SERVICE | null {\n    return this.#searchService;\n  }\n\n  set searchService(service: SEARCH_SERVICE) {\n    this.#searchService = service;\n  }\n\n  #selectedIndexInternal = undefined;\n\n  get selectedIndex(): number | undefined {\n    return this.#selectedIndexInternal;\n  }\n\n  set selectedIndex(newIndex: number) {\n    const oldIndex = this.#selectedIndexInternal;\n    this.#selectedIndexInternal = newIndex;\n\n    // Update accessibility flags.\n    const { ResultsList } = this.#binding;\n\n    const id = getAriaIdForSuggestion(this.#resultListID, newIndex);\n\n    if (newIndex !== undefined) {\n      this.input.setAttribute('aria-activedescendant', id);\n      ResultsList.setAttribute('aria-activedescendant', id);\n    } else {\n      this.input.removeAttribute('aria-activedescendant');\n      ResultsList.removeAttribute('aria-activedescendant');\n    }\n\n    // Update the selected suggestion.\n    if (oldIndex !== newIndex) {\n      const oldId = getAriaIdForSuggestion(this.#resultListID, oldIndex);\n      const oldEl = ResultsList.querySelector(`#${oldId}`);\n      oldEl?.removeAttribute('aria-selected');\n      oldEl?.setAttribute('tabindex', '-1');\n\n      if (newIndex !== undefined) {\n        const el = ResultsList.querySelector(`#${id}`) as HTMLElement;\n        el?.setAttribute('aria-selected', 'true');\n        el?.setAttribute('tabindex', '0');\n        // TODO: uncomment after moving hideResults logic out from handleBlur and delete aria-activedescendant logic\n        // el?.focus();\n      }\n    }\n\n    this.renderAriaMessage();\n  }\n\n  #showResults(): void {\n    if (!this.suggestions || !this.suggestions.length) {\n      return;\n    }\n\n    const { Results, MapboxSearch } = this.#binding;\n\n    // Calculate width, enable display\n    const rect = this.input.getBoundingClientRect();\n    MapboxSearch.style.setProperty('--width', `${rect.width}px`);\n    MapboxSearch.style.setProperty('display', 'block');\n\n    // Update accessibility flags.\n    this.input.setAttribute('aria-expanded', 'true');\n    Results.removeAttribute('aria-hidden');\n    // Reset selected index.\n    this.selectedIndex = undefined;\n  }\n\n  hideResults(): void {\n    const { Results, ResultsList } = this.#binding;\n\n    // Update accessibility flags.\n    Results.setAttribute('aria-hidden', 'true');\n    this.input.setAttribute('aria-expanded', 'false');\n    ResultsList.removeAttribute('aria-activedescendant');\n    this.input.removeAttribute('aria-activedescendant');\n  }\n\n  renderItem(i: number): HTMLElement {\n    const element = this.prepareTemplate(LISTBOX_SUGGESTION_TEMPLATE);\n    element.id = getAriaIdForSuggestion(this.#resultListID, i);\n\n    return element;\n  }\n\n  fillItem(\n    el: Element,\n    item: Suggestion,\n    i: number,\n    totalLength: number\n  ): void {\n    const iconEl = el.querySelector('[class$=\"SuggestionIcon\"]');\n    const nameEl = el.querySelector('[class$=\"SuggestionName\"]');\n    const descriptionEl = el.querySelector('[class$=\"SuggestionDesc\"]');\n\n    // For Autofill suggestions, use 'accuracy' property to generate icon\n    if (this.searchService === SEARCH_SERVICE.AddressAutofill) {\n      iconEl.innerHTML = getIcon(\n        (item as AddressAutofillSuggestion).accuracy === 'street'\n          ? 'street'\n          : 'addressMarker',\n        this.theme\n      );\n      iconEl.removeAttribute('aria-hidden');\n    } else {\n      iconEl.setAttribute('aria-hidden', 'true');\n    }\n\n    // reset previous values\n    nameEl.textContent = descriptionEl.textContent = '';\n\n    nameEl.textContent = getSuggestionTitle(item, this.searchService);\n\n    descriptionEl.textContent = buildSuggestionDescription(\n      item,\n      this.searchService\n    );\n\n    if (i === this.selectedIndex) {\n      el.setAttribute('aria-selected', 'true');\n    } else {\n      el.removeAttribute('aria-selected');\n    }\n\n    el.setAttribute('aria-posinset', (i + 1).toString());\n    el.setAttribute('aria-setsize', totalLength.toString());\n  }\n\n  #renderResultsList(): void {\n    const { ResultsList } = this.#binding;\n\n    if (!this.suggestions || !this.suggestions.length) {\n      // Speed optimization?\n      ResultsList.innerHTML = '';\n      this.hideResults();\n      return;\n    }\n\n    /**\n     * Make sure we have the correct number of nodes.\n     */\n    const elements = getChildElements(ResultsList);\n    // Too few, add any we're missing.\n    if (this.suggestions.length > elements.length) {\n      for (let i = elements.length; i < this.suggestions.length; i++) {\n        const item = this.renderItem(i);\n        elements.push(item);\n\n        // Setup selected index listener.\n        item.onmouseenter = () => {\n          this.selectedIndex = i;\n        };\n        item.onmouseleave = () => {\n          this.selectedIndex = undefined;\n        };\n\n        ResultsList.appendChild(item);\n      }\n    }\n\n    // Too many, remove any we're not using anymore.\n    if (this.suggestions.length < elements.length) {\n      for (let i = this.suggestions.length; i < elements.length; i++) {\n        elements[i].remove();\n      }\n    }\n\n    /**\n     * Fill out DOM nodes with our data.\n     */\n    for (let i = 0; i < this.suggestions.length; i++) {\n      const suggestion = this.suggestions[i];\n      const element = elements[i];\n\n      this.fillItem(element, suggestion, i, this.suggestions.length);\n      // Override 'onclick' for autofill.\n      element.onclick = () => {\n        this.#handleSelect(suggestion, i);\n      };\n    }\n  }\n\n  #themeInternal: Theme = {};\n\n  get theme(): Theme {\n    return this.#themeInternal;\n  }\n\n  set theme(theme: Theme) {\n    this.#themeInternal = theme;\n\n    if (!this.#binding || !theme) {\n      return;\n    }\n\n    this.updateTemplateUserStyle(getThemeCSS('.MapboxSearch', theme));\n  }\n\n  #popoverOptions: Partial<PopoverOptions> = {};\n\n  get popoverOptions(): Partial<PopoverOptions> {\n    return this.#popoverOptions;\n  }\n\n  set popoverOptions(newOptions: Partial<PopoverOptions>) {\n    this.#popoverOptions = newOptions;\n    if (this.#popover) {\n      this.#popover.options = newOptions;\n      this.#popover.update();\n    }\n  }\n\n  #handleInput = (e: InputEvent): void => {\n    // Prevent duping requests.\n    const { Results } = this.#binding;\n    const input = e.target as HTMLInputElement;\n\n    if (input.dataset['mapboxSuccess']) {\n      delete input.dataset['mapboxSuccess'];\n      return;\n    }\n\n    const searchText = input.value;\n\n    this.renderAriaMessage();\n\n    // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-busy\n    Results.setAttribute('aria-busy', 'true');\n\n    this.dispatchEvent(\n      new MapboxHTMLEvent<InputEventDetail>('input', {\n        lastInput: e.data,\n        inputText: searchText\n      })\n    );\n  };\n\n  renderAriaMessage = (): void => {\n    const message = getAriaMessage(\n      this.input?.value,\n      this.suggestions,\n      this.selectedIndex\n    );\n    setLiveRegionMessage(message, this.dataset.seed);\n  };\n\n  clearAriaMessage = (): void => {\n    setLiveRegionMessage('', this.dataset.seed);\n  };\n\n  /**\n   * Handles the rendering of suggestion items returned from the input text search.\n   * @param suggestions Array of suggestions or features returned from the search\n   */\n  handleSuggest = (suggestions: Suggestion[]): void => {\n    this.suggestions = suggestions;\n\n    if (!suggestions || suggestions.length === 0) {\n      this.renderAriaMessage();\n    }\n\n    if (!suggestions) {\n      this.hideResults();\n      return;\n    }\n\n    this.#renderResultsList();\n    if (suggestions.length) {\n      this.#showResults();\n    }\n\n    const { Results } = this.#binding;\n    // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-busy\n    Results.setAttribute('aria-busy', 'false');\n  };\n\n  /**\n   * Handles the results box rendering when an error has occurred.\n   */\n  handleError = (): void => {\n    const { Results } = this.#binding;\n    // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-busy\n    Results.setAttribute('aria-busy', 'false');\n\n    this.hideResults();\n  };\n\n  #handleSelect = async (\n    suggestion: Suggestion,\n    selectedIndex: number\n  ): Promise<void> => {\n    // set mapboxSuccess to 'true'\n    const input = this.input;\n    if (input) {\n      input.dataset['mapboxSuccess'] = 'true';\n    }\n\n    const payload: SelectionEventDetail<Suggestion> = {\n      suggestion,\n      selectedIndex\n    };\n\n    this.dispatchEvent(new MapboxHTMLEvent('select', payload));\n\n    this.hideResults();\n  };\n\n  #handleFocus = (): void => {\n    const input = this.input;\n    delete input.dataset['mapboxSuccess'];\n\n    this.dispatchEvent(new MapboxHTMLEvent('focus'));\n    this.renderAriaMessage();\n    this.#showResults();\n  };\n\n  #handleBlur = (): void => {\n    // See if we're the target.\n    if (document.activeElement === this.input) {\n      return;\n    }\n\n    this.dispatchEvent(new MapboxHTMLEvent('blur'));\n    this.clearAriaMessage();\n  };\n\n  #handleFocusOut = (event: FocusEvent): void => {\n    // Only trigger when focus moves outside the Listbox container\n    if (!this.#binding.MapboxSearch.contains(event.relatedTarget as Node)) {\n      this.hideResults();\n    }\n  };\n\n  handleArrowUp = (): void => {\n    if (this.selectedIndex === undefined) {\n      this.selectedIndex = this.suggestions.length - 1;\n    } else if (this.selectedIndex === 0) {\n      this.selectedIndex = undefined;\n    } else {\n      this.selectedIndex = Math.max(0, this.selectedIndex - 1);\n    }\n  };\n\n  handleArrowDown = (): void => {\n    if (this.selectedIndex === undefined) {\n      this.selectedIndex = 0;\n    } else if (this.selectedIndex === this.suggestions.length - 1) {\n      this.selectedIndex = undefined;\n    } else {\n      this.selectedIndex = Math.min(\n        this.selectedIndex + 1,\n        this.suggestions.length - 1\n      );\n    }\n  };\n\n  #handleKeyDown = (e: KeyboardEvent): void => {\n    if (!this.suggestions?.length) return;\n\n    if (e.key === 'ArrowDown') {\n      e.preventDefault();\n      this.handleArrowDown();\n      return;\n    }\n\n    if (e.key === 'ArrowUp') {\n      e.preventDefault();\n      this.handleArrowUp();\n      return;\n    }\n\n    if (e.key === 'Escape') {\n      this.hideResults();\n      return;\n    }\n\n    if (this.selectedIndex === undefined) {\n      return;\n    }\n\n    if (e.key === 'Enter') {\n      e.preventDefault();\n      this.#handleSelect(\n        this.suggestions[this.selectedIndex],\n        this.selectedIndex\n      );\n      return;\n    }\n  };\n\n  override connectedCallback(): void {\n    super.connectedCallback();\n\n    this.dataSeed = this.dataset.seed;\n\n    this.#labelID = this.dataset.seed + '-Label';\n    this.#resultListID = this.dataset.seed + '-ResultsList';\n\n    if (this.input) {\n      this.input.setAttribute('aria-controls', this.#resultListID);\n    }\n\n    this.#binding = bindElements<Binding>(this, {\n      MapboxSearch: '.MapboxSearch',\n      Results: '.Results',\n      ResultsList: '.ResultsList',\n      Label: '.Label'\n    });\n\n    const { Results, ResultsList, Label } = this.#binding;\n\n    Label.id = this.#labelID;\n    ResultsList.id = this.#resultListID;\n    ResultsList.setAttribute('aria-labelledby', this.#labelID);\n\n    Results.addEventListener('focusout', this.#handleFocusOut);\n\n    if (!this.#popover && this.input) {\n      this.#popover = new Popover(\n        this.input,\n        this.#binding.Results,\n        this.popoverOptions\n      );\n    }\n\n    // Update popover on next frame.\n    requestAnimationFrame(() => {\n      if (this.#popover) {\n        this.#popover.update();\n      }\n    });\n  }\n\n  disconnectedCallback(): void {\n    // Make sure to unbind input listeners.\n    this.input = null;\n\n    const { Results } = this.#binding;\n    Results.removeEventListener('focusout', this.#handleFocusOut);\n\n    if (this.#popover) this.#popover.destroy();\n  }\n\n  focus(): void {\n    // Refire the event internally, in case we missed it\n    // and the end user is trying to replay it.\n    if (document.activeElement === this.input) {\n      this.#handleFocus();\n    } else {\n      this.input.focus();\n    }\n  }\n\n  blur(): void {\n    this.input.blur();\n  }\n\n  updatePopover(): void {\n    if (this.#popover) {\n      this.#popover.update();\n    }\n  }\n}\n\ndeclare global {\n  interface Window {\n    MapboxSearchListbox: typeof MapboxSearchListbox;\n  }\n}\n\nwindow.MapboxSearchListbox = MapboxSearchListbox;\n\nif (!window.customElements.get('mapbox-search-listbox')) {\n  customElements.define('mapbox-search-listbox', MapboxSearchListbox);\n}\n","import {\n  AddressAutofillFeatureSuggestion,\n  AddressAutofillSuggestion,\n  featureToSuggestion\n} from '@mapbox/search-js-core';\nimport { InputFormElement, isVisible, setValue } from './dom';\nimport { SEARCH_SERVICE } from './services';\nimport { getSuggestionTitle } from './listbox';\n\n/**\n * A list of WHATWG autofill tokens relevant to addresses. These will be used to\n * set the `autocomplete` attribute on the input element.\n *\n * Reference: https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute\n */\ntype AutofillTokens =\n  | 'street-address'\n  | 'address-line1'\n  | 'address-line2'\n  | 'address-line3'\n  | 'address-level4'\n  | 'address-level3'\n  | 'address-level2'\n  | 'address-level1'\n  | 'country'\n  | 'country-name'\n  | 'postal-code';\n\nexport const AUTOFILL_TOKENS = new Set<AutofillTokens>([\n  'street-address',\n  'address-line1',\n  'address-line2',\n  'address-line3',\n  'address-level4',\n  'address-level3',\n  'address-level2',\n  'address-level1',\n  'country',\n  'country-name',\n  'postal-code'\n]);\n\n/**\n * A list of WHATWG autofill tokens we can safely ignore when traversing\n * `autocomplete` attributes.\n */\nconst AUTOFILL_SKIP_TOKENS = new Set(['off', 'on', 'true', 'false']);\n\n/**\n * Finds the parent form element of the given element, if any.\n *\n * @returns The parent form element, or `null` if none was found.\n */\nexport function findParentForm(el: Element): HTMLFormElement | null {\n  let node = el.parentNode;\n  while (node) {\n    if (node instanceof HTMLFormElement) {\n      return node;\n    }\n    node = node.parentNode;\n  }\n\n  return null;\n}\n\n/**\n * Finds input elements that are eligible to be used for Address Autofill.\n * Eligible inputs include those with standard WHATWG autocomplete attribute values, either 'address-line1' or 'street-address'\n * @param form - If specified, searches within the given form instead of the whole document\n * @returns Array of input elements\n */\nexport function findAddressInputs(form?: HTMLFormElement): HTMLInputElement[] {\n  const parent = form || document;\n  return Array.from(\n    parent.querySelectorAll<HTMLInputElement>(\n      'input[autocomplete~=\"address-line1\"], input[autocomplete~=\"street-address\"]'\n    )\n  );\n}\n\nconst SECTION = 'section-';\n\nconst SECTION_DEFAULT = 'section-default';\nconst SECTION_SHIPPING = 'section-shipping';\nconst SECTION_BILLING = 'section-billing';\n\ntype FormStructure = {\n  input: InputFormElement;\n  section: string;\n  field: AutofillTokens;\n}[];\n\n/**\n * Implementation of \"autocomplete\" {@link FormStructure} that matches the\n * WHATWG spec and somewhat Chromium.\n *\n * `billing` and `shipping` are treated as special sections. The {@link SECTION_SHIPPING}\n * and {@link SECTION_BILLING} symbols are used to identify them.\n *\n * Any inputs without an `autocomplete` attribute are skipped.\n *\n * Reference: https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill\n * Reference: https://github.com/chromium/chromium/blob/18a1302acbf920bc692ec6bd986cacd41ae9c25c/components/autofill/core/browser/form_structure.cc#L1503\n */\nexport function parseFormStructure(form: HTMLFormElement): FormStructure {\n  const inputs = Array.from(\n    form.querySelectorAll<InputFormElement>('[autocomplete]')\n  ).filter((el) => {\n    const tagName = el.tagName.toLowerCase();\n    return (\n      tagName === 'input' || tagName === 'select' || tagName === 'textarea'\n    );\n  });\n\n  const res: FormStructure = [];\n\n  for (const input of inputs) {\n    if (!isVisible(input)) {\n      continue;\n    }\n\n    // Note: HTML <input> element has an HTMLInputElement.autocomplete reflection\n    // property, but <select> elements do not.\n    //\n    // This does **not** mean that autocomplete properties are not valid on\n    // selects. I verified this on a popular e-commerce checkout page.\n    const autocomplete = input.getAttribute('autocomplete') || '';\n    if (!autocomplete || AUTOFILL_SKIP_TOKENS.has(autocomplete)) {\n      continue;\n    }\n\n    const tokens = autocomplete.toLowerCase().split(' ');\n\n    // The tokens are parsed in reverse order. The expected pattern is:\n    // [section-*] [shipping|billing] [type_hint] field_type\n\n    // Address tokens can be a maximum length of 3. We don't need to check [type_hint].\n    if (tokens.length > 3) {\n      continue;\n    }\n\n    // The last token should be a part of our scheme.\n    const field = tokens[tokens.length - 1] as AutofillTokens;\n    if (!AUTOFILL_TOKENS.has(field)) {\n      continue;\n    }\n    tokens.pop();\n\n    let section: symbol | string = SECTION_DEFAULT;\n\n    // The second to last token /could/ be 'shipping' or 'billing'.\n    if (tokens.length) {\n      const sectionToken = tokens[tokens.length - 1];\n\n      if (sectionToken === 'shipping') {\n        section = SECTION_SHIPPING;\n        tokens.pop();\n      }\n\n      if (sectionToken === 'billing') {\n        section = SECTION_BILLING;\n        tokens.pop();\n      }\n    }\n\n    // The remaining tokens could be a section.\n    if (tokens.length) {\n      const sectionToken = tokens[tokens.length - 1];\n      if (sectionToken.startsWith(SECTION)) {\n        section = sectionToken;\n      }\n    }\n\n    res.push({\n      input,\n      section,\n      field\n    });\n  }\n\n  return res;\n}\n\nexport type AutofillInputMap = { [key in AutofillTokens]?: InputFormElement };\n/**\n * Object mapping WHATWG autocomplete attribute values to corresponding address component strings.\n *\n * @typedef AutofillValueMap\n * @example\n * ```typescript\n * {\n *   \"street-address\"?: string;\n *   \"address-line1\"?: string;\n *   \"address-line2\"?: string;\n *   \"address-line3\"?: string;\n *   \"address-level4\"?: string;\n *   \"address-level3\"?: string;\n *   \"address-level2\"?: string;\n *   \"address-level1\"?: string;\n *   country?: string;\n *   \"country-name\"?: string;\n *   \"postal-code\"?: string;\n * }\n * ```\n */\nexport type AutofillValueMap = { [key in AutofillTokens]?: string };\n\n/**\n * Reference: [chromium.md](../../../../docs/search_js_web/chromium.md)\n *\n * Implementation of autofill that closely matches Chromium, with a few noted differences:\n *\n * 1. There is no hueristic for inferring a match, so the\n *    WHATWG \"autocomplete\" attribute is required.\n * 2. This parser, unlike Chromium, doesn't allow more than one token type per\n *    section. Chromium **only** allows this if they are in the same order.\n */\nexport function findAddressAutofillInputs(\n  form: HTMLFormElement,\n  ref: HTMLInputElement\n): AutofillInputMap {\n  // Use an array-of-structs to improve performance.\n  // Reference: https://en.wikipedia.org/wiki/AoS_and_SoA#:~:text=Structure%20of%20arrays%20(SoA)%20is,one%20parallel%20array%20per%20field.\n  const logicalSections: AutofillInputMap[] = [];\n  const logicalSectionSections: (string | symbol)[] = [];\n\n  // Parse the form structure, then go through each node to create\n  // logical sections.\n  const formStructure = parseFormStructure(form);\n\n  // When we traverse through the form structure, we can check the input against\n  // ref to find the logical section we actually want.\n  let foundSection: AutofillInputMap = null;\n\n  for (const { input, section, field } of formStructure) {\n    let lastIndex = logicalSections.length - 1;\n\n    // 1. If we have no logical sections, create a new section.\n    // 2. If the current section is different from the last section, create a new section.\n    // 3. If the current field already exists in the last section, create a new section.\n    let createNewSection = false;\n    if (!logicalSections.length) {\n      createNewSection = true;\n    } else if (logicalSectionSections[lastIndex] !== section) {\n      createNewSection = true;\n    } else if (logicalSections[lastIndex][field]) {\n      createNewSection = true;\n    }\n\n    if (createNewSection) {\n      // If we have already found a logical section, creating new sections\n      // just wastes time.\n      if (foundSection) {\n        break;\n      }\n\n      logicalSections.push({\n        [field]: input\n      });\n\n      logicalSectionSections.push(section);\n      // Make sure to update lastIndex.\n      lastIndex++;\n    } else {\n      logicalSections[lastIndex][field] = input;\n    }\n\n    if (input === ref) {\n      foundSection = logicalSections[lastIndex];\n    }\n  }\n\n  return foundSection ?? {};\n}\n\n/**\n * Fills in the address form using HTML autocomplete attributes.\n *\n * This does a mapping from {@link SearchBoxAdministrativeUnitTypes} to corresponding WHATWG autocomplete types.\n *\n * Reference:\n * https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete#values\n * https://docs.mapbox.com/api/search/search-box/#administrative-unit-types\n */\nexport function setFormAutofillValues(\n  form: HTMLFormElement,\n  ref: HTMLInputElement,\n  suggestion: AddressAutofillSuggestion\n): void {\n  // Find the inputs that we should fill in.\n  const map = findAddressAutofillInputs(form, ref);\n\n  const streetAddress = [\n    suggestion.address_line1,\n    suggestion.address_line2,\n    suggestion.address_line3\n  ]\n    .filter((part) => Boolean(part))\n    .join(', ');\n\n  setValue(\n    map['street-address'],\n    map['address-line2'] ? suggestion.address_line1 || '' : streetAddress\n  );\n  setValue(map['address-line1'], suggestion.address_line1 || '');\n  setValue(map['address-line2'], suggestion.address_line2 || '');\n\n  setValue(map['address-level1'], suggestion.address_level1 || '');\n  setValue(map['address-level2'], suggestion.address_level2 || '');\n  setValue(map['address-level3'], suggestion.address_level3 || '');\n\n  // Country in WHATWG refers to the country code, not the name.\n  // Example: 'jp' instead of 'Japan'.\n\n  // Note: Make sure to match case here. The country code is lower-case.\n  const countryCode =\n    suggestion.country_code || suggestion.metadata?.iso_3166_1 || '';\n  if (map.country && map.country instanceof HTMLSelectElement) {\n    let firstOption = map.country.querySelector(`option`).value;\n    if (firstOption === '') {\n      // First option was an empty string placeholder, use the second option\n      firstOption = map.country.querySelectorAll(`option`)[1].value;\n    }\n    const isUpperCase = firstOption === firstOption.toUpperCase();\n\n    setValue(\n      map['country'],\n      isUpperCase ? countryCode.toUpperCase() : countryCode\n    );\n  } else {\n    setValue(map['country'], countryCode);\n  }\n\n  setValue(map['country-name'], suggestion.country || '');\n  setValue(map['postal-code'], suggestion.postcode || '');\n}\n\n/**\n * Gets the current input values for address fields given a form and a reference input.\n *\n * @param form - HTML form that includes the autocomplete-compliant input fields\n * @param ref - An input element within the desired form address section\n * @returns A object mapping WHATWG autocomplete properties to their respective form field values\n *\n * @example\n * ```typescript\n * const form = document.querySelector(form);\n * const input = form.querySelector('input[autocomplete~=\"street-address\"]')\n * const valueMap = getFormAutofillValues(form, input);\n * console.log(valueMap);\n * // {\n * //   \"street-address\": \"123 Main\",\n * //   \"address-level2\": \"Boston\",\n * //   \"address-level1\": \"MA\",\n * //   \"postal-code\": \"02129\"\n * // }\n * ```\n */\nexport function getFormAutofillValues(\n  form: HTMLFormElement,\n  ref: HTMLInputElement\n): AutofillValueMap {\n  const map = findAddressAutofillInputs(form, ref);\n  const values: AutofillValueMap = {};\n  for (const [key, input] of Object.entries(map)) {\n    if (input?.value) {\n      values[key] = input.value;\n    }\n  }\n\n  return values;\n}\n\n/**\n * Converts an {@link AutofillValueMap} to a single line, suitable for\n * display in a text field.\n *\n * @param snapshot - An object mapping WHATWG autocomplete attribute values to their corresponding input field values\n * @returns A concatenated address string\n *\n * @example\n * ```typescript\n * const values = {\n *   'street-address': '123 Main St',\n *   'address-level1': 'CA',\n *   'address-level2': 'San Francisco',\n *   'address-level3': '',\n * };\n *\n * const searchText = getAutofillSearchText(values);\n * console.log(searchText); // '123 Main St, San Francisco, CA'\n * ```\n */\nexport function getAutofillSearchText(snapshot: AutofillValueMap): string {\n  const searchText = [];\n\n  if (snapshot['street-address']) {\n    searchText.push(snapshot['street-address']);\n  } else {\n    searchText.push(snapshot['address-line1'] || '');\n  }\n\n  searchText.push(snapshot['address-line2'] || '');\n  searchText.push(snapshot['address-line3'] || '');\n\n  searchText.push(snapshot['address-level3'] || '');\n  searchText.push(snapshot['address-level2'] || '');\n  searchText.push(snapshot['address-level1'] || '');\n  searchText.push(snapshot['postal-code'] || '');\n\n  if (snapshot['country-name']) {\n    searchText.push(snapshot['country-name']);\n  } else {\n    searchText.push(snapshot['country'] || '');\n  }\n\n  return searchText\n    .filter((part) => Boolean(part))\n    .map((part) => part.trim())\n    .join(', ');\n}\n\nexport function fillFormWithFeature(\n  feature: AddressAutofillFeatureSuggestion,\n  input: HTMLInputElement\n): void {\n  const form = findParentForm(input);\n  if (!form) {\n    return;\n  }\n\n  const suggestion = featureToSuggestion(feature);\n  setFormAutofillValues(form, input, suggestion);\n\n  const inputMap = findAddressAutofillInputs(form, input);\n  // TODO: check if suggestion has \"missing_unit\" property true\n  if (inputMap['address-line2'] && !suggestion.address_line2) {\n    inputMap['address-line2'].focus();\n  }\n}\n\n/**\n * Gets address property values from an Autofill feature.\n *\n * @param feature - A {@link AddressAutofillFeatureSuggestion} object.\n * @returns A object mapping WHATWG autocomplete properties to their respective feature values\n */\nexport function featureToAutofillValueMap(\n  feature: AddressAutofillFeatureSuggestion\n): AutofillValueMap {\n  const values: AutofillValueMap = {};\n\n  const streetAddress = [\n    feature.properties.address_line1,\n    feature.properties.address_line2,\n    feature.properties.address_line3\n  ]\n    .filter((part) => Boolean(part))\n    .join(', ');\n\n  values['street-address'] = streetAddress;\n  values['address-line1'] = feature.properties.address_line1;\n  values['address-line2'] = feature.properties.address_line2;\n  values['address-line3'] = feature.properties.address_line3;\n  values['address-level1'] = feature.properties.address_level1;\n  values['address-level2'] = feature.properties.address_level2;\n  values['address-level3'] = feature.properties.address_level3;\n  values['country'] = feature.properties.metadata?.iso_3166_1;\n  values['country-name'] = feature.properties.country;\n  values['postal-code'] = feature.properties.postcode;\n\n  return values;\n}\n\n/**\n * Checks if WHATWG address values from one object match those from another.\n *\n * Can be used to compare an HTML form state against the most recently retrieved Autofill feature\n * to determine if a form has been manually edited after a previous Autofill event.\n *\n * @param targetMap - An {@link AutofillValueMap} object.\n * @param referenceMap - An {@link AutofillValueMap} object.\n * @returns False if all values from the target map are equal to their corresponding value from the reference map.\n */\nexport function checkAutofillValuesChanged(\n  targetMap: AutofillValueMap,\n  referenceMap: AutofillValueMap\n): boolean {\n  for (const [key, value] of Object.entries(targetMap)) {\n    if (referenceMap[key] !== value) return true;\n  }\n  return false;\n}\n\n/**\n * Takes the suggestions array and filters streets inside it to leave only unique ones\n */\nexport const distinctExactStreetResults = (\n  suggestions: AddressAutofillSuggestion[]\n): AddressAutofillSuggestion[] => {\n  return suggestions.filter((item1, idx, arr) => {\n    const title = getSuggestionTitle(item1, SEARCH_SERVICE.AddressAutofill);\n    return (\n      item1.accuracy !== 'street' ||\n      arr.findIndex(\n        (item2) =>\n          title === getSuggestionTitle(item2, SEARCH_SERVICE.AddressAutofill)\n      ) === idx\n    );\n  });\n};\n\nexport const toggleAutocompletion = (\n  input: HTMLInputElement,\n  initialAutocompleteValue: string,\n  enableBrowserAutocomplete: boolean\n): void => {\n  /**\n   * 'new-password' prevents some browsers from suggestion autocompetion including saved addresses, passwords and etc.\n   * https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion#preventing_autofilling_with_autocompletenew-password\n   */\n  const disableValue = 'new-password';\n  const defaultFallbackValue = 'address-line1';\n\n  const autocompleteValue = enableBrowserAutocomplete\n    ? initialAutocompleteValue || defaultFallbackValue\n    : disableValue;\n\n  if (input) {\n    input.autocomplete = autocompleteValue;\n  }\n};\n\nexport const handleStreetSelection = (\n  input: HTMLInputElement,\n  initialAutocompleteValue: string,\n  suggestion: AddressAutofillSuggestion\n): void => {\n  if (!input || !suggestion) {\n    return;\n  }\n\n  // autocomplete attribute is required by fillFormWithFeature method.\n  toggleAutocompletion(input, initialAutocompleteValue, true);\n\n  const feature: AddressAutofillFeatureSuggestion = {\n    properties: {\n      ...suggestion,\n      address_line1: suggestion.address_line1 + ' ',\n      postcode: null\n    }\n  } as any;\n\n  fillFormWithFeature(feature, input);\n\n  // turn off browser autocomplete back\n  toggleAutocompletion(input, initialAutocompleteValue, false);\n\n  input?.focus();\n};\n","import {\n  AddressAutofillFeatureSuggestion,\n  featureToSuggestion\n} from '@mapbox/search-js-core';\nimport { MapboxSearchListboxAutofillType } from './components/MapboxAddressAutofill';\nimport {\n  AddressConfirmOptions,\n  MapboxAddressConfirmation\n} from './components/MapboxAddressConfirmation';\nimport { config } from './config';\n\nimport {\n  featureToAutofillValueMap,\n  findAddressInputs,\n  getFormAutofillValues,\n  checkAutofillValuesChanged,\n  parseFormStructure,\n  setFormAutofillValues,\n  findAddressAutofillInputs\n} from './utils/autofill';\nimport { AddressConfirmShowResult } from './utils/confirmation';\n\nconst confirmation = new MapboxAddressConfirmation();\n\n/**\n * A utility that can be run prior to form submission that allows a user to correct or confirm an address.\n *\n * This parses and compares an address entered into form fields with the closest address suggestion from the Mapbox Address Autofill API.\n * Unless an exact match or a custom comparison callback evaluates to true, the user will be shown a modal dialog\n * asking if they would like to use the suggested address.\n *\n * When a suggested address is accepted, the values are automatically updated in the form fields.\n * @param form - HTML form that includes the autocomplete-compliant input fields\n * @param optionsArg - {@link AddressConfirmOptions} Object defining options for Address Autofill API, UI, form parsing, and address comparison\n * @returns A promise resolving with a result object indicating the decision made by the user\n * @example\n * ```typescript\n * form.addEventListener(\"submit\", async (e) => {\n *   e.preventDefault();\n *   const result = await confirmAddress(form, {\n *     minimap: true,\n *     skipConfirmModal: (feature) =>\n *       ['exact', 'high'].includes(\n *         feature.properties.match_code.confidence\n *       )\n *   });\n *   if (result.type === 'nochange') submitForm();\n * });\n * ```\n */\nexport async function confirmAddress(\n  form: HTMLFormElement,\n  optionsArg: AddressConfirmOptions = {}\n): Promise<AddressConfirmShowResult> {\n  const { sections = [] } = optionsArg;\n\n  if (!confirmation.parentNode) {\n    document.body.appendChild(confirmation);\n  }\n\n  let collectedResult: AddressConfirmShowResult = { type: 'nochange' };\n\n  const inputs = findAddressInputs(form);\n  const structure = parseFormStructure(form);\n\n  const listboxComponents = Array.from(\n    document.querySelectorAll<MapboxSearchListboxAutofillType>(\n      'mapbox-search-listbox'\n    )\n  );\n\n  for (const input of inputs) {\n    // If we have sections, filter by the form structure.\n    if (sections.length) {\n      const structureRef = structure.find((s) => s.input === input);\n      if (!structureRef) {\n        continue;\n      }\n\n      if (!sections.includes(structureRef.section)) {\n        continue;\n      }\n    }\n\n    // Get the form's new autofill values to compare against.\n    const autofillValues = getFormAutofillValues(form, input);\n\n    // Compare form values against the latest Address Autofill snapshot (if any);\n    // If form values have not changed since last snapshot, skip showing confirmation.\n    const listbox = listboxComponents.find((lb) => lb.input === input);\n    const autofill = listbox?.autofillHost;\n    if (autofill) {\n      const lastRetrievedFeature =\n        autofill.retrieveFeature as AddressAutofillFeatureSuggestion;\n      if (lastRetrievedFeature) {\n        const snapshot = featureToAutofillValueMap(lastRetrievedFeature);\n        if (!checkAutofillValuesChanged(autofillValues, snapshot)) {\n          continue;\n        }\n      }\n    }\n\n    // Show the confirmation with the first feature.\n    const accessToken = optionsArg.accessToken || config.accessToken;\n    const result = await confirmation.tryShow(autofillValues, {\n      ...optionsArg,\n      accessToken\n    });\n\n    // If changed, autofill the form.\n    if (result.type === 'change') {\n      const inputMap = findAddressAutofillInputs(form, input);\n      if (inputMap['address-line2']?.value) {\n        // carry over address-line2 if it exists on the form\n        result.feature.properties.address_line2 =\n          inputMap['address-line2'].value;\n      }\n      if (listbox) {\n        // Simulate the feature as if it were retrieved by Address Autofill\n        autofill.simulateRetrieve(result.feature);\n      } else {\n        input.dataset['mapboxSuccess'] = 'true';\n        const suggestion = featureToSuggestion(result.feature);\n        setFormAutofillValues(form, input, suggestion);\n      }\n    }\n\n    // Set to changed if changed and not cancelled.\n    if (result.type === 'change' && collectedResult.type !== 'cancel') {\n      collectedResult = result;\n    }\n\n    // Set to cancelled if cancelled.\n    if (result.type === 'cancel') {\n      collectedResult = result;\n    }\n  }\n\n  return collectedResult;\n}\n","import {\n  MatchCodeConfidence,\n  ValidationOptions,\n  ValidationCore,\n  AddressAutofillFeatureSuggestion\n} from '@mapbox/search-js-core';\nimport noScroll from 'no-scroll';\nimport { createFocusTrap, FocusTrap } from 'focus-trap';\n\nimport { HTMLScopedElement } from './HTMLScopedElement';\nimport { MapboxAddressConfirmationFeature } from './MapboxAddressConfirmationFeature';\nimport { MapboxAddressConfirmationNoFeature } from './MapboxAddressConfirmationNoFeature';\n\nimport { bindElements, createElementFromString } from '../utils/dom';\nimport { AutofillValueMap, getAutofillSearchText } from '../utils/autofill';\nimport { AddressConfirmShowResult } from '../utils/confirmation';\n\nimport { MapboxHTMLEvent } from '../MapboxHTMLEvent';\nimport { getThemeCSS, Theme } from '../theme';\n\nimport style from '../style.css';\nimport { config } from '../config';\nimport { MapboxAddressMinimap } from './MapboxAddressMinimap';\n\n/**\n * Styling and theming options for a {@link MapboxAddressMinimap} embedded inside a confirmation dialog.\n *\n * @typedef ConfirmationMinimapOptions\n * @example\n * ```typescript\n * const result = await confirmAddress(form, {\n *   accessToken: 'abc-123',\n *   minimap: {\n *     defaultMapStyle: ['mapbox', 'outdoors-v11'],\n *     theme: { icons: { marker: MARKER_SVG } },\n *     mapStyleMode: 'default',\n *     satelliteToggle: true\n *   }\n * });\n * ```\n */\nexport type ConfirmationMinimapOptions = Partial<\n  Pick<\n    MapboxAddressMinimap,\n    'defaultMapStyle' | 'theme' | 'mapStyleMode' | 'satelliteToggle'\n  >\n>;\n\n/**\n * Object defining options for Address Autofill API, UI, form parsing, and address comparison\n * @typedef AddressConfirmOptions\n */\nexport interface AddressConfirmOptions {\n  /**\n   * Mapbox access token used for the Address Autofill and Static Image APIs\n   */\n  accessToken?: string;\n  /**\n   * CSS variables and icons\n   */\n  theme?: Theme;\n  /**\n   * Address Autofill API configuration options\n   * {@link ValidationOptions}\n   */\n  options?: Partial<ValidationOptions>;\n  /**\n   * If true, a static minimap showing the suggested address location will be displayed in the modal dialog.\n   * If an object, a minimap will be displayed with the specified styling and theming configuration.\n   * Defaults to false.\n   */\n  minimap?: boolean | ConfirmationMinimapOptions;\n  /**\n   * An array of section names used within form element `autocomplete` attributes to identify and group one address section from another, e.g. \"section-shipping\" or \"section-billing\".\n   * These are often used when a single <form> contains multiple logical sections.\n   * If left undefined, all discoverable sections will be processed.\n   */\n  sections?: string[];\n  /**\n   * A callback used to pre-confirm an address and skip the UI modal.\n   * The feature argument contains all address components, as well as an {@link MatchCode} object,\n   * which are used to express the confidence of an address match.\n   * The callback must return a boolean, with `true` indicating that the address has been pre-confirmed,\n   * and the UI modal will be skipped and will not be presented to the end-user.\n   * If left undefined, this defaults to skipping showing the modal when the validated feature's match code\n   * returns an \"exact\" match.\n   */\n  skipConfirmModal?: (feature: AddressAutofillFeatureSuggestion) => boolean;\n  /**\n   * Custom footer text appearing at the bottom of the confirmation modal dialog.\n   * If `true` or left undefined, the default footer text will be used.\n   * If `false`, the footer will not be shown.\n   */\n  footer?: boolean | string;\n}\n\nconst TEMPLATE = createElementFromString<HTMLTemplateElement>(/* html */ `\n<template>\n  <div class=\"MapboxAddressConfirmation\" aria-hidden=\"true\">\n    <mapbox-address-confirmation-feature class=\"ContentFeature\"></mapbox-address-confirmation-feature>\n    <mapbox-address-confirmation-no-feature class=\"ContentNoFeature\"></mapbox-address-confirmation-no-feature>\n  </div>\n</template>\n`);\n\ntype Binding = {\n  MapboxAddressConfirmation: HTMLDivElement;\n  ContentFeature: MapboxAddressConfirmationFeature;\n  ContentNoFeature: MapboxAddressConfirmationNoFeature;\n};\n\nexport type AddressConfirmationEventTypes = {\n  result: MapboxHTMLEvent<AddressConfirmShowResult['type']>;\n};\n\n/**\n * {@link MapboxAddressConfirmation} is a custom element that\n * will display the \"Did you mean...\" message when the user\n * enters an address that doesn't match any of the results\n * returned by the Mapbox Address Autofill API.\n *\n * This element is used by {@link MapboxAddressAutofill} and the {@link autofill}\n * method, and should not be exposed to the user.\n */\nexport class MapboxAddressConfirmation extends HTMLScopedElement<AddressConfirmationEventTypes> {\n  #show = false;\n\n  #binding: Binding;\n  #focusTrap: FocusTrap | null;\n\n  get template(): HTMLTemplateElement {\n    return TEMPLATE;\n  }\n\n  get templateStyle(): string {\n    return style;\n  }\n\n  get templateUserStyle(): string {\n    return getThemeCSS('.MapboxAddressConfirmation', this.theme);\n  }\n\n  #themeInternal: Theme = {};\n\n  get theme(): Theme {\n    return this.#themeInternal;\n  }\n\n  set theme(theme: Theme) {\n    this.#themeInternal = theme;\n\n    if (!this.#binding || !theme) {\n      return;\n    }\n\n    this.updateTemplateUserStyle(\n      getThemeCSS('.MapboxAddressConfirmation', theme)\n    );\n\n    // Pass theme down into content elements\n    const { ContentFeature, ContentNoFeature } = this.#binding;\n    ContentFeature.theme = theme;\n    ContentNoFeature.theme = theme;\n  }\n\n  connectedCallback(): void {\n    super.connectedCallback();\n\n    this.#binding = bindElements<Binding>(this, {\n      MapboxAddressConfirmation: '.MapboxAddressConfirmation',\n      ContentFeature: '.ContentFeature',\n      ContentNoFeature: '.ContentNoFeature'\n    });\n\n    const { MapboxAddressConfirmation } = this.#binding;\n    MapboxAddressConfirmation.setAttribute('aria-hidden', 'true');\n\n    const theme = this.theme;\n    if (theme) {\n      const { ContentFeature, ContentNoFeature } = this.#binding;\n      ContentFeature.theme = theme;\n      ContentNoFeature.theme = theme;\n    }\n  }\n\n  disconnectedCallback(): void {\n    this.#focusTrap = null;\n  }\n\n  hide(): void {\n    this.#show = false;\n\n    if (!this.#binding) {\n      return;\n    }\n\n    const { MapboxAddressConfirmation } = this.#binding;\n    // Update accessibility flags.\n    MapboxAddressConfirmation.setAttribute('aria-hidden', 'true');\n\n    this.#focusTrap?.deactivate();\n    noScroll.off();\n  }\n\n  async show(\n    autofillValues: AutofillValueMap,\n    optionsArg: AddressConfirmOptions,\n    feature?: AddressAutofillFeatureSuggestion\n  ): Promise<AddressConfirmShowResult> {\n    if (!this.#binding) {\n      return { type: 'cancel' };\n    }\n\n    const { MapboxAddressConfirmation, ContentFeature, ContentNoFeature } =\n      this.#binding;\n\n    const { accessToken, minimap = false, theme, footer } = optionsArg;\n\n    // Update theme in this and child custom elements\n    this.theme = theme;\n\n    // Set content and visibility depending on feature definition\n    if (feature) {\n      ContentFeature.removeAttribute('aria-hidden');\n      ContentNoFeature.setAttribute('aria-hidden', 'true');\n\n      ContentFeature.minimap = minimap;\n      ContentFeature.accessToken = accessToken;\n      ContentFeature.footer = footer;\n\n      ContentFeature.update(feature, autofillValues);\n    } else {\n      ContentFeature.setAttribute('aria-hidden', 'true');\n      ContentNoFeature.removeAttribute('aria-hidden');\n\n      ContentNoFeature.update(autofillValues);\n    }\n\n    this.#show = true;\n\n    // Update accessibility flags.\n    MapboxAddressConfirmation.removeAttribute('aria-hidden');\n\n    noScroll.on();\n\n    const activeContentElement = feature ? ContentFeature : ContentNoFeature;\n\n    this.#focusTrap = createFocusTrap(MapboxAddressConfirmation, {\n      fallbackFocus: activeContentElement,\n      escapeDeactivates: (): boolean => {\n        this.hide();\n        return true;\n      }\n    });\n\n    this.#focusTrap?.activate();\n\n    // Wait for next result event, hide and then return.\n    return new Promise((resolve) => {\n      const eventHost = activeContentElement;\n      const fn = (\n        e: MapboxHTMLEvent<AddressConfirmShowResult['type']>\n      ): void => {\n        eventHost.removeEventListener('result', fn);\n\n        const result = e.detail;\n        this.hide();\n\n        if (result === 'change') {\n          resolve({\n            type: 'change',\n            feature\n          });\n        } else {\n          resolve({\n            type: result\n          });\n        }\n      };\n\n      eventHost.addEventListener('result', fn);\n    });\n  }\n\n  /**\n   * Attempts to show an address confirmation dialog by comparing form input values with the closest match via the Address Autofill API.\n   * @param autofillValues - Map of form `<input>` values for each address component\n   * @param optionsArg - Options object defining API options, UI controls, and callback defining when to bypass the dialog\n   * @returns A promise indicating the action taken from the confirmation dialog\n   */\n  async tryShow(\n    autofillValues: AutofillValueMap,\n    optionsArg: AddressConfirmOptions\n  ): Promise<AddressConfirmShowResult> {\n    if (!this.#binding) {\n      return { type: 'cancel' };\n    }\n\n    const { accessToken, options = {} } = optionsArg;\n\n    const validate = new ValidationCore({\n      accessToken: accessToken,\n      ...options\n    });\n\n    // Get the form's new autofill values to compare against.\n    const searchText = getAutofillSearchText(autofillValues);\n\n    const featureCollection = await validate.validate(searchText, {\n      sessionToken: config.autofillSessionToken\n    });\n\n    const feature = featureCollection.features[0];\n\n    // Pre-validate feature from optional callback, or default to checking for exact match on match_code.\n    // If pre-validated, return \"nochange\" early\n    if (feature) {\n      const defaultValidation = (feature: AddressAutofillFeatureSuggestion) =>\n        feature.properties.match_code.confidence === MatchCodeConfidence.exact;\n      const { skipConfirmModal = defaultValidation } = optionsArg;\n      if (skipConfirmModal(feature)) {\n        return { type: 'nochange' };\n      }\n    }\n\n    return await this.show(autofillValues, optionsArg, feature);\n  }\n}\n\ndeclare global {\n  interface Window {\n    MapboxAddressConfirmation: typeof MapboxAddressConfirmation;\n  }\n}\n\nwindow.MapboxAddressConfirmation = MapboxAddressConfirmation;\n\nif (!window.customElements.get('mapbox-address-confirmation')) {\n  customElements.define(\n    'mapbox-address-confirmation',\n    MapboxAddressConfirmation\n  );\n}\n","import { SessionToken } from '@mapbox/search-js-core';\n\nclass Config {\n  /**\n   * A Mapbox access token used if one is not passed in explicitly to web components\n   */\n  accessToken: string;\n  /**\n   * If true, Address Autofill address or marker location corrections will be submitted to the Mapbox Contribute API to help improve our data accuracy. Defaults to true.\n   */\n  feedbackEnabled = true;\n\n  readonly autofillSessionToken = new SessionToken(); // Shared session token used among Address Autofill-related web components\n  autofillSessionEnabled = false; // True when Address Autofill has been initialized within the current page view\n  detectBrowserAutofillEnabled = false; // True when `initDetectBrowserAutofill` has been called\n}\n\n/**\n * Global configuration singleton object storing settings shared across Search JS Web components.\n *\n * @property {string} accessToken - A [Mapbox access token](https://docs.mapbox.com/help/glossary/access-token/) used if one is not passed in explicitly to web components.\n * @property {boolean} feedbackEnabled - If true, Address Autofill address or marker location corrections will be submitted to the Mapbox Contribute API to help improve our data accuracy. Defaults to true.\n * @example\n * ```typescript\n * config.accessToken = 'pk.abc.123';\n * ...\n * // Don't need to explicitly pass in token to some components\n * autofill({});\n * confirmAddress(form);\n * ```\n */\nconst config = new Config();\n\n// Prevent autofillSessionToken from being overwritten\nObject.defineProperty(config, 'autofillSessionToken', {\n  configurable: false,\n  writable: false\n});\n\nexport { config };\n","import { AddressAutofillFeatureSuggestion } from '@mapbox/search-js-core';\nimport { AddressConfirmOptions } from '../components/MapboxAddressConfirmation';\nimport { confirmAddress } from '../confirmAddress';\nimport {\n  AutofillValueMap,\n  findAddressAutofillInputs,\n  findParentForm,\n  parseFormStructure\n} from './autofill';\nimport { createElementFromString } from './dom';\n\n/**\n * Object indicating the decision made by the user during address confirmation when using {@link confirmAddress}.\n * @typedef AddressConfirmShowResult\n */\nexport type AddressConfirmShowResult =\n  | { type: 'change'; feature: AddressAutofillFeatureSuggestion }\n  | { type: 'nochange' }\n  | { type: 'cancel' };\n\n/**\n * Creates a formatted, multi-line HTML element representing an address\n * @param autofillValues - A map of address `<input>` values by autocomplete attribute\n * @param baseAddress - A full address string. If provided, this will be used for the\n * first and last lines of the formatted address, and will be supplemented by any `address-line2`\n * and/or `address-line3` values provided through the `autofillValues` map.\n * @param featureName - The name of the feature used as the first line of the address.\n * @param featureDescription - The context string the feature used as the last line of the address.\n * @param isSecondary - If true, the address is a secondary address and the featureName includes secondary info.\n * @returns\n */\nexport function createAddressElement(\n  autofillValues: AutofillValueMap,\n  baseAddress?: string,\n  featureName?: string,\n  featureDescription?: string,\n  isSecondary?: boolean\n): HTMLElement {\n  if (baseAddress) {\n    const element = createElementFromString<HTMLSpanElement>(`\n        <span>\n          <span></span>\n          <br />\n          <span></span>\n        </span>\n      `);\n\n    const [firstLine, lastLine] = Array.from(\n      element.querySelectorAll<HTMLSpanElement>('span > span')\n    );\n\n    if (featureName && featureDescription) {\n      firstLine.textContent = featureName;\n      lastLine.textContent = featureDescription;\n    } else {\n      const parts = baseAddress.split(',');\n      firstLine.textContent = parts[0].trim();\n      lastLine.textContent = parts.slice(1).join(',').trim();\n    }\n\n    // If the validated feature is not already a secondary address,\n    // check the customer-entered form inputs to possibly insert into the display name\n    if (!isSecondary) {\n      // Add any customer-entered address-line2, address-line3 input values\n      if (autofillValues['address-line2']) {\n        const span = document.createElement('span');\n        span.textContent = autofillValues['address-line2'];\n        element.insertBefore(span, lastLine);\n        element.insertBefore(document.createElement('br'), lastLine);\n      }\n      if (autofillValues['address-line3']) {\n        const span = document.createElement('span');\n        span.textContent = autofillValues['address-line3'];\n        element.insertBefore(span, lastLine);\n        element.insertBefore(document.createElement('br'), lastLine);\n      }\n    }\n\n    return element;\n  } else {\n    const firstLine =\n      autofillValues['street-address'] || autofillValues['address-line1'] || '';\n    const line2 = autofillValues['address-line2'];\n    const line3 = autofillValues['address-line3'];\n    const lastLine = [\n      autofillValues['address-level4'] || '',\n      autofillValues['address-level3'] || '',\n      autofillValues['address-level2'] || '',\n      `${autofillValues['address-level1'] || ''} ${\n        autofillValues['postal-code'] || ''\n      }`,\n      autofillValues.country || autofillValues['country-name'] || ''\n    ]\n      .filter(Boolean)\n      .join(', ');\n    const addressLines = [firstLine, line2, line3, lastLine].filter(Boolean);\n    const addressLinesHtml = addressLines\n      .map((val) => `<span>${val}</span>`)\n      .join('<br />');\n    const element = createElementFromString<HTMLSpanElement>(`\n        <span>${addressLinesHtml}</span>\n      `);\n    return element;\n  }\n}\n\n/**\n * Checks a browser autofill event against an Address Autofill input and, given\n * custom options, determines and configures if/how to show invoke {@link confirmAddress}.\n *\n * @param input - The `<input>` element wrapped or targeted by Address Autofill.\n * @param event - The custom window event detected and triggered on a browser autofill event.\n * @param confirmOnBrowserAutofill - The value of the instance property set on the autofill instance.\n * @param accessToken - A Mapbox access token.\n * @returns\n */\nexport async function tryConfirmBrowserAutofill(\n  input: HTMLInputElement,\n  event: CustomEvent,\n  confirmOnBrowserAutofill: boolean | AddressConfirmOptions,\n  accessToken: string\n): Promise<void> {\n  // Early exit if confirmation is not enabled on browser autofill events\n  if (!confirmOnBrowserAutofill) return;\n\n  const parentForm = findParentForm(input);\n  /**\n   * Check that at least one of the browser autofilled input elements are\n   * part of the address structure of the form. E.g. if only \"name\" and \"email\"\n   * fields were autofilled, we don't need to confirm the address.\n   */\n  const formElements = Object.values(\n    findAddressAutofillInputs(parentForm, input)\n  );\n  if (!event.detail.elements.some((el) => formElements.includes(el))) {\n    return;\n  }\n\n  const structure = parseFormStructure(parentForm);\n  const structureRef = structure.find((s) => s.input === input);\n  const autofillInstanceSection = structureRef.section;\n\n  // Get list of form sections that were browser autofilled\n  const browserAutofilledSections = Array.from(\n    new Set(\n      structure\n        .filter((s) => event.detail.elements.includes(s.input))\n        .map((s) => s.section)\n    )\n  );\n\n  /**\n   * Skip confirming the autofill instance section if it's not included in\n   * what was autofilled by the browser\n   */\n  if (!browserAutofilledSections.includes(autofillInstanceSection)) {\n    return;\n  }\n\n  /**\n   * Skip confirmation if the impacted autocomplete \"section\" is not included in\n   * an explicitly defined array of form sections from a confirmOnBrowserAutofill object.\n   * e.g. The browser autofill event was triggered by inputs with \"section-billing\" in\n   * their `autocomplete` attribute value, but the `<input>` element targeted by this\n   * autofill instance in this has \"section-shipping\".\n   */\n  const optionsSections =\n    (typeof confirmOnBrowserAutofill === 'object' &&\n      confirmOnBrowserAutofill.sections) ||\n    [];\n  if (\n    optionsSections.length &&\n    !optionsSections.some((section) =>\n      browserAutofilledSections.includes(section)\n    )\n  ) {\n    return;\n  }\n\n  /**\n   * Modify optionsArg to restrict confirmation to only occur\n   * on the \"section\" impacted by the browser autofill event.\n   */\n  let optionsArg: AddressConfirmOptions =\n    typeof confirmOnBrowserAutofill === 'object'\n      ? confirmOnBrowserAutofill\n      : {};\n  optionsArg = {\n    ...optionsArg,\n    accessToken,\n    sections: [autofillInstanceSection]\n  };\n  await confirmAddress(parentForm, optionsArg);\n}\n","import { isLocalServer, isMapboxDomain } from '.';\nimport { config } from '../config';\n\nimport { version } from '../../package.json';\n\nconst CONTRIBUTE_API_BASE_URL = 'https://contribute-api.mapbox.com/v1';\nconst CONTRIBUTE_API_STAGING_BASE_URL =\n  'https://contribute-api-staging.tilestream.net/v1';\nconst EDIT_SUGGESTION_ENDPOINT = 'edit-suggestion';\n\n/**\n * Object defining changes made to an address location feature.\n * Sent as part of payload to Contribute API.\n */\nexport interface ContributeChanges {\n  house?: string; // House number\n  street?: string; // Street name\n  address?: string; // Full address from Address Autofill SDK\n  location?: { longitude: number; latitude: number }; // Location of the user-adjusted pin\n}\n\nexport interface FeedbackArgs {\n  originalCoordinate: [number, number];\n  originalAddress: string;\n  changes: ContributeChanges;\n  labels?: string[];\n}\n\ninterface LocationDto {\n  latitude: number;\n  longitude: number;\n}\n\ninterface UpdateAddressEditSuggestionDto {\n  location: LocationDto;\n  comment?: string;\n  attachments?: string[];\n  userEmail: string;\n  userLocation?: LocationDto;\n  notificationsDisabled?: boolean;\n  submissionNotificationDisabled?: boolean;\n  searchQuery?: string;\n  selectedFeature?: string;\n  selectedFeatureIndex?: number;\n  referrer?: string;\n  labels?: string[];\n  version: '1.18'; // https://github.com/mapbox/itm-backend/blob/main/docs/edit-suggestion.entity_versions.md\n  action: 'update';\n  reason: 'incorrect_data';\n  placeName?: string;\n  mapboxId?: string;\n  changes?: {\n    address?: string;\n    location?: LocationDto;\n  };\n}\n\n/**\n * Sends feedback to the Mapbox Contribute API (https://github.com/mapbox/itm-backend) given an original Address Autofill API feature and a set of user-defined changes to the address or location.\n * @param accessToken - Mapbox access token\n * @param {FeedbackArgs} feedbackArgs - Data detailing the original address and location and any changes requested\n * @param {[number, number]} feedbackArgs.originalCoordinate - Original coordinate from the Address Autofill API\n * @param {string} feedbackArgs.originalAddress - Original full_address or place_name from the Address Autofill API\n * @param {ContributeChanges} feedbackArgs.changes - Address fields or location changed by a user\n * @param {string[]} [feedbackArgs.labels] - List of labels which will be associated with the feedback\n */\nexport function sendFeedback(\n  accessToken: string,\n  feedbackArgs: FeedbackArgs\n): void {\n  // Skip sending feedback if disabled in global config\n  if (!config.feedbackEnabled) return;\n\n  // Direct feedback sent during development or from Mapbox site to staging server\n  const hostname = window.location.hostname;\n  const BASE_URL =\n    isLocalServer(hostname) || isMapboxDomain(hostname)\n      ? CONTRIBUTE_API_STAGING_BASE_URL\n      : CONTRIBUTE_API_BASE_URL;\n  const url = `${BASE_URL}/${EDIT_SUGGESTION_ENDPOINT}/address?access_token=${accessToken}`;\n\n  const { originalCoordinate, originalAddress, changes, labels } = feedbackArgs;\n\n  const payload: UpdateAddressEditSuggestionDto = {\n    version: '1.18',\n    action: 'update',\n    reason: 'incorrect_data',\n    location: {\n      // original location of the address (suggested by SDK/API)\n      longitude: originalCoordinate[0],\n      latitude: originalCoordinate[1]\n    },\n    userEmail: 'no-reply-autofill@mapbox.com',\n    changes,\n    placeName: originalAddress, // Full (original) address from Address Autofill SDK\n    labels,\n    notificationsDisabled: true,\n    submissionNotificationDisabled: true\n  };\n\n  fetch(url, {\n    method: 'POST',\n    headers: new Headers({\n      'User-Agent': `mapbox-search-js.${version}.${navigator.userAgent}`,\n      'Content-Type': 'application/json'\n    }),\n    body: JSON.stringify(payload)\n  });\n}\n","import { AddressAutofillFeatureSuggestion } from '@mapbox/search-js-core';\n\nimport { MapboxAddressMinimap } from './MapboxAddressMinimap';\nimport { HTMLScopedElement } from './HTMLScopedElement';\nimport {\n  AddressConfirmationEventTypes,\n  ConfirmationMinimapOptions\n} from './MapboxAddressConfirmation';\n\nimport { randomValidID } from '../utils';\nimport { bindElements, createElementFromString } from '../utils/dom';\nimport { ariaButtonKeyDown } from '../utils/aria';\nimport { AutofillValueMap, getAutofillSearchText } from '../utils/autofill';\nimport {\n  AddressConfirmShowResult,\n  createAddressElement\n} from '../utils/confirmation';\nimport { sendFeedback } from '../utils/contribute';\n\nimport { MapboxHTMLEvent } from '../MapboxHTMLEvent';\nimport { getIcon, getThemeCSS, Theme } from '../theme';\n\nimport style from '../style.css';\n\nconst TEMPLATE = createElementFromString<HTMLTemplateElement>(/* html */ `\n<template>\n  <div class=\"MapboxAddressConfirmationFeature\">\n    <div class=\"Modal\" aria-modal=\"true\" role=\"dialog\">\n      <div class=\"ModalHeader\">\n        <svg viewBox=\"0 0 18 18\" class=\"Icon IconQuestion\"></svg>\n        <div class=\"ModalHeaderTitle\">Did you mean?</div>\n        <svg\n          viewBox=\"0 0 18 18\"\n          class=\"Icon IconClose\"\n          tabindex=\"0\"\n          role=\"button\"\n          title=\"Close\"\n          aria-label=\"Close\"\n          aria-expanded=\"true\"\n        ></svg>\n      </div>\n\n      <div class=\"ModalAddress ModalAddressApprove\"></div>\n            \n      <div class=\"ModalMap\">\n        <mapbox-address-minimap class=\"Minimap\"></mapbox-address-minimap>\n      </div>\n\n      <div\n        class=\"Button ButtonPrimary ButtonApprove\"\n        tabindex=\"0\"\n        role=\"button\"\n        aria-label=\"Yes\"\n      >\n        Yes\n      </div>\n      \n      <div\n        class=\"Button ButtonSecondary ButtonReject\"\n        tabindex=\"0\"\n        role=\"button\"\n        aria-label=\"No, use the address I provided\"\n      >\n        No, use the address I provided\n      </div>\n\n      <div class=\"ModalFooter\">\n          Your confirmation helps improve address data accuracy.\n      </div>\n    </div>\n  </div>\n</template>\n`);\n\ntype Binding = {\n  MapboxAddressConfirmationFeature: HTMLDivElement;\n  Modal: HTMLDivElement;\n  ModalHeaderTitle: HTMLDivElement;\n  ModalMap: HTMLDivElement;\n  Minimap: MapboxAddressMinimap;\n\n  IconQuestion: SVGSVGElement;\n  IconClose: SVGSVGElement;\n\n  ButtonApprove: HTMLDivElement;\n  ButtonReject: HTMLDivElement;\n\n  ModalAddressApprove: HTMLDivElement;\n};\n\n/**\n * {@link MapboxAddressConfirmationNoFeature} is a custom element that\n * will display a notification showing the closest suggested address to what a user has provided in the form.\n * Optionally, it can display a {@link MapboxAddressMinimap} for the suggesested address feature.\n *\n * This element is hosted by {@link MapboxAddressConfirmation} and should not be exposed to the user.\n */\nexport class MapboxAddressConfirmationFeature extends HTMLScopedElement<AddressConfirmationEventTypes> {\n  #binding: Binding;\n\n  get template(): HTMLTemplateElement {\n    return TEMPLATE;\n  }\n\n  get templateStyle(): string {\n    return style;\n  }\n\n  get templateUserStyle(): string {\n    return getThemeCSS('.MapboxAddressConfirmationFeature', this.theme);\n  }\n\n  #themeInternal: Theme = {};\n\n  get theme(): Theme {\n    return this.#themeInternal;\n  }\n\n  set theme(theme: Theme) {\n    this.#themeInternal = theme;\n\n    if (!this.#binding || !theme) {\n      return;\n    }\n\n    this.updateTemplateUserStyle(\n      getThemeCSS('.MapboxAddressConfirmationFeature', theme)\n    );\n\n    const { IconQuestion, IconClose } = this.#binding;\n\n    IconQuestion.innerHTML = getIcon('question', theme);\n    IconClose.innerHTML = getIcon('close', theme);\n  }\n\n  set footer(val: boolean | string) {\n    // Update modal footer, if specified\n    if (val === undefined) return;\n    const footerEl = this.querySelector('.ModalFooter');\n    if (typeof val === 'string') {\n      footerEl.textContent = val;\n      footerEl.removeAttribute('aria-hidden');\n    } else if (!val) {\n      footerEl.setAttribute('aria-hidden', 'true');\n    } else {\n      footerEl.removeAttribute('aria-hidden');\n    }\n  }\n\n  minimap: boolean | ConfirmationMinimapOptions = false;\n  accessToken: string;\n\n  #feature: AddressAutofillFeatureSuggestion;\n  #formValues: AutofillValueMap;\n\n  /**\n   * Update modal content with a given address suggestion\n   * @param feature - Suggested feature\n   * @param autofillValues - User-provided input values from address fields; used to backfill address-line2, address-line3\n   */\n  update = (\n    feature: AddressAutofillFeatureSuggestion,\n    autofillValues: AutofillValueMap\n  ): void => {\n    this.#feature = feature;\n    this.#formValues = autofillValues;\n    const { ModalMap, Minimap, ModalAddressApprove } = this.#binding;\n    // Update minimap if enabled\n    if (this.minimap) {\n      ModalMap.removeAttribute('aria-hidden');\n      Minimap.accessToken = this.accessToken;\n      if (typeof this.minimap === 'object') {\n        const { defaultMapStyle, theme, mapStyleMode, satelliteToggle } =\n          this.minimap;\n        defaultMapStyle &&\n          (Minimap.defaultMapStyle = this.minimap.defaultMapStyle);\n        theme && (Minimap.theme = this.minimap.theme);\n        mapStyleMode && (Minimap.mapStyleMode = mapStyleMode);\n        satelliteToggle !== undefined &&\n          (Minimap.satelliteToggle = satelliteToggle);\n      }\n      Minimap.feature = feature;\n    } else {\n      ModalMap.setAttribute('aria-hidden', 'true');\n    }\n\n    const approveAddress =\n      feature.properties.place_name ||\n      feature.properties.full_address ||\n      feature.properties.address;\n\n    // Set the text of the approve address.\n    ModalAddressApprove.innerHTML = '';\n    ModalAddressApprove.appendChild(\n      createAddressElement(\n        autofillValues,\n        approveAddress,\n        feature.properties.feature_name,\n        feature.properties.description,\n        feature.properties.place_type?.[0] === 'secondary_address'\n      )\n    );\n  };\n\n  #handleClose = (): void => {\n    this.dispatchEvent(\n      new MapboxHTMLEvent<AddressConfirmShowResult['type']>('result', 'cancel')\n    );\n  };\n\n  approve = (): void => {\n    this.dispatchEvent(\n      new MapboxHTMLEvent<AddressConfirmShowResult['type']>('result', 'change')\n    );\n  };\n\n  reject = (): void => {\n    this.dispatchEvent(\n      new MapboxHTMLEvent<AddressConfirmShowResult['type']>(\n        'result',\n        'nochange'\n      )\n    );\n    // Send feedback to Contribute API with the address from the user's preferred form values\n    sendFeedback(this.accessToken, {\n      originalCoordinate: this.#feature.geometry.coordinates as [\n        number,\n        number\n      ],\n      originalAddress: this.#feature.properties.full_address,\n      changes: {\n        address: getAutofillSearchText(this.#formValues)\n      },\n      labels: ['address_confirm_form']\n    });\n  };\n\n  // IDs to connect for ARIA.\n  #modalID = randomValidID();\n  #modalHeaderTitleID = randomValidID();\n  #modalAddressApproveID = randomValidID();\n\n  connectedCallback(): void {\n    super.connectedCallback();\n\n    this.#binding = bindElements<Binding>(this, {\n      MapboxAddressConfirmationFeature: '.MapboxAddressConfirmationFeature',\n      Modal: '.Modal',\n      ModalHeaderTitle: '.ModalHeaderTitle',\n      ModalMap: '.ModalMap',\n      Minimap: '.Minimap',\n\n      IconQuestion: '.IconQuestion',\n      IconClose: '.IconClose',\n\n      ButtonApprove: '.ButtonApprove',\n      ButtonReject: '.ButtonReject',\n\n      ModalAddressApprove: '.ModalAddressApprove'\n    });\n\n    const {\n      Modal,\n      ModalHeaderTitle,\n      IconClose,\n      ButtonApprove,\n      ButtonReject,\n      ModalAddressApprove\n    } = this.#binding;\n\n    // Setup IDREFs for WAI-ARIA.\n    Modal.setAttribute('aria-labelledby', this.#modalHeaderTitleID);\n    Modal.setAttribute('aria-describedby', this.#modalAddressApproveID);\n    IconClose.setAttribute('aria-controls', this.#modalID);\n\n    Modal.id = this.#modalID;\n    ModalHeaderTitle.id = this.#modalHeaderTitleID;\n    ModalAddressApprove.id = this.#modalAddressApproveID;\n\n    // Setup WAI-ARIA button keyboard events.\n    const buttons = Array.from(this.querySelectorAll('[role=\"button\"]'));\n    for (const button of buttons) {\n      button.addEventListener('keydown', ariaButtonKeyDown);\n    }\n\n    // Setup event listeners.\n    IconClose.addEventListener('click', this.#handleClose);\n    ButtonApprove.addEventListener('click', this.approve);\n    ButtonReject.addEventListener('click', this.reject);\n\n    const theme = this.theme;\n    if (theme) {\n      const { IconQuestion, IconClose } = this.#binding;\n\n      IconQuestion.innerHTML = getIcon('question', theme);\n      IconClose.innerHTML = getIcon('close', theme);\n    }\n  }\n\n  disconnectedCallback(): void {\n    const { IconClose, ButtonApprove } = this.#binding;\n\n    // Make sure to unbind event listeners.\n    IconClose.removeEventListener('click', this.#handleClose);\n    ButtonApprove.removeEventListener('click', this.approve);\n  }\n}\n\ndeclare global {\n  interface Window {\n    MapboxAddressConfirmationFeature: typeof MapboxAddressConfirmationFeature;\n  }\n}\n\nwindow.MapboxAddressConfirmationFeature = MapboxAddressConfirmationFeature;\n\nif (!window.customElements.get('mapbox-address-confirmation-feature')) {\n  customElements.define(\n    'mapbox-address-confirmation-feature',\n    MapboxAddressConfirmationFeature\n  );\n}\n","import { HTMLScopedElement } from './HTMLScopedElement';\nimport { AddressConfirmationEventTypes } from './MapboxAddressConfirmation';\n\nimport { randomValidID } from '../utils';\nimport { bindElements, createElementFromString } from '../utils/dom';\nimport { ariaButtonKeyDown } from '../utils/aria';\nimport { AutofillValueMap } from '../utils/autofill';\nimport {\n  AddressConfirmShowResult,\n  createAddressElement\n} from '../utils/confirmation';\n\nimport { MapboxHTMLEvent } from '../MapboxHTMLEvent';\nimport { getIcon, getThemeCSS, Theme } from '../theme';\n\nimport style from '../style.css';\n\nconst TEMPLATE = createElementFromString<HTMLTemplateElement>(/* html */ `\n<template>\n  <div class=\"MapboxAddressConfirmationNoFeature\">\n    <div class=\"Modal\" aria-modal=\"true\" role=\"dialog\">\n      <div class=\"ModalHeader\">\n        <svg viewBox=\"0 0 18 18\" class=\"Icon IconQuestion\"></svg>\n        <div class=\"ModalHeaderTitle\">Confirm address</div>\n        <svg\n          viewBox=\"0 0 18 18\"\n          class=\"Icon IconClose\"\n          tabindex=\"0\"\n          role=\"button\"\n          title=\"Close\"\n          aria-label=\"Close\"\n          aria-expanded=\"true\"\n        ></svg>\n      </div>\n      <div class=\"ModalDescription\">\n        We couldn't verify this address. Please check that your information is correct before continuing.\n      </div>\n      <br />\n      <div class=\"ModalSubheader\">\n        You entered\n      </div>\n      <div class=\"ModalAddress\"></div>\n      <div\n        class=\"Button ButtonPrimary\"\n        tabindex=\"0\"\n        role=\"button\"\n        aria-label=\"Use the address I provided\"\n      >\n        Use the address I provided\n      </div>\n    </div>\n  </div>\n</template>\n`);\n\ntype Binding = {\n  Modal: HTMLDivElement;\n  ModalHeaderTitle: HTMLDivElement;\n\n  IconQuestion: SVGSVGElement;\n  IconClose: SVGSVGElement;\n\n  ButtonReject: HTMLDivElement;\n\n  ModalAddress: HTMLDivElement;\n};\n\n/**\n * {@link MapboxAddressConfirmationNoFeature} is a custom element that\n * will display a notification when an address entered into an HTML form\n * does not return any features when queried against the Address Autofill API.\n *\n * This element is hosted by {@link MapboxAddressConfirmation} and should not be exposed to the user.\n */\nexport class MapboxAddressConfirmationNoFeature extends HTMLScopedElement<AddressConfirmationEventTypes> {\n  #binding: Binding;\n\n  get template(): HTMLTemplateElement {\n    return TEMPLATE;\n  }\n\n  get templateStyle(): string {\n    return style;\n  }\n\n  get templateUserStyle(): string {\n    return getThemeCSS('.MapboxAddressConfirmationNoFeature', this.theme);\n  }\n\n  #themeInternal: Theme = {};\n\n  get theme(): Theme {\n    return this.#themeInternal;\n  }\n\n  set theme(theme: Theme) {\n    this.#themeInternal = theme;\n\n    if (!this.#binding || !theme) {\n      return;\n    }\n\n    this.updateTemplateUserStyle(\n      getThemeCSS('.MapboxAddressConfirmationNoFeature', theme)\n    );\n\n    const { IconQuestion, IconClose } = this.#binding;\n\n    IconQuestion.innerHTML = getIcon('question', theme);\n    IconClose.innerHTML = getIcon('close', theme);\n  }\n\n  /**\n   * Update modal content with user-provided address\n   * @param autofillValues - User-provided input values from address fields\n   */\n  update = (autofillValues: AutofillValueMap): void => {\n    // Set the text of the approve address.\n    const { ModalAddress } = this.#binding;\n    ModalAddress.innerHTML = '';\n    ModalAddress.appendChild(createAddressElement(autofillValues));\n  };\n\n  #handleClose = (): void => {\n    this.dispatchEvent(\n      new MapboxHTMLEvent<AddressConfirmShowResult['type']>('result', 'cancel')\n    );\n  };\n\n  reject = (): void => {\n    this.dispatchEvent(\n      new MapboxHTMLEvent<AddressConfirmShowResult['type']>(\n        'result',\n        'nochange'\n      )\n    );\n  };\n\n  // IDs to connect for ARIA.\n  #modalID = randomValidID();\n  #modalHeaderTitleID = randomValidID();\n  #modalAddressID = randomValidID();\n\n  connectedCallback(): void {\n    super.connectedCallback();\n\n    this.#binding = bindElements<Binding>(this, {\n      Modal: '.Modal',\n      ModalHeaderTitle: '.ModalHeaderTitle',\n\n      IconQuestion: '.IconQuestion',\n      IconClose: '.IconClose',\n\n      ModalAddress: '.ModalAddress',\n\n      ButtonReject: '.Button'\n    });\n\n    const { Modal, ModalHeaderTitle, IconClose, ModalAddress, ButtonReject } =\n      this.#binding;\n\n    // Setup IDREFs for WAI-ARIA.\n    Modal.setAttribute('aria-labelledby', this.#modalHeaderTitleID);\n    Modal.setAttribute('aria-describedby', this.#modalAddressID);\n    IconClose.setAttribute('aria-controls', this.#modalID);\n\n    Modal.id = this.#modalID;\n    ModalHeaderTitle.id = this.#modalHeaderTitleID;\n    ModalAddress.id = this.#modalAddressID;\n\n    // Setup WAI-ARIA button keyboard events.\n    const buttons = Array.from(this.querySelectorAll('[role=\"button\"]'));\n    for (const button of buttons) {\n      button.addEventListener('keydown', ariaButtonKeyDown);\n    }\n\n    // Setup event listeners.\n    IconClose.addEventListener('click', this.#handleClose);\n    ButtonReject.addEventListener('click', this.reject);\n\n    const theme = this.theme;\n    if (theme) {\n      const { IconQuestion, IconClose } = this.#binding;\n\n      IconQuestion.innerHTML = getIcon('question', theme);\n      IconClose.innerHTML = getIcon('close', theme);\n    }\n  }\n\n  disconnectedCallback(): void {\n    const { IconClose, ButtonReject } = this.#binding;\n\n    // Make sure to unbind event listeners.\n    IconClose.removeEventListener('click', this.#handleClose);\n    ButtonReject.removeEventListener('click', this.reject);\n  }\n}\n\ndeclare global {\n  interface Window {\n    MapboxAddressConfirmationNoFeature: typeof MapboxAddressConfirmationNoFeature;\n  }\n}\n\nwindow.MapboxAddressConfirmationNoFeature = MapboxAddressConfirmationNoFeature;\n\nif (!window.customElements.get('mapbox-address-confirmation-no-feature')) {\n  customElements.define(\n    'mapbox-address-confirmation-no-feature',\n    MapboxAddressConfirmationNoFeature\n  );\n}\n","import {\n  AddressAutofillFeatureSuggestion,\n  AddressAutofillOptions,\n  AddressAutofillRetrieveResponse,\n  AddressAutofillSuggestion,\n  AddressAutofillSuggestionResponse,\n  AddressAutofillCore,\n  SearchSession\n} from '@mapbox/search-js-core';\n\nimport {\n  MapboxSearchListbox,\n  SelectionEventDetail\n} from './MapboxSearchListbox';\nimport { HTMLScopedElement } from './HTMLScopedElement';\n\nimport { tryParseJSON } from '../utils';\nimport {\n  distinctExactStreetResults,\n  fillFormWithFeature,\n  toggleAutocompletion\n} from '../utils/autofill';\nimport { tryConfirmBrowserAutofill } from '../utils/confirmation';\n\nimport { Theme } from '../theme';\nimport { MapboxHTMLEvent } from '../MapboxHTMLEvent';\nimport { config } from '../config';\nimport { initDetectBrowserAutofill } from '../utils/detect_browser_autofill';\nimport { AddressConfirmOptions } from './MapboxAddressConfirmation';\nimport { PopoverOptions } from '../utils/popover';\nimport {\n  createAriaLiveElement,\n  suppressExtensionsAutocomplete\n} from '../utils/aria';\nimport { handleStreetSelection } from '../utils/autofill';\nimport { SEARCH_SERVICE } from '../utils/services';\nimport { InputEventDetail } from '../utils/listbox';\nimport { MapboxEventManager } from '../events/MapboxEventManager';\n\nexport type MapboxSearchListboxAutofillType =\n  MapboxSearchListbox<AddressAutofillSuggestion>;\n\ntype AddressAutofillEventTypes = {\n  /**\n   * Fired when the user is typing in the input and provides a list of suggestions.\n   *\n   * The underlying response from {@link AddressAutofillCore} is passed as the event's detail.\n   *\n   * @event suggest\n   * @instance\n   * @memberof MapboxAddressAutofill\n   * @type {AddressAutofillSuggestionResponse}\n   * @example\n   * ```typescript\n   * autofill.addEventListener('suggest', (event) => {\n   *   const suggestions = event.detail.suggestions;\n   *   // ...\n   * });\n   * ```\n   */\n  suggest: MapboxHTMLEvent<AddressAutofillSuggestionResponse>;\n  /**\n   * Fired when {@link AddressAutofillCore} has errored providing a list of suggestions.\n   *\n   * The underlying error is passed as the event's detail.\n   *\n   * @event suggesterror\n   * @instance\n   * @memberof MapboxAddressAutofill\n   * @type {Error}\n   * @example\n   * ```typescript\n   * autofill.addEventListener('suggesterror', (event) => {\n   *   const error = event.detail;\n   *   // ...\n   * });\n   * ```\n   */\n  suggesterror: MapboxHTMLEvent<Error>;\n  /**\n   * Fired when the user has selected a suggestion, before the form is autofilled.\n   *\n   * The underlying response from {@link AddressAutofillCore} is passed as the event's detail.\n   *\n   * @event retrieve\n   * @instance\n   * @memberof MapboxAddressAutofill\n   * @type {AddressAutofillRetrieveResponse}\n   * @example\n   * ```typescript\n   * autofill.addEventListener('retrieve', (event) => {\n   *   const featureCollection = event.detail;\n   *   // ...\n   * });\n   * ```\n   */\n  retrieve: MapboxHTMLEvent<AddressAutofillRetrieveResponse>;\n  /**\n   * Fired when the user has changed the `<input>` text.\n   *\n   * The new input value is passed as the event's detail.\n   *\n   * @event input\n   * @instance\n   * @memberof MapboxAddressAutofill\n   * @type {string}\n   * @example\n   * ```typescript\n   * autofill.addEventListener('input', (event) => {\n   *   if (e.target !== e.currentTarget) return;\n   *   const searchText = event.detail;\n   *   // ...\n   * });\n   * ```\n   */\n  input: MapboxHTMLEvent<unknown>;\n};\n\n/**\n * `MapboxAddressAutofill`, also available as the element `<mapbox-address-autofill>`,\n * is an element that wraps an address [`<input>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/text) element with\n * intelligent, location-aware autocomplete functionality.\n *\n * To use this element, you must have a [Mapbox access token](https://www.mapbox.com/help/create-api-access-token/).\n *\n * This element must be a descendant of a [`<form>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form) element, and the form\n * must have inputs with proper HTML `autocomplete` attributes. If your application works with browser autofill, you may already have\n * this functionality.\n * - [The HTML autocomplete attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete)\n * - [Autofill](https://web.dev/learn/forms/autofill/)\n *\n * @class MapboxAddressAutofill\n * @example\n * <form>\n *   <mapbox-address-autofill access-token=\"YOUR_MAPBOX_ACCESS_TOKEN\">\n *     <input type=\"text\" name=\"address\" autocomplete=\"shipping street-address\" />\n *   </mapbox-address-autofill>\n * </form>\n */\nexport class MapboxAddressAutofill extends HTMLScopedElement<AddressAutofillEventTypes> {\n  /**\n   * This is read by the Web Components API to affect the\n   * {@link MapboxAddressAutofill.attributeChangedCallback} below.\n   *\n   * All of these are passthroughs to the underlying {@link MapboxSearchListbox}.\n   *\n   * @ignore\n   */\n  static observedAttributes: string[] = [\n    // Access token.\n    'access-token',\n    'browser-autofill-enabled',\n    // Theming, CSS.\n    'theme',\n    'popover-options',\n    'css-text',\n    // Underlying Address Autofill API options.\n    'language',\n    'country',\n    'bbox',\n    'limit',\n    'proximity',\n    'streets'\n  ];\n\n  #autofill = new AddressAutofillCore();\n  #session = new SearchSession<\n    AddressAutofillOptions,\n    AddressAutofillSuggestion,\n    AddressAutofillSuggestionResponse,\n    AddressAutofillRetrieveResponse\n  >(this.#autofill);\n\n  /**\n   * The [Mapbox access token](https://docs.mapbox.com/help/glossary/access-token/) to use for all requests.\n   *\n   * @name accessToken\n   * @instance\n   * @memberof MapboxAddressAutofill\n   * @example\n   * ```typescript\n   * autofill.accessToken = 'pk.my-mapbox-access-token';\n   * ```\n   */\n  get accessToken(): string {\n    return this.#autofill.accessToken;\n  }\n  set accessToken(newToken: string) {\n    this.#autofill.accessToken = newToken;\n  }\n\n  #input: HTMLInputElement;\n  #listbox = new MapboxSearchListbox();\n\n  #eventManager = new MapboxEventManager(SEARCH_SERVICE.AddressAutofill);\n\n  #initialAutocompleteValue: string;\n\n  /**\n   * The `<input>` element wrapped by the autofill component.\n   *\n   * @name input\n   * @instance\n   * @memberof MapboxAddressAutofill\n   * @type {HTMLInputElement}\n   */\n  get input(): HTMLInputElement {\n    return this.#input;\n  }\n\n  /**\n   * Options to pass to the underlying {@link AddressAutofillCore} interface.\n   *\n   * @name options\n   * @instance\n   * @memberof MapboxAddressAutofill\n   * @type {AddressAutofillOptions}\n   * @example\n   * ```typescript\n   * autofill.options = {\n   *  language: 'en',\n   *  country: 'US',\n   * };\n   * ```\n   */\n  options: Partial<AddressAutofillOptions> = {};\n\n  /**\n   * The {@link Theme} to use for styling the autofill component.\n   *\n   * @name theme\n   * @instance\n   * @memberof MapboxAddressAutofill\n   * @type {Theme}\n   * @example\n   * ```typescript\n   * autofill.theme = {\n   *   variables: {\n   *     colorPrimary: 'myBrandRed'\n   *   }\n   * };\n   * ```\n   */\n  get theme(): Theme {\n    return this.#listbox.theme;\n  }\n  set theme(theme: Theme) {\n    this.#listbox.theme = theme;\n  }\n\n  /**\n   * The {@link PopoverOptions} to define popover positioning.\n   *\n   * @name popoverOptions\n   * @instance\n   * @memberof MapboxAddressAutofill\n   * @type {PopoverOptions}\n   * @example\n   * ```typescript\n   * autofill.popoverOptions = {\n   *   placement: 'top-start',\n   *   flip: true,\n   *   offset: 5\n   * };\n   * ```\n   */\n  get popoverOptions(): Partial<PopoverOptions> {\n    return this.#listbox.popoverOptions;\n  }\n  set popoverOptions(newOptions: Partial<PopoverOptions>) {\n    this.#listbox.popoverOptions = newOptions;\n  }\n\n  /**\n   * If true, forms autofilled by the browser will prompt the\n   * {@link confirmAddress} dialog for user confirmation.\n   * An {@link AddressConfirmOptions} object can also be passed\n   * to prompt {@link confirmAddress} with custom options.\n   * Defaults to false.\n   *\n   * @name confirmOnBrowserAutofill\n   * @instance\n   * @memberof MapboxAddressAutofill\n   * @type {boolean | AddressConfirmOptions}\n   * @example\n   * ```typescript\n   * autofill.confirmOnBrowserAutofill = {\n   *   minimap: true,\n   *   skipConfirmModal: (feature) =>\n   *     ['exact', 'high'].includes(\n   *       feature.properties.match_code.confidence\n   *     )\n   * };\n   * ```\n   */\n  confirmOnBrowserAutofill: boolean | AddressConfirmOptions = false;\n\n  #browserAutofillEnabled? = false;\n\n  /**\n   * Enables the browser's autocomplete popup to show during the first two typed characters while Mapbox results are suppressed. Defaults to false.\n   *\n   * **Note:** Due to varying specifications, efforts to suppress browser autocomplete behavior may not work on all browsers.\n   *\n   * @name browserAutofillEnabled\n   * @instance\n   * @memberof MapboxAddressAutofill\n   * @type {boolean}\n   * @example\n   * ```typescript\n   * autofill.browserAutofillEnabled = true;\n   * ```\n   */\n  get browserAutofillEnabled(): boolean {\n    return this.#browserAutofillEnabled;\n  }\n  set browserAutofillEnabled(enable: boolean) {\n    this.#browserAutofillEnabled = enable;\n  }\n\n  #handleSuggest = (result: AddressAutofillSuggestionResponse): void => {\n    const filteredSuggestions = result?.suggestions\n      ? distinctExactStreetResults(result.suggestions)\n      : null;\n    this.#listbox.handleSuggest(filteredSuggestions);\n    // Manually bubble up the event.\n    this.dispatchEvent(new MapboxHTMLEvent('suggest', result));\n  };\n\n  #handleSuggestError = (error: Error): void => {\n    this.#listbox.handleError();\n    // Manually bubble up the event.\n    this.dispatchEvent(new MapboxHTMLEvent('suggesterror', error));\n  };\n\n  #handleRetrieve = (result: AddressAutofillRetrieveResponse): void => {\n    // Manually bubble up the event.\n    this.dispatchEvent(new MapboxHTMLEvent('retrieve', result));\n\n    this.retrieveFeature = result.features?.[0];\n\n    if (!this.#input) {\n      return;\n    }\n\n    const featureCollection = result;\n    if (\n      !featureCollection ||\n      !featureCollection.features ||\n      !featureCollection.features.length\n    ) {\n      return;\n    }\n\n    fillFormWithFeature(featureCollection.features[0], this.#input);\n  };\n\n  // Called when content changes.\n  #handleObserve = (): void => {\n    try {\n      const input: HTMLInputElement = this.querySelector('input') ?? null;\n\n      this.#input = input;\n      this.#listbox.input = input;\n      if (input) {\n        input.addEventListener('blur', this.#onHandleInputBlur);\n      }\n    } catch (e) {\n      this.#input = null;\n      this.#listbox.input = null;\n\n      console.error(e.message || e);\n    }\n  };\n\n  #observer = new MutationObserver(this.#handleObserve);\n\n  #handleBrowserAutofill = (e: CustomEvent): void => {\n    // Hide listbox, if showing\n    this.#listbox.blur();\n\n    // Address confirmation\n    tryConfirmBrowserAutofill(\n      this.#input,\n      e,\n      this.confirmOnBrowserAutofill,\n      this.accessToken\n    );\n  };\n\n  retrieveFeature: AddressAutofillFeatureSuggestion = null;\n\n  /**\n   * A callback providing the opportunity to validate and/or manipulate the input text before it triggers a search, for example by using a regular expression.\n   * If a truthy string value is returned, it will be passed into the underlying search API. If `null`, `undefined` or empty string is returned, no search request will be performed.\n   *\n   * @name interceptSearch\n   * @instance\n   * @memberof MapboxAddressAutofill\n   * @example\n   * Enable search only when the input value length is more than 3 characters.\n   * ```typescript\n   * search.interceptSearch = (val) => val?.length > 3 ? val : null;\n   * ```\n   */\n  interceptSearch: (val: string) => string = null;\n\n  #onHandleInput = (e: MapboxHTMLEvent<InputEventDetail>): void => {\n    // Manually bubble up the event as a basic input event.\n    this.dispatchEvent(\n      new MapboxHTMLEvent<string>('input', e.detail.inputText)\n    );\n\n    const { lastInput, inputText } = e.detail;\n\n    // if following flag set to true and search text is equal or less than 2 characters - enable browser autofill.\n    const enableBrowserAutocomplete =\n      this.browserAutofillEnabled === true && inputText?.length <= 2;\n\n    toggleAutocompletion(\n      this.#input,\n      this.#initialAutocompleteValue,\n      enableBrowserAutocomplete\n    );\n\n    if (!inputText) {\n      this.#handleClear();\n      return;\n    }\n\n    const alteredText = this.interceptSearch && this.interceptSearch(inputText);\n\n    const searchText = this.interceptSearch ? alteredText : inputText;\n\n    if ((this.interceptSearch && !alteredText) || searchText?.length <= 2) {\n      this.#listbox.handleSuggest(null);\n      return;\n    }\n\n    this.#session.suggest(searchText, this.options);\n    this.#eventManager.input(\n      searchText,\n      lastInput,\n      {\n        ...this.options,\n        sessionToken: this.#session.sessionToken,\n        accessToken: this.accessToken\n      },\n      null,\n      this.#autofill.responseHeaders\n    );\n  };\n\n  #onHandleSelect = (\n    e: MapboxHTMLEvent<SelectionEventDetail<AddressAutofillSuggestion>>\n  ): void => {\n    const { suggestion, selectedIndex } = e.detail;\n    if (suggestion.accuracy !== 'street') {\n      toggleAutocompletion(this.#input, this.#initialAutocompleteValue, true);\n\n      this.#session.retrieve(suggestion, this.options);\n      this.#eventManager.select(\n        this.input.value,\n        selectedIndex,\n        this.#listbox.suggestions,\n        {\n          ...this.options,\n          sessionToken: this.#session.sessionToken,\n          accessToken: this.accessToken\n        },\n        null,\n        this.#autofill.responseHeaders\n      );\n    } else {\n      handleStreetSelection(\n        this.#input,\n        this.#initialAutocompleteValue,\n        suggestion\n      );\n    }\n  };\n\n  #onHandleBlur = (): void => {\n    toggleAutocompletion(this.#input, this.#initialAutocompleteValue, true);\n    // Abort any in-progress operations.\n    this.#session.abort();\n  };\n\n  #onHandleInputBlur = (event: FocusEvent): void => {\n    if (!this.#listbox.contains(event.relatedTarget as Node)) {\n      this.#onHandleBlur();\n      this.#listbox.hideResults();\n    }\n  };\n\n  #onHandleFocus = (): void => {\n    const enableBrowserAutocomplete =\n      this.browserAutofillEnabled === true && this.#input.value?.length <= 2;\n    toggleAutocompletion(\n      this.#input,\n      this.#initialAutocompleteValue,\n      enableBrowserAutocomplete\n    );\n  };\n\n  #handleClear = (): void => {\n    this.#listbox.handleSuggest(null);\n    this.#eventManager.clear();\n  };\n\n  connectedCallback(): void {\n    super.connectedCallback();\n\n    config.autofillSessionEnabled = true;\n    this.#session.sessionToken = config.autofillSessionToken.id;\n\n    this.#listbox.autofillHost = this;\n    this.#listbox.searchService = SEARCH_SERVICE.AddressAutofill;\n\n    const input: HTMLInputElement = this.querySelector('input') ?? null;\n\n    // Setup observer handler.\n    this.#observer.observe(this, {\n      subtree: true,\n      childList: true\n    });\n\n    this.#handleObserve();\n\n    this.#listbox.addEventListener('input', this.#onHandleInput);\n    this.#listbox.addEventListener('select', this.#onHandleSelect);\n    this.#listbox.addEventListener('blur', this.#onHandleBlur);\n    this.#listbox.addEventListener('focus', this.#onHandleFocus);\n\n    this.#session.addEventListener('suggest', this.#handleSuggest);\n    this.#session.addEventListener('suggesterror', this.#handleSuggestError);\n    this.#session.addEventListener('retrieve', this.#handleRetrieve);\n\n    document.body.appendChild(this.#listbox);\n\n    if (input) {\n      input.insertAdjacentElement(\n        'beforebegin',\n        createAriaLiveElement(this.#listbox.dataSeed)\n      );\n      suppressExtensionsAutocomplete(input);\n      this.#initialAutocompleteValue = input.autocomplete;\n    }\n\n    // Setup browser autofill detection\n    initDetectBrowserAutofill();\n    window.addEventListener('browserautofill', this.#handleBrowserAutofill);\n  }\n\n  disconnectedCallback(): void {\n    this.#listbox.remove();\n\n    this.#listbox.removeEventListener('input', this.#onHandleInput);\n    this.#listbox.removeEventListener('select', this.#onHandleSelect);\n    this.#listbox.removeEventListener('blur', this.#onHandleBlur);\n    this.#listbox.removeEventListener('focus', this.#onHandleFocus);\n\n    this.#session.removeEventListener('suggest', this.#handleSuggest);\n    this.#session.removeEventListener('suggesterror', this.#handleSuggestError);\n    this.#session.removeEventListener('retrieve', this.#handleRetrieve);\n\n    this.#eventManager.remove();\n\n    this.#observer.disconnect();\n\n    window.removeEventListener('browserautofill', this.#handleBrowserAutofill);\n  }\n\n  attributeChangedCallback(\n    name: string,\n    oldValue: string,\n    newValue: string\n  ): void {\n    if (name === 'access-token') {\n      this.#autofill.accessToken = newValue;\n      return;\n    }\n\n    if (name === 'browser-autofill-enabled') {\n      this.#browserAutofillEnabled = Boolean(newValue);\n      return;\n    }\n\n    if (name === 'theme') {\n      this.theme = tryParseJSON(newValue);\n      return;\n    }\n\n    if (name === 'popover-options') {\n      this.popoverOptions = tryParseJSON(newValue);\n      return;\n    }\n\n    // Convert to the proper name for options.\n    // Example: eta-type => eta_type\n    const optionName = name.split('-').join('_');\n\n    if (!newValue) {\n      delete this.options[optionName];\n    }\n\n    // Otherwise, assume it's a Address Autofill API option.\n    this.options[optionName] = newValue;\n  }\n\n  /** @section {Methods} */\n\n  /**\n   * Focuses the wrapped input element.\n   */\n  focus(): void {\n    this.#listbox.focus();\n  }\n\n  /**\n   * Trigger side effects from a retrieve event with a simulated result.\n   * Used by {@link confirmAddress} when a suggested addresses is accepted.\n   *\n   * @ignore\n   */\n  simulateRetrieve(feature: AddressAutofillFeatureSuggestion): void {\n    const input = this.input;\n    if (input) {\n      input.dataset['mapboxSuccess'] = 'true';\n    }\n    this.#listbox.hideResults();\n\n    const simResult: AddressAutofillRetrieveResponse = {\n      type: 'FeatureCollection',\n      features: [feature],\n      url: ''\n    };\n\n    this.#handleRetrieve(simResult);\n  }\n}\n\ndeclare global {\n  interface Window {\n    MapboxAddressAutofill: typeof MapboxAddressAutofill;\n  }\n}\n\nwindow.MapboxAddressAutofill = MapboxAddressAutofill;\n\nif (!window.customElements.get('mapbox-address-autofill')) {\n  customElements.define('mapbox-address-autofill', MapboxAddressAutofill);\n}\n","/**\n * Detects browser autofill events and emits custom events\n * Reference: https://github.com/matteobad/detect-autofill\n */\n\nimport { debounce } from '@mapbox/search-js-core';\n\nimport { addDocumentStyle } from './dom';\n\nimport browserAutofillCss from './detect_browser_autofill.css';\nimport { config } from '../config';\nimport { MapboxHTMLEvent } from '../MapboxHTMLEvent';\n\n// Note: if we decide to support legacy browsers in future, we may need to polyfill CustomEvent\n// import 'custom-event-polyfill';\n\nexport const ATTR_NAME = 'browser-autofilled';\nlet AUTOFILLED_ELEMENTS: HTMLElement[] = [];\n\nfunction dispatchBrowserAutofillEvent() {\n  window.dispatchEvent(\n    new window.CustomEvent('browserautofill', {\n      bubbles: true,\n      cancelable: true,\n      detail: { elements: AUTOFILLED_ELEMENTS }\n    })\n  );\n  AUTOFILLED_ELEMENTS = []; // reset element array\n}\n\n/**\n * Debounce interval set at 5ms, as it seems like the delay between successive fields (i.e. inputs)\n * being autofilled by the browser is roughly 1-2ms.\n *\n * This ensures that all fields affected by the autofill event have been populated before signaling\n * the event to the rest of the application.\n */\nconst debouncedAutofill = debounce(dispatchBrowserAutofillEvent, 5);\n\n/**\n * Manage an input element when its value is autocompleted\n * by the browser\n *\n * @param {HtmlInputElement} element\n */\nexport function browserAutofill(element: HTMLInputElement): void {\n  if (element.hasAttribute(ATTR_NAME)) return;\n  element.setAttribute(ATTR_NAME, '');\n\n  AUTOFILLED_ELEMENTS.push(element);\n\n  debouncedAutofill();\n}\n\n/**\n * Manage an input element when its autocompleted value is\n * removed by the browser\n *\n * @param {HtmlInputElement} element\n */\nexport function cancelBrowserAutofill(element: HTMLInputElement): void {\n  if (!element.hasAttribute(ATTR_NAME)) return;\n  element.removeAttribute(ATTR_NAME);\n}\n\n/**\n * Handler for -webkit based browser that listen for a custom\n * animation create using the :pseudo-selector in the stylesheet.\n * Works with Chrome, Safari\n *\n * @param {AnimationEvent} event\n */\nexport function onAnimationStart(event: AnimationEvent): void {\n  'onbrowserautofillstart' === event.animationName\n    ? browserAutofill(event.target as HTMLInputElement)\n    : cancelBrowserAutofill(event.target as HTMLInputElement);\n}\n\n/**\n * Handler for non-webkit based browser that listen for input\n * event to trigger the autocomplete-cancel process.\n * Works with Firefox, Edge, IE11\n *\n * @param {InputEvent} event\n */\nexport function onInput(event: InputEvent): void {\n  const targetEl = event.target as HTMLInputElement;\n  targetEl.nodeName.toLowerCase() !== 'select' &&\n  /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n  !(event as any).simulated &&\n  !(event instanceof MapboxHTMLEvent) &&\n  ('insertReplacementText' === event.inputType || !('data' in event))\n    ? browserAutofill(targetEl)\n    : cancelBrowserAutofill(targetEl);\n}\n\n/**\n * Enables detection of browser autofill events\n */\nexport function initDetectBrowserAutofill(): void {\n  // Set global state to ensure event listeners aren't duplicated\n  if (config.detectBrowserAutofillEnabled) {\n    return;\n  } else {\n    config.detectBrowserAutofillEnabled = true;\n  }\n\n  addDocumentStyle(browserAutofillCss);\n  document.addEventListener('animationstart', onAnimationStart, true);\n  document.addEventListener('input', onInput, true);\n}\n","import {\n  AddressAutofillOptions,\n  AddressAutofillSuggestion,\n  GeocodeFeature,\n  GeocodeOptions,\n  LngLat,\n  LngLatBounds,\n  LngLatLike,\n  SearchBoxOptions,\n  SearchBoxSuggestion\n} from '@mapbox/search-js-core';\nimport { SEARCH_SERVICE } from '../utils/services';\n\nexport interface EventPayloadSuggestionsData {\n  suggestionIds: string[];\n  suggestionNames: string[];\n  suggestionTypes: string[];\n  suggestionSources: string[];\n}\n\nexport interface EventPayloadOptionsData {\n  country?: string[];\n  language?: string[];\n  bbox?: number[];\n  types?: string[];\n  limit?: number;\n  autocomplete?: boolean;\n  fuzzyMatch?: boolean;\n  proximity?: number[];\n  routing?: boolean;\n  worldview?: string;\n  streets?: boolean;\n  permanent?: boolean;\n}\n\nexport type Suggestion =\n  | SearchBoxSuggestion\n  | GeocodeFeature\n  | AddressAutofillSuggestion;\n\nexport type Options =\n  | SearchBoxOptions\n  | GeocodeOptions\n  | AddressAutofillOptions;\n\n/**\n * Parse a proximity value, lng/lat coordinate object, lng/lat string, or 'ip'\n * @param proximity\n * @param responseHeaders\n * @returns\n */\nconst parseExplicitOrIPProximity = (\n  proximity: string | LngLatLike,\n  responseHeaders?: Headers\n): number[] => {\n  if (typeof proximity === 'string') {\n    if (proximity === 'ip') {\n      const ipProximityHeader = responseHeaders?.get('ip-proximity');\n      if (ipProximityHeader && typeof ipProximityHeader === 'string') {\n        return ipProximityHeader.split(',').map(parseFloat);\n      } else {\n        return [999, 999]; // Alias for 'ip' in event logs\n      }\n    } else {\n      return proximity.split(',').map(Number);\n    }\n  } else {\n    return LngLat.convert(proximity).toArray();\n  }\n};\n\n/**\n * Converts SearchBox API options to event schema compatible options\n * @param options\n * @returns\n */\nconst transformSearchBoxAPIOptionsToEventSchema = (\n  options: SearchBoxOptions\n): EventPayloadOptionsData => {\n  const transformedOptions: EventPayloadOptionsData = {};\n\n  if (options.bbox) {\n    if (typeof options.bbox === 'string') {\n      transformedOptions.bbox = options.bbox.split(',').map(Number);\n    } else {\n      transformedOptions.bbox = LngLatBounds.convert(\n        options.bbox\n      ).toFlatArray();\n    }\n  }\n\n  if (options.proximity) {\n    transformedOptions.proximity = parseExplicitOrIPProximity(\n      options.proximity\n    );\n  }\n\n  if (options.country) {\n    transformedOptions.country = options.country.split(',');\n  }\n\n  if (options.language) {\n    transformedOptions.language = options.language.split(',');\n  }\n\n  if (options.types) {\n    if (typeof options.types === 'string') {\n      transformedOptions.types = options.types.split(',');\n    } else {\n      transformedOptions.types = Array.from(options.types);\n    }\n  }\n\n  if (options.limit) {\n    if (typeof options.limit === 'string') {\n      transformedOptions.limit = parseInt(options.limit);\n    } else {\n      transformedOptions.limit = options.limit;\n    }\n  }\n\n  return transformedOptions;\n};\n\n/**\n * Converts Geocoding API options to event schema compatible options\n * @param options\n * @param responseHeaders\n * @returns\n */\nconst transformGeocodingAPIOptionsToEventSchema = (\n  options: GeocodeOptions,\n  responseHeaders?: Headers\n): EventPayloadOptionsData => {\n  const transformedOptions: EventPayloadOptionsData = {};\n\n  if (options.bbox) {\n    if (typeof options.bbox === 'string') {\n      transformedOptions.bbox = options.bbox.split(',').map(Number);\n    } else {\n      transformedOptions.bbox = LngLatBounds.convert(\n        options.bbox\n      ).toFlatArray();\n    }\n  }\n\n  if (options.proximity) {\n    transformedOptions.proximity = parseExplicitOrIPProximity(\n      options.proximity,\n      responseHeaders\n    );\n  }\n\n  if (options.country) {\n    transformedOptions.country = options.country.split(',');\n  }\n\n  if (options.language) {\n    transformedOptions.language = options.language.split(',');\n  }\n\n  if (options.types) {\n    if (typeof options.types === 'string') {\n      transformedOptions.types = options.types.split(',');\n    } else {\n      transformedOptions.types = Array.from(options.types);\n    }\n  }\n\n  if (options.limit) {\n    if (typeof options.limit === 'string') {\n      transformedOptions.limit = parseInt(options.limit);\n    } else {\n      transformedOptions.limit = options.limit;\n    }\n  }\n\n  if (typeof options.autocomplete === 'boolean') {\n    transformedOptions.autocomplete = options.autocomplete;\n  }\n\n  if (options.worldview) {\n    transformedOptions.worldview = options.worldview;\n  }\n\n  if (options.permanent) {\n    transformedOptions.permanent = options.permanent;\n  }\n\n  return transformedOptions;\n};\n\n/**\n * Converts Address Autofill API options to event schema compatible options\n * @param options\n * @param responseHeaders\n * @returns\n */\nconst transformAddressAutofillAPIOptionsToEventSchema = (\n  options: AddressAutofillOptions,\n  responseHeaders?: Headers\n): EventPayloadOptionsData => {\n  const transformedOptions: EventPayloadOptionsData = {};\n\n  if (options.bbox) {\n    if (typeof options.bbox === 'string') {\n      transformedOptions.bbox = options.bbox.split(',').map(Number);\n    } else {\n      transformedOptions.bbox = LngLatBounds.convert(\n        options.bbox\n      ).toFlatArray();\n    }\n  }\n\n  if (options.proximity) {\n    transformedOptions.proximity = parseExplicitOrIPProximity(\n      options.proximity,\n      responseHeaders\n    );\n  }\n\n  if (options.country) {\n    transformedOptions.country = options.country.split(',');\n  }\n\n  if (options.language) {\n    transformedOptions.language = options.language.split(',');\n  }\n\n  if (options.limit) {\n    if (typeof options.limit === 'string') {\n      transformedOptions.limit = parseInt(options.limit);\n    } else {\n      transformedOptions.limit = options.limit;\n    }\n  }\n\n  if (options.streets !== undefined && options.streets !== null) {\n    if (typeof options.streets === 'string') {\n      transformedOptions.streets = options.streets === 'true';\n    } else {\n      transformedOptions.streets = options.streets;\n    }\n  }\n\n  return transformedOptions;\n};\n\n/**\n * Converts API-specific options to event schema compatible options\n * @param options API options\n * @param service Search service (SearchBox, Geocoding, AddressAutofill)\n * @param responseHeaders Response headers returned by the API\n * @returns\n */\nexport const transformApiOptionsForEventSchema = (\n  options: Options,\n  service: SEARCH_SERVICE,\n  responseHeaders?: Headers\n): EventPayloadOptionsData => {\n  switch (service) {\n    case SEARCH_SERVICE.SearchBox:\n      return transformSearchBoxAPIOptionsToEventSchema(\n        options as SearchBoxOptions\n      );\n    case SEARCH_SERVICE.Geocoding:\n      return transformGeocodingAPIOptionsToEventSchema(\n        options as GeocodeOptions,\n        responseHeaders\n      );\n    case SEARCH_SERVICE.AddressAutofill:\n      return transformAddressAutofillAPIOptionsToEventSchema(\n        options as AddressAutofillOptions,\n        responseHeaders\n      );\n  }\n};\n\n/**\n * Converts SearchBox API suggestions to event schema compatible suggestions\n * @param suggestions SearchBox API suggestions\n * @returns\n */\nconst transformSearchBoxAPISuggestionsToEventSchema = (\n  suggestions: SearchBoxSuggestion[]\n): EventPayloadSuggestionsData => {\n  return {\n    suggestionIds: suggestions.map((suggestion) => suggestion.mapbox_id || ''),\n    suggestionNames: suggestions.map((suggestion) => {\n      if (suggestion.feature_type === 'poi') {\n        return [suggestion.name, suggestion.full_address]\n          .filter(Boolean)\n          .join(', ');\n      } else if (suggestion.full_address) {\n        return suggestion.full_address; // addresses, places\n      } else {\n        return suggestion.name; // brand, category\n      }\n    }),\n    suggestionTypes: suggestions.map(\n      (suggestion) => suggestion.feature_type || ''\n    ),\n    suggestionSources: suggestions.map((suggestion) => suggestion._source || '')\n  };\n};\n\n/**\n * Converts Geocoding API suggestions to event schema compatible suggestions\n * @param suggestions Geocoding API suggestions\n * @returns\n */\nconst transformGeocodingAPISuggestionsToEventSchema = (\n  suggestions: GeocodeFeature[]\n): EventPayloadSuggestionsData => {\n  return {\n    suggestionIds: suggestions.map(\n      (suggestion) => suggestion.properties.mapbox_id || suggestion.id || ''\n    ),\n    suggestionNames: suggestions.map(\n      (suggestion) => suggestion.properties.full_address || ''\n    ),\n    suggestionTypes: suggestions.map(\n      (suggestion) => suggestion.properties.feature_type || ''\n    ),\n    suggestionSources: suggestions.map((suggestion) => suggestion._source || '')\n  };\n};\n\n/**\n * Converts Address Autofill API suggestions to event schema compatible suggestions\n * @param suggestions Address Autofill API suggestions\n * @returns\n */\nconst transformAddressAutofillAPISuggestionsToEventSchema = (\n  suggestions: AddressAutofillSuggestion[]\n): EventPayloadSuggestionsData => {\n  return {\n    suggestionIds: suggestions.map((suggestion) => suggestion.mapbox_id || ''),\n    suggestionNames: suggestions.map(\n      (suggestion) => suggestion.full_address || ''\n    ),\n    suggestionTypes: suggestions.map(\n      (suggestion) => suggestion.place_type?.[0] || ''\n    ),\n    suggestionSources: suggestions.map((suggestion) => suggestion._source || '')\n  };\n};\n\n/**\n * Converts API-specific suggestions to event schema compatible suggestions\n * @param suggestions API suggestions\n * @param service Search service (SearchBox, Geocoding, AddressAutofill)\n * @returns\n */\nexport const transformSuggestionsForEventSchema = (\n  suggestions: Suggestion[],\n  service: SEARCH_SERVICE\n): EventPayloadSuggestionsData => {\n  switch (service) {\n    case SEARCH_SERVICE.SearchBox:\n      return transformSearchBoxAPISuggestionsToEventSchema(\n        suggestions as SearchBoxSuggestion[]\n      );\n    case SEARCH_SERVICE.Geocoding:\n      return transformGeocodingAPISuggestionsToEventSchema(\n        suggestions as GeocodeFeature[]\n      );\n    case SEARCH_SERVICE.AddressAutofill:\n      return transformAddressAutofillAPISuggestionsToEventSchema(\n        suggestions as AddressAutofillSuggestion[]\n      );\n  }\n};\n\n/**\n * Get the search URL path based on the search service\n * @param service Search service (SearchBox, Geocoding, AddressAutofill)\n * @param queryString The search query string\n * @returns\n */\nexport const getSearchUrlPath = (\n  service: SEARCH_SERVICE,\n  queryString?: string\n): string => {\n  switch (service) {\n    case SEARCH_SERVICE.SearchBox:\n      return 'search/searchbox/v1/suggest';\n    case SEARCH_SERVICE.Geocoding: {\n      const isReverseQuery =\n        /^[ ]*(-?\\d{1,3}(\\.\\d{0,256})?)[, ]+(-?\\d{1,3}(\\.\\d{0,256})?)[ ]*$/.test(\n          queryString\n        );\n      return `search/geocode/v6/${isReverseQuery ? 'reverse' : 'forward'}`;\n    }\n    case SEARCH_SERVICE.AddressAutofill:\n      return 'autofill/v1/suggest';\n  }\n};\n","import { SEARCH_SERVICE } from '../utils/services';\nimport {\n  EventPayloadOptionsData,\n  Options,\n  Suggestion,\n  getSearchUrlPath,\n  transformApiOptionsForEventSchema,\n  transformSuggestionsForEventSchema\n} from './utils';\nimport { version as SDK_VERSION, name as SDK_NAME } from '../../package.json';\nimport mapboxgl from 'mapbox-gl';\n\ntype SearchEventType = 'search.start' | 'search.keystroke' | 'search.select';\n\ninterface SearchEventBasePayload {\n  // event metadata\n  event: SearchEventType; // REQUIRED\n  created: number; // REQUIRED\n  version?: string;\n  // environment info\n  userAgent?: string;\n  keyboardLocale?: string;\n  // session info\n  sessionIdentifier: string; // REQUIRED\n  // map info\n  mapZoom?: number;\n  mapCenterLng?: number;\n  mapCenterLat?: number;\n  // search config/options\n  country?: string[];\n  language?: string[];\n  bbox?: number[];\n  types?: string[];\n  endpoint?: string;\n  autocomplete?: boolean;\n  fuzzyMatch?: boolean;\n  proximity?: number[];\n  limit?: number;\n  routing?: boolean;\n  worldview?: string;\n  // request info\n  queryString: string; // REQUIRED\n}\n\ninterface SearchEventStartPayload extends SearchEventBasePayload {\n  event: 'search.start';\n}\n\ninterface SearchEventKeystrokePayload extends SearchEventBasePayload {\n  event: 'search.keystroke';\n  lastAction: string; // REQUIRED\n  path?: string;\n  streets?: boolean;\n  permanent?: boolean;\n}\n\ninterface SearchEventSelectPayload extends SearchEventBasePayload {\n  event: 'search.select';\n  resultIndex: number; // REQUIRED\n  resultPlaceName?: string;\n  resultId?: string;\n  path: string; // REQUIRED\n  streets?: boolean;\n  permanent?: boolean;\n  suggestionIds: string[]; // REQUIRED\n  suggestionNames?: string[];\n  suggestionTypes?: string[];\n  suggestionSources?: string[];\n  resultMapboxId?: string;\n}\n\ntype SearchEventPayload =\n  | SearchEventStartPayload\n  | SearchEventKeystrokePayload\n  | SearchEventSelectPayload;\n\ninterface SessionTokenOptions {\n  sessionToken: string;\n}\n\ninterface AccessTokenOptions {\n  accessToken: string;\n}\n\ntype EventOptions = Options & SessionTokenOptions & AccessTokenOptions;\n\ninterface SearchEventArgs {\n  queryString: string;\n  lastInput?: string;\n  selectedIndex?: number;\n  suggestions?: Suggestion[];\n  options: EventOptions;\n  map?: mapboxgl.Map;\n  responseHeaders?: Headers;\n}\n\nexport class MapboxEventManager {\n  #origin = 'https://api.mapbox.com';\n  #endpoint = 'events/v2';\n  #access_token: string;\n  #userAgent: string;\n  #locale = navigator.language || null;\n  #eventQueue: SearchEventPayload[] = [];\n\n  // keep some state to deduplicate requests if necessary\n  #lastSentInput = '';\n  #lastSentIndex = 0;\n\n  // track if session is new or continuing\n  #fresh = true;\n\n  #flushInterval = 1000;\n  #maxQueueSize = 100;\n  #timer: NodeJS.Timeout;\n\n  #service: SEARCH_SERVICE;\n\n  constructor(service: SEARCH_SERVICE) {\n    this.#service = service;\n    this.#userAgent = this.#getUserAgent();\n    this.#timer = setTimeout(this.#flush, this.#flushInterval);\n  }\n\n  /**\n   * Send a search.start event to the mapbox events service\n   * This turnstile event marks when a user starts a new search\n   * @param queryString The value of the search query string\n   * @param options API options\n   * @param map A mapbox-gl map instance\n   * @param responseHeaders API response headers\n   * @returns\n   */\n  start = (\n    queryString: string,\n    options: EventOptions,\n    map?: mapboxgl.Map,\n    responseHeaders?: Headers\n  ): void => {\n    this.#access_token = options.accessToken;\n\n    const payload = this.#getEventPayload('search.start', {\n      queryString,\n      options,\n      map,\n      responseHeaders\n    }) as SearchEventStartPayload;\n    if (!payload) return; // reject malformed event\n    this.#push(payload);\n  };\n\n  /**\n   * Send a search.keystroke event to the mapbox events service\n   * This event records each time the input is changed\n   * @param queryString The value of the search query string\n   * @param lastInput The last character(s) typed by the user\n   * @param options API options\n   * @param map A mapbox-gl map instance\n   * @param responseHeaders API response headers\n   * @returns\n   */\n  input = (\n    queryString: string,\n    lastInput: string,\n    options: EventOptions,\n    map?: mapboxgl.Map,\n    responseHeaders?: Headers\n  ): void => {\n    this.#access_token = options.accessToken;\n\n    if (this.#fresh) {\n      this.start(queryString, options, map, responseHeaders);\n      this.#fresh = false;\n    }\n\n    // pass invalid event\n    if (!lastInput) return;\n\n    const payload = this.#getEventPayload('search.keystroke', {\n      lastInput,\n      queryString,\n      options,\n      map,\n      responseHeaders\n    }) as SearchEventKeystrokePayload;\n    if (!payload) return; // reject malformed event\n    this.#push(payload);\n  };\n\n  /**\n   * Send a search.select event to the mapbox events service\n   * This event marks the array index of the item selected by the user out of the array of possible suggestions\n   * @param queryString The value of the search query string\n   * @param selectedIndex The index of the selected item in the suggestions array\n   * @param suggestions The array of suggestions presented to the user\n   * @param options API options\n   * @param map A mapbox-gl map instance\n   * @param responseHeaders API response headers\n   * @returns\n   */\n  select = (\n    queryString: string,\n    selectedIndex: number,\n    suggestions: Suggestion[],\n    options: EventOptions,\n    map?: mapboxgl.Map,\n    responseHeaders?: Headers\n  ): void => {\n    this.#access_token = options.accessToken;\n\n    const payload = this.#getEventPayload('search.select', {\n      queryString,\n      selectedIndex,\n      suggestions,\n      options,\n      map,\n      responseHeaders\n    }) as SearchEventSelectPayload;\n\n    if (!payload) return; // reject malformed event\n    if (\n      (payload.resultIndex === this.#lastSentIndex &&\n        payload.queryString === this.#lastSentInput) ||\n      payload.resultIndex === -1\n    ) {\n      // don't log duplicate events if the user re-selected the same feature on the same search\n      return;\n    }\n    this.#lastSentIndex = payload.resultIndex;\n    this.#lastSentInput = payload.queryString;\n    this.#push(payload);\n  };\n\n  /**\n   * End an event session and start a new one\n   */\n  clear = (): void => {\n    this.#fresh = true;\n    this.#lastSentInput = '';\n    this.#lastSentIndex = 0;\n\n    this.#flush();\n  };\n\n  /**\n   * Send an event to the events service\n   * @param payload Event payload\n   */\n  #send = (payload: SearchEventPayload[]): void => {\n    const eventUrl = `${this.#origin}/${this.#endpoint}?access_token=${\n      this.#access_token\n    }`;\n    const requestOptions = this.#getRequestOptions(payload);\n    try {\n      fetch(eventUrl, requestOptions);\n    } catch (err) {\n      this.#handleError(err);\n    }\n  };\n\n  /**\n   * Get http request options\n   * @param payload Event payload\n   * @returns\n   */\n  #getRequestOptions = (payload: SearchEventPayload[]): RequestInit => {\n    if (!Array.isArray(payload)) payload = [payload];\n    const options = {\n      // events must be sent with POST\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json'\n      },\n      body: JSON.stringify(payload) // events are arrays\n    };\n    return options;\n  };\n\n  /**\n   * * Handle an error that occurred while making a request\n   * @param err\n   */\n  #handleError = (err): void => {\n    console.log(err);\n  };\n\n  /**\n   * Get the event payload to send to the events service\n   * @param event the name of the event to send to the events service. Valid options are 'search.start', 'search.keystroke', and 'search.select'.\n   * @param eventArgs Additional arguments needed for certain event types\n   * @returns\n   */\n  #getEventPayload = (\n    event: SearchEventType,\n    eventArgs: SearchEventArgs\n  ): SearchEventPayload => {\n    // Make sure required arguments are present for certain event types\n    if (\n      (event === 'search.select' &&\n        !(\n          typeof eventArgs.selectedIndex === 'number' || eventArgs.suggestions\n        )) ||\n      (event === 'search.keystroke' && !eventArgs.lastInput)\n    ) {\n      return null;\n    }\n\n    const eventApiOptions = transformApiOptionsForEventSchema(\n      eventArgs.options,\n      this.#service,\n      eventArgs.responseHeaders\n    );\n\n    const payload = this.#createBasePayload(\n      event,\n      eventArgs,\n      eventApiOptions\n    ) as SearchEventPayload;\n\n    if (event === 'search.keystroke') {\n      this.#applySearchEventKeystrokePayload(\n        payload as SearchEventKeystrokePayload,\n        eventArgs,\n        eventApiOptions\n      );\n    } else if (event === 'search.select') {\n      this.#applySearchEventSelectPayload(\n        payload as SearchEventSelectPayload,\n        eventArgs,\n        eventApiOptions\n      );\n    }\n\n    // Finally, validate that required properties are present for API compatibility\n    if (!this.#validatePayload(payload)) {\n      return null;\n    }\n\n    return payload;\n  };\n\n  /**\n   * Create a base payload for all event types\n   * @param event\n   * @param eventArgs\n   * @param eventApiOptions\n   * @returns\n   */\n  #createBasePayload = (\n    event: SearchEventType,\n    eventArgs: SearchEventArgs,\n    eventApiOptions: EventPayloadOptionsData\n  ): SearchEventBasePayload => {\n    let payload: SearchEventBasePayload = {\n      event,\n      version: this.#getEventSchemaVersion(event),\n      created: +new Date(),\n      sessionIdentifier: eventArgs.options.sessionToken,\n      userAgent: this.#userAgent,\n      keyboardLocale: this.#locale,\n      queryString: eventArgs.queryString\n    };\n\n    // add API option fields\n    if (eventApiOptions) {\n      payload = {\n        ...payload,\n        ...eventApiOptions\n      };\n    }\n\n    // remove fields incompatible with `search.start` schema\n    if (event === 'search.start') {\n      for (const field of ['streets', 'permanent']) {\n        delete payload[field];\n      }\n    }\n\n    // add map fields\n    if (eventArgs.map) {\n      const zoom = eventArgs.map.getZoom() || undefined;\n      const center = eventArgs.map.getCenter();\n      payload = {\n        ...payload,\n        mapZoom: zoom,\n        mapCenterLat: center.lat,\n        mapCenterLng: center.lng\n      };\n    }\n\n    return payload;\n  };\n\n  #applySearchEventKeystrokePayload = (\n    payload: SearchEventKeystrokePayload,\n    eventArgs: SearchEventArgs,\n    eventOptions: EventPayloadOptionsData\n  ): void => {\n    switch (this.#service) {\n      case SEARCH_SERVICE.AddressAutofill:\n        eventOptions.streets && (payload.streets = eventOptions.streets);\n        break;\n      case SEARCH_SERVICE.Geocoding:\n        eventOptions.permanent && (payload.permanent = eventOptions.permanent);\n        break;\n    }\n    payload.path = getSearchUrlPath(this.#service, eventArgs.queryString);\n    payload.lastAction = eventArgs.lastInput;\n  };\n\n  #applySearchEventSelectPayload = (\n    payload: SearchEventSelectPayload,\n    eventArgs: SearchEventArgs,\n    eventOptions: EventPayloadOptionsData\n  ): void => {\n    switch (this.#service) {\n      case SEARCH_SERVICE.AddressAutofill:\n        eventOptions.streets && (payload.streets = eventOptions.streets);\n        break;\n      case SEARCH_SERVICE.Geocoding:\n        eventOptions.permanent && (payload.permanent = eventOptions.permanent);\n        break;\n    }\n\n    payload.path = getSearchUrlPath(this.#service, eventArgs.queryString);\n\n    const { selectedIndex, suggestions } = eventArgs;\n\n    if (suggestions && suggestions.length > 0) {\n      const eventSchemaSuggestions = transformSuggestionsForEventSchema(\n        suggestions,\n        this.#service\n      );\n\n      // selected feature attributes\n      payload.resultIndex = selectedIndex;\n      payload.resultPlaceName =\n        eventSchemaSuggestions.suggestionNames[selectedIndex];\n      payload.resultId = eventSchemaSuggestions.suggestionIds[selectedIndex];\n      if (payload.resultId.startsWith('dXJuOm1ie')) {\n        payload.resultMapboxId = payload.resultId;\n      }\n\n      // suggestion list attributes\n      payload.suggestionIds = eventSchemaSuggestions.suggestionIds;\n      payload.suggestionNames = eventSchemaSuggestions.suggestionNames;\n      payload.suggestionTypes = eventSchemaSuggestions.suggestionTypes;\n      payload.suggestionSources = eventSchemaSuggestions.suggestionSources;\n    }\n  };\n\n  /**\n   * Get a user agent string to send with the request to the events service\n   * @returns\n   */\n  #getUserAgent = (): string => {\n    return `mapbox.${SDK_NAME.split('/')[1]}.${SDK_VERSION}.${\n      navigator.userAgent\n    }`;\n  };\n\n  /**\n   * Get the correct schema version for the event\n   * @param event Name of the event\n   * @returns\n   */\n  #getEventSchemaVersion = (event: SearchEventType): string => {\n    if (['search.keystroke', 'search.select'].includes(event)) {\n      return '2.2';\n    } else {\n      return '2.0';\n    }\n  };\n\n  /**\n   * Checks if a payload has all the required properties for the event type\n   * @param payload Event payload\n   * @returns\n   */\n  #validatePayload = (payload: SearchEventPayload): boolean => {\n    if (!payload || !payload.event) return false;\n\n    const searchStartRequiredProps = [\n      'event',\n      'created',\n      'sessionIdentifier',\n      'queryString'\n    ];\n    const searchKeystrokeRequiredProps = [\n      'event',\n      'created',\n      'sessionIdentifier',\n      'queryString',\n      'lastAction'\n    ];\n    const searchSelectRequiredProps = [\n      'event',\n      'created',\n      'sessionIdentifier',\n      'queryString',\n      'resultIndex',\n      'path',\n      'suggestionIds'\n    ];\n\n    const event = payload.event;\n    if (event === 'search.start') {\n      return this.#objectHasRequiredProps(payload, searchStartRequiredProps);\n    } else if (event === 'search.keystroke') {\n      return this.#objectHasRequiredProps(\n        payload,\n        searchKeystrokeRequiredProps\n      );\n    } else if (event === 'search.select') {\n      return this.#objectHasRequiredProps(payload, searchSelectRequiredProps);\n    }\n\n    return true;\n  };\n\n  /**\n   * Checks if an object has all the required properties\n   * @param obj Payload object\n   * @param requiredProps Array of required properties to check for\n   * @returns\n   */\n  #objectHasRequiredProps = (\n    obj: SearchEventPayload,\n    requiredProps: string[]\n  ): boolean => {\n    return requiredProps.every((prop) => {\n      if (prop === 'queryString') {\n        return typeof obj[prop] === 'string' && obj[prop].length > 0;\n      }\n      return obj[prop] !== undefined;\n    });\n  };\n\n  /**\n   * Flush out the event queue by sending events to the events service\n   */\n  #flush = (): void => {\n    if (this.#eventQueue.length > 0 && this.#access_token) {\n      this.#send(this.#eventQueue);\n      this.#eventQueue = [];\n    }\n    // //reset the timer\n    if (this.#timer) clearTimeout(this.#timer);\n    if (this.#flushInterval)\n      this.#timer = setTimeout(this.#flush, this.#flushInterval);\n  };\n\n  /**\n   * Push event into the pending queue\n   * @param event the event to send to the events service\n   * @param forceFlush indicates that the event queue should be flushed after adding this event regardless of size of the queue\n   */\n  #push = (event: SearchEventPayload, forceFlush?: boolean): void => {\n    this.#eventQueue.push(event);\n    if (this.#eventQueue.length >= this.#maxQueueSize || forceFlush) {\n      this.#flush();\n    }\n  };\n\n  /**\n   * Flush any remaining events from the queue before it is removed\n   */\n  remove = (): void => {\n    this.#flush();\n  };\n}\n","import {\n  featureToSuggestion,\n  LngLatBounds,\n  SearchSession,\n  SearchBoxCore,\n  SearchBoxOptions,\n  SearchBoxRetrieveResponse,\n  SearchBoxSuggestion,\n  SearchBoxSuggestionResponse,\n  SearchBoxFeatureSuggestion\n} from '@mapbox/search-js-core';\nimport mapboxgl from 'mapbox-gl';\nimport subtag from 'subtag';\n\nimport {\n  MapboxSearchListbox,\n  SelectionEventDetail\n} from './MapboxSearchListbox';\nimport { HTMLScopedElement } from './HTMLScopedElement';\n\nimport { tryParseJSON } from '../utils';\nimport { bboxViewport, FLY_TO_SPEED, getMaxZoom } from '../utils/map';\n\nimport { Theme, getIcon, getThemeCSS } from '../theme';\nimport { MapboxHTMLEvent } from '../MapboxHTMLEvent';\nimport { SEARCHBOX_TEMPLATE } from '../constants';\n\nimport style from '../style.css';\nimport { PopoverOptions } from '../utils/popover';\nimport { createAriaLiveElement } from '../utils/aria';\nimport { bindElements } from '../utils/dom';\nimport { SEARCH_SERVICE } from '../utils/services';\nimport localization from '../utils/localization';\nimport { InputEventDetail } from '../utils/listbox';\nimport { MapboxEventManager } from '../events/MapboxEventManager';\n\n/**\n * Proximity is designed for local scale. If the user is looking at the whole world,\n * it doesn't make sense to factor in the arbitrary center of the map.\n */\nconst MAX_ZOOM = 9;\n\nconst DEFAULT_COMPONENT_OPTIONS: MapboxSearchBoxComponentOptions = {\n  flyTo: true\n};\n\nconst CORE_COMPONENT_OPTION_KEYS: (keyof MapboxSearchBoxComponentOptions)[] = [\n  'allowReverse',\n  'flipCoordinates'\n];\n\n/**\n * Options to configure component-specific Search behavior\n * @typedef MapboxSearchBoxComponentOptions\n */\nexport interface MapboxSearchBoxComponentOptions {\n  /**\n   * Allow the user to query a coordinate string (e.g. \"lng,lat\") to get a reverse search result.\n   */\n  allowReverse?: boolean;\n  /**\n   * If true, the coordinates in the query string are expected to be (lat,lng) instead of (lng,lat).\n   */\n  flipCoordinates?: boolean;\n  /**\n   * If `false`, animating the map to a selected result is disabled. If `true` (default), animating the map will use the default animation parameters. If an object, it will be passed as `options` to the map `flyTo` method.\n   */\n  flyTo?: mapboxgl.FlyToOptions | boolean;\n  /**\n   * A function accepting the query string which performs supplemental search results\n   * on top of those from the Mapbox Search Box API. Expected to return a Promise\n   * which resolves to an array of suggestions as described in the\n   * [Mapbox Search Box API](https://docs.mapbox.com/api/search/search-box/#response-get-suggested-results).\n   * Additionally, each suggestion must include a `_geometry` property matching the\n   * \"geometry\" object format specified in the [retrieved Feature](https://docs.mapbox.com/api/search/search-box/#response-retrieve-a-suggested-feature)\n   * format.\n   * @param text Query text\n   * @returns Promise resolving to an array of properly formatted suggestion objects\n   * @example\n   * ```typescript\n   * async myCustomFunction((query: string) => {\n   *    // Perform custom search logic, e.g. fetch from a local database or API (can be sync or async)\n   *   const customData = await getData();\n   *\n   *   // Format the data and return\n   *   return customData.map(obj => {\n   *     return {\n   *       name: obj.title,\n   *       place_formatted: obj.description,\n   *       full_address: obj.fullName,\n   *       _geometry: { type: 'Point', coordinates: [obj.lng, obj.lat] }\n   *     }\n   *   });\n   * };\n   * ```\n   */\n  customSearch?: (text: string) => Promise<SearchBoxSuggestion[]>;\n}\n\ntype Binding = {\n  /**\n   * Wrapper around the entire SearchBox component.\n   */\n  SearchBox: HTMLElement;\n  /**\n   * Container for search icon preceding input\n   */\n  SearchIcon: HTMLDivElement;\n  /**\n   * The input element accepting search text\n   */\n  Input: HTMLInputElement;\n  /**\n   * Button element used to clear the input element of text\n   */\n  ClearBtn: HTMLButtonElement;\n  /**\n   * Animated loading icon triggered by a keystroke\n   */\n  LoadingIcon: HTMLDivElement;\n};\n\nexport type MapboxSearchListboxSearchType =\n  MapboxSearchListbox<SearchBoxSuggestion>;\n\ntype SearchEventTypes = {\n  /**\n   * Fired when the user is typing and is provided a list of suggestions.\n   *\n   * The underlying response from {@link SearchBoxCore} is passed as the event's detail.\n   *\n   * @event suggest\n   * @instance\n   * @memberof MapboxSearchBox\n   * @type {SearchBoxSuggestionResponse}\n   * @example\n   * ```typescript\n   * search.addEventListener('suggest', (event) => {\n   *   const suggestions = event.detail.suggestions;\n   *   // ...\n   * });\n   * ```\n   */\n  suggest: MapboxHTMLEvent<SearchBoxSuggestionResponse>;\n  /**\n   * Fired when {@link SearchBoxCore} has errored providing a list of suggestions.\n   *\n   * The underlying error is passed as the event's detail.\n   *\n   * @event suggesterror\n   * @instance\n   * @memberof MapboxSearchBox\n   * @type {Error}\n   * @example\n   * ```typescript\n   * search.addEventListener('suggesterror', (event) => {\n   *   const error = event.detail;\n   *   // ...\n   * });\n   * ```\n   */\n  suggesterror: MapboxHTMLEvent<Error>;\n  /**\n   * Fired when the user has selected a suggestion.\n   *\n   * The underlying response from {@link SearchBoxCore} is passed as the event's detail.\n   *\n   * @event retrieve\n   * @instance\n   * @memberof MapboxSearchBox\n   * @type {SearchBoxRetrieveResponse}\n   * @example\n   * ```typescript\n   * search.addEventListener('retrieve', (event) => {\n   *   const featureCollection = event.detail;\n   *   // ...\n   * });\n   * ```\n   */\n  retrieve: MapboxHTMLEvent<SearchBoxRetrieveResponse>;\n  /**\n   * Fired when the user has changed the `<input>` text.\n   *\n   * The new input value is passed as the event's detail.\n   *\n   * @event input\n   * @instance\n   * @memberof MapboxSearchBox\n   * @type {string}\n   * @example\n   * ```typescript\n   * search.addEventListener('input', (event) => {\n   *   if (e.target !== e.currentTarget) return;\n   *   const searchText = event.detail;\n   *   // ...\n   * });\n   * ```\n   */\n  input: MapboxHTMLEvent<string>;\n  /**\n   * Fired when the user has cleared the <input> box,\n   * either by deleting all text or clicking the \"Clear\" icon.\n   *\n   * @event clear\n   * @instance\n   * @memberof MapboxSearchBox\n   * @example\n   * ```typescript\n   * search.addEventListener('clear', () => {\n   *   console.log('search box cleared');\n   *   // ...\n   * });\n   * ```\n   */\n  clear: MapboxHTMLEvent<unknown>;\n  /**\n   * Fired when the user moved focus away from the MapboxSearchBox component.\n   *\n   * @event blur\n   * @instance\n   * @memberof MapboxSearchBox\n   * @example\n   * ```typescript\n   * search.addEventListener('blur', () => {\n   *   console.log('search box blurred');\n   *   // ...\n   * });\n   * ```\n   */\n  blur: MapboxHTMLEvent<unknown>;\n};\n\n/**\n * `MapboxSearchBox`, also available as the element `<mapbox-search-box>`,\n * is an element that lets you search for places, addresses, and landmarks using\n * the [Mapbox Search Box API](https://docs.mapbox.com/api/search/search-box/).\n *\n * It can control a [Mapbox GL JS](https://docs.mapbox.com/mapbox-gl-js/guides/) map\n * to zoom to the selected result.\n *\n * Additionally, `MapboxSearchBox` implements the [IControl](https://www.mapbox.com/mapbox-gl-js/api/markers/#icontrol)\n * interface.\n *\n * To use this element, you must have a [Mapbox access token](https://www.mapbox.com/help/create-api-access-token/).\n *\n * @class MapboxSearchBox\n * @example\n * ```typescript\n * const search = new MapboxSearchBox();\n * search.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN';\n * map.addControl(search);\n * ```\n * @example\n * <mapbox-search-box\n *   access-token=\"YOUR_MAPBOX_ACCESS_TOKEN\"\n *   proximity=\"0,0\"\n * >\n * </mapbox-search-box>\n */\nexport class MapboxSearchBox\n  extends HTMLScopedElement<SearchEventTypes>\n  implements mapboxgl.IControl\n{\n  /**\n   * This is read by the Web Components API to affect the\n   * {@link MapboxSearchBox#attributeChangedCallback} below.\n   *\n   * All of these are passthroughs to the underlying {@link MapboxSearchListbox}.\n   *\n   * @ignore\n   */\n  static observedAttributes: string[] = [\n    // Access token.\n    'access-token',\n    // Theming.\n    'theme',\n    'popover-options',\n    'placeholder',\n    // Component options.\n    'allow-reverse',\n    'flip-coordinates',\n    // Underlying Search Box API options.\n    'language',\n    'country',\n    'bbox',\n    'limit',\n    'navigation-profile',\n    'origin',\n    'proximity',\n    'eta-type',\n    'types'\n  ];\n\n  #binding: Binding;\n\n  #search = new SearchBoxCore({});\n  #session = new SearchSession<\n    SearchBoxOptions,\n    SearchBoxSuggestion,\n    SearchBoxSuggestionResponse,\n    SearchBoxRetrieveResponse\n  >(this.#search);\n\n  /**\n   * The [Mapbox access token](https://docs.mapbox.com/help/glossary/access-token/) to use for all requests.\n   *\n   * @name accessToken\n   * @instance\n   * @memberof MapboxSearchBox\n   * @example\n   * ```typescript\n   * search.accessToken = 'pk.my-mapbox-access-token';\n   * ```\n   */\n  get accessToken(): string {\n    return this.#search.accessToken;\n  }\n  set accessToken(newToken: string) {\n    this.#search.accessToken = newToken;\n  }\n\n  /**\n   * The value of the input element.\n   *\n   * @name value\n   * @instance\n   * @memberof MapboxSearchBox\n   * @example\n   * ```typescript\n   * console.log(search.value);\n   * ```\n   */\n  get value(): string {\n    return this.#input.value;\n  }\n  set value(newValue: string) {\n    this.#input.value = newValue || '';\n  }\n\n  #map: mapboxgl.Map | null = null;\n\n  #input: HTMLInputElement;\n  #listbox: MapboxSearchListboxSearchType = new MapboxSearchListbox();\n\n  #eventManager = new MapboxEventManager(SEARCH_SERVICE.SearchBox);\n\n  /**\n   * The `<input>` element wrapped by the MapboxSearchBox component.\n   *\n   * @name input\n   * @instance\n   * @memberof MapboxSearchBox\n   * @type {HTMLInputElement}\n   */\n  get input(): HTMLInputElement {\n    return this.#input;\n  }\n\n  protected override get template(): HTMLTemplateElement {\n    return SEARCHBOX_TEMPLATE;\n  }\n\n  protected override get templateStyle(): string {\n    return style;\n  }\n\n  protected override get templateUserStyle(): string {\n    return getThemeCSS('.SearchBox', this.#listbox.theme);\n  }\n\n  /**\n   * API-specific options to pass to the underlying {@link SearchBoxCore} interface.\n   *\n   * @name options\n   * @instance\n   * @memberof MapboxSearchBox\n   * @type {SearchBoxOptions}\n   * @example\n   * ```typescript\n   * search.options = {\n   *  language: 'en',\n   *  country: 'US',\n   * };\n   * ```\n   */\n  options: Partial<SearchBoxOptions> = {};\n\n  #componentOptions: Partial<MapboxSearchBoxComponentOptions> = {\n    ...DEFAULT_COMPONENT_OPTIONS\n  };\n\n  /**\n   * Options defining the behavior of web component or its underlying search functionality.\n   * Distinct from the {@link SearchBoxOptions} options, these do not correspond to the core API specification.\n   *\n   * @name componentOptions\n   * @instance\n   * @memberof MapboxSearchBox\n   * @type {MapboxSearchBoxComponentOptions}\n   * @example\n   * ```typescript\n   * search.componentOptions = {\n   *  allowReverse: true,\n   *  flipCoordinates: true,\n   *  flyTo: true\n   * };\n   * ```\n   */\n  get componentOptions(): MapboxSearchBoxComponentOptions {\n    return this.#componentOptions;\n  }\n  set componentOptions(options: Partial<MapboxSearchBoxComponentOptions>) {\n    this.#componentOptions = {\n      ...DEFAULT_COMPONENT_OPTIONS,\n      ...options\n    };\n  }\n\n  /**\n   * Extracts the subset of the componentOptions that are relevant to SearchBoxCore\n   */\n  #getCoreComponentOptions = (): MapboxSearchBoxComponentOptions => {\n    const options = { ...this.componentOptions };\n    for (const key in options) {\n      if (\n        CORE_COMPONENT_OPTION_KEYS.indexOf(\n          key as keyof MapboxSearchBoxComponentOptions\n        ) === -1\n      ) {\n        delete options[key];\n      }\n    }\n    return options;\n  };\n\n  /**\n   * The {@link Theme} to use for styling the suggestion box and search box.\n   *\n   * @name theme\n   * @instance\n   * @memberof MapboxSearchBox\n   * @type {Theme}\n   * @example\n   * ```typescript\n   * search.theme = {\n   *   variables: {\n   *     colorPrimary: 'myBrandRed'\n   *   },\n   *   cssText: \".Input:active { opacity: 0.9; }\"\n   * };\n   * ```\n   */\n  get theme(): Theme {\n    return this.#listbox.theme;\n  }\n  set theme(theme: Theme) {\n    this.#listbox.theme = theme;\n\n    if (!this.#binding || !theme) {\n      return;\n    }\n\n    this.updateTemplateUserStyle(getThemeCSS('.SearchBox', theme));\n    this.#listbox.updatePopover();\n\n    const { SearchIcon } = this.#binding;\n    SearchIcon.innerHTML = getIcon('search', theme);\n  }\n\n  /**\n   * The {@link PopoverOptions} to define popover positioning.\n   *\n   * @name popoverOptions\n   * @instance\n   * @memberof MapboxSearchBox\n   * @type {PopoverOptions}\n   * @example\n   * ```typescript\n   * search.popoverOptions = {\n   *   placement: 'top-start',\n   *   flip: true,\n   *   offset: 5\n   * };\n   * ```\n   */\n  get popoverOptions(): Partial<PopoverOptions> {\n    return this.#listbox.popoverOptions;\n  }\n  set popoverOptions(newOptions: Partial<PopoverOptions>) {\n    this.#listbox.popoverOptions = newOptions;\n  }\n\n  #getDefaultPlaceholder(): string {\n    if (this.options.language) {\n      const firstLanguage = this.options.language.split(',')[0];\n      const language = subtag.language(firstLanguage);\n      const localizedValue = localization.placeholder[language];\n      if (localizedValue) return localizedValue;\n    }\n    return 'Search';\n  }\n\n  #placeholder: string;\n\n  /**\n   * The input element's placeholder text. The default value may be localized if {@link SearchBoxOptions#language} is set.\n   *\n   * @name placeholder\n   * @instance\n   * @memberof MapboxSearchBox\n   * @type {string}\n   */\n  get placeholder(): string {\n    return this.#placeholder || this.#getDefaultPlaceholder();\n  }\n\n  set placeholder(text: string) {\n    this.#placeholder = text;\n    if (this.#input) {\n      this.#input.placeholder = this.placeholder;\n      this.#input.setAttribute('aria-label', this.placeholder);\n    }\n  }\n\n  #handleSuggest = async (\n    result: SearchBoxSuggestionResponse\n  ): Promise<void> => {\n    this.#setActionIcons();\n\n    let suggestions: SearchBoxSuggestion[] | null = null;\n\n    // Integrate optional custom search results\n    if (this.componentOptions.customSearch) {\n      const customFeatures = await this.componentOptions.customSearch(\n        this.value\n      );\n      if (customFeatures && customFeatures.length) {\n        customFeatures.forEach((feature) => {\n          feature._source = 'custom';\n        });\n        suggestions = customFeatures;\n      }\n    }\n\n    // Integrate results from the Mapbox Geocoding API\n    if (result && result.suggestions) {\n      if (!suggestions) {\n        suggestions = result.suggestions;\n      } else {\n        suggestions = suggestions.concat(result.suggestions);\n      }\n    }\n\n    this.#listbox.handleSuggest(suggestions || null);\n\n    // If focus is not already on the web component, focus it.\n    // This ensures that a future 'blur' event is available to hide the results.\n    // This could happen under the following scenarios:\n    // 1. User types in the input, then moves focus away before suggestions return\n    // 2. Suggest is triggered programmatically via the search() method\n    // 3. Browser autofill (e.g. for Safari iOS) removes focus from the input\n    if (!this.#binding.SearchBox.contains(document.activeElement)) {\n      this.focus();\n    }\n\n    // Manually bubble up the event.\n    this.dispatchEvent(new MapboxHTMLEvent('suggest', result));\n  };\n\n  #handleSuggestError = async (error: Error): Promise<void> => {\n    this.#setActionIcons();\n\n    if (this.componentOptions.customSearch) {\n      // If a custom search function is provided, attempt to generate and render suggestions from it\n      const customFeatures = await this.componentOptions.customSearch(\n        this.value\n      );\n      if (customFeatures && customFeatures.length) {\n        customFeatures.forEach((feature) => {\n          feature._source = 'custom';\n        });\n        this.#listbox.handleSuggest(customFeatures || null);\n      } else {\n        this.#listbox.handleError();\n      }\n    } else {\n      // Otherwise, hide the listbox\n      this.#listbox.handleError();\n    }\n\n    // Manually bubble up the event.\n    this.dispatchEvent(new MapboxHTMLEvent('suggesterror', error));\n  };\n\n  #handleRetrieve = (result: SearchBoxRetrieveResponse): void => {\n    this.#setActionIcons();\n\n    // Manually bubble up the event.\n    this.dispatchEvent(new MapboxHTMLEvent('retrieve', result));\n\n    const featureCollection = result;\n    if (!featureCollection || !featureCollection.features.length) {\n      return;\n    }\n\n    // Set value of the input.\n    const suggestion = featureToSuggestion(featureCollection.features[0]);\n    this.#input.value = suggestion.name;\n\n    const feature = featureCollection.features[0];\n\n    if (!feature) {\n      return;\n    }\n\n    const map = this.#map;\n    if (!map) {\n      return;\n    }\n\n    if (this.componentOptions.flyTo) {\n      this.#fly(feature);\n    }\n\n    // Add marker to map\n    if (this.marker && this.mapboxgl) {\n      this.#handleMarker(feature);\n    }\n  };\n\n  #mapMarker: mapboxgl.Marker;\n\n  /**\n   * Handle the removal of a feature marker\n   */\n  #removeMarker = (): void => {\n    if (this.#mapMarker) {\n      this.#mapMarker.remove();\n      this.#mapMarker = null;\n    }\n  };\n\n  /**\n   * Handle the placement of a marker for the selected feature\n   */\n  #handleMarker = (feature: SearchBoxFeatureSuggestion | null): void => {\n    // clean up any old marker that might be present\n    if (!this.#map) {\n      return;\n    }\n    this.#removeMarker();\n\n    if (!feature) return;\n\n    const defaultMarkerOptions = {\n      color: '#4668F2'\n    };\n    const markerOptions = {\n      ...defaultMarkerOptions,\n      ...(typeof this.marker === 'object' && this.marker)\n    };\n    this.#mapMarker = new this.mapboxgl.Marker(markerOptions);\n    if (\n      feature.geometry &&\n      feature.geometry.type &&\n      feature.geometry.type === 'Point' &&\n      feature.geometry.coordinates\n    ) {\n      this.#mapMarker\n        .setLngLat(feature.geometry.coordinates as mapboxgl.LngLatLike)\n        .addTo(this.#map);\n    }\n  };\n\n  /**\n   * A callback providing the opportunity to validate and/or manipulate the input text before it triggers a search, for example by using a regular expression.\n   * If a truthy string value is returned, it will be passed into the underlying search API. If `null`, `undefined` or empty string is returned, no search request will be performed.\n   *\n   * @name interceptSearch\n   * @instance\n   * @memberof MapboxSearchBox\n   * @example\n   * Enable search only when the input value length is more than 3 characters.\n   * ```typescript\n   * search.interceptSearch = (val) => val?.length > 3 ? val : null;\n   * ```\n   */\n  interceptSearch: (val: string) => string = null;\n\n  #onHandleInput = (e: MapboxHTMLEvent<InputEventDetail>): void => {\n    // Manually bubble up the event as a basic input event.\n    this.dispatchEvent(\n      new MapboxHTMLEvent<string>('input', e.detail.inputText)\n    );\n\n    const { lastInput, inputText } = e.detail;\n\n    // Clear text, suggestions, markers, etc. if empty string\n    if (!inputText) {\n      this.#handleClear();\n      return;\n    }\n\n    const alteredText = this.interceptSearch && this.interceptSearch(inputText);\n\n    const searchText = this.interceptSearch ? alteredText : inputText;\n\n    if (this.interceptSearch && !alteredText) {\n      this.#listbox.hideResults();\n      return;\n    }\n\n    this.#session.suggest(searchText, {\n      ...this.options,\n      ...this.#getCoreComponentOptions()\n    });\n    this.#eventManager.input(\n      searchText,\n      lastInput,\n      {\n        ...this.options,\n        sessionToken: this.#session.sessionToken,\n        accessToken: this.accessToken\n      },\n      this.#map\n    );\n\n    this.#setActionIcons(true);\n  };\n\n  #onHandleSelect = (\n    e: MapboxHTMLEvent<SelectionEventDetail<SearchBoxSuggestion>>\n  ): void => {\n    const { suggestion, selectedIndex } = e.detail;\n    this.#session.retrieve(suggestion, this.options);\n    this.#eventManager.select(\n      this.value,\n      selectedIndex,\n      this.#listbox.suggestions,\n      {\n        ...this.options,\n        sessionToken: this.#session.sessionToken,\n        accessToken: this.accessToken\n      },\n      this.#map\n    );\n\n    this.#setActionIcons(true);\n  };\n\n  #onHandleBlur = (): void => {\n    // Placeholder for any future listbox blur handling\n  };\n\n  #onHandleFocusOut = (event: FocusEvent): void => {\n    // Only trigger when focus moves outside the SearchBox container\n    if (\n      !this.#binding.SearchBox.contains(event.relatedTarget as Node) &&\n      !this.#listbox.contains(event.relatedTarget as Node)\n    ) {\n      this.#onHandleBlur();\n      this.#listbox.hideResults();\n      this.dispatchEvent(new MapboxHTMLEvent('blur'));\n    }\n  };\n\n  #setActionIcons = (loading = false): void => {\n    if (loading) {\n      this.#binding.ClearBtn.style.display = 'none';\n      this.#binding.LoadingIcon.style.display = 'block';\n    } else {\n      this.#binding.LoadingIcon.style.display = 'none';\n      this.#binding.ClearBtn.style.display = this.value ? 'block' : 'none';\n    }\n  };\n\n  #handleClear = (): void => {\n    this.value = '';\n    this.#setActionIcons();\n    this.#handleMarker(null);\n    this.#listbox.handleSuggest(null);\n    this.#listbox.focus();\n\n    this.#eventManager.clear();\n    this.#session.incrementSession();\n\n    // Manually bubble up the event.\n    this.dispatchEvent(new MapboxHTMLEvent('clear'));\n  };\n\n  /** @section {Map settings} */\n\n  /**\n   * A [mapbox-gl](https://github.com/mapbox/mapbox-gl-js) instance to use when creating [Markers](https://docs.mapbox.com/mapbox-gl-js/api/#marker). Required if {@link MapboxSearchBox#marker} is `true`.\n   *\n   * @name mapboxgl\n   * @instance\n   * @memberof MapboxSearchBox\n   */\n  mapboxgl: typeof mapboxgl;\n\n  /**\n   * If `true`, a [Marker](https://docs.mapbox.com/mapbox-gl-js/api/#marker) will be added to the map at the location of the user-selected result using a default set of Marker options.  If the value is an object, the marker will be constructed using these options. If `false`, no marker will be added to the map. Requires that {@link MapboxSearchBox#mapboxgl} also be set.\n   *\n   * @name marker\n   * @instance\n   * @memberof MapboxSearchBox\n   * @type {boolean | mapboxgl.MarkerOptions}\n   * @example\n   * ```typescript\n   * search.marker = {\n   *   color: 'red',\n   *   draggable: true\n   * };\n   * ```\n   */\n  marker: boolean | mapboxgl.MarkerOptions = true;\n\n  override connectedCallback(): void {\n    super.connectedCallback();\n\n    this.#binding = bindElements<Binding>(this, {\n      SearchBox: '.SearchBox',\n      SearchIcon: '.SearchIcon',\n      Input: '.Input',\n      ClearBtn: '.ClearBtn',\n      LoadingIcon: '.LoadingIcon'\n    });\n\n    // Initialize theme if not set before connectedCallback\n    this.theme = { ...this.theme };\n\n    const { Input, ClearBtn, SearchBox } = this.#binding;\n\n    SearchBox.addEventListener('focusout', this.#onHandleFocusOut);\n\n    this.#input = Input;\n    this.#listbox.input = Input;\n    this.#listbox.searchService = SEARCH_SERVICE.SearchBox;\n\n    this.#listbox.addEventListener('input', this.#onHandleInput);\n    this.#listbox.addEventListener('select', this.#onHandleSelect);\n    this.#listbox.addEventListener('blur', this.#onHandleBlur);\n\n    this.#session.addEventListener('suggest', this.#handleSuggest);\n    this.#session.addEventListener('suggesterror', this.#handleSuggestError);\n    this.#session.addEventListener('retrieve', this.#handleRetrieve);\n\n    ClearBtn.addEventListener('click', this.#handleClear);\n\n    this.placeholder = this.#placeholder;\n\n    this.parentElement.appendChild(this.#listbox);\n\n    if (Input) {\n      // Remove any existing aria-live element that may be left over from, e.g., cloning the node\n      if (Input.previousElementSibling.hasAttribute('aria-live')) {\n        Input.previousElementSibling.remove();\n      }\n      Input.insertAdjacentElement(\n        'beforebegin',\n        createAriaLiveElement(this.#listbox.dataSeed)\n      );\n    }\n  }\n\n  disconnectedCallback(): void {\n    const { SearchBox } = this.#binding;\n    SearchBox.removeEventListener('focusout', this.#onHandleFocusOut);\n\n    this.#listbox.remove();\n    this.#listbox.input = null;\n\n    this.#listbox.removeEventListener('input', this.#onHandleInput);\n    this.#listbox.removeEventListener('select', this.#onHandleSelect);\n    this.#listbox.removeEventListener('blur', this.#onHandleBlur);\n\n    this.#session.removeEventListener('suggest', this.#handleSuggest);\n    this.#session.removeEventListener('suggesterror', this.#handleSuggestError);\n    this.#session.removeEventListener('retrieve', this.#handleRetrieve);\n\n    this.#eventManager.remove();\n  }\n\n  attributeChangedCallback(\n    name: string,\n    oldValue: string,\n    newValue: string\n  ): void {\n    if (name === 'access-token') {\n      this.#search.accessToken = newValue;\n      return;\n    }\n\n    if (name === 'theme') {\n      this.theme = tryParseJSON(newValue);\n      return;\n    }\n\n    if (name === 'popover-options') {\n      this.popoverOptions = tryParseJSON(newValue);\n      return;\n    }\n\n    if (name === 'placeholder') {\n      this.placeholder = newValue;\n      return;\n    }\n\n    if (name === 'allow-reverse') {\n      this.componentOptions.allowReverse = ['true', ''].includes(newValue);\n      return;\n    }\n\n    if (name === 'flip-coordinates') {\n      this.componentOptions.flipCoordinates = ['true', ''].includes(newValue);\n      return;\n    }\n\n    // Convert to the proper name for options.\n    // Example: eta-type => eta_type\n    const optionName = name.split('-').join('_');\n\n    if (!newValue) {\n      delete this.options[optionName];\n    }\n\n    // Otherwise, assume it's a Search Box API option.\n    this.options[optionName] = newValue;\n\n    if (optionName === 'language') {\n      this.placeholder = this.#placeholder;\n    }\n  }\n\n  /** @section {Methods} */\n\n  /**\n   * Focuses the input element.\n   */\n  focus(): void {\n    this.#listbox.focus();\n  }\n\n  /**\n   * Sets the input text and triggers a search programmatically\n   */\n  search(text: string): void {\n    this.value = text;\n    const payload: InputEventDetail = {\n      lastInput: text,\n      inputText: text\n    };\n    this.#onHandleInput(new MapboxHTMLEvent('input', payload));\n  }\n\n  #handleMoveEnd = (): void => {\n    const map = this.#map;\n    const options = { ...this.options };\n\n    if (map.getZoom() <= MAX_ZOOM) {\n      delete options.proximity;\n      this.options = options;\n\n      return;\n    }\n\n    const center = map.getCenter();\n    this.options = {\n      ...options,\n      proximity: center\n    };\n  };\n\n  #fly = (feature: SearchBoxFeatureSuggestion): void => {\n    const map = this.#map;\n    if (!map) {\n      return;\n    }\n\n    const placeType = feature.properties.feature_type;\n\n    let flyToOptions: mapboxgl.FlyToOptions;\n\n    const bounds = feature.properties.bbox;\n    if (bounds) {\n      flyToOptions = bboxViewport(\n        map,\n        LngLatBounds.convert(bounds).toFlatArray()\n      );\n    } else {\n      const center = feature.geometry.coordinates as mapboxgl.LngLatLike;\n      const zoom = getMaxZoom(placeType);\n      flyToOptions = {\n        center,\n        zoom,\n        speed: FLY_TO_SPEED\n      };\n    }\n\n    // If the user has set a custom flyTo option, merge it with the default options.\n    flyToOptions = Object.assign(flyToOptions, this.componentOptions.flyTo);\n    map.flyTo(flyToOptions);\n  };\n\n  /** @section {Map binding} */\n\n  /**\n   * Connects the search box to a [Map](https://docs.mapbox.com/mapbox-gl-js/api/#map),\n   * which handles both setting proximity and zoom after a suggestion click.\n   *\n   * @example\n   * ```typescript\n   * const search = new MapboxSearchBox();\n   * search.bindMap(map);\n   * ```\n   */\n  bindMap(map: mapboxgl.Map): void {\n    if (this.#map) {\n      this.#map.off('moveend', this.#handleMoveEnd);\n    }\n\n    if (map) {\n      map.on('moveend', this.#handleMoveEnd);\n    }\n\n    this.#map = map;\n  }\n\n  /**\n   * Unbinds the search box from a [Map](https://docs.mapbox.com/mapbox-gl-js/api/#map).\n   */\n  unbindMap(): void {\n    this.bindMap(null);\n  }\n\n  // IControl interface.\n\n  // eslint-disable-next-line custom-elements/no-method-prefixed-with-on\n  onAdd(map: mapboxgl.Map): HTMLElement {\n    this.bindMap(map);\n    this.remove();\n\n    const container = document.createElement('div');\n    container.className = 'mapboxgl-ctrl';\n    container.style.width = '300px';\n    container.appendChild(this);\n\n    return container;\n  }\n\n  // eslint-disable-next-line custom-elements/no-method-prefixed-with-on\n  onRemove(): void {\n    this.remove();\n    this.unbindMap();\n    this.#removeMarker();\n  }\n\n  getDefaultPosition(): string {\n    return 'top-right';\n  }\n}\n\ndeclare global {\n  interface Window {\n    MapboxSearchBox: typeof MapboxSearchBox;\n  }\n}\n\nwindow.MapboxSearchBox = MapboxSearchBox;\n\nif (!window.customElements.get('mapbox-search-box')) {\n  customElements.define('mapbox-search-box', MapboxSearchBox);\n}\n","/**\n * Localized values for the placeholder string\n */\nconst placeholder = {\n  //  list drawn from https://docs.mapbox.com/api/search/#language-coverage\n  de: 'Suche', //  german\n  it: 'Ricerca', // italian\n  en: 'Search', //  english\n  nl: 'Zoeken', // dutch\n  fr: 'Chercher', // french\n  ca: 'Cerca', // catalan\n  he: 'לחפש', // hebrew\n  ja: 'サーチ', // japanese\n  lv: 'Meklēt', // latvian\n  pt: 'Procurar', // portuguese\n  sr: 'Претрага', // serbian\n  zh: '搜索', // chinese-simplified\n  cs: 'Vyhledávání', // czech\n  hu: 'Keresés', // hungarian\n  ka: 'ძიება', //  georgian\n  nb: 'Søke', // norwegian\n  sk: 'Vyhľadávanie', // slovak\n  th: 'ค้นหา', // thai\n  fi: 'Hae', // finnish\n  is: 'Leita', // icelandic\n  ko: '수색', // korean\n  pl: 'Szukaj', // polish\n  sl: 'Iskanje', // slovenian\n  fa: 'جستجو', // persian(aka farsi)\n  ru: 'Поиск' // russian\n};\n\nexport default { placeholder };\n","import {\n  LngLatBounds,\n  SearchSession,\n  GeocodingCore,\n  GeocodingOptions,\n  GeocodingFeature,\n  GeocodingResponse\n} from '@mapbox/search-js-core';\nimport mapboxgl from 'mapbox-gl';\nimport subtag from 'subtag';\n\nimport {\n  MapboxSearchListbox,\n  SelectionEventDetail\n} from './MapboxSearchListbox';\nimport { HTMLScopedElement } from './HTMLScopedElement';\n\nimport { tryParseJSON } from '../utils';\nimport { bboxViewport, FLY_TO_SPEED, getMaxZoom } from '../utils/map';\n\nimport { Theme, getIcon, getThemeCSS } from '../theme';\nimport { MapboxHTMLEvent } from '../MapboxHTMLEvent';\nimport { GEOCODER_TEMPLATE } from '../constants';\n\nimport style from '../style.css';\nimport { PopoverOptions } from '../utils/popover';\nimport { createAriaLiveElement } from '../utils/aria';\nimport { bindElements } from '../utils/dom';\nimport { SEARCH_SERVICE } from '../utils/services';\nimport localization from '../utils/localization';\nimport { InputEventDetail } from '../utils/listbox';\nimport { MapboxEventManager } from '../events/MapboxEventManager';\n\n/**\n * Proximity is designed for local scale. If the user is looking at the whole world,\n * it doesn't make sense to factor in the arbitrary center of the map.\n */\nconst MAX_ZOOM = 9;\n\nconst DEFAULT_COMPONENT_OPTIONS: MapboxGeocoderComponentOptions = {\n  flyTo: true\n};\n\nconst CORE_COMPONENT_OPTION_KEYS: (keyof MapboxGeocoderComponentOptions)[] = [\n  'flipCoordinates'\n];\n\n/**\n * Options to configure component-specific Search behavior\n * @typedef MapboxGeocoderComponentOptions\n */\nexport interface MapboxGeocoderComponentOptions {\n  /**\n   * If true, the coordinates in the query string are expected to be (lat,lng) instead of (lng,lat).\n   */\n  flipCoordinates?: boolean;\n  /**\n   * If `false`, animating the map to a selected result is disabled. If `true` (default), animating the map will use the default animation parameters. If an object, it will be passed as `options` to the map `flyTo` method.\n   */\n  flyTo?: mapboxgl.FlyToOptions | boolean;\n  /**\n   * A function accepting the query string which performs supplemental search results\n   * on top of those from the Mapbox Geocoding API. Expected to return a Promise\n   * which resolves to an array of GeoJSON-like Features as described in the\n   * [Mapbox Geocoding API](https://docs.mapbox.com/api/search/geocoding/#geocoding-response-object).\n   * @param text Query text\n   * @returns Promise resolving to an array of properly formatted Feature suggestion objects\n   * @example\n   * ```typescript\n   * async myCustomFunction((query: string) => {\n   *    // Perform custom search logic, e.g. fetch from a local database or API (can be sync or async)\n   *   const customData = await getData();\n   *\n   *   // Format the data and return\n   *   return customData.map(obj => {\n   *     return {\n   *       type: 'Feature',\n   *       geometry: { type: 'Point', coordinates: [obj.lng, obj.lat] },\n   *       properties: { full_address: obj.fullName, name: obj.title }\n   *     }\n   *   });\n   * };\n   * ```\n   */\n  customSearch?: (text: string) => Promise<GeocodingFeature[]>;\n}\n\ntype Binding = {\n  /**\n   * Wrapper around the entire Geocoder component.\n   */\n  Geocoder: HTMLElement;\n  /**\n   * Container for search icon preceding input\n   */\n  SearchIcon: HTMLDivElement;\n  /**\n   * The input element accepting search text\n   */\n  Input: HTMLInputElement;\n  /**\n   * Button element used to clear the input element of text\n   */\n  ClearBtn: HTMLButtonElement;\n  /**\n   * Animated loading icon triggered by a keystroke\n   */\n  LoadingIcon: HTMLDivElement;\n};\n\nexport type MapboxSearchListboxSearchType =\n  MapboxSearchListbox<GeocodingFeature>;\n\ntype SearchEventTypes = {\n  /**\n   * Fired when the user is typing and is provided a list of suggestions.\n   *\n   * The underlying response from {@link GeocodingCore} is passed as the event's detail.\n   *\n   * @event suggest\n   * @instance\n   * @memberof MapboxGeocoder\n   * @type {GeocodingResponse}\n   * @example\n   * ```typescript\n   * search.addEventListener('suggest', (event) => {\n   *   const suggestions = event.detail.suggestions;\n   *   // ...\n   * });\n   * ```\n   */\n  suggest: MapboxHTMLEvent<GeocodingResponse>;\n  /**\n   * Fired when {@link GeocodingCore} has errored providing a list of suggestions.\n   *\n   * The underlying error is passed as the event's detail.\n   *\n   * @event suggesterror\n   * @instance\n   * @memberof MapboxGeocoder\n   * @type {Error}\n   * @example\n   * ```typescript\n   * search.addEventListener('suggesterror', (event) => {\n   *   const error = event.detail;\n   *   // ...\n   * });\n   * ```\n   */\n  suggesterror: MapboxHTMLEvent<Error>;\n  /**\n   * Fired when the user has selected a suggestion.\n   *\n   * The underlying response from {@link GeocodingCore} is passed as the event's detail.\n   *\n   * @event retrieve\n   * @instance\n   * @memberof MapboxGeocoder\n   * @type {GeocodingFeature}\n   * @example\n   * ```typescript\n   * search.addEventListener('retrieve', (event) => {\n   *   const feature = event.detail;\n   *   // ...\n   * });\n   * ```\n   */\n  retrieve: MapboxHTMLEvent<GeocodingFeature>;\n  /**\n   * Fired when the user has changed the `<input>` text.\n   *\n   * The new input value is passed as the event's detail.\n   *\n   * @event input\n   * @instance\n   * @memberof MapboxGeocoder\n   * @type {string}\n   * @example\n   * ```typescript\n   * search.addEventListener('input', (event) => {\n   *   if (e.target !== e.currentTarget) return;\n   *   const searchText = event.detail;\n   *   // ...\n   * });\n   * ```\n   */\n  input: MapboxHTMLEvent<string>;\n  /**\n   * Fired when the user has cleared the <input> box,\n   * either by deleting all text or clicking the \"Clear\" icon.\n   *\n   * @event clear\n   * @instance\n   * @memberof MapboxGeocoder\n   * @example\n   * ```typescript\n   * search.addEventListener('clear', () => {\n   *   console.log('search box cleared');\n   *   // ...\n   * });\n   * ```\n   */\n  clear: MapboxHTMLEvent<unknown>;\n  /**\n   * Fired when the user moved focus away from the MapboxGeocoder component.\n   *\n   * @event blur\n   * @instance\n   * @memberof MapboxGeocoder\n   * @example\n   * ```typescript\n   * search.addEventListener('blur', () => {\n   *   console.log('search box blurred');\n   *   // ...\n   * });\n   * ```\n   */\n  blur: MapboxHTMLEvent<unknown>;\n};\n\n/**\n * `MapboxGeocoder`, also available as the element `<mapbox-geocoder>`,\n * is an element that lets you search for addresses and places using\n * the [Mapbox Geocoding API](https://docs.mapbox.com/api/search/geocoding-v6/).\n *\n * It can control a [Mapbox GL JS](https://docs.mapbox.com/mapbox-gl-js/guides/) map\n * to zoom to the selected result.\n *\n * Additionally, `MapboxGeocoder` implements the [IControl](https://www.mapbox.com/mapbox-gl-js/api/markers/#icontrol)\n * interface.\n *\n * To use this element, you must have a [Mapbox access token](https://www.mapbox.com/help/create-api-access-token/).\n *\n * @class MapboxGeocoder\n * @example\n * ```typescript\n * const search = new MapboxGeocoder();\n * search.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN';\n * map.addControl(search);\n * ```\n * @example\n * <mapbox-geocoder\n *   access-token=\"YOUR_MAPBOX_ACCESS_TOKEN\"\n *   proximity=\"0,0\"\n * >\n * </mapbox-geocoder>\n */\nexport class MapboxGeocoder\n  extends HTMLScopedElement<SearchEventTypes>\n  implements mapboxgl.IControl\n{\n  /**\n   * This is read by the Web Components API to affect the\n   * {@link MapboxGeocoder#attributeChangedCallback} below.\n   *\n   * All of these are passthroughs to the underlying {@link MapboxSearchListbox}.\n   *\n   * @ignore\n   */\n  static observedAttributes: string[] = [\n    // Access token.\n    'access-token',\n    // Theming.\n    'theme',\n    'popover-options',\n    'placeholder',\n    // Component options.\n    'flip-coordinates',\n    // Underlying Geocoding API options.\n    'autocomplete',\n    'language',\n    'country',\n    'bbox',\n    'limit',\n    'proximity',\n    'types',\n    'worldview',\n    'permanent'\n  ];\n\n  #binding: Binding;\n\n  #search = new GeocodingCore({});\n  #session = new SearchSession<\n    GeocodingOptions,\n    GeocodingFeature,\n    GeocodingResponse,\n    GeocodingFeature\n  >(this.#search);\n\n  /**\n   * The [Mapbox access token](https://docs.mapbox.com/help/glossary/access-token/) to use for all requests.\n   *\n   * @name accessToken\n   * @instance\n   * @memberof MapboxGeocoder\n   * @example\n   * ```typescript\n   * search.accessToken = 'pk.my-mapbox-access-token';\n   * ```\n   */\n  get accessToken(): string {\n    return this.#search.accessToken;\n  }\n  set accessToken(newToken: string) {\n    this.#search.accessToken = newToken;\n  }\n\n  /**\n   * The value of the input element.\n   *\n   * @name value\n   * @instance\n   * @memberof MapboxGeocoder\n   * @example\n   * ```typescript\n   * console.log(search.value);\n   * ```\n   */\n  get value(): string {\n    return this.#input.value;\n  }\n  set value(newValue: string) {\n    this.#input.value = newValue || '';\n  }\n\n  #map: mapboxgl.Map | null = null;\n\n  #input: HTMLInputElement;\n  #listbox: MapboxSearchListboxSearchType = new MapboxSearchListbox();\n\n  #eventManager = new MapboxEventManager(SEARCH_SERVICE.Geocoding);\n\n  /**\n   * The `<input>` element wrapped by the MapboxGeocoder component.\n   *\n   * @name input\n   * @instance\n   * @memberof MapboxGeocoder\n   * @type {HTMLInputElement}\n   */\n  get input(): HTMLInputElement {\n    return this.#input;\n  }\n\n  protected override get template(): HTMLTemplateElement {\n    return GEOCODER_TEMPLATE;\n  }\n\n  protected override get templateStyle(): string {\n    return style;\n  }\n\n  protected override get templateUserStyle(): string {\n    return getThemeCSS('.Geocoder', this.#listbox.theme);\n  }\n\n  /**\n   * Options to pass to the underlying {@link GeocodingCore} interface.\n   *\n   * @name options\n   * @instance\n   * @memberof MapboxGeocoder\n   * @type {GeocodingOptions}\n   * @example\n   * ```typescript\n   * search.options = {\n   *  language: 'en',\n   *  country: 'US',\n   * };\n   * ```\n   */\n  options: Partial<GeocodingOptions> = {};\n\n  #componentOptions: Partial<MapboxGeocoderComponentOptions> = {\n    ...DEFAULT_COMPONENT_OPTIONS\n  };\n\n  /**\n   * Options defining the behavior of web component or its underlying search functionality.\n   * Distinct from the {@link GeocodingOptions} options, these do not correspond to the core API specification.\n   *\n   * @name componentOptions\n   * @instance\n   * @memberof MapboxGeocoder\n   * @type {MapboxGeocoderComponentOptions}\n   * @example\n   * ```typescript\n   * search.componentOptions = {\n   *  flipCoordinates: true,\n   *  flyTo: true\n   * };\n   * ```\n   */\n  get componentOptions(): MapboxGeocoderComponentOptions {\n    return this.#componentOptions;\n  }\n  set componentOptions(options: Partial<MapboxGeocoderComponentOptions>) {\n    this.#componentOptions = {\n      ...DEFAULT_COMPONENT_OPTIONS,\n      ...options\n    };\n  }\n\n  /**\n   * Extracts the subset of the componentOptions that are relevant to GeocoderCore\n   */\n  #getCoreComponentOptions = (): MapboxGeocoderComponentOptions => {\n    const options = { ...this.componentOptions };\n    for (const key in options) {\n      if (\n        CORE_COMPONENT_OPTION_KEYS.indexOf(\n          key as keyof MapboxGeocoderComponentOptions\n        ) === -1\n      ) {\n        delete options[key];\n      }\n    }\n    return options;\n  };\n\n  /**\n   * The {@link Theme} to use for styling the suggestion box and geocoder input box.\n   *\n   * @name theme\n   * @instance\n   * @memberof MapboxGeocoder\n   * @type {Theme}\n   * @example\n   * ```typescript\n   * search.theme = {\n   *   variables: {\n   *     colorPrimary: 'myBrandRed'\n   *   },\n   *   cssText: \".Input:active { opacity: 0.9; }\"\n   * };\n   * ```\n   */\n  get theme(): Theme {\n    return this.#listbox.theme;\n  }\n  set theme(theme: Theme) {\n    this.#listbox.theme = theme;\n\n    if (!this.#binding || !theme) {\n      return;\n    }\n\n    this.updateTemplateUserStyle(getThemeCSS('.Geocoder', theme));\n    this.#listbox.updatePopover();\n\n    const { SearchIcon } = this.#binding;\n    SearchIcon.innerHTML = getIcon('search', theme);\n  }\n\n  /**\n   * The {@link PopoverOptions} to define popover positioning.\n   *\n   * @name popoverOptions\n   * @instance\n   * @memberof MapboxGeocoder\n   * @type {PopoverOptions}\n   * @example\n   * ```typescript\n   * search.popoverOptions = {\n   *   placement: 'top-start',\n   *   flip: true,\n   *   offset: 5\n   * };\n   * ```\n   */\n  get popoverOptions(): Partial<PopoverOptions> {\n    return this.#listbox.popoverOptions;\n  }\n  set popoverOptions(newOptions: Partial<PopoverOptions>) {\n    this.#listbox.popoverOptions = newOptions;\n  }\n\n  #getDefaultPlaceholder(): string {\n    if (this.options.language) {\n      const firstLanguage = this.options.language.split(',')[0];\n      const language = subtag.language(firstLanguage);\n      const localizedValue = localization.placeholder[language];\n      if (localizedValue) return localizedValue;\n    }\n    return 'Search';\n  }\n\n  #placeholder: string;\n\n  /**\n   * The input element's placeholder text. The default value may be localized if {@link GeocodingOptions#language} is set.\n   *\n   * @name placeholder\n   * @instance\n   * @memberof MapboxGeocoder\n   * @type {string}\n   */\n  get placeholder(): string {\n    return this.#placeholder || this.#getDefaultPlaceholder();\n  }\n\n  set placeholder(text: string) {\n    this.#placeholder = text;\n    if (this.#input) {\n      this.#input.placeholder = this.placeholder;\n      this.#input.setAttribute('aria-label', this.placeholder);\n    }\n  }\n\n  #handleSuggest = async (result: GeocodingResponse): Promise<void> => {\n    this.#setActionIcons();\n\n    let features: GeocodingFeature[] | null = null;\n\n    // Integrate optional custom search results\n    if (this.componentOptions.customSearch) {\n      const customFeatures = await this.componentOptions.customSearch(\n        this.value\n      );\n      if (customFeatures && customFeatures.length) {\n        customFeatures.forEach((feature) => {\n          feature._source = 'custom';\n        });\n        features = customFeatures;\n      }\n    }\n\n    // Integrate results from the Mapbox Geocoding API\n    if (result && result.features) {\n      if (!features) {\n        features = result.features;\n      } else {\n        features = features.concat(result.features);\n      }\n    }\n\n    this.#listbox.handleSuggest(features || null);\n\n    // If focus is not already on the web component, focus it.\n    // This ensures that a future 'blur' event is available to hide the results.\n    // This could happen under the following scenarios:\n    // 1. User types in the input, then moves focus away before suggestions return\n    // 2. Suggest is triggered programmatically via the search() method\n    // 3. Browser autofill (e.g. for Safari iOS) removes focus from the input\n    if (!this.#binding.Geocoder.contains(document.activeElement)) {\n      this.focus();\n    }\n\n    // Manually bubble up the event.\n    this.dispatchEvent(new MapboxHTMLEvent('suggest', result));\n  };\n\n  #handleSuggestError = async (error: Error): Promise<void> => {\n    this.#setActionIcons();\n\n    if (this.componentOptions.customSearch) {\n      // If a custom search function is provided, attempt to generate and render suggestions from it\n      const customFeatures = await this.componentOptions.customSearch(\n        this.value\n      );\n      if (customFeatures && customFeatures.length) {\n        customFeatures.forEach((feature) => {\n          feature._source = 'custom';\n        });\n        this.#listbox.handleSuggest(customFeatures || null);\n      } else {\n        this.#listbox.handleError();\n      }\n    } else {\n      // Otherwise, hide the listbox\n      this.#listbox.handleError();\n    }\n    // Manually bubble up the event.\n    this.dispatchEvent(new MapboxHTMLEvent('suggesterror', error));\n  };\n\n  #handleRetrieve = (result: GeocodingFeature): void => {\n    this.#setActionIcons();\n\n    // Manually bubble up the event.\n    this.dispatchEvent(new MapboxHTMLEvent('retrieve', result));\n\n    const feature = result;\n    if (!feature) {\n      return;\n    }\n\n    // Set value of the input.\n    this.#input.value = feature.properties.full_address;\n\n    const map = this.#map;\n    if (!map) {\n      return;\n    }\n\n    if (this.componentOptions.flyTo) {\n      this.#fly(feature);\n    }\n\n    // Add marker to map\n    if (this.marker && this.mapboxgl) {\n      this.#handleMarker(feature);\n    }\n  };\n\n  #mapMarker: mapboxgl.Marker;\n\n  /**\n   * Handle the removal of a feature marker\n   */\n  #removeMarker = (): void => {\n    if (this.#mapMarker) {\n      this.#mapMarker.remove();\n      this.#mapMarker = null;\n    }\n  };\n\n  /**\n   * Handle the placement of a marker for the selected feature\n   */\n  #handleMarker = (feature: GeocodingFeature | null): void => {\n    // clean up any old marker that might be present\n    if (!this.#map) {\n      return;\n    }\n    this.#removeMarker();\n\n    if (!feature) return;\n\n    const defaultMarkerOptions = {\n      color: '#4668F2'\n    };\n    const markerOptions = {\n      ...defaultMarkerOptions,\n      ...(typeof this.marker === 'object' && this.marker)\n    };\n    this.#mapMarker = new this.mapboxgl.Marker(markerOptions);\n    if (\n      feature.geometry &&\n      feature.geometry.type &&\n      feature.geometry.type === 'Point' &&\n      feature.geometry.coordinates\n    ) {\n      this.#mapMarker\n        .setLngLat(feature.geometry.coordinates as mapboxgl.LngLatLike)\n        .addTo(this.#map);\n    }\n  };\n\n  /**\n   * A callback providing the opportunity to validate and/or manipulate the input text before it triggers a search, for example by using a regular expression.\n   * If a truthy string value is returned, it will be passed into the underlying search API. If `null`, `undefined` or empty string is returned, no search request will be performed.\n   *\n   * @name interceptSearch\n   * @instance\n   * @memberof MapboxGeocoder\n   * @example\n   * Enable search only when the input value length is more than 3 characters.\n   * ```typescript\n   * search.interceptSearch = (val) => val?.length > 3 ? val : null;\n   * ```\n   */\n  interceptSearch: (val: string) => string = null;\n\n  #onHandleInput = (e: MapboxHTMLEvent<InputEventDetail>): void => {\n    // Manually bubble up the event as a basic input event.\n    this.dispatchEvent(\n      new MapboxHTMLEvent<string>('input', e.detail.inputText)\n    );\n\n    const { lastInput, inputText } = e.detail;\n\n    // Clear text, suggestions, markers, etc. if empty string\n    if (!inputText) {\n      this.#handleClear();\n      return;\n    }\n\n    const alteredText = this.interceptSearch && this.interceptSearch(inputText);\n\n    const searchText = this.interceptSearch ? alteredText : inputText;\n\n    if (this.interceptSearch && !alteredText) {\n      this.#listbox.hideResults();\n      return;\n    }\n\n    this.#session.suggest(searchText, {\n      ...this.options,\n      ...this.#getCoreComponentOptions()\n    });\n    this.#eventManager.input(\n      searchText,\n      lastInput,\n      {\n        ...this.options,\n        sessionToken: this.#session.sessionToken,\n        accessToken: this.accessToken\n      },\n      this.#map,\n      this.#search.responseHeaders\n    );\n\n    this.#setActionIcons(true);\n  };\n\n  #onHandleSelect = (\n    e: MapboxHTMLEvent<SelectionEventDetail<GeocodingFeature>>\n  ): void => {\n    const { suggestion, selectedIndex } = e.detail;\n    this.#session.retrieve(suggestion, this.options);\n    this.#eventManager.select(\n      this.value,\n      selectedIndex,\n      this.#listbox.suggestions,\n      {\n        ...this.options,\n        sessionToken: this.#session.sessionToken,\n        accessToken: this.accessToken\n      },\n      this.#map,\n      this.#search.responseHeaders\n    );\n\n    this.#setActionIcons(true);\n  };\n\n  #onHandleBlur = (): void => {\n    // Placeholder for any future listbox blur handling\n  };\n\n  #onHandleFocusOut = (event: FocusEvent): void => {\n    // Only trigger when focus moves outside the Geocoder container\n    if (\n      !this.#binding.Geocoder.contains(event.relatedTarget as Node) &&\n      !this.#listbox.contains(event.relatedTarget as Node)\n    ) {\n      this.#onHandleBlur();\n      this.#listbox.hideResults();\n      this.dispatchEvent(new MapboxHTMLEvent('blur'));\n    }\n  };\n\n  #setActionIcons = (loading = false): void => {\n    if (loading) {\n      this.#binding.ClearBtn.style.display = 'none';\n      this.#binding.LoadingIcon.style.display = 'block';\n    } else {\n      this.#binding.LoadingIcon.style.display = 'none';\n      this.#binding.ClearBtn.style.display = this.value ? 'block' : 'none';\n    }\n  };\n\n  #handleClear = (): void => {\n    this.value = '';\n    this.#setActionIcons();\n    this.#handleMarker(null);\n    this.#listbox.handleSuggest(null);\n    this.#listbox.focus();\n\n    this.#eventManager.clear();\n    this.#session.incrementSession();\n\n    // Manually bubble up the event.\n    this.dispatchEvent(new MapboxHTMLEvent('clear'));\n  };\n\n  /** @section {Map settings} */\n\n  /**\n   * A [mapbox-gl](https://github.com/mapbox/mapbox-gl-js) instance to use when creating [Markers](https://docs.mapbox.com/mapbox-gl-js/api/#marker). Required if {@link MapboxGeocoder#marker} is `true`.\n   *\n   * @name mapboxgl\n   * @instance\n   * @memberof MapboxGeocoder\n   */\n  mapboxgl: typeof mapboxgl;\n\n  /**\n   * If `true`, a [Marker](https://docs.mapbox.com/mapbox-gl-js/api/#marker) will be added to the map at the location of the user-selected result using a default set of Marker options.  If the value is an object, the marker will be constructed using these options. If `false`, no marker will be added to the map. Requires that {@link MapboxGeocoder#mapboxgl} also be set.\n   *\n   * @name marker\n   * @instance\n   * @memberof MapboxGeocoder\n   * @type {boolean | mapboxgl.MarkerOptions}\n   * @example\n   * ```typescript\n   * search.marker = {\n   *   color: 'red',\n   *   draggable: true\n   * };\n   * ```\n   */\n  marker: boolean | mapboxgl.MarkerOptions = true;\n\n  override connectedCallback(): void {\n    super.connectedCallback();\n\n    this.#binding = bindElements<Binding>(this, {\n      Geocoder: '.Geocoder',\n      SearchIcon: '.SearchIcon',\n      Input: '.Input',\n      ClearBtn: '.ClearBtn',\n      LoadingIcon: '.LoadingIcon'\n    });\n\n    // Initialize theme if not set before connectedCallback\n    this.theme = { ...this.theme };\n\n    const { Input, ClearBtn, Geocoder } = this.#binding;\n\n    Geocoder.addEventListener('focusout', this.#onHandleFocusOut);\n\n    this.#input = Input;\n    this.#listbox.input = Input;\n    this.#listbox.searchService = SEARCH_SERVICE.Geocoding;\n\n    this.#listbox.addEventListener('input', this.#onHandleInput);\n    this.#listbox.addEventListener('select', this.#onHandleSelect);\n    this.#listbox.addEventListener('blur', this.#onHandleBlur);\n\n    this.#session.addEventListener('suggest', this.#handleSuggest);\n    this.#session.addEventListener('suggesterror', this.#handleSuggestError);\n    this.#session.addEventListener('retrieve', this.#handleRetrieve);\n\n    ClearBtn.addEventListener('click', this.#handleClear);\n\n    this.placeholder = this.#placeholder;\n\n    this.parentElement.appendChild(this.#listbox);\n\n    if (Input) {\n      // Remove any existing aria-live element that may be left over from, e.g., cloning the node\n      if (Input.previousElementSibling.hasAttribute('aria-live')) {\n        Input.previousElementSibling.remove();\n      }\n      Input.insertAdjacentElement(\n        'beforebegin',\n        createAriaLiveElement(this.#listbox.dataSeed)\n      );\n    }\n  }\n\n  disconnectedCallback(): void {\n    const { Geocoder } = this.#binding;\n    Geocoder.removeEventListener('focusout', this.#onHandleFocusOut);\n\n    this.#listbox.remove();\n    this.#listbox.input = null;\n\n    this.#listbox.removeEventListener('input', this.#onHandleInput);\n    this.#listbox.removeEventListener('select', this.#onHandleSelect);\n    this.#listbox.removeEventListener('blur', this.#onHandleBlur);\n\n    this.#session.removeEventListener('suggest', this.#handleSuggest);\n    this.#session.removeEventListener('suggesterror', this.#handleSuggestError);\n    this.#session.removeEventListener('retrieve', this.#handleRetrieve);\n\n    this.#eventManager.remove();\n  }\n\n  attributeChangedCallback(\n    name: string,\n    oldValue: string,\n    newValue: string\n  ): void {\n    if (name === 'access-token') {\n      this.#search.accessToken = newValue;\n      return;\n    }\n\n    if (name === 'theme') {\n      this.theme = tryParseJSON(newValue);\n      return;\n    }\n\n    if (name === 'popover-options') {\n      this.popoverOptions = tryParseJSON(newValue);\n      return;\n    }\n\n    if (name === 'placeholder') {\n      this.placeholder = newValue;\n      return;\n    }\n\n    if (name === 'flip-coordinates') {\n      this.componentOptions.flipCoordinates = ['true', ''].includes(newValue);\n      return;\n    }\n\n    // Convert to the proper name for options.\n    // Example: eta-type => eta_type\n    const optionName = name.split('-').join('_');\n\n    if (!newValue) {\n      delete this.options[optionName];\n    }\n\n    // Otherwise, assume it's a Geocoding API option.\n    this.options[optionName] = newValue;\n\n    if (optionName === 'language') {\n      this.placeholder = this.#placeholder;\n    }\n  }\n\n  /** @section {Methods} */\n\n  /**\n   * Focuses the input element.\n   */\n  focus(): void {\n    this.#listbox.focus();\n  }\n\n  /**\n   * Sets the input text and triggers a search programmatically\n   */\n  search(text: string): void {\n    this.value = text;\n    const payload: InputEventDetail = {\n      lastInput: text,\n      inputText: text\n    };\n    this.#onHandleInput(new MapboxHTMLEvent('input', payload));\n  }\n\n  #handleMoveEnd = (): void => {\n    const map = this.#map;\n    const options = { ...this.options };\n\n    if (map.getZoom() <= MAX_ZOOM) {\n      delete options.proximity;\n      this.options = options;\n\n      return;\n    }\n\n    const center = map.getCenter();\n    this.options = {\n      ...options,\n      proximity: center\n    };\n  };\n\n  #fly = (feature: GeocodingFeature): void => {\n    const map = this.#map;\n    if (!map) {\n      return;\n    }\n\n    const placeType = feature.properties.feature_type;\n\n    let flyToOptions: mapboxgl.FlyToOptions;\n\n    const bounds = feature.properties.bbox;\n    if (bounds) {\n      flyToOptions = bboxViewport(\n        map,\n        LngLatBounds.convert(bounds).toFlatArray()\n      );\n    } else {\n      const center = feature.geometry.coordinates as mapboxgl.LngLatLike;\n      const zoom = getMaxZoom(placeType);\n      flyToOptions = {\n        center,\n        zoom,\n        speed: FLY_TO_SPEED\n      };\n    }\n\n    // If the user has set a custom flyTo option, merge it with the default options.\n    flyToOptions = Object.assign(flyToOptions, this.componentOptions.flyTo);\n    map.flyTo(flyToOptions);\n  };\n\n  /** @section {Map binding} */\n\n  /**\n   * Connects the Geocoder to a [Map](https://docs.mapbox.com/mapbox-gl-js/api/#map),\n   * which handles both setting proximity and zoom after a suggestion click.\n   *\n   * @example\n   * ```typescript\n   * const search = new MapboxGeocoder();\n   * search.bindMap(map);\n   * ```\n   */\n  bindMap(map: mapboxgl.Map): void {\n    if (this.#map) {\n      this.#map.off('moveend', this.#handleMoveEnd);\n    }\n\n    if (map) {\n      map.on('moveend', this.#handleMoveEnd);\n    }\n\n    this.#map = map;\n  }\n\n  /**\n   * Unbinds the Geocoder from a [Map](https://docs.mapbox.com/mapbox-gl-js/api/#map).\n   */\n  unbindMap(): void {\n    this.bindMap(null);\n  }\n\n  // IControl interface.\n\n  // eslint-disable-next-line custom-elements/no-method-prefixed-with-on\n  onAdd(map: mapboxgl.Map): HTMLElement {\n    this.bindMap(map);\n    this.remove();\n\n    const container = document.createElement('div');\n    container.className = 'mapboxgl-ctrl';\n    container.style.width = '300px';\n    container.appendChild(this);\n\n    return container;\n  }\n\n  // eslint-disable-next-line custom-elements/no-method-prefixed-with-on\n  onRemove(): void {\n    this.remove();\n    this.unbindMap();\n    this.#removeMarker();\n  }\n\n  getDefaultPosition(): string {\n    return 'top-right';\n  }\n}\n\ndeclare global {\n  interface Window {\n    MapboxGeocoder: typeof MapboxGeocoder;\n  }\n}\n\nwindow.MapboxGeocoder = MapboxGeocoder;\n\nif (!window.customElements.get('mapbox-geocoder')) {\n  customElements.define('mapbox-geocoder', MapboxGeocoder);\n}\n","import { LngLat, LngLatLike } from '@mapbox/search-js-core';\n\nimport { HTMLScopedElement } from './HTMLScopedElement';\n\nimport {\n  bindElements,\n  createElementFromString,\n  getElementSize\n} from '../utils/dom';\nimport {\n  Anchor,\n  MapStyleMode,\n  MarkerController,\n  MAX_IMAGE_DIM\n} from '../utils/minimap';\nimport { getStaticBaseUrl } from '../utils/map';\n\nimport {\n  AUTOFILL_SKU_TOKEN_PREFIX,\n  STATIC_BASE_URL_SATELLITE\n} from '../constants';\nimport { getIcon, getImage, getThemeCSS, Theme } from '../theme';\n\nimport style from '../style.css';\nimport logo from '../icons/mapboxgl-ctrl-logo.svg';\nimport { deepEquals } from '../utils';\nimport { sendFeedback } from '../utils/contribute';\n\nimport { config } from '../config';\n\n// TODO: Scale by device pixel ratio?\nconst ZOOM = 16;\n\nconst TEMPLATE = createElementFromString<HTMLTemplateElement>(/* html */ `\n<template>\n  <div class=\"MapboxAddressMinimap\" aria-hidden=\"true\">\n    <div class=\"MinimapImageContainer\">\n      <img class=\"MinimapImage\" draggable=\"false\"></img>\n      <div class=\"MinimapInnerFrame\">\n        <div class=\"MinimapMarker\"></div>\n        <div class=\"MinimapAttribution\">\n          <div class=\"MinimapAttributionLogo\">\n            <a target=\"_blank\" rel=\"noopener nofollow\" href=\"https://www.mapbox.com/\" aria-label=\"Mapbox logo\">\n              ${logo}\n            </a>\n          </div>\n          <div class=\"MinimapAttributionText\">\n            <a target=\"_blank\" href='https://www.mapbox.com/about/maps/'>© Mapbox</a><a target=\"_blank\" href='http://www.openstreetmap.org/copyright'>© OpenStreetMap</a>\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n</template>\n`);\n\nconst STYLE_TOGGLE_TEMPLATE =\n  createElementFromString<HTMLTemplateElement>(/* html */ `\n<template>\n  <button type=\"button\" class=\"MinimapStyleToggle\"></button>\n</template>\n`);\n\nconst FOOTER_TEMPLATE =\n  createElementFromString<HTMLTemplateElement>(/* html */ `\n<template>\n  <div class=\"MinimapFooter\">Adjust the marker on the map if it doesn't precisely match your location. This helps improve address data quality.</div>\n</template>\n`);\n\nconst ADJUST_PIN_TEXT = 'Adjust pin';\nconst SAVE_TEXT = 'Save';\nconst CANCEL_TEXT = 'Cancel';\n\nconst EDIT_BUTTONS_TEMPLATE =\n  createElementFromString<HTMLTemplateElement>(/* html */ `\n<template>\n  <div class=\"MinimapEditButtons\">\n    <div class=\"Button ButtonPrimary MinimapButtonAdjust\">${ADJUST_PIN_TEXT}</div>\n    <div class=\"Button ButtonPrimary MinimapButtonSave\" aria-hidden=\"true\">${SAVE_TEXT}</div>\n    <div class=\"Button MinimapButtonCancel\" aria-hidden=\"true\">${CANCEL_TEXT}</div>\n  </div>\n</template>\n`);\n\ntype Binding = {\n  MapboxAddressMinimap: HTMLElement;\n  ImageContainer: HTMLElement;\n  Image: HTMLImageElement;\n  Marker: HTMLElement;\n  MapStyleToggle?: HTMLElement;\n  EditButtons?: HTMLElement;\n  ButtonAdjust?: HTMLButtonElement;\n  ButtonSave?: HTMLButtonElement;\n  ButtonCancel?: HTMLButtonElement;\n};\n\n/**\n * `MapboxAddressMinimap`, also available as the element `<mapbox-address-minimap>`,\n * is a component that displays a marker for confirmation purposes.\n *\n * Optionally, this marker is editable. When editable, the marker can be moved\n * around the map and the updated location is sent back to the Mapbox Contribute\n * workflow.\n *\n * The goal of `MapboxAddressMinimap` is to reduce delivery or geolocation error in shipping and\n * local dispatching contexts.\n *\n * `MapboxAddressMinimap` expands to fill its container, and is hidden unless\n * {@link MapboxAddressMinimap#feature} is truthy. Setting {@link MapboxAddressMinimap#feature}\n * to `null` hides the component.\n *\n * @class MapboxAddressMinimap\n * @example\n * ```typescript\n * const minimap = new MapboxAddressMinimap();\n * containerElement.appendChild(minimap);\n * minimap.feature = {\n *   type: 'Feature',\n *   geometry: {\n *     type: 'Point',\n *     coordinates: [-122.4194, 37.7749]\n *   },\n *   properties: {}\n * };\n * ```\n */\nexport class MapboxAddressMinimap extends HTMLScopedElement {\n  static observedAttributes: string[] = [\n    'access-token',\n    'can-adjust-marker',\n    'keep-marker-centered',\n    'marker-anchor',\n    'satellite-toggle'\n  ];\n\n  #canAdjustMarkerInternal = false;\n\n  /** @section {Markers} */\n\n  /**\n   * If `true`, the marker can be moved around the map. Defaults to `false`.\n   *\n   * When editable, the marker can be moved around the map and the updated\n   * location can be referenced from the {@link MapboxAddressMinimap#onSaveMarkerLocation} callback.\n   *\n   * @name canAdjustMarker\n   * @instance\n   * @memberof MapboxAddressMinimap\n   * @type {boolean}\n   */\n  get canAdjustMarker(): boolean {\n    return this.#canAdjustMarkerInternal;\n  }\n  set canAdjustMarker(val: boolean) {\n    this.#canAdjustMarkerInternal = val;\n    // Only try to add/remove controls if component is connected\n    if (this.isConnected) {\n      val ? this.#addMarkerEditControls() : this.#removeMarkerEditControls();\n    }\n  }\n  /**\n   * If `true`, the map when panned moves around the marker, keeping the marker\n   * centered. Defaults to `false`.\n   *\n   * @name keepMarkerCentered\n   * @instance\n   * @memberof MapboxAddressMinimap\n   * @type {boolean}\n   */\n  keepMarkerCentered = false;\n  /**\n   * The anchor of the marker, relative to center of the expanded size. Defaults to `'bottom'`.\n   *\n   * @name markerAnchor\n   * @instance\n   * @memberof MapboxAddressMinimap\n   * @type {Anchor}\n   */\n  markerAnchor: Anchor = 'bottom';\n  /**\n   * A client-defined callback that is triggered when the \"Save\" button is clicked in the editing interface,\n   * and gives access to the adjusted marker coordinate.\n   *\n   * @name onSaveMarkerLocation\n   * @instance\n   * @memberof MapboxAddressMinimap\n   * @type {function}\n   */\n  onSaveMarkerLocation: (coordinate: [number, number]) => void;\n\n  #isAdjustMarkerEditing = false;\n\n  #imageLoaded = false;\n\n  #feature: GeoJSON.Feature<GeoJSON.Point>;\n  #url = '';\n\n  #width: number;\n  #height: number;\n\n  #binding: Binding;\n\n  #markerController: MarkerController;\n\n  #accessToken: string;\n\n  /** @section {Input data} */\n\n  /**\n   * The [Mapbox access token](https://docs.mapbox.com/help/glossary/access-token/) to use for all requests.\n   *\n   * If not explicitly set on the component, this will reference the value in the global config object.\n   *\n   * @name accessToken\n   * @instance\n   * @memberof MapboxAddressMinimap\n   * @example\n   * ```typescript\n   * minimap.accessToken = 'pk.my-mapbox-access-token';\n   * ```\n   */\n  get accessToken(): string {\n    return this.#accessToken || config.accessToken;\n  }\n  set accessToken(newToken: string) {\n    this.#accessToken = newToken;\n  }\n\n  /**\n   * A [GeoJSON](https://docs.mapbox.com/help/glossary/geojson/) Feature representing\n   * a [Point](https://geojson.org/geojson-spec.html#point) geometry.\n   *\n   * The minimap is hidden unless\n   * {@link MapboxAddressMinimap#feature} is truthy. Setting {@link MapboxAddressMinimap#feature}\n   * to `null` hides the component.\n   *\n   * @name feature\n   * @instance\n   * @memberof MapboxAddressMinimap\n   * @type {Feature}\n   */\n  get feature(): GeoJSON.Feature<GeoJSON.Point> {\n    return this.#feature;\n  }\n  set feature(feature: GeoJSON.Feature<GeoJSON.Point>) {\n    this.#feature = feature;\n\n    if (!feature) {\n      this.hide();\n    } else {\n      this.show();\n    }\n  }\n\n  get template(): HTMLTemplateElement {\n    return TEMPLATE;\n  }\n\n  get templateStyle(): string {\n    return style;\n  }\n\n  get templateUserStyle(): string {\n    return getThemeCSS('.MapboxAddressMinimap', this.theme);\n  }\n\n  #themeInternal: Theme = {};\n  #satelliteToggleInternal = false;\n\n  /** @section {Appearance} */\n\n  /**\n   * If `true`, the map will have an image toggle between Map and Satellite styles.\n   *\n   * @name satelliteToggle\n   * @instance\n   * @memberof MapboxAddressMinimap\n   * @type {boolean}\n   */\n  get satelliteToggle(): boolean {\n    return this.#satelliteToggleInternal;\n  }\n  set satelliteToggle(val: boolean) {\n    this.#satelliteToggleInternal = val;\n    // Only try to add/remove toggle if component is connected\n    if (this.isConnected) {\n      val ? this.#addSatelliteToggle() : this.#removeSatelliteToggle();\n    }\n  }\n\n  /**\n   * The {@link Theme} to use for styling the editing interface.\n   *\n   * @name theme\n   * @instance\n   * @memberof MapboxAddressMinimap\n   * @type {Theme}\n   * @example\n   * ```typescript\n   * autofill.theme = {\n   *   variables: {\n   *     colorPrimary: 'myBrandRed'\n   *   }\n   * };\n   * ```\n   */\n  get theme(): Theme {\n    return this.#themeInternal;\n  }\n  set theme(theme: Theme) {\n    this.#themeInternal = theme;\n\n    if (!this.#binding || !theme) {\n      return;\n    }\n\n    this.updateTemplateUserStyle(getThemeCSS('.MapboxAddressMinimap', theme));\n\n    const { Marker, MapStyleToggle } = this.#binding;\n    Marker.innerHTML = getIcon('marker', theme);\n    if (MapStyleToggle) {\n      MapStyleToggle.style.backgroundImage = this.#getToggleBackgroundImageUrl(\n        this.mapStyleMode === 'default' ? 'satellite' : 'default'\n      );\n    }\n  }\n\n  #mapStyleMode: MapStyleMode = 'default';\n\n  #adjustBtnText;\n  /**\n   * Custom adjust button text appearing on the map.\n   * If not provided, the default text will be used.\n   *\n   * @name adjustBtnText\n   * @instance\n   * @memberof MapboxAddressMinimap\n   * @type {string}\n   */\n  get adjustBtnText(): string {\n    return this.#adjustBtnText || ADJUST_PIN_TEXT;\n  }\n  set adjustBtnText(val: string) {\n    this.#adjustBtnText = val;\n    const adjustBtn = this.querySelector('.MinimapButtonAdjust');\n    adjustBtn.textContent = val || ADJUST_PIN_TEXT;\n  }\n\n  #saveBtnText;\n  /**\n   * Custom save button text appearing on the map, when marker adjustment is enabled.\n   * If not provided, the default text will be used.\n   *\n   * @name saveBtnText\n   * @instance\n   * @memberof MapboxAddressMinimap\n   * @type {string}\n   */\n  get saveBtnText(): string {\n    return this.#saveBtnText || SAVE_TEXT;\n  }\n  set saveBtnText(val: string) {\n    this.#saveBtnText = val;\n    const saveBtn = this.querySelector('.MinimapButtonSave');\n    saveBtn.textContent = val || SAVE_TEXT;\n  }\n\n  #cancelBtnText;\n  /**\n   * Custom cancel button text appearing on the map, when marker adjustment is enabled.\n   * If not provided, the default text will be used.\n   *\n   * @name cancelBtnText\n   * @instance\n   * @memberof MapboxAddressMinimap\n   * @type {string}\n   */\n  get cancelBtnText(): string {\n    return this.#cancelBtnText || CANCEL_TEXT;\n  }\n  set cancelBtnText(val: string) {\n    this.#cancelBtnText = val;\n    const cancelBtn = this.querySelector('.MinimapButtonCancel');\n    cancelBtn.textContent = val || CANCEL_TEXT;\n  }\n\n  /**\n   * The map style to use, either `'default'` or `'satellite'`. The default map\n   * style is configurable with {@link MapboxAddressMinimap#defaultMapStyle}.\n   *\n   * @name mapStyleMode\n   * @instance\n   * @memberof MapboxAddressMinimap\n   * @type {'default' | 'satellite'}\n   */\n  get mapStyleMode(): MapStyleMode {\n    return this.#mapStyleMode;\n  }\n  set mapStyleMode(styleMode: MapStyleMode) {\n    const prevStyleMode = this.#mapStyleMode;\n    if (prevStyleMode === styleMode) return;\n\n    this.#mapStyleMode = styleMode;\n    if (!this.#binding) {\n      return;\n    }\n\n    // Update toggle button background image\n    const { MapStyleToggle } = this.#binding;\n    if (!MapStyleToggle) {\n      return;\n    }\n\n    MapStyleToggle.style.backgroundImage =\n      this.#getToggleBackgroundImageUrl(prevStyleMode);\n    // Update title attribute\n    MapStyleToggle.setAttribute(\n      'title',\n      `Switch to ${prevStyleMode === 'satellite' ? 'Satellite' : 'Default'}`\n    );\n    this.#updateImageSrc();\n  }\n\n  #defaultMapStyle: [string, string] = ['mapbox', 'streets-v11'];\n\n  /**\n   * The map style to use for the default map style. Defaults to `['mapbox', 'streets-v11']`.\n   *\n   * @name defaultMapStyle\n   * @instance\n   * @memberof MapboxAddressMinimap\n   * @type {[string, string]}\n   */\n  get defaultMapStyle(): [string, string] {\n    return this.#defaultMapStyle;\n  }\n  set defaultMapStyle(style: [string, string]) {\n    this.#defaultMapStyle = style;\n    this.#updateImageSrc();\n  }\n\n  #footer: boolean | string;\n\n  /**\n   * Custom footer text appearing below the map, when marker adjustment is enabled.\n   * If `true` or left undefined, the default footer text will be used.\n   * If `false`, the footer will not be shown.\n   *\n   * @name footer\n   * @instance\n   * @memberof MapboxAddressMinimap\n   * @type {boolean | string}\n   */\n  get footer(): boolean | string {\n    return this.#footer;\n  }\n  set footer(val: boolean | string) {\n    this.#footer = val;\n    const footerEl = this.querySelector<HTMLDivElement>('.MinimapFooter');\n    if (footerEl) {\n      if (typeof val === 'string') {\n        footerEl.textContent = val;\n        footerEl.removeAttribute('aria-hidden');\n      } else if (!val) {\n        footerEl.setAttribute('aria-hidden', 'true');\n      } else {\n        footerEl.removeAttribute('aria-hidden');\n      }\n    }\n  }\n\n  /**\n   * @deprecated Use `container` instead.\n   */\n  #container: HTMLElement | null;\n\n  get container(): HTMLElement | null {\n    return this.#container;\n  }\n\n  set container(newContainer: HTMLElement | null) {\n    if (newContainer) {\n      newContainer.style.position = 'relative';\n      this.#container = newContainer;\n    }\n  }\n\n  /** @section {Methods} */\n\n  /**\n   * If {@link MapboxAddressMinimap#feature} is truthy, show the minimap.\n   */\n  show(): void {\n    if (!this.#feature) {\n      return;\n    }\n\n    const lngLat = this.#feature.geometry.coordinates;\n    this.#markerController.coordinate = lngLat as [number, number];\n\n    this.#url = this.#getImageUrl(lngLat as [number, number]);\n\n    // Update image.\n    const { MapboxAddressMinimap, Image } = this.#binding;\n    Image.src = this.#url;\n\n    MapboxAddressMinimap.removeAttribute('aria-hidden');\n  }\n\n  /**\n   * Hide the minimap.\n   */\n  hide(): void {\n    const { MapboxAddressMinimap } = this.#binding;\n    MapboxAddressMinimap.setAttribute('aria-hidden', 'true');\n  }\n\n  #toggleMarkerEditing = (): void => {\n    const { ImageContainer, ButtonAdjust, ButtonSave, ButtonCancel } =\n      this.#binding;\n    if (this.#isAdjustMarkerEditing) {\n      ImageContainer.classList.add(`${this.dataset.seed}--draggable`);\n      this.#markerController.isActive = true;\n      ButtonAdjust.setAttribute('aria-hidden', 'true');\n      ButtonSave.removeAttribute('aria-hidden');\n      ButtonCancel.removeAttribute('aria-hidden');\n    } else {\n      ImageContainer.classList.remove(`${this.dataset.seed}--draggable`);\n      this.#markerController.isActive = false;\n      ButtonAdjust.removeAttribute('aria-hidden');\n      ButtonSave.setAttribute('aria-hidden', 'true');\n      ButtonCancel.setAttribute('aria-hidden', 'true');\n    }\n  };\n\n  #handleStartMarkerEditing = (): void => {\n    this.#isAdjustMarkerEditing = true;\n    this.#toggleMarkerEditing();\n  };\n\n  #handleSaveMarkerEditing = (): void => {\n    // Send feedback to Contribute API if feature includes address info, and the marker location has changed\n    if (\n      this.feature.properties.full_address &&\n      !deepEquals(\n        this.feature.geometry.coordinates,\n        this.#markerController.coordinate\n      )\n    ) {\n      const [lng, lat] = this.#markerController.coordinate;\n      sendFeedback(this.accessToken, {\n        originalCoordinate: this.feature.geometry.coordinates as [\n          number,\n          number\n        ],\n        originalAddress: this.feature.properties.full_address,\n        changes: {\n          location: { longitude: lng, latitude: lat }\n        },\n        labels: ['address_minimap']\n      });\n    }\n    // Client-defined callback\n    if (this.onSaveMarkerLocation) {\n      this.onSaveMarkerLocation(this.#markerController.coordinate);\n    }\n    // Update component state\n    this.#isAdjustMarkerEditing = false;\n    this.#toggleMarkerEditing();\n  };\n\n  #handleCancelMarkerEditing = (): void => {\n    this.#markerController.reCenter();\n    this.#isAdjustMarkerEditing = false;\n    this.#toggleMarkerEditing();\n  };\n\n  #handleToggleMapStyle = (): void => {\n    this.mapStyleMode =\n      this.mapStyleMode === 'default' ? 'satellite' : 'default';\n  };\n\n  #handleImageLoad = (): void => {\n    if (!this.#imageLoaded) {\n      this.#markerController.reCenter();\n    }\n    this.#imageLoaded = true;\n    this.#markerController && this.#markerController.handleMinimapResize();\n  };\n\n  #handleImageError = (): void => {\n    this.#imageLoaded = false;\n  };\n\n  /**\n   * Get the Static Image API URL for a given coordinate.\n   * Attempts to get an image twice as large as the container to enable panning,\n   * while constraining to the static API size limits.\n   * @param lngLatLike - The coordinate representing the center of the image\n   * @returns\n   */\n  #getImageUrl = (lngLatLike: LngLatLike): string => {\n    // Return empty string if height or width is 0 to prevent 422 error\n    if (this.#width === 0 || this.#height === 0) return '';\n\n    const [username, styleId] = this.defaultMapStyle;\n    const defaultBaseUrl = getStaticBaseUrl(username, styleId);\n    const baseUrl =\n      this.mapStyleMode === 'default'\n        ? defaultBaseUrl\n        : STATIC_BASE_URL_SATELLITE;\n    const skuToken =\n      AUTOFILL_SKU_TOKEN_PREFIX + config.autofillSessionToken.toString();\n    let imgUrl =\n      baseUrl +\n      LngLat.convert(lngLatLike).toArray().join(',') +\n      ',' +\n      ZOOM +\n      ',0/' +\n      Math.min(this.#width * 2, MAX_IMAGE_DIM) +\n      'x' +\n      Math.min(this.#height * 2, MAX_IMAGE_DIM) +\n      '?access_token=' +\n      this.accessToken +\n      '&attribution=false' +\n      '&logo=false';\n    if (config.autofillSessionEnabled) {\n      imgUrl += `&sku=${skuToken}`;\n    }\n    return imgUrl;\n  };\n\n  #updateImageSrc = (): void => {\n    if (this.#feature) {\n      const lngLat = this.#feature.geometry.coordinates;\n      this.#url = this.#getImageUrl(lngLat as [number, number]);\n      const { Image } = this.#binding;\n      Image.src = this.#url;\n    }\n  };\n\n  #getToggleBackgroundImageUrl = (styleMode: MapStyleMode): string => {\n    return `url(\"${getImage(\n      styleMode === 'default' ? 'styleToggleDefault' : 'styleToggleSatellite',\n      this.theme\n    )}\")`;\n  };\n\n  #setSize = (): void => {\n    const { MapboxAddressMinimap, ImageContainer, Image } = this.#binding;\n    const { width, height } = getElementSize(this.container);\n    const [oldWidth, oldHeight] = [this.#width, this.#height];\n    this.#width = Math.min(width, MAX_IMAGE_DIM); // Constrain to Static Image API limit\n    this.#height = Math.min(height, MAX_IMAGE_DIM); // Constrain to Static Image API limit\n    MapboxAddressMinimap.style.setProperty('width', `${this.#width}px`);\n    MapboxAddressMinimap.style.setProperty('height', `${this.#height}px`);\n    ImageContainer.style.setProperty('height', `${this.#height}px`);\n    ImageContainer.style.setProperty('width', `${this.#width}px`);\n    const [imgWidth, imgHeight] = [Image.width, Image.height];\n\n    /**\n     * Conditionally update the <img> src URL.\n     * Only updates if ALL of the following conditions are met:\n     * 1. The Minimap is INCREASING in X or Y dimension\n     * 2. The Minimap dimension is greater than half the <img> dimension (we want to aim for twice the extents for panning)\n     * 3. The <img> dimension is smaller than the maximum per Static Image API (i.e. it still has room to be sized up)\n     */\n    if (\n      (this.#width > oldWidth &&\n        this.#width > imgWidth / 2 &&\n        imgWidth < MAX_IMAGE_DIM) ||\n      (this.#height > oldHeight &&\n        this.#height > imgHeight / 2 &&\n        imgHeight < MAX_IMAGE_DIM)\n    ) {\n      this.#updateImageSrc();\n    } else {\n      this.#markerController && this.#markerController.handleMinimapResize();\n    }\n  };\n\n  #addMarkerEditControls = (): void => {\n    // Footer\n    const existingFooter = this.querySelector('.MinimapFooter');\n    if (existingFooter) return;\n    const footerElement = this.prepareTemplate(FOOTER_TEMPLATE);\n    const minimapElement = this.querySelector('.MapboxAddressMinimap');\n    if (!minimapElement) return;\n    minimapElement.appendChild(footerElement);\n\n    // Edit buttons\n    const existingEditBtns = this.querySelector('.MinimapEditButtons');\n    if (existingEditBtns) return;\n    const editButtonsElement = this.prepareTemplate(EDIT_BUTTONS_TEMPLATE);\n    const innerFrame = this.querySelector('.MinimapInnerFrame');\n    if (!innerFrame) return;\n    innerFrame.appendChild(editButtonsElement);\n\n    // Add to or update object binding\n    this.#binding = {\n      ...this.#binding,\n      EditButtons: this.querySelector('.MinimapEditButtons'),\n      ButtonAdjust: this.querySelector('.MinimapButtonAdjust'),\n      ButtonSave: this.querySelector('.MinimapButtonSave'),\n      ButtonCancel: this.querySelector('.MinimapButtonCancel')\n    };\n\n    // Bind callbacks to button click events\n    const { ButtonAdjust, ButtonSave, ButtonCancel } = this.#binding;\n    ButtonAdjust.addEventListener('click', this.#handleStartMarkerEditing);\n    ButtonSave.addEventListener('click', this.#handleSaveMarkerEditing);\n    ButtonCancel.addEventListener('click', this.#handleCancelMarkerEditing);\n  };\n\n  #removeMarkerEditControls = (): void => {\n    if (!this.#binding) return;\n    const { EditButtons, ButtonAdjust, ButtonSave, ButtonCancel } =\n      this.#binding;\n\n    const existingFooter = this.querySelector('.MinimapFooter');\n    existingFooter?.remove();\n    EditButtons?.remove();\n    if (ButtonAdjust) {\n      ButtonAdjust.remove();\n      ButtonAdjust.removeEventListener('click', this.#handleStartMarkerEditing);\n    }\n    if (ButtonSave) {\n      ButtonSave.remove();\n      ButtonSave.removeEventListener('click', this.#handleSaveMarkerEditing);\n    }\n    if (ButtonCancel) {\n      ButtonCancel.remove();\n      ButtonCancel.removeEventListener(\n        'click',\n        this.#handleCancelMarkerEditing\n      );\n    }\n\n    delete this.#binding.EditButtons;\n    delete this.#binding.ButtonAdjust;\n    delete this.#binding.ButtonSave;\n    delete this.#binding.ButtonCancel;\n  };\n\n  #addSatelliteToggle = (): void => {\n    const existingToggle = this.querySelector('.MinimapStyleToggle');\n    if (existingToggle) return;\n\n    // Add element to DOM\n    const toggleElement = this.prepareTemplate(STYLE_TOGGLE_TEMPLATE);\n    const innerFrame = this.querySelector('.MinimapInnerFrame');\n    if (!innerFrame) return;\n    innerFrame.appendChild(toggleElement);\n\n    // Add to or update object binding\n    this.#binding.MapStyleToggle = toggleElement;\n\n    // Bind callback\n    toggleElement.addEventListener('click', this.#handleToggleMapStyle);\n    // Initialize background image\n    toggleElement.style.backgroundImage = this.#getToggleBackgroundImageUrl(\n      this.mapStyleMode === 'default' ? 'satellite' : 'default'\n    );\n    toggleElement.setAttribute(\n      'title',\n      `Switch to ${this.mapStyleMode === 'default' ? 'Satellite' : 'Default'}`\n    );\n  };\n\n  #removeSatelliteToggle = (): void => {\n    if (!this.#binding) return;\n    const { MapStyleToggle } = this.#binding;\n    if (!MapStyleToggle) return;\n\n    MapStyleToggle.remove();\n    MapStyleToggle.removeEventListener('click', this.#handleToggleMapStyle);\n\n    delete this.#binding.MapStyleToggle;\n  };\n\n  connectedCallback(): void {\n    super.connectedCallback();\n\n    this.#binding = bindElements<Binding>(this, {\n      MapboxAddressMinimap: '.MapboxAddressMinimap',\n      ImageContainer: '.MinimapImageContainer',\n      Image: '.MinimapImage',\n      Marker: '.MinimapMarker',\n      MapStyleToggle: '.MinimapStyleToggle',\n      EditButtons: '.MinimapEditButtons',\n      ButtonAdjust: '.MinimapButtonAdjust',\n      ButtonSave: '.MinimapButtonSave',\n      ButtonCancel: '.MinimapButtonCancel'\n    });\n\n    // Update toggle button background image.\n    this.mapStyleMode = this.#mapStyleMode;\n\n    // Initialize theme if not set before connectedCallback\n    this.theme = { ...this.theme };\n\n    // Append buttons and footer if adjustable (re-check after connected)\n    if (this.#canAdjustMarkerInternal && !this.#binding.EditButtons) {\n      this.#addMarkerEditControls();\n    }\n\n    // Append style toggle if enabled (re-check after connected)\n    if (this.#satelliteToggleInternal && !this.#binding.MapStyleToggle) {\n      this.#addSatelliteToggle();\n    }\n\n    // Calculate size and listen for changes\n    this.container = this.parentElement;\n    const resizeObserver = new ResizeObserver(this.#setSize);\n    resizeObserver.observe(this.container);\n    this.#setSize();\n\n    const { MapboxAddressMinimap, ImageContainer, Image, Marker } =\n      this.#binding;\n\n    // Initialize marker controller\n    this.#markerController = new MarkerController(\n      ImageContainer,\n      Image,\n      Marker,\n      this.keepMarkerCentered,\n      ZOOM,\n      this.markerAnchor\n    );\n    this.#markerController.reCenter();\n    Image.onload = this.#handleImageLoad;\n    Image.onerror = this.#handleImageError;\n\n    Image.src = this.#url;\n\n    if (this.#feature) MapboxAddressMinimap.removeAttribute('aria-hidden');\n    else MapboxAddressMinimap.setAttribute('aria-hidden', 'true');\n  }\n\n  attributeChangedCallback(\n    name: string,\n    oldValue: string,\n    newValue: string\n  ): void {\n    if (name === 'access-token') {\n      this.accessToken = newValue;\n    } else if (name === 'can-adjust-marker') {\n      this.canAdjustMarker = ['true', ''].includes(newValue);\n    } else if (name === 'keep-marker-centered') {\n      this.keepMarkerCentered = ['true', ''].includes(newValue);\n    } else if (name === 'marker-anchor') {\n      const newAnchor = newValue as Anchor;\n      this.markerAnchor = newAnchor;\n      this.#markerController && (this.#markerController.anchor = newAnchor);\n    } else if (name === 'satellite-toggle') {\n      this.satelliteToggle = ['true', ''].includes(newValue);\n    }\n  }\n}\n\ndeclare global {\n  interface Window {\n    MapboxAddressMinimap: typeof MapboxAddressMinimap;\n  }\n}\n\nwindow.MapboxAddressMinimap = MapboxAddressMinimap;\n\nif (!window.customElements.get('mapbox-address-minimap')) {\n  customElements.define('mapbox-address-minimap', MapboxAddressMinimap);\n}\n","import SphericalMercator from '@mapbox/sphericalmercator';\nimport { deepEquals, round } from '.';\nimport { getElementSize } from './dom';\n\nexport type MapStyleMode = 'default' | 'satellite';\n\n/**\n * Valid strings for setting `markerAnchor` on {@link MapboxAddressMinimap}\n *\n * @typedef Anchor\n */\nexport type Anchor =\n  | 'center'\n  | 'top-left'\n  | 'top-right'\n  | 'bottom-left'\n  | 'bottom-right'\n  | 'top'\n  | 'bottom'\n  | 'left'\n  | 'right';\n\n// eslint-disable-next-line\n// @ts-ignore\nconst merc = new SphericalMercator({ size: 512, antimeridian: true });\n\nexport const MAX_IMAGE_DIM = 1280;\n\ninterface MarkerTransform {\n  /** X offset to correct for anchor position */\n  anchorX: number;\n  /** Y offset to correct for anchor position */\n  anchorY: number;\n  /** X offset from manual marker movement */\n  globalX: number;\n  /** Y offset from manual marker movement */\n  globalY: number;\n  correctionX: number;\n  correctionY: number;\n}\n\n/**\n * Get the [X,Y] pixel offset for a given SVG marker and anchor definition\n * @param marker - An SVG element used as the marker\n * @param anchor - The anchor point of the marker to put closest to the marked coordinate\n * @returns [X,Y] pixel coordinate\n */\nexport function getAnchorOffset(\n  marker: HTMLElement,\n  anchor: Anchor\n): [number, number] {\n  const { width, height } = getElementSize(marker, true);\n  switch (anchor) {\n    case 'center':\n      return [0, 0];\n    case 'top':\n      return [0, height / 2];\n    case 'bottom':\n      return [0, (-1 * height) / 2];\n    case 'left':\n      return [width / 2, 0];\n    case 'right':\n      return [(-1 * width) / 2, 0];\n    case 'top-left':\n      return [width / 2, height / 2];\n    case 'top-right':\n      return [(-1 * width) / 2, height / 2];\n    case 'bottom-left':\n      return [width / 2, (-1 * height) / 2];\n    case 'bottom-right':\n      return [(-1 * width) / 2, (-1 * height) / 2];\n  }\n}\n\n/**\n * Manages positioning of a static map image and marker relative to\n * pixel and geographical coordinates. Handles pointer events for\n * interactive/adjustable instances.\n */\nexport class MarkerController {\n  imgContainerElement: HTMLElement;\n  imgElement: HTMLImageElement;\n  markerElement: HTMLElement;\n  keepMarkerCentered: boolean;\n  zoom: number;\n\n  /** X-offset for the marker element to account for its positioning anchor */\n  anchorOffsetX: number;\n  /** Y-offset for the marker element to account for its positioning anchor */\n  anchorOffsetY: number;\n\n  /** Current X pixel of the pointer on the page */\n  curPointerXPos: number;\n  /** Current Y pixel of the pointer on the page */\n  curPointerYPos: number;\n  /** X-pixels deviation of marker position from the current map/feature center point */\n  markerDeltaX: number;\n  /** Y-pixels deviation of marker position from the current map/feature center point */\n  markerDeltaY: number;\n\n  /**\n   * Lng/lat of feature coordinate and initial image center represented as screen pixels.\n   * Value is fixed for a given original coordinate.\n   */\n  imgCenterPx: [number, number];\n  /**\n   * Lng/lat of adjusted image center as screen pixels.\n   * Value changes as the image is panned around in its container.\n   */\n  imgCenterAdjustedPx: [number, number];\n\n  /**\n   *\n   * @param imageContainer - The parent element of the <img>\n   * @param imageContainer - The <img> element\n   * @param marker - SVG Element used as the map marker\n   * @param keepMarkerCentered - If true, the marker will stay centered within the frame while the map moves behind it\n   * @param zoom - The zoom level of the static map, used to calculate between screen pixel and lng/lat\n   * @param anchor - The part of the marker that should be positioned closest to the coordinate\n   */\n  constructor(\n    imageContainer: HTMLElement,\n    imageElement: HTMLImageElement,\n    marker: HTMLElement,\n    keepMarkerCentered: boolean,\n    zoom: number,\n    anchor: Anchor\n  ) {\n    this.markerElement = marker;\n    this.imgContainerElement = imageContainer;\n    this.imgElement = imageElement;\n    this.keepMarkerCentered = keepMarkerCentered;\n    this.zoom = zoom;\n    this.anchor = anchor;\n\n    this.curPointerXPos = 0;\n    this.curPointerYPos = 0;\n    this.markerDeltaX = 0;\n    this.markerDeltaY = 0;\n\n    this.imgContainerElement.addEventListener(\n      'pointerdown',\n      this.#onPointerDownImage\n    );\n\n    if (!this.keepMarkerCentered) {\n      this.markerElement.addEventListener(\n        'pointerdown',\n        this.#onPointerDownMarker\n      );\n    }\n\n    // Listen for changes to anchor size\n    const resizeObserver = new ResizeObserver(this.#handleAnchorResize);\n    resizeObserver.observe(this.markerElement);\n  }\n\n  #anchor: Anchor;\n\n  get anchor(): Anchor {\n    return this.#anchor;\n  }\n\n  set anchor(newAnchor: Anchor) {\n    this.#anchor = newAnchor;\n    [this.anchorOffsetX, this.anchorOffsetY] = getAnchorOffset(\n      this.markerElement,\n      newAnchor\n    );\n    this.markerTransform = {\n      anchorX: this.anchorOffsetX,\n      anchorY: this.anchorOffsetY\n    };\n  }\n\n  #handleAnchorResize = (): void => {\n    [this.anchorOffsetX, this.anchorOffsetY] = getAnchorOffset(\n      this.markerElement,\n      this.anchor\n    );\n    this.markerTransform = {\n      anchorX: this.anchorOffsetX,\n      anchorY: this.anchorOffsetY\n    };\n  };\n\n  #markerTransform: MarkerTransform = {\n    anchorX: 0,\n    anchorY: 0,\n    globalX: 0,\n    globalY: 0,\n    correctionX: 0,\n    correctionY: 0\n  };\n\n  get markerTransform(): MarkerTransform {\n    return this.#markerTransform;\n  }\n\n  set markerTransform(val: Partial<MarkerTransform>) {\n    this.#markerTransform = {\n      ...this.#markerTransform,\n      ...val\n    };\n    this.#updateMarkerTransform();\n  }\n\n  #isActive = false;\n\n  /** True if the marker is currently in edit mode */\n  get isActive(): boolean {\n    return this.#isActive;\n  }\n\n  /** Set to true to enable editing of the marker */\n  set isActive(val: boolean) {\n    this.imgContainerElement.style.touchAction = val ? 'none' : '';\n    this.#isActive = val;\n  }\n\n  #originalCoordinate: [number, number];\n\n  /** Lng/lat of the current marker location */\n  get coordinate(): [number, number] {\n    const adjustedPx: [number, number] = this.keepMarkerCentered\n      ? this.imgCenterAdjustedPx\n      : [\n          this.imgCenterPx[0] - this.markerDeltaX,\n          this.imgCenterPx[1] + this.markerDeltaY\n        ];\n\n    // If the screen pixel hasn't changed, use the original coordinate so as not to incur any precision rounding during translation\n    if (deepEquals(adjustedPx, this.imgCenterPx)) {\n      return this.#originalCoordinate;\n    } else {\n      const lngLat = merc.ll(adjustedPx, this.zoom);\n      return [round(lngLat[0], 6), round(lngLat[1], 6)];\n    }\n  }\n\n  /** Set the lng/lat corresponding to the initial marker and image center location */\n  set coordinate(lngLat: [number, number]) {\n    this.#originalCoordinate = lngLat;\n    this.imgCenterPx = this.imgCenterAdjustedPx = merc.px(lngLat, this.zoom);\n  }\n\n  // Marker dragging event handlers\n  #onPointerDownMarker = (m: PointerEvent): void => {\n    if (!this.isActive) return;\n\n    m.preventDefault();\n    m.stopPropagation();\n\n    this.#updatePointerPosition(m);\n\n    window.addEventListener('pointermove', this.#onPointerMoveMarker);\n    window.addEventListener('pointerup', this.#onPointerUpMarker);\n  };\n\n  #onPointerUpMarker = (): void => {\n    window.removeEventListener('pointermove', this.#onPointerMoveMarker);\n    window.removeEventListener('pointerup', this.#onPointerUpMarker);\n  };\n\n  #onPointerMoveMarker = (m: PointerEvent): void => {\n    m.preventDefault();\n    m.stopPropagation();\n\n    // Calculate change in pointer position\n    const diffX = this.curPointerXPos - m.pageX;\n    const diffY = this.curPointerYPos - m.pageY;\n\n    // Update relative marker positioning\n    this.markerDeltaX += diffX;\n    this.markerDeltaY -= diffY;\n    // Clamp to image bounds\n    this.markerDeltaX = Math.max(\n      Math.min(this.imgElement.width / 2, this.markerDeltaX),\n      (this.imgElement.width / 2) * -1\n    );\n    this.markerDeltaY = Math.max(\n      Math.min(this.imgElement.height / 2, this.markerDeltaY),\n      (this.imgElement.height / 2) * -1\n    );\n\n    // Calculate X/Y transforms\n    const imageOffsetX = this.imgCenterPx[0] - this.imgCenterAdjustedPx[0];\n    const imageOffsetY = this.imgCenterPx[1] - this.imgCenterAdjustedPx[1];\n    const deltaX = this.markerDeltaX - imageOffsetX;\n    const deltaY = this.markerDeltaY + imageOffsetY;\n\n    this.markerTransform = { globalX: deltaX, globalY: deltaY };\n\n    // Update pointer position\n    this.#updatePointerPosition(m);\n  };\n\n  // Image dragging event handlers\n  #onPointerDownImage = (m: PointerEvent): void => {\n    if (!this.isActive) return;\n\n    m.preventDefault();\n    m.stopPropagation();\n\n    this.#updatePointerPosition(m);\n\n    window.addEventListener('pointermove', this.#onPointerMoveImage);\n    window.addEventListener('pointerup', this.#onPointerUpImage);\n  };\n\n  #onPointerUpImage = (): void => {\n    window.removeEventListener('pointermove', this.#onPointerMoveImage);\n    window.removeEventListener('pointerup', this.#onPointerUpImage);\n  };\n\n  #onPointerMoveImage = (m: PointerEvent): void => {\n    m.preventDefault();\n\n    // Calculate and constrain updated scroll position\n    let top = Math.round(\n      this.imgContainerElement.scrollTop + (this.curPointerYPos - m.pageY)\n    );\n    // Clamp to container bounds\n    top = Math.max(\n      Math.min(\n        this.imgElement.height - this.imgContainerElement.clientHeight,\n        top\n      ),\n      0\n    );\n    let left = Math.round(\n      this.imgContainerElement.scrollLeft + (this.curPointerXPos - m.pageX)\n    );\n    // Clamp to container bounds\n    left = Math.max(\n      Math.min(\n        this.imgElement.width - this.imgContainerElement.clientWidth,\n        left\n      ),\n      0\n    );\n    this.imgContainerElement.scrollTop = top;\n    this.imgContainerElement.scrollLeft = left;\n\n    // Update adjusted center location\n    const diffX = Math.round(\n      left - (this.imgElement.width - this.imgContainerElement.clientWidth) / 2\n    );\n    const diffY = Math.round(\n      (this.imgElement.height - this.imgContainerElement.clientHeight) / 2 - top\n    );\n    this.imgCenterAdjustedPx = [\n      this.imgCenterPx[0] + diffX,\n      this.imgCenterPx[1] - diffY\n    ];\n\n    if (!this.keepMarkerCentered) {\n      // Move marker in sync with image to maintain visual positioning on map\n      const deltaX = this.markerDeltaX + diffX;\n      const deltaY = this.markerDeltaY + diffY;\n      this.markerTransform = { globalX: deltaX, globalY: deltaY };\n    }\n\n    this.#updateMarkerCorrection(left, top);\n\n    // Update pointer position\n    this.#updatePointerPosition(m);\n  };\n\n  #updatePointerPosition = (m: PointerEvent): void => {\n    this.curPointerXPos = m.pageX;\n    this.curPointerYPos = m.pageY;\n  };\n\n  #updateMarkerTransform = (): void => {\n    const { anchorX, anchorY, globalX, globalY, correctionX, correctionY } =\n      this.#markerTransform;\n    const transformX = anchorX - globalX + correctionX;\n    const transformY = anchorY + globalY + correctionY;\n    this.markerElement.style.transform = `translate(calc(-50% + ${transformX}px), calc(-50% + ${transformY}px))`;\n  };\n\n  /** Re-center the marker on the map at its original location */\n  reCenter = (): void => {\n    // Set scroll values to center image in its container\n    const top =\n      (this.imgElement.height - this.imgContainerElement.clientHeight) / 2;\n    const left =\n      (this.imgElement.width - this.imgContainerElement.clientWidth) / 2;\n    this.imgContainerElement.scrollTop = top;\n    this.imgContainerElement.scrollLeft = left;\n\n    // Reset adjusted image center screen coordinate to match original\n    this.imgCenterAdjustedPx = this.imgCenterPx;\n\n    // Reset marker transform in case it was changed\n    this.markerDeltaX = this.markerDeltaY = 0;\n    this.markerTransform = {\n      globalX: 0,\n      globalY: 0,\n      correctionX: 0,\n      correctionY: 0\n    };\n  };\n\n  /**\n   * The x/y offset of the image from its center based on its scrolled position within its container.\n   */\n  get imgCenterOffset(): { x: number; y: number } {\n    return {\n      x: this.imgCenterPx[0] - this.imgCenterAdjustedPx[0],\n      y: this.imgCenterPx[1] - this.imgCenterAdjustedPx[1]\n    };\n  }\n\n  /** Update image scroll position when the Minimap has been resized */\n  handleMinimapResize = (): void => {\n    if (!this.imgElement.height || !this.imgElement.width) return;\n\n    const centerOffsetX = this.imgCenterOffset.x;\n    const centerOffsetY = this.imgCenterOffset.y;\n\n    const left =\n      this.imgElement.width / 2 -\n      centerOffsetX -\n      this.imgContainerElement.clientWidth / 2;\n    const top =\n      this.imgElement.height / 2 -\n      centerOffsetY -\n      this.imgContainerElement.clientHeight / 2;\n\n    this.imgContainerElement.scrollLeft = left;\n    this.imgContainerElement.scrollTop = top;\n\n    this.#updateMarkerCorrection(left, top);\n  };\n\n  /**\n   * Update marker X/Y transform corrections based on image scroll position\n   * @param scrollLeft - scrollLeft of image container\n   * @param scrollTop - scrollTop of image container\n   */\n  #updateMarkerCorrection = (scrollLeft: number, scrollTop: number): void => {\n    const centerOffsetX = this.imgCenterOffset.x;\n    const centerOffsetY = this.imgCenterOffset.y;\n\n    const { correctionX, correctionY } = this.markerTransform;\n\n    const corrections: Partial<MarkerTransform> = {};\n\n    // Update marker x-transform correction\n    if (scrollLeft / 2 < centerOffsetX * -1) {\n      const markerTranslateX = centerOffsetX * -1 - scrollLeft / 2;\n      corrections.correctionX = markerTranslateX * 2;\n    } else if (scrollLeft < 0) {\n      corrections.correctionX = scrollLeft;\n    } else if (correctionX !== 0) {\n      corrections.correctionX = 0;\n    }\n\n    // Update marker y-transform correction\n    if (scrollTop / 2 < centerOffsetY * -1) {\n      const markerTranslateY = centerOffsetY * -1 - scrollTop / 2;\n      corrections.correctionY = markerTranslateY * 2;\n    } else if (scrollTop < 0) {\n      corrections.correctionY = scrollTop;\n    } else if (correctionY !== 0) {\n      corrections.correctionY = 0;\n    }\n\n    this.markerTransform = corrections;\n  };\n}\n","import {\n  AddressAutofillFeatureSuggestion,\n  AddressAutofillOptions,\n  AddressAutofillRetrieveResponse,\n  AddressAutofillSuggestion,\n  AddressAutofillSuggestionResponse,\n  Evented,\n  AddressAutofillCore,\n  SearchSession\n} from '@mapbox/search-js-core';\n\nimport {\n  MapboxSearchListbox,\n  SelectionEventDetail\n} from './components/MapboxSearchListbox';\nimport { MapboxHTMLEvent } from './MapboxHTMLEvent';\nimport { Theme } from './theme';\nimport { deepEquals } from './utils';\nimport {\n  distinctExactStreetResults,\n  fillFormWithFeature,\n  findAddressInputs,\n  toggleAutocompletion\n} from './utils/autofill';\nimport { tryConfirmBrowserAutofill } from './utils/confirmation';\n\nimport { config } from './config';\n\nimport { initDetectBrowserAutofill } from './utils/detect_browser_autofill';\nimport { AddressConfirmOptions } from './components/MapboxAddressConfirmation';\nimport { PopoverOptions } from './utils/popover';\nimport {\n  createAriaLiveElement,\n  suppressExtensionsAutocomplete\n} from './utils/aria';\nimport { handleStreetSelection } from './utils/autofill';\nimport { SEARCH_SERVICE } from './utils/services';\nimport { InputEventDetail } from './utils/listbox';\nimport { MapboxEventManager } from './events/MapboxEventManager';\n\n/**\n * @class AddressAutofillInstance\n */\nexport class AddressAutofillInstance {\n  #input: HTMLInputElement;\n\n  get input(): HTMLInputElement {\n    return this.#input;\n  }\n\n  #collection: AddressAutofillCollectionType;\n  #session: SearchSession<\n    AddressAutofillOptions,\n    AddressAutofillSuggestion,\n    AddressAutofillSuggestionResponse,\n    AddressAutofillRetrieveResponse\n  >;\n\n  #autofillCoreRef: AddressAutofillCore;\n\n  options: Partial<AddressAutofillOptions> = {};\n\n  retrieveFeature: AddressAutofillFeatureSuggestion = null;\n\n  listbox = new MapboxSearchListbox();\n\n  #eventManager = new MapboxEventManager(SEARCH_SERVICE.AddressAutofill);\n\n  constructor(\n    collection: AddressAutofillCollectionType,\n    input: HTMLInputElement,\n    autofillRef: AddressAutofillCore\n  ) {\n    this.#input = input;\n    this.#collection = collection;\n    this.#session = new SearchSession<\n      AddressAutofillOptions,\n      AddressAutofillSuggestion,\n      AddressAutofillSuggestionResponse,\n      AddressAutofillRetrieveResponse\n    >(autofillRef);\n    this.#session.sessionToken = config.autofillSessionToken.id;\n\n    this.#autofillCoreRef = autofillRef;\n\n    this.listbox.input = this.#input;\n    this.listbox.autofillHost = this;\n    this.listbox.searchService = SEARCH_SERVICE.AddressAutofill;\n\n    this.#input.addEventListener('blur', this.#onHandleInputBlur);\n\n    this.listbox.addEventListener('input', this.#onHandleInput);\n    this.listbox.addEventListener('select', this.#onHandleSelect);\n    this.listbox.addEventListener('blur', this.#onHandleBlur);\n    this.listbox.addEventListener('focus', this.#onHandleFocus);\n\n    this.#session.addEventListener('suggest', this.#handleSuggest);\n    this.#session.addEventListener('suggesterror', this.#handleSuggestError);\n    this.#session.addEventListener('retrieve', this.#handleRetrieve);\n\n    document.body.appendChild(this.listbox);\n\n    if (input) {\n      input.insertAdjacentElement(\n        'beforebegin',\n        createAriaLiveElement(this.listbox.dataSeed)\n      );\n      suppressExtensionsAutocomplete(input);\n      this.#initialAutocompleteValue = input.autocomplete;\n    }\n  }\n\n  remove(): void {\n    this.listbox.remove();\n\n    this.#input.removeEventListener('blur', this.#onHandleInputBlur);\n\n    this.listbox.removeEventListener('input', this.#onHandleInput);\n    this.listbox.removeEventListener('select', this.#onHandleSelect);\n    this.listbox.removeEventListener('blur', this.#onHandleBlur);\n    this.listbox.removeEventListener('focus', this.#onHandleFocus);\n\n    this.#session.removeEventListener('suggest', this.#handleSuggest);\n    this.#session.removeEventListener('suggesterror', this.#handleSuggestError);\n    this.#session.removeEventListener('retrieve', this.#handleRetrieve);\n  }\n\n  #initialAutocompleteValue: string;\n\n  #onHandleInput = (e: MapboxHTMLEvent<InputEventDetail>): void => {\n    const { lastInput, inputText } = e.detail;\n\n    // if following flag set to true and search text is equal or less than 2 characters - enable browser autofill.\n    const enableBrowserAutocomplete =\n      this.#collection.browserAutofillEnabled === true &&\n      inputText?.length <= 2;\n\n    toggleAutocompletion(\n      this.#input,\n      this.#initialAutocompleteValue,\n      enableBrowserAutocomplete\n    );\n\n    if (!inputText) {\n      this.#handleClear();\n      return;\n    }\n\n    if (inputText?.length <= 2) {\n      this.listbox.handleSuggest(null);\n      return;\n    }\n\n    this.#session.suggest(inputText, this.options);\n    this.#eventManager.input(\n      inputText,\n      lastInput,\n      {\n        ...this.options,\n        sessionToken: this.#session.sessionToken,\n        accessToken: this.#collection.accessToken\n      },\n      null,\n      this.#autofillCoreRef.responseHeaders\n    );\n  };\n\n  #onHandleSelect = (\n    e: MapboxHTMLEvent<SelectionEventDetail<AddressAutofillSuggestion>>\n  ): void => {\n    const { suggestion, selectedIndex } = e.detail;\n    if (suggestion.accuracy !== 'street') {\n      toggleAutocompletion(this.#input, this.#initialAutocompleteValue, true);\n      this.#session.retrieve(suggestion, this.options);\n      this.#eventManager.select(\n        this.input.value,\n        selectedIndex,\n        this.listbox.suggestions,\n        {\n          ...this.options,\n          sessionToken: this.#session.sessionToken,\n          accessToken: this.#collection.accessToken\n        },\n        null,\n        this.#autofillCoreRef.responseHeaders\n      );\n    } else {\n      handleStreetSelection(\n        this.#input,\n        this.#initialAutocompleteValue,\n        suggestion\n      );\n    }\n  };\n\n  #onHandleBlur = (): void => {\n    toggleAutocompletion(this.#input, this.#initialAutocompleteValue, true);\n    // Abort any in-progress operations.\n    this.#session.abort();\n  };\n\n  #onHandleInputBlur = (event: FocusEvent): void => {\n    if (!this.listbox.contains(event.relatedTarget as Node)) {\n      this.#onHandleBlur();\n      this.listbox.hideResults();\n    }\n  };\n\n  #onHandleFocus = (): void => {\n    const enableBrowserAutocomplete =\n      this.#collection.browserAutofillEnabled === true &&\n      this.#input.value?.length <= 2;\n    toggleAutocompletion(\n      this.#input,\n      this.#initialAutocompleteValue,\n      enableBrowserAutocomplete\n    );\n  };\n\n  #handleClear = (): void => {\n    this.listbox.handleSuggest(null);\n    this.#eventManager.clear();\n  };\n\n  #handleSuggest = (result: AddressAutofillSuggestionResponse): void => {\n    const filteredSuggestions = result?.suggestions\n      ? distinctExactStreetResults(result.suggestions)\n      : null;\n    this.listbox.handleSuggest(filteredSuggestions);\n    // Manually bubble up the event.\n    const event = new MapboxHTMLEvent('suggest', result);\n    Object.defineProperty(event, 'target', { value: this.#input });\n    this.#collection.fire('suggest', event);\n  };\n\n  #handleSuggestError = (error: Error): void => {\n    this.listbox.handleError();\n    // Manually bubble up the event.\n    const event = new MapboxHTMLEvent('suggesterror', error);\n    Object.defineProperty(event, 'target', { value: this.#input });\n    this.#collection.fire('suggesterror', event);\n  };\n\n  #handleRetrieve = (result: AddressAutofillRetrieveResponse): void => {\n    const event = new MapboxHTMLEvent('retrieve', result);\n    // Manually bubble up the event.\n    Object.defineProperty(event, 'target', { value: this.#input });\n    this.#collection.fire('retrieve', event);\n\n    this.retrieveFeature = result.features?.[0];\n\n    if (!this.#input) {\n      return;\n    }\n\n    const featureCollection = result;\n    if (\n      !featureCollection ||\n      !featureCollection.features ||\n      !featureCollection.features.length\n    ) {\n      return;\n    }\n\n    fillFormWithFeature(featureCollection.features[0], this.#input);\n  };\n\n  simulateRetrieve(feature: AddressAutofillFeatureSuggestion): void {\n    const input = this.#input;\n    if (input) {\n      input.dataset['mapboxSuccess'] = 'true';\n    }\n    this.listbox.hideResults();\n\n    const simResult: AddressAutofillRetrieveResponse = {\n      type: 'FeatureCollection',\n      features: [feature],\n      url: ''\n    };\n\n    this.#handleRetrieve(simResult);\n  }\n}\n\n/**\n * Object defining options for Address Autofill search behavior and UI. Used to configure {@link AddressAutofillCollection}\n * @typedef AddressAutofillCollectionOptions\n */\nexport interface AddressAutofillCollectionOptions {\n  /**\n   * The [Mapbox access token](https://docs.mapbox.com/help/glossary/access-token/) to use for all requests.\n   */\n  accessToken?: string;\n  /**\n   * Options to pass to the underlying {@link AddressAutofillCore} interface.\n   */\n  options?: Partial<AddressAutofillOptions>;\n  /**\n   * The {@link Theme} to use for styling the autofill component.\n   */\n  theme?: Theme;\n  /**\n   * The {@link PopoverOptions} to define popover positioning.\n   */\n  popoverOptions?: Partial<PopoverOptions>;\n  /**\n   * If true, forms autofilled by the browser will prompt the\n   * {@link confirmAddress} dialog for user confirmation.\n   * An {@link AddressConfirmOptions} object can also be passed\n   * to prompt {@link confirmAddress} with custom options.\n   * Defaults to false.\n   */\n  confirmOnBrowserAutofill?: boolean | AddressConfirmOptions;\n  /**\n   * Enables the browser's autocomplete popup to show during the first two typed characters while Mapbox results are suppressed. Defaults to false.\n   *\n   * **Note:** Due to varying specifications, efforts to suppress browser autocomplete behavior may not work on all browsers.\n   */\n  browserAutofillEnabled?: boolean;\n}\n\ninterface EventTypes<\n  AddressAutofillSuggestionResponse,\n  AddressAutofillRetrieveResponse\n> {\n  /**\n   * Fired when the user is typing in the input and provides a list of suggestions.\n   *\n   * The underlying response from {@link AddressAutofillCore} is passed as the event's detail,\n   * while the responsible input is passed as the event's target.\n   *\n   * @event suggest\n   * @instance\n   * @memberof AddressAutofillCollection\n   * @type {AddressAutofillSuggestionResponse}\n   * @example\n   * ```typescript\n   * collection.addEventListener('suggest', (event) => {\n   *   const suggestions = event.detail.suggestions;\n   *   const inputEl = event.target;\n   *   // ...\n   * });\n   * ```\n   */\n  suggest: MapboxHTMLEvent<AddressAutofillSuggestionResponse>;\n  /**\n   * Fired when {@link AddressAutofillCore} has errored providing a list of suggestions.\n   *\n   * The underlying error is passed as the event's detail,\n   * while the responsible input is passed as the event's target.\n   *\n   * @event suggesterror\n   * @instance\n   * @memberof AddressAutofillCollection\n   * @type {Error}\n   * @example\n   * ```typescript\n   * collection.addEventListener('suggesterror', (event) => {\n   *   const error = event.detail;\n   *   const inputEl = event.target;\n   *   // ...\n   * });\n   * ```\n   */\n  suggesterror: MapboxHTMLEvent<Error>;\n  /**\n   * Fired when the user has selected a suggestion, before the form is autofilled.\n   *\n   * The underlying response from {@link AddressAutofillCore} is passed as the event's detail,\n   * while the responsible input is passed as the event's target.\n   *\n   * @event retrieve\n   * @instance\n   * @memberof AddressAutofillCollection\n   * @type {AddressAutofillRetrieveResponse}\n   * @example\n   * ```typescript\n   * autofill.addEventListener('retrieve', (event) => {\n   *   const featureCollection = event.detail;\n   *   const inputEl = event.target;\n   *   // ...\n   * });\n   * ```\n   */\n  retrieve: MapboxHTMLEvent<AddressAutofillRetrieveResponse>;\n}\n\nexport type AddressAutofillCollectionType = AddressAutofillCollection<\n  AddressAutofillSuggestionResponse,\n  AddressAutofillRetrieveResponse\n>;\n\n/**\n * Underlying collection object class returned by the {@link autofill} function.\n *\n * @class AddressAutofillCollection\n */\nexport class AddressAutofillCollection<\n  AddressAutofillSuggestionResponse,\n  AddressAutofillRetrieveResponse\n> extends Evented<\n  EventTypes<AddressAutofillSuggestionResponse, AddressAutofillRetrieveResponse>\n> {\n  instances: AddressAutofillInstance[] = [];\n  #currentInputs: HTMLInputElement[];\n\n  #autofill = new AddressAutofillCore();\n\n  constructor({\n    accessToken,\n    options,\n    theme,\n    popoverOptions,\n    confirmOnBrowserAutofill,\n    browserAutofillEnabled\n  }: AddressAutofillCollectionOptions) {\n    super();\n\n    // Setup browser autofill detection\n    initDetectBrowserAutofill();\n    window.addEventListener('browserautofill', this.#handleBrowserAutofill);\n\n    config.autofillSessionEnabled = true;\n\n    this.accessToken = accessToken || config.accessToken;\n    options && (this.options = options);\n    theme && (this.theme = theme);\n    popoverOptions && (this.popoverOptions = popoverOptions);\n    confirmOnBrowserAutofill &&\n      (this.confirmOnBrowserAutofill = confirmOnBrowserAutofill);\n    browserAutofillEnabled &&\n      (this.browserAutofillEnabled = browserAutofillEnabled);\n    this.update();\n  }\n\n  /**\n   * The [Mapbox access token](https://docs.mapbox.com/help/glossary/access-token/) to use for all requests.\n   *\n   * @example\n   * ```typescript\n   * autofill.accessToken = 'pk.my-mapbox-access-token';\n   * ```\n   */\n  get accessToken(): string {\n    return this.#autofill.accessToken;\n  }\n  set accessToken(newToken: string) {\n    this.#autofill.accessToken = newToken;\n  }\n\n  #options: Partial<AddressAutofillOptions>;\n\n  /**\n   * Options to pass to the underlying {@link AddressAutofillCore} interface.\n   *\n   * @example\n   * ```typescript\n   * autofill.options = {\n   *  language: 'en',\n   *  country: 'US',\n   * };\n   * ```\n   */\n  get options(): Partial<AddressAutofillOptions> {\n    return this.#options;\n  }\n  set options(newOptions: Partial<AddressAutofillOptions>) {\n    this.#options = { ...this.#options, ...newOptions };\n    this.instances.forEach((instance) => {\n      instance.options = { ...instance.options, ...newOptions };\n    });\n  }\n\n  #theme: Theme;\n\n  /**\n   * The {@link Theme} to use for styling the autofill component.\n   *\n   * @example\n   * ```typescript\n   * autofill.theme = {\n   *   variables: {\n   *     colorPrimary: 'myBrandRed'\n   *   }\n   * };\n   * ```\n   */\n  get theme(): Theme {\n    return this.#theme;\n  }\n  set theme(newTheme: Theme) {\n    this.#theme = newTheme;\n    this.instances.forEach((instance) => {\n      instance.listbox.theme = newTheme;\n    });\n  }\n\n  #popoverOptions: Partial<PopoverOptions>;\n\n  /**\n   * The {@link PopoverOptions} to define popover positioning.\n   *\n   * @example\n   * ```typescript\n   * autofill.popoverOptions = {\n   *   placement: 'top-start',\n   *   flip: true,\n   *   offset: 5\n   * };\n   * ```\n   */\n  get popoverOptions(): Partial<PopoverOptions> {\n    return this.#popoverOptions;\n  }\n  set popoverOptions(newOptions: Partial<PopoverOptions>) {\n    this.#popoverOptions = newOptions;\n    this.instances.forEach((instance) => {\n      instance.listbox.popoverOptions = newOptions;\n    });\n  }\n\n  /**\n   * If true, forms autofilled by the browser will prompt the\n   * {@link confirmAddress} dialog for user confirmation.\n   * An {@link AddressConfirmOptions} object can also be passed\n   * to prompt {@link confirmAddress} with custom options.\n   * Defaults to false.\n   *\n   * @name confirmOnBrowserAutofill\n   * @instance\n   * @memberof AddressAutofillCollection\n   * @type {boolean | AddressConfirmOptions}\n   * @example\n   * ```typescript\n   * autofill.confirmOnBrowserAutofill = {\n   *   minimap: true,\n   *   skipConfirmModal: (feature) =>\n   *     ['exact', 'high'].includes(\n   *       feature.properties.match_code.confidence\n   *     )\n   * };\n   * ```\n   */\n  confirmOnBrowserAutofill: boolean | AddressConfirmOptions = false;\n\n  /**\n   * Enables the browser's autocomplete popup to show during the first two typed characters while Mapbox results are suppressed. Defaults to false.\n   *\n   * **Note:** Due to varying specifications, efforts to suppress browser autocomplete behavior may not work on all browsers.\n   *\n   * @name browserAutofillEnabled\n   * @instance\n   * @memberof AddressAutofillCollection\n   * @type {boolean}\n   * @example\n   * ```typescript\n   * autofill.browserAutofillEnabled = true;\n   * ```\n   */\n  browserAutofillEnabled?: boolean = false;\n\n  /** @section {Methods} */\n\n  /**\n   * Updates autofill collection based on the current DOM state.\n   * @example\n   * ```typescript\n   * collection.update();\n   * ```\n   */\n  update(): void {\n    // STEP 0: Remove and clean up any existing autofill instances\n    this.instances.forEach((instance) => {\n      instance.remove();\n    });\n    // STEP 1: Find the input element(s)\n    this.#currentInputs = findAddressInputs();\n    // STEP 2: Create a new autofill instance for each input\n    this.instances = [];\n    this.#currentInputs.forEach((input) => {\n      const autofillInstance = new AddressAutofillInstance(\n        this,\n        input,\n        this.#autofill\n      );\n      autofillInstance.options = this.options;\n      autofillInstance.listbox.theme = this.theme;\n      autofillInstance.listbox.popoverOptions = this.popoverOptions;\n      this.instances.push(autofillInstance);\n    });\n  }\n\n  // TODO: optimize this!\n  // Called when content changes.\n  #handleObserve = (): void => {\n    // TODO: add test to make sure this comparison works\n    if (!deepEquals(findAddressInputs(), this.#currentInputs)) {\n      this.update();\n    }\n  };\n\n  #observer = new MutationObserver(this.#handleObserve);\n\n  /**\n   * Listen for changes to the DOM, and update autofill instances when autofill-able inputs are added/removed.\n   *\n   * **IMPORTANT:** For performance reasons, it is recommended to carefully control\n   * when this is called and to call {@link AddressAutofillCollection#unobserve} when finished.\n   *\n   * @example\n   * ```typescript\n   * collection.observe();\n   * ```\n   */\n  observe(): void {\n    // Setup observer handler.\n    this.#observer.observe(document, {\n      subtree: true,\n      childList: true\n    });\n\n    this.#handleObserve();\n  }\n\n  /**\n   * Stop listening for changes to the DOM. This only has an effect if called\n   * after {@link AddressAutofillCollection#observe}.\n   *\n   * @example\n   * ```typescript\n   * collection.unobserve();\n   * ```\n   */\n  unobserve(): void {\n    this.#observer.disconnect();\n  }\n\n  /**\n   * Removes all autofill instances and listeners in the document.\n   *\n   * @example\n   * ```typescript\n   * collection.remove();\n   * ```\n   */\n  remove(): void {\n    this.instances.forEach((instance) => {\n      instance.remove();\n    });\n    this.unobserve();\n    window.removeEventListener('browserautofill', this.#handleBrowserAutofill);\n  }\n\n  #handleBrowserAutofill = async (e: CustomEvent): Promise<void> => {\n    // Hide listbox, if showing\n    this.instances.forEach((instance) => instance.listbox.blur());\n\n    // Address confirmation\n    for (const instance of this.instances) {\n      const input = instance.listbox.input;\n      await tryConfirmBrowserAutofill(\n        input,\n        e,\n        this.confirmOnBrowserAutofill,\n        this.accessToken\n      );\n    }\n  };\n}\n\n/**\n * Entry point for Mapbox Address Autofill, for use on standard HTML input elements.\n *\n * Compared to {@link MapboxAddressAutofill}, this function automatically attaches\n * to eligible [`<input>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/text) elements in-place.\n *\n * You must have a [Mapbox access token](https://www.mapbox.com/help/create-api-access-token/).\n *\n * Eligible inputs must be a descendant of a [`<form>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form) element, and the form\n * must have inputs with proper HTML `autocomplete` attributes. The input itself must be of autocomplete `\"street-address\"` or `\"address-line1\"\"`.\n *\n * If your application works with browser autofill, you may already have this functionality.\n * - [The HTML autocomplete attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete)\n * - [Autofill](https://web.dev/learn/forms/autofill/)\n *\n * @param optionsArg - {@link AddressAutofillCollectionOptions} Object defining options for Address Autofill search behavior and UI.\n * @example\n * <input type=\"text\" autocomplete=\"street-address\" />\n * <script>\n * mapboxsearch.autofill({\n *   accessToken: 'pk.my.token',\n *   options: { country: 'us' }\n * };\n * </script>\n * @example\n * ```typescript\n * const collection = autofill({\n *   accessToken: 'pk.my.token',\n *   options\n * })\n *\n * myClientSideRouter.on('route', () => collection.update());\n * ```\n */\nexport function autofill(\n  optionsArg: AddressAutofillCollectionOptions\n): AddressAutofillCollectionType {\n  return new AddressAutofillCollection(optionsArg);\n}\n"]}