From 44a95aa15bc32afc367494405d3bfdb85612f5a5 Mon Sep 17 00:00:00 2001 From: Barsukov Nikita Date: Tue, 19 Apr 2022 11:55:14 +0300 Subject: [PATCH] chore: new version of fix --- .../slider/slider-readonly.directive.ts | 87 ++++++++++++------- 1 file changed, 55 insertions(+), 32 deletions(-) diff --git a/projects/kit/components/slider/slider-readonly.directive.ts b/projects/kit/components/slider/slider-readonly.directive.ts index 9e8b867209c64..72102e3b41d88 100644 --- a/projects/kit/components/slider/slider-readonly.directive.ts +++ b/projects/kit/components/slider/slider-readonly.directive.ts @@ -1,59 +1,82 @@ -import { - ChangeDetectorRef, - Directive, - HostListener, - Inject, - Input, - Optional, - Self, -} from '@angular/core'; -import {NgControl} from '@angular/forms'; +import {DOCUMENT} from '@angular/common'; +import {Directive, ElementRef, HostListener, Inject, Input} from '@angular/core'; import { tuiCoerceBooleanProperty, tuiDefaultProp, TuiDestroyService, - watch, + typedFromEvent, } from '@taiga-ui/cdk'; -import {Observable} from 'rxjs'; -import {takeUntil} from 'rxjs/operators'; +import {combineLatest, merge, Observable} from 'rxjs'; +import {filter, mapTo, takeUntil, tap} from 'rxjs/operators'; -import {TuiSliderComponent} from './slider.component'; +const SLIDER_INTERACTION_KEYS = new Set([ + 'ArrowLeft', + 'ArrowRight', + 'ArrowUp', + 'ArrowDown', + 'Home', + 'End', + 'PageUp', + 'PageDown', +]); /** * Native doesn't work. * This directive imitates this native behaviour. */ +// @dynamic @Directive({ selector: 'input[tuiSlider][readonly]', providers: [TuiDestroyService], }) export class TuiSliderReadonlyDirective { - private lastValue = this.slider.value; - @Input() @tuiDefaultProp() readonly: '' | boolean = true; constructor( - @Optional() - @Self() - @Inject(NgControl) - readonly ngControl: NgControl | null, - @Inject(ChangeDetectorRef) changeDetectorRef: ChangeDetectorRef, - @Inject(TuiDestroyService) destroy$: Observable, - @Inject(TuiSliderComponent) private readonly slider: TuiSliderComponent, + @Inject(ElementRef) elementRef: ElementRef, + @Inject(DOCUMENT) documentRef: Document, + @Inject(TuiDestroyService) + destroy$: Observable, ) { - ngControl?.valueChanges - ?.pipe(watch(changeDetectorRef), takeUntil(destroy$)) - .subscribe(() => { - this.lastValue = this.slider.value; - }); + const touchStart$ = typedFromEvent(elementRef.nativeElement, 'touchstart', { + passive: false, + }); + const touchMove$ = typedFromEvent(documentRef, 'touchmove', { + passive: false, + }); + const touchEnd$ = typedFromEvent(documentRef, 'touchend', { + passive: true, + }); + + const shouldPreventMove$ = merge( + touchStart$.pipe( + tap(e => this.preventEvent(e)), + mapTo(true), + ), + touchEnd$.pipe(mapTo(false)), + ); + + combineLatest([touchMove$, shouldPreventMove$]) + .pipe( + filter(([_, shouldPreventMove]) => shouldPreventMove), + takeUntil(destroy$), + ) + .subscribe(([moveEvent]) => this.preventEvent(moveEvent)); + } + + @HostListener('mousedown', ['$event']) + preventEvent(event: Event) { + if (tuiCoerceBooleanProperty(this.readonly) && event.cancelable) { + event.preventDefault(); + } } - @HostListener('input') - onInput() { - if (tuiCoerceBooleanProperty(this.readonly)) { - this.slider.value = this.lastValue; + @HostListener('keydown', ['$event']) + preventKeyboardInteraction(event: KeyboardEvent) { + if (SLIDER_INTERACTION_KEYS.has(event.key)) { + this.preventEvent(event); } } }