places-autocomplete-svelte 2.2.19 β 2.2.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +204 -86
- package/dist/PlaceAutocomplete.svelte +788 -116
- package/dist/PlaceAutocomplete.svelte.d.ts +4 -1
- package/dist/gmaps.d.ts +62 -14
- package/dist/gmaps.js +64 -25
- package/dist/helpers.js +26 -23
- package/dist/interfaces.d.ts +107 -1
- package/package.json +19 -19
package/README.md
CHANGED
|
@@ -2,47 +2,87 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://badge.fury.io/js/places-autocomplete-svelte)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://developers.google.com/maps)
|
|
5
6
|
|
|
6
|
-
A flexible, accessible, and secure [Svelte](https://kit.svelte.dev) component leveraging the [Google Maps Places Autocomplete API (New)](https://developers.google.com/maps/documentation/javascript/place-autocomplete-overview).
|
|
7
|
+
A flexible, accessible, and secure [Svelte](https://kit.svelte.dev) component leveraging the [Google Maps Places Autocomplete API (New)](https://developers.google.com/maps/documentation/javascript/place-autocomplete-overview). **Winner of the Google Maps Platform Awards 2025**, recognising excellence in Google Maps Platform development.
|
|
7
8
|
|
|
8
9
|
The component handles API loading, session tokens, debounced fetching, and accessibility, allowing you to focus on building your application. It intelligently manages the Google Maps API loader, creating a shared instance via Svelte's context that prevents conflicts with other map components on the same page.
|
|
9
10
|
|
|
10
11
|
**Two initialisation patterns:**
|
|
11
12
|
- **Simple/Automatic**: Pass your API key directly to the component for basic use cases
|
|
12
|
-
- **Advanced/Manual**: Initialise the loader once in a parent component when using multiple Google Maps libraries or components
|
|
13
|
-
|
|
14
|
-
##
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
- **Advanced/Manual**: Initialise the loader once in a parent component when using multiple Google Maps libraries or components
|
|
14
|
+
|
|
15
|
+
## Table of Contents
|
|
16
|
+
|
|
17
|
+
- [Features](#features)
|
|
18
|
+
- [Demo](#demo)
|
|
19
|
+
- [Recognition](#recognition)
|
|
20
|
+
- [Requirements](#requirements)
|
|
21
|
+
- [Installation](#installation)
|
|
22
|
+
- [Usage](#usage)
|
|
23
|
+
- [Basic Usage](#basic-usage-automatic-initialisation)
|
|
24
|
+
- [Advanced Usage](#advanced-usage-manual-initialisation)
|
|
25
|
+
- [Props](#props)
|
|
26
|
+
- [Component Methods](#component-methods-imperative-api)
|
|
27
|
+
- [Options](#options)
|
|
28
|
+
- [Styling](#styling)
|
|
29
|
+
- [Events](#events)
|
|
30
|
+
- [TypeScript](#typescript)
|
|
31
|
+
- [Security](#security)
|
|
32
|
+
- [Accessibility](#accessibility)
|
|
33
|
+
- [Google Places API & Billing](#google-places-api--billing)
|
|
34
|
+
- [Standalone JavaScript Library](#standalone-javascript-library)
|
|
35
|
+
- [Contributing](#contributing)
|
|
36
|
+
- [License](#license)
|
|
18
37
|
|
|
19
38
|
## Features
|
|
20
39
|
|
|
21
|
-
|
|
22
|
-
*
|
|
23
|
-
* **
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* **
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
* **
|
|
30
|
-
* **
|
|
31
|
-
* **
|
|
40
|
+
### Core Functionality
|
|
41
|
+
* πΊοΈ Integrates with the modern **Google Maps Places Autocomplete API (New)**
|
|
42
|
+
* π **Automatic Shared Loader:** Intelligently creates a single Google Maps loader instance and shares it via Svelte's context
|
|
43
|
+
* π° Automatically handles **session tokens** for optimal cost management
|
|
44
|
+
* β‘ **Debounced Input:** Configurable delay to minimise API calls while typing
|
|
45
|
+
* β¨ **Suggestion Highlighting:** Automatically highlights matched text in suggestions
|
|
46
|
+
|
|
47
|
+
### Accessibility & User Experience
|
|
48
|
+
* βΏ **WCAG Compliant:** Follows WAI-ARIA patterns for comboboxes
|
|
49
|
+
* β¨οΈ **Full Keyboard Navigation:** Arrow keys, Enter, and Escape support
|
|
50
|
+
* π’ **Screen Reader Support:** Proper ARIA attributes for assistive technologies
|
|
51
|
+
|
|
52
|
+
### Developer Experience
|
|
53
|
+
* π¨ **Customisable Styling:** Override default styles via `options.classes` prop
|
|
54
|
+
* π§ **Imperative API:** Direct control with `clear()`, `focus()`, `getRequestParams()`, `setRequestParams()`, `setFetchFields()`, and `getFetchFields()` methods
|
|
55
|
+
* π **TypeScript Support:** Fully typed with comprehensive type definitions
|
|
56
|
+
* π **Secure:** XSS protection with safe rendering of suggestions
|
|
57
|
+
* π― **Event Handling:** `onResponse` and `onError` callbacks for complete control
|
|
32
58
|
|
|
33
59
|
## Demo
|
|
34
60
|
|
|
35
|
-
|
|
61
|
+
Explore live examples showcasing different features and use cases:
|
|
62
|
+
|
|
63
|
+
**[π Basic Example](https://places-autocomplete-demo.pages.dev/)** - Get started with the simplest implementation
|
|
36
64
|
|
|
37
|
-
[Reactive
|
|
65
|
+
**[π Reactive Parameters](https://places-autocomplete-demo.pages.dev/examples/reactive-parameters)** - Dynamically change search criteria based on user input, such as filtering by country or switching languages
|
|
38
66
|
|
|
39
|
-
[
|
|
67
|
+
**[βοΈ Custom Request Parameters](https://places-autocomplete-demo.pages.dev/examples/customise-request-parameters)** - Configure advanced search options including language, region, location bias, and place types
|
|
40
68
|
|
|
41
|
-
[Retain Input Value
|
|
42
|
-
This example demonstrates how to configure the component to keep the selected address visible in the input field after a suggestion is chosen.
|
|
69
|
+
**[π Retain Input Value](https://places-autocomplete-demo.pages.dev/examples/retain-input-value)** - Keep the selected address visible in the input field after selection
|
|
43
70
|
|
|
44
71
|
<img src="places-autocomplete-svelte.gif" alt="A video demonstrating the Places Autocomplete Svelte component in action, showing address suggestions and selection.">
|
|
45
72
|
|
|
73
|
+
## Recognition
|
|
74
|
+
|
|
75
|
+
### π Google Maps Platform Awards 2025 Winner
|
|
76
|
+
<p align="left">
|
|
77
|
+
<a href="https://developers.google.com/maps">
|
|
78
|
+
<img src="badge.svg" alt="Google Maps Platform Awards 2025 Winner" width="200">
|
|
79
|
+
</a>
|
|
80
|
+
</p>
|
|
81
|
+
|
|
82
|
+
This component has been recognised as a winner of the **Google Maps Platform Awards 2025** by the Google Developer Program. This award celebrates outstanding projects that demonstrate exceptional use of Google Maps Platform APIs, innovation, and contribution to the developer community.
|
|
83
|
+
|
|
84
|
+
[Learn more about the Google Maps Platform Awards](https://developers.google.com/maps)
|
|
85
|
+
|
|
46
86
|
## Requirements
|
|
47
87
|
|
|
48
88
|
* **Google Maps API Key** with the "Places API" enabled. Refer to [Use API Keys](https://developers.google.com/maps/documentation/javascript/get-api-key) for detailed instructions.
|
|
@@ -88,18 +128,19 @@ For simple use cases, just pass your API key to the component. It will automatic
|
|
|
88
128
|
|
|
89
129
|
### Advanced Usage (Manual Initialisation)
|
|
90
130
|
|
|
91
|
-
For applications
|
|
131
|
+
For applications using multiple Google Maps libraries (e.g., `places`, `maps`, `marker`) or multiple map components, initialise the loader once in a parent component.
|
|
92
132
|
|
|
93
|
-
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
-
|
|
133
|
+
**Benefits:**
|
|
134
|
+
- β
Loads all required libraries in a single API call (more efficient)
|
|
135
|
+
- β
Prevents "Loader must not be called again" errors
|
|
136
|
+
- β
Shares the loader instance across all child components via Svelte context
|
|
137
|
+
- β
Works seamlessly with SvelteKit's SSR (only initialises in the browser)
|
|
97
138
|
|
|
98
139
|
**When to use manual initialisation:**
|
|
99
|
-
-
|
|
100
|
-
-
|
|
101
|
-
-
|
|
102
|
-
-
|
|
140
|
+
- Multiple Google Maps components on the same page
|
|
141
|
+
- Multiple libraries needed (`maps`, `marker`, `geometry`, etc.)
|
|
142
|
+
- Shared map functionality across routes
|
|
143
|
+
- Centralised error handling for the loader
|
|
103
144
|
|
|
104
145
|
```javascript
|
|
105
146
|
// In +layout.svelte or +page.svelte
|
|
@@ -108,6 +149,7 @@ For applications that need multiple Google Maps libraries (e.g., `places`, `maps
|
|
|
108
149
|
import { PlaceAutocomplete } from 'places-autocomplete-svelte';
|
|
109
150
|
import { setGMapsContext, initialiseGMaps, importLibrary } from 'places-autocomplete-svelte/gmaps';
|
|
110
151
|
import { onMount } from 'svelte';
|
|
152
|
+
import type { PlaceResult } from 'places-autocomplete-svelte/interfaces';
|
|
111
153
|
|
|
112
154
|
// 1. Set the context at the top level (must be synchronous)
|
|
113
155
|
setGMapsContext();
|
|
@@ -127,8 +169,6 @@ For applications that need multiple Google Maps libraries (e.g., `places`, `maps
|
|
|
127
169
|
|
|
128
170
|
onMount(async () => {
|
|
129
171
|
const { Map } = await importLibrary('maps');
|
|
130
|
-
const { AdvancedMarkerElement } = await importLibrary('marker');
|
|
131
|
-
|
|
132
172
|
const mapElement = document.getElementById('map');
|
|
133
173
|
if (mapElement) {
|
|
134
174
|
map = new Map(mapElement, {
|
|
@@ -142,7 +182,6 @@ For applications that need multiple Google Maps libraries (e.g., `places`, `maps
|
|
|
142
182
|
// 4. Handle autocomplete responses
|
|
143
183
|
const handleResponse = (response: PlaceResult) => {
|
|
144
184
|
console.log('Selected:', response.formattedAddress);
|
|
145
|
-
// Update map with selected location
|
|
146
185
|
if (response.location && map) {
|
|
147
186
|
map.setCenter(response.location);
|
|
148
187
|
map.setZoom(15);
|
|
@@ -225,6 +264,9 @@ Get a reference to the component instance using `bind:this` to call its methods
|
|
|
225
264
|
|
|
226
265
|
<button onclick={() => autocompleteComponent?.clear()}>Clear</button>
|
|
227
266
|
<button onclick={() => autocompleteComponent?.focus()}>Focus</button>
|
|
267
|
+
<button onclick={() => autocompleteComponent?.setRequestParams({ region: 'FR', language: 'fr' })}>
|
|
268
|
+
Switch to French
|
|
269
|
+
</button>
|
|
228
270
|
```
|
|
229
271
|
|
|
230
272
|
| Method | Signature | Description |
|
|
@@ -232,6 +274,9 @@ Get a reference to the component instance using `bind:this` to call its methods
|
|
|
232
274
|
| `clear()` | `() => void` | Clears the input, removes suggestions, and resets the session token. |
|
|
233
275
|
| `focus()` | `() => void` | Sets focus on the text input field. |
|
|
234
276
|
| `getRequestParams()` | `() => RequestParams` | Returns the current internal `requestParams` object. |
|
|
277
|
+
| `setRequestParams(params)` | `(params: Partial<RequestParams>) => void` | Dynamically updates request parameters. Useful for changing search criteria (region, language, location bias, etc.). Parameters are merged with existing ones. |
|
|
278
|
+
| `setFetchFields(fields)` | `(fields: string[]) => void` | Dynamically updates the Place Data Fields to fetch when a place is selected. |
|
|
279
|
+
| `getFetchFields()` | `() => string[]` | Returns the current array of Place Data Fields that will be requested. |
|
|
235
280
|
|
|
236
281
|
## Options
|
|
237
282
|
|
|
@@ -247,41 +292,82 @@ Get a reference to the component instance using `bind:this` to call its methods
|
|
|
247
292
|
| `classes` | `Partial<ComponentClasses>` | `{}` | Object to override default CSS classes. See Styling section. |
|
|
248
293
|
| `clear_input` | `boolean` | `true` | If `false`, retains the `formattedAddress` in the input after selection. |
|
|
249
294
|
|
|
250
|
-
## Styling
|
|
295
|
+
## Styling
|
|
251
296
|
|
|
252
|
-
|
|
297
|
+
### Default Styles
|
|
253
298
|
|
|
254
|
-
|
|
299
|
+
The component includes built-in styles with `.pac-` prefixed CSS classes, providing a complete, accessible UI out of the box. These styles are:
|
|
255
300
|
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
* `icon_container`: Container for the optional icon.
|
|
261
|
-
* `icon`: SVG string for the icon.
|
|
262
|
-
* `ul`: The `<ul>` element for the suggestions list.
|
|
263
|
-
* `li`: Each `<li>` suggestion item.
|
|
264
|
-
* `li_current`: Class added to the currently highlighted `<li>`.
|
|
265
|
-
* `li_div_container`: Container `div` within each list item.
|
|
266
|
-
* `li_div_one`: First inner `div` (contains the main text).
|
|
267
|
-
* `li_div_one_p`: The `<p>` tag containing the main suggestion text.
|
|
268
|
-
* `li_div_two`: Second inner `div` (contains the distance).
|
|
269
|
-
* `li_div_two_p`: The `<p>` tag containing the distance text.
|
|
270
|
-
* `kbd_container`: Container for the keyboard hint keys.
|
|
271
|
-
* `kbd_escape`: The `<kbd>` tag for the 'Esc' hint.
|
|
272
|
-
* `kbd_up`: The `<kbd>` tag for the 'Up Arrow' hint.
|
|
273
|
-
* `kbd_down`: The `<kbd>` tag for the 'Down Arrow' hint.
|
|
274
|
-
* `highlight`: The class applied to the `<span>` wrapping the matched text. Defaults to `'font-bold'`.
|
|
301
|
+
* **Framework-agnostic**: Pure CSS with no dependencies on Tailwind or other frameworks
|
|
302
|
+
* **Modern design**: Clean, professional appearance with proper spacing, shadows, and hover effects
|
|
303
|
+
* **Fully functional**: Includes keyboard navigation indicators, loading states, and responsive behavior
|
|
304
|
+
* **Customisable**: All styles can be overridden via the `options.classes` prop
|
|
275
305
|
|
|
276
|
-
|
|
306
|
+
The default styles include:
|
|
307
|
+
- Rounded input with shadow and focus states
|
|
308
|
+
- Dropdown list with scroll behavior and dividers
|
|
309
|
+
- Keyboard navigation hints (Esc, β, β)
|
|
310
|
+
- Highlighted current selection with color transitions
|
|
311
|
+
- Distance display for location-based results
|
|
312
|
+
- Icon support with proper alignment
|
|
313
|
+
- Responsive layout for mobile and desktop
|
|
314
|
+
|
|
315
|
+
### Customisation (`options.classes`)
|
|
316
|
+
|
|
317
|
+
Override any default styling by providing your own CSS classes via `options.classes`. Your custom classes will replace the default `.pac-` classes for the specified elements.
|
|
318
|
+
|
|
319
|
+
**Available Class Keys:**
|
|
320
|
+
|
|
321
|
+
* `section`: The main container `section` (default: `.pac-section`)
|
|
322
|
+
* `container`: The `div` containing the input and suggestions list (default: `.pac-container`)
|
|
323
|
+
* `label`: The `label` element
|
|
324
|
+
* `input`: The main text `input` element (default: `.pac-input`)
|
|
325
|
+
* `icon_container`: Container for the optional icon (default: `.pac-icon-container`)
|
|
326
|
+
* `icon`: SVG string for the icon
|
|
327
|
+
* `ul`: The `<ul>` element for the suggestions list (default: `.pac-ul`)
|
|
328
|
+
* `li`: Each `<li>` suggestion item (default: `.pac-li`)
|
|
329
|
+
* `li_current`: Class added to the currently highlighted `<li>` (default: `.pac-li-current`)
|
|
330
|
+
* `li_button`: The `<button>` within each list item (default: `.pac-li-button`)
|
|
331
|
+
* `li_button_current`: Class added to the currently highlighted button (default: `.pac-li-button-current`)
|
|
332
|
+
* `li_div_container`: Container `div` within each list item (default: `.pac-li-div-container`)
|
|
333
|
+
* `li_div_one`: First inner `div` containing the main text (default: `.pac-li-div-one`)
|
|
334
|
+
* `li_div_one_p`: The `<p>` tag containing the main suggestion text (default: `.pac-li-div-one-p`)
|
|
335
|
+
* `li_div_one_p_secondaryText`: The `<p>` tag for secondary text (default: `.pac-li-div-one-p-secondaryText`)
|
|
336
|
+
* `li_div_p_container`: Container for paragraphs (default: `.pac-li-div-p-container`)
|
|
337
|
+
* `li_div_two`: Second inner `div` containing the distance (default: `.pac-li-div-two`)
|
|
338
|
+
* `li_div_two_p`: The `<p>` tag containing the distance text (default: `.pac-li-div-two-p`)
|
|
339
|
+
* `kbd_container`: Container for the keyboard hint keys (default: `.pac-kbd-container`)
|
|
340
|
+
* `kbd_escape`: The `<kbd>` tag for the 'Esc' hint (default: `.pac-kbd-escape`)
|
|
341
|
+
* `kbd_up`: The `<kbd>` tag for the 'Up Arrow' hint (default: `.pac-kbd-up`)
|
|
342
|
+
* `kbd_down`: The `<kbd>` tag for the 'Down Arrow' hint (default: `.pac-kbd-down`)
|
|
343
|
+
* `kbd_active`: Class applied to active keyboard hints (default: `.pac-kbd-active`)
|
|
344
|
+
* `map_pin_icon`: SVG string for the map pin icon
|
|
345
|
+
* `highlight`: The class applied to the `<span>` wrapping the matched text (default: `.pac-highlight`)
|
|
346
|
+
|
|
347
|
+
**Example - Using with Tailwind CSS:**
|
|
277
348
|
|
|
278
349
|
```javascript
|
|
279
350
|
const options = {
|
|
280
351
|
classes: {
|
|
281
|
-
input: '
|
|
282
|
-
ul: 'absolute bg-white shadow-lg rounded-md
|
|
352
|
+
input: 'w-full px-4 py-2.5 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500',
|
|
353
|
+
ul: 'absolute mt-1 w-full bg-white shadow-lg rounded-md border border-gray-200 max-h-60 overflow-auto',
|
|
354
|
+
li: 'px-4 py-2 hover:bg-blue-500 hover:text-white cursor-pointer',
|
|
283
355
|
li_current: 'bg-blue-500 text-white',
|
|
284
|
-
highlight: 'text-blue-700
|
|
356
|
+
highlight: 'font-semibold text-blue-700'
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
**Example - Using with Custom CSS:**
|
|
362
|
+
|
|
363
|
+
```javascript
|
|
364
|
+
const options = {
|
|
365
|
+
classes: {
|
|
366
|
+
section: 'autocomplete-wrapper',
|
|
367
|
+
input: 'search-input',
|
|
368
|
+
ul: 'suggestions-list',
|
|
369
|
+
li: 'suggestion-item',
|
|
370
|
+
li_current: 'suggestion-item--active'
|
|
285
371
|
}
|
|
286
372
|
};
|
|
287
373
|
```
|
|
@@ -295,47 +381,79 @@ const options = {
|
|
|
295
381
|
|
|
296
382
|
## TypeScript
|
|
297
383
|
|
|
298
|
-
This component is written in TypeScript with
|
|
384
|
+
This component is fully written in TypeScript with comprehensive type definitions.
|
|
299
385
|
|
|
300
|
-
|
|
386
|
+
### Available Imports
|
|
301
387
|
|
|
388
|
+
**Component:**
|
|
302
389
|
```typescript
|
|
303
|
-
|
|
304
|
-
|
|
390
|
+
import PlaceAutocomplete from 'places-autocomplete-svelte';
|
|
391
|
+
```
|
|
305
392
|
|
|
306
|
-
|
|
393
|
+
**Types and Interfaces:**
|
|
394
|
+
```typescript
|
|
307
395
|
import type {
|
|
308
|
-
PlaceResult,
|
|
309
|
-
ComponentOptions,
|
|
310
|
-
RequestParams,
|
|
311
|
-
FormattedAddress,
|
|
312
|
-
ComponentClasses,
|
|
313
|
-
Props
|
|
396
|
+
PlaceResult, // Place data returned from API
|
|
397
|
+
ComponentOptions, // UI and behavior configuration
|
|
398
|
+
RequestParams, // Autocomplete request parameters
|
|
399
|
+
FormattedAddress, // Standardised address structure
|
|
400
|
+
ComponentClasses, // CSS class overrides
|
|
401
|
+
Props // Component props
|
|
314
402
|
} from 'places-autocomplete-svelte/interfaces';
|
|
403
|
+
```
|
|
315
404
|
|
|
316
|
-
|
|
405
|
+
**Google Maps Loader Helpers:**
|
|
406
|
+
```typescript
|
|
317
407
|
import {
|
|
318
|
-
setGMapsContext,
|
|
319
|
-
getGMapsContext,
|
|
320
|
-
hasGMapsContext,
|
|
321
|
-
initialiseGMaps,
|
|
322
|
-
initialiseGMapsNoContext,
|
|
323
|
-
importLibrary,
|
|
324
|
-
type GMapsContext,
|
|
325
|
-
type APIOptions
|
|
408
|
+
setGMapsContext, // Create shared context
|
|
409
|
+
getGMapsContext, // Retrieve context
|
|
410
|
+
hasGMapsContext, // Check if context exists
|
|
411
|
+
initialiseGMaps, // Initialise with context
|
|
412
|
+
initialiseGMapsNoContext, // Initialise standalone
|
|
413
|
+
importLibrary, // Load Google Maps libraries
|
|
414
|
+
type GMapsContext, // Context type
|
|
415
|
+
type APIOptions // Loader options type
|
|
326
416
|
} from 'places-autocomplete-svelte/gmaps';
|
|
327
417
|
```
|
|
328
418
|
|
|
329
|
-
##
|
|
419
|
+
## Security
|
|
330
420
|
|
|
331
421
|
* This component uses the Google Maps JavaScript API (Places library). Usage is subject to Google's terms and pricing.
|
|
332
|
-
*
|
|
333
|
-
* Place Details requests (via `fetchFields`) are billed separately. Only request the fields you need to manage costs.
|
|
422
|
+
* **Session Tokens** are used automatically to group Autocomplete requests, which can reduce costs.
|
|
423
|
+
* Place Details requests (via `fetchFields`) are billed separately. **Only request the fields you need** to manage costs effectively.
|
|
424
|
+
* For detailed pricing information, see [Google Maps Platform Pricing](https://developers.google.com/maps/documentation/javascript/usage-and-billing).
|
|
425
|
+
|
|
426
|
+
## Standalone JavaScript Library
|
|
427
|
+
|
|
428
|
+
Need this functionality for a non-Svelte project? Check out our companion vanilla JavaScript library:
|
|
429
|
+
|
|
430
|
+
**[places-autocomplete-js](https://github.com/alexpechkarev/places-autocomplete-js)** - Same core Google Places (New) Autocomplete features, framework-agnostic implementation.
|
|
334
431
|
|
|
335
432
|
## Contributing
|
|
336
433
|
|
|
337
|
-
Contributions are welcome!
|
|
434
|
+
Contributions are welcome! We appreciate bug reports, feature requests, and pull requests.
|
|
435
|
+
|
|
436
|
+
**How to contribute:**
|
|
437
|
+
1. Fork the repository
|
|
438
|
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
439
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
440
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
441
|
+
5. Open a Pull Request
|
|
442
|
+
|
|
443
|
+
Please ensure your code follows the existing style and includes appropriate tests.
|
|
444
|
+
|
|
445
|
+
## Author
|
|
446
|
+
|
|
447
|
+
**Alexander Pechkarev**
|
|
448
|
+
- GitHub: [@alexpechkarev](https://github.com/alexpechkarev)
|
|
449
|
+
- Email: alexpechkarev@gmail.com
|
|
338
450
|
|
|
339
451
|
## License
|
|
340
452
|
|
|
341
|
-
[
|
|
453
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
<p align="center">
|
|
458
|
+
<sub>Built with β€οΈ using Svelte 5 and Google Maps Platform</sub>
|
|
459
|
+
</p>
|