xxf_react 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/flow/index.d.ts +2 -0
  2. package/dist/flow/index.d.ts.map +1 -0
  3. package/dist/flow/index.js +1 -0
  4. package/dist/flow/promise_ext.d.ts +7 -0
  5. package/dist/flow/promise_ext.d.ts.map +1 -0
  6. package/dist/flow/promise_ext.js +44 -0
  7. package/dist/index.d.ts +6 -0
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +10 -0
  10. package/dist/media/index.d.ts +2 -0
  11. package/dist/media/index.d.ts.map +1 -0
  12. package/dist/media/index.js +1 -0
  13. package/dist/media/video-state.d.ts +38 -0
  14. package/dist/media/video-state.d.ts.map +1 -0
  15. package/dist/media/video-state.js +125 -0
  16. package/dist/models/ApiPageDataFieldDTO.d.ts +9 -0
  17. package/dist/models/ApiPageDataFieldDTO.d.ts.map +1 -0
  18. package/dist/models/ApiPageDataFieldDTO.js +1 -0
  19. package/dist/models/PaginationDTO.d.ts +8 -0
  20. package/dist/models/PaginationDTO.d.ts.map +1 -0
  21. package/dist/models/PaginationDTO.js +6 -0
  22. package/dist/models/index.d.ts +3 -0
  23. package/dist/models/index.d.ts.map +1 -0
  24. package/dist/models/index.js +2 -0
  25. package/dist/refresh/LoadMoreAsync.d.ts +36 -0
  26. package/dist/refresh/LoadMoreAsync.d.ts.map +1 -0
  27. package/dist/refresh/LoadMoreAsync.js +55 -0
  28. package/dist/refresh/index.d.ts +2 -0
  29. package/dist/refresh/index.d.ts.map +1 -0
  30. package/dist/refresh/index.js +1 -0
  31. package/dist/responsive/ScreenAdapter.d.ts +2 -0
  32. package/dist/responsive/ScreenAdapter.d.ts.map +1 -0
  33. package/dist/responsive/ScreenAdapter.js +5 -0
  34. package/dist/responsive/index.d.ts +2 -0
  35. package/dist/responsive/index.d.ts.map +1 -0
  36. package/dist/responsive/index.js +1 -0
  37. package/package.json +2 -1
@@ -0,0 +1,2 @@
1
+ export * from './index';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/flow/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC"}
@@ -0,0 +1 @@
1
+ export * from './index';
@@ -0,0 +1,7 @@
1
+ declare global {
2
+ interface Promise<T> {
3
+ bindErrorNotice(filter?: (error: any) => boolean): Promise<T>;
4
+ }
5
+ }
6
+ export declare function initPromiseErrorExtension(): void;
7
+ //# sourceMappingURL=promise_ext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promise_ext.d.ts","sourceRoot":"","sources":["../../src/flow/promise_ext.ts"],"names":[],"mappings":"AAIA,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,OAAO,CAAC,CAAC;QACf,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;KACjE;CACJ;AAED,wBAAgB,yBAAyB,IAAI,IAAI,CAgDhD"}
@@ -0,0 +1,44 @@
1
+ // src/lib/promise_ext.ts
2
+ import { toast } from "react-toastify";
3
+ export function initPromiseErrorExtension() {
4
+ if (typeof Promise === 'undefined') {
5
+ console.warn('Promise is not available in this environment.');
6
+ return;
7
+ }
8
+ // 防止重复定义
9
+ if (Promise.prototype.bindErrorNotice) {
10
+ console.warn('Promise.prototype.bindErrorNotice is already defined.');
11
+ return;
12
+ }
13
+ // 使用 Object.defineProperty,避免直接赋值
14
+ Object.defineProperty(Promise.prototype, 'bindErrorNotice', {
15
+ value: function (filter) {
16
+ return this.catch((error) => {
17
+ const shouldHandle = filter ? filter(error) : true;
18
+ if (shouldHandle) {
19
+ // 错误处理逻辑
20
+ console.error('==========>[Promise Error Notice]', {
21
+ message: (error === null || error === void 0 ? void 0 : error.message) || 'Unknown error',
22
+ error: error,
23
+ timestamp: new Date().toISOString(),
24
+ stack: error === null || error === void 0 ? void 0 : error.stack
25
+ });
26
+ // 使用 toast 通知(需要确保 toast 可用)
27
+ try {
28
+ // 检查 toast 是否可用
29
+ const errorMessage = (error === null || error === void 0 ? void 0 : error.message) || 'An error occurred';
30
+ toast.error(errorMessage.substring(0, 100));
31
+ }
32
+ catch (toastError) {
33
+ // toast 不可用时静默失败
34
+ console.warn('Toast notification failed:', toastError);
35
+ }
36
+ }
37
+ throw error;
38
+ });
39
+ },
40
+ writable: true,
41
+ configurable: true,
42
+ enumerable: false // 设置为不可枚举,避免出现在 for...in 循环中
43
+ });
44
+ }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,10 @@
1
1
  export * from './sse';
