web-touch-ripple
Advanced tools
Comparing version 1.2.31 to 1.3.0
@@ -39,2 +39,6 @@ # 1.1.20 | ||
# 1.2.30 | ||
- Fixed an issue where applying overflow: hidden to ensure that the touch ripple effect was confined within the child elements caused significant rendering performance degradation. The solution now avoids applying this style when the effect is not present or active, resulting in a substantial performance improvement. | ||
- Fixed an issue where applying overflow: hidden to ensure that the touch ripple effect was confined within the child elements caused significant rendering performance degradation. The solution now avoids applying this style when the effect is not present or active, resulting in a substantial performance improvement. | ||
# 1.3.0 | ||
- Fixed an issue where, in a gesture arena, if competing gestures (e.g., double-tap and long-tap) were present, the scenario where a gesture should ultimately win after pointer up, even if the competing gestures lose, was not being correctly handled. | ||
- Fixed an issue where using elements like `<div class="ripple">`, which could lead to duplication, was replaced with a custom element like `<touch-ripple-effect>` to manage its own animation and DOM tree removal. |
@@ -1,2 +0,2 @@ | ||
class t{static initialize(){const t=new CSSStyleSheet;t.insertRule("\n touch-ripple, touch-ripple-connection {\n /* \n * Defines the element to avoid having a separate stylesheet, thereby\n * addressing style issues caused by touch ripple wrapping.\n * For example, if the parent element has its own stylesheet,\n * the size of the child element might be affected as a result.\n */\n display: contents;\n\n /*\n * Needs to remove effects that interfere with touch ripple on\n * touch-based devices, such as in mobile environments.\n */\n -webkit-tap-highlight-color: transparent;\n }\n "),t.insertRule("\n touch-ripple *:has(> touch-ripple-effect-hover),\n touch-ripple *:has(> .ripple) {\n position: relative;\n overflow: hidden;\n user-select: none;\n touch-action: manipulation;\n }\n "),document.adoptedStyleSheets=[...document.adoptedStyleSheets,t]}}var e,i,s;!function(t){t.DOWN="down",t.MOVE="move",t.UP="up",t.CANCEL="cancel"}(e||(e={})),function(t){t[t.ACCEPT=0]="ACCEPT",t[t.REJECT=1]="REJECT",t[t.UPDATE=2]="UPDATE"}(i||(i={}));class n{constructor(){this.listeners=[],this.isHold=!1}accept(){this.perform(i.ACCEPT),this.onAccept()}reject(){this.perform(i.REJECT),this.onReject()}hold(){this.isHold=!0,this.listeners.forEach((t=>t(i.UPDATE)))}release(){this.isHold=!1,this.listeners.forEach((t=>t(i.UPDATE)))}onAccept(){}onReject(){}dispose(){}perform(t){this.dispose(),this.listeners.forEach((e=>e(t)))}}class r extends n{constructor(){super()}createPosition(t){return{x:t.clientX,y:t.clientY}}handlePointer(t,i){const s=this.position=this.createPosition(t);if(t.button>0)return this.reject();i==e.DOWN&&this.pointerDown(s),i==e.MOVE&&this.pointerMove(s),i==e.UP&&this.pointerUp(s),i==e.CANCEL&&(this.reject(),this.pointerCancel(s))}pointerDown(t){}pointerMove(t){}pointerUp(t){}pointerCancel(t){}}class o{constructor(t){this.option=t,this.builders=[],this.recognizers=[],this.option=Object.assign({isKeepAliveLastPointerUp:!0},this.option)}registerBuilder(t){this.builders.push(t)}attach(t){this.recognizers.push(t)}detach(t){this.recognizers=this.recognizers.filter((e=>e!=t))}rejectBy(t){this.detach(t),this.checkCycle()}acceptBy(t){this.recognizers.forEach((e=>e!=t?e.reject():void 0)),this.recognizers=[]}reset(){this.builders=[],this.recognizers=[]}createRecognizer(t){const e=t();return e.listeners.push((t=>{switch(t){case i.REJECT:this.rejectBy(e);break;case i.ACCEPT:this.acceptBy(e);break;case i.UPDATE:this.checkCycle()}})),e}checkCycle(t){if(this.option.isKeepAliveLastPointerUp&&(t==e.UP||null==t)&&1==this.recognizers.length){const t=this.recognizers[0];t.isHold||t.accept()}}handlePointer(t,i){i==e.DOWN&&0==this.recognizers.length&&(this.recognizers=this.builders.map((t=>this.createRecognizer(t)))),this.recognizers.forEach((e=>e.handlePointer(t,i))),this.checkCycle(i)}}class a extends r{constructor(t,e,i,s,n,r){super(),this.onTap=t,this.onTapRejectable=e,this.onTapAccept=i,this.onTapReject=s,this.rejectableDuration=n,this.tappableDuration=r,this.timerIds=[],this.isRejectable=!1}pointerDown(t){const e=()=>{this.isRejectable=!0,this.onTapRejectable(t)};this.rejectableDuration!=1/0&&this.timerIds.push(setTimeout(e,this.rejectableDuration)),0!=this.tappableDuration&&this.timerIds.push(setTimeout(this.reject.bind(this),this.tappableDuration))}dispose(){this.timerIds.forEach((t=>clearTimeout(t))),this.timerIds=null}onAccept(){this.isRejectable?this.onTapAccept(this.position):this.onTap(this.position)}onReject(){this.isRejectable&&this.onTapReject(this.position)}toString(){return"[Object TapGestureRecognizer]"}}class l extends r{constructor(t,e){super(),this.onDoubleTap=t,this.doubleTappableDuration=e,this.tapCount=0}pointerDown(t){2==++this.tapCount?this.accept():(this.hold(),setTimeout((()=>this.reject()),this.doubleTappableDuration))}onAccept(){this.onDoubleTap(this.position)}dispose(){null!=this.timeId&&clearTimeout(this.timeId)}toString(){return"[Object DoubleTapGestureRecognizer]"}}class h extends r{constructor(t,e,i,s,n){super(),this.onLongTapStart=t,this.onLongTapEnd=e,this.onLongTap=i,this.tappableDuration=s,this.longtappableDuration=n,this.isStartCalled=!1}pointerDown(t){this.isHold=!0,this.timerId=setTimeout((()=>{this.isStartCalled=!0,this.onLongTapStart(t),this.timerId=setTimeout((()=>{this.accept(),this.onLongTap()}),this.longtappableDuration)}),this.tappableDuration)}pointerUp(t){this.reject()}onReject(){this.isStartCalled&&this.onLongTapEnd()}dispose(){null!=this.timerId&&clearTimeout(this.timerId)}toString(){return"[Object LongTapGestureRecognizer]"}}class p{constructor(t,e){this.x=t,this.y=e}distance(t,e){let i=this.x-t,s=this.y-e;return Math.sqrt(i*i+s*s)}}class c{static sizeOf(t){const e=parseFloat(t.width),i=parseFloat(t.height);return{width:e+parseFloat(t.paddingLeft)+parseFloat(t.paddingRight),height:i+parseFloat(t.paddingTop)+parseFloat(t.paddingBottom)}}}!function(t){t[t.NONE=0]="NONE",t[t.ACCEPTED=1]="ACCEPTED",t[t.REJECTED=2]="REJECTED",t[t.DISPOSED=3]="DISPOSED"}(s||(s={}));class u extends HTMLElement{constructor(t,e,i,s,n,r,o){var a;super(),this.position=t,this.callback=e,this.isRejectable=i,this.isWait=s,this.option=n,this.parent=r,this.target=o,this._statusListeners=[],null!==(a=this.target)&&void 0!==a||(this.target=this.parent.firstElementChild)}get status(){return this._status}set status(t){this._status!=t&&(this._status=t,this._statusListeners.forEach((e=>e(t))))}set statusListener(t){this._statusListeners.push(t)}notify(){this.callback&&this.callback()}fadeout(t,e=this._ripple){null!=t&&null!=e&&(e.style.transitionProperty="opacity",e.style.transitionDuration=this.option.fadeOutDuration,e.style.transitionTimingFunction=this.option.fadeOutCurve,e.style.opacity="0",requestAnimationFrame((()=>{e.ontransitionend=()=>t.removeChild(e)})),this.dispose())}cancel(t,e=this._ripple){null!=t&&null!=e&&(e.style.transitionProperty="opacity",e.style.transitionDuration="var(--ripple-cancel-duration, 0s)",e.style.transitionTimingFunction="var(--ripple-cancel-curve)",e.style.opacity="0",requestAnimationFrame((()=>{e.ontransitionend=()=>t.removeChild(e)})),this.dispose())}createElement(t,e){const i=e.getBoundingClientRect(),n=getComputedStyle(e),r=c.sizeOf(n),o=parseFloat(n.marginLeft),a=parseFloat(n.marginTop),l=Math.max(r.width,r.height),h=this.position.x-i.left-o,u=this.position.y-i.top-a,d=r.width/2,f=r.height/2;let m=0,E=0;const g=()=>{++E==m&&(this.fadeout(e),this.isWait&&this.notify(),C.ontransitionend=null)};var v=t.getPropertyByName("--ripple-blur-radius")||"6%";if(v.endsWith("%")){const t=Number(v.replace("%",""))/100;var y=Number(l*t)}else y=Number(v.replace("px",""));let b=2*new p(d,f).distance(0,0);b+=2*new p(d,f).distance(h,u),b+=2*y,this._ripple=document.createElement("div");const C=this._ripple;C.classList.add("ripple"),C.style.position="absolute",C.style.left=`${h}px`,C.style.top=`${u}px`,C.style.width=`${b}px`,C.style.height=`${b}px`,C.style.pointerEvents="none",C.style.translate="-50% -50%",C.style.borderRadius="50%",C.style.backgroundColor="var(--ripple, rgba(0, 0, 0, 0.2))",C.style.filter=`blur(${y}px)`,C.style.opacity="0",C.style.transform="scale(var(--ripple-lower-scale, 0.3))",C.style.transformOrigin="center",C.style.transitionProperty="opacity, transform",C.style.transitionDuration=`${this.option.fadeInDuration}, ${this.option.spreadDuration}`,C.style.transitionTimingFunction=`${this.option.fadeInCurve}, ${this.option.spreadCurve}`,queueMicrotask((()=>{C.getBoundingClientRect(),C.style.opacity="1",C.style.transform="scale(var(--ripple-upper-scale, 1))"})),C.addEventListener("transitionstart",(()=>{m+=1}));let D=!1;return C.addEventListener("transitionend",(()=>{D=!0})),this.isRejectable?this.statusListener=t=>{if(t==s.REJECTED&&this.fadeout(e),t==s.ACCEPTED){if(D)return this.notify(),this.fadeout(e);0==this.isWait&&this.notify(),C.ontransitionend=g}}:(0==this.isWait&&this.notify(),C.ontransitionend=g),C}dispose(){this.status=s.DISPOSED,this._statusListeners=null,this._ripple=null}}customElements.define("touch-ripple-effect",u);class d extends HTMLElement{static ancestorOf(t){let e=t.parentElement;for(;e;){if(e instanceof d)return e;e=e.parentElement}}}customElements.define("touch-ripple-connection",d);class f extends HTMLElement{constructor(){super(...arguments),this.arena=new o({isKeepAliveLastPointerUp:!0})}set ontap(t){this._ontap=t,this.initBuiler()}set ondoubletap(t){this._ondoubletap=t,this.initBuiler()}set onlongtap(t){this._onlongtap=t,this.initBuiler()}get child(){var t;const e=this.getAttribute("selector");return e&&null!==(t=this.querySelector(e))&&void 0!==t?t:this.firstElementChild}getPropertyByName(t,e=this){return getComputedStyle(e).getPropertyValue(t)}getDurationByName(t,e=this){const i=this.getPropertyByName(t,e);return""==i||"none"==i?null:i.endsWith("ms")?Number(i.replace("ms","")):1e3*Number(i.replace("s",""))}getBooleanByName(t,e=this){const i=this.getPropertyByName(t,e);if(""!=i)return"1"==i}initBuiler(){var t,e,i,n;this.arena.reset();const r=null!==(t=this.getDurationByName("--ripple-tap-preview-duration"))&&void 0!==t?t:150;if(null!=this._ontap){const t=null!==(e=this.getDurationByName("--ripple-tappable-duration"))&&void 0!==e?e:0,i=null!=this._onlongtap?0:r;this.arena.registerBuilder((()=>{let e=null;return new a((t=>e=this.createEffect(t,this._ontap,!1)),(t=>e=this.createEffect(t,this._ontap,!0)),(()=>e.status=s.ACCEPTED),(()=>e.status=s.REJECTED),i,t)}))}if(null!=this._ondoubletap){const t=null!==(i=this.getDurationByName("--ripple-double-tappable-duration"))&&void 0!==i?i:300;this.arena.registerBuilder((()=>new l((t=>this.createEffect(t,this._ondoubletap,!1)),t)))}if(null!=this._onlongtap){const t=null!==(n=this.getDurationByName("--ripple-long-tappable-duration"))&&void 0!==n?n:1e3;this.arena.registerBuilder((()=>{let e=null;return new h((t=>e=this.createEffect(t,this._onlongtap,!0,{spreadDuration:"var(--ripple-long-tappable-duration, 1s)",fadeInDuration:"var(--ripple-long-tappable-duration, 1s)",spreadCurve:"var(--ripple-long-tappable-curve, linear(0, 1))",fadeInCurve:"var(--ripple-long-tappable-curve, linear(0, 1))"})),(()=>e.status=s.REJECTED),(()=>e.status=s.ACCEPTED),r,t)}))}}initPointerEvent(t){var i;const s=null===(i=this.getBooleanByName("--ripple-use-hover"))||void 0===i||i;t.onpointerdown=t=>this.arena.handlePointer(t,e.DOWN),t.onpointermove=t=>this.arena.handlePointer(t,e.MOVE),t.onpointerup=t=>this.arena.handlePointer(t,e.UP),t.onpointercancel=t=>this.arena.handlePointer(t,e.CANCEL),t.onpointerleave=t=>this.arena.handlePointer(t,e.CANCEL),t.onmouseleave=t=>this.arena.handlePointer(t,e.CANCEL),!("ontouchstart"in window)&&s&&(t.onmouseenter=()=>this.onHoverStart(),t.onmouseleave=()=>this.onHoverEnd())}connectedCallback(){requestAnimationFrame((()=>{let t=this.child;if(null==t)throw"This element must be exists child element.";let e=d.ancestorOf(this);e?this.initPointerEvent(e):this.initPointerEvent(t)}))}createHoverElement(){return document.createElement("touch-ripple-effect-hover")}onHoverStart(){const t=this.child;null==this.hoverEffectElement&&t.appendChild(this.hoverEffectElement=this.createHoverElement()),this.hoverEffectElement.ontransitionend=null,this.hoverEffectElement.getBoundingClientRect(),this.hoverEffectElement.style.opacity="1"}onHoverEnd(){if(this.hoverEffectElement){const t=this.hoverEffectElement;t.style.opacity="0",t.ontransitionend=()=>{this.child.removeChild(t),this.hoverEffectElement=null}}}createEffect(t,e,i,s){var n,r;const o=null!==(n=this.getPropertyByName("--ripple-overlap-behavior"))&&void 0!==n?n:"overlappable";if('"cancel"'==o)null===(r=this.activeEffect)||void 0===r||r.cancel(this.child);else if('"ignoring"'==o&&null!=this.activeEffect)return;const a=Object.assign({spreadDuration:"var(--ripple-spread-duration, 0.3s)",spreadCurve:"var(--ripple-spread-curve, cubic-bezier(.2,.3,.4,1))",fadeInDuration:"var(--ripple-fadein-duration, 0.15s)",fadeInCurve:"var(--ripple-fadein-curve)",fadeOutDuration:"var(--ripple-fadeout-duration, 0.3s)",fadeOutCurve:"var(--ripple-fadeout-curve, cubic-bezier(.15,.5,.5,1))"},s),l=new u(t,e,i,this.hasAttribute("wait"),a,this);return this.child.appendChild(l.createElement(this,this.child)),l}static get observedAttributes(){return["ontap","ondoubletap","onlongtap"]}attributeChangedCallback(t,e,i){if(null!=i){const e=new Function(i);"ontap"==t&&(this.ontap=e),"ondoubletap"==t&&(this.ondoubletap=e),"onlongtap"==t&&(this.onlongtap=e)}}}customElements.define("touch-ripple",f);class m extends HTMLElement{connectedCallback(){this.style.position="absolute",this.style.top="0px",this.style.left="0px",this.style.width="100%",this.style.height="100%",this.style.backgroundColor="var(--ripple-hover, rgba(0, 0, 0, 0.1))",this.style.opacity="0",this.style.transitionProperty="opacity",this.style.transitionDuration="var(--ripple-hover-duration, 0.25s)",this.style.pointerEvents="none"}}customElements.define("touch-ripple-effect-hover",m),addEventListener("DOMContentLoaded",(()=>t.initialize()));export{o as GestureArena,n as GestureRecognizer,t as TouchRippleBinding,d as TouchRippleConnectionElement,u as TouchRippleEffectElement,m as TouchRippleEffectHoverElement,f as TouchRippleElement}; | ||
class t{constructor(){}static get instance(){var e;return null!==(e=this._instance)&&void 0!==e?e:this._instance=new t}initialize(){const t=new CSSStyleSheet;t.insertRule("\n touch-ripple, touch-ripple-connection {\n /* \n * Defines the element to avoid having a separate stylesheet, thereby\n * addressing style issues caused by touch ripple wrapping.\n * For example, if the parent element has its own stylesheet,\n * the size of the child element might be affected as a result.\n */\n display: contents;\n\n /*\n * Needs to remove effects that interfere with touch ripple on\n * touch-based devices, such as in mobile environments.\n */\n -webkit-tap-highlight-color: transparent;\n }\n "),t.insertRule("\n touch-ripple *:has(> touch-ripple-effect),\n touch-ripple *:has(> touch-ripple-effect-hover) {\n position: relative;\n overflow: hidden;\n user-select: none;\n touch-action: manipulation;\n }\n "),document.adoptedStyleSheets=[...document.adoptedStyleSheets,t]}}var e,i,s;!function(t){t.DOWN="down",t.MOVE="move",t.UP="up",t.CANCEL="cancel"}(e||(e={})),function(t){t[t.ACCEPT=0]="ACCEPT",t[t.REJECT=1]="REJECT",t[t.UPDATE=2]="UPDATE"}(i||(i={}));class n{constructor(){this.listeners=[],this.isHold=!1}accept(){this.perform(i.ACCEPT),this.onAccept()}reject(){this.perform(i.REJECT),this.onReject()}hold(){this.isHold=!0,this.listeners.forEach((t=>t(i.UPDATE)))}release(){this.isHold=!1,this.listeners.forEach((t=>t(i.UPDATE)))}onAccept(){}onReject(){}dispose(){}perform(t){this.dispose(),this.listeners.forEach((e=>e(t)))}}class r extends n{constructor(){super()}createPosition(t){return{x:t.clientX,y:t.clientY}}handlePointer(t,i){const s=this.position=this.createPosition(t);if(t.button>0)return this.reject();i==e.DOWN&&this.pointerDown(s),i==e.MOVE&&this.pointerMove(s),i==e.UP&&this.pointerUp(s),i==e.CANCEL&&(this.reject(),this.pointerCancel(s))}pointerDown(t){}pointerMove(t){}pointerUp(t){}pointerCancel(t){}}class o{constructor(t){this.option=t,this.builders=[],this.recognizers=[],this.option=Object.assign({isKeepAliveLastPointerUp:!0},this.option)}registerBuilder(t){this.builders.push(t)}attach(t){this.recognizers.push(t)}detach(t){this.recognizers=this.recognizers.filter((e=>e!=t))}rejectBy(t){this.detach(t),this.checkCycle()}acceptBy(t){this.recognizers.forEach((e=>e!=t?e.reject():void 0)),this.recognizers=[]}reset(){this.builders=[],this.recognizers=[]}createRecognizer(t){const e=t();return e.listeners.push((t=>{switch(t){case i.REJECT:this.rejectBy(e);break;case i.ACCEPT:this.acceptBy(e);break;case i.UPDATE:this.checkCycle()}})),e}checkCycle(t){if(this.option.isKeepAliveLastPointerUp&&(t==e.UP||!t)&&1==this.recognizers.length){const t=this.recognizers[0];t.isHold||t.accept()}}handlePointer(t,i){i==e.DOWN&&0==this.recognizers.length&&(this.recognizers=this.builders.map((t=>this.createRecognizer(t)))),this.recognizers.forEach((e=>e.handlePointer(t,i))),this.checkCycle(i)}}class a extends r{constructor(t,e,i,s,n,r){super(),this.onTap=t,this.onTapRejectable=e,this.onTapAccept=i,this.onTapReject=s,this.rejectableDuration=n,this.tappableDuration=r,this.timerIds=[],this.isRejectable=!1}pointerDown(t){const e=()=>{this.isRejectable=!0,this.onTapRejectable(t)};this.hold(),this.rejectableDuration!=1/0&&this.timerIds.push(setTimeout(e,this.rejectableDuration)),0!=this.tappableDuration&&this.timerIds.push(setTimeout(this.reject.bind(this),this.tappableDuration))}pointerUp(t){this.release()}dispose(){this.timerIds.forEach((t=>clearTimeout(t))),this.timerIds=null}onAccept(){this.isRejectable?this.onTapAccept(this.position):this.onTap(this.position)}onReject(){this.isRejectable&&this.onTapReject(this.position)}toString(){return"[Object TapGestureRecognizer]"}}class h extends r{constructor(t,e){super(),this.onDoubleTap=t,this.doubleTappableDuration=e,this.tapCount=0}pointerDown(t){2==++this.tapCount?this.accept():(this.hold(),setTimeout((()=>this.reject()),this.doubleTappableDuration))}onAccept(){this.onDoubleTap(this.position)}dispose(){null!=this.timeId&&clearTimeout(this.timeId)}toString(){return"[Object DoubleTapGestureRecognizer]"}}class l extends r{constructor(t,e,i,s,n){super(),this.onLongTapStart=t,this.onLongTapEnd=e,this.onLongTap=i,this.tappableDuration=s,this.longtappableDuration=n,this.isStartCalled=!1}pointerDown(t){this.isHold=!0,this.timerId=setTimeout((()=>{this.isStartCalled=!0,this.onLongTapStart(t),this.timerId=setTimeout((()=>{this.accept(),this.onLongTap()}),this.longtappableDuration)}),this.tappableDuration)}pointerUp(t){this.reject()}onReject(){this.isStartCalled&&this.onLongTapEnd()}dispose(){null!=this.timerId&&clearTimeout(this.timerId)}toString(){return"[Object LongTapGestureRecognizer]"}}Object.defineProperty(Element.prototype,"intrinsicSize",{get:function(){return p.intrinsicSizeOf(this)}}),Object.defineProperty(Element.prototype,"intrinsicWidth",{get:function(){return p.intrinsicSizeOf(this).width}}),Object.defineProperty(Element.prototype,"intrinsicHeight",{get:function(){return p.intrinsicSizeOf(this).height}}),Object.defineProperty(Element.prototype,"reflow",{get:function(){return p.reflow(this)}});class p{static reflow(t){t.getBoundingClientRect()}static intrinsicSizeOf(t,e){for(;t;){const i=null!=e?e:getComputedStyle(t),s=parseFloat(i.width),n=parseFloat(i.height),r=parseFloat(i.paddingLeft),o=parseFloat(i.paddingRight),a=parseFloat(i.paddingTop),h=parseFloat(i.paddingBottom),l=parseFloat(i.borderLeftWidth),p=parseFloat(i.borderRightWidth),c=parseFloat(i.borderTopWidth),u=parseFloat(i.borderBottomWidth),d=parseFloat(i.marginLeft),f=parseFloat(i.marginRight),g=parseFloat(i.marginTop),m=parseFloat(i.marginBottom),E=i.boxSizing,y=i.position;if("contents"===i.display){let e=Array.from(t.children).filter((t=>"STYLE"!==t.tagName&&"SCRIPT"!==t.tagName));if(1!==e.length)throw new Error("An element with a display property of 'contents' must have only one child to define its intrinsic size.");t=e[0];continue}let v=s,b=n;return"content-box"===E&&(v+=r+o+l+p,b+=a+h+c+u),"absolute"!==y&&"fixed"!==y&&(v+=d+f,b+=g+m),{width:v,height:b}}}}Object.defineProperty(Element.prototype,"intrinsicRect",{get:function(){return c.intrinsicOf(this)}});class c{static intrinsicOf(t,e){const i=null!=e?e:getComputedStyle(t),s=p.intrinsicSizeOf(t,i),n=t.getBoundingClientRect();return new DOMRect(n.x,n.y,s.width,s.height)}}class u{constructor(t,e){this.x=t,this.y=e}distance(t,e){let i=this.x-t,s=this.y-e;return Math.sqrt(i*i+s*s)}}!function(t){t[t.NONE=0]="NONE",t[t.ACCEPTED=1]="ACCEPTED",t[t.REJECTED=2]="REJECTED",t[t.DISPOSED=3]="DISPOSED"}(s||(s={}));class d extends HTMLElement{constructor(t,e,i,s,n,r,o){var a;super(),this.position=t,this.callback=e,this.isRejectable=i,this.isWait=s,this.option=n,this.parent=r,this.target=o,this._statusListeners=[],null!==(a=this.target)&&void 0!==a||(this.target=this.parent.firstElementChild)}get status(){return this._status}set status(t){this._status!=t&&(this._status=t,this._statusListeners.forEach((e=>e(t))))}set statusListener(t){this._statusListeners.push(t)}notify(){this.callback&&this.callback()}fadeout(t=this.parent){null!=t&&(this.style.transitionProperty="opacity",this.style.transitionDuration=this.option.fadeOutDuration,this.style.transitionTimingFunction=this.option.fadeOutCurve,this.style.opacity="0",requestAnimationFrame((()=>{this.ontransitionend=()=>this.dispose()})))}cancel(t=this.parent){null!=t&&(this.style.transitionProperty="opacity",this.style.transitionDuration="var(--ripple-cancel-duration, 0s)",this.style.transitionTimingFunction="var(--ripple-cancel-curve)",this.style.opacity="0",requestAnimationFrame((()=>{this.ontransitionend=()=>this.dispose()})))}connectedCallback(){const t=this.target,e=this.parent,i=getComputedStyle(t),n=c.intrinsicOf(t,i),r={width:n.width,height:n.height},o=parseFloat(i.marginLeft),a=parseFloat(i.marginTop),h=Math.max(r.width,r.height),l=this.position.x-n.left-o,p=this.position.y-n.top-a,d=r.width/2,f=r.height/2;let g=0,m=0;const E=()=>{++m==g&&(this.fadeout(t),this.isWait&&this.notify(),this.ontransitionend=null)};var y=e.getPropertyByName("--ripple-blur-radius")||"6%";if(y.endsWith("%")){const t=Number(y.replace("%",""))/100;var v=Number(h*t)}else v=Number(y.replace("px",""));let b=2*new u(d,f).distance(0,0);b+=2*new u(d,f).distance(l,p),b+=2*v,this.style.position="absolute",this.style.left=`${l}px`,this.style.top=`${p}px`,this.style.width=`${b}px`,this.style.height=`${b}px`,this.style.pointerEvents="none",this.style.translate="-50% -50%",this.style.borderRadius="50%",this.style.backgroundColor="var(--ripple, rgba(0, 0, 0, 0.2))",this.style.filter=`blur(${v}px)`,this.style.opacity="0",this.style.transform="scale(var(--ripple-lower-scale, 0.3))",this.style.transformOrigin="center",requestAnimationFrame((()=>{this.style.transitionProperty="opacity, transform",this.style.transitionDuration=`${this.option.fadeInDuration}, ${this.option.spreadDuration}`,this.style.transitionTimingFunction=`${this.option.fadeInCurve}, ${this.option.spreadCurve}`,this.style.opacity="1",this.style.transform="scale(var(--ripple-upper-scale, 1))"})),this.addEventListener("transitionstart",(()=>{g+=1}));let C=!1;this.addEventListener("transitionend",(()=>{C=!0})),this.isRejectable?this.statusListener=e=>{if(e==s.REJECTED&&this.fadeout(t),e==s.ACCEPTED){if(C)return this.notify(),this.fadeout(t);0==this.isWait&&this.notify(),this.ontransitionend=E}}:(0==this.isWait&&this.notify(),this.ontransitionend=E)}dispose(){this.status=s.DISPOSED,this._statusListeners=null,this.remove()}}customElements.define("touch-ripple-effect",d);class f extends HTMLElement{static ancestorOf(t){let e=t.parentElement;for(;e;){if(e instanceof f)return e;e=e.parentElement}}}customElements.define("touch-ripple-connection",f);class g extends HTMLElement{constructor(){super(...arguments),this.arena=new o({isKeepAliveLastPointerUp:!0})}set ontap(t){this._ontap=t,this.initBuiler()}set ondoubletap(t){this._ondoubletap=t,this.initBuiler()}set onlongtap(t){this._onlongtap=t,this.initBuiler()}get child(){var t;const e=this.getAttribute("selector");return e&&null!==(t=this.querySelector(e))&&void 0!==t?t:this.firstElementChild}getPropertyByName(t,e=this){return getComputedStyle(e).getPropertyValue(t)}getDurationByName(t,e=this){const i=this.getPropertyByName(t,e);return""==i||"none"==i?null:i.endsWith("ms")?Number(i.replace("ms","")):1e3*Number(i.replace("s",""))}getBooleanByName(t,e=this){const i=this.getPropertyByName(t,e);if(""!=i)return"1"==i}initBuiler(){var t,e,i,n;this.arena.reset();const r=null!==(t=this.getDurationByName("--ripple-tap-preview-duration"))&&void 0!==t?t:150;if(null!=this._ontap){const t=null!==(e=this.getDurationByName("--ripple-tappable-duration"))&&void 0!==e?e:0,i=this._onlongtap||this._ondoubletap?1/0:r;this.arena.registerBuilder((()=>{let e=null;return new a((t=>e=this.createEffect(t,this._ontap,!1)),(t=>e=this.createEffect(t,this._ontap,!0)),(()=>e.status=s.ACCEPTED),(()=>e.status=s.REJECTED),i,t)}))}if(null!=this._ondoubletap){const t=null!==(i=this.getDurationByName("--ripple-double-tappable-duration"))&&void 0!==i?i:300;this.arena.registerBuilder((()=>new h((t=>this.createEffect(t,this._ondoubletap,!1)),t)))}if(null!=this._onlongtap){const t=null!==(n=this.getDurationByName("--ripple-long-tappable-duration"))&&void 0!==n?n:1e3;this.arena.registerBuilder((()=>{let e=null;return new l((t=>e=this.createEffect(t,this._onlongtap,!0,{spreadDuration:"var(--ripple-long-tappable-duration, 1s)",fadeInDuration:"var(--ripple-long-tappable-duration, 1s)",spreadCurve:"var(--ripple-long-tappable-curve, linear(0, 1))",fadeInCurve:"var(--ripple-long-tappable-curve, linear(0, 1))"})),(()=>e.status=s.REJECTED),(()=>e.status=s.ACCEPTED),r,t)}))}}initPointerEvent(t){var i;const s=null===(i=this.getBooleanByName("--ripple-use-hover"))||void 0===i||i;t.onpointerdown=t=>this.arena.handlePointer(t,e.DOWN),t.onpointermove=t=>this.arena.handlePointer(t,e.MOVE),t.onpointerup=t=>this.arena.handlePointer(t,e.UP),t.onpointercancel=t=>this.arena.handlePointer(t,e.CANCEL),t.onpointerleave=t=>this.arena.handlePointer(t,e.CANCEL),t.onmouseleave=t=>this.arena.handlePointer(t,e.CANCEL),!("ontouchstart"in window)&&s&&(t.onmouseenter=()=>this.onHoverStart(),t.onmouseleave=()=>this.onHoverEnd())}connectedCallback(){requestAnimationFrame((()=>{let t=this.child;if(null==t)throw"This element must be exists child element.";let e=f.ancestorOf(this);e?this.initPointerEvent(e):this.initPointerEvent(t)}))}createHoverElement(){return document.createElement("touch-ripple-effect-hover")}onHoverStart(){const t=this.child;null==this.hoverEffectElement&&t.appendChild(this.hoverEffectElement=this.createHoverElement()),this.hoverEffectElement.ontransitionend=null,this.hoverEffectElement.getBoundingClientRect(),this.hoverEffectElement.style.opacity="1"}onHoverEnd(){if(this.hoverEffectElement){const t=this.hoverEffectElement;t.style.opacity="0",t.ontransitionend=()=>{this.child.removeChild(t),this.hoverEffectElement=null}}}createEffect(t,e,i,s){var n,r;const o=null!==(n=this.getPropertyByName("--ripple-overlap-behavior"))&&void 0!==n?n:"overlappable";if('"cancel"'==o)null===(r=this.activeEffect)||void 0===r||r.cancel(this.child);else if('"ignoring"'==o&&null!=this.activeEffect)return;const a=Object.assign({spreadDuration:"var(--ripple-spread-duration, 0.3s)",spreadCurve:"var(--ripple-spread-curve, cubic-bezier(.2,.3,.4,1))",fadeInDuration:"var(--ripple-fadein-duration, 0.15s)",fadeInCurve:"var(--ripple-fadein-curve)",fadeOutDuration:"var(--ripple-fadeout-duration, 0.3s)",fadeOutCurve:"var(--ripple-fadeout-curve, cubic-bezier(.15,.5,.5,1))"},s),h=this.hasAttribute("wait"),l=new d(t,e,i,h,a,this,this.child);return this.child.appendChild(l),l}static get observedAttributes(){return["ontap","ondoubletap","onlongtap"]}attributeChangedCallback(t,e,i){if(null!=i){const e=new Function(i);"ontap"==t&&(this.ontap=e),"ondoubletap"==t&&(this.ondoubletap=e),"onlongtap"==t&&(this.onlongtap=e)}}}customElements.define("touch-ripple",g);class m extends HTMLElement{connectedCallback(){this.style.position="absolute",this.style.top="0px",this.style.left="0px",this.style.width="100%",this.style.height="100%",this.style.backgroundColor="var(--ripple-hover, rgba(0, 0, 0, 0.1))",this.style.opacity="0",this.style.transitionProperty="opacity",this.style.transitionDuration="var(--ripple-hover-duration, 0.25s)",this.style.pointerEvents="none"}}customElements.define("touch-ripple-effect-hover",m),addEventListener("DOMContentLoaded",(()=>t.instance.initialize()));export{o as GestureArena,n as GestureRecognizer,t as TouchRippleBinding,f as TouchRippleConnectionElement,d as TouchRippleEffectElement,m as TouchRippleEffectHoverElement,g as TouchRippleElement}; | ||
//# sourceMappingURL=index.esm.js.map |
@@ -1,2 +0,2 @@ | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).TouchRipple={})}(this,(function(t){"use strict";class e{static initialize(){const t=new CSSStyleSheet;t.insertRule("\n touch-ripple, touch-ripple-connection {\n /* \n * Defines the element to avoid having a separate stylesheet, thereby\n * addressing style issues caused by touch ripple wrapping.\n * For example, if the parent element has its own stylesheet,\n * the size of the child element might be affected as a result.\n */\n display: contents;\n\n /*\n * Needs to remove effects that interfere with touch ripple on\n * touch-based devices, such as in mobile environments.\n */\n -webkit-tap-highlight-color: transparent;\n }\n "),t.insertRule("\n touch-ripple *:has(> touch-ripple-effect-hover),\n touch-ripple *:has(> .ripple) {\n position: relative;\n overflow: hidden;\n user-select: none;\n touch-action: manipulation;\n }\n "),document.adoptedStyleSheets=[...document.adoptedStyleSheets,t]}}var i,s,n;!function(t){t.DOWN="down",t.MOVE="move",t.UP="up",t.CANCEL="cancel"}(i||(i={})),function(t){t[t.ACCEPT=0]="ACCEPT",t[t.REJECT=1]="REJECT",t[t.UPDATE=2]="UPDATE"}(s||(s={}));class o{constructor(){this.listeners=[],this.isHold=!1}accept(){this.perform(s.ACCEPT),this.onAccept()}reject(){this.perform(s.REJECT),this.onReject()}hold(){this.isHold=!0,this.listeners.forEach((t=>t(s.UPDATE)))}release(){this.isHold=!1,this.listeners.forEach((t=>t(s.UPDATE)))}onAccept(){}onReject(){}dispose(){}perform(t){this.dispose(),this.listeners.forEach((e=>e(t)))}}class r extends o{constructor(){super()}createPosition(t){return{x:t.clientX,y:t.clientY}}handlePointer(t,e){const s=this.position=this.createPosition(t);if(t.button>0)return this.reject();e==i.DOWN&&this.pointerDown(s),e==i.MOVE&&this.pointerMove(s),e==i.UP&&this.pointerUp(s),e==i.CANCEL&&(this.reject(),this.pointerCancel(s))}pointerDown(t){}pointerMove(t){}pointerUp(t){}pointerCancel(t){}}class a{constructor(t){this.option=t,this.builders=[],this.recognizers=[],this.option=Object.assign({isKeepAliveLastPointerUp:!0},this.option)}registerBuilder(t){this.builders.push(t)}attach(t){this.recognizers.push(t)}detach(t){this.recognizers=this.recognizers.filter((e=>e!=t))}rejectBy(t){this.detach(t),this.checkCycle()}acceptBy(t){this.recognizers.forEach((e=>e!=t?e.reject():void 0)),this.recognizers=[]}reset(){this.builders=[],this.recognizers=[]}createRecognizer(t){const e=t();return e.listeners.push((t=>{switch(t){case s.REJECT:this.rejectBy(e);break;case s.ACCEPT:this.acceptBy(e);break;case s.UPDATE:this.checkCycle()}})),e}checkCycle(t){if(this.option.isKeepAliveLastPointerUp&&(t==i.UP||null==t)&&1==this.recognizers.length){const t=this.recognizers[0];t.isHold||t.accept()}}handlePointer(t,e){e==i.DOWN&&0==this.recognizers.length&&(this.recognizers=this.builders.map((t=>this.createRecognizer(t)))),this.recognizers.forEach((i=>i.handlePointer(t,e))),this.checkCycle(e)}}class l extends r{constructor(t,e,i,s,n,o){super(),this.onTap=t,this.onTapRejectable=e,this.onTapAccept=i,this.onTapReject=s,this.rejectableDuration=n,this.tappableDuration=o,this.timerIds=[],this.isRejectable=!1}pointerDown(t){const e=()=>{this.isRejectable=!0,this.onTapRejectable(t)};this.rejectableDuration!=1/0&&this.timerIds.push(setTimeout(e,this.rejectableDuration)),0!=this.tappableDuration&&this.timerIds.push(setTimeout(this.reject.bind(this),this.tappableDuration))}dispose(){this.timerIds.forEach((t=>clearTimeout(t))),this.timerIds=null}onAccept(){this.isRejectable?this.onTapAccept(this.position):this.onTap(this.position)}onReject(){this.isRejectable&&this.onTapReject(this.position)}toString(){return"[Object TapGestureRecognizer]"}}class h extends r{constructor(t,e){super(),this.onDoubleTap=t,this.doubleTappableDuration=e,this.tapCount=0}pointerDown(t){2==++this.tapCount?this.accept():(this.hold(),setTimeout((()=>this.reject()),this.doubleTappableDuration))}onAccept(){this.onDoubleTap(this.position)}dispose(){null!=this.timeId&&clearTimeout(this.timeId)}toString(){return"[Object DoubleTapGestureRecognizer]"}}class p extends r{constructor(t,e,i,s,n){super(),this.onLongTapStart=t,this.onLongTapEnd=e,this.onLongTap=i,this.tappableDuration=s,this.longtappableDuration=n,this.isStartCalled=!1}pointerDown(t){this.isHold=!0,this.timerId=setTimeout((()=>{this.isStartCalled=!0,this.onLongTapStart(t),this.timerId=setTimeout((()=>{this.accept(),this.onLongTap()}),this.longtappableDuration)}),this.tappableDuration)}pointerUp(t){this.reject()}onReject(){this.isStartCalled&&this.onLongTapEnd()}dispose(){null!=this.timerId&&clearTimeout(this.timerId)}toString(){return"[Object LongTapGestureRecognizer]"}}class c{constructor(t,e){this.x=t,this.y=e}distance(t,e){let i=this.x-t,s=this.y-e;return Math.sqrt(i*i+s*s)}}class u{static sizeOf(t){const e=parseFloat(t.width),i=parseFloat(t.height);return{width:e+parseFloat(t.paddingLeft)+parseFloat(t.paddingRight),height:i+parseFloat(t.paddingTop)+parseFloat(t.paddingBottom)}}}!function(t){t[t.NONE=0]="NONE",t[t.ACCEPTED=1]="ACCEPTED",t[t.REJECTED=2]="REJECTED",t[t.DISPOSED=3]="DISPOSED"}(n||(n={}));class d extends HTMLElement{constructor(t,e,i,s,n,o,r){var a;super(),this.position=t,this.callback=e,this.isRejectable=i,this.isWait=s,this.option=n,this.parent=o,this.target=r,this._statusListeners=[],null!==(a=this.target)&&void 0!==a||(this.target=this.parent.firstElementChild)}get status(){return this._status}set status(t){this._status!=t&&(this._status=t,this._statusListeners.forEach((e=>e(t))))}set statusListener(t){this._statusListeners.push(t)}notify(){this.callback&&this.callback()}fadeout(t,e=this._ripple){null!=t&&null!=e&&(e.style.transitionProperty="opacity",e.style.transitionDuration=this.option.fadeOutDuration,e.style.transitionTimingFunction=this.option.fadeOutCurve,e.style.opacity="0",requestAnimationFrame((()=>{e.ontransitionend=()=>t.removeChild(e)})),this.dispose())}cancel(t,e=this._ripple){null!=t&&null!=e&&(e.style.transitionProperty="opacity",e.style.transitionDuration="var(--ripple-cancel-duration, 0s)",e.style.transitionTimingFunction="var(--ripple-cancel-curve)",e.style.opacity="0",requestAnimationFrame((()=>{e.ontransitionend=()=>t.removeChild(e)})),this.dispose())}createElement(t,e){const i=e.getBoundingClientRect(),s=getComputedStyle(e),o=u.sizeOf(s),r=parseFloat(s.marginLeft),a=parseFloat(s.marginTop),l=Math.max(o.width,o.height),h=this.position.x-i.left-r,p=this.position.y-i.top-a,d=o.width/2,f=o.height/2;let m=0,E=0;const g=()=>{++E==m&&(this.fadeout(e),this.isWait&&this.notify(),C.ontransitionend=null)};var v=t.getPropertyByName("--ripple-blur-radius")||"6%";if(v.endsWith("%")){const t=Number(v.replace("%",""))/100;var y=Number(l*t)}else y=Number(v.replace("px",""));let b=2*new c(d,f).distance(0,0);b+=2*new c(d,f).distance(h,p),b+=2*y,this._ripple=document.createElement("div");const C=this._ripple;C.classList.add("ripple"),C.style.position="absolute",C.style.left=`${h}px`,C.style.top=`${p}px`,C.style.width=`${b}px`,C.style.height=`${b}px`,C.style.pointerEvents="none",C.style.translate="-50% -50%",C.style.borderRadius="50%",C.style.backgroundColor="var(--ripple, rgba(0, 0, 0, 0.2))",C.style.filter=`blur(${y}px)`,C.style.opacity="0",C.style.transform="scale(var(--ripple-lower-scale, 0.3))",C.style.transformOrigin="center",C.style.transitionProperty="opacity, transform",C.style.transitionDuration=`${this.option.fadeInDuration}, ${this.option.spreadDuration}`,C.style.transitionTimingFunction=`${this.option.fadeInCurve}, ${this.option.spreadCurve}`,queueMicrotask((()=>{C.getBoundingClientRect(),C.style.opacity="1",C.style.transform="scale(var(--ripple-upper-scale, 1))"})),C.addEventListener("transitionstart",(()=>{m+=1}));let T=!1;return C.addEventListener("transitionend",(()=>{T=!0})),this.isRejectable?this.statusListener=t=>{if(t==n.REJECTED&&this.fadeout(e),t==n.ACCEPTED){if(T)return this.notify(),this.fadeout(e);0==this.isWait&&this.notify(),C.ontransitionend=g}}:(0==this.isWait&&this.notify(),C.ontransitionend=g),C}dispose(){this.status=n.DISPOSED,this._statusListeners=null,this._ripple=null}}customElements.define("touch-ripple-effect",d);class f extends HTMLElement{static ancestorOf(t){let e=t.parentElement;for(;e;){if(e instanceof f)return e;e=e.parentElement}}}customElements.define("touch-ripple-connection",f);class m extends HTMLElement{constructor(){super(...arguments),this.arena=new a({isKeepAliveLastPointerUp:!0})}set ontap(t){this._ontap=t,this.initBuiler()}set ondoubletap(t){this._ondoubletap=t,this.initBuiler()}set onlongtap(t){this._onlongtap=t,this.initBuiler()}get child(){var t;const e=this.getAttribute("selector");return e&&null!==(t=this.querySelector(e))&&void 0!==t?t:this.firstElementChild}getPropertyByName(t,e=this){return getComputedStyle(e).getPropertyValue(t)}getDurationByName(t,e=this){const i=this.getPropertyByName(t,e);return""==i||"none"==i?null:i.endsWith("ms")?Number(i.replace("ms","")):1e3*Number(i.replace("s",""))}getBooleanByName(t,e=this){const i=this.getPropertyByName(t,e);if(""!=i)return"1"==i}initBuiler(){var t,e,i,s;this.arena.reset();const o=null!==(t=this.getDurationByName("--ripple-tap-preview-duration"))&&void 0!==t?t:150;if(null!=this._ontap){const t=null!==(e=this.getDurationByName("--ripple-tappable-duration"))&&void 0!==e?e:0,i=null!=this._onlongtap?0:o;this.arena.registerBuilder((()=>{let e=null;return new l((t=>e=this.createEffect(t,this._ontap,!1)),(t=>e=this.createEffect(t,this._ontap,!0)),(()=>e.status=n.ACCEPTED),(()=>e.status=n.REJECTED),i,t)}))}if(null!=this._ondoubletap){const t=null!==(i=this.getDurationByName("--ripple-double-tappable-duration"))&&void 0!==i?i:300;this.arena.registerBuilder((()=>new h((t=>this.createEffect(t,this._ondoubletap,!1)),t)))}if(null!=this._onlongtap){const t=null!==(s=this.getDurationByName("--ripple-long-tappable-duration"))&&void 0!==s?s:1e3;this.arena.registerBuilder((()=>{let e=null;return new p((t=>e=this.createEffect(t,this._onlongtap,!0,{spreadDuration:"var(--ripple-long-tappable-duration, 1s)",fadeInDuration:"var(--ripple-long-tappable-duration, 1s)",spreadCurve:"var(--ripple-long-tappable-curve, linear(0, 1))",fadeInCurve:"var(--ripple-long-tappable-curve, linear(0, 1))"})),(()=>e.status=n.REJECTED),(()=>e.status=n.ACCEPTED),o,t)}))}}initPointerEvent(t){var e;const s=null===(e=this.getBooleanByName("--ripple-use-hover"))||void 0===e||e;t.onpointerdown=t=>this.arena.handlePointer(t,i.DOWN),t.onpointermove=t=>this.arena.handlePointer(t,i.MOVE),t.onpointerup=t=>this.arena.handlePointer(t,i.UP),t.onpointercancel=t=>this.arena.handlePointer(t,i.CANCEL),t.onpointerleave=t=>this.arena.handlePointer(t,i.CANCEL),t.onmouseleave=t=>this.arena.handlePointer(t,i.CANCEL),!("ontouchstart"in window)&&s&&(t.onmouseenter=()=>this.onHoverStart(),t.onmouseleave=()=>this.onHoverEnd())}connectedCallback(){requestAnimationFrame((()=>{let t=this.child;if(null==t)throw"This element must be exists child element.";let e=f.ancestorOf(this);e?this.initPointerEvent(e):this.initPointerEvent(t)}))}createHoverElement(){return document.createElement("touch-ripple-effect-hover")}onHoverStart(){const t=this.child;null==this.hoverEffectElement&&t.appendChild(this.hoverEffectElement=this.createHoverElement()),this.hoverEffectElement.ontransitionend=null,this.hoverEffectElement.getBoundingClientRect(),this.hoverEffectElement.style.opacity="1"}onHoverEnd(){if(this.hoverEffectElement){const t=this.hoverEffectElement;t.style.opacity="0",t.ontransitionend=()=>{this.child.removeChild(t),this.hoverEffectElement=null}}}createEffect(t,e,i,s){var n,o;const r=null!==(n=this.getPropertyByName("--ripple-overlap-behavior"))&&void 0!==n?n:"overlappable";if('"cancel"'==r)null===(o=this.activeEffect)||void 0===o||o.cancel(this.child);else if('"ignoring"'==r&&null!=this.activeEffect)return;const a=Object.assign({spreadDuration:"var(--ripple-spread-duration, 0.3s)",spreadCurve:"var(--ripple-spread-curve, cubic-bezier(.2,.3,.4,1))",fadeInDuration:"var(--ripple-fadein-duration, 0.15s)",fadeInCurve:"var(--ripple-fadein-curve)",fadeOutDuration:"var(--ripple-fadeout-duration, 0.3s)",fadeOutCurve:"var(--ripple-fadeout-curve, cubic-bezier(.15,.5,.5,1))"},s),l=new d(t,e,i,this.hasAttribute("wait"),a,this);return this.child.appendChild(l.createElement(this,this.child)),l}static get observedAttributes(){return["ontap","ondoubletap","onlongtap"]}attributeChangedCallback(t,e,i){if(null!=i){const e=new Function(i);"ontap"==t&&(this.ontap=e),"ondoubletap"==t&&(this.ondoubletap=e),"onlongtap"==t&&(this.onlongtap=e)}}}customElements.define("touch-ripple",m);class E extends HTMLElement{connectedCallback(){this.style.position="absolute",this.style.top="0px",this.style.left="0px",this.style.width="100%",this.style.height="100%",this.style.backgroundColor="var(--ripple-hover, rgba(0, 0, 0, 0.1))",this.style.opacity="0",this.style.transitionProperty="opacity",this.style.transitionDuration="var(--ripple-hover-duration, 0.25s)",this.style.pointerEvents="none"}}customElements.define("touch-ripple-effect-hover",E),addEventListener("DOMContentLoaded",(()=>e.initialize())),t.GestureArena=a,t.GestureRecognizer=o,t.TouchRippleBinding=e,t.TouchRippleConnectionElement=f,t.TouchRippleEffectElement=d,t.TouchRippleEffectHoverElement=E,t.TouchRippleElement=m})); | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).TouchRipple={})}(this,(function(t){"use strict";class e{constructor(){}static get instance(){var t;return null!==(t=this._instance)&&void 0!==t?t:this._instance=new e}initialize(){const t=new CSSStyleSheet;t.insertRule("\n touch-ripple, touch-ripple-connection {\n /* \n * Defines the element to avoid having a separate stylesheet, thereby\n * addressing style issues caused by touch ripple wrapping.\n * For example, if the parent element has its own stylesheet,\n * the size of the child element might be affected as a result.\n */\n display: contents;\n\n /*\n * Needs to remove effects that interfere with touch ripple on\n * touch-based devices, such as in mobile environments.\n */\n -webkit-tap-highlight-color: transparent;\n }\n "),t.insertRule("\n touch-ripple *:has(> touch-ripple-effect),\n touch-ripple *:has(> touch-ripple-effect-hover) {\n position: relative;\n overflow: hidden;\n user-select: none;\n touch-action: manipulation;\n }\n "),document.adoptedStyleSheets=[...document.adoptedStyleSheets,t]}}var i,s,n;!function(t){t.DOWN="down",t.MOVE="move",t.UP="up",t.CANCEL="cancel"}(i||(i={})),function(t){t[t.ACCEPT=0]="ACCEPT",t[t.REJECT=1]="REJECT",t[t.UPDATE=2]="UPDATE"}(s||(s={}));class o{constructor(){this.listeners=[],this.isHold=!1}accept(){this.perform(s.ACCEPT),this.onAccept()}reject(){this.perform(s.REJECT),this.onReject()}hold(){this.isHold=!0,this.listeners.forEach((t=>t(s.UPDATE)))}release(){this.isHold=!1,this.listeners.forEach((t=>t(s.UPDATE)))}onAccept(){}onReject(){}dispose(){}perform(t){this.dispose(),this.listeners.forEach((e=>e(t)))}}class r extends o{constructor(){super()}createPosition(t){return{x:t.clientX,y:t.clientY}}handlePointer(t,e){const s=this.position=this.createPosition(t);if(t.button>0)return this.reject();e==i.DOWN&&this.pointerDown(s),e==i.MOVE&&this.pointerMove(s),e==i.UP&&this.pointerUp(s),e==i.CANCEL&&(this.reject(),this.pointerCancel(s))}pointerDown(t){}pointerMove(t){}pointerUp(t){}pointerCancel(t){}}class a{constructor(t){this.option=t,this.builders=[],this.recognizers=[],this.option=Object.assign({isKeepAliveLastPointerUp:!0},this.option)}registerBuilder(t){this.builders.push(t)}attach(t){this.recognizers.push(t)}detach(t){this.recognizers=this.recognizers.filter((e=>e!=t))}rejectBy(t){this.detach(t),this.checkCycle()}acceptBy(t){this.recognizers.forEach((e=>e!=t?e.reject():void 0)),this.recognizers=[]}reset(){this.builders=[],this.recognizers=[]}createRecognizer(t){const e=t();return e.listeners.push((t=>{switch(t){case s.REJECT:this.rejectBy(e);break;case s.ACCEPT:this.acceptBy(e);break;case s.UPDATE:this.checkCycle()}})),e}checkCycle(t){if(this.option.isKeepAliveLastPointerUp&&(t==i.UP||!t)&&1==this.recognizers.length){const t=this.recognizers[0];t.isHold||t.accept()}}handlePointer(t,e){e==i.DOWN&&0==this.recognizers.length&&(this.recognizers=this.builders.map((t=>this.createRecognizer(t)))),this.recognizers.forEach((i=>i.handlePointer(t,e))),this.checkCycle(e)}}class l extends r{constructor(t,e,i,s,n,o){super(),this.onTap=t,this.onTapRejectable=e,this.onTapAccept=i,this.onTapReject=s,this.rejectableDuration=n,this.tappableDuration=o,this.timerIds=[],this.isRejectable=!1}pointerDown(t){const e=()=>{this.isRejectable=!0,this.onTapRejectable(t)};this.hold(),this.rejectableDuration!=1/0&&this.timerIds.push(setTimeout(e,this.rejectableDuration)),0!=this.tappableDuration&&this.timerIds.push(setTimeout(this.reject.bind(this),this.tappableDuration))}pointerUp(t){this.release()}dispose(){this.timerIds.forEach((t=>clearTimeout(t))),this.timerIds=null}onAccept(){this.isRejectable?this.onTapAccept(this.position):this.onTap(this.position)}onReject(){this.isRejectable&&this.onTapReject(this.position)}toString(){return"[Object TapGestureRecognizer]"}}class h extends r{constructor(t,e){super(),this.onDoubleTap=t,this.doubleTappableDuration=e,this.tapCount=0}pointerDown(t){2==++this.tapCount?this.accept():(this.hold(),setTimeout((()=>this.reject()),this.doubleTappableDuration))}onAccept(){this.onDoubleTap(this.position)}dispose(){null!=this.timeId&&clearTimeout(this.timeId)}toString(){return"[Object DoubleTapGestureRecognizer]"}}class p extends r{constructor(t,e,i,s,n){super(),this.onLongTapStart=t,this.onLongTapEnd=e,this.onLongTap=i,this.tappableDuration=s,this.longtappableDuration=n,this.isStartCalled=!1}pointerDown(t){this.isHold=!0,this.timerId=setTimeout((()=>{this.isStartCalled=!0,this.onLongTapStart(t),this.timerId=setTimeout((()=>{this.accept(),this.onLongTap()}),this.longtappableDuration)}),this.tappableDuration)}pointerUp(t){this.reject()}onReject(){this.isStartCalled&&this.onLongTapEnd()}dispose(){null!=this.timerId&&clearTimeout(this.timerId)}toString(){return"[Object LongTapGestureRecognizer]"}}Object.defineProperty(Element.prototype,"intrinsicSize",{get:function(){return c.intrinsicSizeOf(this)}}),Object.defineProperty(Element.prototype,"intrinsicWidth",{get:function(){return c.intrinsicSizeOf(this).width}}),Object.defineProperty(Element.prototype,"intrinsicHeight",{get:function(){return c.intrinsicSizeOf(this).height}}),Object.defineProperty(Element.prototype,"reflow",{get:function(){return c.reflow(this)}});class c{static reflow(t){t.getBoundingClientRect()}static intrinsicSizeOf(t,e){for(;t;){const i=null!=e?e:getComputedStyle(t),s=parseFloat(i.width),n=parseFloat(i.height),o=parseFloat(i.paddingLeft),r=parseFloat(i.paddingRight),a=parseFloat(i.paddingTop),l=parseFloat(i.paddingBottom),h=parseFloat(i.borderLeftWidth),p=parseFloat(i.borderRightWidth),c=parseFloat(i.borderTopWidth),u=parseFloat(i.borderBottomWidth),d=parseFloat(i.marginLeft),f=parseFloat(i.marginRight),g=parseFloat(i.marginTop),m=parseFloat(i.marginBottom),E=i.boxSizing,y=i.position;if("contents"===i.display){let e=Array.from(t.children).filter((t=>"STYLE"!==t.tagName&&"SCRIPT"!==t.tagName));if(1!==e.length)throw new Error("An element with a display property of 'contents' must have only one child to define its intrinsic size.");t=e[0];continue}let b=s,v=n;return"content-box"===E&&(b+=o+r+h+p,v+=a+l+c+u),"absolute"!==y&&"fixed"!==y&&(b+=d+f,v+=g+m),{width:b,height:v}}}}Object.defineProperty(Element.prototype,"intrinsicRect",{get:function(){return u.intrinsicOf(this)}});class u{static intrinsicOf(t,e){const i=null!=e?e:getComputedStyle(t),s=c.intrinsicSizeOf(t,i),n=t.getBoundingClientRect();return new DOMRect(n.x,n.y,s.width,s.height)}}class d{constructor(t,e){this.x=t,this.y=e}distance(t,e){let i=this.x-t,s=this.y-e;return Math.sqrt(i*i+s*s)}}!function(t){t[t.NONE=0]="NONE",t[t.ACCEPTED=1]="ACCEPTED",t[t.REJECTED=2]="REJECTED",t[t.DISPOSED=3]="DISPOSED"}(n||(n={}));class f extends HTMLElement{constructor(t,e,i,s,n,o,r){var a;super(),this.position=t,this.callback=e,this.isRejectable=i,this.isWait=s,this.option=n,this.parent=o,this.target=r,this._statusListeners=[],null!==(a=this.target)&&void 0!==a||(this.target=this.parent.firstElementChild)}get status(){return this._status}set status(t){this._status!=t&&(this._status=t,this._statusListeners.forEach((e=>e(t))))}set statusListener(t){this._statusListeners.push(t)}notify(){this.callback&&this.callback()}fadeout(t=this.parent){null!=t&&(this.style.transitionProperty="opacity",this.style.transitionDuration=this.option.fadeOutDuration,this.style.transitionTimingFunction=this.option.fadeOutCurve,this.style.opacity="0",requestAnimationFrame((()=>{this.ontransitionend=()=>this.dispose()})))}cancel(t=this.parent){null!=t&&(this.style.transitionProperty="opacity",this.style.transitionDuration="var(--ripple-cancel-duration, 0s)",this.style.transitionTimingFunction="var(--ripple-cancel-curve)",this.style.opacity="0",requestAnimationFrame((()=>{this.ontransitionend=()=>this.dispose()})))}connectedCallback(){const t=this.target,e=this.parent,i=getComputedStyle(t),s=u.intrinsicOf(t,i),o={width:s.width,height:s.height},r=parseFloat(i.marginLeft),a=parseFloat(i.marginTop),l=Math.max(o.width,o.height),h=this.position.x-s.left-r,p=this.position.y-s.top-a,c=o.width/2,f=o.height/2;let g=0,m=0;const E=()=>{++m==g&&(this.fadeout(t),this.isWait&&this.notify(),this.ontransitionend=null)};var y=e.getPropertyByName("--ripple-blur-radius")||"6%";if(y.endsWith("%")){const t=Number(y.replace("%",""))/100;var b=Number(l*t)}else b=Number(y.replace("px",""));let v=2*new d(c,f).distance(0,0);v+=2*new d(c,f).distance(h,p),v+=2*b,this.style.position="absolute",this.style.left=`${h}px`,this.style.top=`${p}px`,this.style.width=`${v}px`,this.style.height=`${v}px`,this.style.pointerEvents="none",this.style.translate="-50% -50%",this.style.borderRadius="50%",this.style.backgroundColor="var(--ripple, rgba(0, 0, 0, 0.2))",this.style.filter=`blur(${b}px)`,this.style.opacity="0",this.style.transform="scale(var(--ripple-lower-scale, 0.3))",this.style.transformOrigin="center",requestAnimationFrame((()=>{this.style.transitionProperty="opacity, transform",this.style.transitionDuration=`${this.option.fadeInDuration}, ${this.option.spreadDuration}`,this.style.transitionTimingFunction=`${this.option.fadeInCurve}, ${this.option.spreadCurve}`,this.style.opacity="1",this.style.transform="scale(var(--ripple-upper-scale, 1))"})),this.addEventListener("transitionstart",(()=>{g+=1}));let C=!1;this.addEventListener("transitionend",(()=>{C=!0})),this.isRejectable?this.statusListener=e=>{if(e==n.REJECTED&&this.fadeout(t),e==n.ACCEPTED){if(C)return this.notify(),this.fadeout(t);0==this.isWait&&this.notify(),this.ontransitionend=E}}:(0==this.isWait&&this.notify(),this.ontransitionend=E)}dispose(){this.status=n.DISPOSED,this._statusListeners=null,this.remove()}}customElements.define("touch-ripple-effect",f);class g extends HTMLElement{static ancestorOf(t){let e=t.parentElement;for(;e;){if(e instanceof g)return e;e=e.parentElement}}}customElements.define("touch-ripple-connection",g);class m extends HTMLElement{constructor(){super(...arguments),this.arena=new a({isKeepAliveLastPointerUp:!0})}set ontap(t){this._ontap=t,this.initBuiler()}set ondoubletap(t){this._ondoubletap=t,this.initBuiler()}set onlongtap(t){this._onlongtap=t,this.initBuiler()}get child(){var t;const e=this.getAttribute("selector");return e&&null!==(t=this.querySelector(e))&&void 0!==t?t:this.firstElementChild}getPropertyByName(t,e=this){return getComputedStyle(e).getPropertyValue(t)}getDurationByName(t,e=this){const i=this.getPropertyByName(t,e);return""==i||"none"==i?null:i.endsWith("ms")?Number(i.replace("ms","")):1e3*Number(i.replace("s",""))}getBooleanByName(t,e=this){const i=this.getPropertyByName(t,e);if(""!=i)return"1"==i}initBuiler(){var t,e,i,s;this.arena.reset();const o=null!==(t=this.getDurationByName("--ripple-tap-preview-duration"))&&void 0!==t?t:150;if(null!=this._ontap){const t=null!==(e=this.getDurationByName("--ripple-tappable-duration"))&&void 0!==e?e:0,i=this._onlongtap||this._ondoubletap?1/0:o;this.arena.registerBuilder((()=>{let e=null;return new l((t=>e=this.createEffect(t,this._ontap,!1)),(t=>e=this.createEffect(t,this._ontap,!0)),(()=>e.status=n.ACCEPTED),(()=>e.status=n.REJECTED),i,t)}))}if(null!=this._ondoubletap){const t=null!==(i=this.getDurationByName("--ripple-double-tappable-duration"))&&void 0!==i?i:300;this.arena.registerBuilder((()=>new h((t=>this.createEffect(t,this._ondoubletap,!1)),t)))}if(null!=this._onlongtap){const t=null!==(s=this.getDurationByName("--ripple-long-tappable-duration"))&&void 0!==s?s:1e3;this.arena.registerBuilder((()=>{let e=null;return new p((t=>e=this.createEffect(t,this._onlongtap,!0,{spreadDuration:"var(--ripple-long-tappable-duration, 1s)",fadeInDuration:"var(--ripple-long-tappable-duration, 1s)",spreadCurve:"var(--ripple-long-tappable-curve, linear(0, 1))",fadeInCurve:"var(--ripple-long-tappable-curve, linear(0, 1))"})),(()=>e.status=n.REJECTED),(()=>e.status=n.ACCEPTED),o,t)}))}}initPointerEvent(t){var e;const s=null===(e=this.getBooleanByName("--ripple-use-hover"))||void 0===e||e;t.onpointerdown=t=>this.arena.handlePointer(t,i.DOWN),t.onpointermove=t=>this.arena.handlePointer(t,i.MOVE),t.onpointerup=t=>this.arena.handlePointer(t,i.UP),t.onpointercancel=t=>this.arena.handlePointer(t,i.CANCEL),t.onpointerleave=t=>this.arena.handlePointer(t,i.CANCEL),t.onmouseleave=t=>this.arena.handlePointer(t,i.CANCEL),!("ontouchstart"in window)&&s&&(t.onmouseenter=()=>this.onHoverStart(),t.onmouseleave=()=>this.onHoverEnd())}connectedCallback(){requestAnimationFrame((()=>{let t=this.child;if(null==t)throw"This element must be exists child element.";let e=g.ancestorOf(this);e?this.initPointerEvent(e):this.initPointerEvent(t)}))}createHoverElement(){return document.createElement("touch-ripple-effect-hover")}onHoverStart(){const t=this.child;null==this.hoverEffectElement&&t.appendChild(this.hoverEffectElement=this.createHoverElement()),this.hoverEffectElement.ontransitionend=null,this.hoverEffectElement.getBoundingClientRect(),this.hoverEffectElement.style.opacity="1"}onHoverEnd(){if(this.hoverEffectElement){const t=this.hoverEffectElement;t.style.opacity="0",t.ontransitionend=()=>{this.child.removeChild(t),this.hoverEffectElement=null}}}createEffect(t,e,i,s){var n,o;const r=null!==(n=this.getPropertyByName("--ripple-overlap-behavior"))&&void 0!==n?n:"overlappable";if('"cancel"'==r)null===(o=this.activeEffect)||void 0===o||o.cancel(this.child);else if('"ignoring"'==r&&null!=this.activeEffect)return;const a=Object.assign({spreadDuration:"var(--ripple-spread-duration, 0.3s)",spreadCurve:"var(--ripple-spread-curve, cubic-bezier(.2,.3,.4,1))",fadeInDuration:"var(--ripple-fadein-duration, 0.15s)",fadeInCurve:"var(--ripple-fadein-curve)",fadeOutDuration:"var(--ripple-fadeout-duration, 0.3s)",fadeOutCurve:"var(--ripple-fadeout-curve, cubic-bezier(.15,.5,.5,1))"},s),l=this.hasAttribute("wait"),h=new f(t,e,i,l,a,this,this.child);return this.child.appendChild(h),h}static get observedAttributes(){return["ontap","ondoubletap","onlongtap"]}attributeChangedCallback(t,e,i){if(null!=i){const e=new Function(i);"ontap"==t&&(this.ontap=e),"ondoubletap"==t&&(this.ondoubletap=e),"onlongtap"==t&&(this.onlongtap=e)}}}customElements.define("touch-ripple",m);class E extends HTMLElement{connectedCallback(){this.style.position="absolute",this.style.top="0px",this.style.left="0px",this.style.width="100%",this.style.height="100%",this.style.backgroundColor="var(--ripple-hover, rgba(0, 0, 0, 0.1))",this.style.opacity="0",this.style.transitionProperty="opacity",this.style.transitionDuration="var(--ripple-hover-duration, 0.25s)",this.style.pointerEvents="none"}}customElements.define("touch-ripple-effect-hover",E),addEventListener("DOMContentLoaded",(()=>e.instance.initialize())),t.GestureArena=a,t.GestureRecognizer=o,t.TouchRippleBinding=e,t.TouchRippleConnectionElement=g,t.TouchRippleEffectElement=f,t.TouchRippleEffectHoverElement=E,t.TouchRippleElement=m})); | ||
//# sourceMappingURL=index.umd.js.map |
import { PointerPosition, TouchRippleEffectStatusListener } from "../type"; | ||
import { TouchRippleElement } from "./touch_ripple"; | ||
/** Signature for the enumeration that defines status values about `TouchRippleEffectElement`. */ | ||
export declare enum TouchRippleEffectStatus { | ||
@@ -9,2 +10,6 @@ NONE = 0, | ||
} | ||
/** | ||
* Signature for the interface that defines custom property animation-related | ||
* identifiers about `TouchRippleEffectElement`. | ||
*/ | ||
export interface TouchRippleEffectOption { | ||
@@ -29,6 +34,5 @@ spreadDuration: string; | ||
parent: TouchRippleElement; | ||
target?: HTMLElement; | ||
target: HTMLElement; | ||
private _status; | ||
private _statusListeners; | ||
private _ripple; | ||
constructor(position: PointerPosition, callback: Function, isRejectable: boolean, | ||
@@ -39,3 +43,3 @@ /** | ||
*/ | ||
isWait: boolean, option: TouchRippleEffectOption, parent: TouchRippleElement, target?: HTMLElement); | ||
isWait: boolean, option: TouchRippleEffectOption, parent: TouchRippleElement, target: HTMLElement); | ||
get status(): TouchRippleEffectStatus; | ||
@@ -45,6 +49,6 @@ set status(newValue: TouchRippleEffectStatus); | ||
notify(): void; | ||
fadeout(parent: HTMLElement, target?: HTMLElement): void; | ||
cancel(parent: HTMLElement, target?: HTMLElement): void; | ||
createElement(parent: TouchRippleElement, target: HTMLElement): HTMLElement; | ||
fadeout(parent?: HTMLElement): void; | ||
cancel(parent?: HTMLElement): void; | ||
connectedCallback(): void; | ||
dispose(): void; | ||
} |
@@ -16,2 +16,3 @@ import { GestureEventCallback, PointerPosition } from "../../type"; | ||
pointerDown(position: PointerPosition): void; | ||
pointerUp(_: PointerPosition): void; | ||
dispose(): void; | ||
@@ -18,0 +19,0 @@ onAccept(): void; |
export declare class TouchRippleBinding { | ||
static initialize(): void; | ||
private static _instance; | ||
private constructor(); | ||
static get instance(): TouchRippleBinding; | ||
/** Initializes statically applied CSS-related values for `TouchRipple`. */ | ||
initialize(): void; | ||
} |
{ | ||
"name": "web-touch-ripple", | ||
"version": "1.2.31", | ||
"version": "1.3.0", | ||
"description": "This package provides visual representation of the pointer event to users.", | ||
@@ -39,2 +39,3 @@ "repository": "https://github.com/MTtankkeo/web_touch_ripple", | ||
"devDependencies": { | ||
"@rollup/plugin-node-resolve": "^15.2.3", | ||
"@rollup/plugin-terser": "^0.4.4", | ||
@@ -45,3 +46,6 @@ "rollup": "^4.13.0", | ||
"typescript": "^5.4.2" | ||
}, | ||
"dependencies": { | ||
"@web-package/utility": "^1.2.10" | ||
} | ||
} | ||
} |
@@ -8,3 +8,3 @@ <div align="center"> | ||
<th>Version</th> | ||
<th>v1.2.31</th> | ||
<th>v1.3.0</th> | ||
</tr> | ||
@@ -11,0 +11,0 @@ </tbody> |
import typescript from "rollup-plugin-typescript2"; | ||
import resolve from "@rollup/plugin-node-resolve"; | ||
import terser from "@rollup/plugin-terser"; | ||
@@ -9,2 +10,3 @@ | ||
}), | ||
resolve(), | ||
terser(), | ||
@@ -11,0 +13,0 @@ ] |
@@ -0,6 +1,7 @@ | ||
import { DOMRectUtil } from "@web-package/utility"; | ||
import { Point } from "../point"; | ||
import { PointerPosition, TouchRippleEffectStatusListener } from "../type"; | ||
import { ElementUtils } from "../utils/element"; | ||
import { TouchRippleElement } from "./touch_ripple"; | ||
/** Signature for the enumeration that defines status values about `TouchRippleEffectElement`. */ | ||
export enum TouchRippleEffectStatus { | ||
@@ -13,2 +14,6 @@ NONE, | ||
/** | ||
* Signature for the interface that defines custom property animation-related | ||
* identifiers about `TouchRippleEffectElement`. | ||
*/ | ||
export interface TouchRippleEffectOption { | ||
@@ -26,3 +31,2 @@ spreadDuration: string; | ||
private _statusListeners: TouchRippleEffectStatusListener[] = []; | ||
private _ripple: HTMLElement; | ||
@@ -40,3 +44,3 @@ constructor( | ||
public parent: TouchRippleElement, | ||
public target?: HTMLElement | ||
public target: HTMLElement | ||
) { | ||
@@ -64,41 +68,33 @@ super(); | ||
fadeout( | ||
parent: HTMLElement, | ||
target: HTMLElement = this._ripple | ||
) { | ||
fadeout(parent: HTMLElement = this.parent) { | ||
if (parent == null) return; | ||
if (target == null) return; | ||
target.style.transitionProperty = "opacity" | ||
target.style.transitionDuration = this.option.fadeOutDuration; | ||
target.style.transitionTimingFunction = this.option.fadeOutCurve; | ||
target.style.opacity = "0"; | ||
this.style.transitionProperty = "opacity" | ||
this.style.transitionDuration = this.option.fadeOutDuration; | ||
this.style.transitionTimingFunction = this.option.fadeOutCurve; | ||
this.style.opacity = "0"; | ||
requestAnimationFrame(() => { | ||
target.ontransitionend = () => parent.removeChild(target); | ||
this.ontransitionend = () => this.dispose(); | ||
}); | ||
this.dispose(); | ||
} | ||
cancel( | ||
parent: HTMLElement, | ||
target: HTMLElement = this._ripple | ||
) { | ||
cancel(parent: HTMLElement = this.parent) { | ||
if (parent == null) return; | ||
if (target == null) return; | ||
target.style.transitionProperty = "opacity" | ||
target.style.transitionDuration = "var(--ripple-cancel-duration, 0s)"; | ||
target.style.transitionTimingFunction = "var(--ripple-cancel-curve)"; | ||
target.style.opacity = "0"; | ||
this.style.transitionProperty = "opacity" | ||
this.style.transitionDuration = "var(--ripple-cancel-duration, 0s)"; | ||
this.style.transitionTimingFunction = "var(--ripple-cancel-curve)"; | ||
this.style.opacity = "0"; | ||
requestAnimationFrame(() => { | ||
target.ontransitionend = () => parent.removeChild(target); | ||
this.ontransitionend = () => this.dispose(); | ||
}); | ||
this.dispose(); | ||
} | ||
createElement( | ||
parent: TouchRippleElement, | ||
target: HTMLElement, | ||
) { | ||
const targetRect = target.getBoundingClientRect(); | ||
connectedCallback() { | ||
const target = this.target; | ||
const parent = this.parent; | ||
const targetStyle = getComputedStyle(target); | ||
const targetSize = ElementUtils.sizeOf(targetStyle); | ||
const targetRect = DOMRectUtil.intrinsicOf(target, targetStyle); | ||
const targetSize = { | ||
width: targetRect.width, // intrinsic size | ||
height: targetRect.height // intrinsic size | ||
}; | ||
const targetShiftLeft = parseFloat(targetStyle.marginLeft); | ||
@@ -126,3 +122,3 @@ const targetShiftTop = parseFloat(targetStyle.marginTop); | ||
// Clean up a registered event callback to prevent a redemption called. | ||
ripple.ontransitionend = null; | ||
this.ontransitionend = null; | ||
} | ||
@@ -147,35 +143,30 @@ } | ||
this._ripple = document.createElement("div"); | ||
const ripple = this._ripple; | ||
ripple.classList.add("ripple"); | ||
ripple.style.position = "absolute"; | ||
ripple.style.left = `${targetX}px`; | ||
ripple.style.top = `${targetY}px`; | ||
ripple.style.width = `${rippleSize}px`; | ||
ripple.style.height = `${rippleSize}px`; | ||
ripple.style.pointerEvents = "none"; | ||
ripple.style.translate = "-50% -50%"; | ||
ripple.style.borderRadius = "50%"; | ||
ripple.style.backgroundColor = "var(--ripple, rgba(0, 0, 0, 0.2))"; | ||
ripple.style.filter = `blur(${blurRadiusValue}px)`; | ||
// Sets style properties for the ripple position and intrinsic size settings. | ||
this.style.position = "absolute"; | ||
this.style.left = `${targetX}px`; | ||
this.style.top = `${targetY}px`; | ||
this.style.width = `${rippleSize}px`; | ||
this.style.height = `${rippleSize}px`; | ||
this.style.pointerEvents = "none"; | ||
this.style.translate = "-50% -50%"; | ||
this.style.borderRadius = "50%"; | ||
this.style.backgroundColor = "var(--ripple, rgba(0, 0, 0, 0.2))"; | ||
this.style.filter = `blur(${blurRadiusValue}px)`; | ||
{ // is fade-in animation ready. | ||
ripple.style.opacity = "0"; | ||
ripple.style.transform = "scale(var(--ripple-lower-scale, 0.3))"; | ||
ripple.style.transformOrigin = "center"; | ||
// Sets style properties for fade-in animation to ready phase. (start) | ||
this.style.opacity = "0"; | ||
this.style.transform = "scale(var(--ripple-lower-scale, 0.3))"; | ||
this.style.transformOrigin = "center"; | ||
// Sets transition settings by related properties. | ||
ripple.style.transitionProperty = "opacity, transform"; | ||
ripple.style.transitionDuration = `${this.option.fadeInDuration}, ${this.option.spreadDuration}`; | ||
ripple.style.transitionTimingFunction = `${this.option.fadeInCurve}, ${this.option.spreadCurve}`; | ||
} | ||
queueMicrotask(() => { // is fade-in animation forward. | ||
ripple.getBoundingClientRect(); // reflowed | ||
ripple.style.opacity = "1"; | ||
ripple.style.transform = "scale(var(--ripple-upper-scale, 1))"; | ||
// Sets style properties for fade-in animation to forward. (end) | ||
requestAnimationFrame(() => { | ||
this.style.transitionProperty = "opacity, transform"; | ||
this.style.transitionDuration = `${this.option.fadeInDuration}, ${this.option.spreadDuration}`; | ||
this.style.transitionTimingFunction = `${this.option.fadeInCurve}, ${this.option.spreadCurve}`; | ||
this.style.opacity = "1"; | ||
this.style.transform = "scale(var(--ripple-upper-scale, 1))"; | ||
}); | ||
// Called when a transition animation started by property. | ||
ripple.addEventListener("transitionstart", () => { | ||
this.addEventListener("transitionstart", () => { | ||
transitionStartCount += 1; | ||
@@ -185,3 +176,3 @@ }); | ||
let isFadeInEnd = false; | ||
ripple.addEventListener("transitionend", () => { | ||
this.addEventListener("transitionend", () => { | ||
isFadeInEnd = true; | ||
@@ -198,3 +189,3 @@ }); | ||
} | ||
ripple.ontransitionend = performFadeout; | ||
this.ontransitionend = performFadeout; | ||
} | ||
@@ -209,6 +200,4 @@ } | ||
// process it according to the current touch ripple status. | ||
ripple.ontransitionend = performFadeout; | ||
this.ontransitionend = performFadeout; | ||
} | ||
return ripple; | ||
} | ||
@@ -219,3 +208,3 @@ | ||
this._statusListeners = null; | ||
this._ripple = null; | ||
this.remove(); | ||
} | ||
@@ -222,0 +211,0 @@ } |
@@ -95,4 +95,4 @@ import { GestureArena } from "../gestures/gesture_arena"; | ||
const tappableDuration = this.getDurationByName("--ripple-tappable-duration") ?? 0; | ||
const rejectableDuration = this._onlongtap != null | ||
? 0.0 | ||
const rejectableDuration = this._onlongtap || this._ondoubletap | ||
? Infinity | ||
: previewDuration; | ||
@@ -228,3 +228,3 @@ | ||
const FINAL_OPTIONS: TouchRippleEffectOption = {...{ | ||
const OPTION: TouchRippleEffectOption = {...{ | ||
spreadDuration: "var(--ripple-spread-duration, 0.3s)", | ||
@@ -238,2 +238,3 @@ spreadCurve: "var(--ripple-spread-curve, cubic-bezier(.2,.3,.4,1))", | ||
const isWait = this.hasAttribute("wait"); | ||
const effect = new TouchRippleEffectElement( | ||
@@ -243,8 +244,9 @@ position, | ||
isRejectable, | ||
this.hasAttribute("wait"), | ||
FINAL_OPTIONS, | ||
this, | ||
isWait, | ||
OPTION, | ||
this, // parent | ||
this.child // target | ||
) | ||
this.child.appendChild(effect.createElement(this, this.child)); | ||
this.child.appendChild(effect); | ||
return effect; | ||
@@ -251,0 +253,0 @@ } |
@@ -27,2 +27,5 @@ import { GestureEventCallback, PointerPosition } from "../../type"; | ||
// Should can only be accept or reject when prointer-up. | ||
this.hold(); | ||
// about --tap-preview-duration | ||
@@ -39,2 +42,6 @@ if (this.rejectableDuration != Infinity) { | ||
pointerUp(_: PointerPosition): void { | ||
this.release(); | ||
} | ||
dispose(): void { | ||
@@ -41,0 +48,0 @@ this.timerIds.forEach(id => clearTimeout(id)); |
@@ -88,6 +88,8 @@ import { GestureRecognizer, GestureRecognizerResult } from "./gesture_recognizer.js"; | ||
// Accept a last recognizer that is un-holded survivor. | ||
if (isKeepAliveLastPointerUp && (type == PointerType.UP || type == null) && this.recognizers.length == 1) { | ||
if (isKeepAliveLastPointerUp && (type == PointerType.UP || !type) && this.recognizers.length == 1) { | ||
const last = this.recognizers[0]; | ||
if(!last.isHold) last.accept(); | ||
if(!last.isHold) { | ||
last.accept(); | ||
} | ||
} | ||
@@ -94,0 +96,0 @@ } |
@@ -10,2 +10,2 @@ import { TouchRippleBinding } from "./modules/touch_ripple_binding"; | ||
addEventListener("DOMContentLoaded", () => TouchRippleBinding.initialize()); | ||
addEventListener("DOMContentLoaded", () => TouchRippleBinding.instance.initialize()); |
export class TouchRippleBinding { | ||
static initialize() { | ||
private static _instance: TouchRippleBinding; | ||
private constructor() {} | ||
static get instance() { | ||
return this._instance ?? (this._instance = new TouchRippleBinding()); | ||
} | ||
/** Initializes statically applied CSS-related values for `TouchRipple`. */ | ||
initialize() { | ||
const sheet = new CSSStyleSheet(); | ||
@@ -24,4 +32,4 @@ sheet.insertRule(` | ||
sheet.insertRule(` | ||
touch-ripple *:has(> touch-ripple-effect-hover), | ||
touch-ripple *:has(> .ripple) { | ||
touch-ripple *:has(> touch-ripple-effect), | ||
touch-ripple *:has(> touch-ripple-effect-hover) { | ||
position: relative; | ||
@@ -28,0 +36,0 @@ overflow: hidden; |
@@ -6,5 +6,6 @@ { | ||
"declaration": true, | ||
"declarationDir": "dist/types/" | ||
"declarationDir": "dist/types/", | ||
"moduleResolution": "Node" | ||
}, | ||
"include": ["src/"] | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
108014
1370
1
6
54
+ Added@web-package/utility@^1.2.10
+ Added@web-package/utility@1.2.20(transitive)