From e94afb63aed782f0caf5e687a3f113ac3f5387ff Mon Sep 17 00:00:00 2001 From: waterplea Date: Mon, 15 Jul 2024 12:49:00 +0500 Subject: [PATCH] fix(addon-mobile): `DropdownMobile` fix open status report --- .../dropdown-mobile.component.ts | 20 ++++++++---- .../dropdown-mobile.style.less | 2 +- .../dropdown-open-monitor.directive.ts | 32 ++++++++++++------- .../hosted-dropdown.template.html | 2 +- projects/core/components/root/root.style.less | 7 +++- .../directives/dropdown/examples/5/index.html | 6 ++-- .../directives/dropdown/examples/5/index.ts | 3 +- 7 files changed, 47 insertions(+), 25 deletions(-) diff --git a/projects/addon-mobile/directives/dropdown-mobile/dropdown-mobile.component.ts b/projects/addon-mobile/directives/dropdown-mobile/dropdown-mobile.component.ts index 4f7ddd8d1fc3..a7535234fed3 100644 --- a/projects/addon-mobile/directives/dropdown-mobile/dropdown-mobile.component.ts +++ b/projects/addon-mobile/directives/dropdown-mobile/dropdown-mobile.component.ts @@ -6,6 +6,7 @@ import { ElementRef, Inject, OnDestroy, + Optional, ViewEncapsulation, } from '@angular/core'; import {TuiKeyboardService} from '@taiga-ui/addon-mobile/services'; @@ -13,13 +14,13 @@ import { TuiActiveZoneDirective, tuiGetNativeFocused, tuiIsElement, - tuiIsNodeIn, tuiPx, TuiSwipe, } from '@taiga-ui/cdk'; import { TUI_ANIMATIONS_DURATION, TuiDropdownDirective, + TuiDropdownOpenMonitorDirective, tuiFadeIn, tuiSlideInTop, } from '@taiga-ui/core'; @@ -61,6 +62,9 @@ export class TuiDropdownMobileComponent implements OnDestroy, AfterViewInit { } as const; constructor( + @Optional() + @Inject(TuiDropdownOpenMonitorDirective) + private readonly monitor: TuiDropdownOpenMonitorDirective | null, @Inject(TuiActiveZoneDirective) _: any, @Inject(TuiKeyboardService) private readonly keyboard: TuiKeyboardService, @Inject(DOCUMENT) private readonly doc: Document, @@ -76,12 +80,10 @@ export class TuiDropdownMobileComponent implements OnDestroy, AfterViewInit { onClick(event: MouseEvent): void { if ( - !this.el.nativeElement.contains(event.target as Node) && - // TODO: find a better way to check if the click is inside interactive element in textfield - !( - tuiIsNodeIn(event.target as Node, 'tui-svg') || - (tuiIsElement(event.target) && event.target.tagName === 'button') - ) + tuiIsElement(event.target) && + !this.el.nativeElement.contains(event.target) && + (!this.dropdown.el.nativeElement.contains(event.target) || + event.target.matches('input,textarea')) ) { event.stopPropagation(); } @@ -103,6 +105,10 @@ export class TuiDropdownMobileComponent implements OnDestroy, AfterViewInit { } close(): void { + if (this.monitor) { + this.monitor.tuiDropdownOpenMonitor = false; + } + this.dropdown.toggle(false); } diff --git a/projects/addon-mobile/directives/dropdown-mobile/dropdown-mobile.style.less b/projects/addon-mobile/directives/dropdown-mobile/dropdown-mobile.style.less index e2cf1823fce4..2674ddd43805 100644 --- a/projects/addon-mobile/directives/dropdown-mobile/dropdown-mobile.style.less +++ b/projects/addon-mobile/directives/dropdown-mobile/dropdown-mobile.style.less @@ -45,7 +45,7 @@ tui-dropdown-mobile._sheet { overflow: auto; background: rgba(0, 0, 0, 0.75); /* stylelint-disable-next-line */ - box-shadow: 0 -50vh 5rem 5rem rgba(0, 0, 0, 0.75); + box-shadow: 0 -80vh 0 5rem rgba(0, 0, 0, 0.75); overflow-y: scroll; scroll-snap-type: y mandatory; overscroll-behavior: none; diff --git a/projects/core/components/hosted-dropdown/dropdown-open-monitor.directive.ts b/projects/core/components/hosted-dropdown/dropdown-open-monitor.directive.ts index 438d18a245f9..20af054849d4 100644 --- a/projects/core/components/hosted-dropdown/dropdown-open-monitor.directive.ts +++ b/projects/core/components/hosted-dropdown/dropdown-open-monitor.directive.ts @@ -1,8 +1,8 @@ -import {Directive, Inject, Optional, Self} from '@angular/core'; +import {Directive, Inject, Input, Optional, Self} from '@angular/core'; import {TuiDestroyService, TuiInjectionTokenType} from '@taiga-ui/cdk'; import {TuiDropdownDirective, TuiDropdownOpenDirective} from '@taiga-ui/core/directives'; import {Observable} from 'rxjs'; -import {filter, takeUntil} from 'rxjs/operators'; +import {takeUntil} from 'rxjs/operators'; import {TUI_HOSTED_DROPDOWN_COMPONENT} from './hosted-dropdown.token'; @@ -11,23 +11,31 @@ import {TUI_HOSTED_DROPDOWN_COMPONENT} from './hosted-dropdown.token'; providers: [TuiDestroyService], }) export class TuiDropdownOpenMonitorDirective { + @Input() + set tuiDropdownOpenMonitor(open: boolean) { + this.open?.update(open); + this.hosted.updateOpen(open); + } + constructor( @Self() @Inject(TuiDestroyService) destroy$: Observable, @Inject(TUI_HOSTED_DROPDOWN_COMPONENT) - hosted: TuiInjectionTokenType, + private readonly hosted: TuiInjectionTokenType< + typeof TUI_HOSTED_DROPDOWN_COMPONENT + >, @Self() @Inject(TuiDropdownDirective) dropdown: TuiDropdownDirective, @Optional() @Inject(TuiDropdownOpenDirective) - open: TuiDropdownOpenDirective | null, + private readonly open: TuiDropdownOpenDirective | null, ) { - open?.tuiDropdownOpenChange - .pipe( - filter(value => value && open.dropdown === dropdown && !hosted.focused), - takeUntil(destroy$), - ) - .subscribe(() => { - hosted.nativeFocusableElement?.focus(); - hosted.updateOpen(true); + if (open?.dropdown === dropdown) { + open.tuiDropdownOpenChange.pipe(takeUntil(destroy$)).subscribe(value => { + if (value) { + hosted.nativeFocusableElement?.focus(); + } + + hosted.updateOpen(value); }); + } } } diff --git a/projects/core/components/hosted-dropdown/hosted-dropdown.template.html b/projects/core/components/hosted-dropdown/hosted-dropdown.template.html index 55fa16f89b92..b61583e2de49 100644 --- a/projects/core/components/hosted-dropdown/hosted-dropdown.template.html +++ b/projects/core/components/hosted-dropdown/hosted-dropdown.template.html @@ -2,10 +2,10 @@ *tuiLet="(open$ | async) ?? openChange.value as isOpen" #activeZone="tuiActiveZone" tuiAccessorProxy - tuiDropdownOpenMonitor class="t-wrapper" [tuiDropdown]="dropdown" [tuiDropdownManual]="isOpen && canOpen" + [tuiDropdownOpenMonitor]="isOpen && canOpen" [tuiDropdownSided]="sided" [tuiObscuredEnabled]="isOpen" (tuiActiveZoneChange)="onActiveZone($event)" diff --git a/projects/core/components/root/root.style.less b/projects/core/components/root/root.style.less index 332e35e6b1c0..c0817b5035b9 100644 --- a/projects/core/components/root/root.style.less +++ b/projects/core/components/root/root.style.less @@ -42,9 +42,14 @@ tui-root > .t-root-scrollbar { } .t-root-content { + position: relative; + top: var(--t-root-top); height: 100%; isolation: isolate; - transform: translateY(var(--t-root-top)); + + > * { + --t-root-top: 0; + } } [tuiDropdownButton][tuiDropdownButton] { diff --git a/projects/demo/src/modules/directives/dropdown/examples/5/index.html b/projects/demo/src/modules/directives/dropdown/examples/5/index.html index eadea627b39b..0d4f61107ce7 100644 --- a/projects/demo/src/modules/directives/dropdown/examples/5/index.html +++ b/projects/demo/src/modules/directives/dropdown/examples/5/index.html @@ -29,9 +29,11 @@ tuiDropdownMobile class="tui-space_vertical-4" [stringify]="stringify" + [tuiDropdownOpen]="!!(open$ | async)" [tuiTextfieldCleaner]="true" + [tuiTextfieldLabelOutside]="true" [(ngModel)]="selected" - [(tuiDropdownOpen)]="open" + (tuiDropdownOpenChange)="open$.next($event)" > Pick more users @@ -45,7 +47,7 @@ size="m" tuiButton tuiDropdownButton - (click)="open = false" + (click)="open$.next(false)" > Done diff --git a/projects/demo/src/modules/directives/dropdown/examples/5/index.ts b/projects/demo/src/modules/directives/dropdown/examples/5/index.ts index e60e61cce3d4..59e54b3ff5b9 100644 --- a/projects/demo/src/modules/directives/dropdown/examples/5/index.ts +++ b/projects/demo/src/modules/directives/dropdown/examples/5/index.ts @@ -2,6 +2,7 @@ import {Component} from '@angular/core'; import {changeDetection} from '@demo/emulate/change-detection'; import {encapsulation} from '@demo/emulate/encapsulation'; import {assets} from '@demo/utils'; +import {Subject} from 'rxjs'; interface User { readonly url: string; @@ -21,7 +22,7 @@ export class TuiDropdownExample5 { sum = null; user: User | null = null; - open = false; + readonly open$ = new Subject(); readonly countries = [ 'Afghanistan',