-----------------------------------------------------------------------------
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE ExistentialQuantification  #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE ScopedTypeVariables        #-}
{-# LANGUAGE DerivingStrategies         #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE RecordWildCards            #-}
{-# LANGUAGE DeriveAnyClass             #-}
{-# LANGUAGE StaticPointers             #-}
{-# LANGUAGE DeriveGeneric              #-}
{-# LANGUAGE DeriveFunctor              #-}
{-# LANGUAGE LambdaCase                 #-}
{-# LANGUAGE DataKinds                  #-}
{-# LANGUAGE CPP                        #-}
-----------------------------------------------------------------------------
{-# OPTIONS_GHC -Wno-orphans #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  Miso.Types
-- 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
--
-- = Overview
--
-- "Miso.Types" defines every core type that miso applications are built
-- from. It is re-exported in its entirety by "Miso", so most application
-- code never needs to import it directly.
--
-- = The Component record
--
-- @'Component' context props model action@ is the central record type. It
-- wires together the MVU loop and all supporting runtime configuration:
--
-- @
-- data 'Component' context props model action = Component
--   { model           :: model
--   , hydrateModel    :: Maybe (IO model)
--   , update          :: action -> 'Miso.Effect.Effect' context props model action
--   , view            :: context -> props -> model -> 'View' context action
--   , useContext      :: Bool
--   , subs            :: ['Miso.Effect.Sub' action]
--   , styles          :: ['CSS']
--   , scripts         :: ['JS']
--   , mountPoint      :: Maybe 'MountPoint'
--   , logLevel        :: 'LogLevel'
--   , mailbox         :: Value -> Maybe action
--   , eventPropagation :: Bool
--   , mount           :: Maybe action
--   , unmount         :: Maybe action
--   , onPropsChanged  :: Maybe (props -> props -> action)
--   }
-- @
--
-- Use the 'component' smart constructor to build one with sane defaults,
-- then override only the fields you need:
--
-- @
-- myApp :: 'App' Model Action
-- myApp = ('component' initialModel update view)
--   { 'subs'   = [ mySub ]
--   , 'styles' = [ 'Href' \"style.css\" (False :: 'CacheBust') ]
--   }
-- @
--
-- = The View type
--
-- @'View' context action@ is miso's virtual DOM tree. Its four constructors
-- map to the four node kinds the runtime handles:
--
-- * 'VNode' — a regular DOM element (@\<div\>@, @\<svg\>@, …)
-- * 'VText' — a text node
-- * 'VComp' — an embedded child 'Component'
-- * 'VFrag' — a keyless group of siblings (no wrapper element)
--
-- = Key types at a glance
--
-- ['Component'] full MVU application\/component record
-- ['App'] alias for @'Component' () () model action@
-- ['View'] virtual DOM node
-- ['Attribute'] DOM property, class list, event handler, or style
-- ['Namespace'] @HTML@ \| @SVG@ \| @MATHML@
-- ['Key'] reconciliation hint for list diffing
-- ['CSS'] stylesheet reference (@Href@, @Style@, @Sheet@)
-- ['JS'] script reference (@Src@, @Script@, @Module@, …)
-- ['LogLevel'] debug verbosity (@Off@, @DebugHydrate@, …)
-- ['URI'] parsed URL (path + query string + fragment)
--
-- = Text combinators
--
-- * 'text' — create a text node (HTML-escaped in SSR mode)
-- * 'textRaw' — create a text node without HTML escaping
-- * 'text_' — concatenate a list of strings with a space separator
-- * 'textKey' / 'textKey_' — keyed variants for efficient list diffing
-- * 'htmlEncode' — manually escape @< > & \" \'@
--
-- = Component mounting
--
-- * @\"key\" '+>' comp@ — mount a child component with a key
-- * 'mount_' — mount without a key (unsafe in dynamic lists)
-- * 'mountWithProps' / 'mountWithProps_' — mount with explicit @props@
-- * 'mountUseContext' — mount without a key, subscribed to @context@ updates
-- * 'vcomp' / 'vcomp_' (with 'mountStatic_' \/ 'mountStaticWithProps' \/
--   'mountStaticUseContext') — static-key mounting; the compile-time
--   'GHC.StaticPtr.StaticKey' already provides identity, so unlike the
--   non-static combinators there is no keyed variant
--
-- __Under the Lynx dual-thread (@NATIVE@) backend, always use 'vcomp' \/
-- 'vcomp_' — never '+>' \/ 'mount_' \/ 'mountWithProps' \/ 'mountWithProps_' \/
-- 'mountUseContext'.__ The non-static combinators build a component with no
-- 'GHC.StaticPtr.StaticKey'; anything mounted with them /after/ the initial
-- frame (e.g. inside a list or behind a conditional) never registers a
-- main-thread mirror on the MTS, which silently drops every @OnStatic@
-- (main-thread) event handler inside that subtree for the component's whole
-- lifetime. This is invisible outside of a console error — there is no type
-- error and no runtime crash. GHC emits a warning at every use site of the
-- non-static combinators when built with @NATIVE@ as a reminder.
--
-- = Fragment combinators
--
-- * 'fragment' / 'vfrag' — group siblings without a wrapper element
-- * 'fragment_' / 'vfrag_' — keyed fragment
--
-- = Conditional view utilities
--
-- * 'optionalAttrs' — add attributes conditionally
-- * 'optionalVoidAttrs' — same for void (no-children) elements
-- * 'optionalChildren' — add children conditionally
--
-- = See also
--
-- * "Miso.Effect" — 'Miso.Effect.Effect', 'Miso.Effect.Sub', 'Miso.Effect.Sink'
-- * "Miso.Html.Element" — element smart constructors built on 'node'
-- * "Miso.Html.Property" — attribute constructors built on 'Attribute'
-- * "Miso.Html.Render" — SSR serialisation via 'Miso.Html.Render.ToHtml'
-- * "Miso.Router" — 'Miso.Router.URI' parsing and pretty-printing
----------------------------------------------------------------------------
module Miso.Types
  ( -- ** Types
    App
  , Component     (..)
  , ComponentId
  , SomeComponent (..)
  , SomeStaticComponent         (..)
  , EventHandler  (..)
  , View          (..)
  , Key           (..)
  , Attribute     (..)
  , Namespace     (..)
  , CSS           (..)
  , JS            (..)
  , LogLevel      (..)
  , VTree         (..)
  , VTreeType     (..)
  , Hydrate       (..)
  , Tag
  , DirectEvents
  , CacheBust
  , MountPoint
  , DOMRef
  , Events
  , Phase         (..)
  , URI           (..)
  -- ** Classes
  , ToKey         (..)
  -- ** Smart Constructors
  , emptyURI
  , component
  -- ** Event handler smart constructor
  , event
  -- ** Component mounting
  , vcomp
  , vcomp_
  , (+>)
  , mount_
  , mountUseContext
  , mountWithProps_
  , mountWithProps
  , mountStatic_
  , mountStaticWithProps
  , mountStaticUseContext
  -- ** Fragment combinators
  , fragment
  , fragment_
  , vfrag
  , vfrag_
  -- ** Utils
  , getMountPoint
  , optionalAttrs
  , optionalVoidAttrs
  , optionalChildren
  , prettyURI
  , prettyQueryString
  -- *** Combinators
  , node
  , nodeDirectEvents
  , vnode
  , text
  , vtext
  , text_
  , textRaw
  , textKey
  , textKey_
  , htmlEncode
  -- *** MisoString
  , MisoString
  , toMisoString
  , fromMisoString
  , ms
  ) where
-----------------------------------------------------------------------------
import           Data.Function
import qualified Data.Map.Strict as M
import           Data.Set (Set)
import qualified Data.Set as S
import           Data.Maybe (fromMaybe, isJust)
import           Data.String (IsString, fromString)
import qualified Data.Text as T
import           GHC.Generics
import           GHC.StaticPtr
import           Prelude
-----------------------------------------------------------------------------
import           Miso.DSL
import           Miso.Effect (Effect, Sub, Sink, DOMRef, ComponentId)
import           Miso.Event.Types
import qualified Miso.Event.Decoder
import           Miso.JSON (Value, ToJSON(..), encode)
#ifdef NATIVE
import           Miso.JSON (FromJSON(..))
#endif
import qualified Miso.String as MS
import           Miso.String (ToMisoString, MisoString, toMisoString, ms, fromMisoString)
import           Miso.CSS.Types (StyleSheet)
-----------------------------------------------------------------------------
-- | Application entry point
data Component context props model action
  = Component
  { forall context props model action.
Component context props model action -> model
model :: model
  -- ^ Initial model
  , forall context props model action.
Component context props model action -> Maybe (IO model)
hydrateModel :: Maybe (IO model)
  -- ^ Optional 'IO' to load component 'model' state, such as reading data from page.
  --   The resulting 'model' is only used during initial hydration, not on remounts.
  --
  --   __Note:__ only synchronous 'IO' should be used here (e.g. reading from
  --   @localStorage@ via 'getLocalStorage').
  , forall context props model action.
Component context props model action
-> action -> Effect context props model action
update :: action -> Effect context props model action
  -- ^ Updates model, optionally providing effects.
  , forall context props model action.
Component context props model action
-> context -> props -> model -> View context model action
view :: context -> props -> model -> View context model action
  -- ^ Draws 'View'. Receives the app-global @context@, the @props@ passed by the
  --   parent, and the current @model@.
  , forall context props model action.
Component context props model action -> Bool
useContext :: Bool
  -- ^ Whether this t'Miso.Types.Component' should be re-rendered when the
  --   app-global @context@ changes (see 'Miso.Effect.modifyContext').
  --
  --   This controls whether a component __reacts__ to context changes, not
  --   whether it may __change__ the context. A component may call
  --   'Miso.Effect.modifyContext' \/ 'Miso.Effect.putContext' with
  --   @useContext = False@; it simply won't re-render in response. Enable it on
  --   the (usually nested) components whose 'view' reads the @context@ and must
  --   refresh when it changes.
  --
  --   Defaults to 'False'.
  --
  -- @since 1.9.0.0
  , forall context props model action.
Component context props model action -> [Sub action]
subs :: [ Sub action ]
  -- ^ Subscriptions to run during application lifetime
  , forall context props model action.
Component context props model action -> [CSS]
styles :: [CSS]
  -- ^ CSS styles expressed as either a URL ('Href') or as 'Style' text.
  -- These styles are appended dynamically to the \<head\> section of your HTML page
  -- before the initial draw on \<body\> occurs.
  --
  -- __Note:__ This field should only be used in development mode.
  --
  -- @since 1.9.0.0
  , forall context props model action.
Component context props model action -> [JS]
scripts :: [JS]
  -- ^ JavaScript scripts expressed as either a URL ('Src') or raw JS text.
  -- These scripts are appended dynamically to the \<head\> section of your HTML page
  -- before the initial draw on \<body\> occurs.
  --
  -- __Note:__ This field should only be used in development mode.
  --
  -- @since 1.9.0.0
  , forall context props model action.
Component context props model action -> Maybe MisoString
mountPoint :: Maybe MountPoint
  -- ^ ID of the root element for DOM diff.
  -- If 'Nothing' is provided, the entire document body is used as a mount point.
  , forall context props model action.
Component context props model action -> LogLevel
logLevel :: LogLevel
  -- ^ Debugging configuration for prerendering and event delegation
  , forall context props model action.
Component context props model action -> Value -> Maybe action
mailbox :: Value -> Maybe action
  -- ^ Receives mail from other components
  --
  -- @since 1.9.0.0
  , forall context props model action.
Component context props model action -> Bool
eventPropagation :: Bool
  -- ^ Should events bubble up past the t'Miso.Types.Component' barrier.
  --
  -- Defaults to t'False'
  --
  -- @since 1.9.0.0
  , forall context props model action.
Component context props model action -> Maybe action
mount :: Maybe action
  -- ^ action to execute during t'Miso.Types.Component' mount phase.
  --
  -- @since 1.9.0.0
  , forall context props model action.
Component context props model action -> Maybe action
unmount :: Maybe action
  -- ^ action to execute during t'Miso.Types.Component' unmount phase.
  --
  -- @since 1.9.0.0
  , forall context props model action.
Component context props model action
-> Maybe (props -> props -> action)
onPropsChanged :: Maybe (props -> props -> action)
  -- ^ action to execute when 'Component' @props@ have changed (a.k.a. @props@ phase).
  -- Receives previous @props@ and current @props@ as arguments.
  --
  -- @since 1.11.0.0
  }
-----------------------------------------------------------------------------
-- | @mountPoint@ for t'Miso.Types.Component', e.g "body"
type MountPoint = MisoString
-----------------------------------------------------------------------------
-- | Allow users to express 'CSS' and append it to \<head\> before the first draw
--
-- > 'Href' "http://domain.com/style.css" ('True' :: 'CacheBust')
-- > 'Style' "body { background-color: red; }"
--
data CSS
  = Href MisoString CacheBust
  -- ^ 'URL' linking to hosted 'CSS'
  | Style MisoString
  -- ^ Raw 'CSS' content in a 'Miso.Html.Element.style_' tag
  | Sheet StyleSheet
  -- ^ 'CSS' built with "Miso.CSS"
  deriving (Int -> CSS -> ShowS
[CSS] -> ShowS
CSS -> String
(Int -> CSS -> ShowS)
-> (CSS -> String) -> ([CSS] -> ShowS) -> Show CSS
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CSS -> ShowS
showsPrec :: Int -> CSS -> ShowS
$cshow :: CSS -> String
show :: CSS -> String
$cshowList :: [CSS] -> ShowS
showList :: [CSS] -> ShowS
Show, CSS -> CSS -> Bool
(CSS -> CSS -> Bool) -> (CSS -> CSS -> Bool) -> Eq CSS
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CSS -> CSS -> Bool
== :: CSS -> CSS -> Bool
$c/= :: CSS -> CSS -> Bool
/= :: CSS -> CSS -> Bool
Eq)
-----------------------------------------------------------------------------
-- | Parameter used to indicate cache busting logic should be used.
-- If 'True' this will append a timestamp to the query. This will force cache
-- invalidation on the browser, causing a fetch of the resources.
--
type CacheBust = Bool
-----------------------------------------------------------------------------
-- | Allow users to express JS and append it to \<head\> before the first draw
--
-- This is meant to be useful in development only.
--
-- @
-- 'Src' \"http:\/\/example.com\/script.js\" ('False' :: 'CacheBust')
-- 'Script' "alert(\"hi\");"
-- 'ImportMap' [ "key" '=:' "value" ]
-- 'Module' "console.log(\"hi\");"
-- @
--
-- @since 1.9.0.0
data JS
  = Src MisoString CacheBust
  -- ^ URL linking to hosted JS
  | Script MisoString
  -- ^ Raw JS content that you would enter in a \<script\> tag
  | Module MisoString
  -- ^ Raw JS module content that you would enter in a \<script type="module"\> tag.
  -- See [script type](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/script/type)
  | ImportMap [(MisoString,MisoString)]
  -- ^ Import map content in a \<script type="importmap"\> tag.
  -- See [importmap](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/script/type/importmap)
  deriving (Int -> JS -> ShowS
[JS] -> ShowS
JS -> String
(Int -> JS -> ShowS)
-> (JS -> String) -> ([JS] -> ShowS) -> Show JS
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> JS -> ShowS
showsPrec :: Int -> JS -> ShowS
$cshow :: JS -> String
show :: JS -> String
$cshowList :: [JS] -> ShowS
showList :: [JS] -> ShowS
Show, JS -> JS -> Bool
(JS -> JS -> Bool) -> (JS -> JS -> Bool) -> Eq JS
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: JS -> JS -> Bool
== :: JS -> JS -> Bool
$c/= :: JS -> JS -> Bool
/= :: JS -> JS -> Bool
Eq)
-----------------------------------------------------------------------------
-- | Convenience for extracting mount point
getMountPoint :: Maybe MisoString -> MisoString
getMountPoint :: Maybe MisoString -> MisoString
getMountPoint = MisoString -> Maybe MisoString -> MisoString
forall a. a -> Maybe a -> a
fromMaybe MisoString
"body"
-----------------------------------------------------------------------------
-- | Smart constructor for t'Miso.Types.Component' with sane defaults.
component
  :: model
  -- ^ model
  -> (action -> Effect context props model action)
  -- ^ update
  -> (context -> props -> model -> View context model action)
  -- ^ view
  -> Component context props model action
component :: forall model action context props.
model
-> (action -> Effect context props model action)
-> (context -> props -> model -> View context model action)
-> Component context props model action
component model
m action -> Effect context props model action
u context -> props -> model -> View context model action
v = Component
  { model :: model
model = model
m
  , hydrateModel :: Maybe (IO model)
hydrateModel = Maybe (IO model)
forall a. Maybe a
Nothing
  , update :: action -> Effect context props model action
update = action -> Effect context props model action
u
  , view :: context -> props -> model -> View context model action
view = context -> props -> model -> View context model action
v
  , useContext :: Bool
useContext = Bool
False
  , subs :: [Sub action]
subs = []
  , styles :: [CSS]
styles = []
  , scripts :: [JS]
scripts = []
  , mountPoint :: Maybe MisoString
mountPoint = Maybe MisoString
forall a. Maybe a
Nothing
  , logLevel :: LogLevel
logLevel = LogLevel
Off
  , mailbox :: Value -> Maybe action
mailbox = Maybe action -> Value -> Maybe action
forall a b. a -> b -> a
const Maybe action
forall a. Maybe a
Nothing
  , eventPropagation :: Bool
eventPropagation = Bool
False
  , mount :: Maybe action
mount = Maybe action
forall a. Maybe a
Nothing
  , unmount :: Maybe action
unmount = Maybe action
forall a. Maybe a
Nothing
  , onPropsChanged :: Maybe (props -> props -> action)
onPropsChanged = Maybe (props -> props -> action)
forall a. Maybe a
Nothing
  }
-----------------------------------------------------------------------------
-- | A miso application is a top-level t'Miso.Types.Component'. Its app-global
-- @context@ defaults to @()@ (see 'Miso.startAppWithContext' to supply a
-- non-trivial context), and its @props@ are fixed to @()@.
--
type App model action = Component () () model action
-----------------------------------------------------------------------------
-- | Logging configuration for debugging Miso internals (useful to see if prerendering is successful)
data LogLevel
  = Off
  -- ^ No debug logging, the default value used in 'component'
  | DebugHydrate
  -- ^ Will warn if the structure or properties of the
  -- DOM vs. Virtual DOM differ during prerendering.
  | DebugEvents
  -- ^ Will warn if an event cannot be routed to the Haskell event
  -- handler that raised it. Also will warn if an event handler is
  -- being used, yet it's not being listened for by the event
  -- delegator mount point.
  | DebugAll
  -- ^ Logs on all of the above
  deriving (Int -> LogLevel -> ShowS
[LogLevel] -> ShowS
LogLevel -> String
(Int -> LogLevel -> ShowS)
-> (LogLevel -> String) -> ([LogLevel] -> ShowS) -> Show LogLevel
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> LogLevel -> ShowS
showsPrec :: Int -> LogLevel -> ShowS
$cshow :: LogLevel -> String
show :: LogLevel -> String
$cshowList :: [LogLevel] -> ShowS
showList :: [LogLevel] -> ShowS
Show, LogLevel -> LogLevel -> Bool
(LogLevel -> LogLevel -> Bool)
-> (LogLevel -> LogLevel -> Bool) -> Eq LogLevel
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: LogLevel -> LogLevel -> Bool
== :: LogLevel -> LogLevel -> Bool
$c/= :: LogLevel -> LogLevel -> Bool
/= :: LogLevel -> LogLevel -> Bool
Eq)
-----------------------------------------------------------------------------
-- | Tag type, (e.g. 'div_', 'p_')
--
-- Meant to indicate the type of element being created.
-- Used as the first argument to @document.createElement@ for the web backend.
--
type Tag = MisoString
-----------------------------------------------------------------------------
-- | The set of events an element dispatches /directly/ on itself rather than
-- by bubbling to the delegated mount listener. Empty for HTML\/SVG\/MathML;
-- populated for Lynx native elements (see 'nodeDirectEvents').
type DirectEvents = Set MisoString
-----------------------------------------------------------------------------
-- | Core type for constructing a virtual DOM in Haskell
data View context model action
  = VNode Namespace Tag [Attribute model action] [View context model action] DirectEvents
    -- ^ The final 'Set' names the events this element dispatches /directly/ on
    -- itself rather than by bubbling to the delegated mount listener (Lynx
    -- native @input@\/@scroll@\/… events). Empty for all HTML\/SVG\/MathML
    -- elements. See 'nodeDirectEvents'.
  | VText (Maybe Key) MisoString
  | VComp (SomeComponent context)
  | forall props . VCompStatic (StaticPtr (SomeStaticComponent props context)) props
    -- ^ An embedded child 'Component'. The 'StaticPtr' holds only the closed
    -- @props -> component@ constructor ('SomeStaticComponent'); the @props@ value — often
    -- derived from the parent's @model@ — rides alongside and crosses the
    -- dual-thread (Lynx) boundary as JSON. The no-props case uses @props ~ ()@
    -- (see 'mount_'). This split is what lets a mount escape @static@\'s
    -- closedness restriction. See 'vcomp'. This is necessary for lynx dual-thread
    -- in order to transfer context, props, event handlers etc.
  | VFrag (Maybe Key) [View context model action]
-----------------------------------------------------------------------------
-- | Existential wrapper allowing nesting of t'Miso.Types.Component' in t'Miso.Types.Component'.
--
-- The @context@ type parameter is shared with the enclosing 'View', so every
-- nested t'Miso.Types.Component' participates in the same app-global context.
data SomeComponent context
#ifdef NATIVE
   = forall model action props . (FromJSON model, ToJSON model, FromJSON action, ToJSON action, FromJSON props, ToJSON props, Eq context, Eq model, Eq props)
#else
   = forall model action props . (Eq context, Eq model, Eq props)
#endif
  => SomeComponent (Maybe Key) props (Component context props model action)
-----------------------------------------------------------------------------
-- | A closed @props -> component@ constructor, bundled with the serialization
-- dictionaries needed to move @props@ across the dual-thread (Lynx) boundary.
--
-- Unlike 'SomeComponent', the @props@ type parameter is /preserved/ (not
-- existential). This lets 'vcompWith' statically require the runtime @props@
-- value to match the constructor, while the packed 'FromJSON' \/ 'ToJSON'
-- dictionaries are recovered on the MTS after 'unsafeLookupStaticPtr' derefs
-- the 'StaticPtr' — so the MTS can decode the wire @props@ at exactly this
-- type and rebuild the 'SomeComponent'.
--
-- Built with 'mount_' \/ 'mountWithProps' \/ '(+>)'; consumed by 'vcomp'.
data SomeStaticComponent props context
#ifdef NATIVE
  = (Eq props, FromJSON props, ToJSON props)
  => SomeStaticComponent (props -> SomeComponent context)
#else
  = Eq props
  => SomeStaticComponent (props -> SomeComponent context)
#endif
-----------------------------------------------------------------------------
-- | Create a fragment (keyless).
--
-- A fragment groups multiple sibling 'View' nodes without introducing
-- an extra DOM element.
--
-- Synonym for `fragment'
--
-- @since 1.10.0.0
vfrag :: [View context model action] -> View context model action
vfrag :: forall context model action.
[View context model action] -> View context model action
vfrag = [View context model action] -> View context model action
forall context model action.
[View context model action] -> View context model action
fragment
-----------------------------------------------------------------------------
-- | Create a fragment (keyless).
--
-- A fragment groups multiple sibling 'View' nodes without introducing
-- an extra DOM element.
--
-- @since 1.10.0.0
fragment :: [View context model action] -> View context model action
fragment :: forall context model action.
[View context model action] -> View context model action
fragment = Maybe Key
-> [View context model action] -> View context model action
forall context model action.
Maybe Key
-> [View context model action] -> View context model action
VFrag Maybe Key
forall a. Maybe a
Nothing
-----------------------------------------------------------------------------
-- | Like 'fragment', but keyed for efficient diffing.
--
-- @since 1.10.0.0
vfrag_ :: MisoString -> [View context model action] -> View context model action
vfrag_ :: forall context model action.
MisoString
-> [View context model action] -> View context model action
vfrag_ MisoString
key = Maybe Key
-> [View context model action] -> View context model action
forall context model action.
Maybe Key
-> [View context model action] -> View context model action
VFrag (Key -> Maybe Key
forall a. a -> Maybe a
Just (MisoString -> Key
Key MisoString
key))
-----------------------------------------------------------------------------
-- | Like 'fragment', but keyed for efficient diffing.
--
-- @since 1.10.0.0
fragment_ :: MisoString -> [View context model action] -> View context model action
fragment_ :: forall context model action.
MisoString
-> [View context model action] -> View context model action
fragment_ MisoString
key = Maybe Key
-> [View context model action] -> View context model action
forall context model action.
Maybe Key
-> [View context model action] -> View context model action
VFrag (Key -> Maybe Key
forall a. a -> Maybe a
Just (MisoString -> Key
Key MisoString
key))
-----------------------------------------------------------------------------
-- | t'Miso.Types.Component' mounting combinator
--
-- Used in the @view@ function to mount a t'Miso.Types.Component' on any 'VNode'.
--
-- @
-- "component-id" +> component model noop $ \\m ->
--   div_ [ id_ "foo" ] [ text (ms m) ]
-- @
--
-- __Warning (Lynx dual-thread \/ @NATIVE@):__ this builds a 'VComp' with no
-- 'GHC.StaticPtr.StaticKey'. A component mounted this way as part of the
-- /initial/ frame is fine (the MTS independently reconstructs it while
-- painting its own first frame). But if it is mounted /later/ — e.g. inside
-- a list or behind a conditional, appearing only after the first frame — the
-- MTS has no other way to learn of it, so it never registers a mirror
-- t'Miso.Types.ComponentState' for it, and any main-thread (@OnStatic@)
-- event handler inside that subtree silently fails to dispatch for the
-- component's whole lifetime, with only a console error as a clue. Use
-- 'vcomp' with 'mountStaticWithProps' instead for anything that may mount
-- after the initial frame under @NATIVE@ — the compile-time
-- 'GHC.StaticPtr.StaticKey' already supplies the identity a manual key would,
-- no explicit key needed.
--
-- @since 1.9.0.0
(+>)
  :: forall context childModel childAction model action .
#ifdef NATIVE
     (Eq context, Eq childModel, FromJSON childModel, ToJSON childModel, FromJSON childAction, ToJSON childAction)
#else
     (Eq context, Eq childModel)
#endif
  => MisoString
  -- ^ 'VComp' 'key_'
  -> Component context () childModel childAction
  -- ^ 'Component'
  -> View context model action
infixr 0 +>
#ifdef NATIVE
{-# WARNING (+>) "[NATIVE] '+>' has no StaticKey; a component mounted with it after the initial frame silently drops OnStatic handlers inside it. Use 'vcomp' with 'mountStaticWithProps' instead." #-}
#endif
MisoString
key +> :: forall context childModel childAction model action.
(Eq context, Eq childModel, FromJSON childModel, ToJSON childModel,
 FromJSON childAction, ToJSON childAction) =>
MisoString
-> Component context () childModel childAction
-> View context model action
+> Component context () childModel childAction
child = SomeComponent context -> View context model action
forall context model action.
SomeComponent context -> View context model action
VComp (Maybe Key
-> ()
-> Component context () childModel childAction
-> SomeComponent context
forall context model action props.
(FromJSON model, ToJSON model, FromJSON action, ToJSON action,
 FromJSON props, ToJSON props, Eq context, Eq model, Eq props) =>
Maybe Key
-> props
-> Component context props model action
-> SomeComponent context
SomeComponent (Key -> Maybe Key
forall a. a -> Maybe a
Just (MisoString -> Key
forall key. ToKey key => key -> Key
toKey MisoString
key)) () Component context () childModel childAction
child)
-----------------------------------------------------------------------------
-- | t'Miso.Types.Component' mounting combinator.
--
-- Note: only use this if you're certain you won't be diffing two t'Miso.Types.Component'
-- against each other. Otherwise, you will need a key to distinguish between
-- the two t'Miso.Types.Component', to ensure unmounting and mounting occurs.
--
-- It takes only the @component@ and yields a closed @props -> component@
-- constructor ('SomeStaticComponent') suitable for @static@ — the @props@ value
-- is /not/ supplied here, but later at the 'vcomp' site, so a parent can pass
-- runtime @props@ (e.g. derived from its own @model@) without an explicit lambda:
--
-- Static mounting automatically provides the 'key_' at compile time (via 'GHC.StaticPtr.staticKey').
-- So the user doesn't need to use the '+>' combinators.
--
-- @
-- vcomp (model ^. field) (static (mountStaticWithProps child))
-- @
--
-- @since 1.11.0.0
mountStaticWithProps
#ifdef NATIVE
  :: (Eq context, Eq props, Eq model, FromJSON model, ToJSON model, FromJSON action, ToJSON action, FromJSON props, ToJSON props)
#else
  :: (Eq context, Eq props, Eq model)
#endif
  => Component context props model action
  -- ^ 'Component' to mount
  -> SomeStaticComponent props context
mountStaticWithProps :: forall context props model action.
(Eq context, Eq props, Eq model, FromJSON model, ToJSON model,
 FromJSON action, ToJSON action, FromJSON props, ToJSON props) =>
Component context props model action
-> SomeStaticComponent props context
mountStaticWithProps Component context props model action
child = (props -> SomeComponent context)
-> SomeStaticComponent props context
forall props context.
(Eq props, FromJSON props, ToJSON props) =>
(props -> SomeComponent context)
-> SomeStaticComponent props context
SomeStaticComponent (\props
props -> Maybe Key
-> props
-> Component context props model action
-> SomeComponent context
forall context model action props.
(FromJSON model, ToJSON model, FromJSON action, ToJSON action,
 FromJSON props, ToJSON props, Eq context, Eq model, Eq props) =>
Maybe Key
-> props
-> Component context props model action
-> SomeComponent context
SomeComponent Maybe Key
forall a. Maybe a
Nothing props
props Component context props model action
child)
-----------------------------------------------------------------------------
-- | t'Miso.Types.Component' mounting combinator, with @props@ supplied directly.
--
-- __Warning (Lynx dual-thread \/ @NATIVE@):__ see the note on '(+>)' — this
-- also builds an unkeyed 'VComp' with no 'GHC.StaticPtr.StaticKey', so the
-- same caveat applies: components mounted with this /after/ the initial
-- frame never get a main-thread mirror registered, silently breaking
-- @OnStatic@ handlers inside them. Use 'vcomp' with 'mountStaticWithProps'
-- instead for anything that may mount dynamically under @NATIVE@.
mountWithProps
  :: forall context props childModel childAction model action .
#ifdef NATIVE
     (Eq context, Eq props, Eq childModel, FromJSON childModel, ToJSON childModel, FromJSON childAction, ToJSON childAction, FromJSON props, ToJSON props)
#else
     (Eq context, Eq props, Eq childModel)
#endif
  => props
  -> Component context props childModel childAction
  -- ^ 'Component' to mount
  -> View context model action
#ifdef NATIVE
{-# WARNING mountWithProps "[NATIVE] 'mountWithProps' has no StaticKey; a component mounted with it after the initial frame silently drops OnStatic handlers inside it. Use 'vcomp' with 'mountStaticWithProps' instead." #-}
#endif
mountWithProps :: forall context props childModel childAction model action.
(Eq context, Eq props, Eq childModel, FromJSON childModel,
 ToJSON childModel, FromJSON childAction, ToJSON childAction,
 FromJSON props, ToJSON props) =>
props
-> Component context props childModel childAction
-> View context model action
mountWithProps props
props Component context props childModel childAction
comp = SomeComponent context -> View context model action
forall context model action.
SomeComponent context -> View context model action
VComp (Maybe Key
-> props
-> Component context props childModel childAction
-> SomeComponent context
forall context model action props.
(FromJSON model, ToJSON model, FromJSON action, ToJSON action,
 FromJSON props, ToJSON props, Eq context, Eq model, Eq props) =>
Maybe Key
-> props
-> Component context props model action
-> SomeComponent context
SomeComponent Maybe Key
forall a. Maybe a
Nothing props
props Component context props childModel childAction
comp)
-----------------------------------------------------------------------------
-- | t'Miso.Types.Component' mounting combinator, keyed, with @props@ supplied directly.
--
-- __Warning (Lynx dual-thread \/ @NATIVE@):__ see the note on '(+>)' — this
-- also builds a 'VComp' with no 'GHC.StaticPtr.StaticKey' (the key here is
-- just the diffing 'Key', unrelated), so the same caveat applies: mounted
-- /after/ the initial frame, it never gets a main-thread mirror registered,
-- silently breaking @OnStatic@ handlers inside it. Use 'vcomp' with
-- 'mountStaticWithProps' instead for anything that may mount dynamically
-- under @NATIVE@ — the compile-time 'GHC.StaticPtr.StaticKey' already
-- supplies the identity a manual key would, no explicit key needed.
mountWithProps_
  :: forall context props childModel childAction model action .
#ifdef NATIVE
     (Eq context, Eq props, Eq childModel, FromJSON childAction, FromJSON childModel, ToJSON childModel, ToJSON childAction, FromJSON props, ToJSON props)
#else
     (Eq context, Eq childModel, Eq props)
#endif
  => MisoString
  -> props
  -> Component context props childModel childAction
  -- ^ 'Component' to mount
  -> View context model action
#ifdef NATIVE
{-# WARNING mountWithProps_ "[NATIVE] 'mountWithProps_' has no StaticKey; a component mounted with it after the initial frame silently drops OnStatic handlers inside it. Use 'vcomp' with 'mountStaticWithProps' instead." #-}
#endif
mountWithProps_ :: forall context props childModel childAction model action.
(Eq context, Eq props, Eq childModel, FromJSON childAction,
 FromJSON childModel, ToJSON childModel, ToJSON childAction,
 FromJSON props, ToJSON props) =>
MisoString
-> props
-> Component context props childModel childAction
-> View context model action
mountWithProps_ MisoString
key props
props Component context props childModel childAction
child = SomeComponent context -> View context model action
forall context model action.
SomeComponent context -> View context model action
VComp (Maybe Key
-> props
-> Component context props childModel childAction
-> SomeComponent context
forall context model action props.
(FromJSON model, ToJSON model, FromJSON action, ToJSON action,
 FromJSON props, ToJSON props, Eq context, Eq model, Eq props) =>
Maybe Key
-> props
-> Component context props model action
-> SomeComponent context
SomeComponent (Key -> Maybe Key
forall a. a -> Maybe a
Just (MisoString -> Key
Key MisoString
key)) props
props Component context props childModel childAction
child)
-----------------------------------------------------------------------------
-- | t'Miso.Types.Component' mounting combinator.
--
-- Note: only use this if you're certain you won't be diffing two t'Miso.Types.Component'
-- against each other. Otherwise, you will need a key to distinguish between
-- the two t'Miso.Types.Component', to ensure unmounting and mounting occurs.
--
-- @
-- mountStatic_ $ component model noop $ \\m ->
--  div_ [ id_ "foo" ] [ text (ms m) ]
-- @
--
-- @since 1.9.0.0
mountStatic_
#ifdef NATIVE
  :: (Eq context, Eq model, FromJSON model, ToJSON model, FromJSON action, ToJSON action)
#else
  :: (Eq context, Eq model)
#endif
  => Component context () model action
  -- ^ 'Component' to mount
  -> SomeStaticComponent () context
mountStatic_ :: forall context model action.
(Eq context, Eq model, FromJSON model, ToJSON model,
 FromJSON action, ToJSON action) =>
Component context () model action -> SomeStaticComponent () context
mountStatic_ Component context () model action
child = (() -> SomeComponent context) -> SomeStaticComponent () context
forall props context.
(Eq props, FromJSON props, ToJSON props) =>
(props -> SomeComponent context)
-> SomeStaticComponent props context
SomeStaticComponent (SomeComponent context -> () -> SomeComponent context
forall a b. a -> b -> a
const (Maybe Key
-> () -> Component context () model action -> SomeComponent context
forall context model action props.
(FromJSON model, ToJSON model, FromJSON action, ToJSON action,
 FromJSON props, ToJSON props, Eq context, Eq model, Eq props) =>
Maybe Key
-> props
-> Component context props model action
-> SomeComponent context
SomeComponent Maybe Key
forall a. Maybe a
Nothing () Component context () model action
child))
-----------------------------------------------------------------------------
-- | t'Miso.Types.Component' mounting combinator.
--
-- Note: only use this if you're certain you won't be diffing two t'Miso.Types.Component'
-- against each other. Otherwise, you will need a key to distinguish between
-- the two t'Miso.Types.Component', to ensure unmounting and mounting occurs.
--
-- @
-- mount_ $ component model noop $ \\m ->
--  div_ [ id_ "foo" ] [ text (ms m) ]
-- @
--
-- __Warning (Lynx dual-thread \/ @NATIVE@):__ see the note on '(+>)' — this
-- also builds a 'VComp' with no 'GHC.StaticPtr.StaticKey', so the same
-- caveat applies: mounted /after/ the initial frame, it never gets a
-- main-thread mirror registered, silently breaking @OnStatic@ handlers
-- inside it. Use 'vcomp_' with 'mountStatic_' instead for anything that may
-- mount dynamically under @NATIVE@.
--
-- @since 1.9.0.0
mount_
  :: forall context childModel childAction model action .
#ifdef NATIVE
     (Eq context, Eq childModel, FromJSON childModel, ToJSON childModel, FromJSON childAction, ToJSON childAction)
#else
     (Eq context, Eq childModel)
#endif
  => Component context () childModel childAction
  -- ^ 'Component' to mount
  -> View context model action
#ifdef NATIVE
{-# WARNING mount_ "[NATIVE] 'mount_' has no StaticKey; a component mounted with it after the initial frame silently drops OnStatic handlers inside it. Use 'vcomp_' with 'mountStatic_' instead." #-}
#endif
mount_ :: forall context childModel childAction model action.
(Eq context, Eq childModel, FromJSON childModel, ToJSON childModel,
 FromJSON childAction, ToJSON childAction) =>
Component context () childModel childAction
-> View context model action
mount_ Component context () childModel childAction
comp = SomeComponent context -> View context model action
forall context model action.
SomeComponent context -> View context model action
VComp (Maybe Key
-> ()
-> Component context () childModel childAction
-> SomeComponent context
forall context model action props.
(FromJSON model, ToJSON model, FromJSON action, ToJSON action,
 FromJSON props, ToJSON props, Eq context, Eq model, Eq props) =>
Maybe Key
-> props
-> Component context props model action
-> SomeComponent context
SomeComponent Maybe Key
forall a. Maybe a
Nothing () Component context () childModel childAction
comp)
-----------------------------------------------------------------------------
-- | Embed a child 'Component' as a 'View'.
--
-- Smart constructor for 'VComp', mirroring 'vnode' \/ 'vtext' \/ 'vfrag'.
--
-- The 'StaticPtr' wraps only the closed @props -> component@ constructor (built
-- with 'mount_', 'mountWithProps', or '(+>)'); it must use the @static@ keyword
-- and refer to a closed, top-level binding. The @props@ value is supplied
-- /separately/ — so it may depend on the parent's @model@ — and is serialized
-- across the dual-thread boundary. The no-props case passes @()@.
--
-- No class constraints appear here: the serialization dictionaries are
-- discharged at the @static (mount_ child)@ site and recovered on the MTS from
-- the 'Props'.
--
-- @
-- div_ [] [ vcomp_ (static (mountStatic_ myComp)) ]
-- @
--
-- @since 1.12.0.0
vcomp
  :: props
  -> StaticPtr (SomeStaticComponent props context)
  -> View context model action
vcomp :: forall props context model action.
props
-> StaticPtr (SomeStaticComponent props context)
-> View context model action
vcomp = (StaticPtr (SomeStaticComponent props context)
 -> props -> View context model action)
-> props
-> StaticPtr (SomeStaticComponent props context)
-> View context model action
forall a b c. (a -> b -> c) -> b -> a -> c
flip StaticPtr (SomeStaticComponent props context)
-> props -> View context model action
forall context model action props.
StaticPtr (SomeStaticComponent props context)
-> props -> View context model action
VCompStatic
-----------------------------------------------------------------------------
vcomp_
  :: StaticPtr (SomeStaticComponent () context)
  -> View context model action
vcomp_ :: forall context model action.
StaticPtr (SomeStaticComponent () context)
-> View context model action
vcomp_ = ()
-> StaticPtr (SomeStaticComponent () context)
-> View context model action
forall props context model action.
props
-> StaticPtr (SomeStaticComponent props context)
-> View context model action
vcomp ()
-----------------------------------------------------------------------------
-- | Static t'Miso.Types.Component' mounting combinator that opts the child
-- into app-global React-style @context@ updates.
--
-- Equivalent to 'mountStatic_', but sets @useContext = True@ on the mounted
-- t'Miso.Types.Component' so it re-renders whenever the @context@ changes
-- (see 'Miso.Effect.modifyContext'). The static-key counterpart of
-- 'mountUseContext' — use this (with 'vcomp_') instead of 'mountUseContext'
-- under the Lynx dual-thread (@NATIVE@) backend.
--
-- @
-- vcomp_ (static (mountStaticUseContext myComp))
-- @
--
-- @since 1.12.0.0
mountStaticUseContext
#ifdef NATIVE
  :: (Eq context, Eq model, FromJSON model, ToJSON model, FromJSON action, ToJSON action)
#else
  :: (Eq context, Eq model)
#endif
  => Component context () model action
  -- ^ 'Component' to mount
  -> SomeStaticComponent () context
mountStaticUseContext :: forall context model action.
(Eq context, Eq model, FromJSON model, ToJSON model,
 FromJSON action, ToJSON action) =>
Component context () model action -> SomeStaticComponent () context
mountStaticUseContext Component context () model action
child =
  (() -> SomeComponent context) -> SomeStaticComponent () context
forall props context.
(Eq props, FromJSON props, ToJSON props) =>
(props -> SomeComponent context)
-> SomeStaticComponent props context
SomeStaticComponent (SomeComponent context -> () -> SomeComponent context
forall a b. a -> b -> a
const (Maybe Key
-> () -> Component context () model action -> SomeComponent context
forall context model action props.
(FromJSON model, ToJSON model, FromJSON action, ToJSON action,
 FromJSON props, ToJSON props, Eq context, Eq model, Eq props) =>
Maybe Key
-> props
-> Component context props model action
-> SomeComponent context
SomeComponent Maybe Key
forall a. Maybe a
Nothing () Component context () model action
child { useContext = True }))
-----------------------------------------------------------------------------
-- | t'Miso.Types.Component' mounting combinator that opts the child into
-- app-global React-style @context@ updates.
--
-- Equivalent to 'mount_', but sets @useContext = True@ on the mounted
-- t'Miso.Types.Component' so it re-renders whenever the @context@ changes
-- (see 'Miso.Effect.modifyContext'). Like 'mount_', this is unkeyed and so
-- unsafe when diffing two t'Miso.Types.Component' against each other.
--
-- @
-- mountUseContext $ component model noop $ \\ctx m ->
--  div_ [ id_ "foo" ] [ text (ms m) ]
-- @
--
-- __Warning (Lynx dual-thread \/ @NATIVE@):__ see the note on 'mount_' —
-- this also builds a 'VComp' with no 'GHC.StaticPtr.StaticKey', so the same
-- caveat applies: mounted /after/ the initial frame, it never gets a
-- main-thread mirror registered, silently breaking @OnStatic@ handlers
-- inside it. Use 'vcomp_' with 'mountStaticUseContext' instead under
-- @NATIVE@.
--
-- @since 1.9.0.0
mountUseContext
  :: forall context childModel childAction model action .
#ifdef NATIVE
     (Eq context, Eq childModel, FromJSON childModel, ToJSON childModel, FromJSON childAction, ToJSON childAction)
#else
     (Eq context, Eq childModel)
#endif
  => Component context () childModel childAction
  -- ^ 'Component' to mount
  -> View context model action
#ifdef NATIVE
{-# WARNING mountUseContext "[NATIVE] 'mountUseContext' has no StaticKey; a component mounted with it after the initial frame silently drops OnStatic handlers inside it. Use 'vcomp_' with 'mountStaticUseContext' instead." #-}
#endif
mountUseContext :: forall context childModel childAction model action.
(Eq context, Eq childModel, FromJSON childModel, ToJSON childModel,
 FromJSON childAction, ToJSON childAction) =>
Component context () childModel childAction
-> View context model action
mountUseContext Component context () childModel childAction
comp = SomeComponent context -> View context model action
forall context model action.
SomeComponent context -> View context model action
VComp (Maybe Key
-> ()
-> Component context () childModel childAction
-> SomeComponent context
forall context model action props.
(FromJSON model, ToJSON model, FromJSON action, ToJSON action,
 FromJSON props, ToJSON props, Eq context, Eq model, Eq props) =>
Maybe Key
-> props
-> Component context props model action
-> SomeComponent context
SomeComponent Maybe Key
forall a. Maybe a
Nothing () Component context () childModel childAction
comp { useContext = True })
-----------------------------------------------------------------------------
-- | DOM element namespace.
data Namespace
  = HTML
  -- ^ HTML Namespace
  | SVG
  -- ^ SVG Namespace
  | MATHML
  -- ^ MATHML Namespace
  deriving (Int -> Namespace -> ShowS
[Namespace] -> ShowS
Namespace -> String
(Int -> Namespace -> ShowS)
-> (Namespace -> String)
-> ([Namespace] -> ShowS)
-> Show Namespace
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Namespace -> ShowS
showsPrec :: Int -> Namespace -> ShowS
$cshow :: Namespace -> String
show :: Namespace -> String
$cshowList :: [Namespace] -> ShowS
showList :: [Namespace] -> ShowS
Show, Namespace -> Namespace -> Bool
(Namespace -> Namespace -> Bool)
-> (Namespace -> Namespace -> Bool) -> Eq Namespace
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Namespace -> Namespace -> Bool
== :: Namespace -> Namespace -> Bool
$c/= :: Namespace -> Namespace -> Bool
/= :: Namespace -> Namespace -> Bool
Eq)
-----------------------------------------------------------------------------
instance ToJSVal Namespace where
  toJSVal :: Namespace -> IO JSVal
toJSVal = \case
    Namespace
SVG -> MisoString -> IO JSVal
forall a. ToJSVal a => a -> IO JSVal
toJSVal (MisoString
"svg" :: MisoString)
    Namespace
HTML -> MisoString -> IO JSVal
forall a. ToJSVal a => a -> IO JSVal
toJSVal (MisoString
"html" :: MisoString)
    Namespace
MATHML -> MisoString -> IO JSVal
forall a. ToJSVal a => a -> IO JSVal
toJSVal (MisoString
"mathml" :: MisoString)
-----------------------------------------------------------------------------
-- | Unique key for a DOM node.
--
-- This key is only used to speed up diffing the children of a DOM
-- node, the actual content is not important. The keys of the children
-- of a given DOM node must be unique. Failure to satisfy this
-- invariant gives undefined behavior at runtime.
newtype Key = Key MisoString
  deriving newtype (Int -> Key -> ShowS
[Key] -> ShowS
Key -> String
(Int -> Key -> ShowS)
-> (Key -> String) -> ([Key] -> ShowS) -> Show Key
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Key -> ShowS
showsPrec :: Int -> Key -> ShowS
$cshow :: Key -> String
show :: Key -> String
$cshowList :: [Key] -> ShowS
showList :: [Key] -> ShowS
Show, Key -> Key -> Bool
(Key -> Key -> Bool) -> (Key -> Key -> Bool) -> Eq Key
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Key -> Key -> Bool
== :: Key -> Key -> Bool
$c/= :: Key -> Key -> Bool
/= :: Key -> Key -> Bool
Eq, String -> Key
(String -> Key) -> IsString Key
forall a. (String -> a) -> IsString a
$cfromString :: String -> Key
fromString :: String -> Key
IsString, [Key] -> Value
Key -> Value
(Key -> Value) -> ([Key] -> Value) -> ToJSON Key
forall a. (a -> Value) -> ([a] -> Value) -> ToJSON a
$ctoJSON :: Key -> Value
toJSON :: Key -> Value
$ctoJSONList :: [Key] -> Value
toJSONList :: [Key] -> Value
ToJSON, Key -> MisoString
(Key -> MisoString) -> ToMisoString Key
forall str. (str -> MisoString) -> ToMisoString str
$ctoMisoString :: Key -> MisoString
toMisoString :: Key -> MisoString
ToMisoString)
-----------------------------------------------------------------------------
-- | ToJSVal instance for t'Key'
instance ToJSVal Key where
  toJSVal :: Key -> IO JSVal
toJSVal (Key MisoString
x) = MisoString -> IO JSVal
forall a. ToJSVal a => a -> IO JSVal
toJSVal MisoString
x
-----------------------------------------------------------------------------
-- | Convert custom key types to t'Key'.
--
-- Instances of this class do not have to guarantee uniqueness of the
-- generated keys, it is up to the user to do so. @toKey@ must be an
-- injective function (different inputs must map to different outputs).
class ToKey key where
  -- | Converts any key into t'Key'
  toKey :: key -> Key
-----------------------------------------------------------------------------
-- | Identity instance
instance ToKey Key where toKey :: Key -> Key
toKey = Key -> Key
forall a. a -> a
id
-----------------------------------------------------------------------------
#ifndef VANILLA
-- | Convert 'MisoString' to t'Key'
instance ToKey MisoString where toKey = Key
#endif
-----------------------------------------------------------------------------
-- | Convert 'T.Text' to t'Key'
instance ToKey T.Text where toKey :: MisoString -> Key
toKey = MisoString -> Key
Key (MisoString -> Key)
-> (MisoString -> MisoString) -> MisoString -> Key
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MisoString -> MisoString
forall str. ToMisoString str => str -> MisoString
toMisoString
-----------------------------------------------------------------------------
-- | Convert 'String' to t'Key'
instance ToKey String where toKey :: String -> Key
toKey = MisoString -> Key
Key (MisoString -> Key) -> (String -> MisoString) -> String -> Key
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> MisoString
forall str. ToMisoString str => str -> MisoString
toMisoString
-----------------------------------------------------------------------------
-- | Convert 'Int' to t'Key'
instance ToKey Int where toKey :: Int -> Key
toKey = MisoString -> Key
Key (MisoString -> Key) -> (Int -> MisoString) -> Int -> Key
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> MisoString
forall str. ToMisoString str => str -> MisoString
toMisoString
-----------------------------------------------------------------------------
-- | Convert 'Double' to t'Key'
instance ToKey Double where toKey :: Double -> Key
toKey = MisoString -> Key
Key (MisoString -> Key) -> (Double -> MisoString) -> Double -> Key
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> MisoString
forall str. ToMisoString str => str -> MisoString
toMisoString
-----------------------------------------------------------------------------
-- | Convert 'Float' to t'Key'
instance ToKey Float where toKey :: Float -> Key
toKey = MisoString -> Key
Key (MisoString -> Key) -> (Float -> MisoString) -> Float -> Key
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Float -> MisoString
forall str. ToMisoString str => str -> MisoString
toMisoString
-----------------------------------------------------------------------------
-- | Convert 'Word' to t'Key'
instance ToKey Word where toKey :: Word -> Key
toKey = MisoString -> Key
Key (MisoString -> Key) -> (Word -> MisoString) -> Word -> Key
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word -> MisoString
forall str. ToMisoString str => str -> MisoString
toMisoString
-----------------------------------------------------------------------------
-- | Wrapper for event handler callbacks, used for cross-thread communication.
--
-- Carries two independent things built from the same @(decoder, convert)@
-- pair:
--
-- * 'eventHandlerInstall' — attaches a real JS listener to a live vnode.
--   Used by 'Miso.Runtime.setAttrs' during diffing, on both threads.
-- * 'eventHandlerDecoder' \/ 'eventHandlerConvert' — the decode step exposed
--   directly, with no JS installer round-trip. Used by the MTS's
--   @dispatchMainThreadEvent@ to decode + dispatch a main-thread event
--   synchronously, without reconstructing (and discarding) a JS callback via
--   a throwaway scratch node on every single event.
data EventHandler model action = forall result. EventHandler
  { forall model action.
EventHandler model action
-> model -> Sink action -> VTree -> LogLevel -> Events -> IO ()
eventHandlerInstall :: model -> Sink action -> VTree -> LogLevel -> Events -> IO ()
  , ()
eventHandlerDecoder :: Miso.Event.Decoder.Decoder result
  , ()
eventHandlerConvert :: result -> model -> DOMRef -> action
  }
-----------------------------------------------------------------------------
-- | Embed a fully-applied @static@ event handler.
--
-- The handler is baked into the 'StaticPtr', so the main thread can rebuild it
-- from the 'StaticKey' alone (no payload to forward). Use this for handlers that
-- take no injected @model@ data — including decoder handlers whose argument is a
-- function (e.g. @onScroll HandleScroll@).
--
-- @
-- button_ [ event (static (onClick AddOne)) ]
-- div_    [ event (static (onScroll HandleScroll)) ]
-- @
event :: StaticPtr (EventHandler model action) -> Attribute model action
event :: forall model action.
StaticPtr (EventHandler model action) -> Attribute model action
event = StaticPtr (EventHandler model action) -> Attribute model action
forall model action.
StaticPtr (EventHandler model action) -> Attribute model action
OnStatic
-----------------------------------------------------------------------------
-- | Attribute of a vnode in a t'View'.
--
data Attribute model action
  = Property MisoString Value
  | ClassList [MisoString]
  | On (model -> Sink action -> VTree -> LogLevel -> Events -> IO ())
  -- ^ A fully-applied @static@ event handler; the main thread rebuilds it from
  -- the 'StaticKey' alone. See 'event'.
  | OnStatic (StaticPtr (EventHandler model action))
  -- ^ A @static@ handler /constructor/ plus a runtime @payload@ (often @model@
  -- data) supplied separately and JSON-shipped across the dual-thread boundary,
  -- so the handler can reach the main thread with runtime data. The @action@
  -- stays outside the existential; only @payload@ is hidden. Handler-identity
  -- diffing is by 'StaticKey' (JS-side, @ts\/miso\/dom.ts@). See 'eventWith'.
  | Styles (M.Map MisoString MisoString)
-----------------------------------------------------------------------------
instance Eq (Attribute model action) where
  Property MisoString
k1 Value
v1 == :: Attribute model action -> Attribute model action -> Bool
== Property MisoString
k2 Value
v2 = MisoString
k1 MisoString -> MisoString -> Bool
forall a. Eq a => a -> a -> Bool
== MisoString
k2 Bool -> Bool -> Bool
&& Value
v1 Value -> Value -> Bool
forall a. Eq a => a -> a -> Bool
== Value
v2
  ClassList [MisoString]
x == ClassList [MisoString]
y = [MisoString]
x [MisoString] -> [MisoString] -> Bool
forall a. Eq a => a -> a -> Bool
== [MisoString]
y
  Styles Map MisoString MisoString
x == Styles Map MisoString MisoString
y = Map MisoString MisoString
x Map MisoString MisoString -> Map MisoString MisoString -> Bool
forall a. Eq a => a -> a -> Bool
== Map MisoString MisoString
y
  -- Compare by handler identity ('StaticKey') only. Payload diffing is a JS
  -- concern (@ts\/miso\/dom.ts@) over the stashed value.
  OnStatic StaticPtr (EventHandler model action)
ptr1 == OnStatic StaticPtr (EventHandler model action)
ptr2 = (StaticKey -> StaticKey -> Bool)
-> (StaticPtr (EventHandler model action) -> StaticKey)
-> StaticPtr (EventHandler model action)
-> StaticPtr (EventHandler model action)
-> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
on StaticKey -> StaticKey -> Bool
forall a. Eq a => a -> a -> Bool
(==) StaticPtr (EventHandler model action) -> StaticKey
forall a. StaticPtr a -> StaticKey
staticKey StaticPtr (EventHandler model action)
ptr1 StaticPtr (EventHandler model action)
ptr2
  Attribute model action
_ == Attribute model action
_ = Bool
False
-----------------------------------------------------------------------------
instance Show (Attribute model action) where
  show :: Attribute model action -> String
show = \case
    Property MisoString
key Value
value ->
      MisoString -> String
MS.unpack MisoString
key String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
"=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> MisoString -> String
MS.unpack (MisoString -> MisoString
forall str. ToMisoString str => str -> MisoString
ms (Value -> MisoString
forall a. ToJSON a => a -> MisoString
encode Value
value))
    ClassList [MisoString]
classes ->
      MisoString -> String
MS.unpack (MisoString -> [MisoString] -> MisoString
MS.intercalate MisoString
" " [MisoString]
classes)
    On model -> Sink action -> VTree -> LogLevel -> Events -> IO ()
_ ->
      String
"<event-handler>"
    OnStatic StaticPtr (EventHandler model action)
ptr ->
      String
"<event-handler-with: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> StaticKey -> String
forall a. Show a => a -> String
show (StaticPtr (EventHandler model action) -> StaticKey
forall a. StaticPtr a -> StaticKey
staticKey StaticPtr (EventHandler model action)
ptr) String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
">"
    Styles Map MisoString MisoString
styles ->
      MisoString -> String
MS.unpack (MisoString -> String) -> MisoString -> String
forall a b. (a -> b) -> a -> b
$ [MisoString] -> MisoString
MS.concat
        [ MisoString
k MisoString -> MisoString -> MisoString
forall a. Semigroup a => a -> a -> a
<> MisoString
"=" MisoString -> MisoString -> MisoString
forall a. Semigroup a => a -> a -> a
<> MisoString
v MisoString -> MisoString -> MisoString
forall a. Semigroup a => a -> a -> a
<> MisoString
";"
        | (MisoString
k, MisoString
v) <- Map MisoString MisoString -> [(MisoString, MisoString)]
forall k a. Map k a -> [(k, a)]
M.toList Map MisoString MisoString
styles
        ]
-----------------------------------------------------------------------------
-- | 'IsString' instance
instance IsString (View context model action) where
  fromString :: String -> View context model action
fromString = Maybe Key -> MisoString -> View context model action
forall context model action.
Maybe Key -> MisoString -> View context model action
VText Maybe Key
forall a. Maybe a
Nothing (MisoString -> View context model action)
-> (String -> MisoString) -> String -> View context model action
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> MisoString
forall a. IsString a => String -> a
fromString
-----------------------------------------------------------------------------
-- | Virtual DOM implemented as a JavaScript t'Object'.
--   Used for diffing, patching and event delegation.
--   Not meant to be constructed directly, see t'Miso.Types.View' instead.
newtype VTree = VTree
  { VTree -> Object
getTree :: Object
  -- ^ Underlying JavaScript object representing the virtual DOM tree
  } deriving newtype (VTree -> IO Object
(VTree -> IO Object) -> ToObject VTree
forall a. (a -> IO Object) -> ToObject a
$ctoObject :: VTree -> IO Object
toObject :: VTree -> IO Object
ToObject, VTree -> IO JSVal
(VTree -> IO JSVal) -> ToJSVal VTree
forall a. (a -> IO JSVal) -> ToJSVal a
$ctoJSVal :: VTree -> IO JSVal
toJSVal :: VTree -> IO JSVal
ToJSVal)
-----------------------------------------------------------------------------
-- | Create a new 'Miso.Types.VNode'.
--
-- @node ns tag attrs children@ creates a new node with tag @tag@
-- in the namespace @ns@. All @attrs@ are called when
-- the node is created and its children are initialized to @children@.
node
  :: Namespace
  -- ^ Element namespace (@HTML@, @SVG@, or @MATHML@)
  -> MisoString
  -- ^ Tag name (e.g. @\"div\"@, @\"circle\"@)
  -> [Attribute model action]
  -- ^ Attributes, properties, and event handlers
  -> [View context model action]
  -- ^ Child nodes
  -> View context model action
node :: forall model action context.
Namespace
-> MisoString
-> [Attribute model action]
-> [View context model action]
-> View context model action
node Namespace
ns MisoString
tag [Attribute model action]
attrs [View context model action]
kids = Namespace
-> MisoString
-> [Attribute model action]
-> [View context model action]
-> DirectEvents
-> View context model action
forall context model action.
Namespace
-> MisoString
-> [Attribute model action]
-> [View context model action]
-> DirectEvents
-> View context model action
VNode Namespace
ns MisoString
tag [Attribute model action]
attrs [View context model action]
kids DirectEvents
forall a. Monoid a => a
mempty
-----------------------------------------------------------------------------
-- | Like 'node', but declares the set of events this element dispatches
-- /directly/ on itself instead of by bubbling to the delegated mount listener.
--
-- Only relevant to the Lynx native runtime, where component-emitted events
-- (@input@, @scroll@, @load@, …) do not bubble and must be bound on the
-- element. The set is a /capability/: a listener is bound only for events the
-- element actually handles. Empty on the browser\/WASM runtime.
--
-- @since 1.10.0.0
nodeDirectEvents
  :: Namespace
  -- ^ Element namespace (@HTML@, @SVG@, or @MATHML@)
  -> MisoString
  -- ^ Tag name (e.g. @\"input\"@, @\"scroll-view\"@)
  -> [Attribute model action]
  -- ^ Attributes, properties, and event handlers
  -> [MisoString]
  -- ^ Events dispatched directly on this element
  -> [View context model action]
  -- ^ Child nodes
  -> View context model action
nodeDirectEvents :: forall model action context.
Namespace
-> MisoString
-> [Attribute model action]
-> [MisoString]
-> [View context model action]
-> View context model action
nodeDirectEvents Namespace
ns MisoString
tag [Attribute model action]
attrs [MisoString]
direct [View context model action]
kids = Namespace
-> MisoString
-> [Attribute model action]
-> [View context model action]
-> DirectEvents
-> View context model action
forall context model action.
Namespace
-> MisoString
-> [Attribute model action]
-> [View context model action]
-> DirectEvents
-> View context model action
VNode Namespace
ns MisoString
tag [Attribute model action]
attrs [View context model action]
kids ([MisoString] -> DirectEvents
forall a. Ord a => [a] -> Set a
S.fromList [MisoString]
direct)
-----------------------------------------------------------------------------
-- | Create a new 'Miso.Types.VNode'.
--
-- Synonym for 'node'
--
vnode
  :: Namespace
  -- ^ Element namespace (@HTML@, @SVG@, or @MATHML@)
  -> MisoString
  -- ^ Tag name (e.g. @\"div\"@, @\"circle\"@)
  -> [Attribute model action]
  -- ^ Attributes, properties, and event handlers
  -> [View context model action]
  -- ^ Child nodes
  -> View context model action
vnode :: forall model action context.
Namespace
-> MisoString
-> [Attribute model action]
-> [View context model action]
-> View context model action
vnode = Namespace
-> MisoString
-> [Attribute model action]
-> [View context model action]
-> View context model action
forall model action context.
Namespace
-> MisoString
-> [Attribute model action]
-> [View context model action]
-> View context model action
node
-----------------------------------------------------------------------------
-- | Create a new v'VText' with the given content.
text :: MisoString -> View context model action
#ifdef SSR
text = VText Nothing . htmlEncode
#else
text :: forall context model action.
MisoString -> View context model action
text = Maybe Key -> MisoString -> View context model action
forall context model action.
Maybe Key -> MisoString -> View context model action
VText Maybe Key
forall a. Maybe a
Nothing
#endif
-----------------------------------------------------------------------------
-- | Synonym for 'text'
vtext :: MisoString -> View context model action
vtext :: forall context model action.
MisoString -> View context model action
vtext = MisoString -> View context model action
forall context model action.
MisoString -> View context model action
text
----------------------------------------------------------------------------
-- | Create a new v'VText', not subject to HTML escaping.
--
-- Like 'text', except will not escape HTML when used on the server.
--
textRaw :: MisoString -> View context model action
textRaw :: forall context model action.
MisoString -> View context model action
textRaw = Maybe Key -> MisoString -> View context model action
forall context model action.
Maybe Key -> MisoString -> View context model action
VText Maybe Key
forall a. Maybe a
Nothing
----------------------------------------------------------------------------
-- |
-- HTML-encodes text.
--
-- Useful for escaping HTML when delivering on the server. Naive usage
-- of 'text' will ensure this as well.
--
-- >>> Data.Text.IO.putStrLn $ text "<a href=\"\">"
-- &lt;a href=&quot;&quot;&gt;
htmlEncode :: MisoString -> MisoString
htmlEncode :: MisoString -> MisoString
htmlEncode = (Char -> MisoString) -> MisoString -> MisoString
MS.concatMap ((Char -> MisoString) -> MisoString -> MisoString)
-> (Char -> MisoString) -> MisoString -> MisoString
forall a b. (a -> b) -> a -> b
$ \case
  Char
'<' -> MisoString
"&lt;"
  Char
'>' -> MisoString
"&gt;"
  Char
'&' -> MisoString
"&amp;"
  Char
'"' -> MisoString
"&quot;"
  Char
'\'' -> MisoString
"&#39;"
  Char
x -> Char -> MisoString
MS.singleton Char
x
-----------------------------------------------------------------------------
-- | Create a new v'VText' containing concatenation of the given strings.
--
-- @
--   view :: View context model action
--   view = div_
--     [ className "container" ]
--     [ text_
--       [ "foo"
--       , "bar"
--       ]
--     ]
-- @
--
-- Renders as @<div class="container">foo bar</div>@
--
-- A single additional space is added between elements.
--
text_ :: [MisoString] -> View context model action
text_ :: forall context model action.
[MisoString] -> View context model action
text_ = Maybe Key -> MisoString -> View context model action
forall context model action.
Maybe Key -> MisoString -> View context model action
VText Maybe Key
forall a. Maybe a
Nothing (MisoString -> View context model action)
-> ([MisoString] -> MisoString)
-> [MisoString]
-> View context model action
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MisoString -> [MisoString] -> MisoString
MS.intercalate MisoString
" "
-----------------------------------------------------------------------------
-- | Like 'text', but allow the node to be keyed for efficient diffing.
--
-- @
-- view :: model -> View context model action
-- view = \x -> div_ [] [ textKey (1 :: Int) "text here" ]
-- @
--
-- @since 1.9.0.0
textKey :: ToKey key => key -> MisoString -> View context model action
textKey :: forall key context model action.
ToKey key =>
key -> MisoString -> View context model action
textKey key
k = Maybe Key -> MisoString -> View context model action
forall context model action.
Maybe Key -> MisoString -> View context model action
VText (Key -> Maybe Key
forall a. a -> Maybe a
Just (key -> Key
forall key. ToKey key => key -> Key
toKey key
k))
-----------------------------------------------------------------------------
-- | Like 'text_', but allow the node to be keyed for efficient diffing.
--
-- @
-- view :: model -> View context model action
-- view = \x -> div_ [] [ textKey_ (1 :: Int) [ "text", "goes", "here" ] ]
-- @
--
-- @since 1.9.0.0
textKey_ :: ToKey key => key -> [MisoString] -> View context model action
textKey_ :: forall key context model action.
ToKey key =>
key -> [MisoString] -> View context model action
textKey_ key
k [MisoString]
xs = Maybe Key -> MisoString -> View context model action
forall context model action.
Maybe Key -> MisoString -> View context model action
VText (Key -> Maybe Key
forall a. a -> Maybe a
Just (key -> Key
forall key. ToKey key => key -> Key
toKey key
k)) (MisoString -> [MisoString] -> MisoString
MS.intercalate MisoString
" " [MisoString]
xs)
-----------------------------------------------------------------------------
-- | Utility function to make it easy to specify conditional attributes
--
-- @
-- view :: Bool -> View context model action
-- view danger = optionalAttrs div_ [ id_ "some-div" ] danger [ class_ "danger" ] ["child"]
-- @
--
-- @since 1.9.0.0
optionalAttrs
  :: ([Attribute model action] -> [View context model action] -> View context model action)
  -> [Attribute model action] -- ^ Attributes to be added unconditionally
  -> Bool -- ^ A condition
  -> [Attribute model action] -- ^ Additional attributes to add if the condition is True
  -> [View context model action] -- ^ Children
  -> View context model action
optionalAttrs :: forall model action context.
([Attribute model action]
 -> [View context model action] -> View context model action)
-> [Attribute model action]
-> Bool
-> [Attribute model action]
-> [View context model action]
-> View context model action
optionalAttrs [Attribute model action]
-> [View context model action] -> View context model action
element [Attribute model action]
attrs Bool
condition [Attribute model action]
opts [View context model action]
kids =
  case [Attribute model action]
-> [View context model action] -> View context model action
element [Attribute model action]
attrs [View context model action]
kids of
    VNode Namespace
ns MisoString
name [Attribute model action]
_ [View context model action]
_ DirectEvents
de -> do
      let newAttrs :: [Attribute model action]
newAttrs = [[Attribute model action]] -> [Attribute model action]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ [Attribute model action]
opts | Bool
condition ] [Attribute model action]
-> [Attribute model action] -> [Attribute model action]
forall a. [a] -> [a] -> [a]
++ [Attribute model action]
attrs
      Namespace
-> MisoString
-> [Attribute model action]
-> [View context model action]
-> DirectEvents
-> View context model action
forall context model action.
Namespace
-> MisoString
-> [Attribute model action]
-> [View context model action]
-> DirectEvents
-> View context model action
VNode Namespace
ns MisoString
name [Attribute model action]
newAttrs [View context model action]
kids DirectEvents
de
    View context model action
x -> View context model action
x
-----------------------------------------------------------------------------
-- | Utility function to make it easy to specify conditional attributes for void elements.
--
-- @
-- view :: Bool -> View context model action
-- view shouldClear = optionalVoidAttrs textarea_ [ value_ "" ] shouldClear [ id_ "text-area-id" ]
-- @
--
-- @since 1.9.0.0
optionalVoidAttrs
  :: ([Attribute model action] -> View context model action)
  -> [Attribute model action] -- ^ Attributes to be added unconditionally
  -> Bool -- ^ A condition
  -> [Attribute model action] -- ^ Additional attributes to add if the condition is True
  -> View context model action
optionalVoidAttrs :: forall model action context.
([Attribute model action] -> View context model action)
-> [Attribute model action]
-> Bool
-> [Attribute model action]
-> View context model action
optionalVoidAttrs [Attribute model action] -> View context model action
element [Attribute model action]
attrs Bool
condition [Attribute model action]
opts =
  case [Attribute model action] -> View context model action
element [Attribute model action]
attrs of
    VNode Namespace
ns MisoString
name [Attribute model action]
_ [View context model action]
kids DirectEvents
de -> do
      let newAttrs :: [Attribute model action]
newAttrs = [[Attribute model action]] -> [Attribute model action]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ [Attribute model action]
opts | Bool
condition ] [Attribute model action]
-> [Attribute model action] -> [Attribute model action]
forall a. [a] -> [a] -> [a]
++ [Attribute model action]
attrs
      Namespace
-> MisoString
-> [Attribute model action]
-> [View context model action]
-> DirectEvents
-> View context model action
forall context model action.
Namespace
-> MisoString
-> [Attribute model action]
-> [View context model action]
-> DirectEvents
-> View context model action
VNode Namespace
ns MisoString
name [Attribute model action]
newAttrs [View context model action]
kids DirectEvents
de
    View context model action
x -> View context model action
x
----------------------------------------------------------------------------
-- | Conditionally adds children.
--
-- @
-- view :: Bool -> View context model action
-- view withChild = optionalChildren div_ [ id_ "txt" ] [] withChild [ "foo" ]
-- @
--
-- @since 1.9.0.0
optionalChildren
  :: ([Attribute model action] -> [View context model action] -> View context model action)
  -> [Attribute model action] -- ^ Attributes to be added unconditionally
  -> [View context model action] -- ^ Children to be added unconditionally
  -> Bool -- ^ A condition
  -> [View context model action] -- ^ Additional children to add if the condition is True
  -> View context model action
optionalChildren :: forall model action context.
([Attribute model action]
 -> [View context model action] -> View context model action)
-> [Attribute model action]
-> [View context model action]
-> Bool
-> [View context model action]
-> View context model action
optionalChildren [Attribute model action]
-> [View context model action] -> View context model action
element [Attribute model action]
attrs [View context model action]
kids Bool
condition [View context model action]
opts =
  case [Attribute model action]
-> [View context model action] -> View context model action
element [Attribute model action]
attrs [View context model action]
kids of
    VNode Namespace
ns MisoString
name [Attribute model action]
_ [View context model action]
_ DirectEvents
de -> do
      let newKids :: [View context model action]
newKids = [View context model action]
kids [View context model action]
-> [View context model action] -> [View context model action]
forall a. [a] -> [a] -> [a]
++ [[View context model action]] -> [View context model action]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ [View context model action]
opts | Bool
condition ]
      Namespace
-> MisoString
-> [Attribute model action]
-> [View context model action]
-> DirectEvents
-> View context model action
forall context model action.
Namespace
-> MisoString
-> [Attribute model action]
-> [View context model action]
-> DirectEvents
-> View context model action
VNode Namespace
ns MisoString
name [Attribute model action]
attrs [View context model action]
newKids DirectEvents
de
    View context model action
x -> View context model action
x
----------------------------------------------------------------------------
-- | URI type. See the official [specification](https://www.rfc-editor.org/rfc/rfc3986)
--
data URI
  = URI
  { URI -> MisoString
uriPath :: MisoString
  -- ^ Path component, e.g. @\"users\/42\"@
  , URI -> MisoString
uriFragment :: MisoString
  -- ^ Fragment identifier (without the leading @#@), e.g. @\"section-1\"@
  , URI -> Map MisoString (Maybe MisoString)
uriQueryString :: M.Map MisoString (Maybe MisoString)
  -- ^ Query parameters. @'Just' v@ for @?key=v@ pairs; 'Nothing' for bare flags (@?flag@).
  } deriving stock (Int -> URI -> ShowS
[URI] -> ShowS
URI -> String
(Int -> URI -> ShowS)
-> (URI -> String) -> ([URI] -> ShowS) -> Show URI
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> URI -> ShowS
showsPrec :: Int -> URI -> ShowS
$cshow :: URI -> String
show :: URI -> String
$cshowList :: [URI] -> ShowS
showList :: [URI] -> ShowS
Show, URI -> URI -> Bool
(URI -> URI -> Bool) -> (URI -> URI -> Bool) -> Eq URI
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: URI -> URI -> Bool
== :: URI -> URI -> Bool
$c/= :: URI -> URI -> Bool
/= :: URI -> URI -> Bool
Eq, (forall x. URI -> Rep URI x)
-> (forall x. Rep URI x -> URI) -> Generic URI
forall x. Rep URI x -> URI
forall x. URI -> Rep URI x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. URI -> Rep URI x
from :: forall x. URI -> Rep URI x
$cto :: forall x. Rep URI x -> URI
to :: forall x. Rep URI x -> URI
Generic)
    deriving anyclass (URI -> IO JSVal
(URI -> IO JSVal) -> ToJSVal URI
forall a. (a -> IO JSVal) -> ToJSVal a
$ctoJSVal :: URI -> IO JSVal
toJSVal :: URI -> IO JSVal
ToJSVal, URI -> IO Object
(URI -> IO Object) -> ToObject URI
forall a. (a -> IO Object) -> ToObject a
$ctoObject :: URI -> IO Object
toObject :: URI -> IO Object
ToObject)
----------------------------------------------------------------------------
-- | Empty t'URI'.
emptyURI :: URI
emptyURI :: URI
emptyURI = MisoString
-> MisoString -> Map MisoString (Maybe MisoString) -> URI
URI MisoString
forall a. Monoid a => a
mempty MisoString
forall a. Monoid a => a
mempty Map MisoString (Maybe MisoString)
forall a. Monoid a => a
mempty
----------------------------------------------------------------------------
instance ToMisoString URI where
  toMisoString :: URI -> MisoString
toMisoString = URI -> MisoString
prettyURI
----------------------------------------------------------------------------
instance ToJSON URI where
  toJSON :: URI -> Value
toJSON = MisoString -> Value
forall a. ToJSON a => a -> Value
toJSON (MisoString -> Value) -> (URI -> MisoString) -> URI -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. URI -> MisoString
forall str. ToMisoString str => str -> MisoString
toMisoString
----------------------------------------------------------------------------
-- | Pretty-prints a t'URI'.
prettyURI :: URI -> MisoString
prettyURI :: URI -> MisoString
prettyURI uri :: URI
uri@URI {Map MisoString (Maybe MisoString)
MisoString
uriPath :: URI -> MisoString
uriFragment :: URI -> MisoString
uriQueryString :: URI -> Map MisoString (Maybe MisoString)
uriPath :: MisoString
uriFragment :: MisoString
uriQueryString :: Map MisoString (Maybe MisoString)
..} = MisoString
"/" MisoString -> MisoString -> MisoString
forall a. Semigroup a => a -> a -> a
<> MisoString
uriPath MisoString -> MisoString -> MisoString
forall a. Semigroup a => a -> a -> a
<> URI -> MisoString
prettyQueryString URI
uri MisoString -> MisoString -> MisoString
forall a. Semigroup a => a -> a -> a
<> MisoString
uriFragment
-----------------------------------------------------------------------------
-- | Pretty-prints a t'URI' query string.
prettyQueryString :: URI -> MisoString
prettyQueryString :: URI -> MisoString
prettyQueryString URI {Map MisoString (Maybe MisoString)
MisoString
uriPath :: URI -> MisoString
uriFragment :: URI -> MisoString
uriQueryString :: URI -> Map MisoString (Maybe MisoString)
uriPath :: MisoString
uriFragment :: MisoString
uriQueryString :: Map MisoString (Maybe MisoString)
..} = MisoString
queries MisoString -> MisoString -> MisoString
forall a. Semigroup a => a -> a -> a
<> MisoString
flags
  where
    queries :: MisoString
queries =
      [MisoString] -> MisoString
MS.concat
      [ MisoString
"?" MisoString -> MisoString -> MisoString
forall a. Semigroup a => a -> a -> a
<>
        MisoString -> [MisoString] -> MisoString
MS.intercalate MisoString
"&"
        [ MisoString
k MisoString -> MisoString -> MisoString
forall a. Semigroup a => a -> a -> a
<> MisoString
"=" MisoString -> MisoString -> MisoString
forall a. Semigroup a => a -> a -> a
<> MisoString
v
        | (MisoString
k, Just MisoString
v) <- Map MisoString (Maybe MisoString)
-> [(MisoString, Maybe MisoString)]
forall k a. Map k a -> [(k, a)]
M.toList Map MisoString (Maybe MisoString)
uriQueryString
        ]
      | (Maybe MisoString -> Bool) -> [Maybe MisoString] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Maybe MisoString -> Bool
forall a. Maybe a -> Bool
isJust (Map MisoString (Maybe MisoString) -> [Maybe MisoString]
forall k a. Map k a -> [a]
M.elems Map MisoString (Maybe MisoString)
uriQueryString)
      ]
    flags :: MisoString
flags = [MisoString] -> MisoString
forall a. Monoid a => [a] -> a
mconcat
        [ MisoString
"?" MisoString -> MisoString -> MisoString
forall a. Semigroup a => a -> a -> a
<> MisoString
k
        | (MisoString
k, Maybe MisoString
Nothing) <- Map MisoString (Maybe MisoString)
-> [(MisoString, Maybe MisoString)]
forall k a. Map k a -> [(k, a)]
M.toList Map MisoString (Maybe MisoString)
uriQueryString
        ]
-----------------------------------------------------------------------------
-- | VTreeType ADT for matching TypeScript enum
data VTreeType
  = VCompType
  | VNodeType
  | VTextType
  | VFragType
  deriving (Int -> VTreeType -> ShowS
[VTreeType] -> ShowS
VTreeType -> String
(Int -> VTreeType -> ShowS)
-> (VTreeType -> String)
-> ([VTreeType] -> ShowS)
-> Show VTreeType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> VTreeType -> ShowS
showsPrec :: Int -> VTreeType -> ShowS
$cshow :: VTreeType -> String
show :: VTreeType -> String
$cshowList :: [VTreeType] -> ShowS
showList :: [VTreeType] -> ShowS
Show, VTreeType -> VTreeType -> Bool
(VTreeType -> VTreeType -> Bool)
-> (VTreeType -> VTreeType -> Bool) -> Eq VTreeType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: VTreeType -> VTreeType -> Bool
== :: VTreeType -> VTreeType -> Bool
$c/= :: VTreeType -> VTreeType -> Bool
/= :: VTreeType -> VTreeType -> Bool
Eq)
-----------------------------------------------------------------------------
instance ToJSVal VTreeType where
  toJSVal :: VTreeType -> IO JSVal
toJSVal = \case
    VTreeType
VCompType -> Int -> IO JSVal
forall a. ToJSVal a => a -> IO JSVal
toJSVal (Int
0 :: Int)
    VTreeType
VNodeType -> Int -> IO JSVal
forall a. ToJSVal a => a -> IO JSVal
toJSVal (Int
1 :: Int)
    VTreeType
VTextType -> Int -> IO JSVal
forall a. ToJSVal a => a -> IO JSVal
toJSVal (Int
2 :: Int)
    VTreeType
VFragType -> Int -> IO JSVal
forall a. ToJSVal a => a -> IO JSVal
toJSVal (Int
3 :: Int)
-----------------------------------------------------------------------------
-- | Hydrate avoids calling @diff@, and instead calls @hydrate@
-- 'Draw' invokes 'Miso.Diff.diff'
data Hydrate
  = Draw
  | Hydrate
  deriving (Int -> Hydrate -> ShowS
[Hydrate] -> ShowS
Hydrate -> String
(Int -> Hydrate -> ShowS)
-> (Hydrate -> String) -> ([Hydrate] -> ShowS) -> Show Hydrate
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Hydrate -> ShowS
showsPrec :: Int -> Hydrate -> ShowS
$cshow :: Hydrate -> String
show :: Hydrate -> String
$cshowList :: [Hydrate] -> ShowS
showList :: [Hydrate] -> ShowS
Show, Hydrate -> Hydrate -> Bool
(Hydrate -> Hydrate -> Bool)
-> (Hydrate -> Hydrate -> Bool) -> Eq Hydrate
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Hydrate -> Hydrate -> Bool
== :: Hydrate -> Hydrate -> Bool
$c/= :: Hydrate -> Hydrate -> Bool
/= :: Hydrate -> Hydrate -> Bool
Eq)
-----------------------------------------------------------------------------