http-request-manager 18.0.12 → 18.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, Injectable, APP_ID, Inject, InjectionToken, Injector, Optional, EventEmitter, Component, ViewEncapsulation, Input, Output, ViewChild, NgModule } from '@angular/core';
2
+ import { inject, Injectable, APP_ID, Inject, InjectionToken, Injector, Optional, signal, computed, effect, EventEmitter, Component, ViewEncapsulation, Input, Output, ViewChild, NgModule } from '@angular/core';
3
3
  import { ComponentStore } from '@ngrx/component-store';
4
4
  import { map, catchError, filter, delay, finalize, takeWhile, retry, startWith, tap, mergeMap, takeUntil, withLatestFrom, switchMap, concatMap, scan, distinctUntilChanged } from 'rxjs/operators';
5
5
  import { HttpClient, HttpHeaders, HttpEventType, HttpHeaderResponse, HttpErrorResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
@@ -59,7 +59,11 @@ class SettingOptions {
59
59
  this.encrypted = encrypted;
60
60
  }
61
61
  static adapt(item) {
62
- return new SettingOptions((item?.storage) ? item.storage : StorageType.GLOBAL, (item?.expires) ? item.expires : 0, (item?.expiresIn) ? item.expiresIn : '', (item?.encrypted) ? item?.encrypted : false);
62
+ const storage = (typeof item?.storage !== 'undefined' && item?.storage !== null) ? Number(item.storage) : StorageType.GLOBAL;
63
+ const expires = (typeof item?.expires !== 'undefined' && item?.expires !== null) ? Number(item.expires) : 0;
64
+ const expiresIn = (typeof item?.expiresIn !== 'undefined' && item?.expiresIn !== null) ? item.expiresIn : '';
65
+ const encrypted = (typeof item?.encrypted !== 'undefined' && item?.encrypted !== null) ? Boolean(item.encrypted) : false;
66
+ return new SettingOptions(storage, expires, expiresIn, encrypted);
63
67
  }
64
68
  }
65
69
 
@@ -902,15 +906,34 @@ function delayedRetry(delayMs, maxRetry = DEFAULT_MAX_RETRIES) {
902
906
  }));
903
907
  }
904
908
 
905
- /**
906
- * @param pollInterval
907
- * @param stopCondition$
908
- * @param isPending$
909
- */
910
909
  function requestPolling(pollInterval, stopCondition$, isPending$) {
911
910
  return (source) => {
912
911
  return interval(pollInterval * 1000)
913
- .pipe(startWith(0), tap(() => isPending$.next(true)), mergeMap(() => source), tap(() => isPending$.next(false)), takeUntil(stopCondition$));
912
+ .pipe(startWith(0), tap(() => {
913
+ try {
914
+ if (isPending$ && typeof isPending$.next === 'function') {
915
+ isPending$.next(true);
916
+ }
917
+ else if (isPending$ && typeof isPending$.set === 'function') {
918
+ isPending$.set(true);
919
+ }
920
+ }
921
+ catch (e) {
922
+ // no-op if setting fails
923
+ }
924
+ }), mergeMap(() => source), tap(() => {
925
+ try {
926
+ if (isPending$ && typeof isPending$.next === 'function') {
927
+ isPending$.next(false);
928
+ }
929
+ else if (isPending$ && typeof isPending$.set === 'function') {
930
+ isPending$.set(false);
931
+ }
932
+ }
933
+ catch (e) {
934
+ // no-op if setting fails
935
+ }
936
+ }), takeUntil(stopCondition$));
914
937
  };
915
938
  }
916
939
 
@@ -1206,6 +1229,7 @@ class RequestOptions {
1206
1229
  class ObjectMergerService {
1207
1230
  constructor(configOptions) {
1208
1231
  this.configOptions = configOptions;
1232
+ this.utils = inject(UtilsService);
1209
1233
  if (!this.configOptions)
1210
1234
  this.configOptions = ConfigOptions.adapt();
1211
1235
  }
@@ -1225,10 +1249,28 @@ class ObjectMergerService {
1225
1249
  const configForRoot = (this.configOptions?.LocalStorageOptions) ? this.configOptions.LocalStorageOptions : LocalStorageOptions.adapt();
1226
1250
  const configForRootOptions = configForRoot.options || LocalStorageOptions.adapt().options;
1227
1251
  const mergedOptions = SettingOptions.adapt(options);
1228
- mergedOptions.storage = (options && options.storage === 0) ? configForRootOptions?.storage || 0 : options.storage;
1229
- mergedOptions.expires = (options && options.expires === 0) ? configForRootOptions?.expires || 0 : options.expires;
1230
- mergedOptions.expiresIn = (options && options.expiresIn === '') ? configForRootOptions?.expiresIn || '' : options.expiresIn;
1231
- mergedOptions.encrypted = (options && !options.encrypted) ? configForRootOptions?.encrypted || false : options.encrypted;
1252
+ // storage type
1253
+ mergedOptions.storage = (options && (typeof options.storage !== 'undefined')) ? options.storage : (configForRootOptions?.storage ?? 0);
1254
+ // expires: prefer explicit numeric expires; if not provided, compute from expiresIn string; otherwise use config default
1255
+ // if an explicit, non-zero numeric expires is provided, use it
1256
+ if (options && (typeof options.expires !== 'undefined') && options.expires !== null && Number(options.expires) > 0) {
1257
+ mergedOptions.expires = Number(options.expires);
1258
+ }
1259
+ else if (options && options.expiresIn) {
1260
+ // compute numeric epoch from expiresIn string using UtilsService if available
1261
+ try {
1262
+ mergedOptions.expires = this.utils ? this.utils.expires(options.expiresIn) : 0;
1263
+ }
1264
+ catch {
1265
+ mergedOptions.expires = 0;
1266
+ }
1267
+ }
1268
+ else {
1269
+ mergedOptions.expires = configForRootOptions?.expires ?? 0;
1270
+ }
1271
+ // keep expiresIn string if explicitly provided, otherwise use config default
1272
+ mergedOptions.expiresIn = (options && (typeof options.expiresIn !== 'undefined')) ? options.expiresIn : (configForRootOptions?.expiresIn || '');
1273
+ mergedOptions.encrypted = (options && (typeof options.encrypted !== 'undefined')) ? options.encrypted : (configForRootOptions?.encrypted || false);
1232
1274
  return mergedOptions;
1233
1275
  }
1234
1276
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ObjectMergerService, deps: [{ token: CONFIG_SETTINGS_TOKEN, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
@@ -1534,6 +1576,272 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
1534
1576
  args: [CONFIG_SETTINGS_TOKEN]
1535
1577
  }] }] });
1536
1578
 
