0 | module Web.Async.List
2 | import Data.Linear.Traverse1
3 | import Data.Linear.Unique
5 | import Derive.Prelude
6 | import Text.HTML.DomID
7 | import Web.Async.Form
10 | %language ElabReflection
17 | data ListEv = Prepend | Append
19 | %runElab derive "ListEv" [Show,Eq,Ord]
26 | ST t = List (Token World, EditRes t)
28 | missing : ST t -> EditRes (List t)
29 | missing [] = Missing
32 | Invalid err => Invalid err
35 | travres : SnocList t -> ST t -> EditRes (List t)
36 | travres sx [] = Valid $
sx <>> []
37 | travres sx (x :: xs) =
39 | Missing => missing xs
40 | Invalid err => Invalid err
41 | Valid val => travres (sx :< val) xs
43 | del : Token World -> ST t -> ST t
44 | del n = filter ((n /=) . fst)
46 | upd : Token World -> EditRes t -> ST t -> ST t
47 | upd tok res = map (\p => if fst p == tok then (tok,res) else p)
49 | new : Token World -> ListEv -> ST t -> ST t
50 | new tok Prepend xs = (tok,Missing)::xs
51 | new tok Append xs = xs ++ [(tok,Missing)]
57 | delete : Token World -> JSStream () -> Ref Void -> JSStream (ST t -> ST t)
58 | delete t us r = P.take 1 us |> P.evalMap (\_ => remove r $> del t)
60 | initial : Maybe (List t) -> IO1 (List (Token World, t))
61 | initial Nothing = ([] #)
63 | traverse1 (\v,t => let tok # t := token1 t in (tok,v) # t) ts
65 | parameters {default 0xffff_fffe limit : Nat}
66 | (parent : Act (Ref Void, HTMLNodes -> Widget ListEv))
67 | (row : HTMLNode -> Act (Ref Void, Widget ()))
70 | rw : Token World -> Maybe t -> Act (Widget $
ST t -> ST t)
72 | W n s <- ed.widget ini
73 | (rid, W n2 del) <- row n
74 | pure $
W n2 $
mergeHaltL (delete tok del rid) (P.mapOutput (upd tok) s)
76 | add : Ref Void -> ListEv -> Act (JSStream (ST t -> ST t))
79 | W n s <- rw tok Nothing
80 | if le == Append then append rpar n else prepend rpar n
81 | pure $
emit (new tok le) <+> s
90 | editList : Editor (List t)
93 | (ref, makeW) <- parent
94 | ini <- lift1 $
initial m
95 | rows <- traverseList (\(t,v) => rw t (Just v)) ini
96 | let W n listEvs := makeW (map node rows)
98 | (emits (map events rows) <+> evalMap (add ref) listEvs)
99 | |> parJoin (S limit)
100 | |> scanFrom1 (map2 Valid ini)
101 | |> P.mapOutput (travres [<])
105 | editList1 : Editor (List t) -> Editor (List1 t)
107 | refineEdit (Just . forget) $
\case
108 | x::xs => Valid $
x:::xs