miso
Copyright(C) 2016-2025 David M. Johnson (@dmjio)
LicenseBSD3-style (see the file LICENSE)
MaintainerDavid M. Johnson <code@dmj.io>
Stabilityexperimental
Portabilitynon-portable
Safe HaskellNone
LanguageHaskell2010

Miso

Description

 
Synopsis

API

Entry

miso :: Eq model => (URI -> Component model action) -> JSM () Source #

Runs an isomorphic miso application. Assumes the pre-rendered DOM is already present. Always mounts to <body>. Copies page into the virtual DOM.

(🍜) :: Eq model => (URI -> Component model action) -> JSM () Source #

Alias for miso.

startComponent Source #

Arguments

:: Eq model 
=> Component model action

Component application

-> JSM () 

Runs a miso application Initializes application at mountPoint (defaults to <body> when Nothing)

renderComponent Source #

Arguments

:: Eq model 
=> Maybe MisoString

Name of the JS object that contains the drawing context

-> Component model action

Component application

-> JSM [JSVal]

Custom hook to perform any JSM action (e.g. render styles) before initialization.

-> JSM () 

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 'tsmisocontext/dom.ts' This is necessary for native support.

Sink

withSink :: (Sink action -> JSM ()) -> Effect model action Source #

withSink allows users to access the sink of the Component or top-level Component in their application. This is useful for introducing IO into the system. A synonym for tell, specialized to Effect.

A use-case is scheduling an IO computation which creates a 3rd-party JS widget which has an associated callback. The callback can then call the sink to turn events into actions. To do this without accessing a sink requires going via a Subscription which introduces a leaky-abstraction.

update FetchJSON = withSink $ \sink -> getJSON (sink . ReceivedJSON) (sink . HandleError)

Since: 1.9.0.0

type Sink action = action -> JSM () Source #

Function to asynchronously dispatch actions to the update function.

Publishers / Subscribers

subscribe :: FromJSON message => Topic message -> (Result message -> action) -> Effect model action Source #

Subscribes to a Topic, provides callback function that writes to Component Sink

If a Topic message does not exist when calling subscribe it is generated dynamically. Each subscriber decodes the received Value using it's own FromJSON instance. This provides for loose-coupling between Component. As long as the underlying Value are identical Component can use their own types without serialization issues. Topic message should have their own JSON API specification when being distributed.

arithmetic :: Topic Message
arithmetic = topic "arithmetic"

clientComponent :: MisoString -> Component Int Action
clientComponent name = component 0 update_ $ m ->
  div_
  []
  [ br_ []
  , text (name <> " : " <> ms (m ^. _id))
  , button_ [ onClick Unsubscribe ] [ "unsubscribe" ]
  , button_ [ onClick Subscribe ] [ "subscribe" ]
  ] where
      update_ :: Action -> Effect Int Action
      update_ = case
        AddOne -> do
          _id += 1
        SubtractOne ->
          _id -= 1
        Unsubscribe ->
          unsubscribe arithmetic
        Subscribe ->
          subscribe arithmetic Notification
        Notification (Success Increment) -> do
          update_ AddOne
        Notification (Success Decrement) -> do
          update_ SubtractOne
        Notification (Error msg) ->
          io_ $ consoleError ("Decode failure: " <> ms msg)
        _ -> pure ()

Since: 1.9.0.0

unsubscribe :: Topic message -> Effect model action Source #

Unsubscribe to a Topic

Unsubscribes a Component from receiving messages from Topic message

See subscribe for more use.

Since: 1.9.0.0

publish :: ToJSON message => Topic message -> message -> Effect model action Source #

Publish to a Topic message

Topic message are generated dynamically if they do not exist. When using publish all subscribers are immediately notified of a new message. A message is distributed as a Value The underlying ToJSON instance is used to construct this Value.

We recommend documenting a public API for the JSON protocol message when distributing a Component downstream to end users for consumption (be it inside a single cabal project or across multiple cabal projects).

arithmetic :: Topic Message
arithmetic = topic "arithmetic"

server :: Component () Action
server = component () update_ $ () ->
  div_
  []
  [ "Server component"
  , button_ [ onClick AddOne ] [ "+" ]
  , button_ [ onClick SubtractOne ] [ "-" ]
  , component_ (client_ "client 1")
    [ onMountedWith Mount
    ]
  , component_ (client_ "client 2")
    [ onMountedWith Mount
    ]
  ] where
      update_ :: Action -> Effect () Action
      update_ = case
        AddOne ->
          publish arithmetic Increment
        SubtractOne ->
          publish arithemtic Decrement

Since: 1.9.0.0

