yummies 7.11.0 → 7.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/async.cjs +162 -48
  2. package/async.cjs.map +1 -1
  3. package/async.d.ts +108 -7
  4. package/async.js +163 -54
  5. package/async.js.map +1 -1
  6. package/chunk-CVq3Gv4J.cjs +50 -0
  7. package/chunk-YKewjYmz.js +37 -0
  8. package/common.cjs +48 -8
  9. package/common.cjs.map +1 -1
  10. package/common.d.ts +35 -2
  11. package/common.js +49 -11
  12. package/common.js.map +1 -1
  13. package/complex.cjs +275 -128
  14. package/complex.cjs.map +1 -1
  15. package/complex.js +275 -133
  16. package/complex.js.map +1 -1
  17. package/cookie.cjs +17 -7
  18. package/cookie.cjs.map +1 -1
  19. package/cookie.d.ts +8 -0
  20. package/cookie.js +18 -9
  21. package/cookie.js.map +1 -1
  22. package/css.cjs +147 -39
  23. package/css.cjs.map +1 -1
  24. package/css.d.ts +98 -6
  25. package/css.js +143 -41
  26. package/css.js.map +1 -1
  27. package/data.cjs +90 -55
  28. package/data.cjs.map +1 -1
  29. package/data.d.ts +32 -0
  30. package/data.js +91 -61
  31. package/data.js.map +1 -1
  32. package/date-time.cjs +578 -412
  33. package/date-time.cjs.map +1 -1
  34. package/date-time.d.ts +88 -0
  35. package/date-time.js +575 -421
  36. package/date-time.js.map +1 -1
  37. package/device.cjs +48 -23
  38. package/device.cjs.map +1 -1
  39. package/device.d.ts +32 -0
  40. package/device.js +49 -31
  41. package/device.js.map +1 -1
  42. package/encodings.cjs +275 -266
  43. package/encodings.cjs.map +1 -1
  44. package/encodings.d.ts +8 -0
  45. package/encodings.js +276 -268
  46. package/encodings.js.map +1 -1
  47. package/errors.cjs +20 -18
  48. package/errors.cjs.map +1 -1
  49. package/errors.js +19 -19
  50. package/errors.js.map +1 -1
  51. package/file.cjs +42 -24
  52. package/file.cjs.map +1 -1
  53. package/file.d.ts +16 -0
  54. package/file.js +43 -27
  55. package/file.js.map +1 -1
  56. package/format.cjs +125 -83
  57. package/format.cjs.map +1 -1
  58. package/format.js +118 -82
  59. package/format.js.map +1 -1
  60. package/html.cjs +226 -137
  61. package/html.cjs.map +1 -1
  62. package/html.d.ts +64 -0
  63. package/html.js +223 -150
  64. package/html.js.map +1 -1
  65. package/id.cjs +74 -17
  66. package/id.cjs.map +1 -1
  67. package/id.js +73 -24
  68. package/id.js.map +1 -1
  69. package/imports.cjs +41 -29
  70. package/imports.cjs.map +1 -1
  71. package/imports.d.ts +8 -0
  72. package/imports.js +40 -31
  73. package/imports.js.map +1 -1
  74. package/math.cjs +32 -6
  75. package/math.cjs.map +1 -1
  76. package/math.d.ts +16 -0
  77. package/math.js +33 -10
  78. package/math.js.map +1 -1
  79. package/media.cjs +275 -84
  80. package/media.cjs.map +1 -1
  81. package/media.d.ts +188 -2
  82. package/media.js +274 -93
  83. package/media.js.map +1 -1
  84. package/mobx.cjs +353 -193
  85. package/mobx.cjs.map +1 -1
  86. package/mobx.d.ts +7 -0
  87. package/mobx.js +351 -200
  88. package/mobx.js.map +1 -1
  89. package/ms.cjs +21 -10
  90. package/ms.cjs.map +1 -1
  91. package/ms.js +22 -13
  92. package/ms.js.map +1 -1
  93. package/number.cjs +13 -7
  94. package/number.cjs.map +1 -1
  95. package/number.js +14 -9
  96. package/number.js.map +1 -1
  97. package/package.json +10 -2
  98. package/parser.cjs +117 -64
  99. package/parser.cjs.map +1 -1
  100. package/parser.js +111 -64
  101. package/parser.js.map +1 -1
  102. package/price.cjs +24 -18
  103. package/price.cjs.map +1 -1
  104. package/price.d.ts +8 -0
  105. package/price.js +25 -20
  106. package/price.js.map +1 -1
  107. package/random.cjs +79 -13
  108. package/random.cjs.map +1 -1
  109. package/random.d.ts +64 -0
  110. package/random.js +80 -22
  111. package/random.js.map +1 -1
  112. package/react.cjs +673 -214
  113. package/react.cjs.map +1 -1
  114. package/react.d.ts +21 -0
  115. package/react.js +674 -239
  116. package/react.js.map +1 -1
  117. package/sound.cjs +14 -9
  118. package/sound.cjs.map +1 -1
  119. package/sound.js +15 -11
  120. package/sound.js.map +1 -1
  121. package/storage.cjs +49 -50
  122. package/storage.cjs.map +1 -1
  123. package/storage.d.ts +8 -0
  124. package/storage.js +50 -53
  125. package/storage.js.map +1 -1
  126. package/text.cjs +51 -34
  127. package/text.cjs.map +1 -1
  128. package/text.js +52 -37
  129. package/text.js.map +1 -1
  130. package/type-guard.cjs +292 -72
  131. package/type-guard.cjs.map +1 -1
  132. package/type-guard.js +288 -73
  133. package/type-guard.js.map +1 -1
  134. package/types.cjs +0 -2
  135. package/types.global.cjs +0 -2
  136. package/types.global.js +0 -2
  137. package/types.js +0 -2
  138. package/vibrate.cjs +31 -6
  139. package/vibrate.cjs.map +1 -1
  140. package/vibrate.d.ts +23 -1
  141. package/vibrate.js +32 -8
  142. package/vibrate.js.map +1 -1
  143. package/types.cjs.map +0 -1
  144. package/types.global.cjs.map +0 -1
  145. package/types.global.js.map +0 -1
  146. package/types.js.map +0 -1
