Bonsai
- Package
- purescript-bonsai
- Repository
- grmble/purescript-bonsai
Bonsai main module for imports
View code will also want Bonsai.Html and Bonsai.Event
Re-exports from Bonsai.Core
#UpdateResult Source
type UpdateResult model msg = { cmd :: Cmd msg, model :: model }An update functions returns a new model and a possibly empty command
#ProgramState Source
type ProgramState model msg = { dnode :: Element, model :: model, vnode :: VNode msg }ProgramState tracks the current state of the model, vnode and dom element.
These are needed to advance the state in reaction to a Cmd message.
#Program Source
type Program model msg = { dbgEvents :: Boolean, dbgTiming :: Boolean, pending :: Ref (Array msg), renderer :: model -> VNode msg, state :: Ref (ProgramState model msg), updater :: model -> msg -> UpdateResult model msg }Program describes the Bonsai program.
It is passed around in a ReaderT and stores callbacks and a ref to the pending commands. Event callbacks append to the list of pending commands, they will then be applied in the main event loop.
#plainResult Source
plainResult :: forall msg model. model -> UpdateResult model msgCreates an update result with empty command.
#mapResult Source
mapResult :: forall msg2 model2 msg1 model1. (model1 -> model2) -> (msg1 -> msg2) -> UpdateResult model1 msg1 -> UpdateResult model2 msg2Helper to map update results from sub-components
Re-exports from Bonsai.DOM
Re-exports from Bonsai.Types
Re-exports from Bonsai.VirtualDom
#Property Source
newtype Property msgWhen using HTML and JS, there are two ways to specify parts of a DOM node.
Attributes — You can set things in HTML itself. So the
classin<div class="greeting"></div>is called an attribute.Properties — You can also set things in JS. So the
classNameindiv.className = 'greeting'is called a property.
So the class attribute corresponds to the className property. At first
glance, perhaps this distinction is defensible, but it gets much crazier.
There is not always a one-to-one mapping between attributes and properties!
Yes, that is a true fact. Sometimes an attribute exists, but there is no
corresponding property. Sometimes changing an attribute does not change the
underlying property. For example, as of this writing, the webkit-playsinline
attribute can be used in HTML, but there is no corresponding property!
Instances
#Options Source
type Options = { preventDefault :: Boolean, stopPropagation :: Boolean }Options for an event listener. If stopPropagation is true, it means the
event stops traveling through the DOM so it will not trigger any other event
listeners. If preventDefault is true, any built-in browser behavior related
to the event is prevented. For example, this is used with touch events when you
want to treat them as gestures of your own, not as scrolls.
#EventDecoder Source
type EventDecoder msg = Foreign -> F (Cmd msg)A EventDecoder turns DOM events into messages.
#property Source
property :: forall msg a. String -> a -> Property msgCreate arbitrary properties.
import JavaScript.Encode as Json
greeting : Html greeting = node "div" [ property "className" (Json.string "greeting") ] [ text "Hello!" ]
Notice that you must give the property name, so we use className as it
would be in JavaScript, not class as it would appear in HTML.
#onWithOptions Source
onWithOptions :: forall msg. String -> Options -> EventDecoder msg -> Property msgSame as on but you can set a few options.
#on Source
on :: forall msg. String -> (EventDecoder msg) -> Property msgCreate a custom event listener.
import Json.Decode as Json
onClick : msg -> Property msg
onClick msg =
on "click" (Json.succeed msg)
You first specify the name of the event in the same format as with JavaScript’s
addEventListener. Next you give a JSON decoder, which lets you pull
information out of the event object. If the decoder succeeds, it will produce
a message and route it to your update function.
#node Source
node :: forall msg. String -> Array (Property msg) -> Array (VNode msg) -> VNode msgCreate a DOM node with a tag name, a list of HTML properties that can
include styles and event listeners, a list of CSS properties like color, and
a list of child nodes.
import Json.Encode as Json
hello : Node msg hello = node "div" [] [ text "Hello!" ]
greeting : Node msg greeting = node "div" [ property "id" (Json.string "greeting") ] [ text "Hello!" ]
#keyedNode Source
keyedNode :: forall msg. String -> Array (Property msg) -> Array (Tuple String (VNode msg)) -> VNode msgWorks just like node, but you add a unique identifier to each child
node. You want this when you have a list of nodes that is changing: adding
nodes, removing nodes, etc. In these cases, the unique identifiers help make
the DOM modifications more efficient.
#attributeNS Source
attributeNS :: forall msg. String -> String -> String -> Property msgWould you believe that there is another way to do this?! This corresponds
to JavaScript's setAttributeNS function under the hood. It is doing pretty
much the same thing as attribute but you are able to have "namespaced"
attributes. This is used in some SVG stuff at least.
#attribute Source
attribute :: forall msg. String -> String -> Property msgCreate arbitrary HTML attributes. Maps onto JavaScript’s setAttribute
function under the hood.
greeting : Html
greeting =
node "div" [ attribute "class" "greeting" ] [
text "Hello!"
]
Notice that you must give the attribute name, so we use class as it would
be in HTML, not className as it would appear in JS.