light-odometer 0.1.2 → 0.1.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/README.md +21 -13
- package/dist/light-odometer.d.ts +159 -164
- package/dist/light-odometer.js +1 -1
- package/package.json +12 -11
package/README.md
CHANGED
|
@@ -14,20 +14,15 @@ No theme is shipped here, no docs either.
|
|
|
14
14
|
## What's changed ?
|
|
15
15
|
For a quick overview in a real-world usage, see https://github.com/EDM115/website/blob/master/app/components/ui/Odometer.vue
|
|
16
16
|
|
|
17
|
+
### Breaking changes
|
|
18
|
+
- Renamed from `TmOdometer` to `LightOdometer`
|
|
17
19
|
- Removal of all built artifacts, themes, demo, screenshots and CoffeeScript code
|
|
18
20
|
- Switch from Rollup to tsdown (Rolldown)
|
|
19
|
-
- Added linting and formatting (OxLint + ESLint Stylistic)
|
|
20
|
-
- Keep only the ESM build and switch to a default export
|
|
21
|
-
- Better TS config and stricter types (no more `any` nor `as`)
|
|
22
|
-
- Target ES2023 instead of ES2015
|
|
23
21
|
- Remove compatibility layers (Internet Explorer, jQuery)
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
-
|
|
28
|
-
- SSR friendly (you can import it top-level without blowing up) and use safe fallbacks fror browser-land functions
|
|
29
|
-
- Multiple performance improvements
|
|
30
|
-
- `value` is now stripped from spaces
|
|
22
|
+
- Keep only the ESM build and switch to a default export
|
|
23
|
+
|
|
24
|
+
### New features
|
|
25
|
+
- SSR friendly (you can import it top-level without blowing up) and use safe fallbacks for browser-land functions
|
|
31
26
|
- Each instance can now have an `id`
|
|
32
27
|
- Ability to customize the framerate
|
|
33
28
|
```ts
|
|
@@ -54,7 +49,7 @@ For a quick overview in a real-world usage, see https://github.com/EDM115/websit
|
|
|
54
49
|
console.log(LightOdometer.getGlobalOptions.selector)
|
|
55
50
|
LightOdometer.setGlobalOptions({ selector: ".my-odometer" })
|
|
56
51
|
```
|
|
57
|
-
- Add per-instance subscriptable animation start/end events
|
|
52
|
+
- Add per-instance subscriptable animation start/end events, they give back the instance id, el, instance, value, oldValue, options
|
|
58
53
|
```ts
|
|
59
54
|
const odo = new LightOdometer({ ... })
|
|
60
55
|
console.log(odo.isAnimating)
|
|
@@ -77,7 +72,7 @@ For a quick overview in a real-world usage, see https://github.com/EDM115/websit
|
|
|
77
72
|
odo.off("odometerstart", onStart)
|
|
78
73
|
odo.off("odometerdone", onDone)
|
|
79
74
|
```
|
|
80
|
-
- Print the instance
|
|
75
|
+
- Print the instance as a JSON-friendly string
|
|
81
76
|
```ts
|
|
82
77
|
const odo = new LightOdometer({ ... })
|
|
83
78
|
console.log(odo.toString())
|
|
@@ -105,3 +100,16 @@ For a quick overview in a real-world usage, see https://github.com/EDM115/websit
|
|
|
105
100
|
"isAnimating": false
|
|
106
101
|
}
|
|
107
102
|
```
|
|
103
|
+
|
|
104
|
+
### Improvements
|
|
105
|
+
- `value` is now stripped from spaces
|
|
106
|
+
- Multiple performance improvements
|
|
107
|
+
- Use overall more optimized methods
|
|
108
|
+
- Stabilize and simplify the interfaces
|
|
109
|
+
|
|
110
|
+
### Other changes
|
|
111
|
+
- No more const functions
|
|
112
|
+
- Better TS config and stricter types (no more `any` nor `as`)
|
|
113
|
+
- Use classes private elements
|
|
114
|
+
- Added linting and formatting (OxLint + ESLint Stylistic)
|
|
115
|
+
- Target ES2023 instead of ES2015
|
package/dist/light-odometer.d.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
//#region src/shared/interfaces.d.ts
|
|
2
2
|
/**
|
|
3
|
-
* LightOdometer global options interface
|
|
4
|
-
* @property {string} [selector] - The selector for the odometer elements.
|
|
5
|
-
* @property {boolean} [auto] - Whether to automatically initialize odometers.
|
|
6
|
-
*/
|
|
3
|
+
* LightOdometer global options interface
|
|
4
|
+
* @property {string} [selector] - The selector for the odometer elements.
|
|
5
|
+
* @property {boolean} [auto] - Whether to automatically initialize odometers.
|
|
6
|
+
*/
|
|
7
7
|
interface LightOdometerGlobalOptions {
|
|
8
8
|
selector?: string;
|
|
9
9
|
auto?: boolean;
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
|
-
* LightOdometer config interface
|
|
13
|
-
* @property {HTMLElement} el - The HTML element to attach the odometer to.
|
|
14
|
-
* @property {string | number | null} [value] - The initial value of the odometer.
|
|
15
|
-
* @property {string} [format] - The format string for the odometer.
|
|
16
|
-
* @property {number} [duration] - The duration of the animation in milliseconds.
|
|
17
|
-
* @property {number} [framerate] - Target framerate for slide animation.
|
|
18
|
-
* @property {number} [countFramerate] - Target framerate for count animation.
|
|
19
|
-
* @property {'count' | 'slide'} [animation] - The animation type ('count' or 'slide').
|
|
20
|
-
* @property {(value: number) => string} [formatFunction] - A custom format function.
|
|
21
|
-
*/
|
|
12
|
+
* LightOdometer config interface
|
|
13
|
+
* @property {HTMLElement} el - The HTML element to attach the odometer to.
|
|
14
|
+
* @property {string | number | null} [value] - The initial value of the odometer.
|
|
15
|
+
* @property {string} [format] - The format string for the odometer.
|
|
16
|
+
* @property {number} [duration] - The duration of the animation in milliseconds.
|
|
17
|
+
* @property {number} [framerate] - Target framerate for slide animation.
|
|
18
|
+
* @property {number} [countFramerate] - Target framerate for count animation.
|
|
19
|
+
* @property {'count' | 'slide'} [animation] - The animation type ('count' or 'slide').
|
|
20
|
+
* @property {(value: number) => string} [formatFunction] - A custom format function.
|
|
21
|
+
*/
|
|
22
22
|
interface LightOdometerOptions {
|
|
23
23
|
el: HTMLElement;
|
|
24
24
|
/** Optional identifier for this instance; propagated in event details */
|
|
@@ -33,11 +33,11 @@ interface LightOdometerOptions {
|
|
|
33
33
|
}
|
|
34
34
|
type LightOdometerEventName = "odometerstart" | "odometerdone";
|
|
35
35
|
/**
|
|
36
|
-
* FormatObject interface
|
|
37
|
-
* @property {string} repeating - The repeating part of the format. (i.e. '(,ddd)')
|
|
38
|
-
* @property {string} [radix] - The radix separator. (i.e. '.')
|
|
39
|
-
* @property {number} precision - The number of decimal places. (i.e. 'dd')
|
|
40
|
-
*/
|
|
36
|
+
* FormatObject interface
|
|
37
|
+
* @property {string} repeating - The repeating part of the format. (i.e. '(,ddd)')
|
|
38
|
+
* @property {string} [radix] - The radix separator. (i.e. '.')
|
|
39
|
+
* @property {number} precision - The number of decimal places. (i.e. 'dd')
|
|
40
|
+
*/
|
|
41
41
|
interface FormatObject {
|
|
42
42
|
repeating: string;
|
|
43
43
|
radix?: string;
|
|
@@ -54,8 +54,8 @@ declare global {
|
|
|
54
54
|
//#endregion
|
|
55
55
|
//#region src/core/odometer.d.ts
|
|
56
56
|
declare class LightOdometer {
|
|
57
|
+
#private;
|
|
57
58
|
static options: LightOdometerGlobalOptions;
|
|
58
|
-
private _isAnimating;
|
|
59
59
|
options: LightOdometerOptions;
|
|
60
60
|
el: HTMLElement;
|
|
61
61
|
value: number;
|
|
@@ -70,215 +70,210 @@ declare class LightOdometer {
|
|
|
70
70
|
MAX_VALUES: number;
|
|
71
71
|
digits: HTMLElement[];
|
|
72
72
|
ribbons: Record<number, HTMLElement>;
|
|
73
|
-
private _rafId?;
|
|
74
|
-
private _countRafId?;
|
|
75
|
-
private _msPerFrame;
|
|
76
|
-
private _countMsPerFrame;
|
|
77
|
-
private _onTransitionEnd?;
|
|
78
73
|
/**
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
74
|
+
* Initializes a new instance of the LightOdometer class.
|
|
75
|
+
* Sets up the odometer's options, formats, and DOM structure.
|
|
76
|
+
* If an odometer instance already exists on the element, it returns the existing instance.
|
|
77
|
+
* @param {LightOdometerOptions} options - Configuration options for the odometer.
|
|
78
|
+
*/
|
|
84
79
|
constructor(options: LightOdometerOptions);
|
|
85
80
|
/**
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
81
|
+
* Renders the inner container of the odometer.
|
|
82
|
+
* Clears the root element (`this.el`) and appends a new child element with the class `odometer-inside`.
|
|
83
|
+
* @returns {void}
|
|
84
|
+
*/
|
|
90
85
|
renderInside(): void;
|
|
91
86
|
/**
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
87
|
+
* Observes changes to the root element's content and updates the odometer accordingly.
|
|
88
|
+
* This is a fallback for environments like Safari where `.innerHTML` cannot be wrapped.
|
|
89
|
+
* @returns {void}
|
|
90
|
+
*/
|
|
96
91
|
watchForMutations(): void;
|
|
97
92
|
/**
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
93
|
+
* Starts observing mutations on the root element (`this.el`).
|
|
94
|
+
* Listens for changes to the element's child nodes (e.g., additions or removals).
|
|
95
|
+
* Requires `this.watchMutations` to be `true` and a `MutationObserver` to be initialized.
|
|
96
|
+
* @returns {void}
|
|
97
|
+
*/
|
|
103
98
|
startWatchingMutations(): void;
|
|
104
99
|
/**
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
100
|
+
* Stops observing mutations on the root element (`this.el`).
|
|
101
|
+
* Disconnects the `MutationObserver` if it is initialized.
|
|
102
|
+
* @returns {void}
|
|
103
|
+
*/
|
|
109
104
|
stopWatchingMutations(): void;
|
|
110
105
|
/**
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
106
|
+
* Cleans and normalizes a value to ensure it can be processed as a number.
|
|
107
|
+
* Converts formatted strings into numeric values by handling radix symbols and removing unnecessary characters.
|
|
108
|
+
* @param {string | number} val - The value to clean and normalize.
|
|
109
|
+
* @returns {number} The cleaned and rounded numeric value.
|
|
110
|
+
*/
|
|
116
111
|
cleanValue(val: string | number): number;
|
|
117
112
|
/**
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
113
|
+
* Binds transition end events to the root element (`this.el`).
|
|
114
|
+
* Ensures that the odometer re-renders only once per transition, even if multiple transition end events are triggered. After rendering, it dispatches the `odometerdone` custom event.
|
|
115
|
+
* @returns {void}
|
|
116
|
+
*/
|
|
122
117
|
bindTransitionEnd(): void;
|
|
123
118
|
/**
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
119
|
+
* Resets and parses the odometer's format configuration.
|
|
120
|
+
* Extracts the repeating pattern, radix symbol, and precision from the format string.
|
|
121
|
+
* Throws an error if the format string is invalid or unparsable.
|
|
122
|
+
* @returns {void}
|
|
123
|
+
*/
|
|
129
124
|
resetFormat(): void;
|
|
130
125
|
/**
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
126
|
+
* Renders the odometer with the specified value.
|
|
127
|
+
* Updates the DOM structure, applies the appropriate classes, and formats the digits for display.
|
|
128
|
+
* @param {number} [value] - The value to render. Defaults to the current value (`this.value`).
|
|
129
|
+
* @returns {void}
|
|
130
|
+
*/
|
|
136
131
|
render(value?: number): void;
|
|
137
132
|
/**
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
133
|
+
* Formats the given value into individual digits and renders them.
|
|
134
|
+
* If a custom format function is provided, it uses that to format the value.
|
|
135
|
+
* Otherwise, it preserves the precision and formats the value based on the odometer's configuration.
|
|
136
|
+
* @param {number} value - The value to format and render as digits.
|
|
137
|
+
* @returns {void}
|
|
138
|
+
*/
|
|
144
139
|
formatDigits(value: number): void;
|
|
145
140
|
/**
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
141
|
+
* Ensures the value maintains the specified precision by adding trailing zeros if necessary.
|
|
142
|
+
* This is used to keep the decimal places consistent at the end of the animation.
|
|
143
|
+
* @param {number} value - The numeric value to format with preserved precision.
|
|
144
|
+
* @returns {string} The value as a string with the required precision.
|
|
145
|
+
*/
|
|
151
146
|
preservePrecision(value: number): string;
|
|
152
147
|
/**
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
148
|
+
* Updates the odometer to display a new value.
|
|
149
|
+
* Cleans and normalizes the input value, determines the difference from the current value, and triggers the appropriate animations and DOM updates.
|
|
150
|
+
* @param {string | number} newValue - The new value to update the odometer to.
|
|
151
|
+
* @returns {number} The updated value of the odometer.
|
|
152
|
+
*/
|
|
158
153
|
update(newValue: string | number): number;
|
|
159
154
|
/**
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
155
|
+
* Creates and returns a new digit element for the odometer.
|
|
156
|
+
* The digit element is generated from the predefined `DIGIT_HTML` template.
|
|
157
|
+
* @returns {HTMLElement} The newly created digit element.
|
|
158
|
+
*/
|
|
164
159
|
renderDigit(): HTMLElement;
|
|
165
160
|
/**
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
161
|
+
* Inserts a digit element into the odometer's inner container.
|
|
162
|
+
* If a reference element (`before`) is provided, the digit is inserted before it.
|
|
163
|
+
* Otherwise, the digit is appended to the container or inserted at the beginning if other children exist.
|
|
164
|
+
* @param {HTMLElement} digit - The digit element to insert.
|
|
165
|
+
* @param {HTMLElement | null} [before] - The reference element to insert the digit before. Defaults to `null`.
|
|
166
|
+
* @returns {HTMLElement} The inserted digit element.
|
|
167
|
+
*/
|
|
173
168
|
insertDigit(digit: HTMLElement, before?: HTMLElement | null): HTMLElement;
|
|
174
169
|
/**
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
170
|
+
* Creates and inserts a spacer element into the odometer's inner container.
|
|
171
|
+
* A spacer is a non-digit element (e.g., a comma or decimal point) used for formatting.
|
|
172
|
+
* @param {string} chr - The character to display in the spacer.
|
|
173
|
+
* @param {HTMLElement | null} [before] - The reference element to insert the spacer before. Defaults to `null`.
|
|
174
|
+
* @param {string} [extraClasses] - Additional CSS classes to apply to the spacer element.
|
|
175
|
+
* @returns {HTMLElement} The inserted spacer element.
|
|
176
|
+
*/
|
|
182
177
|
addSpacer(chr: string, before?: HTMLElement | null, extraClasses?: string): HTMLElement;
|
|
183
178
|
/**
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
179
|
+
* Adds a digit or spacer element to the odometer's inner container.
|
|
180
|
+
* Handles special cases for negation (`-`) and radix (`.`) characters, and ensures the format's repeating pattern is respected.
|
|
181
|
+
* @param {string} value - The digit or character to add.
|
|
182
|
+
* @param {boolean} [repeating=true] - Whether to use the repeating format pattern. Defaults to `true`.
|
|
183
|
+
* @returns {HTMLElement} The inserted digit or spacer element.
|
|
184
|
+
* @throws {Error} If the format string is invalid or lacks digits.
|
|
185
|
+
*/
|
|
191
186
|
addDigit(value: string, repeating?: boolean): HTMLElement;
|
|
192
187
|
/**
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
188
|
+
* Animates the odometer to transition to a new value.
|
|
189
|
+
* Chooses the appropriate animation method (`count` or `slide`) based on the configuration and browser support.
|
|
190
|
+
* @param {number} newValue - The new value to animate the odometer to.
|
|
191
|
+
* @returns {void}
|
|
192
|
+
*/
|
|
198
193
|
animate(newValue: number): void;
|
|
199
194
|
/**
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
195
|
+
* Animates the odometer by incrementing or decrementing the value over time.
|
|
196
|
+
* Uses a "counting" animation to transition smoothly to the new value.
|
|
197
|
+
* @param {number} newValue - The new value to animate the odometer to.
|
|
198
|
+
* @returns {void}
|
|
199
|
+
*/
|
|
205
200
|
animateCount(newValue: number): void;
|
|
206
201
|
/**
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
202
|
+
* Calculates the number of digits in the largest absolute value from the provided numbers.
|
|
203
|
+
* @param {...number} values - A list of numbers to evaluate.
|
|
204
|
+
* @returns {number} The number of digits in the largest absolute value.
|
|
205
|
+
*/
|
|
211
206
|
getDigitCount(...values: number[]): number;
|
|
212
207
|
/**
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
208
|
+
* Calculates the maximum number of fractional digits (decimal places) among the provided numbers.
|
|
209
|
+
* Assumes the values have already been rounded to the specified precision.
|
|
210
|
+
* @param {...number} values - A list of numbers to evaluate.
|
|
211
|
+
* @returns {number} The maximum number of fractional digits.
|
|
212
|
+
*/
|
|
218
213
|
getFractionalDigitCount(...values: number[]): number;
|
|
219
214
|
/**
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
215
|
+
* Resets the odometer's digits and ribbons.
|
|
216
|
+
* Clears the inner container, resets the format configuration, and prepares the odometer for re-rendering.
|
|
217
|
+
* @returns {void}
|
|
218
|
+
*/
|
|
224
219
|
resetDigits(): void;
|
|
225
220
|
/**
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
221
|
+
* Creates an array of numbers between two values
|
|
222
|
+
* @param start The starting value of the range
|
|
223
|
+
* @param end The ending value of the range
|
|
224
|
+
* @param inclusive Whether to include the end value in the range
|
|
225
|
+
* @returns An array containing the range of numbers
|
|
226
|
+
*/
|
|
232
227
|
createRange(start: number, end: number, inclusive: boolean): number[];
|
|
233
228
|
/**
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
229
|
+
* Animates the odometer to transition to a new value using a sliding animation.
|
|
230
|
+
* Breaks the value into individual digits, calculates the frames for each digit's animation, and updates the DOM to reflect the sliding effect.
|
|
231
|
+
* @param {number} newValue - The new value to animate the odometer to.
|
|
232
|
+
* @returns {void}
|
|
233
|
+
*/
|
|
239
234
|
animateSlide(newValue: number): void;
|
|
240
235
|
/**
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
236
|
+
* Initializes all odometer elements on the page.
|
|
237
|
+
* Selects elements matching the configured selector or the default `.odometer` class, and creates a `LightOdometer` instance for each element.
|
|
238
|
+
* @returns {LightOdometer[]} An array of initialized `LightOdometer` instances.
|
|
239
|
+
*/
|
|
245
240
|
static init(): LightOdometer[];
|
|
246
241
|
/**
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
242
|
+
* Mutate this instance's options on-the-fly.
|
|
243
|
+
* Recomputes timing fields and applies changes immediately.
|
|
244
|
+
* If a new value is provided, it triggers update() with the new configuration.
|
|
245
|
+
*/
|
|
251
246
|
setOptions(newOptions: Partial<LightOdometerOptions>): void;
|
|
252
247
|
/**
|
|
253
|
-
|
|
254
|
-
|
|
248
|
+
* Update global default options at runtime. Does not retroactively affect existing instances.
|
|
249
|
+
*/
|
|
255
250
|
static setGlobalOptions(newOptions: Partial<LightOdometerGlobalOptions>): void;
|
|
256
251
|
/** Subscribe to odometer events ("odometerstart" | "odometerdone") for this instance */
|
|
257
252
|
on(event: LightOdometerEventName, handler: EventListener): void;
|
|
258
253
|
/** Unsubscribe from odometer events for this instance */
|
|
259
254
|
off(event: LightOdometerEventName, handler: EventListener): void;
|
|
260
255
|
/**
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
256
|
+
* Get a shallow copy snapshot of this instance's current options.
|
|
257
|
+
* Mutating the returned object will not affect the instance.
|
|
258
|
+
*/
|
|
264
259
|
getOptions(): Readonly<LightOdometerOptions>;
|
|
265
260
|
/**
|
|
266
|
-
|
|
267
|
-
|
|
261
|
+
* Get a shallow copy snapshot of global default options.
|
|
262
|
+
*/
|
|
268
263
|
static getGlobalOptions(): Readonly<LightOdometerGlobalOptions>;
|
|
269
264
|
/**
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
265
|
+
* Animate to a value exactly once and then disconnect listeners/observers.
|
|
266
|
+
* Useful for static numbers that only animate on first reveal.
|
|
267
|
+
*/
|
|
273
268
|
animateOnceAndDisconnect(toValue?: number | string): void;
|
|
274
269
|
/**
|
|
275
|
-
|
|
276
|
-
|
|
270
|
+
* Disconnect all observers and cancel animation frames. Remove transition listener flag.
|
|
271
|
+
*/
|
|
277
272
|
disconnect(): void;
|
|
278
273
|
/**
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
274
|
+
* Returns the current odometer object along with the global options.
|
|
275
|
+
* @returns {string} A JSON-parseable string representation of the current odometer state.
|
|
276
|
+
*/
|
|
282
277
|
toString(): string;
|
|
283
278
|
}
|
|
284
279
|
//#endregion
|
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??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};
|
|
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??{}:{};#e=!1;options;el;value=0;inside;observer;watchMutations=!1;transitionEndBound=!1;destroyed=!1;format={repeating:``,precision:0};get isAnimating(){return this.#e}MAX_VALUES;digits=[];ribbons={};#t;#n;#r;#i;#a;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.#r=1e3/n,e.#i=1e3/r,e.MAX_VALUES=e.options.duration/e.#r/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.#r=1e3/n,this.#i=1e3/r,this.MAX_VALUES=this.options.duration/this.#r/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.#a=()=>e?!0:(e=!0,setTimeout(()=>{this.render(),e=!1,this.#e=!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.#a,!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=n[1]??``,i=n[2],a=(n[3]??``).length;this.format={repeating:r,radix:i,precision:a}}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]=``);let n=e[1]??``;for(let e=0;e<this.format.precision;e++)n[e]||(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.#e=!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.firstElementChild):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(t!=null){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.#e=!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.#i){r=o();let e=c/(this.options.duration||0),n=t*e;i+=n,this.render(Math.round(i))}this.#n=u(s)};this.#n=u(s)}getDigitCount(...e){for(let t=0;t<e.length;t++){let n=e[t]??0;e[t]=Math.abs(n)}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]??0).toString(),i=t.exec(r),a=i?.[1]??``;e[n]=i?a.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;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++){let t=l[e]??0;l[e]=Math.abs(t%10)}a.push(l)}this.resetDigits();let d=a.toReversed();for(let e=0;e<d.length;e++){let t=d[e]??[];this.digits[e]||this.addDigit(` `,e>=n);let a=this.digits[e];if(!a)continue;if(this.ribbons[e]===void 0){let t=a.querySelector(`.odometer-ribbon-inner`);t&&(this.ribbons[e]=t)}let o=this.ribbons[e];if(o){o.textContent=``,r<0&&(t=t.toReversed());for(let e=0;e<t.length;e++){let n=t[e]??0,r=document.createElement(`div`);r.className=`odometer-value`,r.textContent=n.toString(),o.appendChild(r),e===t.length-1&&i(r,`odometer-last-value`),e===0&&i(r,`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.#r=1e3/a,this.#i=1e3/o,this.MAX_VALUES=this.options.duration/this.#r/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.#t),d(this.#n),this.#a&&=(this.el.removeEventListener(`transitionend`,this.#a),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
|
@@ -12,15 +12,16 @@
|
|
|
12
12
|
"description": "for personal use only, see EDM115/website",
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"@stylistic/eslint-plugin": "~5.10.0",
|
|
15
|
-
"@typescript-eslint/parser": "~8.
|
|
16
|
-
"@typescript/native
|
|
17
|
-
"edm115-lint": "~0.2.
|
|
18
|
-
"eslint": "~10.1
|
|
19
|
-
"jiti": "~2.
|
|
20
|
-
"oxlint": "~1.
|
|
21
|
-
"oxlint-tsgolint": "~0.
|
|
22
|
-
"tsdown": "~0.
|
|
23
|
-
"
|
|
15
|
+
"@typescript-eslint/parser": "~8.67.0",
|
|
16
|
+
"@typescript/native": "npm:typescript@^7.0.2",
|
|
17
|
+
"edm115-lint": "~0.2.1",
|
|
18
|
+
"eslint": "~10.8.1",
|
|
19
|
+
"jiti": "~2.7.0",
|
|
20
|
+
"oxlint": "~1.78.0",
|
|
21
|
+
"oxlint-tsgolint": "~7.0.2001",
|
|
22
|
+
"tsdown": "~0.22.14",
|
|
23
|
+
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
24
|
+
"unplugin-unused": "~0.6.0"
|
|
24
25
|
},
|
|
25
26
|
"exports": {
|
|
26
27
|
".": {
|
|
@@ -61,13 +62,13 @@
|
|
|
61
62
|
"url": "git+https://github.com/EDM115/light-odometer.git"
|
|
62
63
|
},
|
|
63
64
|
"type": "module",
|
|
64
|
-
"version": "0.1.
|
|
65
|
+
"version": "0.1.3",
|
|
65
66
|
"scripts": {
|
|
66
67
|
"build": "tsdown",
|
|
67
68
|
"format": "eslint -c eslint.stylistic.config.ts --concurrency=auto --fix .",
|
|
68
69
|
"lint": "oxlint",
|
|
69
70
|
"lint:fix": "oxlint --fix",
|
|
70
71
|
"release": "pnpm publish",
|
|
71
|
-
"typecheck": "
|
|
72
|
+
"typecheck": "tsc --noEmit"
|
|
72
73
|
}
|
|
73
74
|
}
|