├── .editorconfig ├── .gitignore ├── .npmrc ├── CHANGELOG.md ├── README.md ├── angular.json ├── docs ├── 3rdpartylicenses.txt ├── favicon.ico ├── index.html ├── main-U6IZHJQ4.js ├── polyfills-LZBJRJJE.js └── styles-SBGRPVWB.css ├── jest.config.ts ├── logo.svg ├── package-lock.json ├── package.json ├── projects ├── docs │ ├── src │ │ ├── app │ │ │ ├── app.component.html │ │ │ ├── app.component.scss │ │ │ └── app.component.ts │ │ ├── assets │ │ │ └── .gitkeep │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── main.ts │ │ └── styles.scss │ ├── tsconfig.app.json │ └── tsconfig.spec.json └── ngx-reactive-storage │ ├── jest.config.ts │ ├── ng-package.json │ ├── package.json │ ├── src │ ├── lib │ │ ├── idb.spec.ts │ │ ├── idb.ts │ │ ├── index.ts │ │ ├── local-storage.spec.ts │ │ ├── local-storage.ts │ │ ├── observer.ts │ │ └── types.ts │ ├── public-api.ts │ └── test-setup.ts │ ├── tsconfig.lib.json │ ├── tsconfig.lib.prod.json │ └── tsconfig.spec.json └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = tab 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /.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 | /bazel-out 8 | 9 | # Node 10 | /node_modules 11 | npm-debug.log 12 | yarn-error.log 13 | 14 | # IDEs and editors 15 | .idea/ 16 | .project 17 | .classpath 18 | .c9/ 19 | *.launch 20 | .settings/ 21 | *.sublime-workspace 22 | 23 | # Visual Studio Code 24 | .vscode/* 25 | !.vscode/settings.json 26 | !.vscode/tasks.json 27 | !.vscode/launch.json 28 | !.vscode/extensions.json 29 | .history/* 30 | 31 | # Miscellaneous 32 | /.angular/cache 33 | .sass-cache/ 34 | /connect.lock 35 | /coverage 36 | /libpeerconnection.log 37 | testem.log 38 | /typings 39 | 40 | # System files 41 | .DS_Store 42 | Thumbs.db 43 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | legacy-peer-deps = true 2 | strict-peer-dependencies = false 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## v2.0.1 2 | Angular v20 is now supported. 3 | 4 | ## v2.0.0 5 | ### Breaking changes: 6 | * TypeScript version 5.6+ is required. 7 | 8 | This library still works with Angular v16+, but if you use the strict peer dependencies setting (enabled by default) in your package manager, TypeScript version 5.6+ is only supported by Angular v19. 9 | 10 | This is caused by a different method of importing the localForge library, and this method is required for SSR support. 11 | 12 | ### New features: 13 | * SSR is now supported 🎉 14 | 15 | You no longer need to wrap storage initialization in `afterNextRender()`. 16 | 17 | ## v1.2.2 18 | Angular 18 is now supported. 19 | 20 | ## v1.2.1 21 | Add info about `getWritableSignal()` to README. 22 | 23 | ## v1.2.0 24 | Method `getWritableSignal()` will not write initial value to the storage anymore. 25 | 26 | ## v1.1.2 27 | Fix: Do not emit an observable and signal if no value is found during the initial read in the storage. 28 | 29 | ## v1.1.1 30 | Fix types in functions overloading. 31 | 32 | ## v1.1.0 33 | New method: `getWritableSignal()` - returns a signal that you can modify using `set()` or `update()` methods, and these modifications will also update the storage key. 34 | 35 | ## v1.0.4 36 | More types overloading for `getSignal()` 🤦 37 | 38 | ## v1.0.3 39 | Better TypeScript types for `getSignal()`, remove `SignalOptions` type (was not part of public API). 40 | 41 | ## v1.0.2 42 | Better TypeScript types for `getSignal()` and `SignalOptions`. 43 | 44 | ## v1.0.1 45 | Method `getSignal()` now accepts `SignalOptions` as the second argument. This allows you to set the initial value and the equality check function. 46 | 47 | ## v1.0.0 48 | 1. This library has been tested in production for a long enough time. 49 | 2. No breaking changes in the API are expected in the near future. 50 | 51 | 3. So we can indeed call it v1.0.0! 52 | 53 | ## v0.2.0 54 | Use [BroadcastChannel](https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API) to sync changes of IndexedDB stores in multiple tabs. 55 | 56 | ## v0.1.3 57 | More docs, more tests. 58 | 59 | ## v0.1.2 60 | 61 | Improve documentation. 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Reactive Storage 2 | =============== 3 |

