places-autocomplete-svelte 2.2.1 → 2.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -79,7 +79,7 @@ let onResponse = (response) => {
79
79
  | `onResponse` | `CustomEvent` | Dispatched when a place is selected, containing the place details in `event.detail`. | Yes | |
80
80
  | `onError` | `CustomEvent` | Dispatched when an error occurs, with the error message in `event.detail`. | No | |
81
81
  | `requestParams` | `Object` | Object for additional request parameters (e.g., `types`, `bounds`, `origin`, `region`, `language`). See [AutocompleteRequest](https://developers.google.com/maps/documentation/javascript/reference/autocomplete-data#AutocompleteRequest). | No | `{}` |
82
- | `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']` |
82
+ | `fetchFields` | `Array` | Array of place data fields to return. See [Supported Fields](https://developers.google.com/maps/documentation/javascript/place-class-data-fields) documentation for a comprehensive list of available fields. Note that the Places Autocomplete service does not support the following fields, even if they are available in the Place Details API: `geometry`, `icon`, `name`, `permanentlyClosed`, `photo`, `placeId`, `url`, `utcOffset`, `vicinity`, `openingHours`, `icon`, and `name`. If you need these fields, you must make a separate call to the Place Details API using the returned `place_id`. | No | `['formattedAddress', 'addressComponents']` |
83
83
  | `options` | `Object` | Options for customizing the component's behavior and appearance. See "Customization" below. | No | See default values in "Customization" |
84
84
 
85
85
 
@@ -1,8 +1,8 @@
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 { validateOptions, validateRequestParams, formatDistance } from './helpers.js';
4
+ import type { Props } from './interfaces.js';
5
+ import { validateOptions, validateRequestParams, formatDistance, validateFetchFields } from './helpers.js';
6
6
  const { Loader } = GMaps;
7
7
 
8
8
  let {
@@ -11,7 +11,8 @@
11
11
  * @see https://developers.google.com/maps/documentation/javascript/usage-and-billing#location-placedetails
12
12
  */
13
13
  PUBLIC_GOOGLE_MAPS_API_KEY,
14
- fetchFields = $bindable(['formattedAddress', 'addressComponents']),
14
+ //fetchFields = $bindable(['formattedAddress', 'addressComponents']),
15
+ fetchFields,
15
16
  options,
16
17
  onResponse = $bindable((e: Event) => {}),
17
18
  onError = $bindable((error: string) => {}),
@@ -22,10 +23,13 @@
22
23
  options = validateOptions(options);
23
24
  //console.log(options);
24
25
 
26
+ // validate fetchFields
27
+ fetchFields = validateFetchFields(fetchFields);
28
+ //console.log(fetchFields);
29
+
25
30
  // set classes as state
26
31
  let cl = $state(options.classes);
27
32
 
28
-
29
33
  // reset keyboard classes
30
34
  const resetKbdClasses = () => {
31
35
  cl.kbd_down = options.classes.kbd_down;
@@ -39,7 +43,6 @@
39
43
  let loader: GMaps.Loader;
40
44
  let placesApi: { [key: string]: any } = {};
41
45
 
42
-
43
46
  //https://developers.google.com/maps/documentation/javascript/reference/autocomplete-data
44
47
  // validate requestParams
45
48
  requestParams = validateRequestParams(requestParams);
@@ -92,15 +95,17 @@
92
95
  const { suggestions } =
93
96
  await placesApi.AutocompleteSuggestion.fetchAutocompleteSuggestions(request);
94
97
  results = [];
95
- const formatter = new Intl.NumberFormat('en');
98
+ //const formatter = new Intl.NumberFormat('en');
96
99
  // iterate suggestions and add results to an array
97
100
  for (const suggestion of suggestions) {
98
-
99
101
  // add suggestions to results
100
102
  results.push({
101
- to_pace: suggestion.placePrediction.toPlace(),
103
+ place: suggestion.placePrediction.toPlace(),
102
104
  text: suggestion.placePrediction.text.toString(),
103
- distance: formatDistance(suggestion.placePrediction.distanceMeters, options.distance_units ?? 'km'),
105
+ distance: formatDistance(
106
+ suggestion.placePrediction.distanceMeters,
107
+ options.distance_units ?? 'km'
108
+ )
104
109
  });
105
110
  }
106
111
  } catch (e: any) {
@@ -112,13 +117,10 @@
112
117
  //https://developers-dot-devsite-v2-prod.appspot.com/maps/documentation/javascript/reference/autocomplete-data#AutocompleteSuggestion
113
118
  * @param place
114
119
  */
115
- const onPlaceSelected = async (place: {
116
- [x: string]: any;
117
- fetchFields: (arg0: { fields: string[] }) => any;
118
- addressComponents: any;
119
- formattedAddress: string;
120
- }): Promise<void> => {
120
+ const onPlaceSelected = async (place: { fetchFields: (arg0: { fields: string[]; }) => any; toJSON: () => any; }): Promise<void> => {
121
121
  try {
122
+ // console.log(place);
123
+ // console.log(fetchFields);
122
124
  await place.fetchFields({
123
125
  fields: fetchFields
124
126
  });
@@ -164,8 +166,13 @@
164
166
 
165
167
  const { AutocompleteSessionToken, AutocompleteSuggestion } =
166
168
  await loader.importLibrary('places');
169
+
167
170
  placesApi.AutocompleteSessionToken = AutocompleteSessionToken;
168
171
  placesApi.AutocompleteSuggestion = AutocompleteSuggestion;
172
+
173
+ // const {Geocoder} = await loader.importLibrary("geocoding");
174
+ // placesApi.Geocoder = new Geocoder();
175
+
169
176
  setSessionToken();
170
177
  } catch (e: any) {
171
178
  onError(
@@ -188,7 +195,7 @@
188
195
  } else if (e.key === 'Enter') {
189
196
  e.preventDefault();
190
197
  if (currentSuggestion >= 0) {
191
- onPlaceSelected(results[currentSuggestion].to_pace);
198
+ onPlaceSelected(results[currentSuggestion].place);
192
199
  }
193
200
  } else if (e.key === 'Escape') {
194
201
  // reset srarch input and results
@@ -211,7 +218,6 @@
211
218
  </div>
212
219
  {/if}
213
220
 
214
-
215
221
  <input
216
222
  type="text"
217
223
  name="search"
@@ -237,7 +243,7 @@
237
243
  </div>
238
244
 
239
245
  <ul class={options.classes.ul} id="options">
240
- {#each results as place, i}
246
+ {#each results as p, i}
241
247
  <li
242
248
  class={[options.classes.li, i === currentSuggestion && options.classes.li_current]}
243
249
  id="option-{i + 1}"
@@ -245,25 +251,39 @@
245
251
  <!-- svelte-ignore a11y_invalid_attribute -->
246
252
  <a
247
253
  href="javascript:void(0)"
248
- class={[options.classes?.li_a, 'flex justify-between']}
254
+ class={[
255
+ options.classes?.li_a,
256
+ i === currentSuggestion && options.classes.li_a_current
257
+ ]}
249
258
  tabindex={i + 1}
250
- onclick={() => onPlaceSelected(place.to_pace)}
259
+ onclick={() => onPlaceSelected(p.place)}
251
260
  >
252
- <div class="flex min-w-0 gap-x-4">
253
- <!-- <img
254
- class="size-12 flex-none rounded-full bg-gray-50"
255
- src="https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"
256
- alt=""
257
- /> -->
258
- <div class="min-w-0 flex-auto">
259
- <p class={[i === currentSuggestion && options.classes.li_current,'text-sm/6 font-semibold text-gray-900']}>{place.text}</p>
260
- <!-- <p class="mt-1 truncate text-xs/5 text-gray-500">leslie.alexander@example.com</p> -->
261
+ <div class={[options.classes.li_div_container]}>
262
+ <div
263
+ class={[
264
+ options.classes.li_div_one,
265
+ i === currentSuggestion && options.classes.li_div_current
266
+ ]}
267
+ >
268
+ <p
269
+ class={[
270
+ i === currentSuggestion && options.classes.li_current,
271
+ options.classes.li_div_one_p
272
+ ]}
273
+ >
274
+ {p.text}
275
+ </p>
261
276
  </div>
262
277
  </div>
263
- {#if options.distance && place.distance}
264
- <div class="shrink-0 flex flex-col items-end min-w-16">
265
- <p class={[i === currentSuggestion && options.classes.li_current,'mt-1 text-xs/5 text-gray-500']}>
266
- {place.distance}
278
+ {#if options.distance && p.distance}
279
+ <div class={[options.classes.li_div_two]}>
280
+ <p
281
+ class={[
282
+ i === currentSuggestion && options.classes.li_current,
283
+ options.classes.li_div_two_p
284
+ ]}
285
+ >
286
+ {p.distance}
267
287
  </p>
268
288
  </div>
269
289
  {/if}
@@ -1,4 +1,4 @@
1
1
  import type { Props } from './interfaces.js';
2
- declare const PlaceAutocomplete: import("svelte").Component<Props, {}, "fetchFields" | "onResponse" | "onError">;
2
+ declare const PlaceAutocomplete: import("svelte").Component<Props, {}, "onResponse" | "onError">;
3
3
  type PlaceAutocomplete = ReturnType<typeof PlaceAutocomplete>;
4
4
  export default PlaceAutocomplete;
package/dist/helpers.d.ts CHANGED
@@ -3,11 +3,24 @@ import type { RequestParams, ComponentOptions, ComponentClasses, DistanceUnits }
3
3
  * Default request parameters
4
4
  */
5
5
  export declare const requestParamsDefault: RequestParams;
6
+ /**
7
+ * Default fetch fields values
8
+ * https://developers.google.com/maps/documentation/javascript/place-class-data-fields
9
+ *
10
+ * unsupported field values
11
+ * geometry, icon, name, permanentlyClosed, photo, placeId, url, utcOffset, vicinity, openingHours, icon, name
12
+ */
13
+ export declare const defaultFetchFields: Array<string>;
6
14
  /**
7
15
  * Validate and cast request parameters
8
16
  * @param requestParams
9
17
  */
10
18
  export declare const validateRequestParams: (requestParams: RequestParams | undefined) => RequestParams;
19
+ /**
20
+ * Validate fetchFields array parameters
21
+ * @param fetchFields
22
+ */
23
+ export declare const validateFetchFields: (fetchFields: Array<string> | undefined) => string[];
11
24
  /**
12
25
  * Default component classes
13
26
  */
@@ -21,4 +34,10 @@ export declare const componentOptions: ComponentOptions;
21
34
  * @param options
22
35
  */
23
36
  export declare const validateOptions: (options: ComponentOptions | undefined) => ComponentOptions;
37
+ /**
38
+ * Display distance in km or miles
39
+ * @param distance
40
+ * @param units
41
+ * @returns
42
+ */
24
43
  export declare const formatDistance: (distance: number, units: DistanceUnits) => string | null;
package/dist/helpers.js CHANGED
@@ -98,6 +98,71 @@ export const requestParamsDefault = {
98
98
  */
99
99
  sessionToken: ''
100
100
  };
101
+ /**
102
+ * Default fetch fields values
103
+ * https://developers.google.com/maps/documentation/javascript/place-class-data-fields
104
+ *
105
+ * unsupported field values
106
+ * geometry, icon, name, permanentlyClosed, photo, placeId, url, utcOffset, vicinity, openingHours, icon, name
107
+ */
108
+ export const defaultFetchFields = [
109
+ 'formattedAddress',
110
+ 'addressComponents',
111
+ 'accessibilityOptions',
112
+ 'allowsDogs',
113
+ 'businessStatus',
114
+ 'hasCurbsidePickup',
115
+ 'hasDelivery',
116
+ 'hasDineIn',
117
+ 'displayName',
118
+ 'displayNameLanguageCode',
119
+ 'editorialSummary',
120
+ 'evChargeOptions',
121
+ 'adrFormatAddress',
122
+ 'fuelOptions',
123
+ 'isGoodForChildren',
124
+ 'isGoodForGroups',
125
+ 'isGoodForWatchingSports',
126
+ 'svgIconMaskURI',
127
+ 'iconBackgroundColor',
128
+ 'internationalPhoneNumber',
129
+ 'hasLiveMusic',
130
+ 'location',
131
+ 'hasMenuForChildren',
132
+ 'regularOpeningHours',
133
+ 'hasOutdoorSeating',
134
+ 'parkingOptions',
135
+ 'paymentOptions',
136
+ 'photos',
137
+ 'nationalPhoneNumber',
138
+ 'id',
139
+ 'plusCode',
140
+ 'priceLevel',
141
+ 'primaryType',
142
+ 'primaryTypeDisplayName',
143
+ 'primaryTypeDisplayNameLanguageCode',
144
+ 'rating',
145
+ 'userRatingCount',
146
+ 'isReservable',
147
+ 'hasRestroom',
148
+ 'reviews',
149
+ 'servesBeer',
150
+ 'servesBreakfast',
151
+ 'servesBrunch',
152
+ 'servesCocktails',
153
+ 'servesCoffee',
154
+ 'servesDessert',
155
+ 'servesDinner',
156
+ 'servesLunch',
157
+ 'servesVegetarianFood',
158
+ 'servesWine',
159
+ 'hasTakeout',
160
+ 'types',
161
+ 'websiteURI',
162
+ 'utcOffsetMinutes',
163
+ 'viewport',
164
+ 'websiteURI'
165
+ ];
101
166
  /**
102
167
  * Check if a variable is a valid LatLng object
103
168
  * @param latLng
@@ -188,6 +253,39 @@ export const validateRequestParams = (requestParams) => {
188
253
  //console.log('validatedParams:', validatedParams);
189
254
  return validatedParams;
190
255
  };
256
+ /**
257
+ * Validate fetchFields array parameters
258
+ * @param fetchFields
259
+ */
260
+ export const validateFetchFields = (fetchFields) => {
261
+ //https://developers.google.com/maps/documentation/javascript/place-class-data-fields
262
+ /**
263
+ * create a new object to store validated parameters
264
+ */
265
+ const validatedFetchFields = [];
266
+ if (typeof fetchFields === 'undefined' || fetchFields.length === 0) {
267
+ return [
268
+ 'formattedAddress',
269
+ 'addressComponents'
270
+ ];
271
+ }
272
+ // iterate over requestParams
273
+ for (const key of fetchFields) {
274
+ // Check if key is in requestParamsDefault
275
+ if (defaultFetchFields.includes(key)) {
276
+ validatedFetchFields.push(key);
277
+ }
278
+ }
279
+ if (validateFetchFields.length === 0) {
280
+ return [
281
+ 'formattedAddress',
282
+ 'addressComponents'
283
+ ];
284
+ }
285
+ //console.log('validatedParams:', Object.keys(validatedParams));
286
+ //console.log('validatedParams:', validatedParams);
287
+ return validatedFetchFields;
288
+ };
191
289
  /**
192
290
  * Default component classes
193
291
  */
@@ -201,10 +299,17 @@ export const componentClasses = {
201
299
  kbd_escape: 'inline-flex items-center rounded border border-gray-300 px-1 font-sans text-xs text-gray-500 w-8 mr-1',
202
300
  kbd_up: 'inline-flex items-center justify-center rounded border border-gray-300 px-1 font-sans text-xs text-gray-500 w-6',
203
301
  kbd_down: 'inline-flex items-center rounded border border-gray-400 px-1 font-sans text-xs text-gray-500 justify-center w-6',
302
+ kbd_active: 'bg-indigo-500 text-white',
204
303
  ul: 'absolute z-50 -mb-2 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm divide-y divide-gray-100',
205
304
  li: 'z-50 cursor-default select-none py-2 px-2 lg:px-4 text-gray-900 hover:bg-indigo-500 hover:text-white',
206
- li_current: 'bg-indigo-500 text-white',
207
- li_a: 'block w-full',
305
+ li_current: 'bg-indigo-500',
306
+ li_a: 'block w-full flex justify-between',
307
+ li_a_current: 'text-white',
308
+ li_div_container: 'flex min-w-0 gap-x-4',
309
+ li_div_one: 'min-w-0 flex-auto',
310
+ li_div_one_p: 'text-sm/6 font-semibold',
311
+ li_div_two: 'shrink-0 flex flex-col items-end min-w-16',
312
+ li_div_two_p: 'mt-1 text-xs/5'
208
313
  };
209
314
  /**
210
315
  * Default component options
@@ -253,6 +358,12 @@ export const validateOptions = (options) => {
253
358
  }
254
359
  return validatedOptions;
255
360
  };
361
+ /**
362
+ * Display distance in km or miles
363
+ * @param distance
364
+ * @param units
365
+ * @returns
366
+ */
256
367
  export const formatDistance = function (distance, units) {
257
368
  if (typeof distance !== 'number') {
258
369
  return null;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "places-autocomplete-svelte",
3
3
  "license": "MIT",
4
- "version": "2.2.1",
4
+ "version": "2.2.3",
5
5
  "description": "A lightweight and customizable Svelte component for easy integration of Google Maps Places (New) Autocomplete in your Svelte/SvelteKit applications. Provides accessible autocomplete suggestions and detailed address retrieval.",
6
6
  "keywords": [
7
7
  "svelte",
@@ -68,30 +68,30 @@
68
68
  },
69
69
  "devDependencies": {
70
70
  "@sveltejs/adapter-auto": "^4.0.0",
71
- "@sveltejs/adapter-cloudflare": "^5.0.2",
72
- "@sveltejs/kit": "^2.17.1",
71
+ "@sveltejs/adapter-cloudflare": "^5.0.3",
72
+ "@sveltejs/kit": "^2.17.2",
73
73
  "@sveltejs/package": "^2.3.10",
74
74
  "@sveltejs/vite-plugin-svelte": "^5.0.3",
75
- "@tailwindcss/postcss": "^4.0.5",
75
+ "@tailwindcss/postcss": "^4.0.7",
76
76
  "@tailwindcss/typography": "^0.5.16",
77
- "@tailwindcss/vite": "^4.0.5",
77
+ "@tailwindcss/vite": "^4.0.7",
78
78
  "@types/eslint": "^9.6.1",
79
79
  "autoprefixer": "^10.4.20",
80
- "eslint": "^9.20.0",
80
+ "eslint": "^9.20.1",
81
81
  "eslint-config-prettier": "^10.0.1",
82
82
  "eslint-plugin-svelte": "^2.46.1",
83
- "globals": "^15.14.0",
84
- "postcss": "^8.5.1",
85
- "prettier": "^3.4.2",
83
+ "globals": "^16.0.0",
84
+ "postcss": "^8.5.3",
85
+ "prettier": "^3.5.1",
86
86
  "prettier-plugin-svelte": "^3.3.3",
87
- "publint": "^0.3.4",
88
- "svelte": "^5.19.9",
87
+ "publint": "^0.3.6",
88
+ "svelte": "^5.20.2",
89
89
  "svelte-check": "^4.1.4",
90
- "tailwindcss": "^4.0.5",
90
+ "tailwindcss": "^4.0.7",
91
91
  "tslib": "^2.8.1",
92
92
  "typescript": "^5.7.3",
93
- "typescript-eslint": "^8.23.0",
94
- "vite": "^6.1.0"
93
+ "typescript-eslint": "^8.24.1",
94
+ "vite": "^6.1.1"
95
95
  },
96
96
  "svelte": "./dist/index.js",
97
97
  "types": "./dist/PlaceAutocomplete.svelte.d.ts",