Enhance TemplatePreview Component with Scaling and Layout Improvements
Some checks failed
farmcontrol/farmcontrol-ui/pipeline/head There was a failure building this commit
Some checks failed
farmcontrol/farmcontrol-ui/pipeline/head There was a failure building this commit
- Introduced scaleCssSize function to dynamically adjust CSS sizes based on scaling factor. - Added responsive width control for the preview document, improving layout adaptability. - Implemented useLayoutEffect to apply iframe content size based on preview type and width. - Refactored reloadPreview function to simplify parameters and ensure consistent width handling. - Enhanced iframe rendering with scaling transformations for better visual representation.
This commit is contained in:
parent
a590650d80
commit
f01f978ec6
@ -21,6 +21,17 @@ import ProgressDisplay from './ProgressDisplay.jsx'
|
|||||||
import { CaretDownFilled } from '@ant-design/icons'
|
import { CaretDownFilled } from '@ant-design/icons'
|
||||||
const noop = () => {}
|
const noop = () => {}
|
||||||
|
|
||||||
|
const scaleCssSize = (size, scale) => {
|
||||||
|
if (scale === 1 || typeof size !== 'string' || !size.endsWith('px')) {
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
const value = parseFloat(size)
|
||||||
|
if (!Number.isFinite(value)) {
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
return `${Math.ceil(value * scale)}px`
|
||||||
|
}
|
||||||
|
|
||||||
const TemplatePreview = ({
|
const TemplatePreview = ({
|
||||||
objectData,
|
objectData,
|
||||||
documentTemplate,
|
documentTemplate,
|
||||||
@ -57,6 +68,8 @@ const TemplatePreview = ({
|
|||||||
const [previewScale, setPreviewScale] = useState(1)
|
const [previewScale, setPreviewScale] = useState(1)
|
||||||
const [previewType, setPreviewType] = useState('HTML')
|
const [previewType, setPreviewType] = useState('HTML')
|
||||||
const [previewWidth, setPreviewWidth] = useState(defaultPreviewWidth)
|
const [previewWidth, setPreviewWidth] = useState(defaultPreviewWidth)
|
||||||
|
const previewWidthRef = useRef(previewWidth)
|
||||||
|
previewWidthRef.current = previewWidth
|
||||||
const [panMode, setPanMode] = useState(false)
|
const [panMode, setPanMode] = useState(false)
|
||||||
const [isPanning, setIsPanning] = useState(false)
|
const [isPanning, setIsPanning] = useState(false)
|
||||||
const panStartRef = useRef({ x: 0, y: 0, scrollLeft: 0, scrollTop: 0 })
|
const panStartRef = useRef({ x: 0, y: 0, scrollLeft: 0, scrollTop: 0 })
|
||||||
@ -93,12 +106,43 @@ const TemplatePreview = ({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (showWidthControl && !doc.querySelector('.previewDocument') && doc.body) {
|
||||||
|
const container = doc.createElement('div')
|
||||||
|
container.className = 'previewContainer'
|
||||||
|
const pages = doc.createElement('div')
|
||||||
|
pages.className = 'previewPages'
|
||||||
|
pages.id = 'pages'
|
||||||
|
const wrapper = doc.createElement('div')
|
||||||
|
wrapper.className = 'previewWrapper'
|
||||||
|
const page = doc.createElement('div')
|
||||||
|
page.className = 'previewDocument documentPage'
|
||||||
|
page.id = 'content'
|
||||||
|
while (doc.body.firstChild) {
|
||||||
|
page.appendChild(doc.body.firstChild)
|
||||||
|
}
|
||||||
|
wrapper.appendChild(page)
|
||||||
|
pages.appendChild(wrapper)
|
||||||
|
container.appendChild(pages)
|
||||||
|
doc.body.appendChild(container)
|
||||||
|
if (!doc.head?.querySelector('style[data-preview-chrome]')) {
|
||||||
|
const styleEl = doc.createElement('style')
|
||||||
|
styleEl.setAttribute('data-preview-chrome', 'true')
|
||||||
|
styleEl.textContent =
|
||||||
|
'.previewContainer{display:flex;justify-content:center;align-items:flex-start;padding:60px;box-sizing:border-box;width:fit-content}.previewPages{display:flex;flex-direction:row;align-items:flex-start;width:fit-content}.previewWrapper{position:relative;flex-shrink:0}.previewDocument{background:#fff;border:1px solid #000;box-shadow:0 0 5px rgba(0,0,0,.2);transform-origin:top left;position:relative;overflow:visible;box-sizing:content-box}'
|
||||||
|
doc.head?.appendChild(styleEl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const wrappers = doc.querySelectorAll('.previewWrapper')
|
const wrappers = doc.querySelectorAll('.previewWrapper')
|
||||||
wrappers.forEach((wrapper) => {
|
wrappers.forEach((wrapper) => {
|
||||||
const page = wrapper.querySelector('.previewDocument')
|
const page = wrapper.querySelector('.previewDocument')
|
||||||
if (!page) {
|
if (!page) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (showWidthControl) {
|
||||||
|
page.style.width = `${previewWidth}px`
|
||||||
|
page.style.maxWidth = `${previewWidth}px`
|
||||||
|
}
|
||||||
const pageVisual = page.getBoundingClientRect()
|
const pageVisual = page.getBoundingClientRect()
|
||||||
if (pageVisual.width <= 0 && pageVisual.height <= 0) {
|
if (pageVisual.width <= 0 && pageVisual.height <= 0) {
|
||||||
return
|
return
|
||||||
@ -130,9 +174,7 @@ const TemplatePreview = ({
|
|||||||
parseFloat(containerStyle.paddingBottom)
|
parseFloat(containerStyle.paddingBottom)
|
||||||
}
|
}
|
||||||
|
|
||||||
const contentWidth = showWidthControl
|
const contentWidth = Math.ceil(visual.width + padX)
|
||||||
? previewWidth
|
|
||||||
: Math.ceil(visual.width + padX)
|
|
||||||
const contentHeight = Math.ceil(
|
const contentHeight = Math.ceil(
|
||||||
Math.max(visual.height + padY, doc.documentElement.scrollHeight)
|
Math.max(visual.height + padY, doc.documentElement.scrollHeight)
|
||||||
)
|
)
|
||||||
@ -192,6 +234,13 @@ const TemplatePreview = ({
|
|||||||
restoreScrollPosition()
|
restoreScrollPosition()
|
||||||
}, [iframeSize, restoreScrollPosition])
|
}, [iframeSize, restoreScrollPosition])
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
if (previewType != 'HTML') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
applyIframeContentSize()
|
||||||
|
}, [applyIframeContentSize, previewType, previewWidth])
|
||||||
|
|
||||||
const updatePreviewContentHTML = (html) => {
|
const updatePreviewContentHTML = (html) => {
|
||||||
const scrollEl = scrollElementRef.current
|
const scrollEl = scrollElementRef.current
|
||||||
if (scrollEl) {
|
if (scrollEl) {
|
||||||
@ -370,7 +419,7 @@ const TemplatePreview = ({
|
|||||||
)
|
)
|
||||||
|
|
||||||
const reloadPreview = useCallback(
|
const reloadPreview = useCallback(
|
||||||
(content, testObject = {}, scale = 1) => {
|
(content, testObject = {}) => {
|
||||||
const templateId = currentTemplate?._id
|
const templateId = currentTemplate?._id
|
||||||
if (!templateId) {
|
if (!templateId) {
|
||||||
return
|
return
|
||||||
@ -382,7 +431,7 @@ const TemplatePreview = ({
|
|||||||
templateId,
|
templateId,
|
||||||
content,
|
content,
|
||||||
testObject,
|
testObject,
|
||||||
scale,
|
1,
|
||||||
(result) => {
|
(result) => {
|
||||||
if (requestId !== previewRequestIdRef.current) {
|
if (requestId !== previewRequestIdRef.current) {
|
||||||
return
|
return
|
||||||
@ -396,14 +445,13 @@ const TemplatePreview = ({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
templateType,
|
templateType,
|
||||||
showWidthControl ? { width: previewWidth } : {}
|
showWidthControl ? { width: previewWidthRef.current } : {}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
currentTemplate?._id,
|
currentTemplate?._id,
|
||||||
fetchTemplatePreview,
|
fetchTemplatePreview,
|
||||||
onPreviewMessage,
|
onPreviewMessage,
|
||||||
previewWidth,
|
|
||||||
showWidthControl,
|
showWidthControl,
|
||||||
templateType
|
templateType
|
||||||
]
|
]
|
||||||
@ -424,7 +472,7 @@ const TemplatePreview = ({
|
|||||||
|
|
||||||
const timeoutId = window.setTimeout(() => {
|
const timeoutId = window.setTimeout(() => {
|
||||||
if (content == null) {
|
if (content == null) {
|
||||||
reloadPreview(templateContent, objectData, previewScale)
|
reloadPreview(templateContent, objectData)
|
||||||
}
|
}
|
||||||
}, 300)
|
}, 300)
|
||||||
|
|
||||||
@ -435,8 +483,6 @@ const TemplatePreview = ({
|
|||||||
objectData,
|
objectData,
|
||||||
templateContent,
|
templateContent,
|
||||||
templateId,
|
templateId,
|
||||||
previewScale,
|
|
||||||
previewWidth,
|
|
||||||
previewType,
|
previewType,
|
||||||
reloadPreview,
|
reloadPreview,
|
||||||
content
|
content
|
||||||
@ -534,6 +580,8 @@ const TemplatePreview = ({
|
|||||||
}, [isPanning])
|
}, [isPanning])
|
||||||
|
|
||||||
const showProgressOverlay = previewType != 'HTML' && downloadProgress != null
|
const showProgressOverlay = previewType != 'HTML' && downloadProgress != null
|
||||||
|
const scaledIframeWidth = scaleCssSize(iframeSize.width, previewScale)
|
||||||
|
const scaledIframeHeight = scaleCssSize(iframeSize.height, previewScale)
|
||||||
|
|
||||||
const toolbarContent = (
|
const toolbarContent = (
|
||||||
<>
|
<>
|
||||||
@ -707,14 +755,14 @@ const TemplatePreview = ({
|
|||||||
align='center'
|
align='center'
|
||||||
style={{
|
style={{
|
||||||
minWidth: '100%',
|
minWidth: '100%',
|
||||||
width: iframeSize.width,
|
width: scaledIframeWidth,
|
||||||
height: iframeSize.height
|
height: scaledIframeHeight
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
width: iframeSize.width,
|
width: scaledIframeWidth,
|
||||||
height: iframeSize.height,
|
height: scaledIframeHeight,
|
||||||
cursor: panMode
|
cursor: panMode
|
||||||
? isPanning
|
? isPanning
|
||||||
? 'grabbing'
|
? 'grabbing'
|
||||||
@ -729,11 +777,14 @@ const TemplatePreview = ({
|
|||||||
scrolling='no'
|
scrolling='no'
|
||||||
frameBorder='0'
|
frameBorder='0'
|
||||||
style={{
|
style={{
|
||||||
width: '100%',
|
width:
|
||||||
height: iframeSize.height === 'auto' ? 150 : '100%',
|
iframeSize.width === '100%' ? '100%' : iframeSize.width,
|
||||||
|
height: iframeSize.height === 'auto' ? 150 : iframeSize.height,
|
||||||
display: 'block',
|
display: 'block',
|
||||||
border: 0,
|
border: 0,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
|
transform: `scale(${previewScale})`,
|
||||||
|
transformOrigin: 'top left',
|
||||||
pointerEvents: panMode ? 'none' : undefined
|
pointerEvents: panMode ? 'none' : undefined
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user