import { Directive, ElementRef, HostListener, Input, NgZone, Renderer2 } from '@angular/core';
import { AnimationBuilder, style, animate } from '@angular/animations';
@Directive({
selector: '[igxRipple]',
standalone: true
})
export class IgxRippleDirective {
/**
* Sets/gets the ripple target.
* ```html
*
* ```
* ```typescript
* @ViewChild('rippleContainer', {read: IgxRippleDirective})
* public ripple: IgxRippleDirective;
* let rippleTarget = this.ripple.rippleTarget;
* ```
* Can set the ripple to activate on a child element inside the parent where igxRipple is defined.
* ```html
*
*
*
* ```
*
* @memberof IgxRippleDirective
*/
@Input('igxRippleTarget')
public rippleTarget = '';
/**
* Sets/gets the ripple color.
* ```html
*
* ```
* ```typescript
* @ViewChild('rippleContainer', {read: IgxRippleDirective})
* public ripple: IgxRippleDirective;
* let rippleColor = this.ripple.rippleColor;
* ```
*
* @memberof IgxRippleDirective
*/
@Input('igxRipple')
public rippleColor: string;
/**
* Sets/gets the ripple duration(in milliseconds).
* Default value is `600`.
* ```html
*
* ```
* ```typescript
* @ViewChild('rippleContainer', {read: IgxRippleDirective})
* public ripple: IgxRippleDirective;
* let rippleDuration = this.ripple.rippleDuration;
* ```
*
* @memberof IgxRippleDirective
*/
@Input('igxRippleDuration')
public rippleDuration = 600;
/**
* Enables/disables the ripple to be centered.
* ```html
*
* ```
*
* @memberof IgxRippleDirective
*/
@Input('igxRippleCentered')
public set centered(value: boolean) {
this._centered = value || this.centered;
}
/**
* Sets/gets whether the ripple is disabled.
* Default value is `false`.
* ```html
*
* ```
* ```typescript
* @ViewChild('rippleContainer', {read: IgxRippleDirective})
* public ripple: IgxRippleDirective;
* let isRippleDisabled = this.ripple.rippleDisabled;
* ```
*
* @memberof IgxRippleDirective
*/
@Input('igxRippleDisabled')
public rippleDisabled = false;
protected get nativeElement(): HTMLElement {
return this.elementRef.nativeElement;
}
private rippleElementClass = 'igx-ripple__inner';
private rippleHostClass = 'igx-ripple';
private _centered = false;
private animationQueue = [];
constructor(
protected builder: AnimationBuilder,
protected elementRef: ElementRef,
protected renderer: Renderer2,
private zone: NgZone) { }
/**
* @hidden
*/
@HostListener('mousedown', ['$event'])
public onMouseDown(event) {
this.zone.runOutsideAngular(() => this._ripple(event));
}
private setStyles(rippleElement: HTMLElement, styleParams: any) {
this.renderer.addClass(rippleElement, this.rippleElementClass);
this.renderer.setStyle(rippleElement, 'width', `${styleParams.radius}px`);
this.renderer.setStyle(rippleElement, 'height', `${styleParams.radius}px`);
this.renderer.setStyle(rippleElement, 'top', `${styleParams.top}px`);
this.renderer.setStyle(rippleElement, 'left', `${styleParams.left}px`);
if (this.rippleColor) {
this.renderer.setStyle(rippleElement, 'background', this.rippleColor);
}
}
private _ripple(event) {
if (this.rippleDisabled) {
return;
}
const target = (this.rippleTarget ? this.nativeElement.querySelector(this.rippleTarget) || this.nativeElement : this.nativeElement);
const rectBounds = target.getBoundingClientRect();
const radius = Math.max(rectBounds.width, rectBounds.height);
let left = Math.round(event.clientX - rectBounds.left - radius / 2);
let top = Math.round(event.clientY - rectBounds.top - radius / 2);
if (this._centered) {
left = top = 0;
}
const dimensions = {
radius,
top,
left
};
const rippleElement = this.renderer.createElement('span');
this.setStyles(rippleElement, dimensions);
this.renderer.addClass(target, this.rippleHostClass);
this.renderer.appendChild(target, rippleElement);
const animation = this.builder.build([
style({ opacity: 0.5, transform: 'scale(.3)' }),
animate(this.rippleDuration, style({ opacity: 0, transform: 'scale(2)' }))
]).create(rippleElement);
this.animationQueue.push(animation);
animation.onDone(() => {
this.animationQueue.splice(this.animationQueue.indexOf(animation), 1);
target.removeChild(rippleElement);
if (this.animationQueue.length < 1) {
this.renderer.removeClass(target, this.rippleHostClass);
}
});
animation.play();
}
}
/**
* @hidden
*/