@pwd-meter/angular 2.0.0
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/dist/fesm2022/pwd-meter-angular.mjs +310 -0
- package/dist/fesm2022/pwd-meter-angular.mjs.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/lib/password-input.component.d.ts +28 -0
- package/dist/lib/password-strength-meter.component.d.ts +26 -0
- package/dist/lib/password-strength.service.d.ts +12 -0
- package/dist/public-api.d.ts +3 -0
- package/dist/styles.css +82 -0
- package/package.json +47 -0
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Injectable, Input, Component, EventEmitter, Output } from '@angular/core';
|
|
3
|
+
import { analyzePassword, analyzePasswordAsync, checkPwnedPassword, generateSecurePassword, getStrengthColor, getStrengthMessage } from '@pwd-meter/core';
|
|
4
|
+
export { analyzePassword, analyzePasswordAsync, checkPwnedPassword, generateSecurePassword } from '@pwd-meter/core';
|
|
5
|
+
import * as i2 from '@angular/common';
|
|
6
|
+
import { CommonModule } from '@angular/common';
|
|
7
|
+
import * as i3 from '@angular/forms';
|
|
8
|
+
import { FormsModule } from '@angular/forms';
|
|
9
|
+
|
|
10
|
+
class PasswordStrengthService {
|
|
11
|
+
analyze(password) {
|
|
12
|
+
return analyzePassword(password);
|
|
13
|
+
}
|
|
14
|
+
analyzeAsync(password, options) {
|
|
15
|
+
return analyzePasswordAsync(password, options);
|
|
16
|
+
}
|
|
17
|
+
checkPwned(password, options) {
|
|
18
|
+
return checkPwnedPassword(password, options);
|
|
19
|
+
}
|
|
20
|
+
generate(options) {
|
|
21
|
+
return generateSecurePassword(options);
|
|
22
|
+
}
|
|
23
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: PasswordStrengthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
24
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: PasswordStrengthService, providedIn: "root" });
|
|
25
|
+
}
|
|
26
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: PasswordStrengthService, decorators: [{
|
|
27
|
+
type: Injectable,
|
|
28
|
+
args: [{ providedIn: "root" }]
|
|
29
|
+
}] });
|
|
30
|
+
|
|
31
|
+
class PasswordStrengthMeterComponent {
|
|
32
|
+
passwordStrength;
|
|
33
|
+
password = "";
|
|
34
|
+
analysis;
|
|
35
|
+
showSuggestions = true;
|
|
36
|
+
showChecks = false;
|
|
37
|
+
checkPwned = false;
|
|
38
|
+
hibpOptions;
|
|
39
|
+
internalResult = analyzePassword("");
|
|
40
|
+
debounceTimer = null;
|
|
41
|
+
requestId = 0;
|
|
42
|
+
debounceMs = 400;
|
|
43
|
+
constructor(passwordStrength) {
|
|
44
|
+
this.passwordStrength = passwordStrength;
|
|
45
|
+
}
|
|
46
|
+
ngOnChanges() {
|
|
47
|
+
if (this.analysis !== undefined) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (this.debounceTimer) {
|
|
51
|
+
clearTimeout(this.debounceTimer);
|
|
52
|
+
this.debounceTimer = null;
|
|
53
|
+
}
|
|
54
|
+
this.requestId += 1;
|
|
55
|
+
this.internalResult = this.passwordStrength.analyze(this.password);
|
|
56
|
+
if (!this.checkPwned || !this.password) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
this.internalResult = { ...this.internalResult, pwnedCheckPending: true };
|
|
60
|
+
const id = this.requestId;
|
|
61
|
+
this.debounceTimer = setTimeout(async () => {
|
|
62
|
+
if (id !== this.requestId) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const next = await this.passwordStrength.analyzeAsync(this.password, {
|
|
66
|
+
checkPwned: true,
|
|
67
|
+
hibp: this.hibpOptions,
|
|
68
|
+
});
|
|
69
|
+
if (id !== this.requestId) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
this.internalResult = next;
|
|
73
|
+
}, this.debounceMs);
|
|
74
|
+
}
|
|
75
|
+
ngOnDestroy() {
|
|
76
|
+
if (this.debounceTimer) {
|
|
77
|
+
clearTimeout(this.debounceTimer);
|
|
78
|
+
this.debounceTimer = null;
|
|
79
|
+
}
|
|
80
|
+
this.requestId += 1;
|
|
81
|
+
}
|
|
82
|
+
get displayResult() {
|
|
83
|
+
return this.analysis ?? this.internalResult;
|
|
84
|
+
}
|
|
85
|
+
get barWidth() {
|
|
86
|
+
return this.password ? ((this.displayResult.score + 1) / 5) * 100 : 0;
|
|
87
|
+
}
|
|
88
|
+
get barColor() {
|
|
89
|
+
return getStrengthColor(this.displayResult.label);
|
|
90
|
+
}
|
|
91
|
+
get message() {
|
|
92
|
+
return getStrengthMessage(this.displayResult);
|
|
93
|
+
}
|
|
94
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: PasswordStrengthMeterComponent, deps: [{ token: PasswordStrengthService }], target: i0.ɵɵFactoryTarget.Component });
|
|
95
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.25", type: PasswordStrengthMeterComponent, isStandalone: true, selector: "ps-password-strength-meter", inputs: { password: "password", analysis: "analysis", showSuggestions: "showSuggestions", showChecks: "showChecks", checkPwned: "checkPwned", hibpOptions: "hibpOptions" }, usesOnChanges: true, ngImport: i0, template: `
|
|
96
|
+
<div class="ps-meter" aria-live="polite">
|
|
97
|
+
<div class="ps-meter__track" aria-hidden="true">
|
|
98
|
+
<div class="ps-meter__bar" [style.width.%]="barWidth" [style.backgroundColor]="barColor"></div>
|
|
99
|
+
</div>
|
|
100
|
+
<p class="ps-meter__message">{{ message }}</p>
|
|
101
|
+
<p *ngIf="password && !displayResult.isPwned && !displayResult.pwnedCheckPending" class="ps-meter__meta">
|
|
102
|
+
Estimated crack time: {{ displayResult.crackTimeDisplay }}
|
|
103
|
+
</p>
|
|
104
|
+
<ul *ngIf="showChecks && password" class="ps-meter__checks">
|
|
105
|
+
<li [attr.data-pass]="displayResult.checks.length">At least 12 characters</li>
|
|
106
|
+
<li [attr.data-pass]="displayResult.checks.lowercase">Lowercase letter</li>
|
|
107
|
+
<li [attr.data-pass]="displayResult.checks.uppercase">Uppercase letter</li>
|
|
108
|
+
<li [attr.data-pass]="displayResult.checks.number">Number</li>
|
|
109
|
+
<li [attr.data-pass]="displayResult.checks.symbol">Symbol</li>
|
|
110
|
+
</ul>
|
|
111
|
+
<div
|
|
112
|
+
*ngIf="showSuggestions && (displayResult.feedback.warning || displayResult.feedback.suggestions.length)"
|
|
113
|
+
class="ps-meter__feedback"
|
|
114
|
+
>
|
|
115
|
+
<p *ngIf="displayResult.feedback.warning" class="ps-meter__warning">{{ displayResult.feedback.warning }}</p>
|
|
116
|
+
<ul>
|
|
117
|
+
<li *ngFor="let item of displayResult.feedback.suggestions">{{ item }}</li>
|
|
118
|
+
</ul>
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
122
|
+
}
|
|
123
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: PasswordStrengthMeterComponent, decorators: [{
|
|
124
|
+
type: Component,
|
|
125
|
+
args: [{
|
|
126
|
+
selector: "ps-password-strength-meter",
|
|
127
|
+
standalone: true,
|
|
128
|
+
imports: [CommonModule],
|
|
129
|
+
template: `
|
|
130
|
+
<div class="ps-meter" aria-live="polite">
|
|
131
|
+
<div class="ps-meter__track" aria-hidden="true">
|
|
132
|
+
<div class="ps-meter__bar" [style.width.%]="barWidth" [style.backgroundColor]="barColor"></div>
|
|
133
|
+
</div>
|
|
134
|
+
<p class="ps-meter__message">{{ message }}</p>
|
|
135
|
+
<p *ngIf="password && !displayResult.isPwned && !displayResult.pwnedCheckPending" class="ps-meter__meta">
|
|
136
|
+
Estimated crack time: {{ displayResult.crackTimeDisplay }}
|
|
137
|
+
</p>
|
|
138
|
+
<ul *ngIf="showChecks && password" class="ps-meter__checks">
|
|
139
|
+
<li [attr.data-pass]="displayResult.checks.length">At least 12 characters</li>
|
|
140
|
+
<li [attr.data-pass]="displayResult.checks.lowercase">Lowercase letter</li>
|
|
141
|
+
<li [attr.data-pass]="displayResult.checks.uppercase">Uppercase letter</li>
|
|
142
|
+
<li [attr.data-pass]="displayResult.checks.number">Number</li>
|
|
143
|
+
<li [attr.data-pass]="displayResult.checks.symbol">Symbol</li>
|
|
144
|
+
</ul>
|
|
145
|
+
<div
|
|
146
|
+
*ngIf="showSuggestions && (displayResult.feedback.warning || displayResult.feedback.suggestions.length)"
|
|
147
|
+
class="ps-meter__feedback"
|
|
148
|
+
>
|
|
149
|
+
<p *ngIf="displayResult.feedback.warning" class="ps-meter__warning">{{ displayResult.feedback.warning }}</p>
|
|
150
|
+
<ul>
|
|
151
|
+
<li *ngFor="let item of displayResult.feedback.suggestions">{{ item }}</li>
|
|
152
|
+
</ul>
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
`,
|
|
156
|
+
}]
|
|
157
|
+
}], ctorParameters: () => [{ type: PasswordStrengthService }], propDecorators: { password: [{
|
|
158
|
+
type: Input
|
|
159
|
+
}], analysis: [{
|
|
160
|
+
type: Input
|
|
161
|
+
}], showSuggestions: [{
|
|
162
|
+
type: Input
|
|
163
|
+
}], showChecks: [{
|
|
164
|
+
type: Input
|
|
165
|
+
}], checkPwned: [{
|
|
166
|
+
type: Input
|
|
167
|
+
}], hibpOptions: [{
|
|
168
|
+
type: Input
|
|
169
|
+
}] } });
|
|
170
|
+
|
|
171
|
+
class PasswordInputComponent {
|
|
172
|
+
passwordStrength;
|
|
173
|
+
value = "";
|
|
174
|
+
placeholder = "Enter password";
|
|
175
|
+
showMeter = true;
|
|
176
|
+
showGenerate = true;
|
|
177
|
+
checkPwned = false;
|
|
178
|
+
hibpOptions;
|
|
179
|
+
generateOptions;
|
|
180
|
+
valueChange = new EventEmitter();
|
|
181
|
+
result = analyzePassword("");
|
|
182
|
+
debounceTimer = null;
|
|
183
|
+
requestId = 0;
|
|
184
|
+
debounceMs = 400;
|
|
185
|
+
constructor(passwordStrength) {
|
|
186
|
+
this.passwordStrength = passwordStrength;
|
|
187
|
+
}
|
|
188
|
+
ngOnChanges() {
|
|
189
|
+
this.scheduleAnalysis();
|
|
190
|
+
}
|
|
191
|
+
ngOnDestroy() {
|
|
192
|
+
if (this.debounceTimer) {
|
|
193
|
+
clearTimeout(this.debounceTimer);
|
|
194
|
+
this.debounceTimer = null;
|
|
195
|
+
}
|
|
196
|
+
this.requestId += 1;
|
|
197
|
+
}
|
|
198
|
+
get strengthMessage() {
|
|
199
|
+
return getStrengthMessage(this.result);
|
|
200
|
+
}
|
|
201
|
+
onValueChange(next) {
|
|
202
|
+
this.value = next;
|
|
203
|
+
this.valueChange.emit(next);
|
|
204
|
+
this.scheduleAnalysis();
|
|
205
|
+
}
|
|
206
|
+
generate() {
|
|
207
|
+
const next = this.passwordStrength.generate(this.generateOptions);
|
|
208
|
+
this.onValueChange(next);
|
|
209
|
+
}
|
|
210
|
+
scheduleAnalysis() {
|
|
211
|
+
if (this.debounceTimer) {
|
|
212
|
+
clearTimeout(this.debounceTimer);
|
|
213
|
+
this.debounceTimer = null;
|
|
214
|
+
}
|
|
215
|
+
this.requestId += 1;
|
|
216
|
+
this.result = this.passwordStrength.analyze(this.value);
|
|
217
|
+
if (!this.checkPwned || !this.value) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
this.result = { ...this.result, pwnedCheckPending: true };
|
|
221
|
+
const id = this.requestId;
|
|
222
|
+
this.debounceTimer = setTimeout(async () => {
|
|
223
|
+
if (id !== this.requestId) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const next = await this.passwordStrength.analyzeAsync(this.value, {
|
|
227
|
+
checkPwned: true,
|
|
228
|
+
hibp: this.hibpOptions,
|
|
229
|
+
});
|
|
230
|
+
if (id !== this.requestId) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
this.result = next;
|
|
234
|
+
}, this.debounceMs);
|
|
235
|
+
}
|
|
236
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: PasswordInputComponent, deps: [{ token: PasswordStrengthService }], target: i0.ɵɵFactoryTarget.Component });
|
|
237
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.25", type: PasswordInputComponent, isStandalone: true, selector: "ps-password-input", inputs: { value: "value", placeholder: "placeholder", showMeter: "showMeter", showGenerate: "showGenerate", checkPwned: "checkPwned", hibpOptions: "hibpOptions", generateOptions: "generateOptions" }, outputs: { valueChange: "valueChange" }, usesOnChanges: true, ngImport: i0, template: `
|
|
238
|
+
<div class="ps-input">
|
|
239
|
+
<div class="ps-input__row">
|
|
240
|
+
<input
|
|
241
|
+
class="ps-input__field"
|
|
242
|
+
type="password"
|
|
243
|
+
[placeholder]="placeholder"
|
|
244
|
+
[(ngModel)]="value"
|
|
245
|
+
(ngModelChange)="onValueChange($event)"
|
|
246
|
+
aria-describedby="password-strength-message"
|
|
247
|
+
/>
|
|
248
|
+
<button *ngIf="showGenerate" type="button" class="ps-input__generate" (click)="generate()">Generate</button>
|
|
249
|
+
</div>
|
|
250
|
+
<ps-password-strength-meter
|
|
251
|
+
*ngIf="showMeter"
|
|
252
|
+
[password]="value"
|
|
253
|
+
[analysis]="result"
|
|
254
|
+
></ps-password-strength-meter>
|
|
255
|
+
<span id="password-strength-message" class="ps-sr-only">{{ strengthMessage }}</span>
|
|
256
|
+
</div>
|
|
257
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.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: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: PasswordStrengthMeterComponent, selector: "ps-password-strength-meter", inputs: ["password", "analysis", "showSuggestions", "showChecks", "checkPwned", "hibpOptions"] }] });
|
|
258
|
+
}
|
|
259
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: PasswordInputComponent, decorators: [{
|
|
260
|
+
type: Component,
|
|
261
|
+
args: [{
|
|
262
|
+
selector: "ps-password-input",
|
|
263
|
+
standalone: true,
|
|
264
|
+
imports: [CommonModule, FormsModule, PasswordStrengthMeterComponent],
|
|
265
|
+
template: `
|
|
266
|
+
<div class="ps-input">
|
|
267
|
+
<div class="ps-input__row">
|
|
268
|
+
<input
|
|
269
|
+
class="ps-input__field"
|
|
270
|
+
type="password"
|
|
271
|
+
[placeholder]="placeholder"
|
|
272
|
+
[(ngModel)]="value"
|
|
273
|
+
(ngModelChange)="onValueChange($event)"
|
|
274
|
+
aria-describedby="password-strength-message"
|
|
275
|
+
/>
|
|
276
|
+
<button *ngIf="showGenerate" type="button" class="ps-input__generate" (click)="generate()">Generate</button>
|
|
277
|
+
</div>
|
|
278
|
+
<ps-password-strength-meter
|
|
279
|
+
*ngIf="showMeter"
|
|
280
|
+
[password]="value"
|
|
281
|
+
[analysis]="result"
|
|
282
|
+
></ps-password-strength-meter>
|
|
283
|
+
<span id="password-strength-message" class="ps-sr-only">{{ strengthMessage }}</span>
|
|
284
|
+
</div>
|
|
285
|
+
`,
|
|
286
|
+
}]
|
|
287
|
+
}], ctorParameters: () => [{ type: PasswordStrengthService }], propDecorators: { value: [{
|
|
288
|
+
type: Input
|
|
289
|
+
}], placeholder: [{
|
|
290
|
+
type: Input
|
|
291
|
+
}], showMeter: [{
|
|
292
|
+
type: Input
|
|
293
|
+
}], showGenerate: [{
|
|
294
|
+
type: Input
|
|
295
|
+
}], checkPwned: [{
|
|
296
|
+
type: Input
|
|
297
|
+
}], hibpOptions: [{
|
|
298
|
+
type: Input
|
|
299
|
+
}], generateOptions: [{
|
|
300
|
+
type: Input
|
|
301
|
+
}], valueChange: [{
|
|
302
|
+
type: Output
|
|
303
|
+
}] } });
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Generated bundle index. Do not edit.
|
|
307
|
+
*/
|
|
308
|
+
|
|
309
|
+
export { PasswordInputComponent, PasswordStrengthMeterComponent, PasswordStrengthService };
|
|
310
|
+
//# sourceMappingURL=pwd-meter-angular.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pwd-meter-angular.mjs","sources":["../../src/lib/password-strength.service.ts","../../src/lib/password-strength-meter.component.ts","../../src/lib/password-input.component.ts","../../src/pwd-meter-angular.ts"],"sourcesContent":["import { Injectable } from \"@angular/core\";\nimport {\n analyzePassword,\n analyzePasswordAsync,\n checkPwnedPassword,\n generateSecurePassword,\n type AnalyzePasswordOptions,\n type GeneratePasswordOptions,\n type PasswordStrengthResult,\n} from \"@pwd-meter/core\";\n\n@Injectable({ providedIn: \"root\" })\nexport class PasswordStrengthService {\n analyze(password: string): PasswordStrengthResult {\n return analyzePassword(password);\n }\n\n analyzeAsync(password: string, options?: AnalyzePasswordOptions): Promise<PasswordStrengthResult> {\n return analyzePasswordAsync(password, options);\n }\n\n checkPwned(password: string, options?: AnalyzePasswordOptions[\"hibp\"]) {\n return checkPwnedPassword(password, options);\n }\n\n generate(options?: GeneratePasswordOptions): string {\n return generateSecurePassword(options);\n }\n}\n\nexport { analyzePassword, analyzePasswordAsync, checkPwnedPassword, generateSecurePassword };\nexport type {\n AnalyzePasswordOptions,\n GeneratePasswordOptions,\n HibpOptions,\n PasswordStrengthResult,\n PwnedPasswordResult,\n StrengthLabel,\n} from \"@pwd-meter/core\";\n","import { CommonModule } from \"@angular/common\";\nimport { Component, Input, OnChanges, OnDestroy } from \"@angular/core\";\nimport {\n analyzePassword,\n getStrengthColor,\n getStrengthMessage,\n type HibpOptions,\n type PasswordStrengthResult,\n} from \"@pwd-meter/core\";\nimport { PasswordStrengthService } from \"./password-strength.service\";\n\n@Component({\n selector: \"ps-password-strength-meter\",\n standalone: true,\n imports: [CommonModule],\n template: `\n <div class=\"ps-meter\" aria-live=\"polite\">\n <div class=\"ps-meter__track\" aria-hidden=\"true\">\n <div class=\"ps-meter__bar\" [style.width.%]=\"barWidth\" [style.backgroundColor]=\"barColor\"></div>\n </div>\n <p class=\"ps-meter__message\">{{ message }}</p>\n <p *ngIf=\"password && !displayResult.isPwned && !displayResult.pwnedCheckPending\" class=\"ps-meter__meta\">\n Estimated crack time: {{ displayResult.crackTimeDisplay }}\n </p>\n <ul *ngIf=\"showChecks && password\" class=\"ps-meter__checks\">\n <li [attr.data-pass]=\"displayResult.checks.length\">At least 12 characters</li>\n <li [attr.data-pass]=\"displayResult.checks.lowercase\">Lowercase letter</li>\n <li [attr.data-pass]=\"displayResult.checks.uppercase\">Uppercase letter</li>\n <li [attr.data-pass]=\"displayResult.checks.number\">Number</li>\n <li [attr.data-pass]=\"displayResult.checks.symbol\">Symbol</li>\n </ul>\n <div\n *ngIf=\"showSuggestions && (displayResult.feedback.warning || displayResult.feedback.suggestions.length)\"\n class=\"ps-meter__feedback\"\n >\n <p *ngIf=\"displayResult.feedback.warning\" class=\"ps-meter__warning\">{{ displayResult.feedback.warning }}</p>\n <ul>\n <li *ngFor=\"let item of displayResult.feedback.suggestions\">{{ item }}</li>\n </ul>\n </div>\n </div>\n `,\n})\nexport class PasswordStrengthMeterComponent implements OnChanges, OnDestroy {\n @Input() password = \"\";\n @Input() analysis?: PasswordStrengthResult;\n @Input() showSuggestions = true;\n @Input() showChecks = false;\n @Input() checkPwned = false;\n @Input() hibpOptions?: HibpOptions;\n\n internalResult: PasswordStrengthResult = analyzePassword(\"\");\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private requestId = 0;\n private readonly debounceMs = 400;\n\n constructor(private readonly passwordStrength: PasswordStrengthService) {}\n\n ngOnChanges(): void {\n if (this.analysis !== undefined) {\n return;\n }\n\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n\n this.requestId += 1;\n this.internalResult = this.passwordStrength.analyze(this.password);\n\n if (!this.checkPwned || !this.password) {\n return;\n }\n\n this.internalResult = { ...this.internalResult, pwnedCheckPending: true };\n const id = this.requestId;\n this.debounceTimer = setTimeout(async () => {\n if (id !== this.requestId) {\n return;\n }\n\n const next = await this.passwordStrength.analyzeAsync(this.password, {\n checkPwned: true,\n hibp: this.hibpOptions,\n });\n\n if (id !== this.requestId) {\n return;\n }\n\n this.internalResult = next;\n }, this.debounceMs);\n }\n\n ngOnDestroy(): void {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n this.requestId += 1;\n }\n\n get displayResult(): PasswordStrengthResult {\n return this.analysis ?? this.internalResult;\n }\n\n get barWidth(): number {\n return this.password ? ((this.displayResult.score + 1) / 5) * 100 : 0;\n }\n\n get barColor(): string {\n return getStrengthColor(this.displayResult.label);\n }\n\n get message(): string {\n return getStrengthMessage(this.displayResult);\n }\n}\n","import { CommonModule } from \"@angular/common\";\nimport { Component, EventEmitter, Input, OnChanges, OnDestroy, Output } from \"@angular/core\";\nimport { FormsModule } from \"@angular/forms\";\nimport { analyzePassword, getStrengthMessage, type GeneratePasswordOptions, type HibpOptions, type PasswordStrengthResult } from \"@pwd-meter/core\";\nimport { PasswordStrengthMeterComponent } from \"./password-strength-meter.component\";\nimport { PasswordStrengthService } from \"./password-strength.service\";\n\n@Component({\n selector: \"ps-password-input\",\n standalone: true,\n imports: [CommonModule, FormsModule, PasswordStrengthMeterComponent],\n template: `\n <div class=\"ps-input\">\n <div class=\"ps-input__row\">\n <input\n class=\"ps-input__field\"\n type=\"password\"\n [placeholder]=\"placeholder\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"\n aria-describedby=\"password-strength-message\"\n />\n <button *ngIf=\"showGenerate\" type=\"button\" class=\"ps-input__generate\" (click)=\"generate()\">Generate</button>\n </div>\n <ps-password-strength-meter\n *ngIf=\"showMeter\"\n [password]=\"value\"\n [analysis]=\"result\"\n ></ps-password-strength-meter>\n <span id=\"password-strength-message\" class=\"ps-sr-only\">{{ strengthMessage }}</span>\n </div>\n `,\n})\nexport class PasswordInputComponent implements OnChanges, OnDestroy {\n @Input() value = \"\";\n @Input() placeholder = \"Enter password\";\n @Input() showMeter = true;\n @Input() showGenerate = true;\n @Input() checkPwned = false;\n @Input() hibpOptions?: HibpOptions;\n @Input() generateOptions?: GeneratePasswordOptions;\n @Output() valueChange = new EventEmitter<string>();\n\n result: PasswordStrengthResult = analyzePassword(\"\");\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private requestId = 0;\n private readonly debounceMs = 400;\n\n constructor(private readonly passwordStrength: PasswordStrengthService) {}\n\n ngOnChanges(): void {\n this.scheduleAnalysis();\n }\n\n ngOnDestroy(): void {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n this.requestId += 1;\n }\n\n get strengthMessage(): string {\n return getStrengthMessage(this.result);\n }\n\n onValueChange(next: string) {\n this.value = next;\n this.valueChange.emit(next);\n this.scheduleAnalysis();\n }\n\n generate() {\n const next = this.passwordStrength.generate(this.generateOptions);\n this.onValueChange(next);\n }\n\n private scheduleAnalysis(): void {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n\n this.requestId += 1;\n this.result = this.passwordStrength.analyze(this.value);\n\n if (!this.checkPwned || !this.value) {\n return;\n }\n\n this.result = { ...this.result, pwnedCheckPending: true };\n const id = this.requestId;\n this.debounceTimer = setTimeout(async () => {\n if (id !== this.requestId) {\n return;\n }\n\n const next = await this.passwordStrength.analyzeAsync(this.value, {\n checkPwned: true,\n hibp: this.hibpOptions,\n });\n\n if (id !== this.requestId) {\n return;\n }\n\n this.result = next;\n }, this.debounceMs);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.PasswordStrengthService"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { EventEmitter, OnChanges, OnDestroy } from "@angular/core";
|
|
2
|
+
import { type GeneratePasswordOptions, type HibpOptions, type PasswordStrengthResult } from "@pwd-meter/core";
|
|
3
|
+
import { PasswordStrengthService } from "./password-strength.service";
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
export declare class PasswordInputComponent implements OnChanges, OnDestroy {
|
|
6
|
+
private readonly passwordStrength;
|
|
7
|
+
value: string;
|
|
8
|
+
placeholder: string;
|
|
9
|
+
showMeter: boolean;
|
|
10
|
+
showGenerate: boolean;
|
|
11
|
+
checkPwned: boolean;
|
|
12
|
+
hibpOptions?: HibpOptions;
|
|
13
|
+
generateOptions?: GeneratePasswordOptions;
|
|
14
|
+
valueChange: EventEmitter<string>;
|
|
15
|
+
result: PasswordStrengthResult;
|
|
16
|
+
private debounceTimer;
|
|
17
|
+
private requestId;
|
|
18
|
+
private readonly debounceMs;
|
|
19
|
+
constructor(passwordStrength: PasswordStrengthService);
|
|
20
|
+
ngOnChanges(): void;
|
|
21
|
+
ngOnDestroy(): void;
|
|
22
|
+
get strengthMessage(): string;
|
|
23
|
+
onValueChange(next: string): void;
|
|
24
|
+
generate(): void;
|
|
25
|
+
private scheduleAnalysis;
|
|
26
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<PasswordInputComponent, never>;
|
|
27
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<PasswordInputComponent, "ps-password-input", never, { "value": { "alias": "value"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "showMeter": { "alias": "showMeter"; "required": false; }; "showGenerate": { "alias": "showGenerate"; "required": false; }; "checkPwned": { "alias": "checkPwned"; "required": false; }; "hibpOptions": { "alias": "hibpOptions"; "required": false; }; "generateOptions": { "alias": "generateOptions"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
|
|
28
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { OnChanges, OnDestroy } from "@angular/core";
|
|
2
|
+
import { type HibpOptions, type PasswordStrengthResult } from "@pwd-meter/core";
|
|
3
|
+
import { PasswordStrengthService } from "./password-strength.service";
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
export declare class PasswordStrengthMeterComponent implements OnChanges, OnDestroy {
|
|
6
|
+
private readonly passwordStrength;
|
|
7
|
+
password: string;
|
|
8
|
+
analysis?: PasswordStrengthResult;
|
|
9
|
+
showSuggestions: boolean;
|
|
10
|
+
showChecks: boolean;
|
|
11
|
+
checkPwned: boolean;
|
|
12
|
+
hibpOptions?: HibpOptions;
|
|
13
|
+
internalResult: PasswordStrengthResult;
|
|
14
|
+
private debounceTimer;
|
|
15
|
+
private requestId;
|
|
16
|
+
private readonly debounceMs;
|
|
17
|
+
constructor(passwordStrength: PasswordStrengthService);
|
|
18
|
+
ngOnChanges(): void;
|
|
19
|
+
ngOnDestroy(): void;
|
|
20
|
+
get displayResult(): PasswordStrengthResult;
|
|
21
|
+
get barWidth(): number;
|
|
22
|
+
get barColor(): string;
|
|
23
|
+
get message(): string;
|
|
24
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<PasswordStrengthMeterComponent, never>;
|
|
25
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<PasswordStrengthMeterComponent, "ps-password-strength-meter", never, { "password": { "alias": "password"; "required": false; }; "analysis": { "alias": "analysis"; "required": false; }; "showSuggestions": { "alias": "showSuggestions"; "required": false; }; "showChecks": { "alias": "showChecks"; "required": false; }; "checkPwned": { "alias": "checkPwned"; "required": false; }; "hibpOptions": { "alias": "hibpOptions"; "required": false; }; }, {}, never, never, true, never>;
|
|
26
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { analyzePassword, analyzePasswordAsync, checkPwnedPassword, generateSecurePassword, type AnalyzePasswordOptions, type GeneratePasswordOptions, type PasswordStrengthResult } from "@pwd-meter/core";
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export declare class PasswordStrengthService {
|
|
4
|
+
analyze(password: string): PasswordStrengthResult;
|
|
5
|
+
analyzeAsync(password: string, options?: AnalyzePasswordOptions): Promise<PasswordStrengthResult>;
|
|
6
|
+
checkPwned(password: string, options?: AnalyzePasswordOptions["hibp"]): Promise<import("@pwd-meter/core").PwnedPasswordResult>;
|
|
7
|
+
generate(options?: GeneratePasswordOptions): string;
|
|
8
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<PasswordStrengthService, never>;
|
|
9
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<PasswordStrengthService>;
|
|
10
|
+
}
|
|
11
|
+
export { analyzePassword, analyzePasswordAsync, checkPwnedPassword, generateSecurePassword };
|
|
12
|
+
export type { AnalyzePasswordOptions, GeneratePasswordOptions, HibpOptions, PasswordStrengthResult, PwnedPasswordResult, StrengthLabel, } from "@pwd-meter/core";
|
package/dist/styles.css
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
.ps-meter,
|
|
2
|
+
.ps-input {
|
|
3
|
+
font-family: Inter, ui-sans-serif, system-ui, sans-serif;
|
|
4
|
+
color: #0f172a;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.ps-input__row {
|
|
8
|
+
display: flex;
|
|
9
|
+
gap: 8px;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.ps-input__field {
|
|
13
|
+
flex: 1;
|
|
14
|
+
min-height: 42px;
|
|
15
|
+
border: 1px solid #cbd5e1;
|
|
16
|
+
border-radius: 8px;
|
|
17
|
+
padding: 0 12px;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.ps-input__generate {
|
|
21
|
+
min-height: 42px;
|
|
22
|
+
border: 0;
|
|
23
|
+
border-radius: 8px;
|
|
24
|
+
padding: 0 14px;
|
|
25
|
+
color: #fff;
|
|
26
|
+
background: #2563eb;
|
|
27
|
+
cursor: pointer;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.ps-meter {
|
|
31
|
+
margin-top: 10px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.ps-meter__track {
|
|
35
|
+
height: 8px;
|
|
36
|
+
border-radius: 999px;
|
|
37
|
+
background: #e2e8f0;
|
|
38
|
+
overflow: hidden;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.ps-meter__bar {
|
|
42
|
+
height: 100%;
|
|
43
|
+
border-radius: inherit;
|
|
44
|
+
transition: width 0.2s ease, background-color 0.2s ease;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.ps-meter__message {
|
|
48
|
+
margin: 8px 0 0;
|
|
49
|
+
font-size: 0.92rem;
|
|
50
|
+
font-weight: 600;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.ps-meter__meta,
|
|
54
|
+
.ps-meter__warning,
|
|
55
|
+
.ps-meter__feedback {
|
|
56
|
+
margin: 6px 0 0;
|
|
57
|
+
color: #475569;
|
|
58
|
+
font-size: 0.86rem;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.ps-meter__checks {
|
|
62
|
+
margin: 8px 0 0;
|
|
63
|
+
padding-left: 18px;
|
|
64
|
+
color: #64748b;
|
|
65
|
+
font-size: 0.84rem;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.ps-meter__checks li[data-pass="true"] {
|
|
69
|
+
color: #15803d;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.ps-sr-only {
|
|
73
|
+
position: absolute;
|
|
74
|
+
width: 1px;
|
|
75
|
+
height: 1px;
|
|
76
|
+
padding: 0;
|
|
77
|
+
margin: -1px;
|
|
78
|
+
overflow: hidden;
|
|
79
|
+
clip: rect(0, 0, 0, 0);
|
|
80
|
+
white-space: nowrap;
|
|
81
|
+
border: 0;
|
|
82
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pwd-meter/angular",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Angular services and standalone components for password strength checking.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Alen Joy <alenjoy333@gmail.com>",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/alenjoy333/Password-Strength-Checker.git",
|
|
10
|
+
"directory": "packages/angular"
|
|
11
|
+
},
|
|
12
|
+
"keywords": ["password", "angular", "security"],
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "./dist/fesm2022/pwd-meter-angular.mjs",
|
|
15
|
+
"module": "./dist/fesm2022/pwd-meter-angular.mjs",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"default": "./dist/fesm2022/pwd-meter-angular.mjs"
|
|
21
|
+
},
|
|
22
|
+
"./styles.css": "./dist/styles.css"
|
|
23
|
+
},
|
|
24
|
+
"files": ["dist"],
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "ng-packagr -p ng-package.json && cp src/styles.css dist/styles.css",
|
|
28
|
+
"clean": "rm -rf dist"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@pwd-meter/core": "2.0.0"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"@angular/common": ">=17",
|
|
35
|
+
"@angular/core": ">=17",
|
|
36
|
+
"@angular/forms": ">=17"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@angular/common": "^19.2.14",
|
|
40
|
+
"@angular/compiler": "^19.2.14",
|
|
41
|
+
"@angular/compiler-cli": "^19.2.14",
|
|
42
|
+
"@angular/core": "^19.2.14",
|
|
43
|
+
"@angular/forms": "^19.2.14",
|
|
44
|
+
"ng-packagr": "^19.2.2",
|
|
45
|
+
"typescript": "^5.8.3"
|
|
46
|
+
}
|
|
47
|
+
}
|