From d724f15071fbdeeea84c804af190d31d1676187c Mon Sep 17 00:00:00 2001 From: erfanmoghadasi <97363934+erfanmoghadasi@users.noreply.github.com> Date: Mon, 11 Mar 2024 14:28:44 +0330 Subject: [PATCH] feat(form): actions (submit & base button) in form (#5) --- apps/docs/src/app/app.tsx | 108 +++++++++--------- package-lock.json | 96 ++++++++++++++-- package.json | 1 + .../components/actions/base/actionBase.tsx | 9 ++ .../actions/base/actionBase.types.ts | 6 + .../src/components/actions/submit/submit.tsx | 25 ++++ .../components/actions/submit/submit.types.ts | 4 + .../src/components/builder/builder.types.ts | 6 +- .../src/components/{ => fields}/text/text.tsx | 4 +- .../{ => fields}/text/text.types.ts | 2 +- .../components/form/src/types/public.types.ts | 9 +- .../form/src/utils/selector/selector.tsx | 20 +++- .../form/src/utils/selector/selector.types.ts | 8 +- .../src/lib/components/builder/builder.tsx | 9 +- .../core/src/lib/utils/selector/selector.tsx | 10 +- 15 files changed, 218 insertions(+), 99 deletions(-) create mode 100644 packages/components/form/src/components/actions/base/actionBase.tsx create mode 100644 packages/components/form/src/components/actions/base/actionBase.types.ts create mode 100644 packages/components/form/src/components/actions/submit/submit.tsx create mode 100644 packages/components/form/src/components/actions/submit/submit.types.ts rename packages/components/form/src/components/{ => fields}/text/text.tsx (90%) rename packages/components/form/src/components/{ => fields}/text/text.types.ts (63%) diff --git a/apps/docs/src/app/app.tsx b/apps/docs/src/app/app.tsx index 2c28e94..ddc1842 100644 --- a/apps/docs/src/app/app.tsx +++ b/apps/docs/src/app/app.tsx @@ -1,15 +1,58 @@ -import { Route, Routes, Link } from 'react-router-dom'; - -// import { Form } from '@mui-builder/form'; -import { Builder, GROUP_TYPE } from '@mui-builder/core'; -import { FIELD_TYPE } from 'packages/components/form/src/types/public.types'; +import { Link, Route, Routes } from 'react-router-dom'; +import { Builder, IFormTextBuilderProps } from '@mui-builder/core'; export function App() { + const groupList: IFormTextBuilderProps[] = [ + { + id: '1', + groupType: 'form', + type: 'field-text', + props: { + id: 'type-1', + formId: '20', + }, + }, + { + id: '2', + groupType: 'form', + type: 'field-text', + props: { + id: 'type-2', + formId: '20', + helperText: 'mmd', + }, + }, + { + id: '3', + groupType: 'form', + type: 'field-text', + props: { + id: 'type-2', + formId: '21', + helperText: 'mmd', + }, + }, + { + id: '4', + groupType: 'form', + type: 'action-submit', + props: { + formId: '21', + children: 'submit 21', + }, + }, + { + id: '4', + groupType: 'form', + type: 'action-submit', + props: { + formId: '20', + children: 'submit 20', + }, + }, + ]; return (
-
-
-
} /> - {/* } /> */} - - } - /> - - Click here to go back to root page. -
- } - /> + } /> - {/* END: routes */} ); } diff --git a/package-lock.json b/package-lock.json index 5a228e3..a7f5d23 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@changesets/cli": "^2.27.1", "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.0", + "@mui/lab": "^5.0.0-alpha.167", "@mui/material": "^5.15.11", "react": "18.2.0", "react-dom": "18.2.0", @@ -3870,6 +3871,77 @@ "url": "https://opencollective.com/mui-org" } }, + "node_modules/@mui/lab": { + "version": "5.0.0-alpha.167", + "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.167.tgz", + "integrity": "sha512-BNQJ7fBBvL68WGVnzAhbtTmabSuJDXaILr9dz/3RNK4TgGXPgWCAr7qtJeUdc4p1t7c4Z1ifG8UwgqD+5hzMNg==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/base": "5.0.0-beta.38", + "@mui/system": "^5.15.12", + "@mui/types": "^7.2.13", + "@mui/utils": "^5.15.12", + "clsx": "^2.1.0", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material": ">=5.15.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/lab/node_modules/@mui/base": { + "version": "5.0.0-beta.38", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.38.tgz", + "integrity": "sha512-AsjD6Y1X5A1qndxz8xCcR8LDqv31aiwlgWMPxFAX/kCKiIGKlK65yMeVZ62iQr/6LBz+9hSKLiD1i4TZdAHKcQ==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@floating-ui/react-dom": "^2.0.8", + "@mui/types": "^7.2.13", + "@mui/utils": "^5.15.12", + "@popperjs/core": "^2.11.8", + "clsx": "^2.1.0", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@mui/material": { "version": "5.15.11", "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.11.tgz", @@ -3915,12 +3987,12 @@ } }, "node_modules/@mui/private-theming": { - "version": "5.15.11", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.11.tgz", - "integrity": "sha512-jY/696SnSxSzO1u86Thym7ky5T9CgfidU3NFJjguldqK4f3Z5S97amZ6nffg8gTD0HBjY9scB+4ekqDEUmxZOA==", + "version": "5.15.12", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.12.tgz", + "integrity": "sha512-cqoSo9sgA5HE+8vZClbLrq9EkyOnYysooepi5eKaKvJ41lReT2c5wOZAeDDM1+xknrMDos+0mT2zr3sZmUiRRA==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/utils": "^5.15.11", + "@mui/utils": "^5.15.12", "prop-types": "^15.8.1" }, "engines": { @@ -3972,15 +4044,15 @@ } }, "node_modules/@mui/system": { - "version": "5.15.11", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.11.tgz", - "integrity": "sha512-9j35suLFq+MgJo5ktVSHPbkjDLRMBCV17NMBdEQurh6oWyGnLM4uhU4QGZZQ75o0vuhjJghOCA1jkO3+79wKsA==", + "version": "5.15.12", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.12.tgz", + "integrity": "sha512-/pq+GO6yN3X7r3hAwFTrzkAh7K1bTF5r8IzS79B9eyKJg7v6B/t4/zZYMR6OT9qEPtwf6rYN2Utg1e6Z7F1OgQ==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/private-theming": "^5.15.11", + "@mui/private-theming": "^5.15.12", "@mui/styled-engine": "^5.15.11", "@mui/types": "^7.2.13", - "@mui/utils": "^5.15.11", + "@mui/utils": "^5.15.12", "clsx": "^2.1.0", "csstype": "^3.1.3", "prop-types": "^15.8.1" @@ -4024,9 +4096,9 @@ } }, "node_modules/@mui/utils": { - "version": "5.15.11", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.11.tgz", - "integrity": "sha512-D6bwqprUa9Stf8ft0dcMqWyWDKEo7D+6pB1k8WajbqlYIRA8J8Kw9Ra7PSZKKePGBGWO+/xxrX1U8HpG/aXQCw==", + "version": "5.15.12", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.12.tgz", + "integrity": "sha512-8SDGCnO2DY9Yy+5bGzu00NZowSDtuyHP4H8gunhHGQoIlhlY2Z3w64wBzAOLpYw/ZhJNzksDTnS/i8qdJvxuow==", "dependencies": { "@babel/runtime": "^7.23.9", "@types/prop-types": "^15.7.11", diff --git a/package.json b/package.json index a8e038c..fc37f11 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "@changesets/cli": "^2.27.1", "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.0", + "@mui/lab": "^5.0.0-alpha.167", "@mui/material": "^5.15.11", "react": "18.2.0", "react-dom": "18.2.0", diff --git a/packages/components/form/src/components/actions/base/actionBase.tsx b/packages/components/form/src/components/actions/base/actionBase.tsx new file mode 100644 index 0000000..f673024 --- /dev/null +++ b/packages/components/form/src/components/actions/base/actionBase.tsx @@ -0,0 +1,9 @@ +import { LoadingButton } from '@mui/lab'; +import { FC } from 'react'; +import { ActionBaseProps } from './actionBase.types'; + +const ActionBase: FC = ({ children, ...actionBaseProps }) => { + return {children}; +}; + +export default ActionBase; diff --git a/packages/components/form/src/components/actions/base/actionBase.types.ts b/packages/components/form/src/components/actions/base/actionBase.types.ts new file mode 100644 index 0000000..f4e026f --- /dev/null +++ b/packages/components/form/src/components/actions/base/actionBase.types.ts @@ -0,0 +1,6 @@ +import { LoadingButtonProps } from '@mui/lab'; +import { ReactNode } from 'react'; + +export type ActionBaseProps = LoadingButtonProps & { + children: ReactNode; +}; diff --git a/packages/components/form/src/components/actions/submit/submit.tsx b/packages/components/form/src/components/actions/submit/submit.tsx new file mode 100644 index 0000000..f442153 --- /dev/null +++ b/packages/components/form/src/components/actions/submit/submit.tsx @@ -0,0 +1,25 @@ +import { Button } from '@mui/material'; +import { FC } from 'react'; +import { ActionSubmitFieldProps } from './submit.types'; +import useForms from '../../../hooks/useForms/useForms'; +import { FieldValues } from 'react-hook-form'; + +const ActionSubmit: FC = ({ + formId, + children, + ...submitFieldProps +}) => { + const forms = useForms((state) => state.forms); + const { handleSubmit } = forms[formId]; + const onSubmit = (values: FieldValues) => { + console.log(values); + }; + + return ( + + ); +}; + +export default ActionSubmit; diff --git a/packages/components/form/src/components/actions/submit/submit.types.ts b/packages/components/form/src/components/actions/submit/submit.types.ts new file mode 100644 index 0000000..7e4bf25 --- /dev/null +++ b/packages/components/form/src/components/actions/submit/submit.types.ts @@ -0,0 +1,4 @@ +import { FormId } from '../../../types/public.types'; +import { ActionBaseProps } from '../base/actionBase.types'; + +export type ActionSubmitFieldProps = ActionBaseProps & FormId; diff --git a/packages/components/form/src/components/builder/builder.types.ts b/packages/components/form/src/components/builder/builder.types.ts index c6d719a..36f3b4c 100644 --- a/packages/components/form/src/components/builder/builder.types.ts +++ b/packages/components/form/src/components/builder/builder.types.ts @@ -1,6 +1,6 @@ -import { FIELD_TYPE, FieldProps } from '../../types/public.types'; +import { FormTypes, FieldProps } from '../../types/public.types'; export interface BuilderProps { - fieldType: FIELD_TYPE; + fieldType: FormTypes; fieldProps: FieldProps; -} \ No newline at end of file +} diff --git a/packages/components/form/src/components/text/text.tsx b/packages/components/form/src/components/fields/text/text.tsx similarity index 90% rename from packages/components/form/src/components/text/text.tsx rename to packages/components/form/src/components/fields/text/text.tsx index 7647fa5..6844f2b 100644 --- a/packages/components/form/src/components/text/text.tsx +++ b/packages/components/form/src/components/fields/text/text.tsx @@ -2,7 +2,7 @@ import { TextField } from '@mui/material'; import { FC } from 'react'; import { useController } from 'react-hook-form'; import { TextProps } from './text.types'; -import useForms from '../../hooks/useForms/useForms'; +import useForms from '../../../hooks/useForms/useForms'; const Text: FC = ({ formId, ...textFieldProps }) => { const { forms } = useForms(); @@ -12,7 +12,7 @@ const Text: FC = ({ formId, ...textFieldProps }) => { control: formMethod.control, rules: { required: true }, }); - + return ; }; diff --git a/packages/components/form/src/components/text/text.types.ts b/packages/components/form/src/components/fields/text/text.types.ts similarity index 63% rename from packages/components/form/src/components/text/text.types.ts rename to packages/components/form/src/components/fields/text/text.types.ts index 701a407..07fbb67 100644 --- a/packages/components/form/src/components/text/text.types.ts +++ b/packages/components/form/src/components/fields/text/text.types.ts @@ -1,4 +1,4 @@ import { TextFieldProps } from "@mui/material"; -import { FormId, Id } from "../../types/public.types"; +import { FormId, Id } from "../../../types/public.types"; export type TextProps = TextFieldProps & Id & FormId; diff --git a/packages/components/form/src/types/public.types.ts b/packages/components/form/src/types/public.types.ts index 1948b98..93453cd 100644 --- a/packages/components/form/src/types/public.types.ts +++ b/packages/components/form/src/types/public.types.ts @@ -1,4 +1,5 @@ -import { TextProps } from "../components/text/text.types"; +import { ActionSubmitFieldProps } from "../components/actions/submit/submit.types"; +import { TextProps } from "../components/fields/text/text.types"; export type FormId = { formId: string }; @@ -6,8 +7,6 @@ export type Id = { id: string; }; -export enum FIELD_TYPE { - TEXT = 'text', -} +export type FormTypes = 'field-text' | "action-submit"; -export type FieldProps = TextProps; +export type FieldProps = TextProps | ActionSubmitFieldProps; diff --git a/packages/components/form/src/utils/selector/selector.tsx b/packages/components/form/src/utils/selector/selector.tsx index adaa86c..d84c162 100644 --- a/packages/components/form/src/utils/selector/selector.tsx +++ b/packages/components/form/src/utils/selector/selector.tsx @@ -1,13 +1,16 @@ import { FC, Fragment, Suspense, lazy } from 'react'; -import { TextProps } from '../../components/text/text.types'; import { SelectorProps } from './selector.types'; +import { TextProps } from '../../components/fields/text/text.types'; +import { ActionSubmitFieldProps } from '../../components/actions/submit/submit.types'; const Selector: FC = ({ fieldType, fieldProps }) => { let SelectedComponent; switch (fieldType) { - case 'text': - SelectedComponent = lazy(() => import('../../components/text/text')); + case 'field-text': + SelectedComponent = lazy( + () => import('../../components/fields/text/text') + ); return ( Loading...}> @@ -15,6 +18,17 @@ const Selector: FC = ({ fieldType, fieldProps }) => { ); + case 'action-submit': + SelectedComponent = lazy( + () => import('../../components/actions/submit/submit') + ); + + return ( + Loading...}> + + + ); + default: SelectedComponent = Fragment; diff --git a/packages/components/form/src/utils/selector/selector.types.ts b/packages/components/form/src/utils/selector/selector.types.ts index fe9b2a8..a1b5e30 100644 --- a/packages/components/form/src/utils/selector/selector.types.ts +++ b/packages/components/form/src/utils/selector/selector.types.ts @@ -1,6 +1,6 @@ -import { FIELD_TYPE, FieldProps } from "../../types/public.types"; +import { FormTypes, FieldProps } from '../../types/public.types'; export interface SelectorProps { - fieldType: FIELD_TYPE; - fieldProps: FieldProps; - } \ No newline at end of file + fieldType: FormTypes; + fieldProps: FieldProps; +} diff --git a/packages/core/src/lib/components/builder/builder.tsx b/packages/core/src/lib/components/builder/builder.tsx index 28d8769..1a0c9d5 100644 --- a/packages/core/src/lib/components/builder/builder.tsx +++ b/packages/core/src/lib/components/builder/builder.tsx @@ -1,14 +1,11 @@ import React from 'react'; import Selector from '../../utils/selector/selector'; import { - FIELD_TYPE, + FormTypes, FieldProps, } from 'packages/components/form/src/types/public.types'; -export enum GROUP_TYPE { - FORM = 'form', - SECTION = 'section', -} +export type GROUP_TYPE = 'form'; export enum SECTION_TYPE { CARD = 'card', @@ -17,7 +14,7 @@ export enum SECTION_TYPE { export interface IFormTextBuilderProps { id: string; groupType: GROUP_TYPE; - type: FIELD_TYPE; + type: FormTypes; props: FieldProps; } diff --git a/packages/core/src/lib/utils/selector/selector.tsx b/packages/core/src/lib/utils/selector/selector.tsx index ede3e67..4ede482 100644 --- a/packages/core/src/lib/utils/selector/selector.tsx +++ b/packages/core/src/lib/utils/selector/selector.tsx @@ -1,21 +1,17 @@ import { FC, Fragment, Suspense, lazy } from 'react'; import { GROUP_TYPE } from '../../components/builder/builder'; import { - FIELD_TYPE, + FormTypes, FieldProps, } from 'packages/components/form/src/types/public.types'; export interface SelectorProps { groupType: GROUP_TYPE; - fieldType: FIELD_TYPE; + fieldType: FormTypes; fieldProps: FieldProps; } -const Selector: FC = ({ - groupType, - fieldType, - fieldProps, -}) => { +const Selector: FC = ({ groupType, fieldType, fieldProps }) => { let SelectedComponent; switch (groupType) {