chore: moved to a new branch to save space

This commit is contained in:
Haoyu Xu
2023-03-16 21:49:29 -04:00
commit 59bffecc0f
116 changed files with 23521 additions and 0 deletions

View 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,
};

View 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,
};

View 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,
};

View 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,
};

View 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,
};

View 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%;
}
}

View 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;
}
}

View 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);
}
}
}

View 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;
}
}

View 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;
}
}
}
}

View 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,
};

View 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,
}