Composable UIs for interactive data.
This library is in early development and the API is not stable yet. Things may not yet work as expected.
thought2.github.io/purescript-interactive-data
-
Framework agnostic
_Can be embedded in any React app -
Configurable
UIs for each data type can be customized -
Extensible
UIs for any custom data type can be written -
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:
- settings panel
- back office tools
- user input forms
The following types are supported out of the box:
String
Number
Record
- Tagged unions
npm install ts-interactive-data
App.tsx:
import * as ID from "ts-interactive-data";
import * as React from "react";
// 1. Compose a "Data UI" for a specific type
const sampleDataUi = ID.record_({
user: ID.record_({
firstName: ID.string({
multiline: false,
maxLength: 100,
}),
lastName: ID.string({}),
size: ID.number({
min: 0,
max: 100,
}),
info: ID.variant_("age", {
age: ID.number({}),
name: ID.string({}),
}),
}),
settings: ID.record_({
accountId: ID.string({}),
description: ID.string({}),
}),
});
// 2. Turn "Data UI" into an App interface
const sampleApp = ID.toApp(sampleDataUi, {
name: "Sample",
fullscreen: true,
});
// 3. With the `useApp` hook you can integrate the UI into any React app
export const App = () => {
const { jsx, data } = ID.useApp(sampleApp);
React.useEffect(() => {
console.log("Data of new state:");
console.log(data);
}, [data]);
return <div>{jsx}</div>;
};
We also need to create a simple html file and an index.tsx to run the web app.
index.tsx:
import * as React from "react";
import { createRoot } from "react-dom/client";
import { App } from "./App";
const container = document.getElementById("app");
if (!container) {
throw new Error("No container");
}
const root = createRoot(container);
root.render(<App />);
index.html:
<html>
<head>
<title>ts-interactive-data Demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<script src="./index.tsx" type="module"></script>
<div id="app"></div>
</body>
</html>
parcel static/index.html