panelui-native 0.102.1 → 0.102.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/lib/module/components/number-input/index.js +28 -17
- package/lib/module/components/number-input/index.js.map +1 -1
- package/lib/module/components/number-input/number-input-repeat.js +51 -0
- package/lib/module/components/number-input/number-input-repeat.js.map +1 -0
- package/lib/typescript/src/components/number-input/index.d.ts.map +1 -1
- package/lib/typescript/src/components/number-input/number-input-repeat.d.ts +24 -0
- package/lib/typescript/src/components/number-input/number-input-repeat.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/components/number-input/index.tsx +28 -17
- package/src/components/number-input/number-input-repeat.ts +55 -0
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
* short delay and then faster, the way a native stepper does — so walking from
|
|
14
14
|
* 0 to 200 is a press, not two hundred of them. The repeat reads the live
|
|
15
15
|
* value from a ref rather than a closure, so it never strides off a stale
|
|
16
|
-
* number
|
|
16
|
+
* number, and it stops at a bound on its own rather than waiting for a
|
|
17
|
+
* release a disabled button may never send.
|
|
17
18
|
*
|
|
18
19
|
* Typing is allowed to be briefly invalid — an empty field, a lone `-`, a
|
|
19
20
|
* trailing `.` — because clamping every keystroke fights the person mid-number.
|
|
@@ -37,6 +38,7 @@ import { Text } from "../../primitives/text.js";
|
|
|
37
38
|
import { selectionTick } from "../../utils/haptics.js";
|
|
38
39
|
import { Label } from "../label/index.js";
|
|
39
40
|
import { normalize, precisionOf } from "./number-input-math.js";
|
|
41
|
+
import { createRepeater } from "./number-input-repeat.js";
|
|
40
42
|
|
|
41
43
|
/** Wait before a held button starts repeating — a tap must not trip it. */
|
|
42
44
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
@@ -204,26 +206,35 @@ export const NumberInput = /*#__PURE__*/forwardRef(({
|
|
|
204
206
|
const clamped = normalize(next, min, max, step);
|
|
205
207
|
if (tick && haptics) selectionTick();
|
|
206
208
|
if (!isControlled) setUncontrolled(clamped);
|
|
207
|
-
if (clamped !==
|
|
208
|
-
|
|
209
|
+
if (clamped !== valueRef.current) onValueChange?.(clamped);
|
|
210
|
+
// Advance the ref now, so the next repeat steps from here even if the
|
|
211
|
+
// render carrying this value has not landed yet.
|
|
212
|
+
valueRef.current = clamped;
|
|
213
|
+
}, [min, max, step, haptics, isControlled, onValueChange]);
|
|
209
214
|
|
|
210
215
|
// --- hold-to-repeat -----------------------------------------------------
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
216
|
+
// The timer outlives the render that started it, so it calls the latest
|
|
217
|
+
// `commit` through a ref instead of the one it was created with.
|
|
218
|
+
const commitRef = useRef(commit);
|
|
219
|
+
commitRef.current = commit;
|
|
220
|
+
const repeaterRef = useRef(null);
|
|
221
|
+
if (!repeaterRef.current) repeaterRef.current = createRepeater(REPEAT_DELAY, REPEAT_INTERVAL);
|
|
222
|
+
const repeater = repeaterRef.current;
|
|
223
|
+
const stopRepeat = repeater.stop;
|
|
219
224
|
useEffect(() => stopRepeat, [stopRepeat]);
|
|
225
|
+
useEffect(() => {
|
|
226
|
+
if (disabled) stopRepeat();
|
|
227
|
+
}, [disabled, stopRepeat]);
|
|
220
228
|
const startRepeat = useCallback(direction => {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
229
|
+
repeater.start(() => {
|
|
230
|
+
const current = valueRef.current;
|
|
231
|
+
const next = normalize(current + direction * step, min, max, step);
|
|
232
|
+
if (next === current) return false;
|
|
233
|
+
commitRef.current(next, true);
|
|
234
|
+
// Keep going only while there is room for another step.
|
|
235
|
+
return direction > 0 ? next < max : next > min;
|
|
236
|
+
});
|
|
237
|
+
}, [repeater, step, min, max]);
|
|
227
238
|
const atMin = value <= min;
|
|
228
239
|
const atMax = value >= max;
|
|
229
240
|
const handleEndEditing = useCallback(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["forwardRef","useCallback","useEffect","useRef","useState","TextInput","View","tv","useCSSVariable","MinusIcon","PlusIcon","AnimatedPressable","Text","selectionTick","Label","normalize","precisionOf","jsx","_jsx","jsxs","_jsxs","REPEAT_DELAY","REPEAT_INTERVAL","numberInputVariants","slots","container","control","button","field","description","error","variants","variant","outline","filled","size","sm","md","lg","invalid","true","disabled","defaultVariants","ICON_SIZE","FIELD_BASE","paddingVertical","paddingHorizontal","includeFontPadding","textAlignVertical","fontVariant","FIELD_STYLE","fontSize","NumberInput","className","containerClassName","value","controlledValue","defaultValue","min","Infinity","max","step","onValueChange","formatValue","editable","label","errorMessage","isRequired","haptics","placeholder","onFocus","onBlur","returnKeyType","ref","isControlled","undefined","initial","isFinite","uncontrolled","setUncontrolled","valueRef","current","foreground","iconColor","format","v","String","text","setText","focused","setFocused","commit","next","tick","clamped","
|
|
1
|
+
{"version":3,"names":["forwardRef","useCallback","useEffect","useRef","useState","TextInput","View","tv","useCSSVariable","MinusIcon","PlusIcon","AnimatedPressable","Text","selectionTick","Label","normalize","precisionOf","createRepeater","jsx","_jsx","jsxs","_jsxs","REPEAT_DELAY","REPEAT_INTERVAL","numberInputVariants","slots","container","control","button","field","description","error","variants","variant","outline","filled","size","sm","md","lg","invalid","true","disabled","defaultVariants","ICON_SIZE","FIELD_BASE","paddingVertical","paddingHorizontal","includeFontPadding","textAlignVertical","fontVariant","FIELD_STYLE","fontSize","NumberInput","className","containerClassName","value","controlledValue","defaultValue","min","Infinity","max","step","onValueChange","formatValue","editable","label","errorMessage","isRequired","haptics","placeholder","onFocus","onBlur","returnKeyType","ref","isControlled","undefined","initial","isFinite","uncontrolled","setUncontrolled","valueRef","current","foreground","iconColor","format","v","String","text","setText","focused","setFocused","commit","next","tick","clamped","commitRef","repeaterRef","repeater","stopRepeat","stop","startRepeat","direction","start","atMin","atMax","handleEndEditing","parsed","parseFloat","Number","isNaN","children","isInvalid","isDisabled","pressOpacity","onPressIn","onPressOut","accessibilityRole","accessibilityLabel","accessibilityState","style","opacity","color","strokeWidth","keyboardType","selectTextOnFocus","onChangeText","e","onSubmitEditing","displayName"],"sourceRoot":"../../../../src","sources":["components/number-input/index.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The hold-to-repeat timer behind NumberInput's − and + buttons.
|
|
5
|
+
*
|
|
6
|
+
* A press steps once, then after `delay` keeps stepping every `interval` until
|
|
7
|
+
* it is stopped. Two things keep it from running away:
|
|
8
|
+
*
|
|
9
|
+
* - There is only ever one timer. `start` clears whatever is already running,
|
|
10
|
+
* because a press-in does not always arrive after the previous press-out —
|
|
11
|
+
* quick taps on Android can deliver two press-ins in a row, and a second
|
|
12
|
+
* timer started over the first leaves the first with no handle to clear it.
|
|
13
|
+
* - The step reports whether another one is possible. At a bound the button
|
|
14
|
+
* disables, and a disabled button is not guaranteed to deliver the release
|
|
15
|
+
* that would stop the timer, so the timer stops itself there instead.
|
|
16
|
+
*
|
|
17
|
+
* Kept free of React so it can be tested on its own.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
export function createRepeater(delay, interval) {
|
|
21
|
+
let delayTimer = null;
|
|
22
|
+
let intervalTimer = null;
|
|
23
|
+
// Bumped by every start and stop. A callback from an earlier generation does
|
|
24
|
+
// nothing, so a timer that fires once more after being cleared cannot step.
|
|
25
|
+
let generation = 0;
|
|
26
|
+
const stop = () => {
|
|
27
|
+
generation += 1;
|
|
28
|
+
if (delayTimer !== null) clearTimeout(delayTimer);
|
|
29
|
+
if (intervalTimer !== null) clearInterval(intervalTimer);
|
|
30
|
+
delayTimer = null;
|
|
31
|
+
intervalTimer = null;
|
|
32
|
+
};
|
|
33
|
+
const start = step => {
|
|
34
|
+
stop();
|
|
35
|
+
const current = generation;
|
|
36
|
+
if (!step()) return;
|
|
37
|
+
delayTimer = setTimeout(() => {
|
|
38
|
+
if (current !== generation) return;
|
|
39
|
+
delayTimer = null;
|
|
40
|
+
intervalTimer = setInterval(() => {
|
|
41
|
+
if (current !== generation) return;
|
|
42
|
+
if (!step()) stop();
|
|
43
|
+
}, interval);
|
|
44
|
+
}, delay);
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
start,
|
|
48
|
+
stop
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=number-input-repeat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["createRepeater","delay","interval","delayTimer","intervalTimer","generation","stop","clearTimeout","clearInterval","start","step","current","setTimeout","setInterval"],"sourceRoot":"../../../../src","sources":["components/number-input/number-input-repeat.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AASA,OAAO,SAASA,cAAcA,CAACC,KAAa,EAAEC,QAAgB,EAAY;EACxE,IAAIC,UAAgD,GAAG,IAAI;EAC3D,IAAIC,aAAoD,GAAG,IAAI;EAC/D;EACA;EACA,IAAIC,UAAU,GAAG,CAAC;EAElB,MAAMC,IAAI,GAAGA,CAAA,KAAM;IACjBD,UAAU,IAAI,CAAC;IACf,IAAIF,UAAU,KAAK,IAAI,EAAEI,YAAY,CAACJ,UAAU,CAAC;IACjD,IAAIC,aAAa,KAAK,IAAI,EAAEI,aAAa,CAACJ,aAAa,CAAC;IACxDD,UAAU,GAAG,IAAI;IACjBC,aAAa,GAAG,IAAI;EACtB,CAAC;EAED,MAAMK,KAAK,GAAIC,IAAmB,IAAK;IACrCJ,IAAI,CAAC,CAAC;IACN,MAAMK,OAAO,GAAGN,UAAU;IAC1B,IAAI,CAACK,IAAI,CAAC,CAAC,EAAE;IACbP,UAAU,GAAGS,UAAU,CAAC,MAAM;MAC5B,IAAID,OAAO,KAAKN,UAAU,EAAE;MAC5BF,UAAU,GAAG,IAAI;MACjBC,aAAa,GAAGS,WAAW,CAAC,MAAM;QAChC,IAAIF,OAAO,KAAKN,UAAU,EAAE;QAC5B,IAAI,CAACK,IAAI,CAAC,CAAC,EAAEJ,IAAI,CAAC,CAAC;MACrB,CAAC,EAAEJ,QAAQ,CAAC;IACd,CAAC,EAAED,KAAK,CAAC;EACX,CAAC;EAED,OAAO;IAAEQ,KAAK;IAAEH;EAAK,CAAC;AACxB","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/number-input/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/number-input/index.tsx"],"names":[],"mappings":"AA6BA,OAAO,EAAE,SAAS,EAAQ,KAAK,cAAc,EAAkB,MAAM,cAAc,CAAC;AACpF,OAAO,EAAM,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAe1D,QAAA,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2CAkCvB,CAAC;AAuCH,KAAK,uBAAuB,GAAG,YAAY,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAExE,MAAM,WAAW,gBACf,SAAQ,IAAI,CAAC,uBAAuB,EAAE,SAAS,GAAG,UAAU,CAAC,EAC3D,IAAI,CAAC,cAAc,EAAE,SAAS,GAAG,QAAQ,GAAG,aAAa,GAAG,eAAe,CAAC;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iFAAiF;IACjF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,yEAAyE;IACzE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,wGA+LvB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The hold-to-repeat timer behind NumberInput's − and + buttons.
|
|
3
|
+
*
|
|
4
|
+
* A press steps once, then after `delay` keeps stepping every `interval` until
|
|
5
|
+
* it is stopped. Two things keep it from running away:
|
|
6
|
+
*
|
|
7
|
+
* - There is only ever one timer. `start` clears whatever is already running,
|
|
8
|
+
* because a press-in does not always arrive after the previous press-out —
|
|
9
|
+
* quick taps on Android can deliver two press-ins in a row, and a second
|
|
10
|
+
* timer started over the first leaves the first with no handle to clear it.
|
|
11
|
+
* - The step reports whether another one is possible. At a bound the button
|
|
12
|
+
* disables, and a disabled button is not guaranteed to deliver the release
|
|
13
|
+
* that would stop the timer, so the timer stops itself there instead.
|
|
14
|
+
*
|
|
15
|
+
* Kept free of React so it can be tested on its own.
|
|
16
|
+
*/
|
|
17
|
+
export interface Repeater {
|
|
18
|
+
/** Step once now, then repeat until `stop`. Replaces any running repeat. */
|
|
19
|
+
start: (step: () => boolean) => void;
|
|
20
|
+
/** Stop repeating. Safe to call when nothing is running. */
|
|
21
|
+
stop: () => void;
|
|
22
|
+
}
|
|
23
|
+
export declare function createRepeater(delay: number, interval: number): Repeater;
|
|
24
|
+
//# sourceMappingURL=number-input-repeat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"number-input-repeat.d.ts","sourceRoot":"","sources":["../../../../../src/components/number-input/number-input-repeat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,QAAQ;IACvB,4EAA4E;IAC5E,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,OAAO,KAAK,IAAI,CAAC;IACrC,4DAA4D;IAC5D,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,QAAQ,CA8BxE"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "panelui-native",
|
|
3
|
-
"version": "0.102.
|
|
3
|
+
"version": "0.102.2",
|
|
4
4
|
"description": "High-performance React Native UI components for Expo. Semantic design tokens, powered by Uniwind (Tailwind v4) and Reanimated.",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"module": "./lib/module/index.js",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
* short delay and then faster, the way a native stepper does — so walking from
|
|
12
12
|
* 0 to 200 is a press, not two hundred of them. The repeat reads the live
|
|
13
13
|
* value from a ref rather than a closure, so it never strides off a stale
|
|
14
|
-
* number
|
|
14
|
+
* number, and it stops at a bound on its own rather than waiting for a
|
|
15
|
+
* release a disabled button may never send.
|
|
15
16
|
*
|
|
16
17
|
* Typing is allowed to be briefly invalid — an empty field, a lone `-`, a
|
|
17
18
|
* trailing `.` — because clamping every keystroke fights the person mid-number.
|
|
@@ -35,6 +36,7 @@ import { Text } from '../../primitives/text';
|
|
|
35
36
|
import { selectionTick } from '../../utils/haptics';
|
|
36
37
|
import { Label } from '../label';
|
|
37
38
|
import { normalize, precisionOf } from './number-input-math';
|
|
39
|
+
import { createRepeater } from './number-input-repeat';
|
|
38
40
|
|
|
39
41
|
/** Wait before a held button starts repeating — a tap must not trip it. */
|
|
40
42
|
const REPEAT_DELAY = 400;
|
|
@@ -227,33 +229,42 @@ export const NumberInput = forwardRef<TextInput, NumberInputProps>(
|
|
|
227
229
|
const clamped = normalize(next, min, max, step);
|
|
228
230
|
if (tick && haptics) selectionTick();
|
|
229
231
|
if (!isControlled) setUncontrolled(clamped);
|
|
230
|
-
if (clamped !==
|
|
232
|
+
if (clamped !== valueRef.current) onValueChange?.(clamped);
|
|
233
|
+
// Advance the ref now, so the next repeat steps from here even if the
|
|
234
|
+
// render carrying this value has not landed yet.
|
|
235
|
+
valueRef.current = clamped;
|
|
231
236
|
},
|
|
232
|
-
[min, max, step, haptics, isControlled,
|
|
237
|
+
[min, max, step, haptics, isControlled, onValueChange]
|
|
233
238
|
);
|
|
234
239
|
|
|
235
240
|
// --- hold-to-repeat -----------------------------------------------------
|
|
236
|
-
|
|
237
|
-
|
|
241
|
+
// The timer outlives the render that started it, so it calls the latest
|
|
242
|
+
// `commit` through a ref instead of the one it was created with.
|
|
243
|
+
const commitRef = useRef(commit);
|
|
244
|
+
commitRef.current = commit;
|
|
238
245
|
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
delayRef.current = null;
|
|
243
|
-
intervalRef.current = null;
|
|
244
|
-
}, []);
|
|
246
|
+
const repeaterRef = useRef<ReturnType<typeof createRepeater> | null>(null);
|
|
247
|
+
if (!repeaterRef.current) repeaterRef.current = createRepeater(REPEAT_DELAY, REPEAT_INTERVAL);
|
|
248
|
+
const repeater = repeaterRef.current;
|
|
245
249
|
|
|
250
|
+
const stopRepeat = repeater.stop;
|
|
246
251
|
useEffect(() => stopRepeat, [stopRepeat]);
|
|
252
|
+
useEffect(() => {
|
|
253
|
+
if (disabled) stopRepeat();
|
|
254
|
+
}, [disabled, stopRepeat]);
|
|
247
255
|
|
|
248
256
|
const startRepeat = useCallback(
|
|
249
257
|
(direction: 1 | -1) => {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
258
|
+
repeater.start(() => {
|
|
259
|
+
const current = valueRef.current;
|
|
260
|
+
const next = normalize(current + direction * step, min, max, step);
|
|
261
|
+
if (next === current) return false;
|
|
262
|
+
commitRef.current(next, true);
|
|
263
|
+
// Keep going only while there is room for another step.
|
|
264
|
+
return direction > 0 ? next < max : next > min;
|
|
265
|
+
});
|
|
255
266
|
},
|
|
256
|
-
[
|
|
267
|
+
[repeater, step, min, max]
|
|
257
268
|
);
|
|
258
269
|
|
|
259
270
|
const atMin = value <= min;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The hold-to-repeat timer behind NumberInput's − and + buttons.
|
|
3
|
+
*
|
|
4
|
+
* A press steps once, then after `delay` keeps stepping every `interval` until
|
|
5
|
+
* it is stopped. Two things keep it from running away:
|
|
6
|
+
*
|
|
7
|
+
* - There is only ever one timer. `start` clears whatever is already running,
|
|
8
|
+
* because a press-in does not always arrive after the previous press-out —
|
|
9
|
+
* quick taps on Android can deliver two press-ins in a row, and a second
|
|
10
|
+
* timer started over the first leaves the first with no handle to clear it.
|
|
11
|
+
* - The step reports whether another one is possible. At a bound the button
|
|
12
|
+
* disables, and a disabled button is not guaranteed to deliver the release
|
|
13
|
+
* that would stop the timer, so the timer stops itself there instead.
|
|
14
|
+
*
|
|
15
|
+
* Kept free of React so it can be tested on its own.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export interface Repeater {
|
|
19
|
+
/** Step once now, then repeat until `stop`. Replaces any running repeat. */
|
|
20
|
+
start: (step: () => boolean) => void;
|
|
21
|
+
/** Stop repeating. Safe to call when nothing is running. */
|
|
22
|
+
stop: () => void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function createRepeater(delay: number, interval: number): Repeater {
|
|
26
|
+
let delayTimer: ReturnType<typeof setTimeout> | null = null;
|
|
27
|
+
let intervalTimer: ReturnType<typeof setInterval> | null = null;
|
|
28
|
+
// Bumped by every start and stop. A callback from an earlier generation does
|
|
29
|
+
// nothing, so a timer that fires once more after being cleared cannot step.
|
|
30
|
+
let generation = 0;
|
|
31
|
+
|
|
32
|
+
const stop = () => {
|
|
33
|
+
generation += 1;
|
|
34
|
+
if (delayTimer !== null) clearTimeout(delayTimer);
|
|
35
|
+
if (intervalTimer !== null) clearInterval(intervalTimer);
|
|
36
|
+
delayTimer = null;
|
|
37
|
+
intervalTimer = null;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const start = (step: () => boolean) => {
|
|
41
|
+
stop();
|
|
42
|
+
const current = generation;
|
|
43
|
+
if (!step()) return;
|
|
44
|
+
delayTimer = setTimeout(() => {
|
|
45
|
+
if (current !== generation) return;
|
|
46
|
+
delayTimer = null;
|
|
47
|
+
intervalTimer = setInterval(() => {
|
|
48
|
+
if (current !== generation) return;
|
|
49
|
+
if (!step()) stop();
|
|
50
|
+
}, interval);
|
|
51
|
+
}, delay);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
return { start, stop };
|
|
55
|
+
}
|