mirror of
https://github.com/bitwarden/browser
synced 2025-12-10 13:23:34 +00:00
[CL-553] Migrate CL to Control Flow syntax (#12390)
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { NgIf, NgClass } from "@angular/common";
|
import { NgClass } from "@angular/common";
|
||||||
import { Component, Input, OnChanges } from "@angular/core";
|
import { Component, Input, OnChanges } from "@angular/core";
|
||||||
import { DomSanitizer, SafeResourceUrl } from "@angular/platform-browser";
|
import { DomSanitizer, SafeResourceUrl } from "@angular/platform-browser";
|
||||||
|
|
||||||
@@ -18,9 +18,11 @@ const SizeClasses: Record<SizeTypes, string[]> = {
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "bit-avatar",
|
selector: "bit-avatar",
|
||||||
template: `<img *ngIf="src" [src]="src" title="{{ title || text }}" [ngClass]="classList" />`,
|
template: `@if (src) {
|
||||||
|
<img [src]="src" title="{{ title || text }}" [ngClass]="classList" />
|
||||||
|
}`,
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [NgIf, NgClass],
|
imports: [NgClass],
|
||||||
})
|
})
|
||||||
export class AvatarComponent implements OnChanges {
|
export class AvatarComponent implements OnChanges {
|
||||||
@Input() border = false;
|
@Input() border = false;
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
<div class="tw-inline-flex tw-flex-wrap tw-gap-2">
|
<div class="tw-inline-flex tw-flex-wrap tw-gap-2">
|
||||||
<ng-container *ngFor="let item of filteredItems; let last = last">
|
@for (item of filteredItems; track item; let last = $last) {
|
||||||
<span bitBadge [variant]="variant" [truncate]="truncate">
|
<span bitBadge [variant]="variant" [truncate]="truncate">
|
||||||
{{ item }}
|
{{ item }}
|
||||||
</span>
|
</span>
|
||||||
<span class="tw-sr-only" *ngIf="!last || isFiltered">, </span>
|
@if (!last || isFiltered) {
|
||||||
</ng-container>
|
<span class="tw-sr-only">, </span>
|
||||||
<span *ngIf="isFiltered" bitBadge [variant]="variant">
|
}
|
||||||
{{ "plusNMore" | i18n: (items.length - filteredItems.length).toString() }}
|
}
|
||||||
</span>
|
@if (isFiltered) {
|
||||||
|
<span bitBadge [variant]="variant">
|
||||||
|
{{ "plusNMore" | i18n: (items.length - filteredItems.length).toString() }}
|
||||||
|
</span>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { CommonModule } from "@angular/common";
|
|
||||||
import { Component, Input, OnChanges } from "@angular/core";
|
import { Component, Input, OnChanges } from "@angular/core";
|
||||||
|
|
||||||
import { I18nPipe } from "@bitwarden/ui-common";
|
import { I18nPipe } from "@bitwarden/ui-common";
|
||||||
@@ -11,7 +11,7 @@ import { BadgeModule, BadgeVariant } from "../badge";
|
|||||||
selector: "bit-badge-list",
|
selector: "bit-badge-list",
|
||||||
templateUrl: "badge-list.component.html",
|
templateUrl: "badge-list.component.html",
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, BadgeModule, I18nPipe],
|
imports: [BadgeModule, I18nPipe],
|
||||||
})
|
})
|
||||||
export class BadgeListComponent implements OnChanges {
|
export class BadgeListComponent implements OnChanges {
|
||||||
private _maxItems: number;
|
private _maxItems: number;
|
||||||
|
|||||||
@@ -4,21 +4,24 @@
|
|||||||
[attr.role]="useAlertRole ? 'status' : null"
|
[attr.role]="useAlertRole ? 'status' : null"
|
||||||
[attr.aria-live]="useAlertRole ? 'polite' : null"
|
[attr.aria-live]="useAlertRole ? 'polite' : null"
|
||||||
>
|
>
|
||||||
<i class="bwi tw-align-middle tw-text-base" [ngClass]="icon" *ngIf="icon" aria-hidden="true"></i>
|
@if (icon) {
|
||||||
|
<i class="bwi tw-align-middle tw-text-base" [ngClass]="icon" aria-hidden="true"></i>
|
||||||
|
}
|
||||||
<!-- Overriding focus-visible color for link buttons for a11y against colored background -->
|
<!-- Overriding focus-visible color for link buttons for a11y against colored background -->
|
||||||
<span class="tw-grow tw-text-base [&>button[bitlink]:focus-visible:before]:!tw-ring-text-main">
|
<span class="tw-grow tw-text-base [&>button[bitlink]:focus-visible:before]:!tw-ring-text-main">
|
||||||
<ng-content></ng-content>
|
<ng-content></ng-content>
|
||||||
</span>
|
</span>
|
||||||
<!-- Overriding hover and focus-visible colors for a11y against colored background -->
|
<!-- Overriding hover and focus-visible colors for a11y against colored background -->
|
||||||
<button
|
@if (showClose) {
|
||||||
*ngIf="showClose"
|
<button
|
||||||
class="hover:tw-border-text-main focus-visible:before:tw-ring-text-main"
|
class="hover:tw-border-text-main focus-visible:before:tw-ring-text-main"
|
||||||
type="button"
|
type="button"
|
||||||
bitIconButton="bwi-close"
|
bitIconButton="bwi-close"
|
||||||
buttonType="main"
|
buttonType="main"
|
||||||
size="default"
|
size="default"
|
||||||
(click)="onClose.emit()"
|
(click)="onClose.emit()"
|
||||||
[attr.title]="'close' | i18n"
|
[attr.title]="'close' | i18n"
|
||||||
[attr.aria-label]="'close' | i18n"
|
[attr.aria-label]="'close' | i18n"
|
||||||
></button>
|
></button>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
<ng-template>
|
<ng-template>
|
||||||
<i *ngIf="icon" class="bwi {{ icon }} !tw-mr-2" aria-hidden="true"></i><ng-content></ng-content>
|
@if (icon) {
|
||||||
|
<i class="bwi {{ icon }} !tw-mr-2" aria-hidden="true"></i>
|
||||||
|
}
|
||||||
|
<ng-content></ng-content>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { NgIf } from "@angular/common";
|
|
||||||
import { Component, EventEmitter, Input, Output, TemplateRef, ViewChild } from "@angular/core";
|
import { Component, EventEmitter, Input, Output, TemplateRef, ViewChild } from "@angular/core";
|
||||||
import { QueryParamsHandling } from "@angular/router";
|
import { QueryParamsHandling } from "@angular/router";
|
||||||
|
|
||||||
@@ -8,7 +8,6 @@ import { QueryParamsHandling } from "@angular/router";
|
|||||||
selector: "bit-breadcrumb",
|
selector: "bit-breadcrumb",
|
||||||
templateUrl: "./breadcrumb.component.html",
|
templateUrl: "./breadcrumb.component.html",
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [NgIf],
|
|
||||||
})
|
})
|
||||||
export class BreadcrumbComponent {
|
export class BreadcrumbComponent {
|
||||||
@Input()
|
@Input()
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<ng-container *ngFor="let breadcrumb of beforeOverflow; let last = last">
|
@for (breadcrumb of beforeOverflow; track breadcrumb; let last = $last) {
|
||||||
<ng-container *ngIf="breadcrumb.route">
|
@if (breadcrumb.route) {
|
||||||
<a
|
<a
|
||||||
bitLink
|
bitLink
|
||||||
linkType="primary"
|
linkType="primary"
|
||||||
@@ -10,8 +10,8 @@
|
|||||||
>
|
>
|
||||||
<ng-container [ngTemplateOutlet]="breadcrumb.content"></ng-container>
|
<ng-container [ngTemplateOutlet]="breadcrumb.content"></ng-container>
|
||||||
</a>
|
</a>
|
||||||
</ng-container>
|
}
|
||||||
<ng-container *ngIf="!breadcrumb.route">
|
@if (!breadcrumb.route) {
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
bitLink
|
bitLink
|
||||||
@@ -21,13 +21,16 @@
|
|||||||
>
|
>
|
||||||
<ng-container [ngTemplateOutlet]="breadcrumb.content"></ng-container>
|
<ng-container [ngTemplateOutlet]="breadcrumb.content"></ng-container>
|
||||||
</button>
|
</button>
|
||||||
</ng-container>
|
}
|
||||||
<i *ngIf="!last" class="bwi bwi-angle-right tw-mx-1.5 tw-text-main"></i>
|
@if (!last) {
|
||||||
</ng-container>
|
<i class="bwi bwi-angle-right tw-mx-1.5 tw-text-main"></i>
|
||||||
|
}
|
||||||
<ng-container *ngIf="hasOverflow">
|
}
|
||||||
<i *ngIf="beforeOverflow.length > 0" class="bwi bwi-angle-right tw-mx-1.5 tw-text-main"></i>
|
|
||||||
|
|
||||||
|
@if (hasOverflow) {
|
||||||
|
@if (beforeOverflow.length > 0) {
|
||||||
|
<i class="bwi bwi-angle-right tw-mx-1.5 tw-text-main"></i>
|
||||||
|
}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
bitIconButton="bwi-ellipsis-h"
|
bitIconButton="bwi-ellipsis-h"
|
||||||
@@ -35,10 +38,9 @@
|
|||||||
size="small"
|
size="small"
|
||||||
aria-haspopup
|
aria-haspopup
|
||||||
></button>
|
></button>
|
||||||
|
|
||||||
<bit-menu #overflowMenu>
|
<bit-menu #overflowMenu>
|
||||||
<ng-container *ngFor="let breadcrumb of overflow">
|
@for (breadcrumb of overflow; track breadcrumb) {
|
||||||
<ng-container *ngIf="breadcrumb.route">
|
@if (breadcrumb.route) {
|
||||||
<a
|
<a
|
||||||
bitMenuItem
|
bitMenuItem
|
||||||
linkType="primary"
|
linkType="primary"
|
||||||
@@ -48,18 +50,17 @@
|
|||||||
>
|
>
|
||||||
<ng-container [ngTemplateOutlet]="breadcrumb.content"></ng-container>
|
<ng-container [ngTemplateOutlet]="breadcrumb.content"></ng-container>
|
||||||
</a>
|
</a>
|
||||||
</ng-container>
|
}
|
||||||
<ng-container *ngIf="!breadcrumb.route">
|
@if (!breadcrumb.route) {
|
||||||
<button type="button" bitMenuItem linkType="primary" (click)="breadcrumb.onClick($event)">
|
<button type="button" bitMenuItem linkType="primary" (click)="breadcrumb.onClick($event)">
|
||||||
<ng-container [ngTemplateOutlet]="breadcrumb.content"></ng-container>
|
<ng-container [ngTemplateOutlet]="breadcrumb.content"></ng-container>
|
||||||
</button>
|
</button>
|
||||||
</ng-container>
|
}
|
||||||
</ng-container>
|
}
|
||||||
</bit-menu>
|
</bit-menu>
|
||||||
<i class="bwi bwi-angle-right tw-mx-1.5 tw-text-main"></i>
|
<i class="bwi bwi-angle-right tw-mx-1.5 tw-text-main"></i>
|
||||||
|
@for (breadcrumb of afterOverflow; track breadcrumb; let last = $last) {
|
||||||
<ng-container *ngFor="let breadcrumb of afterOverflow; let last = last">
|
@if (breadcrumb.route) {
|
||||||
<ng-container *ngIf="breadcrumb.route">
|
|
||||||
<a
|
<a
|
||||||
bitLink
|
bitLink
|
||||||
linkType="primary"
|
linkType="primary"
|
||||||
@@ -70,8 +71,8 @@
|
|||||||
>
|
>
|
||||||
<ng-container [ngTemplateOutlet]="breadcrumb.content"></ng-container>
|
<ng-container [ngTemplateOutlet]="breadcrumb.content"></ng-container>
|
||||||
</a>
|
</a>
|
||||||
</ng-container>
|
}
|
||||||
<ng-container *ngIf="!breadcrumb.route">
|
@if (!breadcrumb.route) {
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
bitLink
|
bitLink
|
||||||
@@ -81,7 +82,9 @@
|
|||||||
>
|
>
|
||||||
<ng-container [ngTemplateOutlet]="breadcrumb.content"></ng-container>
|
<ng-container [ngTemplateOutlet]="breadcrumb.content"></ng-container>
|
||||||
</button>
|
</button>
|
||||||
</ng-container>
|
}
|
||||||
<i *ngIf="!last" class="bwi bwi-angle-right tw-mx-1.5 tw-text-main"></i>
|
@if (!last) {
|
||||||
</ng-container>
|
<i class="bwi bwi-angle-right tw-mx-1.5 tw-text-main"></i>
|
||||||
</ng-container>
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -86,16 +86,15 @@ export const DisabledWithAttribute: Story = {
|
|||||||
render: (args) => ({
|
render: (args) => ({
|
||||||
props: args,
|
props: args,
|
||||||
template: `
|
template: `
|
||||||
<ng-container *ngIf="disabled">
|
@if (disabled) {
|
||||||
<button bitButton disabled [loading]="loading" [block]="block" buttonType="primary" class="tw-mr-2">Primary</button>
|
<button bitButton disabled [loading]="loading" [block]="block" buttonType="primary" class="tw-mr-2">Primary</button>
|
||||||
<button bitButton disabled [loading]="loading" [block]="block" buttonType="secondary" class="tw-mr-2">Secondary</button>
|
<button bitButton disabled [loading]="loading" [block]="block" buttonType="secondary" class="tw-mr-2">Secondary</button>
|
||||||
<button bitButton disabled [loading]="loading" [block]="block" buttonType="danger" class="tw-mr-2">Danger</button>
|
<button bitButton disabled [loading]="loading" [block]="block" buttonType="danger" class="tw-mr-2">Danger</button>
|
||||||
</ng-container>
|
} @else {
|
||||||
<ng-container *ngIf="!disabled">
|
|
||||||
<button bitButton [loading]="loading" [block]="block" buttonType="primary" class="tw-mr-2">Primary</button>
|
<button bitButton [loading]="loading" [block]="block" buttonType="primary" class="tw-mr-2">Primary</button>
|
||||||
<button bitButton [loading]="loading" [block]="block" buttonType="secondary" class="tw-mr-2">Secondary</button>
|
<button bitButton [loading]="loading" [block]="block" buttonType="secondary" class="tw-mr-2">Secondary</button>
|
||||||
<button bitButton [loading]="loading" [block]="block" buttonType="danger" class="tw-mr-2">Danger</button>
|
<button bitButton [loading]="loading" [block]="block" buttonType="danger" class="tw-mr-2">Danger</button>
|
||||||
</ng-container>
|
}
|
||||||
`,
|
`,
|
||||||
}),
|
}),
|
||||||
args: {
|
args: {
|
||||||
|
|||||||
@@ -3,10 +3,14 @@
|
|||||||
[ngClass]="calloutClass"
|
[ngClass]="calloutClass"
|
||||||
[attr.aria-labelledby]="titleId"
|
[attr.aria-labelledby]="titleId"
|
||||||
>
|
>
|
||||||
<header id="{{ titleId }}" class="tw-mb-1 tw-mt-0 tw-text-base tw-font-semibold" *ngIf="title">
|
@if (title) {
|
||||||
<i class="bwi" [ngClass]="[icon, headerClass]" *ngIf="icon" aria-hidden="true"></i>
|
<header id="{{ titleId }}" class="tw-mb-1 tw-mt-0 tw-text-base tw-font-semibold">
|
||||||
{{ title }}
|
@if (icon) {
|
||||||
</header>
|
<i class="bwi" [ngClass]="[icon, headerClass]" aria-hidden="true"></i>
|
||||||
|
}
|
||||||
|
{{ title }}
|
||||||
|
</header>
|
||||||
|
}
|
||||||
<div bitTypography="body2">
|
<div bitTypography="body2">
|
||||||
<ng-content></ng-content>
|
<ng-content></ng-content>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import { CommonModule } from "@angular/common";
|
|
||||||
import { ChangeDetectionStrategy, Component } from "@angular/core";
|
import { ChangeDetectionStrategy, Component } from "@angular/core";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "bit-card",
|
selector: "bit-card",
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule],
|
|
||||||
template: `<ng-content></ng-content>`,
|
template: `<ng-content></ng-content>`,
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
host: {
|
host: {
|
||||||
|
|||||||
@@ -30,78 +30,80 @@
|
|||||||
<i class="bwi !tw-text-[inherit]" [ngClass]="icon"></i>
|
<i class="bwi !tw-text-[inherit]" [ngClass]="icon"></i>
|
||||||
<span class="tw-truncate">{{ label }}</span>
|
<span class="tw-truncate">{{ label }}</span>
|
||||||
</span>
|
</span>
|
||||||
<i
|
@if (!selectedOption) {
|
||||||
*ngIf="!selectedOption"
|
<i
|
||||||
class="bwi tw-mt-0.5"
|
class="bwi tw-mt-0.5"
|
||||||
[ngClass]="menuTrigger.isOpen ? 'bwi-angle-up' : 'bwi-angle-down'"
|
[ngClass]="menuTrigger.isOpen ? 'bwi-angle-up' : 'bwi-angle-down'"
|
||||||
></i>
|
></i>
|
||||||
|
}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- Close button -->
|
<!-- Close button -->
|
||||||
<button
|
@if (selectedOption) {
|
||||||
*ngIf="selectedOption"
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
[attr.aria-label]="'removeItem' | i18n: label"
|
[attr.aria-label]="'removeItem' | i18n: label"
|
||||||
[disabled]="disabled"
|
[disabled]="disabled"
|
||||||
class="tw-bg-transparent hover:tw-bg-transparent tw-outline-none tw-rounded-full tw-py-0.5 tw-px-1 tw-mr-1 tw-text-[color:inherit] tw-text-[length:inherit] tw-border-solid tw-border tw-border-transparent hover:tw-border-text-contrast hover:disabled:tw-border-transparent tw-flex tw-items-center tw-justify-center focus-visible:tw-ring-2 tw-ring-text-contrast focus-visible:hover:tw-border-transparent"
|
class="tw-bg-transparent hover:tw-bg-transparent tw-outline-none tw-rounded-full tw-py-0.5 tw-px-1 tw-mr-1 tw-text-[color:inherit] tw-text-[length:inherit] tw-border-solid tw-border tw-border-transparent hover:tw-border-text-contrast hover:disabled:tw-border-transparent tw-flex tw-items-center tw-justify-center focus-visible:tw-ring-2 tw-ring-text-contrast focus-visible:hover:tw-border-transparent"
|
||||||
[ngClass]="{
|
[ngClass]="{
|
||||||
'tw-cursor-not-allowed': disabled,
|
'tw-cursor-not-allowed': disabled,
|
||||||
}"
|
}"
|
||||||
(click)="clear()"
|
(click)="clear()"
|
||||||
>
|
>
|
||||||
<i class="bwi bwi-close tw-text-xs"></i>
|
<i class="bwi bwi-close tw-text-xs"></i>
|
||||||
</button>
|
</button>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<bit-menu #menu (closed)="handleMenuClosed()">
|
<bit-menu #menu (closed)="handleMenuClosed()">
|
||||||
<div
|
@if (renderedOptions) {
|
||||||
*ngIf="renderedOptions"
|
<div
|
||||||
class="tw-max-h-80 tw-min-w-32 tw-max-w-80 tw-text-sm"
|
class="tw-max-h-80 tw-min-w-32 tw-max-w-80 tw-text-sm"
|
||||||
[ngStyle]="menuWidth && { width: menuWidth + 'px' }"
|
[ngStyle]="menuWidth && { width: menuWidth + 'px' }"
|
||||||
>
|
|
||||||
<ng-container *ngIf="getParent(renderedOptions) as parent">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
bitMenuItem
|
|
||||||
(click)="viewOption(parent, $event)"
|
|
||||||
class="tw-text-[length:inherit]"
|
|
||||||
[title]="'backTo' | i18n: parent.label ?? placeholderText"
|
|
||||||
>
|
|
||||||
<i slot="start" class="bwi bwi-angle-left" aria-hidden="true"></i>
|
|
||||||
{{ "backTo" | i18n: parent.label ?? placeholderText }}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
bitMenuItem
|
|
||||||
(click)="selectOption(renderedOptions, $event)"
|
|
||||||
[title]="'viewItemsIn' | i18n: renderedOptions.label"
|
|
||||||
class="tw-text-[length:inherit]"
|
|
||||||
>
|
|
||||||
<i slot="start" class="bwi bwi-list" aria-hidden="true"></i>
|
|
||||||
{{ "viewItemsIn" | i18n: renderedOptions.label }}
|
|
||||||
</button>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
bitMenuItem
|
|
||||||
*ngFor="let option of renderedOptions.children"
|
|
||||||
(click)="option.children?.length ? viewOption(option, $event) : selectOption(option, $event)"
|
|
||||||
[disabled]="option.disabled"
|
|
||||||
[title]="option.label"
|
|
||||||
class="tw-text-[length:inherit]"
|
|
||||||
[attr.aria-haspopup]="option.children?.length ? 'menu' : null"
|
|
||||||
>
|
>
|
||||||
<i
|
@if (getParent(renderedOptions); as parent) {
|
||||||
*ngIf="option.icon"
|
<button
|
||||||
slot="start"
|
type="button"
|
||||||
class="bwi"
|
bitMenuItem
|
||||||
[ngClass]="option.icon"
|
(click)="viewOption(parent, $event)"
|
||||||
aria-hidden="true"
|
class="tw-text-[length:inherit]"
|
||||||
></i>
|
[title]="'backTo' | i18n: parent.label ?? placeholderText"
|
||||||
{{ option.label }}
|
>
|
||||||
<i *ngIf="option.children?.length" slot="end" class="bwi bwi-angle-right"></i>
|
<i slot="start" class="bwi bwi-angle-left" aria-hidden="true"></i>
|
||||||
</button>
|
{{ "backTo" | i18n: parent.label ?? placeholderText }}
|
||||||
</div>
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
bitMenuItem
|
||||||
|
(click)="selectOption(renderedOptions, $event)"
|
||||||
|
[title]="'viewItemsIn' | i18n: renderedOptions.label"
|
||||||
|
class="tw-text-[length:inherit]"
|
||||||
|
>
|
||||||
|
<i slot="start" class="bwi bwi-list" aria-hidden="true"></i>
|
||||||
|
{{ "viewItemsIn" | i18n: renderedOptions.label }}
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
@for (option of renderedOptions.children; track option) {
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
bitMenuItem
|
||||||
|
(click)="
|
||||||
|
option.children?.length ? viewOption(option, $event) : selectOption(option, $event)
|
||||||
|
"
|
||||||
|
[disabled]="option.disabled"
|
||||||
|
[title]="option.label"
|
||||||
|
class="tw-text-[length:inherit]"
|
||||||
|
[attr.aria-haspopup]="option.children?.length ? 'menu' : null"
|
||||||
|
>
|
||||||
|
@if (option.icon) {
|
||||||
|
<i slot="start" class="bwi" [ngClass]="option.icon" aria-hidden="true"></i>
|
||||||
|
}
|
||||||
|
{{ option.label }}
|
||||||
|
@if (option.children?.length) {
|
||||||
|
<i slot="end" class="bwi bwi-angle-right"></i>
|
||||||
|
}
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</bit-menu>
|
</bit-menu>
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ export type ChipSelectOption<T> = Option<T> & {
|
|||||||
multi: true,
|
multi: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
preserveWhitespaces: false,
|
||||||
})
|
})
|
||||||
export class ChipSelectComponent<T = unknown> implements ControlValueAccessor, AfterViewInit {
|
export class ChipSelectComponent<T = unknown> implements ControlValueAccessor, AfterViewInit {
|
||||||
@ViewChild(MenuComponent) menu: MenuComponent;
|
@ViewChild(MenuComponent) menu: MenuComponent;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { NgFor, NgIf } from "@angular/common";
|
|
||||||
import { Component, HostBinding, Input } from "@angular/core";
|
import { Component, HostBinding, Input } from "@angular/core";
|
||||||
|
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
@@ -14,18 +14,16 @@ enum CharacterType {
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "bit-color-password",
|
selector: "bit-color-password",
|
||||||
template: `<span
|
template: `@for (character of passwordArray; track character; let i = $index) {
|
||||||
*ngFor="let character of passwordArray; index as i"
|
<span [class]="getCharacterClass(character)">
|
||||||
[class]="getCharacterClass(character)"
|
<span>{{ character }}</span>
|
||||||
>
|
@if (showCount) {
|
||||||
<span>{{ character }}</span>
|
<span class="tw-whitespace-nowrap tw-text-xs tw-leading-5 tw-text-main">{{ i + 1 }}</span>
|
||||||
<span *ngIf="showCount" class="tw-whitespace-nowrap tw-text-xs tw-leading-5 tw-text-main">{{
|
}
|
||||||
i + 1
|
</span>
|
||||||
}}</span>
|
}`,
|
||||||
</span>`,
|
|
||||||
preserveWhitespaces: false,
|
preserveWhitespaces: false,
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [NgFor, NgIf],
|
|
||||||
})
|
})
|
||||||
export class ColorPasswordComponent {
|
export class ColorPasswordComponent {
|
||||||
@Input() password: string = null;
|
@Input() password: string = null;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { CommonModule } from "@angular/common";
|
|
||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -7,7 +6,6 @@ import { Component } from "@angular/core";
|
|||||||
@Component({
|
@Component({
|
||||||
selector: "bit-container",
|
selector: "bit-container",
|
||||||
templateUrl: "container.component.html",
|
templateUrl: "container.component.html",
|
||||||
imports: [CommonModule],
|
|
||||||
standalone: true,
|
standalone: true,
|
||||||
})
|
})
|
||||||
export class ContainerComponent {}
|
export class ContainerComponent {}
|
||||||
|
|||||||
@@ -13,9 +13,11 @@
|
|||||||
class="tw-text-main tw-mb-0 tw-truncate"
|
class="tw-text-main tw-mb-0 tw-truncate"
|
||||||
>
|
>
|
||||||
{{ title }}
|
{{ title }}
|
||||||
<span *ngIf="subtitle" class="tw-text-muted tw-font-normal tw-text-sm">
|
@if (subtitle) {
|
||||||
{{ subtitle }}
|
<span class="tw-text-muted tw-font-normal tw-text-sm">
|
||||||
</span>
|
{{ subtitle }}
|
||||||
|
</span>
|
||||||
|
}
|
||||||
<ng-content select="[bitDialogTitle]"></ng-content>
|
<ng-content select="[bitDialogTitle]"></ng-content>
|
||||||
</h1>
|
</h1>
|
||||||
<button
|
<button
|
||||||
@@ -35,9 +37,11 @@
|
|||||||
'tw-min-h-60': loading,
|
'tw-min-h-60': loading,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div *ngIf="loading" class="tw-absolute tw-flex tw-size-full tw-items-center tw-justify-center">
|
@if (loading) {
|
||||||
<i class="bwi bwi-spinner bwi-spin bwi-lg" [attr.aria-label]="'loading' | i18n"></i>
|
<div class="tw-absolute tw-flex tw-size-full tw-items-center tw-justify-center">
|
||||||
</div>
|
<i class="bwi bwi-spinner bwi-spin bwi-lg" [attr.aria-label]="'loading' | i18n"></i>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
<div
|
<div
|
||||||
[ngClass]="{
|
[ngClass]="{
|
||||||
'tw-p-4': !disablePadding,
|
'tw-p-4': !disablePadding,
|
||||||
|
|||||||
@@ -11,16 +11,17 @@
|
|||||||
{{ acceptButtonText }}
|
{{ acceptButtonText }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
@if (showCancelButton) {
|
||||||
*ngIf="showCancelButton"
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
bitButton
|
bitButton
|
||||||
bitFormButton
|
bitFormButton
|
||||||
buttonType="secondary"
|
buttonType="secondary"
|
||||||
(click)="dialogRef.close(false)"
|
(click)="dialogRef.close(false)"
|
||||||
>
|
>
|
||||||
{{ cancelButtonText }}
|
{{ cancelButtonText }}
|
||||||
</button>
|
</button>
|
||||||
|
}
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</bit-simple-dialog>
|
</bit-simple-dialog>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { DialogRef, DIALOG_DATA } from "@angular/cdk/dialog";
|
import { DialogRef, DIALOG_DATA } from "@angular/cdk/dialog";
|
||||||
import { NgIf } from "@angular/common";
|
|
||||||
import { Component, Inject } from "@angular/core";
|
import { Component, Inject } from "@angular/core";
|
||||||
import { FormGroup, ReactiveFormsModule } from "@angular/forms";
|
import { FormGroup, ReactiveFormsModule } from "@angular/forms";
|
||||||
|
|
||||||
@@ -39,7 +38,6 @@ const DEFAULT_COLOR: Record<SimpleDialogType, string> = {
|
|||||||
IconDirective,
|
IconDirective,
|
||||||
ButtonComponent,
|
ButtonComponent,
|
||||||
BitFormButtonDirective,
|
BitFormButtonDirective,
|
||||||
NgIf,
|
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class SimpleConfigurableDialogComponent {
|
export class SimpleConfigurableDialogComponent {
|
||||||
|
|||||||
@@ -12,23 +12,24 @@ import { DialogModule } from "../../dialog.module";
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: `
|
template: `
|
||||||
<div *ngFor="let group of dialogs">
|
@for (group of dialogs; track group) {
|
||||||
<h2>{{ group.title }}</h2>
|
<div>
|
||||||
<div class="tw-mb-4 tw-flex tw-flex-row tw-gap-2">
|
<h2>{{ group.title }}</h2>
|
||||||
<button
|
<div class="tw-mb-4 tw-flex tw-flex-row tw-gap-2">
|
||||||
type="button"
|
@for (dialog of group.dialogs; track dialog) {
|
||||||
*ngFor="let dialog of group.dialogs"
|
<button type="button" bitButton (click)="openSimpleConfigurableDialog(dialog)">
|
||||||
bitButton
|
{{ dialog.title }}
|
||||||
(click)="openSimpleConfigurableDialog(dialog)"
|
</button>
|
||||||
>
|
}
|
||||||
{{ dialog.title }}
|
</div>
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
}
|
||||||
|
|
||||||
<bit-callout *ngIf="showCallout" [type]="calloutType" title="Dialog Close Result">
|
@if (showCallout) {
|
||||||
{{ dialogCloseResult }}
|
<bit-callout [type]="calloutType" title="Dialog Close Result">
|
||||||
</bit-callout>
|
{{ dialogCloseResult }}
|
||||||
|
</bit-callout>
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
class StoryDialogComponent {
|
class StoryDialogComponent {
|
||||||
|
|||||||
@@ -3,12 +3,11 @@
|
|||||||
@fadeIn
|
@fadeIn
|
||||||
>
|
>
|
||||||
<div class="tw-flex tw-flex-col tw-items-center tw-gap-2 tw-px-4 tw-pt-4 tw-text-center">
|
<div class="tw-flex tw-flex-col tw-items-center tw-gap-2 tw-px-4 tw-pt-4 tw-text-center">
|
||||||
<ng-container *ngIf="hasIcon; else elseBlock">
|
@if (hasIcon) {
|
||||||
<ng-content select="[bitDialogIcon]"></ng-content>
|
<ng-content select="[bitDialogIcon]"></ng-content>
|
||||||
</ng-container>
|
} @else {
|
||||||
<ng-template #elseBlock>
|
|
||||||
<i class="bwi bwi-exclamation-triangle tw-text-3xl tw-text-warning" aria-hidden="true"></i>
|
<i class="bwi bwi-exclamation-triangle tw-text-3xl tw-text-warning" aria-hidden="true"></i>
|
||||||
</ng-template>
|
}
|
||||||
<h1
|
<h1
|
||||||
bitDialogTitleContainer
|
bitDialogTitleContainer
|
||||||
bitTypography="h3"
|
bitTypography="h3"
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { NgIf } from "@angular/common";
|
|
||||||
import { Component, ContentChild, Directive } from "@angular/core";
|
import { Component, ContentChild, Directive } from "@angular/core";
|
||||||
|
|
||||||
import { TypographyDirective } from "../../typography/typography.directive";
|
import { TypographyDirective } from "../../typography/typography.directive";
|
||||||
@@ -16,7 +15,7 @@ export class IconDirective {}
|
|||||||
templateUrl: "./simple-dialog.component.html",
|
templateUrl: "./simple-dialog.component.html",
|
||||||
animations: [fadeIn],
|
animations: [fadeIn],
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [NgIf, DialogTitleContainerDirective, TypographyDirective],
|
imports: [DialogTitleContainerDirective, TypographyDirective],
|
||||||
})
|
})
|
||||||
export class SimpleDialogComponent {
|
export class SimpleDialogComponent {
|
||||||
@ContentChild(IconDirective) icon!: IconDirective;
|
@ContentChild(IconDirective) icon!: IconDirective;
|
||||||
|
|||||||
@@ -9,11 +9,17 @@
|
|||||||
>
|
>
|
||||||
<span bitTypography="body2">
|
<span bitTypography="body2">
|
||||||
<ng-content select="bit-label"></ng-content>
|
<ng-content select="bit-label"></ng-content>
|
||||||
<span *ngIf="required" class="tw-text-xs tw-font-normal"> ({{ "required" | i18n }})</span>
|
@if (required) {
|
||||||
|
<span class="tw-text-xs tw-font-normal"> ({{ "required" | i18n }})</span>
|
||||||
|
}
|
||||||
</span>
|
</span>
|
||||||
<ng-content select="bit-hint" *ngIf="!hasError"></ng-content>
|
@if (!hasError) {
|
||||||
|
<ng-content select="bit-hint"></ng-content>
|
||||||
|
}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<div *ngIf="hasError" class="tw-mt-1 tw-text-danger tw-text-xs tw-ml-0.5">
|
@if (hasError) {
|
||||||
<i class="bwi bwi-error"></i> {{ displayError }}
|
<div class="tw-mt-1 tw-text-danger tw-text-xs tw-ml-0.5">
|
||||||
</div>
|
<i class="bwi bwi-error"></i> {{ displayError }}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { coerceBooleanProperty } from "@angular/cdk/coercion";
|
import { coerceBooleanProperty } from "@angular/cdk/coercion";
|
||||||
import { NgClass, NgIf } from "@angular/common";
|
import { NgClass } from "@angular/common";
|
||||||
import { Component, ContentChild, HostBinding, Input } from "@angular/core";
|
import { Component, ContentChild, HostBinding, Input } from "@angular/core";
|
||||||
|
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
@@ -15,7 +15,7 @@ import { BitFormControlAbstraction } from "./form-control.abstraction";
|
|||||||
selector: "bit-form-control",
|
selector: "bit-form-control",
|
||||||
templateUrl: "form-control.component.html",
|
templateUrl: "form-control.component.html",
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [NgClass, TypographyDirective, NgIf, I18nPipe],
|
imports: [NgClass, TypographyDirective, I18nPipe],
|
||||||
})
|
})
|
||||||
export class FormControlComponent {
|
export class FormControlComponent {
|
||||||
@Input() label: string;
|
@Input() label: string;
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
<!-- labels inside a form control (checkbox, radio button) should not truncate -->
|
<!-- labels inside a form control (checkbox, radio button) should not truncate -->
|
||||||
<span [ngClass]="{ 'tw-truncate': !isInsideFormControl }">
|
<span [ngClass]="{ 'tw-truncate': !isInsideFormControl }">
|
||||||
<ng-content></ng-content>
|
<ng-content></ng-content>
|
||||||
<ng-container *ngIf="isInsideFormControl">
|
@if (isInsideFormControl) {
|
||||||
<ng-container *ngTemplateOutlet="endSlotContent"></ng-container>
|
<ng-container *ngTemplateOutlet="endSlotContent"></ng-container>
|
||||||
</ng-container>
|
}
|
||||||
</span>
|
</span>
|
||||||
<ng-container *ngIf="!isInsideFormControl">
|
@if (!isInsideFormControl) {
|
||||||
<ng-container *ngTemplateOutlet="endSlotContent"></ng-container>
|
<ng-container *ngTemplateOutlet="endSlotContent"></ng-container>
|
||||||
</ng-container>
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { NgIf } from "@angular/common";
|
|
||||||
import { Component, Input } from "@angular/core";
|
import { Component, Input } from "@angular/core";
|
||||||
import { AbstractControl, UntypedFormGroup } from "@angular/forms";
|
import { AbstractControl, UntypedFormGroup } from "@angular/forms";
|
||||||
|
|
||||||
@@ -8,15 +8,15 @@ import { I18nPipe } from "@bitwarden/ui-common";
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "bit-error-summary",
|
selector: "bit-error-summary",
|
||||||
template: ` <ng-container *ngIf="errorCount > 0">
|
template: ` @if (errorCount > 0) {
|
||||||
<i class="bwi bwi-error"></i> {{ "fieldsNeedAttention" | i18n: errorString }}
|
<i class="bwi bwi-error"></i> {{ "fieldsNeedAttention" | i18n: errorString }}
|
||||||
</ng-container>`,
|
}`,
|
||||||
host: {
|
host: {
|
||||||
class: "tw-block tw-text-danger tw-mt-2",
|
class: "tw-block tw-text-danger tw-mt-2",
|
||||||
"aria-live": "assertive",
|
"aria-live": "assertive",
|
||||||
},
|
},
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [NgIf, I18nPipe],
|
imports: [I18nPipe],
|
||||||
})
|
})
|
||||||
export class BitErrorSummary {
|
export class BitErrorSummary {
|
||||||
@Input()
|
@Input()
|
||||||
|
|||||||
@@ -15,63 +15,65 @@
|
|||||||
<ng-content select="[bitSuffix]"></ng-content>
|
<ng-content select="[bitSuffix]"></ng-content>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<div *ngIf="!readOnly; else readOnlyView" class="tw-w-full tw-relative tw-group/bit-form-field">
|
@if (!readOnly) {
|
||||||
<div class="tw-absolute tw-size-full tw-top-0 tw-pointer-events-none tw-z-20">
|
<div class="tw-w-full tw-relative tw-group/bit-form-field">
|
||||||
<div class="tw-size-full tw-flex">
|
<div class="tw-absolute tw-size-full tw-top-0 tw-pointer-events-none tw-z-20">
|
||||||
<div
|
<div class="tw-size-full tw-flex">
|
||||||
class="tw-min-w-3 tw-border-r-0 group-focus-within/bit-form-field:tw-border-r-0 !tw-rounded-l-lg"
|
<div
|
||||||
[ngClass]="inputBorderClasses"
|
class="tw-min-w-3 tw-border-r-0 group-focus-within/bit-form-field:tw-border-r-0 !tw-rounded-l-lg"
|
||||||
></div>
|
[ngClass]="inputBorderClasses"
|
||||||
<div
|
></div>
|
||||||
class="tw-px-1 tw-shrink tw-min-w-0 tw-mt-px tw-border-x-0 tw-border-t-0 group-focus-within/bit-form-field:tw-border-x-0 group-focus-within/bit-form-field:tw-border-t-0 tw-hidden group-has-[bit-label]/bit-form-field:tw-block"
|
<div
|
||||||
[ngClass]="inputBorderClasses"
|
class="tw-px-1 tw-shrink tw-min-w-0 tw-mt-px tw-border-x-0 tw-border-t-0 group-focus-within/bit-form-field:tw-border-x-0 group-focus-within/bit-form-field:tw-border-t-0 tw-hidden group-has-[bit-label]/bit-form-field:tw-block"
|
||||||
>
|
[ngClass]="inputBorderClasses"
|
||||||
<label
|
|
||||||
class="tw-flex tw-gap-1 tw-text-sm tw-text-muted -tw-translate-y-[0.675rem] tw-mb-0 tw-max-w-full tw-pointer-events-auto"
|
|
||||||
[attr.for]="input.labelForId"
|
|
||||||
>
|
>
|
||||||
<ng-container *ngTemplateOutlet="labelContent"></ng-container>
|
<label
|
||||||
<span *ngIf="input.required" class="tw-text-[0.625rem] tw-relative tw-bottom-[-1px]">
|
class="tw-flex tw-gap-1 tw-text-sm tw-text-muted -tw-translate-y-[0.675rem] tw-mb-0 tw-max-w-full tw-pointer-events-auto"
|
||||||
({{ "required" | i18n }})</span
|
[attr.for]="input.labelForId"
|
||||||
>
|
>
|
||||||
</label>
|
<ng-container *ngTemplateOutlet="labelContent"></ng-container>
|
||||||
|
@if (input.required) {
|
||||||
|
<span class="tw-text-[0.625rem] tw-relative tw-bottom-[-1px]">
|
||||||
|
({{ "required" | i18n }})</span
|
||||||
|
>
|
||||||
|
}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="tw-min-w-3 tw-grow tw-border-l-0 group-focus-within/bit-form-field:tw-border-l-0 !tw-rounded-r-lg"
|
||||||
|
[ngClass]="inputBorderClasses"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="tw-gap-1 tw-bg-background tw-rounded-lg tw-flex tw-min-h-11 [&:not(:has(button:enabled)):has(input:read-only)]:tw-bg-secondary-100 [&:not(:has(button:enabled)):has(textarea:read-only)]:tw-bg-secondary-100"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
#prefixContainer
|
||||||
|
class="tw-flex tw-items-center tw-gap-1 tw-pl-3 tw-py-2"
|
||||||
|
[hidden]="!prefixHasChildren()"
|
||||||
|
>
|
||||||
|
<ng-container *ngTemplateOutlet="prefixContent"></ng-container>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="tw-min-w-3 tw-grow tw-border-l-0 group-focus-within/bit-form-field:tw-border-l-0 !tw-rounded-r-lg"
|
class="default-content tw-w-full tw-relative tw-py-2 has-[bit-select]:tw-p-0 has-[bit-multi-select]:tw-p-0 has-[input:read-only:not([hidden])]:tw-bg-secondary-100 has-[textarea:read-only:not([hidden])]:tw-bg-secondary-100"
|
||||||
[ngClass]="inputBorderClasses"
|
[ngClass]="[
|
||||||
></div>
|
prefixHasChildren() ? '' : 'tw-rounded-l-lg tw-pl-3',
|
||||||
|
suffixHasChildren() ? '' : 'tw-rounded-r-lg tw-pr-3',
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<ng-container *ngTemplateOutlet="defaultContent"></ng-container>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
#suffixContainer
|
||||||
|
class="tw-flex tw-items-center tw-gap-1 tw-pr-3 tw-py-2"
|
||||||
|
[hidden]="!suffixHasChildren()"
|
||||||
|
>
|
||||||
|
<ng-container *ngTemplateOutlet="suffixContent"></ng-container>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
} @else {
|
||||||
class="tw-gap-1 tw-bg-background tw-rounded-lg tw-flex tw-min-h-11 [&:not(:has(button:enabled)):has(input:read-only)]:tw-bg-secondary-100 [&:not(:has(button:enabled)):has(textarea:read-only)]:tw-bg-secondary-100"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
#prefixContainer
|
|
||||||
class="tw-flex tw-items-center tw-gap-1 tw-pl-3 tw-py-2"
|
|
||||||
[hidden]="!prefixHasChildren()"
|
|
||||||
>
|
|
||||||
<ng-container *ngTemplateOutlet="prefixContent"></ng-container>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="default-content tw-w-full tw-relative tw-py-2 has-[bit-select]:tw-p-0 has-[bit-multi-select]:tw-p-0 has-[input:read-only:not([hidden])]:tw-bg-secondary-100 has-[textarea:read-only:not([hidden])]:tw-bg-secondary-100"
|
|
||||||
[ngClass]="[
|
|
||||||
prefixHasChildren() ? '' : 'tw-rounded-l-lg tw-pl-3',
|
|
||||||
suffixHasChildren() ? '' : 'tw-rounded-r-lg tw-pr-3',
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<ng-container *ngTemplateOutlet="defaultContent"></ng-container>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
#suffixContainer
|
|
||||||
class="tw-flex tw-items-center tw-gap-1 tw-pr-3 tw-py-2"
|
|
||||||
[hidden]="!suffixHasChildren()"
|
|
||||||
>
|
|
||||||
<ng-container *ngTemplateOutlet="suffixContent"></ng-container>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ng-template #readOnlyView>
|
|
||||||
<div class="tw-w-full tw-relative">
|
<div class="tw-w-full tw-relative">
|
||||||
<label
|
<label
|
||||||
class="tw-flex tw-gap-1 tw-text-sm tw-text-muted tw-mb-0 tw-max-w-full"
|
class="tw-flex tw-gap-1 tw-text-sm tw-text-muted tw-mb-0 tw-max-w-full"
|
||||||
@@ -107,9 +109,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
}
|
||||||
|
|
||||||
<ng-container [ngSwitch]="input.hasError">
|
@switch (input.hasError) {
|
||||||
<ng-content select="bit-hint" *ngSwitchCase="false"></ng-content>
|
@case (false) {
|
||||||
<bit-error [error]="input.error" *ngSwitchCase="true"></bit-error>
|
<ng-content select="bit-hint"></ng-content>
|
||||||
</ng-container>
|
}
|
||||||
|
@case (true) {
|
||||||
|
<bit-error [error]="input.error"></bit-error>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { CommonModule } from "@angular/common";
|
|
||||||
import {
|
import {
|
||||||
AfterContentChecked,
|
AfterContentChecked,
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
@@ -16,7 +16,7 @@ import { TypographyModule } from "../typography";
|
|||||||
@Component({
|
@Component({
|
||||||
selector: "bit-item-content, [bit-item-content]",
|
selector: "bit-item-content, [bit-item-content]",
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, TypographyModule],
|
imports: [TypographyModule],
|
||||||
templateUrl: `item-content.component.html`,
|
templateUrl: `item-content.component.html`,
|
||||||
host: {
|
host: {
|
||||||
class:
|
class:
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { CommonModule } from "@angular/common";
|
|
||||||
import {
|
import {
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
Component,
|
Component,
|
||||||
@@ -14,7 +13,7 @@ import { ItemActionComponent } from "./item-action.component";
|
|||||||
@Component({
|
@Component({
|
||||||
selector: "bit-item",
|
selector: "bit-item",
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, ItemActionComponent],
|
imports: [ItemActionComponent],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
templateUrl: "item.component.html",
|
templateUrl: "item.component.html",
|
||||||
providers: [{ provide: A11yRowDirective, useExisting: ItemComponent }],
|
providers: [{ provide: A11yRowDirective, useExisting: ItemComponent }],
|
||||||
|
|||||||
@@ -23,19 +23,21 @@
|
|||||||
<ng-content></ng-content>
|
<ng-content></ng-content>
|
||||||
|
|
||||||
<!-- overlay backdrop for side-nav -->
|
<!-- overlay backdrop for side-nav -->
|
||||||
<div
|
@if (
|
||||||
*ngIf="{
|
{
|
||||||
open: sideNavService.open$ | async,
|
open: sideNavService.open$ | async,
|
||||||
} as data"
|
};
|
||||||
class="tw-pointer-events-none tw-fixed tw-inset-0 tw-z-10 tw-bg-black tw-bg-opacity-0 motion-safe:tw-transition-colors md:tw-hidden"
|
as data
|
||||||
[ngClass]="[data.open ? 'tw-bg-opacity-30 md:tw-bg-opacity-0' : 'tw-bg-opacity-0']"
|
) {
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
*ngIf="data.open"
|
class="tw-pointer-events-none tw-fixed tw-inset-0 tw-z-10 tw-bg-black tw-bg-opacity-0 motion-safe:tw-transition-colors md:tw-hidden"
|
||||||
(click)="sideNavService.toggle()"
|
[ngClass]="[data.open ? 'tw-bg-opacity-30 md:tw-bg-opacity-0' : 'tw-bg-opacity-0']"
|
||||||
class="tw-pointer-events-auto tw-size-full"
|
>
|
||||||
></div>
|
@if (data.open) {
|
||||||
</div>
|
<div (click)="sideNavService.toggle()" class="tw-pointer-events-auto tw-size-full"></div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</main>
|
</main>
|
||||||
<ng-template [cdkPortalOutlet]="drawerPortal()"></ng-template>
|
<ng-template [cdkPortalOutlet]="drawerPortal()"></ng-template>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -31,7 +31,9 @@
|
|||||||
[disabled]="disabled"
|
[disabled]="disabled"
|
||||||
(click)="clear(item)"
|
(click)="clear(item)"
|
||||||
>
|
>
|
||||||
<i *ngIf="item.icon != null" class="bwi bwi-fw {{ item.icon }}" aria-hidden="true"></i>
|
@if (item.icon != null) {
|
||||||
|
<i class="bwi bwi-fw {{ item.icon }}" aria-hidden="true"></i>
|
||||||
|
}
|
||||||
<span class="tw-truncate">
|
<span class="tw-truncate">
|
||||||
{{ item.labelName }}
|
{{ item.labelName }}
|
||||||
</span>
|
</span>
|
||||||
@@ -41,10 +43,14 @@
|
|||||||
<ng-template ng-option-tmp let-item="item">
|
<ng-template ng-option-tmp let-item="item">
|
||||||
<div class="tw-flex">
|
<div class="tw-flex">
|
||||||
<div class="tw-w-7 tw-flex-none">
|
<div class="tw-w-7 tw-flex-none">
|
||||||
<i *ngIf="isSelected(item)" class="bwi bwi-fw bwi-check" aria-hidden="true"></i>
|
@if (isSelected(item)) {
|
||||||
|
<i class="bwi bwi-fw bwi-check" aria-hidden="true"></i>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="tw-mr-2 tw-flex-initial">
|
<div class="tw-mr-2 tw-flex-initial">
|
||||||
<i *ngIf="item.icon != null" class="bwi bwi-fw {{ item.icon }}" aria-hidden="true"></i>
|
@if (item.icon != null) {
|
||||||
|
<i class="bwi bwi-fw {{ item.icon }}" aria-hidden="true"></i>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="tw-flex-1">
|
<div class="tw-flex-1">
|
||||||
{{ item.listName }}
|
{{ item.listName }}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { coerceBooleanProperty } from "@angular/cdk/coercion";
|
import { coerceBooleanProperty } from "@angular/cdk/coercion";
|
||||||
import { hasModifierKey } from "@angular/cdk/keycodes";
|
import { hasModifierKey } from "@angular/cdk/keycodes";
|
||||||
import { NgIf } from "@angular/common";
|
|
||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
Input,
|
Input,
|
||||||
@@ -39,7 +38,7 @@ let nextId = 0;
|
|||||||
templateUrl: "./multi-select.component.html",
|
templateUrl: "./multi-select.component.html",
|
||||||
providers: [{ provide: BitFormFieldControl, useExisting: MultiSelectComponent }],
|
providers: [{ provide: BitFormFieldControl, useExisting: MultiSelectComponent }],
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [NgSelectModule, ReactiveFormsModule, FormsModule, BadgeModule, NgIf, I18nPipe],
|
imports: [NgSelectModule, ReactiveFormsModule, FormsModule, BadgeModule, I18nPipe],
|
||||||
})
|
})
|
||||||
/**
|
/**
|
||||||
* This component has been implemented to only support Multi-select list events
|
* This component has been implemented to only support Multi-select list events
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
<div *ngIf="sideNavService.open$ | async" class="tw-h-px tw-w-full tw-bg-secondary-300"></div>
|
@if (sideNavService.open$ | async) {
|
||||||
|
<div class="tw-h-px tw-w-full tw-bg-secondary-300"></div>
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- This a higher order component that composes `NavItemComponent` -->
|
<!-- This a higher order component that composes `NavItemComponent` -->
|
||||||
<ng-container *ngIf="!hideIfEmpty || nestedNavComponents.length > 0">
|
@if (!hideIfEmpty || nestedNavComponents.length > 0) {
|
||||||
<bit-nav-item
|
<bit-nav-item
|
||||||
[text]="text"
|
[text]="text"
|
||||||
[icon]="icon"
|
[icon]="icon"
|
||||||
@@ -29,28 +29,29 @@
|
|||||||
[attr.aria-label]="['toggleCollapse' | i18n, text].join(' ')"
|
[attr.aria-label]="['toggleCollapse' | i18n, text].join(' ')"
|
||||||
></button>
|
></button>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<!-- Show toggle to the left for trees otherwise to the right -->
|
<!-- Show toggle to the left for trees otherwise to the right -->
|
||||||
<ng-container slot="start" *ngIf="variant === 'tree'">
|
@if (variant === "tree") {
|
||||||
<ng-container *ngTemplateOutlet="button"></ng-container>
|
<ng-container slot="start">
|
||||||
</ng-container>
|
|
||||||
<ng-container slot="end">
|
|
||||||
<ng-content select="[slot=end]"></ng-content>
|
|
||||||
<ng-container *ngIf="variant !== 'tree'">
|
|
||||||
<ng-container *ngTemplateOutlet="button"></ng-container>
|
<ng-container *ngTemplateOutlet="button"></ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
}
|
||||||
|
<ng-container slot="end">
|
||||||
|
<ng-content select="[slot=end]"></ng-content>
|
||||||
|
@if (variant !== "tree") {
|
||||||
|
<ng-container *ngTemplateOutlet="button"></ng-container>
|
||||||
|
}
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</bit-nav-item>
|
</bit-nav-item>
|
||||||
|
|
||||||
<!-- [attr.aria-controls] of the above button expects a unique ID on the controlled element -->
|
<!-- [attr.aria-controls] of the above button expects a unique ID on the controlled element -->
|
||||||
<ng-container *ngIf="sideNavService.open$ | async">
|
@if (sideNavService.open$ | async) {
|
||||||
<div
|
@if (open) {
|
||||||
*ngIf="open"
|
<div
|
||||||
[attr.id]="contentId"
|
[attr.id]="contentId"
|
||||||
[attr.aria-label]="[text, 'submenu' | i18n].join(' ')"
|
[attr.aria-label]="[text, 'submenu' | i18n].join(' ')"
|
||||||
role="group"
|
role="group"
|
||||||
>
|
>
|
||||||
<ng-content></ng-content>
|
<ng-content></ng-content>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
}
|
||||||
</ng-container>
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import { SideNavService } from "./side-nav.service";
|
|||||||
],
|
],
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, NavItemComponent, IconButtonModule, I18nPipe],
|
imports: [CommonModule, NavItemComponent, IconButtonModule, I18nPipe],
|
||||||
|
preserveWhitespaces: false,
|
||||||
})
|
})
|
||||||
export class NavGroupComponent extends NavBaseComponent implements AfterContentInit {
|
export class NavGroupComponent extends NavBaseComponent implements AfterContentInit {
|
||||||
@ContentChildren(NavBaseComponent, {
|
@ContentChildren(NavBaseComponent, {
|
||||||
|
|||||||
@@ -1,20 +1,23 @@
|
|||||||
<div *ngIf="sideNavService.open" class="tw-sticky tw-top-0 tw-z-50">
|
@if (sideNavService.open) {
|
||||||
<a
|
<div class="tw-sticky tw-top-0 tw-z-50">
|
||||||
[routerLink]="route"
|
<a
|
||||||
class="tw-px-5 tw-pb-5 tw-pt-7 tw-block tw-bg-background-alt3 tw-outline-none focus-visible:tw-ring focus-visible:tw-ring-inset focus-visible:tw-ring-text-alt2"
|
[routerLink]="route"
|
||||||
[attr.aria-label]="label"
|
class="tw-px-5 tw-pb-5 tw-pt-7 tw-block tw-bg-background-alt3 tw-outline-none focus-visible:tw-ring focus-visible:tw-ring-inset focus-visible:tw-ring-text-alt2"
|
||||||
[title]="label"
|
[attr.aria-label]="label"
|
||||||
routerLinkActive
|
[title]="label"
|
||||||
[ariaCurrentWhenActive]="'page'"
|
routerLinkActive
|
||||||
>
|
[ariaCurrentWhenActive]="'page'"
|
||||||
<bit-icon [icon]="openIcon"></bit-icon>
|
>
|
||||||
</a>
|
<bit-icon [icon]="openIcon"></bit-icon>
|
||||||
</div>
|
</a>
|
||||||
<bit-nav-item
|
</div>
|
||||||
class="tw-block tw-pt-7"
|
}
|
||||||
[hideActiveStyles]="true"
|
@if (!sideNavService.open) {
|
||||||
[route]="route"
|
<bit-nav-item
|
||||||
[icon]="closedIcon"
|
class="tw-block tw-pt-7"
|
||||||
*ngIf="!sideNavService.open"
|
[hideActiveStyles]="true"
|
||||||
[text]="label"
|
[route]="route"
|
||||||
></bit-nav-item>
|
[icon]="closedIcon"
|
||||||
|
[text]="label"
|
||||||
|
></bit-nav-item>
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { NgIf } from "@angular/common";
|
|
||||||
import { Component, Input } from "@angular/core";
|
import { Component, Input } from "@angular/core";
|
||||||
import { RouterLinkActive, RouterLink } from "@angular/router";
|
import { RouterLinkActive, RouterLink } from "@angular/router";
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ import { SideNavService } from "./side-nav.service";
|
|||||||
selector: "bit-nav-logo",
|
selector: "bit-nav-logo",
|
||||||
templateUrl: "./nav-logo.component.html",
|
templateUrl: "./nav-logo.component.html",
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [NgIf, RouterLinkActive, RouterLink, BitIconComponent, NavItemComponent],
|
imports: [RouterLinkActive, RouterLink, BitIconComponent, NavItemComponent],
|
||||||
})
|
})
|
||||||
export class NavLogoComponent {
|
export class NavLogoComponent {
|
||||||
/** Icon that is displayed when the side nav is closed */
|
/** Icon that is displayed when the side nav is closed */
|
||||||
|
|||||||
@@ -1,42 +1,46 @@
|
|||||||
<nav
|
@if (
|
||||||
*ngIf="{
|
{
|
||||||
open: sideNavService.open$ | async,
|
open: sideNavService.open$ | async,
|
||||||
isOverlay: sideNavService.isOverlay$ | async,
|
isOverlay: sideNavService.isOverlay$ | async,
|
||||||
} as data"
|
};
|
||||||
id="bit-side-nav"
|
as data
|
||||||
class="tw-fixed md:tw-sticky tw-inset-y-0 tw-left-0 tw-z-30 tw-flex tw-h-screen tw-flex-col tw-overscroll-none tw-overflow-auto tw-bg-background-alt3 tw-outline-none"
|
) {
|
||||||
[ngClass]="{ 'tw-w-60': data.open }"
|
<nav
|
||||||
[ngStyle]="
|
id="bit-side-nav"
|
||||||
variant === 'secondary' && {
|
class="tw-fixed md:tw-sticky tw-inset-y-0 tw-left-0 tw-z-30 tw-flex tw-h-screen tw-flex-col tw-overscroll-none tw-overflow-auto tw-bg-background-alt3 tw-outline-none"
|
||||||
'--color-text-alt2': 'var(--color-text-main)',
|
[ngClass]="{ 'tw-w-60': data.open }"
|
||||||
'--color-background-alt3': 'var(--color-secondary-100)',
|
[ngStyle]="
|
||||||
'--color-background-alt4': 'var(--color-secondary-300)',
|
variant === 'secondary' && {
|
||||||
}
|
'--color-text-alt2': 'var(--color-text-main)',
|
||||||
"
|
'--color-background-alt3': 'var(--color-secondary-100)',
|
||||||
[cdkTrapFocus]="data.isOverlay"
|
'--color-background-alt4': 'var(--color-secondary-300)',
|
||||||
[attr.role]="data.isOverlay ? 'dialog' : null"
|
}
|
||||||
[attr.aria-modal]="data.isOverlay ? 'true' : null"
|
"
|
||||||
(keydown)="handleKeyDown($event)"
|
[cdkTrapFocus]="data.isOverlay"
|
||||||
>
|
[attr.role]="data.isOverlay ? 'dialog' : null"
|
||||||
<ng-content></ng-content>
|
[attr.aria-modal]="data.isOverlay ? 'true' : null"
|
||||||
<div class="tw-sticky tw-bottom-0 tw-left-0 tw-z-20 tw-mt-auto tw-w-full tw-bg-background-alt3">
|
(keydown)="handleKeyDown($event)"
|
||||||
<bit-nav-divider></bit-nav-divider>
|
>
|
||||||
<ng-container *ngIf="data.open">
|
<ng-content></ng-content>
|
||||||
<ng-content select="[slot=footer]"></ng-content>
|
<div class="tw-sticky tw-bottom-0 tw-left-0 tw-z-20 tw-mt-auto tw-w-full tw-bg-background-alt3">
|
||||||
</ng-container>
|
<bit-nav-divider></bit-nav-divider>
|
||||||
<div class="tw-mx-0.5 tw-my-4 tw-w-[3.75rem]">
|
@if (data.open) {
|
||||||
<button
|
<ng-content select="[slot=footer]"></ng-content>
|
||||||
#toggleButton
|
}
|
||||||
type="button"
|
<div class="tw-mx-0.5 tw-my-4 tw-w-[3.75rem]">
|
||||||
class="tw-mx-auto tw-block tw-max-w-fit"
|
<button
|
||||||
[bitIconButton]="data.open ? 'bwi-angle-left' : 'bwi-angle-right'"
|
#toggleButton
|
||||||
buttonType="light"
|
type="button"
|
||||||
size="small"
|
class="tw-mx-auto tw-block tw-max-w-fit"
|
||||||
(click)="sideNavService.toggle()"
|
[bitIconButton]="data.open ? 'bwi-angle-left' : 'bwi-angle-right'"
|
||||||
[attr.aria-label]="'toggleSideNavigation' | i18n"
|
buttonType="light"
|
||||||
[attr.aria-expanded]="data.open"
|
size="small"
|
||||||
aria-controls="bit-side-nav"
|
(click)="sideNavService.toggle()"
|
||||||
></button>
|
[attr.aria-label]="'toggleSideNavigation' | i18n"
|
||||||
|
[attr.aria-expanded]="data.open"
|
||||||
|
aria-controls="bit-side-nav"
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</nav>
|
||||||
</nav>
|
}
|
||||||
|
|||||||
@@ -7,13 +7,12 @@
|
|||||||
attr.aria-valuenow="{{ barWidth }}"
|
attr.aria-valuenow="{{ barWidth }}"
|
||||||
[ngStyle]="{ width: barWidth + '%' }"
|
[ngStyle]="{ width: barWidth + '%' }"
|
||||||
>
|
>
|
||||||
<div
|
@if (displayText) {
|
||||||
*ngIf="displayText"
|
<div class="tw-flex tw-h-full tw-flex-wrap tw-items-center tw-overflow-hidden">
|
||||||
class="tw-flex tw-h-full tw-flex-wrap tw-items-center tw-overflow-hidden"
|
<!-- If text is too long to fit, wrap it below to hide -->
|
||||||
>
|
<div class="tw-h-full"> </div>
|
||||||
<!-- If text is too long to fit, wrap it below to hide -->
|
<div class="tw-pr-1">{{ textContent }}</div>
|
||||||
<div class="tw-h-full"> </div>
|
</div>
|
||||||
<div class="tw-pr-1">{{ textContent }}</div>
|
}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
<ng-container *ngIf="label">
|
@if (label) {
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend class="tw-mb-1 tw-block tw-text-sm tw-font-semibold tw-text-main">
|
<legend class="tw-mb-1 tw-block tw-text-sm tw-font-semibold tw-text-main">
|
||||||
<ng-content select="bit-label"></ng-content>
|
<ng-content select="bit-label"></ng-content>
|
||||||
<span *ngIf="required" class="tw-text-xs tw-font-normal"> ({{ "required" | i18n }})</span>
|
@if (required) {
|
||||||
|
<span class="tw-text-xs tw-font-normal"> ({{ "required" | i18n }})</span>
|
||||||
|
}
|
||||||
</legend>
|
</legend>
|
||||||
<ng-container *ngTemplateOutlet="content"></ng-container>
|
<ng-container *ngTemplateOutlet="content"></ng-container>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</ng-container>
|
}
|
||||||
|
|
||||||
<ng-container *ngIf="!label">
|
@if (!label) {
|
||||||
<ng-container *ngTemplateOutlet="content"></ng-container>
|
<ng-container *ngTemplateOutlet="content"></ng-container>
|
||||||
</ng-container>
|
}
|
||||||
|
|
||||||
<ng-template #content>
|
<ng-template #content>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { NgIf, NgTemplateOutlet } from "@angular/common";
|
import { NgTemplateOutlet } from "@angular/common";
|
||||||
import { Component, ContentChild, HostBinding, Input, Optional, Self } from "@angular/core";
|
import { Component, ContentChild, HostBinding, Input, Optional, Self } from "@angular/core";
|
||||||
import { ControlValueAccessor, NgControl, Validators } from "@angular/forms";
|
import { ControlValueAccessor, NgControl, Validators } from "@angular/forms";
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ let nextId = 0;
|
|||||||
selector: "bit-radio-group",
|
selector: "bit-radio-group",
|
||||||
templateUrl: "radio-group.component.html",
|
templateUrl: "radio-group.component.html",
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [NgIf, NgTemplateOutlet, I18nPipe],
|
imports: [NgTemplateOutlet, I18nPipe],
|
||||||
})
|
})
|
||||||
export class RadioGroupComponent implements ControlValueAccessor {
|
export class RadioGroupComponent implements ControlValueAccessor {
|
||||||
selected: unknown;
|
selected: unknown;
|
||||||
|
|||||||
@@ -13,7 +13,9 @@
|
|||||||
<ng-template ng-option-tmp let-item="item">
|
<ng-template ng-option-tmp let-item="item">
|
||||||
<div class="tw-flex" [title]="item.label">
|
<div class="tw-flex" [title]="item.label">
|
||||||
<div class="tw-mr-2 tw-flex-initial">
|
<div class="tw-mr-2 tw-flex-initial">
|
||||||
<i *ngIf="item.icon != null" class="bwi bwi-fw {{ item.icon }}" aria-hidden="true"></i>
|
@if (item.icon != null) {
|
||||||
|
<i class="bwi bwi-fw {{ item.icon }}" aria-hidden="true"></i>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="tw-flex-1 tw-text-ellipsis tw-overflow-hidden">
|
<div class="tw-flex-1 tw-text-ellipsis tw-overflow-hidden">
|
||||||
{{ item.label }}
|
{{ item.label }}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { NgIf } from "@angular/common";
|
|
||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
ContentChildren,
|
ContentChildren,
|
||||||
@@ -36,7 +36,7 @@ let nextId = 0;
|
|||||||
templateUrl: "select.component.html",
|
templateUrl: "select.component.html",
|
||||||
providers: [{ provide: BitFormFieldControl, useExisting: SelectComponent }],
|
providers: [{ provide: BitFormFieldControl, useExisting: SelectComponent }],
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [NgSelectModule, ReactiveFormsModule, FormsModule, NgIf],
|
imports: [NgSelectModule, ReactiveFormsModule, FormsModule],
|
||||||
})
|
})
|
||||||
export class SelectComponent<T> implements BitFormFieldControl, ControlValueAccessor {
|
export class SelectComponent<T> implements BitFormFieldControl, ControlValueAccessor {
|
||||||
@ViewChild(NgSelectComponent) select: NgSelectComponent;
|
@ViewChild(NgSelectComponent) select: NgSelectComponent;
|
||||||
|
|||||||
@@ -49,11 +49,9 @@ import { KitchenSinkSharedModule } from "../kitchen-sink-shared.module";
|
|||||||
<bit-form-field>
|
<bit-form-field>
|
||||||
<bit-label>Your favorite color</bit-label>
|
<bit-label>Your favorite color</bit-label>
|
||||||
<bit-select formControlName="favColor">
|
<bit-select formControlName="favColor">
|
||||||
<bit-option
|
@for (color of colors; track color) {
|
||||||
*ngFor="let color of colors"
|
<bit-option [value]="color.value" [label]="color.name"></bit-option>
|
||||||
[value]="color.value"
|
}
|
||||||
[label]="color.name"
|
|
||||||
></bit-option>
|
|
||||||
</bit-select>
|
</bit-select>
|
||||||
</bit-form-field>
|
</bit-form-field>
|
||||||
|
|
||||||
|
|||||||
@@ -36,9 +36,11 @@ class KitchenSinkDialog {
|
|||||||
|
|
||||||
<p class="tw-mt-4">
|
<p class="tw-mt-4">
|
||||||
<bit-breadcrumbs>
|
<bit-breadcrumbs>
|
||||||
<bit-breadcrumb *ngFor="let item of navItems" [icon]="item.icon" [route]="[item.route]">
|
@for (item of navItems; track item) {
|
||||||
{{ item.name }}
|
<bit-breadcrumb [icon]="item.icon" [route]="[item.route]">
|
||||||
</bit-breadcrumb>
|
{{ item.name }}
|
||||||
|
</bit-breadcrumb>
|
||||||
|
}
|
||||||
</bit-breadcrumbs>
|
</bit-breadcrumbs>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|||||||
@@ -16,11 +16,15 @@ import { KitchenSinkSharedModule } from "../kitchen-sink-shared.module";
|
|||||||
<bit-toggle value="small"> Mid-sized <span bitBadge variant="info">1</span> </bit-toggle>
|
<bit-toggle value="small"> Mid-sized <span bitBadge variant="info">1</span> </bit-toggle>
|
||||||
</bit-toggle-group>
|
</bit-toggle-group>
|
||||||
</div>
|
</div>
|
||||||
<ul *ngFor="let company of companyList">
|
@for (company of companyList; track company) {
|
||||||
<li *ngIf="company.size === selectedToggle || selectedToggle === 'all'">
|
<ul>
|
||||||
{{ company.name }}
|
@if (company.size === selectedToggle || selectedToggle === "all") {
|
||||||
</li>
|
<li>
|
||||||
</ul>
|
{{ company.name }}
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
export class KitchenSinkToggleList {
|
export class KitchenSinkToggleList {
|
||||||
|
|||||||
@@ -5,40 +5,41 @@
|
|||||||
[attr.aria-label]="label"
|
[attr.aria-label]="label"
|
||||||
(keydown)="keyManager.onKeydown($event)"
|
(keydown)="keyManager.onKeydown($event)"
|
||||||
>
|
>
|
||||||
<button
|
@for (tab of tabs; track tab; let i = $index) {
|
||||||
bitTabListItem
|
<button
|
||||||
*ngFor="let tab of tabs; let i = index"
|
bitTabListItem
|
||||||
type="button"
|
type="button"
|
||||||
role="tab"
|
role="tab"
|
||||||
[id]="getTabLabelId(i)"
|
[id]="getTabLabelId(i)"
|
||||||
[active]="tab.isActive"
|
[active]="tab.isActive"
|
||||||
[disabled]="tab.disabled"
|
[disabled]="tab.disabled"
|
||||||
[attr.aria-selected]="selectedIndex === i"
|
[attr.aria-selected]="selectedIndex === i"
|
||||||
[attr.tabindex]="selectedIndex === i ? 0 : -1"
|
[attr.tabindex]="selectedIndex === i ? 0 : -1"
|
||||||
(click)="selectTab(i)"
|
(click)="selectTab(i)"
|
||||||
>
|
>
|
||||||
<ng-container [ngTemplateOutlet]="content"></ng-container>
|
<ng-container [ngTemplateOutlet]="content"></ng-container>
|
||||||
|
<ng-template #content>
|
||||||
<ng-template #content>
|
@if (tab.templateLabel) {
|
||||||
<ng-template [ngIf]="tab.templateLabel" [ngIfElse]="tabTextLabel">
|
<ng-container [ngTemplateOutlet]="tab.templateLabel.templateRef"></ng-container>
|
||||||
<ng-container [ngTemplateOutlet]="tab.templateLabel.templateRef"></ng-container>
|
} @else {
|
||||||
|
{{ tab.textLabel }}
|
||||||
|
}
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
</button>
|
||||||
<ng-template #tabTextLabel>{{ tab.textLabel }}</ng-template>
|
}
|
||||||
</ng-template>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</bit-tab-header>
|
</bit-tab-header>
|
||||||
<div class="tw-px-4 tw-pt-5">
|
<div class="tw-px-4 tw-pt-5">
|
||||||
<bit-tab-body
|
@for (tab of tabs; track tab; let i = $index) {
|
||||||
role="tabpanel"
|
<bit-tab-body
|
||||||
*ngFor="let tab of tabs; let i = index"
|
role="tabpanel"
|
||||||
[id]="getTabContentId(i)"
|
[id]="getTabContentId(i)"
|
||||||
[attr.tabindex]="tab.contentTabIndex"
|
[attr.tabindex]="tab.contentTabIndex"
|
||||||
[attr.labeledby]="getTabLabelId(i)"
|
[attr.labeledby]="getTabLabelId(i)"
|
||||||
[active]="tab.isActive"
|
[active]="tab.isActive"
|
||||||
[content]="tab.content"
|
[content]="tab.content"
|
||||||
[preserveContent]="preserveContent"
|
[preserveContent]="preserveContent"
|
||||||
>
|
>
|
||||||
</bit-tab-body>
|
</bit-tab-body>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { FocusKeyManager } from "@angular/cdk/a11y";
|
import { FocusKeyManager } from "@angular/cdk/a11y";
|
||||||
import { coerceNumberProperty } from "@angular/cdk/coercion";
|
import { coerceNumberProperty } from "@angular/cdk/coercion";
|
||||||
import { CommonModule } from "@angular/common";
|
import { NgTemplateOutlet } from "@angular/common";
|
||||||
import {
|
import {
|
||||||
AfterContentChecked,
|
AfterContentChecked,
|
||||||
AfterContentInit,
|
AfterContentInit,
|
||||||
@@ -33,7 +33,7 @@ let nextId = 0;
|
|||||||
templateUrl: "./tab-group.component.html",
|
templateUrl: "./tab-group.component.html",
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
NgTemplateOutlet,
|
||||||
TabHeaderComponent,
|
TabHeaderComponent,
|
||||||
TabListContainerDirective,
|
TabListContainerDirective,
|
||||||
TabListItemDirective,
|
TabListItemDirective,
|
||||||
|
|||||||
@@ -7,15 +7,14 @@
|
|||||||
<i aria-hidden="true" class="bwi tw-text-xl tw-py-1.5 tw-px-2.5 {{ iconClass }}"></i>
|
<i aria-hidden="true" class="bwi tw-text-xl tw-py-1.5 tw-px-2.5 {{ iconClass }}"></i>
|
||||||
<div>
|
<div>
|
||||||
<span class="tw-sr-only">{{ variant | i18n }}</span>
|
<span class="tw-sr-only">{{ variant | i18n }}</span>
|
||||||
<p *ngIf="title" data-testid="toast-title" class="tw-font-semibold tw-mb-0">{{ title }}</p>
|
@if (title) {
|
||||||
<p
|
<p data-testid="toast-title" class="tw-font-semibold tw-mb-0">{{ title }}</p>
|
||||||
bitTypography="body2"
|
}
|
||||||
*ngFor="let m of messageArray"
|
@for (m of messageArray; track m) {
|
||||||
data-testid="toast-message"
|
<p bitTypography="body2" data-testid="toast-message" class="tw-mb-2 last:tw-mb-0">
|
||||||
class="tw-mb-2 last:tw-mb-0"
|
{{ m }}
|
||||||
>
|
</p>
|
||||||
{{ m }}
|
}
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- Overriding hover and focus-visible colors for a11y against colored background -->
|
<!-- Overriding hover and focus-visible colors for a11y against colored background -->
|
||||||
<button
|
<button
|
||||||
|
|||||||
Reference in New Issue
Block a user