@mkmonkeycat/dom-utils 0.1.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.
@@ -0,0 +1,283 @@
1
+ const h = (...t) => t.flatMap((r) => typeof r == "string" ? r.trim().split(/\s+/).filter(Boolean) : r || []), A = (t, r, ...n) => {
2
+ const o = document.createElement(t);
3
+ return r ? (Object.entries(r).forEach(([s, e]) => {
4
+ if (e != null) {
5
+ if (s === "className" || s === "class") {
6
+ const i = Array.isArray(e) ? h(...e) : h(e);
7
+ o.className = i.join(" ");
8
+ return;
9
+ }
10
+ if (s === "style") {
11
+ typeof e == "string" ? o.style.cssText = e : typeof e == "object" && Object.assign(o.style, e);
12
+ return;
13
+ }
14
+ if (s === "dataset" && typeof e == "object") {
15
+ Object.assign(o.dataset, e);
16
+ return;
17
+ }
18
+ if (s.startsWith("on")) {
19
+ const i = s.slice(2).toLowerCase();
20
+ typeof e == "function" ? o.addEventListener(i, e) : Array.isArray(e) && e.forEach((c) => {
21
+ typeof c == "function" && o.addEventListener(i, c);
22
+ });
23
+ return;
24
+ }
25
+ s in o ? o[s] = e : o.setAttribute(s, String(e));
26
+ }
27
+ }), E(o, n), o) : (E(o, n), o);
28
+ }, S = (...t) => {
29
+ const r = document.createDocumentFragment();
30
+ return t.forEach((n) => {
31
+ typeof n == "string" ? r.appendChild(document.createTextNode(n)) : r.appendChild(n);
32
+ }), r;
33
+ }, E = (t, r) => {
34
+ r.forEach((n) => {
35
+ typeof n == "string" ? t.appendChild(document.createTextNode(n)) : t.appendChild(n);
36
+ });
37
+ }, P = (t) => ({
38
+ width: t.offsetWidth,
39
+ height: t.offsetHeight
40
+ }), O = (t) => ({
41
+ top: t.offsetTop,
42
+ left: t.offsetLeft
43
+ }), F = (t, r) => window.getComputedStyle(t).getPropertyValue(r).trim(), I = (t, r) => {
44
+ t && (t === document.documentElement || t === document.body ? window.scrollTo(r) : t.scrollTo?.(r));
45
+ }, M = (t, r) => {
46
+ t.scrollIntoView?.(r);
47
+ }, D = (t) => ({
48
+ width: t.clientWidth,
49
+ height: t.clientHeight
50
+ }), x = (t, r = !1) => {
51
+ let n = t.offsetWidth, o = t.offsetHeight;
52
+ if (r) {
53
+ const s = window.getComputedStyle(t), e = parseFloat(s.marginLeft || "0"), i = parseFloat(s.marginRight || "0"), c = parseFloat(s.marginTop || "0"), u = parseFloat(s.marginBottom || "0");
54
+ n += e + i, o += c + u;
55
+ }
56
+ return { width: n, height: o };
57
+ }, j = (t) => t.getBoundingClientRect(), V = (t) => {
58
+ const n = new DOMParser().parseFromString(t, "image/svg+xml");
59
+ if (n.documentElement.nodeName === "parsererror")
60
+ throw new Error("Invalid SVG string: Failed to parse SVG");
61
+ return n.documentElement;
62
+ }, T = (t, r) => (Object.defineProperty(t, r, { value: !0 }), t), W = (t, r) => !!t[r], p = (t) => T(t, "__mkEvent"), R = (t, r, n = {}) => {
63
+ const { event: o = "mousedown", capture: s = !0, exclude: e = [] } = n, i = p((c) => {
64
+ const u = c.target;
65
+ t.contains(u) || e.some((a) => a?.contains(u)) || r(c);
66
+ });
67
+ return document.addEventListener(o, i, s), () => document.removeEventListener(o, i, s);
68
+ }, g = (t, r, n = {}) => {
69
+ const {
70
+ preventDefault: o = !1,
71
+ stopPropagation: s = !1,
72
+ event: e = "keydown",
73
+ target: i = document
74
+ } = n, c = Array.isArray(t) ? t : [t], u = p((a) => {
75
+ c.includes(a.key) && (o && a.preventDefault(), s && a.stopPropagation(), r(a));
76
+ });
77
+ return i.addEventListener(e, u), () => i.removeEventListener(e, u);
78
+ }, $ = (t, r = {}) => g("Escape", t, r), N = (t, r = {}) => g("Enter", t, r), z = (t, r, n = {}) => {
79
+ const { duration: o = 500, threshold: s = 10 } = n;
80
+ let e = null, i = 0, c = 0;
81
+ const u = (d) => "touches" in d ? d.touches[0] : d, a = p((d) => {
82
+ const m = u(d);
83
+ i = m.clientX, c = m.clientY, e = setTimeout(() => {
84
+ r(d);
85
+ }, o);
86
+ }), w = p((d) => {
87
+ if (!e) return;
88
+ const m = u(d), v = Math.abs(m.clientX - i), b = Math.abs(m.clientY - c);
89
+ (v > s || b > s) && l();
90
+ }), l = p(() => {
91
+ e && (clearTimeout(e), e = null);
92
+ }), f = L(t, {
93
+ mousedown: a,
94
+ mousemove: w,
95
+ mouseup: l,
96
+ mouseleave: l,
97
+ touchstart: a,
98
+ touchmove: w,
99
+ touchend: l,
100
+ touchcancel: l
101
+ });
102
+ return () => {
103
+ f(), e && clearTimeout(e);
104
+ };
105
+ }, L = (t, r, n) => {
106
+ const o = [];
107
+ return Object.entries(r).forEach(([s, e]) => {
108
+ if (!e) return;
109
+ const i = s;
110
+ Array.isArray(e) ? e.forEach((c) => {
111
+ t.addEventListener(i, c, n), o.push([i, c]);
112
+ }) : (t.addEventListener(i, e, n), o.push([i, e]));
113
+ }), () => {
114
+ o.forEach(([s, e]) => {
115
+ t.removeEventListener(s, e, n);
116
+ });
117
+ };
118
+ }, K = (t, r = {}) => {
119
+ const { timeout: n = 5e3, root: o = document.body, interval: s = 100 } = r;
120
+ return new Promise((e, i) => {
121
+ const c = o.querySelector(t);
122
+ if (c) {
123
+ e(c);
124
+ return;
125
+ }
126
+ const u = new MutationObserver(() => {
127
+ const f = o.querySelector(t);
128
+ f && (l(), e(f));
129
+ });
130
+ u.observe(o, {
131
+ childList: !0,
132
+ subtree: !0
133
+ });
134
+ const a = setInterval(() => {
135
+ const f = o.querySelector(t);
136
+ f && (l(), e(f));
137
+ }, s), w = setTimeout(() => {
138
+ l(), i(new Error(`Timeout: Element "${t}" not found within ${n}ms`));
139
+ }, n), l = () => {
140
+ u.disconnect(), clearTimeout(w), clearInterval(a);
141
+ };
142
+ });
143
+ }, X = (t, r = {}) => {
144
+ const { onRemove: n, root: o = document.body } = r, s = new MutationObserver(() => {
145
+ o.contains(t) || (n?.(), s.disconnect());
146
+ });
147
+ return s.observe(o, {
148
+ childList: !0,
149
+ subtree: !0
150
+ }), () => s.disconnect();
151
+ }, Y = (t, r = {}) => {
152
+ const { root: n = document.body, timeout: o } = r;
153
+ return new Promise((s, e) => {
154
+ if (!n.contains(t)) {
155
+ s();
156
+ return;
157
+ }
158
+ let i;
159
+ const c = new MutationObserver(() => {
160
+ n.contains(t) || (u(), s());
161
+ });
162
+ c.observe(n, {
163
+ childList: !0,
164
+ subtree: !0
165
+ }), o && (i = setTimeout(() => {
166
+ u(), e(new Error(`Timeout: Element not removed within ${o}ms`));
167
+ }, o));
168
+ const u = () => {
169
+ c.disconnect(), i && clearTimeout(i);
170
+ };
171
+ });
172
+ }, Z = (t, r = {}) => {
173
+ const {
174
+ attributes: n = !0,
175
+ childList: o = !0,
176
+ characterData: s = !1,
177
+ subtree: e = !1,
178
+ onMutation: i
179
+ } = r, c = new MutationObserver((u) => i?.(u));
180
+ return c.observe(t, {
181
+ attributes: n,
182
+ childList: o,
183
+ characterData: s,
184
+ subtree: e
185
+ }), () => c.disconnect();
186
+ }, q = (t, r = {}) => {
187
+ const { id: n, nonce: o, target: s = document.head } = r, e = document.createElement("style");
188
+ return n && (e.id = n), o && e.setAttribute("nonce", o), e.textContent = t, s.appendChild(e), { style: e, remove: () => {
189
+ e.parentNode?.removeChild(e);
190
+ } };
191
+ }, y = typeof unsafeWindow < "u" ? unsafeWindow : window, B = y.document;
192
+ function G(t) {
193
+ return t ? t instanceof Window ? t : t instanceof UIEvent && t.view ? t.view : t instanceof Document ? t.defaultView : t instanceof ShadowRoot ? t.host.ownerDocument?.defaultView ?? null : t instanceof Node ? t.ownerDocument?.defaultView ?? null : null : y;
194
+ }
195
+ const H = (t) => t.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2").toLowerCase(), _ = (t) => t.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2").toLowerCase(), U = (t, r) => {
196
+ let n = null, o = null;
197
+ const s = (...e) => {
198
+ o = e, n && clearTimeout(n), n = setTimeout(() => {
199
+ t(...o), n = null, o = null;
200
+ }, r);
201
+ };
202
+ return s.cancel = () => {
203
+ n && clearTimeout(n), n = null, o = null;
204
+ }, s.flush = () => {
205
+ n && (t(...o), clearTimeout(n), n = null, o = null);
206
+ }, s;
207
+ }, J = (t, r) => {
208
+ let n = null, o = null, s = 0;
209
+ const e = () => {
210
+ n && (clearTimeout(n), n = null);
211
+ }, i = (...c) => {
212
+ const u = Date.now();
213
+ if (o = c, s === 0)
214
+ t(...c), s = u;
215
+ else {
216
+ const a = u - s;
217
+ a >= r ? (t(...c), s = u, e()) : (e(), n = setTimeout(() => {
218
+ t(...o), s = Date.now(), n = null;
219
+ }, r - a));
220
+ }
221
+ };
222
+ return i.cancel = () => {
223
+ e(), s = 0, o = null;
224
+ }, i.flush = () => {
225
+ s > 0 && o !== null && t(...o), e(), s = 0, o = null;
226
+ }, i;
227
+ }, C = (t) => new Promise((r) => setTimeout(r, t)), Q = (t) => C(t), k = (t, r, n = `Operation timed out after ${r}ms`) => Promise.race([
228
+ t,
229
+ new Promise((o, s) => setTimeout(() => s(new Error(n)), r))
230
+ ]), tt = () => {
231
+ }, et = async (t, r = {}) => {
232
+ const { maxAttempts: n = 3, delay: o = 1e3, exponential: s = !1 } = r;
233
+ let e;
234
+ for (let i = 1; i <= n; i++)
235
+ try {
236
+ return await t();
237
+ } catch (c) {
238
+ if (e = c instanceof Error ? c : new Error(String(c)), i < n) {
239
+ const u = s ? o * Math.pow(2, i - 1) : o;
240
+ await new Promise((a) => setTimeout(a, u));
241
+ }
242
+ }
243
+ throw e || new Error("Retry failed");
244
+ };
245
+ export {
246
+ L as addEventsListener,
247
+ H as camelToKebab,
248
+ A as createElement,
249
+ S as createFragment,
250
+ V as createSVGFromString,
251
+ U as debounce,
252
+ C as delay,
253
+ F as getComputedStyle,
254
+ D as getInnerSize,
255
+ O as getOffset,
256
+ x as getOuterSize,
257
+ j as getRect,
258
+ P as getSize,
259
+ G as getWin,
260
+ B as globalDoc,
261
+ y as globalWin,
262
+ q as injectStyle,
263
+ W as isMarkedAs,
264
+ T as markFunc,
265
+ tt as noop,
266
+ R as onClickOutside,
267
+ N as onEnter,
268
+ $ as onEscape,
269
+ g as onKeyPress,
270
+ z as onLongPress,
271
+ h as parseClass,
272
+ _ as pascalToKebab,
273
+ et as retry,
274
+ M as scrollIntoView,
275
+ I as scrollTo,
276
+ Q as sleep,
277
+ J as throttle,
278
+ k as timeout,
279
+ K as waitForElement,
280
+ Y as waitForElementRemoval,
281
+ Z as watchElementChanges,
282
+ X as watchElementRemoval
283
+ };
@@ -0,0 +1 @@
1
+ (function(i,m){typeof exports=="object"&&typeof module<"u"?m(exports):typeof define=="function"&&define.amd?define(["exports"],m):(i=typeof globalThis<"u"?globalThis:i||self,m(i.MKDomUtils={}))})(this,(function(i){"use strict";const m=(...e)=>e.flatMap(r=>typeof r=="string"?r.trim().split(/\s+/).filter(Boolean):r||[]),C=(e,r,...n)=>{const o=document.createElement(e);return r?(Object.entries(r).forEach(([s,t])=>{if(t!=null){if(s==="className"||s==="class"){const c=Array.isArray(t)?m(...t):m(t);o.className=c.join(" ");return}if(s==="style"){typeof t=="string"?o.style.cssText=t:typeof t=="object"&&Object.assign(o.style,t);return}if(s==="dataset"&&typeof t=="object"){Object.assign(o.dataset,t);return}if(s.startsWith("on")){const c=s.slice(2).toLowerCase();typeof t=="function"?o.addEventListener(c,t):Array.isArray(t)&&t.forEach(a=>{typeof a=="function"&&o.addEventListener(c,a)});return}s in o?o[s]=t:o.setAttribute(s,String(t))}}),p(o,n),o):(p(o,n),o)},L=(...e)=>{const r=document.createDocumentFragment();return e.forEach(n=>{typeof n=="string"?r.appendChild(document.createTextNode(n)):r.appendChild(n)}),r},p=(e,r)=>{r.forEach(n=>{typeof n=="string"?e.appendChild(document.createTextNode(n)):e.appendChild(n)})},A=e=>({width:e.offsetWidth,height:e.offsetHeight}),F=e=>({top:e.offsetTop,left:e.offsetLeft}),O=(e,r)=>window.getComputedStyle(e).getPropertyValue(r).trim(),P=(e,r)=>{e&&(e===document.documentElement||e===document.body?window.scrollTo(r):e.scrollTo?.(r))},I=(e,r)=>{e.scrollIntoView?.(r)},M=e=>({width:e.clientWidth,height:e.clientHeight}),D=(e,r=!1)=>{let n=e.offsetWidth,o=e.offsetHeight;if(r){const s=window.getComputedStyle(e),t=parseFloat(s.marginLeft||"0"),c=parseFloat(s.marginRight||"0"),a=parseFloat(s.marginTop||"0"),u=parseFloat(s.marginBottom||"0");n+=t+c,o+=a+u}return{width:n,height:o}},j=e=>e.getBoundingClientRect(),R=e=>{const n=new DOMParser().parseFromString(e,"image/svg+xml");if(n.documentElement.nodeName==="parsererror")throw new Error("Invalid SVG string: Failed to parse SVG");return n.documentElement},v=(e,r)=>(Object.defineProperty(e,r,{value:!0}),e),V=(e,r)=>!!e[r],w=e=>v(e,"__mkEvent"),W=(e,r,n={})=>{const{event:o="mousedown",capture:s=!0,exclude:t=[]}=n,c=w(a=>{const u=a.target;e.contains(u)||t.some(l=>l?.contains(u))||r(a)});return document.addEventListener(o,c,s),()=>document.removeEventListener(o,c,s)},y=(e,r,n={})=>{const{preventDefault:o=!1,stopPropagation:s=!1,event:t="keydown",target:c=document}=n,a=Array.isArray(e)?e:[e],u=w(l=>{a.includes(l.key)&&(o&&l.preventDefault(),s&&l.stopPropagation(),r(l))});return c.addEventListener(t,u),()=>c.removeEventListener(t,u)},z=(e,r={})=>y("Escape",e,r),K=(e,r={})=>y("Enter",e,r),$=(e,r,n={})=>{const{duration:o=500,threshold:s=10}=n;let t=null,c=0,a=0;const u=f=>"touches"in f?f.touches[0]:f,l=w(f=>{const g=u(f);c=g.clientX,a=g.clientY,t=setTimeout(()=>{r(f)},o)}),E=w(f=>{if(!t)return;const g=u(f),te=Math.abs(g.clientX-c),ne=Math.abs(g.clientY-a);(te>s||ne>s)&&d()}),d=w(()=>{t&&(clearTimeout(t),t=null)}),h=T(e,{mousedown:l,mousemove:E,mouseup:d,mouseleave:d,touchstart:l,touchmove:E,touchend:d,touchcancel:d});return()=>{h(),t&&clearTimeout(t)}},T=(e,r,n)=>{const o=[];return Object.entries(r).forEach(([s,t])=>{if(!t)return;const c=s;Array.isArray(t)?t.forEach(a=>{e.addEventListener(c,a,n),o.push([c,a])}):(e.addEventListener(c,t,n),o.push([c,t]))}),()=>{o.forEach(([s,t])=>{e.removeEventListener(s,t,n)})}},N=(e,r={})=>{const{timeout:n=5e3,root:o=document.body,interval:s=100}=r;return new Promise((t,c)=>{const a=o.querySelector(e);if(a){t(a);return}const u=new MutationObserver(()=>{const h=o.querySelector(e);h&&(d(),t(h))});u.observe(o,{childList:!0,subtree:!0});const l=setInterval(()=>{const h=o.querySelector(e);h&&(d(),t(h))},s),E=setTimeout(()=>{d(),c(new Error(`Timeout: Element "${e}" not found within ${n}ms`))},n),d=()=>{u.disconnect(),clearTimeout(E),clearInterval(l)}})},G=(e,r={})=>{const{onRemove:n,root:o=document.body}=r,s=new MutationObserver(()=>{o.contains(e)||(n?.(),s.disconnect())});return s.observe(o,{childList:!0,subtree:!0}),()=>s.disconnect()},X=(e,r={})=>{const{root:n=document.body,timeout:o}=r;return new Promise((s,t)=>{if(!n.contains(e)){s();return}let c;const a=new MutationObserver(()=>{n.contains(e)||(u(),s())});a.observe(n,{childList:!0,subtree:!0}),o&&(c=setTimeout(()=>{u(),t(new Error(`Timeout: Element not removed within ${o}ms`))},o));const u=()=>{a.disconnect(),c&&clearTimeout(c)}})},Y=(e,r={})=>{const{attributes:n=!0,childList:o=!0,characterData:s=!1,subtree:t=!1,onMutation:c}=r,a=new MutationObserver(u=>c?.(u));return a.observe(e,{attributes:n,childList:o,characterData:s,subtree:t}),()=>a.disconnect()},Z=(e,r={})=>{const{id:n,nonce:o,target:s=document.head}=r,t=document.createElement("style");return n&&(t.id=n),o&&t.setAttribute("nonce",o),t.textContent=e,s.appendChild(t),{style:t,remove:()=>{t.parentNode?.removeChild(t)}}},b=typeof unsafeWindow<"u"?unsafeWindow:window,q=b.document;function B(e){return e?e instanceof Window?e:e instanceof UIEvent&&e.view?e.view:e instanceof Document?e.defaultView:e instanceof ShadowRoot?e.host.ownerDocument?.defaultView??null:e instanceof Node?e.ownerDocument?.defaultView??null:null:b}const H=e=>e.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g,"$1-$2").toLowerCase(),_=e=>e.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g,"$1-$2").toLowerCase(),U=(e,r)=>{let n=null,o=null;const s=(...t)=>{o=t,n&&clearTimeout(n),n=setTimeout(()=>{e(...o),n=null,o=null},r)};return s.cancel=()=>{n&&clearTimeout(n),n=null,o=null},s.flush=()=>{n&&(e(...o),clearTimeout(n),n=null,o=null)},s},J=(e,r)=>{let n=null,o=null,s=0;const t=()=>{n&&(clearTimeout(n),n=null)},c=(...a)=>{const u=Date.now();if(o=a,s===0)e(...a),s=u;else{const l=u-s;l>=r?(e(...a),s=u,t()):(t(),n=setTimeout(()=>{e(...o),s=Date.now(),n=null},r-l))}};return c.cancel=()=>{t(),s=0,o=null},c.flush=()=>{s>0&&o!==null&&e(...o),t(),s=0,o=null},c},S=e=>new Promise(r=>setTimeout(r,e)),Q=e=>S(e),k=(e,r,n=`Operation timed out after ${r}ms`)=>Promise.race([e,new Promise((o,s)=>setTimeout(()=>s(new Error(n)),r))]),x=()=>{},ee=async(e,r={})=>{const{maxAttempts:n=3,delay:o=1e3,exponential:s=!1}=r;let t;for(let c=1;c<=n;c++)try{return await e()}catch(a){if(t=a instanceof Error?a:new Error(String(a)),c<n){const u=s?o*Math.pow(2,c-1):o;await new Promise(l=>setTimeout(l,u))}}throw t||new Error("Retry failed")};i.addEventsListener=T,i.camelToKebab=H,i.createElement=C,i.createFragment=L,i.createSVGFromString=R,i.debounce=U,i.delay=S,i.getComputedStyle=O,i.getInnerSize=M,i.getOffset=F,i.getOuterSize=D,i.getRect=j,i.getSize=A,i.getWin=B,i.globalDoc=q,i.globalWin=b,i.injectStyle=Z,i.isMarkedAs=V,i.markFunc=v,i.noop=x,i.onClickOutside=W,i.onEnter=K,i.onEscape=z,i.onKeyPress=y,i.onLongPress=$,i.parseClass=m,i.pascalToKebab=_,i.retry=ee,i.scrollIntoView=I,i.scrollTo=P,i.sleep=Q,i.throttle=J,i.timeout=k,i.waitForElement=N,i.waitForElementRemoval=X,i.watchElementChanges=Y,i.watchElementRemoval=G,Object.defineProperty(i,Symbol.toStringTag,{value:"Module"})}));
@@ -0,0 +1,4 @@
1
+ export * from './string';
2
+ export * from './tag';
3
+ export * from './timing';
4
+ export * from './types';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Converts a camelCase string to kebab-case.
3
+ * @param str - The camelCase string to convert.
4
+ * @returns The kebab-case string.
5
+ */
6
+ export declare const camelToKebab: (str: string) => string;
7
+ /**
8
+ * Converts a PascalCase string to kebab-case.
9
+ * @param str - The PascalCase string to convert.
10
+ * @returns The kebab-case string.
11
+ */
12
+ export declare const pascalToKebab: (str: string) => string;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Type representing a function tagged with a specific string.
3
+ */
4
+ export type TaggedFunction<F extends CallableFunction, T extends string> = F & {
5
+ readonly [K in T]?: true;
6
+ };
7
+ /**
8
+ * Marks a function with a specific tag.
9
+ * @param func - The function to mark.
10
+ * @param tag - The tag to assign.
11
+ * @returns The marked function.
12
+ */
13
+ export declare const markFunc: <F extends CallableFunction, T extends string>(func: F, tag: T) => TaggedFunction<F, T>;
14
+ /**
15
+ * Checks if a function is marked with a specific tag.
16
+ * @param func - The function to check.
17
+ * @param tag - The tag to look for.
18
+ * @returns True if the function is marked with the tag, false otherwise.
19
+ */
20
+ export declare const isMarkedAs: <F extends CallableFunction, T extends string>(func: F, tag: T) => func is TaggedFunction<F, T>;
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Debounce function that delays the execution of a callback until after a specified wait time has elapsed.
3
+ * @param callback - The function to debounce.
4
+ * @param wait - The delay in milliseconds.
5
+ * @returns A debounced function with cancel and flush methods.
6
+ */
7
+ export declare const debounce: <T extends (...args: unknown[]) => unknown>(callback: T, wait: number) => ((...args: Parameters<T>) => void) & {
8
+ cancel: () => void;
9
+ flush: () => void;
10
+ };
11
+ /**
12
+ * Throttle function that executes a callback at most once every specified wait time.
13
+ * @param callback - The function to throttle.
14
+ * @param wait - The minimum interval in milliseconds between executions.
15
+ * @returns A throttled function with cancel and flush methods.
16
+ */
17
+ export declare const throttle: <T extends (...args: unknown[]) => unknown>(callback: T, wait: number) => ((...args: Parameters<T>) => void) & {
18
+ cancel: () => void;
19
+ flush: () => void;
20
+ };
21
+ /**
22
+ * Creates a promise that resolves after a specified delay.
23
+ * @param ms - The delay in milliseconds.
24
+ * @returns A promise that resolves after the delay.
25
+ */
26
+ export declare const delay: (ms: number) => Promise<void>;
27
+ /**
28
+ * Pauses execution for a specified duration in async contexts.
29
+ * @param ms - The duration to sleep in milliseconds.
30
+ * @returns A promise that resolves after the sleep duration.
31
+ */
32
+ export declare const sleep: (ms: number) => Promise<void>;
33
+ /**
34
+ * Creates a promise that rejects if the given promise doesn't resolve within the specified timeout.
35
+ * @param promise - The promise to apply a timeout to.
36
+ * @param ms - The timeout duration in milliseconds.
37
+ * @param message - Optional error message for the timeout error.
38
+ * @returns A promise that resolves with the original promise's value or rejects on timeout.
39
+ */
40
+ export declare const timeout: <T>(promise: Promise<T>, ms: number, message?: string) => Promise<T>;
41
+ /**
42
+ * A no-operation function that does nothing when called.
43
+ */
44
+ export declare const noop: () => void;
45
+ /**
46
+ * Retries a function until it succeeds or reaches the maximum number of attempts.
47
+ * @param fn - The async function to retry.
48
+ * @param options - Configuration options for retry behavior.
49
+ * @returns A promise that resolves with the function result or rejects if all attempts fail.
50
+ */
51
+ export declare const retry: <T>(fn: () => Promise<T>, options?: {
52
+ /** Maximum number of attempts. Default: 3 */
53
+ maxAttempts?: number;
54
+ /** Delay in milliseconds between attempts. Default: 1000 */
55
+ delay?: number;
56
+ /** Whether to use exponential backoff. Default: false */
57
+ exponential?: boolean;
58
+ }) => Promise<T>;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * A type that represents a value that can be either a single instance of type T or an array of type T.
3
+ */
4
+ export type SingleOrArray<T> = T | T[];
5
+ /**
6
+ * A type that represents a value that can be either a direct value of type T or a Promise that resolves to type T.
7
+ */
8
+ export type MaybePromise<T> = T | Promise<T>;
9
+ /**
10
+ * A type that represents a value that can be null or undefined.
11
+ */
12
+ export type Nullable<T> = T | null | undefined;
@@ -0,0 +1,33 @@
1
+ import { defineConfig } from 'eslint/config';
2
+ import prettier from 'eslint-plugin-prettier';
3
+ import simpleImportSort from 'eslint-plugin-simple-import-sort';
4
+ import tseslint from 'typescript-eslint';
5
+
6
+ export default defineConfig([
7
+ { ignores: ['dist/**', 'node_modules/**', 'example-dist/**'] },
8
+ ...tseslint.configs.recommended,
9
+ {
10
+ name: 'globals-and-rules',
11
+ languageOptions: {
12
+ ecmaVersion: 2024,
13
+ sourceType: 'module',
14
+ globals: {
15
+ window: 'readonly',
16
+ document: 'readonly',
17
+ navigator: 'readonly',
18
+ },
19
+ },
20
+ plugins: {
21
+ 'simple-import-sort': simpleImportSort,
22
+ prettier,
23
+ },
24
+ rules: {
25
+ '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
26
+ 'simple-import-sort/imports': 'warn',
27
+ 'simple-import-sort/exports': 'warn',
28
+ 'prettier/prettier': ['warn', { endOfLine: 'auto' }],
29
+ 'no-console': 'warn',
30
+ 'no-debugger': 'warn',
31
+ },
32
+ },
33
+ ]);
package/index.html ADDED
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>tt</title>
8
+ </head>
9
+ <body>
10
+ <div id="app"></div>
11
+ <script type="module" src="/src/main.ts"></script>
12
+ </body>
13
+ </html>
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@mkmonkeycat/dom-utils",
3
+ "version": "0.1.0",
4
+ "description": "A TypeScript utility library for DOM manipulation and common web development tasks.",
5
+ "type": "module",
6
+ "main": "dist/index.cjs",
7
+ "module": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "repository": "https://github.com/MKMonkeyCat/dom-utils.git",
10
+ "bugs": {
11
+ "url": "https://github.com/MKMonkeyCat/dom-utils/issues"
12
+ },
13
+ "author": "MKMonkeyCat <a102009102009@gmail.com>",
14
+ "license": "MIT",
15
+ "keywords": [
16
+ "typescript",
17
+ "dom",
18
+ "utilities",
19
+ "utils",
20
+ "library",
21
+ "web",
22
+ "frontend"
23
+ ],
24
+ "scripts": {
25
+ "dev": "vite",
26
+ "build": "tsc && vite build",
27
+ "preview": "vite preview",
28
+ "test": "vitest run",
29
+ "test:watch": "vitest",
30
+ "lint:fix": "eslint ./src --ext .ts,.tsx --quiet --fix",
31
+ "lint:format": "prettier --log-level warn --write \"./**/*.{ts,tsx,css,md,json}\"",
32
+ "lint": "yarn lint:format && yarn lint:fix"
33
+ },
34
+ "devDependencies": {
35
+ "@eslint/js": "^9.39.2",
36
+ "@types/jsdom": "^27.0.0",
37
+ "@types/node": "^25.0.3",
38
+ "@typescript-eslint/eslint-plugin": "^8.50.1",
39
+ "@typescript-eslint/parser": "^8.50.1",
40
+ "@vitest/coverage-v8": "^4.0.16",
41
+ "eslint": "^9.39.2",
42
+ "eslint-plugin-import": "^2.32.0",
43
+ "eslint-plugin-prettier": "^5.5.4",
44
+ "eslint-plugin-simple-import-sort": "^12.1.1",
45
+ "happy-dom": "^20.0.11",
46
+ "jsdom": "^27.3.0",
47
+ "prettier": "^3.7.4",
48
+ "typescript": "^5.9.3",
49
+ "typescript-eslint": "^8.50.1",
50
+ "vite": "^7.3.0",
51
+ "vite-plugin-dts": "^4.5.4",
52
+ "vitest": "^4.0.16"
53
+ },
54
+ "dependencies": {}
55
+ }