xxf_react 0.4.3 → 0.4.4

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.
@@ -4,5 +4,6 @@ export * from './resize/core/ResizeObserverHook';
4
4
  export * from './resize/impl/SizedContainer';
5
5
  export * from './resize/impl/SizedLayout';
6
6
  export * from './image/XImage';
7
+ export * from './visibility/ElementVisibilityHooks';
7
8
  export * from './virtualized/VirtualizedConfig';
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/layout/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAA;AAC9C,cAAc,kCAAkC,CAAA;AAChD,cAAc,kCAAkC,CAAA;AAChD,cAAc,8BAA8B,CAAA;AAC5C,cAAc,2BAA2B,CAAA;AACzC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,iCAAiC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/layout/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAA;AAC9C,cAAc,kCAAkC,CAAA;AAChD,cAAc,kCAAkC,CAAA;AAChD,cAAc,8BAA8B,CAAA;AAC5C,cAAc,2BAA2B,CAAA;AACzC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,qCAAqC,CAAA;AACnD,cAAc,iCAAiC,CAAA"}
@@ -4,4 +4,5 @@ export * from './resize/core/ResizeObserverHook';
4
4
  export * from './resize/impl/SizedContainer';
5
5
  export * from './resize/impl/SizedLayout';
6
6
  export * from './image/XImage';
7
+ export * from './visibility/ElementVisibilityHooks';
7
8
  export * from './virtualized/VirtualizedConfig';
@@ -0,0 +1,10 @@
1
+ import { RefObject } from 'react';
2
+ /**
3
+ * 监听元素及其所有祖先的可见性
4
+ * 支持检测 display: none、visibility: hidden、opacity: 0
5
+ *
6
+ * @param ref - 要监听的元素 ref
7
+ * @param debounceMs - 防抖时间(毫秒),默认 16ms(约一帧)
8
+ */
9
+ export declare function useElementVisibility(ref: RefObject<HTMLElement | null>, debounceMs?: number): boolean;
10
+ //# sourceMappingURL=ElementVisibilityHooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ElementVisibilityHooks.d.ts","sourceRoot":"","sources":["../../../src/layout/visibility/ElementVisibilityHooks.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA8B,SAAS,EAAC,MAAM,OAAO,CAAA;AAE5D;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAChC,GAAG,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EAClC,UAAU,GAAE,MAAW,GACxB,OAAO,CAoHT"}
@@ -0,0 +1,109 @@
1
+ 'use client';
2
+ import { useState, useEffect, useRef } from 'react';
3
+ /**
4
+ * 监听元素及其所有祖先的可见性
5
+ * 支持检测 display: none、visibility: hidden、opacity: 0
6
+ *
7
+ * @param ref - 要监听的元素 ref
8
+ * @param debounceMs - 防抖时间(毫秒),默认 16ms(约一帧)
9
+ */
10
+ export function useElementVisibility(ref, debounceMs = 16) {
11
+ const [isVisible, setIsVisible] = useState(null);
12
+ const lastVisibleRef = useRef(null);
13
+ const timerRef = useRef(null);
14
+ const observerRef = useRef(null);
15
+ const debounceMsRef = useRef(debounceMs);
16
+ const mountedRef = useRef(true);
17
+ // 保持 debounceMs 最新,但不触发 effect 重新执行
18
+ debounceMsRef.current = debounceMs;
19
+ useEffect(() => {
20
+ // 重置状态(处理组件重新挂载的情况)
21
+ mountedRef.current = true;
22
+ lastVisibleRef.current = null;
23
+ // 检查元素及所有祖先是否可见
24
+ const checkVisibility = () => {
25
+ if (!mountedRef.current)
26
+ return;
27
+ const el = ref.current;
28
+ if (!el)
29
+ return;
30
+ let current = el;
31
+ let visible = true;
32
+ while (current) {
33
+ const style = getComputedStyle(current);
34
+ if (style.display === 'none' ||
35
+ style.visibility === 'hidden' ||
36
+ style.opacity === '0') {
37
+ visible = false;
38
+ break;
39
+ }
40
+ current = current.parentElement;
41
+ }
42
+ // 只在值变化时更新
43
+ if (mountedRef.current && lastVisibleRef.current !== visible) {
44
+ lastVisibleRef.current = visible;
45
+ setIsVisible(visible);
46
+ }
47
+ };
48
+ // 带防抖的检查
49
+ const debouncedCheck = () => {
50
+ if (timerRef.current) {
51
+ clearTimeout(timerRef.current);
52
+ }
53
+ timerRef.current = setTimeout(checkVisibility, debounceMsRef.current);
54
+ };
55
+ // 设置 observer
56
+ const setupObserver = () => {
57
+ const el = ref.current;
58
+ if (!el)
59
+ return;
60
+ // 清理旧的 observer
61
+ if (observerRef.current) {
62
+ observerRef.current.disconnect();
63
+ }
64
+ const observer = new MutationObserver(debouncedCheck);
65
+ let parent = el;
66
+ while (parent) {
67
+ observer.observe(parent, {
68
+ attributes: true,
69
+ attributeFilter: ['style', 'class'],
70
+ });
71
+ parent = parent.parentElement;
72
+ }
73
+ observerRef.current = observer;
74
+ checkVisibility(); // 初始检查
75
+ };
76
+ setupObserver();
77
+ // 监听 ref 变化(通过 RAF 轮询,处理 ref 延迟赋值的情况)
78
+ let rafId = null;
79
+ const checkRef = () => {
80
+ if (!mountedRef.current)
81
+ return;
82
+ if (ref.current && !observerRef.current) {
83
+ setupObserver();
84
+ rafId = null;
85
+ return;
86
+ }
87
+ rafId = requestAnimationFrame(checkRef);
88
+ };
89
+ if (!ref.current) {
90
+ rafId = requestAnimationFrame(checkRef);
91
+ }
92
+ return () => {
93
+ mountedRef.current = false;
94
+ if (observerRef.current) {
95
+ observerRef.current.disconnect();
96
+ observerRef.current = null;
97
+ }
98
+ if (timerRef.current) {
99
+ clearTimeout(timerRef.current);
100
+ timerRef.current = null;
101
+ }
102
+ if (rafId) {
103
+ cancelAnimationFrame(rafId);
104
+ }
105
+ };
106
+ }, [ref]);
107
+ // 如果还没检测到,返回 true(默认可见)
108
+ return isVisible !== null && isVisible !== void 0 ? isVisible : true;
109
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xxf_react",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "dist/index.js",