Add main menu; add panel fixes
This commit is contained in:
+1
-3
@@ -29,9 +29,7 @@
|
|||||||
"since 2010"
|
"since 2010"
|
||||||
],
|
],
|
||||||
"development": [
|
"development": [
|
||||||
"last 1 chrome version",
|
"since 2010"
|
||||||
"last 1 firefox version",
|
|
||||||
"last 1 safari version"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-1
@@ -1,7 +1,15 @@
|
|||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import { KeyboardEvent, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
|
import { KeyboardEvent, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
|
||||||
|
|
||||||
import { MusicComponent, PanelComponent, PreviewComponent, SettingsComponent, ViewComponent } from '../components'
|
import {
|
||||||
|
MainMenuComponent,
|
||||||
|
MenuItemComponent,
|
||||||
|
MusicComponent,
|
||||||
|
PanelComponent,
|
||||||
|
PreviewComponent,
|
||||||
|
SettingsComponent,
|
||||||
|
ViewComponent
|
||||||
|
} from '../components'
|
||||||
import places from '../assets'
|
import places from '../assets'
|
||||||
import { delay, soundLoad, UI_SOUND_VOLUME } from '../utils'
|
import { delay, soundLoad, UI_SOUND_VOLUME } from '../utils'
|
||||||
import { useSettings } from '../hooks'
|
import { useSettings } from '../hooks'
|
||||||
@@ -131,6 +139,16 @@ export default function App() {
|
|||||||
className='main'
|
className='main'
|
||||||
>
|
>
|
||||||
<ViewComponent src={places[activePlace].view[activeView]}/>
|
<ViewComponent src={places[activePlace].view[activeView]}/>
|
||||||
|
<MainMenuComponent>
|
||||||
|
<div className='author'>
|
||||||
|
<a href="https://github.com/obergodmar">obergodmar</a>
|
||||||
|
<span>v1.2.0</span>
|
||||||
|
</div>
|
||||||
|
<MenuItemComponent
|
||||||
|
isActive={isSettingsShown}
|
||||||
|
handleClick={openCloseSettings}
|
||||||
|
/>
|
||||||
|
</MainMenuComponent>
|
||||||
<PanelComponent
|
<PanelComponent
|
||||||
openSoundPlay={panelOpenSound.playSound}
|
openSoundPlay={panelOpenSound.playSound}
|
||||||
closeSoundPlay={panelCloseSound.playSound}
|
closeSoundPlay={panelCloseSound.playSound}
|
||||||
|
|||||||
@@ -33,6 +33,30 @@ body {
|
|||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.author {
|
||||||
|
padding: 0 10px;
|
||||||
|
width: 130px;
|
||||||
|
font-family: $font;
|
||||||
|
text-shadow: $fontShadow;
|
||||||
|
color: $fontColor;
|
||||||
|
font-size: 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
a {
|
||||||
|
cursor: $cursorPointer, auto;
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
box-shadow: $hoverBox;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
|
|||||||
@@ -25,3 +25,5 @@ $radio: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAQCAYAAACm53kpA
|
|||||||
$rangeBorder: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIoAAAAQCAYAAADJeudBAAAABmJLR0QAKAAqADbykokVAAABBUlEQVRo3u3asW2DQBiG4RfkghG49qp4hLjGA3BI3gNdEUWurYjCyh5I2APAHqQxc9CRBmySULhJxfdUCKh+vbqTThfw8AYkiDw0QAGwmUfic69Q5O78eZ4ei808kt3rjuyQdRqRVGVlgWQWC7XP/VCV1QDcgFpjWr0auFVlNfjcD0AdAhhjppWkA/aa0+rtgS47ZJ0xBoBw4QeRPy2Emoc8Q6HI86G0batJyKKpDa0ooq1H/i8UnaHIYgshQBzHuNRZwCoWGRuwLnU2jmMAAsYj/OP7MWm/Wi7Xi47wBZc6u33Zcvo4NUATjO9/xNL3vSa1YlEUMY8EKILZd10zkN/u1wy+AWM3S3inoVC2AAAAAElFTkSuQmCC');
|
$rangeBorder: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIoAAAAQCAYAAADJeudBAAAABmJLR0QAKAAqADbykokVAAABBUlEQVRo3u3asW2DQBiG4RfkghG49qp4hLjGA3BI3gNdEUWurYjCyh5I2APAHqQxc9CRBmySULhJxfdUCKh+vbqTThfw8AYkiDw0QAGwmUfic69Q5O78eZ4ei808kt3rjuyQdRqRVGVlgWQWC7XP/VCV1QDcgFpjWr0auFVlNfjcD0AdAhhjppWkA/aa0+rtgS47ZJ0xBoBw4QeRPy2Emoc8Q6HI86G0batJyKKpDa0ooq1H/i8UnaHIYgshQBzHuNRZwCoWGRuwLnU2jmMAAsYj/OP7MWm/Wi7Xi47wBZc6u33Zcvo4NUATjO9/xNL3vSa1YlEUMY8EKILZd10zkN/u1wy+AWM3S3inoVC2AAAAAElFTkSuQmCC');
|
||||||
$range: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAB+ElEQVR4nO2VP2gTURzHP6kOJ1nurR1vcwghOaHERRuuoygGOjQIFeUQddOhq5OtZBShXdO0EIl26ImQs+Io2kBSsVtwu3a6Gxo5muEc8g4zONy7kizmA8e993jv9/vy4/cHZsz437l0gbcCmJfrcNoCDOAWYMq1Lz9l5lI6twCz862zLkVY8nziAkTsfOPlhg3QarbsMRFiGgJE7DxGihBpBKjmgAGY7ic3zGQyxpK1RBAEVJYrLqMc6AOeikGVCAjA1PSSWFldsx49eUbh2lVCNBpNxwJdgG6SIgpJMYH1ldW1qPX+Y6Tppbaml9qgtxtNJ2o0nQj0OCkTo1wFlds3qd5/4QLW3Ts3rIXSglVdrrqqdlILGOfd3peLPAfgsuJ98cFxCINjCsU8AOHgBAjwfh0DwcQECGSj6XR6vH5Ts54+fi7DHlB7VbO6va6yc4BMwntGNpu1B4OBD7pRKObtBw/vARCeBXR7Xerb9bfAIeDKfyIS94HhcOgBPmjzJ95p6HmnRrGY5/D7V+rbdZdR/QvpPHEvSCog/Gs0NMqL1+0r2hzh7zPOh+fkcjnj6MeRC+wDP1GYjqpV4AP+weeDrfHDnd2dLUZdsE/KqaiCAdjAZnmxHAGbcp9qGiZNwn+JiKefzyjx+iltpSYuzYn1/hkzZkyFP182nWrkPhvCAAAAAElFTkSuQmCC');
|
$range: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAB+ElEQVR4nO2VP2gTURzHP6kOJ1nurR1vcwghOaHERRuuoygGOjQIFeUQddOhq5OtZBShXdO0EIl26ImQs+Io2kBSsVtwu3a6Gxo5muEc8g4zONy7kizmA8e993jv9/vy4/cHZsz437l0gbcCmJfrcNoCDOAWYMq1Lz9l5lI6twCz862zLkVY8nziAkTsfOPlhg3QarbsMRFiGgJE7DxGihBpBKjmgAGY7ic3zGQyxpK1RBAEVJYrLqMc6AOeikGVCAjA1PSSWFldsx49eUbh2lVCNBpNxwJdgG6SIgpJMYH1ldW1qPX+Y6Tppbaml9qgtxtNJ2o0nQj0OCkTo1wFlds3qd5/4QLW3Ts3rIXSglVdrrqqdlILGOfd3peLPAfgsuJ98cFxCINjCsU8AOHgBAjwfh0DwcQECGSj6XR6vH5Ts54+fi7DHlB7VbO6va6yc4BMwntGNpu1B4OBD7pRKObtBw/vARCeBXR7Xerb9bfAIeDKfyIS94HhcOgBPmjzJ95p6HmnRrGY5/D7V+rbdZdR/QvpPHEvSCog/Gs0NMqL1+0r2hzh7zPOh+fkcjnj6MeRC+wDP1GYjqpV4AP+weeDrfHDnd2dLUZdsE/KqaiCAdjAZnmxHAGbcp9qGiZNwn+JiKefzyjx+iltpSYuzYn1/hkzZkyFP182nWrkPhvCAAAAAElFTkSuQmCC');
|
||||||
$rangeBackground: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAFUlEQVR4nGNkYGDoYMADmPBJDh8FAJNoAJjpM54wAAAAAElFTkSuQmCC');
|
$rangeBackground: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAFUlEQVR4nGNkYGDoYMADmPBJDh8FAJNoAJjpM54wAAAAAElFTkSuQmCC');
|
||||||
|
$helpButton: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAApCAMAAABjq9sOAAABp1BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAACAgIDAgLDQsODQsODwsOEA4TDQsTDw4WFhMWFxYYGBgYHBgZGBYbGRYbGxYbHBsbHRsbHxshGBAhHxshIBghICEhJCEkIRskIx4kIyEmEwsmGxYmHRsmIx4mJRsmJSEpGBgpICEpJCEpKCEpKCkpLCksKyYxFBAxGBAxHBgxJBgxLCkxLSw3GBA3MzE3NzQ5GBM5KCE5LCk5OzlCQTlHRkJKExBKQUJKRUJKSUJKTUpNDxBNEAhNHQ1STUpSUUpSU1JSVVJVExBYV1JdEAtdFBBjBAhjCABjCwhjEAhlY2BoFQ1oZ2hrDAhrDQhrFAhrFBBraWNwJRtwOClzCAhzKBBzb257DAh7EAh7dWt7dXN7eXt7fXuEAACEfXuEgnuJDAWJDAiMCACMKh6RIBaUjoyXKBuaLB6cmpyfKxinKyGtpqWwEwuwJx6wWUG1BAC1CAC4NSO9bUrIRTTLLSHLQS/OXUrTSjneSTHee2XvKCHveVrvmIH3EAj3MCn3XUr/WUL/aVL/tpzPGTKNAAAACHRSTlMAESIzVYjM7umjQSUAAAIfSURBVDjLhdT7W9JQGMDxMZw7k25aUWqCsATXSior7aYIRasIAiIw5NK9GBia3TAvtQGK/tG9Z7MaZwO/vwDP++GMhz17KQqy0XaLaBt1EN3HWNZH/533s5b16wLm6Eup9AZ6C72GPkCrq891YYPvl0rIIk3YKJph3+UQmr9LdNPh+PSRZWjKzrCPEMrN3yN6BuIJy9h1kEP8KSKHwwh4vid4zE0dHz4NnYNeQlch3+AgkkwgnU5rIG8CwxjcSn9ttdbWfu01vufzPp8ZvIJ5C+Z7jUYjf8cAQigwMjI9Lcs7ULVQ/dncbyrF8wMDDztAXP4B88/VQqGqNPeVByYgx+XNzZ1iAcC2FYjLslyEMFAUZbvjEtz1sbGnUCYTFa8tLantdrt2e+IEChvBfQ2IIszV9lYtNUGCcUgUxeg3VVVrqVQ3EM3AXE0RQMIA7hd/IVip1Ov12AvAl84e/fdHaUDAoFKplMvl2HgXIAQPAXwwm83GYrErJAjDzZrCvyEDLULwVjABQRAALK/v7m4s4nmXE5Z/64DnzSfw+ITM+sbKiukSIS4wGvBOeieT75PJSCSS8Hv8/otnjnEhAxj1QhgkEokZD2QNkhjMuDwulxm43V636yA4oOMSEnfD6XQTXR4aQv8B53SeJIK5DuDpnl3gOO4IEcznQvjpxvthAQsimM9p+0HbQLOSFIZCkAThV/ho2EE9d9ThW673nvwDLWrF2ZF5DfoAAAAASUVORK5CYII=');
|
||||||
|
$helpButtonClick: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAApCAMAAABjq9sOAAABPlBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMIAAALAAAOAAAQAAAQBAAYAAAZAwAbAAAeHh4hAAAhICEpAAAsCQUsEw4xBAMxBwMxMDE0MjE3AAA3BAM3MzE8OzxCAABCBABCBQVCFhBCQTlEEAtKBABKBQNKCABKCANKGBBKQUJKRTlKRUJKSUJKTUpMGBNPEwtSAABSCABSGBBSTUpSUUpSU1JSVVJYJRtYV1JaWVpbDQVdDQhjCAVjCAhoFw5oZ2hrCAhuCAVuIxlwGxNzHBBzKyFzb257dWt7dXN7eXt7fXuBIBaBMSaDCwWDDAWEFAiEHxiEOCmEfXuEgnuHKRuJPjGPHRWUDAiUIBiXW02cNimclpScmpylDAilPCmlQTGlWUqtIBitpqW1STm1TTm9EAi9MCG9fWsZTHqDAAAACHRSTlMAESIzVYjM7umjQSUAAAGuSURBVDjLjdTpUoJgFIBhRBGiyLIyK8nIlKgosGjPirJodWmx1FIxt/u/gQ4EDX4i9f4RPA84MsPBMMiH+13CfZgVHiBcC+D2PEi6FvwRMKe+NO0WuoNuoGfo8/P8R/jgek2jXDKFD8MJ8v6Icu3jhSRwzE+Qe9SQDknCb4FweBqpHxzF4/NICw6wP+K4LQ3Zx4oLYJNJD8Cy7EUSOph1BROrF7Va7aHb7T5ZwgaiccIwfK4JlXRdr1TW1ozvdvsAz3dgnt3eLuk9EAOA53MAsgAu9UpvEIQA5N6aOzsASj0EbMBx7BSSZZlWVbXdarUkA6w4QHoZikRoAG0AkgFCThAzAU3LarVafZSkEHoH6zHLV0W1qMK8Dyi/jzqaee908kLKOhVREM1k3vN5QaCGgLEMJAjCuDWfQsEMAkZtsGmBWApKMAxj/8QWAiZNkEh4gLPXeqMxHKRTZ/V643oQiBZYOjkplwuFYxr9mw7AcXNzHoDjDED/AehBoAx79f4H4O1eFN3n66Lxdhv7QQQxggTzdXM/mBtoUVE2IRFSIOMTTh07yHNH/b3lvPfkN1HZaz2zDt62AAAAAElFTkSuQmCC');
|
||||||
|
|||||||
@@ -7,3 +7,5 @@ export { SettingsComponent } from './settings-component/settings-component'
|
|||||||
export { CheckBoxComponent } from './checkbox-component/checkbox-component'
|
export { CheckBoxComponent } from './checkbox-component/checkbox-component'
|
||||||
export { BorderedHeader } from './bordered-header/bordered-header'
|
export { BorderedHeader } from './bordered-header/bordered-header'
|
||||||
export { MusicComponent } from './music-component/music-component'
|
export { MusicComponent } from './music-component/music-component'
|
||||||
|
export { MainMenuComponent } from './main-menu-component/main-menu-component'
|
||||||
|
export { MenuItemComponent } from './menu-item-component/menu-item-component'
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
@import "../../app/style";
|
||||||
|
|
||||||
|
$menuHeight: 42px;
|
||||||
|
$menuWidth: 290px;
|
||||||
|
|
||||||
|
.main-menu {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index: 3;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
border: 1px double $fontColor;
|
||||||
|
border-image: $rangeBorder 5 5 5 5;
|
||||||
|
background: $panelBackground center repeat;
|
||||||
|
border-image-width: 5px;
|
||||||
|
border-image-repeat: round round;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 2px 3px;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import * as React from 'react'
|
||||||
|
|
||||||
|
import './main-menu-component.scss'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MainMenuComponent = ({children}: Props) => {
|
||||||
|
return (
|
||||||
|
<div className='main-menu'>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
MainMenuComponent.displayName = 'MainMenuComponent'
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
@import '../../app/style';
|
||||||
|
|
||||||
|
$menuItemWidth: 32px;
|
||||||
|
$menuItemHeight: 41px;
|
||||||
|
|
||||||
|
.menu-item {
|
||||||
|
width: $menuItemWidth - 4px;
|
||||||
|
height: $menuItemHeight - 4px;
|
||||||
|
border-radius: 6px;
|
||||||
|
background-image: $helpButton;
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: $menuItemWidth $menuItemHeight;
|
||||||
|
|
||||||
|
&--active {
|
||||||
|
background-image: $helpButtonClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: $hoverBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
box-shadow: $hoverBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-image: $helpButtonClick;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import * as React from 'react'
|
||||||
|
import { KeyboardEvent } from 'react'
|
||||||
|
|
||||||
|
import './menu-item-component.scss'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
isActive: boolean
|
||||||
|
handleClick: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MenuItemComponent = ({isActive, handleClick}: Props) => {
|
||||||
|
|
||||||
|
const handleKeyDown = (e: KeyboardEvent) => {
|
||||||
|
if (e.keyCode !== 13 && e.keyCode !== 32) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
handleClick()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
tabIndex={0}
|
||||||
|
onClick={handleClick}
|
||||||
|
onKeyDown={handleKeyDown}
|
||||||
|
className={`menu-item ${isActive ? 'menu-item--active' : ''}`}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItemComponent.displayName = 'MainMenuComponent'
|
||||||
@@ -57,7 +57,7 @@ export const PanelComponent = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const resizePanel = useCallback((animate = true) => {
|
const resetPanel = useCallback((animate = true) => {
|
||||||
if (!panel.current) {
|
if (!panel.current) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -73,7 +73,7 @@ export const PanelComponent = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let timeout: NodeJS.Timeout
|
let timeout: NodeJS.Timeout
|
||||||
const handleResize = debounce(() => {
|
const handleResize = debounce(() => {
|
||||||
resizePanel()
|
resetPanel()
|
||||||
timeout = setTimeout(() => {
|
timeout = setTimeout(() => {
|
||||||
if (!panel || !panel.current) {
|
if (!panel || !panel.current) {
|
||||||
return
|
return
|
||||||
@@ -88,33 +88,48 @@ export const PanelComponent = ({
|
|||||||
}
|
}
|
||||||
window.removeEventListener('resize', handleResize)
|
window.removeEventListener('resize', handleResize)
|
||||||
}
|
}
|
||||||
}, [panel, resizePanel])
|
}, [panel, resetPanel])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isShown) {
|
if (!isShown) {
|
||||||
resizePanel(false)
|
resetPanel(false)
|
||||||
}
|
}
|
||||||
}, [isShown, resizePanel])
|
}, [isShown, resetPanel])
|
||||||
|
|
||||||
const handleDragScroll = (e: MouseEvent) => {
|
const handleDragScroll = (e: MouseEvent) => {
|
||||||
if (!isDrag) {
|
if (!isDrag) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
const overflow = windowOverflow()
|
||||||
|
if (!overflow) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const {clientX, clientY} = e
|
||||||
|
const value = isBottom ? clientX : clientY
|
||||||
|
const diff = limiter(value, overflow)
|
||||||
|
setPosition(diff)
|
||||||
|
changePosition()
|
||||||
|
}
|
||||||
|
|
||||||
|
const windowOverflow = () => {
|
||||||
const {innerWidth, innerHeight} = window
|
const {innerWidth, innerHeight} = window
|
||||||
const windowSize = isBottom ? innerWidth : innerHeight
|
const windowSize = isBottom ? innerWidth : innerHeight
|
||||||
const containerSize = itemsCount * ((isBottom ? PREVIEW_WIDTH : PREVIEW_HEIGHT) + 15)
|
const containerSize = itemsCount * ((isBottom ? PREVIEW_WIDTH : PREVIEW_HEIGHT) + 15)
|
||||||
if (!(containerSize > windowSize)) {
|
if (!(containerSize > windowSize)) {
|
||||||
return
|
return 0
|
||||||
}
|
}
|
||||||
const overflow = Math.abs(containerSize - windowSize)
|
return Math.abs(containerSize - windowSize)
|
||||||
const {clientX, clientY} = e
|
|
||||||
const value = isBottom ? clientX : clientY
|
|
||||||
const diff = trackMouse - value + lastPosition
|
|
||||||
if (Math.abs(diff) > overflow + 40 || diff < 0) {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
setPosition(diff)
|
|
||||||
changePosition()
|
const limiter = (value: number, overflow: number, isWheel: boolean = false) => {
|
||||||
|
let diff = (!isWheel ? trackMouse : 0) - value + lastPosition
|
||||||
|
if (Math.abs(diff) > overflow + 40) {
|
||||||
|
diff = overflow + 40
|
||||||
|
} else if (diff < 0) {
|
||||||
|
diff = 0
|
||||||
|
}
|
||||||
|
return diff
|
||||||
}
|
}
|
||||||
|
|
||||||
const changePosition = () => {
|
const changePosition = () => {
|
||||||
@@ -125,8 +140,9 @@ export const PanelComponent = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleMouseDown = (e: MouseEvent) => {
|
const handleMouseDown = (e: MouseEvent) => {
|
||||||
|
const {clientX, clientY} = e
|
||||||
e.nativeEvent.stopImmediatePropagation()
|
e.nativeEvent.stopImmediatePropagation()
|
||||||
setTrackMouse(isBottom ? e.clientX : e.clientY)
|
setTrackMouse(isBottom ? clientX : clientY)
|
||||||
setDrag(true)
|
setDrag(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,19 +155,14 @@ export const PanelComponent = ({
|
|||||||
|
|
||||||
const handleTouchMove = (e: TouchEvent) => {
|
const handleTouchMove = (e: TouchEvent) => {
|
||||||
const {touches} = e
|
const {touches} = e
|
||||||
const {innerWidth, innerHeight} = window
|
|
||||||
const windowSize = isBottom ? innerWidth : innerHeight
|
|
||||||
const containerSize = itemsCount * ((isBottom ? PREVIEW_WIDTH : PREVIEW_HEIGHT) + 15)
|
|
||||||
if (!(containerSize > windowSize)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const overflow = Math.abs(containerSize - windowSize)
|
|
||||||
const {clientX, clientY} = touches[0]
|
const {clientX, clientY} = touches[0]
|
||||||
const value = isBottom ? clientX : clientY
|
const overflow = windowOverflow()
|
||||||
const diff = trackMouse - value + lastPosition
|
if (!overflow) {
|
||||||
if (Math.abs(diff) > overflow + 40 || diff < 0) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const value = isBottom ? clientX : clientY
|
||||||
|
const diff = limiter(value, overflow)
|
||||||
setPosition(diff)
|
setPosition(diff)
|
||||||
changePosition()
|
changePosition()
|
||||||
}
|
}
|
||||||
@@ -164,17 +175,13 @@ export const PanelComponent = ({
|
|||||||
|
|
||||||
const handleScroll = (e: WheelEvent) => {
|
const handleScroll = (e: WheelEvent) => {
|
||||||
const {deltaY} = e
|
const {deltaY} = e
|
||||||
const {innerWidth, innerHeight} = window
|
const overflow = windowOverflow()
|
||||||
const windowSize = isBottom ? innerWidth : innerHeight
|
if (!overflow) {
|
||||||
const containerSize = itemsCount * ((isBottom ? PREVIEW_WIDTH : PREVIEW_HEIGHT) + 15)
|
|
||||||
if (!(containerSize > windowSize)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const overflow = Math.abs(containerSize - windowSize)
|
|
||||||
const diff = (deltaY > 0 ? 80 : -80) + lastPosition
|
|
||||||
if (Math.abs(diff) > overflow + 40 || diff < 0) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const value = deltaY > 0 ? 80 : -80
|
||||||
|
const diff = limiter(value, overflow, true)
|
||||||
setPosition(diff)
|
setPosition(diff)
|
||||||
changePosition()
|
changePosition()
|
||||||
setLastPosition(position)
|
setLastPosition(position)
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export const RangeComponent = ({handleChange, defaultValue}: Props) => {
|
|||||||
}
|
}
|
||||||
const {width, left} = (stick.current.parentNode as HTMLDivElement).getBoundingClientRect()
|
const {width, left} = (stick.current.parentNode as HTMLDivElement).getBoundingClientRect()
|
||||||
const {clientX} = e
|
const {clientX} = e
|
||||||
const diff = clientX - left
|
const diff = clientX - left - 20
|
||||||
if (diff > width - 35 || diff < 0) {
|
if (diff > width - 35 || diff < 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,34 +25,6 @@
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
&-author {
|
|
||||||
z-index: 2;
|
|
||||||
position: absolute;
|
|
||||||
right: 10px;
|
|
||||||
top: 10px;
|
|
||||||
width: 110px;
|
|
||||||
font-family: $font;
|
|
||||||
text-shadow: $fontShadow;
|
|
||||||
color: $fontColor;
|
|
||||||
font-size: 16px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
opacity: .3;
|
|
||||||
|
|
||||||
a {
|
|
||||||
cursor: $cursorPointer, auto;
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
outline: none;
|
|
||||||
box-shadow: $hoverBox;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulse {
|
@keyframes pulse {
|
||||||
|
|||||||
@@ -37,10 +37,6 @@ export const ViewComponent = ({src}: Props) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className={`view-background ${isLoaded ? 'view-background--loaded' : ''}`}/>
|
<div className={`view-background ${isLoaded ? 'view-background--loaded' : ''}`}/>
|
||||||
<div className='view-author'>
|
|
||||||
<a href="https://github.com/obergodmar">obergodmar</a>
|
|
||||||
<span>1.1.0</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-7
@@ -20,15 +20,12 @@ export const randomNumber = (min: number, max: number) => (
|
|||||||
Math.floor(Math.random() * (max - min)) + min
|
Math.floor(Math.random() * (max - min)) + min
|
||||||
)
|
)
|
||||||
|
|
||||||
export const debounce = (fn: () => any, ms: number) => {
|
export function debounce(fn: (args: any) => any, ms: number) {
|
||||||
let timer: NodeJS.Timeout | null
|
let timer: NodeJS.Timeout
|
||||||
return () => {
|
return (...args: any) => {
|
||||||
if (timer) {
|
if (timer) {
|
||||||
clearTimeout(timer)
|
clearTimeout(timer)
|
||||||
}
|
}
|
||||||
timer = setTimeout(() => {
|
timer = setTimeout(() => fn.apply(this, args), ms)
|
||||||
timer = null
|
|
||||||
fn()
|
|
||||||
}, ms)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"downlevelIteration": true,
|
"downlevelIteration": true,
|
||||||
|
"noImplicitThis": false,
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
|
|||||||
Reference in New Issue
Block a user