mirror of
https://github.com/remvze/moodist.git
synced 2025-09-29 15:30:49 -04:00
Merge branch 'develop'
This commit is contained in:
commit
a46a4cdc96
@ -1,4 +1,4 @@
|
|||||||
import { useCallback, useEffect } from 'react';
|
import { useCallback, useEffect, forwardRef } from 'react';
|
||||||
import { ImSpinner9 } from 'react-icons/im/index';
|
import { ImSpinner9 } from 'react-icons/im/index';
|
||||||
|
|
||||||
import { Range } from './range';
|
import { Range } from './range';
|
||||||
@ -10,27 +10,21 @@ import { cn } from '@/helpers/styles';
|
|||||||
|
|
||||||
import styles from './sound.module.css';
|
import styles from './sound.module.css';
|
||||||
|
|
||||||
import type { Sound } from '@/data/types';
|
import type { Sound as SoundType } from '@/data/types';
|
||||||
|
|
||||||
import { useKeyboardButton } from '@/hooks/use-keyboard-button';
|
import { useKeyboardButton } from '@/hooks/use-keyboard-button';
|
||||||
|
|
||||||
interface SoundProps extends Sound {
|
interface SoundProps extends SoundType {
|
||||||
functional: boolean;
|
functional: boolean;
|
||||||
hidden: boolean;
|
hidden: boolean;
|
||||||
selectHidden: (key: string) => void;
|
selectHidden: (key: string) => void;
|
||||||
unselectHidden: (key: string) => void;
|
unselectHidden: (key: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Sound({
|
export const Sound = forwardRef<HTMLDivElement, SoundProps>(function Sound(
|
||||||
functional,
|
{ functional, hidden, icon, id, label, selectHidden, src, unselectHidden },
|
||||||
hidden,
|
ref,
|
||||||
icon,
|
) {
|
||||||
id,
|
|
||||||
label,
|
|
||||||
selectHidden,
|
|
||||||
src,
|
|
||||||
unselectHidden,
|
|
||||||
}: SoundProps) {
|
|
||||||
const isPlaying = useSoundStore(state => state.isPlaying);
|
const isPlaying = useSoundStore(state => state.isPlaying);
|
||||||
const play = useSoundStore(state => state.play);
|
const play = useSoundStore(state => state.play);
|
||||||
const select = useSoundStore(state => state.select);
|
const select = useSoundStore(state => state.select);
|
||||||
@ -82,6 +76,7 @@ export function Sound({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
aria-label={`${label} sound`}
|
aria-label={`${label} sound`}
|
||||||
|
ref={ref}
|
||||||
role="button"
|
role="button"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
className={cn(
|
className={cn(
|
||||||
@ -108,4 +103,4 @@ export function Sound({
|
|||||||
<Range id={id} label={label} />
|
<Range id={id} label={label} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useState, useMemo, useCallback } from 'react';
|
import { useState, useMemo, useCallback, useRef, useEffect } from 'react';
|
||||||
import { AnimatePresence, motion } from 'framer-motion';
|
import { AnimatePresence, motion } from 'framer-motion';
|
||||||
|
|
||||||
import { Sound } from '@/components/sound';
|
import { Sound } from '@/components/sound';
|
||||||
@ -19,6 +19,17 @@ interface SoundsProps {
|
|||||||
export function Sounds({ functional, id, sounds }: SoundsProps) {
|
export function Sounds({ functional, id, sounds }: SoundsProps) {
|
||||||
const [showAll, setShowAll] = useLocalStorage(`${id}-show-more`, false);
|
const [showAll, setShowAll] = useLocalStorage(`${id}-show-more`, false);
|
||||||
|
|
||||||
|
const firstNewSound = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const showMoreButton = useRef<HTMLButtonElement>(null);
|
||||||
|
const [exitComplete, setExitComplete] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (showAll) {
|
||||||
|
firstNewSound.current?.focus();
|
||||||
|
}
|
||||||
|
}, [showAll]);
|
||||||
|
|
||||||
const [hiddenSelections, setHiddenSelections] = useState<{
|
const [hiddenSelections, setHiddenSelections] = useState<{
|
||||||
[key: string]: boolean;
|
[key: string]: boolean;
|
||||||
}>({});
|
}>({});
|
||||||
@ -54,6 +65,7 @@ export function Sounds({ functional, id, sounds }: SoundsProps) {
|
|||||||
{...sound}
|
{...sound}
|
||||||
functional={functional}
|
functional={functional}
|
||||||
hidden={!showAll && index > 5}
|
hidden={!showAll && index > 5}
|
||||||
|
ref={index === 6 ? firstNewSound : undefined}
|
||||||
selectHidden={selectHidden}
|
selectHidden={selectHidden}
|
||||||
unselectHidden={unselectHidden}
|
unselectHidden={unselectHidden}
|
||||||
/>
|
/>
|
||||||
@ -66,12 +78,17 @@ export function Sounds({ functional, id, sounds }: SoundsProps) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{sounds.length > 6 && (
|
{sounds.length > 6 && (
|
||||||
<AnimatePresence initial={false} mode="wait">
|
<AnimatePresence
|
||||||
|
initial={false}
|
||||||
|
mode="wait"
|
||||||
|
onExitComplete={() => setExitComplete(true)}
|
||||||
|
>
|
||||||
<motion.button
|
<motion.button
|
||||||
animate="show"
|
animate="show"
|
||||||
exit="hidden"
|
exit="hidden"
|
||||||
initial="hidden"
|
initial="hidden"
|
||||||
key={showAll ? `${id}-show-less` : `${id}-show-more`}
|
key={showAll ? `${id}-show-less` : `${id}-show-more`}
|
||||||
|
ref={showMoreButton}
|
||||||
transition={{ duration: 0.2 }}
|
transition={{ duration: 0.2 }}
|
||||||
variants={variants}
|
variants={variants}
|
||||||
className={cn(
|
className={cn(
|
||||||
@ -79,6 +96,12 @@ export function Sounds({ functional, id, sounds }: SoundsProps) {
|
|||||||
hasHiddenSelection && !showAll && styles.active,
|
hasHiddenSelection && !showAll && styles.active,
|
||||||
)}
|
)}
|
||||||
onClick={() => setShowAll(prev => !prev)}
|
onClick={() => setShowAll(prev => !prev)}
|
||||||
|
onAnimationComplete={() => {
|
||||||
|
if (!showAll && exitComplete) {
|
||||||
|
setExitComplete(false);
|
||||||
|
showMoreButton.current?.focus();
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{showAll ? 'Show Less' : 'Show More'}
|
{showAll ? 'Show Less' : 'Show More'}
|
||||||
</motion.button>
|
</motion.button>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user