Some checks are pending
E2E / Playwright e2e (push) Waiting to run
- Introduced turbopack alias for canvas in next.config.mjs. - Updated package.json scripts for development and branding tasks. - Added new dependencies for Tiptap extensions. - Implemented new demo layouts for agenda, contacts, drive, and mail applications. - Enhanced globals.css for improved theming and splash screen animations. - Added OAuth callback handling for drive mounts. - Updated layout components to integrate new demo shells and improve structure.
63 lines
2.1 KiB
TypeScript
63 lines
2.1 KiB
TypeScript
/** Hauteur utile du corps d’un iframe d’aperçu mail (évite le scrollHeight fantôme). */
|
||
|
||
export const EMAIL_PREVIEW_MIN_IFRAME_HEIGHT = 120
|
||
export const EMAIL_PREVIEW_HEIGHT_BUFFER = 8
|
||
export const EMAIL_PREVIEW_MEASURE_ROOT_SELECTOR = "[data-ultimail-measure-root]"
|
||
|
||
const CONTENT_MEASURE_SELECTORS =
|
||
"p,div,span,td,th,li,h1,h2,h3,h4,h5,h6,table,img,blockquote,pre,hr,a,section,article,footer,header"
|
||
|
||
function roundPreviewHeight(raw: number): number {
|
||
return Math.max(
|
||
EMAIL_PREVIEW_MIN_IFRAME_HEIGHT,
|
||
Math.ceil(raw / 4) * 4 + EMAIL_PREVIEW_HEIGHT_BUFFER
|
||
)
|
||
}
|
||
|
||
export function resolveEmailPreviewMeasureRoot(doc: Document): HTMLElement {
|
||
return (
|
||
doc.querySelector<HTMLElement>(EMAIL_PREVIEW_MEASURE_ROOT_SELECTOR) ??
|
||
doc.body
|
||
)
|
||
}
|
||
|
||
export function measureEmailPreviewIframeHeight(doc: Document): number {
|
||
const root = resolveEmailPreviewMeasureRoot(doc)
|
||
const view = doc.defaultView
|
||
if (!root || !view) return EMAIL_PREVIEW_MIN_IFRAME_HEIGHT
|
||
|
||
const scrollEstimate = Math.max(
|
||
root.scrollHeight,
|
||
root.offsetHeight,
|
||
doc.body?.scrollHeight ?? 0,
|
||
doc.body?.offsetHeight ?? 0,
|
||
doc.documentElement?.scrollHeight ?? 0,
|
||
doc.documentElement?.offsetHeight ?? 0
|
||
)
|
||
|
||
const rootTop = root.getBoundingClientRect().top
|
||
let contentBottom = rootTop
|
||
|
||
for (const el of root.querySelectorAll(CONTENT_MEASURE_SELECTORS)) {
|
||
const cs = view.getComputedStyle(el)
|
||
if (cs.display === "none" || cs.visibility === "hidden") continue
|
||
const rect = el.getBoundingClientRect()
|
||
if (rect.height < 1 && rect.width < 1) continue
|
||
contentBottom = Math.max(contentBottom, rect.bottom)
|
||
}
|
||
|
||
const hasVisibleLayout = contentBottom > rootTop + 8
|
||
if (hasVisibleLayout) {
|
||
const boundEstimate = Math.ceil(contentBottom - rootTop) + 4
|
||
// Prefer bounds over scrollHeight (phantom tail in newsletters), but never
|
||
// shrink below scroll when inline/absolute content extends past last block.
|
||
const contentHeight = Math.max(
|
||
boundEstimate,
|
||
Math.min(scrollEstimate, boundEstimate + 48)
|
||
)
|
||
return roundPreviewHeight(contentHeight)
|
||
}
|
||
|
||
return roundPreviewHeight(scrollEstimate + 2)
|
||
}
|