├── .babelrc ├── .circleci └── config.yml ├── .editorconfig ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE.md └── workflows │ └── main.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── angular.json ├── assets ├── angular-material-extensions-logo.png ├── angular-material-extensions-logo.svg ├── badge_made-in-germany.svg ├── demo1.gif ├── demo1.mp4 └── v3.0.0 │ ├── search.gif │ ├── search1.png │ └── search2.png ├── browserslist ├── commitlint.config.js ├── config ├── gulp-tasks │ └── README.md ├── helpers.js ├── jestGlobalMocks.ts └── setupJest.ts ├── e2e ├── protractor.conf.js ├── src │ ├── app.e2e-spec.ts │ └── app.po.ts └── tsconfig.json ├── greenkeeper.json ├── package-lock.json ├── package.json ├── prerender.ts ├── projects └── angular-material-extensions │ └── google-maps-autocomplete │ ├── karma.conf.js │ ├── ng-package.json │ ├── node_modules │ └── .cache │ │ └── ng-packagr │ │ ├── content-v2 │ │ └── sha512 │ │ │ ├── 15 │ │ │ └── 21 │ │ │ │ └── d5af89fd3142e3c7bf0aa10e736edae5ea24492c8e4a8250dce96c004b2e7d85be435f4974bec584e7ced7fc0b98ceeff3baeaf53231e36402af96ae188a │ │ │ ├── 16 │ │ │ └── 3f │ │ │ │ └── 9f744ed46fdc8d7b55bec11bff75b7f64ea338602450a92c85addf6f70a35ef46e5a56db735534c81248c958d21391945792c462e8dcbfc7181c7ee18da4 │ │ │ ├── 23 │ │ │ ├── 21 │ │ │ │ └── df2eb0d936b785b0352cb96ad16591d124d86f6d35acc6cc3d25b3ab593ba6b5994e6086f995704238d10c69250a24488e1019984caad3b26dcda9af08bb │ │ │ └── fb │ │ │ │ └── 7aacc6eec4e4a8a1c67de16f6242eae7da50aac1bd8c997d8e6a7cced65b5efdc1e25c5b19c734793b9612748185db90e991d6dc5846e139a41a149291d0 │ │ │ ├── 54 │ │ │ └── a6 │ │ │ │ └── b721c9dd751dd4f92f7d02646a0cb43968e227e5388186895a58ebb22fc9baa4b294a58ef51ce3f3dd94aa38d80f608892835ace4233df6035ffbd196901 │ │ │ ├── 67 │ │ │ └── 31 │ │ │ │ └── 9cecfec2f180082e1244181f20aa0abc2437a320dc6609e8579be2ba8220c3f7c2d98c470f5e917b1240eb5e1b456064bcb77f5cea59a808396e8e0c87d7 │ │ │ ├── 76 │ │ │ └── cc │ │ │ │ └── 55f458c91fc13bf52348df88ca4462225b0347d0bf562f60ee51f55c188ca7d047a1e23b896e7686075a412cc72386dbdeccba4f376136c8fbb252a7ccf1 │ │ │ ├── 81 │ │ │ └── 96 │ │ │ │ └── edfb554da2b5a51d20581d32137e812eaf43bd4300cafd6723c4de404b3ea1fd9a5937fb27c911f7f2e08e9de84e4159f97cdb03d10da4dd68758cb995d7 │ │ │ ├── 93 │ │ │ └── 56 │ │ │ │ └── e078ad8306e895b50b728db0eaa919499900249c86ad25466655ea2307aa40fe326f7ce07fb3a5cf480dc33da098f9c2ebcca286f011066b385611f5adb2 │ │ │ ├── 2f │ │ │ └── 11 │ │ │ │ └── 992a76442fcc308948364d8a42f0c62794bbeefbd1b9983ffb05b2604b678233123825d4ea3070cb747f87e33d563b6c21d7d923829a3f692c3c0d8debe2 │ │ │ ├── 4f │ │ │ └── 6b │ │ │ │ └── 1ece513bacb6348e7aa067e3eec18d9f920331f201f9b76e9f883516d1f0da616b62bb96f51d77befb9feed26f032fecf22191d43085ddbdbcaa46a4608a │ │ │ ├── 5e │ │ │ └── 5e │ │ │ │ └── 1da69cbf0de384ed5cbf68c909fd5122519834ad1186dd38fc6986155d796a487be52a3ce20b87dee5ff1e275aec2e9247e83ba986613a40fd95a55f0cda │ │ │ ├── 7a │ │ │ └── ad │ │ │ │ └── 2fbd2d1fea282b7de09b2293075889bad3c4bd5288c30cf78dfd3b70da7bd1207ebcad68ae82f31f8e70d4de13bb2804b6d6f59cae80cdec3d9831641587 │ │ │ ├── 8d │ │ │ └── 53 │ │ │ │ └── ad58764bc240411378ae1c47c0c20525da378a3b143795a11bc3fdbf6c9cde6fb2de6c3947d673d5872b9ce205d6274114b3b4dfd27609a636df7fd0b600 │ │ │ ├── b6 │ │ │ └── 5d │ │ │ │ └── 695b14072241752a254c6c4faa0f6fc5fc51d329dd2c3847f98d4f0e7bd2d9e89a0b99960526d9e3140a7c35490dec17a7cde0b7eba332eca789b56996e2 │ │ │ ├── b8 │ │ │ └── c8 │ │ │ │ └── 42e0762d2044c7a516dc8db369320b19eb5334e9ecaf2d5b6da892ace6f58c18c831d1415cae4672fa682c5039b26754b8ce22b4be613d1d4d8b48dcd743 │ │ │ ├── bb │ │ │ └── 4b │ │ │ │ └── 10bb5826a50194a0a5530cb69157e0eced738eac335e190c668336e841eeed94725f25c5e3674915c063314a239a356e061e2d3320b2436c95161ba4d7f9 │ │ │ ├── c5 │ │ │ └── 23 │ │ │ │ └── 7d68f163be98e5c05596699fe395753869553115427c224b7e8390bbf047691bfa86b77821f77260db5f8320b2b4ad965cf028f8a7cd897fba7daa49614b │ │ │ ├── f9 │ │ │ └── 86 │ │ │ │ └── df317e51f6568f250f50832e217cda3cb96f9e1c557fcc32f497bcbdfa942d510fa9084a143ff6f3399264944189e39de138ee02f92c7728187153b0a8d6 │ │ │ └── fb │ │ │ └── 6e │ │ │ └── 841c9a325e0621e48344ae42727f3e618961d073329ff8f92bd6540e1b818c3116767e15b85512ad68dce40e6abac49d8a773ab1ce29c33da9f73c4d7cb4 │ │ ├── index-v5 │ │ ├── 19 │ │ │ ├── e1 │ │ │ │ └── 29951b2873bc084a6884051b82ef358dbf04b1a2ad56ee9a418e597d0921 │ │ │ └── ee │ │ │ │ └── 68c4353ae955146953eb987f5fa58756715b0c0149452881153dfe60797f │ │ ├── 22 │ │ │ └── 73 │ │ │ │ └── f529ea7a007e93501a1e7e6e198a8085f080d270af983bd083823bd7515c │ │ ├── 30 │ │ │ └── 96 │ │ │ │ └── fd7e7628d0f09536f1f3ef0eb8409e6ad9d085afdf3bfd5c1a37943599de │ │ ├── 69 │ │ │ └── f1 │ │ │ │ └── 760835fe120ace77db4e25332fd732548ed84d4a7dd35d47f28f06469495 │ │ ├── 85 │ │ │ └── 9b │ │ │ │ └── 2e474c9ad8ef48835537e9964f9c046e49c77e20d7bcd1cd54957cd3a81e │ │ ├── 4a │ │ │ └── a7 │ │ │ │ └── 53885ff7f65600450455f4731be0e743dcf06239aff1eba82c932f34b0f4 │ │ ├── e8 │ │ │ └── 45 │ │ │ │ └── 220879efee1038dc25ab3e872f4a51fb09f05e2f50fb4dfb26b2aa8ec464 │ │ └── ed │ │ │ └── e7 │ │ │ └── 4d855f633cac01456450c1767a172aa10a8e68ec42dc18ad78b18d9cc3cb │ │ └── tsbuildinfo │ │ └── angular-material-extensions-google-maps-autocomplete.tsbuildinfo │ ├── package.json │ ├── schematics │ ├── collection.json │ ├── helpers │ │ ├── angular │ │ │ ├── ast-utils.ts │ │ │ ├── change.ts │ │ │ ├── component-schema.ts │ │ │ ├── dependencies.ts │ │ │ ├── find-module.ts │ │ │ ├── index.ts │ │ │ ├── latest-versions.ts │ │ │ ├── ng-ast-utils.ts │ │ │ ├── parse-name.ts │ │ │ ├── paths.ts │ │ │ └── validation.ts │ │ ├── index.ts │ │ └── material │ │ │ ├── ast │ │ │ └── ng-module-imports.ts │ │ │ ├── build-component.ts │ │ │ ├── index.ts │ │ │ └── package-config.ts │ └── ng-add │ │ ├── index.ts │ │ └── index_spec.ts │ ├── src │ ├── lib │ │ ├── animations │ │ │ └── index.ts │ │ ├── component │ │ │ ├── index.ts │ │ │ ├── mat-google-maps-autocomplete.component.html │ │ │ ├── mat-google-maps-autocomplete.component.scss │ │ │ ├── mat-google-maps-autocomplete.component.ts │ │ │ └── mat-search-google-maps-autocomplete │ │ │ │ ├── mat-search-google-maps-autocomplete.component.html │ │ │ │ ├── mat-search-google-maps-autocomplete.component.scss │ │ │ │ ├── mat-search-google-maps-autocomplete.component.spec.ts │ │ │ │ └── mat-search-google-maps-autocomplete.component.ts │ │ ├── directives │ │ │ ├── address-validator │ │ │ │ ├── mat-address-validator.directive.spec.ts │ │ │ │ └── mat-address-validator.directive.ts │ │ │ ├── mat-google-maps-autocomplete.directive.spec.ts │ │ │ └── mat-google-maps-autocomplete.directive.ts │ │ ├── helpers │ │ │ └── parser.ts │ │ ├── interfaces │ │ │ ├── germand.address.interface.ts │ │ │ ├── index.ts │ │ │ └── location.interface.ts │ │ ├── mat-google-maps-autocomplete.module.ts │ │ ├── services │ │ │ ├── script-loader.service.spec.ts │ │ │ └── script-loader.service.ts │ │ ├── testing │ │ │ └── mock-ng-zone.ts │ │ └── tokens │ │ │ └── index.ts │ ├── public-api.ts │ └── test.ts │ ├── tsconfig.lib.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.schematics.json │ ├── tsconfig.spec.json │ └── tslint.json ├── server.ts ├── server.ts.bak ├── src ├── app │ ├── app.component.html │ ├── app.component.scss │ ├── app.component.ts │ ├── app.module.ts │ └── app.server.module.ts ├── assets │ ├── .gitkeep │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon.png │ ├── browserconfig.xml │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── github-circle.svg │ ├── images │ │ └── icons │ │ │ ├── icon-128x128.png │ │ │ ├── icon-144x144.png │ │ │ ├── icon-152x152.png │ │ │ ├── icon-192x192.png │ │ │ ├── icon-384x384.png │ │ │ ├── icon-512x512.png │ │ │ ├── icon-72x72.png │ │ │ └── icon-96x96.png │ ├── library.svg │ ├── manifest.json │ ├── md │ │ ├── html.md │ │ ├── scss.md │ │ ├── search │ │ │ └── html.md │ │ └── ts.md │ ├── mstile-150x150.png │ ├── npm-variant-outline.svg │ ├── safari-pinned-tab.svg │ └── site.webmanifest ├── config │ ├── config.component.html │ ├── config.component.scss │ └── config.component.ts ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── favicon.ico ├── index.html ├── main.server.ts ├── main.ts ├── polyfills.ts ├── setup-jest.ts ├── styles.scss └── test-config.helper.ts ├── static.paths.ts ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.server.json ├── tsconfig.spec.json ├── tslint.json └── webpack.server.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env"] 3 | } 4 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Javascript Node CircleCI 2.0 configuration file 2 | # 3 | # Check https://circleci.com/docs/2.0/language-javascript/ for more details 4 | # 5 | version: 2 6 | jobs: 7 | build: 8 | docker: 9 | # specify the version you desire here 10 | - image: circleci/node:12.19.0-browsers 11 | 12 | # Specify service dependencies here if necessary 13 | # CircleCI maintains a library of pre-built images 14 | # documented at https://circleci.com/docs/2.0/circleci-images/ 15 | # - image: circleci/mongo:3.4.4 16 | 17 | working_directory: ~/repo 18 | 19 | environment: 20 | CHROME_BIN: "chromium-browser" 21 | 22 | steps: 23 | - checkout 24 | 25 | # Download and cache dependencies 26 | - restore_cache: 27 | keys: 28 | - v1-dependencies-{{ checksum "package.json" }} 29 | # fallback to using the latest cache if no exact match is found 30 | - v1-dependencies- 31 | - run: ls -la && pwd 32 | - run: git --version 33 | - run: npm install 34 | - run: npm install --only=dev 35 | - run: npm run build 36 | - run: ls -la && pwd 37 | 38 | - save_cache: 39 | paths: 40 | - node_modules 41 | key: v1-dependencies-{{ checksum "package.json" }} 42 | 43 | - persist_to_workspace: 44 | root: . 45 | paths: 46 | - dist 47 | # run tests! 48 | #- run: npm test 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: angular-material-extensions 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: npm/@angular-material-extensions/google-maps-autocomplete 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: ['https://github.com/AnthonyNahas','anahas.de'] 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | ### Bug Report or Feature Request (mark with an `x`) 5 | ``` 6 | - [ ] bug report -> please search issues before submitting 7 | - [ ] feature request 8 | ``` 9 | 10 | ### OS and Version? 11 | 14 | 15 | ### Versions 16 | 20 | 21 | 22 | ### Repro steps 23 | 28 | 29 | 30 | ### The log given by the failure 31 | 32 | 33 | 34 | ### Desired functionality 35 | 39 | 40 | 41 | ### Mention any other details that might be useful 42 | 43 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: CI 4 | 5 | # Controls when the action will run. Triggers the workflow on push or pull request 6 | # events but only for the master branch 7 | on: 8 | push: 9 | branches: [ master ] 10 | pull_request: 11 | branches: [ master ] 12 | 13 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 14 | jobs: 15 | # This workflow contains a single job called "build" 16 | build: 17 | # The type of runner that the job will run on 18 | runs-on: ubuntu-latest 19 | 20 | # Steps represent a sequence of tasks that will be executed as part of the job 21 | steps: 22 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 23 | - uses: actions/checkout@v2 24 | 25 | # Runs 26 | - name: Setup Node.js environment 27 | uses: actions/setup-node@v2.1.2 28 | - run: npm ci 29 | - run: npm run build:lib 30 | - run: | 31 | cd projects/angular-material-extensions/google-maps-autocomplete 32 | npm run build 33 | - run: | 34 | cd dist/angular-material-extensions/google-maps-autocomplete 35 | npm pack 36 | 37 | # Uploads 38 | - uses: actions/upload-artifact@v2 39 | with: 40 | name: angular-material-extensions-google-maps-autocomplete 41 | path: dist/angular-material-extensions/google-maps-autocomplete/*.tgz 42 | 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | # Only exists if Bazel was run 8 | /bazel-out 9 | 10 | # dependencies 11 | /node_modules 12 | 13 | # profiling files 14 | chrome-profiler-events*.json 15 | speed-measure-plugin*.json 16 | 17 | # IDEs and editors 18 | /.idea 19 | .project 20 | .classpath 21 | .c9/ 22 | *.launch 23 | .settings/ 24 | *.sublime-workspace 25 | 26 | # IDE - VSCode 27 | .vscode/* 28 | !.vscode/settings.json 29 | !.vscode/tasks.json 30 | !.vscode/launch.json 31 | !.vscode/extensions.json 32 | .history/* 33 | 34 | # misc 35 | /.angular/cache 36 | /.sass-cache 37 | /connect.lock 38 | /coverage 39 | /libpeerconnection.log 40 | npm-debug.log 41 | yarn-error.log 42 | testem.log 43 | /typings 44 | 45 | # System Files 46 | .DS_Store 47 | Thumbs.db 48 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | 4 | #install google chrome, using addons 5 | addons: 6 | apt: 7 | sources: 8 | - google-chrome 9 | packages: 10 | - google-chrome-stable 11 | 12 | language: node_js 13 | node_js: 14 | - "8" 15 | 16 | before_script: 17 | - export DISPLAY=:99.0 18 | - sh -e /etc/init.d/xvfb start 19 | - npm install --quiet -g gulp-cli 20 | 21 | script: gulp test:ci 22 | 23 | after_success: gulp coveralls 24 | 25 | cache: 26 | yarn: true 27 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Citizen Code of Conduct 2 | 3 | ## 1. Purpose 4 | 5 | A primary goal of Select Country is to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof). 6 | 7 | This code of conduct outlines our expectations for all those who participate in our community, as well as the consequences for unacceptable behavior. 8 | 9 | We invite all those who participate in Select Country to help us create safe and positive experiences for everyone. 10 | 11 | ## 2. Open [Source/Culture/Tech] Citizenship 12 | 13 | A supplemental goal of this Code of Conduct is to increase open [source/culture/tech] citizenship by encouraging participants to recognize and strengthen the relationships between our actions and their effects on our community. 14 | 15 | Communities mirror the societies in which they exist and positive action is essential to counteract the many forms of inequality and abuses of power that exist in society. 16 | 17 | If you see someone who is making an extra effort to ensure our community is welcoming, friendly, and encourages all participants to contribute to the fullest extent, we want to know. 18 | 19 | ## 3. Expected Behavior 20 | 21 | The following behaviors are expected and requested of all community members: 22 | 23 | * Participate in an authentic and active way. In doing so, you contribute to the health and longevity of this community. 24 | * Exercise consideration and respect in your speech and actions. 25 | * Attempt collaboration before conflict. 26 | * Refrain from demeaning, discriminatory, or harassing behavior and speech. 27 | * Be mindful of your surroundings and of your fellow participants. Alert community leaders if you notice a dangerous situation, someone in distress, or violations of this Code of Conduct, even if they seem inconsequential. 28 | * Remember that community event venues may be shared with members of the public; please be respectful to all patrons of these locations. 29 | 30 | ## 4. Unacceptable Behavior 31 | 32 | The following behaviors are considered harassment and are unacceptable within our community: 33 | 34 | * Violence, threats of violence or violent language directed against another person. 35 | * Sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory jokes and language. 36 | * Posting or displaying sexually explicit or violent material. 37 | * Posting or threatening to post other people's personally identifying information ("doxing"). 38 | * Personal insults, particularly those related to gender, sexual orientation, race, religion, or disability. 39 | * Inappropriate photography or recording. 40 | * Inappropriate physical contact. You should have someone's consent before touching them. 41 | * Unwelcome sexual attention. This includes, sexualized comments or jokes; inappropriate touching, groping, and unwelcomed sexual advances. 42 | * Deliberate intimidation, stalking or following (online or in person). 43 | * Advocating for, or encouraging, any of the above behavior. 44 | * Sustained disruption of community events, including talks and presentations. 45 | 46 | ## 5. Weapons Policy 47 | 48 | No weapons will be allowed at Select Country events, community spaces, or in other spaces covered by the scope of this Code of Conduct. Weapons include but are not limited to guns, explosives (including fireworks), and large knives such as those used for hunting or display, as well as any other item used for the purpose of causing injury or harm to others. Anyone seen in possession of one of these items will be asked to leave immediately, and will only be allowed to return without the weapon. Community members are further expected to comply with all state and local laws on this matter. 49 | 50 | ## 6. Consequences of Unacceptable Behavior 51 | 52 | Unacceptable behavior from any community member, including sponsors and those with decision-making authority, will not be tolerated. 53 | 54 | Anyone asked to stop unacceptable behavior is expected to comply immediately. 55 | 56 | If a community member engages in unacceptable behavior, the community organizers may take any action they deem appropriate, up to and including a temporary ban or permanent expulsion from the community without warning (and without refund in the case of a paid event). 57 | 58 | ## 7. Reporting Guidelines 59 | 60 | If you are subject to or witness unacceptable behavior, or have any other concerns, please notify a community organizer as soon as possible. Anthony.na@hotmail.de. 61 | 62 | 63 | 64 | Additionally, community organizers are available to help community members engage with local law enforcement or to otherwise help those experiencing unacceptable behavior feel safe. In the context of in-person events, organizers will also provide escorts as desired by the person experiencing distress. 65 | 66 | ## 8. Addressing Grievances 67 | 68 | If you feel you have been falsely or unfairly accused of violating this Code of Conduct, you should notify angular-material-extensions with a concise description of your grievance. Your grievance will be handled in accordance with our existing governing policies. 69 | 70 | 71 | 72 | ## 9. Scope 73 | 74 | We expect all community participants (contributors, paid or otherwise; sponsors; and other guests) to abide by this Code of Conduct in all community venues--online and in-person--as well as in all one-on-one communications pertaining to community business. 75 | 76 | This code of conduct and its related procedures also applies to unacceptable behavior occurring outside the scope of community activities when such behavior has the potential to adversely affect the safety and well-being of community members. 77 | 78 | ## 10. Contact info 79 | 80 | Anthony.na@hotmail.de 81 | 82 | ## 11. License and attribution 83 | 84 | The Citizen Code of Conduct is distributed by [Stumptown Syndicate](http://stumptownsyndicate.org) under a [Creative Commons Attribution-ShareAlike license](http://creativecommons.org/licenses/by-sa/3.0/). 85 | 86 | Portions of text derived from the [Django Code of Conduct](https://www.djangoproject.com/conduct/) and the [Geek Feminism Anti-Harassment Policy](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy). 87 | 88 | _Revision 2.3. Posted 6 March 2017._ 89 | 90 | _Revision 2.2. Posted 4 February 2016._ 91 | 92 | _Revision 2.1. Posted 23 June 2014._ 93 | 94 | _Revision 2.0, adopted by the [Stumptown Syndicate](http://stumptownsyndicate.org) board on 10 January 2013. Posted 17 March 2013._ 95 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. 8 | 9 | ## Our Standards 10 | 11 | Examples of behavior that contributes to a positive environment for our community include: 12 | 13 | * Demonstrating empathy and kindness toward other people 14 | * Being respectful of differing opinions, viewpoints, and experiences 15 | * Giving and gracefully accepting constructive feedback 16 | * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience 17 | * Focusing on what is best not just for us as individuals, but for the overall community 18 | 19 | Examples of unacceptable behavior include: 20 | 21 | * The use of sexualized language or imagery, and sexual attention or 22 | advances of any kind 23 | * Trolling, insulting or derogatory comments, and personal or political attacks 24 | * Public or private harassment 25 | * Publishing others' private information, such as a physical or email 26 | address, without their explicit permission 27 | * Other conduct which could reasonably be considered inappropriate in a 28 | professional setting 29 | 30 | ## Enforcement Responsibilities 31 | 32 | Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. 33 | 34 | Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. 35 | 36 | ## Scope 37 | 38 | This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. 39 | 40 | ## Enforcement 41 | 42 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [INSERT CONTACT METHOD]. All complaints will be reviewed and investigated promptly and fairly. 43 | 44 | All community leaders are obligated to respect the privacy and security of the reporter of any incident. 45 | 46 | ## Enforcement Guidelines 47 | 48 | Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: 49 | 50 | ### 1. Correction 51 | 52 | **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. 53 | 54 | **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. 55 | 56 | ### 2. Warning 57 | 58 | **Community Impact**: A violation through a single incident or series of actions. 59 | 60 | **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. 61 | 62 | ### 3. Temporary Ban 63 | 64 | **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. 65 | 66 | **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. 67 | 68 | ### 4. Permanent Ban 69 | 70 | **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. 71 | 72 | **Consequence**: A permanent ban from any sort of public interaction within the project community. 73 | 74 | ## Attribution 75 | 76 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, 77 | available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 78 | 79 | Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). 80 | 81 | [homepage]: https://www.contributor-covenant.org 82 | 83 | For answers to common questions about this code of conduct, see the FAQ at 84 | https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations. 85 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019-2022 Anthony Nahas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "google-maps-autocomplete": { 7 | "projectType": "application", 8 | "schematics": { 9 | "@schematics/angular:component": { 10 | "style": "scss" 11 | } 12 | }, 13 | "root": "", 14 | "sourceRoot": "src", 15 | "prefix": "app", 16 | "architect": { 17 | "build": { 18 | "builder": "@angular-devkit/build-angular:browser", 19 | "options": { 20 | "outputPath": "dist/browser", 21 | "index": "src/index.html", 22 | "main": "src/main.ts", 23 | "polyfills": "src/polyfills.ts", 24 | "tsConfig": "tsconfig.app.json", 25 | "assets": [ 26 | "src/favicon.ico", 27 | "src/assets" 28 | ], 29 | "styles": [ 30 | "src/styles.scss", 31 | "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", 32 | "./node_modules/prismjs/themes/prism-okaidia.css" 33 | ], 34 | "scripts": [ 35 | "./node_modules/prismjs/prism.js", 36 | "./node_modules/prismjs/components/prism-typescript.min.js" 37 | ], 38 | "vendorChunk": true, 39 | "extractLicenses": false, 40 | "buildOptimizer": false, 41 | "sourceMap": true, 42 | "optimization": false, 43 | "namedChunks": true 44 | }, 45 | "configurations": { 46 | "production": { 47 | "fileReplacements": [ 48 | { 49 | "replace": "src/environments/environment.ts", 50 | "with": "src/environments/environment.prod.ts" 51 | } 52 | ], 53 | "optimization": true, 54 | "outputHashing": "all", 55 | "sourceMap": false, 56 | "namedChunks": false, 57 | "extractLicenses": true, 58 | "vendorChunk": false, 59 | "buildOptimizer": true, 60 | "budgets": [ 61 | { 62 | "type": "initial", 63 | "maximumWarning": "2mb", 64 | "maximumError": "5mb" 65 | }, 66 | { 67 | "type": "anyComponentStyle", 68 | "maximumWarning": "6kb", 69 | "maximumError": "10kb" 70 | } 71 | ] 72 | } 73 | }, 74 | "defaultConfiguration": "" 75 | }, 76 | "build_ghpages": { 77 | "builder": "@angular-devkit/build-angular:browser", 78 | "options": { 79 | "baseHref": "/google-maps-autocomplete/", 80 | "deployUrl": "/google-maps-autocomplete/", 81 | "outputPath": "dist/browser", 82 | "index": "src/index.html", 83 | "main": "src/main.ts", 84 | "polyfills": "src/polyfills.ts", 85 | "tsConfig": "tsconfig.app.json", 86 | "assets": [ 87 | "src/favicon.ico", 88 | "src/assets" 89 | ], 90 | "styles": [ 91 | "src/styles.scss", 92 | "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", 93 | "./node_modules/prismjs/themes/prism-okaidia.css" 94 | ], 95 | "scripts": [ 96 | "./node_modules/prismjs/prism.js", 97 | "./node_modules/prismjs/components/prism-typescript.min.js" 98 | ], 99 | "vendorChunk": true, 100 | "extractLicenses": false, 101 | "buildOptimizer": false, 102 | "sourceMap": true, 103 | "optimization": false, 104 | "namedChunks": true 105 | }, 106 | "configurations": { 107 | "production": { 108 | "fileReplacements": [ 109 | { 110 | "replace": "src/environments/environment.ts", 111 | "with": "src/environments/environment.prod.ts" 112 | } 113 | ], 114 | "optimization": true, 115 | "outputHashing": "all", 116 | "sourceMap": false, 117 | "namedChunks": false, 118 | "extractLicenses": true, 119 | "vendorChunk": false, 120 | "buildOptimizer": true, 121 | "budgets": [ 122 | { 123 | "type": "initial", 124 | "maximumWarning": "2mb", 125 | "maximumError": "5mb" 126 | }, 127 | { 128 | "type": "anyComponentStyle", 129 | "maximumWarning": "6kb", 130 | "maximumError": "10kb" 131 | } 132 | ] 133 | } 134 | }, 135 | "defaultConfiguration": "" 136 | }, 137 | "serve": { 138 | "builder": "@angular-devkit/build-angular:dev-server", 139 | "options": { 140 | "browserTarget": "google-maps-autocomplete:build" 141 | }, 142 | "configurations": { 143 | "production": { 144 | "browserTarget": "google-maps-autocomplete:build:production" 145 | } 146 | } 147 | }, 148 | "extract-i18n": { 149 | "builder": "@angular-devkit/build-angular:extract-i18n", 150 | "options": { 151 | "browserTarget": "google-maps-autocomplete:build" 152 | } 153 | }, 154 | "test": { 155 | "builder": "@angular-devkit/build-angular:karma", 156 | "options": { 157 | "main": "src/test.ts", 158 | "polyfills": "src/polyfills.ts", 159 | "tsConfig": "tsconfig.spec.json", 160 | "karmaConfig": "karma.conf.js", 161 | "assets": [ 162 | "src/favicon.ico", 163 | "src/assets" 164 | ], 165 | "styles": [ 166 | "src/styles.scss", 167 | "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", 168 | "./node_modules/prismjs/themes/prism-okaidia.css" 169 | ], 170 | "scripts": [ 171 | "./node_modules/prismjs/prism.js", 172 | "./node_modules/prismjs/components/prism-typescript.min.js" 173 | ] 174 | } 175 | }, 176 | "e2e": { 177 | "builder": "@angular-devkit/build-angular:protractor", 178 | "options": { 179 | "protractorConfig": "e2e/protractor.conf.js", 180 | "devServerTarget": "google-maps-autocomplete:serve" 181 | }, 182 | "configurations": { 183 | "production": { 184 | "devServerTarget": "google-maps-autocomplete:serve:production" 185 | } 186 | } 187 | }, 188 | "server": { 189 | "builder": "@angular-devkit/build-angular:server", 190 | "options": { 191 | "outputPath": "dist/server", 192 | "main": "server.ts", 193 | "tsConfig": "tsconfig.server.json", 194 | "sourceMap": true, 195 | "optimization": false, 196 | "buildOptimizer": false 197 | }, 198 | "configurations": { 199 | "production": { 200 | "fileReplacements": [ 201 | { 202 | "replace": "src/environments/environment.ts", 203 | "with": "src/environments/environment.prod.ts" 204 | } 205 | ], 206 | "sourceMap": false, 207 | "optimization": true, 208 | "buildOptimizer": true 209 | } 210 | }, 211 | "defaultConfiguration": "" 212 | }, 213 | "deploy": { 214 | "builder": "angular-cli-ghpages:deploy", 215 | "options": {} 216 | }, 217 | "serve-ssr": { 218 | "builder": "@nguniversal/builders:ssr-dev-server", 219 | "options": { 220 | "browserTarget": "google-maps-autocomplete:build", 221 | "serverTarget": "google-maps-autocomplete:server" 222 | }, 223 | "configurations": { 224 | "production": { 225 | "browserTarget": "google-maps-autocomplete:build:production", 226 | "serverTarget": "google-maps-autocomplete:server:production" 227 | } 228 | } 229 | }, 230 | "prerender": { 231 | "builder": "@nguniversal/builders:prerender", 232 | "options": { 233 | "browserTarget": "google-maps-autocomplete:build:production", 234 | "serverTarget": "google-maps-autocomplete:server:production", 235 | "routes": [ 236 | "/" 237 | ] 238 | }, 239 | "configurations": { 240 | "production": {} 241 | } 242 | }, 243 | "prerender_ghpages": { 244 | "builder": "@nguniversal/builders:prerender", 245 | "options": { 246 | "browserTarget": "google-maps-autocomplete:build_ghpages:production", 247 | "serverTarget": "google-maps-autocomplete:server:production", 248 | "routes": [ 249 | "/" 250 | ] 251 | }, 252 | "configurations": { 253 | "production": {} 254 | } 255 | } 256 | } 257 | }, 258 | "@angular-material-extensions/google-maps-autocomplete": { 259 | "projectType": "library", 260 | "root": "projects/angular-material-extensions/google-maps-autocomplete", 261 | "sourceRoot": "projects/angular-material-extensions/google-maps-autocomplete/src", 262 | "prefix": "lib", 263 | "architect": { 264 | "build": { 265 | "builder": "@angular-devkit/build-ng-packagr:build", 266 | "options": { 267 | "tsConfig": "projects/angular-material-extensions/google-maps-autocomplete/tsconfig.lib.json", 268 | "project": "projects/angular-material-extensions/google-maps-autocomplete/ng-package.json" 269 | }, 270 | "configurations": { 271 | "production": { 272 | "tsConfig": "projects/angular-material-extensions/google-maps-autocomplete/tsconfig.lib.prod.json" 273 | } 274 | } 275 | }, 276 | "test": { 277 | "builder": "@angular-devkit/build-angular:karma", 278 | "options": { 279 | "main": "projects/angular-material-extensions/google-maps-autocomplete/src/test.ts", 280 | "tsConfig": "projects/angular-material-extensions/google-maps-autocomplete/tsconfig.spec.json", 281 | "karmaConfig": "projects/angular-material-extensions/google-maps-autocomplete/karma.conf.js" 282 | } 283 | } 284 | } 285 | } 286 | }, 287 | "cli": { 288 | "analytics": "66b4ab45-d3f5-4efa-9eee-c4a0b45e6b77" 289 | } 290 | } 291 | -------------------------------------------------------------------------------- /assets/angular-material-extensions-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/assets/angular-material-extensions-logo.png -------------------------------------------------------------------------------- /assets/angular-material-extensions-logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/badge_made-in-germany.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/demo1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/assets/demo1.gif -------------------------------------------------------------------------------- /assets/demo1.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/assets/demo1.mp4 -------------------------------------------------------------------------------- /assets/v3.0.0/search.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/assets/v3.0.0/search.gif -------------------------------------------------------------------------------- /assets/v3.0.0/search1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/assets/v3.0.0/search1.png -------------------------------------------------------------------------------- /assets/v3.0.0/search2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/assets/v3.0.0/search2.png -------------------------------------------------------------------------------- /browserslist: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # You can see what browsers were selected by your queries by running: 6 | # npx browserslist 7 | 8 | > 0.5% 9 | last 2 versions 10 | Firefox ESR 11 | not dead 12 | not IE 9-11 # For IE 9-11 support, remove 'not'. -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = {extends: ['@commitlint/config-conventional']}; 2 | -------------------------------------------------------------------------------- /config/gulp-tasks/README.md: -------------------------------------------------------------------------------- 1 | 2 | Put additional tasks here. 3 | See [gulp-hub](https://github.com/frankwallis/gulp-hub) for more info, on how to write those tasks. 4 | -------------------------------------------------------------------------------- /config/helpers.js: -------------------------------------------------------------------------------- 1 | const os = require('os'); 2 | const path = require('path'); 3 | const exec = require('child_process').exec; 4 | 5 | const _root = path.resolve(__dirname, '..'); 6 | 7 | 8 | /** 9 | * Plaform independant path to an executable cmd 10 | * @param {string} path 11 | */ 12 | platformPath = (path) => { 13 | return /^win/.test(os.platform()) ? `${path}.cmd` : path; 14 | }; 15 | 16 | /** 17 | * 18 | * @param {string[]} args 19 | */ 20 | rootDir = (...args) => { 21 | return path.join.apply(path, [_root].concat(...args)); 22 | }; 23 | 24 | /** 25 | * 26 | * @param {string} cmd 27 | */ 28 | binPath = (cmd) => { 29 | return platformPath(`/node_modules/.bin/${cmd}`); 30 | }; 31 | 32 | /** 33 | * Promisified child_process.exec 34 | * 35 | * @param cmd 36 | * @param opts See child_process.exec node docs 37 | * @returns {Promise} 38 | */ 39 | execp = (cmd, opts) => { 40 | opts = Object.assign(opts || {}, { 41 | stdout: process.stdout, 42 | stderr: process.stderr 43 | }); 44 | return new Promise((resolve, reject) => { 45 | const child = exec(cmd, opts, 46 | (err, stdout, stderr) => err ? reject(err.code) : resolve(0)); 47 | 48 | if (opts.stdout) { 49 | child.stdout.pipe(opts.stdout); 50 | } 51 | if (opts.stderr) { 52 | child.stderr.pipe(opts.stderr); 53 | } 54 | }); 55 | }; 56 | 57 | /** 58 | * Install dependencies using yarn, if present, or npm otherwise. 59 | * @param opts See child_process.exec node docs 60 | * @returns {Promise} 61 | */ 62 | installDependencies = (opts) => { 63 | return execp('yarn -v') // first try to install deps using yarn 64 | .then(exitCode => exitCode === 0 ? execp('yarn install', opts) : execp('npm install', opts)); 65 | }; 66 | 67 | var exports = module.exports = { 68 | root: rootDir, 69 | execp: execp, 70 | binPath: binPath, 71 | platformPath: platformPath, 72 | installDependencies: installDependencies 73 | }; 74 | -------------------------------------------------------------------------------- /config/jestGlobalMocks.ts: -------------------------------------------------------------------------------- 1 | global['CSS'] = null; 2 | 3 | const mock = () => { 4 | let storage = {}; 5 | return { 6 | getItem: key => key in storage ? storage[key] : null, 7 | setItem: (key, value) => storage[key] = value || '', 8 | removeItem: key => delete storage[key], 9 | clear: () => storage = {}, 10 | }; 11 | }; 12 | 13 | Object.defineProperty(window, 'localStorage', {value: mock()}); 14 | Object.defineProperty(window, 'sessionStorage', {value: mock()}); 15 | Object.defineProperty(document, 'doctype', { 16 | value: '' 17 | }); 18 | Object.defineProperty(window, 'getComputedStyle', { 19 | value: () => { 20 | return { 21 | display: 'none', 22 | appearance: ['-webkit-appearance'] 23 | }; 24 | } 25 | }); 26 | /** 27 | * ISSUE: https://github.com/angular/material2/issues/7101 28 | * Workaround for JSDOM missing transform property 29 | */ 30 | Object.defineProperty(document.body.style, 'transform', { 31 | value: () => { 32 | return { 33 | enumerable: true, 34 | configurable: true, 35 | }; 36 | }, 37 | }); 38 | -------------------------------------------------------------------------------- /config/setupJest.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular'; 2 | import './jestGlobalMocks'; 3 | -------------------------------------------------------------------------------- /e2e/protractor.conf.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | // Protractor configuration file, see link for more information 3 | // https://github.com/angular/protractor/blob/master/lib/config.ts 4 | 5 | const { SpecReporter } = require('jasmine-spec-reporter'); 6 | 7 | /** 8 | * @type { import("protractor").Config } 9 | */ 10 | exports.config = { 11 | allScriptsTimeout: 11000, 12 | specs: [ 13 | './src/**/*.e2e-spec.ts' 14 | ], 15 | capabilities: { 16 | browserName: 'chrome' 17 | }, 18 | directConnect: true, 19 | baseUrl: 'http://localhost:4200/', 20 | framework: 'jasmine', 21 | jasmineNodeOpts: { 22 | showColors: true, 23 | defaultTimeoutInterval: 30000, 24 | print: function() {} 25 | }, 26 | onPrepare() { 27 | require('ts-node').register({ 28 | project: require('path').join(__dirname, './tsconfig.json') 29 | }); 30 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 31 | } 32 | }; -------------------------------------------------------------------------------- /e2e/src/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { AppPage } from './app.po'; 2 | import { browser, logging } from 'protractor'; 3 | 4 | describe('workspace-project App', () => { 5 | let page: AppPage; 6 | 7 | beforeEach(() => { 8 | page = new AppPage(); 9 | }); 10 | 11 | it('should display welcome message', () => { 12 | page.navigateTo(); 13 | expect(page.getTitleText()).toEqual('google-maps-autocomplete app is running!'); 14 | }); 15 | 16 | afterEach(async () => { 17 | // Assert that there are no errors emitted from the browser 18 | const logs = await browser.manage().logs().get(logging.Type.BROWSER); 19 | expect(logs).not.toContain(jasmine.objectContaining({ 20 | level: logging.Level.SEVERE, 21 | } as logging.Entry)); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /e2e/src/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AppPage { 4 | navigateTo() { 5 | return browser.get(browser.baseUrl) as Promise; 6 | } 7 | 8 | getTitleText() { 9 | return element(by.css('app-root .content span')).getText() as Promise; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/e2e", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "types": [ 8 | "jasmine", 9 | "jasminewd2", 10 | "node" 11 | ] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /greenkeeper.json: -------------------------------------------------------------------------------- 1 | { 2 | "groups": { 3 | "default": { 4 | "packages": [ 5 | "demo/package.json", 6 | "package.json" 7 | ] 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "google-maps-autocomplete", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve --port 4510", 7 | "build": "ng build --statsJson", 8 | "build:client-and-server-bundles:ghpages": "npm run build:prod:ghpages && ng run google-maps-autocomplete:server:production --bundleDependencies all", 9 | "build:docs": "npx compodoc -p projects/angular-material-extensions/google-maps-autocomplete/tsconfig.lib.json --hideGenerator --disableCoverage -d dist/browser/doc/", 10 | "build:lib": "ng build @angular-material-extensions/google-maps-autocomplete", 11 | "build:lib:Watch": "ng build @angular-material-extensions/google-maps-autocomplete --watch", 12 | "build:prod": "ng build --configuration production", 13 | "build:prod:ghpages": "ng build --preserve-symlinks --configuration production --aot --build-optimizer --base-href /google-maps-autocomplete/ --deploy-url /google-maps-autocomplete/", 14 | "build:prerender": "npm run build:client-and-server-bundles && npm run compile:server && npm run generate:prerender", 15 | "build:prerender:ghpages": "npm run build:client-and-server-bundles:ghpages && npm run compile:server && npm run generate:prerender", 16 | "deploy": "ng deploy --base-href=/google-maps-autocomplete/ --no-build", 17 | "generate:prerender": "cd dist && node prerender", 18 | "test": "jest", 19 | "lint": "ng lint", 20 | "e2e": "ng e2e", 21 | "serve:prerender": "cd dist/browser && http-server", 22 | "release": "release-it", 23 | "test:watch": "jest --watch", 24 | "compile:server": "webpack --config webpack.server.config.js --progress --color", 25 | "build:ssr_bak": "npm run build:client-and-server-bundles && npm run compile:server", 26 | "serve:ssr_bak": "node dist/server", 27 | "build:client-and-server-bundles_bak": "ng build --configuration production && ng run google-maps-autocomplete:server:production --bundleDependencies all", 28 | "dev:ssr": "ng run google-maps-autocomplete:serve-ssr", 29 | "serve:ssr": "node dist/server/main.js", 30 | "build:ssr": "ng build --configuration production && ng run google-maps-autocomplete:server:production", 31 | "prerender": "ng run google-maps-autocomplete:prerender", 32 | "prerender:ghpages": "ng run google-maps-autocomplete:prerender_ghpages", 33 | "bundle-report": "webpack-bundle-analyzer dist/browser/stats-es2015.json" 34 | }, 35 | "private": true, 36 | "dependencies": { 37 | "@agm/core": "^3.0.0-beta.0", 38 | "@angular-devkit/core": "^16.2.0", 39 | "@angular-devkit/schematics": "^16.2.0", 40 | "@angular/animations": "^16.2.2", 41 | "@angular/cdk": "^16.2.1", 42 | "@angular/common": "^16.2.2", 43 | "@angular/compiler": "^16.2.2", 44 | "@angular/core": "^16.2.2", 45 | "@angular/flex-layout": "^14.0.0-beta.41", 46 | "@angular/forms": "^16.2.2", 47 | "@angular/material": "^16.2.1", 48 | "@angular/google-maps": "^16.2.1", 49 | "@angular/platform-browser": "^16.2.2", 50 | "@angular/platform-browser-dynamic": "^16.2.2", 51 | "@angular/platform-server": "^16.2.2", 52 | "@angular/router": "^16.2.2", 53 | "@briebug/jest-schematic": "^3.1.0", 54 | "@nguniversal/express-engine": "^16.2.0", 55 | "@nguniversal/module-map-ngfactory-loader": "^8.2.6", 56 | "angular-cli-ghpages": "^0.6.2", 57 | "angulartics2": "^12.1.0", 58 | "express": "^4.17.1", 59 | "gulp": "^4.0.2", 60 | "http-server": "^0.12.3", 61 | "karma": "^6.3.4", 62 | "ngx-markdown": "^16.0.0", 63 | "rxjs": "^6.6.7", 64 | "tslib": "^2.2.0", 65 | "zone.js": "~0.13.1" 66 | }, 67 | "devDependencies": { 68 | "@angular-devkit/build-angular": "^16.2.0", 69 | "@angular-devkit/build-ng-packagr": "^0.1001.7", 70 | "@angular/cli": "^16.2.0", 71 | "@angular/compiler-cli": "^16.2.2", 72 | "@angular/language-service": "^16.2.2", 73 | "@compodoc/compodoc": "^1.1.11", 74 | "@nguniversal/builders": "^16.2.0", 75 | "@release-it/conventional-changelog": "^5.1.1", 76 | "@schematics/angular": "^9.1.15", 77 | "@schematics/update": "^0.1001.7", 78 | "@types/express": "^4.17.11", 79 | "@types/googlemaps": "3.39.12", 80 | "@types/jasmine": "^3.6.10", 81 | "@types/jasminewd2": "~2.0.3", 82 | "@types/jest": "25.1.2", 83 | "@types/node": "^12.20.10", 84 | "codelyzer": "^6.0.1", 85 | "commitplease": "^3.2.0", 86 | "jasmine-core": "~3.5.0", 87 | "jasmine-spec-reporter": "~4.2.1", 88 | "jest": "29.6.4", 89 | "jest-preset-angular": "8.0.0", 90 | "ng-packagr": "^16.2.1", 91 | "protractor": "^7.0.0", 92 | "release-it": "^15.5.0", 93 | "ts-loader": "^6.2.2", 94 | "ts-node": "~8.6.2", 95 | "tslint": "~6.1.3", 96 | "typescript": "5.1.6" 97 | }, 98 | "greenkeeper": { 99 | "ignore": [ 100 | "@angular/animations", 101 | "@angular/core", 102 | "@angular/common", 103 | "@angular/compiler", 104 | "@angular/cdk", 105 | "@angular/material", 106 | "@angular/platform-server", 107 | "@angular/platform-browser", 108 | "@angular/platform-browser-dynamic", 109 | "@angular/compiler-cli", 110 | "webpack", 111 | "zone.js", 112 | "rxjs", 113 | "tslint", 114 | "typescript", 115 | "codelyzer", 116 | "@types/jasmine", 117 | "@types/jest", 118 | "@types/node" 119 | ] 120 | }, 121 | "jest": { 122 | "preset": "jest-preset-angular", 123 | "roots": [ 124 | "src" 125 | ], 126 | "transform": { 127 | "^.+\\.(ts|js|html)$": "ts-jest" 128 | }, 129 | "setupFilesAfterEnv": [ 130 | "/src/setup-jest.ts" 131 | ], 132 | "moduleNameMapper": { 133 | "@app/(.*)": "/src/app/$1", 134 | "@assets/(.*)": "/src/assets/$1", 135 | "@core/(.*)": "/src/app/core/$1", 136 | "@env": "/src/environments/environment", 137 | "@src/(.*)": "/src/src/$1", 138 | "@state/(.*)": "/src/app/state/$1" 139 | }, 140 | "globals": { 141 | "ts-jest": { 142 | "tsConfig": "/tsconfig.spec.json", 143 | "stringifyContentPathRegex": "\\.html$", 144 | "astTransformers": [ 145 | "jest-preset-angular/build/InlineFilesTransformer", 146 | "jest-preset-angular/build/StripStylesTransformer" 147 | ] 148 | } 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /prerender.ts: -------------------------------------------------------------------------------- 1 | // Load zone.js for the server. 2 | import 'zone.js/node'; 3 | import 'reflect-metadata'; 4 | import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'; 5 | import { join } from 'path'; 6 | 7 | import { enableProdMode } from '@angular/core'; 8 | // Import module map for lazy loading 9 | import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader'; 10 | import { renderModuleFactory } from '@angular/platform-server'; 11 | import { ROUTES } from './static.paths'; 12 | 13 | // (global as any).WebSocket = require('ws'); 14 | // (global as any).XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; 15 | 16 | // Faster server renders w/ Prod mode (dev mode never needed) 17 | enableProdMode(); 18 | 19 | // * NOTE :: leave this as require() since this file is built Dynamically from webpack 20 | const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main'); 21 | 22 | const BROWSER_FOLDER = join(process.cwd(), 'browser'); 23 | 24 | // Load the index.html file containing referances to your application bundle. 25 | const index = readFileSync(join(BROWSER_FOLDER, 'index.html'), 'utf8'); 26 | 27 | let previousRender = Promise.resolve(); 28 | 29 | // Iterate each route path 30 | ROUTES.forEach(route => { 31 | const fullPath = join(BROWSER_FOLDER, route); 32 | 33 | // Make sure the directory structure is there 34 | if (!existsSync(fullPath)) { 35 | mkdirSync(fullPath); 36 | } 37 | 38 | // Writes rendered HTML to index.html, replacing the file if it already exists. 39 | previousRender = previousRender 40 | .then(_ => 41 | renderModuleFactory(AppServerModuleNgFactory, { 42 | document: index, 43 | url: route, 44 | extraProviders: [provideModuleMap(LAZY_MODULE_MAP)] 45 | }) 46 | ) 47 | .then(html => writeFileSync(join(fullPath, 'index.html'), html)); 48 | }); 49 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, '../../../coverage/angular-material-extensions/google-maps-autocomplete'), 20 | reports: ['html', 'lcovonly', 'text-summary'], 21 | fixWebpackSourcePaths: true 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false, 30 | restartOnFileChange: true 31 | }); 32 | }; 33 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../../dist/angular-material-extensions/google-maps-autocomplete", 4 | "lib": { 5 | "entryFile": "src/public-api.ts" 6 | } 7 | } -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/node_modules/.cache/ng-packagr/content-v2/sha512/23/21/df2eb0d936b785b0352cb96ad16591d124d86f6d35acc6cc3d25b3ab593ba6b5994e6086f995704238d10c69250a24488e1019984caad3b26dcda9af08bb: -------------------------------------------------------------------------------- 1 | {"css":".full-width{width:100%}\n","warnings":[]} -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/node_modules/.cache/ng-packagr/content-v2/sha512/8d/53/ad58764bc240411378ae1c47c0c20525da378a3b143795a11bc3fdbf6c9cde6fb2de6c3947d673d5872b9ce205d6274114b3b4dfd27609a636df7fd0b600: -------------------------------------------------------------------------------- 1 | {"css":"","warnings":[]} -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/node_modules/.cache/ng-packagr/index-v5/19/e1/29951b2873bc084a6884051b82ef358dbf04b1a2ad56ee9a418e597d0921: -------------------------------------------------------------------------------- 1 | 2 | 7eb9ecbd1c2d51ff8bfadb861305c1b2ef550ded {"key":"7ec1e20d0e3d03e096decd3f453701ce9d2724e3","integrity":"sha512-T2sezlE7rLY0jnqgZ+PuwY2fkgMx8gH5t26fiDUW0fDaYWtiu5b1HXe++5/u0m8DL+zyIZHUMIXdvbyqRqRgig==","time":1669391947647,"size":1057965} 3 | 3b2562b8c7a171eb2e421f978334f8d4ba07740e {"key":"7ec1e20d0e3d03e096decd3f453701ce9d2724e3","integrity":"sha512-FSHVr4n9MULjx78KoQ5zbtrl6iRJLI5KglDc6WwASy59hb5DX0l0vsWE587X/AuYzu/zuur1MjHjZAKvlq4Yig==","time":1669392923018,"size":1061322} -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/node_modules/.cache/ng-packagr/index-v5/19/ee/68c4353ae955146953eb987f5fa58756715b0c0149452881153dfe60797f: -------------------------------------------------------------------------------- 1 | 2 | e6e11fee02c22ee1b7ae1755722685de73fec47c {"key":"b7aa347af64e4229ea98b82ea8edf5904c99e8ed","integrity":"sha512-jVOtWHZLwkBBE3iuHEfAwgUl2jeKOxQ3laEbw/2/bJzeb7LebDlH1nPVhyuc4gXWJ0EUs7Tf0nYJpjbff9C2AA==","time":1669391942372,"size":24} -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/node_modules/.cache/ng-packagr/index-v5/22/73/f529ea7a007e93501a1e7e6e198a8085f080d270af983bd083823bd7515c: -------------------------------------------------------------------------------- 1 | 2 | 4e0375c904e347e94f0a794296f835331d3b16aa {"key":"e306772fa8a49fd4a23d48da1039fff03c474992","integrity":"sha512-jVOtWHZLwkBBE3iuHEfAwgUl2jeKOxQ3laEbw/2/bJzeb7LebDlH1nPVhyuc4gXWJ0EUs7Tf0nYJpjbff9C2AA==","time":1710407527694,"size":24} -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/node_modules/.cache/ng-packagr/index-v5/30/96/fd7e7628d0f09536f1f3ef0eb8409e6ad9d085afdf3bfd5c1a37943599de: -------------------------------------------------------------------------------- 1 | 2 | 5d08448c5d0610c1c5796e1b70ab9f867727a744 {"key":"0ab759e79324ecf02011602fadff50086aebe750","integrity":"sha512-+YbfMX5R9laPJQ9Qgy4hfNo8uW+eHFV/zDL0l7y9+pQtUQ+pCEoUP/bzOZJklEGJ453hOO4C+Sx3KBhxU7Co1g==","time":1669391947655,"size":236962} 3 | 9eefbc17802e3cd6e8b9a0b1814c283039fb2ee2 {"key":"0ab759e79324ecf02011602fadff50086aebe750","integrity":"sha512-eq0vvS0f6igrfeCbIpMHWIm608S9UojDDPeN/Ttw2nvRIH68rWiugvMfjnDU3hO7KAS21vWcroDN7D2YMWQVhw==","time":1669392923024,"size":237660} -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/node_modules/.cache/ng-packagr/index-v5/4a/a7/53885ff7f65600450455f4731be0e743dcf06239aff1eba82c932f34b0f4: -------------------------------------------------------------------------------- 1 | 2 | 790cb36fdfcae61234eb43ed170b122fac4c0a7b {"key":"97c55d56e42c7c88e65307e66c654db3b3d8ebc0","integrity":"sha512-IyHfLrDZNreFsDUsuWrRZZHRJNhvbTWsxsw9JbOrWTumtZlOYIb5lXBCONEMaSUKJEiOEBmYTKrTsm3Nqa8Iuw==","time":1710407527694,"size":49} -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/node_modules/.cache/ng-packagr/index-v5/69/f1/760835fe120ace77db4e25332fd732548ed84d4a7dd35d47f28f06469495: -------------------------------------------------------------------------------- 1 | 2 | 538e0fe42d334b8f442ae19b6aa983c8b1542d31 {"key":"5b6fad0a575e0c18f77fd1075ba2d5fa4ce4da92","integrity":"sha512-gZbt+1VNorWlHSBYHTITfoEur0O9QwDK/WcjxN5ASz6h/ZpZN/snyRH38uCOnehOQVn5fNsD0Q2k3Wh1jLmV1w==","time":1710407631316,"size":192049} 3 | 14e66b20ccac426a1c1933039681db550ffd2443 {"key":"5b6fad0a575e0c18f77fd1075ba2d5fa4ce4da92","integrity":"sha512-u0sQu1gmpQGUoKVTDLaRV+Ds7XOOrDNeGQxmgzboQe7tlHJfJcXjZ0kVwGMxSiOaNW4GHi0zILJDbJUWG6TX+Q==","time":1710407711979,"size":192049} 4 | eacebdb4f64a37f8de3bba809e4925f31b24c3bc {"key":"5b6fad0a575e0c18f77fd1075ba2d5fa4ce4da92","integrity":"sha512-VKa3IcnddR3U+S99AmRqDLQ5aOIn5TiBholaWOuyL8m6pLKUpY71HOPz3ZSqONgPYIiSg1rOQjPfYDX/vRlpAQ==","time":1710408806553,"size":193325} 5 | 44d5e6b7a7ffe501d9f50e66a9a5b438f8cad1ad {"key":"5b6fad0a575e0c18f77fd1075ba2d5fa4ce4da92","integrity":"sha512-tl1pWxQHIkF1KiVMbE+qD2/F/FHTKd0sOEf5jU8Oe9LZ6JoLmZYFJtnjFAp8NUkN7BenzeC366My7KeJtWmW4g==","time":1710409537200,"size":193097} 6 | c5d1075c40c560691893fbef4a0db6291c6882d0 {"key":"5b6fad0a575e0c18f77fd1075ba2d5fa4ce4da92","integrity":"sha512-xSN9aPFjvpjlwFWWaZ/jlXU4aVUxFUJ8Ikt+g5C78EdpG/qGt3gh93Jg21+DILK0rZZc8Cj4p82Jf7p9qklhSw==","time":1710409552765,"size":193097} 7 | bb30086c520c0202aef0b791093177c40c20280c {"key":"5b6fad0a575e0c18f77fd1075ba2d5fa4ce4da92","integrity":"sha512-uMhC4HYtIETHpRbcjbNpMgsZ61M06eyvLVttqJKs5vWMGMgx0UFcrkZy+mgsUDmyZ1S4ziK0vmE9HU2LSNzXQw==","time":1710410819634,"size":193276} 8 | 9540dc551b47086a3a3459787e83f730ff881a19 {"key":"5b6fad0a575e0c18f77fd1075ba2d5fa4ce4da92","integrity":"sha512-Fj+fdE7Ub9yNe1W+wRv/dbf2TqM4YCRQqSyFrd9vcKNe9G5aVttzVTTIEkjJWNITkZRXksRi6Ny/xxgcfuGNpA==","time":1710411072240,"size":194298} 9 | 3fb87e8ffb66f975c9674061308d4c7f59e5608a {"key":"5b6fad0a575e0c18f77fd1075ba2d5fa4ce4da92","integrity":"sha512-acop0NnxK/eaH7V8dYtvQyeDoe7JjNuzdyzxOeJvd2pV8GGGkChy5L7V5KPOaba7Jq/KgW3pnw3LizrEgbBZbA==","time":1726908675808,"size":194196} 10 | 4f4ed8ecc59b1edfefc6fa94eabbf2496ef1e4e4 {"key":"5b6fad0a575e0c18f77fd1075ba2d5fa4ce4da92","integrity":"sha512-m1+23AWF5rCw/d9rsbiOFPI6DifnEwK/QFN2aWrqmI9AXC6Ck+/f6cgQuBq87NeEUphF9CXpUx29O+CaawBScA==","time":1726908783781,"size":194554} 11 | 17150256f3b7e83e931b0ab08fb7d4b55491c2a2 {"key":"5b6fad0a575e0c18f77fd1075ba2d5fa4ce4da92","integrity":"sha512-kJkSi5CdNUgE8qu7QafV9Wt/wZjWVLi9MPeaV7WBH8MtTbln+sZ1lmrqp2+8FK2mAteFwrCvJlA5WUP10UFxtw==","time":1726908866248,"size":194890} 12 | 407a85477dab8f57adda378c571e2a41951ac7d3 {"key":"5b6fad0a575e0c18f77fd1075ba2d5fa4ce4da92","integrity":"sha512-1T3iaxQuvKXbL22y5jPl35YO+iRe20EuwMSMbBgTwn0z4K1IYshL2/3uB3ERh4HSTyc5lU6xRTt9O3wIaogVTg==","time":1726908967599,"size":194778} -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/node_modules/.cache/ng-packagr/index-v5/85/9b/2e474c9ad8ef48835537e9964f9c046e49c77e20d7bcd1cd54957cd3a81e: -------------------------------------------------------------------------------- 1 | 2 | 8c2f36b162321976614070269111af4e6cc1765c {"key":"58dd0202605f1ba23f42ba40bda2c3a1d82f687e","integrity":"sha512-dsxV9FjJH8E79SNI34jKRGIiWwNH0L9WL2DuUfVcGIyn0Eeh4juJbnaGB1pBLMcjhtvezLpPN2E2yPuyUqfM8Q==","time":1710407631308,"size":1008079} 3 | 4071a6317780d0063e53345cd11a75b218679bd6 {"key":"58dd0202605f1ba23f42ba40bda2c3a1d82f687e","integrity":"sha512-dsxV9FjJH8E79SNI34jKRGIiWwNH0L9WL2DuUfVcGIyn0Eeh4juJbnaGB1pBLMcjhtvezLpPN2E2yPuyUqfM8Q==","time":1710407711974,"size":1008079} 4 | a6e8769bf0fc9d413e0f4caf9162dd0aa93d7e30 {"key":"58dd0202605f1ba23f42ba40bda2c3a1d82f687e","integrity":"sha512-I/t6rMbuxOSoocZ94W9iQurn2lCqwb2MmX2OanzO1lte/cHiXFsZxzR5O5YSdIGF25DpkdbcWEbhOaQaFJKR0A==","time":1710408806551,"size":1016078} 5 | 280ad93901fb13d54a6ad723a81446fdd85a54f1 {"key":"58dd0202605f1ba23f42ba40bda2c3a1d82f687e","integrity":"sha512-Xl4dppy/DeOE7Vy/aMkJ/VEiUZg0rRGG3Tj8aYYVXXlqSHvlKjziC4fe5f8eJ1rsLpJH6DuphmE6QP2VpV8M2g==","time":1710409537197,"size":1014596} 6 | d46d9c5fac801cf7dcede7569becc039c891cbf3 {"key":"58dd0202605f1ba23f42ba40bda2c3a1d82f687e","integrity":"sha512-Xl4dppy/DeOE7Vy/aMkJ/VEiUZg0rRGG3Tj8aYYVXXlqSHvlKjziC4fe5f8eJ1rsLpJH6DuphmE6QP2VpV8M2g==","time":1710409552762,"size":1014596} 7 | 16067bd9dd059c891e2a6d65b35b690eed9f5328 {"key":"58dd0202605f1ba23f42ba40bda2c3a1d82f687e","integrity":"sha512-ZzGc7P7C8YAILhJEGB8gqgq8JDejINxmCehXm+K6giDD98LZjEcPXpF7EkDrXhtFYGS8t39c6lmoCDlujgyH1w==","time":1710410819631,"size":1016187} 8 | 3ef03b76fbe18ffe344c1cc69db924d51db43354 {"key":"58dd0202605f1ba23f42ba40bda2c3a1d82f687e","integrity":"sha512-+26EHJoyXgYh5INErkJyfz5hiWHQczKf+Pkr1lQOG4GMMRZ2fhW4VRKtaNzkDmq6xJ2KdzqxzinDPan3PE18tA==","time":1710411072234,"size":1023098} 9 | 8a6fa257c599f7eabc33f7b1e689b26a4187604c {"key":"58dd0202605f1ba23f42ba40bda2c3a1d82f687e","integrity":"sha512-2aIrj5KgEPmu2VElRI4mmrEXOR/PTSoBf8fGNR35skt2mYWul5hInlHSYiFgSJ5BDemAiYGQ0h9qGEhDesjGqA==","time":1726908675800,"size":1022159} 10 | dd31d102a447301a959fa37f9b052100cd69da28 {"key":"58dd0202605f1ba23f42ba40bda2c3a1d82f687e","integrity":"sha512-2JaMaNitbzdotbdljGhw+Hht3I5XCKLIOqKosCZHksBlONYuZ2CaOqDv4Ah5TGBwOslr84VkTwoby62pxMsMqQ==","time":1726908783776,"size":1024008} 11 | d717a7b81bf4001616b33819bb6d21ea561bcd9e {"key":"58dd0202605f1ba23f42ba40bda2c3a1d82f687e","integrity":"sha512-INYi+K1KQcWMZgGLEwl0u5KFvmsgVfbd1ZrZeA1QdEbpwOcpW2KTfRPXZOI/G4ixaELEQBd2Wu+SJgjTiqrsJg==","time":1726908866243,"size":1025794} 12 | a5be93c8a19cd74a359bc13ef546efc3546bfd78 {"key":"58dd0202605f1ba23f42ba40bda2c3a1d82f687e","integrity":"sha512-bYiS8eZPV1L37U1ugER6tw2gPQWupxZJLqWTWDSmUtrU0BBQHNhtrgtQ/l6CDtVLT3v3WxIq9aSZ4zihQ+XvDg==","time":1726908967594,"size":1023645} -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/node_modules/.cache/ng-packagr/index-v5/e8/45/220879efee1038dc25ab3e872f4a51fb09f05e2f50fb4dfb26b2aa8ec464: -------------------------------------------------------------------------------- 1 | 2 | 5f0e12bfb6fecb2d8819e9707675f27f1f7e3555 {"key":"9d60f902afccba6a518a72d287c1b3350573250b","integrity":"sha512-IyHfLrDZNreFsDUsuWrRZZHRJNhvbTWsxsw9JbOrWTumtZlOYIb5lXBCONEMaSUKJEiOEBmYTKrTsm3Nqa8Iuw==","time":1669391942372,"size":49} -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/node_modules/.cache/ng-packagr/index-v5/ed/e7/4d855f633cac01456450c1767a172aa10a8e68ec42dc18ad78b18d9cc3cb: -------------------------------------------------------------------------------- 1 | 2 | a68bf2605f354c80efd441978fb56d02a47640fd {"key":"e99ffcf5cb244fb8d6b22685e109b0ec0dd85767","integrity":"sha512-LxGZKnZEL8wwiUg2TYpC8MYnlLvu+9G5mD/7BbJgS2eCMxI4JdTqMHDLdH+H4z1WO2wh19kjgpo/aSw8DY3r4g==","time":1669391947006,"size":934360} 3 | 8158d247082a73292aed88393c764dff83581e27 {"key":"e99ffcf5cb244fb8d6b22685e109b0ec0dd85767","integrity":"sha512-k1bgeK2DBuiVtQtyjbDqqRlJmQAknIatJUZmVeojB6pA/jJvfOB/s6XPSA3DPaCY+cLrzKKG8BEGazhWEfWtsg==","time":1669392922532,"size":936805} -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@angular-material-extensions/google-maps-autocomplete", 3 | "description": "Autocomplete input component and directive for google-maps built with angular and material design", 4 | "version": "16.4.0", 5 | "homepage": "https://angular-material-extensions.github.io/google-maps-autocomplete", 6 | "author": { 7 | "name": "Anthony Nahas", 8 | "url": "https://github.com/angular-material-extensions" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git://github.com/angular-material-extensions/google-maps-autocomplete.git" 13 | }, 14 | "license": "MIT", 15 | "schematics": "./schematics/collection.json", 16 | "keywords": [ 17 | "angular", 18 | "material design", 19 | "google maps", 20 | "autocomplete", 21 | "places", 22 | "locations", 23 | "parse", 24 | "street name", 25 | "location", 26 | "country", 27 | "city" 28 | ], 29 | "bugs": { 30 | "url": "https://github.com/angular-material-extensions/google-maps-autocomplete/issues" 31 | }, 32 | "scripts": { 33 | "build": "ng build @angular-material-extensions/google-maps-autocomplete --configuration production", 34 | "build:watch": "../../../node_modules/.bin/ng build @angular-material-extensions/google-maps-autocomplete --watch", 35 | "build:schematics": "../../../node_modules/.bin/tsc -p tsconfig.schematics.json", 36 | "clean": "rm -rf ../../../dist", 37 | "lint": "../../../node_modules/.bin/ng lint @angular-material-extensions/google-maps-autocomplete", 38 | "resync:schematics": "rsync -a schematics/collection.json ../../../dist/angular-material-extensions/google-maps-autocomplete/schematics/", 39 | "resync:readme": "rsync -a ../../../README.md ../../../dist/angular-material-extensions/google-maps-autocomplete/", 40 | "postbuild": "npm run build:schematics && npm run resync:readme && npm run resync:schematics", 41 | "prepublish": "npm run build", 42 | "postinstall": "ngcc", 43 | "release:patch": "../../../node_modules/.bin/release-it --patch --ci", 44 | "release:minor": "../../../node_modules/.bin/release-it --minor --ci", 45 | "release:major": "../../../node_modules/.bin/release-it --major --ci --no-git.requireCleanWorkingDir --dry-run", 46 | "release:custom": "../../../node_modules/.bin/release-it 16.4.0 --ci --no-git.requireCleanWorkingDir", 47 | "ng:test": "../../../node_modules/.bin/ng test @angular-material-extensions/google-maps-autocomplete", 48 | "test": "../../../node_modules/.bin/jest --coverage", 49 | "test:watch": "../../../node_modules/.bin/jest --coverage --watch" 50 | }, 51 | "peerDependencies": { 52 | "@angular/common": "^16.x", 53 | "@angular/core": "^16.x", 54 | "@angular/platform-browser": "^16.x", 55 | "@angular/flex-layout": "^15.0.0-beta.42", 56 | "@angular/forms": "^16.x", 57 | "@angular/cdk": "^16.x", 58 | "@angular/material": "^16.x", 59 | "@types/googlemaps": "~3.43.3", 60 | "rxjs": "^7.x", 61 | "zone.js": "~0.13.x" 62 | }, 63 | "engines": { 64 | "node": ">=16.0.0" 65 | }, 66 | "release-it": { 67 | "github": { 68 | "release": true 69 | }, 70 | "npm": { 71 | "publish": true, 72 | "publishPath": "../../../dist/angular-material-extensions/google-maps-autocomplete" 73 | }, 74 | "publishConfig": { 75 | "access": "public" 76 | }, 77 | "plugins": { 78 | "@release-it/conventional-changelog": { 79 | "preset": "angular", 80 | "infile": "../../../CHANGELOG.md" 81 | } 82 | }, 83 | "hooks": { 84 | "before:init": [ 85 | "npm run clean" 86 | ], 87 | "after:bump": "echo \"building lib v${version}... \" && npm run build", 88 | "before:git:release": "echo \"Updating CHANGELOG.md for v${version} \" && git commit -a -m \"docs(project): Updating CHANGELOG.md for v${version} \" && git push", 89 | "after:release": "echo Successfully released ${name} v${version} to ${repo.repository}.", 90 | "before:npm": "echo building the library..." 91 | } 92 | }, 93 | "jest": { 94 | "preset": "jest-preset-angular", 95 | "setupFilesAfterEnv": [ 96 | "/../../../src/setup-jest.ts" 97 | ] 98 | }, 99 | "globals": { 100 | "ts-jest": { 101 | "tsConfig": "/tsconfig.spec.json", 102 | "stringifyContentPathRegex": "\\.html$", 103 | "astTransformers": [ 104 | "jest-preset-angular/build/InlineFilesTransformer", 105 | "jest-preset-angular/build/StripStylesTransformer" 106 | ] 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/schematics/collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../../node_modules/@angular-devkit/schematics/collection-schema.json", 3 | "schematics": { 4 | "ng-add": { 5 | "description": "Installs and injects the @angular-material-extensions/google-maps-autocomplete library", 6 | "factory": "./ng-add/index" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/schematics/helpers/angular/ast-utils.ts: -------------------------------------------------------------------------------- 1 | import { 2 | insertImport as originalInsertImport, 3 | findNodes as originalFindNodes, 4 | findNode as originalFindNode, 5 | getSourceNodes as originalGetSourceNodes, 6 | insertAfterLastOccurrence as originalInsertAfterLastOccurrence, 7 | getContentOfKeyLiteral as originalGetContentOfKeyLiteral, 8 | getFirstNgModuleName as originalGetFirstNgModuleName, 9 | getDecoratorMetadata as originalGetDecoratorMetadata, 10 | getMetadataField as originalGetMetadataField, 11 | getRouterModuleDeclaration as originalGetRouterModuleDeclaration, 12 | addSymbolToNgModuleMetadata as originalAddSymbolToNgModuleMetadata, 13 | addDeclarationToModule as originalAddDeclarationToModule, 14 | addImportToModule as originalAddImportToModule, 15 | addProviderToModule as originalAddProviderToModule, 16 | addExportToModule as originalAddExportToModule, 17 | addBootstrapToModule as originalAddBootstrapToModule, 18 | addEntryComponentToModule as originalAddEntryComponentToModule, 19 | addRouteDeclarationToModule as originalAddRouteDeclarationToModule, 20 | isImported as originalIsImported 21 | } from '@schematics/angular/utility/ast-utils'; 22 | import * as ts from '@schematics/angular/third_party/github.com/Microsoft/TypeScript/lib/typescript'; 23 | 24 | import { Change } from './change'; 25 | 26 | /** 27 | * Add Import `import { symbolName } from fileName` if the import doesn't exit 28 | * already. Assumes fileToEdit can be resolved and accessed. 29 | * @param fileToEdit (file we want to add import to) 30 | * @param symbolName (item to import) 31 | * @param fileName (path to the file) 32 | * @param isDefault (if true, import follows style for importing default exports) 33 | * @return Change 34 | */ 35 | export function insertImport( 36 | source: ts.SourceFile, 37 | fileToEdit: string, 38 | symbolName: string, 39 | fileName: string, 40 | isDefault = false 41 | ): Change { 42 | return originalInsertImport(source, fileToEdit, symbolName, fileName, isDefault); 43 | } 44 | 45 | /** 46 | * Find all nodes from the AST in the subtree of node of SyntaxKind kind. 47 | * @param node 48 | * @param kind 49 | * @param max The maximum number of items to return. 50 | * @param recursive Continue looking for nodes of kind recursive until end 51 | * the last child even when node of kind has been found. 52 | * @return all nodes of kind, or [] if none is found 53 | */ 54 | export function findNodes(node: ts.Node, kind: ts.SyntaxKind, max = Infinity, recursive = false): ts.Node[] { 55 | return originalFindNodes(node, kind, max, recursive); 56 | } 57 | 58 | /** 59 | * Get all the nodes from a source. 60 | * @param sourceFile The source file object. 61 | * @returns {Observable} An observable of all the nodes in the source. 62 | */ 63 | export function getSourceNodes(sourceFile: ts.SourceFile): ts.Node[] { 64 | return originalGetSourceNodes(sourceFile); 65 | } 66 | 67 | export function findNode(node: ts.Node, kind: ts.SyntaxKind, text: string): ts.Node | null { 68 | return originalFindNode(node, kind, text); 69 | } 70 | 71 | /** 72 | * Insert `toInsert` after the last occurence of `ts.SyntaxKind[nodes[i].kind]` 73 | * or after the last of occurence of `syntaxKind` if the last occurence is a sub child 74 | * of ts.SyntaxKind[nodes[i].kind] and save the changes in file. 75 | * 76 | * @param nodes insert after the last occurence of nodes 77 | * @param toInsert string to insert 78 | * @param file file to insert changes into 79 | * @param fallbackPos position to insert if toInsert happens to be the first occurence 80 | * @param syntaxKind the ts.SyntaxKind of the subchildren to insert after 81 | * @return Change instance 82 | * @throw Error if toInsert is first occurence but fall back is not set 83 | */ 84 | export function insertAfterLastOccurrence( 85 | nodes: ts.Node[], 86 | toInsert: string, 87 | file: string, 88 | fallbackPos: number, 89 | syntaxKind?: ts.SyntaxKind 90 | ): Change { 91 | return originalInsertAfterLastOccurrence(nodes, toInsert, file, fallbackPos, syntaxKind); 92 | } 93 | 94 | export function getContentOfKeyLiteral(_source: ts.SourceFile, node: ts.Node): string | null { 95 | return originalGetContentOfKeyLiteral(_source, node); 96 | } 97 | 98 | export function getDecoratorMetadata(source: ts.SourceFile, identifier: string, module: string): ts.Node[] { 99 | return originalGetDecoratorMetadata(source, identifier, module); 100 | } 101 | 102 | /** 103 | * Given a source file with @NgModule class(es), find the name of the first @NgModule class. 104 | * 105 | * @param source source file containing one or more @NgModule 106 | * @returns the name of the first @NgModule, or `undefined` if none is found 107 | */ 108 | export function getFirstNgModuleName(source: ts.SourceFile): string | undefined { 109 | return originalGetFirstNgModuleName(source); 110 | } 111 | 112 | export function getMetadataField(node: ts.ObjectLiteralExpression, metadataField: string): ts.ObjectLiteralElement[] { 113 | return originalGetMetadataField(node, metadataField); 114 | } 115 | 116 | export function addSymbolToNgModuleMetadata( 117 | source: ts.SourceFile, 118 | ngModulePath: string, 119 | metadataField: string, 120 | symbolName: string, 121 | importPath: string | null = null 122 | ): Change[] { 123 | return originalAddSymbolToNgModuleMetadata(source, ngModulePath, metadataField, symbolName, importPath); 124 | } 125 | 126 | /** 127 | * Custom function to insert a declaration (component, pipe, directive) 128 | * into NgModule declarations. It also imports the component. 129 | */ 130 | export function addDeclarationToModule( 131 | source: ts.SourceFile, 132 | modulePath: string, 133 | classifiedName: string, 134 | importPath: string 135 | ): Change[] { 136 | return originalAddDeclarationToModule(source, modulePath, classifiedName, importPath); 137 | } 138 | 139 | /** 140 | * Custom function to insert an NgModule into NgModule imports. It also imports the module. 141 | */ 142 | export function addImportToModule( 143 | source: ts.SourceFile, 144 | modulePath: string, 145 | classifiedName: string, 146 | importPath: string 147 | ): Change[] { 148 | return originalAddImportToModule(source, modulePath, classifiedName, importPath); 149 | } 150 | 151 | /** 152 | * Custom function to insert a provider into NgModule. It also imports it. 153 | */ 154 | export function addProviderToModule( 155 | source: ts.SourceFile, 156 | modulePath: string, 157 | classifiedName: string, 158 | importPath: string 159 | ): Change[] { 160 | return originalAddProviderToModule(source, modulePath, classifiedName, importPath); 161 | } 162 | 163 | /** 164 | * Custom function to insert an export into NgModule. It also imports it. 165 | */ 166 | export function addExportToModule( 167 | source: ts.SourceFile, 168 | modulePath: string, 169 | classifiedName: string, 170 | importPath: string 171 | ): Change[] { 172 | return originalAddExportToModule(source, modulePath, classifiedName, importPath); 173 | } 174 | 175 | /** 176 | * Custom function to insert an export into NgModule. It also imports it. 177 | */ 178 | export function addBootstrapToModule( 179 | source: ts.SourceFile, 180 | modulePath: string, 181 | classifiedName: string, 182 | importPath: string 183 | ): Change[] { 184 | return originalAddBootstrapToModule(source, modulePath, classifiedName, importPath); 185 | } 186 | 187 | /** 188 | * Custom function to insert an entryComponent into NgModule. It also imports it. 189 | */ 190 | export function addEntryComponentToModule( 191 | source: ts.SourceFile, 192 | modulePath: string, 193 | classifiedName: string, 194 | importPath: string 195 | ): Change[] { 196 | return originalAddEntryComponentToModule(source, modulePath, classifiedName, importPath); 197 | } 198 | 199 | /** 200 | * Determine if an import already exists. 201 | */ 202 | export function isImported(source: ts.SourceFile, classifiedName: string, importPath: string): boolean { 203 | return originalIsImported(source, classifiedName, importPath); 204 | } 205 | 206 | /** 207 | * Returns the RouterModule declaration from NgModule metadata, if any. 208 | */ 209 | export function getRouterModuleDeclaration(source: ts.SourceFile): ts.Expression | undefined { 210 | return originalGetRouterModuleDeclaration(source); 211 | } 212 | 213 | /** 214 | * Adds a new route declaration to a router module (i.e. has a RouterModule declaration) 215 | */ 216 | export function addRouteDeclarationToModule(source: ts.SourceFile, fileToAdd: string, routeLiteral: string): Change { 217 | return originalAddRouteDeclarationToModule(source, fileToAdd, routeLiteral); 218 | } 219 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/schematics/helpers/angular/change.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Host as OriginalHost, 3 | Change as OriginalChange, 4 | NoopChange as OriginalNoopChange, 5 | InsertChange as OriginalInsertChange, 6 | RemoveChange as OriginalRemoveChange, 7 | ReplaceChange as OriginalReplaceChange 8 | } from '@schematics/angular/utility/change'; 9 | 10 | export interface Host extends OriginalHost {} 11 | 12 | export interface Change extends OriginalChange {} 13 | 14 | /** 15 | * An operation that does nothing. 16 | */ 17 | export class NoopChange extends OriginalNoopChange {} 18 | 19 | /** 20 | * Will add text to the source code. 21 | */ 22 | export class InsertChange extends OriginalInsertChange {} 23 | 24 | /** 25 | * Will remove text from the source code. 26 | */ 27 | export class RemoveChange extends OriginalRemoveChange {} 28 | 29 | /** 30 | * Will replace text from the source code. 31 | */ 32 | export class ReplaceChange extends OriginalReplaceChange {} 33 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/schematics/helpers/angular/component-schema.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google Inc. All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | export interface Schema { 10 | /** 11 | * The path to create the component. 12 | */ 13 | path?: string; 14 | /** 15 | * The name of the project. 16 | */ 17 | project?: string; 18 | /** 19 | * The name of the component. 20 | */ 21 | name: string; 22 | /** 23 | * Specifies if the style will be in the ts file. 24 | */ 25 | inlineStyle?: boolean; 26 | /** 27 | * Specifies if the template will be in the ts file. 28 | */ 29 | inlineTemplate?: boolean; 30 | /** 31 | * Specifies the view encapsulation strategy. 32 | */ 33 | viewEncapsulation?: 'Emulated' | 'Native' | 'None'; 34 | /** 35 | * Specifies the change detection strategy. 36 | */ 37 | changeDetection?: 'Default' | 'OnPush'; 38 | /** 39 | * The prefix to apply to generated selectors. 40 | */ 41 | prefix?: string; 42 | /** 43 | * The file extension to be used for style files. 44 | */ 45 | styleext?: string; 46 | /** 47 | * Specifies if a spec file is generated. 48 | */ 49 | spec?: boolean; 50 | /** 51 | * Flag to indicate if a dir is created. 52 | */ 53 | flat?: boolean; 54 | /** 55 | * Flag to skip the module import. 56 | */ 57 | skipImport?: boolean; 58 | /** 59 | * The selector to use for the component. 60 | */ 61 | selector?: string; 62 | /** 63 | * Allows specification of the declaring module. 64 | */ 65 | module?: string; 66 | /** 67 | * Specifies if declaring module exports the component. 68 | */ 69 | export?: boolean; 70 | /** 71 | * Specifies if the component is an entry component of declaring module. 72 | */ 73 | entryComponent?: boolean; 74 | /** 75 | * Specifies whether to apply lint fixes after generating the component. 76 | */ 77 | lintFix?: boolean; 78 | } 79 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/schematics/helpers/angular/dependencies.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@angular-devkit/schematics'; 2 | import { 3 | NodeDependency as OriginalNodeDependency, 4 | addPackageJsonDependency as originalAddPackageJsonDependency, 5 | getPackageJsonDependency as originalGetPackageJsonDependency, 6 | removePackageJsonDependency as originalRemovePackageJsonDependency 7 | } from '@schematics/angular/utility/dependencies'; 8 | 9 | export enum NodeDependencyType { 10 | Default = 'dependencies', 11 | Dev = 'devDependencies', 12 | Peer = 'peerDependencies', 13 | Optional = 'optionalDependencies' 14 | } 15 | 16 | export interface NodeDependency extends OriginalNodeDependency {} 17 | 18 | export function addPackageJsonDependency(tree: Tree, dependency: NodeDependency): void { 19 | return originalAddPackageJsonDependency(tree, dependency); 20 | } 21 | 22 | export function removePackageJsonDependency(tree: Tree, name: string): void { 23 | return originalRemovePackageJsonDependency(tree, name); 24 | } 25 | 26 | export function getPackageJsonDependency(tree: Tree, name: string): NodeDependency | null { 27 | return originalGetPackageJsonDependency(tree, name); 28 | } 29 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/schematics/helpers/angular/find-module.ts: -------------------------------------------------------------------------------- 1 | import { Path } from '@angular-devkit/core'; 2 | import { Tree } from '@angular-devkit/schematics'; 3 | 4 | import { 5 | ModuleOptions as OriginalModuleOptions, 6 | findModuleFromOptions as originalFindModuleFromOptions, 7 | findModule as originalFindModule, 8 | buildRelativePath as originalBuildRelativePath, 9 | MODULE_EXT as ORIGINAL_MODULE_EXT, 10 | ROUTING_MODULE_EXT as ORIGINAL_ROUTING_MODULE_EXT 11 | } from '@schematics/angular/utility/find-module'; 12 | 13 | export interface ModuleOptions extends OriginalModuleOptions {} 14 | 15 | /** 16 | * Find the module referred by a set of options passed to the schematics. 17 | */ 18 | export function findModuleFromOptions(host: Tree, options: ModuleOptions): Path | undefined { 19 | return originalFindModuleFromOptions(host, options); 20 | } 21 | 22 | /** 23 | * Function to find the "closest" module to a generated file's path. 24 | */ 25 | export function findModule( 26 | host: Tree, 27 | generateDir: string, 28 | moduleExt = MODULE_EXT, 29 | routingModuleExt = ROUTING_MODULE_EXT 30 | ): Path { 31 | return originalFindModule(host, generateDir, moduleExt, routingModuleExt); 32 | } 33 | 34 | /** 35 | * Build a relative path from one file path to another file path. 36 | */ 37 | export function buildRelativePath(from: string, to: string): string { 38 | return originalBuildRelativePath(from, to); 39 | } 40 | 41 | export const MODULE_EXT = ORIGINAL_MODULE_EXT; 42 | export const ROUTING_MODULE_EXT = ORIGINAL_ROUTING_MODULE_EXT; 43 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/schematics/helpers/angular/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ast-utils'; 2 | export * from './change'; 3 | export * from './component-schema'; 4 | export * from './dependencies'; 5 | export * from './find-module'; 6 | export * from './latest-versions'; 7 | export * from './ng-ast-utils'; 8 | export * from './parse-name'; 9 | export * from './paths'; 10 | export * from './validation'; 11 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/schematics/helpers/angular/latest-versions.ts: -------------------------------------------------------------------------------- 1 | import { latestVersions as originalLatestVersions } from '@schematics/angular/utility/latest-versions'; 2 | 3 | export const latestVersions = originalLatestVersions; 4 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/schematics/helpers/angular/ng-ast-utils.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@angular-devkit/schematics'; 2 | import { 3 | findBootstrapModuleCall as originalFindBootstrapModuleCall, 4 | findBootstrapModulePath as originalFindBootstrapModulePath, 5 | getAppModulePath as originalGetAppModulePath 6 | } from '@schematics/angular/utility/ng-ast-utils'; 7 | import * as ts from '@schematics/angular/third_party/github.com/Microsoft/TypeScript/lib/typescript'; 8 | 9 | export function findBootstrapModuleCall(host: Tree, mainPath: string): ts.CallExpression | null { 10 | return originalFindBootstrapModuleCall(host, mainPath); 11 | } 12 | 13 | export function findBootstrapModulePath(host: Tree, mainPath: string): string { 14 | return originalFindBootstrapModulePath(host, mainPath); 15 | } 16 | 17 | export function getAppModulePath(host: Tree, mainPath: string): string { 18 | return originalGetAppModulePath(host, mainPath); 19 | } 20 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/schematics/helpers/angular/parse-name.ts: -------------------------------------------------------------------------------- 1 | import { Location as OriginalLocation, parseName as originalParseName } from '@schematics/angular/utility/parse-name'; 2 | 3 | export interface Location extends OriginalLocation {} 4 | 5 | export function parseName(path: string, name: string): Location { 6 | return originalParseName(path, name); 7 | } 8 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/schematics/helpers/angular/paths.ts: -------------------------------------------------------------------------------- 1 | import { relativePathToWorkspaceRoot as originalRelativePathToWorkspaceRoot } from '@schematics/angular/utility/paths'; 2 | 3 | export function relativePathToWorkspaceRoot(projectRoot: string | undefined): string { 4 | return originalRelativePathToWorkspaceRoot(projectRoot); 5 | } 6 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/schematics/helpers/angular/validation.ts: -------------------------------------------------------------------------------- 1 | import { 2 | htmlSelectorRe as originalHtmlSelectorRe, 3 | validateName as originalValidateName, 4 | validateHtmlSelector as originalValidateHtmlSelector, 5 | validateProjectName as originalValidateProjectName 6 | } from '@schematics/angular/utility/validation'; 7 | 8 | export function validateName(name: string): void { 9 | return originalValidateName(name); 10 | } 11 | 12 | // Must start with a letter, and must contain only alphanumeric characters or dashes. 13 | // When adding a dash the segment after the dash must also start with a letter. 14 | export const htmlSelectorRe = originalHtmlSelectorRe; 15 | 16 | export function validateHtmlSelector(selector: string): void { 17 | return originalValidateHtmlSelector(selector); 18 | } 19 | 20 | export function validateProjectName(projectName: string) { 21 | return originalValidateProjectName(projectName); 22 | } 23 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/schematics/helpers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './angular/index'; 2 | export * from './material/index'; 3 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/schematics/helpers/material/ast/ng-module-imports.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@angular-devkit/schematics'; 2 | import { hasNgModuleImport as originalHasNgModuleImport } from '@angular/cdk/schematics'; 3 | 4 | /** 5 | * Whether the Angular module in the given path imports the specified module class name. 6 | */ 7 | export function hasNgModuleImport(tree: Tree, modulePath: string, className: string): boolean { 8 | return originalHasNgModuleImport(tree, modulePath, className); 9 | } 10 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/schematics/helpers/material/build-component.ts: -------------------------------------------------------------------------------- 1 | import { Rule } from '@angular-devkit/schematics'; 2 | import { Schema as ComponentOptions } from '@schematics/angular/component/schema'; 3 | import { buildComponent as originalBuildComponent } from '@angular/cdk/schematics'; 4 | 5 | /** 6 | * Rule that copies and interpolates the files that belong to this schematic context. Additionally 7 | * a list of file paths can be passed to this rule in order to expose them inside the EJS 8 | * template context. 9 | * 10 | * This allows inlining the external template or stylesheet files in EJS without having 11 | * to manually duplicate the file content. 12 | */ 13 | export function buildComponent(options: ComponentOptions, additionalFiles: { [key: string]: string } = {}): Rule { 14 | return originalBuildComponent(options, additionalFiles); 15 | } 16 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/schematics/helpers/material/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ast/ng-module-imports'; 2 | export * from './build-component'; 3 | export * from './package-config'; 4 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/schematics/helpers/material/package-config.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@angular-devkit/schematics'; 2 | import { addPackageToPackageJson as originalAddPackageToPackageJson } from '@angular/cdk/schematics/ng-add/package-config'; 3 | 4 | /** Adds a package to the package.json in the given host tree. */ 5 | export function addPackageToPackageJson(host: Tree, pkg: string, version: string): Tree { 6 | return originalAddPackageToPackageJson(host, pkg, version); 7 | } 8 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/schematics/ng-add/index.ts: -------------------------------------------------------------------------------- 1 | import {chain, noop, Rule, SchematicContext, Tree} from '@angular-devkit/schematics'; 2 | import {NodePackageInstallTask} from '@angular-devkit/schematics/tasks'; 3 | import {addPackageJsonDependency, NodeDependency, NodeDependencyType} from '../helpers'; 4 | import {getWorkspace} from '@schematics/angular/utility/config'; 5 | import {addModuleImportToRootModule, getProjectFromWorkspace} from '@angular/cdk/schematics'; 6 | 7 | /** Loads the full version from the given Angular package gracefully. */ 8 | function loadPackageVersionGracefully(context: SchematicContext): string | null { 9 | try { 10 | context.logger.log('info', `🧟‍ @angular-material-extensions/google-maps-autocomplete 11 | is using the following version ${require(`../../package.json`).version}`); 12 | return require(`../../package.json`).version; 13 | } catch { 14 | return null; 15 | } 16 | } 17 | 18 | // You don't have to export the function as default. You can also have more than one rule factory 19 | // per file. 20 | export function addPackageJsonDependencies(): Rule { 21 | return (host: Tree, context: SchematicContext) => { 22 | 23 | const ngCoreVersionTag = getPackageVersionFromPackageJson(host, '@angular/core'); 24 | 25 | const dependencies: NodeDependency[] = [ 26 | { 27 | type: NodeDependencyType.Default, 28 | version: loadPackageVersionGracefully(context) || 'latest', 29 | name: '@angular-material-extensions/google-maps-autocomplete' 30 | }, 31 | {type: NodeDependencyType.Default, version: '^3.0.0-beta.0', name: '@agm/core'}, 32 | {type: NodeDependencyType.Default, version: '3.39.12', name: '@types/googlemaps'}, 33 | {type: NodeDependencyType.Default, version: ngCoreVersionTag || '~10.0.0', name: '@angular/animations'}, 34 | {type: NodeDependencyType.Default, version: ngCoreVersionTag || '~10.0.0', name: '@angular/forms'} 35 | ]; 36 | 37 | dependencies.forEach(dependency => { 38 | addPackageJsonDependency(host, dependency); 39 | context.logger.log('info', `✅️ Added "${dependency.name}" into ${dependency.type}`); 40 | }); 41 | 42 | return host; 43 | }; 44 | } 45 | 46 | export function installPackageJsonDependencies(): Rule { 47 | return (host: Tree, context: SchematicContext) => { 48 | context.addTask(new NodePackageInstallTask()); 49 | context.logger.log('info', `🔍 Installing packages...`); 50 | 51 | return host; 52 | }; 53 | } 54 | 55 | export function addModuleToImports(options: any): Rule { 56 | return (host: Tree, context: SchematicContext) => { 57 | const workspace = getWorkspace(host); 58 | // @ts-ignore 59 | const project = getProjectFromWorkspace(workspace, options.project); 60 | const moduleName = 'MatGoogleMapsAutocompleteModule'; 61 | const agmCoreModule = 'AgmCoreModule.forRoot()'; 62 | 63 | addModuleImportToRootModule(host, moduleName, '@angular-material-extensions/google-maps-autocomplete', project); 64 | addModuleImportToRootModule(host, agmCoreModule, '@agm/core', project); 65 | context.logger.log('info', `✅️ "${moduleName}" is imported`); 66 | 67 | return host; 68 | }; 69 | } 70 | 71 | /** Gets the version of the specified package by looking at the package.json in the given tree. */ 72 | export function getPackageVersionFromPackageJson(tree: Tree, name: string): string | null { 73 | if (!tree.exists('package.json')) { 74 | return null; 75 | } 76 | 77 | // tslint:disable-next-line:no-non-null-assertion 78 | const packageJson = JSON.parse(tree.read('package.json')!.toString('utf8')); 79 | 80 | if (packageJson.dependencies && packageJson.dependencies[name]) { 81 | return packageJson.dependencies[name]; 82 | } 83 | 84 | return null; 85 | } 86 | 87 | export default function (options: any): Rule { 88 | return chain([ 89 | options && options.skipPackageJson ? noop() : addPackageJsonDependencies(), 90 | options && options.skipPackageJson ? noop() : installPackageJsonDependencies(), 91 | options && options.skipModuleImport ? noop() : addModuleToImports(options), 92 | ]); 93 | } 94 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/schematics/ng-add/index_spec.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@angular-devkit/schematics'; 2 | import { SchematicTestRunner } from '@angular-devkit/schematics/testing'; 3 | import * as path from 'path'; 4 | 5 | 6 | const collectionPath = path.join(__dirname, '../collection.json'); 7 | 8 | 9 | describe('schematics', () => { 10 | it('works', async () => { 11 | const runner = new SchematicTestRunner('schematics', collectionPath); 12 | const tree = await runner.runSchematicAsync('schematics', {}, Tree.empty()); 13 | tree.subscribe(tree=>{ 14 | expect(tree.files).toEqual([]); 15 | }); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/animations/index.ts: -------------------------------------------------------------------------------- 1 | import {animate, animateChild, animation, query, stagger, state, style, transition, trigger, useAnimation} from '@angular/animations'; 2 | 3 | const customAnimation = animation( 4 | [ 5 | style({ 6 | opacity: '{{opacity}}', 7 | transform: 'scale({{scale}}) translate3d({{x}}, {{y}}, {{z}})' 8 | }), 9 | animate('{{duration}} {{delay}} cubic-bezier(0.0, 0.0, 0.2, 1)', style('*')) 10 | ], 11 | { 12 | params: { 13 | duration: '200ms', 14 | delay: '0ms', 15 | opacity: '0', 16 | scale: '1', 17 | x: '0', 18 | y: '0', 19 | z: '0' 20 | } 21 | } 22 | ); 23 | 24 | export const InputAnimations = [ 25 | trigger('animate', [transition('void => *', [useAnimation(customAnimation)])]), 26 | 27 | trigger('animateStagger', [ 28 | state('50', style('*')), 29 | state('100', style('*')), 30 | state('200', style('*')), 31 | 32 | transition('void => 50', query('@*', [stagger('50ms', [animateChild()])], {optional: true})), 33 | transition('void => 100', query('@*', [stagger('100ms', [animateChild()])], {optional: true})), 34 | transition('void => 200', query('@*', [stagger('200ms', [animateChild()])], {optional: true})) 35 | ]), 36 | ]; 37 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/component/index.ts: -------------------------------------------------------------------------------- 1 | export * from './mat-google-maps-autocomplete.component'; 2 | export * from './mat-search-google-maps-autocomplete/mat-search-google-maps-autocomplete.component'; 3 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/component/mat-google-maps-autocomplete.component.html: -------------------------------------------------------------------------------- 1 | 2 | {{addressLabelText}} 3 | 11 | 12 | {{requiredErrorText}} 13 | 14 | 15 | {{invalidErrorText}} 16 | 17 | 18 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/component/mat-google-maps-autocomplete.component.scss: -------------------------------------------------------------------------------- 1 | .full-width { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/component/mat-google-maps-autocomplete.component.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Component, 3 | ElementRef, 4 | EventEmitter, 5 | forwardRef, 6 | Inject, 7 | Input, 8 | NgZone, 9 | OnDestroy, 10 | OnInit, 11 | Output, 12 | ViewChild 13 | } from '@angular/core'; 14 | import {ControlValueAccessor, NG_VALUE_ACCESSOR, UntypedFormControl, Validators} from '@angular/forms'; 15 | import {MatValidateAddressDirective} from '../directives/address-validator/mat-address-validator.directive'; 16 | import {Location} from '../interfaces/location.interface'; 17 | import {GermanAddress} from '../interfaces'; 18 | import {ScriptLoaderService} from "../services/script-loader.service"; 19 | import {ApiKeyToken} from "../tokens"; 20 | import PlaceResult = google.maps.places.PlaceResult; 21 | import AutocompleteOptions = google.maps.places.AutocompleteOptions; 22 | 23 | export enum Appearance { 24 | STANDARD = 'standard', 25 | FILL = 'fill', 26 | OUTLINE = 'outline', 27 | LEGACY = 'legacy', 28 | } 29 | 30 | @Component({ 31 | selector: 'mat-google-maps-autocomplete', 32 | exportAs: 'matGoogleMapsAutocomplete', 33 | templateUrl: './mat-google-maps-autocomplete.component.html', 34 | styleUrls: ['./mat-google-maps-autocomplete.component.scss'], 35 | providers: [ 36 | { 37 | provide: NG_VALUE_ACCESSOR, 38 | useExisting: forwardRef(() => MatGoogleMapsAutocompleteComponent), 39 | multi: true 40 | } 41 | ] 42 | }) 43 | export class MatGoogleMapsAutocompleteComponent implements OnInit, OnDestroy, ControlValueAccessor { 44 | 45 | autocomplete: google.maps.places.Autocomplete | undefined; 46 | 47 | @ViewChild('search') 48 | public searchElementRef: ElementRef; 49 | 50 | @Input() 51 | addressLabelText = 'Address'; 52 | 53 | @Input() 54 | placeholderText = 'Please enter the address'; 55 | 56 | @Input() 57 | requiredErrorText = 'The address is required'; 58 | 59 | @Input() 60 | invalidErrorText = 'The address is not valid'; 61 | 62 | @Input() 63 | appearance: string | Appearance = Appearance.STANDARD; 64 | 65 | @Input() 66 | value: PlaceResult; 67 | 68 | @Input() 69 | address: PlaceResult | string; 70 | 71 | @Input() 72 | country: string | string[]; 73 | 74 | @Input() 75 | placeIdOnly?: boolean; 76 | 77 | @Input() 78 | strictBounds?: boolean; 79 | 80 | @Input() 81 | types?: string[]; 82 | // types: string[] = ['address']; 83 | 84 | @Input() 85 | type?: string; 86 | 87 | @Input() 88 | autoCompleteOptions: AutocompleteOptions = {}; 89 | 90 | @Output() 91 | onChange: EventEmitter = new EventEmitter(); 92 | 93 | @Output() 94 | onAutocompleteSelected: EventEmitter = new EventEmitter(); 95 | 96 | @Output() 97 | onGermanAddressMapped: EventEmitter = new EventEmitter(); 98 | 99 | @Output() 100 | onLocationSelected: EventEmitter = new EventEmitter(); 101 | 102 | 103 | private onNewPlaceResult: EventEmitter = new EventEmitter(); 104 | private addressValidator: MatValidateAddressDirective = new MatValidateAddressDirective(); 105 | 106 | public addressSearchControl: UntypedFormControl = new UntypedFormControl({value: null}, Validators.compose([ 107 | Validators.required, 108 | this.addressValidator.validate()]) 109 | ); 110 | 111 | propagateChange = (_: any) => { 112 | }; 113 | 114 | constructor(private ngZone: NgZone, 115 | @Inject(ApiKeyToken) 116 | public apiKey: string, 117 | private loaderService: ScriptLoaderService,) { 118 | } 119 | 120 | ngOnInit(): void { 121 | this.addressValidator.subscribe(this.onNewPlaceResult); 122 | 123 | const options: AutocompleteOptions = { 124 | // types: ['address'], 125 | // componentRestrictions: {country: this.country}, 126 | placeIdOnly: this.placeIdOnly, 127 | strictBounds: this.strictBounds, 128 | // types: this.types, 129 | type: this.type 130 | }; 131 | 132 | // tslint:disable-next-line:no-unused-expression 133 | this.country ? options.componentRestrictions = {country: this.country} : null; 134 | // tslint:disable-next-line:no-unused-expression 135 | this.country ? options.types = this.types : null; 136 | 137 | this.autoCompleteOptions = Object.assign(this.autoCompleteOptions, options); 138 | this.initGoogleMapsAutocomplete(); 139 | } 140 | 141 | ngOnDestroy(): void { 142 | if (this.autocomplete) { 143 | google.maps.event.clearInstanceListeners(this.autocomplete); 144 | } 145 | } 146 | 147 | public initGoogleMapsAutocomplete() { 148 | this.loaderService 149 | .loadScript(`https://maps.googleapis.com/maps/api/js?key=${this.apiKey}&libraries=places`) 150 | .then(() => { 151 | this.autocomplete = new google.maps.places.Autocomplete(this.searchElementRef.nativeElement, this.autoCompleteOptions); 152 | this.autocomplete.addListener('place_changed', () => { 153 | this.ngZone.run(() => { 154 | // get the place result 155 | const place: PlaceResult = this.autocomplete.getPlace(); 156 | 157 | const germanAddress: GermanAddress = { 158 | gmID: place.id, 159 | icon: place.icon, 160 | url: place.url, 161 | placeID: place.place_id, 162 | displayAddress: place.formatted_address, 163 | name: place.name, 164 | vicinity: place.vicinity, 165 | locality: {}, 166 | state: {}, 167 | country: {}, 168 | geoLocation: {latitude: -1, longitude: -1}, 169 | }; 170 | 171 | if (place.geometry && place.geometry.location) { 172 | germanAddress.geoLocation.latitude = place.geometry.location.lat(); 173 | germanAddress.geoLocation.longitude = place.geometry.location.lng(); 174 | } 175 | 176 | if (place.address_components) { 177 | // console.log("place.address_components --> ", place.address_components); 178 | place.address_components.forEach(value => { 179 | if (value.types.indexOf('street_number') > -1) { 180 | germanAddress.streetNumber = value.short_name; 181 | } 182 | if (value.types.indexOf('route') > -1) { 183 | germanAddress.streetName = value.long_name; 184 | } 185 | if (value.types.indexOf('postal_code') > -1) { 186 | germanAddress.postalCode = value.short_name; 187 | } 188 | if (value.types.indexOf('sublocality') > -1) { 189 | germanAddress.sublocality = value.long_name; 190 | } 191 | if (value.types.indexOf('locality') > -1) { 192 | germanAddress.locality.long = value.long_name; 193 | germanAddress.locality.short = value.short_name; 194 | } 195 | if (value.types.indexOf('administrative_area_level_1') > -1) { 196 | germanAddress.state.long = value.long_name; 197 | germanAddress.state.short = value.short_name; 198 | } 199 | if (value.types.indexOf('country') > -1) { 200 | germanAddress.country.long = value.long_name; 201 | germanAddress.country.short = value.short_name; 202 | } 203 | if (value.types.indexOf('administrative_area_level_3') > -1) { 204 | germanAddress.locality.short = value.short_name; 205 | } 206 | }); 207 | } 208 | 209 | this.onGermanAddressMapped.emit(germanAddress); 210 | 211 | if (!place.place_id || place.geometry === undefined || place.geometry === null) { 212 | // place result is not valid 213 | return; 214 | } else { 215 | // show dialog to select a address from the input 216 | // emit failed event 217 | this.value = place; 218 | this.propagateChange(this.value) 219 | } 220 | this.address = place.formatted_address; 221 | this.onAutocompleteSelected.emit(place); 222 | this.onLocationSelected.emit( 223 | { 224 | latitude: place.geometry.location.lat(), 225 | longitude: place.geometry.location.lng() 226 | }); 227 | }); 228 | }); 229 | }) 230 | .catch((err) => console.log(err)); 231 | } 232 | 233 | public onQuery(event: any) { 234 | this.onChange.emit(this.address); 235 | } 236 | 237 | private resetAddress() { 238 | this.address = null; 239 | this.addressSearchControl.updateValueAndValidity(); 240 | } 241 | 242 | writeValue(obj: any): void { 243 | if (obj) { 244 | this.value = obj; 245 | } 246 | } 247 | 248 | registerOnChange(fn: any): void { 249 | this.propagateChange = fn; 250 | } 251 | 252 | registerOnTouched(fn: any): void { 253 | throw new Error('Method not implemented.'); 254 | } 255 | 256 | setDisabledState?(isDisabled: boolean): void { 257 | throw new Error('Method not implemented.'); 258 | } 259 | 260 | } 261 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/component/mat-search-google-maps-autocomplete/mat-search-google-maps-autocomplete.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 5 | {{searchAddressLabel}} 6 | 17 | search 18 | 19 | 20 |
21 | 22 |
23 |
24 | 27 | {{streetNameLabel}} 28 | 34 | 35 | 36 | 37 | 38 | {{streetNumberLabel}} 39 | 45 | 46 | 47 | 48 |
49 |
50 | 51 | {{postalCodeLabel}} 52 | 59 | 60 | 61 | 62 | 65 | {{vicinityLabel}} 66 | 71 | 72 |
73 | 74 | {{localityLabel}} 75 | 81 | add_location 82 | 83 | 84 |
85 |
86 |
87 |
88 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/component/mat-search-google-maps-autocomplete/mat-search-google-maps-autocomplete.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/projects/angular-material-extensions/google-maps-autocomplete/src/lib/component/mat-search-google-maps-autocomplete/mat-search-google-maps-autocomplete.component.scss -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/component/mat-search-google-maps-autocomplete/mat-search-google-maps-autocomplete.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; 2 | 3 | import { MatSearchGoogleMapsAutocompleteComponent } from './mat-search-google-maps-autocomplete.component'; 4 | 5 | describe('MatSearchGoogleMapsAutocompleteComponent', () => { 6 | let component: MatSearchGoogleMapsAutocompleteComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(waitForAsync(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ MatSearchGoogleMapsAutocompleteComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(MatSearchGoogleMapsAutocompleteComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/component/mat-search-google-maps-autocomplete/mat-search-google-maps-autocomplete.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, EventEmitter, forwardRef, Input, OnInit, Output} from '@angular/core'; 2 | import { 3 | ControlValueAccessor, 4 | NG_VALUE_ACCESSOR, 5 | UntypedFormBuilder, 6 | UntypedFormGroup, 7 | Validators 8 | } from '@angular/forms'; 9 | 10 | import {parseGermanAddress} from '../../helpers/parser'; 11 | import {GermanAddress} from '../../interfaces'; 12 | import {Appearance} from '../mat-google-maps-autocomplete.component'; 13 | import {InputAnimations} from '../../animations'; 14 | import {debounceTime, distinctUntilChanged, takeUntil} from 'rxjs/operators'; 15 | import {Subject} from 'rxjs'; 16 | 17 | @Component({ 18 | selector: 'mat-search-google-maps-autocomplete', 19 | templateUrl: './mat-search-google-maps-autocomplete.component.html', 20 | styleUrls: ['./mat-search-google-maps-autocomplete.component.scss'], 21 | animations: InputAnimations, 22 | providers: [ 23 | { 24 | provide: NG_VALUE_ACCESSOR, 25 | useExisting: forwardRef(() => MatSearchGoogleMapsAutocompleteComponent), 26 | multi: true 27 | } 28 | ] 29 | }) 30 | export class MatSearchGoogleMapsAutocompleteComponent implements OnInit, ControlValueAccessor { 31 | 32 | constructor(private formBuilder: UntypedFormBuilder) { 33 | // Set the private defaults 34 | this._unsubscribeAll = new Subject(); 35 | } 36 | 37 | @Input() 38 | searchBarAppearance: string | Appearance; 39 | 40 | @Input() 41 | appearance: string | Appearance = Appearance.STANDARD; 42 | 43 | @Input() 44 | searchAddressLabel = 'Search Address'; 45 | 46 | @Input() 47 | streetNameLabel = 'Street'; 48 | 49 | @Input() 50 | streetNumberLabel = 'Nr.'; 51 | 52 | @Input() 53 | postalCodeLabel = 'PLZ'; 54 | 55 | @Input() 56 | localityLabel = 'Locality'; 57 | 58 | @Input() 59 | vicinityLabel = 'Vicinity'; 60 | 61 | @Input() 62 | showVicinity: boolean; 63 | 64 | @Input() 65 | country: string | string[]; 66 | 67 | @Input() 68 | placeIdOnly?: boolean; 69 | 70 | @Input() 71 | strictBounds?: boolean; 72 | 73 | @Input() 74 | types?: string[]; 75 | // types: string[] = ['address']; 76 | 77 | @Input() 78 | type?: string; 79 | 80 | @Input() 81 | readonly: boolean; 82 | 83 | @Input() 84 | disableSearch: boolean; 85 | 86 | @Input() private _value: GermanAddress; 87 | 88 | @Output() 89 | onGermanAddressMapped: EventEmitter = new EventEmitter(); 90 | 91 | germanAddress: GermanAddress; 92 | addressFormGroup: UntypedFormGroup; 93 | 94 | firstInit = true; 95 | 96 | // Private 97 | private _unsubscribeAll: Subject; 98 | 99 | propagateChange = (_: any) => { 100 | }; 101 | 102 | 103 | get value(): GermanAddress { 104 | return this._value; 105 | } 106 | 107 | @Input() 108 | set value(value: GermanAddress) { 109 | this._value = value; 110 | this.propagateChange(this.value); 111 | } 112 | 113 | ngOnInit() { 114 | this.createAddressFormGroup(); 115 | this.enableCustomInput(); 116 | } 117 | 118 | createAddressFormGroup(): void { 119 | this.addressFormGroup = this.formBuilder.group({ 120 | streetName: [this.value && this.value.streetName ? this.value.streetName : null, Validators.required], 121 | streetNumber: [this.value && this.value.streetNumber ? this.value.streetNumber : null, Validators.required], 122 | postalCode: [this.value && this.value.postalCode ? this.value.postalCode : null, Validators.required], 123 | vicinity: [this.value && this.value.vicinity ? this.value.vicinity : null], 124 | locality: this.formBuilder.group({ 125 | long: [this.value && this.value.locality && this.value.locality.long ? this.value.locality.long : null, Validators.required], 126 | }), 127 | }); 128 | } 129 | 130 | enableCustomInput() { 131 | this.addressFormGroup 132 | .get('streetName') 133 | .valueChanges 134 | .pipe(distinctUntilChanged(), debounceTime(400), takeUntil(this._unsubscribeAll)) 135 | .subscribe(streetName => { 136 | !this.value ? this.value = {streetName} : this.value.streetName = streetName; 137 | this.value.displayAddress = this.parseDisplayAddress(); 138 | this.propagateChange(this.value); 139 | }); 140 | this.addressFormGroup 141 | .get('streetNumber') 142 | .valueChanges 143 | .pipe(distinctUntilChanged(), debounceTime(400), takeUntil(this._unsubscribeAll)) 144 | .subscribe(streetNumber => { 145 | !this.value ? this.value = {streetNumber} : this.value.streetNumber = streetNumber; 146 | this.value.displayAddress = this.parseDisplayAddress(); 147 | this.propagateChange(this.value); 148 | }); 149 | this.addressFormGroup 150 | .get('postalCode') 151 | .valueChanges 152 | .pipe(distinctUntilChanged(), debounceTime(400), takeUntil(this._unsubscribeAll)) 153 | .subscribe(postalCode => { 154 | !this.value ? this.value = {postalCode} : this.value.postalCode = postalCode; 155 | this.value.displayAddress = this.parseDisplayAddress(); 156 | this.propagateChange(this.value); 157 | }); 158 | this.addressFormGroup 159 | .get('vicinity') 160 | .valueChanges 161 | .pipe(distinctUntilChanged(), debounceTime(400), takeUntil(this._unsubscribeAll)) 162 | .subscribe(vicinity => { 163 | !this.value ? this.value = {vicinity} : this.value.vicinity = vicinity; 164 | this.value.displayAddress = this.parseDisplayAddress(); 165 | this.propagateChange(this.value); 166 | }); 167 | this.addressFormGroup 168 | .get('locality') 169 | .valueChanges 170 | .pipe(distinctUntilChanged(), debounceTime(400), takeUntil(this._unsubscribeAll)) 171 | .subscribe(locality => { 172 | !this.value ? this.value = {locality} : this.value.locality = locality; 173 | this.value.displayAddress = this.parseDisplayAddress(); 174 | this.propagateChange(this.value); 175 | }); 176 | } 177 | 178 | parseDisplayAddress() { 179 | return `${this.value?.streetName ? this.value?.streetName : ''} ${this.value?.streetNumber ? this.value?.streetNumber : ''}${this.value?.postalCode || this.value?.locality?.long ? ', ' : ''}${this.value?.postalCode ? this.value?.postalCode : ''} ${this.value?.locality?.long ? this.value?.locality?.long : ''}` 180 | } 181 | 182 | syncAutoComplete($event: google.maps.places.PlaceResult) { 183 | if (this.germanAddress) { 184 | this.addressFormGroup.reset(); 185 | } 186 | const germanAddress: GermanAddress = parseGermanAddress($event); 187 | this.germanAddress = germanAddress; 188 | if (germanAddress.vicinity) { 189 | this.addressFormGroup.get('vicinity').patchValue(germanAddress.vicinity, {emitEvent: false, onlySelf: true}); 190 | } 191 | if (germanAddress.streetName) { 192 | this.addressFormGroup.get('streetName').patchValue(germanAddress.streetName, {emitEvent: false, onlySelf: true}); 193 | } 194 | if (germanAddress.streetNumber) { 195 | this.addressFormGroup.get('streetNumber').patchValue(germanAddress.streetNumber.toString(), { 196 | emitEvent: false, 197 | onlySelf: true 198 | }); 199 | } 200 | if (germanAddress.postalCode) { 201 | this.addressFormGroup.get('postalCode').patchValue(germanAddress.postalCode, {emitEvent: false, onlySelf: true}); 202 | } 203 | if (germanAddress.locality && germanAddress.locality.long) { 204 | this.addressFormGroup.get('locality.long').patchValue(germanAddress.locality.long, { 205 | emitEvent: false, 206 | onlySelf: true 207 | }); 208 | } 209 | 210 | this.value = germanAddress; 211 | this.onGermanAddressMapped.emit(germanAddress); 212 | } 213 | 214 | writeValue(obj: any): void { 215 | let shouldRecreateFG = false; 216 | if (obj) { 217 | if (!this.value && this.firstInit) { 218 | shouldRecreateFG = true; 219 | } 220 | this.value = obj; 221 | if (shouldRecreateFG) { 222 | this.createAddressFormGroup(); 223 | this.firstInit = false; 224 | } 225 | } 226 | } 227 | 228 | registerOnChange(fn: any): void { 229 | this.propagateChange = fn; 230 | } 231 | 232 | registerOnTouched(fn: any): void { 233 | } 234 | 235 | setDisabledState(isDisabled: boolean): void { 236 | } 237 | 238 | } 239 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/directives/address-validator/mat-address-validator.directive.spec.ts: -------------------------------------------------------------------------------- 1 | import {MatValidateAddressDirective} from './mat-address-validator.directive'; 2 | 3 | describe('AddressValidator', () => { 4 | it('should create an instance', () => { 5 | const directive = new MatValidateAddressDirective(); 6 | expect(directive).toBeTruthy(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/directives/address-validator/mat-address-validator.directive.ts: -------------------------------------------------------------------------------- 1 | import {Directive, EventEmitter, forwardRef} from '@angular/core'; 2 | import {AbstractControl, NG_VALIDATORS, ValidationErrors, Validator, ValidatorFn} from '@angular/forms'; 3 | import PlaceResult = google.maps.places.PlaceResult; 4 | 5 | // https://github.com/angular/angular/blob/master/packages/forms/src/directives/validators.ts 6 | 7 | @Directive({ 8 | selector: '[mat-address-validate][formControlName],[MatValidateAddress][formControl],[MatValidateAddress][ngModel]', 9 | providers: [ 10 | {provide: NG_VALIDATORS, useExisting: forwardRef(() => MatValidateAddressDirective), multi: true} 11 | ] 12 | }) 13 | export class MatValidateAddressDirective implements Validator { 14 | 15 | public subscription: any; 16 | 17 | private _address: PlaceResult; 18 | 19 | 20 | constructor() { 21 | } 22 | 23 | public validate(): ValidatorFn { 24 | return (control: AbstractControl): ValidationErrors | any => { 25 | return this.address ? null : { 26 | validateAddress: { 27 | valid: false 28 | } 29 | }; 30 | } 31 | } 32 | 33 | public subscribe(eventEmitter: EventEmitter) { 34 | this.subscription = eventEmitter.subscribe((address: PlaceResult) => { 35 | this.address = address; 36 | }); 37 | } 38 | 39 | public unsubscribe() { 40 | this.subscription.unsubscribe(); 41 | } 42 | 43 | get address() { 44 | return this._address; 45 | } 46 | 47 | set address(value) { 48 | this._address = value; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/directives/mat-google-maps-autocomplete.directive.spec.ts: -------------------------------------------------------------------------------- 1 | import {MatGoogleMapsAutocompleteDirective} from './mat-google-maps-autocomplete.directive'; 2 | import { TestBed, waitForAsync } from '@angular/core/testing'; 3 | import {Component, DebugElement, ElementRef, NgZone, PLATFORM_ID} from '@angular/core'; 4 | import {MapsAPILoader} from '@agm/core'; 5 | import {MockNgZone} from '../testing/mock-ng-zone'; 6 | import {environment} from '../../../../../../src/environments/environment'; 7 | 8 | @Component({ 9 | template: `` 10 | }) 11 | class TestGoogleMapsAutoCompleteComponent { 12 | } 13 | 14 | describe('MatGoogleMapsAutocompleteDirective', () => { 15 | 16 | let directive: MatGoogleMapsAutocompleteDirective; 17 | let inputEl: DebugElement; 18 | 19 | const elementRefPartial: Partial = {}; 20 | const mapsAPILoaderPartial: Partial = {}; 21 | const ngZonePartial: Partial = {run: (fn: Function) => fn()}; 22 | 23 | // spyOn(ngZonePartial, 'run').and.callFake((fn: Function) => fn()); 24 | 25 | const googleMapsParams = { 26 | apiKey: environment.GOOGLE_MAPS_API_KEY, 27 | libraries: ['places'], 28 | language: 'en', 29 | // region: 'DE' 30 | }; 31 | 32 | beforeEach(waitForAsync(() => { 33 | 34 | TestBed.configureTestingModule({ 35 | // imports: [AgmCoreModule.forRoot(googleMapsParams)], 36 | declarations: [], 37 | providers: [ 38 | {provide: ElementRef, useValue: elementRefPartial}, 39 | {provide: MapsAPILoader, useValue: mapsAPILoaderPartial}, 40 | {provide: NgZone, useClass: MockNgZone}, 41 | ] 42 | }).compileComponents(); 43 | })); 44 | 45 | beforeEach(() => { 46 | directive = new MatGoogleMapsAutocompleteDirective( 47 | TestBed.get(PLATFORM_ID), 48 | TestBed.get(ElementRef), 49 | TestBed.get(MapsAPILoader), 50 | TestBed.get(NgZone)); 51 | }); 52 | 53 | it('should create an instance', () => { 54 | expect(directive).toBeTruthy(); 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/directives/mat-google-maps-autocomplete.directive.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AfterViewInit, 3 | ChangeDetectorRef, 4 | Directive, 5 | ElementRef, 6 | EventEmitter, 7 | forwardRef, 8 | HostListener, 9 | Inject, 10 | Input, 11 | NgZone, 12 | OnDestroy, 13 | OnInit, 14 | Output, 15 | PLATFORM_ID, 16 | ViewChild 17 | } from '@angular/core'; 18 | import {ControlValueAccessor, FormControl, NG_VALIDATORS, Validators} from '@angular/forms'; 19 | import {GermanAddress, Location} from '../interfaces'; 20 | import {isPlatformBrowser} from '@angular/common'; 21 | import {ScriptLoaderService} from "../services/script-loader.service"; 22 | import {ApiKeyToken} from "../tokens"; 23 | import PlaceResult = google.maps.places.PlaceResult; 24 | import AutocompleteOptions = google.maps.places.AutocompleteOptions; 25 | 26 | @Directive({ 27 | selector: '[matGoogleMapsAutocomplete]', 28 | exportAs: 'matGoogleMapsAutocomplete', 29 | providers: [ 30 | { 31 | provide: NG_VALIDATORS, 32 | useExisting: forwardRef(() => MatGoogleMapsAutocompleteDirective), 33 | multi: true 34 | } 35 | ] 36 | }) 37 | export class MatGoogleMapsAutocompleteDirective implements OnInit, AfterViewInit, OnDestroy, ControlValueAccessor { 38 | 39 | @ViewChild('inputField') 40 | inputField!: ElementRef; 41 | 42 | autocomplete: google.maps.places.Autocomplete | undefined; 43 | 44 | @Input() 45 | address: PlaceResult | string; 46 | 47 | @Input() 48 | country: string | string[]; 49 | 50 | @Input() 51 | placeIdOnly?: boolean; 52 | 53 | @Input() 54 | strictBounds?: boolean; 55 | 56 | @Input() 57 | types?: string[]; 58 | 59 | @Input() 60 | type?: string; 61 | 62 | @Input() 63 | autoCompleteOptions: AutocompleteOptions = {}; 64 | 65 | @Output() 66 | onChange: EventEmitter = new EventEmitter(); 67 | 68 | @Output() 69 | onAutocompleteSelected: EventEmitter = new EventEmitter(); 70 | 71 | @Output() 72 | onGermanAddressMapped: EventEmitter = new EventEmitter(); 73 | 74 | @Output() 75 | onLocationSelected: EventEmitter = new EventEmitter(); 76 | 77 | disabled: boolean 78 | 79 | _value: string; 80 | 81 | get value(): string { 82 | return this._value; 83 | } 84 | 85 | @Input() 86 | set value(value: string) { 87 | this._value = value; 88 | this.propagateChange(this.value); 89 | this.cf.markForCheck(); 90 | } 91 | 92 | private onNewPlaceResult: EventEmitter = new EventEmitter(); 93 | 94 | propagateChange = (_: any) => { 95 | }; 96 | 97 | constructor(@Inject(PLATFORM_ID) public platformId: string, 98 | @Inject(ApiKeyToken) 99 | public apiKey: string, 100 | public elemRef: ElementRef, 101 | private cf: ChangeDetectorRef, 102 | private loaderService: ScriptLoaderService, 103 | private ngZone: NgZone) { 104 | } 105 | 106 | ngOnDestroy(): void { 107 | if (this.autocomplete) { 108 | google.maps.event.clearInstanceListeners(this.autocomplete); 109 | } 110 | } 111 | 112 | ngAfterViewInit(): void { 113 | this.loadMap(); 114 | } 115 | 116 | ngOnInit(): void { 117 | } 118 | 119 | validate(fc: FormControl) { 120 | return fc.hasValidator(Validators.required) ? !!fc?.value : true; 121 | } 122 | 123 | @HostListener('change') 124 | onChangeInputValue(): void { 125 | const value = (this.elemRef.nativeElement as HTMLInputElement)?.value; 126 | this.value = value; 127 | } 128 | 129 | public initGoogleMapsAutocomplete() { 130 | const autocomplete = new google.maps.places.Autocomplete(this.elemRef.nativeElement, this.autoCompleteOptions); 131 | autocomplete.addListener('place_changed', () => { 132 | this.ngZone.run(() => { 133 | // get the place result 134 | const place: PlaceResult = autocomplete.getPlace(); 135 | 136 | const germanAddress: GermanAddress = { 137 | gmID: place.id, 138 | icon: place.icon, 139 | url: place.url, 140 | placeID: place.place_id, 141 | displayAddress: place.formatted_address, 142 | name: place.name, 143 | vicinity: place.vicinity, 144 | locality: {}, 145 | state: {}, 146 | country: {}, 147 | geoLocation: {latitude: -1, longitude: -1}, 148 | }; 149 | 150 | if (place.geometry && place.geometry.location) { 151 | germanAddress.geoLocation.latitude = place.geometry.location.lat(); 152 | germanAddress.geoLocation.longitude = place.geometry.location.lng(); 153 | } 154 | 155 | // console.log("place.address_components --> ", place.address_components); 156 | place.address_components.forEach(value => { 157 | if (value.types.indexOf('street_number') > -1) { 158 | germanAddress.streetNumber = value.short_name; 159 | } 160 | if (value.types.indexOf('route') > -1) { 161 | germanAddress.streetName = value.long_name; 162 | } 163 | if (value.types.indexOf('postal_code') > -1) { 164 | germanAddress.postalCode = value.short_name; 165 | } 166 | if (value.types.indexOf('sublocality') > -1) { 167 | germanAddress.sublocality = value.long_name; 168 | } 169 | if (value.types.indexOf('locality') > -1) { 170 | germanAddress.locality.long = value.long_name; 171 | germanAddress.locality.short = value.short_name; 172 | } 173 | if (value.types.indexOf('administrative_area_level_1') > -1) { 174 | germanAddress.state.long = value.long_name; 175 | germanAddress.state.short = value.short_name; 176 | } 177 | if (value.types.indexOf('country') > -1) { 178 | germanAddress.country.long = value.long_name; 179 | germanAddress.country.short = value.short_name; 180 | } 181 | if (value.types.indexOf('administrative_area_level_3') > -1) { 182 | germanAddress.locality.short = value.short_name; 183 | } 184 | }); 185 | 186 | this.onGermanAddressMapped.emit(germanAddress); 187 | 188 | this.value = place.formatted_address; 189 | this.address = place.formatted_address; 190 | this.onAutocompleteSelected.emit(place); 191 | this.onLocationSelected.emit( 192 | { 193 | latitude: place.geometry.location.lat(), 194 | longitude: place.geometry.location.lng() 195 | }); 196 | }); 197 | }); 198 | } 199 | 200 | registerOnChange(fn: any): void { 201 | this.propagateChange = fn; 202 | } 203 | 204 | registerOnTouched(fn: any): void { 205 | } 206 | 207 | setDisabledState(isDisabled: boolean): void { 208 | this.disabled = isDisabled; 209 | } 210 | 211 | writeValue(obj: any): void { 212 | if (obj) { 213 | this.value = obj; 214 | } 215 | } 216 | 217 | loadMap(): void { 218 | this.loaderService.loadScript(`https://maps.googleapis.com/maps/api/js?key=${this.apiKey}&libraries=places`) 219 | .then(() => { 220 | this.initMap(); 221 | }) 222 | .catch(error => console.error('Google Maps loading failed: ', error)); 223 | } 224 | 225 | initMap() { 226 | if (isPlatformBrowser(this.platformId)) { 227 | 228 | console.log("on after view init --> ", this.elemRef.nativeElement) 229 | 230 | this.autocomplete = new google.maps.places.Autocomplete( 231 | this.elemRef.nativeElement 232 | ); 233 | 234 | const options: AutocompleteOptions = { 235 | // types: ['address'], 236 | // componentRestrictions: {country: this.country}, 237 | placeIdOnly: this.placeIdOnly, 238 | strictBounds: this.strictBounds, 239 | // types: this.types, 240 | type: this.type 241 | }; 242 | 243 | // tslint:disable-next-line:no-unused-expression 244 | this.country ? options.componentRestrictions = {country: this.country} : null; 245 | // tslint:disable-next-line:no-unused-expression 246 | this.country ? options.types = this.types : null; 247 | 248 | this.autoCompleteOptions = Object.assign(this.autoCompleteOptions, options); 249 | this.initGoogleMapsAutocomplete(); 250 | } 251 | } 252 | 253 | } 254 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/helpers/parser.ts: -------------------------------------------------------------------------------- 1 | import PlaceResult = google.maps.places.PlaceResult; 2 | import {GermanAddress} from '../interfaces'; 3 | 4 | export function parseGermanAddress(placeResult: PlaceResult): GermanAddress { 5 | const germanAddress: GermanAddress = { 6 | gmID: placeResult.id, 7 | icon: placeResult.icon, 8 | url: placeResult.url, 9 | placeID: placeResult.place_id, 10 | displayAddress: placeResult.formatted_address, 11 | name: placeResult.name, 12 | vicinity: placeResult.vicinity, 13 | locality: {}, 14 | state: {}, 15 | country: {}, 16 | geoLocation: {latitude: -1, longitude: -1}, 17 | }; 18 | 19 | if (placeResult.geometry && placeResult.geometry.location) { 20 | germanAddress.geoLocation.latitude = placeResult.geometry.location.lat(); 21 | germanAddress.geoLocation.longitude = placeResult.geometry.location.lng(); 22 | } 23 | 24 | if (placeResult.address_components && placeResult.address_components.length > 0) { 25 | placeResult.address_components.forEach(value => { 26 | if (value.types.indexOf('street_number') > -1) { 27 | germanAddress.streetNumber = value.short_name; 28 | } 29 | if (value.types.indexOf('route') > -1) { 30 | germanAddress.streetName = value.long_name; 31 | } 32 | if (value.types.indexOf('postal_code') > -1) { 33 | germanAddress.postalCode = value.short_name; 34 | } 35 | if (value.types.indexOf('sublocality') > -1) { 36 | germanAddress.sublocality = value.long_name; 37 | } 38 | if (value.types.indexOf('locality') > -1) { 39 | germanAddress.locality.long = value.long_name; 40 | germanAddress.locality.short = value.short_name; 41 | } 42 | if (value.types.indexOf('administrative_area_level_1') > -1) { 43 | germanAddress.state.long = value.long_name; 44 | germanAddress.state.short = value.short_name; 45 | } 46 | if (value.types.indexOf('country') > -1) { 47 | germanAddress.country.long = value.long_name; 48 | germanAddress.country.short = value.short_name; 49 | } 50 | if (value.types.indexOf('administrative_area_level_3') > -1) { 51 | germanAddress.locality.short = value.short_name; 52 | } 53 | }); 54 | } 55 | return germanAddress; 56 | } 57 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/interfaces/germand.address.interface.ts: -------------------------------------------------------------------------------- 1 | import {Location} from './location.interface'; 2 | 3 | /** 4 | * @author Anthony Nahas 5 | * @since 23.12.19 6 | * @version 1.0 7 | */ 8 | export interface GermanAddress { 9 | id?: string; 10 | gmID?: string; 11 | placeID?: string; 12 | name?: string; 13 | icon?: string; 14 | displayAddress?: string; 15 | postalCode?: string; 16 | streetNumber?: string; 17 | streetName?: string; 18 | sublocality?: string; 19 | locality?: { 20 | short?: string; 21 | long?: string; 22 | }; 23 | state?: { 24 | short?: string; 25 | long?: string; 26 | }; 27 | country?: { 28 | short?: string; 29 | long?: string; 30 | }; 31 | vicinity?: string; 32 | url?: string; 33 | geoLocation?: Location; 34 | } 35 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/interfaces/index.ts: -------------------------------------------------------------------------------- 1 | export * from './germand.address.interface'; 2 | export * from './location.interface'; 3 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/interfaces/location.interface.ts: -------------------------------------------------------------------------------- 1 | export interface Location { 2 | latitude: number; 3 | longitude: number; 4 | } 5 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/mat-google-maps-autocomplete.module.ts: -------------------------------------------------------------------------------- 1 | import {CommonModule} from '@angular/common'; 2 | import {ModuleWithProviders, NgModule} from '@angular/core'; 3 | import {FlexLayoutModule} from '@angular/flex-layout'; 4 | import {FormsModule, ReactiveFormsModule} from '@angular/forms'; 5 | import {MatIconModule} from '@angular/material/icon'; 6 | import {MatGoogleMapsAutocompleteDirective} from './directives/mat-google-maps-autocomplete.directive'; 7 | import {MatValidateAddressDirective} from './directives/address-validator/mat-address-validator.directive'; 8 | // tslint:disable-next-line:max-line-length 9 | import {MatGoogleMapsAutocompleteComponent, MatSearchGoogleMapsAutocompleteComponent} from './component'; 10 | import {MatInputModule} from '@angular/material/input'; 11 | import {ApiKeyToken} from "./tokens"; 12 | import {ScriptLoaderService} from "./services/script-loader.service"; 13 | 14 | 15 | @NgModule({ 16 | imports: 17 | [ 18 | CommonModule, 19 | FormsModule, 20 | ReactiveFormsModule, 21 | FlexLayoutModule, 22 | MatInputModule, 23 | MatIconModule 24 | ], 25 | exports: [ 26 | MatGoogleMapsAutocompleteComponent, 27 | MatGoogleMapsAutocompleteDirective, 28 | MatValidateAddressDirective, 29 | MatSearchGoogleMapsAutocompleteComponent, 30 | ], 31 | declarations: [ 32 | MatGoogleMapsAutocompleteComponent, 33 | MatGoogleMapsAutocompleteDirective, 34 | MatValidateAddressDirective, 35 | MatSearchGoogleMapsAutocompleteComponent 36 | ], 37 | providers: [ 38 | // { 39 | // provide: NG_VALUE_ACCESSOR, 40 | // useExisting: forwardRef(() => MatGoogleMapsAutocompleteDirective), 41 | // multi: true 42 | // } 43 | ] 44 | }) 45 | export class MatGoogleMapsAutocompleteModule { 46 | 47 | constructor() { 48 | } 49 | 50 | static forRoot( 51 | apiKey: string, 52 | ): ModuleWithProviders { 53 | 54 | return { 55 | ngModule: MatGoogleMapsAutocompleteModule, 56 | providers: 57 | [ 58 | { 59 | provide: ApiKeyToken, 60 | useValue: apiKey 61 | }, 62 | ] 63 | }; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/services/script-loader.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { ScriptLoaderService } from './script-loader.service'; 4 | 5 | describe('ScriptLoaderService', () => { 6 | let service: ScriptLoaderService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(ScriptLoaderService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/services/script-loader.service.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | 3 | @Injectable({ 4 | providedIn: 'root' 5 | }) 6 | export class ScriptLoaderService { 7 | private loadedScripts: { [src: string]: boolean } = {}; 8 | private scriptPromises: { [src: string]: Promise } = {}; // Neu 9 | 10 | loadScript(src: string): Promise { 11 | // Wenn das Skript bereits erfolgreich geladen wurde, sofort auflösen 12 | if (this.loadedScripts[src]) { 13 | return Promise.resolve(); 14 | } 15 | 16 | // Wenn ein Ladevorgang für dieses Skript bereits im Gange ist, das vorhandene Promise zurückgeben 17 | if (this.scriptPromises[src]) { 18 | return this.scriptPromises[src]; 19 | } 20 | 21 | // Ein neues Promise für das Skript-Laden erstellen und speichern 22 | this.scriptPromises[src] = new Promise((resolve, reject) => { 23 | const script = document.createElement('script'); 24 | script.src = src; 25 | script.async = true; // Empfohlen für externe Skripte 26 | script.onload = () => { 27 | this.loadedScripts[src] = true; // Markiere das Skript als geladen 28 | resolve(); 29 | }; 30 | script.onerror = (error: any) => { 31 | this.scriptPromises[src] = null; // Bei Fehler, entferne das Promise, damit erneute Versuche möglich sind 32 | reject(error); 33 | }; 34 | document.body.appendChild(script); 35 | }); 36 | 37 | return this.scriptPromises[src]; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/testing/mock-ng-zone.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright Google LLC All Rights Reserved. 4 | * 5 | * Use of this source code is governed by an MIT-style license that can be 6 | * found in the LICENSE file at https://angular.io/license 7 | */ 8 | 9 | import {EventEmitter, Injectable, NgZone} from '@angular/core'; 10 | 11 | 12 | /** 13 | * Mock synchronous NgZone implementation that can be used 14 | * to flush out `onStable` subscriptions in tests. 15 | * 16 | * via: https://github.com/angular/angular/blob/master/packages/core/testing/src/ng_zone_mock.ts 17 | * @docs-private 18 | */ 19 | @Injectable() 20 | export class MockNgZone extends NgZone { 21 | onStable: EventEmitter = new EventEmitter(false); 22 | 23 | constructor() { 24 | super({enableLongStackTrace: false}); 25 | } 26 | 27 | run(fn: Function): any { 28 | return fn(); 29 | } 30 | 31 | runOutsideAngular(fn: Function): any { 32 | return fn(); 33 | } 34 | 35 | simulateZoneExit(): void { 36 | this.onStable.emit(null); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/lib/tokens/index.ts: -------------------------------------------------------------------------------- 1 | import {InjectionToken} from "@angular/core"; 2 | 3 | export const ApiKeyToken = new InjectionToken('apiKey'); 4 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/public-api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of google-maps-autocomplete 3 | */ 4 | 5 | export * from './lib/helpers/parser'; 6 | export * from './lib/interfaces'; 7 | export * from './lib/tokens'; 8 | export * from './lib/services/script-loader.service'; 9 | export * from './lib/component'; 10 | export * from './lib/directives/mat-google-maps-autocomplete.directive'; 11 | export * from './lib/directives/address-validator/mat-address-validator.directive'; 12 | export * from './lib/mat-google-maps-autocomplete.module'; 13 | 14 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js'; 4 | import 'zone.js/testing'; 5 | import { getTestBed } from '@angular/core/testing'; 6 | import { 7 | BrowserDynamicTestingModule, 8 | platformBrowserDynamicTesting 9 | } from '@angular/platform-browser-dynamic/testing'; 10 | 11 | declare const require: any; 12 | 13 | // First, initialize the Angular testing environment. 14 | getTestBed().initTestEnvironment( 15 | BrowserDynamicTestingModule, 16 | platformBrowserDynamicTesting(), { 17 | teardown: { destroyAfterEach: false } 18 | } 19 | ); 20 | // Then we find all the tests. 21 | const context = require.context('./', true, /\.spec\.ts$/); 22 | // And load the modules. 23 | context.keys().map(context); 24 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../out-tsc/lib", 5 | "target": "es2015", 6 | "declaration": true, 7 | "inlineSources": true, 8 | "types": ["googlemaps"], 9 | "lib": [ 10 | "dom", 11 | "es2018" 12 | ] 13 | }, 14 | "angularCompilerOptions": { 15 | "skipTemplateCodegen": true, 16 | "strictMetadataEmit": true, 17 | "fullTemplateTypeCheck": true, 18 | "strictInjectionParameters": true, 19 | "enableResourceInlining": true 20 | }, 21 | "exclude": [ 22 | "src/test.ts", 23 | "**/*.spec.ts" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "angularCompilerOptions": { 4 | // "enableIvy": true 5 | "compilationMode": "partial" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/tsconfig.schematics.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "tsconfig", 4 | "lib": [ 5 | "es2018", 6 | "dom" 7 | ], 8 | "declaration": true, 9 | "module": "commonjs", 10 | "moduleResolution": "node", 11 | "noEmitOnError": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "noImplicitAny": true, 14 | "noImplicitThis": true, 15 | "noUnusedParameters": true, 16 | "noUnusedLocals": true, 17 | "rootDir": "schematics", 18 | "outDir": "../../../dist/angular-material-extensions/google-maps-autocomplete/schematics", 19 | "skipDefaultLibCheck": true, 20 | "skipLibCheck": true, 21 | "sourceMap": true, 22 | "strictNullChecks": true, 23 | "target": "es6", 24 | "types": [ 25 | "jasmine", 26 | "node" 27 | ] 28 | }, 29 | "include": [ 30 | "schematics/**/*" 31 | ], 32 | "exclude": [ 33 | "schematics/*/files/**/*" 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../out-tsc/spec", 5 | "types": [ 6 | "jasmine", 7 | "node" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /projects/angular-material-extensions/google-maps-autocomplete/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tslint.json", 3 | "rules": { 4 | "directive-selector": [ 5 | true, 6 | "attribute", 7 | "mat", 8 | "camelCase" 9 | ], 10 | "component-selector": [ 11 | true, 12 | "element", 13 | "mat", 14 | "kebab-case" 15 | ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /server.ts: -------------------------------------------------------------------------------- 1 | import 'zone.js/node'; 2 | 3 | import { ngExpressEngine } from '@nguniversal/express-engine'; 4 | import * as express from 'express'; 5 | import { join } from 'path'; 6 | 7 | import { AppServerModule } from './src/main.server'; 8 | import { APP_BASE_HREF } from '@angular/common'; 9 | import { existsSync } from 'fs'; 10 | 11 | // The Express app is exported so that it can be used by serverless Functions. 12 | export function app() { 13 | const server = express(); 14 | const distFolder = join(process.cwd(), 'dist/browser'); 15 | const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index'; 16 | 17 | // Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine) 18 | server.engine('html', ngExpressEngine({ 19 | bootstrap: AppServerModule, 20 | })); 21 | 22 | server.set('view engine', 'html'); 23 | server.set('views', distFolder); 24 | 25 | // Example Express Rest API endpoints 26 | // app.get('/api/**', (req, res) => { }); 27 | // Serve static files from /browser 28 | server.get('*.*', express.static(distFolder, { 29 | maxAge: '1y' 30 | })); 31 | 32 | // All regular routes use the Universal engine 33 | server.get('*', (req, res) => { 34 | res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] }); 35 | }); 36 | 37 | return server; 38 | } 39 | 40 | function run() { 41 | const port = process.env.PORT || 4000; 42 | 43 | // Start up the Node server 44 | const server = app(); 45 | server.listen(port, () => { 46 | console.log(`Node Express server listening on http://localhost:${port}`); 47 | }); 48 | } 49 | 50 | // Webpack will replace 'require' with '__webpack_require__' 51 | // '__non_webpack_require__' is a proxy to Node 'require' 52 | // The below code is to ensure that the server is run only when not requiring the bundle. 53 | declare const __non_webpack_require__: NodeRequire; 54 | const mainModule = __non_webpack_require__.main; 55 | const moduleFilename = mainModule && mainModule.filename || ''; 56 | if (moduleFilename === __filename || moduleFilename.includes('iisnode')) { 57 | run(); 58 | } 59 | 60 | export * from './src/main.server'; 61 | -------------------------------------------------------------------------------- /server.ts.bak: -------------------------------------------------------------------------------- 1 | /** 2 | * *** NOTE ON IMPORTING FROM ANGULAR AND NGUNIVERSAL IN THIS FILE *** 3 | * 4 | * If your application uses third-party dependencies, you'll need to 5 | * either use Webpack or the Angular CLI's `bundleDependencies` feature 6 | * in order to adequately package them for use on the server without a 7 | * node_modules directory. 8 | * 9 | * However, due to the nature of the CLI's `bundleDependencies`, importing 10 | * Angular in this file will create a different instance of Angular than 11 | * the version in the compiled application code. This leads to unavoidable 12 | * conflicts. Therefore, please do not explicitly import from @angular or 13 | * @nguniversal in this file. You can export any needed resources 14 | * from your application's main.server.ts file, as seen below with the 15 | * import for `ngExpressEngine`. 16 | */ 17 | 18 | import 'zone.js/dist/zone-node'; 19 | 20 | import * as express from 'express'; 21 | import {join} from 'path'; 22 | 23 | // Express server 24 | const app = express(); 25 | 26 | const PORT = process.env.PORT || 4000; 27 | const DIST_FOLDER = join(process.cwd(), 'dist/browser'); 28 | 29 | // * NOTE :: leave this as require() since this file is built Dynamically from webpack 30 | const {AppServerModuleNgFactory, LAZY_MODULE_MAP, ngExpressEngine, provideModuleMap} = require('./dist/server/main'); 31 | 32 | // Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine) 33 | app.engine('html', ngExpressEngine({ 34 | bootstrap: AppServerModuleNgFactory, 35 | providers: [ 36 | provideModuleMap(LAZY_MODULE_MAP) 37 | ] 38 | })); 39 | 40 | app.set('view engine', 'html'); 41 | app.set('views', DIST_FOLDER); 42 | 43 | // Example Express Rest API endpoints 44 | // app.get('/api/**', (req, res) => { }); 45 | // Serve static files from /browser 46 | app.get('*.*', express.static(DIST_FOLDER, { 47 | maxAge: '1y' 48 | })); 49 | 50 | // All regular routes use the Universal engine 51 | app.get('*', (req, res) => { 52 | res.render('index', { req }); 53 | }); 54 | 55 | // Start up the Node server 56 | app.listen(PORT, () => { 57 | console.log(`Node Express server listening on http://localhost:${PORT}`); 58 | }); 59 | -------------------------------------------------------------------------------- /src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | agm-map { 2 | height: 400px; 3 | } 4 | 5 | .autocomplete-container { 6 | padding: 1rem 0 1rem 0; 7 | width: 50%; 8 | } 9 | 10 | mat-card { 11 | margin: 1rem; 12 | padding: 1rem; 13 | max-width: 100%; 14 | } 15 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {Appearance, GermanAddress, Location} from '@angular-material-extensions/google-maps-autocomplete'; 3 | import {UntypedFormControl, UntypedFormGroup, Validators} from '@angular/forms'; 4 | import PlaceResult = google.maps.places.PlaceResult; 5 | import {Angulartics2GoogleAnalytics} from 'angulartics2'; 6 | 7 | @Component({ 8 | selector: 'app-root', 9 | templateUrl: './app.component.html', 10 | styleUrls: ['./app.component.scss'] 11 | }) 12 | export class AppComponent implements OnInit { 13 | 14 | title = 'google-maps-autocomplete'; 15 | 16 | addressFC: UntypedFormControl = new UntypedFormControl(null, [Validators.required]); 17 | addressFormGroup: UntypedFormGroup; 18 | 19 | public appearance = Appearance; 20 | public zoom: number; 21 | public latitude: number; 22 | public longitude: number; 23 | public showAsDirective = true; 24 | public showAsComponent = false; 25 | 26 | addressValue: GermanAddress = { 27 | streetNumber: '100', 28 | streetName: 'Your StreetName', 29 | vicinity: 'Your vicinity', 30 | postalCode: '37084', 31 | locality: { 32 | long: 'your locality' 33 | } 34 | }; 35 | 36 | constructor(angulartics2GoogleAnalytics: Angulartics2GoogleAnalytics) { 37 | angulartics2GoogleAnalytics.startTracking(); 38 | } 39 | 40 | private setCurrentPosition() { 41 | if ('geolocation' in navigator) { 42 | navigator.geolocation.getCurrentPosition((position) => { 43 | this.latitude = position.coords.latitude; 44 | this.longitude = position.coords.longitude; 45 | this.zoom = 12; 46 | }); 47 | } 48 | } 49 | 50 | onAutocompleteSelected(result: PlaceResult) { 51 | // console.log('onAddressSelected: ', result); 52 | } 53 | 54 | onLocationSelected(location: Location) { 55 | this.latitude = location.latitude; 56 | this.longitude = location.longitude; 57 | } 58 | 59 | flip() { 60 | this.showAsDirective = !this.showAsDirective; 61 | this.showAsComponent = !this.showAsDirective; 62 | } 63 | 64 | onGermanAddressMapped($event: GermanAddress) { 65 | console.log('onGermanAddressMapped', $event); 66 | console.log('default value --> ', this.addressFC.value) 67 | } 68 | 69 | ngOnInit(): void { 70 | this.addressFormGroup = new UntypedFormGroup({ 71 | address: new UntypedFormControl(this.addressValue), 72 | // address: new FormControl(), 73 | }); 74 | 75 | // this.addressFormGroup 76 | // .get('address') 77 | // .valueChanges 78 | // .subscribe(value => console.log('value changed', value)) 79 | 80 | this.addressFC 81 | .valueChanges 82 | .subscribe(value => console.log('value changed', value)) 83 | 84 | console.log('default value --> ', this.addressFC.value) 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import {BrowserModule} from '@angular/platform-browser'; 2 | import {CUSTOM_ELEMENTS_SCHEMA, NgModule, NO_ERRORS_SCHEMA} from '@angular/core'; 3 | 4 | import {AppComponent} from './app.component'; 5 | import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; 6 | import {HttpClientModule} from '@angular/common/http'; 7 | 8 | import {MatGoogleMapsAutocompleteModule} from '@angular-material-extensions/google-maps-autocomplete'; 9 | import {MatButtonToggleModule} from '@angular/material/button-toggle'; 10 | import {MatExpansionModule} from '@angular/material/expansion'; 11 | import {FlexLayoutModule} from '@angular/flex-layout'; 12 | import {ConfigComponent} from '../config/config.component'; 13 | import {FormsModule, ReactiveFormsModule} from '@angular/forms'; 14 | import {environment} from '../environments/environment'; 15 | import {Angulartics2Module} from 'angulartics2'; 16 | import {MarkdownModule} from 'ngx-markdown'; 17 | import {RouterModule} from '@angular/router'; 18 | import {CommonModule} from '@angular/common'; 19 | import {MatCardModule} from '@angular/material/card'; 20 | import {MatInputModule} from '@angular/material/input'; 21 | import {MatTabsModule} from '@angular/material/tabs'; 22 | import {MatRadioModule} from '@angular/material/radio'; 23 | 24 | const googleMapsParams = { 25 | apiKey: environment.GOOGLE_MAPS_API_KEY, 26 | libraries: ['places'], 27 | language: 'en', 28 | // region: 'DE' 29 | }; 30 | 31 | @NgModule({ 32 | declarations: [ 33 | AppComponent, 34 | ConfigComponent 35 | ], 36 | imports: [ 37 | CommonModule, 38 | BrowserModule.withServerTransition({appId: 'serverApp'}), 39 | BrowserAnimationsModule, 40 | RouterModule.forRoot([], { 41 | initialNavigation: 'enabledBlocking', 42 | // relativeLinkResolution: 'legacy' 43 | }), 44 | Angulartics2Module.forRoot(), 45 | MarkdownModule.forRoot(), 46 | MatGoogleMapsAutocompleteModule.forRoot('YOUR_API_KEY'), 47 | FlexLayoutModule, 48 | FormsModule, 49 | ReactiveFormsModule, 50 | HttpClientModule, 51 | MatButtonToggleModule, 52 | MatCardModule, 53 | MatInputModule, 54 | MatExpansionModule, 55 | MatTabsModule, 56 | MatRadioModule 57 | ], 58 | providers: [], 59 | schemas: [ 60 | CUSTOM_ELEMENTS_SCHEMA, 61 | NO_ERRORS_SCHEMA 62 | ], 63 | bootstrap: [AppComponent] 64 | }) 65 | export class AppModule { 66 | } 67 | -------------------------------------------------------------------------------- /src/app/app.server.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {ServerModule} from '@angular/platform-server'; 3 | 4 | import {AppModule} from './app.module'; 5 | import {AppComponent} from './app.component'; 6 | import {FlexLayoutServerModule} from '@angular/flex-layout/server'; 7 | 8 | @NgModule({ 9 | imports: [ 10 | AppModule, 11 | ServerModule, 12 | FlexLayoutServerModule 13 | ], 14 | bootstrap: [AppComponent], 15 | }) 16 | export class AppServerModule { 17 | } 18 | -------------------------------------------------------------------------------- /src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/src/assets/.gitkeep -------------------------------------------------------------------------------- /src/assets/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/src/assets/android-chrome-192x192.png -------------------------------------------------------------------------------- /src/assets/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/src/assets/android-chrome-512x512.png -------------------------------------------------------------------------------- /src/assets/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/src/assets/apple-touch-icon.png -------------------------------------------------------------------------------- /src/assets/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #00aba9 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/assets/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/src/assets/favicon-16x16.png -------------------------------------------------------------------------------- /src/assets/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/src/assets/favicon-32x32.png -------------------------------------------------------------------------------- /src/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/src/assets/favicon.ico -------------------------------------------------------------------------------- /src/assets/github-circle.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/images/icons/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/src/assets/images/icons/icon-128x128.png -------------------------------------------------------------------------------- /src/assets/images/icons/icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/src/assets/images/icons/icon-144x144.png -------------------------------------------------------------------------------- /src/assets/images/icons/icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/src/assets/images/icons/icon-152x152.png -------------------------------------------------------------------------------- /src/assets/images/icons/icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/src/assets/images/icons/icon-192x192.png -------------------------------------------------------------------------------- /src/assets/images/icons/icon-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/src/assets/images/icons/icon-384x384.png -------------------------------------------------------------------------------- /src/assets/images/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/src/assets/images/icons/icon-512x512.png -------------------------------------------------------------------------------- /src/assets/images/icons/icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/src/assets/images/icons/icon-72x72.png -------------------------------------------------------------------------------- /src/assets/images/icons/icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/src/assets/images/icons/icon-96x96.png -------------------------------------------------------------------------------- /src/assets/library.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /src/assets/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@angular-material-extensions/select-country", 3 | "short_name": "select-country", 4 | "theme_color": "#1976d2", 5 | "background_color": "#2196f3", 6 | "display": "browser", 7 | "Scope": "/", 8 | "start_url": "/https://angular-material-extensions.github.io/select-country/", 9 | "icons": [ 10 | { 11 | "src": "images/icons/icon-72x72.png", 12 | "sizes": "72x72", 13 | "type": "image/png" 14 | }, 15 | { 16 | "src": "images/icons/icon-96x96.png", 17 | "sizes": "96x96", 18 | "type": "image/png" 19 | }, 20 | { 21 | "src": "images/icons/icon-128x128.png", 22 | "sizes": "128x128", 23 | "type": "image/png" 24 | }, 25 | { 26 | "src": "images/icons/icon-144x144.png", 27 | "sizes": "144x144", 28 | "type": "image/png" 29 | }, 30 | { 31 | "src": "images/icons/icon-152x152.png", 32 | "sizes": "152x152", 33 | "type": "image/png" 34 | }, 35 | { 36 | "src": "images/icons/icon-192x192.png", 37 | "sizes": "192x192", 38 | "type": "image/png" 39 | }, 40 | { 41 | "src": "images/icons/icon-384x384.png", 42 | "sizes": "384x384", 43 | "type": "image/png" 44 | }, 45 | { 46 | "src": "images/icons/icon-512x512.png", 47 | "sizes": "512x512", 48 | "type": "image/png" 49 | }, 50 | { 51 | "src": "android-chrome-192x192.png", 52 | "sizes": "192x192", 53 | "type": "image/png" 54 | }, 55 | { 56 | "src": "android-chrome-512x512.png", 57 | "sizes": "512x512", 58 | "type": "image/png" 59 | } 60 | ], 61 | "splash_pages": null 62 | } 63 | -------------------------------------------------------------------------------- /src/assets/md/html.md: -------------------------------------------------------------------------------- 1 | ```html 2 |
3 | 4 |
5 | 6 | 7 | 8 |
9 | 10 |
14 | 17 | 18 |
19 | 20 |
21 | ``` 22 | -------------------------------------------------------------------------------- /src/assets/md/scss.md: -------------------------------------------------------------------------------- 1 | ```scss 2 | agm-map { 3 | height: 400px; 4 | } 5 | 6 | .autocomplete-container { 7 | padding: 1rem 0 1rem 0; 8 | width: 50%; 9 | } 10 | ``` 11 | -------------------------------------------------------------------------------- /src/assets/md/search/html.md: -------------------------------------------------------------------------------- 1 | ```html 2 | 3 | Auto Parse Address 4 | 5 | 6 | 9 | > 10 | 11 | 12 | ``` 13 | 14 | 15 | ```typescript 16 | import {Appearance, GermanAddress, Location} from '@angular-material-extensions/google-maps-autocomplete'; 17 | 18 | onGermanAddressMapped($event;: GermanAddress;) { 19 | console.log('onGermanAddressMapped', $event); 20 | } 21 | ``` 22 | -------------------------------------------------------------------------------- /src/assets/md/ts.md: -------------------------------------------------------------------------------- 1 | ```typescript 2 | import {Component, OnInit, ViewEncapsulation} from '@angular/core'; 3 | import {Title} from '@angular/platform-browser'; 4 | import {Location, Appearance, GermanAddress} from '@angular-material-extensions/google-maps-autocomplete'; 5 | import {} from '@types/googlemaps'; 6 | import PlaceResult = google.maps.places.PlaceResult; 7 | 8 | @Component({ 9 | selector: 'app-home', 10 | templateUrl: './home.component.html', 11 | styleUrls: ['./home.component.scss'], 12 | encapsulation: ViewEncapsulation.None, 13 | }) 14 | export class HomeComponent implements OnInit { 15 | 16 | public appearance = Appearance; 17 | public zoom: number; 18 | public latitude: number; 19 | public longitude: number; 20 | public selectedAddress: PlaceResult; 21 | 22 | constructor(private titleService: Title) { 23 | } 24 | 25 | ngOnInit() { 26 | this.titleService.setTitle('Home | @angular-material-extensions/google-maps-autocomplete'); 27 | 28 | this.zoom = 10; 29 | this.latitude = 52.520008; 30 | this.longitude = 13.404954; 31 | 32 | this.setCurrentPosition(); 33 | 34 | } 35 | 36 | private setCurrentPosition() { 37 | if ('geolocation' in navigator) { 38 | navigator.geolocation.getCurrentPosition((position) => { 39 | this.latitude = position.coords.latitude; 40 | this.longitude = position.coords.longitude; 41 | this.zoom = 12; 42 | }); 43 | } 44 | } 45 | 46 | onAutocompleteSelected(result: PlaceResult) { 47 | console.log('onAutocompleteSelected: ', result); 48 | } 49 | 50 | onLocationSelected(location: Location) { 51 | console.log('onLocationSelected: ', location); 52 | this.latitude = location.latitude; 53 | this.longitude = location.longitude; 54 | } 55 | 56 | onGermanAddressMapped($event: GermanAddress) { 57 | console.log('onGermanAddressMapped', $event); 58 | } 59 | 60 | } 61 | 62 | ``` 63 | -------------------------------------------------------------------------------- /src/assets/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/src/assets/mstile-150x150.png -------------------------------------------------------------------------------- /src/assets/npm-variant-outline.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.11, written by Peter Selinger 2001-2013 9 | 10 | 12 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/assets/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /src/config/config.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Configuration 4 | Adjust the configuration of this extensions on your own way <3 5 | 6 | 7 | 8 | addressLabelText 9 | 10 | 11 | 12 | 13 | placeholderText 14 | 15 | 16 | 17 | 18 | requiredErrorText 19 | 20 | 21 | 22 | 23 | invalidErrorText 24 | 25 | 26 | 27 | 28 | 29 | Google Maps API 30 | The component need to be re-rendered after changing these properties 31 | 32 | 33 | 34 | Enter the desired country code, e.g: en, de, fr ... 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | Input's appearance style 43 | 44 | 45 | 46 | 49 | {{option}} 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/config/config.component.scss: -------------------------------------------------------------------------------- 1 | .full-width { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/config/config.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {Appearance} from '@angular-material-extensions/google-maps-autocomplete'; 3 | 4 | @Component({ 5 | selector: 'app-config', 6 | templateUrl: './config.component.html', 7 | styleUrls: ['./config.component.scss'] 8 | }) 9 | export class ConfigComponent implements OnInit { 10 | 11 | addressLabelText = 'Address'; 12 | 13 | placeholderText = 'Please enter the address'; 14 | 15 | requiredErrorText = 'The address is required'; 16 | 17 | invalidErrorText = 'The address is not valid'; 18 | 19 | country; 20 | 21 | appearance = Appearance.OUTLINE; 22 | appearanceOptions = Object.keys(Appearance); 23 | 24 | constructor() { 25 | } 26 | 27 | ngOnInit() { 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | GOOGLE_MAPS_API_KEY: '', 4 | }; 5 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false, 7 | GOOGLE_MAPS_API_KEY: '' 8 | }; 9 | 10 | /* 11 | * For easier debugging in development mode, you can import the following file 12 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 13 | * 14 | * This import should be commented out in production mode because it will have a negative impact 15 | * on performance if an error is thrown. 16 | */ 17 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 18 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angular-material-extensions/google-maps-autocomplete/a47216fb8e07b0695807b68d79a5875887bdbc8f/src/favicon.ico -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | GoogleMapsAutocomplete 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | 23 | 24 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /src/main.server.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | 3 | import { environment } from './environments/environment'; 4 | 5 | if (environment.production) { 6 | enableProdMode(); 7 | } 8 | 9 | export { AppServerModule } from './app/app.server.module'; 10 | export { ngExpressEngine } from "@nguniversal/express-engine"; 11 | 12 | 13 | export { renderModuleFactory } from '@angular/platform-server'; -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | document.addEventListener('DOMContentLoaded', () => { 12 | platformBrowserDynamic().bootstrapModule(AppModule) 13 | .catch(err => console.error(err)); 14 | }); 15 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** 22 | * By default, zone.js will patch all possible macroTask and DomEvents 23 | * user can disable parts of macroTask/DomEvents patch by setting following flags 24 | * because those flags need to be set before `zone.js` being loaded, and webpack 25 | * will put import in the top of bundle, so user need to create a separate file 26 | * in this directory (for example: zone-flags.ts), and put the following flags 27 | * into that file, and then add the following code before importing zone.js. 28 | * import './zone-flags.ts'; 29 | * 30 | * The flags allowed in zone-flags.ts are listed here. 31 | * 32 | * The following flags will work for all browsers. 33 | * 34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 37 | * 38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 40 | * 41 | * (window as any).__Zone_enable_cross_context_check = true; 42 | * 43 | */ 44 | 45 | /*************************************************************************************************** 46 | * Zone JS is required by default for Angular itself. 47 | */ 48 | import 'zone.js'; // Included with Angular CLI. 49 | 50 | 51 | /*************************************************************************************************** 52 | * APPLICATION IMPORTS 53 | */ 54 | -------------------------------------------------------------------------------- /src/setup-jest.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular'; 2 | 3 | /* global mocks for jsdom */ 4 | const mock = () => { 5 | let storage: { [key: string]: string } = {}; 6 | return { 7 | getItem: (key: string) => (key in storage ? storage[key] : null), 8 | setItem: (key: string, value: string) => (storage[key] = value || ''), 9 | removeItem: (key: string) => delete storage[key], 10 | clear: () => (storage = {}) 11 | }; 12 | }; 13 | 14 | Object.defineProperty(window, 'localStorage', { value: mock() }); 15 | Object.defineProperty(window, 'sessionStorage', { value: mock() }); 16 | Object.defineProperty(window, 'getComputedStyle', { 17 | value: () => ['-webkit-appearance'], 18 | }); 19 | 20 | Object.defineProperty(document.body.style, 'transform', { 21 | value: () => { 22 | return { 23 | enumerable: true, 24 | configurable: true, 25 | }; 26 | }, 27 | }); 28 | 29 | /* output shorter and more meaningful Zone error stack traces */ 30 | // Error.stackTraceLimit = 2; 31 | -------------------------------------------------------------------------------- /src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | 3 | html, body { height: 100%; } 4 | body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } 5 | -------------------------------------------------------------------------------- /src/test-config.helper.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | type CompilerOptions = Partial<{ 4 | providers: any[]; 5 | useJit: boolean; 6 | preserveWhitespaces: boolean; 7 | }>; 8 | export type ConfigureFn = (testBed: typeof TestBed) => void; 9 | 10 | export const configureTests = ( 11 | configure: ConfigureFn, 12 | compilerOptions: CompilerOptions = {} 13 | ) => { 14 | const compilerConfig: CompilerOptions = { 15 | preserveWhitespaces: false, 16 | ...compilerOptions, 17 | }; 18 | 19 | const configuredTestBed = TestBed.configureCompiler(compilerConfig); 20 | 21 | configure(configuredTestBed); 22 | 23 | return configuredTestBed.compileComponents().then(() => configuredTestBed); 24 | }; 25 | -------------------------------------------------------------------------------- /static.paths.ts: -------------------------------------------------------------------------------- 1 | export const ROUTES = [ 2 | '/', 3 | ]; 4 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/app", 5 | "types": [] 6 | }, 7 | "files": [ 8 | "src/main.ts", 9 | "src/polyfills.ts" 10 | ], 11 | "include": [ 12 | "src/**/*.d.ts" 13 | ], 14 | "exclude": [ 15 | "src/test.ts", 16 | "src/**/*.spec.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "downlevelIteration": true, 9 | "experimentalDecorators": true, 10 | "module": "esnext", 11 | "moduleResolution": "node", 12 | "importHelpers": true, 13 | "target": "es2020", 14 | "typeRoots": [ 15 | "node_modules/@types" 16 | ], 17 | "lib": [ 18 | "es2018", 19 | "dom" 20 | ], 21 | "paths": { 22 | "@angular-material-extensions/google-maps-autocomplete": [ 23 | "dist/angular-material-extensions/google-maps-autocomplete" 24 | ], 25 | "@angular-material-extensions/google-maps-autocomplete/*": [ 26 | "dist/angular-material-extensions/google-maps-autocomplete/*" 27 | ] 28 | } 29 | }, 30 | "angularCompilerOptions": { 31 | "fullTemplateTypeCheck": true, 32 | "strictInjectionParameters": true 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tsconfig.server.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.app.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/app-server", 5 | "module": "commonjs" 6 | }, 7 | "files": [ 8 | "src/main.server.ts", 9 | "server.ts" 10 | ], 11 | "angularCompilerOptions": { 12 | "entryModule": "./src/app/app.server.module#AppServerModule" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/spec", 5 | "types": [ 6 | "jasmine", 7 | "node" 8 | ], 9 | "emitDecoratorMetadata": true, 10 | "allowJs": true 11 | }, 12 | "files": [ 13 | "src/polyfills.ts" 14 | ], 15 | "include": [ 16 | "src/**/*.spec.ts", 17 | "src/**/*.d.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint:recommended", 3 | "rules": { 4 | "array-type": false, 5 | "arrow-parens": false, 6 | "deprecation": { 7 | "severity": "warning" 8 | }, 9 | "component-class-suffix": true, 10 | "contextual-lifecycle": true, 11 | "directive-class-suffix": true, 12 | "directive-selector": [ 13 | true, 14 | "attribute", 15 | "app", 16 | "camelCase" 17 | ], 18 | "component-selector": [ 19 | true, 20 | "element", 21 | "app", 22 | "kebab-case" 23 | ], 24 | "import-blacklist": [ 25 | true, 26 | "rxjs/Rx" 27 | ], 28 | "interface-name": false, 29 | "max-classes-per-file": false, 30 | "max-line-length": [ 31 | true, 32 | 140 33 | ], 34 | "member-access": false, 35 | "member-ordering": [ 36 | true, 37 | { 38 | "order": [ 39 | "static-field", 40 | "instance-field", 41 | "static-method", 42 | "instance-method" 43 | ] 44 | } 45 | ], 46 | "no-consecutive-blank-lines": false, 47 | "no-console": [ 48 | true, 49 | "debug", 50 | "info", 51 | "time", 52 | "timeEnd", 53 | "trace" 54 | ], 55 | "no-empty": false, 56 | "no-inferrable-types": [ 57 | true, 58 | "ignore-params" 59 | ], 60 | "no-non-null-assertion": true, 61 | "no-redundant-jsdoc": true, 62 | "no-switch-case-fall-through": true, 63 | "no-var-requires": false, 64 | "object-literal-key-quotes": [ 65 | true, 66 | "as-needed" 67 | ], 68 | "object-literal-sort-keys": false, 69 | "ordered-imports": false, 70 | "quotemark": [ 71 | true, 72 | "single" 73 | ], 74 | "trailing-comma": false, 75 | "no-conflicting-lifecycle": true, 76 | "no-host-metadata-property": true, 77 | "no-input-rename": true, 78 | "no-inputs-metadata-property": true, 79 | "no-output-native": true, 80 | "no-output-on-prefix": false, 81 | "no-output-rename": true, 82 | "no-outputs-metadata-property": true, 83 | "template-banana-in-box": true, 84 | "template-no-negated-async": true, 85 | "use-lifecycle-interface": true, 86 | "use-pipe-transform-interface": true 87 | }, 88 | "rulesDirectory": [ 89 | "codelyzer" 90 | ] 91 | } 92 | -------------------------------------------------------------------------------- /webpack.server.config.js: -------------------------------------------------------------------------------- 1 | // Work around for https://github.com/angular/angular-cli/issues/7200 2 | 3 | const path = require('path'); 4 | const webpack = require('webpack'); 5 | 6 | module.exports = { 7 | mode: 'none', 8 | entry: { 9 | // This is our Express server for Dynamic universal 10 | server: './server.ts', 11 | // This is an example of Static prerendering (generative) 12 | prerender: './prerender.ts' 13 | }, 14 | externals: { 15 | './dist/server/main': 'require("./server/main")' 16 | }, 17 | target: 'node', 18 | resolve: { extensions: ['.ts', '.js'] }, 19 | optimization: { 20 | minimize: false 21 | }, 22 | output: { 23 | // Puts the output at the root of the dist folder 24 | path: path.join(__dirname, 'dist'), 25 | filename: '[name].js' 26 | }, 27 | module: { 28 | noParse: /polyfills-.*\.js/, 29 | rules: [ 30 | { test: /\.ts$/, loader: 'ts-loader' }, 31 | { 32 | // Mark files inside `@angular/core` as using SystemJS style dynamic imports. 33 | // Removing this will cause deprecation warnings to appear. 34 | test: /(\\|\/)@angular(\\|\/)core(\\|\/).+\.js$/, 35 | parser: { system: true }, 36 | }, 37 | ] 38 | }, 39 | plugins: [ 40 | new webpack.ContextReplacementPlugin( 41 | // fixes WARNING Critical dependency: the request of a dependency is an expression 42 | /(.+)?angular(\\|\/)core(.+)?/, 43 | path.join(__dirname, 'src'), // location of your src 44 | {} // a map of your routes 45 | ), 46 | new webpack.ContextReplacementPlugin( 47 | // fixes WARNING Critical dependency: the request of a dependency is an expression 48 | /(.+)?express(\\|\/)(.+)?/, 49 | path.join(__dirname, 'src'), 50 | {} 51 | ) 52 | ] 53 | }; 54 | --------------------------------------------------------------------------------