Theme designer updates
This commit is contained in:
@@ -9,6 +9,9 @@ const appTheme = atom<any>({
|
|||||||
primaryColor: '#222222',
|
primaryColor: '#222222',
|
||||||
accentColor: '#5c5c5c',
|
accentColor: '#5c5c5c',
|
||||||
borderColor: '#5c5c5c',
|
borderColor: '#5c5c5c',
|
||||||
|
textShadowsEnabled: false,
|
||||||
|
appShadowsEnabled: false,
|
||||||
|
themeFont: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
export { appTheme };
|
export { appTheme };
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ export function useCommonHooks() {
|
|||||||
nickname: 'Boss',
|
nickname: 'Boss',
|
||||||
email: 'triggerUser@default.com',
|
email: 'triggerUser@default.com',
|
||||||
physicalAddress: '1510 Polk St, Houston, TX 77002',
|
physicalAddress: '1510 Polk St, Houston, TX 77002',
|
||||||
|
defaultFont: 'Jost',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const [currentLocation, setCurrentLocation] = useLocalStorage<Location>({
|
const [currentLocation, setCurrentLocation] = useLocalStorage<Location>({
|
||||||
|
|||||||
@@ -179,6 +179,8 @@ export default function Search({
|
|||||||
open(`${providerURL}${subtext}`, '_self');
|
open(`${providerURL}${subtext}`, '_self');
|
||||||
});
|
});
|
||||||
} else if (providerLabel === 'Show weather') {
|
} else if (providerLabel === 'Show weather') {
|
||||||
|
setSearchValue('');
|
||||||
|
closeDropdown();
|
||||||
openWeatherModal();
|
openWeatherModal();
|
||||||
} else if (providerLabel.startsWith('Launch')) {
|
} else if (providerLabel.startsWith('Launch')) {
|
||||||
const url = applications?.find((app: Application) =>
|
const url = applications?.find((app: Application) =>
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import {
|
import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
|
Box,
|
||||||
Button,
|
Button,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
ColorPicker,
|
ColorPicker,
|
||||||
ColorSwatch,
|
ColorSwatch,
|
||||||
Group,
|
Group,
|
||||||
Image,
|
Image,
|
||||||
|
Overlay,
|
||||||
ScrollArea,
|
ScrollArea,
|
||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
@@ -14,9 +16,11 @@ import {
|
|||||||
UnstyledButton,
|
UnstyledButton,
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useDisclosure } from '@mantine/hooks';
|
import { useDisclosure } from '@mantine/hooks';
|
||||||
|
import { notifications } from '@mantine/notifications';
|
||||||
import { useCommonHooks } from 'hooks';
|
import { useCommonHooks } from 'hooks';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import FontPicker from 'react-fontpicker-ts';
|
import FontPicker from 'react-fontpicker-ts';
|
||||||
|
import { FaClipboard, FaFont, FaGoogle } from 'react-icons/fa';
|
||||||
import { FaShuffle } from 'react-icons/fa6';
|
import { FaShuffle } from 'react-icons/fa6';
|
||||||
import { FiImage, FiSave, FiShuffle, FiX } from 'react-icons/fi';
|
import { FiImage, FiSave, FiShuffle, FiX } from 'react-icons/fi';
|
||||||
import {
|
import {
|
||||||
@@ -27,7 +31,7 @@ import {
|
|||||||
textInputClasses,
|
textInputClasses,
|
||||||
toolTipClasses,
|
toolTipClasses,
|
||||||
} from 'styles';
|
} from 'styles';
|
||||||
import { BackgroundProperties, type Theme } from 'types';
|
import { type Theme, ThemeProperties } from 'types';
|
||||||
import { ThemeModalContent } from './ThemeModalContent';
|
import { ThemeModalContent } from './ThemeModalContent';
|
||||||
|
|
||||||
export function ThemeEditor({
|
export function ThemeEditor({
|
||||||
@@ -61,31 +65,40 @@ export function ThemeEditor({
|
|||||||
}) {
|
}) {
|
||||||
const [query, setQuery] = useState('');
|
const [query, setQuery] = useState('');
|
||||||
const [hovered, setHovered] = useState(-1);
|
const [hovered, setHovered] = useState(-1);
|
||||||
const { isMobile, theme, getObjectDiff, textShadowStyle } = useCommonHooks();
|
const { currentUser, isMobile, theme, getObjectDiff, textShadowStyle } =
|
||||||
|
useCommonHooks();
|
||||||
const viewportRef = useRef<HTMLDivElement>(null);
|
const viewportRef = useRef<HTMLDivElement>(null);
|
||||||
const [colorId, setColorId] = useState<string>('');
|
const [colorId, setColorId] = useState<string>('');
|
||||||
const [colorValue, setColorValue] = useState('#000000');
|
const [colorValue, setColorValue] = useState('#000000');
|
||||||
const [font, setFont] = useState<Theme['themeFont']>();
|
const [font, setFont] = useState<Theme['themeFont']>();
|
||||||
|
const [customFontEnabled, setCustomFontEnabled] = useState<boolean>(false);
|
||||||
const re = /(?:\.([^.]+))?$/;
|
const re = /(?:\.([^.]+))?$/;
|
||||||
const [backgroundPicker, { open: openBackgroundPicker, close: closeBackgroundPicker }] =
|
const [backgroundPicker, { open: openBackgroundPicker, close: closeBackgroundPicker }] =
|
||||||
useDisclosure(false);
|
useDisclosure(false);
|
||||||
const filtered = backgroundList.filter((item: string) =>
|
const filtered = backgroundList.filter((item: string) =>
|
||||||
item.toLowerCase().includes(query.toLowerCase()),
|
item.toLowerCase().includes(query.toLowerCase()),
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (font) {
|
if (font) {
|
||||||
|
setCustomFontEnabled(true);
|
||||||
setSelectedTheme({
|
setSelectedTheme({
|
||||||
...selectedTheme,
|
...selectedTheme,
|
||||||
themeFont: font,
|
themeFont: font,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
setCustomFontEnabled(false);
|
||||||
setSelectedTheme({
|
setSelectedTheme({
|
||||||
...selectedTheme,
|
...selectedTheme,
|
||||||
themeFont: null,
|
themeFont: null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [font]);
|
}, [font]);
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedTheme) {
|
||||||
|
setCustomFontEnabled(selectedTheme.themeFont !== null);
|
||||||
|
setFont(selectedTheme.themeFont);
|
||||||
|
}
|
||||||
|
}, [selectedTheme]);
|
||||||
const items = filtered.map((item: string, index: number) => {
|
const items = filtered.map((item: string, index: number) => {
|
||||||
return (
|
return (
|
||||||
<UnstyledButton
|
<UnstyledButton
|
||||||
@@ -171,6 +184,7 @@ export function ThemeEditor({
|
|||||||
}
|
}
|
||||||
return color;
|
return color;
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Group p={'2rem'} w={'100%'} justify='space-between'>
|
<Group p={'2rem'} w={'100%'} justify='space-between'>
|
||||||
@@ -289,10 +303,10 @@ export function ThemeEditor({
|
|||||||
<Stack
|
<Stack
|
||||||
w={isMobile ? '100%' : '28%'}
|
w={isMobile ? '100%' : '28%'}
|
||||||
h={'450px'}
|
h={'450px'}
|
||||||
p={'1rem'}
|
|
||||||
style={{
|
style={{
|
||||||
borderRadius: '1rem',
|
borderRadius: '1rem',
|
||||||
backgroundColor: 'var(--mantine-color-accent-0)',
|
backgroundColor: 'var(--mantine-color-accent-0)',
|
||||||
|
overflow: 'clip',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{pickerOpen && (
|
{pickerOpen && (
|
||||||
@@ -305,8 +319,7 @@ export function ThemeEditor({
|
|||||||
textShadow: theme.textShadowsEnabled ? textShadowStyle : undefined,
|
textShadow: theme.textShadowsEnabled ? textShadowStyle : undefined,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Change{' '}
|
Change {ThemeProperties[colorId as keyof typeof ThemeProperties]}
|
||||||
{BackgroundProperties[colorId as keyof typeof BackgroundProperties]}
|
|
||||||
</Text>
|
</Text>
|
||||||
{colorId === 'searchColor' && (
|
{colorId === 'searchColor' && (
|
||||||
<ColorPicker
|
<ColorPicker
|
||||||
@@ -492,79 +505,200 @@ export function ThemeEditor({
|
|||||||
)}
|
)}
|
||||||
{!pickerOpen && !backgroundPicker && (
|
{!pickerOpen && !backgroundPicker && (
|
||||||
<Stack h={'100%'} justify='space-between' align='center' gap={4}>
|
<Stack h={'100%'} justify='space-between' align='center' gap={4}>
|
||||||
<Stack w={'100%'} align='center' gap={4}>
|
<Stack w={'100%'} align='center' gap={0} h={'min-content'}>
|
||||||
<Checkbox
|
<Group gap={2} w={'100%'} justify='space-between' align='center'>
|
||||||
label='Text Shadows'
|
<Checkbox.Card
|
||||||
checked={selectedTheme.textShadowsEnabled === 1}
|
w={'calc(50% - 1px)'}
|
||||||
c={'var(--mantine-color-background-0)'}
|
checked={selectedTheme.textShadowsEnabled === 1}
|
||||||
onChange={(e) => {
|
c={'var(--mantine-color-background-0)'}
|
||||||
setSelectedTheme({
|
onChange={(e) => {
|
||||||
...selectedTheme,
|
setSelectedTheme({
|
||||||
textShadowsEnabled: e.target.checked ? 1 : 0,
|
...selectedTheme,
|
||||||
});
|
textShadowsEnabled: e ? 1 : 0,
|
||||||
}}
|
});
|
||||||
styles={{
|
}}
|
||||||
root: { width: '50%' },
|
style={{
|
||||||
body: {
|
border: 'none',
|
||||||
width: '100%',
|
filter: `grayscale(${selectedTheme.textShadowsEnabled === 1 ? 0 : '75%'}) brightness(${selectedTheme.textShadowsEnabled === 1 ? '1' : '1.5'})`,
|
||||||
display: 'flex',
|
transition: 'all 1s ease',
|
||||||
justifyContent: 'space-between',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Checkbox
|
|
||||||
label='App Shadows'
|
|
||||||
checked={selectedTheme.appShadowsEnabled === 1}
|
|
||||||
c={'var(--mantine-color-background-0)'}
|
|
||||||
onChange={(e) => {
|
|
||||||
setSelectedTheme({
|
|
||||||
...selectedTheme,
|
|
||||||
appShadowsEnabled: e.target.checked ? 1 : 0,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
styles={{
|
|
||||||
root: { width: '50%' },
|
|
||||||
body: {
|
|
||||||
width: '100%',
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Group w={'100%'} justify='center'>
|
|
||||||
<FontPicker
|
|
||||||
style={{ width: '75%' }}
|
|
||||||
autoLoad
|
|
||||||
defaultValue={
|
|
||||||
selectedTheme.themeFont === null ? 'Jost' : selectedTheme.themeFont
|
|
||||||
}
|
|
||||||
value={(font: string) => setFont(font)}
|
|
||||||
/>
|
|
||||||
<ActionIcon
|
|
||||||
onClick={() => {
|
|
||||||
setFont(null);
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FiX />
|
<Tooltip
|
||||||
</ActionIcon>
|
label='Text Shadows'
|
||||||
|
className={toolTipClasses.default}
|
||||||
|
classNames={toolTipClasses}
|
||||||
|
>
|
||||||
|
<Group
|
||||||
|
w={'100%'}
|
||||||
|
justify='center'
|
||||||
|
style={{
|
||||||
|
backgroundColor: selectedTheme.backgroundColor,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
classNames={textClasses}
|
||||||
|
className={textClasses.sectionTitle}
|
||||||
|
style={{
|
||||||
|
color: selectedTheme.accentColor,
|
||||||
|
textShadow: `2px 2px ${selectedTheme.primaryColor}`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Shadows
|
||||||
|
</Text>
|
||||||
|
</Group>
|
||||||
|
</Tooltip>
|
||||||
|
</Checkbox.Card>
|
||||||
|
<Checkbox.Card
|
||||||
|
w={'calc(50% - 1px)'}
|
||||||
|
checked={selectedTheme.appShadowsEnabled === 1}
|
||||||
|
c={'var(--mantine-color-background-0)'}
|
||||||
|
onChange={(e) => {
|
||||||
|
setSelectedTheme({
|
||||||
|
...selectedTheme,
|
||||||
|
appShadowsEnabled: e ? 1 : 0,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
border: 'none',
|
||||||
|
filter: `grayscale(${selectedTheme.appShadowsEnabled === 1 ? 0 : '75%'}) brightness(${selectedTheme.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: selectedTheme.backgroundColor,
|
||||||
|
overflow: 'clip',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FaGoogle
|
||||||
|
style={{
|
||||||
|
marginTop: '12px',
|
||||||
|
marginBottom: '7px',
|
||||||
|
color: selectedTheme.primaryColor,
|
||||||
|
height: 32,
|
||||||
|
width: 32,
|
||||||
|
filter: `drop-shadow(2px 2px color-mix(in srgb, ${selectedTheme.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(null);
|
||||||
|
}}
|
||||||
|
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={
|
||||||
|
selectedTheme.themeFont === null
|
||||||
|
? 'Jost'
|
||||||
|
: selectedTheme.themeFont
|
||||||
|
}
|
||||||
|
value={(font: string) => {
|
||||||
|
if (customFontEnabled) {
|
||||||
|
setFont(font);
|
||||||
|
} else {
|
||||||
|
setFont(null);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<Tooltip
|
||||||
|
label='Reset to use default'
|
||||||
|
className={toolTipClasses.default}
|
||||||
|
classNames={toolTipClasses}
|
||||||
|
>
|
||||||
|
<ActionIcon
|
||||||
|
disabled={!customFontEnabled}
|
||||||
|
color={'red'}
|
||||||
|
size={32}
|
||||||
|
onClick={() => {
|
||||||
|
setFont(null);
|
||||||
|
setCustomFontEnabled(false);
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
borderRadius: '0px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FiX />
|
||||||
|
</ActionIcon>
|
||||||
|
</Tooltip>
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
{JSON.stringify(defaultTheme) !== JSON.stringify(selectedTheme) && (
|
{JSON.stringify(defaultTheme) !== JSON.stringify(selectedTheme) && (
|
||||||
<>
|
<Stack
|
||||||
<Text c={'var(--mantine-color-background-0)'} fz={'1.5rem'}>
|
gap={0}
|
||||||
Changes:
|
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>
|
</Text>
|
||||||
<ScrollArea.Autosize
|
<ScrollArea.Autosize
|
||||||
w={'100%'}
|
w={'100%'}
|
||||||
className={scrollAreaClasses.default}
|
className={scrollAreaClasses.default}
|
||||||
classNames={scrollAreaClasses}
|
classNames={scrollAreaClasses}
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: 'var(--mantine-color-background-0)',
|
|
||||||
borderRadius: 8,
|
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
}}
|
}}
|
||||||
|
styles={{
|
||||||
|
scrollbar: {
|
||||||
|
position: 'absolute',
|
||||||
|
right: -2,
|
||||||
|
},
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Stack w={'100%'} gap={0}>
|
<Stack w={'95%'} gap={2}>
|
||||||
{getObjectDiff(defaultTheme, designerTheme) !== null &&
|
{getObjectDiff(defaultTheme, designerTheme) !== null &&
|
||||||
Object.keys(getObjectDiff(defaultTheme, designerTheme)).map(
|
Object.keys(getObjectDiff(defaultTheme, designerTheme)).map(
|
||||||
(key: any) => {
|
(key: any) => {
|
||||||
@@ -576,22 +710,115 @@ export function ThemeEditor({
|
|||||||
gap={0}
|
gap={0}
|
||||||
key={key}
|
key={key}
|
||||||
>
|
>
|
||||||
<Text key={key}>
|
<Group w={'100%'} justify='space-between'>
|
||||||
{
|
<Text
|
||||||
BackgroundProperties[
|
key={key}
|
||||||
key as keyof typeof BackgroundProperties
|
pl={2}
|
||||||
]
|
style={{
|
||||||
}
|
color: 'var(--mantine-color-primary-0)',
|
||||||
</Text>
|
backgroundColor:
|
||||||
|
'var(--mantine-color-background-0)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{ThemeProperties[key as keyof typeof ThemeProperties]}
|
||||||
|
</Text>
|
||||||
|
<Tooltip
|
||||||
|
label={`Reset ${
|
||||||
|
ThemeProperties[key as keyof typeof ThemeProperties]
|
||||||
|
}`}
|
||||||
|
classNames={toolTipClasses}
|
||||||
|
className={toolTipClasses.default}
|
||||||
|
>
|
||||||
|
<ActionIcon
|
||||||
|
variant='subtle'
|
||||||
|
color='red'
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedTheme({
|
||||||
|
...designerTheme,
|
||||||
|
[key]: defaultTheme[key as keyof Theme],
|
||||||
|
});
|
||||||
|
if (key.includes('Font')) {
|
||||||
|
setFont(defaultTheme.themeFont);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FiX />
|
||||||
|
</ActionIcon>
|
||||||
|
</Tooltip>
|
||||||
|
</Group>
|
||||||
{key === 'name' && (
|
{key === 'name' && (
|
||||||
<Group w={'100%'} justify='center'>
|
<Group
|
||||||
|
w={'100%'}
|
||||||
|
justify='center'
|
||||||
|
bg='var(--mantine-color-accent-0)'
|
||||||
|
style={{ borderRadius: 8, overflow: 'clip' }}
|
||||||
|
h={48}
|
||||||
|
>
|
||||||
<Text>{defaultTheme[key as keyof Theme]}</Text>
|
<Text>{defaultTheme[key as keyof Theme]}</Text>
|
||||||
<Text>→</Text>
|
<Text>→</Text>
|
||||||
<Text>{designerTheme[key as keyof Theme]}</Text>
|
<Text>{designerTheme[key as keyof Theme]}</Text>
|
||||||
</Group>
|
</Group>
|
||||||
)}
|
)}
|
||||||
|
{key.includes('Shadow') && (
|
||||||
|
<Group
|
||||||
|
w={'100%'}
|
||||||
|
justify='center'
|
||||||
|
bg='var(--mantine-color-accent-0)'
|
||||||
|
style={{ borderRadius: 8, overflow: 'clip' }}
|
||||||
|
h={48}
|
||||||
|
>
|
||||||
|
{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') && (
|
||||||
|
<Group
|
||||||
|
w={'100%'}
|
||||||
|
justify='center'
|
||||||
|
bg='var(--mantine-color-accent-0)'
|
||||||
|
h={48}
|
||||||
|
style={{ borderRadius: 8, overflow: 'clip' }}
|
||||||
|
>
|
||||||
|
<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: selectedTheme.themeFont ?? undefined,
|
||||||
|
fontSize: 18,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{designerTheme[key as keyof Theme] ||
|
||||||
|
`Default (${currentUser.defaultFont})`}
|
||||||
|
</Text>
|
||||||
|
</Group>
|
||||||
|
)}
|
||||||
{key === 'backgroundImage' && (
|
{key === 'backgroundImage' && (
|
||||||
<Group w={'100%'} justify='center' gap={4}>
|
<Group
|
||||||
|
w={'100%'}
|
||||||
|
justify='center'
|
||||||
|
gap={4}
|
||||||
|
bg='var(--mantine-color-accent-0)'
|
||||||
|
style={{ borderRadius: 8, overflow: 'clip' }}
|
||||||
|
>
|
||||||
<Image
|
<Image
|
||||||
w={'40%'}
|
w={'40%'}
|
||||||
src={
|
src={
|
||||||
@@ -616,39 +843,133 @@ export function ThemeEditor({
|
|||||||
</Group>
|
</Group>
|
||||||
)}
|
)}
|
||||||
{key.includes('Color') && (
|
{key.includes('Color') && (
|
||||||
<Group w={'100%'} justify='center'>
|
<Group
|
||||||
<ColorSwatch
|
w={'100%'}
|
||||||
color={defaultTheme[key as keyof Theme] as string}
|
justify='space-between'
|
||||||
/>
|
bg='var(--mantine-color-accent-0)'
|
||||||
|
style={{ borderRadius: 8, overflow: 'clip' }}
|
||||||
|
>
|
||||||
|
<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>
|
<Text>→</Text>
|
||||||
<ColorSwatch
|
<Tooltip
|
||||||
color={designerTheme[key as keyof Theme] as string}
|
label='Copy color code'
|
||||||
/>
|
classNames={toolTipClasses}
|
||||||
</Group>
|
className={toolTipClasses.default}
|
||||||
)}
|
>
|
||||||
{key.includes('Shadow') && (
|
<ColorSwatch
|
||||||
<Group w={'100%'} justify='center'>
|
h={50}
|
||||||
{defaultTheme[key as keyof Theme] === 0 ? (
|
onClick={() => {
|
||||||
<Text>Off</Text>
|
navigator.clipboard.writeText(
|
||||||
) : (
|
defaultTheme[key as keyof Theme] as string,
|
||||||
<Text>On</Text>
|
);
|
||||||
)}
|
notifications.show({
|
||||||
<Text>→</Text>
|
title: (
|
||||||
{designerTheme[key as keyof Theme] === 0 ? (
|
<Text
|
||||||
<Text>Off</Text>
|
fw={600}
|
||||||
) : (
|
c={'var(--mantine-color-accent-0)'}
|
||||||
<Text>On</Text>
|
>
|
||||||
)}
|
Copied{' '}
|
||||||
</Group>
|
{
|
||||||
)}
|
ThemeProperties[
|
||||||
{key.includes('Font') && (
|
key as keyof typeof ThemeProperties
|
||||||
<Group w={'100%'} justify='center'>
|
]
|
||||||
<Text>
|
}
|
||||||
{defaultTheme[key as keyof Theme] ||
|
</Text>
|
||||||
'Default (Jost)'}
|
),
|
||||||
</Text>
|
message: (
|
||||||
<Text>→</Text>
|
<Text c={'var(--mantine-color-primary-0)'}>
|
||||||
<Text>{designerTheme[key as keyof Theme]}</Text>
|
{
|
||||||
|
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>
|
</Group>
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -657,9 +978,9 @@ export function ThemeEditor({
|
|||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
</ScrollArea.Autosize>
|
</ScrollArea.Autosize>
|
||||||
</>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
<Group mih={'36px'}>
|
<Group mih={'36px'} pb={'1.5rem'}>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
label={'Randomize Colors!'}
|
label={'Randomize Colors!'}
|
||||||
c={'var(--mantine-color-primary-0)'}
|
c={'var(--mantine-color-primary-0)'}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export type { PersonalData } from './personalData';
|
|||||||
export type { Provider } from './provider';
|
export type { Provider } from './provider';
|
||||||
export type { SearchHistoryItem, SearchShortcut } from './search';
|
export type { SearchHistoryItem, SearchShortcut } from './search';
|
||||||
export type { Theme, ThemePlaylist } from './theme';
|
export type { Theme, ThemePlaylist } from './theme';
|
||||||
export { BackgroundProperties } from './theme';
|
export { ThemeProperties } from './theme';
|
||||||
export type { User } from './user';
|
export type { User } from './user';
|
||||||
export type {
|
export type {
|
||||||
CurrentWeather,
|
CurrentWeather,
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ export interface ThemePlaylist {
|
|||||||
themeList: string;
|
themeList: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum BackgroundProperties {
|
export enum ThemeProperties {
|
||||||
|
name = 'Theme Name',
|
||||||
backgroundImage = 'Background Image',
|
backgroundImage = 'Background Image',
|
||||||
backgroundColor = 'Background Color',
|
backgroundColor = 'Background Color',
|
||||||
searchColor = 'Search Color',
|
searchColor = 'Search Color',
|
||||||
@@ -30,4 +31,5 @@ export enum BackgroundProperties {
|
|||||||
randomEnabled = 'Random',
|
randomEnabled = 'Random',
|
||||||
textShadowsEnabled = 'Text Shadows',
|
textShadowsEnabled = 'Text Shadows',
|
||||||
appShadowsEnabled = 'App Shadows',
|
appShadowsEnabled = 'App Shadows',
|
||||||
|
themeFont = 'Theme Font',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ export interface User {
|
|||||||
email: string;
|
email: string;
|
||||||
physicalAddress: string;
|
physicalAddress: string;
|
||||||
nickname: string;
|
nickname: string;
|
||||||
|
defaultFont: string;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user