mirror of
https://github.com/bitwarden/browser
synced 2025-12-13 06:43:35 +00:00
[CL-737] Migrate last copy click input to signal (#16291)
This commit is contained in:
@@ -1,11 +1,11 @@
|
|||||||
import {
|
import {
|
||||||
Directive,
|
Directive,
|
||||||
HostListener,
|
HostListener,
|
||||||
Input,
|
|
||||||
InjectionToken,
|
InjectionToken,
|
||||||
Inject,
|
Inject,
|
||||||
Optional,
|
Optional,
|
||||||
input,
|
input,
|
||||||
|
computed,
|
||||||
} from "@angular/core";
|
} from "@angular/core";
|
||||||
|
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
@@ -26,8 +26,19 @@ export const COPY_CLICK_LISTENER = new InjectionToken<CopyClickListener>("CopyCl
|
|||||||
selector: "[appCopyClick]",
|
selector: "[appCopyClick]",
|
||||||
})
|
})
|
||||||
export class CopyClickDirective {
|
export class CopyClickDirective {
|
||||||
private _showToast = false;
|
private _showToast = computed(() => {
|
||||||
private toastVariant: ToastVariant = "success";
|
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(
|
constructor(
|
||||||
private platformUtilsService: PlatformUtilsService,
|
private platformUtilsService: PlatformUtilsService,
|
||||||
@@ -57,17 +68,7 @@ export class CopyClickDirective {
|
|||||||
* <app-component [appCopyClick]="value to copy" showToast="info"/></app-component>
|
* <app-component [appCopyClick]="value to copy" showToast="info"/></app-component>
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
// TODO: Skipped for signal migration because:
|
showToast = input<ToastVariant | "">();
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@HostListener("click") onClick() {
|
@HostListener("click") onClick() {
|
||||||
const valueToCopy = this.valueToCopy();
|
const valueToCopy = this.valueToCopy();
|
||||||
@@ -77,14 +78,14 @@ export class CopyClickDirective {
|
|||||||
this.copyListener.onCopy(valueToCopy);
|
this.copyListener.onCopy(valueToCopy);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._showToast) {
|
if (this._showToast()) {
|
||||||
const valueLabel = this.valueLabel();
|
const valueLabel = this.valueLabel();
|
||||||
const message = valueLabel
|
const message = valueLabel
|
||||||
? this.i18nService.t("valueCopied", valueLabel)
|
? this.i18nService.t("valueCopied", valueLabel)
|
||||||
: this.i18nService.t("copySuccessful");
|
: this.i18nService.t("copySuccessful");
|
||||||
|
|
||||||
this.toastService.showToast({
|
this.toastService.showToast({
|
||||||
variant: this.toastVariant,
|
variant: this.toastVariant(),
|
||||||
message,
|
message,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
142
libs/components/src/copy-click/copy-click.stories.ts
Normal file
142
libs/components/src/copy-click/copy-click.stories.ts
Normal 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>
|
||||||
|
`,
|
||||||
|
}),
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user