Skip to content

Commit f888ea9

Browse files
broke out react from page
1 parent 8ab95ac commit f888ea9

12 files changed

Lines changed: 677 additions & 630 deletions

File tree

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
1-
package react
1+
package page
22

3-
func BannerTitle(version string) *Element {
4-
return CreateElement(bannerTitleComponent, Props{
3+
import "github.com/gopherjs/gopherjs.github.io/playground/internal/react"
4+
5+
func BannerTitle(version string) *react.Element {
6+
return react.CreateElement(bannerTitleComponent, react.Props{
57
`version`: version,
68
})
79
}
810

9-
func bannerTitleComponent(props Props) *Element {
11+
func bannerTitleComponent(props react.Props) *react.Element {
1012
version := props.GetString(`version`)
11-
return Span(Props{
13+
return react.Span(react.Props{
1214
`id`: `banner-title`,
1315
},
1416
`playground `,
15-
Span(Props{
17+
react.Span(react.Props{
1618
`id`: `banner-title-sub`,
1719
},
1820
// TODO(grantnelson-wf): Make this a link to the gopherjs repo
1921
// https://github.com/gopherjs/gopherjs
2022
`GopherJS `,
2123
),
22-
Span(Props{
24+
react.Span(react.Props{
2325
`id`: `banner-title-version`,
2426
},
2527
// TODO(grantnelson-wf): Make this version a link to release notes
Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package react
1+
package page
22

33
import (
44
"strconv"
@@ -8,35 +8,36 @@ import (
88

99
"github.com/gopherjs/gopherjs.github.io/playground/internal/common"
1010
"github.com/gopherjs/gopherjs.github.io/playground/internal/editor"
11+
"github.com/gopherjs/gopherjs.github.io/playground/internal/react"
1112
)
1213

13-
func CodeBox(code string, setCode Setter, onSave Setter, onEscape Setter) *Element {
14-
return CreateElement(codeBoxComponent, Props{
14+
func CodeBox(code string, setCode react.Setter, onSave react.Setter, onEscape react.Setter) *react.Element {
15+
return react.CreateElement(codeBoxComponent, react.Props{
1516
`curCode`: code,
1617
`setCode`: setCode,
1718
`onSave`: onSave,
1819
`onEscape`: onEscape,
1920
})
2021
}
2122

22-
func codeBoxComponent(props Props) *Element {
23+
func codeBoxComponent(props react.Props) *react.Element {
2324
var (
2425
curCode = props.GetString(`curCode`)
2526
setCode = props.GetFunc(`setCode`)
2627
onSave = props.GetFunc(`onSave`)
2728
onEscape = props.GetFunc(`onEscape`)
28-
textAreaRef = UseRef()
29-
lineNumsRef = UseRef()
29+
textAreaRef = react.UseRef()
30+
lineNumsRef = react.UseRef()
3031
)
3132

32-
onInput := UseCallback(func(e *js.Object) {
33+
onInput := react.UseCallback(func(e *js.Object) {
3334
newCode := e.Get(`target`).Get(`value`).String()
3435
sel := getSelection(textAreaRef)
3536
globals.UndoRedo().RecordCodeChange(sel, curCode, newCode)
3637
setCode(newCode)
3738
}, []any{curCode, setCode, textAreaRef})
3839

39-
onKeyDown := UseCallback(func(e *js.Object) {
40+
onKeyDown := react.UseCallback(func(e *js.Object) {
4041
key := e.Get(`key`).String()
4142
shift := e.Get(`shiftKey`).Bool()
4243
ctrl := e.Get(`metaKey`).Bool() || e.Get(`ctrlKey`).Bool()
@@ -53,12 +54,12 @@ func codeBoxComponent(props Props) *Element {
5354
}
5455
}, []any{curCode, setCode, onSave, onEscape, textAreaRef})
5556

56-
onScroll := UseCallback(func(e *js.Object) {
57+
onScroll := react.UseCallback(func(e *js.Object) {
5758
scrollTop := e.Get(`target`).Get(`scrollTop`).Int()
5859
lineNumsRef.Current().Set(`scrollTop`, scrollTop)
5960
}, []any{lineNumsRef})
6061

61-
onSelect := UseCallback(func(e *js.Object) {
62+
onSelect := react.UseCallback(func(e *js.Object) {
6263
// Don't normalize the selection so that the direction is preserved.
6364
globals.UndoRedo().RecordSelectionChange(getSelection(textAreaRef))
6465
}, []any{textAreaRef})
@@ -67,28 +68,28 @@ func codeBoxComponent(props Props) *Element {
6768
// then maybe we could indent the pasted code automatically to match
6869
// the indent of where it is being pasted.
6970

70-
UseEffect(func() {
71+
react.UseEffect(func() {
7172
// On first render, focus the code textarea.
7273
textAreaRef.Current().Call(`focus`)
7374
setSelection(textAreaRef, common.Selection{})
7475
}, []any{})
7576

7677
lineCount := strings.Count(curCode, "\n") + 1
77-
lineNumbers := UseMemo(func() string {
78+
lineNumbers := react.UseMemo(func() string {
7879
return getLineNumbers(lineCount)
7980
}, []any{lineCount})
8081

81-
return Div(Props{
82+
return react.Div(react.Props{
8283
`id`: `code-box`,
8384
},
84-
TextArea(Props{
85+
react.TextArea(react.Props{
8586
`id`: `line-nums`,
8687
`ref`: lineNumsRef,
8788
`value`: lineNumbers,
8889
`readOnly`: true,
8990
`disable`: `true`,
9091
}),
91-
TextArea(Props{
92+
react.TextArea(react.Props{
9293
`id`: `code`,
9394
`ref`: textAreaRef,
9495
`value`: curCode,
@@ -107,10 +108,10 @@ func codeBoxComponent(props Props) *Element {
107108

108109
type codeBoxAssistant struct {
109110
curCode string
110-
setCode Func
111-
onSave Func
112-
onEscape Func
113-
textAreaRef *Ref
111+
setCode react.Func
112+
onSave react.Func
113+
onEscape react.Func
114+
textAreaRef *react.Ref
114115
}
115116

116117
var _ common.CodeBoxWrapper = (*codeBoxAssistant)(nil)
@@ -166,7 +167,7 @@ func (cba *codeBoxAssistant) SetCode(sel common.Selection, code string) {
166167
horizontallyAutoScroll(cba.textAreaRef, sel.End, code)
167168
}
168169

169-
func verticallyAutoScroll(textAreaRef *Ref, caret int, code string) {
170+
func verticallyAutoScroll(textAreaRef *react.Ref, caret int, code string) {
170171
textArea := textAreaRef.Current()
171172
totalHeight := textArea.Get(`scrollHeight`).Int()
172173
visibleHeight := textArea.Get(`clientHeight`).Int()
@@ -186,7 +187,7 @@ func verticallyAutoScroll(textAreaRef *Ref, caret int, code string) {
186187
}
187188
}
188189

189-
func horizontallyAutoScroll(textAreaRef *Ref, caret int, code string) {
190+
func horizontallyAutoScroll(textAreaRef *react.Ref, caret int, code string) {
190191
textArea := textAreaRef.Current()
191192
totalWidth := textArea.Get(`scrollWidth`).Int()
192193
visibleWidth := textArea.Get(`clientWidth`).Int()
@@ -207,15 +208,15 @@ func horizontallyAutoScroll(textAreaRef *Ref, caret int, code string) {
207208
}
208209
}
209210

210-
func getSelection(textAreaRef *Ref) common.Selection {
211+
func getSelection(textAreaRef *react.Ref) common.Selection {
211212
textArea := textAreaRef.Current()
212213
start := textArea.Get(`selectionStart`).Int()
213214
end := textArea.Get(`selectionEnd`).Int()
214215
return common.Selection{Start: start, End: end}
215216
}
216217

217218
// setSelection sets the selection on the given textarea ref.
218-
func setSelection(textAreaRef *Ref, sel common.Selection) {
219+
func setSelection(textAreaRef *react.Ref, sel common.Selection) {
219220
textArea := textAreaRef.Current()
220221
textArea.Set(`selectionStart`, sel.Start)
221222
textArea.Set(`selectionEnd`, sel.End)
Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,4 @@
1-
// The globals are the global objects used by the react components.
2-
//
3-
// Since passing Go structs through React props will cause problems
4-
// because of how React serializes props, even if we wrap it in a Ref
5-
// the GopherJS will convert structs to JS objects,
6-
// instead we use a global singleton instead to pass around global state.
7-
//
8-
// This could be problematic if we ever want to have multiple code editors
9-
// on the same page, but that is not a use case we currently have to support.
10-
package react
1+
package page
112

123
import (
134
"sync"
@@ -18,6 +9,15 @@ import (
189
"github.com/gopherjs/gopherjs.github.io/playground/internal/undoRedo"
1910
)
2011

12+
// globals are the global objects used by the react components.
13+
//
14+
// Since passing Go structs through React props will cause problems
15+
// because of how React serializes props, even if we wrap it in a Ref
16+
// the GopherJS will convert structs to JS objects,
17+
// instead we use a global singleton instead to pass around global state.
18+
//
19+
// This could be problematic if we ever want to have multiple code editors
20+
// on the same page, but that is not a use case we currently have to support.
2121
var globals = struct {
2222
UndoRedo func() common.UndoRedoStack
2323
SnippetsStore func() common.SnippetStore
Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
package react
1+
package page
22

33
import (
44
"fmt"
55
"go/scanner"
66

77
"github.com/gopherjs/gopherjs.github.io/playground/internal/common"
8+
"github.com/gopherjs/gopherjs.github.io/playground/internal/react"
89
)
910

1011
const (
@@ -14,11 +15,11 @@ const (
1415
contextKey = `context`
1516
)
1617

17-
func Output(setOutput Setter) common.Output {
18+
func Output(setOutput react.Setter) common.Output {
1819
return &outputImpl{setOutput: setOutput}
1920
}
2021

21-
type outputImpl struct{ setOutput Setter }
22+
type outputImpl struct{ setOutput react.Setter }
2223

2324
func (o *outputImpl) Clear() {
2425
o.setOutput.Invoke([]any{})
@@ -50,19 +51,19 @@ func (o *outputImpl) AddOutput(out string) {
5051
}
5152

5253
// OutputBox creates a box React element for displaying output strings and errors.
53-
func OutputBox(output []any) *Element {
54-
return CreateElement(outputBoxComponent, Props{
54+
func OutputBox(output []any) *react.Element {
55+
return react.CreateElement(outputBoxComponent, react.Props{
5556
`output`: output,
5657
})
5758
}
5859

59-
func outputBoxComponent(props Props) *Element {
60+
func outputBoxComponent(props react.Props) *react.Element {
6061
var (
6162
output = props.Get(`output`).([]any)
62-
outputBoxRef = UseRef()
63+
outputBoxRef = react.UseRef()
6364
)
6465

65-
UseEffect(func() {
66+
react.UseEffect(func() {
6667
// If there are only errors, scroll to the top,
6768
// otherwise scroll to the bottom.
6869
outputBox := outputBoxRef.Current()
@@ -73,7 +74,7 @@ func outputBoxComponent(props Props) *Element {
7374
outputBox.Set(`scrollTop`, scrollTop)
7475
}, []any{output})
7576

76-
children := make([]Node, 0, len(output))
77+
children := make([]react.Node, 0, len(output))
7778
for i, item := range output {
7879
itemMap := item.(map[string]any)
7980
children = append(children, outputLine(
@@ -82,7 +83,7 @@ func outputBoxComponent(props Props) *Element {
8283
))
8384
}
8485

85-
return Div(Props{
86+
return react.Div(react.Props{
8687
`id`: `output-box`,
8788
`ref`: outputBoxRef,
8889
}, children...)
@@ -102,15 +103,15 @@ func hasNonErrors(output []any) bool {
102103
// outputLine creates a React element for a single output line.
103104
// The index is used to create a unique ID for the line so it should
104105
// be the line's position in the output list.
105-
func outputLine(index int, isError bool, content string) *Element {
106-
return CreateElement(outputLineComponent, Props{
106+
func outputLine(index int, isError bool, content string) *react.Element {
107+
return react.CreateElement(outputLineComponent, react.Props{
107108
`index`: index,
108109
`isError`: isError,
109110
`content`: content,
110111
})
111112
}
112113

113-
func outputLineComponent(props Props) *Element {
114+
func outputLineComponent(props react.Props) *react.Element {
114115
var (
115116
index = props.GetInt(`index`)
116117
isError = props.GetBool(`isError`)
@@ -123,7 +124,7 @@ func outputLineComponent(props Props) *Element {
123124
}
124125
id := fmt.Sprintf(`output-item-%d`, index)
125126

126-
return Pre(Props{
127+
return react.Pre(react.Props{
127128
`className`: classType,
128129
`id`: id,
129130
}, content)

0 commit comments

Comments
 (0)