1579
+ const initialState = {
1580
+ localStores: [],
1581
+ sessionStores: [],
1582
+ settings: [],
1583
+ };
1584
+ class LocalStorageSignalsManagerService {
1585
+ constructor(configOptions) {
1586
+ this.configOptions = configOptions;
1587
+ this.state = signal(initialState);
1588
+ this.storageName = 'storage';
1589
+ this.storageSettingsName = 'global-storage';
1590
+ this.defaultOptions = SettingOptions.adapt();
1591
+ this.stateRetrieved = false;
1592
+ this.encrypted = false;
1593
+ this.app = inject(AppService);
1594
+ this.utils = inject(UtilsService);
1595
+ this.objectMergerService = inject(ObjectMergerService);
1596
+ this.encryption = inject(SymmetricalEncryptionService);
1597
+ this.encryptionTest = inject(EncryptionTestService);
1598
+ // --- SELECTORS ---
1599
+ this.stores = computed(() => this.state().settings);
1600
+ this.storeExists = (store) => computed(() => !!this.state().settings.find(item => item.name === store));
1601
+ this.store = (store) => computed(() => {
1602
+ const data = this.state();
1603
+ const foundStore = data.settings.find(item => item.name === store);
1604
+ if (!foundStore)
1605
+ return null;
1606
+ const options = SettingOptions.adapt(foundStore.options);
1607
+ const found = options.storage === StorageType.GLOBAL
1608
+ ? data.localStores.find(item => item.id === foundStore.id)
1609
+ : data.sessionStores.find(item => item.id === foundStore.id);
1610
+ if (!found) {
1611
+ this.deleteStore({ name: store });
1612
+ return null;
1613
+ }
1614
+ if (!this.app?.appID) {
1615
+ console.warn('No App ID found - AppId not Provided');
1616
+ return null;
1617
+ }
1618
+ const storageData = options.encrypted
1619
+ ? this.encryption.decrypt(found.data, this.app.appID)
1620
+ : found.data;
1621
+ return this.isString(storageData) ? JSON.parse(storageData) : storageData;
1622
+ });
1623
+ this.settings = computed(() => this.state().settings);
1624
+ this.setting = (store) => computed(() => this.state().settings.find(item => item.name === store) ?? null);
1625
+ this.storageName = configOptions?.LocalStorageOptions?.storageName || this.storageName;
1626
+ this.storageSettingsName = configOptions?.LocalStorageOptions?.storageSettingsName || this.storageSettingsName;
1627
+ this.defaultOptions = configOptions?.LocalStorageOptions?.options || this.defaultOptions;
1628
+ this.retrieveState();
1629
+ // Auto-persist when state changes
1630
+ effect(() => {
1631
+ if (this.stateRetrieved) {
1632
+ this.persistState(this.state());
1633
+ }
1634
+ });
1635
+ // Expiration timer every 3s
1636
+ setInterval(() => {
1637
+ const state = this.state();
1638
+ const expired = this.expired(state);
1639
+ if (expired.length > 0) {
1640
+ const ids = expired.map(i => i.id);
1641
+ const updated = {
1642
+ ...state,
1643
+ localStores: state.localStores.filter(i => !ids.includes(i.id)),
1644
+ sessionStores: state.sessionStores.filter(i => !ids.includes(i.id)),
1645
+ settings: state.settings.filter(i => !ids.includes(i.id)),
1646
+ };
1647
+ this.state.set(updated);
1648
+ this.persistState(updated);
1649
+ }
1650
+ }, 3000);
1651
+ }
1652
+ // --- STATE MUTATORS ---
1653
+ setStore(store) {
1654
+ this.state.update(state => {
1655
+ const settings = StorageOption.adapt(store);
1656
+ settings.options = this.objectMergerService.mergeStorageOptions(settings.options);
1657
+ store.name = this.validStoreName(store.name);
1658
+ const str = this.encryptionTest.isEncrypted(store.data) ? store.data : JSON.stringify(store.data);
1659
+ const dataStr = this.isObjectOrArray(str) && store.options.encrypted
1660
+ ? this.encryption.encrypt(str, this.app.appID)
1661
+ : store.data;
1662
+ const localData = dataStr && settings.options?.storage === StorageType.GLOBAL
1663
+ ? [{ data: dataStr, id: settings.id }]
1664
+ : [];
1665
+ const sessionData = dataStr && settings.options?.storage === StorageType.SESSION
1666
+ ? [{ data: dataStr, id: settings.id }]
1667
+ : [];
1668
+ return {
1669
+ ...state,
1670
+ localStores: [...state.localStores, ...localData],
1671
+ sessionStores: [...state.sessionStores, ...sessionData],
1672
+ settings: [...state.settings, settings],
1673
+ };
1674
+ });
1675
+ }
1676
+ createStore(store) {
1677
+ this.state.update(state => {
1678
+ const settings = StorageOption.adapt(store);
1679
+ settings.options = this.objectMergerService.mergeStorageOptions(settings.options);
1680
+ if (state.settings.some(item => item.name === store.name)) {
1681
+ return state;
1682
+ }
1683
+ if (!this.isObjectOrArray(store.data)) {
1684
+ console.warn('Data must be an Object or Array');
1685
+ return state;
1686
+ }
1687
+ const dataStr = store.options.encrypted ? this.encryption.encrypt(store.data, this.app.appID) : store.data;
1688
+ const localData = settings.options?.storage === StorageType.GLOBAL ? [{ data: dataStr, id: settings.id }] : [];
1689
+ const sessionData = settings.options?.storage === StorageType.SESSION ? [{ data: dataStr, id: settings.id }] : [];
1690
+ return {
1691
+ ...state,
1692
+ localStores: [...state.localStores, ...localData],
1693
+ sessionStores: [...state.sessionStores, ...sessionData],
1694
+ settings: [...state.settings, settings],
1695
+ };
1696
+ });
1697
+ }
1698
+ updateStore(store) {
1699
+ this.state.update(state => {
1700
+ const settings = state.settings.find(item => item.name === store.name);
1701
+ if (!settings)
1702
+ return state;
1703
+ const dataStr = settings.options?.encrypted
1704
+ ? this.encryption.encrypt(store.data, this.app.appID)
1705
+ : store.data;
1706
+ const localData = settings.options?.storage === StorageType.GLOBAL ? [{ data: dataStr, id: settings.id }] : [];
1707
+ const sessionData = settings.options?.storage === StorageType.SESSION ? [{ data: dataStr, id: settings.id }] : [];
1708
+ return {
1709
+ ...state,
1710
+ localStores: [...state.localStores.filter(i => i.id !== settings.id), ...localData],
1711
+ sessionStores: [...state.sessionStores.filter(i => i.id !== settings.id), ...sessionData],
1712
+ };
1713
+ });
1714
+ }
1715
+ deleteStore(store) {
1716
+ this.state.update(state => {
1717
+ const id = state.settings.find(item => item.name === store.name)?.id;
1718
+ if (!id)
1719
+ return state;
1720
+ return {
1721
+ ...state,
1722
+ localStores: state.localStores.filter(i => i.id !== id),
1723
+ sessionStores: state.sessionStores.filter(i => i.id !== id),
1724
+ settings: state.settings.filter(i => i.id !== id),
1725
+ };
1726
+ });
1727
+ }
1728
+ resetStore() {
1729
+ const cleared = { localStores: [], sessionStores: [], settings: [] };
1730
+ this.state.set(cleared);
1731
+ this.persistState(cleared);
1732
+ }
1733
+ // --- HELPERS ---
1734
+ persistState(state) {
1735
+ localStorage.setItem(this.storageName, JSON.stringify(state.localStores));
1736
+ sessionStorage.setItem(this.storageName, JSON.stringify(state.sessionStores));
1737
+ const settingsStr = this.encryption.encrypt(state.settings, this.app.appID);
1738
+ localStorage.setItem(this.storageSettingsName, settingsStr || '');
1739
+ }
1740
+ expired(state) {
1741
+ return state.settings.filter(s => (s.options?.expires || 0) > 0 && this.utils.hasExpired(s.options?.expires));
1742
+ }
1743
+ retrieveState() {
1744
+ const str = localStorage.getItem(this.storageSettingsName);
1745
+ const localStr = localStorage.getItem(this.storageName);
1746
+ const sessionStr = sessionStorage.getItem(this.storageName);
1747
+ const localData = localStr ? JSON.parse(localStr) : [];
1748
+ const sessionData = sessionStr ? JSON.parse(sessionStr) : [];
1749
+ const decryptedStr = str ? this.encryption.decrypt(str, this.app.appID) : null;
1750
+ const settings = decryptedStr ? JSON.parse(decryptedStr) : [];
1751
+ settings.forEach(store => {
1752
+ // normalize options so we compare numbers and compute expires correctly
1753
+ const options = SettingOptions.adapt(store.options);
1754
+ // if persisted data included expiresIn but not numeric expires, compute it now
1755
+ if ((!options.expires || options.expires === 0) && options.expiresIn) {
1756
+ try {
1757
+ const computed = this.utils.expires(options.expiresIn);
1758
+ options.expires = computed || 0;
1759
+ }
1760
+ catch {
1761
+ options.expires = 0;
1762
+ }
1763
+ }
1764
+ const expired = (options.expires || 0) > 0 && this.utils.hasExpired(options.expires || 0);
1765
+ if (!expired) {
1766
+ const hasStorage = this.hasGlobalStorage(options.storage, store.id || '');
1767
+ if (!hasStorage) {
1768
+ this.createStore({ id: store.id, name: store.name, data: [], options });
1769
+ }
1770
+ else {
1771
+ const storeData = (options.storage === StorageType.GLOBAL)
1772
+ ? localData.find(item => item.id === store.id)
1773
+ : sessionData.find(item => item.id === store.id);
1774
+ this.setStore({ id: store.id || '', name: store.name, data: storeData?.data, options });
1775
+ }
1776
+ }
1777
+ });
1778
+ this.stateRetrieved = true;
1779
+ // Ensure all stored settings have numeric expires computed and persisted
1780
+ try {
1781
+ const current = this.state();
1782
+ let changed = false;
1783
+ const normalizedSettings = current.settings.map(s => {
1784
+ const opts = SettingOptions.adapt(s.options);
1785
+ if ((!opts.expires || opts.expires === 0) && opts.expiresIn) {
1786
+ const computed = this.utils.expires(opts.expiresIn) || 0;
1787
+ if (computed && computed !== opts.expires) {
1788
+ opts.expires = computed;
1789
+ changed = true;
1790
+ }
1791
+ }
1792
+ return { ...s, options: opts };
1793
+ });
1794
+ if (changed) {
1795
+ const updated = { ...current, settings: normalizedSettings };
1796
+ this.state.set(updated);
1797
+ this.persistState(updated);
1798
+ }
1799
+ }
1800
+ catch (e) {
1801
+ // swallow normalization errors to avoid breaking init
1802
+ }
1803
+ }
1804
+ hasGlobalStorage(type = StorageType.GLOBAL, id) {
1805
+ const strData = [];
1806
+ if (type === StorageType.GLOBAL) {
1807
+ const str = localStorage.getItem(this.storageName);
1808
+ strData.push(...(str ? JSON.parse(str) : []));
1809
+ }
1810
+ else {
1811
+ const str = sessionStorage.getItem(this.storageName);
1812
+ strData.push(...(str ? JSON.parse(str) : []));
1813
+ }
1814
+ const found = strData.find(store => store.id === id);
1815
+ return !!found;
1816
+ }
1817
+ isObjectOrArray(obj) {
1818
+ try {
1819
+ const parsed = typeof obj === 'object' ? obj : JSON.parse(obj);
1820
+ return typeof parsed === 'object' && parsed !== null;
1821
+ }
1822
+ catch {
1823
+ return false;
1824
+ }
1825
+ }
1826
+ isString(obj) {
1827
+ return Object.prototype.toString.call(obj) === '[object String]';
1828
+ }
1829
+ validStoreName(str) {
1830
+ return str.toLowerCase().replace(/\s+/g, '_').replace(/[^ -~]/g, '');
1831
+ }
1832
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LocalStorageSignalsManagerService, deps: [{ token: CONFIG_SETTINGS_TOKEN, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
1833
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LocalStorageSignalsManagerService, providedIn: 'root' }); }
1834
+ }
1835
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LocalStorageSignalsManagerService, decorators: [{
1836
+ type: Injectable,
1837
+ args: [{ providedIn: 'root' }]
1838
+ }], ctorParameters: () => [{ type: ConfigOptions, decorators: [{
1839
+ type: Optional
1840
+ }, {
1841
+ type: Inject,
1842
+ args: [CONFIG_SETTINGS_TOKEN]
1843
+ }] }] });
1844
+
1537
1845
  const API_OPTS = new InjectionToken('API_OPTS');
