File

src/lib/default-header/settings-button/settings-button.component.ts

Metadata

Index

Properties
Methods

Methods

clickItem
clickItem(item: SettingsMenuItem)
Parameters :
Name Type Optional
item SettingsMenuItem No
Returns : void
previewDensity
previewDensity(density: ThemeDensity)
Parameters :
Name Type Optional
density ThemeDensity No
Returns : void
previewTheme
previewTheme(theme: string)
Parameters :
Name Type Optional
theme string No
Returns : void
previewTypography
previewTypography(typography: string)
Parameters :
Name Type Optional
typography string No
Returns : void
restoreDensity
restoreDensity()
Returns : void
restoreTheme
restoreTheme()
Returns : void
restoreTypography
restoreTypography()
Returns : void
setDensity
setDensity(density: ThemeDensity)
Parameters :
Name Type Optional
density ThemeDensity No
Returns : void
setTheme
setTheme(theme: string)
Parameters :
Name Type Optional
theme string No
Returns : void
setTypography
setTypography(typography: string)
Parameters :
Name Type Optional
typography string No
Returns : void

Properties

Public Readonly availableThemes
Default value : this.theme.getAvailableThemes()
Public Readonly availableTypographies
Default value : this.theme.getAvailableTypographies()
customItemComponents
Type : Signal<ComponentPortal[]>
Default value : toSignal(from(Promise.all( coerceArray(inject(RXAP_SETTINGS_MENU_ITEM_COMPONENT, { optional: true })) .map(item => IsFunction(item) ? item() : item), )).pipe(map(items => items.map(item => new ComponentPortal(item, null, this.injector)))), { initialValue: [] })
customItems
Default value : signal(coerceArray(inject(RXAP_SETTINGS_MENU_ITEM, { optional: true })))
Protected Readonly injector
Default value : inject(Injector)
Public isDevMode
Default value : isDevMode()
Public Readonly theme
Default value : inject(ThemeService)
import {
  CdkPortalOutlet,
  ComponentPortal,
} from '@angular/cdk/portal';
import { NgIf } from '@angular/common';
import {
  Component,
  inject,
  Injector,
  isDevMode,
  runInInjectionContext,
  Signal,
  signal,
} from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { MatIconButton } from '@angular/material/button';
import { MatIcon } from '@angular/material/icon';
import {
  MatMenu,
  MatMenuItem,
  MatMenuTrigger,
} from '@angular/material/menu';
import { IconDirective } from '@rxap/material-directives/icon';
import {
  ThemeService,
} from '@rxap/ngx-theme';
import {
  coerceArray,
  IsFunction,
  ThemeDensity,
} from '@rxap/utilities';
import { from } from 'rxjs';
import { map } from 'rxjs/operators';
import {
  RXAP_SETTINGS_MENU_ITEM,
  RXAP_SETTINGS_MENU_ITEM_COMPONENT,
} from '../../tokens';
import { SettingsMenuItem } from '../../types';

@Component({
    selector: 'rxap-settings-button',
    templateUrl: './settings-button.component.html',
    styleUrls: ['./settings-button.component.scss'],
    imports: [
        MatIconButton,
        MatIcon,
        MatMenu,
        MatMenuTrigger,
        MatMenuItem,
        CdkPortalOutlet,
        IconDirective,
        NgIf,
    ]
})
export class SettingsButtonComponent {

  public isDevMode = isDevMode();

  public readonly theme = inject(ThemeService);
  protected readonly injector = inject(Injector);

  customItemComponents: Signal<ComponentPortal<unknown>[]> = toSignal(from(Promise.all(
    coerceArray(inject(RXAP_SETTINGS_MENU_ITEM_COMPONENT, { optional: true }))
      .map(item => IsFunction(item) ? item() : item),
  )).pipe(map(items => items.map(item => new ComponentPortal(item, null, this.injector)))), { initialValue: [] });

  customItems = signal(coerceArray(inject(RXAP_SETTINGS_MENU_ITEM, { optional: true })));

  private savePreviewDensityValue = false;
  private currentDensityValue: ThemeDensity | null = null;

  private savePreviewTypographyValue = false;
  private currentTypographyValue: string | null = null;

  public readonly availableTypographies = this.theme.getAvailableTypographies();
  private savePreviewThemeValue = false;

  public readonly availableThemes = this.theme.getAvailableThemes();
  private currentThemeValue: string | null = null;

  previewDensity(density: ThemeDensity) {
    this.theme.applyDensity(density);
  }

  restoreDensity() {
    this.theme.applyDensity(this.theme.density());
  }

