@@ -13,11 +13,13 @@ import Control.Monad.Free (Free, foldFree, liftF)
1313import Data.Array (length , (!!))
1414import Data.Maybe (Maybe (..), fromMaybe )
1515import Data.Time.Duration (Milliseconds (..))
16- import Data.Traversable (for_ , traverse_ )
16+ import Data.Traversable (for_ , traverse , traverse_ )
1717import Effect.Aff (Fiber , delay , error , forkAff , killFiber )
1818import Effect.Aff.AVar (AVar )
1919import Effect.Aff.AVar as AVar
2020import Effect.Aff.Class (class MonadAff )
21+ import Effect.Ref (Ref )
22+ import Effect.Ref as Ref
2123import Halogen as H
2224import Halogen.HTML as HH
2325import Renderless.State (getState , modifyState_ , modifyStore )
@@ -30,22 +32,18 @@ import Web.UIEvent.MouseEvent as ME
3032-- Component Types
3133
3234-- | A useful shorthand for the Halogen component type
33- type Component o item m
34- = H.Component HH.HTML (Query o item ) (Input o item ) (Message o item ) m
35+ type Component o item m = H.Component HH.HTML (Query o item ) (Input o item ) (Message o item ) m
3536
3637-- | A useful shorthand for the Halogen component HTML type
37- type ComponentHTML o item
38- = H.ComponentHTML (Query o item )
38+ type ComponentHTML o item = H.ComponentHTML (Query o item )
3939
4040-- | A useful shorthand for the Halogen component DSL type
41- type ComponentDSL o item m
42- = H.ComponentDSL (StateStore o item ) (Query o item ) (Message o item ) m
41+ type ComponentDSL o item m = H.ComponentDSL (StateStore o item ) (Query o item ) (Message o item ) m
4342
4443-- | The component's state type, wrapped in `Store`. The state and result of the
4544-- | render function are stored so that `extract` from `Control.Comonad` can be
4645-- | used to pull out the render function.
47- type StateStore o item
48- = Store (State item ) (ComponentHTML o item )
46+ type StateStore o item = Store (State item ) (ComponentHTML o item )
4947
5048-- --------
5149-- Core Constructors
@@ -72,6 +70,7 @@ data QueryF o item a
7270 | GetVisibility (Visibility -> a )
7371 | ReplaceItems (Array item ) a
7472 | Raise (o Unit ) a
73+ | Initialize a
7574 | Receive (Input o item ) a
7675
7776type Query o item = Free (QueryF o item )
@@ -138,6 +137,10 @@ raise o = liftF (Raise o unit)
138137receive :: ∀ o item . Input o item -> Query o item Unit
139138receive i = liftF (Receive i unit)
140139
140+ -- | Initializes the component on mount.
141+ initialize :: ∀ o item . Query o item Unit
142+ initialize = liftF (Initialize unit)
143+
141144-- | Represents a way to navigate on `Highlight` events: to the previous
142145-- | item, next item, or the item at a particular index.
143146data Target = Prev | Next | Index Int
@@ -183,8 +186,8 @@ data InputType
183186-- | they have typed on the toggle.
184187-- | - `debounceTime`: How long, in milliseconds, before events should occur based
185188-- | on user searches.
186- -- | - `debouncer `: A representation of a running timer that, when it expires, will
187- -- | trigger debounced events.
189+ -- | - `debounceRef `: A representation of a running timer that, when it expires, will
190+ -- | trigger debounced events.
188191-- | - `inputElement`: A reference to the toggle or input element.
189192-- | - `items`: An array of user-provided `item`s.
190193-- | - `visibility`: Whether the array of items should be considered visible or not.
@@ -196,7 +199,7 @@ type State item =
196199 { inputType :: InputType
197200 , search :: String
198201 , debounceTime :: Milliseconds
199- , debouncer :: Maybe Debouncer
202+ , debounceRef :: Maybe ( Ref ( Maybe Debouncer ))
200203 , items :: Array item
201204 , visibility :: Visibility
202205 , highlightedIndex :: Maybe Int
@@ -207,7 +210,8 @@ type State item =
207210-- | .cts.
208211type Debouncer =
209212 { var :: AVar Unit
210- , fiber :: Fiber Unit }
213+ , fiber :: Fiber Unit
214+ }
211215
212216-- | The component's input type, which includes the component's render function. This
213217-- | render function can also be used to share data with the parent component, as every
@@ -234,22 +238,22 @@ data Message o item
234238 | VisibilityChanged Visibility
235239 | Emit (o Unit )
236240
237- component :: ∀ o item m
238- . MonadAff m
239- => Component o item m
241+ component :: ∀ o item m . MonadAff m => Component o item m
240242component =
241- H .component
243+ H .lifecycleComponent
242244 { initialState
243245 , render: extract
244246 , eval: eval'
245247 , receiver: Just <<< receive
248+ , initializer: Just initialize
249+ , finalizer: Nothing
246250 }
247251 where
248252 initialState i = store i.render
249253 { inputType: i.inputType
250254 , search: fromMaybe " " i.initialSearch
251255 , debounceTime: fromMaybe (Milliseconds 0.0 ) i.debounceTime
252- , debouncer : Nothing
256+ , debounceRef : Nothing
253257 , items: i.items
254258 , highlightedIndex: Nothing
255259 , visibility: Off
@@ -267,27 +271,33 @@ component =
267271 -- Just the normal Halogen eval
268272 eval :: QueryF o item ~> ComponentDSL o item m
269273 eval = case _ of
274+ Initialize a -> a <$ do
275+ ref <- H .liftEffect $ Ref .new Nothing
276+ modifyState_ _ { debounceRef = Just ref }
277+
270278 Search str a -> a <$ do
271279 st <- getState
280+ ref :: Maybe Debouncer <- H .liftEffect $ map join $ traverse Ref .read st.debounceRef
272281 modifyState_ _ { search = str }
273282 setVis On
274283
275- case st.inputType, st.debouncer of
284+ case st.inputType, ref of
276285 TextInput , Nothing -> unit <$ do
277286 var <- H .liftAff AVar .empty
278287 fiber <- H .liftAff $ forkAff do
279288 delay st.debounceTime
280289 AVar .put unit var
281290
282291 -- This compututation will fork and run in the background. When the
283- -- var is finally filled, the .ct will run (raise a new search)
292+ -- var is finally filled, the action will run (raise a new search)
284293 _ <- H .fork do
285294 _ <- H .liftAff $ AVar .take var
286- modifyState_ _ { debouncer = Nothing , highlightedIndex = Just 0 }
295+ void $ H .liftEffect $ traverse_ (Ref .write Nothing ) st.debounceRef
296+ modifyState_ _ { highlightedIndex = Just 0 }
287297 newState <- getState
288298 H .raise $ Searched newState.search
289299
290- modifyState_ _ { debouncer = Just { var, fiber } }
300+ void $ H .liftEffect $ traverse_ ( Ref .write $ Just { var, fiber }) st.debounceRef
291301
292302 TextInput , Just debouncer -> do
293303 let var = debouncer.var
@@ -296,7 +306,7 @@ component =
296306 delay st.debounceTime
297307 AVar .put unit var
298308
299- modifyState_ _ { debouncer = Just { var, fiber } }
309+ void $ H .liftEffect $ traverse_ ( Ref .write $ Just { var, fiber }) st.debounceRef
300310
301311 -- Key stream is not yet implemented. However, this should capture user
302312 -- key events and expire their search after a set number of milliseconds.
0 commit comments