chore: moved to a new branch to save space
This commit is contained in:
14
directory/src/component/border.jsx
Normal file
14
directory/src/component/border.jsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classes from './scss/border.module.scss';
|
||||
|
||||
export default function Border(props) {
|
||||
return (
|
||||
<section className={classes.border}>
|
||||
{props.children}
|
||||
</section>
|
||||
)
|
||||
}
|
||||
Border.propTypes = {
|
||||
children: PropTypes.node,
|
||||
};
|
||||
20
directory/src/component/char_icon.jsx
Normal file
20
directory/src/component/char_icon.jsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export default function CharIcon(props) {
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox={props.viewBox}>
|
||||
{
|
||||
props.type === 'operator' ?
|
||||
<g><path d="M89 17.5 30.4 57 24.3 71.4 82.9 32.6Z"></path><path d="M0 17.5 58.6 57 64.7 71.4 6.1 32.7Z"> </path><path d="M89 0 30.4 39.5 24.3 53.9 82.9 15.1Z"> </path><path d="M0 0 58.6 39.5 64.7 53.9 6.1 15.2Z"> </path></g>
|
||||
:
|
||||
<path d="M90.4 50.6l-39.8-23.5v-4c0-4.5-5-6.5-5-6.5a5.4 5.4 0 012.2-10.1c2.7 0 5.3 1.5 5.5 4.8.4 5.3 6.4 3.9 6.4-.3a11.7 11.7 0 00-12-11c-9 0-11.6 8.8-11.6 11.6a11.5 11.5 0 001.6 6.2c2.2 3.8 6.6 4.3 6.6 6.8v2.5L4.2 50.7c-4 2.3-4.7 7.3-3.8 10.3a9.1 9.1 0 009.1 6.4h75.2c5.9 0 8.6-3.4 9.5-6.3C95 58.1 95 53.4 90.4 50.6Zm-5.6 10.3h-75.2c-2.4.1-4-3.3-1.5-4.8l39.2-22.9 39 22.8A2.7 2.7 0 0184.7 60.8Z" />
|
||||
}
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
CharIcon.propTypes = {
|
||||
viewBox: PropTypes.string,
|
||||
type: PropTypes.string,
|
||||
};
|
||||
58
directory/src/component/dropdown.jsx
Normal file
58
directory/src/component/dropdown.jsx
Normal file
@@ -0,0 +1,58 @@
|
||||
import React, {
|
||||
useState
|
||||
} from 'react'
|
||||
import PropTypes from 'prop-types';
|
||||
import classes from './scss/dropdown.module.scss'
|
||||
|
||||
export default function Dropdown(props) {
|
||||
const [hidden, setHidden] = useState(true)
|
||||
|
||||
const toggleDropdown = () => {
|
||||
setHidden(!hidden)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<section className={`${classes.dropdown} ${hidden ? '' : classes.active} ${props.className ? props.className : ''}`} >
|
||||
<section
|
||||
className={classes.text}
|
||||
onClick={() => toggleDropdown()}
|
||||
>
|
||||
<span className={classes.content}>{props.text}</span>
|
||||
<span className={classes.icon}></span>
|
||||
</section>
|
||||
<ul className={classes.menu} style={props.activeColor}>
|
||||
{
|
||||
props.menu.map((item) => {
|
||||
return (
|
||||
<li
|
||||
key={item.name}
|
||||
className={`${classes.item} ${item.name === props.text || (props.activeRule && props.activeRule(item)) ? classes.active : ''}`}
|
||||
onClick={() => {
|
||||
props.onClick(item)
|
||||
toggleDropdown()
|
||||
}}
|
||||
>
|
||||
<section className={classes.text}>{item.name}</section>
|
||||
</li>
|
||||
)
|
||||
})
|
||||
}
|
||||
</ul>
|
||||
<section
|
||||
className={classes.overlay}
|
||||
hidden={hidden}
|
||||
onClick={() => toggleDropdown()}
|
||||
/>
|
||||
</section>
|
||||
</>
|
||||
)
|
||||
}
|
||||
Dropdown.propTypes = {
|
||||
className: PropTypes.string,
|
||||
text: PropTypes.string,
|
||||
menu: PropTypes.array,
|
||||
onClick: PropTypes.func,
|
||||
activeColor: PropTypes.object,
|
||||
activeRule: PropTypes.func,
|
||||
};
|
||||
42
directory/src/component/popup.jsx
Normal file
42
directory/src/component/popup.jsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import React, {
|
||||
useState,
|
||||
} from 'react'
|
||||
import classes from './scss/popup.module.scss';
|
||||
import ReturnButton from '@/component/return_button';
|
||||
import Border from '@/component/border';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export default function Popup(props) {
|
||||
const [hidden, setHidden] = useState(true)
|
||||
|
||||
const toggle = () => {
|
||||
setHidden(!hidden)
|
||||
}
|
||||
|
||||
return (<>
|
||||
<section className={`${classes.popup} ${hidden ? '' : classes.active}`}>
|
||||
<section className={classes.wrapper}>
|
||||
<section className={classes.title}>
|
||||
<section className={classes.text}>{props.title}</section>
|
||||
<ReturnButton onClick={toggle} className={classes["return-button"]} />
|
||||
</section>
|
||||
<Border />
|
||||
<section className={classes.content}>
|
||||
{props.children}
|
||||
</section>
|
||||
</section>
|
||||
<section className={`${classes.overlay} ${hidden ? '' : classes.active}`}
|
||||
onClick={() => toggle()} />
|
||||
</section>
|
||||
<span
|
||||
className={classes['entry-text']}
|
||||
onClick={toggle}
|
||||
>
|
||||
{props.title}
|
||||
</span>
|
||||
</>)
|
||||
}
|
||||
Popup.propTypes = {
|
||||
title: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
};
|
||||
39
directory/src/component/return_button.jsx
Normal file
39
directory/src/component/return_button.jsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classes from './scss/return_button.module.scss'
|
||||
|
||||
export default function ReturnButton(props) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<section className={`${classes['return-button']} ${props.className ? props.className : ''}`}
|
||||
onClick={() => props.onClick()}
|
||||
>
|
||||
<section className={classes.wrapper}>
|
||||
<section className={classes["arrow-left"]}></section>
|
||||
<section className={classes.bar}></section>
|
||||
<section className={classes["arrow-right"]}></section>
|
||||
</section>
|
||||
<section className={classes.wrapper}>
|
||||
<section className={classes["arrow-left"]}></section>
|
||||
<section className={classes.bar}></section>
|
||||
<section className={classes["arrow-right"]}></section>
|
||||
</section>
|
||||
<section className={classes.wrapper}>
|
||||
<section className={classes["arrow-left"]}></section>
|
||||
<section className={classes.bar}></section>
|
||||
<section className={classes["arrow-right"]}></section>
|
||||
</section>
|
||||
<section className={classes.wrapper}>
|
||||
<section className={classes["arrow-left"]}></section>
|
||||
<section className={classes.bar}></section>
|
||||
<section className={classes["arrow-right"]}></section>
|
||||
</section>
|
||||
</section>
|
||||
</>
|
||||
)
|
||||
}
|
||||
ReturnButton.propTypes = {
|
||||
onClick: PropTypes.func,
|
||||
className: PropTypes.string,
|
||||
};
|
||||
22
directory/src/component/scss/border.module.scss
Normal file
22
directory/src/component/scss/border.module.scss
Normal file
@@ -0,0 +1,22 @@
|
||||
.border {
|
||||
position: relative;
|
||||
bottom: 1px;
|
||||
border-bottom: 1px solid var(--text-color);
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
top: -2px;
|
||||
background-color: var(--text-color);
|
||||
}
|
||||
&:before {
|
||||
right: 100%;
|
||||
}
|
||||
&:after {
|
||||
left: 100%;
|
||||
}
|
||||
}
|
||||
111
directory/src/component/scss/dropdown.module.scss
Normal file
111
directory/src/component/scss/dropdown.module.scss
Normal file
@@ -0,0 +1,111 @@
|
||||
.dropdown {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
user-select: none;
|
||||
z-index: 2;
|
||||
padding: 0.5rem;
|
||||
cursor: pointer;
|
||||
|
||||
.text {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
bottom: 0.5rem;
|
||||
right: -0.1rem;
|
||||
width: 0.5em;
|
||||
height: 0.5em;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
border-left: 0.15em solid var(--text-color);
|
||||
border-bottom: 0.15em solid var(--text-color);
|
||||
border-right: 0.15em solid var(--text-color);
|
||||
border-top: 0.15em solid var(--text-color);
|
||||
transform: translate(0, -0.15em) rotate(-45deg);
|
||||
}
|
||||
|
||||
.menu {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
background-color: var(--root-background-color);
|
||||
width: max-content;
|
||||
z-index: -1;
|
||||
top: 2rem;
|
||||
right: 0;
|
||||
gap: 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
transition: all cubic-bezier(0.65, 0.05, 0.36, 1) 0.3s;
|
||||
overflow: hidden;
|
||||
padding: 0.5rem;
|
||||
border: 1px solid var(--border-color);
|
||||
visibility: hidden;
|
||||
color: var(--link-highlight-color);
|
||||
cursor: auto;
|
||||
|
||||
.item {
|
||||
cursor: pointer;
|
||||
padding: 0.5rem;
|
||||
font-size: 1rem;
|
||||
width: max-content;
|
||||
height: max-content;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
transition: color cubic-bezier(0.65, 0.05, 0.36, 1) 0.3s;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&.active {
|
||||
.text {
|
||||
color: currentColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.overlay {
|
||||
z-index: -1;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
&.active,
|
||||
&:hover {
|
||||
.icon {
|
||||
animation: icon-flash 2s cubic-bezier(0.65, 0.05, 0.36, 1) infinite;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
.menu {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes icon-flash {
|
||||
50% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
94
directory/src/component/scss/popup.module.scss
Normal file
94
directory/src/component/scss/popup.module.scss
Normal file
@@ -0,0 +1,94 @@
|
||||
.entry-text {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.popup {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
z-index: -1;
|
||||
border: unset;
|
||||
transition: all cubic-bezier(0.65, 0.05, 0.36, 1) 0.3s;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.2rem;
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
flex-wrap: nowrap;
|
||||
max-width: 480px;
|
||||
height: fit-content;
|
||||
margin: 0 auto;
|
||||
background-color: var(--root-background-color);
|
||||
border: 1px solid var(--border-color);
|
||||
padding: 2rem;
|
||||
}
|
||||
.title {
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-content: center;
|
||||
align-items: center;
|
||||
text-transform: uppercase;
|
||||
font-family: "Geometos", "Noto Sans SC", sans-serif;
|
||||
.return-button {
|
||||
color: var(--button-color);
|
||||
transition: color cubic-bezier(0.65, 0.05, 0.36, 1) 0.3s;
|
||||
&:hover {
|
||||
color: var(--text-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
.text {
|
||||
flex-grow: 1;
|
||||
margin-right: 3rem;
|
||||
}
|
||||
.content {
|
||||
line-height: 1.3em;
|
||||
padding: 1rem 1rem 0 1rem;
|
||||
user-select: text;
|
||||
}
|
||||
.overlay {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: -1;
|
||||
opacity: 0;
|
||||
background-color: var(--root-background-color);
|
||||
transition: all cubic-bezier(0.65, 0.05, 0.36, 1) 0.3s;
|
||||
|
||||
&.active {
|
||||
opacity: 0.5;
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
&.active {
|
||||
opacity: 1;
|
||||
z-index: 10;
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.title {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.content {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.return-button {
|
||||
transform: scale(0.8);
|
||||
}
|
||||
}
|
||||
}
|
||||
46
directory/src/component/scss/return_button.module.scss
Normal file
46
directory/src/component/scss/return_button.module.scss
Normal file
@@ -0,0 +1,46 @@
|
||||
.return-button {
|
||||
%arrow-shared {
|
||||
border-top: 0.24rem solid transparent;
|
||||
border-bottom: 0.24rem solid transparent;
|
||||
}
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
padding: 0.6rem 0;
|
||||
width: 3rem;
|
||||
cursor: pointer;
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
&:nth-child(1) {
|
||||
transform: translateY(-0.1rem) rotate(45deg);
|
||||
}
|
||||
&:nth-child(2) {
|
||||
transform: translateY(-0.1rem) translate(90%, -100%) rotate(-45deg);
|
||||
}
|
||||
&:nth-child(3) {
|
||||
transform: translateY(-0.1rem) translateY(150%) rotate(315deg);
|
||||
}
|
||||
&:nth-child(4) {
|
||||
transform: translateY(-0.1rem) translate(90%, 50%) rotate(225deg);
|
||||
}
|
||||
}
|
||||
.bar {
|
||||
width: 1rem;
|
||||
height: 0.4rem;
|
||||
background-color: currentColor;
|
||||
transition: transform cubic-bezier(0.65, 0.05, 0.36, 1) 0.3s;
|
||||
}
|
||||
.arrow-left {
|
||||
@extend %arrow-shared;
|
||||
border-right: 0.3rem solid currentColor;
|
||||
}
|
||||
.arrow-right {
|
||||
@extend %arrow-shared;
|
||||
border-left: 0.3rem solid currentColor;
|
||||
}
|
||||
}
|
||||
60
directory/src/component/scss/switch.module.scss
Normal file
60
directory/src/component/scss/switch.module.scss
Normal file
@@ -0,0 +1,60 @@
|
||||
.switch {
|
||||
position: relative;
|
||||
user-select: none;
|
||||
z-index: 2;
|
||||
padding: 8px 36px 8px 8px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
color: var(--secondary-text-color);
|
||||
transition: color cubic-bezier(0.65, 0.05, 0.36, 1) 0.3s;
|
||||
|
||||
.content {
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
color: var(--secondary-text-color);
|
||||
transition: all cubic-bezier(0.65, 0.05, 0.36, 1) 0.3s;
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
bottom: 8px;
|
||||
right: 18px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
border-left: 2px solid currentColor;
|
||||
border-bottom: 2px solid currentColor;
|
||||
border-right: 2px solid currentColor;
|
||||
border-top: 2px solid currentColor;
|
||||
transform: translate(0, -2px) rotate(-45deg);
|
||||
transition: right cubic-bezier(0.65, 0.05, 0.36, 1) 0.3s,
|
||||
background-color cubic-bezier(0.65, 0.05, 0.36, 1) 0.3s;
|
||||
}
|
||||
.line {
|
||||
position: absolute;
|
||||
bottom: 15px;
|
||||
right: 6px;
|
||||
width: 18px;
|
||||
height: 2px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
background-color: currentColor;
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: var(--text-color);
|
||||
.wrapper {
|
||||
color: var(--text-color-full);
|
||||
.icon {
|
||||
background-color: currentColor;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
directory/src/component/switch.jsx
Normal file
37
directory/src/component/switch.jsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classes from './scss/switch.module.scss';
|
||||
import {
|
||||
useI18n
|
||||
} from '@/state/language'
|
||||
|
||||
export default function Switch(props) {
|
||||
const [on, setOn] = useState(props.on)
|
||||
const { i18n } = useI18n()
|
||||
|
||||
useEffect(() => {
|
||||
setOn(props.on)
|
||||
}, [props.on])
|
||||
|
||||
return (
|
||||
<section
|
||||
className={`${classes.switch} ${on ? classes.active : ''}`}
|
||||
onClick={() => {
|
||||
if (props.handleOnClick) {
|
||||
props.handleOnClick(!on)
|
||||
}
|
||||
}}
|
||||
>
|
||||
<span className={classes.text}>{i18n(props.text)}</span>
|
||||
<section className={classes.wrapper}>
|
||||
<span className={classes.line}></span>
|
||||
<span className={classes.icon}></span>
|
||||
</section>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
Switch.propTypes = {
|
||||
on: PropTypes.bool,
|
||||
text: PropTypes.string,
|
||||
handleOnClick: PropTypes.func,
|
||||
};
|
||||
53
directory/src/component/voice.jsx
Normal file
53
directory/src/component/voice.jsx
Normal file
@@ -0,0 +1,53 @@
|
||||
import React, {
|
||||
useEffect,
|
||||
useRef,
|
||||
} from "react"
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export default function VoiceElement({
|
||||
src,
|
||||
replay,
|
||||
handleAduioStateChange,
|
||||
}) {
|
||||
const audioRef = useRef(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (src) {
|
||||
audioRef.current.src = src
|
||||
audioRef.current.play()
|
||||
} else {
|
||||
audioRef.current.pause()
|
||||
}
|
||||
}, [src])
|
||||
|
||||
useEffect(() => {
|
||||
if (replay) {
|
||||
audioRef.current.currentTime = 0
|
||||
audioRef.current.play()
|
||||
}
|
||||
}, [replay])
|
||||
|
||||
return (
|
||||
<audio
|
||||
ref={audioRef}
|
||||
preload="auto"
|
||||
autoPlay
|
||||
onEnded={(e) => {
|
||||
if (handleAduioStateChange) handleAduioStateChange(e, 'ended')
|
||||
}}
|
||||
onPlay={(e) => {
|
||||
if (handleAduioStateChange) handleAduioStateChange(e, 'play')
|
||||
}}
|
||||
onPause={(e) => {
|
||||
if (handleAduioStateChange) handleAduioStateChange(e, 'pause')
|
||||
}}
|
||||
>
|
||||
<source type="audio/ogg" />
|
||||
</audio>
|
||||
)
|
||||
}
|
||||
VoiceElement.propTypes = {
|
||||
src: PropTypes.string,
|
||||
handleAduioStateChange: PropTypes.func,
|
||||
replay: PropTypes.bool,
|
||||
}
|
||||
Reference in New Issue
Block a user