mirror of
https://github.com/lagunoff/htmlt.git
synced 2024-10-04 02:47:08 +03:00
Lightweight frontend library for GHCJS
benchmarks | ||
examples | ||
src | ||
.gitignore | ||
8.6.0.nix | ||
8.10.7.nix | ||
9.7.2.nix | ||
htmlt.cabal | ||
README.md | ||
shell.nix |
Lightweight frontend library for GHCJS with focus on minimalism and simplicity
Getting started
First you have to install nix
package manager to download and install the dependecies. By default
nix-shell gets GHCJS compiler from
reflex-platform
project. You have to add their binary caches to your nix.conf
to
avoid building everything from sources
# ~/.config/nix.conf
substituters = https://nixcache.reflex-frp.org
trusted-substituters = https://nixcache.reflex-frp.org
trusted-public-keys = ryantrinkle.com-1:JJiAKaRv9mWgpVAz8dwewnZe0AzzEAzPkagE9SP5NWI=
Build the examples:
# Clone the repository
git clone https://github.com/lagunoff/htmlt.git
cd htmlt
# Enter the nix-shell
nix-shell
# Build examples with cabal
cabal build -fexamples --ghcjs --ghcjs-options="-j"
Once cabal build
is successful you can find the js executables in
dist-newstyle/build/x86_64-linux/ghcjs-8.6.0.1/htmlt-0.1.0.0/x/
and run them opening index.html
in browser
Simple example
-- Example featuring <input> element and two buttons. The input value
-- is synchronized with 'DynRef's state and can be modified by either entering a
-- number into the input or by clicking one of the two buttons
main :: IO ()
main = void $ attachToBody do
-- First create a 'DynRef
counterRef <- newRef @Int 0
div_ do
input_ do
-- Show the value inside <input>
dynProp "value" $ T.pack . show <$> fromRef counterRef
-- Parse and update the value on each InputEvent
on "input" $ decodeEvent intDecoder $ writeRef counterRef
br_
-- Decrease the value on each click
button_ do
on_ "click" $ modifyRef counterRef pred
text "Decrease"
-- Increase the value on each click
button_ do
on_ "click" $ modifyRef counterRef succ
text "Increase"
where
intDecoder =
valueDecoder >=> MaybeT . pure . readMaybe . T.unpack
Quick API summary
-- Constructing DOM
el :: Text -> Html a -> Html a
elns :: Text -> Text -> Html a -> Html a
text :: Text -> Html ()
dynText :: Dynamic Text -> Html ()
-- Applying attributes and properties
prop :: Text -> v -> Html ()
dynProp :: Text -> Dynamic v -> Html ()
attr :: Text -> Text -> Html ()
dynAttr :: Text -> Text -> Html ()
toggleClass :: Text -> Dynamic Bool -> Html ()
toggleAttr :: Text -> Dynamic Bool -> Html ()
dynStyle :: Text -> Dynamic Text -> Html ()
dynStyles :: Dynamic Text -> Html ()
dynValue :: Dynamic Text -> Html ()
dynClass :: Dynamic Text -> Html ()
dynChecked :: Dynamic Bool -> Html ()
dynDisabled :: Dynamic Bool -> Html ()
-- Handling DOM events
on :: EventName -> (DOMEvent -> Step ()) -> Html ()
on_ :: EventName -> Step () -> Html ()
onOptions :: EventName -> ListenerOpts -> (DOMEvent -> Step ()) -> Html ()
onDecoder :: EventName -> Decoder a -> (a -> Step ()) -> Html ()
onGlobalEvent :: ListenerOpts -> DOMNode -> EventName -> (DOMEvent -> Step ()) -> Html ()
-- Decoding data from DOM Events
mouseDeltaDecoder :: JSVal -> MaybeT m MouseDelta
clientXYDecoder :: JSVal -> MaybeT m (Point Int)
offsetXYDecoder :: JSVal -> MaybeT m (Point Int)
pageXYDecoder :: JSVal -> MaybeT m (Point Int)
keyModifiersDecoder :: JSVal -> MaybeT m KeyModifiers
keyCodeDecoder :: JSVal -> MaybeT m Int
keyboardEventDecoder :: JSVal -> MaybeT m KeyboardEvent
valueDecoder :: JSVal -> MaybeT m Text
checkedDecoder :: JSVal -> MaybeT m Bool
-- DOM extras, useful helpers
unsafeHtml :: MonadIO m => Text -> HtmlT m ()
portal :: Monad m => DOMElement -> HtmlT m a -> HtmlT m a
addFinalizer :: MonadReactive m => IO () -> m ()
-- Dynamic collections
simpleList :: Dynamic [a] -> (Int -> DynRef a -> Html ()) -> Html ()
-- Arbitrary dynamic content
dyn :: Dynamic (Html ()) -> Html ()
-- Contructing Events
newEvent :: MonadReactive m => m (Event a, Trigger a)
fmap :: (a -> b) -> Event a -> Event a
never :: Event a
updates :: Dynamic a -> Event a
mapMaybeE :: (a -> Maybe b) -> Event a -> Event b
-- Constructing Dynamics
constDyn :: a -> Dynamic a
fromRef :: DynRef a -> Dynamic a
fmap :: (a -> b) -> Dynamic a -> Dynamic b
(<*>) :: Dynamic (a -> b) -> Dynamic a -> Dynamic b
mapDyn :: MonadReactive m => Dynamic a -> (a -> b)-> m (Dynamic b)
mapDyn2 :: MonadReactive m => Dynamic a -> Dynamic b -> (a -> b -> c) -> m (Dynamic c)
holdUniqDyn :: Eq a => Dynamic a -> Dynamic a
holdUniqDynBy :: (a -> a -> Bool) -> Dynamic a -> Dynamic a
-- Constructing DynRefs
newRef :: MonadReactive m => a -> m (DynRef a)
lensMap :: Lens' s a -> DynRef s -> DynRef a
-- Read and write DynRefs, Dynamics
readDyn :: MonadIO m => Dynamic a -> m a
readRef :: MonadIO m => DynRef a -> m a
writeRef :: DynRef a -> a -> Step ()
modifyRef :: DynRef a -> (a -> a) -> Step ()
-- Starting and shutting down the application
atatchOptions :: StartOpts -> Html a -> IO (a, RunningApp)
attachTo :: DOMElement -> Html a -> IO (a, RunningApp)
attachToBody :: Html a -> IO (a, RunningApp)
detach :: RunningApp -> IO ()
Other examples
Counter | source | demo |
TodoMVC | source | demo |
Simple Routing | source | demo |
Todos
- API to display sum types
- Reduce compile time by getting rid of
ghcjs-dom
andjsaddle-dom
from dependency list - Add benchmarks
- More examples and documentation
- Similar library for ReactNative