-
Notifications
You must be signed in to change notification settings - Fork 11
/
helpers.go
134 lines (113 loc) · 3.17 KB
/
helpers.go
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
132
133
134
// Copyright 2018 PJ Engineering and Business Solutions Pty. Ltd. All rights reserved.
package react
import (
"strings"
"github.com/gopherjs/gopherjs/js"
)
// Fragment is used to group a list of children
// without adding extra nodes to the DOM.
//
// See: https://reactjs.org/docs/fragments.html
func Fragment(key *string, children ...interface{}) *js.Object {
props := map[string]interface{}{}
if key != nil {
props["key"] = *key
}
return JSX(React.Get("Fragment"), props, children...)
}
// JSX is used to create an Element.
func JSX(component interface{}, props interface{}, children ...interface{}) *js.Object {
args := []interface{}{
component,
SToMap(props),
}
if len(children) > 0 {
args = append(args, children...)
}
return React.Call("createElement", args...)
}
// JSFn is a convenience function used to call javascript native functions.
// If the native function throws an exception, then a *js.Error is returned.
//
// Example:
//
// // alert('Hello World!')
// JSFn("alert", "Hello World!")
//
// // JSON.parse('{"name":"John"}')
// JSFn("JSON.parse", `{"name":"John"}`)
//
func JSFn(funcName string, args ...interface{}) (_ *js.Object, rErr error) {
defer func() {
if e := recover(); e != nil {
err, ok := e.(*js.Error)
if !ok {
panic(e)
}
rErr = err
}
}()
out := js.Global
splits := strings.Split(funcName, ".")
for idx, split := range splits {
if idx == len(splits)-1 {
out = out.Call(split, args...)
} else {
out = out.Get(split)
}
}
return out, nil
}
// CreateRef will create a Ref.
//
// See: https://reactjs.org/docs/refs-and-the-dom.html
func CreateRef() *js.Object {
return React.Call("createRef")
}
// ForwardRef will forward a Ref to child components.
//
// See: https://reactjs.org/docs/forwarding-refs.html
func ForwardRef(component interface{}) *js.Object {
return React.Call("forwardRef", func(props *js.Object, ref *js.Object) *js.Object {
props.Set("ref", ref)
n := React.Get("Children").Call("count", props.Get("children")).Int()
switch n {
case 0:
return JSX(component, props)
case 1:
return JSX(component, props, props.Get("children"))
default:
children := []interface{}{}
for i := 0; i < n; i++ {
children = append(children, props.Get("children").Index(i))
}
return JSX(component, props, children...)
}
})
}
// CreateContext is used when you want to pass data to a deeply
// embedded child component without using props.
//
// See: https://reactjs.org/docs/context.html#reactcreatecontext
func CreateContext(defaultValue ...interface{}) (Context *js.Object, Provider *js.Object, Consumer *js.Object) {
var res *js.Object
if len(defaultValue) > 0 {
res = React.Call("createContext", defaultValue[0])
} else {
res = React.Call("createContext")
}
return res, res.Get("Provider"), res.Get("Consumer")
}
// CloneElement is used to clone and return a new React Element.
//
// See: https://reactjs.org/docs/react-api.html#cloneelement
func CloneElement(element interface{}, props interface{}, children ...interface{}) *js.Object {
args := []interface{}{
element,
SToMap(props),
}
if len(children) > 0 {
args = append(args, children...)
}
return React.Call("cloneElement", args...)
}