Hedwig
Hedwig is a fast, type safe, declarative PureScript library for building web applications.
Getting Started | Examples
Features
Fast
The performance of Hedwig is competitive with mainstream JavaScript frameworks, both in terms of CPU usage and Memory consumption. In js-framework-benchmark, Hedwig performs as well as or better than React, Angular, and Vue.
Small
A Hello World program weighs in at around 11kB minified + gzipped. The js-framework-benchmark implementation weighs in at around 16kB.
Declarative Animations
Animations are essential to maintain a direct and engaging real-world feel. Hedwig makes adding animations easy using a declarative CSS transition based API. Read More β
Integration with Developer Tools
Hedwig integrates with Redux DevTools to provide an interactive state modification viewer and time travelling debugger. Read More β
Getting Started
You'll need to have Node.js and pulp installed.
You can either clone the starter template or follow the instructions below to create an application from scratch.
Starter Template
Clone the repository, install the dependencies, and start the dev server:
$ git clone https://github.com/utkarshkukreti/purescript-hedwig-starter my-app
$ cd my-app
$ npm install
$ bower install
$ npm start
and open index.html
in your browser.
From Scratch
Initialize a new project using pulp
and create an empty package.json
:
$ mkdir my-app
$ cd my-app
$ pulp init
$ echo '{}' > package.json
Install the dependencies:
$ bower install --save purescript-hedwig
$ npm install --save purescript-hedwig
Create an HTML file to load the JS (save this to index.html
):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My App</title>
</head>
<body>
<main></main>
<script src="index.js"></script>
</body>
</html>
Create and mount the application (save this to src/Main.purs
):
module Main where
import Prelude
import Effect (Effect)
import Hedwig as H
import Hedwig ((:>))
type Model = Int
init :: Model
init = 0
data Msg = Increment | Decrement
update :: Model -> Msg -> Model
update model = case _ of
Increment -> model + 1
Decrement -> model - 1
view :: Model -> H.Html Msg
view model = H.main [H.id "main"] [
H.button [H.onClick Decrement] [H.text "-"],
H.text (show model),
H.button [H.onClick Increment] [H.text "+"]
]
main :: Effect Unit
main = do
H.mount "main" {
init: init :> [],
update: \msg model -> update msg model :> [],
view
}
Compile the application:
$ pulp browserify --to index.js
Finally, open index.html
in your browser. You should now see the text "Hello,
world!" appear on the screen.
Animations
Hedwig provides two main functions to add animation to elements:
(1) Hedwig.transition :: String -> Trait msg
Adding this to the traits list of an element will make Hedwig to add 6 classes
to the element at different times. The String
argument is the prefix to use
for the classes. Let's say we do div [Hedwig.transition "fade"] [text "Hello"]
. This will apply 6 classes:
-
fade-enter: Starting state for enter. Added before element is inserted, removed one frame after element is inserted.
-
fade-enter-active: Active state for enter. Applied during the entire entering phase. Added before element is inserted, removed when transition/animation finishes. This class can be used to define the duration, delay and easing curve for the entering transition.
-
fade-enter-to: Ending state for enter. Added one frame after element is inserted (at the same time v-enter is removed), removed when transition/animation finishes.
-
fade-leave: Starting state for leave. Added immediately when a leaving transition is triggered, removed after one frame.
-
fade-leave-active: Active state for leave. Applied during the entire leaving phase. Added immediately when leave transition is triggered, removed when the transition/animation finishes. This class can be used to define the duration, delay and easing curve for the leaving transition.
-
fade-leave-to: Ending state for leave. Added one frame after a leaving transition is triggered (at the same time v-leave is removed), removed when the transition/animation finishes.
Inspiration for the feature and source of the description above..
With a tiny bit of CSS, you can create all sorts of animations with the above. See the AnimatedList.purs and AnimatedList.css and its Live Demo for an example.
Hedwig.transition'
is similar but lets you specify custom class names to add
for each stage.
- Hedwig.transitionGroup :: String -> Trait msg
A transition group enables normal transition on all its children elements, plus it keeps track of the positions of its children, and whenever that changes, adds CSS classes and a CSS transform to them. With a line of CSS, you can animate the movement of the nodes:
.fade-move {
transition: transform 0.2s;
}
See AnimatedList.purs and AnimatedList.css and its Live Demo for an example.
Hedwig.transitionGroup'
is similar but lets you specify custom class names to
add for each stage.
Developer Tools
Hedwig integrates with Redux DevTools to provide an interactive state modification viewer and time travelling debugger.
(To try this right now, install the Redux DevTools Chrome Extension and head over to this page.)
To enable this, you need to do two things:
-
Import
Hedwig.Devtools
-
In your
main
function, before you mount the application, callHedwig.Devtools.init
.
For an example, check out the source of the Counters example.
After recompiling your application, you should see all messages and state being logged into the Redux tab of Chrome DevTools window.
Examples
The examples/
directory contains a bunch of examples:
-
HelloWorld (Demo) - Just writes the text "Hello, world!" to the screen.
-
Counter (Demo) - A numeric counter with increment and decrement buttons.
-
Dice (Demo) - Rolls a dice using the purescript-random package. Showcases how a Hedwig application can run side effects.
-
Prompt (Demo) - Prompts the user to enter their name by calling
window.prompt
. Also showcases how to run functions with side effects. -
AnimatedList (Demo) - An animated list of boxes.
-
JsFrameworkBenchmark (Demo) - An implementation of js-framework-benchmark. See benchmark results here.