Define UIs in terms of data types.
- Data centric
UIs are defined in terms of data types. You don't have to know much about frontends. - Type safety
Impossible to create wrong configutations for given types. - Framework agnostic
Can be embedded in any ReactBasic or Halogen app - Configurable
UIs for each data type can be customized - Extensible
UIs for any data type can be written in a simple MVC architecture - Data validation
Data is validated on the fly and errors are displayed
Any part of a web app that need to handle user input of nested structured data. E.g: It works best for scenarios where highest priority is correctness of data and not so much the look and feel.
- Settings/Config panels
- Controls to showcase UI components
- Back office tools
The following types are supported out of the box:
- Primitives like
String,Int,Number,Boolean RecordVariantArray- Common ADTs like
Maybe,Either,Tuple - Newtypes
- Refinement of existing types (smart constructor pattern)
- Custom ADTs
- Generic Json inputs for not yet supported types
API docs are published on Pursuit.
Learn about the core concepts of interactive-data in the Library Manual.
-
Install the library
spago install interactive-data -
Install a virtual dom implementation, e.g. one of the following:
spago install chameleon-halogen spago install chameleon-react-basic -
Install a bundler, e.g.:
npm install --dev --save parcel
The following example renders with Halogen. Have a look at the demo folder for more examples in different frameworks.
src/Main.purs:
module Main (main) where
import Prelude
import Data.Maybe (Maybe(..))
import Effect (Effect)
import Effect.Class.Console (log)
import InteractiveData as ID
import Chameleon.Impl.Halogen as HI
main :: Effect Unit
main = do
let
-- 1. Compose a "Data UI" for a specific type
sampleDataUi = ID.record_
{ user: ID.record_
{ firstName: ID.string_
, lastName: ID.string_
, size: ID.number { min: 0.0, max: 100.0 }
}
, meta: ID.record_
{ description: ID.string_
, headline: ID.string_
}
}
-- 2. Turn "Data UI" into an App interface
sampleApp =
ID.toApp
{ name: "Sample"
, initData: Nothing
, fullscreen: true
, showLogo: false
}
sampleDataUi
-- 3. Create Halogen component
halogenComponent =
HI.uiToHalogenComponent
{ onStateChange: \newState -> do
-- Use the `extract` function to get data out of the state
log (show $ sampleApp.extract newState)
}
sampleApp.ui
-- 4. Finally mount the component to the DOM
HI.uiMountAtId "root" halogenComponentWe also need to create a simple html file and a index.js file to run the web app.
static/index.html:
<html>
<head>
<title>Interactive Data Sample</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<script src="index.js" type="module"></script>
<div id="root"></div>
</body>
</html>static/index.js:
import { main } from "../output/Main/index.js";
main();spago build
parcel static/index.html
Go to http://localhost:1234
- Currently no support for recursive types.
- Data UIs cannot have side effects other than user input. A Data UI that fetches data from a server is currently not possible.
If you have ideas for improvements or want to contribute, please open an issue or PR.
The repo structure is described in docs/repo-structure.md.