From 500275cd186f45d082a2630012e51305222c6b0e Mon Sep 17 00:00:00 2001 From: Heather Pfeiffer Date: Mon, 22 Apr 2024 19:29:06 -0400 Subject: [PATCH 1/7] =?UTF-8?q?MUITypes=20added=20>=20>=20Co-author-by:=20?= =?UTF-8?q?Zack=20Vandiver=20=20Co-author-by:=20Au?= =?UTF-8?q?stin=20Alvarez=20=20Co-author-by?= =?UTF-8?q?:=20Heather=20Pfeiffer=20=20Co-author-by:=20Jesse?= =?UTF-8?q?=20Wowczuk=20=20Co-author-by:=20Sean=20?= =?UTF-8?q?Ryan=20=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/redux/MUITypes.ts | 123 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 app/src/redux/MUITypes.ts diff --git a/app/src/redux/MUITypes.ts b/app/src/redux/MUITypes.ts new file mode 100644 index 00000000..22894d49 --- /dev/null +++ b/app/src/redux/MUITypes.ts @@ -0,0 +1,123 @@ +import { TextFieldProps as MuiTextFieldProps } from '@mui/material/TextField'; +import { ButtonProps as MuiButtonProps } from '@mui/material/Button'; +import { CardProps as MuiCardProps } from '@mui/material/Card'; +import { TypographyProps as MuiTypographyProps } from '@mui/material/Typography'; +import { MUIType } from '../interfaces/Interfaces'; +import { TroubleshootSharp } from '@mui/icons-material'; + +interface ButtonSchema { + id: number; + tag: string; + name: string; + style: React.CSSProperties; + placeHolderShort: string; + placeHolderLong: string; + icon: string; + framework: string; + nestable: boolean; + props: MuiButtonProps; + } +interface InputSchema { + id: number; + tag: string; + name: string; + style: React.CSSProperties; + placeHolderShort: string; + placeHolderLong: string; + icon: string; + framework: string; + nestable: boolean; + props: MuiTextFieldProps; + } +interface CardSchema { + id: number; + tag: string; + name: string; + style: React.CSSProperties; + placeHolderShort: string; + placeHolderLong: string; + icon: string; + framework: string; + nestable: boolean; + props: MuiCardProps; + } +interface TypographySchema { + id: number; + tag: string; + name: string; + style: React.CSSProperties; + placeHolderShort: string; + placeHolderLong: string; + icon: string; + framework: string; + nestable: boolean; + props: MuiTypographyProps; + } + +const MUITypes: MUIType[] = [ + { + id: 11, + tag: 'button', + name: 'Material UI Button', + style: {}, + placeHolderShort: 'button', + placeHolderLong: 'Material UI Button Component', + icon: 'Code', + framework: 'reactClassic', + nestable: true, + props: { + variant: 'contained', + color: 'primary', + disabled: false, + // Add other MUI ButtonProps as needed + }, + }, + { + id: 21, + tag: 'input', + name: 'Material UI TextField', + style: {}, + placeHolderShort: 'input', + placeHolderLong: 'Material UI TextField Component', + icon: 'TextFields', + framework: 'reactClassic', + nestable: true, + props: { + variant: 'outlined', + fullWidth: true, + // Add other MUI TextFieldProps as needed + }, + }, + { + id: 31, + tag: 'card', + name: 'Material UI Card', + style: {}, + placeHolderShort: 'card', + placeHolderLong: 'Material UI Card Component', + icon: 'CardTravel', + framework: 'reactClassic', + nestable: true, + props: { + variant: 'outlined', + // Add other MUI CardProps as needed + }, + }, + { + id: 41, + tag: 'typography', + name: 'Material UI Typography', + style: {}, + placeHolderShort: 'typography', + placeHolderLong: 'Material UI Typography Component', + icon: 'TextFormat', + framework: 'reactClassic', + nestable: true, + props: { + variant: 'h6', + // Add other MUI TypographyProps as needed + }, + } +]; + +export default MUITypes; \ No newline at end of file From a6d96108f5b546ea3f6fdd5d96875fc5c6e13745 Mon Sep 17 00:00:00 2001 From: Heather Pfeiffer Date: Mon, 22 Apr 2024 22:18:35 -0400 Subject: [PATCH 2/7] added MUITypes Props and added props to interface --- app/src/interfaces/Interfaces.ts | 1 + app/src/redux/MUITypes.ts | 146 +++++++++++++++---------------- 2 files changed, 72 insertions(+), 75 deletions(-) diff --git a/app/src/interfaces/Interfaces.ts b/app/src/interfaces/Interfaces.ts index 5e49e324..d8008442 100644 --- a/app/src/interfaces/Interfaces.ts +++ b/app/src/interfaces/Interfaces.ts @@ -114,6 +114,7 @@ export interface MUIType { framework: string; nestable: boolean; imports: any[]; + props: any[]; } export interface DragItem extends DragObjectWithType { newInstance: boolean; diff --git a/app/src/redux/MUITypes.ts b/app/src/redux/MUITypes.ts index 22894d49..4c57fca6 100644 --- a/app/src/redux/MUITypes.ts +++ b/app/src/redux/MUITypes.ts @@ -1,59 +1,6 @@ -import { TextFieldProps as MuiTextFieldProps } from '@mui/material/TextField'; -import { ButtonProps as MuiButtonProps } from '@mui/material/Button'; -import { CardProps as MuiCardProps } from '@mui/material/Card'; -import { TypographyProps as MuiTypographyProps } from '@mui/material/Typography'; import { MUIType } from '../interfaces/Interfaces'; import { TroubleshootSharp } from '@mui/icons-material'; -interface ButtonSchema { - id: number; - tag: string; - name: string; - style: React.CSSProperties; - placeHolderShort: string; - placeHolderLong: string; - icon: string; - framework: string; - nestable: boolean; - props: MuiButtonProps; - } -interface InputSchema { - id: number; - tag: string; - name: string; - style: React.CSSProperties; - placeHolderShort: string; - placeHolderLong: string; - icon: string; - framework: string; - nestable: boolean; - props: MuiTextFieldProps; - } -interface CardSchema { - id: number; - tag: string; - name: string; - style: React.CSSProperties; - placeHolderShort: string; - placeHolderLong: string; - icon: string; - framework: string; - nestable: boolean; - props: MuiCardProps; - } -interface TypographySchema { - id: number; - tag: string; - name: string; - style: React.CSSProperties; - placeHolderShort: string; - placeHolderLong: string; - icon: string; - framework: string; - nestable: boolean; - props: MuiTypographyProps; - } - const MUITypes: MUIType[] = [ { id: 11, @@ -62,15 +9,27 @@ const MUITypes: MUIType[] = [ style: {}, placeHolderShort: 'button', placeHolderLong: 'Material UI Button Component', - icon: 'Code', + icon: 'EditAttributes', framework: 'reactClassic', nestable: true, - props: { - variant: 'contained', - color: 'primary', - disabled: false, - // Add other MUI ButtonProps as needed - }, + imports: ["import Button from '@mui/material/Button'"], + props: [ + 'children', + 'classes', + 'color', + 'component', + 'disabled', + 'disableElevation', + 'disableFocusRipple', + 'disableRipple', + 'endIcon', + 'fullWidth', + 'href', + 'size', + 'startIcon', + 'sx', + 'variant' + ] }, { id: 21, @@ -79,14 +38,44 @@ const MUITypes: MUIType[] = [ style: {}, placeHolderShort: 'input', placeHolderLong: 'Material UI TextField Component', - icon: 'TextFields', + icon: 'Input', framework: 'reactClassic', nestable: true, - props: { - variant: 'outlined', - fullWidth: true, - // Add other MUI TextFieldProps as needed - }, + imports: ["import Box from '@mui/material/Box'", "import TextField from '@mui/material/TextField'"], + props: [ + 'autoComplete', + 'autoFocus', + 'classes', + 'color', + 'defaultValue', + 'disabled', + 'error', + 'FormHelperTextProps', + 'fullWidth', + 'helperText', + 'id', + 'InputLabelProps', + 'inputProps', + 'InputProps', + 'inputRef', + 'label', + 'margin', + 'maxRows', + 'minRows', + 'multiline', + 'name', + 'onChange', + 'placeholder', + 'required', + 'rows', + 'select', + 'SelectProps', + 'size', + 'sx', + 'type', + 'value', + 'variant' + ] }, { id: 31, @@ -98,10 +87,8 @@ const MUITypes: MUIType[] = [ icon: 'CardTravel', framework: 'reactClassic', nestable: true, - props: { - variant: 'outlined', - // Add other MUI CardProps as needed - }, + imports: ["import Box from '@mui/material/Box'", "import Card from '@mui/material/Card'", "import CardActions from '@mui/material/CardActions'", "import CardContent from '@mui/material/CardContent'", "import Button from '@mui/material/Button'", "import Typography from '@mui/material/Typography'"], + props: ['children','classes','raised','sx'] }, { id: 41, @@ -110,13 +97,22 @@ const MUITypes: MUIType[] = [ style: {}, placeHolderShort: 'typography', placeHolderLong: 'Material UI Typography Component', - icon: 'TextFormat', + icon: 'TextFields', framework: 'reactClassic', nestable: true, - props: { - variant: 'h6', - // Add other MUI TypographyProps as needed - }, + imports: ["import Box from '@mui/material/Box'", "import Typography from '@mui/material/Typography'"], + props: [ + 'align', + 'children', + 'classes', + 'component', + 'gutterBottom', + 'noWrap', + 'paragraph', + 'sx', + 'variant', + 'variantMapping' + ] } ]; From 3bf7ddbf8bcf7d863d9bff2e8583467737da956e Mon Sep 17 00:00:00 2001 From: Jesse Wowczuk Date: Mon, 22 Apr 2024 19:29:20 -0700 Subject: [PATCH 3/7] Jesse 4/22, reworked the DragDropPanel to add arrodions for Root Components, HTML Components, MUI Components and React Reouter. also restyled the App icon. relocate the Root Components on the top of HTML Components. > > Co-author-by: Heather Pfeiffer Co-author-by: Jesse Wowczuk Co-author-by: Zack Vandiver Co-author-by: Sean Ryan Co-author-by: Austin Alvarez --- app/src/components/left/ComponentDrag.tsx | 50 +++-- .../components/left/ComponentsContainer.tsx | 2 +- app/src/components/left/DragDropPanel.tsx | 202 +++++++++++------- app/src/components/left/ElementsContainer.tsx | 5 +- app/src/components/left/HTMLItem.tsx | 2 +- .../components/right/ComponentPanelItem.tsx | 49 +++-- package-lock.json | 192 +++++++++++++++++ package.json | 1 + 8 files changed, 387 insertions(+), 116 deletions(-) diff --git a/app/src/components/left/ComponentDrag.tsx b/app/src/components/left/ComponentDrag.tsx index b3048fa4..0f370e60 100644 --- a/app/src/components/left/ComponentDrag.tsx +++ b/app/src/components/left/ComponentDrag.tsx @@ -1,11 +1,31 @@ -import ComponentPanelItem from '../right/ComponentPanelItem'; -import Grid from '@mui/material/Grid'; import React from 'react'; +import Grid from '@mui/material/Grid'; import { RootState } from '../../redux/store'; import makeStyles from '@mui/styles/makeStyles'; import { useSelector } from 'react-redux'; +import ComponentPanelItem from '../right/ComponentPanelItem'; + -const ComponentDrag = ({ isThemeLight }): JSX.Element => { +const useStyles = makeStyles({ + panelWrapper: { + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + flexGrow: 1, + overflow: 'auto' + }, + panelWrapperList: { + minHeight: 'auto' + }, + lightThemeFontColor: { + color: '#fff' + }, + darkThemeFontColor: { + color: '#fff' + } +}); + +const ComponentDrag = ({ isVisible, isThemeLight }): JSX.Element | null => { const classes = useStyles(); const state = useSelector((store: RootState) => store.appState); @@ -13,13 +33,15 @@ const ComponentDrag = ({ isThemeLight }): JSX.Element => { return state.canvasFocus.componentId === targetId ? true : false; }; + if (!isVisible) return null; + return (

{state.projectType === 'Next.js' || state.projectType === 'Gatsby.js' ? 'Pages' - : 'Root Components'} + : ''}

{ ); }; -const useStyles = makeStyles({ - panelWrapper: { - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - flexGrow: 1, - overflow: 'auto' - }, - panelWrapperList: { - minHeight: '120px' - }, - lightThemeFontColor: { - color: '#fff' - }, - darkThemeFontColor: { - color: '#fff' - } -}); - export default ComponentDrag; + diff --git a/app/src/components/left/ComponentsContainer.tsx b/app/src/components/left/ComponentsContainer.tsx index 217aad4b..d4e3c5fd 100644 --- a/app/src/components/left/ComponentsContainer.tsx +++ b/app/src/components/left/ComponentsContainer.tsx @@ -48,7 +48,7 @@ const useStyles = makeStyles({ overflow: 'auto' }, panelWrapperList: { - minHeight: '120px' + minHeight: 'auto' }, lightThemeFontColor: { color: '#fff' diff --git a/app/src/components/left/DragDropPanel.tsx b/app/src/components/left/DragDropPanel.tsx index 33f371c7..256e14fd 100644 --- a/app/src/components/left/DragDropPanel.tsx +++ b/app/src/components/left/DragDropPanel.tsx @@ -5,32 +5,36 @@ import React from 'react'; import { RootState } from '../../redux/store'; import { deleteElement } from '../../redux/reducers/slice/appStateSlice'; import { emitEvent } from '../../helperFunctions/socket'; +import Accordion from '@mui/material/Accordion'; +import AccordionSummary from '@mui/material/AccordionSummary'; +import AccordionDetails from '@mui/material/AccordionDetails'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import { makeStyles } from '@mui/styles'; +import ComponentDrag from './ComponentDrag'; -/* -DESCRIPTION: This is the top half of the left panel, starting from the 'HTML - Elements' header. The boxes containing each HTML element are rendered in - HTMLItem, which itself is rendered by this component. -Central state contains all available HTML elements (stored in the HTMLTypes property). - The data for HTMLTypes is stored in HTMLTypes.tsx and is added to central state in - initialState.tsx. +const useStyles = makeStyles({ + accordion: { + backgroundColor: '#000000', // Set the background color to gray + color: '#ffffff', // Set the text color to white + }, + accordionSummary: { + backgroundColor: '#000000', // Set the background color of the summary to gray + color: '#ffffff', // Set the text color of the summary to white + }, +}); -Hook state: - -tag: -*/ -// Extracted the drag and drop functionality from HTMLPanel to make a modular component that can hang wherever the future designers may choose. const DragDropPanel = (props): JSX.Element => { + const classes = useStyles(); const dispatch = useDispatch(); - const state = useSelector((store: RootState) => store.appState); // current state - const contextParam = useSelector((store: RootState) => store.contextSlice); // current contextParam - const roomCode = useSelector((store: RootState) => store.roomSlice.roomCode); // current roomCode + const state = useSelector((store: RootState) => store.appState); + const contextParam = useSelector((store: RootState) => store.contextSlice); + const roomCode = useSelector((store: RootState) => store.roomSlice.roomCode); - // function for delete element const handleDelete = (id: number): void => { dispatch(deleteElement({ id: id, contextParam: contextParam })); if (roomCode) { - // send delete element to server to broadcast to all users emitEvent('deleteElementAction', roomCode, { id, contextParam @@ -38,68 +42,121 @@ const DragDropPanel = (props): JSX.Element => { } }; - // filter out separator so that it will not appear on the html panel const htmlTypesToRender = state.HTMLTypes.filter( (type) => type.name !== 'separator' ); + return (
-

HTML Elements

- - {htmlTypesToRender.map((option) => { - if ( - !['Switch', 'LinkTo', 'LinkHref', 'Image', 'Route'].includes( - option.name - ) - ) { - return ( - - ); - } - })} - - - {state.projectType === 'Classic React' ? ( -

React Router

- ) : null} - - {htmlTypesToRender.map((option) => { - if ( - (option.name === 'Switch' || - option.name === 'LinkTo' || - option.name === 'Route') && - state.projectType === 'Classic React' - ) { - return ( - - ); - } - })} - - + + } + aria-controls="panel1a-content" + id="panel1a-header" + className={classes.accordionSummary} + > +

Root Components

+
+ + + +
+ + } + aria-controls="panel1a-content" + id="panel1a-header" + className={classes.accordionSummary} + > +

HTML Elements

+
+ + + {htmlTypesToRender.map((option) => { + if ( + !['Switch', 'LinkTo', 'LinkHref', 'Image', 'Route'].includes( + option.name + ) + ) { + return ( + + ); + } + })} + + +
+ + {/* MUI Components */} + + } + aria-controls="panel2a-content" + id="panel2a-header" + className={classes.accordionSummary} + > +