2
2
  export * from './fetch';
3
3
  export * from './utils';
4
+ export * from './refresh';
5
+ export * from './models';
6
+ export * from './media';
7
+ export * from './flow';
8
+ export * from './responsive';
9
+ export declare function initXXF(): void;
4
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAG7B,wBAAgB,OAAO,SAEtB"}
package/dist/index.js CHANGED
@@ -1,3 +1,13 @@
1
+ import { initPromiseErrorExtension } from "./flow/promise_ext";
1
2
  export * from './sse';
2
3
  export * from './fetch';
3
4
  export * from './utils';
5
+ export * from './refresh';
6
+ export * from './models';
7
+ export * from './media';
8
+ export * from './flow';
9
+ export * from './responsive';
10
+ ///框架初始化函数,调用后会初始化一些全局功能
11
+ export function initXXF() {
12
+ initPromiseErrorExtension();
13
+ }
@@ -0,0 +1,2 @@
1
+ export * from './video-state';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/media/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC"}
@@ -0,0 +1 @@
1
+ export * from './video-state';
@@ -0,0 +1,38 @@
1
+ /**
2
+ * VideoState - 视频播放状态接口
3
+ * 用于描述 HTML5 video 元素的完整播放状态
4
+ */
5
+ export interface VideoState {
6
+ /** 是否正在播放(非暂停且未结束) */
7
+ playing: boolean;
8
+ /** 是否正在缓冲(播放中因数据不足暂停) */
9
+ buffering: boolean;
10
+ /** 是否可以播放(已加载足够数据) */
11
+ canPlay: boolean;
12
+ /** 当前播放时间(秒) */
13
+ currentTime: number;
14
+ /** 视频总时长(秒) */
15
+ duration: number;
16
+ /** 已缓冲的时间点(秒) */
17
+ buffered: number;
18
+ /** 视频原始宽度(像素) */
19
+ videoWidth: number;
20
+ /** 视频原始高度(像素) */
21
+ videoHeight: number;
22
+ /** 是否已播放结束 */
23
+ ended: boolean;
24
+ /** 播放错误信息(无错误时为 null) */
25
+ error: MediaError | null;
26
+ }
27
+ /**
28
+ * useVideoState - 视频状态管理 Hook
29
+ * @param videoRef - 外部传入的 videoRef,可跨层级(允许 null)
30
+ * @param autoPlay - 是否在 canPlay 后自动播放
31
+ */
32
+ export declare function useVideoState(videoRef: React.RefObject<HTMLVideoElement | null>, autoPlay?: boolean): {
33
+ playState: VideoState;
34
+ play: () => Promise<void> | undefined;
35
+ pause: () => void | undefined;
36
+ seek: (time: number) => void;
37
+ };
38
+ //# sourceMappingURL=video-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-state.d.ts","sourceRoot":"","sources":["../../src/media/video-state.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,WAAW,UAAU;IACvB,sBAAsB;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,yBAAyB;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,sBAAsB;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc;IACd,KAAK,EAAE,OAAO,CAAC;IACf,yBAAyB;IACzB,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,EAAE,QAAQ,UAAQ;;;;iBAyH9D,MAAM;EAGzC"}
@@ -0,0 +1,125 @@
1
+ import { useState, useEffect, useCallback } from 'react';
2
+ /**
3
+ * useVideoState - 视频状态管理 Hook
4
+ * @param videoRef - 外部传入的 videoRef,可跨层级(允许 null)
5
+ * @param autoPlay - 是否在 canPlay 后自动播放
6
+ */
7
+ export function useVideoState(videoRef, autoPlay = false) {
8
+ const [state, setState] = useState({
9
+ playing: false,
10
+ buffering: false,
11
+ canPlay: false,
12
+ currentTime: 0,
13
+ duration: 0,
14
+ buffered: 0,
15
+ videoWidth: 0,
16
+ videoHeight: 0,
17
+ ended: false,
18
+ error: null,
19
+ });
20
+ // 核心事件回调
21
+ const updatePlaying = useCallback(() => {
22
+ const v = videoRef.current;
23
+ if (!v)
24
+ return;
25
+ setState(s => ({ ...s, playing: !v.paused && !v.ended }));
26
+ }, [videoRef]);
27
+ // 缓冲状态:waiting 时为 true,playing 时为 false
28
+ const setBufferingTrue = useCallback(() => {
29
+ setState(s => ({ ...s, buffering: true }));
30
+ }, []);
31
+ const setBufferingFalse = useCallback(() => {
32
+ setState(s => ({ ...s, buffering: false }));
33
+ }, []);
34
+ const updateCanPlay = useCallback(() => {
35
+ setState(s => ({ ...s, canPlay: true }));
36
+ if (autoPlay) {
37
+ const v = videoRef.current;
38
+ v === null || v === void 0 ? void 0 : v.play().catch(() => { });
39
+ }
40
+ }, [videoRef, autoPlay]);
41
+ const updateTime = useCallback(() => {
42
+ const v = videoRef.current;
43
+ if (!v)
44
+ return;
45
+ setState(s => ({ ...s, currentTime: v.currentTime }));
46
+ }, [videoRef]);
47
+ const updateDuration = useCallback(() => {
48
+ const v = videoRef.current;
49
+ if (!v)
50
+ return;
51
+ setState(s => ({ ...s, duration: v.duration }));
52
+ }, [videoRef]);
53
+ const updateBuffered = useCallback(() => {
54
+ const v = videoRef.current;
55
+ if (!v)
56
+ return;
57
+ setState(s => ({
58
+ ...s,
59
+ buffered: v.buffered.length ? v.buffered.end(v.buffered.length - 1) : 0
60
+ }));
61
+ }, [videoRef]);
62
+ const updateSize = useCallback(() => {
63
+ const v = videoRef.current;
64
+ if (!v)
65
+ return;
66
+ setState(s => ({
67
+ ...s,
68
+ videoWidth: v.videoWidth,
69
+ videoHeight: v.videoHeight
70
+ }));
71
+ }, [videoRef]);
72
+ const updateEnded = useCallback(() => {
73
+ const v = videoRef.current;
74
+ if (!v)
75
+ return;
76
+ setState(s => ({ ...s, ended: v.ended }));
77
+ }, [videoRef]);
78
+ const updateError = useCallback(() => {
79
+ const v = videoRef.current;
80
+ if (!v)
81
+ return;
82
+ setState(s => ({ ...s, error: v.error }));
83
+ }, [videoRef]);
84
+ useEffect(() => {
85
+ const video = videoRef.current;
86
+ if (!video)
87
+ return;
88
+ // 注册事件
89
+ video.addEventListener('play', updatePlaying); // 播放请求被接受
90
+ video.addEventListener('playing', updatePlaying); // 真正开始播放(有画面)
91
+ video.addEventListener('playing', setBufferingFalse); // 播放时结束缓冲
92
+ video.addEventListener('pause', updatePlaying); // 暂停
93
+ video.addEventListener('waiting', updatePlaying); // 缓冲中(暂时无法播放)
94
+ video.addEventListener('waiting', setBufferingTrue); // 开始缓冲
95
+ video.addEventListener('canplay', updateCanPlay);
96
+ video.addEventListener('timeupdate', updateTime);
97
+ video.addEventListener('durationchange', updateDuration);
98
+ video.addEventListener('progress', updateBuffered);
99
+ video.addEventListener('loadedmetadata', updateSize);
100
+ video.addEventListener('ended', updateEnded);
101
+ video.addEventListener('error', updateError);
102
+ // cleanup
103
+ return () => {
104
+ video.removeEventListener('play', updatePlaying);
105
+ video.removeEventListener('playing', updatePlaying);
106
+ video.removeEventListener('playing', setBufferingFalse);
107
+ video.removeEventListener('pause', updatePlaying);
108
+ video.removeEventListener('waiting', updatePlaying);
109
+ video.removeEventListener('waiting', setBufferingTrue);
110
+ video.removeEventListener('canplay', updateCanPlay);
111
+ video.removeEventListener('timeupdate', updateTime);
112
+ video.removeEventListener('durationchange', updateDuration);
113
+ video.removeEventListener('progress', updateBuffered);
114
+ video.removeEventListener('loadedmetadata', updateSize);
115
+ video.removeEventListener('ended', updateEnded);
116
+ video.removeEventListener('error', updateError);
117
+ };
118
+ }, [videoRef, updatePlaying, setBufferingTrue, setBufferingFalse, updateCanPlay, updateTime, updateDuration, updateBuffered, updateSize, updateEnded, updateError]);
119
+ // 控制方法
120
+ const play = useCallback(() => { var _a; return (_a = videoRef.current) === null || _a === void 0 ? void 0 : _a.play().catch(() => { }); }, [videoRef]);
121
+ const pause = useCallback(() => { var _a; return (_a = videoRef.current) === null || _a === void 0 ? void 0 : _a.pause(); }, [videoRef]);
122
+ const seek = useCallback((time) => { if (videoRef.current)
123
+ videoRef.current.currentTime = time; }, [videoRef]);
124
+ return { playState: state, play, pause, seek };
125
+ }
@@ -0,0 +1,9 @@
1
+ import { PaginationDTO } from "./PaginationDTO";
2
+ /**
3
+ * 分页数据字段接口
4
+ */
5
+ export interface ApiPageDataFieldDTO<T> {
6
+ list: T[];
7
+ pagination: PaginationDTO;
8
+ }
9
+ //# sourceMappingURL=ApiPageDataFieldDTO.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiPageDataFieldDTO.d.ts","sourceRoot":"","sources":["../../src/models/ApiPageDataFieldDTO.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,mBAAmB,CAAC,CAAC;IAClC,IAAI,EAAE,CAAC,EAAE,CAAA;IACT,UAAU,EAAE,aAAa,CAAA;CAC5B"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ export interface PaginationDTO {
2
+ limit: number;
3
+ page: number;
4
+ total: number;
5
+ total_pages: number;
6
+ }
7
+ export declare const hasNextPage: (pagination?: PaginationDTO) => boolean;
8
+ //# sourceMappingURL=PaginationDTO.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PaginationDTO.d.ts","sourceRoot":"","sources":["../../src/models/PaginationDTO.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,aAAa;IAC1B,KAAK,EAAQ,MAAM,CAAC;IACpB,IAAI,EAAS,MAAM,CAAC;IACpB,KAAK,EAAQ,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,WAAW,GAAI,aAAa,aAAa,KAAG,OAGxD,CAAC"}
@@ -0,0 +1,6 @@
1
+ // 判断是否有下一页的方法
2
+ export const hasNextPage = (pagination) => {
3
+ if (!pagination)
4
+ return false;
5
+ return pagination.page < pagination.total_pages;
6
+ };
@@ -0,0 +1,3 @@
1
+ export * from './ApiPageDataFieldDTO';
2
+ export * from './PaginationDTO';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './ApiPageDataFieldDTO';
2
+ export * from './PaginationDTO';
@@ -0,0 +1,36 @@
1
+ import { ApiPageDataFieldDTO } from "../models/ApiPageDataFieldDTO";
2
+ /**
3
+ * 返回一个稳定的回调(empty deps)。
4
+ * 适合不想因 asyncResult 变化频繁重建回调的场景。
5
+ *
6
+ * 用法:
7
+ * const handleLoadMore = useStableHandleLoadMore(asyncResult, setPageNum);
8
+ * // 自定义是否有下一页的判定逻辑
9
+ * // const handleLoadMore = useHandleLoadMoreCustom<TemplatePaginationResponse, UseAsyncReturn<TemplatePaginationResponse>>(asyncResult, setPageNum, (data) => hasNextPage(data?.pagination))
10
+ *
11
+ * 在对应的组件上使用
12
+ * endReached={handleLoadMore}
13
+ * atBottomStateChange={(atBottom) => {
14
+ * if (atBottom) {
15
+ * handleLoadMore()
16
+ * }
17
+ * }}
18
+ */
19
+ export declare function useHandleLoadMore<TData extends ApiPageDataFieldDTO<any>, TAsyncResult extends {
20
+ loading: boolean;
21
+ error: unknown;
22
+ execute: () => Promise<TData>;
23
+ result?: TData;
24
+ }>(asyncResult: TAsyncResult, setPageNum: (updater: (p: number) => number) => void): () => void;
25
+ /**
26
+ * 可自定义 hasNextPage 判定的版本(名称:useHandleLoadMoreCustom)
27
+ * - hasNextPageFn 接受完整的 TData(可能为 undefined),返回 boolean
28
+ * - 返回稳定回调,内部通过 ref 读取最新 asyncResult 与 hasNextPageFn
29
+ */
30
+ export declare function useHandleLoadMoreCustom<TData, TAsyncResult extends {
31
+ loading: boolean;
32
+ error: unknown;
33
+ execute?: () => Promise<TData>;
34
+ result?: TData;
35
+ }>(asyncResult: TAsyncResult, setPageNum: (updater: (p: number) => number) => void, hasNextPage: (data: TData | undefined) => boolean): () => void;
36
+ //# sourceMappingURL=LoadMoreAsync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoadMoreAsync.d.ts","sourceRoot":"","sources":["../../src/refresh/LoadMoreAsync.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,mBAAmB,EAAC,MAAM,+BAA+B,CAAC;AAElE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,SAAS,mBAAmB,CAAC,GAAG,CAAC,EAAE,YAAY,SAAS;IAC3F,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,KAAK,CAAA;CACjB,EACG,WAAW,EAAE,YAAY,EACzB,UAAU,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,KAAK,IAAI,SAwB/C,IAAI,CAjBZ;AAGD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,YAAY,SAAS;IAChE,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,KAAK,CAAC;CAClB,EACG,WAAW,EAAE,YAAY,EACzB,UAAU,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,KAAK,IAAI,EACpD,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,GAAG,SAAS,KAAK,OAAO,GAClD,MAAM,IAAI,CA+BZ"}
@@ -0,0 +1,55 @@
1
+ import { useCallback, useEffect, useRef } from "react";
2
+ import { hasNextPage } from "../models/PaginationDTO";
3
+ /**
4
+ * 返回一个稳定的回调(empty deps)。
5
+ * 适合不想因 asyncResult 变化频繁重建回调的场景。
6
+ *
7
+ * 用法:
8
+ * const handleLoadMore = useStableHandleLoadMore(asyncResult, setPageNum);
9
+ * // 自定义是否有下一页的判定逻辑
10
+ * // const handleLoadMore = useHandleLoadMoreCustom<TemplatePaginationResponse, UseAsyncReturn<TemplatePaginationResponse>>(asyncResult, setPageNum, (data) => hasNextPage(data?.pagination))
11
+ *
12
+ * 在对应的组件上使用
13
+ * endReached={handleLoadMore}
14
+ * atBottomStateChange={(atBottom) => {
15
+ * if (atBottom) {
16
+ * handleLoadMore()
17
+ * }
18
+ * }}
19
+ */
20
+ export function useHandleLoadMore(asyncResult, setPageNum) {
21
+ return useHandleLoadMoreCustom(asyncResult, setPageNum, (data) => hasNextPage(data === null || data === void 0 ? void 0 : data.pagination));
22
+ }
23
+ /**
24
+ * 可自定义 hasNextPage 判定的版本(名称:useHandleLoadMoreCustom)
25
+ * - hasNextPageFn 接受完整的 TData(可能为 undefined),返回 boolean
26
+ * - 返回稳定回调,内部通过 ref 读取最新 asyncResult 与 hasNextPageFn
27
+ */
28
+ export function useHandleLoadMoreCustom(asyncResult, setPageNum, hasNextPage) {
29
+ const ref = useRef(asyncResult);
30
+ useEffect(() => {
31
+ ref.current = asyncResult;
32
+ }, [asyncResult]);
33
+ // 保证读取到最新的判断函数,同时回调保持稳定(不随函数重建)
34
+ const hasNextRef = useRef((d) => hasNextPage(d === null || d === void 0 ? void 0 : d.pagination));
35
+ useEffect(() => {
36
+ hasNextRef.current = hasNextPage;
37
+ }, [hasNextPage]);
38
+ return useCallback(() => {
39
+ var _a;
40
+ const cur = ref.current;
41
+ if (!cur)
42
+ return;
43
+ if (cur.loading)
44
+ return;
45
+ if (cur.error) {
46
+ (_a = cur.execute) === null || _a === void 0 ? void 0 : _a.call(cur);
47
+ return;
48
+ }
49
+ // 使用最新的 hasNext 判定
50
+ if (!hasNextRef.current(cur.result))
51
+ return;
52
+ ///进行下一页
53
+ setPageNum(p => p + 1);
54
+ }, [setPageNum]);
55
+ }
@@ -0,0 +1,2 @@
1
+ export * from './LoadMoreAsync';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/refresh/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1 @@
1
+ export * from './LoadMoreAsync';
@@ -0,0 +1,2 @@
1
+ export declare const useIsBelowMd: () => boolean;
2
+ //# sourceMappingURL=ScreenAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScreenAdapter.d.ts","sourceRoot":"","sources":["../../src/responsive/ScreenAdapter.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY,eAExB,CAAA"}
@@ -0,0 +1,5 @@
1
+ import { useMediaQuery } from 'react-responsive';
2
+ ///可用于判断手机端和电脑端的分界线
3
+ export const useIsBelowMd = () => {
4
+ return useMediaQuery({ maxWidth: 767 });
5
+ };
@@ -0,0 +1,2 @@
1
+ export * from './index';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/responsive/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC"}
@@ -0,0 +1 @@
1
+ export * from './index';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xxf_react",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "private": false,
5
5
 
6
6
  "type": "module",
@@ -20,6 +20,7 @@
20
20
 
21
21
  "dependencies": {
22
22
  "@microsoft/fetch-event-source": "^2.0.1",
23
+ "react-responsive": "^10.0.1",
23
24
  "react-toastify": "^11.0.5",
24
25
  "react-virtuoso": "^4.17.0",
25
26
  "use-debounce": "^10.0.6",