@instructure/ui-source-code-editor 10.12.0 → 10.12.1-pr-snapshot-1741273500459
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/package.json +18 -18
- package/src/SourceCodeEditor/README.md +1100 -414
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -54,190 +54,370 @@ Setting the correct language adds **syntax highlighting** and other helpful feat
|
|
|
54
54
|
|
|
55
55
|
**Note:** In case you need support for additional languages, please contact us on [GitHub](https://github.com/instructure/instructure-ui)!
|
|
56
56
|
|
|
57
|
-
```js
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
- ```js
|
|
58
|
+
const languages = {
|
|
59
|
+
json: `{
|
|
60
|
+
"name": "@instructure/ui-source-code-editor",
|
|
61
|
+
"version": "8.24.2",
|
|
62
|
+
"description": "A UI component library made by Instructure Inc.",
|
|
63
|
+
"author": "Instructure, Inc. Engineering and Product Design",
|
|
64
|
+
"module": "./es/index.js",
|
|
65
|
+
"main": "./lib/index.js",
|
|
66
|
+
"types": "./types/index.d.ts",
|
|
67
|
+
"repository": {
|
|
68
|
+
"type": "git",
|
|
69
|
+
"url": "https://github.com/instructure/instructure-ui.git"
|
|
70
|
+
},
|
|
71
|
+
}`,
|
|
72
|
+
javascript: `const fruit: string = "apple"
|
|
73
|
+
|
|
74
|
+
const re = new RegExp('ab+c')
|
|
75
|
+
|
|
76
|
+
function exampleMethod(props: Props) {
|
|
77
|
+
return props ? props.value : null
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* This is an example
|
|
82
|
+
* @param {Object} props
|
|
83
|
+
*/
|
|
84
|
+
const Example = () => {
|
|
85
|
+
return (
|
|
86
|
+
<View as="div" padding={'large'}>
|
|
87
|
+
<Position
|
|
88
|
+
renderTarget={<GoodComponent />}
|
|
89
|
+
placement='end center'
|
|
90
|
+
offsetX='20px'
|
|
91
|
+
>
|
|
92
|
+
<span style={{ padding: '8px', background: 'white' }}>
|
|
93
|
+
Positioned content
|
|
94
|
+
</span>
|
|
95
|
+
</Position>
|
|
96
|
+
</View>
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
render(<Example />)`,
|
|
101
|
+
html: `<!DOCTYPE html>
|
|
102
|
+
<html lang="en">
|
|
103
|
+
<head>
|
|
104
|
+
<meta charset="UTF-8" />
|
|
105
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
106
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
107
|
+
<title>Example app</title>
|
|
108
|
+
</head>
|
|
109
|
+
<body>
|
|
110
|
+
<div id="app">
|
|
111
|
+
<button onclick="myFunction()">Click me</button>
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
<script src="script.js"></script>
|
|
115
|
+
</body>
|
|
116
|
+
</html>`,
|
|
117
|
+
css: `a {
|
|
118
|
+
text-decoration: none;
|
|
119
|
+
|
|
120
|
+
&:hover { text-decoration: underline; }
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
a:link, a:visited, a:hover, a:active {
|
|
124
|
+
background-color: green;
|
|
125
|
+
color: white;
|
|
126
|
+
padding: 10px 25px;
|
|
127
|
+
text-align: center;
|
|
128
|
+
text-decoration: none;
|
|
129
|
+
display: inline-block;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.centertext { text-align: center; }
|
|
133
|
+
|
|
134
|
+
img { opacity: 0.5; filter: alpha(opacity=50); }`,
|
|
135
|
+
markdown: `#### The quarterly results look great!
|
|
136
|
+
|
|
137
|
+
> - Revenue was off the chart.
|
|
138
|
+
> - Profits were higher than ever.
|
|
139
|
+
|
|
140
|
+
*Everything* is going according to **plan**.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
type: example
|
|
144
|
+
---`,
|
|
145
|
+
shell: `#!/bin/bash
|
|
146
|
+
|
|
147
|
+
# example of using arguments to a script
|
|
148
|
+
echo "My first name is $1"
|
|
149
|
+
echo "My surname is $2"
|
|
150
|
+
echo "Total number of arguments is $#"
|
|
151
|
+
|
|
152
|
+
________________________________________
|
|
153
|
+
|
|
154
|
+
$ chmod a+x name.sh
|
|
155
|
+
$ ./name.sh Hans-Wolfgang Loidl
|
|
156
|
+
My first name is Hans-Wolfgang
|
|
157
|
+
My surname is Loidl
|
|
158
|
+
Total number of arguments is 2`,
|
|
159
|
+
yml: `---
|
|
160
|
+
doe: "a deer, a female deer"
|
|
161
|
+
ray: "a drop of golden sun"
|
|
162
|
+
pi: 3.14159
|
|
163
|
+
xmas: true
|
|
164
|
+
french-hens: 3
|
|
165
|
+
calling-birds:
|
|
166
|
+
- huey
|
|
167
|
+
- dewey
|
|
168
|
+
- louie
|
|
169
|
+
- fred
|
|
170
|
+
xmas-fifth-day:
|
|
171
|
+
calling-birds: four
|
|
172
|
+
french-hens: 3
|
|
173
|
+
golden-rings: 5
|
|
174
|
+
partridges:
|
|
175
|
+
count: 1
|
|
176
|
+
location: "a pear tree"
|
|
177
|
+
turtle-doves: two`
|
|
178
|
+
}
|
|
61
179
|
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
javascript: `const fruit: string = "apple"
|
|
77
|
-
|
|
78
|
-
const re = new RegExp('ab+c')
|
|
79
|
-
|
|
80
|
-
function exampleMethod(props: Props) {
|
|
81
|
-
return props ? props.value : null
|
|
82
|
-
}
|
|
180
|
+
const languageMap = {
|
|
181
|
+
json: languages.json,
|
|
182
|
+
js: languages.javascript,
|
|
183
|
+
jsx: languages.javascript,
|
|
184
|
+
javascript: languages.javascript,
|
|
185
|
+
html: languages.html,
|
|
186
|
+
css: languages.css,
|
|
187
|
+
markdown: languages.markdown,
|
|
188
|
+
sh: languages.shell,
|
|
189
|
+
shell: languages.shell,
|
|
190
|
+
bash: languages.shell,
|
|
191
|
+
yml: languages.yml,
|
|
192
|
+
yaml: languages.yml
|
|
193
|
+
}
|
|
83
194
|
|
|
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
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
195
|
+
class LanguageExamples extends React.Component {
|
|
196
|
+
state = {
|
|
197
|
+
currentLanguage: 'javascript',
|
|
198
|
+
currentValue: languageMap.javascript
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
render() {
|
|
202
|
+
const languageKeys = Object.keys(languageMap)
|
|
203
|
+
|
|
204
|
+
return (
|
|
205
|
+
<Flex alignItems="start">
|
|
206
|
+
<Flex.Item>
|
|
207
|
+
<RadioInputGroup
|
|
208
|
+
name="languageOptions"
|
|
209
|
+
value={this.state.currentLanguage}
|
|
210
|
+
description="Language"
|
|
211
|
+
onChange={(e, currentLanguage) => {
|
|
212
|
+
this.setState({
|
|
213
|
+
currentLanguage,
|
|
214
|
+
currentValue: languageMap[currentLanguage]
|
|
215
|
+
})
|
|
216
|
+
}}
|
|
217
|
+
>
|
|
218
|
+
{languageKeys.map((language) => (
|
|
219
|
+
<RadioInput key={language} label={language} value={language} />
|
|
220
|
+
))}
|
|
221
|
+
</RadioInputGroup>
|
|
222
|
+
</Flex.Item>
|
|
223
|
+
|
|
224
|
+
<Flex.Item padding="0 0 0 large" shouldGrow shouldShrink>
|
|
225
|
+
<FormField label="SourceCodeEditor with syntax highlight">
|
|
226
|
+
<SourceCodeEditor
|
|
227
|
+
label={`${this.state.currentLanguage} code editor`}
|
|
228
|
+
language={this.state.currentLanguage}
|
|
229
|
+
value={this.state.currentValue}
|
|
230
|
+
onChange={(value) => {
|
|
231
|
+
this.setState({
|
|
232
|
+
currentValue: value
|
|
233
|
+
})
|
|
234
|
+
}}
|
|
235
|
+
lineNumbers
|
|
236
|
+
lineWrapping
|
|
237
|
+
highlightActiveLine
|
|
238
|
+
highlightActiveLineGutter
|
|
239
|
+
/>
|
|
240
|
+
</FormField>
|
|
241
|
+
</Flex.Item>
|
|
242
|
+
</Flex>
|
|
243
|
+
)
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
render(<LanguageExamples />)
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
- ```js
|
|
251
|
+
const languages = {
|
|
252
|
+
json: `{
|
|
253
|
+
"name": "@instructure/ui-source-code-editor",
|
|
254
|
+
"version": "8.24.2",
|
|
255
|
+
"description": "A UI component library made by Instructure Inc.",
|
|
256
|
+
"author": "Instructure, Inc. Engineering and Product Design",
|
|
257
|
+
"module": "./es/index.js",
|
|
258
|
+
"main": "./lib/index.js",
|
|
259
|
+
"types": "./types/index.d.ts",
|
|
260
|
+
"repository": {
|
|
261
|
+
"type": "git",
|
|
262
|
+
"url": "https://github.com/instructure/instructure-ui.git"
|
|
263
|
+
},
|
|
264
|
+
}`,
|
|
265
|
+
javascript: `const fruit: string = "apple"
|
|
266
|
+
|
|
267
|
+
const re = new RegExp('ab+c')
|
|
268
|
+
|
|
269
|
+
function exampleMethod(props: Props) {
|
|
270
|
+
return props ? props.value : null
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* This is an example
|
|
275
|
+
* @param {Object} props
|
|
276
|
+
*/
|
|
277
|
+
const Example = () => {
|
|
278
|
+
return (
|
|
279
|
+
<View as="div" padding={'large'}>
|
|
280
|
+
<Position
|
|
281
|
+
renderTarget={<GoodComponent />}
|
|
282
|
+
placement='end center'
|
|
283
|
+
offsetX='20px'
|
|
284
|
+
>
|
|
285
|
+
<span style={{ padding: '8px', background: 'white' }}>
|
|
286
|
+
Positioned content
|
|
287
|
+
</span>
|
|
288
|
+
</Position>
|
|
289
|
+
</View>
|
|
290
|
+
)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
render(<Example />)`,
|
|
294
|
+
|
|
295
|
+
html: `<!DOCTYPE html>
|
|
296
|
+
<html lang="en">
|
|
297
|
+
<head>
|
|
298
|
+
<meta charset="UTF-8" />
|
|
299
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
300
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
301
|
+
<title>Example app</title>
|
|
302
|
+
</head>
|
|
303
|
+
<body>
|
|
304
|
+
<div id="app">
|
|
305
|
+
<button onclick="myFunction()">Click me</button>
|
|
306
|
+
</div>
|
|
307
|
+
|
|
308
|
+
<script src="script.js"></script>
|
|
309
|
+
</body>
|
|
310
|
+
</html>`,
|
|
311
|
+
css: `a {
|
|
312
|
+
text-decoration: none;
|
|
313
|
+
|
|
314
|
+
&:hover { text-decoration: underline; }
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
a:link, a:visited, a:hover, a:active {
|
|
318
|
+
background-color: green;
|
|
319
|
+
color: white;
|
|
320
|
+
padding: 10px 25px;
|
|
321
|
+
text-align: center;
|
|
322
|
+
text-decoration: none;
|
|
323
|
+
display: inline-block;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.centertext { text-align: center; }
|
|
327
|
+
|
|
328
|
+
img { opacity: 0.5; filter: alpha(opacity=50); }`,
|
|
329
|
+
markdown: `#### The quarterly results look great!
|
|
330
|
+
|
|
331
|
+
> - Revenue was off the chart.
|
|
332
|
+
> - Profits were higher than ever.
|
|
333
|
+
|
|
334
|
+
*Everything* is going according to **plan**.
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
type: example
|
|
338
|
+
---`,
|
|
339
|
+
shell: `#!/bin/bash
|
|
340
|
+
|
|
341
|
+
# example of using arguments to a script
|
|
342
|
+
echo "My first name is $1"
|
|
343
|
+
echo "My surname is $2"
|
|
344
|
+
echo "Total number of arguments is $#"
|
|
345
|
+
|
|
346
|
+
________________________________________
|
|
347
|
+
|
|
348
|
+
$ chmod a+x name.sh
|
|
349
|
+
$ ./name.sh Hans-Wolfgang Loidl
|
|
350
|
+
My first name is Hans-Wolfgang
|
|
351
|
+
My surname is Loidl
|
|
352
|
+
Total number of arguments is 2`,
|
|
353
|
+
yml: `---
|
|
354
|
+
doe: "a deer, a female deer"
|
|
355
|
+
ray: "a drop of golden sun"
|
|
356
|
+
pi: 3.14159
|
|
357
|
+
xmas: true
|
|
358
|
+
french-hens: 3
|
|
359
|
+
calling-birds:
|
|
360
|
+
- huey
|
|
361
|
+
- dewey
|
|
362
|
+
- louie
|
|
363
|
+
- fred
|
|
364
|
+
xmas-fifth-day:
|
|
365
|
+
calling-birds: four
|
|
366
|
+
french-hens: 3
|
|
367
|
+
golden-rings: 5
|
|
368
|
+
partridges:
|
|
369
|
+
count: 1
|
|
370
|
+
location: "a pear tree"
|
|
371
|
+
turtle-doves: two`
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const languageMap = {
|
|
375
|
+
json: languages.json,
|
|
376
|
+
js: languages.javascript,
|
|
377
|
+
jsx: languages.javascript,
|
|
378
|
+
javascript: languages.javascript,
|
|
379
|
+
html: languages.html,
|
|
380
|
+
css: languages.css,
|
|
381
|
+
markdown: languages.markdown,
|
|
382
|
+
sh: languages.shell,
|
|
383
|
+
shell: languages.shell,
|
|
384
|
+
bash: languages.shell,
|
|
385
|
+
yml: languages.yml,
|
|
386
|
+
yaml: languages.yml
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
const LanguageExamples = () => {
|
|
390
|
+
const [currentLanguage, setCurrentLanguage] = useState('javascript')
|
|
391
|
+
const [currentValue, setCurrentValue] = useState(languageMap.javascript)
|
|
145
392
|
|
|
146
|
-
---
|
|
147
|
-
type: example
|
|
148
|
-
---`,
|
|
149
|
-
shell: `#!/bin/bash
|
|
150
|
-
|
|
151
|
-
# example of using arguments to a script
|
|
152
|
-
echo "My first name is $1"
|
|
153
|
-
echo "My surname is $2"
|
|
154
|
-
echo "Total number of arguments is $#"
|
|
155
|
-
|
|
156
|
-
________________________________________
|
|
157
|
-
|
|
158
|
-
$ chmod a+x name.sh
|
|
159
|
-
$ ./name.sh Hans-Wolfgang Loidl
|
|
160
|
-
My first name is Hans-Wolfgang
|
|
161
|
-
My surname is Loidl
|
|
162
|
-
Total number of arguments is 2`,
|
|
163
|
-
yml: `---
|
|
164
|
-
doe: "a deer, a female deer"
|
|
165
|
-
ray: "a drop of golden sun"
|
|
166
|
-
pi: 3.14159
|
|
167
|
-
xmas: true
|
|
168
|
-
french-hens: 3
|
|
169
|
-
calling-birds:
|
|
170
|
-
- huey
|
|
171
|
-
- dewey
|
|
172
|
-
- louie
|
|
173
|
-
- fred
|
|
174
|
-
xmas-fifth-day:
|
|
175
|
-
calling-birds: four
|
|
176
|
-
french-hens: 3
|
|
177
|
-
golden-rings: 5
|
|
178
|
-
partridges:
|
|
179
|
-
count: 1
|
|
180
|
-
location: "a pear tree"
|
|
181
|
-
turtle-doves: two`
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const languageMap = {
|
|
185
|
-
json: languages.json,
|
|
186
|
-
js: languages.javascript,
|
|
187
|
-
jsx: languages.javascript,
|
|
188
|
-
javascript: languages.javascript,
|
|
189
|
-
html: languages.html,
|
|
190
|
-
css: languages.css,
|
|
191
|
-
markdown: languages.markdown,
|
|
192
|
-
sh: languages.shell,
|
|
193
|
-
shell: languages.shell,
|
|
194
|
-
bash: languages.shell,
|
|
195
|
-
yml: languages.yml,
|
|
196
|
-
yaml: languages.yml,
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
class LanguageExamples extends React.Component {
|
|
200
|
-
state = {
|
|
201
|
-
currentLanguage: 'javascript',
|
|
202
|
-
currentValue: languageMap.javascript,
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
render() {
|
|
206
393
|
const languageKeys = Object.keys(languageMap)
|
|
207
394
|
|
|
208
395
|
return (
|
|
209
|
-
<Flex alignItems=
|
|
396
|
+
<Flex alignItems="start">
|
|
210
397
|
<Flex.Item>
|
|
211
398
|
<RadioInputGroup
|
|
212
399
|
name="languageOptions"
|
|
213
|
-
value={
|
|
400
|
+
value={currentLanguage}
|
|
214
401
|
description="Language"
|
|
215
|
-
onChange={(e,
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
currentValue: languageMap[currentLanguage]
|
|
219
|
-
})
|
|
402
|
+
onChange={(e, newLanguage) => {
|
|
403
|
+
setCurrentLanguage(newLanguage)
|
|
404
|
+
setCurrentValue(languageMap[newLanguage])
|
|
220
405
|
}}
|
|
221
406
|
>
|
|
222
|
-
{languageKeys.map(language => (
|
|
223
|
-
<RadioInput
|
|
224
|
-
|
|
225
|
-
label={language}
|
|
226
|
-
value={language}
|
|
227
|
-
/>))}
|
|
407
|
+
{languageKeys.map((language) => (
|
|
408
|
+
<RadioInput key={language} label={language} value={language} />
|
|
409
|
+
))}
|
|
228
410
|
</RadioInputGroup>
|
|
229
411
|
</Flex.Item>
|
|
230
412
|
|
|
231
413
|
<Flex.Item padding="0 0 0 large" shouldGrow shouldShrink>
|
|
232
414
|
<FormField label="SourceCodeEditor with syntax highlight">
|
|
233
415
|
<SourceCodeEditor
|
|
234
|
-
label={`${
|
|
235
|
-
language={
|
|
236
|
-
value={
|
|
416
|
+
label={`${currentLanguage} SourceCodeEditor with syntax highlight`}
|
|
417
|
+
language={currentLanguage}
|
|
418
|
+
value={currentValue}
|
|
237
419
|
onChange={(value) => {
|
|
238
|
-
|
|
239
|
-
currentValue: value
|
|
240
|
-
})
|
|
420
|
+
setCurrentValue(value)
|
|
241
421
|
}}
|
|
242
422
|
lineNumbers
|
|
243
423
|
lineWrapping
|
|
@@ -249,11 +429,9 @@ class LanguageExamples extends React.Component {
|
|
|
249
429
|
</Flex>
|
|
250
430
|
)
|
|
251
431
|
}
|
|
252
|
-
}
|
|
253
432
|
|
|
254
|
-
render(<LanguageExamples />)
|
|
255
|
-
|
|
256
|
-
```
|
|
433
|
+
render(<LanguageExamples />)
|
|
434
|
+
```
|
|
257
435
|
|
|
258
436
|
### Controlled mode
|
|
259
437
|
|
|
@@ -261,40 +439,109 @@ SourceCodeEditor works best as an uncontrolled component (with the `defaultValue
|
|
|
261
439
|
|
|
262
440
|
We've implemented the "controlled" usage, but please let us know if you run into any performance issues or bugs.
|
|
263
441
|
|
|
264
|
-
```js
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
442
|
+
- ```js
|
|
443
|
+
class ControlledExample extends React.Component {
|
|
444
|
+
state = {
|
|
445
|
+
value: `const fruit: string = "apple"
|
|
446
|
+
|
|
447
|
+
function exampleMethod(props: Props) {
|
|
448
|
+
return props ? props.value : null
|
|
449
|
+
}`
|
|
450
|
+
}
|
|
271
451
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
452
|
+
textAreaRef = null
|
|
453
|
+
|
|
454
|
+
render() {
|
|
455
|
+
return (
|
|
456
|
+
<View display="block" background="primary">
|
|
457
|
+
<Flex alignItems="start">
|
|
458
|
+
<Flex.Item shouldGrow shouldShrink padding="0 large 0 0">
|
|
459
|
+
<FormField
|
|
460
|
+
label="Controlled code editor"
|
|
461
|
+
id="controlledCodeEditor"
|
|
462
|
+
messages={[
|
|
463
|
+
{
|
|
464
|
+
type: 'hint',
|
|
465
|
+
text: 'Type in the editor or set the value from the textarea.'
|
|
466
|
+
}
|
|
467
|
+
]}
|
|
468
|
+
>
|
|
469
|
+
<SourceCodeEditor
|
|
470
|
+
label="controlled code editor"
|
|
471
|
+
value={this.state.value}
|
|
472
|
+
onChange={(value) => {
|
|
473
|
+
this.setState({ value })
|
|
474
|
+
}}
|
|
475
|
+
highlightActiveLine
|
|
476
|
+
highlightActiveLineGutter
|
|
477
|
+
lineWrapping
|
|
478
|
+
lineNumbers
|
|
479
|
+
foldGutter
|
|
480
|
+
spellcheck
|
|
481
|
+
/>
|
|
482
|
+
</FormField>
|
|
483
|
+
</Flex.Item>
|
|
484
|
+
<Flex.Item size="50%" padding="0 0 0 large">
|
|
485
|
+
<FormFieldGroup
|
|
486
|
+
description="Set value from the outside"
|
|
487
|
+
name="setValue"
|
|
488
|
+
>
|
|
489
|
+
<TextArea
|
|
490
|
+
label={
|
|
491
|
+
<ScreenReaderContent>Change value</ScreenReaderContent>
|
|
492
|
+
}
|
|
493
|
+
textareaRef={(e) => {
|
|
494
|
+
this.textAreaRef = e
|
|
495
|
+
}}
|
|
496
|
+
defaultValue={this.state.value}
|
|
497
|
+
/>
|
|
498
|
+
<Button
|
|
499
|
+
color="primary"
|
|
500
|
+
onClick={() => {
|
|
501
|
+
this.setState({ value: this.textAreaRef.value })
|
|
502
|
+
}}
|
|
503
|
+
>
|
|
504
|
+
Update value
|
|
505
|
+
</Button>
|
|
506
|
+
</FormFieldGroup>
|
|
507
|
+
</Flex.Item>
|
|
508
|
+
</Flex>
|
|
509
|
+
</View>
|
|
510
|
+
)
|
|
511
|
+
}
|
|
275
512
|
}
|
|
276
513
|
|
|
277
|
-
|
|
514
|
+
render(<ControlledExample />)
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
- ```js
|
|
518
|
+
const ControlledExample = () => {
|
|
519
|
+
const [value, setValue] = useState(`const fruit: string = "apple"
|
|
520
|
+
|
|
521
|
+
function exampleMethod(props: Props) {
|
|
522
|
+
return props ? props.value : null
|
|
523
|
+
}`)
|
|
524
|
+
|
|
525
|
+
const textAreaRef = useRef(null)
|
|
278
526
|
|
|
279
|
-
render () {
|
|
280
527
|
return (
|
|
281
528
|
<View display="block" background="primary">
|
|
282
|
-
<Flex alignItems=
|
|
529
|
+
<Flex alignItems="start">
|
|
283
530
|
<Flex.Item shouldGrow shouldShrink padding="0 large 0 0">
|
|
284
531
|
<FormField
|
|
285
|
-
label=
|
|
286
|
-
id=
|
|
287
|
-
messages={[
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
532
|
+
label="Controlled code editor"
|
|
533
|
+
id="controlledCodeEditor"
|
|
534
|
+
messages={[
|
|
535
|
+
{
|
|
536
|
+
type: 'hint',
|
|
537
|
+
text: 'Type in the editor or set the value from the textarea.'
|
|
538
|
+
}
|
|
539
|
+
]}
|
|
291
540
|
>
|
|
292
541
|
<SourceCodeEditor
|
|
293
|
-
label=
|
|
294
|
-
value={
|
|
295
|
-
onChange={(
|
|
296
|
-
this.setState({ value })
|
|
297
|
-
}}
|
|
542
|
+
label="controlled code editor"
|
|
543
|
+
value={value}
|
|
544
|
+
onChange={(newValue) => setValue(newValue)}
|
|
298
545
|
highlightActiveLine
|
|
299
546
|
highlightActiveLineGutter
|
|
300
547
|
lineWrapping
|
|
@@ -304,19 +551,26 @@ function exampleMethod(props: Props) {
|
|
|
304
551
|
/>
|
|
305
552
|
</FormField>
|
|
306
553
|
</Flex.Item>
|
|
307
|
-
<Flex.Item size=
|
|
554
|
+
<Flex.Item size="50%" padding="0 0 0 large">
|
|
308
555
|
<FormFieldGroup
|
|
309
|
-
description=
|
|
310
|
-
name=
|
|
556
|
+
description="Set value from the outside"
|
|
557
|
+
name="setValue"
|
|
311
558
|
>
|
|
312
559
|
<TextArea
|
|
313
560
|
label={<ScreenReaderContent>Change value</ScreenReaderContent>}
|
|
314
|
-
textareaRef={(e) => {
|
|
315
|
-
|
|
561
|
+
textareaRef={(e) => {
|
|
562
|
+
textAreaRef.current = e
|
|
563
|
+
}}
|
|
564
|
+
defaultValue={value}
|
|
316
565
|
/>
|
|
317
|
-
<Button
|
|
318
|
-
|
|
319
|
-
|
|
566
|
+
<Button
|
|
567
|
+
color="primary"
|
|
568
|
+
onClick={() => {
|
|
569
|
+
if (textAreaRef.current) {
|
|
570
|
+
setValue(textAreaRef.current.value)
|
|
571
|
+
}
|
|
572
|
+
}}
|
|
573
|
+
>
|
|
320
574
|
Update value
|
|
321
575
|
</Button>
|
|
322
576
|
</FormFieldGroup>
|
|
@@ -325,10 +579,8 @@ function exampleMethod(props: Props) {
|
|
|
325
579
|
</View>
|
|
326
580
|
)
|
|
327
581
|
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
render(<ControlledExample />)
|
|
331
|
-
```
|
|
582
|
+
render(<ControlledExample />)
|
|
583
|
+
```
|
|
332
584
|
|
|
333
585
|
### Editable and readOnly
|
|
334
586
|
|
|
@@ -337,50 +589,93 @@ The editability of the content can be set with the combination of the `editable`
|
|
|
337
589
|
The `readOnly` prop works like a "preventDefault" and disables any interaction by the user or API calls (e.g. copy-paste).
|
|
338
590
|
If the `editable` prop is set to `false`, the editor is also not focusable, and the `contenteditable="false"` is set on the content.
|
|
339
591
|
|
|
340
|
-
```js
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
592
|
+
- ```js
|
|
593
|
+
class EditableExample extends React.Component {
|
|
594
|
+
state = {
|
|
595
|
+
editable: true,
|
|
596
|
+
readOnly: false
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
render() {
|
|
600
|
+
return (
|
|
601
|
+
<View
|
|
602
|
+
display="block"
|
|
603
|
+
padding="medium medium small"
|
|
604
|
+
background="primary"
|
|
605
|
+
>
|
|
606
|
+
<View display="block" margin="small none large">
|
|
607
|
+
<FormFieldGroup description="Settings" rowSpacing="small">
|
|
608
|
+
{['editable', 'readOnly'].map((prop) => (
|
|
609
|
+
<Checkbox
|
|
610
|
+
label={prop}
|
|
611
|
+
key={prop}
|
|
612
|
+
defaultChecked={this.state[prop]}
|
|
613
|
+
onChange={() => {
|
|
614
|
+
this.setState({ [prop]: !this.state[prop] })
|
|
615
|
+
}}
|
|
616
|
+
/>
|
|
617
|
+
))}
|
|
618
|
+
</FormFieldGroup>
|
|
619
|
+
</View>
|
|
620
|
+
|
|
621
|
+
<SourceCodeEditor
|
|
622
|
+
label="editable code editor"
|
|
623
|
+
language="jsx"
|
|
624
|
+
editable={this.state.editable}
|
|
625
|
+
readOnly={this.state.readOnly}
|
|
626
|
+
defaultValue={`function example() {
|
|
627
|
+
console.log('example')
|
|
628
|
+
}`}
|
|
629
|
+
/>
|
|
630
|
+
</View>
|
|
631
|
+
)
|
|
632
|
+
}
|
|
348
633
|
}
|
|
349
634
|
|
|
350
|
-
render
|
|
635
|
+
render(<EditableExample />)
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
- ```js
|
|
639
|
+
const EditableExample = () => {
|
|
640
|
+
const [settings, setSettings] = useState({
|
|
641
|
+
editable: true,
|
|
642
|
+
readOnly: false
|
|
643
|
+
})
|
|
644
|
+
|
|
351
645
|
return (
|
|
352
646
|
<View display="block" padding="medium medium small" background="primary">
|
|
353
647
|
<View display="block" margin="small none large">
|
|
354
648
|
<FormFieldGroup description="Settings" rowSpacing="small">
|
|
355
|
-
{
|
|
649
|
+
{Object.keys(settings).map((prop) => (
|
|
356
650
|
<Checkbox
|
|
357
651
|
label={prop}
|
|
358
652
|
key={prop}
|
|
359
|
-
defaultChecked={
|
|
360
|
-
onChange={() =>
|
|
361
|
-
|
|
362
|
-
|
|
653
|
+
defaultChecked={settings[prop]}
|
|
654
|
+
onChange={() =>
|
|
655
|
+
setSettings((prevState) => ({
|
|
656
|
+
...prevState,
|
|
657
|
+
[prop]: !prevState[prop]
|
|
658
|
+
}))
|
|
659
|
+
}
|
|
363
660
|
/>
|
|
364
661
|
))}
|
|
365
662
|
</FormFieldGroup>
|
|
366
663
|
</View>
|
|
367
664
|
|
|
368
665
|
<SourceCodeEditor
|
|
369
|
-
label=
|
|
666
|
+
label="editable code editor"
|
|
370
667
|
language="jsx"
|
|
371
|
-
editable={
|
|
372
|
-
readOnly={
|
|
668
|
+
editable={settings.editable}
|
|
669
|
+
readOnly={settings.readOnly}
|
|
373
670
|
defaultValue={`function example() {
|
|
374
|
-
|
|
375
|
-
}`}
|
|
671
|
+
console.log('example')
|
|
672
|
+
}`}
|
|
376
673
|
/>
|
|
377
674
|
</View>
|
|
378
675
|
)
|
|
379
676
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
render(<EditableExample />)
|
|
383
|
-
```
|
|
677
|
+
render(<EditableExample />)
|
|
678
|
+
```
|
|
384
679
|
|
|
385
680
|
### Gutter settings
|
|
386
681
|
|
|
@@ -388,30 +683,113 @@ The `lineNumbers` prop displays the line numbers in the side gutter, and the `fo
|
|
|
388
683
|
|
|
389
684
|
If any of these two props are active, the gutter is displayed, and the `highlightActiveLineGutter` highlights the active line in the gutter. (The `highlightActiveLine` prop highlights the line itself.)
|
|
390
685
|
|
|
391
|
-
```js
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
686
|
+
- ```js
|
|
687
|
+
class GutterExample extends React.Component {
|
|
688
|
+
state = {
|
|
689
|
+
lineNumbers: true,
|
|
690
|
+
foldGutter: true,
|
|
691
|
+
highlightActiveLineGutter: true,
|
|
692
|
+
highlightActiveLine: true
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
render() {
|
|
696
|
+
return (
|
|
697
|
+
<View
|
|
698
|
+
display="block"
|
|
699
|
+
padding="medium medium small"
|
|
700
|
+
background="primary"
|
|
701
|
+
>
|
|
702
|
+
<View display="block" margin="small none large">
|
|
703
|
+
<FormFieldGroup description="Settings" rowSpacing="small">
|
|
704
|
+
{[
|
|
705
|
+
'lineNumbers',
|
|
706
|
+
'foldGutter',
|
|
707
|
+
'highlightActiveLineGutter',
|
|
708
|
+
'highlightActiveLine'
|
|
709
|
+
].map((prop) => (
|
|
710
|
+
<Checkbox
|
|
711
|
+
label={prop}
|
|
712
|
+
key={prop}
|
|
713
|
+
defaultChecked={this.state[prop]}
|
|
714
|
+
onChange={() => {
|
|
715
|
+
this.setState({ [prop]: !this.state[prop] })
|
|
716
|
+
}}
|
|
717
|
+
/>
|
|
718
|
+
))}
|
|
719
|
+
</FormFieldGroup>
|
|
720
|
+
</View>
|
|
721
|
+
|
|
722
|
+
<SourceCodeEditor
|
|
723
|
+
label="gutter example"
|
|
724
|
+
language="jsx"
|
|
725
|
+
lineNumbers={this.state.lineNumbers}
|
|
726
|
+
foldGutter={this.state.foldGutter}
|
|
727
|
+
highlightActiveLineGutter={this.state.highlightActiveLineGutter}
|
|
728
|
+
highlightActiveLine={this.state.highlightActiveLine}
|
|
729
|
+
defaultValue={`const fruit: string = "apple"
|
|
730
|
+
|
|
731
|
+
function exampleMethod(props: Props) {
|
|
732
|
+
return props ? props.value : null
|
|
401
733
|
}
|
|
734
|
+
|
|
735
|
+
/**
|
|
736
|
+
* This is an example
|
|
737
|
+
* @param {Object} props
|
|
738
|
+
*/
|
|
739
|
+
const Example = () => {
|
|
740
|
+
return (
|
|
741
|
+
<View as="div" padding={'large'}>
|
|
742
|
+
<Position
|
|
743
|
+
renderTarget={<GoodComponent />}
|
|
744
|
+
placement='end center'
|
|
745
|
+
offsetX='20px'
|
|
746
|
+
>
|
|
747
|
+
<span style={{ padding: '8px', background: 'white' }}>
|
|
748
|
+
Positioned content
|
|
749
|
+
</span>
|
|
750
|
+
</Position>
|
|
751
|
+
</View>
|
|
752
|
+
)
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
render(<Example />)`}
|
|
756
|
+
/>
|
|
757
|
+
</View>
|
|
758
|
+
)
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
render(<GutterExample />)
|
|
763
|
+
```
|
|
764
|
+
|
|
765
|
+
- ```js
|
|
766
|
+
const GutterExample = () => {
|
|
767
|
+
const [settings, setSettings] = useState({
|
|
768
|
+
lineNumbers: true,
|
|
769
|
+
foldGutter: true,
|
|
770
|
+
highlightActiveLineGutter: true,
|
|
771
|
+
highlightActiveLine: true
|
|
772
|
+
})
|
|
402
773
|
|
|
403
|
-
render () {
|
|
404
774
|
return (
|
|
405
775
|
<View display="block" padding="medium medium small" background="primary">
|
|
406
776
|
<View display="block" margin="small none large">
|
|
407
777
|
<FormFieldGroup description="Settings" rowSpacing="small">
|
|
408
|
-
{[
|
|
778
|
+
{[
|
|
779
|
+
'lineNumbers',
|
|
780
|
+
'foldGutter',
|
|
781
|
+
'highlightActiveLineGutter',
|
|
782
|
+
'highlightActiveLine'
|
|
783
|
+
].map((prop) => (
|
|
409
784
|
<Checkbox
|
|
410
785
|
label={prop}
|
|
411
786
|
key={prop}
|
|
412
|
-
defaultChecked={
|
|
787
|
+
defaultChecked={settings[prop]}
|
|
413
788
|
onChange={() => {
|
|
414
|
-
|
|
789
|
+
setSettings((prevSettings) => ({
|
|
790
|
+
...prevSettings,
|
|
791
|
+
[prop]: !prevSettings[prop]
|
|
792
|
+
}))
|
|
415
793
|
}}
|
|
416
794
|
/>
|
|
417
795
|
))}
|
|
@@ -419,23 +797,23 @@ class GutterExample extends React.Component {
|
|
|
419
797
|
</View>
|
|
420
798
|
|
|
421
799
|
<SourceCodeEditor
|
|
422
|
-
label=
|
|
800
|
+
label="gutter example"
|
|
423
801
|
language="jsx"
|
|
424
|
-
lineNumbers={
|
|
425
|
-
foldGutter={
|
|
426
|
-
highlightActiveLineGutter={
|
|
427
|
-
highlightActiveLine={
|
|
802
|
+
lineNumbers={settings.lineNumbers}
|
|
803
|
+
foldGutter={settings.foldGutter}
|
|
804
|
+
highlightActiveLineGutter={settings.highlightActiveLineGutter}
|
|
805
|
+
highlightActiveLine={settings.highlightActiveLine}
|
|
428
806
|
defaultValue={`const fruit: string = "apple"
|
|
429
|
-
|
|
430
|
-
function exampleMethod(props: Props) {
|
|
807
|
+
|
|
808
|
+
function exampleMethod(props: Props) {
|
|
431
809
|
return props ? props.value : null
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
/**
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
const Example = () => {
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* This is an example
|
|
814
|
+
* @param {Object} props
|
|
815
|
+
*/
|
|
816
|
+
const Example = () => {
|
|
439
817
|
return (
|
|
440
818
|
<View as="div" padding={'large'}>
|
|
441
819
|
<Position
|
|
@@ -449,17 +827,15 @@ const Example = () => {
|
|
|
449
827
|
</Position>
|
|
450
828
|
</View>
|
|
451
829
|
)
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
render(<Example />)`}
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
render(<Example />)`}
|
|
455
833
|
/>
|
|
456
834
|
</View>
|
|
457
835
|
)
|
|
458
836
|
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
render(<GutterExample />)
|
|
462
|
-
```
|
|
837
|
+
render(<GutterExample />)
|
|
838
|
+
```
|
|
463
839
|
|
|
464
840
|
### Indentation
|
|
465
841
|
|
|
@@ -483,107 +859,207 @@ The `indentUnitCount` prop should be a string consisting either entirely of spac
|
|
|
483
859
|
|
|
484
860
|
Another useful feature is the `indentAll` public method on the `SourceCodeEditor` component that can be called anytime to trigger a re-indent on the content.
|
|
485
861
|
|
|
486
|
-
```js
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
indentWithTab: true,
|
|
493
|
-
indentUnitCount: '2',
|
|
494
|
-
}
|
|
862
|
+
- ```js
|
|
863
|
+
class IndentExample extends React.Component {
|
|
864
|
+
state = {
|
|
865
|
+
indentWithTab: true,
|
|
866
|
+
indentUnitCount: '2'
|
|
867
|
+
}
|
|
495
868
|
|
|
496
|
-
|
|
869
|
+
editor = null
|
|
497
870
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
871
|
+
get indentUnit() {
|
|
872
|
+
return Array(parseInt(this.state.indentUnitCount)).fill(' ').join('')
|
|
873
|
+
}
|
|
501
874
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
875
|
+
reIndent() {
|
|
876
|
+
this.editor.indentAll()
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
indentCurrentSelection() {
|
|
880
|
+
this.editor.indentCurrentSelection()
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
render() {
|
|
884
|
+
return (
|
|
885
|
+
<View
|
|
886
|
+
display="block"
|
|
887
|
+
padding="medium medium small"
|
|
888
|
+
background="primary"
|
|
889
|
+
>
|
|
890
|
+
<View display="block" margin="small none large">
|
|
891
|
+
<FormFieldGroup description="Settings">
|
|
892
|
+
<Checkbox
|
|
893
|
+
label="indentWithTab"
|
|
894
|
+
defaultChecked={this.state.indentWithTab}
|
|
895
|
+
onChange={() => {
|
|
896
|
+
this.setState({ indentWithTab: !this.state.indentWithTab })
|
|
897
|
+
}}
|
|
898
|
+
/>
|
|
899
|
+
<RadioInputGroup
|
|
900
|
+
name="indentUnitCount"
|
|
901
|
+
value={this.state.indentUnitCount}
|
|
902
|
+
description="indent space count"
|
|
903
|
+
onChange={(e, indentUnitCount) => {
|
|
904
|
+
this.setState({ indentUnitCount })
|
|
905
|
+
this.reIndent()
|
|
906
|
+
}}
|
|
907
|
+
>
|
|
908
|
+
{['2', '4', '8'].map((count) => (
|
|
909
|
+
<RadioInput key={count} label={count} value={count} />
|
|
910
|
+
))}
|
|
911
|
+
</RadioInputGroup>
|
|
912
|
+
<Button
|
|
913
|
+
onClick={() => {
|
|
914
|
+
this.reIndent()
|
|
915
|
+
}}
|
|
916
|
+
>
|
|
917
|
+
Re-indent code
|
|
918
|
+
</Button>
|
|
919
|
+
<Button
|
|
920
|
+
onClick={() => {
|
|
921
|
+
this.indentCurrentSelection()
|
|
922
|
+
}}
|
|
923
|
+
>
|
|
924
|
+
Indent current selection
|
|
925
|
+
</Button>
|
|
926
|
+
</FormFieldGroup>
|
|
927
|
+
</View>
|
|
505
928
|
|
|
506
|
-
|
|
507
|
-
|
|
929
|
+
<SourceCodeEditor
|
|
930
|
+
label="indent example"
|
|
931
|
+
ref={(component) => {
|
|
932
|
+
this.editor = component
|
|
933
|
+
}}
|
|
934
|
+
language="jsx"
|
|
935
|
+
indentWithTab={this.state.indentWithTab}
|
|
936
|
+
indentUnit={this.indentUnit}
|
|
937
|
+
defaultValue={`const fruit: string = "apple"
|
|
938
|
+
|
|
939
|
+
function exampleMethod(props: Props) {
|
|
940
|
+
return props ? props.value : null
|
|
508
941
|
}
|
|
942
|
+
|
|
943
|
+
/**
|
|
944
|
+
* This is an example
|
|
945
|
+
* @param {Object} props
|
|
946
|
+
*/
|
|
947
|
+
const Example = () => {
|
|
948
|
+
return (
|
|
949
|
+
<View as="div" padding={'large'}>
|
|
950
|
+
<Position
|
|
951
|
+
renderTarget={<GoodComponent />}
|
|
952
|
+
placement='end center'
|
|
953
|
+
offsetX='20px'
|
|
954
|
+
>
|
|
955
|
+
<span style={{ padding: '8px', background: 'white' }}>
|
|
956
|
+
Positioned content
|
|
957
|
+
</span>
|
|
958
|
+
</Position>
|
|
959
|
+
</View>
|
|
960
|
+
)
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
render(<Example />)`}
|
|
964
|
+
/>
|
|
965
|
+
</View>
|
|
966
|
+
)
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
render(<IndentExample />)
|
|
971
|
+
```
|
|
972
|
+
|
|
973
|
+
- ```js
|
|
974
|
+
const IndentExample = () => {
|
|
975
|
+
const [indentWithTab, setIndentWithTab] = useState(true)
|
|
976
|
+
const [indentUnitCount, setIndentUnitCount] = useState('2')
|
|
977
|
+
|
|
978
|
+
const editorRef = useRef(null)
|
|
979
|
+
|
|
980
|
+
const indentUnit = Array(parseInt(indentUnitCount)).fill(' ').join('')
|
|
981
|
+
|
|
982
|
+
const reIndent = () => {
|
|
983
|
+
if (editorRef.current) {
|
|
984
|
+
editorRef.current.indentAll()
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
const indentCurrentSelection = () => {
|
|
989
|
+
if (editorRef.current) {
|
|
990
|
+
editorRef.current.indentCurrentSelection()
|
|
991
|
+
}
|
|
992
|
+
}
|
|
509
993
|
|
|
510
|
-
render () {
|
|
511
994
|
return (
|
|
512
995
|
<View display="block" padding="medium medium small" background="primary">
|
|
513
996
|
<View display="block" margin="small none large">
|
|
514
997
|
<FormFieldGroup description="Settings">
|
|
515
998
|
<Checkbox
|
|
516
999
|
label="indentWithTab"
|
|
517
|
-
defaultChecked={
|
|
518
|
-
onChange={() =>
|
|
519
|
-
this.setState({ indentWithTab: !this.state.indentWithTab })
|
|
520
|
-
}}
|
|
1000
|
+
defaultChecked={indentWithTab}
|
|
1001
|
+
onChange={() => setIndentWithTab(!indentWithTab)}
|
|
521
1002
|
/>
|
|
522
1003
|
<RadioInputGroup
|
|
523
1004
|
name="indentUnitCount"
|
|
524
|
-
value={
|
|
1005
|
+
value={indentUnitCount}
|
|
525
1006
|
description="indent space count"
|
|
526
|
-
onChange={(e,
|
|
527
|
-
|
|
528
|
-
|
|
1007
|
+
onChange={(e, value) => {
|
|
1008
|
+
setIndentUnitCount(value)
|
|
1009
|
+
reIndent()
|
|
529
1010
|
}}
|
|
530
1011
|
>
|
|
531
|
-
{['2', '4', '8'].map(count =>
|
|
1012
|
+
{['2', '4', '8'].map((count) => (
|
|
1013
|
+
<RadioInput key={count} label={count} value={count} />
|
|
1014
|
+
))}
|
|
532
1015
|
</RadioInputGroup>
|
|
533
|
-
<Button onClick={
|
|
534
|
-
|
|
535
|
-
}}>
|
|
536
|
-
Re-indent code
|
|
537
|
-
</Button>
|
|
538
|
-
<Button onClick={() => {
|
|
539
|
-
this.indentCurrentSelection()
|
|
540
|
-
}}>
|
|
1016
|
+
<Button onClick={reIndent}>Re-indent code</Button>
|
|
1017
|
+
<Button onClick={indentCurrentSelection}>
|
|
541
1018
|
Indent current selection
|
|
542
1019
|
</Button>
|
|
543
1020
|
</FormFieldGroup>
|
|
544
1021
|
</View>
|
|
545
1022
|
|
|
546
1023
|
<SourceCodeEditor
|
|
547
|
-
label=
|
|
548
|
-
ref={
|
|
1024
|
+
label="indent example"
|
|
1025
|
+
ref={editorRef}
|
|
549
1026
|
language="jsx"
|
|
550
|
-
indentWithTab={
|
|
551
|
-
indentUnit={
|
|
1027
|
+
indentWithTab={indentWithTab}
|
|
1028
|
+
indentUnit={indentUnit}
|
|
552
1029
|
defaultValue={`const fruit: string = "apple"
|
|
553
|
-
|
|
554
|
-
function exampleMethod(props: Props) {
|
|
555
|
-
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
/**
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
const Example = () => {
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
render(<Example />)`}
|
|
1030
|
+
|
|
1031
|
+
function exampleMethod(props: Props) {
|
|
1032
|
+
return props ? props.value : null
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
/**
|
|
1036
|
+
* This is an example
|
|
1037
|
+
* @param {Object} props
|
|
1038
|
+
*/
|
|
1039
|
+
const Example = () => {
|
|
1040
|
+
return (
|
|
1041
|
+
<View as="div" padding={'large'}>
|
|
1042
|
+
<Position
|
|
1043
|
+
renderTarget={<GoodComponent />}
|
|
1044
|
+
placement='end center'
|
|
1045
|
+
offsetX='20px'
|
|
1046
|
+
>
|
|
1047
|
+
<span style={{ padding: '8px', background: 'white' }}>
|
|
1048
|
+
Positioned content
|
|
1049
|
+
</span>
|
|
1050
|
+
</Position>
|
|
1051
|
+
</View>
|
|
1052
|
+
)
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
render(<Example />)`}
|
|
579
1056
|
/>
|
|
580
1057
|
</View>
|
|
581
1058
|
)
|
|
582
1059
|
}
|
|
583
|
-
}
|
|
584
1060
|
|
|
585
|
-
render(<IndentExample />)
|
|
586
|
-
```
|
|
1061
|
+
render(<IndentExample />)
|
|
1062
|
+
```
|
|
587
1063
|
|
|
588
1064
|
### Direction
|
|
589
1065
|
|
|
@@ -591,83 +1067,176 @@ SourceCodeEditor is a bidirectional component. It will inherit the text-directio
|
|
|
591
1067
|
|
|
592
1068
|
The `rtlMoveVisually` prop controls the cursor movement in RTL mode, whether it should be **visual** (pressing the left arrow moves the cursor left) or **logical** (pressing the left arrow moves to the next lower index in the string, which is visually right in RTL text).
|
|
593
1069
|
|
|
594
|
-
```js
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
1070
|
+
- ```js
|
|
1071
|
+
class DirectionExample extends React.Component {
|
|
1072
|
+
state = {
|
|
1073
|
+
contextDir: 'unset',
|
|
1074
|
+
editorDir: 'unset',
|
|
1075
|
+
rtlMoveVisually: true
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
render() {
|
|
1079
|
+
return (
|
|
1080
|
+
<InstUISettingsProvider
|
|
1081
|
+
dir={
|
|
1082
|
+
this.state.contextDir !== 'unset'
|
|
1083
|
+
? this.state.contextDir
|
|
1084
|
+
: undefined
|
|
1085
|
+
}
|
|
1086
|
+
>
|
|
1087
|
+
<View
|
|
1088
|
+
display="block"
|
|
1089
|
+
padding="medium medium small"
|
|
1090
|
+
background="primary"
|
|
1091
|
+
>
|
|
1092
|
+
<View display="block" margin="small none large">
|
|
1093
|
+
<FormFieldGroup
|
|
1094
|
+
description="Settings"
|
|
1095
|
+
layout="columns"
|
|
1096
|
+
vAlign="top"
|
|
1097
|
+
>
|
|
1098
|
+
<RadioInputGroup
|
|
1099
|
+
name="contextDir"
|
|
1100
|
+
value={this.state.contextDir}
|
|
1101
|
+
description="context direction"
|
|
1102
|
+
onChange={(e, contextDir) => {
|
|
1103
|
+
this.setState({ contextDir })
|
|
1104
|
+
}}
|
|
1105
|
+
>
|
|
1106
|
+
{['unset', 'ltr', 'rtl'].map((dir) => (
|
|
1107
|
+
<RadioInput key={dir} label={dir} value={dir} />
|
|
1108
|
+
))}
|
|
1109
|
+
</RadioInputGroup>
|
|
1110
|
+
<RadioInputGroup
|
|
1111
|
+
name="editorDir"
|
|
1112
|
+
value={this.state.editorDir}
|
|
1113
|
+
description="editor direction"
|
|
1114
|
+
onChange={(e, editorDir) => {
|
|
1115
|
+
this.setState({ editorDir })
|
|
1116
|
+
}}
|
|
1117
|
+
>
|
|
1118
|
+
{['unset', 'ltr', 'rtl'].map((dir) => (
|
|
1119
|
+
<RadioInput key={dir} label={dir} value={dir} />
|
|
1120
|
+
))}
|
|
1121
|
+
</RadioInputGroup>
|
|
1122
|
+
<Checkbox
|
|
1123
|
+
label="rtlMoveVisually"
|
|
1124
|
+
defaultChecked={this.state.rtlMoveVisually}
|
|
1125
|
+
onChange={() => {
|
|
1126
|
+
this.setState({
|
|
1127
|
+
rtlMoveVisually: !this.state.rtlMoveVisually
|
|
1128
|
+
})
|
|
1129
|
+
}}
|
|
1130
|
+
/>
|
|
1131
|
+
</FormFieldGroup>
|
|
1132
|
+
</View>
|
|
1133
|
+
|
|
1134
|
+
<SourceCodeEditor
|
|
1135
|
+
label="editable code editor"
|
|
1136
|
+
language="jsx"
|
|
1137
|
+
direction={
|
|
1138
|
+
this.state.editorDir !== 'unset'
|
|
1139
|
+
? this.state.editorDir
|
|
1140
|
+
: undefined
|
|
1141
|
+
}
|
|
1142
|
+
rtlMoveVisually={this.state.rtlMoveVisually}
|
|
1143
|
+
defaultValue={`function directionExample(dir?: 'ltr' | 'rtl') {
|
|
1144
|
+
console.log(dir)
|
|
1145
|
+
}`}
|
|
1146
|
+
/>
|
|
1147
|
+
</View>
|
|
1148
|
+
</InstUISettingsProvider>
|
|
1149
|
+
)
|
|
1150
|
+
}
|
|
603
1151
|
}
|
|
604
1152
|
|
|
605
|
-
render
|
|
1153
|
+
render(<DirectionExample />)
|
|
1154
|
+
```
|
|
1155
|
+
|
|
1156
|
+
- ```js
|
|
1157
|
+
const DirectionExample = () => {
|
|
1158
|
+
const [settings, setSettings] = useState({
|
|
1159
|
+
contextDir: 'unset',
|
|
1160
|
+
editorDir: 'unset',
|
|
1161
|
+
rtlMoveVisually: true
|
|
1162
|
+
})
|
|
1163
|
+
|
|
606
1164
|
return (
|
|
607
|
-
<InstUISettingsProvider
|
|
608
|
-
?
|
|
609
|
-
|
|
610
|
-
}>
|
|
1165
|
+
<InstUISettingsProvider
|
|
1166
|
+
dir={settings.contextDir !== 'unset' ? settings.contextDir : undefined}
|
|
1167
|
+
>
|
|
611
1168
|
<View
|
|
612
1169
|
display="block"
|
|
613
1170
|
padding="medium medium small"
|
|
614
1171
|
background="primary"
|
|
615
1172
|
>
|
|
616
|
-
<View
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
1173
|
+
<View display="block" margin="small none large">
|
|
1174
|
+
<FormFieldGroup
|
|
1175
|
+
description="Settings"
|
|
1176
|
+
layout="columns"
|
|
1177
|
+
vAlign="top"
|
|
1178
|
+
>
|
|
621
1179
|
<RadioInputGroup
|
|
622
1180
|
name="contextDir"
|
|
623
|
-
value={
|
|
1181
|
+
value={settings.contextDir}
|
|
624
1182
|
description="context direction"
|
|
625
1183
|
onChange={(e, contextDir) => {
|
|
626
|
-
|
|
1184
|
+
setSettings((prevSettings) => ({
|
|
1185
|
+
...prevSettings,
|
|
1186
|
+
contextDir
|
|
1187
|
+
}))
|
|
627
1188
|
}}
|
|
628
1189
|
>
|
|
629
|
-
{['unset', 'ltr', 'rtl'].map(dir =>
|
|
1190
|
+
{['unset', 'ltr', 'rtl'].map((dir) => (
|
|
1191
|
+
<RadioInput key={dir} label={dir} value={dir} />
|
|
1192
|
+
))}
|
|
630
1193
|
</RadioInputGroup>
|
|
631
1194
|
<RadioInputGroup
|
|
632
1195
|
name="editorDir"
|
|
633
|
-
value={
|
|
1196
|
+
value={settings.editorDir}
|
|
634
1197
|
description="editor direction"
|
|
635
1198
|
onChange={(e, editorDir) => {
|
|
636
|
-
|
|
1199
|
+
setSettings((prevSettings) => ({
|
|
1200
|
+
...prevSettings,
|
|
1201
|
+
editorDir
|
|
1202
|
+
}))
|
|
637
1203
|
}}
|
|
638
1204
|
>
|
|
639
|
-
{['unset', 'ltr', 'rtl'].map(dir =>
|
|
1205
|
+
{['unset', 'ltr', 'rtl'].map((dir) => (
|
|
1206
|
+
<RadioInput key={dir} label={dir} value={dir} />
|
|
1207
|
+
))}
|
|
640
1208
|
</RadioInputGroup>
|
|
641
1209
|
<Checkbox
|
|
642
1210
|
label="rtlMoveVisually"
|
|
643
|
-
defaultChecked={
|
|
1211
|
+
defaultChecked={settings.rtlMoveVisually}
|
|
644
1212
|
onChange={() => {
|
|
645
|
-
|
|
1213
|
+
setSettings((prevSettings) => ({
|
|
1214
|
+
...prevSettings,
|
|
1215
|
+
rtlMoveVisually: !prevSettings.rtlMoveVisually
|
|
1216
|
+
}))
|
|
646
1217
|
}}
|
|
647
1218
|
/>
|
|
648
1219
|
</FormFieldGroup>
|
|
649
1220
|
</View>
|
|
650
1221
|
|
|
651
1222
|
<SourceCodeEditor
|
|
652
|
-
label=
|
|
1223
|
+
label="editable code editor"
|
|
653
1224
|
language="jsx"
|
|
654
|
-
direction={
|
|
655
|
-
?
|
|
656
|
-
: undefined
|
|
1225
|
+
direction={
|
|
1226
|
+
settings.editorDir !== 'unset' ? settings.editorDir : undefined
|
|
657
1227
|
}
|
|
658
|
-
rtlMoveVisually={
|
|
1228
|
+
rtlMoveVisually={settings.rtlMoveVisually}
|
|
659
1229
|
defaultValue={`function directionExample(dir?: 'ltr' | 'rtl') {
|
|
660
|
-
|
|
661
|
-
}`}
|
|
1230
|
+
console.log(dir)
|
|
1231
|
+
}`}
|
|
662
1232
|
/>
|
|
663
1233
|
</View>
|
|
664
1234
|
</InstUISettingsProvider>
|
|
665
1235
|
)
|
|
666
1236
|
}
|
|
667
|
-
}
|
|
668
1237
|
|
|
669
|
-
render(<DirectionExample />)
|
|
670
|
-
```
|
|
1238
|
+
render(<DirectionExample />)
|
|
1239
|
+
```
|
|
671
1240
|
|
|
672
1241
|
### Focus management
|
|
673
1242
|
|
|
@@ -677,68 +1246,180 @@ The `autofocus` prop will automatically focus the editor on the initial render.
|
|
|
677
1246
|
|
|
678
1247
|
You can also manually focus the editor with its public `focus` method (the `hasFocus` getter is also available).
|
|
679
1248
|
|
|
680
|
-
```js
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
1249
|
+
- ```js
|
|
1250
|
+
class FocusExample extends React.Component {
|
|
1251
|
+
state = {
|
|
1252
|
+
indentWithTab: true,
|
|
1253
|
+
indentUnitCount: '2'
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
editor = null
|
|
1257
|
+
|
|
1258
|
+
render() {
|
|
1259
|
+
return (
|
|
1260
|
+
<View
|
|
1261
|
+
display="block"
|
|
1262
|
+
padding="medium medium small"
|
|
1263
|
+
background="primary"
|
|
1264
|
+
>
|
|
1265
|
+
<View display="block" margin="small none large">
|
|
1266
|
+
<Button
|
|
1267
|
+
onClick={() => {
|
|
1268
|
+
console.log('manual focus')
|
|
1269
|
+
this.editor.focus()
|
|
1270
|
+
}}
|
|
1271
|
+
>
|
|
1272
|
+
Focus editor
|
|
1273
|
+
</Button>
|
|
1274
|
+
</View>
|
|
1275
|
+
|
|
1276
|
+
<SourceCodeEditor
|
|
1277
|
+
label="focus example"
|
|
1278
|
+
ref={(component) => {
|
|
1279
|
+
this.editor = component
|
|
1280
|
+
}}
|
|
1281
|
+
language="jsx"
|
|
1282
|
+
onFocus={() => {
|
|
1283
|
+
console.log('onFocus')
|
|
1284
|
+
console.log({ hasFocus: this.editor.hasFocus })
|
|
1285
|
+
}}
|
|
1286
|
+
onBlur={() => {
|
|
1287
|
+
console.log('onBlur')
|
|
1288
|
+
console.log({ hasFocus: this.editor.hasFocus })
|
|
1289
|
+
}}
|
|
1290
|
+
defaultValue={`function exampleMethod(props: Props) {
|
|
1291
|
+
return props ? props.value : null
|
|
1292
|
+
}`}
|
|
1293
|
+
/>
|
|
1294
|
+
</View>
|
|
1295
|
+
)
|
|
1296
|
+
}
|
|
688
1297
|
}
|
|
689
1298
|
|
|
690
|
-
|
|
1299
|
+
render(<FocusExample />)
|
|
1300
|
+
```
|
|
1301
|
+
|
|
1302
|
+
- ```js
|
|
1303
|
+
const FocusExample = () => {
|
|
1304
|
+
const [indentWithTab, setIndentWithTab] = useState(true)
|
|
1305
|
+
const [indentUnitCount, setIndentUnitCount] = useState('2')
|
|
1306
|
+
|
|
1307
|
+
const editorRef = useRef(null)
|
|
691
1308
|
|
|
692
|
-
render () {
|
|
693
1309
|
return (
|
|
694
1310
|
<View display="block" padding="medium medium small" background="primary">
|
|
695
1311
|
<View display="block" margin="small none large">
|
|
696
|
-
<Button
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
1312
|
+
<Button
|
|
1313
|
+
onClick={() => {
|
|
1314
|
+
console.log('manual focus')
|
|
1315
|
+
editorRef.current.focus()
|
|
1316
|
+
}}
|
|
1317
|
+
>
|
|
700
1318
|
Focus editor
|
|
701
1319
|
</Button>
|
|
702
1320
|
</View>
|
|
703
1321
|
|
|
704
1322
|
<SourceCodeEditor
|
|
705
|
-
label=
|
|
706
|
-
ref={
|
|
1323
|
+
label="focus example"
|
|
1324
|
+
ref={editorRef}
|
|
707
1325
|
language="jsx"
|
|
708
1326
|
onFocus={() => {
|
|
709
1327
|
console.log('onFocus')
|
|
710
|
-
console.log({ hasFocus:
|
|
1328
|
+
console.log({ hasFocus: editorRef.current.hasFocus })
|
|
711
1329
|
}}
|
|
712
1330
|
onBlur={() => {
|
|
713
1331
|
console.log('onBlur')
|
|
714
|
-
console.log({ hasFocus:
|
|
1332
|
+
console.log({ hasFocus: editorRef.current.hasFocus })
|
|
715
1333
|
}}
|
|
716
1334
|
defaultValue={`function exampleMethod(props: Props) {
|
|
717
|
-
|
|
718
|
-
}`}
|
|
1335
|
+
return props ? props.value : null
|
|
1336
|
+
}`}
|
|
719
1337
|
/>
|
|
720
1338
|
</View>
|
|
721
1339
|
)
|
|
722
1340
|
}
|
|
723
|
-
}
|
|
724
1341
|
|
|
725
|
-
render(<FocusExample />)
|
|
726
|
-
```
|
|
1342
|
+
render(<FocusExample />)
|
|
1343
|
+
```
|
|
727
1344
|
|
|
728
1345
|
### Attachment
|
|
729
1346
|
|
|
730
1347
|
The `attachment` prop removes the top/bottom border-radius and margin of the editor, so it can be attached to the top or bottom of another element.
|
|
731
1348
|
|
|
732
|
-
```js
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
1349
|
+
- ```js
|
|
1350
|
+
class AttachmentExample extends React.Component {
|
|
1351
|
+
state = {
|
|
1352
|
+
attachment: 'none'
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
render() {
|
|
1356
|
+
const viewProps = {
|
|
1357
|
+
as: 'div',
|
|
1358
|
+
background: 'primary-inverse',
|
|
1359
|
+
padding: 'small'
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
return (
|
|
1363
|
+
<View
|
|
1364
|
+
display="block"
|
|
1365
|
+
padding="medium medium small"
|
|
1366
|
+
background="primary"
|
|
1367
|
+
>
|
|
1368
|
+
<View display="block" margin="small none large">
|
|
1369
|
+
<RadioInputGroup
|
|
1370
|
+
name="attachmentExample"
|
|
1371
|
+
value={this.state.attachment}
|
|
1372
|
+
description="attachment"
|
|
1373
|
+
onChange={(e, attachment) => {
|
|
1374
|
+
this.setState({ attachment })
|
|
1375
|
+
}}
|
|
1376
|
+
>
|
|
1377
|
+
{['none', 'top', 'bottom'].map((attachment) => (
|
|
1378
|
+
<RadioInput
|
|
1379
|
+
key={attachment}
|
|
1380
|
+
label={attachment}
|
|
1381
|
+
value={attachment}
|
|
1382
|
+
/>
|
|
1383
|
+
))}
|
|
1384
|
+
</RadioInputGroup>
|
|
1385
|
+
</View>
|
|
1386
|
+
|
|
1387
|
+
{this.state.attachment === 'bottom' && (
|
|
1388
|
+
<View {...viewProps}>
|
|
1389
|
+
CodeEditor is attached to the bottom of this element
|
|
1390
|
+
</View>
|
|
1391
|
+
)}
|
|
1392
|
+
<SourceCodeEditor
|
|
1393
|
+
label="attachment example"
|
|
1394
|
+
language="jsx"
|
|
1395
|
+
attachment={
|
|
1396
|
+
this.state.attachment === 'none'
|
|
1397
|
+
? undefined
|
|
1398
|
+
: this.state.attachment
|
|
1399
|
+
}
|
|
1400
|
+
defaultValue={`const fruit: string = "apple"
|
|
1401
|
+
|
|
1402
|
+
function exampleMethod(props: Props) {
|
|
1403
|
+
return props ? props.value : null
|
|
1404
|
+
}`}
|
|
1405
|
+
/>
|
|
1406
|
+
{this.state.attachment === 'top' && (
|
|
1407
|
+
<View {...viewProps}>
|
|
1408
|
+
CodeEditor is attached to the top of this element
|
|
1409
|
+
</View>
|
|
1410
|
+
)}
|
|
1411
|
+
</View>
|
|
1412
|
+
)
|
|
1413
|
+
}
|
|
739
1414
|
}
|
|
740
1415
|
|
|
741
|
-
render
|
|
1416
|
+
render(<AttachmentExample />)
|
|
1417
|
+
```
|
|
1418
|
+
|
|
1419
|
+
- ```js
|
|
1420
|
+
const AttachmentExample = () => {
|
|
1421
|
+
const [attachment, setAttachment] = useState('none')
|
|
1422
|
+
|
|
742
1423
|
const viewProps = {
|
|
743
1424
|
as: 'div',
|
|
744
1425
|
background: 'primary-inverse',
|
|
@@ -750,32 +1431,38 @@ class AttachmentExample extends React.Component {
|
|
|
750
1431
|
<View display="block" margin="small none large">
|
|
751
1432
|
<RadioInputGroup
|
|
752
1433
|
name="attachmentExample"
|
|
753
|
-
value={
|
|
1434
|
+
value={attachment}
|
|
754
1435
|
description="attachment"
|
|
755
1436
|
onChange={(e, attachment) => {
|
|
756
|
-
|
|
1437
|
+
setAttachment(attachment)
|
|
757
1438
|
}}
|
|
758
1439
|
>
|
|
759
|
-
{['none', 'top', 'bottom'].map(attachment =>
|
|
1440
|
+
{['none', 'top', 'bottom'].map((attachment) => (
|
|
1441
|
+
<RadioInput
|
|
1442
|
+
key={attachment}
|
|
1443
|
+
label={attachment}
|
|
1444
|
+
value={attachment}
|
|
1445
|
+
/>
|
|
1446
|
+
))}
|
|
760
1447
|
</RadioInputGroup>
|
|
761
1448
|
</View>
|
|
762
1449
|
|
|
763
|
-
{
|
|
1450
|
+
{attachment === 'bottom' && (
|
|
764
1451
|
<View {...viewProps}>
|
|
765
1452
|
CodeEditor is attached to the bottom of this element
|
|
766
1453
|
</View>
|
|
767
1454
|
)}
|
|
768
1455
|
<SourceCodeEditor
|
|
769
|
-
label=
|
|
1456
|
+
label="attachment example"
|
|
770
1457
|
language="jsx"
|
|
771
|
-
attachment={
|
|
1458
|
+
attachment={attachment === 'none' ? undefined : attachment}
|
|
772
1459
|
defaultValue={`const fruit: string = "apple"
|
|
773
|
-
|
|
774
|
-
function exampleMethod(props: Props) {
|
|
775
|
-
|
|
776
|
-
}`}
|
|
1460
|
+
|
|
1461
|
+
function exampleMethod(props: Props) {
|
|
1462
|
+
return props ? props.value : null
|
|
1463
|
+
}`}
|
|
777
1464
|
/>
|
|
778
|
-
{
|
|
1465
|
+
{attachment === 'top' && (
|
|
779
1466
|
<View {...viewProps}>
|
|
780
1467
|
CodeEditor is attached to the top of this element
|
|
781
1468
|
</View>
|
|
@@ -783,10 +1470,9 @@ function exampleMethod(props: Props) {
|
|
|
783
1470
|
</View>
|
|
784
1471
|
)
|
|
785
1472
|
}
|
|
786
|
-
}
|
|
787
1473
|
|
|
788
|
-
render(<AttachmentExample />)
|
|
789
|
-
```
|
|
1474
|
+
render(<AttachmentExample />)
|
|
1475
|
+
```
|
|
790
1476
|
|
|
791
1477
|
### Search
|
|
792
1478
|
|