@agent-native/toolkit 0.224.0 → 0.225.0-nightly-20261105110131
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/dist/app/review/ReviewCommentComposer.d.ts.map +1 -1
- package/dist/app/review/ReviewCommentComposer.js +3 -5
- package/dist/app/review/ReviewCommentComposer.js.map +1 -1
- package/dist/composer/MentionPopover.d.ts +7 -0
- package/dist/composer/MentionPopover.d.ts.map +1 -1
- package/dist/composer/MentionPopover.js +4 -2
- package/dist/composer/MentionPopover.js.map +1 -1
- package/dist/composer/TiptapComposer.d.ts +6 -0
- package/dist/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/composer/TiptapComposer.js +12 -2
- package/dist/composer/TiptapComposer.js.map +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/use-focus-within-through-press.d.ts +19 -0
- package/dist/hooks/use-focus-within-through-press.d.ts.map +1 -0
- package/dist/hooks/use-focus-within-through-press.js +82 -0
- package/dist/hooks/use-focus-within-through-press.js.map +1 -0
- package/package.json +4 -4
- package/src/app/review/ReviewCommentComposer.spec.tsx +40 -0
- package/src/app/review/ReviewCommentComposer.tsx +3 -6
- package/src/composer/MentionPopover.spec.tsx +76 -0
- package/src/composer/MentionPopover.tsx +11 -1
- package/src/composer/TiptapComposer.spec.ts +32 -0
- package/src/composer/TiptapComposer.tsx +16 -3
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-focus-within-through-press.spec.tsx +208 -0
- package/src/hooks/use-focus-within-through-press.ts +86 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
// A tap moves focus and clicks after its release, within the browser's
|
|
4
|
+
// double-tap delay of about 300 ms.
|
|
5
|
+
const TAP_CLICK_WAIT_MS = 400;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Tracks focus inside an element that shrinks when focus leaves it, such as a
|
|
9
|
+
* reply box that rests as one line.
|
|
10
|
+
*
|
|
11
|
+
* Pressing a control outside the element moves focus on pointer down. Shrinking
|
|
12
|
+
* right then moves everything laid out around the element, so the control can
|
|
13
|
+
* slide out from under the pointer before the release, and the click lands
|
|
14
|
+
* somewhere else. Focus lost during a press only counts once that press's click
|
|
15
|
+
* has fired.
|
|
16
|
+
*/
|
|
17
|
+
export function useFocusWithinThroughPress(
|
|
18
|
+
ref: React.RefObject<HTMLElement | null>,
|
|
19
|
+
) {
|
|
20
|
+
const [focused, setFocused] = React.useState(false);
|
|
21
|
+
const pressing = React.useRef(false);
|
|
22
|
+
const blurredDuringPress = React.useRef(false);
|
|
23
|
+
|
|
24
|
+
React.useEffect(() => {
|
|
25
|
+
let settleTimer: ReturnType<typeof setTimeout> | undefined;
|
|
26
|
+
let tapTimer: ReturnType<typeof setTimeout> | undefined;
|
|
27
|
+
const onPressStart = () => {
|
|
28
|
+
clearTimeout(tapTimer);
|
|
29
|
+
pressing.current = true;
|
|
30
|
+
};
|
|
31
|
+
const onPressEnd = () => {
|
|
32
|
+
clearTimeout(tapTimer);
|
|
33
|
+
pressing.current = false;
|
|
34
|
+
if (!blurredDuringPress.current) return;
|
|
35
|
+
blurredDuringPress.current = false;
|
|
36
|
+
clearTimeout(settleTimer);
|
|
37
|
+
// The click's own handlers run ahead of this timer.
|
|
38
|
+
settleTimer = setTimeout(() => {
|
|
39
|
+
setFocused(Boolean(ref.current?.contains(document.activeElement)));
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
const onPointerUp = (event: PointerEvent) => {
|
|
43
|
+
if (event.pointerType !== "touch") {
|
|
44
|
+
onPressEnd();
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
clearTimeout(tapTimer);
|
|
48
|
+
tapTimer = setTimeout(onPressEnd, TAP_CLICK_WAIT_MS);
|
|
49
|
+
};
|
|
50
|
+
window.addEventListener("pointerdown", onPressStart, true);
|
|
51
|
+
window.addEventListener("pointerup", onPointerUp, true);
|
|
52
|
+
window.addEventListener("pointercancel", onPressEnd, true);
|
|
53
|
+
window.addEventListener("click", onPressEnd, true);
|
|
54
|
+
// Neither of these reports a release, so a press could otherwise stick.
|
|
55
|
+
window.addEventListener("contextmenu", onPressEnd, true);
|
|
56
|
+
window.addEventListener("blur", onPressEnd);
|
|
57
|
+
return () => {
|
|
58
|
+
clearTimeout(settleTimer);
|
|
59
|
+
clearTimeout(tapTimer);
|
|
60
|
+
window.removeEventListener("pointerdown", onPressStart, true);
|
|
61
|
+
window.removeEventListener("pointerup", onPointerUp, true);
|
|
62
|
+
window.removeEventListener("pointercancel", onPressEnd, true);
|
|
63
|
+
window.removeEventListener("click", onPressEnd, true);
|
|
64
|
+
window.removeEventListener("contextmenu", onPressEnd, true);
|
|
65
|
+
window.removeEventListener("blur", onPressEnd);
|
|
66
|
+
};
|
|
67
|
+
}, [ref]);
|
|
68
|
+
|
|
69
|
+
const focusWithinProps = {
|
|
70
|
+
onFocusCapture: () => {
|
|
71
|
+
blurredDuringPress.current = false;
|
|
72
|
+
setFocused(true);
|
|
73
|
+
},
|
|
74
|
+
onBlurCapture: (event: React.FocusEvent) => {
|
|
75
|
+
const next = event.relatedTarget as Node | null;
|
|
76
|
+
if (next && ref.current?.contains(next)) return;
|
|
77
|
+
if (pressing.current) {
|
|
78
|
+
blurredDuringPress.current = true;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
setFocused(false);
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
return { focused, focusWithinProps };
|
|
86
|
+
}
|