Safe Haskell | None |
---|---|
Language | Haskell2010 |
I think I know precisely what I mean.
A frontend abstraction motivated by simplicity, performance, and egonomics. This module provides core abstractions and types with almost no implimentation details. IE no batteries included. You may use this model a la carte, build ontop of it, or include more Backend packages for additional batteries.
Backend is focused on letting you build your frontend the way you want to. And so is as unopinionated as possible, beyond providing a concrete programming model.
Synopsis
- data Html :: (Type -> Type) -> Type -> Type where
- data Prop m o where
- type Props m o = [(Text, Prop m o)]
- mapHtml :: Functor m => (m ~> n) -> Html m o -> Html n o
- mapProp :: (m ~> n) -> Prop m o -> Prop n o
- mapProps :: ([(Text, Prop m o)] -> [(Text, Prop m o)]) -> Html m o -> Html m o
- mapChildren :: ([Html m a] -> [Html m a]) -> Html m a -> Html m a
- class Backend b m a | b m -> a where
- shpadoinkle :: forall b m a t. Backend b m a => Territory t => Eq a => (m ~> JSM) -> (t a -> b m ~> m) -> a -> t a -> (a -> Html (b m) a) -> b m RawNode -> JSM ()
- fullPage :: Backend b m a => Territory t => Eq a => (m ~> JSM) -> (t a -> b m ~> m) -> a -> (a -> Html (b m) a) -> b m RawNode -> JSM ()
- fullPageJSM :: Backend b JSM a => Territory t => Eq a => (t a -> b JSM ~> JSM) -> a -> (a -> Html (b JSM) a) -> b JSM RawNode -> JSM ()
- class Territory s where
- writeUpdate :: s a -> (a -> JSM a) -> JSM ()
- shouldUpdate :: Eq a => (b -> a -> JSM b) -> b -> s a -> JSM ()
- createTerritory :: a -> JSM (s a)
- type (~>) m n = forall a. m a -> n a
- type Html' a = forall m. Applicative m => Html m a
- newtype RawNode = RawNode {}
- newtype RawEvent = RawEvent {
- unRawEvent :: JSVal
- h :: Text -> [(Text, Prop m o)] -> [Html m o] -> Html m o
- text :: Text -> Html m o
- flag :: Bool -> Prop m o
- listener :: m o -> Prop m o
- listen :: Text -> m o -> (Text, Prop m o)
- listenRaw :: Text -> (RawNode -> RawEvent -> m o) -> (Text, Prop m o)
- listen' :: Applicative m => Text -> o -> (Text, Prop m o)
- baked :: JSM RawNode -> Html m o
- 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)
- injectProps :: [(Text, Prop m o)] -> Html m o -> Html m o
- class (Applicative m, MonadIO m) => MonadJSM (m :: Type -> Type)
- data JSM a
- liftJSM :: MonadJSM m => JSM a -> m a
- newTVarIO :: MonadIO m => a -> m (TVar a)
- readTVarIO :: MonadIO m => TVar a -> m a
- runJSorWarp :: Int -> JSM () -> IO ()
- runJSM :: MonadIO m => JSM a -> JSContextRef -> m a
- askJSM :: MonadJSM m => m JSContextRef
Documentation
data Html :: (Type -> Type) -> Type -> Type where Source #
This is the core type in Backend.
The (Html m) Functor
is used to describe Html documents.
Please note, this is NOT a the Virtual Dom used by Backend
this type backs a DSL that is then interpreted into Virual Dom
by the backend of your choosing. Html comments are not supported.
Node :: Text -> [(Text, Prop m o)] -> [Html m o] -> Html m o | A standard node in the dom tree |
Potato :: JSM RawNode -> Html m o | If you can bake an element into a |
TextNode :: Text -> Html m o | The humble text node |
Properties of a Dom node, Backend does not use attributes directly, but rather is focued 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 corrosponding property.
PText :: Text -> Prop m o | A text property |
PListener :: (RawNode -> RawEvent -> m o) -> Prop m o | Event listeners are provided with the |
PFlag :: Bool -> Prop m o | A boolean property, works as a flag
for example |
Instances
Functor m => Functor (Prop m) Source # | Props are also merely |
IsString [(Text, Prop m o)] Source # | Strings are overload as the class property
|
Defined in Shpadoinkle fromString :: String -> [(Text, Prop m o)] # | |
IsString (Prop m o) Source # | Strings are overload as text props
|
Defined in Shpadoinkle fromString :: String -> Prop m o # |
type Props m o = [(Text, Prop m o)] Source #
Type alias for convenience. Typing out the nested brackets is tiresome.
mapHtml :: Functor m => (m ~> n) -> Html m o -> Html n o Source #
If you can provide a Natural Transformation from one Monad to another
you may change the action of Html
mapProp :: (m ~> n) -> Prop m o -> Prop n o Source #
If you can provide a Natural Transformation from one Monad to another
you may change the action of Prop
mapProps :: ([(Text, Prop m o)] -> [(Text, Prop m o)]) -> Html m o -> Html m o Source #
Transform the properites of some Node. This has no effect on TextNode
s or Potato
s
mapChildren :: ([Html m a] -> [Html m a]) -> Html m a -> Html m a Source #
Transform the children of some Node. This has no effect on TextNode
s or Potato
s
class Backend b m a | b m -> a where Source #
patch raw Nothing >=> patch raw Nothing = patch raw Nothing
The Backend class describes a backend that can render Html
.
Backends are generally Monad Transformers b
over some Monad m
.
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 for use to diff. Will be |
-> VNode b m | New Virtual Dom to render. |
-> b m (VNode b m) | Effect producing and 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 () -> b m () Source #
A backend may perform some inperative setup steps
:: Backend b m a | |
=> Territory t | |
=> Eq a | |
=> (m ~> JSM) | how to be get to JSM? |
-> (t a -> b m ~> m) | What backend are we running? |
-> a | what is the initial state? |
-> t 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. This combines a backend, a territory, and a model and renders the Backend view to the page.
:: Backend b m a | |
=> Territory t | |
=> Eq a | |
=> (m ~> JSM) | how do we get to JSM? |
-> (t 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 | |
=> Territory t | |
=> Eq a | |
=> (t 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 () |
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.
class Territory s where Source #
Shpadoinkling requires a Territory, such as Colorado Territory. This class provides for the state container. As such you may use any type you wish where this semantic can be implimented.
writeUpdate :: s a -> (a -> JSM a) -> JSM () Source #
How do we update the state?
shouldUpdate :: Eq a => (b -> a -> JSM b) -> b -> s a -> JSM () Source #
When should consider a state updated? This is akin to React's component should update thing. The idea is to provide a semantic for when we consider the model to have changed.
createTerritory :: a -> JSM (s a) Source #
Create a new territory
type Html' a = forall m. Applicative m => Html m a Source #
A type alias to support scenarios where the view code event listeners are pure.
A dom node reference. Useful for building baked potatoes, and binding a Backend view to the page
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
injectProps :: [(Text, Prop m o)] -> Html m o -> Html m o Source #
Inject props into an existing Node
class (Applicative m, MonadIO m) => MonadJSM (m :: Type -> Type) #
Instances
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 | |
MakeArgs arg => MakeArgs (JSM arg) | |
type Ref JSM | |
Defined in Language.Javascript.JSaddle.Types |
readTVarIO :: MonadIO m => TVar a -> m a #
Lifted version of readTVarIO
Since: unliftio-0.2.1.0
runJSorWarp :: Int -> JSM () -> IO () Source #
Start the program!
For GHC or GHCjs. I saved your from using CPP directly. Your welcome.
runJSM :: MonadIO m => JSM a -> JSContextRef -> m a #
Runs a JSM
JavaScript function in a given JavaScript context.
askJSM :: MonadJSM m => m JSContextRef #
Gets the JavaScript context from the monad