donar 0.0.1

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 (106) hide show
  1. package/.cspell/custom-dictionary.txt +5 -0
  2. package/.github/actions/base-check/action.yaml +27 -0
  3. package/.github/actions/env-setup/action.yaml +74 -0
  4. package/.github/workflows/pr-check.yaml +33 -0
  5. package/.github/workflows/release.yaml +112 -0
  6. package/.gitignore +41 -0
  7. package/.node-version +1 -0
  8. package/.npmignore +7 -0
  9. package/.vscode/extensions.json +10 -0
  10. package/.vscode/settings.json +44 -0
  11. package/LICENSE +21 -0
  12. package/README.md +160 -0
  13. package/commitlint.config.ts +3 -0
  14. package/cspell.json +27 -0
  15. package/dist/components.esm.js +2 -0
  16. package/dist/css/components.C24nnsjt.css +1 -0
  17. package/dist/hooks.esm.js +185 -0
  18. package/dist/index.esm.js +4 -0
  19. package/dist/js/components.nFDoAkCq.js +198 -0
  20. package/dist/js/utils.CVb1iSAU.js +330 -0
  21. package/dist/types/components.d.ts +1 -0
  22. package/dist/types/hooks.d.ts +1 -0
  23. package/dist/types/index.d.ts +1 -0
  24. package/dist/types/src/components/async-custom-show/index.d.ts +22 -0
  25. package/dist/types/src/components/carousel/hooks.d.ts +74 -0
  26. package/dist/types/src/components/carousel/index.d.ts +88 -0
  27. package/dist/types/src/components/custom-show/index.d.ts +21 -0
  28. package/dist/types/src/components/error-boundary/index.d.ts +31 -0
  29. package/dist/types/src/components/index.d.ts +8 -0
  30. package/dist/types/src/hooks/async-guard.d.ts +9 -0
  31. package/dist/types/src/hooks/index.d.ts +5 -0
  32. package/dist/types/src/hooks/observer.d.ts +70 -0
  33. package/dist/types/src/hooks/state.d.ts +44 -0
  34. package/dist/types/src/hooks/storage.d.ts +25 -0
  35. package/dist/types/src/hooks/timer.d.ts +16 -0
  36. package/dist/types/src/index.d.ts +3 -0
  37. package/dist/types/src/test/emiter-test.d.ts +1 -0
  38. package/dist/types/src/test/index.d.ts +1 -0
  39. package/dist/types/src/test/retry-async-test.d.ts +1 -0
  40. package/dist/types/src/utils/class-singleton.d.ts +6 -0
  41. package/dist/types/src/utils/concurrency.d.ts +17 -0
  42. package/dist/types/src/utils/debounce.d.ts +8 -0
  43. package/dist/types/src/utils/deep-copy.d.ts +11 -0
  44. package/dist/types/src/utils/dev.d.ts +8 -0
  45. package/dist/types/src/utils/download.d.ts +15 -0
  46. package/dist/types/src/utils/event-emitter/helpers.d.ts +36 -0
  47. package/dist/types/src/utils/event-emitter/index.d.ts +65 -0
  48. package/dist/types/src/utils/fetch-xhr/helpers.d.ts +28 -0
  49. package/dist/types/src/utils/fetch-xhr/index.d.ts +25 -0
  50. package/dist/types/src/utils/hash.d.ts +8 -0
  51. package/dist/types/src/utils/index.d.ts +15 -0
  52. package/dist/types/src/utils/is-deep-plain-equal.d.ts +15 -0
  53. package/dist/types/src/utils/json-convert.d.ts +66 -0
  54. package/dist/types/src/utils/micro-queue-scheduler.d.ts +14 -0
  55. package/dist/types/src/utils/raf-interval.d.ts +16 -0
  56. package/dist/types/src/utils/record-typed-map.d.ts +27 -0
  57. package/dist/types/src/utils/retry-async.d.ts +9 -0
  58. package/dist/types/src/utils/thenable.d.ts +15 -0
  59. package/dist/types/utils.d.ts +1 -0
  60. package/dist/utils.esm.js +2 -0
  61. package/eslint.config.ts +48 -0
  62. package/lint-staged.config.ts +13 -0
  63. package/oxfmt.config.ts +14 -0
  64. package/package.json +90 -0
  65. package/pnpm-workspace.yaml +3 -0
  66. package/scripts/sync-node-version/index.js +31 -0
  67. package/simple-git-hooks.js +4 -0
  68. package/src/components/async-custom-show/index.tsx +37 -0
  69. package/src/components/carousel/hooks.ts +312 -0
  70. package/src/components/carousel/index.module.scss +163 -0
  71. package/src/components/carousel/index.tsx +215 -0
  72. package/src/components/custom-show/index.tsx +31 -0
  73. package/src/components/error-boundary/index.tsx +48 -0
  74. package/src/components/index.ts +11 -0
  75. package/src/hooks/async-guard.ts +53 -0
  76. package/src/hooks/index.ts +5 -0
  77. package/src/hooks/observer.ts +236 -0
  78. package/src/hooks/state.ts +140 -0
  79. package/src/hooks/storage.ts +103 -0
  80. package/src/hooks/timer.ts +42 -0
  81. package/src/index.ts +3 -0
  82. package/src/test/emiter-test.ts +19 -0
  83. package/src/test/index.ts +35 -0
  84. package/src/test/retry-async-test.ts +8 -0
  85. package/src/utils/class-singleton.ts +23 -0
  86. package/src/utils/concurrency.ts +49 -0
  87. package/src/utils/debounce.ts +20 -0
  88. package/src/utils/deep-copy.ts +132 -0
  89. package/src/utils/dev.ts +16 -0
  90. package/src/utils/download.ts +39 -0
  91. package/src/utils/event-emitter/helpers.ts +80 -0
  92. package/src/utils/event-emitter/index.ts +171 -0
  93. package/src/utils/fetch-xhr/helpers.ts +85 -0
  94. package/src/utils/fetch-xhr/index.ts +103 -0
  95. package/src/utils/hash.ts +25 -0
  96. package/src/utils/index.ts +18 -0
  97. package/src/utils/is-deep-plain-equal.ts +45 -0
  98. package/src/utils/json-convert.ts +257 -0
  99. package/src/utils/micro-queue-scheduler.ts +38 -0
  100. package/src/utils/raf-interval.ts +42 -0
  101. package/src/utils/record-typed-map.ts +38 -0
  102. package/src/utils/retry-async.ts +30 -0
  103. package/src/utils/thenable.ts +30 -0
  104. package/tsconfig.json +43 -0
  105. package/types/scss.d.ts +10 -0
  106. package/vite.config.ts +51 -0
