fix minor issues

This commit is contained in:
Salihu
2026-09-09 00:30:46 +01:00
parent 6556a1b5a0
commit 107e7b3776
@@ -3,7 +3,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { ActionIcon, Box, Modal, Text, Title, Tooltip } from "@mantine/core"; import { ActionIcon, Box, Modal, Text, Title, Tooltip } from "@mantine/core";
import { IconChevronLeft, IconChevronRight, IconX } from "@tabler/icons-react"; import { IconChevronLeft, IconChevronRight, IconX } from "@tabler/icons-react";
import { useHotkeys } from "@mantine/hooks"; import { useHotkeys } from "@mantine/hooks";
import { EditorProvider, type JSONContent } from "@tiptap/react"; import { EditorProvider, isNodeEmpty, type JSONContent } from "@tiptap/react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { mainExtensions } from "@/features/editor/extensions/extensions"; import { mainExtensions } from "@/features/editor/extensions/extensions";
import { TransclusionLookupProvider } from "@/features/editor/components/transclusion/transclusion-lookup-context"; import { TransclusionLookupProvider } from "@/features/editor/components/transclusion/transclusion-lookup-context";
@@ -18,6 +18,8 @@ type MeasuredContentSlide = {
scrollable: boolean; scrollable: boolean;
}; };
type MeasuredNode = { node: JSONContent; rect: DOMRect };
interface PresentationModalProps { interface PresentationModalProps {
title: string; title: string;
content: JSONContent; content: JSONContent;
@@ -31,6 +33,23 @@ const excludedExtensionNames = new Set([
"tableReadonlySort", "tableReadonlySort",
]); ]);
const isEmptyJsonNode = (node: JSONContent) =>
node.type === "paragraph" && !node.text?.trim() && !node.content?.length;
const isDivider = (node: JSONContent) => node.type === "horizontalRule";
const isSectionHeading = (node: JSONContent) =>
node.type === "heading" && node.attrs?.level === 1;
function getAvailableHeight(area: HTMLElement): number {
const styles = window.getComputedStyle(area);
return (
area.clientHeight -
parseFloat(styles.paddingTop) -
parseFloat(styles.paddingBottom)
);
}
export default function PresentationModal({ export default function PresentationModal({
title, title,
content, content,
@@ -103,47 +122,55 @@ export default function PresentationModal({
return; return;
} }
const editorElement = editor.view.dom; const renderedNodes = Array.from(editor.view.dom.children) as HTMLElement[];
const renderedNodes = Array.from(editorElement.children) as HTMLElement[]; if (!renderedNodes.length) {
setContentSlides([]);
return;
}
const areaStyles = window.getComputedStyle(area); const availableHeight = getAvailableHeight(area);
const availableHeight =
area.clientHeight -
parseFloat(areaStyles.paddingTop) -
parseFloat(areaStyles.paddingBottom);
const slides: MeasuredContentSlide[] = []; const slides: MeasuredContentSlide[] = [];
let currentSlide: JSONContent[] = []; let currentSlide: JSONContent[] = [];
let currentSlideTop = renderedNodes[0].getBoundingClientRect().top; let currentSlideTop = 0;
let currentSlideBottom = currentSlideTop; let currentSlideBottom = 0;
const saveCurrentSlide = () => { const saveCurrentSlide = () => {
if (currentSlide.length === 0) return; if (!currentSlide.length) return;
slides.push({ slides.push({
doc: { type: "doc", content: currentSlide }, doc: { type: "doc", content: currentSlide },
scrollable: currentSlideBottom - currentSlideTop > availableHeight, scrollable: currentSlideBottom - currentSlideTop > availableHeight,
}); });
currentSlide = [];
}; };
renderedNodes.forEach((renderedNode, index) => { for (let index = 0; index < renderedNodes.length; index++) {
const node = nodes[index]; const node = nodes[index];
const nodeRect = renderedNode.getBoundingClientRect(); const renderedNode = renderedNodes[index];
const startsNewSection = if (!node || !renderedNode || isEmptyJsonNode(node)) continue;
node.type === "horizontalRule" ||
(node.type === "heading" && node.attrs?.level === 1);
const exceedsPage =
currentSlide.length > 0 &&
nodeRect.bottom - currentSlideTop > availableHeight;
if (currentSlide.length > 0 && (startsNewSection || exceedsPage)) { const rect = renderedNode.getBoundingClientRect();
if (isDivider(node)) {
saveCurrentSlide(); saveCurrentSlide();
currentSlide = []; currentSlideTop = rect.bottom;
currentSlideTop = nodeRect.top; currentSlideBottom = rect.bottom;
continue;
}
if (currentSlide.length === 0) {
currentSlideTop = rect.top;
} else if (
isSectionHeading(node) ||
rect.bottom - currentSlideTop > availableHeight
) {
saveCurrentSlide();
currentSlideTop = rect.top;
} }
currentSlide.push(node); currentSlide.push(node);
currentSlideBottom = nodeRect.bottom; currentSlideBottom = rect.bottom;
}); }
saveCurrentSlide(); saveCurrentSlide();
setContentSlides(slides); setContentSlides(slides);