fix(colourPicker): saving presets list at incorrect times

This commit is contained in:
sethburkart123
2024-10-01 19:50:28 +10:00
parent 1360736dd7
commit 49d4f39584
5 changed files with 124 additions and 41 deletions
+2
View File
@@ -52,6 +52,7 @@
}, },
"dependencies": { "dependencies": {
"@bedframe/cli": "^0.0.85", "@bedframe/cli": "^0.0.85",
"@codemirror/lang-css": "^6.3.0",
"@codemirror/lang-less": "^6.0.2", "@codemirror/lang-less": "^6.0.2",
"@million/lint": "latest", "@million/lint": "latest",
"@sveltejs/vite-plugin-svelte": "4.0.0-next.7", "@sveltejs/vite-plugin-svelte": "4.0.0-next.7",
@@ -70,6 +71,7 @@
"@vitejs/plugin-react": "^4.3.1", "@vitejs/plugin-react": "^4.3.1",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"classnames": "^2.5.1", "classnames": "^2.5.1",
"codemirror": "^6.0.1",
"color": "^4.2.3", "color": "^4.2.3",
"dompurify": "^3.1.6", "dompurify": "^3.1.6",
"idb": "^8.0.0", "idb": "^8.0.0",
@@ -1,4 +1,70 @@
<script lang="ts"> <script lang="ts">
import { EditorState } from '@codemirror/state';
import { highlightSelectionMatches } from '@codemirror/search';
import { indentWithTab, history, defaultKeymap, historyKeymap } from '@codemirror/commands';
import { foldGutter, indentOnInput, indentUnit, bracketMatching, foldKeymap, syntaxHighlighting, defaultHighlightStyle } from '@codemirror/language';
import { closeBrackets, autocompletion, closeBracketsKeymap, completionKeymap } from '@codemirror/autocomplete';
import { lineNumbers, highlightActiveLineGutter, highlightSpecialChars, drawSelection, rectangularSelection, crosshairCursor, highlightActiveLine, keymap, EditorView } from '@codemirror/view'; // dropCursor
// Theme
import { oneDark } from "@codemirror/theme-one-dark";
// Language
import { css } from "@codemirror/lang-css";
import { onMount } from 'svelte'
function createEditorState(initialContents: string, options = {}) {
let extensions = [
/* lineNumbers(),
highlightActiveLineGutter(),
highlightSpecialChars(),
history(),
foldGutter(),
drawSelection(),
indentUnit.of(" "),
EditorState.allowMultipleSelections.of(true),
indentOnInput(),
bracketMatching(),
closeBrackets(),
autocompletion(),
rectangularSelection(),
crosshairCursor(),
highlightActiveLine(),
highlightSelectionMatches(),
keymap.of([
indentWithTab,
...closeBracketsKeymap,
...defaultKeymap,
...historyKeymap,
...foldKeymap,
...completionKeymap,
]), */
css(),
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
];
/* if (options.oneDark)
extensions.push(oneDark); */
return EditorState.create({
doc: initialContents,
extensions
});
}
function createEditorView(state: any, parent: HTMLElement) {
return new EditorView({ state, parent });
}
onMount(() => {
const editor = document.querySelector('#cm-target');
if (editor) {
const state = createEditorState('body {\n color: red;\n}');
const view = createEditorView(state, editor as HTMLElement);
console.log(view)
}
});
</script> </script>
<div>Code Editor Here</div> <div id="cm-target"></div>
@@ -5,16 +5,18 @@
import { animate, spring } from 'motion'; import { animate, spring } from 'motion';
import { delay } from '@/seqta/utils/delay.ts' import { delay } from '@/seqta/utils/delay.ts'
const { hidePicker, standalone = false } = $props<{ const { hidePicker, standalone = false, savePresets = true } = $props<{
hidePicker?: () => void, hidePicker?: () => void,
standalone?: boolean standalone?: boolean,
savePresets?: boolean
}>(); }>();
let background: HTMLDivElement; let background = $state<HTMLDivElement | null>(null);
let content: HTMLDivElement; let content = $state<HTMLDivElement | null>(null);
const closePicker = async () => { const closePicker = async () => {
if (standalone) return; if (standalone) return;
if (!background || !content) return;
animate( animate(
content, content,
@@ -34,6 +36,7 @@
onMount(() => { onMount(() => {
if (standalone) return; if (standalone) return;
if (!background || !content) return;
animate( animate(
background, background,
@@ -69,7 +72,7 @@
{#if standalone} {#if standalone}
<div class="h-auto rounded-xl overflow-clip"> <div class="h-auto rounded-xl overflow-clip">
<ReactAdapter el={ColourPicker} /> <ReactAdapter savePresets={savePresets} el={ColourPicker} />
</div> </div>
{:else} {:else}
<!-- svelte-ignore a11y_no_static_element_interactions --> <!-- svelte-ignore a11y_no_static_element_interactions -->
@@ -83,7 +86,7 @@
bind:this={content} bind:this={content}
class="h-auto p-4 bg-white border shadow-lg cursor-auto rounded-xl dark:bg-zinc-800 border-zinc-100 dark:border-zinc-700" class="h-auto p-4 bg-white border shadow-lg cursor-auto rounded-xl dark:bg-zinc-800 border-zinc-100 dark:border-zinc-700"
> >
<ReactAdapter el={ColourPicker} /> <ReactAdapter savePresets={savePresets} el={ColourPicker} />
</div> </div>
</div> </div>
{/if} {/if}
@@ -1,5 +1,5 @@
import ColorPicker from "react-best-gradient-color-picker" import ColorPicker from "react-best-gradient-color-picker"
import React, { useEffect, useState } from "react" import React, { useEffect, useState, useRef } from "react"
import { settingsState } from "@/seqta/utils/listeners/SettingsState.ts" import { settingsState } from "@/seqta/utils/listeners/SettingsState.ts"
const defaultPresets = [ const defaultPresets = [
@@ -35,13 +35,23 @@ export default function Picker({
customState, customState,
savePresets = true, savePresets = true,
}: PickerProps) { }: PickerProps) {
const [customThemeColor, setCustomThemeColor] = useState<string | null>( const [customThemeColor, setCustomThemeColor] = useState<string | null>()
() => customState ?? settingsState.selectedColor ?? null const [presets, setPresets] = useState<string[]>()
)
const [presets, setPresets] = useState<string[]>(() => { const latestValuesRef = useRef({ customThemeColor, customOnChange, savePresets, presets });
const savedPresets = localStorage.getItem("colorPickerPresets")
return savedPresets ? JSON.parse(savedPresets) : defaultPresets useEffect(() => {
}) if (customState !== undefined) {
setCustomThemeColor(customState)
} else {
setCustomThemeColor(settingsState.selectedColor ?? null)
}
if (presets === undefined) {
const savedPresets = localStorage.getItem("colorPickerPresets")
setPresets(savedPresets ? JSON.parse(savedPresets) : defaultPresets)
}
}, [])
useEffect(() => { useEffect(() => {
if (customState !== undefined) { if (customState !== undefined) {
@@ -50,32 +60,34 @@ export default function Picker({
}, [customState]) }, [customState])
useEffect(() => { useEffect(() => {
if (customThemeColor && !customOnChange && savePresets) { latestValuesRef.current = { customThemeColor, customOnChange, savePresets, presets };
return () => { }, [customThemeColor, customOnChange, savePresets, presets]);
// Check if the selected color is already in the presets
const existingIndex = presets.indexOf(customThemeColor)
let updatedPresets useEffect(() => {
if (existingIndex > -1) { return () => {
// If the color exists, move it to the front const { customThemeColor, customOnChange, savePresets, presets } = latestValuesRef.current;
updatedPresets = [ if (!(customThemeColor && !customOnChange && savePresets)) return;
customThemeColor,
...presets.slice(0, existingIndex),
...presets.slice(existingIndex + 1),
]
} else {
// If the color is new, add it to the front and slice the array
updatedPresets = [customThemeColor, ...presets].slice(0, 18)
}
setPresets(updatedPresets) // Only proceed if presets are different (avoid unnecessary updates)
localStorage.setItem( const existingIndex = presets.indexOf(customThemeColor);
"colorPickerPresets", let updatedPresets;
JSON.stringify(updatedPresets),
) if (existingIndex === 0) {
// No need to update if the selected color is already the first element
return;
} else if (existingIndex > -1) {
updatedPresets = [
customThemeColor,
...presets.slice(0, existingIndex),
...presets.slice(existingIndex + 1),
];
} else {
updatedPresets = [customThemeColor, ...presets].slice(0, 18);
} }
localStorage.setItem("colorPickerPresets", JSON.stringify(updatedPresets));
} }
}, [customThemeColor, customOnChange, savePresets, presets]) }, [])
useEffect(() => { useEffect(() => {
if (customThemeColor && !customOnChange) { if (customThemeColor && !customOnChange) {
@@ -74,16 +74,16 @@
{:else if item.type === 'slider'} {:else if item.type === 'slider'}
<Slider {...(item.props as SliderProps)} /> <Slider {...(item.props as SliderProps)} />
{:else if item.type === 'colourPicker'} {:else if item.type === 'colourPicker'}
<ColourPicker standalone={true} {...(item.props)} /> <ColourPicker savePresets={false} standalone={true} {...(item.props)} />
{:else if item.type === 'codeEditor'} {:else if item.type === 'codeEditor'}
<CodeEditor {...(item.props as CodeEditorProps)} /> <CodeEditor /> <!-- {/*...(item.props as CodeEditorProps)*/} -->
{/if} {/if}
</div> </div>
</div> </div>
{/snippet} {/snippet}
<div class='h-screen overflow-y-scroll {$settingsState.DarkMode && "dark"} '> <div class='h-screen overflow-y-scroll {$settingsState.DarkMode && "dark"} '>
<div class='w-full min-h-screen bg-zinc-100 dark:bg-zinc-800 flex flex-col p-2 dark:text-white'> <div class='flex flex-col w-full min-h-screen p-2 bg-zinc-100 dark:bg-zinc-800 dark:text-white'>
<h1 class='text-xl font-semibold'>Theme Creator</h1> <h1 class='text-xl font-semibold'>Theme Creator</h1>
<a href='https://betterseqta.gitbook.io/betterseqta-docs' target='_blank' class='text-sm font-light text-zinc-500 dark:text-zinc-400'> <a href='https://betterseqta.gitbook.io/betterseqta-docs' target='_blank' class='text-sm font-light text-zinc-500 dark:text-zinc-400'>
<span class='no-underline font-IconFamily pr-0.5'>{'\ueb44'}</span> <span class='no-underline font-IconFamily pr-0.5'>{'\ueb44'}</span>