Updates to search component
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { useTextTicker } from '@gfazioli/mantine-text-animate';
|
||||
import {
|
||||
ActionIcon,
|
||||
type ComboboxItem,
|
||||
@@ -12,7 +13,7 @@ import { useCommonHooks, useQueryAPI } from 'hooks';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { FaDice } from 'react-icons/fa';
|
||||
import { FiShuffle } from 'react-icons/fi';
|
||||
import { actionIconClasses, selectClasses, stackClasses } from 'styles';
|
||||
import { actionIconClasses, selectClasses, stackClasses, textClasses } from 'styles';
|
||||
import type { Theme, ThemePlaylist } from 'types';
|
||||
|
||||
function ThemingCard() {
|
||||
@@ -38,43 +39,46 @@ function ThemingCard() {
|
||||
currentThemePlaylist,
|
||||
setCurrentThemePlaylist,
|
||||
} = useCommonHooks();
|
||||
|
||||
const [current, setCurrent] = useState<string>(theme.name);
|
||||
|
||||
const { text, isAnimating, start, stop } = useTextTicker({
|
||||
initialText: 'target',
|
||||
value: theme.name,
|
||||
delay: 0,
|
||||
speed: 1,
|
||||
easing: 'ease-in-out',
|
||||
animate: current !== theme.name,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (theme.name !== current) {
|
||||
start();
|
||||
} else {
|
||||
setCurrent(theme.name);
|
||||
stop();
|
||||
}
|
||||
}, [theme]);
|
||||
|
||||
return (
|
||||
<Stack
|
||||
gap={0}
|
||||
justify='space-between'
|
||||
className={stackClasses.menuStack}
|
||||
classNames={stackClasses}
|
||||
pos={'relative'}
|
||||
style={{ aspectRatio: isMobile ? undefined : '1/1' }}
|
||||
>
|
||||
<Menu.Label pb={'.25rem'}>Themes</Menu.Label>
|
||||
<Group mt={'-1.5rem'} mb={'-.25rem'} w={'95%'} justify='space-between'>
|
||||
<Tooltip
|
||||
label='Shuffle Themes'
|
||||
c={'var(--mantine-color-primary-0)'}
|
||||
bg={'var(--mantine-color-background-0)'}
|
||||
withArrow
|
||||
>
|
||||
<ActionIcon
|
||||
className={actionIconClasses.menuActions}
|
||||
classNames={actionIconClasses}
|
||||
disabled={currentThemePlaylist === 'Time of Day'}
|
||||
style={{
|
||||
backgroundColor:
|
||||
currentTheme === 'random'
|
||||
? `${theme?.searchColor === theme?.primaryColor ? theme.searchColor?.substring(0, 7) : theme.primaryColor?.substring(0, 7)}88`
|
||||
: 'transparent',
|
||||
color:
|
||||
currentTheme === 'random'
|
||||
? 'var(--mantine-color-accent-0)'
|
||||
: 'var(--mantine-color-primary-0)',
|
||||
}}
|
||||
onClick={() => {
|
||||
setCurrentTheme(currentTheme === 'random' ? theme.name : 'random');
|
||||
setCurrentThemePlaylist('All');
|
||||
}}
|
||||
>
|
||||
<FiShuffle />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
<Menu.Label pb={'2rem'}>Themes</Menu.Label>
|
||||
<Group mt={'-1.5rem'} mb={'-.25rem'} w={'95%'} h={'100%'} gap={0}>
|
||||
<Stack gap={0}>
|
||||
<Text className={textClasses.currentTheme} classNames={textClasses}>
|
||||
Current theme:
|
||||
</Text>
|
||||
<Text className={textClasses.themeName} classNames={textClasses}>
|
||||
{text}
|
||||
</Text>
|
||||
</Stack>
|
||||
<Tooltip
|
||||
label='Random Theme'
|
||||
c={'var(--mantine-color-primary-0)'}
|
||||
@@ -84,11 +88,29 @@ function ThemingCard() {
|
||||
<ActionIcon
|
||||
className={actionIconClasses.menuActions}
|
||||
classNames={actionIconClasses}
|
||||
h={40}
|
||||
style={{
|
||||
backgroundColor: 'transparent',
|
||||
color: 'var(--mantine-color-primary-0)',
|
||||
borderTopRightRadius: 0,
|
||||
borderTopLeftRadius: 0,
|
||||
borderBottomLeftRadius: '10px',
|
||||
borderBottomRightRadius: '10px',
|
||||
position: 'absolute',
|
||||
right: 0,
|
||||
}}
|
||||
disabled={currentThemePlaylist === 'Time of Day'}
|
||||
styles={{
|
||||
icon: {
|
||||
width: 'fit-content',
|
||||
height: 'fit-content',
|
||||
position: 'absolute',
|
||||
padding: 8,
|
||||
right: 2,
|
||||
bottom: 2,
|
||||
borderRadius: '50%',
|
||||
},
|
||||
}}
|
||||
disabled={currentThemePlaylist === 'Time of Day' || isAnimating}
|
||||
onClick={() => {
|
||||
const themeList = JSON.parse(
|
||||
themePlaylistData?.find(
|
||||
@@ -119,81 +141,139 @@ function ThemingCard() {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<FaDice />
|
||||
<FaDice size={20} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
<Text fw={'bold'} fz={'1.125rem'}>
|
||||
Currently:{' '}
|
||||
</Text>
|
||||
{theme.name}
|
||||
<Text fw={'bold'} fz={'1.125rem'}>
|
||||
Playlist:{' '}
|
||||
</Text>
|
||||
<Select
|
||||
labelProps={{ display: 'none' }}
|
||||
placeholder='Pick a playlist...'
|
||||
value={currentThemePlaylist}
|
||||
data={[
|
||||
{ value: 'All', label: 'All' },
|
||||
{
|
||||
value: 'Backgrounds',
|
||||
label: 'Backgrounds',
|
||||
disabled:
|
||||
allThemes.filter(
|
||||
(a: any) => !a.backgroundImage.toLowerCase().includes('none'),
|
||||
).length === 0,
|
||||
},
|
||||
{
|
||||
value: 'No Backgrounds',
|
||||
label: 'No Backgrounds',
|
||||
disabled:
|
||||
allThemes.filter((a: any) =>
|
||||
a.backgroundImage.toLowerCase().includes('none'),
|
||||
).length === 0,
|
||||
},
|
||||
...(themePlaylistData
|
||||
?.map((playlist: ThemePlaylist) => {
|
||||
return {
|
||||
value: playlist.name,
|
||||
label: playlist.name,
|
||||
disabled: JSON.parse(playlist.themeList).length === 0,
|
||||
};
|
||||
})
|
||||
.toSorted((a: ComboboxItem, b: ComboboxItem) =>
|
||||
a.label.localeCompare(b.label),
|
||||
) ?? []),
|
||||
]}
|
||||
w='92%'
|
||||
classNames={{
|
||||
root: selectClasses.menuSelectRoot,
|
||||
input: selectClasses.menuSelectInput,
|
||||
label: selectClasses.menuSelectLabel,
|
||||
options: selectClasses.menuSelectOptions,
|
||||
option: selectClasses.menuSelectOption,
|
||||
}}
|
||||
comboboxProps={{
|
||||
withinPortal: false,
|
||||
position: 'top',
|
||||
}}
|
||||
onChange={(_value, option: ComboboxItem) => {
|
||||
setCurrentThemePlaylist(option.value);
|
||||
if (option.value !== 'Time of Day') {
|
||||
setThemeName('random');
|
||||
} else {
|
||||
const themeList = JSON.parse(
|
||||
themePlaylistData.find((t: ThemePlaylist) => t.name === 'Time of Day')
|
||||
.themeList,
|
||||
);
|
||||
setThemeName(
|
||||
allThemeData.find(
|
||||
(t: Theme) =>
|
||||
t.id === Number(themeList[Math.floor(new Date().getHours() / 6)]),
|
||||
).name,
|
||||
);
|
||||
<Group justify='space-between' pos={'relative'} gap={0}>
|
||||
<Select
|
||||
label='Current Playlist:'
|
||||
placeholder='Pick a playlist...'
|
||||
mb={'.25rem'}
|
||||
ml={'.25rem'}
|
||||
value={currentThemePlaylist}
|
||||
data={[
|
||||
{ value: 'All', label: 'All' },
|
||||
{
|
||||
value: 'Backgrounds',
|
||||
label: 'Backgrounds',
|
||||
disabled:
|
||||
allThemes.filter(
|
||||
(a: any) => !a.backgroundImage.toLowerCase().includes('none'),
|
||||
).length === 0,
|
||||
},
|
||||
{
|
||||
value: 'No Backgrounds',
|
||||
label: 'No Backgrounds',
|
||||
disabled:
|
||||
allThemes.filter((a: any) =>
|
||||
a.backgroundImage.toLowerCase().includes('none'),
|
||||
).length === 0,
|
||||
},
|
||||
...(themePlaylistData
|
||||
?.map((playlist: ThemePlaylist) => {
|
||||
return {
|
||||
value: playlist.name,
|
||||
label: playlist.name,
|
||||
disabled: JSON.parse(playlist.themeList).length === 0,
|
||||
};
|
||||
})
|
||||
.toSorted((a: ComboboxItem, b: ComboboxItem) =>
|
||||
a.label.localeCompare(b.label),
|
||||
) ?? []),
|
||||
]}
|
||||
classNames={{
|
||||
wrapper: selectClasses.menuSelectWrapper,
|
||||
root: selectClasses.menuSelectRoot,
|
||||
input: selectClasses.menuSelectInput,
|
||||
label: selectClasses.menuSelectLabel,
|
||||
options: selectClasses.menuSelectOptions,
|
||||
option: selectClasses.menuSelectOption,
|
||||
}}
|
||||
labelProps={{ top: 8, left: 12 }}
|
||||
comboboxProps={{
|
||||
withinPortal: false,
|
||||
position: 'top',
|
||||
width: '100%',
|
||||
}}
|
||||
w={'70%'}
|
||||
style={{
|
||||
zIndex: 2,
|
||||
}}
|
||||
styles={
|
||||
theme.textShadowsEnabled
|
||||
? {
|
||||
label: { boxShadow: '2px 2px var(--mantine-color-border-0)' },
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
}}
|
||||
/>
|
||||
onChange={(_value, option: ComboboxItem) => {
|
||||
setCurrentThemePlaylist(option.value);
|
||||
if (option.value !== 'Time of Day') {
|
||||
setThemeName('random');
|
||||
} else {
|
||||
const themeList = JSON.parse(
|
||||
themePlaylistData.find((t: ThemePlaylist) => t.name === 'Time of Day')
|
||||
.themeList,
|
||||
);
|
||||
setThemeName(
|
||||
allThemeData.find(
|
||||
(t: Theme) =>
|
||||
t.id === Number(themeList[Math.floor(new Date().getHours() / 6)]),
|
||||
).name,
|
||||
);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Tooltip
|
||||
label='Shuffle Playlist'
|
||||
c={'var(--mantine-color-primary-0)'}
|
||||
bg={'var(--mantine-color-background-0)'}
|
||||
withArrow
|
||||
>
|
||||
<ActionIcon
|
||||
className={actionIconClasses.menuActions}
|
||||
classNames={actionIconClasses}
|
||||
disabled={currentThemePlaylist === 'Time of Day' || isAnimating}
|
||||
h={40}
|
||||
style={{
|
||||
backgroundColor: 'transparent',
|
||||
color:
|
||||
currentTheme === 'random'
|
||||
? 'var(--mantine-color-accent-0)'
|
||||
: 'var(--mantine-color-primary-0)',
|
||||
borderTopRightRadius: 0,
|
||||
borderTopLeftRadius: 0,
|
||||
borderBottomLeftRadius: '10px',
|
||||
borderBottomRightRadius: '10px',
|
||||
position: 'absolute',
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
styles={{
|
||||
icon: {
|
||||
backgroundColor:
|
||||
currentTheme === 'random'
|
||||
? `${theme?.searchColor === theme?.primaryColor ? theme.searchColor?.substring(0, 7) : theme.primaryColor?.substring(0, 7)}88`
|
||||
: 'transparent',
|
||||
width: 'fit-content',
|
||||
height: 'fit-content',
|
||||
position: 'absolute',
|
||||
padding: 8,
|
||||
right: 2,
|
||||
bottom: 2,
|
||||
borderRadius: '50%',
|
||||
},
|
||||
}}
|
||||
onClick={() => {
|
||||
setCurrentTheme(currentTheme === 'random' ? theme.name : 'random');
|
||||
setCurrentThemePlaylist('All');
|
||||
}}
|
||||
>
|
||||
<FiShuffle size={20} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user