0.3.0 • Published 5 years ago
@warren-bank/react-trix-editor v0.3.0
react-trix-editor
React component for Basecamp's Trix rich text editor
Origin story
I'm adding an HTML editor to Secure-Webmail
did a quick survey of what's available:
library size (min+gzip) size (min) jquery bootstrap react link pell 1.38kB 3.54kB https://github.com/jaredreich/pell squire 16kB 49kB https://github.com/neilj/Squire medium-editor 27kB 105kB https://github.com/yabwe/medium-editor quill 43kB 205kB https://github.com/quilljs/quill trix 47kB 204kB https://github.com/basecamp/trix ckeditor 163kB 551kB https://ckeditor.com trumbowyg 8kB 23kB x https://github.com/Alex-D/Trumbowyg summernote 26kB 93kB x x https://github.com/summernote/summernote draft 46kB 147kB x https://github.com/facebook/draft-js froala 52kB 186kB x https://github.com/froala/wysiwyg-editor tinymce 157kB 491kB x https://github.com/tinymce/tinymce ruled out the ones that depend on jQuery
- tried out the rest
- Trix is the only html editor that could properly generate nested lists
What this is, and what this is not..
- Trix uses a very non-opinionated approach
- the library provides a lot of low-level events to enable deep customization, but doesn't provide much high-level functionality out-of-the-box
- the purpose of this library is to:
- provide a React component wrapper around Trix
- encapsulate all of the customizations that I want for my particular use-case
- share the result for anyone who has a similar need
Customizations
- file attachments:
- are NOT uploaded to any server
- the only files of any interest are images, which are embedded (using a
data:
URI)
- additional toolbar buttons:
- Embed an image
- opens a file-chooser dialog
- embeds the image(s)
- Horizontal rule
- adds an
<hr />
tag
- adds an
- Embed an image
- behavior:
- the editor is a fixed height, and a vertical scrollbar is used (when necessary)
- the editor automatically scrolls, such that the cursor is visible in the middle of the viewport, when:
- image(s) are embedded
- rich text content is pasted into the editor
React props
set_exportTrixElement
- Function
set_exportHTML
- Function
set_exportDocument
- Function
document
- Object
autofocus
- Boolean
placeholder
- String
notes:
- all React props are optional
Anti-Pattern
set_exportTrixElement
set_exportHTML
set_exportDocument
- these are functions passed to
TrixEditor
TrixEditor
calls these functions when:- componentDidMount
- componentDidUpdate
TrixEditor
passes a (corresponding) function back to the parent component- after the parent component has received a reference to these functions, they can be called to obtain (corresponding) data from the
TrixEditor
component
- after the parent component has received a reference to these functions, they can be called to obtain (corresponding) data from the
- these are functions passed to
specifically:
set_exportTrixElement
is passed a reference to the function:exportTrixElement
exportTrixElement
returns: the HTMLElement bound to this instance of Trix
set_exportHTML
is passed a reference to the function:exportHTML
exportHTML
returns: a string of HTML text
set_exportDocument
is passed a reference to the function:exportDocument
exportDocument
returns: an immutable Object representation of the current state of the document in the editor- the data type of this immutable Object is the same as the React prop:
document
- the data type of this immutable Object is the same as the React prop:
Installation:
npm install --save @warren-bank/react-trix-editor
Dependencies:
- I chose to not bundle Trix with this component
- it expects the global:
window.Trix
- this can be satisfied in 1 of 2 ways:
- include Trix externally
- example: from a CDN
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/trix/1.0.0/trix.css" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/trix/1.0.0/trix.js"></script>
- example: from a CDN
- include Trix internally
- add as a project dependency
- in the script used as the entry-point for Webpack:
const Trix = require('trix'); require('trix/dist/trix.css'); window.Trix = Trix
- include Trix externally
- this can be satisfied in 1 of 2 ways:
- it expects the global:
Demos:
notes:
- both demos are nearly identical; they only differ in the way Trix is included
- in addition to rendering an instance of the
TrixEditor
component:- the App component sets 2 interval timers:
- every 5 seconds:
- a reference to the immutable Object representation of the current state of the document in the editor is stored in a class instance property
- every 1 second:
- this class instance property is saved to state
- the
TrixEditor
component will update only ifthis.state.document
has changed- when this does occur:
- the string of HTML text returned by
exportHTML
is logged to console - the position of the cursor in the editor jumps to the beginning
- makes the demo(s) annoying to use, but does effectively prove that the feature is working
- this methodology would never be used in a real app; it's entirely contrived
- the string of HTML text returned by
- when this does occur:
- every 5 seconds:
- the App component sets 2 interval timers:
Legal:
- copyright: Warren Bank
- license: GPL-2.0