79 lines
1.9 KiB
TypeScript
79 lines
1.9 KiB
TypeScript
import { MutableRefObject, useLayoutEffect, useState } from 'react';
|
|
import {
|
|
DOCUMENT_VIEWER_PORTRAIT_HEIGHT_RATIO,
|
|
MIN_STACKED_BREAKPOINT,
|
|
PORTRAIT_RATIO_STYLE_ID,
|
|
} from '../constants/preview';
|
|
|
|
const ensurePortraitRatioStyle = () => {
|
|
const cssValue = String(DOCUMENT_VIEWER_PORTRAIT_HEIGHT_RATIO);
|
|
const cssText = `:root { --document-viewer-portrait-height-ratio: ${cssValue}; }`;
|
|
|
|
let styleEl = document.getElementById(PORTRAIT_RATIO_STYLE_ID);
|
|
if (!styleEl) {
|
|
styleEl = document.createElement('style');
|
|
styleEl.id = PORTRAIT_RATIO_STYLE_ID;
|
|
document.head.appendChild(styleEl);
|
|
}
|
|
|
|
if (styleEl.textContent !== cssText) {
|
|
styleEl.textContent = cssText;
|
|
}
|
|
};
|
|
|
|
const computeStackedLayoutBreakpoint = () => Math.max(window.innerWidth / 2, MIN_STACKED_BREAKPOINT);
|
|
|
|
export const useViewerLayoutMode = (
|
|
ref: MutableRefObject<HTMLElement | null> | null,
|
|
dependency?: unknown,
|
|
) => {
|
|
const [isStacked, setIsStacked] = useState(false);
|
|
|
|
useLayoutEffect(() => {
|
|
ensurePortraitRatioStyle();
|
|
}, []);
|
|
|
|
useLayoutEffect(() => {
|
|
const node = ref?.current;
|
|
if (!node) {
|
|
setIsStacked(false);
|
|
return undefined;
|
|
}
|
|
|
|
let frame: number | null = null;
|
|
const commitMeasure = (width: number) => {
|
|
if (frame) {
|
|
cancelAnimationFrame(frame);
|
|
}
|
|
frame = requestAnimationFrame(() => {
|
|
const breakpoint = computeStackedLayoutBreakpoint();
|
|
setIsStacked(width < breakpoint);
|
|
});
|
|
};
|
|
|
|
const measure = () => {
|
|
commitMeasure(node.getBoundingClientRect().width);
|
|
};
|
|
|
|
measure();
|
|
|
|
const observer = new ResizeObserver((entries) => {
|
|
if (!entries.length) {
|
|
return;
|
|
}
|
|
commitMeasure(entries[0].contentRect.width);
|
|
});
|
|
|
|
observer.observe(node);
|
|
|
|
return () => {
|
|
observer.disconnect();
|
|
if (frame) {
|
|
cancelAnimationFrame(frame);
|
|
}
|
|
};
|
|
}, [ref, dependency]);
|
|
|
|
return isStacked;
|
|
};
|