-----------------------------------------------------------------------------
{-# LANGUAGE CPP                        #-}
{-# LANGUAGE QuasiQuotes                #-}
{-# LANGUAGE NamedFieldPuns             #-}
{-# LANGUAGE RecordWildCards            #-}
{-# LANGUAGE TemplateHaskell            #-}
-----------------------------------------------------------------------------
{-# OPTIONS_GHC -Wno-duplicate-exports #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  Miso
-- Copyright   :  (C) 2016-2026 David M. Johnson (@dmjio)
-- License     :  BSD3-style (see the file LICENSE)
-- Maintainer  :  David M. Johnson <code@dmj.io>
-- Stability   :  experimental
-- Portability :  non-portable
--
-- = miso 🍜
--
-- @miso@ is a library for building web and native user interface applications in Haskell. See the [GitHub group](https://github.com/haskell-miso).
--
-- It provides a [React](https://react.dev)-like programming experience for a simple [Haskell](https://haskell.org) dialect that emphasizes
--
-- * performance
-- * purity
-- * simplicity
-- * extensibility
-- * composability
--
-- miso addresses common areas of web development:
--
-- * __DOM manipulation__: @miso@ uses a [Virtual DOM](https://en.wikipedia.org/wiki/Virtual_DOM) with a diffing algorithm that is
--   responsible for all DOM modification and 'Component' lifecycle hooks.
--
-- * __Event delegation__: All event listeners are attached to a top-level element
--   (typically @\<body\>@). When raised, events are routed through the virtual DOM
--   to Haskell event handlers which cause application state changes. Internally @miso@
--   virtualizes both the @capture@ and @bubble@ phases of the browser when it performs event routing.
--
-- * __Prerendering__: Prerendering is a process where the server delivers HTML
--   to the client before the JavaScript (or WebAssembly) application bootstraps.
--   Instead of performing an initial draw, the application will create and populate the virtual DOM from the actual DOM.
--   This is a process known as \"hydration\". This avoids unnecessary page draws on initial page
--   load and enhances search engine optimization. @miso@ provides its own HTML rendering
--   ("Miso.Html.Render") to render HTML on the server and the 'miso' function exists on the client to \"hydrate\"
--   the virtual DOM with the DOM.
--
-- * __Components__: A 'Component' can be considered an instance of a @miso@ application. A 'Component'
--   contains user-defined state, logic for updating this state, and a function
--   for creating UI templates from this user-defined state. 'Component' can nest other 'Component',
--   enabling arbitrarily deep UI trees.
--
-- * __Custom renderers__: The underlying DOM operations are able to be abstracted.
-- This allows a custom rendering engine to be used. This is seen in the [miso-lynx](https://github.com/haskell-miso/miso-lynx) project
-- (which allows miso to target mobile phone devices).
--
-- * __Lifecycle hooks__: 'Component' expose 'Miso.Types.mount' and 'Miso.Types.unmount' lifecycle hooks. This allows users to define custom logic that will
-- execute when a 'Component' mounts or unmounts. 'Miso.Event.onCreated' and 'Miso.Event.onDestroyed' are 'VNode' specific lifecycle hooks.
-- These hooks are commonly used for 'Component' communication and for third-party integration with JavaScript libraries.
--
-- * __State management__: 'Component' @model@ state can be manipulated using "Miso.Lens" or "Miso.State" in response to application events.
--
-- = Architecture
--
-- * __React__: miso implements a subset of the [React](https://react.dev) architecture including 'Component', Lifecycle Hooks, Virtual DOM, Event delegation,
-- [Fragment](https://react.dev/reference/react/Fragment) and [Props](https://react.dev/learn/passing-props-to-a-component).
--
-- * __Elm__: miso also implements the [Elm](https://elm-lang.org) architecture (MVU) and the 'mailbox' communication pattern.
--
-- = The Model-View-Update pattern
--
-- The core type of miso is 'Component'. The 'Component' API adheres to the [Elm](https://elm-lang.org)
-- MVU (model-view-update) interface. This is similar to a left-fold over @action@s — the 'Component'
-- @model@ is updated by 'Miso.Types.update' and rendered by 'Miso.Types.view'.
--
-- * __model__: This can be any user-defined type in Haskell. An 'Eq' constraint
--   is required. We recommend using the default derived 'Eq' instance.
--
-- * __view__: @'view' :: props -> model -> 'View' model action@
--   This is the templating function that is used to construct a new virtual DOM
--   (or HTML if rendering on the server).
--
-- * __update__: @'update' :: action -> 'Effect' parent props model action@
--   The 'update' function handles how the 'model' evolves over time in response
--   to events that are raised by the application. This function takes any @action@,
--   updating the @model@ and optionally introduces 'IO' into the system.
--
-- = Your first t'Component'
--
-- To define a 'Component', the 'component' smart constructor can be used.
-- Below is an example of a simple counter 'Component'.
--
-- @
-- -----------------------------------------------------------------------------
-- module Main where
-- -----------------------------------------------------------------------------
-- import Miso
-- import Miso.Lens
-- import qualified Miso.Html.Element as H
-- import qualified Miso.Html.Event as HE
-- import qualified Miso.Html.Property as HP
-- -----------------------------------------------------------------------------
--                       * - The type of the parent Component 'model'
--                       |    * - The type of the parent Component 'props' accessible to the child
--                       |    |   * - The type of the current Component's 'model'
--                       |    |   |   * - The type of the action that updates the 'model'
--                       |    |   |   |
-- counter :: 'Component' ROOT () Int Action
-- counter = 'vcomp' m u v
--   where
--     m :: Int
--     m = 0
--                             * - The type of the parent Component 'model'
--                             |   * - The type of the parent Component 'props' accessible to the child
--                             |   |   * - The type of the current Component's 'model'
--                             |   |   |   * - The type of the action that updates the 'model'
--                             |   |   |   |
--     u :: Action -> 'Effect' ROOT () Int Action
--     u = \\case
--       Add -> 'this' += 1
--       Subtract -> 'this' -= 1
--
--     v :: () -> Int -> 'View' Int Action
--     v _ x = 'vfrag'
--       [ H.button_ [ HE.onClick Add, HP.id_ "add" ] [ "+" ]
--       , text (ms x)
--       , H.button_ [ HE.onClick Subtract, HP.id_ "subtract" ] [ "-" ]
--       ]
-- -----------------------------------------------------------------------------
-- main :: IO ()
-- main = 'startApp' 'defaultEvents' counter
-- -----------------------------------------------------------------------------
-- data Action
--   = Add
--   | Subtract
--   deriving (Eq, Show)
-- -----------------------------------------------------------------------------
-- @
--
-- = Running your first t'Component'
--
-- The 'startApp' (or 'miso') functions are used to run the above t'Component'.
--
-- @
-- main :: IO ()
-- main = 'startApp' 'defaultEvents' counter
-- @
--
-- We recommend 'startApp' as the starting point — it sets up event listeners, performs the initial page draw,
-- and assumes @\<body\>@ is empty.
--
-- The 'miso' function (and 'prerender') assume that @\<body\>@ has already been populated by the results of the 'view' function.
-- Instead of drawing, 'miso' will perform hydration.
-- If the structures do not match, 'miso' will fall back to drawing the page from scratch (clearing the contents of @\<body\>@ first).
--
-- It is possible to execute an initial action when a t'Component' is first mounted. See the 'mount' (and similarly 'unmount') hooks.
--
-- @
--
-- data Action = Init
--
-- main :: IO ()
-- main = 'startApp' 'defaultEvents' counter { 'mount' = Just Init }
--
-- update :: 'App' model Action
-- update = \\case
--   Init -> 'io_' ('consoleLog' "hello world!")
-- @
--
-- Note also the signature of 'startApp'.
--
-- @
-- 'startApp' :: 'Eq' model => 'Events' -> 'App' model action -> IO ()
-- @
--
-- The 'App' type synonym is defined as:
--
-- @
-- type 'App' model action = 'Component' 'ROOT' () model action
-- @
--
-- 'ROOT' is a type tag for top-level 'Component' — one with no @parent@.
--
-- @
-- data 'ROOT'
-- @
--
-- 'startApp' and 'miso' will always infer @parent@ as 'ROOT'.
--
-- = t'View' DSL
--
-- The 'View' type represents the virtual DOM — a [Rose tree](https://en.wikipedia.org/wiki/Rose_tree)
-- of nodes mutually recursive with 'Component' via the 'view' function.
--
-- @
-- data 'View' model action
--   = 'VNode' 'Namespace' 'Tag' ['Attribute' action] ['View' model action]
--   | 'VText' (Maybe 'Key') 'MisoString'
--   | 'VComp' (Maybe 'Key') ('SomeComponent' model)
--   | 'VFrag' (Maybe 'Key') ['View' model action]
-- @
--
-- 'VNode' and 'VText' have a one-to-one mapping from the virtual DOM to the physical DOM. The 'VComp' and 'VFrag' constructors are abstract (live only on the virtual DOM) and do not contain a reference to the physical DOM. The existential 'SomeComponent' is what allows embedding polymorphic 'Component' within a 'View'.
--
-- @
-- data 'SomeComponent' parent
--   = forall model action props . (Eq model, Eq props)
--   => 'SomeComponent' props ('Component' parent props model action)
-- @
--
-- The smart constructors:
--
-- * 'node', 'vnode' — build a 'VNode'
-- * 'text', 'vtext' — build a 'VText'
-- * 'component', 'vcomp' — build a 'VComp' ('vcomp' is a synonym for 'component')
-- * 'fragment', 'vfrag', 'fragment_', 'vfrag_' — build a 'VFrag'
-- * ('+>') — key and mount a child 'Component'
--
-- A full list of element smart constructors built on 'node' (e.g. 'Miso.Html.Element.div_') can be found in "Miso.Html.Element".
--
-- = 'VComp'
--
-- == Composition
--
-- @miso@ 'Component' can contain other 'Component'. This is
-- accomplished through the 'Component' mounting combinator ('+>'). This combinator
-- is responsible for encoding a typed 'Component' hierarchy, allowing 'Component'
-- type-safe read-only access to their @parent@ model state.
--
-- This combinator unifies the parent @model@ with the child @parent@, and
-- subsequently the grandchild @parent@ unifies with the child @model@. This
-- gives us a correct-by-construction 'Component' hierarchy.
--
-- @
-- ('+>')
--   :: forall child model action a . Eq child
--   => 'MisoString'
--   -> 'Component' model () child action
--   -> 'View' model a
-- key '+>' vcomp = 'VComp' (Just (toKey key)) ('SomeComponent' () vcomp)
-- @
--
-- Practically, using this combinator looks like:
--
-- @
-- view :: props -> Int -> 'View' Int action
-- view _ _ = 'div_' [ 'id_' "container" ] [ "counter" '+>' counter ]
-- @
--
-- The @\"counter\"@ string is a unique 'Key' that identifies the 'Component' at runtime. These keys are very important when
-- diffing two 'Component' together. When intentionally replacing 'Component' it is important
-- to specify a new 'Key', otherwise the 'Component' will not be unmounted.
--
-- It is possible to mount a component using the 'mount_' function, which avoids specifying a 'key_', but this should only be used
-- when the user is certain they will not be diffing their 'Component' with another 'Component'. When in doubt, use the ('+>') combinator
-- and 'key_' your 'Component'.
--
-- == Lifecycle hooks
--
-- 'Component's are mounted during diffing. All t'Component' are equipped with 'Miso.Types.mount' and 'Miso.Types.unmount' hooks, allowing custom actions to be dispatched in response to lifecycle events.
--
-- * 'Miso.Types.mount'
-- * 'Miso.Types.unmount'
--
-- = 'VNode' (Element nodes)
--
-- A 'VNode' represents a [DOM element node](https://developer.mozilla.org/en-US/docs/Web/API/Element) — the most common kind of virtual DOM node.
-- It carries a 'Namespace', a tag name, a list of 'Attribute' values, and a list of child 'View' nodes:
--
-- @
-- 'VNode' 'HTML' "div" [ 'id_' "container" ] [ "Hello, world!" ]
-- @
--
-- In practice you will rarely construct 'VNode' directly. Instead use the element smart constructors
-- from "Miso.Html.Element", which fix the namespace and tag for you:
--
-- @
-- 'div_'    [ 'id_' "container" ] [ "Hello, world!" ]
-- 'button_' [ 'onClick' DoSomething ] [ "Click me" ]
-- 'h1_'     [ 'className' "title" ] [ 'text' (ms pageTitle) ]
-- @
--
-- For elements not covered by "Miso.Html.Element", use 'node' (or its synonym 'vnode') directly:
--
-- @
-- 'node' 'HTML' "details" [] [ 'node' 'HTML' "summary" [] [ "More info" ] ]
-- @
--
-- SVG and MathML elements use the 'SVG' and 'MATHML' namespaces respectively,
-- and are covered by the smart constructors in "Miso.Svg.Element" and "Miso.Mathml.Element".
--
-- Unlike 'VComp' and 'VFrag', 'VNode' has a one-to-one correspondence with a physical DOM element:
-- each 'VNode' in the virtual DOM maps to exactly one element in the browser.
--
-- The smart constructors for 'VNode' are:
--
-- * 'node'  — raw constructor, takes 'Namespace', tag, attributes, children
-- * 'vnode' — synonym for 'node'
-- * All combinators in "Miso.Html.Element", "Miso.Svg.Element", "Miso.Mathml.Element"
--
-- == Lifecycle hooks
--
-- Like t'Component', 'VNode' elements expose lifecycle hooks.
--
-- * 'Miso.Event.onBeforeCreated'
-- * 'Miso.Event.onCreated' / 'Miso.Event.onCreatedWith'
-- * 'Miso.Event.onBeforeDestroyed' / 'Miso.Event.onBeforeDestroyedWith'
-- * 'Miso.Event.onDestroyed'
--
-- These are useful for initializing and tearing down third-party libraries, as in the example below using [highlight.js](https://highlightjs.org/)
--
-- @
-- {-# LANGUAGE QuasiQuotes -#}
-- {-# LANGUAGE MultilineStrings -#}
--
-- import Miso
-- import Miso.FFI.QQ (js)
--
-- data Action = Highlight DOMRef
--
-- update :: Action -> 'Effect' parent props model Action
-- update = \\case
--   Highlight domRef -> 'io_' $ do
--     ['js'| hljs.highlight(${domRef}) |]
--
-- view :: props -> model -> 'View' model Action
-- view _ x =
--   'code_'
--   [ 'onCreatedWith' Highlight
--   ]
--   [ """
--     function addOne (x) { return x + 1; }
--     """
--   ]
-- @
--
-- As a convention, the @*with@ variant of 'VNode' lifecycle hooks (e.g. 'Miso.Event.onCreatedWith') provides the target 'DOMRef' in the callback.
--
-- = 'VText' (Text nodes)
--
-- A 'VText' node represents a [DOM text node](https://developer.mozilla.org/en-US/docs/Web/API/Text).
-- Unlike 'VComp' and 'VFrag', 'VText' has a one-to-one correspondence with a physical DOM node:
-- each 'VText' in the virtual DOM maps to exactly one @Text@ node in the browser.
--
-- The simplest way to produce a 'VText' is via the 'IsString' instance on @'View' model action@.
-- String literals inside a child list are automatically promoted to 'VText' nodes without
-- any extra imports:
--
-- @
-- 'div_' [] [ "Hello, world!" ]
-- @
--
-- For dynamic content, use the 'text' smart constructor with a 'MisoString':
--
-- @
-- 'div_' [] [ 'text' (ms userName) ]
-- @
--
-- == HTML Encoding
--
-- When compiling with the @ssr@ flag (server-side rendering), 'text' automatically
-- HTML-encodes its argument — @\<@, @\>@, @&@, @\"@, and @\'@ are replaced with their
-- respective HTML entities. This prevents accidental XSS when rendering user-supplied
-- strings on the server.
--
-- @
-- -- SSR output: &lt;b&gt;bold&lt;\/b&gt;
-- 'text' "\<b\>bold\<\/b\>"
-- @
--
-- To embed pre-rendered or trusted content without escaping, use 'textRaw'. It is a
-- no-op on the client and bypasses encoding on the server:
--
-- @
-- 'textRaw' "\<b\>bold\<\/b\>"   -- server and client: \<b\>bold\<\/b\>
-- @
--
-- == Concatenating Multiple Strings
--
-- 'text_' accepts a list of 'MisoString' values and joins them with a single space,
-- which is useful when building text from multiple pieces without manual concatenation:
--
-- @
-- -- Renders: Hello world
-- 'div_' [] [ 'text_' [ "Hello", "world" ] ]
-- @
--
-- == Keyed Text Nodes
--
-- A 'VText' may optionally carry a 'Key'. Keyed text nodes participate in the same
-- reconciliation algorithm as keyed 'VNode' and 'VFrag' nodes. Providing a stable key
-- lets the differ identify the node across renders, preventing unnecessary DOM text node
-- replacement when sibling order changes.
--
-- @
-- 'ul_' [] (map renderItem items)
--
-- renderItem :: Item -> 'View' model Action
-- renderItem item = 'li_' [] [ 'textKey' (itemId item) (itemLabel item) ]
-- @
--
-- 'keyed' can also attach a key to any existing 'View', including a 'VText' produced
-- by a string literal or 'text':
--
-- @
-- 'keyed' "greeting" ("Hello!" :: 'View' model action)
-- @
--
-- The smart constructors for 'VText' are:
--
-- * 'text'     — single string, HTML-encoded on the server
-- * 'vtext'    — synonym for 'text'
-- * 'textRaw'  — single string, never HTML-encoded
-- * 'text_'    — list of strings joined with a space
-- * 'textKey'  — single keyed string
-- * 'textKey_' — list of keyed strings joined with a space
-- * 'keyed'    — attach a key to any 'View', including 'VText'
--
-- = 'VFrag' (Fragment nodes)
--
-- 'VFrag' groups sibling nodes without a wrapper element in the DOM, analogous to the [React Fragment](https://react.dev/reference/react/Fragment) API (@\<\>\<\/\>@) and the browser's @DocumentFragment@.
--
-- @
-- -- Renders two \<li\> elements as direct siblings, no enclosing element
-- 'fragment' [ 'li_' [] [ 'text' "Item A" ], 'li_' [] [ 'text' "Item B" ] ]
-- @
--
-- A 'VFrag' may optionally carry a 'Key'. Keyed fragments participate in the same
-- reconciliation algorithm as keyed 'VNode' and 'VText' nodes, allowing the virtual
-- DOM differ to identify, reorder, and reuse groups of siblings efficiently.
--
-- @
-- -- Keyed fragment — survives reordering without full teardown\/remount
-- 'vfrag_' "my-key" [ 'li_' [] [ 'text' "Item A" ], 'li_' [] [ 'text' "Item B" ] ]
-- @
--
-- Fragments may be nested — a 'VFrag' child may itself be a 'VFrag'. The diff function
-- recurses into nested fragments and processes all fragments as if they were
-- a flat sequence of sibling DOM nodes, so nesting carries no runtime cost beyond the extra 'VFrag' constructor allocation.
--
-- Empty fragments (@'fragment' []@) in child nodes are erased from the virtual DOM tree in the
-- Haskell layer before they reach diffing in JavaScript and are therefore a no-op.
--
-- The smart constructors for 'VFrag' are:
--
-- * 'fragment'   — unkeyed fragment
-- * 'vfrag'      — unkeyed fragment (alias)
-- * 'fragment_'  — keyed fragment
-- * 'vfrag_'     — keyed fragment (alias, infix-friendly: @\"key\" \`vfrag_\` [...]@)
--
-- = 'Key'
--
-- A 'Key' is a unique identifier used to optimize diffing.
--
-- Virtual DOM nodes can be \"keyed\" (See 'key_'). Keys have multiple meanings in @miso@ (and react).
--
-- * Keys are used to optimize child node list diffing.
--
-- When two lists of elements are being diffed, as long as they all have unique keys, diffing large child lists will be much faster. This optimization automatically occurs when all the elements in a 'VNode' child list contain unique keys. Unless all 'View' nodes in a child list are keyed, this optimization will not fire.
--
-- * Keys are used to compare two identical nodes.
--
-- If two `VNode` are being compared (or two `VComp`) and their keys differ, the old node will be destroyed and a new one created. Otherwise, the underlying DOM node won't be removed, but its properties will be diffed. In the case of diffing two t'Component' (the 'VComp' case), if the keys differ, the 'unmount' phase will be triggered for the old 'VComp' and the 'mount' phase will be triggered for the new 'Component'. The underlying DOM reference will be replaced.
--
-- See the 'key_' property for usage (and smart constructors like 'textKey_' and ('+>') as well).
--
-- @
-- 'ul_'
--   []
--   [ 'li_' [ 'key_' "key-1" ] [ "a" ]
--   , 'li_' [ 'key_' "key-2" ] [ "b" ]
--   , "key-3" '+>' counter
--   , 'textKey' "key-4" "text here"
--   , 'vfrag_' "key-5" [ "foo", "bar" ]
--   ]
-- @
--
-- = 'Events'
--
-- * Event Delegation
--
-- By default all events are delegated through @\<body\>@. Miso supports both @capture@ and @bubble@ phases of browser events.
-- Users can handle both phases in their applications.
--
-- * Using events
--
-- Miso exposes a 'defaultEvents' for convenience, these events are commonly used events and listened for on @\<body\>@. They get routed through the 'View' to the virtual DOM node that raised the event. Other 'Events' are exposed as conveniences (e.g. 'touchEvents'). All events required by all 'Component' must be combined together for use when running your application (e.g. @keyboardEvents <> touchEvents@).
--
-- @
-- 'touchEvents' :: 'Events'
-- 'touchEvents' = M.fromList
--   [ ("touchstart", 'BUBBLE')
--   , ("touchcancel", 'BUBBLE')
--   , ("touchmove", 'BUBBLE')
--   , ("touchend", 'BUBBLE')
--   ]
-- @
--
-- * Defining event handlers
--
-- Users can define their own event handlers using the 'Miso.Event.on' combinator. By default this will define an event in the 'Miso.Event.Types.BUBBLE' phase. See 'Miso.Event.onCapture' for handling events during the 'Miso.Event.Types.CAPTURE' phase. See the module "Miso.Html.Event" for many predefined events.
--
-- @
-- 'onChangeWith' :: ('MisoString' -> 'DOMRef' -> action) -> 'Attribute' action
-- 'onChangeWith' = 'on' "change" 'valueDecoder'
-- @
--
-- The @*with@ variant of events (e.g. 'Miso.Event.onChangeWith') provides the target 'DOMRef' in the callback function.
--
-- * Decoding events
--
-- After an event has been raised, one can extract information from the event for use in their application. This is accomplished through a 'Decoder'. Many common decoders are available for use in "Miso.Event.Decoder".
--
-- @
-- data 'Decoder' a
--   = 'Decoder'
--   { 'decoder' :: 'Value' -> 'Parser' a
--   , 'decodeAt' :: 'DecodeTarget'
--   }
--
-- -- | Example of a custom 'Decoder' for the @value@ property of an event target.
-- 'valueDecoder' :: 'Decoder' 'MisoString'
-- 'valueDecoder' = Decoder {..}
--   where
--     decodeAt = 'DecodeTarget' ["target"]
--     decoder = 'withObject' "target" $ \\o -> o .: "value"
-- @
--
-- = Attributes / Properties
--
-- The 'Attribute' type carries everything that can be attached to a DOM element:
--
-- @
-- data 'Attribute' action
--   = 'Property' 'MisoString' 'Miso.JSON.Value'          -- ^ DOM property (key/value)
--   | 'ClassList' ['MisoString']                         -- ^ CSS class list
--   | 'On' ('Sink' action -> ...)                        -- ^ Event handler
--   | 'Styles' ('Data.Map.Strict.Map' 'MisoString' 'MisoString') -- ^ Inline style map
-- @
--
-- In practice you never construct these directly. Use the smart constructors from
-- "Miso.Html.Property", "Miso.Html.Event", "Miso.Property", and "Miso.CSS":
--
-- @
-- 'div_'
--   [ 'id_' "container"                    -- textProp "id"
--   , 'className' "card active"            -- textProp "class"
--   , 'classList' ["card", "active"]       -- ClassList (alternative)
--   , 'disabled_'                          -- boolProp "disabled" True
--   , 'onClick' MyAction                   -- On event handler
--   , 'Miso.CSS.style_' [ 'Miso.CSS.display' "flex" ] -- Styles map
--   ]
--   []
-- @
--
-- == Custom properties
--
-- Use 'prop' (or the typed variants 'textProp', 'boolProp', 'intProp', 'doubleProp',
-- 'objectProp') from "Miso.Property" to set arbitrary DOM properties:
--
-- @
-- 'prop' "data-index" (42 :: Int)      -- sets element.data-index = 42
-- 'textProp' "placeholder" "Search…"  -- sets element.placeholder
-- 'boolProp' "checked" True            -- sets element.checked = true
-- @
--
-- Note that DOM /properties/ and HTML /attributes/ are distinct. Miso sets
-- properties on the DOM node object (e.g. @node.checked@) rather than the
-- HTML attribute (e.g. @setAttribute("checked", ...)@). This matches what
-- the browser actually exposes in JavaScript and avoids common pitfalls with
-- boolean attributes.
--
-- == Keys
--
-- 'key_' (and its alias 'keyProp') attaches a reconciliation key to any element.
-- See the @'Key'@ section for details.
--
-- @
-- 'li_' [ 'key_' (itemId item) ] [ 'text' (itemLabel item) ]
-- @
--
-- = 'Effect'
--
-- The 'Effect' type is used to mutate the @model@ over time in response to @action@.
-- 'Effect' also allows 'IO' to be scheduled for evaluation by the @miso@ scheduler.
--
-- Note: 'IO' is never evaluated inside of 'Effect', it is only scheduled.
-- There is no 'MonadIO' instance for 'Effect'.
--
-- The 'Effect' type is defined as a 'RWS'.
--
-- @
-- type 'Effect' parent props model action = 'RWS' ('ComponentInfo' parent props) ['Schedule' action] model ()
-- @
--
-- * The 'Control.Monad.Reader' portion of 'Effect' is 'ComponentInfo'. 'ask', 'asks', 'Miso.Lens.view' can be used to access its fields.
-- * The 'Control.Monad.Writer' portion of 'Effect' is used to schedule t'IO' actions. 'tell' can be used to create a 'Schedule' for an 'IO' action that is executed according to 'Synchronicity'. See also 'withSink' for usage.
-- * The 'Control.Monad.State' portion of 'Effect' is used to manipulate the @model@. 'get', 'put', 'modify', and the 'Control.Monad.State.MonadState' lenses in t'Miso.Lens.Lens' can be used to modify the @model@.
--
-- 'IO' can be performed either synchronously or asynchronously. By default all 'IO' is asynchronous
--
-- == Asynchronous 'IO'
--
-- * 'io': Used to introduce asynchronous 'io' into the system, see also the 'io_' variant.
--
-- * 'withSink': The core function (from which most other combinators are defined)
--   that gives users access to the underlying event 'Sink'. This also allows us to
--   introduce 'IO' into the system. The @miso@ scheduler attaches exception
--   handlers to all 'IO' actions.
--
-- * For maximum flexibility, the 'MonadWriter' instance ('tell') can be used to schedule 'IO' (see the 'withSink' implementation).
--
-- == Synchronous 'IO'
--
-- * 'sync': Forces the scheduler to evaluate 'IO' synchronously. It is
--   recommended to use the 'io' function by default, 'sync' *will* block the scheduler.
--
-- == 'Sink'
--
-- @
-- type 'Sink' action = action -> 'IO' ()
-- @
--
-- The 'Sink' function allows one to write any @action@ to the global event queue. See 'withSink' for more information.
--
-- == Managing 'model' state.
--
-- Any 'MonadState' function is allowed for use when manipulating @model@, 'Miso.State.get', 'Miso.State.put', etc. See "Miso.State".
--
-- The 'MonadReader' instances allows the retrieval of 'ComponentInfo' within 'Effect'.
-- 'ComponentInfo' provides the current 'ComponentId' the @parent@ 'ComponentId', and the 'DOMRef' ('_componentDOMRef') that the 'Component' is mounted on.
--
-- = 'Component' communication
--
-- Miso provides three mechanisms for 'Component' to exchange data:
--
-- * __Props__ — synchronous, parent-to-child read-only data passed at mount time (see below).
-- * __Async mailbox__ — message-passing via 'mail' / 'broadcast' / 'checkMail'; any 'Component' can send a t'Miso.JSON.Value' to any other by 'ComponentId'.
-- * __PubSub__ ("Miso.PubSub") — publish\/subscribe for fan-out messaging across unrelated 'Component'.
--
-- == Props
--
-- Inspired by [React props](https://react.dev/learn/passing-props-to-a-component),
-- @miso@ allows a parent 'Component' to pass read-only data down to a child 'Component'
-- via a mechanism called /props/ (short for /properties/).
--
-- === Props vs. Component-local state
--
-- * __model__: Component-local state. It is owned and mutated exclusively by the 'Component'
--   itself through its 'Miso.Types.update' function. No other 'Component' can write to it directly.
--
-- * __props__: Data /inherited/ from the @parent@ 'Component'. Props flow downward through
--   the component hierarchy and are read-only from the child's perspective. The parent decides
--   what props to pass at mount time; the child cannot mutate them. Props that change in a
--   the parent cause the child to re-render.
--
-- This mirrors the distinction in React between component state (@useState@) and props
-- received from above (@function MyComponent({ name }) { ... }@).
--
-- ==== When to use props
--
-- Props are best suited for /metadata/ — contextual or configuration data that the child needs
-- to know about but should not own. Good examples: a user's display name, a theme token, a
-- locale string, or a read-only identifier used to customise rendering.
--
-- If the data drives the child's own business logic — counters it increments, form fields it
-- edits, async state it manages — that data belongs in the child's @model@ instead. Putting
-- mutable business-logic state in @props@ would require the parent to own and thread through
-- every change, creating unnecessary coupling. Prefer @props@ for \"what the child should
-- know\" and @model@ for \"what the child should do\".
--
-- === Props in 'Miso.Types.view'
--
-- The 'Miso.Types.view' field of a 'Component' always takes @props@ as its first argument:
--
-- @
-- view :: props -> model -> 'View' model action
-- @
--
-- Top-level applications have no parent, so @props@ is always @()@:
--
-- @
-- view :: () -> model -> 'View' model action
-- view _props model = …
-- @
--
-- === Props in 'Effect' \/ 'Miso.Types.update'
--
-- Use 'getProps' inside the 'Effect' monad to read the current value of @props@:
--
-- @
-- update :: Action -> 'Effect' parent props Model Action
-- update = \\case
--   SomeAction -> do
--     p <- 'getProps'
--     'io_' ('consoleLog' (ms (show p)))
-- @
--
-- Alternatively, use the 'Miso.Lens.view' combinator with the 'props' lens:
--
-- @
-- update = \\case
--   SomeAction -> do
--     p <- 'Miso.Lens.view' 'props'
--     …
-- @
--
-- === 'ROOT' — the top-level 'Component'
--
-- When a 'Component' is passed to 'startApp' (or 'miso') it has no parent.
-- The @parent@ type is specialized to 'ROOT' and @props@ is fixed to @()@:
--
-- @
-- type 'App' model action = 'Component' 'ROOT' () model action
-- @
--
-- Because there is no parent to inherit from, @props@ will always be @()@ for a
-- root-level 'Component'. You can simply ignore the first argument in 'view' and
-- skip 'getProps' in 'Miso.Types.update'.
--
-- === Passing props to a child 'Component'
--
-- Use 'mountWithProps_' (keyed) or 'mountWithProps' (unkeyed) in the parent's 'view' to
-- mount a child and supply its props:
--
-- @
-- 'mountWithProps_'
--   :: ('Eq' child, 'Eq' props)
--   => 'MisoString'
--   -> props
--   -> 'Component' parent props child action
--   -> 'View' parent a
-- @
--
-- === Example: child reading parent-supplied props
--
-- The following shows a parent 'Component' that maintains a greeting string in its
-- @model@ and passes it as @props@ to a child 'Component'. The child renders the
-- greeting and can also read it from within its 'Miso.Types.update' function.
--
-- @
-- -----------------------------------------------------------------------------
-- -- The props type: what the parent shares with the child
-- newtype Greeting = Greeting 'MisoString' deriving ('Eq')
-- -----------------------------------------------------------------------------
-- -- Child component
-- --
-- --                  parent      props    model  action
-- --                  |           |        |      |
-- child :: 'Component' ParentModel Greeting ()     ChildAction
-- child = 'vcomp' () updateChild viewChild
--   where
--     viewChild :: Greeting -> () -> 'View' () ChildAction
--     viewChild (Greeting g) _ =
--       'div_' [] [ 'text' ("Hello, " <> g <> "!") ]
--
--     updateChild :: ChildAction -> 'Effect' ParentModel Greeting () ChildAction
--     updateChild = \\case
--       ReadGreeting -> do
--         Greeting g <- 'getProps'
--         'io_' ('consoleLog' g)
-- -----------------------------------------------------------------------------
-- -- Parent component: owns the greeting, passes it to the child as props
-- parent :: 'App' ParentModel ParentAction
-- parent = 'vcomp' (ParentModel "World") 'noop' viewParent
--   where
--     viewParent :: () -> ParentModel -> 'View' ParentModel ParentAction
--     viewParent _ (ParentModel g) =
--       'mountWithProps_' "child" (Greeting g) child
-- -----------------------------------------------------------------------------
-- newtype ParentModel = ParentModel 'MisoString' deriving ('Eq')
-- data ChildAction = ReadGreeting
-- data ParentAction
-- @
--
-- A few things to notice:
--
-- * The child's @parent@ type parameter is @ParentModel@. This must match the
--   parent 'Component' @model@ type — 'mountWithProps_' enforces this at compile time.
-- * 'getProps' inside the child's 'Miso.Types.update' yields a @Greeting@, not
--   the full @ParentModel@. The child only sees what the parent explicitly chose to share.
-- * The root 'App' always has @props ~ ()@; no extra plumbing is needed when calling 'startApp'.
--
--
-- == Asynchronous communication
--
-- Every 'Component' has a 'mailbox' — a slot that receives t'Miso.JSON.Value' messages
-- sent by other components. Messages are dispatched asynchronously via the event queue.
--
-- === Sending
--
-- * 'mail' @componentId msg@ — send to a specific 'ComponentId' (obtained via 'ask' inside 'Effect')
-- * 'mailParent' @msg@ — send to the direct parent
-- * 'mailChildren' @msg@ — send to all immediate children
-- * 'mailAncestors' @msg@ — walk up the hierarchy, delivering to every ancestor
-- * 'mailDescendants' @msg@ — walk down the hierarchy, delivering to every descendant
-- * 'broadcast' @msg@ — deliver to every mounted 'Component' except the sender
--
-- === Receiving with 'checkMail'
--
-- Wire up the 'mailbox' field on 'Component' using 'checkMail', which handles
-- JSON parsing and routes to success\/error actions:
--
-- @
-- data Action
--   = ReceivedMsg MyMsg
--   | MailError   MisoString
--
-- myComp :: 'Component' parent props model Action
-- myComp = ('vcomp' m u v)
--   { 'mailbox' = 'checkMail' ReceivedMsg MailError }
-- @
--
-- === Looking up a 'ComponentId'
--
-- Inside 'Effect', use 'ask' to obtain a t'ComponentInfo':
--
-- @
-- update = \\case
--   SendMsg targetId -> do
--     'io_' ('mail' targetId ("hello" :: 'MisoString'))
--   GetMyId -> do
--     info <- 'ask'
--     let myId = '_componentInfoId' info
--     ...
-- @
--
-- * "Miso.PubSub" — publish\/subscribe pattern for fan-out messaging across unrelated components.
--
-- == Synchronous communication
--
-- * "Miso.Binding"
--
-- Experimental support for data bindings (where 'Component' model can synchronize fields via a 'Miso.Lens.Lens' in response to model differences along the parent-child relationship). See the "Miso.Binding" module for more information, and the [miso-reactive](https://github.com/haskell-miso/miso-reactive) example. *Warning*: This is still considered experimental.
--
-- == Parent access
--
-- * 'parent'
--
-- While not direct communication, a 'Component' can asynchronously receive read-only access to its @parent@ state via the 'parent' function.
--
-- = Subscriptions
--
-- A t'Sub' is any long-running operation that is external to a 'Component', but that can write
-- to a 'Component' 'Sink'. 'Sub' come in two flavors, a dynamic 'Sub' (via 'startSub' / 'stopSub') and 'subs'.
--
-- * 'subs'
--
-- @
-- main :: IO ()
-- main = 'startApp' 'defaultEvents' app { 'subs' = [ timerSub ] }
--
-- timerSub :: 'Sub' Action
-- timerSub sink = 'forever' $ ('threadDelay' 100000) >> sink Log
--
-- data Action = Log
-- @
--
-- The 'subs' field of 'Component' contains 'Sub' that exist for the lifetime of that 'Component'.
-- When a 'Component' unmounts, these 'Sub' will be stopped, and their resources finalized.
--
-- @
-- 'onLineSub' :: (Bool -> action) -> 'Sub' action
-- 'onLineSub' f sink = 'Miso.Subscription.Util.createSub' acquire release sink
--   where
--     release (cb1, cb2) = do
--       'Miso.FFI.windowRemoveEventListener' "online"  cb1
--       'Miso.FFI.windowRemoveEventListener' "offline" cb2
--     acquire = do
--       cb1 <- 'Miso.FFI.windowAddEventListener' "online"  (const $ sink (f True))
--       cb2 <- 'Miso.FFI.windowAddEventListener' "offline" (const $ sink (f False))
--       pure (cb1, cb2)
-- @
--
-- * 'startSub' / 'stopSub'
--
-- At times its necessary to dynamically generate a 'Sub' in reponse to an event (e.g. starting a "Miso.WebSocket" connection
-- when a user logs in). The 'startSub' and 'stopSub' functions facilitate dynamic 'Sub' creation / removal.
--
-- @
-- update = \\case
--   StartTimer -> 'startSub' ("timer" :: MisoString) timerSub
--   StopTimer -> 'stopSub' "timer"
--   Log -> 'io_' ('consoleLog' "log")
--     where
--       timerSub :: 'Sub' Action
--       timerSub sink = 'Control.Monad.forever' $ ('Control.Concurrent.threadDelay' 100000) >> sink Log
--
-- data Action = Log
-- @
--
-- * 'Miso.Subscription.Util.createSub'
--
-- 'Miso.Subscription.Util.createSub' is a helper function for creating a 'Sub' using the 'Control.Exception.bracket' pattern.
-- This ensures that event listeners can be unregistered when a 'Component' unmounts. For example usage
-- please see the "Miso.Subscription" sub modules. 'createSub' is only meant to be used in scenarios where
-- custom event listeners are required.
--
-- = 'Control.Monad.State.State' management
--
-- Miso bundles a lightweight lens library in "Miso.Lens" to minimise dependencies
-- and payload size. Any lens library (optics, lens) also works — "Miso.Lens" is not required.
--
-- == Basic lens operations
--
-- @
-- 'Miso.Lens.view' l   -- read a field (MonadReader)
-- 'set'  l v           -- write a field
-- 'over' l f           -- modify a field
-- r '^.' l             -- infix read
-- r '&' l '.~' v       -- infix write
-- @
--
-- == 'MonadState' operators (for use inside 'Effect')
--
-- @
-- l '+=' n   -- increment a numeric field
-- l '-=' n   -- decrement
-- l '*=' n   -- multiply
-- @
--
-- == 'this' — the identity lens
--
-- When the model /is/ the field (e.g. the model is a plain @Int@), use 'this':
--
-- @
-- update = \\case
--   Increment -> 'this' '+=' 1
--   Decrement -> 'this' '-=' 1
-- @
--
-- == Generating lenses
--
-- Three approaches, pick one:
--
-- * __Template Haskell__ ("Miso.Lens.TH"): 'makeLenses' / 'makeClassy' splice lenses for each record field.
--
-- @
-- {-# LANGUAGE TemplateHaskell #-}
-- import Miso.Lens.TH (makeLenses)
--
-- data Model = Model { _count :: Int, _name :: MisoString }
-- makeLenses ''Model
--
-- update = \\case
--   Increment -> count '+=' 1
--   Rename n  -> name '.=' n
-- @
--
-- * __Generics__ ("Miso.Lens.Generic"): 'field' \/ 'HasLens' derive lenses at compile time
--   using @GHC.Generics@ — no TH splice required. Requires @TypeApplications@ and,
--   optionally, @OverloadedLabels@ for the @#field@ shorthand.
--
-- @
-- {-# LANGUAGE DataKinds          #-}
-- {-# LANGUAGE DeriveGeneric      #-}
-- {-# LANGUAGE OverloadedLabels   #-}
-- {-# LANGUAGE TypeApplications   #-}
-- import GHC.Generics (Generic)
-- import Miso.Lens.Generic (field)
--
-- data Model = Model { count :: Int, name :: MisoString }
--   deriving (Eq, Generic)
--
-- update = \\case
--   Increment -> 'field' \@\"count\" '+=' 1          -- via TypeApplications
--   Rename n  -> #name '.=' n                     -- via OverloadedLabels
-- @
--
-- * __Hand-written__: construct a 'Lens' directly using 'lens' and the @'Lens' s a@ synonym.
--
-- @
-- name :: 'Lens' Person 'MisoString'
-- name = 'lens' _name $ \\p n -> p { _name = n }
-- @
--
-- = (2D/3D) Canvas support
--
-- Miso has full 2D and 3D canvas support via "Miso.Canvas". See also the
-- [miso-canvas](https://github.com/haskell-miso/miso-canvas2d) example and the
-- [three-miso](https://github.com/haskell-miso/three-miso) package for Three.js integration.
--
-- == The 'Miso.Canvas.Canvas' monad
--
-- Drawing commands run in the 'Miso.Canvas.Canvas' monad, which is a 'ReaderT' over a
-- @CanvasContext2D@ (the raw JavaScript @CanvasRenderingContext2D@):
--
-- @
-- type Canvas a = ReaderT CanvasContext2D IO a
-- @
--
-- == Embedding a canvas in the view
--
-- Use the 'Miso.Canvas.canvas' smart constructor.
-- It takes an /init/ callback (runs once on mount, returns state) and a
-- /draw/ callback (runs on every render with the current state):
--
-- @
-- 'Miso.Canvas.canvas'
--   [ HP.'width_' "800", HP.'height_' "480" ]
--   (\\_ -> pure ())                   -- init: called once on canvas initialization
--   (\\() -> drawScene myModel)        -- draw: called many times, on each diff.
-- @
--
-- 'Miso.Canvas.canvas_' is the variant that threads no init state at all (always passes @()@).
--
-- == Drawing commands
--
-- Common 2D primitives:
--
-- @
-- drawScene :: Model -> 'Miso.Canvas.Canvas' ()
-- drawScene model = do
--   'Miso.Canvas.clearRect' (0, 0, 800, 480)
--   'Miso.Canvas.fillStyle' ('Miso.CSS.Color.RGB' 30 144 255)
--   'Miso.Canvas.beginPath' ()
--   'Miso.Canvas.arc' (400, 240, 50, 0, 2 * pi)
--   'Miso.Canvas.fill' ()
--   'Miso.Canvas.font' "24px sans-serif"
--   'Miso.Canvas.fillText' ("Score: " \<\> ms (score model), 10, 30)
-- @
--
-- Available primitives include: 'Miso.Canvas.clearRect', 'Miso.Canvas.fillRect', 'Miso.Canvas.strokeRect',
-- 'Miso.Canvas.beginPath', 'Miso.Canvas.closePath', 'Miso.Canvas.moveTo', 'Miso.Canvas.lineTo',
-- 'Miso.Canvas.arc', 'Miso.Canvas.arcTo', 'Miso.Canvas.fill', 'Miso.Canvas.stroke',
-- 'Miso.Canvas.fillText', 'Miso.Canvas.drawImage'.
--
-- Style setters: 'Miso.Canvas.fillStyle', 'Miso.Canvas.strokeStyle', 'Miso.Canvas.lineWidth', 'Miso.Canvas.font'.
-- 'Miso.Canvas.fillStyle' and 'Miso.Canvas.strokeStyle' accept a 'Miso.Canvas.StyleArg' — use
-- 'Miso.Canvas.color' (not 'Miso.CSS.color') to construct one from a t'Miso.CSS.Color.Color' value.
-- See the __Canonical Import Pattern__ section for how to avoid the name collision
-- between 'Miso.Canvas.color' and 'Miso.CSS.color'.
--
-- == Animation loop
--
-- For smooth 60 FPS canvas animations, use 'Miso.Subscription.RAF.rAFSub' from
-- "Miso.Subscription.RAF" instead of a manual 'threadDelay' loop.
-- It hooks into the browser's @requestAnimationFrame@ API and delivers a
-- [DOMHighResTimeStamp](https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp)
-- (milliseconds) on each frame:
--
-- @
-- data Action = Tick Double
--
-- main :: IO ()
-- main = startApp defaultEvents comp { subs = [ 'Miso.Subscription.RAF.rAFSub' Tick ] }
-- @
--
-- = HTML
--
-- Miso's 'View' type doubles as an HTML serialiser via the 'ToHtml' class in
-- "Miso.Html.Render". This is used for server-side rendering (SSR): build a
-- 'View' with the normal DSL and render it to a lazy 'Data.ByteString.Lazy.ByteString'
-- on the server.
--
-- @
-- class 'ToHtml' a where
--   'toHtml' :: a -> 'Data.ByteString.Lazy.ByteString'
-- @
--
-- Instances are provided for @'View' m a@ and @['View' m a]@:
--
-- @
-- import Miso.Html.Render (toHtml)
--
-- pageHtml :: 'Data.ByteString.Lazy.ByteString'
-- pageHtml = 'toHtml' $ 'div_' [ 'id_' "root" ] [ "Hello, world!" ]
-- @
--
-- This is typically wired into a Servant handler on the server using the
-- [servant-miso-html](https://github.com/haskell-miso/servant-miso-html) package,
-- which provides an @HTML@ content-type that serialises 'View' and 'Component'
-- values directly — no manual 'ByteString' conversion needed:
--
-- @
-- import Servant.Miso.Html (HTML)
--
-- type Home    = \"home\"    :\> Get '[HTML] (Component model action)
-- type About   = \"about\"   :\> Get '[HTML] (View model action)
-- type Contact = \"contact\" :\> Get '[HTML] [View model action]
-- type API = Home :\<|\> About :\<|\> Contact
-- @
--
-- On the client, pass the matching 'Component' to 'miso' (instead of 'startApp')
-- so it hydrates the server-rendered markup rather than redrawing from scratch.
-- See the __Prerendering__ section for the full flow.
--
-- = JavaScript EDSL
--
-- "Miso.DSL" provides a JavaScript DSL inspired by [jsaddle](https://hackage.haskell.org/package/jsaddle)
-- for interacting with the browser from Haskell.
--
-- == Key operators
--
-- * '(Miso.DSL.!)' — property access: @obj '!' "key"@ reads @obj.key@
-- * '(Miso.DSL.#)' — method call: @obj '#' "method" args@ calls @obj.method(args)@
-- * 'Miso.DSL.jsg' — access a global JS variable by name
-- * 'Miso.DSL.jsgf' — call a global JS function by name with arguments
--
-- @
-- -- Read document.body.children.length
-- document <- 'Miso.DSL.jsg' "document"
-- len :: 'Int' <- 'Miso.DSL.fromJSValUnchecked' =<< (document 'Miso.DSL.!' "body" 'Miso.DSL.!' "children" 'Miso.DSL.!' "length")
--
-- -- Call console.log("hello")
-- console <- 'Miso.DSL.jsg' "console"
-- console 'Miso.DSL.#' "log" $ ["hello" :: 'MisoString']
-- @
--
-- == Marshalling
--
-- 'Miso.DSL.ToJSVal' converts Haskell values to 'Miso.DSL.JSVal' for passing into JavaScript.
-- 'Miso.DSL.FromJSVal' converts 'Miso.DSL.JSVal' back to Haskell.
-- 'Miso.DSL.fromJSValUnchecked' throws on failure; use 'Miso.DSL.fromJSVal' for a safe @Maybe@ variant.
--
-- = QuasiQuotation (@inline-js@)
--
-- "Miso.FFI.QQ" provides the 'Miso.FFI.QQ.js' QuasiQuoter for embedding inline JavaScript
-- directly in Haskell source. Any Haskell binding in scope can be interpolated into
-- the JavaScript body with @${varName}@ syntax — miso uses the binding's 'Miso.DSL.ToJSVal'
-- instance to marshal it across the boundary at runtime.
--
-- @
-- {-# LANGUAGE QuasiQuotes #-}
--
-- import Miso.FFI.QQ ('Miso.FFI.QQ.js')
--
-- -- Fire-and-forget: pass a value to a JS library
-- update :: Action -> 'Effect' parent props model Action
-- update = \\case
--   Log msg -> 'io_' ['Miso.FFI.QQ.js'| console.log(${msg}) |]
--
-- data Action = Log MisoString
-- @
--
-- == Returning values from JavaScript
--
-- The return type is inferred from the call site via 'Miso.DSL.FromJSVal'.
-- Use an explicit type annotation or a @do@-binding to drive inference:
--
-- @
-- fac :: Int -> IO Int
-- fac n = ['Miso.FFI.QQ.js'|
--   let x = 1;
--   for (let i = 1; i <= ${n}; i++) { x *= i; }
--   return x;
-- |]
-- @
--
-- Haskell variables referenced inside the quoter must be in scope at the splice
-- site; the compiler will report an error if a @${name}@ has no corresponding binding.
--
-- = Routing
--
-- "Miso.Router" provides a reversible, type-safe client-side router. A @Route@
-- type encodes URL structure; the 'Router' class converts between routes and
-- 'URI' values in both directions. Use it with 'Miso.Subscription.History.routerSub'
-- or 'Miso.Subscription.History.uriSub' to react to browser navigation.
--
-- == Defining a 'Router' with Generics
--
-- Derive 'Router' via @GHC.Generics@ — constructor names become path segments
-- (camel-case uses only the first hump). Use t'Capture', t'Path', t'QueryParam',
-- and t'QueryFlag' as constructor fields to describe the URL shape:
--
-- @
-- {-# LANGUAGE DeriveGeneric  #-}
-- {-# LANGUAGE DeriveAnyClass #-}
--
-- import GHC.Generics
-- import Miso.Router
--
-- data Route
--   = Index                                                      -- matches "/"
--   | About                                                      -- matches "/about"
--   | Product (Capture "id" Int) (QueryParam "tab" MisoString)   -- matches "/product/42?tab=info"
--   deriving stock    (Show, Eq, Generic)
--   deriving anyclass Router
-- @
--
-- The router is /reversible/ — 'prettyRoute' re-serialises any route back to a URL:
--
-- @
-- 'prettyRoute' (Product (Capture 42) (QueryParam (Just "info")))
-- -- "\/product\/42?tab=info"
-- @
--
-- == Defining a 'Router' manually
--
-- For full control, implement 'routeParser' and 'fromRoute' directly:
--
-- @
-- data Route = Product Int
--
-- instance Router Route where
--   routeParser = routes [ Product \<$\> ('path' "product" *\> 'capture') ]
--   fromRoute (Product n) = [ 'toPath' "product", 'toCapture' n ]
-- @
--
-- == Subscribing to URI changes
--
-- 'Miso.Subscription.History.routerSub' listens to @popstate@ events and delivers
-- the parsed route (or a 'RoutingError') to your @update@ function:
--
-- @
-- app = ('vcomp' m u v) { 'subs' = [ 'routerSub' HandleRoute ] }
--
-- update = \\case
--   HandleRoute (Right Index)       -> 'modify' (\\m -> m { page = HomePage })
--   HandleRoute (Right About)       -> 'modify' (\\m -> m { page = AboutPage })
--   HandleRoute (Left _)            -> 'modify' (\\m -> m { page = NotFound })
-- @
--
-- 'Miso.Subscription.History.uriSub' is the lower-level variant — it delivers
-- the raw 'URI' without parsing, useful when you want to handle routing yourself.
--
-- == Navigating programmatically
--
-- @
-- 'pushURI'    uri    -- push a raw 'URI' onto the History stack
-- 'pushRoute'  route  -- push a typed route (serialised via 'Router')
-- 'replaceURI' uri    -- replace the current history entry
-- 'back'              -- go back one entry
-- 'forward'           -- go forward one entry
-- @
--
-- == Type-safe links in views
--
-- 'Miso.Router.href_' produces a type-safe @href@ attribute from any route:
--
-- @
-- 'button_' [ 'Miso.Router.href_' (Product (Capture 10) (QueryParam Nothing)) ] [ "Go to product 10" ]
-- @
--
-- = 'MisoString'
--
-- t'MisoString' is miso's canonical string type, chosen to minimise copying between
-- the Haskell and JavaScript heaps:
--
-- * __JS / WASM backends__: t'MisoString' is @JSString@, a direct reference to a
--   JavaScript string — no marshalling cost when passing to the DOM or FFI.
-- * __Server / vanilla GHC__ (@ssr@ flag): t'MisoString' is t'Data.Text'.
--
-- Use t'MisoString' anywhere you would otherwise reach for 'String' or 'Text' in a
-- miso application. See "Miso.String" for the full API.
--
-- == Converting to 'MisoString'
--
-- The 'ms' function (shorthand for 'toMisoString') converts any type with a
-- 'ToMisoString' instance:
--
-- @
-- ms "hello"          -- String    -> MisoString
-- ms (42 :: Int)      -- Int       -> MisoString
-- ms (3.14 :: Double) -- Double    -> MisoString
-- ms myText           -- Data.Text -> MisoString
-- @
--
-- 'ToMisoString' instances are provided for 'String', t'Data.Text.Text',
-- t'Data.Text.Lazy.Text', t'Data.ByteString.ByteString', 'Int', 'Word',
-- 'Double', 'Float', and 'Char'.
--
-- == Converting from 'MisoString'
--
-- 'fromMisoString' parses a t'MisoString' back into another type (throws on failure).
-- Use 'fromMisoStringEither' for a safe variant:
--
-- @
-- fromMisoString "42"     :: Int     -- 42
-- fromMisoString "3.14"   :: Double  -- 3.14
-- fromMisoStringEither s  :: Either String Int
-- @
--
-- 'FromMisoString' instances are provided for 'String', t'Data.Text.Text',
-- t'Data.Text.Lazy.Text', t'Data.ByteString.ByteString', 'Int', 'Word',
-- 'Double', and 'Float'.
--
-- == Multiline literals
--
-- "Miso.String.QQ" provides a QuasiQuoter for multiline t'MisoString' literals:
--
-- @
-- {-# LANGUAGE QuasiQuotes #-}
--
-- import Miso.String.QQ (misoString)
--
-- snippet :: MisoString
-- snippet = [misoString|
--   line one
--   line two
-- |]
-- @
--
-- t'MisoString' is also the element type used throughout "Miso.Util.Lexer" and
-- "Miso.Util.Parser".
--
-- = JSON
--
-- "Miso.JSON" is a [microaeson](https://hackage.haskell.org/package/microaeson)-inspired
-- JSON library specialised to t'MisoString'. On the JS\/WASM backends it delegates
-- encoding and decoding to the JavaScript runtime (@JSON.stringify@ \/ @JSON.parse@)
-- for performance. On the server (@ssr@ flag) it uses a pure Haskell implementation.
-- "Miso.JSON" is used internally by "Miso.Event.Decoder", "Miso.Fetch", and "Miso.WebSocket".
--
-- == 'Miso.JSON.Value'
--
-- The JSON t'Miso.JSON.Value' type mirrors the JSON specification:
--
-- @
-- data 'Miso.JSON.Value'
--   = 'Miso.JSON.Number' 'Double'
--   | 'Miso.JSON.Bool'   'Bool'
--   | 'Miso.JSON.String' 'MisoString'
--   | 'Miso.JSON.Array'  ['Miso.JSON.Value']
--   | 'Miso.JSON.Object' 'Miso.JSON.Object'
--   | 'Miso.JSON.Null'
-- @
--
-- == Encoding
--
-- Encode any 'ToJSON' instance to a t'MisoString':
--
-- @
-- 'encode' value        -- uses JS runtime on client, pure on server
-- 'encodePure' value    -- always uses pure Haskell implementation
-- @
--
-- == Decoding
--
-- @
-- 'decode' s            :: Maybe a      -- returns Nothing on failure
-- 'eitherDecode' s      :: Either MisoString a
-- @
--
-- == 'ToJSON' \/ 'FromJSON'
--
-- Derive instances via @GHC.Generics@:
--
-- @
-- {-# LANGUAGE DeriveGeneric #-}
--
-- import GHC.Generics
-- import Miso.JSON
--
-- data User = User { name :: MisoString, age :: Int }
--   deriving (Generic)
--
-- instance ToJSON   User
-- instance FromJSON User
-- @
--
-- Use 'genericToJSON' \/ 'genericParseJSON' with 'Options' to customise field and
-- constructor names. 'camelTo2' is provided for converting @camelCase@ to
-- @snake_case@ (or any separator):
--
-- @
-- instance ToJSON User where
--   toJSON = 'genericToJSON' 'defaultOptions' { 'fieldLabelModifier' = 'camelTo2' \'_\' }
-- @
--
-- == Building and Parsing Objects
--
-- @
-- -- Build
-- 'object' [ "name" '.=' ms "Alice", "age" '.=' (30 :: Int) ]
--
-- -- Parse (inside a 'withObject' callback or event decoder)
-- 'withObject' "User" $ \\o -> User
--   \<$\> o '.:' "name"     -- required field
--   \<*\> o '.:' "age"
--
-- o '.:?' "nickname"    -- optional field → Maybe a
-- o '.:!' "nickname"    -- optional field, explicit null → Maybe a
-- p '.!=' "anon"        -- provide a default for a Maybe parser
-- @
--
-- == Pretty-Printing
--
-- @
-- 'encodePretty'  value          -- indented with 'defConfig' (2-space indent)
-- 'encodePretty'' config value   -- indented with custom 'Config'
-- @
--
-- == @miso-aeson@
--
-- If you prefer to use the [aeson](https://hackage.haskell.org/package/aeson) library directly,
-- the [miso-aeson](https://github.com/haskell-miso/miso-aeson) package provides a compatibility
-- shim that bridges @aeson@\'s 'Data.Aeson.ToJSON' \/ 'Data.Aeson.FromJSON' instances with miso\'s
-- event decoder and fetch API, so existing @aeson@-derived instances can be used without rewriting them.
--
-- = Styles
--
-- Miso does not prescribe a single CSS strategy. Three approaches work out of the box:
--
-- == 1. Structured DSL ("Miso.CSS")
--
-- 'style_' takes a list of @'Style'@ values (which are @(MisoString, MisoString)@ pairs).
-- Miso manages individual properties on the DOM node, merging and diffing them efficiently:
--
-- @
-- import qualified Miso.CSS as CSS
-- import           Miso.CSS.Color (RGB(..))
--
-- 'div_'
--   [ CSS.'style_'
--       [ CSS.'display' "flex"
--       , CSS.'flexDirection' "column"
--       , CSS.'backgroundColor' (RGB 30 30 30)
--       , CSS.'color' (RGB 255 255 255)
--       ]
--   ]
--   []
-- @
--
-- Custom properties can be constructed with the '=:' operator (re-exported from "Miso.Util"):
--
-- @
-- "user-select" '=:' "none"
-- @
--
-- == 2. Inline string ('CSS.styleInline_')
--
-- For simple or dynamic style strings, 'styleInline_' sets the element's @style@
-- attribute as a raw string:
--
-- @
-- CSS.'styleInline_' "display:flex; gap:8px; padding:16px"
-- @
--
-- == 3. External stylesheets
--
-- Link external CSS files from the @\<head\>@ via the 'styles' field on 'Component'
-- (see the __Development__ section), or include them in your HTML template directly.
-- This is the most common approach for production apps using Tailwind, Bootstrap, etc.
--
-- See [miso-ui](https://ui.haskell-miso.org) for a larger example.
--
-- = Development
--
-- When developing miso applications interactively it is possible to append 'styles' and 'scripts' to the @\<head\>@ portion of
-- the page when the 'Component' mounts. This is a convenience only meant to be used in development. We recommend guarding the usage behind a flag.
--
-- @
-- main :: 'IO' ()
-- main = 'startApp' 'defaultEvents' counter
--  where
--    app = counter
-- #ifdef INTERACTIVE
--      { 'scripts' = [ 'Src' "https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js" ('False' :: 'CacheBust') ]
--      , 'styles' = [ 'Href' "https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" ('False' :: 'CacheBust')  ]
--      }
-- #endif
-- @
--
-- See the [miso-sampler](https://github.com/haskell-miso/miso-sampler) repository for more information.
--
-- = Debugging
--
-- Sometimes things can go wrong. Common errors like using `onClick` but not listening for the 'click' event are common.
-- These are errors that cannot be caught statically (unless we use a dependently-typed language like [Idris](https://idris-lang.org)). These can be detected by enabling 'DebugAll'. Currently, debugging event delegation and page hydration is supported.
--
-- * 'DebugHydrate'
-- * 'DebugEvents'
--
-- @
-- counter { 'logLevel' = 'DebugAll' }
-- @
--
-- = Internals
--
-- Internally miso uses a global event queue and a scheduler to process all
-- events raised by 'Component' throughout the lifetime of an application.
-- Events are processed in FIFO order, batched by the 'Component' that raised them.
--
-- * __Event queue__: All actions dispatched via a 'Sink' (from event handlers,
--   subscriptions, or 'io' callbacks) are enqueued and drained by the scheduler.
--
-- * __Scheduler__: The scheduler pulls actions off the queue one batch at a time,
--   runs the 'update' function for each, collects the resulting 'IO' work, and
--   executes it. Rendering (VDOM diff + patch) is triggered after each batch.
--
-- * __'Waiter'__: A 'Miso.Concurrent.Waiter' is a synchronization primitive used
--   internally to coordinate the event loop — it blocks the scheduler thread until
--   new work arrives, avoiding busy-waiting.
--
-- * __Event delegation__: Rather than attaching listeners to individual DOM nodes,
--   miso attaches a single capture and a single bubble listener to @\<body\>@.
--   Incoming events are routed through the virtual DOM tree to the matching handler.
--   This minimises listener churn when the VDOM is patched.
--
-- * __VDOM diffing__: The diff algorithm in "Miso.Diff" compares old and new
--   'View' trees and emits the minimal set of DOM mutations. Keyed children (see
--   the 'Key' section) significantly speed up child list reconciliation.
--
-- = Prerendering
--
-- Prerendering is the process of delivering HTML from a web server before the client loads and performs any drawing to the page. In miso it comes in two flavors, static
-- or dynamic prerendering. Static prerendering assumes no model state needs to be shared between the server and client. Dynamic uses 'hydrateModel' to share @model@ state.
--
-- == Static prerendering
--
-- miso provides the 'prerender' and 'miso' functions to facilitate static prerendering. Any page can be generated from a miso 'View' using the 'Miso.Html.Render.toHtml' instance.
--
-- A simple example of static prerendering would be an @index.html@ page with some HTML
--
-- @
-- echo "\<html\>\<head\>\<\/head\>\<body\>hello world\<\/body\>\<html\>" > index.html
-- @
--
-- And a miso application that looks like:
--
-- @
-- main :: IO ()
-- main = 'prerender' 'defaultEvents' $ ('vcomp' () 'noop' $ \\_ () -> "hello world") { 'logLevel' = 'DebugPrerender' }
-- @
--
-- Assuming the JS / WASM payload and @index.html@ are delivered together from the web server, the console should output below
--
-- > [DEBUG_HYDRATE] Successfully prerendered page
--
-- See the [Haskell miso](https://haskell-miso.org) website console for an example usage of static prerendering with 'miso' and [miso-ui](https://ui.haskell-miso.org) for 'prerender' usage.
--
-- == Dynamic prerendering
--
-- Dynamic prerendering shares @model@ state between the server and client so the
-- client can hydrate from a meaningful initial state rather than a blank model.
-- The @-fssr@ Cabal flag must be enabled when compiling the server.
--
-- The 'hydrateModel' field on 'Component' is @Maybe (IO model)@. When set, the
-- action runs once at hydration time to produce the initial model; it is ignored
-- on subsequent remounts. A typical pattern embeds the model as JSON in the
-- server response and reads it back on the client via the JS DSL:
--
-- @
-- myComp :: 'App' Model Action
-- myComp = ('vcomp' defaultModel updateFn viewFn)
--   { 'hydrateModel' = Just $ do
--       val <- 'Miso.DSL.jsg' "window" 'Miso.DSL.!' "__initialModel__"
--       'Miso.DSL.fromJSValUnchecked' val
--   }
-- @
--
-- On the server, populate @window.__initialModel__@ by embedding the JSON
-- in a @\<script\>@ tag alongside the rendered HTML:
--
-- @
-- serverView :: Model -> 'View' Model Action
-- serverView m =
--   'div_' []
--     [ 'script_' [] [ 'textRaw' ("window.__initialModel__ = " \<\> 'encode' m) ]
--     , appView m
--     ]
-- @
--
-- When 'hydrateModel' is @Nothing@, the static 'model' field is used instead —
-- equivalent to static prerendering.
--
-----------------------------------------------------------------------------
module Miso
  ( -- * API
    -- ** Miso
    miso
  , prerender
  , (🍜)
    -- ** App
  , App
  , startApp
  , renderApp
    -- ** Component
  , Component (..)
  , component
  , vcomp
  , (+>)
  , mount_
    -- ** View
  , vnode
  , vtext
    -- ** Sink
  , withSink
  , Sink
    -- ** Mail
  , mail
  , checkMail
  , parent
  , mailParent
  , mailChildren
  , mailDescendants
  , mailAncestors
  , broadcast
    -- ** Subscriptions
  , startSub
  , stopSub
  , Sub
    -- ** Effect
  , issue
  , batch
  , io
  , io_
  , sync
  , sync_
  , for
  -- ** JS file embedding
#ifdef WASM
  , evalFile
#endif
  , withJS
    -- * Bindings
    -- | Primitives for synchronizing parent and child models.
  , module Miso.Binding
    -- * DSL
    -- | A JavaScript DSL for easy FFI interoperability
  , module Miso.DSL
    -- * Effect
    -- | 'Effect', 'Sub', and 'Sink' types for defining update functions and subscriptions.
  , module Miso.Effect
    -- * Event
    -- | Functions for specifying component lifecycle events and event handlers.
  , module Miso.Event
    -- * Fetch
    -- | Interface to the Fetch API for making HTTP requests.
  , module Miso.Fetch
    -- * PubSub
    -- | Publish / Subscribe primitives for communication between components.
  , module Miso.PubSub
    -- * Property
    -- | Construct custom properties on DOM elements.
  , module Miso.Property
    -- * Reload
    -- | Support for clearing the page during live-reloading w/ WASM browser mode.
  , module Miso.Reload
    -- * Subscriptions
    -- | Subscriptions for external events (mouse, keyboard, window, history, etc.).
  , module Miso.Subscription
    -- * Storage
    -- | Web Storage API (Local and Session storage) interface.
  , module Miso.Storage
    -- * Types
    -- | Core types for Miso applications.
  , module Miso.Types
    -- * Util
    -- | Utility functions for views, parsing, and general purpose combinators.
  , module Miso.Util
    -- * FFI
    -- | Foreign Function Interface (FFI) utilities for interacting with JavaScript.
  , module Miso.FFI
    -- * State management
    -- | State management for Miso applications.
  , module Miso.State
  ) where
-----------------------------------------------------------------------------
import           Miso.Binding
import           Miso.DSL
import           Miso.Effect
import           Miso.Event
import           Miso.Fetch
import           Miso.FFI
import qualified Miso.FFI.Internal as FFI
import           Miso.Property
import           Miso.PubSub
import           Miso.Reload
import           Miso.Runtime
import           Miso.State
import           Miso.Storage
import           Miso.Subscription
import           Miso.Types
import           Miso.Util
----------------------------------------------------------------------------
-- | Runs an @miso@ application.
--
-- Assumes the pre-rendered DOM is already present.
-- Always mounts to \<body\>. Copies page into the virtual DOM.
--
-- @
-- main :: 'IO' ()
-- main = 'miso' 'defaultEvents' app
-- @
miso
  :: Eq model
  => Events
  -- ^ Globally delegated Events
  -> (URI -> App model action)
  -- ^ The Component application, with the current URI as an argument
  -> IO ()
miso :: forall model action.
Eq model =>
Events -> (URI -> App model action) -> IO ()
miso Events
events URI -> App model action
f = do
  comp <- URI -> App model action
f (URI -> App model action) -> IO URI -> IO (App model action)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO URI
getURI
  initComponent events Hydrate False comp { mountPoint = Nothing }
----------------------------------------------------------------------------
-- | Like 'miso', except discards the 'URI' argument.
--
-- Use this function if you'd like to prerender, but not use navigation.
--
-- @
-- main :: 'IO' ()
-- main = 'prerender' 'defaultEvents' app
-- @
prerender
  :: Eq model
  => Events
  -- ^ Globally delegated 'Events'
  -> App model action
  -- ^ 'Component' application
  -> IO ()
prerender :: forall model action.
Eq model =>
Events -> App model action -> IO ()
prerender Events
events App model action
comp = Events -> Hydrate -> Bool -> App model action -> IO ()
forall parent model action.
(Eq parent, Eq model) =>
Events
-> Hydrate -> Bool -> Component parent () model action -> IO ()
initComponent Events
events Hydrate
Hydrate Bool
False App model action
comp { mountPoint = Nothing }
-----------------------------------------------------------------------------
-- | Like 'miso', except it does not perform page hydration.
--
-- This function draws your application on an empty <body>
--
-- You will most likely want to use this function for your application
-- unless you are using prerendering.
--
-- @
-- main :: 'IO' ()
-- main = 'startApp' 'defaultEvents' app
-- @
--
startApp
  :: Eq model
  => Events
  -- ^ Globally delegated 'Events'
  -> App model action
  -- ^ 'Component' application
  -> IO ()
startApp :: forall model action.
Eq model =>
Events -> App model action -> IO ()
startApp Events
events = Events
-> Hydrate -> Bool -> Component ROOT () model action -> IO ()
forall parent model action.
(Eq parent, Eq model) =>
Events
-> Hydrate -> Bool -> Component parent () model action -> IO ()
initComponent Events
events Hydrate
Draw Bool
False
-----------------------------------------------------------------------------
-- | Alias for 'Miso.miso'.
(🍜)
  :: Eq model
  => Events
  -- ^ Globally delegated 'Events'
  -> (URI -> App model action)
  -- ^ 'Component' application, with the current URI as an argument
  -> IO ()
🍜 :: forall model action.
Eq model =>
Events -> (URI -> App model action) -> IO ()
(🍜) = Events -> (URI -> App model action) -> IO ()
forall model action.
Eq model =>
Events -> (URI -> App model action) -> IO ()
miso
----------------------------------------------------------------------------
-- | Runs a 'miso' application, but with a custom rendering engine.
--
-- The 'MisoString' specified here is the variable name of a globally-scoped
-- JS object that implements the context interface per @ts\/miso\/context\/dom.ts@
-- This is necessary for native support.
--
-- It is expected to be run on an empty @\<body\>@
--
-- @
-- main :: IO ()
-- main = 'renderApp' 'defaultEvents' "my-context" app
-- @
renderApp
  :: Eq model
  => Events
  -- ^ Globally delegated 'Events'
  -> MisoString
  -- ^ Name of the JS object that contains the drawing context
  -> App model action
  -- ^ 'Component' application
  -> IO ()
renderApp :: forall model action.
Eq model =>
Events -> MountPoint -> App model action -> IO ()
renderApp Events
events MountPoint
renderer App model action
comp = do
  MountPoint -> IO ()
FFI.setDrawingContext MountPoint
renderer
  Events -> Hydrate -> Bool -> App model action -> IO ()
forall parent model action.
(Eq parent, Eq model) =>
Events
-> Hydrate -> Bool -> Component parent () model action -> IO ()
initComponent Events
events Hydrate
Draw Bool
False App model action
comp
----------------------------------------------------------------------------