From 9e45e34e25dab5292cf89e4b3a9d2e1b48ad7cb7 Mon Sep 17 00:00:00 2001 From: Kevin Basta Date: Thu, 2 Nov 2023 21:56:35 -0400 Subject: [PATCH] main menu refactor --- src/App.tsx | 2 +- src/color-palette/PaletteColorsStyles.tsx | 2 +- src/menu/CreateCanvas.tsx | 55 +++++++++ src/menu/CreateCanvasStyles.tsx | 20 ++++ .../{GifStorageItem.tsx => GIFStorage.tsx} | 110 +++++++++++------- src/menu/GIFStorageStyles.tsx | 47 ++++++++ src/menu/GifStorageContext.tsx | 17 --- src/menu/GifStorageContextStyles.tsx | 16 --- src/menu/GifStorageItemStyles.tsx | 73 ------------ src/menu/MainMenu.tsx | 50 ++------ src/menu/MainMenuStyles.tsx | 19 --- src/options/CanvasOptions.tsx | 9 +- src/options/FrameOptions.tsx | 16 +-- src/shared-styles/Button.tsx | 37 ++++++ src/shared-styles/Image.tsx | 9 ++ src/shared-styles/Input.tsx | 20 +++- src/shared-styles/Text.tsx | 33 ++++++ src/shared/SharedStyledComponents.tsx | 46 -------- 18 files changed, 309 insertions(+), 272 deletions(-) create mode 100644 src/menu/CreateCanvas.tsx create mode 100644 src/menu/CreateCanvasStyles.tsx rename src/menu/{GifStorageItem.tsx => GIFStorage.tsx} (51%) create mode 100644 src/menu/GIFStorageStyles.tsx delete mode 100644 src/menu/GifStorageContext.tsx delete mode 100644 src/menu/GifStorageContextStyles.tsx delete mode 100644 src/menu/GifStorageItemStyles.tsx delete mode 100644 src/shared/SharedStyledComponents.tsx diff --git a/src/App.tsx b/src/App.tsx index 8c94087..81c10d9 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -30,7 +30,7 @@ const GlobalStyles = createGlobalStyle` --tertiary-color: #E0E2DB; --tertiary-color-active: #cacbc5; --quaternary-color: #000000; - --quinary-color: ; + --quinary-color: #4795d4; --senary-color: ; --scroll-background-color: #E0E2DB; diff --git a/src/color-palette/PaletteColorsStyles.tsx b/src/color-palette/PaletteColorsStyles.tsx index ce386f2..f4a4631 100644 --- a/src/color-palette/PaletteColorsStyles.tsx +++ b/src/color-palette/PaletteColorsStyles.tsx @@ -13,4 +13,4 @@ export const PaletteColorsWrapper = styled.div` justify-content: flex-start; align-content: flex-start; flex-wrap: wrap; -` +`; diff --git a/src/menu/CreateCanvas.tsx b/src/menu/CreateCanvas.tsx new file mode 100644 index 0000000..495b3aa --- /dev/null +++ b/src/menu/CreateCanvas.tsx @@ -0,0 +1,55 @@ +import { useState } from "react"; +import { CreateCanvasWrapper, SizePickerContainer } from "./CreateCanvasStyles"; +import { Label, Title } from "../shared-styles/Text"; +import { InputStandard } from "../shared-styles/Input"; +import { maxCanvasSize, minCanvasSize } from "../shared/Constants"; +import { updateInput, validateAndConvertInput } from "../shared/SharedUtilities"; +import { ButtonLarge } from "../shared-styles/Button"; + +interface CreateCanvasProps { + initCanvas: Function; + initCanvasFromSave: Function; +} + +export function CreateCanvas(props: CreateCanvasProps) { + const [name, setName] = useState(''); + const [width, setWidth] = useState('10'); + const [height, setHeight] = useState('10'); + + return ( + <> + + Canvas Options + + + + {let element: HTMLInputElement = e.target as HTMLInputElement; element.focus();}} + onChange={(e) => {setName(e.target.value)}}/> + + + {let element: HTMLInputElement = e.target as HTMLInputElement; element.focus();}} + onChange={(e) => {updateInput(e, setWidth, 1, 3000)}}/> + + + {let element: HTMLInputElement = e.target as HTMLInputElement; element.focus();}} + onChange={(e) => {updateInput(e, setHeight, 1, 3000)}}/> + + + { + props.initCanvas(name, validateAndConvertInput(width, minCanvasSize), validateAndConvertInput(height, minCanvasSize)); + }}>create a canvas + + + ); +} diff --git a/src/menu/CreateCanvasStyles.tsx b/src/menu/CreateCanvasStyles.tsx new file mode 100644 index 0000000..2f16978 --- /dev/null +++ b/src/menu/CreateCanvasStyles.tsx @@ -0,0 +1,20 @@ +import styled from "styled-components"; + +export const CreateCanvasWrapper = styled.div` + width: min(70vw, 70vh); + padding: max(4vw, 4vh); + gap: 3vh; + + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + background-color: var(--secondary-color); +`; + +export const SizePickerContainer = styled.div` + width: inherit; + display: grid; + grid-template-columns: 4fr 10fr; + grid-row-gap: min(1vw, 1vh); +`; diff --git a/src/menu/GifStorageItem.tsx b/src/menu/GIFStorage.tsx similarity index 51% rename from src/menu/GifStorageItem.tsx rename to src/menu/GIFStorage.tsx index 1104458..14d9f51 100644 --- a/src/menu/GifStorageItem.tsx +++ b/src/menu/GIFStorage.tsx @@ -1,13 +1,14 @@ import { useState, useEffect } from "react"; -import { GifStorageItemButton, GifStorageItemPreview, GifStorageItemPreviewWrapper, GifStorageItemTitle, GifStorageItemWrapper } from "./GifStorageItemStyles"; +import { GIFStorageItemWrapper, GIFStorageWrapper, GIFStorageItemPreviewWrapper, GIFStorageItemTitle } from "./GIFStorageStyles"; import { gifRecord } from "../shared/Formats"; - +import { ButtonGIFStorageItem } from "../shared-styles/Button"; +import { ImgGIFStorageItemPreview } from "../shared-styles/Image"; interface GifStorageItemsProps { initCanvasFromSave: Function; } -export function GifStorageItems(props: GifStorageItemsProps) { +export function GIFStorage(props: GifStorageItemsProps) { const [localStorageGIFs, setLocalStorageGIFs] = useState>(JSON.parse(localStorage.getItem("GIFS") || "[]")); function deleteSavedGIF(deletingIndex: number) { @@ -22,24 +23,6 @@ export function GifStorageItems(props: GifStorageItemsProps) { setLocalStorageGIFs(() => { return newGIFs }); } - function downloadSavedGIF(index: number) { - const blob = new Blob([JSON.stringify(localStorageGIFs[index])], { type: "application/json" }); - const link = document.createElement("a"); - - link.download = localStorageGIFs[index].canvas.canvasName + ".json"; - link.href = window.URL.createObjectURL(blob); - link.dataset.downloadurl = ["application/json", link.download, link.href].join(":"); - - const evt = new MouseEvent("click", { - view: window, - bubbles: true, - cancelable: true, - }); - - link.dispatchEvent(evt); - link.remove() - } - function uploadJsonGIF() { var files = (document.getElementById('jsonFile') as HTMLInputElement).files; console.log(files); @@ -60,6 +43,24 @@ export function GifStorageItems(props: GifStorageItemsProps) { fr.readAsText(files.item(0), "application/json"); } + function downloadSavedGIF(index: number) { + const blob = new Blob([JSON.stringify(localStorageGIFs[index])], { type: "application/json" }); + const link = document.createElement("a"); + + link.download = localStorageGIFs[index].canvas.canvasName + ".json"; + link.href = window.URL.createObjectURL(blob); + link.dataset.downloadurl = ["application/json", link.download, link.href].join(":"); + + const evt = new MouseEvent("click", { + view: window, + bubbles: true, + cancelable: true, + }); + + link.dispatchEvent(evt); + link.remove() + } + function getSavedGIFs() { if (localStorageGIFs.length == 0) { return; @@ -79,19 +80,40 @@ export function GifStorageItems(props: GifStorageItemsProps) { } elements.push( - - - - + + + + - {currentGIF.canvas.canvasName || "GIF SAVE #" + (i + 1) } + + { currentGIF.canvas.canvasName || "GIF SAVE #" + (i + 1) } + - props.initCanvasFromSave(currentGIF.canvas, currentGIF.frames, currentGIF.globalColorTable)}>load - downloadSavedGIF(i)}>download data - deleteSavedGIF(i)}>delete - + { + props.initCanvasFromSave(currentGIF.canvas, + currentGIF.frames, + currentGIF.globalColorTable) + }}>draw + + { + downloadSavedGIF(i) + }}>download + + { + deleteSavedGIF(i) + }}>delete + ) } @@ -102,17 +124,23 @@ export function GifStorageItems(props: GifStorageItemsProps) { localStorage.setItem("GIFS", JSON.stringify(localStorageGIFs)); }, [localStorageGIFs]); - return ( <> - { - getSavedGIFs() - } - - Upload a json file - - uploadJsonGIF()}>Upload File - + + { + getSavedGIFs() + } + + Upload a json file + + { + uploadJsonGIF() + }}>upload + + ); } diff --git a/src/menu/GIFStorageStyles.tsx b/src/menu/GIFStorageStyles.tsx new file mode 100644 index 0000000..f277224 --- /dev/null +++ b/src/menu/GIFStorageStyles.tsx @@ -0,0 +1,47 @@ +import styled from "styled-components"; + +export const GIFStorageWrapper = styled.div` + width: min(70vw, 70vh); + height: 20vh; + padding: max(4vw, 4vh); + + gap: 3vh; + overflow-y: scroll; + + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + background-color: var(--secondary-color); +`; + +export const GIFStorageItemWrapper = styled.div` + width: min(63vw, 63vh); + height: 75px; + padding: max(1.5vw, 1.5vh); + gap: 10px; + + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-start; + background-color: var(--primary-color); +`; + +export const GIFStorageItemPreviewWrapper = styled.div` + height: 90%; + aspect-ratio: 1/1; + margin-right: 10px; +`; + +export const GIFStorageItemTitle = styled.p` + font-size: var(--font-size-sm); + color: var(--tertiary-color); + flex-grow: 1; + margin: 0px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +`; + + diff --git a/src/menu/GifStorageContext.tsx b/src/menu/GifStorageContext.tsx deleted file mode 100644 index 1a87e0d..0000000 --- a/src/menu/GifStorageContext.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { GifStorageWrapper } from "./GifStorageContextStyles"; -import { GifStorageItems } from "./GifStorageItem"; - -interface GifStorageContextProps { - initCanvasFromSave: Function; -} - -export function GifStorageContext(props: GifStorageContextProps) { - - return ( - <> - - - - - ); -} \ No newline at end of file diff --git a/src/menu/GifStorageContextStyles.tsx b/src/menu/GifStorageContextStyles.tsx deleted file mode 100644 index dccdc61..0000000 --- a/src/menu/GifStorageContextStyles.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import styled from "styled-components"; - -export const GifStorageWrapper = styled.div` - width: min(70vw, 70vh); - height: 20vh; - padding: max(4vw, 4vh); - - gap: 3vh; - overflow-y: scroll; - - display: flex; - flex-direction: column; - align-items: center; - justify-content: flex-start; - background-color: var(--secondary-color); -`; diff --git a/src/menu/GifStorageItemStyles.tsx b/src/menu/GifStorageItemStyles.tsx deleted file mode 100644 index 6b1386c..0000000 --- a/src/menu/GifStorageItemStyles.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import styled from "styled-components"; - -export const GifStorageItemWrapper = styled.div` - width: min(63vw, 63vh); - height: 75px; - padding: max(1.5vw, 1.5vh); - gap: 10px; - - display: flex; - flex-direction: row; - align-items: center; - justify-content: flex-start; - background-color: var(--primary-color); -`; - - - -export const GifStorageItemTitle = styled.p` - font-size: var(--font-size-sm); - color: var(--tertiary-color); - flex-grow: 1; - margin: 0px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -`; - -export const GifStorageItemPreviewWrapper = styled.div` - height: 90%; - aspect-ratio: 1/1; -`; - -export const GifStorageItemPreview = styled.img<{ $widthratio: number; $heightratio: number; }>` - max-width: 90%; - max-height: 90%; - - aspect-ratio: ${props => props.$widthratio / props.$heightratio}; -`; - -export const GifStorageItemButton = styled.button<{ $disabled?: boolean; }>` - background-color: var(--tertiary-color); - color: black; - border: 2px solid #555555; - border: none; - - text-align: center; - text-decoration: none; - display: inline-block; - font-size: var(--font-size-sm); - - box-shadow: var(--button-shadow-small); - transform: var(--button-transform-small); - - ${props => props.$disabled ? - ` - opacity: 0.6; - cursor: not-allowed; - ` - : - ` - cursor: pointer; - transition: 0.01s; - - &:hover { - background-color: var(--tertiary-color-active); - } - - &:active { - box-shadow: var(--button-shadow-active); - transform: var(--button-transform-active); - } - `}; -`; diff --git a/src/menu/MainMenu.tsx b/src/menu/MainMenu.tsx index 3355015..704829b 100644 --- a/src/menu/MainMenu.tsx +++ b/src/menu/MainMenu.tsx @@ -1,10 +1,8 @@ import { useState } from "react"; -import { Input, Label, LargeTitle, Title } from "../shared/SharedStyledComponents"; -import { updateInput, validateAndConvertInput } from "../shared/SharedUtilities"; -import { CreateCanvasWrapper, MenuWrapper, SizePickerContainer } from "./MainMenuStyles"; -import { maxCanvasSize, minCanvasSize } from "../shared/Constants"; -import { GifStorageContext } from "./GifStorageContext"; -import { ButtonLarge } from "../shared-styles/Button"; +import { LargeTitle } from "../shared-styles/Text"; +import { MenuWrapper } from "./MainMenuStyles"; +import { GIFStorage } from "./GIFStorage"; +import { CreateCanvas } from "./CreateCanvas"; interface TitleScreenProps { initCanvas: Function; @@ -12,47 +10,13 @@ interface TitleScreenProps { } export function MainMenu(props: TitleScreenProps) { - const [name, setName] = useState(''); - const [width, setWidth] = useState('10'); - const [height, setHeight] = useState('10'); - return ( <> DRAW-A-GIF - - Canvas Options - - - - {let element: HTMLInputElement = e.target as HTMLInputElement; element.focus();}} - onChange={(e) => {setName(e.target.value)}}/> - - - {let element: HTMLInputElement = e.target as HTMLInputElement; element.focus();}} - onChange={(e) => {updateInput(e, setWidth, 1, 3000)}}/> - - - {let element: HTMLInputElement = e.target as HTMLInputElement; element.focus();}} - onChange={(e) => {updateInput(e, setHeight, 1, 3000)}}/> - - - { - props.initCanvas(name, validateAndConvertInput(width, minCanvasSize), validateAndConvertInput(height, minCanvasSize)); - }}>create a canvas - - + + ); diff --git a/src/menu/MainMenuStyles.tsx b/src/menu/MainMenuStyles.tsx index 028404e..bbcc875 100644 --- a/src/menu/MainMenuStyles.tsx +++ b/src/menu/MainMenuStyles.tsx @@ -19,22 +19,3 @@ export const MenuWrapper = styled.div` justify-content: flex-start; gap: 1vh; `; - -export const CreateCanvasWrapper = styled.div` - width: min(70vw, 70vh); - padding: max(4vw, 4vh); - gap: 3vh; - - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - background-color: var(--secondary-color); -`; - -export const SizePickerContainer = styled.div` - width: inherit; - display: grid; - grid-template-columns: 4fr 10fr; - grid-row-gap: min(1vw, 1vh); -`; diff --git a/src/options/CanvasOptions.tsx b/src/options/CanvasOptions.tsx index c8955dc..b52c3fa 100644 --- a/src/options/CanvasOptions.tsx +++ b/src/options/CanvasOptions.tsx @@ -1,12 +1,13 @@ import { useState } from "react"; import { canvasType, frameType } from "../shared/Formats"; import { CanvasOptionsWrapper } from "./CanvasOptionsStyles"; -import { Input, Label, Title } from "../shared/SharedStyledComponents"; +import { Label, Title } from "../shared-styles/Text"; import { maxCanvasSize, maxQualityMultiplier, minCanvasSize, minQualityMultiplier, widthCanvasOptions } from "../shared/Constants"; import { returnInput } from "../shared/SharedUtilities"; import { ButtonCanvasTab, ButtonLarge } from "../shared-styles/Button"; import { OptionsInputLabelWrapper, OptionsSection, OptionsWrapper } from "./OptionsWrappers"; import { getCanvasUpdatedQualityMultiplier } from "../core/CanvasCore"; +import { InputStandard } from "../shared-styles/Input"; interface CanvasOptionsProps { canvas: canvasType, @@ -69,7 +70,7 @@ export function CanvasOptions(props: CanvasOptionsProps) { - updateQualityMultiplier(e)} /> - updateCanvasWidth(e)} */ /> - - updateDisposalMethod(parseInt(e.target.value))}> - Normal - Keep - Previous State - + Normal + Keep + Previous State + - ` content: "${props => props.$icon}"; } `; + +export const ButtonGIFStorageItem = styled.button<{ $disabled?: boolean; }>` + background-color: #638796; + height: 100%; + aspect-ratio: 1/1; + color: black; + border: 2px solid #555555; + border: none; + + text-align: center; + text-decoration: none; + display: inline-block; + font-size: var(--font-size-medium); + + box-shadow: var(--button-shadow-small); + transform: var(--button-transform-small); + + ${props => props.$disabled ? + ` + opacity: 0.6; + cursor: not-allowed; + ` + : + ` + cursor: pointer; + transition: 0.01s; + + &:hover { + background-color: #4F6D7A; + } + + &:active { + box-shadow: var(--button-shadow-active); + transform: var(--button-transform-active); + } + `}; +`; diff --git a/src/shared-styles/Image.tsx b/src/shared-styles/Image.tsx index e69de29..1880cfe 100644 --- a/src/shared-styles/Image.tsx +++ b/src/shared-styles/Image.tsx @@ -0,0 +1,9 @@ +import styled from "styled-components"; + + +export const ImgGIFStorageItemPreview = styled.img<{ $widthratio: number; $heightratio: number; }>` + max-width: 90%; + max-height: 90%; + + aspect-ratio: ${props => props.$widthratio / props.$heightratio}; +`; \ No newline at end of file diff --git a/src/shared-styles/Input.tsx b/src/shared-styles/Input.tsx index 8fec828..40434bb 100644 --- a/src/shared-styles/Input.tsx +++ b/src/shared-styles/Input.tsx @@ -1,5 +1,18 @@ import styled from "styled-components"; +export const InputStandard = styled.input` + width: 100%; + background-color: var(--tertiary-color); + font-family: 'DotGothic16', sans-serif; + + place-self: center; + text-align: center; + cursor: text; + margin: 0px; + padding: 0px; + font-size: var(--font-size-sm); +`; + export const InputToolSize = styled.input` aspect-ratio: 1 / 1; width: var(--tool-item-width); @@ -28,7 +41,7 @@ export const InputToolSize = styled.input` } `; -export const SelectTransition = styled.select` +export const SelectTransitionType = styled.select` width: 100%; height: max(2vh, var(--font-size-large)); font-size: var(--font-size-sm); @@ -36,7 +49,8 @@ export const SelectTransition = styled.select` margin: 0px; `; -export const OptionTransition = styled.option` +export const OptionTransitionType = styled.option` font-family: 'DotGothic16', sans-serif; font-size: var(--font-size-sm); -`; \ No newline at end of file +`; + diff --git a/src/shared-styles/Text.tsx b/src/shared-styles/Text.tsx index e69de29..7f0efe7 100644 --- a/src/shared-styles/Text.tsx +++ b/src/shared-styles/Text.tsx @@ -0,0 +1,33 @@ +import styled from "styled-components"; + +export const LargeTitle = styled.p` + font-size: var(--font-size-extra-large); + color: var(--tertiary-color); + + user-drag: none; + -webkit-user-drag: none; + user-select: none; + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; +`; + +export const Title = styled.p` + font-size: var(--font-size-large); + color: var(--tertiary-color); + margin: 0px; + + user-drag: none; + -webkit-user-drag: none; + user-select: none; + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; +`; + +export const Label = styled.p` + width: 100%; + color: var(--tertiary-color-active); + font-size: var(--font-size-medium); + margin: 0px; +`; diff --git a/src/shared/SharedStyledComponents.tsx b/src/shared/SharedStyledComponents.tsx deleted file mode 100644 index 1c80ee1..0000000 --- a/src/shared/SharedStyledComponents.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import styled from "styled-components"; - -export const LargeTitle = styled.p` - font-size: var(--font-size-extra-large); - color: var(--tertiary-color); - - user-drag: none; - -webkit-user-drag: none; - user-select: none; - -moz-user-select: none; - -webkit-user-select: none; - -ms-user-select: none; -`; - -export const Title = styled.p` - font-size: var(--font-size-large); - color: var(--tertiary-color); - margin: 0px; - - user-drag: none; - -webkit-user-drag: none; - user-select: none; - -moz-user-select: none; - -webkit-user-select: none; - -ms-user-select: none; -`; - -export const Label = styled.p` - width: 100%; - color: var(--tertiary-color-active); - font-size: var(--font-size-medium); - margin: 0px; -`; - -export const Input = styled.input` - width: 100%; - background-color: var(--tertiary-color); - font-family: 'DotGothic16', sans-serif; - - place-self: center; - text-align: center; - cursor: text; - margin: 0px; - padding: 0px; - font-size: var(--font-size-sm); -`;