@wpmoo/ui 1.0.0-rc.1 → 1.0.0-rc.3
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/ASSET_LICENSE.md +2 -2
- package/README.md +32 -16
- package/THIRD_PARTY_NOTICES.md +53 -0
- package/certification.json +8 -3
- package/dist/assets/css/moo-ui.css +10095 -8896
- package/dist/assets/css/moo-ui.min.css +5 -2
- package/dist/assets/css/moo.css +1425 -382
- package/dist/assets/css/moo.min.css +5 -2
- package/dist/js/chart.js +15258 -0
- package/dist/js/chart.min.js +27 -0
- package/dist/js/combobox.js +69 -31
- package/dist/js/context-menu.js +22 -1
- package/dist/js/datatable.js +198 -24
- package/dist/js/datepicker.js +1154 -0
- package/dist/js/datepicker.min.js +6 -0
- package/dist/js/sidebar.js +67 -25
- package/dist/js/slider.js +324 -0
- package/package.json +19 -7
- package/scss/_config.scss +24 -0
- package/scss/_facade-settings.scss +0 -51
- package/scss/settings/_facade_public.scss +0 -23
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Moo UI datepicker.min.js v1.0.0-rc.3 (https://ui.wpmoo.org/)
|
|
3
|
+
* Copyright 2026 WPMoo (https://wpmoo.org)
|
|
4
|
+
* Licensed under MIT (https://github.com/wpmoo-org/ui/blob/main/LICENSE)
|
|
5
|
+
*/
|
|
6
|
+
var x=new WeakMap,V=new WeakMap,M=new WeakMap,w="en",pt=1440*60*1e3,nt=new Date(2026,7,16),C=8;function H(i,t){return i?.nodeType===1&&!!i.matches?.(t)}function h(i,t,e,a,s){t&&(t.addEventListener(e,a,s),i.push({target:t,type:e,handler:a,options:s}))}function S(i){i.forEach(({target:t,type:e,handler:a,options:s})=>{t.removeEventListener(e,a,s)}),i.length=0}function d(i){if(!i)return null;if(i instanceof Date)return Number.isNaN(i.getTime())?null:new Date(i.getFullYear(),i.getMonth(),i.getDate());if(typeof i=="number")return d(new Date(i));let t=String(i).trim(),e=/^(\d{4})-(\d{2})-(\d{2})$/.exec(t);if(e){let a=new Date(Number(e[1]),Number(e[2])-1,Number(e[3]));return a.getFullYear()===Number(e[1])&&a.getMonth()===Number(e[2])-1&&a.getDate()===Number(e[3])?a:null}return null}function j(i){return String(i).padStart(2,"0")}function f(i){return`${i.getFullYear()}-${j(i.getMonth()+1)}-${j(i.getDate())}`}function g(i,t){return!i||!t?0:i.getTime()-t.getTime()}function k(i,t){return!!(i&&t&&f(i)===f(t))}function b(i,t){return new Date(i.getFullYear(),i.getMonth(),i.getDate()+t)}function q(i,t){let e=new Date(i.getFullYear(),i.getMonth()+t,1),a=Math.min(i.getDate(),$(e.getFullYear(),e.getMonth()));return new Date(e.getFullYear(),e.getMonth(),a)}function L(i=w){try{if(typeof Intl<"u"&&typeof Intl.Locale=="function"){let t=new Intl.Locale(i||w),e=t.weekInfo||t.getWeekInfo?.();if(Number.isInteger(e?.firstDay))return e.firstDay%7}}catch{}return 0}function rt(i=w){let t=L(i);return Array.from({length:7},(e,a)=>b(nt,(t+a)%7))}function y(i){return new Date(i.getFullYear(),i.getMonth(),1)}function $(i,t){return new Date(i,t+1,0).getDate()}function ot(i,t,e){return t&&g(i,t)<0?new Date(t):e&&g(i,e)>0?new Date(e):i}function lt(i){if(Array.isArray(i))return i.map(d).filter(Boolean).map(f);if(!i)return[];let t=String(i).trim();if(!t)return[];try{let e=JSON.parse(t);if(Array.isArray(e))return e.map(d).filter(Boolean).map(f)}catch{}return t.split(",").map(d).filter(Boolean).map(f)}function A(i,t=w){return i?new Intl.DateTimeFormat(t||w,{month:"short",day:"numeric",year:"numeric"}).format(i):""}function Q(i,t=w){return new Intl.DateTimeFormat(t||w,{month:"long",year:"numeric"}).format(i)}function R(i,t,e=w){if(i)return t==="yyyy-mm-dd"?f(i):t?A(i,e):new Date(i)}function z(i,t={}){let e=i.dataset||{},a=t.locale||e.datepickerLocale||e.calendarLocale||w,s=d(t.minDate||e.calendarMinDate||e.datepickerMinDate),n=d(t.maxDate||e.calendarMaxDate||e.datepickerMaxDate);return{locale:a,mode:t.mode||e.calendarMode||e.datepickerMode||"single",placeholder:t.placeholder||e.datepickerPlaceholder||"Pick a date",value:t.value||e.calendarValue||e.datepickerValue||"",startValue:t.startValue||e.calendarStartValue||e.datepickerStartValue||"",endValue:t.endValue||e.calendarEndValue||e.datepickerEndValue||"",minDate:s,maxDate:n,disabledDates:lt(t.disabledDates||e.calendarDisabledDates||e.datepickerDisabledDates),captionLayout:t.captionLayout||e.calendarCaptionLayout||"",showPresets:t.showPresets??(e.calendarShowPresets==="true"||e.datepickerShowPresets==="true")}}function m(i,t,e,a={},s=!1){return i.dispatchEvent(new t.CustomEvent(e,{bubbles:!0,cancelable:s,detail:a}))}function B(i,t){i&&(i.value=t||"")}function it(i,t){i&&(i.value=t||"")}function U(i,t,e){if(e){i.dataset.invalid="true",t.classList.add("is-invalid"),t.setAttribute("aria-invalid","true");return}delete i.dataset.invalid,t.classList.remove("is-invalid"),t.removeAttribute("aria-invalid")}function at(i,t,e){e?.required&&e.checkValidity()&&U(i,t,!1)}function X(i,t,e){return e<t?t:Math.min(Math.max(i,t),e)}function dt(i,t,e){let a=i?.ownerDocument?.defaultView||window,s=i?a.getComputedStyle(i).getPropertyValue(t).trim():"",n=Number.parseFloat(s);if(!Number.isFinite(n))return e;if(s.endsWith("rem")){let r=i.ownerDocument.documentElement,_=Number.parseFloat(a.getComputedStyle(r).fontSize);return Number.isFinite(_)?n*_:e}if(s.endsWith("em")){let r=Number.parseFloat(a.getComputedStyle(i).fontSize);return Number.isFinite(r)?n*r:e}return Number.isFinite(n)?n:e}function P(i,t){return!!(t&&(i._element.contains(t)||i._popover.contains(t)))}function Z(i){let t=i._element.closest("[data-bs-theme]")?.getAttribute("data-bs-theme")||i._document.documentElement.getAttribute("data-bs-theme"),e=getComputedStyle(i._trigger).direction;t&&i._popover.setAttribute("data-bs-theme",t),e==="rtl"&&i._popover.setAttribute("dir","rtl")}function ht(i){let t=i._popover;if(i._popoverPortal?.host?.parentElement===i._document.body){Z(i);return}let e=i._document.createElement("div");e.className="moo-ui",e.dataset.datepickerPortalHost="",i._popoverPortal={parent:t.parentNode,nextSibling:t.nextSibling,host:e,hadTheme:t.hasAttribute("data-bs-theme"),theme:t.getAttribute("data-bs-theme"),hadDirection:t.hasAttribute("dir"),direction:t.getAttribute("dir")},e.appendChild(t),i._document.body.appendChild(e),Z(i)}function K(i){let t=i._popoverPortal;if(!t)return;let e=i._popover;t.parent?.isConnected?t.nextSibling?.parentNode===t.parent?t.parent.insertBefore(e,t.nextSibling):t.parent.appendChild(e):e.remove(),t.host?.remove(),t.hadTheme?e.setAttribute("data-bs-theme",t.theme):e.removeAttribute("data-bs-theme"),t.hadDirection?e.setAttribute("dir",t.direction):e.removeAttribute("dir"),i._popoverPortal=null}function ct(i,t,e,a){let s=dt(e,"--moo-datepicker-popover-offset",6),n=getComputedStyle(i).direction;t.style.position="fixed",t.style.inset="auto",t.style.right="auto",t.style.bottom="auto",t.style.maxHeight="",t.style.overflowY="";let r=i.getBoundingClientRect(),_=t.getBoundingClientRect(),E=a.innerWidth,D=a.innerHeight,N=n==="rtl"?r.right-_.width:r.left,Y=X(N,C,E-_.width-C),I=r.bottom+s<=D?D-r.bottom-s-C:0,c=r.top-s-C,l=_.height>I&&c>I,u=l?"top":"bottom",o=Math.max(0,l?c:I),F=Math.min(_.height,o),v=l?r.top-s-F:r.bottom+s;t.style.left=`${Math.round(Y)}px`,t.style.top=`${Math.round(X(v,C,D-F-C))}px`,o>0&&(t.style.maxHeight=`${Math.floor(o)}px`,t.style.overflowY="auto"),t.dataset.datepickerPlacement=u}function ut(i){i.style.position="",i.style.inset="",i.style.right="",i.style.bottom="",i.style.left="",i.style.top="",i.style.maxHeight="",i.style.overflowY="",delete i.dataset.datepickerPlacement}function st(i){S(i._floatingListeners),ht(i);let t=()=>{i.isOpen()&&ct(i._trigger,i._popover,i._element,i._window)};i._positionPopover=t,t(),h(i._floatingListeners,i._window,"resize",t),h(i._floatingListeners,i._window,"scroll",t,!0),h(i._floatingListeners,i._document,"scroll",t,!0)}function O(i){S(i._floatingListeners),i._positionPopover=null,ut(i._popover),K(i)}function _t(i,t){return new Intl.DateTimeFormat(t||w,{month:"short"}).format(new Date(2026,i,1))}function ft(i,t,e){let a=i?i.getFullYear():e.getFullYear()-100,s=t?t.getFullYear():e.getFullYear()+20,n=[];for(let r=a;r<=s;r+=1)n.push(r);return n}function tt(i,t,e=""){let a=i.createElement("span");return a.className=e,a.setAttribute("aria-hidden","true"),a.textContent=t,a}var T=class i{static getInstance(t){return t?.nodeType===1&&V.get(t)||null}static getOrCreateInstance(t,e={}){return i.getInstance(t)||new i(t,e)}constructor(t,e={}){if(!H(t,"[data-calendar]"))throw new TypeError("MooCalendar requires a [data-calendar] root element.");let a=V.get(t);if(a)return a;this._element=t,this._document=t.ownerDocument,this._window=this._document.defaultView||window,this._listeners=[],this._disposed=!1,this._config=z(t,e),this._mode=this._config.mode==="range"?"range":"single",this._disabledDates=new Set(this._config.disabledDates),this._selectedDate=d(this._config.value),this._rangeStart=d(this._config.startValue),this._rangeEnd=d(this._config.endValue),this._activeDate=this._nearestEnabledDate(this._rangeStart||this._selectedDate||new Date),this._viewDate=y(this._activeDate),this._captionId=this._element.id?`${this._element.id}-caption`:`moo-calendar-caption-${Math.random().toString(36).slice(2)}`,this._labelId=this._element.id?`${this._element.id}-label`:`moo-calendar-label-${Math.random().toString(36).slice(2)}`,V.set(t,this),this._bindEvents(),this._render()}dispose(){this._disposed||(this._disposed=!0,S(this._listeners),this._element.replaceChildren(),V.get(this._element)===this&&V.delete(this._element))}getDate(t=void 0){return this._mode==="range"?this.getDates(t):R(this._selectedDate,t,this._config.locale)}getDates(t=void 0){return[R(this._rangeStart,t,this._config.locale),R(this._rangeEnd,t,this._config.locale)]}setDate(t,e={}){if(this._mode!=="single")return!1;let a=d(t);return!a||this._isDisabled(a)?!1:(this._selectedDate=a,this._activeDate=a,this._viewDate=y(a),this._render(),e.emit!==!1&&this._emitChange(!0),!0)}setDates(t,e,a={}){if(this._mode!=="range")return!1;let s=d(t),n=d(e);return s&&this._isDisabled(s)||n&&this._isDisabled(n)?!1:(this._rangeStart=s,this._rangeEnd=n,this._rangeStart&&this._rangeEnd&&g(this._rangeStart,this._rangeEnd)>0&&([this._rangeStart,this._rangeEnd]=[this._rangeEnd,this._rangeStart]),this._activeDate=this._rangeEnd||this._rangeStart||this._activeDate,this._viewDate=y(this._activeDate),this._render(),a.emit!==!1&&this._emitChange(!!(this._rangeStart&&this._rangeEnd)),!0)}clear(t={}){this._selectedDate=null,this._rangeStart=null,this._rangeEnd=null,this._render(),t.emit!==!1&&this._emitChange(!1)}focusActiveDay(){this._dayButton(this._activeDate)?.focus()}_bindEvents(){h(this._listeners,this._element,"click",t=>{let e=t.target,a=e.closest?.("[data-calendar-day]"),s=e.closest?.("[data-calendar-prev]"),n=e.closest?.("[data-calendar-next]"),r=e.closest?.("[data-calendar-preset]");s?this._changeMonth(-1,!0):n?this._changeMonth(1,!0):r?this._selectPreset(r.dataset.calendarPreset):a&&this._selectDate(d(a.dataset.calendarDay),!0)}),h(this._listeners,this._element,"keydown",t=>{t.target.closest?.("[data-calendar-day]")&&this._handleDayKeydown(t)}),h(this._listeners,this._element,"change",t=>{t.target.matches?.("[data-calendar-month]")&&this._setActiveMonth(this._viewDate.getFullYear(),Number(t.target.value),!0),t.target.matches?.("[data-calendar-year]")&&this._setActiveMonth(Number(t.target.value),this._viewDate.getMonth(),!0)})}_emitChange(t){m(this._element,this._window,"change.moo.calendar",{date:this._selectedDate?new Date(this._selectedDate):void 0,value:this._selectedDate?f(this._selectedDate):"",startDate:this._rangeStart?new Date(this._rangeStart):void 0,endDate:this._rangeEnd?new Date(this._rangeEnd):void 0,startValue:this._rangeStart?f(this._rangeStart):"",endValue:this._rangeEnd?f(this._rangeEnd):"",complete:t})}_changeMonth(t,e){let a=y(q(this._viewDate,t));this._setActiveMonth(a.getFullYear(),a.getMonth(),e)}_setActiveMonth(t,e,a=!1){let s=Math.min(this._activeDate.getDate(),$(t,e));this._activeDate=this._nearestEnabledDate(new Date(t,e,s)),this._viewDate=y(this._activeDate),this._render(),a&&this.focusActiveDay()}_selectPreset(t){if(!t)return;let e=new Date,a={today:0,tomorrow:1,"in-3-days":3,"in-a-week":7,"in-2-weeks":14};t in a&&this._selectDate(b(e,a[t]),!0)}_handleDayKeydown(t){let e=t.target.closest?.("[data-calendar-day]"),a=d(e?.dataset?.calendarDay);a&&g(a,this._activeDate)!==0&&(this._activeDate=a);let s={ArrowRight:1,ArrowLeft:-1,ArrowDown:7,ArrowUp:-7},n=null;if(t.key in s)n=b(this._activeDate,s[t.key]);else if(t.key==="Home"){let r=L(this._config.locale),_=(this._activeDate.getDay()-r+7)%7;n=b(this._activeDate,-_)}else if(t.key==="End"){let r=L(this._config.locale),_=(this._activeDate.getDay()-r+7)%7;n=b(this._activeDate,6-_)}else if(t.key==="PageUp")n=q(this._activeDate,-1);else if(t.key==="PageDown")n=q(this._activeDate,1);else if(t.key==="Enter"||t.key===" "||t.key==="Spacebar"){t.preventDefault(),this._selectDate(this._activeDate,!0);return}else return;t.preventDefault(),this._setActiveDate(n,!0,g(n,this._activeDate)<0?-1:1)}_setActiveDate(t,e=!1,a=0){let s=a===0?this._nearestEnabledDate(t):this._nextEnabledDate(t,a);this._activeDate=s,this._viewDate=y(s),this._render(),e&&this.focusActiveDay()}_nextEnabledDate(t,e){let a=d(t);if(!a)return this._activeDate;let s=e<0?-1:1;for(let n=0;n<366&&!(this._config.minDate&&g(a,this._config.minDate)<0||this._config.maxDate&&g(a,this._config.maxDate)>0);n+=1){if(!this._isDisabled(a))return a;a=b(a,s)}return this._activeDate}_nearestEnabledDate(t){let e=ot(d(t)||new Date,this._config.minDate,this._config.maxDate);if(!this._isDisabled(e))return e;let a=y(e),s=$(a.getFullYear(),a.getMonth());for(let n=1;n<=s;n+=1){let r=new Date(a.getFullYear(),a.getMonth(),n);if(!this._isDisabled(r))return r}return e}_selectDate(t,e){if(!(!t||this._isDisabled(t))){if(this._activeDate=t,this._viewDate=y(t),this._mode==="range"){!this._rangeStart||this._rangeEnd||g(t,this._rangeStart)<0?(this._rangeStart=t,this._rangeEnd=null):this._rangeEnd=t,this._render(),e&&this._emitChange(!!(this._rangeStart&&this._rangeEnd));return}this._selectedDate=t,this._render(),e&&this._emitChange(!0)}}_isDisabled(t){return!t||this._config.minDate&&g(t,this._config.minDate)<0||this._config.maxDate&&g(t,this._config.maxDate)>0?!0:this._disabledDates.has(f(t))}_isSelected(t){return this._mode==="range"?k(t,this._rangeStart)||k(t,this._rangeEnd):k(t,this._selectedDate)}_rangeState(t){return this._mode!=="range"||!this._rangeStart?"":k(t,this._rangeStart)?"start":k(t,this._rangeEnd)?"end":this._rangeStart&&this._rangeEnd&&g(t,this._rangeStart)>0&&g(t,this._rangeEnd)<0?"middle":""}_dayButton(t){return this._element.querySelector(`[data-calendar-day="${f(t)}"]`)}_render(){let t=this._document,e=t.createDocumentFragment(),a=t.createElement("div");a.className="moo-calendar__header";let s=t.createElement("button");s.className="btn btn-ghost btn-icon-sm moo-calendar__nav",s.type="button",s.dataset.calendarPrev="true",s.setAttribute("aria-label","Previous month"),s.appendChild(tt(t,"\u2039","moo-calendar__nav-icon"));let n=t.createElement("button");n.className="btn btn-ghost btn-icon-sm moo-calendar__nav",n.type="button",n.dataset.calendarNext="true",n.setAttribute("aria-label","Next month"),n.appendChild(tt(t,"\u203A","moo-calendar__nav-icon"));let r=t.createElement("div");if(r.className="moo-calendar__caption",r.id=this._captionId,r.setAttribute("aria-live","polite"),this._config.captionLayout==="dropdown"){let c=t.createElement("select");c.className="moo-calendar__select",c.dataset.calendarMonth="true",c.setAttribute("aria-label","Month");for(let u=0;u<12;u+=1){let o=t.createElement("option");o.value=String(u),o.textContent=_t(u,this._config.locale),o.selected=u===this._viewDate.getMonth(),c.appendChild(o)}let l=t.createElement("select");l.className="moo-calendar__select",l.dataset.calendarYear="true",l.setAttribute("aria-label","Year"),ft(this._config.minDate,this._config.maxDate,this._viewDate).forEach(u=>{let o=t.createElement("option");o.value=String(u),o.textContent=String(u),o.selected=u===this._viewDate.getFullYear(),l.appendChild(o)}),r.append(c,l)}else r.textContent=Q(this._viewDate,this._config.locale);a.append(s,r,n),e.appendChild(a);let _=t.createElement("div");_.id=this._labelId,_.className="visually-hidden",_.textContent=this._element.getAttribute("aria-label")||Q(this._viewDate,this._config.locale),e.appendChild(_);let E=t.createElement("div");E.className="moo-calendar__weekdays",E.setAttribute("role","row"),rt(this._config.locale).forEach(c=>{let l=t.createElement("span");l.className="moo-calendar__weekday",l.setAttribute("role","columnheader"),l.textContent=new Intl.DateTimeFormat(this._config.locale,{weekday:"narrow"}).format(c),E.appendChild(l)});let D=t.createElement("div");D.className="moo-calendar__grid",D.setAttribute("role","grid"),D.setAttribute("aria-labelledby",this._labelId),D.appendChild(E);let N=y(this._viewDate),Y=L(this._config.locale),I=b(N,-((N.getDay()-Y+7)%7));for(let c=0;c<6;c+=1){let l=t.createElement("div");l.className="moo-calendar__week",l.setAttribute("role","row");for(let u=0;u<7;u+=1){let o=b(I,c*7+u),F=f(o),v=t.createElement("div");v.className="moo-calendar__cell",v.setAttribute("role","gridcell");let p=t.createElement("button");p.className="moo-calendar__day",p.type="button",p.dataset.calendarDay=F,p.textContent=String(o.getDate()),p.tabIndex=k(o,this._activeDate)?0:-1,p.setAttribute("aria-label",A(o,this._config.locale));let G=this._isSelected(o);p.dataset.calendarSelected=String(G),v.setAttribute("aria-selected",G?"true":"false"),o.getMonth()!==this._viewDate.getMonth()&&(p.dataset.calendarOutside="true"),k(o,new Date)&&(p.dataset.calendarToday="true",p.setAttribute("aria-current","date"));let J=this._rangeState(o);J&&(p.dataset.calendarRange=J),this._isDisabled(o)&&(p.disabled=!0,p.setAttribute("aria-disabled","true")),v.appendChild(p),l.appendChild(v)}D.appendChild(l)}if(e.appendChild(D),this._config.showPresets){let c=t.createElement("div");c.className="moo-calendar__presets",[["today","Today"],["tomorrow","Tomorrow"],["in-3-days","In 3 days"],["in-a-week","In a week"],["in-2-weeks","In 2 weeks"]].forEach(([l,u])=>{let o=t.createElement("button");o.className="btn btn-outline-secondary btn-sm moo-calendar__preset",o.type="button",o.dataset.calendarPreset=l,o.textContent=u,c.appendChild(o)}),e.appendChild(c)}this._element.classList.add("moo-calendar"),this._element.dataset.calendar=this._element.dataset.calendar||"",this._element.dataset.calendarMode=this._mode,this._element.dataset.calendarActiveDate=f(this._activeDate),this._mode==="single"&&this._selectedDate?this._element.dataset.calendarValue=f(this._selectedDate):delete this._element.dataset.calendarValue,this._mode==="range"?(this._element.dataset.calendarStartValue=this._rangeStart?f(this._rangeStart):"",this._element.dataset.calendarEndValue=this._rangeEnd?f(this._rangeEnd):""):(delete this._element.dataset.calendarStartValue,delete this._element.dataset.calendarEndValue),this._element.replaceChildren(e)}},W=class i{static getInstance(t){return t?.nodeType===1&&x.get(t)||null}static getOrCreateInstance(t,e={}){return i.getInstance(t)||new i(t,e)}constructor(t,e={}){if(!H(t,"[data-datepicker]"))throw new TypeError("MooDatepicker requires a [data-datepicker] root element.");let a=x.get(t);if(a)return a;if(this._element=t,this._document=t.ownerDocument,this._window=this._document.defaultView||window,this._listeners=[],this._floatingListeners=[],this._disposed=!1,this._positionPopover=null,this._popoverPortal=null,this._trigger=t.querySelector("[data-datepicker-trigger]"),this._popover=t.querySelector("[data-datepicker-popover]"),this._label=t.querySelector("[data-datepicker-label]"),this._input=t.querySelector("[data-datepicker-input]")||t.querySelector('input[type="hidden"]'),this._validationInput=t.querySelector("[data-datepicker-validation]"),this._calendarRoot=t.querySelector("[data-calendar]"),!this._trigger||!this._popover||!this._label||!this._input||!this._calendarRoot)throw new TypeError("MooDatepicker requires a trigger, popover, calendar, and hidden input.");this._config=z(t,{...e,value:e.value||this._input.value||t.dataset.datepickerValue}),this._placeholder=this._config.placeholder,this._defaultValue=this._input.defaultValue||this._input.getAttribute("value")||"",this.calendar=T.getOrCreateInstance(this._calendarRoot,{...this._config,mode:"single",value:this._input.value||this._config.value}),x.set(t,this),this._syncFromCalendar(),this._bindEvents()}dispose(){this._disposed||(this._disposed=!0,S(this._listeners),this.hide(!1),O(this),K(this),S(this._floatingListeners),this.calendar?.dispose(),x.get(this._element)===this&&x.delete(this._element))}show(){this._trigger.disabled||this._element.dataset.datepickerDisabled==="true"||this.isOpen()||m(this._element,this._window,"show.moo.datepicker",{},!0)&&(this._popover.hidden=!1,this._popover.classList.add("show"),st(this),this._trigger.setAttribute("aria-expanded","true"),this.calendar.focusActiveDay(),m(this._element,this._window,"shown.moo.datepicker"))}hide(t=!0){this.isOpen()&&m(this._element,this._window,"hide.moo.datepicker",{},!0)&&(this._popover.hidden=!0,this._popover.classList.remove("show"),O(this),this._trigger.setAttribute("aria-expanded","false"),t&&this._trigger.focus(),m(this._element,this._window,"hidden.moo.datepicker"))}toggle(){this.isOpen()?this.hide():this.show()}isOpen(){return!this._popover.hidden}getDate(t=void 0){return this.calendar.getDate(t)}setDate(t,e={}){let a=this.calendar.setDate(t,{emit:!1});return a&&(this._syncFromCalendar(),e.emit!==!1&&this._emitChange()),a}clear(t={}){this.calendar.clear({emit:!1}),this._syncFromCalendar(),t.emit!==!1&&this._emitChange()}_bindEvents(){h(this._listeners,this._trigger,"click",()=>this.toggle()),h(this._listeners,this._popover,"keydown",e=>{e.key==="Escape"&&(e.preventDefault(),this.hide())}),h(this._listeners,this._document,"pointerdown",e=>{this.isOpen()&&!P(this,e.target)&&this._window.setTimeout(()=>{this.isOpen()&&!P(this,e.target)&&this.hide()},0)}),h(this._listeners,this._calendarRoot,"change.moo.calendar",e=>{this._syncFromCalendar(),this._emitChange(),e.detail.complete&&this.hide()});let t=this._input.form||this._element.closest("form");h(this._listeners,this._validationInput,"invalid",e=>{e.preventDefault(),U(this._element,this._trigger,!0),this._trigger.focus({preventScroll:!0})}),h(this._listeners,t,"reset",()=>{this._window.setTimeout(()=>{this._defaultValue?this.setDate(this._defaultValue,{emit:!1}):this.clear({emit:!1})},0)})}_syncFromCalendar(){let t=this.calendar.getDate("yyyy-mm-dd")||"";B(this._input,t),it(this._validationInput,t),at(this._element,this._trigger,this._validationInput),this._element.dataset.datepickerValue=t,this._label.textContent=t?A(d(t),this._config.locale):this._placeholder}_emitChange(){m(this._element,this._window,"change.moo.datepicker",{date:this.getDate(),value:this.getDate("yyyy-mm-dd")||""})}},et=class i{static getInstance(t){return t?.nodeType===1&&M.get(t)||null}static getOrCreateInstance(t,e={}){return i.getInstance(t)||new i(t,e)}constructor(t,e={}){if(!H(t,"[data-datepicker-range]"))throw new TypeError("MooDateRangePicker requires a [data-datepicker-range] root element.");let a=M.get(t);if(a)return a;if(this._element=t,this._document=t.ownerDocument,this._window=this._document.defaultView||window,this._listeners=[],this._floatingListeners=[],this._disposed=!1,this._positionPopover=null,this._popoverPortal=null,this._trigger=t.querySelector("[data-datepicker-trigger]"),this._popover=t.querySelector("[data-datepicker-popover]"),this._label=t.querySelector("[data-datepicker-label]"),this._startInput=t.querySelector("[data-datepicker-range-start]"),this._endInput=t.querySelector("[data-datepicker-range-end]"),this._validationInput=t.querySelector("[data-datepicker-validation]"),this._calendarRoot=t.querySelector("[data-calendar]"),!this._trigger||!this._popover||!this._label||!this._startInput||!this._endInput||!this._calendarRoot)throw new TypeError("MooDateRangePicker requires a trigger, popover, calendar, and start/end hidden inputs.");this._config=z(t,{...e,mode:"range",startValue:e.startValue||this._startInput.value||t.dataset.datepickerStartValue,endValue:e.endValue||this._endInput.value||t.dataset.datepickerEndValue}),this._placeholder=this._config.placeholder,this._defaultStartValue=this._startInput.defaultValue||this._startInput.getAttribute("value")||"",this._defaultEndValue=this._endInput.defaultValue||this._endInput.getAttribute("value")||"",this.calendar=T.getOrCreateInstance(this._calendarRoot,this._config),M.set(t,this),this._syncFromCalendar(),this._bindEvents()}dispose(){this._disposed||(this._disposed=!0,S(this._listeners),this.hide(!1),O(this),K(this),S(this._floatingListeners),this.calendar?.dispose(),M.get(this._element)===this&&M.delete(this._element))}show(){this._trigger.disabled||this._element.dataset.datepickerDisabled==="true"||this.isOpen()||m(this._element,this._window,"show.moo.datepicker",{},!0)&&(this._popover.hidden=!1,this._popover.classList.add("show"),st(this),this._trigger.setAttribute("aria-expanded","true"),this.calendar.focusActiveDay(),m(this._element,this._window,"shown.moo.datepicker"))}hide(t=!0){this.isOpen()&&m(this._element,this._window,"hide.moo.datepicker",{},!0)&&(this._popover.hidden=!0,this._popover.classList.remove("show"),O(this),this._trigger.setAttribute("aria-expanded","false"),t&&this._trigger.focus(),m(this._element,this._window,"hidden.moo.datepicker"))}toggle(){this.isOpen()?this.hide():this.show()}isOpen(){return!this._popover.hidden}getDates(t=void 0){return this.calendar.getDates(t)}setDates(t,e,a={}){let s=this.calendar.setDates(t,e,{emit:!1});return s&&(this._syncFromCalendar(),a.emit!==!1&&this._emitChange()),s}clear(t={}){this.calendar.clear({emit:!1}),this._syncFromCalendar(),t.emit!==!1&&this._emitChange()}_bindEvents(){h(this._listeners,this._trigger,"click",()=>this.toggle()),h(this._listeners,this._popover,"keydown",a=>{a.key==="Escape"&&(a.preventDefault(),this.hide())}),h(this._listeners,this._document,"pointerdown",a=>{this.isOpen()&&!P(this,a.target)&&this._window.setTimeout(()=>{this.isOpen()&&!P(this,a.target)&&this.hide()},0)});let t=()=>{this._window.setTimeout(()=>{this.isOpen()&&!P(this,this._document.activeElement)&&this.hide(!1)},0)};h(this._listeners,this._element,"focusout",t),h(this._listeners,this._popover,"focusout",t),h(this._listeners,this._calendarRoot,"change.moo.calendar",a=>{this._syncFromCalendar(),this._emitChange(),a.detail.complete?this.hide():this.calendar.focusActiveDay()});let e=this._startInput.form||this._element.closest("form");h(this._listeners,this._validationInput,"invalid",a=>{a.preventDefault(),U(this._element,this._trigger,!0),this._trigger.focus({preventScroll:!0})}),h(this._listeners,e,"reset",()=>{this._window.setTimeout(()=>{this.setDates(this._defaultStartValue,this._defaultEndValue,{emit:!1})},0)})}_syncFromCalendar(){let[t="",e=""]=this.calendar.getDates("yyyy-mm-dd");B(this._startInput,t||""),B(this._endInput,e||""),it(this._validationInput,t&&e?`${t} - ${e}`:""),at(this._element,this._trigger,this._validationInput),this._element.dataset.datepickerStartValue=t||"",this._element.dataset.datepickerEndValue=e||"",t&&e?this._label.textContent=`${A(d(t),this._config.locale)} - ${A(d(e),this._config.locale)}`:t?this._label.textContent=A(d(t),this._config.locale):this._label.textContent=this._placeholder}_emitChange(){let[t,e]=this.getDates(),[a="",s=""]=this.getDates("yyyy-mm-dd");m(this._element,this._window,"change.moo.datepicker",{startDate:t,endDate:e,startValue:a,endValue:s})}};export{T as MooCalendar,et as MooDateRangePicker,W as default};
|
package/dist/js/sidebar.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Moo UI sidebar.js v1.0.0-rc.3 (https://ui.wpmoo.org/)
|
|
3
|
+
* Copyright 2026 WPMoo (https://wpmoo.org)
|
|
4
|
+
* Licensed under MIT (https://github.com/wpmoo-org/ui/blob/main/LICENSE)
|
|
5
|
+
*/
|
|
1
6
|
const instances = new WeakMap();
|
|
2
7
|
|
|
3
8
|
export default class Sidebar {
|
|
@@ -39,7 +44,8 @@ export default class Sidebar {
|
|
|
39
44
|
instances.set(element, this);
|
|
40
45
|
this._bindEvents();
|
|
41
46
|
this._restoreState();
|
|
42
|
-
this.
|
|
47
|
+
this._scrollActiveItemIntoView();
|
|
48
|
+
this._element.setAttribute("data-sidebar-ready", "");
|
|
43
49
|
this._observeDirection();
|
|
44
50
|
}
|
|
45
51
|
|
|
@@ -51,15 +57,15 @@ export default class Sidebar {
|
|
|
51
57
|
this._directionObserver?.disconnect();
|
|
52
58
|
this._closeFlyouts();
|
|
53
59
|
this._element
|
|
54
|
-
.querySelectorAll("[data-
|
|
60
|
+
.querySelectorAll("[data-sidebar-dropdown-positioned]")
|
|
55
61
|
.forEach((item) => this._clearDropdownPosition(item));
|
|
56
62
|
this._element
|
|
57
|
-
.querySelectorAll("[data-
|
|
63
|
+
.querySelectorAll("[data-sidebar-tooltip]")
|
|
58
64
|
.forEach((control) => this._disposeTooltip(control));
|
|
59
65
|
this._offcanvas?.dispose();
|
|
60
66
|
this._offcanvas = null;
|
|
61
67
|
this._offcanvasTrigger = null;
|
|
62
|
-
this._element.removeAttribute("data-
|
|
68
|
+
this._element.removeAttribute("data-sidebar-ready");
|
|
63
69
|
instances.delete(this._element);
|
|
64
70
|
}
|
|
65
71
|
|
|
@@ -79,7 +85,7 @@ export default class Sidebar {
|
|
|
79
85
|
}
|
|
80
86
|
|
|
81
87
|
_isCollapsed() {
|
|
82
|
-
return this._isDesktop() && this._element.dataset.
|
|
88
|
+
return this._isDesktop() && this._element.dataset.sidebarState === "collapsed";
|
|
83
89
|
}
|
|
84
90
|
|
|
85
91
|
_trigger(name, detail = {}) {
|
|
@@ -108,7 +114,7 @@ export default class Sidebar {
|
|
|
108
114
|
}
|
|
109
115
|
|
|
110
116
|
_restoreState() {
|
|
111
|
-
const key = this._element.dataset.
|
|
117
|
+
const key = this._element.dataset.sidebarKey;
|
|
112
118
|
let stored = null;
|
|
113
119
|
if (key) {
|
|
114
120
|
try {
|
|
@@ -120,19 +126,55 @@ export default class Sidebar {
|
|
|
120
126
|
const initial =
|
|
121
127
|
stored === "collapsed" || stored === "expanded"
|
|
122
128
|
? stored
|
|
123
|
-
: this._element.dataset.
|
|
129
|
+
: this._element.dataset.sidebarState === "collapsed"
|
|
124
130
|
? "collapsed"
|
|
125
131
|
: "expanded";
|
|
126
132
|
this._setState(initial, false, false);
|
|
127
133
|
}
|
|
128
134
|
|
|
135
|
+
_scrollActiveItemIntoView() {
|
|
136
|
+
const activeRoute = this._element.querySelector(
|
|
137
|
+
'[data-slot="sidebar-content"] a[data-slot="sidebar-menu-button"][aria-current="page"], ' +
|
|
138
|
+
'[data-slot="sidebar-content"] a.sidebar-menu-button[aria-current="page"], ' +
|
|
139
|
+
'[data-slot="sidebar-content"] a.sidebar-menu-button.active'
|
|
140
|
+
);
|
|
141
|
+
const active = activeRoute || this._element.querySelector(
|
|
142
|
+
'[data-slot="sidebar-content"] [data-slot="sidebar-menu-button"][aria-current="page"], ' +
|
|
143
|
+
'[data-slot="sidebar-content"] .sidebar-menu-button[aria-current="page"], ' +
|
|
144
|
+
'[data-slot="sidebar-content"] .sidebar-menu-button.active'
|
|
145
|
+
);
|
|
146
|
+
const content = active?.closest?.('[data-slot="sidebar-content"]');
|
|
147
|
+
if (!active || !content || content.clientHeight <= 0) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const maxScrollTop = content.scrollHeight - content.clientHeight;
|
|
151
|
+
if (maxScrollTop <= 0) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const contentRect = content.getBoundingClientRect();
|
|
156
|
+
const activeRect = active.getBoundingClientRect();
|
|
157
|
+
if (contentRect.height <= 0 || activeRect.height <= 0) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const targetScrollTop =
|
|
162
|
+
content.scrollTop +
|
|
163
|
+
activeRect.top -
|
|
164
|
+
contentRect.top -
|
|
165
|
+
(content.clientHeight - activeRect.height) / 2;
|
|
166
|
+
content.scrollTop = Math.round(
|
|
167
|
+
Math.min(Math.max(targetScrollTop, 0), maxScrollTop)
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
129
171
|
_setState(state, persist = true, emit = true) {
|
|
130
172
|
const next = state === "collapsed" ? "collapsed" : "expanded";
|
|
131
|
-
const previous = this._element.dataset.
|
|
132
|
-
this._element.dataset.
|
|
133
|
-
const key = this._element.dataset.
|
|
173
|
+
const previous = this._element.dataset.sidebarState;
|
|
174
|
+
this._element.dataset.sidebarState = next;
|
|
175
|
+
const key = this._element.dataset.sidebarKey;
|
|
134
176
|
if (key === "catalog-shell") {
|
|
135
|
-
this._root.dataset.
|
|
177
|
+
this._root.dataset.sidebarCatalogState = next;
|
|
136
178
|
}
|
|
137
179
|
if (persist && key) {
|
|
138
180
|
try {
|
|
@@ -155,16 +197,16 @@ export default class Sidebar {
|
|
|
155
197
|
|
|
156
198
|
_toggle() {
|
|
157
199
|
this._setState(
|
|
158
|
-
this._element.dataset.
|
|
200
|
+
this._element.dataset.sidebarState === "collapsed" ? "expanded" : "collapsed"
|
|
159
201
|
);
|
|
160
202
|
}
|
|
161
203
|
|
|
162
204
|
_syncControls() {
|
|
163
205
|
const expanded = this._isDesktop()
|
|
164
|
-
? this._element.dataset.
|
|
206
|
+
? this._element.dataset.sidebarState === "expanded"
|
|
165
207
|
: this._sidebar?.classList.contains("show") || false;
|
|
166
208
|
this._element
|
|
167
|
-
.querySelectorAll("[data-
|
|
209
|
+
.querySelectorAll("[data-sidebar-trigger], [data-sidebar-rail]")
|
|
168
210
|
.forEach((control) => control.setAttribute("aria-expanded", String(expanded)));
|
|
169
211
|
}
|
|
170
212
|
|
|
@@ -186,7 +228,7 @@ export default class Sidebar {
|
|
|
186
228
|
if (!item) {
|
|
187
229
|
return;
|
|
188
230
|
}
|
|
189
|
-
delete item.dataset.
|
|
231
|
+
delete item.dataset.sidebarDropdownPositioned;
|
|
190
232
|
item.style.removeProperty("--moo-sidebar-dropdown-block-start");
|
|
191
233
|
item.style.removeProperty("--moo-sidebar-dropdown-inline-start");
|
|
192
234
|
}
|
|
@@ -237,7 +279,7 @@ export default class Sidebar {
|
|
|
237
279
|
"--moo-sidebar-dropdown-inline-start",
|
|
238
280
|
`${Math.round(inlineStart)}px`
|
|
239
281
|
);
|
|
240
|
-
item.dataset.
|
|
282
|
+
item.dataset.sidebarDropdownPositioned = "";
|
|
241
283
|
}
|
|
242
284
|
|
|
243
285
|
_removeFlyoutPortal() {
|
|
@@ -281,7 +323,7 @@ export default class Sidebar {
|
|
|
281
323
|
flyout.removeAttribute("id");
|
|
282
324
|
flyout.classList.remove("collapse", "show", "collapsing");
|
|
283
325
|
flyout.classList.add("sidebar-menu-flyout");
|
|
284
|
-
flyout.dataset.
|
|
326
|
+
flyout.dataset.sidebarFlyout = "";
|
|
285
327
|
flyout.removeAttribute("style");
|
|
286
328
|
flyout.style.setProperty("--moo-sidebar-flyout-block-start", `${Math.round(rect.top)}px`);
|
|
287
329
|
flyout.style.setProperty(
|
|
@@ -328,7 +370,7 @@ export default class Sidebar {
|
|
|
328
370
|
}
|
|
329
371
|
const collapsed = this._isCollapsed();
|
|
330
372
|
const placement = this._root.dir === "rtl" ? "left" : "right";
|
|
331
|
-
this._element.querySelectorAll("[data-
|
|
373
|
+
this._element.querySelectorAll("[data-sidebar-tooltip]").forEach((control) => {
|
|
332
374
|
this._disposeTooltip(control);
|
|
333
375
|
if (
|
|
334
376
|
!collapsed ||
|
|
@@ -343,7 +385,7 @@ export default class Sidebar {
|
|
|
343
385
|
// state-driven Sidebar tooltip instead.
|
|
344
386
|
const anchor = this._tooltipAnchor(control);
|
|
345
387
|
new Tooltip(anchor, {
|
|
346
|
-
title: control.getAttribute("data-
|
|
388
|
+
title: control.getAttribute("data-sidebar-tooltip"),
|
|
347
389
|
placement,
|
|
348
390
|
container: "body",
|
|
349
391
|
trigger: "hover focus",
|
|
@@ -386,7 +428,7 @@ export default class Sidebar {
|
|
|
386
428
|
this._listen(this._window, "resize", () => {
|
|
387
429
|
this._closeFlyouts();
|
|
388
430
|
this._element
|
|
389
|
-
.querySelectorAll("[data-
|
|
431
|
+
.querySelectorAll("[data-sidebar-dropdown-positioned]")
|
|
390
432
|
.forEach((item) => this._clearDropdownPosition(item));
|
|
391
433
|
this._syncControls();
|
|
392
434
|
this._syncTooltips();
|
|
@@ -397,18 +439,18 @@ export default class Sidebar {
|
|
|
397
439
|
if (!(target instanceof this._window.Element) || !this._element.contains(target)) {
|
|
398
440
|
return null;
|
|
399
441
|
}
|
|
400
|
-
if (target.matches('[data-bs-toggle="dropdown"][data-
|
|
442
|
+
if (target.matches('[data-bs-toggle="dropdown"][data-sidebar-tooltip]')) {
|
|
401
443
|
return target;
|
|
402
444
|
}
|
|
403
445
|
return target.querySelector?.(
|
|
404
|
-
'[data-bs-toggle="dropdown"][data-
|
|
446
|
+
'[data-bs-toggle="dropdown"][data-sidebar-tooltip]'
|
|
405
447
|
) || null;
|
|
406
448
|
}
|
|
407
449
|
|
|
408
450
|
_handleControlClick(event) {
|
|
409
451
|
const target = event.target;
|
|
410
452
|
const control = target instanceof this._window.Element
|
|
411
|
-
? target.closest("[data-
|
|
453
|
+
? target.closest("[data-sidebar-trigger], [data-sidebar-rail]")
|
|
412
454
|
: null;
|
|
413
455
|
if (!control || !this._element.contains(control)) {
|
|
414
456
|
return;
|
|
@@ -419,7 +461,7 @@ export default class Sidebar {
|
|
|
419
461
|
this._toggle();
|
|
420
462
|
return;
|
|
421
463
|
}
|
|
422
|
-
if (!control.matches("[data-
|
|
464
|
+
if (!control.matches("[data-sidebar-trigger]")) {
|
|
423
465
|
return;
|
|
424
466
|
}
|
|
425
467
|
const sidebar = this._document.getElementById(control.getAttribute("aria-controls"));
|
|
@@ -478,7 +520,7 @@ export default class Sidebar {
|
|
|
478
520
|
}
|
|
479
521
|
const preferred =
|
|
480
522
|
this._document.querySelector(
|
|
481
|
-
'[data-slot="sidebar-wrapper"][data-
|
|
523
|
+
'[data-slot="sidebar-wrapper"][data-sidebar-key]'
|
|
482
524
|
) || this._document.querySelector('[data-slot="sidebar-wrapper"]');
|
|
483
525
|
if (preferred !== this._element) {
|
|
484
526
|
return;
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Moo UI slider.js v1.0.0-rc.3 (https://ui.wpmoo.org/)
|
|
3
|
+
* Copyright 2026 WPMoo (https://wpmoo.org)
|
|
4
|
+
* Licensed under MIT (https://github.com/wpmoo-org/ui/blob/main/LICENSE)
|
|
5
|
+
*/
|
|
6
|
+
const instances = new WeakMap();
|
|
7
|
+
|
|
8
|
+
function asNumber(value, fallback) {
|
|
9
|
+
const number = Number(value);
|
|
10
|
+
return Number.isFinite(number) ? number : fallback;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function inputMinimum(input) {
|
|
14
|
+
return asNumber(input.min, 0);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function inputMaximum(input) {
|
|
18
|
+
return asNumber(input.max, 100);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function inputStep(input) {
|
|
22
|
+
if (!input.step || input.step === "any") {
|
|
23
|
+
return 1;
|
|
24
|
+
}
|
|
25
|
+
const step = Number(input.step);
|
|
26
|
+
return Number.isFinite(step) && step > 0 ? step : 1;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function clamp(value, min, max) {
|
|
30
|
+
return Math.min(Math.max(value, min), max);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function decimalPlaces(value) {
|
|
34
|
+
const text = String(value);
|
|
35
|
+
if (!text.includes(".")) {
|
|
36
|
+
return 0;
|
|
37
|
+
}
|
|
38
|
+
return text.split(".").at(-1).length;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function snapToStep(value, input) {
|
|
42
|
+
const min = inputMinimum(input);
|
|
43
|
+
const max = inputMaximum(input);
|
|
44
|
+
if (input.step === "any") {
|
|
45
|
+
return Number(clamp(value, min, max).toFixed(4));
|
|
46
|
+
}
|
|
47
|
+
const step = inputStep(input);
|
|
48
|
+
const snapped = min + Math.round((value - min) / step) * step;
|
|
49
|
+
const precision = Math.max(decimalPlaces(step), decimalPlaces(min));
|
|
50
|
+
return clamp(Number(snapped.toFixed(precision)), min, max);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function valuePercent(input) {
|
|
54
|
+
const min = inputMinimum(input);
|
|
55
|
+
const max = inputMaximum(input);
|
|
56
|
+
if (max <= min) {
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
59
|
+
return ((asNumber(input.value, min) - min) / (max - min)) * 100;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function displayValue(input) {
|
|
63
|
+
return input.value || String(inputMinimum(input));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export default class MooSlider {
|
|
67
|
+
static getInstance(element) {
|
|
68
|
+
return element?.nodeType === 1 ? instances.get(element) || null : null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static getOrCreateInstance(element, config = {}) {
|
|
72
|
+
return MooSlider.getInstance(element) || new MooSlider(element, config);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
constructor(element, config = {}) {
|
|
76
|
+
if (element?.nodeType !== 1 || !element.matches("[data-slider]")) {
|
|
77
|
+
throw new TypeError("MooSlider requires a [data-slider] root element.");
|
|
78
|
+
}
|
|
79
|
+
const existing = instances.get(element);
|
|
80
|
+
if (existing) {
|
|
81
|
+
return existing;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
this._element = element;
|
|
85
|
+
this._document = element.ownerDocument;
|
|
86
|
+
this._window = this._document.defaultView;
|
|
87
|
+
this._config = { ...config };
|
|
88
|
+
this._listeners = [];
|
|
89
|
+
this._dragListeners = [];
|
|
90
|
+
this._draggingInput = null;
|
|
91
|
+
this._disposed = false;
|
|
92
|
+
this._inputs = Array.from(
|
|
93
|
+
element.querySelectorAll(':scope input[type="range"][data-slider-input]')
|
|
94
|
+
);
|
|
95
|
+
this._track = element.querySelector("[data-slider-track]");
|
|
96
|
+
this._output = element.querySelector("[data-slider-output]");
|
|
97
|
+
|
|
98
|
+
if (this._inputs.length < 1 || this._inputs.length > 2) {
|
|
99
|
+
throw new TypeError("MooSlider requires one or two native range inputs.");
|
|
100
|
+
}
|
|
101
|
+
if (!this._track) {
|
|
102
|
+
throw new TypeError("MooSlider requires a [data-slider-track] element.");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
instances.set(element, this);
|
|
106
|
+
this._bindEvents();
|
|
107
|
+
this._sync();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
dispose() {
|
|
111
|
+
if (this._disposed) return;
|
|
112
|
+
this._disposed = true;
|
|
113
|
+
this._clearDragListeners();
|
|
114
|
+
this._clearPointerFocus();
|
|
115
|
+
this._listeners.forEach(({ target, type, handler, options }) => {
|
|
116
|
+
target.removeEventListener(type, handler, options);
|
|
117
|
+
});
|
|
118
|
+
this._listeners = [];
|
|
119
|
+
if (instances.get(this._element) === this) {
|
|
120
|
+
instances.delete(this._element);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
_listen(target, type, handler, options) {
|
|
125
|
+
if (!target) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
target.addEventListener(type, handler, options);
|
|
129
|
+
this._listeners.push({ target, type, handler, options });
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
_listenDuringDrag(target, type, handler, options) {
|
|
133
|
+
if (!target) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
target.addEventListener(type, handler, options);
|
|
137
|
+
this._dragListeners.push({ target, type, handler, options });
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
_clearDragListeners() {
|
|
141
|
+
this._dragListeners.forEach(({ target, type, handler, options }) => {
|
|
142
|
+
target.removeEventListener(type, handler, options);
|
|
143
|
+
});
|
|
144
|
+
this._dragListeners = [];
|
|
145
|
+
this._draggingInput = null;
|
|
146
|
+
this._element.removeAttribute("data-slider-dragging");
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
_bindEvents() {
|
|
150
|
+
this._inputs.forEach((input) => {
|
|
151
|
+
this._listen(input, "input", () => this._sync(input));
|
|
152
|
+
this._listen(input, "change", () => {
|
|
153
|
+
this._sync(input);
|
|
154
|
+
this._trigger("change");
|
|
155
|
+
});
|
|
156
|
+
this._listen(input, "keydown", () => this._clearPointerFocus());
|
|
157
|
+
this._listen(input, "focusout", () => this._clearPointerFocus());
|
|
158
|
+
});
|
|
159
|
+
const forms = new Set(
|
|
160
|
+
this._inputs
|
|
161
|
+
.map((input) => input.form || input.closest?.("form"))
|
|
162
|
+
.filter(Boolean),
|
|
163
|
+
);
|
|
164
|
+
forms.forEach((form) => {
|
|
165
|
+
this._listen(form, "reset", () => {
|
|
166
|
+
this._window.setTimeout(() => this._sync(), 0);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
this._listen(this._track, "pointerdown", (event) => this._handleTrackPointer(event));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
_trigger(name) {
|
|
173
|
+
this._element.dispatchEvent(
|
|
174
|
+
new this._window.CustomEvent(`${name}.moo.slider`, {
|
|
175
|
+
bubbles: true,
|
|
176
|
+
})
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
_isRange() {
|
|
181
|
+
return this._inputs.length === 2;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
_sync(changedInput = null) {
|
|
185
|
+
if (this._isRange()) {
|
|
186
|
+
const [startInput, endInput] = this._inputs;
|
|
187
|
+
const start = asNumber(startInput.value, inputMinimum(startInput));
|
|
188
|
+
const end = asNumber(endInput.value, inputMaximum(endInput));
|
|
189
|
+
if (start > end) {
|
|
190
|
+
if (changedInput === endInput) {
|
|
191
|
+
endInput.value = startInput.value;
|
|
192
|
+
} else {
|
|
193
|
+
startInput.value = endInput.value;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
this._writeFill(valuePercent(startInput), valuePercent(endInput));
|
|
197
|
+
this._writeOutput(`${displayValue(startInput)} - ${displayValue(endInput)}`);
|
|
198
|
+
this._syncAria(startInput);
|
|
199
|
+
this._syncAria(endInput);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const input = this._inputs[0];
|
|
204
|
+
this._writeFill(0, valuePercent(input));
|
|
205
|
+
this._writeOutput(displayValue(input));
|
|
206
|
+
this._syncAria(input);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
_syncAria(input) {
|
|
210
|
+
input.setAttribute("aria-valuemin", String(inputMinimum(input)));
|
|
211
|
+
input.setAttribute("aria-valuemax", String(inputMaximum(input)));
|
|
212
|
+
input.setAttribute("aria-valuenow", displayValue(input));
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
_writeFill(start, end) {
|
|
216
|
+
const clampedStart = clamp(start, 0, 100);
|
|
217
|
+
const clampedEnd = clamp(end, 0, 100);
|
|
218
|
+
this._element.style.setProperty("--moo-slider-start", `${Math.min(clampedStart, clampedEnd)}%`);
|
|
219
|
+
this._element.style.setProperty("--moo-slider-end", `${Math.max(clampedStart, clampedEnd)}%`);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
_writeOutput(value) {
|
|
223
|
+
if (this._output) {
|
|
224
|
+
this._output.textContent = value;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
_handleTrackPointer(event) {
|
|
229
|
+
if (event.button !== undefined && event.button !== 0) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const enabledInputs = this._inputs.filter((input) => !input.disabled);
|
|
233
|
+
if (!enabledInputs.length) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
event.preventDefault?.();
|
|
237
|
+
const percent = this._pointerPercent(event);
|
|
238
|
+
const target = this._nearestInput(percent * 100, enabledInputs);
|
|
239
|
+
this._setPointerFocus();
|
|
240
|
+
this._startDrag(target, event);
|
|
241
|
+
this._setInputFromPointer(target, event);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
_setPointerFocus() {
|
|
245
|
+
this._element.setAttribute("data-slider-pointer-focus", "true");
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
_clearPointerFocus() {
|
|
249
|
+
this._element.removeAttribute("data-slider-pointer-focus");
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
_startDrag(input, event) {
|
|
253
|
+
this._clearDragListeners();
|
|
254
|
+
this._draggingInput = input;
|
|
255
|
+
this._element.setAttribute("data-slider-dragging", "true");
|
|
256
|
+
this._track.setPointerCapture?.(event.pointerId);
|
|
257
|
+
|
|
258
|
+
const pointerId = event.pointerId;
|
|
259
|
+
const samePointer = (nextEvent) => pointerId === undefined || nextEvent.pointerId === pointerId;
|
|
260
|
+
const onMove = (moveEvent) => {
|
|
261
|
+
if (!samePointer(moveEvent) || this._draggingInput !== input) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
moveEvent.preventDefault?.();
|
|
265
|
+
this._setInputFromPointer(input, moveEvent);
|
|
266
|
+
};
|
|
267
|
+
const onEnd = (endEvent) => {
|
|
268
|
+
if (!samePointer(endEvent) || this._draggingInput !== input) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
endEvent.preventDefault?.();
|
|
272
|
+
this._setInputFromPointer(input, endEvent, false);
|
|
273
|
+
input.dispatchEvent(new this._window.Event("change", { bubbles: true }));
|
|
274
|
+
this._track.releasePointerCapture?.(pointerId);
|
|
275
|
+
this._clearDragListeners();
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
this._listenDuringDrag(this._document, "pointermove", onMove);
|
|
279
|
+
this._listenDuringDrag(this._document, "pointerup", onEnd);
|
|
280
|
+
this._listenDuringDrag(this._document, "pointercancel", onEnd);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
_setInputFromPointer(input, event, emitInput = true) {
|
|
284
|
+
const percent = this._pointerPercent(event);
|
|
285
|
+
const min = inputMinimum(input);
|
|
286
|
+
const max = inputMaximum(input);
|
|
287
|
+
input.value = String(snapToStep(min + percent * (max - min), input));
|
|
288
|
+
input.focus({ preventScroll: true });
|
|
289
|
+
this._sync(input);
|
|
290
|
+
if (emitInput) {
|
|
291
|
+
input.dispatchEvent(new this._window.Event("input", { bubbles: true }));
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
_pointerPercent(event) {
|
|
296
|
+
const rect = this._track.getBoundingClientRect();
|
|
297
|
+
const orientation = this._element.dataset.sliderOrientation || "horizontal";
|
|
298
|
+
if (orientation === "vertical") {
|
|
299
|
+
return clamp((rect.bottom - event.clientY) / (rect.height || 1), 0, 1);
|
|
300
|
+
}
|
|
301
|
+
return this._horizontalPointerPercent(event, rect);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
_horizontalPointerPercent(event, rect) {
|
|
305
|
+
const direction = this._window.getComputedStyle?.(this._element).direction;
|
|
306
|
+
const offset = direction === "rtl" ? rect.right - event.clientX : event.clientX - rect.left;
|
|
307
|
+
return clamp(offset / (rect.width || 1), 0, 1);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
_nearestInput(percent, inputs) {
|
|
311
|
+
if (inputs.length === 1) {
|
|
312
|
+
return inputs[0];
|
|
313
|
+
}
|
|
314
|
+
const [startInput, endInput] = inputs;
|
|
315
|
+
const startPercent = valuePercent(startInput);
|
|
316
|
+
const endPercent = valuePercent(endInput);
|
|
317
|
+
const startDistance = Math.abs(startPercent - percent);
|
|
318
|
+
const endDistance = Math.abs(endPercent - percent);
|
|
319
|
+
if (startDistance === endDistance) {
|
|
320
|
+
return percent >= startPercent ? endInput : startInput;
|
|
321
|
+
}
|
|
322
|
+
return endDistance < startDistance ? endInput : startInput;
|
|
323
|
+
}
|
|
324
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wpmoo/ui",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.3",
|
|
4
4
|
"description": "Bootstrap markup. shadcn feel. A frontend-framework-free component system for server-rendered apps.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "WPMoo (https://wpmoo.org)",
|
|
@@ -31,7 +31,12 @@
|
|
|
31
31
|
"./sidebar.js": "./dist/js/sidebar.js",
|
|
32
32
|
"./context-menu.js": "./dist/js/context-menu.js",
|
|
33
33
|
"./datatable.js": "./dist/js/datatable.js",
|
|
34
|
-
"./
|
|
34
|
+
"./slider.js": "./dist/js/slider.js",
|
|
35
|
+
"./chart.js": "./dist/js/chart.js",
|
|
36
|
+
"./chart.min.js": "./dist/js/chart.min.js",
|
|
37
|
+
"./datepicker.js": "./dist/js/datepicker.js",
|
|
38
|
+
"./datepicker.min.js": "./dist/js/datepicker.min.js",
|
|
39
|
+
"./scss/config": "./scss/_config.scss",
|
|
35
40
|
"./certification.json": "./certification.json",
|
|
36
41
|
"./package.json": "./package.json"
|
|
37
42
|
},
|
|
@@ -44,12 +49,17 @@
|
|
|
44
49
|
"dist/js/sidebar.js",
|
|
45
50
|
"dist/js/context-menu.js",
|
|
46
51
|
"dist/js/datatable.js",
|
|
47
|
-
"
|
|
48
|
-
"
|
|
52
|
+
"dist/js/slider.js",
|
|
53
|
+
"dist/js/chart.js",
|
|
54
|
+
"dist/js/chart.min.js",
|
|
55
|
+
"dist/js/datepicker.js",
|
|
56
|
+
"dist/js/datepicker.min.js",
|
|
57
|
+
"scss/_config.scss",
|
|
49
58
|
"certification.json",
|
|
50
59
|
"README.md",
|
|
51
60
|
"LICENSE",
|
|
52
|
-
"ASSET_LICENSE.md"
|
|
61
|
+
"ASSET_LICENSE.md",
|
|
62
|
+
"THIRD_PARTY_NOTICES.md"
|
|
53
63
|
],
|
|
54
64
|
"peerDependencies": {
|
|
55
65
|
"bootstrap": ">=5.3.0 <5.4"
|
|
@@ -74,7 +84,9 @@
|
|
|
74
84
|
"access": "public"
|
|
75
85
|
},
|
|
76
86
|
"devDependencies": {
|
|
77
|
-
"axe-core": "4.
|
|
78
|
-
"
|
|
87
|
+
"axe-core": "4.13.0",
|
|
88
|
+
"chart.js": "4.5.1",
|
|
89
|
+
"esbuild": "0.28.1",
|
|
90
|
+
"wrangler": "^4.120.0"
|
|
79
91
|
}
|
|
80
92
|
}
|