1538
1846
  const defaultState = {
1539
1847
  data: [],
@@ -2891,14 +3199,180 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
2891
3199
  args: [PROXY_CONFIG]
2892
3200
  }] }] });
2893
3201
 
3202
+ class LocalStorageSignalsDemoComponent {
3203
+ // store type is driven by the form control
3204
+ get type() {
3205
+ return (this.typeControl.value) ? +this.typeControl.value : 0;
3206
+ }
3207
+ get isValid() {
3208
+ return this.newStoreForm.valid;
3209
+ }
3210
+ get isValidData() {
3211
+ return this.storageForm.valid;
3212
+ }
3213
+ settingFor(name) {
3214
+ const c = this.localStorageManagerService.setting(name);
3215
+ return c ? c() : null;
3216
+ }
3217
+ constructor(configOptions) {
3218
+ this.configOptions = configOptions;
3219
+ this.fb = inject(FormBuilder);
3220
+ this.utils = inject(UtilsService);
3221
+ this.typeControl = this.fb.control(StorageType.GLOBAL.toString());
3222
+ this.localStorageManagerService = inject(LocalStorageSignalsManagerService);
3223
+ // Use signals directly and computed values for template binding
3224
+ this.settings = computed(() => this.localStorageManagerService.settings());
3225
+ // selected store (signal) and its JSON data for template
3226
+ this.storeSelected = signal(null);
3227
+ this.selectedStoreData = computed(() => {
3228
+ const s = this.storeSelected();
3229
+ if (!s)
3230
+ return '';
3231
+ const computed = this.localStorageManagerService.store(s.name);
3232
+ return computed ? JSON.stringify(computed()) : '';
3233
+ });
3234
+ // filtered settings by selected type
3235
+ this.selectedType = signal(StorageType.GLOBAL);
3236
+ this.filteredSettings = computed(() => {
3237
+ const values = this.settings() || [];
3238
+ return values.filter((item) => item.options.storage === +this.selectedType());
3239
+ });
3240
+ this.storageForm = this.fb.group({
3241
+ store: this.fb.control(null),
3242
+ type: 'local',
3243
+ settingType: 'local',
3244
+ encrypted: false,
3245
+ data: this.fb.control('', Validators.required),
3246
+ });
3247
+ this.newStoreForm = this.fb.group({
3248
+ name: this.fb.control(null, Validators.required),
3249
+ storage: 'local',
3250
+ encrypted: false,
3251
+ data: this.fb.control('', Validators.required),
3252
+ expiresIn: this.fb.control('0')
3253
+ });
3254
+ // no RxJS Observables here; template uses signals/computed directly
3255
+ this.expiresIn = (epoch) => this.utils.expiresIn(epoch);
3256
+ this.isValidJSON = (str) => {
3257
+ try {
3258
+ JSON.parse(str);
3259
+ return true;
3260
+ }
3261
+ catch (e) {
3262
+ return false;
3263
+ }
3264
+ };
3265
+ this.displayedColumns = ['name', 'id', 'encrypted', 'expires', "option"];
3266
+ this.filterData = (values) => {
3267
+ if (!values)
3268
+ return [];
3269
+ return values.filter((item) => item.options && item.options.storage === +this.type);
3270
+ };
3271
+ this.create = false;
3272
+ }
3273
+ ngOnInit() {
3274
+ this.storeProps = this.configOptions?.LocalStorageOptions;
3275
+ this.options = this.storeProps?.options;
3276
+ if (this.options?.storage) {
3277
+ this.typeControl.patchValue(this.options.storage.toString());
3278
+ this.typeControl.disable();
3279
+ }
3280
+ else {
3281
+ this.typeControl.enable();
3282
+ }
3283
+ if (this.options?.expiresIn) {
3284
+ this.newStoreForm.get('expiresIn')?.patchValue(this.options.expiresIn);
3285
+ this.newStoreForm.get('expiresIn')?.disable();
3286
+ }
3287
+ else {
3288
+ this.newStoreForm.get('expiresIn')?.enable();
3289
+ }
3290
+ if (this.options?.encrypted) {
3291
+ this.newStoreForm.get('encrypted')?.patchValue(this.options.encrypted);
3292
+ this.newStoreForm.get('encrypted')?.disable();
3293
+ }
3294
+ else {
3295
+ this.newStoreForm.get('encrypted')?.enable();
3296
+ }
3297
+ // nothing to synchronize - templates read computed signals directly
3298
+ }
3299
+ onCreateStore() {
3300
+ if (!this.isValid)
3301
+ return;
3302
+ const store = this.newStoreForm.value;
3303
+ if (!store.name || store.name === '')
3304
+ return;
3305
+ const options = { storage: this.type, encrypted: store.encrypted, expiresIn: store.expiresIn };
3306
+ this.localStorageManagerService.createStore({
3307
+ name: store.name,
3308
+ data: store.data,
3309
+ options: SettingOptions.adapt(options)
3310
+ });
3311
+ this.newStoreForm.reset();
3312
+ this.create = false;
3313
+ }
3314
+ onUpdateStore(store) {
3315
+ if (!this.storageForm.valid)
3316
+ return;
3317
+ const storeData = this.storageForm.value;
3318
+ const data = JSON.parse(storeData.data || '');
3319
+ const type = (storeData.type === 'local') ? StorageType.GLOBAL : StorageType.SESSION;
3320
+ this.localStorageManagerService.updateStore({
3321
+ name: store.name,
3322
+ data
3323
+ });
3324
+ }
3325
+ onSelectedRow(store) {
3326
+ this.store = store;
3327
+ this.storeSelected.set(store);
3328
+ this.create = false;
3329
+ }
3330
+ onCreate() {
3331
+ this.onCancel();
3332
+ this.create = true;
3333
+ }
3334
+ onDelete(store) {
3335
+ this.localStorageManagerService.deleteStore({
3336
+ name: store.name,
3337
+ });
3338
+ this.onCancel();
3339
+ }
3340
+ onCancel() {
3341
+ this.storeSelected.set(null);
3342
+ this.store = null;
3343
+ this.create = false;
3344
+ }
3345
+ onUpdate(store, data) {
3346
+ this.localStorageManagerService.updateStore({
3347
+ name: store.name,
3348
+ data: JSON.parse(data)
3349
+ });
3350
+ this.onCancel();
3351
+ }
3352
+ onReset() {
3353
+ this.localStorageManagerService.resetStore();
3354
+ }
3355
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LocalStorageSignalsDemoComponent, deps: [{ token: CONFIG_SETTINGS_TOKEN }], target: i0.ɵɵFactoryTarget.Component }); }
3356
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: LocalStorageSignalsDemoComponent, selector: "app-local-storage-signals-demo", ngImport: i0, template: "<div style=\"margin: 2rem;\">\n\n <div style=\"display: flex; gap: 1rem\">\n <h2 style=\"padding-top: .5rem; display: flex;\">\n <div style=\"padding-top: .5rem;\">Local Storage Manager</div>\n <div>\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\n <mat-icon>info</mat-icon>\n </button>\n </div>\n </h2>\n <span style=\"flex:1\"></span>\n <div style=\"padding-top: .25rem;\">\n <mat-button-toggle-group name=\"storage\" [formControl]=\"typeControl\" (change)=\"onCancel()\">\n <mat-button-toggle value=\"0\">Local Storage</mat-button-toggle>\n <mat-button-toggle value=\"1\">Session Storage</mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div style=\"margin-top: .25rem;\">\n <button mat-icon-button (click)=\"onCreate()\">\n <mat-icon>add</mat-icon>\n </button>\n </div>\n </div>\n\n <ng-container *ngIf=\"storeProps?.storageName || storeProps?.storageSettingsName\">\n <div style=\"display: flex; gap: .5rem; flex-direction: column; border: gray solid thin; background-color: whitesmoke; padding: 1rem;\"\n >\n <div style=\"display: flex;\">\n <div *ngIf=\"storeProps?.storageSettingsName\" style=\"flex:1\">\n Database: <b>{{ storeProps?.storageSettingsName }}</b>\n </div>\n <div *ngIf=\"storeProps?.storageName\" style=\"flex:1\">\n Data: <b>{{ storeProps?.storageName }}</b>\n </div>\n </div>\n </div>\n </ng-container>\n\n <div style=\"margin-top: 2rem;\" [formGroup]=\"newStoreForm\" *ngIf=\"create; else LIST\">\n\n <h2>Create Store</h2>\n\n <div style=\"display: flex; gap: 1rem;\">\n <div style=\"flex:1\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Store Name</mat-label>\n <input matInput placeholder=\"sample\" formControlName=\"name\">\n </mat-form-field>\n </div>\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>Expires In...</mat-label>\n <mat-select formControlName=\"expiresIn\">\n <mat-option value=\"0\">None</mat-option>\n <mat-option value=\"30s\">30 Seconds</mat-option>\n <mat-option value=\"1mn\">1 Minute</mat-option>\n <mat-option value=\"1hr\">1 Hour</mat-option>\n <mat-option value=\"1d\">1 Day</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div style=\"margin-top: 1rem;\">\n <mat-slide-toggle formControlName=\"encrypted\">Encrypted</mat-slide-toggle>\n </div>\n </div>\n\n <div style=\"display: flex;\">\n <mat-form-field appearance=\"outline\" style=\"flex: 1;\">\n <mat-label>Data (Must be an Object or Array of any)</mat-label>\n <textarea matInput placeholder=\"[]\" formControlName=\"data\" #json></textarea>\n </mat-form-field>\n </div>\n <mat-error *ngIf=\"!isValidJSON(json.value)\">Not Valid Data</mat-error>\n\n <div style=\"display: flex;\">\n <span style=\"flex:1\"></span>\n <button mat-stroked-button (click)=\"onCreateStore()\" [disabled]=\"!(isValid && isValidJSON(json.value))\">\n Save Store\n </button>\n </div>\n\n </div>\n\n <ng-template #LIST>\n\n <div style=\"margin-top: 1rem;\">\n <mat-divider></mat-divider>\n </div>\n{{ settings() | json }}\n <div *ngIf=\"filterData(settings()) as data\">\n <ng-container *ngIf=\"data.length > 0; else NO_DATA\">\n <table mat-table [dataSource]=\"data\">\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef> Store </th>\n <td mat-cell *matCellDef=\"let element\" style=\"font-weight: bold; text-transform: uppercase;\"> {{element.name}} </td>\n </ng-container>\n\n <ng-container matColumnDef=\"id\">\n <th mat-header-cell *matHeaderCellDef> ID </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.id}} </td>\n </ng-container>\n\n <ng-container matColumnDef=\"encrypted\">\n <th mat-header-cell *matHeaderCellDef style=\"text-align: center;\"> Encrypted </th>\n <td mat-cell *matCellDef=\"let element\" style=\"text-align: center;\">\n <ng-container *ngIf=\"element.options.encrypted; else NO\">YES</ng-container>\n <ng-template #NO><span style=\"color:gray\">NO</span></ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"expires\">\n <th mat-header-cell *matHeaderCellDef style=\"text-align: center;\"> Expires </th>\n <td mat-cell *matCellDef=\"let element\" style=\"text-align: center;\">\n <ng-container *ngIf=\"element.options.expires !== 0; else NO_DATA\">\n {{expiresIn(element.options.expires)}}\n </ng-container>\n <ng-template #NO_DATA>\n \u221E\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"option\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let element\" style=\"padding-right: 0;\">\n <div style=\"display: flex;justify-content: flex-end;\">\n <button mat-icon-button color=\"warn\" (click)=\"onDelete(element); $event.stopPropagation()\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\" (click)=\"onSelectedRow(row)\"></tr>\n </table>\n </ng-container>\n\n <ng-template #NO_DATA>\n <h3 style=\"margin-top: 1rem;\">No Data</h3>\n </ng-template>\n\n <div *ngIf=\"storeSelected() as selectedStore\" style=\"margin-top: 2rem;\">\n <div style=\"margin-bottom: 1rem;\">\n <mat-divider></mat-divider>\n </div>\n\n <h3>STORE: <span style=\"font-weight: bold;\">{{ selectedStore.name | uppercase }}</span></h3>\n <h3>SETTINGS: {{ localStorageManagerService.setting(selectedStore.name) ? (localStorageManagerService.setting(selectedStore.name)() | json) : '{}' }}</h3>\n <div style=\"display: flex;\">\n <mat-form-field appearance=\"outline\" style=\"flex: 1;\">\n <mat-label>Data (Must be an Object or Array of any)</mat-label>\n <textarea matInput placeholder=\"[]\" #json [value]=\"selectedStoreData()\"></textarea>\n </mat-form-field>\n </div>\n <mat-error *ngIf=\"!isValidJSON(json.value)\">Not Valid Data</mat-error>\n\n <div style=\"display: flex; gap: .5rem;\">\n <span style=\"flex:1\"></span>\n <button mat-stroked-button (click)=\"onCancel()\">Cancel</button>\n <button mat-stroked-button (click)=\"onUpdate(selectedStore, json.value)\" [disabled]=\"!(isValidJSON(json.value))\">Update</button>\n </div>\n </div>\n </div>\n\n </ng-template>\n\n <div style=\"margin-top: 1rem;\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 1rem;\">\n <button mat-stroked-button (click)=\"onReset()\">Delete All Stores</button>\n </div>\n\n</div>\n\n\n<mat-menu #menu=\"matMenu\">\n <div style=\"padding: 1rem;\">\n <p>Please note that the LocalStorage (encryption) and management of data is dependant on initializing the APP_ID</p>\n <p>Must provide a value for <b>APP_ID</b> in AppModule->Providers</p>\n <mat-divider></mat-divider>\n <div style=\"font-size: smaller; margin-top: .5rem;\">\n <p>Example: UUID (self.crypto.randomUUID() to generate)</p>\n <div style=\"background-color: whitesmoke; padding: 1rem;\">\n &#123;<br>\n provide: APP_ID,<br>\n useValue: \"056991ac-3537-43ab-b5b9-83edf6554eff\",<br>\n &#125;\n </div>\n </div>\n </div>\n</mat-menu>\n", styles: [".mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor}.demo-row-is-clicked{font-weight:700}.mat-mdc-menu-panel.mat-mdc-menu-panel{max-width:280px!important}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i3$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i5.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i9.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i10$1.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i10$1.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "component", type: i11.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i12.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i13.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "pipe", type: i1$1.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }], encapsulation: i0.ViewEncapsulation.None }); }
3357
+ }
3358
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LocalStorageSignalsDemoComponent, decorators: [{
3359
+ type: Component,
3360
+ args: [{ selector: 'app-local-storage-signals-demo', encapsulation: ViewEncapsulation.None, template: "<div style=\"margin: 2rem;\">\n\n <div style=\"display: flex; gap: 1rem\">\n <h2 style=\"padding-top: .5rem; display: flex;\">\n <div style=\"padding-top: .5rem;\">Local Storage Manager</div>\n <div>\n <button mat-icon-button [matMenuTriggerFor]=\"menu\">\n <mat-icon>info</mat-icon>\n </button>\n </div>\n </h2>\n <span style=\"flex:1\"></span>\n <div style=\"padding-top: .25rem;\">\n <mat-button-toggle-group name=\"storage\" [formControl]=\"typeControl\" (change)=\"onCancel()\">\n <mat-button-toggle value=\"0\">Local Storage</mat-button-toggle>\n <mat-button-toggle value=\"1\">Session Storage</mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div style=\"margin-top: .25rem;\">\n <button mat-icon-button (click)=\"onCreate()\">\n <mat-icon>add</mat-icon>\n </button>\n </div>\n </div>\n\n <ng-container *ngIf=\"storeProps?.storageName || storeProps?.storageSettingsName\">\n <div style=\"display: flex; gap: .5rem; flex-direction: column; border: gray solid thin; background-color: whitesmoke; padding: 1rem;\"\n >\n <div style=\"display: flex;\">\n <div *ngIf=\"storeProps?.storageSettingsName\" style=\"flex:1\">\n Database: <b>{{ storeProps?.storageSettingsName }}</b>\n </div>\n <div *ngIf=\"storeProps?.storageName\" style=\"flex:1\">\n Data: <b>{{ storeProps?.storageName }}</b>\n </div>\n </div>\n </div>\n </ng-container>\n\n <div style=\"margin-top: 2rem;\" [formGroup]=\"newStoreForm\" *ngIf=\"create; else LIST\">\n\n <h2>Create Store</h2>\n\n <div style=\"display: flex; gap: 1rem;\">\n <div style=\"flex:1\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Store Name</mat-label>\n <input matInput placeholder=\"sample\" formControlName=\"name\">\n </mat-form-field>\n </div>\n <div>\n <mat-form-field appearance=\"outline\">\n <mat-label>Expires In...</mat-label>\n <mat-select formControlName=\"expiresIn\">\n <mat-option value=\"0\">None</mat-option>\n <mat-option value=\"30s\">30 Seconds</mat-option>\n <mat-option value=\"1mn\">1 Minute</mat-option>\n <mat-option value=\"1hr\">1 Hour</mat-option>\n <mat-option value=\"1d\">1 Day</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div style=\"margin-top: 1rem;\">\n <mat-slide-toggle formControlName=\"encrypted\">Encrypted</mat-slide-toggle>\n </div>\n </div>\n\n <div style=\"display: flex;\">\n <mat-form-field appearance=\"outline\" style=\"flex: 1;\">\n <mat-label>Data (Must be an Object or Array of any)</mat-label>\n <textarea matInput placeholder=\"[]\" formControlName=\"data\" #json></textarea>\n </mat-form-field>\n </div>\n <mat-error *ngIf=\"!isValidJSON(json.value)\">Not Valid Data</mat-error>\n\n <div style=\"display: flex;\">\n <span style=\"flex:1\"></span>\n <button mat-stroked-button (click)=\"onCreateStore()\" [disabled]=\"!(isValid && isValidJSON(json.value))\">\n Save Store\n </button>\n </div>\n\n </div>\n\n <ng-template #LIST>\n\n <div style=\"margin-top: 1rem;\">\n <mat-divider></mat-divider>\n </div>\n{{ settings() | json }}\n <div *ngIf=\"filterData(settings()) as data\">\n <ng-container *ngIf=\"data.length > 0; else NO_DATA\">\n <table mat-table [dataSource]=\"data\">\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef> Store </th>\n <td mat-cell *matCellDef=\"let element\" style=\"font-weight: bold; text-transform: uppercase;\"> {{element.name}} </td>\n </ng-container>\n\n <ng-container matColumnDef=\"id\">\n <th mat-header-cell *matHeaderCellDef> ID </th>\n <td mat-cell *matCellDef=\"let element\"> {{element.id}} </td>\n </ng-container>\n\n <ng-container matColumnDef=\"encrypted\">\n <th mat-header-cell *matHeaderCellDef style=\"text-align: center;\"> Encrypted </th>\n <td mat-cell *matCellDef=\"let element\" style=\"text-align: center;\">\n <ng-container *ngIf=\"element.options.encrypted; else NO\">YES</ng-container>\n <ng-template #NO><span style=\"color:gray\">NO</span></ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"expires\">\n <th mat-header-cell *matHeaderCellDef style=\"text-align: center;\"> Expires </th>\n <td mat-cell *matCellDef=\"let element\" style=\"text-align: center;\">\n <ng-container *ngIf=\"element.options.expires !== 0; else NO_DATA\">\n {{expiresIn(element.options.expires)}}\n </ng-container>\n <ng-template #NO_DATA>\n \u221E\n </ng-template>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"option\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let element\" style=\"padding-right: 0;\">\n <div style=\"display: flex;justify-content: flex-end;\">\n <button mat-icon-button color=\"warn\" (click)=\"onDelete(element); $event.stopPropagation()\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\" (click)=\"onSelectedRow(row)\"></tr>\n </table>\n </ng-container>\n\n <ng-template #NO_DATA>\n <h3 style=\"margin-top: 1rem;\">No Data</h3>\n </ng-template>\n\n <div *ngIf=\"storeSelected() as selectedStore\" style=\"margin-top: 2rem;\">\n <div style=\"margin-bottom: 1rem;\">\n <mat-divider></mat-divider>\n </div>\n\n <h3>STORE: <span style=\"font-weight: bold;\">{{ selectedStore.name | uppercase }}</span></h3>\n <h3>SETTINGS: {{ localStorageManagerService.setting(selectedStore.name) ? (localStorageManagerService.setting(selectedStore.name)() | json) : '{}' }}</h3>\n <div style=\"display: flex;\">\n <mat-form-field appearance=\"outline\" style=\"flex: 1;\">\n <mat-label>Data (Must be an Object or Array of any)</mat-label>\n <textarea matInput placeholder=\"[]\" #json [value]=\"selectedStoreData()\"></textarea>\n </mat-form-field>\n </div>\n <mat-error *ngIf=\"!isValidJSON(json.value)\">Not Valid Data</mat-error>\n\n <div style=\"display: flex; gap: .5rem;\">\n <span style=\"flex:1\"></span>\n <button mat-stroked-button (click)=\"onCancel()\">Cancel</button>\n <button mat-stroked-button (click)=\"onUpdate(selectedStore, json.value)\" [disabled]=\"!(isValidJSON(json.value))\">Update</button>\n </div>\n </div>\n </div>\n\n </ng-template>\n\n <div style=\"margin-top: 1rem;\">\n <mat-divider></mat-divider>\n </div>\n\n <div style=\"margin-top: 1rem;\">\n <button mat-stroked-button (click)=\"onReset()\">Delete All Stores</button>\n </div>\n\n</div>\n\n\n<mat-menu #menu=\"matMenu\">\n <div style=\"padding: 1rem;\">\n <p>Please note that the LocalStorage (encryption) and management of data is dependant on initializing the APP_ID</p>\n <p>Must provide a value for <b>APP_ID</b> in AppModule->Providers</p>\n <mat-divider></mat-divider>\n <div style=\"font-size: smaller; margin-top: .5rem;\">\n <p>Example: UUID (self.crypto.randomUUID() to generate)</p>\n <div style=\"background-color: whitesmoke; padding: 1rem;\">\n &#123;<br>\n provide: APP_ID,<br>\n useValue: \"056991ac-3537-43ab-b5b9-83edf6554eff\",<br>\n &#125;\n </div>\n </div>\n </div>\n</mat-menu>\n", styles: [".mat-mdc-row .mat-mdc-cell{border-bottom:1px solid transparent;border-top:1px solid transparent;cursor:pointer}.mat-mdc-row:hover .mat-mdc-cell{border-color:currentColor}.demo-row-is-clicked{font-weight:700}.mat-mdc-menu-panel.mat-mdc-menu-panel{max-width:280px!important}\n"] }]
3361
+ }], ctorParameters: () => [{ type: ConfigOptions, decorators: [{
3362
+ type: Inject,
3363
+ args: [CONFIG_SETTINGS_TOKEN]
3364
+ }] }] });
3365
+
2894
3366
  class HttpRequestServicesDemoComponent {
2895
3367
  constructor(configOptions) {
2896
3368
  this.configOptions = configOptions;
2897
3369
  this.requestTypes = [
2898
3370
  { name: "Http Service", value: 'http_service' },
3371
+ { name: "Http Signals Service", value: 'http-signals_service' },
2899
3372
  { name: "Http State Service", value: 'http_state_service' },
2900
3373
  { name: "Database Service", value: 'database_service', divider: true, disabled: true },
2901
3374
  { name: "Local Storage Service", value: 'local_storage_service' },
3375
+ { name: "Local Signals Storage Service", value: 'local_storage_signals_service' },
2902
3376
  ];
2903
3377
  this.selectedService = this.requestTypes[0].value;
2904
3378
  }
@@ -2910,11 +3384,11 @@ class HttpRequestServicesDemoComponent {
2910
3384
  this.selectedService = this.requestTypes[type].value;
2911
3385
  }
2912
3386
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: HttpRequestServicesDemoComponent, deps: [{ token: CONFIG_SETTINGS_TOKEN }], target: i0.ɵɵFactoryTarget.Component }); }
2913
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: HttpRequestServicesDemoComponent, selector: "app-http-request-services-demo", ngImport: i0, template: "<mat-toolbar style=\"display:flex\">\n <div>Http Request Manager Services</div>\n <div style=\"flex:1\"></div>\n <button mat-stroked-button [matMenuTriggerFor]=\"menu\">Services</button>\n <mat-menu #menu=\"matMenu\">\n <ng-container *ngFor=\"let type of requestTypes; index as i\">\n <div\n *ngIf=\"type?.divider\"\n style=\"margin-top: .5rem; margin-bottom: .5rem;\"\n >\n <mat-divider></mat-divider>\n </div>\n <button\n mat-menu-item\n (click)=\"onSelected(i)\"\n [disabled]=\"type.disabled\"\n >\n {{ type.name }}\n </button>\n </ng-container>\n\n </mat-menu>\n</mat-toolbar>\n\n<span [ngSwitch]=\"selectedService\">\n <p *ngSwitchCase=\"'http_service'\">\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <app-request-manager-demo></app-request-manager-demo>\n </p>\n <p *ngSwitchCase=\"'http_state_service'\">\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <app-request-manager-state-demo></app-request-manager-state-demo>\n </p>\n <p *ngSwitchCase=\"'database_service'\">\n <!-- <app-database-data-demo></app-database-data-demo> -->\n </p>\n <p *ngSwitchCase=\"'local_storage_service'\">\n <ng-container *ngTemplateOutlet=\"LOCAL_OPTIONS\"></ng-container>\n <app-local-storage-demo></app-local-storage-demo>\n </p>\n <p *ngSwitchDefault>\n Other\n </p>\n</span>\n\n<ng-template #HTTP_OPTIONS>\n <ng-container *ngIf=\"injectionOptions?.httpRequestOptions\">\n <div class=\"box\">\n <h3 style=\"font-weight: bold;\">Injection Token Detected - HTTP Options</h3>\n {{ injectionOptions?.httpRequestOptions| json }}\n </div>\n </ng-container>\n</ng-template>\n\n<ng-template #LOCAL_OPTIONS>\n <ng-container class=\"box\" *ngIf=\"injectionOptions?.LocalStorageOptions\">\n <div class=\"box\">\n <h3 style=\"font-weight: bold;\">Injection Token Detected - LocalStorage Options</h3>\n {{ injectionOptions?.LocalStorageOptions| json }}\n </div>\n </ng-container>\n</ng-template>\n\n\n", styles: [".box{padding:1rem;background-color:#f5f5f5;border:thin gray solid;margin-top:1rem}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "component", type: i3$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i12.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: i5$1.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "component", type: RequestManagerStateDemoComponent, selector: "app-request-manager-state-demo" }, { kind: "component", type: RequestManagerDemoComponent, selector: "app-request-manager-demo" }, { kind: "component", type: LocalStorageDemoComponent, selector: "app-local-storage-demo" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }] }); }
3387
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: HttpRequestServicesDemoComponent, selector: "app-http-request-services-demo", ngImport: i0, template: "<mat-toolbar style=\"display:flex\">\n <div>Http Request Manager Services</div>\n <div style=\"flex:1\"></div>\n <button mat-stroked-button [matMenuTriggerFor]=\"menu\">Services</button>\n <mat-menu #menu=\"matMenu\">\n <ng-container *ngFor=\"let type of requestTypes; index as i\">\n <div\n *ngIf=\"type?.divider\"\n style=\"margin-top: .5rem; margin-bottom: .5rem;\"\n >\n <mat-divider></mat-divider>\n </div>\n <button\n mat-menu-item\n (click)=\"onSelected(i)\"\n [disabled]=\"type.disabled\"\n >\n {{ type.name }}\n </button>\n </ng-container>\n\n </mat-menu>\n</mat-toolbar>\n\n<span [ngSwitch]=\"selectedService\">\n <p *ngSwitchCase=\"'http_service'\">\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <app-request-manager-demo></app-request-manager-demo>\n </p>\n <p *ngSwitchCase=\"'http_signals_service'\">\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <!-- <app-request-signals-manager-demo></app-request-signals-manager-demo> -->\n </p>\n <p *ngSwitchCase=\"'http_state_service'\">\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <app-request-manager-state-demo></app-request-manager-state-demo>\n </p>\n <p *ngSwitchCase=\"'database_service'\">\n <!-- <app-database-data-demo></app-database-data-demo> -->\n </p>\n <p *ngSwitchCase=\"'local_storage_service'\">\n <ng-container *ngTemplateOutlet=\"LOCAL_OPTIONS\"></ng-container>\n <app-local-storage-demo></app-local-storage-demo>\n </p>\n <p *ngSwitchCase=\"'local_storage_signals_service'\">\n <ng-container *ngTemplateOutlet=\"LOCAL_OPTIONS\"></ng-container>\n <app-local-storage-signals-demo></app-local-storage-signals-demo>\n </p>\n <p *ngSwitchDefault>\n Other\n </p>\n</span>\n\n<ng-template #HTTP_OPTIONS>\n <ng-container *ngIf=\"injectionOptions?.httpRequestOptions\">\n <div class=\"box\">\n <h3 style=\"font-weight: bold;\">Injection Token Detected - HTTP Options</h3>\n {{ injectionOptions?.httpRequestOptions| json }}\n </div>\n </ng-container>\n</ng-template>\n\n<ng-template #LOCAL_OPTIONS>\n <ng-container class=\"box\" *ngIf=\"injectionOptions?.LocalStorageOptions\">\n <div class=\"box\">\n <h3 style=\"font-weight: bold;\">Injection Token Detected - LocalStorage Options</h3>\n {{ injectionOptions?.LocalStorageOptions| json }}\n </div>\n </ng-container>\n</ng-template>\n\n\n", styles: [".box{padding:1rem;background-color:#f5f5f5;border:thin gray solid;margin-top:1rem}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "component", type: i3$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i12.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: i5$1.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "component", type: RequestManagerStateDemoComponent, selector: "app-request-manager-state-demo" }, { kind: "component", type: RequestManagerDemoComponent, selector: "app-request-manager-demo" }, { kind: "component", type: LocalStorageDemoComponent, selector: "app-local-storage-demo" }, { kind: "component", type: LocalStorageSignalsDemoComponent, selector: "app-local-storage-signals-demo" }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }] }); }
2914
3388
  }
2915
3389
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: HttpRequestServicesDemoComponent, decorators: [{
2916
3390
  type: Component,
2917
- args: [{ selector: 'app-http-request-services-demo', template: "<mat-toolbar style=\"display:flex\">\n <div>Http Request Manager Services</div>\n <div style=\"flex:1\"></div>\n <button mat-stroked-button [matMenuTriggerFor]=\"menu\">Services</button>\n <mat-menu #menu=\"matMenu\">\n <ng-container *ngFor=\"let type of requestTypes; index as i\">\n <div\n *ngIf=\"type?.divider\"\n style=\"margin-top: .5rem; margin-bottom: .5rem;\"\n >\n <mat-divider></mat-divider>\n </div>\n <button\n mat-menu-item\n (click)=\"onSelected(i)\"\n [disabled]=\"type.disabled\"\n >\n {{ type.name }}\n </button>\n </ng-container>\n\n </mat-menu>\n</mat-toolbar>\n\n<span [ngSwitch]=\"selectedService\">\n <p *ngSwitchCase=\"'http_service'\">\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <app-request-manager-demo></app-request-manager-demo>\n </p>\n <p *ngSwitchCase=\"'http_state_service'\">\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <app-request-manager-state-demo></app-request-manager-state-demo>\n </p>\n <p *ngSwitchCase=\"'database_service'\">\n <!-- <app-database-data-demo></app-database-data-demo> -->\n </p>\n <p *ngSwitchCase=\"'local_storage_service'\">\n <ng-container *ngTemplateOutlet=\"LOCAL_OPTIONS\"></ng-container>\n <app-local-storage-demo></app-local-storage-demo>\n </p>\n <p *ngSwitchDefault>\n Other\n </p>\n</span>\n\n<ng-template #HTTP_OPTIONS>\n <ng-container *ngIf=\"injectionOptions?.httpRequestOptions\">\n <div class=\"box\">\n <h3 style=\"font-weight: bold;\">Injection Token Detected - HTTP Options</h3>\n {{ injectionOptions?.httpRequestOptions| json }}\n </div>\n </ng-container>\n</ng-template>\n\n<ng-template #LOCAL_OPTIONS>\n <ng-container class=\"box\" *ngIf=\"injectionOptions?.LocalStorageOptions\">\n <div class=\"box\">\n <h3 style=\"font-weight: bold;\">Injection Token Detected - LocalStorage Options</h3>\n {{ injectionOptions?.LocalStorageOptions| json }}\n </div>\n </ng-container>\n</ng-template>\n\n\n", styles: [".box{padding:1rem;background-color:#f5f5f5;border:thin gray solid;margin-top:1rem}\n"] }]
3391
+ args: [{ selector: 'app-http-request-services-demo', template: "<mat-toolbar style=\"display:flex\">\n <div>Http Request Manager Services</div>\n <div style=\"flex:1\"></div>\n <button mat-stroked-button [matMenuTriggerFor]=\"menu\">Services</button>\n <mat-menu #menu=\"matMenu\">\n <ng-container *ngFor=\"let type of requestTypes; index as i\">\n <div\n *ngIf=\"type?.divider\"\n style=\"margin-top: .5rem; margin-bottom: .5rem;\"\n >\n <mat-divider></mat-divider>\n </div>\n <button\n mat-menu-item\n (click)=\"onSelected(i)\"\n [disabled]=\"type.disabled\"\n >\n {{ type.name }}\n </button>\n </ng-container>\n\n </mat-menu>\n</mat-toolbar>\n\n<span [ngSwitch]=\"selectedService\">\n <p *ngSwitchCase=\"'http_service'\">\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <app-request-manager-demo></app-request-manager-demo>\n </p>\n <p *ngSwitchCase=\"'http_signals_service'\">\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <!-- <app-request-signals-manager-demo></app-request-signals-manager-demo> -->\n </p>\n <p *ngSwitchCase=\"'http_state_service'\">\n <ng-container *ngTemplateOutlet=\"HTTP_OPTIONS\"></ng-container>\n <app-request-manager-state-demo></app-request-manager-state-demo>\n </p>\n <p *ngSwitchCase=\"'database_service'\">\n <!-- <app-database-data-demo></app-database-data-demo> -->\n </p>\n <p *ngSwitchCase=\"'local_storage_service'\">\n <ng-container *ngTemplateOutlet=\"LOCAL_OPTIONS\"></ng-container>\n <app-local-storage-demo></app-local-storage-demo>\n </p>\n <p *ngSwitchCase=\"'local_storage_signals_service'\">\n <ng-container *ngTemplateOutlet=\"LOCAL_OPTIONS\"></ng-container>\n <app-local-storage-signals-demo></app-local-storage-signals-demo>\n </p>\n <p *ngSwitchDefault>\n Other\n </p>\n</span>\n\n<ng-template #HTTP_OPTIONS>\n <ng-container *ngIf=\"injectionOptions?.httpRequestOptions\">\n <div class=\"box\">\n <h3 style=\"font-weight: bold;\">Injection Token Detected - HTTP Options</h3>\n {{ injectionOptions?.httpRequestOptions| json }}\n </div>\n </ng-container>\n</ng-template>\n\n<ng-template #LOCAL_OPTIONS>\n <ng-container class=\"box\" *ngIf=\"injectionOptions?.LocalStorageOptions\">\n <div class=\"box\">\n <h3 style=\"font-weight: bold;\">Injection Token Detected - LocalStorage Options</h3>\n {{ injectionOptions?.LocalStorageOptions| json }}\n </div>\n </ng-container>\n</ng-template>\n\n\n", styles: [".box{padding:1rem;background-color:#f5f5f5;border:thin gray solid;margin-top:1rem}\n"] }]
2918
3392
  }], ctorParameters: () => [{ type: ConfigOptions, decorators: [{
2919
3393
  type: Inject,
2920
3394
  args: [CONFIG_SETTINGS_TOKEN]
@@ -2993,9 +3467,8 @@ class HttpRequestManagerModule {
2993
3467
  static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: HttpRequestManagerModule, declarations: [HttpRequestServicesDemoComponent,
2994
3468
  RequestManagerStateDemoComponent,
2995
3469
  RequestManagerDemoComponent,
2996
- LocalStorageDemoComponent
2997
- // DatabaseDataDemoComponent,
2998
- ], imports: [CommonModule,
3470
+ LocalStorageDemoComponent,
3471
+ LocalStorageSignalsDemoComponent], imports: [CommonModule,
2999
3472
  ToastMessageDisplayModule,
3000
3473
  FormsModule,
3001
3474
  ReactiveFormsModule,
@@ -3014,7 +3487,19 @@ class HttpRequestManagerModule {
3014
3487
  MatInputModule,
3015
3488
  MatToolbarModule,
3016
3489
  MatSlideToggleModule, i1.TranslateModule, MatSidenavModule,
3017
- FileDownloaderModule], exports: [HttpRequestServicesDemoComponent] }); }
3490
+ FileDownloaderModule], exports: [HttpRequestServicesDemoComponent,
3491
+ // Re-export commonly used modules so demo component templates have access to
3492
+ // Angular common pipes and Material components when the library is imported.
3493
+ CommonModule,
3494
+ MatButtonToggleModule,
3495
+ MatFormFieldModule,
3496
+ MatSelectModule,
3497
+ MatInputModule,
3498
+ MatIconModule,
3499
+ MatTableModule,
3500
+ MatSlideToggleModule,
3501
+ MatProgressBarModule,
3502
+ MatDividerModule] }); }
3018
3503
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: HttpRequestManagerModule, providers: [
3019
3504
  { provide: HTTP_INTERCEPTORS, useClass: WithCredentialsInterceptor, multi: true },
3020
3505
  { provide: HTTP_INTERCEPTORS, useClass: RequestHeadersInterceptor, multi: true },
@@ -3042,7 +3527,19 @@ class HttpRequestManagerModule {
3042
3527
  MatSlideToggleModule,
3043
3528
  TranslateModule.forRoot(),
3044
3529
  MatSidenavModule,
3045
- FileDownloaderModule] }); }
3530
+ FileDownloaderModule,
3531
+ // Re-export commonly used modules so demo component templates have access to
3532
+ // Angular common pipes and Material components when the library is imported.
3533
+ CommonModule,
3534
+ MatButtonToggleModule,
3535
+ MatFormFieldModule,
3536
+ MatSelectModule,
3537
+ MatInputModule,
3538
+ MatIconModule,
3539
+ MatTableModule,
3540
+ MatSlideToggleModule,
3541
+ MatProgressBarModule,
3542
+ MatDividerModule] }); }
3046
3543
  }
