diff --git a/package.json b/package.json
index ce627a86..844fff32 100644
--- a/package.json
+++ b/package.json
@@ -86,15 +86,15 @@
"postcss": "^8.4.45",
"publish-browser-extension": "^2.2.1",
"react": "^18.3.1",
- "react-best-gradient-color-picker": "3.0.5",
+ "react-best-gradient-color-picker": "^3.0.10",
"react-dom": "^18.3.1",
"react-error-boundary": "^4.0.13",
"react-router-dom": "^6.26.2",
+ "react-shadow-root": "^6.2.0",
"react-toastify": "^10.0.5",
"rimraf": "^5.0.10",
"sortablejs": "^1.15.3",
"svelte": "5.0.0-next.244",
- "svelte-hash-router": "^1.0.1",
"swiper": "latest",
"tailwindcss": "^3.4.11",
"ts-loader": "^9.5.1",
diff --git a/src/svelte-interface/components/ColorPicker.svelte b/src/svelte-interface/components/ColorPicker.svelte
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/svelte-interface/components/ColourPicker.svelte b/src/svelte-interface/components/ColourPicker.svelte
new file mode 100644
index 00000000..f61212f0
--- /dev/null
+++ b/src/svelte-interface/components/ColourPicker.svelte
@@ -0,0 +1,73 @@
+
+
+
+
{ e.key === 'Enter' && handleBackgroundClick }}
+>
+
+
+
+
\ No newline at end of file
diff --git a/src/svelte-interface/components/ColourPicker.tsx b/src/svelte-interface/components/ColourPicker.tsx
new file mode 100644
index 00000000..3f5cae3f
--- /dev/null
+++ b/src/svelte-interface/components/ColourPicker.tsx
@@ -0,0 +1,70 @@
+import ColorPicker from 'react-best-gradient-color-picker';
+import { useEffect, useState } from 'react';
+import { settingsState } from '@/seqta/utils/listeners/SettingsState';
+
+const defaultPresets = [
+ 'linear-gradient(30deg, rgba(229,209,218,1) 0%, RGBA(235,169,202,1) 46%, rgba(214,155,162,1) 100%)',
+ 'linear-gradient(40deg, rgba(201,61,0,1) 0%, RGBA(170, 5, 58, 1) 100%)',
+ 'linear-gradient(40deg, rgba(0, 141, 201, 0.76) 0%, rgba(8, 5, 170, 0.66) 100%)',
+ 'linear-gradient(40deg, rgba(0, 201, 20, 0.76) 0%, rgba(4, 160, 105, 0.66) 100%)',
+ 'linear-gradient(40deg, rgba(199, 20, 55, 0.76) 0%, rgba(95, 11, 160, 0.66) 100%)',
+ 'linear-gradient(40deg, rgba(24, 20, 199, 0.76) 0%, rgba(23, 173, 65, 0.66) 100%)',
+ 'radial-gradient(circle, rgba(20, 199, 178, 0.76) 32%, rgba(3, 120, 57, 0.66) 100%)',
+ 'radial-gradient(circle, rgba(13, 15, 145, 0.76) 12%, rgba(103, 3, 120, 0.66) 100%)',
+ 'linear-gradient(20deg, rgb(230, 21, 21) 0%, rgb(230, 109, 21) 12%, rgb(230, 34, 21) 26%, rgb(230, 21, 21) 39%, rgb(230, 84, 21) 48%, rgb(230, 34, 21) 58%, rgb(230, 96, 21) 69%, rgb(230, 34, 21) 80%, rgb(230, 71, 21) 89%, rgb(230, 21, 21) 100%)',
+ 'rgba(114, 1, 170, 0.89)',
+ 'rgba(93, 135, 63, 0.89)',
+ 'rgba(4, 4, 138, 0.77)',
+ 'rgba(21, 20, 20, 0.89)',
+ 'linear-gradient(340deg, rgb(205, 74, 82) 18%, rgba(132, 8, 8, 0.89) 46%, rgb(204, 78, 85) 72%)',
+ 'radial-gradient(circle, rgb(74, 205, 158) 0%, rgba(8, 72, 132, 0.89) 99%)',
+ 'rgba(17, 94, 89, 1)',
+ 'rgba(30, 64, 175, 0.89)',
+ 'rgba(134, 25, 143, 1)',
+ 'rgba(14, 165, 233, 0.9)'
+];
+
+function Picker() {
+ const [customThemeColor, setCustomThemeColor] = useState(() => {
+ return settingsState.selectedColor
+ });
+ const [presets, setPresets] = useState(() => {
+ const savedPresets = localStorage.getItem('colorPickerPresets');
+ return savedPresets ? JSON.parse(savedPresets) : defaultPresets;
+ });
+
+
+ useEffect(() => {
+ // on component dismount, save the presets to local storage
+ return () => {
+ // Check if the selected color is already in the presets
+ const existingIndex = presets.indexOf(customThemeColor);
+
+ let updatedPresets;
+ if (existingIndex > -1) {
+ // If the color exists, move it to the front
+ updatedPresets = [
+ 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);
+ localStorage.setItem('colorPickerPresets', JSON.stringify(updatedPresets));
+ }
+ }, []);
+
+ useEffect(() => {
+ settingsState.selectedColor = customThemeColor;
+ }, [customThemeColor]);
+
+ return (
+
+ );
+}
+
+export default Picker;
diff --git a/src/svelte-interface/components/PickerSwatch.svelte b/src/svelte-interface/components/PickerSwatch.svelte
index a8d040e6..643f5f46 100644
--- a/src/svelte-interface/components/PickerSwatch.svelte
+++ b/src/svelte-interface/components/PickerSwatch.svelte
@@ -1,129 +1,11 @@
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/svelte-interface/components/TabbedContainer.svelte b/src/svelte-interface/components/TabbedContainer.svelte
index 71f8a3fb..0941dc55 100644
--- a/src/svelte-interface/components/TabbedContainer.svelte
+++ b/src/svelte-interface/components/TabbedContainer.svelte
@@ -3,7 +3,7 @@
import './TabbedContainer.css';
import { onMount } from 'svelte';
- let { tabs } = $props<{ tabs: { title: string, Content: any }[] }>();
+ let { tabs } = $props<{ tabs: { title: string, Content: any, props?: any }[] }>();
let activeTab = $state(0);
let hoveredTab = $state(null);
let containerRef: HTMLElement | null = null;
@@ -71,10 +71,10 @@
transition={springTransition}
>
- {#each tabs as { Content }, index}
+ {#each tabs as { Content, props }, index}
- {@render Content()}
+
{/each}
diff --git a/src/svelte-interface/components/utils/ReactAdapter.svelte b/src/svelte-interface/components/utils/ReactAdapter.svelte
new file mode 100644
index 00000000..2a7de2fc
--- /dev/null
+++ b/src/svelte-interface/components/utils/ReactAdapter.svelte
@@ -0,0 +1,27 @@
+
+
+
\ No newline at end of file
diff --git a/src/svelte-interface/pages/settings.svelte b/src/svelte-interface/pages/settings.svelte
index 2f57d2c9..8763cf22 100644
--- a/src/svelte-interface/pages/settings.svelte
+++ b/src/svelte-interface/pages/settings.svelte
@@ -10,6 +10,12 @@
import { settingsState } from '@/seqta/utils/listeners/SettingsState'
import { closeSettings, OpenAboutPage, OpenWhatsNewPopup } from "@/SEQTA"
+ import ColourPicker from '../components/ColourPicker.svelte'
+
+
+ const openColourPicker = () => {
+ showColourPicker = true;
+ }
const openChangelog = () => {
OpenWhatsNewPopup();
@@ -22,6 +28,7 @@
};
let { standalone = false } = $props<{ standalone?: boolean }>();
+ let showColourPicker = $state(false);
onMount(() => {
if (!standalone) return;
@@ -38,12 +45,17 @@
+
+
+ {#if showColourPicker}
+ { showColourPicker = false }} />
+ {/if}
\ No newline at end of file
diff --git a/src/svelte-interface/pages/settings/general.svelte b/src/svelte-interface/pages/settings/general.svelte
index 72781435..9e0957eb 100644
--- a/src/svelte-interface/pages/settings/general.svelte
+++ b/src/svelte-interface/pages/settings/general.svelte
@@ -1,13 +1,15 @@
{#snippet Setting({ title, description, Component, props }: SettingsList) }
@@ -54,12 +56,15 @@
onChange: (value: number) => settingsState.bksliderinput = `${value}`
}
},
- /* {
+ {
title: "Custom Theme Colour",
description: "Customise the overall theme colour of SEQTA Learn.",
id: 4,
- Component: PickerSwatch
- }, */
+ Component: PickerSwatch,
+ props: {
+ onClick: showColourPicker
+ }
+ },
{
title: "Edit Sidebar Layout",
description: "Customise the sidebar layout.",
diff --git a/vite.config.ts b/vite.config.ts
index 8e541961..8f114392 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -4,7 +4,7 @@ import { join, resolve } from 'path';
import { base64Loader } from './lib/base64loader';
import type { BuildTarget } from './lib/types';
-//import react from '@vitejs/plugin-react-swc';
+import react from '@vitejs/plugin-react-swc';
//import million from "million/compiler";
//import MillionLint from '@million/lint';
@@ -27,7 +27,7 @@ const mode = process.env.MODE || 'chrome';
export default defineConfig({
plugins: [
base64Loader,
- //react(),
+ react(),
svelte({
emitCss: false
}),