Skip to content

Commit 385ff69

Browse files
committed
chore: init
1 parent 8ea0ed1 commit 385ff69

File tree

3 files changed

+74
-42
lines changed

3 files changed

+74
-42
lines changed

docs/demo/focus.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
title: Focus Utils
3+
---
4+
5+
# Focus Utils Demo
6+
7+
Demonstrates the usage of focus-related utility functions, including `limitTabRange`, `getFocusNodeList`, and `triggerFocus`.
8+
9+
<code src="../examples/focus.tsx"></code>

docs/examples/focus.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React, { useRef } from 'react';
2+
import {} from '../../src';
3+
4+
export default function FocusDemo() {
5+
const containerRef = useRef<HTMLDivElement>(null);
6+
7+
return (
8+
<div style={{ padding: 32 }}>
9+
<h2>Focus Utils Demo</h2>
10+
11+
{/* External buttons */}
12+
<button>External Button 1</button>
13+
14+
{/* Middle container - Tab key cycling is limited within this area */}
15+
<div
16+
ref={containerRef}
17+
style={{
18+
border: '2px solid #1890ff',
19+
padding: 24,
20+
margin: 16,
21+
borderRadius: 8,
22+
backgroundColor: '#f0f8ff',
23+
}}
24+
>
25+
<button>Container Button 1</button>
26+
<button>Container Button 2</button>
27+
<button>Container Button 3</button>
28+
</div>
29+
30+
{/* External buttons */}
31+
<button>External Button 2</button>
32+
</div>
33+
);
34+
}

src/Dom/focus.ts

Lines changed: 31 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -56,48 +56,6 @@ export function getFocusNodeList(node: HTMLElement, includePositive = false) {
5656
return res;
5757
}
5858

59-
let lastFocusElement = null;
60-
61-
/** @deprecated Do not use since this may failed when used in async */
62-
export function saveLastFocusNode() {
63-
lastFocusElement = document.activeElement;
64-
}
65-
66-
/** @deprecated Do not use since this may failed when used in async */
67-
export function clearLastFocusNode() {
68-
lastFocusElement = null;
69-
}
70-
71-
/** @deprecated Do not use since this may failed when used in async */
72-
export function backLastFocusNode() {
73-
if (lastFocusElement) {
74-
try {
75-
// 元素可能已经被移动了
76-
lastFocusElement.focus();
77-
78-
/* eslint-disable no-empty */
79-
} catch (e) {
80-
// empty
81-
}
82-
/* eslint-enable no-empty */
83-
}
84-
}
85-
86-
export function limitTabRange(node: HTMLElement, e: KeyboardEvent) {
87-
if (e.keyCode === 9) {
88-
const tabNodeList = getFocusNodeList(node);
89-
const lastTabNode = tabNodeList[e.shiftKey ? 0 : tabNodeList.length - 1];
90-
const leavingTab =
91-
lastTabNode === document.activeElement || node === document.activeElement;
92-
93-
if (leavingTab) {
94-
const target = tabNodeList[e.shiftKey ? tabNodeList.length - 1 : 0];
95-
target.focus();
96-
e.preventDefault();
97-
}
98-
}
99-
}
100-
10159
export interface InputFocusOptions extends FocusOptions {
10260
cursor?: 'start' | 'end' | 'all';
10361
}
@@ -137,3 +95,34 @@ export function triggerFocus(
13795
}
13896
}
13997
}
98+
99+
// ======================================================
100+
// == Lock Focus ==
101+
// ======================================================
102+
let focusElements: HTMLElement[] = [];
103+
104+
function onWindowFocus(e: FocusEvent) {
105+
const lastElement = focusElements[focusElements.length - 1];
106+
107+
console.log('lock focus', e.target, lastElement);
108+
}
109+
110+
/**
111+
* Lock focus in the element.
112+
* It will force back to the first focusable element when focus leaves the element.
113+
*/
114+
export function lockFocus(element: HTMLElement): VoidFunction {
115+
// Refresh focus elements
116+
focusElements = focusElements.filter(ele => ele !== element);
117+
focusElements.push(element);
118+
119+
// Just add event since it will de-duplicate
120+
window.addEventListener('focusin', onWindowFocus, true);
121+
122+
return () => {
123+
focusElements = focusElements.filter(ele => ele !== element);
124+
if (focusElements.length === 0) {
125+
window.removeEventListener('focusin', onWindowFocus, true);
126+
}
127+
};
128+
}

0 commit comments

Comments
 (0)