mirror of
https://github.com/bitwarden/browser.git
synced 2025-01-02 18:17:46 +01:00
[CL-63] Color password component (#4018)
This commit is contained in:
parent
a57424df75
commit
dc84a54928
@ -0,0 +1,79 @@
|
||||
import { Component, HostBinding, Input } from "@angular/core";
|
||||
|
||||
import { Utils } from "@bitwarden/common/misc/utils";
|
||||
|
||||
enum CharacterType {
|
||||
Letter,
|
||||
Emoji,
|
||||
Special,
|
||||
Number,
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: "bit-color-password",
|
||||
template: `<div
|
||||
*ngFor="let character of passwordArray; index as i"
|
||||
[class]="getCharacterClass(character)"
|
||||
>
|
||||
<span>{{ character }}</span>
|
||||
<span *ngIf="showCount" class="tw-whitespace-nowrap tw-text-xs tw-leading-5 tw-text-main">{{
|
||||
i + 1
|
||||
}}</span>
|
||||
</div>`,
|
||||
})
|
||||
export class ColorPasswordComponent {
|
||||
@Input() private password: string = null;
|
||||
@Input() showCount = false;
|
||||
|
||||
characterStyles: Record<CharacterType, string[]> = {
|
||||
[CharacterType.Emoji]: [],
|
||||
[CharacterType.Letter]: ["tw-text-main"],
|
||||
[CharacterType.Special]: ["tw-text-danger"],
|
||||
[CharacterType.Number]: ["tw-text-primary-500"],
|
||||
};
|
||||
|
||||
@HostBinding("class")
|
||||
get classList() {
|
||||
return ["tw-min-w-0", "tw-whitespace-pre-wrap", "tw-break-all"];
|
||||
}
|
||||
|
||||
get passwordArray() {
|
||||
// Convert to an array to handle cases that strings have special characters, i.e.: emoji.
|
||||
return Array.from(this.password);
|
||||
}
|
||||
|
||||
getCharacterClass(character: string) {
|
||||
const charType = this.getCharacterType(character);
|
||||
const charClass = this.characterStyles[charType].concat("tw-inline-flex");
|
||||
|
||||
if (this.showCount) {
|
||||
return charClass.concat([
|
||||
"tw-inline-flex",
|
||||
"tw-flex-col",
|
||||
"tw-items-center",
|
||||
"tw-w-7",
|
||||
"tw-py-1",
|
||||
"odd:tw-bg-secondary-100",
|
||||
]);
|
||||
}
|
||||
|
||||
return charClass;
|
||||
}
|
||||
|
||||
private getCharacterType(character: string): CharacterType {
|
||||
if (character.match(Utils.regexpEmojiPresentation)) {
|
||||
return CharacterType.Emoji;
|
||||
}
|
||||
|
||||
if (character.match(/\d/)) {
|
||||
return CharacterType.Number;
|
||||
}
|
||||
|
||||
const specials = ["&", "<", ">", " "];
|
||||
if (specials.includes(character) || character.match(/[^\w ]/)) {
|
||||
return CharacterType.Special;
|
||||
}
|
||||
|
||||
return CharacterType.Letter;
|
||||
}
|
||||
}
|
11
libs/components/src/color-password/color-password.module.ts
Normal file
11
libs/components/src/color-password/color-password.module.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { NgModule } from "@angular/core";
|
||||
|
||||
import { ColorPasswordComponent } from "./color-password.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule],
|
||||
exports: [ColorPasswordComponent],
|
||||
declarations: [ColorPasswordComponent],
|
||||
})
|
||||
export class ColorPasswordModule {}
|
52
libs/components/src/color-password/color-password.stories.ts
Normal file
52
libs/components/src/color-password/color-password.stories.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import { Meta, Story } from "@storybook/angular";
|
||||
|
||||
import { ColorPasswordComponent } from "./color-password.component";
|
||||
|
||||
const examplePassword = "Wq$Jk😀7jDX#rS5Sdi!z";
|
||||
|
||||
export default {
|
||||
title: "Component Library/Color Password",
|
||||
component: ColorPasswordComponent,
|
||||
args: {
|
||||
password: examplePassword,
|
||||
showCount: false,
|
||||
},
|
||||
parameters: {
|
||||
design: {
|
||||
type: "figma",
|
||||
url: "https://www.figma.com/file/6fvTDa3zfvgWdizLQ7nSTP/Numbered-Password",
|
||||
},
|
||||
},
|
||||
} as Meta;
|
||||
|
||||
const Template: Story<ColorPasswordComponent> = (args: ColorPasswordComponent) => ({
|
||||
props: args,
|
||||
template: `
|
||||
<bit-color-password class="tw-text-base" [password]="password" [showCount]="showCount"></bit-color-password>
|
||||
`,
|
||||
});
|
||||
|
||||
const WrappedTemplate: Story<ColorPasswordComponent> = (args: ColorPasswordComponent) => ({
|
||||
props: args,
|
||||
template: `
|
||||
<div class="tw-max-w-32">
|
||||
<bit-color-password class="tw-text-base" [password]="password" [showCount]="showCount"></bit-color-password>
|
||||
</div>
|
||||
`,
|
||||
});
|
||||
|
||||
export const ColorPassword = Template.bind({});
|
||||
|
||||
export const WrappedColorPassword = WrappedTemplate.bind({});
|
||||
|
||||
export const ColorPasswordCount = Template.bind({});
|
||||
ColorPasswordCount.args = {
|
||||
password: examplePassword,
|
||||
showCount: true,
|
||||
};
|
||||
|
||||
export const WrappedColorPasswordCount = WrappedTemplate.bind({});
|
||||
WrappedColorPasswordCount.args = {
|
||||
password: examplePassword,
|
||||
showCount: true,
|
||||
};
|
1
libs/components/src/color-password/index.ts
Normal file
1
libs/components/src/color-password/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from "./color-password.module";
|
@ -14,4 +14,5 @@ export * from "./multi-select";
|
||||
export * from "./tabs";
|
||||
export * from "./table";
|
||||
export * from "./toggle-group";
|
||||
export * from "./color-password";
|
||||
export * from "./utils/i18n-mock.service";
|
||||
|
Loading…
Reference in New Issue
Block a user