Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 

62 wiersze
2.1 KiB

  1. import { useCallback, useRef } from 'react';
  2. import useEventCallback from './useEventCallback';
  3. import useMounted from './useMounted';
  4. /**
  5. * useFocusManager provides a way to track and manage focus as it moves around
  6. * a container element. An `onChange` is fired when focus enters or leaves the
  7. * element, but not when it moves around inside the element, similar to
  8. * `pointerenter` and `pointerleave` DOM events.
  9. *
  10. * ```tsx
  11. * const [focused, setFocusState] = useState(false)
  12. *
  13. * const { onBlur, onFocus } = useFocusManager({
  14. * onChange: nextFocused => setFocusState(nextFocused)
  15. * })
  16. *
  17. * return (
  18. * <div tabIndex="-1" onFocus={onFocus} onBlur={onBlur}>
  19. * {String(focused)}
  20. * <input />
  21. * <input />
  22. *
  23. * <button>A button</button>
  24. * </div>
  25. * ```
  26. *
  27. */
  28. export default function useFocusManager(opts) {
  29. var isMounted = useMounted();
  30. var lastFocused = useRef();
  31. var handle = useRef();
  32. var willHandle = useEventCallback(opts.willHandle);
  33. var didHandle = useEventCallback(opts.didHandle);
  34. var onChange = useEventCallback(opts.onChange);
  35. var isDisabled = useEventCallback(opts.isDisabled);
  36. var handleFocusChange = useCallback(function (focused, event) {
  37. if (event && event.persist) event.persist();
  38. if (willHandle && willHandle(focused, event) === false) return;
  39. clearTimeout(handle.current);
  40. handle.current = setTimeout(function () {
  41. if (focused !== lastFocused.current) {
  42. if (didHandle) didHandle(focused, event); // only fire a change when unmounted if its a blur
  43. if (isMounted() || !focused) {
  44. lastFocused.current = focused;
  45. onChange && onChange(focused, event);
  46. }
  47. }
  48. });
  49. }, [isMounted, willHandle, didHandle, onChange, lastFocused]);
  50. var handleBlur = useCallback(function (event) {
  51. if (!isDisabled()) handleFocusChange(false, event);
  52. }, [handleFocusChange, isDisabled]);
  53. var handleFocus = useCallback(function (event) {
  54. if (!isDisabled()) handleFocusChange(true, event);
  55. }, [handleFocusChange, isDisabled]);
  56. return {
  57. onBlur: handleBlur,
  58. onFocus: handleFocus
  59. };
  60. }