  setDensity(density: ThemeDensity) {
    this.theme.setDensity(density);
  }

  previewTypography(typography: string) {
    this.theme.applyTypography(typography);
  }

  restoreTypography() {
    this.theme.applyTypography(this.theme.typography());
  }

  setTypography(typography: string) {
    this.theme.setTypography(typography);
  }

  previewTheme(theme: string) {
    this.theme.applyTheme(theme);
  }

  restoreTheme() {
    this.theme.applyTheme(this.theme.themeName());
  }

  setTheme(theme: string) {
    this.theme.setTheme(theme);
  }

  clickItem(item: SettingsMenuItem) {
    runInInjectionContext(this.injector, () => item.action());
  }
}
<button [matMenuTriggerFor]="menu" mat-icon-button>
  <mat-icon svgIcon="cog"></mat-icon>
</button>

<mat-menu #menu="matMenu">
  <button (click)="theme.toggleDarkTheme()" mat-menu-item>
    @if (theme.darkMode()) {
      <mat-icon svgIcon="brightness-2"></mat-icon>
    } @else {
      <mat-icon svgIcon="brightness-5"></mat-icon>
    }
    <span i18n>Mode</span>
  </button>
  <button [matMenuTriggerFor]="themeMenu" mat-menu-item>
    <mat-icon svgIcon="compare"></mat-icon>
    <span i18n>Theme</span>
  </button>
  @for (item of customItems(); track item.label) {
    <button (click)="clickItem(item)" mat-menu-item>
      <mat-icon *ngIf="item.icon as icon" [rxapIcon]="icon"></mat-icon>
      <span>{{ item.label }}</span>
    </button>
  }
  @for (item of customItemComponents(); track item) {
    <ng-template [cdkPortalOutlet]="item"></ng-template>
  }
</mat-menu>

<mat-menu #themeMenu="matMenu" xPosition="before">
  <button [matMenuTriggerFor]="themeDensityMenu" mat-menu-item>
    <mat-icon svgIcon="move-resize"></mat-icon>
    <span i18n>Density</span>
  </button>
  @if (availableTypographies?.length) {
    <button [matMenuTriggerFor]="themeFontMenu" mat-menu-item>
      <mat-icon svgIcon="format-font"></mat-icon>
      <span i18n>Font</span>
    </button>
  }
  @if (availableThemes?.length) {
    <button [matMenuTriggerFor]="themePresetMenu" mat-menu-item>
      <mat-icon svgIcon="shape-outline"></mat-icon>
      <span i18n>Preset</span>
    </button>
  }
</mat-menu>

<mat-menu #themeDensityMenu="matMenu" xPosition="before">
  <button (click)="setDensity(0)" (mouseenter)="previewDensity(0)" (mouseleave)="restoreDensity()" mat-menu-item>
    <mat-icon svgIcon="size-l"></mat-icon>
    <span i18n>Normal</span>
  </button>
  <button (click)="setDensity(-1)" (mouseenter)="previewDensity(-1)" (mouseleave)="restoreDensity()" mat-menu-item>
    <mat-icon svgIcon="size-m"></mat-icon>
    <span i18n>Dense</span>
  </button>
  <button (click)="setDensity(-2)" (mouseenter)="previewDensity(-2)" (mouseleave)="restoreDensity()" mat-menu-item>
    <mat-icon svgIcon="size-s"></mat-icon>
    <span i18n>Very Dense</span>
  </button>
  <button (click)="setDensity(-3)" (mouseenter)="previewDensity(-3)" (mouseleave)="restoreDensity()" mat-menu-item>
    <mat-icon svgIcon="size-xs"></mat-icon>
    <span i18n>Extreme Dense</span>
  </button>
</mat-menu>
<mat-menu #themeFontMenu="matMenu" xPosition="before">
  @for (typographyName of availableTypographies ?? []; track typographyName) {
    <button (click)="setTypography(typographyName)"
            (mouseenter)="previewTypography(typographyName)"
            (mouseleave)="restoreTypography()"
            mat-menu-item>
      {{ typographyName }}
    </button>
  }
</mat-menu>

<mat-menu #themePresetMenu="matMenu" xPosition="before">
  @for (themeName of availableThemes ?? []; track themeName) {
    <button (click)="setTheme(themeName)"
            (mouseenter)="previewTheme(themeName)"
            (mouseleave)="restoreTheme()"
            mat-menu-item>
      {{ themeName }}
    </button>
  }
</mat-menu>

./settings-button.component.scss

Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""