@@ -0,0 +1,330 @@
1
+ //#region src/utils/thenable.ts
2
+ var e = async (e) => {
3
+ try {
4
+ return [
5
+ !0,
6
+ null,
7
+ await Promise.resolve(e)
8
+ ];
9
+ } catch (e) {
10
+ return [
11
+ !1,
12
+ e instanceof Error ? e : Error(String(e)),
13
+ null
14
+ ];
15
+ }
16
+ }, t = (e) => new Promise((t) => {
17
+ t(typeof e == "function" ? e() : e);
18
+ });
19
+ //#endregion
20
+ //#region \0@oxc-project+runtime@0.122.0/helpers/typeof.js
21
+ function n(e) {
22
+ "@babel/helpers - typeof";
23
+ return n = typeof Symbol == "function" && typeof Symbol.iterator == "symbol" ? function(e) {
24
+ return typeof e;
25
+ } : function(e) {
26
+ return e && typeof Symbol == "function" && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e;
27
+ }, n(e);
28
+ }
29
+ //#endregion
30
+ //#region \0@oxc-project+runtime@0.122.0/helpers/toPrimitive.js
31
+ function r(e, t) {
32
+ if (n(e) != "object" || !e) return e;
33
+ var r = e[Symbol.toPrimitive];
34
+ if (r !== void 0) {
35
+ var i = r.call(e, t || "default");
36
+ if (n(i) != "object") return i;
37
+ throw TypeError("@@toPrimitive must return a primitive value.");
38
+ }
39
+ return (t === "string" ? String : Number)(e);
40
+ }
41
+ //#endregion
42
+ //#region \0@oxc-project+runtime@0.122.0/helpers/toPropertyKey.js
43
+ function i(e) {
44
+ var t = r(e, "string");
45
+ return n(t) == "symbol" ? t : t + "";
46
+ }
47
+ //#endregion
48
+ //#region \0@oxc-project+runtime@0.122.0/helpers/defineProperty.js
49
+ function a(e, t, n) {
50
+ return (t = i(t)) in e ? Object.defineProperty(e, t, {
51
+ value: n,
52
+ enumerable: !0,
53
+ configurable: !0,
54
+ writable: !0
55
+ }) : e[t] = n, e;
56
+ }
57
+ //#endregion
58
+ //#region src/utils/concurrency.ts
59
+ var o = class {
60
+ constructor(e = 5) {
61
+ a(this, "queue", []), a(this, "concurrency", void 0), a(this, "running", 0), this.concurrency = e;
62
+ }
63
+ push(e) {
64
+ return new Promise((t, n) => {
65
+ this.queue.push({
66
+ task: e,
67
+ resolve: t,
68
+ reject: n
69
+ }), this.run();
70
+ });
71
+ }
72
+ run() {
73
+ for (; this.running < this.concurrency && this.queue.length > 0;) this.next();
74
+ }
75
+ next() {
76
+ if (this.running >= this.concurrency) return;
77
+ let { task: e, resolve: n, reject: r } = this.queue.shift() ?? {};
78
+ e && (this.running++, t(e).then(n, r).finally(() => {
79
+ this.running--, this.run();
80
+ }));
81
+ }
82
+ }, s = (e, t) => {
83
+ let n;
84
+ return function(...r) {
85
+ n && clearTimeout(n), n = setTimeout(() => {
86
+ e.apply(this, r);
87
+ }, t);
88
+ };
89
+ };
90
+ //#endregion
91
+ //#region src/utils/hash.ts
92
+ async function c(e, t = "SHA-1") {
93
+ try {
94
+ if (!e) throw Error("message is empty");
95
+ let n = new TextEncoder().encode(e), r = await window.crypto.subtle.digest(t, n);
96
+ return Array.from(new Uint8Array(r)).map((e) => e.toString(16).padStart(2, "0")).join("");
97
+ } catch (e) {
98
+ throw e instanceof Error ? e : /* @__PURE__ */ Error("string to hash failed");
99
+ }
100
+ }
101
+ //#endregion
102
+ //#region src/utils/download.ts
103
+ var l = (e) => new Promise((t, n) => {
104
+ try {
105
+ let r = window.open(e, "_blank");
106
+ !r || r.closed || r.closed === void 0 ? n(/* @__PURE__ */ Error("Tab 可能被拦截了")) : t(!0);
107
+ } catch {
108
+ n(/* @__PURE__ */ Error("下载出错"));
109
+ }
110
+ }), u = (e, t, n = !0) => {
111
+ let r = URL.createObjectURL(e);
112
+ try {
113
+ let e = document.createElement("a");
114
+ e.href = r, e.download = t, n || e.setAttribute("target", "_blank"), e.click();
115
+ } finally {
116
+ URL.revokeObjectURL(r);
117
+ }
118
+ }, d = (() => {
119
+ let e = /^\[[a-z]+ ([A-Za-z]+)\]$/;
120
+ return (t) => t.constructor && t.constructor.name || Object.prototype.toString.call(t).replace(e, "$1");
121
+ })(), f = (e) => e === Object(e), p = (e) => f(e) ? e instanceof Set ? !0 : Object.prototype.hasOwnProperty.call(e, "size") && typeof e.add == "function" && typeof e.has == "function" : !1, m = (e) => f(e) ? e instanceof Map ? !0 : Object.prototype.hasOwnProperty.call(e, "size") && typeof e.set == "function" && typeof e.get == "function" : !1, h = (e) => Array.isArray(e) ? [] : p(e) ? /* @__PURE__ */ new Set() : m(e) ? /* @__PURE__ */ new Map() : {}, g = (e, t = !0) => {
122
+ let n = /* @__PURE__ */ new WeakMap(), r = (e) => {
123
+ if (!f(e)) return e;
124
+ switch (d(e)) {
125
+ case "Date":
126
+ case "RegExp":
127
+ case "Function": {
128
+ let t = e.constructor;
129
+ return new t(e);
130
+ }
131
+ case "WeakMap":
132
+ case "WeakSet": return e;
133
+ }
134
+ if (n.get(e)) return n.get(e);
135
+ let i = h(e);
136
+ if (t && Object.setPrototypeOf(i, Object.getPrototypeOf(e)), n.set(e, i), p(e)) {
137
+ for (let t of e) i.add(r(t));
138
+ return i;
139
+ }
140
+ if (m(e)) {
141
+ for (let [t, n] of e) i.set(r(t), r(n));
142
+ return i;
143
+ }
144
+ return Reflect.ownKeys(e).map((t) => i[t] = r(e[t])), i;
145
+ };
146
+ return r(e);
147
+ }, _ = (e, t) => {
148
+ let n = Date.now(), r = !1, i = () => r = !0, a = () => {
149
+ requestAnimationFrame(() => {
150
+ let i = Date.now();
151
+ i - n >= t && (e(), n = i), r || a();
152
+ });
153
+ };
154
+ return requestAnimationFrame(a), { stop: i };
155
+ }, v = (e) => {
156
+ typeof e == "object" && e.stop && e.stop(), typeof e == "function" && e();
157
+ }, y = (e) => e && e.charAt(0).toUpperCase() + e.slice(1), b = (e) => e && e.charAt(0).toLowerCase() + e.slice(1), x = (e) => e && e.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, ""), S = (e) => e && e.replace(/_([a-zA-Z])/g, (e, t) => t.toUpperCase()).replace(/_(\d+)/g, (e, t) => t).replace(/_/g, ""), C = ({ obj: e, ignoreKeys: t = /* @__PURE__ */ new Set(), convertFn: n }) => {
158
+ if (Object(e) !== e) return e;
159
+ if (Array.isArray(e)) return e.map((e) => C({
160
+ obj: e,
161
+ ignoreKeys: t,
162
+ convertFn: n
163
+ }));
164
+ let r = {}, i = Object.entries(e);
165
+ for (let [e, a] of i) {
166
+ let i = t.has(e) ? e : n(e);
167
+ r[i] = C({
168
+ obj: a,
169
+ ignoreKeys: t,
170
+ convertFn: n
171
+ });
172
+ }
173
+ return r;
174
+ }, w = {
175
+ SnakeToCamel: "snakeToCamel",
176
+ CamelToSnake: "camelToSnake",
177
+ CamelToPascal: "camelToPascal",
178
+ PascalToCamel: "pascalToCamel"
179
+ }, T = (e, t) => C({
180
+ obj: e,
181
+ ignoreKeys: new Set(t ?? []),
182
+ convertFn: S
183
+ }), E = (e, t) => C({
184
+ obj: e,
185
+ ignoreKeys: new Set(t ?? []),
186
+ convertFn: x
187
+ }), D = (e, t) => C({
188
+ obj: e,
189
+ ignoreKeys: new Set(t ?? []),
190
+ convertFn: y
191
+ }), O = (e, t) => C({
192
+ obj: e,
193
+ ignoreKeys: new Set(t ?? []),
194
+ convertFn: b
195
+ }), k = (e, t) => {
196
+ t && (t instanceof Headers ? t.forEach((t, n) => {
197
+ e.setRequestHeader(n, t);
198
+ }) : Array.isArray(t) ? t.forEach((t) => {
199
+ e.setRequestHeader(t[0], t[1]);
200
+ }) : Object.keys(t).forEach((n) => {
201
+ e.setRequestHeader(n, t[n]);
202
+ }));
203
+ }, A = async (e, t) => {
204
+ if (!(e instanceof ReadableStream)) return e;
205
+ let n = [], r = e.getReader();
206
+ for (;;) {
207
+ t?.throwIfAborted();
208
+ let { done: e, value: i } = await r.read();
209
+ if (e) break;
210
+ n.push(i);
211
+ }
212
+ return new Blob(n);
213
+ }, j = /[\r\n]+/, M = function(e) {
214
+ let t = e.getAllResponseHeaders().trim().split(j).map((e) => {
215
+ let t = e.indexOf(":");
216
+ return t <= -1 ? [] : [e.slice(0, t), e.slice(t + 1).trim()];
217
+ });
218
+ return new Headers(t);
219
+ }, N = class extends DOMException {
220
+ constructor(e) {
221
+ super(e ?? "signal is aborted without reason", "AbortError"), a(this, "isTimeout", !0);
222
+ }
223
+ }, P = async (e, t) => new Promise((n, r) => {
224
+ let { body: i, method: a = "GET", headers: o, credentials: s, signal: c, timeout: l, onUploadProgress: u, onDownloadProgress: d } = t || {}, f = new XMLHttpRequest(), p = a.toUpperCase();
225
+ if (f.open(p, e, !0), k(f, o), s === "include" && (f.withCredentials = !0), f.responseType = "blob", typeof l == "number" && !Number.isNaN(l) && (f.timeout = l), u && (f.upload.onprogress = (e) => u(e.loaded, e.total, e)), d && (f.onprogress = (e) => d(e.loaded, e.total, e)), c) {
226
+ let e = () => f.abort();
227
+ c.addEventListener("abort", e, { once: !0 }), f.onloadend = () => c?.removeEventListener("abort", e);
228
+ }
229
+ f.onabort = () => r(new DOMException("signal is aborted without reason", "AbortError")), f.ontimeout = () => r(new N("请求超时")), f.onerror = () => r(/* @__PURE__ */ TypeError("网络错误")), f.onload = () => n(new Response(f.response, {
230
+ status: f.status,
231
+ statusText: f.statusText,
232
+ headers: M(f)
233
+ })), A(i, c).then((e) => f.send(["GET", "HEAD"].includes(p) ? null : e));
234
+ }), F = (e) => {
235
+ let t, n = new Proxy(e, { construct(n, r) {
236
+ return t ? console.warn(`${e.name}为单例构造函数,只能有一个实例`) : t = new n(...r), t;
237
+ } });
238
+ return e.prototype.constructor = n, n;
239
+ }, I = (e, t) => Object.prototype.hasOwnProperty.call(e, t), L = () => /* @__PURE__ */ new Map(), R = () => ({
240
+ once: (e, t, n) => {
241
+ e.get(t)?.delete(n[0]), e.get(t)?.size || e.delete(t);
242
+ },
243
+ signal: (e, t, n) => {
244
+ if (!(n[1]?.signal instanceof AbortSignal)) throw TypeError("参数 signal 类型错误。必须是一个 AbortSignal 对象");
245
+ n[1].signal.aborted && (e.get(t)?.delete(n[0]), e.get(t)?.size || e.delete(t), Reflect.deleteProperty(n, 0));
246
+ }
247
+ }), z = () => {
248
+ let e = [], t = null;
249
+ return (n) => (e.push(n), t || (t = Promise.resolve().then(() => {
250
+ let t;
251
+ for (; t = e.shift();) t();
252
+ }).finally(() => {
253
+ t = null;
254
+ })), t);
255
+ }, B = class extends Map {
256
+ constructor(e) {
257
+ super(e ? Object.entries(e) : []);
258
+ }
259
+ get(e) {
260
+ return super.get(e);
261
+ }
262
+ set(e, t) {
263
+ return super.set(e, t);
264
+ }
265
+ }, V = class {
266
+ constructor(e) {
267
+ a(this, "events", new B()), a(this, "eventOptionExecutor", void 0), a(this, "scheduler", void 0), this.scheduler = e ?? z(), this.eventOptionExecutor = R();
268
+ }
269
+ addEventListener(e, t, n) {
270
+ if (n) {
271
+ let e = Object.keys(this.eventOptionExecutor);
272
+ if (typeof n != "object" || Array.isArray(n)) throw TypeError("参数 options 类型错误。options 应该为一个配置对象。");
273
+ if (!e.some((e) => I(n, e))) throw TypeError(`options 仅支持 ${e.join("、")} 参数`);
274
+ }
275
+ this.events.has(e) || this.events.set(e, L()), this.events.get(e)?.set(t, n);
276
+ }
277
+ removeEventListener(e, t) {
278
+ this.events.has(e) && this.events.get(e)?.delete(t);
279
+ }
280
+ on(e, t, n) {
281
+ this.addEventListener(e, t, n);
282
+ }
283
+ off(e, t) {
284
+ this.removeEventListener(e, t);
285
+ }
286
+ clear(e) {
287
+ return e ? this.events.delete(e) : this.events.clear() ?? !0;
288
+ }
289
+ emit(e, t) {
290
+ this.events.has(e) && this.scheduler(() => {
291
+ this.events.get(e)?.forEach((n, r) => {
292
+ let i = [r, n];
293
+ n && Object.keys(n).forEach((t) => {
294
+ I(this.eventOptionExecutor, t) && this.eventOptionExecutor[t](this.events, e, i);
295
+ }), i[0] && r(t);
296
+ });
297
+ });
298
+ }
299
+ }, H = (e, t = 5, n = 0) => new Promise((r, i) => {
300
+ let a = (o) => {
301
+ e().then(r).catch((e) => {
302
+ if (o <= 0) return i(e);
303
+ let r = t - o, s = typeof n == "function" ? n(r, e) : n;
304
+ setTimeout(() => a(o - 1), s ?? 0);
305
+ });
306
+ };
307
+ a(t);
308
+ }), U = (e) => e == null, W = (e, t) => {
309
+ if (U(e) || U(t)) return Object.is(e, t);
310
+ if (Object.is(e, t)) return !0;
311
+ if (typeof e != typeof t) return !1;
312
+ if (Array.isArray(e) && Array.isArray(t)) {
313
+ if (e.length !== t.length) return !1;
314
+ for (let n = 0, r = e.length; n < r; n++) if (!W(e[n], t[n])) return !1;
315
+ return !0;
316
+ }
317
+ if (typeof e == "object" && typeof t == "object") {
318
+ let n = Object.keys(e), r = Object.keys(t);
319
+ if (n.length !== r.length) return !1;
320
+ for (let r of n) if (!Object.hasOwnProperty.call(t, r) || !W(e[r], t[r])) return !1;
321
+ return !0;
322
+ }
323
+ return !1;
324
+ };
325
+ console.clog = (...e) => {
326
+ let t = typeof e[0] == "string" ? e.shift() : "==>";
327
+ e.unshift(`%c ${t}`, "padding: 4px 8px; border-radius: 4px; color:#fff; background: linear-gradient(90deg, #833ab4 0%, #fd1d1d 50%, #fcb045 100%);"), console.log(...e);
328
+ };
329
+ //#endregion
330
+ export { a as C, o as S, e as T, g as _, B as a, c as b, P as c, D as d, E as f, _ as g, v as h, V as i, N as l, T as m, U as n, z as o, O as p, H as r, F as s, W as t, w as u, u as v, t as w, s as x, l as y };
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,22 @@
1
+ import { FC, ReactNode, JSX } from 'react';
2
+ export type AsyncCustomShowProps<T> = {
3
+ /** 异步判断 Promise */
4
+ when: Promise<T> | undefined | null | false;
5
+ /** 异步失败时的展示 */
6
+ fallback?: ReactNode;
7
+ /** 异步成功时的展示 */
8
+ children: (value: T | undefined | null | false) => ReactNode;
9
+ };
10
+ export interface AsyncCustomShowType<T> extends FC<AsyncCustomShowProps<T>> {
11
+ (props: AsyncCustomShowProps<T>): JSX.Element;
12
+ }
13
+ /**
14
+ * @author sonion
15
+ * @description 异步展示组件
16
+ * @param {AsyncCustomShowProps<T>} props - 组件属性
17
+ * @param {Promise<T> | undefined | null | false} props.when 异步判断 Promise
18
+ * @param {ReactNode} [props.fallback] 异步失败时的展示
19
+ * @param {(value: T | undefined | null | false) => ReactNode} props.children 异步成功时的展示
20
+ */
21
+ declare function AsyncCustomShow<T>({ when, fallback, children, }: AsyncCustomShowProps<T>): import("react/jsx-runtime").JSX.Element;
22
+ export default AsyncCustomShow;
@@ -0,0 +1,74 @@
1
+ import { ReactElement } from 'react';
2
+ export type ShowArrowType = 'always' | 'auto' | 'hover' | 'none';
3
+ type ShowArrowHookParams = {
4
+ /** 箭头类型 */
5
+ showArrow: ShowArrowType;
6
+ /** 轮播图数量 */
7
+ length: number;
8
+ /** 轮播图宽度 */
9
+ cardWidth?: number;
10
+ /** 轮播图容器 */
11
+ wrapperRef?: HTMLElement;
12
+ };
13
+ /**
14
+ * @author sonion
15
+ * @description 计算是否显示左右箭头
16
+ * @param {ShowArrowHookParams} params - hook参数
17
+ * @param {ShowArrowType} params.showArrow - 箭头类型
18
+ * @param {number} params.length - 轮播图数量
19
+ * @param {number} params.cardWidth - 轮播图宽度
20
+ * @param {HTMLElement} params.wrapperRef - 轮播图容器
21
+ * @returns {(index: number)=>[boolean, boolean]} - 计算是否显示左右箭头的函数
22
+ */
23
+ export declare const useShowArrow: ({ showArrow, length, cardWidth, wrapperRef, }: ShowArrowHookParams) => (index: number) => [boolean, boolean];
24
+ export type NonLoopEndFuncType = (
25
+ /** 切换方向 */
26
+ direction: 'prev' | 'next',
27
+ /** 当前索引 */
28
+ current: number,
29
+ /** 轮播图数量 */
30
+ total: number,
31
+ /** 非循环轮播结束时的偏移量 */
32
+ offset: number) => void;
33
+ type PlayControlHookParams = {
34
+ /** 轮播图数量 */
35
+ length: number;
36
+ /** 是否无缝轮播 */
37
+ loop: boolean;
38
+ /** 箭头类型 */
39
+ showArrow: ShowArrowType;
40
+ /** 轮播图宽度 */
41
+ cardWidth?: number;
42
+ /** 非循环轮播结束时的回调 */
43
+ onNonLoopEnd?: NonLoopEndFuncType;
44
+ /** 非循环轮播结束时的偏移量 */
45
+ offsetOnEnd?: number;
46
+ };
47
+ /**
48
+ * @author sonion
49
+ * @description 播放轮播图控制
50
+ * @param {PlayControlHookParams} params - hook参数
51
+ * @param {number} params.length - 轮播图数量
52
+ * @param {boolean} params.loop - 是否无缝轮播
53
+ * @param {ShowArrowType} params.showArrow - 箭头类型
54
+ * @param {number} params.cardWidth - 轮播图宽度
55
+ * @param {NonLoopEndFuncType} params.onNonLoopEnd - 非循环轮播结束回调
56
+ * @param {number} params.offsetOnEnd - 非循环轮播结束时的偏移量
57
+ */
58
+ export declare const usePlayControl: ({ length, loop, showArrow, cardWidth, onNonLoopEnd, offsetOnEnd, }: PlayControlHookParams) => readonly [(node: HTMLElement | null) => void, (direction?: "prev" | "next") => void, (index: number) => void, () => number, import('react').MutableRefObject<boolean>];
59
+ /**
60
+ * 子元素重渲染的依赖的类型
61
+ * length 依赖 children的数量
62
+ * child 依赖 children本身的变化
63
+ */
64
+ export type RerenderType = 'length' | 'child';
65
+ /**
66
+ * @author sonion
67
+ * @description 创建无缝轮播结构
68
+ * @param {ReactElement} children - 轮播列表
69
+ * @param {boolean} loop - 是否无缝轮播
70
+ * @param {RerenderType} rerender - 子元素重渲染的依赖类型
71
+ * @returns {ReactElement[]} - 无缝轮播结构
72
+ */
73
+ export declare const useLoopChildren: (children: ReactElement[], loop: boolean, rerender: RerenderType) => ReactElement<any, string | import('react').JSXElementConstructor<any>>[];
74
+ export {};
@@ -0,0 +1,88 @@
1
+ import { FC, CSSProperties, ReactElement } from 'react';
2
+ import { ShowArrowType, RerenderType, NonLoopEndFuncType } from './hooks';
3
+ type IndicatorType = 'line' | 'dot' | 'none';
4
+ export type CarouselProps = {
5
+ /** 单个轮播项的宽度 */
6
+ cardWidth?: number;
7
+ /** 单个轮播项的高度 */
8
+ cardHeight?: number;
9
+ /** 轮播容器的宽度 */
10
+ wrapperWidth?: number;
11
+ /** 轮播容器的高度 */
12
+ wrapperHeight?: number;
13
+ /** 轮播项之间的间隔 */
14
+ gapSize?: number;
15
+ /** 是否无缝轮播 */
16
+ loop?: boolean;
17
+ /** 切换时间(毫秒) */
18
+ duration?: number;
19
+ /** 是否自动播放 */
20
+ autoPlay?: boolean;
21
+ /** 箭头类型 */
22
+ showArrow?: ShowArrowType;
23
+ /** 指示器类型 */
24
+ indicatorType?: IndicatorType;
25
+ /** 主轮播类名,不包括指示器 */
26
+ className?: string;
27
+ /** 主轮播样式,不包括指示器 */
28
+ style?: CSSProperties;
29
+ /** 轮播项 */
30
+ children: ReactElement[];
31
+ /** 轮播项更新依赖方式 */
32
+ rerender?: RerenderType;
33
+ /** 非循环模式下,轮播结束回调 */
34
+ onNonLoopEnd?: NonLoopEndFuncType;
35
+ /** 非循环模式下,轮播结束时的偏移量。就是提前第几张就算结束。暂不支持延后。 */
36
+ offsetOnEnd?: number;
37
+ /** 自定义渲染箭头 */
38
+ arrows?: [
39
+ /** 自定义渲染上一个箭头 */
40
+ FC<{
41
+ onClick: () => void;
42
+ className?: string;
43
+ }>,
44
+ /** 自定义渲染下一个箭头 */
45
+ FC<{
46
+ onClick: () => void;
47
+ className?: string;
48
+ }>
49
+ ];
50
+ };
51
+ export type CarouselRef = {
52
+ /** 开始播放 */
53
+ run: () => void;
54
+ /** 停止播放 */
55
+ stop: () => void;
56
+ /** 切换到上一个或下一个 */
57
+ stepChange: (arg: 'prev' | 'next') => void;
58
+ /** 跳转到指定索引 */
59
+ jumpChange: (arg: number) => void;
60
+ /** 获取当前索引 */
61
+ getCurrentIndex: () => number;
62
+ };
63
+ /**
64
+ * @author sonion
65
+ * @description 轮播组件,用于展示多个轮播项
66
+ * @param {CarouselProps} props - 组件的属性
67
+ * @param {number} [props.cardWidth] - 单个轮播项的宽度
68
+ * @param {number} [props.cardHeight] - 单个轮播项的高度
69
+ * @param {number} [props.wrapperWidth] - 轮播容器的宽度
70
+ * @param {number} [props.wrapperHeight] - 轮播容器的高度
71
+ * @param {number} [props.gapSize] - 轮播项之间的间隔
72
+ * @param {boolean} [props.loop] - 是否无缝循环
73
+ * @param {number} [props.duration=6000] - 切换时间(毫秒)
74
+ * @param {boolean} [props.autoPlay=true] - 是否自动播放
75
+ * @param {ShowArrowType} [props.showArrow='always'] - 箭头类型
76
+ * @param {IndicatorType} [props.indicatorType='line'] - 指示器类型
77
+ * @param {string} [props.className] - 主轮播类名,不包括指示器
78
+ * @param {CSSProperties} [props.style] - 主轮播样式,不包括指示器
79
+ * @param {ReactElement[]} children - 轮播项
80
+ * @param {RerenderType} [props.rerender='length'] - 轮播项更新依赖方式
81
+ * @param {(direction: 'prev' | 'next', current: number, total: number, offset: number) => void} [props.onNonLoopEnd] - 非循环模式下,轮播结束回调。
82
+ * @param {number} [props.offsetOnEnd=0] - 非循环模式下,轮播结束时的偏移量。就是提前第几张就算结束。暂不支持延后。
83
+ * @param {[FC<{ onClick: () => void; className?: string }>, FC<{ onClick: () => void; className?: string }>]} [props.arrows] - 自定义渲染箭头
84
+ */
85
+ declare const Carousel: import('react').ForwardRefExoticComponent<CarouselProps & import('react').RefAttributes<CarouselRef>>;
86
+ type CarouselType = typeof Carousel;
87
+ export type { ShowArrowType, RerenderType, CarouselType };
88
+ export default Carousel;
@@ -0,0 +1,21 @@
1
+ import { FC, ReactNode, JSX, PropsWithChildren } from 'react';
2
+ export type CustomShowProps<T> = PropsWithChildren<{
3
+ /** 判断条件 */
4
+ when: T | null | undefined | false;
5
+ /** 不满足条件时的渲染内容 */
6
+ fallback?: ReactNode;
7
+ }>;
8
+ export interface CustomShowType<T> extends FC<CustomShowProps<T>> {
9
+ (props: CustomShowProps<T>): JSX.Element;
10
+ }
11
+ /**
12
+ * @author sonion
13
+ * @description 根据条件渲染内容,替代用三目运算和短路规则条件渲染
14
+ * @param {CustomShowProps<T>} props 组件属性
15
+ * @param {T | null | undefined | false} props.when 条件
16
+ * @param {ReactNode} props.fallback 不满足条件时的渲染内容
17
+ * @param {(value: T | null | undefined | false) => ReactNode} props.children 满足条件时的渲染内容
18
+ * @returns {JSX.Element} - 组件节点
19
+ */
20
+ declare function CustomShow<T>({ when, fallback, children, }: CustomShowProps<T>): JSX.Element;
21
+ export default CustomShow;
@@ -0,0 +1,31 @@
1
+ import { Component, ErrorInfo, ReactNode } from 'react';
2
+ export interface ErrorBoundaryProps {
3
+ /** 正常展示 */
4
+ children: ReactNode;
5
+ /** 错误发生时显示的回退内容 */
6
+ fallback: ReactNode;
7
+ /** 错误信息的提示文本 */
8
+ msg?: string;
9
+ }
10
+ interface State {
11
+ hasError: boolean;
12
+ }
13
+ /**
14
+ * @author sonion
15
+ * @description 错误边界组件,用于捕获子组件的错误并显示自定义的回退内容
16
+ * @param {ErrorBoundaryProps} props - 组件的属性
17
+ * @param {ReactNode} props.fallback - 错误发生时显示的回退内容
18
+ * @param {string} [props.msg='组件加载失败'] - 错误信息的提示文本
19
+ * @param {ReactNode} props.children - 子组件,可能会触发错误
20
+ * @returns {import('react').JSX.Element} - 组件节点
21
+ */
22
+ declare class ErrorBoundary extends Component<ErrorBoundaryProps, State> {
23
+ state: State;
24
+ private msg;
25
+ static getDerivedStateFromError(): State;
26
+ componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
27
+ render(): ReactNode;
28
+ }
29
+ type ErrorBoundaryType = typeof ErrorBoundary;
30
+ export type { ErrorBoundaryType };
31
+ export default ErrorBoundary;
@@ -0,0 +1,8 @@
1
+ export * from './carousel';
2
+ export { default as Carousel } from './carousel';
3
+ export * from './custom-show';
4
+ export { default as CustomShow } from './custom-show';
5
+ export * from './async-custom-show';
6
+ export { default as AsyncCustomShow } from './async-custom-show';
7
+ export * from './error-boundary';
8
+ export { default as ErrorBoundary } from './error-boundary';
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @author sonion
3
+ * @description 异步操作锁,防止重复调用。通过返回的 Promise 确定是否执行中,执行中不可重复触发。
4
+ * @param {(...args: T)=>Promise<R>} asyncAction - 异步方法,需返回Promise
5
+ * @param {(isPending: boolean) => void} [onChange] - 状态变化回调
6
+ * @param {string} [msg] - 警告信息
7
+ * @returns {[boolean, (...args: T) => (Promise<R> | Promise<void>)]} - 返回是否执行中,执行方法
8
+ */
9
+ export declare const useAsyncActionLock: <T extends unknown[], R>(asyncAction: (...args: T) => Promise<R>, onChange?: (isPending: boolean) => void, msg?: string) => readonly [boolean, (...args: T) => Promise<R> | Promise<void>];
@@ -0,0 +1,5 @@
1
+ export * from './state';
2
+ export * from './timer';
3
+ export * from './observer';
4
+ export * from './storage';
5
+ export * from './async-guard';
@@ -0,0 +1,70 @@
1
+ type MutationObserverCallback = (entry: MutationRecord[], observer: MutationObserver) => void;
2
+ /**
3
+ * @author sonion
4
+ * @description dom变化观察器hook
5
+ * @param {MutationObserverCallback} callback - 回调函数,参数为 MutationRecord[]
6
+ * @param {boolean} [once] - 是否只观察一次,默认false
7
+ */
8
+ export declare const useMutationObserver: (callback: MutationObserverCallback, once?: boolean) => {
9
+ /** 开始观察 因重新生成观察器observe不会更新,故不可以observe是否更新做依赖依据 */
10
+ observe: (el: Node | null, options?: MutationObserverInit) => void;
11
+ /** 获取所有未处理的观察记录 */
12
+ takeRecords: () => MutationRecord[] | undefined;
13
+ /** 取消所有观察,用observe重新启用 */
14
+ disconnect: () => void | undefined;
15
+ };
16
+ type IntersectionObserverCallback = (
17
+ /** 交叉目标 */
18
+ target: Element,
19
+ /** 交叉目标的根元素 */
20
+ root: Element | undefined,
21
+ /** 交叉观察器实例 */
22
+ observer: IntersectionObserver) => void;
23
+ type IntersectionObserverParams = {
24
+ callback: IntersectionObserverCallback;
25
+ rootMargin?: number;
26
+ threshold?: number;
27
+ once?: boolean;
28
+ };
29
+ /**
30
+ * @author sonion
31
+ * @description 视口交叉观察器hook
32
+ * @param {IntersectionObserverParams} params - 观察器初始化参数
33
+ * @param {IntersectionObserverCallback} params.callback - 加载回调。
34
+ * @param {number} [params.rootMargin] - 提前多少px触发
35
+ * @param {number} [params.threshold] - 被观察目标与观察区交叉多少触发,0-1
36
+ * @param {boolean} [params.once] - 是否只触发一次
37
+ */
38
+ export declare const useIntersectionObserver: ({ callback, rootMargin, threshold, once, }: IntersectionObserverParams) => {
39
+ rootRef: Element | undefined;
40
+ /** 设置观察区域 */
41
+ setRootRef: (node: Element | null) => void;
42
+ /** 开始观察 */
43
+ observe: (el: Element | null) => void;
44
+ /** 取消观察 */
45
+ unobserve: (el: Element | null) => void | null | undefined;
46
+ /** 取消所有观察,用observe重新启用 */
47
+ disconnect: () => void | undefined;
48
+ /** 获取 未触发回调前,所有未处理的观察记录,触发后清空 */
49
+ takeRecords: () => IntersectionObserverEntry[] | undefined;
50
+ };
51
+ type ResizeObserverCallback = (
52
+ /** 变化记录 */
53
+ entry: ResizeObserverEntry,
54
+ /** 观察器实例 */
55
+ observer: ResizeObserver) => void;
56
+ /**
57
+ * @author sonion
58
+ * @description 元素尺寸变化观察器hook
59
+ * @param {ResizeObserverCallback} callback - 回调函数,参数为ResizeObserverEntry
60
+ * @param {boolean} [once] - 是否只观察一次,默认false
61
+ */
62
+ export declare const useResizeObserver: (callback: ResizeObserverCallback, once?: boolean) => {
63
+ /** 开始观察 因重新生成观察器observe不会更新,故不可以observe是否更新做依赖依据 */
64
+ observe: (el: Element | null, options?: ResizeObserverOptions) => void;
65
+ /** 取消观察 */
66
+ unobserve: (el: Element | null) => void | null | undefined;
67
+ /** 取消所有观察,用observe重新启用 */
68
+ disconnect: () => void | undefined;
69
+ };
70
+ export {};