Safe Haskell | None |
---|---|
Language | Haskell2010 |
Shpadoinkle is an abstract frontend programming model, with one-way data flow, and a single source of truth. This module provides a parsimonious implementation of Shpadoinkle with few implementation details.
Synopsis
- data Html :: (Type -> Type) -> Type -> Type where
- data Prop :: (Type -> Type) -> Type -> Type where
- textProp :: Text -> Prop m a
- listenerProp :: (RawNode -> RawEvent -> JSM (Continuation m a)) -> Prop m a
- flagProp :: Bool -> Prop m a
- listenRaw :: Text -> (RawNode -> RawEvent -> JSM (Continuation m a)) -> (Text, Prop m a)
- listen :: Text -> a -> (Text, Prop m a)
- listenM :: Monad m => Text -> m (a -> a) -> (Text, Prop m a)
- listenM_ :: Monad m => Text -> m () -> (Text, Prop m a)
- listenC :: Text -> Continuation m a -> (Text, Prop m a)
- listener :: Continuation m a -> Prop m a
- h :: Text -> [(Text, Prop m a)] -> [Html m a] -> Html m a
- baked :: JSM RawNode -> Html m a
- text :: Text -> Html m a
- props :: Applicative f => ([(Text, Prop m a)] -> f [(Text, Prop m a)]) -> Html m a -> f (Html m a)
- children :: Applicative f => ([Html m a] -> f [Html m a]) -> Html m a -> f (Html m a)
- name :: Applicative f => (Text -> f Text) -> Html m a -> f (Html m a)
- textContent :: Applicative f => (Text -> f Text) -> Html m a -> f (Html m a)
- hoistHtml :: Functor m => (m ~> n) -> Html m a -> Html n a
- hoistProp :: Functor m => (m ~> n) -> Prop m a -> Prop n a
- cataH :: (Text -> [(Text, Prop m a)] -> [b] -> b) -> (JSM RawNode -> b) -> (Text -> b) -> Html m a -> b
- cataProp :: (Text -> b) -> ((RawNode -> RawEvent -> JSM (Continuation m a)) -> b) -> (Bool -> b) -> Prop m a -> b
- mapProps :: ([(Text, Prop m a)] -> [(Text, Prop m a)]) -> Html m a -> Html m a
- mapChildren :: ([Html m a] -> [Html m a]) -> Html m a -> Html m a
- injectProps :: [(Text, Prop m a)] -> Html m a -> Html m a
- eitherH :: Monad m => (a -> Html m a) -> (b -> Html m b) -> Either a b -> Html m (Either a b)
- newtype RawNode = RawNode {}
- newtype RawEvent = RawEvent {
- unRawEvent :: JSVal
- class Backend b m a | b m -> a where
- type (~>) m n = forall a. m a -> n a
- shpadoinkle :: forall b m a. Backend b m a => Monad (b m) => Eq a => (m ~> JSM) -> (TVar a -> b m ~> m) -> a -> TVar a -> (a -> Html (b m) a) -> b m RawNode -> JSM ()
- runJSorWarp :: Int -> JSM () -> IO ()
- fullPage :: Backend b m a => Monad (b m) => Eq a => (m ~> JSM) -> (TVar a -> b m ~> m) -> a -> (a -> Html (b m) a) -> b m RawNode -> JSM ()
- fullPageJSM :: Backend b JSM a => Monad (b JSM) => Eq a => (TVar a -> b JSM ~> JSM) -> a -> (a -> Html (b JSM) a) -> b JSM RawNode -> JSM ()
- simple :: Backend b JSM a => Monad (b JSM) => Eq a => (TVar a -> b JSM ~> JSM) -> a -> (a -> Html (b JSM) a) -> b JSM RawNode -> JSM ()
- data JSM a
- class (Applicative m, MonadIO m) => MonadJSM (m :: Type -> Type)
- data TVar a
- newTVarIO :: MonadIO m => a -> m (TVar a)
- readTVarIO :: MonadIO m => TVar a -> m a
Base Types
data Html :: (Type -> Type) -> Type -> Type where Source #
This is the core type in Backend. Please note, this is NOT the Virtual DOM used by Backend. This type backs a DSL that is then interpreted into Virtual DOM by the Backend of your choosing. HTML comments are not supported.
Node :: Text -> [(Text, Prop m a)] -> [Html m a] -> Html m a | A standard node in the DOM tree |
Potato :: JSM RawNode -> Html m a | If you can bake an element into a |
TextNode :: Text -> Html m a | The humble text node |
Instances
Continuous Html Source # | Given a lens, you can change the type of an Html by using the lens to convert the types of the Continuations inside it. |
Defined in Shpadoinkle.Core mapC :: (Functor m, Functor n) => (Continuation m a -> Continuation n b) -> Html m a -> Html n b Source # | |
Monad m => Functor EndoIso EndoIso (Html m :: Type -> Type) Source # |
|
IsString (Html m a) Source # | Strings are overloaded as HTML text nodes:
|
Defined in Shpadoinkle.Core fromString :: String -> Html m a # |
data Prop :: (Type -> Type) -> Type -> Type where Source #
Properties of a DOM node. Backend does not use attributes directly, but rather is focused on the more capable properties that may be set on a DOM node in JavaScript. If you wish to add attributes, you may do so by setting its corresponding property.
PText :: Text -> Prop m a | A text property |
PListener :: (RawNode -> RawEvent -> JSM (Continuation m a)) -> Prop m a | Event listeners are provided with the |
PFlag :: Bool -> Prop m a | A boolean property works as a flag:
for example |
Instances
Continuous Prop Source # | Given a lens, you can change the type of a Prop by using the lens to convert the types of the Continuations which it contains if it is a listener. |
Defined in Shpadoinkle.Core mapC :: (Functor m, Functor n) => (Continuation m a -> Continuation n b) -> Prop m a -> Prop n b Source # | |
IsString [(Text, Prop m a)] Source # | Strings are overloaded as the class property:
|
Defined in Shpadoinkle.Core fromString :: String -> [(Text, Prop m a)] # | |
Monad m => Functor EndoIso EndoIso (Prop m :: Type -> Type) Source # | Prop is a functor in the EndoIso category, where the objects are types and the morphisms are EndoIsos. |
IsString (Prop m a) Source # | Strings are overloaded as text props:
|
Defined in Shpadoinkle.Core fromString :: String -> Prop m a # |
Prop Constructors
listenerProp :: (RawNode -> RawEvent -> JSM (Continuation m a)) -> Prop m a Source #
Create an event listener property.
Listeners
listenRaw :: Text -> (RawNode -> RawEvent -> JSM (Continuation m a)) -> (Text, Prop m a) Source #
Construct a listener from its name and an event handler.
listen :: Text -> a -> (Text, Prop m a) Source #
Construct a listener from its Text
name and an output value.
listenM :: Monad m => Text -> m (a -> a) -> (Text, Prop m a) Source #
Construct a listener from its name and a simple monadic event handler.
listenM_ :: Monad m => Text -> m () -> (Text, Prop m a) Source #
Construct a listener from its name and a simple stateless monadic event handler.
listenC :: Text -> Continuation m a -> (Text, Prop m a) Source #
Construct a listener from its name and an event handler.
listener :: Continuation m a -> Prop m a Source #
Construct a simple listener property that will perform an action.
Html Constructors
h :: Text -> [(Text, Prop m a)] -> [Html m a] -> Html m a Source #
Construct an HTML element JSX-style.
Html Lenses
props :: Applicative f => ([(Text, Prop m a)] -> f [(Text, Prop m a)]) -> Html m a -> f (Html m a) Source #
Lens to props
children :: Applicative f => ([Html m a] -> f [Html m a]) -> Html m a -> f (Html m a) Source #
Lens to children
textContent :: Applicative f => (Text -> f Text) -> Html m a -> f (Html m a) Source #
Lens to content of TextNode
s
Hoists
hoistHtml :: Functor m => (m ~> n) -> Html m a -> Html n a Source #
If you can provide a Natural Transformation from one Functor to another
then you may change the action of Html
.
hoistProp :: Functor m => (m ~> n) -> Prop m a -> Prop n a Source #
If you can provide a Natural Transformation from one Functor to another
then you may change the action of Prop
.
Catamorphisms
cataH :: (Text -> [(Text, Prop m a)] -> [b] -> b) -> (JSM RawNode -> b) -> (Text -> b) -> Html m a -> b Source #
Fold an HTML element, i.e. transform an h-algebra into an h-catamorphism.
cataProp :: (Text -> b) -> ((RawNode -> RawEvent -> JSM (Continuation m a)) -> b) -> (Bool -> b) -> Prop m a -> b Source #
Transform a p-algebra into a p-catamorphism. This is like polymorphic pattern matching.
Utilities
injectProps :: [(Text, Prop m a)] -> Html m a -> Html m a Source #
Inject props into an existing Node
.
eitherH :: Monad m => (a -> Html m a) -> (b -> Html m b) -> Either a b -> Html m (Either a b) Source #
Construct an HTML element out of heterogeneous alternatives.
JSVal Wrappers
A DOM node reference. Useful for building baked potatoes and binding a Backend view to the page
Backend Interface
class Backend b m a | b m -> a where Source #
The Backend class describes a backend that can render Html
.
Backends are generally Monad Transformers b
over some Monad m
.
patch raw Nothing >=> patch raw Nothing = patch raw Nothing
VNode type family allows backends to have their own Virtual DOM. As such we can change out the rendering of our Backend view with new backends without updating our view logic.
:: (m ~> JSM) | Natural transformation for some |
-> Html (b m) a |
|
-> b m (VNode b m) | Effect producing the Virtual DOM representation |
A backend must be able to interpret Html
into its own internal Virtual DOM.
:: RawNode | The container for rendering the Backend view |
-> Maybe (VNode b m) | Perhaps there is a previous Virtual DOM to diff against. The value will be |
-> VNode b m | New Virtual DOM to render |
-> b m (VNode b m) | Effect producing an updated Virtual DOM. This is not needed by all backends.
Some JavaScript-based backends need to do this for the next tick. Regardless, whatever
|
A Backend must be able to patch the RawNode
containing the view, with a
new view if the Virtual DOM changed.
setup :: JSM () -> JSM () Source #
A Backend may perform some imperative setup steps.
The Shpadoinkle Primitive
:: Backend b m a | |
=> Monad (b m) | |
=> Eq a | |
=> (m ~> JSM) | How to get to JSM? |
-> (TVar a -> b m ~> m) | What backend are we running? |
-> a | What is the initial state? |
-> TVar a | How can we know when to update? |
-> (a -> Html (b m) a) | How should the HTML look? |
-> b m RawNode | Where do we render? |
-> JSM () |
The core view instantiation function combines a backend, a territory, and a model and renders the Backend view to the page.
Convenience Variants
runJSorWarp :: Int -> JSM () -> IO () Source #
Start the program!
This function works in GHC and GHCjs. I saved you from using C preprocessor directly. You're welcome.
:: Backend b m a | |
=> Monad (b m) | |
=> Eq a | |
=> (m ~> JSM) | How do we get to JSM? |
-> (TVar a -> b m ~> m) | What backend are we running? |
-> a | What is the initial state? |
-> (a -> Html (b m) a) | How should the html look? |
-> b m RawNode | Where do we render? |
-> JSM () |
Wrapper around shpadoinkle
for full page apps
that do not need outside control of the territory
:: Backend b JSM a | |
=> Monad (b JSM) | |
=> Eq a | |
=> (TVar a -> b JSM ~> JSM) | What backend are we running? |
-> a | What is the initial state? |
-> (a -> Html (b JSM) a) | How should the html look? |
-> b JSM RawNode | Where do we render? |
-> JSM () |
fullPageJSM
is a wrapper around shpadoinkle
for full page apps that do not need outside control
of the territory, where actions are performed directly in JSM.
This set of assumptions is extremely common when starting a new project.
:: Backend b JSM a | |
=> Monad (b JSM) | |
=> Eq a | |
=> (TVar a -> b JSM ~> JSM) | What backend are we running? |
-> a | what is the initial state? |
-> (a -> Html (b JSM) a) | how should the html look? |
-> b JSM RawNode | where do we render? |
-> JSM () |
Simple app
(a good starting place)
Re-Exports
The JSM
monad keeps track of the JavaScript execution context.
When using GHCJS it is IO
.
Given a JSM
function and a JSContextRef
you can run the
function like this...
runJSM jsmFunction javaScriptContext
Instances
Monad JSM | |
Functor JSM | |
MonadFix JSM | |
Defined in Language.Javascript.JSaddle.Types | |
MonadFail JSM | |
Defined in Language.Javascript.JSaddle.Types | |
Applicative JSM | |
MonadIO JSM | |
Defined in Language.Javascript.JSaddle.Types | |
MonadThrow JSM | |
Defined in Language.Javascript.JSaddle.Types | |
MonadCatch JSM | |
MonadMask JSM | |
MonadJSM JSM | |
Defined in Language.Javascript.JSaddle.Types | |
MonadRef JSM | |
MonadAtomicRef JSM | |
Defined in Language.Javascript.JSaddle.Types atomicModifyRef :: Ref JSM a -> (a -> (a, b)) -> JSM b # atomicModifyRef' :: Ref JSM a -> (a -> (a, b)) -> JSM b # | |
MonadUnliftIO JSM | |
Defined in Language.Javascript.JSaddle.Types | |
type Ref JSM | |
Defined in Language.Javascript.JSaddle.Types |
class (Applicative m, MonadIO m) => MonadJSM (m :: Type -> Type) #
Instances
Shared memory locations that support atomic memory transactions.
readTVarIO :: MonadIO m => TVar a -> m a #
Lifted version of readTVarIO
Since: unliftio-0.2.1.0