• Stars
    star
    123
  • Rank 284,238 (Top 6 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created almost 4 years ago
  • Updated over 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

workflowy like editor built with draft-js. Used in https://deepnotes.in.

deepnotes-editor is the editor used in deepnotes.in. It's a clone of the workflowy.com editor written in draft-js. deepnotes-editor can be used as a react component.

Here's a gif of how it works -

deepnotes editor demo

Why deepnotes-editor?

  • Supports infinitely nested lists
  • Every list item can be zoomed into. Therefore every list item can be thought of as a document in itself
  • Nested lists can be collapsed to reduce clutter
  • Powerful keyboard shortcuts so that you don't have to remove your hands from the keyboard when navigating the documents
  • Supports hashtags, automatic link detection and inline code block formatting
  • Bookmarking of any list item

Desktop only

deepnotes-editor doesn't work well on mobile browsers. That's because draft-js itself does not work well on mobile browsers.

Usage -

Install deepnoter-editor

npm install deepnotes-editor # or yarn add deepnotes-editor

Use anywhere in your react codebase

import Editor from 'deepnotes-editor';

// it will look like it's not working without the css
import 'deepnotes-editor/dist/deepnotes-editor.css';

// inside your dom heirarchy somewhere
<div>
  <Editor onChange={editorState => saveToDb(editorState)} />
</div>

How to save editor state?

You can use draft-js utilities to convert the EditorState returned from onChange prop. The prop returned is an immutable-js value.

import { convertToRaw } from 'draft-js'

function saveToDb(editorState) {
  const contentState = JSON.stringify(convertToRaw(contentState)),

  saveToDbOrLocalStorage(contentState);
}

How to get back editor state from the saved content state?

You can use convertFromRaw utility from draft-js to convert the content state json back to immutable-js EditorState. You have to use the createDecorators function which comes with deepnotes-editor so that the hashtags, links and code are highlighted properly.

import DeepnotesEditor, { createDecorators} from 'deepnotes-editor';
import 'deepnotes-editor/dist/deepnotes-editor.css';

const contentState = convertFromRaw(JSON.parse(backupContent));
const editorState = EditorState.createWithContent(
  contentState,
  createDecorators()
);

// inside your render function
return <div>
  <DeepnotesEditor
    initialEditorState={editorState}
    onChange={(changedEditorState) => saveToDb(changedEditorState)}}
  />
</div>

Customization or configuration

These are the props deepnotes-editor accepts

initialEditorState

This prop can be used to initialize the editor with some saved state. The state is of the type EditorState from draft-js. See draft-js documentation for more details - https://draftjs.org/docs/quickstart-api-basics#controlling-rich-text

P. S. - This component is not a controlled component. The state of the editor is maintained inside the component. If you change the zoomedInItemId, the editor will zoom into that item. But changing the initialEditorState between renders will not change the content of the editor to the new value of initialEditorState.

initialZoomedInItemId

If we want the editor to open zoomed in on some item. Very useful if you map the zoomedin items with urls and then if a user pastes or goes to a particular item directly, the editor can be also zoomed in to that item.

searchText

If you want to filter the items by some text

onChange

onChange is a function which is called with the new EditorState on every change. This can be used to save the new EditorState to local storage or to some persistent database.

onRootChange

This prop is called if the user zooms into a particular item. Please checkout workflowy.com to understand what zoom in means.

onBookmarkClick

If a user wants to bookmarks a particular zoomed in item. This can be used to build a bookmarking feature where the user can zoom to any of the bookmarked item.

withToolbar

If you don't want the menu/toolbar which shows up above the editor, you can set withToolbar to false.

Development

Install dependencies and start the build for the Editor component

npm install # or yarn install
npm start # or yarn start

This builds to /dist and runs the project in watch mode so any edits you save inside src causes a rebuild to /dist.

This does not start a server. It only watches your files and builds and puts them in dist folder when any file in src directory changes. To view the editor in action, you need to ru na server inside the example directory.

Then run the example inside another:

cd example
npm i # or yarn to install dependencies
npm start # or yarn start

The example is served on http://localhost:1234. If that port is busy, parcel might try starting the server on some other port.

The default example imports and live reloads whatever is in /dist, so if you are seeing an out of date component, make sure TSDX is running in watch mode like we recommend above. No symlinking required, we use Parcel's aliasing.

To do a one-off build, use npm run build or yarn build.

To run tests, use npm test or yarn test.

More Repositories

1

react-telephone-input

React component for entering and validating international telephone numbers
Less
266
star
2

frolic

Learn elm faster and in a fun way
JavaScript
48
star
3

react-photo-grid

Reactjs Component for Facebook like photo/image grids
JavaScript
45
star
4

country-telephone-data

Data related to a country's telephone dial code and number formatting
JavaScript
41
star
5

statechart-calculator

Created with CodeSandbox
JavaScript
40
star
6

elm-instant

atom package to try your elm code from the editor. Provides a visual REPL and a preview pane
JavaScript
31
star
7

config

Lua
23
star
8

jssmartcheck

Property based generative testing for JavaScript
JavaScript
13
star
9

haskell-programming-book

Haskell book exercises - http://haskellbook.com/
Haskell
12
star
10

generate-ui-tests

UI interaction test generation from the browser
JavaScript
10
star
11

xstate-viz-chrome-extension

Rust
7
star
12

babel-plugin-remove-data-test-id-attribute

Remove data-test-id attribute from jsx html elements
JavaScript
5
star
13

screencapturekit-node

Swift
5
star
14

elm-rope

rope data structure implemented in elm
Elm
3
star
15

codemods

code modifiers scripts which work with jscodeshift
JavaScript
3
star
16

sketch-systems-to-xstate-parser

TypeScript
2
star
17

narrator

CSS
2
star
18

bugsnag-browser-lite

bugsnag logging in the browser
TypeScript
2
star
19

react-component-playground

An interactive playground for your react components
JavaScript
2
star
20

mithril-testing-library

Wrapper around testing-library for testing mithril components
JavaScript
2
star
21

tinyparsec

A very basic implementation of a parser combinator library in purescript
PureScript
1
star
22

mithril-onclickoutside

JavaScript
1
star
23

snowpack-express

Getting snowpack dev to work with a custom express server
JavaScript
1
star
24

react-togglegroup

Component to abstract toggling on/off states of group of items
JavaScript
1
star
25

screencapturekit-cli

A command line wrapper around swift screencapturekit
Swift
1
star
26

elm-analog-clock

Elm
1
star
27

rollick

Like codepen, but for react components
JavaScript
1
star
28

model-based-testing

Statechart based models for common UI patterns
JavaScript
1
star
29

sketch-parser-rust

Parse sketch.systems like language and convert to xstate json config
Rust
1
star