mirror of https://github.com/ghostfolio/ghostfolio
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
544 lines
18 KiB
544 lines
18 KiB
import { normalizePassiveListenerOptions, _getEventTarget, Platform } from '@angular/cdk/platform';
|
|
import * as i0 from '@angular/core';
|
|
import { Component, ChangeDetectionStrategy, ViewEncapsulation, InjectionToken, inject, ElementRef, NgZone, Injector, Directive, Input } from '@angular/core';
|
|
import { isFakeMousedownFromScreenReader, isFakeTouchstartFromScreenReader } from '@angular/cdk/a11y';
|
|
import { coerceElement } from '@angular/cdk/coercion';
|
|
import { _CdkPrivateStyleLoader } from '@angular/cdk/private';
|
|
import { _animationsDisabled } from './_animation-chunk.mjs';
|
|
|
|
var RippleState;
|
|
(function (RippleState) {
|
|
RippleState[RippleState["FADING_IN"] = 0] = "FADING_IN";
|
|
RippleState[RippleState["VISIBLE"] = 1] = "VISIBLE";
|
|
RippleState[RippleState["FADING_OUT"] = 2] = "FADING_OUT";
|
|
RippleState[RippleState["HIDDEN"] = 3] = "HIDDEN";
|
|
})(RippleState || (RippleState = {}));
|
|
class RippleRef {
|
|
_renderer;
|
|
element;
|
|
config;
|
|
_animationForciblyDisabledThroughCss;
|
|
state = RippleState.HIDDEN;
|
|
constructor(_renderer, element, config, _animationForciblyDisabledThroughCss = false) {
|
|
this._renderer = _renderer;
|
|
this.element = element;
|
|
this.config = config;
|
|
this._animationForciblyDisabledThroughCss = _animationForciblyDisabledThroughCss;
|
|
}
|
|
fadeOut() {
|
|
this._renderer.fadeOutRipple(this);
|
|
}
|
|
}
|
|
|
|
const passiveCapturingEventOptions$1 = normalizePassiveListenerOptions({
|
|
passive: true,
|
|
capture: true
|
|
});
|
|
class RippleEventManager {
|
|
_events = new Map();
|
|
addHandler(ngZone, name, element, handler) {
|
|
const handlersForEvent = this._events.get(name);
|
|
if (handlersForEvent) {
|
|
const handlersForElement = handlersForEvent.get(element);
|
|
if (handlersForElement) {
|
|
handlersForElement.add(handler);
|
|
} else {
|
|
handlersForEvent.set(element, new Set([handler]));
|
|
}
|
|
} else {
|
|
this._events.set(name, new Map([[element, new Set([handler])]]));
|
|
ngZone.runOutsideAngular(() => {
|
|
document.addEventListener(name, this._delegateEventHandler, passiveCapturingEventOptions$1);
|
|
});
|
|
}
|
|
}
|
|
removeHandler(name, element, handler) {
|
|
const handlersForEvent = this._events.get(name);
|
|
if (!handlersForEvent) {
|
|
return;
|
|
}
|
|
const handlersForElement = handlersForEvent.get(element);
|
|
if (!handlersForElement) {
|
|
return;
|
|
}
|
|
handlersForElement.delete(handler);
|
|
if (handlersForElement.size === 0) {
|
|
handlersForEvent.delete(element);
|
|
}
|
|
if (handlersForEvent.size === 0) {
|
|
this._events.delete(name);
|
|
document.removeEventListener(name, this._delegateEventHandler, passiveCapturingEventOptions$1);
|
|
}
|
|
}
|
|
_delegateEventHandler = event => {
|
|
const target = _getEventTarget(event);
|
|
if (target) {
|
|
this._events.get(event.type)?.forEach((handlers, element) => {
|
|
if (element === target || element.contains(target)) {
|
|
handlers.forEach(handler => handler.handleEvent(event));
|
|
}
|
|
});
|
|
}
|
|
};
|
|
}
|
|
|
|
const defaultRippleAnimationConfig = {
|
|
enterDuration: 225,
|
|
exitDuration: 150
|
|
};
|
|
const ignoreMouseEventsTimeout = 800;
|
|
const passiveCapturingEventOptions = normalizePassiveListenerOptions({
|
|
passive: true,
|
|
capture: true
|
|
});
|
|
const pointerDownEvents = ['mousedown', 'touchstart'];
|
|
const pointerUpEvents = ['mouseup', 'mouseleave', 'touchend', 'touchcancel'];
|
|
class _MatRippleStylesLoader {
|
|
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
minVersion: "12.0.0",
|
|
version: "21.0.3",
|
|
ngImport: i0,
|
|
type: _MatRippleStylesLoader,
|
|
deps: [],
|
|
target: i0.ɵɵFactoryTarget.Component
|
|
});
|
|
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
minVersion: "14.0.0",
|
|
version: "21.0.3",
|
|
type: _MatRippleStylesLoader,
|
|
isStandalone: true,
|
|
selector: "ng-component",
|
|
host: {
|
|
attributes: {
|
|
"mat-ripple-style-loader": ""
|
|
}
|
|
},
|
|
ngImport: i0,
|
|
template: '',
|
|
isInline: true,
|
|
styles: [".mat-ripple{overflow:hidden;position:relative}.mat-ripple:not(:empty){transform:translateZ(0)}.mat-ripple.mat-ripple-unbounded{overflow:visible}.mat-ripple-element{position:absolute;border-radius:50%;pointer-events:none;transition:opacity,transform 0ms cubic-bezier(0, 0, 0.2, 1);transform:scale3d(0, 0, 0);background-color:var(--mat-ripple-color, color-mix(in srgb, var(--mat-sys-on-surface) 10%, transparent))}@media(forced-colors: active){.mat-ripple-element{display:none}}.cdk-drag-preview .mat-ripple-element,.cdk-drag-placeholder .mat-ripple-element{display:none}\n"],
|
|
changeDetection: i0.ChangeDetectionStrategy.OnPush,
|
|
encapsulation: i0.ViewEncapsulation.None
|
|
});
|
|
}
|
|
i0.ɵɵngDeclareClassMetadata({
|
|
minVersion: "12.0.0",
|
|
version: "21.0.3",
|
|
ngImport: i0,
|
|
type: _MatRippleStylesLoader,
|
|
decorators: [{
|
|
type: Component,
|
|
args: [{
|
|
template: '',
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
encapsulation: ViewEncapsulation.None,
|
|
host: {
|
|
'mat-ripple-style-loader': ''
|
|
},
|
|
styles: [".mat-ripple{overflow:hidden;position:relative}.mat-ripple:not(:empty){transform:translateZ(0)}.mat-ripple.mat-ripple-unbounded{overflow:visible}.mat-ripple-element{position:absolute;border-radius:50%;pointer-events:none;transition:opacity,transform 0ms cubic-bezier(0, 0, 0.2, 1);transform:scale3d(0, 0, 0);background-color:var(--mat-ripple-color, color-mix(in srgb, var(--mat-sys-on-surface) 10%, transparent))}@media(forced-colors: active){.mat-ripple-element{display:none}}.cdk-drag-preview .mat-ripple-element,.cdk-drag-placeholder .mat-ripple-element{display:none}\n"]
|
|
}]
|
|
}]
|
|
});
|
|
class RippleRenderer {
|
|
_target;
|
|
_ngZone;
|
|
_platform;
|
|
_containerElement;
|
|
_triggerElement = null;
|
|
_isPointerDown = false;
|
|
_activeRipples = new Map();
|
|
_mostRecentTransientRipple = null;
|
|
_lastTouchStartEvent;
|
|
_pointerUpEventsRegistered = false;
|
|
_containerRect = null;
|
|
static _eventManager = new RippleEventManager();
|
|
constructor(_target, _ngZone, elementOrElementRef, _platform, injector) {
|
|
this._target = _target;
|
|
this._ngZone = _ngZone;
|
|
this._platform = _platform;
|
|
if (_platform.isBrowser) {
|
|
this._containerElement = coerceElement(elementOrElementRef);
|
|
}
|
|
if (injector) {
|
|
injector.get(_CdkPrivateStyleLoader).load(_MatRippleStylesLoader);
|
|
}
|
|
}
|
|
fadeInRipple(x, y, config = {}) {
|
|
const containerRect = this._containerRect = this._containerRect || this._containerElement.getBoundingClientRect();
|
|
const animationConfig = {
|
|
...defaultRippleAnimationConfig,
|
|
...config.animation
|
|
};
|
|
if (config.centered) {
|
|
x = containerRect.left + containerRect.width / 2;
|
|
y = containerRect.top + containerRect.height / 2;
|
|
}
|
|
const radius = config.radius || distanceToFurthestCorner(x, y, containerRect);
|
|
const offsetX = x - containerRect.left;
|
|
const offsetY = y - containerRect.top;
|
|
const enterDuration = animationConfig.enterDuration;
|
|
const ripple = document.createElement('div');
|
|
ripple.classList.add('mat-ripple-element');
|
|
ripple.style.left = `${offsetX - radius}px`;
|
|
ripple.style.top = `${offsetY - radius}px`;
|
|
ripple.style.height = `${radius * 2}px`;
|
|
ripple.style.width = `${radius * 2}px`;
|
|
if (config.color != null) {
|
|
ripple.style.backgroundColor = config.color;
|
|
}
|
|
ripple.style.transitionDuration = `${enterDuration}ms`;
|
|
this._containerElement.appendChild(ripple);
|
|
const computedStyles = window.getComputedStyle(ripple);
|
|
const userTransitionProperty = computedStyles.transitionProperty;
|
|
const userTransitionDuration = computedStyles.transitionDuration;
|
|
const animationForciblyDisabledThroughCss = userTransitionProperty === 'none' || userTransitionDuration === '0s' || userTransitionDuration === '0s, 0s' || containerRect.width === 0 && containerRect.height === 0;
|
|
const rippleRef = new RippleRef(this, ripple, config, animationForciblyDisabledThroughCss);
|
|
ripple.style.transform = 'scale3d(1, 1, 1)';
|
|
rippleRef.state = RippleState.FADING_IN;
|
|
if (!config.persistent) {
|
|
this._mostRecentTransientRipple = rippleRef;
|
|
}
|
|
let eventListeners = null;
|
|
if (!animationForciblyDisabledThroughCss && (enterDuration || animationConfig.exitDuration)) {
|
|
this._ngZone.runOutsideAngular(() => {
|
|
const onTransitionEnd = () => {
|
|
if (eventListeners) {
|
|
eventListeners.fallbackTimer = null;
|
|
}
|
|
clearTimeout(fallbackTimer);
|
|
this._finishRippleTransition(rippleRef);
|
|
};
|
|
const onTransitionCancel = () => this._destroyRipple(rippleRef);
|
|
const fallbackTimer = setTimeout(onTransitionCancel, enterDuration + 100);
|
|
ripple.addEventListener('transitionend', onTransitionEnd);
|
|
ripple.addEventListener('transitioncancel', onTransitionCancel);
|
|
eventListeners = {
|
|
onTransitionEnd,
|
|
onTransitionCancel,
|
|
fallbackTimer
|
|
};
|
|
});
|
|
}
|
|
this._activeRipples.set(rippleRef, eventListeners);
|
|
if (animationForciblyDisabledThroughCss || !enterDuration) {
|
|
this._finishRippleTransition(rippleRef);
|
|
}
|
|
return rippleRef;
|
|
}
|
|
fadeOutRipple(rippleRef) {
|
|
if (rippleRef.state === RippleState.FADING_OUT || rippleRef.state === RippleState.HIDDEN) {
|
|
return;
|
|
}
|
|
const rippleEl = rippleRef.element;
|
|
const animationConfig = {
|
|
...defaultRippleAnimationConfig,
|
|
...rippleRef.config.animation
|
|
};
|
|
rippleEl.style.transitionDuration = `${animationConfig.exitDuration}ms`;
|
|
rippleEl.style.opacity = '0';
|
|
rippleRef.state = RippleState.FADING_OUT;
|
|
if (rippleRef._animationForciblyDisabledThroughCss || !animationConfig.exitDuration) {
|
|
this._finishRippleTransition(rippleRef);
|
|
}
|
|
}
|
|
fadeOutAll() {
|
|
this._getActiveRipples().forEach(ripple => ripple.fadeOut());
|
|
}
|
|
fadeOutAllNonPersistent() {
|
|
this._getActiveRipples().forEach(ripple => {
|
|
if (!ripple.config.persistent) {
|
|
ripple.fadeOut();
|
|
}
|
|
});
|
|
}
|
|
setupTriggerEvents(elementOrElementRef) {
|
|
const element = coerceElement(elementOrElementRef);
|
|
if (!this._platform.isBrowser || !element || element === this._triggerElement) {
|
|
return;
|
|
}
|
|
this._removeTriggerEvents();
|
|
this._triggerElement = element;
|
|
pointerDownEvents.forEach(type => {
|
|
RippleRenderer._eventManager.addHandler(this._ngZone, type, element, this);
|
|
});
|
|
}
|
|
handleEvent(event) {
|
|
if (event.type === 'mousedown') {
|
|
this._onMousedown(event);
|
|
} else if (event.type === 'touchstart') {
|
|
this._onTouchStart(event);
|
|
} else {
|
|
this._onPointerUp();
|
|
}
|
|
if (!this._pointerUpEventsRegistered) {
|
|
this._ngZone.runOutsideAngular(() => {
|
|
pointerUpEvents.forEach(type => {
|
|
this._triggerElement.addEventListener(type, this, passiveCapturingEventOptions);
|
|
});
|
|
});
|
|
this._pointerUpEventsRegistered = true;
|
|
}
|
|
}
|
|
_finishRippleTransition(rippleRef) {
|
|
if (rippleRef.state === RippleState.FADING_IN) {
|
|
this._startFadeOutTransition(rippleRef);
|
|
} else if (rippleRef.state === RippleState.FADING_OUT) {
|
|
this._destroyRipple(rippleRef);
|
|
}
|
|
}
|
|
_startFadeOutTransition(rippleRef) {
|
|
const isMostRecentTransientRipple = rippleRef === this._mostRecentTransientRipple;
|
|
const {
|
|
persistent
|
|
} = rippleRef.config;
|
|
rippleRef.state = RippleState.VISIBLE;
|
|
if (!persistent && (!isMostRecentTransientRipple || !this._isPointerDown)) {
|
|
rippleRef.fadeOut();
|
|
}
|
|
}
|
|
_destroyRipple(rippleRef) {
|
|
const eventListeners = this._activeRipples.get(rippleRef) ?? null;
|
|
this._activeRipples.delete(rippleRef);
|
|
if (!this._activeRipples.size) {
|
|
this._containerRect = null;
|
|
}
|
|
if (rippleRef === this._mostRecentTransientRipple) {
|
|
this._mostRecentTransientRipple = null;
|
|
}
|
|
rippleRef.state = RippleState.HIDDEN;
|
|
if (eventListeners !== null) {
|
|
rippleRef.element.removeEventListener('transitionend', eventListeners.onTransitionEnd);
|
|
rippleRef.element.removeEventListener('transitioncancel', eventListeners.onTransitionCancel);
|
|
if (eventListeners.fallbackTimer !== null) {
|
|
clearTimeout(eventListeners.fallbackTimer);
|
|
}
|
|
}
|
|
rippleRef.element.remove();
|
|
}
|
|
_onMousedown(event) {
|
|
const isFakeMousedown = isFakeMousedownFromScreenReader(event);
|
|
const isSyntheticEvent = this._lastTouchStartEvent && Date.now() < this._lastTouchStartEvent + ignoreMouseEventsTimeout;
|
|
if (!this._target.rippleDisabled && !isFakeMousedown && !isSyntheticEvent) {
|
|
this._isPointerDown = true;
|
|
this.fadeInRipple(event.clientX, event.clientY, this._target.rippleConfig);
|
|
}
|
|
}
|
|
_onTouchStart(event) {
|
|
if (!this._target.rippleDisabled && !isFakeTouchstartFromScreenReader(event)) {
|
|
this._lastTouchStartEvent = Date.now();
|
|
this._isPointerDown = true;
|
|
const touches = event.changedTouches;
|
|
if (touches) {
|
|
for (let i = 0; i < touches.length; i++) {
|
|
this.fadeInRipple(touches[i].clientX, touches[i].clientY, this._target.rippleConfig);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_onPointerUp() {
|
|
if (!this._isPointerDown) {
|
|
return;
|
|
}
|
|
this._isPointerDown = false;
|
|
this._getActiveRipples().forEach(ripple => {
|
|
const isVisible = ripple.state === RippleState.VISIBLE || ripple.config.terminateOnPointerUp && ripple.state === RippleState.FADING_IN;
|
|
if (!ripple.config.persistent && isVisible) {
|
|
ripple.fadeOut();
|
|
}
|
|
});
|
|
}
|
|
_getActiveRipples() {
|
|
return Array.from(this._activeRipples.keys());
|
|
}
|
|
_removeTriggerEvents() {
|
|
const trigger = this._triggerElement;
|
|
if (trigger) {
|
|
pointerDownEvents.forEach(type => RippleRenderer._eventManager.removeHandler(type, trigger, this));
|
|
if (this._pointerUpEventsRegistered) {
|
|
pointerUpEvents.forEach(type => trigger.removeEventListener(type, this, passiveCapturingEventOptions));
|
|
this._pointerUpEventsRegistered = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function distanceToFurthestCorner(x, y, rect) {
|
|
const distX = Math.max(Math.abs(x - rect.left), Math.abs(x - rect.right));
|
|
const distY = Math.max(Math.abs(y - rect.top), Math.abs(y - rect.bottom));
|
|
return Math.sqrt(distX * distX + distY * distY);
|
|
}
|
|
|
|
const MAT_RIPPLE_GLOBAL_OPTIONS = new InjectionToken('mat-ripple-global-options');
|
|
class MatRipple {
|
|
_elementRef = inject(ElementRef);
|
|
_animationsDisabled = _animationsDisabled();
|
|
color;
|
|
unbounded = false;
|
|
centered = false;
|
|
radius = 0;
|
|
animation;
|
|
get disabled() {
|
|
return this._disabled;
|
|
}
|
|
set disabled(value) {
|
|
if (value) {
|
|
this.fadeOutAllNonPersistent();
|
|
}
|
|
this._disabled = value;
|
|
this._setupTriggerEventsIfEnabled();
|
|
}
|
|
_disabled = false;
|
|
get trigger() {
|
|
return this._trigger || this._elementRef.nativeElement;
|
|
}
|
|
set trigger(trigger) {
|
|
this._trigger = trigger;
|
|
this._setupTriggerEventsIfEnabled();
|
|
}
|
|
_trigger;
|
|
_rippleRenderer;
|
|
_globalOptions;
|
|
_isInitialized = false;
|
|
constructor() {
|
|
const ngZone = inject(NgZone);
|
|
const platform = inject(Platform);
|
|
const globalOptions = inject(MAT_RIPPLE_GLOBAL_OPTIONS, {
|
|
optional: true
|
|
});
|
|
const injector = inject(Injector);
|
|
this._globalOptions = globalOptions || {};
|
|
this._rippleRenderer = new RippleRenderer(this, ngZone, this._elementRef, platform, injector);
|
|
}
|
|
ngOnInit() {
|
|
this._isInitialized = true;
|
|
this._setupTriggerEventsIfEnabled();
|
|
}
|
|
ngOnDestroy() {
|
|
this._rippleRenderer._removeTriggerEvents();
|
|
}
|
|
fadeOutAll() {
|
|
this._rippleRenderer.fadeOutAll();
|
|
}
|
|
fadeOutAllNonPersistent() {
|
|
this._rippleRenderer.fadeOutAllNonPersistent();
|
|
}
|
|
get rippleConfig() {
|
|
return {
|
|
centered: this.centered,
|
|
radius: this.radius,
|
|
color: this.color,
|
|
animation: {
|
|
...this._globalOptions.animation,
|
|
...(this._animationsDisabled ? {
|
|
enterDuration: 0,
|
|
exitDuration: 0
|
|
} : {}),
|
|
...this.animation
|
|
},
|
|
terminateOnPointerUp: this._globalOptions.terminateOnPointerUp
|
|
};
|
|
}
|
|
get rippleDisabled() {
|
|
return this.disabled || !!this._globalOptions.disabled;
|
|
}
|
|
_setupTriggerEventsIfEnabled() {
|
|
if (!this.disabled && this._isInitialized) {
|
|
this._rippleRenderer.setupTriggerEvents(this.trigger);
|
|
}
|
|
}
|
|
launch(configOrX, y = 0, config) {
|
|
if (typeof configOrX === 'number') {
|
|
return this._rippleRenderer.fadeInRipple(configOrX, y, {
|
|
...this.rippleConfig,
|
|
...config
|
|
});
|
|
} else {
|
|
return this._rippleRenderer.fadeInRipple(0, 0, {
|
|
...this.rippleConfig,
|
|
...configOrX
|
|
});
|
|
}
|
|
}
|
|
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
minVersion: "12.0.0",
|
|
version: "21.0.3",
|
|
ngImport: i0,
|
|
type: MatRipple,
|
|
deps: [],
|
|
target: i0.ɵɵFactoryTarget.Directive
|
|
});
|
|
static ɵdir = i0.ɵɵngDeclareDirective({
|
|
minVersion: "14.0.0",
|
|
version: "21.0.3",
|
|
type: MatRipple,
|
|
isStandalone: true,
|
|
selector: "[mat-ripple], [matRipple]",
|
|
inputs: {
|
|
color: ["matRippleColor", "color"],
|
|
unbounded: ["matRippleUnbounded", "unbounded"],
|
|
centered: ["matRippleCentered", "centered"],
|
|
radius: ["matRippleRadius", "radius"],
|
|
animation: ["matRippleAnimation", "animation"],
|
|
disabled: ["matRippleDisabled", "disabled"],
|
|
trigger: ["matRippleTrigger", "trigger"]
|
|
},
|
|
host: {
|
|
properties: {
|
|
"class.mat-ripple-unbounded": "unbounded"
|
|
},
|
|
classAttribute: "mat-ripple"
|
|
},
|
|
exportAs: ["matRipple"],
|
|
ngImport: i0
|
|
});
|
|
}
|
|
i0.ɵɵngDeclareClassMetadata({
|
|
minVersion: "12.0.0",
|
|
version: "21.0.3",
|
|
ngImport: i0,
|
|
type: MatRipple,
|
|
decorators: [{
|
|
type: Directive,
|
|
args: [{
|
|
selector: '[mat-ripple], [matRipple]',
|
|
exportAs: 'matRipple',
|
|
host: {
|
|
'class': 'mat-ripple',
|
|
'[class.mat-ripple-unbounded]': 'unbounded'
|
|
}
|
|
}]
|
|
}],
|
|
ctorParameters: () => [],
|
|
propDecorators: {
|
|
color: [{
|
|
type: Input,
|
|
args: ['matRippleColor']
|
|
}],
|
|
unbounded: [{
|
|
type: Input,
|
|
args: ['matRippleUnbounded']
|
|
}],
|
|
centered: [{
|
|
type: Input,
|
|
args: ['matRippleCentered']
|
|
}],
|
|
radius: [{
|
|
type: Input,
|
|
args: ['matRippleRadius']
|
|
}],
|
|
animation: [{
|
|
type: Input,
|
|
args: ['matRippleAnimation']
|
|
}],
|
|
disabled: [{
|
|
type: Input,
|
|
args: ['matRippleDisabled']
|
|
}],
|
|
trigger: [{
|
|
type: Input,
|
|
args: ['matRippleTrigger']
|
|
}]
|
|
}
|
|
});
|
|
|
|
export { MAT_RIPPLE_GLOBAL_OPTIONS, MatRipple, RippleRef, RippleRenderer, RippleState, defaultRippleAnimationConfig };
|
|
//# sourceMappingURL=_ripple-chunk.mjs.map
|
|
|