Skip to content

Commit

Permalink
Merge pull request #591 from sebgroup/develop
Browse files Browse the repository at this point in the history
release dynamic form item wrapping element to beta
  • Loading branch information
mario-subo authored Apr 27, 2021
2 parents 60203b8 + 15e6e33 commit 7ad8f1e
Show file tree
Hide file tree
Showing 11 changed files with 333 additions and 28 deletions.
4 changes: 2 additions & 2 deletions docs/src/pages/docs/checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const CheckboxPage: React.FC = (): React.ReactElement<void> => {
options: indicators,
controlType: "Radio",
value: indicators[0].value,
additionalProps: { className: "indent pl-3 pt-2" },
formElementAdditionalProps: { className: "indent pl-3 pt-2" },
},
{
key: "indicatorGrouping",
Expand All @@ -48,7 +48,7 @@ const CheckboxPage: React.FC = (): React.ReactElement<void> => {
condition: true,
options: indicatorGrouping,
value: indicatorGrouping[0].value,
additionalProps: { className: "indent pl-3 pt-2" },
formElementAdditionalProps: { className: "indent pl-3 pt-2" },
},
],
},
Expand Down
1 change: 1 addition & 0 deletions docs/src/pages/docs/datepicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const DatepickerPage: React.FC = () => {
label: "Locale code:",
description: "Set a locale for the custom picker (defaults to system locale).",
controlType: "Text",
wrappingElement: "div",
additionalProps: { className: "indent pl-3 pt-2" },
},
],
Expand Down
290 changes: 288 additions & 2 deletions docs/src/pages/docs/dynamic-forms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";
import { Helmet } from "react-helmet";
import Layout from "@common/Layout";
import { CodeSnippet } from "@common/CodeSnippet";
import { useDynamicForm, DynamicFormSection } from "@sebgroup/react-components/hooks";
import { useDynamicForm, DynamicFormSection, DynamicFormItem, DynamicFormOption } from "@sebgroup/react-components/hooks";
import { Table, TableBody, TableCell, TableHeader, TableHeaderCell, TableRow } from "@sebgroup/react-components/Table";
import { Button } from "@sebgroup/react-components/Button";
import { isEmpty } from "@sebgroup/frontend-tools";
Expand Down Expand Up @@ -131,6 +131,7 @@ export default ComponentConditionalRender;
<CodeSnippet language="javascript">
{`
import { useDynamicForm } from "@sebgroup/react-components/hooks/useDynamicForm";
import { isEmpty } from "@sebgroup/frontend-tools";
const FormWithErrors: React.FC = () => {
const sections: DynamicFormSection[] = [
Expand Down Expand Up @@ -187,6 +188,147 @@ export default FormWithErrors;

<hr />

<h2 className="pt-3 pb-3">Full example</h2>
<p>A complete example of every form element with label, description and optional error message. All form elements use responsive layout.</p>
<CodeSnippet language="javascript">
{`
import { useDynamicForm, DynamicFormSection, DynamicFormItem, DynamicFormOption } from "@sebgroup/react-components/hooks";
const ShowMeEverything: React.FC = () => {
const COMMON_ITEM: Partial<DynamicFormItem> = {
wrappingElement: "div",
additionalProps: {
className: "col-12 col-sm-6 col-md-4 mb-2",
},
};
const valueItems: DynamicFormItem[] = (["Text", "Textarea", "Datepicker", "Stepper", "Checkbox"] as DynamicFormItem["controlType"][]).map(
(controlType: DynamicFormItem["controlType"], i: number) => {
return {
key: controlType,
label: \`\${controlType} label\`,
description: \`\${controlType} description\`,
order: i,
controlType,
...COMMON_ITEM,
};
}
);
const options: DynamicFormOption[] = [
{ key: "one", label: "One", value: "1" },
{ key: "two", label: "Two", value: "2" },
{ key: "three", label: "Three", value: "3" },
];
const multiSingleItems: DynamicFormItem[] = (["Radio", "Dropdown"] as DynamicFormItem["controlType"][]).map((controlType: DynamicFormItem["controlType"], i: number) => {
return {
key: controlType,
label: \`\${controlType} label\`,
description: \`\${controlType} description\`,
multi: false,
order: i,
options: [
...options.map((e) => {
return { ...e, key: \`\${e.key}-multi-single\` };
}),
],
controlType,
...COMMON_ITEM,
};
});
const multiManyItems: DynamicFormItem[] = (["Dropdown", "Option"] as DynamicFormItem["controlType"][]).map((controlType: DynamicFormItem["controlType"], i: number) => {
return {
key: controlType,
label: \`\${controlType} label\`,
description: \`\${controlType} description\`,
multi: true,
order: i,
options: [
...options.map((e) => {
return { ...e, key: \`\${e.key}-multi-many\` };
}),
],
controlType,
...COMMON_ITEM,
};
});
const COMMON_SECTION: Partial<DynamicFormItem> = {
wrappingElement: "section",
additionalProps: {
className: "row d-flex flex-wrap mb-2",
},
};
const sections: DynamicFormSection[] = [
{
key: "value-items-section",
title: "Simple single values only",
items: valueItems,
...COMMON_SECTION,
},
{
key: "multi-single-items-section",
title: "Choose one of many options",
items: multiSingleItems,
...COMMON_SECTION,
},
{
key: "multi-many-items-section",
title: "Choose any of multiple options",
items: multiManyItems,
...COMMON_SECTION,
},
];
const [renderForm, state,, setErrors] = useDynamicForm(sections);
const validate = () => {
setErrors({
"value-items-section": {
Text: "Text error message",
Textarea: "Textarea error message",
Checkbox: "Checkbox error message",
Datepicker: "Datepicker error message",
Stepper: "Stepper error message",
},
"multi-single-items-section": {
Radio: "Radio error message",
Dropdown: "Dropdown error message",
},
"multi-many-items-section": {
Dropdown: "Dropdown error message",
Option: "Option error message",
},
});
};
return (
<>
<div>{renderForm()}</div>
<div>
<Button onClick={validate}>
Show errors
</Button>
<Button className="ml-3" onClick={() => alert(JSON.stringify(state, null, 4))}>
Show current values
</Button>
</div>
</>
);
};
export default ShowMeEverything;
`}
</CodeSnippet>
<div className="p-3 rounded bg-white">
<ShowMeEverything />
</div>

<hr />

<h2 className="pt-3 pb-3">Dynamic forms API</h2>
<h3 className="pt-3 pb-3">
<code>DynamicFormSection</code>
Expand Down Expand Up @@ -459,6 +601,26 @@ export default FormWithErrors;
Any additional element props to be mapped to the element. Depends on the <b>controlType</b>. Must be a valid prop for that element.
</TableCell>
</TableRow>
<TableRow>
<TableCell>
<b>wrappingElement</b>
</TableCell>
<TableCell>&#10004;</TableCell>
<TableCell>
<code>{`"div" | "section" | "none"`}</code>
</TableCell>
<TableCell>The wrapping element (if any) for the form item. It wraps the label, element, error message and description in the chosen element. Defaut: "none"'.</TableCell>
</TableRow>
<TableRow>
<TableCell>
<b>additionalProps</b>
</TableCell>
<TableCell>&#10004;</TableCell>
<TableCell>
<code>{`{ [k: string]: any; }`}</code>
</TableCell>
<TableCell>Any additional element props to be mapped to the wrappingElement (if one is enabled).</TableCell>
</TableRow>
</TableBody>
</Table>

Expand Down Expand Up @@ -519,7 +681,7 @@ export default FormWithErrors;
</TableRow>
<TableRow>
<TableCell>
<b>additionalProps</b>
<b>formElementAdditionalProps</b>
</TableCell>
<TableCell>&#10004;</TableCell>
<TableCell>
Expand Down Expand Up @@ -650,3 +812,127 @@ const FormWithErrors: React.FC = () => {
</>
);
};

const ShowMeEverything: React.FC = () => {
const COMMON_ITEM: Partial<DynamicFormItem> = {
wrappingElement: "div",
additionalProps: {
className: "col-12 col-sm-6 col-md-4 mb-2",
},
};

const valueItems: DynamicFormItem[] = (["Text", "Textarea", "Datepicker", "Stepper", "Checkbox"] as DynamicFormItem["controlType"][]).map(
(controlType: DynamicFormItem["controlType"], i: number) => {
return {
key: controlType,
label: `${controlType} label`,
description: `${controlType} description`,
order: i,
controlType,
...COMMON_ITEM,
};
}
);

const options: DynamicFormOption[] = [
{ key: "one", label: "One", value: "1" },
{ key: "two", label: "Two", value: "2" },
{ key: "three", label: "Three", value: "3" },
];

const multiSingleItems: DynamicFormItem[] = (["Radio", "Dropdown"] as DynamicFormItem["controlType"][]).map((controlType: DynamicFormItem["controlType"], i: number) => {
return {
key: controlType,
label: `${controlType} label`,
description: `${controlType} description`,
multi: false,
order: i,
options: [
...options.map((e) => {
return { ...e, key: `${e.key}-multi-single` };
}),
],
controlType,
...COMMON_ITEM,
};
});

const multiManyItems: DynamicFormItem[] = (["Dropdown", "Option"] as DynamicFormItem["controlType"][]).map((controlType: DynamicFormItem["controlType"], i: number) => {
return {
key: controlType,
label: `${controlType} label`,
description: `${controlType} description`,
multi: true,
order: i,
options: [
...options.map((e) => {
return { ...e, key: `${e.key}-multi-many` };
}),
],
controlType,
...COMMON_ITEM,
};
});

const COMMON_SECTION: Partial<DynamicFormItem> = {
wrappingElement: "section",
additionalProps: {
className: "row d-flex flex-wrap mb-2",
},
};

const sections: DynamicFormSection[] = [
{
key: "value-items-section",
title: "Simple single values only",
items: valueItems,
...COMMON_SECTION,
},
{
key: "multi-single-items-section",
title: "Choose one of many options",
items: multiSingleItems,
...COMMON_SECTION,
},
{
key: "multi-many-items-section",
title: "Choose any of multiple options",
items: multiManyItems,
...COMMON_SECTION,
},
];

const [renderForm, state, , setErrors] = useDynamicForm(sections);

const validate = () => {
setErrors({
"value-items-section": {
Text: "Text error message",
Textarea: "Textarea error message",
Checkbox: "Checkbox error message",
Datepicker: "Datepicker error message",
Stepper: "Stepper error message",
},
"multi-single-items-section": {
Radio: "Radio error message",
Dropdown: "Dropdown error message",
},
"multi-many-items-section": {
Dropdown: "Dropdown error message",
Option: "Option error message",
},
});
};

return (
<>
<div>{renderForm()}</div>
<div>
<Button onClick={validate}>Show errors</Button>
<Button className="ml-3" onClick={() => alert(JSON.stringify(state, null, 4))}>
Show current values
</Button>
</div>
</>
);
};
8 changes: 4 additions & 4 deletions docs/src/pages/docs/image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,17 @@ const ImagePage: React.FC = (): React.ReactElement<void> => {
key: "bgFixed",
label: "bgFixed",
rulerKey: "imgType",
additionalProps: { className: "indent pl-3 pt-2" },
condition: imgTypes[1],
formElementAdditionalProps: { className: "indent pl-3 pt-2" },
condition: imgTypes[1].value,
description: "Fixing the background allows it to have parallax effect when scrolling. Only available for div image type.",
controlType: "Checkbox",
},
{
key: "showChildren",
label: "Render children inside div image",
rulerKey: "imgType",
additionalProps: { className: "indent pl-3 pt-2" },
condition: imgTypes[1],
formElementAdditionalProps: { className: "indent pl-3 pt-2" },
condition: imgTypes[1].value,
description: "One advantage of a div image is that you can render children inside the image",
controlType: "Checkbox",
},
Expand Down
4 changes: 2 additions & 2 deletions docs/src/pages/docs/slider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const SliderPage: React.FC = (): React.ReactElement<void> => {
condition: true,
options: indicators,
value: indicators[0].value,
additionalProps: { className: "indent pl-3 pt-2" },
formElementAdditionalProps: { className: "indent pl-3 pt-2" },
},
{ key: "labels", label: "labels", controlType: "Checkbox", value: false, description: "Pass a list of positions and labels to be mapped" },
{
Expand All @@ -56,7 +56,7 @@ const SliderPage: React.FC = (): React.ReactElement<void> => {
description: "Show ticks for the lables",
rulerKey: "labels",
condition: true,
additionalProps: { className: "indent pl-3 pt-2" },
formElementAdditionalProps: { className: "indent pl-3 pt-2" },
},
],
},
Expand Down
Loading

0 comments on commit 7ad8f1e

Please sign in to comment.