MUI Components

+
+ + + {htmlTypesToRender.map((option) => { + if (option.name === 'MUI') { + return ( + + ); + } + })} + + +
+ + {/* React Router */} + + } + aria-controls="panel1a-content" + id="panel1a-header" + className={classes.accordionSummary} + > +

React Router

+
+ + + {htmlTypesToRender.map((option) => { + if ( + (option.name === 'Switch' || + option.name === 'LinkTo' || + option.name === 'Route') && + state.projectType === 'Classic React' + ) { + return ( + + ); + } + })} + + +
+ {/* Next.js */} {state.projectType === 'Next.js' ? (

Next.js

@@ -126,3 +183,4 @@ const DragDropPanel = (props): JSX.Element => { }; export default DragDropPanel; + diff --git a/app/src/components/left/ElementsContainer.tsx b/app/src/components/left/ElementsContainer.tsx index bff6d195..b1fb2a43 100644 --- a/app/src/components/left/ElementsContainer.tsx +++ b/app/src/components/left/ElementsContainer.tsx @@ -55,9 +55,10 @@ const ElementsContainer = (props): JSX.Element => { > {' '} -
+ { // moved ComponentDrag to DragDropPanel + /*
-
+
*/} ); }; diff --git a/app/src/components/left/HTMLItem.tsx b/app/src/components/left/HTMLItem.tsx index d5948a5c..028ab8cd 100644 --- a/app/src/components/left/HTMLItem.tsx +++ b/app/src/components/left/HTMLItem.tsx @@ -17,7 +17,7 @@ const useStyles = makeStyles({ HTMLPanelItem: { height: 'auto', width: 'auto', - fontSize: 'medium', + fontSize: 'small', display: 'flex', flexDirection: 'row', justifyContent: 'space-evenly', diff --git a/app/src/components/right/ComponentPanelItem.tsx b/app/src/components/right/ComponentPanelItem.tsx index 7248c791..a6fc640e 100644 --- a/app/src/components/right/ComponentPanelItem.tsx +++ b/app/src/components/right/ComponentPanelItem.tsx @@ -7,6 +7,7 @@ import { useDispatch, useSelector } from 'react-redux'; import { changeFocus } from '../../redux/reducers/slice/appStateSlice'; import { RootState } from '../../redux/store'; import { emitEvent } from '../../helperFunctions/socket'; +import * as Icons from '@mui/icons-material'; /* DESCRIPTION: This component is each box beneath the 'HTML Elements' and 'reusable components' (in classic React mode) headings. Drag-and-drop @@ -23,11 +24,13 @@ const ComponentPanelItem: React.FC<{ isFocus: boolean; isThemeLight: boolean; }> = ({ name, id, root, isFocus, isThemeLight }) => { - const classes = useStyles(); + const classes = useStyles({}); const state = useSelector((store: RootState) => store.appState); const roomCode = useSelector((store: RootState) => store.roomSlice.roomCode); const dispatch = useDispatch(); + const IconComponent = Icons[name]; // Use the correct icon component based on the name + // useDrag hook allows components in left panel to be drag source const [{ isDragging }, drag] = useDrag({ item: { @@ -61,36 +64,47 @@ const ComponentPanelItem: React.FC<{ ref={drag} xs={8} style={{ - color: 'white', - backgroundColor: 'transparent', + fontSize: 'small', + backgroundColor: '#2D313A', // Set background color border: '2px solid', - borderRadius: '4px', - borderColor: '#0671e3', + borderRadius: '10px', + borderColor: '#2D313A', margin: '5px 0px', - wordBreak: 'break-all', - width: '10rem' + width: '10rem', + height: '3rem', + position: 'relative', }} > {isFocus &&
}
- {/* render element's name on the left panel*/} -

{name}

+
+ {IconComponent && } +

+ {name} +

+
); }; const useStyles = makeStyles({ - activeFocus: { - backgroundColor: 'rgba (0, 0, 0, 0.54)' //this doesnt do anything.... + nameContainer: { + display: 'flex', + alignItems: 'center', }, focusMark: { - backgroundColor: '#0671e3', - justifySelf: 'left', - width: '14px', - height: '14px', - borderRadius: '25px', - position: 'absolute' //so it doesn't cause the containing box to jiggle when selected due to change in size + border: '2px solid #0671e3', + borderRadius: '5%', + position: 'absolute', + top: '0', + left: '0', + right: '0', + bottom: '0', }, lightTheme: { color: 'rgba (0, 0, 0, 0.54)' @@ -99,4 +113,5 @@ const useStyles = makeStyles({ color: '#ffffff' } }); + export default ComponentPanelItem; diff --git a/package-lock.json b/package-lock.json index 4aaca51e..48068801 100644 --- a/package-lock.json +++ b/package-lock.json @@ -135,6 +135,7 @@ "html-webpack-plugin": "^4.5.2", "jest": "^28.1.3", "jest-environment-jsdom": "^28.1.3", + "jsdoc": "^4.0.2", "mini-css-extract-plugin": "^2.7.6", "mongodb": "^3.5.9", "nodemon": "^3.0.2", @@ -10949,6 +10950,18 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@jsdoc/salty": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.8.tgz", + "integrity": "sha512-5e+SFVavj1ORKlKaKr2BmTOekmXbelU7dC0cDkQLqag7xfuTPuGMUFx7KWJuv4bYZrTsoL2Z18VVCOKYxzoHcg==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=v12.0.0" + } + }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", @@ -14731,11 +14744,33 @@ "@types/node": "*" } }, + "node_modules/@types/linkify-it": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz", + "integrity": "sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==", + "dev": true + }, "node_modules/@types/long": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" }, + "node_modules/@types/markdown-it": { + "version": "12.2.3", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", + "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", + "dev": true, + "dependencies": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.5.tgz", + "integrity": "sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==", + "dev": true + }, "node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", @@ -18604,6 +18639,18 @@ "cdl": "bin/cdl.js" } }, + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -27107,6 +27154,15 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "dev": true, + "dependencies": { + "xmlcreate": "^2.0.4" + } + }, "node_modules/jsc-android": { "version": "250231.0.0", "resolved": "https://registry.npmjs.org/jsc-android/-/jsc-android-250231.0.0.tgz", @@ -27191,6 +27247,44 @@ "signal-exit": "^3.0.2" } }, + "node_modules/jsdoc": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", + "integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^12.2.3", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^12.3.2", + "markdown-it-anchor": "^8.4.1", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdoc/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/jsdom": { "version": "19.0.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-19.0.0.tgz", @@ -27454,6 +27548,15 @@ "node": ">=0.10.0" } }, + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -27555,6 +27658,15 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "devOptional": true }, + "node_modules/linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "dev": true, + "dependencies": { + "uc.micro": "^1.0.1" + } + }, "node_modules/listr": { "version": "0.14.3", "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", @@ -28326,6 +28438,59 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it-anchor": { + "version": "8.6.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", + "dev": true, + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "node_modules/markdown-it/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/markdown-it/node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/marky": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz", @@ -28344,6 +28509,12 @@ "node": ">=10" } }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "dev": true + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -32234,6 +32405,15 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, + "node_modules/requizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21" + } + }, "node_modules/reselect": { "version": "4.1.8", "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", @@ -34756,6 +34936,12 @@ "node": ">=8" } }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, "node_modules/uid-safe": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", @@ -36254,6 +36440,12 @@ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, + "node_modules/xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", + "dev": true + }, "node_modules/xmlhttprequest-ssl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", diff --git a/package.json b/package.json index 3bb49d25..f9bbfa2f 100644 --- a/package.json +++ b/package.json @@ -248,6 +248,7 @@ "html-webpack-plugin": "^4.5.2", "jest": "^28.1.3", "jest-environment-jsdom": "^28.1.3", + "jsdoc": "^4.0.2", "mini-css-extract-plugin": "^2.7.6", "mongodb": "^3.5.9", "nodemon": "^3.0.2", From bf1e05fe1f72abfb80feec2ce6606d2e0cc4b159 Mon Sep 17 00:00:00 2001 From: Sean Ryan Date: Mon, 22 Apr 2024 20:11:33 -0700 Subject: [PATCH 4/7] Sean 4/22 Fixed render overlap of buttons and input fields in the CustomizationPanel component > > Co-author-by: Heather Pfeiffer Co-author-by: Jesse Wowczuk Co-author-by: Zack Vandiver Co-author-by: Sean Ryan Co-author-by: Austin Alvarez --- app/src/components/main/DeleteButton.tsx | 4 ++- app/src/containers/CustomizationPanel.tsx | 42 +++++++++++++++++++++-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/app/src/components/main/DeleteButton.tsx b/app/src/components/main/DeleteButton.tsx index 0a7d22e2..f9e5027a 100644 --- a/app/src/components/main/DeleteButton.tsx +++ b/app/src/components/main/DeleteButton.tsx @@ -34,7 +34,9 @@ function DeleteButton({ id, name, onClickHandler }: DeleteButtons) { id={'btn' + id} onClick={(event) => { event.stopPropagation(); - onClickHandler(event); + if (typeof onClickHandler === 'function') { + onClickHandler(event); + } deleteHTMLtype(id); }} > diff --git a/app/src/containers/CustomizationPanel.tsx b/app/src/containers/CustomizationPanel.tsx index e2263c04..49748638 100644 --- a/app/src/containers/CustomizationPanel.tsx +++ b/app/src/containers/CustomizationPanel.tsx @@ -56,6 +56,7 @@ const CustomizationPanel = ({ isThemeLight }): JSX.Element => { const [flexDir, setFlexDir] = useState(''); const [flexJustify, setFlexJustify] = useState(''); const [flexAlign, setFlexAlign] = useState(''); + const [flexOptionsVisible, setFlexOptionsVisible] = useState(false); const [BGColor, setBGColor] = useState(''); const [compText, setCompText] = useState(''); const [compLink, setCompLink] = useState(''); @@ -69,7 +70,9 @@ const CustomizationPanel = ({ isThemeLight }): JSX.Element => { const [useContextObj, setUseContextObj] = useState({}); const [stateUsedObj, setStateUsedObj] = useState({}); const [eventAll, setEventAll] = useState(['', '']); + const [eventOptionsVisible, setEventOptionsVisible] = useState(false); const [eventRow, setEventRow] = useState([]); + const [eventRowsVisible, setEventRowsVisible] = useState(false); const currFocus = getFocus().child; @@ -86,6 +89,35 @@ const CustomizationPanel = ({ isThemeLight }): JSX.Element => { } }, [state]); + useEffect(() => { + if (displayMode === 'flex') { + return setFlexOptionsVisible(true); + } + return setFlexOptionsVisible(false); + }, [displayMode]); + + useEffect(() => { + if (eventAll[0] !== '') { + return setEventOptionsVisible(true); + } + return setEventOptionsVisible(false); + }, [eventAll]); + + useEffect(() => { + if (eventRow.length) { + return setEventRowsVisible(true); + } + return setEventRowsVisible(false); + }, [eventRow]); + + const marginTopAmount = () => { + let totalMargin = 0; + if (eventOptionsVisible) totalMargin += 90; + if (flexOptionsVisible) totalMargin = Math.max(totalMargin, 210); + if (eventRowsVisible) totalMargin = Math.max(totalMargin, 335); + return `${totalMargin}px`; + }; + //this function allows properties to persist and appear in nested divs function deepIterate(arr) { const output = []; @@ -128,7 +160,7 @@ const CustomizationPanel = ({ isThemeLight }): JSX.Element => { resetFields(); }, [state.canvasFocus.componentId, state.canvasFocus.childId]); // handles all input field changes, with specific updates called based on input's name - const handleChange = (e: React.ChangeEvent<{ value: any }>) => { + const handleChange = (e: React.ChangeEvent) => { const inputVal = e.target.value; switch (e.target.name) { case 'display': @@ -862,7 +894,10 @@ const CustomizationPanel = ({ isThemeLight }): JSX.Element => { )}
-
+
)} -
+
+
+ )} + {modal} + + ); +}; + +export default MUIItem; From 5523ba921286862d689b9b47393d99d88c38522c Mon Sep 17 00:00:00 2001 From: Zack Vandiver Date: Tue, 23 Apr 2024 12:31:15 -0500 Subject: [PATCH 6/7] Integrated MUI component into more files --- app/src/components/left/DragDropPanel.tsx | 43 ++++++++++--------- app/src/interfaces/Interfaces.ts | 1 + app/src/redux/reducers/slice/appStateSlice.ts | 5 ++- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/app/src/components/left/DragDropPanel.tsx b/app/src/components/left/DragDropPanel.tsx index 256e14fd..ad16ac55 100644 --- a/app/src/components/left/DragDropPanel.tsx +++ b/app/src/components/left/DragDropPanel.tsx @@ -1,6 +1,7 @@ import { useDispatch, useSelector } from 'react-redux'; import Grid from '@mui/material/Grid'; import HTMLItem from './HTMLItem'; +import MUIItem from './MUI_Item'; import React from 'react'; import { RootState } from '../../redux/store'; import { deleteElement } from '../../redux/reducers/slice/appStateSlice'; @@ -10,18 +11,17 @@ import AccordionSummary from '@mui/material/AccordionSummary'; import AccordionDetails from '@mui/material/AccordionDetails'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import { makeStyles } from '@mui/styles'; -import ComponentDrag from './ComponentDrag'; - +import ComponentDrag from './ComponentDrag'; const useStyles = makeStyles({ accordion: { backgroundColor: '#000000', // Set the background color to gray - color: '#ffffff', // Set the text color to white + color: '#ffffff' // Set the text color to white }, accordionSummary: { backgroundColor: '#000000', // Set the background color of the summary to gray - color: '#ffffff', // Set the text color of the summary to white - }, + color: '#ffffff' // Set the text color of the summary to white + } }); const DragDropPanel = (props): JSX.Element => { @@ -46,6 +46,8 @@ const DragDropPanel = (props): JSX.Element => { (type) => type.name !== 'separator' ); + const muiTypesToRender = state.MUITypes; + return (
@@ -93,7 +95,7 @@ const DragDropPanel = (props): JSX.Element => { - + {/* MUI Components */} { - {htmlTypesToRender.map((option) => { - if (option.name === 'MUI') { - return ( - - ); - } + {muiTypesToRender.map((option) => { + // if (option.name === 'MUI') { + return ( + + ); + // } })} - + {/* React Router */} { - + {/* Next.js */} {state.projectType === 'Next.js' ? (

Next.js

@@ -183,4 +185,3 @@ const DragDropPanel = (props): JSX.Element => { }; export default DragDropPanel; - diff --git a/app/src/interfaces/Interfaces.ts b/app/src/interfaces/Interfaces.ts index d8008442..1c38b7f9 100644 --- a/app/src/interfaces/Interfaces.ts +++ b/app/src/interfaces/Interfaces.ts @@ -17,6 +17,7 @@ export interface State { nextBottomSeparatorId?: number; nextChildId: number; HTMLTypes: HTMLType[]; + MUITypes: MUIType[]; tailwind: boolean; stylesheet: string; codePreview: boolean; diff --git a/app/src/redux/reducers/slice/appStateSlice.ts b/app/src/redux/reducers/slice/appStateSlice.ts index 1b1b0c12..7ed5013b 100644 --- a/app/src/redux/reducers/slice/appStateSlice.ts +++ b/app/src/redux/reducers/slice/appStateSlice.ts @@ -5,9 +5,11 @@ import { State, Component, ChildElement, - HTMLType + HTMLType, + MUIType } from '../../../interfaces/Interfaces'; import HTMLTypes from '../../HTMLTypes'; +import MUITypes from '../../MUITypes'; import generateCode from '../../../helperFunctions/generateCode'; import manageSeparators from '../../../helperFunctions/manageSeparators'; @@ -40,6 +42,7 @@ export const initialState: State = { nextChildId: 1, nextTopSeparatorId: 1000, HTMLTypes: HTMLTypes, // left as is for now + MUITypes: MUITypes, // left as is for now tailwind: false, stylesheet: '', codePreview: false, From 62d1b497d7e5cb15593156067893645a278aa461 Mon Sep 17 00:00:00 2001 From: Sean Ryan Date: Tue, 23 Apr 2024 18:58:48 -0700 Subject: [PATCH 7/7] Sean 4/23 integrated MUITypes into redux and appStateSlice; created DirectChildMUI and DirectChildMUINestable components; added MUI components to DragDropPanel component; updated MUITypes; updated associated imports > > Co-author-by: Heather Pfeiffer Co-author-by: Jesse Wowczuk Co-author-by: Zack Vandiver Co-author-by: Sean Ryan --- app/src/components/left/DragDropPanel.tsx | 13 +- app/src/components/left/HTMLItem.tsx | 1 + .../left/{MUI_Item.tsx => MUIItem.tsx} | 34 ++- app/src/components/main/Canvas.tsx | 1 + app/src/components/main/DirectChildMUI.tsx | 90 +++++++ .../main/DirectChildMUINestable.tsx | 240 ++++++++++++++++++ app/src/components/main/SeparatorChild.tsx | 14 +- app/src/helperFunctions/generateCode.ts | 37 +++ app/src/helperFunctions/renderChildren.tsx | 67 ++++- app/src/public/styles/style.css | 30 ++- app/src/redux/MUITypes.ts | 198 ++++++++------- app/src/redux/reducers/slice/appStateSlice.ts | 167 ++++++------ 12 files changed, 711 insertions(+), 181 deletions(-) rename app/src/components/left/{MUI_Item.tsx => MUIItem.tsx} (91%) create mode 100644 app/src/components/main/DirectChildMUI.tsx create mode 100644 app/src/components/main/DirectChildMUINestable.tsx diff --git a/app/src/components/left/DragDropPanel.tsx b/app/src/components/left/DragDropPanel.tsx index ad16ac55..6bb98eac 100644 --- a/app/src/components/left/DragDropPanel.tsx +++ b/app/src/components/left/DragDropPanel.tsx @@ -1,7 +1,7 @@ import { useDispatch, useSelector } from 'react-redux'; import Grid from '@mui/material/Grid'; import HTMLItem from './HTMLItem'; -import MUIItem from './MUI_Item'; +import MUIItem from './MUIItem'; import React from 'react'; import { RootState } from '../../redux/store'; import { deleteElement } from '../../redux/reducers/slice/appStateSlice'; @@ -46,11 +46,14 @@ const DragDropPanel = (props): JSX.Element => { (type) => type.name !== 'separator' ); - const muiTypesToRender = state.MUITypes; + const muiTypesToRender = state.MUITypes.filter( + (type) => type.name !== 'separator' + ); return (
+ {/* Root Components */} } @@ -64,6 +67,8 @@ const DragDropPanel = (props): JSX.Element => { + + {/* HTML Components */} } @@ -109,9 +114,8 @@ const DragDropPanel = (props): JSX.Element => { {muiTypesToRender.map((option) => { - // if (option.name === 'MUI') { return ( - { handleDelete={handleDelete} /> ); - // } })} diff --git a/app/src/components/left/HTMLItem.tsx b/app/src/components/left/HTMLItem.tsx index 40e13d73..cbe65eef 100644 --- a/app/src/components/left/HTMLItem.tsx +++ b/app/src/components/left/HTMLItem.tsx @@ -19,6 +19,7 @@ const useStyles = makeStyles({ height: 'auto', width: 'auto', fontSize: 'small', + alignItems: 'center', display: 'flex', flexDirection: 'row', justifyContent: 'space-evenly', diff --git a/app/src/components/left/MUI_Item.tsx b/app/src/components/left/MUIItem.tsx similarity index 91% rename from app/src/components/left/MUI_Item.tsx rename to app/src/components/left/MUIItem.tsx index 050767c4..b91a59f7 100644 --- a/app/src/components/left/MUI_Item.tsx +++ b/app/src/components/left/MUIItem.tsx @@ -20,10 +20,11 @@ const useStyles = makeStyles({ MUIPanelItem: { height: 'auto', width: 'auto', - fontSize: 'medium', + fontSize: 'small', display: 'flex', flexDirection: 'row', justifyContent: 'space-evenly', + alignItems: 'center', textAlign: 'center', cursor: 'grab' }, @@ -48,15 +49,20 @@ const MUIItem: React.FC<{ // Use drag and drop functionality const classes = useStyles(); const [modal, setModal] = useState(null); + + const item = { + type: ItemTypes.INSTANCE, + newInstance: true, + instanceType: 'MUI Component', // MUI Element? - we should carefully consider what we call this + name, + icon, + instanceTypeId: id + }; + + // console.log('draggable item', item); + const [{ isDragging }, drag] = useDrag({ - item: { - type: ItemTypes.INSTANCE, - newInstance: true, - instanceType: 'MUI Component', // MUI Element? - we should carefully consider what we call this - name, - icon, - instanceTypeId: id - }, + item, collect: (monitor: any) => ({ isDragging: !!monitor.isDragging() }) @@ -137,8 +143,8 @@ const MUIItem: React.FC<{ // id over/under 20 logic // html-g{name} - html grid name = item return ( - - {id <= 20 && ( + + {id >= 20 && (
{ handleClick(); }} @@ -158,12 +164,12 @@ const MUIItem: React.FC<{
)} - {id > 20 && ( + {id < 20 && (
{ handleClick(); }} diff --git a/app/src/components/main/Canvas.tsx b/app/src/components/main/Canvas.tsx index c491dfd3..3936c3d2 100644 --- a/app/src/components/main/Canvas.tsx +++ b/app/src/components/main/Canvas.tsx @@ -211,6 +211,7 @@ const Canvas = forwardRef(({ zoom }, ref) => { } // if item dropped is going to be a new instance (i.e. it came from the left panel), then create a new child component if (item.newInstance && item.instanceType !== 'Component') { + console.log('inside not component check', item); dispatch( //update state addChild({ diff --git a/app/src/components/main/DirectChildMUI.tsx b/app/src/components/main/DirectChildMUI.tsx new file mode 100644 index 00000000..934ef48a --- /dev/null +++ b/app/src/components/main/DirectChildMUI.tsx @@ -0,0 +1,90 @@ +import React from 'react'; +import { ChildElement, MUIType } from '../../interfaces/Interfaces'; +import { useDrag } from 'react-dnd'; +import { ItemTypes } from '../../constants/ItemTypes'; +import { combineStyles } from '../../helperFunctions/combineStyles'; +import globalDefaultStyle from '../../public/styles/globalDefaultStyles'; +import DeleteButton from './DeleteButton'; +import { useDispatch, useSelector } from 'react-redux'; +import { changeFocus } from '../../redux/reducers/slice/appStateSlice'; +import { RootState } from '../../redux/store'; +import { emitEvent } from '../../helperFunctions/socket'; + +function DirectChildMUI({ childId, name, type, typeId, style }: ChildElement) { + const state = useSelector((store: RootState) => store.appState); + + const roomCode = useSelector((store: RootState) => store.roomSlice.roomCode); + + const dispatch = useDispatch(); + + // find the MUI element corresponding with this instance of an MUI element + // find the current component to render on the canvas + const MUIType: MUIType = state.MUITypes.find( + (type: MUIType) => type.id === typeId + ); + // hook that allows component to be draggable + const [{ isDragging }, drag] = useDrag({ + // setting item attributes to be referenced when updating state with new instance of dragged item + item: { + type: ItemTypes.INSTANCE, + newInstance: false, + childId: childId, + instanceType: type, + instanceTypeId: typeId + }, + collect: (monitor: any) => ({ + isDragging: !!monitor.isDragging() + }) + }); + + const changeFocusFunction = (componentId: number, childId: number | null) => { + dispatch(changeFocus({ componentId, childId })); + if (roomCode) { + emitEvent('changeFocusAction', roomCode, { + componentId: componentId, + childId: childId + }); + // console.log('emit focus event from DirectChildMUI'); + } + }; + + // onClickHandler is responsible for changing the focused component and child component + function onClickHandler(event) { + event.stopPropagation(); + changeFocusFunction(state.canvasFocus.componentId, childId); + } + + // combine all styles so that higher priority style specifications overrule lower priority style specifications + // priority order is 1) style directly set for this child (style), 2) style of the referenced HTML element, and 3) default styling + const interactiveStyle = { + border: + state.canvasFocus.childId === childId + ? '2px solid #0671e3' + : '1px solid #31343A' + }; + + const combinedStyle = combineStyles( + combineStyles(combineStyles(globalDefaultStyle, MUIType.style), style), + interactiveStyle + ); + + return ( +
+ + {MUIType.placeHolderShort} + + +
+ ); +} + +export default DirectChildMUI; diff --git a/app/src/components/main/DirectChildMUINestable.tsx b/app/src/components/main/DirectChildMUINestable.tsx new file mode 100644 index 00000000..f30848cb --- /dev/null +++ b/app/src/components/main/DirectChildMUINestable.tsx @@ -0,0 +1,240 @@ +import React, { useRef } from 'react'; +import { ChildElement, MUIType } from '../../interfaces/Interfaces'; +import { useDrag, useDrop, DropTargetMonitor } from 'react-dnd'; +import { ItemTypes } from '../../constants/ItemTypes'; +import { combineStyles } from '../../helperFunctions/combineStyles'; +import globalDefaultStyle from '../../public/styles/globalDefaultStyles'; +import renderChildren from '../../helperFunctions/renderChildren'; +import DeleteButton from './DeleteButton'; +import validateNewParent from '../../helperFunctions/changePositionValidation'; +import componentNest from '../../helperFunctions/componentNestValidation'; +import AddRoute from './AddRoute'; +import AddLink from './AddLink'; +import { useDispatch, useSelector } from 'react-redux'; +import { RootState } from '../../redux/store'; +import { emitEvent } from '../../helperFunctions/socket'; + +import { + changeFocus, + changePosition, + addChild, + snapShotAction +} from '../../redux/reducers/slice/appStateSlice'; + +function DirectChildMUINestable({ + childId, + type, + typeId, + style, + children, + name, + attributes +}: ChildElement): React.JSX.Element { + const state = useSelector((store: RootState) => store.appState); + const contextParam = useSelector((store: RootState) => store.contextSlice); + + const dispatch = useDispatch(); + const roomCode = useSelector((store: RootState) => store.roomSlice.roomCode); + + const ref = useRef(null); + + // takes a snapshot of state to be used in UNDO and REDO cases. snapShotFunc is also invoked in Canvas.tsx + const snapShotFunc = () => { + //makes a deep clone of state + const deepCopiedState = JSON.parse(JSON.stringify(state)); + const focusIndex = state.canvasFocus.componentId - 1; + //pushes the last user action on the canvas into the past array of Component + dispatch( + snapShotAction({ + focusIndex: focusIndex, + deepCopiedState: deepCopiedState + }) + ); + }; + + // find the MUI element corresponding with this instance of an MUI element + // find the current component to render on the canvas + const MUIType: MUIType = state.MUITypes.find( + (type: MUIType) => type.id === typeId + ); + + // hook that allows component to be draggable + const [{ isDragging }, drag] = useDrag({ + // setting item attributes to be referenced when updating state with new instance of dragged item + item: { + type: ItemTypes.INSTANCE, + newInstance: false, + childId: childId, + instanceType: type, + instanceTypeId: typeId, + name: name + }, + canDrag: MUIType.id !== 1000, // dragging not permitted if element is separator + collect: (monitor: any) => { + return { + isDragging: !!monitor.isDragging() + }; + } + }); + + // both useDrop and useDrag used here to allow canvas components to be both a drop target and drag source + const [{ isOver }, drop] = useDrop({ + accept: ItemTypes.INSTANCE, + // triggered on drop + drop: (item: any, monitor: DropTargetMonitor) => { + const didDrop = monitor.didDrop(); + // takes a snapshot of state to be used in UNDO and REDO cases + snapShotFunc(); + if (didDrop) { + return; + } + // updates state with new instance + // if item dropped is going to be a new instance (i.e. it came from the left panel), then create a new child component + if (item.newInstance) { + if ( + (item.instanceType === 'Component' && + componentNest( + state.components[item.instanceTypeId - 1].children, + childId + )) || + item.instanceType !== 'Component' + ) { + dispatch( + addChild({ + type: item.instanceType, + typeId: item.instanceTypeId, + childId: childId, + contextParam: contextParam + }) + ); + if (roomCode) { + emitEvent('addChildAction', roomCode, { + type: item.instanceType, + typeId: item.instanceTypeId, + childId: childId, + contextParam: contextParam + }); + + // console.log( + // 'emit addChildAction event is triggered in DirectChildMUINestable' + // ); + } + } + } + // if item is not a new instance, change position of element dragged inside div so that the div is the new parent + else { + // check to see if the selected child is trying to nest within itself + if (validateNewParent(state, item.childId, childId) === true) { + dispatch( + changePosition({ + currentChildId: item.childId, + newParentChildId: childId, + contextParam: contextParam + }) + ); + if (roomCode) { + emitEvent('changePositionAction', roomCode, { + currentChildId: item.childId, + newParentChildId: childId, + contextParam: contextParam + }); + + // console.log( + // 'emit changePosition event is triggered in DirectChildMUINestable' + // ); + } + } + } + }, + + collect: (monitor: any) => { + return { + isOver: !!monitor.isOver({ shallow: true }) + }; + } + }); + + const changeFocusFunction = (componentId: number, childId: number | null) => { + dispatch(changeFocus({ componentId, childId })); + if (roomCode) { + emitEvent('changeFocusAction', roomCode, { + componentId: componentId, + childId: childId + }); + // console.log('emit focus event from DirectChildMUINestable'); + } + }; + + // onClickHandler is responsible for changing the focused component and child component + function onClickHandler(event) { + event.stopPropagation(); + changeFocusFunction(state.canvasFocus.componentId, childId); + } + + // combine all styles so that higher priority style specifications overrule lower priority style specifications + // priority order is 1) style directly set for this child (style), 2) style of the referenced MUI element, and 3) default styling + const defaultNestableStyle = { ...globalDefaultStyle }; + const interactiveStyle = { + border: + state.canvasFocus.childId === childId + ? '2px solid #0671e3' + : '1px solid #31343A' + }; + + // interactive style to change color when nested element is hovered over + if (isOver) defaultNestableStyle['#3c59ba']; + defaultNestableStyle['backgroundColor'] = isOver + ? '#3c59ba' + : defaultNestableStyle['backgroundColor']; + + const combinedStyle = combineStyles( + combineStyles(combineStyles(defaultNestableStyle, MUIType.style), style), + interactiveStyle + ); + + drag(drop(ref)); + + const routeButton = []; + if (typeId === 17) { + routeButton.push(); + } + if (typeId === 19) { + routeButton.push( + + ); + } + + return ( +
+ + {MUIType.placeHolderShort} + + {attributes && attributes.compLink ? ` ${attributes.compLink}` : ''} + + {routeButton} + + + {renderChildren(children)} +
+ ); +} + +export default DirectChildMUINestable; diff --git a/app/src/components/main/SeparatorChild.tsx b/app/src/components/main/SeparatorChild.tsx index 8d9388ec..f2910ebb 100644 --- a/app/src/components/main/SeparatorChild.tsx +++ b/app/src/components/main/SeparatorChild.tsx @@ -1,5 +1,10 @@ import React, { useRef } from 'react'; -import { ChildElement, HTMLType, DragItem } from '../../interfaces/Interfaces'; +import { + ChildElement, + HTMLType, + MUIType, + DragItem +} from '../../interfaces/Interfaces'; import { useDrag, useDrop, DropTargetMonitor } from 'react-dnd'; import { ItemTypes } from '../../constants/ItemTypes'; import { combineStyles } from '../../helperFunctions/combineStyles'; @@ -37,6 +42,9 @@ function SeparatorChild({ (type: HTMLType) => type.id === typeId ); + const MUIType: MUIType = state.MUITypes.find( + (type: MUIType) => type.id === typeId + ); // hook that allows component to be draggable const [{ isDragging }, drag] = useDrag({ // setting item attributes to be referenced when updating state with new instance of dragged item @@ -47,7 +55,7 @@ function SeparatorChild({ instanceType: type, instanceTypeId: typeId }, - canDrag: HTMLType.id !== 1000, // dragging not permitted if element is separator + canDrag: HTMLType.id !== 1000 || MUIType.id !== 1000, // dragging not permitted if element is separator collect: (monitor: any) => { return { isDragging: !!monitor.isDragging() @@ -144,7 +152,7 @@ function SeparatorChild({ // priority order is 1) style directly set for this child (style), 2) style of the referenced HTML element, and 3) default styling const defaultNestableStyle = { ...globalDefaultStyle }; const separatorStyle = { - padding: isOver ? '40px 10px' : '2px 10px', + padding: isOver ? '40px 10px' : '2px 10px', margin: '1px 10px', transition: 'padding 1s ease-out' }; diff --git a/app/src/helperFunctions/generateCode.ts b/app/src/helperFunctions/generateCode.ts index bd9b1e9e..35bbf93e 100644 --- a/app/src/helperFunctions/generateCode.ts +++ b/app/src/helperFunctions/generateCode.ts @@ -2,6 +2,7 @@ import { Component, ChildElement, HTMLType, + MUIType, ChildStyle, StateProp } from '../interfaces/Interfaces'; @@ -17,6 +18,7 @@ const generateCode = ( rootComponents: number[], projectType: string, HTMLTypes: HTMLType[], + MUITypes: MUIType[], tailwind: boolean, contextParam: any ) => { @@ -26,6 +28,7 @@ const generateCode = ( rootComponents, projectType, HTMLTypes, + MUITypes, tailwind, contextParam ); @@ -39,6 +42,7 @@ const generateUnformattedCode = ( rootComponents: number[], projectType: string, HTMLTypes: HTMLType[], + MUITypes: MUIType[], tailwind: boolean, contextParam: any ) => { @@ -105,6 +109,30 @@ const generateUnformattedCode = ( else if (referencedHTML.tag === 'Link') links = true; if (referencedHTML.tag === 'Image') images = true; return child; + } else if (child.type === 'MUI Component') { + const referencedMUI = MUITypes.find((elem) => elem.id === child.typeId); + child['tag'] = referencedMUI.tag; + if ( + referencedMUI.tag === 'button' || + referencedMUI.tag === 'card' || + referencedMUI.tag === 'typography' || + referencedMUI.tag === 'input' || + referencedMUI.tag === 'Link' || + referencedMUI.tag === 'Switch' || + referencedMUI.tag === 'Route' + ) { + child.children = getEnrichedChildren(child); + } + + // when we see a Switch or LinkTo, import React Router + if ( + (referencedMUI.tag === 'Switch' || referencedMUI.tag === 'Route') && + projectType === 'Classic React' + ) + importReactRouter = true; + else if (referencedMUI.tag === 'Link') links = true; + if (referencedMUI.tag === 'Image') images = true; + return child; } else if (child.type === 'Route Link') { links = true; child.name = components.find( @@ -499,6 +527,15 @@ const generateUnformattedCode = ( if (child.children.length !== 0) importStr += createEventHandler(child.children); } + if (child.type === 'MUI Component') { + if (child.events) { + for (const [event, funcName] of Object.entries(child.events)) { + importStr += `\tconst ${funcName} = () => {};\n`; + } + } + if (child.children.length !== 0) + importStr += createEventHandler(child.children); + } }); return importStr; diff --git a/app/src/helperFunctions/renderChildren.tsx b/app/src/helperFunctions/renderChildren.tsx index bbae5960..9a19901a 100644 --- a/app/src/helperFunctions/renderChildren.tsx +++ b/app/src/helperFunctions/renderChildren.tsx @@ -3,6 +3,8 @@ import { ChildElement } from '../interfaces/Interfaces'; import DirectChildComponent from '../components/main/DirectChildComponent'; import DirectChildHTML from '../components/main/DirectChildHTML'; import DirectChildHTMLNestable from '../components/main/DirectChildHTMLNestable'; +import DirectChildMUI from '../components/main/DirectChildMUI'; +import DirectChildMUINestable from '../components/main/DirectChildMUINestable'; import SeparatorChild from '../components/main/SeparatorChild'; import RouteLink from '../components/main/RouteLink'; import { useSelector } from 'react-redux'; @@ -17,7 +19,12 @@ const renderChildren = (children: ChildElement[]) => { return children.map((child: ChildElement, i: number) => { const { type, style, childId, children, attributes, name } = child; + // console.log('state components', state.components); + // console.log('state MUI type', state.MUITypes); let { typeId } = child; + // console.log('typeID', typeId); + // console.log('name', name); + // console.log('child.name', state.components[typeId - 1].name); if (name === '') child.name = state.components[typeId - 1].name; // A DirectChildComponent is an instance of a top level component // This component will render IndirectChild components (div/components rendered inside a child component) @@ -39,7 +46,8 @@ const renderChildren = (children: ChildElement[]) => { /> ); } - // child is a non-nestable type of HTML element (aka NOT divs, forms, OrderedLists, UnorderedLists, menus) + // child is a non-nestable type of HTML element + // nestable = false -> input(10), img(12), image(20) else if ( type === 'HTML Element' && typeId !== 11 && @@ -119,6 +127,63 @@ const renderChildren = (children: ChildElement[]) => { passedInProps={[]} /> ); + } else if (type === 'MUI Component' && typeId === 31) { + return ( + + ); + } + // child is a nestable type of HTML element (divs, forms, OrderedLists, UnorderedLists, menus) + else if ( + type === 'MUI Component' && + (typeId === 21 || typeId === 41 || typeId === 51) + ) { + return ( + + ); + } else if (type === 'MUI Component' && typeId === 1000) { + return ( + + ); } else if (type === 'HTML Element' && typeId === 1000) { return ( { // if no match is found return false return; }; +function createHTMLElement(data) { + return { + ...data, + isHTMLElement: true + }; +} + // update all ids and typeIds to match one another const updateAllIds = (comp: Component[] | ChildElement[]) => { // put components' names and ids into an obj @@ -275,6 +282,7 @@ const appStateSlice = createSlice({ [...state.rootComponents], state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -283,7 +291,6 @@ const appStateSlice = createSlice({ }, addChild: (state, action) => { - let parentComponentId: number; const { type, typeId, @@ -291,60 +298,57 @@ const appStateSlice = createSlice({ }: { type: string; typeId: number; childId: any } = action.payload; // determine the parent component id - if (action.payload.copyId) { - parentComponentId = action.payload.copyId; - } else { - parentComponentId = state.canvasFocus.componentId; - } + const parentComponentId = + action.payload.copyId || state.canvasFocus.componentId; // make a copy of the components from state const components = [...state.components]; // find the parent component const parentComponent = findComponent(components, parentComponentId); + if (!parentComponent) return state; // ensure that parent component exists // if type is 'Component', loop through components to find componentName and componentChildren let componentName: string = ''; let componentChildren: ChildElement[] = []; - if (type === 'Component') { - components.forEach((comp) => { - if (comp.id === typeId) { - componentName = comp.name; - componentChildren = comp.children; - } - }); - } + if (type === 'Component') { const originalComponent = findComponent(state.components, typeId); if (originalComponent) { + componentName = originalComponent.name; + componentChildren = originalComponent.children; if ( childTypeExists('Component', parentComponentId, originalComponent) ) return state; } - } - - // create a new name based on the type of element - let newName = state.HTMLTypes.reduce((name, el) => { - if (typeId === el.id) { - name = type === 'Component' ? componentName : el.tag; + } else if (type === 'Route Link') { + const routeLinkComponent = components.find( + (comp) => comp.id === typeId + ); + if (routeLinkComponent) { + componentName = routeLinkComponent.name; } - return name; - }, ''); - - if (type === 'Route Link') { - components.find((comp) => { - if (comp.id === typeId) { - newName = comp.name; - return; + } else if (type === 'HTML Element') { + componentName = state.HTMLTypes.reduce((name, el) => { + if (typeId === el.id) { + name = el.tag; } - }); + return name; + }, ''); + } else { + componentName = state.MUITypes.reduce((name, el) => { + if (typeId === el.id) { + name = el.tag; + } + return name; + }, ''); } const newChild: ChildElement = { type, typeId, - name: newName, + name: componentName, childId: state.nextChildId, style: {}, attributes: {}, @@ -372,26 +376,20 @@ const appStateSlice = createSlice({ // if the newChild Element is an input or img type, delete the children key/value pair // if (newChild.name === 'input' && newChild.name === 'img') // delete newChild.children; - let directParent: HTMLElement | any; + // let directParent: HTMLElement | any; if (childId === null) { - if (parentComponent) { - parentComponent.children.push(topSeparator); - parentComponent.children.push(newChild); - } - } - // if there is a childId (childId here references the direct parent of the new child) find that child and add new child to its children array - else { - if (parentComponent) { - directParent = findChild(parentComponent, childId); - //disable nesting a component inside a HTML element + parentComponent.children.push(topSeparator, newChild); + } else { + const directParent = findChild(parentComponent, childId); + if (directParent) { if (directParent.type === 'HTML Element' && type === 'HTML Element') { - directParent.children.push(topSeparator); - directParent.children.push(newChild); + directParent.children.push(topSeparator, newChild); } else { return { ...state }; } } } + // update canvasFocus to the new child const canvasFocus = { ...state.canvasFocus, @@ -399,38 +397,34 @@ const appStateSlice = createSlice({ childId: newChild.childId }; - const nextChildId = state.nextChildId + 1; - let nextTopSeparatorId = state.nextTopSeparatorId + 1; - let addChildArray = components[canvasFocus.componentId - 1].children; - // merge separator needs interface and type - addChildArray = manageSeparators.mergeSeparator(addChildArray, 1); - if (directParent && directParent.name === 'separator') - nextTopSeparatorId = manageSeparators.handleSeparators( - // handle separator needs interface and type - addChildArray, - 'add' - ); - - components[canvasFocus.componentId - 1].children = addChildArray; + // Increment IDs + state.nextChildId += 1; + state.nextTopSeparatorId += 1; - // generate code - if (parentComponent) { - parentComponent.code = generateCode( - components, - parentComponentId, - [...state.rootComponents], - state.projectType, - state.HTMLTypes, - state.tailwind, - action.payload.contextParam + // Update the components array and potentially other parts of the state + components[parentComponentId - 1].children = + manageSeparators.mergeSeparator( + components[parentComponentId - 1].children, + 1 ); - } - // update the state with the new values + // Generate code for the component + parentComponent.code = generateCode( + components, + parentComponentId, + [...state.rootComponents], + state.projectType, + state.HTMLTypes, + state.MUITypes, + state.tailwind, + action.payload.contextParam + ); + + // Update state state.components = components; - state.nextChildId = nextChildId; state.canvasFocus = canvasFocus; - state.nextTopSeparatorId = nextTopSeparatorId; + + return state; }, changeTailwind: (state, action) => { @@ -468,6 +462,7 @@ const appStateSlice = createSlice({ [...state.rootComponents], state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -492,6 +487,7 @@ const appStateSlice = createSlice({ [...state.rootComponents], state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -559,6 +555,7 @@ const appStateSlice = createSlice({ [...state.rootComponents], state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -585,6 +582,7 @@ const appStateSlice = createSlice({ [...state.rootComponents], state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -613,6 +611,7 @@ const appStateSlice = createSlice({ [...state.rootComponents], state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -642,6 +641,7 @@ const appStateSlice = createSlice({ [...state.rootComponents], state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -668,6 +668,7 @@ const appStateSlice = createSlice({ [...state.rootComponents], state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -726,6 +727,7 @@ const appStateSlice = createSlice({ rootComponents, state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -756,6 +758,7 @@ const appStateSlice = createSlice({ [...state.rootComponents], projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -784,6 +787,7 @@ const appStateSlice = createSlice({ const stylesheet = ''; const resetHTMLTypes = HTMLTypes; + const resetMUITypes = MUITypes; return { ...state, @@ -794,7 +798,8 @@ const appStateSlice = createSlice({ components, canvasFocus, stylesheet, - HTMLTypes: resetHTMLTypes + HTMLTypes: resetHTMLTypes, + MUITypes: resetMUITypes }; }, updateProjectName: (state, action) => { @@ -817,6 +822,12 @@ const appStateSlice = createSlice({ } return el.id !== action.payload.id; }); + // const MUITypes: MUIType[] = [...state.MUITypes].filter((el) => { + // if (el.id === action.payload.id) { + // name = el.tag; + // } + // return el.id !== action.payload.id; + // }); const components: Component[] = deleteById( action.payload.id, name, @@ -831,6 +842,7 @@ const appStateSlice = createSlice({ rootComponents, state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -838,6 +850,7 @@ const appStateSlice = createSlice({ state.canvasFocus = canvasFocus; state.HTMLTypes = HTMLTypes; + // state.MUITypes = MUITypes; }, deleteChild: (state, action) => { @@ -883,6 +896,7 @@ const appStateSlice = createSlice({ [...state.rootComponents], state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -934,6 +948,7 @@ const appStateSlice = createSlice({ state.rootComponents, state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -962,6 +977,7 @@ const appStateSlice = createSlice({ state.rootComponents, state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -985,6 +1001,7 @@ const appStateSlice = createSlice({ [...state.rootComponents], state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -1038,6 +1055,7 @@ const appStateSlice = createSlice({ [...state.rootComponents], state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -1048,6 +1066,7 @@ const appStateSlice = createSlice({ [...state.rootComponents], state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -1104,6 +1123,7 @@ const appStateSlice = createSlice({ [...state.rootComponents], state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -1128,6 +1148,7 @@ const appStateSlice = createSlice({ [...state.rootComponents], state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -1151,6 +1172,7 @@ const appStateSlice = createSlice({ [...state.rootComponents], state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -1165,6 +1187,7 @@ const appStateSlice = createSlice({ [...state.rootComponents], state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -1269,6 +1292,7 @@ const appStateSlice = createSlice({ [...state.rootComponents], state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam ); @@ -1281,6 +1305,7 @@ const appStateSlice = createSlice({ [...state.rootComponents], state.projectType, state.HTMLTypes, + state.MUITypes, state.tailwind, action.payload.contextParam );