├── .env ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── pull_request_template.md ├── .gitignore ├── .husky └── pre-commit ├── .lintstagedrc.json ├── .prettierrc ├── .vscode └── extensions.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── create-cdn-pr.sh ├── deno.lock ├── eslint.config.js ├── examples ├── leaflet │ ├── AppLeaflet.svelte │ ├── index.html │ └── main.ts ├── maplibregl │ ├── AppMapLibreGl.svelte │ ├── index.html │ └── main.ts ├── maptiler-sdk │ ├── AppMapTilerSdk.svelte │ ├── index.html │ └── main.ts ├── openlayers │ ├── AppOpenLayers.svelte │ ├── index.html │ └── main.ts ├── react │ ├── index.html │ ├── main.tsx │ └── style.css ├── standalone │ ├── leaflet.html │ ├── maplibregl.html │ └── ol.html └── vanilla │ ├── AppVanilla.svelte │ ├── index.html │ └── main.ts ├── images ├── JS-logo.svg ├── TS-logo.svg ├── maptiler-client-logo.svg ├── maptiler-logo-256.png ├── maptiler-logo.svg ├── react-logo.svg └── svelte-logo.svg ├── index.html ├── package-lock.json ├── package.json ├── public └── icons │ ├── 10pin.svg │ ├── 9pin.svg │ ├── advertising_column.svg │ ├── aerodrome.svg │ ├── alcohol.svg │ ├── alpine_hut.svg │ ├── amusement_arcade.svg │ ├── amusement_park.svg │ ├── apartment.svg │ ├── archaeological_site.svg │ ├── area.svg │ ├── art.svg │ ├── arts_centre.svg │ ├── artwork.svg │ ├── audioguide.svg │ ├── bag.svg │ ├── beauty.svg │ ├── bed.svg │ ├── bell_tower.svg │ ├── beverages.svg │ ├── bicycle_repair_station.svg │ ├── biergarten.svg │ ├── bird_hide.svg │ ├── boat_rental.svg │ ├── bookmaker.svg │ ├── books.svg │ ├── bowl.svg │ ├── bowling_alley.svg │ ├── bunker.svg │ ├── bureau_de_change.svg │ ├── bus_station.svg │ ├── bust.svg │ ├── camping.svg │ ├── car_parts.svg │ ├── car_wash.svg │ ├── caravan_park.svg │ ├── carpet.svg │ ├── cattle_grid.svg │ ├── cave_entrance.svg │ ├── chalet.svg │ ├── charity.svg │ ├── chemist.svg │ ├── chimney.svg │ ├── church.svg │ ├── city_gate.svg │ ├── clinic.svg │ ├── clothes.svg │ ├── coffee.svg │ ├── community_centre.svg │ ├── computer.svg │ ├── consulate.svg │ ├── copyshop.svg │ ├── cosmetics.svg │ ├── courthouse.svg │ ├── crane.svg │ ├── dairy.svg │ ├── deli.svg │ ├── department_store.svg │ ├── diy.svg │ ├── electronics.svg │ ├── embankment.svg │ ├── embassy.svg │ ├── excrement_bags.svg │ ├── fabric.svg │ ├── farmyard.svg │ ├── ferry.svg │ ├── firepit.svg │ ├── firestation.svg │ ├── fishing.svg │ ├── fitness.svg │ ├── ford.svg │ ├── fort.svg │ ├── fortress.svg │ ├── full-height_turnstile.svg │ ├── generator_wind.svg │ ├── golf_pin.svg │ ├── greengrocer.svg │ ├── guest_house.svg │ ├── helipad.svg │ ├── hifi.svg │ ├── hostel.svg │ ├── hotel.svg │ ├── housenumber.svg │ ├── houseware.svg │ ├── hunting_stand.svg │ ├── interior_decoration.svg │ ├── internet_cafe.svg │ ├── kindergarten.svg │ ├── kissing_gate.svg │ ├── manor.svg │ ├── map.svg │ ├── marker_reverse.svg │ ├── marker_selected.svg │ ├── marker_unselected.svg │ ├── marketplace.svg │ ├── massage.svg │ ├── mast.svg │ ├── mast_communications.svg │ ├── mast_lighting.svg │ ├── medical_supply.svg │ ├── memorial.svg │ ├── miniature_golf.svg │ ├── motel.svg │ ├── mountain_range.svg │ ├── multifaith.svg │ ├── musical_instrument.svg │ ├── newsagent.svg │ ├── nightclub.svg │ ├── ocean.svg │ ├── office.svg │ ├── outdoor_seating.svg │ ├── palace.svg │ ├── parcel_locker.svg │ ├── parking_space.svg │ ├── parking_tickets.svg │ ├── pet.svg │ ├── photo.svg │ ├── picnic.svg │ ├── plaque.svg │ ├── poi.svg │ ├── post_box.svg │ ├── post_office.svg │ ├── postal_code.svg │ ├── pub.svg │ ├── public_bath.svg │ ├── public_bookcase.svg │ ├── public_building.svg │ ├── public_transport_tickets.svg │ ├── reverse.svg │ ├── river.svg │ ├── road.svg │ ├── saddle.svg │ ├── sauna.svg │ ├── sea.svg │ ├── second_hand.svg │ ├── shintoist.svg │ ├── shoe.svg │ ├── shower.svg │ ├── shrine.svg │ ├── sikhist.svg │ ├── slipway.svg │ ├── snowmobile.svg │ ├── social_facility.svg │ ├── sports.svg │ ├── sprite.json │ ├── sprite.png │ ├── sprite@2x.json │ ├── sprite@2x.png │ ├── stationery.svg │ ├── stile.svg │ ├── stone.svg │ ├── storage_tank.svg │ ├── stream.svg │ ├── street.svg │ ├── supermarket.svg │ ├── tea.svg │ ├── telescope_dish.svg │ ├── telescope_dome.svg │ ├── ticket.svg │ ├── tobacco.svg │ ├── tower_cantilever_communication.svg │ ├── tower_cooling.svg │ ├── tower_dish.svg │ ├── tower_dome.svg │ ├── tower_generic.svg │ ├── tower_lattice.svg │ ├── tower_lattice_communication.svg │ ├── tower_lattice_lighting.svg │ ├── tower_lighting.svg │ ├── townhall.svg │ ├── toys.svg │ ├── trade.svg │ ├── traffic_light.svg │ ├── train_station.svg │ ├── travel_agency.svg │ ├── tyres.svg │ ├── university.svg │ ├── variety_store.svg │ ├── vehicle_inspection.svg │ ├── vending_machine.svg │ ├── video.svg │ ├── video_games.svg │ ├── waste_disposal.svg │ ├── water_well.svg │ ├── waterfall.svg │ └── wilderness_hut.svg ├── replace-env-vars.js ├── src ├── ClearIcon.svelte ├── FailIcon.svelte ├── FeatureItem.svelte ├── GeocodingControl.svelte ├── LoadingIcon.svelte ├── MapLibreBasedGeocodingControl.ts ├── MarkerIcon.svelte ├── ReverseGeocodingIcon.svelte ├── SearchIcon.svelte ├── geo-coordinates-parser.t.ts ├── geoUtils.ts ├── leaflet-controller.ts ├── leaflet.ts ├── maplibregl-controller.ts ├── maplibregl.ts ├── maptilersdk.ts ├── mask.ts ├── openlayers-controller.ts ├── openlayers.ts ├── proximity.ts ├── react.ts ├── types.ts ├── vanilla.ts └── vite-env.d.ts ├── svelte.config.js ├── sync-info.js ├── tsconfig.dist.json ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts /.env: -------------------------------------------------------------------------------- 1 | VITE_API_URL=https://api.maptiler.com/geocoding 2 | VITE_LIB_VERSION=$npm_package_version 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: "" 6 | assignees: zdila 7 | --- 8 | 9 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **To Reproduce** 13 | Steps to reproduce the behavior and browser identification. 14 | 15 | **Expected behavior** 16 | A clear and concise description of what you expected to happen. 17 | 18 | **Screenshots** 19 | If applicable, add screenshots to help explain your problem. 20 | 21 | **Additional context** 22 | Add any other context about the problem here. 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[FEATURE]" 5 | labels: "" 6 | assignees: jachym 7 | --- 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Describe alternatives you've considered** 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | 18 | **Additional context** 19 | Add any other context or screenshots about the feature request here. 20 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | GO-XXX 2 | 3 | ## Objective 4 | What is the goal? 5 | 6 | ## Description 7 | What changed, how and why? 8 | 9 | ### Acceptance 10 | How were changes tested? 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist.svelte 13 | *.local 14 | .svelte-kit 15 | 16 | # Editor directories and files 17 | .vscode/* 18 | !.vscode/extensions.json 19 | .idea 20 | .DS_Store 21 | *.suo 22 | *.ntvs* 23 | *.njsproj 24 | *.sln 25 | *.sw? 26 | 27 | *.tgz 28 | src/info.json 29 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | npm exec -- lint-staged 2 | -------------------------------------------------------------------------------- /.lintstagedrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "*": ["prettier --check"], 3 | "*.{ts,svelte}": ["eslint"] 4 | } 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["prettier-plugin-svelte", "prettier-plugin-organize-imports"], 3 | "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }], 4 | "organizeImportsSkipDestructiveCodeActions": true 5 | } 6 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["svelte.svelte-vscode"] 3 | } 4 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | - Using welcoming and inclusive language 12 | - Being respectful of differing viewpoints and experiences 13 | - Gracefully accepting constructive criticism 14 | - Focusing on what is best for the community 15 | - Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | - The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | - Trolling, insulting/derogatory comments, and personal or political attacks 21 | - Public or private harassment 22 | - Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | - Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the MapTiler support team at `support [at] maptiler.com` . The support team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The support team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: https://contributor-covenant.org 46 | [version]: https://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | Thank you for considering contributing to MapTiler Geocoding Control package. It's people 4 | like you that make it to great tool. 5 | 6 | ### Where do I go from here? 7 | 8 | If you've noticed a bug or have a feature request, [make one](https://github.com/maptiler/maptiler-geocoding-control/issues/new/choose)! It's 9 | generally best if you get confirmation of your bug or approval for your feature 10 | request this way before starting to code. 11 | 12 | If you have a general question about MapTiler Geocoding Control, you can reach out to the 13 | [MapTiler documentation portal](https://documentation.maptiler.com/hc/en-us/search?query=geocoding) 14 | or contact [our support](https://documentation.maptiler.com/hc/en-us/requests/new), the issue tracker is only for bugs and feature requests. 15 | 16 | ### Fork & create a branch 17 | 18 | If this is something you think you can fix, then [create the fork](https://github.com/maptiler/maptiler-geocoding-control/fork) and create 19 | a branch with a descriptive name. 20 | 21 | A good branch name would be (where issue #325 is the ticket you're working on): 22 | 23 | ```sh 24 | git checkout -b 325-add-poi-filter 25 | ``` 26 | 27 | ### Get the test suite running 28 | 29 | Make sure you're using a recent version of NodeJS. 30 | 31 | Install the development dependencies: 32 | 33 | ```sh 34 | npm install 35 | ``` 36 | 37 | Then run the development mode, make sure, you export the [MapTiler Key](https://docs.maptiler.com/cloud/api/authentication-key/) as environment variable 38 | 39 | ```sh 40 | VITE_API_KEY=YOUR_MAPTILER_API_KEY_HERE npm run dev 41 | ``` 42 | 43 | ### Implement your fix or feature 44 | 45 | At this point, you're ready to make your changes! Feel free to ask for help; 46 | everyone is a beginner at first :smile_cat: 47 | 48 | ### Make a Pull Request 49 | 50 | At this point, you should switch back to your master branch and make sure it's 51 | up to date with MapTiler Geocoding Control main branch: 52 | 53 | ```sh 54 | git remote add upstream git@github.com:maptiler/maptiler-geocoding-control.git 55 | git checkout main 56 | git pull upstream main 57 | ``` 58 | 59 | Then update your feature branch from your local copy of master, and push it! 60 | 61 | ```sh 62 | git checkout 325-add-poi-filter 63 | git rebase main 64 | git push --set-upstream origin 325-add-poi-filter 65 | ``` 66 | 67 | Finally, go to GitHub and [make a Pull Request](https://github.com/maptiler/maptiler-geocoding-control/compare) 68 | 69 | ## Final word 70 | 71 | Thank you one more time for your contribution. We try to deliver best user experience of geocoding, your contribution 72 | will make better experience to all users! 73 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2023, MapTiler 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | official page →
3 | 4 |

