UNPKG

15.9 kBJavaScriptView Raw
1import { Directive, TemplateRef, EventEmitter, Component, ChangeDetectionStrategy, ElementRef, Inject, ChangeDetectorRef, HostBinding, Input, Output, ViewChild, HostListener, NgModule } from '@angular/core';
2import { Directionality, BidiModule } from '@angular/cdk/bidi';
3import { OverlayModule } from '@angular/cdk/overlay';
4import { DOCUMENT, CommonModule } from '@angular/common';
5import { PAGE_DOWN, PAGE_UP, DOWN_ARROW, UP_ARROW, LEFT_ARROW, RIGHT_ARROW } from '@angular/cdk/keycodes';
6import { map, takeUntil, startWith, share, debounceTime } from 'rxjs/operators';
7import { fromEvent } from 'rxjs';
8
9/**
10 * @fileoverview added by tsickle
11 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
12 */
13/**
14 * Directive to draw a tooltip to the progress bar
15 */
16class BMSliderValueTooltipDirective {
17 /**
18 * @param {?} templateRef
19 */
20 constructor(templateRef) {
21 this.templateRef = templateRef;
22 }
23}
24BMSliderValueTooltipDirective.decorators = [
25 { type: Directive, args: [{
26 selector: '[bmSliderValueTooltip]',
27 },] }
28];
29/** @nocollapse */
30BMSliderValueTooltipDirective.ctorParameters = () => [
31 { type: TemplateRef }
32];
33
34/**
35 * @fileoverview added by tsickle
36 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
37 */
38/**
39 * Observable Drag. Return relative position without the first
40 * container, or body, with position non static.
41 * @param {?} mousedownEvent
42 * @param {?=} doc
43 * @return {?}
44 */
45function dragObservable(mousedownEvent, doc = document) {
46 /** @type {?} */
47 let container = (/** @type {?} */ (mousedownEvent.target));
48 while (container.tagName !== 'BODY' &&
49 getComputedStyle(container).getPropertyValue('position') !== 'static') {
50 container = (/** @type {?} */ (container.parentElement));
51 }
52 const { left, width } = container.getBoundingClientRect();
53 /** @type {?} */
54 const offsetX = mousedownEvent.offsetX;
55 /** @type {?} */
56 const mouseup = fromEvent(doc, 'mouseup');
57 /** @type {?} */
58 const mousemove = fromEvent(doc, 'mousemove');
59 return mousemove.pipe(map((/**
60 * @param {?} mousemoveEvent
61 * @return {?}
62 */
63 mousemoveEvent => {
64 mousemoveEvent.preventDefault();
65 return Math.min(1, Math.max(0, (mousemoveEvent.clientX - offsetX - left) / width));
66 })), takeUntil(mouseup));
67}
68
69/**
70 * @fileoverview added by tsickle
71 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
72 */
73/**
74 * Observable Drag. Return relative position without the first
75 * container, or body, with position non static.
76 * @param {?} mouseenterEvent
77 * @param {?=} doc
78 * @return {?}
79 */
80function mouseoverRelativeCoordinatesObservable(mouseenterEvent, doc = document) {
81 mouseenterEvent.preventDefault();
82 /** @type {?} */
83 let container = (/** @type {?} */ (mouseenterEvent.target));
84 while (container.tagName !== 'BODY' &&
85 getComputedStyle(container).getPropertyValue('position') !== 'static') {
86 container = (/** @type {?} */ (container.parentElement));
87 }
88 const { left, width } = container.getBoundingClientRect();
89 /** @type {?} */
90 const mouseleave = fromEvent(container, 'mouseleave');
91 /** @type {?} */
92 const mousemove = fromEvent(doc, 'mousemove');
93 return mousemove.pipe(map((/**
94 * @param {?} mousemoveEvent
95 * @return {?}
96 */
97 mousemoveEvent => {
98 mousemoveEvent.preventDefault();
99 return Math.min(1, Math.max(0, (mousemoveEvent.clientX - left) / width));
100 })), takeUntil(mouseleave), startWith(Math.min(1, Math.max(0, (mouseenterEvent.clientX - left) / width))));
101}
102
103/**
104 * @fileoverview added by tsickle
105 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
106 */
107/**
108 * Media progress slider
109 */
110class BMSliderComponent {
111 /**
112 * @param {?} _elementRef
113 * @param {?} _document
114 * @param {?} _cdr
115 * @param {?} _dir
116 */
117 constructor(_elementRef, _document, _cdr, _dir) {
118 this._elementRef = _elementRef;
119 this._document = _document;
120 this._cdr = _cdr;
121 this._dir = _dir;
122 this.min = 0;
123 this.tabindex = 0;
124 this.role = 'slider';
125 this.change = new EventEmitter();
126 this.dragStart = new EventEmitter();
127 this.dragEnd = new EventEmitter();
128 this._isDragging = false;
129 this._isOver = false;
130 }
131 /**
132 * @param {?} v
133 * @return {?}
134 */
135 set value(v) {
136 this._value = v;
137 }
138 /**
139 * @return {?}
140 */
141 get value() {
142 return this._value;
143 }
144 /**
145 * @param {?} v
146 * @return {?}
147 */
148 writeValue(v) {
149 this.value = v;
150 }
151 /**
152 * @param {?} fn
153 * @return {?}
154 */
155 registerOnChange(fn) {
156 this._onChangeCB = fn;
157 }
158 /**
159 * @param {?} fn
160 * @return {?}
161 */
162 registerOnTouched(fn) {
163 this._onTouchedCB = fn;
164 }
165 /**
166 * @param {?} isDisabled
167 * @return {?}
168 */
169 setDisabledState(isDisabled) {
170 this.disabled = isDisabled;
171 }
172 /**
173 * @param {?} $event
174 * @return {?}
175 */
176 onMouseenter($event) {
177 if (this.disabled) {
178 return;
179 }
180 this._isOver = true;
181 mouseoverRelativeCoordinatesObservable($event, this._document).subscribe({
182 next: (/**
183 * @param {?} val
184 * @return {?}
185 */
186 val => {
187 this.pointerTime = val * (this.max || 0);
188 /** @type {?} */
189 const overTime = Math.max(0, this.getRelativeLeft(this.pointerTime) -
190 this.getRelativeLeft(this.value));
191 if (overTime > 0 &&
192 this._previewBar &&
193 this._previewBar.nativeElement) {
194 /** @type {?} */
195 const relativeLeft = this.getRelativeLeft(this.value);
196 this._previewBar.nativeElement.style.left = `${relativeLeft}px`;
197 this._previewBar.nativeElement.style.width = `${overTime}px`;
198 }
199 this._cdr.markForCheck();
200 }),
201 error: (/**
202 * @return {?}
203 */
204 () => {
205 this._isOver = false;
206 }),
207 complete: (/**
208 * @return {?}
209 */
210 () => {
211 this._isOver = false;
212 this._cdr.markForCheck();
213 }),
214 });
215 }
216 /**
217 * @param {?} e
218 * @return {?}
219 */
220 onClick(e) {
221 if (!this._isDragging) {
222 e.preventDefault();
223 const { offsetX } = e;
224 const { width } = this._elementRef.nativeElement.getBoundingClientRect();
225 /** @type {?} */
226 const percent = offsetX / width;
227 this.value = percent * (this.max || 0);
228 this.change.emit(this.value);
229 }
230 }
231 /**
232 * @return {?}
233 */
234 onFocusin() {
235 if (this._onTouchedCB) {
236 this._onTouchedCB();
237 }
238 }
239 // tslint:disable-next-line:cyclomatic-complexity
240 /**
241 * @param {?} e
242 * @return {?}
243 */
244 onKeydown(e) {
245 if (this.disabled) {
246 return;
247 }
248 /** @type {?} */
249 let emitChanges = false;
250 if (this.max) {
251 /** @type {?} */
252 const smallStep = (this.max || 1) / 100;
253 switch (e.keyCode) {
254 case PAGE_DOWN: {
255 e.preventDefault();
256 this._value = Math.max(0, this._value - 10 * smallStep);
257 emitChanges = true;
258 break;
259 }
260 case PAGE_UP: {
261 e.preventDefault();
262 this._value = Math.min(this.max, this._value + 10 * smallStep);
263 emitChanges = true;
264 break;
265 }
266 case DOWN_ARROW: {
267 e.preventDefault();
268 this._value = Math.max(0, this._value - smallStep);
269 emitChanges = true;
270 break;
271 }
272 case UP_ARROW: {
273 e.preventDefault();
274 this._value = Math.min(this.max, this._value + smallStep);
275 emitChanges = true;
276 break;
277 }
278 case LEFT_ARROW: {
279 e.preventDefault();
280 this._value = Math.min(Math.max(0, this._value +
281 (this._dir.value === 'ltr' ? -smallStep : smallStep)), this.max);
282 emitChanges = true;
283 break;
284 }
285 case RIGHT_ARROW: {
286 e.preventDefault();
287 this._value = Math.min(Math.max(0, this._value +
288 (this._dir.value === 'ltr' ? smallStep : -smallStep)), this.max);
289 emitChanges = true;
290 break;
291 }
292 default:
293 }
294 }
295 if (emitChanges) {
296 if (this._onChangeCB) {
297 this._onChangeCB(this.value);
298 }
299 this.change.emit(this.value);
300 }
301 }
302 /**
303 * @param {?} value
304 * @return {?}
305 */
306 getRelativeLeft(value) {
307 if (this._elementRef.nativeElement && value && this.max) {
308 const { width } = this._elementRef.nativeElement.getBoundingClientRect();
309 /** @type {?} */
310 const relative = value / (this.max - this.min);
311 return relative * width;
312 }
313 return 0;
314 }
315 /**
316 * @return {?}
317 */
318 showThumb() {
319 return this._isDragging || this._isOver;
320 }
321 /**
322 * @return {?}
323 */
324 showPreviewBar() {
325 return this._isOver && !this._isDragging;
326 }
327 /**
328 * @param {?} $event
329 * @return {?}
330 */
331 onThumbMousedown($event) {
332 if (this.disabled) {
333 return;
334 }
335 this._cdr.detach();
336 this._isDragging = true;
337 if (this._onTouchedCB) {
338 this._onTouchedCB();
339 }
340 this.dragStart.emit();
341 /** @type {?} */
342 const dragObservable$ = dragObservable($event, this._document).pipe(share());
343 // The two observables with different throttles target components
344 // that should update at different rates. The bounced targets the
345 // the time tooltip, while the non bounced targets the dragged thumb
346 // and bars.
347 dragObservable$
348 .pipe(debounceTime(15))
349 .subscribe((/**
350 * @return {?}
351 */
352 () => this._cdr.detectChanges()));
353 dragObservable$.subscribe({
354 next: (/**
355 * @param {?} val
356 * @return {?}
357 */
358 val => {
359 this._value = val * (this.max || 0);
360 /** @type {?} */
361 const relativeLeft = this.getRelativeLeft(this.value);
362 ((/** @type {?} */ ($event.target))).style.left = `${relativeLeft}px`;
363 if (this._doneBar && this._doneBar.nativeElement) {
364 this._doneBar.nativeElement.style.width = `${relativeLeft}px`;
365 }
366 if (this._onChangeCB) {
367 this._onChangeCB(Math.min(Math.max(this.min, this.value), this.max));
368 }
369 this.change.emit(this.value);
370 }),
371 error: (/**
372 * @return {?}
373 */
374 () => {
375 this._cdr.reattach();
376 }),
377 complete: (/**
378 * @return {?}
379 */
380 () => {
381 this._cdr.reattach();
382 this.dragEnd.emit();
383 setTimeout((/**
384 * @return {?}
385 */
386 () => {
387 this._isDragging = false;
388 }), 10);
389 }),
390 });
391 }
392}
393BMSliderComponent.decorators = [
394 { type: Component, args: [{
395 selector: 'bm-slider',
396 template: "<span\n *ngIf=\"showPreviewBar()\"\n #previewBar\n class=\"bm-slider__bar bm-slider__bar--preview\"\n></span>\n<span\n #doneBar\n class=\"bm-slider__bar bm-slider__bar--done\"\n [ngStyle]=\"{ 'width.px': getRelativeLeft(value) }\"\n></span>\n<span\n *ngIf=\"showThumb()\"\n #thumb\n class=\"bm-slider-thumb\"\n [ngStyle]=\"{ 'left.px': getRelativeLeft(value), 'margin-left.em': -0.5 }\"\n (mousedown)=\"onThumbMousedown($event)\"\n></span>\n<ng-content></ng-content>\n",
397 changeDetection: ChangeDetectionStrategy.OnPush,
398 styles: [":host{height:.5em;border-radius:.4em;display:inline-block;background-color:var(--secondary-color,#bcbcbc);max-width:100%;min-width:var(--bm-slider-min--width,200px);position:relative}:host:focus{outline:solid var(--anchor-color,#4399fd) 2px}:host(.bm-slider--disabled){opacity:.5}.bm-slider__bar{height:.5em;border-radius:.4em;display:inline-block;position:absolute}.bm-slider__bar--done{background-color:var(--header-background-color,#3e71ad)}.bm-slider__bar--preview{background-color:var(--secondary-color-hover,#959494)}.bm-slider-thumb{position:absolute;background-color:var(--header-background-color,#3e71ad);border-radius:50%;display:inline-block;height:1em;width:1em;top:-.25em}.bm-slider-tooltip{display:inline-block;background-color:rgba(0,0,0,.7);border:1px solid #000;border-radius:3px;padding:.25em .5em;color:#fff;font-size:smaller}"]
399 }] }
400];
401/** @nocollapse */
402BMSliderComponent.ctorParameters = () => [
403 { type: ElementRef },
404 { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] },
405 { type: ChangeDetectorRef },
406 { type: Directionality }
407];
408BMSliderComponent.propDecorators = {
409 max: [{ type: HostBinding, args: ['attr.aria-valuemax',] }, { type: Input }],
410 value: [{ type: HostBinding, args: ['attr.aria-valuenow',] }, { type: Input }],
411 min: [{ type: HostBinding, args: ['attr.aria-valuemin',] }, { type: Input }],
412 tabindex: [{ type: HostBinding, args: ['attr.tabindex',] }, { type: Input }],
413 disabled: [{ type: Input }, { type: HostBinding, args: ['attr.aria-disabled',] }, { type: HostBinding, args: ['class.bm-slider--disabled',] }],
414 role: [{ type: HostBinding, args: ['attr.role',] }],
415 change: [{ type: Output }],
416 dragStart: [{ type: Output }],
417 dragEnd: [{ type: Output }],
418 _doneBar: [{ type: ViewChild, args: ['doneBar', { read: ElementRef, static: true },] }],
419 _previewBar: [{ type: ViewChild, args: ['previewBar', { read: ElementRef, static: false },] }],
420 onMouseenter: [{ type: HostListener, args: ['mouseenter', ['$event'],] }],
421 onClick: [{ type: HostListener, args: ['click', ['$event'],] }],
422 onFocusin: [{ type: HostListener, args: ['focusin',] }],
423 onKeydown: [{ type: HostListener, args: ['keydown', ['$event'],] }]
424};
425
426/**
427 * @fileoverview added by tsickle
428 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
429 */
430/**
431 * Slider component module
432 */
433class BMSliderComponentModule {
434}
435BMSliderComponentModule.decorators = [
436 { type: NgModule, args: [{
437 imports: [BidiModule, CommonModule, OverlayModule],
438 declarations: [BMSliderValueTooltipDirective, BMSliderComponent],
439 exports: [BMSliderComponent, BMSliderValueTooltipDirective],
440 },] }
441];
442
443export { BMSliderComponent, BMSliderComponentModule, BMSliderValueTooltipDirective };
444//# sourceMappingURL=bmat-angular-forms-bm-slider.js.map