diff --git a/package-lock.json b/package-lock.json index 913fe23..29b0121 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,7 +32,7 @@ "@vitest/coverage-v8": "^3.2.4", "@vitest/ui": "^3.2.4", "typescript": "^5.8.3", - "vite": "^7.0.5", + "vite": "^7.0.6", "vite-plugin-dts": "~4.5.4", "vite-tsconfig-paths": "^5.1.4", "vitest": "^3.2.4" @@ -3468,9 +3468,9 @@ "dev": true }, "node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { @@ -4506,15 +4506,15 @@ } }, "node_modules/vite": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.0.5.tgz", - "integrity": "sha512-1mncVwJxy2C9ThLwz0+2GKZyEXuC3MyWtAAlNftlZZXZDP3AJt5FmwcMit/IGGaNZ8ZOB2BNO/HFUB+CpN0NQw==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.0.6.tgz", + "integrity": "sha512-MHFiOENNBd+Bd9uvc8GEsIzdkn1JxMmEeYX35tI3fv0sJBUTfW5tQsoaOwuY4KhBI09A3dUJ/DXf2yxPVPUceg==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.6", - "picomatch": "^4.0.2", + "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.40.0", "tinyglobby": "^0.2.14" diff --git a/package.json b/package.json index 5eb9e92..64a791a 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@vitest/coverage-v8": "^3.2.4", "@vitest/ui": "^3.2.4", "typescript": "^5.8.3", - "vite": "^7.0.5", + "vite": "^7.0.6", "vite-plugin-dts": "~4.5.4", "vite-tsconfig-paths": "^5.1.4", "vitest": "^3.2.4" diff --git a/src/pages/settings/components/Theming/ThemePlaylists/ThemePlaylistModal.tsx b/src/pages/settings/components/Theming/ThemePlaylists/ThemePlaylistModal.tsx index 57d7796..01bb063 100644 --- a/src/pages/settings/components/Theming/ThemePlaylists/ThemePlaylistModal.tsx +++ b/src/pages/settings/components/Theming/ThemePlaylists/ThemePlaylistModal.tsx @@ -1,4 +1,4 @@ -import { Button, Group, Modal, SimpleGrid, Text, TextInput } from '@mantine/core'; +import { Button, Group, Modal, Text, TextInput } from '@mantine/core'; import { useCommonHooks } from 'hooks'; import { useEffect, useState } from 'react'; import { modalClasses, textInputClasses } from 'styles'; @@ -87,7 +87,7 @@ export function ThemePlaylistModal({ /> ) : ( <> - + {selectedPlaylist?.name !== 'Time of Day' && allThemes?.map((miniTheme: Theme) => { const newThemeList = themeList; @@ -102,7 +102,7 @@ export function ThemePlaylistModal({ /> ); })} - + + + + + {}} + allThemes={[]} + themePlaylists={[]} + /> + + + + + + + ) : ( + + - Change{' '} - {BackgroundProperties[colorId as keyof typeof BackgroundProperties]} - - {colorId === 'backgroundColor' && ( - { - setColorValue(e); - setDesignerTheme({ - ...designerTheme, - backgroundColor: e, - }); - }} - format={'hex'} - w={'90%'} - mb={'1.5rem'} - /> - )} - {colorId !== 'backgroundColor' && ( - { - setColorValue(e); - setDesignerTheme({ - ...designerTheme, - [colorId]: e, - }); - }} - format={'hexa'} - w={'90%'} - /> - )} - setColorValue(e.target.value)} - /> - - + + + )} - {backgroundPicker && ( - - - + ) : ( + <> + + + + + { + setColorId('primaryColor'); + setColorValue(selectedTheme.primaryColor); + handleSwatchClick(); + }} + color={selectedTheme.primaryColor} + bd={`1px solid ${selectedTheme.primaryColor}`} + pos={'absolute'} + top={'6.25rem'} + left={'1.5rem'} + /> + + + { + setColorId('accentColor'); + setColorValue(selectedTheme.accentColor); + handleSwatchClick(); + }} + color={selectedTheme.accentColor} + bd={`1px solid ${selectedTheme.primaryColor}`} + pos={'absolute'} + bottom={'6rem'} + left={'11rem'} + /> + + + { + setColorId('backgroundColor'); + setColorValue(selectedTheme.backgroundColor); + handleSwatchClick(); + }} + color={selectedTheme.backgroundColor} + bd={`1px solid ${selectedTheme.primaryColor}`} + pos={'absolute'} + bottom={'10rem'} + right={'3.5rem'} + /> + + + { + setColorId('borderColor'); + setColorValue(selectedTheme.borderColor); + handleSwatchClick(); + }} + color={selectedTheme.borderColor} + bd={`1px solid ${selectedTheme.primaryColor}`} + pos={'absolute'} + top={'4.5rem'} + right={'15%'} + /> + + + { + setColorId('searchColor'); + setColorValue(selectedTheme.searchColor); + handleSwatchClick(); + }} + color={selectedTheme.searchColor} + bd={`1px solid ${selectedTheme.primaryColor}`} + pos={'absolute'} + top={'3.25rem'} + left={'6.5rem'} + /> + + + { + closePicker(); + openBackgroundPicker(); + setDesignerTheme(selectedTheme); + }} + pos={'absolute'} + right={0} + > + + + + + + {pickerOpen && ( + + + Change{' '} + { + BackgroundProperties[ + colorId as keyof typeof BackgroundProperties + ] + } + + {colorId === 'backgroundColor' && ( + { + setColorValue(e); + setDesignerTheme({ + ...designerTheme, + backgroundColor: e, + }); }} + format={'hex'} + w={'90%'} + mb={'1.5rem'} + /> + )} + {colorId !== 'backgroundColor' && ( + { + setColorValue(e); + setDesignerTheme({ + ...designerTheme, + [colorId]: e, + }); + }} + format={'hexa'} + w={'90%'} + /> + )} + setColorValue(e.target.value)} + /> + + + + + + )} + {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; + }); + } }} /> - } - 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 && ( - - - { - setSelectedTheme({ - ...selectedTheme, - textShadowsEnabled: e.target.checked ? 1 : 0, - }); - }} - styles={{ - root: { width: '50%' }, - body: { - width: '100%', - display: 'flex', - justifyContent: 'space-between', - }, - }} - /> - { - setSelectedTheme({ - ...selectedTheme, - appShadowsEnabled: e.target.checked ? 1 : 0, - }); - }} - styles={{ - root: { width: '50%' }, - body: { - width: '100%', - display: 'flex', - justifyContent: 'space-between', - }, - }} - /> - - {JSON.stringify(defaultTheme) !== JSON.stringify(selectedTheme) && ( - <> - Changes: + - - {getObjectDiff(defaultTheme, designerTheme) !== null && - Object.keys(getObjectDiff(defaultTheme, designerTheme)).map( - (key: any) => { - return ( - - - { - BackgroundProperties[ - key as keyof typeof BackgroundProperties - ] - } - - {key === 'name' && ( - - {defaultTheme[key as keyof Theme]} - → - {designerTheme[key as keyof Theme]} - - )} - {key === 'backgroundImage' && ( - - - → - - - )} - {key.includes('Color') && ( - - - → - - - )} - {key.includes('Shadow') && ( - - {defaultTheme[key as keyof Theme] === 0 ? ( - Off - ) : ( - On - )} - → - {designerTheme[key as keyof Theme] === 0 ? ( - Off - ) : ( - On - )} - - )} - - ); - }, - )} + + {items} - + + + + + + )} + {!pickerOpen && !backgroundPicker && ( + + + { + setSelectedTheme({ + ...selectedTheme, + textShadowsEnabled: e.target.checked ? 1 : 0, + }); + }} + styles={{ + root: { width: '50%' }, + body: { + width: '100%', + display: 'flex', + justifyContent: 'space-between', + }, + }} + /> + { + setSelectedTheme({ + ...selectedTheme, + appShadowsEnabled: e.target.checked ? 1 : 0, + }); + }} + styles={{ + root: { width: '50%' }, + body: { + width: '100%', + display: 'flex', + justifyContent: 'space-between', + }, + }} + /> + + {JSON.stringify(defaultTheme) !== JSON.stringify(selectedTheme) && ( + <> + Changes: + + + {getObjectDiff(defaultTheme, designerTheme) !== null && + Object.keys( + getObjectDiff(defaultTheme, designerTheme), + ).map((key: any) => { + return ( + + + { + BackgroundProperties[ + key as keyof typeof BackgroundProperties + ] + } + + {key === 'name' && ( + + {defaultTheme[key as keyof Theme]} + → + {designerTheme[key as keyof Theme]} + + )} + {key === 'backgroundImage' && ( + + + → + + + )} + {key.includes('Color') && ( + + + → + + + )} + {key.includes('Shadow') && ( + + {defaultTheme[key as keyof Theme] === 0 ? ( + Off + ) : ( + On + )} + → + {designerTheme[key as keyof Theme] === 0 ? ( + Off + ) : ( + On + )} + + )} + + ); + })} + + + + )} + + )} - - )} - - - - - - + + + + + + + )} diff --git a/src/pages/settings/components/Theming/Themes/Themes.tsx b/src/pages/settings/components/Theming/Themes/Themes.tsx index cbde821..4ae62cd 100644 --- a/src/pages/settings/components/Theming/Themes/Themes.tsx +++ b/src/pages/settings/components/Theming/Themes/Themes.tsx @@ -44,7 +44,7 @@ export function Themes() { primaryColor: '#222222', accentColor: '#5c5c5c', borderColor: '#5c5c5c', - randomEnabled: 0, + randomEnabled: 1, textShadowsEnabled: 0, appShadowsEnabled: 0, }); @@ -52,6 +52,7 @@ export function Themes() { const [searchValue, setSearchValue] = useState(''); const [debouncedSearch] = useDebouncedValue(searchValue, 500); const [isLoading, setIsLoading] = useState(false); + const [isNew, setIsNew] = useState(false); const navigate = useNavigate(); const { currentTheme, @@ -70,6 +71,7 @@ export function Themes() { const handleClose = () => { closeThemeModal(); closePicker(); + setIsNew(false); setSelectedTheme({ id: undefined, name: 'default', @@ -79,12 +81,17 @@ export function Themes() { primaryColor: '#222222', accentColor: '#5c5c5c', borderColor: '#5c5c5c', - randomEnabled: 0, + randomEnabled: 1, textShadowsEnabled: 0, appShadowsEnabled: 0, }); }; + const handleNewTheme = () => { + setIsNew(true); + openThemeModal(); + }; + const handleSaveTheme = () => { mutateAsync({ method: selectedTheme?.id === undefined ? 'POST' : 'PATCH', @@ -147,6 +154,9 @@ export function Themes() { pickerOpen={pickerOpen} closePicker={closePicker} handleSaveTheme={handleSaveTheme} + isNew={isNew} + setIsNew={setIsNew} + allThemes={allThemes} />