package/async.cjs CHANGED
@@ -1,60 +1,174 @@
1
- "use strict";
2
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const sleep = (time = 0, signal) => new Promise((resolve, reject) => {
4
- if (signal) {
5
- const abortListener = () => {
6
- clearTimeout(timerId);
7
- reject(signal?.reason);
8
- };
9
- const timerId = setTimeout(() => {
10
- signal.removeEventListener("abort", abortListener);
11
- resolve();
12
- }, time);
13
- signal.addEventListener("abort", abortListener, { once: true });
14
- } else {
15
- setTimeout(resolve, time);
16
- }
2
+ //#region src/async.ts
3
+ /**
4
+ * Returns a promise that resolves after `time` milliseconds.
5
+ *
6
+ * When `signal` is passed and becomes aborted before the delay elapses, the promise
7
+ * rejects with `signal.reason` (same as native `fetch` / `AbortController` usage).
8
+ * The timeout is cleared on abort so no resolve happens after cancellation.
9
+ *
10
+ * @param time - Delay in milliseconds. Defaults to `0` (next macrotask tick, same idea as `setTimeout(0)`).
11
+ * @param signal - Optional `AbortSignal` to cancel the wait early.
12
+ * @returns A promise that resolves with `void` when the delay completes, or rejects if aborted.
13
+ *
14
+ * @example
15
+ * Basic pause in an async function:
16
+ * ```ts
17
+ * await sleep(250);
18
+ * console.log('after 250ms');
19
+ * ```
20
+ *
21
+ * @example
22
+ * Cancellable delay tied to component unmount or user action:
23
+ * ```ts
24
+ * const ac = new AbortController();
25
+ * try {
26
+ * await sleep(5000, ac.signal);
27
+ * } catch (e) {
28
+ * // aborted — e is signal.reason
29
+ * }
30
+ * ac.abort('user cancelled');
31
+ * ```
32
+ */
33
+ var sleep = (time = 0, signal) => new Promise((resolve, reject) => {
34
+ if (signal) {
35
+ const abortListener = () => {
36
+ clearTimeout(timerId);
37
+ reject(signal?.reason);
38
+ };
39
+ const timerId = setTimeout(() => {
40
+ signal.removeEventListener("abort", abortListener);
41
+ resolve();
42
+ }, time);
43
+ signal.addEventListener("abort", abortListener, { once: true });
44
+ } else setTimeout(resolve, time);
17
45
  });
18
- const waitAsync = async (ms = 1e3) => new Promise((resolve) => setTimeout(resolve, ms));
19
- const endlessRAF = (quitFunction, asMicrotask) => {
20
- if (quitFunction()) return;
21
- const raf = () => requestAnimationFrame(() => endlessRAF(quitFunction, asMicrotask));
22
- if (asMicrotask) {
23
- queueMicrotask(raf);
24
- } else {
25
- raf();
26
- }
46
+ /**
47
+ * Creates a promise that resolves after the specified number of milliseconds.
48
+ *
49
+ * @deprecated Use `sleep` instead.
50
+ * @param ms Delay in milliseconds.
51
+ * @returns Promise
52
+ */
53
+ var waitAsync = async (ms = 1e3) => new Promise((resolve) => setTimeout(resolve, ms));
54
+ /**
55
+ * Runs a loop driven by `requestAnimationFrame`: on each frame, `quitFunction` is called first.
56
+ * If it returns a truthy value, the loop stops and no further frames are scheduled.
57
+ * If it returns falsy or nothing, the next frame is scheduled recursively.
58
+ *
59
+ * Use this for per-frame work (animations, layout reads after paint) without managing
60
+ * `cancelAnimationFrame` manually — returning `true` from `quitFunction` is the exit condition.
61
+ *
62
+ * When `asMicrotask` is `true`, scheduling the next RAF is deferred with `queueMicrotask`
63
+ * so other microtasks can run before the frame is requested (useful when you need to
64
+ * batch DOM updates or let reactive frameworks flush first).
65
+ *
66
+ * @param quitFunction - Invoked each animation frame. Return `true` to stop the loop.
67
+ * @param asMicrotask - If `true`, wrap the `requestAnimationFrame` call in `queueMicrotask`.
68
+ *
69
+ * @example
70
+ * Stop after 60 frames (~1s at 60Hz):
71
+ * ```ts
72
+ * let frames = 0;
73
+ * endlessRAF(() => {
74
+ * frames++;
75
+ * updateSomething(frames);
76
+ * return frames >= 60;
77
+ * });
78
+ * ```
79
+ *
80
+ * @example
81
+ * Run until an element is removed or a flag is set:
82
+ * ```ts
83
+ * let running = true;
84
+ * endlessRAF(() => {
85
+ * if (!running || !document.body.contains(el)) return true;
86
+ * draw(el);
87
+ * }, true);
88
+ * ```
89
+ */
90
+ var endlessRAF = (quitFunction, asMicrotask) => {
91
+ if (quitFunction()) return;
92
+ const raf = () => requestAnimationFrame(() => endlessRAF(quitFunction, asMicrotask));
93
+ if (asMicrotask) queueMicrotask(raf);
94
+ else raf();
27
95
  };
96
+ /**
97
+ * Like `setTimeout`, but if `signal` aborts before the delay fires, the timer is cleared
98
+ * and `callback` is never run. If the callback runs normally, the abort listener is removed.
99
+ *
100
+ * Does nothing special if `signal` is omitted — behaves like a plain timeout.
101
+ *
102
+ * @param callback - Function to run once after `delayInMs` (same as `setTimeout` callback).
103
+ * @param delayInMs - Milliseconds to wait. Passed through to `setTimeout` (browser/Node semantics apply).
104
+ * @param signal - When aborted, clears the pending timeout so `callback` is not invoked.
105
+ *
106
+ * @example
107
+ * ```ts
108
+ * const controller = new AbortController();
109
+ * setAbortableTimeout(() => console.log('done'), 500, controller.signal);
110
+ * // later: controller.abort(); // timeout cancelled, log never runs
111
+ * ```
112
+ *
113
+ * @example
114
+ * Zero-delay scheduling that can still be cancelled before the macrotask runs:
115
+ * ```ts
116
+ * const ac = new AbortController();
117
+ * setAbortableTimeout(() => startIntro(), 0, ac.signal);
118
+ * // e.g. on teardown: ac.abort();
119
+ * ```
120
+ */
28
121
  function setAbortableTimeout(callback, delayInMs, signal) {
29
- let internalTimer = null;
30
- const handleAbort = () => {
31
- if (internalTimer == null) {
32
- return;
33
- }
34
- clearTimeout(internalTimer);
35
- internalTimer = null;
36
- };
37
- signal?.addEventListener("abort", handleAbort, { once: true });
38
- internalTimer = setTimeout(() => {
39
- signal?.removeEventListener("abort", handleAbort);
40
- callback();
41
- }, delayInMs);
122
+ let internalTimer = null;
123
+ const handleAbort = () => {
124
+ if (internalTimer == null) return;
125
+ clearTimeout(internalTimer);
126
+ internalTimer = null;
127
+ };
128
+ signal?.addEventListener("abort", handleAbort, { once: true });
129
+ internalTimer = setTimeout(() => {
130
+ signal?.removeEventListener("abort", handleAbort);
131
+ callback();
132
+ }, delayInMs);
42
133
  }
134
+ /**
135
+ * Like `setInterval`, but when `signal` aborts, the interval is cleared with `clearInterval`
136
+ * and `callback` stops being called. If `signal` is omitted, behaves like a normal interval
137
+ * (you must clear it yourself).
138
+ *
139
+ * @param callback - Invoked every `delayInMs` milliseconds until aborted or cleared.
140
+ * @param delayInMs - Interval period in milliseconds (same as `setInterval`).
141
+ * @param signal - Aborting stops the interval and removes the abort listener path from keeping work alive.
142
+ *
143
+ * @example
144
+ * ```ts
145
+ * const controller = new AbortController();
146
+ * setAbortableInterval(() => console.log('tick'), 1000, controller.signal);
147
+ * // stop: controller.abort();
148
+ * ```
149
+ *
150
+ * @example
151
+ * ```ts
152
+ * const ac = new AbortController();
153
+ * setAbortableInterval(syncStatus, 30_000, ac.signal);
154
+ * window.addEventListener('beforeunload', () => ac.abort());
155
+ * ```
156
+ */
43
157
  function setAbortableInterval(callback, delayInMs, signal) {
44
- let timer = null;
45
- const handleAbort = () => {
46
- if (timer == null) {
47
- return;
48
- }
49
- clearInterval(timer);
50
- timer = null;
51
- };
52
- signal?.addEventListener("abort", handleAbort, { once: true });
53
- timer = setInterval(callback, delayInMs);
158
+ let timer = null;
159
+ const handleAbort = () => {
160
+ if (timer == null) return;
161
+ clearInterval(timer);
162
+ timer = null;
163
+ };
164
+ signal?.addEventListener("abort", handleAbort, { once: true });
165
+ timer = setInterval(callback, delayInMs);
54
166
  }
167
+ //#endregion
55
168
  exports.endlessRAF = endlessRAF;
56
169
  exports.setAbortableInterval = setAbortableInterval;
57
170
  exports.setAbortableTimeout = setAbortableTimeout;
58
171
  exports.sleep = sleep;
59
172
  exports.waitAsync = waitAsync;
60
- //# sourceMappingURL=async.cjs.map
173
+
174
+ //# sourceMappingURL=async.cjs.map
package/async.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"async.cjs","sources":["../src/async.ts"],"sourcesContent":["/**\n * Creates a promise that resolves after the specified number of milliseconds.\n *\n * @param time Delay in milliseconds.\n * @returns Promise\n */\nexport const sleep = (time: number = 0, signal?: AbortSignal) =>\n new Promise<void>((resolve, reject) => {\n if (signal) {\n const abortListener = () => {\n clearTimeout(timerId);\n reject(signal?.reason);\n };\n const timerId = setTimeout(() => {\n signal.removeEventListener('abort', abortListener);\n resolve();\n }, time);\n signal.addEventListener('abort', abortListener, { once: true });\n } else {\n setTimeout(resolve, time);\n }\n });\n\n/**\n * Creates a promise that resolves after the specified number of milliseconds.\n *\n * @deprecated Use `sleep` instead.\n * @param ms Delay in milliseconds.\n * @returns Promise\n */\nexport const waitAsync = async (ms = 1000) =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Repeatedly schedules `requestAnimationFrame` until `quitFunction` returns `true`.\n *\n * @param quitFunction Function executed on each animation frame.\n * @param asMicrotask Additionally wraps the RAF scheduling in `queueMicrotask`.\n * @returns void\n */\nexport const endlessRAF = (\n quitFunction: () => boolean | void,\n asMicrotask?: boolean,\n) => {\n if (quitFunction()) return;\n\n const raf = () =>\n requestAnimationFrame(() => endlessRAF(quitFunction, asMicrotask));\n\n if (asMicrotask) {\n queueMicrotask(raf);\n } else {\n raf();\n }\n};\n\nexport function setAbortableTimeout(\n callback: VoidFunction,\n delayInMs?: number,\n signal?: AbortSignal,\n) {\n let internalTimer: number | null = null;\n\n const handleAbort = () => {\n if (internalTimer == null) {\n return;\n }\n clearTimeout(internalTimer);\n internalTimer = null;\n };\n\n signal?.addEventListener('abort', handleAbort, { once: true });\n\n internalTimer = setTimeout(() => {\n signal?.removeEventListener('abort', handleAbort);\n callback();\n }, delayInMs);\n}\n\nexport function setAbortableInterval(\n callback: VoidFunction,\n delayInMs?: number,\n signal?: AbortSignal,\n) {\n let timer: number | null = null;\n\n const handleAbort = () => {\n if (timer == null) {\n return;\n }\n clearInterval(timer);\n timer = null;\n };\n\n signal?.addEventListener('abort', handleAbort, { once: true });\n\n timer = setInterval(callback, delayInMs);\n}\n"],"names":[],"mappings":";;AAMO,MAAM,QAAQ,CAAC,OAAe,GAAG,WACtC,IAAI,QAAc,CAAC,SAAS,WAAW;AACrC,MAAI,QAAQ;AACV,UAAM,gBAAgB,MAAM;AAC1B,mBAAa,OAAO;AACpB,aAAO,QAAQ,MAAM;AAAA,IACvB;AACA,UAAM,UAAU,WAAW,MAAM;AAC/B,aAAO,oBAAoB,SAAS,aAAa;AACjD,cAAA;AAAA,IACF,GAAG,IAAI;AACP,WAAO,iBAAiB,SAAS,eAAe,EAAE,MAAM,MAAM;AAAA,EAChE,OAAO;AACL,eAAW,SAAS,IAAI;AAAA,EAC1B;AACF,CAAC;AASI,MAAM,YAAY,OAAO,KAAK,QACnC,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAS3C,MAAM,aAAa,CACxB,cACA,gBACG;AACH,MAAI,eAAgB;AAEpB,QAAM,MAAM,MACV,sBAAsB,MAAM,WAAW,cAAc,WAAW,CAAC;AAEnE,MAAI,aAAa;AACf,mBAAe,GAAG;AAAA,EACpB,OAAO;AACL,QAAA;AAAA,EACF;AACF;AAEO,SAAS,oBACd,UACA,WACA,QACA;AACA,MAAI,gBAA+B;AAEnC,QAAM,cAAc,MAAM;AACxB,QAAI,iBAAiB,MAAM;AACzB;AAAA,IACF;AACA,iBAAa,aAAa;AAC1B,oBAAgB;AAAA,EAClB;AAEA,UAAQ,iBAAiB,SAAS,aAAa,EAAE,MAAM,MAAM;AAE7D,kBAAgB,WAAW,MAAM;AAC/B,YAAQ,oBAAoB,SAAS,WAAW;AAChD,aAAA;AAAA,EACF,GAAG,SAAS;AACd;AAEO,SAAS,qBACd,UACA,WACA,QACA;AACA,MAAI,QAAuB;AAE3B,QAAM,cAAc,MAAM;AACxB,QAAI,SAAS,MAAM;AACjB;AAAA,IACF;AACA,kBAAc,KAAK;AACnB,YAAQ;AAAA,EACV;AAEA,UAAQ,iBAAiB,SAAS,aAAa,EAAE,MAAM,MAAM;AAE7D,UAAQ,YAAY,UAAU,SAAS;AACzC;;;;;;"}
1
+ {"version":3,"file":"async.cjs","names":[],"sources":["../src/async.ts"],"sourcesContent":["/**\n * Returns a promise that resolves after `time` milliseconds.\n *\n * When `signal` is passed and becomes aborted before the delay elapses, the promise\n * rejects with `signal.reason` (same as native `fetch` / `AbortController` usage).\n * The timeout is cleared on abort so no resolve happens after cancellation.\n *\n * @param time - Delay in milliseconds. Defaults to `0` (next macrotask tick, same idea as `setTimeout(0)`).\n * @param signal - Optional `AbortSignal` to cancel the wait early.\n * @returns A promise that resolves with `void` when the delay completes, or rejects if aborted.\n *\n * @example\n * Basic pause in an async function:\n * ```ts\n * await sleep(250);\n * console.log('after 250ms');\n * ```\n *\n * @example\n * Cancellable delay tied to component unmount or user action:\n * ```ts\n * const ac = new AbortController();\n * try {\n * await sleep(5000, ac.signal);\n * } catch (e) {\n * // aborted — e is signal.reason\n * }\n * ac.abort('user cancelled');\n * ```\n */\nexport const sleep = (time: number = 0, signal?: AbortSignal) =>\n new Promise<void>((resolve, reject) => {\n if (signal) {\n const abortListener = () => {\n clearTimeout(timerId);\n reject(signal?.reason);\n };\n const timerId = setTimeout(() => {\n signal.removeEventListener('abort', abortListener);\n resolve();\n }, time);\n signal.addEventListener('abort', abortListener, { once: true });\n } else {\n setTimeout(resolve, time);\n }\n });\n\n/**\n * Creates a promise that resolves after the specified number of milliseconds.\n *\n * @deprecated Use `sleep` instead.\n * @param ms Delay in milliseconds.\n * @returns Promise\n */\nexport const waitAsync = async (ms = 1000) =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Runs a loop driven by `requestAnimationFrame`: on each frame, `quitFunction` is called first.\n * If it returns a truthy value, the loop stops and no further frames are scheduled.\n * If it returns falsy or nothing, the next frame is scheduled recursively.\n *\n * Use this for per-frame work (animations, layout reads after paint) without managing\n * `cancelAnimationFrame` manually — returning `true` from `quitFunction` is the exit condition.\n *\n * When `asMicrotask` is `true`, scheduling the next RAF is deferred with `queueMicrotask`\n * so other microtasks can run before the frame is requested (useful when you need to\n * batch DOM updates or let reactive frameworks flush first).\n *\n * @param quitFunction - Invoked each animation frame. Return `true` to stop the loop.\n * @param asMicrotask - If `true`, wrap the `requestAnimationFrame` call in `queueMicrotask`.\n *\n * @example\n * Stop after 60 frames (~1s at 60Hz):\n * ```ts\n * let frames = 0;\n * endlessRAF(() => {\n * frames++;\n * updateSomething(frames);\n * return frames >= 60;\n * });\n * ```\n *\n * @example\n * Run until an element is removed or a flag is set:\n * ```ts\n * let running = true;\n * endlessRAF(() => {\n * if (!running || !document.body.contains(el)) return true;\n * draw(el);\n * }, true);\n * ```\n */\nexport const endlessRAF = (\n quitFunction: () => boolean | void,\n asMicrotask?: boolean,\n) => {\n if (quitFunction()) return;\n\n const raf = () =>\n requestAnimationFrame(() => endlessRAF(quitFunction, asMicrotask));\n\n if (asMicrotask) {\n queueMicrotask(raf);\n } else {\n raf();\n }\n};\n\n/**\n * Like `setTimeout`, but if `signal` aborts before the delay fires, the timer is cleared\n * and `callback` is never run. If the callback runs normally, the abort listener is removed.\n *\n * Does nothing special if `signal` is omitted — behaves like a plain timeout.\n *\n * @param callback - Function to run once after `delayInMs` (same as `setTimeout` callback).\n * @param delayInMs - Milliseconds to wait. Passed through to `setTimeout` (browser/Node semantics apply).\n * @param signal - When aborted, clears the pending timeout so `callback` is not invoked.\n *\n * @example\n * ```ts\n * const controller = new AbortController();\n * setAbortableTimeout(() => console.log('done'), 500, controller.signal);\n * // later: controller.abort(); // timeout cancelled, log never runs\n * ```\n *\n * @example\n * Zero-delay scheduling that can still be cancelled before the macrotask runs:\n * ```ts\n * const ac = new AbortController();\n * setAbortableTimeout(() => startIntro(), 0, ac.signal);\n * // e.g. on teardown: ac.abort();\n * ```\n */\nexport function setAbortableTimeout(\n callback: VoidFunction,\n delayInMs?: number,\n signal?: AbortSignal,\n) {\n let internalTimer: number | null = null;\n\n const handleAbort = () => {\n if (internalTimer == null) {\n return;\n }\n clearTimeout(internalTimer);\n internalTimer = null;\n };\n\n signal?.addEventListener('abort', handleAbort, { once: true });\n\n internalTimer = setTimeout(() => {\n signal?.removeEventListener('abort', handleAbort);\n callback();\n }, delayInMs);\n}\n\n/**\n * Like `setInterval`, but when `signal` aborts, the interval is cleared with `clearInterval`\n * and `callback` stops being called. If `signal` is omitted, behaves like a normal interval\n * (you must clear it yourself).\n *\n * @param callback - Invoked every `delayInMs` milliseconds until aborted or cleared.\n * @param delayInMs - Interval period in milliseconds (same as `setInterval`).\n * @param signal - Aborting stops the interval and removes the abort listener path from keeping work alive.\n *\n * @example\n * ```ts\n * const controller = new AbortController();\n * setAbortableInterval(() => console.log('tick'), 1000, controller.signal);\n * // stop: controller.abort();\n * ```\n *\n * @example\n * ```ts\n * const ac = new AbortController();\n * setAbortableInterval(syncStatus, 30_000, ac.signal);\n * window.addEventListener('beforeunload', () => ac.abort());\n * ```\n */\nexport function setAbortableInterval(\n callback: VoidFunction,\n delayInMs?: number,\n signal?: AbortSignal,\n) {\n let timer: number | null = null;\n\n const handleAbort = () => {\n if (timer == null) {\n return;\n }\n clearInterval(timer);\n timer = null;\n };\n\n signal?.addEventListener('abort', handleAbort, { once: true });\n\n timer = setInterval(callback, delayInMs);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,IAAa,SAAS,OAAe,GAAG,WACtC,IAAI,SAAe,SAAS,WAAW;AACrC,KAAI,QAAQ;EACV,MAAM,sBAAsB;AAC1B,gBAAa,QAAQ;AACrB,UAAO,QAAQ,OAAO;;EAExB,MAAM,UAAU,iBAAiB;AAC/B,UAAO,oBAAoB,SAAS,cAAc;AAClD,YAAS;KACR,KAAK;AACR,SAAO,iBAAiB,SAAS,eAAe,EAAE,MAAM,MAAM,CAAC;OAE/D,YAAW,SAAS,KAAK;EAE3B;;;;;;;;AASJ,IAAa,YAAY,OAAO,KAAK,QACnC,IAAI,SAAS,YAAY,WAAW,SAAS,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCnD,IAAa,cACX,cACA,gBACG;AACH,KAAI,cAAc,CAAE;CAEpB,MAAM,YACJ,4BAA4B,WAAW,cAAc,YAAY,CAAC;AAEpE,KAAI,YACF,gBAAe,IAAI;KAEnB,MAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BT,SAAgB,oBACd,UACA,WACA,QACA;CACA,IAAI,gBAA+B;CAEnC,MAAM,oBAAoB;AACxB,MAAI,iBAAiB,KACnB;AAEF,eAAa,cAAc;AAC3B,kBAAgB;;AAGlB,SAAQ,iBAAiB,SAAS,aAAa,EAAE,MAAM,MAAM,CAAC;AAE9D,iBAAgB,iBAAiB;AAC/B,UAAQ,oBAAoB,SAAS,YAAY;AACjD,YAAU;IACT,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;AA0Bf,SAAgB,qBACd,UACA,WACA,QACA;CACA,IAAI,QAAuB;CAE3B,MAAM,oBAAoB;AACxB,MAAI,SAAS,KACX;AAEF,gBAAc,MAAM;AACpB,UAAQ;;AAGV,SAAQ,iBAAiB,SAAS,aAAa,EAAE,MAAM,MAAM,CAAC;AAE9D,SAAQ,YAAY,UAAU,UAAU"}
package/async.d.ts CHANGED
@@ -1,8 +1,32 @@
1
1
  /**
2
- * Creates a promise that resolves after the specified number of milliseconds.
2
+ * Returns a promise that resolves after `time` milliseconds.
3
3
  *
4
- * @param time Delay in milliseconds.
5
- * @returns Promise
4
+ * When `signal` is passed and becomes aborted before the delay elapses, the promise
5
+ * rejects with `signal.reason` (same as native `fetch` / `AbortController` usage).
6
+ * The timeout is cleared on abort so no resolve happens after cancellation.
7
+ *
8
+ * @param time - Delay in milliseconds. Defaults to `0` (next macrotask tick, same idea as `setTimeout(0)`).
9
+ * @param signal - Optional `AbortSignal` to cancel the wait early.
10
+ * @returns A promise that resolves with `void` when the delay completes, or rejects if aborted.
11
+ *
12
+ * @example
13
+ * Basic pause in an async function:
14
+ * ```ts
15
+ * await sleep(250);
16
+ * console.log('after 250ms');
17
+ * ```
18
+ *
19
+ * @example
20
+ * Cancellable delay tied to component unmount or user action:
21
+ * ```ts
22
+ * const ac = new AbortController();
23
+ * try {
24
+ * await sleep(5000, ac.signal);
25
+ * } catch (e) {
26
+ * // aborted — e is signal.reason
27
+ * }
28
+ * ac.abort('user cancelled');
29
+ * ```
6
30
  */
7
31
  declare const sleep: (time?: number, signal?: AbortSignal) => Promise<void>;
8
32
  /**
@@ -14,14 +38,91 @@ declare const sleep: (time?: number, signal?: AbortSignal) => Promise<void>;
14
38
  */
15
39
  declare const waitAsync: (ms?: number) => Promise<unknown>;
16
40
  /**
17
- * Repeatedly schedules `requestAnimationFrame` until `quitFunction` returns `true`.
41
+ * Runs a loop driven by `requestAnimationFrame`: on each frame, `quitFunction` is called first.
42
+ * If it returns a truthy value, the loop stops and no further frames are scheduled.
43
+ * If it returns falsy or nothing, the next frame is scheduled recursively.
18
44
  *
19
- * @param quitFunction Function executed on each animation frame.
20
- * @param asMicrotask Additionally wraps the RAF scheduling in `queueMicrotask`.
21
- * @returns void
45
+ * Use this for per-frame work (animations, layout reads after paint) without managing
46
+ * `cancelAnimationFrame` manually returning `true` from `quitFunction` is the exit condition.
47
+ *
48
+ * When `asMicrotask` is `true`, scheduling the next RAF is deferred with `queueMicrotask`
49
+ * so other microtasks can run before the frame is requested (useful when you need to
50
+ * batch DOM updates or let reactive frameworks flush first).
51
+ *
52
+ * @param quitFunction - Invoked each animation frame. Return `true` to stop the loop.
53
+ * @param asMicrotask - If `true`, wrap the `requestAnimationFrame` call in `queueMicrotask`.
54
+ *
55
+ * @example
56
+ * Stop after 60 frames (~1s at 60Hz):
57
+ * ```ts
58
+ * let frames = 0;
59
+ * endlessRAF(() => {
60
+ * frames++;
61
+ * updateSomething(frames);
62
+ * return frames >= 60;
63
+ * });
64
+ * ```
65
+ *
66
+ * @example
67
+ * Run until an element is removed or a flag is set:
68
+ * ```ts
69
+ * let running = true;
70
+ * endlessRAF(() => {
71
+ * if (!running || !document.body.contains(el)) return true;
72
+ * draw(el);
73
+ * }, true);
74
+ * ```
22
75
  */
23
76
  declare const endlessRAF: (quitFunction: () => boolean | void, asMicrotask?: boolean) => void;
77
+ /**
78
+ * Like `setTimeout`, but if `signal` aborts before the delay fires, the timer is cleared
79
+ * and `callback` is never run. If the callback runs normally, the abort listener is removed.
80
+ *
81
+ * Does nothing special if `signal` is omitted — behaves like a plain timeout.
82
+ *
83
+ * @param callback - Function to run once after `delayInMs` (same as `setTimeout` callback).
84
+ * @param delayInMs - Milliseconds to wait. Passed through to `setTimeout` (browser/Node semantics apply).
85
+ * @param signal - When aborted, clears the pending timeout so `callback` is not invoked.
86
+ *
87
+ * @example
88
+ * ```ts
89
+ * const controller = new AbortController();
90
+ * setAbortableTimeout(() => console.log('done'), 500, controller.signal);
91
+ * // later: controller.abort(); // timeout cancelled, log never runs
92
+ * ```
93
+ *
94
+ * @example
95
+ * Zero-delay scheduling that can still be cancelled before the macrotask runs:
96
+ * ```ts
97
+ * const ac = new AbortController();
98
+ * setAbortableTimeout(() => startIntro(), 0, ac.signal);
99
+ * // e.g. on teardown: ac.abort();
100
+ * ```
101
+ */
24
102
  declare function setAbortableTimeout(callback: VoidFunction, delayInMs?: number, signal?: AbortSignal): void;
103
+ /**
104
+ * Like `setInterval`, but when `signal` aborts, the interval is cleared with `clearInterval`
105
+ * and `callback` stops being called. If `signal` is omitted, behaves like a normal interval
106
+ * (you must clear it yourself).
107
+ *
108
+ * @param callback - Invoked every `delayInMs` milliseconds until aborted or cleared.
109
+ * @param delayInMs - Interval period in milliseconds (same as `setInterval`).
110
+ * @param signal - Aborting stops the interval and removes the abort listener path from keeping work alive.
111
+ *
112
+ * @example
113
+ * ```ts
114
+ * const controller = new AbortController();
115
+ * setAbortableInterval(() => console.log('tick'), 1000, controller.signal);
116
+ * // stop: controller.abort();
117
+ * ```
118
+ *
119
+ * @example
120
+ * ```ts
121
+ * const ac = new AbortController();
122
+ * setAbortableInterval(syncStatus, 30_000, ac.signal);
123
+ * window.addEventListener('beforeunload', () => ac.abort());
124
+ * ```
125
+ */
25
126
  declare function setAbortableInterval(callback: VoidFunction, delayInMs?: number, signal?: AbortSignal): void;
26
127
 
27
128
  export { endlessRAF, setAbortableInterval, setAbortableTimeout, sleep, waitAsync };
package/async.js CHANGED
@@ -1,60 +1,169 @@
1
- const sleep = (time = 0, signal) => new Promise((resolve, reject) => {
2
- if (signal) {
3
- const abortListener = () => {
4
- clearTimeout(timerId);
5
- reject(signal?.reason);
6
- };
7
- const timerId = setTimeout(() => {
8
- signal.removeEventListener("abort", abortListener);
9
- resolve();
10
- }, time);
11
- signal.addEventListener("abort", abortListener, { once: true });
12
- } else {
13
- setTimeout(resolve, time);
14
- }
1
+ //#region src/async.ts
2
+ /**
3
+ * Returns a promise that resolves after `time` milliseconds.
4
+ *
5
+ * When `signal` is passed and becomes aborted before the delay elapses, the promise
6
+ * rejects with `signal.reason` (same as native `fetch` / `AbortController` usage).
7
+ * The timeout is cleared on abort so no resolve happens after cancellation.
8
+ *
9
+ * @param time - Delay in milliseconds. Defaults to `0` (next macrotask tick, same idea as `setTimeout(0)`).
10
+ * @param signal - Optional `AbortSignal` to cancel the wait early.
11
+ * @returns A promise that resolves with `void` when the delay completes, or rejects if aborted.
12
+ *
13
+ * @example
14
+ * Basic pause in an async function:
15
+ * ```ts
16
+ * await sleep(250);
17
+ * console.log('after 250ms');
18
+ * ```
19
+ *
20
+ * @example
21
+ * Cancellable delay tied to component unmount or user action:
22
+ * ```ts
23
+ * const ac = new AbortController();
24
+ * try {
25
+ * await sleep(5000, ac.signal);
26
+ * } catch (e) {
27
+ * // aborted — e is signal.reason
28
+ * }
29
+ * ac.abort('user cancelled');
30
+ * ```
31
+ */
32
+ var sleep = (time = 0, signal) => new Promise((resolve, reject) => {
33
+ if (signal) {
34
+ const abortListener = () => {
35
+ clearTimeout(timerId);
36
+ reject(signal?.reason);
37
+ };
38
+ const timerId = setTimeout(() => {
39
+ signal.removeEventListener("abort", abortListener);
40
+ resolve();
41
+ }, time);
42
+ signal.addEventListener("abort", abortListener, { once: true });
43
+ } else setTimeout(resolve, time);
15
44
  });
16
- const waitAsync = async (ms = 1e3) => new Promise((resolve) => setTimeout(resolve, ms));
17
- const endlessRAF = (quitFunction, asMicrotask) => {
18
- if (quitFunction()) return;
19
- const raf = () => requestAnimationFrame(() => endlessRAF(quitFunction, asMicrotask));
20
- if (asMicrotask) {
21
- queueMicrotask(raf);
22
- } else {
23
- raf();
24
- }
45
+ /**
46
+ * Creates a promise that resolves after the specified number of milliseconds.
47
+ *
48
+ * @deprecated Use `sleep` instead.
49
+ * @param ms Delay in milliseconds.
50
+ * @returns Promise
51
+ */
52
+ var waitAsync = async (ms = 1e3) => new Promise((resolve) => setTimeout(resolve, ms));
53
+ /**
54
+ * Runs a loop driven by `requestAnimationFrame`: on each frame, `quitFunction` is called first.
55
+ * If it returns a truthy value, the loop stops and no further frames are scheduled.
56
+ * If it returns falsy or nothing, the next frame is scheduled recursively.
57
+ *
58
+ * Use this for per-frame work (animations, layout reads after paint) without managing
59
+ * `cancelAnimationFrame` manually — returning `true` from `quitFunction` is the exit condition.
60
+ *
61
+ * When `asMicrotask` is `true`, scheduling the next RAF is deferred with `queueMicrotask`
62
+ * so other microtasks can run before the frame is requested (useful when you need to
63
+ * batch DOM updates or let reactive frameworks flush first).
64
+ *
65
+ * @param quitFunction - Invoked each animation frame. Return `true` to stop the loop.
66
+ * @param asMicrotask - If `true`, wrap the `requestAnimationFrame` call in `queueMicrotask`.
67
+ *
68
+ * @example
69
+ * Stop after 60 frames (~1s at 60Hz):
70
+ * ```ts
71
+ * let frames = 0;
72
+ * endlessRAF(() => {
73
+ * frames++;
74
+ * updateSomething(frames);
75
+ * return frames >= 60;
76
+ * });
77
+ * ```
78
+ *
79
+ * @example
80
+ * Run until an element is removed or a flag is set:
81
+ * ```ts
82
+ * let running = true;
83
+ * endlessRAF(() => {
84
+ * if (!running || !document.body.contains(el)) return true;
85
+ * draw(el);
86
+ * }, true);
87
+ * ```
88
+ */
89
+ var endlessRAF = (quitFunction, asMicrotask) => {
90
+ if (quitFunction()) return;
91
+ const raf = () => requestAnimationFrame(() => endlessRAF(quitFunction, asMicrotask));
92
+ if (asMicrotask) queueMicrotask(raf);
93
+ else raf();
25
94
  };
95
+ /**
96
+ * Like `setTimeout`, but if `signal` aborts before the delay fires, the timer is cleared
97
+ * and `callback` is never run. If the callback runs normally, the abort listener is removed.
98
+ *
99
+ * Does nothing special if `signal` is omitted — behaves like a plain timeout.
100
+ *
101
+ * @param callback - Function to run once after `delayInMs` (same as `setTimeout` callback).
102
+ * @param delayInMs - Milliseconds to wait. Passed through to `setTimeout` (browser/Node semantics apply).
103
+ * @param signal - When aborted, clears the pending timeout so `callback` is not invoked.
104
+ *
105
+ * @example
106
+ * ```ts
107
+ * const controller = new AbortController();
108
+ * setAbortableTimeout(() => console.log('done'), 500, controller.signal);
109
+ * // later: controller.abort(); // timeout cancelled, log never runs
110
+ * ```
111
+ *
112
+ * @example
113
+ * Zero-delay scheduling that can still be cancelled before the macrotask runs:
114
+ * ```ts
115
+ * const ac = new AbortController();
116
+ * setAbortableTimeout(() => startIntro(), 0, ac.signal);
117
+ * // e.g. on teardown: ac.abort();
118
+ * ```
119
+ */
26
120
  function setAbortableTimeout(callback, delayInMs, signal) {
27
- let internalTimer = null;
28
- const handleAbort = () => {
29
- if (internalTimer == null) {
30
- return;
31
- }
32
- clearTimeout(internalTimer);
33
- internalTimer = null;
34
- };
35
- signal?.addEventListener("abort", handleAbort, { once: true });
36
- internalTimer = setTimeout(() => {
37
- signal?.removeEventListener("abort", handleAbort);
38
- callback();
39
- }, delayInMs);
121
+ let internalTimer = null;
122
+ const handleAbort = () => {
123
+ if (internalTimer == null) return;
124
+ clearTimeout(internalTimer);
125
+ internalTimer = null;
126
+ };
127
+ signal?.addEventListener("abort", handleAbort, { once: true });
128
+ internalTimer = setTimeout(() => {
129
+ signal?.removeEventListener("abort", handleAbort);
130
+ callback();
131
+ }, delayInMs);
40
132
  }
133
+ /**
134
+ * Like `setInterval`, but when `signal` aborts, the interval is cleared with `clearInterval`
135
+ * and `callback` stops being called. If `signal` is omitted, behaves like a normal interval
136
+ * (you must clear it yourself).
137
+ *
138
+ * @param callback - Invoked every `delayInMs` milliseconds until aborted or cleared.
139
+ * @param delayInMs - Interval period in milliseconds (same as `setInterval`).
140
+ * @param signal - Aborting stops the interval and removes the abort listener path from keeping work alive.
141
+ *
142
+ * @example
143
+ * ```ts
144
+ * const controller = new AbortController();
145
+ * setAbortableInterval(() => console.log('tick'), 1000, controller.signal);
146
+ * // stop: controller.abort();
147
+ * ```
148
+ *
149
+ * @example
150
+ * ```ts
151
+ * const ac = new AbortController();
152
+ * setAbortableInterval(syncStatus, 30_000, ac.signal);
153
+ * window.addEventListener('beforeunload', () => ac.abort());
154
+ * ```
155
+ */
41
156
  function setAbortableInterval(callback, delayInMs, signal) {
42
- let timer = null;
43
- const handleAbort = () => {
44
- if (timer == null) {
45
- return;
46
- }
47
- clearInterval(timer);
48
- timer = null;
49
- };
50
- signal?.addEventListener("abort", handleAbort, { once: true });
51
- timer = setInterval(callback, delayInMs);
157
+ let timer = null;
158
+ const handleAbort = () => {
159
+ if (timer == null) return;
160
+ clearInterval(timer);
161
+ timer = null;
162
+ };
163
+ signal?.addEventListener("abort", handleAbort, { once: true });
164
+ timer = setInterval(callback, delayInMs);
52
165
  }
53
- export {
54
- endlessRAF,
55
- setAbortableInterval,
56
- setAbortableTimeout,
57
- sleep,
58
- waitAsync
59
- };
60
- //# sourceMappingURL=async.js.map
166
+ //#endregion
167
+ export { endlessRAF, setAbortableInterval, setAbortableTimeout, sleep, waitAsync };
168
+
169
+ //# sourceMappingURL=async.js.map
package/async.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"async.js","sources":["../src/async.ts"],"sourcesContent":["/**\n * Creates a promise that resolves after the specified number of milliseconds.\n *\n * @param time Delay in milliseconds.\n * @returns Promise\n */\nexport const sleep = (time: number = 0, signal?: AbortSignal) =>\n new Promise<void>((resolve, reject) => {\n if (signal) {\n const abortListener = () => {\n clearTimeout(timerId);\n reject(signal?.reason);\n };\n const timerId = setTimeout(() => {\n signal.removeEventListener('abort', abortListener);\n resolve();\n }, time);\n signal.addEventListener('abort', abortListener, { once: true });\n } else {\n setTimeout(resolve, time);\n }\n });\n\n/**\n * Creates a promise that resolves after the specified number of milliseconds.\n *\n * @deprecated Use `sleep` instead.\n * @param ms Delay in milliseconds.\n * @returns Promise\n */\nexport const waitAsync = async (ms = 1000) =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Repeatedly schedules `requestAnimationFrame` until `quitFunction` returns `true`.\n *\n * @param quitFunction Function executed on each animation frame.\n * @param asMicrotask Additionally wraps the RAF scheduling in `queueMicrotask`.\n * @returns void\n */\nexport const endlessRAF = (\n quitFunction: () => boolean | void,\n asMicrotask?: boolean,\n) => {\n if (quitFunction()) return;\n\n const raf = () =>\n requestAnimationFrame(() => endlessRAF(quitFunction, asMicrotask));\n\n if (asMicrotask) {\n queueMicrotask(raf);\n } else {\n raf();\n }\n};\n\nexport function setAbortableTimeout(\n callback: VoidFunction,\n delayInMs?: number,\n signal?: AbortSignal,\n) {\n let internalTimer: number | null = null;\n\n const handleAbort = () => {\n if (internalTimer == null) {\n return;\n }\n clearTimeout(internalTimer);\n internalTimer = null;\n };\n\n signal?.addEventListener('abort', handleAbort, { once: true });\n\n internalTimer = setTimeout(() => {\n signal?.removeEventListener('abort', handleAbort);\n callback();\n }, delayInMs);\n}\n\nexport function setAbortableInterval(\n callback: VoidFunction,\n delayInMs?: number,\n signal?: AbortSignal,\n) {\n let timer: number | null = null;\n\n const handleAbort = () => {\n if (timer == null) {\n return;\n }\n clearInterval(timer);\n timer = null;\n };\n\n signal?.addEventListener('abort', handleAbort, { once: true });\n\n timer = setInterval(callback, delayInMs);\n}\n"],"names":[],"mappings":"AAMO,MAAM,QAAQ,CAAC,OAAe,GAAG,WACtC,IAAI,QAAc,CAAC,SAAS,WAAW;AACrC,MAAI,QAAQ;AACV,UAAM,gBAAgB,MAAM;AAC1B,mBAAa,OAAO;AACpB,aAAO,QAAQ,MAAM;AAAA,IACvB;AACA,UAAM,UAAU,WAAW,MAAM;AAC/B,aAAO,oBAAoB,SAAS,aAAa;AACjD,cAAA;AAAA,IACF,GAAG,IAAI;AACP,WAAO,iBAAiB,SAAS,eAAe,EAAE,MAAM,MAAM;AAAA,EAChE,OAAO;AACL,eAAW,SAAS,IAAI;AAAA,EAC1B;AACF,CAAC;AASI,MAAM,YAAY,OAAO,KAAK,QACnC,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAS3C,MAAM,aAAa,CACxB,cACA,gBACG;AACH,MAAI,eAAgB;AAEpB,QAAM,MAAM,MACV,sBAAsB,MAAM,WAAW,cAAc,WAAW,CAAC;AAEnE,MAAI,aAAa;AACf,mBAAe,GAAG;AAAA,EACpB,OAAO;AACL,QAAA;AAAA,EACF;AACF;AAEO,SAAS,oBACd,UACA,WACA,QACA;AACA,MAAI,gBAA+B;AAEnC,QAAM,cAAc,MAAM;AACxB,QAAI,iBAAiB,MAAM;AACzB;AAAA,IACF;AACA,iBAAa,aAAa;AAC1B,oBAAgB;AAAA,EAClB;AAEA,UAAQ,iBAAiB,SAAS,aAAa,EAAE,MAAM,MAAM;AAE7D,kBAAgB,WAAW,MAAM;AAC/B,YAAQ,oBAAoB,SAAS,WAAW;AAChD,aAAA;AAAA,EACF,GAAG,SAAS;AACd;AAEO,SAAS,qBACd,UACA,WACA,QACA;AACA,MAAI,QAAuB;AAE3B,QAAM,cAAc,MAAM;AACxB,QAAI,SAAS,MAAM;AACjB;AAAA,IACF;AACA,kBAAc,KAAK;AACnB,YAAQ;AAAA,EACV;AAEA,UAAQ,iBAAiB,SAAS,aAAa,EAAE,MAAM,MAAM;AAE7D,UAAQ,YAAY,UAAU,SAAS;AACzC;"}
1
+ {"version":3,"file":"async.js","names":[],"sources":["../src/async.ts"],"sourcesContent":["/**\n * Returns a promise that resolves after `time` milliseconds.\n *\n * When `signal` is passed and becomes aborted before the delay elapses, the promise\n * rejects with `signal.reason` (same as native `fetch` / `AbortController` usage).\n * The timeout is cleared on abort so no resolve happens after cancellation.\n *\n * @param time - Delay in milliseconds. Defaults to `0` (next macrotask tick, same idea as `setTimeout(0)`).\n * @param signal - Optional `AbortSignal` to cancel the wait early.\n * @returns A promise that resolves with `void` when the delay completes, or rejects if aborted.\n *\n * @example\n * Basic pause in an async function:\n * ```ts\n * await sleep(250);\n * console.log('after 250ms');\n * ```\n *\n * @example\n * Cancellable delay tied to component unmount or user action:\n * ```ts\n * const ac = new AbortController();\n * try {\n * await sleep(5000, ac.signal);\n * } catch (e) {\n * // aborted — e is signal.reason\n * }\n * ac.abort('user cancelled');\n * ```\n */\nexport const sleep = (time: number = 0, signal?: AbortSignal) =>\n new Promise<void>((resolve, reject) => {\n if (signal) {\n const abortListener = () => {\n clearTimeout(timerId);\n reject(signal?.reason);\n };\n const timerId = setTimeout(() => {\n signal.removeEventListener('abort', abortListener);\n resolve();\n }, time);\n signal.addEventListener('abort', abortListener, { once: true });\n } else {\n setTimeout(resolve, time);\n }\n });\n\n/**\n * Creates a promise that resolves after the specified number of milliseconds.\n *\n * @deprecated Use `sleep` instead.\n * @param ms Delay in milliseconds.\n * @returns Promise\n */\nexport const waitAsync = async (ms = 1000) =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Runs a loop driven by `requestAnimationFrame`: on each frame, `quitFunction` is called first.\n * If it returns a truthy value, the loop stops and no further frames are scheduled.\n * If it returns falsy or nothing, the next frame is scheduled recursively.\n *\n * Use this for per-frame work (animations, layout reads after paint) without managing\n * `cancelAnimationFrame` manually — returning `true` from `quitFunction` is the exit condition.\n *\n * When `asMicrotask` is `true`, scheduling the next RAF is deferred with `queueMicrotask`\n * so other microtasks can run before the frame is requested (useful when you need to\n * batch DOM updates or let reactive frameworks flush first).\n *\n * @param quitFunction - Invoked each animation frame. Return `true` to stop the loop.\n * @param asMicrotask - If `true`, wrap the `requestAnimationFrame` call in `queueMicrotask`.\n *\n * @example\n * Stop after 60 frames (~1s at 60Hz):\n * ```ts\n * let frames = 0;\n * endlessRAF(() => {\n * frames++;\n * updateSomething(frames);\n * return frames >= 60;\n * });\n * ```\n *\n * @example\n * Run until an element is removed or a flag is set:\n * ```ts\n * let running = true;\n * endlessRAF(() => {\n * if (!running || !document.body.contains(el)) return true;\n * draw(el);\n * }, true);\n * ```\n */\nexport const endlessRAF = (\n quitFunction: () => boolean | void,\n asMicrotask?: boolean,\n) => {\n if (quitFunction()) return;\n\n const raf = () =>\n requestAnimationFrame(() => endlessRAF(quitFunction, asMicrotask));\n\n if (asMicrotask) {\n queueMicrotask(raf);\n } else {\n raf();\n }\n};\n\n/**\n * Like `setTimeout`, but if `signal` aborts before the delay fires, the timer is cleared\n * and `callback` is never run. If the callback runs normally, the abort listener is removed.\n *\n * Does nothing special if `signal` is omitted — behaves like a plain timeout.\n *\n * @param callback - Function to run once after `delayInMs` (same as `setTimeout` callback).\n * @param delayInMs - Milliseconds to wait. Passed through to `setTimeout` (browser/Node semantics apply).\n * @param signal - When aborted, clears the pending timeout so `callback` is not invoked.\n *\n * @example\n * ```ts\n * const controller = new AbortController();\n * setAbortableTimeout(() => console.log('done'), 500, controller.signal);\n * // later: controller.abort(); // timeout cancelled, log never runs\n * ```\n *\n * @example\n * Zero-delay scheduling that can still be cancelled before the macrotask runs:\n * ```ts\n * const ac = new AbortController();\n * setAbortableTimeout(() => startIntro(), 0, ac.signal);\n * // e.g. on teardown: ac.abort();\n * ```\n */\nexport function setAbortableTimeout(\n callback: VoidFunction,\n delayInMs?: number,\n signal?: AbortSignal,\n) {\n let internalTimer: number | null = null;\n\n const handleAbort = () => {\n if (internalTimer == null) {\n return;\n }\n clearTimeout(internalTimer);\n internalTimer = null;\n };\n\n signal?.addEventListener('abort', handleAbort, { once: true });\n\n internalTimer = setTimeout(() => {\n signal?.removeEventListener('abort', handleAbort);\n callback();\n }, delayInMs);\n}\n\n/**\n * Like `setInterval`, but when `signal` aborts, the interval is cleared with `clearInterval`\n * and `callback` stops being called. If `signal` is omitted, behaves like a normal interval\n * (you must clear it yourself).\n *\n * @param callback - Invoked every `delayInMs` milliseconds until aborted or cleared.\n * @param delayInMs - Interval period in milliseconds (same as `setInterval`).\n * @param signal - Aborting stops the interval and removes the abort listener path from keeping work alive.\n *\n * @example\n * ```ts\n * const controller = new AbortController();\n * setAbortableInterval(() => console.log('tick'), 1000, controller.signal);\n * // stop: controller.abort();\n * ```\n *\n * @example\n * ```ts\n * const ac = new AbortController();\n * setAbortableInterval(syncStatus, 30_000, ac.signal);\n * window.addEventListener('beforeunload', () => ac.abort());\n * ```\n */\nexport function setAbortableInterval(\n callback: VoidFunction,\n delayInMs?: number,\n signal?: AbortSignal,\n) {\n let timer: number | null = null;\n\n const handleAbort = () => {\n if (timer == null) {\n return;\n }\n clearInterval(timer);\n timer = null;\n };\n\n signal?.addEventListener('abort', handleAbort, { once: true });\n\n timer = setInterval(callback, delayInMs);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,IAAa,SAAS,OAAe,GAAG,WACtC,IAAI,SAAe,SAAS,WAAW;AACrC,KAAI,QAAQ;EACV,MAAM,sBAAsB;AAC1B,gBAAa,QAAQ;AACrB,UAAO,QAAQ,OAAO;;EAExB,MAAM,UAAU,iBAAiB;AAC/B,UAAO,oBAAoB,SAAS,cAAc;AAClD,YAAS;KACR,KAAK;AACR,SAAO,iBAAiB,SAAS,eAAe,EAAE,MAAM,MAAM,CAAC;OAE/D,YAAW,SAAS,KAAK;EAE3B;;;;;;;;AASJ,IAAa,YAAY,OAAO,KAAK,QACnC,IAAI,SAAS,YAAY,WAAW,SAAS,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCnD,IAAa,cACX,cACA,gBACG;AACH,KAAI,cAAc,CAAE;CAEpB,MAAM,YACJ,4BAA4B,WAAW,cAAc,YAAY,CAAC;AAEpE,KAAI,YACF,gBAAe,IAAI;KAEnB,MAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BT,SAAgB,oBACd,UACA,WACA,QACA;CACA,IAAI,gBAA+B;CAEnC,MAAM,oBAAoB;AACxB,MAAI,iBAAiB,KACnB;AAEF,eAAa,cAAc;AAC3B,kBAAgB;;AAGlB,SAAQ,iBAAiB,SAAS,aAAa,EAAE,MAAM,MAAM,CAAC;AAE9D,iBAAgB,iBAAiB;AAC/B,UAAQ,oBAAoB,SAAS,YAAY;AACjD,YAAU;IACT,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;AA0Bf,SAAgB,qBACd,UACA,WACA,QACA;CACA,IAAI,QAAuB;CAE3B,MAAM,oBAAoB;AACxB,MAAI,SAAS,KACX;AAEF,gBAAc,MAAM;AACpB,UAAQ;;AAGV,SAAQ,iBAAiB,SAAS,aAAa,EAAE,MAAM,MAAM,CAAC;AAE9D,SAAQ,YAAY,UAAU,UAAU"}