From 1b03ee7a905b7e317dd47ad0ebef9137033fe268 Mon Sep 17 00:00:00 2001 From: Chris Griffing Date: Sun, 3 Nov 2024 14:20:34 -0800 Subject: [PATCH] fix: use a store instead of individual signals --- playgrounds/app/src/components/Editor.tsx | 298 +++++++++--------- playgrounds/app/src/routes/index.tsx | 124 ++------ .../app/src/routes/snippets/[snippetId].tsx | 59 +--- playgrounds/app/src/types.ts | 15 +- 4 files changed, 207 insertions(+), 289 deletions(-) diff --git a/playgrounds/app/src/components/Editor.tsx b/playgrounds/app/src/components/Editor.tsx index 5cb3d80..3ca89b5 100644 --- a/playgrounds/app/src/components/Editor.tsx +++ b/playgrounds/app/src/components/Editor.tsx @@ -40,10 +40,18 @@ import { DialogHeader, DialogTitle, } from '~/components/ui/dialog' -import { createMemo, createResource, createSignal, onCleanup, Setter, Show } from 'solid-js' +import { + createEffect, + createMemo, + createResource, + createSignal, + onCleanup, + Setter, + Show, +} from 'solid-js' import { createHighlighter, bundledThemes, bundledLanguages } from 'shiki' import { ShikiMagicMove } from 'shiki-magic-move/solid' -import { AnimationFrameConfig } from '~/types' +import { AnimationFrameConfig, SnippetSettings } from '~/types' import { authFetch } from '~/lib/utils' import { useNavigate } from '@solidjs/router' import { authToken } from '~/lib/store' @@ -51,6 +59,7 @@ import { toast } from 'solid-sonner' import { Separator } from './ui/separator' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select' import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from './ui/accordion' +import { SetStoreFunction } from 'solid-js/store' const animationSeconds = 1 const animationFPS = 10 @@ -78,46 +87,8 @@ const bgTypeOptions: SelectOption[] = [ interface EditorProps { snippetId?: string - startCode: string - setStartCode: Setter - endCode: string - setEndCode: Setter - snippetWidth: number - setSnippetWidth: Setter - yPadding: number - setYPadding: Setter - xPadding: number - setXPadding: Setter - shadowEnabled: boolean - setShadowEnabled: Setter - shadowOffsetY: number - setShadowOffsetY: Setter - shadowBlur: number - setShadowBlur: Setter - shadowColor: string - setShadowColor: Setter - shadowOpacity: number - setShadowOpacity: Setter - bgType: 'solid' | 'linearGradient' - setBgType: Setter<'solid' | 'linearGradient'> - bgColor: string - setBgColor: Setter - bgGradientColorStart: string - setBgGradientColorStart: Setter - bgGradientColorEnd: string - setBgGradientColorEnd: Setter - bgGradientDirection: number - setBgGradientDirection: Setter - fontSize: number - setFontSize: Setter - fontFamily: string - setFontFamily: Setter - language: string - setLanguage: Setter - theme: string - setTheme: Setter - // TODO: If the app grows, this logic should be surfaced to the top level route - title?: string + snippetSettings: SnippetSettings + setSnippetSettings: SetStoreFunction } export default function Editor(props: EditorProps) { @@ -130,14 +101,14 @@ export default function Editor(props: EditorProps) { width: number height: number }>() - const [code, setCode] = createSignal(props.startCode) - const [hiddenCode, setHiddenCode] = createSignal(props.startCode) + const [code, setCode] = createSignal(props.snippetSettings.codeLeft) + const [hiddenCode, setHiddenCode] = createSignal(props.snippetSettings.codeLeft) const [isResizing, setIsResizing] = createSignal(false) const [isLooping, setIsLooping] = createSignal(true) const [isGenerating, setIsGenerating] = createSignal(false) const [gifDataUrl, setGifDataUrl] = createSignal('') const [isShowingGifDialog, setIsShowingGifDialog] = createSignal(false) - const [title, setTitle] = createSignal(props.title) + const [title, setTitle] = createSignal(props.snippetSettings.title) const [isSaving, setIsSaving] = createSignal(false) const [highlighter] = createResource(async () => { @@ -149,18 +120,23 @@ export default function Editor(props: EditorProps) { return newHighlighter }) + createEffect(() => { + setCode(props.snippetSettings.codeLeft) + setHiddenCode(props.snippetSettings.codeLeft) + }) + const intervalId = setInterval(() => { if ( selectedTab() === 'output' && - props.startCode !== '' && - props.endCode !== '' && + props.snippetSettings.codeLeft !== '' && + props.snippetSettings.codeRight !== '' && !isResizing() && isLooping() ) { if (toggled()) { - setCode(props.startCode) + setCode(props.snippetSettings.codeLeft) } else { - setCode(props.endCode) + setCode(props.snippetSettings.codeRight) } setToggled(!toggled()) } @@ -173,7 +149,7 @@ export default function Editor(props: EditorProps) { document.body.addEventListener('mousemove', e => { if (isResizing()) { const deltaX = e.movementX - props.setSnippetWidth(props.snippetWidth + deltaX) + props.setSnippetSettings('snippetWidth', props.snippetSettings.snippetWidth + deltaX) } }) @@ -229,25 +205,25 @@ export default function Editor(props: EditorProps) { maxContainerDimensions()?.height || 100, { layout: { - yPadding: props.yPadding, - xPadding: props.xPadding, + yPadding: props.snippetSettings.yPadding, + xPadding: props.snippetSettings.xPadding, }, shadow: { - shadowEnabled: props.shadowEnabled, - shadowOffsetY: props.shadowOffsetY, - shadowBlur: props.shadowBlur, - shadowColor: props.shadowColor, - shadowOpacity: props.shadowOpacity, + shadowEnabled: props.snippetSettings.shadowEnabled, + shadowOffsetY: props.snippetSettings.shadowOffsetY, + shadowBlur: props.snippetSettings.shadowBlur, + shadowColor: props.snippetSettings.shadowColor, + shadowOpacity: props.snippetSettings.shadowOpacity, }, styling: { fontSize, fontFamily, snippetBackgroundColor: backgroundColor, - backgroundColor: props.bgColor, - backgroundType: props.bgType, - backgroundGradientColorStart: props.bgGradientColorStart, - backgroundGradientColorEnd: props.bgGradientColorEnd, - backgroundGradientDirection: props.bgGradientDirection, + backgroundColor: props.snippetSettings.bgColor, + backgroundType: props.snippetSettings.bgType, + backgroundGradientColorStart: props.snippetSettings.bgGradientColorStart, + backgroundGradientColorEnd: props.snippetSettings.bgGradientColorEnd, + backgroundGradientDirection: props.snippetSettings.bgGradientDirection, }, }, ) @@ -277,9 +253,9 @@ export default function Editor(props: EditorProps) { props.setSnippetSettings('theme', newTheme || '')} placeholder="Search a theme..." itemComponent={props => ( @@ -300,9 +276,9 @@ export default function Editor(props: EditorProps) { props.setSnippetSettings('language', newLanguage || '')} placeholder="Search a Language..." itemComponent={props => ( @@ -337,18 +313,28 @@ export default function Editor(props: EditorProps) { id="bg-type" - value={bgTypeOptions.find(option => option.value === props.bgType)} + value={bgTypeOptions.find( + option => option.value === props.snippetSettings.bgType, + )} optionValue="value" optionTextValue="label" onChange={newType => - newType && props.setBgType(newType.value as 'solid' | 'linearGradient') + newType && + props.setSnippetSettings( + 'bgType', + newType.value as 'solid' | 'linearGradient', + ) } options={bgTypeOptions} itemComponent={props => ( {props.item.rawValue.label} )} > - + > {state => state.selectedOption()?.label} @@ -357,7 +343,7 @@ export default function Editor(props: EditorProps) { - {props.bgType === 'linearGradient' && ( + {props.snippetSettings.bgType === 'linearGradient' && ( <>
@@ -381,18 +367,18 @@ export default function Editor(props: EditorProps) { id="bg-color-input-grad-end" class="h-6 w-6 rounded" type="color" - value={props.bgGradientColorEnd} + value={props.snippetSettings.bgGradientColorEnd} onInput={e => { - props.setBgGradientColorEnd(e.target.value) + props.setSnippetSettings('bgGradientColorEnd', e.target.value) }} /> { - props.setBgGradientDirection(e[0]) + props.setSnippetSettings('bgGradientDirection', e[0]) }} >
@@ -410,7 +396,7 @@ export default function Editor(props: EditorProps) { )} - {props.bgType === 'solid' && ( + {props.snippetSettings.bgType === 'solid' && (
@@ -435,11 +421,11 @@ export default function Editor(props: EditorProps) {
{ - props.setSnippetWidth(e[0]) + props.setSnippetSettings('snippetWidth', e[0]) }} >
@@ -456,11 +442,11 @@ export default function Editor(props: EditorProps) { { - props.setYPadding(e[0]) + props.setSnippetSettings('yPadding', e[0]) }} >
@@ -477,11 +463,11 @@ export default function Editor(props: EditorProps) { { - props.setXPadding(e[0]) + props.setSnippetSettings('xPadding', e[0]) }} >
@@ -507,15 +493,23 @@ export default function Editor(props: EditorProps) {
{ - props.setShadowEnabled(!props.shadowEnabled) + props.setSnippetSettings( + 'shadowEnabled', + !props.snippetSettings.shadowEnabled, + ) }} />
@@ -529,18 +523,18 @@ export default function Editor(props: EditorProps) { id="shadow-color-input" class="h-6 w-6 rounded" type="color" - value={props.shadowColor} - onInput={e => props.setShadowColor(e.target.value)} + value={props.snippetSettings.shadowColor} + onInput={e => props.setSnippetSettings('shadowColor', e.target.value)} />
{ - props.setShadowOpacity(e[0]) + props.setSnippetSettings('shadowOpacity', e[0]) }} >
@@ -555,11 +549,11 @@ export default function Editor(props: EditorProps) {
{ - props.setShadowOffsetY(e[0]) + props.setSnippetSettings('shadowOffsetY', e[0]) }} >
@@ -577,11 +571,11 @@ export default function Editor(props: EditorProps) {
{ - props.setShadowBlur(e[0]) + props.setSnippetSettings('shadowBlur', e[0]) }} >
@@ -610,10 +604,14 @@ export default function Editor(props: EditorProps) { id="font-family" - value={supportedFontFamilies.find(option => option.name === props.fontFamily)} + value={supportedFontFamilies.find( + option => option.name === props.snippetSettings.fontFamily, + )} optionValue="name" optionTextValue="name" - onChange={newFamily => newFamily && props.setFontFamily(newFamily.name)} + onChange={newFamily => + newFamily && props.setSnippetSettings('fontFamily', newFamily.name) + } options={supportedFontFamilies} itemComponent={props => ( {props.item.rawValue.name} @@ -622,7 +620,7 @@ export default function Editor(props: EditorProps) { > {state => state.selectedOption()?.name} @@ -633,11 +631,11 @@ export default function Editor(props: EditorProps) {
{ - props.setFontSize(e[0]) + props.setSnippetSettings('fontSize', e[0]) }} >
@@ -678,7 +676,10 @@ export default function Editor(props: EditorProps) { onClick={() => { setSelectedTab('output') }} - disabled={props.startCode === '' || props.endCode === ''} + disabled={ + props.snippetSettings.codeLeft === '' || + props.snippetSettings.codeRight === '' + } > Next @@ -688,8 +689,8 @@ export default function Editor(props: EditorProps) {
props.setSnippetSettings('codeLeft', newCodeLeft)} > Start Code @@ -697,8 +698,8 @@ export default function Editor(props: EditorProps) { props.setSnippetSettings('codeRight', newEndCode)} > End Code @@ -716,13 +717,13 @@ export default function Editor(props: EditorProps) { disabled={isGenerating()} onClick={async () => { setIsGenerating(true) - setHiddenCode(props.endCode) + setHiddenCode(props.snippetSettings.codeRight) setTimeout(async () => { const dataUrl = await generateGifDataUrl()() setGifDataUrl(dataUrl) setIsGenerating(false) setIsShowingGifDialog(true) - setHiddenCode(props.startCode) + setHiddenCode(props.snippetSettings.codeLeft) }, 1000) }} > @@ -744,14 +745,14 @@ export default function Editor(props: EditorProps) { id="styled-snippet" class="flex flex-row items-center justify-center overflow-hidden" style={{ - ...(props.bgType === 'linearGradient' + ...(props.snippetSettings.bgType === 'linearGradient' ? { - background: `linear-gradient(${props.bgGradientDirection}deg, ${props.bgGradientColorStart}, ${props.bgGradientColorEnd})`, + background: `linear-gradient(${props.snippetSettings.bgGradientDirection}deg, ${props.snippetSettings.bgGradientColorStart}, ${props.snippetSettings.bgGradientColorEnd})`, } : { - background: props.bgColor, + background: props.snippetSettings.bgColor, }), - padding: `${props.yPadding}px ${props.xPadding}px`, + padding: `${props.snippetSettings.yPadding}px ${props.snippetSettings.xPadding}px`, }} >
@@ -761,20 +762,22 @@ export default function Editor(props: EditorProps) {