Skip to content

Instantly share code, notes, and snippets.

@dmitriid

dmitriid/vnode.re

Last active Jun 24, 2017
Embed
What would you like to do?
type any = Js.t {.};
type key =
| String string
| Int int;
type hero = {id: string};
type attach_data = Js.t {. placeholder : option any, real : option string}; /* TODO */
type vnode = {
sel: option string,
data: option vnode_data,
children: option (list vnode),
text: option string,
elm: option string,
key: option key
}
and vnode_data = {
props: option any,
attrs: option any,
classes: option (list any),
style: option (list any),
dataset: option any,
on: option any,
hero: option hero,
attach_data: option attach_data,
hook: hooks,
key: option key,
ns: option string,
fn: option (unit => vnode),
args: option (list any)
}
and hooks = {
pre: option pre_hook,
init: option init_hook,
create: option create_hook,
insert: option insert_hook,
prepatch: option prepatch_hook,
update: option update_hook,
postpatch: option postpatch_hook,
destroy: option destroy_hook,
remove: option remove_hook,
post: option post_hook
}
and pre_hook = unit => any
and init_hook = vnode => any
and create_hook = vnode => vnode => any
and insert_hook = vnode => any
and prepatch_hook = vnode => vnode => any
and update_hook = vnode => vnode => any
and postpatch_hook = vnode => vnode => any
and destroy_hook = vnode => any
and remove_hook = vnode => (unit => unit) => any
and post_hook = unit => any;
type vnode_queue = list vnode;
/*module type VNode = {
let vnode:
option string =>
option vnode_data =>
option (list vnode) =>
option string =>
option string =>
vnode;
};
module VNode: VNode = {
let vnode sel (data: option vnode_data) children text elm => {
let key =
switch data {
| None => None
| Some data => data.key
};
{sel, data, children, text, elm, key}
};
};
*/
open ReasonJs.Dom;
let map f =>
fun
| Some v => Some (f v)
| None => None;
let andThen (f: 'a => option 'b) =>
fun
| Some v => f v
| None => None;
let unwrapUnsafely =
fun
| Some v => v
| None => raise (Invalid_argument "Passed `None` to unwrapUnsafely");
module Snabbdom = {
let vnode
sel::(sel: option string)=?
data::(data: option vnode_data)=?
children::(children: option (list vnode))=?
text::(text: option string)=?
elm::(elm: option string)=?
() => {
sel,
data,
children,
text,
elm,
key: None
};
let rec create_elm vnode :option Dom.element =>
switch vnode.sel {
| None => None
| Some sel =>
Some (document |> Document.createElement sel |> createTextNode vnode |> createChildren vnode)
}
and createTextNode vnode (elm: ReasonJs.Dom.Element.t) =>
switch vnode.text {
| None => elm
| Some text =>
Element.setInnerText elm text;
elm
}
and createChildren vnode (elm: ReasonJs.Dom.Element.t) =>
switch vnode.children {
| None => elm
| Some children =>
let append child => elm |> Element.appendChild (create_elm child |> unwrapUnsafely);
List.iter append children;
elm
};
};
let flushToDOM v => {
let elm = Snabbdom.create_elm v;
let unwrapped = elm |> unwrapUnsafely;
document |> Document.asHtmlDocument |> andThen HtmlDocument.body |>
map (Element.appendChild unwrapped)
};
flushToDOM (Snabbdom.vnode sel::"div" text::"woot" ());
flushToDOM (Snabbdom.vnode sel::"div" text::"woot1" ());
flushToDOM (Snabbdom.vnode sel::"div" text::"woot2" ());
flushToDOM (Snabbdom.vnode sel::"div" text::"woot3" ());
flushToDOM (Snabbdom.vnode sel::"div" text::"woot4" ());
let z = Snabbdom.vnode sel::"div" text::"z" ();
flushToDOM (Snabbdom.vnode sel::"div" text::"woot5" children::[z, z, z] ());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment