I’m trying to build a paginated editor with Slate React similar to MS Word. However, I’ve had problems trying to apply automatic page breaks.
Description of the problem
To create the pages for the editor, I came up with a custom node of type ‘page’ that has the following structure when rendered:
<div className="page" {...attributes} >
<div className="inner-page-container">
{children}
</div>
</div>
Children are “paragraph” nodes that render like:
<p className="paragraph" {...attributes}>{children}</p>
Then, I try to normalize each of these page nodes with:
import { Transforms,Element,Node, Editor ,Text, nodes} from 'slate'
import { ReactEditor } from 'slate-react'
const emptyPage: any ={type:'page',children:[{type:'paragraph', children:[{type:'text',text:''}]}]}
function withCustomNormalize(editor: ReactEditor) {
const { normalizeNode } = editor
editor.normalizeNode = (entry) => {
const [node, path] = entry
// if(Text.isText(node)) return normalizeNode(entry)
if (Element.isElement(node) && node.type === 'page') {
let PageNode
let NextPageNode
let PageHeight
let ChildrenHeight = 0
try{
PageNode = ReactEditor.toDOMNode(editor, node)
NextPageNode = PageNode.nextSibling
const styles = window.getComputedStyle(PageNode)
PageHeight = PageNode.clientHeight - (parseFloat(styles.paddingTop) + parseFloat(styles.paddingBottom))
}catch(e){
console.log(e)
return
}
const innerContainer = (PageNode.children[0] as HTMLElement)
for (const child of innerContainer.children){
ChildrenHeight += child.clientHeight
}
const delta = PageHeight - ChildrenHeight
if (delta < 0 && NextPageNode == null){
Transforms.liftNodes(editor)
Transforms.splitNodes(editor)
Transforms.wrapNodes(editor, emptyPage)
} else if (delta < 0 && NextPageNode != null){
try {
Transforms.moveNodes(editor, {to: [path[0] + 1, 0]})
} catch (e){
return
}
}
}
normalizeNode(entry)
}
return editor
}
export default withCustomNormalize
The code checks if there’s overflow on the inner-container and, case positive, if there’s no “next page”, splits the selections and wraps it around a new page node, otherwise it just moves the selection to the next page. Problem is: when hitting enter on the last possible line before overflowing, another paragraph node is created below. Only when I type something in, normalization is called. The image below kind of describes what I mean.
For more context, pretty much the same behavior can be seen here https://github.com/usunil0/slate-paged/tree/master (where I got the core idea for most of the code)
(Although the last node is active as if you could type something in, as soon as you try so, normalization is called, when it should’ve been called before for this to work as expected)
I know this is due to how normalization is triggered, as mentioned here https://github.com/ianstormtaylor/slate/issues/3465
I’d like to know of any ideas/possible workarounds for this problem. How can I call normalization for all children nodes under a certain parent(as in my “page” case)?