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
Record
Variant
Array
- 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" halogenComponent
We 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.