Dashboard sipadu mbip
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

useFocusManager.js 2.2KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import { useCallback, useRef } from 'react';
  2. import useMounted from './useMounted';
  3. import useEventCallback from './useEventCallback';
  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. * ```ts
  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. * @param opts Options
  28. * @returns FocusController a set of paired focus and blur event handlers
  29. */
  30. export default function useFocusManager(opts) {
  31. var isMounted = useMounted();
  32. var lastFocused = useRef();
  33. var handle = useRef();
  34. var willHandle = useEventCallback(opts.willHandle);
  35. var didHandle = useEventCallback(opts.didHandle);
  36. var onChange = useEventCallback(opts.onChange);
  37. var isDisabled = useEventCallback(opts.isDisabled);
  38. var handleFocusChange = useCallback(function (focused, event) {
  39. if (event && event.persist) event.persist();
  40. if (willHandle && willHandle(focused, event) === false) return;
  41. clearTimeout(handle.current);
  42. handle.current = setTimeout(function () {
  43. if (focused !== lastFocused.current) {
  44. if (didHandle) didHandle(focused, event); // only fire a change when unmounted if its a blur
  45. if (isMounted() || !focused) {
  46. lastFocused.current = focused;
  47. onChange && onChange(focused, event);
  48. }
  49. }
  50. });
  51. }, [isMounted, willHandle, didHandle, onChange, lastFocused]);
  52. var handleBlur = useCallback(function (event) {
  53. if (!isDisabled()) handleFocusChange(false, event);
  54. }, [handleFocusChange, isDisabled]);
  55. var handleFocus = useCallback(function (event) {
  56. if (!isDisabled()) handleFocusChange(true, event);
  57. }, [handleFocusChange, isDisabled]);
  58. return {
  59. onBlur: handleBlur,
  60. onFocus: handleFocus
  61. };
  62. }