diff --git a/src/Components/Editor/Editor.tsx b/src/Components/Editor/Editor.tsx index fcd62f9..75bf90c 100644 --- a/src/Components/Editor/Editor.tsx +++ b/src/Components/Editor/Editor.tsx @@ -91,16 +91,15 @@ const Editor: React.FunctionComponent = (props) => { setHistory, setHistoryCurrentStep )} - OnPropertyChange={(key, value) => OnPropertyChange( - key, value, + OnPropertyChange={(key, value, isStyle) => OnPropertyChange( + key, value, isStyle, history, historyCurrentStep, setHistory, setHistoryCurrentStep )} - OnPropertiesSubmit={(event, properties) => OnPropertiesSubmit( + OnPropertiesSubmit={(event) => OnPropertiesSubmit( event, - properties, history, historyCurrentStep, setHistory, diff --git a/src/Components/Editor/PropertiesOperations.ts b/src/Components/Editor/PropertiesOperations.ts index 4bd4c2d..cccc363 100644 --- a/src/Components/Editor/PropertiesOperations.ts +++ b/src/Components/Editor/PropertiesOperations.ts @@ -1,7 +1,6 @@ import { Dispatch, SetStateAction } from 'react'; import { IContainerModel, ContainerModel } from '../../Interfaces/IContainerModel'; import { IHistoryState } from '../../Interfaces/IHistoryState'; -import IProperties from '../../Interfaces/IProperties'; import { findContainerById } from '../../utils/itertools'; import { getCurrentHistory } from './Editor'; import { RecalculatePhysics } from './Behaviors/RigidBodyBehaviors'; @@ -17,6 +16,7 @@ import { ImposePosition } from './Behaviors/AnchorBehaviors'; export function OnPropertyChange( key: string, value: string | number | boolean, + isStyle: boolean = false, fullHistory: IHistoryState[], historyCurrentStep: number, setHistory: Dispatch>, @@ -37,10 +37,14 @@ export function OnPropertyChange( throw new Error('[OnPropertyChange] Container model was not found among children of the main container!'); } - if (INPUT_TYPES[key] === 'number') { - (container.properties as any)[key] = Number(value); + if (isStyle) { + (container.properties.style as any)[key] = value; } else { - (container.properties as any)[key] = value; + if (INPUT_TYPES[key] === 'number') { + (container.properties as any)[key] = Number(value); + } else { + (container.properties as any)[key] = value; + } } if (container.properties.isAnchor) { @@ -70,7 +74,6 @@ export function OnPropertyChange( */ export function OnPropertiesSubmit( event: React.SyntheticEvent, - properties: IProperties, fullHistory: IHistoryState[], historyCurrentStep: number, setHistory: Dispatch>, @@ -92,15 +95,33 @@ export function OnPropertiesSubmit( throw new Error('[OnPropertyChange] Container model was not found among children of the main container!'); } - for (const property in properties) { + // Assign container properties + for (const property in container.properties) { const input = (event.target as HTMLFormElement).querySelector(`#${property}`); if (input instanceof HTMLInputElement) { (container.properties as any)[property] = input.value; + if (INPUT_TYPES[property] === 'number') { (container.properties as any)[property] = Number(input.value); - } else { - (container.properties as any)[property] = input.value; + continue; } + + (container.properties as any)[property] = input.value; + } + } + + // Assign cssproperties + for (const styleProperty in container.properties.style) { + const input = (event.target as HTMLFormElement).querySelector(`#${styleProperty}`); + if (input instanceof HTMLInputElement) { + (container.properties.style as any)[styleProperty] = input.value; + + if (INPUT_TYPES[styleProperty] === 'number') { + (container.properties.style as any)[styleProperty] = Number(input.value); + continue; + } + + (container.properties.style as any)[styleProperty] = input.value; } } diff --git a/src/Components/ElementsSidebar/ElementsSidebar.tsx b/src/Components/ElementsSidebar/ElementsSidebar.tsx index ab3efdd..21eb6b2 100644 --- a/src/Components/ElementsSidebar/ElementsSidebar.tsx +++ b/src/Components/ElementsSidebar/ElementsSidebar.tsx @@ -14,8 +14,8 @@ interface IElementsSidebarProps { isOpen: boolean isHistoryOpen: boolean SelectedContainer: IContainerModel | null - OnPropertyChange: (key: string, value: string | number | boolean) => void - OnPropertiesSubmit: (event: React.FormEvent, properties: ContainerProperties) => void + OnPropertyChange: (key: string, value: string | number | boolean, isStyle?: boolean) => void + OnPropertiesSubmit: (event: React.FormEvent) => void SelectContainer: (container: IContainerModel) => void DeleteContainer: (containerid: string) => void AddContainer: (index: number, type: string, parent: string) => void diff --git a/src/Components/InputGroup/InputGroup.tsx b/src/Components/InputGroup/InputGroup.tsx new file mode 100644 index 0000000..bc794d3 --- /dev/null +++ b/src/Components/InputGroup/InputGroup.tsx @@ -0,0 +1,48 @@ +import * as React from 'react'; + +interface IInputGroupProps { + labelKey?: string + labelText: string + inputKey: string + labelClassName: string + inputClassName: string + type: string + value?: string + checked?: boolean + defaultValue?: string + defaultChecked?: boolean + isDisabled?: boolean + onChange?: (event: React.ChangeEvent) => void +} + +const className = ` + w-full + text-xs font-medium transition-all text-gray-800 mt-1 px-3 py-2 + bg-white border-2 border-white rounded-lg placeholder-gray-800 + focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500 + disabled:bg-slate-300 disabled:text-gray-500 disabled:border-slate-300 disabled:shadow-none`; + +export const InputGroup: React.FunctionComponent = (props) => { + return <> + + + ; +}; diff --git a/src/Components/Properties/DynamicForm.tsx b/src/Components/Properties/DynamicForm.tsx new file mode 100644 index 0000000..7ef1031 --- /dev/null +++ b/src/Components/Properties/DynamicForm.tsx @@ -0,0 +1,119 @@ +import * as React from 'react'; +import IProperties from '../../Interfaces/IProperties'; +import { InputGroup } from '../InputGroup/InputGroup'; + +interface IDynamicFormProps { + properties: IProperties + onChange: (key: string, value: string | number | boolean, isStyle?: boolean) => void +} + +const getCSSInputs = ( + properties: IProperties, + onChange: (key: string, value: string | number | boolean, isStyle?: boolean) => void +): JSX.Element[] => { + const groupInput: JSX.Element[] = []; + for (const key in properties.style) { + groupInput.push( onChange(key, event.target.value, true)} + />); + } + return groupInput; +}; + +const DynamicForm: React.FunctionComponent = (props) => { + return ( +
+ + + props.onChange('x', event.target.value)} + /> + props.onChange('y', event.target.value)} + /> + props.onChange('width', event.target.value)} + /> + props.onChange('height', event.target.value)} + /> + props.onChange('isRigidBody', event.target.checked)} + /> + props.onChange('isAnchor', event.target.checked)} + /> + props.onChange('xPositionReference', event.target.value)} + /> + { getCSSInputs(props.properties, props.onChange) } +
+ ); +}; + +export default DynamicForm; diff --git a/src/Components/Properties/Form.tsx b/src/Components/Properties/Form.tsx new file mode 100644 index 0000000..bc0f508 --- /dev/null +++ b/src/Components/Properties/Form.tsx @@ -0,0 +1,24 @@ +import * as React from 'react'; +import IProperties from '../../Interfaces/IProperties'; +import DynamicForm from './DynamicForm'; +import StaticForm from './StaticForm'; + +interface IFormProps { + properties: IProperties + isDynamicInput: boolean + onChange: (key: string, value: string | number | boolean, isStyle?: boolean) => void + onSubmit: (event: React.FormEvent) => void +} + +export const Form: React.FunctionComponent = (props) => { + if (props.isDynamicInput) { + return ; + } + return ; +}; diff --git a/src/Components/Properties/Properties.tsx b/src/Components/Properties/Properties.tsx index 516f23d..b72eead 100644 --- a/src/Components/Properties/Properties.tsx +++ b/src/Components/Properties/Properties.tsx @@ -1,12 +1,12 @@ import React, { useState } from 'react'; -import ContainerProperties from '../../Interfaces/IProperties'; +import IProperties from '../../Interfaces/IProperties'; import { ToggleButton } from '../ToggleButton/ToggleButton'; -import { INPUT_TYPES } from './PropertiesInputTypes'; +import { Form } from './Form'; interface IPropertiesProps { - properties?: ContainerProperties - onChange: (key: string, value: string | number | boolean) => void - onSubmit: (event: React.FormEvent, properties: ContainerProperties) => void + properties?: IProperties + onChange: (key: string, value: string | number | boolean, isStyle?: boolean) => void + onSubmit: (event: React.FormEvent) => void } export const Properties: React.FC = (props: IPropertiesProps) => { @@ -16,26 +16,6 @@ export const Properties: React.FC = (props: IPropertiesProps) return
; } - const groupInput: React.ReactNode[] = []; - Object - .entries(props.properties) - .forEach((pair) => handleProperties(pair, groupInput, isDynamicInput, props.onChange)); - - const form = isDynamicInput - ?
- { groupInput } -
- :
props.onSubmit(event, props.properties as ContainerProperties)} - > - -
- { groupInput } -
-
- ; - return (
= (props: IPropertiesProps) checked={isDynamicInput} onChange={() => setIsDynamicInput(!isDynamicInput)} /> - { form } +
); -}; - -const handleProperties = ( - [key, value]: [string, string | number], - groupInput: React.ReactNode[], - isDynamicInput: boolean, - onChange: (key: string, value: string | number | boolean) => void -): void => { - const id = `property-${key}`; - let type = 'text'; - let checked; - - /// hardcoded stuff for ergonomy /// - if (typeof value === 'boolean') { - checked = value; - } - - if (key in INPUT_TYPES) { - type = INPUT_TYPES[key]; - } - - const className = ` - w-full - text-xs font-medium transition-all text-gray-800 mt-1 px-3 py-2 - bg-white border-2 border-white rounded-lg placeholder-gray-800 - focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500 - disabled:bg-slate-300 disabled:text-gray-500 disabled:border-slate-300 disabled:shadow-none`; - const isDisabled = ['id', 'parentId'].includes(key); - const input = isDynamicInput - ? { - if (type === 'checkbox') { - onChange(key, event.target.checked); - return; - } - onChange(key, event.target.value); - }} - disabled={isDisabled} - /> - : ; - - groupInput.push( - - ); - groupInput.push(input); -}; +}; \ No newline at end of file diff --git a/src/Components/Properties/StaticForm.tsx b/src/Components/Properties/StaticForm.tsx new file mode 100644 index 0000000..06a186e --- /dev/null +++ b/src/Components/Properties/StaticForm.tsx @@ -0,0 +1,112 @@ +import * as React from 'react'; +import IProperties from '../../Interfaces/IProperties'; +import { InputGroup } from '../InputGroup/InputGroup'; + +interface IStaticFormProps { + properties: IProperties + onSubmit: (event: React.FormEvent) => void +} + +const getCSSInputs = (properties: IProperties): JSX.Element[] => { + const groupInput: JSX.Element[] = []; + for (const key in properties.style) { + groupInput.push(); + } + return groupInput; +}; + +const StaticForm: React.FunctionComponent = (props) => { + return ( props.onSubmit(event)} + > + +
+ + + + + + + + + + { getCSSInputs(props.properties) } +
+ ); +}; + +export default StaticForm; diff --git a/src/Components/UI/UI.tsx b/src/Components/UI/UI.tsx index 4fa36e6..c57daee 100644 --- a/src/Components/UI/UI.tsx +++ b/src/Components/UI/UI.tsx @@ -8,7 +8,6 @@ import { IHistoryState } from '../../Interfaces/IHistoryState'; import { PhotographIcon, UploadIcon } from '@heroicons/react/outline'; import { FloatingButton } from '../FloatingButton/FloatingButton'; import { Bar } from '../Bar/Bar'; -import IProperties from '../../Interfaces/IProperties'; interface IUIProps { current: IHistoryState @@ -17,8 +16,8 @@ interface IUIProps { AvailableContainers: IAvailableContainer[] SelectContainer: (container: ContainerModel) => void DeleteContainer: (containerId: string) => void - OnPropertyChange: (key: string, value: string | number | boolean) => void - OnPropertiesSubmit: (event: React.FormEvent, properties: IProperties) => void + OnPropertyChange: (key: string, value: string | number | boolean, isStyle?: boolean) => void + OnPropertiesSubmit: (event: React.FormEvent) => void AddContainerToSelectedContainer: (type: string) => void AddContainer: (index: number, type: string, parentId: string) => void SaveEditorAsJSON: () => void