Giter Site home page Giter Site logo

coconut.ui's People

Contributors

back2dos avatar kevinresol avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

coconut.ui's Issues

Feature request: have default children for view classes also

Right now if you have a coconut view then it's impossible to have default children, and you always have to specify it. If you create View classes that are used as containers many times it would be convinient to just define the children directly.

ie using hxx:

<List>
    <ListItem>hello1</ListItem>
    <ListItem>hello2</ListItem>
    <ListItem>hello3</ListItem>
</List>

Add an observability check for `@:computed` properties in views

From discord:
I have a Array<Array> which worked fine as @:computed, but now I tried to clean the stuff up and made a new component. Then I want to pass that computed array to the component, so I have to convert that to a pure list. Would be nice if this could keep working.

React like Context

As it's been asked before thought I'd add it for discussion. Not sure what it would look like in coconut terms. Or if it should interop with React's implementation when using coconut.react-core.

Parsing problem

I think this one is about tink_hxx, but I am not sure

import coconut.Ui.*;
import coconut.ui.*;
import coconut.data.*;


class Main {
    static function main() {
        hxx('<Dropdown values=${List.fromArray([{name:'a'}, {name:'b'}])} />');
    }
}

class Dropdown extends View<{values:List<Value>}> {
    function render() '<div/>';
}

typedef Value = {
    var name(default, never):String;
}

Error:
/Users/kevin/Codes/test/src/Main.hx:9: characters 67-68 : Unexpected b

If main() is

static function main() {
    var list = List.fromArray([{name:'a'}, {name:'b'}]);
    hxx('<Dropdown values=${List.fromArray([{name:'a'}, {name:'b'}])} />');
}

Error becomes:

/Users/kevin/Codes/test/src/Main.hx:9: characters 67-68 : Unexpected b
/Users/kevin/Codes/test/src/Main.hx:9: characters 67-68 : Missing ;
/Users/kevin/Codes/test/src/Main.hx:9: characters 68-77 : Missing ;
/Users/kevin/Codes/test/src/Main.hx:9: characters 77-78 : Unexpected )

It compiles if the List is stored in a variable before hxx();

[gen4] should ref be a State?

So instead of {current:T} it is State<T>

so in viewDidMount we can write:

var binding = ref.bind(null, div -> doSomething(div));
untilUnmounted(binding.dissolve);

otherwise with the current implementation we need to handle both viewDidMount and viewDidUpdate? Or did I miss something?

default @:attribute not working as before

I used to have something like this, that worked before the last change 2922be9

class MyButton extends View {
	@:attribute var title: String;
	@:attribute var click: Void->Void;
	@:attribute var child: Void->RenderResult = emptyChild;

	function emptyChild()
		return <span></span>;

	function render() {
		return
			<a href="#" 
				class="button button-outline" 
				onclick={click}
			>{title}
			{child()}
			</a>;
	}
}

now I get an error "TypeError: tink_state_Observable.get_value(...) is not a function" in:

        ,child: function() {
		return (tink_state_Observable.get_value(this.__coco_child))();
	}

looks like __coco_child is initialized with something weird

Extremely unreadable error messages

Many times when I generate an error in a view class that inherits the properties of a big object I receive such error messages:

