Skip to content

Commit e741880

Browse files
committed
fix: improve page height calculation and rendering of page breaks in preview panel
1 parent 9b4a6c6 commit e741880

File tree

1 file changed

+69
-25
lines changed

1 file changed

+69
-25
lines changed

src/components/preview/index.tsx

Lines changed: 69 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ interface PreviewPanelProps {
1919
const PageBreakLine = React.memo(({ pageNumber }: { pageNumber: number }) => {
2020
const { activeResume } = useResumeStore();
2121
const { globalSettings } = activeResume || {};
22-
if (!globalSettings?.pagePadding) return;
22+
if (!globalSettings?.pagePadding) return null;
23+
2324
const A4_HEIGHT_MM = 297;
2425
const MM_TO_PX = 3.78;
2526

26-
const TOP_MARGIN_MM = globalSettings?.pagePadding / MM_TO_PX;
27-
const CONTENT_HEIGHT_MM = A4_HEIGHT_MM + TOP_MARGIN_MM + TOP_MARGIN_MM;
27+
const pagePaddingMM = globalSettings.pagePadding / MM_TO_PX;
28+
29+
const CONTENT_HEIGHT_MM = A4_HEIGHT_MM + pagePaddingMM;
2830
const pageHeight = CONTENT_HEIGHT_MM * MM_TO_PX;
2931

3032
return (
@@ -63,59 +65,80 @@ const PreviewPanel = ({
6365
}, [activeResume?.templateId]);
6466

6567
const startRef = useRef<HTMLDivElement>(null);
66-
const previewRef = React.useRef<HTMLDivElement>(null);
67-
const resumeContentRef = React.useRef<HTMLDivElement>(null);
68+
const previewRef = useRef<HTMLDivElement>(null);
69+
const resumeContentRef = useRef<HTMLDivElement>(null);
6870
const [contentHeight, setContentHeight] = useState(0);
6971

7072
const updateContentHeight = () => {
7173
if (resumeContentRef.current) {
72-
const height = resumeContentRef.current.scrollHeight;
74+
const height = resumeContentRef.current.clientHeight;
7375
if (height > 0) {
74-
setContentHeight(height);
76+
if (height !== contentHeight) {
77+
setContentHeight(height);
78+
}
7579
}
7680
}
7781
};
7882

7983
useEffect(() => {
80-
const observer = new MutationObserver(updateContentHeight);
84+
const debouncedUpdate = throttle(() => {
85+
requestAnimationFrame(() => {
86+
updateContentHeight();
87+
});
88+
}, 100);
89+
90+
const observer = new MutationObserver(debouncedUpdate);
91+
8192
if (resumeContentRef.current) {
8293
observer.observe(resumeContentRef.current, {
8394
childList: true,
8495
subtree: true,
8596
attributes: true,
97+
characterData: true,
8698
});
8799

88100
updateContentHeight();
89101
}
90102

91-
const resizeObserver = new ResizeObserver(
92-
throttle(updateContentHeight, 100)
93-
);
103+
const resizeObserver = new ResizeObserver(debouncedUpdate);
104+
94105
if (resumeContentRef.current) {
95106
resizeObserver.observe(resumeContentRef.current);
96107
}
97108

98-
const timeoutId = setTimeout(updateContentHeight, 100);
99-
100109
return () => {
101110
observer.disconnect();
102111
resizeObserver.disconnect();
103-
clearTimeout(timeoutId);
104112
};
113+
}, []);
114+
115+
useEffect(() => {
116+
if (activeResume) {
117+
const timer = setTimeout(updateContentHeight, 300);
118+
return () => clearTimeout(timer);
119+
}
105120
}, [activeResume]);
106121

107-
const pageBreakCount = useMemo(() => {
108-
let TOP_MARGIN_MM;
122+
const { pageHeightPx, pageBreakCount } = useMemo(() => {
109123
const MM_TO_PX = 3.78;
110124
const A4_HEIGHT_MM = 297;
125+
126+
let pagePaddingMM = 0;
111127
if (activeResume?.globalSettings?.pagePadding) {
112-
TOP_MARGIN_MM = activeResume.globalSettings.pagePadding / MM_TO_PX;
113-
} else {
114-
TOP_MARGIN_MM = 0;
128+
pagePaddingMM = activeResume.globalSettings.pagePadding / MM_TO_PX;
115129
}
116-
const CONTENT_HEIGHT_MM = A4_HEIGHT_MM - TOP_MARGIN_MM - TOP_MARGIN_MM;
130+
131+
const CONTENT_HEIGHT_MM = A4_HEIGHT_MM - pagePaddingMM;
117132
const pageHeightPx = CONTENT_HEIGHT_MM * MM_TO_PX;
118-
return Math.max(0, Math.ceil(contentHeight / pageHeightPx) - 1);
133+
134+
if (contentHeight <= 0) {
135+
return { pageHeightPx, pageBreakCount: 0 };
136+
}
137+
138+
const pageCount = Math.max(1, Math.ceil(contentHeight / pageHeightPx));
139+
const pageBreakCount = Math.max(0, pageCount - 1);
140+
141+
return { pageHeightPx, pageBreakCount };
119142
}, [contentHeight, activeResume?.globalSettings?.pagePadding]);
120143

121144
if (!activeResume) return null;
@@ -128,7 +151,7 @@ const PreviewPanel = ({
128151
fontFamily: "MiSans VF, sans-serif",
129152
}}
130153
>
131-
<div className="py-4 ml-4 px-4 min-h-screen flex justify-center scale-[58%] origin-top md:scale-90 md:origin-top-left">
154+
<div className="py-4 ml-4 px-4 min-h-screen flex justify-center scale-[58%] origin-top md:scale-90 md:origin-top-left">
132155
<div
133156
ref={startRef}
134157
className={cn(
@@ -186,9 +209,30 @@ const PreviewPanel = ({
186209
}
187210
`}</style>
188211
<ResumeTemplateComponent data={activeResume} template={template} />
189-
{Array.from({ length: pageBreakCount }, (_, i) => (
190-
<PageBreakLine key={i} pageNumber={i + 1} />
191-
))}
212+
{contentHeight > 0 && (
213+
<>
214+
<div key={`page-breaks-container-${contentHeight}`}>
215+
{Array.from(
216+
{ length: Math.min(pageBreakCount, 20) },
217+
(_, i) => {
218+
const pageNumber = i + 1;
219+
220+
const pageLinePosition = pageHeightPx * pageNumber;
221+
222+
if (pageLinePosition <= contentHeight) {
223+
return (
224+
<PageBreakLine
225+
key={`page-break-${pageNumber}`}
226+
pageNumber={pageNumber}
227+
/>
228+
);
229+
}
230+
return null;
231+
}
232+
).filter(Boolean)}
233+
</div>
234+
</>
235+
)}
192236
</div>
193237
</div>
194238
</div>

0 commit comments

Comments
 (0)