diff --git a/libs/components/src/color-password/color-password.component.ts b/libs/components/src/color-password/color-password.component.ts new file mode 100644 index 0000000000..b55384dea1 --- /dev/null +++ b/libs/components/src/color-password/color-password.component.ts @@ -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: `
+ {{ character }} + {{ + i + 1 + }} +
`, +}) +export class ColorPasswordComponent { + @Input() private password: string = null; + @Input() showCount = false; + + characterStyles: Record = { + [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; + } +} diff --git a/libs/components/src/color-password/color-password.module.ts b/libs/components/src/color-password/color-password.module.ts new file mode 100644 index 0000000000..692c206bb4 --- /dev/null +++ b/libs/components/src/color-password/color-password.module.ts @@ -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 {} diff --git a/libs/components/src/color-password/color-password.stories.ts b/libs/components/src/color-password/color-password.stories.ts new file mode 100644 index 0000000000..87565b8127 --- /dev/null +++ b/libs/components/src/color-password/color-password.stories.ts @@ -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 = (args: ColorPasswordComponent) => ({ + props: args, + template: ` + + `, +}); + +const WrappedTemplate: Story = (args: ColorPasswordComponent) => ({ + props: args, + template: ` +
+ +
+ `, +}); + +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, +}; diff --git a/libs/components/src/color-password/index.ts b/libs/components/src/color-password/index.ts new file mode 100644 index 0000000000..86718f037f --- /dev/null +++ b/libs/components/src/color-password/index.ts @@ -0,0 +1 @@ +export * from "./color-password.module"; diff --git a/libs/components/src/index.ts b/libs/components/src/index.ts index e217c6bf02..8abb6bade3 100644 --- a/libs/components/src/index.ts +++ b/libs/components/src/index.ts @@ -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";