1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-06 00:13:28 +00:00

[CL-737] Migrate last copy click input to signal (#16291)

This commit is contained in:
Vicki League
2025-09-19 11:28:07 -07:00
committed by GitHub
parent 049f84bd0e
commit ea5eb9aaf7
2 changed files with 159 additions and 16 deletions

View File

@@ -1,11 +1,11 @@
import {
Directive,
HostListener,
Input,
InjectionToken,
Inject,
Optional,
input,
computed,
} from "@angular/core";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@@ -26,8 +26,19 @@ export const COPY_CLICK_LISTENER = new InjectionToken<CopyClickListener>("CopyCl
selector: "[appCopyClick]",
})
export class CopyClickDirective {
private _showToast = false;
private toastVariant: ToastVariant = "success";
private _showToast = computed(() => {
return this.showToast() !== undefined;
});
private toastVariant = computed(() => {
const showToast = this.showToast();
// When the `showToast` is set without a value, an empty string will be passed
if (showToast === "" || showToast === undefined) {
return "success";
} else {
return showToast;
}
});
constructor(
private platformUtilsService: PlatformUtilsService,
@@ -57,17 +68,7 @@ export class CopyClickDirective {
* <app-component [appCopyClick]="value to copy" showToast="info"/></app-component>
* ```
*/
// TODO: Skipped for signal migration because:
// Accessor inputs cannot be migrated as they are too complex.
@Input() set showToast(value: ToastVariant | "") {
// When the `showToast` is set without a value, an empty string will be passed
if (value === "") {
this._showToast = true;
} else {
this._showToast = true;
this.toastVariant = value;
}
}
showToast = input<ToastVariant | "">();
@HostListener("click") onClick() {
const valueToCopy = this.valueToCopy();
@@ -77,14 +78,14 @@ export class CopyClickDirective {
this.copyListener.onCopy(valueToCopy);
}
if (this._showToast) {
if (this._showToast()) {
const valueLabel = this.valueLabel();
const message = valueLabel
? this.i18nService.t("valueCopied", valueLabel)
: this.i18nService.t("copySuccessful");
this.toastService.showToast({
variant: this.toastVariant,
variant: this.toastVariant(),
message,
});
}

View File

@@ -0,0 +1,142 @@
import { provideNoopAnimations } from "@angular/platform-browser/animations";
import { applicationConfig, moduleMetadata, StoryObj } from "@storybook/angular";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { FormFieldModule } from "../form-field";
import { IconButtonModule } from "../icon-button";
import { InputModule } from "../input";
import { ToastModule } from "../toast";
import { I18nMockService } from "../utils";
import { CopyClickDirective } from "./copy-click.directive";
export default {
title: "Component Library/Copy Click Directive",
component: CopyClickDirective,
decorators: [
moduleMetadata({
imports: [ToastModule, FormFieldModule, InputModule, IconButtonModule],
}),
applicationConfig({
providers: [
ToastModule.forRoot().providers!,
{
provide: PlatformUtilsService,
useValue: {
// eslint-disable-next-line
copyToClipboard: (text: string) => console.log(`"${text}" copied to clipboard`),
},
},
{
provide: I18nService,
useFactory: () => {
return new I18nMockService({
valueCopied: (text) => `${text} copied`,
copySuccessful: "Copy Successful",
success: "Success",
close: "Close",
info: "Info",
});
},
},
provideNoopAnimations(),
],
}),
],
};
type Story = StoryObj<CopyClickDirective>;
export const Default: Story = {
render: (args) => ({
props: {
value: "testValue123",
...args,
},
template: /*html*/ `
<bit-form-field>
<bit-label>API Key</bit-label>
<input bitInput disabled [value]="value" />
<button
type="button"
bitSuffix
bitIconButton="bwi-clone"
[label]="'Copy'"
[appCopyClick]="value"
></button>
</bit-form-field>
`,
}),
};
export const WithDefaultToast: Story = {
render: (args) => ({
props: {
value: "testValue123",
...args,
},
template: /*html*/ `
<bit-form-field>
<bit-label>API Key</bit-label>
<input bitInput disabled [value]="value" />
<button
type="button"
bitSuffix
bitIconButton="bwi-clone"
[label]="'Copy'"
[appCopyClick]="value"
showToast
></button>
</bit-form-field>
`,
}),
};
export const WithCustomToastVariant: Story = {
render: (args) => ({
props: {
value: "testValue123",
...args,
},
template: /*html*/ `
<bit-form-field>
<bit-label>API Key</bit-label>
<input bitInput disabled [value]="value" />
<button
type="button"
bitSuffix
bitIconButton="bwi-clone"
[label]="'Copy'"
[appCopyClick]="value"
showToast="info"
></button>
</bit-form-field>
`,
}),
};
export const WithCustomValueLabel: Story = {
render: (args) => ({
props: {
value: "testValue123",
...args,
},
template: /*html*/ `
<bit-form-field>
<bit-label>API Key</bit-label>
<input bitInput disabled [value]="value" />
<button
type="button"
bitSuffix
bitIconButton="bwi-clone"
[label]="'Copy'"
[appCopyClick]="value"
showToast
valueLabel="API Key"
></button>
</bit-form-field>
`,
}),
};