Error: (<js.html.Event, js.html.InputElement>>>, ?ongotpointercapture) Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onfullscreenerror : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onfullscreenchange : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onfocus : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onerror : Null<tink.Callback<vdom.EventFrom<js.html.ErrorEvent, js.html.InputElement>>>, ?onended : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onemptied : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?ondurationchange : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?ondrop : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondragstart : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondragover : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondragleave : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondragenter : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondragend : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondrag : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondblclick : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?oncut : Null<tink.Callback<vdom.EventFrom<js.html.ClipboardEvent, js.html.InputElement>>>, ?oncopy : Null<tink.Callback<vdom.EventFrom<js.html.ClipboardEvent, js.html.InputElement>>>, ?oncontextmenu : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onclick : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onchange : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?oncanplaythrough : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?oncanplay : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onblur : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onabort : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?name : Null<Null<String>>, ?min : Null<Null<String>>, ?maxlength : Null<Int>, ?max : Null<Null<String>>, ?lang : Null<Null<String>>, ?label : Null<Null<String>>, ?key : Null<Null<vdom.Key>>, ?id : Null<Null<String>>, ?icon : Null<Null<String>>, ?hidden : Null<Bool>, ?draggable : Null<Bool>, ?disabled : Null<Bool>, ?dir : Null<Null<String>>, ?dense : Null<Bool>, ?contentEditable : Null<Bool>, ?compact2 : Null<Bool>, ?className : Null<Null<vdom.ClassName>>, ?checked : Null<Bool>, ?attributes : Null<Null<vdom.PureDynamicAccess<vdom.Ext>>>, ?accessKeyLabel : Null<Null<String>>, ?accessKey : Null<Null<String>> } should be mdc.ButtonAttr
Error: (putElement>>>, ?onfullscreenerror) Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onfullscreenchange : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onfocus : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onerror : Null<tink.Callback<vdom.EventFrom<js.html.ErrorEvent, js.html.InputElement>>>, ?onended : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onemptied : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?ondurationchange : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?ondrop : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondragstart : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondragover : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondragleave : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondragenter : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondragend : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondrag : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondblclick : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?oncut : Null<tink.Callback<vdom.EventFrom<js.html.ClipboardEvent, js.html.InputElement>>>, ?oncopy : Null<tink.Callback<vdom.EventFrom<js.html.ClipboardEvent, js.html.InputElement>>>, ?oncontextmenu : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onclick : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onchange : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?oncanplaythrough : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?oncanplay : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onblur : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onabort : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?name : Null<Null<String>>, ?min : Null<Null<String>>, ?maxlength : Null<Int>, ?max : Null<Null<String>>, ?lang : Null<Null<String>>, ?label : Null<Null<String>>, ?key : Null<Null<vdom.Key>>, ?id : Null<Null<String>>, ?icon : Null<Null<String>>, ?hidden : Null<Bool>, ?draggable : Null<Bool>, ?disabled : Null<Bool>, ?dir : Null<Null<String>>, ?dense : Null<Bool>, ?contentEditable : Null<Bool>, ?compact2 : Null<Bool>, ?className : Null<Null<vdom.ClassName>>, ?checked : Null<Bool>, ?attributes : Null<Null<vdom.PureDynamicAccess<vdom.Ext>>>, ?accessKeyLabel : Null<Null<String>>, ?accessKey : Null<Null<String>> } should be { ?value : Null<String>, ?unelevated : Null<Bool>, ?type : Null<String>, ?title : Null<String>, ?tabIndex : Null<Int>, ?style : Null<vdom.Style>, ?stroked : Null<Bool>, ?step : Null<String>, ?spellcheck : Null<Bool>, ?ripple : Null<Bool>, ?required : Null<Bool>, ?raised : Null<Bool>, ?placeholder : Null<String>, ?onwheel : Null<tink.Callback<vdom.EventFrom<js.html.WheelEvent, js.html.InputElement>>>, ?onwaiting : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onvolumechange : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?ontouchstart : Null<tink.Callback<vdom.EventFrom<js.html.TouchEvent, js.html.InputElement>>>, ?ontouchmove : Null<tink.Callback<vdom.EventFrom<js.html.TouchEvent, js.html.InputElement>>>, ?ontouchend : Null<tink.Callback<vdom.EventFrom<js.html.TouchEvent, js.html.InputElement>>>, ?ontouchcancel : Null<tink.Callback<vdom.EventFrom<js.html.TouchEvent, js.html.InputElement>>>, ?ontimeupdate : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onsuspend : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onsubmit : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onstalled : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onshow : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onselect : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onseeking : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onseeked : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onscroll : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onresize : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onreset : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onratechange : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onprogress : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onpointerup : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointerover : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointerout : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointermove : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointerlockerror : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onpointerlockchange : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onpointerleave : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointerenter : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointerdown : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointercancel : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onplaying : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onplay : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onpause : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onpaste : Null<tink.Callback<vdom.EventFrom<js.html.ClipboardEvent, js.html.InputElement>>>, ?onmouseup : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onmouseover : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onmouseout : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onmousemove : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onmouseleave : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onmouseenter : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onmousedown : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onlostpointercapture : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onloadstart : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onloadedmetadata : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onloadeddata : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onload : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onkeyup : Null<tink.Callback<vdom.EventFrom<js.html.KeyboardEvent, js.html.InputElement>>>, ?onkeypress : Null<tink.Callback<vdom.EventFrom<js.html.KeyboardEvent, js.html.InputElement>>>, ?onkeydown : Null<tink.Callback<vdom.EventFrom<js.html.KeyboardEvent, js.html.InputElement>>>, ?oninvalid : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?oninput : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?ongotpointercapture : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onfullscreenerror : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onfullscreenchange : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onfocus : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onerror : Null<tink.Ca
Error: (llback<vdom.EventFrom<js.html.ErrorEvent, js.html.InputElement>>>, ?onended) Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onemptied : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?ondurationchange : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?ondrop : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondragstart : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondragover : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondragleave : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondragenter : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondragend : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondrag : Null<tink.Callback<vdom.EventFrom<js.html.DragEvent, js.html.InputElement>>>, ?ondblclick : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?oncut : Null<tink.Callback<vdom.EventFrom<js.html.ClipboardEvent, js.html.InputElement>>>, ?oncopy : Null<tink.Callback<vdom.EventFrom<js.html.ClipboardEvent, js.html.InputElement>>>, ?oncontextmenu : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onclick : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onchange : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?oncanplaythrough : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?oncanplay : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onblur : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onabort : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?name : Null<String>, ?min : Null<String>, ?maxlength : Null<Int>, ?max : Null<String>, ?lang : Null<String>, ?label : Null<String>, ?key : Null<vdom.Key>, ?id : Null<String>, ?icon : Null<String>, ?hidden : Null<Bool>, ?draggable : Null<Bool>, ?disabled : Null<Bool>, ?dir : Null<String>, ?dense : Null<Bool>, ?contentEditable : Null<Bool>, ?compact2 : Null<Bool>, ?className : Null<vdom.ClassName>, ?checked : Null<Bool>, ?attributes : Null<vdom.PureDynamicAccess<vdom.Ext>>, ?accessKeyLabel : Null<String>, ?accessKey : Null<String> }
Information:No additional error information available.
Error: (Command exited with an error code) 1
C:\Users\grosmar\AppData\Roaming\haxe\haxe_libraries\coconut.ui\0.6.1\haxelib\src\coconut\ui\macros\ViewBuilder.hx
Error:(127, 79) { ?value : Null<Null<String>>, ?unelevated : Null<Bool>, ?type : Null<Null<String>>, ?title : Null<Null<String>>, ?tabIndex : Null<Int>, ?style : Null<Null<vdom.Style>>, ?stroked : Null<Bool>, ?step : Null<Null<String>>, ?spellcheck : Null<Bool>, ?ripple : Null<Bool>, ?required : Null<Bool>, ?raised : Null<Bool>, ?placeholder : Null<Null<String>>, ?onwheel : Null<tink.Callback<vdom.EventFrom<js.html.WheelEvent, js.html.InputElement>>>, ?onwaiting : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onvolumechange : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?ontouchstart : Null<tink.Callback<vdom.EventFrom<js.html.TouchEvent, js.html.InputElement>>>, ?ontouchmove : Null<tink.Callback<vdom.EventFrom<js.html.TouchEvent, js.html.InputElement>>>, ?ontouchend : Null<tink.Callback<vdom.EventFrom<js.html.TouchEvent, js.html.InputElement>>>, ?ontouchcancel : Null<tink.Callback<vdom.EventFrom<js.html.TouchEvent, js.html.InputElement>>>, ?ontimeupdate : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onsuspend : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onsubmit : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onstalled : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onshow : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onselect : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onseeking : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onseeked : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onscroll : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onresize : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onreset : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onratechange : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onprogress : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onpointerup : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointerover : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointerout : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointermove : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointerlockerror : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onpointerlockchange : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onpointerleave : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointerenter : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointerdown : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointercancel : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onplaying : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onplay : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onpause : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onpaste : Null<tink.Callback<vdom.EventFrom<js.html.ClipboardEvent, js.html.InputElement>>>, ?onmouseup : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onmouseover : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onmouseout : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onmousemove : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onmouseleave : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onmouseenter : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onmousedown : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onlostpointercapture : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onloadstart : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onloadedmetadata : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onloadeddata : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onload : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onkeyup : Null<tink.Callback<vdom.EventFrom<js.html.KeyboardEvent, js.html.InputElement>>>, ?onkeypress : Null<tink.Callback<vdom.EventFrom<js.html.KeyboardEvent, js.html.InputElement>>>, ?onkeydown : Null<tink.Callback<vdom.EventFrom<js.html.KeyboardEvent, js.html.InputElement>>>, ?oninvalid : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?oninput : Null<tink.Callback<vdom.EventFrom
Error:(127, 79) { ?value : Null<Null<String>>, ?unelevated : Null<Bool>, ?type : Null<Null<String>>, ?title : Null<Null<String>>, ?tabIndex : Null<Int>, ?style : Null<Null<vdom.Style>>, ?stroked : Null<Bool>, ?step : Null<Null<String>>, ?spellcheck : Null<Bool>, ?ripple : Null<Bool>, ?required : Null<Bool>, ?raised : Null<Bool>, ?placeholder : Null<Null<String>>, ?onwheel : Null<tink.Callback<vdom.EventFrom<js.html.WheelEvent, js.html.InputElement>>>, ?onwaiting : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onvolumechange : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?ontouchstart : Null<tink.Callback<vdom.EventFrom<js.html.TouchEvent, js.html.InputElement>>>, ?ontouchmove : Null<tink.Callback<vdom.EventFrom<js.html.TouchEvent, js.html.InputElement>>>, ?ontouchend : Null<tink.Callback<vdom.EventFrom<js.html.TouchEvent, js.html.InputElement>>>, ?ontouchcancel : Null<tink.Callback<vdom.EventFrom<js.html.TouchEvent, js.html.InputElement>>>, ?ontimeupdate : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onsuspend : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onsubmit : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onstalled : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onshow : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onselect : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onseeking : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onseeked : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onscroll : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onresize : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onreset : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onratechange : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onprogress : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onpointerup : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointerover : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointerout : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointermove : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointerlockerror : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onpointerlockchange : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onpointerleave : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointerenter : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointerdown : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onpointercancel : Null<tink.Callback<vdom.EventFrom<js.html.PointerEvent, js.html.InputElement>>>, ?onplaying : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onplay : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onpause : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onpaste : Null<tink.Callback<vdom.EventFrom<js.html.ClipboardEvent, js.html.InputElement>>>, ?onmouseup : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onmouseover : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onmouseout : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onmousemove : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onmouseleave : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onmouseenter : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onmousedown : Null<tink.Callback<vdom.EventFrom<js.html.MouseEvent, js.html.InputElement>>>, ?onlostpointercapture : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onloadstart : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onloadedmetadata : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onloadeddata : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onload : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?onkeyup : Null<tink.Callback<vdom.EventFrom<js.html.KeyboardEvent, js.html.InputElement>>>, ?onkeypress : Null<tink.Callback<vdom.EventFrom<js.html.KeyboardEvent, js.html.InputElement>>>, ?onkeydown : Null<tink.Callback<vdom.EventFrom<js.html.KeyboardEvent, js.html.InputElement>>>, ?oninvalid : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?oninput : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.InputElement>>>, ?ongotpointercapture : Null<tink.Callback<vdom.EventFrom<js.html.Event, js.html.In
Error:(127, 79) Inconsistent setter for field compact2 : never should be default
Error:(127, 79) For function argument 'attr'
D:\GIT-REPOS\coconut.mdc\src\mdc\Button.hx
Error:(9, -1) Defined in this class

Finding the error in it is kind of hell. I guess it's coming from the nature of the compiler.
My proposal is a big change, but what if the View class signature would look like this:
class View<{attr:T, ?children:T}> extends BaseView ...

It would make the types readable in case of error also, and it would make place for default children too.

What do you think?

Type not found : TagCreate

When pasting your first sample from the doc it triggers:
coconut,ui/0,9,0/src/coconut/ui/macros/Generator.hx:63: characters 55-64 : Type not found : TagCreate

I don't know if there's some magic under the hood but TagCreate in Generator.hx is imported with import tink.hxx.Generator.TagCreate; and doesn't seem to exist in that file (unless built from macro !?).

TagCreate exists in tink.hxx.Generator.Tag though, but importing it spawn different errors.

I'm using haxe4-rc1

Returning nothing from view if top level element is a conditional

We ran into a view that had:

class Blub extends View {
  @:attribute var foo:Bool;
  function render() '
    <if {foo}><button>click me</button></if>
  ';
}

This can become problematic in many cases, for example when calling toElement to mount it into DOM, but receiving null. Simplest solution would be to disallow for views to return nothing - could be achieved in hxx.

Do not invalidate views for callback changes.

If an attribute changes that is a Callback (or a function returning Void), it's not necessary to invalidate the view. However, proper storage and propagation will be slightly tricky:

class Container extends View {
  @:attribute var onclick:Void->Void;
  function render() '
    <Button onclick={onclick} />
  ';
}

If onclick changes in the Container, then it should also change in the child Button. One way to achieve this would be to wrap callback attributes in something like this:

abstract Action<T>(Void->T) {
  public function get():T return this();
  @:from macro static function ofAny<T>(e:ExprOf<T>):ExprOf<Action<T>>;
}

This is similar to coconut.data.Value, except that it provides just indirection without the overhead of observability.

[gen4] Cannot parameterize a View

class Main {
	static function main() {}
}

class MyView<T:EnumValue> extends coconut.ui.View {
	@:attr var data:Data<T>;
	function render() return null;
}

class Data<T:EnumValue> implements coconut.data.Model {}

This gives Type not found : T

Commenting out the attribute results in Invalid number of type parameters for MyView

Null safety support?

Hi

Sorry if it already was discussed, but I did not find anything related.
Looks like currently coconut.ui not supporting Haxe's new null safety feature.
Is there any plans to support it?

Thank you

Creating a custom backend for coconut.ui

So I have been working on an imitation of vdom.VDom, the repository is here xdom, it depends on Haxe's Xml library, instead of javascript DOM library.

Although their implementations are different, I followed the tests in tink.hxx to craft mine, but I don't know how to go about making it compatible with coconut.ui.

This is what the generator code looks like:

package xdom;

import haxe.DynamicAccess;
import haxe.macro.Expr;

using tink.hxx.Node;

import tink.hxx.Located;

using tink.hxx.Attribute;

#if macro
class Dom extends tink.hxx.Generator {
	var __root:Expr;

	public function new(e) {
		super();
		this.__root = e;
	}

	var childrenType = haxe.macro.ComplexTypeTools.toType(macro:Dynamic);

	override function node(n:tink.hxx.Node, pos:haxe.macro.Expr.Position) {
		var attr:Array<tink.anon.Macro.Part> = [], splats = [];

		for (a in n.attributes)
			switch a {
				case Splat(e):
					splats.push(e);
				case Empty(name):
					attr.push({
						name: name.value,
						pos: name.pos,
						getValue: function(_) return macro @:pos(name.pos) true,
					});
				case Regular(name, value):
					attr.push({
						name: name.value,
						pos: name.pos,
						getValue: function(_) return value,
					});
			}

		var a = tink.anon.Macro.mergeParts(attr, splats, pos, macro:Dynamic);
		var children = switch n.children {
			case null | {value: null | []}: macro null;
			case v: {
				makeChildren(v, childrenType, false);
			}
		}
		return macro @:pos(pos) Root.tag($__root, $v{n.name.value}, $a, $children);
	}
}
#end

The DOM representation:

package xdom;

import haxe.macro.Expr;

abstract Root(Xml) from Xml to Xml {


	public inline function new(?name:String) {
		if (name != null) {
			this = Xml.createElement(name);
		} else {
			this = Xml.createElement('root');
		}
	}

	static public function tag(?root:Root, name:String, attr:Dynamic, ?children:Array<Dynamic>):Dynamic {
		
		if (root == null) {
			root = Xml.createElement(name);

			for (a in Reflect.fields(attr)) {
				root.set(a, Reflect.field(attr, a));
			}
			
			if (children != null)
				for (child in children) {
					root.addChild(child);
				}

			return root;
		} else {
			var child = Xml.createElement(name);
			for (a in Reflect.fields(attr)) {
				child.set(a, Reflect.field(attr, a));
			}
			
			if (children != null)
				for (_child in children) {
					if(Std.is(_child, Xml)){
						child.addChild(_child);
					} else {
						child.addChild(Xml.createPCData(_child));
					}
				}

			root.addChild(child);

			return child;
		}
	}

       .......

	macro public function update(ethis, e) {
		return new Dom(ethis).root(tink.hxx.Parser.parseRoot(e, {
			defaultExtension: 'hxx',
			isVoid: function(s) return switch s.value {
				case 'img': true;
				default: false;
			}
		}));
	}
}

[gen4] Is `@:computed` supposed to work?

haxe 4p3

import coconut.ui.*;
import coconut.Ui.*;
import js.Browser.*;

class Main extends View {
  static function main() {
    Renderer.mount(document.body, hxx('<Main/>'));
  }
  
  @:attr var foo:Int = 0;
  @:computed var bar:Int = foo + 1;
  
  function render() {
    trace('render');
    return @hxx '
      <div>${foo} ${bar}</div>
    ';
  }
}

Generated the following code:

var Main = function(__coco_data_) {
	this.bar = tink_state__$Observable_Observable_$Impl_$.get_value(this.__slots.foo) + 1;
	this.__tink_defaults0 = { foo : tink_state__$Observable_Observable_$Impl_$["const"](0)};
	this.__slots = { foo : new coconut_ui_tools_Slot(this,null)};
	this.__initAttributes(__coco_data_);
	coconut_ui_View.call(this,$bind(this,this.render),null,null,null,null,null);
};

and this.__slots.foo is still undefined at the first line

exception after removing items from ObservableArray

Running mostly github versions of everything, I get Cannot read property '__coco_i' of undefined in RowView.render.

class Main {
    public static function main() {
        var data = new Data();
        coconut.ui.Renderer.mount(
            cast js.Browser.document.body.appendChild(js.Browser.document.createDivElement()),
            coconut.Ui.hxx('
                <div><for {item in data.rows}>
                    <RowView row={item} />
                </for></div>')
        );
        haxe.Timer.delay(function() data.rows.splice(1, 1), 1000);
    }
}

class RowView extends coconut.ui.View {
    @:attribute var row:Row;
    function render() '<div>{row.i}</div>';
}

class Data implements coconut.data.Model {
    var rows:tink.state.ObservableArray<Row> = new tink.state.ObservableArray(
        [for(i in 0...10) new Row({ i: i })]
    );
}

class Row implements coconut.data.Model {
    @:editable var i:Int;
}

@:tracked and ObservableMap

Probably @:tracked could somehow support an expression to support tracking the internals of some structures like ObservableMap?

like @:tracked(_.get('key'))

Wrong error position when typing @:state

@:state var date:Date = '';

The above typing error is reported as
coconut/ui/macros/ViewBuilder.hx:174: characters 83-107 : tink.state.State<Date> should be tink.state.State<String>

Type errors are swallowed

class Main extends coconut.ui.View {
    static function main() {}
    function render() '<Page/>';
}

class Page extends coconut.ui.View {
    function render() '<div/>';
    override function afterInit(e) Extern.foo(('str':Int));
}

extern class Extern {
	@:overload(function(s:String):Void {})
	static function foo(i:Int):Void;
}

Error: (note that there are actually no "reasons" printed)

src/Main.hx:8: characters 36-59 : Could not find a suitable overload, reasons follow
The terminal process terminated with exit code: 1

Instead if the afterInit is moved into the Main class, we get:


src/Main.hx:4: characters 36-59 : Could not find a suitable overload, reasons follow
src/Main.hx:4: characters 36-59 : Overload resolution failed for i : Int -> Void
src/Main.hx:4: characters 47-58 : String should be Int
src/Main.hx:4: characters 47-58 : For function argument 'i'
src/Main.hx:4: characters 36-59 : Overload resolution failed for s : String -> Void
src/Main.hx:4: characters 47-58 : String should be Int
src/Main.hx:4: characters 47-58 : For function argument 's'
src/Main.hx:4: characters 36-59 : End of overload failure reasons
The terminal process terminated with exit code: 1

Note: benchmarking

Not a bug, just a quick note not to forget (you can close the issue after reading, just thought putting this here as more chances to be useful than lost in a gitter chat).

Reading this article I noticed they use an interesting benchmark to compare different flavours of react.

example image

Seems to be located here : https://rawgit.com/krausest/js-framework-benchmark/master/webdriver-ts-results/table.html if it's still there.

That's all. So if there's a need one day for another benchmark we can look that up.

Should be able to trigger Views lifecycle events also if just a subview updates

If I have a @:state or @:attr in a View class and it's only consumed by a subelement, then there are no lifecycles fired in my View class, however maybe I want to do some computation based on them.

The only hack I found so far, to reference these properties in the beginning of the render() function, but it's not really nice.

xDOM incompatibility in haxe4rc5

class Main extends coconut.ui.View {
    @:ref var img:js.html.ImageElement;
    function render() '<img ref=${img}/>';
    static function main() {}
}

This use to work but in rc5 I get js.html.ImageElement should be Null<coconut.ui.Ref<xdom.Wrapped<js.html.ImageElement>>>

Avoid recreating anonymous functions.

Given this view:

class Foo extends View {
  @:state var bar = 1;
  function render() '
     <div>
       <Child onblub={bar++} />
       <span>{bar}</span>
     </div>
  ';
}

The blub event handler is a function that always does the same thing, but at every rerender a new function gets created, thus invalidating the view.

For anonymous functions, it should be possible to find out which variables they capture (in this case none) and then use those (and the string represenation of the function's AST) as a cache key. For example in TodoMVC the item and function (event) todos.delete(item) would be the cache key.

[gen4] type errors are mutated to something weird

// Main.hx
class Main extends coconut.ui.View {
  static function main() {}
  function render() '<Foo/>';
}

// Foo.hx
class Foo extends coconut.ui.View {
	function render() '<div/>';
	function capture(e:Dummy) {}
}

Expected: Type not found : Dummy
Actual: this direct initialization causes the compiler to do really weird things

Render function as attribute no longer works

The following code no longer works in gen4

import coconut.ui.*;

class Dashboard extends View {
  @:attr var sidebar:{className:String}->RenderResult;
  function render() '<div/>';
}

class SideBar extends View {
  @:attr var className:String;
  function render() '<div/>';
}

class Main extends View {
  static function main() {}
  function render() '
    <Dashboard><sidebar attr><SideBar ${...attr}/></sidebar></Dashboard>
  ';
}

Error (without position): Array<Unknown<0>> should be { className : String } -> coconut.ui.RenderResult

[regression] Function type attributes are generated as member function?

import coconut.Ui.hxx;

class Main extends coconut.ui.View {
	
	static function main() {
		trace(hxx('<Main/>'));
	}
	
	@:attr var onPress:Void->Void = null;
	
	function render() '
		<div>
			<if ${onPress == null}>
				<div onclick=${onPress}>Button</div>
			<else>
				No Button
			</if>
		</div>
	';
}

Generated this:

Main.prototype = $extend(coconut_ui_View.prototype,{
	onPress: function() {
		(tink_state__$Observable_Observable_$Impl_$.get_value(this.__slots.onPress))();
		return;
	}
	,render: function() {
		var __r = [];
		var __r1 = [];
		if(this.onPress == null) {
			var __ret = { onclick : tink_core__$Callback_Callback_$Impl_$.fromNiladic($bind(this,this.onPress))};
			var __r2 = [];
			__r2.push(coconut_vdom__$Child_Child_$Impl_$.ofText("Button"));
			__r1.push(coconut_vdom__$Child_Child_$Impl_$.element("div",__ret,__r2));
		} else {
			__r1.push(coconut_vdom__$Child_Child_$Impl_$.ofText("No Button"));
		}
		__r.push(coconut_vdom__$Child_Child_$Impl_$.element("div",{ },__r1));
		return __r[0];
	}
	,__initAttributes: function(attributes) {
		var this1 = attributes.onPress;
		this.__slots.onPress.setData(this1 == null ? this.__tink_defaults0.onPress : this1);
	}
});

Note that this.onPress will never be null because it is referencing the instance method. Also, the app will crash when trying to invoke onPress, because get_value() of the slot will give null.
Looks like a serious regression.

Passing states into lifecycle functions

For example:

class MyView extends View<{data:Data}> {
  override function afterInit(e) {
    // allow accessing `data` here
  }
}

Currently I store data into a class member during render, which doesn't feel too good.

Support @:loaded properties.

Since @:computed is supported, it'd make sense. Also one shouldn't have to create a model just to use this feature.

VSHaxe code completion issue

I found a bug, but i don't know it's bug of VSHaxe or bug of coconut.ui (tink_*, etc).
It appears only when i use latest coconut.ui from git and latest tink libs from git.

Source code:

import js.Browser.*;

class Main {
	public static function main() {
		coconut.ui.Renderer.mount(document.body, new App({}));
	}
}

class App extends coconut.ui.View {
	var name:String;

	function render() {
		return hxx('<div>GOOD</div>');
	}
}

When i hover on any item in class that extends coconut.ui.View, it shows "@:optional ..."
screen2

build.hxml
-cp src
-main Main
-lib coconut.ui
-lib coconut.vdom
-js out/main.js

Haxe Compiler 4.0.0-preview.5+da718a30e
Windows 7 x64

`@:computed` depending on `@:ref` stops working when ref changes

@:ref var something:Something; 
@:computed var boink:Boink = something.boink; //stops updating when `something` changes
function render() '<Something ref=${something} />';

Workaround:

@:state var something:Something = null;
@:computed var boink:Boink = something.boink; 
function render() '<Something ref=${v -> something = v} />';

Weird stackoverflow

using tink.CoreApi;

class Main extends coconut.ui.View {
    @:attr var item:ItemData;
    function render() '
        <div>
            <div>
                <div>
                    <div>
                        <switch ${item.data}>
                            <case ${Loading}>
                            <case ${Done(data)}>
                                <div>
                                    <div>
                                        <div>
                                            <div>
                                                <a>${data.user}</a>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            <case ${Failed(e)}>
                        </switch>
                    </div>
                </div>
            </div>
        </div>
    ';
    public static function main() {}
}

typedef ItemResponse = {
    final user:SimpleUserResponse;
}

typedef SimpleUserResponse = {
    final id:String;
    final name:String;
}

class ItemData implements coconut.data.Model {
    @:loaded var data:ItemResponse = null;
}

Somehow this requires a somewhat deep html hierarchy to reproduce.
(try removing one div wrapper and it will behave correctly)

var attributes:vdom.Attr looks like memory leaking

Based on a few hours of playing around I think var attributes:vdom.Arr causes memory leaking.
I could not figure out so far which porperty causes the leaking, or maybe the full object is leaking just it's visible because vdom.Attr is a huge object.

View generic parameters should be accessible from everywhere

Right now the only render function can access the generic parameters in view classes.
For example in lifecycle events they can be essential to be able to access them and make computations, etc.

Also when delegate behavior from hxx to views it's not so convenient sometimes to pass all the parameters and it would be simpler to rely on class properties. I know this approach is not functional, but it should be the developer's choice which way he goes

[gen4] ref.current is empty in case of custom compoent

When I try to define a ref for a custom component, it's current property is always empty.

package;

import coconut.ui.View;

class HelloView extends View
{
    @:attr var model:HelloModel;
    @:ref var sub:js.html.Element;

    function render()
    {
        return @hxx '<HelloSubView ref=${sub} />';
   }

    override function viewDidMount()
    {
        js.Browser.console.log("HelloView afterMounting", sub.current); //it's always null
    }

    override function viewDidUpdate()
    {
        js.Browser.console.log("HelloView afterPatching", sub.current); //it's always null
	}
}

https://github.com/grosmar/coconut-playground/tree/gen4-lifecycle-bug

DCE doesn't eliminate unused attributes

Looks like now all my application sizes grow extremely since latest version of coconut.
I looked into the generated js and it looks like if I have attributes that I never use DCE doesn't remove them anymore.

And because I still use var attributes:Attr a lot, it generates a lot of code.

Docs needed

I will try to consolidate some topics that I think requires documentation/explanations. Some may belong to tink_hxx or specific renderer, but I am not sure:

  • rendering-function vs full View class: performance, caching, allows state, etc
  • attribute-declared-as-children syntax: <Parent><attr1 props><Child {...props}/></attr1></Parent>
  • attribute name mangling: e.g. class -> className
  • typing function attributes: <div onclick={attr = value}/> <- this works somehow, but the haxe expr is not a function at all
  • observable vs plain value: e.g. function render() '<div attr={value}/>', what is the difference if value is Observable vs a plain value?
  • view caching: how it works?

Feel free to add to the list.

Root level switch case

Is it possible to make this work?

import coconut.data.*;
import coconut.ui.*;
import coconut.Ui.*;

class Main {
    static function main() {
        var h = hxx('<MyView />');
        var e = h.toElement();
        trace(h);
        trace(e); // null
        js.Browser.document.body.appendChild(e);
    }
}

class MyView extends View<{}> {
    function render() '
        <switch ${int()}>
            <case ${0}>
                <div>Zero</div>
            <case ${1}>
                <div>One</div>
            <case ${_}>
                <div>Default</div>
        </switch>
    ';
    
    function int() return 1;
}

Multiple backends

Me: I was wondering, is it possible to have multiple renderers in the same build. eg. lets say I want half of the app coconut.vdom and the other half coconut.pixi or something?
You: No

...

Me: you mean not at all, I mean also not when there are separate roots?
You: the problem is that currently, there are types such as RenderResult which tend to be quite useful, but if you want to have multiple backends, that won't fly
You: for me it's not that hard, but presenting a nice api to the user will be tricky ^^
you'll have to write extends View<js.html.Node> and extends View<pixijs.Sprite> and what not
Me: ๐Ÿ’ก yeah or extends coconut.vdom.View and extends coconut.pixi.View. but I understand this is tricky and opens box of lesser nice api
You: ๐Ÿ’ก actually, that's pretty cool
You: can you please dump that in a ticker for me?

There you go! ๐Ÿš€

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.