4 | 5 | 6 | Wrapper around [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) and [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage). 7 | 8 | Allows to create databases and tables in both of them using a simple API. 9 | 10 | Modifications of the data can be observed using RxJS Observables or Angular Signals. 11 | 12 | > [!IMPORTANT] 13 | > While observing a specific key, you will receive notifications about changes made not only in the current instance of the application but also in other tabs or windows. 14 | > It opens a lot of interesting opportunities for data synchronization across tabs and windows. 15 | 16 | Observables and signals will be created only upon demand, ensuring that no resources are wasted for keys that are not being observed. 17 | 18 | ## Uses 19 | ✳️ Angular v19+ 20 | ✳️ TypeScript 5.6+ 21 | ✳️ RxJS v7+ 22 | ✳️ localForage (IndexedDB) 23 | 24 | ## Installation 25 | 26 | [npm](https://www.npmjs.com/package/ngx-reactive-storage): 27 | ```bash 28 | npm i ngx-reactive-storage 29 | ``` 30 | 31 | Yarn: 32 | ```bash 33 | yarn add ngx-reactive-storage 34 | ``` 35 | 36 | ## Usage 37 | 38 | ```ts 39 | import { RxStorage } from "ngx-reactive-storage"; 40 | 41 | const storage = new RxStorage(); 42 | 43 | storage.set('hello', 'world!'); 44 | ``` 45 | 46 | 47 | API 48 | === 49 | ```ts 50 | export type ReactiveStorage = { 51 | /** 52 | * Returns value by the key 53 | */ 54 | get(key: string): Promise; 55 | 56 | /** 57 | * Returns a hot observable (replay:1) and pushes the current value for this key. 58 | * Future modifications will be pushed to the returned observable. 59 | * 60 | * If localStorage is being used as the storage, the value will be pushed synchronously 61 | * (to allow you to read it synchronously or asynchronously). 62 | */ 63 | getObservable(key: string): Observable; 64 | 65 | /** 66 | * Returns a signal with the current value for this key. 67 | * The key becomes "observed" and future modifications will be 68 | * written to the returned signal. 69 | * 70 | * If localStorage is being used as the storage, the value will be pushed synchronously. 71 | */ 72 | getSignal(key: string, options?: SignalOptions): Signal; 73 | 74 | 75 | /** 76 | * Returns a signal with the current value for this key. 77 | * The key becomes "observed" and future modifications will be 78 | * written to the returned signal. 79 | * 80 | * The usage of the `set()` and `update()` methods of this signal will also update the storage key. 81 | * 82 | * If localStorage is being used as the storage, the value will be pushed synchronously. 83 | */ 84 | getWritableSignal(key: string, options?: SignalOptions): WritableSignal; 85 | 86 | /** 87 | * Set a key-value pair 88 | */ 89 | set(key: string, value: unknown): Promise; 90 | 91 | /** 92 | * Removes a key 93 | */ 94 | remove(key: string): Promise; 95 | 96 | /** 97 | * Returns keys of the current table (located in the current database). 98 | */ 99 | getKeys(): Promise; 100 | 101 | /** 102 | * Removes all keys of the current table (located in the current database). 103 | */ 104 | clear(): Promise; 105 | 106 | /** 107 | * Removes links to observables and signals; removes event listeners. 108 | */ 109 | dispose(): void; 110 | } 111 | ``` 112 | 113 | https://user-images.githubusercontent.com/526352/284077145-51b438e0-e0e7-416d-b38d-d55449983793.mov 114 | 115 | 116 | ## What storage to use 117 | The recommended storage is **IndexedDB**, because it: 118 | 1. Is supported by every browser alive; 119 | 2. Gives you gigabytes of space (60% of the disk in Chrome, 10 Gb in Firefox, [etc.](https://developer.mozilla.org/en-US/docs/Web/API/Storage_API/Storage_quotas_and_eviction_criteria#other_web_technologies)); 120 | 3. Has native separation by databases and tables. 121 | 122 | **localStorage** is limited to just 5 Mb of space, but sometimes you need to read some data synchronously before you render something. 123 | 124 | Using this library, you can use all the nice additions, one API for both types of storages, and still read from localStorage synchronously when needed, using observables or signals. 125 | 126 | Example: 127 | ```ts 128 | import { RxLocalStorage } from "ngx-reactive-storage"; 129 | 130 | const storage = new RxLocalStorage('settings', 'db1'); 131 | 132 | const colorScheme = storage.getSignal('color-scheme')(); 133 | 134 | ``` 135 | 136 | ## Supported browsers 137 | * Chrome: v54+ 138 | * Edge: v79+ 139 | * Firefox: v38+ 140 | * Safari: v15.4+ 141 | * Opera: v41+ 142 | * Chrome for Android: v115+ 143 | * Firefox for Android: v115+ 144 | * Safari iOS: v15.4+ 145 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "ngx-reactive-storage": { 7 | "projectType": "library", 8 | "root": "projects/ngx-reactive-storage", 9 | "sourceRoot": "projects/ngx-reactive-storage/src", 10 | "prefix": "lib", 11 | "architect": { 12 | "build": { 13 | "builder": "@angular-devkit/build-angular:ng-packagr", 14 | "options": { 15 | "project": "projects/ngx-reactive-storage/ng-package.json" 16 | }, 17 | "configurations": { 18 | "production": { 19 | "tsConfig": "projects/ngx-reactive-storage/tsconfig.lib.prod.json" 20 | }, 21 | "development": { 22 | "tsConfig": "projects/ngx-reactive-storage/tsconfig.lib.json" 23 | } 24 | }, 25 | "defaultConfiguration": "production" 26 | }, 27 | "test": { 28 | "builder": "@angular-devkit/build-angular:karma", 29 | "options": { 30 | "tsConfig": "projects/ngx-reactive-storage/tsconfig.spec.json", 31 | "polyfills": [ 32 | "zone.js", 33 | "zone.js/testing" 34 | ] 35 | } 36 | } 37 | } 38 | }, 39 | "docs": { 40 | "projectType": "application", 41 | "schematics": { 42 | "@schematics/angular:component": { 43 | "style": "scss" 44 | } 45 | }, 46 | "root": "projects/docs", 47 | "sourceRoot": "projects/docs/src", 48 | "prefix": "app", 49 | "architect": { 50 | "build": { 51 | "builder": "@angular-devkit/build-angular:browser-esbuild", 52 | "options": { 53 | "outputPath": "docs", 54 | "baseHref": "/ngx-reactive-storage/", 55 | "index": "projects/docs/src/index.html", 56 | "main": "projects/docs/src/main.ts", 57 | "polyfills": [ 58 | "zone.js" 59 | ], 60 | "tsConfig": "projects/docs/tsconfig.app.json", 61 | "inlineStyleLanguage": "scss", 62 | "assets": [ 63 | "projects/docs/src/favicon.ico", 64 | "projects/docs/src/assets" 65 | ], 66 | "styles": [ 67 | "projects/docs/src/styles.scss" 68 | ], 69 | "scripts": [] 70 | }, 71 | "configurations": { 72 | "production": { 73 | "budgets": [ 74 | { 75 | "type": "initial", 76 | "maximumWarning": "500kb", 77 | "maximumError": "1mb" 78 | }, 79 | { 80 | "type": "anyComponentStyle", 81 | "maximumWarning": "2kb", 82 | "maximumError": "4kb" 83 | } 84 | ], 85 | "outputHashing": "all" 86 | }, 87 | "development": { 88 | "optimization": false, 89 | "extractLicenses": false, 90 | "sourceMap": true 91 | } 92 | }, 93 | "defaultConfiguration": "production" 94 | }, 95 | "serve": { 96 | "builder": "@angular-devkit/build-angular:dev-server", 97 | "configurations": { 98 | "production": { 99 | "buildTarget": "docs:build:production" 100 | }, 101 | "development": { 102 | "buildTarget": "docs:build:development" 103 | } 104 | }, 105 | "defaultConfiguration": "development" 106 | }, 107 | "extract-i18n": { 108 | "builder": "@angular-devkit/build-angular:extract-i18n", 109 | "options": { 110 | "buildTarget": "docs:build" 111 | } 112 | }, 113 | "test": { 114 | "builder": "@angular-devkit/build-angular:karma", 115 | "options": { 116 | "polyfills": [ 117 | "zone.js", 118 | "zone.js/testing" 119 | ], 120 | "tsConfig": "projects/docs/tsconfig.spec.json", 121 | "inlineStyleLanguage": "scss", 122 | "assets": [ 123 | "projects/docs/src/favicon.ico", 124 | "projects/docs/src/assets" 125 | ], 126 | "styles": [ 127 | "projects/docs/src/styles.scss" 128 | ], 129 | "scripts": [] 130 | } 131 | } 132 | } 133 | } 134 | }, 135 | "cli": { 136 | "analytics": false 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /docs/3rdpartylicenses.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- 3 | Package: localforage 4 | License: "Apache-2.0" 5 | 6 | Apache License 7 | Version 2.0, January 2004 8 | http://www.apache.org/licenses/ 9 | 10 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 11 | 12 | 1. Definitions. 13 | 14 | "License" shall mean the terms and conditions for use, reproduction, 15 | and distribution as defined by Sections 1 through 9 of this document. 16 | 17 | "Licensor" shall mean the copyright owner or entity authorized by 18 | the copyright owner that is granting the License. 19 | 20 | "Legal Entity" shall mean the union of the acting entity and all 21 | other entities that control, are controlled by, or are under common 22 | control with that entity. For the purposes of this definition, 23 | "control" means (i) the power, direct or indirect, to cause the 24 | direction or management of such entity, whether by contract or 25 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 26 | outstanding shares, or (iii) beneficial ownership of such entity. 27 | 28 | "You" (or "Your") shall mean an individual or Legal Entity 29 | exercising permissions granted by this License. 30 | 31 | "Source" form shall mean the preferred form for making modifications, 32 | including but not limited to software source code, documentation 33 | source, and configuration files. 34 | 35 | "Object" form shall mean any form resulting from mechanical 36 | transformation or translation of a Source form, including but 37 | not limited to compiled object code, generated documentation, 38 | and conversions to other media types. 39 | 40 | "Work" shall mean the work of authorship, whether in Source or 41 | Object form, made available under the License, as indicated by a 42 | copyright notice that is included in or attached to the work 43 | (an example is provided in the Appendix below). 44 | 45 | "Derivative Works" shall mean any work, whether in Source or Object 46 | form, that is based on (or derived from) the Work and for which the 47 | editorial revisions, annotations, elaborations, or other modifications 48 | represent, as a whole, an original work of authorship. For the purposes 49 | of this License, Derivative Works shall not include works that remain 50 | separable from, or merely link (or bind by name) to the interfaces of, 51 | the Work and Derivative Works thereof. 52 | 53 | "Contribution" shall mean any work of authorship, including 54 | the original version of the Work and any modifications or additions 55 | to that Work or Derivative Works thereof, that is intentionally 56 | submitted to Licensor for inclusion in the Work by the copyright owner 57 | or by an individual or Legal Entity authorized to submit on behalf of 58 | the copyright owner. For the purposes of this definition, "submitted" 59 | means any form of electronic, verbal, or written communication sent 60 | to the Licensor or its representatives, including but not limited to 61 | communication on electronic mailing lists, source code control systems, 62 | and issue tracking systems that are managed by, or on behalf of, the 63 | Licensor for the purpose of discussing and improving the Work, but 64 | excluding communication that is conspicuously marked or otherwise 65 | designated in writing by the copyright owner as "Not a Contribution." 66 | 67 | "Contributor" shall mean Licensor and any individual or Legal Entity 68 | on behalf of whom a Contribution has been received by Licensor and 69 | subsequently incorporated within the Work. 70 | 71 | 2. Grant of Copyright License. Subject to the terms and conditions of 72 | this License, each Contributor hereby grants to You a perpetual, 73 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 74 | copyright license to reproduce, prepare Derivative Works of, 75 | publicly display, publicly perform, sublicense, and distribute the 76 | Work and such Derivative Works in Source or Object form. 77 | 78 | 3. Grant of Patent License. Subject to the terms and conditions of 79 | this License, each Contributor hereby grants to You a perpetual, 80 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 81 | (except as stated in this section) patent license to make, have made, 82 | use, offer to sell, sell, import, and otherwise transfer the Work, 83 | where such license applies only to those patent claims licensable 84 | by such Contributor that are necessarily infringed by their 85 | Contribution(s) alone or by combination of their Contribution(s) 86 | with the Work to which such Contribution(s) was submitted. If You 87 | institute patent litigation against any entity (including a 88 | cross-claim or counterclaim in a lawsuit) alleging that the Work 89 | or a Contribution incorporated within the Work constitutes direct 90 | or contributory patent infringement, then any patent licenses 91 | granted to You under this License for that Work shall terminate 92 | as of the date such litigation is filed. 93 | 94 | 4. Redistribution. You may reproduce and distribute copies of the 95 | Work or Derivative Works thereof in any medium, with or without 96 | modifications, and in Source or Object form, provided that You 97 | meet the following conditions: 98 | 99 | (a) You must give any other recipients of the Work or 100 | Derivative Works a copy of this License; and 101 | 102 | (b) You must cause any modified files to carry prominent notices 103 | stating that You changed the files; and 104 | 105 | (c) You must retain, in the Source form of any Derivative Works 106 | that You distribute, all copyright, patent, trademark, and 107 | attribution notices from the Source form of the Work, 108 | excluding those notices that do not pertain to any part of 109 | the Derivative Works; and 110 | 111 | (d) If the Work includes a "NOTICE" text file as part of its 112 | distribution, then any Derivative Works that You distribute must 113 | include a readable copy of the attribution notices contained 114 | within such NOTICE file, excluding those notices that do not 115 | pertain to any part of the Derivative Works, in at least one 116 | of the following places: within a NOTICE text file distributed 117 | as part of the Derivative Works; within the Source form or 118 | documentation, if provided along with the Derivative Works; or, 119 | within a display generated by the Derivative Works, if and 120 | wherever such third-party notices normally appear. The contents 121 | of the NOTICE file are for informational purposes only and 122 | do not modify the License. You may add Your own attribution 123 | notices within Derivative Works that You distribute, alongside 124 | or as an addendum to the NOTICE text from the Work, provided 125 | that such additional attribution notices cannot be construed 126 | as modifying the License. 127 | 128 | You may add Your own copyright statement to Your modifications and 129 | may provide additional or different license terms and conditions 130 | for use, reproduction, or distribution of Your modifications, or 131 | for any such Derivative Works as a whole, provided Your use, 132 | reproduction, and distribution of the Work otherwise complies with 133 | the conditions stated in this License. 134 | 135 | 5. Submission of Contributions. Unless You explicitly state otherwise, 136 | any Contribution intentionally submitted for inclusion in the Work 137 | by You to the Licensor shall be under the terms and conditions of 138 | this License, without any additional terms or conditions. 139 | Notwithstanding the above, nothing herein shall supersede or modify 140 | the terms of any separate license agreement you may have executed 141 | with Licensor regarding such Contributions. 142 | 143 | 6. Trademarks. This License does not grant permission to use the trade 144 | names, trademarks, service marks, or product names of the Licensor, 145 | except as required for reasonable and customary use in describing the 146 | origin of the Work and reproducing the content of the NOTICE file. 147 | 148 | 7. Disclaimer of Warranty. Unless required by applicable law or 149 | agreed to in writing, Licensor provides the Work (and each 150 | Contributor provides its Contributions) on an "AS IS" BASIS, 151 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 152 | implied, including, without limitation, any warranties or conditions 153 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 154 | PARTICULAR PURPOSE. You are solely responsible for determining the 155 | appropriateness of using or redistributing the Work and assume any 156 | risks associated with Your exercise of permissions under this License. 157 | 158 | 8. Limitation of Liability. In no event and under no legal theory, 159 | whether in tort (including negligence), contract, or otherwise, 160 | unless required by applicable law (such as deliberate and grossly 161 | negligent acts) or agreed to in writing, shall any Contributor be 162 | liable to You for damages, including any direct, indirect, special, 163 | incidental, or consequential damages of any character arising as a 164 | result of this License or out of the use or inability to use the 165 | Work (including but not limited to damages for loss of goodwill, 166 | work stoppage, computer failure or malfunction, or any and all 167 | other commercial damages or losses), even if such Contributor 168 | has been advised of the possibility of such damages. 169 | 170 | 9. Accepting Warranty or Additional Liability. While redistributing 171 | the Work or Derivative Works thereof, You may choose to offer, 172 | and charge a fee for, acceptance of support, warranty, indemnity, 173 | or other liability obligations and/or rights consistent with this 174 | License. However, in accepting such obligations, You may act only 175 | on Your own behalf and on Your sole responsibility, not on behalf 176 | of any other Contributor, and only if You agree to indemnify, 177 | defend, and hold each Contributor harmless for any liability 178 | incurred by, or claims asserted against, such Contributor by reason 179 | of your accepting any such warranty or additional liability. 180 | 181 | END OF TERMS AND CONDITIONS 182 | 183 | APPENDIX: How to apply the Apache License to your work. 184 | 185 | To apply the Apache License to your work, attach the following 186 | boilerplate notice, with the fields enclosed by brackets "{}" 187 | replaced with your own identifying information. (Don't include 188 | the brackets!) The text should be enclosed in the appropriate 189 | comment syntax for the file format. We also recommend that a 190 | file or class name and description of purpose be included on the 191 | same "printed page" as the copyright notice for easier 192 | identification within third-party archives. 193 | 194 | Copyright 2014 Mozilla 195 | 196 | Licensed under the Apache License, Version 2.0 (the "License"); 197 | you may not use this file except in compliance with the License. 198 | You may obtain a copy of the License at 199 | 200 | http://www.apache.org/licenses/LICENSE-2.0 201 | 202 | Unless required by applicable law or agreed to in writing, software 203 | distributed under the License is distributed on an "AS IS" BASIS, 204 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 205 | See the License for the specific language governing permissions and 206 | limitations under the License. 207 | 208 | -------------------------------------------------------------------------------- 209 | Package: @angular/core 210 | License: "MIT" 211 | 212 | 213 | -------------------------------------------------------------------------------- 214 | Package: rxjs 215 | License: "Apache-2.0" 216 | 217 | Apache License 218 | Version 2.0, January 2004 219 | http://www.apache.org/licenses/ 220 | 221 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 222 | 223 | 1. Definitions. 224 | 225 | "License" shall mean the terms and conditions for use, reproduction, 226 | and distribution as defined by Sections 1 through 9 of this document. 227 | 228 | "Licensor" shall mean the copyright owner or entity authorized by 229 | the copyright owner that is granting the License. 230 | 231 | "Legal Entity" shall mean the union of the acting entity and all 232 | other entities that control, are controlled by, or are under common 233 | control with that entity. For the purposes of this definition, 234 | "control" means (i) the power, direct or indirect, to cause the 235 | direction or management of such entity, whether by contract or 236 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 237 | outstanding shares, or (iii) beneficial ownership of such entity. 238 | 239 | "You" (or "Your") shall mean an individual or Legal Entity 240 | exercising permissions granted by this License. 241 | 242 | "Source" form shall mean the preferred form for making modifications, 243 | including but not limited to software source code, documentation 244 | source, and configuration files. 245 | 246 | "Object" form shall mean any form resulting from mechanical 247 | transformation or translation of a Source form, including but 248 | not limited to compiled object code, generated documentation, 249 | and conversions to other media types. 250 | 251 | "Work" shall mean the work of authorship, whether in Source or 252 | Object form, made available under the License, as indicated by a 253 | copyright notice that is included in or attached to the work 254 | (an example is provided in the Appendix below). 255 | 256 | "Derivative Works" shall mean any work, whether in Source or Object 257 | form, that is based on (or derived from) the Work and for which the 258 | editorial revisions, annotations, elaborations, or other modifications 259 | represent, as a whole, an original work of authorship. For the purposes 260 | of this License, Derivative Works shall not include works that remain 261 | separable from, or merely link (or bind by name) to the interfaces of, 262 | the Work and Derivative Works thereof. 263 | 264 | "Contribution" shall mean any work of authorship, including 265 | the original version of the Work and any modifications or additions 266 | to that Work or Derivative Works thereof, that is intentionally 267 | submitted to Licensor for inclusion in the Work by the copyright owner 268 | or by an individual or Legal Entity authorized to submit on behalf of 269 | the copyright owner. For the purposes of this definition, "submitted" 270 | means any form of electronic, verbal, or written communication sent 271 | to the Licensor or its representatives, including but not limited to 272 | communication on electronic mailing lists, source code control systems, 273 | and issue tracking systems that are managed by, or on behalf of, the 274 | Licensor for the purpose of discussing and improving the Work, but 275 | excluding communication that is conspicuously marked or otherwise 276 | designated in writing by the copyright owner as "Not a Contribution." 277 | 278 | "Contributor" shall mean Licensor and any individual or Legal Entity 279 | on behalf of whom a Contribution has been received by Licensor and 280 | subsequently incorporated within the Work. 281 | 282 | 2. Grant of Copyright License. Subject to the terms and conditions of 283 | this License, each Contributor hereby grants to You a perpetual, 284 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 285 | copyright license to reproduce, prepare Derivative Works of, 286 | publicly display, publicly perform, sublicense, and distribute the 287 | Work and such Derivative Works in Source or Object form. 288 | 289 | 3. Grant of Patent License. Subject to the terms and conditions of 290 | this License, each Contributor hereby grants to You a perpetual, 291 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 292 | (except as stated in this section) patent license to make, have made, 293 | use, offer to sell, sell, import, and otherwise transfer the Work, 294 | where such license applies only to those patent claims licensable 295 | by such Contributor that are necessarily infringed by their 296 | Contribution(s) alone or by combination of their Contribution(s) 297 | with the Work to which such Contribution(s) was submitted. If You 298 | institute patent litigation against any entity (including a 299 | cross-claim or counterclaim in a lawsuit) alleging that the Work 300 | or a Contribution incorporated within the Work constitutes direct 301 | or contributory patent infringement, then any patent licenses 302 | granted to You under this License for that Work shall terminate 303 | as of the date such litigation is filed. 304 | 305 | 4. Redistribution. You may reproduce and distribute copies of the 306 | Work or Derivative Works thereof in any medium, with or without 307 | modifications, and in Source or Object form, provided that You 308 | meet the following conditions: 309 | 310 | (a) You must give any other recipients of the Work or 311 | Derivative Works a copy of this License; and 312 | 313 | (b) You must cause any modified files to carry prominent notices 314 | stating that You changed the files; and 315 | 316 | (c) You must retain, in the Source form of any Derivative Works 317 | that You distribute, all copyright, patent, trademark, and 318 | attribution notices from the Source form of the Work, 319 | excluding those notices that do not pertain to any part of 320 | the Derivative Works; and 321 | 322 | (d) If the Work includes a "NOTICE" text file as part of its 323 | distribution, then any Derivative Works that You distribute must 324 | include a readable copy of the attribution notices contained 325 | within such NOTICE file, excluding those notices that do not 326 | pertain to any part of the Derivative Works, in at least one 327 | of the following places: within a NOTICE text file distributed 328 | as part of the Derivative Works; within the Source form or 329 | documentation, if provided along with the Derivative Works; or, 330 | within a display generated by the Derivative Works, if and 331 | wherever such third-party notices normally appear. The contents 332 | of the NOTICE file are for informational purposes only and 333 | do not modify the License. You may add Your own attribution 334 | notices within Derivative Works that You distribute, alongside 335 | or as an addendum to the NOTICE text from the Work, provided 336 | that such additional attribution notices cannot be construed 337 | as modifying the License. 338 | 339 | You may add Your own copyright statement to Your modifications and 340 | may provide additional or different license terms and conditions 341 | for use, reproduction, or distribution of Your modifications, or 342 | for any such Derivative Works as a whole, provided Your use, 343 | reproduction, and distribution of the Work otherwise complies with 344 | the conditions stated in this License. 345 | 346 | 5. Submission of Contributions. Unless You explicitly state otherwise, 347 | any Contribution intentionally submitted for inclusion in the Work 348 | by You to the Licensor shall be under the terms and conditions of 349 | this License, without any additional terms or conditions. 350 | Notwithstanding the above, nothing herein shall supersede or modify 351 | the terms of any separate license agreement you may have executed 352 | with Licensor regarding such Contributions. 353 | 354 | 6. Trademarks. This License does not grant permission to use the trade 355 | names, trademarks, service marks, or product names of the Licensor, 356 | except as required for reasonable and customary use in describing the 357 | origin of the Work and reproducing the content of the NOTICE file. 358 | 359 | 7. Disclaimer of Warranty. Unless required by applicable law or 360 | agreed to in writing, Licensor provides the Work (and each 361 | Contributor provides its Contributions) on an "AS IS" BASIS, 362 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 363 | implied, including, without limitation, any warranties or conditions 364 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 365 | PARTICULAR PURPOSE. You are solely responsible for determining the 366 | appropriateness of using or redistributing the Work and assume any 367 | risks associated with Your exercise of permissions under this License. 368 | 369 | 8. Limitation of Liability. In no event and under no legal theory, 370 | whether in tort (including negligence), contract, or otherwise, 371 | unless required by applicable law (such as deliberate and grossly 372 | negligent acts) or agreed to in writing, shall any Contributor be 373 | liable to You for damages, including any direct, indirect, special, 374 | incidental, or consequential damages of any character arising as a 375 | result of this License or out of the use or inability to use the 376 | Work (including but not limited to damages for loss of goodwill, 377 | work stoppage, computer failure or malfunction, or any and all 378 | other commercial damages or losses), even if such Contributor 379 | has been advised of the possibility of such damages. 380 | 381 | 9. Accepting Warranty or Additional Liability. While redistributing 382 | the Work or Derivative Works thereof, You may choose to offer, 383 | and charge a fee for, acceptance of support, warranty, indemnity, 384 | or other liability obligations and/or rights consistent with this 385 | License. However, in accepting such obligations, You may act only 386 | on Your own behalf and on Your sole responsibility, not on behalf 387 | of any other Contributor, and only if You agree to indemnify, 388 | defend, and hold each Contributor harmless for any liability 389 | incurred by, or claims asserted against, such Contributor by reason 390 | of your accepting any such warranty or additional liability. 391 | 392 | END OF TERMS AND CONDITIONS 393 | 394 | APPENDIX: How to apply the Apache License to your work. 395 | 396 | To apply the Apache License to your work, attach the following 397 | boilerplate notice, with the fields enclosed by brackets "[]" 398 | replaced with your own identifying information. (Don't include 399 | the brackets!) The text should be enclosed in the appropriate 400 | comment syntax for the file format. We also recommend that a 401 | file or class name and description of purpose be included on the 402 | same "printed page" as the copyright notice for easier 403 | identification within third-party archives. 404 | 405 | Copyright (c) 2015-2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors 406 | 407 | Licensed under the Apache License, Version 2.0 (the "License"); 408 | you may not use this file except in compliance with the License. 409 | You may obtain a copy of the License at 410 | 411 | http://www.apache.org/licenses/LICENSE-2.0 412 | 413 | Unless required by applicable law or agreed to in writing, software 414 | distributed under the License is distributed on an "AS IS" BASIS, 415 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 416 | See the License for the specific language governing permissions and 417 | limitations under the License. 418 | 419 | 420 | -------------------------------------------------------------------------------- 421 | Package: tslib 422 | License: "0BSD" 423 | 424 | Copyright (c) Microsoft Corporation. 425 | 426 | Permission to use, copy, modify, and/or distribute this software for any 427 | purpose with or without fee is hereby granted. 428 | 429 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 430 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 431 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 432 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 433 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 434 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 435 | PERFORMANCE OF THIS SOFTWARE. 436 | -------------------------------------------------------------------------------- 437 | Package: @angular/common 438 | License: "MIT" 439 | 440 | 441 | -------------------------------------------------------------------------------- 442 | Package: @angular/platform-browser 443 | License: "MIT" 444 | 445 | 446 | -------------------------------------------------------------------------------- 447 | Package: @angular/animations 448 | License: "MIT" 449 | 450 | 451 | -------------------------------------------------------------------------------- 452 | Package: @angular/forms 453 | License: "MIT" 454 | 455 | 456 | -------------------------------------------------------------------------------- 457 | Package: @angular/cdk 458 | License: "MIT" 459 | 460 | The MIT License 461 | 462 | Copyright (c) 2023 Google LLC. 463 | 464 | Permission is hereby granted, free of charge, to any person obtaining a copy 465 | of this software and associated documentation files (the "Software"), to deal 466 | in the Software without restriction, including without limitation the rights 467 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 468 | copies of the Software, and to permit persons to whom the Software is 469 | furnished to do so, subject to the following conditions: 470 | 471 | The above copyright notice and this permission notice shall be included in 472 | all copies or substantial portions of the Software. 473 | 474 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 475 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 476 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 477 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 478 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 479 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 480 | THE SOFTWARE. 481 | 482 | -------------------------------------------------------------------------------- 483 | Package: @angular/material 484 | License: "MIT" 485 | 486 | The MIT License 487 | 488 | Copyright (c) 2023 Google LLC. 489 | 490 | Permission is hereby granted, free of charge, to any person obtaining a copy 491 | of this software and associated documentation files (the "Software"), to deal 492 | in the Software without restriction, including without limitation the rights 493 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 494 | copies of the Software, and to permit persons to whom the Software is 495 | furnished to do so, subject to the following conditions: 496 | 497 | The above copyright notice and this permission notice shall be included in 498 | all copies or substantial portions of the Software. 499 | 500 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 501 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 502 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 503 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 504 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 505 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 506 | THE SOFTWARE. 507 | 508 | -------------------------------------------------------------------------------- 509 | Package: zone.js 510 | License: "MIT" 511 | 512 | The MIT License 513 | 514 | Copyright (c) 2010-2023 Google LLC. https://angular.io/license 515 | 516 | Permission is hereby granted, free of charge, to any person obtaining a copy 517 | of this software and associated documentation files (the "Software"), to deal 518 | in the Software without restriction, including without limitation the rights 519 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 520 | copies of the Software, and to permit persons to whom the Software is 521 | furnished to do so, subject to the following conditions: 522 | 523 | The above copyright notice and this permission notice shall be included in 524 | all copies or substantial portions of the Software. 525 | 526 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 527 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 528 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 529 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 530 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 531 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 532 | THE SOFTWARE. 533 | 534 | -------------------------------------------------------------------------------- 535 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/e-oz/ngx-reactive-storage/d0db398aeb3ad637c78858b8731764135658e799/docs/favicon.ico -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Reactive Storage 6 | 7 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/polyfills-LZBJRJJE.js: -------------------------------------------------------------------------------- 1 | (function(e){let n=e.performance;function c(L){n&&n.mark&&n.mark(L)}function r(L,t){n&&n.measure&&n.measure(L,t)}c("Zone");let a=e.__Zone_symbol_prefix||"__zone_symbol__";function l(L){return a+L}let y=e[l("forceDuplicateZoneCheck")]===!0;if(e.Zone){if(y||typeof e.Zone.__symbol__!="function")throw new Error("Zone already loaded.");return e.Zone}let oe=class oe{static assertZonePatched(){if(e.Promise!==re.ZoneAwarePromise)throw new Error("Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten.\nMost likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js.)")}static get root(){let t=oe.current;for(;t.parent;)t=t.parent;return t}static get current(){return U.zone}static get currentTask(){return te}static __load_patch(t,s,o=!1){if(re.hasOwnProperty(t)){if(!o&&y)throw Error("Already loaded patch: "+t)}else if(!e["__Zone_disable_"+t]){let v="Zone:"+t;c(v),re[t]=s(e,oe,z),r(v,v)}}get parent(){return this._parent}get name(){return this._name}constructor(t,s){this._parent=t,this._name=s?s.name||"unnamed":"",this._properties=s&&s.properties||{},this._zoneDelegate=new k(this,this._parent&&this._parent._zoneDelegate,s)}get(t){let s=this.getZoneWith(t);if(s)return s._properties[t]}getZoneWith(t){let s=this;for(;s;){if(s._properties.hasOwnProperty(t))return s;s=s._parent}return null}fork(t){if(!t)throw new Error("ZoneSpec required!");return this._zoneDelegate.fork(this,t)}wrap(t,s){if(typeof t!="function")throw new Error("Expecting function got: "+t);let o=this._zoneDelegate.intercept(this,t,s),v=this;return function(){return v.runGuarded(o,this,arguments,s)}}run(t,s,o,v){U={parent:U,zone:this};try{return this._zoneDelegate.invoke(this,t,s,o,v)}finally{U=U.parent}}runGuarded(t,s=null,o,v){U={parent:U,zone:this};try{try{return this._zoneDelegate.invoke(this,t,s,o,v)}catch(F){if(this._zoneDelegate.handleError(this,F))throw F}}finally{U=U.parent}}runTask(t,s,o){if(t.zone!=this)throw new Error("A task can only be run in the zone of creation! (Creation: "+(t.zone||$).name+"; Execution: "+this.name+")");if(t.state===H&&(t.type===K||t.type===P))return;let v=t.state!=T;v&&t._transitionTo(T,M),t.runCount++;let F=te;te=t,U={parent:U,zone:this};try{t.type==P&&t.data&&!t.data.isPeriodic&&(t.cancelFn=void 0);try{return this._zoneDelegate.invokeTask(this,t,s,o)}catch(u){if(this._zoneDelegate.handleError(this,u))throw u}}finally{t.state!==H&&t.state!==d&&(t.type==K||t.data&&t.data.isPeriodic?v&&t._transitionTo(M,T):(t.runCount=0,this._updateTaskCount(t,-1),v&&t._transitionTo(H,T,H))),U=U.parent,te=F}}scheduleTask(t){if(t.zone&&t.zone!==this){let o=this;for(;o;){if(o===t.zone)throw Error(`can not reschedule task to ${this.name} which is descendants of the original zone ${t.zone.name}`);o=o.parent}}t._transitionTo(X,H);let s=[];t._zoneDelegates=s,t._zone=this;try{t=this._zoneDelegate.scheduleTask(this,t)}catch(o){throw t._transitionTo(d,X,H),this._zoneDelegate.handleError(this,o),o}return t._zoneDelegates===s&&this._updateTaskCount(t,1),t.state==X&&t._transitionTo(M,X),t}scheduleMicroTask(t,s,o,v){return this.scheduleTask(new m(N,t,s,o,v,void 0))}scheduleMacroTask(t,s,o,v,F){return this.scheduleTask(new m(P,t,s,o,v,F))}scheduleEventTask(t,s,o,v,F){return this.scheduleTask(new m(K,t,s,o,v,F))}cancelTask(t){if(t.zone!=this)throw new Error("A task can only be cancelled in the zone of creation! (Creation: "+(t.zone||$).name+"; Execution: "+this.name+")");if(!(t.state!==M&&t.state!==T)){t._transitionTo(x,M,T);try{this._zoneDelegate.cancelTask(this,t)}catch(s){throw t._transitionTo(d,x),this._zoneDelegate.handleError(this,s),s}return this._updateTaskCount(t,-1),t._transitionTo(H,x),t.runCount=0,t}}_updateTaskCount(t,s){let o=t._zoneDelegates;s==-1&&(t._zoneDelegates=null);for(let v=0;vL.hasTask(s,o),onScheduleTask:(L,t,s,o)=>L.scheduleTask(s,o),onInvokeTask:(L,t,s,o,v,F)=>L.invokeTask(s,o,v,F),onCancelTask:(L,t,s,o)=>L.cancelTask(s,o)};class k{constructor(t,s,o){this._taskCounts={microTask:0,macroTask:0,eventTask:0},this.zone=t,this._parentDelegate=s,this._forkZS=o&&(o&&o.onFork?o:s._forkZS),this._forkDlgt=o&&(o.onFork?s:s._forkDlgt),this._forkCurrZone=o&&(o.onFork?this.zone:s._forkCurrZone),this._interceptZS=o&&(o.onIntercept?o:s._interceptZS),this._interceptDlgt=o&&(o.onIntercept?s:s._interceptDlgt),this._interceptCurrZone=o&&(o.onIntercept?this.zone:s._interceptCurrZone),this._invokeZS=o&&(o.onInvoke?o:s._invokeZS),this._invokeDlgt=o&&(o.onInvoke?s:s._invokeDlgt),this._invokeCurrZone=o&&(o.onInvoke?this.zone:s._invokeCurrZone),this._handleErrorZS=o&&(o.onHandleError?o:s._handleErrorZS),this._handleErrorDlgt=o&&(o.onHandleError?s:s._handleErrorDlgt),this._handleErrorCurrZone=o&&(o.onHandleError?this.zone:s._handleErrorCurrZone),this._scheduleTaskZS=o&&(o.onScheduleTask?o:s._scheduleTaskZS),this._scheduleTaskDlgt=o&&(o.onScheduleTask?s:s._scheduleTaskDlgt),this._scheduleTaskCurrZone=o&&(o.onScheduleTask?this.zone:s._scheduleTaskCurrZone),this._invokeTaskZS=o&&(o.onInvokeTask?o:s._invokeTaskZS),this._invokeTaskDlgt=o&&(o.onInvokeTask?s:s._invokeTaskDlgt),this._invokeTaskCurrZone=o&&(o.onInvokeTask?this.zone:s._invokeTaskCurrZone),this._cancelTaskZS=o&&(o.onCancelTask?o:s._cancelTaskZS),this._cancelTaskDlgt=o&&(o.onCancelTask?s:s._cancelTaskDlgt),this._cancelTaskCurrZone=o&&(o.onCancelTask?this.zone:s._cancelTaskCurrZone),this._hasTaskZS=null,this._hasTaskDlgt=null,this._hasTaskDlgtOwner=null,this._hasTaskCurrZone=null;let v=o&&o.onHasTask,F=s&&s._hasTaskZS;(v||F)&&(this._hasTaskZS=v?o:b,this._hasTaskDlgt=s,this._hasTaskDlgtOwner=this,this._hasTaskCurrZone=t,o.onScheduleTask||(this._scheduleTaskZS=b,this._scheduleTaskDlgt=s,this._scheduleTaskCurrZone=this.zone),o.onInvokeTask||(this._invokeTaskZS=b,this._invokeTaskDlgt=s,this._invokeTaskCurrZone=this.zone),o.onCancelTask||(this._cancelTaskZS=b,this._cancelTaskDlgt=s,this._cancelTaskCurrZone=this.zone))}fork(t,s){return this._forkZS?this._forkZS.onFork(this._forkDlgt,this.zone,t,s):new _(t,s)}intercept(t,s,o){return this._interceptZS?this._interceptZS.onIntercept(this._interceptDlgt,this._interceptCurrZone,t,s,o):s}invoke(t,s,o,v,F){return this._invokeZS?this._invokeZS.onInvoke(this._invokeDlgt,this._invokeCurrZone,t,s,o,v,F):s.apply(o,v)}handleError(t,s){return this._handleErrorZS?this._handleErrorZS.onHandleError(this._handleErrorDlgt,this._handleErrorCurrZone,t,s):!0}scheduleTask(t,s){let o=s;if(this._scheduleTaskZS)this._hasTaskZS&&o._zoneDelegates.push(this._hasTaskDlgtOwner),o=this._scheduleTaskZS.onScheduleTask(this._scheduleTaskDlgt,this._scheduleTaskCurrZone,t,s),o||(o=s);else if(s.scheduleFn)s.scheduleFn(s);else if(s.type==N)R(s);else throw new Error("Task is missing scheduleFn.");return o}invokeTask(t,s,o,v){return this._invokeTaskZS?this._invokeTaskZS.onInvokeTask(this._invokeTaskDlgt,this._invokeTaskCurrZone,t,s,o,v):s.callback.apply(o,v)}cancelTask(t,s){let o;if(this._cancelTaskZS)o=this._cancelTaskZS.onCancelTask(this._cancelTaskDlgt,this._cancelTaskCurrZone,t,s);else{if(!s.cancelFn)throw Error("Task is not cancelable");o=s.cancelFn(s)}return o}hasTask(t,s){try{this._hasTaskZS&&this._hasTaskZS.onHasTask(this._hasTaskDlgt,this._hasTaskCurrZone,t,s)}catch(o){this.handleError(t,o)}}_updateTaskCount(t,s){let o=this._taskCounts,v=o[t],F=o[t]=v+s;if(F<0)throw new Error("More tasks executed then were scheduled.");if(v==0||F==0){let u={microTask:o.microTask>0,macroTask:o.macroTask>0,eventTask:o.eventTask>0,change:t};this.hasTask(this.zone,u)}}}class m{constructor(t,s,o,v,F,u){if(this._zone=null,this.runCount=0,this._zoneDelegates=null,this._state="notScheduled",this.type=t,this.source=s,this.data=v,this.scheduleFn=F,this.cancelFn=u,!o)throw new Error("callback is not defined");this.callback=o;let f=this;t===K&&v&&v.useG?this.invoke=m.invokeTask:this.invoke=function(){return m.invokeTask.call(e,f,this,arguments)}}static invokeTask(t,s,o){t||(t=this),Q++;try{return t.runCount++,t.zone.runTask(t,s,o)}finally{Q==1&&E(),Q--}}get zone(){return this._zone}get state(){return this._state}cancelScheduleRequest(){this._transitionTo(H,X)}_transitionTo(t,s,o){if(this._state===s||this._state===o)this._state=t,t==H&&(this._zoneDelegates=null);else throw new Error(`${this.type} '${this.source}': can not transition to '${t}', expecting state '${s}'${o?" or '"+o+"'":""}, was '${this._state}'.`)}toString(){return this.data&&typeof this.data.handleId<"u"?this.data.handleId.toString():Object.prototype.toString.call(this)}toJSON(){return{type:this.type,state:this.state,source:this.source,zone:this.zone.name,runCount:this.runCount}}}let I=l("setTimeout"),Z=l("Promise"),O=l("then"),B=[],A=!1,J;function q(L){if(J||e[Z]&&(J=e[Z].resolve(0)),J){let t=J[O];t||(t=J.then),t.call(J,L)}else e[I](L,0)}function R(L){Q===0&&B.length===0&&q(E),L&&B.push(L)}function E(){if(!A){for(A=!0;B.length;){let L=B;B=[];for(let t=0;tU,onUnhandledError:W,microtaskDrainDone:W,scheduleMicroTask:R,showUncaughtError:()=>!_[l("ignoreConsoleErrorUncaughtError")],patchEventTarget:()=>[],patchOnProperties:W,patchMethod:()=>W,bindArguments:()=>[],patchThen:()=>W,patchMacroTask:()=>W,patchEventPrototype:()=>W,isIEOrEdge:()=>!1,getGlobalObjects:()=>{},ObjectDefineProperty:()=>W,ObjectGetOwnPropertyDescriptor:()=>{},ObjectCreate:()=>{},ArraySlice:()=>[],patchClass:()=>W,wrapWithCurrentZone:()=>W,filterProperties:()=>[],attachOriginToPatched:()=>W,_redefineProperty:()=>W,patchCallbacks:()=>W,nativeScheduleMicroTask:q},U={parent:null,zone:new _(null,null)},te=null,Q=0;function W(){}return r("Zone","Zone"),e.Zone=_})(globalThis);var me=Object.getOwnPropertyDescriptor,Ne=Object.defineProperty,Ie=Object.getPrototypeOf,it=Object.create,ct=Array.prototype.slice,Me="addEventListener",Le="removeEventListener",Se=Zone.__symbol__(Me),De=Zone.__symbol__(Le),ie="true",ce="false",pe=Zone.__symbol__("");function Ae(e,n){return Zone.current.wrap(e,n)}function je(e,n,c,r,a){return Zone.current.scheduleMacroTask(e,n,c,r,a)}var j=Zone.__symbol__,Pe=typeof window<"u",Te=Pe?window:void 0,Y=Pe&&Te||globalThis,at="removeAttribute";function He(e,n){for(let c=e.length-1;c>=0;c--)typeof e[c]=="function"&&(e[c]=Ae(e[c],n+"_"+c));return e}function lt(e,n){let c=e.constructor.name;for(let r=0;r{let b=function(){return _.apply(this,He(arguments,c+"."+a))};return ae(b,_),b})(l)}}}function Ye(e){return e?e.writable===!1?!1:!(typeof e.get=="function"&&typeof e.set>"u"):!0}var $e=typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope,we=!("nw"in Y)&&typeof Y.process<"u"&&{}.toString.call(Y.process)==="[object process]",xe=!we&&!$e&&!!(Pe&&Te.HTMLElement),Je=typeof Y.process<"u"&&{}.toString.call(Y.process)==="[object process]"&&!$e&&!!(Pe&&Te.HTMLElement),be={},We=function(e){if(e=e||Y.event,!e)return;let n=be[e.type];n||(n=be[e.type]=j("ON_PROPERTY"+e.type));let c=this||e.target||Y,r=c[n],a;if(xe&&c===Te&&e.type==="error"){let l=e;a=r&&r.call(this,l.message,l.filename,l.lineno,l.colno,l.error),a===!0&&e.preventDefault()}else a=r&&r.apply(this,arguments),a!=null&&!a&&e.preventDefault();return a};function qe(e,n,c){let r=me(e,n);if(!r&&c&&me(c,n)&&(r={enumerable:!0,configurable:!0}),!r||!r.configurable)return;let a=j("on"+n+"patched");if(e.hasOwnProperty(a)&&e[a])return;delete r.writable,delete r.value;let l=r.get,y=r.set,_=n.slice(2),b=be[_];b||(b=be[_]=j("ON_PROPERTY"+_)),r.set=function(k){let m=this;if(!m&&e===Y&&(m=Y),!m)return;typeof m[b]=="function"&&m.removeEventListener(_,We),y&&y.call(m,null),m[b]=k,typeof k=="function"&&m.addEventListener(_,We,!1)},r.get=function(){let k=this;if(!k&&e===Y&&(k=Y),!k)return null;let m=k[b];if(m)return m;if(l){let I=l.call(this);if(I)return r.set.call(this,I),typeof k[at]=="function"&&k.removeAttribute(n),I}return null},Ne(e,n,r),e[a]=!0}function Ke(e,n,c){if(n)for(let r=0;rfunction(y,_){let b=c(y,_);return b.cbIdx>=0&&typeof _[b.cbIdx]=="function"?je(b.name,_[b.cbIdx],b,a):l.apply(y,_)})}function ae(e,n){e[j("OriginalDelegate")]=n}var Xe=!1,Ze=!1;function ft(){try{let e=Te.navigator.userAgent;if(e.indexOf("MSIE ")!==-1||e.indexOf("Trident/")!==-1)return!0}catch{}return!1}function ht(){if(Xe)return Ze;Xe=!0;try{let e=Te.navigator.userAgent;(e.indexOf("MSIE ")!==-1||e.indexOf("Trident/")!==-1||e.indexOf("Edge/")!==-1)&&(Ze=!0)}catch{}return Ze}Zone.__load_patch("ZoneAwarePromise",(e,n,c)=>{let r=Object.getOwnPropertyDescriptor,a=Object.defineProperty;function l(u){if(u&&u.toString===Object.prototype.toString){let f=u.constructor&&u.constructor.name;return(f||"")+": "+JSON.stringify(u)}return u?u.toString():Object.prototype.toString.call(u)}let y=c.symbol,_=[],b=e[y("DISABLE_WRAPPING_UNCAUGHT_PROMISE_REJECTION")]!==!1,k=y("Promise"),m=y("then"),I="__creationTrace__";c.onUnhandledError=u=>{if(c.showUncaughtError()){let f=u&&u.rejection;f?console.error("Unhandled Promise rejection:",f instanceof Error?f.message:f,"; Zone:",u.zone.name,"; Task:",u.task&&u.task.source,"; Value:",f,f instanceof Error?f.stack:void 0):console.error(u)}},c.microtaskDrainDone=()=>{for(;_.length;){let u=_.shift();try{u.zone.runGuarded(()=>{throw u.throwOriginal?u.rejection:u})}catch(f){O(f)}}};let Z=y("unhandledPromiseRejectionHandler");function O(u){c.onUnhandledError(u);try{let f=n[Z];typeof f=="function"&&f.call(this,u)}catch{}}function B(u){return u&&u.then}function A(u){return u}function J(u){return t.reject(u)}let q=y("state"),R=y("value"),E=y("finally"),$=y("parentPromiseValue"),H=y("parentPromiseState"),X="Promise.then",M=null,T=!0,x=!1,d=0;function N(u,f){return i=>{try{z(u,f,i)}catch(h){z(u,!1,h)}}}let P=function(){let u=!1;return function(i){return function(){u||(u=!0,i.apply(null,arguments))}}},K="Promise resolved with itself",re=y("currentTaskTrace");function z(u,f,i){let h=P();if(u===i)throw new TypeError(K);if(u[q]===M){let g=null;try{(typeof i=="object"||typeof i=="function")&&(g=i&&i.then)}catch(w){return h(()=>{z(u,!1,w)})(),u}if(f!==x&&i instanceof t&&i.hasOwnProperty(q)&&i.hasOwnProperty(R)&&i[q]!==M)te(i),z(u,i[q],i[R]);else if(f!==x&&typeof g=="function")try{g.call(i,h(N(u,f)),h(N(u,!1)))}catch(w){h(()=>{z(u,!1,w)})()}else{u[q]=f;let w=u[R];if(u[R]=i,u[E]===E&&f===T&&(u[q]=u[H],u[R]=u[$]),f===x&&i instanceof Error){let p=n.currentTask&&n.currentTask.data&&n.currentTask.data[I];p&&a(i,re,{configurable:!0,enumerable:!1,writable:!0,value:p})}for(let p=0;p{try{let C=u[R],S=!!i&&E===i[E];S&&(i[$]=C,i[H]=w);let D=f.run(p,void 0,S&&p!==J&&p!==A?[]:[C]);z(i,!0,D)}catch(C){z(i,!1,C)}},i)}let W="function ZoneAwarePromise() { [native code] }",oe=function(){},L=e.AggregateError;class t{static toString(){return W}static resolve(f){return z(new this(null),T,f)}static reject(f){return z(new this(null),x,f)}static any(f){if(!f||typeof f[Symbol.iterator]!="function")return Promise.reject(new L([],"All promises were rejected"));let i=[],h=0;try{for(let p of f)h++,i.push(t.resolve(p))}catch{return Promise.reject(new L([],"All promises were rejected"))}if(h===0)return Promise.reject(new L([],"All promises were rejected"));let g=!1,w=[];return new t((p,C)=>{for(let S=0;S{g||(g=!0,p(D))},D=>{w.push(D),h--,h===0&&(g=!0,C(new L(w,"All promises were rejected")))})})}static race(f){let i,h,g=new this((C,S)=>{i=C,h=S});function w(C){i(C)}function p(C){h(C)}for(let C of f)B(C)||(C=this.resolve(C)),C.then(w,p);return g}static all(f){return t.allWithCallback(f)}static allSettled(f){return(this&&this.prototype instanceof t?this:t).allWithCallback(f,{thenCallback:h=>({status:"fulfilled",value:h}),errorCallback:h=>({status:"rejected",reason:h})})}static allWithCallback(f,i){let h,g,w=new this((D,G)=>{h=D,g=G}),p=2,C=0,S=[];for(let D of f){B(D)||(D=this.resolve(D));let G=C;try{D.then(V=>{S[G]=i?i.thenCallback(V):V,p--,p===0&&h(S)},V=>{i?(S[G]=i.errorCallback(V),p--,p===0&&h(S)):g(V)})}catch(V){g(V)}p++,C++}return p-=2,p===0&&h(S),w}constructor(f){let i=this;if(!(i instanceof t))throw new Error("Must be an instanceof Promise.");i[q]=M,i[R]=[];try{let h=P();f&&f(h(N(i,T)),h(N(i,x)))}catch(h){z(i,!1,h)}}get[Symbol.toStringTag](){return"Promise"}get[Symbol.species](){return t}then(f,i){let h=this.constructor?.[Symbol.species];(!h||typeof h!="function")&&(h=this.constructor||t);let g=new h(oe),w=n.current;return this[q]==M?this[R].push(w,g,f,i):Q(this,w,g,f,i),g}catch(f){return this.then(null,f)}finally(f){let i=this.constructor?.[Symbol.species];(!i||typeof i!="function")&&(i=t);let h=new i(oe);h[E]=E;let g=n.current;return this[q]==M?this[R].push(g,h,f,f):Q(this,g,h,f,f),h}}t.resolve=t.resolve,t.reject=t.reject,t.race=t.race,t.all=t.all;let s=e[k]=e.Promise;e.Promise=t;let o=y("thenPatched");function v(u){let f=u.prototype,i=r(f,"then");if(i&&(i.writable===!1||!i.configurable))return;let h=f.then;f[m]=h,u.prototype.then=function(g,w){return new t((C,S)=>{h.call(this,C,S)}).then(g,w)},u[o]=!0}c.patchThen=v;function F(u){return function(f,i){let h=u.apply(f,i);if(h instanceof t)return h;let g=h.constructor;return g[o]||v(g),h}}return s&&(v(s),le(e,"fetch",u=>F(u))),Promise[n.__symbol__("uncaughtPromiseErrors")]=_,t});Zone.__load_patch("toString",e=>{let n=Function.prototype.toString,c=j("OriginalDelegate"),r=j("Promise"),a=j("Error"),l=function(){if(typeof this=="function"){let k=this[c];if(k)return typeof k=="function"?n.call(k):Object.prototype.toString.call(k);if(this===Promise){let m=e[r];if(m)return n.call(m)}if(this===Error){let m=e[a];if(m)return n.call(m)}}return n.call(this)};l[c]=n,Function.prototype.toString=l;let y=Object.prototype.toString,_="[object Promise]";Object.prototype.toString=function(){return typeof Promise=="function"&&this instanceof Promise?_:y.call(this)}});var _e=!1;if(typeof window<"u")try{let e=Object.defineProperty({},"passive",{get:function(){_e=!0}});window.addEventListener("test",e,e),window.removeEventListener("test",e,e)}catch{_e=!1}var dt={useG:!0},ee={},Qe={},et=new RegExp("^"+pe+"(\\w+)(true|false)$"),tt=j("propagationStopped");function nt(e,n){let c=(n?n(e):e)+ce,r=(n?n(e):e)+ie,a=pe+c,l=pe+r;ee[e]={},ee[e][ce]=a,ee[e][ie]=l}function _t(e,n,c,r){let a=r&&r.add||Me,l=r&&r.rm||Le,y=r&&r.listeners||"eventListeners",_=r&&r.rmAll||"removeAllListeners",b=j(a),k="."+a+":",m="prependListener",I="."+m+":",Z=function(R,E,$){if(R.isRemoved)return;let H=R.callback;typeof H=="object"&&H.handleEvent&&(R.callback=T=>H.handleEvent(T),R.originalDelegate=H);let X;try{R.invoke(R,E,[$])}catch(T){X=T}let M=R.options;if(M&&typeof M=="object"&&M.once){let T=R.originalDelegate?R.originalDelegate:R.callback;E[l].call(E,$.type,T,M)}return X};function O(R,E,$){if(E=E||e.event,!E)return;let H=R||E.target||e,X=H[ee[E.type][$?ie:ce]];if(X){let M=[];if(X.length===1){let T=Z(X[0],H,E);T&&M.push(T)}else{let T=X.slice();for(let x=0;x{throw x})}}}let B=function(R){return O(this,R,!1)},A=function(R){return O(this,R,!0)};function J(R,E){if(!R)return!1;let $=!0;E&&E.useG!==void 0&&($=E.useG);let H=E&&E.vh,X=!0;E&&E.chkDup!==void 0&&(X=E.chkDup);let M=!1;E&&E.rt!==void 0&&(M=E.rt);let T=R;for(;T&&!T.hasOwnProperty(a);)T=Ie(T);if(!T&&R[a]&&(T=R),!T||T[b])return!1;let x=E&&E.eventNameToString,d={},N=T[b]=T[a],P=T[j(l)]=T[l],K=T[j(y)]=T[y],re=T[j(_)]=T[_],z;E&&E.prepend&&(z=T[j(E.prepend)]=T[E.prepend]);function U(i,h){return!_e&&typeof i=="object"&&i?!!i.capture:!_e||!h?i:typeof i=="boolean"?{capture:i,passive:!0}:i?typeof i=="object"&&i.passive!==!1?{...i,passive:!0}:i:{passive:!0}}let te=function(i){if(!d.isExisting)return N.call(d.target,d.eventName,d.capture?A:B,d.options)},Q=function(i){if(!i.isRemoved){let h=ee[i.eventName],g;h&&(g=h[i.capture?ie:ce]);let w=g&&i.target[g];if(w){for(let p=0;pfunction(a,l){a[tt]=!0,r&&r.apply(a,l)})}function Tt(e,n,c,r,a){let l=Zone.__symbol__(r);if(n[l])return;let y=n[l]=n[r];n[r]=function(_,b,k){return b&&b.prototype&&a.forEach(function(m){let I=`${c}.${r}::`+m,Z=b.prototype;try{if(Z.hasOwnProperty(m)){let O=e.ObjectGetOwnPropertyDescriptor(Z,m);O&&O.value?(O.value=e.wrapWithCurrentZone(O.value,I),e._redefineProperty(b.prototype,m,O)):Z[m]&&(Z[m]=e.wrapWithCurrentZone(Z[m],I))}else Z[m]&&(Z[m]=e.wrapWithCurrentZone(Z[m],I))}catch{}}),y.call(n,_,b,k)},e.attachOriginToPatched(n[r],y)}function ot(e,n,c){if(!c||c.length===0)return n;let r=c.filter(l=>l.target===e);if(!r||r.length===0)return n;let a=r[0].ignoreProperties;return n.filter(l=>a.indexOf(l)===-1)}function ze(e,n,c,r){if(!e)return;let a=ot(e,n,c);Ke(e,a,r)}function Oe(e){return Object.getOwnPropertyNames(e).filter(n=>n.startsWith("on")&&n.length>2).map(n=>n.substring(2))}function yt(e,n){if(we&&!Je||Zone[e.symbol("patchEvents")])return;let c=n.__Zone_ignore_on_properties,r=[];if(xe){let a=window;r=r.concat(["Document","SVGElement","Element","HTMLElement","HTMLBodyElement","HTMLMediaElement","HTMLFrameSetElement","HTMLFrameElement","HTMLIFrameElement","HTMLMarqueeElement","Worker"]);let l=ft()?[{target:a,ignoreProperties:["error"]}]:[];ze(a,Oe(a),c&&c.concat(l),Ie(a))}r=r.concat(["XMLHttpRequest","XMLHttpRequestEventTarget","IDBIndex","IDBRequest","IDBOpenDBRequest","IDBDatabase","IDBTransaction","IDBCursor","WebSocket"]);for(let a=0;a{let r=Oe(e);c.patchOnProperties=Ke,c.patchMethod=le,c.bindArguments=He,c.patchMacroTask=ut;let a=n.__symbol__("BLACK_LISTED_EVENTS"),l=n.__symbol__("UNPATCHED_EVENTS");e[l]&&(e[a]=e[l]),e[a]&&(n[a]=n[l]=e[a]),c.patchEventPrototype=Et,c.patchEventTarget=_t,c.isIEOrEdge=ht,c.ObjectDefineProperty=Ne,c.ObjectGetOwnPropertyDescriptor=me,c.ObjectCreate=it,c.ArraySlice=ct,c.patchClass=ge,c.wrapWithCurrentZone=Ae,c.filterProperties=ot,c.attachOriginToPatched=ae,c._redefineProperty=Object.defineProperty,c.patchCallbacks=Tt,c.getGlobalObjects=()=>({globalSources:Qe,zoneSymbolEventNames:ee,eventNames:r,isBrowser:xe,isMix:Je,isNode:we,TRUE_STR:ie,FALSE_STR:ce,ZONE_SYMBOL_PREFIX:pe,ADD_EVENT_LISTENER_STR:Me,REMOVE_EVENT_LISTENER_STR:Le})});function mt(e,n){n.patchMethod(e,"queueMicrotask",c=>function(r,a){Zone.current.scheduleMicroTask("queueMicrotask",a[0])})}var ve=j("zoneTask");function Ee(e,n,c,r){let a=null,l=null;n+=r,c+=r;let y={};function _(k){let m=k.data;return m.args[0]=function(){return k.invoke.apply(this,arguments)},m.handleId=a.apply(e,m.args),k}function b(k){return l.call(e,k.data.handleId)}a=le(e,n,k=>function(m,I){if(typeof I[0]=="function"){let Z={isPeriodic:r==="Interval",delay:r==="Timeout"||r==="Interval"?I[1]||0:void 0,args:I},O=I[0];I[0]=function(){try{return O.apply(this,arguments)}finally{Z.isPeriodic||(typeof Z.handleId=="number"?delete y[Z.handleId]:Z.handleId&&(Z.handleId[ve]=null))}};let B=je(n,I[0],Z,_,b);if(!B)return B;let A=B.data.handleId;return typeof A=="number"?y[A]=B:A&&(A[ve]=B),A&&A.ref&&A.unref&&typeof A.ref=="function"&&typeof A.unref=="function"&&(B.ref=A.ref.bind(A),B.unref=A.unref.bind(A)),typeof A=="number"||A?A:B}else return k.apply(e,I)}),l=le(e,c,k=>function(m,I){let Z=I[0],O;typeof Z=="number"?O=y[Z]:(O=Z&&Z[ve],O||(O=Z)),O&&typeof O.type=="string"?O.state!=="notScheduled"&&(O.cancelFn&&O.data.isPeriodic||O.runCount===0)&&(typeof Z=="number"?delete y[Z]:Z&&(Z[ve]=null),O.zone.cancelTask(O)):k.apply(e,I)})}function pt(e,n){let{isBrowser:c,isMix:r}=n.getGlobalObjects();if(!c&&!r||!e.customElements||!("customElements"in e))return;let a=["connectedCallback","disconnectedCallback","adoptedCallback","attributeChangedCallback"];n.patchCallbacks(n,e.customElements,"customElements","define",a)}function gt(e,n){if(Zone[n.symbol("patchEventTarget")])return;let{eventNames:c,zoneSymbolEventNames:r,TRUE_STR:a,FALSE_STR:l,ZONE_SYMBOL_PREFIX:y}=n.getGlobalObjects();for(let b=0;b{let n=e[Zone.__symbol__("legacyPatch")];n&&n()});Zone.__load_patch("timers",e=>{let n="set",c="clear";Ee(e,n,c,"Timeout"),Ee(e,n,c,"Interval"),Ee(e,n,c,"Immediate")});Zone.__load_patch("requestAnimationFrame",e=>{Ee(e,"request","cancel","AnimationFrame"),Ee(e,"mozRequest","mozCancel","AnimationFrame"),Ee(e,"webkitRequest","webkitCancel","AnimationFrame")});Zone.__load_patch("blocking",(e,n)=>{let c=["alert","prompt","confirm"];for(let r=0;rfunction(b,k){return n.current.run(l,e,k,_)})}});Zone.__load_patch("EventTarget",(e,n,c)=>{kt(e,c),gt(e,c);let r=e.XMLHttpRequestEventTarget;r&&r.prototype&&c.patchEventTarget(e,c,[r.prototype])});Zone.__load_patch("MutationObserver",(e,n,c)=>{ge("MutationObserver"),ge("WebKitMutationObserver")});Zone.__load_patch("IntersectionObserver",(e,n,c)=>{ge("IntersectionObserver")});Zone.__load_patch("FileReader",(e,n,c)=>{ge("FileReader")});Zone.__load_patch("on_property",(e,n,c)=>{yt(c,e)});Zone.__load_patch("customElements",(e,n,c)=>{pt(e,c)});Zone.__load_patch("XHR",(e,n)=>{b(e);let c=j("xhrTask"),r=j("xhrSync"),a=j("xhrListener"),l=j("xhrScheduled"),y=j("xhrURL"),_=j("xhrErrorBeforeScheduled");function b(k){let m=k.XMLHttpRequest;if(!m)return;let I=m.prototype;function Z(d){return d[c]}let O=I[Se],B=I[De];if(!O){let d=k.XMLHttpRequestEventTarget;if(d){let N=d.prototype;O=N[Se],B=N[De]}}let A="readystatechange",J="scheduled";function q(d){let N=d.data,P=N.target;P[l]=!1,P[_]=!1;let K=P[a];O||(O=P[Se],B=P[De]),K&&B.call(P,A,K);let re=P[a]=()=>{if(P.readyState===P.DONE)if(!N.aborted&&P[l]&&d.state===J){let U=P[n.__symbol__("loadfalse")];if(P.status!==0&&U&&U.length>0){let te=d.invoke;d.invoke=function(){let Q=P[n.__symbol__("loadfalse")];for(let W=0;Wfunction(d,N){return d[r]=N[2]==!1,d[y]=N[1],$.apply(d,N)}),H="XMLHttpRequest.send",X=j("fetchTaskAborting"),M=j("fetchTaskScheduling"),T=le(I,"send",()=>function(d,N){if(n.current[M]===!0||d[r])return T.apply(d,N);{let P={target:d,url:d[y],isPeriodic:!1,args:N,aborted:!1},K=je(H,R,P,q,E);d&&d[_]===!0&&!P.aborted&&K.state===J&&K.invoke()}}),x=le(I,"abort",()=>function(d,N){let P=Z(d);if(P&&typeof P.type=="string"){if(P.cancelFn==null||P.data&&P.data.aborted)return;P.zone.cancelTask(P)}else if(n.current[X]===!0)return x.apply(d,N)})}});Zone.__load_patch("geolocation",e=>{e.navigator&&e.navigator.geolocation&<(e.navigator.geolocation,["getCurrentPosition","watchPosition"])});Zone.__load_patch("PromiseRejectionEvent",(e,n)=>{function c(r){return function(a){rt(e,r).forEach(y=>{let _=e.PromiseRejectionEvent;if(_){let b=new _(r,{promise:a.promise,reason:a.rejection});y.invoke(b)}})}}e.PromiseRejectionEvent&&(n[j("unhandledPromiseRejectionHandler")]=c("unhandledrejection"),n[j("rejectionHandledHandler")]=c("rejectionhandled"))});Zone.__load_patch("queueMicrotask",(e,n,c)=>{mt(e,c)}); 3 | -------------------------------------------------------------------------------- /docs/styles-SBGRPVWB.css: -------------------------------------------------------------------------------- 1 | .mat-ripple{overflow:hidden;position:relative}.mat-ripple:not(:empty){transform:translateZ(0)}.mat-ripple.mat-ripple-unbounded{overflow:visible}.mat-ripple-element{position:absolute;border-radius:50%;pointer-events:none;transition:opacity,transform 0ms cubic-bezier(0,0,.2,1);transform:scale3d(0,0,0);background-color:var(--mat-ripple-color, rgba(0, 0, 0, .1))}.cdk-high-contrast-active .mat-ripple-element{display:none}.cdk-visually-hidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;white-space:nowrap;outline:0;-webkit-appearance:none;-moz-appearance:none;left:0}[dir=rtl] .cdk-visually-hidden{left:auto;right:0}.cdk-overlay-container,.cdk-global-overlay-wrapper{pointer-events:none;top:0;left:0;height:100%;width:100%}.cdk-overlay-container{position:fixed;z-index:1000}.cdk-overlay-container:empty{display:none}.cdk-global-overlay-wrapper{display:flex;position:absolute;z-index:1000}.cdk-overlay-pane{position:absolute;pointer-events:auto;box-sizing:border-box;z-index:1000;display:flex;max-width:100%;max-height:100%}.cdk-overlay-backdrop{position:absolute;inset:0;z-index:1000;pointer-events:auto;-webkit-tap-highlight-color:transparent;transition:opacity .4s cubic-bezier(.25,.8,.25,1);opacity:0}.cdk-overlay-backdrop.cdk-overlay-backdrop-showing{opacity:1}.cdk-high-contrast-active .cdk-overlay-backdrop.cdk-overlay-backdrop-showing{opacity:.6}.cdk-overlay-dark-backdrop{background:rgba(0,0,0,.32)}.cdk-overlay-transparent-backdrop{transition:visibility 1ms linear,opacity 1ms linear;visibility:hidden;opacity:1}.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing{opacity:0;visibility:visible}.cdk-overlay-backdrop-noop-animation{transition:none}.cdk-overlay-connected-position-bounding-box{position:absolute;z-index:1000;display:flex;flex-direction:column;min-width:1px;min-height:1px}.cdk-global-scrollblock{position:fixed;width:100%;overflow-y:scroll}textarea.cdk-textarea-autosize{resize:none}textarea.cdk-textarea-autosize-measuring{padding:2px 0!important;box-sizing:content-box!important;height:auto!important;overflow:hidden!important}textarea.cdk-textarea-autosize-measuring-firefox{padding:2px 0!important;box-sizing:content-box!important;height:0!important}@keyframes cdk-text-field-autofill-start{}@keyframes cdk-text-field-autofill-end{}.cdk-text-field-autofill-monitored:-webkit-autofill{animation:cdk-text-field-autofill-start 0s 1ms}.cdk-text-field-autofill-monitored:not(:-webkit-autofill){animation:cdk-text-field-autofill-end 0s 1ms}.mat-focus-indicator{position:relative}.mat-focus-indicator:before{inset:0;position:absolute;box-sizing:border-box;pointer-events:none;display:var(--mat-focus-indicator-display, none);border:var(--mat-focus-indicator-border-width, 3px) var(--mat-focus-indicator-border-style, solid) var(--mat-focus-indicator-border-color, transparent);border-radius:var(--mat-focus-indicator-border-radius, 4px)}.mat-focus-indicator:focus:before{content:""}.cdk-high-contrast-active{--mat-focus-indicator-display: block}.mat-mdc-focus-indicator{position:relative}.mat-mdc-focus-indicator:before{inset:0;position:absolute;box-sizing:border-box;pointer-events:none;display:var(--mat-mdc-focus-indicator-display, none);border:var(--mat-mdc-focus-indicator-border-width, 3px) var(--mat-mdc-focus-indicator-border-style, solid) var(--mat-mdc-focus-indicator-border-color, transparent);border-radius:var(--mat-mdc-focus-indicator-border-radius, 4px)}.mat-mdc-focus-indicator:focus:before{content:""}.cdk-high-contrast-active{--mat-mdc-focus-indicator-display: block}html{--mat-ripple-color: rgba(0, 0, 0, .1)}html{--mat-option-selected-state-label-text-color: #3f51b5;--mat-option-label-text-color: rgba(0, 0, 0, .87);--mat-option-hover-state-layer-color: rgba(0, 0, 0, .04);--mat-option-focus-state-layer-color: rgba(0, 0, 0, .04);--mat-option-selected-state-layer-color: rgba(0, 0, 0, .04)}.mat-accent{--mat-option-selected-state-label-text-color: #ff4081;--mat-option-label-text-color: rgba(0, 0, 0, .87);--mat-option-hover-state-layer-color: rgba(0, 0, 0, .04);--mat-option-focus-state-layer-color: rgba(0, 0, 0, .04);--mat-option-selected-state-layer-color: rgba(0, 0, 0, .04)}.mat-warn{--mat-option-selected-state-label-text-color: #f44336;--mat-option-label-text-color: rgba(0, 0, 0, .87);--mat-option-hover-state-layer-color: rgba(0, 0, 0, .04);--mat-option-focus-state-layer-color: rgba(0, 0, 0, .04);--mat-option-selected-state-layer-color: rgba(0, 0, 0, .04)}html{--mat-optgroup-label-text-color: rgba(0, 0, 0, .87)}.mat-pseudo-checkbox-full{color:#0000008a}.mat-pseudo-checkbox-full.mat-pseudo-checkbox-disabled{color:#b0b0b0}.mat-primary .mat-pseudo-checkbox-checked.mat-pseudo-checkbox-minimal:after,.mat-primary .mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-minimal:after{color:#3f51b5}.mat-primary .mat-pseudo-checkbox-checked.mat-pseudo-checkbox-full,.mat-primary .mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-full{background:#3f51b5}.mat-primary .mat-pseudo-checkbox-checked.mat-pseudo-checkbox-full:after,.mat-primary .mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-full:after{color:#fafafa}.mat-pseudo-checkbox-checked.mat-pseudo-checkbox-minimal:after,.mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-minimal:after{color:#ff4081}.mat-pseudo-checkbox-checked.mat-pseudo-checkbox-full,.mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-full{background:#ff4081}.mat-pseudo-checkbox-checked.mat-pseudo-checkbox-full:after,.mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-full:after{color:#fafafa}.mat-accent .mat-pseudo-checkbox-checked.mat-pseudo-checkbox-minimal:after,.mat-accent .mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-minimal:after{color:#ff4081}.mat-accent .mat-pseudo-checkbox-checked.mat-pseudo-checkbox-full,.mat-accent .mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-full{background:#ff4081}.mat-accent .mat-pseudo-checkbox-checked.mat-pseudo-checkbox-full:after,.mat-accent .mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-full:after{color:#fafafa}.mat-warn .mat-pseudo-checkbox-checked.mat-pseudo-checkbox-minimal:after,.mat-warn .mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-minimal:after{color:#f44336}.mat-warn .mat-pseudo-checkbox-checked.mat-pseudo-checkbox-full,.mat-warn .mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-full{background:#f44336}.mat-warn .mat-pseudo-checkbox-checked.mat-pseudo-checkbox-full:after,.mat-warn .mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-full:after{color:#fafafa}.mat-pseudo-checkbox-disabled.mat-pseudo-checkbox-checked.mat-pseudo-checkbox-minimal:after,.mat-pseudo-checkbox-disabled.mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-minimal:after{color:#b0b0b0}.mat-pseudo-checkbox-disabled.mat-pseudo-checkbox-checked.mat-pseudo-checkbox-full,.mat-pseudo-checkbox-disabled.mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-full{background:#b0b0b0}.mat-app-background{background-color:#fafafa;color:#000000de}.mat-elevation-z0,.mat-mdc-elevation-specific.mat-elevation-z0{box-shadow:0 0 #0003,0 0 #00000024,0 0 #0000001f}.mat-elevation-z1,.mat-mdc-elevation-specific.mat-elevation-z1{box-shadow:0 2px 1px -1px #0003,0 1px 1px #00000024,0 1px 3px #0000001f}.mat-elevation-z2,.mat-mdc-elevation-specific.mat-elevation-z2{box-shadow:0 3px 1px -2px #0003,0 2px 2px #00000024,0 1px 5px #0000001f}.mat-elevation-z3,.mat-mdc-elevation-specific.mat-elevation-z3{box-shadow:0 3px 3px -2px #0003,0 3px 4px #00000024,0 1px 8px #0000001f}.mat-elevation-z4,.mat-mdc-elevation-specific.mat-elevation-z4{box-shadow:0 2px 4px -1px #0003,0 4px 5px #00000024,0 1px 10px #0000001f}.mat-elevation-z5,.mat-mdc-elevation-specific.mat-elevation-z5{box-shadow:0 3px 5px -1px #0003,0 5px 8px #00000024,0 1px 14px #0000001f}.mat-elevation-z6,.mat-mdc-elevation-specific.mat-elevation-z6{box-shadow:0 3px 5px -1px #0003,0 6px 10px #00000024,0 1px 18px #0000001f}.mat-elevation-z7,.mat-mdc-elevation-specific.mat-elevation-z7{box-shadow:0 4px 5px -2px #0003,0 7px 10px 1px #00000024,0 2px 16px 1px #0000001f}.mat-elevation-z8,.mat-mdc-elevation-specific.mat-elevation-z8{box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.mat-elevation-z9,.mat-mdc-elevation-specific.mat-elevation-z9{box-shadow:0 5px 6px -3px #0003,0 9px 12px 1px #00000024,0 3px 16px 2px #0000001f}.mat-elevation-z10,.mat-mdc-elevation-specific.mat-elevation-z10{box-shadow:0 6px 6px -3px #0003,0 10px 14px 1px #00000024,0 4px 18px 3px #0000001f}.mat-elevation-z11,.mat-mdc-elevation-specific.mat-elevation-z11{box-shadow:0 6px 7px -4px #0003,0 11px 15px 1px #00000024,0 4px 20px 3px #0000001f}.mat-elevation-z12,.mat-mdc-elevation-specific.mat-elevation-z12{box-shadow:0 7px 8px -4px #0003,0 12px 17px 2px #00000024,0 5px 22px 4px #0000001f}.mat-elevation-z13,.mat-mdc-elevation-specific.mat-elevation-z13{box-shadow:0 7px 8px -4px #0003,0 13px 19px 2px #00000024,0 5px 24px 4px #0000001f}.mat-elevation-z14,.mat-mdc-elevation-specific.mat-elevation-z14{box-shadow:0 7px 9px -4px #0003,0 14px 21px 2px #00000024,0 5px 26px 4px #0000001f}.mat-elevation-z15,.mat-mdc-elevation-specific.mat-elevation-z15{box-shadow:0 8px 9px -5px #0003,0 15px 22px 2px #00000024,0 6px 28px 5px #0000001f}.mat-elevation-z16,.mat-mdc-elevation-specific.mat-elevation-z16{box-shadow:0 8px 10px -5px #0003,0 16px 24px 2px #00000024,0 6px 30px 5px #0000001f}.mat-elevation-z17,.mat-mdc-elevation-specific.mat-elevation-z17{box-shadow:0 8px 11px -5px #0003,0 17px 26px 2px #00000024,0 6px 32px 5px #0000001f}.mat-elevation-z18,.mat-mdc-elevation-specific.mat-elevation-z18{box-shadow:0 9px 11px -5px #0003,0 18px 28px 2px #00000024,0 7px 34px 6px #0000001f}.mat-elevation-z19,.mat-mdc-elevation-specific.mat-elevation-z19{box-shadow:0 9px 12px -6px #0003,0 19px 29px 2px #00000024,0 7px 36px 6px #0000001f}.mat-elevation-z20,.mat-mdc-elevation-specific.mat-elevation-z20{box-shadow:0 10px 13px -6px #0003,0 20px 31px 3px #00000024,0 8px 38px 7px #0000001f}.mat-elevation-z21,.mat-mdc-elevation-specific.mat-elevation-z21{box-shadow:0 10px 13px -6px #0003,0 21px 33px 3px #00000024,0 8px 40px 7px #0000001f}.mat-elevation-z22,.mat-mdc-elevation-specific.mat-elevation-z22{box-shadow:0 10px 14px -6px #0003,0 22px 35px 3px #00000024,0 8px 42px 7px #0000001f}.mat-elevation-z23,.mat-mdc-elevation-specific.mat-elevation-z23{box-shadow:0 11px 14px -7px #0003,0 23px 36px 3px #00000024,0 9px 44px 8px #0000001f}.mat-elevation-z24,.mat-mdc-elevation-specific.mat-elevation-z24{box-shadow:0 11px 15px -7px #0003,0 24px 38px 3px #00000024,0 9px 46px 8px #0000001f}.mat-theme-loaded-marker{display:none}html{--mat-option-label-text-font: Roboto, sans-serif;--mat-option-label-text-line-height: 24px;--mat-option-label-text-size: 16px;--mat-option-label-text-tracking: .03125em;--mat-option-label-text-weight: 400}html{--mat-optgroup-label-text-font: Roboto, sans-serif;--mat-optgroup-label-text-line-height: 24px;--mat-optgroup-label-text-size: 16px;--mat-optgroup-label-text-tracking: .03125em;--mat-optgroup-label-text-weight: 400}html{--mdc-elevated-card-container-shape: 4px;--mdc-outlined-card-container-shape: 4px;--mdc-outlined-card-outline-width: 1px}html{--mdc-elevated-card-container-color: white;--mdc-elevated-card-container-elevation: 0px 2px 1px -1px rgba(0, 0, 0, .2), 0px 1px 1px 0px rgba(0, 0, 0, .14), 0px 1px 3px 0px rgba(0, 0, 0, .12);--mdc-outlined-card-container-color: white;--mdc-outlined-card-outline-color: rgba(0, 0, 0, .12);--mdc-outlined-card-container-elevation: 0px 0px 0px 0px rgba(0, 0, 0, .2), 0px 0px 0px 0px rgba(0, 0, 0, .14), 0px 0px 0px 0px rgba(0, 0, 0, .12);--mat-card-subtitle-text-color: rgba(0, 0, 0, .54)}html{--mat-card-title-text-font: Roboto, sans-serif;--mat-card-title-text-line-height: 32px;--mat-card-title-text-size: 20px;--mat-card-title-text-tracking: .0125em;--mat-card-title-text-weight: 500;--mat-card-subtitle-text-font: Roboto, sans-serif;--mat-card-subtitle-text-line-height: 22px;--mat-card-subtitle-text-size: 14px;--mat-card-subtitle-text-tracking: .0071428571em;--mat-card-subtitle-text-weight: 500}html{--mdc-linear-progress-active-indicator-height: 4px;--mdc-linear-progress-track-height: 4px;--mdc-linear-progress-track-shape: 0}.mat-mdc-progress-bar{--mdc-linear-progress-active-indicator-color: #3f51b5;--mdc-linear-progress-track-color: rgba(63, 81, 181, .25)}.mat-mdc-progress-bar .mdc-linear-progress__buffer-dots{background-color:#3f51b540;background-color:var(--mdc-linear-progress-track-color, rgba(63, 81, 181, .25))}@media (forced-colors: active){.mat-mdc-progress-bar .mdc-linear-progress__buffer-dots{background-color:ButtonBorder}}@media all and (-ms-high-contrast: none),(-ms-high-contrast: active){.mat-mdc-progress-bar .mdc-linear-progress__buffer-dots{background-color:transparent;background-image:url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' enable-background='new 0 0 5 2' xml:space='preserve' viewBox='0 0 5 2' preserveAspectRatio='none slice'%3E%3Ccircle cx='1' cy='1' r='1' fill='rgba(63, 81, 181, 0.25)'/%3E%3C/svg%3E")}}.mat-mdc-progress-bar .mdc-linear-progress__buffer-bar{background-color:#3f51b540;background-color:var(--mdc-linear-progress-track-color, rgba(63, 81, 181, .25))}.mat-mdc-progress-bar.mat-accent{--mdc-linear-progress-active-indicator-color: #ff4081;--mdc-linear-progress-track-color: rgba(255, 64, 129, .25)}.mat-mdc-progress-bar.mat-accent .mdc-linear-progress__buffer-dots{background-color:#ff408140;background-color:var(--mdc-linear-progress-track-color, rgba(255, 64, 129, .25))}@media (forced-colors: active){.mat-mdc-progress-bar.mat-accent .mdc-linear-progress__buffer-dots{background-color:ButtonBorder}}@media all and (-ms-high-contrast: none),(-ms-high-contrast: active){.mat-mdc-progress-bar.mat-accent .mdc-linear-progress__buffer-dots{background-color:transparent;background-image:url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' enable-background='new 0 0 5 2' xml:space='preserve' viewBox='0 0 5 2' preserveAspectRatio='none slice'%3E%3Ccircle cx='1' cy='1' r='1' fill='rgba(255, 64, 129, 0.25)'/%3E%3C/svg%3E")}}.mat-mdc-progress-bar.mat-accent .mdc-linear-progress__buffer-bar{background-color:#ff408140;background-color:var(--mdc-linear-progress-track-color, rgba(255, 64, 129, .25))}.mat-mdc-progress-bar.mat-warn{--mdc-linear-progress-active-indicator-color: #f44336;--mdc-linear-progress-track-color: rgba(244, 67, 54, .25)}@keyframes mdc-linear-progress-buffering{}.mat-mdc-progress-bar.mat-warn .mdc-linear-progress__buffer-dots{background-color:#f4433640;background-color:var(--mdc-linear-progress-track-color, rgba(244, 67, 54, .25))}@media (forced-colors: active){.mat-mdc-progress-bar.mat-warn .mdc-linear-progress__buffer-dots{background-color:ButtonBorder}}@media all and (-ms-high-contrast: none),(-ms-high-contrast: active){.mat-mdc-progress-bar.mat-warn .mdc-linear-progress__buffer-dots{background-color:transparent;background-image:url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' enable-background='new 0 0 5 2' xml:space='preserve' viewBox='0 0 5 2' preserveAspectRatio='none slice'%3E%3Ccircle cx='1' cy='1' r='1' fill='rgba(244, 67, 54, 0.25)'/%3E%3C/svg%3E")}}.mat-mdc-progress-bar.mat-warn .mdc-linear-progress__buffer-bar{background-color:#f4433640;background-color:var(--mdc-linear-progress-track-color, rgba(244, 67, 54, .25))}html{--mdc-plain-tooltip-container-shape: 4px;--mdc-plain-tooltip-supporting-text-line-height: 16px}html{--mdc-plain-tooltip-container-color: #616161;--mdc-plain-tooltip-supporting-text-color: #fff}html{--mdc-plain-tooltip-supporting-text-font: Roboto, sans-serif;--mdc-plain-tooltip-supporting-text-size: 12px;--mdc-plain-tooltip-supporting-text-weight: 400;--mdc-plain-tooltip-supporting-text-tracking: .0333333333em}html{--mdc-filled-text-field-active-indicator-height: 1px;--mdc-filled-text-field-focus-active-indicator-height: 2px;--mdc-filled-text-field-container-shape: 4px;--mdc-outlined-text-field-outline-width: 1px;--mdc-outlined-text-field-focus-outline-width: 2px;--mdc-outlined-text-field-container-shape: 4px}html{--mdc-filled-text-field-caret-color: #3f51b5;--mdc-filled-text-field-focus-active-indicator-color: #3f51b5;--mdc-filled-text-field-focus-label-text-color: rgba(63, 81, 181, .87);--mdc-filled-text-field-container-color: whitesmoke;--mdc-filled-text-field-disabled-container-color: #fafafa;--mdc-filled-text-field-label-text-color: rgba(0, 0, 0, .6);--mdc-filled-text-field-disabled-label-text-color: rgba(0, 0, 0, .38);--mdc-filled-text-field-input-text-color: rgba(0, 0, 0, .87);--mdc-filled-text-field-disabled-input-text-color: rgba(0, 0, 0, .38);--mdc-filled-text-field-input-text-placeholder-color: rgba(0, 0, 0, .6);--mdc-filled-text-field-error-focus-label-text-color: #f44336;--mdc-filled-text-field-error-label-text-color: #f44336;--mdc-filled-text-field-error-caret-color: #f44336;--mdc-filled-text-field-active-indicator-color: rgba(0, 0, 0, .42);--mdc-filled-text-field-disabled-active-indicator-color: rgba(0, 0, 0, .06);--mdc-filled-text-field-hover-active-indicator-color: rgba(0, 0, 0, .87);--mdc-filled-text-field-error-active-indicator-color: #f44336;--mdc-filled-text-field-error-focus-active-indicator-color: #f44336;--mdc-filled-text-field-error-hover-active-indicator-color: #f44336;--mdc-outlined-text-field-caret-color: #3f51b5;--mdc-outlined-text-field-focus-outline-color: #3f51b5;--mdc-outlined-text-field-focus-label-text-color: rgba(63, 81, 181, .87);--mdc-outlined-text-field-label-text-color: rgba(0, 0, 0, .6);--mdc-outlined-text-field-disabled-label-text-color: rgba(0, 0, 0, .38);--mdc-outlined-text-field-input-text-color: rgba(0, 0, 0, .87);--mdc-outlined-text-field-disabled-input-text-color: rgba(0, 0, 0, .38);--mdc-outlined-text-field-input-text-placeholder-color: rgba(0, 0, 0, .6);--mdc-outlined-text-field-error-caret-color: #f44336;--mdc-outlined-text-field-error-focus-label-text-color: #f44336;--mdc-outlined-text-field-error-label-text-color: #f44336;--mdc-outlined-text-field-outline-color: rgba(0, 0, 0, .38);--mdc-outlined-text-field-disabled-outline-color: rgba(0, 0, 0, .06);--mdc-outlined-text-field-hover-outline-color: rgba(0, 0, 0, .87);--mdc-outlined-text-field-error-focus-outline-color: #f44336;--mdc-outlined-text-field-error-hover-outline-color: #f44336;--mdc-outlined-text-field-error-outline-color: #f44336;--mat-form-field-focus-select-arrow-color: rgba(63, 81, 181, .87);--mat-form-field-disabled-input-text-placeholder-color: rgba(0, 0, 0, .38);--mat-form-field-state-layer-color: rgba(0, 0, 0, .87);--mat-form-field-error-text-color: #f44336;--mat-form-field-select-option-text-color: inherit;--mat-form-field-select-disabled-option-text-color: GrayText;--mat-form-field-enabled-select-arrow-color: rgba(0, 0, 0, .54);--mat-form-field-disabled-select-arrow-color: rgba(0, 0, 0, .38);--mat-form-field-hover-state-layer-opacity: .04;--mat-form-field-focus-state-layer-opacity: .12}.mat-mdc-form-field.mat-accent{--mdc-filled-text-field-caret-color: #ff4081;--mdc-filled-text-field-focus-active-indicator-color: #ff4081;--mdc-filled-text-field-focus-label-text-color: rgba(255, 64, 129, .87);--mdc-outlined-text-field-caret-color: #ff4081;--mdc-outlined-text-field-focus-outline-color: #ff4081;--mdc-outlined-text-field-focus-label-text-color: rgba(255, 64, 129, .87);--mat-form-field-focus-select-arrow-color: rgba(255, 64, 129, .87)}.mat-mdc-form-field.mat-warn{--mdc-filled-text-field-caret-color: #f44336;--mdc-filled-text-field-focus-active-indicator-color: #f44336;--mdc-filled-text-field-focus-label-text-color: rgba(244, 67, 54, .87);--mdc-outlined-text-field-caret-color: #f44336;--mdc-outlined-text-field-focus-outline-color: #f44336;--mdc-outlined-text-field-focus-label-text-color: rgba(244, 67, 54, .87);--mat-form-field-focus-select-arrow-color: rgba(244, 67, 54, .87)}.mat-mdc-form-field-infix{min-height:56px}.mat-mdc-text-field-wrapper .mat-mdc-form-field-flex .mat-mdc-floating-label{top:28px}.mat-mdc-text-field-wrapper.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{--mat-mdc-form-field-label-transform: translateY( -34.75px) scale(var(--mat-mdc-form-field-floating-label-scale, .75));transform:var(--mat-mdc-form-field-label-transform)}.mat-mdc-text-field-wrapper.mdc-text-field--outlined .mat-mdc-form-field-infix{padding-top:16px;padding-bottom:16px}.mat-mdc-text-field-wrapper:not(.mdc-text-field--outlined) .mat-mdc-form-field-infix{padding-top:24px;padding-bottom:8px}.mdc-text-field--no-label:not(.mdc-text-field--outlined):not(.mdc-text-field--textarea) .mat-mdc-form-field-infix{padding-top:16px;padding-bottom:16px}html{--mdc-filled-text-field-label-text-font: Roboto, sans-serif;--mdc-filled-text-field-label-text-size: 16px;--mdc-filled-text-field-label-text-tracking: .03125em;--mdc-filled-text-field-label-text-weight: 400;--mdc-outlined-text-field-label-text-font: Roboto, sans-serif;--mdc-outlined-text-field-label-text-size: 16px;--mdc-outlined-text-field-label-text-tracking: .03125em;--mdc-outlined-text-field-label-text-weight: 400;--mat-form-field-container-text-font: Roboto, sans-serif;--mat-form-field-container-text-line-height: 24px;--mat-form-field-container-text-size: 16px;--mat-form-field-container-text-tracking: .03125em;--mat-form-field-container-text-weight: 400;--mat-form-field-outlined-label-text-populated-size: 16px;--mat-form-field-subscript-text-font: Roboto, sans-serif;--mat-form-field-subscript-text-line-height: 20px;--mat-form-field-subscript-text-size: 12px;--mat-form-field-subscript-text-tracking: .0333333333em;--mat-form-field-subscript-text-weight: 400}html{--mat-select-panel-background-color: white;--mat-select-enabled-trigger-text-color: rgba(0, 0, 0, .87);--mat-select-disabled-trigger-text-color: rgba(0, 0, 0, .38);--mat-select-placeholder-text-color: rgba(0, 0, 0, .6);--mat-select-enabled-arrow-color: rgba(0, 0, 0, .54);--mat-select-disabled-arrow-color: rgba(0, 0, 0, .38);--mat-select-focused-arrow-color: rgba(63, 81, 181, .87);--mat-select-invalid-arrow-color: rgba(244, 67, 54, .87)}html .mat-mdc-form-field.mat-accent{--mat-select-panel-background-color: white;--mat-select-enabled-trigger-text-color: rgba(0, 0, 0, .87);--mat-select-disabled-trigger-text-color: rgba(0, 0, 0, .38);--mat-select-placeholder-text-color: rgba(0, 0, 0, .6);--mat-select-enabled-arrow-color: rgba(0, 0, 0, .54);--mat-select-disabled-arrow-color: rgba(0, 0, 0, .38);--mat-select-focused-arrow-color: rgba(255, 64, 129, .87);--mat-select-invalid-arrow-color: rgba(244, 67, 54, .87)}html .mat-mdc-form-field.mat-warn{--mat-select-panel-background-color: white;--mat-select-enabled-trigger-text-color: rgba(0, 0, 0, .87);--mat-select-disabled-trigger-text-color: rgba(0, 0, 0, .38);--mat-select-placeholder-text-color: rgba(0, 0, 0, .6);--mat-select-enabled-arrow-color: rgba(0, 0, 0, .54);--mat-select-disabled-arrow-color: rgba(0, 0, 0, .38);--mat-select-focused-arrow-color: rgba(244, 67, 54, .87);--mat-select-invalid-arrow-color: rgba(244, 67, 54, .87)}html{--mat-select-trigger-text-font: Roboto, sans-serif;--mat-select-trigger-text-line-height: 24px;--mat-select-trigger-text-size: 16px;--mat-select-trigger-text-tracking: .03125em;--mat-select-trigger-text-weight: 400}html{--mat-autocomplete-background-color: white}html{--mdc-dialog-container-elevation-shadow: 0px 11px 15px -7px rgba(0, 0, 0, .2), 0px 24px 38px 3px rgba(0, 0, 0, .14), 0px 9px 46px 8px rgba(0, 0, 0, .12);--mdc-dialog-container-shadow-color: #000;--mdc-dialog-container-shape: 4px}html{--mdc-dialog-container-color: white;--mdc-dialog-subhead-color: rgba(0, 0, 0, .87);--mdc-dialog-supporting-text-color: rgba(0, 0, 0, .6)}html{--mdc-dialog-subhead-font: Roboto, sans-serif;--mdc-dialog-subhead-line-height: 32px;--mdc-dialog-subhead-size: 20px;--mdc-dialog-subhead-weight: 500;--mdc-dialog-subhead-tracking: .0125em;--mdc-dialog-supporting-text-font: Roboto, sans-serif;--mdc-dialog-supporting-text-line-height: 24px;--mdc-dialog-supporting-text-size: 16px;--mdc-dialog-supporting-text-weight: 400;--mdc-dialog-supporting-text-tracking: .03125em}.mat-mdc-standard-chip{--mdc-chip-container-shape-family: rounded;--mdc-chip-container-shape-radius: 16px 16px 16px 16px;--mdc-chip-with-avatar-avatar-shape-family: rounded;--mdc-chip-with-avatar-avatar-shape-radius: 14px 14px 14px 14px;--mdc-chip-with-avatar-avatar-size: 28px;--mdc-chip-with-icon-icon-size: 18px}.mat-mdc-standard-chip{--mdc-chip-disabled-label-text-color: #212121;--mdc-chip-elevated-container-color: #e0e0e0;--mdc-chip-elevated-disabled-container-color: #e0e0e0;--mdc-chip-focus-state-layer-color: black;--mdc-chip-focus-state-layer-opacity: .12;--mdc-chip-label-text-color: #212121;--mdc-chip-with-icon-icon-color: #212121;--mdc-chip-with-icon-disabled-icon-color: #212121;--mdc-chip-with-icon-selected-icon-color: #212121;--mdc-chip-with-trailing-icon-disabled-trailing-icon-color: #212121;--mdc-chip-with-trailing-icon-trailing-icon-color: #212121}.mat-mdc-standard-chip.mat-mdc-chip-selected.mat-primary,.mat-mdc-standard-chip.mat-mdc-chip-highlighted.mat-primary{--mdc-chip-disabled-label-text-color: white;--mdc-chip-elevated-container-color: #3f51b5;--mdc-chip-elevated-disabled-container-color: #3f51b5;--mdc-chip-focus-state-layer-color: black;--mdc-chip-focus-state-layer-opacity: .12;--mdc-chip-label-text-color: white;--mdc-chip-with-icon-icon-color: white;--mdc-chip-with-icon-disabled-icon-color: white;--mdc-chip-with-icon-selected-icon-color: white;--mdc-chip-with-trailing-icon-disabled-trailing-icon-color: white;--mdc-chip-with-trailing-icon-trailing-icon-color: white}.mat-mdc-standard-chip.mat-mdc-chip-selected.mat-accent,.mat-mdc-standard-chip.mat-mdc-chip-highlighted.mat-accent{--mdc-chip-disabled-label-text-color: white;--mdc-chip-elevated-container-color: #ff4081;--mdc-chip-elevated-disabled-container-color: #ff4081;--mdc-chip-focus-state-layer-color: black;--mdc-chip-focus-state-layer-opacity: .12;--mdc-chip-label-text-color: white;--mdc-chip-with-icon-icon-color: white;--mdc-chip-with-icon-disabled-icon-color: white;--mdc-chip-with-icon-selected-icon-color: white;--mdc-chip-with-trailing-icon-disabled-trailing-icon-color: white;--mdc-chip-with-trailing-icon-trailing-icon-color: white}.mat-mdc-standard-chip.mat-mdc-chip-selected.mat-warn,.mat-mdc-standard-chip.mat-mdc-chip-highlighted.mat-warn{--mdc-chip-disabled-label-text-color: white;--mdc-chip-elevated-container-color: #f44336;--mdc-chip-elevated-disabled-container-color: #f44336;--mdc-chip-focus-state-layer-color: black;--mdc-chip-focus-state-layer-opacity: .12;--mdc-chip-label-text-color: white;--mdc-chip-with-icon-icon-color: white;--mdc-chip-with-icon-disabled-icon-color: white;--mdc-chip-with-icon-selected-icon-color: white;--mdc-chip-with-trailing-icon-disabled-trailing-icon-color: white;--mdc-chip-with-trailing-icon-trailing-icon-color: white}.mat-mdc-chip.mat-mdc-standard-chip{--mdc-chip-container-height: 32px}.mat-mdc-standard-chip{--mdc-chip-label-text-font: Roboto, sans-serif;--mdc-chip-label-text-line-height: 20px;--mdc-chip-label-text-size: 14px;--mdc-chip-label-text-tracking: .0178571429em;--mdc-chip-label-text-weight: 400}.mdc-switch{--mdc-switch-disabled-handle-opacity: .38;--mdc-switch-disabled-selected-icon-opacity: .38;--mdc-switch-disabled-track-opacity: .12;--mdc-switch-disabled-unselected-icon-opacity: .38;--mdc-switch-handle-height: 20px;--mdc-switch-handle-shape: 10px;--mdc-switch-handle-width: 20px;--mdc-switch-selected-icon-size: 18px;--mdc-switch-track-height: 14px;--mdc-switch-track-shape: 7px;--mdc-switch-track-width: 36px;--mdc-switch-unselected-icon-size: 18px;--mdc-switch-state-layer-size: 40px;--mdc-switch-selected-focus-state-layer-opacity: .12;--mdc-switch-selected-hover-state-layer-opacity: .04;--mdc-switch-selected-pressed-state-layer-opacity: .1;--mdc-switch-unselected-focus-state-layer-opacity: .12;--mdc-switch-unselected-hover-state-layer-opacity: .04;--mdc-switch-unselected-pressed-state-layer-opacity: .1}.mat-mdc-slide-toggle{--mdc-switch-selected-focus-state-layer-color: #3949ab;--mdc-switch-selected-handle-color: #3949ab;--mdc-switch-selected-hover-state-layer-color: #3949ab;--mdc-switch-selected-pressed-state-layer-color: #3949ab;--mdc-switch-selected-focus-handle-color: #1a237e;--mdc-switch-selected-hover-handle-color: #1a237e;--mdc-switch-selected-pressed-handle-color: #1a237e;--mdc-switch-selected-focus-track-color: #7986cb;--mdc-switch-selected-hover-track-color: #7986cb;--mdc-switch-selected-pressed-track-color: #7986cb;--mdc-switch-selected-track-color: #7986cb;--mdc-switch-disabled-selected-handle-color: #424242;--mdc-switch-disabled-selected-icon-color: #fff;--mdc-switch-disabled-selected-track-color: #424242;--mdc-switch-disabled-unselected-handle-color: #424242;--mdc-switch-disabled-unselected-icon-color: #fff;--mdc-switch-disabled-unselected-track-color: #424242;--mdc-switch-handle-surface-color: var(--mdc-theme-surface, #fff);--mdc-switch-handle-elevation-shadow: 0px 2px 1px -1px rgba(0, 0, 0, .2), 0px 1px 1px 0px rgba(0, 0, 0, .14), 0px 1px 3px 0px rgba(0, 0, 0, .12);--mdc-switch-handle-shadow-color: black;--mdc-switch-disabled-handle-elevation-shadow: 0px 0px 0px 0px rgba(0, 0, 0, .2), 0px 0px 0px 0px rgba(0, 0, 0, .14), 0px 0px 0px 0px rgba(0, 0, 0, .12);--mdc-switch-selected-icon-color: #fff;--mdc-switch-unselected-focus-handle-color: #212121;--mdc-switch-unselected-focus-state-layer-color: #424242;--mdc-switch-unselected-focus-track-color: #e0e0e0;--mdc-switch-unselected-handle-color: #616161;--mdc-switch-unselected-hover-handle-color: #212121;--mdc-switch-unselected-hover-state-layer-color: #424242;--mdc-switch-unselected-hover-track-color: #e0e0e0;--mdc-switch-unselected-icon-color: #fff;--mdc-switch-unselected-pressed-handle-color: #212121;--mdc-switch-unselected-pressed-state-layer-color: #424242;--mdc-switch-unselected-pressed-track-color: #e0e0e0;--mdc-switch-unselected-track-color: #e0e0e0}.mat-mdc-slide-toggle .mdc-form-field{color:var(--mdc-theme-text-primary-on-background, rgba(0, 0, 0, .87))}.mat-mdc-slide-toggle .mdc-switch--disabled+label{color:#00000061}.mat-mdc-slide-toggle.mat-accent{--mdc-switch-selected-focus-state-layer-color: #d81b60;--mdc-switch-selected-handle-color: #d81b60;--mdc-switch-selected-hover-state-layer-color: #d81b60;--mdc-switch-selected-pressed-state-layer-color: #d81b60;--mdc-switch-selected-focus-handle-color: #880e4f;--mdc-switch-selected-hover-handle-color: #880e4f;--mdc-switch-selected-pressed-handle-color: #880e4f;--mdc-switch-selected-focus-track-color: #f06292;--mdc-switch-selected-hover-track-color: #f06292;--mdc-switch-selected-pressed-track-color: #f06292;--mdc-switch-selected-track-color: #f06292}.mat-mdc-slide-toggle.mat-warn{--mdc-switch-selected-focus-state-layer-color: #e53935;--mdc-switch-selected-handle-color: #e53935;--mdc-switch-selected-hover-state-layer-color: #e53935;--mdc-switch-selected-pressed-state-layer-color: #e53935;--mdc-switch-selected-focus-handle-color: #b71c1c;--mdc-switch-selected-hover-handle-color: #b71c1c;--mdc-switch-selected-pressed-handle-color: #b71c1c;--mdc-switch-selected-focus-track-color: #e57373;--mdc-switch-selected-hover-track-color: #e57373;--mdc-switch-selected-pressed-track-color: #e57373;--mdc-switch-selected-track-color: #e57373}.mat-mdc-slide-toggle{--mdc-switch-state-layer-size: 48px}.mat-mdc-slide-toggle{--mat-slide-toggle-label-text-font: Roboto, sans-serif;--mat-slide-toggle-label-text-size: 14px;--mat-slide-toggle-label-text-tracking: .0178571429em;--mat-slide-toggle-label-text-line-height: 20px;--mat-slide-toggle-label-text-weight: 400}.mat-mdc-slide-toggle .mdc-form-field{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Roboto,sans-serif;font-family:var(--mdc-typography-body2-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:.875rem;font-size:var(--mdc-typography-body2-font-size, .875rem);line-height:1.25rem;line-height:var(--mdc-typography-body2-line-height, 1.25rem);font-weight:400;font-weight:var(--mdc-typography-body2-font-weight, 400);letter-spacing:.0178571429em;letter-spacing:var(--mdc-typography-body2-letter-spacing, .0178571429em);text-decoration:inherit;text-decoration:var(--mdc-typography-body2-text-decoration, inherit);text-transform:inherit;text-transform:var(--mdc-typography-body2-text-transform, inherit)}html{--mdc-radio-disabled-selected-icon-opacity: .38;--mdc-radio-disabled-unselected-icon-opacity: .38;--mdc-radio-state-layer-size: 40px}.mat-mdc-radio-button .mdc-form-field{color:var(--mdc-theme-text-primary-on-background, rgba(0, 0, 0, .87))}.mat-mdc-radio-button.mat-primary{--mdc-radio-disabled-selected-icon-color: #000;--mdc-radio-disabled-unselected-icon-color: #000;--mdc-radio-unselected-hover-icon-color: #212121;--mdc-radio-unselected-icon-color: rgba(0, 0, 0, .54);--mdc-radio-unselected-pressed-icon-color: rgba(0, 0, 0, .54);--mdc-radio-selected-focus-icon-color: #3f51b5;--mdc-radio-selected-hover-icon-color: #3f51b5;--mdc-radio-selected-icon-color: #3f51b5;--mdc-radio-selected-pressed-icon-color: #3f51b5;--mat-radio-ripple-color: #000;--mat-radio-checked-ripple-color: #3f51b5;--mat-radio-disabled-label-color: rgba(0, 0, 0, .38)}.mat-mdc-radio-button.mat-accent{--mdc-radio-disabled-selected-icon-color: #000;--mdc-radio-disabled-unselected-icon-color: #000;--mdc-radio-unselected-hover-icon-color: #212121;--mdc-radio-unselected-icon-color: rgba(0, 0, 0, .54);--mdc-radio-unselected-pressed-icon-color: rgba(0, 0, 0, .54);--mdc-radio-selected-focus-icon-color: #ff4081;--mdc-radio-selected-hover-icon-color: #ff4081;--mdc-radio-selected-icon-color: #ff4081;--mdc-radio-selected-pressed-icon-color: #ff4081;--mat-radio-ripple-color: #000;--mat-radio-checked-ripple-color: #ff4081;--mat-radio-disabled-label-color: rgba(0, 0, 0, .38)}.mat-mdc-radio-button.mat-warn{--mdc-radio-disabled-selected-icon-color: #000;--mdc-radio-disabled-unselected-icon-color: #000;--mdc-radio-unselected-hover-icon-color: #212121;--mdc-radio-unselected-icon-color: rgba(0, 0, 0, .54);--mdc-radio-unselected-pressed-icon-color: rgba(0, 0, 0, .54);--mdc-radio-selected-focus-icon-color: #f44336;--mdc-radio-selected-hover-icon-color: #f44336;--mdc-radio-selected-icon-color: #f44336;--mdc-radio-selected-pressed-icon-color: #f44336;--mat-radio-ripple-color: #000;--mat-radio-checked-ripple-color: #f44336;--mat-radio-disabled-label-color: rgba(0, 0, 0, .38)}html{--mdc-radio-state-layer-size: 40px}.mat-mdc-radio-button .mdc-form-field{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:var(--mdc-typography-body2-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:var(--mdc-typography-body2-font-size, 14px);line-height:var(--mdc-typography-body2-line-height, 20px);font-weight:var(--mdc-typography-body2-font-weight, 400);letter-spacing:var(--mdc-typography-body2-letter-spacing, .0178571429em);text-decoration:var(--mdc-typography-body2-text-decoration, inherit);text-transform:var(--mdc-typography-body2-text-transform, none)}html{--mdc-slider-active-track-height: 6px;--mdc-slider-active-track-shape: 9999px;--mdc-slider-handle-height: 20px;--mdc-slider-handle-shape: 50%;--mdc-slider-handle-width: 20px;--mdc-slider-inactive-track-height: 4px;--mdc-slider-inactive-track-shape: 9999px;--mdc-slider-with-overlap-handle-outline-width: 1px;--mdc-slider-with-tick-marks-active-container-opacity: .6;--mdc-slider-with-tick-marks-container-shape: 50%;--mdc-slider-with-tick-marks-container-size: 2px;--mdc-slider-with-tick-marks-inactive-container-opacity: .6}html{--mdc-slider-handle-color: #3f51b5;--mdc-slider-focus-handle-color: #3f51b5;--mdc-slider-hover-handle-color: #3f51b5;--mdc-slider-active-track-color: #3f51b5;--mdc-slider-inactive-track-color: #3f51b5;--mdc-slider-with-tick-marks-inactive-container-color: #3f51b5;--mdc-slider-with-tick-marks-active-container-color: white;--mdc-slider-disabled-active-track-color: #000;--mdc-slider-disabled-handle-color: #000;--mdc-slider-disabled-inactive-track-color: #000;--mdc-slider-label-container-color: #000;--mdc-slider-label-label-text-color: #fff;--mdc-slider-with-overlap-handle-outline-color: #fff;--mdc-slider-with-tick-marks-disabled-container-color: #000;--mdc-slider-handle-elevation: 0px 2px 1px -1px rgba(0, 0, 0, .2), 0px 1px 1px 0px rgba(0, 0, 0, .14), 0px 1px 3px 0px rgba(0, 0, 0, .12);--mat-mdc-slider-ripple-color: #3f51b5;--mat-mdc-slider-hover-ripple-color: rgba(63, 81, 181, .05);--mat-mdc-slider-focus-ripple-color: rgba(63, 81, 181, .2);--mat-slider-value-indicator-opacity: .6}html .mat-accent{--mdc-slider-handle-color: #ff4081;--mdc-slider-focus-handle-color: #ff4081;--mdc-slider-hover-handle-color: #ff4081;--mdc-slider-active-track-color: #ff4081;--mdc-slider-inactive-track-color: #ff4081;--mdc-slider-with-tick-marks-inactive-container-color: #ff4081;--mdc-slider-with-tick-marks-active-container-color: white;--mat-mdc-slider-ripple-color: #ff4081;--mat-mdc-slider-hover-ripple-color: rgba(255, 64, 129, .05);--mat-mdc-slider-focus-ripple-color: rgba(255, 64, 129, .2)}html .mat-warn{--mdc-slider-handle-color: #f44336;--mdc-slider-focus-handle-color: #f44336;--mdc-slider-hover-handle-color: #f44336;--mdc-slider-active-track-color: #f44336;--mdc-slider-inactive-track-color: #f44336;--mdc-slider-with-tick-marks-inactive-container-color: #f44336;--mdc-slider-with-tick-marks-active-container-color: white;--mat-mdc-slider-ripple-color: #f44336;--mat-mdc-slider-hover-ripple-color: rgba(244, 67, 54, .05);--mat-mdc-slider-focus-ripple-color: rgba(244, 67, 54, .2)}html{--mdc-slider-label-label-text-font: Roboto, sans-serif;--mdc-slider-label-label-text-size: 14px;--mdc-slider-label-label-text-line-height: 22px;--mdc-slider-label-label-text-tracking: .0071428571em;--mdc-slider-label-label-text-weight: 500}html{--mat-menu-container-shape: 4px}html{--mat-menu-item-label-text-color: rgba(0, 0, 0, .87);--mat-menu-item-icon-color: rgba(0, 0, 0, .87);--mat-menu-item-hover-state-layer-color: rgba(0, 0, 0, .04);--mat-menu-item-focus-state-layer-color: rgba(0, 0, 0, .04);--mat-menu-container-color: white}html{--mat-menu-item-label-text-font: Roboto, sans-serif;--mat-menu-item-label-text-size: 16px;--mat-menu-item-label-text-tracking: .03125em;--mat-menu-item-label-text-line-height: 24px;--mat-menu-item-label-text-weight: 400}html{--mdc-list-list-item-container-shape: 0;--mdc-list-list-item-leading-avatar-shape: 50%;--mdc-list-list-item-container-color: transparent;--mdc-list-list-item-selected-container-color: transparent;--mdc-list-list-item-leading-avatar-color: transparent;--mdc-list-list-item-leading-icon-size: 24px;--mdc-list-list-item-leading-avatar-size: 40px;--mdc-list-list-item-trailing-icon-size: 24px;--mdc-list-list-item-disabled-state-layer-color: transparent;--mdc-list-list-item-disabled-state-layer-opacity: 0;--mdc-list-list-item-disabled-label-text-opacity: .38;--mdc-list-list-item-disabled-leading-icon-opacity: .38;--mdc-list-list-item-disabled-trailing-icon-opacity: .38}html{--mdc-list-list-item-label-text-color: rgba(0, 0, 0, .87);--mdc-list-list-item-supporting-text-color: rgba(0, 0, 0, .54);--mdc-list-list-item-leading-icon-color: rgba(0, 0, 0, .38);--mdc-list-list-item-trailing-supporting-text-color: rgba(0, 0, 0, .38);--mdc-list-list-item-trailing-icon-color: rgba(0, 0, 0, .38);--mdc-list-list-item-selected-trailing-icon-color: rgba(0, 0, 0, .38);--mdc-list-list-item-disabled-label-text-color: black;--mdc-list-list-item-disabled-leading-icon-color: black;--mdc-list-list-item-disabled-trailing-icon-color: black;--mdc-list-list-item-hover-label-text-color: rgba(0, 0, 0, .87);--mdc-list-list-item-hover-leading-icon-color: rgba(0, 0, 0, .38);--mdc-list-list-item-hover-trailing-icon-color: rgba(0, 0, 0, .38);--mdc-list-list-item-focus-label-text-color: rgba(0, 0, 0, .87);--mdc-list-list-item-hover-state-layer-color: black;--mdc-list-list-item-hover-state-layer-opacity: .04;--mdc-list-list-item-focus-state-layer-color: black;--mdc-list-list-item-focus-state-layer-opacity: .12}.mdc-list-item__start,.mdc-list-item__end{--mdc-radio-disabled-selected-icon-color: #000;--mdc-radio-disabled-unselected-icon-color: #000;--mdc-radio-unselected-hover-icon-color: #212121;--mdc-radio-unselected-icon-color: rgba(0, 0, 0, .54);--mdc-radio-unselected-pressed-icon-color: rgba(0, 0, 0, .54);--mdc-radio-selected-focus-icon-color: #3f51b5;--mdc-radio-selected-hover-icon-color: #3f51b5;--mdc-radio-selected-icon-color: #3f51b5;--mdc-radio-selected-pressed-icon-color: #3f51b5}.mat-accent .mdc-list-item__start,.mat-accent .mdc-list-item__end{--mdc-radio-disabled-selected-icon-color: #000;--mdc-radio-disabled-unselected-icon-color: #000;--mdc-radio-unselected-hover-icon-color: #212121;--mdc-radio-unselected-icon-color: rgba(0, 0, 0, .54);--mdc-radio-unselected-pressed-icon-color: rgba(0, 0, 0, .54);--mdc-radio-selected-focus-icon-color: #ff4081;--mdc-radio-selected-hover-icon-color: #ff4081;--mdc-radio-selected-icon-color: #ff4081;--mdc-radio-selected-pressed-icon-color: #ff4081}.mat-warn .mdc-list-item__start,.mat-warn .mdc-list-item__end{--mdc-radio-disabled-selected-icon-color: #000;--mdc-radio-disabled-unselected-icon-color: #000;--mdc-radio-unselected-hover-icon-color: #212121;--mdc-radio-unselected-icon-color: rgba(0, 0, 0, .54);--mdc-radio-unselected-pressed-icon-color: rgba(0, 0, 0, .54);--mdc-radio-selected-focus-icon-color: #f44336;--mdc-radio-selected-hover-icon-color: #f44336;--mdc-radio-selected-icon-color: #f44336;--mdc-radio-selected-pressed-icon-color: #f44336}.mat-mdc-list-option{--mdc-checkbox-disabled-selected-icon-color: rgba(0, 0, 0, .38);--mdc-checkbox-disabled-unselected-icon-color: rgba(0, 0, 0, .38);--mdc-checkbox-selected-checkmark-color: #fff;--mdc-checkbox-selected-focus-icon-color: #3f51b5;--mdc-checkbox-selected-hover-icon-color: #3f51b5;--mdc-checkbox-selected-icon-color: #3f51b5;--mdc-checkbox-selected-pressed-icon-color: #3f51b5;--mdc-checkbox-unselected-focus-icon-color: #212121;--mdc-checkbox-unselected-hover-icon-color: #212121;--mdc-checkbox-unselected-icon-color: rgba(0, 0, 0, .54);--mdc-checkbox-unselected-pressed-icon-color: rgba(0, 0, 0, .54);--mdc-checkbox-selected-focus-state-layer-color: #3f51b5;--mdc-checkbox-selected-hover-state-layer-color: #3f51b5;--mdc-checkbox-selected-pressed-state-layer-color: #3f51b5;--mdc-checkbox-unselected-focus-state-layer-color: black;--mdc-checkbox-unselected-hover-state-layer-color: black;--mdc-checkbox-unselected-pressed-state-layer-color: black}.mat-mdc-list-option.mat-accent{--mdc-checkbox-disabled-selected-icon-color: rgba(0, 0, 0, .38);--mdc-checkbox-disabled-unselected-icon-color: rgba(0, 0, 0, .38);--mdc-checkbox-selected-checkmark-color: #fff;--mdc-checkbox-selected-focus-icon-color: #ff4081;--mdc-checkbox-selected-hover-icon-color: #ff4081;--mdc-checkbox-selected-icon-color: #ff4081;--mdc-checkbox-selected-pressed-icon-color: #ff4081;--mdc-checkbox-unselected-focus-icon-color: #212121;--mdc-checkbox-unselected-hover-icon-color: #212121;--mdc-checkbox-unselected-icon-color: rgba(0, 0, 0, .54);--mdc-checkbox-unselected-pressed-icon-color: rgba(0, 0, 0, .54);--mdc-checkbox-selected-focus-state-layer-color: #ff4081;--mdc-checkbox-selected-hover-state-layer-color: #ff4081;--mdc-checkbox-selected-pressed-state-layer-color: #ff4081;--mdc-checkbox-unselected-focus-state-layer-color: black;--mdc-checkbox-unselected-hover-state-layer-color: black;--mdc-checkbox-unselected-pressed-state-layer-color: black}.mat-mdc-list-option.mat-warn{--mdc-checkbox-disabled-selected-icon-color: rgba(0, 0, 0, .38);--mdc-checkbox-disabled-unselected-icon-color: rgba(0, 0, 0, .38);--mdc-checkbox-selected-checkmark-color: #fff;--mdc-checkbox-selected-focus-icon-color: #f44336;--mdc-checkbox-selected-hover-icon-color: #f44336;--mdc-checkbox-selected-icon-color: #f44336;--mdc-checkbox-selected-pressed-icon-color: #f44336;--mdc-checkbox-unselected-focus-icon-color: #212121;--mdc-checkbox-unselected-hover-icon-color: #212121;--mdc-checkbox-unselected-icon-color: rgba(0, 0, 0, .54);--mdc-checkbox-unselected-pressed-icon-color: rgba(0, 0, 0, .54);--mdc-checkbox-selected-focus-state-layer-color: #f44336;--mdc-checkbox-selected-hover-state-layer-color: #f44336;--mdc-checkbox-selected-pressed-state-layer-color: #f44336;--mdc-checkbox-unselected-focus-state-layer-color: black;--mdc-checkbox-unselected-hover-state-layer-color: black;--mdc-checkbox-unselected-pressed-state-layer-color: black}.mat-mdc-list-base.mat-mdc-list-base .mdc-list-item--selected .mdc-list-item__primary-text,.mat-mdc-list-base.mat-mdc-list-base .mdc-list-item--activated .mdc-list-item__primary-text,.mat-mdc-list-base.mat-mdc-list-base .mdc-list-item--selected.mdc-list-item--with-leading-icon .mdc-list-item__start,.mat-mdc-list-base.mat-mdc-list-base .mdc-list-item--activated.mdc-list-item--with-leading-icon .mdc-list-item__start{color:#3f51b5}.mat-mdc-list-base .mdc-list-item--disabled .mdc-list-item__start,.mat-mdc-list-base .mdc-list-item--disabled .mdc-list-item__content,.mat-mdc-list-base .mdc-list-item--disabled .mdc-list-item__end{opacity:1}html{--mdc-list-list-item-one-line-container-height: 48px;--mdc-list-list-item-two-line-container-height: 64px;--mdc-list-list-item-three-line-container-height: 88px}.mdc-list-item__start,.mdc-list-item__end{--mdc-radio-state-layer-size: 40px}.mat-mdc-list-item.mdc-list-item--with-leading-avatar.mdc-list-item--with-one-line,.mat-mdc-list-item.mdc-list-item--with-leading-checkbox.mdc-list-item--with-one-line,.mat-mdc-list-item.mdc-list-item--with-leading-icon.mdc-list-item--with-one-line{height:56px}.mat-mdc-list-item.mdc-list-item--with-leading-avatar.mdc-list-item--with-two-lines,.mat-mdc-list-item.mdc-list-item--with-leading-checkbox.mdc-list-item--with-two-lines,.mat-mdc-list-item.mdc-list-item--with-leading-icon.mdc-list-item--with-two-lines{height:72px}html{--mdc-list-list-item-label-text-font: Roboto, sans-serif;--mdc-list-list-item-label-text-line-height: 24px;--mdc-list-list-item-label-text-size: 16px;--mdc-list-list-item-label-text-tracking: .03125em;--mdc-list-list-item-label-text-weight: 400;--mdc-list-list-item-supporting-text-font: Roboto, sans-serif;--mdc-list-list-item-supporting-text-line-height: 20px;--mdc-list-list-item-supporting-text-size: 14px;--mdc-list-list-item-supporting-text-tracking: .0178571429em;--mdc-list-list-item-supporting-text-weight: 400;--mdc-list-list-item-trailing-supporting-text-font: Roboto, sans-serif;--mdc-list-list-item-trailing-supporting-text-line-height: 20px;--mdc-list-list-item-trailing-supporting-text-size: 12px;--mdc-list-list-item-trailing-supporting-text-tracking: .0333333333em;--mdc-list-list-item-trailing-supporting-text-weight: 400}.mdc-list-group__subheader{font:400 16px/28px Roboto,sans-serif;letter-spacing:.009375em}html{--mat-paginator-container-text-color: rgba(0, 0, 0, .87);--mat-paginator-container-background-color: white;--mat-paginator-enabled-icon-color: rgba(0, 0, 0, .54);--mat-paginator-disabled-icon-color: rgba(0, 0, 0, .12)}html{--mat-paginator-container-size: 56px}.mat-mdc-paginator .mat-mdc-form-field-infix{min-height:40px}.mat-mdc-paginator .mat-mdc-text-field-wrapper .mat-mdc-form-field-flex .mat-mdc-floating-label{top:20px}.mat-mdc-paginator .mat-mdc-text-field-wrapper.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{--mat-mdc-form-field-label-transform: translateY( -26.75px) scale(var(--mat-mdc-form-field-floating-label-scale, .75));transform:var(--mat-mdc-form-field-label-transform)}.mat-mdc-paginator .mat-mdc-text-field-wrapper.mdc-text-field--outlined .mat-mdc-form-field-infix{padding-top:8px;padding-bottom:8px}.mat-mdc-paginator .mat-mdc-text-field-wrapper:not(.mdc-text-field--outlined) .mat-mdc-form-field-infix{padding-top:8px;padding-bottom:8px}.mat-mdc-paginator .mdc-text-field--no-label:not(.mdc-text-field--outlined):not(.mdc-text-field--textarea) .mat-mdc-form-field-infix{padding-top:8px;padding-bottom:8px}.mat-mdc-paginator .mat-mdc-text-field-wrapper:not(.mdc-text-field--outlined) .mat-mdc-floating-label{display:none}html{--mat-paginator-container-text-font: Roboto, sans-serif;--mat-paginator-container-text-line-height: 20px;--mat-paginator-container-text-size: 12px;--mat-paginator-container-text-tracking: .0333333333em;--mat-paginator-container-text-weight: 400;--mat-paginator-select-trigger-text-size: 12px}html{--mdc-tab-indicator-active-indicator-height: 2px;--mdc-tab-indicator-active-indicator-shape: 0;--mdc-secondary-navigation-tab-container-height: 48px}.mat-mdc-tab-group,.mat-mdc-tab-nav-bar{--mdc-tab-indicator-active-indicator-color: #3f51b5;--mat-tab-header-disabled-ripple-color: rgba(0, 0, 0, .38);--mat-tab-header-pagination-icon-color: #000;--mat-tab-header-inactive-label-text-color: rgba(0, 0, 0, .6);--mat-tab-header-active-label-text-color: #3f51b5;--mat-tab-header-active-ripple-color: #3f51b5;--mat-tab-header-inactive-ripple-color: #3f51b5;--mat-tab-header-inactive-focus-label-text-color: rgba(0, 0, 0, .6);--mat-tab-header-inactive-hover-label-text-color: rgba(0, 0, 0, .6);--mat-tab-header-active-focus-label-text-color: #3f51b5;--mat-tab-header-active-hover-label-text-color: #3f51b5;--mat-tab-header-active-focus-indicator-color: #3f51b5;--mat-tab-header-active-hover-indicator-color: #3f51b5}.mat-mdc-tab-group.mat-accent,.mat-mdc-tab-nav-bar.mat-accent{--mdc-tab-indicator-active-indicator-color: #ff4081;--mat-tab-header-disabled-ripple-color: rgba(0, 0, 0, .38);--mat-tab-header-pagination-icon-color: #000;--mat-tab-header-inactive-label-text-color: rgba(0, 0, 0, .6);--mat-tab-header-active-label-text-color: #ff4081;--mat-tab-header-active-ripple-color: #ff4081;--mat-tab-header-inactive-ripple-color: #ff4081;--mat-tab-header-inactive-focus-label-text-color: rgba(0, 0, 0, .6);--mat-tab-header-inactive-hover-label-text-color: rgba(0, 0, 0, .6);--mat-tab-header-active-focus-label-text-color: #ff4081;--mat-tab-header-active-hover-label-text-color: #ff4081;--mat-tab-header-active-focus-indicator-color: #ff4081;--mat-tab-header-active-hover-indicator-color: #ff4081}.mat-mdc-tab-group.mat-warn,.mat-mdc-tab-nav-bar.mat-warn{--mdc-tab-indicator-active-indicator-color: #f44336;--mat-tab-header-disabled-ripple-color: rgba(0, 0, 0, .38);--mat-tab-header-pagination-icon-color: #000;--mat-tab-header-inactive-label-text-color: rgba(0, 0, 0, .6);--mat-tab-header-active-label-text-color: #f44336;--mat-tab-header-active-ripple-color: #f44336;--mat-tab-header-inactive-ripple-color: #f44336;--mat-tab-header-inactive-focus-label-text-color: rgba(0, 0, 0, .6);--mat-tab-header-inactive-hover-label-text-color: rgba(0, 0, 0, .6);--mat-tab-header-active-focus-label-text-color: #f44336;--mat-tab-header-active-hover-label-text-color: #f44336;--mat-tab-header-active-focus-indicator-color: #f44336;--mat-tab-header-active-hover-indicator-color: #f44336}.mat-mdc-tab-group.mat-background-primary,.mat-mdc-tab-nav-bar.mat-background-primary{--mat-tab-header-with-background-background-color: #3f51b5;--mat-tab-header-with-background-foreground-color: white}.mat-mdc-tab-group.mat-background-accent,.mat-mdc-tab-nav-bar.mat-background-accent{--mat-tab-header-with-background-background-color: #ff4081;--mat-tab-header-with-background-foreground-color: white}.mat-mdc-tab-group.mat-background-warn,.mat-mdc-tab-nav-bar.mat-background-warn{--mat-tab-header-with-background-background-color: #f44336;--mat-tab-header-with-background-foreground-color: white}.mat-mdc-tab-header{--mdc-secondary-navigation-tab-container-height: 48px}.mat-mdc-tab-header{--mat-tab-header-label-text-font: Roboto, sans-serif;--mat-tab-header-label-text-size: 14px;--mat-tab-header-label-text-tracking: .0892857143em;--mat-tab-header-label-text-line-height: 36px;--mat-tab-header-label-text-weight: 500}html{--mdc-checkbox-disabled-selected-checkmark-color: #fff;--mdc-checkbox-selected-focus-state-layer-opacity: .16;--mdc-checkbox-selected-hover-state-layer-opacity: .04;--mdc-checkbox-selected-pressed-state-layer-opacity: .16;--mdc-checkbox-unselected-focus-state-layer-opacity: .16;--mdc-checkbox-unselected-hover-state-layer-opacity: .04;--mdc-checkbox-unselected-pressed-state-layer-opacity: .16}html{--mdc-checkbox-disabled-selected-icon-color: rgba(0, 0, 0, .38);--mdc-checkbox-disabled-unselected-icon-color: rgba(0, 0, 0, .38);--mdc-checkbox-selected-checkmark-color: #fff;--mdc-checkbox-selected-focus-icon-color: #ff4081;--mdc-checkbox-selected-hover-icon-color: #ff4081;--mdc-checkbox-selected-icon-color: #ff4081;--mdc-checkbox-selected-pressed-icon-color: #ff4081;--mdc-checkbox-unselected-focus-icon-color: #212121;--mdc-checkbox-unselected-hover-icon-color: #212121;--mdc-checkbox-unselected-icon-color: rgba(0, 0, 0, .54);--mdc-checkbox-unselected-pressed-icon-color: rgba(0, 0, 0, .54);--mdc-checkbox-selected-focus-state-layer-color: #ff4081;--mdc-checkbox-selected-hover-state-layer-color: #ff4081;--mdc-checkbox-selected-pressed-state-layer-color: #ff4081;--mdc-checkbox-unselected-focus-state-layer-color: black;--mdc-checkbox-unselected-hover-state-layer-color: black;--mdc-checkbox-unselected-pressed-state-layer-color: black}.mat-mdc-checkbox.mat-primary{--mdc-checkbox-disabled-selected-icon-color: rgba(0, 0, 0, .38);--mdc-checkbox-disabled-unselected-icon-color: rgba(0, 0, 0, .38);--mdc-checkbox-selected-checkmark-color: #fff;--mdc-checkbox-selected-focus-icon-color: #3f51b5;--mdc-checkbox-selected-hover-icon-color: #3f51b5;--mdc-checkbox-selected-icon-color: #3f51b5;--mdc-checkbox-selected-pressed-icon-color: #3f51b5;--mdc-checkbox-unselected-focus-icon-color: #212121;--mdc-checkbox-unselected-hover-icon-color: #212121;--mdc-checkbox-unselected-icon-color: rgba(0, 0, 0, .54);--mdc-checkbox-unselected-pressed-icon-color: rgba(0, 0, 0, .54);--mdc-checkbox-selected-focus-state-layer-color: #3f51b5;--mdc-checkbox-selected-hover-state-layer-color: #3f51b5;--mdc-checkbox-selected-pressed-state-layer-color: #3f51b5;--mdc-checkbox-unselected-focus-state-layer-color: black;--mdc-checkbox-unselected-hover-state-layer-color: black;--mdc-checkbox-unselected-pressed-state-layer-color: black}.mat-mdc-checkbox.mat-warn{--mdc-checkbox-disabled-selected-icon-color: rgba(0, 0, 0, .38);--mdc-checkbox-disabled-unselected-icon-color: rgba(0, 0, 0, .38);--mdc-checkbox-selected-checkmark-color: #fff;--mdc-checkbox-selected-focus-icon-color: #f44336;--mdc-checkbox-selected-hover-icon-color: #f44336;--mdc-checkbox-selected-icon-color: #f44336;--mdc-checkbox-selected-pressed-icon-color: #f44336;--mdc-checkbox-unselected-focus-icon-color: #212121;--mdc-checkbox-unselected-hover-icon-color: #212121;--mdc-checkbox-unselected-icon-color: rgba(0, 0, 0, .54);--mdc-checkbox-unselected-pressed-icon-color: rgba(0, 0, 0, .54);--mdc-checkbox-selected-focus-state-layer-color: #f44336;--mdc-checkbox-selected-hover-state-layer-color: #f44336;--mdc-checkbox-selected-pressed-state-layer-color: #f44336;--mdc-checkbox-unselected-focus-state-layer-color: black;--mdc-checkbox-unselected-hover-state-layer-color: black;--mdc-checkbox-unselected-pressed-state-layer-color: black}.mat-mdc-checkbox .mdc-form-field{color:var(--mdc-theme-text-primary-on-background, rgba(0, 0, 0, .87))}.mat-mdc-checkbox.mat-mdc-checkbox-disabled label{color:#00000061}html{--mdc-checkbox-state-layer-size: 40px}.mat-mdc-checkbox .mdc-form-field{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:var(--mdc-typography-body2-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:var(--mdc-typography-body2-font-size, 14px);line-height:var(--mdc-typography-body2-line-height, 20px);font-weight:var(--mdc-typography-body2-font-weight, 400);letter-spacing:var(--mdc-typography-body2-letter-spacing, .0178571429em);text-decoration:var(--mdc-typography-body2-text-decoration, inherit);text-transform:var(--mdc-typography-body2-text-transform, none)}.mat-mdc-button{--mdc-text-button-label-text-color: #000;--mdc-text-button-disabled-label-text-color: rgba(0, 0, 0, .38);--mat-text-button-state-layer-color: #000;--mat-text-button-ripple-color: rgba(0, 0, 0, .1);--mat-text-button-hover-state-layer-opacity: .04;--mat-text-button-focus-state-layer-opacity: .12;--mat-text-button-pressed-state-layer-opacity: .12}.mat-mdc-button.mat-primary{--mdc-text-button-label-text-color: #3f51b5;--mat-text-button-state-layer-color: #3f51b5;--mat-text-button-ripple-color: rgba(63, 81, 181, .1)}.mat-mdc-button.mat-accent{--mdc-text-button-label-text-color: #ff4081;--mat-text-button-state-layer-color: #ff4081;--mat-text-button-ripple-color: rgba(255, 64, 129, .1)}.mat-mdc-button.mat-warn{--mdc-text-button-label-text-color: #f44336;--mat-text-button-state-layer-color: #f44336;--mat-text-button-ripple-color: rgba(244, 67, 54, .1)}.mat-mdc-unelevated-button{--mdc-filled-button-container-color: white;--mdc-filled-button-label-text-color: #000;--mdc-filled-button-disabled-container-color: rgba(0, 0, 0, .12);--mdc-filled-button-disabled-label-text-color: rgba(0, 0, 0, .38);--mat-filled-button-state-layer-color: #000;--mat-filled-button-ripple-color: rgba(0, 0, 0, .1);--mat-filled-button-hover-state-layer-opacity: .04;--mat-filled-button-focus-state-layer-opacity: .12;--mat-filled-button-pressed-state-layer-opacity: .12}.mat-mdc-unelevated-button.mat-primary{--mdc-filled-button-container-color: #3f51b5;--mdc-filled-button-label-text-color: #fff;--mat-filled-button-state-layer-color: #fff;--mat-filled-button-ripple-color: rgba(255, 255, 255, .1)}.mat-mdc-unelevated-button.mat-accent{--mdc-filled-button-container-color: #ff4081;--mdc-filled-button-label-text-color: #fff;--mat-filled-button-state-layer-color: #fff;--mat-filled-button-ripple-color: rgba(255, 255, 255, .1)}.mat-mdc-unelevated-button.mat-warn{--mdc-filled-button-container-color: #f44336;--mdc-filled-button-label-text-color: #fff;--mat-filled-button-state-layer-color: #fff;--mat-filled-button-ripple-color: rgba(255, 255, 255, .1)}.mat-mdc-raised-button{--mdc-protected-button-container-color: white;--mdc-protected-button-label-text-color: #000;--mdc-protected-button-disabled-container-color: rgba(0, 0, 0, .12);--mdc-protected-button-disabled-label-text-color: rgba(0, 0, 0, .38);--mat-protected-button-state-layer-color: #000;--mat-protected-button-ripple-color: rgba(0, 0, 0, .1);--mat-protected-button-hover-state-layer-opacity: .04;--mat-protected-button-focus-state-layer-opacity: .12;--mat-protected-button-pressed-state-layer-opacity: .12;box-shadow:0 3px 1px -2px #0003,0 2px 2px #00000024,0 1px 5px #0000001f}.mat-mdc-raised-button.mat-primary{--mdc-protected-button-container-color: #3f51b5;--mdc-protected-button-label-text-color: #fff;--mat-protected-button-state-layer-color: #fff;--mat-protected-button-ripple-color: rgba(255, 255, 255, .1)}.mat-mdc-raised-button.mat-accent{--mdc-protected-button-container-color: #ff4081;--mdc-protected-button-label-text-color: #fff;--mat-protected-button-state-layer-color: #fff;--mat-protected-button-ripple-color: rgba(255, 255, 255, .1)}.mat-mdc-raised-button.mat-warn{--mdc-protected-button-container-color: #f44336;--mdc-protected-button-label-text-color: #fff;--mat-protected-button-state-layer-color: #fff;--mat-protected-button-ripple-color: rgba(255, 255, 255, .1)}.mat-mdc-raised-button:hover,.mat-mdc-raised-button:focus{box-shadow:0 2px 4px -1px #0003,0 4px 5px #00000024,0 1px 10px #0000001f}.mat-mdc-raised-button:active,.mat-mdc-raised-button:focus:active{box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.mat-mdc-outlined-button{--mdc-outlined-button-disabled-outline-color: rgba(0, 0, 0, .12);--mdc-outlined-button-disabled-label-text-color: rgba(0, 0, 0, .38);--mdc-outlined-button-label-text-color: #000;--mdc-outlined-button-outline-color: rgba(0, 0, 0, .12);--mat-outlined-button-state-layer-color: #000;--mat-outlined-button-ripple-color: rgba(0, 0, 0, .1);--mat-outlined-button-hover-state-layer-opacity: .04;--mat-outlined-button-focus-state-layer-opacity: .12;--mat-outlined-button-pressed-state-layer-opacity: .12}.mat-mdc-outlined-button.mat-primary{--mdc-outlined-button-label-text-color: #3f51b5;--mdc-outlined-button-outline-color: rgba(0, 0, 0, .12);--mat-outlined-button-state-layer-color: #3f51b5;--mat-outlined-button-ripple-color: rgba(63, 81, 181, .1)}.mat-mdc-outlined-button.mat-accent{--mdc-outlined-button-label-text-color: #ff4081;--mdc-outlined-button-outline-color: rgba(0, 0, 0, .12);--mat-outlined-button-state-layer-color: #ff4081;--mat-outlined-button-ripple-color: rgba(255, 64, 129, .1)}.mat-mdc-outlined-button.mat-warn{--mdc-outlined-button-label-text-color: #f44336;--mdc-outlined-button-outline-color: rgba(0, 0, 0, .12);--mat-outlined-button-state-layer-color: #f44336;--mat-outlined-button-ripple-color: rgba(244, 67, 54, .1)}.mat-mdc-button{--mdc-text-button-container-height: 36px}.mat-mdc-raised-button{--mdc-protected-button-container-height: 36px}.mat-mdc-unelevated-button{--mdc-filled-button-container-height: 36px}.mat-mdc-outlined-button{--mdc-outlined-button-container-height: 36px}.mdc-button{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:var(--mdc-typography-button-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:var(--mdc-typography-button-font-size, 14px);line-height:var(--mdc-typography-button-line-height, 36px);font-weight:var(--mdc-typography-button-font-weight, 500);letter-spacing:var(--mdc-typography-button-letter-spacing, .0892857143em);text-decoration:var(--mdc-typography-button-text-decoration, none);text-transform:var(--mdc-typography-button-text-transform, none)}.mat-mdc-raised-button{line-height:inherit}.mat-mdc-icon-button{--mdc-icon-button-icon-color: inherit;--mdc-icon-button-disabled-icon-color: rgba(0, 0, 0, .38);--mat-icon-button-state-layer-color: #000;--mat-icon-button-ripple-color: rgba(0, 0, 0, .1);--mat-icon-button-hover-state-layer-opacity: .04;--mat-icon-button-focus-state-layer-opacity: .12;--mat-icon-button-pressed-state-layer-opacity: .12}.mat-mdc-icon-button.mat-primary{--mdc-icon-button-icon-color: #3f51b5;--mat-icon-button-state-layer-color: #3f51b5;--mat-icon-button-ripple-color: rgba(63, 81, 181, .1)}.mat-mdc-icon-button.mat-accent{--mdc-icon-button-icon-color: #ff4081;--mat-icon-button-state-layer-color: #ff4081;--mat-icon-button-ripple-color: rgba(255, 64, 129, .1)}.mat-mdc-icon-button.mat-warn{--mdc-icon-button-icon-color: #f44336;--mat-icon-button-state-layer-color: #f44336;--mat-icon-button-ripple-color: rgba(244, 67, 54, .1)}.mat-mdc-icon-button.mat-mdc-button-base{--mdc-icon-button-state-layer-size: 48px;width:var(--mdc-icon-button-state-layer-size);height:var(--mdc-icon-button-state-layer-size);padding:12px}html{--mdc-fab-container-shape: 50%;--mdc-fab-icon-size: 24px}html{--mdc-fab-container-color: white;--mat-fab-foreground-color: black;--mat-fab-state-layer-color: #000;--mat-fab-ripple-color: rgba(0, 0, 0, .1);--mat-fab-hover-state-layer-opacity: .04;--mat-fab-focus-state-layer-opacity: .12;--mat-fab-pressed-state-layer-opacity: .12;--mat-fab-disabled-state-container-color: rgba(0, 0, 0, .12);--mat-fab-disabled-state-foreground-color: rgba(0, 0, 0, .38)}html .mat-mdc-fab.mat-primary,html .mat-mdc-mini-fab.mat-primary{--mdc-fab-container-color: #3f51b5;--mat-fab-foreground-color: #fff;--mat-fab-state-layer-color: #fff;--mat-fab-ripple-color: rgba(255, 255, 255, .1)}html .mat-mdc-fab.mat-accent,html .mat-mdc-mini-fab.mat-accent{--mdc-fab-container-color: #ff4081;--mat-fab-foreground-color: #fff;--mat-fab-state-layer-color: #fff;--mat-fab-ripple-color: rgba(255, 255, 255, .1)}html .mat-mdc-fab.mat-warn,html .mat-mdc-mini-fab.mat-warn{--mdc-fab-container-color: #f44336;--mat-fab-foreground-color: #fff;--mat-fab-state-layer-color: #fff;--mat-fab-ripple-color: rgba(255, 255, 255, .1)}.mdc-fab--extended{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:var(--mdc-typography-button-font-family, var(--mdc-typography-font-family, Roboto, sans-serif));font-size:var(--mdc-typography-button-font-size, 14px);line-height:var(--mdc-typography-button-line-height, 36px);font-weight:var(--mdc-typography-button-font-weight, 500);letter-spacing:var(--mdc-typography-button-letter-spacing, .0892857143em);text-decoration:var(--mdc-typography-button-text-decoration, none);text-transform:var(--mdc-typography-button-text-transform, none)}html{--mdc-extended-fab-label-text-font: Roboto, sans-serif;--mdc-extended-fab-label-text-size: 14px;--mdc-extended-fab-label-text-tracking: .0892857143em;--mdc-extended-fab-label-text-weight: 500}html{--mdc-snackbar-container-shape: 4px}html{--mdc-snackbar-container-color: #333333;--mdc-snackbar-supporting-text-color: rgba(255, 255, 255, .87);--mat-snack-bar-button-color: #ff4081}html{--mdc-snackbar-supporting-text-font: Roboto, sans-serif;--mdc-snackbar-supporting-text-line-height: 20px;--mdc-snackbar-supporting-text-size: 14px;--mdc-snackbar-supporting-text-weight: 400}html{--mat-table-row-item-outline-width: 1px}html{--mat-table-background-color: white;--mat-table-header-headline-color: rgba(0, 0, 0, .87);--mat-table-row-item-label-text-color: rgba(0, 0, 0, .87);--mat-table-row-item-outline-color: rgba(0, 0, 0, .12)}html{--mat-table-header-container-height: 56px;--mat-table-footer-container-height: 52px;--mat-table-row-item-container-height: 52px}html{--mat-table-header-headline-font: Roboto, sans-serif;--mat-table-header-headline-line-height: 22px;--mat-table-header-headline-size: 14px;--mat-table-header-headline-weight: 500;--mat-table-header-headline-tracking: .0071428571em;--mat-table-row-item-label-text-font: Roboto, sans-serif;--mat-table-row-item-label-text-line-height: 20px;--mat-table-row-item-label-text-size: 14px;--mat-table-row-item-label-text-weight: 400;--mat-table-row-item-label-text-tracking: .0178571429em;--mat-table-footer-supporting-text-font: Roboto, sans-serif;--mat-table-footer-supporting-text-line-height: 20px;--mat-table-footer-supporting-text-size: 14px;--mat-table-footer-supporting-text-weight: 400;--mat-table-footer-supporting-text-tracking: .0178571429em}html{--mdc-circular-progress-active-indicator-width: 4px;--mdc-circular-progress-size: 48px}html{--mdc-circular-progress-active-indicator-color: #3f51b5}html .mat-accent{--mdc-circular-progress-active-indicator-color: #ff4081}html .mat-warn{--mdc-circular-progress-active-indicator-color: #f44336}.mat-badge{position:relative}.mat-badge.mat-badge{overflow:visible}.mat-badge-content{position:absolute;text-align:center;display:inline-block;border-radius:50%;transition:transform .2s ease-in-out;transform:scale(.6);overflow:hidden;white-space:nowrap;text-overflow:ellipsis;pointer-events:none;background-color:var(--mat-badge-background-color);color:var(--mat-badge-text-color);font-family:Roboto,sans-serif;font-family:var(--mat-badge-text-font, Roboto, sans-serif);font-size:12px;font-size:var(--mat-badge-text-size, 12px);font-weight:600;font-weight:var(--mat-badge-text-weight, 600)}.cdk-high-contrast-active .mat-badge-content{outline:solid 1px;border-radius:0}.mat-badge-disabled .mat-badge-content{background-color:var(--mat-badge-disabled-state-background-color);color:var(--mat-badge-disabled-state-text-color)}.mat-badge-hidden .mat-badge-content{display:none}.ng-animate-disabled .mat-badge-content,.mat-badge-content._mat-animation-noopable{transition:none}.mat-badge-content.mat-badge-active{transform:none}.mat-badge-small .mat-badge-content{width:16px;height:16px;line-height:16px;font-size:9px;font-size:var(--mat-badge-small-size-text-size, 9px)}.mat-badge-small.mat-badge-above .mat-badge-content{top:-8px}.mat-badge-small.mat-badge-below .mat-badge-content{bottom:-8px}.mat-badge-small.mat-badge-before .mat-badge-content{left:-16px}[dir=rtl] .mat-badge-small.mat-badge-before .mat-badge-content{left:auto;right:-16px}.mat-badge-small.mat-badge-after .mat-badge-content{right:-16px}[dir=rtl] .mat-badge-small.mat-badge-after .mat-badge-content{right:auto;left:-16px}.mat-badge-small.mat-badge-overlap.mat-badge-before .mat-badge-content{left:-8px}[dir=rtl] .mat-badge-small.mat-badge-overlap.mat-badge-before .mat-badge-content{left:auto;right:-8px}.mat-badge-small.mat-badge-overlap.mat-badge-after .mat-badge-content{right:-8px}[dir=rtl] .mat-badge-small.mat-badge-overlap.mat-badge-after .mat-badge-content{right:auto;left:-8px}.mat-badge-medium .mat-badge-content{width:22px;height:22px;line-height:22px}.mat-badge-medium.mat-badge-above .mat-badge-content{top:-11px}.mat-badge-medium.mat-badge-below .mat-badge-content{bottom:-11px}.mat-badge-medium.mat-badge-before .mat-badge-content{left:-22px}[dir=rtl] .mat-badge-medium.mat-badge-before .mat-badge-content{left:auto;right:-22px}.mat-badge-medium.mat-badge-after .mat-badge-content{right:-22px}[dir=rtl] .mat-badge-medium.mat-badge-after .mat-badge-content{right:auto;left:-22px}.mat-badge-medium.mat-badge-overlap.mat-badge-before .mat-badge-content{left:-11px}[dir=rtl] .mat-badge-medium.mat-badge-overlap.mat-badge-before .mat-badge-content{left:auto;right:-11px}.mat-badge-medium.mat-badge-overlap.mat-badge-after .mat-badge-content{right:-11px}[dir=rtl] .mat-badge-medium.mat-badge-overlap.mat-badge-after .mat-badge-content{right:auto;left:-11px}.mat-badge-large .mat-badge-content{width:28px;height:28px;line-height:28px;font-size:24px;font-size:var(--mat-badge-large-size-text-size, 24px)}.mat-badge-large.mat-badge-above .mat-badge-content{top:-14px}.mat-badge-large.mat-badge-below .mat-badge-content{bottom:-14px}.mat-badge-large.mat-badge-before .mat-badge-content{left:-28px}[dir=rtl] .mat-badge-large.mat-badge-before .mat-badge-content{left:auto;right:-28px}.mat-badge-large.mat-badge-after .mat-badge-content{right:-28px}[dir=rtl] .mat-badge-large.mat-badge-after .mat-badge-content{right:auto;left:-28px}.mat-badge-large.mat-badge-overlap.mat-badge-before .mat-badge-content{left:-14px}[dir=rtl] .mat-badge-large.mat-badge-overlap.mat-badge-before .mat-badge-content{left:auto;right:-14px}.mat-badge-large.mat-badge-overlap.mat-badge-after .mat-badge-content{right:-14px}[dir=rtl] .mat-badge-large.mat-badge-overlap.mat-badge-after .mat-badge-content{right:auto;left:-14px}html{--mat-badge-background-color: #3f51b5;--mat-badge-text-color: white;--mat-badge-disabled-state-background-color: #b9b9b9;--mat-badge-disabled-state-text-color: rgba(0, 0, 0, .38)}.mat-badge-accent{--mat-badge-background-color: #ff4081;--mat-badge-text-color: white}.mat-badge-warn{--mat-badge-background-color: #f44336;--mat-badge-text-color: white}html{--mat-badge-text-font: Roboto, sans-serif;--mat-badge-text-size: 12px;--mat-badge-text-weight: 600;--mat-badge-small-size-text-size: 9px;--mat-badge-large-size-text-size: 24px}html{--mat-bottom-sheet-container-shape: 4px}html{--mat-bottom-sheet-container-text-color: rgba(0, 0, 0, .87);--mat-bottom-sheet-container-background-color: white}html{--mat-bottom-sheet-container-text-font: Roboto, sans-serif;--mat-bottom-sheet-container-text-line-height: 20px;--mat-bottom-sheet-container-text-size: 14px;--mat-bottom-sheet-container-text-tracking: .0178571429em;--mat-bottom-sheet-container-text-weight: 400}html{--mat-legacy-button-toggle-height: 36px;--mat-legacy-button-toggle-shape: 2px;--mat-legacy-button-toggle-focus-state-layer-opacity: 1;--mat-standard-button-toggle-shape: 4px;--mat-standard-button-toggle-hover-state-layer-opacity: .04;--mat-standard-button-toggle-focus-state-layer-opacity: .12}html{--mat-legacy-button-toggle-text-color: rgba(0, 0, 0, .38);--mat-legacy-button-toggle-state-layer-color: rgba(0, 0, 0, .12);--mat-legacy-button-toggle-selected-state-text-color: rgba(0, 0, 0, .54);--mat-legacy-button-toggle-selected-state-background-color: #e0e0e0;--mat-legacy-button-toggle-disabled-state-text-color: rgba(0, 0, 0, .26);--mat-legacy-button-toggle-disabled-state-background-color: #eeeeee;--mat-legacy-button-toggle-disabled-selected-state-background-color: #bdbdbd;--mat-standard-button-toggle-text-color: rgba(0, 0, 0, .87);--mat-standard-button-toggle-background-color: white;--mat-standard-button-toggle-state-layer-color: black;--mat-standard-button-toggle-selected-state-background-color: #e0e0e0;--mat-standard-button-toggle-selected-state-text-color: rgba(0, 0, 0, .87);--mat-standard-button-toggle-disabled-state-text-color: rgba(0, 0, 0, .26);--mat-standard-button-toggle-disabled-state-background-color: white;--mat-standard-button-toggle-disabled-selected-state-text-color: rgba(0, 0, 0, .87);--mat-standard-button-toggle-disabled-selected-state-background-color: #bdbdbd;--mat-standard-button-toggle-divider-color: #e0e0e0}html{--mat-standard-button-toggle-height: 48px}html{--mat-legacy-button-toggle-text-font: Roboto, sans-serif;--mat-standard-button-toggle-text-font: Roboto, sans-serif}html{--mat-datepicker-calendar-date-selected-state-text-color: white;--mat-datepicker-calendar-date-selected-state-background-color: #3f51b5;--mat-datepicker-calendar-date-selected-disabled-state-background-color: rgba(63, 81, 181, .4);--mat-datepicker-calendar-date-today-selected-state-outline-color: white;--mat-datepicker-calendar-date-focus-state-background-color: rgba(63, 81, 181, .3);--mat-datepicker-calendar-date-hover-state-background-color: rgba(63, 81, 181, .3);--mat-datepicker-toggle-active-state-icon-color: #3f51b5;--mat-datepicker-calendar-date-in-range-state-background-color: rgba(63, 81, 181, .2);--mat-datepicker-calendar-date-in-comparison-range-state-background-color: rgba(249, 171, 0, .2);--mat-datepicker-calendar-date-in-overlap-range-state-background-color: #a8dab5;--mat-datepicker-calendar-date-in-overlap-range-selected-state-background-color: #46a35e;--mat-datepicker-toggle-icon-color: rgba(0, 0, 0, .54);--mat-datepicker-calendar-body-label-text-color: rgba(0, 0, 0, .54);--mat-datepicker-calendar-period-button-icon-color: rgba(0, 0, 0, .54);--mat-datepicker-calendar-navigation-button-icon-color: rgba(0, 0, 0, .54);--mat-datepicker-calendar-header-divider-color: rgba(0, 0, 0, .12);--mat-datepicker-calendar-header-text-color: rgba(0, 0, 0, .54);--mat-datepicker-calendar-date-today-outline-color: rgba(0, 0, 0, .38);--mat-datepicker-calendar-date-today-disabled-state-outline-color: rgba(0, 0, 0, .18);--mat-datepicker-calendar-date-text-color: rgba(0, 0, 0, .87);--mat-datepicker-calendar-date-outline-color: transparent;--mat-datepicker-calendar-date-disabled-state-text-color: rgba(0, 0, 0, .38);--mat-datepicker-calendar-date-preview-state-outline-color: rgba(0, 0, 0, .24);--mat-datepicker-range-input-separator-color: rgba(0, 0, 0, .87);--mat-datepicker-range-input-disabled-state-separator-color: rgba(0, 0, 0, .38);--mat-datepicker-range-input-disabled-state-text-color: rgba(0, 0, 0, .38);--mat-datepicker-calendar-container-background-color: white;--mat-datepicker-calendar-container-text-color: rgba(0, 0, 0, .87)}.mat-datepicker-content.mat-accent{--mat-datepicker-calendar-date-selected-state-text-color: white;--mat-datepicker-calendar-date-selected-state-background-color: #ff4081;--mat-datepicker-calendar-date-selected-disabled-state-background-color: rgba(255, 64, 129, .4);--mat-datepicker-calendar-date-today-selected-state-outline-color: white;--mat-datepicker-calendar-date-focus-state-background-color: rgba(255, 64, 129, .3);--mat-datepicker-calendar-date-hover-state-background-color: rgba(255, 64, 129, .3);--mat-datepicker-calendar-date-in-range-state-background-color: rgba(255, 64, 129, .2);--mat-datepicker-calendar-date-in-comparison-range-state-background-color: rgba(249, 171, 0, .2);--mat-datepicker-calendar-date-in-overlap-range-state-background-color: #a8dab5;--mat-datepicker-calendar-date-in-overlap-range-selected-state-background-color: #46a35e}.mat-datepicker-content.mat-warn{--mat-datepicker-calendar-date-selected-state-text-color: white;--mat-datepicker-calendar-date-selected-state-background-color: #f44336;--mat-datepicker-calendar-date-selected-disabled-state-background-color: rgba(244, 67, 54, .4);--mat-datepicker-calendar-date-today-selected-state-outline-color: white;--mat-datepicker-calendar-date-focus-state-background-color: rgba(244, 67, 54, .3);--mat-datepicker-calendar-date-hover-state-background-color: rgba(244, 67, 54, .3);--mat-datepicker-calendar-date-in-range-state-background-color: rgba(244, 67, 54, .2);--mat-datepicker-calendar-date-in-comparison-range-state-background-color: rgba(249, 171, 0, .2);--mat-datepicker-calendar-date-in-overlap-range-state-background-color: #a8dab5;--mat-datepicker-calendar-date-in-overlap-range-selected-state-background-color: #46a35e}.mat-datepicker-toggle-active.mat-accent{--mat-datepicker-toggle-active-state-icon-color: #ff4081}.mat-datepicker-toggle-active.mat-warn{--mat-datepicker-toggle-active-state-icon-color: #f44336}.mat-calendar-controls .mat-mdc-icon-button.mat-mdc-button-base{--mdc-icon-button-state-layer-size: 40px;width:var(--mdc-icon-button-state-layer-size);height:var(--mdc-icon-button-state-layer-size);padding:8px}.mat-calendar-controls .mat-mdc-icon-button.mat-mdc-button-base .mat-mdc-button-touch-target{display:none}html{--mat-datepicker-calendar-text-font: Roboto, sans-serif;--mat-datepicker-calendar-text-size: 13px;--mat-datepicker-calendar-body-label-text-size: 14px;--mat-datepicker-calendar-body-label-text-weight: 500;--mat-datepicker-calendar-period-button-text-size: 14px;--mat-datepicker-calendar-period-button-text-weight: 500;--mat-datepicker-calendar-header-text-size: 11px;--mat-datepicker-calendar-header-text-weight: 400}html{--mat-divider-width: 1px}html{--mat-divider-color: rgba(0, 0, 0, .12)}html{--mat-expansion-container-shape: 4px}html{--mat-expansion-container-background-color: white;--mat-expansion-container-text-color: rgba(0, 0, 0, .87);--mat-expansion-actions-divider-color: rgba(0, 0, 0, .12);--mat-expansion-header-hover-state-layer-color: rgba(0, 0, 0, .04);--mat-expansion-header-focus-state-layer-color: rgba(0, 0, 0, .04);--mat-expansion-header-disabled-state-text-color: rgba(0, 0, 0, .26);--mat-expansion-header-text-color: rgba(0, 0, 0, .87);--mat-expansion-header-description-color: rgba(0, 0, 0, .54);--mat-expansion-header-indicator-color: rgba(0, 0, 0, .54)}html{--mat-expansion-header-collapsed-state-height: 48px;--mat-expansion-header-expanded-state-height: 64px}html{--mat-expansion-header-text-font: Roboto, sans-serif;--mat-expansion-header-text-size: 14px;--mat-expansion-header-text-weight: 500;--mat-expansion-header-text-line-height: inherit;--mat-expansion-header-text-tracking: inherit;--mat-expansion-container-text-font: Roboto, sans-serif;--mat-expansion-container-text-line-height: 20px;--mat-expansion-container-text-size: 14px;--mat-expansion-container-text-tracking: .0178571429em;--mat-expansion-container-text-weight: 400}html{--mat-grid-list-tile-header-primary-text-size: 14px;--mat-grid-list-tile-header-secondary-text-size: 12px;--mat-grid-list-tile-footer-primary-text-size: 14px;--mat-grid-list-tile-footer-secondary-text-size: 12px}html{--mat-icon-color: inherit}.mat-icon.mat-primary{--mat-icon-color: #3f51b5}.mat-icon.mat-accent{--mat-icon-color: #ff4081}.mat-icon.mat-warn{--mat-icon-color: #f44336}html{--mat-sidenav-container-shape: 0}html{--mat-sidenav-container-divider-color: rgba(0, 0, 0, .12);--mat-sidenav-container-background-color: white;--mat-sidenav-container-text-color: rgba(0, 0, 0, .87);--mat-sidenav-content-background-color: #fafafa;--mat-sidenav-content-text-color: rgba(0, 0, 0, .87);--mat-sidenav-scrim-color: rgba(0, 0, 0, .6)}html{--mat-stepper-header-icon-foreground-color: white;--mat-stepper-header-selected-state-icon-background-color: #3f51b5;--mat-stepper-header-selected-state-icon-foreground-color: white;--mat-stepper-header-done-state-icon-background-color: #3f51b5;--mat-stepper-header-done-state-icon-foreground-color: white;--mat-stepper-header-edit-state-icon-background-color: #3f51b5;--mat-stepper-header-edit-state-icon-foreground-color: white;--mat-stepper-container-color: white;--mat-stepper-line-color: rgba(0, 0, 0, .12);--mat-stepper-header-hover-state-layer-color: rgba(0, 0, 0, .04);--mat-stepper-header-focus-state-layer-color: rgba(0, 0, 0, .04);--mat-stepper-header-label-text-color: rgba(0, 0, 0, .54);--mat-stepper-header-optional-label-text-color: rgba(0, 0, 0, .54);--mat-stepper-header-selected-state-label-text-color: rgba(0, 0, 0, .87);--mat-stepper-header-error-state-label-text-color: #f44336;--mat-stepper-header-icon-background-color: rgba(0, 0, 0, .54);--mat-stepper-header-error-state-icon-foreground-color: #f44336;--mat-stepper-header-error-state-icon-background-color: transparent}html .mat-step-header.mat-accent{--mat-stepper-header-icon-foreground-color: white;--mat-stepper-header-selected-state-icon-background-color: #ff4081;--mat-stepper-header-selected-state-icon-foreground-color: white;--mat-stepper-header-done-state-icon-background-color: #ff4081;--mat-stepper-header-done-state-icon-foreground-color: white;--mat-stepper-header-edit-state-icon-background-color: #ff4081;--mat-stepper-header-edit-state-icon-foreground-color: white}html .mat-step-header.mat-warn{--mat-stepper-header-icon-foreground-color: white;--mat-stepper-header-selected-state-icon-background-color: #f44336;--mat-stepper-header-selected-state-icon-foreground-color: white;--mat-stepper-header-done-state-icon-background-color: #f44336;--mat-stepper-header-done-state-icon-foreground-color: white;--mat-stepper-header-edit-state-icon-background-color: #f44336;--mat-stepper-header-edit-state-icon-foreground-color: white}html{--mat-stepper-header-height: 72px}html{--mat-stepper-container-text-font: Roboto, sans-serif;--mat-stepper-header-label-text-font: Roboto, sans-serif;--mat-stepper-header-label-text-size: 14px;--mat-stepper-header-label-text-weight: 400;--mat-stepper-header-error-state-label-text-size: 16px;--mat-stepper-header-selected-state-label-text-size: 16px;--mat-stepper-header-selected-state-label-text-weight: 400}html{--mat-sort-arrow-color: #757575}html{--mat-toolbar-container-background-color: whitesmoke;--mat-toolbar-container-text-color: rgba(0, 0, 0, .87)}.mat-toolbar.mat-primary{--mat-toolbar-container-background-color: #3f51b5;--mat-toolbar-container-text-color: white}.mat-toolbar.mat-accent{--mat-toolbar-container-background-color: #ff4081;--mat-toolbar-container-text-color: white}.mat-toolbar.mat-warn{--mat-toolbar-container-background-color: #f44336;--mat-toolbar-container-text-color: white}html{--mat-toolbar-standard-height: 64px;--mat-toolbar-mobile-height: 56px}html{--mat-toolbar-title-text-font: Roboto, sans-serif;--mat-toolbar-title-text-line-height: 32px;--mat-toolbar-title-text-size: 20px;--mat-toolbar-title-text-tracking: .0125em;--mat-toolbar-title-text-weight: 500}html{--mat-tree-container-background-color: white;--mat-tree-node-text-color: rgba(0, 0, 0, .87)}html{--mat-tree-node-min-height: 48px}html{--mat-tree-node-text-font: Roboto, sans-serif;--mat-tree-node-text-size: 14px;--mat-tree-node-text-weight: 400} 2 | -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | projects: ['/projects/ngx-reactive-storage/jest.config.ts'] 3 | }; 4 | -------------------------------------------------------------------------------- /logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 97 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-reactive-storage", 3 | "version": "2.0.1", 4 | "license": "MIT", 5 | "author": { 6 | "name": "Evgeniy OZ", 7 | "email": "normandiggs@gmail.com", 8 | "url": "https://jamm.dev" 9 | }, 10 | "repository": { 11 | "url": "git+https://github.com/e-oz/ngx-reactive-storage.git" 12 | }, 13 | "keywords": [ 14 | "angular", 15 | "reactive", 16 | "storage", 17 | "indexeddb", 18 | "localstorage" 19 | ], 20 | "scripts": { 21 | "ng": "ng", 22 | "build": "npx ng build ngx-reactive-storage", 23 | "test": "npx jest", 24 | "pub": "npm run pre && npm publish ./dist/ngx-reactive-storage", 25 | "pub-next": "npm run pre && npm publish ./dist/ngx-reactive-storage --tag next", 26 | "pre": "npm i && npx ng build ngx-reactive-storage && cp ./README.md ./dist/ngx-reactive-storage/README.md && npx jest --clearCache && npm run test && npm publish ./dist/ngx-reactive-storage --dry-run", 27 | "reinst": "rm -rf node_modules && rm -f package-lock.json && rm -rf dist && npm i && npm run pre" 28 | }, 29 | "private": false, 30 | "dependencies": { 31 | "@angular/common": "^20.0.1", 32 | "@angular/cdk": "^20.0.2", 33 | "@angular/core": "^20.0.1", 34 | "@angular/material": "^20.0.2", 35 | "@angular/platform-browser": "^20.0.1", 36 | "localforage": "^1.10.0", 37 | "rxjs": "^7.8.2" 38 | }, 39 | "devDependencies": { 40 | "@angular-devkit/build-angular": "^20.0.1", 41 | "@angular/compiler": "^20.0.1", 42 | "@angular/compiler-cli": "^20.0.1", 43 | "@angular/platform-browser-dynamic": "^20.0.1", 44 | "@types/jest": "^29.5.14", 45 | "fake-indexeddb": "^6.0.1", 46 | "jest": "^29.7.0", 47 | "jest-preset-angular": "^14.6.0", 48 | "ng-packagr": "^20.0.0", 49 | "ts-node": "^10.9.2", 50 | "typescript": "~5.8.3", 51 | "zone.js": "~0.15.1" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /projects/docs/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | Toggle me! 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | Expand me! 15 | 16 |

