• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

EcrituresNumeriques / stylo / 28380938656

29 Jun 2026 02:51PM UTC coverage: 68.636% (-0.3%) from 68.902%
28380938656

push

github

web-flow
feat: refonte de l'entĂȘte principale (#2057)

936 of 1474 branches covered (63.5%)

Branch coverage included in aggregate %.

0 of 25 new or added lines in 2 files covered. (0.0%)

1 existing line in 1 file now uncovered.

4942 of 7090 relevant lines covered (69.7%)

6.36 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/front/src/hooks/componentVisible.js
1
import { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react'
2

3
/**
4
 * @see https://zellwk.com/blog/keyboard-focusable-elements/
5
 * @param {HTMLElement} node
6
 * @returns {T[]}
7
 */
8
function findToggleableElements(node) {
9
  return Array.from(
×
10
    node.querySelectorAll(
11
      'a[href], button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])'
12
    )
13
  )
14
}
15

16
export default function useComponentVisible({
×
17
  initialVisible = false,
×
18
  namespace = 'default',
×
19
  ref: baseRef,
20
  track = [],
×
21
  trapNavigation = true,
×
22
} = {}) {
NEW
23
  const [isComponentVisible, setIsComponentVisible] = useState(initialVisible)
×
NEW
24
  const uniqueId = useId()
×
NEW
25
  const selfRef = useRef(null)
×
NEW
26
  const clickOutsideRefs = [baseRef, selfRef, ...track].filter(
×
NEW
27
    (d) => d?.current
×
28
  )
NEW
29
  const rotorRef = baseRef ?? selfRef
×
30

NEW
31
  const handleClickOutside = useCallback(
×
32
    (event) => {
NEW
33
      if (!isComponentVisible) {
×
NEW
34
        return
×
35
      }
36

37
      const hasClickedOutside =
NEW
38
        clickOutsideRefs.some((r) => r.current.contains(event.target)) === false
×
39

NEW
40
      if (
×
41
        (clickOutsideRefs.length && hasClickedOutside) ||
×
42
        (event.target.nodeName === 'A' && event.target.getAttribute('href'))
43
      ) {
NEW
44
        setIsComponentVisible(false)
×
45
      }
46
    },
47
    [isComponentVisible, clickOutsideRefs]
48
  )
49

NEW
50
  const handleEscapeKey = useCallback(
×
51
    function componenteVisibleHandleEscapeKey(event) {
NEW
52
      if (event.key === 'Escape') {
×
NEW
53
        setIsComponentVisible(false)
×
NEW
54
        const first = findToggleableElements(rotorRef.current).at(0)
×
NEW
55
        first?.focus()
×
56
      }
57
    },
58
    [rotorRef]
59
  )
60

61
  /*
62
   * It is acceptable not to have rotorRef otherwise unregistering the event does not work
63
   * (therefore, it blocks shift+tab navigation when menu is closed)
64
   */
UNCOV
65
  const handleTabulation = useCallback(
×
66
    function componenteVisibleTabulationRotor(event) {
67
      if (event.key === 'Tab') {
×
NEW
68
        const all = findToggleableElements(rotorRef.current)
×
69
        const index = all.indexOf(event.target)
×
70

71
        // out of range, we rotate back
72
        if (!event.shiftKey && index + 1 === all.length) {
×
73
          event.preventDefault()
×
74
          all.at(0).focus()
×
75
        }
76
        // we rewinded back to beginning, we resume from the end
77
        else if (event.shiftKey && index - 1 < 0) {
×
78
          event.preventDefault()
×
79
          all.at(-1).focus()
×
NEW
80
        } else if (event.shiftKey) {
×
NEW
81
          all.at(index - 1).focus()
×
82
        }
83
      }
84
    },
85
    [rotorRef]
86
  )
87

88
  // uninstall on keyup if element was inside ref.current[aria-controls]
89

90
  const toggleComponentIsVisible = useCallback(() => {
×
91
    setIsComponentVisible(!isComponentVisible)
×
92
  }, [isComponentVisible])
93

94
  const uninstallListeners = useCallback(() => {
×
95
    document.removeEventListener('click', handleClickOutside, true)
×
96
    document.removeEventListener('keyup', handleEscapeKey)
×
NEW
97
    trapNavigation && document.removeEventListener('keydown', handleTabulation)
×
98
  }, [rotorRef])
99

100
  useEffect(() => {
×
101
    if (isComponentVisible) {
×
102
      document.addEventListener('click', handleClickOutside, true)
×
103
      document.addEventListener('keyup', handleEscapeKey)
×
NEW
104
      trapNavigation && document.addEventListener('keydown', handleTabulation)
×
105
    } else {
106
      uninstallListeners()
×
107
    }
108
  }, [isComponentVisible, uniqueId])
109

110
  return {
×
111
    id: uniqueId,
112
    isComponentVisible,
113
    ref: baseRef ?? selfRef,
×
114
    setIsComponentVisible,
115
    toggleComponentIsVisible,
116
  }
117
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc