Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api-goldens/element-ng/application-header/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { NavigationExtras } from '@angular/router';
import { OnChanges } from '@angular/core';
import { OnDestroy } from '@angular/core';
import { OnInit } from '@angular/core';
import * as rxjs from 'rxjs';
import * as _siemens_element_ng_application_header from '@siemens/element-ng/application-header';
import * as _siemens_element_translate_ng_translate from '@siemens/element-translate-ng/translate';
import { SiHeaderDropdownTriggerDirective } from '@siemens/element-ng/header-dropdown';
Expand Down Expand Up @@ -78,6 +77,7 @@ export class SiAccountDetailsComponent {

// @public
export class SiApplicationHeaderComponent implements HeaderWithDropdowns, OnDestroy {
constructor();
readonly expandBreakpoint: _angular_core.InputSignal<"sm" | "md" | "lg" | "xl" | "xxl" | "never">;
// (undocumented)
readonly launchpad: _angular_core.InputSignal<TemplateRef<void> | undefined>;
Expand Down
3 changes: 2 additions & 1 deletion api-goldens/element-ng/header-dropdown/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import * as _angular_core from '@angular/core';
import { ConnectedPosition } from '@angular/cdk/overlay';
import { InjectionToken } from '@angular/core';
import { MenuItem } from '@siemens/element-ng/common';
import { Observable } from 'rxjs';
import { OnChanges } from '@angular/core';
import { OnDestroy } from '@angular/core';
import { OnInit } from '@angular/core';
import * as _siemens_element_ng_header_dropdown from '@siemens/element-ng/header-dropdown';
import { Signal } from '@angular/core';
import { TemplateRef } from '@angular/core';

// @public
Expand All @@ -31,6 +31,7 @@ export class SiHeaderDropdownItemComponent {

// @public
export class SiHeaderDropdownTriggerDirective implements OnChanges, OnInit, OnDestroy {
constructor();
close(options?: {
all?: boolean;
}): void;
Expand Down
1 change: 0 additions & 1 deletion api-goldens/element-ng/navbar/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { MenuItem } from '@siemens/element-ng/common';
import { OnChanges } from '@angular/core';
import { OnDestroy } from '@angular/core';
import { OnInit } from '@angular/core';
import * as rxjs from 'rxjs';
import { SiApplicationHeaderComponent } from '@siemens/element-ng/application-header';
import * as _siemens_element_translate_ng_translate from '@siemens/element-translate-ng/translate';
import { SiHeaderCollapsibleActionsComponent } from '@siemens/element-ng/application-header';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ import { NgTemplateOutlet } from '@angular/common';
import {
ChangeDetectionStrategy,
Component,
effect,
ElementRef,
inject,
Injector,
input,
OnDestroy,
signal,
TemplateRef,
untracked,
viewChild
} from '@angular/core';
Comment thread
spike-rabbit marked this conversation as resolved.
import { toObservable, toSignal } from '@angular/core/rxjs-interop';
import { elementMenu, elementThumbnails } from '@siemens/element-icons';
import {
HeaderWithDropdowns,
Expand All @@ -26,8 +29,8 @@ import {
import { addIcons, SiIconComponent } from '@siemens/element-ng/icon';
import { BOOTSTRAP_BREAKPOINTS, Breakpoints } from '@siemens/element-ng/resize-observer';
import { SiTranslatePipe, t } from '@siemens/element-translate-ng/translate';
import { defer, of, Subject } from 'rxjs';
import { map, skip, takeUntil } from 'rxjs/operators';
import { of, Subject } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
Comment thread
spike-rabbit marked this conversation as resolved.

/** Root component for the application header. */
@Component({
Expand Down Expand Up @@ -83,20 +86,30 @@ export class SiApplicationHeaderComponent implements HeaderWithDropdowns, OnDest
});

/** @internal */
// defer is required to re-check the current breakpoint as it may change.
readonly inlineDropdown = defer(() => {
const expandBreakpoint = this.expandBreakpoint();
if (expandBreakpoint === 'never') {
return of(true);
}
return this.breakpointObserver
.observe(
`(min-width: ${
BOOTSTRAP_BREAKPOINTS[(expandBreakpoint + 'Minimum') as keyof Breakpoints]
}px)`
)
.pipe(map(({ matches }) => !matches));
});
readonly inlineDropdown = toSignal(
toObservable(this.expandBreakpoint).pipe(
switchMap(expandBreakpoint => {
if (expandBreakpoint === 'never') {
return of(true);
}
return this.breakpointObserver
.observe(
`(min-width: ${
BOOTSTRAP_BREAKPOINTS[(expandBreakpoint + 'Minimum') as keyof Breakpoints]
}px)`
)
.pipe(map(({ matches }) => !matches));
})
),
{ initialValue: false }
);

constructor() {
effect(() => {
this.inlineDropdown();
untracked(() => this.closeMobileMenus.next());
});
}
Comment thread
spike-rabbit marked this conversation as resolved.

ngOnDestroy(): void {
this.closeMobileSub.unsubscribe();
Expand Down Expand Up @@ -177,9 +190,6 @@ export class SiApplicationHeaderComponent implements HeaderWithDropdowns, OnDest
this.closeMobileMenus.next();
this.mobileNavigationExpanded.set(true);
this.dropdownOpened();
this.inlineDropdown
.pipe(skip(1), takeUntil(this.closeMobileMenus))
.subscribe(() => this.closeMobileMenus.next());
this.focusTrap().focusTrap.focusFirstTabbableElementWhenReady();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ import { elementOptionsVertical } from '@siemens/element-icons';
import { SI_HEADER_DROPDOWN_OPTIONS } from '@siemens/element-ng/header-dropdown';
import { addIcons, SiIconComponent } from '@siemens/element-ng/icon';
import { SiTranslatePipe, t } from '@siemens/element-translate-ng/translate';
import { Subscription } from 'rxjs';
import { skip, takeUntil } from 'rxjs/operators';

import { SiApplicationHeaderComponent } from './si-application-header.component';
Comment thread
spike-rabbit marked this conversation as resolved.

Expand Down Expand Up @@ -61,11 +59,9 @@ export class SiHeaderCollapsibleActionsComponent implements OnDestroy {
private readonly focusTrap = viewChild.required(CdkTrapFocus);
private header = inject(SiApplicationHeaderComponent);
private closeMobileSub = this.header.closeMobileMenus.subscribe(() => this.closeMobile());
private inlineChangeSubscription?: Subscription;

ngOnDestroy(): void {
this.closeMobileSub.unsubscribe();
this.inlineChangeSubscription?.unsubscribe();
}

protected toggleMobileExpanded(): void {
Expand All @@ -86,9 +82,6 @@ export class SiHeaderCollapsibleActionsComponent implements OnDestroy {
this.header.closeMobileMenus.next();
this.header.dropdownOpened();
this.mobileExpanded.set(true);
this.inlineChangeSubscription = this.header.inlineDropdown
.pipe(skip(1), takeUntil(this.header.closeMobileMenus))
.subscribe(() => this.header.closeMobileMenus.next());
this.focusTrap().focusTrap.focusFirstTabbableElementWhenReady();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
Component,
ComponentRef,
Directive,
effect,
ElementRef,
EmbeddedViewRef,
inject,
Comment thread
spike-rabbit marked this conversation as resolved.
Expand All @@ -18,10 +19,11 @@ import {
OnInit,
output,
TemplateRef,
untracked,
ViewContainerRef
} from '@angular/core';
Comment thread
spike-rabbit marked this conversation as resolved.
import { of, Subject } from 'rxjs';
import { filter, skip, take, takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs';
import { filter, take, takeUntil } from 'rxjs/operators';
Comment thread
spike-rabbit marked this conversation as resolved.

import { SI_HEADER_WITH_DROPDOWNS } from './si-header.model';

Expand Down Expand Up @@ -96,6 +98,17 @@ export class SiHeaderDropdownTriggerDirective implements OnChanges, OnInit, OnDe

private headerAnchorComponentRef?: ComponentRef<SiHeaderAnchorComponent>;

constructor() {
effect(() => {
const inline = this.navbar?.inlineDropdown() ?? false;
untracked(() => {
if (this._isOpen && inline === this.isOverlay) {
this.close();
}
});
});
}
Comment thread
spike-rabbit marked this conversation as resolved.

/** Whether the dropdown is open. */
get isOpen(): boolean {
return this._isOpen;
Expand Down Expand Up @@ -129,15 +142,10 @@ export class SiHeaderDropdownTriggerDirective implements OnChanges, OnInit, OnDe
return;
}

(this.navbar?.inlineDropdown ?? of(false)).pipe(take(1)).subscribe(inline => {
this._isOpen = true;
if (!inline) {
this.attachDropdownOverlay();
}
this.navbar?.inlineDropdown
?.pipe(skip(1), takeUntil(this.dropdownClose))
.subscribe(() => this.close());
});
this._isOpen = true;
if (!(this.navbar?.inlineDropdown() ?? false)) {
this.attachDropdownOverlay();
}
Comment thread
spike-rabbit marked this conversation as resolved.

if (this.parent) {
this.parent.openSubmenu = this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
*/
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { Component, viewChild } from '@angular/core';
import { Component, signal, viewChild } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BehaviorSubject } from 'rxjs';

import { SiHeaderDropdownItemComponent } from './si-header-dropdown-item.component';
import { SiHeaderDropdownTriggerDirective } from './si-header-dropdown-trigger.directive';
Expand Down Expand Up @@ -43,7 +42,7 @@ import { SiHeaderDropdownTriggerHarness } from './testing/si-header-dropdown-tri
providers: [{ provide: SI_HEADER_WITH_DROPDOWNS, useExisting: TestHostComponent }]
})
class TestHostComponent implements HeaderWithDropdowns {
inlineDropdown = new BehaviorSubject(false);
readonly inlineDropdown = signal(false);
readonly trigger1 = viewChild.required('trigger1', { read: SiHeaderDropdownTriggerDirective });
readonly trigger2 = viewChild.required('trigger2', { read: SiHeaderDropdownTriggerDirective });
}
Expand Down Expand Up @@ -95,7 +94,7 @@ describe('SiHeaderDropdown', () => {
it('should close on resize', async () => {
await trigger1Harness.toggle();
expect(await trigger1Harness.isOpen()).toBe(true);
fixture.componentInstance.inlineDropdown.next(false);
fixture.componentInstance.inlineDropdown.set(true);
expect(await trigger1Harness.isOpen()).toBe(false);
});

Expand Down Expand Up @@ -130,7 +129,7 @@ describe('SiHeaderDropdown', () => {
});

describe('in mobile mode', () => {
beforeEach(() => fixture.componentInstance.inlineDropdown.next(true));
beforeEach(() => fixture.componentInstance.inlineDropdown.set(true));

it('should open inline in mobile view', async () => {
await trigger1Harness.toggle();
Expand All @@ -155,7 +154,7 @@ describe('SiHeaderDropdown', () => {
it('should close on resize', async () => {
await trigger1Harness.toggle();
expect(await trigger1Harness.isOpen()).toBe(true);
fixture.componentInstance.inlineDropdown.next(true);
fixture.componentInstance.inlineDropdown.set(false);
expect(await trigger1Harness.isOpen()).toBe(false);
});

Expand Down
5 changes: 2 additions & 3 deletions projects/element-ng/header-dropdown/si-header.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
* SPDX-License-Identifier: MIT
*/
import { ConnectedPosition } from '@angular/cdk/overlay';
import { InjectionToken } from '@angular/core';
import { Observable } from 'rxjs';
import { InjectionToken, Signal } from '@angular/core';

import { SiHeaderDropdownTriggerDirective } from './si-header-dropdown-trigger.directive';

Expand All @@ -13,7 +12,7 @@ export interface HeaderWithDropdowns {
/** Called whenever an item is triggered that is not opening another dropdown. */
onDropdownItemTriggered?(): void;
/** Whether the dropdown should be opened inline. */
inlineDropdown?: Observable<boolean>;
inlineDropdown: Signal<boolean>;
/** The position of the dropdown if opened in an overlay. */
overlayPosition?: ConnectedPosition[];
/** Called whenever a dropdown is opened **/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { NgTemplateOutlet } from '@angular/common';
import {
booleanAttribute,
Component,
computed,
input,
OnChanges,
output,
Expand Down Expand Up @@ -38,7 +39,6 @@ import {
} from '@siemens/element-ng/header-dropdown';
import { Link, SiLinkDirective } from '@siemens/element-ng/link';
import { SiTranslatePipe, t } from '@siemens/element-translate-ng/translate';
import { defer } from 'rxjs';

import { AccountItem } from '../account.model';
import { AppItem, AppItemCategory } from './si-navbar-primary.model';
Expand Down Expand Up @@ -277,8 +277,7 @@ export class SiNavbarPrimaryComponent implements OnChanges, HeaderWithDropdowns
protected active?: MenuItem;

/** @internal */
// defer is required as header is not available at the time of creation.`
readonly inlineDropdown = defer(() => this.header().inlineDropdown);
readonly inlineDropdown = computed(() => this.header().inlineDropdown());

/** @internal */
onDropdownItemTriggered(): void {
Expand Down
Loading