({toc})
| 135 | } |
| 136 | |
| 137 | export function MobileHeader({toc}) { |
| 138 | let ref = useRef<HTMLDivElement | null>(null); |
| 139 | let linkRef = useRef<HTMLAnchorElement | null>(null); |
| 140 | let labelRef = useRef<HTMLSpanElement | null>(null); |
| 141 | let {colorScheme} = useSettings(); |
| 142 | |
| 143 | useEffect(() => { |
| 144 | // Tiny polyfill for scroll driven animations. |
| 145 | // Element must have animationDuration: 1s and animationPlayState: paused. |
| 146 | if (!CSS.supports('(animation-timeline: scroll())') && ref.current) { |
| 147 | let [start, end] = animationRange.split(' ').map(v => parseInt(v, 10)); |
| 148 | let animations = ref.current.getAnimations({subtree: true}); |
| 149 | let onScroll = () => { |
| 150 | // Calculate animation time based on percentage of animationRange * duration. |
| 151 | let time = Math.max(0, Math.min(end, window.scrollY - start) / (end - start)) * 1000; |
| 152 | for (let animation of animations) { |
| 153 | animation.currentTime = time; |
| 154 | } |
| 155 | }; |
| 156 | |
| 157 | window.addEventListener('scroll', onScroll, {passive: true}); |
| 158 | return () => window.removeEventListener('scroll', onScroll); |
| 159 | } |
| 160 | }, []); |
| 161 | |
| 162 | let {currentPage} = useRouter(); |
| 163 | let library = getLibraryFromPage(currentPage); |
| 164 | let icon = getLibraryIcon(library); |
| 165 | let subdirectory: 's2' | 'react-aria' = 's2'; |
| 166 | if (library === 'react-aria') { |
| 167 | // the internationalized library has no homepage so i've chosen to route it to the react aria homepage |
| 168 | subdirectory = 'react-aria'; |
| 169 | } |
| 170 | |
| 171 | let baseUrl = getBaseUrl(subdirectory); |
| 172 | let homepage = `${baseUrl}/`; |
| 173 | |
| 174 | let [isOpen, setOpen] = useState(false); |
| 175 | let [wasOpen, setWasOpen] = useState(isOpen); |
| 176 | let [isTransitioning, setTransitioning] = useState(false); |
| 177 | let renderCallback = useRef<(() => void) | null>(null); |
| 178 | let onOpenChange = (isOpen: boolean) => { |
| 179 | if (!document.startViewTransition) { |
| 180 | setOpen(false); |
| 181 | if (isOpen) { |
| 182 | setWasOpen(true); |
| 183 | } |
| 184 | return; |
| 185 | } |
| 186 | |
| 187 | // Don't transition the entire page. |
| 188 | document.documentElement.style.viewTransitionName = 'none'; |
| 189 | |
| 190 | // Only transition label if it is visible (scrolled to the top of the page). |
| 191 | if (window.scrollY === 0 && labelRef.current && isOpen) { |
| 192 | labelRef.current.style.viewTransitionName = 'search-menu-label'; |
| 193 | } |
| 194 |
nothing calls this directly
no test coverage detected