I'm trying to build an editor on slate.js
Copied most of the code from Slate official examples.
https://github.com/ianstormtaylor/slate/blob/master/examples/hovering-menu/index.js
Whenever i select a text, everything works perfectly. Positioning is smooth and works like a charm. But gets positioning wrong after select/deselect marking action.
Here is example gif. https://i.stack.imgur.com/OWvMU.gif
Thing i changed menu classnames and HOC hovering menu.
import React, { Component } from 'react';
function withHoverMenu (Menu) {
return class extends React.Component {
componentDidMount = () => {
this.updateMenu()
}
componentDidUpdate = () => {
this.updateMenu()
}
updateMenu = () => {
const { value } = this.props
const menu = this.menu
if (!menu) return
if (value.isBlurred || value.isEmpty) {
menu.removeAttribute('style')
return
}
const selection = window.getSelection()
const range = selection.getRangeAt(0)
const rect = range.getBoundingClientRect()
console.log(rect)
menu.style.opacity = 1
menu.style.top = `${rect.top + window.scrollY - menu.offsetHeight}px`
menu.style.left = `${rect.left + window.scrollX - menu.offsetWidth / 2 + rect.width / 2}px`
}
menuRef = (menu) => {
this.menu = menu
}
render () {
return <Menu className="slate-rte-balloon" menuRef={this.menuRef} {...this.props} />
}
}
}
export default withHoverMenu;
Editor part is slightly different but nothing much.
import Menu from './menu';
import withHoverMenu from './menu-balloon';
const HoveredMenu = withHoverMenu(Menu)
class SlateRTE extends Component {
state = {
value: Value.fromJSON(initialValue)
}
onChange = ({ value }) => {
this.setState({ value })
}
render() {
return (
<div className="slate-rte">
<HoveredMenu value={this.state.value} onChange={this.onChange} />
<Editor placeholder="Enter some text..." renderMark={this.renderMark} value={this.state.value} onChange={this.onChange} />
</div>
);
}
renderMark = (props) => {
const { children, mark } = props
switch (mark.type) {
case 'bold': return <strong>{children}</strong>
case 'code': return <code>{children}</code>
case 'italic': return <em>{children}</em>
case 'underlined': return <u>{children}</u>
}
}
}