places-autocomplete-js 1.1.2 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Initializes a Places Autocomplete widget.
2
+ * Initialises a Places Autocomplete widget.
3
3
  * This script dynamically loads the Google Maps JavaScript API, creates the UI elements
4
4
  * for the autocomplete input and suggestions list, handles user input with debouncing,
5
5
  * fetches suggestions, manages keyboard navigation, and calls user-defined callbacks
@@ -1 +1 @@
1
- {"version":3,"file":"places-autocomplete.js","sources":["../PlacesAutocomplete.js"],"sourcesContent":["/**\n * Initializes a Places Autocomplete widget.\n * This script dynamically loads the Google Maps JavaScript API, creates the UI elements\n * for the autocomplete input and suggestions list, handles user input with debouncing,\n * fetches suggestions, manages keyboard navigation, and calls user-defined callbacks\n * on place selection or error.\n *\n * @author Alexander Pechkarev <alexpechkarev@gmail.com>\n * @license MIT\n *\n */\n\n/**\n * PacAutocomplete class\n * This class provides a Places Autocomplete widget.\n */\nexport class PlacesAutocomplete {\n // --- Private Properties (using # or _ prefix by convention) ---\n #containerId; // Container ID where the autocomplete widget will be rendered.\n #pacEl;\n #googleMapsApiKey;\n #googleMapsApiVersion;\n #options;\n #request;\n #inputElement;\n #container;\n #ul;\n #kbdEscape;\n #kbdUp;\n #kbdDown;\n #allSuggestions = [];\n #currentSuggestion = -1;\n #onDataCallback; // For user-provided data callback\n #onErrorCallback; // For user-provided error callback\n _debouncedMakeAcRequest; // Declare without initializing here\n #defaultOptions = {\n // Default options for the autocomplete widget.\n autofocus: false, // Automatically focus the input on load.\n autocomplete: \"off\", // HTML autocomplete attribute for the input.\n placeholder: \"Start typing your address ...\", // Placeholder text for the input.\n distance: true, // Show distance in suggestions (requires origin in request).\n distance_units: \"km\", // Units for distance ('km' or 'miles').\n label: \"\", // Optional label text above the input.\n debounce: 100, // Debounce delay (ms) for API requests.\n clear_input: true, // Clear input button (not implemented in this version).\n debug: false, // Enable debug mode (not implemented in this version).\n };\n #defaultClasses = {\n // CSS classes for various parts of the widget.\n section: \"\", // Outer section container.\n container: \"relative z-10 transform rounded-xl mt-4\", // Main container div.\n icon_container:\n \"pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3\", // Container for the search icon.\n icon: '<svg xmlns=\"http://www.w3.org/2000/svg\" class=\"w-5 h-5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"11\" cy=\"11\" r=\"8\" /><path d=\"m21 21-4.3-4.3\" /></svg>', // SVG for the search icon.\n input:\n \"border-1 w-full rounded-md border-0 shadow-sm bg-gray-100 px-4 py-2.5 pl-10 pr-20 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 sm:text-sm\", // Input field.\n kbd_container: \"absolute inset-y-0 right-0 flex py-1.5 pr-1.5\", // Container for keyboard hints.\n kbd_escape:\n \"inline-flex items-center rounded border border-gray-300 px-1 font-sans text-xs text-gray-500 w-8 mr-1\", // Escape key hint.\n kbd_up:\n \"inline-flex items-center justify-center rounded border border-gray-300 px-1 font-sans text-xs text-gray-500 w-6\", // Up arrow key hint.\n kbd_down:\n \"inline-flex items-center rounded border border-gray-400 px-1 font-sans text-xs text-gray-500 justify-center w-6\", // Down arrow key hint.\n kbd_active: \"bg-indigo-500 text-white\", // Class for active keyboard hint.\n ul: \"absolute z-50 -mb-2 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm divide-y divide-gray-100\", // Suggestions list (ul).\n li: \"z-50 cursor-default select-none py-2 px-2 lg:px-4 text-gray-900 hover:bg-indigo-500 hover:text-white\", // Suggestion item (li).\n li_current: \"bg-indigo-500\", // Class for the currently selected suggestion item.\n li_a: \"block w-full flex justify-between\", // Link element within a suggestion item.\n li_a_current: \"text-white\", // Class for the link in the currently selected suggestion item.\n li_div_container: \"flex min-w-0 gap-x-4\", // Container div within the suggestion link.\n li_div_one: \"min-w-0 flex-auto\", // First inner div (for place name).\n li_div_one_p: \"text-sm/6\", // Paragraph for the place name.\n li_div_two: \"shrink-0 flex flex-col items-end min-w-16\", // Second inner div (for distance).\n li_div_two_p: \"mt-1 text-xs/5\", // Paragraph for the distance.\n highlight: \"font-bold\", // Class for highlighting matched text in suggestions.\n };\n #defaultRequestParams = {\n // Default parameters for the autocomplete request.\n input: \"\", // Initial input value (empty).\n includedRegionCodes: [\"GB\"], // Default region codes to include in suggestions.\n language: \"en-gb\",\n region: \"GB\",\n };\n #fetchFields = [\"formattedAddress\", \"addressComponents\"];\n #defaultFetchFields = [\"formattedAddress\", \"addressComponents\"]; // Fields to fetch for the selected place (can be extended).\n\n /**\n * Class constructor for PacAutocomplete.\n * Initializes the autocomplete widget with the provided configuration.\n * @param {Object} config - Configuration object for the autocomplete widget.\n * @param {string} config.containerId - ID of the container element for the widget.\n * @param {string} config.googleMapsApiKey - Google Maps API key.\n * @param {string} [config.googleMapsApiVersion] - Version of the Google Maps API to use (default: \"weekly\").\n * @param {Object} [config.options] - Additional options for the widget (e.g., classes, callbacks).\n * @param {Object} [config.requestParams] - Parameters for the autocomplete request (e.g., input, region).\n * @param {*} config\n */\n constructor(config) {\n if (!config || !config.containerId || !config.googleMapsApiKey) {\n throw new Error(\n \"PacAutocomplete: Missing required configuration (containerId, googleMapsApiKey).\"\n );\n }\n\n this.#containerId = config.containerId; // Store the configuration object\n this.#pacEl = document.getElementById(config.containerId);\n if (!this.#pacEl) {\n throw new Error(\n `PacAutocomplete: Container element with ID \"${config.containerId}\" not found.`\n );\n }\n\n this.#googleMapsApiKey = config.googleMapsApiKey;\n this.#googleMapsApiVersion = config.googleMapsApiVersion || \"weekly\";\n\n // Merge user options with defaults\n this.#options = {\n ...this.#defaultOptions, // Default options\n ...config.options, // User-defined options override defaults\n };\n // Ensure classes are deeply merged if user provides partial classes\n if (config.options && config.options.classes) {\n this.#options.classes = {\n ...this.#defaultClasses,\n ...config.options.classes,\n };\n } else {\n this.#options.classes = this.#defaultClasses; // Use default classes if none provided\n }\n\n if (this.#options.debug) {\n console.log(\"___debug constructor options:\");\n console.log(this.#options);\n }\n\n if (config.fetchFields && Array.isArray(config.fetchFields)) {\n this._setFetchFields(config.fetchFields); // Set fetch fields from user config\n }\n\n // Set default response and error callbacks if not provided\n this.#onDataCallback =\n config.onResponse ||\n ((place) => {\n console.info(\"---------Default onResponse not provided---------\");\n console.info(\"Selected Place:\", JSON.stringify(place, null, 2));\n });\n this.#onErrorCallback =\n config.onError ||\n ((error) => {\n console.error(\"---------Default onError not provided---------\");\n console.error(\"PAC Error:\", error);\n });\n\n if (config.requestParams && Object.keys(config.requestParams).length > 0) {\n this.#request = {\n ...this.#defaultRequestParams,\n ...config.requestParams,\n };\n } else {\n this.#request = { ...this.#defaultRequestParams }; // Use defaults if no requestParams provided\n }\n\n if (this.#options.debug) {\n console.log(\"___debug constructor requestParams:\", this.#request);\n }\n\n this._initialiseDebouncedRequest(); // Initialize the debounced request function\n\n this._init(); // Underscore prefix for internal initialization method\n }\n\n // --- Private Initialization Method ---\n async _init() {\n try {\n // check if google maps api is already loaded\n if (typeof google === \"undefined\" || !google.maps) {\n // Load the Google Maps API dynamically\n await this._loadGoogleMapsApi({\n key: this.#googleMapsApiKey,\n v: this.#googleMapsApiVersion,\n });\n }\n this._createPACStructure();\n await this._initializeAutocomplete();\n } catch (error) {\n this.#onErrorCallback(error);\n }\n }\n\n /**\n * Initializes the debounced request function for fetching autocomplete suggestions.\n *\n * Debounced function to fetch autocomplete suggestions from the Google Places API.\n * Triggered by the 'input' event on the input element.\n *\n *\n */\n _initialiseDebouncedRequest() {\n this._debouncedMakeAcRequest = this._debounce(async () => {\n if (!this.#inputElement || !this.#inputElement.value) {\n this._reset();\n if (this.#inputElement)\n this.#inputElement.setAttribute(\"aria-expanded\", \"false\");\n return;\n }\n\n this.#request.input = this.#inputElement.value;\n\n try {\n const { suggestions } =\n // eslint-disable-next-line no-undef\n await google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions(\n this.#request\n );\n\n // Display suggestions\n if (suggestions && suggestions.length > 0) {\n this.#ul.replaceChildren(\n ...this._createSuggestionElements(suggestions)\n );\n this.#ul.style.display = \"block\";\n this.#inputElement.setAttribute(\"aria-expanded\", \"true\");\n } else {\n // No suggestions found\n this._reset(); // Clear any old suggestions\n this.#inputElement.setAttribute(\"aria-expanded\", \"false\");\n // Optionally display a \"no results\" message in the 'ul'\n }\n } catch (error) {\n this.#onErrorCallback(error);\n this._reset();\n }\n }, this.#options.debounce); // Default debounce to 100ms if not set\n }\n /**\n * Sets the fields to fetch for the selected place.\n * @param {Array<string>} fields - The fields to fetch.\n */\n _setFetchFields(fields) {\n if (Array.isArray(fields) && fields.length > 0) {\n this.#fetchFields = [\n ...new Set([...this.#defaultFetchFields, ...fields]),\n ].filter((e) => e); // Ensure unique and non-empty fields\n }\n }\n\n /**\n * Creates a debounced version of a function.\n * The debounced function delays invoking `func` until after `wait` milliseconds have\n * elapsed since the last time the debounced function was invoked.\n * @param {Function} func - The function to debounce.\n * @param {number} wait - The number of milliseconds to delay.\n * @returns {Function} The new debounced function.\n */\n _debounce(func, wait) {\n if (this.#options.debug) {\n console.log(\"___debug debounce function called with wait:\", wait);\n }\n\n let timeout = null;\n return function executedFunction(...args) {\n const later = () => {\n timeout = null;\n func(...args); // Call original function\n };\n if (timeout !== null) {\n clearTimeout(timeout); // Clear the previous timeout\n }\n timeout = setTimeout(later, wait ?? 100); // Set the new timeout\n };\n }\n /**\n * Formats a distance in meters into kilometers or miles.\n * @param {number | null | undefined} distance - Distance in meters.\n * @param {'km' | 'miles'} units - The desired output units.\n * @returns {string | null} Formatted distance string (e.g., \"1.23 km\") or null if input is invalid.\n */\n _formatDistance(distance, units) {\n if (typeof distance !== \"number\" || !this.#options.distance) {\n return null; // Return null if distance isn't shown or invalid\n }\n let value;\n let unitLabel;\n if (units === \"km\") {\n value = (distance / 1000).toFixed(2);\n unitLabel = \"km\";\n } else {\n // Default to miles if not 'km'\n value = (distance / 1609.34).toFixed(2);\n unitLabel = \"miles\";\n }\n // Avoid showing \".00\"\n value = value.replace(/\\.00$/, \"\");\n return `${value} ${unitLabel}`;\n }\n\n /**\n * Dynamically loads the Google Maps JavaScript API using the importLibrary method.\n * This is the standard approach recommended by Google.\n * @see https://developers.google.com/maps/documentation/javascript/load-maps-js-api\n * @param {object} g - Configuration object for the API loader (key, v, libraries, etc.).\n */\n async _loadGoogleMapsApi(g) {\n var h, // Promise tracking API load\n a, // Script element\n k, // Loop variable for config keys\n p = \"The Google Maps JavaScript API\", // Error message prefix\n c = \"google\", // Global namespace\n l = \"importLibrary\", // Loader function name\n q = \"__ib__\", // Internal callback name\n m = document, // Document reference\n b = window; // Window reference\n b = b[c] || (b[c] = {}); // Ensure google namespace exists\n var d = b.maps || (b.maps = {}), // Ensure google.maps namespace exists\n r = new Set(), // Set to track requested libraries\n e = new URLSearchParams(), // URL parameters for the API script\n u = () =>\n // Function to initiate API loading (if not already started)\n h ||\n // eslint-disable-next-line no-async-promise-executor\n (h = new Promise(async (f, n) => {\n // Create script element (done async to potentially wait for nonce)\n // await (a = m.createElement('script')); // Original Google code had await here, might not be needed\n a = m.createElement(\"script\"); // Create script tag\n e.set(\"libraries\", [...r].join(\",\")); // Add accumulated libraries\n // Add other parameters from the config object 'g'\n for (k in g)\n e.set(\n k.replace(/[A-Z]/g, (t) => \"_\" + t[0].toLowerCase()), // Convert camelCase to snake_case\n g[k]\n );\n e.set(\"callback\", c + \".maps.\" + q); // Set the internal callback function name\n a.src = `https://maps.${c}apis.com/maps/api/js?` + e; // Construct the API URL\n d[q] = f; // Assign the promise resolver to the callback name on google.maps\n // Error handling for script loading failure\n a.onerror = () =>\n (h = n(\n new Error(\n `${p} could not load. Check your API key and network connection.`\n )\n )); // Use onerror for load failures\n // Nonce for Content Security Policy\n a.nonce = m.querySelector(\"script[nonce]\")?.nonce || \"\";\n m.head.append(a); // Append the script to the document head\n }));\n // Define or reuse the importLibrary function on google.maps\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n d[l]\n ? console.warn(p + \" only loads once. Ignoring:\", g) // Warn if called again\n : (d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n))); // The actual importLibrary implementation\n }\n\n // --- UI Creation ---\n _createPACStructure() {\n const section = document.createElement(\"section\");\n section.className = this.#options.classes.section;\n\n // Main container\n this.#container = document.createElement(\"div\");\n this.#container.className = this.#options.classes.container;\n this.#container.setAttribute(\"id\", this.#containerId + \"-div\");\n section.appendChild(this.#container);\n\n // Icon\n const iconContainer = document.createElement(\"div\");\n iconContainer.className = this.#options.classes.icon_container;\n this.#container.appendChild(iconContainer);\n const icon = document.createElement(\"div\");\n icon.innerHTML = this.#options.classes.icon;\n iconContainer.appendChild(icon.firstElementChild); // Append the actual SVG element\n\n // Input field\n this.#inputElement = document.createElement(\"input\");\n this.#inputElement.id = this.#containerId + \"-input\"; // Assign ID for label association\n this.#inputElement.type = \"text\";\n this.#inputElement.name = \"search\"; // Consider making name configurable\n this.#inputElement.placeholder = this.#options.placeholder;\n this.#inputElement.autocomplete = this.#options.autocomplete;\n this.#inputElement.className = this.#options.classes.input;\n this.#inputElement.setAttribute(\"role\", \"combobox\");\n this.#inputElement.setAttribute(\"aria-autocomplete\", \"list\");\n this.#inputElement.setAttribute(\"aria-expanded\", \"false\"); // Will be updated dynamically\n this.#inputElement.setAttribute(\"aria-controls\", \"pacSuggestions\"); // Links to the suggestions list\n this.#inputElement.setAttribute(\"aria-activedescendant\", \"\"); // Will be updated dynamically\n\n if (this.#options.autofocus) {\n this.#inputElement.autofocus = true;\n }\n if (this.#options.label) {\n const label = document.createElement(\"label\");\n label.htmlFor = this.#inputElement.id; // Correctly link label to input by ID\n label.textContent = this.#options.label;\n // Add label classes if needed from opts.classes\n section.prepend(label); // Append label before input or adjust structure\n }\n this.#container.appendChild(this.#inputElement);\n\n // Keyboard hints container\n const kbdContainer = document.createElement(\"div\");\n kbdContainer.className = this.#options.classes.kbd_container;\n this.#kbdEscape = document.createElement(\"kbd\");\n this.#kbdEscape.className = this.#options.classes.kbd_escape;\n this.#kbdEscape.textContent = \"Esc\";\n kbdContainer.appendChild(this.#kbdEscape);\n this.#kbdUp = document.createElement(\"kbd\");\n this.#kbdUp.className = this.#options.classes.kbd_up;\n this.#kbdUp.innerHTML = \"&#8593;\"; // Up arrow HTML entity\n kbdContainer.appendChild(this.#kbdUp);\n this.#kbdDown = document.createElement(\"kbd\");\n this.#kbdDown.className = this.#options.classes.kbd_down;\n this.#kbdDown.innerHTML = \"&#8595;\"; // Down arrow HTML entity\n kbdContainer.appendChild(this.#kbdDown);\n this.#container.appendChild(kbdContainer);\n\n // Suggestions list (initially hidden)\n this.#ul = document.createElement(\"ul\");\n this.#ul.id = \"pacSuggestions\"; // Must match aria-controls\n this.#ul.className = this.#options.classes.ul;\n this.#ul.style.display = \"none\";\n this.#ul.setAttribute(\"role\", \"listbox\");\n this.#ul.setAttribute(\"aria-labelledby\", this.#inputElement.id); // Link listbox to input for accessibility\n this.#container.appendChild(this.#ul);\n\n this.#pacEl.appendChild(section);\n section.addEventListener(\"keydown\", this._onKeyDown.bind(this)); // Bind 'this'\n }\n\n /**\n * Attaches event listeners to the input element for handling user input.\n * This includes debounced input handling, focus/blur events, and keyboard navigation.\n */\n _attachedEventListeners() {\n this.#inputElement.addEventListener(\"input\", this._debouncedMakeAcRequest);\n // Add focus/blur listeners if needed to manage suggestion visibility\n this.#inputElement.addEventListener(\"blur\", () => {\n // Delay hiding suggestions to allow click events on them\n setTimeout(() => {\n if (this.#ul && !this.#ul.contains(document.activeElement)) {\n // Check if focus moved outside suggestions\n this.#ul.style.display = \"none\";\n this.#inputElement.setAttribute(\"aria-expanded\", \"false\");\n }\n }, 200); // Adjust delay as needed\n });\n this.#inputElement.addEventListener(\"focus\", () => {\n // Potentially show suggestions again if input has value\n if (this.#inputElement.value && this.#allSuggestions.length > 0) {\n this.#ul.style.display = \"block\";\n this.#inputElement.setAttribute(\"aria-expanded\", \"true\");\n }\n });\n }\n\n _detachEventListeners() {\n // Remove event listeners, remove elements from DOM\n if (this.#inputElement) {\n this.#inputElement.removeEventListener(\n \"input\",\n this._debouncedMakeAcRequest\n );\n // remove other listeners\n }\n if (this.#pacEl && this.#container) {\n this.#pacEl.removeChild(this.#container.parentElement); // remove the whole section\n }\n }\n\n /**\n * Initializes the core autocomplete functionality after the API is loaded.\n * Imports necessary libraries and sets up the input event listener.\n */\n async _initializeAutocomplete() {\n try {\n // Ensure the 'places' library is available via the dynamic loader\n // eslint-disable-next-line no-undef\n await google.maps.importLibrary(\"places\");\n // console.log('Places library imported successfully.'); // For debugging\n\n // Initial token generation\n this._refreshToken();\n\n // Attach the debounced request function to the input element's 'input' event\n if (this.#inputElement) {\n this._attachedEventListeners();\n } else {\n this.#onErrorCallback(\n new Error(\"Input element not found during initialization.\")\n );\n }\n } catch (error) {\n console.error(\"Error initializing Google Places Autocomplete:\", error);\n // eslint-disable-next-line no-undef\n this.#onErrorCallback(\n new Error(\"Google Maps Places library not available.\")\n );\n }\n }\n\n /**\n * Resets the autocomplete input field, clears suggestions, and optionally refreshes the session token.\n * @param {boolean} [refresh=false] - Whether to refresh the Google Places session token.\n */\n _reset(refresh = false, placeData = null) {\n this.#currentSuggestion = -1;\n\n /**\n * If the input element exists and clear_input is false, set its value to the formatted address\n * from placeData. Otherwise, clear the input value.\n * This allows the user to keep the input value if they selected a place,\n * but still allows clearing it if clear_input is true or placeData is not provided.\n * @type {HTMLInputElement}\n * @property {string} value - The value of the input element.\n * @property {boolean} clear_input - Whether to clear the input value after selection.\n * @property {Object} placeData - The data of the selected place, containing formattedAddress.\n */\n if (\n this.#inputElement &&\n this.#options.clear_input == false &&\n placeData &&\n placeData.formattedAddress\n ) {\n this.#inputElement.value = placeData.formattedAddress; // Set input value to formatted address\n } else if (this.#inputElement) {\n this.#inputElement.value = \"\";\n }\n\n if (this.#inputElement) {\n this.#inputElement.setAttribute(\"aria-expanded\", \"false\");\n this.#inputElement.setAttribute(\"aria-activedescendant\", \"\"); // Clear aria-activedescendant\n this.#inputElement.blur();\n }\n\n this.#allSuggestions = [];\n this.#currentSuggestion = -1;\n if (this.#ul) {\n this.#ul.innerHTML = \"\"; // Clear existing suggestions\n this.#ul.style.display = \"none\";\n }\n if (refresh) {\n this._refreshToken();\n }\n }\n /**\n * Removes the 'current' highlighting classes from all suggestion list items (li) and their links (a).\n */\n _resetLiClasses() {\n if (!this.#ul) return;\n Array.from(this.#ul.children).forEach((li) => {\n this.#options.classes.li_current\n .split(\" \")\n .forEach((cl) => li.classList.remove(cl));\n const link = li.querySelector(\"a\");\n if (link) {\n this.#options.classes.li_a_current\n .split(\" \")\n .forEach((cl) => link.classList.remove(cl));\n }\n });\n }\n\n /**\n * Handles keyboard events (ArrowDown, ArrowUp, Enter, Escape) for navigating\n * and selecting suggestions or closing the list.\n * @param {KeyboardEvent} e - The keyboard event object.\n */\n _onKeyDown(e) {\n this._resetLiClasses(); // Reset classes on any key press within the suggestions\n\n if (e.key === \"Escape\") {\n e.preventDefault();\n // Visual feedback for key press\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdEscape?.classList.add(cl));\n setTimeout(\n () =>\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdEscape?.classList.remove(cl)),\n 300\n );\n\n this._reset(true); // Reset search input and results, refresh token\n }\n\n if (\n !this.#allSuggestions.length ||\n !this.#ul ||\n this.#ul.style.display === \"none\"\n )\n return;\n\n if (e.key === \"ArrowDown\") {\n e.preventDefault(); // Prevent cursor movement in input\n this.#currentSuggestion = Math.min(\n this.#currentSuggestion + 1,\n this.#allSuggestions.length - 1\n );\n if (this.#currentSuggestion < 0) this.#currentSuggestion = 0; // Handle case where it was -1\n\n const currentLi = this.#ul.children.item(this.#currentSuggestion);\n if (currentLi) {\n const currentA = currentLi.querySelector(\"a\");\n this.#options.classes.li_current\n .split(\" \")\n .forEach((cl) => currentLi.classList.add(cl));\n if (currentA) {\n this.#options.classes.li_a_current\n .split(\" \")\n .forEach((cl) => currentA.classList.add(cl));\n }\n currentLi.scrollIntoView({ block: \"nearest\" }); // Ensure visible\n this.#inputElement.setAttribute(\"aria-activedescendant\", currentLi.id); // Update aria-activedescendant\n }\n\n // Visual feedback for key press\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdDown?.classList.add(cl));\n setTimeout(\n () =>\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdDown?.classList.remove(cl)),\n 300\n );\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault(); // Prevent cursor movement in input\n this.#currentSuggestion = Math.max(this.#currentSuggestion - 1, 0); // Stay at 0 if already there\n\n const currentLi = this.#ul.children.item(this.#currentSuggestion);\n if (currentLi) {\n const currentA = currentLi.querySelector(\"a\");\n this.#options.classes.li_current\n .split(\" \")\n .forEach((cl) => currentLi.classList.add(cl));\n if (currentA) {\n this.#options.classes.li_a_current\n .split(\" \")\n .forEach((cl) => currentA.classList.add(cl));\n }\n currentLi.scrollIntoView({ block: \"nearest\" }); // Ensure visible\n }\n\n // Visual feedback for key press\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdUp?.classList.add(cl));\n setTimeout(\n () =>\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdUp?.classList.remove(cl)),\n 300\n );\n } else if (e.key === \"Enter\") {\n e.preventDefault(); // Prevent form submission if applicable\n if (\n this.#currentSuggestion >= 0 &&\n this.#currentSuggestion < this.#allSuggestions.length\n ) {\n this._onPlaceSelected(\n this.#allSuggestions[this.#currentSuggestion].place\n );\n // Reset is handled within onPlaceSelected via reset(true)\n }\n }\n }\n\n /**\n * Creates an array of list item (LI) elements for the suggestions dropdown.\n * Each LI contains a link (A) with the place prediction details and distance.\n * Handles highlighting the matched parts of the suggestion text.\n * @param {Array<google.maps.places.AutocompleteSuggestion>} suggestions - Array of suggestion objects from the API.\n * @returns {Array<HTMLLIElement>} An array of LI elements to be added to the suggestions UL.\n */\n _createSuggestionElements(suggestions) {\n this.#allSuggestions = []; // Reset before populating\n return suggestions.map((suggestion, index) => {\n this.#allSuggestions.push({\n id: index + 1,\n description: suggestion.placePrediction.toString(),\n place: suggestion.placePrediction.toPlace(),\n });\n\n // create div elements\n const divContainer = document.createElement(\"div\");\n divContainer.className = this.#options.classes.li_div_container; // flex min-w-0 gap-x-4\n // create inner div element - place name\n const divInner = document.createElement(\"div\");\n divInner.className = this.#options.classes.li_div_one; // min-w-0 flex-auto\n divContainer.appendChild(divInner);\n // create p element - place name\n const p = document.createElement(\"p\");\n p.className = this.#options.classes.li_div_one_p; // text-sm/6\n\n // get prediction text\n const predictionText = suggestion.placePrediction.text;\n const originalText = predictionText.text;\n // Array of objects with startOffset, endOffset\n const matches = predictionText.matches;\n\n //Highlighting Logic\n let lastIndex = 0;\n\n // Sort matches just in case they aren't ordered (though they usually are)\n matches.sort((a, b) => a.startOffset - b.startOffset);\n\n // 1. Create the outer span\n const outerSpan = document.createElement(\"span\");\n\n // 2. Create the inner span for the bold part\n const innerSpan = document.createElement(\"span\");\n innerSpan.classList = this.#options.classes.highlight ?? \"font-bold\"; // Use the highlight class from options\n\n for (const match of matches) {\n // Append text before the current match\n outerSpan.textContent += originalText.substring(\n lastIndex,\n match.startOffset\n );\n\n // Append the highlighted match segment\n if (match.startOffset > 0) {\n // check previous charter is space\n const prevChar = originalText.charAt(match.startOffset - 1);\n if (prevChar == \" \") {\n innerSpan.textContent += \" \";\n }\n }\n innerSpan.textContent += originalText.substring(\n match.startOffset,\n match.endOffset\n );\n\n // Update the last index processed\n lastIndex = match.endOffset;\n }\n\n // 3. Create a text node for the remaining text\n const remainingText = document.createTextNode(\n originalText.substring(lastIndex)\n );\n\n // 4. Append the inner span and the text node to the outer span\n outerSpan.appendChild(innerSpan);\n outerSpan.appendChild(remainingText);\n\n // 5. Append the outer span to the paragraph element\n p.appendChild(outerSpan);\n\n divInner.appendChild(p);\n divContainer.appendChild(divInner);\n\n // create inner div element - distance\n const divInner2 = document.createElement(\"div\");\n divInner2.className = this.#options.classes.li_div_two; //'shrink-0 flex flex-col items-end min-w-16';\n divContainer.appendChild(divInner2);\n // create p element - distance\n const p2 = document.createElement(\"p\");\n p2.className = this.#options.classes.li_div_two_p; //'mt-1 text-xs/5 ';\n p2.textContent = this._formatDistance(\n suggestion.placePrediction.distanceMeters,\n this.#options.distance_units ?? \"km\"\n );\n divInner2.appendChild(p2);\n\n // // create a link element\n const a = document.createElement(\"a\");\n a.href = \"javascript:void(0)\";\n a.tabIndex = index + 1;\n a.className = this.#options.classes.li_a; // block w-full flex justify-between\n\n a.addEventListener(\"click\", () => {\n this._onPlaceSelected(suggestion.placePrediction.toPlace());\n });\n\n // ...\n // a.addEventListener(\"click\", () => {\n // this._fetchPlaceDetails(prediction.place_id);\n // });\n a.appendChild(divContainer);\n a.appendChild(divInner2);\n\n const li = document.createElement(\"li\");\n li.id = `option-${index + 1}`;\n li.className = this.#options.classes.li;\n\n li.appendChild(a);\n return li;\n });\n }\n\n /**\n * Handles the selection of a place. Fetches required fields\n * (displayName, formattedAddress, addressComponents) and calls the\n * user-defined `onPacData` callback.\n * @param {google.maps.places.Place} place - The selected Place object.\n */\n async _onPlaceSelected(place) {\n let data = null;\n try {\n // Fetch necessary details for the selected place\n await place.fetchFields({\n fields: this.#fetchFields, //[\"displayName\", \"formattedAddress\", \"addressComponents\"], // Add more fields as needed\n });\n // Call the user-provided callback with the place data\n // eslint-disable-next-line no-undef\n data = place.toJSON(); // Convert to plain JSON object\n this.#onDataCallback(data); // Convert to plain JSON object for the callback\n } catch (error) {\n console.error(\"Error fetching place details:\", error);\n // eslint-disable-next-line no-undef\n this.#onErrorCallback(error);\n } finally {\n // Reset the input and suggestions regardless of success/error\n this._reset(true, data); // Refresh token after selection\n }\n }\n\n /**\n * Creates a new Google Places Autocomplete Session Token.\n * This should be called before starting a new series of autocomplete requests.\n */\n _refreshToken() {\n try {\n // eslint-disable-next-line no-undef\n this.#request.sessionToken =\n new google.maps.places.AutocompleteSessionToken();\n } catch (error) {\n console.error(\"Error creating session token:\", error);\n // eslint-disable-next-line no-undef\n this.#onErrorCallback(error);\n }\n }\n\n /**\n * Sets the fields to be fetched for the selected place.\n * This allows you to specify which details you want to retrieve\n * when a place is selected, such as displayName, formattedAddress,\n * addressComponents, etc.\n * @param {Array<string>} fields - Array of field names to fetch.\n */\n setFetchFields(fields) {\n this._setFetchFields(fields);\n }\n /**\n * Gets the current fields that will be fetched for the selected place.\n * This is useful for understanding what details will be available\n * when a place is selected, such as displayName, formattedAddress,\n * addressComponents, etc.\n * @returns {Array<string>} The current fetch fields.\n */\n getFetchFields() {\n return this.#fetchFields;\n }\n\n /**\n * Sets the request parameters for the Places Autocomplete instance.\n * This method allows you to update the request parameters dynamically,\n * such as the input value, region codes, language, etc.\n * It merges the provided parameters with the default request parameters,\n * allowing you to override specific values while keeping the defaults intact.\n * This is useful for updating the search criteria without needing to recreate the instance.\n * @param {*} params\n */\n setRequestParams(params) {\n if (\n typeof params === \"object\" &&\n !Array.isArray(params) &&\n params !== null\n ) {\n // if params.input is provided, set it to the input element\n if (params.input && typeof params.input === \"string\") {\n this.#inputElement.value = params.input; // Set input value if provided\n }\n // Merge provided params with default request parameters\n // This allows overriding specific request parameters while keeping defaults\n this.#request = {\n ...this.#defaultRequestParams,\n ...params,\n };\n }\n }\n\n /**\n * Returns the current request parameters used by the Places Autocomplete instance.\n * This includes the input value, included region codes, language, and other settings.\n * It is useful for debugging or when you need to know the current search criteria.\n * @returns {Object} The current request parameters.\n */\n getRequestParams() {\n return this.#request;\n }\n\n /**\n * Sets the options for the Places Autocomplete instance.\n * This method allows you to change the appearance and behavior of the autocomplete widget,\n * such as classes, placeholder text, debounce time, etc.\n * It merges the provided options with the default options, allowing you to override specific values\n * while keeping the defaults intact.\n * This is useful for updating the widget's configuration without needing to recreate the instance.\n * @param {*} options\n */\n setOptions(options) {\n if (\n typeof options === \"object\" &&\n !Array.isArray(options) &&\n options !== null\n ) {\n this._detachEventListeners(); // Detach event listeners\n\n // // Ensure classes are deeply merged if user provides partial classes\n const tmpClasses = options.classes || {};\n delete options.classes; // Remove classes from options to avoid overwriting\n\n // Merge provided options with default options\n // This allows overriding specific options while keeping defaults\n this.#options = {\n ...this.#defaultOptions,\n ...options,\n };\n\n // Merge classes with defaults\n // This allows overriding specific classes while keeping defaults\n if (\n tmpClasses &&\n typeof tmpClasses === \"object\" &&\n Object.keys(tmpClasses).length > 0\n ) {\n this.#options.classes = {\n ...this.#defaultClasses,\n ...tmpClasses,\n };\n } else {\n this.#options.classes = { ...this.#defaultClasses }; // Use defaults if no classes provided\n }\n\n this._initialiseDebouncedRequest(); // Reinitialize the debounced request function\n this._createPACStructure(); // Recreate the structure with new options\n // Reattach the input event listener to the input element\n // This is necessary to ensure the new input element is ready for events\n if (this.#inputElement) {\n this._attachedEventListeners();\n } // Reinitialize the autocomplete functionality\n }\n }\n\n /**\n * Gets the current options used by the Places Autocomplete instance.\n * @returns {Object} The current options.\n */\n getOptions() {\n /**\n * Returns the current options used by the Places Autocomplete instance.\n * This includes classes, placeholder text, debounce time, and other settings.\n * It is useful for debugging or when you need to know the current configuration of the widget.\n * @returns {Object} The current options.\n */\n return this.#options;\n }\n\n /**\n * Clears the autocomplete input field and suggestions list.\n * This method resets the state of the autocomplete widget,\n * allowing the user to start a new search without any previous input or suggestions.\n * It also refreshes the Google Places session token to ensure a new session.\n * @returns {void}\n */\n clear() {\n this._reset(true);\n }\n\n /**\n * Destroys the PacAutocomplete instance.\n * Removes event listeners, clears the DOM, and nullifies properties.\n * This method should be called when the autocomplete widget is no longer needed.\n * It ensures that all resources are cleaned up to prevent memory leaks.\n * @returns {void}\n */\n destroy() {\n // Remove event listeners, remove elements from DOM\n this._detachEventListeners(); // Detach event listeners\n // Nullify properties\n this.#containerId = null;\n this.#pacEl = null;\n this.#googleMapsApiKey = null;\n this.#googleMapsApiVersion = null;\n this.#options = null;\n this.#request = null;\n this.#inputElement = null;\n this.#container = null;\n this.#ul = null;\n this.#kbdEscape = null;\n this.#kbdUp = null;\n this.#kbdDown = null;\n this.#allSuggestions = null;\n this.#currentSuggestion = -1;\n this.#onDataCallback = null;\n this.#onErrorCallback = null;\n this._debouncedMakeAcRequest = null;\n console.log(\"PacAutocomplete instance destroyed.\");\n }\n}\n"],"names":["PlacesAutocomplete","#containerId","#pacEl","#googleMapsApiKey","#googleMapsApiVersion","#options","#request","#inputElement","#container","#ul","#kbdEscape","#kbdUp","#kbdDown","#allSuggestions","#currentSuggestion","#onDataCallback","#onErrorCallback","#defaultOptions","#defaultClasses","#defaultRequestParams","#fetchFields","#defaultFetchFields","config","place","error","suggestions","fields","e","func","wait","timeout","args","later","distance","units","value","unitLabel","g","h","a","k","p","c","l","q","b","d","r","u","f","n","t","section","iconContainer","icon","label","kbdContainer","refresh","placeData","li","cl","link","currentLi","currentA","suggestion","index","divContainer","divInner","predictionText","originalText","matches","lastIndex","outerSpan","innerSpan","match","remainingText","divInner2","p2","data","params","options","tmpClasses"],"mappings":"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"}
1
+ {"version":3,"file":"places-autocomplete.js","sources":["../PlacesAutocomplete.js"],"sourcesContent":["/**\n * Initialises a Places Autocomplete widget.\n * This script dynamically loads the Google Maps JavaScript API, creates the UI elements\n * for the autocomplete input and suggestions list, handles user input with debouncing,\n * fetches suggestions, manages keyboard navigation, and calls user-defined callbacks\n * on place selection or error.\n *\n * @author Alexander Pechkarev <alexpechkarev@gmail.com>\n * @license MIT\n *\n */\n\n/**\n * PacAutocomplete class\n * This class provides a Places Autocomplete widget.\n */\nexport class PlacesAutocomplete {\n // --- Private Properties (using # or _ prefix by convention) ---\n #containerId; // Container ID where the autocomplete widget will be rendered.\n #pacEl;\n #googleMapsApiKey;\n #googleMapsApiVersion;\n #options;\n #request;\n #inputElement;\n #container;\n #ul;\n #kbdEscape;\n #kbdUp;\n #kbdDown;\n #allSuggestions = [];\n #currentSuggestion = -1;\n #onDataCallback; // For user-provided data callback\n #onErrorCallback; // For user-provided error callback\n _debouncedMakeAcRequest; // Declare without initializing here\n #defaultOptions = {\n // Default options for the autocomplete widget.\n autofocus: false, // Automatically focus the input on load.\n autocomplete: \"off\", // HTML autocomplete attribute for the input.\n placeholder: \"Start typing your address ...\", // Placeholder text for the input.\n distance: true, // Show distance in suggestions (requires origin in request).\n distance_units: \"km\", // Units for distance ('km' or 'miles').\n label: \"\", // Optional label text above the input.\n debounce: 100, // Debounce delay (ms) for API requests.\n clear_input: true, // Clear input button (not implemented in this version).\n debug: false, // Enable debug mode (not implemented in this version).\n };\n #defaultClasses = {\n // CSS classes for various parts of the widget.\n section: \"\", // Outer section container.\n container: \"relative z-10 transform rounded-xl mt-4\", // Main container div.\n icon_container:\n \"pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3\", // Container for the search icon.\n icon: '<svg xmlns=\"http://www.w3.org/2000/svg\" class=\"w-5 h-5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"11\" cy=\"11\" r=\"8\" /><path d=\"m21 21-4.3-4.3\" /></svg>', // SVG for the search icon.\n input:\n \"border-1 w-full rounded-md border-0 shadow-sm bg-gray-100 px-4 py-2.5 pl-10 pr-20 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 sm:text-sm\", // Input field.\n kbd_container: \"absolute inset-y-0 right-0 flex py-1.5 pr-1.5\", // Container for keyboard hints.\n kbd_escape:\n \"inline-flex items-center rounded border border-gray-300 px-1 font-sans text-xs text-gray-500 w-8 mr-1\", // Escape key hint.\n kbd_up:\n \"inline-flex items-center justify-center rounded border border-gray-300 px-1 font-sans text-xs text-gray-500 w-6\", // Up arrow key hint.\n kbd_down:\n \"inline-flex items-center rounded border border-gray-400 px-1 font-sans text-xs text-gray-500 justify-center w-6\", // Down arrow key hint.\n kbd_active: \"bg-indigo-500 text-white\", // Class for active keyboard hint.\n ul: \"absolute z-50 -mb-2 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm divide-y divide-gray-100\", // Suggestions list (ul).\n li: \"z-50 cursor-default select-none py-2 px-2 lg:px-4 text-gray-900 hover:bg-indigo-500 hover:text-white\", // Suggestion item (li).\n li_current: \"bg-indigo-500\", // Class for the currently selected suggestion item.\n li_a: \"block w-full flex justify-between\", // Link element within a suggestion item.\n li_a_current: \"text-white\", // Class for the link in the currently selected suggestion item.\n li_div_container: \"flex min-w-0 gap-x-4\", // Container div within the suggestion link.\n li_div_one: \"min-w-0 flex-auto\", // First inner div (for place name).\n li_div_one_p: \"text-sm/6\", // Paragraph for the place name.\n li_div_two: \"shrink-0 flex flex-col items-end min-w-16\", // Second inner div (for distance).\n li_div_two_p: \"mt-1 text-xs/5\", // Paragraph for the distance.\n highlight: \"font-bold\", // Class for highlighting matched text in suggestions.\n };\n #defaultRequestParams = {\n // Default parameters for the autocomplete request.\n input: \"\", // Initial input value (empty).\n includedRegionCodes: [\"GB\"], // Default region codes to include in suggestions.\n language: \"en-gb\",\n region: \"GB\",\n };\n #fetchFields = [\"formattedAddress\", \"addressComponents\"];\n #defaultFetchFields = [\"formattedAddress\", \"addressComponents\"]; // Fields to fetch for the selected place (can be extended).\n\n /**\n * Class constructor for PacAutocomplete.\n * Initializes the autocomplete widget with the provided configuration.\n * @param {Object} config - Configuration object for the autocomplete widget.\n * @param {string} config.containerId - ID of the container element for the widget.\n * @param {string} config.googleMapsApiKey - Google Maps API key.\n * @param {string} [config.googleMapsApiVersion] - Version of the Google Maps API to use (default: \"weekly\").\n * @param {Object} [config.options] - Additional options for the widget (e.g., classes, callbacks).\n * @param {Object} [config.requestParams] - Parameters for the autocomplete request (e.g., input, region).\n * @param {*} config\n */\n constructor(config) {\n if (!config || !config.containerId || !config.googleMapsApiKey) {\n throw new Error(\n \"PacAutocomplete: Missing required configuration (containerId, googleMapsApiKey).\"\n );\n }\n\n this.#containerId = config.containerId; // Store the configuration object\n this.#pacEl = document.getElementById(config.containerId);\n if (!this.#pacEl) {\n throw new Error(\n `PacAutocomplete: Container element with ID \"${config.containerId}\" not found.`\n );\n }\n\n this.#googleMapsApiKey = config.googleMapsApiKey;\n this.#googleMapsApiVersion = config.googleMapsApiVersion || \"weekly\";\n\n // Merge user options with defaults\n this.#options = {\n ...this.#defaultOptions, // Default options\n ...config.options, // User-defined options override defaults\n };\n // Ensure classes are deeply merged if user provides partial classes\n if (config.options && config.options.classes) {\n this.#options.classes = {\n ...this.#defaultClasses,\n ...config.options.classes,\n };\n } else {\n this.#options.classes = this.#defaultClasses; // Use default classes if none provided\n }\n\n if (this.#options.debug) {\n console.log(\"___debug constructor options:\");\n console.log(this.#options);\n }\n\n if (config.fetchFields && Array.isArray(config.fetchFields)) {\n this._setFetchFields(config.fetchFields); // Set fetch fields from user config\n }\n\n // Set default response and error callbacks if not provided\n this.#onDataCallback =\n config.onResponse ||\n ((place) => {\n console.info(\"---------Default onResponse not provided---------\");\n console.info(\"Selected Place:\", JSON.stringify(place, null, 2));\n });\n this.#onErrorCallback =\n config.onError ||\n ((error) => {\n console.error(\"---------Default onError not provided---------\");\n console.error(\"PAC Error:\", error);\n });\n\n if (config.requestParams && Object.keys(config.requestParams).length > 0) {\n this.#request = {\n ...this.#defaultRequestParams,\n ...config.requestParams,\n };\n } else {\n this.#request = { ...this.#defaultRequestParams }; // Use defaults if no requestParams provided\n }\n\n if (this.#options.debug) {\n console.log(\"___debug constructor requestParams:\", this.#request);\n }\n\n this._initialiseDebouncedRequest(); // Initialize the debounced request function\n\n this._init(); // Underscore prefix for internal initialization method\n }\n\n // --- Private Initialization Method ---\n async _init() {\n try {\n // check if google maps api is already loaded\n if (typeof google === \"undefined\" || !google.maps) {\n // Load the Google Maps API dynamically\n await this._loadGoogleMapsApi({\n key: this.#googleMapsApiKey,\n v: this.#googleMapsApiVersion,\n });\n }\n this._createPACStructure();\n await this._initializeAutocomplete();\n } catch (error) {\n this.#onErrorCallback(error);\n }\n }\n\n /**\n * Initializes the debounced request function for fetching autocomplete suggestions.\n *\n * Debounced function to fetch autocomplete suggestions from the Google Places API.\n * Triggered by the 'input' event on the input element.\n *\n *\n */\n _initialiseDebouncedRequest() {\n this._debouncedMakeAcRequest = this._debounce(async () => {\n if (!this.#inputElement || !this.#inputElement.value) {\n this._reset();\n if (this.#inputElement)\n this.#inputElement.setAttribute(\"aria-expanded\", \"false\");\n return;\n }\n\n this.#request.input = this.#inputElement.value;\n\n try {\n const { suggestions } =\n // eslint-disable-next-line no-undef\n await google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions(\n this.#request\n );\n\n // Display suggestions\n if (suggestions && suggestions.length > 0) {\n this.#ul.replaceChildren(\n ...this._createSuggestionElements(suggestions)\n );\n this.#ul.style.display = \"block\";\n this.#inputElement.setAttribute(\"aria-expanded\", \"true\");\n } else {\n // No suggestions found\n this._reset(); // Clear any old suggestions\n this.#inputElement.setAttribute(\"aria-expanded\", \"false\");\n // Optionally display a \"no results\" message in the 'ul'\n }\n } catch (error) {\n this.#onErrorCallback(error);\n this._reset();\n }\n }, this.#options.debounce); // Default debounce to 100ms if not set\n }\n /**\n * Sets the fields to fetch for the selected place.\n * @param {Array<string>} fields - The fields to fetch.\n */\n _setFetchFields(fields) {\n if (Array.isArray(fields) && fields.length > 0) {\n this.#fetchFields = [\n ...new Set([...this.#defaultFetchFields, ...fields]),\n ].filter((e) => e); // Ensure unique and non-empty fields\n }\n }\n\n /**\n * Creates a debounced version of a function.\n * The debounced function delays invoking `func` until after `wait` milliseconds have\n * elapsed since the last time the debounced function was invoked.\n * @param {Function} func - The function to debounce.\n * @param {number} wait - The number of milliseconds to delay.\n * @returns {Function} The new debounced function.\n */\n _debounce(func, wait) {\n if (this.#options.debug) {\n console.log(\"___debug debounce function called with wait:\", wait);\n }\n\n let timeout = null;\n return function executedFunction(...args) {\n const later = () => {\n timeout = null;\n func(...args); // Call original function\n };\n if (timeout !== null) {\n clearTimeout(timeout); // Clear the previous timeout\n }\n timeout = setTimeout(later, wait ?? 100); // Set the new timeout\n };\n }\n /**\n * Formats a distance in meters into kilometers or miles.\n * @param {number | null | undefined} distance - Distance in meters.\n * @param {'km' | 'miles'} units - The desired output units.\n * @returns {string | null} Formatted distance string (e.g., \"1.23 km\") or null if input is invalid.\n */\n _formatDistance(distance, units) {\n if (typeof distance !== \"number\" || !this.#options.distance) {\n return null; // Return null if distance isn't shown or invalid\n }\n let value;\n let unitLabel;\n if (units === \"km\") {\n value = (distance / 1000).toFixed(2);\n unitLabel = \"km\";\n } else {\n // Default to miles if not 'km'\n value = (distance / 1609.34).toFixed(2);\n unitLabel = \"miles\";\n }\n // Avoid showing \".00\"\n value = value.replace(/\\.00$/, \"\");\n return `${value} ${unitLabel}`;\n }\n\n /**\n * Dynamically loads the Google Maps JavaScript API using the importLibrary method.\n * This is the standard approach recommended by Google.\n * @see https://developers.google.com/maps/documentation/javascript/load-maps-js-api\n * @param {object} g - Configuration object for the API loader (key, v, libraries, etc.).\n */\n async _loadGoogleMapsApi(g) {\n var h, // Promise tracking API load\n a, // Script element\n k, // Loop variable for config keys\n p = \"The Google Maps JavaScript API\", // Error message prefix\n c = \"google\", // Global namespace\n l = \"importLibrary\", // Loader function name\n q = \"__ib__\", // Internal callback name\n m = document, // Document reference\n b = window; // Window reference\n b = b[c] || (b[c] = {}); // Ensure google namespace exists\n var d = b.maps || (b.maps = {}), // Ensure google.maps namespace exists\n r = new Set(), // Set to track requested libraries\n e = new URLSearchParams(), // URL parameters for the API script\n u = () =>\n // Function to initiate API loading (if not already started)\n h ||\n // eslint-disable-next-line no-async-promise-executor\n (h = new Promise(async (f, n) => {\n // Create script element (done async to potentially wait for nonce)\n // await (a = m.createElement('script')); // Original Google code had await here, might not be needed\n a = m.createElement(\"script\"); // Create script tag\n e.set(\"libraries\", [...r].join(\",\")); // Add accumulated libraries\n // Add other parameters from the config object 'g'\n for (k in g)\n e.set(\n k.replace(/[A-Z]/g, (t) => \"_\" + t[0].toLowerCase()), // Convert camelCase to snake_case\n g[k]\n );\n e.set(\"callback\", c + \".maps.\" + q); // Set the internal callback function name\n a.src = `https://maps.${c}apis.com/maps/api/js?` + e; // Construct the API URL\n d[q] = f; // Assign the promise resolver to the callback name on google.maps\n // Error handling for script loading failure\n a.onerror = () =>\n (h = n(\n new Error(\n `${p} could not load. Check your API key and network connection.`\n )\n )); // Use onerror for load failures\n // Nonce for Content Security Policy\n a.nonce = m.querySelector(\"script[nonce]\")?.nonce || \"\";\n m.head.append(a); // Append the script to the document head\n }));\n // Define or reuse the importLibrary function on google.maps\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n d[l]\n ? console.warn(p + \" only loads once. Ignoring:\", g) // Warn if called again\n : (d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n))); // The actual importLibrary implementation\n }\n\n // --- UI Creation ---\n _createPACStructure() {\n const section = document.createElement(\"section\");\n section.className = this.#options.classes.section;\n\n // Main container\n this.#container = document.createElement(\"div\");\n this.#container.className = this.#options.classes.container;\n this.#container.setAttribute(\"id\", this.#containerId + \"-div\");\n section.appendChild(this.#container);\n\n // Icon\n const iconContainer = document.createElement(\"div\");\n iconContainer.className = this.#options.classes.icon_container;\n this.#container.appendChild(iconContainer);\n const icon = document.createElement(\"div\");\n icon.innerHTML = this.#options.classes.icon;\n iconContainer.appendChild(icon.firstElementChild); // Append the actual SVG element\n\n // Input field\n this.#inputElement = document.createElement(\"input\");\n this.#inputElement.id = this.#containerId + \"-input\"; // Assign ID for label association\n this.#inputElement.type = \"text\";\n this.#inputElement.name = \"search\"; // Consider making name configurable\n this.#inputElement.placeholder = this.#options.placeholder;\n this.#inputElement.autocomplete = this.#options.autocomplete;\n this.#inputElement.className = this.#options.classes.input;\n this.#inputElement.setAttribute(\"role\", \"combobox\");\n this.#inputElement.setAttribute(\"aria-autocomplete\", \"list\");\n this.#inputElement.setAttribute(\"aria-expanded\", \"false\"); // Will be updated dynamically\n this.#inputElement.setAttribute(\"aria-controls\", \"pacSuggestions\"); // Links to the suggestions list\n this.#inputElement.setAttribute(\"aria-activedescendant\", \"\"); // Will be updated dynamically\n\n if (this.#options.autofocus) {\n this.#inputElement.autofocus = true;\n }\n if (this.#options.label) {\n const label = document.createElement(\"label\");\n label.htmlFor = this.#inputElement.id; // Correctly link label to input by ID\n label.textContent = this.#options.label;\n // Add label classes if needed from opts.classes\n section.prepend(label); // Append label before input or adjust structure\n }\n this.#container.appendChild(this.#inputElement);\n\n // Keyboard hints container\n const kbdContainer = document.createElement(\"div\");\n kbdContainer.className = this.#options.classes.kbd_container;\n this.#kbdEscape = document.createElement(\"kbd\");\n this.#kbdEscape.className = this.#options.classes.kbd_escape;\n this.#kbdEscape.textContent = \"Esc\";\n kbdContainer.appendChild(this.#kbdEscape);\n this.#kbdUp = document.createElement(\"kbd\");\n this.#kbdUp.className = this.#options.classes.kbd_up;\n this.#kbdUp.innerHTML = \"&#8593;\"; // Up arrow HTML entity\n kbdContainer.appendChild(this.#kbdUp);\n this.#kbdDown = document.createElement(\"kbd\");\n this.#kbdDown.className = this.#options.classes.kbd_down;\n this.#kbdDown.innerHTML = \"&#8595;\"; // Down arrow HTML entity\n kbdContainer.appendChild(this.#kbdDown);\n this.#container.appendChild(kbdContainer);\n\n // Suggestions list (initially hidden)\n this.#ul = document.createElement(\"ul\");\n this.#ul.id = \"pacSuggestions\"; // Must match aria-controls\n this.#ul.className = this.#options.classes.ul;\n this.#ul.style.display = \"none\";\n this.#ul.setAttribute(\"role\", \"listbox\");\n this.#ul.setAttribute(\"aria-labelledby\", this.#inputElement.id); // Link listbox to input for accessibility\n this.#container.appendChild(this.#ul);\n\n this.#pacEl.appendChild(section);\n section.addEventListener(\"keydown\", this._onKeyDown.bind(this)); // Bind 'this'\n }\n\n /**\n * Attaches event listeners to the input element for handling user input.\n * This includes debounced input handling, focus/blur events, and keyboard navigation.\n */\n _attachedEventListeners() {\n this.#inputElement.addEventListener(\"input\", this._debouncedMakeAcRequest);\n // Add focus/blur listeners if needed to manage suggestion visibility\n this.#inputElement.addEventListener(\"blur\", () => {\n // Delay hiding suggestions to allow click events on them\n setTimeout(() => {\n if (this.#ul && !this.#ul.contains(document.activeElement)) {\n // Check if focus moved outside suggestions\n this.#ul.style.display = \"none\";\n this.#inputElement.setAttribute(\"aria-expanded\", \"false\");\n }\n }, 200); // Adjust delay as needed\n });\n this.#inputElement.addEventListener(\"focus\", () => {\n // Potentially show suggestions again if input has value\n if (this.#inputElement.value && this.#allSuggestions.length > 0) {\n this.#ul.style.display = \"block\";\n this.#inputElement.setAttribute(\"aria-expanded\", \"true\");\n }\n });\n }\n\n _detachEventListeners() {\n // Remove event listeners, remove elements from DOM\n if (this.#inputElement) {\n this.#inputElement.removeEventListener(\n \"input\",\n this._debouncedMakeAcRequest\n );\n // remove other listeners\n }\n if (this.#pacEl && this.#container) {\n this.#pacEl.removeChild(this.#container.parentElement); // remove the whole section\n }\n }\n\n /**\n * Initializes the core autocomplete functionality after the API is loaded.\n * Imports necessary libraries and sets up the input event listener.\n */\n async _initializeAutocomplete() {\n try {\n // Ensure the 'places' library is available via the dynamic loader\n // eslint-disable-next-line no-undef\n await google.maps.importLibrary(\"places\");\n // console.log('Places library imported successfully.'); // For debugging\n\n // Initial token generation\n this._refreshToken();\n\n // Attach the debounced request function to the input element's 'input' event\n if (this.#inputElement) {\n this._attachedEventListeners();\n } else {\n this.#onErrorCallback(\n new Error(\"Input element not found during initialization.\")\n );\n }\n } catch (error) {\n console.error(\"Error initializing Google Places Autocomplete:\", error);\n // eslint-disable-next-line no-undef\n this.#onErrorCallback(\n new Error(\"Google Maps Places library not available.\")\n );\n }\n }\n\n /**\n * Resets the autocomplete input field, clears suggestions, and optionally refreshes the session token.\n * @param {boolean} [refresh=false] - Whether to refresh the Google Places session token.\n */\n _reset(refresh = false, placeData = null) {\n this.#currentSuggestion = -1;\n\n /**\n * If the input element exists and clear_input is false, set its value to the formatted address\n * from placeData. Otherwise, clear the input value.\n * This allows the user to keep the input value if they selected a place,\n * but still allows clearing it if clear_input is true or placeData is not provided.\n * @type {HTMLInputElement}\n * @property {string} value - The value of the input element.\n * @property {boolean} clear_input - Whether to clear the input value after selection.\n * @property {Object} placeData - The data of the selected place, containing formattedAddress.\n */\n if (\n this.#inputElement &&\n this.#options.clear_input == false &&\n placeData &&\n placeData.formattedAddress\n ) {\n this.#inputElement.value = placeData.formattedAddress; // Set input value to formatted address\n } else if (this.#inputElement) {\n this.#inputElement.value = \"\";\n }\n\n if (this.#inputElement) {\n this.#inputElement.setAttribute(\"aria-expanded\", \"false\");\n this.#inputElement.setAttribute(\"aria-activedescendant\", \"\"); // Clear aria-activedescendant\n this.#inputElement.blur();\n }\n\n this.#allSuggestions = [];\n this.#currentSuggestion = -1;\n if (this.#ul) {\n this.#ul.innerHTML = \"\"; // Clear existing suggestions\n this.#ul.style.display = \"none\";\n }\n if (refresh) {\n this._refreshToken();\n }\n }\n /**\n * Removes the 'current' highlighting classes from all suggestion list items (li) and their links (a).\n */\n _resetLiClasses() {\n if (!this.#ul) return;\n Array.from(this.#ul.children).forEach((li) => {\n this.#options.classes.li_current\n .split(\" \")\n .forEach((cl) => li.classList.remove(cl));\n const link = li.querySelector(\"a\");\n if (link) {\n this.#options.classes.li_a_current\n .split(\" \")\n .forEach((cl) => link.classList.remove(cl));\n }\n });\n }\n\n /**\n * Handles keyboard events (ArrowDown, ArrowUp, Enter, Escape) for navigating\n * and selecting suggestions or closing the list.\n * @param {KeyboardEvent} e - The keyboard event object.\n */\n _onKeyDown(e) {\n this._resetLiClasses(); // Reset classes on any key press within the suggestions\n\n if (e.key === \"Escape\") {\n e.preventDefault();\n // Visual feedback for key press\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdEscape?.classList.add(cl));\n setTimeout(\n () =>\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdEscape?.classList.remove(cl)),\n 300\n );\n\n this._reset(true); // Reset search input and results, refresh token\n }\n\n if (\n !this.#allSuggestions.length ||\n !this.#ul ||\n this.#ul.style.display === \"none\"\n )\n return;\n\n if (e.key === \"ArrowDown\") {\n e.preventDefault(); // Prevent cursor movement in input\n this.#currentSuggestion = Math.min(\n this.#currentSuggestion + 1,\n this.#allSuggestions.length - 1\n );\n if (this.#currentSuggestion < 0) this.#currentSuggestion = 0; // Handle case where it was -1\n\n const currentLi = this.#ul.children.item(this.#currentSuggestion);\n if (currentLi) {\n const currentA = currentLi.querySelector(\"a\");\n this.#options.classes.li_current\n .split(\" \")\n .forEach((cl) => currentLi.classList.add(cl));\n if (currentA) {\n this.#options.classes.li_a_current\n .split(\" \")\n .forEach((cl) => currentA.classList.add(cl));\n }\n currentLi.scrollIntoView({ block: \"nearest\" }); // Ensure visible\n this.#inputElement.setAttribute(\"aria-activedescendant\", currentLi.id); // Update aria-activedescendant\n }\n\n // Visual feedback for key press\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdDown?.classList.add(cl));\n setTimeout(\n () =>\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdDown?.classList.remove(cl)),\n 300\n );\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault(); // Prevent cursor movement in input\n this.#currentSuggestion = Math.max(this.#currentSuggestion - 1, 0); // Stay at 0 if already there\n\n const currentLi = this.#ul.children.item(this.#currentSuggestion);\n if (currentLi) {\n const currentA = currentLi.querySelector(\"a\");\n this.#options.classes.li_current\n .split(\" \")\n .forEach((cl) => currentLi.classList.add(cl));\n if (currentA) {\n this.#options.classes.li_a_current\n .split(\" \")\n .forEach((cl) => currentA.classList.add(cl));\n }\n currentLi.scrollIntoView({ block: \"nearest\" }); // Ensure visible\n }\n\n // Visual feedback for key press\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdUp?.classList.add(cl));\n setTimeout(\n () =>\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdUp?.classList.remove(cl)),\n 300\n );\n } else if (e.key === \"Enter\") {\n e.preventDefault(); // Prevent form submission if applicable\n if (\n this.#currentSuggestion >= 0 &&\n this.#currentSuggestion < this.#allSuggestions.length\n ) {\n this._onPlaceSelected(\n this.#allSuggestions[this.#currentSuggestion].place\n );\n // Reset is handled within onPlaceSelected via reset(true)\n }\n }\n }\n\n /**\n * Creates an array of list item (LI) elements for the suggestions dropdown.\n * Each LI contains a link (A) with the place prediction details and distance.\n * Handles highlighting the matched parts of the suggestion text.\n * @param {Array<google.maps.places.AutocompleteSuggestion>} suggestions - Array of suggestion objects from the API.\n * @returns {Array<HTMLLIElement>} An array of LI elements to be added to the suggestions UL.\n */\n _createSuggestionElements(suggestions) {\n this.#allSuggestions = []; // Reset before populating\n return suggestions.map((suggestion, index) => {\n this.#allSuggestions.push({\n id: index + 1,\n description: suggestion.placePrediction.toString(),\n place: suggestion.placePrediction.toPlace(),\n });\n\n // create div elements\n const divContainer = document.createElement(\"div\");\n divContainer.className = this.#options.classes.li_div_container; // flex min-w-0 gap-x-4\n // create inner div element - place name\n const divInner = document.createElement(\"div\");\n divInner.className = this.#options.classes.li_div_one; // min-w-0 flex-auto\n divContainer.appendChild(divInner);\n // create p element - place name\n const p = document.createElement(\"p\");\n p.className = this.#options.classes.li_div_one_p; // text-sm/6\n\n // get prediction text\n const predictionText = suggestion.placePrediction.text;\n const originalText = predictionText.text;\n // Array of objects with startOffset, endOffset\n const matches = predictionText.matches;\n\n //Highlighting Logic\n let lastIndex = 0;\n\n // Sort matches just in case they aren't ordered (though they usually are)\n matches.sort((a, b) => a.startOffset - b.startOffset);\n\n // 1. Create the outer span\n const outerSpan = document.createElement(\"span\");\n\n // 2. Create the inner span for the bold part\n const innerSpan = document.createElement(\"span\");\n innerSpan.classList = this.#options.classes.highlight ?? \"font-bold\"; // Use the highlight class from options\n\n for (const match of matches) {\n // Append text before the current match\n outerSpan.textContent += originalText.substring(\n lastIndex,\n match.startOffset\n );\n\n // Append the highlighted match segment\n if (match.startOffset > 0) {\n // check previous charter is space\n const prevChar = originalText.charAt(match.startOffset - 1);\n if (prevChar == \" \") {\n innerSpan.textContent += \" \";\n }\n }\n innerSpan.textContent += originalText.substring(\n match.startOffset,\n match.endOffset\n );\n\n // Update the last index processed\n lastIndex = match.endOffset;\n }\n\n // 3. Create a text node for the remaining text\n const remainingText = document.createTextNode(\n originalText.substring(lastIndex)\n );\n\n // 4. Append the inner span and the text node to the outer span\n outerSpan.appendChild(innerSpan);\n outerSpan.appendChild(remainingText);\n\n // 5. Append the outer span to the paragraph element\n p.appendChild(outerSpan);\n\n divInner.appendChild(p);\n divContainer.appendChild(divInner);\n\n // create inner div element - distance\n const divInner2 = document.createElement(\"div\");\n divInner2.className = this.#options.classes.li_div_two; //'shrink-0 flex flex-col items-end min-w-16';\n divContainer.appendChild(divInner2);\n // create p element - distance\n const p2 = document.createElement(\"p\");\n p2.className = this.#options.classes.li_div_two_p; //'mt-1 text-xs/5 ';\n p2.textContent = this._formatDistance(\n suggestion.placePrediction.distanceMeters,\n this.#options.distance_units ?? \"km\"\n );\n divInner2.appendChild(p2);\n\n // // create a link element\n const a = document.createElement(\"a\");\n a.href = \"javascript:void(0)\";\n a.tabIndex = index + 1;\n a.className = this.#options.classes.li_a; // block w-full flex justify-between\n\n a.addEventListener(\"click\", () => {\n this._onPlaceSelected(suggestion.placePrediction.toPlace());\n });\n\n // ...\n // a.addEventListener(\"click\", () => {\n // this._fetchPlaceDetails(prediction.place_id);\n // });\n a.appendChild(divContainer);\n a.appendChild(divInner2);\n\n const li = document.createElement(\"li\");\n li.id = `option-${index + 1}`;\n li.className = this.#options.classes.li;\n\n li.appendChild(a);\n return li;\n });\n }\n\n /**\n * Handles the selection of a place. Fetches required fields\n * (displayName, formattedAddress, addressComponents) and calls the\n * user-defined `onPacData` callback.\n * @param {google.maps.places.Place} place - The selected Place object.\n */\n async _onPlaceSelected(place) {\n let data = null;\n try {\n // Fetch necessary details for the selected place\n await place.fetchFields({\n fields: this.#fetchFields, //[\"displayName\", \"formattedAddress\", \"addressComponents\"], // Add more fields as needed\n });\n // Call the user-provided callback with the place data\n // eslint-disable-next-line no-undef\n data = place.toJSON(); // Convert to plain JSON object\n this.#onDataCallback(data); // Convert to plain JSON object for the callback\n } catch (error) {\n console.error(\"Error fetching place details:\", error);\n // eslint-disable-next-line no-undef\n this.#onErrorCallback(error);\n } finally {\n // Reset the input and suggestions regardless of success/error\n this._reset(true, data); // Refresh token after selection\n }\n }\n\n /**\n * Creates a new Google Places Autocomplete Session Token.\n * This should be called before starting a new series of autocomplete requests.\n */\n _refreshToken() {\n try {\n // eslint-disable-next-line no-undef\n this.#request.sessionToken =\n new google.maps.places.AutocompleteSessionToken();\n } catch (error) {\n console.error(\"Error creating session token:\", error);\n // eslint-disable-next-line no-undef\n this.#onErrorCallback(error);\n }\n }\n\n /**\n * Sets the fields to be fetched for the selected place.\n * This allows you to specify which details you want to retrieve\n * when a place is selected, such as displayName, formattedAddress,\n * addressComponents, etc.\n * @param {Array<string>} fields - Array of field names to fetch.\n */\n setFetchFields(fields) {\n this._setFetchFields(fields);\n }\n /**\n * Gets the current fields that will be fetched for the selected place.\n * This is useful for understanding what details will be available\n * when a place is selected, such as displayName, formattedAddress,\n * addressComponents, etc.\n * @returns {Array<string>} The current fetch fields.\n */\n getFetchFields() {\n return this.#fetchFields;\n }\n\n /**\n * Sets the request parameters for the Places Autocomplete instance.\n * This method allows you to update the request parameters dynamically,\n * such as the input value, region codes, language, etc.\n * It merges the provided parameters with the default request parameters,\n * allowing you to override specific values while keeping the defaults intact.\n * This is useful for updating the search criteria without needing to recreate the instance.\n * @param {*} params\n */\n setRequestParams(params) {\n if (\n typeof params === \"object\" &&\n !Array.isArray(params) &&\n params !== null\n ) {\n // if params.input is provided, set it to the input element\n if (params.input && typeof params.input === \"string\") {\n this.#inputElement.value = params.input; // Set input value if provided\n }\n // Merge provided params with default request parameters\n // This allows overriding specific request parameters while keeping defaults\n this.#request = {\n ...this.#defaultRequestParams,\n ...params,\n };\n }\n }\n\n /**\n * Returns the current request parameters used by the Places Autocomplete instance.\n * This includes the input value, included region codes, language, and other settings.\n * It is useful for debugging or when you need to know the current search criteria.\n * @returns {Object} The current request parameters.\n */\n getRequestParams() {\n return this.#request;\n }\n\n /**\n * Sets the options for the Places Autocomplete instance.\n * This method allows you to change the appearance and behavior of the autocomplete widget,\n * such as classes, placeholder text, debounce time, etc.\n * It merges the provided options with the default options, allowing you to override specific values\n * while keeping the defaults intact.\n * This is useful for updating the widget's configuration without needing to recreate the instance.\n * @param {*} options\n */\n setOptions(options) {\n if (\n typeof options === \"object\" &&\n !Array.isArray(options) &&\n options !== null\n ) {\n this._detachEventListeners(); // Detach event listeners\n\n // // Ensure classes are deeply merged if user provides partial classes\n const tmpClasses = options.classes || {};\n delete options.classes; // Remove classes from options to avoid overwriting\n\n // Merge provided options with default options\n // This allows overriding specific options while keeping defaults\n this.#options = {\n ...this.#defaultOptions,\n ...options,\n };\n\n // Merge classes with defaults\n // This allows overriding specific classes while keeping defaults\n if (\n tmpClasses &&\n typeof tmpClasses === \"object\" &&\n Object.keys(tmpClasses).length > 0\n ) {\n this.#options.classes = {\n ...this.#defaultClasses,\n ...tmpClasses,\n };\n } else {\n this.#options.classes = { ...this.#defaultClasses }; // Use defaults if no classes provided\n }\n\n this._initialiseDebouncedRequest(); // Reinitialize the debounced request function\n this._createPACStructure(); // Recreate the structure with new options\n // Reattach the input event listener to the input element\n // This is necessary to ensure the new input element is ready for events\n if (this.#inputElement) {\n this._attachedEventListeners();\n } // Reinitialize the autocomplete functionality\n }\n }\n\n /**\n * Gets the current options used by the Places Autocomplete instance.\n * @returns {Object} The current options.\n */\n getOptions() {\n /**\n * Returns the current options used by the Places Autocomplete instance.\n * This includes classes, placeholder text, debounce time, and other settings.\n * It is useful for debugging or when you need to know the current configuration of the widget.\n * @returns {Object} The current options.\n */\n return this.#options;\n }\n\n /**\n * Clears the autocomplete input field and suggestions list.\n * This method resets the state of the autocomplete widget,\n * allowing the user to start a new search without any previous input or suggestions.\n * It also refreshes the Google Places session token to ensure a new session.\n * @returns {void}\n */\n clear() {\n this._reset(true);\n }\n\n /**\n * Destroys the PacAutocomplete instance.\n * Removes event listeners, clears the DOM, and nullifies properties.\n * This method should be called when the autocomplete widget is no longer needed.\n * It ensures that all resources are cleaned up to prevent memory leaks.\n * @returns {void}\n */\n destroy() {\n // Remove event listeners, remove elements from DOM\n this._detachEventListeners(); // Detach event listeners\n // Nullify properties\n this.#containerId = null;\n this.#pacEl = null;\n this.#googleMapsApiKey = null;\n this.#googleMapsApiVersion = null;\n this.#options = null;\n this.#request = null;\n this.#inputElement = null;\n this.#container = null;\n this.#ul = null;\n this.#kbdEscape = null;\n this.#kbdUp = null;\n this.#kbdDown = null;\n this.#allSuggestions = null;\n this.#currentSuggestion = -1;\n this.#onDataCallback = null;\n this.#onErrorCallback = null;\n this._debouncedMakeAcRequest = null;\n console.log(\"PacAutocomplete instance destroyed.\");\n }\n}\n"],"names":["PlacesAutocomplete","#containerId","#pacEl","#googleMapsApiKey","#googleMapsApiVersion","#options","#request","#inputElement","#container","#ul","#kbdEscape","#kbdUp","#kbdDown","#allSuggestions","#currentSuggestion","#onDataCallback","#onErrorCallback","#defaultOptions","#defaultClasses","#defaultRequestParams","#fetchFields","#defaultFetchFields","config","place","error","suggestions","fields","e","func","wait","timeout","args","later","distance","units","value","unitLabel","g","h","a","k","p","c","l","q","b","d","r","u","f","n","t","section","iconContainer","icon","label","kbdContainer","refresh","placeData","li","cl","link","currentLi","currentA","suggestion","index","divContainer","divInner","predictionText","originalText","matches","lastIndex","outerSpan","innerSpan","match","remainingText","divInner2","p2","data","params","options","tmpClasses"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  (function(p,y){typeof exports=="object"&&typeof module<"u"?y(exports):typeof define=="function"&&define.amd?define(["exports"],y):(p=typeof globalThis<"u"?globalThis:p||self,y(p.PlacesAutocomplete={}))})(this,(function(p){"use strict";/**
2
- * Initializes a Places Autocomplete widget.
2
+ * Initialises a Places Autocomplete widget.
3
3
  * This script dynamically loads the Google Maps JavaScript API, creates the UI elements
4
4
  * for the autocomplete input and suggestions list, handles user input with debouncing,
5
5
  * fetches suggestions, manages keyboard navigation, and calls user-defined callbacks
@@ -1 +1 @@
1
- {"version":3,"file":"places-autocomplete.umd.cjs","sources":["../PlacesAutocomplete.js"],"sourcesContent":["/**\n * Initializes a Places Autocomplete widget.\n * This script dynamically loads the Google Maps JavaScript API, creates the UI elements\n * for the autocomplete input and suggestions list, handles user input with debouncing,\n * fetches suggestions, manages keyboard navigation, and calls user-defined callbacks\n * on place selection or error.\n *\n * @author Alexander Pechkarev <alexpechkarev@gmail.com>\n * @license MIT\n *\n */\n\n/**\n * PacAutocomplete class\n * This class provides a Places Autocomplete widget.\n */\nexport class PlacesAutocomplete {\n // --- Private Properties (using # or _ prefix by convention) ---\n #containerId; // Container ID where the autocomplete widget will be rendered.\n #pacEl;\n #googleMapsApiKey;\n #googleMapsApiVersion;\n #options;\n #request;\n #inputElement;\n #container;\n #ul;\n #kbdEscape;\n #kbdUp;\n #kbdDown;\n #allSuggestions = [];\n #currentSuggestion = -1;\n #onDataCallback; // For user-provided data callback\n #onErrorCallback; // For user-provided error callback\n _debouncedMakeAcRequest; // Declare without initializing here\n #defaultOptions = {\n // Default options for the autocomplete widget.\n autofocus: false, // Automatically focus the input on load.\n autocomplete: \"off\", // HTML autocomplete attribute for the input.\n placeholder: \"Start typing your address ...\", // Placeholder text for the input.\n distance: true, // Show distance in suggestions (requires origin in request).\n distance_units: \"km\", // Units for distance ('km' or 'miles').\n label: \"\", // Optional label text above the input.\n debounce: 100, // Debounce delay (ms) for API requests.\n clear_input: true, // Clear input button (not implemented in this version).\n debug: false, // Enable debug mode (not implemented in this version).\n };\n #defaultClasses = {\n // CSS classes for various parts of the widget.\n section: \"\", // Outer section container.\n container: \"relative z-10 transform rounded-xl mt-4\", // Main container div.\n icon_container:\n \"pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3\", // Container for the search icon.\n icon: '<svg xmlns=\"http://www.w3.org/2000/svg\" class=\"w-5 h-5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"11\" cy=\"11\" r=\"8\" /><path d=\"m21 21-4.3-4.3\" /></svg>', // SVG for the search icon.\n input:\n \"border-1 w-full rounded-md border-0 shadow-sm bg-gray-100 px-4 py-2.5 pl-10 pr-20 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 sm:text-sm\", // Input field.\n kbd_container: \"absolute inset-y-0 right-0 flex py-1.5 pr-1.5\", // Container for keyboard hints.\n kbd_escape:\n \"inline-flex items-center rounded border border-gray-300 px-1 font-sans text-xs text-gray-500 w-8 mr-1\", // Escape key hint.\n kbd_up:\n \"inline-flex items-center justify-center rounded border border-gray-300 px-1 font-sans text-xs text-gray-500 w-6\", // Up arrow key hint.\n kbd_down:\n \"inline-flex items-center rounded border border-gray-400 px-1 font-sans text-xs text-gray-500 justify-center w-6\", // Down arrow key hint.\n kbd_active: \"bg-indigo-500 text-white\", // Class for active keyboard hint.\n ul: \"absolute z-50 -mb-2 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm divide-y divide-gray-100\", // Suggestions list (ul).\n li: \"z-50 cursor-default select-none py-2 px-2 lg:px-4 text-gray-900 hover:bg-indigo-500 hover:text-white\", // Suggestion item (li).\n li_current: \"bg-indigo-500\", // Class for the currently selected suggestion item.\n li_a: \"block w-full flex justify-between\", // Link element within a suggestion item.\n li_a_current: \"text-white\", // Class for the link in the currently selected suggestion item.\n li_div_container: \"flex min-w-0 gap-x-4\", // Container div within the suggestion link.\n li_div_one: \"min-w-0 flex-auto\", // First inner div (for place name).\n li_div_one_p: \"text-sm/6\", // Paragraph for the place name.\n li_div_two: \"shrink-0 flex flex-col items-end min-w-16\", // Second inner div (for distance).\n li_div_two_p: \"mt-1 text-xs/5\", // Paragraph for the distance.\n highlight: \"font-bold\", // Class for highlighting matched text in suggestions.\n };\n #defaultRequestParams = {\n // Default parameters for the autocomplete request.\n input: \"\", // Initial input value (empty).\n includedRegionCodes: [\"GB\"], // Default region codes to include in suggestions.\n language: \"en-gb\",\n region: \"GB\",\n };\n #fetchFields = [\"formattedAddress\", \"addressComponents\"];\n #defaultFetchFields = [\"formattedAddress\", \"addressComponents\"]; // Fields to fetch for the selected place (can be extended).\n\n /**\n * Class constructor for PacAutocomplete.\n * Initializes the autocomplete widget with the provided configuration.\n * @param {Object} config - Configuration object for the autocomplete widget.\n * @param {string} config.containerId - ID of the container element for the widget.\n * @param {string} config.googleMapsApiKey - Google Maps API key.\n * @param {string} [config.googleMapsApiVersion] - Version of the Google Maps API to use (default: \"weekly\").\n * @param {Object} [config.options] - Additional options for the widget (e.g., classes, callbacks).\n * @param {Object} [config.requestParams] - Parameters for the autocomplete request (e.g., input, region).\n * @param {*} config\n */\n constructor(config) {\n if (!config || !config.containerId || !config.googleMapsApiKey) {\n throw new Error(\n \"PacAutocomplete: Missing required configuration (containerId, googleMapsApiKey).\"\n );\n }\n\n this.#containerId = config.containerId; // Store the configuration object\n this.#pacEl = document.getElementById(config.containerId);\n if (!this.#pacEl) {\n throw new Error(\n `PacAutocomplete: Container element with ID \"${config.containerId}\" not found.`\n );\n }\n\n this.#googleMapsApiKey = config.googleMapsApiKey;\n this.#googleMapsApiVersion = config.googleMapsApiVersion || \"weekly\";\n\n // Merge user options with defaults\n this.#options = {\n ...this.#defaultOptions, // Default options\n ...config.options, // User-defined options override defaults\n };\n // Ensure classes are deeply merged if user provides partial classes\n if (config.options && config.options.classes) {\n this.#options.classes = {\n ...this.#defaultClasses,\n ...config.options.classes,\n };\n } else {\n this.#options.classes = this.#defaultClasses; // Use default classes if none provided\n }\n\n if (this.#options.debug) {\n console.log(\"___debug constructor options:\");\n console.log(this.#options);\n }\n\n if (config.fetchFields && Array.isArray(config.fetchFields)) {\n this._setFetchFields(config.fetchFields); // Set fetch fields from user config\n }\n\n // Set default response and error callbacks if not provided\n this.#onDataCallback =\n config.onResponse ||\n ((place) => {\n console.info(\"---------Default onResponse not provided---------\");\n console.info(\"Selected Place:\", JSON.stringify(place, null, 2));\n });\n this.#onErrorCallback =\n config.onError ||\n ((error) => {\n console.error(\"---------Default onError not provided---------\");\n console.error(\"PAC Error:\", error);\n });\n\n if (config.requestParams && Object.keys(config.requestParams).length > 0) {\n this.#request = {\n ...this.#defaultRequestParams,\n ...config.requestParams,\n };\n } else {\n this.#request = { ...this.#defaultRequestParams }; // Use defaults if no requestParams provided\n }\n\n if (this.#options.debug) {\n console.log(\"___debug constructor requestParams:\", this.#request);\n }\n\n this._initialiseDebouncedRequest(); // Initialize the debounced request function\n\n this._init(); // Underscore prefix for internal initialization method\n }\n\n // --- Private Initialization Method ---\n async _init() {\n try {\n // check if google maps api is already loaded\n if (typeof google === \"undefined\" || !google.maps) {\n // Load the Google Maps API dynamically\n await this._loadGoogleMapsApi({\n key: this.#googleMapsApiKey,\n v: this.#googleMapsApiVersion,\n });\n }\n this._createPACStructure();\n await this._initializeAutocomplete();\n } catch (error) {\n this.#onErrorCallback(error);\n }\n }\n\n /**\n * Initializes the debounced request function for fetching autocomplete suggestions.\n *\n * Debounced function to fetch autocomplete suggestions from the Google Places API.\n * Triggered by the 'input' event on the input element.\n *\n *\n */\n _initialiseDebouncedRequest() {\n this._debouncedMakeAcRequest = this._debounce(async () => {\n if (!this.#inputElement || !this.#inputElement.value) {\n this._reset();\n if (this.#inputElement)\n this.#inputElement.setAttribute(\"aria-expanded\", \"false\");\n return;\n }\n\n this.#request.input = this.#inputElement.value;\n\n try {\n const { suggestions } =\n // eslint-disable-next-line no-undef\n await google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions(\n this.#request\n );\n\n // Display suggestions\n if (suggestions && suggestions.length > 0) {\n this.#ul.replaceChildren(\n ...this._createSuggestionElements(suggestions)\n );\n this.#ul.style.display = \"block\";\n this.#inputElement.setAttribute(\"aria-expanded\", \"true\");\n } else {\n // No suggestions found\n this._reset(); // Clear any old suggestions\n this.#inputElement.setAttribute(\"aria-expanded\", \"false\");\n // Optionally display a \"no results\" message in the 'ul'\n }\n } catch (error) {\n this.#onErrorCallback(error);\n this._reset();\n }\n }, this.#options.debounce); // Default debounce to 100ms if not set\n }\n /**\n * Sets the fields to fetch for the selected place.\n * @param {Array<string>} fields - The fields to fetch.\n */\n _setFetchFields(fields) {\n if (Array.isArray(fields) && fields.length > 0) {\n this.#fetchFields = [\n ...new Set([...this.#defaultFetchFields, ...fields]),\n ].filter((e) => e); // Ensure unique and non-empty fields\n }\n }\n\n /**\n * Creates a debounced version of a function.\n * The debounced function delays invoking `func` until after `wait` milliseconds have\n * elapsed since the last time the debounced function was invoked.\n * @param {Function} func - The function to debounce.\n * @param {number} wait - The number of milliseconds to delay.\n * @returns {Function} The new debounced function.\n */\n _debounce(func, wait) {\n if (this.#options.debug) {\n console.log(\"___debug debounce function called with wait:\", wait);\n }\n\n let timeout = null;\n return function executedFunction(...args) {\n const later = () => {\n timeout = null;\n func(...args); // Call original function\n };\n if (timeout !== null) {\n clearTimeout(timeout); // Clear the previous timeout\n }\n timeout = setTimeout(later, wait ?? 100); // Set the new timeout\n };\n }\n /**\n * Formats a distance in meters into kilometers or miles.\n * @param {number | null | undefined} distance - Distance in meters.\n * @param {'km' | 'miles'} units - The desired output units.\n * @returns {string | null} Formatted distance string (e.g., \"1.23 km\") or null if input is invalid.\n */\n _formatDistance(distance, units) {\n if (typeof distance !== \"number\" || !this.#options.distance) {\n return null; // Return null if distance isn't shown or invalid\n }\n let value;\n let unitLabel;\n if (units === \"km\") {\n value = (distance / 1000).toFixed(2);\n unitLabel = \"km\";\n } else {\n // Default to miles if not 'km'\n value = (distance / 1609.34).toFixed(2);\n unitLabel = \"miles\";\n }\n // Avoid showing \".00\"\n value = value.replace(/\\.00$/, \"\");\n return `${value} ${unitLabel}`;\n }\n\n /**\n * Dynamically loads the Google Maps JavaScript API using the importLibrary method.\n * This is the standard approach recommended by Google.\n * @see https://developers.google.com/maps/documentation/javascript/load-maps-js-api\n * @param {object} g - Configuration object for the API loader (key, v, libraries, etc.).\n */\n async _loadGoogleMapsApi(g) {\n var h, // Promise tracking API load\n a, // Script element\n k, // Loop variable for config keys\n p = \"The Google Maps JavaScript API\", // Error message prefix\n c = \"google\", // Global namespace\n l = \"importLibrary\", // Loader function name\n q = \"__ib__\", // Internal callback name\n m = document, // Document reference\n b = window; // Window reference\n b = b[c] || (b[c] = {}); // Ensure google namespace exists\n var d = b.maps || (b.maps = {}), // Ensure google.maps namespace exists\n r = new Set(), // Set to track requested libraries\n e = new URLSearchParams(), // URL parameters for the API script\n u = () =>\n // Function to initiate API loading (if not already started)\n h ||\n // eslint-disable-next-line no-async-promise-executor\n (h = new Promise(async (f, n) => {\n // Create script element (done async to potentially wait for nonce)\n // await (a = m.createElement('script')); // Original Google code had await here, might not be needed\n a = m.createElement(\"script\"); // Create script tag\n e.set(\"libraries\", [...r].join(\",\")); // Add accumulated libraries\n // Add other parameters from the config object 'g'\n for (k in g)\n e.set(\n k.replace(/[A-Z]/g, (t) => \"_\" + t[0].toLowerCase()), // Convert camelCase to snake_case\n g[k]\n );\n e.set(\"callback\", c + \".maps.\" + q); // Set the internal callback function name\n a.src = `https://maps.${c}apis.com/maps/api/js?` + e; // Construct the API URL\n d[q] = f; // Assign the promise resolver to the callback name on google.maps\n // Error handling for script loading failure\n a.onerror = () =>\n (h = n(\n new Error(\n `${p} could not load. Check your API key and network connection.`\n )\n )); // Use onerror for load failures\n // Nonce for Content Security Policy\n a.nonce = m.querySelector(\"script[nonce]\")?.nonce || \"\";\n m.head.append(a); // Append the script to the document head\n }));\n // Define or reuse the importLibrary function on google.maps\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n d[l]\n ? console.warn(p + \" only loads once. Ignoring:\", g) // Warn if called again\n : (d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n))); // The actual importLibrary implementation\n }\n\n // --- UI Creation ---\n _createPACStructure() {\n const section = document.createElement(\"section\");\n section.className = this.#options.classes.section;\n\n // Main container\n this.#container = document.createElement(\"div\");\n this.#container.className = this.#options.classes.container;\n this.#container.setAttribute(\"id\", this.#containerId + \"-div\");\n section.appendChild(this.#container);\n\n // Icon\n const iconContainer = document.createElement(\"div\");\n iconContainer.className = this.#options.classes.icon_container;\n this.#container.appendChild(iconContainer);\n const icon = document.createElement(\"div\");\n icon.innerHTML = this.#options.classes.icon;\n iconContainer.appendChild(icon.firstElementChild); // Append the actual SVG element\n\n // Input field\n this.#inputElement = document.createElement(\"input\");\n this.#inputElement.id = this.#containerId + \"-input\"; // Assign ID for label association\n this.#inputElement.type = \"text\";\n this.#inputElement.name = \"search\"; // Consider making name configurable\n this.#inputElement.placeholder = this.#options.placeholder;\n this.#inputElement.autocomplete = this.#options.autocomplete;\n this.#inputElement.className = this.#options.classes.input;\n this.#inputElement.setAttribute(\"role\", \"combobox\");\n this.#inputElement.setAttribute(\"aria-autocomplete\", \"list\");\n this.#inputElement.setAttribute(\"aria-expanded\", \"false\"); // Will be updated dynamically\n this.#inputElement.setAttribute(\"aria-controls\", \"pacSuggestions\"); // Links to the suggestions list\n this.#inputElement.setAttribute(\"aria-activedescendant\", \"\"); // Will be updated dynamically\n\n if (this.#options.autofocus) {\n this.#inputElement.autofocus = true;\n }\n if (this.#options.label) {\n const label = document.createElement(\"label\");\n label.htmlFor = this.#inputElement.id; // Correctly link label to input by ID\n label.textContent = this.#options.label;\n // Add label classes if needed from opts.classes\n section.prepend(label); // Append label before input or adjust structure\n }\n this.#container.appendChild(this.#inputElement);\n\n // Keyboard hints container\n const kbdContainer = document.createElement(\"div\");\n kbdContainer.className = this.#options.classes.kbd_container;\n this.#kbdEscape = document.createElement(\"kbd\");\n this.#kbdEscape.className = this.#options.classes.kbd_escape;\n this.#kbdEscape.textContent = \"Esc\";\n kbdContainer.appendChild(this.#kbdEscape);\n this.#kbdUp = document.createElement(\"kbd\");\n this.#kbdUp.className = this.#options.classes.kbd_up;\n this.#kbdUp.innerHTML = \"&#8593;\"; // Up arrow HTML entity\n kbdContainer.appendChild(this.#kbdUp);\n this.#kbdDown = document.createElement(\"kbd\");\n this.#kbdDown.className = this.#options.classes.kbd_down;\n this.#kbdDown.innerHTML = \"&#8595;\"; // Down arrow HTML entity\n kbdContainer.appendChild(this.#kbdDown);\n this.#container.appendChild(kbdContainer);\n\n // Suggestions list (initially hidden)\n this.#ul = document.createElement(\"ul\");\n this.#ul.id = \"pacSuggestions\"; // Must match aria-controls\n this.#ul.className = this.#options.classes.ul;\n this.#ul.style.display = \"none\";\n this.#ul.setAttribute(\"role\", \"listbox\");\n this.#ul.setAttribute(\"aria-labelledby\", this.#inputElement.id); // Link listbox to input for accessibility\n this.#container.appendChild(this.#ul);\n\n this.#pacEl.appendChild(section);\n section.addEventListener(\"keydown\", this._onKeyDown.bind(this)); // Bind 'this'\n }\n\n /**\n * Attaches event listeners to the input element for handling user input.\n * This includes debounced input handling, focus/blur events, and keyboard navigation.\n */\n _attachedEventListeners() {\n this.#inputElement.addEventListener(\"input\", this._debouncedMakeAcRequest);\n // Add focus/blur listeners if needed to manage suggestion visibility\n this.#inputElement.addEventListener(\"blur\", () => {\n // Delay hiding suggestions to allow click events on them\n setTimeout(() => {\n if (this.#ul && !this.#ul.contains(document.activeElement)) {\n // Check if focus moved outside suggestions\n this.#ul.style.display = \"none\";\n this.#inputElement.setAttribute(\"aria-expanded\", \"false\");\n }\n }, 200); // Adjust delay as needed\n });\n this.#inputElement.addEventListener(\"focus\", () => {\n // Potentially show suggestions again if input has value\n if (this.#inputElement.value && this.#allSuggestions.length > 0) {\n this.#ul.style.display = \"block\";\n this.#inputElement.setAttribute(\"aria-expanded\", \"true\");\n }\n });\n }\n\n _detachEventListeners() {\n // Remove event listeners, remove elements from DOM\n if (this.#inputElement) {\n this.#inputElement.removeEventListener(\n \"input\",\n this._debouncedMakeAcRequest\n );\n // remove other listeners\n }\n if (this.#pacEl && this.#container) {\n this.#pacEl.removeChild(this.#container.parentElement); // remove the whole section\n }\n }\n\n /**\n * Initializes the core autocomplete functionality after the API is loaded.\n * Imports necessary libraries and sets up the input event listener.\n */\n async _initializeAutocomplete() {\n try {\n // Ensure the 'places' library is available via the dynamic loader\n // eslint-disable-next-line no-undef\n await google.maps.importLibrary(\"places\");\n // console.log('Places library imported successfully.'); // For debugging\n\n // Initial token generation\n this._refreshToken();\n\n // Attach the debounced request function to the input element's 'input' event\n if (this.#inputElement) {\n this._attachedEventListeners();\n } else {\n this.#onErrorCallback(\n new Error(\"Input element not found during initialization.\")\n );\n }\n } catch (error) {\n console.error(\"Error initializing Google Places Autocomplete:\", error);\n // eslint-disable-next-line no-undef\n this.#onErrorCallback(\n new Error(\"Google Maps Places library not available.\")\n );\n }\n }\n\n /**\n * Resets the autocomplete input field, clears suggestions, and optionally refreshes the session token.\n * @param {boolean} [refresh=false] - Whether to refresh the Google Places session token.\n */\n _reset(refresh = false, placeData = null) {\n this.#currentSuggestion = -1;\n\n /**\n * If the input element exists and clear_input is false, set its value to the formatted address\n * from placeData. Otherwise, clear the input value.\n * This allows the user to keep the input value if they selected a place,\n * but still allows clearing it if clear_input is true or placeData is not provided.\n * @type {HTMLInputElement}\n * @property {string} value - The value of the input element.\n * @property {boolean} clear_input - Whether to clear the input value after selection.\n * @property {Object} placeData - The data of the selected place, containing formattedAddress.\n */\n if (\n this.#inputElement &&\n this.#options.clear_input == false &&\n placeData &&\n placeData.formattedAddress\n ) {\n this.#inputElement.value = placeData.formattedAddress; // Set input value to formatted address\n } else if (this.#inputElement) {\n this.#inputElement.value = \"\";\n }\n\n if (this.#inputElement) {\n this.#inputElement.setAttribute(\"aria-expanded\", \"false\");\n this.#inputElement.setAttribute(\"aria-activedescendant\", \"\"); // Clear aria-activedescendant\n this.#inputElement.blur();\n }\n\n this.#allSuggestions = [];\n this.#currentSuggestion = -1;\n if (this.#ul) {\n this.#ul.innerHTML = \"\"; // Clear existing suggestions\n this.#ul.style.display = \"none\";\n }\n if (refresh) {\n this._refreshToken();\n }\n }\n /**\n * Removes the 'current' highlighting classes from all suggestion list items (li) and their links (a).\n */\n _resetLiClasses() {\n if (!this.#ul) return;\n Array.from(this.#ul.children).forEach((li) => {\n this.#options.classes.li_current\n .split(\" \")\n .forEach((cl) => li.classList.remove(cl));\n const link = li.querySelector(\"a\");\n if (link) {\n this.#options.classes.li_a_current\n .split(\" \")\n .forEach((cl) => link.classList.remove(cl));\n }\n });\n }\n\n /**\n * Handles keyboard events (ArrowDown, ArrowUp, Enter, Escape) for navigating\n * and selecting suggestions or closing the list.\n * @param {KeyboardEvent} e - The keyboard event object.\n */\n _onKeyDown(e) {\n this._resetLiClasses(); // Reset classes on any key press within the suggestions\n\n if (e.key === \"Escape\") {\n e.preventDefault();\n // Visual feedback for key press\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdEscape?.classList.add(cl));\n setTimeout(\n () =>\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdEscape?.classList.remove(cl)),\n 300\n );\n\n this._reset(true); // Reset search input and results, refresh token\n }\n\n if (\n !this.#allSuggestions.length ||\n !this.#ul ||\n this.#ul.style.display === \"none\"\n )\n return;\n\n if (e.key === \"ArrowDown\") {\n e.preventDefault(); // Prevent cursor movement in input\n this.#currentSuggestion = Math.min(\n this.#currentSuggestion + 1,\n this.#allSuggestions.length - 1\n );\n if (this.#currentSuggestion < 0) this.#currentSuggestion = 0; // Handle case where it was -1\n\n const currentLi = this.#ul.children.item(this.#currentSuggestion);\n if (currentLi) {\n const currentA = currentLi.querySelector(\"a\");\n this.#options.classes.li_current\n .split(\" \")\n .forEach((cl) => currentLi.classList.add(cl));\n if (currentA) {\n this.#options.classes.li_a_current\n .split(\" \")\n .forEach((cl) => currentA.classList.add(cl));\n }\n currentLi.scrollIntoView({ block: \"nearest\" }); // Ensure visible\n this.#inputElement.setAttribute(\"aria-activedescendant\", currentLi.id); // Update aria-activedescendant\n }\n\n // Visual feedback for key press\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdDown?.classList.add(cl));\n setTimeout(\n () =>\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdDown?.classList.remove(cl)),\n 300\n );\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault(); // Prevent cursor movement in input\n this.#currentSuggestion = Math.max(this.#currentSuggestion - 1, 0); // Stay at 0 if already there\n\n const currentLi = this.#ul.children.item(this.#currentSuggestion);\n if (currentLi) {\n const currentA = currentLi.querySelector(\"a\");\n this.#options.classes.li_current\n .split(\" \")\n .forEach((cl) => currentLi.classList.add(cl));\n if (currentA) {\n this.#options.classes.li_a_current\n .split(\" \")\n .forEach((cl) => currentA.classList.add(cl));\n }\n currentLi.scrollIntoView({ block: \"nearest\" }); // Ensure visible\n }\n\n // Visual feedback for key press\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdUp?.classList.add(cl));\n setTimeout(\n () =>\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdUp?.classList.remove(cl)),\n 300\n );\n } else if (e.key === \"Enter\") {\n e.preventDefault(); // Prevent form submission if applicable\n if (\n this.#currentSuggestion >= 0 &&\n this.#currentSuggestion < this.#allSuggestions.length\n ) {\n this._onPlaceSelected(\n this.#allSuggestions[this.#currentSuggestion].place\n );\n // Reset is handled within onPlaceSelected via reset(true)\n }\n }\n }\n\n /**\n * Creates an array of list item (LI) elements for the suggestions dropdown.\n * Each LI contains a link (A) with the place prediction details and distance.\n * Handles highlighting the matched parts of the suggestion text.\n * @param {Array<google.maps.places.AutocompleteSuggestion>} suggestions - Array of suggestion objects from the API.\n * @returns {Array<HTMLLIElement>} An array of LI elements to be added to the suggestions UL.\n */\n _createSuggestionElements(suggestions) {\n this.#allSuggestions = []; // Reset before populating\n return suggestions.map((suggestion, index) => {\n this.#allSuggestions.push({\n id: index + 1,\n description: suggestion.placePrediction.toString(),\n place: suggestion.placePrediction.toPlace(),\n });\n\n // create div elements\n const divContainer = document.createElement(\"div\");\n divContainer.className = this.#options.classes.li_div_container; // flex min-w-0 gap-x-4\n // create inner div element - place name\n const divInner = document.createElement(\"div\");\n divInner.className = this.#options.classes.li_div_one; // min-w-0 flex-auto\n divContainer.appendChild(divInner);\n // create p element - place name\n const p = document.createElement(\"p\");\n p.className = this.#options.classes.li_div_one_p; // text-sm/6\n\n // get prediction text\n const predictionText = suggestion.placePrediction.text;\n const originalText = predictionText.text;\n // Array of objects with startOffset, endOffset\n const matches = predictionText.matches;\n\n //Highlighting Logic\n let lastIndex = 0;\n\n // Sort matches just in case they aren't ordered (though they usually are)\n matches.sort((a, b) => a.startOffset - b.startOffset);\n\n // 1. Create the outer span\n const outerSpan = document.createElement(\"span\");\n\n // 2. Create the inner span for the bold part\n const innerSpan = document.createElement(\"span\");\n innerSpan.classList = this.#options.classes.highlight ?? \"font-bold\"; // Use the highlight class from options\n\n for (const match of matches) {\n // Append text before the current match\n outerSpan.textContent += originalText.substring(\n lastIndex,\n match.startOffset\n );\n\n // Append the highlighted match segment\n if (match.startOffset > 0) {\n // check previous charter is space\n const prevChar = originalText.charAt(match.startOffset - 1);\n if (prevChar == \" \") {\n innerSpan.textContent += \" \";\n }\n }\n innerSpan.textContent += originalText.substring(\n match.startOffset,\n match.endOffset\n );\n\n // Update the last index processed\n lastIndex = match.endOffset;\n }\n\n // 3. Create a text node for the remaining text\n const remainingText = document.createTextNode(\n originalText.substring(lastIndex)\n );\n\n // 4. Append the inner span and the text node to the outer span\n outerSpan.appendChild(innerSpan);\n outerSpan.appendChild(remainingText);\n\n // 5. Append the outer span to the paragraph element\n p.appendChild(outerSpan);\n\n divInner.appendChild(p);\n divContainer.appendChild(divInner);\n\n // create inner div element - distance\n const divInner2 = document.createElement(\"div\");\n divInner2.className = this.#options.classes.li_div_two; //'shrink-0 flex flex-col items-end min-w-16';\n divContainer.appendChild(divInner2);\n // create p element - distance\n const p2 = document.createElement(\"p\");\n p2.className = this.#options.classes.li_div_two_p; //'mt-1 text-xs/5 ';\n p2.textContent = this._formatDistance(\n suggestion.placePrediction.distanceMeters,\n this.#options.distance_units ?? \"km\"\n );\n divInner2.appendChild(p2);\n\n // // create a link element\n const a = document.createElement(\"a\");\n a.href = \"javascript:void(0)\";\n a.tabIndex = index + 1;\n a.className = this.#options.classes.li_a; // block w-full flex justify-between\n\n a.addEventListener(\"click\", () => {\n this._onPlaceSelected(suggestion.placePrediction.toPlace());\n });\n\n // ...\n // a.addEventListener(\"click\", () => {\n // this._fetchPlaceDetails(prediction.place_id);\n // });\n a.appendChild(divContainer);\n a.appendChild(divInner2);\n\n const li = document.createElement(\"li\");\n li.id = `option-${index + 1}`;\n li.className = this.#options.classes.li;\n\n li.appendChild(a);\n return li;\n });\n }\n\n /**\n * Handles the selection of a place. Fetches required fields\n * (displayName, formattedAddress, addressComponents) and calls the\n * user-defined `onPacData` callback.\n * @param {google.maps.places.Place} place - The selected Place object.\n */\n async _onPlaceSelected(place) {\n let data = null;\n try {\n // Fetch necessary details for the selected place\n await place.fetchFields({\n fields: this.#fetchFields, //[\"displayName\", \"formattedAddress\", \"addressComponents\"], // Add more fields as needed\n });\n // Call the user-provided callback with the place data\n // eslint-disable-next-line no-undef\n data = place.toJSON(); // Convert to plain JSON object\n this.#onDataCallback(data); // Convert to plain JSON object for the callback\n } catch (error) {\n console.error(\"Error fetching place details:\", error);\n // eslint-disable-next-line no-undef\n this.#onErrorCallback(error);\n } finally {\n // Reset the input and suggestions regardless of success/error\n this._reset(true, data); // Refresh token after selection\n }\n }\n\n /**\n * Creates a new Google Places Autocomplete Session Token.\n * This should be called before starting a new series of autocomplete requests.\n */\n _refreshToken() {\n try {\n // eslint-disable-next-line no-undef\n this.#request.sessionToken =\n new google.maps.places.AutocompleteSessionToken();\n } catch (error) {\n console.error(\"Error creating session token:\", error);\n // eslint-disable-next-line no-undef\n this.#onErrorCallback(error);\n }\n }\n\n /**\n * Sets the fields to be fetched for the selected place.\n * This allows you to specify which details you want to retrieve\n * when a place is selected, such as displayName, formattedAddress,\n * addressComponents, etc.\n * @param {Array<string>} fields - Array of field names to fetch.\n */\n setFetchFields(fields) {\n this._setFetchFields(fields);\n }\n /**\n * Gets the current fields that will be fetched for the selected place.\n * This is useful for understanding what details will be available\n * when a place is selected, such as displayName, formattedAddress,\n * addressComponents, etc.\n * @returns {Array<string>} The current fetch fields.\n */\n getFetchFields() {\n return this.#fetchFields;\n }\n\n /**\n * Sets the request parameters for the Places Autocomplete instance.\n * This method allows you to update the request parameters dynamically,\n * such as the input value, region codes, language, etc.\n * It merges the provided parameters with the default request parameters,\n * allowing you to override specific values while keeping the defaults intact.\n * This is useful for updating the search criteria without needing to recreate the instance.\n * @param {*} params\n */\n setRequestParams(params) {\n if (\n typeof params === \"object\" &&\n !Array.isArray(params) &&\n params !== null\n ) {\n // if params.input is provided, set it to the input element\n if (params.input && typeof params.input === \"string\") {\n this.#inputElement.value = params.input; // Set input value if provided\n }\n // Merge provided params with default request parameters\n // This allows overriding specific request parameters while keeping defaults\n this.#request = {\n ...this.#defaultRequestParams,\n ...params,\n };\n }\n }\n\n /**\n * Returns the current request parameters used by the Places Autocomplete instance.\n * This includes the input value, included region codes, language, and other settings.\n * It is useful for debugging or when you need to know the current search criteria.\n * @returns {Object} The current request parameters.\n */\n getRequestParams() {\n return this.#request;\n }\n\n /**\n * Sets the options for the Places Autocomplete instance.\n * This method allows you to change the appearance and behavior of the autocomplete widget,\n * such as classes, placeholder text, debounce time, etc.\n * It merges the provided options with the default options, allowing you to override specific values\n * while keeping the defaults intact.\n * This is useful for updating the widget's configuration without needing to recreate the instance.\n * @param {*} options\n */\n setOptions(options) {\n if (\n typeof options === \"object\" &&\n !Array.isArray(options) &&\n options !== null\n ) {\n this._detachEventListeners(); // Detach event listeners\n\n // // Ensure classes are deeply merged if user provides partial classes\n const tmpClasses = options.classes || {};\n delete options.classes; // Remove classes from options to avoid overwriting\n\n // Merge provided options with default options\n // This allows overriding specific options while keeping defaults\n this.#options = {\n ...this.#defaultOptions,\n ...options,\n };\n\n // Merge classes with defaults\n // This allows overriding specific classes while keeping defaults\n if (\n tmpClasses &&\n typeof tmpClasses === \"object\" &&\n Object.keys(tmpClasses).length > 0\n ) {\n this.#options.classes = {\n ...this.#defaultClasses,\n ...tmpClasses,\n };\n } else {\n this.#options.classes = { ...this.#defaultClasses }; // Use defaults if no classes provided\n }\n\n this._initialiseDebouncedRequest(); // Reinitialize the debounced request function\n this._createPACStructure(); // Recreate the structure with new options\n // Reattach the input event listener to the input element\n // This is necessary to ensure the new input element is ready for events\n if (this.#inputElement) {\n this._attachedEventListeners();\n } // Reinitialize the autocomplete functionality\n }\n }\n\n /**\n * Gets the current options used by the Places Autocomplete instance.\n * @returns {Object} The current options.\n */\n getOptions() {\n /**\n * Returns the current options used by the Places Autocomplete instance.\n * This includes classes, placeholder text, debounce time, and other settings.\n * It is useful for debugging or when you need to know the current configuration of the widget.\n * @returns {Object} The current options.\n */\n return this.#options;\n }\n\n /**\n * Clears the autocomplete input field and suggestions list.\n * This method resets the state of the autocomplete widget,\n * allowing the user to start a new search without any previous input or suggestions.\n * It also refreshes the Google Places session token to ensure a new session.\n * @returns {void}\n */\n clear() {\n this._reset(true);\n }\n\n /**\n * Destroys the PacAutocomplete instance.\n * Removes event listeners, clears the DOM, and nullifies properties.\n * This method should be called when the autocomplete widget is no longer needed.\n * It ensures that all resources are cleaned up to prevent memory leaks.\n * @returns {void}\n */\n destroy() {\n // Remove event listeners, remove elements from DOM\n this._detachEventListeners(); // Detach event listeners\n // Nullify properties\n this.#containerId = null;\n this.#pacEl = null;\n this.#googleMapsApiKey = null;\n this.#googleMapsApiVersion = null;\n this.#options = null;\n this.#request = null;\n this.#inputElement = null;\n this.#container = null;\n this.#ul = null;\n this.#kbdEscape = null;\n this.#kbdUp = null;\n this.#kbdDown = null;\n this.#allSuggestions = null;\n this.#currentSuggestion = -1;\n this.#onDataCallback = null;\n this.#onErrorCallback = null;\n this._debouncedMakeAcRequest = null;\n console.log(\"PacAutocomplete instance destroyed.\");\n }\n}\n"],"names":["PlacesAutocomplete","#containerId","#pacEl","#googleMapsApiKey","#googleMapsApiVersion","#options","#request","#inputElement","#container","#ul","#kbdEscape","#kbdUp","#kbdDown","#allSuggestions","#currentSuggestion","#onDataCallback","#onErrorCallback","#defaultOptions","#defaultClasses","#defaultRequestParams","#fetchFields","#defaultFetchFields","config","place","error","suggestions","fields","e","func","wait","timeout","args","later","distance","units","value","unitLabel","g","h","a","k","p","c","l","q","m","b","d","r","u","f","n","t","section","iconContainer","icon","label","kbdContainer","refresh","placeData","li","cl","link","currentLi","currentA","suggestion","index","divContainer","divInner","predictionText","originalText","matches","lastIndex","outerSpan","innerSpan","match","remainingText","divInner2","p2","data","params","options","tmpClasses"],"mappings":"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"}
1
+ {"version":3,"file":"places-autocomplete.umd.cjs","sources":["../PlacesAutocomplete.js"],"sourcesContent":["/**\n * Initialises a Places Autocomplete widget.\n * This script dynamically loads the Google Maps JavaScript API, creates the UI elements\n * for the autocomplete input and suggestions list, handles user input with debouncing,\n * fetches suggestions, manages keyboard navigation, and calls user-defined callbacks\n * on place selection or error.\n *\n * @author Alexander Pechkarev <alexpechkarev@gmail.com>\n * @license MIT\n *\n */\n\n/**\n * PacAutocomplete class\n * This class provides a Places Autocomplete widget.\n */\nexport class PlacesAutocomplete {\n // --- Private Properties (using # or _ prefix by convention) ---\n #containerId; // Container ID where the autocomplete widget will be rendered.\n #pacEl;\n #googleMapsApiKey;\n #googleMapsApiVersion;\n #options;\n #request;\n #inputElement;\n #container;\n #ul;\n #kbdEscape;\n #kbdUp;\n #kbdDown;\n #allSuggestions = [];\n #currentSuggestion = -1;\n #onDataCallback; // For user-provided data callback\n #onErrorCallback; // For user-provided error callback\n _debouncedMakeAcRequest; // Declare without initializing here\n #defaultOptions = {\n // Default options for the autocomplete widget.\n autofocus: false, // Automatically focus the input on load.\n autocomplete: \"off\", // HTML autocomplete attribute for the input.\n placeholder: \"Start typing your address ...\", // Placeholder text for the input.\n distance: true, // Show distance in suggestions (requires origin in request).\n distance_units: \"km\", // Units for distance ('km' or 'miles').\n label: \"\", // Optional label text above the input.\n debounce: 100, // Debounce delay (ms) for API requests.\n clear_input: true, // Clear input button (not implemented in this version).\n debug: false, // Enable debug mode (not implemented in this version).\n };\n #defaultClasses = {\n // CSS classes for various parts of the widget.\n section: \"\", // Outer section container.\n container: \"relative z-10 transform rounded-xl mt-4\", // Main container div.\n icon_container:\n \"pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3\", // Container for the search icon.\n icon: '<svg xmlns=\"http://www.w3.org/2000/svg\" class=\"w-5 h-5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"11\" cy=\"11\" r=\"8\" /><path d=\"m21 21-4.3-4.3\" /></svg>', // SVG for the search icon.\n input:\n \"border-1 w-full rounded-md border-0 shadow-sm bg-gray-100 px-4 py-2.5 pl-10 pr-20 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 sm:text-sm\", // Input field.\n kbd_container: \"absolute inset-y-0 right-0 flex py-1.5 pr-1.5\", // Container for keyboard hints.\n kbd_escape:\n \"inline-flex items-center rounded border border-gray-300 px-1 font-sans text-xs text-gray-500 w-8 mr-1\", // Escape key hint.\n kbd_up:\n \"inline-flex items-center justify-center rounded border border-gray-300 px-1 font-sans text-xs text-gray-500 w-6\", // Up arrow key hint.\n kbd_down:\n \"inline-flex items-center rounded border border-gray-400 px-1 font-sans text-xs text-gray-500 justify-center w-6\", // Down arrow key hint.\n kbd_active: \"bg-indigo-500 text-white\", // Class for active keyboard hint.\n ul: \"absolute z-50 -mb-2 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm divide-y divide-gray-100\", // Suggestions list (ul).\n li: \"z-50 cursor-default select-none py-2 px-2 lg:px-4 text-gray-900 hover:bg-indigo-500 hover:text-white\", // Suggestion item (li).\n li_current: \"bg-indigo-500\", // Class for the currently selected suggestion item.\n li_a: \"block w-full flex justify-between\", // Link element within a suggestion item.\n li_a_current: \"text-white\", // Class for the link in the currently selected suggestion item.\n li_div_container: \"flex min-w-0 gap-x-4\", // Container div within the suggestion link.\n li_div_one: \"min-w-0 flex-auto\", // First inner div (for place name).\n li_div_one_p: \"text-sm/6\", // Paragraph for the place name.\n li_div_two: \"shrink-0 flex flex-col items-end min-w-16\", // Second inner div (for distance).\n li_div_two_p: \"mt-1 text-xs/5\", // Paragraph for the distance.\n highlight: \"font-bold\", // Class for highlighting matched text in suggestions.\n };\n #defaultRequestParams = {\n // Default parameters for the autocomplete request.\n input: \"\", // Initial input value (empty).\n includedRegionCodes: [\"GB\"], // Default region codes to include in suggestions.\n language: \"en-gb\",\n region: \"GB\",\n };\n #fetchFields = [\"formattedAddress\", \"addressComponents\"];\n #defaultFetchFields = [\"formattedAddress\", \"addressComponents\"]; // Fields to fetch for the selected place (can be extended).\n\n /**\n * Class constructor for PacAutocomplete.\n * Initializes the autocomplete widget with the provided configuration.\n * @param {Object} config - Configuration object for the autocomplete widget.\n * @param {string} config.containerId - ID of the container element for the widget.\n * @param {string} config.googleMapsApiKey - Google Maps API key.\n * @param {string} [config.googleMapsApiVersion] - Version of the Google Maps API to use (default: \"weekly\").\n * @param {Object} [config.options] - Additional options for the widget (e.g., classes, callbacks).\n * @param {Object} [config.requestParams] - Parameters for the autocomplete request (e.g., input, region).\n * @param {*} config\n */\n constructor(config) {\n if (!config || !config.containerId || !config.googleMapsApiKey) {\n throw new Error(\n \"PacAutocomplete: Missing required configuration (containerId, googleMapsApiKey).\"\n );\n }\n\n this.#containerId = config.containerId; // Store the configuration object\n this.#pacEl = document.getElementById(config.containerId);\n if (!this.#pacEl) {\n throw new Error(\n `PacAutocomplete: Container element with ID \"${config.containerId}\" not found.`\n );\n }\n\n this.#googleMapsApiKey = config.googleMapsApiKey;\n this.#googleMapsApiVersion = config.googleMapsApiVersion || \"weekly\";\n\n // Merge user options with defaults\n this.#options = {\n ...this.#defaultOptions, // Default options\n ...config.options, // User-defined options override defaults\n };\n // Ensure classes are deeply merged if user provides partial classes\n if (config.options && config.options.classes) {\n this.#options.classes = {\n ...this.#defaultClasses,\n ...config.options.classes,\n };\n } else {\n this.#options.classes = this.#defaultClasses; // Use default classes if none provided\n }\n\n if (this.#options.debug) {\n console.log(\"___debug constructor options:\");\n console.log(this.#options);\n }\n\n if (config.fetchFields && Array.isArray(config.fetchFields)) {\n this._setFetchFields(config.fetchFields); // Set fetch fields from user config\n }\n\n // Set default response and error callbacks if not provided\n this.#onDataCallback =\n config.onResponse ||\n ((place) => {\n console.info(\"---------Default onResponse not provided---------\");\n console.info(\"Selected Place:\", JSON.stringify(place, null, 2));\n });\n this.#onErrorCallback =\n config.onError ||\n ((error) => {\n console.error(\"---------Default onError not provided---------\");\n console.error(\"PAC Error:\", error);\n });\n\n if (config.requestParams && Object.keys(config.requestParams).length > 0) {\n this.#request = {\n ...this.#defaultRequestParams,\n ...config.requestParams,\n };\n } else {\n this.#request = { ...this.#defaultRequestParams }; // Use defaults if no requestParams provided\n }\n\n if (this.#options.debug) {\n console.log(\"___debug constructor requestParams:\", this.#request);\n }\n\n this._initialiseDebouncedRequest(); // Initialize the debounced request function\n\n this._init(); // Underscore prefix for internal initialization method\n }\n\n // --- Private Initialization Method ---\n async _init() {\n try {\n // check if google maps api is already loaded\n if (typeof google === \"undefined\" || !google.maps) {\n // Load the Google Maps API dynamically\n await this._loadGoogleMapsApi({\n key: this.#googleMapsApiKey,\n v: this.#googleMapsApiVersion,\n });\n }\n this._createPACStructure();\n await this._initializeAutocomplete();\n } catch (error) {\n this.#onErrorCallback(error);\n }\n }\n\n /**\n * Initializes the debounced request function for fetching autocomplete suggestions.\n *\n * Debounced function to fetch autocomplete suggestions from the Google Places API.\n * Triggered by the 'input' event on the input element.\n *\n *\n */\n _initialiseDebouncedRequest() {\n this._debouncedMakeAcRequest = this._debounce(async () => {\n if (!this.#inputElement || !this.#inputElement.value) {\n this._reset();\n if (this.#inputElement)\n this.#inputElement.setAttribute(\"aria-expanded\", \"false\");\n return;\n }\n\n this.#request.input = this.#inputElement.value;\n\n try {\n const { suggestions } =\n // eslint-disable-next-line no-undef\n await google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions(\n this.#request\n );\n\n // Display suggestions\n if (suggestions && suggestions.length > 0) {\n this.#ul.replaceChildren(\n ...this._createSuggestionElements(suggestions)\n );\n this.#ul.style.display = \"block\";\n this.#inputElement.setAttribute(\"aria-expanded\", \"true\");\n } else {\n // No suggestions found\n this._reset(); // Clear any old suggestions\n this.#inputElement.setAttribute(\"aria-expanded\", \"false\");\n // Optionally display a \"no results\" message in the 'ul'\n }\n } catch (error) {\n this.#onErrorCallback(error);\n this._reset();\n }\n }, this.#options.debounce); // Default debounce to 100ms if not set\n }\n /**\n * Sets the fields to fetch for the selected place.\n * @param {Array<string>} fields - The fields to fetch.\n */\n _setFetchFields(fields) {\n if (Array.isArray(fields) && fields.length > 0) {\n this.#fetchFields = [\n ...new Set([...this.#defaultFetchFields, ...fields]),\n ].filter((e) => e); // Ensure unique and non-empty fields\n }\n }\n\n /**\n * Creates a debounced version of a function.\n * The debounced function delays invoking `func` until after `wait` milliseconds have\n * elapsed since the last time the debounced function was invoked.\n * @param {Function} func - The function to debounce.\n * @param {number} wait - The number of milliseconds to delay.\n * @returns {Function} The new debounced function.\n */\n _debounce(func, wait) {\n if (this.#options.debug) {\n console.log(\"___debug debounce function called with wait:\", wait);\n }\n\n let timeout = null;\n return function executedFunction(...args) {\n const later = () => {\n timeout = null;\n func(...args); // Call original function\n };\n if (timeout !== null) {\n clearTimeout(timeout); // Clear the previous timeout\n }\n timeout = setTimeout(later, wait ?? 100); // Set the new timeout\n };\n }\n /**\n * Formats a distance in meters into kilometers or miles.\n * @param {number | null | undefined} distance - Distance in meters.\n * @param {'km' | 'miles'} units - The desired output units.\n * @returns {string | null} Formatted distance string (e.g., \"1.23 km\") or null if input is invalid.\n */\n _formatDistance(distance, units) {\n if (typeof distance !== \"number\" || !this.#options.distance) {\n return null; // Return null if distance isn't shown or invalid\n }\n let value;\n let unitLabel;\n if (units === \"km\") {\n value = (distance / 1000).toFixed(2);\n unitLabel = \"km\";\n } else {\n // Default to miles if not 'km'\n value = (distance / 1609.34).toFixed(2);\n unitLabel = \"miles\";\n }\n // Avoid showing \".00\"\n value = value.replace(/\\.00$/, \"\");\n return `${value} ${unitLabel}`;\n }\n\n /**\n * Dynamically loads the Google Maps JavaScript API using the importLibrary method.\n * This is the standard approach recommended by Google.\n * @see https://developers.google.com/maps/documentation/javascript/load-maps-js-api\n * @param {object} g - Configuration object for the API loader (key, v, libraries, etc.).\n */\n async _loadGoogleMapsApi(g) {\n var h, // Promise tracking API load\n a, // Script element\n k, // Loop variable for config keys\n p = \"The Google Maps JavaScript API\", // Error message prefix\n c = \"google\", // Global namespace\n l = \"importLibrary\", // Loader function name\n q = \"__ib__\", // Internal callback name\n m = document, // Document reference\n b = window; // Window reference\n b = b[c] || (b[c] = {}); // Ensure google namespace exists\n var d = b.maps || (b.maps = {}), // Ensure google.maps namespace exists\n r = new Set(), // Set to track requested libraries\n e = new URLSearchParams(), // URL parameters for the API script\n u = () =>\n // Function to initiate API loading (if not already started)\n h ||\n // eslint-disable-next-line no-async-promise-executor\n (h = new Promise(async (f, n) => {\n // Create script element (done async to potentially wait for nonce)\n // await (a = m.createElement('script')); // Original Google code had await here, might not be needed\n a = m.createElement(\"script\"); // Create script tag\n e.set(\"libraries\", [...r].join(\",\")); // Add accumulated libraries\n // Add other parameters from the config object 'g'\n for (k in g)\n e.set(\n k.replace(/[A-Z]/g, (t) => \"_\" + t[0].toLowerCase()), // Convert camelCase to snake_case\n g[k]\n );\n e.set(\"callback\", c + \".maps.\" + q); // Set the internal callback function name\n a.src = `https://maps.${c}apis.com/maps/api/js?` + e; // Construct the API URL\n d[q] = f; // Assign the promise resolver to the callback name on google.maps\n // Error handling for script loading failure\n a.onerror = () =>\n (h = n(\n new Error(\n `${p} could not load. Check your API key and network connection.`\n )\n )); // Use onerror for load failures\n // Nonce for Content Security Policy\n a.nonce = m.querySelector(\"script[nonce]\")?.nonce || \"\";\n m.head.append(a); // Append the script to the document head\n }));\n // Define or reuse the importLibrary function on google.maps\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n d[l]\n ? console.warn(p + \" only loads once. Ignoring:\", g) // Warn if called again\n : (d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n))); // The actual importLibrary implementation\n }\n\n // --- UI Creation ---\n _createPACStructure() {\n const section = document.createElement(\"section\");\n section.className = this.#options.classes.section;\n\n // Main container\n this.#container = document.createElement(\"div\");\n this.#container.className = this.#options.classes.container;\n this.#container.setAttribute(\"id\", this.#containerId + \"-div\");\n section.appendChild(this.#container);\n\n // Icon\n const iconContainer = document.createElement(\"div\");\n iconContainer.className = this.#options.classes.icon_container;\n this.#container.appendChild(iconContainer);\n const icon = document.createElement(\"div\");\n icon.innerHTML = this.#options.classes.icon;\n iconContainer.appendChild(icon.firstElementChild); // Append the actual SVG element\n\n // Input field\n this.#inputElement = document.createElement(\"input\");\n this.#inputElement.id = this.#containerId + \"-input\"; // Assign ID for label association\n this.#inputElement.type = \"text\";\n this.#inputElement.name = \"search\"; // Consider making name configurable\n this.#inputElement.placeholder = this.#options.placeholder;\n this.#inputElement.autocomplete = this.#options.autocomplete;\n this.#inputElement.className = this.#options.classes.input;\n this.#inputElement.setAttribute(\"role\", \"combobox\");\n this.#inputElement.setAttribute(\"aria-autocomplete\", \"list\");\n this.#inputElement.setAttribute(\"aria-expanded\", \"false\"); // Will be updated dynamically\n this.#inputElement.setAttribute(\"aria-controls\", \"pacSuggestions\"); // Links to the suggestions list\n this.#inputElement.setAttribute(\"aria-activedescendant\", \"\"); // Will be updated dynamically\n\n if (this.#options.autofocus) {\n this.#inputElement.autofocus = true;\n }\n if (this.#options.label) {\n const label = document.createElement(\"label\");\n label.htmlFor = this.#inputElement.id; // Correctly link label to input by ID\n label.textContent = this.#options.label;\n // Add label classes if needed from opts.classes\n section.prepend(label); // Append label before input or adjust structure\n }\n this.#container.appendChild(this.#inputElement);\n\n // Keyboard hints container\n const kbdContainer = document.createElement(\"div\");\n kbdContainer.className = this.#options.classes.kbd_container;\n this.#kbdEscape = document.createElement(\"kbd\");\n this.#kbdEscape.className = this.#options.classes.kbd_escape;\n this.#kbdEscape.textContent = \"Esc\";\n kbdContainer.appendChild(this.#kbdEscape);\n this.#kbdUp = document.createElement(\"kbd\");\n this.#kbdUp.className = this.#options.classes.kbd_up;\n this.#kbdUp.innerHTML = \"&#8593;\"; // Up arrow HTML entity\n kbdContainer.appendChild(this.#kbdUp);\n this.#kbdDown = document.createElement(\"kbd\");\n this.#kbdDown.className = this.#options.classes.kbd_down;\n this.#kbdDown.innerHTML = \"&#8595;\"; // Down arrow HTML entity\n kbdContainer.appendChild(this.#kbdDown);\n this.#container.appendChild(kbdContainer);\n\n // Suggestions list (initially hidden)\n this.#ul = document.createElement(\"ul\");\n this.#ul.id = \"pacSuggestions\"; // Must match aria-controls\n this.#ul.className = this.#options.classes.ul;\n this.#ul.style.display = \"none\";\n this.#ul.setAttribute(\"role\", \"listbox\");\n this.#ul.setAttribute(\"aria-labelledby\", this.#inputElement.id); // Link listbox to input for accessibility\n this.#container.appendChild(this.#ul);\n\n this.#pacEl.appendChild(section);\n section.addEventListener(\"keydown\", this._onKeyDown.bind(this)); // Bind 'this'\n }\n\n /**\n * Attaches event listeners to the input element for handling user input.\n * This includes debounced input handling, focus/blur events, and keyboard navigation.\n */\n _attachedEventListeners() {\n this.#inputElement.addEventListener(\"input\", this._debouncedMakeAcRequest);\n // Add focus/blur listeners if needed to manage suggestion visibility\n this.#inputElement.addEventListener(\"blur\", () => {\n // Delay hiding suggestions to allow click events on them\n setTimeout(() => {\n if (this.#ul && !this.#ul.contains(document.activeElement)) {\n // Check if focus moved outside suggestions\n this.#ul.style.display = \"none\";\n this.#inputElement.setAttribute(\"aria-expanded\", \"false\");\n }\n }, 200); // Adjust delay as needed\n });\n this.#inputElement.addEventListener(\"focus\", () => {\n // Potentially show suggestions again if input has value\n if (this.#inputElement.value && this.#allSuggestions.length > 0) {\n this.#ul.style.display = \"block\";\n this.#inputElement.setAttribute(\"aria-expanded\", \"true\");\n }\n });\n }\n\n _detachEventListeners() {\n // Remove event listeners, remove elements from DOM\n if (this.#inputElement) {\n this.#inputElement.removeEventListener(\n \"input\",\n this._debouncedMakeAcRequest\n );\n // remove other listeners\n }\n if (this.#pacEl && this.#container) {\n this.#pacEl.removeChild(this.#container.parentElement); // remove the whole section\n }\n }\n\n /**\n * Initializes the core autocomplete functionality after the API is loaded.\n * Imports necessary libraries and sets up the input event listener.\n */\n async _initializeAutocomplete() {\n try {\n // Ensure the 'places' library is available via the dynamic loader\n // eslint-disable-next-line no-undef\n await google.maps.importLibrary(\"places\");\n // console.log('Places library imported successfully.'); // For debugging\n\n // Initial token generation\n this._refreshToken();\n\n // Attach the debounced request function to the input element's 'input' event\n if (this.#inputElement) {\n this._attachedEventListeners();\n } else {\n this.#onErrorCallback(\n new Error(\"Input element not found during initialization.\")\n );\n }\n } catch (error) {\n console.error(\"Error initializing Google Places Autocomplete:\", error);\n // eslint-disable-next-line no-undef\n this.#onErrorCallback(\n new Error(\"Google Maps Places library not available.\")\n );\n }\n }\n\n /**\n * Resets the autocomplete input field, clears suggestions, and optionally refreshes the session token.\n * @param {boolean} [refresh=false] - Whether to refresh the Google Places session token.\n */\n _reset(refresh = false, placeData = null) {\n this.#currentSuggestion = -1;\n\n /**\n * If the input element exists and clear_input is false, set its value to the formatted address\n * from placeData. Otherwise, clear the input value.\n * This allows the user to keep the input value if they selected a place,\n * but still allows clearing it if clear_input is true or placeData is not provided.\n * @type {HTMLInputElement}\n * @property {string} value - The value of the input element.\n * @property {boolean} clear_input - Whether to clear the input value after selection.\n * @property {Object} placeData - The data of the selected place, containing formattedAddress.\n */\n if (\n this.#inputElement &&\n this.#options.clear_input == false &&\n placeData &&\n placeData.formattedAddress\n ) {\n this.#inputElement.value = placeData.formattedAddress; // Set input value to formatted address\n } else if (this.#inputElement) {\n this.#inputElement.value = \"\";\n }\n\n if (this.#inputElement) {\n this.#inputElement.setAttribute(\"aria-expanded\", \"false\");\n this.#inputElement.setAttribute(\"aria-activedescendant\", \"\"); // Clear aria-activedescendant\n this.#inputElement.blur();\n }\n\n this.#allSuggestions = [];\n this.#currentSuggestion = -1;\n if (this.#ul) {\n this.#ul.innerHTML = \"\"; // Clear existing suggestions\n this.#ul.style.display = \"none\";\n }\n if (refresh) {\n this._refreshToken();\n }\n }\n /**\n * Removes the 'current' highlighting classes from all suggestion list items (li) and their links (a).\n */\n _resetLiClasses() {\n if (!this.#ul) return;\n Array.from(this.#ul.children).forEach((li) => {\n this.#options.classes.li_current\n .split(\" \")\n .forEach((cl) => li.classList.remove(cl));\n const link = li.querySelector(\"a\");\n if (link) {\n this.#options.classes.li_a_current\n .split(\" \")\n .forEach((cl) => link.classList.remove(cl));\n }\n });\n }\n\n /**\n * Handles keyboard events (ArrowDown, ArrowUp, Enter, Escape) for navigating\n * and selecting suggestions or closing the list.\n * @param {KeyboardEvent} e - The keyboard event object.\n */\n _onKeyDown(e) {\n this._resetLiClasses(); // Reset classes on any key press within the suggestions\n\n if (e.key === \"Escape\") {\n e.preventDefault();\n // Visual feedback for key press\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdEscape?.classList.add(cl));\n setTimeout(\n () =>\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdEscape?.classList.remove(cl)),\n 300\n );\n\n this._reset(true); // Reset search input and results, refresh token\n }\n\n if (\n !this.#allSuggestions.length ||\n !this.#ul ||\n this.#ul.style.display === \"none\"\n )\n return;\n\n if (e.key === \"ArrowDown\") {\n e.preventDefault(); // Prevent cursor movement in input\n this.#currentSuggestion = Math.min(\n this.#currentSuggestion + 1,\n this.#allSuggestions.length - 1\n );\n if (this.#currentSuggestion < 0) this.#currentSuggestion = 0; // Handle case where it was -1\n\n const currentLi = this.#ul.children.item(this.#currentSuggestion);\n if (currentLi) {\n const currentA = currentLi.querySelector(\"a\");\n this.#options.classes.li_current\n .split(\" \")\n .forEach((cl) => currentLi.classList.add(cl));\n if (currentA) {\n this.#options.classes.li_a_current\n .split(\" \")\n .forEach((cl) => currentA.classList.add(cl));\n }\n currentLi.scrollIntoView({ block: \"nearest\" }); // Ensure visible\n this.#inputElement.setAttribute(\"aria-activedescendant\", currentLi.id); // Update aria-activedescendant\n }\n\n // Visual feedback for key press\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdDown?.classList.add(cl));\n setTimeout(\n () =>\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdDown?.classList.remove(cl)),\n 300\n );\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault(); // Prevent cursor movement in input\n this.#currentSuggestion = Math.max(this.#currentSuggestion - 1, 0); // Stay at 0 if already there\n\n const currentLi = this.#ul.children.item(this.#currentSuggestion);\n if (currentLi) {\n const currentA = currentLi.querySelector(\"a\");\n this.#options.classes.li_current\n .split(\" \")\n .forEach((cl) => currentLi.classList.add(cl));\n if (currentA) {\n this.#options.classes.li_a_current\n .split(\" \")\n .forEach((cl) => currentA.classList.add(cl));\n }\n currentLi.scrollIntoView({ block: \"nearest\" }); // Ensure visible\n }\n\n // Visual feedback for key press\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdUp?.classList.add(cl));\n setTimeout(\n () =>\n this.#options.classes.kbd_active\n .split(\" \")\n .forEach((cl) => this.#kbdUp?.classList.remove(cl)),\n 300\n );\n } else if (e.key === \"Enter\") {\n e.preventDefault(); // Prevent form submission if applicable\n if (\n this.#currentSuggestion >= 0 &&\n this.#currentSuggestion < this.#allSuggestions.length\n ) {\n this._onPlaceSelected(\n this.#allSuggestions[this.#currentSuggestion].place\n );\n // Reset is handled within onPlaceSelected via reset(true)\n }\n }\n }\n\n /**\n * Creates an array of list item (LI) elements for the suggestions dropdown.\n * Each LI contains a link (A) with the place prediction details and distance.\n * Handles highlighting the matched parts of the suggestion text.\n * @param {Array<google.maps.places.AutocompleteSuggestion>} suggestions - Array of suggestion objects from the API.\n * @returns {Array<HTMLLIElement>} An array of LI elements to be added to the suggestions UL.\n */\n _createSuggestionElements(suggestions) {\n this.#allSuggestions = []; // Reset before populating\n return suggestions.map((suggestion, index) => {\n this.#allSuggestions.push({\n id: index + 1,\n description: suggestion.placePrediction.toString(),\n place: suggestion.placePrediction.toPlace(),\n });\n\n // create div elements\n const divContainer = document.createElement(\"div\");\n divContainer.className = this.#options.classes.li_div_container; // flex min-w-0 gap-x-4\n // create inner div element - place name\n const divInner = document.createElement(\"div\");\n divInner.className = this.#options.classes.li_div_one; // min-w-0 flex-auto\n divContainer.appendChild(divInner);\n // create p element - place name\n const p = document.createElement(\"p\");\n p.className = this.#options.classes.li_div_one_p; // text-sm/6\n\n // get prediction text\n const predictionText = suggestion.placePrediction.text;\n const originalText = predictionText.text;\n // Array of objects with startOffset, endOffset\n const matches = predictionText.matches;\n\n //Highlighting Logic\n let lastIndex = 0;\n\n // Sort matches just in case they aren't ordered (though they usually are)\n matches.sort((a, b) => a.startOffset - b.startOffset);\n\n // 1. Create the outer span\n const outerSpan = document.createElement(\"span\");\n\n // 2. Create the inner span for the bold part\n const innerSpan = document.createElement(\"span\");\n innerSpan.classList = this.#options.classes.highlight ?? \"font-bold\"; // Use the highlight class from options\n\n for (const match of matches) {\n // Append text before the current match\n outerSpan.textContent += originalText.substring(\n lastIndex,\n match.startOffset\n );\n\n // Append the highlighted match segment\n if (match.startOffset > 0) {\n // check previous charter is space\n const prevChar = originalText.charAt(match.startOffset - 1);\n if (prevChar == \" \") {\n innerSpan.textContent += \" \";\n }\n }\n innerSpan.textContent += originalText.substring(\n match.startOffset,\n match.endOffset\n );\n\n // Update the last index processed\n lastIndex = match.endOffset;\n }\n\n // 3. Create a text node for the remaining text\n const remainingText = document.createTextNode(\n originalText.substring(lastIndex)\n );\n\n // 4. Append the inner span and the text node to the outer span\n outerSpan.appendChild(innerSpan);\n outerSpan.appendChild(remainingText);\n\n // 5. Append the outer span to the paragraph element\n p.appendChild(outerSpan);\n\n divInner.appendChild(p);\n divContainer.appendChild(divInner);\n\n // create inner div element - distance\n const divInner2 = document.createElement(\"div\");\n divInner2.className = this.#options.classes.li_div_two; //'shrink-0 flex flex-col items-end min-w-16';\n divContainer.appendChild(divInner2);\n // create p element - distance\n const p2 = document.createElement(\"p\");\n p2.className = this.#options.classes.li_div_two_p; //'mt-1 text-xs/5 ';\n p2.textContent = this._formatDistance(\n suggestion.placePrediction.distanceMeters,\n this.#options.distance_units ?? \"km\"\n );\n divInner2.appendChild(p2);\n\n // // create a link element\n const a = document.createElement(\"a\");\n a.href = \"javascript:void(0)\";\n a.tabIndex = index + 1;\n a.className = this.#options.classes.li_a; // block w-full flex justify-between\n\n a.addEventListener(\"click\", () => {\n this._onPlaceSelected(suggestion.placePrediction.toPlace());\n });\n\n // ...\n // a.addEventListener(\"click\", () => {\n // this._fetchPlaceDetails(prediction.place_id);\n // });\n a.appendChild(divContainer);\n a.appendChild(divInner2);\n\n const li = document.createElement(\"li\");\n li.id = `option-${index + 1}`;\n li.className = this.#options.classes.li;\n\n li.appendChild(a);\n return li;\n });\n }\n\n /**\n * Handles the selection of a place. Fetches required fields\n * (displayName, formattedAddress, addressComponents) and calls the\n * user-defined `onPacData` callback.\n * @param {google.maps.places.Place} place - The selected Place object.\n */\n async _onPlaceSelected(place) {\n let data = null;\n try {\n // Fetch necessary details for the selected place\n await place.fetchFields({\n fields: this.#fetchFields, //[\"displayName\", \"formattedAddress\", \"addressComponents\"], // Add more fields as needed\n });\n // Call the user-provided callback with the place data\n // eslint-disable-next-line no-undef\n data = place.toJSON(); // Convert to plain JSON object\n this.#onDataCallback(data); // Convert to plain JSON object for the callback\n } catch (error) {\n console.error(\"Error fetching place details:\", error);\n // eslint-disable-next-line no-undef\n this.#onErrorCallback(error);\n } finally {\n // Reset the input and suggestions regardless of success/error\n this._reset(true, data); // Refresh token after selection\n }\n }\n\n /**\n * Creates a new Google Places Autocomplete Session Token.\n * This should be called before starting a new series of autocomplete requests.\n */\n _refreshToken() {\n try {\n // eslint-disable-next-line no-undef\n this.#request.sessionToken =\n new google.maps.places.AutocompleteSessionToken();\n } catch (error) {\n console.error(\"Error creating session token:\", error);\n // eslint-disable-next-line no-undef\n this.#onErrorCallback(error);\n }\n }\n\n /**\n * Sets the fields to be fetched for the selected place.\n * This allows you to specify which details you want to retrieve\n * when a place is selected, such as displayName, formattedAddress,\n * addressComponents, etc.\n * @param {Array<string>} fields - Array of field names to fetch.\n */\n setFetchFields(fields) {\n this._setFetchFields(fields);\n }\n /**\n * Gets the current fields that will be fetched for the selected place.\n * This is useful for understanding what details will be available\n * when a place is selected, such as displayName, formattedAddress,\n * addressComponents, etc.\n * @returns {Array<string>} The current fetch fields.\n */\n getFetchFields() {\n return this.#fetchFields;\n }\n\n /**\n * Sets the request parameters for the Places Autocomplete instance.\n * This method allows you to update the request parameters dynamically,\n * such as the input value, region codes, language, etc.\n * It merges the provided parameters with the default request parameters,\n * allowing you to override specific values while keeping the defaults intact.\n * This is useful for updating the search criteria without needing to recreate the instance.\n * @param {*} params\n */\n setRequestParams(params) {\n if (\n typeof params === \"object\" &&\n !Array.isArray(params) &&\n params !== null\n ) {\n // if params.input is provided, set it to the input element\n if (params.input && typeof params.input === \"string\") {\n this.#inputElement.value = params.input; // Set input value if provided\n }\n // Merge provided params with default request parameters\n // This allows overriding specific request parameters while keeping defaults\n this.#request = {\n ...this.#defaultRequestParams,\n ...params,\n };\n }\n }\n\n /**\n * Returns the current request parameters used by the Places Autocomplete instance.\n * This includes the input value, included region codes, language, and other settings.\n * It is useful for debugging or when you need to know the current search criteria.\n * @returns {Object} The current request parameters.\n */\n getRequestParams() {\n return this.#request;\n }\n\n /**\n * Sets the options for the Places Autocomplete instance.\n * This method allows you to change the appearance and behavior of the autocomplete widget,\n * such as classes, placeholder text, debounce time, etc.\n * It merges the provided options with the default options, allowing you to override specific values\n * while keeping the defaults intact.\n * This is useful for updating the widget's configuration without needing to recreate the instance.\n * @param {*} options\n */\n setOptions(options) {\n if (\n typeof options === \"object\" &&\n !Array.isArray(options) &&\n options !== null\n ) {\n this._detachEventListeners(); // Detach event listeners\n\n // // Ensure classes are deeply merged if user provides partial classes\n const tmpClasses = options.classes || {};\n delete options.classes; // Remove classes from options to avoid overwriting\n\n // Merge provided options with default options\n // This allows overriding specific options while keeping defaults\n this.#options = {\n ...this.#defaultOptions,\n ...options,\n };\n\n // Merge classes with defaults\n // This allows overriding specific classes while keeping defaults\n if (\n tmpClasses &&\n typeof tmpClasses === \"object\" &&\n Object.keys(tmpClasses).length > 0\n ) {\n this.#options.classes = {\n ...this.#defaultClasses,\n ...tmpClasses,\n };\n } else {\n this.#options.classes = { ...this.#defaultClasses }; // Use defaults if no classes provided\n }\n\n this._initialiseDebouncedRequest(); // Reinitialize the debounced request function\n this._createPACStructure(); // Recreate the structure with new options\n // Reattach the input event listener to the input element\n // This is necessary to ensure the new input element is ready for events\n if (this.#inputElement) {\n this._attachedEventListeners();\n } // Reinitialize the autocomplete functionality\n }\n }\n\n /**\n * Gets the current options used by the Places Autocomplete instance.\n * @returns {Object} The current options.\n */\n getOptions() {\n /**\n * Returns the current options used by the Places Autocomplete instance.\n * This includes classes, placeholder text, debounce time, and other settings.\n * It is useful for debugging or when you need to know the current configuration of the widget.\n * @returns {Object} The current options.\n */\n return this.#options;\n }\n\n /**\n * Clears the autocomplete input field and suggestions list.\n * This method resets the state of the autocomplete widget,\n * allowing the user to start a new search without any previous input or suggestions.\n * It also refreshes the Google Places session token to ensure a new session.\n * @returns {void}\n */\n clear() {\n this._reset(true);\n }\n\n /**\n * Destroys the PacAutocomplete instance.\n * Removes event listeners, clears the DOM, and nullifies properties.\n * This method should be called when the autocomplete widget is no longer needed.\n * It ensures that all resources are cleaned up to prevent memory leaks.\n * @returns {void}\n */\n destroy() {\n // Remove event listeners, remove elements from DOM\n this._detachEventListeners(); // Detach event listeners\n // Nullify properties\n this.#containerId = null;\n this.#pacEl = null;\n this.#googleMapsApiKey = null;\n this.#googleMapsApiVersion = null;\n this.#options = null;\n this.#request = null;\n this.#inputElement = null;\n this.#container = null;\n this.#ul = null;\n this.#kbdEscape = null;\n this.#kbdUp = null;\n this.#kbdDown = null;\n this.#allSuggestions = null;\n this.#currentSuggestion = -1;\n this.#onDataCallback = null;\n this.#onErrorCallback = null;\n this._debouncedMakeAcRequest = null;\n console.log(\"PacAutocomplete instance destroyed.\");\n }\n}\n"],"names":["PlacesAutocomplete","#containerId","#pacEl","#googleMapsApiKey","#googleMapsApiVersion","#options","#request","#inputElement","#container","#ul","#kbdEscape","#kbdUp","#kbdDown","#allSuggestions","#currentSuggestion","#onDataCallback","#onErrorCallback","#defaultOptions","#defaultClasses","#defaultRequestParams","#fetchFields","#defaultFetchFields","config","place","error","suggestions","fields","e","func","wait","timeout","args","later","distance","units","value","unitLabel","g","h","a","k","p","c","l","q","m","b","d","r","u","f","n","t","section","iconContainer","icon","label","kbdContainer","refresh","placeData","li","cl","link","currentLi","currentA","suggestion","index","divContainer","divInner","predictionText","originalText","matches","lastIndex","outerSpan","innerSpan","match","remainingText","divInner2","p2","data","params","options","tmpClasses"],"mappings":"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"}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "places-autocomplete-js",
3
3
  "license": "MIT",
4
4
  "type": "module",
5
- "version": "1.1.2",
5
+ "version": "1.1.3",
6
6
  "description": "A flexible and customisable vanilla JavaScript library leveraging the Google Maps Places (New) Autocomplete API. This library provides a user-friendly way to search for and retrieve detailed address information in any web application.",
7
7
  "keywords": [
8
8
  "place-autocomplete",
@@ -46,6 +46,7 @@
46
46
  ],
47
47
  "main": "./dist/places-autocomplete.umd.cjs",
48
48
  "module": "./dist/places-autocomplete.js",
49
+ "types": "./index.d.ts",
49
50
  "exports": {
50
51
  ".": {
51
52
  "import": "./dist/places-autocomplete.js",
@@ -62,18 +63,18 @@
62
63
  "test": "npm run test:vitest && npm run test:e2e"
63
64
  },
64
65
  "devDependencies": {
65
- "@playwright/test": "^1.55.1",
66
- "@tailwindcss/postcss": "^4.1.14",
67
- "@tailwindcss/vite": "^4.1.14",
68
- "@types/node": "^24.6.2",
69
- "@vitest/ui": "^3.2.4",
66
+ "@playwright/test": "^1.56.1",
67
+ "@tailwindcss/postcss": "^4.1.16",
68
+ "@tailwindcss/vite": "^4.1.16",
69
+ "@types/node": "^24.9.1",
70
+ "@vitest/ui": "^4.0.3",
70
71
  "dotenv": "^17.2.3",
71
- "eslint": "^9.36.0",
72
- "jsdom": "^27.0.0",
73
- "playwright": "^1.55.1",
72
+ "eslint": "^9.38.0",
73
+ "jsdom": "^27.0.1",
74
+ "playwright": "^1.56.1",
74
75
  "postcss": "^8.5.6",
75
- "tailwindcss": "^4.1.14",
76
- "vite": "^7.1.8",
77
- "vitest": "^3.2.4"
76
+ "tailwindcss": "^4.1.16",
77
+ "vite": "^7.1.12",
78
+ "vitest": "^4.0.3"
78
79
  }
79
80
  }