/
editor.tsx
131 lines (124 loc) · 4.16 KB
/
editor.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import { Component, h, Prop, State } from '@stencil/core'
import CodeFlask from 'codeflask'
import { createReactComponentGenerator } from '@teleporthq/teleport-component-generator-react'
import { createVueComponentGenerator } from '@teleporthq/teleport-component-generator-vue'
import Prism from 'prismjs'
import 'prismjs/components/prism-jsx'
@Component({
tag: 'teleport-uidl-repl',
styleUrl: 'editor.css',
shadow: false,
})
export class Editor {
@Prop() public uidl: string
@Prop() public dark: boolean = false
@State() public selectedCSSFlavour: string
@State() public selectedFramework: 'vue' | 'react' = 'react'
@State() public showCssFile: boolean = false
private jsonEditor: any
private javascriptEditor: any
private cssEditor: any
public componentDidLoad() {
this.setupEditor()
}
public render() {
return (
<div class="repl-wrapper" data-theme={this.dark ? 'dark' : ''}>
<div class="repl-options">
<div class="repl-options-right">
<div class="repl-options-framework">
<div>
<input
type="radio"
id="react"
name="framework"
value="react"
checked
onInput={(event) => this.handleChange(event)}
/>
<label htmlFor="react">React</label>
</div>
<div>
<input
type="radio"
id="vue"
name="framework"
value="vue"
onInput={(event) => this.handleChange(event)}
/>
<label htmlFor="vue">Vue</label>
</div>
</div>
{this.selectedFramework === 'react' ? (
<select onInput={(event) => this.handleSelect(event)}>
<option value="InlineStyles">InlineStyles</option>
<option value="JSS">JSS</option>
<option value="StyledJSX">StyledJSX</option>
<option value="CSSModules">CSSModules</option>
<option value="StyledComponents">StyledComponents</option>
</select>
) : (
''
)}
</div>
</div>
<div class="editor-wrapper">
<div id="jsonEditor">{this.uidl}</div>
<div>
<div id="javascriptEditor" class="javascript-editor">
{this.generateComponent}
</div>
<div class={this.showCssFile ? 'show-css-tab' : 'hide-css-tab'} id="css-tab">
<div class="css-tab-header" onClick={() => (this.showCssFile = !this.showCssFile)} />
<div id="cssEditor" />
</div>
</div>
</div>
</div>
)
}
private setupEditor() {
this.jsonEditor = new CodeFlask('#jsonEditor', {
language: 'js',
lineNumbers: true,
})
this.javascriptEditor = new CodeFlask('#javascriptEditor', {
language: 'jsx',
readonly: true,
})
this.javascriptEditor.addLanguage('jsx', Prism.languages.jsx)
this.jsonEditor.onUpdate(() => {
this.generateComponent()
})
this.cssEditor = new CodeFlask('#cssEditor', {
language: 'css',
readonly: true,
})
this.cssEditor.addLanguage('css', Prism.languages.css)
}
private async generateComponent() {
let generator = createReactComponentGenerator(this.selectedCSSFlavour)
if (this.selectedFramework === 'vue') {
generator = createVueComponentGenerator()
}
if (JSON.parse(this.jsonEditor.getCode())) {
const uidl = JSON.parse(this.jsonEditor.getCode())
const result = await generator.generateComponent(uidl)
this.javascriptEditor.updateCode(result.files[0].content.trim())
if (result.files[1]) {
this.showCssFile = true
this.cssEditor.updateCode(result.files[1].content.trim())
}
}
}
private handleChange(event) {
this.selectedFramework = event.target.value
this.generateComponent()
this.cssEditor.updateCode('')
}
private handleSelect(event) {
this.selectedCSSFlavour = event.target.value
this.generateComponent()
this.cssEditor.updateCode('')
}
}