data Topic a Source #

A Topic represents a place to send and receive messages. Topic is used to facilitate communication between Component. Component can subscribe to or publish to any Topic, within the same Component or across Component.

This requires creating a custom ToJSON / FromJSON. Any other Component can publish or subscribe to this Topic message. It is a way to provide loosely-coupled communication between Components.

See publish, subscribe, unsubscribe for more details.

When distributing Component for third-party use, it is recommended to export the Topic, where message is the JSON protocol.

Since: 1.9.0.0

Instances

Instances details
Show (Topic a) Source # 
Instance details

Defined in Miso.Runtime

Methods

showsPrec :: Int -> Topic a -> ShowS #

show :: Topic a -> String #

showList :: [Topic a] -> ShowS #

Eq (Topic a) Source # 
Instance details

Defined in Miso.Runtime

Methods

(==) :: Topic a -> Topic a -> Bool #

(/=) :: Topic a -> Topic a -> Bool #

Ord (Topic a) Source # 
Instance details

Defined in Miso.Runtime

Methods

compare :: Topic a -> Topic a -> Ordering #

(<) :: Topic a -> Topic a -> Bool #

(<=) :: Topic a -> Topic a -> Bool #

(>) :: Topic a -> Topic a -> Bool #

(>=) :: Topic a -> Topic a -> Bool #

max :: Topic a -> Topic a -> Topic a #

min :: Topic a -> Topic a -> Topic a #

ToMisoString (Topic a) Source # 
Instance details

Defined in Miso.Runtime

topic :: MisoString -> Topic a Source #

Smart constructor for creating a Topic message to write to

data Message
  = Increment
  | Decrement
  deriving (Show, Eq, Generic, ToJSON, FromJSON)

arithmetic :: Topic Message
arithmetic = topic "arithmetic"

data Action
  = Notification (Result Message)
  | Subscribe
  | Unsubscribe

update_ :: Action -> Effect Int Action
update_ = case
  Unsubscribe ->
    unsubscribe arithmetic
  Subscribe ->
    subscribe arithmetic Notification
  Notification (Success Increment) ->
    update_ AddOne
  Notification (Success Decrement) ->
    update_ SubtractOne
  Notification (Error msg) ->
    io_ $ consoleError ("Decode failure: " <> ms msg)

Since: 1.9.0.0

Component

mail :: ToJSON message => ComponentId -> message -> Effect model action Source #

Send any 'ToJSON message => message' to a Component mailbox, by ComponentId

mail componentId ("test message" :: MisoString) :: Effect model action

Since: 1.9.0.0

getComponentId :: (ComponentId -> action) -> Effect model action Source #

Used to acquire the ComponentId of the current Component

getParentComponentId Source #

Arguments

:: (ComponentId -> action)

Successful callback (with parent ComponentId)

-> action

Errorful callback (without ComponentId)

-> Effect model action 

Used to acquire the parent ComponentId of the current Component This is commonly used in situations to send messages or receive messages between components.

Subscriptions

startSub :: ToMisoString subKey => subKey -> Sub action -> Effect model action Source #

Starts a named Sub dynamically, during the life of a Component. The Sub can be stopped by calling Ord subKey => stop subKey from the update function. All Sub started will be stopped if a Component is unmounted.

data SubType = LoggerSub | TimerSub
  deriving (Eq, Ord)

update Action =
  startSub LoggerSub $ sink -> forever (threadDelay (secs 1) >> consoleLog "test")

Since: 1.9.0.0

stopSub :: ToMisoString subKey => subKey -> Effect model action Source #

Stops a named Sub dynamically, during the life of a Component. All Sub started will be stopped automatically if a Component is unmounted.

data SubType = LoggerSub | TimerSub
  deriving (Eq, Ord)

update Action = do
  stopSub LoggerSub

Since: 1.9.0.0

type Sub action = Sink action -> JSM () Source #

Type synonym for constructing event subscriptions.

The Sink callback is used to dispatch actions which are then fed back into the update function.

Effect

issue :: action -> Effect model action Source #

Issue a new Action to be processed by update.

update :: Action -> Effect Model Action
update = \case
  Click -> issue HelloWorld

Since: 1.9.0.0

batch :: [JSM action] -> Effect model action Source #

Smart constructor for an Effect with multiple actions. @since 1.9.0.0

io :: JSM action -> Effect model action Source #

Schedule a single IO action for later execution.

Note that multiple IO action can be scheduled using tell from the mtl library.

Since: 1.9.0.0

io_ :: JSM () -> Effect model action Source #

Like io_ but doesn't cause an action to be dispatched to the update function.

