UNPKG

11.9 kBMarkdownView Raw
1[![Coverage](https://img.shields.io/coveralls/scniro/react-codemirror2.svg?style=flat-square)](https://coveralls.io/github/scniro/react-codemirror2)
2[![Downloads](https://img.shields.io/npm/dm/react-codemirror2.svg?style=flat-square)](https://www.npmjs.com/package/react-codemirror2)
3[![NPM Version](https://img.shields.io/npm/v/react-codemirror2.svg?style=flat-square)](https://www.npmjs.com/package/react-codemirror2)
4
5### react-codemirror2
6
7demo @ [scniro.github.io/react-codemirror2](https://scniro.github.io/react-codemirror2/)
8
9
10## Install
11
12```bash
13npm install react-codemirror2 codemirror --save
14```
15
16`react-codemirror2` ships with the notion of an [uncontrolled](https://reactjs.org/docs/uncontrolled-components.html) and [controlled](https://reactjs.org/docs/forms.html#controlled-components) component. `UnControlled` consists of a simple wrapper largely powered by the inner workings of `codemirror` itself, while `Controlled` will demand state management from the user, preventing codemirror changes unless properly handled via `value`. The latter will offer more control and likely be more appropriate with [redux](http://redux.js.org/) heavy apps.
17
18## uncontrolled usage
19```jsx
20import {UnControlled as CodeMirror} from 'react-codemirror2'
21
22<CodeMirror
23 value='<h1>I ♥ react-codemirror2</h1>'
24 options={{
25 mode: 'xml',
26 theme: 'material',
27 lineNumbers: true
28 }}
29 onChange={(editor, data, value) => {
30 }}
31/>
32```
33
34## controlled usage
35```jsx
36import {Controlled as CodeMirror} from 'react-codemirror2'
37
38<CodeMirror
39 value={this.state.value}
40 options={options}
41 onBeforeChange={(editor, data, value) => {
42 this.setState({value});
43 }}
44 onChange={(editor, data, value) => {
45 }}
46/>
47```
48
49## requiring codemirror resources
50
51- [codemirror](https://www.npmjs.com/package/codemirror)
52
53`codemirror` comes as a [peer dependency](https://nodejs.org/en/blog/npm/peer-dependencies/), meaning you'll need to require it in your project _in addition to_ `react-codemirror2`. This prevents any versioning conflicts that would arise if `codemirror` came as a dependency through this wrapper. It's been observed that version mismatches can cause difficult to trace issues such as syntax highlighting disappearing without any explicit errors/warnings
54
55- additional
56
57Since codemirror ships mostly unconfigured, the user is left with the responsibility for requiring any additional resources should they be necessary. This is often the case when specifying certain [language modes]() and [themes](). How to import/require these assets will vary according to the specifics of your development environment. Below is a sample to include the assets necessary to specify a mode of `xml` (HTML) and a `material` theme.
58
59> note that the base codemirror.css file is required in all use cases
60
61```css
62@import 'codemirror/lib/codemirror.css';
63@import 'codemirror/theme/material.css';
64```
65
66```jsx
67import CodeMirror from 'react-codemirror2';
68require('codemirror/mode/xml/xml');
69require('codemirror/mode/javascript/javascript');
70```
71
72## props
73
74| prop | type&nbsp;*`default`* | components | description |
75|--------------|------------------------|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------|
76| `autoCursor` | boolean&nbsp;*`true`* | `Controlled`&nbsp;`UnControlled` | should component cursor position correct when `value` changed | |
77| `autoScroll` | boolean&nbsp;*`true`* | `Controlled`&nbsp;`UnControlled` | should component scroll cursor position into view when `value` changed |
78| `className` | string | `Controlled`&nbsp;`UnControlled` | pass through class *`class="react-codemirror2 className"`* |
79| `defineMode` | object | `Controlled`&nbsp;`UnControlled` | pass a [custom mode](http://marijnhaverbeke.nl/blog/codemirror-mode-system.html) via `{name: 'custom', fn: myModeFn}` |
80| `detach` | boolean | `UnControlled` | should component ignore new props |
81| `options` | object | `Controlled`&nbsp;`UnControlled` | [codemirror configuration](https://codemirror.net/doc/manual.html#config) |
82| `value` | string | *`Controlled`&nbsp;`UnControlled` | * component value _**must be managed for controlled components**_ |
83
84## props cont. (wrapped codemirror [programming api](https://codemirror.net/doc/manual.html#api))
85
86- `cursor` - *[setCursor](https://codemirror.net/doc/manual.html#setCursor)*
87> will programmatically set cursor to the position specified
88```jsx
89<CodeMirror
90 [...]
91 cursor={{
92 line: 5,
93 ch: 10
94 }}
95 onCursor={(editor, data) => {}}
96/>
97```
98- `scroll` - *[scrollTo](https://codemirror.net/doc/manual.html#scrollTo)*
99> will programmatically scroll to the specified coordinate
100```jsx
101<CodeMirror
102 [...]
103 scroll={{
104 x: 50,
105 y: 50
106 }}
107 onScroll={(editor, data) => {}}
108/>
109```
110- `selection={{ranges: array<{anchor, head}>, focus?: boolean}` - *[setSelections](https://codemirror.net/doc/manual.html#setSelections)*
111> will programmatically select the ranges specified
112```jsx
113<CodeMirror
114 [...]
115 selection={{
116 ranges: [{
117 anchor: {ch: 8, line: 5},
118 head: {ch: 37, line: 5}
119 }],
120 focus: true // defaults false if not specified
121 }}
122 onSelection={(editor, data) => {}}
123/>
124```
125
126## events
127
128| event | components | description |
129|------------------------------------------------------------------|----------------------------------|-------------------------------------------------------------------------------------------------------------|
130| **editorDidAttach(editor)** | `UnControlled` | component is now **responding** to new props |
131| **editorDidConfigure(editor)** | `Controlled`&nbsp;`UnControlled` | component configuration has been set |
132| **editorDidDetach(editor)** | `UnControlled` | component is now **ignoring** new props |
133| **editorDidMount(editor,&nbsp;_[next]_)** | `Controlled`&nbsp;`UnControlled` | * invoking optional `next` will trigger `editorDidConfigure` |
134| **editorWillUnmount(editor)** | `Controlled`&nbsp;`UnControlled` | invoked before [`componentWillUnmount`](https://reactjs.org/docs/react-component.html#componentwillunmount) |
135| **onBeforeChange(editor,&nbsp;data,&nbsp;value,&nbsp;_[next]_)** | `Controlled`&nbsp;`UnControlled` | * if used, `next` is returned via `UnControlled` and *must* be invoked to trigger onChange |
136| **onChange(editor,&nbsp;data,&nbsp;value)** | `Controlled`&nbsp;`UnControlled` | the component value has been changed |
137
138## events cont. [wrapped codemirror events](https://codemirror.net/doc/manual.html#events)
139
140- `onBlur(editor, event)` - *[blur](https://codemirror.net/doc/manual.html#event_blur)*
141- `onContextMenu(editor, event)` - *[contextmenu](https://codemirror.net/doc/manual.html#event_dom)*
142- `onCopy(editor)` - *[copy](https://codemirror.net/doc/manual.html#event_dom)*
143- `onCursor(editor, data)`- *[cursorActivity](https://codemirror.net/doc/manual.html#event_doc_cursorActivity)*
144- `onCursorActivity(editor)` - *[cursorActivity](https://codemirror.net/doc/manual.html#event_cursorActivity)*
145- `onCut(editor)` - *[cut](https://codemirror.net/doc/manual.html#event_dom)*
146- `onDblClick(editor, event)` - *[dblclick](https://codemirror.net/doc/manual.html#event_dom)*
147- `onDragEnter(editor, event)` - *[dragenter](https://codemirror.net/doc/manual.html#event_dom)*
148- `onDragOver(editor, event)` - *[dragover](https://codemirror.net/doc/manual.html#event_dom)*
149- `onDragLeave(editor, event)` - *[dragleave](https://codemirror.net/doc/manual.html#event_dom)*
150- `onDragStart(editor, event)` - *[dragstart](https://codemirror.net/doc/manual.html#event_dom)*
151- `onDrop(editor, event)` - *[drop](https://codemirror.net/doc/manual.html#event_dom)*
152- `onFocus(editor, event)` - *[focus](https://codemirror.net/doc/manual.html#event_focus)*
153- `onGutterClick(editor, lineNumber, gutter, event)` - *[gutterClick](https://codemirror.net/doc/manual.html#event_gutterClick)*
154- `onInputRead(editor, changeObj)` - *[gutterClick](https://codemirror.net/doc/manual.html#events)*
155- `onKeyDown(editor, event)` - *[keydown](https://codemirror.net/doc/manual.html#event_dom)*
156- `onKeyHandled(editor, key, event)` - *[keyhandled](https://codemirror.net/doc/manual.html#events)*
157- `onKeyPress(editor, event)` - *[keypress](https://codemirror.net/doc/manual.html#event_dom)*
158- `onKeyUp(editor, event)` - *[keyup](https://codemirror.net/doc/manual.html#event_dom)*
159- `onMouseDown(editor, event)` - *[mousedown](https://codemirror.net/doc/manual.html#event_dom)*
160- `onPaste(editor)` - *[paste](https://codemirror.net/doc/manual.html#event_dom)*
161- `onScroll(editor, data)` - *[scroll](https://codemirror.net/doc/manual.html#event_scroll)*
162- `onSelection(editor, data)` - *[beforeSelectionChange](https://codemirror.net/doc/manual.html#event_doc_beforeSelectionChange)*
163- `onTouchStart(editor, event)` - *[touchstart](https://codemirror.net/doc/manual.html#event_dom)*
164- `onUpdate(editor, event)` - *[update](https://codemirror.net/doc/manual.html#event_update)*
165- `onViewportChange(editor, from, to)` - *[viewportChange](https://codemirror.net/doc/manual.html#event_viewportChange)*
166
167## FAQ
168
169- Is server side rendering supported?
170
171Yes. react-codemirror2 will prevent rendering in absence of `navigator`. You can also force the component to not render via a `PREVENT_CODEMIRROR_RENDER` global.
172
173- How can I get the instance?
174
175The recommended technique to get the instance is to persist the `editor` returned via event callbacks. There is no static method to get it on demand, e.g. `CodeMirror.getInstance()`. Example...
176
177```jsx
178constructor() {
179 this.instance = null;
180}
181
182render() {
183 <CodeMirror editorDidMount={editor => { this.instance = editor }}/>
184}
185```
186
187- How can I have a resizable editor?
188
189Check out [bokuweb/re-resizable](https://github.com/bokuweb/re-resizable). Wrapping your component with `<Resizable/>'s` works well
190
191## Contributing
192
193Pull Requests are welcome. Be mindful of the available scripts below to help submitting a well-received contribution.
194
195- `npm run start` to run the app on `localhost:8000`
196- `npm run test` to ensure tests continue to pass
197- `npm run build` to generate the demo bundle
198
199note that it's necessary to bump the [package.json](https://github.com/scniro/react-codemirror2/blob/master/package.json#L3) version prior to final `npm run build` so we can grab the proposed new version as seen in the demo header. Also note, the core changes are to be made in `src/index.tsx` as `./index.js` and `./index.d.ts` are _generated_
200
201[MIT](./LICENSE) © 2020 [scniro](https://github.com/scniro)