3047
3544
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: HttpRequestManagerModule, decorators: [{
3048
3545
  type: NgModule,
@@ -3075,11 +3572,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
3075
3572
  HttpRequestServicesDemoComponent,
3076
3573
  RequestManagerStateDemoComponent,
3077
3574
  RequestManagerDemoComponent,
3078
- LocalStorageDemoComponent
3575
+ LocalStorageDemoComponent,
3576
+ LocalStorageSignalsDemoComponent,
3079
3577
  // DatabaseDataDemoComponent,
3080
3578
  ],
3081
3579
  exports: [
3082
3580
  HttpRequestServicesDemoComponent,
3581
+ // Re-export commonly used modules so demo component templates have access to
3582
+ // Angular common pipes and Material components when the library is imported.
3583
+ CommonModule,
3584
+ MatButtonToggleModule,
3585
+ MatFormFieldModule,
3586
+ MatSelectModule,
3587
+ MatInputModule,
3588
+ MatIconModule,
3589
+ MatTableModule,
3590
+ MatSlideToggleModule,
3591
+ MatProgressBarModule,
3592
+ MatDividerModule,
3083
3593
  ],
3084
3594
  providers: [
3085
3595
  { provide: HTTP_INTERCEPTORS, useClass: WithCredentialsInterceptor, multi: true },
@@ -3440,5 +3950,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
3440
3950
  * Generated bundle index. Do not edit.
3441
3951
  */
3442
3952
 
3443
- export { ApiRequest, AppService, AsymmetricalEncryptionService, ConfigHTTPOptions, ConfigOptions, DataType, DatabaseDataDemoComponent, DatabaseStorage, ErrorDisplaySettings, GlobalStoreOptions, HTTPManagerService, HTTPManagerStateService, HeadersService, HttpRequestManagerModule, HttpRequestServicesDemoComponent, LocalStorageDemoComponent, LocalStorageManagerService, LocalStorageOptions, PathQueryService, Random, RandomNumber, RandomNumbers, RandomNumbersUnique, RandomSignature, RandomStr, RequestErrorInterceptor, RequestHeadersInterceptor, RequestManagerDemoComponent, RequestManagerStateDemoComponent, RequestOptions, RetryOptions, SettingOptions, StorageData, StorageOption, StorageType, SymmetricalEncryptionService, UUID, UtilsService, WithCredentialsInterceptor, countdown, delayedRetry, requestPolling, requestStreaming };
3953
+ export { ApiRequest, AppService, AsymmetricalEncryptionService, ConfigHTTPOptions, ConfigOptions, DataType, DatabaseDataDemoComponent, DatabaseStorage, ErrorDisplaySettings, GlobalStoreOptions, HTTPManagerService, HTTPManagerStateService, HeadersService, HttpRequestManagerModule, HttpRequestServicesDemoComponent, LocalStorageDemoComponent, LocalStorageManagerService, LocalStorageOptions, LocalStorageSignalsManagerService, PathQueryService, Random, RandomNumber, RandomNumbers, RandomNumbersUnique, RandomSignature, RandomStr, RequestErrorInterceptor, RequestHeadersInterceptor, RequestManagerDemoComponent, RequestManagerStateDemoComponent, RequestOptions, RetryOptions, SettingOptions, StorageData, StorageOption, StorageType, SymmetricalEncryptionService, UUID, UtilsService, WithCredentialsInterceptor, countdown, delayedRetry, requestPolling, requestStreaming };
3444
3954
  //# sourceMappingURL=http-request-manager.mjs.map