Merge pull request #12306 from Bouncey/feature/codemirrorSkeleton
Render CodeMirror skeleton for SSR
This commit is contained in:
@ -1201,3 +1201,4 @@ and (max-width : 400px) {
|
|||||||
@import "map.less";
|
@import "map.less";
|
||||||
@import "sk-wave.less";
|
@import "sk-wave.less";
|
||||||
@import "classic-modal.less";
|
@import "classic-modal.less";
|
||||||
|
@import "skeleton-shimmer.less";
|
||||||
|
41
client/less/skeleton-shimmer.less
Normal file
41
client/less/skeleton-shimmer.less
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
@keyframes skeletonShimmer{
|
||||||
|
0% {
|
||||||
|
transform: translateX(-48px);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateX(1000px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.shimmer {
|
||||||
|
position: relative;
|
||||||
|
min-height: 18px;
|
||||||
|
|
||||||
|
.row {
|
||||||
|
height: 18px;
|
||||||
|
|
||||||
|
.col-xs-12 {
|
||||||
|
padding-right: 12px;
|
||||||
|
height: 17px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sprite-wrapper {
|
||||||
|
background-color: #333;
|
||||||
|
height: 17px;
|
||||||
|
width: 75%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sprite {
|
||||||
|
animation-name: skeletonShimmer;
|
||||||
|
animation-duration: 2.5s;
|
||||||
|
animation-timing-function: linear;
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
animation-direction: normal;
|
||||||
|
background: white;
|
||||||
|
box-shadow: 0 0 3px 2px;
|
||||||
|
height: 17px;
|
||||||
|
width: 2px;
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,8 @@ import Codemirror from 'react-codemirror';
|
|||||||
import NoSSR from 'react-no-ssr';
|
import NoSSR from 'react-no-ssr';
|
||||||
import PureComponent from 'react-pure-render/component';
|
import PureComponent from 'react-pure-render/component';
|
||||||
|
|
||||||
|
import CodeMirrorSkeleton from '../skeleton/CodeMirrorSkeleton.jsx';
|
||||||
|
|
||||||
const mapStateToProps = createSelector(
|
const mapStateToProps = createSelector(
|
||||||
state => state.app.windowHeight,
|
state => state.app.windowHeight,
|
||||||
state => state.app.navHeight,
|
state => state.app.navHeight,
|
||||||
@ -123,7 +125,7 @@ export class Editor extends PureComponent {
|
|||||||
className='challenges-editor'
|
className='challenges-editor'
|
||||||
style={ style }
|
style={ style }
|
||||||
>
|
>
|
||||||
<NoSSR>
|
<NoSSR onSSR={ <CodeMirrorSkeleton content={ content } /> }>
|
||||||
<Codemirror
|
<Codemirror
|
||||||
onChange={ this.handleChange }
|
onChange={ this.handleChange }
|
||||||
options={ this.createOptions({ executeChallenge, mode, options }) }
|
options={ this.createOptions({ executeChallenge, mode, options }) }
|
||||||
|
@ -3,6 +3,8 @@ import PureComponent from 'react-pure-render/component';
|
|||||||
import NoSSR from 'react-no-ssr';
|
import NoSSR from 'react-no-ssr';
|
||||||
import Codemirror from 'react-codemirror';
|
import Codemirror from 'react-codemirror';
|
||||||
|
|
||||||
|
import CodeMirrorSkeleton from '../skeleton/CodeMirrorSkeleton.jsx';
|
||||||
|
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
lineNumbers: false,
|
lineNumbers: false,
|
||||||
mode: 'javascript',
|
mode: 'javascript',
|
||||||
@ -20,7 +22,7 @@ export default class extends PureComponent {
|
|||||||
const { output } = this.props;
|
const { output } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className='challenge-log'>
|
<div className='challenge-log'>
|
||||||
<NoSSR>
|
<NoSSR onSSR={ <CodeMirrorSkeleton content={ output } /> }>
|
||||||
<Codemirror
|
<Codemirror
|
||||||
options={ defaultOptions }
|
options={ defaultOptions }
|
||||||
value={ output }
|
value={ output }
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
import React, { PropTypes } from 'react';
|
||||||
|
import PureComponent from 'react-pure-render/component';
|
||||||
|
import { Grid, Col, Row } from 'react-bootstrap';
|
||||||
|
|
||||||
|
const propTypes = {
|
||||||
|
content: PropTypes.string
|
||||||
|
};
|
||||||
|
export default class CodeMirrorSkeleton extends PureComponent {
|
||||||
|
|
||||||
|
renderLine(line, i) {
|
||||||
|
return (
|
||||||
|
<div className='shimmer' key={ i }>
|
||||||
|
<Row>
|
||||||
|
<Col xs={ 12 }>
|
||||||
|
<div className='sprite-wrapper'>
|
||||||
|
<div className='sprite' />
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
content
|
||||||
|
} = this.props;
|
||||||
|
const editorLines = content.split('\n');
|
||||||
|
return (
|
||||||
|
<div className='ReactCodeMirror'>
|
||||||
|
<div className='CodeMirror cm-s-monokai CodeMirror-wrap'>
|
||||||
|
<div className='CodeMirror-scrollbar-filler' />
|
||||||
|
<div className='CodeMirror-gutter-filler' />
|
||||||
|
<div className='CodeMirror-scroll'>
|
||||||
|
<div
|
||||||
|
className='CodeMirror-sizer'
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
minHeight: (editorLines.length * 18) + 'px',
|
||||||
|
overflow: 'hidden'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className='CodeMirror-lines'>
|
||||||
|
<div className='CodeMirror-code'>
|
||||||
|
<Grid>
|
||||||
|
{ editorLines.map(this.renderLine) }
|
||||||
|
</Grid>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeMirrorSkeleton.displayName = 'CodeMirrorSkeleton';
|
||||||
|
CodeMirrorSkeleton.propTypes = propTypes;
|
Reference in New Issue
Block a user