This is handy for scheduling IO computations where you don't care about their results or when they complete.

Since: 1.9.0.0

for :: Foldable f => JSM (f action) -> Effect model action Source #

Like io but generalized to any instance of Foldable

This is handy for scheduling IO computations that return a Maybe value

Since: 1.9.0.0

module Miso.Types

Effect

Event

module Miso.Event

Property

Html

module Miso.Html

Property

Router

Run

module Miso.Run

Subscriptions

Storage

Fetch

module Miso.Fetch

Util

module Miso.Util

FFI

addEventListener Source #

Arguments

:: JSVal

Event target on which we want to register event listener

-> MisoString

Type of event to listen to (e.g. "click")

-> (JSVal -> JSM ())

Callback which will be called when the event occurs, the event will be passed to it as a parameter.

-> JSM () 

Register an event listener on given target.

addStyle :: MisoString -> JSM JSVal Source #

Appends a style_ element containing CSS to head_

addStyle "body { background-color: green; }"
<head><style>body { background-color: green; }</style></head>

addStyleSheet :: MisoString -> JSM JSVal Source #

Appends a StyleSheet link_ element to head_ The link_ tag will contain a URL to a CSS file.

addStyleSheet "https://cdn.jsdelivr.net/npm/todomvc-common@1.0.5/base.min.css"
<head><link href="https://cdn.jsdelivr.net/npm/todomvc-common@1.0.5/base.min.css" ref="stylesheet"></head>

alert :: MisoString -> JSM () Source #

Calls the alert() function.

asyncCallback :: JSM () -> JSM Function Source #

Creates an asynchronous callback function

asyncCallback1 :: (JSVal -> JSM ()) -> JSM Function Source #

Creates an asynchronous callback function with a single argument

asyncCallback2 :: (JSVal -> JSVal -> JSM ()) -> JSM Function Source #

Creates an asynchronous callback function with two arguments

blur :: MisoString -> JSM () Source #

Fails silently if the element is not found.

Analogous to document.getElementById(id).blur()

consoleError :: MisoString -> JSM () Source #

Outputs an error message to the web console

See https://developer.mozilla.org/en-US/docs/Web/API/Console/error

Console logging of JavaScript strings.

consoleLog :: MisoString -> JSM () Source #

Outputs a message to the web console

See https://developer.mozilla.org/en-US/docs/Web/API/Console/log

Console logging of JavaScript strings.

consoleLog' :: JSVal -> JSM () Source #

Console-logging of JSVal

consoleWarn :: MisoString -> JSM () Source #

Outputs a warning message to the web console

See https://developer.mozilla.org/en-US/docs/Web/API/Console/warn

Console logging of JavaScript strings.

focus :: MisoString -> JSM () Source #

Fails silently if the element is not found.

Analogous to document.getElementById(id).focus().

getElementById :: MisoString -> JSM JSVal Source #

Returns an Element object representing the element whose id property matches the specified string.

See https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById

jsonParse :: FromJSON json => JSVal -> JSM json Source #

Parses a MisoString

jsonStringify :: ToJSON json => json -> JSM MisoString Source #

Encodes a Haskell object as a JSON string by way of a JavaScript object

newImage :: MisoString -> JSM Image Source #

Smart constructor for building a Image w/ src attribute.

reload :: JSM () Source #

Calls the location.reload() function.

set :: ToJSVal v => MisoString -> v -> Object -> JSM () Source #

Set property on object

setDrawingContext :: MisoString -> JSM () Source #

Used to select a drawing context. Users can override the default DOM renderer by implementing their own Context, and exporting it to the global scope. This opens the door to different rendering engines, ala miso-native.

syncCallback :: JSM () -> JSM Function Source #

Creates a synchronous callback function (no return value)

syncCallback1 :: (JSVal -> JSM ()) -> JSM Function Source #

Creates a synchronous callback function with one argument

windowInnerHeight :: JSM Int Source #

Retrieves the height (in pixels) of the browser window viewport including, if rendered, the horizontal scrollbar.

See https://developer.mozilla.org/en-US/docs/Web/API/Window/innerHeight

windowInnerWidth :: JSM Int Source #

Retrieves the width (in pixels) of the browser window viewport including if rendered, the vertical scrollbar.

See https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth

newtype Date Source #

Constructors

Date JSVal 

Instances

Instances details
ToJSVal Date Source # 
Instance details

Defined in Miso.FFI.Internal

MakeObject Date Source # 
Instance details

Defined in Miso.FFI.Internal

newtype Image Source #

Constructors

Image JSVal 

State management

module Miso.State