import { useLayoutEffect, useRef } from "react"; import { Title, AppShell, Flex } from "@mantine/core"; import { useLingui } from "@lingui/react"; import { HeaderConfig } from "../types/header-config"; import BackButton from "./back-button"; const MIN_TITLE_SCALE = 0.55; const Header = ({ collapsed, title, titleValues, withBackButton }: HeaderConfig) => { const { i18n } = useLingui(); const titleRef = useRef(null); const resolvedTitle = typeof title === "string" || title === undefined ? title : i18n._({ ...title, values: titleValues }); useLayoutEffect(() => { const el = titleRef.current; if (!el) return; let cancelled = false; const textWidth = () => { const range = document.createRange(); range.selectNodeContents(el); return range.getBoundingClientRect().width; }; const fit = () => { el.style.fontSize = ""; const available = el.clientWidth - 1; if (available <= 0) return; let needed = textWidth(); if (needed <= available) return; const natural = parseFloat(getComputedStyle(el).fontSize); let scale = Math.max(available / needed, MIN_TITLE_SCALE); el.style.fontSize = `${natural * scale}px`; for (let i = 0; i < 3 && scale > MIN_TITLE_SCALE && textWidth() > available; i++) { scale = Math.max(scale * 0.98, MIN_TITLE_SCALE); el.style.fontSize = `${natural * scale}px`; } }; fit(); document.fonts?.ready.then(() => { if (!cancelled) fit(); }); const observer = new ResizeObserver(fit); observer.observe(el); return () => { cancelled = true; observer.disconnect(); }; }, [resolvedTitle]); return ( { withBackButton && } {resolvedTitle?.toLocaleUpperCase()} ); } export default Header;