Add scroll, languages, settings
This commit is contained in:
@@ -1,98 +1,78 @@
|
||||
@import "../../app/style";
|
||||
|
||||
$panelWidth: $previewWidth + 40px;
|
||||
$panelHeight: $previewHeight + 40px;
|
||||
|
||||
$panelBorderSize: 8px;
|
||||
|
||||
.panel {
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
border: none;
|
||||
position: absolute;
|
||||
height: 220px;
|
||||
width: 360px;
|
||||
height: $panelHeight;
|
||||
width: $panelWidth;
|
||||
background-image: $panelBackground;
|
||||
background-repeat: repeat;
|
||||
|
||||
&-content {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
button {
|
||||
z-index: 3;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border: 2px solid var(--foreground);
|
||||
background-color: unset;
|
||||
transition: width 0.2s;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--foreground);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
&--bottom {
|
||||
bottom: -220px;
|
||||
bottom: -$panelHeight + $panelBorderSize;
|
||||
width: 100%;
|
||||
transition: bottom 0.5s;
|
||||
transition: bottom $transitionDuration $transitionType;
|
||||
border-top: $panelBorderSize double $fontColor;
|
||||
border-image: $borderTop 16 32 16 32;
|
||||
border-image-outset: $panelBorderSize - 2px 0 0 0;
|
||||
border-image-width: $panelBorderSize*2 0 0 100%;
|
||||
border-image-repeat: round round;
|
||||
|
||||
.panel-border {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
top: -10px;
|
||||
min-width: 100%;
|
||||
background-image: $borderRight;
|
||||
background-repeat: repeat;
|
||||
height: 16px;
|
||||
.panel-content {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
button {
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
top: -10px;
|
||||
width: 50px;
|
||||
top: -$buttonHeight - 5px;
|
||||
}
|
||||
|
||||
&--shown {
|
||||
bottom: 0;
|
||||
|
||||
button {
|
||||
height: 25px;
|
||||
top: -25px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&--left {
|
||||
left: -360px;
|
||||
flex-direction: column;
|
||||
left: -$panelWidth + $panelBorderSize;
|
||||
height: 100%;
|
||||
transition: left 0.5s;
|
||||
border-right: $panelBorderSize double $fontColor;
|
||||
border-image: $borderRight 32 16 0 0;
|
||||
border-image-outset: 0 $panelBorderSize - 2px 0 0;
|
||||
border-image-width: 100% $panelBorderSize*2 0 0;
|
||||
transition: left $transitionDuration $transitionType;
|
||||
|
||||
.panel-border {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
right: -8px;
|
||||
min-height: 100%;
|
||||
background-image: $borderTop;
|
||||
background-repeat: repeat;
|
||||
width: 16px;
|
||||
.panel-content {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
button {
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
right: -10px;
|
||||
height: 50px;
|
||||
transform: translateY(-50%) rotate(90deg);
|
||||
right: -80px;
|
||||
}
|
||||
|
||||
&--shown {
|
||||
left: 0;
|
||||
|
||||
button {
|
||||
width: 25px;
|
||||
right: -25px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,124 @@
|
||||
import * as React from 'react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { FocusEvent, MouseEvent, useEffect, useMemo, useRef, useState, WheelEvent } from 'react'
|
||||
import UIfx from 'uifx'
|
||||
|
||||
import { PREVIEW_HEIGHT, PREVIEW_WIDTH, UI_SOUND_VOLUME } from '../../utils'
|
||||
import { useSettings } from '../../hooks'
|
||||
|
||||
import './panel-component.scss'
|
||||
|
||||
interface Props {
|
||||
orientation: 'bottom' | 'left'
|
||||
isShown: boolean
|
||||
itemsCount: number
|
||||
setShown: () => void
|
||||
openSound: UIfx
|
||||
closeSound: UIfx
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export const PanelComponent = ({orientation, isShown, setShown, children}: Props) => {
|
||||
const [isRendered, setRendered] = useState(false)
|
||||
export const PanelComponent = ({
|
||||
isShown,
|
||||
setShown,
|
||||
children,
|
||||
openSound,
|
||||
closeSound,
|
||||
itemsCount,
|
||||
orientation
|
||||
}: Props) => {
|
||||
const {settings: {language, uiSound}} = useSettings()
|
||||
const [isDrag, setDrag] = useState(false)
|
||||
const [trackMouse, setTrackMouse] = useState(0)
|
||||
const [lastPosition, setLastPosition] = useState(0)
|
||||
|
||||
const panel = useRef<HTMLInputElement>(null)
|
||||
let position = 0
|
||||
const isBottom = useMemo(() => orientation === 'bottom', [orientation])
|
||||
|
||||
useEffect(() => {
|
||||
setRendered(isShown)
|
||||
if (!isShown && panel.current) {
|
||||
panel.current.style.transform = 'unset'
|
||||
setLastPosition(0)
|
||||
}
|
||||
}, [isShown])
|
||||
|
||||
const handleClick = useCallback((event) => {
|
||||
const handleClick = (event: MouseEvent) => {
|
||||
event.preventDefault()
|
||||
setShown()
|
||||
}, [setShown])
|
||||
if (!uiSound) {
|
||||
return
|
||||
}
|
||||
if (isShown) {
|
||||
openSound.play(UI_SOUND_VOLUME)
|
||||
} else {
|
||||
closeSound.play(UI_SOUND_VOLUME)
|
||||
}
|
||||
}
|
||||
|
||||
const handleDragScroll = (e: MouseEvent) => {
|
||||
if (!isDrag) {
|
||||
return
|
||||
}
|
||||
|
||||
const {clientX, clientY} = e
|
||||
const value = isBottom ? clientX : clientY
|
||||
position = trackMouse - value + lastPosition
|
||||
changePosition()
|
||||
}
|
||||
|
||||
const changePosition = () => {
|
||||
if (!panel.current) {
|
||||
return
|
||||
}
|
||||
const {innerHeight, innerWidth} = window
|
||||
const overflowWindow = isBottom ? innerWidth : innerHeight
|
||||
const overflowContainer = itemsCount * ((isBottom ? PREVIEW_WIDTH : PREVIEW_HEIGHT) + 10)
|
||||
const overflow = overflowContainer > overflowWindow ? overflowContainer : overflowWindow
|
||||
if (Math.abs(position) > overflow) {
|
||||
position = -position
|
||||
}
|
||||
panel.current.style.transform = `translate${isBottom ? 'X' : 'Y'}(${-position}px)`
|
||||
}
|
||||
|
||||
const handlePress = (e: MouseEvent) => {
|
||||
e.preventDefault()
|
||||
setTrackMouse(isBottom ? e.clientX : e.clientY)
|
||||
setDrag(true)
|
||||
}
|
||||
|
||||
const handleFree = (e: MouseEvent | FocusEvent) => {
|
||||
e.preventDefault()
|
||||
setDrag(false)
|
||||
setLastPosition(position)
|
||||
}
|
||||
|
||||
const handleScroll = (e: WheelEvent) => {
|
||||
const {deltaY} = e
|
||||
const value = deltaY > 0 ? 50 : -50
|
||||
position = value + lastPosition
|
||||
changePosition()
|
||||
setLastPosition(position)
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
onMouseDown={handlePress}
|
||||
onMouseUp={handleFree}
|
||||
onMouseMove={handleDragScroll}
|
||||
onMouseLeave={handleFree}
|
||||
onWheel={handleScroll}
|
||||
onBlur={handleFree}
|
||||
className={`panel panel--${orientation} ${isShown ? `panel--${orientation}--shown` : ''}`}
|
||||
>
|
||||
<div className='panel-border'/>
|
||||
{isRendered && children}
|
||||
<button onClick={handleClick}/>
|
||||
<div
|
||||
ref={panel}
|
||||
className='panel-content'
|
||||
>
|
||||
{isShown && children}
|
||||
</div>
|
||||
<button onClick={handleClick}>
|
||||
{orientation === 'bottom' ? language['ui.button.views'] : language['ui.button.places']}
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user