Magic of Reactive Storage!

17 |
18 | 19 |
20 | -------------------------------------------------------------------------------- /projects/docs/src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: flex; 3 | flex-flow: column; 4 | gap: 1em; 5 | padding: 1em; 6 | } 7 | -------------------------------------------------------------------------------- /projects/docs/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { FormsModule } from "@angular/forms"; 3 | import { MatExpansionModule } from "@angular/material/expansion"; 4 | import { MatSlideToggleModule } from "@angular/material/slide-toggle"; 5 | import { MatSliderModule } from "@angular/material/slider"; 6 | import { RxStorage } from "@oz/reactive-storage"; 7 | 8 | @Component({ 9 | selector: 'app-root', 10 | standalone: true, 11 | imports: [ 12 | MatSlideToggleModule, 13 | MatSliderModule, 14 | FormsModule, 15 | MatExpansionModule, 16 | ], 17 | templateUrl: './app.component.html', 18 | styleUrl: './app.component.scss', 19 | changeDetection: ChangeDetectionStrategy.OnPush 20 | }) 21 | export class AppComponent { 22 | protected readonly storage = new RxStorage('example', 'ngx-reactive-storage'); 23 | protected readonly $toggle = this.storage.getWritableSignal('toggle', { initialValue: true }); 24 | protected readonly $slider = this.storage.getWritableSignal('slider', { initialValue: 50 }); 25 | protected readonly $expanded = this.storage.getWritableSignal('expanded'); 26 | } 27 | -------------------------------------------------------------------------------- /projects/docs/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/e-oz/ngx-reactive-storage/d0db398aeb3ad637c78858b8731764135658e799/projects/docs/src/assets/.gitkeep -------------------------------------------------------------------------------- /projects/docs/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/e-oz/ngx-reactive-storage/d0db398aeb3ad637c78858b8731764135658e799/projects/docs/src/favicon.ico -------------------------------------------------------------------------------- /projects/docs/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Reactive Storage 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /projects/docs/src/main.ts: -------------------------------------------------------------------------------- 1 | import { bootstrapApplication } from '@angular/platform-browser'; 2 | import { provideAnimations } from "@angular/platform-browser/animations"; 3 | import { AppComponent } from './app/app.component'; 4 | 5 | bootstrapApplication(AppComponent, { 6 | providers: [ 7 | provideAnimations(), 8 | ] 9 | }).catch((err) => console.error(err)); 10 | -------------------------------------------------------------------------------- /projects/docs/src/styles.scss: -------------------------------------------------------------------------------- 1 | // Custom Theming for Angular Material 2 | // For more information: https://material.angular.io/guide/theming 3 | @use '@angular/material' as mat; 4 | // Plus imports for other components in your app. 5 | 6 | // Include the common styles for Angular Material. We include this here so that you only 7 | // have to load a single css file for Angular Material in your app. 8 | // Be sure that you only ever include this mixin once! 9 | @include mat.core(); 10 | 11 | // Define the palettes for your theme using the Material Design palettes available in palette.scss 12 | // (imported above). For each palette, you can optionally specify a default, lighter, and darker 13 | // hue. Available color palettes: https://material.io/design/color/ 14 | $theme-primary: mat.define-palette(mat.$indigo-palette); 15 | $theme-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400); 16 | 17 | // The warn palette is optional (defaults to red). 18 | $theme-warn: mat.define-palette(mat.$red-palette); 19 | 20 | // Create the theme object. A theme consists of configurations for individual 21 | // theming systems such as "color" or "typography". 22 | $theme: mat.define-light-theme(( 23 | color: ( 24 | primary: $theme-primary, 25 | accent: $theme-accent, 26 | warn: $theme-warn, 27 | ), 28 | typography: mat.define-typography-config(), 29 | )); 30 | 31 | // Include theme styles for core and each component used in your app. 32 | // Alternatively, you can import and @include the theme mixins for each component 33 | // that you are using. 34 | @include mat.all-component-themes($theme); 35 | -------------------------------------------------------------------------------- /projects/docs/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "../../tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "../../out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "src/main.ts" 10 | ], 11 | "include": [ 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /projects/docs/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "../../tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "../../out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "include": [ 11 | "src/**/*.spec.ts", 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /projects/ngx-reactive-storage/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'ngx-reactive-storage', 4 | preset: 'jest-preset-angular', 5 | setupFilesAfterEnv: ['/src/test-setup.ts'], 6 | globals: { }, 7 | transform: { 8 | '^.+\\.(ts|mjs|js|html)$': ['jest-preset-angular', { 9 | tsconfig: '/tsconfig.spec.json', 10 | stringifyContentPathRegex: '\\.(html|svg)$', 11 | }], 12 | }, 13 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 14 | snapshotSerializers: [ 15 | 'jest-preset-angular/build/serializers/no-ng-attributes', 16 | 'jest-preset-angular/build/serializers/ng-snapshot', 17 | 'jest-preset-angular/build/serializers/html-comment', 18 | ], 19 | }; 20 | -------------------------------------------------------------------------------- /projects/ngx-reactive-storage/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/ngx-reactive-storage", 4 | "lib": { 5 | "entryFile": "src/public-api.ts" 6 | }, 7 | "allowedNonPeerDependencies": [ 8 | "localforage" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /projects/ngx-reactive-storage/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-reactive-storage", 3 | "version": "2.0.1", 4 | "license": "MIT", 5 | "private": false, 6 | "author": { 7 | "name": "Evgeniy OZ", 8 | "email": "normandiggs@gmail.com", 9 | "url": "https://jamm.dev" 10 | }, 11 | "repository": { 12 | "url": "git+https://github.com/e-oz/ngx-reactive-storage.git" 13 | }, 14 | "keywords": [ 15 | "angular", 16 | "reactive", 17 | "storage", 18 | "indexeddb", 19 | "localstorage" 20 | ], 21 | "dependencies": { 22 | "localforage": "^1.10.0" 23 | }, 24 | "peerDependencies": { 25 | "@angular/core": "^19.0.0 || ^20.0.0", 26 | "rxjs": "^7.8.1" 27 | }, 28 | "sideEffects": false 29 | } 30 | -------------------------------------------------------------------------------- /projects/ngx-reactive-storage/src/lib/idb.spec.ts: -------------------------------------------------------------------------------- 1 | import { Observable } from "rxjs"; 2 | import { RxStorage } from './idb'; 3 | import 'fake-indexeddb/auto'; 4 | 5 | class BCMock { 6 | addEventListener() { 7 | } 8 | 9 | postMessage() { 10 | } 11 | } 12 | 13 | // @ts-ignore 14 | BroadcastChannel = BCMock; 15 | 16 | function readObs(obs: Observable): T | undefined { 17 | let v; 18 | obs.subscribe((val) => v = val); 19 | return v; 20 | } 21 | 22 | describe('IdbStorage', () => { 23 | let storage: RxStorage; 24 | const registryName = 'test'; 25 | 26 | beforeEach(() => { 27 | storage = new RxStorage(registryName); 28 | }); 29 | 30 | it('should create an instance of the IdbStorage class', () => { 31 | expect(storage).toBeInstanceOf(RxStorage); 32 | }); 33 | 34 | it('should set and get a value', async () => { 35 | const key = 'testKey'; 36 | const value = 'testValue'; 37 | await storage.set(key, value); 38 | const result = await storage.get(key); 39 | expect(result).toEqual(value); 40 | }); 41 | 42 | it('should remove a value', async () => { 43 | const key = 'testKey'; 44 | const value = 'testValue'; 45 | await storage.set(key, value); 46 | await storage.remove(key); 47 | const result = await storage.get(key); 48 | expect(result).toBeNull(); 49 | }); 50 | 51 | it('should set and get an object', async () => { 52 | const key = 'testKey'; 53 | const value = { test: 'testValue' }; 54 | await storage.set(key, value); 55 | const result = await storage.get<{ 56 | test: string 57 | }>(key); 58 | expect(result).toEqual(value); 59 | }); 60 | 61 | it('should return a signal and update it', async () => { 62 | const key = 'testKey'; 63 | const value = 'testValue'; 64 | const s = storage.getSignal(key); 65 | expect(s()).toStrictEqual(undefined); 66 | await storage.set(key, value); 67 | expect(s()).toStrictEqual(value); 68 | await storage.remove(key); 69 | expect(s()).toStrictEqual(undefined); 70 | }); 71 | 72 | it('should return an observable and update it', async () => { 73 | const key = 'testKey'; 74 | const value = 'testValue'; 75 | const obs = storage.getObservable(key); 76 | 77 | expect(readObs(obs)).toStrictEqual(undefined); 78 | await storage.set(key, value); 79 | expect(readObs(obs)).toStrictEqual(value); 80 | await storage.remove(key); 81 | expect(readObs(obs)).toStrictEqual(undefined); 82 | }); 83 | 84 | it('should update a key in the storage when WritableSignal is updated', async () => { 85 | const key = 'testKey'; 86 | const value = 'testValue'; 87 | const initValue = 'initial value'; 88 | const newValue = 'new value'; 89 | 90 | const ws = storage.getWritableSignal(key, { initialValue: initValue }); 91 | expect(ws()).toStrictEqual(initValue); 92 | 93 | ws.set(value); 94 | expect(ws()).toStrictEqual(value); 95 | expect(await storage.get(key)).toStrictEqual(value); 96 | 97 | ws.update((val) => { 98 | expect(val).toStrictEqual(value); 99 | return newValue; 100 | }); 101 | 102 | expect(ws()).toStrictEqual(newValue); 103 | expect(await storage.get(key)).toStrictEqual(newValue); 104 | await storage.remove(key); 105 | expect(ws()).toStrictEqual(undefined); 106 | }); 107 | }); 108 | -------------------------------------------------------------------------------- /projects/ngx-reactive-storage/src/lib/idb.ts: -------------------------------------------------------------------------------- 1 | import { type Signal, type ValueEqualityFn, type WritableSignal } from '@angular/core'; 2 | import localforage from 'localforage'; 3 | import type { Observable } from 'rxjs'; 4 | import { Observer } from './observer'; 5 | import type { ReactiveStorage, SignalOptions } from './types'; 6 | 7 | type KeyChange = { 8 | type: 'set' | 'remove'; 9 | key: string; 10 | value?: unknown; 11 | }; 12 | 13 | export class RxStorage implements ReactiveStorage { 14 | private readonly storage?: LocalForage; 15 | private readonly dbName: string; 16 | private readonly tableName: string; 17 | private readonly observer = new Observer(this); 18 | private readonly channel?: BroadcastChannel; 19 | private readonly listener = (event: MessageEvent) => { 20 | if (event.data && typeof event.data === 'object') { 21 | const msg = event.data as KeyChange; 22 | switch (msg.type) { 23 | case 'set': 24 | this.observer.set(msg.key, msg.value); 25 | break; 26 | case 'remove': 27 | this.observer.removed(msg.key); 28 | break; 29 | } 30 | } 31 | }; 32 | 33 | /** 34 | * @param tableName - name of the table in DB. Use name of the feature or the component when possible. 35 | * @param dbName - DB name. Use application name when possible. 36 | */ 37 | constructor(tableName: string = 'table', dbName: string = 'db') { 38 | this.tableName = tableName || 'table'; 39 | this.dbName = dbName || 'db'; 40 | 41 | if (typeof window !== 'undefined' && typeof BroadcastChannel !== 'undefined' && typeof window.indexedDB !== 'undefined') { 42 | this.storage = localforage.createInstance({ name: this.dbName, storeName: this.tableName }); 43 | this.channel = new BroadcastChannel(this.dbName + '.' + this.tableName); 44 | this.channel.addEventListener('message', this.listener, { passive: true }) 45 | } 46 | } 47 | 48 | get(key: string): Promise { 49 | return new Promise((resolve, reject) => { 50 | if (!this.storage) { 51 | resolve(undefined); 52 | return; 53 | } 54 | this.storage.getItem(key).then((value) => { 55 | if (value !== null) { 56 | this.observer.set(key, value); 57 | } 58 | resolve(value); 59 | }).catch(reject); 60 | }); 61 | } 62 | 63 | getObservable(key: string): Observable { 64 | const obs = this.observer.getObservable(key, undefined); 65 | this.get(key).catch((e) => { 66 | console.error('RxStorage::getObservable', e); 67 | }); 68 | return obs; 69 | } 70 | 71 | getSignal(key: string): Signal; 72 | 73 | getSignal(key: string, options: SignalOptions & { 74 | initialValue: undefined, 75 | equal: ValueEqualityFn; 76 | }): Signal; 77 | 78 | getSignal(key: string, options: SignalOptions & { 79 | initialValue: undefined, 80 | }): Signal; 81 | 82 | getSignal(key: string, options: SignalOptions & { 83 | initialValue: T; 84 | }): Signal; 85 | 86 | getSignal(key: string, options: SignalOptions & { 87 | initialValue: T; 88 | equal: ValueEqualityFn; 89 | }): Signal; 90 | 91 | getSignal(key: string, options: SignalOptions & { 92 | initialValue: T; 93 | equal: undefined; 94 | }): Signal; 95 | 96 | getSignal(key: string, options?: SignalOptions & { 97 | initialValue?: T; 98 | equal?: ValueEqualityFn; 99 | }): Signal { 100 | const s = this.observer.getSignal(key, options?.initialValue, options?.equal); 101 | this.get(key).catch((e) => { 102 | console.error('RxStorage::getSignal', e); 103 | }); 104 | return s; 105 | } 106 | 107 | getWritableSignal(key: string): WritableSignal; 108 | 109 | getWritableSignal(key: string, options: SignalOptions & { 110 | initialValue: undefined, 111 | equal: ValueEqualityFn; 112 | }): WritableSignal; 113 | 114 | getWritableSignal(key: string, options: SignalOptions & { 115 | initialValue: undefined, 116 | }): WritableSignal; 117 | 118 | getWritableSignal(key: string, options: SignalOptions & { 119 | initialValue: T; 120 | }): WritableSignal; 121 | 122 | getWritableSignal(key: string, options: SignalOptions & { 123 | initialValue: T; 124 | equal: ValueEqualityFn; 125 | }): WritableSignal; 126 | 127 | getWritableSignal(key: string, options: SignalOptions & { 128 | initialValue: T; 129 | equal: undefined; 130 | }): WritableSignal; 131 | 132 | getWritableSignal(key: string, options?: SignalOptions & { 133 | initialValue?: T; 134 | equal?: ValueEqualityFn; 135 | }): WritableSignal { 136 | const s = this.observer.getWritableSignal(key, options?.initialValue, options?.equal); 137 | this.get(key).catch((e) => { 138 | console.error('RxStorage::getWritableSignal', e); 139 | }); 140 | return s; 141 | } 142 | 143 | set(key: string, value: unknown): Promise { 144 | return new Promise((resolve, reject) => { 145 | if (!this.storage) { 146 | resolve(); 147 | return; 148 | } 149 | this.storage.setItem(key, value).then(() => { 150 | this.observer.set(key, value); 151 | this.broadcastChange({ 152 | type: 'set', 153 | key, 154 | value 155 | }); 156 | resolve(); 157 | }).catch(reject); 158 | }); 159 | } 160 | 161 | remove(key: string): Promise { 162 | return new Promise((resolve, reject) => { 163 | if (!this.storage) { 164 | resolve(); 165 | return; 166 | } 167 | this.storage.removeItem(key).then(() => { 168 | this.observer.removed(key); 169 | this.broadcastChange({ 170 | type: 'remove', 171 | key, 172 | }); 173 | resolve(); 174 | }).catch(reject); 175 | }); 176 | } 177 | 178 | getKeys(): Promise { 179 | return new Promise((resolve, reject) => { 180 | if (!this.storage) { 181 | resolve([]); 182 | return; 183 | } 184 | this.storage.keys().then((keys) => { 185 | resolve(keys); 186 | }).catch(reject); 187 | }); 188 | } 189 | 190 | clear(): Promise { 191 | return new Promise((resolve, reject) => { 192 | if (!this.storage) { 193 | resolve(); 194 | return; 195 | } 196 | this.storage.keys().then((keys) => { 197 | keys.forEach((key) => this.observer.removed(key)); 198 | this.storage?.clear().then(() => resolve()).catch(reject); 199 | }).catch(reject); 200 | }); 201 | } 202 | 203 | dispose(): void { 204 | this.observer.dispose(); 205 | if (this.channel) { 206 | this.channel.removeEventListener('message', this.listener); 207 | this.channel.close(); 208 | } 209 | } 210 | 211 | private broadcastChange(change: KeyChange) { 212 | this.channel?.postMessage(change); 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /projects/ngx-reactive-storage/src/lib/index.ts: -------------------------------------------------------------------------------- 1 | export type * from './types'; 2 | 3 | export * from './idb'; 4 | export * from './local-storage'; 5 | -------------------------------------------------------------------------------- /projects/ngx-reactive-storage/src/lib/local-storage.spec.ts: -------------------------------------------------------------------------------- 1 | import { RxLocalStorage } from './local-storage'; 2 | 3 | describe('LocalStorage', () => { 4 | let localStorageMock: Record; 5 | let mockStorageEvent: StorageEvent; 6 | let originalLocalStorage: Storage; 7 | let localStorageSpy: jest.SpyInstance; 8 | 9 | beforeEach(() => { 10 | localStorageMock = {}; 11 | originalLocalStorage = window.localStorage; 12 | Object.defineProperty(window, 'localStorage', { 13 | value: { 14 | getItem: (key: string) => localStorageMock[key] || null, 15 | setItem: (key: string, value: string) => { 16 | localStorageMock[key] = value; 17 | mockStorageEvent = new StorageEvent('storage', { key, newValue: value }); 18 | window.dispatchEvent(mockStorageEvent); 19 | }, 20 | removeItem: (key: string) => { 21 | delete localStorageMock[key]; 22 | mockStorageEvent = new StorageEvent('storage', { key, newValue: null }); 23 | window.dispatchEvent(mockStorageEvent); 24 | }, 25 | clear: () => { 26 | localStorageMock = {}; 27 | mockStorageEvent = new StorageEvent('storage', { key: null, newValue: null }); 28 | window.dispatchEvent(mockStorageEvent); 29 | }, 30 | }, 31 | writable: true, 32 | }); 33 | localStorageSpy = jest.spyOn(window.localStorage, 'getItem'); 34 | }); 35 | 36 | afterEach(() => { 37 | localStorageSpy.mockRestore(); 38 | Object.defineProperty(window, 'localStorage', { value: originalLocalStorage }); 39 | }); 40 | 41 | describe('getObservable', () => { 42 | it('returns an observable with the stored value', () => { 43 | const storage = new RxLocalStorage(); 44 | const key = 'testKey'; 45 | const value = 'testValue'; 46 | localStorage.setItem(storage['prefixed'](key), JSON.stringify(value)); 47 | const observable = storage.getObservable(key); 48 | let result: string | undefined; 49 | observable.subscribe((val) => { 50 | result = val; 51 | }); 52 | expect(result).toBe(value); 53 | }); 54 | }); 55 | 56 | describe('getSignal', () => { 57 | it('returns a signal with the stored value', () => { 58 | const storage = new RxLocalStorage(); 59 | const key = 'testKey'; 60 | const value = 'testValue'; 61 | storage.set(key, value); 62 | const signal = storage.getSignal(key); 63 | expect(signal()).toBe(value); 64 | }); 65 | }); 66 | 67 | describe('get', () => { 68 | it('returns a Promise that resolves with the stored value', async () => { 69 | const storage = new RxLocalStorage(); 70 | const key = 'testKey'; 71 | const value = 'testValue'; 72 | localStorage.setItem(storage['prefixed'](key), JSON.stringify(value)); 73 | const result = await storage.get(key); 74 | expect(result).toBe(value); 75 | }); 76 | 77 | it('returns a Promise that resolves with null if the key does not exist', async () => { 78 | const storage = new RxLocalStorage(); 79 | const key = 'nonExistentKey'; 80 | const result = await storage.get(key); 81 | expect(result).toBeNull(); 82 | }); 83 | 84 | it('returns a Promise that rejects if the stored value is not a valid JSON', async () => { 85 | const storage = new RxLocalStorage(); 86 | const key = 'testKey'; 87 | const invalidValue = 'invalidJSON'; 88 | localStorage.setItem(storage['prefixed'](key), invalidValue); 89 | await expect(storage.get(key)).rejects.toThrow(); 90 | }); 91 | }); 92 | 93 | describe('remove', () => { 94 | it('removes the item from localStorage', async () => { 95 | const storage = new RxLocalStorage(); 96 | const key = 'testKey'; 97 | localStorage.setItem(storage['prefixed'](key), 'value'); 98 | await storage.remove(key); 99 | expect(localStorage.getItem(storage['prefixed'](key))).toBeNull(); 100 | }); 101 | 102 | it('rejects the Promise if an error occurs', async () => { 103 | const storage = new RxLocalStorage(); 104 | const key = 'testKey'; 105 | localStorage.removeItem = jest.fn(() => { 106 | throw new Error('Failed to remove item'); 107 | }); 108 | await expect(storage.remove(key)).rejects.toThrow('Failed to remove item'); 109 | }); 110 | }); 111 | 112 | describe('set', () => { 113 | it('sets the item in localStorage', async () => { 114 | const storage = new RxLocalStorage(); 115 | const key = 'testKey'; 116 | const value = 'testValue'; 117 | await storage.set(key, value); 118 | expect(localStorage.getItem(storage['prefixed'](key))).toBe(JSON.stringify(value)); 119 | }); 120 | 121 | it('rejects the Promise if an error occurs', async () => { 122 | const storage = new RxLocalStorage(); 123 | const key = 'testKey'; 124 | const value = 'testValue'; 125 | localStorage.setItem = jest.fn(() => { 126 | throw new Error('Failed to set item'); 127 | }); 128 | await expect(storage.set(key, value)).rejects.toThrow('Failed to set item'); 129 | }); 130 | 131 | 132 | it('should update a key in the storage when WritableSignal is updated', async () => { 133 | const storage = new RxLocalStorage(); 134 | const key = 'testKey'; 135 | const value = 'testValue'; 136 | const initValue = 'initial value'; 137 | const newValue = 'new value'; 138 | 139 | const ws = storage.getWritableSignal(key, { initialValue: initValue }); 140 | expect(ws()).toStrictEqual(initValue); 141 | 142 | ws.set(value); 143 | expect(ws()).toStrictEqual(value); 144 | expect(await storage.get(key)).toStrictEqual(value); 145 | 146 | ws.update((val) => { 147 | expect(val).toStrictEqual(value); 148 | return newValue; 149 | }); 150 | 151 | expect(ws()).toStrictEqual(newValue); 152 | expect(await storage.get(key)).toStrictEqual(newValue); 153 | await storage.remove(key); 154 | expect(ws()).toStrictEqual(undefined); 155 | }); 156 | }); 157 | 158 | describe('dispose', () => { 159 | it('disposes the observer and removes the storage event listener', () => { 160 | const storage = new RxLocalStorage(); 161 | storage.getObservable('test'); 162 | const removeEventListenerSpy = jest.spyOn(window, 'removeEventListener'); 163 | storage.dispose(); 164 | expect(removeEventListenerSpy).toHaveBeenCalledWith('storage', storage['listener']); 165 | }); 166 | }); 167 | }); 168 | -------------------------------------------------------------------------------- /projects/ngx-reactive-storage/src/lib/local-storage.ts: -------------------------------------------------------------------------------- 1 | import type { Signal } from '@angular/core'; 2 | import { type ValueEqualityFn, type WritableSignal } from '@angular/core'; 3 | import type { Observable } from 'rxjs'; 4 | import { Observer } from "./observer"; 5 | import type { ReactiveStorage, SignalOptions } from './types'; 6 | 7 | type Key = string; 8 | 9 | type PrefixedKey = Key & { __key: 'prefixed' }; 10 | 11 | export class RxLocalStorage implements ReactiveStorage { 12 | private readonly tableName: string; 13 | private readonly dbName: string; 14 | private readonly delimiter: string; 15 | private readonly observer = new Observer(this); 16 | private isListening = false; 17 | private observedKeys = new Set(); 18 | private readonly listener = (event: StorageEvent) => { 19 | if (event.key && this.observedKeys.has(event.key as PrefixedKey)) { 20 | try { 21 | const key = this.unprefixed(event.key); 22 | if (key) { 23 | const value = event.newValue == null ? 24 | event.newValue 25 | : event.newValue === 'undefined' ? undefined : JSON.parse(event.newValue); 26 | this.observer.set(key, value); 27 | } 28 | } catch (e) { 29 | console.error('RxLocalStorage::listener', e); 30 | } 31 | } 32 | }; 33 | 34 | constructor(tableName: string = 'table', dbName: string = 'db', delimiter: string = '|~:%:^|') { 35 | this.delimiter = delimiter || '|~:%:^|'; 36 | this.dbName = dbName || 'db'; 37 | this.tableName = tableName || 'table'; 38 | } 39 | 40 | getObservable(key: string): Observable { 41 | let value: T | undefined; 42 | if (typeof localStorage !== 'undefined') { 43 | const str = localStorage.getItem(this.prefixed(key)); 44 | if (str !== null) { 45 | try { 46 | value = JSON.parse(str); 47 | } catch (_) { 48 | } 49 | } 50 | this.startListening(key); 51 | } 52 | return this.observer.getObservable(key, value); 53 | } 54 | 55 | getSignal(key: string): Signal; 56 | 57 | getSignal(key: string, options: SignalOptions & { 58 | equal: ValueEqualityFn; 59 | }): Signal; 60 | 61 | getSignal(key: string, options: SignalOptions & { 62 | initialValue: undefined, 63 | equal: ValueEqualityFn; 64 | }): Signal; 65 | 66 | getSignal(key: string, options: SignalOptions & { 67 | initialValue: undefined, 68 | }): Signal; 69 | 70 | getSignal(key: string, options: SignalOptions & { 71 | initialValue: T; 72 | }): Signal; 73 | 74 | getSignal(key: string, options: SignalOptions & { 75 | initialValue: T; 76 | equal: ValueEqualityFn; 77 | }): Signal; 78 | 79 | getSignal(key: string, options: SignalOptions & { 80 | initialValue: T; 81 | equal: undefined; 82 | }): Signal; 83 | 84 | getSignal(key: string, options?: SignalOptions & { 85 | initialValue?: T; 86 | equal?: ValueEqualityFn; 87 | }): Signal { 88 | let value = options?.initialValue; 89 | if (typeof localStorage !== 'undefined') { 90 | const str = localStorage.getItem(this.prefixed(key)); 91 | if (str !== null) { 92 | try { 93 | value = JSON.parse(str); 94 | } catch (_) { 95 | } 96 | } 97 | this.startListening(key); 98 | } 99 | return this.observer.getSignal(key, value, options?.equal); 100 | } 101 | 102 | getWritableSignal(key: string): WritableSignal; 103 | 104 | getWritableSignal(key: string, options: SignalOptions & { 105 | initialValue: undefined, 106 | equal: ValueEqualityFn; 107 | }): WritableSignal; 108 | 109 | getWritableSignal(key: string, options: SignalOptions & { 110 | initialValue: undefined, 111 | }): WritableSignal; 112 | 113 | getWritableSignal(key: string, options: SignalOptions & { 114 | initialValue: T; 115 | }): WritableSignal; 116 | 117 | getWritableSignal(key: string, options: SignalOptions & { 118 | initialValue: T; 119 | equal: ValueEqualityFn; 120 | }): WritableSignal; 121 | 122 | getWritableSignal(key: string, options: SignalOptions & { 123 | initialValue: T; 124 | equal: undefined; 125 | }): WritableSignal; 126 | 127 | getWritableSignal(key: string, options?: SignalOptions & { 128 | initialValue?: T; 129 | equal?: ValueEqualityFn; 130 | }): WritableSignal { 131 | let value = options?.initialValue; 132 | if (typeof localStorage !== 'undefined') { 133 | const str = localStorage.getItem(this.prefixed(key)); 134 | if (str !== null) { 135 | try { 136 | value = JSON.parse(str); 137 | } catch (_) { 138 | } 139 | } 140 | this.startListening(key); 141 | } 142 | return this.observer.getWritableSignal(key, value, options?.equal); 143 | } 144 | 145 | get(key: string): Promise { 146 | return new Promise((resolve, reject) => { 147 | if (typeof localStorage !== 'undefined') { 148 | try { 149 | const str = localStorage.getItem(this.prefixed(key)); 150 | if (str === null) { 151 | this.observer.removed(key); 152 | resolve(str); 153 | return; 154 | } 155 | resolve(JSON.parse(str)); 156 | } catch (e) { 157 | reject(e); 158 | } 159 | } else { 160 | resolve(undefined); 161 | } 162 | }); 163 | } 164 | 165 | getKeys(): Promise { 166 | return Promise.resolve( 167 | typeof localStorage === 'undefined' ? [] : 168 | Object.keys(localStorage).map( 169 | (k) => this.unprefixed(k) 170 | ).filter(key => key !== undefined) as string[] 171 | ); 172 | } 173 | 174 | remove(key: string): Promise { 175 | if (typeof localStorage === 'undefined') { 176 | return Promise.resolve(); 177 | } 178 | try { 179 | localStorage.removeItem(this.prefixed(key)); 180 | this.observer.removed(key); 181 | return Promise.resolve(); 182 | } catch (e) { 183 | return Promise.reject(e); 184 | } 185 | } 186 | 187 | set(key: string, value: unknown): Promise { 188 | if (typeof localStorage === 'undefined') { 189 | return Promise.resolve(); 190 | } 191 | try { 192 | const v = JSON.stringify(value); 193 | localStorage.setItem(this.prefixed(key), v); 194 | this.observer.set(key, value); 195 | return Promise.resolve(undefined); 196 | } catch (e) { 197 | return Promise.reject(e); 198 | } 199 | } 200 | 201 | clear(): Promise { 202 | return new Promise((resolve) => { 203 | this.getKeys().then((keys) => { 204 | const requests: Promise[] = []; 205 | keys.forEach((key) => requests.push(this.remove(key))); 206 | Promise.all(requests).then(() => resolve()); 207 | }); 208 | }); 209 | } 210 | 211 | dispose() { 212 | this.observer.dispose(); 213 | this.observedKeys.clear(); 214 | if (this.isListening) { 215 | try { 216 | window.removeEventListener('storage', this.listener); 217 | } catch (_) { 218 | } 219 | } 220 | } 221 | 222 | private prefixed(key: Key): PrefixedKey { 223 | return [this.dbName, this.tableName, key].join(this.delimiter) as PrefixedKey; 224 | } 225 | 226 | private unprefixed(key: string): Key | undefined { 227 | const parts = key.split(this.delimiter); 228 | if (parts.length < 3) { 229 | return undefined; 230 | } 231 | if (parts[0] !== this.dbName) { 232 | return undefined; 233 | } 234 | if (parts[1] !== this.tableName) { 235 | return undefined; 236 | } 237 | return parts[2]; 238 | } 239 | 240 | private startListening(key: Key) { 241 | this.observedKeys.add(this.prefixed(key)); 242 | if (!this.isListening) { 243 | this.isListening = true; 244 | window.addEventListener('storage', this.listener, { passive: true }); 245 | } 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /projects/ngx-reactive-storage/src/lib/observer.ts: -------------------------------------------------------------------------------- 1 | import type { Signal, WritableSignal } from "@angular/core"; 2 | import { signal, type ValueEqualityFn } from "@angular/core"; 3 | import type { Observable} from "rxjs"; 4 | import { BehaviorSubject, shareReplay } from "rxjs"; 5 | import type { ReactiveStorage } from "./types"; 6 | 7 | let skipStorageSet = false; 8 | 9 | export class Observer { 10 | constructor(private readonly storage: ReactiveStorage) { 11 | } 12 | 13 | private readonly observables = new Map>(); 14 | private readonly signals = new Map>(); 15 | 16 | /** 17 | * Pushes new value to observable (if it's not equal to previous), 18 | * sets signal value, if observable/signal was requested for this key. 19 | */ 20 | public set(key: string, value: unknown) { 21 | const obs = this.observables.get(key); 22 | if (obs) { 23 | if (obs.getValue() !== value) { 24 | obs.next(value); 25 | } 26 | } 27 | 28 | const s = this.signals.get(key); 29 | if (s) { 30 | skipStorageSet = true; 31 | s.set(value); 32 | skipStorageSet = false; 33 | } 34 | } 35 | 36 | /** 37 | * Pushes `undefined` to the observable/signal related to this key, 38 | * if such observable/signal was requested. 39 | */ 40 | public removed(key: string) { 41 | const obs = this.observables.get(key); 42 | if (obs) { 43 | obs.next(undefined); 44 | } 45 | 46 | const s = this.signals.get(key); 47 | if (s) { 48 | s.set(undefined); 49 | } 50 | } 51 | 52 | /** 53 | * Returns a hot observable (replay:1) and pushes the current value for this key. 54 | * The key becomes "observed" and future modifications will be pushed 55 | * to the returned observable. 56 | */ 57 | public getObservable(key: string, initialValue: unknown): Observable { 58 | let obs = this.observables.get(key); 59 | if (!obs) { 60 | obs = new BehaviorSubject(undefined); 61 | this.observables.set(key, obs); 62 | } 63 | if (initialValue !== null) { 64 | obs.next(initialValue); 65 | } 66 | return obs.pipe( 67 | shareReplay({ refCount: true, bufferSize: 1 }) 68 | ) as unknown as Observable; 69 | } 70 | 71 | /** 72 | * Returns a signal and sets the current value for this key. 73 | * The key becomes "observed" and future modifications will be 74 | * written to the returned signal. 75 | */ 76 | public getSignal(key: string, initialValue: T | undefined, equal?: ValueEqualityFn): Signal; 77 | public getSignal(key: string, initialValue: undefined, equal?: ValueEqualityFn): Signal; 78 | 79 | public getSignal(key: string, initialValue?: T, equal?: ValueEqualityFn): Signal | Signal { 80 | let s = this.signals.get(key) as WritableSignal; 81 | if (!s) { 82 | s = signal(initialValue, { equal }); 83 | this.signals.set(key, s); 84 | } 85 | if (initialValue !== undefined) { 86 | s.set(initialValue); 87 | } 88 | return s.asReadonly(); 89 | } 90 | 91 | public getWritableSignal(key: string, initialValue: T | undefined, equal?: ValueEqualityFn): WritableSignal; 92 | public getWritableSignal(key: string, initialValue: undefined, equal?: ValueEqualityFn): WritableSignal; 93 | 94 | public getWritableSignal(key: string, initialValue?: T, equal?: ValueEqualityFn): WritableSignal | WritableSignal { 95 | let s = this.signals.get(key) as WritableSignal; 96 | if (!s) { 97 | s = signal(initialValue, { equal }); 98 | const srcSet = s.set; 99 | s.set = (value: T) => { 100 | if (!skipStorageSet) { 101 | this.storage.set(key, value).catch(console?.error); 102 | } 103 | srcSet(value); 104 | } 105 | s.update = (updateFn: (value: T | undefined) => T | undefined) => { 106 | const value = updateFn(s()); 107 | if (!skipStorageSet) { 108 | this.storage.set(key, value).catch(console?.error); 109 | } 110 | srcSet(value); 111 | } 112 | this.signals.set(key, s); 113 | } 114 | return s; 115 | } 116 | 117 | public dispose() { 118 | this.observables.clear(); 119 | this.signals.clear(); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /projects/ngx-reactive-storage/src/lib/types.ts: -------------------------------------------------------------------------------- 1 | import type { Signal, ValueEqualityFn, WritableSignal } from "@angular/core"; 2 | import type { Observable } from "rxjs"; 3 | 4 | export type ReactiveStorage = { 5 | /** 6 | * Returns value by the key 7 | */ 8 | get(key: string): Promise; 9 | 10 | /** 11 | * Returns a hot observable (replay:1) and pushes the current value for this key. 12 | * Future modifications will be pushed to the returned observable. 13 | * 14 | * If localStorage is being used as the storage, the value will be pushed synchronously 15 | * (to allow you to read it synchronously or asynchronously). 16 | */ 17 | getObservable(key: string): Observable; 18 | 19 | /** 20 | * Returns a signal with the current value for this key. 21 | * The key becomes "observed" and future modifications will be 22 | * written to the returned signal. 23 | * 24 | * If localStorage is being used as the storage, the value will be pushed synchronously. 25 | */ 26 | getSignal(key: string, options?: SignalOptions): Signal; 27 | 28 | 29 | /** 30 | * Returns a signal with the current value for this key. 31 | * The key becomes "observed" and future modifications will be 32 | * written to the returned signal. 33 | * 34 | * The usage of the `set()` and `update()` methods of this signal will also update the storage key. 35 | * 36 | * If localStorage is being used as the storage, the value will be pushed synchronously. 37 | */ 38 | getWritableSignal(key: string, options?: SignalOptions): WritableSignal; 39 | 40 | /** 41 | * Set a key-value pair 42 | */ 43 | set(key: string, value: unknown): Promise; 44 | 45 | /** 46 | * Removes a key 47 | */ 48 | remove(key: string): Promise; 49 | 50 | /** 51 | * Returns keys of the current table (located in the current database). 52 | */ 53 | getKeys(): Promise; 54 | 55 | /** 56 | * Removes all keys of the current table (located in the current database). 57 | */ 58 | clear(): Promise; 59 | 60 | /** 61 | * Removes links to observables and signals; removes event listeners. 62 | */ 63 | dispose(): void; 64 | } 65 | 66 | export type SignalOptions = { 67 | initialValue?: unknown; 68 | equal?: ValueEqualityFn; 69 | }; 70 | -------------------------------------------------------------------------------- /projects/ngx-reactive-storage/src/public-api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of ngx-reactive-storage 3 | */ 4 | 5 | export * from './lib'; 6 | -------------------------------------------------------------------------------- /projects/ngx-reactive-storage/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular/setup-jest'; 2 | -------------------------------------------------------------------------------- /projects/ngx-reactive-storage/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "../../tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "../../out-tsc/lib", 6 | "declaration": true, 7 | "declarationMap": true, 8 | "inlineSources": true, 9 | "types": [] 10 | }, 11 | "exclude": [ 12 | "**/*.spec.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /projects/ngx-reactive-storage/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.lib.json", 4 | "compilerOptions": { 5 | "declarationMap": false 6 | }, 7 | "angularCompilerOptions": { 8 | "compilationMode": "partial" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /projects/ngx-reactive-storage/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "../../tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "../../dist/out-tsc/spec", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "**/*.spec.ts", 10 | "**/*.d.ts" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "paths": { 7 | "ngx-reactive-storage": [ 8 | "dist/ngx-reactive-storage" 9 | ], 10 | "@oz/reactive-storage": ["projects/ngx-reactive-storage/src/lib/index.ts"] 11 | }, 12 | "outDir": "./dist/out-tsc", 13 | "forceConsistentCasingInFileNames": true, 14 | "strict": true, 15 | "esModuleInterop": true, 16 | "noFallthroughCasesInSwitch": true, 17 | "noImplicitAny": true, 18 | "noImplicitThis": true, 19 | "noImplicitReturns": true, 20 | "noImplicitOverride": true, 21 | "noUnusedLocals": true, 22 | "noUnusedParameters": true, 23 | "removeComments": true, 24 | "skipLibCheck": true, 25 | "skipDefaultLibCheck": true, 26 | "strictNullChecks": true, 27 | "strictPropertyInitialization": true, 28 | "noPropertyAccessFromIndexSignature": true, 29 | "sourceMap": true, 30 | "declaration": false, 31 | "downlevelIteration": true, 32 | "experimentalDecorators": true, 33 | "moduleResolution": "node", 34 | "importHelpers": true, 35 | "target": "ES2022", 36 | "module": "ES2022", 37 | "useDefineForClassFields": false, 38 | "lib": [ 39 | "ES2022", 40 | "dom" 41 | ] 42 | }, 43 | "angularCompilerOptions": { 44 | "enableI18nLegacyMessageIdFormat": false, 45 | "strictInjectionParameters": true, 46 | "strictInputAccessModifiers": true, 47 | "strictTemplates": true 48 | } 49 | } 50 | --------------------------------------------------------------------------------