ngx-dev-toolbar 0.0.2-1 → 0.0.2-3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -3
- package/project.json +1 -1
- package/src/components/button/button.component.scss +36 -0
- package/src/components/button/button.component.ts +36 -0
- package/src/components/icons/angular-icon.component.ts +35 -0
- package/src/components/icons/bug-icon.component.ts +27 -0
- package/src/components/icons/code-icon.component.ts +24 -0
- package/src/components/icons/database-icon.component.ts +27 -0
- package/src/components/icons/gauge-icon.component.ts +27 -0
- package/src/components/icons/gear-icon.component.ts +27 -0
- package/src/components/icons/git-branch-icon.component.ts +27 -0
- package/src/components/icons/icon.component.ts +105 -0
- package/src/components/icons/icon.models.ts +21 -0
- package/src/components/icons/layout-icon.component.ts +24 -0
- package/src/components/icons/lighting-icon.component.ts +24 -0
- package/src/components/icons/moon-icon.component.ts +27 -0
- package/src/components/icons/network-icon.component.ts +27 -0
- package/src/components/icons/puzzle-icon.component.ts +27 -0
- package/src/components/icons/refresh-icon.component.ts +27 -0
- package/src/components/icons/star-icon.component.ts +27 -0
- package/src/components/icons/sun-icon.component.ts +27 -0
- package/src/components/icons/terminal-icon.component.ts +27 -0
- package/src/components/icons/toggle-left-icon.component.ts +27 -0
- package/src/components/icons/translate-icon.component.ts +23 -0
- package/src/components/icons/users-icon.component.ts +27 -0
- package/src/components/input/input.component.ts +66 -0
- package/src/components/select/select.component.scss +102 -0
- package/src/components/select/select.component.ts +40 -0
- package/src/components/tool-button/tool-button.component.scss +67 -0
- package/src/components/tool-button/tool-button.component.ts +126 -0
- package/src/components/toolbar-tool/toolbar-tool.component.scss +9 -0
- package/src/components/toolbar-tool/toolbar-tool.component.ts +128 -0
- package/src/components/toolbar-tool/toolbar-tool.models.ts +9 -0
- package/src/components/window/window.component.scss +99 -0
- package/src/components/window/window.component.ts +79 -0
- package/src/components/window/window.models.ts +28 -0
- package/src/dev-toolbar-state.service.ts +89 -0
- package/src/dev-toolbar.component.scss +22 -0
- package/src/dev-toolbar.component.ts +104 -0
- package/src/index.ts +6 -1
- package/src/models/dev-tools.interface.ts +19 -0
- package/src/styles.scss +363 -0
- package/src/tools/feature-flags-tool/feature-flags-internal.service.ts +96 -0
- package/src/tools/feature-flags-tool/feature-flags-tool.component.ts +262 -0
- package/src/tools/feature-flags-tool/feature-flags.models.ts +10 -0
- package/src/tools/feature-flags-tool/feature-flags.service.ts +26 -0
- package/src/tools/home-tool/home-tool.component.scss +61 -0
- package/src/tools/home-tool/home-tool.component.ts +72 -0
- package/src/tools/home-tool/settings.models.ts +3 -0
- package/src/tools/home-tool/settings.service.spec.ts +59 -0
- package/src/tools/home-tool/settings.service.ts +21 -0
- package/src/tools/language-tool/language-internal.service.ts +51 -0
- package/src/tools/language-tool/language-tool.component.scss +7 -0
- package/src/tools/language-tool/language-tool.component.ts +75 -0
- package/src/tools/language-tool/language.models.ts +4 -0
- package/src/tools/language-tool/language.service.ts +26 -0
- package/src/utils/storage.service.ts +19 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Injectable, inject } from '@angular/core';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { DevToolsService } from '../../models/dev-tools.interface';
|
|
4
|
+
import { DevToolbarInternalFeatureFlagService } from './feature-flags-internal.service';
|
|
5
|
+
import { Flag } from './feature-flags.models';
|
|
6
|
+
|
|
7
|
+
@Injectable({ providedIn: 'root' })
|
|
8
|
+
export class DevToolbarFeatureFlagService implements DevToolsService<Flag> {
|
|
9
|
+
private internalService = inject(DevToolbarInternalFeatureFlagService);
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Sets the available flags that will be displayed in the tool on the dev toolbar
|
|
13
|
+
* @param flags The flags to be displayed
|
|
14
|
+
*/
|
|
15
|
+
setAvailableOptions(flags: Flag[]): void {
|
|
16
|
+
this.internalService.setAppFlags(flags);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Gets the flags that were forced/modified through the tool on the dev toolbar
|
|
21
|
+
* @returns Observable of forced flags array
|
|
22
|
+
*/
|
|
23
|
+
getForcedValues(): Observable<Flag[]> {
|
|
24
|
+
return this.internalService.getForcedFlags();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
@use '../../styles' as *;
|
|
2
|
+
|
|
3
|
+
.settings {
|
|
4
|
+
padding: var(--devtools-spacing-md);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.instruction {
|
|
8
|
+
display: flex;
|
|
9
|
+
justify-content: space-between;
|
|
10
|
+
align-items: center;
|
|
11
|
+
gap: var(--devtools-spacing-md);
|
|
12
|
+
|
|
13
|
+
&__label {
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
gap: var(--devtools-spacing-xs);
|
|
17
|
+
|
|
18
|
+
&-text {
|
|
19
|
+
color: var(--devtools-text-primary);
|
|
20
|
+
font-size: var(--devtools-font-size-sm);
|
|
21
|
+
font-weight: 500;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
&-description {
|
|
25
|
+
color: var(--devtools-text-muted);
|
|
26
|
+
font-size: var(--devtools-font-size-xs);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.theme {
|
|
32
|
+
display: flex;
|
|
33
|
+
gap: var(--devtools-spacing-xs);
|
|
34
|
+
|
|
35
|
+
&__button {
|
|
36
|
+
display: flex;
|
|
37
|
+
align-items: center;
|
|
38
|
+
justify-content: center;
|
|
39
|
+
padding: var(--devtools-spacing-xs);
|
|
40
|
+
border-radius: var(--devtools-border-radius-small);
|
|
41
|
+
border: 1px solid var(--devtools-border-subtle);
|
|
42
|
+
background: var(--devtools-bg-primary);
|
|
43
|
+
color: var(--devtools-text-primary);
|
|
44
|
+
cursor: pointer;
|
|
45
|
+
transition: var(--devtools-transition-default);
|
|
46
|
+
|
|
47
|
+
&:hover {
|
|
48
|
+
background: var(--devtools-hover-bg);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
&--active {
|
|
52
|
+
background: var(--devtools-primary);
|
|
53
|
+
color: var(--devtools-text-on-primary);
|
|
54
|
+
border-color: var(--devtools-primary);
|
|
55
|
+
|
|
56
|
+
&:hover {
|
|
57
|
+
background: var(--devtools-primary);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ChangeDetectionStrategy,
|
|
3
|
+
Component,
|
|
4
|
+
inject,
|
|
5
|
+
input,
|
|
6
|
+
} from '@angular/core';
|
|
7
|
+
import { FormsModule } from '@angular/forms';
|
|
8
|
+
import { DevToolbarButtonComponent } from '../../components/button/button.component';
|
|
9
|
+
import { DevToolbarToolComponent } from '../../components/toolbar-tool/toolbar-tool.component';
|
|
10
|
+
import { WindowConfig } from '../../components/window/window.models';
|
|
11
|
+
import { DevToolbarStateService } from '../../dev-toolbar-state.service';
|
|
12
|
+
import { SettingsService } from './settings.service';
|
|
13
|
+
|
|
14
|
+
type ThemeType = 'light' | 'dark';
|
|
15
|
+
|
|
16
|
+
@Component({
|
|
17
|
+
selector: 'ndt-home-tool',
|
|
18
|
+
standalone: true,
|
|
19
|
+
imports: [DevToolbarToolComponent, FormsModule, DevToolbarButtonComponent],
|
|
20
|
+
template: `
|
|
21
|
+
<ndt-toolbar-tool [windowConfig]="windowConfig" title="Home" icon="angular">
|
|
22
|
+
<section class="settings">
|
|
23
|
+
<div class="instruction">
|
|
24
|
+
<div class="instruction__label">
|
|
25
|
+
<span class="instruction__label-text">Theme</span>
|
|
26
|
+
<span class="instruction__label-description">
|
|
27
|
+
Switch between light and dark mode
|
|
28
|
+
</span>
|
|
29
|
+
</div>
|
|
30
|
+
<div class="instruction__control">
|
|
31
|
+
<div class="theme">
|
|
32
|
+
<ndt-button
|
|
33
|
+
[isActive]="true"
|
|
34
|
+
(click)="onToggleTheme()"
|
|
35
|
+
variant="icon"
|
|
36
|
+
[ariaLabel]="
|
|
37
|
+
state.isDarkTheme()
|
|
38
|
+
? 'Switch to light theme'
|
|
39
|
+
: 'Switch to dark theme'
|
|
40
|
+
"
|
|
41
|
+
[icon]="state.isDarkTheme() ? 'sun' : 'moon'"
|
|
42
|
+
/>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</section>
|
|
47
|
+
</ndt-toolbar-tool>
|
|
48
|
+
`,
|
|
49
|
+
styleUrls: ['./home-tool.component.scss'],
|
|
50
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
51
|
+
})
|
|
52
|
+
export class DevToolbarHomeToolComponent {
|
|
53
|
+
state = inject(DevToolbarStateService);
|
|
54
|
+
settingsService = inject(SettingsService);
|
|
55
|
+
|
|
56
|
+
readonly badge = input<string | number>();
|
|
57
|
+
readonly title = `Angular Dev Toolbar`;
|
|
58
|
+
readonly windowConfig: WindowConfig = {
|
|
59
|
+
title: this.title,
|
|
60
|
+
isClosable: true,
|
|
61
|
+
id: 'ndt-home',
|
|
62
|
+
size: 'medium',
|
|
63
|
+
description: '',
|
|
64
|
+
isBeta: true,
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
onToggleTheme(): void {
|
|
68
|
+
const newTheme: ThemeType = this.state.isDarkTheme() ? 'light' : 'dark';
|
|
69
|
+
this.settingsService.setSettings({ isDarkMode: newTheme === 'dark' });
|
|
70
|
+
this.state.setTheme(newTheme);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { TestBed } from '@angular/core/testing';
|
|
2
|
+
import { DevToolsStorageService } from '../../utils/storage.service';
|
|
3
|
+
import { SettingsService } from './settings.service';
|
|
4
|
+
|
|
5
|
+
describe('SettingsService', () => {
|
|
6
|
+
let service: SettingsService;
|
|
7
|
+
let storageServiceMock: DevToolsStorageService;
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
storageServiceMock = {
|
|
11
|
+
get: vi.fn(),
|
|
12
|
+
set: vi.fn(),
|
|
13
|
+
} as unknown as DevToolsStorageService;
|
|
14
|
+
|
|
15
|
+
TestBed.configureTestingModule({
|
|
16
|
+
providers: [
|
|
17
|
+
SettingsService,
|
|
18
|
+
{ provide: DevToolsStorageService, useValue: storageServiceMock },
|
|
19
|
+
],
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
service = TestBed.inject(SettingsService);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should be created', () => {
|
|
26
|
+
expect(service).toBeTruthy();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe('getSettings', () => {
|
|
30
|
+
it('should return settings from storage if they exist', () => {
|
|
31
|
+
const mockSettings = { isDarkMode: true };
|
|
32
|
+
vi.spyOn(storageServiceMock, 'get').mockReturnValue(mockSettings);
|
|
33
|
+
|
|
34
|
+
const result = service.getSettings();
|
|
35
|
+
|
|
36
|
+
expect(storageServiceMock.get).toHaveBeenCalledWith('settings');
|
|
37
|
+
expect(result).toEqual(mockSettings);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should return default settings if nothing in storage', () => {
|
|
41
|
+
vi.spyOn(storageServiceMock, 'get').mockReturnValue(null);
|
|
42
|
+
|
|
43
|
+
const result = service.getSettings();
|
|
44
|
+
|
|
45
|
+
expect(storageServiceMock.get).toHaveBeenCalledWith('settings');
|
|
46
|
+
expect(result).toEqual({ isDarkMode: false });
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe('setSettings', () => {
|
|
51
|
+
it('should save settings to storage', () => {
|
|
52
|
+
const settings = { isDarkMode: true };
|
|
53
|
+
|
|
54
|
+
service.setSettings(settings);
|
|
55
|
+
|
|
56
|
+
expect(storageServiceMock.set).toHaveBeenCalledWith('settings', settings);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Injectable, inject } from '@angular/core';
|
|
2
|
+
import { DevToolsStorageService } from '../../utils/storage.service';
|
|
3
|
+
import { Settings } from './settings.models';
|
|
4
|
+
|
|
5
|
+
@Injectable({ providedIn: 'root' })
|
|
6
|
+
export class SettingsService {
|
|
7
|
+
private readonly STORAGE_KEY = 'settings';
|
|
8
|
+
private readonly storageService = inject(DevToolsStorageService);
|
|
9
|
+
|
|
10
|
+
public getSettings(): Settings {
|
|
11
|
+
return (
|
|
12
|
+
this.storageService.get<Settings>(this.STORAGE_KEY) || {
|
|
13
|
+
isDarkMode: false,
|
|
14
|
+
}
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public setSettings(settings: Settings): void {
|
|
19
|
+
this.storageService.set(this.STORAGE_KEY, settings);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Injectable, inject } from '@angular/core';
|
|
2
|
+
import { toSignal } from '@angular/core/rxjs-interop';
|
|
3
|
+
import { BehaviorSubject, Observable, map } from 'rxjs';
|
|
4
|
+
import { DevToolsStorageService } from '../../utils/storage.service';
|
|
5
|
+
import { Language } from './language.models';
|
|
6
|
+
|
|
7
|
+
@Injectable({ providedIn: 'root' })
|
|
8
|
+
export class DevToolbarInternalLanguageService {
|
|
9
|
+
private readonly STORAGE_KEY = 'language';
|
|
10
|
+
private readonly storageService = inject(DevToolsStorageService);
|
|
11
|
+
|
|
12
|
+
private languages$ = new BehaviorSubject<Language[]>([]);
|
|
13
|
+
private forcedLanguage$ = new BehaviorSubject<Language | null>(null);
|
|
14
|
+
|
|
15
|
+
public languages = toSignal(this.languages$, { initialValue: [] });
|
|
16
|
+
|
|
17
|
+
constructor() {
|
|
18
|
+
this.loadForcedLanguage();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
setAppLanguages(languages: Language[]): void {
|
|
22
|
+
this.languages$.next(languages);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
getAppLanguages(): Observable<Language[]> {
|
|
26
|
+
return this.languages$.asObservable();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
setForcedLanguage(language: Language): void {
|
|
30
|
+
this.forcedLanguage$.next(language);
|
|
31
|
+
this.storageService.set(this.STORAGE_KEY, language);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
getForcedLanguage(): Observable<Language[]> {
|
|
35
|
+
return this.forcedLanguage$.pipe(
|
|
36
|
+
map((language) => (language ? [language] : []))
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
removeForcedLanguage(): void {
|
|
41
|
+
this.forcedLanguage$.next(null);
|
|
42
|
+
this.storageService.remove(this.STORAGE_KEY);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private loadForcedLanguage(): void {
|
|
46
|
+
const savedLanguage = this.storageService.get<Language>(this.STORAGE_KEY);
|
|
47
|
+
if (savedLanguage) {
|
|
48
|
+
this.forcedLanguage$.next(savedLanguage);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Component, inject, signal } from '@angular/core';
|
|
2
|
+
import { toSignal } from '@angular/core/rxjs-interop';
|
|
3
|
+
import { firstValueFrom, map } from 'rxjs';
|
|
4
|
+
import { DevToolbarSelectComponent } from '../../components/select/select.component';
|
|
5
|
+
import { DevToolbarToolComponent } from '../../components/toolbar-tool/toolbar-tool.component';
|
|
6
|
+
import { WindowSize } from '../../components/window/window.models';
|
|
7
|
+
import { DevToolbarInternalLanguageService } from './language-internal.service';
|
|
8
|
+
import { Language } from './language.models';
|
|
9
|
+
|
|
10
|
+
@Component({
|
|
11
|
+
selector: 'ndt-language-tool',
|
|
12
|
+
standalone: true,
|
|
13
|
+
imports: [DevToolbarToolComponent, DevToolbarSelectComponent],
|
|
14
|
+
styleUrls: ['./language-tool.component.scss'],
|
|
15
|
+
template: `
|
|
16
|
+
<ndt-toolbar-tool
|
|
17
|
+
title="Languages"
|
|
18
|
+
icon="translate"
|
|
19
|
+
[windowConfig]="windowConfig"
|
|
20
|
+
>
|
|
21
|
+
<div class="language-select">
|
|
22
|
+
<label for="language-select">Language</label>
|
|
23
|
+
<ndt-select
|
|
24
|
+
id="language-select"
|
|
25
|
+
[value]="activeLanguage()"
|
|
26
|
+
[options]="languageOptions()"
|
|
27
|
+
[size]="'medium'"
|
|
28
|
+
(valueChange)="onLanguageChange($event ?? '')"
|
|
29
|
+
/>
|
|
30
|
+
</div>
|
|
31
|
+
</ndt-toolbar-tool>
|
|
32
|
+
`,
|
|
33
|
+
})
|
|
34
|
+
export class DevToolbarLanguageToolComponent {
|
|
35
|
+
private readonly languageService = inject(DevToolbarInternalLanguageService);
|
|
36
|
+
|
|
37
|
+
protected readonly windowConfig = {
|
|
38
|
+
title: 'Languages',
|
|
39
|
+
description: 'Set the language for your current session',
|
|
40
|
+
isClosable: true,
|
|
41
|
+
size: 'small' as WindowSize,
|
|
42
|
+
id: 'ndt-language',
|
|
43
|
+
isBeta: true,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
activeLanguage = signal<string>('not-forced');
|
|
47
|
+
|
|
48
|
+
languageOptions = toSignal(
|
|
49
|
+
this.languageService.getAppLanguages().pipe(
|
|
50
|
+
map((languages) => [
|
|
51
|
+
{ value: 'not-forced', label: 'Not Forced' },
|
|
52
|
+
...languages.map(({ id: value, name: label }) => ({
|
|
53
|
+
value,
|
|
54
|
+
label,
|
|
55
|
+
})),
|
|
56
|
+
])
|
|
57
|
+
),
|
|
58
|
+
{ initialValue: [] }
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
async onLanguageChange(language: string): Promise<void> {
|
|
62
|
+
if (language === 'not-forced' || !language) {
|
|
63
|
+
this.languageService.removeForcedLanguage();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const languages = await firstValueFrom(
|
|
68
|
+
this.languageService.getAppLanguages()
|
|
69
|
+
);
|
|
70
|
+
const selectedLanguage = languages.find(({ id }) => id === language);
|
|
71
|
+
if (selectedLanguage) {
|
|
72
|
+
this.languageService.setForcedLanguage(selectedLanguage as Language);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { inject, Injectable } from '@angular/core';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { DevToolsService } from '../../models/dev-tools.interface';
|
|
4
|
+
import { DevToolbarInternalLanguageService } from './language-internal.service';
|
|
5
|
+
import { Language } from './language.models';
|
|
6
|
+
|
|
7
|
+
@Injectable({ providedIn: 'root' })
|
|
8
|
+
export class DevToolbarLanguageService implements DevToolsService<Language> {
|
|
9
|
+
private internalService = inject(DevToolbarInternalLanguageService);
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Sets the available languages that will be displayed in the tool on the dev toolbar
|
|
13
|
+
* @param languages The languages to be displayed
|
|
14
|
+
*/
|
|
15
|
+
setAvailableOptions(languages: Language[]): void {
|
|
16
|
+
this.internalService.setAppLanguages(languages);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Gets the languages that were forced/modified through the tool on the dev toolbar
|
|
21
|
+
* @returns Observable of forced languages array
|
|
22
|
+
*/
|
|
23
|
+
getForcedValues(): Observable<Language[]> {
|
|
24
|
+
return this.internalService.getForcedLanguage();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
@Injectable({ providedIn: 'root' })
|
|
4
|
+
export class DevToolsStorageService {
|
|
5
|
+
private readonly prefix = 'ndt-';
|
|
6
|
+
|
|
7
|
+
public set<T>(key: string, value: T): void {
|
|
8
|
+
localStorage.setItem(this.prefix + key, JSON.stringify(value));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
public get<T>(key: string): T | null {
|
|
12
|
+
const item = localStorage.getItem(this.prefix + key);
|
|
13
|
+
return item ? JSON.parse(item) : null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public remove(key: string): void {
|
|
17
|
+
localStorage.removeItem(this.prefix + key);
|
|
18
|
+
}
|
|
19
|
+
}
|