xxf_react 0.5.6 → 0.5.8
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,147 @@
|
|
|
1
|
+
import React, { ReactNode, HTMLAttributes } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* XHover 组件属性
|
|
4
|
+
*/
|
|
5
|
+
export interface XHoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onMouseEnter' | 'onMouseLeave'> {
|
|
6
|
+
/**
|
|
7
|
+
* 子组件
|
|
8
|
+
*/
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
/**
|
|
11
|
+
* 悬浮触发延迟时间(毫秒)
|
|
12
|
+
*
|
|
13
|
+
* 鼠标进入后,需要持续悬浮该时间才会触发 onHover 回调和显示 hoverLayer。
|
|
14
|
+
* - 设为 0 或不设置:鼠标进入立即触发
|
|
15
|
+
* - 设为正数:鼠标需要停留指定毫秒后才触发
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* // 悬浮 2 秒后触发
|
|
20
|
+
* <XHover hoverDelay={2000} onHover={handleHover}>
|
|
21
|
+
*
|
|
22
|
+
* // 立即触发(默认)
|
|
23
|
+
* <XHover onHover={handleHover}>
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @default 0
|
|
27
|
+
*/
|
|
28
|
+
hoverDelay?: number;
|
|
29
|
+
/**
|
|
30
|
+
* 鼠标进入时立即触发的回调(不等待 hoverDelay)
|
|
31
|
+
*
|
|
32
|
+
* 适用于需要在鼠标进入时立即做一些事情的场景,如显示边框高亮等
|
|
33
|
+
*/
|
|
34
|
+
onEnter?: () => void;
|
|
35
|
+
/**
|
|
36
|
+
* 悬浮回调
|
|
37
|
+
*
|
|
38
|
+
* 当鼠标悬浮达到 hoverDelay 时间后触发
|
|
39
|
+
*/
|
|
40
|
+
onHover?: () => void;
|
|
41
|
+
/**
|
|
42
|
+
* 鼠标离开回调
|
|
43
|
+
*
|
|
44
|
+
* @param triggered - 是否已触发过 onHover(用于判断是否需要隐藏 tooltip 等)
|
|
45
|
+
*/
|
|
46
|
+
onLeave?: (triggered: boolean) => void;
|
|
47
|
+
/**
|
|
48
|
+
* 悬浮覆盖层
|
|
49
|
+
*
|
|
50
|
+
* 当悬浮触发(达到 hoverDelay 时间)后,显示在 children 上方的内容。
|
|
51
|
+
* 鼠标离开后自动隐藏。
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```tsx
|
|
55
|
+
* <XHover
|
|
56
|
+
* hoverDelay={1000}
|
|
57
|
+
* hoverLayer={() => (
|
|
58
|
+
* <div className="absolute inset-0 bg-black/50 flex items-center justify-center">
|
|
59
|
+
* <span className="text-white">悬浮提示</span>
|
|
60
|
+
* </div>
|
|
61
|
+
* )}
|
|
62
|
+
* >
|
|
63
|
+
* <img src="..." />
|
|
64
|
+
* </XHover>
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
hoverLayer?: () => ReactNode;
|
|
68
|
+
/**
|
|
69
|
+
* 是否禁用悬浮检测
|
|
70
|
+
*
|
|
71
|
+
* @default false
|
|
72
|
+
*/
|
|
73
|
+
disabled?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* 容器元素类型
|
|
76
|
+
*
|
|
77
|
+
* @default 'div'
|
|
78
|
+
*/
|
|
79
|
+
as?: 'div' | 'span';
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* 悬浮触发组件
|
|
83
|
+
*
|
|
84
|
+
* 支持延迟触发悬浮回调,适用于需要用户停留一段时间后才响应的场景。
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```tsx
|
|
88
|
+
* // 基础用法:鼠标悬浮 2 秒后触发
|
|
89
|
+
* <XHover hoverDelay={2000} onHover={() => console.log('悬浮触发')}>
|
|
90
|
+
* <div>悬浮我</div>
|
|
91
|
+
* </XHover>
|
|
92
|
+
*
|
|
93
|
+
* // 无延迟:立即触发
|
|
94
|
+
* <XHover onHover={() => console.log('立即触发')}>
|
|
95
|
+
* <div>悬浮我</div>
|
|
96
|
+
* </XHover>
|
|
97
|
+
*
|
|
98
|
+
* // 带离开回调,判断是否触发过
|
|
99
|
+
* <XHover
|
|
100
|
+
* hoverDelay={1000}
|
|
101
|
+
* onHover={() => setShowTooltip(true)}
|
|
102
|
+
* onLeave={(triggered) => {
|
|
103
|
+
* if (triggered) setShowTooltip(false)
|
|
104
|
+
* }}
|
|
105
|
+
* >
|
|
106
|
+
* <Button>悬浮显示提示</Button>
|
|
107
|
+
* </XHover>
|
|
108
|
+
*
|
|
109
|
+
* // 使用 hoverLayer 显示悬浮覆盖层
|
|
110
|
+
* <XHover
|
|
111
|
+
* hoverDelay={1000}
|
|
112
|
+
* hoverLayer={() => (
|
|
113
|
+
* <div className="absolute inset-0 bg-black/50 flex items-center justify-center">
|
|
114
|
+
* <PlayIcon className="text-white w-12 h-12" />
|
|
115
|
+
* </div>
|
|
116
|
+
* )}
|
|
117
|
+
* >
|
|
118
|
+
* <img src="thumbnail.jpg" />
|
|
119
|
+
* </XHover>
|
|
120
|
+
*
|
|
121
|
+
* // 使用 span 作为容器(适用于 inline 场景)
|
|
122
|
+
* <XHover as="span" hoverDelay={500} onHover={handleHover}>
|
|
123
|
+
* <span>inline 文本</span>
|
|
124
|
+
* </XHover>
|
|
125
|
+
*
|
|
126
|
+
* // 禁用状态
|
|
127
|
+
* <XHover disabled={isLoading} hoverDelay={1000} onHover={handleHover}>
|
|
128
|
+
* <div>内容</div>
|
|
129
|
+
* </XHover>
|
|
130
|
+
*
|
|
131
|
+
* // 使用 onEnter 立即响应 + onHover 延迟响应
|
|
132
|
+
* <XHover
|
|
133
|
+
* hoverDelay={1000}
|
|
134
|
+
* onEnter={() => setHighlight(true)}
|
|
135
|
+
* onHover={() => setShowDetail(true)}
|
|
136
|
+
* onLeave={() => {
|
|
137
|
+
* setHighlight(false)
|
|
138
|
+
* setShowDetail(false)
|
|
139
|
+
* }}
|
|
140
|
+
* >
|
|
141
|
+
* <Card />
|
|
142
|
+
* </XHover>
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
export declare function XHover({ children, hoverDelay, onEnter, onHover, onLeave, hoverLayer, disabled, as: Component, style, ...rest }: XHoverProps): React.JSX.Element;
|
|
146
|
+
export default XHover;
|
|
147
|
+
//# sourceMappingURL=XHover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"XHover.d.ts","sourceRoot":"","sources":["../../../src/layout/hover/XHover.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAA2C,SAAS,EAAE,cAAc,EAAC,MAAM,OAAO,CAAA;AAEhG;;GAEG;AACH,MAAM,WAAW,WAAY,SAAQ,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,cAAc,GAAG,cAAc,CAAC;IACtG;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAA;IAEnB;;;;;;;;;;;;;;;;;OAiBG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IAEpB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IAEpB;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAA;IAEtC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,UAAU,CAAC,EAAE,MAAM,SAAS,CAAA;IAE5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB;;;;OAIG;IACH,EAAE,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AACH,wBAAgB,MAAM,CAAC,EACnB,QAAQ,EACR,UAAc,EACd,OAAO,EACP,OAAO,EACP,OAAO,EACP,UAAU,EACV,QAAgB,EAChB,EAAE,EAAE,SAAiB,EACrB,KAAK,EACL,GAAG,IAAI,EACV,EAAE,WAAW,qBA0Eb;AAED,eAAe,MAAM,CAAA"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import React, { useCallback, useRef, useEffect, useState } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* 悬浮触发组件
|
|
4
|
+
*
|
|
5
|
+
* 支持延迟触发悬浮回调,适用于需要用户停留一段时间后才响应的场景。
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* // 基础用法:鼠标悬浮 2 秒后触发
|
|
10
|
+
* <XHover hoverDelay={2000} onHover={() => console.log('悬浮触发')}>
|
|
11
|
+
* <div>悬浮我</div>
|
|
12
|
+
* </XHover>
|
|
13
|
+
*
|
|
14
|
+
* // 无延迟:立即触发
|
|
15
|
+
* <XHover onHover={() => console.log('立即触发')}>
|
|
16
|
+
* <div>悬浮我</div>
|
|
17
|
+
* </XHover>
|
|
18
|
+
*
|
|
19
|
+
* // 带离开回调,判断是否触发过
|
|
20
|
+
* <XHover
|
|
21
|
+
* hoverDelay={1000}
|
|
22
|
+
* onHover={() => setShowTooltip(true)}
|
|
23
|
+
* onLeave={(triggered) => {
|
|
24
|
+
* if (triggered) setShowTooltip(false)
|
|
25
|
+
* }}
|
|
26
|
+
* >
|
|
27
|
+
* <Button>悬浮显示提示</Button>
|
|
28
|
+
* </XHover>
|
|
29
|
+
*
|
|
30
|
+
* // 使用 hoverLayer 显示悬浮覆盖层
|
|
31
|
+
* <XHover
|
|
32
|
+
* hoverDelay={1000}
|
|
33
|
+
* hoverLayer={() => (
|
|
34
|
+
* <div className="absolute inset-0 bg-black/50 flex items-center justify-center">
|
|
35
|
+
* <PlayIcon className="text-white w-12 h-12" />
|
|
36
|
+
* </div>
|
|
37
|
+
* )}
|
|
38
|
+
* >
|
|
39
|
+
* <img src="thumbnail.jpg" />
|
|
40
|
+
* </XHover>
|
|
41
|
+
*
|
|
42
|
+
* // 使用 span 作为容器(适用于 inline 场景)
|
|
43
|
+
* <XHover as="span" hoverDelay={500} onHover={handleHover}>
|
|
44
|
+
* <span>inline 文本</span>
|
|
45
|
+
* </XHover>
|
|
46
|
+
*
|
|
47
|
+
* // 禁用状态
|
|
48
|
+
* <XHover disabled={isLoading} hoverDelay={1000} onHover={handleHover}>
|
|
49
|
+
* <div>内容</div>
|
|
50
|
+
* </XHover>
|
|
51
|
+
*
|
|
52
|
+
* // 使用 onEnter 立即响应 + onHover 延迟响应
|
|
53
|
+
* <XHover
|
|
54
|
+
* hoverDelay={1000}
|
|
55
|
+
* onEnter={() => setHighlight(true)}
|
|
56
|
+
* onHover={() => setShowDetail(true)}
|
|
57
|
+
* onLeave={() => {
|
|
58
|
+
* setHighlight(false)
|
|
59
|
+
* setShowDetail(false)
|
|
60
|
+
* }}
|
|
61
|
+
* >
|
|
62
|
+
* <Card />
|
|
63
|
+
* </XHover>
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export function XHover({ children, hoverDelay = 0, onEnter, onHover, onLeave, hoverLayer, disabled = false, as: Component = 'div', style, ...rest }) {
|
|
67
|
+
const timerRef = useRef(null);
|
|
68
|
+
const hasTriggeredRef = useRef(false);
|
|
69
|
+
// 只有 hoverLayer 存在时才需要状态
|
|
70
|
+
const [showLayer, setShowLayer] = useState(false);
|
|
71
|
+
const clearTimer = useCallback(() => {
|
|
72
|
+
if (timerRef.current) {
|
|
73
|
+
clearTimeout(timerRef.current);
|
|
74
|
+
timerRef.current = null;
|
|
75
|
+
}
|
|
76
|
+
}, []);
|
|
77
|
+
// 组件卸载时清理定时器
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
return clearTimer;
|
|
80
|
+
}, [clearTimer]);
|
|
81
|
+
// disabled 变化时清理定时器和状态
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
if (disabled) {
|
|
84
|
+
clearTimer();
|
|
85
|
+
if (hoverLayer) {
|
|
86
|
+
setShowLayer(false);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}, [disabled, clearTimer, hoverLayer]);
|
|
90
|
+
const handleMouseEnter = useCallback(() => {
|
|
91
|
+
if (disabled)
|
|
92
|
+
return;
|
|
93
|
+
hasTriggeredRef.current = false;
|
|
94
|
+
clearTimer();
|
|
95
|
+
// 立即触发 onEnter
|
|
96
|
+
onEnter === null || onEnter === void 0 ? void 0 : onEnter();
|
|
97
|
+
if (hoverDelay <= 0) {
|
|
98
|
+
hasTriggeredRef.current = true;
|
|
99
|
+
if (hoverLayer)
|
|
100
|
+
setShowLayer(true);
|
|
101
|
+
onHover === null || onHover === void 0 ? void 0 : onHover();
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
timerRef.current = setTimeout(() => {
|
|
105
|
+
hasTriggeredRef.current = true;
|
|
106
|
+
if (hoverLayer)
|
|
107
|
+
setShowLayer(true);
|
|
108
|
+
onHover === null || onHover === void 0 ? void 0 : onHover();
|
|
109
|
+
}, hoverDelay);
|
|
110
|
+
}
|
|
111
|
+
}, [hoverDelay, onEnter, onHover, clearTimer, disabled, hoverLayer]);
|
|
112
|
+
const handleMouseLeave = useCallback(() => {
|
|
113
|
+
if (disabled)
|
|
114
|
+
return;
|
|
115
|
+
clearTimer();
|
|
116
|
+
if (hoverLayer)
|
|
117
|
+
setShowLayer(false);
|
|
118
|
+
onLeave === null || onLeave === void 0 ? void 0 : onLeave(hasTriggeredRef.current);
|
|
119
|
+
}, [clearTimer, onLeave, disabled, hoverLayer]);
|
|
120
|
+
// 如果有 hoverLayer,需要使用 relative 定位(用户 style 可覆盖)
|
|
121
|
+
const containerStyle = hoverLayer
|
|
122
|
+
? { position: 'relative', ...style }
|
|
123
|
+
: style;
|
|
124
|
+
return (React.createElement(Component, { ...rest, style: containerStyle, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave },
|
|
125
|
+
children,
|
|
126
|
+
hoverLayer && showLayer && hoverLayer()));
|
|
127
|
+
}
|
|
128
|
+
export default XHover;
|
package/dist/layout/index.d.ts
CHANGED
|
@@ -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,qCAAqC,CAAA;AACnD,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;AAC/C,cAAc,gBAAgB,CAAA"}
|
package/dist/layout/index.js
CHANGED