novo-elements
Version:
715 lines (708 loc) • 32.3 kB
JavaScript
import * as i3 from '@angular/common';
import { isPlatformBrowser, CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { PLATFORM_ID, Inject, Injectable, forwardRef, EventEmitter, Output, Input, Component, NgModule, InjectionToken } from '@angular/core';
import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';
import { BasePickerResults } from 'novo-elements/elements/picker';
import * as i2 from 'novo-elements/services';
import { Observable } from 'rxjs';
import * as i1 from '@angular/common/http';
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import * as i4 from 'novo-elements/elements/list';
import { NovoListModule } from 'novo-elements/elements/list';
class GooglePlacesService {
constructor(_http, platformId, _global, _localStorageService) {
this._http = _http;
this.platformId = platformId;
this._global = _global;
this._localStorageService = _localStorageService;
}
getPredictions(url, query) {
return new Promise((resolve) => {
const separator = url.includes('?') ? '&' : '?';
this._http.get(url + separator + 'query=' + query).subscribe((data) => {
if (data) {
resolve(data);
}
else {
resolve(false);
}
});
});
}
getLatLngDetail(url, lat, lng) {
return new Promise((resolve) => {
const separator = url.includes('?') ? '&' : '?';
this._http.get(url + separator + 'lat=' + lat + '&lng=' + lng).subscribe((data) => {
if (data) {
resolve(data);
}
else {
resolve(false);
}
});
});
}
getPlaceDetails(url, placeId) {
return new Promise((resolve) => {
const separator = url.includes('?') ? '&' : '?';
this._http.get(url + separator + 'query=' + placeId).subscribe((data) => {
if (data) {
resolve(data);
}
else {
resolve(false);
}
});
});
}
getGeoCurrentLocation() {
return new Promise((resolve) => {
if (isPlatformBrowser(this.platformId)) {
const _window = this._global.nativeGlobal;
if (_window.navigator.geolocation) {
_window.navigator.geolocation.getCurrentPosition((pos) => {
const latlng = { lat: parseFloat(pos.coords.latitude + ''), lng: parseFloat(pos.coords.longitude + '') };
resolve(latlng);
});
}
else {
resolve(false);
}
}
else {
resolve(false);
}
});
}
getGeoLatLngDetail(latlng) {
return new Promise((resolve) => {
if (isPlatformBrowser(this.platformId)) {
const _window = this._global.nativeGlobal;
const geocoder = new _window.google.maps.Geocoder();
geocoder.geocode({ location: latlng }, (results, status) => {
if (status === 'OK') {
this.getGeoPlaceDetail(results[0].place_id).then((result) => {
if (result) {
resolve(result);
}
else {
resolve(false);
}
});
}
else {
resolve(false);
}
});
}
else {
resolve(false);
}
});
}
getGeoPrediction(params) {
return new Promise((resolve) => {
if (isPlatformBrowser(this.platformId)) {
const _window = this._global.nativeGlobal;
const placesService = new _window.google.maps.places.AutocompleteService();
let queryInput = {};
const promiseArr = [];
if (params.countryRestriction.length) {
queryInput = {
input: params.query,
componentRestrictions: { country: params.countryRestriction },
};
}
else {
queryInput = {
input: params.query,
};
}
if (params.geoLocation) {
queryInput.location = new _window.google.maps.LatLng(parseFloat(params.geoLocation[0]), parseFloat(params.geoLocation[1]));
queryInput.radius = params.radius;
}
if (params.geoTypes.length) {
for (let i = 0; i < params.geoTypes.length; i++) {
const _tempQuery = queryInput;
_tempQuery.types = new Array(params.geoTypes[i]);
promiseArr.push(this.geoPredictionCall(placesService, _tempQuery));
}
}
else {
promiseArr.push(this.geoPredictionCall(placesService, queryInput));
}
Promise.all(promiseArr).then((values) => {
const val = values;
if (val.length > 1) {
let _tempArr = [];
for (let j = 0; j < val.length; j++) {
if (val[j] && val[j].length) {
_tempArr = _tempArr.concat(val[j]);
}
}
_tempArr = this.getUniqueResults(_tempArr);
resolve(_tempArr);
}
else {
resolve(values[0]);
}
});
}
else {
resolve(false);
}
});
}
async getGeoPlaceDetail(placeId) {
const placeDetail = await new Promise((resolve) => {
if (isPlatformBrowser(this.platformId)) {
const _window = this._global.nativeGlobal;
const placesService = new _window.google.maps.places.PlacesService(document.createElement('div'));
placesService.getDetails({ placeId }, (result) => {
if (result === null || result.length === 0) {
this.getGeoPaceDetailByReferance(result.referance).then((referanceData) => {
if (!referanceData) {
resolve(false);
}
else {
resolve(referanceData);
}
});
}
else {
resolve(result);
}
});
}
else {
resolve(false);
}
});
if (placeDetail?.types?.includes('locality')) {
placeDetail.postal_codes = await this.getPostalCodes(placeDetail);
}
return placeDetail;
}
getGeoPaceDetailByReferance(referance) {
return new Promise((resolve) => {
if (isPlatformBrowser(this.platformId)) {
const _window = this._global.nativeGlobal;
const placesService = new _window.google.maps.places.PlacesService();
placesService.getDetails({ reference: referance }, (result, status) => {
if (status === _window.google.maps.places.PlacesServiceStatus.OK) {
resolve(result);
}
else {
resolve(false);
}
});
}
else {
resolve(false);
}
});
}
addRecentList(localStorageName, result, itemSavedLength) {
this.getRecentList(localStorageName).then((data) => {
if (data) {
for (let i = 0; i < data.length; i++) {
if (data[i].description === result.description) {
data.splice(i, 1);
break;
}
}
data.unshift(result);
if (data.length > itemSavedLength) {
data.pop();
}
this._localStorageService.setItem(localStorageName, JSON.stringify(data));
}
});
}
getRecentList(localStorageName) {
return new Promise((resolve) => {
let value = this._localStorageService.getItem(localStorageName);
if (value) {
value = JSON.parse(value);
}
else {
value = [];
}
resolve(value);
});
}
getPostalCodes(placeDetail) {
const _window = this._global.nativeGlobal;
const geocoder = new _window.google.maps.Geocoder();
return new Promise((resolve) => {
geocoder.geocode({ location: placeDetail.geometry.location }, (results, status) => {
if (status === 'OK' && results.length) {
resolve(results.reduce((postalCodes, result) => {
const postalCodeComponent = result.address_components.find(item => item.types.includes('postal_code'));
if (postalCodeComponent && !postalCodes.includes(postalCodeComponent.long_name)) {
postalCodes.push(postalCodeComponent.long_name);
}
return postalCodes;
}, []));
}
else {
resolve(null);
}
});
});
}
getUniqueResults(arr) {
return Array.from(arr.reduce((m, t) => m.set(t.place_id, t), new Map()).values());
}
geoPredictionCall(placesService, queryInput) {
const _window = this._global.nativeGlobal;
return new Promise((resolve) => {
placesService.getPlacePredictions(queryInput, (result, status) => {
if (status === _window.google.maps.places.PlacesServiceStatus.OK) {
resolve(result);
}
else {
resolve(false);
}
});
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GooglePlacesService, deps: [{ token: i1.HttpClient }, { token: PLATFORM_ID }, { token: i2.GlobalRef }, { token: i2.LocalStorageService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GooglePlacesService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GooglePlacesService, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: Object, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }, { type: i2.GlobalRef }, { type: i2.LocalStorageService }] });
// NG2
// Value accessor for the component (supports ngModel)
const PLACES_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => PlacesListComponent),
multi: true,
};
class PlacesListComponent extends BasePickerResults {
constructor(platformId, _elmRef, _global, _googlePlacesService, cdr) {
super(_elmRef, cdr);
this.platformId = platformId;
this._elmRef = _elmRef;
this._global = _global;
this._googlePlacesService = _googlePlacesService;
this.cdr = cdr;
this.termChange = new EventEmitter();
this.select = new EventEmitter();
this.matchesUpdated = new EventEmitter();
this.locationInput = '';
this.gettingCurrentLocationFlag = false;
this.dropdownOpen = false;
this.recentDropdownOpen = false;
this.isSettingsError = false;
this.settingsErrorMsg = '';
this.settings = {};
this.moduleinit = false;
this.selectedDataIndex = -1;
this.recentSearchData = [];
this.userSelectedOption = '';
this.defaultSettings = {
geoPredictionServerUrl: '',
geoLatLangServiceUrl: '',
geoLocDetailServerUrl: '',
geoCountryRestriction: [],
geoTypes: [],
geoLocation: [],
geoRadius: 0,
serverResponseListHierarchy: [],
serverResponseatLangHierarchy: [],
serverResponseDetailHierarchy: [],
resOnSearchButtonClickOnly: false,
useGoogleGeoApi: true,
inputPlaceholderText: 'Enter Area Name',
inputString: '',
showSearchButton: true,
showRecentSearch: true,
showCurrentLocation: true,
recentStorageName: 'recentSearches',
noOfRecentSearchSave: 5,
currentLocIconUrl: '',
searchIconUrl: '',
locationIconUrl: '',
};
this.onModelChange = () => { };
this.onModelTouched = () => { };
this.config = {};
}
ngOnInit() {
if (!this.moduleinit) {
this.moduleInit();
}
}
ngOnChanges() {
this.moduleinit = true;
this.moduleInit();
this.searchinputCallback(null);
}
writeValue(model) {
this.model = model;
}
registerOnChange(fn) {
this.onModelChange = fn;
}
registerOnTouched(fn) {
this.onModelTouched = fn;
}
// function called when click event happens in input box. (Binded with view)
searchinputClickCallback(event) {
event.target.select();
this.searchinputCallback(event);
}
// function called when there is a change in input. (Binded with view)
searchinputCallback(event) {
const inputVal = this.locationInput;
if (inputVal) {
this.getListQuery(inputVal);
}
else {
this.matches = [];
if (this.userSelectedOption) {
this.userQuerySubmit('false');
}
this.userSelectedOption = '';
if (this.settings.showRecentSearch) {
this.showRecentSearch();
}
else {
this.dropdownOpen = false;
}
}
}
// function to execute when user hover over autocomplete list. (binded with view)
activeListNode(index) {
for (let i = 0; i < this.matches.length; i++) {
if (index === i) {
this.matches[i].active = true;
this.selectedDataIndex = index;
}
else {
this.matches[i].active = false;
}
}
}
// function to execute when user selects a match from the autocomplete list. (binded with view)
selectedListNode(event, index) {
this.selectMatch(this.matches[index]);
}
// function to execute when user selects a match.
selectMatch(match) {
this.dropdownOpen = false;
if (this.recentDropdownOpen) {
// Recent items carry full detail on `raw`, which downstream consumers need.
this.setRecentLocation(match.raw ?? match);
}
else {
this.getPlaceLocationInfo(match);
}
}
// function to close the autocomplete list when clicked outside. (binded with view)
closeAutocomplete(event) {
if (!this._elmRef.nativeElement.contains(event.target)) {
this.selectedDataIndex = -1;
this.dropdownOpen = false;
}
}
// function to manually trigger the callback to parent component when clicked search button.
userQuerySubmit(selectedOption) {
const _userOption = selectedOption === 'false' ? '' : this.userSelectedOption;
if (_userOption) {
this.select.emit(this.userSelectedOption);
}
else {
// this.select.emit(false);
}
}
// function to get user current location from the device.
currentLocationSelected() {
if (isPlatformBrowser(this.platformId)) {
this.gettingCurrentLocationFlag = true;
this.dropdownOpen = false;
this._googlePlacesService.getGeoCurrentLocation().then((result) => {
if (!result) {
this.gettingCurrentLocationFlag = false;
}
else {
this.getCurrentLocationInfo(result);
}
});
}
}
// module initialization happens. function called by ngOninit and ngOnChange
moduleInit() {
this.settings = this.setUserSettings();
// condition to check if Radius is set without location detail.
if (this.settings.geoRadius) {
if (this.settings.geoLocation.length !== 2) {
this.isSettingsError = true;
this.settingsErrorMsg =
this.settingsErrorMsg + 'Radius should be used with GeoLocation. Please use "geoLocation" key to set lat and lng. ';
}
}
// condition to check if lat and lng is set and radious is not set then it will set to 20,000KM by default
if (this.settings.geoLocation.length === 2 && !this.settings.geoRadius) {
this.settings.geoRadius = 20000000;
}
if (this.settings.showRecentSearch) {
this.getRecentLocations();
}
if (!this.settings.useGoogleGeoApi) {
if (!this.settings.geoPredictionServerUrl) {
this.isSettingsError = true;
this.settingsErrorMsg =
this.settingsErrorMsg + 'Prediction custom server url is not defined. Please use "geoPredictionServerUrl" key to set. ';
}
if (!this.settings.geoLatLangServiceUrl) {
this.isSettingsError = true;
this.settingsErrorMsg =
this.settingsErrorMsg + 'Latitude and longitude custom server url is not defined. Please use "geoLatLangServiceUrl" key to set. ';
}
if (!this.settings.geoLocDetailServerUrl) {
this.isSettingsError = true;
this.settingsErrorMsg =
this.settingsErrorMsg + 'Location detail custom server url is not defined. Please use "geoLocDetailServerUrl" key to set. ';
}
}
this.locationInput = this.term;
}
// function to process the search query when pressed enter.
processSearchQuery() {
if (this.matches.length) {
if (this.selectedDataIndex > -1) {
this.selectedListNode(null, this.selectedDataIndex);
}
else {
this.selectedListNode(null, 0);
}
}
}
// function to set user settings if it is available.
setUserSettings() {
const _tempObj = {};
if (this.userSettings && typeof this.userSettings === 'object') {
const keys = Object.keys(this.defaultSettings);
for (const value of keys) {
_tempObj[value] = this.userSettings[value] !== undefined ? this.userSettings[value] : this.defaultSettings[value];
}
return _tempObj;
}
else {
return this.defaultSettings;
}
}
// function to get the autocomplete list based on user input.
getListQuery(value) {
this.recentDropdownOpen = false;
if (this.settings.useGoogleGeoApi) {
const _tempParams = {
query: value,
countryRestriction: this.settings.geoCountryRestriction,
geoTypes: this.settings.geoTypes,
};
if (this.settings.geoLocation.length === 2) {
_tempParams.geoLocation = this.settings.geoLocation;
_tempParams.radius = this.settings.geoRadius;
}
this._googlePlacesService.getGeoPrediction(_tempParams).then((result) => {
this.updateListItem(result);
});
}
else {
this._googlePlacesService.getPredictions(this.settings.geoPredictionServerUrl, value).then((result) => {
result = this.extractServerList(this.settings.serverResponseListHierarchy, result);
this.updateListItem(result);
});
}
}
// function to extratc custom data which is send by the server.
extractServerList(arrayList, data) {
if (arrayList.length) {
let _tempData = data;
for (const key of arrayList) {
_tempData = _tempData[key];
}
return _tempData;
}
else {
return data;
}
}
// function to update the predicted list.
updateListItem(listData) {
this.matches = (listData || []).map((item) => this.normalizePrediction(item));
// Reset highlight so Enter can't act on a stale prediction.
this.activeMatch = undefined;
this.dropdownOpen = true;
this.cdr.detectChanges();
this.matchesUpdated.emit(this.matches);
}
// function to show the recent search result.
showRecentSearch() {
this.recentDropdownOpen = true;
this.dropdownOpen = true;
this._googlePlacesService.getRecentList(this.settings.recentStorageName).then((result) => {
this.matches = (result || []).map((item) => this.normalizePrediction(item));
});
}
// function to execute to get location detail based on latitude and longitude.
getCurrentLocationInfo(latlng) {
if (this.settings.useGoogleGeoApi) {
this._googlePlacesService.getGeoLatLngDetail(latlng).then((result) => {
if (result) {
this.setRecentLocation(result);
}
this.gettingCurrentLocationFlag = false;
});
}
else {
this._googlePlacesService.getLatLngDetail(this.settings.geoLatLangServiceUrl, latlng.lat, latlng.lng).then((result) => {
if (result) {
result = this.extractServerList(this.settings.serverResponseatLangHierarchy, result);
this.setRecentLocation(result);
}
this.gettingCurrentLocationFlag = false;
});
}
}
// function to retrieve the location info based on google place id.
getPlaceLocationInfo(selectedData) {
const placeId = selectedData.placeId;
if (this.settings.useGoogleGeoApi) {
this._googlePlacesService.getGeoPlaceDetail(placeId).then((data) => {
if (data) {
this.setRecentLocation(data);
}
});
}
else {
this._googlePlacesService.getPlaceDetails(this.settings.geoLocDetailServerUrl, placeId).then((result) => {
if (result) {
result = this.extractServerList(this.settings.serverResponseDetailHierarchy, result);
this.setRecentLocation(result);
}
});
}
}
// function to store the selected user search in the localstorage.
setRecentLocation(data) {
data = JSON.parse(JSON.stringify(data));
data.description = data.description ? data.description : (data.formattedAddress || data.formatted_address);
data.active = false;
this.selectedDataIndex = -1;
this.locationInput = data.description;
if (this.settings.showRecentSearch) {
this._googlePlacesService.addRecentList(this.settings.recentStorageName, data, this.settings.noOfRecentSearchSave);
this.getRecentLocations();
}
this.userSelectedOption = data;
// below code will execute only when user press enter or select any option selection and it emit a callback to the parent component.
if (!this.settings.resOnSearchButtonClickOnly) {
this.select.emit(data);
this.termChange.emit(data);
}
}
// function to retrive the stored recent user search from the localstorage.
getRecentLocations() {
this._googlePlacesService.getRecentList(this.settings.recentStorageName).then((data) => {
this.recentSearchData = data && data.length ? data : [];
});
}
// Fold a raw Google/REST/recent record into the internal AddressLookupPrediction shape.
normalizePrediction(raw) {
return {
placeId: raw?.placeId || raw?.place_id,
primaryText: raw?.primaryText || raw?.structured_formatting?.main_text || raw?.displayAddress || raw?.description || '',
secondaryText: raw?.secondaryText || raw?.structured_formatting?.secondary_text || '',
displayAddress: raw?.displayAddress || raw?.description,
types: raw?.types,
raw,
};
}
onKeyDown(event) {
if (this.dropdownOpen) {
if (event.key === "ArrowUp" /* Key.ArrowUp */) {
this.prevActiveMatch();
return;
}
if (event.key === "ArrowDown" /* Key.ArrowDown */) {
this.nextActiveMatch();
return;
}
if (event.key === "Enter" /* Key.Enter */) {
// Only select when a prediction is highlighted.
if (this.activeMatch) {
this.selectMatch(this.activeMatch);
}
return;
}
}
}
search(term, mode) {
// Disable the base search term functionality here since it is handled by the places picker separately
return new Observable();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: PlacesListComponent, deps: [{ token: PLATFORM_ID }, { token: i0.ElementRef }, { token: i2.GlobalRef }, { token: GooglePlacesService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: PlacesListComponent, isStandalone: false, selector: "google-places-list", inputs: { userSettings: "userSettings" }, outputs: { termChange: "termChange", select: "select", matchesUpdated: "matchesUpdated" }, providers: [PLACES_VALUE_ACCESSOR], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `
<novo-list direction="vertical">
<novo-list-item *ngFor="let data of matches; let $index = index" (click)="selectedListNode($event, $index)" [ngClass]="{ active: data === activeMatch }">
<item-header>
<item-avatar icon="location"></item-avatar>
<item-title>{{ data.primaryText }}</item-title>
</item-header>
<item-content>{{ data.secondaryText }}</item-content>
</novo-list-item>
</novo-list>
`, isInline: true, styles: [":host{display:grid}:host novo-list{border:1px solid #4a89dc;background-color:#fff}:host novo-list novo-list-item{cursor:pointer;flex:0 0;transition:background-color .25s}:host novo-list novo-list-item>div{width:100%}:host novo-list novo-list-item.active{background-color:#e0ebf9}:host novo-list novo-list-item:hover{background-color:#f1f6fc}:host novo-list novo-list-item item-content{flex-flow:row wrap}:host novo-list novo-list-item item-content>*{flex:0 0 33%;white-space:nowrap}\n"], dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: i4.NovoListElement, selector: "novo-list", inputs: ["theme", "direction"] }, { kind: "component", type: i4.NovoListItemElement, selector: "novo-list-item, a[list-item], button[list-item]" }, { kind: "component", type: i4.NovoItemAvatarElement, selector: "item-avatar, novo-item-avatar", inputs: ["icon", "color"] }, { kind: "component", type: i4.NovoItemTitleElement, selector: "item-title, novo-item-title" }, { kind: "component", type: i4.NovoItemHeaderElement, selector: "item-header, novo-item-header" }, { kind: "component", type: i4.NovoItemContentElement, selector: "item-content, novo-item-content", inputs: ["direction"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: PlacesListComponent, decorators: [{
type: Component,
args: [{ selector: 'google-places-list', providers: [PLACES_VALUE_ACCESSOR], template: `
<novo-list direction="vertical">
<novo-list-item *ngFor="let data of matches; let $index = index" (click)="selectedListNode($event, $index)" [ngClass]="{ active: data === activeMatch }">
<item-header>
<item-avatar icon="location"></item-avatar>
<item-title>{{ data.primaryText }}</item-title>
</item-header>
<item-content>{{ data.secondaryText }}</item-content>
</novo-list-item>
</novo-list>
`, standalone: false, styles: [":host{display:grid}:host novo-list{border:1px solid #4a89dc;background-color:#fff}:host novo-list novo-list-item{cursor:pointer;flex:0 0;transition:background-color .25s}:host novo-list novo-list-item>div{width:100%}:host novo-list novo-list-item.active{background-color:#e0ebf9}:host novo-list novo-list-item:hover{background-color:#f1f6fc}:host novo-list novo-list-item item-content{flex-flow:row wrap}:host novo-list novo-list-item item-content>*{flex:0 0 33%;white-space:nowrap}\n"] }]
}], ctorParameters: () => [{ type: Object, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }, { type: i0.ElementRef }, { type: i2.GlobalRef }, { type: GooglePlacesService }, { type: i0.ChangeDetectorRef }], propDecorators: { userSettings: [{
type: Input
}], termChange: [{
type: Output
}], select: [{
type: Output
}], matchesUpdated: [{
type: Output
}] } });
class GooglePlacesModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GooglePlacesModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.19", ngImport: i0, type: GooglePlacesModule, declarations: [PlacesListComponent], imports: [CommonModule, FormsModule, NovoListModule], exports: [PlacesListComponent] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GooglePlacesModule, providers: [GooglePlacesService, provideHttpClient(withInterceptorsFromDi())], imports: [CommonModule, FormsModule, NovoListModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: GooglePlacesModule, decorators: [{
type: NgModule,
args: [{ declarations: [PlacesListComponent],
exports: [PlacesListComponent], imports: [CommonModule, FormsModule, NovoListModule], providers: [GooglePlacesService, provideHttpClient(withInterceptorsFromDi())] }]
}] });
/** App-wide address-lookup config; when provided, every novo-address enables autocomplete on Address 1. */
const NOVO_ADDRESS_CONFIG = new InjectionToken('NOVO_ADDRESS_CONFIG');
/**
* Generated bundle index. Do not edit.
*/
export { GooglePlacesModule, GooglePlacesService, NOVO_ADDRESS_CONFIG, PlacesListComponent };
//# sourceMappingURL=novo-elements-elements-places.mjs.map