diff --git a/components/uncap/TranscendencePopover/index.tsx b/components/uncap/TranscendencePopover/index.tsx index 8d11b484..7e5eb1fe 100644 --- a/components/uncap/TranscendencePopover/index.tsx +++ b/components/uncap/TranscendencePopover/index.tsx @@ -17,6 +17,7 @@ interface Props HTMLDivElement > { type: 'character' | 'summon' + starRef: React.RefObject open: boolean stage: number onOpenChange?: (open: boolean) => void @@ -24,8 +25,9 @@ interface Props } const TranscendencePopover = ({ - children, open: popoverOpen, + starRef, + children, type, stage, tabIndex, @@ -45,8 +47,8 @@ const TranscendencePopover = ({ }) useEffect(() => { - if (open) popoverRef.current?.focus() - }, []) + setOpen(popoverOpen) + }, [popoverOpen]) useEffect(() => { if (stage) setCurrentStage(stage) @@ -57,10 +59,6 @@ const TranscendencePopover = ({ else if (type === 'summon') setBaseLevel(200) }, [type]) - useEffect(() => { - setOpen(popoverOpen) - }, [popoverOpen]) - function handleFragmentClicked(newStage: number) { setCurrentStage(newStage) if (sendValue) sendValue(newStage) @@ -70,13 +68,33 @@ const TranscendencePopover = ({ setCurrentStage(newStage) } + function closePopover() { + setOpen(false) + if (onOpenChange) onOpenChange(false) + } + + function handlePointerDownOutside( + event: CustomEvent<{ originalEvent: PointerEvent }> + ) { + const target = event.detail.originalEvent.target as Element + if ( + target && + starRef.current && + target.closest('.TranscendenceStar') !== starRef.current + ) { + closePopover() + } + } + return ( - + {children} { - const [visibleStage, setVisibleStage] = useState(0) - const [currentStage, setCurrentStage] = useState(0) - const [immutable, setImmutable] = useState(false) - - // Classes - const starClasses = classnames({ - [styles.star]: true, - [styles.immutable]: immutable, - [styles.empty]: stage === 0, - [styles.stage1]: stage === 1, - [styles.stage2]: stage === 2, - [styles.stage3]: stage === 3, - [styles.stage4]: stage === 4, - [styles.stage5]: stage === 5, - }) - - const baseImageClasses = classnames( +const TranscendenceStar = React.forwardRef( + function TranscendenceStar( { - [styles.figure]: true, - }, - className?.split(' ').map((c) => styles[c]) - ) + className, + interactive, + stage, + editable, + tabIndex, + onStarClick, + onFragmentClick, + onFragmentHover, + }: Props, + forwardedRef + ) { + const [visibleStage, setVisibleStage] = useState(0) + const [currentStage, setCurrentStage] = useState(0) + const [immutable, setImmutable] = useState(false) - useEffect(() => { - setVisibleStage(stage) - setCurrentStage(stage) - }, [stage]) + // Classes + const starClasses = classnames({ + TranscendenceStar: true, + [styles.star]: true, + [styles.immutable]: immutable, + [styles.empty]: stage === 0, + [styles.stage1]: stage === 1, + [styles.stage2]: stage === 2, + [styles.stage3]: stage === 3, + [styles.stage4]: stage === 4, + [styles.stage5]: stage === 5, + }) - function handleClick() { - if (onStarClick) { - onStarClick() + const baseImageClasses = classnames( + { + [styles.figure]: true, + }, + className?.split(' ').map((c) => styles[c]) + ) + + useEffect(() => { + setVisibleStage(stage) + setCurrentStage(stage) + }, [stage]) + + function handleClick() { + if (onStarClick) onStarClick() } - } - function handleFragmentClick(index: number) { - let newStage = index - if (index === currentStage) newStage = 0 + function handleFragmentClick(index: number) { + let newStage = index + if (index === currentStage) newStage = 0 - setVisibleStage(newStage) - setCurrentStage(newStage) - if (onFragmentClick) onFragmentClick(newStage) - } + setVisibleStage(newStage) + setCurrentStage(newStage) + if (onFragmentClick) onFragmentClick(newStage) + } - function handleFragmentHover(index: number) { - setVisibleStage(index) - if (onFragmentHover) onFragmentHover(index) - } + function handleFragmentHover(index: number) { + setVisibleStage(index) + if (onFragmentHover) onFragmentHover(index) + } - function handleMouseLeave() { - setVisibleStage(currentStage) - if (onFragmentHover) onFragmentHover(currentStage) - } + function handleMouseLeave() { + setVisibleStage(currentStage) + if (onFragmentHover) onFragmentHover(currentStage) + } - return ( -
{}} - onMouseLeave={interactive ? handleMouseLeave : () => {}} - tabIndex={tabIndex} - > -
- {[...Array(NUM_FRAGMENTS)].map((e, i) => { - const loopStage = i + 1 - return interactive ? ( - - ) : ( - '' - ) - })} + return ( +
{}} + onMouseLeave={interactive ? handleMouseLeave : () => {}} + ref={forwardedRef} + tabIndex={tabIndex} + > +
+ {[...Array(NUM_FRAGMENTS)].map((e, i) => { + const loopStage = i + 1 + return interactive ? ( + + ) : ( + '' + ) + })} +
+
- -
- ) -} + ) + } +) TranscendenceStar.defaultProps = { stage: 0, diff --git a/components/uncap/UncapIndicator/index.tsx b/components/uncap/UncapIndicator/index.tsx index 57221f7b..5aa144c2 100644 --- a/components/uncap/UncapIndicator/index.tsx +++ b/components/uncap/UncapIndicator/index.tsx @@ -26,6 +26,8 @@ const UncapIndicator = (props: Props) => { const [popoverOpen, setPopoverOpen] = useState(false) + const transcendenceStarRef = React.createRef() + const classes = classNames( { [styles.wrapper]: true, @@ -82,7 +84,11 @@ const UncapIndicator = (props: Props) => { function sendTranscendenceStage(stage: number) { if (props.updateTranscendence) props.updateTranscendence(stage) - togglePopover(false) + setPopoverOpen(false) + } + + function handleStarClicked() { + if (props.editable) togglePopover(!popoverOpen) } const transcendence = (i: number) => { @@ -90,25 +96,27 @@ const UncapIndicator = (props: Props) => { return props.type === 'character' || props.type === 'summon' ? ( togglePopover(true)} + ref={transcendenceStarRef} + onStarClick={handleStarClicked} /> ) : (