miso-1.13.0.0: src/Miso/Native/X/Element/Viewpager/Event.hs
-----------------------------------------------------------------------------
{-# LANGUAGE OverloadedStrings #-}
-----------------------------------------------------------------------------
-- |
-- Module : Miso.Native.X.Element.Viewpager.Event
-- Copyright : (C) 2016-2026 David M. Johnson
-- License : BSD3-style (see the file LICENSE)
-- Maintainer : David M. Johnson <code@dmj.io>
-- Stability : experimental
-- Portability : non-portable
--
-- @since 1.13.0.0
----------------------------------------------------------------------------
module Miso.Native.X.Element.Viewpager.Event
( -- *** Events
onChange
, onChangeWith
, onChangeMain
, onChangeMainWith
, onOffsetChange
, onOffsetChangeWith
, onOffsetChangeMain
, onOffsetChangeMainWith
, onWillChange
, onWillChangeWith
, onWillChangeMain
, onWillChangeMainWith
-- *** Types
, ViewpagerChangeEvent (..)
-- *** Decoders
, viewpagerChangeDecoder
, offsetChangeDecoder
-- *** Event Map
, viewpagerEvents
) where
-----------------------------------------------------------------------------
import qualified Data.Map as M
-----------------------------------------------------------------------------
import Miso.Event
import Miso.JSON
import Miso.Types (DOMRef, Attribute, EventHandler)
-----------------------------------------------------------------------------
-- | The 'Events' map for the Lynx @<viewpager>@ element.
--
-- Combine with other element maps using @<>@ and pass the result to
-- 'Miso.Native.native', so the delegator listens for these events.
--
-- @since 1.13.0.0
viewpagerEvents :: Events
viewpagerEvents
= M.fromList
[ ("change", BUBBLE)
, ("offsetchange", BUBBLE)
, ("willchange", BUBBLE)
]
-----------------------------------------------------------------------------
-- | Payload of the @bindchange@ and @bindwillchange@ events.
data ViewpagerChangeEvent
= ViewpagerChangeEvent
{ index :: Int
-- ^ The page index
, isDragged :: Bool
-- ^ Whether the change was user-initiated
} deriving (Show, Eq)
-----------------------------------------------------------------------------
-- | t'Decoder' producing a t'ViewpagerChangeEvent' from the raw Lynx event payload.
--
-- Pass it to 'Miso.Event.on' \/ 'Miso.Event.onMain' when writing a handler by
-- hand; the @on*@ helpers in this module already use it.
--
-- @since 1.13.0.0
viewpagerChangeDecoder :: Decoder ViewpagerChangeEvent
viewpagerChangeDecoder = ["detail"] `at` details
where
details = withObject "detail" $ \o ->
ViewpagerChangeEvent
<$> o .: "index"
<*> o .: "isDragged"
-----------------------------------------------------------------------------
-- | t'Decoder' producing a t'Double' from the raw Lynx event payload.
--
-- Pass it to 'Miso.Event.on' \/ 'Miso.Event.onMain' when writing a handler by
-- hand; the @on*@ helpers in this module already use it.
--
-- @since 1.13.0.0
offsetChangeDecoder :: Decoder Double
offsetChangeDecoder = ["detail"] `at` details
where
details = withObject "detail" $ \o -> o .: "offset"
-----------------------------------------------------------------------------
-- | https://lynxjs.org/api/elements/built-in/viewpager.html#bindchange
--
-- Triggered with the current page index after the transition completes.
--
onChange :: (ViewpagerChangeEvent -> action) -> Attribute model action
onChange action = on "change" viewpagerChangeDecoder (\e _ _ -> action e)
-----------------------------------------------------------------------------
-- | Like 'onChange', but dispatched on the Lynx __main thread__ (@MTS@).
--
-- Runs imperatively on the MTS (no VDOM diff). Meant to be used with
-- @-XStaticPointers@.
--
-- @
-- data Action = Changed ViewpagerChangeEvent
--
-- view_ [ event (static (onChangeMain Changed)) ] [ "some view" ]
-- @
--
onChangeMain :: (ViewpagerChangeEvent -> action) -> EventHandler model action
onChangeMain action = onMain "change" viewpagerChangeDecoder (\e _ _ -> action e)
-----------------------------------------------------------------------------
-- | Like 'onChangeMain', but the handler also receives read-only access to the
-- @model@ and the target element's 'DOMRef' (for imperative MTS mutation).
--
-- @
-- data Action = Changed ViewpagerChangeEvent Model DOMRef
--
-- view_ [ event (static (onChangeMainWith Changed)) ] [ "some view" ]
-- @
--
onChangeMainWith :: (ViewpagerChangeEvent -> model -> DOMRef -> action) -> EventHandler model action
onChangeMainWith action = onMain "change" viewpagerChangeDecoder action
-----------------------------------------------------------------------------
-- | https://lynxjs.org/api/elements/built-in/viewpager.html#bindoffsetchange
--
-- Triggered with the scrolling progress during a page transition.
--
onOffsetChange :: (Double -> action) -> Attribute model action
onOffsetChange action = on "offsetchange" offsetChangeDecoder (\e _ _ -> action e)
-----------------------------------------------------------------------------
-- | Like 'onOffsetChange', but dispatched on the Lynx __main thread__ (@MTS@).
--
-- Runs imperatively on the MTS (no VDOM diff). Meant to be used with
-- @-XStaticPointers@.
--
-- @
-- data Action = OffsetChanged Double
--
-- view_ [ event (static (onOffsetChangeMain OffsetChanged)) ] [ "some view" ]
-- @
--
onOffsetChangeMain :: (Double -> action) -> EventHandler model action
onOffsetChangeMain action = onMain "offsetchange" offsetChangeDecoder (\e _ _ -> action e)
-----------------------------------------------------------------------------
-- | Like 'onOffsetChangeMain', but the handler also receives read-only access to
-- the @model@ and the target element's 'DOMRef' (for imperative MTS mutation).
--
-- @
-- data Action = OffsetChanged Double Model DOMRef
--
-- view_ [ event (static (onOffsetChangeMainWith OffsetChanged)) ] [ "some view" ]
-- @
--
onOffsetChangeMainWith :: (Double -> model -> DOMRef -> action) -> EventHandler model action
onOffsetChangeMainWith action = onMain "offsetchange" offsetChangeDecoder action
-----------------------------------------------------------------------------
-- | https://lynxjs.org/api/elements/built-in/viewpager.html#bindwillchange
--
-- Triggered with the next page index before the transition starts.
--
onWillChange :: (ViewpagerChangeEvent -> action) -> Attribute model action
onWillChange action = on "willchange" viewpagerChangeDecoder (\e _ _ -> action e)
-----------------------------------------------------------------------------
-- | Like 'onWillChange', but dispatched on the Lynx __main thread__ (@MTS@).
--
-- Runs imperatively on the MTS (no VDOM diff). Meant to be used with
-- @-XStaticPointers@.
--
-- @
-- data Action = WillChange ViewpagerChangeEvent
--
-- view_ [ event (static (onWillChangeMain WillChange)) ] [ "some view" ]
-- @
--
onWillChangeMain :: (ViewpagerChangeEvent -> action) -> EventHandler model action
onWillChangeMain action = onMain "willchange" viewpagerChangeDecoder (\e _ _ -> action e)
-----------------------------------------------------------------------------
-- | Like 'onWillChangeMain', but the handler also receives read-only access to
-- the @model@ and the target element's 'DOMRef' (for imperative MTS mutation).
--
-- @
-- data Action = WillChange ViewpagerChangeEvent Model DOMRef
--
-- view_ [ event (static (onWillChangeMainWith WillChange)) ] [ "some view" ]
-- @
--
onWillChangeMainWith :: (ViewpagerChangeEvent -> model -> DOMRef -> action) -> EventHandler model action
onWillChangeMainWith action = onMain "willchange" viewpagerChangeDecoder action
-----------------------------------------------------------------------------
-- | Like 'onChange', but the handler also receives the target element's 'DOMRef'.
-- Use for main-thread (@MTS@) handlers that imperatively mutate the element.
onChangeWith :: (ViewpagerChangeEvent -> DOMRef -> action) -> Attribute model action
onChangeWith action = on "change" viewpagerChangeDecoder $ \vpce _ domRef -> action vpce domRef
-----------------------------------------------------------------------------
-- | Like 'onOffsetChange', but the handler also receives the target element's 'DOMRef'.
-- Use for main-thread (@MTS@) handlers that imperatively mutate the element.
onOffsetChangeWith :: (Double -> DOMRef -> action) -> Attribute model action
onOffsetChangeWith action = on "offsetchange" offsetChangeDecoder $ \vpce _ domRef -> action vpce domRef
-----------------------------------------------------------------------------
-- | Like 'onWillChange', but the handler also receives the target element's 'DOMRef'.
-- Use for main-thread (@MTS@) handlers that imperatively mutate the element.
onWillChangeWith :: (ViewpagerChangeEvent -> DOMRef -> action) -> Attribute model action
onWillChangeWith action = on "willchange" viewpagerChangeDecoder $ \vpce _ domRef -> action vpce domRef
-----------------------------------------------------------------------------