import { CommonModule } from "@angular/common"; import { Component, importProvidersFrom, Injectable, Input } from "@angular/core"; import { RouterModule } from "@angular/router"; import { applicationConfig, componentWrapperDecorator, Meta, moduleMetadata, StoryObj, } from "@storybook/angular"; import { BehaviorSubject, combineLatest, map, of } from "rxjs"; import { JslibModule } from "@bitwarden/angular/jslib.module"; import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; import { AvatarModule, BreadcrumbsModule, ButtonModule, IconButtonModule, IconModule, InputModule, MenuModule, NavigationModule, TabsModule, TypographyModule, } from "@bitwarden/components"; import { DynamicAvatarComponent } from "../../components/dynamic-avatar.component"; import { PreloadedEnglishI18nModule } from "../../core/tests"; import { WebHeaderComponent } from "../header/web-header.component"; import { WebLayoutMigrationBannerService } from "./web-layout-migration-banner.service"; @Injectable({ providedIn: "root", }) class MockStateService { activeAccount$ = new BehaviorSubject("1").asObservable(); accounts$ = new BehaviorSubject({ "1": { profile: { name: "Foo" } } }).asObservable(); } @Component({ selector: "product-switcher", template: ``, }) class MockProductSwitcher {} @Component({ selector: "dynamic-avatar", template: ``, standalone: true, imports: [CommonModule, AvatarModule], }) class MockDynamicAvatar implements Partial { protected name$ = combineLatest([ this.stateService.accounts$, this.stateService.activeAccount$, ]).pipe( map( ([accounts, activeAccount]) => accounts[activeAccount as keyof typeof accounts].profile.name, ), ); @Input() text?: string; constructor(private stateService: MockStateService) {} } export default { title: "Web/Header", component: WebHeaderComponent, decorators: [ componentWrapperDecorator( (story) => `
${story}
`, ), moduleMetadata({ imports: [ JslibModule, AvatarModule, BreadcrumbsModule, ButtonModule, IconButtonModule, IconModule, InputModule, MenuModule, TabsModule, TypographyModule, NavigationModule, MockDynamicAvatar, ], declarations: [WebHeaderComponent, MockProductSwitcher], providers: [ { provide: StateService, useClass: MockStateService }, { provide: AccountService, useValue: { activeAccount$: of({ name: "Foobar Warden", }), } as Partial, }, { provide: WebLayoutMigrationBannerService, useValue: { showBanner$: of(false), } as Partial, }, { provide: PlatformUtilsService, useValue: { isSelfHost() { return false; }, } as Partial, }, { provide: VaultTimeoutSettingsService, useValue: { availableVaultTimeoutActions$() { return new BehaviorSubject([VaultTimeoutAction.Lock]).asObservable(); }, } as Partial, }, { provide: MessagingService, useValue: { send: (...args: any[]) => { // eslint-disable-next-line no-console console.log("MessagingService.send", args); }, } as Partial, }, ], }), applicationConfig({ providers: [ importProvidersFrom(RouterModule.forRoot([], { useHash: true })), importProvidersFrom(PreloadedEnglishI18nModule), ], }), ], } as Meta; type Story = StoryObj; export const KitchenSink: Story = { render: (args) => ({ props: args, template: ` Foo Bar Foo Bar `, }), }; export const Basic: Story = { render: (args: any) => ({ props: args, template: ` `, }), }; export const WithLongTitle: Story = { render: (arg: any) => ({ props: arg, template: ` `, }), }; export const WithBreadcrumbs: Story = { render: (args: any) => ({ props: args, template: ` Foo Bar `, }), }; export const WithSearch: Story = { render: (args: any) => ({ props: args, template: ` `, }), }; export const WithSecondaryContent: Story = { render: (args) => ({ props: args, template: ` `, }), }; export const WithTabs: Story = { render: (args) => ({ props: args, template: ` Foo Bar `, }), }; export const WithTitleSuffixComponent: Story = { render: (args) => ({ props: args, template: ` `, }), };