Skip to content

Commit ac97eeb

Browse files
chekoopaMikhail Chekan
andauthored
VNode hooks implementation (#24)
* vnode hooks implementation * vnode hooks: consistency edits 8 spaces indent EffectFn usage qualified import in Renderer module * vnode hooks: overengineering elimination Co-authored-by: Mikhail Chekan <[email protected]>
1 parent 68071ec commit ac97eeb

File tree

3 files changed

+65
-6
lines changed

3 files changed

+65
-6
lines changed

src/Flame/Renderer/Hook.purs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
-- | Snabbdom VNode hooks
2+
module Flame.Renderer.Hook where
3+
4+
import Prelude ((<<<), Unit)
5+
import Effect (Effect)
6+
import Effect.Uncurried (EffectFn1, EffectFn2)
7+
import Foreign (Foreign)
8+
import Foreign as F
9+
import Flame.Types (NodeData(Hook), VNode)
10+
11+
-- | Foreign VNode hook function with single parameter
12+
type HookFn1 = EffectFn1 VNode Unit
13+
14+
-- | Foreign VNode hook function with two parameters
15+
type HookFn2 = EffectFn2 VNode VNode Unit
16+
17+
-- | Foreign VNode hook function with VNode and remove callback parameters
18+
type HookFnRemove = EffectFn2 VNode (Effect Unit) Unit
19+
20+
-- | Creates a hook for given `name` and provided foreign function
21+
createHook :: msg. String -> Foreign -> NodeData msg
22+
createHook name = Hook name
23+
24+
-- | Attaches a hook for a vnode been added
25+
atInit :: msg. HookFn1 -> NodeData msg
26+
atInit = createHook "init" <<< F.unsafeToForeign
27+
28+
-- | Attaches a hook for a DOM element been created based on a vnode
29+
atCreate :: msg. HookFn2 -> NodeData msg
30+
atCreate = createHook "create" <<< F.unsafeToForeign
31+
32+
-- | Attaches a hook for a vnode element been inserted into the DOM
33+
atInsert :: msg. HookFn1 -> NodeData msg
34+
atInsert = createHook "insert" <<< F.unsafeToForeign
35+
36+
-- | Attaches a hook for a vnode element about to be patched
37+
atPrepatch :: msg. HookFn2 -> NodeData msg
38+
atPrepatch = createHook "prepatch" <<< F.unsafeToForeign
39+
40+
-- | Attaches a hook for a vnode element being updated
41+
atUpdate :: msg. HookFn2 -> NodeData msg
42+
atUpdate = createHook "update" <<< F.unsafeToForeign
43+
44+
-- | Attaches a hook for a vnode element been patched
45+
atPostpatch :: msg. HookFn2 -> NodeData msg
46+
atPostpatch = createHook "postpatch" <<< F.unsafeToForeign
47+
48+
-- | Attaches a hook for a vnode element directly or indirectly being removed
49+
atDestroy :: msg. HookFn1 -> NodeData msg
50+
atDestroy = createHook "destroy" <<< F.unsafeToForeign
51+
52+
-- | Attaches a hook for a vnode element directly being removed
53+
atRemove :: msg. HookFnRemove -> NodeData msg
54+
atRemove = createHook "remove" <<< F.unsafeToForeign

src/Flame/Renderer/Renderer.purs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,21 +96,23 @@ render oldVNode updater element = do
9696
toVNode :: forall message. (message -> Effect Unit) -> Html message -> VNode
9797
toVNode updater (Text value) = text value
9898
toVNode updater (Node tag nodeData children) = h tag vNodeData $ map (toVNode updater) children
99-
where toVNodeData { properties, attributes, events } = {
99+
where toVNodeData { properties, attributes, events, hooks } = {
100100
attrs: attributes,
101101
props: properties,
102-
on: toVNodeEvents events
102+
on: toVNodeEvents events,
103+
hook: hooks
103104
}
104105

105106
handleRawEvent handler event = do
106107
message <- handler event
107108
updater message
108109

109-
unions record@{ properties, attributes, events } =
110+
unions record@{ properties, attributes, events, hooks } =
110111
case _ of
111112
Property name value -> record { properties = FO.insert name value properties }
112113
Attribute name value -> record { attributes = FO.insert name value attributes }
113114
Event name message -> record { events = FO.insert name (const (updater message)) events }
114115
RawEvent name handler -> record { events = FO.insert name (handleRawEvent handler) events }
116+
Hook name fn -> record { hooks = FO.insert name fn hooks }
115117

116-
vNodeData = toVNodeData $ DF.foldl unions { properties: FO.empty, attributes: FO.empty, events: FO.empty } nodeData
118+
vNodeData = toVNodeData $ DF.foldl unions { properties: FO.empty, attributes: FO.empty, events: FO.empty, hooks: FO.empty } nodeData

src/Flame/Types.purs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Data.Array as DA
77
import Data.Foldable as DF
88
import Data.Tuple (Tuple(..))
99
import Effect (Effect)
10+
import Foreign (Foreign)
1011
import Foreign.Object (Object)
1112
import Web.DOM.Element as WDE
1213
import Web.Event.Event (Event)
@@ -20,7 +21,8 @@ type VNodeData = {
2021
-- we need attrs mainly for svg
2122
attrs :: Object String,
2223
props :: Object String,
23-
on :: VNodeEvents
24+
on :: VNodeEvents,
25+
hook :: Object Foreign
2426
}
2527

2628
-- | Virtual DOM representation
@@ -83,7 +85,8 @@ data NodeData message =
8385
Attribute String String |
8486
Property String String |
8587
Event String message |
86-
RawEvent String (Event -> Effect message)
88+
RawEvent String (Event -> Effect message) |
89+
Hook String Foreign
8790

8891
derive instance nodeDataFunctor :: Functor NodeData
8992

0 commit comments

Comments
 (0)