places-autocomplete-svelte 2.0.8 → 2.1.0
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 +85 -38
- package/dist/PlaceAutocomplete.svelte +590 -52
- package/dist/PlaceAutocomplete.svelte.d.ts +3 -14
- package/dist/helpers.d.ts +7 -0
- package/dist/helpers.js +183 -0
- package/dist/interfaces.d.ts +39 -0
- package/dist/interfaces.js +1 -0
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -2,17 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
This Svelte component leverages the [Google Maps Places Autocomplete API](https://developers.google.com/maps/documentation/javascript/place-autocomplete-overview) to provide a user-friendly way to search for and retrieve detailed address information within your [SvelteKit](https://kit.svelte.dev) applications.
|
|
4
4
|
|
|
5
|
-
Preview this package [Demo](https://2bbb9bef.places-autocomplete-demo.pages.dev/)
|
|
6
5
|
|
|
7
6
|
## Features:
|
|
8
7
|
|
|
9
8
|
- **Seamless Integration:** Easily integrate the component into your SvelteKit projects.
|
|
10
|
-
- **Autocomplete Suggestions:**
|
|
9
|
+
- **Autocomplete Suggestions:** Provides real-time address suggestions as the user types.
|
|
11
10
|
- **Detailed Address Retrieval:** Retrieve comprehensive address information, including street address, city, region, postal code, and country.
|
|
12
|
-
- **Country/Region
|
|
13
|
-
- **Customizable:** Tailor the component's appearance
|
|
11
|
+
- **Country/Region Filtering:** Refine search results by specifying countries or regions.
|
|
12
|
+
- **Customizable:** Tailor the component's appearance (placeholder, language) and data retrieved (`fetchFields`).
|
|
14
13
|
- **Accessible:** Supports keyboard navigation for selecting suggestions.
|
|
15
14
|
|
|
15
|
+
## Demo
|
|
16
|
+
|
|
17
|
+
See a live demo of the component in action: [Demo](https://places-autocomplete-demo.pages.dev/)
|
|
18
|
+
|
|
16
19
|

|
|
17
20
|
|
|
18
21
|
## Requirements
|
|
@@ -55,36 +58,95 @@ npm i places-autocomplete-svelte@1.0.1
|
|
|
55
58
|
<p>Response Object: {JSON.stringify(fullResponse, null, 2)}</p>
|
|
56
59
|
```
|
|
57
60
|
|
|
58
|
-
## Countries/Regions
|
|
59
61
|
|
|
60
|
-
|
|
62
|
+
|
|
63
|
+
## Customization
|
|
64
|
+
|
|
65
|
+
- `countries`: Use countries property to refine search by region
|
|
66
|
+
- `placeholder`: Use the placeholder property to customize the input field's placeholder text.
|
|
67
|
+
- `autocomplete`: Use to disable the HTML `<input>` autocomplete attribute.
|
|
68
|
+
- `requestParams` (autocomplete request):
|
|
69
|
+
- `language`: Use the language property to set the language of the autocomplete results.
|
|
70
|
+
- `region`: Use the region property to bias the results toward a particular region. If the countries array is provided the region will be used from the selected country.
|
|
71
|
+
- `fetchFields`: Use to control the Place response
|
|
61
72
|
|
|
62
73
|
```svelte
|
|
63
74
|
<script>
|
|
64
75
|
// ... other imports
|
|
65
76
|
|
|
77
|
+
/**
|
|
78
|
+
* @type array optional
|
|
79
|
+
*/
|
|
66
80
|
let countries = [
|
|
67
|
-
{ name: 'United Kingdom', region: 'GB'
|
|
68
|
-
{ name: 'United States', region: 'US'
|
|
81
|
+
{ name: 'United Kingdom', region: 'GB'},
|
|
82
|
+
{ name: 'United States', region: 'US' }
|
|
69
83
|
// ... more countries
|
|
70
84
|
];
|
|
85
|
+
/**
|
|
86
|
+
* @type string optional
|
|
87
|
+
*/
|
|
88
|
+
const placeholder = 'Search...';
|
|
89
|
+
/**
|
|
90
|
+
* @type string optional
|
|
91
|
+
* The <input> HTML autocomplete attribute.
|
|
92
|
+
* if ommited defaults to 'off'
|
|
93
|
+
* */
|
|
94
|
+
const autocompete = 'off';
|
|
95
|
+
/**
|
|
96
|
+
* @type object optional
|
|
97
|
+
* List of accepted AutocompleteRequest properties
|
|
98
|
+
*/
|
|
99
|
+
const requestParams = {
|
|
100
|
+
/**
|
|
101
|
+
* @type string optional
|
|
102
|
+
*/
|
|
103
|
+
language : 'en-GB',
|
|
104
|
+
/**
|
|
105
|
+
* @type string optional
|
|
106
|
+
*/
|
|
107
|
+
region : 'GB',
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @type array optional
|
|
112
|
+
*/
|
|
113
|
+
const fetchFields = ['formattedAddress', 'addressComponents'];
|
|
71
114
|
</script>
|
|
72
115
|
|
|
73
|
-
<PlaceAutocomplete
|
|
116
|
+
<PlaceAutocomplete
|
|
117
|
+
{onError}
|
|
118
|
+
{onResponse}
|
|
119
|
+
{PUBLIC_GOOGLE_MAPS_API_KEY}
|
|
120
|
+
bind:countries
|
|
121
|
+
{placeholder}
|
|
122
|
+
{autocompete}
|
|
123
|
+
{fetchFields}/>
|
|
124
|
+
|
|
74
125
|
```
|
|
75
126
|
|
|
76
|
-
-
|
|
77
|
-
-
|
|
127
|
+
- `region` code follows the [CLDR two-character format](https://developers.google.com/maps/documentation/javascript/reference/autocomplete-data#AutocompleteRequest). The selected country region overwrites the `region` value in `requestParams`
|
|
128
|
+
- `language` in which to return results. If ommited defaults to the browser's language preference. [See details](https://developers.google.com/maps/documentation/javascript/reference/autocomplete-data#AutocompleteRequest.language)
|
|
129
|
+
- `requestParams` list of accepted [AutocompleteRequest properties](https://developers.google.com/maps/documentation/javascript/reference/autocomplete-data#AutocompleteRequest)
|
|
130
|
+
- `fetchFields` the [types](https://developers.google.com/maps/documentation/javascript/place-class-data-fields) of Place data to return when requesting place details. If omitted defaults to `['formattedAddress', 'addressComponents']`
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
## Component Properties
|
|
134
|
+
| Property | Type | Description | Required | Default Value |
|
|
135
|
+
|--------------------------|--------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------------------------------------------|
|
|
136
|
+
| `PUBLIC_GOOGLE_MAPS_API_KEY` | `String` | Your Google Maps Places API Key. | Yes | |
|
|
137
|
+
| `onResponse` | `CustomEvent` | Dispatched when a place is selected, containing the place details. | Yes | |
|
|
138
|
+
| `onError` | `CustomEvent` | Dispatched when an error occurs. | No | |
|
|
139
|
+
| `countries` | `Array` | Array of countries/regions to filter results. | No | `[]` |
|
|
140
|
+
| `placeholder` | `String` | Placeholder text for the input field. | No | `"Search..."` |
|
|
141
|
+
| `autocomplete` | `string` | HTML `autocomplete` attribute for the input field. Set to "off" to disable browser autocomplete. | No | `"off"` |
|
|
142
|
+
| `requestParams` | `Object` | Object for additional request parameters (e.g., `types`, `bounds`). See [AutocompleteRequest](https://developers.google.com/maps/documentation/javascript/reference/autocomplete-data#AutocompleteRequest). | No | `{}` |
|
|
143
|
+
| `fetchFields` | `Array` | Array of place data fields to return. See [Supported Fields](https://developers.google.com/maps/documentation/javascript/reference/places-service#PlaceResult) | No | `['formattedAddress', 'addressComponents']` |
|
|
78
144
|
|
|
79
145
|
|
|
80
146
|
## Error Handling
|
|
81
147
|
|
|
82
|
-
The
|
|
83
|
-
|
|
84
|
-
- The Google Maps API key is invalid or missing.
|
|
85
|
-
- There are network issues connecting to the Google Maps service.
|
|
148
|
+
The `onError` event will be dispatched if there is an issue with the Google Maps API or the autocomplete request.
|
|
86
149
|
|
|
87
|
-
Handle these errors gracefully in your application:
|
|
88
150
|
|
|
89
151
|
```svelte
|
|
90
152
|
<script>
|
|
@@ -95,36 +157,19 @@ Handle these errors gracefully in your application:
|
|
|
95
157
|
let onError = (error: string) => {
|
|
96
158
|
console.error(error);
|
|
97
159
|
pacError = error;
|
|
98
|
-
|
|
160
|
+
};
|
|
99
161
|
</script>
|
|
100
162
|
|
|
101
|
-
<PlaceAutocomplete
|
|
163
|
+
<PlaceAutocomplete
|
|
164
|
+
{onResponse}
|
|
165
|
+
{onError}
|
|
166
|
+
{PUBLIC_GOOGLE_MAPS_API_KEY} />
|
|
102
167
|
|
|
103
168
|
{#if pacError}
|
|
104
169
|
<p class="error">{pacError}</p>
|
|
105
170
|
{/if}
|
|
106
171
|
```
|
|
107
172
|
|
|
108
|
-
## Customization
|
|
109
|
-
|
|
110
|
-
- Placeholder: Use the placeholder property to customize the input field's placeholder text.
|
|
111
|
-
- Language: Use the language property to set the language of the autocomplete results.
|
|
112
|
-
- Region: Use the region property to bias the results toward a particular region. If the countries array is provided the region will be used from the selected country.
|
|
113
|
-
- Autocomplete: Use to disable the input autocomplete.
|
|
114
|
-
|
|
115
|
-
```svelte
|
|
116
|
-
<script>
|
|
117
|
-
// ... other imports
|
|
118
|
-
const placeholder = 'Search...';
|
|
119
|
-
const language = 'en-GB';
|
|
120
|
-
const region = 'GB';
|
|
121
|
-
const autocompete = 'off';
|
|
122
|
-
</script>
|
|
123
|
-
|
|
124
|
-
<PlaceAutocomplete {onError} {onResponse} {PUBLIC_GOOGLE_MAPS_API_KEY} bind:countries {placeholder} {language} {region} {autocomplete}/>
|
|
125
|
-
|
|
126
|
-
```
|
|
127
|
-
|
|
128
173
|
## Contributing
|
|
129
174
|
|
|
130
175
|
Contributions are welcome! Please open an issue or submit a pull request on the [GitHub repository](https://github.com/alexpechkarev/places-autocomplete-svelte/).
|
|
@@ -132,3 +177,5 @@ Contributions are welcome! Please open an issue or submit a pull request on the
|
|
|
132
177
|
## License
|
|
133
178
|
|
|
134
179
|
[MIT](LICENSE)
|
|
180
|
+
|
|
181
|
+
|
|
@@ -1,35 +1,26 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { onMount } from 'svelte';
|
|
3
3
|
import * as GMaps from '@googlemaps/js-api-loader';
|
|
4
|
+
import type { Props } from './interfaces.js';
|
|
5
|
+
import {
|
|
6
|
+
validateRequestParams,
|
|
7
|
+
requestParamsDefault,
|
|
8
|
+
} from './helpers.js';
|
|
4
9
|
const { Loader } = GMaps;
|
|
5
10
|
|
|
6
|
-
// Props Interface
|
|
7
|
-
interface Props {
|
|
8
|
-
PUBLIC_GOOGLE_MAPS_API_KEY: string;
|
|
9
|
-
fetchFields?: string[];
|
|
10
|
-
countries: { name: string; region: string }[];
|
|
11
|
-
placeholder?: string;
|
|
12
|
-
language?: string;
|
|
13
|
-
region?: string;
|
|
14
|
-
autocomplete?: AutoFill;
|
|
15
|
-
onResponse: (e: Event) => void;
|
|
16
|
-
onError: (error: string) => void;
|
|
17
|
-
}
|
|
18
|
-
// Bindable Props
|
|
19
11
|
let {
|
|
20
|
-
PUBLIC_GOOGLE_MAPS_API_KEY = $bindable(''),
|
|
21
12
|
/**
|
|
22
13
|
* By default using SKU: Place Detals (Location Only) - 0.005 USD per each
|
|
23
14
|
* @see https://developers.google.com/maps/documentation/javascript/usage-and-billing#location-placedetails
|
|
24
15
|
*/
|
|
16
|
+
PUBLIC_GOOGLE_MAPS_API_KEY,
|
|
25
17
|
fetchFields = $bindable(['formattedAddress', 'addressComponents']),
|
|
26
18
|
countries = $bindable([]),
|
|
27
|
-
placeholder =
|
|
28
|
-
|
|
29
|
-
region = $bindable('GB'),
|
|
30
|
-
autocomplete = $bindable('off'),
|
|
19
|
+
placeholder = 'Search...',
|
|
20
|
+
autocompete = 'off',
|
|
31
21
|
onResponse = $bindable((e: Event) => {}),
|
|
32
|
-
onError = $bindable((error: string) => {})
|
|
22
|
+
onError = $bindable((error: string) => {}),
|
|
23
|
+
requestParams
|
|
33
24
|
}: Props = $props();
|
|
34
25
|
|
|
35
26
|
// Check if countries are available
|
|
@@ -39,16 +30,12 @@
|
|
|
39
30
|
let currentSuggestion = $state(-1);
|
|
40
31
|
let title: string = $state('');
|
|
41
32
|
let results: any[] = $state([]);
|
|
42
|
-
let token;
|
|
43
33
|
let loader: GMaps.Loader;
|
|
44
34
|
let placesApi: { [key: string]: any } = {};
|
|
45
|
-
//https://developers.google.com/maps/documentation/javascript/reference/autocomplete-data
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
region: region,
|
|
50
|
-
sessionToken: ''
|
|
51
|
-
});
|
|
35
|
+
//https://developers.google.com/maps/documentation/javascript/reference/autocomplete-data
|
|
36
|
+
// validate and merge requestParams with requestParamsDefault
|
|
37
|
+
let request = $state(validateRequestParams(Object.assign(requestParamsDefault, requestParams)));
|
|
38
|
+
|
|
52
39
|
|
|
53
40
|
$effect(() => {
|
|
54
41
|
if (request.input == '') {
|
|
@@ -63,7 +50,7 @@
|
|
|
63
50
|
currentSuggestion = -1;
|
|
64
51
|
request.input = '';
|
|
65
52
|
results = [];
|
|
66
|
-
|
|
53
|
+
setSessionToken();
|
|
67
54
|
};
|
|
68
55
|
|
|
69
56
|
/**
|
|
@@ -80,16 +67,25 @@
|
|
|
80
67
|
results = [];
|
|
81
68
|
return;
|
|
82
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Prevent making request if the inputOffset is greater than the length of the input
|
|
72
|
+
* The input lenght should be greater than the inputOffset before making a request and displaying suggestions
|
|
73
|
+
*/
|
|
74
|
+
if (request.inputOffset && request.inputOffset >= target.value.length) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
83
77
|
|
|
78
|
+
// set request input
|
|
84
79
|
request.input = target.value;
|
|
85
|
-
|
|
80
|
+
|
|
81
|
+
// attempt to get autocomplete suggestions
|
|
86
82
|
try {
|
|
87
83
|
const { suggestions } =
|
|
88
84
|
await placesApi.AutocompleteSuggestion.fetchAutocompleteSuggestions(request);
|
|
89
85
|
results = [];
|
|
90
86
|
// iterate suggestions and add results to an array
|
|
91
87
|
for (const suggestion of suggestions) {
|
|
92
|
-
// add
|
|
88
|
+
// add suggestions to results
|
|
93
89
|
results.push({
|
|
94
90
|
to_pace: suggestion.placePrediction.toPlace(),
|
|
95
91
|
text: suggestion.placePrediction.text.toString()
|
|
@@ -122,35 +118,29 @@
|
|
|
122
118
|
);
|
|
123
119
|
}
|
|
124
120
|
|
|
125
|
-
// reset
|
|
121
|
+
// reset search input and results
|
|
126
122
|
reset();
|
|
127
123
|
};
|
|
128
124
|
|
|
129
125
|
/**
|
|
130
|
-
* Helper function to
|
|
131
|
-
* @param request
|
|
126
|
+
* Helper function to set the session token.
|
|
132
127
|
*/
|
|
133
|
-
const
|
|
134
|
-
input?: string;
|
|
135
|
-
language?: string;
|
|
136
|
-
region?: string;
|
|
137
|
-
sessionToken?: any;
|
|
138
|
-
}): Promise<{ input?: string; language?: string; region?: string; sessionToken?: any }> => {
|
|
128
|
+
const setSessionToken = () => {
|
|
139
129
|
try {
|
|
140
|
-
|
|
141
|
-
request.sessionToken = token;
|
|
142
|
-
return request;
|
|
130
|
+
request.sessionToken = new placesApi.AutocompleteSessionToken();
|
|
143
131
|
} catch (e: any) {
|
|
144
132
|
onError((e.name || 'An error occurred') + ' - ' + (e.message || 'error fetch token'));
|
|
145
|
-
|
|
146
|
-
}
|
|
133
|
+
}
|
|
147
134
|
};
|
|
135
|
+
|
|
148
136
|
/**
|
|
149
137
|
* Initialize the Google Maps JavaScript API Loader.
|
|
150
138
|
*/
|
|
151
139
|
onMount(async (): Promise<void> => {
|
|
140
|
+
// focus on the input
|
|
152
141
|
inputRef.focus();
|
|
153
142
|
|
|
143
|
+
// load the Google Maps API
|
|
154
144
|
try {
|
|
155
145
|
loader = new Loader({
|
|
156
146
|
apiKey: PUBLIC_GOOGLE_MAPS_API_KEY,
|
|
@@ -162,8 +152,7 @@
|
|
|
162
152
|
await loader.importLibrary('places');
|
|
163
153
|
placesApi.AutocompleteSessionToken = AutocompleteSessionToken;
|
|
164
154
|
placesApi.AutocompleteSuggestion = AutocompleteSuggestion;
|
|
165
|
-
|
|
166
|
-
request.sessionToken = token;
|
|
155
|
+
setSessionToken();
|
|
167
156
|
} catch (e: any) {
|
|
168
157
|
onError(
|
|
169
158
|
(e.name || 'An error occurred') + ' - ' + (e.message || 'Error loading Google Maps API')
|
|
@@ -217,8 +206,8 @@
|
|
|
217
206
|
name="search"
|
|
218
207
|
bind:this={inputRef}
|
|
219
208
|
class="border-1 w-full rounded-md border-0 shadow-sm bg-gray-100 px-4 py-2.5 pl-10 pr-20 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 sm:text-sm"
|
|
220
|
-
|
|
221
|
-
autocomplete={
|
|
209
|
+
{placeholder}
|
|
210
|
+
autocomplete={autocompete}
|
|
222
211
|
aria-controls="options"
|
|
223
212
|
bind:value={request.input}
|
|
224
213
|
oninput={makeAcRequest}
|
|
@@ -283,10 +272,559 @@
|
|
|
283
272
|
</select>
|
|
284
273
|
</div>
|
|
285
274
|
</div>
|
|
286
|
-
|
|
287
|
-
|
|
288
275
|
</div>
|
|
289
276
|
</section>
|
|
277
|
+
|
|
290
278
|
<style>
|
|
291
|
-
input,
|
|
292
|
-
|
|
279
|
+
input,
|
|
280
|
+
select,
|
|
281
|
+
ul {
|
|
282
|
+
margin: 0;
|
|
283
|
+
padding: 0;
|
|
284
|
+
}
|
|
285
|
+
.absolute,
|
|
286
|
+
.sr-only {
|
|
287
|
+
position: absolute;
|
|
288
|
+
}
|
|
289
|
+
.block,
|
|
290
|
+
svg {
|
|
291
|
+
display: block;
|
|
292
|
+
}
|
|
293
|
+
*,
|
|
294
|
+
.border-gray-300 {
|
|
295
|
+
--tw-border-opacity: 1;
|
|
296
|
+
}
|
|
297
|
+
.text-gray-500,
|
|
298
|
+
.text-gray-900,
|
|
299
|
+
.text-white {
|
|
300
|
+
--tw-text-opacity: 1;
|
|
301
|
+
}
|
|
302
|
+
*,
|
|
303
|
+
:after,
|
|
304
|
+
:before {
|
|
305
|
+
box-sizing: border-box;
|
|
306
|
+
border: 0 solid #e5e7eb;
|
|
307
|
+
--tw-border-spacing-x: 0;
|
|
308
|
+
--tw-border-spacing-y: 0;
|
|
309
|
+
--tw-translate-x: 0;
|
|
310
|
+
--tw-translate-y: 0;
|
|
311
|
+
--tw-rotate: 0;
|
|
312
|
+
--tw-skew-x: 0;
|
|
313
|
+
--tw-skew-y: 0;
|
|
314
|
+
--tw-scale-x: 1;
|
|
315
|
+
--tw-scale-y: 1;
|
|
316
|
+
--tw-pan-x: ;
|
|
317
|
+
--tw-pan-y: ;
|
|
318
|
+
--tw-pinch-zoom: ;
|
|
319
|
+
--tw-scroll-snap-strictness: proximity;
|
|
320
|
+
--tw-gradient-from-position: ;
|
|
321
|
+
--tw-gradient-via-position: ;
|
|
322
|
+
--tw-gradient-to-position: ;
|
|
323
|
+
--tw-ordinal: ;
|
|
324
|
+
--tw-slashed-zero: ;
|
|
325
|
+
--tw-numeric-figure: ;
|
|
326
|
+
--tw-numeric-spacing: ;
|
|
327
|
+
--tw-numeric-fraction: ;
|
|
328
|
+
--tw-ring-inset: ;
|
|
329
|
+
--tw-ring-offset-width: 0px;
|
|
330
|
+
--tw-ring-offset-color: #fff;
|
|
331
|
+
--tw-ring-color: rgb(59 130 246 / 0.5);
|
|
332
|
+
--tw-ring-offset-shadow: 0 0 #0000;
|
|
333
|
+
--tw-ring-shadow: 0 0 #0000;
|
|
334
|
+
--tw-shadow: 0 0 #0000;
|
|
335
|
+
--tw-shadow-colored: 0 0 #0000;
|
|
336
|
+
--tw-blur: ;
|
|
337
|
+
--tw-brightness: ;
|
|
338
|
+
--tw-contrast: ;
|
|
339
|
+
--tw-grayscale: ;
|
|
340
|
+
--tw-hue-rotate: ;
|
|
341
|
+
--tw-invert: ;
|
|
342
|
+
--tw-saturate: ;
|
|
343
|
+
--tw-sepia: ;
|
|
344
|
+
--tw-drop-shadow: ;
|
|
345
|
+
--tw-backdrop-blur: ;
|
|
346
|
+
--tw-backdrop-brightness: ;
|
|
347
|
+
--tw-backdrop-contrast: ;
|
|
348
|
+
--tw-backdrop-grayscale: ;
|
|
349
|
+
--tw-backdrop-hue-rotate: ;
|
|
350
|
+
--tw-backdrop-invert: ;
|
|
351
|
+
--tw-backdrop-opacity: ;
|
|
352
|
+
--tw-backdrop-saturate: ;
|
|
353
|
+
--tw-backdrop-sepia: ;
|
|
354
|
+
--tw-contain-size: ;
|
|
355
|
+
--tw-contain-layout: ;
|
|
356
|
+
--tw-contain-paint: ;
|
|
357
|
+
--tw-contain-style: ;
|
|
358
|
+
}
|
|
359
|
+
:after,
|
|
360
|
+
:before {
|
|
361
|
+
--tw-content: '';
|
|
362
|
+
}
|
|
363
|
+
:host,
|
|
364
|
+
section {
|
|
365
|
+
line-height: 1.5;
|
|
366
|
+
-webkit-text-size-adjust: 100%;
|
|
367
|
+
-moz-tab-size: 4;
|
|
368
|
+
-o-tab-size: 4;
|
|
369
|
+
tab-size: 4;
|
|
370
|
+
font-family:
|
|
371
|
+
system-ui,
|
|
372
|
+
sans-serif,
|
|
373
|
+
apple color emoji,
|
|
374
|
+
segoe ui emoji,
|
|
375
|
+
Segoe UI Symbol,
|
|
376
|
+
noto color emoji;
|
|
377
|
+
font-feature-settings: normal;
|
|
378
|
+
font-variation-settings: normal;
|
|
379
|
+
-webkit-tap-highlight-color: transparent;
|
|
380
|
+
}
|
|
381
|
+
kbd {
|
|
382
|
+
font-family:
|
|
383
|
+
ui-monospace,
|
|
384
|
+
SFMono-Regular,
|
|
385
|
+
Menlo,
|
|
386
|
+
Monaco,
|
|
387
|
+
Consolas,
|
|
388
|
+
Liberation Mono,
|
|
389
|
+
Courier New,
|
|
390
|
+
monospace;
|
|
391
|
+
font-feature-settings: normal;
|
|
392
|
+
font-variation-settings: normal;
|
|
393
|
+
font-size: 1em;
|
|
394
|
+
}
|
|
395
|
+
input,
|
|
396
|
+
select {
|
|
397
|
+
font-family: inherit;
|
|
398
|
+
font-feature-settings: inherit;
|
|
399
|
+
font-variation-settings: inherit;
|
|
400
|
+
font-size: 100%;
|
|
401
|
+
font-weight: inherit;
|
|
402
|
+
line-height: inherit;
|
|
403
|
+
letter-spacing: inherit;
|
|
404
|
+
color: inherit;
|
|
405
|
+
}
|
|
406
|
+
:-moz-focusring {
|
|
407
|
+
outline: auto;
|
|
408
|
+
}
|
|
409
|
+
:-moz-ui-invalid {
|
|
410
|
+
box-shadow: none;
|
|
411
|
+
}
|
|
412
|
+
::-webkit-inner-spin-button,
|
|
413
|
+
::-webkit-outer-spin-button {
|
|
414
|
+
height: auto;
|
|
415
|
+
}
|
|
416
|
+
::-webkit-search-decoration {
|
|
417
|
+
-webkit-appearance: none;
|
|
418
|
+
}
|
|
419
|
+
::-webkit-file-upload-button {
|
|
420
|
+
-webkit-appearance: button;
|
|
421
|
+
font: inherit;
|
|
422
|
+
}
|
|
423
|
+
ul {
|
|
424
|
+
list-style: none;
|
|
425
|
+
}
|
|
426
|
+
.cursor-default,
|
|
427
|
+
:disabled {
|
|
428
|
+
cursor: default;
|
|
429
|
+
}
|
|
430
|
+
svg {
|
|
431
|
+
vertical-align: middle;
|
|
432
|
+
}
|
|
433
|
+
[type='text'],
|
|
434
|
+
input:where(:not([type])),
|
|
435
|
+
select {
|
|
436
|
+
-webkit-appearance: none;
|
|
437
|
+
-moz-appearance: none;
|
|
438
|
+
appearance: none;
|
|
439
|
+
background-color: #fff;
|
|
440
|
+
border-color: #6b7280;
|
|
441
|
+
border-width: 1px;
|
|
442
|
+
border-radius: 0;
|
|
443
|
+
padding: 0.5rem 0.75rem;
|
|
444
|
+
font-size: 1rem;
|
|
445
|
+
line-height: 1.5rem;
|
|
446
|
+
--tw-shadow: 0 0 #0000;
|
|
447
|
+
}
|
|
448
|
+
[type='text']:focus,
|
|
449
|
+
input:where(:not([type])):focus,
|
|
450
|
+
select:focus {
|
|
451
|
+
outline: transparent solid 2px;
|
|
452
|
+
outline-offset: 2px;
|
|
453
|
+
--tw-ring-inset: var(--tw-empty,);
|
|
454
|
+
--tw-ring-offset-width: 0px;
|
|
455
|
+
--tw-ring-offset-color: #fff;
|
|
456
|
+
--tw-ring-color: #2563eb;
|
|
457
|
+
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width)
|
|
458
|
+
var(--tw-ring-offset-color);
|
|
459
|
+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width))
|
|
460
|
+
var(--tw-ring-color);
|
|
461
|
+
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
462
|
+
border-color: #2563eb;
|
|
463
|
+
}
|
|
464
|
+
input::-moz-placeholder {
|
|
465
|
+
color: #6b7280;
|
|
466
|
+
opacity: 1;
|
|
467
|
+
}
|
|
468
|
+
input::placeholder {
|
|
469
|
+
color: #6b7280;
|
|
470
|
+
opacity: 1;
|
|
471
|
+
}
|
|
472
|
+
select {
|
|
473
|
+
text-transform: none;
|
|
474
|
+
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIGZpbGw9J25vbmUnIHZpZXdCb3g9JzAgMCAyMCAyMCc+PHBhdGggc3Ryb2tlPScjNmI3MjgwJyBzdHJva2UtbGluZWNhcD0ncm91bmQnIHN0cm9rZS1saW5lam9pbj0ncm91bmQnIHN0cm9rZS13aWR0aD0nMS41JyBkPSdNNiA4bDQgNCA0LTQnLz48L3N2Zz4=);
|
|
475
|
+
background-position: right 0.5rem center;
|
|
476
|
+
background-repeat: no-repeat;
|
|
477
|
+
background-size: 1.5em 1.5em;
|
|
478
|
+
padding-right: 2.5rem;
|
|
479
|
+
-webkit-print-color-adjust: exact;
|
|
480
|
+
print-color-adjust: exact;
|
|
481
|
+
}
|
|
482
|
+
:root {
|
|
483
|
+
--background: 0 0% 100%;
|
|
484
|
+
--foreground: 222.2 84% 4.9%;
|
|
485
|
+
--muted: 210 40% 96.1%;
|
|
486
|
+
--muted-foreground: 215.4 16.3% 46.9%;
|
|
487
|
+
--popover: 0 0% 100%;
|
|
488
|
+
--popover-foreground: 222.2 84% 4.9%;
|
|
489
|
+
--card: 0 0% 100%;
|
|
490
|
+
--card-foreground: 222.2 84% 4.9%;
|
|
491
|
+
--border: 214.3 31.8% 91.4%;
|
|
492
|
+
--input: 214.3 31.8% 91.4%;
|
|
493
|
+
--primary: 222.2 47.4% 11.2%;
|
|
494
|
+
--primary-foreground: 210 40% 98%;
|
|
495
|
+
--secondary: 210 40% 96.1%;
|
|
496
|
+
--secondary-foreground: 222.2 47.4% 11.2%;
|
|
497
|
+
--accent: 210 40% 96.1%;
|
|
498
|
+
--accent-foreground: 222.2 47.4% 11.2%;
|
|
499
|
+
--destructive: 0 72.2% 50.6%;
|
|
500
|
+
--destructive-foreground: 210 40% 98%;
|
|
501
|
+
--ring: 222.2 84% 4.9%;
|
|
502
|
+
--radius: 0.5rem;
|
|
503
|
+
}
|
|
504
|
+
* {
|
|
505
|
+
border-color: hsl(var(--border) / var(--tw-border-opacity));
|
|
506
|
+
}
|
|
507
|
+
::backdrop {
|
|
508
|
+
--tw-border-spacing-x: 0;
|
|
509
|
+
--tw-border-spacing-y: 0;
|
|
510
|
+
--tw-translate-x: 0;
|
|
511
|
+
--tw-translate-y: 0;
|
|
512
|
+
--tw-rotate: 0;
|
|
513
|
+
--tw-skew-x: 0;
|
|
514
|
+
--tw-skew-y: 0;
|
|
515
|
+
--tw-scale-x: 1;
|
|
516
|
+
--tw-scale-y: 1;
|
|
517
|
+
--tw-pan-x: ;
|
|
518
|
+
--tw-pan-y: ;
|
|
519
|
+
--tw-pinch-zoom: ;
|
|
520
|
+
--tw-scroll-snap-strictness: proximity;
|
|
521
|
+
--tw-gradient-from-position: ;
|
|
522
|
+
--tw-gradient-via-position: ;
|
|
523
|
+
--tw-gradient-to-position: ;
|
|
524
|
+
--tw-ordinal: ;
|
|
525
|
+
--tw-slashed-zero: ;
|
|
526
|
+
--tw-numeric-figure: ;
|
|
527
|
+
--tw-numeric-spacing: ;
|
|
528
|
+
--tw-numeric-fraction: ;
|
|
529
|
+
--tw-ring-inset: ;
|
|
530
|
+
--tw-ring-offset-width: 0px;
|
|
531
|
+
--tw-ring-offset-color: #fff;
|
|
532
|
+
--tw-ring-color: rgb(59 130 246 / 0.5);
|
|
533
|
+
--tw-ring-offset-shadow: 0 0 #0000;
|
|
534
|
+
--tw-ring-shadow: 0 0 #0000;
|
|
535
|
+
--tw-shadow: 0 0 #0000;
|
|
536
|
+
--tw-shadow-colored: 0 0 #0000;
|
|
537
|
+
--tw-blur: ;
|
|
538
|
+
--tw-brightness: ;
|
|
539
|
+
--tw-contrast: ;
|
|
540
|
+
--tw-grayscale: ;
|
|
541
|
+
--tw-hue-rotate: ;
|
|
542
|
+
--tw-invert: ;
|
|
543
|
+
--tw-saturate: ;
|
|
544
|
+
--tw-sepia: ;
|
|
545
|
+
--tw-drop-shadow: ;
|
|
546
|
+
--tw-backdrop-blur: ;
|
|
547
|
+
--tw-backdrop-brightness: ;
|
|
548
|
+
--tw-backdrop-contrast: ;
|
|
549
|
+
--tw-backdrop-grayscale: ;
|
|
550
|
+
--tw-backdrop-hue-rotate: ;
|
|
551
|
+
--tw-backdrop-invert: ;
|
|
552
|
+
--tw-backdrop-opacity: ;
|
|
553
|
+
--tw-backdrop-saturate: ;
|
|
554
|
+
--tw-backdrop-sepia: ;
|
|
555
|
+
--tw-contain-size: ;
|
|
556
|
+
--tw-contain-layout: ;
|
|
557
|
+
--tw-contain-paint: ;
|
|
558
|
+
--tw-contain-style: ;
|
|
559
|
+
}
|
|
560
|
+
.sr-only {
|
|
561
|
+
width: 1px;
|
|
562
|
+
height: 1px;
|
|
563
|
+
padding: 0;
|
|
564
|
+
margin: -1px;
|
|
565
|
+
overflow: hidden;
|
|
566
|
+
clip: rect(0, 0, 0, 0);
|
|
567
|
+
white-space: nowrap;
|
|
568
|
+
border-width: 0;
|
|
569
|
+
}
|
|
570
|
+
.pointer-events-none {
|
|
571
|
+
pointer-events: none;
|
|
572
|
+
}
|
|
573
|
+
.relative {
|
|
574
|
+
position: relative;
|
|
575
|
+
}
|
|
576
|
+
.inset-y-0 {
|
|
577
|
+
top: 0;
|
|
578
|
+
bottom: 0;
|
|
579
|
+
}
|
|
580
|
+
.left-0 {
|
|
581
|
+
left: 0;
|
|
582
|
+
}
|
|
583
|
+
.right-0 {
|
|
584
|
+
right: 0;
|
|
585
|
+
}
|
|
586
|
+
.z-50 {
|
|
587
|
+
z-index: 50;
|
|
588
|
+
}
|
|
589
|
+
.-mb-2 {
|
|
590
|
+
margin-bottom: -0.5rem;
|
|
591
|
+
}
|
|
592
|
+
.mr-1 {
|
|
593
|
+
margin-right: 0.25rem;
|
|
594
|
+
}
|
|
595
|
+
.mt-4 {
|
|
596
|
+
margin-top: 1rem;
|
|
597
|
+
}
|
|
598
|
+
.flex {
|
|
599
|
+
display: flex;
|
|
600
|
+
}
|
|
601
|
+
.inline-flex {
|
|
602
|
+
display: inline-flex;
|
|
603
|
+
}
|
|
604
|
+
.hidden {
|
|
605
|
+
display: none;
|
|
606
|
+
}
|
|
607
|
+
.h-10 {
|
|
608
|
+
height: 2.5rem;
|
|
609
|
+
}
|
|
610
|
+
.h-5 {
|
|
611
|
+
height: 1.25rem;
|
|
612
|
+
}
|
|
613
|
+
.max-h-60 {
|
|
614
|
+
max-height: 15rem;
|
|
615
|
+
}
|
|
616
|
+
.w-5 {
|
|
617
|
+
width: 1.25rem;
|
|
618
|
+
}
|
|
619
|
+
.w-6 {
|
|
620
|
+
width: 1.5rem;
|
|
621
|
+
}
|
|
622
|
+
.w-8 {
|
|
623
|
+
width: 2rem;
|
|
624
|
+
}
|
|
625
|
+
.w-full {
|
|
626
|
+
width: 100%;
|
|
627
|
+
}
|
|
628
|
+
.transform {
|
|
629
|
+
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate))
|
|
630
|
+
skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x))
|
|
631
|
+
scaleY(var(--tw-scale-y));
|
|
632
|
+
}
|
|
633
|
+
.select-none {
|
|
634
|
+
-webkit-user-select: none;
|
|
635
|
+
-moz-user-select: none;
|
|
636
|
+
user-select: none;
|
|
637
|
+
}
|
|
638
|
+
.grid-cols-1 {
|
|
639
|
+
grid-template-columns: repeat(1, minmax(0, 1fr));
|
|
640
|
+
grid-template-columns: 1fr;
|
|
641
|
+
}
|
|
642
|
+
.items-center {
|
|
643
|
+
align-items: center;
|
|
644
|
+
}
|
|
645
|
+
.gap-x-4 {
|
|
646
|
+
-moz-column-gap: 1rem;
|
|
647
|
+
column-gap: 1rem;
|
|
648
|
+
row-gap: 1rem;
|
|
649
|
+
}
|
|
650
|
+
.rounded-md {
|
|
651
|
+
border-radius: calc(var(--radius) - 2px);
|
|
652
|
+
}
|
|
653
|
+
.rounded-xl {
|
|
654
|
+
border-radius: 0.75rem;
|
|
655
|
+
}
|
|
656
|
+
.border {
|
|
657
|
+
border-width: 1px;
|
|
658
|
+
}
|
|
659
|
+
.border-gray-300 {
|
|
660
|
+
border-color: rgb(209 213 219 / var(--tw-border-opacity));
|
|
661
|
+
}
|
|
662
|
+
.bg-gray-100 {
|
|
663
|
+
--tw-bg-opacity: 1;
|
|
664
|
+
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
|
|
665
|
+
}
|
|
666
|
+
.bg-indigo-500,
|
|
667
|
+
.hover\:bg-indigo-500:hover {
|
|
668
|
+
--tw-bg-opacity: 1;
|
|
669
|
+
background-color: rgb(99 102 241 / var(--tw-bg-opacity));
|
|
670
|
+
}
|
|
671
|
+
.bg-transparent {
|
|
672
|
+
background-color: transparent;
|
|
673
|
+
}
|
|
674
|
+
.bg-white {
|
|
675
|
+
--tw-bg-opacity: 1;
|
|
676
|
+
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
|
677
|
+
}
|
|
678
|
+
.px-1 {
|
|
679
|
+
padding-left: 0.25rem;
|
|
680
|
+
padding-right: 0.25rem;
|
|
681
|
+
}
|
|
682
|
+
.px-4 {
|
|
683
|
+
padding-left: 1rem;
|
|
684
|
+
padding-right: 1rem;
|
|
685
|
+
}
|
|
686
|
+
.py-0 {
|
|
687
|
+
padding-top: 0;
|
|
688
|
+
padding-bottom: 0;
|
|
689
|
+
}
|
|
690
|
+
.py-1 {
|
|
691
|
+
padding-top: 0.25rem;
|
|
692
|
+
padding-bottom: 0.25rem;
|
|
693
|
+
}
|
|
694
|
+
.py-1\.5 {
|
|
695
|
+
padding-top: 0.375rem;
|
|
696
|
+
padding-bottom: 0.375rem;
|
|
697
|
+
}
|
|
698
|
+
.py-2 {
|
|
699
|
+
padding-top: 0.5rem;
|
|
700
|
+
padding-bottom: 0.5rem;
|
|
701
|
+
}
|
|
702
|
+
.py-2\.5 {
|
|
703
|
+
padding-top: 0.625rem;
|
|
704
|
+
padding-bottom: 0.625rem;
|
|
705
|
+
}
|
|
706
|
+
.pl-10 {
|
|
707
|
+
padding-left: 2.5rem;
|
|
708
|
+
}
|
|
709
|
+
.pl-2 {
|
|
710
|
+
padding-left: 0.5rem;
|
|
711
|
+
}
|
|
712
|
+
.pl-3 {
|
|
713
|
+
padding-left: 0.75rem;
|
|
714
|
+
}
|
|
715
|
+
.pl-4 {
|
|
716
|
+
padding-left: 1rem;
|
|
717
|
+
}
|
|
718
|
+
.pr-1\.5 {
|
|
719
|
+
padding-right: 0.375rem;
|
|
720
|
+
}
|
|
721
|
+
.pr-20 {
|
|
722
|
+
padding-right: 5rem;
|
|
723
|
+
}
|
|
724
|
+
.pr-7 {
|
|
725
|
+
padding-right: 1.75rem;
|
|
726
|
+
}
|
|
727
|
+
.text-base {
|
|
728
|
+
font-size: 1rem;
|
|
729
|
+
line-height: 1.5rem;
|
|
730
|
+
}
|
|
731
|
+
.text-sm {
|
|
732
|
+
font-size: 0.875rem;
|
|
733
|
+
line-height: 1.25rem;
|
|
734
|
+
}
|
|
735
|
+
.text-xs {
|
|
736
|
+
font-size: 0.75rem;
|
|
737
|
+
line-height: 1rem;
|
|
738
|
+
}
|
|
739
|
+
.text-gray-500 {
|
|
740
|
+
color: rgb(107 114 128 / var(--tw-text-opacity));
|
|
741
|
+
}
|
|
742
|
+
.text-gray-900 {
|
|
743
|
+
color: rgb(17 24 39 / var(--tw-text-opacity));
|
|
744
|
+
}
|
|
745
|
+
.text-white {
|
|
746
|
+
color: rgb(255 255 255 / var(--tw-text-opacity));
|
|
747
|
+
}
|
|
748
|
+
.shadow-lg {
|
|
749
|
+
--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
750
|
+
--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color),
|
|
751
|
+
0 4px 6px -4px var(--tw-shadow-color);
|
|
752
|
+
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
|
753
|
+
var(--tw-shadow);
|
|
754
|
+
}
|
|
755
|
+
.focus\:ring-2:focus,
|
|
756
|
+
.ring-1 {
|
|
757
|
+
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width)
|
|
758
|
+
var(--tw-ring-offset-color);
|
|
759
|
+
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
|
760
|
+
}
|
|
761
|
+
.ring-1 {
|
|
762
|
+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width))
|
|
763
|
+
var(--tw-ring-color);
|
|
764
|
+
}
|
|
765
|
+
.ring-black {
|
|
766
|
+
--tw-ring-opacity: 1;
|
|
767
|
+
--tw-ring-color: rgb(0 0 0 / var(--tw-ring-opacity));
|
|
768
|
+
}
|
|
769
|
+
.focus\:outline-none:focus {
|
|
770
|
+
outline: transparent solid 2px;
|
|
771
|
+
outline-offset: 2px;
|
|
772
|
+
}
|
|
773
|
+
.focus\:ring-2:focus {
|
|
774
|
+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width))
|
|
775
|
+
var(--tw-ring-color);
|
|
776
|
+
}
|
|
777
|
+
.focus\:ring-inset:focus {
|
|
778
|
+
--tw-ring-inset: inset;
|
|
779
|
+
}
|
|
780
|
+
@media (min-width: 640px) {
|
|
781
|
+
.sm\:text-sm {
|
|
782
|
+
font-size: 0.875rem;
|
|
783
|
+
line-height: 1.25rem;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
@media (min-width: 1024px) {
|
|
787
|
+
.lg\:col-span-2 {
|
|
788
|
+
grid-column: span 2 / span 2;
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
@keyframes swipe-out {
|
|
792
|
+
0% {
|
|
793
|
+
transform: translateY(calc(var(--lift) * var(--offset) + var(--swipe-amount)));
|
|
794
|
+
opacity: 1;
|
|
795
|
+
}
|
|
796
|
+
to {
|
|
797
|
+
transform: translateY(
|
|
798
|
+
calc(var(--lift) * var(--offset) + var(--swipe-amount) + var(--lift) * -100%)
|
|
799
|
+
);
|
|
800
|
+
opacity: 0;
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
.grid {
|
|
804
|
+
display: grid;
|
|
805
|
+
}
|
|
806
|
+
@media (min-width: 768px) {
|
|
807
|
+
.lg\:grid-cols-6 {
|
|
808
|
+
grid-template-columns: repeat(6, 1fr);
|
|
809
|
+
}
|
|
810
|
+
.lg\:col-span-6 {
|
|
811
|
+
grid-column-start: span 6;
|
|
812
|
+
}
|
|
813
|
+
.lg\:col-span-4 {
|
|
814
|
+
grid-column-start: span 4;
|
|
815
|
+
}
|
|
816
|
+
.lg\:col-span-2 {
|
|
817
|
+
grid-column-start: span 2;
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
.my-10 {
|
|
821
|
+
margin-top: 2.5rem;
|
|
822
|
+
margin-bottom: 2.5rem;
|
|
823
|
+
}
|
|
824
|
+
.justify-center {
|
|
825
|
+
justify-content: center;
|
|
826
|
+
}
|
|
827
|
+
.hover\:text-white:hover {
|
|
828
|
+
color: rgb(255 255 255 / var(--tw-text-opacity));
|
|
829
|
+
}
|
|
830
|
+
</style>
|
|
@@ -1,15 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
countries: {
|
|
5
|
-
name: string;
|
|
6
|
-
region: string;
|
|
7
|
-
}[];
|
|
8
|
-
placeholder?: string;
|
|
9
|
-
language?: string;
|
|
10
|
-
region?: string;
|
|
11
|
-
autocomplete?: AutoFill;
|
|
12
|
-
onResponse: (e: Event) => void;
|
|
13
|
-
onError: (error: string) => void;
|
|
14
|
-
}, {}, "PUBLIC_GOOGLE_MAPS_API_KEY" | "fetchFields" | "countries" | "placeholder" | "language" | "region" | "autocomplete" | "onResponse" | "onError">;
|
|
1
|
+
import type { Props } from './interfaces.js';
|
|
2
|
+
declare const PlaceAutocomplete: import("svelte").Component<Props, {}, "fetchFields" | "countries" | "onResponse" | "onError">;
|
|
3
|
+
type PlaceAutocomplete = ReturnType<typeof PlaceAutocomplete>;
|
|
15
4
|
export default PlaceAutocomplete;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RequestParams } from './interfaces.js';
|
|
2
|
+
export declare const requestParamsDefault: RequestParams;
|
|
3
|
+
/**
|
|
4
|
+
* Validate and cast request parameters
|
|
5
|
+
* @param requestParams
|
|
6
|
+
*/
|
|
7
|
+
export declare const validateRequestParams: (requestParams: RequestParams) => RequestParams;
|
package/dist/helpers.js
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
export const requestParamsDefault = {
|
|
2
|
+
/**
|
|
3
|
+
* @type string required
|
|
4
|
+
* The text string on which to search.
|
|
5
|
+
*/
|
|
6
|
+
input: '',
|
|
7
|
+
/**
|
|
8
|
+
* @type Array<string>
|
|
9
|
+
* A Place is only returned if its primary type is included in this list.
|
|
10
|
+
* Up to 5 values can be specified.
|
|
11
|
+
* If no types are specified, all Place types are returned.
|
|
12
|
+
* https://developers.google.com/maps/documentation/javascript/place-types
|
|
13
|
+
*
|
|
14
|
+
* ['postal_code','premise','street_address','route']
|
|
15
|
+
* FY83DD 72
|
|
16
|
+
*/
|
|
17
|
+
//includedPrimaryTypes: ['postal_code','premise','street_address','route'],
|
|
18
|
+
includedPrimaryTypes: [],
|
|
19
|
+
/**
|
|
20
|
+
* @type Array<string> optional
|
|
21
|
+
* Only include results in the specified regions, specified as up to 15 CLDR two-character region codes.
|
|
22
|
+
* An empty set will not restrict the results.
|
|
23
|
+
* If both locationRestriction and includedRegionCodes are set, the results will be located in the area of intersection.
|
|
24
|
+
*/
|
|
25
|
+
includedRegionCodes: ['GB'],
|
|
26
|
+
/**
|
|
27
|
+
* @type number optional
|
|
28
|
+
* A zero-based Unicode character offset of input indicating the cursor position in input.
|
|
29
|
+
* The cursor position may influence what predictions are returned. If not specified, defaults to the length of input.
|
|
30
|
+
*/
|
|
31
|
+
inputOffset: 0,
|
|
32
|
+
/**
|
|
33
|
+
* @type string optional
|
|
34
|
+
* The language in which to return results. Will default to the browser's language preference.
|
|
35
|
+
*
|
|
36
|
+
*/
|
|
37
|
+
language: 'en-GB',
|
|
38
|
+
/**
|
|
39
|
+
* @type LocationBias optional
|
|
40
|
+
* Bias results to a specified location.
|
|
41
|
+
*
|
|
42
|
+
* At most one of locationBias or locationRestriction should be set.
|
|
43
|
+
* If neither are set, the results will be biased by IP address, meaning the IP address
|
|
44
|
+
* will be mapped to an imprecise location and used as a biasing signal.
|
|
45
|
+
*/
|
|
46
|
+
locationBias: null,
|
|
47
|
+
/**
|
|
48
|
+
* @param LocationRestriction optional
|
|
49
|
+
* Restrict results to a specified location.
|
|
50
|
+
*
|
|
51
|
+
* At most one of locationBias or locationRestriction should be set.
|
|
52
|
+
* If neither are set, the results will be biased by IP address, meaning the IP address will
|
|
53
|
+
* be mapped to an imprecise location and used as a biasing signal.
|
|
54
|
+
*/
|
|
55
|
+
locationRestriction: {
|
|
56
|
+
west: 0,
|
|
57
|
+
south: 0,
|
|
58
|
+
east: 0,
|
|
59
|
+
north: 0
|
|
60
|
+
},
|
|
61
|
+
/**
|
|
62
|
+
* @type LatLng|LatLngLiteral optional
|
|
63
|
+
* The point around which you wish to retrieve place information.
|
|
64
|
+
*/
|
|
65
|
+
origin: {
|
|
66
|
+
lat: 0,
|
|
67
|
+
lng: 0
|
|
68
|
+
},
|
|
69
|
+
/**
|
|
70
|
+
* @type string optional
|
|
71
|
+
* The region code, specified as a CLDR two-character region code. T
|
|
72
|
+
* his affects address formatting, result ranking, and may influence what results are returned.
|
|
73
|
+
* This does not restrict results to the specified region.
|
|
74
|
+
*/
|
|
75
|
+
region: 'GB',
|
|
76
|
+
/**
|
|
77
|
+
* @type AutocompleteSessionToken optional
|
|
78
|
+
*
|
|
79
|
+
* A token which identifies an Autocomplete session for billing purposes.
|
|
80
|
+
* Generate a new session token via AutocompleteSessionToken The session begins when the user starts typing a query, and concludes
|
|
81
|
+
* when they select a place and call Place.fetchFields. Each session can have multiple queries, followed by one fetchFields call.
|
|
82
|
+
* The credentials used for each request within a session must belong to the same Google Cloud Console project. Once a session has
|
|
83
|
+
* concluded, the token is no longer valid; your app must generate a fresh token for each session. If the sessionToken parameter is
|
|
84
|
+
* omitted, or if you reuse a session token, the session is charged as if no session token was provided (each request is billed
|
|
85
|
+
* separately).
|
|
86
|
+
*
|
|
87
|
+
* We recommend the following guidelines:
|
|
88
|
+
* Use session tokens for all Place Autocomplete calls.
|
|
89
|
+
* Generate a fresh token for each session.
|
|
90
|
+
* Be sure to pass a unique session token for each new session. Using the same token for more than one session will result in each
|
|
91
|
+
* request being billed individually.
|
|
92
|
+
*/
|
|
93
|
+
sessionToken: ''
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Validate and cast request parameters
|
|
97
|
+
* @param requestParams
|
|
98
|
+
*/
|
|
99
|
+
export const validateRequestParams = (requestParams) => {
|
|
100
|
+
// https://developers.google.com/maps/documentation/javascript/reference/autocomplete-data
|
|
101
|
+
/**
|
|
102
|
+
* If requestParams is not an object, set it to an empty object
|
|
103
|
+
*/
|
|
104
|
+
if (typeof requestParams !== 'object') {
|
|
105
|
+
requestParams = {
|
|
106
|
+
input: String(''),
|
|
107
|
+
sessionToken: String(''),
|
|
108
|
+
};
|
|
109
|
+
return requestParams;
|
|
110
|
+
}
|
|
111
|
+
// Remove any keys that are not in requestParamsDefault
|
|
112
|
+
for (const key in requestParams) {
|
|
113
|
+
if (!(key in requestParamsDefault)) {
|
|
114
|
+
delete requestParams[key];
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Reset sessionToken to empty string if passed to the component
|
|
118
|
+
if (requestParams.sessionToken) {
|
|
119
|
+
requestParams.sessionToken = String('');
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* If requestParams.input is not a string, set it to an empty string
|
|
123
|
+
*/
|
|
124
|
+
if (typeof requestParams.input !== 'string') {
|
|
125
|
+
requestParams.input = String('');
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* If requestParams.includedPrimaryTypes is not an array or is an empty array, remove it
|
|
129
|
+
* If requestParams.includedPrimaryTypes is an array and has more than 5 items, slice it to 5
|
|
130
|
+
*/
|
|
131
|
+
if (!Array.isArray(requestParams.includedPrimaryTypes)
|
|
132
|
+
|| (Array.isArray(requestParams.includedPrimaryTypes) && requestParams.includedPrimaryTypes.length === 0)) {
|
|
133
|
+
delete requestParams.includedPrimaryTypes;
|
|
134
|
+
}
|
|
135
|
+
else if (Array.isArray(requestParams.includedPrimaryTypes) && requestParams.includedPrimaryTypes.length > 5) {
|
|
136
|
+
requestParams.includedPrimaryTypes = requestParams.includedPrimaryTypes.slice(0, 5);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* If requestParams.includedRegionCodes is not an array or is an empty array, remove it
|
|
140
|
+
* If requestParams.includedRegionCodes is an array and has more than 15 items, slice it to 15
|
|
141
|
+
*/
|
|
142
|
+
if (!Array.isArray(requestParams.includedRegionCodes)
|
|
143
|
+
|| (Array.isArray(requestParams.includedPrimaryTypes) && requestParams.includedPrimaryTypes.length === 0)) {
|
|
144
|
+
delete requestParams.includedRegionCodes;
|
|
145
|
+
}
|
|
146
|
+
else if (Array.isArray(requestParams.includedRegionCodes) && requestParams.includedRegionCodes.length > 15) {
|
|
147
|
+
requestParams.includedRegionCodes = requestParams.includedRegionCodes.slice(0, 15);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* If requestParams.inputOffset is not a number or is less than 1, remove it
|
|
151
|
+
*/
|
|
152
|
+
if (typeof requestParams.inputOffset !== 'number'
|
|
153
|
+
|| (typeof requestParams.inputOffset === 'number' && requestParams.inputOffset < 1)) {
|
|
154
|
+
delete requestParams.inputOffset;
|
|
155
|
+
}
|
|
156
|
+
// If language is not a string, remove it
|
|
157
|
+
if (typeof requestParams.language !== 'string') {
|
|
158
|
+
delete requestParams.language;
|
|
159
|
+
}
|
|
160
|
+
// If locationBias is not a string, remove it
|
|
161
|
+
if (typeof requestParams.locationBias !== 'string') {
|
|
162
|
+
delete requestParams.locationBias;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* If locationRestriction is not set, remove it
|
|
166
|
+
*/
|
|
167
|
+
if (requestParams.locationRestriction?.east === 0
|
|
168
|
+
&& requestParams.locationRestriction?.north === 0
|
|
169
|
+
&& requestParams.locationRestriction?.south === 0
|
|
170
|
+
&& requestParams.locationRestriction?.west === 0) {
|
|
171
|
+
delete requestParams.locationRestriction;
|
|
172
|
+
}
|
|
173
|
+
// If origin is not set, remove it
|
|
174
|
+
if (requestParams.origin?.lat === 0 && requestParams.origin?.lng === 0) {
|
|
175
|
+
delete requestParams.origin;
|
|
176
|
+
}
|
|
177
|
+
// If region is not a string, remove it
|
|
178
|
+
if (typeof requestParams.region !== 'string') {
|
|
179
|
+
delete requestParams.region;
|
|
180
|
+
}
|
|
181
|
+
//console.log('requestParams:', Object.keys(requestParams));
|
|
182
|
+
return requestParams;
|
|
183
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @interface RequestParams
|
|
3
|
+
* https://developers.google.com/maps/documentation/javascript/reference/autocomplete-data
|
|
4
|
+
*/
|
|
5
|
+
export interface RequestParams {
|
|
6
|
+
input: string;
|
|
7
|
+
includedPrimaryTypes?: string[];
|
|
8
|
+
includedRegionCodes?: string[];
|
|
9
|
+
inputOffset?: number;
|
|
10
|
+
language?: string;
|
|
11
|
+
locationBias?: unknown | string;
|
|
12
|
+
locationRestriction?: {
|
|
13
|
+
west: number;
|
|
14
|
+
south: number;
|
|
15
|
+
east: number;
|
|
16
|
+
north: number;
|
|
17
|
+
};
|
|
18
|
+
origin?: {
|
|
19
|
+
lat: number;
|
|
20
|
+
lng: number;
|
|
21
|
+
};
|
|
22
|
+
region?: string;
|
|
23
|
+
sessionToken?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface Props {
|
|
26
|
+
PUBLIC_GOOGLE_MAPS_API_KEY: string;
|
|
27
|
+
fetchFields?: string[];
|
|
28
|
+
countries: {
|
|
29
|
+
name: string;
|
|
30
|
+
region: string;
|
|
31
|
+
}[];
|
|
32
|
+
placeholder?: string;
|
|
33
|
+
language?: string;
|
|
34
|
+
region?: string;
|
|
35
|
+
autocompete?: AutoFill;
|
|
36
|
+
requestParams: RequestParams;
|
|
37
|
+
onResponse: (e: Event) => void;
|
|
38
|
+
onError: (error: string) => void;
|
|
39
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "places-autocomplete-svelte",
|
|
3
3
|
"license": "MIT",
|
|
4
|
-
"version": "2.0
|
|
4
|
+
"version": "2.1.0",
|
|
5
5
|
"description": "A lightweight and customizable Svelte component for easy integration of Google Maps Places Autocomplete (New API) in your Svelte/SvelteKit applications. Provides accessible autocomplete suggestions and detailed address retrieval.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"svelte",
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
"address",
|
|
16
16
|
"address-input",
|
|
17
17
|
"input",
|
|
18
|
-
"search",
|
|
18
|
+
"search",
|
|
19
19
|
"new api"
|
|
20
20
|
],
|
|
21
|
-
"homepage": "https://
|
|
21
|
+
"homepage": "https://places-autocomplete-demo.pages.dev",
|
|
22
22
|
"repository": {
|
|
23
23
|
"type": "git",
|
|
24
24
|
"url": "git+https://github.com/alexpechkarev/places-autocomplete-svelte.git"
|
|
@@ -69,26 +69,26 @@
|
|
|
69
69
|
"devDependencies": {
|
|
70
70
|
"@sveltejs/adapter-auto": "^3.3.1",
|
|
71
71
|
"@sveltejs/adapter-cloudflare": "^4.7.4",
|
|
72
|
-
"@sveltejs/kit": "^2.
|
|
72
|
+
"@sveltejs/kit": "^2.8.0",
|
|
73
73
|
"@sveltejs/package": "^2.3.7",
|
|
74
74
|
"@sveltejs/vite-plugin-svelte": "^4.0.0",
|
|
75
75
|
"@tailwindcss/typography": "^0.5.15",
|
|
76
76
|
"@types/eslint": "^9.6.1",
|
|
77
77
|
"autoprefixer": "^10.4.20",
|
|
78
|
-
"eslint": "^9.
|
|
78
|
+
"eslint": "^9.14.0",
|
|
79
79
|
"eslint-config-prettier": "^9.1.0",
|
|
80
80
|
"eslint-plugin-svelte": "^2.46.0",
|
|
81
|
-
"globals": "^15.
|
|
81
|
+
"globals": "^15.12.0",
|
|
82
82
|
"postcss": "^8.4.47",
|
|
83
83
|
"prettier": "^3.3.3",
|
|
84
84
|
"prettier-plugin-svelte": "^3.2.7",
|
|
85
85
|
"publint": "^0.2.12",
|
|
86
|
-
"svelte": "^5.1.
|
|
87
|
-
"svelte-check": "^4.0.
|
|
86
|
+
"svelte": "^5.1.12",
|
|
87
|
+
"svelte-check": "^4.0.6",
|
|
88
88
|
"tailwindcss": "^3.4.14",
|
|
89
|
-
"tslib": "^2.8.
|
|
89
|
+
"tslib": "^2.8.1",
|
|
90
90
|
"typescript": "^5.6.3",
|
|
91
|
-
"typescript-eslint": "^8.
|
|
91
|
+
"typescript-eslint": "^8.13.0",
|
|
92
92
|
"vite": "^5.4.10"
|
|
93
93
|
},
|
|
94
94
|
"svelte": "./dist/index.js",
|