timepicker-ui 4.2.2 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -805
- package/dist/index.cjs +2 -2
- package/dist/index.d.ts +7 -1
- package/dist/index.js +2 -2
- package/dist/index.umd.js +1 -1
- package/dist/plugins/range.cjs +1 -1
- package/dist/plugins/range.js +1 -1
- package/dist/plugins/range.umd.js +1 -1
- package/dist/plugins/timezone.cjs +1 -1
- package/dist/plugins/timezone.js +1 -1
- package/dist/plugins/timezone.umd.js +1 -1
- package/dist/plugins/wheel.cjs +1 -1
- package/dist/plugins/wheel.js +1 -1
- package/dist/plugins/wheel.umd.js +1 -1
- package/package.json +1 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).TimepickerUIWheel={})}(this,function(e){"use strict";const t=()=>"undefined"!=typeof document,s=(e="")=>{const t=e.replace(/(AM|PM|am|pm)/,e=>` ${e}`),s=new Date(`September 20, 2000 ${t}`);return`${s.getHours().toString().padStart(2,"0")}:${s.getMinutes().toString().padStart(2,"0")}`},r=e=>{const[t,s]=e.split(":");return`${t.padStart(2,"0")}:${s.padStart(2,"0")}`},l=(e,t,l,n,i)=>{if(!(e&&t&&n&&i))return!1;const o="12h"===i?s(`${e}:${t} ${l||""}`.trim()):r(`${e}:${t}`),a=Array.isArray(n)?n:[n];for(const e of a){const[t,l]=e.trim().split("-");let n,a;if("12h"===i){const e=t.trim(),r=l.trim();if(!/\s?(AM|PM|am|pm)\s?$/.test(e)||!/\s?(AM|PM|am|pm)\s?$/.test(r))continue;n=s(e),a=s(r)}else{const e=t.trim(),s=l.trim();if(/\s?(AM|PM|am|pm)\s?/.test(e)||/\s?(AM|PM|am|pm)\s?/.test(s))continue;n=r(e),a=r(s)}if(o>=n&&o<=a)return!1}return!0},n={hours:".tp-ui-wheel-hours",minutes:".tp-ui-wheel-minutes",ampm:".tp-ui-wheel-ampm"};class i{core;columns=new Map;cachedItemHeight=null;cachedItems=new Map;removedItems=new Map;constructor(e){this.core=e}init(){if(this.cachedItems.clear(),this.cachedItemHeight=null,this.restoreRemovedItems(),!t())return;const e=this.core.getModalElement();if(!e)return;["hours","minutes","ampm"].forEach(t=>{const s=e.querySelector(n[t]);s&&this.columns.set(t,s)}),this.updateDisabledItems()}updateDisabledItems(){const e=this.core.disabledTime;if(!e?.value)return;const t=!0===this.core.options.wheel.hideDisabled;t&&(this.restoreRemovedItems(),this.invalidateItemCache()),e.value.isInterval&&e.value.intervals?this.updateDisabledByInterval(e.value,t):this.updateDisabledByFlatLists(e.value,t),t&&this.invalidateItemCache()}updateDisabledByFlatLists(e,t){const s=this.columns.get("hours"),r=this.columns.get("minutes");if(s&&e.hours){const r=new Set(e.hours.map(String));this.toggleDisabledOnItems(s,r,t)}if(r&&e.minutes){const s=new Set(e.minutes.map(String));this.toggleDisabledOnItems(r,s,t)}}updateDisabledByInterval(e,t){const s=e.clockType??"12h",r=e.intervals,n=this.getCurrentAmPm(),i=this.getCurrentHour(),o=this.columns.get("hours");if(o){o.querySelectorAll(".tp-ui-wheel-item").forEach(e=>{const l=e.getAttribute("data-value");if(null===l)return;const i=this.isHourFullyDisabled(l,n,r,s);e.classList.toggle("is-disabled",i),t&&i&&this.removeItemFromDOM(e,o)})}const a=this.columns.get("minutes");if(a){a.querySelectorAll(".tp-ui-wheel-item").forEach(e=>{const o=e.getAttribute("data-value");if(null===o)return;const c=l(i,o,n,r,s);e.classList.toggle("is-disabled",!c),t&&!c&&this.removeItemFromDOM(e,a)})}}isHourFullyDisabled(e,t,s,r){if(!s)return!1;for(let n=0;n<60;n++){const i=n.toString().padStart(2,"0");if(l(e,i,t,s,r))return!1}return!0}toggleDisabledOnItems(e,t,s){e.querySelectorAll(".tp-ui-wheel-item").forEach(r=>{const l=r.getAttribute("data-value");if(null!==l){const n=String(parseInt(l,10)),i=t.has(n)||t.has(l);r.classList.toggle("is-disabled",i),s&&i&&this.removeItemFromDOM(r,e)}})}getCurrentAmPm(){const e=this.core.getAM();return e?.classList.contains("active")?"AM":"PM"}getCurrentHour(){const e=this.core.getHour();return e?.value?.padStart(2,"0")??"12"}getColumnElement(e){return this.columns.get(e)??null}getItems(e){const t=this.cachedItems.get(e);if(t)return t;const s=this.columns.get(e);if(!s)return null;const r=s.querySelectorAll(".tp-ui-wheel-item");return this.cachedItems.set(e,r),r}invalidateItemCache(){this.cachedItems.clear(),this.cachedItemHeight=null}getItemCount(e){const t=this.getItems(e);return t?t.length:0}getItemHeight(){if(null!==this.cachedItemHeight)return this.cachedItemHeight;const e=this.columns.get("hours");if(!e)return 0;const t=e.querySelector(".tp-ui-wheel-item");if(!t)return 0;const s=t.getBoundingClientRect().height;return s>0&&(this.cachedItemHeight=s),s}removeItemFromDOM(e,t){const s=this.getColumnTypeByElement(t);if(!s)return;const r=this.removedItems.get(s)??[];r.push(e),this.removedItems.set(s,r),e.remove()}restoreRemovedItems(){["hours","minutes","ampm"].forEach(e=>{const t=this.removedItems.get(e);if(!t||0===t.length)return;const s=this.columns.get(e);if(!s)return;const r=Array.from(s.querySelectorAll(".tp-ui-wheel-item"));t.forEach(e=>{e.classList.remove("is-disabled");const t=parseInt(e.getAttribute("data-value")??"0",10),l=r.find(e=>parseInt(e.getAttribute("data-value")??"0",10)>t);if(l)s.insertBefore(e,l);else{const t=r[r.length-1],l=t?.nextSibling??null;l?s.insertBefore(e,l):s.appendChild(e)}r.push(e),r.sort((e,t)=>parseInt(e.getAttribute("data-value")??"0",10)-parseInt(t.getAttribute("data-value")??"0",10))})}),this.removedItems.clear()}getColumnTypeByElement(e){for(const[t,s]of this.columns)if(s===e)return t;return null}destroy(){this.restoreRemovedItems(),this.columns.clear(),this.cachedItems.clear(),this.cachedItemHeight=null,this.removedItems.clear()}}class o{renderer;core;dragHandler=null;onScrollEnd=null;onScrollStart=null;constructor(e,t){this.renderer=e,this.core=t}setDragHandler(e){this.dragHandler=e}init(){this.dragHandler&&(this.dragHandler.setSnapCallback(e=>{this.onColumnSnapped(e)}),this.dragHandler.setScrollStartCallback(e=>{this.emitScrollStart(e)}))}setScrollEndCallback(e){this.onScrollEnd=e}setScrollStartCallback(e){this.onScrollStart=e}scrollToValue(e,t){if(!this.renderer.getColumnElement(e)||!this.dragHandler)return;const s=this.renderer.getItemHeight();if(s<=0)return;const r=this.renderer.getItems(e);if(!r)return;let l=-1;for(let e=0;e<r.length;e++)if(r[e].getAttribute("data-value")===t){l=e;break}if(l<0)return;const n=l*s;this.dragHandler.setScrollOffset(e,n),this.applyVisualClassesForIndex(e,l)}getSelectedValue(e){if(!this.dragHandler)return null;const t=this.renderer.getItemHeight();if(t<=0)return null;const s=this.dragHandler.getScrollOffset(e),r=Math.round(s/t),l=this.renderer.getItems(e);return!l||r<0||r>=l.length?null:l[r].getAttribute("data-value")}getCurrentSelection(){const e=this.getSelectedValue("hours")??"12",t=this.getSelectedValue("minutes")??"00";let s=null;if("24h"!==this.core.options.clock.type&&(s=this.getSelectedValue("ampm"),null===s)){const e=this.core.getAM();s=e?.classList.contains("active")?"AM":"PM"}return{hour:e,minute:t,ampm:s}}destroy(){this.onScrollEnd=null,this.onScrollStart=null,this.dragHandler=null}onColumnSnapped(e){const t=this.getSelectedValue(e);null!==t&&(this.isValueDisabled(e,t)?this.scrollToNextValid(e,t):this.onScrollEnd&&this.onScrollEnd(e,t))}emitScrollStart(e){this.onScrollStart&&this.onScrollStart(e)}updateVisualClasses(e){if(!this.dragHandler)return;const t=this.renderer.getItemHeight();if(t<=0)return;const s=this.dragHandler.getScrollOffset(e),r=Math.round(s/t);this.applyVisualClassesForIndex(e,r)}applyVisualClassesForIndex(e,t){const s=this.renderer.getItems(e);if(!s)return;s.forEach((e,s)=>{const r=Math.abs(s-t),l=0===r;e.classList.toggle("is-center",l),e.classList.toggle("is-near",1===r),e.setAttribute("aria-selected",String(l))});const r=this.renderer.getColumnElement(e);if(r){const e=s[t];if(e){const t=e.getAttribute("id");t&&r.setAttribute("aria-activedescendant",t)}const l=r.parentElement;l&&(l.classList.toggle("at-start",t<=0),l.classList.toggle("at-end",t>=s.length-1))}}isValueDisabled(e,t){const s=this.renderer.getItems(e);if(!s)return!1;for(let e=0;e<s.length;e++)if(s[e].getAttribute("data-value")===t)return s[e].classList.contains("is-disabled");return!1}scrollToNextValid(e,t){const s=this.renderer.getItems(e);if(!s)return;let r=-1;for(let e=0;e<s.length;e++)if(s[e].getAttribute("data-value")===t){r=e;break}if(r<0)return;const l=s.length;for(let t=1;t<=l;t++){const l=r+t,n=r-t;if(l<s.length&&!s[l].classList.contains("is-disabled")){const t=s[l].getAttribute("data-value");if(null!==t)return this.scrollToValue(e,t),void(this.onScrollEnd&&this.onScrollEnd(e,t))}if(n>=0&&!s[n].classList.contains("is-disabled")){const t=s[n].getAttribute("data-value");if(null!==t)return this.scrollToValue(e,t),void(this.onScrollEnd&&this.onScrollEnd(e,t))}}}}const a=(e,t)=>{if(!e)return;const s=e.querySelector(".timepicker-announcer");s&&(s.textContent="",setTimeout(()=>{s.textContent=t},100))},c="ArrowUp";class u{emitter;scrollHandler;core;keydownListeners=new Map;clearHandler=null;previousValues=new Map;scrollStartHandler=null;commitOnScrollTimer=null;constructor(e,t,s){this.emitter=e,this.scrollHandler=t,this.core=s}init(){this.removeKeyboardListeners(),this.removeClearListener(),this.previousValues.clear(),this.captureCurrentValues(),this.scrollHandler.setScrollEndCallback((e,t)=>{this.handleColumnScrollEnd(e,t)}),this.scrollStartHandler=e=>{this.emitter.emit("wheel:scroll:start",{column:e})},this.scrollHandler.setScrollStartCallback(this.scrollStartHandler),this.attachKeyboardListeners(),this.attachClearListener()}destroy(){this.scrollHandler.setScrollEndCallback(()=>{}),this.scrollHandler.setScrollStartCallback(null),this.removeKeyboardListeners(),this.removeClearListener(),this.previousValues.clear(),this.scrollStartHandler=null,null!==this.commitOnScrollTimer&&(clearTimeout(this.commitOnScrollTimer),this.commitOnScrollTimer=null)}handleColumnScrollEnd(e,t){const s=this.scrollHandler.getCurrentSelection(),r=this.previousValues.get(e)??null;this.emitter.emit("wheel:scroll:end",{column:e,value:t,previousValue:r}),this.previousValues.set(e,t);const l=this.core.getModalElement();switch(e){case"hours":this.syncHourInput(t),this.emitter.emit("select:hour",{hour:t}),a(l,`Hour: ${t}`);break;case"minutes":this.syncMinuteInput(t),this.emitter.emit("select:minute",{minutes:t}),a(l,`Minutes: ${t}`);break;case"ampm":this.syncAmPmState(t),"AM"===t?this.emitter.emit("select:am",{}):this.emitter.emit("select:pm",{}),a(l,`${t} selected`)}this.emitter.emit("update",{hour:s.hour,minutes:s.minute,type:s.ampm??void 0}),!0===this.core.options.wheel?.commitOnScroll&&this.scheduleCommitOnScroll()}scheduleCommitOnScroll(){null!==this.commitOnScrollTimer&&clearTimeout(this.commitOnScrollTimer),this.commitOnScrollTimer=setTimeout(()=>{this.commitOnScrollTimer=null;const e=this.scrollHandler.getCurrentSelection(),t=this.core.getInput();if(t){const s=e.ampm?` ${e.ampm}`:"";t.value=`${e.hour}:${e.minute}${s}`}this.emitter.emit("confirm",{hour:e.hour,minutes:e.minute,type:e.ampm??void 0,autoCommit:!0})},400)}syncHourInput(e){const t=this.core.getHour();t&&(t.value=e,t.setAttribute("aria-valuenow",e)),this.core.setDegreesHours(30*parseInt(e,10))}syncMinuteInput(e){const t=this.core.getMinutes();t&&(t.value=e,t.setAttribute("aria-valuenow",e)),this.core.setDegreesMinutes(6*parseInt(e,10))}syncAmPmState(e){const t=this.core.getAM(),s=this.core.getPM();t&&s&&(t.classList.toggle("active","AM"===e),s.classList.toggle("active","PM"===e))}attachKeyboardListeners(){if(!t())return;["hours","minutes","ampm"].forEach(e=>{const t=this.scrollHandler.getCurrentSelection()?this.getColumnFromRenderer(e):null;if(!t)return;const s=t=>{t.key!==c&&"ArrowDown"!==t.key||(t.preventDefault(),this.handleArrowKey(e,t.key))};t.addEventListener("keydown",s),this.keydownListeners.set(e,s)})}getColumnFromRenderer(e){if(!t())return null;const s=this.core.getModalElement();if(!s)return null;return s.querySelector({hours:".tp-ui-wheel-hours",minutes:".tp-ui-wheel-minutes",ampm:".tp-ui-wheel-ampm"}[e])}handleArrowKey(e,t){const s=this.scrollHandler.getSelectedValue(e);if(null===s)return;const r=this.getColumnFromRenderer(e);if(!r)return;const l=r.querySelectorAll(".tp-ui-wheel-item");let n=-1;for(let e=0;e<l.length;e++)if(l[e].getAttribute("data-value")===s){n=e;break}if(n<0)return;const i=n+(t===c?-1:1);if(i<0||i>=l.length)return;const o=l[i].getAttribute("data-value");null!==o&&(this.scrollHandler.scrollToValue(e,o),this.handleColumnScrollEnd(e,o))}removeKeyboardListeners(){this.keydownListeners.forEach((e,t)=>{const s=this.getColumnFromRenderer(t);s&&s.removeEventListener("keydown",e)}),this.keydownListeners.clear()}attachClearListener(){this.clearHandler=()=>{this.scrollHandler.scrollToValue("hours","12"),this.scrollHandler.scrollToValue("minutes","00"),this.scrollHandler.scrollToValue("ampm","AM")},this.emitter.on("clear",this.clearHandler)}removeClearListener(){this.clearHandler&&(this.emitter.off("clear",this.clearHandler),this.clearHandler=null)}captureCurrentValues(){const e=this.scrollHandler.getCurrentSelection();this.previousValues.set("hours",e.hour),this.previousValues.set("minutes",e.minute),null!==e.ampm&&this.previousValues.set("ampm",e.ampm)}}class h{element;columnType;_lastY=0;_isDragging=!1;_pointerId=-1;_momentumRaf=null;velocitySamples=[];snapTimeout=null;snapAnimationRaf=null;abortController=null;constructor(e,t){this.element=e,this.columnType=t,this.abortController=new AbortController}get lastY(){return this._lastY}get isDragging(){return this._isDragging}get pointerId(){return this._pointerId}get signal(){return this.abortController?this.abortController.signal:(new AbortController).signal}startDrag(e,t){this.stopMomentum(),this._isDragging=!0,this._lastY=e,this._pointerId=t,this.velocitySamples=[{time:performance.now(),y:e}]}updateLastY(e){this._lastY=e}addVelocitySample(e){this.velocitySamples.push({time:performance.now(),y:e}),this.velocitySamples.length>5&&this.velocitySamples.shift()}computeReleaseVelocity(){const e=performance.now(),t=this.velocitySamples.filter(t=>e-t.time<100);if(t.length<2)return 0;const s=t[0],r=t[t.length-1],l=r.time-s.time;return l<=0?0:(s.y-r.y)/l}endDrag(){this._isDragging=!1,this._pointerId=-1,this.velocitySamples=[]}setMomentumRaf(e){this._momentumRaf=e}hasMomentum(){return null!==this._momentumRaf}stopMomentum(){null!==this._momentumRaf&&(cancelAnimationFrame(this._momentumRaf),this._momentumRaf=null),null!==this.snapAnimationRaf&&(cancelAnimationFrame(this.snapAnimationRaf),this.snapAnimationRaf=null)}animateToOffset(e,t){this.stopMomentum();const s=this.element.scrollTop,r=e-s,l=performance.now();if(Math.abs(r)<.5)return this.element.scrollTop=e,void t();const n=()=>{const i=performance.now()-l,o=Math.min(i/180,1),a=1-Math.pow(1-o,3);this.element.scrollTop=s+r*a,o<1?this.snapAnimationRaf=requestAnimationFrame(n):(this.element.scrollTop=e,this.snapAnimationRaf=null,t())};this.snapAnimationRaf=requestAnimationFrame(n)}scheduleSnapAfterWheel(e){null!==this.snapTimeout&&clearTimeout(this.snapTimeout),this.snapTimeout=setTimeout(()=>{this.snapTimeout=null,e()},120)}destroy(){this.stopMomentum(),null!==this.snapTimeout&&(clearTimeout(this.snapTimeout),this.snapTimeout=null),this.abortController&&(this.abortController.abort(),this.abortController=null)}}class m{renderer;columnStates=new Map;onSnap=null;onVisualUpdate=null;onScrollStart=null;activeDragColumn=null;visualUpdateRaf=null;pendingVisualColumns=new Set;wheelAccumulator=new Map;pointerMoveHandler;pointerUpHandler;documentListenerController=null;constructor(e){this.renderer=e,this.pointerMoveHandler=e=>this.handlePointerMove(e),this.pointerUpHandler=e=>this.handlePointerUp(e)}setSnapCallback(e){this.onSnap=e}setVisualUpdateCallback(e){this.onVisualUpdate=e}setScrollStartCallback(e){this.onScrollStart=e}init(){if(this.cleanupPreviousInit(),!t())return;["hours","minutes","ampm"].forEach(e=>{const t=this.renderer.getColumnElement(e);if(!t)return;const s=new h(t,e);this.columnStates.set(e,s),t.addEventListener("pointerdown",t=>{this.handlePointerDown(e,t)},{signal:s.signal}),t.addEventListener("wheel",t=>{this.handleWheel(e,t)},{passive:!1,signal:s.signal})}),this.documentListenerController=new AbortController,document.addEventListener("pointermove",this.pointerMoveHandler,{signal:this.documentListenerController.signal}),document.addEventListener("pointerup",this.pointerUpHandler,{signal:this.documentListenerController.signal})}getScrollOffset(e){const t=this.renderer.getColumnElement(e);return t?t.scrollTop:0}setScrollOffset(e,t){const s=this.columnStates.get(e);s&&s.stopMomentum();const r=this.renderer.getColumnElement(e);r&&(r.scrollTop=t)}getMaxOffset(e){const t=this.renderer.getItemHeight();if(t<=0)return 0;const s=this.renderer.getItemCount(e);return Math.max(0,(s-1)*t)}destroy(){this.cleanupPreviousInit(),this.onSnap=null,this.onVisualUpdate=null,this.onScrollStart=null}cleanupPreviousInit(){null!==this.visualUpdateRaf&&(cancelAnimationFrame(this.visualUpdateRaf),this.visualUpdateRaf=null),this.pendingVisualColumns.clear(),this.wheelAccumulator.clear(),this.activeDragColumn=null,this.documentListenerController&&(this.documentListenerController.abort(),this.documentListenerController=null),this.columnStates.forEach(e=>e.destroy()),this.columnStates.clear()}handlePointerDown(e,t){const s=this.columnStates.get(e);s&&(t.preventDefault(),this.activeDragColumn=e,s.startDrag(t.clientY,t.pointerId),s.element.classList.add("is-dragging"),s.element.setPointerCapture(t.pointerId),this.onScrollStart&&this.onScrollStart(e))}handlePointerMove(e){if(null===this.activeDragColumn)return;const t=this.columnStates.get(this.activeDragColumn);if(!t||!t.isDragging||t.pointerId!==e.pointerId)return;const s=t.lastY-e.clientY;t.addVelocitySample(e.clientY);const r=this.getMaxOffset(t.columnType),l=d(t.element.scrollTop+s,0,r);t.element.scrollTop=l,t.updateLastY(e.clientY),this.scheduleVisualUpdate(t.columnType)}handlePointerUp(e){if(null===this.activeDragColumn)return;const t=this.columnStates.get(this.activeDragColumn);if(!t||!t.isDragging||t.pointerId!==e.pointerId)return;t.element.classList.remove("is-dragging"),t.element.releasePointerCapture(e.pointerId),this.activeDragColumn=null;const s=t.computeReleaseVelocity();t.endDrag(),Math.abs(s)>.3?this.startMomentum(t,s):this.snapColumn(t.columnType)}handleWheel(e,t){t.preventDefault();const s=this.columnStates.get(e);if(!s)return;const r=s.hasMomentum();s.stopMomentum(),!r&&this.onScrollStart&&this.onScrollStart(e);const l=this.renderer.getItemHeight();if(l<=0)return;const n=(this.wheelAccumulator.get(e)??0)+t.deltaY;if(this.wheelAccumulator.set(e,n),Math.abs(n)>=30){const t=n>0?1:-1;this.wheelAccumulator.set(e,0);const r=this.getMaxOffset(e),i=d((Math.round(s.element.scrollTop/l)+t)*l,0,r);s.animateToOffset(i,()=>{this.emitVisualUpdate(e),this.onSnap&&this.onSnap(e)}),this.scheduleVisualUpdate(e)}}startMomentum(e,t){let s=d(t,-8,8),r=performance.now();const l=this.getMaxOffset(e.columnType),n=()=>{const t=performance.now(),i=t-r;r=t,s*=.92;const o=s*i,a=d(e.element.scrollTop+o,0,l);if(e.element.scrollTop=a,this.emitVisualUpdate(e.columnType),Math.abs(s)<.3||a<=0||a>=l)return e.setMomentumRaf(null),void this.snapColumn(e.columnType);e.setMomentumRaf(requestAnimationFrame(n))};e.setMomentumRaf(requestAnimationFrame(n))}snapColumn(e){const t=this.columnStates.get(e);if(!t)return;const s=this.renderer.getItemHeight();if(s<=0)return;const r=this.getMaxOffset(e),l=d(Math.round(t.element.scrollTop/s)*s,0,r);t.animateToOffset(l,()=>{this.emitVisualUpdate(e),this.onSnap&&this.onSnap(e)})}scheduleVisualUpdate(e){this.pendingVisualColumns.add(e),null===this.visualUpdateRaf&&(this.visualUpdateRaf=requestAnimationFrame(()=>{this.visualUpdateRaf=null,this.pendingVisualColumns.forEach(e=>{this.emitVisualUpdate(e)}),this.pendingVisualColumns.clear()}))}emitVisualUpdate(e){this.onVisualUpdate&&this.onVisualUpdate(e)}}function d(e,t,s){return Math.max(t,Math.min(s,e))}class p{core;emitter;resizeHandler=null;scrollHandler=null;clickOutsideHandler=null;rafId=null;isAttached=!1;constructor(e,t){this.core=e,this.emitter=t}isPopoverMode(){return"compact-wheel"===this.core.options.ui.mode&&!!this.core.options.wheel?.placement}attach(){if(!this.isPopoverMode())return;if(!t())return;if(this.isAttached)return;const e=this.core.getModalElement();e&&(e.classList.add("tp-ui-popover"),this.positionPopover(),this.addListeners(),this.isAttached=!0)}detach(){this.isAttached&&(this.removeListeners(),this.isAttached=!1)}destroy(){this.detach()}positionPopover(){const e=this.core.getInput(),t=this.core.getModalElement();if(!e||!t)return;const s=e.getBoundingClientRect(),r=this.core.options.wheel?.placement??"auto",l=Math.min(Math.max(s.width,260),328);t.style.width=`${l}px`;const n=t.offsetHeight,i=this.resolvePlacement(r,s,n),o=this.computeTop(i,s,n),a=this.clampHorizontal(s.left,l);t.style.top=`${o}px`,t.style.left=`${a}px`,t.setAttribute("data-popover-placement",i)}resolvePlacement(e,t,s){if("top"===e)return"top";if("bottom"===e)return"bottom";const r=document.documentElement.clientHeight-t.bottom,l=t.top,n=s+4+16;return r>=n?"bottom":l>=n?"top":r>=l?"bottom":"top"}computeTop(e,t,s){return"top"===e?t.top-s-4:t.bottom+4}clampHorizontal(e,t){const s=document.documentElement.clientWidth;let r=e;return r+t>s&&(r=s-t-4),r<4&&(r=4),r}addListeners(){if(!t())return;this.resizeHandler=()=>{this.scheduleReposition()},this.scrollHandler=()=>{this.scheduleReposition()},this.clickOutsideHandler=e=>{this.handleClickOutside(e)},window.addEventListener("resize",this.resizeHandler,{passive:!0}),window.addEventListener("scroll",this.scrollHandler,{passive:!0,capture:!0});const e=this.clickOutsideHandler;setTimeout(()=>{e===this.clickOutsideHandler&&document.addEventListener("pointerdown",e)},0)}removeListeners(){null!==this.rafId&&(cancelAnimationFrame(this.rafId),this.rafId=null),this.resizeHandler&&(window.removeEventListener("resize",this.resizeHandler),this.resizeHandler=null),this.scrollHandler&&(window.removeEventListener("scroll",this.scrollHandler,!0),this.scrollHandler=null),this.clickOutsideHandler&&(document.removeEventListener("pointerdown",this.clickOutsideHandler),this.clickOutsideHandler=null)}scheduleReposition(){null===this.rafId&&(this.rafId=requestAnimationFrame(()=>{this.rafId=null,this.positionPopover()}))}handleClickOutside(e){if(this.core.options.wheel?.ignoreOutsideClick)return;const t=this.core.getModalElement(),s=this.core.getInput(),r=e.target;if(!t||!r)return;const l=t.contains(r),n=!!s&&s.contains(r);l||n||this.emitter.emit("cancel",{})}}class g{renderer;dragHandler;scrollHandler;eventHandler;core;emitter;popover;amPmHandler=null;hourChangeHandler=null;clearHandler=null;constructor(e,t){this.core=e,this.emitter=t,this.renderer=new i(e),this.dragHandler=new m(this.renderer),this.scrollHandler=new o(this.renderer,e),this.scrollHandler.setDragHandler(this.dragHandler),this.eventHandler=new u(t,this.scrollHandler,e),this.popover=new p(e,t)}init(){this.renderer.init(),this.dragHandler.init(),this.scrollHandler.init(),this.eventHandler.init(),this.dragHandler.setVisualUpdateCallback(e=>{this.scrollHandler.updateVisualClasses(e)}),this.listenForAmPmChanges(),this.listenForHourChanges(),this.listenForClear(),this.deferInitialSync()}scrollToValue(e,t,s){this.scrollHandler.scrollToValue("hours",e.padStart(2,"0")),this.scrollHandler.scrollToValue("minutes",t.padStart(2,"0")),s&&this.isCompactWheelMode()&&this.scrollHandler.scrollToValue("ampm",s.toUpperCase())}updateDisabledItems(){this.renderer.updateDisabledItems()}attachPopover(){this.popover.attach()}detachPopover(){this.popover.detach()}destroy(){this.popover.destroy(),this.amPmHandler&&(this.emitter.off("select:am",this.amPmHandler),this.emitter.off("select:pm",this.amPmHandler),this.amPmHandler=null),this.hourChangeHandler&&(this.emitter.off("select:hour",this.hourChangeHandler),this.hourChangeHandler=null),this.clearHandler&&(this.emitter.off("clear",this.clearHandler),this.clearHandler=null),this.eventHandler.destroy(),this.scrollHandler.destroy(),this.dragHandler.destroy(),this.renderer.destroy()}deferInitialSync(){"undefined"!=typeof requestAnimationFrame?requestAnimationFrame(()=>{this.syncInitialValues()}):this.syncInitialValues()}syncInitialValues(){const e=this.core.getHour(),t=this.core.getMinutes(),s=this.isCompactWheelMode();let r=e?.value??"",l=t?.value??"";if(s&&(!r||!l)){const e=this.parseMainInputValue();r||(r=e.hour),l||(l=e.minutes)}if(r&&this.scrollHandler.scrollToValue("hours",r.padStart(2,"0")),l&&this.scrollHandler.scrollToValue("minutes",l.padStart(2,"0")),s){const e=this.core.getAM(),t=e?.classList.contains("active")?"AM":"PM";this.scrollHandler.scrollToValue("ampm",t)}}parseMainInputValue(){const e=this.core.getInput();if(!e?.value)return{hour:"",minutes:""};const t=e.value.trim(),[s,r]=t.split(" "),[l="",n=""]=(s??"").split(":");return{hour:l.replace(/\D/g,"").padStart(2,"0"),minutes:n.replace(/\D/g,"").padStart(2,"0"),type:"12h"===this.core.options.clock.type?r:void 0}}isCompactWheelMode(){return"compact-wheel"===this.core.options.ui.mode}listenForAmPmChanges(){"24h"!==this.core.options.clock.type&&(this.amPmHandler=()=>{const e=this.scrollHandler.getSelectedValue("hours"),t=this.scrollHandler.getSelectedValue("minutes");this.renderer.updateDisabledItems(),this.scrollToFirstAvailable("hours",e),this.scrollToFirstAvailable("minutes",t)},this.emitter.on("select:am",this.amPmHandler),this.emitter.on("select:pm",this.amPmHandler))}listenForClear(){this.clearHandler=()=>{this.deferInitialSync()},this.emitter.on("clear",this.clearHandler)}listenForHourChanges(){const e=this.core.disabledTime;e?.value?.isInterval&&(this.hourChangeHandler=()=>{const e=this.scrollHandler.getSelectedValue("minutes");this.renderer.updateDisabledItems(),this.scrollToFirstAvailable("minutes",e)},this.emitter.on("select:hour",this.hourChangeHandler))}scrollToFirstAvailable(e,t){const s=this.renderer.getItems(e);if(s&&0!==s.length){if(null!==t)for(let r=0;r<s.length;r++)if(s[r].getAttribute("data-value")===t&&!s[r].classList.contains("is-disabled"))return void this.scrollHandler.scrollToValue(e,t);for(let t=0;t<s.length;t++)if(!s[t].classList.contains("is-disabled")){const r=s[t].getAttribute("data-value");if(null!==r)return void this.scrollHandler.scrollToValue(e,r)}}}}const f={name:"wheel",factory:(e,t)=>new g(e,t)};e.WheelManager=g,e.WheelPlugin=f});
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).TimepickerUIWheel={})}(this,function(e){"use strict";const t=()=>"undefined"!=typeof document,s=(e="")=>{const t=e.replace(/(AM|PM|am|pm)/,e=>` ${e}`),s=new Date(`September 20, 2000 ${t}`);return`${s.getHours().toString().padStart(2,"0")}:${s.getMinutes().toString().padStart(2,"0")}`},r=e=>{const[t,s]=e.split(":");return`${t.padStart(2,"0")}:${s.padStart(2,"0")}`},l=(e,t,l,i,n)=>{if(!(e&&t&&i&&n))return!1;const o="12h"===n?s(`${e}:${t} ${l||""}`.trim()):r(`${e}:${t}`),a=Array.isArray(i)?i:[i];for(const e of a){const[t,l]=e.trim().split("-");let i,a;if("12h"===n){const e=t.trim(),r=l.trim();if(!/\s?(AM|PM|am|pm)\s?$/.test(e)||!/\s?(AM|PM|am|pm)\s?$/.test(r))continue;i=s(e),a=s(r)}else{const e=t.trim(),s=l.trim();if(/\s?(AM|PM|am|pm)\s?/.test(e)||/\s?(AM|PM|am|pm)\s?/.test(s))continue;i=r(e),a=r(s)}if(o>=i&&o<=a)return!1}return!0},i={hours:".tp-ui-wheel-hours",minutes:".tp-ui-wheel-minutes",ampm:".tp-ui-wheel-ampm"};class n{core;columns=new Map;cachedItemHeight=null;cachedItems=new Map;removedItems=new Map;constructor(e){this.core=e}init(){if(this.cachedItems.clear(),this.cachedItemHeight=null,this.restoreRemovedItems(),!t())return;const e=this.core.getModalElement();if(!e)return;["hours","minutes","ampm"].forEach(t=>{const s=e.querySelector(i[t]);s&&this.columns.set(t,s)}),this.updateDisabledItems()}updateDisabledItems(){const e=this.core.disabledTime;if(!e?.value)return;const t=!0===this.core.options.wheel.hideDisabled;t&&(this.restoreRemovedItems(),this.invalidateItemCache()),e.value.isInterval&&e.value.intervals?this.updateDisabledByInterval(e.value,t):this.updateDisabledByFlatLists(e.value,t),t&&this.invalidateItemCache()}updateDisabledByFlatLists(e,t){const s=this.columns.get("hours"),r=this.columns.get("minutes");if(s&&e.hours){const r=new Set(e.hours.map(String));this.toggleDisabledOnItems(s,r,t)}if(r&&e.minutes){const s=new Set(e.minutes.map(String));this.toggleDisabledOnItems(r,s,t)}}updateDisabledByInterval(e,t){const s=e.clockType??"12h",r=e.intervals,i=this.getCurrentAmPm(),n=this.getCurrentHour(),o=this.columns.get("hours");if(o){o.querySelectorAll(".tp-ui-wheel-item").forEach(e=>{const l=e.getAttribute("data-value");if(null===l)return;const n=this.isHourFullyDisabled(l,i,r,s);e.classList.toggle("is-disabled",n),t&&n&&this.removeItemFromDOM(e,o)})}const a=this.columns.get("minutes");if(a){a.querySelectorAll(".tp-ui-wheel-item").forEach(e=>{const o=e.getAttribute("data-value");if(null===o)return;const c=l(n,o,i,r,s);e.classList.toggle("is-disabled",!c),t&&!c&&this.removeItemFromDOM(e,a)})}}isHourFullyDisabled(e,t,s,r){if(!s)return!1;for(let i=0;i<60;i++){const n=i.toString().padStart(2,"0");if(l(e,n,t,s,r))return!1}return!0}toggleDisabledOnItems(e,t,s){e.querySelectorAll(".tp-ui-wheel-item").forEach(r=>{const l=r.getAttribute("data-value");if(null!==l){const i=String(parseInt(l,10)),n=t.has(i)||t.has(l);r.classList.toggle("is-disabled",n),s&&n&&this.removeItemFromDOM(r,e)}})}getCurrentAmPm(){const e=this.core.getAM();return e?.classList.contains("active")?"AM":"PM"}getCurrentHour(){const e=this.core.getHour();return e?.value?.padStart(2,"0")??"12"}getColumnElement(e){return this.columns.get(e)??null}getItems(e){const t=this.cachedItems.get(e);if(t)return t;const s=this.columns.get(e);if(!s)return null;const r=s.querySelectorAll(".tp-ui-wheel-item");return this.cachedItems.set(e,r),r}invalidateItemCache(){this.cachedItems.clear(),this.cachedItemHeight=null}getItemCount(e){const t=this.getItems(e);return t?t.length:0}getItemHeight(){if(null!==this.cachedItemHeight)return this.cachedItemHeight;const e=this.columns.get("hours");if(!e)return 0;const t=e.querySelector(".tp-ui-wheel-item");if(!t)return 0;const s=t.getBoundingClientRect().height;return s>0&&(this.cachedItemHeight=s),s}removeItemFromDOM(e,t){const s=this.getColumnTypeByElement(t);if(!s)return;const r=this.removedItems.get(s)??[];r.push(e),this.removedItems.set(s,r),e.remove()}restoreRemovedItems(){["hours","minutes","ampm"].forEach(e=>{const t=this.removedItems.get(e);if(!t||0===t.length)return;const s=this.columns.get(e);if(!s)return;const r=Array.from(s.querySelectorAll(".tp-ui-wheel-item"));t.forEach(e=>{e.classList.remove("is-disabled");const t=parseInt(e.getAttribute("data-value")??"0",10),l=r.find(e=>parseInt(e.getAttribute("data-value")??"0",10)>t);if(l)s.insertBefore(e,l);else{const t=r[r.length-1],l=t?.nextSibling??null;l?s.insertBefore(e,l):s.appendChild(e)}r.push(e),r.sort((e,t)=>parseInt(e.getAttribute("data-value")??"0",10)-parseInt(t.getAttribute("data-value")??"0",10))})}),this.removedItems.clear()}getColumnTypeByElement(e){for(const[t,s]of this.columns)if(s===e)return t;return null}destroy(){this.restoreRemovedItems(),this.columns.clear(),this.cachedItems.clear(),this.cachedItemHeight=null,this.removedItems.clear()}}class o{renderer;core;dragHandler=null;onScrollEnd=null;onScrollStart=null;constructor(e,t){this.renderer=e,this.core=t}setDragHandler(e){this.dragHandler=e}init(){this.dragHandler&&(this.dragHandler.setSnapCallback(e=>{this.onColumnSnapped(e)}),this.dragHandler.setScrollStartCallback(e=>{this.emitScrollStart(e)}))}setScrollEndCallback(e){this.onScrollEnd=e}setScrollStartCallback(e){this.onScrollStart=e}scrollToValue(e,t){if(!this.renderer.getColumnElement(e)||!this.dragHandler)return;const s=this.renderer.getItemHeight();if(s<=0)return;const r=this.renderer.getItems(e);if(!r)return;let l=-1;for(let e=0;e<r.length;e++)if(r[e].getAttribute("data-value")===t){l=e;break}if(l<0)return;const i=l*s;this.dragHandler.setScrollOffset(e,i),this.applyVisualClassesForIndex(e,l)}getSelectedValue(e){if(!this.dragHandler)return null;const t=this.renderer.getItemHeight();if(t<=0)return null;const s=this.dragHandler.getScrollOffset(e),r=Math.round(s/t),l=this.renderer.getItems(e);return!l||r<0||r>=l.length?null:l[r].getAttribute("data-value")}getCurrentSelection(){const e=this.getSelectedValue("hours")??"12",t=this.getSelectedValue("minutes")??"00";let s=null;if("24h"!==this.core.options.clock.type&&(s=this.getSelectedValue("ampm"),null===s)){const e=this.core.getAM();s=e?.classList.contains("active")?"AM":"PM"}return{hour:e,minute:t,ampm:s}}destroy(){this.onScrollEnd=null,this.onScrollStart=null,this.dragHandler=null}onColumnSnapped(e){const t=this.getSelectedValue(e);null!==t&&(this.isValueDisabled(e,t)?this.scrollToNextValid(e,t):this.onScrollEnd&&this.onScrollEnd(e,t))}emitScrollStart(e){this.onScrollStart&&this.onScrollStart(e)}updateVisualClasses(e){if(!this.dragHandler)return;const t=this.renderer.getItemHeight();if(t<=0)return;const s=this.dragHandler.getScrollOffset(e),r=Math.round(s/t);this.applyVisualClassesForIndex(e,r)}applyVisualClassesForIndex(e,t){const s=this.renderer.getItems(e);if(!s)return;s.forEach((e,s)=>{const r=Math.abs(s-t),l=0===r;e.classList.toggle("is-center",l),e.classList.toggle("is-near",1===r),e.setAttribute("aria-selected",String(l))});const r=this.renderer.getColumnElement(e);if(r){const e=s[t];if(e){const t=e.getAttribute("id");t&&r.setAttribute("aria-activedescendant",t)}const l=r.parentElement;l&&(l.classList.toggle("at-start",t<=0),l.classList.toggle("at-end",t>=s.length-1))}}isValueDisabled(e,t){const s=this.renderer.getItems(e);if(!s)return!1;for(let e=0;e<s.length;e++)if(s[e].getAttribute("data-value")===t)return s[e].classList.contains("is-disabled");return!1}scrollToNextValid(e,t){const s=this.renderer.getItems(e);if(!s)return;let r=-1;for(let e=0;e<s.length;e++)if(s[e].getAttribute("data-value")===t){r=e;break}if(r<0)return;const l=s.length;for(let t=1;t<=l;t++){const l=r+t,i=r-t;if(l<s.length&&!s[l].classList.contains("is-disabled")){const t=s[l].getAttribute("data-value");if(null!==t)return this.scrollToValue(e,t),void(this.onScrollEnd&&this.onScrollEnd(e,t))}if(i>=0&&!s[i].classList.contains("is-disabled")){const t=s[i].getAttribute("data-value");if(null!==t)return this.scrollToValue(e,t),void(this.onScrollEnd&&this.onScrollEnd(e,t))}}}}const a=(e,t)=>{if(!e)return;const s=e.querySelector(".timepicker-announcer");s&&(s.textContent="",setTimeout(()=>{s.textContent=t},100))},c="ArrowUp";class u{emitter;scrollHandler;core;keydownListeners=new Map;clearHandler=null;previousValues=new Map;scrollStartHandler=null;commitOnScrollTimer=null;constructor(e,t,s){this.emitter=e,this.scrollHandler=t,this.core=s}init(){this.removeKeyboardListeners(),this.removeClearListener(),this.previousValues.clear(),this.captureCurrentValues(),this.scrollHandler.setScrollEndCallback((e,t)=>{this.handleColumnScrollEnd(e,t)}),this.scrollStartHandler=e=>{this.emitter.emit("wheel:scroll:start",{column:e})},this.scrollHandler.setScrollStartCallback(this.scrollStartHandler),this.attachKeyboardListeners(),this.attachClearListener()}destroy(){this.scrollHandler.setScrollEndCallback(()=>{}),this.scrollHandler.setScrollStartCallback(null),this.removeKeyboardListeners(),this.removeClearListener(),this.previousValues.clear(),this.scrollStartHandler=null,null!==this.commitOnScrollTimer&&(clearTimeout(this.commitOnScrollTimer),this.commitOnScrollTimer=null)}handleColumnScrollEnd(e,t){const s=this.scrollHandler.getCurrentSelection(),r=this.previousValues.get(e)??null;this.emitter.emit("wheel:scroll:end",{column:e,value:t,previousValue:r}),this.previousValues.set(e,t);const l=this.core.getModalElement();switch(e){case"hours":this.syncHourInput(t),this.emitter.emit("select:hour",{hour:t}),a(l,`Hour: ${t}`);break;case"minutes":this.syncMinuteInput(t),this.emitter.emit("select:minute",{minutes:t}),a(l,`Minutes: ${t}`);break;case"ampm":this.syncAmPmState(t),"AM"===t?this.emitter.emit("select:am",{}):this.emitter.emit("select:pm",{}),a(l,`${t} selected`)}this.emitter.emit("update",{hour:s.hour,minutes:s.minute,type:s.ampm??void 0}),!0===this.core.options.wheel?.commitOnScroll&&this.scheduleCommitOnScroll()}scheduleCommitOnScroll(){null!==this.commitOnScrollTimer&&clearTimeout(this.commitOnScrollTimer),this.commitOnScrollTimer=setTimeout(()=>{this.commitOnScrollTimer=null;const e=this.scrollHandler.getCurrentSelection(),t=this.core.getInput();if(t){const s=e.ampm?` ${e.ampm}`:"";t.value=`${e.hour}:${e.minute}${s}`}this.emitter.emit("confirm",{hour:e.hour,minutes:e.minute,type:e.ampm??void 0,autoCommit:!0})},400)}syncHourInput(e){const t=this.core.getHour();t&&(t.value=e,t.setAttribute("aria-valuenow",e)),this.core.setDegreesHours(30*parseInt(e,10))}syncMinuteInput(e){const t=this.core.getMinutes();t&&(t.value=e,t.setAttribute("aria-valuenow",e)),this.core.setDegreesMinutes(6*parseInt(e,10))}syncAmPmState(e){const t=this.core.getAM(),s=this.core.getPM();t&&s&&(t.classList.toggle("active","AM"===e),s.classList.toggle("active","PM"===e))}attachKeyboardListeners(){if(!t())return;["hours","minutes","ampm"].forEach(e=>{const t=this.scrollHandler.getCurrentSelection()?this.getColumnFromRenderer(e):null;if(!t)return;const s=t=>{t.key!==c&&"ArrowDown"!==t.key||(t.preventDefault(),this.handleArrowKey(e,t.key))};t.addEventListener("keydown",s),this.keydownListeners.set(e,s)})}getColumnFromRenderer(e){if(!t())return null;const s=this.core.getModalElement();if(!s)return null;return s.querySelector({hours:".tp-ui-wheel-hours",minutes:".tp-ui-wheel-minutes",ampm:".tp-ui-wheel-ampm"}[e])}handleArrowKey(e,t){const s=this.scrollHandler.getSelectedValue(e);if(null===s)return;const r=this.getColumnFromRenderer(e);if(!r)return;const l=r.querySelectorAll(".tp-ui-wheel-item");let i=-1;for(let e=0;e<l.length;e++)if(l[e].getAttribute("data-value")===s){i=e;break}if(i<0)return;const n=i+(t===c?-1:1);if(n<0||n>=l.length)return;const o=l[n].getAttribute("data-value");null!==o&&(this.scrollHandler.scrollToValue(e,o),this.handleColumnScrollEnd(e,o))}removeKeyboardListeners(){this.keydownListeners.forEach((e,t)=>{const s=this.getColumnFromRenderer(t);s&&s.removeEventListener("keydown",e)}),this.keydownListeners.clear()}attachClearListener(){this.clearHandler=()=>{this.scrollHandler.scrollToValue("hours","12"),this.scrollHandler.scrollToValue("minutes","00"),this.scrollHandler.scrollToValue("ampm","AM")},this.emitter.on("clear",this.clearHandler)}removeClearListener(){this.clearHandler&&(this.emitter.off("clear",this.clearHandler),this.clearHandler=null)}captureCurrentValues(){const e=this.scrollHandler.getCurrentSelection();this.previousValues.set("hours",e.hour),this.previousValues.set("minutes",e.minute),null!==e.ampm&&this.previousValues.set("ampm",e.ampm)}}class h{element;columnType;_lastY=0;_isDragging=!1;_pointerId=-1;_momentumRaf=null;velocitySamples=[];snapTimeout=null;snapAnimationRaf=null;abortController=null;constructor(e,t){this.element=e,this.columnType=t,this.abortController=new AbortController}get lastY(){return this._lastY}get isDragging(){return this._isDragging}get pointerId(){return this._pointerId}get signal(){return this.abortController?this.abortController.signal:(new AbortController).signal}startDrag(e,t){this.stopMomentum(),this._isDragging=!0,this._lastY=e,this._pointerId=t,this.velocitySamples=[{time:performance.now(),y:e}]}updateLastY(e){this._lastY=e}addVelocitySample(e){this.velocitySamples.push({time:performance.now(),y:e}),this.velocitySamples.length>5&&this.velocitySamples.shift()}computeReleaseVelocity(){const e=performance.now(),t=this.velocitySamples.filter(t=>e-t.time<100);if(t.length<2)return 0;const s=t[0],r=t[t.length-1],l=r.time-s.time;return l<=0?0:(s.y-r.y)/l}endDrag(){this._isDragging=!1,this._pointerId=-1,this.velocitySamples=[]}setMomentumRaf(e){this._momentumRaf=e}hasMomentum(){return null!==this._momentumRaf}stopMomentum(){null!==this._momentumRaf&&(cancelAnimationFrame(this._momentumRaf),this._momentumRaf=null),null!==this.snapAnimationRaf&&(cancelAnimationFrame(this.snapAnimationRaf),this.snapAnimationRaf=null)}animateToOffset(e,t){this.stopMomentum();const s=this.element.scrollTop,r=e-s,l=performance.now();if(Math.abs(r)<.5)return this.element.scrollTop=e,void t();const i=()=>{const n=performance.now()-l,o=Math.min(n/180,1),a=1-Math.pow(1-o,3);this.element.scrollTop=s+r*a,o<1?this.snapAnimationRaf=requestAnimationFrame(i):(this.element.scrollTop=e,this.snapAnimationRaf=null,t())};this.snapAnimationRaf=requestAnimationFrame(i)}scheduleSnapAfterWheel(e){null!==this.snapTimeout&&clearTimeout(this.snapTimeout),this.snapTimeout=setTimeout(()=>{this.snapTimeout=null,e()},120)}destroy(){this.stopMomentum(),null!==this.snapTimeout&&(clearTimeout(this.snapTimeout),this.snapTimeout=null),this.abortController&&(this.abortController.abort(),this.abortController=null)}}class m{renderer;columnStates=new Map;onSnap=null;onVisualUpdate=null;onScrollStart=null;activeDragColumn=null;visualUpdateRaf=null;pendingVisualColumns=new Set;wheelAccumulator=new Map;pointerMoveHandler;pointerUpHandler;documentListenerController=null;constructor(e){this.renderer=e,this.pointerMoveHandler=e=>this.handlePointerMove(e),this.pointerUpHandler=e=>this.handlePointerUp(e)}setSnapCallback(e){this.onSnap=e}setVisualUpdateCallback(e){this.onVisualUpdate=e}setScrollStartCallback(e){this.onScrollStart=e}init(){if(this.cleanupPreviousInit(),!t())return;["hours","minutes","ampm"].forEach(e=>{const t=this.renderer.getColumnElement(e);if(!t)return;const s=new h(t,e);this.columnStates.set(e,s),t.addEventListener("pointerdown",t=>{this.handlePointerDown(e,t)},{signal:s.signal}),t.addEventListener("wheel",t=>{this.handleWheel(e,t)},{passive:!1,signal:s.signal})}),this.documentListenerController=new AbortController,document.addEventListener("pointermove",this.pointerMoveHandler,{signal:this.documentListenerController.signal}),document.addEventListener("pointerup",this.pointerUpHandler,{signal:this.documentListenerController.signal})}getScrollOffset(e){const t=this.renderer.getColumnElement(e);return t?t.scrollTop:0}setScrollOffset(e,t){const s=this.columnStates.get(e);s&&s.stopMomentum();const r=this.renderer.getColumnElement(e);r&&(r.scrollTop=t)}getMaxOffset(e){const t=this.renderer.getItemHeight();if(t<=0)return 0;const s=this.renderer.getItemCount(e);return Math.max(0,(s-1)*t)}destroy(){this.cleanupPreviousInit(),this.onSnap=null,this.onVisualUpdate=null,this.onScrollStart=null}cleanupPreviousInit(){null!==this.visualUpdateRaf&&(cancelAnimationFrame(this.visualUpdateRaf),this.visualUpdateRaf=null),this.pendingVisualColumns.clear(),this.wheelAccumulator.clear(),this.activeDragColumn=null,this.documentListenerController&&(this.documentListenerController.abort(),this.documentListenerController=null),this.columnStates.forEach(e=>e.destroy()),this.columnStates.clear()}handlePointerDown(e,t){const s=this.columnStates.get(e);s&&(t.preventDefault(),this.activeDragColumn=e,s.startDrag(t.clientY,t.pointerId),s.element.classList.add("is-dragging"),s.element.setPointerCapture(t.pointerId),this.onScrollStart&&this.onScrollStart(e))}handlePointerMove(e){if(null===this.activeDragColumn)return;const t=this.columnStates.get(this.activeDragColumn);if(!t||!t.isDragging||t.pointerId!==e.pointerId)return;const s=t.lastY-e.clientY;t.addVelocitySample(e.clientY);const r=this.getMaxOffset(t.columnType),l=d(t.element.scrollTop+s,0,r);t.element.scrollTop=l,t.updateLastY(e.clientY),this.scheduleVisualUpdate(t.columnType)}handlePointerUp(e){if(null===this.activeDragColumn)return;const t=this.columnStates.get(this.activeDragColumn);if(!t||!t.isDragging||t.pointerId!==e.pointerId)return;t.element.classList.remove("is-dragging"),t.element.releasePointerCapture(e.pointerId),this.activeDragColumn=null;const s=t.computeReleaseVelocity();t.endDrag(),Math.abs(s)>.3?this.startMomentum(t,s):this.snapColumn(t.columnType)}handleWheel(e,t){t.preventDefault();const s=this.columnStates.get(e);if(!s)return;const r=s.hasMomentum();s.stopMomentum(),!r&&this.onScrollStart&&this.onScrollStart(e);const l=this.renderer.getItemHeight();if(l<=0)return;const i=(this.wheelAccumulator.get(e)??0)+t.deltaY;if(this.wheelAccumulator.set(e,i),Math.abs(i)>=30){const t=i>0?1:-1;this.wheelAccumulator.set(e,0);const r=this.getMaxOffset(e),n=d((Math.round(s.element.scrollTop/l)+t)*l,0,r);s.animateToOffset(n,()=>{this.emitVisualUpdate(e),this.onSnap&&this.onSnap(e)}),this.scheduleVisualUpdate(e)}}startMomentum(e,t){let s=d(t,-8,8),r=performance.now();const l=this.getMaxOffset(e.columnType),i=()=>{const t=performance.now(),n=t-r;r=t,s*=.92;const o=s*n,a=d(e.element.scrollTop+o,0,l);if(e.element.scrollTop=a,this.emitVisualUpdate(e.columnType),Math.abs(s)<.3||a<=0||a>=l)return e.setMomentumRaf(null),void this.snapColumn(e.columnType);e.setMomentumRaf(requestAnimationFrame(i))};e.setMomentumRaf(requestAnimationFrame(i))}snapColumn(e){const t=this.columnStates.get(e);if(!t)return;const s=this.renderer.getItemHeight();if(s<=0)return;const r=this.getMaxOffset(e),l=d(Math.round(t.element.scrollTop/s)*s,0,r);t.animateToOffset(l,()=>{this.emitVisualUpdate(e),this.onSnap&&this.onSnap(e)})}scheduleVisualUpdate(e){this.pendingVisualColumns.add(e),null===this.visualUpdateRaf&&(this.visualUpdateRaf=requestAnimationFrame(()=>{this.visualUpdateRaf=null,this.pendingVisualColumns.forEach(e=>{this.emitVisualUpdate(e)}),this.pendingVisualColumns.clear()}))}emitVisualUpdate(e){this.onVisualUpdate&&this.onVisualUpdate(e)}}function d(e,t,s){return Math.max(t,Math.min(s,e))}class p{core;emitter;resizeHandler=null;scrollHandler=null;clickOutsideHandler=null;rafId=null;isAttached=!1;constructor(e,t){this.core=e,this.emitter=t}isPopoverMode(){return"compact-wheel"===this.core.options.ui.mode&&!!this.core.options.wheel?.placement}attach(){if(!this.isPopoverMode())return;if(!t())return;if(this.isAttached)return;const e=this.core.getModalElement();e&&(e.classList.add("tp-ui-popover"),this.positionPopover(),this.addListeners(),this.isAttached=!0)}detach(){this.isAttached&&(this.removeListeners(),this.isAttached=!1)}destroy(){this.detach()}positionPopover(){const e=this.core.getInput(),t=this.core.getModalElement();if(!e||!t)return;const s=e.getBoundingClientRect(),r=this.core.options.wheel?.placement??"auto",l=Math.min(Math.max(s.width,260),328);t.style.width=`${l}px`;const i=t.offsetHeight,n=this.resolvePlacement(r,s,i),o=this.computeTop(n,s,i),a=this.clampHorizontal(s.left,l);t.style.top=`${o}px`,t.style.left=`${a}px`,t.setAttribute("data-popover-placement",n)}resolvePlacement(e,t,s){if("top"===e)return"top";if("bottom"===e)return"bottom";const r=document.documentElement.clientHeight-t.bottom,l=t.top,i=s+4+16;return r>=i?"bottom":l>=i?"top":r>=l?"bottom":"top"}computeTop(e,t,s){return"top"===e?t.top-s-4:t.bottom+4}clampHorizontal(e,t){const s=document.documentElement.clientWidth;let r=e;return r+t>s&&(r=s-t-4),r<4&&(r=4),r}addListeners(){if(!t())return;this.resizeHandler=()=>{this.scheduleReposition()},this.scrollHandler=()=>{this.scheduleReposition()},this.clickOutsideHandler=e=>{this.handleClickOutside(e)},window.addEventListener("resize",this.resizeHandler,{passive:!0}),window.addEventListener("scroll",this.scrollHandler,{passive:!0,capture:!0});const e=this.clickOutsideHandler;setTimeout(()=>{e===this.clickOutsideHandler&&document.addEventListener("pointerdown",e)},0)}removeListeners(){null!==this.rafId&&(cancelAnimationFrame(this.rafId),this.rafId=null),this.resizeHandler&&(window.removeEventListener("resize",this.resizeHandler),this.resizeHandler=null),this.scrollHandler&&(window.removeEventListener("scroll",this.scrollHandler,!0),this.scrollHandler=null),this.clickOutsideHandler&&(document.removeEventListener("pointerdown",this.clickOutsideHandler),this.clickOutsideHandler=null)}scheduleReposition(){null===this.rafId&&(this.rafId=requestAnimationFrame(()=>{this.rafId=null,this.positionPopover()}))}handleClickOutside(e){if(this.core.options.wheel?.ignoreOutsideClick)return;const t=this.core.getModalElement(),s=this.core.getInput(),r=e.target;if(!t||!r)return;const l=t.contains(r),i=!!s&&s.contains(r);l||i||this.emitter.emit("cancel",{})}}class g{renderer;dragHandler;scrollHandler;eventHandler;core;emitter;popover;amPmHandler=null;hourChangeHandler=null;clearHandler=null;constructor(e,t){this.core=e,this.emitter=t,this.renderer=new n(e),this.dragHandler=new m(this.renderer),this.scrollHandler=new o(this.renderer,e),this.scrollHandler.setDragHandler(this.dragHandler),this.eventHandler=new u(t,this.scrollHandler,e),this.popover=new p(e,t)}init(){this.renderer.init(),this.dragHandler.init(),this.scrollHandler.init(),this.eventHandler.init(),this.dragHandler.setVisualUpdateCallback(e=>{this.scrollHandler.updateVisualClasses(e)}),this.listenForAmPmChanges(),this.listenForHourChanges(),this.listenForClear(),this.deferInitialSync()}scrollToValue(e,t,s){this.scrollHandler.scrollToValue("hours",e.padStart(2,"0")),this.scrollHandler.scrollToValue("minutes",t.padStart(2,"0")),s&&this.isCompactWheelMode()&&this.scrollHandler.scrollToValue("ampm",s.toUpperCase())}updateDisabledItems(){this.renderer.updateDisabledItems()}attachPopover(){this.popover.attach()}detachPopover(){this.popover.detach()}destroy(){this.popover.destroy(),this.amPmHandler&&(this.emitter.off("select:am",this.amPmHandler),this.emitter.off("select:pm",this.amPmHandler),this.amPmHandler=null),this.hourChangeHandler&&(this.emitter.off("select:hour",this.hourChangeHandler),this.hourChangeHandler=null),this.clearHandler&&(this.emitter.off("clear",this.clearHandler),this.clearHandler=null),this.eventHandler.destroy(),this.scrollHandler.destroy(),this.dragHandler.destroy(),this.renderer.destroy()}deferInitialSync(){"undefined"!=typeof requestAnimationFrame?requestAnimationFrame(()=>{this.syncInitialValues()}):this.syncInitialValues()}syncInitialValues(){const e=this.core.getHour(),t=this.core.getMinutes(),s=this.isCompactWheelMode();let r=e?.value??"",l=t?.value??"";if(s&&(!r||!l)){const e=this.parseMainInputValue();r||(r=e.hour),l||(l=e.minutes)}if(r&&this.scrollHandler.scrollToValue("hours",r.padStart(2,"0")),l&&this.scrollHandler.scrollToValue("minutes",l.padStart(2,"0")),s){const e=this.core.getAM(),t=e?.classList.contains("active")?"AM":"PM";this.scrollHandler.scrollToValue("ampm",t)}}parseMainInputValue(){const e=this.core.getInput();if(!e?.value)return{hour:"",minutes:""};const t=e.value.trim(),[s,r]=t.split(" "),[l="",i=""]=(s??"").split(":");return{hour:l.replace(/\D/g,"").padStart(2,"0"),minutes:i.replace(/\D/g,"").padStart(2,"0"),type:"12h"===this.core.options.clock.type?r:void 0}}isCompactWheelMode(){return"compact-wheel"===this.core.options.ui.mode}listenForAmPmChanges(){"24h"!==this.core.options.clock.type&&(this.amPmHandler=()=>{const e=this.scrollHandler.getSelectedValue("hours"),t=this.scrollHandler.getSelectedValue("minutes");this.renderer.updateDisabledItems(),this.scrollToFirstAvailable("hours",e),this.scrollToFirstAvailable("minutes",t)},this.emitter.on("select:am",this.amPmHandler),this.emitter.on("select:pm",this.amPmHandler))}listenForClear(){this.clearHandler=()=>{this.deferInitialSync()},this.emitter.on("clear",this.clearHandler)}listenForHourChanges(){const e=this.core.disabledTime;e?.value?.isInterval&&(this.hourChangeHandler=()=>{const e=this.scrollHandler.getSelectedValue("minutes");this.renderer.updateDisabledItems(),this.scrollToFirstAvailable("minutes",e)},this.emitter.on("select:hour",this.hourChangeHandler))}scrollToFirstAvailable(e,t){const s=this.renderer.getItems(e);if(s&&0!==s.length){if(null!==t)for(let r=0;r<s.length;r++)if(s[r].getAttribute("data-value")===t&&!s[r].classList.contains("is-disabled"))return void this.scrollHandler.scrollToValue(e,t);for(let t=0;t<s.length;t++)if(!s[t].classList.contains("is-disabled")){const r=s[t].getAttribute("data-value");if(null!==r)return void this.scrollHandler.scrollToValue(e,r)}}}}const f=e=>String(e).padStart(2,"0"),v=()=>Array.from({length:2}).map(()=>'<div class="tp-ui-wheel-padding"></div>').join(""),S=(e,t,s,r,l)=>`<div class="tp-ui-wheel-column-wrapper at-start"><div class="tp-ui-wheel-column ${e}" role="listbox" aria-label="${t}" aria-activedescendant="" tabindex="0">${v()}${((e,t,s)=>e.map(e=>`<div class="tp-ui-wheel-item" role="option" id="${s}-${e}" data-value="${e}" aria-label="${t} ${e}" aria-selected="false">${e}</div>`).join(""))(s,r,l)}${v()}</div></div>`,H=["AM","PM"],C=(e,t,s=!1,r="tp")=>{const l="12h"===e?Array.from({length:12},(e,t)=>f(t+1)):Array.from({length:24},(e,t)=>f(t)),i=(n=t,Array.from({length:Math.ceil(60/n)},(e,t)=>f(t*n)));var n;return`<div class="tp-ui-wheel-container">${S("tp-ui-wheel-hours","Hours",l,"Hour",`${r}-wh`)}<div class="tp-ui-wheel-separator" aria-hidden="true">:</div>${S("tp-ui-wheel-minutes","Minutes",i,"Minute",`${r}-wm`)}${s&&"12h"===e?S("tp-ui-wheel-ampm","Period",H,"Period",`${r}-wp`):""}<div class="tp-ui-wheel-highlight" aria-hidden="true"></div></div>`},y={name:"wheel",factory:(e,t)=>new g(e,t),templateProvider:(e,t)=>{const s="compact-wheel"===e.ui.mode&&"12h"===e.clock.type;return C(e.clock.type,e.clock.incrementMinutes??1,s,t)}};e.WheelManager=g,e.WheelPlugin=y});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "timepicker-ui",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.0",
|
|
4
4
|
"description": "timepicker-ui is a customizable time picker library built with TypeScript, inspired by Google's Material Design. Lightweight, themeable, and easy to integrate.",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -74,8 +74,6 @@
|
|
|
74
74
|
"author": "Piotr Glejzer (@pglejzer)",
|
|
75
75
|
"license": "MIT",
|
|
76
76
|
"sideEffects": [
|
|
77
|
-
"./dist/plugins/*.js",
|
|
78
|
-
"./dist/plugins/*.cjs",
|
|
79
77
|
"./dist/css/**/*.css"
|
|
80
78
|
],
|
|
81
79
|
"bugs": {
|