@fluentui/react-positioning 9.18.4 → 9.19.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.
- package/CHANGELOG.md +20 -2
- package/dist/index.d.ts +1 -1
- package/lib/hooks/useSafeZoneArea/useSafeZoneArea.js +30 -54
- package/lib/hooks/useSafeZoneArea/useSafeZoneArea.js.map +1 -1
- package/lib-commonjs/hooks/useSafeZoneArea/useSafeZoneArea.js +28 -53
- package/lib-commonjs/hooks/useSafeZoneArea/useSafeZoneArea.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
@@ -1,12 +1,30 @@
|
|
1
1
|
# Change Log - @fluentui/react-positioning
|
2
2
|
|
3
|
-
This log was last generated on
|
3
|
+
This log was last generated on Fri, 11 Jul 2025 15:56:57 GMT and should not be manually modified.
|
4
4
|
|
5
5
|
<!-- Start content -->
|
6
6
|
|
7
|
+
## [9.19.0](https://github.com/microsoft/fluentui/tree/@fluentui/react-positioning_v9.19.0)
|
8
|
+
|
9
|
+
Fri, 11 Jul 2025 15:56:57 GMT
|
10
|
+
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-positioning_v9.18.5..@fluentui/react-positioning_v9.19.0)
|
11
|
+
|
12
|
+
### Minor changes
|
13
|
+
|
14
|
+
- feat: SafeZone restarts timeout on mouse move ([PR #34807](https://github.com/microsoft/fluentui/pull/34807) by lingfangao@hotmail.com)
|
15
|
+
|
16
|
+
## [9.18.5](https://github.com/microsoft/fluentui/tree/@fluentui/react-positioning_v9.18.5)
|
17
|
+
|
18
|
+
Fri, 27 Jun 2025 13:39:40 GMT
|
19
|
+
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-positioning_v9.18.4..@fluentui/react-positioning_v9.18.5)
|
20
|
+
|
21
|
+
### Patches
|
22
|
+
|
23
|
+
- fix: stop rAF if no mouse movement happening ([PR #34734](https://github.com/microsoft/fluentui/pull/34734) by olfedias@microsoft.com)
|
24
|
+
|
7
25
|
## [9.18.4](https://github.com/microsoft/fluentui/tree/@fluentui/react-positioning_v9.18.4)
|
8
26
|
|
9
|
-
Thu, 26 Jun 2025 14:
|
27
|
+
Thu, 26 Jun 2025 14:11:55 GMT
|
10
28
|
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-positioning_v9.18.3..@fluentui/react-positioning_v9.18.4)
|
11
29
|
|
12
30
|
### Patches
|
package/dist/index.d.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import type { GriffelStyle } from '@griffel/react';
|
2
2
|
import * as React_2 from 'react';
|
3
|
-
import { RefObjectFunction } from '@fluentui/react-utilities';
|
3
|
+
import type { RefObjectFunction } from '@fluentui/react-utilities';
|
4
4
|
|
5
5
|
export declare type Alignment = 'top' | 'bottom' | 'start' | 'end' | 'center';
|
6
6
|
|
@@ -1,16 +1,20 @@
|
|
1
|
-
import {
|
2
|
-
import { useEventCallback, useMergedRefs } from '@fluentui/react-utilities';
|
1
|
+
import { useAnimationFrame, useEventCallback, useMergedRefs, useTimeout } from '@fluentui/react-utilities';
|
3
2
|
import * as React from 'react';
|
4
3
|
import { createSafeZoneAreaStateStore } from './createSafeZoneAreaStateStore';
|
5
4
|
import { SafeZoneArea } from './SafeZoneArea';
|
5
|
+
/**
|
6
|
+
* Time in milliseconds after which the safe zone area will be cleared if no mouse movement is detected.
|
7
|
+
*
|
8
|
+
* Only affects the target element, not the safe zone area itself.
|
9
|
+
*/ const MOUSE_MOVE_TARGET_POLLING_TIMEOUT = 2000;
|
10
|
+
// ---
|
6
11
|
export function useSafeZoneArea({ debug = false, disabled = false, onSafeZoneEnter, onSafeZoneMove, onSafeZoneLeave, onSafeZoneTimeout, timeout = 1500 } = {}) {
|
7
12
|
const [stateStore] = React.useState(createSafeZoneAreaStateStore);
|
8
|
-
const { targetDocument } = useFluent_unstable();
|
9
13
|
const safeZoneAreaRef = React.useRef(null);
|
10
14
|
const containerRef = React.useRef(null);
|
11
15
|
const targetRef = React.useRef(null);
|
12
|
-
const
|
13
|
-
const
|
16
|
+
const [setSafeZoneCloseTimeout, clearSafeZoneCloseTimeout] = useTimeout();
|
17
|
+
const [requestUpdateFrame, clearUpdateFrame] = useAnimationFrame();
|
14
18
|
const mouseCoordinatesRef = React.useRef({
|
15
19
|
x: 0,
|
16
20
|
y: 0
|
@@ -23,14 +27,7 @@ export function useSafeZoneArea({ debug = false, disabled = false, onSafeZoneEnt
|
|
23
27
|
}
|
24
28
|
let containerEl = null;
|
25
29
|
function onContainerMouseEnter() {
|
26
|
-
|
27
|
-
if (!targetWindow) {
|
28
|
-
return;
|
29
|
-
}
|
30
|
-
if (timeoutIdRef.current) {
|
31
|
-
targetWindow.clearTimeout(timeoutIdRef.current);
|
32
|
-
timeoutIdRef.current = null;
|
33
|
-
}
|
30
|
+
clearSafeZoneCloseTimeout();
|
34
31
|
stateStore.toggleActive(false);
|
35
32
|
}
|
36
33
|
return (el)=>{
|
@@ -41,9 +38,9 @@ export function useSafeZoneArea({ debug = false, disabled = false, onSafeZoneEnt
|
|
41
38
|
el === null || el === void 0 ? void 0 : el.addEventListener('mouseenter', onContainerMouseEnter);
|
42
39
|
};
|
43
40
|
}, [
|
41
|
+
clearSafeZoneCloseTimeout,
|
44
42
|
disabled,
|
45
|
-
stateStore
|
46
|
-
targetDocument
|
43
|
+
stateStore
|
47
44
|
]);
|
48
45
|
const targetListenerRef = React.useMemo(()=>{
|
49
46
|
if (disabled) {
|
@@ -57,56 +54,41 @@ export function useSafeZoneArea({ debug = false, disabled = false, onSafeZoneEnt
|
|
57
54
|
x: e.clientX,
|
58
55
|
y: e.clientY
|
59
56
|
};
|
60
|
-
if (timeoutIdRef.current) {
|
61
|
-
var _targetDocument_defaultView;
|
62
|
-
targetDocument === null || targetDocument === void 0 ? void 0 : (_targetDocument_defaultView = targetDocument.defaultView) === null || _targetDocument_defaultView === void 0 ? void 0 : _targetDocument_defaultView.clearTimeout(timeoutIdRef.current);
|
63
|
-
timeoutIdRef.current = null;
|
64
|
-
}
|
65
57
|
if (!stateStore.isActive()) {
|
66
58
|
stateStore.toggleActive(true);
|
67
59
|
}
|
60
|
+
setSafeZoneCloseTimeout(()=>{
|
61
|
+
stateStore.toggleActive(false);
|
62
|
+
}, MOUSE_MOVE_TARGET_POLLING_TIMEOUT);
|
68
63
|
}
|
69
64
|
return (el)=>{
|
70
65
|
if (el === null) {
|
71
|
-
|
72
|
-
|
73
|
-
if (mouseMoveIdRef.current) {
|
74
|
-
targetWindow.cancelAnimationFrame(mouseMoveIdRef.current);
|
75
|
-
mouseMoveIdRef.current = null;
|
76
|
-
}
|
77
|
-
if (timeoutIdRef.current) {
|
78
|
-
targetWindow.clearTimeout(timeoutIdRef.current);
|
79
|
-
timeoutIdRef.current = null;
|
80
|
-
}
|
81
|
-
}
|
66
|
+
clearUpdateFrame();
|
67
|
+
clearSafeZoneCloseTimeout();
|
82
68
|
targetEl === null || targetEl === void 0 ? void 0 : targetEl.removeEventListener('mousemove', onTargetMouseMove);
|
83
69
|
}
|
84
70
|
targetEl = el;
|
85
71
|
el === null || el === void 0 ? void 0 : el.addEventListener('mousemove', onTargetMouseMove);
|
86
72
|
};
|
87
73
|
}, [
|
74
|
+
clearUpdateFrame,
|
75
|
+
clearSafeZoneCloseTimeout,
|
88
76
|
disabled,
|
89
77
|
stateStore,
|
90
|
-
|
78
|
+
setSafeZoneCloseTimeout
|
91
79
|
]);
|
92
80
|
const onSvgMouseEnter = useEventCallback((e)=>{
|
93
81
|
onSafeZoneEnter === null || onSafeZoneEnter === void 0 ? void 0 : onSafeZoneEnter(e);
|
94
|
-
|
95
|
-
if (!targetWindow) {
|
96
|
-
return;
|
97
|
-
}
|
98
|
-
if (timeoutIdRef.current) {
|
99
|
-
targetWindow.clearTimeout(timeoutIdRef.current);
|
100
|
-
timeoutIdRef.current = null;
|
101
|
-
}
|
102
|
-
// React 17 still uses pooled synthetic events
|
103
|
-
e.persist();
|
104
|
-
timeoutIdRef.current = targetWindow.setTimeout(()=>{
|
82
|
+
setSafeZoneCloseTimeout(()=>{
|
105
83
|
stateStore.toggleActive(false);
|
106
84
|
onSafeZoneTimeout === null || onSafeZoneTimeout === void 0 ? void 0 : onSafeZoneTimeout();
|
107
85
|
}, timeout);
|
108
86
|
});
|
109
87
|
const onSvgMouseMove = useEventCallback((e)=>{
|
88
|
+
setSafeZoneCloseTimeout(()=>{
|
89
|
+
stateStore.toggleActive(false);
|
90
|
+
onSafeZoneTimeout === null || onSafeZoneTimeout === void 0 ? void 0 : onSafeZoneTimeout();
|
91
|
+
}, timeout);
|
110
92
|
onSafeZoneMove === null || onSafeZoneMove === void 0 ? void 0 : onSafeZoneMove(e);
|
111
93
|
});
|
112
94
|
const onSvgMouseLeave = useEventCallback((e)=>{
|
@@ -118,7 +100,6 @@ export function useSafeZoneArea({ debug = false, disabled = false, onSafeZoneEnt
|
|
118
100
|
function updateSVGs() {
|
119
101
|
const containerEl = containerRef.current;
|
120
102
|
const targetEl = targetRef.current;
|
121
|
-
const targetWindow = targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.defaultView;
|
122
103
|
if (containerEl && targetEl) {
|
123
104
|
var _safeZoneAreaRef_current;
|
124
105
|
(_safeZoneAreaRef_current = safeZoneAreaRef.current) === null || _safeZoneAreaRef_current === void 0 ? void 0 : _safeZoneAreaRef_current.updateSVG({
|
@@ -130,22 +111,17 @@ export function useSafeZoneArea({ debug = false, disabled = false, onSafeZoneEnt
|
|
130
111
|
targetRect: targetEl.getBoundingClientRect()
|
131
112
|
});
|
132
113
|
}
|
133
|
-
|
134
|
-
mouseMoveIdRef.current = targetWindow.requestAnimationFrame(updateSVGs);
|
135
|
-
}
|
114
|
+
requestUpdateFrame(updateSVGs);
|
136
115
|
}
|
137
116
|
updateSVGs();
|
138
117
|
return;
|
139
118
|
}
|
140
|
-
|
141
|
-
var _targetDocument_defaultView;
|
142
|
-
targetDocument === null || targetDocument === void 0 ? void 0 : (_targetDocument_defaultView = targetDocument.defaultView) === null || _targetDocument_defaultView === void 0 ? void 0 : _targetDocument_defaultView.cancelAnimationFrame(mouseMoveIdRef.current);
|
143
|
-
mouseMoveIdRef.current = null;
|
144
|
-
}
|
119
|
+
clearUpdateFrame();
|
145
120
|
});
|
146
121
|
}, [
|
147
|
-
|
148
|
-
|
122
|
+
clearUpdateFrame,
|
123
|
+
requestUpdateFrame,
|
124
|
+
stateStore
|
149
125
|
]);
|
150
126
|
return {
|
151
127
|
containerRef: useMergedRefs(containerRef, containerListenerRef),
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../src/hooks/useSafeZoneArea/useSafeZoneArea.tsx"],"sourcesContent":["import { useFluent_unstable } from '@fluentui/react-shared-contexts';\nimport { useEventCallback, useMergedRefs } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nimport { createSafeZoneAreaStateStore } from './createSafeZoneAreaStateStore';\nimport { type SafeZoneAreaImperativeHandle, SafeZoneArea } from './SafeZoneArea';\n\nexport type UseSafeZoneOptions = {\n /** Enables debug mode: makes drawn shapes visible. */\n debug?: boolean;\n\n /** Disables the safe zone area. */\n disabled?: boolean;\n\n /** The time in milliseconds to wait before clearing the safe zone. */\n timeout?: number;\n\n /** Called when the mouse enters the safe zone. */\n onSafeZoneEnter?: (e: React.MouseEvent) => void;\n\n /** Called when the mouse moves within the safe zone. */\n onSafeZoneMove?: (e: React.MouseEvent) => void;\n\n /** Called when the mouse leaves the safe zone. */\n onSafeZoneLeave?: (e: React.MouseEvent) => void;\n\n /** Called when the safe zone times out, even if a cursor is still over a safe zone. */\n onSafeZoneTimeout?: () => void;\n};\n\nexport function useSafeZoneArea({\n debug = false,\n disabled = false,\n\n onSafeZoneEnter,\n onSafeZoneMove,\n onSafeZoneLeave,\n onSafeZoneTimeout,\n\n timeout = 1500,\n}: UseSafeZoneOptions = {}) {\n const [stateStore] = React.useState(createSafeZoneAreaStateStore);\n const { targetDocument } = useFluent_unstable();\n\n const safeZoneAreaRef = React.useRef<SafeZoneAreaImperativeHandle>(null);\n const containerRef = React.useRef<HTMLElement>(null);\n const targetRef = React.useRef<HTMLElement>(null);\n\n const timeoutIdRef = React.useRef<number | null>(null);\n const mouseMoveIdRef = React.useRef<number | null>(null);\n\n const mouseCoordinatesRef = React.useRef<{ x: number; y: number }>({ x: 0, y: 0 });\n\n const containerListenerRef = React.useMemo(() => {\n if (disabled) {\n return () => {\n // do nothing\n };\n }\n\n let containerEl: HTMLElement | null = null;\n\n function onContainerMouseEnter() {\n const targetWindow = targetDocument?.defaultView;\n\n if (!targetWindow) {\n return;\n }\n\n if (timeoutIdRef.current) {\n targetWindow.clearTimeout(timeoutIdRef.current);\n timeoutIdRef.current = null;\n }\n\n stateStore.toggleActive(false);\n }\n\n return (el: HTMLElement | null) => {\n if (el === null) {\n containerEl?.removeEventListener('mouseenter', onContainerMouseEnter);\n }\n\n containerEl = el;\n el?.addEventListener('mouseenter', onContainerMouseEnter);\n };\n }, [disabled, stateStore, targetDocument]);\n\n const targetListenerRef = React.useMemo(() => {\n if (disabled) {\n return () => {\n // do nothing\n };\n }\n\n let targetEl: HTMLElement | null = null;\n\n function onTargetMouseMove(e: MouseEvent) {\n mouseCoordinatesRef.current = { x: e.clientX, y: e.clientY };\n\n if (timeoutIdRef.current) {\n targetDocument?.defaultView?.clearTimeout(timeoutIdRef.current);\n timeoutIdRef.current = null;\n }\n\n if (!stateStore.isActive()) {\n stateStore.toggleActive(true);\n }\n }\n\n return (el: HTMLElement | null) => {\n if (el === null) {\n const targetWindow = targetDocument?.defaultView;\n\n if (targetWindow) {\n if (mouseMoveIdRef.current) {\n targetWindow.cancelAnimationFrame(mouseMoveIdRef.current);\n mouseMoveIdRef.current = null;\n }\n\n if (timeoutIdRef.current) {\n targetWindow.clearTimeout(timeoutIdRef.current);\n timeoutIdRef.current = null;\n }\n }\n\n targetEl?.removeEventListener('mousemove', onTargetMouseMove);\n }\n\n targetEl = el;\n el?.addEventListener('mousemove', onTargetMouseMove);\n };\n }, [disabled, stateStore, targetDocument]);\n\n const onSvgMouseEnter = useEventCallback((e: React.MouseEvent) => {\n onSafeZoneEnter?.(e);\n\n const targetWindow = targetDocument?.defaultView;\n\n if (!targetWindow) {\n return;\n }\n\n if (timeoutIdRef.current) {\n targetWindow.clearTimeout(timeoutIdRef.current);\n timeoutIdRef.current = null;\n }\n\n // React 17 still uses pooled synthetic events\n e.persist();\n\n timeoutIdRef.current = targetWindow.setTimeout(() => {\n stateStore.toggleActive(false);\n onSafeZoneTimeout?.();\n }, timeout);\n });\n\n const onSvgMouseMove = useEventCallback((e: React.MouseEvent) => {\n onSafeZoneMove?.(e);\n });\n\n const onSvgMouseLeave = useEventCallback((e: React.MouseEvent) => {\n onSafeZoneLeave?.(e);\n });\n\n React.useEffect(() => {\n return stateStore.subscribe(isActive => {\n if (isActive) {\n function updateSVGs() {\n const containerEl = containerRef.current;\n const targetEl = targetRef.current;\n const targetWindow = targetDocument?.defaultView;\n\n if (containerEl && targetEl) {\n safeZoneAreaRef.current?.updateSVG({\n containerRect: containerEl.getBoundingClientRect(),\n mouseCoordinates: [mouseCoordinatesRef.current.x, mouseCoordinatesRef.current.y],\n targetRect: targetEl.getBoundingClientRect(),\n });\n }\n\n if (targetWindow) {\n mouseMoveIdRef.current = targetWindow.requestAnimationFrame(updateSVGs);\n }\n }\n\n updateSVGs();\n return;\n }\n\n if (mouseMoveIdRef.current) {\n targetDocument?.defaultView?.cancelAnimationFrame(mouseMoveIdRef.current);\n mouseMoveIdRef.current = null;\n }\n });\n }, [stateStore, targetDocument]);\n\n return {\n containerRef: useMergedRefs(containerRef, containerListenerRef),\n targetRef: useMergedRefs(targetRef, targetListenerRef),\n\n elementToRender: React.useMemo(\n () =>\n disabled ? null : (\n <SafeZoneArea\n debug={debug}\n onMouseEnter={onSvgMouseEnter}\n onMouseMove={onSvgMouseMove}\n onMouseLeave={onSvgMouseLeave}\n imperativeRef={safeZoneAreaRef}\n stateStore={stateStore}\n />\n ),\n [disabled, debug, onSvgMouseEnter, onSvgMouseMove, onSvgMouseLeave, stateStore],\n ),\n };\n}\n"],"names":["useFluent_unstable","useEventCallback","useMergedRefs","React","createSafeZoneAreaStateStore","SafeZoneArea","useSafeZoneArea","debug","disabled","onSafeZoneEnter","onSafeZoneMove","onSafeZoneLeave","onSafeZoneTimeout","timeout","stateStore","useState","targetDocument","safeZoneAreaRef","useRef","containerRef","targetRef","timeoutIdRef","mouseMoveIdRef","mouseCoordinatesRef","x","y","containerListenerRef","useMemo","containerEl","onContainerMouseEnter","targetWindow","defaultView","current","clearTimeout","toggleActive","el","removeEventListener","addEventListener","targetListenerRef","targetEl","onTargetMouseMove","e","clientX","clientY","isActive","cancelAnimationFrame","onSvgMouseEnter","persist","setTimeout","onSvgMouseMove","onSvgMouseLeave","useEffect","subscribe","updateSVGs","updateSVG","containerRect","getBoundingClientRect","mouseCoordinates","targetRect","requestAnimationFrame","elementToRender","onMouseEnter","onMouseMove","onMouseLeave","imperativeRef"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
1
|
+
{"version":3,"sources":["../src/hooks/useSafeZoneArea/useSafeZoneArea.tsx"],"sourcesContent":["import { useAnimationFrame, useEventCallback, useMergedRefs, useTimeout } from '@fluentui/react-utilities';\nimport type { RefObjectFunction } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nimport { createSafeZoneAreaStateStore } from './createSafeZoneAreaStateStore';\nimport { type SafeZoneAreaImperativeHandle, SafeZoneArea } from './SafeZoneArea';\n\nexport type UseSafeZoneOptions = {\n /** Enables debug mode: makes drawn shapes visible. */\n debug?: boolean;\n\n /** Disables the safe zone area. */\n disabled?: boolean;\n\n /** The time in milliseconds to wait before clearing the safe zone. */\n timeout?: number;\n\n /** Called when the mouse enters the safe zone. */\n onSafeZoneEnter?: (e: React.MouseEvent) => void;\n\n /** Called when the mouse moves within the safe zone. */\n onSafeZoneMove?: (e: React.MouseEvent) => void;\n\n /** Called when the mouse leaves the safe zone. */\n onSafeZoneLeave?: (e: React.MouseEvent) => void;\n\n /** Called when the safe zone times out, even if a cursor is still over a safe zone. */\n onSafeZoneTimeout?: () => void;\n};\n\n/**\n * Time in milliseconds after which the safe zone area will be cleared if no mouse movement is detected.\n *\n * Only affects the target element, not the safe zone area itself.\n */\nconst MOUSE_MOVE_TARGET_POLLING_TIMEOUT = 2000;\n\n// ---\n\nexport function useSafeZoneArea({\n debug = false,\n disabled = false,\n\n onSafeZoneEnter,\n onSafeZoneMove,\n onSafeZoneLeave,\n onSafeZoneTimeout,\n\n timeout = 1500,\n}: UseSafeZoneOptions = {}): {\n containerRef: RefObjectFunction<HTMLElement>;\n targetRef: RefObjectFunction<HTMLElement>;\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n elementToRender: JSX.Element | null;\n} {\n const [stateStore] = React.useState(createSafeZoneAreaStateStore);\n\n const safeZoneAreaRef = React.useRef<SafeZoneAreaImperativeHandle>(null);\n const containerRef = React.useRef<HTMLElement>(null);\n const targetRef = React.useRef<HTMLElement>(null);\n\n const [setSafeZoneCloseTimeout, clearSafeZoneCloseTimeout] = useTimeout();\n const [requestUpdateFrame, clearUpdateFrame] = useAnimationFrame();\n\n const mouseCoordinatesRef = React.useRef<{ x: number; y: number }>({ x: 0, y: 0 });\n\n const containerListenerRef = React.useMemo(() => {\n if (disabled) {\n return () => {\n // do nothing\n };\n }\n\n let containerEl: HTMLElement | null = null;\n\n function onContainerMouseEnter() {\n clearSafeZoneCloseTimeout();\n stateStore.toggleActive(false);\n }\n\n return (el: HTMLElement | null) => {\n if (el === null) {\n containerEl?.removeEventListener('mouseenter', onContainerMouseEnter);\n }\n\n containerEl = el;\n el?.addEventListener('mouseenter', onContainerMouseEnter);\n };\n }, [clearSafeZoneCloseTimeout, disabled, stateStore]);\n\n const targetListenerRef = React.useMemo(() => {\n if (disabled) {\n return () => {\n // do nothing\n };\n }\n\n let targetEl: HTMLElement | null = null;\n\n function onTargetMouseMove(e: MouseEvent) {\n mouseCoordinatesRef.current = { x: e.clientX, y: e.clientY };\n\n if (!stateStore.isActive()) {\n stateStore.toggleActive(true);\n }\n\n setSafeZoneCloseTimeout(() => {\n stateStore.toggleActive(false);\n }, MOUSE_MOVE_TARGET_POLLING_TIMEOUT);\n }\n\n return (el: HTMLElement | null) => {\n if (el === null) {\n clearUpdateFrame();\n clearSafeZoneCloseTimeout();\n\n targetEl?.removeEventListener('mousemove', onTargetMouseMove);\n }\n\n targetEl = el;\n el?.addEventListener('mousemove', onTargetMouseMove);\n };\n }, [clearUpdateFrame, clearSafeZoneCloseTimeout, disabled, stateStore, setSafeZoneCloseTimeout]);\n\n const onSvgMouseEnter = useEventCallback((e: React.MouseEvent) => {\n onSafeZoneEnter?.(e);\n\n setSafeZoneCloseTimeout(() => {\n stateStore.toggleActive(false);\n onSafeZoneTimeout?.();\n }, timeout);\n });\n\n const onSvgMouseMove = useEventCallback((e: React.MouseEvent) => {\n setSafeZoneCloseTimeout(() => {\n stateStore.toggleActive(false);\n onSafeZoneTimeout?.();\n }, timeout);\n onSafeZoneMove?.(e);\n });\n\n const onSvgMouseLeave = useEventCallback((e: React.MouseEvent) => {\n onSafeZoneLeave?.(e);\n });\n\n React.useEffect(() => {\n return stateStore.subscribe(isActive => {\n if (isActive) {\n function updateSVGs() {\n const containerEl = containerRef.current;\n const targetEl = targetRef.current;\n\n if (containerEl && targetEl) {\n safeZoneAreaRef.current?.updateSVG({\n containerRect: containerEl.getBoundingClientRect(),\n mouseCoordinates: [mouseCoordinatesRef.current.x, mouseCoordinatesRef.current.y],\n targetRect: targetEl.getBoundingClientRect(),\n });\n }\n\n requestUpdateFrame(updateSVGs);\n }\n\n updateSVGs();\n return;\n }\n\n clearUpdateFrame();\n });\n }, [clearUpdateFrame, requestUpdateFrame, stateStore]);\n\n return {\n containerRef: useMergedRefs(containerRef, containerListenerRef),\n targetRef: useMergedRefs(targetRef, targetListenerRef),\n\n elementToRender: React.useMemo(\n () =>\n disabled ? null : (\n <SafeZoneArea\n debug={debug}\n onMouseEnter={onSvgMouseEnter}\n onMouseMove={onSvgMouseMove}\n onMouseLeave={onSvgMouseLeave}\n imperativeRef={safeZoneAreaRef}\n stateStore={stateStore}\n />\n ),\n [disabled, debug, onSvgMouseEnter, onSvgMouseMove, onSvgMouseLeave, stateStore],\n ),\n };\n}\n"],"names":["useAnimationFrame","useEventCallback","useMergedRefs","useTimeout","React","createSafeZoneAreaStateStore","SafeZoneArea","MOUSE_MOVE_TARGET_POLLING_TIMEOUT","useSafeZoneArea","debug","disabled","onSafeZoneEnter","onSafeZoneMove","onSafeZoneLeave","onSafeZoneTimeout","timeout","stateStore","useState","safeZoneAreaRef","useRef","containerRef","targetRef","setSafeZoneCloseTimeout","clearSafeZoneCloseTimeout","requestUpdateFrame","clearUpdateFrame","mouseCoordinatesRef","x","y","containerListenerRef","useMemo","containerEl","onContainerMouseEnter","toggleActive","el","removeEventListener","addEventListener","targetListenerRef","targetEl","onTargetMouseMove","e","current","clientX","clientY","isActive","onSvgMouseEnter","onSvgMouseMove","onSvgMouseLeave","useEffect","subscribe","updateSVGs","updateSVG","containerRect","getBoundingClientRect","mouseCoordinates","targetRect","elementToRender","onMouseEnter","onMouseMove","onMouseLeave","imperativeRef"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
@@ -9,19 +9,22 @@ Object.defineProperty(exports, "useSafeZoneArea", {
|
|
9
9
|
}
|
10
10
|
});
|
11
11
|
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
|
12
|
-
const _reactsharedcontexts = require("@fluentui/react-shared-contexts");
|
13
12
|
const _reactutilities = require("@fluentui/react-utilities");
|
14
13
|
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
|
15
14
|
const _createSafeZoneAreaStateStore = require("./createSafeZoneAreaStateStore");
|
16
15
|
const _SafeZoneArea = require("./SafeZoneArea");
|
16
|
+
/**
|
17
|
+
* Time in milliseconds after which the safe zone area will be cleared if no mouse movement is detected.
|
18
|
+
*
|
19
|
+
* Only affects the target element, not the safe zone area itself.
|
20
|
+
*/ const MOUSE_MOVE_TARGET_POLLING_TIMEOUT = 2000;
|
17
21
|
function useSafeZoneArea({ debug = false, disabled = false, onSafeZoneEnter, onSafeZoneMove, onSafeZoneLeave, onSafeZoneTimeout, timeout = 1500 } = {}) {
|
18
22
|
const [stateStore] = _react.useState(_createSafeZoneAreaStateStore.createSafeZoneAreaStateStore);
|
19
|
-
const { targetDocument } = (0, _reactsharedcontexts.useFluent_unstable)();
|
20
23
|
const safeZoneAreaRef = _react.useRef(null);
|
21
24
|
const containerRef = _react.useRef(null);
|
22
25
|
const targetRef = _react.useRef(null);
|
23
|
-
const
|
24
|
-
const
|
26
|
+
const [setSafeZoneCloseTimeout, clearSafeZoneCloseTimeout] = (0, _reactutilities.useTimeout)();
|
27
|
+
const [requestUpdateFrame, clearUpdateFrame] = (0, _reactutilities.useAnimationFrame)();
|
25
28
|
const mouseCoordinatesRef = _react.useRef({
|
26
29
|
x: 0,
|
27
30
|
y: 0
|
@@ -34,14 +37,7 @@ function useSafeZoneArea({ debug = false, disabled = false, onSafeZoneEnter, onS
|
|
34
37
|
}
|
35
38
|
let containerEl = null;
|
36
39
|
function onContainerMouseEnter() {
|
37
|
-
|
38
|
-
if (!targetWindow) {
|
39
|
-
return;
|
40
|
-
}
|
41
|
-
if (timeoutIdRef.current) {
|
42
|
-
targetWindow.clearTimeout(timeoutIdRef.current);
|
43
|
-
timeoutIdRef.current = null;
|
44
|
-
}
|
40
|
+
clearSafeZoneCloseTimeout();
|
45
41
|
stateStore.toggleActive(false);
|
46
42
|
}
|
47
43
|
return (el)=>{
|
@@ -52,9 +48,9 @@ function useSafeZoneArea({ debug = false, disabled = false, onSafeZoneEnter, onS
|
|
52
48
|
el === null || el === void 0 ? void 0 : el.addEventListener('mouseenter', onContainerMouseEnter);
|
53
49
|
};
|
54
50
|
}, [
|
51
|
+
clearSafeZoneCloseTimeout,
|
55
52
|
disabled,
|
56
|
-
stateStore
|
57
|
-
targetDocument
|
53
|
+
stateStore
|
58
54
|
]);
|
59
55
|
const targetListenerRef = _react.useMemo(()=>{
|
60
56
|
if (disabled) {
|
@@ -68,56 +64,41 @@ function useSafeZoneArea({ debug = false, disabled = false, onSafeZoneEnter, onS
|
|
68
64
|
x: e.clientX,
|
69
65
|
y: e.clientY
|
70
66
|
};
|
71
|
-
if (timeoutIdRef.current) {
|
72
|
-
var _targetDocument_defaultView;
|
73
|
-
targetDocument === null || targetDocument === void 0 ? void 0 : (_targetDocument_defaultView = targetDocument.defaultView) === null || _targetDocument_defaultView === void 0 ? void 0 : _targetDocument_defaultView.clearTimeout(timeoutIdRef.current);
|
74
|
-
timeoutIdRef.current = null;
|
75
|
-
}
|
76
67
|
if (!stateStore.isActive()) {
|
77
68
|
stateStore.toggleActive(true);
|
78
69
|
}
|
70
|
+
setSafeZoneCloseTimeout(()=>{
|
71
|
+
stateStore.toggleActive(false);
|
72
|
+
}, MOUSE_MOVE_TARGET_POLLING_TIMEOUT);
|
79
73
|
}
|
80
74
|
return (el)=>{
|
81
75
|
if (el === null) {
|
82
|
-
|
83
|
-
|
84
|
-
if (mouseMoveIdRef.current) {
|
85
|
-
targetWindow.cancelAnimationFrame(mouseMoveIdRef.current);
|
86
|
-
mouseMoveIdRef.current = null;
|
87
|
-
}
|
88
|
-
if (timeoutIdRef.current) {
|
89
|
-
targetWindow.clearTimeout(timeoutIdRef.current);
|
90
|
-
timeoutIdRef.current = null;
|
91
|
-
}
|
92
|
-
}
|
76
|
+
clearUpdateFrame();
|
77
|
+
clearSafeZoneCloseTimeout();
|
93
78
|
targetEl === null || targetEl === void 0 ? void 0 : targetEl.removeEventListener('mousemove', onTargetMouseMove);
|
94
79
|
}
|
95
80
|
targetEl = el;
|
96
81
|
el === null || el === void 0 ? void 0 : el.addEventListener('mousemove', onTargetMouseMove);
|
97
82
|
};
|
98
83
|
}, [
|
84
|
+
clearUpdateFrame,
|
85
|
+
clearSafeZoneCloseTimeout,
|
99
86
|
disabled,
|
100
87
|
stateStore,
|
101
|
-
|
88
|
+
setSafeZoneCloseTimeout
|
102
89
|
]);
|
103
90
|
const onSvgMouseEnter = (0, _reactutilities.useEventCallback)((e)=>{
|
104
91
|
onSafeZoneEnter === null || onSafeZoneEnter === void 0 ? void 0 : onSafeZoneEnter(e);
|
105
|
-
|
106
|
-
if (!targetWindow) {
|
107
|
-
return;
|
108
|
-
}
|
109
|
-
if (timeoutIdRef.current) {
|
110
|
-
targetWindow.clearTimeout(timeoutIdRef.current);
|
111
|
-
timeoutIdRef.current = null;
|
112
|
-
}
|
113
|
-
// React 17 still uses pooled synthetic events
|
114
|
-
e.persist();
|
115
|
-
timeoutIdRef.current = targetWindow.setTimeout(()=>{
|
92
|
+
setSafeZoneCloseTimeout(()=>{
|
116
93
|
stateStore.toggleActive(false);
|
117
94
|
onSafeZoneTimeout === null || onSafeZoneTimeout === void 0 ? void 0 : onSafeZoneTimeout();
|
118
95
|
}, timeout);
|
119
96
|
});
|
120
97
|
const onSvgMouseMove = (0, _reactutilities.useEventCallback)((e)=>{
|
98
|
+
setSafeZoneCloseTimeout(()=>{
|
99
|
+
stateStore.toggleActive(false);
|
100
|
+
onSafeZoneTimeout === null || onSafeZoneTimeout === void 0 ? void 0 : onSafeZoneTimeout();
|
101
|
+
}, timeout);
|
121
102
|
onSafeZoneMove === null || onSafeZoneMove === void 0 ? void 0 : onSafeZoneMove(e);
|
122
103
|
});
|
123
104
|
const onSvgMouseLeave = (0, _reactutilities.useEventCallback)((e)=>{
|
@@ -129,7 +110,6 @@ function useSafeZoneArea({ debug = false, disabled = false, onSafeZoneEnter, onS
|
|
129
110
|
function updateSVGs() {
|
130
111
|
const containerEl = containerRef.current;
|
131
112
|
const targetEl = targetRef.current;
|
132
|
-
const targetWindow = targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.defaultView;
|
133
113
|
if (containerEl && targetEl) {
|
134
114
|
var _safeZoneAreaRef_current;
|
135
115
|
(_safeZoneAreaRef_current = safeZoneAreaRef.current) === null || _safeZoneAreaRef_current === void 0 ? void 0 : _safeZoneAreaRef_current.updateSVG({
|
@@ -141,22 +121,17 @@ function useSafeZoneArea({ debug = false, disabled = false, onSafeZoneEnter, onS
|
|
141
121
|
targetRect: targetEl.getBoundingClientRect()
|
142
122
|
});
|
143
123
|
}
|
144
|
-
|
145
|
-
mouseMoveIdRef.current = targetWindow.requestAnimationFrame(updateSVGs);
|
146
|
-
}
|
124
|
+
requestUpdateFrame(updateSVGs);
|
147
125
|
}
|
148
126
|
updateSVGs();
|
149
127
|
return;
|
150
128
|
}
|
151
|
-
|
152
|
-
var _targetDocument_defaultView;
|
153
|
-
targetDocument === null || targetDocument === void 0 ? void 0 : (_targetDocument_defaultView = targetDocument.defaultView) === null || _targetDocument_defaultView === void 0 ? void 0 : _targetDocument_defaultView.cancelAnimationFrame(mouseMoveIdRef.current);
|
154
|
-
mouseMoveIdRef.current = null;
|
155
|
-
}
|
129
|
+
clearUpdateFrame();
|
156
130
|
});
|
157
131
|
}, [
|
158
|
-
|
159
|
-
|
132
|
+
clearUpdateFrame,
|
133
|
+
requestUpdateFrame,
|
134
|
+
stateStore
|
160
135
|
]);
|
161
136
|
return {
|
162
137
|
containerRef: (0, _reactutilities.useMergedRefs)(containerRef, containerListenerRef),
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../src/hooks/useSafeZoneArea/useSafeZoneArea.tsx"],"sourcesContent":["import { useFluent_unstable } from '@fluentui/react-shared-contexts';\nimport { useEventCallback, useMergedRefs } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nimport { createSafeZoneAreaStateStore } from './createSafeZoneAreaStateStore';\nimport { type SafeZoneAreaImperativeHandle, SafeZoneArea } from './SafeZoneArea';\n\nexport type UseSafeZoneOptions = {\n /** Enables debug mode: makes drawn shapes visible. */\n debug?: boolean;\n\n /** Disables the safe zone area. */\n disabled?: boolean;\n\n /** The time in milliseconds to wait before clearing the safe zone. */\n timeout?: number;\n\n /** Called when the mouse enters the safe zone. */\n onSafeZoneEnter?: (e: React.MouseEvent) => void;\n\n /** Called when the mouse moves within the safe zone. */\n onSafeZoneMove?: (e: React.MouseEvent) => void;\n\n /** Called when the mouse leaves the safe zone. */\n onSafeZoneLeave?: (e: React.MouseEvent) => void;\n\n /** Called when the safe zone times out, even if a cursor is still over a safe zone. */\n onSafeZoneTimeout?: () => void;\n};\n\nexport function useSafeZoneArea({\n debug = false,\n disabled = false,\n\n onSafeZoneEnter,\n onSafeZoneMove,\n onSafeZoneLeave,\n onSafeZoneTimeout,\n\n timeout = 1500,\n}: UseSafeZoneOptions = {}) {\n const [stateStore] = React.useState(createSafeZoneAreaStateStore);\n const { targetDocument } = useFluent_unstable();\n\n const safeZoneAreaRef = React.useRef<SafeZoneAreaImperativeHandle>(null);\n const containerRef = React.useRef<HTMLElement>(null);\n const targetRef = React.useRef<HTMLElement>(null);\n\n const timeoutIdRef = React.useRef<number | null>(null);\n const mouseMoveIdRef = React.useRef<number | null>(null);\n\n const mouseCoordinatesRef = React.useRef<{ x: number; y: number }>({ x: 0, y: 0 });\n\n const containerListenerRef = React.useMemo(() => {\n if (disabled) {\n return () => {\n // do nothing\n };\n }\n\n let containerEl: HTMLElement | null = null;\n\n function onContainerMouseEnter() {\n const targetWindow = targetDocument?.defaultView;\n\n if (!targetWindow) {\n return;\n }\n\n if (timeoutIdRef.current) {\n targetWindow.clearTimeout(timeoutIdRef.current);\n timeoutIdRef.current = null;\n }\n\n stateStore.toggleActive(false);\n }\n\n return (el: HTMLElement | null) => {\n if (el === null) {\n containerEl?.removeEventListener('mouseenter', onContainerMouseEnter);\n }\n\n containerEl = el;\n el?.addEventListener('mouseenter', onContainerMouseEnter);\n };\n }, [disabled, stateStore, targetDocument]);\n\n const targetListenerRef = React.useMemo(() => {\n if (disabled) {\n return () => {\n // do nothing\n };\n }\n\n let targetEl: HTMLElement | null = null;\n\n function onTargetMouseMove(e: MouseEvent) {\n mouseCoordinatesRef.current = { x: e.clientX, y: e.clientY };\n\n if (timeoutIdRef.current) {\n targetDocument?.defaultView?.clearTimeout(timeoutIdRef.current);\n timeoutIdRef.current = null;\n }\n\n if (!stateStore.isActive()) {\n stateStore.toggleActive(true);\n }\n }\n\n return (el: HTMLElement | null) => {\n if (el === null) {\n const targetWindow = targetDocument?.defaultView;\n\n if (targetWindow) {\n if (mouseMoveIdRef.current) {\n targetWindow.cancelAnimationFrame(mouseMoveIdRef.current);\n mouseMoveIdRef.current = null;\n }\n\n if (timeoutIdRef.current) {\n targetWindow.clearTimeout(timeoutIdRef.current);\n timeoutIdRef.current = null;\n }\n }\n\n targetEl?.removeEventListener('mousemove', onTargetMouseMove);\n }\n\n targetEl = el;\n el?.addEventListener('mousemove', onTargetMouseMove);\n };\n }, [disabled, stateStore, targetDocument]);\n\n const onSvgMouseEnter = useEventCallback((e: React.MouseEvent) => {\n onSafeZoneEnter?.(e);\n\n const targetWindow = targetDocument?.defaultView;\n\n if (!targetWindow) {\n return;\n }\n\n if (timeoutIdRef.current) {\n targetWindow.clearTimeout(timeoutIdRef.current);\n timeoutIdRef.current = null;\n }\n\n // React 17 still uses pooled synthetic events\n e.persist();\n\n timeoutIdRef.current = targetWindow.setTimeout(() => {\n stateStore.toggleActive(false);\n onSafeZoneTimeout?.();\n }, timeout);\n });\n\n const onSvgMouseMove = useEventCallback((e: React.MouseEvent) => {\n onSafeZoneMove?.(e);\n });\n\n const onSvgMouseLeave = useEventCallback((e: React.MouseEvent) => {\n onSafeZoneLeave?.(e);\n });\n\n React.useEffect(() => {\n return stateStore.subscribe(isActive => {\n if (isActive) {\n function updateSVGs() {\n const containerEl = containerRef.current;\n const targetEl = targetRef.current;\n const targetWindow = targetDocument?.defaultView;\n\n if (containerEl && targetEl) {\n safeZoneAreaRef.current?.updateSVG({\n containerRect: containerEl.getBoundingClientRect(),\n mouseCoordinates: [mouseCoordinatesRef.current.x, mouseCoordinatesRef.current.y],\n targetRect: targetEl.getBoundingClientRect(),\n });\n }\n\n if (targetWindow) {\n mouseMoveIdRef.current = targetWindow.requestAnimationFrame(updateSVGs);\n }\n }\n\n updateSVGs();\n return;\n }\n\n if (mouseMoveIdRef.current) {\n targetDocument?.defaultView?.cancelAnimationFrame(mouseMoveIdRef.current);\n mouseMoveIdRef.current = null;\n }\n });\n }, [stateStore, targetDocument]);\n\n return {\n containerRef: useMergedRefs(containerRef, containerListenerRef),\n targetRef: useMergedRefs(targetRef, targetListenerRef),\n\n elementToRender: React.useMemo(\n () =>\n disabled ? null : (\n <SafeZoneArea\n debug={debug}\n onMouseEnter={onSvgMouseEnter}\n onMouseMove={onSvgMouseMove}\n onMouseLeave={onSvgMouseLeave}\n imperativeRef={safeZoneAreaRef}\n stateStore={stateStore}\n />\n ),\n [disabled, debug, onSvgMouseEnter, onSvgMouseMove, onSvgMouseLeave, stateStore],\n ),\n };\n}\n"],"names":["useSafeZoneArea","debug","disabled","onSafeZoneEnter","onSafeZoneMove","onSafeZoneLeave","onSafeZoneTimeout","timeout","stateStore","React","useState","createSafeZoneAreaStateStore","targetDocument","useFluent_unstable","safeZoneAreaRef","useRef","containerRef","targetRef","timeoutIdRef","mouseMoveIdRef","mouseCoordinatesRef","x","y","containerListenerRef","useMemo","containerEl","onContainerMouseEnter","targetWindow","defaultView","current","clearTimeout","toggleActive","el","removeEventListener","addEventListener","targetListenerRef","targetEl","onTargetMouseMove","e","clientX","clientY","isActive","cancelAnimationFrame","onSvgMouseEnter","useEventCallback","persist","setTimeout","onSvgMouseMove","onSvgMouseLeave","useEffect","subscribe","updateSVGs","updateSVG","containerRect","getBoundingClientRect","mouseCoordinates","targetRect","requestAnimationFrame","useMergedRefs","elementToRender","createElement","SafeZoneArea","onMouseEnter","onMouseMove","onMouseLeave","imperativeRef"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
1
|
+
{"version":3,"sources":["../src/hooks/useSafeZoneArea/useSafeZoneArea.tsx"],"sourcesContent":["import { useAnimationFrame, useEventCallback, useMergedRefs, useTimeout } from '@fluentui/react-utilities';\nimport type { RefObjectFunction } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nimport { createSafeZoneAreaStateStore } from './createSafeZoneAreaStateStore';\nimport { type SafeZoneAreaImperativeHandle, SafeZoneArea } from './SafeZoneArea';\n\nexport type UseSafeZoneOptions = {\n /** Enables debug mode: makes drawn shapes visible. */\n debug?: boolean;\n\n /** Disables the safe zone area. */\n disabled?: boolean;\n\n /** The time in milliseconds to wait before clearing the safe zone. */\n timeout?: number;\n\n /** Called when the mouse enters the safe zone. */\n onSafeZoneEnter?: (e: React.MouseEvent) => void;\n\n /** Called when the mouse moves within the safe zone. */\n onSafeZoneMove?: (e: React.MouseEvent) => void;\n\n /** Called when the mouse leaves the safe zone. */\n onSafeZoneLeave?: (e: React.MouseEvent) => void;\n\n /** Called when the safe zone times out, even if a cursor is still over a safe zone. */\n onSafeZoneTimeout?: () => void;\n};\n\n/**\n * Time in milliseconds after which the safe zone area will be cleared if no mouse movement is detected.\n *\n * Only affects the target element, not the safe zone area itself.\n */\nconst MOUSE_MOVE_TARGET_POLLING_TIMEOUT = 2000;\n\n// ---\n\nexport function useSafeZoneArea({\n debug = false,\n disabled = false,\n\n onSafeZoneEnter,\n onSafeZoneMove,\n onSafeZoneLeave,\n onSafeZoneTimeout,\n\n timeout = 1500,\n}: UseSafeZoneOptions = {}): {\n containerRef: RefObjectFunction<HTMLElement>;\n targetRef: RefObjectFunction<HTMLElement>;\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n elementToRender: JSX.Element | null;\n} {\n const [stateStore] = React.useState(createSafeZoneAreaStateStore);\n\n const safeZoneAreaRef = React.useRef<SafeZoneAreaImperativeHandle>(null);\n const containerRef = React.useRef<HTMLElement>(null);\n const targetRef = React.useRef<HTMLElement>(null);\n\n const [setSafeZoneCloseTimeout, clearSafeZoneCloseTimeout] = useTimeout();\n const [requestUpdateFrame, clearUpdateFrame] = useAnimationFrame();\n\n const mouseCoordinatesRef = React.useRef<{ x: number; y: number }>({ x: 0, y: 0 });\n\n const containerListenerRef = React.useMemo(() => {\n if (disabled) {\n return () => {\n // do nothing\n };\n }\n\n let containerEl: HTMLElement | null = null;\n\n function onContainerMouseEnter() {\n clearSafeZoneCloseTimeout();\n stateStore.toggleActive(false);\n }\n\n return (el: HTMLElement | null) => {\n if (el === null) {\n containerEl?.removeEventListener('mouseenter', onContainerMouseEnter);\n }\n\n containerEl = el;\n el?.addEventListener('mouseenter', onContainerMouseEnter);\n };\n }, [clearSafeZoneCloseTimeout, disabled, stateStore]);\n\n const targetListenerRef = React.useMemo(() => {\n if (disabled) {\n return () => {\n // do nothing\n };\n }\n\n let targetEl: HTMLElement | null = null;\n\n function onTargetMouseMove(e: MouseEvent) {\n mouseCoordinatesRef.current = { x: e.clientX, y: e.clientY };\n\n if (!stateStore.isActive()) {\n stateStore.toggleActive(true);\n }\n\n setSafeZoneCloseTimeout(() => {\n stateStore.toggleActive(false);\n }, MOUSE_MOVE_TARGET_POLLING_TIMEOUT);\n }\n\n return (el: HTMLElement | null) => {\n if (el === null) {\n clearUpdateFrame();\n clearSafeZoneCloseTimeout();\n\n targetEl?.removeEventListener('mousemove', onTargetMouseMove);\n }\n\n targetEl = el;\n el?.addEventListener('mousemove', onTargetMouseMove);\n };\n }, [clearUpdateFrame, clearSafeZoneCloseTimeout, disabled, stateStore, setSafeZoneCloseTimeout]);\n\n const onSvgMouseEnter = useEventCallback((e: React.MouseEvent) => {\n onSafeZoneEnter?.(e);\n\n setSafeZoneCloseTimeout(() => {\n stateStore.toggleActive(false);\n onSafeZoneTimeout?.();\n }, timeout);\n });\n\n const onSvgMouseMove = useEventCallback((e: React.MouseEvent) => {\n setSafeZoneCloseTimeout(() => {\n stateStore.toggleActive(false);\n onSafeZoneTimeout?.();\n }, timeout);\n onSafeZoneMove?.(e);\n });\n\n const onSvgMouseLeave = useEventCallback((e: React.MouseEvent) => {\n onSafeZoneLeave?.(e);\n });\n\n React.useEffect(() => {\n return stateStore.subscribe(isActive => {\n if (isActive) {\n function updateSVGs() {\n const containerEl = containerRef.current;\n const targetEl = targetRef.current;\n\n if (containerEl && targetEl) {\n safeZoneAreaRef.current?.updateSVG({\n containerRect: containerEl.getBoundingClientRect(),\n mouseCoordinates: [mouseCoordinatesRef.current.x, mouseCoordinatesRef.current.y],\n targetRect: targetEl.getBoundingClientRect(),\n });\n }\n\n requestUpdateFrame(updateSVGs);\n }\n\n updateSVGs();\n return;\n }\n\n clearUpdateFrame();\n });\n }, [clearUpdateFrame, requestUpdateFrame, stateStore]);\n\n return {\n containerRef: useMergedRefs(containerRef, containerListenerRef),\n targetRef: useMergedRefs(targetRef, targetListenerRef),\n\n elementToRender: React.useMemo(\n () =>\n disabled ? null : (\n <SafeZoneArea\n debug={debug}\n onMouseEnter={onSvgMouseEnter}\n onMouseMove={onSvgMouseMove}\n onMouseLeave={onSvgMouseLeave}\n imperativeRef={safeZoneAreaRef}\n stateStore={stateStore}\n />\n ),\n [disabled, debug, onSvgMouseEnter, onSvgMouseMove, onSvgMouseLeave, stateStore],\n ),\n };\n}\n"],"names":["useSafeZoneArea","MOUSE_MOVE_TARGET_POLLING_TIMEOUT","debug","disabled","onSafeZoneEnter","onSafeZoneMove","onSafeZoneLeave","onSafeZoneTimeout","timeout","stateStore","React","useState","createSafeZoneAreaStateStore","safeZoneAreaRef","useRef","containerRef","targetRef","setSafeZoneCloseTimeout","clearSafeZoneCloseTimeout","useTimeout","requestUpdateFrame","clearUpdateFrame","useAnimationFrame","mouseCoordinatesRef","x","y","containerListenerRef","useMemo","containerEl","onContainerMouseEnter","toggleActive","el","removeEventListener","addEventListener","targetListenerRef","targetEl","onTargetMouseMove","e","current","clientX","clientY","isActive","onSvgMouseEnter","useEventCallback","onSvgMouseMove","onSvgMouseLeave","useEffect","subscribe","updateSVGs","updateSVG","containerRect","getBoundingClientRect","mouseCoordinates","targetRect","useMergedRefs","elementToRender","createElement","SafeZoneArea","onMouseEnter","onMouseMove","onMouseLeave","imperativeRef"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|