added a new way for native DOM <-> virtual DOM interop, see nativenodes.nim example
This commit is contained in:
parent
a90efe752d
commit
18b5a12d1e
5 changed files with 36 additions and 30 deletions
|
|
@ -1 +1,2 @@
|
||||||
--path: "../karax"
|
--path: "../karax"
|
||||||
|
--path: ".."
|
||||||
|
|
|
||||||
18
experiments/nativenodes.nim
Normal file
18
experiments/nativenodes.nim
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
|
||||||
|
include karax / prelude
|
||||||
|
import karax / kdom
|
||||||
|
|
||||||
|
proc myInput: VNode =
|
||||||
|
result = buildHtml:
|
||||||
|
input()
|
||||||
|
|
||||||
|
var inp = vnodeToDom(myInput())
|
||||||
|
|
||||||
|
proc myAwesomeComponent(x: Node): VNode =
|
||||||
|
result = dthunk(x)
|
||||||
|
|
||||||
|
proc main: VNode =
|
||||||
|
result = myAwesomeComponent(inp)
|
||||||
|
|
||||||
|
setRenderer main
|
||||||
|
|
@ -8,18 +8,15 @@ import macros, vdom, tables, strutils, kbase
|
||||||
when defined(js):
|
when defined(js):
|
||||||
var
|
var
|
||||||
vcomponents* = newJDict[cstring, proc(args: seq[VNode]): VNode]()
|
vcomponents* = newJDict[cstring, proc(args: seq[VNode]): VNode]()
|
||||||
dcomponents* = newJDict[cstring, proc(args: seq[VNode]): Node]()
|
|
||||||
else:
|
else:
|
||||||
var
|
var
|
||||||
vcomponents* = newTable[kstring, proc(args: seq[VNode]): VNode]()
|
vcomponents* = newTable[kstring, proc(args: seq[VNode]): VNode]()
|
||||||
dcomponents* = newTable[kstring, proc(args: seq[VNode]): Node]()
|
|
||||||
|
|
||||||
type
|
type
|
||||||
ComponentKind* {.pure.} = enum
|
ComponentKind* {.pure.} = enum
|
||||||
None,
|
None,
|
||||||
Tag,
|
Tag,
|
||||||
VNode,
|
VNode
|
||||||
Node
|
|
||||||
|
|
||||||
var
|
var
|
||||||
allcomponents {.compileTime.} = initTable[string, ComponentKind]()
|
allcomponents {.compileTime.} = initTable[string, ComponentKind]()
|
||||||
|
|
@ -84,10 +81,8 @@ when defined(js):
|
||||||
var isvirtual = ComponentKind.None
|
var isvirtual = ComponentKind.None
|
||||||
if rettype == "VNode":
|
if rettype == "VNode":
|
||||||
isvirtual = ComponentKind.VNode
|
isvirtual = ComponentKind.VNode
|
||||||
elif rettype == "Node":
|
|
||||||
isvirtual = ComponentKind.Node
|
|
||||||
else:
|
else:
|
||||||
error "component must return VNode or Node", params[0]
|
error "component must return VNode", params[0]
|
||||||
let realName = if name.kind == nnkPostfix: name[1] else: name
|
let realName = if name.kind == nnkPostfix: name[1] else: name
|
||||||
let nn = $realName
|
let nn = $realName
|
||||||
n[0] = ident("inner" & nn)
|
n[0] = ident("inner" & nn)
|
||||||
|
|
@ -105,26 +100,15 @@ when defined(js):
|
||||||
proc pname(args: seq[VNode]): VNode =
|
proc pname(args: seq[VNode]): VNode =
|
||||||
unpackCall
|
unpackCall
|
||||||
|
|
||||||
template dwrapper(pname, unpackCall) {.dirty.} =
|
|
||||||
proc pname(args: seq[VNode]): Node =
|
|
||||||
unpackCall
|
|
||||||
|
|
||||||
template vregister(key, val) =
|
template vregister(key, val) =
|
||||||
bind jdict.`[]=`
|
bind jdict.`[]=`
|
||||||
`[]=`(vcomponents, kstring(key), val)
|
`[]=`(vcomponents, kstring(key), val)
|
||||||
|
|
||||||
template dregister(key, val) =
|
|
||||||
bind jdict.`[]=`
|
|
||||||
`[]=`(dcomponents, kstring(key), val)
|
|
||||||
|
|
||||||
result = newTree(nnkStmtList, n)
|
result = newTree(nnkStmtList, n)
|
||||||
|
|
||||||
if isvirtual == ComponentKind.VNode:
|
if isvirtual == ComponentKind.VNode:
|
||||||
result.add getAst(vwrapper(newname name, unpackCall))
|
result.add getAst(vwrapper(newname name, unpackCall))
|
||||||
result.add getAst(vregister(newLit(nn), realName))
|
result.add getAst(vregister(newLit(nn), realName))
|
||||||
else:
|
|
||||||
result.add getAst(dwrapper(newname name, unpackCall))
|
|
||||||
result.add getAst(dregister(newLit(nn), realName))
|
|
||||||
allcomponents[nn] = isvirtual
|
allcomponents[nn] = isvirtual
|
||||||
when defined(debugKaraxDsl):
|
when defined(debugKaraxDsl):
|
||||||
echo repr result
|
echo repr result
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ template attach(n: VNode) =
|
||||||
n.dom = result
|
n.dom = result
|
||||||
if n.id != nil: kxi.byId[n.id] = n
|
if n.id != nil: kxi.byId[n.id] = n
|
||||||
|
|
||||||
proc applyEvents(n: VNode; kxi: KaraxInstance) =
|
proc applyEvents(n: VNode) =
|
||||||
let dest = n.dom
|
let dest = n.dom
|
||||||
for i in 0..<len(n.events):
|
for i in 0..<len(n.events):
|
||||||
n.events[i][2] = wrapEvent(dest, n, n.events[i][0], n.events[i][1])
|
n.events[i][2] = wrapEvent(dest, n, n.events[i][0], n.events[i][1])
|
||||||
|
|
@ -134,7 +134,7 @@ proc getVNodeById*(id: cstring; kxi: KaraxInstance = kxi): VNode =
|
||||||
if kxi.byId.contains(id):
|
if kxi.byId.contains(id):
|
||||||
result = kxi.byId[id]
|
result = kxi.byId[id]
|
||||||
|
|
||||||
proc vnodeToDom*(n: VNode; kxi: KaraxInstance): Node =
|
proc vnodeToDom*(n: VNode; kxi: KaraxInstance = nil): Node =
|
||||||
if n.kind == VNodeKind.text:
|
if n.kind == VNodeKind.text:
|
||||||
result = document.createTextNode(n.text)
|
result = document.createTextNode(n.text)
|
||||||
attach n
|
attach n
|
||||||
|
|
@ -150,7 +150,8 @@ proc vnodeToDom*(n: VNode; kxi: KaraxInstance): Node =
|
||||||
attach n
|
attach n
|
||||||
return result
|
return result
|
||||||
elif n.kind == VNodeKind.dthunk:
|
elif n.kind == VNodeKind.dthunk:
|
||||||
result = callThunk(dcomponents[n.text], n)
|
result = n.dom #callThunk(dcomponents[n.text], n)
|
||||||
|
assert result != nil
|
||||||
#n.key = result.key
|
#n.key = result.key
|
||||||
attach n
|
attach n
|
||||||
return result
|
return result
|
||||||
|
|
@ -182,8 +183,8 @@ proc vnodeToDom*(n: VNode; kxi: KaraxInstance): Node =
|
||||||
for k, v in attrs(n):
|
for k, v in attrs(n):
|
||||||
if v != nil:
|
if v != nil:
|
||||||
result.setAttr(k, v)
|
result.setAttr(k, v)
|
||||||
applyEvents(n, kxi)
|
applyEvents(n)
|
||||||
if n == kxi.toFocusV and kxi.toFocus.isNil:
|
if kxi != nil and n == kxi.toFocusV and kxi.toFocus.isNil:
|
||||||
kxi.toFocus = result
|
kxi.toFocus = result
|
||||||
if not n.style.isNil: applyStyle(result, n.style)
|
if not n.style.isNil: applyStyle(result, n.style)
|
||||||
|
|
||||||
|
|
@ -194,7 +195,7 @@ proc same(n: VNode, e: Node; nesting = 0): bool =
|
||||||
elif n.kind == VNodeKind.verbatim:
|
elif n.kind == VNodeKind.verbatim:
|
||||||
result = true
|
result = true
|
||||||
elif n.kind == VNodeKind.vthunk or n.kind == VNodeKind.dthunk:
|
elif n.kind == VNodeKind.vthunk or n.kind == VNodeKind.dthunk:
|
||||||
# we don't check these for now:
|
# we don't check these:
|
||||||
result = true
|
result = true
|
||||||
elif toTag[n.kind] == e.nodename:
|
elif toTag[n.kind] == e.nodename:
|
||||||
result = true
|
result = true
|
||||||
|
|
@ -245,11 +246,13 @@ proc eq(a, b: VNode): EqResult =
|
||||||
if a.text != b.text:
|
if a.text != b.text:
|
||||||
when defined(profileKarax): inc reasons[deText]
|
when defined(profileKarax): inc reasons[deText]
|
||||||
return different # similar
|
return different # similar
|
||||||
elif a.kind == VNodeKind.vthunk or a.kind == VNodeKind.dthunk:
|
elif a.kind == VNodeKind.vthunk:
|
||||||
if a.text != b.text: return different
|
if a.text != b.text: return different
|
||||||
if a.len != b.len: return different
|
if a.len != b.len: return different
|
||||||
for i in 0..<a.len:
|
for i in 0..<a.len:
|
||||||
if eq(a[i], b[i]) == different: return different
|
if eq(a[i], b[i]) == different: return different
|
||||||
|
elif a.kind == VNodeKind.dthunk:
|
||||||
|
return identical
|
||||||
elif a.kind == VNodeKind.verbatim:
|
elif a.kind == VNodeKind.verbatim:
|
||||||
if a.text != b.text:
|
if a.text != b.text:
|
||||||
return different
|
return different
|
||||||
|
|
@ -302,7 +305,7 @@ proc mergeEvents(newNode, oldNode: VNode; kxi: KaraxInstance) =
|
||||||
else: toEventName[k]
|
else: toEventName[k]
|
||||||
d.removeEventListener(name, oldNode.events[i][2])
|
d.removeEventListener(name, oldNode.events[i][2])
|
||||||
shallowCopy(oldNode.events, newNode.events)
|
shallowCopy(oldNode.events, newNode.events)
|
||||||
applyEvents(oldNode, kxi)
|
applyEvents(oldNode)
|
||||||
|
|
||||||
when false:
|
when false:
|
||||||
proc printV(n: VNode; depth: cstring = "") =
|
proc printV(n: VNode; depth: cstring = "") =
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ type
|
||||||
script, noscript,
|
script, noscript,
|
||||||
body, section, nav, article, aside,
|
body, section, nav, article, aside,
|
||||||
h1, h2, h3, h4, h5, h6,
|
h1, h2, h3, h4, h5, h6,
|
||||||
header, footer, address, main
|
header, footer, address, main,
|
||||||
|
|
||||||
p, hr, pre, blockquote, ol, ul, li,
|
p, hr, pre, blockquote, ol, ul, li,
|
||||||
dl, dt, dd,
|
dl, dt, dd,
|
||||||
|
|
@ -167,8 +167,8 @@ template callThunk*(fn: typed; n: VNode): untyped =
|
||||||
proc vthunk*(name: kstring; args: varargs[VNode, vn]): VNode =
|
proc vthunk*(name: kstring; args: varargs[VNode, vn]): VNode =
|
||||||
VNode(kind: VNodeKind.vthunk, text: name, index: -1, kids: @args)
|
VNode(kind: VNodeKind.vthunk, text: name, index: -1, kids: @args)
|
||||||
|
|
||||||
proc dthunk*(name: kstring; args: varargs[VNode, vn]): VNode =
|
proc dthunk*(dom: Node): VNode =
|
||||||
VNode(kind: VNodeKind.dthunk, text: name, index: -1, kids: @args)
|
VNode(kind: VNodeKind.dthunk, dom: dom)
|
||||||
|
|
||||||
proc setEventIfNoConflict(v: VNode; kind: EventKind; handler: EventHandler) =
|
proc setEventIfNoConflict(v: VNode; kind: EventKind; handler: EventHandler) =
|
||||||
assert handler != nil
|
assert handler != nil
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue