light-odometer 0.1.1 → 0.1.2
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 +37 -8
- package/dist/light-odometer.js +1 -1
- package/package.json +10 -11
package/README.md
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# light-odometer
|
|
4
|
+
  [](https://npmx.dev/light-odometer)
|
|
5
|
+
|
|
6
|
+
</div>
|
|
2
7
|
|
|
3
8
|
This project is made only for personal use, as a small and lightweight build of [tm-odometer](https://github.com/mtmarco87/tm-odometer), which is itself a fork of [HubSpot's odometer](https://github.com/HubSpot/odometer).
|
|
4
|
-
Do not use this, use [@mtmarco87](https://github.com/mtmarco87)'s package instead.
|
|
9
|
+
⚠️ Do not use this, use [@mtmarco87](https://github.com/mtmarco87)'s package instead.
|
|
5
10
|
Huge props to him for this TypeScript refactor !
|
|
6
11
|
|
|
7
12
|
No theme is shipped here, no docs either.
|
|
@@ -14,7 +19,7 @@ For a quick overview in a real-world usage, see https://github.com/EDM115/websit
|
|
|
14
19
|
- Added linting and formatting (OxLint + ESLint Stylistic)
|
|
15
20
|
- Keep only the ESM build and switch to a default export
|
|
16
21
|
- Better TS config and stricter types (no more `any` nor `as`)
|
|
17
|
-
- Target
|
|
22
|
+
- Target ES2023 instead of ES2015
|
|
18
23
|
- Remove compatibility layers (Internet Explorer, jQuery)
|
|
19
24
|
- Stabilize and simplify the interfaces
|
|
20
25
|
- Use overall more optimized methods
|
|
@@ -26,7 +31,8 @@ For a quick overview in a real-world usage, see https://github.com/EDM115/websit
|
|
|
26
31
|
- Each instance can now have an `id`
|
|
27
32
|
- Ability to customize the framerate
|
|
28
33
|
```ts
|
|
29
|
-
const odo = new LightOdometer({ ..., framerate: 20 })
|
|
34
|
+
const odo = new LightOdometer({ ..., framerate: 20 })
|
|
35
|
+
// default is 30, going above isn't recommended
|
|
30
36
|
// use countFramerate if you use the `count` mode instead of `slide`
|
|
31
37
|
```
|
|
32
38
|
- Ability to render once and destroy the instance
|
|
@@ -44,7 +50,7 @@ For a quick overview in a real-world usage, see https://github.com/EDM115/websit
|
|
|
44
50
|
const odo = new LightOdometer({ ... })
|
|
45
51
|
console.log(odo.getOptions().duration)
|
|
46
52
|
odo.setOptions({ duration: 2000 })
|
|
47
|
-
|
|
53
|
+
|
|
48
54
|
console.log(LightOdometer.getGlobalOptions.selector)
|
|
49
55
|
LightOdometer.setGlobalOptions({ selector: ".my-odometer" })
|
|
50
56
|
```
|
|
@@ -52,13 +58,13 @@ For a quick overview in a real-world usage, see https://github.com/EDM115/websit
|
|
|
52
58
|
```ts
|
|
53
59
|
const odo = new LightOdometer({ ... })
|
|
54
60
|
console.log(odo.isAnimating)
|
|
55
|
-
|
|
61
|
+
|
|
56
62
|
function onStart(e: Event) {
|
|
57
63
|
const { detail } = e as CustomEvent<LightOdometerEventDetail>
|
|
58
64
|
// detail.id, detail.value, detail.instance.isAnimating, ...
|
|
59
65
|
console.log(`started animating to ${detail.value}`)
|
|
60
66
|
}
|
|
61
|
-
|
|
67
|
+
|
|
62
68
|
function onDone(e: Event) {
|
|
63
69
|
const { detail } = e as CustomEvent<LightOdometerEventDetail>
|
|
64
70
|
console.log(`finished animating to ${detail.value}`)
|
|
@@ -74,5 +80,28 @@ For a quick overview in a real-world usage, see https://github.com/EDM115/websit
|
|
|
74
80
|
- Print the instance in a JSON-friendly string
|
|
75
81
|
```ts
|
|
76
82
|
const odo = new LightOdometer({ ... })
|
|
77
|
-
console.log(odo.toString())
|
|
83
|
+
console.log(odo.toString())
|
|
84
|
+
```
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"id": 2,
|
|
88
|
+
"value": 157,
|
|
89
|
+
"options": {
|
|
90
|
+
"id": 2,
|
|
91
|
+
"value": 0,
|
|
92
|
+
"animation": "slide",
|
|
93
|
+
"duration": 8000,
|
|
94
|
+
"format": "( ddd)",
|
|
95
|
+
"framerate": 20
|
|
96
|
+
},
|
|
97
|
+
"globalOptions": {},
|
|
98
|
+
"watchMutations": false,
|
|
99
|
+
"transitionEndBound": true,
|
|
100
|
+
"destroyed": false,
|
|
101
|
+
"format": {
|
|
102
|
+
"repeating": " ",
|
|
103
|
+
"precision": 0
|
|
104
|
+
},
|
|
105
|
+
"isAnimating": false
|
|
106
|
+
}
|
|
78
107
|
```
|
package/dist/light-odometer.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=/^\(?([^)]*)\)?(?:(.)(d+))?$/,t=2e3;function n(e){let t=document.createElement(`div`);if(t.innerHTML=e,!(t.firstElementChild instanceof HTMLElement))throw Error(`Invalid HTML: No valid root element found.`);return t.firstElementChild}function r(e,t){let n=t.split(` `);for(let t of n)e.classList.remove(t);return e.className}function i(e,t){let n=t.split(` `);for(let t of n)t&&e.classList.add(t);return e.className}function a(e,t,n){let r=new CustomEvent(t,{bubbles:!0,cancelable:!0,detail:n});e.dispatchEvent(r)}function o(){return typeof performance<`u`&&typeof performance.now==`function`?performance.now():Date.now()}function s(e,t){return t??=0,t?(e*=10**t,e+=.5,e=Math.floor(e),e/=10**t):Math.round(e)}function c(e){return e<0?Math.ceil(e):Math.floor(e)}function l(){return typeof window<`u`&&typeof document<`u`}function u(e){return l()&&typeof requestAnimationFrame==`function`?requestAnimationFrame(e):setTimeout(()=>e(o()),16)}function d(e){e!=null&&(l()&&typeof cancelAnimationFrame==`function`&&typeof e==`number`?cancelAnimationFrame(e):clearTimeout(e))}function f(e){l()&&(document.readyState===`complete`||document.readyState===`interactive`?setTimeout(e,0):document.addEventListener(`DOMContentLoaded`,e,{once:!0}))}function p(e){l()&&setTimeout(()=>{window.odometerOptions&&(e.options={...e.options,...window.odometerOptions})},0)}function m(e){f(()=>{e.options.auto!==!1&&e.init()})}var h=class f{static options=typeof window<`u`?window.odometerOptions??{}:{};_isAnimating=!1;options;el;value=0;inside;observer;watchMutations=!1;transitionEndBound=!1;destroyed=!1;format={repeating:``,precision:0};get isAnimating(){return this._isAnimating}MAX_VALUES;digits=[];ribbons={};_rafId;_countRafId;_msPerFrame;_countMsPerFrame;_onTransitionEnd;constructor(e){if(this.options=e,this.el=this.options.el,this.el.odometer){let e=this.el.odometer;e.options={...e.options,...this.options},e.options.duration??=t;let n=e.options.framerate??30,r=e.options.countFramerate??20;return e._msPerFrame=1e3/n,e._countMsPerFrame=1e3/r,e.MAX_VALUES=e.options.duration/e._msPerFrame/2|0,e.resetFormat(),this.options.value==null?l()&&e.render():e.update(this.options.value),e}this.el.odometer=this,this.options={...f.options,...this.options},this.options.duration??=t;let n=this.options.framerate??30,r=this.options.countFramerate??20;this._msPerFrame=1e3/n,this._countMsPerFrame=1e3/r,this.MAX_VALUES=this.options.duration/this._msPerFrame/2|0,this.resetFormat(),this.value=this.cleanValue(this.options.value??``),l()&&(this.renderInside(),this.render());try{for(let e of[`innerHTML`,`innerText`,`textContent`])Object.defineProperty(this.el,e,{get:()=>e===`innerHTML`?this.inside?.outerHTML??``:this.inside?.innerText??this.inside?.textContent??``,set:e=>this.update(e)})}catch{l()&&this.watchForMutations()}}renderInside(){l()&&(this.inside=document.createElement(`div`),this.inside.className=`odometer-inside`,this.el.textContent=``,this.el.appendChild(this.inside))}watchForMutations(){try{this.observer??=new MutationObserver(e=>{let t=this.el.innerText||``;this.renderInside(),this.render(this.value),this.update(t)}),this.watchMutations=!0,this.startWatchingMutations()}catch{}}startWatchingMutations(){this.watchMutations&&l()&&this.observer?.observe(this.el,{childList:!0})}stopWatchingMutations(){this.observer?.disconnect()}cleanValue(e){return typeof e==`string`&&(e=e.replace(this.format.radix??`.`,`<radix>`),e=e.replace(/[.,\s\u00A0\u202F]/g,``),e=e.replace(`<radix>`,`.`),e=parseFloat(e)||0),s(e,this.format.precision)}bindTransitionEnd(){if(this.transitionEndBound)return;this.transitionEndBound=!0;let e=!1;this._onTransitionEnd=()=>e?!0:(e=!0,setTimeout(()=>{this.render(),e=!1,this._isAnimating=!1,a(this.el,`odometerdone`,{id:this.options.id,el:this.el,instance:this,value:this.value,options:this.getOptions()})},0),!0),this.el.addEventListener(`transitionend`,this._onTransitionEnd,!1)}resetFormat(){let t=this.options.format??`(,ddd).dd`;t||=`d`;let n=e.exec(t);if(!n)throw Error(`LightOdometer: Unparsable digit format`);let[r,i,a,o]=n;this.format={repeating:i,radix:a,precision:o?.length||0}}render(e){if(l()){e??=this.value,this.stopWatchingMutations(),this.resetFormat(),this.inside.textContent=``;for(let e of Array.from(this.el.classList))/^odometer(-|$)/.test(e)&&this.el.classList.remove(e);this.el.classList.add(`odometer`,`odometer-auto-theme`),this.el.style.setProperty(`--odometer-duration`,`${this.options.duration??t}ms`),this.ribbons={},this.formatDigits(e),this.startWatchingMutations()}}formatDigits(e){if(this.digits=[],this.options.formatFunction){let t=this.options.formatFunction(e);for(let e of t.split(``).toReversed())if(/\d/.test(e)){let t=this.renderDigit(),n=t.querySelector(`.odometer-value`);n.textContent=e,i(n,`odometer-first-value odometer-last-value`),this.digits.push(t),this.insertDigit(t)}else this.addSpacer(e)}else{let t=this.preservePrecision(e),n=!this.format.precision;for(let e of t.split(``).toReversed())e===`.`&&(n=!0),this.addDigit(e,n)}}preservePrecision(e){let t=e.toString();if(this.format.precision){let e=t.split(`.`);e.length===1&&(t+=`.`,e[1]=``);for(let n=0;n<this.format.precision;n++)e[1][n]||(t+=`0`)}return t}update(e){if(!l())return this.value=this.cleanValue(e),this.value;e=this.cleanValue(e);let t=e-this.value;return t?(r(this.el,`odometer-animating-up odometer-animating-down odometer-animating`),t>0?i(this.el,`odometer-animating-up`):i(this.el,`odometer-animating-down`),this._isAnimating=!0,a(this.el,`odometerstart`,{id:this.options.id,el:this.el,instance:this,value:e,oldValue:this.value,options:this.getOptions()}),this.stopWatchingMutations(),this.animate(e),this.startWatchingMutations(),setTimeout(()=>{this.el.offsetHeight,i(this.el,`odometer-animating`)},0),this.value=e,this.value):this.value}renderDigit(){return n(`<span class="odometer-digit"><span class="odometer-digit-spacer">8</span><span class="odometer-digit-inner"><span class="odometer-ribbon"><span class="odometer-ribbon-inner"><span class="odometer-value"></span></span></span></span></span>`)}insertDigit(e,t){return t?this.inside.insertBefore(e,t):this.inside.children.length?this.inside.insertBefore(e,this.inside.children[0]):this.inside.appendChild(e)}addSpacer(e,t,r){let a=n(`<span class="odometer-formatting-mark"></span>`);return a.textContent=e,r&&i(a,r),this.insertDigit(a,t)}addDigit(e,t){if(t??=!0,e===`-`)return this.addSpacer(e,null,`odometer-negation-mark`);if(e===`.`)return this.addSpacer(this.format.radix??`.`,null,`odometer-radix-mark`);if(t){let e=!1;for(;;){if(!this.format.repeating.length){if(e)throw Error(`Bad odometer format without digits`);this.resetFormat(),e=!0}let t=this.format.repeating[this.format.repeating.length-1];if(this.format.repeating=this.format.repeating.substring(0,this.format.repeating.length-1),t===`d`)break;this.addSpacer(t)}}let n=this.renderDigit(),r=n.querySelector(`.odometer-value`);return r.textContent=e,i(r,`odometer-first-value odometer-last-value`),this.digits.push(n),this.insertDigit(n)}animate(e){this.options.animation===`count`?this.animateCount(e):this.animateSlide(e)}animateCount(e){if(!l())return;let t=e-this.value;if(!t)return;let n=o(),r=n,i=this.value,s=()=>{if(o()-n>(this.options.duration||0)){this.value=e,this.render(),this._isAnimating=!1,a(this.el,`odometerdone`,{id:this.options.id,el:this.el,instance:this,value:this.value,options:this.getOptions()});return}let c=o()-r;if(c>this._countMsPerFrame){r=o();let e=t*(c/(this.options.duration||0));i+=e,this.render(Math.round(i))}this._countRafId=u(s)};this._countRafId=u(s)}getDigitCount(...e){for(let t=0;t<e.length;t++)e[t]=Math.abs(e[t]);let t=Math.max(...e);return Math.ceil(Math.log(t+1)/Math.log(10))}getFractionalDigitCount(...e){let t=/^-?\d*\.(\d*?)0*$/;for(let n=0;n<e.length;n++){let r=e[n].toString(),i=t.exec(r);e[n]=i?i[1].length:0}return Math.max(...e)}resetDigits(){this.digits=[],this.ribbons={},this.inside.textContent=``,this.resetFormat()}createRange(e,t,n){let r=e<t,i=Math.abs(t-e)+(n?1:0);return Array.from({length:i},(t,n)=>r?e+n:e-n)}animateSlide(e){if(!l())return;let t=this.value,n=this.format.precision;n&&(e*=10**n,t*=10**n);let r=e-t;if(!r)return;this.bindTransitionEnd();let a=[],o=this.getDigitCount(t,e),s=0,u=t;for(let n=0;n<o;n++){u=c(t/10**(o-n-1));let r=c(e/10**(o-n-1)),i=r-u,l;if(Math.abs(i)>this.MAX_VALUES){l=[];let e=i/(this.MAX_VALUES*(1+s*.5)),t=u;for(;i>0&&t<r||i<0&&t>r;)l.push(Math.round(t)),t+=e;l[l.length-1]!==r&&l.push(r),s++}else l=this.createRange(u,r,!0);for(let e=0;e<l.length;e++)l[e]=Math.abs(l[e]%10);a.push(l)}this.resetDigits();let d=a.toReversed();for(let e=0;e<d.length;e++){let t=d[e];if(this.digits[e]||this.addDigit(` `,e>=n),this.ribbons[e]===void 0){let t=this.digits[e].querySelector(`.odometer-ribbon-inner`);t&&(this.ribbons[e]=t)}this.ribbons[e].textContent=``,r<0&&(t=t.toReversed());for(let n=0;n<t.length;n++){let r=t[n],a=document.createElement(`div`);a.className=`odometer-value`,a.textContent=r.toString(),this.ribbons[e].appendChild(a),n===t.length-1&&i(a,`odometer-last-value`),n===0&&i(a,`odometer-first-value`)}}u<0&&this.addDigit(`-`);let f=this.inside.querySelector(`.odometer-radix-mark`);f&&f.parentNode.removeChild(f),n&&this.addSpacer(this.format.radix??`.`,this.digits[n-1],`odometer-radix-mark`)}static init(){if(!l())return[];let e=document.querySelectorAll(f.options.selector||`.odometer`);return Array.from(e,e=>e.odometer=new f({el:e,value:e.innerText??e.textContent}))}setOptions(e){if(!e||typeof e!=`object`)return;`el`in e&&delete e.el;let n=Object.prototype.hasOwnProperty.call(e,`value`),r=Object.prototype.hasOwnProperty.call(e,`format`)||Object.prototype.hasOwnProperty.call(e,`formatFunction`),i=Object.prototype.hasOwnProperty.call(e,`duration`)||Object.prototype.hasOwnProperty.call(e,`framerate`)||Object.prototype.hasOwnProperty.call(e,`countFramerate`);this.options={...this.options,...e},this.options.duration??=t;let a=this.options.framerate??30,o=this.options.countFramerate??20;if(this._msPerFrame=1e3/a,this._countMsPerFrame=1e3/o,this.MAX_VALUES=this.options.duration/this._msPerFrame/2|0,l()&&this.el.style.setProperty(`--odometer-duration`,`${this.options.duration}ms`),r&&this.resetFormat(),n){this.update(this.options.value??0);return}(r||i)&&l()&&(this.stopWatchingMutations(),this.render(),this.startWatchingMutations())}static setGlobalOptions(e){f.options={...f.options,...e}}on(e,t){this.el.addEventListener(e,t)}off(e,t){this.el.removeEventListener(e,t)}getOptions(){return{...this.options}}static getGlobalOptions(){return{...f.options}}animateOnceAndDisconnect(e){e!=null&&this.update(e);let n=()=>this.disconnect(),r=e=>{this.el.removeEventListener(`odometerdone`,r),n()};this.el.addEventListener(`odometerdone`,r,{once:!0}),setTimeout(n,(this.options.duration??t)+100)}disconnect(){this.destroyed||=(this.stopWatchingMutations(),d(this._rafId),d(this._countRafId),this._onTransitionEnd&&=(this.el.removeEventListener(`transitionend`,this._onTransitionEnd),void 0),this.transitionEndBound=!1,!0)}toString(){let{el:e,...t}={...this.getOptions()},n={id:this.options.id,value:this.value,options:t,globalOptions:f.getGlobalOptions(),watchMutations:this.watchMutations,transitionEndBound:this.transitionEndBound,destroyed:this.destroyed,format:this.format,isAnimating:this.isAnimating};return JSON.stringify(n)}};p(h),m(h);export{h as LightOdometer,h as default};
|
|
1
|
+
const e=/^\(?([^)]*)\)?(?:(.)(d+))?$/,t=2e3;function n(e){let t=document.createElement(`div`);if(t.innerHTML=e,!(t.firstElementChild instanceof HTMLElement))throw Error(`Invalid HTML: No valid root element found.`);return t.firstElementChild}function r(e,t){let n=t.split(` `);for(let t of n)e.classList.remove(t);return e.className}function i(e,t){let n=t.split(` `);for(let t of n)t&&e.classList.add(t);return e.className}function a(e,t,n){let r=new CustomEvent(t,{bubbles:!0,cancelable:!0,detail:n});e.dispatchEvent(r)}function o(){return typeof performance<`u`&&typeof performance.now==`function`?performance.now():Date.now()}function s(e,t){return t??=0,t?(e*=10**t,e+=.5,e=Math.floor(e),e/=10**t):Math.round(e)}function c(e){return e<0?Math.ceil(e):Math.floor(e)}function l(){return typeof window<`u`&&typeof document<`u`}function u(e){return l()&&typeof requestAnimationFrame==`function`?requestAnimationFrame(e):setTimeout(()=>e(o()),16)}function d(e){e!=null&&(l()&&typeof cancelAnimationFrame==`function`&&typeof e==`number`?cancelAnimationFrame(e):clearTimeout(e))}function f(e){l()&&(document.readyState===`complete`||document.readyState===`interactive`?setTimeout(e,0):document.addEventListener(`DOMContentLoaded`,e,{once:!0}))}function p(e){l()&&setTimeout(()=>{window.odometerOptions&&(e.options={...e.options,...window.odometerOptions})},0)}function m(e){f(()=>{e.options.auto!==!1&&e.init()})}var h=class f{static options=typeof window<`u`?window.odometerOptions??{}:{};_isAnimating=!1;options;el;value=0;inside;observer;watchMutations=!1;transitionEndBound=!1;destroyed=!1;format={repeating:``,precision:0};get isAnimating(){return this._isAnimating}MAX_VALUES;digits=[];ribbons={};_rafId;_countRafId;_msPerFrame;_countMsPerFrame;_onTransitionEnd;constructor(e){if(this.options=e,this.el=this.options.el,this.el.odometer){let e=this.el.odometer;e.options={...e.options,...this.options},e.options.duration??=t;let n=e.options.framerate??30,r=e.options.countFramerate??20;return e._msPerFrame=1e3/n,e._countMsPerFrame=1e3/r,e.MAX_VALUES=e.options.duration/e._msPerFrame/2|0,e.resetFormat(),this.options.value==null?l()&&e.render():e.update(this.options.value),e}this.el.odometer=this,this.options={...f.options,...this.options},this.options.duration??=t;let n=this.options.framerate??30,r=this.options.countFramerate??20;this._msPerFrame=1e3/n,this._countMsPerFrame=1e3/r,this.MAX_VALUES=this.options.duration/this._msPerFrame/2|0,this.resetFormat(),this.value=this.cleanValue(this.options.value??``),l()&&(this.renderInside(),this.render());try{for(let e of[`innerHTML`,`innerText`,`textContent`])Object.defineProperty(this.el,e,{get:()=>e===`innerHTML`?this.inside?.outerHTML??``:this.inside?.innerText??this.inside?.textContent??``,set:e=>this.update(e)})}catch{l()&&this.watchForMutations()}}renderInside(){l()&&(this.inside=document.createElement(`div`),this.inside.className=`odometer-inside`,this.el.textContent=``,this.el.appendChild(this.inside))}watchForMutations(){try{this.observer??=new MutationObserver(e=>{let t=this.el.innerText||``;this.renderInside(),this.render(this.value),this.update(t)}),this.watchMutations=!0,this.startWatchingMutations()}catch{}}startWatchingMutations(){this.watchMutations&&l()&&this.observer?.observe(this.el,{childList:!0})}stopWatchingMutations(){this.observer?.disconnect()}cleanValue(e){return typeof e==`string`&&(e=e.replace(this.format.radix??`.`,`<radix>`),e=e.replace(/[.,\s\u00A0\u202F]/g,``),e=e.replace(`<radix>`,`.`),e=parseFloat(e)||0),s(e,this.format.precision)}bindTransitionEnd(){if(this.transitionEndBound)return;this.transitionEndBound=!0;let e=!1;this._onTransitionEnd=()=>e?!0:(e=!0,setTimeout(()=>{this.render(),e=!1,this._isAnimating=!1,a(this.el,`odometerdone`,{id:this.options.id,el:this.el,instance:this,value:this.value,options:this.getOptions()})},0),!0),this.el.addEventListener(`transitionend`,this._onTransitionEnd,!1)}resetFormat(){let t=this.options.format??`(,ddd).dd`;t||=`d`;let n=e.exec(t);if(!n)throw Error(`LightOdometer: Unparsable digit format`);let[r,i,a,o]=n;this.format={repeating:i,radix:a,precision:o?.length||0}}render(e){if(l()){e??=this.value,this.stopWatchingMutations(),this.resetFormat(),this.inside.textContent=``;for(let e of Array.from(this.el.classList))/^odometer(-|$)/.test(e)&&this.el.classList.remove(e);this.el.classList.add(`odometer`,`odometer-auto-theme`),this.el.style.setProperty(`--odometer-duration`,`${this.options.duration??2e3}ms`),this.ribbons={},this.formatDigits(e),this.startWatchingMutations()}}formatDigits(e){if(this.digits=[],this.options.formatFunction){let t=this.options.formatFunction(e);for(let e of t.split(``).toReversed())if(/\d/.test(e)){let t=this.renderDigit(),n=t.querySelector(`.odometer-value`);n.textContent=e,i(n,`odometer-first-value odometer-last-value`),this.digits.push(t),this.insertDigit(t)}else this.addSpacer(e)}else{let t=this.preservePrecision(e),n=!this.format.precision;for(let e of t.split(``).toReversed())e===`.`&&(n=!0),this.addDigit(e,n)}}preservePrecision(e){let t=e.toString();if(this.format.precision){let e=t.split(`.`);e.length===1&&(t+=`.`,e[1]=``);for(let n=0;n<this.format.precision;n++)e[1][n]||(t+=`0`)}return t}update(e){if(!l())return this.value=this.cleanValue(e),this.value;e=this.cleanValue(e);let t=e-this.value;return t?(r(this.el,`odometer-animating-up odometer-animating-down odometer-animating`),t>0?i(this.el,`odometer-animating-up`):i(this.el,`odometer-animating-down`),this._isAnimating=!0,a(this.el,`odometerstart`,{id:this.options.id,el:this.el,instance:this,value:e,oldValue:this.value,options:this.getOptions()}),this.stopWatchingMutations(),this.animate(e),this.startWatchingMutations(),setTimeout(()=>{this.el.offsetHeight,i(this.el,`odometer-animating`)},0),this.value=e,this.value):this.value}renderDigit(){return n(`<span class="odometer-digit"><span class="odometer-digit-spacer">8</span><span class="odometer-digit-inner"><span class="odometer-ribbon"><span class="odometer-ribbon-inner"><span class="odometer-value"></span></span></span></span></span>`)}insertDigit(e,t){return t?this.inside.insertBefore(e,t):this.inside.children.length?this.inside.insertBefore(e,this.inside.children[0]):this.inside.appendChild(e)}addSpacer(e,t,r){let a=n(`<span class="odometer-formatting-mark"></span>`);return a.textContent=e,r&&i(a,r),this.insertDigit(a,t)}addDigit(e,t){if(t??=!0,e===`-`)return this.addSpacer(e,null,`odometer-negation-mark`);if(e===`.`)return this.addSpacer(this.format.radix??`.`,null,`odometer-radix-mark`);if(t){let e=!1;for(;;){if(!this.format.repeating.length){if(e)throw Error(`Bad odometer format without digits`);this.resetFormat(),e=!0}let t=this.format.repeating[this.format.repeating.length-1];if(this.format.repeating=this.format.repeating.substring(0,this.format.repeating.length-1),t===`d`)break;this.addSpacer(t)}}let n=this.renderDigit(),r=n.querySelector(`.odometer-value`);return r.textContent=e,i(r,`odometer-first-value odometer-last-value`),this.digits.push(n),this.insertDigit(n)}animate(e){this.options.animation===`count`?this.animateCount(e):this.animateSlide(e)}animateCount(e){if(!l())return;let t=e-this.value;if(!t)return;let n=o(),r=n,i=this.value,s=()=>{if(o()-n>(this.options.duration||0)){this.value=e,this.render(),this._isAnimating=!1,a(this.el,`odometerdone`,{id:this.options.id,el:this.el,instance:this,value:this.value,options:this.getOptions()});return}let c=o()-r;if(c>this._countMsPerFrame){r=o();let e=t*(c/(this.options.duration||0));i+=e,this.render(Math.round(i))}this._countRafId=u(s)};this._countRafId=u(s)}getDigitCount(...e){for(let t=0;t<e.length;t++)e[t]=Math.abs(e[t]);let t=Math.max(...e);return Math.ceil(Math.log(t+1)/Math.log(10))}getFractionalDigitCount(...e){let t=/^-?\d*\.(\d*?)0*$/;for(let n=0;n<e.length;n++){let r=e[n].toString(),i=t.exec(r);e[n]=i?i[1].length:0}return Math.max(...e)}resetDigits(){this.digits=[],this.ribbons={},this.inside.textContent=``,this.resetFormat()}createRange(e,t,n){let r=e<t,i=Math.abs(t-e)+(n?1:0);return Array.from({length:i},(t,n)=>r?e+n:e-n)}animateSlide(e){if(!l())return;let t=this.value,n=this.format.precision;n&&(e*=10**n,t*=10**n);let r=e-t;if(!r)return;this.bindTransitionEnd();let a=[],o=this.getDigitCount(t,e),s=0,u=t;for(let n=0;n<o;n++){u=c(t/10**(o-n-1));let r=c(e/10**(o-n-1)),i=r-u,l;if(Math.abs(i)>this.MAX_VALUES){l=[];let e=i/(this.MAX_VALUES*(1+s*.5)),t=u;for(;i>0&&t<r||i<0&&t>r;)l.push(Math.round(t)),t+=e;l[l.length-1]!==r&&l.push(r),s++}else l=this.createRange(u,r,!0);for(let e=0;e<l.length;e++)l[e]=Math.abs(l[e]%10);a.push(l)}this.resetDigits();let d=a.toReversed();for(let e=0;e<d.length;e++){let t=d[e];if(this.digits[e]||this.addDigit(` `,e>=n),this.ribbons[e]===void 0){let t=this.digits[e].querySelector(`.odometer-ribbon-inner`);t&&(this.ribbons[e]=t)}this.ribbons[e].textContent=``,r<0&&(t=t.toReversed());for(let n=0;n<t.length;n++){let r=t[n],a=document.createElement(`div`);a.className=`odometer-value`,a.textContent=r.toString(),this.ribbons[e].appendChild(a),n===t.length-1&&i(a,`odometer-last-value`),n===0&&i(a,`odometer-first-value`)}}u<0&&this.addDigit(`-`);let f=this.inside.querySelector(`.odometer-radix-mark`);f&&f.parentNode.removeChild(f),n&&this.addSpacer(this.format.radix??`.`,this.digits[n-1],`odometer-radix-mark`)}static init(){if(!l())return[];let e=document.querySelectorAll(f.options.selector||`.odometer`);return Array.from(e,e=>e.odometer=new f({el:e,value:e.innerText??e.textContent}))}setOptions(e){if(!e||typeof e!=`object`)return;`el`in e&&delete e.el;let n=Object.prototype.hasOwnProperty.call(e,`value`),r=Object.prototype.hasOwnProperty.call(e,`format`)||Object.prototype.hasOwnProperty.call(e,`formatFunction`),i=Object.prototype.hasOwnProperty.call(e,`duration`)||Object.prototype.hasOwnProperty.call(e,`framerate`)||Object.prototype.hasOwnProperty.call(e,`countFramerate`);this.options={...this.options,...e},this.options.duration??=t;let a=this.options.framerate??30,o=this.options.countFramerate??20;if(this._msPerFrame=1e3/a,this._countMsPerFrame=1e3/o,this.MAX_VALUES=this.options.duration/this._msPerFrame/2|0,l()&&this.el.style.setProperty(`--odometer-duration`,`${this.options.duration}ms`),r&&this.resetFormat(),n){this.update(this.options.value??0);return}(r||i)&&l()&&(this.stopWatchingMutations(),this.render(),this.startWatchingMutations())}static setGlobalOptions(e){f.options={...f.options,...e}}on(e,t){this.el.addEventListener(e,t)}off(e,t){this.el.removeEventListener(e,t)}getOptions(){return{...this.options}}static getGlobalOptions(){return{...f.options}}animateOnceAndDisconnect(e){e!=null&&this.update(e);let t=()=>this.disconnect(),n=e=>{this.el.removeEventListener(`odometerdone`,n),t()};this.el.addEventListener(`odometerdone`,n,{once:!0}),setTimeout(t,(this.options.duration??2e3)+100)}disconnect(){this.destroyed||=(this.stopWatchingMutations(),d(this._rafId),d(this._countRafId),this._onTransitionEnd&&=(this.el.removeEventListener(`transitionend`,this._onTransitionEnd),void 0),this.transitionEndBound=!1,!0)}toString(){let{el:e,...t}={...this.getOptions()},n={id:this.options.id,value:this.value,options:t,globalOptions:f.getGlobalOptions(),watchMutations:this.watchMutations,transitionEndBound:this.transitionEndBound,destroyed:this.destroyed,format:this.format,isAnimating:this.isAnimating};return JSON.stringify(n)}};p(h),m(h);export{h as LightOdometer,h as default};
|
package/package.json
CHANGED
|
@@ -11,16 +11,15 @@
|
|
|
11
11
|
],
|
|
12
12
|
"description": "for personal use only, see EDM115/website",
|
|
13
13
|
"devDependencies": {
|
|
14
|
-
"@stylistic/eslint-plugin": "~5.
|
|
15
|
-
"@
|
|
16
|
-
"@typescript-eslint/parser": "~8.56.0",
|
|
14
|
+
"@stylistic/eslint-plugin": "~5.10.0",
|
|
15
|
+
"@typescript-eslint/parser": "~8.57.1",
|
|
17
16
|
"@typescript/native-preview": "latest",
|
|
18
|
-
"edm115-lint": "~0.
|
|
19
|
-
"eslint": "~10.
|
|
17
|
+
"edm115-lint": "~0.2.0",
|
|
18
|
+
"eslint": "~10.1.0",
|
|
20
19
|
"jiti": "~2.6.1",
|
|
21
|
-
"oxlint": "~1.
|
|
22
|
-
"oxlint-tsgolint": "~0.
|
|
23
|
-
"tsdown": "~0.
|
|
20
|
+
"oxlint": "~1.56.0",
|
|
21
|
+
"oxlint-tsgolint": "~0.17.1",
|
|
22
|
+
"tsdown": "~0.21.4",
|
|
24
23
|
"unplugin-unused": "~0.5.7"
|
|
25
24
|
},
|
|
26
25
|
"exports": {
|
|
@@ -62,12 +61,12 @@
|
|
|
62
61
|
"url": "git+https://github.com/EDM115/light-odometer.git"
|
|
63
62
|
},
|
|
64
63
|
"type": "module",
|
|
65
|
-
"version": "0.1.
|
|
64
|
+
"version": "0.1.2",
|
|
66
65
|
"scripts": {
|
|
67
66
|
"build": "tsdown",
|
|
68
67
|
"format": "eslint -c eslint.stylistic.config.ts --concurrency=auto --fix .",
|
|
69
|
-
"lint": "oxlint
|
|
70
|
-
"lint:fix": "oxlint --fix
|
|
68
|
+
"lint": "oxlint",
|
|
69
|
+
"lint:fix": "oxlint --fix",
|
|
71
70
|
"release": "pnpm publish",
|
|
72
71
|
"typecheck": "tsgo --noEmit"
|
|
73
72
|
}
|