5 | 6 |

7 | The Javascript & TypeScript Map Control component for MapTiler Geocoding service! Easy to be integrated into any JavaScript mapping application. 8 |

9 | 10 |

11 | 12 | 13 | 14 | 15 | 16 | 17 |

18 | 19 | # MapTiler Geocoding control for MapTiler SDK, MapLibre GL JS, Leaflet and OpenLayers 20 | 21 | ## About 22 | 23 | A _Geocoding control_ for [MapTiler SDK](https://github.com/maptiler/maptiler-sdk-js), 24 | [MapLibre GL JS](https://github.com/maplibre/maplibre-gl-js), 25 | [Leaflet](https://leafletjs.com) and [OpenLayers](https://openlayers.org) utilizes [MapTiler Cloud Geocoding 26 | API](https://www.maptiler.com/cloud/geocoding/). With this control, users of 27 | mapping application can find any place on Earth (States, Cities, Streets, Addresses, POIs, ...) down 28 | to the address level, restrict the search area to a specific country, highlight 29 | searched results on the map, autocomplete words while typing, and much more. 30 | 31 | The component can be used as an ES module or UMD module with or without bundler. 32 | 33 | Geocoding control is also provided as [React component](https://docs.maptiler.com/sdk-js/modules/geocoding/api/usage/react/) and [Svelte component](https://docs.maptiler.com/sdk-js/modules/geocoding/api/usage/svelte/) and [other libraries](#installation-and-more-usage-examples). 34 | 35 | ## Quick start 36 | 37 | Install the Geocoding control unsing `npm`: 38 | 39 | **⚠️ Warning! ⚠️** 40 | 41 | The current version of Geocoding Control is only compatible with Svelte v4, this will potentially cause peer dependency issues when installing with certain versions of npm in Svelte projects (eg if you're using Svelte v5), or if you intend to import the Svelte component directly. 42 | 43 | If you are using a this library in a Svelte project you can npm install with `--force` or `--legacy-peer-deps` and use only the **pre-compiled `GeoLocatControl` vanilla module**, not the Svelte component. 44 | 45 | ```shell 46 | npm install --save @maptiler/geocoding-control @maptiler/sdk 47 | ``` 48 | 49 | Use the component in your mapping application: 50 | 51 | ```js 52 | import * as maptilersdk from "@maptiler/sdk"; 53 | import { GeocodingControl } from "@maptiler/geocoding-control/maptilersdk"; 54 | import "@maptiler/sdk/dist/maptiler-sdk.css"; 55 | import "@maptiler/geocoding-control/style.css"; 56 | 57 | maptilersdk.config.apiKey = "YOUR_MAPTILER_API_KEY_HERE"; 58 | 59 | const map = new maptilersdk.Map({ 60 | container: "map", // id of HTML container element 61 | }); 62 | 63 | const gc = new GeocodingControl(); 64 | 65 | map.addControl(gc); 66 | ``` 67 | 68 | NOTE: Get your personal [MapTiler API key](https://docs.maptiler.com/cloud/api/authentication-key/) in the [MapTiler Cloud](https://cloud.maptiler.com). 69 | 70 | ## Installation and more usage examples 71 | 72 | - [With MapTiler SDK](https://docs.maptiler.com/sdk-js/modules/geocoding/api/usage/sdk-js/) 73 | - [With MapLibre GL](https://docs.maptiler.com/sdk-js/modules/geocoding/api/usage/maplibre-gl-js/) 74 | - [With Leaflet](https://docs.maptiler.com/sdk-js/modules/geocoding/api/usage/leaflet/) 75 | - [With OpenLayers](https://docs.maptiler.com/sdk-js/modules/geocoding/api/usage/openlayers/) 76 | - [As a React component](https://docs.maptiler.com/sdk-js/modules/geocoding/api/usage/react/) 77 | - [As Svelte component](https://docs.maptiler.com/sdk-js/modules/geocoding/api/usage/svelte/) 78 | - [As vanilla JavaScript module](https://docs.maptiler.com/sdk-js/modules/geocoding/api/usage/vanilla-js/) 79 | 80 | ## API Documentation 81 | 82 | In addition to the details and examples provided in this `README.md` and our documentation, check out 83 | 84 | - [The complete Geocoding service API documentation](https://docs.maptiler.com/cloud/api/geocoding/) 85 | - [The complete Geocoding control reference](https://docs.maptiler.com/sdk-js/modules/geocoding/api/api-reference/) 86 | - [UMD global variables](https://docs.maptiler.com/sdk-js/modules/geocoding/#umd-global-variables) 87 | 88 | ## Development 89 | 90 | ### Building 91 | 92 | ```bash 93 | npm install && npm run build 94 | ``` 95 | 96 | You will find compilation result in the `dist` directory. 97 | 98 | ### Running in dev mode 99 | 100 | ```bash 101 | npm install && VITE_API_KEY=YOUR_MAPTILER_API_KEY_HERE npm run dev 102 | ``` 103 | 104 | ### POI icons and bundlers 105 | 106 | POI icons are served from CDN per default. If there is an requirement to serve them from a different location and the control is used in the application which is built with Web Application bundler (like Webpack or Vite) then it is necessary to do some extra configuration. Icons are bundled in the library and you can find them in `node_modules/@maptiler/geocoding-control/icons`. Configure your bundler and/or provide `iconsBaseUrl` option for the icons to be properly resolved. You can also copy icons from that directory to your `public` directory. 107 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Following versions are supported with security updateds: 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | 0.0.x | :white_check_mark: | 10 | 11 | ## Reporting a Vulnerability 12 | 13 | To report Vulnerability, add [new issue](https://github.com/maptiler/maptiler-geocoding-control/issues/new/choose) to the issues tracker 14 | -------------------------------------------------------------------------------- /create-cdn-pr.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | export GIT_WORK_TREE=../cdn.maptiler.com 5 | export GIT_DIR=$GIT_WORK_TREE/.git 6 | 7 | git checkout main 8 | 9 | git pull 10 | 11 | VERSION=$npm_package_version 12 | 13 | git checkout -b maptiler-geocoding-control-$VERSION 14 | 15 | BASE=../cdn.maptiler.com/maptiler-geocoding-control 16 | 17 | mkdir -p $BASE/v$VERSION 18 | 19 | cp -r dist/* $BASE/v$VERSION 20 | 21 | ln -sfn v$VERSION $BASE/latest 22 | 23 | git add maptiler-geocoding-control/v$VERSION maptiler-geocoding-control/latest 24 | 25 | git reset maptiler-geocoding-control/v$VERSION/*.tgz 26 | 27 | git commit -m "Add maptiler-geocoding-control v$VERSION" 28 | 29 | gh pr create --base main --fill --repo maptiler/cdn.maptiler.com 30 | -------------------------------------------------------------------------------- /deno.lock: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4", 3 | "redirects": { 4 | "https://cdn.skypack.dev/chroma-js": "https://cdn.skypack.dev/new/chroma-js@v3.1.2/dist=es2019", 5 | "https://cdn.skypack.dev/new/chroma-js@v3.1.2/dist=es2019": "https://cdn.skypack.dev/error/build:chroma-js@v3.1.2-QwkMr4VCpNO0CLkbGUyZ" 6 | }, 7 | "remote": { 8 | "https://cdn.skypack.dev/error/build:chroma-js@v3.1.2-QwkMr4VCpNO0CLkbGUyZ": "97aee30af87a5f6905a6af1a3eb1ed523426de337cf7d92ed3604a6b289eca8b" 9 | }, 10 | "workspace": { 11 | "packageJson": { 12 | "dependencies": [ 13 | "npm:@maptiler/sdk@^2.5.0", 14 | "npm:@sveltejs/package@^2.3.7", 15 | "npm:@sveltejs/vite-plugin-svelte@^3.1.2", 16 | "npm:@tsconfig/svelte@^5.0.4", 17 | "npm:@turf/bbox@^7.1.0", 18 | "npm:@turf/clone@^7.1.0", 19 | "npm:@turf/difference@^7.1.0", 20 | "npm:@turf/flatten@^7.1.0", 21 | "npm:@turf/union@^7.1.0", 22 | "npm:@types/geojson@^7946.0.15", 23 | "npm:@types/leaflet@^1.9.15", 24 | "npm:@types/node@^22.10.1", 25 | "npm:@types/react-dom@^19.0.2", 26 | "npm:@types/react@^19.0.1", 27 | "npm:concurrently@^9.1.0", 28 | "npm:dotenv@^16.4.7", 29 | "npm:eslint-plugin-svelte@^2.46.1", 30 | "npm:eslint@^9.16.0", 31 | "npm:esm-env@^1.2.1", 32 | "npm:geo-coordinates-parser@^1.7.4", 33 | "npm:globals@^15.13.0", 34 | "npm:husky@^9.1.7", 35 | "npm:leaflet@^1.9.4", 36 | "npm:lint-staged@^15.2.11", 37 | "npm:maplibre-gl@^4.7.1", 38 | "npm:ol@10.3", 39 | "npm:prettier-plugin-organize-imports@^4.1.0", 40 | "npm:prettier-plugin-svelte@^3.3.2", 41 | "npm:prettier@^3.4.2", 42 | "npm:react-dom@19", 43 | "npm:react@19", 44 | "npm:replace-in-file@^8.2.0", 45 | "npm:sass@^1.82.0", 46 | "npm:svelte-check@^4.1.1", 47 | "npm:svelte-preprocess@^6.0.3", 48 | "npm:svelte@^4.2.19", 49 | "npm:tslib@^2.8.1", 50 | "npm:typescript-eslint@^8.18.0", 51 | "npm:typescript@^5.7.2", 52 | "npm:vite@^5.4.11" 53 | ] 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from "@eslint/js"; 2 | import tsParser from "@typescript-eslint/parser"; 3 | import eslintPluginSvelte from "eslint-plugin-svelte"; 4 | import globals from "globals"; 5 | import svelteParser from "svelte-eslint-parser"; 6 | import tsEslint from "typescript-eslint"; 7 | 8 | export default [ 9 | js.configs.recommended, 10 | ...tsEslint.configs.strict, 11 | ...eslintPluginSvelte.configs["flat/recommended"], 12 | ...eslintPluginSvelte.configs["flat/prettier"], 13 | { 14 | rules: { 15 | "no-undef": "off", 16 | "@typescript-eslint/no-unused-vars": [ 17 | "error", 18 | { ignoreRestSiblings: true }, 19 | ], 20 | // TODO for the reason of next 2 rules see https://github.com/eslint/eslint/issues/19134#issuecomment-2480588649 21 | "@typescript-eslint/no-unused-expressions": [ 22 | "error", 23 | { 24 | allowShortCircuit: true, 25 | allowTernary: true, 26 | }, 27 | ], 28 | "@typescript-eslint/no-empty-function": [ 29 | "error", 30 | { allow: ["arrowFunctions"] }, 31 | ], 32 | }, 33 | }, 34 | { 35 | ignores: [ 36 | "dist/", 37 | "dist.svelte/", 38 | ".svelte-kit/", 39 | "replace-env-vars.js", 40 | "eslint.config.js", 41 | "svelte.config.js", 42 | ], 43 | }, 44 | { 45 | files: ["**/*.svelte"], 46 | languageOptions: { 47 | ecmaVersion: 2022, 48 | sourceType: "module", 49 | globals: { 50 | ...globals.browser, 51 | RequestInit: false, 52 | }, 53 | parser: svelteParser, 54 | parserOptions: { 55 | parser: tsParser, 56 | // project: true, 57 | extraFileExtensions: [".svelte"], 58 | }, 59 | }, 60 | }, 61 | ]; 62 | -------------------------------------------------------------------------------- /examples/leaflet/AppLeaflet.svelte: -------------------------------------------------------------------------------- 1 | 63 | 64 |
65 | 66 | 72 | -------------------------------------------------------------------------------- /examples/leaflet/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MapTiler Geocoding Control :: Leaflet 6 | 7 |
8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/leaflet/main.ts: -------------------------------------------------------------------------------- 1 | import App from "./AppLeaflet.svelte"; 2 | 3 | const appElement = document.getElementById("app"); 4 | 5 | if (!appElement) { 6 | throw new Error("element with id 'app' not found"); 7 | } 8 | 9 | export default new App({ target: appElement }); 10 | -------------------------------------------------------------------------------- /examples/maplibregl/AppMapLibreGl.svelte: -------------------------------------------------------------------------------- 1 | 81 | 82 |
83 | 84 | 90 | -------------------------------------------------------------------------------- /examples/maplibregl/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MapTiler Geocoding Control :: MapLibre GL JS 6 | 7 |
8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/maplibregl/main.ts: -------------------------------------------------------------------------------- 1 | import App from "./AppMapLibreGl.svelte"; 2 | 3 | const appElement = document.getElementById("app"); 4 | 5 | if (!appElement) { 6 | throw new Error("element with id 'app' not found"); 7 | } 8 | 9 | export default new App({ target: appElement }); 10 | -------------------------------------------------------------------------------- /examples/maptiler-sdk/AppMapTilerSdk.svelte: -------------------------------------------------------------------------------- 1 | 53 | 54 |
55 | 56 | 62 | -------------------------------------------------------------------------------- /examples/maptiler-sdk/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MapTiler Geocoding Control :: MapTiler SDK 6 | 7 |
8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/maptiler-sdk/main.ts: -------------------------------------------------------------------------------- 1 | import App from "./AppMapTilerSdk.svelte"; 2 | 3 | const appElement = document.getElementById("app"); 4 | 5 | if (!appElement) { 6 | throw new Error("element with id 'app' not found"); 7 | } 8 | 9 | export default new App({ target: appElement }); 10 | -------------------------------------------------------------------------------- /examples/openlayers/AppOpenLayers.svelte: -------------------------------------------------------------------------------- 1 | 57 | 58 |
59 | 60 | 72 | -------------------------------------------------------------------------------- /examples/openlayers/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MapTiler Geocoding Control :: OpenLayers 6 | 7 |
8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/openlayers/main.ts: -------------------------------------------------------------------------------- 1 | import App from "./AppOpenLayers.svelte"; 2 | 3 | const appElement = document.getElementById("app"); 4 | 5 | if (!appElement) { 6 | throw new Error("element with id 'app' not found"); 7 | } 8 | 9 | export default new App({ target: appElement }); 10 | -------------------------------------------------------------------------------- /examples/react/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | MapTiler Geocoding Control :: React 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/react/style.css: -------------------------------------------------------------------------------- 1 | html, 2 | body, 3 | main { 4 | height: 100%; 5 | background-color: #eee; 6 | } 7 | 8 | main { 9 | padding: 1em; 10 | display: flex; 11 | flex-direction: column; 12 | } 13 | 14 | .control-bar { 15 | display: flex; 16 | gap: 0.5em; 17 | align-items: center; 18 | flex-wrap: wrap; 19 | } 20 | 21 | .flex-grow { 22 | flex-grow: 1; 23 | } 24 | 25 | .overflow-auto { 26 | overflow: auto; 27 | } 28 | 29 | .logs { 30 | display: grid; 31 | column-gap: 1em; 32 | grid-template-columns: auto 1fr; 33 | height: 0px; /* fixes overflow */ 34 | } 35 | 36 | .logs > div:nth-child(2n) { 37 | text-wrap: nowrap; 38 | color: blue; 39 | } 40 | 41 | select { 42 | margin-right: 2ex; 43 | } 44 | 45 | button.is-small { 46 | padding: 4px 8px; 47 | font-size: 0.8em; 48 | } 49 | -------------------------------------------------------------------------------- /examples/standalone/leaflet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 11 | 12 | 13 | 21 | 22 | 28 | 29 |
30 | 31 | 68 | -------------------------------------------------------------------------------- /examples/standalone/maplibregl.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 11 | 12 | 13 | 21 | 22 | 28 | 29 |
30 | 31 | 68 | -------------------------------------------------------------------------------- /examples/standalone/ol.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 19 | 20 | 32 | 33 |
34 | 35 | 76 | -------------------------------------------------------------------------------- /examples/vanilla/AppVanilla.svelte: -------------------------------------------------------------------------------- 1 | 26 | 27 |
28 | -------------------------------------------------------------------------------- /examples/vanilla/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MapTiler Geocoding Control :: Vanilla JS 6 | 7 |
8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/vanilla/main.ts: -------------------------------------------------------------------------------- 1 | import App from "./AppVanilla.svelte"; 2 | 3 | const appElement = document.getElementById("app"); 4 | 5 | if (!appElement) { 6 | throw new Error("element with id 'app' not found"); 7 | } 8 | 9 | export default new App({ target: appElement }); 10 | -------------------------------------------------------------------------------- /images/JS-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /images/TS-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | TypeScript logo 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /images/maptiler-logo-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maptiler/maptiler-geocoding-control/e8b4d65286d75c9dd906f24c554c42582ae71b91/images/maptiler-logo-256.png -------------------------------------------------------------------------------- /images/maptiler-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /images/react-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | React Logo 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /images/svelte-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 12 | 20 | 21 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | MapTiler Geocoding Control 11 | 12 |

MapTiler Geocoding Control Examples

13 | 14 |

Svelte

15 | 22 | 23 |

React

24 | 31 | 32 |

Vanilla JS (UMD)

33 | 34 |

35 | Before opening the following examples first build the library with 36 | npm run build. 37 |

38 | 39 | 44 | -------------------------------------------------------------------------------- /public/icons/10pin.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/icons/9pin.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/icons/advertising_column.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/aerodrome.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/alcohol.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/alpine_hut.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/amusement_arcade.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/amusement_park.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/apartment.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/icons/archaeological_site.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/area.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/art.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/arts_centre.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/artwork.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/icons/audioguide.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/bag.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/beauty.svg: -------------------------------------------------------------------------------- 1 | 2 | 9 | 11 | 14 | 15 | -------------------------------------------------------------------------------- /public/icons/bed.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/bell_tower.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/beverages.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/bicycle_repair_station.svg: -------------------------------------------------------------------------------- 1 | 2 | 9 | 11 | 14 | 18 | 19 | -------------------------------------------------------------------------------- /public/icons/biergarten.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/icons/bird_hide.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/boat_rental.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/bookmaker.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/books.svg: -------------------------------------------------------------------------------- 1 | 2 | 9 | 11 | 14 | 15 | -------------------------------------------------------------------------------- /public/icons/bowl.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/icons/bowling_alley.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/icons/bunker.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/bureau_de_change.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/bus_station.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/bust.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/camping.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/car_parts.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/car_wash.svg: -------------------------------------------------------------------------------- 1 | 2 | 9 | 11 | 15 | 19 | 20 | -------------------------------------------------------------------------------- /public/icons/caravan_park.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/carpet.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/cattle_grid.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/cave_entrance.svg: -------------------------------------------------------------------------------- 1 | 2 | 9 | 11 | 15 | 16 | -------------------------------------------------------------------------------- /public/icons/chalet.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/charity.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/chemist.svg: -------------------------------------------------------------------------------- 1 | 2 | 9 | 11 | 14 | 15 | -------------------------------------------------------------------------------- /public/icons/chimney.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/church.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/icons/city_gate.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/clinic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/clothes.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/coffee.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/community_centre.svg: -------------------------------------------------------------------------------- 1 | 2 | 11 | 13 | 20 | 21 | -------------------------------------------------------------------------------- /public/icons/computer.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/consulate.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/copyshop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /public/icons/cosmetics.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/courthouse.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/crane.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/dairy.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/deli.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/department_store.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/diy.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/electronics.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/embankment.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/embassy.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/excrement_bags.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/fabric.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/farmyard.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /public/icons/ferry.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/firepit.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/firestation.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/icons/fishing.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/fitness.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/ford.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/fort.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/fortress.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/full-height_turnstile.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/generator_wind.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/golf_pin.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/greengrocer.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/guest_house.svg: -------------------------------------------------------------------------------- 1 | 2 | 11 | 15 | 21 | 22 | 24 | 26 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /public/icons/helipad.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/hifi.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/hostel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/hotel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/housenumber.svg: -------------------------------------------------------------------------------- 1 | 2 | 10 | 12 | 15 | 20 | 21 | -------------------------------------------------------------------------------- /public/icons/houseware.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/hunting_stand.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/interior_decoration.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/internet_cafe.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/kindergarten.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/kissing_gate.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/manor.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/map.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /public/icons/marker_reverse.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /public/icons/marker_selected.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /public/icons/marker_unselected.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /public/icons/marketplace.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/massage.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/mast.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/mast_communications.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/mast_lighting.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/medical_supply.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 20 | 21 | -------------------------------------------------------------------------------- /public/icons/memorial.svg: -------------------------------------------------------------------------------- 1 | 2 | 9 | 11 | 14 | 15 | -------------------------------------------------------------------------------- /public/icons/miniature_golf.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/motel.svg: -------------------------------------------------------------------------------- 1 | 2 | 9 | 11 | 15 | 19 | 20 | -------------------------------------------------------------------------------- /public/icons/mountain_range.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 7 | 10 | 13 | 15 | 18 | 21 | 23 | 26 | 27 | -------------------------------------------------------------------------------- /public/icons/multifaith.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/musical_instrument.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/newsagent.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/nightclub.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/ocean.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /public/icons/office.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/outdoor_seating.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/palace.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/parcel_locker.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /public/icons/parking_space.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/parking_tickets.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/pet.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/photo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/picnic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/plaque.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/poi.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /public/icons/post_box.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/post_office.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/postal_code.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/pub.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /public/icons/public_bath.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/public_bookcase.svg: -------------------------------------------------------------------------------- 1 | 2 | 9 | 11 | 14 | 15 | -------------------------------------------------------------------------------- /public/icons/public_building.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/icons/public_transport_tickets.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/reverse.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /public/icons/river.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/icons/road.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /public/icons/saddle.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/sauna.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/sea.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /public/icons/second_hand.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/shintoist.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/shoe.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/shower.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/shrine.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/sikhist.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/slipway.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/snowmobile.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/social_facility.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/sports.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maptiler/maptiler-geocoding-control/e8b4d65286d75c9dd906f24c554c42582ae71b91/public/icons/sprite.png -------------------------------------------------------------------------------- /public/icons/sprite@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maptiler/maptiler-geocoding-control/e8b4d65286d75c9dd906f24c554c42582ae71b91/public/icons/sprite@2x.png -------------------------------------------------------------------------------- /public/icons/stationery.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/stile.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/stone.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/storage_tank.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/stream.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/icons/street.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /public/icons/supermarket.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/tea.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/telescope_dish.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/telescope_dome.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/ticket.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/tobacco.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/tower_cantilever_communication.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/tower_cooling.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/tower_dish.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/tower_dome.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/tower_generic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/tower_lattice.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/tower_lattice_communication.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/tower_lattice_lighting.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/tower_lighting.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/townhall.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /public/icons/toys.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/trade.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/traffic_light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/travel_agency.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/tyres.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/university.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /public/icons/variety_store.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/vehicle_inspection.svg: -------------------------------------------------------------------------------- 1 | 2 | 9 | 11 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /public/icons/vending_machine.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /public/icons/video.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/video_games.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/waste_disposal.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/water_well.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /public/icons/waterfall.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/icons/wilderness_hut.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /replace-env-vars.js: -------------------------------------------------------------------------------- 1 | import "dotenv/config"; 2 | import { replaceInFile } from "replace-in-file"; 3 | 4 | replaceInFile({ 5 | files: ["dist.svelte/*.svelte", "dist.svelte/*.ts", "dist.svelte/*.js"], 6 | from: /\bimport\.meta\.env\.(\w+)/g, 7 | to: (_, name) => JSON.stringify(process.env[name]), 8 | }).catch((err) => { 9 | console.error(err); 10 | 11 | process.exit(1); 12 | }); 13 | -------------------------------------------------------------------------------- /src/ClearIcon.svelte: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 13 | -------------------------------------------------------------------------------- /src/FailIcon.svelte: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 13 | -------------------------------------------------------------------------------- /src/LoadingIcon.svelte: -------------------------------------------------------------------------------- 1 |
2 | 3 | 7 | 11 | 12 |
13 | 14 | 41 | -------------------------------------------------------------------------------- /src/MarkerIcon.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | 16 | 17 | 18 | 73 | -------------------------------------------------------------------------------- /src/ReverseGeocodingIcon.svelte: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 13 | -------------------------------------------------------------------------------- /src/SearchIcon.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 27 | -------------------------------------------------------------------------------- /src/geo-coordinates-parser.t.ts: -------------------------------------------------------------------------------- 1 | declare module "geo-coordinates-parser" { 2 | export function convert( 3 | input: string, 4 | decimalPlaces: number, 5 | ): { 6 | decimalLatitude: number; 7 | decimalLongitude: number; 8 | verbatimLatitude: string; 9 | verbatimLongitude: string; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /src/geoUtils.ts: -------------------------------------------------------------------------------- 1 | import type { BBox } from "./types"; 2 | 3 | // taken from Leaflet 4 | export function wrapNum( 5 | x: number, 6 | range: [number, number], 7 | includeMax: boolean, 8 | ) { 9 | const max = range[1], 10 | min = range[0], 11 | d = max - min; 12 | 13 | return x === max && includeMax ? x : ((((x - min) % d) + d) % d) + min; 14 | } 15 | 16 | export function unwrapBbox(bbox0: BBox): BBox { 17 | const bbox = [...bbox0] satisfies BBox; 18 | 19 | if (bbox[2] < bbox[0]) { 20 | if ( 21 | Math.abs((bbox[0] + bbox[2] + 360) / 2) > 22 | Math.abs((bbox[0] - 360 + bbox[2]) / 2) 23 | ) { 24 | bbox[0] -= 360; 25 | } else { 26 | bbox[2] += 360; 27 | } 28 | } 29 | 30 | return bbox; 31 | } 32 | -------------------------------------------------------------------------------- /src/maplibregl.ts: -------------------------------------------------------------------------------- 1 | import type { Map } from "maplibre-gl"; 2 | import * as maplibregl from "maplibre-gl"; 3 | import { 4 | crateClasses, 5 | type MapLibreBaseControlOptions, 6 | } from "./MapLibreBasedGeocodingControl"; 7 | export { createMapLibreGlMapController } from "./maplibregl-controller"; 8 | 9 | type Options = MapLibreBaseControlOptions & { 10 | /** 11 | * Maptiler API key. Optional if used with MapTiler SDK. 12 | */ 13 | apiKey: string; 14 | }; 15 | 16 | const { MapLibreBasedGeocodingControl, events } = crateClasses( 17 | maplibregl.Evented, 18 | maplibregl, 19 | ); 20 | 21 | export class GeocodingControl 22 | extends MapLibreBasedGeocodingControl 23 | implements maplibregl.IControl 24 | { 25 | onAdd(map: Map): HTMLElement { 26 | return super.onAddInt(map); 27 | } 28 | } 29 | 30 | export const SelectEvent = events.SelectEvent; 31 | 32 | export const FeaturesListedEvent = events.FeaturesListedEvent; 33 | 34 | export const FeaturesMarkedEvent = events.FeaturesMarkedEvent; 35 | 36 | export const OptionsVisibilityChangeEvent = events.OptionsVisibilityChangeEvent; 37 | 38 | export const PickEvent = events.PickEvent; 39 | 40 | export const QueryChangeEvent = events.QueryChangeEvent; 41 | 42 | export const ResponseEvent = events.ResponseEvent; 43 | 44 | export const ReverseToggleEvent = events.ReverseToggleEvent; 45 | -------------------------------------------------------------------------------- /src/maptilersdk.ts: -------------------------------------------------------------------------------- 1 | import * as maptilersdk from "@maptiler/sdk"; 2 | import type * as maplibregl from "maplibre-gl"; 3 | import type { Map } from "maplibre-gl"; 4 | import { 5 | crateClasses, 6 | type MapLibreBaseControlOptions, 7 | } from "./MapLibreBasedGeocodingControl"; 8 | import { name, version } from "./info.json"; 9 | 10 | export { createMapLibreGlMapController } from "./maplibregl-controller"; 11 | 12 | const { MapLibreBasedGeocodingControl, events } = 13 | crateClasses( 14 | maptilersdk.Evented, 15 | maptilersdk, 16 | (map: Map, div: HTMLElement) => { 17 | const sdkConfig: { apiKey?: string; language?: string } = {}; 18 | 19 | if (!("getSdkConfig" in map && typeof map.getSdkConfig === "function")) { 20 | throw new Error("MapTiler SDK not detected"); 21 | } 22 | 23 | const { primaryLanguage, apiKey } = map.getSdkConfig(); 24 | 25 | sdkConfig.apiKey = apiKey; 26 | 27 | const match = /^([a-z]{2})($|_|-)/.exec(primaryLanguage); 28 | 29 | if (match) { 30 | sdkConfig.language = match[1]; 31 | } 32 | 33 | div.className += " maptiler-ctrl"; 34 | 35 | return sdkConfig; 36 | }, 37 | ); 38 | 39 | export class GeocodingControl 40 | extends MapLibreBasedGeocodingControl 41 | implements maptilersdk.IControl 42 | { 43 | onAdd(map: maptilersdk.Map): HTMLElement { 44 | map.telemetry?.registerModule(name, version); 45 | return super.onAddInt(map as unknown as maplibregl.Map); 46 | } 47 | } 48 | 49 | export const SelectEvent = events.SelectEvent; 50 | 51 | export const FeaturesListedEvent = events.FeaturesListedEvent; 52 | 53 | export const FeaturesMarkedEvent = events.FeaturesMarkedEvent; 54 | 55 | export const OptionsVisibilityChangeEvent = events.OptionsVisibilityChangeEvent; 56 | 57 | export const PickEvent = events.PickEvent; 58 | 59 | export const QueryChangeEvent = events.QueryChangeEvent; 60 | 61 | export const ResponseEvent = events.ResponseEvent; 62 | 63 | export const ReverseToggleEvent = events.ReverseToggleEvent; 64 | -------------------------------------------------------------------------------- /src/mask.ts: -------------------------------------------------------------------------------- 1 | import bbox from "@turf/bbox"; 2 | import difference from "@turf/difference"; 3 | import flatten from "@turf/flatten"; 4 | import { featureCollection, polygon } from "@turf/helpers"; 5 | import union from "@turf/union"; 6 | import type { 7 | Feature, 8 | FeatureCollection, 9 | MultiPolygon, 10 | Polygon, 11 | } from "geojson"; 12 | import { unwrapBbox } from "./geoUtils"; 13 | import type { BBox } from "./types"; 14 | 15 | export function setMask( 16 | picked: Feature, 17 | setData: (data?: FeatureCollection) => void, 18 | ): void { 19 | const diff = difference( 20 | featureCollection([ 21 | polygon([ 22 | [ 23 | [180, 90], 24 | [-180, 90], 25 | [-180, -90], 26 | [180, -90], 27 | [180, 90], 28 | ], 29 | ]), 30 | picked, 31 | ]), 32 | ); 33 | 34 | if (!diff) { 35 | return; 36 | } 37 | 38 | diff.properties = { isMask: true }; 39 | 40 | const bb = unwrapBbox(bbox(picked) as BBox); 41 | 42 | // bigger features (continents, oceans) have bigger tolerance 43 | // because of the used source data simplification 44 | const tolerance = (bb[2] - bb[0]) / 360 / 1_000; 45 | 46 | const leaksLeft = bb[0] < -180; 47 | const leaksRight = bb[2] > 180; 48 | 49 | const flattened = flatten(picked); 50 | 51 | if (flattened.features.length > 1 && (leaksLeft || leaksRight)) { 52 | for (const poly of flattened.features) { 53 | const bb = unwrapBbox(bbox(poly) as BBox); 54 | 55 | if (leaksRight && bb[0] < -180 + tolerance) { 56 | for (const ring of poly.geometry.coordinates) { 57 | for (const position of ring) { 58 | position[0] += 360 - tolerance; 59 | } 60 | } 61 | } 62 | 63 | if (leaksLeft && bb[2] > 180 - tolerance) { 64 | for (const ring of poly.geometry.coordinates) { 65 | for (const position of ring) { 66 | position[0] -= 360 - tolerance; 67 | } 68 | } 69 | } 70 | } 71 | } 72 | 73 | setData( 74 | featureCollection([ 75 | flattened.features.length < 2 ? picked : (union(flattened) ?? picked), 76 | diff, 77 | ]), 78 | ); 79 | } 80 | -------------------------------------------------------------------------------- /src/proximity.ts: -------------------------------------------------------------------------------- 1 | import type { MapController, ProximityRule } from "./types"; 2 | 3 | let cachedLocation: { time: number; coords: undefined | string } | undefined; 4 | 5 | export async function getProximity( 6 | mapController: MapController | undefined, 7 | proximity: ProximityRule[] | null | undefined, 8 | ac: AbortController, 9 | ) { 10 | const centerAndZoom = mapController?.getCenterAndZoom(); 11 | 12 | for (const rule of proximity ?? []) { 13 | if ( 14 | centerAndZoom && 15 | ((rule.minZoom != undefined && rule.minZoom > centerAndZoom[0]) || 16 | (rule.maxZoom != undefined && rule.maxZoom < centerAndZoom[0])) 17 | ) { 18 | continue; 19 | } 20 | 21 | if (rule.type === "fixed") { 22 | return rule.coordinates.join(","); 23 | } 24 | 25 | cg: if (rule.type === "client-geolocation") { 26 | if ( 27 | cachedLocation && 28 | rule.cachedLocationExpiry && 29 | cachedLocation.time + rule.cachedLocationExpiry > Date.now() 30 | ) { 31 | if (!cachedLocation.coords) { 32 | break cg; 33 | } 34 | 35 | return cachedLocation.coords; 36 | } 37 | 38 | let coords: string | undefined; 39 | 40 | try { 41 | coords = await new Promise((resolve, reject) => { 42 | ac.signal.addEventListener("abort", () => { 43 | reject(Error("aborted")); 44 | }); 45 | 46 | navigator.geolocation.getCurrentPosition( 47 | (pos) => { 48 | resolve( 49 | [pos.coords.longitude, pos.coords.latitude] 50 | .map((c) => c.toFixed(6)) 51 | .join(","), 52 | ); 53 | }, 54 | (err) => { 55 | reject(err); 56 | }, 57 | rule, 58 | ); 59 | }); 60 | 61 | return coords; 62 | } catch { 63 | // ignore 64 | } finally { 65 | if (rule.cachedLocationExpiry) { 66 | cachedLocation = { 67 | time: Date.now(), 68 | coords, 69 | }; 70 | } 71 | } 72 | 73 | if (ac.signal.aborted) { 74 | return; 75 | } 76 | } 77 | 78 | if (rule.type === "server-geolocation") { 79 | return "ip"; 80 | } 81 | 82 | if (centerAndZoom && rule.type === "map-center") { 83 | return centerAndZoom[1].toFixed(6) + "," + centerAndZoom[2].toFixed(6); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/react.ts: -------------------------------------------------------------------------------- 1 | import { 2 | createElement, 3 | forwardRef, 4 | useEffect, 5 | useImperativeHandle, 6 | useRef, 7 | type Ref, 8 | } from "react"; 9 | import GeocodingControl from "./GeocodingControl.svelte"; 10 | import type { ControlOptions, DispatcherTypeCC, MapController } from "./types"; 11 | 12 | type EventNames = keyof DispatcherTypeCC; 13 | 14 | type EventHandlerFnName = `on${Capitalize}`; 15 | 16 | type CallbackProperties = { 17 | [K in keyof T as EventHandlerFnName>]?: ( 18 | event: T[K], 19 | ) => void; 20 | }; 21 | 22 | const eventNames = [ 23 | "featuresListed", 24 | "featuresMarked", 25 | "optionsVisibilityChange", 26 | "pick", 27 | "queryChange", 28 | "response", 29 | "reverseToggle", 30 | "select", 31 | ] as const satisfies readonly EventNames[]; 32 | 33 | type MapControllerProp = { 34 | mapController?: MapController; 35 | }; 36 | 37 | const propertyNames = [ 38 | "adjustUrlQuery", 39 | "adjustUrl", 40 | "apiKey", 41 | "apiUrl", 42 | "bbox", 43 | "class", 44 | "clearButtonTitle", 45 | "clearListOnPick", 46 | "clearOnBlur", 47 | "collapsed", 48 | "country", 49 | "debounceSearch", 50 | "enableReverse", 51 | "errorMessage", 52 | "excludeTypes", 53 | "reverseGeocodingExcludeTypes", 54 | "exhaustiveReverseGeocoding", 55 | "fetchParameters", 56 | "filter", 57 | "flyToSelected", 58 | "fuzzyMatch", 59 | "iconsBaseUrl", 60 | "keepListOpen", 61 | "language", 62 | "limit", 63 | "reverseGeocodingLimit", 64 | "mapController", 65 | "markerOnSelected", 66 | "minLength", 67 | "noResultsMessage", 68 | "pickedResultStyle", 69 | "placeholder", 70 | "proximity", 71 | "reverseActive", 72 | "reverseButtonTitle", 73 | "selectFirst", 74 | "showPlaceType", 75 | "showResultsWhileTyping", 76 | "types", 77 | "reverseGeocodingTypes", 78 | "zoom", 79 | ] as const satisfies readonly (keyof (ControlOptions & MapControllerProp))[]; 80 | 81 | function getEventFnName(name: T): EventHandlerFnName { 82 | return ("on" + 83 | name[0].toUpperCase() + 84 | name.slice(1)) as EventHandlerFnName; 85 | } 86 | 87 | export type Props = ControlOptions & 88 | CallbackProperties & 89 | MapControllerProp; 90 | 91 | // defining the type explicitly otherwise compiled .d.ts refers to .svelte which is not good 92 | // type MethodNames = "blur" | "focus" | "setQuery"; 93 | // export type Methods = { [T in MethodNames]: GeocodingControl[T] }; 94 | export type Methods = { 95 | /** 96 | * Blur the search input box. 97 | */ 98 | blur(): void; 99 | 100 | /** 101 | * Focus the search input box. 102 | * 103 | * @param options [FocusOptions](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus#options) 104 | */ 105 | focus(options?: FocusOptions): void; 106 | 107 | /** 108 | * Set the content of search input box. 109 | * 110 | * @param value text to set 111 | * @param submit perform the search 112 | */ 113 | setQuery(value: string, submit?: boolean): void; 114 | 115 | /** 116 | * Clear geocoding search results from the map. 117 | */ 118 | clearMap(): void; 119 | 120 | /** 121 | * Clear search result list. 122 | */ 123 | clearList(): void; 124 | 125 | /** 126 | * Set reverse geocoding mode. 127 | * 128 | * @param reverseActive reverse geocoding active 129 | */ 130 | setReverseMode(reverseActive: boolean): void; 131 | }; 132 | 133 | const ReactGeocodingControl = forwardRef(function ReactGeocodingControl( 134 | props: Props, 135 | ref: Ref, 136 | ) { 137 | const divRef = useRef(undefined); 138 | 139 | const controlRef = useRef(undefined); 140 | 141 | const options = { ...props }; 142 | 143 | for (const eventName of eventNames) { 144 | // eslint-disable-next-line @typescript-eslint/no-dynamic-delete 145 | delete options[getEventFnName(eventName)]; 146 | } 147 | 148 | useEffect(() => { 149 | if (!divRef.current) { 150 | throw new Error(); 151 | } 152 | 153 | const control = new GeocodingControl({ 154 | target: divRef.current, 155 | props: options, 156 | }); 157 | 158 | controlRef.current = control; 159 | 160 | return () => control.$destroy(); 161 | }, []); 162 | 163 | // watch change on every option 164 | for (const propName of propertyNames) { 165 | useEffect(() => { 166 | if (controlRef.current && props[propName] !== undefined) { 167 | controlRef.current.$set({ [propName]: props[propName] }); 168 | } 169 | }, [props[propName]]); 170 | } 171 | 172 | // attach event handlers 173 | for (const eventName of eventNames) { 174 | const eventHandlerFn = props[getEventFnName(eventName)]; 175 | 176 | useEffect( 177 | () => 178 | eventHandlerFn && 179 | controlRef.current?.$on(eventName.toLowerCase(), (e) => { 180 | eventHandlerFn(e.detail as never); 181 | }), 182 | 183 | [eventHandlerFn], 184 | ); 185 | } 186 | 187 | useImperativeHandle(ref, () => ({ 188 | setQuery: (value: string, submit = true) => 189 | controlRef.current?.setQuery(value, submit), 190 | clearMap: () => controlRef.current?.clearMap(), 191 | clearList: () => controlRef.current?.clearList(), 192 | focus: (options?: FocusOptions) => controlRef.current?.focus(options), 193 | blur: () => controlRef.current?.blur(), 194 | setReverseMode: (reverseActive: boolean) => 195 | controlRef.current?.$set({ reverseActive }), 196 | })); 197 | 198 | return createElement("div", { ref: divRef }); 199 | }); 200 | 201 | export { ReactGeocodingControl as GeocodingControl }; 202 | -------------------------------------------------------------------------------- /src/vanilla.ts: -------------------------------------------------------------------------------- 1 | import GeocodingControlComponent from "./GeocodingControl.svelte"; 2 | import type { ControlOptions, DispatcherType, MapController } from "./types"; 3 | 4 | const finalizationRegistry = 5 | new FinalizationRegistry((gc) => { 6 | gc.$destroy(); 7 | }); 8 | 9 | type Options = ControlOptions & { mapController?: MapController }; 10 | 11 | interface GeocodingControlEvent extends CustomEvent { 12 | readonly target: GeocodingControl; 13 | readonly currentTarget: GeocodingControl; 14 | } 15 | 16 | type CustomEventListenerOrEventListenerObject = 17 | | ((evt: CustomEventMap[K]) => void) 18 | | { handleEvent(object: CustomEventMap[K]): void }; 19 | 20 | type CustomEventMap = { 21 | [T in keyof DispatcherType]: GeocodingControlEvent; 22 | }; 23 | 24 | export class GeocodingControl extends EventTarget { 25 | #gc: GeocodingControlComponent; 26 | 27 | constructor({ target, ...options }: Options & { target: HTMLElement }) { 28 | super(); 29 | 30 | this.#gc = new GeocodingControlComponent({ 31 | target, 32 | props: options, 33 | }); 34 | 35 | for (const eventName of [ 36 | "select", 37 | "pick", 38 | "featureslisted", 39 | "featuresmarked", 40 | "response", 41 | "optionsvisibilitychange", 42 | "reversetoggle", 43 | "querychange", 44 | ] as const) { 45 | this.#gc.$on(eventName, (event) => { 46 | // Use the new `emit` method for type-safe dispatching 47 | this.#emit(eventName, event.detail); 48 | }); 49 | } 50 | 51 | this.#gc.$on("select", (event) => { 52 | const geocodingEvent = new CustomEvent(event.type, { 53 | detail: event.detail, 54 | }) as GeocodingControlEvent; 55 | 56 | this.dispatchEvent(geocodingEvent); 57 | }); 58 | 59 | finalizationRegistry.register(this, this.#gc); 60 | } 61 | 62 | /** 63 | * Update the control options. 64 | * 65 | * @param options options to update 66 | */ 67 | setOptions(options: Partial) { 68 | this.#gc.$set(options); 69 | } 70 | 71 | /** 72 | * Set the content of search input box. 73 | * 74 | * @param value text to set 75 | * @param submit perform the search 76 | */ 77 | setQuery(value: string, submit = true) { 78 | this.#gc?.setQuery(value, submit); 79 | } 80 | 81 | /** 82 | * Clear geocoding search results from the map. 83 | */ 84 | clearMap() { 85 | this.#gc?.clearMap(); 86 | } 87 | 88 | /** 89 | * Clear search result list. 90 | */ 91 | clearList() { 92 | this.#gc?.clearList(); 93 | } 94 | 95 | /** 96 | * Set reverse geocoding mode. 97 | * 98 | * @param reverseActive reverse geocoding active 99 | */ 100 | setReverseMode(reverseActive: boolean) { 101 | this.#gc?.$set({ reverseActive }); 102 | } 103 | 104 | /** 105 | * Focus the search input box. 106 | * 107 | * @param options [FocusOptions](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus#options) 108 | */ 109 | focus(options?: FocusOptions) { 110 | this.#gc?.focus(options); 111 | } 112 | 113 | /** 114 | * Blur the search input box. 115 | */ 116 | blur() { 117 | this.#gc?.blur(); 118 | } 119 | 120 | addEventListener( 121 | type: K, 122 | callback: CustomEventListenerOrEventListenerObject | null, 123 | options?: AddEventListenerOptions | boolean, 124 | ): void; 125 | 126 | addEventListener( 127 | type: string, 128 | callback: EventListenerOrEventListenerObject | null, 129 | options?: AddEventListenerOptions | boolean, 130 | ): void { 131 | super.addEventListener(type, callback, options); 132 | } 133 | 134 | removeEventListener( 135 | type: K, 136 | callback: CustomEventListenerOrEventListenerObject | null, 137 | options?: EventListenerOptions | boolean, 138 | ): void; 139 | 140 | removeEventListener( 141 | type: string, 142 | callback: EventListenerOrEventListenerObject | null, 143 | options?: EventListenerOptions | boolean, 144 | ): void { 145 | super.removeEventListener(type, callback, options); 146 | } 147 | 148 | dispatchEvent( 149 | event: CustomEventMap[K], 150 | ): boolean; 151 | 152 | dispatchEvent(event: Event): boolean { 153 | return super.dispatchEvent(event); 154 | } 155 | 156 | #emit( 157 | type: K, 158 | detail: CustomEventMap[K]["detail"], 159 | ): boolean { 160 | return super.dispatchEvent( 161 | new CustomEvent(type, { 162 | detail, 163 | }) as GeocodingControlEvent, 164 | ); 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /svelte.config.js: -------------------------------------------------------------------------------- 1 | import sveltePreprocess from "svelte-preprocess"; 2 | 3 | export default { 4 | // Consult https://github.com/sveltejs/svelte-preprocess 5 | // for more information about preprocessors 6 | preprocess: sveltePreprocess(), 7 | }; 8 | -------------------------------------------------------------------------------- /sync-info.js: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import path from "path"; 3 | import { argv } from "process"; 4 | 5 | export function syncInfo() { 6 | const packageJson = JSON.parse( 7 | fs.readFileSync(path.resolve(import.meta.dirname, "package.json"), "utf-8"), 8 | ); 9 | 10 | fs.writeFileSync( 11 | path.resolve(import.meta.dirname, "src/info.json"), 12 | JSON.stringify({ 13 | name: packageJson.name, 14 | version: packageJson.version, 15 | }), 16 | ); 17 | } 18 | 19 | if (argv[2] === "run") { 20 | syncInfo(); 21 | } 22 | -------------------------------------------------------------------------------- /tsconfig.dist.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/svelte/tsconfig.json", 3 | "compilerOptions": { 4 | "target": "ESNext", 5 | "useDefineForClassFields": true, 6 | "module": "ESNext", 7 | "baseUrl": ".", 8 | /** 9 | * Typecheck JS in `.svelte` and `.js` files by default. 10 | * Disable checkJs if you'd like to use dynamic types in JS. 11 | * Note that setting allowJs false does not prevent the use 12 | * of JS in `.svelte` files. 13 | */ 14 | "allowJs": true, 15 | "checkJs": true, 16 | "strict": true, 17 | "moduleResolution": "Node", 18 | "resolveJsonModule": true 19 | }, 20 | "include": ["src/*.d.ts", "src/*.ts", "src/*.js", "src/*.svelte"], 21 | "references": [{ "path": "./tsconfig.node.json" }] 22 | } 23 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.dist.json", 3 | "compilerOptions": { 4 | "jsx": "react-jsx" 5 | }, 6 | "include": [ 7 | "src/*.d.ts", 8 | "src/*.ts", 9 | "src/*.js", 10 | "src/*.svelte", 11 | "examples/**/*.d.ts", 12 | "examples/**/*.ts", 13 | "examples/**/*.tsx", 14 | "examples/**/*.js", 15 | "examples/**/*.svelte" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node" 6 | }, 7 | "include": ["vite.config.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { svelte } from "@sveltejs/vite-plugin-svelte"; 2 | import process from "node:process"; 3 | import { sveltePreprocess } from "svelte-preprocess"; 4 | import { BuildOptions, defineConfig } from "vite"; 5 | import { syncInfo } from "./sync-info"; 6 | 7 | const libs = { 8 | leaflet: { 9 | fileName: "leaflet", 10 | entry: ["src/leaflet.ts"], 11 | name: "leafletMaptilerGeocoder", 12 | }, 13 | maplibre: { 14 | fileName: "maplibregl", 15 | entry: ["src/maplibregl.ts"], 16 | name: "maplibreglMaptilerGeocoder", 17 | }, 18 | maptilersdk: { 19 | fileName: "maptilersdk", 20 | entry: ["src/maptilersdk.ts"], 21 | name: "maptilersdkMaptilerGeocoder", 22 | }, 23 | openlayers: { 24 | fileName: "openlayers", 25 | entry: ["src/openlayers.ts"], 26 | name: "openlayersMaptilerGeocoder", 27 | }, 28 | react: { 29 | fileName: "react", 30 | entry: ["src/react.ts"], 31 | name: "reactMaptilerGeocoder", 32 | }, 33 | vanilla: { 34 | fileName: "vanilla", 35 | entry: ["src/vanilla.ts"], 36 | name: "maptilerGeocoder", 37 | }, 38 | "leaflet-controller": { 39 | fileName: "leaflet-controller", 40 | entry: ["src/leaflet-controller.ts"], 41 | name: "leafletMaptilerGeocodingController", 42 | }, 43 | "maplibregl-controller": { 44 | fileName: "maplibregl-controller", 45 | entry: ["src/maplibregl-controller.ts"], 46 | name: "maplibreglMaptilerGeocodingController", 47 | }, 48 | "openlayers-controller": { 49 | fileName: "openlayers-controller", 50 | entry: ["src/openlayers-controller.ts"], 51 | name: "openlayersMaptilerGeocodingController", 52 | }, 53 | }; 54 | 55 | let lib: BuildOptions["lib"]; 56 | 57 | let rollupOptions: BuildOptions["rollupOptions"]; 58 | 59 | const flavour = process.env.FLAVOUR; 60 | 61 | if (flavour) { 62 | if (!(flavour in libs)) { 63 | throw new Error("invalid FLAVOUR"); 64 | } 65 | 66 | lib = libs[flavour as keyof typeof libs]; 67 | 68 | rollupOptions = { 69 | external: [ 70 | "@maptiler/sdk", 71 | "maplibre-gl", 72 | "leaflet", 73 | "react", 74 | "react-dom", 75 | /^ol(\/.*)?/, 76 | ], 77 | output: [ 78 | { 79 | format: "es", 80 | entryFileNames: "[name].js", 81 | chunkFileNames: "[name].js", 82 | assetFileNames: "[name].[ext]", 83 | }, 84 | { 85 | name: lib.name, 86 | format: "umd", 87 | entryFileNames: "[name].umd.js", 88 | chunkFileNames: "[name].umd.js", 89 | assetFileNames: "[name].[ext]", 90 | 91 | // Provide global variables to use in the UMD build for externalized deps 92 | globals(name) { 93 | const global = { 94 | "@maptiler/sdk": "maptilersdk", 95 | "maplibre-gl": "maplibregl", 96 | leaflet: "L", 97 | react: "React", 98 | "react-dom": "ReactDOM", 99 | }[name]; 100 | 101 | return ( 102 | global ?? (name.startsWith("ol") ? name.replace(/\//g, ".") : "") 103 | ); 104 | }, 105 | }, 106 | ], 107 | }; 108 | } 109 | 110 | // https://vitejs.dev/config/ 111 | export default defineConfig({ 112 | plugins: [ 113 | { 114 | name: "sync-info", 115 | buildStart: syncInfo, 116 | }, 117 | svelte({ 118 | preprocess: sveltePreprocess(), 119 | }), 120 | ], 121 | publicDir: "public", 122 | build: { 123 | sourcemap: true, 124 | emptyOutDir: false, 125 | lib, 126 | rollupOptions, 127 | }, 128 | }); 129 | --------------------------------------------------------------------------------