diff --git a/src/pages/settings/components/Theming/Themes/ThemeModal/components/BackgroundItem.tsx b/src/pages/settings/components/Theming/Themes/ThemeModal/components/BackgroundItem.tsx
new file mode 100644
index 0000000..623f6d9
--- /dev/null
+++ b/src/pages/settings/components/Theming/Themes/ThemeModal/components/BackgroundItem.tsx
@@ -0,0 +1,83 @@
+import { Group, Text, UnstyledButton } from '@mantine/core';
+
+export default function BackgroundItem({
+ item,
+ index,
+ hovered,
+ designerTheme,
+ setDesignerTheme,
+}: {
+ item: string;
+ index: number;
+ hovered: number;
+ designerTheme: any;
+ setDesignerTheme: any;
+}) {
+ const re = /(?:\.([^.]+))?$/;
+ return (
+
+ setDesignerTheme({
+ ...designerTheme,
+ backgroundImage: item,
+ })
+ }
+ >
+
+
+ {item.replace(/\.[^/.]+$/, '')}
+
+ {item !== 'None' && (
+
+ {re.exec(item.toUpperCase())?.[1]}
+
+ )}
+
+
+ );
+}
diff --git a/src/pages/settings/components/Theming/Themes/ThemeModal/components/BackgroundPicker.tsx b/src/pages/settings/components/Theming/Themes/ThemeModal/components/BackgroundPicker.tsx
new file mode 100644
index 0000000..c988210
--- /dev/null
+++ b/src/pages/settings/components/Theming/Themes/ThemeModal/components/BackgroundPicker.tsx
@@ -0,0 +1,138 @@
+import { Button, Group, ScrollArea, Stack, TextInput } from '@mantine/core';
+import { useRef, useState } from 'react';
+import { FiSave, FiX } from 'react-icons/fi';
+import { scrollAreaClasses, textInputClasses } from 'styles';
+import type { Theme } from 'types';
+import BackgroundItem from './BackgroundItem';
+
+export default function BackgroundPicker({
+ defaultTheme,
+ designerTheme,
+ setDesignerTheme,
+ backgroundList,
+ closeBackgroundPicker,
+}: {
+ defaultTheme: Theme;
+ designerTheme: Theme;
+ setDesignerTheme: (Theme: Theme) => void;
+ backgroundList: string[];
+ closeBackgroundPicker: () => void;
+}) {
+ const [query, setQuery] = useState('');
+ const filtered = backgroundList.filter((item: string) =>
+ item.toLowerCase().includes(query.toLowerCase()),
+ );
+ const [hovered, setHovered] = useState(-1);
+ const viewportRef = useRef(null);
+ return (
+
+
+ {
+ setQuery('');
+ }}
+ />
+ }
+ onChange={(event) => {
+ setQuery(event.currentTarget.value);
+ setHovered(-1);
+ }}
+ onKeyDown={(event) => {
+ if (event.key === 'ArrowDown') {
+ event.preventDefault();
+ setHovered((current: number) => {
+ const nextIndex = current + 1 >= filtered.length ? current : current + 1;
+ viewportRef.current
+ ?.querySelectorAll('[data-list-item]')
+ ?.[nextIndex]?.scrollIntoView({ block: 'nearest' });
+ return nextIndex;
+ });
+ }
+
+ if (event.key === 'ArrowUp') {
+ event.preventDefault();
+ setHovered((current: number) => {
+ const nextIndex = current - 1 < 0 ? current : current - 1;
+ viewportRef.current
+ ?.querySelectorAll('[data-list-item]')
+ ?.[nextIndex]?.scrollIntoView({ block: 'nearest' });
+ return nextIndex;
+ });
+ }
+ }}
+ />
+
+
+
+ {filtered.map((image: string, index: number) => (
+
+ ))}
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeChanges.tsx b/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeChanges.tsx
new file mode 100644
index 0000000..3c029d0
--- /dev/null
+++ b/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeChanges.tsx
@@ -0,0 +1,309 @@
+import {
+ ActionIcon,
+ ColorSwatch,
+ Group,
+ Image,
+ ScrollArea,
+ Stack,
+ Text,
+ Tooltip,
+} from '@mantine/core';
+import { notifications } from '@mantine/notifications';
+import { useCommonHooks } from 'hooks';
+import { FaClipboard } from 'react-icons/fa';
+import { FiX } from 'react-icons/fi';
+import { scrollAreaClasses, toolTipClasses } from 'styles';
+import { type Theme, ThemeProperties } from 'types';
+
+export default function ThemeChanges({
+ duplicate,
+ defaultTheme,
+ designerTheme,
+ setDesignerTheme,
+}: {
+ duplicate: boolean;
+ defaultTheme: Theme;
+ designerTheme: Theme;
+ setDesignerTheme: (theme: Theme) => void;
+}) {
+ const { currentUser, getObjectDiff } = useCommonHooks();
+ return (
+
+
+ Changes
+
+
+
+ {getObjectDiff(defaultTheme, designerTheme) !== null &&
+ Object.keys(getObjectDiff(defaultTheme, designerTheme)).map((key: any) => {
+ return (
+ key !== 'id' && (
+
+
+
+ {ThemeProperties[key as keyof typeof ThemeProperties]}
+
+
+ {
+ setDesignerTheme({
+ ...designerTheme,
+ [key]: defaultTheme[key as keyof Theme],
+ });
+ }}
+ pos={'absolute'}
+ right={0}
+ >
+
+
+
+
+
+ {key === 'name' && (
+
+ {defaultTheme[key as keyof Theme]}
+ →
+ {designerTheme[key as keyof Theme]}
+
+ )}
+ {key.includes('Shadow') && (
+
+ {defaultTheme[key as keyof Theme] === 0 ? (
+ Off
+ ) : (
+ On
+ )}
+ →
+ {designerTheme[key as keyof Theme] === 0 ? (
+ Off
+ ) : (
+ On
+ )}
+
+ )}
+ {key.includes('Font') && (
+ <>
+
+ {defaultTheme[key as keyof Theme] ||
+ `Default (${currentUser.defaultFont})`}
+
+ →
+
+ {designerTheme[key as keyof Theme] ||
+ `Default (${currentUser.defaultFont})`}
+
+ >
+ )}
+ {key === 'backgroundImage' && (
+ <>
+
+ →
+
+ >
+ )}
+ {key.includes('Color') && (
+ <>
+
+ {
+ navigator.clipboard.writeText(
+ defaultTheme[key as keyof Theme] as string,
+ );
+ notifications.show({
+ title: (
+
+ Copied{' '}
+ {
+ ThemeProperties[
+ key as keyof typeof ThemeProperties
+ ]
+ }
+
+ ),
+ message: (
+
+ {defaultTheme[key as keyof Theme] as string}
+
+ ),
+ autoClose: true,
+ withCloseButton: true,
+ icon: ,
+ });
+ }}
+ color={defaultTheme[key as keyof Theme] as string}
+ style={{
+ cursor: 'pointer',
+ }}
+ styles={{
+ alphaOverlay: {
+ borderRadius: '0px',
+ },
+ colorOverlay: {
+ borderRadius: '0px',
+ },
+ shadowOverlay: {
+ borderRadius: '0px',
+ },
+ childrenOverlay: {
+ borderRadius: '0px',
+ },
+ }}
+ />
+
+ →
+
+ {
+ navigator.clipboard.writeText(
+ defaultTheme[key as keyof Theme] as string,
+ );
+ notifications.show({
+ title: (
+
+ Copied{' '}
+ {
+ ThemeProperties[
+ key as keyof typeof ThemeProperties
+ ]
+ }
+
+ ),
+ message: (
+
+ {designerTheme[key as keyof Theme] as string}
+
+ ),
+ autoClose: true,
+ withCloseButton: true,
+ icon: ,
+ });
+ }}
+ color={designerTheme[key as keyof Theme] as string}
+ style={{
+ cursor: 'pointer',
+ }}
+ styles={{
+ alphaOverlay: {
+ borderRadius: '0px',
+ },
+ colorOverlay: {
+ borderRadius: '0px',
+ },
+ shadowOverlay: {
+ borderRadius: '0px',
+ },
+ childrenOverlay: {
+ borderRadius: '0px',
+ },
+ }}
+ />
+
+ >
+ )}
+
+
+ )
+ );
+ })}
+
+
+
+ );
+}
diff --git a/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeColorPicker.tsx b/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeColorPicker.tsx
new file mode 100644
index 0000000..24e45ad
--- /dev/null
+++ b/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeColorPicker.tsx
@@ -0,0 +1,246 @@
+import {
+ Button,
+ ColorPicker,
+ Group,
+ Stack,
+ Text,
+ TextInput,
+ Tooltip,
+} from '@mantine/core';
+import { useCommonHooks } from 'hooks';
+import { FaCheck } from 'react-icons/fa';
+import { FiRefreshCcw, FiShuffle } from 'react-icons/fi';
+import { textClasses, textInputClasses, toolTipClasses } from 'styles';
+import { type Theme, ThemeProperties } from 'types';
+
+export default function ThemeColorPicker({
+ colorId,
+ colorValue,
+ setColorValue,
+ defaultTheme,
+ designerTheme,
+ setDesignerTheme,
+ rgba,
+ setRgba,
+ randomColor,
+ closePicker,
+}: {
+ colorId: string;
+ colorValue: string;
+ setColorValue: any;
+ defaultTheme: Theme;
+ designerTheme: Theme;
+ setDesignerTheme: any;
+ rgba: any;
+ setRgba: (rgba: any) => void;
+ randomColor: (withAlpha?: boolean) => string;
+ closePicker: () => void;
+}) {
+ const { theme, textShadowStyle } = useCommonHooks();
+ return (
+
+
+ Change {ThemeProperties[colorId as keyof typeof ThemeProperties]}
+
+ {colorId === 'searchColor' && (
+ {
+ setColorValue(e);
+ setDesignerTheme({
+ ...designerTheme,
+ [colorId]: e,
+ });
+ }}
+ format={'hexa'}
+ w={'90%'}
+ />
+ )}
+ {colorId !== 'searchColor' && (
+ {
+ setColorValue(e);
+ setDesignerTheme({
+ ...designerTheme,
+ [colorId]: e,
+ });
+ }}
+ format={'hex'}
+ w={'90%'}
+ mb={'1.5rem'}
+ />
+ )}
+
+ setColorValue(e.target.value)}
+ />
+
+ {
+ if (e.target.value) {
+ setRgba({
+ ...rgba,
+ r: Number.parseInt(e.target.value, 10),
+ });
+ setColorValue(
+ `${colorValue.substring(0, 1)}${Number.parseInt(e.target.value, 10).toString(16).padStart(2, '0')}${colorValue.substring(3)}`,
+ );
+ } else {
+ setRgba({
+ ...rgba,
+ r: 0,
+ });
+ }
+ }}
+ />
+ {
+ if (e.target.value) {
+ setRgba({
+ ...rgba,
+ g: Number.parseInt(e.target.value, 10),
+ });
+ setColorValue(
+ `${colorValue.substring(0, 3)}${Number.parseInt(e.target.value, 10).toString(16).padStart(2, '0')}${colorValue.substring(5)}`,
+ );
+ } else {
+ setRgba({
+ ...rgba,
+ g: 0,
+ });
+ }
+ }}
+ />
+ {
+ if (e.target.value) {
+ setRgba({
+ ...rgba,
+ b: Number.parseInt(e.target.value, 10),
+ });
+ setColorValue(
+ `${colorValue.substring(0, 5)}${Number.parseInt(e.target.value, 10).toString(16).padStart(2, '0')}${colorValue.substring(7)}`,
+ );
+ } else {
+ setRgba({
+ ...rgba,
+ b: 0,
+ });
+ }
+ }}
+ />
+ {
+ if (e.target.value) {
+ setRgba({
+ ...rgba,
+ a: Number.parseInt(e.target.value, 10),
+ });
+ setColorValue(
+ `${colorValue.substring(0, 7)}${Number.parseInt(e.target.value, 10).toString(16).padStart(2, '0')}`,
+ );
+ } else {
+ setRgba({
+ ...rgba,
+ a: 0,
+ });
+ }
+ }}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeColorSwatches.tsx b/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeColorSwatches.tsx
new file mode 100644
index 0000000..5016e2e
--- /dev/null
+++ b/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeColorSwatches.tsx
@@ -0,0 +1,132 @@
+import { ActionIcon, ColorSwatch, Tooltip } from '@mantine/core';
+import { FiImage } from 'react-icons/fi';
+import { colorSwatchClasses, toolTipClasses } from 'styles';
+import type { Theme } from 'types';
+
+export default function ThemeColorSwatches({
+ designerTheme,
+ setDesignerTheme,
+ handleSwatchClick,
+ openBackgroundPicker,
+ closePicker,
+}: {
+ designerTheme: Theme;
+ setDesignerTheme: (Theme: Theme) => void;
+ handleSwatchClick: (colorId: string, colorValue: string) => void;
+ openBackgroundPicker: () => void;
+ closePicker: () => void;
+}) {
+ return (
+ <>
+
+ {
+ handleSwatchClick('primaryColor', designerTheme.primaryColor);
+ }}
+ color={designerTheme.primaryColor}
+ style={{ borderColor: designerTheme.primaryColor }}
+ className={colorSwatchClasses.themeDesignerSwatch}
+ classNames={colorSwatchClasses}
+ top={'11.5rem'}
+ left={'8.5rem'}
+ />
+
+
+ {
+ handleSwatchClick('accentColor', designerTheme.accentColor);
+ }}
+ color={designerTheme.accentColor}
+ style={{ borderColor: designerTheme.primaryColor }}
+ className={colorSwatchClasses.themeDesignerSwatch}
+ classNames={colorSwatchClasses}
+ bottom={'6rem'}
+ left={'11rem'}
+ />
+
+
+ {
+ handleSwatchClick('backgroundColor', designerTheme.backgroundColor);
+ }}
+ color={designerTheme.backgroundColor}
+ style={{ borderColor: designerTheme.primaryColor }}
+ className={colorSwatchClasses.themeDesignerSwatch}
+ classNames={colorSwatchClasses}
+ bottom={'4rem'}
+ right={'3.5rem'}
+ />
+
+
+ {
+ handleSwatchClick('borderColor', designerTheme.borderColor);
+ }}
+ color={designerTheme.borderColor}
+ style={{ borderColor: designerTheme.primaryColor }}
+ className={colorSwatchClasses.themeDesignerSwatch}
+ classNames={colorSwatchClasses}
+ top={'4.5rem'}
+ right={'15%'}
+ />
+
+
+ {
+ handleSwatchClick('searchColor', designerTheme.searchColor);
+ }}
+ color={designerTheme.searchColor}
+ style={{ borderColor: designerTheme.primaryColor }}
+ className={colorSwatchClasses.themeDesignerSwatch}
+ classNames={colorSwatchClasses}
+ top={'3.25rem'}
+ left={'6.5rem'}
+ />
+
+
+ {
+ closePicker();
+ openBackgroundPicker();
+ setDesignerTheme(designerTheme);
+ }}
+ pos={'absolute'}
+ right={0}
+ style={{
+ color: designerTheme.backgroundColor,
+ backgroundColor: designerTheme.primaryColor,
+ borderRadius: 0,
+ borderBottomLeftRadius: 10,
+ borderTopRightRadius: 10,
+ }}
+ >
+
+
+
+ >
+ );
+}
diff --git a/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeEditor.tsx b/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeEditor.tsx
index f8749c1..e4ec2cd 100644
--- a/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeEditor.tsx
+++ b/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeEditor.tsx
@@ -1,38 +1,14 @@
-import {
- ActionIcon,
- Box,
- Button,
- Checkbox,
- ColorPicker,
- ColorSwatch,
- Group,
- Image,
- Overlay,
- ScrollArea,
- Stack,
- Text,
- TextInput,
- Tooltip,
- UnstyledButton,
-} from '@mantine/core';
+import { Button, Group, Stack } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
-import { notifications } from '@mantine/notifications';
import { useCommonHooks } from 'hooks';
-import { useEffect, useRef, useState } from 'react';
-import FontPicker from 'react-fontpicker-ts';
-import { FaCheck, FaClipboard, FaFont, FaGoogle } from 'react-icons/fa';
-import { FaShuffle } from 'react-icons/fa6';
-import { FiImage, FiRefreshCcw, FiSave, FiShuffle, FiX } from 'react-icons/fi';
-import {
- buttonClasses,
- colorSwatchClasses,
- scrollAreaClasses,
- textClasses,
- textInputClasses,
- toolTipClasses,
-} from 'styles';
-import { type Theme, ThemeProperties } from 'types';
+import { useEffect, useState } from 'react';
+import { buttonClasses } from 'styles';
+import type { Theme } from 'types';
+import BackgroundPicker from './BackgroundPicker';
+import ThemeColorPicker from './ThemeColorPicker';
+import ThemeColorSwatches from './ThemeColorSwatches';
import { ThemeModalContent } from './ThemeModalContent';
+import ThemeOptions from './ThemeOptions';
export function ThemeEditor({
backgroundList,
@@ -61,11 +37,7 @@ export function ThemeEditor({
duplicate: boolean;
setDuplicate: (duplicate: boolean) => void;
}) {
- const [query, setQuery] = useState('');
- const [hovered, setHovered] = useState(-1);
- const { currentUser, isMobile, theme, getObjectDiff, textShadowStyle } =
- useCommonHooks();
- const viewportRef = useRef(null);
+ const { currentUser, isMobile } = useCommonHooks();
const [colorId, setColorId] = useState('');
const [colorValue, setColorValue] = useState('#000000');
const [rgba, setRgba] = useState<{ r: number; g: number; b: number; a?: number }>({
@@ -75,80 +47,8 @@ export function ThemeEditor({
});
const [font, setFont] = useState();
const [customFontEnabled, setCustomFontEnabled] = useState(false);
- const re = /(?:\.([^.]+))?$/;
const [backgroundPicker, { open: openBackgroundPicker, close: closeBackgroundPicker }] =
useDisclosure(false);
- const filtered = backgroundList.filter((item: string) =>
- item.toLowerCase().includes(query.toLowerCase()),
- );
- const items = filtered.map((item: string, index: number) => {
- return (
-
- setDesignerTheme({
- ...designerTheme,
- backgroundImage: item,
- })
- }
- >
-
-
- {item.replace(/\.[^/.]+$/, '')}
-
- {item !== 'None' && (
-
- {re.exec(item.toUpperCase())?.[1]}
-
- )}
-
-
- );
- });
const handleSwatchClick = (colorId: string, colorValue: string) => {
setRgba({
@@ -200,120 +100,19 @@ export function ThemeEditor({
});
}
}, [colorValue]);
+
return (
<>
-
- {
- handleSwatchClick('primaryColor', designerTheme.primaryColor);
- }}
- color={designerTheme.primaryColor}
- style={{ borderColor: designerTheme.primaryColor }}
- className={colorSwatchClasses.themeDesignerSwatch}
- classNames={colorSwatchClasses}
- top={'11.5rem'}
- left={'8.5rem'}
- />
-
-
- {
- handleSwatchClick('accentColor', designerTheme.accentColor);
- }}
- color={designerTheme.accentColor}
- style={{ borderColor: designerTheme.primaryColor }}
- className={colorSwatchClasses.themeDesignerSwatch}
- classNames={colorSwatchClasses}
- bottom={'6rem'}
- left={'11rem'}
- />
-
-
- {
- handleSwatchClick('backgroundColor', designerTheme.backgroundColor);
- }}
- color={designerTheme.backgroundColor}
- style={{ borderColor: designerTheme.primaryColor }}
- className={colorSwatchClasses.themeDesignerSwatch}
- classNames={colorSwatchClasses}
- bottom={'4rem'}
- right={'3.5rem'}
- />
-
-
- {
- handleSwatchClick('borderColor', designerTheme.borderColor);
- }}
- color={designerTheme.borderColor}
- style={{ borderColor: designerTheme.primaryColor }}
- className={colorSwatchClasses.themeDesignerSwatch}
- classNames={colorSwatchClasses}
- top={'4.5rem'}
- right={'15%'}
- />
-
-
- {
- handleSwatchClick('searchColor', designerTheme.searchColor);
- }}
- color={designerTheme.searchColor}
- style={{ borderColor: designerTheme.primaryColor }}
- className={colorSwatchClasses.themeDesignerSwatch}
- classNames={colorSwatchClasses}
- top={'3.25rem'}
- left={'6.5rem'}
- />
-
-
- {
- closePicker();
- openBackgroundPicker();
- setDesignerTheme(designerTheme);
- }}
- pos={'absolute'}
- right={0}
- style={{
- color: designerTheme.backgroundColor,
- backgroundColor: designerTheme.primaryColor,
- borderRadius: 0,
- borderBottomLeftRadius: 10,
- borderTopRightRadius: 10,
- }}
- >
-
-
-
+
{pickerOpen && (
-
-
- Change {ThemeProperties[colorId as keyof typeof ThemeProperties]}
-
- {colorId === 'searchColor' && (
- {
- setColorValue(e);
- setDesignerTheme({
- ...designerTheme,
- [colorId]: e,
- });
- }}
- format={'hexa'}
- w={'90%'}
- />
- )}
- {colorId !== 'searchColor' && (
- {
- setColorValue(e);
- setDesignerTheme({
- ...designerTheme,
- [colorId]: e,
- });
- }}
- format={'hex'}
- w={'90%'}
- mb={'1.5rem'}
- />
- )}
-
- setColorValue(e.target.value)}
- />
-
- {
- if (e.target.value) {
- setRgba({
- ...rgba,
- r: Number.parseInt(e.target.value, 10),
- });
- setColorValue(
- `${colorValue.substring(0, 1)}${Number.parseInt(e.target.value, 10).toString(16).padStart(2, '0')}${colorValue.substring(3)}`,
- );
- } else {
- setRgba({
- ...rgba,
- r: 0,
- });
- }
- }}
- />
- {
- if (e.target.value) {
- setRgba({
- ...rgba,
- g: Number.parseInt(e.target.value, 10),
- });
- setColorValue(
- `${colorValue.substring(0, 3)}${Number.parseInt(e.target.value, 10).toString(16).padStart(2, '0')}${colorValue.substring(5)}`,
- );
- } else {
- setRgba({
- ...rgba,
- g: 0,
- });
- }
- }}
- />
- {
- if (e.target.value) {
- setRgba({
- ...rgba,
- b: Number.parseInt(e.target.value, 10),
- });
- setColorValue(
- `${colorValue.substring(0, 5)}${Number.parseInt(e.target.value, 10).toString(16).padStart(2, '0')}${colorValue.substring(7)}`,
- );
- } else {
- setRgba({
- ...rgba,
- b: 0,
- });
- }
- }}
- />
- {
- if (e.target.value) {
- setRgba({
- ...rgba,
- a: Number.parseInt(e.target.value, 10),
- });
- setColorValue(
- `${colorValue.substring(0, 7)}${Number.parseInt(e.target.value, 10).toString(16).padStart(2, '0')}`,
- );
- } else {
- setRgba({
- ...rgba,
- a: 0,
- });
- }
- }}
- />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
)}
{backgroundPicker && (
-
-
- {
- setQuery('');
- }}
- />
- }
- onChange={(event) => {
- setQuery(event.currentTarget.value);
- setHovered(-1);
- }}
- onKeyDown={(event) => {
- if (event.key === 'ArrowDown') {
- event.preventDefault();
- setHovered((current) => {
- const nextIndex =
- current + 1 >= filtered.length ? current : current + 1;
- viewportRef.current
- ?.querySelectorAll('[data-list-item]')
- ?.[nextIndex]?.scrollIntoView({ block: 'nearest' });
- return nextIndex;
- });
- }
-
- if (event.key === 'ArrowUp') {
- event.preventDefault();
- setHovered((current) => {
- const nextIndex = current - 1 < 0 ? current : current - 1;
- viewportRef.current
- ?.querySelectorAll('[data-list-item]')
- ?.[nextIndex]?.scrollIntoView({ block: 'nearest' });
- return nextIndex;
- });
- }
- }}
- />
-
-
-
- {items}
-
-
-
-
-
-
-
+
)}
{!pickerOpen && !backgroundPicker && (
-
-
-
- {
- setDesignerTheme({
- ...designerTheme,
- textShadowsEnabled: e ? 1 : 0,
- });
- }}
- style={{
- border: 'none',
- filter: `grayscale(${designerTheme.textShadowsEnabled === 1 ? 0 : '75%'}) brightness(${designerTheme.textShadowsEnabled === 1 ? '1' : '1.5'})`,
- transition: 'all 1s ease',
- }}
- >
-
-
-
- Shadows
-
-
-
-
- {
- setDesignerTheme({
- ...designerTheme,
- appShadowsEnabled: e ? 1 : 0,
- });
- }}
- style={{
- border: 'none',
- filter: `grayscale(${designerTheme.appShadowsEnabled === 1 ? 0 : '75%'}) brightness(${designerTheme.appShadowsEnabled === 1 ? '1' : '1.5'})`,
- transition: 'all 1s ease',
- }}
- >
-
-
-
-
-
-
-
-
-
- {
- setCustomFontEnabled(!customFontEnabled);
- setFont(
- customFontEnabled
- ? currentUser.defaultFont
- : defaultTheme.themeFont,
- );
- }}
- style={{
- borderRadius: '0px',
- filter: `grayscale(${customFontEnabled ? 0 : '75%'})`,
- }}
- >
-
-
-
- {
- if (!customFontEnabled) {
- e.preventDefault();
- e.stopPropagation();
- }
- }}
- pos={'relative'}
- >
- {!customFontEnabled && }
- {
- if (customFontEnabled) {
- setFont(pickerFont);
- }
- }}
- />
-
-
- {
- setFont(currentUser.defaultFont);
- setCustomFontEnabled(false);
- }}
- style={{
- borderRadius: '0px',
- }}
- >
-
-
-
-
-
- {JSON.stringify(defaultTheme) !== JSON.stringify(designerTheme) && (
-
-
- Changes
-
-
-
- {getObjectDiff(defaultTheme, designerTheme) !== null &&
- Object.keys(getObjectDiff(defaultTheme, designerTheme)).map(
- (key: any) => {
- return (
- key !== 'id' && (
-
-
-
- {
- ThemeProperties[
- key as keyof typeof ThemeProperties
- ]
- }
-
-
- {
- setDesignerTheme({
- ...designerTheme,
- [key]: defaultTheme[key as keyof Theme],
- });
- }}
- pos={'absolute'}
- right={0}
- >
-
-
-
-
-
- {key === 'name' && (
- <>
- {defaultTheme[key as keyof Theme]}
- →
- {designerTheme[key as keyof Theme]}
- >
- )}
- {key.includes('Shadow') && (
- <>
- {defaultTheme[key as keyof Theme] === 0 ? (
- Off
- ) : (
- On
- )}
- →
- {designerTheme[key as keyof Theme] === 0 ? (
- Off
- ) : (
- On
- )}
- >
- )}
- {key.includes('Font') && (
- <>
-
- {defaultTheme[key as keyof Theme] ||
- `Default (${currentUser.defaultFont})`}
-
- →
-
- {designerTheme[key as keyof Theme] ||
- `Default (${currentUser.defaultFont})`}
-
- >
- )}
- {key === 'backgroundImage' && (
- <>
-
- →
-
- >
- )}
- {key.includes('Color') && (
- <>
-
- {
- navigator.clipboard.writeText(
- defaultTheme[
- key as keyof Theme
- ] as string,
- );
- notifications.show({
- title: (
-
- Copied{' '}
- {
- ThemeProperties[
- key as keyof typeof ThemeProperties
- ]
- }
-
- ),
- message: (
-
- {
- defaultTheme[
- key as keyof Theme
- ] as string
- }
-
- ),
- autoClose: true,
- withCloseButton: true,
- icon: ,
- });
- }}
- color={
- defaultTheme[key as keyof Theme] as string
- }
- style={{
- cursor: 'pointer',
- }}
- styles={{
- alphaOverlay: {
- borderRadius: '0px',
- },
- colorOverlay: {
- borderRadius: '0px',
- },
- shadowOverlay: {
- borderRadius: '0px',
- },
- childrenOverlay: {
- borderRadius: '0px',
- },
- }}
- />
-
- →
-
- {
- navigator.clipboard.writeText(
- defaultTheme[
- key as keyof Theme
- ] as string,
- );
- notifications.show({
- title: (
-
- Copied{' '}
- {
- ThemeProperties[
- key as keyof typeof ThemeProperties
- ]
- }
-
- ),
- message: (
-
- {
- designerTheme[
- key as keyof Theme
- ] as string
- }
-
- ),
- autoClose: true,
- withCloseButton: true,
- icon: ,
- });
- }}
- color={
- designerTheme[key as keyof Theme] as string
- }
- style={{
- cursor: 'pointer',
- }}
- styles={{
- alphaOverlay: {
- borderRadius: '0px',
- },
- colorOverlay: {
- borderRadius: '0px',
- },
- shadowOverlay: {
- borderRadius: '0px',
- },
- childrenOverlay: {
- borderRadius: '0px',
- },
- }}
- />
-
- >
- )}
-
-
- )
- );
- },
- )}
-
-
-
- )}
-
-
-
-
-
-
-
+
)}
diff --git a/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeOptions.tsx b/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeOptions.tsx
new file mode 100644
index 0000000..d341c5e
--- /dev/null
+++ b/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeOptions.tsx
@@ -0,0 +1,245 @@
+import {
+ ActionIcon,
+ Box,
+ Button,
+ Checkbox,
+ Group,
+ Overlay,
+ Stack,
+ Text,
+ Tooltip,
+} from '@mantine/core';
+import { useCommonHooks } from 'hooks';
+import FontPicker from 'react-fontpicker-ts';
+import { FaFont, FaGoogle } from 'react-icons/fa';
+import { FaShuffle } from 'react-icons/fa6';
+import { FiX } from 'react-icons/fi';
+import { textClasses, toolTipClasses } from 'styles';
+import type { Theme } from 'types';
+import ThemeChanges from './ThemeChanges';
+
+export default function ThemeOptions({
+ defaultTheme,
+ designerTheme,
+ setDesignerTheme,
+ setFont,
+ customFontEnabled,
+ setCustomFontEnabled,
+ duplicate,
+ randomColor,
+}: {
+ defaultTheme: Theme;
+ designerTheme: any;
+ setDesignerTheme: any;
+ setFont: any;
+ customFontEnabled: boolean;
+ setCustomFontEnabled: any;
+ duplicate: boolean;
+ randomColor: (withAlpha?: boolean) => string;
+}) {
+ const { currentUser } = useCommonHooks();
+ return (
+
+
+
+ {
+ setDesignerTheme({
+ ...designerTheme,
+ textShadowsEnabled: e ? 1 : 0,
+ });
+ }}
+ style={{
+ border: 'none',
+ filter: `grayscale(${designerTheme.textShadowsEnabled === 1 ? 0 : '75%'}) brightness(${designerTheme.textShadowsEnabled === 1 ? '1' : '1.5'})`,
+ transition: 'all 1s ease',
+ }}
+ >
+
+
+
+ Shadows
+
+
+
+
+ {
+ setDesignerTheme({
+ ...designerTheme,
+ appShadowsEnabled: e ? 1 : 0,
+ });
+ }}
+ style={{
+ border: 'none',
+ filter: `grayscale(${designerTheme.appShadowsEnabled === 1 ? 0 : '75%'}) brightness(${designerTheme.appShadowsEnabled === 1 ? '1' : '1.5'})`,
+ transition: 'all 1s ease',
+ }}
+ >
+
+
+
+
+
+
+
+
+
+ {
+ setCustomFontEnabled(!customFontEnabled);
+ setFont(
+ customFontEnabled ? currentUser.defaultFont : defaultTheme.themeFont,
+ );
+ }}
+ style={{
+ borderRadius: '0px',
+ filter: `grayscale(${customFontEnabled ? 0 : '75%'})`,
+ }}
+ >
+
+
+
+ {
+ if (!customFontEnabled) {
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ }}
+ pos={'relative'}
+ >
+ {!customFontEnabled && }
+ {
+ if (customFontEnabled) {
+ setFont(pickerFont);
+ }
+ }}
+ />
+
+
+ {
+ setFont(currentUser.defaultFont);
+ setCustomFontEnabled(false);
+ }}
+ style={{
+ borderRadius: '0px',
+ }}
+ >
+
+
+
+
+
+ {JSON.stringify(defaultTheme) !== JSON.stringify(designerTheme) && (
+
+ )}
+
+
+
+
+
+
+
+ );
+}