hooks/orientation.jsxjavascript
/*
  Tracks the physical device/viewport orientation via the CSS
  `(orientation: ...)` media feature - the same signal the SCSS mixins
  (src/styles/_mixins.scss) react to, so this hook and the stylesheets can
  never disagree about which orientation is currently active.

  Used by RotateOverlay (src/components/RotateOverlay/RotateOverlay.jsx)
  together with useRequiredOrientation (src/services/orientation.js) to
  detect when the kiosk is held the "wrong" way for the current route.
*/

import { useState, useEffect } from "react";

const getOrientation = () =>
  window.matchMedia("(orientation: portrait)").matches ? "portrait" : "landscape";

/**
 * @returns {"landscape"|"portrait"} The current viewport orientation, kept
 *   in sync live as the device is rotated/resized.
 */
export const useOrientation = () => {
  const [orientation, setOrientation] = useState(getOrientation);

  useEffect(() => {
    const mediaQuery = window.matchMedia("(orientation: portrait)");
    const handleChange = () => setOrientation(mediaQuery.matches ? "portrait" : "landscape");

    handleChange();
    mediaQuery.addEventListener("change", handleChange);
    return () => mediaQuery.removeEventListener("change", handleChange);
  }, []);

  return orientation;
};