0 | module Rhone.JS.Reactimate
2 | import Control.Monad.Either.Extra
7 | import Rhone.JS.ElemRef
8 | import Rhone.JS.Event
22 | registerDOMEvent : Handler JSIO e => EventTarget -> DOMEvent e -> JSIO ()
23 | registerDOMEvent el de = case de of
24 | Input f => inst "input" inputInfo f
25 | Change f => inst "change" changeInfo f
26 | Click f => inst "click" mouseInfo f
27 | DblClick f => inst "dblclick" mouseInfo f
28 | KeyDown f => inst "keydown" keyInfo f
29 | KeyUp f => inst "keyup" keyInfo f
30 | Blur v => inst "blur" {a = Event} (const $
pure v) Just
31 | Focus v => inst "focus" {a = Event} (const $
pure v) Just
32 | MouseDown f => inst "mousedown" mouseInfo f
33 | MouseUp f => inst "mouseup" mouseInfo f
34 | MouseEnter f => inst "mouseenter" mouseInfo f
35 | MouseLeave f => inst "mouseleave" mouseInfo f
36 | MouseOver f => inst "mouseover" mouseInfo f
37 | MouseOut f => inst "mouseout" mouseInfo f
38 | MouseMove f => inst "mousemove" mouseInfo f
39 | HashChange v => inst "hashchange" {a = Event} (const $
pure v) Just
40 | Wheel f => inst "wheel" wheelInfo f
45 | -> {auto c : SafeCast a}
51 | c <- callback {cb = EventListener} $
\e => do
52 | va <- tryCast_ a "Control.Monad.Dom.Interface.inst" e
53 | conv va >>= maybe (pure ()) handle . f
55 | addEventListener el s (Just c)
57 | parameters {0 e : Type}
58 | {auto h : Handler JSIO e}
62 | handleEvent : ElemRef t -> DOMEvent e -> JSIO ()
63 | handleEvent ref de = do
64 | el <- castElementByRef ref
65 | registerDOMEvent el de
68 | setAttribute : Element -> Attribute e -> JSIO ()
69 | setAttribute el (Id value) = setAttribute el "id" value
70 | setAttribute el (Str name value) = setAttribute el name value
71 | setAttribute el (Bool name value) = case value of
72 | True => setAttribute el name ""
73 | False => removeAttribute el name
74 | setAttribute el (Event ev) = registerDOMEvent (up el) ev
75 | setAttribute el Empty = pure ()
78 | setAttributeRef : ElemRef t -> Attribute e -> JSIO ()
79 | setAttributeRef ref a = do
80 | el <- castElementByRef {t2 = Element} ref
84 | setAttributesRef : ElemRef t -> List (Attribute e) -> JSIO ()
85 | setAttributesRef el = traverseList_ (setAttributeRef el)
91 | nodeList : DocumentFragment -> List (HSum [Node,String])
92 | nodeList df = [inject $
df :> Node]
96 | replaceChildren : Element -> DocumentFragment -> JSIO ()
97 | replaceChildren elem = replaceChildren elem . nodeList
101 | appendDF : Element -> DocumentFragment -> JSIO ()
102 | appendDF elem = append elem . nodeList
106 | prependDF : Element -> DocumentFragment -> JSIO ()
107 | prependDF elem = prepend elem . nodeList
111 | afterDF : Element -> DocumentFragment -> JSIO ()
112 | afterDF elem = after elem . nodeList
116 | beforeDF : Element -> DocumentFragment -> JSIO ()
117 | beforeDF elem = before elem . nodeList
121 | replaceDF : Element -> DocumentFragment -> JSIO ()
122 | replaceDF elem = replaceWith elem . nodeList
125 | data DOMUpdate : Type -> Type where
126 | Children : ElemRef t -> (ns : List (Node e)) -> DOMUpdate e
127 | Replace : ElemRef t -> (ns : List (Node e)) -> DOMUpdate e
128 | Append : ElemRef t -> (ns : List (Node e)) -> DOMUpdate e
129 | Prepend : ElemRef t -> (ns : List (Node e)) -> DOMUpdate e
130 | After : ElemRef t -> (ns : List (Node e)) -> DOMUpdate e
131 | Before : ElemRef t -> (ns : List (Node e)) -> DOMUpdate e
132 | Attr : ElemRef t -> Attribute e -> DOMUpdate e
133 | Remove : ElemRef t -> DOMUpdate e
139 | parameters {0 e : Type}
140 | {auto h : Handler JSIO e}
142 | createNode : Document -> String -> List (Attribute e) -> JSIO Element
143 | createNode doc str xs = do
144 | el <- createElement doc str
145 | traverseList_ (setAttribute el) xs
149 | {auto 0 _ : JSType t}
150 | -> {auto 0 _ : Elem ParentNode (Types t)}
151 | -> (doc : Document)
153 | -> (nodes : List (Node e))
157 | {auto 0 _ : JSType t}
158 | -> {auto 0 _ : Elem ParentNode (Types t)}
159 | -> (doc : Document)
163 | addNode doc p (El tag xs ys) = do
164 | n <- createNode doc tag xs
165 | append p [inject $
n :> Node]
167 | addNode doc p (Raw str) = do
168 | el <- createElement doc "template"
169 | Just temp <- pure (castTo HTMLTemplateElement el) | Nothing => pure ()
170 | innerHTML temp .= str
172 | append p [inject $
c :> Node]
174 | addNode doc p (Text str) = append p [inject str]
176 | addNode doc p Empty = pure ()
178 | addNodes doc p = assert_total $
traverseList_ (addNode doc p)
181 | (Element -> DocumentFragment -> JSIO ())
185 | setupNodes adj ref ns = do
187 | elem <- castElementByRef {t2 = Element} ref
188 | df <- createDocumentFragment doc
194 | (Element -> DocumentFragment -> JSIO ())
198 | setupNode adj ref n = setupNodes adj ref [n]
203 | innerHtmlAtN : ElemRef t -> List (Node e) -> JSIO ()
204 | innerHtmlAtN = setupNodes replaceChildren
209 | innerHtmlAt : ElemRef t -> Node e -> JSIO ()
210 | innerHtmlAt = setupNode replaceChildren
215 | afterN : ElemRef t -> List (Node e) -> JSIO ()
216 | afterN = setupNodes afterDF
221 | after : ElemRef t -> Node e -> JSIO ()
222 | after = setupNode afterDF
227 | beforeN : ElemRef t -> List (Node e) -> JSIO ()
228 | beforeN = setupNodes beforeDF
233 | before : ElemRef t -> Node e -> JSIO ()
234 | before = setupNode beforeDF
239 | appendN : ElemRef t -> List (Node e) -> JSIO ()
240 | appendN = setupNodes appendDF
245 | append : ElemRef t -> Node e -> JSIO ()
246 | append = setupNode appendDF
251 | prependN : ElemRef t -> List (Node e) -> JSIO ()
252 | prependN = setupNodes prependDF
257 | prepend : ElemRef t -> Node e -> JSIO ()
258 | prepend = setupNode prependDF
263 | replaceN : ElemRef t -> List (Node e) -> JSIO ()
264 | replaceN = setupNodes replaceDF
269 | replace : ElemRef t -> Node e -> JSIO ()
270 | replace = setupNode replaceDF
274 | updateDOM1 : DOMUpdate e -> JSIO ()
275 | updateDOM1 (Children x ns) = innerHtmlAtN x ns
276 | updateDOM1 (Replace x ns) = replaceN x ns
277 | updateDOM1 (Append x ns) = appendN x ns
278 | updateDOM1 (Prepend x ns) = prependN x ns
279 | updateDOM1 (After x ns) = afterN x ns
280 | updateDOM1 (Before x ns) = beforeN x ns
281 | updateDOM1 (Attr x a) = setAttributeRef x a
282 | updateDOM1 (Remove x) = castElementByRef {t2 = Element} x >>= remove
286 | updateDOM : List (DOMUpdate e) -> JSIO ()
287 | updateDOM = traverseList_ updateDOM1