Bug fixes and refactoring
This commit is contained in:
@@ -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 (
|
||||||
|
<UnstyledButton
|
||||||
|
data-list-item
|
||||||
|
key={item}
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
height: '75px',
|
||||||
|
background:
|
||||||
|
item !== 'none' && item !== 'None'
|
||||||
|
? index === hovered
|
||||||
|
? `linear-gradient(${designerTheme.backgroundColor}88, ${designerTheme.backgroundColor}88), no-repeat center url(../../api/backgroundImages/thumbs/${item})`
|
||||||
|
: `no-repeat center url(../../api/backgroundImages/thumbs/${item})`
|
||||||
|
: 'repeating-linear-gradient(45deg, #33333366, #33333366 10px, #88888866 10px, #88888866 20px)',
|
||||||
|
backgroundSize: item === 'none' ? undefined : 'cover',
|
||||||
|
backgroundColor: item === 'none' ? '#00000088' : undefined,
|
||||||
|
paddingLeft: '.5rem',
|
||||||
|
alignItems: 'center',
|
||||||
|
}}
|
||||||
|
onClick={() =>
|
||||||
|
setDesignerTheme({
|
||||||
|
...designerTheme,
|
||||||
|
backgroundImage: item,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Group
|
||||||
|
h={'100%'}
|
||||||
|
w={'100%'}
|
||||||
|
justify='space-between'
|
||||||
|
style={{ textOverflow: 'hidden', whiteSpace: 'nowrap' }}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
width: 'min-content',
|
||||||
|
maxWidth: '170px',
|
||||||
|
backdropFilter: 'blur(5px) brightness(.25)',
|
||||||
|
padding: '.5rem',
|
||||||
|
borderBottomRightRadius: 4,
|
||||||
|
marginTop: '-2.15rem',
|
||||||
|
marginLeft: '-.5rem',
|
||||||
|
color: 'white',
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{item.replace(/\.[^/.]+$/, '')}
|
||||||
|
</Text>
|
||||||
|
{item !== 'None' && (
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
width: 'min-content',
|
||||||
|
backdropFilter: 'blur(5px) brightness(.25)',
|
||||||
|
padding: '.5rem',
|
||||||
|
marginTop: '2rem',
|
||||||
|
marginBottom: -1,
|
||||||
|
borderTopLeftRadius: 4,
|
||||||
|
color: 'white',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{re.exec(item.toUpperCase())?.[1]}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</Group>
|
||||||
|
</UnstyledButton>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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<HTMLDivElement>(null);
|
||||||
|
return (
|
||||||
|
<Stack h={'100%'} align='center' justify='center'>
|
||||||
|
<Group gap={0}>
|
||||||
|
<TextInput
|
||||||
|
className={textInputClasses.default}
|
||||||
|
classNames={textInputClasses}
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
color: 'var(--mantine-color-primary-0)',
|
||||||
|
},
|
||||||
|
input: {
|
||||||
|
color: designerTheme.primaryColor,
|
||||||
|
backgroundColor: designerTheme.backgroundColor,
|
||||||
|
border: 'none',
|
||||||
|
borderBottom: '1px solid var(--mantine-color-primary-0)',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
placeholder='Search'
|
||||||
|
value={query.replace(/\.[^/.]+$/, '')}
|
||||||
|
rightSection={
|
||||||
|
<FiX
|
||||||
|
style={{
|
||||||
|
cursor: 'pointer',
|
||||||
|
margin: '.25rem',
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
<ScrollArea.Autosize
|
||||||
|
viewportRef={viewportRef}
|
||||||
|
className={scrollAreaClasses.default}
|
||||||
|
classNames={scrollAreaClasses}
|
||||||
|
style={{
|
||||||
|
height: 325,
|
||||||
|
width: '90%',
|
||||||
|
borderRadius: 8,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Stack gap={0} align='center' display={'block'}>
|
||||||
|
{filtered.map((image: string, index: number) => (
|
||||||
|
<BackgroundItem
|
||||||
|
key={image}
|
||||||
|
item={image}
|
||||||
|
index={index}
|
||||||
|
hovered={hovered}
|
||||||
|
designerTheme={designerTheme}
|
||||||
|
setDesignerTheme={setDesignerTheme}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
</ScrollArea.Autosize>
|
||||||
|
<Group justify='center'>
|
||||||
|
<Button
|
||||||
|
color={'green'}
|
||||||
|
onClick={() => {
|
||||||
|
setDesignerTheme({
|
||||||
|
...designerTheme,
|
||||||
|
backgroundImage: designerTheme.backgroundImage,
|
||||||
|
});
|
||||||
|
closeBackgroundPicker();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FiSave />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
color={'red'}
|
||||||
|
styles={{ label: { color: 'black' } }}
|
||||||
|
onClick={() => {
|
||||||
|
closeBackgroundPicker();
|
||||||
|
setDesignerTheme({
|
||||||
|
...designerTheme,
|
||||||
|
backgroundImage: defaultTheme.backgroundImage,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FiX />
|
||||||
|
</Button>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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 (
|
||||||
|
<Stack
|
||||||
|
gap={0}
|
||||||
|
w={'95%'}
|
||||||
|
h={'calc(100% - 144px)'}
|
||||||
|
align='center'
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'var(--mantine-color-background-0)',
|
||||||
|
borderRadius: 8,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
c={'var(--mantine-color-primary-0)'}
|
||||||
|
fz={'1.5rem'}
|
||||||
|
w={'100%'}
|
||||||
|
style={{
|
||||||
|
textAlign: 'center',
|
||||||
|
borderBottom: '1px solid var(--mantine-color-primary-0',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Changes
|
||||||
|
</Text>
|
||||||
|
<ScrollArea.Autosize
|
||||||
|
w={'100%'}
|
||||||
|
className={scrollAreaClasses.default}
|
||||||
|
classNames={scrollAreaClasses}
|
||||||
|
style={{
|
||||||
|
padding: '1rem',
|
||||||
|
}}
|
||||||
|
styles={{
|
||||||
|
scrollbar: {
|
||||||
|
position: 'absolute',
|
||||||
|
right: -2,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Stack w={'95%'} gap={2}>
|
||||||
|
{getObjectDiff(defaultTheme, designerTheme) !== null &&
|
||||||
|
Object.keys(getObjectDiff(defaultTheme, designerTheme)).map((key: any) => {
|
||||||
|
return (
|
||||||
|
key !== 'id' && (
|
||||||
|
<Stack w={'100%'} align='center' justify='center' gap={0} key={key}>
|
||||||
|
<Group w={'100%'} justify='space-between' pos={'relative'}>
|
||||||
|
<Text
|
||||||
|
w={'100%'}
|
||||||
|
key={key}
|
||||||
|
pl={2}
|
||||||
|
style={{
|
||||||
|
color: 'var(--mantine-color-primary-0)',
|
||||||
|
backgroundColor: 'var(--mantine-color-background-0)',
|
||||||
|
overflow: 'clip',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{ThemeProperties[key as keyof typeof ThemeProperties]}
|
||||||
|
</Text>
|
||||||
|
<Tooltip
|
||||||
|
label={`Reset ${
|
||||||
|
ThemeProperties[key as keyof typeof ThemeProperties]
|
||||||
|
}`}
|
||||||
|
classNames={toolTipClasses}
|
||||||
|
className={toolTipClasses.default}
|
||||||
|
>
|
||||||
|
<ActionIcon
|
||||||
|
disabled={duplicate && key === 'name'}
|
||||||
|
variant='subtle'
|
||||||
|
color='red'
|
||||||
|
onClick={() => {
|
||||||
|
setDesignerTheme({
|
||||||
|
...designerTheme,
|
||||||
|
[key]: defaultTheme[key as keyof Theme],
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
pos={'absolute'}
|
||||||
|
right={0}
|
||||||
|
>
|
||||||
|
<FiX />
|
||||||
|
</ActionIcon>
|
||||||
|
</Tooltip>
|
||||||
|
</Group>
|
||||||
|
<Group
|
||||||
|
w={'100%'}
|
||||||
|
justify={key.includes('Color') ? 'space-between' : 'center'}
|
||||||
|
gap={key.includes('Color') ? 4 : 0}
|
||||||
|
bg='var(--mantine-color-accent-0)'
|
||||||
|
c='var(--mantine-color-background-0)'
|
||||||
|
style={{ borderRadius: 8, overflow: 'clip' }}
|
||||||
|
h={48}
|
||||||
|
>
|
||||||
|
{key === 'name' && (
|
||||||
|
<Group w={'95%'} justify='space-between'>
|
||||||
|
<Text>{defaultTheme[key as keyof Theme]}</Text>
|
||||||
|
<Text>→</Text>
|
||||||
|
<Text>{designerTheme[key as keyof Theme]}</Text>
|
||||||
|
</Group>
|
||||||
|
)}
|
||||||
|
{key.includes('Shadow') && (
|
||||||
|
<Group w={'95%'} justify='space-between'>
|
||||||
|
{defaultTheme[key as keyof Theme] === 0 ? (
|
||||||
|
<Text>Off</Text>
|
||||||
|
) : (
|
||||||
|
<Text>On</Text>
|
||||||
|
)}
|
||||||
|
<Text>→</Text>
|
||||||
|
{designerTheme[key as keyof Theme] === 0 ? (
|
||||||
|
<Text>Off</Text>
|
||||||
|
) : (
|
||||||
|
<Text>On</Text>
|
||||||
|
)}
|
||||||
|
</Group>
|
||||||
|
)}
|
||||||
|
{key.includes('Font') && (
|
||||||
|
<>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontFamily:
|
||||||
|
(defaultTheme[key as keyof Theme] as string) ?? undefined,
|
||||||
|
fontSize: 18,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{defaultTheme[key as keyof Theme] ||
|
||||||
|
`Default (${currentUser.defaultFont})`}
|
||||||
|
</Text>
|
||||||
|
<Text>→</Text>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontFamily: designerTheme.themeFont ?? undefined,
|
||||||
|
fontSize: 18,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{designerTheme[key as keyof Theme] ||
|
||||||
|
`Default (${currentUser.defaultFont})`}
|
||||||
|
</Text>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{key === 'backgroundImage' && (
|
||||||
|
<>
|
||||||
|
<Image
|
||||||
|
w={'40%'}
|
||||||
|
src={
|
||||||
|
(
|
||||||
|
defaultTheme[key as keyof Theme] as string
|
||||||
|
).toLocaleLowerCase() === 'none'
|
||||||
|
? 'https://placehold.co/540x360?text=None'
|
||||||
|
: `../../api/backgroundImages/thumbs/${defaultTheme[key as keyof Theme] as string}`
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Text>→</Text>
|
||||||
|
<Image
|
||||||
|
w={'40%'}
|
||||||
|
src={
|
||||||
|
(
|
||||||
|
designerTheme[key as keyof Theme] as string
|
||||||
|
).toLocaleLowerCase() === 'none'
|
||||||
|
? 'https://placehold.co/540x360?text=None'
|
||||||
|
: `../../api/backgroundImages/thumbs/${designerTheme[key as keyof Theme] as string}`
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{key.includes('Color') && (
|
||||||
|
<>
|
||||||
|
<Tooltip
|
||||||
|
label='Copy color code'
|
||||||
|
classNames={toolTipClasses}
|
||||||
|
className={toolTipClasses.default}
|
||||||
|
>
|
||||||
|
<ColorSwatch
|
||||||
|
h={50}
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(
|
||||||
|
defaultTheme[key as keyof Theme] as string,
|
||||||
|
);
|
||||||
|
notifications.show({
|
||||||
|
title: (
|
||||||
|
<Text fw={600} c={'var(--mantine-color-accent-0)'}>
|
||||||
|
Copied{' '}
|
||||||
|
{
|
||||||
|
ThemeProperties[
|
||||||
|
key as keyof typeof ThemeProperties
|
||||||
|
]
|
||||||
|
}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
message: (
|
||||||
|
<Text c={'var(--mantine-color-primary-0)'}>
|
||||||
|
{defaultTheme[key as keyof Theme] as string}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
autoClose: true,
|
||||||
|
withCloseButton: true,
|
||||||
|
icon: <FaClipboard size={24} />,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
color={defaultTheme[key as keyof Theme] as string}
|
||||||
|
style={{
|
||||||
|
cursor: 'pointer',
|
||||||
|
}}
|
||||||
|
styles={{
|
||||||
|
alphaOverlay: {
|
||||||
|
borderRadius: '0px',
|
||||||
|
},
|
||||||
|
colorOverlay: {
|
||||||
|
borderRadius: '0px',
|
||||||
|
},
|
||||||
|
shadowOverlay: {
|
||||||
|
borderRadius: '0px',
|
||||||
|
},
|
||||||
|
childrenOverlay: {
|
||||||
|
borderRadius: '0px',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
<Text>→</Text>
|
||||||
|
<Tooltip
|
||||||
|
label='Copy color code'
|
||||||
|
classNames={toolTipClasses}
|
||||||
|
className={toolTipClasses.default}
|
||||||
|
>
|
||||||
|
<ColorSwatch
|
||||||
|
h={50}
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(
|
||||||
|
defaultTheme[key as keyof Theme] as string,
|
||||||
|
);
|
||||||
|
notifications.show({
|
||||||
|
title: (
|
||||||
|
<Text fw={600} c={'var(--mantine-color-accent-0)'}>
|
||||||
|
Copied{' '}
|
||||||
|
{
|
||||||
|
ThemeProperties[
|
||||||
|
key as keyof typeof ThemeProperties
|
||||||
|
]
|
||||||
|
}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
message: (
|
||||||
|
<Text c={'var(--mantine-color-primary-0)'}>
|
||||||
|
{designerTheme[key as keyof Theme] as string}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
autoClose: true,
|
||||||
|
withCloseButton: true,
|
||||||
|
icon: <FaClipboard size={24} />,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
color={designerTheme[key as keyof Theme] as string}
|
||||||
|
style={{
|
||||||
|
cursor: 'pointer',
|
||||||
|
}}
|
||||||
|
styles={{
|
||||||
|
alphaOverlay: {
|
||||||
|
borderRadius: '0px',
|
||||||
|
},
|
||||||
|
colorOverlay: {
|
||||||
|
borderRadius: '0px',
|
||||||
|
},
|
||||||
|
shadowOverlay: {
|
||||||
|
borderRadius: '0px',
|
||||||
|
},
|
||||||
|
childrenOverlay: {
|
||||||
|
borderRadius: '0px',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Stack>
|
||||||
|
</ScrollArea.Autosize>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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 (
|
||||||
|
<Stack h={'100%'} align='center'>
|
||||||
|
<Text
|
||||||
|
className={textClasses.sectionTitle}
|
||||||
|
classNames={textClasses}
|
||||||
|
c={'var(--mantine-color-background-0)'}
|
||||||
|
style={{
|
||||||
|
textShadow: theme.textShadowsEnabled ? textShadowStyle : undefined,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Change {ThemeProperties[colorId as keyof typeof ThemeProperties]}
|
||||||
|
</Text>
|
||||||
|
{colorId === 'searchColor' && (
|
||||||
|
<ColorPicker
|
||||||
|
value={colorValue}
|
||||||
|
onChange={(e) => {
|
||||||
|
setColorValue(e);
|
||||||
|
setDesignerTheme({
|
||||||
|
...designerTheme,
|
||||||
|
[colorId]: e,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
format={'hexa'}
|
||||||
|
w={'90%'}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{colorId !== 'searchColor' && (
|
||||||
|
<ColorPicker
|
||||||
|
value={colorValue}
|
||||||
|
onChange={(e) => {
|
||||||
|
setColorValue(e);
|
||||||
|
setDesignerTheme({
|
||||||
|
...designerTheme,
|
||||||
|
[colorId]: e,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
format={'hex'}
|
||||||
|
w={'90%'}
|
||||||
|
mb={'1.5rem'}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Stack w={'90%'} gap={0}>
|
||||||
|
<TextInput
|
||||||
|
className={textInputClasses.colorSwatchInput}
|
||||||
|
classNames={textInputClasses}
|
||||||
|
label={'Hex Value'}
|
||||||
|
value={colorValue}
|
||||||
|
onChange={(e) => setColorValue(e.target.value)}
|
||||||
|
/>
|
||||||
|
<Group gap={0} w={'100%'} justify='space-between'>
|
||||||
|
<TextInput
|
||||||
|
className={textInputClasses.colorSwatchInput}
|
||||||
|
classNames={textInputClasses}
|
||||||
|
label={'Red'}
|
||||||
|
w={'23%'}
|
||||||
|
value={rgba.r}
|
||||||
|
onChange={(e) => {
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
className={textInputClasses.colorSwatchInput}
|
||||||
|
classNames={textInputClasses}
|
||||||
|
label={'Green'}
|
||||||
|
w={'23%'}
|
||||||
|
value={rgba.g}
|
||||||
|
onChange={(e) => {
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
className={textInputClasses.colorSwatchInput}
|
||||||
|
classNames={textInputClasses}
|
||||||
|
label={'Blue'}
|
||||||
|
w={'23%'}
|
||||||
|
value={rgba.b}
|
||||||
|
onChange={(e) => {
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
disabled={colorId !== 'searchColor'}
|
||||||
|
className={textInputClasses.colorSwatchInput}
|
||||||
|
classNames={textInputClasses}
|
||||||
|
label={'Alpha'}
|
||||||
|
w={'23%'}
|
||||||
|
value={rgba.a}
|
||||||
|
onChange={(e) => {
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
<Group mt={'auto'} justify='center' mih={'36px'} pb={'1.5rem'}>
|
||||||
|
<Tooltip
|
||||||
|
label={'Random Color'}
|
||||||
|
className={toolTipClasses.default}
|
||||||
|
classNames={toolTipClasses}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
c={'white'}
|
||||||
|
onClick={() => {
|
||||||
|
const rc = randomColor(colorId === 'searchColor');
|
||||||
|
setColorValue(rc);
|
||||||
|
setDesignerTheme({
|
||||||
|
...designerTheme,
|
||||||
|
[colorId]: rc,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FiShuffle />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip
|
||||||
|
label={'Reset Color'}
|
||||||
|
className={toolTipClasses.default}
|
||||||
|
classNames={toolTipClasses}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
color={'red'}
|
||||||
|
styles={{ label: { color: 'black' } }}
|
||||||
|
onClick={() => {
|
||||||
|
setColorValue(defaultTheme[colorId as keyof Theme] as string);
|
||||||
|
setDesignerTheme({
|
||||||
|
...designerTheme,
|
||||||
|
[colorId]: defaultTheme[colorId as keyof Theme],
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FiRefreshCcw />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip
|
||||||
|
label={'Done'}
|
||||||
|
className={toolTipClasses.default}
|
||||||
|
classNames={toolTipClasses}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
color={'green'}
|
||||||
|
onClick={() => {
|
||||||
|
setDesignerTheme({
|
||||||
|
...designerTheme,
|
||||||
|
[colorId]: colorValue,
|
||||||
|
});
|
||||||
|
|
||||||
|
closePicker();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FaCheck />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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 (
|
||||||
|
<>
|
||||||
|
<Tooltip
|
||||||
|
label={'Change Primary Color'}
|
||||||
|
className={toolTipClasses.default}
|
||||||
|
classNames={toolTipClasses}
|
||||||
|
>
|
||||||
|
<ColorSwatch
|
||||||
|
onClick={() => {
|
||||||
|
handleSwatchClick('primaryColor', designerTheme.primaryColor);
|
||||||
|
}}
|
||||||
|
color={designerTheme.primaryColor}
|
||||||
|
style={{ borderColor: designerTheme.primaryColor }}
|
||||||
|
className={colorSwatchClasses.themeDesignerSwatch}
|
||||||
|
classNames={colorSwatchClasses}
|
||||||
|
top={'11.5rem'}
|
||||||
|
left={'8.5rem'}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip
|
||||||
|
label={'Change Accent Color'}
|
||||||
|
className={toolTipClasses.default}
|
||||||
|
classNames={toolTipClasses}
|
||||||
|
>
|
||||||
|
<ColorSwatch
|
||||||
|
onClick={() => {
|
||||||
|
handleSwatchClick('accentColor', designerTheme.accentColor);
|
||||||
|
}}
|
||||||
|
color={designerTheme.accentColor}
|
||||||
|
style={{ borderColor: designerTheme.primaryColor }}
|
||||||
|
className={colorSwatchClasses.themeDesignerSwatch}
|
||||||
|
classNames={colorSwatchClasses}
|
||||||
|
bottom={'6rem'}
|
||||||
|
left={'11rem'}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip
|
||||||
|
label={'Change Background Color'}
|
||||||
|
className={toolTipClasses.default}
|
||||||
|
classNames={toolTipClasses}
|
||||||
|
>
|
||||||
|
<ColorSwatch
|
||||||
|
onClick={() => {
|
||||||
|
handleSwatchClick('backgroundColor', designerTheme.backgroundColor);
|
||||||
|
}}
|
||||||
|
color={designerTheme.backgroundColor}
|
||||||
|
style={{ borderColor: designerTheme.primaryColor }}
|
||||||
|
className={colorSwatchClasses.themeDesignerSwatch}
|
||||||
|
classNames={colorSwatchClasses}
|
||||||
|
bottom={'4rem'}
|
||||||
|
right={'3.5rem'}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip
|
||||||
|
label={'Change Border Color'}
|
||||||
|
className={toolTipClasses.default}
|
||||||
|
classNames={toolTipClasses}
|
||||||
|
>
|
||||||
|
<ColorSwatch
|
||||||
|
onClick={() => {
|
||||||
|
handleSwatchClick('borderColor', designerTheme.borderColor);
|
||||||
|
}}
|
||||||
|
color={designerTheme.borderColor}
|
||||||
|
style={{ borderColor: designerTheme.primaryColor }}
|
||||||
|
className={colorSwatchClasses.themeDesignerSwatch}
|
||||||
|
classNames={colorSwatchClasses}
|
||||||
|
top={'4.5rem'}
|
||||||
|
right={'15%'}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip
|
||||||
|
label={'Change Search Color'}
|
||||||
|
className={toolTipClasses.default}
|
||||||
|
classNames={toolTipClasses}
|
||||||
|
>
|
||||||
|
<ColorSwatch
|
||||||
|
onClick={() => {
|
||||||
|
handleSwatchClick('searchColor', designerTheme.searchColor);
|
||||||
|
}}
|
||||||
|
color={designerTheme.searchColor}
|
||||||
|
style={{ borderColor: designerTheme.primaryColor }}
|
||||||
|
className={colorSwatchClasses.themeDesignerSwatch}
|
||||||
|
classNames={colorSwatchClasses}
|
||||||
|
top={'3.25rem'}
|
||||||
|
left={'6.5rem'}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip
|
||||||
|
label={'Change Background'}
|
||||||
|
className={toolTipClasses.default}
|
||||||
|
classNames={toolTipClasses}
|
||||||
|
>
|
||||||
|
<ActionIcon
|
||||||
|
onClick={() => {
|
||||||
|
closePicker();
|
||||||
|
openBackgroundPicker();
|
||||||
|
setDesignerTheme(designerTheme);
|
||||||
|
}}
|
||||||
|
pos={'absolute'}
|
||||||
|
right={0}
|
||||||
|
style={{
|
||||||
|
color: designerTheme.backgroundColor,
|
||||||
|
backgroundColor: designerTheme.primaryColor,
|
||||||
|
borderRadius: 0,
|
||||||
|
borderBottomLeftRadius: 10,
|
||||||
|
borderTopRightRadius: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FiImage size={20} />
|
||||||
|
</ActionIcon>
|
||||||
|
</Tooltip>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -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 (
|
||||||
|
<Stack h={'100%'} justify='space-between' align='center' gap={4}>
|
||||||
|
<Stack w={'100%'} align='center' gap={0} h={'min-content'}>
|
||||||
|
<Group gap={2} w={'100%'} justify='space-between' align='center'>
|
||||||
|
<Checkbox.Card
|
||||||
|
w={'calc(50% - 1px)'}
|
||||||
|
checked={designerTheme.textShadowsEnabled === 1}
|
||||||
|
c={'var(--mantine-color-background-0)'}
|
||||||
|
onChange={(e) => {
|
||||||
|
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',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Tooltip
|
||||||
|
label='Text Shadows'
|
||||||
|
className={toolTipClasses.default}
|
||||||
|
classNames={toolTipClasses}
|
||||||
|
>
|
||||||
|
<Group
|
||||||
|
w={'100%'}
|
||||||
|
justify='center'
|
||||||
|
style={{
|
||||||
|
backgroundColor: designerTheme.backgroundColor,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
classNames={textClasses}
|
||||||
|
className={textClasses.sectionTitle}
|
||||||
|
style={{
|
||||||
|
color: designerTheme.accentColor,
|
||||||
|
textShadow: `2px 2px ${designerTheme.primaryColor}`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Shadows
|
||||||
|
</Text>
|
||||||
|
</Group>
|
||||||
|
</Tooltip>
|
||||||
|
</Checkbox.Card>
|
||||||
|
<Checkbox.Card
|
||||||
|
w={'calc(50% - 1px)'}
|
||||||
|
checked={designerTheme.appShadowsEnabled === 1}
|
||||||
|
c={'var(--mantine-color-background-0)'}
|
||||||
|
onChange={(e) => {
|
||||||
|
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',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Tooltip
|
||||||
|
label='Icon Shadows'
|
||||||
|
className={toolTipClasses.default}
|
||||||
|
classNames={toolTipClasses}
|
||||||
|
>
|
||||||
|
<Group
|
||||||
|
w={'100%'}
|
||||||
|
justify='center'
|
||||||
|
align='center'
|
||||||
|
style={{
|
||||||
|
backgroundColor: designerTheme.backgroundColor,
|
||||||
|
overflow: 'clip',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FaGoogle
|
||||||
|
style={{
|
||||||
|
marginTop: '12px',
|
||||||
|
marginBottom: '7px',
|
||||||
|
color: designerTheme.primaryColor,
|
||||||
|
height: 32,
|
||||||
|
width: 32,
|
||||||
|
filter: `drop-shadow(2px 2px color-mix(in srgb, ${designerTheme.accentColor}, transparent 30%))`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
</Tooltip>
|
||||||
|
</Checkbox.Card>
|
||||||
|
</Group>
|
||||||
|
<Group w={'100%'} gap={0} justify='center'>
|
||||||
|
<Tooltip
|
||||||
|
label={`Custom Font ${customFontEnabled ? 'Enabled' : 'Disabled'}`}
|
||||||
|
className={toolTipClasses.default}
|
||||||
|
classNames={toolTipClasses}
|
||||||
|
>
|
||||||
|
<ActionIcon
|
||||||
|
color={'red'}
|
||||||
|
size={32}
|
||||||
|
onClick={() => {
|
||||||
|
setCustomFontEnabled(!customFontEnabled);
|
||||||
|
setFont(
|
||||||
|
customFontEnabled ? currentUser.defaultFont : defaultTheme.themeFont,
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
borderRadius: '0px',
|
||||||
|
filter: `grayscale(${customFontEnabled ? 0 : '75%'})`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FaFont />
|
||||||
|
</ActionIcon>
|
||||||
|
</Tooltip>
|
||||||
|
<Box
|
||||||
|
w={'calc(100% - 64px)'}
|
||||||
|
onClick={(e) => {
|
||||||
|
if (!customFontEnabled) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
pos={'relative'}
|
||||||
|
>
|
||||||
|
{!customFontEnabled && <Overlay pos={'absolute'} />}
|
||||||
|
<FontPicker
|
||||||
|
autoLoad
|
||||||
|
defaultValue={
|
||||||
|
designerTheme.themeFont === null
|
||||||
|
? currentUser.defaultFont
|
||||||
|
: designerTheme.themeFont
|
||||||
|
}
|
||||||
|
value={(pickerFont: string) => {
|
||||||
|
if (customFontEnabled) {
|
||||||
|
setFont(pickerFont);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<Tooltip
|
||||||
|
label='Reset to use default'
|
||||||
|
className={toolTipClasses.default}
|
||||||
|
classNames={toolTipClasses}
|
||||||
|
>
|
||||||
|
<ActionIcon
|
||||||
|
disabled={!customFontEnabled}
|
||||||
|
color={'red'}
|
||||||
|
size={32}
|
||||||
|
onClick={() => {
|
||||||
|
setFont(currentUser.defaultFont);
|
||||||
|
setCustomFontEnabled(false);
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
borderRadius: '0px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FiX />
|
||||||
|
</ActionIcon>
|
||||||
|
</Tooltip>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
{JSON.stringify(defaultTheme) !== JSON.stringify(designerTheme) && (
|
||||||
|
<ThemeChanges
|
||||||
|
duplicate={duplicate}
|
||||||
|
defaultTheme={defaultTheme}
|
||||||
|
designerTheme={designerTheme}
|
||||||
|
setDesignerTheme={setDesignerTheme}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Group mih={'36px'} pb={'1.5rem'}>
|
||||||
|
<Tooltip
|
||||||
|
label={'Randomize Colors!'}
|
||||||
|
c={'var(--mantine-color-primary-0)'}
|
||||||
|
bg={'var(--mantine-color-background-0)'}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setDesignerTheme({
|
||||||
|
...designerTheme,
|
||||||
|
backgroundColor: randomColor(),
|
||||||
|
searchColor: randomColor(true),
|
||||||
|
primaryColor: randomColor(),
|
||||||
|
accentColor: randomColor(),
|
||||||
|
borderColor: randomColor(),
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FaShuffle />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setCustomFontEnabled(defaultTheme.themeFont !== null);
|
||||||
|
duplicate
|
||||||
|
? setDesignerTheme({
|
||||||
|
...defaultTheme,
|
||||||
|
name: `${defaultTheme.name} copy`,
|
||||||
|
})
|
||||||
|
: setDesignerTheme({ ...defaultTheme });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Reset Changes
|
||||||
|
</Button>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user