mirror of
https://github.com/He4eT/elseifplayer.git
synced 2026-05-04 17:07:22 +00:00
Player: replace player.css with scss modules
This commit is contained in:
parent
ae9456d6dd
commit
ade6f5d2c3
14 changed files with 189 additions and 181 deletions
|
|
@ -14,7 +14,7 @@ import ThemesView from '~/src/views/ThemesView/ThemesView'
|
||||||
import PlayerView from '~/src/views/PlayerView/PlayerView'
|
import PlayerView from '~/src/views/PlayerView/PlayerView'
|
||||||
import NotFoundView from '~/src/views/NotFoundView/NotFoundView'
|
import NotFoundView from '~/src/views/NotFoundView/NotFoundView'
|
||||||
|
|
||||||
import * as style from './style/App.module.scss'
|
import * as s from './style/App.module.scss'
|
||||||
|
|
||||||
export default function App () {
|
export default function App () {
|
||||||
const themeEngine = useThemeEngine()
|
const themeEngine = useThemeEngine()
|
||||||
|
|
@ -32,9 +32,10 @@ export default function App () {
|
||||||
return (
|
return (
|
||||||
<Router hook={useHashLocation}>
|
<Router hook={useHashLocation}>
|
||||||
<div className={[
|
<div className={[
|
||||||
style.app,
|
s.app,
|
||||||
style[extractView(currentLocation)],
|
s[extractView(currentLocation)],
|
||||||
themeEngine.currentTheme].join(' ')}>
|
themeEngine.currentTheme,
|
||||||
|
].join(' ')}>
|
||||||
|
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path='/'>
|
<Route path='/'>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ import { useEffect, useRef, useState } from 'preact/hooks'
|
||||||
|
|
||||||
import MenuButton from './MenuButton/MenuButton'
|
import MenuButton from './MenuButton/MenuButton'
|
||||||
|
|
||||||
|
import * as s from './InputBox.module.scss'
|
||||||
|
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
const keyCodes = {
|
const keyCodes = {
|
||||||
KEY_BACKSPACE: 8,
|
KEY_BACKSPACE: 8,
|
||||||
|
|
@ -147,9 +149,9 @@ export default function InputBox ({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className='inputControls'>
|
<section className={s.inputControls}>
|
||||||
<input {...inputHandlers[inputType]}
|
<input {...inputHandlers[inputType]}
|
||||||
className='inputBox'
|
className={s.inputBox}
|
||||||
ref={inputEl}
|
ref={inputEl}
|
||||||
value={inputText}
|
value={inputText}
|
||||||
autofocus
|
autofocus
|
||||||
|
|
|
||||||
31
src/components/Player/InputBox/InputBox.module.scss
Normal file
31
src/components/Player/InputBox/InputBox.module.scss
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
.inputControls {
|
||||||
|
position: relative;
|
||||||
|
margin-top: var(--input-box-margin);
|
||||||
|
|
||||||
|
.inputBox {
|
||||||
|
font: inherit;
|
||||||
|
color: inherit;
|
||||||
|
outline: 0;
|
||||||
|
|
||||||
|
background-color: var(--bg-color);
|
||||||
|
border: var(--border-width) solid var(--main-color);
|
||||||
|
border-top: var(--separator-width) solid var(--main-color);
|
||||||
|
padding: var(--inner-padding);
|
||||||
|
padding-right: calc(4 * var(--inner-padding));
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: var(--main-color);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus::placeholder {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-search-cancel-button {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
.menu {
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
border-left: none;
|
|
||||||
border-right: none;
|
|
||||||
text-align: center;
|
|
||||||
padding-top: 0;
|
|
||||||
padding-bottom: 0;
|
|
||||||
|
|
||||||
background-color: var(--bg-color);
|
|
||||||
border-color: var(--main-color);
|
|
||||||
color: var(--main-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu::backdrop {
|
|
||||||
background: none;
|
|
||||||
backdrop-filter: blur(2px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu > section {
|
|
||||||
margin: 32px auto 40px;
|
|
||||||
gap: 32px;
|
|
||||||
max-width: 270px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu .navigation {
|
|
||||||
color: var(--accent-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu .appearance {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu select,
|
|
||||||
.menu button {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { Link } from 'wouter-preact'
|
||||||
import ThemeSelector from
|
import ThemeSelector from
|
||||||
'~/src/components/ThemeSelector/ThemeSelector'
|
'~/src/components/ThemeSelector/ThemeSelector'
|
||||||
|
|
||||||
import './MenuOverlay.css'
|
import * as s from './MenuOverlay.module.scss'
|
||||||
|
|
||||||
export default function MenuOverlay ({
|
export default function MenuOverlay ({
|
||||||
themeEngine, onFullscreenRequest, menuOpen, setMenuOpen,
|
themeEngine, onFullscreenRequest, menuOpen, setMenuOpen,
|
||||||
|
|
@ -35,7 +35,7 @@ export default function MenuOverlay ({
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<dialog ref={dialog} className='menu'>
|
<dialog ref={dialog} className={s.menu}>
|
||||||
<section>
|
<section>
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
|
|
@ -46,7 +46,7 @@ export default function MenuOverlay ({
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='appearance'>
|
<div className={s.appearance}>
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
dialog.current.close()
|
dialog.current.close()
|
||||||
|
|
@ -68,7 +68,7 @@ export default function MenuOverlay ({
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='navigation'>
|
<div className={s.navigation}>
|
||||||
<Link href="/" tabIndex={0}>
|
<Link href="/" tabIndex={0}>
|
||||||
ElseIfPlayer
|
ElseIfPlayer
|
||||||
</Link>
|
</Link>
|
||||||
|
|
|
||||||
41
src/components/Player/MenuOverlay/MenuOverlay.module.scss
Normal file
41
src/components/Player/MenuOverlay/MenuOverlay.module.scss
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
.menu {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
border-left: none;
|
||||||
|
border-right: none;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
|
||||||
|
background-color: var(--bg-color);
|
||||||
|
border-color: var(--main-color);
|
||||||
|
color: var(--main-color);
|
||||||
|
|
||||||
|
&::backdrop {
|
||||||
|
background: none;
|
||||||
|
backdrop-filter: blur(2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
& > section {
|
||||||
|
margin: 32px auto 40px;
|
||||||
|
gap: 32px;
|
||||||
|
max-width: 270px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation {
|
||||||
|
color: var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.appearance {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
select,
|
||||||
|
button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import { useEffect, useState } from 'preact/hooks'
|
import { useEffect, useState } from 'preact/hooks'
|
||||||
|
|
||||||
import TextMessage from './TextMessage'
|
import TextMessage from '../TextMessage/TextMessage'
|
||||||
|
|
||||||
|
import * as s from '../../Player.module.scss'
|
||||||
|
|
||||||
export default function GridBuffer ({ inbox, currentWindow }) {
|
export default function GridBuffer ({ inbox, currentWindow }) {
|
||||||
const [prevMessages, setPrevMessages] = useState([])
|
const [prevMessages, setPrevMessages] = useState([])
|
||||||
|
|
@ -70,8 +72,7 @@ export default function GridBuffer ({ inbox, currentWindow }) {
|
||||||
}, [inbox, currentWindow, prevMessages])
|
}, [inbox, currentWindow, prevMessages])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section
|
<section className={[s.buffer, s.gridBuffer].join(' ')}>
|
||||||
className='buffer gridBuffer'>
|
|
||||||
{messages.map(TextMessage)}
|
{messages.map(TextMessage)}
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import { useEffect, useRef, useState } from 'preact/hooks'
|
import { useEffect, useRef, useState } from 'preact/hooks'
|
||||||
|
|
||||||
import TextMessage from './TextMessage'
|
import TextMessage from '../TextMessage/TextMessage'
|
||||||
|
|
||||||
|
import * as s from '../../Player.module.scss'
|
||||||
|
|
||||||
const isFakeStatus = (w) =>
|
const isFakeStatus = (w) =>
|
||||||
w.height < 5
|
w.height < 5
|
||||||
|
|
@ -75,17 +77,19 @@ export default function TextBuffer ({ inbox, currentWindow }) {
|
||||||
}, 0)
|
}, 0)
|
||||||
}, [currentWindow, inbox])
|
}, [currentWindow, inbox])
|
||||||
|
|
||||||
const classes = [
|
const classes = () => [
|
||||||
|
s.buffer,
|
||||||
isFakeStatus(currentWindow)
|
isFakeStatus(currentWindow)
|
||||||
? 'gridBuffer'
|
? s.gridBuffer
|
||||||
: 'textBuffer',
|
: s.textBuffer,
|
||||||
'buffer'].join(' ')
|
].join(' ')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
tabindex='0'
|
tabindex='0'
|
||||||
ref={textBufferEl}
|
ref={textBufferEl}
|
||||||
className={classes}>
|
className={classes()}
|
||||||
|
>
|
||||||
{messages.map(TextMessage)}
|
{messages.map(TextMessage)}
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
export default function TextMessage ({ style, text }) {
|
|
||||||
const defaultContent = (
|
|
||||||
<span className={['message', style].join(' ')}>
|
|
||||||
{text}
|
|
||||||
</span>)
|
|
||||||
|
|
||||||
return ({
|
|
||||||
grid: (text?.length > 0 ? <div>{text}</div> : <br />),
|
|
||||||
input: (<span className='message input'>> {text}</span>),
|
|
||||||
subheader: (<strong className='message subheader'>{text}</strong>),
|
|
||||||
emphasized: (<em className='message emphasized'>{text}</em>),
|
|
||||||
endOfLine: (<br />),
|
|
||||||
})[style] || defaultContent
|
|
||||||
}
|
|
||||||
21
src/components/Player/OutputBox/TextMessage/TextMessage.jsx
Normal file
21
src/components/Player/OutputBox/TextMessage/TextMessage.jsx
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import * as s from './TextMessage.module.scss'
|
||||||
|
|
||||||
|
export default function TextMessage ({ style, text }) {
|
||||||
|
const defaultContent = (
|
||||||
|
<span className={[s.message, s[style]].join(' ')}>
|
||||||
|
{text}
|
||||||
|
</span>)
|
||||||
|
|
||||||
|
return ({
|
||||||
|
grid:
|
||||||
|
(text?.length > 0 ? <div>{text}</div> : <br />),
|
||||||
|
input:
|
||||||
|
(<span className={[s.message, s.input].join(' ')}>> {text}</span>),
|
||||||
|
subheader:
|
||||||
|
(<strong className={[s.message, s.subheader].join(' ')}>{text}</strong>),
|
||||||
|
emphasized:
|
||||||
|
(<em className={[s.message, s.emphasized].join(' ')}>{text}</em>),
|
||||||
|
endOfLine:
|
||||||
|
(<br />),
|
||||||
|
})[style] || defaultContent
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
.message {
|
||||||
|
&.input {
|
||||||
|
scroll-margin-top: var(--inner-padding);
|
||||||
|
color: var(--input-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.emphasized,
|
||||||
|
&.subheader {
|
||||||
|
color: var(--accent-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,8 +2,8 @@ import { useState, useEffect } from 'preact/hooks'
|
||||||
|
|
||||||
import CheapGlkOte from 'cheap-glkote'
|
import CheapGlkOte from 'cheap-glkote'
|
||||||
|
|
||||||
import TextBuffer from './OutputBox/TextBuffer'
|
import TextBuffer from './OutputBox/TextBuffer/TextBuffer'
|
||||||
import GridBuffer from './OutputBox/GridBuffer'
|
import GridBuffer from './OutputBox/GridBuffer/GridBuffer'
|
||||||
|
|
||||||
import InputBox from './InputBox/InputBox'
|
import InputBox from './InputBox/InputBox'
|
||||||
import Status from './Status/Status'
|
import Status from './Status/Status'
|
||||||
|
|
@ -13,7 +13,7 @@ import {
|
||||||
unhandledRejectionHandler,
|
unhandledRejectionHandler,
|
||||||
} from './common/playerHandlers'
|
} from './common/playerHandlers'
|
||||||
|
|
||||||
import './player.css'
|
import * as s from './Player.module.scss'
|
||||||
|
|
||||||
const INITIAL_STATUS = {
|
const INITIAL_STATUS = {
|
||||||
stage: 'loading',
|
stage: 'loading',
|
||||||
|
|
@ -104,14 +104,16 @@ export default function Player ({
|
||||||
|
|
||||||
return status.stage !== 'ready'
|
return status.stage !== 'ready'
|
||||||
? (<Status {...status} />)
|
? (<Status {...status} />)
|
||||||
: (<section className='ifplayer'>
|
: (<section className={s.elseifplayer}>
|
||||||
<section className='output'>{
|
<section className={s.output}>
|
||||||
|
{
|
||||||
windows
|
windows
|
||||||
.sort(byTop)
|
.sort(byTop)
|
||||||
.filter(singleWindow
|
.filter(singleWindow
|
||||||
? ({ id }) => id === currentWindowId
|
? ({ id }) => id === currentWindowId
|
||||||
: () => true)
|
: () => true)
|
||||||
.map(textWindow(inbox))}
|
.map(textWindow(inbox))
|
||||||
|
}
|
||||||
</section>
|
</section>
|
||||||
<InputBox {...{
|
<InputBox {...{
|
||||||
inputType,
|
inputType,
|
||||||
|
|
|
||||||
49
src/components/Player/Player.module.scss
Normal file
49
src/components/Player/Player.module.scss
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
.elseifplayer {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
background-color: var(--bg-color);
|
||||||
|
color: var(--main-color);
|
||||||
|
padding: var(--outer-padding);
|
||||||
|
|
||||||
|
.output {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 2;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow-y: hidden;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
|
||||||
|
border: var(--border-width) solid var(--main-color);
|
||||||
|
|
||||||
|
.buffer {
|
||||||
|
overflow-y: scroll;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
padding: var(--inner-padding);
|
||||||
|
|
||||||
|
&:empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > br:first-child,
|
||||||
|
& > br:last-child,
|
||||||
|
& > br + br + br {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.gridBuffer {
|
||||||
|
flex-shrink: 0;
|
||||||
|
max-height: 100%;
|
||||||
|
border-bottom: var(--separator-width) solid var(--main-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.textBuffer {
|
||||||
|
flex: 2 1;
|
||||||
|
outline: none;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,100 +0,0 @@
|
||||||
.ifplayer {
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
background-color: var(--bg-color);
|
|
||||||
color: var(--main-color);
|
|
||||||
padding: var(--outer-padding);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ifplayer .inputControls {
|
|
||||||
position: relative;
|
|
||||||
margin-top: var(--input-box-margin);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ifplayer .inputControls .menuButton {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ifplayer .inputBox {
|
|
||||||
font: inherit;
|
|
||||||
color: inherit;
|
|
||||||
outline: 0;
|
|
||||||
|
|
||||||
background-color: var(--bg-color);
|
|
||||||
border: var(--border-width) solid var(--main-color);
|
|
||||||
border-top: var(--separator-width) solid var(--main-color);
|
|
||||||
padding: var(--inner-padding);
|
|
||||||
padding-right: calc(4 * var(--inner-padding));
|
|
||||||
margin: 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ifplayer .inputBox::placeholder {
|
|
||||||
color: var(--main-color);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ifplayer .inputBox:focus::placeholder {
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ifplayer .inputBox::-webkit-search-cancel-button {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ifplayer .output {
|
|
||||||
display: flex;
|
|
||||||
flex-grow: 2;
|
|
||||||
flex-direction: column;
|
|
||||||
overflow-y: hidden;
|
|
||||||
overflow-wrap: break-word;
|
|
||||||
|
|
||||||
border: var(--border-width) solid var(--main-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ifplayer .output .buffer {
|
|
||||||
overflow-y: scroll;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
padding: var(--inner-padding);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ifplayer .output .buffer:empty {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ifplayer .output .gridBuffer {
|
|
||||||
flex-shrink: 0;
|
|
||||||
max-height: 100%;
|
|
||||||
border-bottom: var(--separator-width) solid var(--main-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ifplayer .output .textBuffer {
|
|
||||||
flex: 2 1;
|
|
||||||
outline: none;
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ifplayer .output .textBuffer > br:first-child,
|
|
||||||
.ifplayer .output .gridBuffer > br:first-child,
|
|
||||||
.ifplayer .output .textBuffer > br:last-child,
|
|
||||||
.ifplayer .output .gridBuffer > br:last-child,
|
|
||||||
.ifplayer .output .textBuffer > br + br + br,
|
|
||||||
.ifplayer .output .gridBuffer > br + br + br {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ifplayer .output .textBuffer .message.input {
|
|
||||||
scroll-margin-top: var(--inner-padding);
|
|
||||||
color: var(--input-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ifplayer .output .textBuffer .message.emphasized,
|
|
||||||
.ifplayer .output .textBuffer .message.subheader {
|
|
||||||
color: var(--accent-color);
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue