mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-06 11:44:40 +00:00
fix(colourPicker): saving presets list at incorrect times
This commit is contained in:
@@ -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 });
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (customState !== undefined) {
|
||||||
|
setCustomThemeColor(customState)
|
||||||
|
} else {
|
||||||
|
setCustomThemeColor(settingsState.selectedColor ?? null)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (presets === undefined) {
|
||||||
const savedPresets = localStorage.getItem("colorPickerPresets")
|
const savedPresets = localStorage.getItem("colorPickerPresets")
|
||||||
return savedPresets ? JSON.parse(savedPresets) : defaultPresets
|
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;
|
||||||
|
if (!(customThemeColor && !customOnChange && savePresets)) return;
|
||||||
|
|
||||||
|
// Only proceed if presets are different (avoid unnecessary updates)
|
||||||
|
const existingIndex = presets.indexOf(customThemeColor);
|
||||||
|
let updatedPresets;
|
||||||
|
|
||||||
|
if (existingIndex === 0) {
|
||||||
|
// No need to update if the selected color is already the first element
|
||||||
|
return;
|
||||||
|
} else if (existingIndex > -1) {
|
||||||
updatedPresets = [
|
updatedPresets = [
|
||||||
customThemeColor,
|
customThemeColor,
|
||||||
...presets.slice(0, existingIndex),
|
...presets.slice(0, existingIndex),
|
||||||
...presets.slice(existingIndex + 1),
|
...presets.slice(existingIndex + 1),
|
||||||
]
|
];
|
||||||
} else {
|
} else {
|
||||||
// If the color is new, add it to the front and slice the array
|
updatedPresets = [customThemeColor, ...presets].slice(0, 18);
|
||||||
updatedPresets = [customThemeColor, ...presets].slice(0, 18)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setPresets(updatedPresets)
|
localStorage.setItem("colorPickerPresets", JSON.stringify(updatedPresets));
|
||||||
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>
|
||||||
|
|||||||
Reference in New Issue
Block a user