in packages/hooks/src/useTextSelection/index.ts [52:109]
function useTextSelection(target?: BasicTarget<Document | Element>): State {
const [state, setState] = useState(initState);
const stateRef = useRef(state);
const isInRangeRef = useRef(false);
stateRef.current = state;
useEffectWithTarget(
() => {
const el = getTargetElement(target, document);
if (!el) {
return;
}
const mouseupHandler = () => {
let selObj: Selection | null = null;
let text = '';
let rect = initRect;
if (!window.getSelection) return;
selObj = window.getSelection();
text = selObj ? selObj.toString() : '';
if (text && isInRangeRef.current) {
rect = getRectFromSelection(selObj);
setState({ ...state, text, ...rect });
}
};
// 任意点击都需要清空之前的 range
const mousedownHandler = (e) => {
// 如果是鼠标右键需要跳过 这样选中的数据就不会被清空
if (e.button === 2) return;
if (!window.getSelection) return;
if (stateRef.current.text) {
setState({ ...initState });
}
isInRangeRef.current = false;
const selObj = window.getSelection();
if (!selObj) return;
selObj.removeAllRanges();
isInRangeRef.current = el.contains(e.target);
};
el.addEventListener('mouseup', mouseupHandler);
document.addEventListener('mousedown', mousedownHandler);
return () => {
el.removeEventListener('mouseup', mouseupHandler);
document.removeEventListener('mousedown', mousedownHandler);
};
},
[],
target,
);
return state;
}