2 | import Control.Monad.Either.Extra
11 | import Web.MVC.Canvas
13 | import Web.MVC.Event
18 | %foreign "browser:lambda:(e,f,w) => {const o = new ResizeObserver((es) => f(e.getBoundingClientRect())(w));o.observe(e)}"
19 | prim__observeResize : Element -> (DOMRect -> PrimIO ()) -> PrimIO ()
33 | -> (preventDefault, stopPropagation : Bool)
37 | registerDOMEvent h prev stop el de = case de of
38 | Input f => inst "input" changeInfo f
39 | Change f => inst "change" changeInfo f
40 | Click f => inst "click" mouseInfo f
41 | DblClick f => inst "dblclick" mouseInfo f
42 | KeyDown f => inst "keydown" keyInfo f
43 | KeyUp f => inst "keyup" keyInfo f
44 | Blur v => inst "blur" {t = Event} (const $
pure v) Just
45 | Focus v => inst "focus" {t = Event} (const $
pure v) Just
46 | MouseDown f => inst "mousedown" mouseInfo f
47 | MouseUp f => inst "mouseup" mouseInfo f
48 | MouseEnter f => inst "mouseenter" mouseInfo f
49 | MouseLeave f => inst "mouseleave" mouseInfo f
50 | MouseOver f => inst "mouseover" mouseInfo f
51 | MouseOut f => inst "mouseout" mouseInfo f
52 | MouseMove f => inst "mousemove" mouseInfo f
53 | HashChange v => inst "hashchange" {t = Event} (const $
pure v) Just
54 | Scroll f => inst "scroll" scrollInfo f
55 | Wheel f => inst "wheel" wheelInfo f
56 | Resize f => onresize f
61 | -> {auto c : SafeCast t}
66 | inst {t} s conv f = do
67 | c <- callback {cb = EventListener} $
\e => do
68 | canc <- cancelable e
70 | when (canc && prev) (preventDefault e)
71 | when (bubl && stop) (stopPropagation e)
72 | va <- tryCast_ t "Web.MVC.View.inst" e
73 | conv va >>= maybe (pure ()) h . f
75 | addEventListener el s (Just c)
77 | onresize : (Rect -> Maybe e) -> JSIO ()
79 | va <- tryCast_ Element "Web.MVC.View.onresize" el
80 | primIO $
prim__observeResize va $
\r => toPrim $
runJS $
do
82 | maybe (pure ()) h (f rect)
85 | setAttribute : (e -> JSIO ()) -> Element -> Attribute t e -> JSIO ()
86 | setAttribute h el (Id (Id value)) = setAttribute el "id" value
87 | setAttribute h el (Str name value) = setAttribute el name value
88 | setAttribute h el (Bool name value) = case value of
89 | True => setAttribute el name ""
90 | False => removeAttribute el name
91 | setAttribute h el (Event_ prev stop ev) = registerDOMEvent h prev stop(up el) ev
92 | setAttribute h el Empty = pure ()
100 | {auto 0 _ : JSType t}
101 | -> {auto 0 _ : Elem ParentNode (Types t)}
102 | -> (h : e -> JSIO ())
103 | -> (doc : Document)
105 | -> (nodes : List (Node e))
109 | {auto 0 _ : JSType t}
110 | -> {auto 0 _ : Elem ParentNode (Types t)}
111 | -> (h : e -> JSIO ())
112 | -> (doc : Document)
116 | addNode h doc p (El {tag} _ xs ys) = do
117 | n <- createElement doc tag
118 | append p [inject $
n :> Node]
119 | addNodes h doc n ys
120 | traverseList_ (setAttribute h n) xs
122 | addNode h doc p (Raw str) = do
123 | el <- createElement doc "template"
124 | Just temp <- pure (castTo HTMLTemplateElement el) | Nothing => pure ()
125 | innerHTML temp .= str
127 | append p [inject $
c :> Node]
129 | addNode h doc p (Text str) = append p [inject str]
131 | addNode h doc p Empty = pure ()
133 | addNodes h doc p = assert_total $
traverseList_ (addNode h doc p)
136 | (Element -> DocumentFragment -> JSIO ())
140 | setupNodes adj r ns = C $
\h => do
142 | elem <- castElementByRef {t = Element} r
143 | df <- createDocumentFragment doc
144 | addNodes h doc df ns
149 | (Element -> DocumentFragment -> JSIO ())
153 | setupNode adj r n = setupNodes adj r [n]
158 | children : Ref t -> List (Node e) -> Cmd e
159 | children = setupNodes replaceChildren
164 | child : Ref t -> Node e -> Cmd e
165 | child = setupNode replaceChildren
170 | text : Ref t -> String -> Cmd e
171 | text r = child r . Text
176 | show : Show b => Ref t -> b -> Cmd e
177 | show r = text r . show
182 | raw : Ref t -> String -> Cmd e
183 | raw r = child r . Raw
187 | style : Ref Tag.Style -> List (Rule 1) -> Cmd e
189 | let str := fastUnlines $
map interpolate rules
195 | afterMany : Ref t -> List (Node e) -> Cmd e
196 | afterMany = setupNodes afterDF
201 | after : Ref t -> Node e -> Cmd e
202 | after = setupNode afterDF
207 | beforeMany : Ref t -> List (Node e) -> Cmd e
208 | beforeMany = setupNodes beforeDF
213 | before : Ref t -> Node e -> Cmd e
214 | before = setupNode beforeDF
219 | appendMany : Ref t -> List (Node e) -> Cmd e
220 | appendMany = setupNodes appendDF
225 | append : Ref t -> Node e -> Cmd e
226 | append = setupNode appendDF
231 | prependMany : Ref t -> List (Node e) -> Cmd e
232 | prependMany = setupNodes prependDF
237 | prepend : Ref t -> Node e -> Cmd e
238 | prepend = setupNode prependDF
243 | replaceMany : Ref t -> List (Node e) -> Cmd e
244 | replaceMany = setupNodes replaceDF
249 | replace : Ref t -> Node e -> Cmd e
250 | replace = setupNode replaceDF
254 | validityMsg : Ref t -> ValidityTag t => String -> Cmd e
255 | validityMsg r s = cmd_ $
setValidityMessage r s
259 | validate : Ref t -> ValidityTag t => Either String b -> Cmd e
260 | validate r (Left s) = validityMsg r s
261 | validate r (Right s) = validityMsg r ""
265 | attr : Ref t -> Attribute t e -> Cmd e
266 | attr r a = C $
\h => castElementByRef r >>= \el => setAttribute h el a
270 | checked : Ref Tag.Input -> Bool -> Cmd e
271 | checked r b = C $
\h => castElementByRef r >>= (HTMLInputElement.checked =. b)
275 | disabled : Ref t -> Bool -> Cmd e
276 | disabled r = attr r . disabled
284 | disabledE : {0 a,b : _} -> Ref t -> Either a b -> Cmd e
285 | disabledE r = disabled r . isLeft
293 | disabledM : {0 a : _} -> Ref t -> Maybe a -> Cmd e
294 | disabledM r = disabled r . isNothing
298 | remove : Ref t -> Cmd e
299 | remove r = cmd_ (castElementByRef {t = Element} r >>= remove)
303 | value : Ref t -> ValueTag t => String -> Cmd e
304 | value r s = cmd_ (setValue r s)
308 | renderWithMetrics : Ref Tag.Canvas -> (TextMeasure => CanvasDims -> Scene) -> Cmd e
309 | renderWithMetrics r s = cmd_ (renderWithMetrics r s)
313 | renderWithDims : Ref Tag.Canvas -> (CanvasDims -> Scene) -> Cmd e
314 | renderWithDims r s = cmd_ (render r s)
318 | render : Ref Tag.Canvas -> Scene -> Cmd e
319 | render r = renderWithDims r . const
323 | setCanvasDims : Ref Tag.Canvas -> CanvasDims -> Cmd e
324 | setCanvasDims r d =
326 | c <- castElementByRef {t = HTMLCanvasElement} r
327 | set (height c) (cast d.cheight)
328 | set (width c) (cast d.cwidth)
333 | focus : Ref t -> Cmd e
334 | focus r = cmd_ (castElementByRef {t = HTMLElement} r >>= HTMLOrSVGElement.focus)
338 | blur : Ref t -> Cmd e
339 | blur r = cmd_ (castElementByRef {t = HTMLElement} r >>= HTMLOrSVGElement.blur)
344 | withMetricsFor : Ref Tag.Canvas -> (TextMeasure => Cmd e) -> Cmd e
345 | withMetricsFor ref c =
347 | canvas <- castElementByRef {t = HTMLCanvasElement} ref
348 | ctxt <- context2D canvas
349 | run (withMetrics ctxt c) h