@sandlada/mdc
Version:
@sandlada/mdc is an open source component library that follows the Material Design 3 design specifications.
12 lines • 5.16 kB
JavaScript
import"../../node_modules/lit/index.js";import{Easing as e}from"../../node_modules/@sandlada/mdk/build/domain/easing.js";import"../../node_modules/@sandlada/mdk/build/index.js";
/**
* @license
* Copyright 2022 Google LLC
* SPDX-License-Identifier: Apache-2.0
* @link
* https://github.com/material-components/material-web/blob/main/ripple/internal/ripple.ts
*
* [Modified by Kai-Orion & Sandlada]
*/
const t={Inactive:0,TouchDelay:1,Holding:2,WaitingForClick:3},n={pressGrowMs:550,minimumPressMs:250,initialOriginScale:.2,padding:10,softEdgeMinimumSize:75,softEdgeContainerRadio:.35,animationFill:`forwards`,touchDelayMs:150},r=[`click`,`contextmenu`,`pointercancel`,`pointerdown`,`pointerenter`,`pointerleave`,`pointerup`,`focus`,`blur`];var i=class{constructor(e){this.state=t.Inactive,this.startEvent=null,this.checkBoundsAfterContextMenu=!1,this.initialSize=0,this.rippleScale=``,this.rippleSize=``,this.growAnimation=null,this.handleEvent=async e=>{switch(e.type){case`click`:this.handleClick();break;case`contextmenu`:this.handleContextmenu();break;case`pointercancel`:this.handlePointercancel(e);break;case`pointerdown`:await this.handlePointerdown(e);break;case`pointerenter`:this.handlePointerenter(e);break;case`pointerleave`:this.handlePointerleave(e);break;case`pointerup`:this.handlePointerup(e);break;case`focus`:this.handleFocus();break;case`blur`:this.handleBlur()}},this.host=e}onControlChange(e,t){for(let n of r)e?.removeEventListener(n,this.handleEvent),t?.addEventListener(n,this.handleEvent)}handlePointerenter(e){this.shouldReactToEvent(e)&&(this.host.hovered=!0)}handlePointerleave(e){this.shouldReactToEvent(e)&&(this.host.hovered=!1,this.state!==t.Inactive&&this.endPressAnimation())}handlePointerup(e){if(this.shouldReactToEvent(e)){if(this.state===t.Holding){this.state=t.WaitingForClick;return}if(this.state===t.TouchDelay){this.state=t.WaitingForClick,this.startPressAnimation(this.startEvent||void 0);return}}}async handlePointerdown(e){if(this.shouldReactToEvent(e)){if(this.startEvent=e,!this.isTouch(e)){this.state=t.WaitingForClick,this.startPressAnimation(e);return}this.checkBoundsAfterContextMenu&&!this.inBounds(e)||(this.checkBoundsAfterContextMenu=!1,this.state=t.TouchDelay,await new Promise(e=>{setTimeout(e,n.touchDelayMs)}),this.state===t.TouchDelay&&(this.state=t.Holding,this.startPressAnimation(e)))}}handlePointercancel(e){this.shouldReactToEvent(e)&&this.endPressAnimation()}handleClick(){if(!this.host.disabled){if(this.state===t.WaitingForClick){this.endPressAnimation();return}this.state===t.Inactive&&(this.startPressAnimation(),this.endPressAnimation())}}handleContextmenu(){this.host.disabled||(this.checkBoundsAfterContextMenu=!0,this.endPressAnimation())}handleFocus(){this.host.disabled||(this.host.focused=!0)}handleBlur(){this.host.disabled||(this.host.focused=!1,this.state!==t.Inactive&&this.endPressAnimation())}startPressAnimation(t){this.host.pressed=!0,this.growAnimation?.cancel(),this.determineRippleSize();let{startPoint:r,endPoint:i}=this.getTranslationCoordinates(t),a=`${r.x}px, ${r.y}px`,o=`${i.x}px, ${i.y}px`;this.host!==null&&(this.growAnimation=this.host.pressStateLayerElement.animate({top:[0,0],left:[0,0],height:[this.rippleSize,this.rippleSize],width:[this.rippleSize,this.rippleSize],transform:[`translate(${a}) scale(1)`,`translate(${o}) scale(${this.rippleScale})`]},{duration:n.pressGrowMs,easing:e.Standard.ToCSSValue(),fill:n.animationFill}))}getTranslationCoordinates(e){if(this.host===null)return;let{height:t,width:n}=this.host.getBoundingClientRect(),r={x:(n-this.initialSize)/2,y:(t-this.initialSize)/2},i={x:n/2,y:t/2};return e instanceof PointerEvent&&(i=this.getNormalizedPointerEventCoords(e)),i={x:i.x-this.initialSize/2,y:i.y-this.initialSize/2},{startPoint:i,endPoint:r}}getNormalizedPointerEventCoords(e){if(this.host===null)return;let{scrollX:t,scrollY:n}=window,{left:r,top:i}=this.host.getBoundingClientRect(),a=t+r,o=n+i,{pageX:s,pageY:c}=e;return{x:s-a,y:c-o}}async endPressAnimation(){this.state=t.Inactive;let e=this.growAnimation,r=1/0;if(typeof e?.currentTime==`number`?r=e.currentTime:e?.currentTime&&(r=e.currentTime.to(`ms`).value),r>=n.minimumPressMs){this.host.pressed=!1;return}await new Promise(e=>{setTimeout(e,n.minimumPressMs-r)}),this.growAnimation===e&&(this.host.pressed=!1)}determineRippleSize(){if(this.host===null)return;let{height:e,width:t}=this.host.getBoundingClientRect(),r=Math.max(e,t),i=Math.max(n.softEdgeContainerRadio*r,n.softEdgeMinimumSize),a=Math.floor(r*n.initialOriginScale),o=Math.sqrt(t**2+e**2)+n.padding;this.initialSize=a,this.rippleScale=`${(o+i)/this.initialSize}`,this.rippleSize=`${this.initialSize}px`}inBounds({x:e,y:t}){if(this.host===null)return;let{top:n,left:r,bottom:i,right:a}=this.host.getBoundingClientRect();return e>=r&&e<=a&&t>=n&&t<=i}isTouch({pointerType:e}){return e===`touch`}shouldReactToEvent(e){if(this.host.disabled||!e.isPrimary||this.startEvent&&this.startEvent.pointerId!==e.pointerId)return!1;if(e.type===`pointerenter`||e.type===`pointerleave`)return!this.isTouch(e);let t=e.buttons===1;return this.isTouch(e)||t}};export{i as RippleAction};
//# sourceMappingURL=ripple-action.js.map