diff --git a/src/components/atoms/AlertSnackbar.tsx b/src/components/atoms/AlertSnackbar.tsx new file mode 100644 index 00000000..3cf5c554 --- /dev/null +++ b/src/components/atoms/AlertSnackbar.tsx @@ -0,0 +1,40 @@ +import * as React from 'react'; +import Snackbar from '@mui/material/Snackbar'; +import MuiAlert, { AlertProps } from '@mui/material/Alert'; +import { useGlobalInfoStore } from "../../context/globalInfo"; + +const Alert = React.forwardRef(function Alert( + props, + ref, +) { + return ; +}); + +export interface AlertSnackbarProps { + severity: 'error' | 'warning' | 'info' | 'success', + message: string, + isOpen: boolean, +}; + +export const AlertSnackbar = ({ severity, message, isOpen }: AlertSnackbarProps) => { + const [open, setOpen] = React.useState(isOpen); + + const { closeNotify } = useGlobalInfoStore(); + + const handleClose = (event?: React.SyntheticEvent | Event, reason?: string) => { + if (reason === 'clickaway') { + return; + } + + closeNotify(); + setOpen(false); + }; + + return ( + + + {message} + + + ); +} diff --git a/src/components/atoms/Box.tsx b/src/components/atoms/Box.tsx new file mode 100644 index 00000000..b04f1ad1 --- /dev/null +++ b/src/components/atoms/Box.tsx @@ -0,0 +1,25 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; + +interface BoxProps { + width: number | string, + height: number | string, + background: string, + radius: string, + children?: JSX.Element, +}; + +export const SimpleBox = ({ width, height, background, radius, children }: BoxProps) => { + return ( + + {children} + + ); +} diff --git a/src/components/atoms/DropdownMui.tsx b/src/components/atoms/DropdownMui.tsx new file mode 100644 index 00000000..ff97ff71 --- /dev/null +++ b/src/components/atoms/DropdownMui.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { FormControl, InputLabel, Select } from "@mui/material"; +import { SelectChangeEvent } from "@mui/material/Select/Select"; + +interface DropdownProps { + id: string; + label: string; + value: string | undefined; + handleSelect: (event: SelectChangeEvent) => void; + children?: React.ReactNode; +}; + +export const Dropdown = ({ id, label, value, handleSelect, children }: DropdownProps) => { + return ( + + {label} + + + ); +}; diff --git a/src/components/atoms/GenericModal.tsx b/src/components/atoms/GenericModal.tsx new file mode 100644 index 00000000..30ba7a68 --- /dev/null +++ b/src/components/atoms/GenericModal.tsx @@ -0,0 +1,44 @@ +import React, { FC } from 'react'; +import { Modal, IconButton, Box } from '@mui/material'; +import { Clear } from "@mui/icons-material"; + +interface ModalProps { + isOpen: boolean; + onClose: () => void; + children?: JSX.Element; + modalStyle?: React.CSSProperties; + canBeClosed?: boolean; +} + +export const GenericModal: FC = ( + { isOpen, onClose, children, modalStyle, canBeClosed = true }) => { + + return ( + { }} > + + {canBeClosed ? + + + + : null + } + {children} + + + ); +}; + +const defaultModalStyle = { + position: 'absolute', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + width: 500, + bgcolor: 'background.paper', + boxShadow: 24, + p: 4, + height: '60%', + display: 'block', + overflow: 'scroll', + padding: '5px 25px 10px 25px', +}; diff --git a/src/components/atoms/KeyValuePair.tsx b/src/components/atoms/KeyValuePair.tsx new file mode 100644 index 00000000..a681b782 --- /dev/null +++ b/src/components/atoms/KeyValuePair.tsx @@ -0,0 +1,52 @@ +import React, { forwardRef, useImperativeHandle } from "react"; +import { Box, TextField } from "@mui/material"; + +interface KeyValueFormProps { + keyLabel?: string; + valueLabel?: string; +} + +export const KeyValuePair = forwardRef(({ keyLabel, valueLabel }: KeyValueFormProps, ref) => { + const [key, setKey] = React.useState(''); + const [value, setValue] = React.useState(''); + useImperativeHandle(ref, () => ({ + getKeyValuePair() { + return { key, value }; + } + })); + return ( + :not(style)': { m: 1, width: '100px' }, + }} + noValidate + autoComplete="off" + > + ) => setKey(event.target.value)} + size="small" + required + /> + ) => { + const num = Number(event.target.value); + if (isNaN(num)) { + setValue(event.target.value); + } + else { + setValue(num); + } + }} + size="small" + required + /> + + ); +}); diff --git a/src/components/atoms/Loader.tsx b/src/components/atoms/Loader.tsx new file mode 100644 index 00000000..aafdaee4 --- /dev/null +++ b/src/components/atoms/Loader.tsx @@ -0,0 +1,86 @@ +import styled from "styled-components"; +import { Stack } from "@mui/material"; + +export const Loader = () => { + return ( + + + + Loading... + + + ); +} + +const StyledParagraph = styled.p` + font-size: x-large; + font-family: inherit; + color: #1976d2; + display: grid; + justify-content: center; +`; + +const StyledLoader = styled.div` + border-radius: 50%; + color: #1976d2; + font-size: 11px; + text-indent: -99999em; + margin: 55px auto; + position: relative; + width: 10em; + height: 10em; + box-shadow: inset 0 0 0 1em; + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); + &:before { + position: absolute; + content: ''; + border-radius: 50%; + width: 5.2em; + height: 10.2em; + background: #ffffff; + border-radius: 10.2em 0 0 10.2em; + top: -0.1em; + left: -0.1em; + -webkit-transform-origin: 5.1em 5.1em; + transform-origin: 5.1em 5.1em; + -webkit-animation: load2 2s infinite ease 1.5s; + animation: load2 2s infinite ease 1.5s; + } + &:after { + position: absolute; + content: ''; + border-radius: 50%; + width: 5.2em; + height: 10.2em; + background: #ffffff; + border-radius: 0 10.2em 10.2em 0; + top: -0.1em; + left: 4.9em; + -webkit-transform-origin: 0.1em 5.1em; + transform-origin: 0.1em 5.1em; + -webkit-animation: load2 2s infinite ease; + animation: load2 2s infinite ease; + } + @-webkit-keyframes load2 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } + } + @keyframes load2 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } + } +`; diff --git a/src/components/atoms/PairDisplayDiv.tsx b/src/components/atoms/PairDisplayDiv.tsx new file mode 100644 index 00000000..3611e135 --- /dev/null +++ b/src/components/atoms/PairDisplayDiv.tsx @@ -0,0 +1,42 @@ +import React, { FC } from 'react'; +import Typography from '@mui/material/Typography'; +import { WhereWhatPair } from "@wbr-project/wbr-interpret"; +import styled from "styled-components"; + +interface PairDisplayDivProps { + index: string; + pair: WhereWhatPair; +} + +export const PairDisplayDiv: FC = ({ index, pair }) => { + + return ( +
+ + {`Index: ${index}`} + {pair.id ? `, Id: ${pair.id}` : ''} + + + {"Where:"} + + +
{JSON.stringify(pair?.where, undefined, 2)}
+
+ + {"What:"} + + +
{JSON.stringify(pair?.what, undefined, 2)}
+
+
+ ); +} + +const DescriptionWrapper = styled.div` + margin: 0; + font-family: "Roboto","Helvetica","Arial",sans-serif; + font-weight: 400; + font-size: 1rem; + line-height: 1.5; + letter-spacing: 0.00938em; +`; diff --git a/src/components/atoms/RecorderIcon.tsx b/src/components/atoms/RecorderIcon.tsx new file mode 100644 index 00000000..afed1756 --- /dev/null +++ b/src/components/atoms/RecorderIcon.tsx @@ -0,0 +1,23 @@ +import React from 'react'; + +export const RecordingIcon = () => { + return ( + + + + + + + + ); +}; diff --git a/src/components/atoms/buttons/AddButton.tsx b/src/components/atoms/buttons/AddButton.tsx new file mode 100644 index 00000000..716e346f --- /dev/null +++ b/src/components/atoms/buttons/AddButton.tsx @@ -0,0 +1,36 @@ +import { IconButton } from "@mui/material"; +import { Add } from "@mui/icons-material"; +import React, { FC } from "react"; + +interface AddButtonProps { + handleClick: () => void; + size?: "small" | "medium" | "large"; + title?: string; + disabled?: boolean; + hoverEffect?: boolean; + style?: React.CSSProperties; +} + +export const AddButton: FC = ( + { handleClick, + size, + title, + disabled = false, + hoverEffect = true, + style + }) => { + return ( + + {title} + + ); +}; diff --git a/src/components/atoms/buttons/BreakpointButton.tsx b/src/components/atoms/buttons/BreakpointButton.tsx new file mode 100644 index 00000000..ad14e69a --- /dev/null +++ b/src/components/atoms/buttons/BreakpointButton.tsx @@ -0,0 +1,30 @@ +import { IconButton } from "@mui/material"; +import { Circle } from "@mui/icons-material"; + +interface BreakpointButtonProps { + handleClick: () => void; + size?: "small" | "medium" | "large"; + changeColor?: boolean; +} + +export const BreakpointButton = + ({ handleClick, size, changeColor }: BreakpointButtonProps) => { + return ( + + + + ); + }; diff --git a/src/components/atoms/buttons/ClearButton.tsx b/src/components/atoms/buttons/ClearButton.tsx new file mode 100644 index 00000000..4eabf9fa --- /dev/null +++ b/src/components/atoms/buttons/ClearButton.tsx @@ -0,0 +1,17 @@ +import { IconButton } from "@mui/material"; +import { Clear } from "@mui/icons-material"; +import React, { FC } from "react"; + +interface ClearButtonProps { + handleClick: () => void; + size?: "small" | "medium" | "large"; +} + +export const ClearButton: FC = ({ handleClick, size }) => { + return ( + + + + ); +}; diff --git a/src/components/atoms/buttons/EditButton.tsx b/src/components/atoms/buttons/EditButton.tsx new file mode 100644 index 00000000..cfef1a23 --- /dev/null +++ b/src/components/atoms/buttons/EditButton.tsx @@ -0,0 +1,17 @@ +import { IconButton } from "@mui/material"; +import { Edit } from "@mui/icons-material"; +import React, { FC } from "react"; + +interface EditButtonProps { + handleClick: () => void; + size?: "small" | "medium" | "large"; +} + +export const EditButton: FC = ({ handleClick, size }) => { + return ( + + + + ); +}; diff --git a/src/components/atoms/buttons/RemoveButton.tsx b/src/components/atoms/buttons/RemoveButton.tsx new file mode 100644 index 00000000..67dcd6cd --- /dev/null +++ b/src/components/atoms/buttons/RemoveButton.tsx @@ -0,0 +1,17 @@ +import { IconButton } from "@mui/material"; +import { Remove } from "@mui/icons-material"; +import React, { FC } from "react"; + +interface RemoveButtonProps { + handleClick: () => void; + size?: "small" | "medium" | "large"; +} + +export const RemoveButton: FC = ({ handleClick, size }) => { + return ( + + + + ); +}; diff --git a/src/components/atoms/canvas.tsx b/src/components/atoms/canvas.tsx index 6a2f9dea..5152cf5e 100644 --- a/src/components/atoms/canvas.tsx +++ b/src/components/atoms/canvas.tsx @@ -1,22 +1,16 @@ -import React, {useCallback, useEffect, useRef} from 'react'; +import React, { useCallback, useEffect, useRef } from 'react'; import { useSocketStore } from '../../context/socket'; import { getMappedCoordinates } from "../../helpers/inputHelpers"; import { useGlobalInfoStore } from "../../context/globalInfo"; interface CreateRefCallback { - (ref: React.RefObject): void; - } interface CanvasProps { - width: number; - height: number; - onCreateRef: CreateRefCallback; - } /** @@ -40,7 +34,7 @@ const Canvas = ({ width, height, onCreateRef }: CanvasProps) => { }; const lastMousePosition = useRef({ x: 0, y: 0 }); - //const lastWheelPosition = useRef({ deltaX: 0, deltaY: 0 }); + //const lastWheelPosition = useRef({ deltaX: 0, deltaY: 0 }); const onMouseEvent = useCallback((event: MouseEvent) => { if (socket) { @@ -57,12 +51,12 @@ const Canvas = ({ width, height, onCreateRef }: CanvasProps) => { case 'mousemove': const coordinates = getMappedCoordinates(event, canvasRef.current, width, height); if (lastMousePosition.current.x !== coordinates.x || - lastMousePosition.current.y !== coordinates.y) { + lastMousePosition.current.y !== coordinates.y) { lastMousePosition.current = { x: coordinates.x, y: coordinates.y, }; - socket.emit('input:mousemove', { + socket.emit('input:mousemove', { x: coordinates.x, y: coordinates.y, }); @@ -122,21 +116,21 @@ const Canvas = ({ width, height, onCreateRef }: CanvasProps) => { } }; - }else { + } else { console.log('Canvas not initialized'); } }, [onMouseEvent]); return ( - // - + // + ); }; diff --git a/src/components/atoms/texts.tsx b/src/components/atoms/texts.tsx new file mode 100644 index 00000000..e31b9ceb --- /dev/null +++ b/src/components/atoms/texts.tsx @@ -0,0 +1,15 @@ +import styled from "styled-components"; + +export const WarningText = styled.p` + border: 1px solid orange; + display: flex; + margin: 10px; + flex-direction: column; + font-size: small; + background: rgba(255,165,0,0.15); + padding: 5px; + font-family: "Roboto","Helvetica","Arial",sans-serif; + font-weight: 400; + line-height: 1.5; + letter-spacing: 0.00938em; +`