Skip to content

Instantly share code, notes, and snippets.

@satya164 satya164/BasicEditor.js Secret
Created Feb 16, 2018

Embed
What would you like to do?
/* @flow */
import * as React from 'react';
import { StyleSheet, css } from 'aphrodite';
import Helmet from 'react-helmet';
import debounce from 'lodash/debounce';
import { renderOnClient } from '../common/ComponentUtils';
import EditorSessionManager from '../utils/EditorSessionManager';
import withThemeName from './theming/withThemeName';
import colors from '../configs/colors';
import type { Annotation } from '../utils/convertErrorToAnnotation';
import type { TextFileEntry } from '../types';
type Props = {|
entry: TextFileEntry,
annotations: Array<Annotation>,
onLoad?: Function,
onChangeCode: Function,
theme: string,
keybindings?: string,
|};
type State = {|
height: string | number,
width: string | number,
|};
@withThemeName
class BasicEditor extends React.PureComponent<Props, State> {
state = {
height: '100%',
width: '640px',
};
componentDidMount() {
this._phantom.contentWindow.addEventListener('resize', this._handleResize);
this._handleResize();
this._restoreSession(this.props.entry);
}
componentWillUpdate(nextProps: Props) {
if (this.props.entry.item.path !== nextProps.entry.item.path) {
this._saveSession(this.props.entry);
this._restoreSession(nextProps.entry);
}
}
componentWillUnmount() {
this._phantom.contentWindow.removeEventListener('resize', this._handleResize);
this._saveSession(this.props.entry);
}
_getMode = entry => (entry.item.path.endsWith('.json') ? 'json' : 'jsx');
_saveSession = (entry: TextFileEntry) => {
EditorSessionManager.save(entry.item.path, this._editor.getSession());
};
_restoreSession = (entry: TextFileEntry) => {
const session = EditorSessionManager.create(
entry.item.path,
entry.item.content,
`ace/mode/${this._getMode(entry)}`
);
const editor = this._editor;
// Enable text wrapping
session.setUseWrapMode(true);
// Use 2 spaces for indentation
session.setOptions({
tabSize: 2,
useSoftTabs: true,
});
editor.setSession(session);
// Don't override Ctrl+L/Cmd+L
editor.commands.removeCommands(['gotoline']);
};
_editor: any;
_phantom: any;
_adjustSoftWrap = (editor: any) => {
const characterWidth = editor.renderer.characterWidth;
const contentWidth = editor.renderer.scroller.clientWidth;
const session = editor.getSession();
if (contentWidth > 0 && session.getUseWrapMode()) {
session.setWrapLimit(parseInt((contentWidth - 24) / characterWidth, 10));
}
};
_handleResize = debounce(
() => {
const size = this._phantom.getBoundingClientRect();
this.setState(
{
height: size.height,
width: size.width,
},
() => {
if (this._editor) {
this._editor.resize();
this._adjustSoftWrap(this._editor);
}
}
);
},
100,
{ leading: true, trailing: true }
);
_handleLoad = (editor: any) => {
this._editor = editor;
if (this.props.onLoad) {
this.props.onLoad(editor);
}
};
render() {
require('brace');
const AceEditor = require('react-ace').default;
require('brace/mode/jsx');
require('brace/mode/json');
require('brace/ext/language_tools');
require('brace/ext/searchbox');
require('ayu-ace/light');
require('ayu-ace/mirage');
require('brace/keybinding/vim');
const { onChangeCode, entry, annotations, theme } = this.props;
return (
<div className={css(styles.container)}>
<iframe ref={c => (this._phantom = c)} type="text/html" className={css(styles.phantom)} />
<AceEditor
enableBasicAutocompletion
enableLiveAutocompletion
focus
mode={this._getMode(entry)}
tabSize={2}
theme={theme === 'light' ? 'ayu-light' : 'ayu-mirage'}
onChange={onChangeCode}
name="code"
value={entry.item.content}
annotations={annotations}
editorProps={{ $blockScrolling: Infinity }}
showPrintMargin={false}
scrollMargin={[16, 0, 0, 0]}
style={{
width: this.state.width,
height: this.state.height,
lineHeight: 1.5,
}}
className={css(styles.editor, styles.fill)}
onLoad={this._handleLoad}
keyboardHandler={this.props.editorMode === 'normal' ? null : this.props.editorMode}
/>
<Helmet
style={[
{
cssText: `
/* Editor styles */
.ace_gutter {
border-right: 1px solid ${colors.border}; !important;
background: none !important;
color: #999 !important;
}
.ace_gutter-cell.ace_error {
background-image: url(${require('../assets/cross-red.png')}) !important;
background-size: 16px !important;
}
.ace_search {
right: 0 !important;
bottom: 0 !important;
left: auto !important;
top: auto !important;
margin: 0 1em !important;
border-radius: 5px 5px 0 0 !important;
background-color: #fff !important;
border: 1px solid ${colors.border} !important;
border-bottom: 0 !important;
padding: 1em !important;
padding-bottom: 1em !important;
max-width: 339px !important;
}
.ace_search_form {
border-color: ${colors.border} !important;
}
.ace_search_field {
height: 28px !important;
width: 212px !important;
color: inherit;
}
.ace_searchbtn {
height: 28px !important;
width: 33px !important;
}
.ace_replacebtn {
height: 28px !important;
}
.ace_searchbtn_close {
display: none !important;
}
.ace_tooltip {
background-color: #fbfbfb !important;
background-image: none !important;
border-color: lightgray !important;
border-radius: 0 !important;
}
/* Theme specific */
.ace_editor.ace_autocomplete.ace-ayu-mirage {
background-color: ${colors.ayu.mirage.background};
border-color: ${colors.ayu.mirage.border};
color: ${colors.ayu.mirage.text};
}
.ace_editor.ace_autocomplete.ace-ayu-mirage .ace_completion-highlight {
color: #FFCC66;
}
.ace_editor.ace_autocomplete.ace-ayu-mirage .ace_marker-layer .ace_active-line,
.ace_editor.ace_autocomplete.ace-ayu-mirage .ace_marker-layer .ace_line-hover {
background-color: rgba(255, 255, 255, .1);
border-color: transparent;
}
.ace_editor.ace-ayu-mirage .ace_search {
background-color: ${colors.ayu.mirage.background} !important;
border-color: ${colors.ayu.mirage.border} !important;
}
.ace_editor.ace-ayu-mirage .ace_search_form,
.ace_editor.ace-ayu-mirage .ace_replace_form {
border-color: ${colors.ayu.mirage.border} !important;
}
.ace_editor.ace-ayu-mirage .ace_search_field,
.ace_editor.ace-ayu-mirage .ace_searchbtn,
.ace_editor.ace-ayu-mirage .ace_replacebtn,
.ace_editor.ace-ayu-mirage .ace_searchbtn_close {
background-color: ${colors.background.dark} !important;
border-color: ${colors.ayu.mirage.border} !important;
color: inherit;
}
.ace_editor.ace-ayu-mirage .ace_button {
background-color: ${colors.background.dark} !important;
color: inherit;
}
.ace_editor.ace-ayu-mirage .ace_button:not(.checked) {
border-color: ${colors.ayu.mirage.border} !important;
}
.ace_editor.ace-ayu-mirage .ace_tooltip {
background-color: ${colors.ayu.mirage.background} !important;
border-color: ${colors.ayu.mirage.border} !important;
color: ${colors.ayu.mirage.text};
}
`,
},
]}
/>
</div>
);
}
}
export default renderOnClient(BasicEditor);
const styles = StyleSheet.create({
container: {
flex: 1,
display: 'flex',
position: 'relative',
overflow: 'hidden',
},
fill: {
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
},
resizable: {
opacity: 0,
},
editor: {
backgroundColor: 'transparent',
fontFamily: [
'Fira Code',
'Fira Mono',
'Monaco',
'Menlo',
'Ubuntu Mono',
'Consolas',
'source-code-pro',
'monospace',
],
},
phantom: {
display: 'block',
position: 'absolute',
left: 0,
top: 0,
height: '100%',
width: '100%',
pointerEvents: 'none',
opacity: 0,
},
});
@enmi2018

This comment has been minimized.

Copy link

enmi2018 commented Mar 18, 2020

very good work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.