MUI json endpoint form builder. Check this storybook for more samples...
A React view builder which interacts with a JSON endpoint to generate nested 12-column grids with input fields and automatic state management in a declarative style. Endpoint is typed by TypeScript guards (IntelliSense available). This tool is based on MUI
components, so your application will look beautiful on any device...
There is a
create-react-app
template available in this repository
yarn create react-app --template cra-template-react-declarative .
or
npx create-react-app . --template=react-declarative
There is a sample app avalible in demo folder...
npm install --save react-declarative tss-react @mui/material @emotion/react @emotion/styled
The
react-declarative
is not just a form builder. This one is the huge framework with dashboard adaptive cards builder, crud-based Grid component and more.
This tool also provide it's own way of rapid application development by simplifying app state managament. New features appear frequently, so you should be able to read the project's storybook, browse an organization with sample projects, and read the source code.
Also, several starter kits available
1. Pure React Starter
GitHub repo: https://github.com/react-declarative/cra-template-react-declarative
yarn create react-app --template cra-template-react-declarative .
2. Ethers.js/React Starter
GitHub repo: https://github.com/react-declarative/cra-template-solidity
yarn create react-app --template cra-template-solidity .
3. AppWrite/React Starter
GitHub repo: https://github.com/react-declarative/cra-template-appwrite
yarn create react-app --template cra-template-appwrite .
and few more quite interesting demo projects
1. ERC-20 Payment gateway
GitHub repo: https://github.com/react-declarative/erc20-payment-gateway
git clone https://github.com/react-declarative/erc20-payment-gateway.git
2. React Face KYC
GitHub repo: https://github.com/react-declarative/react-face-kyc
git clone https://github.com/react-declarative/react-face-kyc.git
3. BrainJS Cryptocurrency Trend
GitHub repo: https://github.com/react-declarative/brainjs-cryptocurrency-trend
git clone https://github.com/react-declarative/brainjs-cryptocurrency-trend.git
4. NFT Mint Tool
GitHub repo: https://github.com/react-declarative/nft-mint-tool
git clone https://github.com/react-declarative/nft-mint-tool.git
5. React PocketBase CRM
GitHub repo: https://github.com/react-declarative/react-pocketbase-crm
git clone https://github.com/react-declarative/react-pocketbase-crm.git
Link to the source code
The <Scaffold2 />
implements the basic Material Design visual layout structure by using config instead of manual ui elements composition.
const options: IScaffold2Group[] = [
{
id: 'build',
label: 'Build',
children: [
{
id: 'authentication',
label: 'Authentication',
isVisible: async () => await ioc.authService.hasRole('unauthorized'),
icon: PeopleIcon,
tabs: [
{ id: 'tab1', label: 'Tab1 in header', },
{ id: 'tab2', label: 'Tab2 in header', },
],
options: [
{ id: 'tab1', label: 'Tab1 in side menu' },
{ id: 'tab2', label: 'Tab2 in side menu' },
],
},
{ id: 'Database', label: 'Label is optional (can be generated automatically from ID in snake case)', icon: DnsRoundedIcon, },
{ id: 'Storage', isDisabled: async () => await myAmazingGuard(), icon: PermMediaOutlinedIcon, },
{ id: 'Hosting', icon: PublicIcon, },
...
1. Layout grid
Link to the source code
const fields: TypedField[] = [
{
type: FieldType.Line,
title: 'User info',
},
{
type: FieldType.Group,
phoneColumns: '12',
tabletColumns: '6',
desktopColumns: '4',
fields: [
{
type: FieldType.Text,
title: 'First name',
defaultValue: 'Petr',
description: 'Your first name',
leadingIcon: Face,
focus() { console.log("focus :-)"); },
blur() { console.log("blur :-("); },
name: 'firstName',
},
{
type: FieldType.Text,
title: 'Last name',
defaultValue: 'Tripolsky',
description: 'Your last name',
name: 'lastName',
},
...
];
2. Form validation
Link to the source code
const fields: TypedField[] = [
{
type: FieldType.Text,
name: 'email',
trailingIcon: Email,
defaultValue: 'tripolskypetr@gmail.com',
isInvalid({email}) {
const expr = /^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$/g;
if (!expr.test(email)) {
return 'Invalid email address';
} else {
return null;
}
},
isDisabled({disabled}) {
return disabled;
},
isVisible({visible}) {
return visible;
}
},
{
type: FieldType.Expansion,
title: 'Settings',
description: 'Hide or disable',
fields: [
{
type: FieldType.Switch,
title: 'Mark as visible',
name: 'visible',
defaultValue: true,
},
...
3. Gallery of controls
Link to the source code
const fields: TypedField[] = [
{
type: FieldType.Paper,
fields: [
{
type: FieldType.Line,
title: 'Checkboxes',
},
{
type: FieldType.Checkbox,
name: 'checkbox1',
columns: '3',
title: 'Checkbox 1',
},
{
type: FieldType.Checkbox,
name: 'checkbox2',
columns: '3',
title: 'Checkbox 2',
},
...
4. JSX Injection
Link to the source code
const fields: TypedField[] = [
{
type: FieldType.Paper,
fields: [
{
type: FieldType.Component,
element: (props) => <Logger {...props}/>,
},
],
},
...
];
5. UI-Kit override
Link to the source code
<OneSlotFactory
CheckBox={MyCheckBox}
Text={MyInput}
...
>
<One
...
/>
...
</OneSlotFactory>
6. Hiding fields by business functions
See RBAC
const fields: TypedField[] = [
{
type: FieldType.Text,
name: 'phone',
hidden: ({ payload }) => {
return !payload.features.has('show-phone-number');
},
},
...
];
Link to the source code
Adaptive json-configurable data grid with build-in mobile device support
const filters: TypedField[] = [
{
type: FieldType.Text,
name: 'firstName',
title: 'First name',
},
{
type: FieldType.Text,
name: 'lastName',
title: 'Last name',
}
];
const columns: IColumn[] = [
{
type: ColumnType.Text,
field: 'id',
headerName: 'ID',
width: (fullWidth) => Math.max(fullWidth - 650, 200),
columnMenu: [
{
action: 'test-action',
label: 'Column action',
},
],
},
...
];
const actions: IListAction[] = [
{
type: ActionType.Add,
label: 'Create item'
},
...
];
const operations: IListOperation[] = [
{
action: 'operation-one',
label: 'Operation one',
},
];
const chips: IListChip[] = [
{
label: 'The chip1_enabled is true',
name: 'chip1_enabled',
color: '#4caf50',
},
...
];
const rowActions: IListRowAction[] = [
{
label: 'chip1',
action: 'chip1-action',
isVisible: ({ chip1_enabled }) => chip1_enabled,
},
...
];
...
return (
<ListTyped
withMobile
withSearch
withArrowPagination
rowActions={rowActions}
actions={actions}
filters={filters}
columns={columns}
operations={operations}
chips={chips}
/>
)
You can use InfiniteView for always-mounted or VirtualView for virtualized infinite lists
<VirtualView
component={Paper}
sx={{
width: "100%",
height: 250,
mb: 1,
}}
onDataRequest={() => {
console.log('data-request');
setItems((items) => [
...items,
...[uuid(), uuid(), uuid(), uuid(), uuid()],
]);
}}
>
{items.map((item) => (
<span key={item}>{item}</span>
))}
</VirtualView>
See angular2 docs
import { Async } from 'react-declarative'
import { CircularProgress } from '@mui/material'
const PostItem = ({
id,
}) => {
const { getPostById } = useBlogApi();
return (
<Async payload={id} Loader={CircularProgress}>
{async (id) => {
const { title, body } = await getPostById(id);
return (
<div>
<p>{title}</p>
<p>{body}</p>
</div>
);
}}
</Async>
);
};
See angular2 docs
import { If } from 'react-declarative'
const ProfilePage = () => {
const { hasRole } = useRoleApi();
return (
<If condition={() => hasRole("admin")}>
<button>The admin's button</button>
</If>
);
};
Link to the source code
import { FetchView } from 'react-declarative'
const PostList = () => {
const { getPosts } = useBlogApi();
const state = [
getPosts,
];
return (
<FetchView state={state} animation="fadeIn">
{(posts) => (
<div>
{posts.map((post, idx) => (
<p key={idx}>
<b>{post.title}</b>
{post.body}
</p>
))}
</div>
)}
</FetchView>
);
};
Link to the source code
import { Switch } from 'react-declarative';
...
const routes = [
{
path: '/mint-page',
guard: async () => await ioc.roleService.has('whitelist'),
prefetch: async () => await ioc.ethersService.init(),
unload: async () => await ioc.ethersService.dispose(),
redirect: () => {
let isOk = true;
isOk = isOk && ioc.ethersService.isMetamaskAvailable;
isOk = isOk && ioc.ethersService.isProviderConnected;
isOk = isOk && ioc.ethersService.isAccountEnabled;
if (isOk) {
return "/connect-page";
}
return null;
},
},
];
...
const App = () => (
<Switch history={history} items={routes} />
);
Link to the source code
import { Source } from 'react-declarative';
...
const verifyCompleteEmitter = Source.multicast(() =>
Source
.join([
captureStateEmitter,
Source.fromInterval(1_000),
])
.reduce((acm, [{ state: isValid }]) => {
if (isValid) {
return acm + 1;
}
return 0;
}, 0)
.tap((ticker) => {
if (ticker === 1) {
mediaRecorderInstance.beginCapture();
}
})
.filter((ticker) => ticker === CC_SECONDS_TO_VERIFY)
.tap(() => {
mediaRecorderInstance.endCapture();
})
);
Link to the source code
import { useCollection } from "react-declarative";
...
const collection = useCollection({
onChange: (collection, target) => console.log({
collection,
target,
}),
initialValue: [],
});
const handleAdd = async () => {
const { id, ...data } = await fetchApi("/api/v1/counters/create", {
method: "POST",
});
collection.push({
id,
...data,
});
};
const handleUpsert = async () => {
const updatedItems = await fetchApi("/api/v1/counters/list");
collection.upsert(updatedItems);
};
return (
<>
<button onClick={handleAdd}>Add item</button>
<button onClick={handleUpsert}>Upsert items</button>
<ul>
{collection.map((entity) => (
<ListItem key={entity.id} entity={entity} />
))}
</ul>
</>
);
import { ConstraintView } from 'react-declarative';
import { DragDropView } from 'react-declarative';
import { ScrollView } from 'react-declarative';
import { ScaleView } from 'react-declarative';
import { FadeView } from 'react-declarative';
import { TabsView } from 'react-declarative';
import { WaitView } from 'react-declarative';
import { PingView } from 'react-declarative';
import { OfflineView } from 'react-declarative';
import { RevealView } from 'react-declarative';
import { SecretView } from 'react-declarative';
import { PortalView } from 'react-declarative';
import { RecordView } from 'react-declarative';
import { CardView } from 'react-declarative';
import { ErrorView } from 'react-declarative';
import { AuthView } from 'react-declarative';
import { InfiniteView } from 'react-declarative';
import { VirtualView } from 'react-declarative';
- MVVM -
useCollection
,useModel
- DI -
provide
,inject
,createServiceManager
- Builder -
useListEditor
,useMediaStreamBuilder
- Observer -
useChangeSubject
,useSubject
,useRenderWaiter
,Subject
,BehaviorSubject
,EventEmitter
,fromPromise
- Command -
ActionTrigger
,ActionFilter
,ActionButton
,ActionToggle
,ActionMenu
,ActionIcon
,ActionModal
,InfiniteView
,VirtualView
,useActionModal
- Coroutine -
FetchView
,WaitView
,PingView
,Async
,If
,useAsyncAction
- Routing -
Switch
,OutletView
,getRouteParams
,getRouteItem
,useRouteParams
,useRouteItem
,createRouteItemManager
,createRouteParamsManager
- Monad -
singleshot
,cancelable
,queued
,cached
,debounce
,compose
,trycatch
,memoize
,ttl
,lock
- Composition -
VirtualView
,InfiniteView
,PortalView
,RevealView
,PingView
,WaitView
,FadeView
,ScaleView
,ScrollView
,ModalManager
- HoC -
ConstraintView
,AutoSizer
,FetchView
,Async
,If
- Facade -
Subject
,Observer
- Scheduled-task -
Task
,singlerun
- RAD -
RecordView
,CardView
- Functional -
useActualValue
,useActualCallback
,useActualState
,useSearchParams
,useSearchState
,useChange
- Declarative -
One
,List
,Scaffold
,Scaffold2
,RecordView
,CardView
- Reactive -
EventEmitter
,Subject
,BehaviorSubject
,Observer
- Lambda Architecture -
Source
,Operator
,useSource
,useSubscription
- Aspect Oriented -
serviceManager
,Source
- Reflection -
getAvailableFields
,VisibilityView
- Pagination -
useOffsetPaginator
,useCursorPaginator
- Feature model -
useFeatureView
,useVisibilityView
,FeatureView
,VisibilityView
- Software Fault Prevention -
ErrorBoundary
,ErrorView
-
React: declarative vs imperative
Declarative programming is when a more qualified specialist writing code in a way when its behavior can be changed by using external config which represent oriented graph of objects
-
Fractal pattern conveys that similar patterns recur progressively and the same thought process is applied to the structuring of codebase i.e All units repeat themselves.
-
SOLID principles described by simple words with examples in a source code
-
These principles will help you to keep the code as clean as possible when you need to make a MVP immediately
-
Oriented graphs: reduce algoritm difficulty
The real useful note for working with oriented graphs
-
Using underected data flow for building software product line
Useful snippets to split procedure code with the inversion of control pattern
P.S. Got a question? Feel free to write It in issues, I need traffic
LGPL 2.1 @tripolskypetr