|
// remirror.js hellow world example code |
|
// |
|
// src |
|
// https://github.com/ifiokjr/remirror/blob/master/docs/examples/document-model.tsx |
|
// |
|
// discussion |
|
// https://discuss.prosemirror.net/t/using-with-react/904/14 |
|
|
|
import React, { FunctionComponent, MouseEventHandler, useState } from 'react'; |
|
|
|
import { memoize } from '@remirror/core'; |
|
import { Bold, Italic, Underline } from '@remirror/core-extensions'; |
|
import { bubblePositioner, Remirror, RemirrorEventListener, RemirrorProps } from '@remirror/react'; |
|
import { RenderTree } from '@remirror/renderer-react'; |
|
|
|
function EditorLayout({initialJson}) { |
|
const extensions = [new Bold(), new Italic(), new Underline()]; |
|
const [json, setJson] = useState(JSON.stringify(initialJson, null, 2)); |
|
const [displayJson, toggleJsonDisplay] = useState(false); |
|
|
|
const onChange = ({ getJSON }) => { |
|
const newJson = JSON.stringify(getJSON(), null, 2); |
|
setJson(newJson); |
|
}; |
|
|
|
|
|
// hand-compiled typescript source that was here to js like so... |
|
// var runAction = memoize(function (method) { return function (e) { |
|
// e.preventDefault(); |
|
// method(); |
|
// }; }); |
|
|
|
const runAction = memoize( |
|
function (method) { |
|
return function (e) { |
|
e.preventDefault(); |
|
method(); |
|
}; |
|
}); |
|
|
|
|
|
// TODO figure out how to set this up - see |
|
// /Users/100ideas/dev/da-play/1_overmind/remirror/support/types/prosemirror-view/index.d.ts#406 |
|
const handleDoubleClick = (view, pos, event) => { |
|
console.dir(view, pos, event) |
|
return true |
|
} |
|
|
|
return ( |
|
<div |
|
style={{ |
|
gridTemplateColumns: '1fr', |
|
gridTemplateRows: 'auto 1fr', |
|
gridTemplateAreas: '"editor" "json"', |
|
}} |
|
> |
|
<div style={{ gridArea: 'editor' }}> |
|
<Remirror |
|
attributes={{ 'data-test-id': 'editor-instance' }} |
|
onChange={onChange} |
|
placeholder='Start typing for magic...' |
|
autoFocus={true} |
|
extensions={extensions} |
|
initialContent={initialJson} |
|
handleDoubleClick={handleDoubleClick} |
|
> |
|
{({ getPositionerProps, actions }) => { |
|
const props = getPositionerProps({ |
|
positionerId: 'bubble', |
|
...bubblePositioner, |
|
}); |
|
return ( |
|
<div> |
|
<div |
|
style={{ |
|
position: 'absolute', |
|
bottom: props.isActive ? props.bottom : -9999, |
|
left: props.isActive ? props.left : -9999, |
|
}} |
|
ref={props.ref} |
|
> |
|
<button |
|
style={{ |
|
backgroundColor: actions.bold.isActive() ? 'white' : 'pink', |
|
fontWeight: actions.bold.isActive() ? 600 : 300, |
|
}} |
|
disabled={!actions.bold.isEnabled()} |
|
onClick={runAction(actions.bold.command)} |
|
> |
|
B |
|
</button> |
|
<button |
|
style={{ |
|
backgroundColor: actions.italic.isActive() ? 'white' : 'pink', |
|
fontWeight: actions.italic.isActive() ? 600 : 300, |
|
}} |
|
disabled={!actions.italic.isEnabled()} |
|
onClick={runAction(actions.italic.command)} |
|
> |
|
i |
|
</button> |
|
<button |
|
style={{ |
|
backgroundColor: actions.underline.isActive() ? 'white' : 'pink', |
|
fontWeight: actions.underline.isActive() ? 600 : 300, |
|
}} |
|
disabled={!actions.underline.isEnabled()} |
|
onClick={runAction(actions.underline.command)} |
|
> |
|
u |
|
</button> |
|
</div> |
|
</div> |
|
); |
|
}} |
|
</Remirror> |
|
</div> |
|
<div> |
|
<pre |
|
style={{ |
|
width: '100%', |
|
height: '50%', |
|
overflowY: 'auto', |
|
padding: '1em', |
|
background: 'black', |
|
color: 'lawngreen', |
|
}} |
|
> |
|
{json} |
|
</pre> |
|
</div> |
|
</div> |
|
); |
|
}; |
|
|
|
|
|
const markMap = { |
|
bold: 'strong', |
|
italic: 'em', |
|
// em: 'em', |
|
// strong: 'strong', |
|
code: 'code', |
|
link: 'a', |
|
underline: 'u', |
|
}; |
|
|
|
|
|
// prosemirror-view ? |
|
export function DocumentModelEditor() { return <EditorLayout initialJson={initialJson2} /> }; |
|
|
|
// prosemirror DOMserializer renders output |
|
export function BasicRendererReact() { return <RenderTree json={initialJson1} /> }; |
|
export default function () { return <RenderTree json={initialJson2} markMap={markMap} /> }; |
|
|
|
const initialJson1 = { |
|
type: 'doc', |
|
content: [ |
|
{ |
|
type: 'paragraph', |
|
content: [ |
|
{ |
|
type: 'text', |
|
text: 'Better docs to come soon...', |
|
}, |
|
], |
|
}, |
|
{ |
|
type: 'paragraph', |
|
}, |
|
{ |
|
type: 'paragraph', |
|
content: [ |
|
{ |
|
type: 'text', |
|
text: 'However for now it is important that something is in place.', |
|
}, |
|
], |
|
}, |
|
], |
|
}; |
|
|
|
const initialJson2 = { |
|
"type": "doc", |
|
"content": [ |
|
{ |
|
"type": "paragraph", |
|
"content": [ |
|
{ |
|
"type": "text", |
|
"marks": [ |
|
{ |
|
"type": "italic" |
|
} |
|
], |
|
"text": "Better docs to come soon..." |
|
} |
|
] |
|
}, |
|
{ |
|
"type": "paragraph", |
|
"content": [ |
|
{ |
|
"type": "text", |
|
"text": "..." |
|
} |
|
] |
|
}, |
|
{ |
|
"type": "paragraph", |
|
"content": [ |
|
{ |
|
"type": "text", |
|
"marks": [ |
|
{ |
|
"type": "bold" |
|
} |
|
], |
|
"text": "What’s the logic in your updateView method?" |
|
} |
|
] |
|
}, |
|
{ |
|
"type": "paragraph", |
|
"content": [ |
|
{ |
|
"type": "text", |
|
"text": "I have a similar challenge to you, and one idea I’ve been chewing on is to write a custom element that scrolls the page to bring itself into view. The idea is to do this in the connected callback, so that when it is attached to the DOM it can schedule scrolling via requestAnimationFrame. You would hook this into ProseMirror by just rendering it as a decoration." |
|
} |
|
] |
|
}, |
|
{ |
|
"type": "paragraph", |
|
"content": [ |
|
{ |
|
"type": "text", |
|
"text": "There’s probably a few wrinkles I haven’t thought about, but one that does come to mind is:" |
|
} |
|
] |
|
}, |
|
{ |
|
"type": "paragraph" |
|
}, |
|
{ |
|
"type": "paragraph", |
|
"content": [ |
|
{ |
|
"type": "text", |
|
"marks": [ |
|
{ |
|
"type": "bold" |
|
} |
|
], |
|
"text": "After the scroll has completed, how do you stop it from repeating when the decoration is rendered again?" |
|
} |
|
] |
|
}, |
|
{ |
|
"type": "paragraph", |
|
"content": [ |
|
{ |
|
"type": "text", |
|
"text": "However for now it is important that something is in place." |
|
} |
|
] |
|
} |
|
] |
|
} |