@apexcura/ui-builder
Version:
A low-code UI builder library for dynamic form generation and reusable components built with React, Redux, Tailwind, and Ant Design.
312 lines (269 loc) • 8.41 kB
Markdown
# @apexcura/ui-builder
A **powerful, JSON Schema-driven UI renderer** built for React applications. It handles everything — from rendering UI elements to managing state via Redux, making API calls, handling validations, and defining event flows — all configurable through a single JSON schema.
> ⚡ Declarative. Scalable. Developer-friendly.
---
## ✨ Features
* 🧹 **Schema-Driven UI Rendering**
Define forms, tables, dashboards, charts, and dynamic layouts using a flexible JSON structure.
* 🧠 **State Management with Redux Toolkit**
Automatically sets up Redux stores, reducers, actions, and selectors for your UI based on the schema.
* 🔁 **Built-in API Integration**
Perform GET, POST, PUT, DELETE requests — all defined declaratively in the schema.
* ⚙️ **Event Handling Without Code**
Manage click handlers, form submissions, conditional rendering, and navigation using event maps.
* 💿 **Redux Persist Support**
Automatically persists state across sessions.
* 🎨 **TailwindCSS + Ant Design UI**
Combines the flexibility of Tailwind with the power of Ant Design components.
* 📊 **Highcharts Support**
Render charts using `highcharts` and `highcharts-react-official` directly from JSON.
* 🔐 **Form Validations, Modals, Toasts, Print View, Rich Text, and More**
All natively supported via schema keys.
---
## 🚀 Get Started
### Installation
```bash
npm install @apexcura/ui-builder
```
> ⚠️ Make sure to install the required peer dependencies:
```bash
npm install react react-dom react-redux @reduxjs/toolkit redux-thunk redux-persist react-router-dom
```
> ℹ️ Add required CSS imports to your main application file:
```bash
import '@apexcura/ui-builder/dist/styles/index.css';
```
---
## 🛠 Usage
Inside the project's reducers list add dynamicStateReducer also into it with name dynamic
```tsx
import { combineReducers } from "@reduxjs/toolkit";
import { resetState } from "./actions";
import { dynamicStateReducer } from "@apexcura/ui-builder"; // Package Slice
import appStateReducer from "./appState/appStateSlice"; // Project slice
const appReducer = combineReducers({
appState: appStateReducer,
dynamic: dynamicStateReducer, // UIBuilder's state slice
});
const rootReducer = (state: RootState | undefined, action: any): RootState => {
if (action.type === resetState.type) {
state = undefined;
}
return appReducer(state, action);
};
export default rootReducer;
export type RootState = ReturnType<typeof appReducer>;
```
Create a wrapper component that provides the necessary context:
```tsx
// src/index.tsx
function App() {
return (
<ACWrapperContext
props={{
constants: CONSTANTS, // constants if you have any
store: store, // redux store object
utils: Utils, // Utils object of that project (which contains makeApiCall function)
}}
>
<Provider store={store}>
...
</Provider>
</ACWrapperContext>
);
}
```
> ℹ️ As each project has its own api calling patterns along with their own base urls, our library directly call the project's api functions using project's base urls only
---
## Creating Your First View
Define a schema and use the UIBuilder component to render it:
```tsx
import { UIBuilder } from "@apexcura/ui-builder";
import useAppNavigate from "../../hooks/useAppNavigate";
import basicSchema from "../../schemas/basicSchema.json";
const BasicExample = () => {
const navigate = useAppNavigate(); // you can use useNavigate hook also
return <UIBuilder json={basicSchema} navigate={navigate} />;
};
export default BasicExample;
```
---
## 📄 Example Schema
```json
{
"name": "basic-example-form",
"schema": [
{
"name": "physio_evaluation",
"initial_states": {
"org_name": "@localStorage.organization.name"
},
"className": "w-full flex bg-white rounded-md p-2 py-6",
"fields": [
{
"name": "name",
"label": "First Name",
"element": "input-text",
"required": true,
"placeholder": "Eg: Jon Doe",
"color": "primary",
"valueSource": {
"storedLocation": "patient_details.first_name"
},
"handlers": [
{
"action": "changeState",
"type": "onChange",
"args": {
"storedLocation": "patient_details.first_name"
}
}
]
},
{
"name": "phno",
"label": "Phone number",
"element": "input-number",
"required": true,
"placeholder": "Eg: 9123456789",
"color": "primary",
"valueSource": {
"storedLocation": "patient_details.phno"
},
"handlers": [
{
"action": "changeState",
"type": "onChange",
"args": {
"storedLocation": "patient_details.phno"
}
}
]
},
{
"name": "btn-cancel",
"label": "Previous",
"element": "button",
"variant": "outlined",
"color": "primary",
"iconClassName": "aci-left-arrow aci-dynamic-size size-[12px]",
"handlers": [
{
"action": "changeState",
"args": {
"storedLocation": "selectedTab",
"value": "patient_details"
}
}
]
},
{
"name": "btn-submit",
"label": "Save and next",
"iconClassName": "aci-right-arrow aci-dynamic-size size-[12px]",
"iconPosition": "right",
"element": "button",
"variant": "solid",
"handlers": [
{
"action": "validateForm",
"args": {
"onTrue": [
{
"action": "makeApiCall",
"args": {
"api": {
"endpoint": "/addPatient",
"method": "POST",
"payload": {
"patient_umr": "@state.patient_details.uhid",
"formData": "@state.patient_details"
},
"onSuccess": [
{
"action": "displayToast",
"args": {
"type": "success",
"message": "Patient added successfully!!!"
}
}
]
}
}
}
]
}
}
]
},
{
"name": "effects",
"handlers": [
{
"action": "makeApiCall",
"args": {
"api": {
"endpoint": "/patient/${patient_id}",
"method": "GET",
"params": {
"patient_id": "@state.patient_id"
},
"onSuccess": [
{
"action": "changeState",
"args": {
"storedLocation": "patient_details_resp"
}
}
],
"onFailure": [
{
"action": "displayToast",
"args": {
"type": "error",
"message": "Unable to fetch details"
}
}
]
}
},
"dependencies": ["patient_id"]
}
]
}
],
"handlers": []
}
]
}
```
---
## 🧪 Development
### Build the project:
```bash
npm install
npm run build
```
### Watch for changes during development:
```bash
npm run watch
```
### Lint and format code:
```bash
npm run lint
npm run format
```
---
## 🧹 Built With
* ⚛️ React 18
* 🧰 Redux Toolkit
* 💿 Redux Persist
* 🧠 Redux Thunk
* 🎨 TailwindCSS + Ant Design
* 📊 Highcharts
* 📄 React Quill
* 🖰 React To Print
* 📦 Webpack
---
## 📘 License
ISC © \[Apex Cura HealthCare]