Skip to content

Commit

Permalink
- added bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
rocketlaunchr-cto committed Oct 16, 2018
1 parent 2f3e181 commit bfda483
Show file tree
Hide file tree
Showing 9 changed files with 2,853 additions and 0 deletions.
1,694 changes: 1,694 additions & 0 deletions elements/elements.go

Large diffs are not rendered by default.

364 changes: 364 additions & 0 deletions elements/styles.go

Large diffs are not rendered by default.

63 changes: 63 additions & 0 deletions helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package main

import (
"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 functions.
func JSFn(name string, args ...interface{}) *js.Object {
return js.Global.Call(name, args...)
}

// 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...)
}
})
}
36 changes: 36 additions & 0 deletions react.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package main

import (
"github.com/gopherjs/gopherjs/js"
"honnef.co/go/js/dom"
)

var (
// React points to the React library. Change it
// if it is not in your global namespace.
React = js.Global.Get("React")
// ReactDOM points to the ReactDOM library. Change it
// if it is not in your global namespace.
ReactDOM = js.Global.Get("ReactDOM")
// CreateReactClass points to create-react-class module.
CreateReactClass = js.Global
)

// ForceUpdate will force a rerender of the component.
// See: https://reactjs.org/docs/react-component.html#forceupdate
func ForceUpdate(this *js.Object, callback ...func()) {

if len(callback) > 0 && callback[0] != nil {
this.Call("forceUpdate", callback[0])
} else {
this.Call("forceUpdate")
}
}

// Render will render component to the specified target dom element.
func Render(element *js.Object, domTarget dom.Element, callback ...func()) *js.Object {
if len(callback) > 0 && callback[0] != nil {
return ReactDOM.Call("render", element, domTarget, callback[0])
}
return ReactDOM.Call("render", element, domTarget)
}
116 changes: 116 additions & 0 deletions react_class.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package main

import (
"github.com/gopherjs/gopherjs/js"
)

// Map is a convenience method that can be used to access fields in a
// js object.
type Map func(key string) *js.Object

// UpdaterFunc is the first argument for SetState method.
// See: https://reactjs.org/docs/react-component.html#setstate
type UpdaterFunc func(props, state Map) interface{}

// SetState is used to asynchronously update the state.
// See: https://reactjs.org/docs/react-component.html#setstate
type SetState func(updater interface{}, callback ...func())

type ClassDef map[string]interface{}

// NewClassDef will create an empty class definition which can immediately be used
// to create a React component.
func NewClassDef(displayName string) ClassDef {
def := ClassDef{
render: js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
return nil
}),
}
def["displayName"] = displayName
return def
}

func (def ClassDef) setMethod(static bool, name string, f func(this *js.Object, props, state Map, setState SetState, arguments []*js.Object) interface{}) {

const statics = "statics"

if f == nil {
// Clear method
if static {
if _, exists := def[statics]; exists {
switch s := def[statics].(type) {
case (map[string]interface{}):
delete(s, name)
default:

}
}
} else {
delete(def, name)
}
return
}

if !static && name == statics {
panic("can't have function name called 'statics'")
}

x := func(this *js.Object, arguments []*js.Object) interface{} {

props := func(key string) *js.Object {
return this.Get("props").Get(key)
}

state := func(key string) *js.Object {
return this.Get("state").Get(key)
}

setState := func(updater interface{}, callback ...func()) {

if updater == nil {
return
}

if len(callback) > 0 && callback[0] != nil {
switch updater := updater.(type) {
case func(props, state Map) interface{}:
this.Call("setState", SToMap(updater(props, state)), callback[0])
case UpdaterFunc:
this.Call("setState", SToMap(updater(props, state)), callback[0])
default:
this.Call("setState", SToMap(updater), callback[0])
}
} else {
switch updater := updater.(type) {
case func(props, state Map) interface{}:
this.Call("setState", SToMap(updater(props, state)))
case UpdaterFunc:
this.Call("setState", SToMap(updater(props, state)))
default:
this.Call("setState", SToMap(updater))
}
}
}

return f(this, props, state, setState, arguments)
}

if static {
def[statics] = map[string]interface{}{
name: js.MakeFunc(x),
}
} else {
def[name] = js.MakeFunc(x)
}
}

// SetMethod allows a custom method to be attached.
// By passing nil for f, the method can also be detached (cleared).
func (def ClassDef) SetMethod(name string, f func(this *js.Object, props, state Map, setState SetState, arguments []*js.Object) interface{}) {
def.setMethod(false, name, f)
}

// ReactCreateClass is used to create a react component.
func ReactCreateClass(def ClassDef) *js.Object {
return CreateReactClass.Call("createReactClass", def)
}
Loading

0 comments on commit bfda483

Please sign in to comment.