content: {-# LANGUAGE CPP #-}
  {-# LANGUAGE ConstraintKinds #-}
  {-# LANGUAGE DataKinds #-}
  {-# LANGUAGE DefaultSignatures #-}
  {-# LANGUAGE DeriveFunctor #-}
  {-# LANGUAGE FlexibleContexts #-}
  {-# LANGUAGE FlexibleInstances #-}
  {-# LANGUAGE FunctionalDependencies #-}
  {-# LANGUAGE GeneralizedNewtypeDeriving #-}
  #if !MIN_VERSION_base(4,9,0)
  {-# LANGUAGE ImpredicativeTypes #-}
  #else
  {-# LANGUAGE Rank2Types #-} -- Implied by ImpredicativeTypes
  #endif
  {-# LANGUAGE LambdaCase #-}
  {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE PolyKinds #-}
  {-# LANGUAGE RecursiveDo #-}
  {-# LANGUAGE ScopedTypeVariables #-}
  {-# LANGUAGE StandaloneDeriving #-}
  #ifdef USE_TEMPLATE_HASKELL
  {-# LANGUAGE TemplateHaskell #-}
  #endif
  {-# LANGUAGE TypeFamilies #-}
  {-# LANGUAGE TypeOperators #-}
  {-# LANGUAGE UndecidableInstances #-}
  module Reflex.Dom.Builder.Class
         ( module Reflex.Dom.Builder.Class
         , module Reflex.Dom.Builder.Class.Events
         , module Reflex.NotReady.Class
         ) where
  
  import Reflex.Adjustable.Class
  import Reflex.Class as Reflex
  import Reflex.Dom.Builder.Class.Events
  #ifdef USE_TEMPLATE_HASKELL
  import Reflex.Dom.Builder.Class.TH
  #endif
  import Reflex.BehaviorWriter.Base
  import Reflex.DynamicWriter.Base
  import Reflex.EventWriter.Base
  import Reflex.NotReady.Class
  import Reflex.PerformEvent.Class
  import Reflex.PostBuild.Base
  import Reflex.Query.Base
  import Reflex.Query.Class
  import Reflex.Requester.Base
  
  import qualified Control.Category
  import Control.Lens hiding (element)
  import Control.Monad.Fix
  import Control.Monad.Reader
  import qualified Control.Monad.State as Lazy
  import Control.Monad.State.Strict
  import Control.Monad.Trans.Control
  import Data.Default
  import Data.Functor.Misc
  import Data.Kind (Type)
  import Data.Map (Map)
  import qualified Data.Map as Map
  import Data.Maybe
  import Data.Proxy
  import Data.Semigroup.Commutative
  import Data.String
  import Data.Text (Text)
  import Data.Type.Coercion
  import GHCJS.DOM.Types (JSM)
  import qualified GHCJS.DOM.Types as DOM
  
  class Default (EventSpec d EventResult) => DomSpace d where
    type EventSpec d :: (EventTag -> Type) -> Type
    type RawDocument d :: Type
    type RawTextNode d :: Type
    type RawCommentNode d :: Type
    type RawElement d :: Type
    type RawInputElement d :: Type
    type RawTextAreaElement d :: Type
    type RawSelectElement d :: Type
    addEventSpecFlags :: proxy d -> EventName en -> (Maybe (er en) -> EventFlags) -> EventSpec d er -> EventSpec d er
  
  -- | @'DomBuilder' t m@ indicates that @m@ is a 'Monad' capable of building
  -- dynamic DOM in the 'Reflex' timeline @t@
  class (Monad m, Reflex t, DomSpace (DomBuilderSpace m), NotReady t m, Adjustable t m) => DomBuilder t m | m -> t where
    type DomBuilderSpace m :: Type
    textNode :: TextNodeConfig t -> m (TextNode (DomBuilderSpace m) t)
    default textNode :: ( MonadTrans f
                        , m ~ f m'
                        , DomBuilderSpace m' ~ DomBuilderSpace m
                        , DomBuilder t m'
                        )
                     => TextNodeConfig t -> m (TextNode (DomBuilderSpace m) t)
    textNode = lift . textNode
    {-# INLINABLE textNode #-}
    commentNode :: CommentNodeConfig t -> m (CommentNode (DomBuilderSpace m) t)
    default commentNode :: ( MonadTrans f
                        , m ~ f m'
                        , DomBuilderSpace m' ~ DomBuilderSpace m
                        , DomBuilder t m'
                        )
                     => CommentNodeConfig t -> m (CommentNode (DomBuilderSpace m) t)
    commentNode = lift . commentNode
    {-# INLINABLE commentNode #-}
    element :: Text -> ElementConfig er t (DomBuilderSpace m) -> m a -> m (Element er (DomBuilderSpace m) t, a)
    default element :: ( MonadTransControl f
                       , StT f a ~ a
                       , m ~ f m'
                       , DomBuilderSpace m' ~ DomBuilderSpace m
                       , DomBuilder t m'
                       )
                    => Text -> ElementConfig er t (DomBuilderSpace m) -> m a -> m (Element er (DomBuilderSpace m) t, a)
    element t cfg child = liftWith $ \run -> element t cfg $ run child
    {-# INLINABLE element #-}
    inputElement :: InputElementConfig er t (DomBuilderSpace m) -> m (InputElement er (DomBuilderSpace m) t)
    default inputElement :: ( MonadTransControl f
                            , m ~ f m'
                            , DomBuilderSpace m' ~ DomBuilderSpace m
                            , DomBuilder t m'
                            )
                         => InputElementConfig er t (DomBuilderSpace m) -> m (InputElement er (DomBuilderSpace m) t)
    inputElement = lift . inputElement
    {-# INLINABLE inputElement #-}
    textAreaElement :: TextAreaElementConfig er t (DomBuilderSpace m) -> m (TextAreaElement er (DomBuilderSpace m) t)
    default textAreaElement :: ( MonadTransControl f
                               , m ~ f m'
                               , DomBuilderSpace m' ~ DomBuilderSpace m
                               , DomBuilder t m'
                               )
                            => TextAreaElementConfig er t (DomBuilderSpace m) -> m (TextAreaElement er (DomBuilderSpace m) t)
    textAreaElement = lift . textAreaElement
    {-# INLINABLE textAreaElement #-}
    selectElement :: SelectElementConfig er t (DomBuilderSpace m) -> m a -> m (SelectElement er (DomBuilderSpace m) t, a)
    default selectElement :: ( MonadTransControl f
                             , StT f a ~ a
                             , m ~ f m'
                             , DomBuilderSpace m' ~ DomBuilderSpace m
                             , DomBuilder t m'
                             )
                          => SelectElementConfig er t (DomBuilderSpace m) -> m a -> m (SelectElement er (DomBuilderSpace m) t, a)
    selectElement cfg child = do
      liftWith $ \run -> selectElement cfg $ run child
    {-# INLINABLE selectElement #-}
    placeRawElement :: RawElement (DomBuilderSpace m) -> m ()
    default placeRawElement :: ( MonadTrans f
                               , m ~ f m'
                               , DomBuilderSpace m' ~ DomBuilderSpace m
                               , DomBuilder t m'
                               )
                            => RawElement (DomBuilderSpace m) -> m ()
    placeRawElement = lift . placeRawElement
    {-# INLINABLE placeRawElement #-}
    wrapRawElement :: RawElement (DomBuilderSpace m) -> RawElementConfig er t (DomBuilderSpace m) -> m (Element er (DomBuilderSpace m) t)
    default wrapRawElement :: ( MonadTrans f
                              , m ~ f m'
                              , DomBuilderSpace m' ~ DomBuilderSpace m
                              , DomBuilder t m'
                              )
                           => RawElement (DomBuilderSpace m) -> RawElementConfig er t (DomBuilderSpace m) -> m (Element er (DomBuilderSpace m) t)
    wrapRawElement e cfg = lift $ wrapRawElement e $ cfg
      { _rawElementConfig_eventSpec = _rawElementConfig_eventSpec cfg
      }
    {-# INLINABLE wrapRawElement #-}
  
  class DomBuilder t m => MountableDomBuilder t m where
    type DomFragment m :: Type
    buildDomFragment :: m a -> m (DomFragment m, a)
    mountDomFragment :: DomFragment m -> Event t (DomFragment m) -> m ()
  
  type Namespace = Text
  
  data TextNodeConfig t
     = TextNodeConfig { _textNodeConfig_initialContents :: {-# UNPACK #-} !Text
                      , _textNodeConfig_setContents :: !(Maybe (Event t Text))
                      }
  
  #ifndef USE_TEMPLATE_HASKELL
  textNodeConfig_initialContents :: Lens' (TextNodeConfig t) Text
  textNodeConfig_initialContents f (TextNodeConfig a b) = (\a' -> TextNodeConfig a' b) <$> f a
  {-# INLINE textNodeConfig_initialContents #-}
  #endif
  
  instance (Reflex t) => Default (TextNodeConfig t) where
    {-# INLINABLE def #-}
    def = TextNodeConfig
      { _textNodeConfig_initialContents = mempty
      , _textNodeConfig_setContents = Nothing
      }
  
  newtype TextNode d t = TextNode
    { _textNode_raw :: RawTextNode d
    }
  
  data CommentNodeConfig t
     = CommentNodeConfig { _commentNodeConfig_initialContents :: {-# UNPACK #-} !Text
                         , _commentNodeConfig_setContents :: !(Maybe (Event t Text))
                         }
  
  #ifndef USE_TEMPLATE_HASKELL
  commentNodeConfig_initialContents :: Lens' (CommentNodeConfig t) Text
  commentNodeConfig_initialContents f (CommentNodeConfig a b) = (\a' -> CommentNodeConfig a' b) <$> f a
  {-# INLINE commentNodeConfig_initialContents #-}
  #endif
  
  instance (Reflex t) => Default (CommentNodeConfig t) where
    {-# INLINABLE def #-}
    def = CommentNodeConfig
      { _commentNodeConfig_initialContents = mempty
      , _commentNodeConfig_setContents = Nothing
      }
  
  newtype CommentNode d t = CommentNode
    { _commentNode_raw :: RawCommentNode d
    }
  
  data AttributeName = AttributeName !(Maybe Namespace) !Text deriving (Show, Read, Eq, Ord)
  
  mapKeysToAttributeName :: Map Text v -> Map AttributeName v
  mapKeysToAttributeName = Map.mapKeysMonotonic (AttributeName Nothing)
  
  -- | By default, AttributeNames are unnamespaced
  instance IsString AttributeName where
    fromString = AttributeName Nothing . fromString
  
  data Propagation
     = Propagation_Continue
     | Propagation_Stop
     | Propagation_StopImmediate
     deriving (Show, Read, Eq, Ord)
  
  instance Semigroup Propagation where
    {-# INLINABLE (<>) #-}
    (<>) = max
  
  instance Monoid Propagation where
    {-# INLINABLE mempty #-}
    mempty = Propagation_Continue
    {-# INLINABLE mappend #-}
    mappend = (<>)
  
  data EventFlags = EventFlags --TODO: Monoid; ways of building each flag
    { _eventFlags_propagation :: Propagation
    , _eventFlags_preventDefault :: Bool
    }
  
  instance Semigroup EventFlags where
    {-# INLINABLE (<>) #-}
    EventFlags p pd <> EventFlags p' pd' = EventFlags (p <> p') (pd || pd')
  
  instance Monoid EventFlags where
    {-# INLINABLE mempty #-}
    mempty = EventFlags Propagation_Continue False
    {-# INLINABLE mappend #-}
    mappend = (<>)
  
  preventDefault :: EventFlags
  preventDefault = mempty { _eventFlags_preventDefault = True }
  
  stopPropagation :: EventFlags
  stopPropagation = mempty { _eventFlags_propagation = Propagation_Stop }
  
  data ElementConfig er t s
     = ElementConfig { _elementConfig_namespace :: Maybe Namespace
                     , _elementConfig_initialAttributes :: Map AttributeName Text
                     , _elementConfig_modifyAttributes :: Maybe (Event t (Map AttributeName (Maybe Text)))
                     , _elementConfig_eventSpec :: EventSpec s er
                     }
  
  #ifndef USE_TEMPLATE_HASKELL
  elementConfig_namespace :: Lens' (ElementConfig er t s) (Maybe Namespace)
  elementConfig_namespace f (ElementConfig a b c d) = (\a' -> ElementConfig a' b c d) <$> f a
  {-# INLINE elementConfig_namespace #-}
  elementConfig_initialAttributes :: Lens' (ElementConfig er t s) (Map AttributeName Text)
  elementConfig_initialAttributes f (ElementConfig a b c d) = (\b' -> ElementConfig a b' c d) <$> f b
  {-# INLINE elementConfig_initialAttributes #-}
  elementConfig_eventSpec :: Lens
      (ElementConfig er1 t s1)
      (ElementConfig er2 t s2)
      (EventSpec s1 er1)
      (EventSpec s2 er2)
  elementConfig_eventSpec f (ElementConfig a b c d) = (\d' -> ElementConfig a b c d') <$> f d
  {-# INLINE elementConfig_eventSpec #-}
  #endif
  
  data Element er d t
     = Element { _element_events :: EventSelector t (WrapArg er EventName) --TODO: EventSelector should have two arguments
               , _element_raw :: RawElement d
               }
  
  data InputElementConfig er t s
     = InputElementConfig { _inputElementConfig_initialValue :: Text
                          , _inputElementConfig_setValue :: Maybe (Event t Text)
                          , _inputElementConfig_initialChecked :: Bool
                          , _inputElementConfig_setChecked :: Maybe (Event t Bool)
                          , _inputElementConfig_elementConfig :: ElementConfig er t s
                          }
  
  #ifndef USE_TEMPLATE_HASKELL
  inputElementConfig_initialValue :: Lens' (InputElementConfig er t m) Text
  inputElementConfig_initialValue f (InputElementConfig a b c d e) = (\a' -> InputElementConfig a' b c d e) <$> f a
  {-# INLINE inputElementConfig_initialValue #-}
  inputElementConfig_initialChecked :: Lens' (InputElementConfig er t m) Bool
  inputElementConfig_initialChecked f (InputElementConfig a b c d e) = (\c' -> InputElementConfig a b c' d e) <$> f c
  {-# INLINE inputElementConfig_initialChecked #-}
  inputElementConfig_elementConfig :: Lens
      (InputElementConfig er1 t m1)
      (InputElementConfig er2 t m2)
      (ElementConfig er1 t m1)
      (ElementConfig er2 t m2)
  inputElementConfig_elementConfig f (InputElementConfig a b c d e) = (\e' -> InputElementConfig a b c d e') <$> f e
  {-# INLINE inputElementConfig_elementConfig #-}
  #endif
  
  instance (Reflex t, er ~ EventResult, DomSpace s) => Default (ElementConfig er t s) where
    {-# INLINABLE def #-}
    def = ElementConfig
      { _elementConfig_namespace = Nothing
      , _elementConfig_initialAttributes = mempty
      , _elementConfig_modifyAttributes = Nothing
      , _elementConfig_eventSpec = def
      }
  
  instance (Reflex t, er ~ EventResult, DomSpace s) => Default (InputElementConfig er t s) where
    {-# INLINABLE def #-}
    def = InputElementConfig
      { _inputElementConfig_initialValue = ""
      , _inputElementConfig_setValue = Nothing
      , _inputElementConfig_initialChecked = False
      , _inputElementConfig_setChecked = Nothing
      , _inputElementConfig_elementConfig = def
      }
  
  data InputElement er d t
     = InputElement { _inputElement_value :: Dynamic t Text
                    , _inputElement_checked :: Dynamic t Bool
                    , _inputElement_checkedChange :: Event t Bool
                    , _inputElement_input :: Event t Text
                    , _inputElement_hasFocus :: Dynamic t Bool
                    , _inputElement_element :: Element er d t
                    , _inputElement_raw :: RawInputElement d
                    , _inputElement_files :: Dynamic t [DOM.File]
                    }
  
  data TextAreaElementConfig er t m
     = TextAreaElementConfig { _textAreaElementConfig_initialValue :: Text
                             , _textAreaElementConfig_setValue :: Maybe (Event t Text)
                             , _textAreaElementConfig_elementConfig :: ElementConfig er t m
                             }
  
  #ifndef USE_TEMPLATE_HASKELL
  textAreaElementConfig_initialValue :: Lens' (TextAreaElementConfig er t m) Text
  textAreaElementConfig_initialValue f (TextAreaElementConfig a b c) = (\a' -> TextAreaElementConfig a' b c) <$> f a
  {-# INLINE textAreaElementConfig_initialValue #-}
  textAreaElementConfig_elementConfig :: Lens
      (TextAreaElementConfig er1 t m1)
      (TextAreaElementConfig er2 t m2)
      (ElementConfig er1 t m1)
      (ElementConfig er2 t m2)
  textAreaElementConfig_elementConfig f (TextAreaElementConfig a b c) = (\c' -> TextAreaElementConfig a b c') <$> f c
  {-# INLINE textAreaElementConfig_elementConfig #-}
  #endif
  
  instance (Reflex t, er ~ EventResult, DomSpace s) => Default (TextAreaElementConfig er t s) where
    {-# INLINABLE def #-}
    def = TextAreaElementConfig
      { _textAreaElementConfig_initialValue = ""
      , _textAreaElementConfig_setValue = Nothing
      , _textAreaElementConfig_elementConfig = def
      }
  
  data TextAreaElement er d t
     = TextAreaElement { _textAreaElement_value :: Dynamic t Text
                       , _textAreaElement_input :: Event t Text
                       , _textAreaElement_hasFocus :: Dynamic t Bool
                       , _textAreaElement_element :: Element er d t
                       , _textAreaElement_raw :: RawTextAreaElement d
                       }
  
  extractRawElementConfig :: ElementConfig er t m -> RawElementConfig er t m
  extractRawElementConfig cfg = RawElementConfig
    { _rawElementConfig_modifyAttributes = _elementConfig_modifyAttributes cfg
    , _rawElementConfig_eventSpec = _elementConfig_eventSpec cfg
    }
  
  data RawElementConfig er t s = RawElementConfig
    { _rawElementConfig_modifyAttributes :: Maybe (Event t (Map AttributeName (Maybe Text)))
    , _rawElementConfig_eventSpec :: EventSpec s er
    }
  
  #ifndef USE_TEMPLATE_HASKELL
  rawElementConfig_eventSpec :: Lens
      (RawElementConfig er1 t s1)
      (RawElementConfig er2 t s2)
      (EventSpec s1 er1)
      (EventSpec s2 er2)
  rawElementConfig_eventSpec f (RawElementConfig a b) = (\b' -> RawElementConfig a b') <$> f b
  {-# INLINE rawElementConfig_eventSpec #-}
  #endif
  
  instance (Reflex t, er ~ EventResult, DomSpace s) => Default (RawElementConfig er t s) where
    def = RawElementConfig
      { _rawElementConfig_modifyAttributes = Nothing
      , _rawElementConfig_eventSpec = def
      }
  
  data SelectElementConfig er t m = SelectElementConfig
    { _selectElementConfig_initialValue :: Text
    , _selectElementConfig_setValue :: Maybe (Event t Text)
    , _selectElementConfig_elementConfig :: ElementConfig er t m
    }
  
  #ifndef USE_TEMPLATE_HASKELL
  selectElementConfig_initialValue :: Lens' (SelectElementConfig er t m) Text
  selectElementConfig_initialValue f (SelectElementConfig a b c) = (\a' -> SelectElementConfig a' b c) <$> f a
  {-# INLINE selectElementConfig_initialValue #-}
  selectElementConfig_elementConfig :: Lens
      (SelectElementConfig er1 t m1)
      (SelectElementConfig er2 t m2)
      (ElementConfig er1 t m1)
      (ElementConfig er2 t m2)
  selectElementConfig_elementConfig f (SelectElementConfig a b c) = (\c' -> SelectElementConfig a b c') <$> f c
  {-# INLINE selectElementConfig_elementConfig #-}
  #endif
  
  instance (Reflex t, er ~ EventResult, DomSpace s) => Default (SelectElementConfig er t s) where
    def = SelectElementConfig
      { _selectElementConfig_initialValue = ""
      , _selectElementConfig_setValue = Nothing
      , _selectElementConfig_elementConfig = def
      }
  
  data SelectElement er d t = SelectElement
    { _selectElement_element :: Element er d t
    , _selectElement_value :: Dynamic t Text
    , _selectElement_change :: Event t Text -- ^ Fires when the value is changed by the user, but not when it is set by setValue
    , _selectElement_hasFocus :: Dynamic t Bool
    , _selectElement_raw :: RawSelectElement d
    }
  
  #ifdef USE_TEMPLATE_HASKELL
  concat <$> mapM (uncurry makeLensesWithoutField)
    [ (["_textNodeConfig_setContents"], ''TextNodeConfig)
    , (["_commentNodeConfig_setContents"], ''CommentNodeConfig)
    , ([ "_inputElementConfig_setValue"
       , "_inputElementConfig_setChecked" ], ''InputElementConfig)
    , (["_rawElementConfig_modifyAttributes"], ''RawElementConfig)
    , (["_elementConfig_modifyAttributes"], ''ElementConfig)
    , (["_textAreaElementConfig_setValue"], ''TextAreaElementConfig)
    , (["_selectElementConfig_setValue"], ''SelectElementConfig)
    ]
  #endif
  
  -- | This lens is technically illegal. The implementation of 'TextNodeConfig' uses a 'Maybe' under the hood for efficiency reasons. However, always interacting with 'TextNodeConfig' via lenses will always behave correctly, and if you pattern match on it, you should always treat 'Nothing' as 'never'.
  textNodeConfig_setContents :: Reflex t => Lens' (TextNodeConfig t) (Event t Text)
  textNodeConfig_setContents =
    let getter = fromMaybe never . _textNodeConfig_setContents
        setter t e = t { _textNodeConfig_setContents = Just e }
    in lens getter setter
  
  -- | This lens is technically illegal. The implementation of 'CommentNodeConfig' uses a 'Maybe' under the hood for efficiency reasons. However, always interacting with 'CommentNodeConfig' via lenses will always behave correctly, and if you pattern match on it, you should always treat 'Nothing' as 'never'.
  commentNodeConfig_setContents :: Reflex t => Lens (CommentNodeConfig t) (CommentNodeConfig t) (Event t Text) (Event t Text)
  commentNodeConfig_setContents =
    let getter = fromMaybe never . _commentNodeConfig_setContents
        setter t e = t { _commentNodeConfig_setContents = Just e }
    in lens getter setter
  
  -- | This lens is technically illegal. The implementation of 'InputElementConfig' uses a 'Maybe' under the hood for efficiency reasons. However, always interacting with 'InputElementConfig' via lenses will always behave correctly, and if you pattern match on it, you should always treat 'Nothing' as 'never'.
  inputElementConfig_setValue :: Reflex t => Lens' (InputElementConfig er t m) (Event t Text)
  inputElementConfig_setValue =
    let getter = fromMaybe never . _inputElementConfig_setValue
        setter t e = t { _inputElementConfig_setValue = Just e }
    in lens getter setter
  
  -- | This lens is technically illegal. The implementation of 'InputElementConfig' uses a 'Maybe' under the hood for efficiency reasons. However, always interacting with 'InputElementConfig' via lenses will always behave correctly, and if you pattern match on it, you should always treat 'Nothing' as 'never'.
  inputElementConfig_setChecked :: Reflex t => Lens' (InputElementConfig er t m) (Event t Bool)
  inputElementConfig_setChecked =
    let getter = fromMaybe never . _inputElementConfig_setChecked
        setter t e = t { _inputElementConfig_setChecked = Just e }
    in lens getter setter
  
  -- | This lens is technically illegal. The implementation of 'RawElementConfig' uses a 'Maybe' under the hood for efficiency reasons. However, always interacting with 'RawElementConfig' via lenses will always behave correctly, and if you pattern match on it, you should always treat 'Nothing' as 'never'.
  rawElementConfig_modifyAttributes :: Reflex t => Lens' (RawElementConfig er t m) (Event t (Map AttributeName (Maybe Text)))
  rawElementConfig_modifyAttributes =
    let getter = fromMaybe never . _rawElementConfig_modifyAttributes
        setter t e = t { _rawElementConfig_modifyAttributes = Just e }
    in lens getter setter
  
  -- | This lens is technically illegal. The implementation of 'RawElementConfig' uses a 'Maybe' under the hood for efficiency reasons. However, always interacting with 'RawElementConfig' via lenses will always behave correctly, and if you pattern match on it, you should always treat 'Nothing' as 'never'.
  elementConfig_modifyAttributes :: Reflex t => Lens' (ElementConfig er t m) (Event t (Map AttributeName (Maybe Text)))
  elementConfig_modifyAttributes =
    let getter = fromMaybe never . _elementConfig_modifyAttributes
        setter t e = t { _elementConfig_modifyAttributes = Just e }
    in lens getter setter
  
  -- | This lens is technically illegal. The implementation of 'TextAreaElementConfig' uses a 'Maybe' under the hood for efficiency reasons. However, always interacting with 'TextAreaElementConfig' via lenses will always behave correctly, and if you pattern match on it, you should always treat 'Nothing' as 'never'.
  textAreaElementConfig_setValue :: Reflex t => Lens' (TextAreaElementConfig er t m) (Event t Text)
  textAreaElementConfig_setValue =
    let getter = fromMaybe never . _textAreaElementConfig_setValue
        setter t e = t { _textAreaElementConfig_setValue = Just e }
    in lens getter setter
  
  -- | This lens is technically illegal. The implementation of 'SelectElementConfig' uses a 'Maybe' under the hood for efficiency reasons. However, always interacting with 'SelectElementConfig' via lenses will always behave correctly, and if you pattern match on it, you should always treat 'Nothing' as 'never'.
  selectElementConfig_setValue :: Reflex t => Lens' (SelectElementConfig er t m) (Event t Text)
  selectElementConfig_setValue =
    let getter = fromMaybe never . _selectElementConfig_setValue
        setter t e = t { _selectElementConfig_setValue = Just e }
    in lens getter setter
  
  class InitialAttributes a where
    initialAttributes :: Lens' a (Map AttributeName Text)
  
  instance InitialAttributes (ElementConfig er t m) where
    {-# INLINABLE initialAttributes #-}
    initialAttributes = elementConfig_initialAttributes
  
  instance InitialAttributes (InputElementConfig er t m) where
    {-# INLINABLE initialAttributes #-}
    initialAttributes = inputElementConfig_elementConfig . elementConfig_initialAttributes
  
  instance InitialAttributes (TextAreaElementConfig er t m) where
    {-# INLINABLE initialAttributes #-}
    initialAttributes = textAreaElementConfig_elementConfig . elementConfig_initialAttributes
  
  instance InitialAttributes (SelectElementConfig er t m) where
    {-# INLINABLE initialAttributes #-}
    initialAttributes = selectElementConfig_elementConfig . elementConfig_initialAttributes
  
  class ModifyAttributes t a | a -> t where
    modifyAttributes :: Reflex t => Lens' a (Event t (Map AttributeName (Maybe Text)))
  
  instance ModifyAttributes t (ElementConfig er t m) where
    {-# INLINABLE modifyAttributes #-}
    modifyAttributes = elementConfig_modifyAttributes
  
  instance ModifyAttributes t (InputElementConfig er t m) where
    {-# INLINABLE modifyAttributes #-}
    modifyAttributes = inputElementConfig_elementConfig . elementConfig_modifyAttributes
  
  instance ModifyAttributes t (TextAreaElementConfig er t m) where
    {-# INLINABLE modifyAttributes #-}
    modifyAttributes = textAreaElementConfig_elementConfig . elementConfig_modifyAttributes
  
  instance ModifyAttributes t (SelectElementConfig er t m) where
    {-# INLINABLE modifyAttributes #-}
    modifyAttributes = selectElementConfig_elementConfig . elementConfig_modifyAttributes
  
  instance ModifyAttributes t (RawElementConfig er t m) where
    {-# INLINABLE modifyAttributes #-}
    modifyAttributes = rawElementConfig_modifyAttributes
  
  class HasNamespace a where
    namespace :: Lens' a (Maybe Namespace)
  
  instance HasNamespace (ElementConfig er t m) where
    {-# INLINABLE namespace #-}
    namespace = elementConfig_namespace
  
  instance (DomBuilder t m, PerformEvent t m, MonadFix m, MonadHold t m) => DomBuilder t (PostBuildT t m) where
    type DomBuilderSpace (PostBuildT t m) = DomBuilderSpace m
    wrapRawElement e = lift . wrapRawElement e
  
  instance (MountableDomBuilder t m, PerformEvent t m, MonadFix m, MonadHold t m) => MountableDomBuilder t (PostBuildT t m) where
    type DomFragment (PostBuildT t m) = DomFragment m
    buildDomFragment = liftThrough buildDomFragment
    mountDomFragment f0 f' = lift $ mountDomFragment f0 f'
  
  instance (DomBuilder t m, MonadFix m, Monoid w, MonadHold t m) => DomBuilder t (DynamicWriterT t w m) where
    type DomBuilderSpace (DynamicWriterT t w m) = DomBuilderSpace m
    textNode = liftTextNode
    commentNode = liftCommentNode
    element elementTag cfg (DynamicWriterT child) = DynamicWriterT $ do
      s <- get
      (el, (a, newS)) <- lift $ element elementTag cfg $ runStateT child s
      put newS
      return (el, a)
    inputElement = lift . inputElement
    textAreaElement = lift . textAreaElement
    selectElement cfg (DynamicWriterT child) = DynamicWriterT $ do
      s <- get
      (el, (a, newS)) <- lift $ selectElement cfg $ runStateT child s
      put newS
      return (el, a)
    placeRawElement = lift . placeRawElement
    wrapRawElement e = lift . wrapRawElement e
  
  instance (DomBuilder t m, MonadHold t m, MonadFix m) => DomBuilder t (RequesterT t request response m) where
    type DomBuilderSpace (RequesterT t request response m) = DomBuilderSpace m
    textNode = liftTextNode
    commentNode = liftCommentNode
    element elementTag cfg (RequesterT child) = RequesterT $ do
      r <- ask
      old <- get
      (el, (a, new)) <- lift $ lift $ element elementTag cfg $ runReaderT (runStateT child old) r
      put new
      return (el, a)
    inputElement = lift . inputElement
    textAreaElement = lift . textAreaElement
    selectElement cfg (RequesterT child) = RequesterT $ do
      r <- ask
      old <- get
      (el, (a, new)) <- lift $ lift $ selectElement cfg $ runReaderT (runStateT child old) r
      put new
      return (el, a)
    placeRawElement = lift . placeRawElement
    wrapRawElement e = lift . wrapRawElement e
  
  instance (DomBuilder t m, MonadHold t m, Semigroup w) => DomBuilder t (EventWriterT t w m) where
    type DomBuilderSpace (EventWriterT t w m) = DomBuilderSpace m
    textNode = liftTextNode
    commentNode = liftCommentNode
    element elementTag cfg (EventWriterT child) = EventWriterT $ do
      old <- get
      (el, (a, new)) <- lift $ element elementTag cfg $ runStateT child old
      put new
      return (el, a)
    inputElement = lift . inputElement
    textAreaElement = lift . textAreaElement
    selectElement cfg (EventWriterT child) = EventWriterT $ do
      old <- get
      (el, (a, new)) <- lift $ selectElement cfg $ runStateT child old
      put new
      return (el, a)
    placeRawElement = lift . placeRawElement
    wrapRawElement e = lift . wrapRawElement e
  
  instance (DomBuilder t m, MonadFix m, MonadHold t m, Group q, Query q, Commutative q, Eq q) => DomBuilder t (QueryT t q m) where
    type DomBuilderSpace (QueryT t q m) = DomBuilderSpace m
    textNode = liftTextNode
    commentNode = liftCommentNode
    element elementTag cfg (QueryT child) = QueryT $ do
      s <- get
      (e, (a, newS)) <- lift $ element elementTag cfg $ runStateT child s
      put newS
      return (e, a)
    inputElement = lift . inputElement
    textAreaElement = lift . textAreaElement
    selectElement cfg (QueryT child) = QueryT $ do
      s <- get
      (e, (a, newS)) <- lift $ selectElement cfg $ runStateT child s
      put newS
      return (e, a)
    placeRawElement = lift . placeRawElement
    wrapRawElement e = lift . wrapRawElement e
  
  -- * Convenience functions
  
  class HasDomEvent t target eventName | target -> t where
    type DomEventType target eventName :: Type
    domEvent :: EventName eventName -> target -> Event t (DomEventType target eventName)
  
  instance Reflex t => HasDomEvent t (Element EventResult d t) en where
    type DomEventType (Element EventResult d t) en = EventResultType en
    {-# INLINABLE domEvent #-}
    domEvent en e = coerceEvent $ Reflex.select (_element_events e) (WrapArg en)
  
  instance Reflex t => HasDomEvent t (InputElement EventResult d t) en where
    type DomEventType (InputElement EventResult d t) en = EventResultType en
    {-# INLINABLE domEvent #-}
    domEvent en = domEvent en . _inputElement_element
  
  instance Reflex t => HasDomEvent t (TextAreaElement EventResult d t) en where
    type DomEventType (TextAreaElement EventResult d t) en = EventResultType en
    {-# INLINABLE domEvent #-}
    domEvent en = domEvent en . _textAreaElement_element
  
  instance DomBuilder t m => DomBuilder t (ReaderT r m) where
    type DomBuilderSpace (ReaderT r m) = DomBuilderSpace m
  
  type LiftDomBuilder t f m =
    ( Reflex t
    , MonadTransControlStateless f
    , Monad m
    , DomBuilder t m
    , DomBuilderSpace (f m) ~ DomBuilderSpace m
    )
  
  class MonadTransControl t => MonadTransControlStateless t where
    stTCoercion :: proxy t -> Coercion (StT t a) a
    default stTCoercion :: (a ~ StT t a) => proxy t -> Coercion (StT t a) a
    stTCoercion _ = Control.Category.id
  
  toStT :: MonadTransControlStateless t => proxy t -> a -> StT t a
  toStT = coerceWith . sym . stTCoercion
  
  fromStT :: MonadTransControlStateless t => proxy t -> StT t a -> a
  fromStT = coerceWith . stTCoercion
  
  instance MonadTransControlStateless (ReaderT r)
  
  type RunStateless t = forall n b. Monad n => t n b -> n b
  
  liftWithStateless :: forall m t a. (Monad m, MonadTransControlStateless t) => (RunStateless t -> m a) -> t m a
  liftWithStateless a = liftWith $ \run -> a $ fmap (fromStT (Proxy :: Proxy t)) . run
  
  liftTextNode :: (MonadTrans f, DomBuilder t m) => TextNodeConfig t -> f m (TextNode (DomBuilderSpace m) t)
  liftTextNode = lift . textNode
  
  liftCommentNode :: (MonadTrans f, DomBuilder t m) => CommentNodeConfig t -> f m (CommentNode (DomBuilderSpace m) t)
  liftCommentNode = lift . commentNode
  
  liftElement :: LiftDomBuilder t f m => Text -> ElementConfig er t (DomBuilderSpace m) -> f m a -> f m (Element er (DomBuilderSpace m) t, a)
  liftElement elementTag cfg child = liftWithStateless $ \run -> element elementTag cfg $ run child
  
  class (Reflex t, Monad m) => DomRenderHook t m | m -> t where
    withRenderHook :: (forall x. JSM x -> JSM x) -> m a -> m a
    requestDomAction :: Event t (JSM a) -> m (Event t a)
    requestDomAction_ :: Event t (JSM a) -> m ()
  
  instance DomRenderHook t m => DomRenderHook t (ReaderT e m) where
    withRenderHook hook (ReaderT a) = ReaderT $ \e -> withRenderHook hook $ a e
    requestDomAction = lift . requestDomAction
    requestDomAction_ = lift . requestDomAction_
  
  instance DomRenderHook t m => DomRenderHook t (StateT e m) where
    withRenderHook hook (StateT a) = StateT $ \s -> withRenderHook hook $ a s
    requestDomAction = lift . requestDomAction
    requestDomAction_ = lift . requestDomAction_
  
  instance DomRenderHook t m => DomRenderHook t (Lazy.StateT e m) where
    withRenderHook hook (Lazy.StateT a) = Lazy.StateT $ \s -> withRenderHook hook $ a s
    requestDomAction = lift . requestDomAction
    requestDomAction_ = lift . requestDomAction_
  
  deriving instance DomRenderHook t m => DomRenderHook t (BehaviorWriterT t w m)
  deriving instance DomRenderHook t m => DomRenderHook t (EventWriterT t w m)
  deriving instance DomRenderHook t m => DomRenderHook t (DynamicWriterT t w m)
  deriving instance DomRenderHook t m => DomRenderHook t (RequesterT t req rsp m)
  deriving instance DomRenderHook t m => DomRenderHook t (PostBuildT t m)
  deriving instance DomRenderHook t m => DomRenderHook t (QueryT t q m)
  
  {-# DEPRECATED liftElementConfig "Use 'id' instead; this function is no longer necessary" #-}
  liftElementConfig :: ElementConfig er t s -> ElementConfig er t s
  liftElementConfig = id
  
  class Monad m => HasDocument m where
    askDocument :: m (RawDocument (DomBuilderSpace m))
    default askDocument
      :: ( m ~ f m'
         , RawDocument (DomBuilderSpace m) ~ RawDocument (DomBuilderSpace m')
         , MonadTrans f
         , HasDocument m'
         )
      => m (RawDocument (DomBuilderSpace m))
    askDocument = lift askDocument
  
  instance HasDocument m => HasDocument (ReaderT r m)
  instance HasDocument m => HasDocument (EventWriterT t w m)
  instance HasDocument m => HasDocument (DynamicWriterT t w m)
  instance HasDocument m => HasDocument (PostBuildT t m)
  instance HasDocument m => HasDocument (RequesterT t request response m)
  instance HasDocument m => HasDocument (QueryT t q m)
  
  class HasSetValue a where
    type SetValue a :: Type
    setValue :: Lens' a (SetValue a)
  
  instance Reflex t => HasSetValue (TextAreaElementConfig er t m) where
    type SetValue (TextAreaElementConfig er t m) = Event t Text
    setValue = textAreaElementConfig_setValue
  